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