665f30b04a00a529494c903117786ce37cb02f3f
[openpower-isa.git] / src / openpower / test / bigint / bigint_cases.py
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
7 _SHIFT_TEST_RANGE = list(range(-64, 128, 16)) + [1, 63]
8
9
10 class BigIntCases(TestAccumulatorBase):
11 def case_maddedu(self):
12 lst = list(SVP64Asm(["maddedu 3,5,6,7"]))
13 gprs = [0] * 32
14 gprs[5] = 0x123456789ABCDEF
15 gprs[6] = 0xFEDCBA9876543210
16 gprs[7] = 0x02468ACE13579BDF
17 e = ExpectedState(pc=4, int_regs=gprs)
18 e.intregs[3] = (gprs[5] * gprs[6] + gprs[7]) % 2 ** 64
19 e.intregs[7] = (gprs[5] * gprs[6] + gprs[7]) >> 64
20 self.add_case(Program(lst, False), gprs, expected=e)
21
22 def case_divmod2du(self):
23 lst = list(SVP64Asm(["divmod2du 3,5,6,7"]))
24 gprs = [0] * 32
25 gprs[5] = 0x123456789ABCDEF
26 gprs[6] = 0xFEDCBA9876543210
27 gprs[7] = 0x02468ACE13579BDF
28 e = ExpectedState(pc=4, int_regs=gprs)
29 v = gprs[5] | (gprs[7] << 64)
30 e.intregs[3] = v // gprs[6]
31 e.intregs[7] = v % gprs[6]
32 self.add_case(Program(lst, False), gprs, expected=e)
33
34 # FIXME: test more divmod2du special cases
35
36 def case_dsld0(self):
37 prog = Program(list(SVP64Asm(["dsld 3,4,5,6"])), False)
38 for sh in _SHIFT_TEST_RANGE:
39 with self.subTest(sh=sh):
40 gprs = [0] * 32
41 gprs[6] = 0x123456789ABCDEF
42 gprs[4] = 0xFEDCBA9876543210
43 gprs[5] = sh % 2 ** 64
44 e = ExpectedState(pc=4, int_regs=gprs)
45 v = gprs[4]
46 v <<= sh % 64
47 mask = (1 << (sh % 64))-1
48 v |= gprs[6] & mask
49 e.intregs[3] = v % 2 ** 64
50 e.intregs[6] = (v >> 64) % 2 ** 64
51 self.add_case(prog, gprs, expected=e)
52
53 def case_dsrd0(self):
54 prog = Program(list(SVP64Asm(["dsrd 3,4,5,6"])), False)
55 for sh in _SHIFT_TEST_RANGE:
56 with self.subTest(sh=sh):
57 gprs = [0] * 32
58 gprs[6] = 0x123456789ABCDEF
59 gprs[4] = 0xFEDCBA9876543210
60 gprs[5] = sh % 2 ** 64
61 e = ExpectedState(pc=4, int_regs=gprs)
62 v = (gprs[4] << 64)
63 v >>= sh % 64
64 mask = ~((2 ** 64 - 1) >> (sh % 64))
65 v |= (gprs[6] & mask) << 64
66 print("case_dsrd0", hex(mask), sh, hex(v))
67 e.intregs[3] = (v >> 64) % 2 ** 64
68 e.intregs[6] = v % 2 ** 64
69 self.add_case(prog, gprs, expected=e)
70
71
72 class SVP64BigIntCases(TestAccumulatorBase):
73 def case_sv_bigint_add(self):
74 """performs a carry-rollover-vector-add aka "big integer vector add"
75 this is remarkably simple, each sv.adde uses and produces a CA which
76 goes into the next sv.adde. arbitrary size is possible (1024+) as
77 is looping using the CA bit from one sv.adde on another batch to do
78 unlimited-size biginteger add.
79
80 r19/r18: 0x0000_0000_0000_0001 0xffff_ffff_ffff_ffff +
81 r21/r20: 0x8000_0000_0000_0000 0x0000_0000_0000_0001 =
82 r17/r16: 0x8000_0000_0000_0002 0x0000_0000_0000_0000
83 """
84 prog = Program(list(SVP64Asm(["sv.adde *16, *18, *20"])), False)
85 gprs = [0] * 32
86 gprs[18] = 0xffff_ffff_ffff_ffff
87 gprs[19] = 0x0000_0000_0000_0001
88 gprs[20] = 0x0000_0000_0000_0001
89 gprs[21] = 0x8000_0000_0000_0000
90 svstate = SVP64State()
91 svstate.vl = 2
92 svstate.maxvl = 2
93 e = ExpectedState(pc=8, int_regs=gprs)
94 e.intregs[16] = 0x0000_0000_0000_0000
95 e.intregs[17] = 0x8000_0000_0000_0002
96 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
97
98 def case_sv_bigint_shift_right_by_scalar(self):
99 """performs a bigint shift-right by scalar.
100
101 r5 starts off (as the carry-in) at 0x9000_0000_0000_0000
102
103 r18 r17 r16 r3
104 0x0000_0000_5000_0002 0x8000_8000_8000_8001 0xffff_ffff_ffff_ffff >> 4
105 0x0000_0000_0500_0000 0x2800_0800_0800_0800 0x1fff_ffff_ffff_ffff
106
107 with the 4-bit part that drops out of the 4 LSBs of r16 ending up
108 in r0
109 """
110 prog = Program(list(SVP64Asm(["sv.dsrd/mrr *16,*16,3,5"])), False)
111 gprs = [0] * 32
112 gprs[5] = 0x9000_0000_0000_0000
113 gprs[16] = 0xffff_ffff_ffff_ffff
114 gprs[17] = 0x8000_8000_8000_8001
115 gprs[18] = 0x0000_0000_5000_0002
116 gprs[3] = 4
117 svstate = SVP64State()
118 svstate.vl = 3
119 svstate.maxvl = 3
120 e = ExpectedState(pc=8, int_regs=gprs)
121 e.intregs[5] = 0xf000_0000_0000_0000 # remainder (shifted out of 16)
122 e.intregs[16] = 0x1fff_ffff_ffff_ffff
123 e.intregs[17] = 0x2800_0800_0800_0800
124 e.intregs[18] = 0x9000_0000_0500_0000 # initial r0 into top
125 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
126
127 def case_sv_bigint_shift_left_by_scalar(self):
128 """performs a bigint shift-left by scalar.
129
130 because the result is moved down by one register there is no need
131 for reverse-gear.
132
133 r5 starts off as the carry-in: 0x0000_0000_0000_000a
134
135 r18 r17 r16 r3
136 0x9000_0000_0001_0002 0x3fff_ffff_ffff_ffff 0x4000_0000_0000_0001 << 4
137 r18 r17 r16
138 0x0000_0000_0010_0023 0xffff_ffff_ffff_fff4 0x0000_0000_0000_0010
139
140 with the top 4 bits of r18 being pushed into the LSBs of r14
141 """
142 prog = Program(list(SVP64Asm(["sv.dsld *16,*16,3,5"])), False)
143 gprs = [0] * 32
144 gprs[5] = 0x0000_0000_0000_000a
145 gprs[16] = 0x4000_0000_0000_0001
146 gprs[17] = 0x3fff_ffff_ffff_ffff
147 gprs[18] = 0x9000_0000_0001_0002
148 gprs[3] = 4
149 svstate = SVP64State()
150 svstate.vl = 3
151 svstate.maxvl = 3
152 e = ExpectedState(pc=8, int_regs=gprs)
153 e.intregs[5] = 9
154 e.intregs[16] = 0x0000_0000_0000_001a
155 e.intregs[17] = 0xffff_ffff_ffff_fff4
156 e.intregs[18] = 0x0000_0000_0010_0023
157 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
158
159 def case_sv_bigint_shift_left_then_back(self):
160 """performs a bigint shift-right then a shift-left, should
161 get the same results... but doesn't. reason: the carry-in
162 compared to carry-out is shifted to the opposite end
163 """
164 prog = Program(list(SVP64Asm(["sv.dsrd/mrr *16,*16,3,5",
165 "sv.dsld *16,*16,3,5"])), False)
166 gprs = [0] * 32
167 gprs[5] = 0x0000_0000_0000_0009
168 gprs[16] = 0xffff_ffff_ffff_ffff
169 gprs[17] = 0x8000_8000_8000_8001
170 gprs[18] = 0x0000_0000_5000_0002
171 gprs[3] = 4
172 svstate = SVP64State()
173 svstate.vl = 3
174 svstate.maxvl = 3
175 e = ExpectedState(pc=8, int_regs=gprs)
176 e.intregs[5] = 0x0000_0000_0000_0000 # it's down the other end...
177 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
178
179 def case_sv_bigint_mul_by_scalar(self):
180 """performs a carry-rollover-vector-mul-with-add with a scalar,
181 using "RC" as a 64-bit carry in/out. matched with the
182 sv.divmod2du below
183
184 r18 r17 r16
185 0x1234_0000_5678_0000 0x9ABC_0000_DEF0_0000 0x1357_0000_9BDF_0000 *
186 r3 (scalar factor) 0x1_0001 +
187 r4 (carry in) 0xFEDC =
188 r18 r17 r16
189 0x1234_5678_5678_9ABC 0x9ABC_DEF0_DEF0_1357 0x1357_9BDF_9BDF_FEDC
190 r4 (carry out) 0x1234
191 """
192 prog = Program(list(SVP64Asm(["sv.maddedu *16,*16,3,4"])), False)
193 gprs = [0] * 32
194 gprs[16] = 0x1357_0000_9BDF_0000 # vector...
195 gprs[17] = 0x9ABC_0000_DEF0_0000 # ...
196 gprs[18] = 0x1234_0000_5678_0000 # ... input
197 gprs[3] = 0x1_0001 # scalar multiplier
198 gprs[4] = 0xFEDC # 64-bit carry-in
199 svstate = SVP64State()
200 svstate.vl = 3
201 svstate.maxvl = 3
202 e = ExpectedState(pc=8, int_regs=gprs)
203 e.intregs[16] = 0x1357_9BDF_9BDF_FEDC # vector...
204 e.intregs[17] = 0x9ABC_DEF0_DEF0_1357 # ...
205 e.intregs[18] = 0x1234_5678_5678_9ABC # ... result
206 e.intregs[4] = 0x1234 # 64-bit carry-out
207 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
208
209 def case_sv_bigint_scalar_maddedu(self):
210 prog = Program(list(SVP64Asm(["sv.maddedu 6,5,3,4"])), False)
211 gprs = [0] * 32
212 gprs[5] = 0x1357_0000_9BDF_0000 # scalar input
213 gprs[3] = 0x1_0001 # scalar multiplier
214 gprs[4] = 0xFEDC # 64-bit carry-in
215 svstate = SVP64State()
216 svstate.vl = 16 # detect writing to RT+MAXVL or RT+1 rather than RC
217 svstate.maxvl = 16
218 e = ExpectedState(pc=8, int_regs=gprs)
219 e.intregs[6] = 0x1357_9BDF_9BDF_FEDC # scalar output
220 e.intregs[4] = 0x1357 # 64-bit carry-out
221 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
222
223 def case_sv_bigint_div_by_scalar(self):
224 """performs a carry-rollover-vector-divmod with a scalar,
225 using "RC" as a 64-bit carry. matched with the sv.maddedu
226 above it is effectively the scalar-vector inverse
227
228 r18 r17 r16
229 0x1234_5678_5678_9ABC 0x9ABC_DEF0_DEF0_1357 0x1357_9BDF_9BDF_FEDC /
230 r3 (scalar factor) 0x1_0001 +
231 r4 (carry in at top-end) 0x1234 << 192 =
232 r18 r17 r16
233 0x1234_0000_5678_0000 0x9ABC_0000_DEF0_0000 0x1357_0000_9BDF_0000 *
234 r4 (carry out i.e. scalar remainder) 0xFEDC
235 """
236 prog = Program(list(SVP64Asm(["sv.divmod2du/mrr *16,*16,3,4"])), False)
237 gprs = [0] * 32
238 gprs[16] = 0x1357_9BDF_9BDF_FEDC # vector...
239 gprs[17] = 0x9ABC_DEF0_DEF0_1357 # ...
240 gprs[18] = 0x1234_5678_5678_9ABC # ... input
241 gprs[3] = 0x1_0001 # scalar multiplier
242 gprs[4] = 0x1234 # 64-bit carry-in
243 svstate = SVP64State()
244 svstate.vl = 3
245 svstate.maxvl = 3
246 e = ExpectedState(pc=8, int_regs=gprs)
247 e.intregs[16] = 0x1357_0000_9BDF_0000 # vector...
248 e.intregs[17] = 0x9ABC_0000_DEF0_0000 # ...
249 e.intregs[18] = 0x1234_0000_5678_0000 # ... result
250 e.intregs[4] = 0xFEDC # 64-bit carry-out
251 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)