test fcvttgo. instead of fcvttg
[openpower-isa.git] / src / openpower / test / fmv_fcvt / fmv_fcvt.py
1 from openpower.test.common import TestAccumulatorBase, skip_case
2 from openpower.sv.trans.svp64 import SVP64Asm
3 from openpower.test.state import ExpectedState
4 from openpower.simulator.program import Program
5 from openpower.decoder.isa.caller import SVP64State
6 from openpower.fpscr import FPSCRState
7 import struct
8 import math
9 import functools
10
11
12 @functools.lru_cache()
13 def _cached_program(*instrs):
14 return Program(list(SVP64Asm(list(instrs))), bigendian=False)
15
16
17 def fp_bits_add(fp, amount):
18 """add `amount` to the IEEE 754 bits representing `fp`"""
19 bits = struct.unpack("<Q", struct.pack("<d", fp))[0]
20 bits += amount
21 return struct.unpack("<d", struct.pack("<Q", bits))[0]
22
23
24 def round_even(v):
25 """round v to the nearest integer, with ties rounding to the even integer
26 """
27 v = float(v)
28 return int(v - math.remainder(v, 1.0))
29
30
31 def do_round(v, round_mode):
32 if round_mode == 0:
33 return round_even(v)
34 if round_mode == 1:
35 return math.trunc(v)
36 if round_mode == 2:
37 return math.ceil(v)
38 if round_mode == 3:
39 return math.floor(v)
40 assert False, "invalid round_mode"
41
42
43 class FMvFCvtCases(TestAccumulatorBase):
44 def toint(
45 self, inp, expected=None, test_title="", inp_bits=None,
46 signed=True, _32bit=True, CVM=5, RN=0,
47 ):
48 if CVM & 1:
49 for i in range(4):
50 self.toint(inp=inp, inp_bits=inp_bits, signed=signed,
51 _32bit=_32bit, CVM=CVM - 1, RN=i)
52 if CVM == 5:
53 for i in (1, 3):
54 self.toint(inp=inp, inp_bits=inp_bits, signed=signed,
55 _32bit=_32bit, CVM=i)
56 if CVM & 1:
57 round_mode = 1 # trunc
58 else:
59 round_mode = RN
60 max_v = 2 ** 64 - 1
61 if _32bit:
62 max_v >>= 32
63 min_v = 0
64 if signed:
65 max_v >>= 1
66 min_v = ~max_v
67 inp = float(inp)
68 if inp_bits is None:
69 inp_bits = struct.unpack("<Q", struct.pack("<d", inp))[0]
70 if expected is None:
71 if CVM >> 1 == 0: # openpower semantics
72 if math.isnan(inp):
73 expected = min_v
74 elif inp > max_v:
75 expected = max_v
76 elif inp < min_v:
77 expected = min_v
78 else:
79 expected = do_round(inp, round_mode)
80 elif CVM >> 1 == 1: # saturating semantics
81 if math.isnan(inp):
82 expected = 0
83 elif inp > max_v:
84 expected = max_v
85 elif inp < min_v:
86 expected = min_v
87 else:
88 expected = do_round(inp, round_mode)
89 elif CVM >> 1 == 2: # js semantics
90 if math.isfinite(inp):
91 expected = do_round(inp, round_mode)
92 else:
93 expected = 0
94 if _32bit:
95 expected %= 2 ** 32
96 if signed and expected >> 31:
97 expected -= 2 ** 32
98 expected %= 2 ** 64
99 IT = (not signed) + (not _32bit) * 2
100 with self.subTest(inp=inp.hex(), inp_bits=hex(inp_bits),
101 expected=hex(expected), test_title=test_title,
102 signed=signed, _32bit=_32bit, CVM=CVM, RN=RN):
103 lst = [f"fcvttgo. 3,0,{CVM},{IT}"]
104 gprs = [0] * 32
105 fprs = [0] * 32
106 fprs[0] = inp_bits
107 initial_fpscr = FPSCRState()
108 initial_fpscr.RN = RN
109 e = ExpectedState(pc=4, int_regs=gprs, fp_regs=fprs)
110 e.intregs[3] = expected
111 fpscr = FPSCRState(initial_fpscr)
112 if math.isnan(inp) and (inp_bits & 2 ** 51) == 0: # SNaN
113 fpscr.VXSNAN = 1
114 fpscr.FX = 1
115 overflow = True
116 if math.isfinite(inp):
117 overflow = not (min_v <= do_round(inp, round_mode) <= max_v)
118 if overflow:
119 fpscr.VXCVI = 1
120 fpscr.FX = 1
121 e.so = 1
122 e.ov = 0b11
123 elif do_round(inp, round_mode) != inp: # inexact
124 fpscr.XX = 1
125 fpscr.FX = 1
126 fpscr.FI = 1
127 fpscr.FPRF = 0 # undefined value we happen to pick
128 fpscr.FR = 0 # trunc never increments
129 lt = bool(expected & (1 << 63))
130 gt = not lt and expected != 0
131 eq = expected == 0
132 e.crregs[0] = (lt << 3) | (gt << 2) | (eq << 1) | e.so
133 with self.subTest(expected_VXSNAN=fpscr.VXSNAN,
134 expected_VXCVI=fpscr.VXCVI,
135 expected_XX=fpscr.XX,
136 expected_FI=fpscr.FI):
137 e.fpscr = int(fpscr)
138 self.add_case(
139 _cached_program(*lst), gprs, fpregs=fprs, expected=e,
140 initial_fpscr=int(initial_fpscr))
141
142 def case_js_toint32(self):
143 min_value = pow(2, -1074)
144 # test cases from:
145 # https://chromium.googlesource.com/v8/v8.git/+/d94dfc2b01f988566aa410ce871588cf23b1285d/test/mjsunit/toint32.js
146 # Copyright 2008 the V8 project authors. All rights reserved.
147 # Redistribution and use in source and binary forms, with or without
148 # modification, are permitted provided that the following conditions are
149 # met:
150 #
151 # * Redistributions of source code must retain the above copyright
152 # notice, this list of conditions and the following disclaimer.
153 # * Redistributions in binary form must reproduce the above
154 # copyright notice, this list of conditions and the following
155 # disclaimer in the documentation and/or other materials provided
156 # with the distribution.
157 # * Neither the name of Google Inc. nor the names of its
158 # contributors may be used to endorse or promote products derived
159 # from this software without specific prior written permission.
160 #
161 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
163 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
164 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
165 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
166 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
167 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
168 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
169 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
170 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
171 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
172
173 self.toint(math.inf, 0, "Inf")
174 self.toint(-math.inf, 0, "-Inf")
175 self.toint(math.nan, 0, "NaN")
176 self.toint(math.nan, 0, "SNaN", inp_bits=0x7ff0_0000_0000_0001)
177 self.toint(0.0, 0, "zero")
178 self.toint(-0.0, 0, "-zero")
179 self.toint(min_value, 0)
180 self.toint(-min_value, 0)
181 self.toint(0.1, 0)
182 self.toint(-0.1, 0)
183 self.toint(1, 1, "one")
184 self.toint(1.1, 1, "onepointone")
185 self.toint(-1, -1, "-one")
186 self.toint(0.6, 0, "truncate positive (0.6)")
187 self.toint(1.6, 1, "truncate positive (1.6)")
188 self.toint(-0.6, 0, "truncate negative (-0.6)")
189 self.toint(-1.6, -1, "truncate negative (-1.6)")
190 self.toint(2147483647, 2147483647)
191 self.toint(2147483648, -2147483648)
192 self.toint(2147483649, -2147483647)
193 self.toint(4294967295, -1)
194 self.toint(4294967296, 0)
195 self.toint(4294967297, 1)
196 self.toint(-2147483647, -2147483647)
197 self.toint(-2147483648, -2147483648)
198 self.toint(-2147483649, 2147483647)
199 self.toint(-4294967295, 1)
200 self.toint(-4294967296, 0)
201 self.toint(-4294967297, -1)
202 self.toint(2147483648.25, -2147483648)
203 self.toint(2147483648.5, -2147483648)
204 self.toint(2147483648.75, -2147483648)
205 self.toint(4294967295.25, -1)
206 self.toint(4294967295.5, -1)
207 self.toint(4294967295.75, -1)
208 self.toint(3000000000.25, -1294967296)
209 self.toint(3000000000.5, -1294967296)
210 self.toint(3000000000.75, -1294967296)
211 self.toint(-2147483648.25, -2147483648)
212 self.toint(-2147483648.5, -2147483648)
213 self.toint(-2147483648.75, -2147483648)
214 self.toint(-4294967295.25, 1)
215 self.toint(-4294967295.5, 1)
216 self.toint(-4294967295.75, 1)
217 self.toint(-3000000000.25, 1294967296)
218 self.toint(-3000000000.5, 1294967296)
219 self.toint(-3000000000.75, 1294967296)
220 base = pow(2, 64)
221 self.toint(base + 0, 0)
222 self.toint(base + 1117, 0)
223 self.toint(base + 2234, 4096)
224 self.toint(base + 3351, 4096)
225 self.toint(base + 4468, 4096)
226 self.toint(base + 5585, 4096)
227 self.toint(base + 6702, 8192)
228 self.toint(base + 7819, 8192)
229 self.toint(base + 8936, 8192)
230 self.toint(base + 10053, 8192)
231 self.toint(base + 11170, 12288)
232 self.toint(base + 12287, 12288)
233 self.toint(base + 13404, 12288)
234 self.toint(base + 14521, 16384)
235 self.toint(base + 15638, 16384)
236 self.toint(base + 16755, 16384)
237 self.toint(base + 17872, 16384)
238 self.toint(base + 18989, 20480)
239 self.toint(base + 20106, 20480)
240 self.toint(base + 21223, 20480)
241 self.toint(base + 22340, 20480)
242 self.toint(base + 23457, 24576)
243 self.toint(base + 24574, 24576)
244 self.toint(base + 25691, 24576)
245 self.toint(base + 26808, 28672)
246 self.toint(base + 27925, 28672)
247 self.toint(base + 29042, 28672)
248 self.toint(base + 30159, 28672)
249 self.toint(base + 31276, 32768)
250 # bignum is (2 ^ 53 - 1) * 2 ^ 31 - highest number with bit 31 set.
251 bignum = pow(2, 84) - pow(2, 31)
252 self.toint(bignum, -pow(2, 31))
253 self.toint(-bignum, -pow(2, 31))
254 self.toint(2 * bignum, 0)
255 self.toint(-(2 * bignum), 0)
256 self.toint(bignum - pow(2, 31), 0)
257 self.toint(-(bignum - pow(2, 31)), 0)
258 # max_fraction is largest number below 1.
259 max_fraction = (1 - pow(2, -53))
260 self.toint(max_fraction, 0)
261 self.toint(-max_fraction, 0)
262
263 def case_js_touint32(self):
264 min_value = pow(2, -1074)
265 # test cases from:
266 # https://chromium.googlesource.com/v8/v8.git/+/d94dfc2b01f988566aa410ce871588cf23b1285d/test/mjsunit/touint32.js
267 # with identical copyright notice as in case_js_toint32
268 self.toint(0, 0, "0", signed=False)
269 self.toint(-0, 0, "-0", signed=False)
270 self.toint(math.inf, 0, "Infinity", signed=False)
271 self.toint(-math.inf, 0, "-Infinity", signed=False)
272 self.toint(math.nan, 0, "NaN", signed=False)
273 self.toint(math.nan, 0, "SNaN", inp_bits=0x7ff0_0000_0000_0001,
274 signed=False)
275 self.toint(min_value, 0, "MIN", signed=False)
276 self.toint(-min_value, 0, "-MIN", signed=False)
277 self.toint(0.1, 0, "0.1", signed=False)
278 self.toint(-0.1, 0, "-0.1", signed=False)
279 self.toint(1, 1, "1", signed=False)
280 self.toint(1.1, 1, "1.1", signed=False)
281 self.toint(-1, 4294967295, "-1", signed=False)
282 self.toint(-1.1, 4294967295, "-1.1", signed=False)
283 self.toint(2147483647, 2147483647, "2147483647", signed=False)
284 self.toint(2147483648, 2147483648, "2147483648", signed=False)
285 self.toint(2147483649, 2147483649, "2147483649", signed=False)
286 self.toint(4294967295, 4294967295, "4294967295", signed=False)
287 self.toint(4294967296, 0, "4294967296", signed=False)
288 self.toint(4294967297, 1, "4294967297", signed=False)
289 self.toint(-2147483647, 2147483649, "-2147483647", signed=False)
290 self.toint(-2147483648, 2147483648, "-2147483648", signed=False)
291 self.toint(-2147483649, 2147483647, "-2147483649", signed=False)
292 self.toint(-4294967295, 1, "-4294967295", signed=False)
293 self.toint(-4294967296, 0, "-4294967296", signed=False)
294 self.toint(-4294967297, 4294967295, "-4294967297", signed=False)
295
296 def case_js_toint64(self):
297 # 64-bit equivalent of javascript's toint32
298 min_value = pow(2, -1074)
299 # test cases derived from:
300 # https://chromium.googlesource.com/v8/v8.git/+/d94dfc2b01f988566aa410ce871588cf23b1285d/test/mjsunit/toint32.js
301 # with identical copyright notice as in case_js_toint32
302
303 self.toint(math.inf, 0, "Inf", _32bit=False)
304 self.toint(-math.inf, 0, "-Inf", _32bit=False)
305 self.toint(math.nan, 0, "NaN", _32bit=False)
306 self.toint(math.nan, 0, "SNaN",
307 inp_bits=0x7ff0_0000_0000_0001, _32bit=False)
308 self.toint(0.0, 0, "zero", _32bit=False)
309 self.toint(-0.0, 0, "-zero", _32bit=False)
310 self.toint(min_value, 0, _32bit=False)
311 self.toint(-min_value, 0, _32bit=False)
312 self.toint(0.1, 0, _32bit=False)
313 self.toint(-0.1, 0, _32bit=False)
314 self.toint(1, 1, "one", _32bit=False)
315 self.toint(1.1, 1, "onepointone", _32bit=False)
316 self.toint(-1, -1, "-one", _32bit=False)
317 self.toint(0.6, 0, "truncate positive (0.6)", _32bit=False)
318 self.toint(1.6, 1, "truncate positive (1.6)", _32bit=False)
319 self.toint(-0.6, 0, "truncate negative (-0.6)", _32bit=False)
320 self.toint(-1.6, -1, "truncate negative (-1.6)", _32bit=False)
321 self.toint(fp_bits_add(2**63, -1), _32bit=False)
322 self.toint(2**63, _32bit=False)
323 self.toint(fp_bits_add(2**63, 1), _32bit=False)
324 self.toint(fp_bits_add(2**64, -1), _32bit=False)
325 self.toint(2**64, 0, _32bit=False)
326 self.toint(fp_bits_add(2**64, 1), _32bit=False)
327 self.toint(-fp_bits_add(2**63, -1), _32bit=False)
328 self.toint(-(2**63), _32bit=False)
329 self.toint(-fp_bits_add(2**63, 1), _32bit=False)
330 self.toint(-fp_bits_add(2**64, -1), _32bit=False)
331 self.toint(-(2**64), 0, _32bit=False)
332 self.toint(-fp_bits_add(2**64, 1), _32bit=False)
333 self.toint(2147483648.25, _32bit=False)
334 self.toint(2147483648.5, _32bit=False)
335 self.toint(2147483648.75, _32bit=False)
336 self.toint(4294967295.25, _32bit=False)
337 self.toint(4294967295.5, _32bit=False)
338 self.toint(4294967295.75, _32bit=False)
339 self.toint(3000000000.25, _32bit=False)
340 self.toint(3000000000.5, _32bit=False)
341 self.toint(3000000000.75, _32bit=False)
342 self.toint(-2147483648.25, _32bit=False)
343 self.toint(-2147483648.5, _32bit=False)
344 self.toint(-2147483648.75, _32bit=False)
345 self.toint(-4294967295.25, _32bit=False)
346 self.toint(-4294967295.5, _32bit=False)
347 self.toint(-4294967295.75, _32bit=False)
348 self.toint(-3000000000.25, _32bit=False)
349 self.toint(-3000000000.5, _32bit=False)
350 self.toint(-3000000000.75, _32bit=False)
351 base = pow(2, 64)
352 self.toint(base + 0, _32bit=False)
353 self.toint(base + 1117, _32bit=False)
354 self.toint(base + 2234, _32bit=False)
355 self.toint(base + 3351, _32bit=False)
356 self.toint(base + 4468, _32bit=False)
357 self.toint(base + 5585, _32bit=False)
358 self.toint(base + 6702, _32bit=False)
359 self.toint(base + 7819, _32bit=False)
360 self.toint(base + 8936, _32bit=False)
361 self.toint(base + 10053, _32bit=False)
362 self.toint(base + 11170, _32bit=False)
363 self.toint(base + 12287, _32bit=False)
364 self.toint(base + 13404, _32bit=False)
365 self.toint(base + 14521, _32bit=False)
366 self.toint(base + 15638, _32bit=False)
367 self.toint(base + 16755, _32bit=False)
368 self.toint(base + 17872, _32bit=False)
369 self.toint(base + 18989, _32bit=False)
370 self.toint(base + 20106, _32bit=False)
371 self.toint(base + 21223, _32bit=False)
372 self.toint(base + 22340, _32bit=False)
373 self.toint(base + 23457, _32bit=False)
374 self.toint(base + 24574, _32bit=False)
375 self.toint(base + 25691, _32bit=False)
376 self.toint(base + 26808, _32bit=False)
377 self.toint(base + 27925, _32bit=False)
378 self.toint(base + 29042, _32bit=False)
379 self.toint(base + 30159, _32bit=False)
380 self.toint(base + 31276, _32bit=False)
381 # bignum is (2 ^ 53 - 1) * 2 ^ 31 - highest number with bit 31 set.
382 bignum = pow(2, 84) - pow(2, 31)
383 self.toint(bignum, _32bit=False)
384 self.toint(-bignum, _32bit=False)
385 self.toint(2 * bignum, _32bit=False)
386 self.toint(-(2 * bignum), _32bit=False)
387 self.toint(bignum - pow(2, 31), _32bit=False)
388 self.toint(-(bignum - pow(2, 31)), _32bit=False)
389 # max_fraction is largest number below 1.
390 max_fraction = (1 - pow(2, -53))
391 self.toint(max_fraction, 0, _32bit=False)
392 self.toint(-max_fraction, 0, _32bit=False)
393
394 def case_js_touint64(self):
395 # 64-bit equivalent of javascript's touint32
396 min_value = pow(2, -1074)
397 # test cases derived from:
398 # https://chromium.googlesource.com/v8/v8.git/+/d94dfc2b01f988566aa410ce871588cf23b1285d/test/mjsunit/touint32.js
399 # with identical copyright notice as in case_js_toint32
400 self.toint(0, 0, "0", signed=False, _32bit=False)
401 self.toint(-0, 0, "-0", signed=False, _32bit=False)
402 self.toint(math.inf, 0, "Infinity", signed=False, _32bit=False)
403 self.toint(-math.inf, 0, "-Infinity", signed=False, _32bit=False)
404 self.toint(math.nan, 0, "NaN", signed=False, _32bit=False)
405 self.toint(math.nan, 0, "SNaN", inp_bits=0x7ff0_0000_0000_0001,
406 signed=False, _32bit=False)
407 self.toint(min_value, 0, "MIN", signed=False, _32bit=False)
408 self.toint(-min_value, 0, "-MIN", signed=False, _32bit=False)
409 self.toint(0.1, 0, "0.1", signed=False, _32bit=False)
410 self.toint(-0.1, 0, "-0.1", signed=False, _32bit=False)
411 self.toint(1, 1, "1", signed=False, _32bit=False)
412 self.toint(1.1, 1, "1.1", signed=False, _32bit=False)
413 self.toint(-1, 2**64 - 1, "-1", signed=False, _32bit=False)
414 self.toint(-1.1, 2**64 - 1, "-1.1", signed=False, _32bit=False)
415 self.toint(fp_bits_add(2**63, -1), signed=False, _32bit=False)
416 self.toint(2**63, signed=False, _32bit=False)
417 self.toint(fp_bits_add(2**63, 1), signed=False, _32bit=False)
418 self.toint(fp_bits_add(2**64, -1), signed=False, _32bit=False)
419 self.toint(2**64, 0, signed=False, _32bit=False)
420 self.toint(fp_bits_add(2**64, 1), signed=False, _32bit=False)
421 self.toint(-fp_bits_add(2**63, -1), signed=False, _32bit=False)
422 self.toint(-(2**63), signed=False, _32bit=False)
423 self.toint(-fp_bits_add(2**63, 1), signed=False, _32bit=False)
424 self.toint(-fp_bits_add(2**64, -1), signed=False, _32bit=False)
425 self.toint(-(2**64), 0, signed=False, _32bit=False)
426 self.toint(-fp_bits_add(2**64, 1), signed=False, _32bit=False)
427
428
429 class SVP64FMvFCvtCases(TestAccumulatorBase):
430 @skip_case("FIXME: rewrite to fmv/fcvt tests")
431 def case_sv_fmaxmag19(self):
432 lst = list(SVP64Asm(["sv.fmaxmag19 *32,*64,*96"]))
433 gprs = [0] * 128
434 fprs = [0] * 128
435 svstate = SVP64State()
436 svstate.vl = 32
437 svstate.maxvl = 32
438 r = range(svstate.vl)
439 for i, rev_i in zip(r, reversed(r)):
440 fprs[64 + i] = struct.unpack("<Q", struct.pack("<d", i))[0]
441 fprs[96 + i] = struct.unpack("<Q", struct.pack("<d", rev_i))[0]
442 e = ExpectedState(pc=8, int_regs=gprs, fp_regs=fprs)
443 e.fpregs[32] = 0x403f000000000000
444 e.fpregs[33] = 0x403e000000000000
445 e.fpregs[34] = 0x403d000000000000
446 e.fpregs[35] = 0x403c000000000000
447 e.fpregs[36] = 0x403b000000000000
448 e.fpregs[37] = 0x403a000000000000
449 e.fpregs[38] = 0x4039000000000000
450 e.fpregs[39] = 0x4038000000000000
451 e.fpregs[40] = 0x4037000000000000
452 e.fpregs[41] = 0x4036000000000000
453 e.fpregs[42] = 0x4035000000000000
454 e.fpregs[43] = 0x4034000000000000
455 e.fpregs[44] = 0x4033000000000000
456 e.fpregs[45] = 0x4032000000000000
457 e.fpregs[46] = 0x4031000000000000
458 e.fpregs[47] = 0x4030000000000000
459 e.fpregs[48] = 0x4030000000000000
460 e.fpregs[49] = 0x4031000000000000
461 e.fpregs[50] = 0x4032000000000000
462 e.fpregs[51] = 0x4033000000000000
463 e.fpregs[52] = 0x4034000000000000
464 e.fpregs[53] = 0x4035000000000000
465 e.fpregs[54] = 0x4036000000000000
466 e.fpregs[55] = 0x4037000000000000
467 e.fpregs[56] = 0x4038000000000000
468 e.fpregs[57] = 0x4039000000000000
469 e.fpregs[58] = 0x403a000000000000
470 e.fpregs[59] = 0x403b000000000000
471 e.fpregs[60] = 0x403c000000000000
472 e.fpregs[61] = 0x403d000000000000
473 e.fpregs[62] = 0x403e000000000000
474 e.fpregs[63] = 0x403f000000000000
475 self.add_case(Program(lst, False), gprs, fpregs=fprs,
476 initial_svstate=svstate, expected=e)