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
"fcvttgo. 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 _fcvtfg_fpscr(RN
, set_XX
, FR
, FPRF
, fpscr_unmodified
):
456 """ cached FPSCR computation for fcvtfg_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 fcvtfg_one(self
, inp
, bfp32
, IT
, Rc
, RN
):
472 inp_width
= 64 if IT
& 0b10 else 32
473 inp_value
= inp
% 2 ** inp_width
476 if inp_value
>> (inp_width
- 1):
478 inp_value
-= 2 ** inp_width
479 # cast to nearby f32/f64
480 inp_fp
= fp_bits_add(inp_value
, 0, bfp32
=bfp32
)
481 if inp_fp
== inp_value
: # exact conversion -- no rounding necessary
483 expected_bits
= bitcast_fp_to_int(expected_fp
, bfp32
=False)
485 # get the fp value on either side of the exact value.
486 # we need to get several values and select 2 because int -> fp
487 # conversion in fp_bits_add could be off by a bit due to
488 # rounding/double-rounding.
489 # we can ignore weirdness around infinity because input values
490 # can't get big enough to convert to infinity for bfp32/64.
491 # we can ignore weirdness around zero because small integers
492 # always convert exactly, and therefore don't reach this
495 fp_bits_add(inp_value
, i
, bfp32
=bfp32
) for i
in range(-2, 3))
496 while fp_values
[-2] > inp_value
:
498 prev_fp
= fp_values
[-2]
499 next_fp
= fp_values
[-1]
500 # if fp values are big enough to not be exact, they are always
502 prev_int
= int(prev_fp
)
503 next_int
= int(next_fp
)
504 prev_fp_is_even
= bitcast_fp_to_int(prev_fp
, bfp32
=bfp32
) & 1 == 0
505 halfway
= 2 * inp_value
== prev_int
+ next_int
506 prev_is_closer
= 2 * inp_value
< prev_int
+ next_int
509 use_prev
= (halfway
and prev_fp_is_even
) or prev_is_closer
512 use_prev
= abs(prev_int
) < abs(next_int
)
517 assert RN
== 3, "invalid RN"
521 expected_fp
= prev_fp
523 expected_fp
= next_fp
524 expected_bits
= bitcast_fp_to_int(expected_fp
, bfp32
=False)
526 if expected_fp
!= inp_value
:
528 FR
= abs(expected_fp
) > abs(inp_value
)
530 FPRF
= "- Normal Number"
531 elif expected_fp
> 0:
532 FPRF
= "+ Normal Number"
534 # integer conversion never gives -0.0
537 # defined to not modify FPSCR since the conversion is always exact
538 fpscr_unmodified
= inp_width
== 32 and not bfp32
540 initial_fpscr
, fpscr
= self
._fcvtfg
_fpscr
(
541 RN
=RN
, set_XX
=set_XX
, FR
=FR
, FPRF
=FPRF
,
542 fpscr_unmodified
=fpscr_unmodified
)
544 cr1
= int(fpscr
.FX
) << 3
545 cr1 |
= int(fpscr
.FEX
) << 2
546 cr1 |
= int(fpscr
.VX
) << 1
551 inp
=hex(inp
), bfp32
=bfp32
, IT
=IT
, Rc
=Rc
, RN
=RN
,
552 expected_fp
=expected_fp
.hex(), expected_bits
=hex(expected_bits
),
553 XX
=fpscr
.XX
, FR
=fpscr
.FR
, FPRF
=bin(int(fpscr
.FPRF
)), CR1
=bin(cr1
),
555 s
= "s" if bfp32
else ""
556 rc_str
= "." if Rc
else ""
557 lst
= [f
"fcvtfg{s}{rc_str} 0,3,{IT}"]
561 e
= ExpectedState(pc
=4, int_regs
=gprs
, fp_regs
=fprs
)
563 e
.fpregs
[0] = expected_bits
566 _cached_program(*lst
), gprs
, fpregs
=fprs
, expected
=e
,
567 initial_fpscr
=int(initial_fpscr
))
569 def fcvtfg(self
, inp
):
570 for bfp32
in (False, True):
572 for Rc
in (False, True):
574 self
.fcvtfg_one(inp
, bfp32
, IT
, Rc
, RN
)
576 def case_fcvtfg(self
):
578 for sh
in (0, 22, 23, 24, 31, 52, 53, 54, 63):
579 for offset
in range(-2, 3):
580 for offset_sh
in range(64):
582 v
+= offset
<< offset_sh
585 for i
in sorted(inp_values
):
589 class SVP64FMvFCvtCases(TestAccumulatorBase
):
590 @skip_case("FIXME: rewrite to fmv/fcvt tests")
591 def case_sv_fmaxmag19(self
):
592 lst
= list(SVP64Asm(["sv.fmaxmag19 *32,*64,*96"]))
595 svstate
= SVP64State()
598 r
= range(svstate
.vl
)
599 for i
, rev_i
in zip(r
, reversed(r
)):
600 fprs
[64 + i
] = struct
.unpack("<Q", struct
.pack("<d", i
))[0]
601 fprs
[96 + i
] = struct
.unpack("<Q", struct
.pack("<d", rev_i
))[0]
602 e
= ExpectedState(pc
=8, int_regs
=gprs
, fp_regs
=fprs
)
603 e
.fpregs
[32] = 0x403f000000000000
604 e
.fpregs
[33] = 0x403e000000000000
605 e
.fpregs
[34] = 0x403d000000000000
606 e
.fpregs
[35] = 0x403c000000000000
607 e
.fpregs
[36] = 0x403b000000000000
608 e
.fpregs
[37] = 0x403a000000000000
609 e
.fpregs
[38] = 0x4039000000000000
610 e
.fpregs
[39] = 0x4038000000000000
611 e
.fpregs
[40] = 0x4037000000000000
612 e
.fpregs
[41] = 0x4036000000000000
613 e
.fpregs
[42] = 0x4035000000000000
614 e
.fpregs
[43] = 0x4034000000000000
615 e
.fpregs
[44] = 0x4033000000000000
616 e
.fpregs
[45] = 0x4032000000000000
617 e
.fpregs
[46] = 0x4031000000000000
618 e
.fpregs
[47] = 0x4030000000000000
619 e
.fpregs
[48] = 0x4030000000000000
620 e
.fpregs
[49] = 0x4031000000000000
621 e
.fpregs
[50] = 0x4032000000000000
622 e
.fpregs
[51] = 0x4033000000000000
623 e
.fpregs
[52] = 0x4034000000000000
624 e
.fpregs
[53] = 0x4035000000000000
625 e
.fpregs
[54] = 0x4036000000000000
626 e
.fpregs
[55] = 0x4037000000000000
627 e
.fpregs
[56] = 0x4038000000000000
628 e
.fpregs
[57] = 0x4039000000000000
629 e
.fpregs
[58] = 0x403a000000000000
630 e
.fpregs
[59] = 0x403b000000000000
631 e
.fpregs
[60] = 0x403c000000000000
632 e
.fpregs
[61] = 0x403d000000000000
633 e
.fpregs
[62] = 0x403e000000000000
634 e
.fpregs
[63] = 0x403f000000000000
635 self
.add_case(Program(lst
, False), gprs
, fpregs
=fprs
,
636 initial_svstate
=svstate
, expected
=e
)