1/* 2 * Copyright (c) 2016 The University of Virginia 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Alec Roelke 29 */ 30 31#pragma once 32 33#include <cstdint> 34#include <limits> 35 36#include "insttest.h" 37 38namespace F 39{ 40 41constexpr inline uint32_t 42bits(float f) 43{ 44 return reinterpret_cast<uint32_t&>(f); 45} 46 47constexpr inline float 48number(uint32_t b) 49{ 50 return reinterpret_cast<float&>(b); 51} 52 53inline bool 54isquietnan(float f) 55{ 56 return std::isnan(f) && (bits(f)&0x00400000) != 0; 57} 58 59inline bool 60issignalingnan(float f) 61{ 62 return std::isnan(f) && (bits(f)&0x00400000) == 0; 63} 64 65inline float 66load(float mem) 67{ 68 float fd = std::numeric_limits<float>::signaling_NaN(); 69 asm volatile("flw %0,%1" 70 : "=f" (fd) 71 : "m" (mem)); 72 return fd; 73} 74 75inline float 76store(float fs) 77{ 78 float mem = std::numeric_limits<float>::signaling_NaN(); 79 asm volatile("fsw %1,%0" : "=m" (mem) : "f" (fs)); 80 return mem; 81} 82 83inline uint64_t 84frflags() 85{ 86 uint64_t rd = -1; 87 asm volatile("frflags %0" : "=r" (rd)); 88 return rd; 89} 90 91inline uint64_t 92fsflags(uint64_t rs1) 93{ 94 uint64_t rd = -1; 95 asm volatile("fsflags %0,%1" : "=r" (rd) : "r" (rs1)); 96 return rd; 97} 98 99inline float 100fmadd_s(float fs1, float fs2, float fs3) 101{ 102 float fd = std::numeric_limits<float>::signaling_NaN(); 103 FR4OP("fmadd.s", fd, fs1, fs2, fs3); 104 return fd; 105} 106 107inline float 108fmsub_s(float fs1, float fs2, float fs3) 109{ 110 float fd = std::numeric_limits<float>::signaling_NaN(); 111 FR4OP("fmsub.s", fd, fs1, fs2, fs3); 112 return fd; 113} 114 115inline float 116fnmsub_s(float fs1, float fs2, float fs3) 117{ 118 float fd = std::numeric_limits<float>::signaling_NaN(); 119 FR4OP("fnmsub.s", fd, fs1, fs2, fs3); 120 return fd; 121} 122 123inline float 124fnmadd_s(float fs1, float fs2, float fs3) 125{ 126 float fd = std::numeric_limits<float>::signaling_NaN(); 127 FR4OP("fnmadd.s", fd, fs1, fs2, fs3); 128 return fd; 129} 130 131inline float 132fadd_s(float fs1, float fs2) 133{ 134 float fd = std::numeric_limits<float>::signaling_NaN(); 135 FROP("fadd.s", fd, fs1, fs2); 136 return fd; 137} 138 139inline float 140fsub_s(float fs1, float fs2) 141{ 142 float fd = std::numeric_limits<float>::signaling_NaN(); 143 FROP("fsub.s", fd, fs1, fs2); 144 return fd; 145} 146 147inline float 148fmul_s(float fs1, float fs2) 149{ 150 float fd = std::numeric_limits<float>::signaling_NaN(); 151 FROP("fmul.s", fd, fs1, fs2); 152 return fd; 153} 154 155inline float 156fdiv_s(float fs1, float fs2) 157{ 158 159 float fd = 0.0; 160 FROP("fdiv.s", fd, fs1, fs2); 161 return fd; 162} 163 164inline float 165fsqrt_s(float fs1) 166{ 167 float fd = std::numeric_limits<float>::infinity(); 168 asm volatile("fsqrt.s %0,%1" : "=f" (fd) : "f" (fs1)); 169 return fd; 170} 171 172inline float 173fsgnj_s(float fs1, float fs2) 174{ 175 float fd = std::numeric_limits<float>::signaling_NaN(); 176 FROP("fsgnj.s", fd, fs1, fs2); 177 return fd; 178} 179 180inline float 181fsgnjn_s(float fs1, float fs2) 182{ 183 float fd = std::numeric_limits<float>::signaling_NaN(); 184 FROP("fsgnjn.s", fd, fs1, fs2); 185 return fd; 186} 187 188inline float 189fsgnjx_s(float fs1, float fs2) 190{ 191 float fd = std::numeric_limits<float>::signaling_NaN(); 192 FROP("fsgnjx.s", fd, fs1, fs2); 193 return fd; 194} 195 196inline float 197fmin_s(float fs1, float fs2) 198{ 199 float fd = std::numeric_limits<float>::signaling_NaN(); 200 FROP("fmin.s", fd, fs1, fs2); 201 return fd; 202} 203 204inline float 205fmax_s(float fs1, float fs2) 206{ 207 float fd = std::numeric_limits<float>::signaling_NaN(); 208 FROP("fmax.s", fd, fs1, fs2); 209 return fd; 210} 211 212inline int64_t 213fcvt_w_s(float fs1) 214{ 215 int64_t rd = 0; 216 asm volatile("fcvt.w.s %0,%1" : "=r" (rd) : "f" (fs1)); 217 return rd; 218} 219 220inline uint64_t 221fcvt_wu_s(float fs1) 222{ 223 uint64_t rd = 0; 224 asm volatile("fcvt.wu.s %0,%1" : "=r" (rd) : "f" (fs1)); 225 return rd; 226} 227 228inline uint64_t 229fmv_x_s(float fs1) 230{ 231 uint64_t rd = 0; 232 asm volatile("fmv.x.s %0,%1" : "=r" (rd) : "f" (fs1)); 233 return rd; 234} 235 236inline bool 237feq_s(float fs1, float fs2) 238{ 239 bool rd = false; 240 asm volatile("feq.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); 241 return rd; 242} 243 244inline bool 245flt_s(float fs1, float fs2) 246{ 247 bool rd = false; 248 asm volatile("flt.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); 249 return rd; 250} 251 252inline bool 253fle_s(float fs1, float fs2) 254{ 255 bool rd = false; 256 asm volatile("fle.s %0,%1,%2" : "=r" (rd) : "f" (fs1), "f" (fs2)); 257 return rd; 258} 259 260inline uint64_t 261fclass_s(float fs1) 262{ 263 uint64_t rd = -1; 264 asm volatile("fclass.s %0,%1" : "=r" (rd) : "f" (fs1)); 265 return rd; 266} 267 268inline float 269fcvt_s_w(int64_t rs1) 270{ 271 float fd = std::numeric_limits<float>::signaling_NaN(); 272 asm volatile("fcvt.s.w %0,%1" : "=f" (fd) : "r" (rs1)); 273 return fd; 274} 275 276inline float 277fcvt_s_wu(uint64_t rs1) 278{ 279 float fd = std::numeric_limits<float>::signaling_NaN(); 280 asm volatile("fcvt.s.wu %0,%1" : "=f" (fd) : "r" (rs1)); 281 return fd; 282} 283 284inline float 285fmv_s_x(uint64_t rs1) 286{ 287 float fd = std::numeric_limits<float>::signaling_NaN(); 288 asm volatile("fmv.s.x %0,%1" : "=f" (fd) : "r" (rs1)); 289 return fd; 290} 291 292inline uint64_t 293frcsr() 294{ 295 uint64_t rd = -1; 296 asm volatile("frcsr %0" : "=r" (rd)); 297 return rd; 298} 299 300inline uint64_t 301frrm() 302{ 303 uint64_t rd = -1; 304 asm volatile("frrm %0" : "=r" (rd)); 305 return rd; 306} 307 308inline uint64_t 309fscsr(uint64_t rs1) 310{ 311 uint64_t rd = -1; 312 asm volatile("fscsr %0,%1" : "=r" (rd) : "r" (rs1)); 313 return rd; 314} 315 316inline uint64_t 317fsrm(uint64_t rs1) 318{ 319 uint64_t rd = -1; 320 asm volatile("fsrm %0,%1" : "=r" (rd) : "r" (rs1)); 321 return rd; 322} 323 324inline int64_t 325fcvt_l_s(float fs1) 326{ 327 int64_t rd = 0; 328 asm volatile("fcvt.l.s %0,%1" : "=r" (rd) : "f" (fs1)); 329 return rd; 330} 331 332inline uint64_t 333fcvt_lu_s(float fs1) 334{ 335 336 int64_t rd = 0; 337 asm volatile("fcvt.lu.s %0,%1" : "=r" (rd) : "f" (fs1)); 338 return rd; 339} 340 341inline float 342fcvt_s_l(int64_t rs1) 343{ 344 float fd = std::numeric_limits<float>::signaling_NaN(); 345 asm volatile("fcvt.s.l %0,%1" : "=f" (fd) : "r" (rs1)); 346 return fd; 347} 348 349inline float 350fcvt_s_lu(uint64_t rs1) 351{ 352 float fd = std::numeric_limits<float>::signaling_NaN(); 353 asm volatile("fcvt.s.lu %0,%1" : "=f" (fd) : "r" (rs1)); 354 return fd; 355} 356 357} // namespace F 358