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