speed up divmod shift-sub tests by removing most test cases
[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
8 import struct
9 import itertools
10
11
12 class BitManipTestCase(TestAccumulatorBase):
13 def do_case_ternlogi(self, rc, rt, ra, rb, imm):
14 rc_dot = "." if rc else ""
15 lst = [f"ternlogi{rc_dot} 3, 4, 5, {imm}"]
16 initial_regs = [0] * 32
17 rt %= 2 ** 64
18 ra %= 2 ** 64
19 rb %= 2 ** 64
20 initial_regs[3] = rt
21 initial_regs[4] = ra
22 initial_regs[5] = rb
23 lst = list(SVP64Asm(lst, bigendian))
24 e = ExpectedState(pc=4)
25 expected = 0
26 for i in range(64):
27 lut_index = 0
28 if rb & 2 ** i:
29 lut_index |= 2 ** 0
30 if ra & 2 ** i:
31 lut_index |= 2 ** 1
32 if rt & 2 ** i:
33 lut_index |= 2 ** 2
34 if imm & 2 ** lut_index:
35 expected |= 2 ** i
36 e.intregs[3] = expected
37 e.intregs[4] = ra
38 e.intregs[5] = rb
39 if rc:
40 if expected & 2 ** 63: # sign extend
41 expected -= 2 ** 64
42 eq = expected == 0
43 gt = expected > 0
44 lt = expected < 0
45 e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
46 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
47
48 def do_case_grev(self, w, is_imm, ra, rb):
49 bits = 32 if w else 64
50 masked_rb = rb % bits
51 if is_imm:
52 lst = [f"grev{'w' if w else ''}i. 3, 4, {masked_rb}"]
53 else:
54 lst = [f"grev{'w' if w else ''}. 3, 4, 5"]
55 initial_regs = [0] * 32
56 ra %= 2 ** 64
57 rb %= 2 ** 64
58 initial_regs[4] = ra
59 initial_regs[5] = rb
60 lst = list(SVP64Asm(lst, bigendian))
61 e = ExpectedState(pc=4)
62 expected = 0
63 for i in range(bits):
64 dest_bit = i ^ masked_rb
65 if ra & 2 ** i:
66 expected |= 2 ** dest_bit
67 e.intregs[3] = expected
68 e.intregs[4] = ra
69 e.intregs[5] = rb
70 if expected & 2 ** 63: # sign extend
71 expected -= 2 ** 64
72 eq = expected == 0
73 gt = expected > 0
74 lt = expected < 0
75 e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
76 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
77
78 def case_ternlogi_0(self):
79 self.do_case_ternlogi(False,
80 0x8000_0000_FFFF_0000,
81 0x8000_0000_FF00_FF00,
82 0x8000_0000_F0F0_F0F0, 0x80)
83 self.do_case_ternlogi(True,
84 0x8000_0000_FFFF_0000,
85 0x8000_0000_FF00_FF00,
86 0x8000_0000_F0F0_F0F0, 0x80)
87
88 def case_ternlogi_FF(self):
89 self.do_case_ternlogi(False, 0, 0, 0, 0xFF)
90 self.do_case_ternlogi(True, 0, 0, 0, 0xFF)
91
92 def case_ternlogi_random(self):
93 for i in range(100):
94 rc = bool(hash_256(f"ternlogi rc {i}") & 1)
95 imm = hash_256(f"ternlogi imm {i}") & 0xFF
96 rt = hash_256(f"ternlogi rt {i}") % 2 ** 64
97 ra = hash_256(f"ternlogi ra {i}") % 2 ** 64
98 rb = hash_256(f"ternlogi rb {i}") % 2 ** 64
99 self.do_case_ternlogi(rc, rt, ra, rb, imm)
100
101 @skip_case("grev removed -- leaving code for later use in grevlut")
102 def case_grev_random(self):
103 for i in range(100):
104 w = hash_256(f"grev w {i}") & 1
105 is_imm = hash_256(f"grev is_imm {i}") & 1
106 ra = hash_256(f"grev ra {i}") % 2 ** 64
107 rb = hash_256(f"grev rb {i}") % 2 ** 64
108 self.do_case_grev(w, is_imm, ra, rb)
109
110 @skip_case("grev removed -- leaving code for later use in grevlut")
111 def case_grevi_1(self):
112 self.do_case_grev(False, True, 14361919363078703450,
113 8396479064514513069)
114
115 @skip_case("grev removed -- leaving code for later use in grevlut")
116 def case_grevi_2(self):
117 self.do_case_grev(True, True, 397097147229333315, 8326716970539357702)
118
119 @skip_case("grev removed -- leaving code for later use in grevlut")
120 def case_grevi_3(self):
121 self.do_case_grev(True, True, 0xFFFF_FFFF_0000_0000, 6)
122
123 def case_byterev(self):
124 """ brh/brw/brd """
125 options = (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
126 values = (0x0123456789ABCDEF, 0xFEDCBA9876543210)
127 for RS, (pack_str, mnemonic) in itertools.product(values, options):
128 prog = Program(list(SVP64Asm(["%s 3,4" % mnemonic])), bigendian)
129 chunks = struct.unpack("<" + pack_str, struct.pack("<Q", RS))
130 res = struct.unpack("<Q", struct.pack(">" + pack_str, *chunks))[0]
131 with self.subTest(mnemonic=mnemonic, RS=hex(RS), expected=hex(res)):
132 gprs = [0] * 32
133 gprs[4] = RS
134 e = ExpectedState(pc=4, int_regs=gprs)
135 e.intregs[3] = res
136 self.add_case(prog, gprs, expected=e)
137
138 def case_sv_byterev(self):
139 """ sv.brh/brw/brd """
140 options = (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
141 values = range(10)
142 for idx, (pack_str, mnemonic) in itertools.product(values, options):
143 listing = list(SVP64Asm(["sv.%s *10,*20" % mnemonic]))
144 prog = Program(listing, bigendian)
145 VL = 5
146 svstate = SVP64State()
147 svstate.vl = VL
148 svstate.maxvl = VL
149 gprs = [0] * 128
150 for elidx in range(VL):
151 k = "sv.%s %d %d r20" % (mnemonic, idx, elidx)
152 gprs[20 + elidx] = hash_256(k) % 2**64
153 e = ExpectedState(pc=8, int_regs=gprs)
154 for elidx in range(VL):
155 packed = struct.pack("<Q", gprs[20 + elidx])
156 chunks = struct.unpack( "<" + pack_str, packed)
157 packed = struct.pack(">" + pack_str, *chunks)
158 res = struct.unpack("<Q", packed)[0]
159 e.intregs[10 + elidx] = res
160 RS = [hex(gprs[20 + i]) for i in range(VL)],
161 res =[hex(e.intregs[10 + i]) for i in range(VL)]
162 with self.subTest(case_idx=idx, RS_in=RS, expected_RA=res):
163 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)