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
.decoder
.power_enums
import FMinMaxMode
7 from openpower
.fpscr
import FPSCRState
14 0x0000_0000_0000_0000, # 0.0
15 0x8000_0000_0000_0000, # -0.0
16 # too many values, comment some out
17 # 0x0000_0000_0000_0001, # min denormal
18 # 0x8000_0000_0000_0001, # - min denormal
19 # 0x0010_0000_0000_0000, # min normal
20 # 0x8010_0000_0000_0000, # - min normal
21 # 0x36A0_0000_0000_0000, # min f32 denormal
22 # 0xB6A0_0000_0000_0000, # - min f32 denormal
23 # 0x3810_0000_0000_0000, # min f32 normal
24 # 0xB810_0000_0000_0000, # - min f32 normal
25 0x3FF0_0000_0000_0000, # 1.0
26 0xBFF0_0000_0000_0000, # -1.0
27 0x4000_0000_0000_0000, # 2.0
28 0xC000_0000_0000_0000, # -2.0
29 # 0x47EF_FFFF_E000_0000, # max f32 normal
30 # 0xC7EF_FFFF_E000_0000, # - max f32 normal
31 # 0x7FEF_FFFF_FFFF_FFFF, # max normal
32 # 0xFFEF_FFFF_FFFF_FFFF, # - max normal
33 0x7FF0_0000_0000_0000, # infinity
34 0xFFF0_0000_0000_0000, # -infinity
35 # 0x7FF0_0000_0000_0001, # first sNaN
36 0xFFF0_0000_0000_0001, # - first sNaN
37 # 0x7FF0_0000_2000_0000, # first f32 sNaN
38 # 0xFFF0_0000_2000_0000, # - first f32 sNaN
39 # 0x7FF7_FFFF_E000_0000, # last f32 sNaN
40 # 0xFFF7_FFFF_E000_0000, # - last f32 sNaN
41 # 0x7FF7_FFFF_FFFF_FFFF, # last sNaN
42 # 0xFFF7_FFFF_FFFF_FFFF, # - last sNaN
43 0x7FF8_0000_0000_0000, # first qNaN
44 # 0xFFF8_0000_0000_0000, # - first qNaN
45 # 0x7FFF_FFFF_E000_0000, # last f32 qNaN
46 # 0xFFFF_FFFF_E000_0000, # - last f32 qNaN
47 # 0x7FFF_FFFF_FFFF_FFFF, # last qNaN
48 0xFFFF_FFFF_FFFF_FFFF, # - last qNaN
52 class FMinMaxCases(TestAccumulatorBase
):
53 # _FILTER is for debugging
56 # 'RA': '0x0', 'RB': '0xfff0000000000001',
57 # 'FMM': 'FMinMaxMode.fminnum08', 'VE': False, 'initial_VXSNAN': False,
58 # 'expected': '0xfff8000000000001', 'any_snan': True, 'CR1': 10,
61 def reference_fminmax(self
, FMM
, RA
, RB
):
62 # type: (FMinMaxMode, int, int) -> tuple[int, bool]
63 op
= FMinMaxMode(FMM
.value
& 0b11)
64 is_max
= bool(FMM
.value
& 0b1000)
65 is_mag
= bool(FMM
.value
& 0b100)
66 MANT_MASK
= 0xF_FFFF_FFFF_FFFF
67 EXP_MASK
= 0x7FF0_0000_0000_0000
68 SIGN_MASK
= 0x8000_0000_0000_0000
69 a_is_nan
= RA
& MANT_MASK
and RA
& EXP_MASK
== EXP_MASK
70 a_quieted
= RA |
0x8_0000_0000_0000
71 b_is_nan
= RB
& MANT_MASK
and RB
& EXP_MASK
== EXP_MASK
72 b_quieted
= RB |
0x8_0000_0000_0000
73 a_is_snan
= a_is_nan
and a_quieted
!= RA
74 b_is_snan
= b_is_nan
and b_quieted
!= RB
75 any_snan
= a_is_snan
or b_is_snan
76 if op
is FMinMaxMode
.fminnum08
:
78 return a_quieted
, any_snan
80 return b_quieted
, any_snan
81 if a_is_nan
and b_is_nan
:
82 return a_quieted
, any_snan
87 elif op
is FMinMaxMode
.fmin19
:
89 return a_quieted
, any_snan
91 return b_quieted
, any_snan
92 elif op
is FMinMaxMode
.fminnum19
:
93 if a_is_nan
and b_is_nan
:
94 return a_quieted
, any_snan
100 assert op
is FMinMaxMode
.fminc
101 if a_is_nan
or b_is_nan
:
103 if RA
& ~SIGN_MASK
== 0 and RB
& ~SIGN_MASK
== 0:
105 if RA
& ~SIGN_MASK
== 0 and RB
& ~SIGN_MASK
== 0:
107 return RA
& RB
, any_snan
108 return RA | RB
, any_snan
114 if is_mag
and RA
& ~SIGN_MASK
!= RB
& ~SIGN_MASK
:
117 cmp_RA
= struct
.unpack("<d", struct
.pack("<Q", cmp_RA
))[0]
118 cmp_RB
= struct
.unpack("<d", struct
.pack("<Q", cmp_RB
))[0]
119 if cmp(cmp_RA
, cmp_RB
):
123 def fminmax(self
, FMM
, VE
, initial_VXSNAN
):
124 # type: (FMinMaxMode, bool, bool) -> None
125 if self
._FILTER
is not None and (
126 str(FMM
) != self
._FILTER
['FMM'] or
127 VE
!= self
._FILTER
['VE'] or
128 initial_VXSNAN
!= self
._FILTER
['initial_VXSNAN']):
130 prog
= Program(list(SVP64Asm([f
"fminmax. 3,4,5,{FMM.value}"])), False)
131 for RA
in _TEST_VALUES
:
132 for RB
in _TEST_VALUES
:
135 fprs
[3] = 0x0123_4567_89AB_CDEF
138 e
= ExpectedState(pc
=4, int_regs
=gprs
, fp_regs
=fprs
)
139 initial_fpscr
= FPSCRState()
140 initial_fpscr
.VE
= VE
141 initial_fpscr
.VXSNAN
= initial_VXSNAN
142 fpscr
= FPSCRState(initial_fpscr
)
143 RT
, any_snan
= self
.reference_fminmax(FMM
, RA
, RB
)
148 if not fpscr
.VE
or not any_snan
:
152 e
.sprs
['SRR0'] = 0 # insn is at address 0
153 e
.sprs
['SRR1'] = e
.msr |
(1 << (63 - 43))
154 e
.msr
= 0x9000000000000001
156 cr1
= int(fpscr
.FX
) << 3
157 cr1 |
= int(fpscr
.FEX
) << 2
158 cr1 |
= int(fpscr
.VX
) << 1
162 RA
=hex(RA
), RB
=hex(RB
), FMM
=str(FMM
), VE
=VE
,
163 initial_VXSNAN
=initial_VXSNAN
, expected
=hex(RT
),
164 any_snan
=any_snan
, CR1
=cr1
)
165 if self
._FILTER
is not None and kwargs
!= self
._FILTER
:
167 with self
.subTest(**kwargs
):
168 self
.add_case(prog
, gprs
, fpregs
=fprs
, expected
=e
,
169 initial_fpscr
=int(initial_fpscr
))
171 def case_fminmax(self
):
172 for FMM
, VE
, VXSNAN
in itertools
.product(
173 FMinMaxMode
, (False, True), (False, True)):
175 # isn't really a legal state that the simulator can end up in
176 # since MSR.FE0/FE1 are also set, this would have been caught
177 # by whatever previous instruction changed to this state
179 self
.fminmax(FMM
, VE
, VXSNAN
)