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