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#include <cstdint>
32#include <limits>
33
34#include "insttest.h"
35#include "rv64d.h"
36#include "rv64f.h"
37
38int main()
39{
40    using namespace std;
41    using namespace insttest;
42
43    // Memory (FLD, FSD)
44    expect<double>(3.1415926, []{return D::load(3.1415926);}, "fld");
45    expect<double>(1.61803398875, []{return D::store(1.61803398875);}, "fsd");
46
47    // FMADD.D
48    expect<double>(D::number(0x4019FD5AED13B1CEULL),
49                []{return D::fmadd_d(3.1415926, 1.61803398875,1.41421356237);},
50                "fmadd.d");
51    expect<bool>(true, []{
52            double fd = D::fmadd_d(numeric_limits<double>::quiet_NaN(), 3.14,
53                    1.816);
54            return D::isquietnan(fd);
55        }, "fmadd.d, quiet NaN");
56    expect<bool>(true, []{
57            double fd = D::fmadd_d(3.14,
58                    numeric_limits<double>::signaling_NaN(), 1.816);
59            return D::isquietnan(fd);
60        }, "fmadd.d, signaling NaN");
61    expect<double>(numeric_limits<double>::infinity(),
62        []{return D::fmadd_d(3.14, numeric_limits<double>::infinity(),1.414);},
63        "fmadd.d, infinity");
64    expect<double>(-numeric_limits<double>::infinity(),
65        []{return D::fmadd_d(3.14,-numeric_limits<double>::infinity(),1.414);},
66        "fmadd.d, -infinity");
67
68    // FMSUB.D
69    expect<double>(D::number(0x400d5A1773A85E43ULL),
70        []{return D::fmsub_d(3.1415926, 1.61803398875, 1.41421356237);},
71        "fmsub.d");
72    expect<bool>(true, []{
73            double fd = D::fmsub_d(3.14, numeric_limits<double>::quiet_NaN(),
74                    1.414);
75            return D::isquietnan(fd);
76        }, "fmsub.d, quiet NaN");
77    expect<bool>(true, []{
78            double fd = D::fmsub_d(3.14, 1.816,
79                    numeric_limits<double>::signaling_NaN());
80            return D::isquietnan(fd);
81        }, "fmsub.d, signaling NaN");
82    expect<double>(numeric_limits<double>::infinity(),
83            []{return D::fmsub_d(numeric_limits<double>::infinity(), 1.816,
84                    1.414);},
85            "fmsub.d, infinity");
86    expect<double>(-numeric_limits<double>::infinity(),
87            []{return D::fmsub_d(3.14, -numeric_limits<double>::infinity(),
88                    1.414);},
89            "fmsub.d, -infinity");
90    expect<double>(-numeric_limits<double>::infinity(),
91            []{return D::fmsub_d(3.14, 1.816,
92                    numeric_limits<double>::infinity());},
93            "fmsub.d, subtract infinity");
94
95    // FNMSUB.D
96    expect<double>(D::number(0xC00D5A1773A85E43ULL),
97            []{return D::fnmsub_d(3.1415926, 1.61803398875, 1.41421356237);},
98            "fnmsub.d");
99    expect<bool>(true, []{
100            double fd = D::fnmsub_d(3.14, 1.816,
101                    numeric_limits<double>::quiet_NaN());
102            return D::isquietnan(fd);
103        }, "fnmsub.d, quiet NaN");
104    expect<bool>(true, []{
105            double fd = D::fnmsub_d(numeric_limits<double>::signaling_NaN(),
106                    1.816, 1.414);
107            return D::isquietnan(fd);
108        }, "fnmsub.d, signaling NaN");
109    expect<double>(-numeric_limits<double>::infinity(),
110            []{return D::fnmsub_d(numeric_limits<double>::infinity(), 1.816,
111                    1.414);},
112            "fnmsub.d, infinity");
113    expect<double>(numeric_limits<double>::infinity(),
114            []{return D::fnmsub_d(3.14, -numeric_limits<double>::infinity(),
115                    1.414);},
116            "fnmsub.d, -infinity");
117    expect<double>(numeric_limits<double>::infinity(),
118            []{return D::fnmsub_d(3.14, 1.816,
119                    numeric_limits<double>::infinity());},
120            "fnmsub.d, subtract infinity");
121
122    // FNMADD.D
123    expect<double>(D::number(0xC019FD5AED13B1CEULL),
124            []{return D::fnmadd_d(3.1415926, 1.61803398875, 1.41421356237);},
125            "fnmadd.d");
126    expect<bool>(true, []{
127            double fd = D::fnmadd_d(numeric_limits<double>::quiet_NaN(), 3.14,
128                    1.816);
129            return D::isquietnan(fd);
130        }, "fnmadd.d, quiet NaN");
131    expect<bool>(true, []{
132            double fd = D::fnmadd_d(3.14,
133                    numeric_limits<double>::signaling_NaN(), 1.816);
134            return D::isquietnan(fd);
135        }, "fnmadd.d, signaling NaN");
136    expect<double>(-numeric_limits<double>::infinity(),
137            []{return D::fnmadd_d(3.14, numeric_limits<double>::infinity(),
138                    1.414);},
139            "fnmadd.d, infinity");
140    expect<double>(numeric_limits<double>::infinity(),
141            []{return D::fnmadd_d(3.14, -numeric_limits<double>::infinity(),
142                    1.414);},
143            "fnmadd.d, -infinity");
144
145    // FADD.D
146    expect<double>(D::number(0x4012392540292D7CULL),
147            []{return D::fadd_d(3.1415926, 1.41421356237);}, "fadd.d");
148    expect<bool>(true, []{
149            double fd = D::fadd_d(numeric_limits<double>::quiet_NaN(), 1.414);
150            return D::isquietnan(fd);
151        }, "fadd.d, quiet NaN");
152    expect<bool>(true, []{
153            double fd = D::fadd_d(3.14,
154                    numeric_limits<double>::signaling_NaN());
155            return D::isquietnan(fd);
156        }, "fadd.d, signaling NaN");
157    expect<double>(numeric_limits<double>::infinity(),
158            []{return D::fadd_d(3.14, numeric_limits<double>::infinity());},
159            "fadd.d, infinity");
160    expect<double>(-numeric_limits<double>::infinity(),
161            []{return D::fadd_d(-numeric_limits<double>::infinity(), 1.816);},
162            "fadd.d, -infinity");
163
164    // FSUB.D
165    expect<double>(D::number(0xBFFBA35833AB7AAEULL),
166            []{return D::fsub_d(1.4142135623, 3.1415926);}, "fsub.d");
167    expect<bool>(true, []{
168            double fd = D::fsub_d(numeric_limits<double>::quiet_NaN(), 1.414);
169            return D::isquietnan(fd);
170        }, "fsub.d, quiet NaN");
171    expect<bool>(true, []{
172            double fd = D::fsub_d(3.14,
173                    numeric_limits<double>::signaling_NaN());
174            return D::isquietnan(fd);
175        }, "fsub.d, signaling NaN");
176    expect<double>(numeric_limits<double>::infinity(),
177            []{return D::fsub_d(numeric_limits<double>::infinity(), 3.14);},
178            "fsub.d, infinity");
179    expect<double>(-numeric_limits<double>::infinity(),
180            []{return D::fsub_d(-numeric_limits<double>::infinity(), 3.14);},
181            "fsub.d, -infinity");
182    expect<double>(-numeric_limits<double>::infinity(),
183            []{return D::fsub_d(1.414, numeric_limits<double>::infinity());},
184            "fsub.d, subtract infinity");
185
186    // FMUL.D
187    expect<double>(D::number(0x40024E53B708ED9AULL),
188            []{return D::fmul_d(1.61803398875, 1.4142135623);}, "fmul.d");
189    expect<bool>(true, []{
190            double fd = D::fmul_d(numeric_limits<double>::quiet_NaN(), 1.414);
191            return D::isquietnan(fd);
192        }, "fmul.d, quiet NaN");
193    expect<bool>(true, []{
194            double fd = D::fmul_d(1.816,
195                    numeric_limits<double>::signaling_NaN());
196            return D::isquietnan(fd);
197        }, "fmul.d, signaling NaN");
198    expect<double>(numeric_limits<double>::infinity(),
199            []{return D::fmul_d(numeric_limits<double>::infinity(), 2.718);},
200            "fmul.d, infinity");
201    expect<double>(-numeric_limits<double>::infinity(),
202            []{return D::fmul_d(2.5966, -numeric_limits<double>::infinity());},
203            "fmul.d, -infinity");
204    expect<bool>(true, []{
205            double fd = D::fmul_d(0.0, numeric_limits<double>::infinity());
206            return D::isquietnan(fd);
207        }, "fmul.d, 0*infinity");
208    expect<double>(numeric_limits<double>::infinity(),
209            []{return D::fmul_d(numeric_limits<double>::max(), 2.0);},
210            "fmul.d, overflow");
211    expect<double>(0.0,
212            []{return D::fmul_d(numeric_limits<double>::min(),
213                    numeric_limits<double>::min());},
214            "fmul.d, underflow");
215
216    // FDIV.D
217    expect<double>(2.5, []{return D::fdiv_d(10.0, 4.0);}, "fdiv.d");
218    expect<bool>(true, []{
219            double fd = D::fdiv_d(numeric_limits<double>::quiet_NaN(), 4.0);
220            return D::isquietnan(fd);
221        }, "fdiv.d, quiet NaN");
222    expect<bool>(true, []{
223            double fd = D::fdiv_d(10.0,
224                    numeric_limits<double>::signaling_NaN());
225            return D::isquietnan(fd);
226        }, "fdiv.d, signaling NaN");
227    expect<double>(numeric_limits<double>::infinity(),
228            []{return D::fdiv_d(10.0, 0.0);}, "fdiv.d/0");
229    expect<double>(0.0,
230            []{return D::fdiv_d(10.0, numeric_limits<double>::infinity());},
231            "fdiv.d/infinity");
232    expect<bool>(true, []{
233            double fd = D::fdiv_d(numeric_limits<double>::infinity(),
234                    numeric_limits<double>::infinity());
235            return D::isquietnan(fd);
236        }, "fdiv.d, infinity/infinity");
237    expect<bool>(true, []{
238            double fd = D::fdiv_d(0.0, 0.0);
239            return D::isquietnan(fd);
240        }, "fdiv.d, 0/0");
241    expect<double>(numeric_limits<double>::infinity(),
242            []{return D::fdiv_d(numeric_limits<double>::infinity(), 0.0);},
243            "fdiv.d, infinity/0");
244    expect<double>(0.0,
245            []{return D::fdiv_d(0.0, numeric_limits<double>::infinity());},
246            "fdiv.d, 0/infinity");
247    expect<double>(0.0,
248            []{return D::fdiv_d(numeric_limits<double>::min(),
249                    numeric_limits<double>::max());},
250            "fdiv.d, underflow");
251    expect<double>(numeric_limits<double>::infinity(),
252            []{return D::fdiv_d(numeric_limits<double>::max(),
253                    numeric_limits<double>::min());},
254            "fdiv.d, overflow");
255
256    // FSQRT.D
257    expect<double>(1e154, []{return D::fsqrt_d(1e308);}, "fsqrt.d");
258    expect<bool>(true, []{
259            double fd = D::fsqrt_d(-1.0);
260            return D::isquietnan(fd);
261        }, "fsqrt.d, NaN");
262    expect<bool>(true, []{
263            double fd = D::fsqrt_d(numeric_limits<double>::quiet_NaN());
264            return D::isquietnan(fd);
265        }, "fsqrt.d, quiet NaN");
266    expect<bool>(true, []{
267            double fd = D::fsqrt_d(numeric_limits<double>::signaling_NaN());
268            return D::isquietnan(fd);
269        }, "fsqrt.d, signaling NaN");
270    expect<double>(numeric_limits<double>::infinity(),
271            []{return D::fsqrt_d(numeric_limits<double>::infinity());},
272            "fsqrt.d, infinity");
273
274    // FSGNJ.D
275    expect<double>(1.0, []{return D::fsgnj_d(1.0, 25.0);}, "fsgnj.d, ++");
276    expect<double>(-1.0, []{return D::fsgnj_d(1.0, -25.0);}, "fsgnj.d, +-");
277    expect<double>(1.0, []{return D::fsgnj_d(-1.0, 25.0);}, "fsgnj.d, -+");
278    expect<double>(-1.0, []{return D::fsgnj_d(-1.0, -25.0);}, "fsgnj.d, --");
279    expect<bool>(true, []{
280            double fd = D::fsgnj_d(numeric_limits<double>::quiet_NaN(), -4.0);
281            return D::isquietnan(fd);
282        }, "fsgnj.d, quiet NaN");
283    expect<bool>(true, []{
284            double fd = D::fsgnj_d(numeric_limits<double>::signaling_NaN(),
285                    -4.0);
286            return D::issignalingnan(fd);
287        }, "fsgnj.d, signaling NaN");
288    expect<double>(4.0,
289            []{return D::fsgnj_d(4.0, numeric_limits<double>::quiet_NaN());},
290            "fsgnj.d, inject NaN");
291    expect<double>(-4.0,
292            []{return D::fsgnj_d(4.0, -numeric_limits<double>::quiet_NaN());},
293            "fsgnj.d, inject -NaN");
294
295    // FSGNJN.D
296    expect<double>(-1.0, []{return D::fsgnjn_d(1.0, 25.0);}, "fsgnjn.d, ++");
297    expect<double>(1.0, []{return D::fsgnjn_d(1.0, -25.0);}, "fsgnjn.d, +-");
298    expect<double>(-1.0, []{return D::fsgnjn_d(-1.0, 25.0);}, "fsgnjn.d, -+");
299    expect<double>(1.0, []{return D::fsgnjn_d(-1.0, -25.0);}, "fsgnjn.d, --");
300    expect<bool>(true, []{
301            double fd = D::fsgnjn_d(numeric_limits<double>::quiet_NaN(), -4.0);
302            return D::isquietnan(fd);
303        }, "fsgnjn.d, quiet NaN");
304    expect<bool>(true, []{
305            double fd = D::fsgnjn_d(numeric_limits<double>::signaling_NaN(),
306                    -4.0);
307            return D::issignalingnan(fd);
308        }, "fsgnjn.d, signaling NaN");
309    expect<double>(-4.0,
310            []{return D::fsgnjn_d(4.0, numeric_limits<double>::quiet_NaN());},
311            "fsgnjn.d, inject NaN");
312    expect<double>(4.0,
313            []{return D::fsgnjn_d(4.0, -numeric_limits<double>::quiet_NaN());},
314            "fsgnjn.d, inject NaN");
315
316    // FSGNJX.D
317    expect<double>(1.0, []{return D::fsgnjx_d(1.0, 25.0);}, "fsgnjx.d, ++");
318    expect<double>(-1.0, []{return D::fsgnjx_d(1.0, -25.0);}, "fsgnjx.d, +-");
319    expect<double>(-1.0, []{return D::fsgnjx_d(-1.0, 25.0);}, "fsgnjx.d, -+");
320    expect<double>(1.0, []{return D::fsgnjx_d(-1.0, -25.0);}, "fsgnjx.d, --");
321    expect<bool>(true, []{
322            double fd = D::fsgnjx_d(numeric_limits<double>::quiet_NaN(), -4.0);
323            return D::isquietnan(fd);
324        }, "fsgnjx.d, quiet NaN");
325    expect<bool>(true, []{
326            double fd = D::fsgnjx_d(numeric_limits<double>::signaling_NaN(),
327                    -4.0);
328            return D::issignalingnan(fd);
329        }, "fsgnjx.d, signaling NaN");
330    expect<double>(4.0,
331            []{return D::fsgnjx_d(4.0, numeric_limits<double>::quiet_NaN());},
332            "fsgnjx.d, inject NaN");
333    expect<double>(-4.0,
334            []{return D::fsgnjx_d(4.0, -numeric_limits<double>::quiet_NaN());},
335            "fsgnjx.d, inject NaN");
336
337    // FMIN.D
338    expect<double>(2.718, []{return D::fmin_d(3.14, 2.718);}, "fmin.d");
339    expect<double>(-numeric_limits<double>::infinity(),
340            []{return D::fmin_d(-numeric_limits<double>::infinity(),
341                    numeric_limits<double>::min());},
342            "fmin.d, -infinity");
343    expect<double>(numeric_limits<double>::max(),
344            []{return D::fmin_d(numeric_limits<double>::infinity(),
345                    numeric_limits<double>::max());},
346            "fmin.d, infinity");
347    expect<double>(-1.414,
348            []{return D::fmin_d(numeric_limits<double>::quiet_NaN(), -1.414);},
349            "fmin.d, quiet NaN first");
350    expect<double>(2.718,
351            []{return D::fmin_d(2.718, numeric_limits<double>::quiet_NaN());},
352            "fmin.d, quiet NaN second");
353    expect<bool>(true, []{
354            double fd = D::fmin_d(numeric_limits<double>::quiet_NaN(),
355                    numeric_limits<double>::quiet_NaN());
356            return D::isquietnan(fd);
357        }, "fmin.d, quiet NaN both");
358    expect<double>(3.14,
359            []{return D::fmin_d(numeric_limits<double>::signaling_NaN(),
360                    3.14);},
361            "fmin.d, signaling NaN first");
362    expect<double>(1.816,
363            []{return D::fmin_d(1.816,
364                    numeric_limits<double>::signaling_NaN());},
365            "fmin.d, signaling NaN second");
366    expect<bool>(true, []{
367            double fd = D::fmin_d(numeric_limits<double>::signaling_NaN(),
368                    numeric_limits<double>::signaling_NaN());
369            return D::issignalingnan(fd);
370        }, "fmin.d, signaling NaN both");
371
372    // FMAX.D
373    expect<double>(3.14, []{return D::fmax_d(3.14, 2.718);}, "fmax.d");
374    expect<double>(numeric_limits<double>::min(),
375            []{return D::fmax_d(-numeric_limits<double>::infinity(),
376                    numeric_limits<double>::min());},
377            "fmax.d, -infinity");
378    expect<double>(numeric_limits<double>::infinity(),
379            []{return D::fmax_d(numeric_limits<double>::infinity(),
380                    numeric_limits<double>::max());},
381            "fmax.d, infinity");
382    expect<double>(-1.414,
383            []{return D::fmax_d(numeric_limits<double>::quiet_NaN(), -1.414);},
384            "fmax.d, quiet NaN first");
385    expect<double>(2.718,
386            []{return D::fmax_d(2.718, numeric_limits<double>::quiet_NaN());},
387            "fmax.d, quiet NaN second");
388    expect<bool>(true, []{
389            double fd = D::fmax_d(numeric_limits<double>::quiet_NaN(),
390                    numeric_limits<double>::quiet_NaN());
391            return D::isquietnan(fd);
392        }, "fmax.d, quiet NaN both");
393    expect<double>(3.14,
394            []{return D::fmax_d(numeric_limits<double>::signaling_NaN(),
395                    3.14);},
396            "fmax.d, signaling NaN first");
397    expect<double>(1.816,
398            []{return D::fmax_d(1.816,
399                    numeric_limits<double>::signaling_NaN());},
400            "fmax.d, signaling NaN second");
401    expect<bool>(true, []{
402            double fd = D::fmax_d(numeric_limits<double>::signaling_NaN(),
403                    numeric_limits<double>::signaling_NaN());
404            return D::issignalingnan(fd);
405        }, "fmax.d, signaling NaN both");
406
407    // FCVT.S.D
408    expect<float>(4.0, []{return D::fcvt_s_d(4.0);}, "fcvt.s.d");
409    expect<bool>(true, []{
410            float fd = D::fcvt_s_d(numeric_limits<double>::quiet_NaN());
411            return F::isquietnan(fd);
412        }, "fcvt.s.d, quiet NaN");
413    expect<bool>(true, []{
414            float fd = D::fcvt_s_d(numeric_limits<double>::signaling_NaN());
415            return F::isquietnan(fd);
416        }, "fcvt.s.d, signaling NaN");
417    expect<float>(numeric_limits<float>::infinity(),
418            []{return D::fcvt_s_d(numeric_limits<double>::infinity());},
419            "fcvt.s.d, infinity");
420    expect<float>(numeric_limits<float>::infinity(),
421            []{return D::fcvt_s_d(numeric_limits<double>::max());},
422            "fcvt.s.d, overflow");
423    expect<float>(0.0, []{return D::fcvt_s_d(numeric_limits<double>::min());},
424            "fcvt.s.d, underflow");
425
426    // FCVT.D.S
427    expect<double>(D::number(0x4005BE76C0000000),
428            []{return D::fcvt_d_s(2.718);}, "fcvt.d.s");
429    expect<bool>(true, []{
430            double fd = D::fcvt_d_s(numeric_limits<float>::quiet_NaN());
431            return D::isquietnan(fd);
432        }, "fcvt.d.s, quiet NaN");
433    expect<bool>(true, []{
434            double fd = D::fcvt_d_s(numeric_limits<float>::signaling_NaN());
435            return D::isquietnan(fd);
436        }, "fcvt.d.s, signaling NaN");
437    expect<double>(numeric_limits<double>::infinity(),
438            []{return D::fcvt_d_s(numeric_limits<float>::infinity());},
439            "fcvt.d.s, infinity");
440
441    // FEQ.D
442    expect<bool>(true, []{return D::feq_d(1.414, 1.414);}, "feq.d, equal");
443    expect<bool>(false,[]{return D::feq_d(2.718, 1.816);}, "feq.d, not equal");
444    expect<bool>(true, []{return D::feq_d(0.0, -0.0);}, "feq.d, 0 == -0");
445    expect<bool>(false,
446            []{return D::feq_d(numeric_limits<double>::quiet_NaN(), -1.0);},
447            "feq.d, quiet NaN first");
448    expect<bool>(false,
449            []{return D::feq_d(2.0, numeric_limits<double>::quiet_NaN());},
450            "feq.d, quiet NaN second");
451    expect<bool>(false,
452            []{return D::feq_d(numeric_limits<double>::quiet_NaN(),
453                    numeric_limits<double>::quiet_NaN());},
454            "feq.d, quiet NaN both");
455    expect<bool>(false,
456            []{return D::feq_d(numeric_limits<double>::signaling_NaN(),-1.0);},
457            "feq.d, signaling NaN first");
458    expect<bool>(false,
459            []{return D::feq_d(2.0, numeric_limits<double>::signaling_NaN());},
460            "feq.d, signaling NaN second");
461    expect<bool>(false,
462            []{return D::feq_d(numeric_limits<double>::signaling_NaN(),
463                    numeric_limits<double>::signaling_NaN());},
464            "feq.d, signaling NaN both");
465
466    // FLT.D
467    expect<bool>(false, []{return D::flt_d(1.414, 1.414);}, "flt.d, equal");
468    expect<bool>(true, []{return D::flt_d(1.816, 2.718);}, "flt.d, less");
469    expect<bool>(false, []{return D::flt_d(2.718, 1.816);}, "flt.d, greater");
470    expect<bool>(false,
471            []{return D::flt_d(numeric_limits<double>::quiet_NaN(), -1.0);},
472            "flt.d, quiet NaN first");
473    expect<bool>(false,
474            []{return D::flt_d(2.0, numeric_limits<double>::quiet_NaN());},
475            "flt.d, quiet NaN second");
476    expect<bool>(false,
477            []{return D::flt_d(numeric_limits<double>::quiet_NaN(),
478                    numeric_limits<double>::quiet_NaN());},
479            "flt.d, quiet NaN both");
480    expect<bool>(false,
481            []{return D::flt_d(numeric_limits<double>::signaling_NaN(),-1.0);},
482            "flt.d, signaling NaN first");
483    expect<bool>(false,
484            []{return D::flt_d(2.0, numeric_limits<double>::signaling_NaN());},
485            "flt.d, signaling NaN second");
486    expect<bool>(false,
487            []{return D::flt_d(numeric_limits<double>::signaling_NaN(),
488                    numeric_limits<double>::signaling_NaN());},
489            "flt.d, signaling NaN both");
490
491    // FLE.D
492    expect<bool>(true, []{return D::fle_d(1.414, 1.414);}, "fle.d, equal");
493    expect<bool>(true, []{return D::fle_d(1.816, 2.718);}, "fle.d, less");
494    expect<bool>(false, []{return D::fle_d(2.718, 1.816);}, "fle.d, greater");
495    expect<bool>(true, []{return D::fle_d(0.0, -0.0);}, "fle.d, 0 == -0");
496    expect<bool>(false,
497            []{return D::fle_d(numeric_limits<double>::quiet_NaN(), -1.0);},
498            "fle.d, quiet NaN first");
499    expect<bool>(false,
500            []{return D::fle_d(2.0, numeric_limits<double>::quiet_NaN());},
501            "fle.d, quiet NaN second");
502    expect<bool>(false,
503            []{return D::fle_d(numeric_limits<double>::quiet_NaN(),
504                    numeric_limits<double>::quiet_NaN());},
505            "fle.d, quiet NaN both");
506    expect<bool>(false,
507            []{return D::fle_d(numeric_limits<double>::signaling_NaN(),-1.0);},
508            "fle.d, signaling NaN first");
509    expect<bool>(false,
510            []{return D::fle_d(2.0, numeric_limits<double>::signaling_NaN());},
511            "fle.d, signaling NaN second");
512    expect<bool>(false,
513            []{return D::fle_d(numeric_limits<double>::signaling_NaN(),
514                    numeric_limits<double>::signaling_NaN());},
515            "fle.d, signaling NaN both");
516
517    // FCLASS.D
518    expect<uint64_t>(0x1,
519            []{return D::fclass_d(-numeric_limits<double>::infinity());},
520            "fclass.d, -infinity");
521    expect<uint64_t>(0x2,
522            []{return D::fclass_d(-3.14);}, "fclass.d, -normal");
523    expect<uint64_t>(0x4,
524            []{return D::fclass_d(D::number(0x800FFFFFFFFFFFFFULL));},
525            "fclass.d, -subnormal");
526    expect<uint64_t>(0x8, []{return D::fclass_d(-0.0);}, "fclass.d, -0.0");
527    expect<uint64_t>(0x10, []{return D::fclass_d(0.0);}, "fclass.d, 0.0");
528    expect<uint64_t>(0x20,
529            []{return D::fclass_d(D::number(0x000FFFFFFFFFFFFFULL));},
530            "fclass.d, subnormal");
531    expect<uint64_t>(0x40, []{return D::fclass_d(1.816);}, "fclass.d, normal");
532    expect<uint64_t>(0x80,
533            []{return D::fclass_d(numeric_limits<double>::infinity());},
534            "fclass.d, infinity");
535    expect<uint64_t>(0x100,
536            []{return D::fclass_d(numeric_limits<double>::signaling_NaN());},
537            "fclass.d, signaling NaN");
538    expect<uint64_t>(0x200,
539            []{return D::fclass_d(numeric_limits<double>::quiet_NaN());},
540            "fclass.s, quiet NaN");
541
542    // FCVT.W.D
543    expect<int64_t>(256, []{return D::fcvt_w_d(256.3);},
544            "fcvt.w.d, truncate positive");
545    expect<int64_t>(-256, []{return D::fcvt_w_d(-256.2);},
546            "fcvt.w.d, truncate negative");
547    expect<int64_t>(0, []{return D::fcvt_w_d(0.0);}, "fcvt.w.d, 0.0");
548    expect<int64_t>(0, []{return D::fcvt_w_d(-0.0);}, "fcvt.w.d, -0.0");
549    expect<int64_t>(numeric_limits<int32_t>::max(),
550            []{return D::fcvt_w_d(numeric_limits<double>::max());},
551            "fcvt.w.d, overflow");
552    expect<int64_t>(0, []{return D::fcvt_w_d(numeric_limits<double>::min());},
553            "fcvt.w.d, underflow");
554    expect<int64_t>(numeric_limits<int32_t>::max(),
555            []{return D::fcvt_w_d(numeric_limits<double>::infinity());},
556            "fcvt.w.d, infinity");
557    expect<int64_t>(numeric_limits<int32_t>::min(),
558            []{return D::fcvt_w_d(-numeric_limits<double>::infinity());},
559            "fcvt.w.d, -infinity");
560    expect<int64_t>(numeric_limits<int32_t>::max(),
561            []{return D::fcvt_w_d(numeric_limits<double>::quiet_NaN());},
562            "fcvt.w.d, quiet NaN");
563    expect<int64_t>(numeric_limits<int32_t>::max(),
564            []{return D::fcvt_w_d(-numeric_limits<double>::quiet_NaN());},
565            "fcvt.w.d, quiet -NaN");
566    expect<int64_t>(numeric_limits<int32_t>::max(),
567            []{return D::fcvt_w_d(numeric_limits<double>::signaling_NaN());},
568            "fcvt.w.d, signaling NaN");
569
570    // FCVT.WU.D
571    expect<uint64_t>(256, []{return D::fcvt_wu_d(256.3);},
572            "fcvt.wu.d, truncate positive");
573    expect<uint64_t>(0, []{return D::fcvt_wu_d(-256.2);},
574            "fcvt.wu.d, truncate negative");
575    expect<uint64_t>(0, []{return D::fcvt_wu_d(0.0);}, "fcvt.wu.d, 0.0");
576    expect<uint64_t>(0, []{return D::fcvt_wu_d(-0.0);}, "fcvt.wu.d, -0.0");
577    expect<uint64_t>(numeric_limits<uint64_t>::max(),
578            []{return D::fcvt_wu_d(numeric_limits<double>::max());},
579            "fcvt.wu.d, overflow");
580    expect<uint64_t>(0,[]{return D::fcvt_wu_d(numeric_limits<double>::min());},
581            "fcvt.wu.d, underflow");
582    expect<uint64_t>(numeric_limits<uint64_t>::max(),
583            []{return D::fcvt_wu_d(numeric_limits<double>::infinity());},
584            "fcvt.wu.d, infinity");
585    expect<uint64_t>(0,
586            []{return D::fcvt_wu_d(-numeric_limits<double>::infinity());},
587            "fcvt.wu.d, -infinity");
588    expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
589            []{return D::fcvt_wu_d(numeric_limits<double>::quiet_NaN());},
590            "fcvt.wu.d, quiet NaN");
591    expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
592            []{return D::fcvt_wu_d(-numeric_limits<double>::quiet_NaN());},
593            "fcvt.wu.d, quiet -NaN");
594    expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
595            []{return D::fcvt_wu_d(numeric_limits<double>::signaling_NaN());},
596            "fcvt.wu.d, signaling NaN");
597
598    // FCVT.D.W
599    expect<double>(0.0, []{return D::fcvt_d_w(0);}, "fcvt.d.w, 0");
600    expect<double>(-2147483648.0,
601            []{return D::fcvt_d_w(numeric_limits<int32_t>::min());},
602            "fcvt.d.w, negative");
603    expect<double>(255.0, []{return D::fcvt_d_w(0xFFFFFFFF000000FFLL);},
604            "fcvt.d.w, truncate");
605
606    // FCVT.D.WU
607    expect<double>(0.0, []{return D::fcvt_d_wu(0);}, "fcvt.d.wu, 0");
608    expect<double>(2147483648.0,
609            []{return D::fcvt_d_wu(numeric_limits<int32_t>::min());},
610            "fcvt.d.wu");
611    expect<double>(255.0,
612            []{return D::fcvt_d_wu(0xFFFFFFFF000000FFLL);},
613            "fcvt.d.wu, truncate");
614
615    // FCVT.L.D
616    expect<int64_t>(256, []{return D::fcvt_l_d(256.3);},
617            "fcvt.l.d, truncate positive");
618    expect<int64_t>(-256, []{return D::fcvt_l_d(-256.2);},
619            "fcvt.l.d, truncate negative");
620    expect<int64_t>(0, []{return D::fcvt_l_d(0.0);}, "fcvt.l.d, 0.0");
621    expect<int64_t>(0, []{return D::fcvt_l_d(-0.0);}, "fcvt.l.d, -0.0");
622    expect<int64_t>(-8589934592LL, []{return D::fcvt_l_d(-8589934592.0);},
623            "fcvt.l.d, 32-bit overflow");
624    expect<int64_t>(numeric_limits<int64_t>::max(),
625            []{return D::fcvt_l_d(numeric_limits<double>::max());},
626            "fcvt.l.d, overflow");
627    expect<int64_t>(0, []{return D::fcvt_l_d(numeric_limits<double>::min());},
628            "fcvt.l.d, underflow");
629    expect<int64_t>(numeric_limits<int64_t>::max(),
630            []{return D::fcvt_l_d(numeric_limits<double>::infinity());},
631            "fcvt.l.d, infinity");
632    expect<int64_t>(numeric_limits<int64_t>::min(),
633            []{return D::fcvt_l_d(-numeric_limits<double>::infinity());},
634            "fcvt.l.d, -infinity");
635    expect<int64_t>(numeric_limits<int64_t>::max(),
636            []{return D::fcvt_l_d(numeric_limits<double>::quiet_NaN());},
637            "fcvt.l.d, quiet NaN");
638    expect<int64_t>(numeric_limits<int64_t>::max(),
639            []{return D::fcvt_l_d(-numeric_limits<double>::quiet_NaN());},
640            "fcvt.l.d, quiet -NaN");
641    expect<int64_t>(numeric_limits<int64_t>::max(),
642            []{return D::fcvt_l_d(numeric_limits<double>::signaling_NaN());},
643            "fcvt.l.d, signaling NaN");
644
645    // FCVT.LU.D
646    expect<uint64_t>(256, []{return D::fcvt_lu_d(256.3);},
647            "fcvt.lu.d, truncate positive");
648    expect<uint64_t>(0, []{return D::fcvt_lu_d(-256.2);},
649            "fcvt.lu.d, truncate negative");
650    expect<uint64_t>(0, []{return D::fcvt_lu_d(0.0);}, "fcvt.lu.d, 0.0");
651    expect<uint64_t>(0, []{return D::fcvt_lu_d(-0.0);}, "fcvt.lu.d, -0.0");
652    expect<uint64_t>(8589934592LL, []{return D::fcvt_lu_d(8589934592.0);},
653            "fcvt.lu.d, 32-bit overflow");
654    expect<uint64_t>(numeric_limits<uint64_t>::max(),
655            []{return D::fcvt_lu_d(numeric_limits<double>::max());},
656            "fcvt.lu.d, overflow");
657    expect<uint64_t>(0,[]{return D::fcvt_lu_d(numeric_limits<double>::min());},
658            "fcvt.lu.d, underflow");
659    expect<uint64_t>(numeric_limits<uint64_t>::max(),
660            []{return D::fcvt_lu_d(numeric_limits<double>::infinity());},
661            "fcvt.lu.d, infinity");
662    expect<uint64_t>(0,
663            []{return D::fcvt_lu_d(-numeric_limits<double>::infinity());},
664            "fcvt.lu.d, -infinity");
665    expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
666            []{return D::fcvt_lu_d(numeric_limits<double>::quiet_NaN());},
667            "fcvt.lu.d, quiet NaN");
668    expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
669            []{return D::fcvt_lu_d(-numeric_limits<double>::quiet_NaN());},
670            "fcvt.lu.d, quiet -NaN");
671    expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL,
672            []{return D::fcvt_lu_d(numeric_limits<double>::signaling_NaN());},
673            "fcvt.lu.d, signaling NaN");
674
675    // FMV.X.D
676    expect<uint64_t>(0x40091EB851EB851FULL, []{return D::fmv_x_d(3.14);},
677            "fmv.x.d, positive");
678    expect<uint64_t>(0xC0091EB851EB851FULL, []{return D::fmv_x_d(-3.14);},
679            "fmv.x.d, negative");
680    expect<uint64_t>(0x0000000000000000ULL, []{return D::fmv_x_d(0.0);},
681            "fmv.x.d, 0.0");
682    expect<uint64_t>(0x8000000000000000ULL, []{return D::fmv_x_d(-0.0);},
683            "fmv.x.d, -0.0");
684
685    // FCVT.D.L
686    expect<double>(0.0, []{return D::fcvt_d_l(0);}, "fcvt.d.l, 0");
687    expect<double>(D::number(0xC3E0000000000000),
688            []{return D::fcvt_d_l(numeric_limits<int64_t>::min());},
689            "fcvt.d.l, negative");
690    expect<double>(D::number(0xC1EFFFFFE0200000),
691            []{return D::fcvt_d_l(0xFFFFFFFF000000FFLL);},
692            "fcvt.d.l, 32-bit truncate");
693
694    // FCVT.D.LU
695    expect<double>(0.0, []{return D::fcvt_d_lu(0);}, "fcvt.d.lu, 0");
696    expect<double>(D::number(0x43E0000000000000),
697            []{return D::fcvt_d_lu(numeric_limits<int64_t>::min());},
698            "fcvt.d.lu");
699    expect<double>(D::number(0x43EFFFFFFFE00000),
700            []{return D::fcvt_d_lu(0xFFFFFFFF000000FFLL);},
701            "fcvt.d.lu, 32-bit truncate");
702
703    // FMV.D.X
704    expect<double>(-numeric_limits<float>::infinity(),
705            []{return D::fmv_d_x(0xFFF0000000000000ULL);}, "fmv.d.x");
706
707    return 0;
708}
709