6faba490c155db6874a73a444705b20e6612b1e5
[openpower-isa.git] / src / openpower / test / bitmanip / bitmanip_cases.py
1 from openpower.insndb.asm import SVP64Asm
2 from openpower.test.common import TestAccumulatorBase, skip_case
3 from openpower.endian import bigendian
4 from openpower.simulator.program import Program
5 from openpower.test.state import ExpectedState
6 from nmutil.sim_util import hash_256
7 from openpower.decoder.isa.caller import SVP64State, CRFields
8 from openpower.util import log
9 import struct
10 import itertools
11
12 def bmatflip(ra):
13 result = 0
14 for j in range(8):
15 for k in range(8):
16 b = (ra >> (63-k*8-j)) & 1
17 result |= b << (63-j*8-k)
18 return result
19
20
21 def crfbinlog(bf, bfa, bfb, mask):
22 lut = bfb
23 expected = bf&~mask # start at BF, mask overwrites masked bits only
24 checks = (bfa, bf) # LUT positions 1<<0=bfa 1<<1=bf
25 for i in range(4):
26 lut_index = 0
27 for j, check in enumerate(checks):
28 if check & (1<<i):
29 lut_index |= 1<<j
30 maskbit = (mask >> i) & 0b1
31 if (lut & (1<<lut_index)) and maskbit:
32 expected |= 1<<i
33 return expected
34
35
36 def ternlogi(rc, rt, ra, rb, imm):
37 expected = 0
38 for i in range(64):
39 lut_index = 0
40 if rb & 2 ** i:
41 lut_index |= 2 ** 0
42 if ra & 2 ** i:
43 lut_index |= 2 ** 1
44 if rt & 2 ** i:
45 lut_index |= 2 ** 2
46 if imm & 2 ** lut_index:
47 expected |= 2 ** i
48 return expected
49
50
51 def crternlogi(bt, ba, bb, imm):
52 expected = 0
53 checks = (bb, ba, bt) # LUT positions 1<<0=bb 1<<1=ba 1<<2=bt
54 lut_index = 0
55 for j, check in enumerate(checks):
56 if check & 1:
57 lut_index |= 1<<j
58 if imm & (1<<lut_index):
59 expected |= 1
60 return expected
61
62
63 def crfternlogi(bf, bfa, bfb, imm, mask):
64 expected = bf&~mask # start at BF, mask overwrites masked bits only
65 checks = (bfb, bfa, bf) # LUT positions 1<<0=bfb 1<<1=bfa 1<<2=bf
66 for i in range(4):
67 lut_index = 0
68 for j, check in enumerate(checks):
69 if check & (1<<i):
70 lut_index |= 1<<j
71 maskbit = (mask >> i) & 0b1
72 if (imm & (1<<lut_index)) and maskbit:
73 expected |= 1<<i
74 return expected
75
76
77 class BitManipTestCase(TestAccumulatorBase):
78 def case_gbbd(self):
79 lst = ["gbbd 0, 1"]
80 lst = list(SVP64Asm(lst, bigendian))
81 initial_regs = [0] * 32
82 initial_regs[1] = 0x9231_5897_2083_ffff
83 e = ExpectedState(pc=4)
84 e.intregs[0] = bmatflip(initial_regs[1])
85 e.intregs[1] = initial_regs[1]
86 log("case_gbbd", bin(initial_regs[1]), bin(e.intregs[0]))
87 log("hex", hex(initial_regs[1]), hex(e.intregs[0]))
88
89 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
90
91 def do_case_crternlogi(self, bt, ba, bb, imm):
92 lst = ["crternlogi 0,4,8,%d" % imm]
93 # set up CR to match bt bit 0, ba bit 4, bb bit 8, in MSB0 order
94 # bearing in mind that CRFields.cr is a 64-bit SelectableInt. sigh.
95 cr = CRFields()
96 cr.cr[32+0] = bt
97 cr.cr[32+4] = ba
98 cr.cr[32+8] = bb
99 initial_cr = cr.cr.asint()
100 print("initial cr", bin(initial_cr), bt, ba, bb,
101 "tli", bin(imm), lst)
102
103 lst = list(SVP64Asm(lst, bigendian))
104 e = ExpectedState(pc=4)
105 e.crregs[0] = crternlogi(bt, ba, bb, imm) << 3
106 e.crregs[1] = ba << 3
107 e.crregs[2] = bb << 3
108 self.add_case(Program(lst, bigendian), initial_regs=None, expected=e,
109 initial_cr=initial_cr)
110
111 def case_crternlogi_0(self):
112 self.do_case_crternlogi(0b1,
113 0b1,
114 0b1,
115 0x80)
116
117 def case_crternlogi_random(self):
118 for i in range(100):
119 imm = hash_256(f"crternlogi imm {i}") & 0xFF
120 bt = hash_256(f"crternlogi bt {i}") & 1
121 ba = hash_256(f"crternlogi ba {i}") & 1
122 bb = hash_256(f"crternlogi bb {i}") & 1
123 self.do_case_crternlogi(bt, ba, bb, imm)
124
125 def do_case_crfternlogi(self, bf, bfa, bfb, imm, mask):
126 lst = [f"crfternlogi 3,4,5,%d,%d" % (imm, mask)]
127 # set up CR
128 bf %= 2 ** 4
129 bfa %= 2 ** 4
130 bfb %= 2 ** 4
131 cr = CRFields()
132 cr.crl[3][0:4] = bf
133 cr.crl[4][0:4] = bfa
134 cr.crl[5][0:4] = bfb
135 initial_cr = cr.cr.asint()
136 print("initial cr", bin(initial_cr), bf, bfa, bfb)
137 print("mask tli", bin(mask), bin(imm))
138
139 lst = list(SVP64Asm(lst, bigendian))
140 e = ExpectedState(pc=4)
141 e.crregs[3] = crfternlogi(bf, bfa, bfb, imm, mask)
142 e.crregs[4] = bfa
143 e.crregs[5] = bfb
144 self.add_case(Program(lst, bigendian), initial_regs=None, expected=e,
145 initial_cr=initial_cr)
146
147 def case_crfternlogi_0(self):
148 self.do_case_crfternlogi(0b1111,
149 0b1100,
150 0b1010,
151 0x80, 0b1111)
152
153 def case_crfternlogi_random(self):
154 for i in range(100):
155 imm = hash_256(f"crfternlogi imm {i}") & 0xFF
156 bf = hash_256(f"crfternlogi bf {i}") % 2 ** 4
157 bfa = hash_256(f"crfternlogi bfa {i}") % 2 ** 4
158 bfb = hash_256(f"crfternlogi bfb {i}") % 2 ** 4
159 msk = hash_256(f"crfternlogi msk {i}") % 2 ** 4
160 self.do_case_crfternlogi(bf, bfa, bfb, imm, msk)
161
162 def do_case_crfbinlog(self, bf, bfa, bfb, mask):
163 lst = ["crfbinlog 3,4,5,%d" % mask]
164 # set up CR
165 bf %= 2 ** 4
166 bfa %= 2 ** 4
167 bfb %= 2 ** 4
168 cr = CRFields()
169 cr.crl[3][0:4] = bf
170 cr.crl[4][0:4] = bfa
171 cr.crl[5][0:4] = bfb
172 lut = bfb
173 initial_cr = cr.cr.asint()
174 print("initial cr", bin(initial_cr), bf, bfa, bfb)
175 print("mask lut2", bin(mask), bin(lut))
176
177 lst = list(SVP64Asm(lst, bigendian))
178 e = ExpectedState(pc=4)
179 e.crregs[3] = crfbinlog(bf, bfa, bfb, mask)
180 e.crregs[4] = bfa
181 e.crregs[5] = bfb
182 self.add_case(Program(lst, bigendian), initial_regs=None, expected=e,
183 initial_cr=initial_cr)
184
185 def case_crfbinlog_0(self):
186 self.do_case_crfbinlog(0b1111,
187 0b1100,
188 0x8, 0b1111)
189
190 def case_crfbinlog_random(self):
191 for i in range(100):
192 bf = hash_256(f"crfbinlog bf {i}") % 2 ** 4
193 bfa = hash_256(f"crfbinlog bfa {i}") % 2 ** 4
194 bfb = hash_256(f"crfbinlog bfb {i}") % 2 ** 4
195 msk = hash_256(f"crfbinlog msk {i}") % 2 ** 4
196 self.do_case_crfbinlog(bf, bfa, bfb, msk)
197
198 def do_case_ternlogi(self, rc, rt, ra, rb, imm):
199 rc_dot = "." if rc else ""
200 lst = [f"ternlogi{rc_dot} 3, 4, 5, {imm}"]
201 initial_regs = [0] * 32
202 rt %= 2 ** 64
203 ra %= 2 ** 64
204 rb %= 2 ** 64
205 initial_regs[3] = rt
206 initial_regs[4] = ra
207 initial_regs[5] = rb
208 lst = list(SVP64Asm(lst, bigendian))
209 e = ExpectedState(pc=4)
210 expected = 0
211 for i in range(64):
212 lut_index = 0
213 if rb & 2 ** i:
214 lut_index |= 2 ** 0
215 if ra & 2 ** i:
216 lut_index |= 2 ** 1
217 if rt & 2 ** i:
218 lut_index |= 2 ** 2
219 if imm & 2 ** lut_index:
220 expected |= 2 ** i
221 e.intregs[3] = expected
222 e.intregs[4] = ra
223 e.intregs[5] = rb
224 if rc:
225 if expected & 2 ** 63: # sign extend
226 expected -= 2 ** 64
227 eq = expected == 0
228 gt = expected > 0
229 lt = expected < 0
230 e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
231 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
232
233 def do_case_binlog(self, ra, rb, rc, nh):
234 lst = ["binlog 3, 4, 5, 6, %d" % nh]
235 initial_regs = [0] * 32
236 initial_regs[4] = ra
237 initial_regs[5] = rb
238 initial_regs[6] = rc
239 lut = rc & 0b11111111 # one of two 4-bit LUTs is in 1st 8 bits
240 if nh == 1: # top half (bits 4-7... sigh MSB 56-59) else 0-3 (60-63)
241 lut = lut >> 4
242 lut = lut & 0b1111
243 lst = list(SVP64Asm(lst, bigendian))
244 e = ExpectedState(pc=4)
245 expected = 0
246 for i in range(64):
247 lut_index = 0
248 if rb & 2 ** i:
249 lut_index |= 2 ** 0
250 if ra & 2 ** i:
251 lut_index |= 2 ** 1
252 if lut & 2 ** lut_index:
253 expected |= 2 ** i
254 e.intregs[3] = expected
255 e.intregs[4] = ra
256 e.intregs[5] = rb
257 e.intregs[6] = rc
258 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
259
260 def case_binlog_0(self):
261 self.do_case_binlog(0x8000_0000_FFFF_0000,
262 0x8000_0000_FF00_FF00,
263 0x8, 1)
264 self.do_case_binlog(0x8000_0000_FFFF_0000,
265 0x8000_0000_FF00_FF00,
266 0x8, 0)
267
268 def case_binlog_random(self):
269 for i in range(100):
270 ra = hash_256(f"binlog ra {i}") % 2 ** 64
271 rb = hash_256(f"binlog rb {i}") % 2 ** 64
272 rc = hash_256(f"binlog rc {i}") % 2 ** 8
273 nh = hash_256(f"binlog nh {i}") & 0b1
274 self.do_case_binlog(ra, rb, rc, nh)
275
276 def do_case_grev(self, w, is_imm, ra, rb):
277 bits = 32 if w else 64
278 masked_rb = rb % bits
279 if is_imm:
280 lst = [f"grev{'w' if w else ''}i. 3, 4, {masked_rb}"]
281 else:
282 lst = [f"grev{'w' if w else ''}. 3, 4, 5"]
283 initial_regs = [0] * 32
284 ra %= 2 ** 64
285 rb %= 2 ** 64
286 initial_regs[4] = ra
287 initial_regs[5] = rb
288 lst = list(SVP64Asm(lst, bigendian))
289 e = ExpectedState(pc=4)
290 expected = 0
291 for i in range(bits):
292 dest_bit = i ^ masked_rb
293 if ra & 2 ** i:
294 expected |= 2 ** dest_bit
295 e.intregs[3] = expected
296 e.intregs[4] = ra
297 e.intregs[5] = rb
298 if expected & 2 ** 63: # sign extend
299 expected -= 2 ** 64
300 eq = expected == 0
301 gt = expected > 0
302 lt = expected < 0
303 e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
304 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
305
306 def case_ternlogi_0(self):
307 self.do_case_ternlogi(False,
308 0x8000_0000_FFFF_0000,
309 0x8000_0000_FF00_FF00,
310 0x8000_0000_F0F0_F0F0, 0x80)
311 self.do_case_ternlogi(True,
312 0x8000_0000_FFFF_0000,
313 0x8000_0000_FF00_FF00,
314 0x8000_0000_F0F0_F0F0, 0x80)
315
316 def case_ternlogi_FF(self):
317 self.do_case_ternlogi(False, 0, 0, 0, 0xFF)
318 self.do_case_ternlogi(True, 0, 0, 0, 0xFF)
319
320 def case_ternlogi_random(self):
321 for i in range(100):
322 rc = bool(hash_256(f"ternlogi rc {i}") & 1)
323 imm = hash_256(f"ternlogi imm {i}") & 0xFF
324 rt = hash_256(f"ternlogi rt {i}") % 2 ** 64
325 ra = hash_256(f"ternlogi ra {i}") % 2 ** 64
326 rb = hash_256(f"ternlogi rb {i}") % 2 ** 64
327 self.do_case_ternlogi(rc, rt, ra, rb, imm)
328
329 @skip_case("grev removed -- leaving code for later use in grevlut")
330 def case_grev_random(self):
331 for i in range(100):
332 w = hash_256(f"grev w {i}") & 1
333 is_imm = hash_256(f"grev is_imm {i}") & 1
334 ra = hash_256(f"grev ra {i}") % 2 ** 64
335 rb = hash_256(f"grev rb {i}") % 2 ** 64
336 self.do_case_grev(w, is_imm, ra, rb)
337
338 @skip_case("grev removed -- leaving code for later use in grevlut")
339 def case_grevi_1(self):
340 self.do_case_grev(False, True, 14361919363078703450,
341 8396479064514513069)
342
343 @skip_case("grev removed -- leaving code for later use in grevlut")
344 def case_grevi_2(self):
345 self.do_case_grev(True, True, 397097147229333315, 8326716970539357702)
346
347 @skip_case("grev removed -- leaving code for later use in grevlut")
348 def case_grevi_3(self):
349 self.do_case_grev(True, True, 0xFFFF_FFFF_0000_0000, 6)
350
351 def case_byterev(self):
352 """ brh/brw/brd """
353 options = (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
354 values = (0x0123456789ABCDEF, 0xFEDCBA9876543210)
355 for RS, (pack_str, mnemonic) in itertools.product(values, options):
356 prog = Program(list(SVP64Asm(["%s 3,4" % mnemonic])), bigendian)
357 chunks = struct.unpack("<" + pack_str, struct.pack("<Q", RS))
358 res = struct.unpack("<Q", struct.pack(">" + pack_str, *chunks))[0]
359 with self.subTest(mnemonic=mnemonic, RS=hex(RS), expected=hex(res)):
360 gprs = [0] * 32
361 gprs[4] = RS
362 e = ExpectedState(pc=4, int_regs=gprs)
363 e.intregs[3] = res
364 self.add_case(prog, gprs, expected=e)
365
366 def case_sv_byterev(self):
367 """ sv.brh/brw/brd """
368 options = (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
369 values = range(10)
370 for idx, (pack_str, mnemonic) in itertools.product(values, options):
371 listing = list(SVP64Asm(["sv.%s *10,*20" % mnemonic]))
372 prog = Program(listing, bigendian)
373 VL = 5
374 svstate = SVP64State()
375 svstate.vl = VL
376 svstate.maxvl = VL
377 gprs = [0] * 128
378 for elidx in range(VL):
379 k = "sv.%s %d %d r20" % (mnemonic, idx, elidx)
380 gprs[20 + elidx] = hash_256(k) % 2**64
381 e = ExpectedState(pc=8, int_regs=gprs)
382 for elidx in range(VL):
383 packed = struct.pack("<Q", gprs[20 + elidx])
384 chunks = struct.unpack( "<" + pack_str, packed)
385 packed = struct.pack(">" + pack_str, *chunks)
386 res = struct.unpack("<Q", packed)[0]
387 e.intregs[10 + elidx] = res
388 RS = [hex(gprs[20 + i]) for i in range(VL)],
389 res =[hex(e.intregs[10 + i]) for i in range(VL)]
390 with self.subTest(case_idx=idx, RS_in=RS, expected_RA=res):
391 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
392
393 def do_case_sv_crternlogi(self, idx, bt, ba, bb, imm):
394 """note for now that this test is LIMITED due to the
395 range of CR EXTRA3 encoding, it can only do CR0 CR4 CR8 CR12 ... CR124
396 therefore BB is marked as *scalar*.
397 see https://bugs.libre-soc.org/show_bug.cgi?id=1034#c11
398 """
399 lst = ["sv.crternlogi *0,*16,31,%d" % imm]
400 # set up CR to match bt bit 0, ba bit 16, bb bit 31, in MSB0 order
401 # bearing in mind that CRFields.cr is a 64-bit SelectableInt. sigh.
402 cr = CRFields()
403 #for i, (t, a, b) in enumerate(zip(bt, ba, bb)):
404 for i, (t, a) in enumerate(zip(bt, ba)):
405 cr.cr[32+i+0] = t # *vector* BT
406 cr.cr[32+i+16] = a # *vector* BA
407 # XXX cannot do vector yet cr.cr[32+i+32] = bb # *SCALAR* BB
408 cr.cr[32+31] = bb # *SCALAR* BB
409 initial_cr = cr.cr.asint()
410 print("initial cr", bin(initial_cr), bt, ba, bb,
411 "tli", bin(imm), lst)
412
413 lst = list(SVP64Asm(lst, bigendian))
414 e = ExpectedState(pc=8)
415 #for i, (t, a, b) in enumerate(zip(bt, ba, bb)):
416 for i, (t, a) in enumerate(zip(bt, ba)):
417 k,j = i >> 2, (3 - (i % 4))
418 expected = crternlogi(t, a, bb, imm) << j
419 e.crregs[k+0] |= expected # vector result
420 e.crregs[k+4] |= a << j # vector input BA
421 e.crregs[7] |= bb << 3 # scalar input BB
422 with self.subTest(case_idx=idx):
423 VL = len(bt)
424 svstate = SVP64State()
425 svstate.vl = VL
426 svstate.maxvl = VL
427 self.add_case(Program(lst, bigendian), initial_regs=None,
428 expected=e,
429 initial_cr=initial_cr,
430 initial_svstate=svstate)
431
432 def case_sv_crternlogi(self):
433 for i in range(1):
434 bt, ba, bb = [], [], []
435 for j in range(2):
436 t = hash_256("crternlogi bt %d %d" % (i, j)) & 1
437 a = hash_256("crternlogi ba %d %d" % (i, j)) & 1
438 b = hash_256("crternlogi bb %d %d" % (i, j)) & 1
439 bt.append(t)
440 ba.append(a)
441 bb.append(b)
442 imm = hash_256("crternlogi imm %d" % (i)) & 0xFF
443 # temporarily do Vector BT, Vector BA, but *scalar* BB
444 self.do_case_sv_crternlogi(i, bt, ba, bb[0], imm)