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 crbinlog(bt
, ba
, bfb
):
24 checks
= (ba
, bt
) # LUT positions 1<<0=ba 1<<1=bt
26 for j
, check
in enumerate(checks
):
29 lut_index
= 3-lut_index
# MSB0 inversion
30 if lut
& (1<<lut_index
):
35 def crfbinlog(bf
, bfa
, bfb
, mask
):
37 expected
= bf
&~mask
# start at BF, mask overwrites masked bits only
38 checks
= (bfa
, bf
) # LUT positions 1<<0=bfa 1<<1=bf
41 for j
, check
in enumerate(checks
):
44 maskbit
= (mask
>> i
) & 0b1
45 lut_index
= 3-lut_index
# MSB0 inversion
46 if (lut
& (1<<lut_index
)) and maskbit
:
51 def ternlogi(rc
, rt
, ra
, rb
, imm
):
61 if imm
& 2 ** lut_index
:
66 def crternlogi(bt
, ba
, bb
, imm
):
68 checks
= (bb
, ba
, bt
) # LUT positions 1<<0=bb 1<<1=ba 1<<2=bt
70 for j
, check
in enumerate(checks
):
73 lut_index
= 7-lut_index
# MSB0 inversion
74 if imm
& (1<<lut_index
):
79 def crfternlogi(bf
, bfa
, bfb
, imm
, mask
):
80 expected
= bf
&~mask
# start at BF, mask overwrites masked bits only
81 checks
= (bfb
, bfa
, bf
) # LUT positions 1<<0=bfb 1<<1=bfa 1<<2=bf
84 for j
, check
in enumerate(checks
):
87 maskbit
= (mask
>> i
) & 0b1
88 lut_index
= 7-lut_index
# MSB0 inversion
89 if (imm
& (1<<lut_index
)) and maskbit
:
94 class BitManipTestCase(TestAccumulatorBase
):
97 lst
= list(SVP64Asm(lst
, bigendian
))
98 initial_regs
= [0] * 32
99 initial_regs
[1] = 0x9231_5897_2083_ffff
100 e
= ExpectedState(pc
=4)
101 e
.intregs
[0] = bmatflip(initial_regs
[1])
102 e
.intregs
[1] = initial_regs
[1]
103 log("case_gbbd", bin(initial_regs
[1]), bin(e
.intregs
[0]))
104 log("hex", hex(initial_regs
[1]), hex(e
.intregs
[0]))
106 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
108 def do_case_crternlogi(self
, bt
, ba
, bb
, imm
):
109 lst
= ["crternlogi 0,4,8,%d" % imm
]
110 # set up CR to match bt bit 0, ba bit 4, bb bit 8, in MSB0 order
111 # bearing in mind that CRFields.cr is a 64-bit SelectableInt. sigh.
116 initial_cr
= cr
.cr
.asint()
117 print("initial cr", bin(initial_cr
), bt
, ba
, bb
,
118 "tli", bin(imm
), lst
)
120 lst
= list(SVP64Asm(lst
, bigendian
))
121 e
= ExpectedState(pc
=4)
122 e
.crregs
[0] = crternlogi(bt
, ba
, bb
, imm
) << 3
123 e
.crregs
[1] = ba
<< 3
124 e
.crregs
[2] = bb
<< 3
125 self
.add_case(Program(lst
, bigendian
), initial_regs
=None, expected
=e
,
126 initial_cr
=initial_cr
)
128 def case_crternlogi_0(self
):
129 self
.do_case_crternlogi(0b1,
134 def case_crternlogi_random(self
):
136 imm
= hash_256(f
"crternlogi imm {i}") & 0xFF
137 bt
= hash_256(f
"crternlogi bt {i}") & 1
138 ba
= hash_256(f
"crternlogi ba {i}") & 1
139 bb
= hash_256(f
"crternlogi bb {i}") & 1
140 self
.do_case_crternlogi(bt
, ba
, bb
, imm
)
142 def do_case_crfternlogi(self
, bf
, bfa
, bfb
, imm
, mask
):
143 lst
= [f
"crfternlogi 3,4,5,%d,%d" % (imm
, mask
)]
152 initial_cr
= cr
.cr
.asint()
153 print("initial cr", bin(initial_cr
), bf
, bfa
, bfb
)
154 print("mask tli", bin(mask
), bin(imm
))
156 lst
= list(SVP64Asm(lst
, bigendian
))
157 e
= ExpectedState(pc
=4)
158 e
.crregs
[3] = crfternlogi(bf
, bfa
, bfb
, imm
, mask
)
161 self
.add_case(Program(lst
, bigendian
), initial_regs
=None, expected
=e
,
162 initial_cr
=initial_cr
)
164 def case_crfternlogi_0(self
):
165 self
.do_case_crfternlogi(0b1111,
170 def case_crfternlogi_random(self
):
172 imm
= hash_256(f
"crfternlogi imm {i}") & 0xFF
173 bf
= hash_256(f
"crfternlogi bf {i}") % 2 ** 4
174 bfa
= hash_256(f
"crfternlogi bfa {i}") % 2 ** 4
175 bfb
= hash_256(f
"crfternlogi bfb {i}") % 2 ** 4
176 msk
= hash_256(f
"crfternlogi msk {i}") % 2 ** 4
177 self
.do_case_crfternlogi(bf
, bfa
, bfb
, imm
, msk
)
179 def do_case_crbinlog(self
, bt
, ba
, bfb
):
180 lst
= ["crbinlog 4,8,0"]
183 cr
.cr
[32+4] = bt
# BT bit
184 cr
.cr
[32+8] = ba
# BA bit
185 cr
.crl
[0][0:4] = bfb
# BFB *field*
187 initial_cr
= cr
.cr
.asint()
188 print("initial cr", bin(initial_cr
), bt
, ba
, bfb
)
190 lst
= list(SVP64Asm(lst
, bigendian
))
191 e
= ExpectedState(pc
=4)
192 e
.crregs
[1] = crbinlog(bt
, ba
, bfb
) << 3 # overwrites BT
193 e
.crregs
[2] = ba
<< 3
195 self
.add_case(Program(lst
, bigendian
), initial_regs
=None, expected
=e
,
196 initial_cr
=initial_cr
)
198 def case_crbinlog_0(self
):
199 self
.do_case_crbinlog(0b1,
203 def case_crbinlog_random(self
):
205 bt
= hash_256(f
"crbinlog bt {i}") % 2
206 ba
= hash_256(f
"crbinlog ba {i}") % 2
207 bfb
= hash_256(f
"crbinlog bfb {i}") % 2 ** 4
208 self
.do_case_crbinlog(bt
, ba
, bfb
)
210 def do_case_crfbinlog(self
, bf
, bfa
, bfb
, mask
):
211 lst
= ["crfbinlog 3,4,5,%d" % mask
]
221 initial_cr
= cr
.cr
.asint()
222 print("initial cr", bin(initial_cr
), bf
, bfa
, bfb
)
223 print("mask lut2", bin(mask
), bin(lut
))
225 lst
= list(SVP64Asm(lst
, bigendian
))
226 e
= ExpectedState(pc
=4)
227 e
.crregs
[3] = crfbinlog(bf
, bfa
, bfb
, mask
)
230 self
.add_case(Program(lst
, bigendian
), initial_regs
=None, expected
=e
,
231 initial_cr
=initial_cr
)
233 def case_crfbinlog_0(self
):
234 self
.do_case_crfbinlog(0b1111,
238 def case_crfbinlog_random(self
):
240 bf
= hash_256(f
"crfbinlog bf {i}") % 2 ** 4
241 bfa
= hash_256(f
"crfbinlog bfa {i}") % 2 ** 4
242 bfb
= hash_256(f
"crfbinlog bfb {i}") % 2 ** 4
243 msk
= hash_256(f
"crfbinlog msk {i}") % 2 ** 4
244 self
.do_case_crfbinlog(bf
, bfa
, bfb
, msk
)
246 def do_case_ternlogi(self
, rc
, rt
, ra
, rb
, imm
):
247 rc_dot
= "." if rc
else ""
248 lst
= [f
"ternlogi{rc_dot} 3, 4, 5, {imm}"]
249 initial_regs
= [0] * 32
256 lst
= list(SVP64Asm(lst
, bigendian
))
257 e
= ExpectedState(pc
=4)
267 lut_index
= 7-lut_index
# MSB0 inversion
268 if imm
& 2 ** lut_index
:
270 e
.intregs
[3] = expected
274 if expected
& 2 ** 63: # sign extend
279 e
.crregs
[0] = (eq
<< 1) |
(gt
<< 2) |
(lt
<< 3)
280 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
282 def do_case_binlog(self
, ra
, rb
, rc
, nh
):
283 lst
= ["binlog 3, 4, 5, 6, %d" % nh
]
284 initial_regs
= [0] * 32
288 lut
= rc
& 0b11111111 # one of two 4-bit LUTs is in 1st 8 bits
289 if nh
== 1: # top half (bits 4-7... sigh MSB 56-59) else 0-3 (60-63)
292 lst
= list(SVP64Asm(lst
, bigendian
))
293 e
= ExpectedState(pc
=4)
301 lut_index
= 3-lut_index
# MSB0 inversion
302 if lut
& 2 ** lut_index
:
304 e
.intregs
[3] = expected
308 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
310 def case_binlog_0(self
):
311 self
.do_case_binlog(0x8000_0000_FFFF_0000,
312 0x8000_0000_FF00_FF00,
314 self
.do_case_binlog(0x8000_0000_FFFF_0000,
315 0x8000_0000_FF00_FF00,
318 def case_binlog_random(self
):
320 ra
= hash_256(f
"binlog ra {i}") % 2 ** 64
321 rb
= hash_256(f
"binlog rb {i}") % 2 ** 64
322 rc
= hash_256(f
"binlog rc {i}") % 2 ** 8
323 nh
= hash_256(f
"binlog nh {i}") & 0b1
324 self
.do_case_binlog(ra
, rb
, rc
, nh
)
326 def do_case_grev(self
, w
, is_imm
, ra
, rb
):
327 bits
= 32 if w
else 64
328 masked_rb
= rb
% bits
330 lst
= [f
"grev{'w' if w else ''}i. 3, 4, {masked_rb}"]
332 lst
= [f
"grev{'w' if w else ''}. 3, 4, 5"]
333 initial_regs
= [0] * 32
338 lst
= list(SVP64Asm(lst
, bigendian
))
339 e
= ExpectedState(pc
=4)
341 for i
in range(bits
):
342 dest_bit
= i ^ masked_rb
344 expected |
= 2 ** dest_bit
345 e
.intregs
[3] = expected
348 if expected
& 2 ** 63: # sign extend
353 e
.crregs
[0] = (eq
<< 1) |
(gt
<< 2) |
(lt
<< 3)
354 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
356 def case_ternlogi_0(self
):
357 self
.do_case_ternlogi(False,
358 0x8000_0000_FFFF_0000,
359 0x8000_0000_FF00_FF00,
360 0x8000_0000_F0F0_F0F0, 0x80)
361 self
.do_case_ternlogi(True,
362 0x8000_0000_FFFF_0000,
363 0x8000_0000_FF00_FF00,
364 0x8000_0000_F0F0_F0F0, 0x80)
366 def case_ternlogi_FF(self
):
367 self
.do_case_ternlogi(False, 0, 0, 0, 0xFF)
368 self
.do_case_ternlogi(True, 0, 0, 0, 0xFF)
370 def case_ternlogi_random(self
):
372 rc
= bool(hash_256(f
"ternlogi rc {i}") & 1)
373 imm
= hash_256(f
"ternlogi imm {i}") & 0xFF
374 rt
= hash_256(f
"ternlogi rt {i}") % 2 ** 64
375 ra
= hash_256(f
"ternlogi ra {i}") % 2 ** 64
376 rb
= hash_256(f
"ternlogi rb {i}") % 2 ** 64
377 self
.do_case_ternlogi(rc
, rt
, ra
, rb
, imm
)
379 @skip_case("grev removed -- leaving code for later use in grevlut")
380 def case_grev_random(self
):
382 w
= hash_256(f
"grev w {i}") & 1
383 is_imm
= hash_256(f
"grev is_imm {i}") & 1
384 ra
= hash_256(f
"grev ra {i}") % 2 ** 64
385 rb
= hash_256(f
"grev rb {i}") % 2 ** 64
386 self
.do_case_grev(w
, is_imm
, ra
, rb
)
388 @skip_case("grev removed -- leaving code for later use in grevlut")
389 def case_grevi_1(self
):
390 self
.do_case_grev(False, True, 14361919363078703450,
393 @skip_case("grev removed -- leaving code for later use in grevlut")
394 def case_grevi_2(self
):
395 self
.do_case_grev(True, True, 397097147229333315, 8326716970539357702)
397 @skip_case("grev removed -- leaving code for later use in grevlut")
398 def case_grevi_3(self
):
399 self
.do_case_grev(True, True, 0xFFFF_FFFF_0000_0000, 6)
401 def case_byterev(self
):
403 options
= (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
404 values
= (0x0123456789ABCDEF, 0xFEDCBA9876543210)
405 for RS
, (pack_str
, mnemonic
) in itertools
.product(values
, options
):
406 prog
= Program(list(SVP64Asm(["%s 3,4" % mnemonic
])), bigendian
)
407 chunks
= struct
.unpack("<" + pack_str
, struct
.pack("<Q", RS
))
408 res
= struct
.unpack("<Q", struct
.pack(">" + pack_str
, *chunks
))[0]
409 with self
.subTest(mnemonic
=mnemonic
, RS
=hex(RS
), expected
=hex(res
)):
412 e
= ExpectedState(pc
=4, int_regs
=gprs
)
414 self
.add_case(prog
, gprs
, expected
=e
)
416 def case_sv_byterev(self
):
417 """ sv.brh/brw/brd """
418 options
= (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
420 for idx
, (pack_str
, mnemonic
) in itertools
.product(values
, options
):
421 listing
= list(SVP64Asm(["sv.%s *10,*20" % mnemonic
]))
422 prog
= Program(listing
, bigendian
)
424 svstate
= SVP64State()
428 for elidx
in range(VL
):
429 k
= "sv.%s %d %d r20" % (mnemonic
, idx
, elidx
)
430 gprs
[20 + elidx
] = hash_256(k
) % 2**64
431 e
= ExpectedState(pc
=8, int_regs
=gprs
)
432 for elidx
in range(VL
):
433 packed
= struct
.pack("<Q", gprs
[20 + elidx
])
434 chunks
= struct
.unpack( "<" + pack_str
, packed
)
435 packed
= struct
.pack(">" + pack_str
, *chunks
)
436 res
= struct
.unpack("<Q", packed
)[0]
437 e
.intregs
[10 + elidx
] = res
438 RS
= [hex(gprs
[20 + i
]) for i
in range(VL
)],
439 res
=[hex(e
.intregs
[10 + i
]) for i
in range(VL
)]
440 with self
.subTest(case_idx
=idx
, RS_in
=RS
, expected_RA
=res
):
441 self
.add_case(prog
, gprs
, expected
=e
, initial_svstate
=svstate
)
443 def do_case_sv_crternlogi(self
, idx
, bt
, ba
, bb
, imm
):
444 """note for now that this test is LIMITED due to the
445 range of CR EXTRA3 encoding, it can only do CR0 CR4 CR8 CR12 ... CR124
446 therefore BB is marked as *scalar*.
447 see https://bugs.libre-soc.org/show_bug.cgi?id=1034#c11
449 lst
= ["sv.crternlogi *0,*16,31,%d" % imm
]
450 # set up CR to match bt bit 0, ba bit 16, bb bit 31, in MSB0 order
451 # bearing in mind that CRFields.cr is a 64-bit SelectableInt. sigh.
453 #for i, (t, a, b) in enumerate(zip(bt, ba, bb)):
454 for i
, (t
, a
) in enumerate(zip(bt
, ba
)):
455 cr
.cr
[32+i
*4+0] = t
# *vector* BT
456 cr
.cr
[32+i
*4+16] = a
# *vector* BA
457 # XXX cannot do vector yet cr.cr[32+i+32] = bb # *SCALAR* BB
458 cr
.cr
[32+31] = bb
# *SCALAR* BB
459 initial_cr
= cr
.cr
.asint()
460 print("initial cr", bin(initial_cr
), bt
, ba
, bb
,
461 "tli", bin(imm
), lst
)
463 print("cr field %d" % i
, bin(cr
.crl
[i
].asint()))
465 lst
= list(SVP64Asm(lst
, bigendian
))
466 e
= ExpectedState(pc
=8)
467 #for i, (t, a, b) in enumerate(zip(bt, ba, bb)):
468 # ok so remember that you have to do MSB0-to-LSB0 conversion
469 # so subtract 3-0 for vector BT=*0 and BA=*16 (hence n<<3) but 3-3
470 # (hence bb<<0) for BB=31 (the scalar BB)
471 for i
, (t
, a
) in enumerate(zip(bt
, ba
)):
472 expected
= crternlogi(t
, a
, bb
, imm
)
473 print("crternlogi expected", i
, bin(expected
))
474 e
.crregs
[i
+0] &= ~
1<<3 # clear vector result bit first
475 e
.crregs
[i
+0] |
= expected
<<3 # vector result
476 e
.crregs
[i
+4] |
= a
<<3 # vector input BA
477 e
.crregs
[7] |
= bb
<<0 # scalar input BB
478 with self
.subTest(case_idx
=idx
):
480 svstate
= SVP64State()
483 self
.add_case(Program(lst
, bigendian
), initial_regs
=None,
485 initial_cr
=initial_cr
,
486 initial_svstate
=svstate
)
488 def case_sv_crternlogi_0(self
):
489 self
.do_case_sv_crternlogi(0, [1,1,1], [1,0,1], 1, 0x80)
491 def case_sv_crternlogi(self
):
493 bt
, ba
, bb
= [], [], []
495 t
= hash_256("crternlogi bt %d %d" % (i
, j
)) & 1
496 a
= hash_256("crternlogi ba %d %d" % (i
, j
)) & 1
497 b
= hash_256("crternlogi bb %d %d" % (i
, j
)) & 1
501 imm
= hash_256("crternlogi imm %d" % (i
)) & 0xFF
502 # temporarily do Vector BT, Vector BA, but *scalar* BB
503 self
.do_case_sv_crternlogi(i
, bt
, ba
, bb
[0], imm
)