1 from openpower
.test
.common
import TestAccumulatorBase
, skip_case
2 from openpower
.insndb
.asm
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 from openpower
.consts
import MSR
13 @functools.lru_cache()
14 def _cached_program(*instrs
):
15 return Program(list(SVP64Asm(list(instrs
))), bigendian
=False)
18 def bitcast_int_to_fp(bits
, bfp32
):
20 return struct
.unpack("<f", struct
.pack("<L", bits
))[0]
21 return struct
.unpack("<d", struct
.pack("<Q", bits
))[0]
24 def bitcast_fp_to_int(fp
, bfp32
):
26 return struct
.unpack("<L", struct
.pack("<f", fp
))[0]
27 return struct
.unpack("<Q", struct
.pack("<d", fp
))[0]
30 def fp_bits_add(fp
, amount
, bfp32
=False):
31 """add `amount` to the IEEE 754 bits representing `fp`"""
32 return bitcast_int_to_fp(amount
+ bitcast_fp_to_int(fp
, bfp32
), bfp32
)
36 """round v to the nearest integer, with ties rounding to the even integer
39 return int(v
- math
.remainder(v
, 1.0))
42 def do_round(v
, round_mode
):
51 assert False, "invalid round_mode"
54 class FMvFCvtCases(TestAccumulatorBase
):
55 def toint_helper(self
, *, inp
, expected
=None, test_title
="", inp_bits
=None,
56 signed
=True, _32bit
=True, CVM
, RN
, VE
):
58 round_mode
= 1 # trunc
70 inp_bits
= struct
.unpack("<Q", struct
.pack("<d", inp
))[0]
72 if CVM
>> 1 == 0: # openpower semantics
80 expected
= do_round(inp
, round_mode
)
81 elif CVM
>> 1 == 1: # saturating semantics
89 expected
= do_round(inp
, round_mode
)
90 elif CVM
>> 1 == 2: # js semantics
91 if math
.isfinite(inp
):
92 expected
= do_round(inp
, round_mode
)
97 if signed
and expected
>> 31:
100 IT
= (not signed
) + (not _32bit
) * 2
101 with self
.subTest(inp
=inp
.hex(), inp_bits
=hex(inp_bits
),
102 test_title
=test_title
,
103 signed
=signed
, _32bit
=_32bit
, CVM
=CVM
, RN
=RN
, VE
=VE
):
104 lst
= [f
"cffpro. 3,0,{CVM},{IT}"]
108 gprs
[3] = 0xabcdef9876543210
109 initial_fpscr
= FPSCRState()
110 initial_fpscr
.RN
= RN
111 initial_fpscr
.VE
= VE
112 e
= ExpectedState(pc
=4, int_regs
=gprs
, fp_regs
=fprs
)
113 fpscr
= FPSCRState(initial_fpscr
)
114 if math
.isnan(inp
) and (inp_bits
& 2 ** 51) == 0: # SNaN
118 if math
.isfinite(inp
):
119 overflow
= not (min_v
<= do_round(inp
, round_mode
) <= max_v
)
125 elif do_round(inp
, round_mode
) != inp
: # inexact
129 fpscr
.FPRF
= 0 # undefined value we happen to pick
131 fpscr
.FR
= abs(do_round(inp
, round_mode
)) > abs(inp
)
132 if overflow
and fpscr
.VE
:
133 # FIXME: #1087 proposes to change pseudocode of fcvt* to
134 # always write output, this implements reading RT when output
135 # isn't written, which is terrible
136 # https://bugs.libre-soc.org/show_bug.cgi?id=1087#c21
137 expected
= e
.intregs
[3]
139 e
.sprs
['SRR0'] = 0 # insn is at address 0
140 e
.sprs
['SRR1'] = e
.msr |
(1 << (63 - 43))
141 e
.msr
= 0x9000000000000001
142 lt
= bool(expected
& (1 << 63))
143 gt
= not lt
and expected
!= 0
145 e
.crregs
[0] = (lt
<< 3) |
(gt
<< 2) |
(eq
<< 1) | e
.so
146 e
.intregs
[3] = expected
147 with self
.subTest(expected_VXSNAN
=fpscr
.VXSNAN
,
148 expected_VXCVI
=fpscr
.VXCVI
,
149 expected_XX
=fpscr
.XX
,
150 expected_FI
=fpscr
.FI
,
151 expected
=hex(expected
)):
154 _cached_program(*lst
), gprs
, fpregs
=fprs
, expected
=e
,
155 initial_fpscr
=int(initial_fpscr
))
157 def toint(self
, inp
, expected
=None, test_title
="", inp_bits
=None,
158 signed
=True, _32bit
=True):
160 for RN
in range(1 if CVM
& 1 else 4):
163 inp
=inp
, expected
=expected
if CVM
== 5 else None,
164 test_title
=test_title
, inp_bits
=inp_bits
,
165 signed
=signed
, _32bit
=_32bit
, CVM
=CVM
, RN
=RN
, VE
=VE
)
167 def case_js_toint32(self
):
168 min_value
= pow(2, -1074)
170 # https://chromium.googlesource.com/v8/v8.git/+/d94dfc2b01f988566aa410ce871588cf23b1285d/test/mjsunit/toint32.js
171 # Copyright 2008 the V8 project authors. All rights reserved.
172 # Redistribution and use in source and binary forms, with or without
173 # modification, are permitted provided that the following conditions are
176 # * Redistributions of source code must retain the above copyright
177 # notice, this list of conditions and the following disclaimer.
178 # * Redistributions in binary form must reproduce the above
179 # copyright notice, this list of conditions and the following
180 # disclaimer in the documentation and/or other materials provided
181 # with the distribution.
182 # * Neither the name of Google Inc. nor the names of its
183 # contributors may be used to endorse or promote products derived
184 # from this software without specific prior written permission.
186 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
187 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
188 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
189 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
190 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
191 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
192 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
193 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
194 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
195 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
196 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
198 self
.toint(math
.inf
, 0, "Inf")
199 self
.toint(-math
.inf
, 0, "-Inf")
200 self
.toint(math
.nan
, 0, "NaN")
201 self
.toint(math
.nan
, 0, "SNaN", inp_bits
=0x7ff0_0000_0000_0001)
202 self
.toint(0.0, 0, "zero")
203 self
.toint(-0.0, 0, "-zero")
204 self
.toint(min_value
, 0)
205 self
.toint(-min_value
, 0)
208 self
.toint(1, 1, "one")
209 self
.toint(1.1, 1, "onepointone")
210 self
.toint(-1, -1, "-one")
211 self
.toint(0.6, 0, "truncate positive (0.6)")
212 self
.toint(1.6, 1, "truncate positive (1.6)")
213 self
.toint(-0.6, 0, "truncate negative (-0.6)")
214 self
.toint(-1.6, -1, "truncate negative (-1.6)")
215 self
.toint(2147483647, 2147483647)
216 self
.toint(2147483648, -2147483648)
217 self
.toint(2147483649, -2147483647)
218 self
.toint(4294967295, -1)
219 self
.toint(4294967296, 0)
220 self
.toint(4294967297, 1)
221 self
.toint(-2147483647, -2147483647)
222 self
.toint(-2147483648, -2147483648)
223 self
.toint(-2147483649, 2147483647)
224 self
.toint(-4294967295, 1)
225 self
.toint(-4294967296, 0)
226 self
.toint(-4294967297, -1)
227 self
.toint(2147483648.25, -2147483648)
228 self
.toint(2147483648.5, -2147483648)
229 self
.toint(2147483648.75, -2147483648)
230 self
.toint(4294967295.25, -1)
231 self
.toint(4294967295.5, -1)
232 self
.toint(4294967295.75, -1)
233 self
.toint(3000000000.25, -1294967296)
234 self
.toint(3000000000.5, -1294967296)
235 self
.toint(3000000000.75, -1294967296)
236 self
.toint(-2147483648.25, -2147483648)
237 self
.toint(-2147483648.5, -2147483648)
238 self
.toint(-2147483648.75, -2147483648)
239 self
.toint(-4294967295.25, 1)
240 self
.toint(-4294967295.5, 1)
241 self
.toint(-4294967295.75, 1)
242 self
.toint(-3000000000.25, 1294967296)
243 self
.toint(-3000000000.5, 1294967296)
244 self
.toint(-3000000000.75, 1294967296)
246 self
.toint(base
+ 0, 0)
247 self
.toint(base
+ 1117, 0)
248 self
.toint(base
+ 2234, 4096)
249 self
.toint(base
+ 3351, 4096)
250 self
.toint(base
+ 4468, 4096)
251 self
.toint(base
+ 5585, 4096)
252 self
.toint(base
+ 6702, 8192)
253 self
.toint(base
+ 7819, 8192)
254 self
.toint(base
+ 8936, 8192)
255 self
.toint(base
+ 10053, 8192)
256 self
.toint(base
+ 11170, 12288)
257 self
.toint(base
+ 12287, 12288)
258 self
.toint(base
+ 13404, 12288)
259 self
.toint(base
+ 14521, 16384)
260 self
.toint(base
+ 15638, 16384)
261 self
.toint(base
+ 16755, 16384)
262 self
.toint(base
+ 17872, 16384)
263 self
.toint(base
+ 18989, 20480)
264 self
.toint(base
+ 20106, 20480)
265 self
.toint(base
+ 21223, 20480)
266 self
.toint(base
+ 22340, 20480)
267 self
.toint(base
+ 23457, 24576)
268 self
.toint(base
+ 24574, 24576)
269 self
.toint(base
+ 25691, 24576)
270 self
.toint(base
+ 26808, 28672)
271 self
.toint(base
+ 27925, 28672)
272 self
.toint(base
+ 29042, 28672)
273 self
.toint(base
+ 30159, 28672)
274 self
.toint(base
+ 31276, 32768)
275 # bignum is (2 ^ 53 - 1) * 2 ^ 31 - highest number with bit 31 set.
276 bignum
= pow(2, 84) - pow(2, 31)
277 self
.toint(bignum
, -pow(2, 31))
278 self
.toint(-bignum
, -pow(2, 31))
279 self
.toint(2 * bignum
, 0)
280 self
.toint(-(2 * bignum
), 0)
281 self
.toint(bignum
- pow(2, 31), 0)
282 self
.toint(-(bignum
- pow(2, 31)), 0)
283 # max_fraction is largest number below 1.
284 max_fraction
= (1 - pow(2, -53))
285 self
.toint(max_fraction
, 0)
286 self
.toint(-max_fraction
, 0)
288 def case_js_touint32(self
):
289 min_value
= pow(2, -1074)
291 # https://chromium.googlesource.com/v8/v8.git/+/d94dfc2b01f988566aa410ce871588cf23b1285d/test/mjsunit/touint32.js
292 # with identical copyright notice as in case_js_toint32
293 self
.toint(0, 0, "0", signed
=False)
294 self
.toint(-0, 0, "-0", signed
=False)
295 self
.toint(math
.inf
, 0, "Infinity", signed
=False)
296 self
.toint(-math
.inf
, 0, "-Infinity", signed
=False)
297 self
.toint(math
.nan
, 0, "NaN", signed
=False)
298 self
.toint(math
.nan
, 0, "SNaN", inp_bits
=0x7ff0_0000_0000_0001,
300 self
.toint(min_value
, 0, "MIN", signed
=False)
301 self
.toint(-min_value
, 0, "-MIN", signed
=False)
302 self
.toint(0.1, 0, "0.1", signed
=False)
303 self
.toint(-0.1, 0, "-0.1", signed
=False)
304 self
.toint(1, 1, "1", signed
=False)
305 self
.toint(1.1, 1, "1.1", signed
=False)
306 self
.toint(-1, 4294967295, "-1", signed
=False)
307 self
.toint(-1.1, 4294967295, "-1.1", signed
=False)
308 self
.toint(2147483647, 2147483647, "2147483647", signed
=False)
309 self
.toint(2147483648, 2147483648, "2147483648", signed
=False)
310 self
.toint(2147483649, 2147483649, "2147483649", signed
=False)
311 self
.toint(4294967295, 4294967295, "4294967295", signed
=False)
312 self
.toint(4294967296, 0, "4294967296", signed
=False)
313 self
.toint(4294967297, 1, "4294967297", signed
=False)
314 self
.toint(-2147483647, 2147483649, "-2147483647", signed
=False)
315 self
.toint(-2147483648, 2147483648, "-2147483648", signed
=False)
316 self
.toint(-2147483649, 2147483647, "-2147483649", signed
=False)
317 self
.toint(-4294967295, 1, "-4294967295", signed
=False)
318 self
.toint(-4294967296, 0, "-4294967296", signed
=False)
319 self
.toint(-4294967297, 4294967295, "-4294967297", signed
=False)
321 def case_js_toint64(self
):
322 # 64-bit equivalent of javascript's toint32
323 min_value
= pow(2, -1074)
324 # test cases derived from:
325 # https://chromium.googlesource.com/v8/v8.git/+/d94dfc2b01f988566aa410ce871588cf23b1285d/test/mjsunit/toint32.js
326 # with identical copyright notice as in case_js_toint32
328 self
.toint(math
.inf
, 0, "Inf", _32bit
=False)
329 self
.toint(-math
.inf
, 0, "-Inf", _32bit
=False)
330 self
.toint(math
.nan
, 0, "NaN", _32bit
=False)
331 self
.toint(math
.nan
, 0, "SNaN",
332 inp_bits
=0x7ff0_0000_0000_0001, _32bit
=False)
333 self
.toint(0.0, 0, "zero", _32bit
=False)
334 self
.toint(-0.0, 0, "-zero", _32bit
=False)
335 self
.toint(min_value
, 0, _32bit
=False)
336 self
.toint(-min_value
, 0, _32bit
=False)
337 self
.toint(0.1, 0, _32bit
=False)
338 self
.toint(-0.1, 0, _32bit
=False)
339 self
.toint(1, 1, "one", _32bit
=False)
340 self
.toint(1.1, 1, "onepointone", _32bit
=False)
341 self
.toint(-1, -1, "-one", _32bit
=False)
342 self
.toint(0.6, 0, "truncate positive (0.6)", _32bit
=False)
343 self
.toint(1.6, 1, "truncate positive (1.6)", _32bit
=False)
344 self
.toint(-0.6, 0, "truncate negative (-0.6)", _32bit
=False)
345 self
.toint(-1.6, -1, "truncate negative (-1.6)", _32bit
=False)
346 self
.toint(fp_bits_add(2**63, -1), _32bit
=False)
347 self
.toint(2**63, _32bit
=False)
348 self
.toint(fp_bits_add(2**63, 1), _32bit
=False)
349 self
.toint(fp_bits_add(2**64, -1), _32bit
=False)
350 self
.toint(2**64, 0, _32bit
=False)
351 self
.toint(fp_bits_add(2**64, 1), _32bit
=False)
352 self
.toint(-fp_bits_add(2**63, -1), _32bit
=False)
353 self
.toint(-(2**63), _32bit
=False)
354 self
.toint(-fp_bits_add(2**63, 1), _32bit
=False)
355 self
.toint(-fp_bits_add(2**64, -1), _32bit
=False)
356 self
.toint(-(2**64), 0, _32bit
=False)
357 self
.toint(-fp_bits_add(2**64, 1), _32bit
=False)
358 self
.toint(2147483648.25, _32bit
=False)
359 self
.toint(2147483648.5, _32bit
=False)
360 self
.toint(2147483648.75, _32bit
=False)
361 self
.toint(4294967295.25, _32bit
=False)
362 self
.toint(4294967295.5, _32bit
=False)
363 self
.toint(4294967295.75, _32bit
=False)
364 self
.toint(3000000000.25, _32bit
=False)
365 self
.toint(3000000000.5, _32bit
=False)
366 self
.toint(3000000000.75, _32bit
=False)
367 self
.toint(-2147483648.25, _32bit
=False)
368 self
.toint(-2147483648.5, _32bit
=False)
369 self
.toint(-2147483648.75, _32bit
=False)
370 self
.toint(-4294967295.25, _32bit
=False)
371 self
.toint(-4294967295.5, _32bit
=False)
372 self
.toint(-4294967295.75, _32bit
=False)
373 self
.toint(-3000000000.25, _32bit
=False)
374 self
.toint(-3000000000.5, _32bit
=False)
375 self
.toint(-3000000000.75, _32bit
=False)
377 self
.toint(base
+ 0, _32bit
=False)
378 self
.toint(base
+ 1117, _32bit
=False)
379 self
.toint(base
+ 2234, _32bit
=False)
380 self
.toint(base
+ 3351, _32bit
=False)
381 self
.toint(base
+ 4468, _32bit
=False)
382 self
.toint(base
+ 5585, _32bit
=False)
383 self
.toint(base
+ 6702, _32bit
=False)
384 self
.toint(base
+ 7819, _32bit
=False)
385 self
.toint(base
+ 8936, _32bit
=False)
386 self
.toint(base
+ 10053, _32bit
=False)
387 self
.toint(base
+ 11170, _32bit
=False)
388 self
.toint(base
+ 12287, _32bit
=False)
389 self
.toint(base
+ 13404, _32bit
=False)
390 self
.toint(base
+ 14521, _32bit
=False)
391 self
.toint(base
+ 15638, _32bit
=False)
392 self
.toint(base
+ 16755, _32bit
=False)
393 self
.toint(base
+ 17872, _32bit
=False)
394 self
.toint(base
+ 18989, _32bit
=False)
395 self
.toint(base
+ 20106, _32bit
=False)
396 self
.toint(base
+ 21223, _32bit
=False)
397 self
.toint(base
+ 22340, _32bit
=False)
398 self
.toint(base
+ 23457, _32bit
=False)
399 self
.toint(base
+ 24574, _32bit
=False)
400 self
.toint(base
+ 25691, _32bit
=False)
401 self
.toint(base
+ 26808, _32bit
=False)
402 self
.toint(base
+ 27925, _32bit
=False)
403 self
.toint(base
+ 29042, _32bit
=False)
404 self
.toint(base
+ 30159, _32bit
=False)
405 self
.toint(base
+ 31276, _32bit
=False)
406 # bignum is (2 ^ 53 - 1) * 2 ^ 31 - highest number with bit 31 set.
407 bignum
= pow(2, 84) - pow(2, 31)
408 self
.toint(bignum
, _32bit
=False)
409 self
.toint(-bignum
, _32bit
=False)
410 self
.toint(2 * bignum
, _32bit
=False)
411 self
.toint(-(2 * bignum
), _32bit
=False)
412 self
.toint(bignum
- pow(2, 31), _32bit
=False)
413 self
.toint(-(bignum
- pow(2, 31)), _32bit
=False)
414 # max_fraction is largest number below 1.
415 max_fraction
= (1 - pow(2, -53))
416 self
.toint(max_fraction
, 0, _32bit
=False)
417 self
.toint(-max_fraction
, 0, _32bit
=False)
419 def case_js_touint64(self
):
420 # 64-bit equivalent of javascript's touint32
421 min_value
= pow(2, -1074)
422 # test cases derived from:
423 # https://chromium.googlesource.com/v8/v8.git/+/d94dfc2b01f988566aa410ce871588cf23b1285d/test/mjsunit/touint32.js
424 # with identical copyright notice as in case_js_toint32
425 self
.toint(0, 0, "0", signed
=False, _32bit
=False)
426 self
.toint(-0, 0, "-0", signed
=False, _32bit
=False)
427 self
.toint(math
.inf
, 0, "Infinity", signed
=False, _32bit
=False)
428 self
.toint(-math
.inf
, 0, "-Infinity", signed
=False, _32bit
=False)
429 self
.toint(math
.nan
, 0, "NaN", signed
=False, _32bit
=False)
430 self
.toint(math
.nan
, 0, "SNaN", inp_bits
=0x7ff0_0000_0000_0001,
431 signed
=False, _32bit
=False)
432 self
.toint(min_value
, 0, "MIN", signed
=False, _32bit
=False)
433 self
.toint(-min_value
, 0, "-MIN", signed
=False, _32bit
=False)
434 self
.toint(0.1, 0, "0.1", signed
=False, _32bit
=False)
435 self
.toint(-0.1, 0, "-0.1", signed
=False, _32bit
=False)
436 self
.toint(1, 1, "1", signed
=False, _32bit
=False)
437 self
.toint(1.1, 1, "1.1", signed
=False, _32bit
=False)
438 self
.toint(-1, 2**64 - 1, "-1", signed
=False, _32bit
=False)
439 self
.toint(-1.1, 2**64 - 1, "-1.1", signed
=False, _32bit
=False)
440 self
.toint(fp_bits_add(2**63, -1), signed
=False, _32bit
=False)
441 self
.toint(2**63, signed
=False, _32bit
=False)
442 self
.toint(fp_bits_add(2**63, 1), signed
=False, _32bit
=False)
443 self
.toint(fp_bits_add(2**64, -1), signed
=False, _32bit
=False)
444 self
.toint(2**64, 0, signed
=False, _32bit
=False)
445 self
.toint(fp_bits_add(2**64, 1), signed
=False, _32bit
=False)
446 self
.toint(-fp_bits_add(2**63, -1), signed
=False, _32bit
=False)
447 self
.toint(-(2**63), signed
=False, _32bit
=False)
448 self
.toint(-fp_bits_add(2**63, 1), signed
=False, _32bit
=False)
449 self
.toint(-fp_bits_add(2**64, -1), signed
=False, _32bit
=False)
450 self
.toint(-(2**64), 0, signed
=False, _32bit
=False)
451 self
.toint(-fp_bits_add(2**64, 1), signed
=False, _32bit
=False)
454 @functools.lru_cache(maxsize
=None)
455 def _ctfpr_fpscr(RN
, set_XX
, FR
, FPRF
, fpscr_unmodified
):
456 """ cached FPSCR computation for ctfpr_one since that part is slow """
457 initial_fpscr
= FPSCRState()
458 initial_fpscr
.RN
= RN
459 fpscr
= FPSCRState(initial_fpscr
)
467 fpscr
= FPSCRState(initial_fpscr
)
468 return initial_fpscr
, fpscr
470 def ctfpr_one(self
, inp
, bfp32
, IT
, Rc
, RN
):
471 if (dict(inp
=hex(inp
), bfp32
=bfp32
, IT
=IT
, Rc
=Rc
, RN
=RN
) !=
472 {'inp': '0x80001000', 'bfp32': True, 'IT': 3, 'Rc': True, 'RN': 0}):
473 return # FIXME: just for debugging
475 inp_width
= 64 if IT
& 0b10 else 32
476 inp_value
= inp
% 2 ** inp_width
479 if inp_value
>> (inp_width
- 1):
481 inp_value
-= 2 ** inp_width
482 # cast to nearby f32/f64
483 inp_fp
= fp_bits_add(inp_value
, 0, bfp32
=bfp32
)
484 if inp_fp
== inp_value
: # exact conversion -- no rounding necessary
486 expected_bits
= bitcast_fp_to_int(expected_fp
, bfp32
=False)
488 # get the fp value on either side of the exact value.
489 # we need to get several values and select 2 because int -> fp
490 # conversion in fp_bits_add could be off by a bit due to
491 # rounding/double-rounding.
492 # we can ignore weirdness around infinity because input values
493 # can't get big enough to convert to infinity for bfp32/64.
494 # we can ignore weirdness around zero because small integers
495 # always convert exactly, and therefore don't reach this
498 fp_bits_add(inp_value
, i
, bfp32
=bfp32
) for i
in range(-2, 3))
499 while fp_values
[-2] > inp_value
:
501 prev_fp
= fp_values
[-2]
502 next_fp
= fp_values
[-1]
503 # if fp values are big enough to not be exact, they are always
505 prev_int
= int(prev_fp
)
506 next_int
= int(next_fp
)
507 prev_fp_is_even
= bitcast_fp_to_int(prev_fp
, bfp32
=bfp32
) & 1 == 0
508 halfway
= 2 * inp_value
== prev_int
+ next_int
509 prev_is_closer
= 2 * inp_value
< prev_int
+ next_int
512 use_prev
= (halfway
and prev_fp_is_even
) or prev_is_closer
515 use_prev
= abs(prev_int
) < abs(next_int
)
520 assert RN
== 3, "invalid RN"
524 expected_fp
= prev_fp
526 expected_fp
= next_fp
527 expected_bits
= bitcast_fp_to_int(expected_fp
, bfp32
=False)
529 if expected_fp
!= inp_value
:
531 FR
= abs(expected_fp
) > abs(inp_value
)
533 FPRF
= "- Normal Number"
534 elif expected_fp
> 0:
535 FPRF
= "+ Normal Number"
537 # integer conversion never gives -0.0
540 # defined to not modify FPSCR since the conversion is always exact
541 fpscr_unmodified
= inp_width
== 32 and not bfp32
543 initial_fpscr
, fpscr
= self
._ctfpr
_fpscr
(
544 RN
=RN
, set_XX
=set_XX
, FR
=FR
, FPRF
=FPRF
,
545 fpscr_unmodified
=fpscr_unmodified
)
547 cr1
= int(fpscr
.FX
) << 3
548 cr1 |
= int(fpscr
.FEX
) << 2
549 cr1 |
= int(fpscr
.VX
) << 1
554 inp
=hex(inp
), bfp32
=bfp32
, IT
=IT
, Rc
=Rc
, RN
=RN
,
555 expected_fp
=expected_fp
.hex(), expected_bits
=hex(expected_bits
),
556 XX
=fpscr
.XX
, FR
=fpscr
.FR
, FPRF
=bin(int(fpscr
.FPRF
)), CR1
=bin(cr1
),
558 s
= "s" if bfp32
else ""
559 rc_str
= "." if Rc
else ""
560 lst
= [f
"ctfpr{s}{rc_str} 0,3,{IT}"]
564 e
= ExpectedState(pc
=4, int_regs
=gprs
, fp_regs
=fprs
)
566 e
.fpregs
[0] = expected_bits
569 _cached_program(*lst
), gprs
, fpregs
=fprs
, expected
=e
,
570 initial_fpscr
=int(initial_fpscr
))
572 def ctfpr(self
, inp
):
573 for bfp32
in (False, True):
575 for Rc
in (False, True):
577 self
.ctfpr_one(inp
, bfp32
, IT
, Rc
, RN
)
579 def case_ctfpr(self
):
581 for sh
in (0, 22, 23, 24, 31, 52, 53, 54, 63):
582 for offset
in range(-2, 3):
583 for offset_sh
in range(64):
585 v
+= offset
<< offset_sh
588 for i
in sorted(inp_values
):
591 def fmv(self
, gpr_bits
, bfp32
, Rc
):
594 if gpr_bits
& 0x7f80_0000 == 0x7f80_0000: # inf or nan
595 fpr_bits
= (gpr_bits
& 0x8000_0000) << 32
596 fpr_bits |
= 0x7ff0_0000_0000_0000
597 fpr_bits |
= (gpr_bits
& 0x7f_ffff) << 29
599 fpr_bits
= bitcast_fp_to_int(bitcast_int_to_fp(
600 gpr_bits
, bfp32
=True), bfp32
=False)
604 with self
.subTest(gpr_bits
=hex(gpr_bits
), fpr_bits
=hex(fpr_bits
),
606 s
= "s" if bfp32
else ""
607 rc_str
= "." if Rc
else ""
608 tg_p
= _cached_program(f
"mffpr{s}{rc_str} 3, 0")
609 # mtfpr[s]. doesn't exist since Rc=1 is basically useless due to
610 # fmv* not changing any FPSCR bits
611 fg_p
= _cached_program(f
"mtfpr{s} 0, 3")
616 tg_fprs
[0] = fpr_bits
617 fg_gprs
[3] = gpr_bits
618 tg_e
= ExpectedState(pc
=4, int_regs
=tg_gprs
, fp_regs
=tg_fprs
)
619 fg_e
= ExpectedState(pc
=4, int_regs
=fg_gprs
, fp_regs
=fg_fprs
)
620 tg_lt
= bool(gpr_bits
& (1 << 63))
621 tg_gt
= not tg_lt
and gpr_bits
!= 0
622 tg_eq
= gpr_bits
== 0
625 (tg_lt
<< 3) |
(tg_gt
<< 2) |
(tg_eq
<< 1) | tg_e
.so
)
626 fg_e
.fpregs
[0] = fpr_bits
627 tg_e
.intregs
[3] = gpr_bits
628 self
.add_case(fg_p
, fg_gprs
, fpregs
=fg_fprs
, expected
=fg_e
)
629 self
.add_case(tg_p
, tg_gprs
, fpregs
=tg_fprs
, expected
=tg_e
)
633 for sh
in (0, 22, 23, 24, 31, 52, 53, 54, 63):
634 for offset
in range(-2, 3):
635 for offset_sh
in range(64):
637 v
+= offset
<< offset_sh
640 for i
in sorted(inp_values
):
641 for bfp32
in (False, True):
642 for Rc
in (False, True):
643 self
.fmv(i
, bfp32
, Rc
)
646 class SVP64FMvFCvtCases(TestAccumulatorBase
):
647 def case_sv_mtfpr(self
):
648 lst
= list(SVP64Asm(["sv.mtfpr *3, *3"]))
651 svstate
= SVP64State()
654 gprs
[3] = 0xa2f77210b3759b72 # -3.0762581375623643e-140
655 gprs
[4] = 0xbb6c6f98d5f1165 # 3.106739523264776e-252
656 gprs
[5] = 0x4d94f81cb94383fe # 5.520783182773991e+65
657 gprs
[6] = 0xbabd64f913a550c0 # -9.497851164560019e-26
658 gprs
[7] = 0x946ee3df50c8b3c9 # -2.9362479271656598e-210
659 gprs
[8] = 0xc04c4950eeac2bf8 # -56.57278235823463
660 gprs
[9] = 0x94aadc76d0641448 # -4.0852462310367517e-209
661 gprs
[10] = 0x183ff479cd3c162a # 7.0039231684450285e-192
662 gprs
[11] = 0xa07f1f2626c68dad # -3.7138570072369393e-152
663 gprs
[12] = 0xc8f3eeb4b229348f # -2.778177315415125e+43
664 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
665 e
.fpregs
[3] = 0xa2f77210b3759b72 # -3.0762581375623643e-140
666 e
.fpregs
[4] = 0xbb6c6f98d5f1165 # 3.106739523264776e-252
667 e
.fpregs
[5] = 0x4d94f81cb94383fe # 5.520783182773991e+65
668 e
.fpregs
[6] = 0xbabd64f913a550c0 # -9.497851164560019e-26
669 e
.fpregs
[7] = 0x946ee3df50c8b3c9 # -2.9362479271656598e-210
670 e
.fpregs
[8] = 0xc04c4950eeac2bf8 # -56.57278235823463
671 e
.fpregs
[9] = 0x94aadc76d0641448 # -4.0852462310367517e-209
672 e
.fpregs
[10] = 0x183ff479cd3c162a # 7.0039231684450285e-192
673 e
.fpregs
[11] = 0xa07f1f2626c68dad # -3.7138570072369393e-152
674 e
.fpregs
[12] = 0xc8f3eeb4b229348f # -2.778177315415125e+43
675 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
676 initial_svstate
=svstate
, expected
=e
)
678 def case_sv_mffpr(self
):
679 lst
= list(SVP64Asm(["sv.mffpr *3, *3"]))
682 svstate
= SVP64State()
685 fprs
[3] = 0x4a467f81df2c49c2 # 6.576194817283066e+49
686 fprs
[4] = 0xad9e2a873ed027e4 # -5.923533316236948e-89
687 fprs
[5] = 0xd5e965376a6c56b6 # -7.28053270057725e+105
688 fprs
[6] = 0xa58d0a3abb7d83e3 # -8.378916175016297e-128
689 fprs
[7] = 0x22a5d28a80cebc2 # 3.1493721884183893e-298
690 fprs
[8] = 0xcf0249c06893a97c # -4.039032746538712e+72
691 fprs
[9] = 0x58bfa28e7438dce1 # 3.1909937185457982e+119
692 fprs
[10] = 0x8e4cb0a3d0022bc6 # -8.605260192425176e-240
693 fprs
[11] = 0xdff979f581d80ae5 # -2.134891937663687e+154
694 fprs
[12] = 0x4b45b570cd46b00b # 4.158570794713441e+54
695 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
696 e
.intregs
[3] = 0x4a467f81df2c49c2 # 6.576194817283066e+49
697 e
.intregs
[4] = 0xad9e2a873ed027e4 # -5.923533316236948e-89
698 e
.intregs
[5] = 0xd5e965376a6c56b6 # -7.28053270057725e+105
699 e
.intregs
[6] = 0xa58d0a3abb7d83e3 # -8.378916175016297e-128
700 e
.intregs
[7] = 0x22a5d28a80cebc2 # 3.1493721884183893e-298
701 e
.intregs
[8] = 0xcf0249c06893a97c # -4.039032746538712e+72
702 e
.intregs
[9] = 0x58bfa28e7438dce1 # 3.1909937185457982e+119
703 e
.intregs
[10] = 0x8e4cb0a3d0022bc6 # -8.605260192425176e-240
704 e
.intregs
[11] = 0xdff979f581d80ae5 # -2.134891937663687e+154
705 e
.intregs
[12] = 0x4b45b570cd46b00b # 4.158570794713441e+54
706 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
707 initial_svstate
=svstate
, expected
=e
)
709 def case_sv_mtfprs(self
):
710 lst
= list(SVP64Asm(["sv.mtfprs *3, *3"]))
713 svstate
= SVP64State()
716 gprs
[3] = 0x3388bdb0b2a9e320 # 0x3388bdb0 || -1.9777473880822072e-08
717 gprs
[4] = 0x8719509941543782 # 0x87195099 || 13.263551712036133
718 gprs
[5] = 0xaae3fe31cd28d549 # 0xaae3fe31 || -177034384.0
719 gprs
[6] = 0xcc89e2fc3834d36e # 0xcc89e2fc || 4.3112253479193896e-05
720 gprs
[7] = 0xf2ae167344013f0 # 0xf2ae167 || 1.7888646652863827e-07
721 gprs
[8] = 0x6ea3c0a2a2f641ea # 0x6ea3c0a2 || -6.674822283613962e-18
722 gprs
[9] = 0x4645527fdab1ee2f # 0x4645527f || -2.5041478254329856e+16
723 gprs
[10] = 0x6aa03fc062dcbe1e # 0x6aa03fc0 || 2.0359915416663045e+21
724 gprs
[11] = 0x489c6f48871f0169 # 0x489c6f48 || -1.196224492164401e-34
725 gprs
[12] = 0x6a92d0d40070bb60 # 0x6a92d0d4 || 1.0352793054431749e-38
726 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
727 e
.fpregs
[3] = 0xbe553c6400000000 # -1.9777473880822072e-08
728 e
.fpregs
[4] = 0x402a86f040000000 # 13.263551712036133
729 e
.fpregs
[5] = 0xc1a51aa920000000 # -177034384.0
730 e
.fpregs
[6] = 0x3f069a6dc0000000 # 4.3112253479193896e-05
731 e
.fpregs
[7] = 0x3e88027e00000000 # 1.7888646652863827e-07
732 e
.fpregs
[8] = 0xbc5ec83d40000000 # -6.674822283613962e-18
733 e
.fpregs
[9] = 0xc3563dc5e0000000 # -2.5041478254329856e+16
734 e
.fpregs
[10] = 0x445b97c3c0000000 # 2.0359915416663045e+21
735 e
.fpregs
[11] = 0xb8e3e02d20000000 # -1.196224492164401e-34
736 e
.fpregs
[12] = 0x380c2ed800000000 # 1.0352793054431749e-38
737 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
738 initial_svstate
=svstate
, expected
=e
)
740 def case_sv_mffprs(self
):
741 lst
= list(SVP64Asm(["sv.mffprs *3, *3"]))
744 svstate
= SVP64State()
747 fprs
[3] = 0xb848c47620000000 # f64 -1.4556985522680637e-37
748 fprs
[4] = 0x3d6e75f2a0000000 # f64 8.657461141210743e-13
749 fprs
[5] = 0x47b89e7a80000000 # f64 3.272433939766293e+37
750 fprs
[6] = 0xc02ef02820000000 # f64 -15.469056129455566
751 fprs
[7] = 0xc619b3dc00000000 # f64 -5.090919608237361e+29
752 fprs
[8] = 0xc794867ba0000000 # f64 -6.820708776907309e+36
753 fprs
[9] = 0x3f49827860000000 # f64 0.0007784927147440612
754 fprs
[10] = 0xbaf7107e40000000 # f64 -1.1924028985020467e-24
755 fprs
[11] = 0x43aa3150a0000000 # f64 9.43689183484969e+17
756 fprs
[12] = 0xbed08ab060000000 # f64 -3.943861429434037e-06
757 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
758 e
.intregs
[3] = 0x824623b1 # f32 -1.4556985522680637e-37
759 e
.intregs
[4] = 0x2b73af95 # f32 8.657461141210743e-13
760 e
.intregs
[5] = 0x7dc4f3d4 # f32 3.272433939766293e+37
761 e
.intregs
[6] = 0xc1778141 # f32 -15.469056129455566
762 e
.intregs
[7] = 0xf0cd9ee0 # f32 -5.090919608237361e+29
763 e
.intregs
[8] = 0xfca433dd # f32 -6.820708776907309e+36
764 e
.intregs
[9] = 0x3a4c13c3 # f32 0.0007784927147440612
765 e
.intregs
[10] = 0x97b883f2 # f32 -1.1924028985020467e-24
766 e
.intregs
[11] = 0x5d518a85 # f32 9.43689183484969e+17
767 e
.intregs
[12] = 0xb6845583 # f32 -3.943861429434037e-06
768 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
769 initial_svstate
=svstate
, expected
=e
)
771 def case_sv_ctfpr(self
):
772 lst
= list(SVP64Asm(["sv.ctfpr *3, *3, 0"]))
775 svstate
= SVP64State()
778 gprs
[3] = 0xa2f77210b3759b72 # 0xa2f77210 || -1284138126
779 gprs
[4] = 0xbb6c6f98d5f1165 # 0xbb6c6f9 || -1923149467
780 gprs
[5] = 0x4d94f81cb94383fe # 0x4d94f81c || -1186757634
781 gprs
[6] = 0xbabd64f913a550c0 # 0xbabd64f9 || 329601216
782 gprs
[7] = 0x946ee3df50c8b3c9 # 0x946ee3df || 1355330505
783 gprs
[8] = 0xc04c4950eeac2bf8 # 0xc04c4950 || -290706440
784 gprs
[9] = 0x94aadc76d0641448 # 0x94aadc76 || -798747576
785 gprs
[10] = 0x183ff479cd3c162a # 0x183ff479 || -851700182
786 gprs
[11] = 0xa07f1f2626c68dad # 0xa07f1f26 || 650546605
787 gprs
[12] = 0xc8f3eeb4b229348f # 0xc8f3eeb4 || -1305922417
788 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
789 e
.fpregs
[3] = 0xc1d3229923800000 # f64 -1284138126.0
790 e
.fpregs
[4] = 0xc1dca83ba6c00000 # f64 -1923149467.0
791 e
.fpregs
[5] = 0xc1d1af1f00800000 # f64 -1186757634.0
792 e
.fpregs
[6] = 0x41b3a550c0000000 # f64 329601216.0
793 e
.fpregs
[7] = 0x41d4322cf2400000 # f64 1355330505.0
794 e
.fpregs
[8] = 0xc1b153d408000000 # f64 -290706440.0
795 e
.fpregs
[9] = 0xc1c7cdf5dc000000 # f64 -798747576.0
796 e
.fpregs
[10] = 0xc1c961f4eb000000 # f64 -851700182.0
797 e
.fpregs
[11] = 0x41c36346d6800000 # f64 650546605.0
798 e
.fpregs
[12] = 0xc1d375b2dc400000 # f64 -1305922417.0
799 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
800 initial_svstate
=svstate
, expected
=e
)
802 def case_sv_cffpr_js(self
):
803 lst
= list(SVP64Asm(["sv.cffpr *3, *3, 5, 0"]))
806 svstate
= SVP64State()
809 fprs
[3] = 0xc11b409582aac6c2 # f64 -446501.37760458526
810 fprs
[4] = 0x40311164f59f97ba # f64 17.067946769202287
811 fprs
[5] = 0x4179786c25161402 # f64 26707650.317890175
812 fprs
[6] = 0x77a2d30d30aedc37 # f64 1.9423512004394842e+268
813 fprs
[7] = 0xfcc691390ace2fbe # f64 -1.1260170101142855e+293
814 fprs
[8] = 0xc145328877d66458 # f64 -2778384.9362302236
815 fprs
[9] = 0xc0e6c2048e0540f9 # f64 -46608.14233648958
816 fprs
[10] = 0xc1497c2a90a71511 # f64 -3340373.130098947
817 fprs
[11] = 0x2aaabda57b592051 # f64 3.731006400911987e-103
818 fprs
[12] = 0x40839fff57931a98 # f64 627.9996787540904
819 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
820 e
.intregs
[3] = 0xfffffffffff92fdb # -446501
821 e
.intregs
[4] = 0x11 # 17
822 e
.intregs
[5] = 0x19786c2 # 26707650
825 e
.intregs
[8] = 0xffffffffffd59af0 # -2778384
826 e
.intregs
[9] = 0xffffffffffff49f0 # -46608
827 e
.intregs
[10] = 0xffffffffffcd07ab # -3340373
829 e
.intregs
[12] = 0x273 # 627
831 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
832 initial_svstate
=svstate
, expected
=e
)
834 def case_sv_cffpr_sat(self
):
835 lst
= list(SVP64Asm(["sv.cffpr *3, *3, 3, 0"]))
838 svstate
= SVP64State()
841 fprs
[3] = 0x41d6317a0c07f8c2 # f64 1489365040.124558
842 fprs
[4] = 0xc12fca9889a15f42 # f64 -1041740.2688092964
843 fprs
[5] = 0x2d7709c8cb530878 # f64 1.1309677587699661e-89
844 fprs
[6] = 0x4c653162f75415d0 # f64 1.0642407361512732e+60
845 fprs
[7] = 0xc106f58246849979 # f64 -188080.28443260098
846 fprs
[8] = 0x3fc86e10067c6b85 # f64 0.1908588439626692
847 fprs
[9] = 0xc04998b922650ff1 # f64 -51.19314985212976
848 fprs
[10] = 0xc0bf8d2648f0d00b # f64 -8077.149550486366
849 fprs
[11] = 0xcac1f352558671c8 # f64 -1.3432140136107625e+52
850 fprs
[12] = 0xc1799318e724a0a8 # f64 -26816910.446442276
851 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
852 e
.intregs
[3] = 0x58c5e830 # 1489365040
853 e
.intregs
[4] = 0xfffffffffff01ab4 # -1041740
855 e
.intregs
[6] = 0x7fffffff # 2147483647
856 e
.intregs
[7] = 0xfffffffffffd2150 # -188080
858 e
.intregs
[9] = 0xffffffffffffffcd # -51
859 e
.intregs
[10] = 0xffffffffffffe073 # -8077
860 e
.intregs
[11] = 0xffffffff80000000 # -2147483648
861 e
.intregs
[12] = 0xfffffffffe66ce72 # -26816910
863 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
864 initial_svstate
=svstate
, expected
=e
)
866 def case_sv_ctfprs(self
):
867 lst
= list(SVP64Asm(["sv.ctfprs *3, *3, 0"]))
870 svstate
= SVP64State()
873 gprs
[3] = 0x3388bdb0b2a9e320 # 0x3388bdb0 || -1297489120
874 gprs
[4] = 0x8719509941543782 # 0x87195099 || 1096038274
875 gprs
[5] = 0xaae3fe31cd28d549 # 0xaae3fe31 || -852961975
876 gprs
[6] = 0xcc89e2fc3834d36e # 0xcc89e2fc || 942986094
877 gprs
[7] = 0xf2ae167344013f0 # 0xf2ae167 || 876614640
878 gprs
[8] = 0x6ea3c0a2a2f641ea # 0x6ea3c0a2 || -1560919574
879 gprs
[9] = 0x4645527fdab1ee2f # 0x4645527f || -625873361
880 gprs
[10] = 0x6aa03fc062dcbe1e # 0x6aa03fc0 || 1658633758
881 gprs
[11] = 0x489c6f48871f0169 # 0x489c6f48 || -2028011159
882 gprs
[12] = 0x6a92d0d40070bb60 # 0x6a92d0d4 || 7388000
883 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
884 e
.fpregs
[3] = 0xc1d3558740000000 # f64 -1297489152.0
885 e
.fpregs
[4] = 0x41d0550de0000000 # f64 1096038272.0
886 e
.fpregs
[5] = 0xc1c96b9560000000 # f64 -852961984.0
887 e
.fpregs
[6] = 0x41cc1a69c0000000 # f64 942986112.0
888 e
.fpregs
[7] = 0x41ca200a00000000 # f64 876614656.0
889 e
.fpregs
[8] = 0xc1d7426f80000000 # f64 -1560919552.0
890 e
.fpregs
[9] = 0xc1c2a708e0000000 # f64 -625873344.0
891 e
.fpregs
[10] = 0x41d8b72f80000000 # f64 1658633728.0
892 e
.fpregs
[11] = 0xc1de383fa0000000 # f64 -2028011136.0
893 e
.fpregs
[12] = 0x415c2ed800000000 # f64 7388000.0
895 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
896 initial_svstate
=svstate
, expected
=e
)