2 from openpower
.test
.common
import TestAccumulatorBase
3 from openpower
.endian
import bigendian
4 from openpower
.simulator
.program
import Program
5 from openpower
.decoder
.selectable_int
import SelectableInt
6 from openpower
.decoder
.power_enums
import XER_bits
7 from openpower
.decoder
.isa
.caller
import special_sprs
8 from openpower
.decoder
.helpers
import exts
9 from openpower
.test
.state
import ExpectedState
13 class ALUTestCase(TestAccumulatorBase
):
15 def case_1_regression(self
):
16 lst
= [f
"add. 3, 1, 2"]
17 initial_regs
= [0] * 32
18 initial_regs
[1] = 0xc523e996a8ff6215
19 initial_regs
[2] = 0xe1e5b9cc9864c4a8
20 e
= ExpectedState(pc
=4)
21 e
.intregs
[1] = 0xc523e996a8ff6215
22 e
.intregs
[2] = 0xe1e5b9cc9864c4a8
23 e
.intregs
[3] = 0xa709a363416426bd
25 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
27 def case_2_regression(self
):
29 initial_regs
= [0] * 32
30 initial_regs
[1] = 0xb6a1fc6c8576af91
31 e
= ExpectedState(pc
=4)
32 e
.intregs
[1] = 0xb6a1fc6c8576af91
33 e
.intregs
[3] = 0xffffffff8576af91
34 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
36 lst
= [f
"subf 3, 1, 2"]
37 initial_regs
= [0] * 32
38 initial_regs
[1] = 0x3d7f3f7ca24bac7b
39 initial_regs
[2] = 0xf6b2ac5e13ee15c2
40 e
= ExpectedState(pc
=4)
41 e
.intregs
[1] = 0x3d7f3f7ca24bac7b
42 e
.intregs
[2] = 0xf6b2ac5e13ee15c2
43 e
.intregs
[3] = 0xb9336ce171a26947
44 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
46 lst
= [f
"subf 3, 1, 2"]
47 initial_regs
= [0] * 32
48 initial_regs
[1] = 0x833652d96c7c0058
49 initial_regs
[2] = 0x1c27ecff8a086c1a
50 e
= ExpectedState(pc
=4)
51 e
.intregs
[1] = 0x833652d96c7c0058
52 e
.intregs
[2] = 0x1c27ecff8a086c1a
53 e
.intregs
[3] = 0x98f19a261d8c6bc2
54 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
57 initial_regs
= [0] * 32
58 initial_regs
[1] = 0x7f9497aaff900ea0
59 e
= ExpectedState(pc
=4)
60 e
.intregs
[1] = 0x7f9497aaff900ea0
61 e
.intregs
[3] = 0xffffffffffffffa0
62 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
64 lst
= [f
"add 3, 1, 2"]
65 initial_regs
= [0] * 32
66 initial_regs
[1] = 0x2e08ae202742baf8
67 initial_regs
[2] = 0x86c43ece9efe5baa
68 e
= ExpectedState(pc
=4)
69 e
.intregs
[1] = 0x2e08ae202742baf8
70 e
.intregs
[2] = 0x86c43ece9efe5baa
71 e
.intregs
[3] = 0xb4cceceec64116a2
72 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
75 insns
= ["add", "add.", "subf"]
77 choice
= random
.choice(insns
)
78 lst
= [f
"{choice} 3, 1, 2"]
79 initial_regs
= [0] * 32
80 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
81 initial_regs
[2] = random
.randint(0, (1 << 64)-1)
83 e
= ExpectedState(pc
=4)
84 e
.intregs
[1] = initial_regs
[1]
85 e
.intregs
[2] = initial_regs
[2]
87 result
= initial_regs
[1] + initial_regs
[2]
88 e
.intregs
[3] = result
& ((2**64)-1)
89 elif choice
== "add.":
90 result
= initial_regs
[1] + initial_regs
[2]
91 e
.intregs
[3] = result
& ((2**64)-1)
95 if (e
.intregs
[3] & (1 << 63)) != 0:
97 elif e
.intregs
[3] == 0:
101 e
.crregs
[0] = (eq
<< 1) |
(gt
<< 2) |
(le
<< 3)
102 elif choice
== "subf":
103 result
= ~initial_regs
[1] + initial_regs
[2] + 1
104 e
.intregs
[3] = result
& ((2**64)-1)
106 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
108 def case_addme_ca_0(self
):
109 insns
= ["addme", "addme.", "addmeo", "addmeo."]
111 lst
= [f
"{choice} 6, 16"]
112 for value
in [0x7ffffffff,
114 initial_regs
= [0] * 32
115 initial_regs
[16] = value
117 xer
= SelectableInt(0, 64)
118 xer
[XER_bits
['CA']] = 0 # input carry is 0 (see test below)
119 initial_sprs
[special_sprs
['XER']] = xer
121 # create expected results. pc should be 4 (one instruction)
122 e
= ExpectedState(pc
=4)
123 # input value should not be modified
124 e
.intregs
[16] = value
125 # carry-out should always occur
127 # create output value
128 if value
== 0x7ffffffff:
129 e
.intregs
[6] = 0x7fffffffe
131 e
.intregs
[6] = 0xffff7ffff
132 # CR version needs an expected CR
135 self
.add_case(Program(lst
, bigendian
),
136 initial_regs
, initial_sprs
,
139 def case_addme_ca_1(self
):
140 insns
= ["addme", "addme.", "addmeo", "addmeo."]
142 lst
= [f
"{choice} 6, 16"]
143 for value
in [0x7ffffffff, # fails, bug #476
145 initial_regs
= [0] * 32
146 initial_regs
[16] = value
148 xer
= SelectableInt(0, 64)
149 # input carry is 1 (differs from above)
150 xer
[XER_bits
['CA']] = 1
151 initial_sprs
[special_sprs
['XER']] = xer
152 e
= ExpectedState(pc
=4)
153 e
.intregs
[16] = value
155 if value
== 0x7ffffffff:
156 e
.intregs
[6] = 0x7ffffffff
158 e
.intregs
[6] = 0xffff80000
161 self
.add_case(Program(lst
, bigendian
),
162 initial_regs
, initial_sprs
, expected
=e
)
164 def case_addme_ca_so_4(self
):
165 """test of SO being set
167 lst
= ["addmeo. 6, 16"]
168 initial_regs
= [0] * 32
169 initial_regs
[16] = 0x7fffffffffffffff
171 xer
= SelectableInt(0, 64)
172 xer
[XER_bits
['CA']] = 1
173 initial_sprs
[special_sprs
['XER']] = xer
174 e
= ExpectedState(pc
=4)
175 e
.intregs
[16] = 0x7fffffffffffffff
176 e
.intregs
[6] = 0x7fffffffffffffff
179 self
.add_case(Program(lst
, bigendian
),
180 initial_regs
, initial_sprs
, expected
=e
)
182 def case_addme_ca_so_3(self
):
183 """bug where SO does not get passed through to CR0
185 lst
= ["addme. 6, 16"]
186 initial_regs
= [0] * 32
187 initial_regs
[16] = 0x7ffffffff
189 xer
= SelectableInt(0, 64)
190 xer
[XER_bits
['CA']] = 1
191 xer
[XER_bits
['SO']] = 1
192 initial_sprs
[special_sprs
['XER']] = xer
193 e
= ExpectedState(pc
=4)
194 e
.intregs
[16] = 0x7ffffffff
195 e
.intregs
[6] = 0x7ffffffff
199 self
.add_case(Program(lst
, bigendian
),
200 initial_regs
, initial_sprs
, expected
=e
)
202 def case_addme_subfme_ca_propagation(self
):
203 for flags
in range(1 << 2):
205 is_sub
= (flags
>> 1) & 1
207 prog
= Program(["subfmeo 3, 4"], bigendian
)
209 prog
= Program(["addmeo 3, 4"], bigendian
)
210 for i
in range(-2, 3):
212 with self
.subTest(ra
=hex(ra
), ca
=ca
, is_sub
=is_sub
):
213 initial_regs
= [0] * 32
216 xer
= SelectableInt(0, 64)
217 xer
[XER_bits
['CA']] = ca
218 initial_sprs
[special_sprs
['XER']] = xer
219 e
= ExpectedState(pc
=4)
221 rb
= 2 ** 64 - 1 # add 0xfff...fff *not* -1
223 expected32
= ca
+ (rb
% 2 ** 32)
227 inv_ra
= ~ra
% 2 ** 64
229 expected32
+= inv_ra
% 2 ** 32
230 e
.intregs
[3] = expected
% 2 ** 64
231 ca
= bool(expected
>> 64)
232 ca32
= bool(expected32
>> 32)
233 e
.ca
= (ca32
<< 1) | ca
234 # use algorithm from microwatt's calc_ov
235 # https://github.com/antonblanchard/microwatt/blob/5c6d57de3056bd08fdc1f656bc8656635a77512b/execute1.vhdl#L284
237 emsb
= (expected
>> 63) & 1
238 ov
= ca ^ emsb
and not (axb
>> 63) & 1
239 e32msb
= (expected32
>> 31) & 1
240 ov32
= ca32 ^ e32msb
and not (axb
>> 31) & 1
241 e
.ov
= (ov32
<< 1) | ov
242 self
.add_case(prog
, initial_regs
, initial_sprs
,
245 def case_addze(self
):
246 insns
= ["addze", "addze.", "addzeo", "addzeo."]
248 lst
= [f
"{choice} 6, 16"]
249 initial_regs
= [0] * 32
250 initial_regs
[16] = 0x00ff00ff00ff0080
251 e
= ExpectedState(pc
=4)
252 e
.intregs
[16] = 0xff00ff00ff0080
253 e
.intregs
[6] = 0xff00ff00ff0080
256 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
258 def case_addis_nonzero_r0_regression(self
):
259 lst
= [f
"addis 3, 0, 1"]
261 initial_regs
= [0] * 32
263 e
= ExpectedState(initial_regs
, pc
=4)
264 e
.intregs
[3] = 0x10000
265 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
267 def case_addis_nonzero_r0(self
):
269 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
270 lst
= [f
"addis 3, 0, {imm}"]
272 initial_regs
= [0] * 32
273 initial_regs
[0] = random
.randint(0, (1 << 64)-1)
274 e
= ExpectedState(pc
=4)
275 e
.intregs
[0] = initial_regs
[0]
276 e
.intregs
[3] = (imm
<< 16) & ((1 << 64)-1)
277 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
279 def case_rand_imm(self
):
280 insns
= ["addi", "addis", "subfic"]
282 choice
= random
.choice(insns
)
283 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
284 lst
= [f
"{choice} 3, 1, {imm}"]
286 initial_regs
= [0] * 32
287 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
289 e
= ExpectedState(pc
=4)
290 e
.intregs
[1] = initial_regs
[1]
292 result
= initial_regs
[1] + imm
293 e
.intregs
[3] = result
& ((2**64)-1)
294 elif choice
== "addis":
295 result
= initial_regs
[1] + (imm
<< 16)
296 e
.intregs
[3] = result
& ((2**64)-1)
297 elif choice
== "subfic":
298 result
= ~initial_regs
[1] + imm
+ 1
299 value
= (~initial_regs
[1]+2**64) + (imm
) + 1
302 carry_out
= value
& (1 << 64) != 0
303 value
= (~initial_regs
[1]+2**64 & 0xffff_ffff) + imm
+ 1
306 carry_out32
= value
& (1 << 32) != 0
307 e
.intregs
[3] = result
& ((2**64)-1)
308 e
.ca
= carry_out |
(carry_out32
<< 1)
310 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
312 def case_0_adde(self
):
313 lst
= ["adde. 5, 6, 7"]
315 initial_regs
= [0] * 32
316 initial_regs
[6] = random
.randint(0, (1 << 64)-1)
317 initial_regs
[7] = random
.randint(0, (1 << 64)-1)
319 xer
= SelectableInt(0, 64)
320 xer
[XER_bits
['CA']] = 1
321 initial_sprs
[special_sprs
['XER']] = xer
322 # calculate result *including carry* and mask it to 64-bit
323 # (if it overflows, we don't care, because this is not addeo)
324 result
= 1 + initial_regs
[6] + initial_regs
[7]
325 # detect 65th bit as carry-out?
326 carry_out
= result
& (1 << 64) != 0
327 carry_out32
= (initial_regs
[6] & 0xffff_ffff) + \
328 (initial_regs
[7] & 0xffff_ffff) & (1 << 32) != 0
329 result
= result
& ((1 << 64)-1) # round
333 if (result
& (1 << 63)) != 0:
339 # now construct the state
340 e
= ExpectedState(pc
=4)
341 e
.intregs
[6] = initial_regs
[6] # should be same as initial
342 e
.intregs
[7] = initial_regs
[7] # should be same as initial
343 e
.intregs
[5] = result
344 # carry_out goes into bit 0 of ca, carry_out32 into bit 1
345 e
.ca
= carry_out |
(carry_out32
<< 1)
346 # eq goes into bit 1 of CR0, gt into bit 2, le into bit 3.
347 # SO goes into bit 0 but overflow doesn't occur here [we hope]
348 e
.crregs
[0] = (eq
<< 1) |
(gt
<< 2) |
(le
<< 3)
350 self
.add_case(Program(lst
, bigendian
),
351 initial_regs
, initial_sprs
, expected
=e
)
354 lst
= ["subf. 1, 6, 7",
356 initial_regs
= [0] * 32
357 initial_regs
[6] = 0x10
358 initial_regs
[7] = 0x05
359 e
= ExpectedState(pc
=8)
362 e
.intregs
[1] = 0xfffffffffffffff5
365 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
368 lst
= ["cmp cr2, 0, 2, 3"]
369 initial_regs
= [0] * 32
370 initial_regs
[2] = 0xffffffffaaaaaaaa
371 initial_regs
[3] = 0x00000000aaaaaaaa
372 e
= ExpectedState(pc
=4)
373 e
.intregs
[2] = 0xffffffffaaaaaaaa
374 e
.intregs
[3] = 0xaaaaaaaa
376 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
378 lst
= ["cmp cr2, 0, 4, 5"]
379 initial_regs
= [0] * 32
380 initial_regs
[4] = 0x00000000aaaaaaaa
381 initial_regs
[5] = 0xffffffffaaaaaaaa
382 e
= ExpectedState(pc
=4)
383 e
.intregs
[4] = 0xaaaaaaaa
384 e
.intregs
[5] = 0xffffffffaaaaaaaa
386 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
389 lst
= ["cmp cr2, 1, 2, 3"]
390 initial_regs
= [0] * 32
391 initial_regs
[2] = 0xffffffffaaaaaaaa
392 initial_regs
[3] = 0x00000000aaaaaaaa
393 e
= ExpectedState(pc
=4)
394 e
.intregs
[2] = 0xffffffffaaaaaaaa
395 e
.intregs
[3] = 0xaaaaaaaa
397 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
399 lst
= ["cmp cr2, 1, 4, 5"]
400 initial_regs
= [0] * 32
401 initial_regs
[4] = 0x00000000aaaaaaaa
402 initial_regs
[5] = 0xffffffffaaaaaaaa
403 e
= ExpectedState(pc
=4)
404 e
.intregs
[4] = 0xaaaaaaaa
405 e
.intregs
[5] = 0xffffffffaaaaaaaa
407 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
409 def case_cmpl_microwatt_0(self
):
411 115b8: 40 50 d1 7c .long 0x7cd15040 # cmpl 6, 0, 17, 10
412 register_file.vhdl: Reading GPR 11 000000000001C026
413 register_file.vhdl: Reading GPR 0A FEDF3FFF0001C025
414 cr_file.vhdl: Reading CR 35055050
415 cr_file.vhdl: Writing 35055058 to CR mask 01 35055058
418 lst
= ["cmpl 6, 0, 17, 10"]
419 initial_regs
= [0] * 32
420 initial_regs
[0x11] = 0x1c026
421 initial_regs
[0xa] = 0xFEDF3FFF0001C025
425 e
= ExpectedState(pc
=4)
426 e
.intregs
[10] = 0xfedf3fff0001c025
427 e
.intregs
[17] = 0x1c026
437 self
.add_case(Program(lst
, bigendian
), initial_regs
,
438 initial_sprs
={'XER': XER
},
439 initial_cr
=CR
, expected
=e
)
441 def case_cmpl_microwatt_0_disasm(self
):
442 """microwatt 1.bin: disassembled version
443 115b8: 40 50 d1 7c .long 0x7cd15040 # cmpl 6, 0, 17, 10
444 register_file.vhdl: Reading GPR 11 000000000001C026
445 register_file.vhdl: Reading GPR 0A FEDF3FFF0001C025
446 cr_file.vhdl: Reading CR 35055050
447 cr_file.vhdl: Writing 35055058 to CR mask 01 35055058
450 dis
= ["cmpl 6, 0, 17, 10"]
451 lst
= bytes([0x40, 0x50, 0xd1, 0x7c]) # 0x7cd15040
452 initial_regs
= [0] * 32
453 initial_regs
[0x11] = 0x1c026
454 initial_regs
[0xa] = 0xFEDF3FFF0001C025
458 e
= ExpectedState(pc
=4)
459 e
.intregs
[10] = 0xfedf3fff0001c025
460 e
.intregs
[17] = 0x1c026
470 p
= Program(lst
, bigendian
)
471 p
.assembly
= '\n'.join(dis
)+'\n'
472 self
.add_case(p
, initial_regs
,
473 initial_sprs
={'XER': XER
},
474 initial_cr
=CR
, expected
=e
)
476 def case_cmplw_microwatt_1(self
):
478 10d94: 40 20 96 7c cmplw cr1,r22,r4
479 gpr: 00000000ffff6dc1 <- r4
480 gpr: 0000000000000000 <- r22
483 lst
= ["cmpl 1, 0, 22, 4"]
484 initial_regs
= [0] * 32
485 initial_regs
[4] = 0xffff6dc1
490 e
= ExpectedState(pc
=4)
491 e
.intregs
[4] = 0xffff6dc1
504 self
.add_case(Program(lst
, bigendian
), initial_regs
,
505 initial_sprs
={'XER': XER
},
506 initial_cr
=CR
, expected
=e
)
508 def case_cmpli_microwatt(self
):
509 """microwatt 1.bin: cmpli
510 123ac: 9c 79 8d 2a cmpli cr5,0,r13,31132
511 gpr: 00000000301fc7a7 <- r13
512 cr : 0000000090215393
513 xer: so 1 ca 0 32 0 ov 0 32 0
517 lst
= ["cmpli 5, 0, 13, 31132"]
518 initial_regs
= [0] * 32
519 initial_regs
[13] = 0x301fc7a7
523 e
= ExpectedState(pc
=4)
524 e
.intregs
[13] = 0x301fc7a7
536 self
.add_case(Program(lst
, bigendian
), initial_regs
,
537 initial_sprs
={'XER': XER
},
538 initial_cr
=CR
, expected
=e
)
540 def case_extsb(self
):
541 insns
= ["extsb", "extsh", "extsw"]
543 choice
= random
.choice(insns
)
544 lst
= [f
"{choice} 3, 1"]
546 initial_regs
= [0] * 32
547 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
549 e
= ExpectedState(pc
=4)
550 e
.intregs
[1] = initial_regs
[1]
551 if choice
== "extsb":
552 e
.intregs
[3] = exts(initial_regs
[1], 8) & ((1 << 64)-1)
553 elif choice
== "extsh":
554 e
.intregs
[3] = exts(initial_regs
[1], 16) & ((1 << 64)-1)
556 e
.intregs
[3] = exts(initial_regs
[1], 32) & ((1 << 64)-1)
558 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)
560 def case_cmpeqb(self
):
561 lst
= ["cmpeqb cr1, 1, 2"]
563 initial_regs
= [0] * 32
565 initial_regs
[2] = 0x0001030507090b0f
567 e
= ExpectedState(pc
=4)
569 e
.intregs
[2] = 0x1030507090b0f
570 matlst
= [0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0f]
575 self
.add_case(Program(lst
, bigendian
), initial_regs
, expected
=e
)