2e79931f76b795304fa93d82fc345eaa587beafb
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
16 b
= (ra
>> (63-k
*8-j
)) & 1
17 result |
= b
<< (63-j
*8-k
)
21 def crfbinlog(bf
, bfa
, bfb
, mask
):
23 expected
= bf
&~mask
# start at BF, mask overwrites masked bits only
24 checks
= (bfa
, bf
) # LUT positions 1<<0=bfa 1<<1=bf
27 for j
, check
in enumerate(checks
):
30 maskbit
= (mask
>> i
) & 0b1
31 lut_index
= 3-lut_index
# MSB0 inversion
32 if (lut
& (1<<lut_index
)) and maskbit
:
37 def ternlogi(rc
, rt
, ra
, rb
, imm
):
47 if imm
& 2 ** lut_index
:
52 def crternlogi(bt
, ba
, bb
, imm
):
54 checks
= (bb
, ba
, bt
) # LUT positions 1<<0=bb 1<<1=ba 1<<2=bt
56 for j
, check
in enumerate(checks
):
59 lut_index
= 7-lut_index
# MSB0 inversion
60 if imm
& (1<<lut_index
):
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
70 for j
, check
in enumerate(checks
):
73 maskbit
= (mask
>> i
) & 0b1
74 lut_index
= 7-lut_index
# MSB0 inversion
75 if (imm
& (1<<lut_index
)) and maskbit
:
80 class BitManipTestCase(TestAccumulatorBase
):
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]))
92 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
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.
102 initial_cr
= cr
.cr
.asint()
103 print("initial cr", bin(initial_cr
), bt
, ba
, bb
,
104 "tli", bin(imm
), lst
)
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
)
114 def case_crternlogi_0(self
):
115 self
.do_case_crternlogi(0b1,
120 def case_crternlogi_random(self
):
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
)
128 def do_case_crfternlogi(self
, bf
, bfa
, bfb
, imm
, mask
):
129 lst
= [f
"crfternlogi 3,4,5,%d,%d" % (imm
, mask
)]
138 initial_cr
= cr
.cr
.asint()
139 print("initial cr", bin(initial_cr
), bf
, bfa
, bfb
)
140 print("mask tli", bin(mask
), bin(imm
))
142 lst
= list(SVP64Asm(lst
, bigendian
))
143 e
= ExpectedState(pc
=4)
144 e
.crregs
[3] = crfternlogi(bf
, bfa
, bfb
, imm
, mask
)
147 self
.add_case(Program(lst
, bigendian
), initial_regs
=None, expected
=e
,
148 initial_cr
=initial_cr
)
150 def case_crfternlogi_0(self
):
151 self
.do_case_crfternlogi(0b1111,
156 def case_crfternlogi_random(self
):
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
)
165 def do_case_crfbinlog(self
, bf
, bfa
, bfb
, mask
):
166 lst
= ["crfbinlog 3,4,5,%d" % mask
]
176 initial_cr
= cr
.cr
.asint()
177 print("initial cr", bin(initial_cr
), bf
, bfa
, bfb
)
178 print("mask lut2", bin(mask
), bin(lut
))
180 lst
= list(SVP64Asm(lst
, bigendian
))
181 e
= ExpectedState(pc
=4)
182 e
.crregs
[3] = crfbinlog(bf
, bfa
, bfb
, mask
)
185 self
.add_case(Program(lst
, bigendian
), initial_regs
=None, expected
=e
,
186 initial_cr
=initial_cr
)
188 def case_crfbinlog_0(self
):
189 self
.do_case_crfbinlog(0b1111,
193 def case_crfbinlog_random(self
):
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
)
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
211 lst
= list(SVP64Asm(lst
, bigendian
))
212 e
= ExpectedState(pc
=4)
222 lut_index
= 7-lut_index
# MSB0 inversion
223 if imm
& 2 ** lut_index
:
225 e
.intregs
[3] = expected
229 if expected
& 2 ** 63: # sign extend
234 e
.crregs
[0] = (eq
<< 1) |
(gt
<< 2) |
(lt
<< 3)
235 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
237 def do_case_binlog(self
, ra
, rb
, rc
, nh
):
238 lst
= ["binlog 3, 4, 5, 6, %d" % nh
]
239 initial_regs
= [0] * 32
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)
247 lst
= list(SVP64Asm(lst
, bigendian
))
248 e
= ExpectedState(pc
=4)
256 lut_index
= 3-lut_index
# MSB0 inversion
257 if lut
& 2 ** lut_index
:
259 e
.intregs
[3] = expected
263 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
265 def case_binlog_0(self
):
266 self
.do_case_binlog(0x8000_0000_FFFF_0000,
267 0x8000_0000_FF00_FF00,
269 self
.do_case_binlog(0x8000_0000_FFFF_0000,
270 0x8000_0000_FF00_FF00,
273 def case_binlog_random(self
):
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
)
281 def do_case_grev(self
, w
, is_imm
, ra
, rb
):
282 bits
= 32 if w
else 64
283 masked_rb
= rb
% bits
285 lst
= [f
"grev{'w' if w else ''}i. 3, 4, {masked_rb}"]
287 lst
= [f
"grev{'w' if w else ''}. 3, 4, 5"]
288 initial_regs
= [0] * 32
293 lst
= list(SVP64Asm(lst
, bigendian
))
294 e
= ExpectedState(pc
=4)
296 for i
in range(bits
):
297 dest_bit
= i ^ masked_rb
299 expected |
= 2 ** dest_bit
300 e
.intregs
[3] = expected
303 if expected
& 2 ** 63: # sign extend
308 e
.crregs
[0] = (eq
<< 1) |
(gt
<< 2) |
(lt
<< 3)
309 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
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)
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)
325 def case_ternlogi_random(self
):
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
)
334 @skip_case("grev removed -- leaving code for later use in grevlut")
335 def case_grev_random(self
):
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
)
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,
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)
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)
356 def case_byterev(self
):
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
)):
367 e
= ExpectedState(pc
=4, int_regs
=gprs
)
369 self
.add_case(prog
, gprs
, expected
=e
)
371 def case_sv_byterev(self
):
372 """ sv.brh/brw/brd """
373 options
= (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
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
)
379 svstate
= SVP64State()
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
)
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
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.
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
)
418 print("cr field %d" % i
, bin(cr
.crl
[i
].asint()))
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
):
435 svstate
= SVP64State()
438 self
.add_case(Program(lst
, bigendian
), initial_regs
=None,
440 initial_cr
=initial_cr
,
441 initial_svstate
=svstate
)
443 def case_sv_crternlogi_0(self
):
444 self
.do_case_sv_crternlogi(0, [1,1,1], [1,0,1], 1, 0x80)
446 def case_sv_crternlogi(self
):
448 bt
, ba
, bb
= [], [], []
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
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
)