misc fixes for fallout of copying insn inputs
[openpower-isa.git] / src / openpower / test / fptrans / fminmax_cases.py
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
8 import operator
9 import struct
10 import itertools
11
12
13 _TEST_VALUES = [
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
49 ]
50
51
52 class FMinMaxCases(TestAccumulatorBase):
53 # _FILTER is for debugging
54 _FILTER = None
55 # _FILTER = {
56 # 'RA': '0x0', 'RB': '0xfff0000000000001',
57 # 'FMM': 'FMinMaxMode.fminnum08', 'VE': False, 'initial_VXSNAN': False,
58 # 'expected': '0xfff8000000000001', 'any_snan': True, 'CR1': 10,
59 # }
60
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:
77 if a_is_snan:
78 return a_quieted, any_snan
79 if b_is_snan:
80 return b_quieted, any_snan
81 if a_is_nan and b_is_nan:
82 return a_quieted, any_snan
83 if a_is_nan:
84 return RB, any_snan
85 if b_is_nan:
86 return RA, any_snan
87 elif op is FMinMaxMode.fmin19:
88 if a_is_nan:
89 return a_quieted, any_snan
90 if b_is_nan:
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
95 if a_is_nan:
96 return RB, any_snan
97 if b_is_nan:
98 return RA, any_snan
99 else:
100 assert op is FMinMaxMode.fminc
101 if a_is_nan or b_is_nan:
102 return RB, any_snan
103 if RA & ~SIGN_MASK == 0 and RB & ~SIGN_MASK == 0:
104 return RB, any_snan
105 if RA & ~SIGN_MASK == 0 and RB & ~SIGN_MASK == 0:
106 if is_max:
107 return RA & RB, any_snan
108 return RA | RB, any_snan
109 cmp = operator.lt
110 if is_max:
111 cmp = operator.gt
112 cmp_RA = RA
113 cmp_RB = RB
114 if is_mag and RA & ~SIGN_MASK != RB & ~SIGN_MASK:
115 cmp_RA &= ~SIGN_MASK
116 cmp_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):
120 return RA, any_snan
121 return RB, any_snan
122
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']):
129 return
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:
133 gprs = [0] * 32
134 fprs = [0] * 32
135 fprs[3] = 0x0123_4567_89AB_CDEF
136 fprs[4] = RA
137 fprs[5] = RB
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)
144 if any_snan:
145 if not fpscr.VXSNAN:
146 fpscr.FX = 1
147 fpscr.VXSNAN = 1
148 if not fpscr.VE or not any_snan:
149 e.fpregs[3] = RT
150 else:
151 e.pc = 0x700
152 e.sprs['SRR0'] = 0 # insn is at address 0
153 e.sprs['SRR1'] = e.msr | (1 << (63 - 43))
154 e.msr = 0x9000000000000001
155 e.fpscr = int(fpscr)
156 cr1 = int(fpscr.FX) << 3
157 cr1 |= int(fpscr.FEX) << 2
158 cr1 |= int(fpscr.VX) << 1
159 cr1 |= int(fpscr.OX)
160 e.crregs[1] = cr1
161 kwargs = dict(
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:
166 continue
167 with self.subTest(**kwargs):
168 self.add_case(prog, gprs, fpregs=fprs, expected=e,
169 initial_fpscr=int(initial_fpscr))
170
171 def case_fminmax(self):
172 for FMM, VE, VXSNAN in itertools.product(
173 FMinMaxMode, (False, True), (False, True)):
174 if VE and VXSNAN:
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
178 continue
179 self.fminmax(FMM, VE, VXSNAN)