931ba7fba928aa904b64e5d9a3bca803bff0891b
[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)