add tests for carry/overflow calculation of addmeo/subfmeo
[openpower-isa.git] / src / openpower / test / alu / alu_cases.py
1 import random
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
10 import unittest
11
12
13 class ALUTestCase(TestAccumulatorBase):
14
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
24 e.crregs[0] = 0x8
25 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
26
27 def case_2_regression(self):
28 lst = [f"extsw 3, 1"]
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)
35
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)
45
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)
55
56 lst = [f"extsb 3, 1"]
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)
63
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)
73
74 def case_rand(self):
75 insns = ["add", "add.", "subf"]
76 for i in range(40):
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)
82
83 e = ExpectedState(pc=4)
84 e.intregs[1] = initial_regs[1]
85 e.intregs[2] = initial_regs[2]
86 if choice == "add":
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)
92 eq = 0
93 gt = 0
94 le = 0
95 if (e.intregs[3] & (1 << 63)) != 0:
96 le = 1
97 elif e.intregs[3] == 0:
98 eq = 1
99 else:
100 gt = 1
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)
105
106 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
107
108 def case_addme_ca_0(self):
109 insns = ["addme", "addme.", "addmeo", "addmeo."]
110 for choice in insns:
111 lst = [f"{choice} 6, 16"]
112 for value in [0x7ffffffff,
113 0xffff80000]:
114 initial_regs = [0] * 32
115 initial_regs[16] = value
116 initial_sprs = {}
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
120
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
126 e.ca = 0x3
127 # create output value
128 if value == 0x7ffffffff:
129 e.intregs[6] = 0x7fffffffe
130 else:
131 e.intregs[6] = 0xffff7ffff
132 # CR version needs an expected CR
133 if '.' in choice:
134 e.crregs[0] = 0x4
135 self.add_case(Program(lst, bigendian),
136 initial_regs, initial_sprs,
137 expected=e)
138
139 def case_addme_ca_1(self):
140 insns = ["addme", "addme.", "addmeo", "addmeo."]
141 for choice in insns:
142 lst = [f"{choice} 6, 16"]
143 for value in [0x7ffffffff, # fails, bug #476
144 0xffff80000]:
145 initial_regs = [0] * 32
146 initial_regs[16] = value
147 initial_sprs = {}
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
154 e.ca = 0x3
155 if value == 0x7ffffffff:
156 e.intregs[6] = 0x7ffffffff
157 else:
158 e.intregs[6] = 0xffff80000
159 if '.' in choice:
160 e.crregs[0] = 0x4
161 self.add_case(Program(lst, bigendian),
162 initial_regs, initial_sprs, expected=e)
163
164 def case_addme_ca_so_4(self):
165 """test of SO being set
166 """
167 lst = ["addmeo. 6, 16"]
168 initial_regs = [0] * 32
169 initial_regs[16] = 0x7fffffffffffffff
170 initial_sprs = {}
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
177 e.ca = 0x3
178 e.crregs[0] = 0x4
179 self.add_case(Program(lst, bigendian),
180 initial_regs, initial_sprs, expected=e)
181
182 def case_addme_ca_so_3(self):
183 """bug where SO does not get passed through to CR0
184 """
185 lst = ["addme. 6, 16"]
186 initial_regs = [0] * 32
187 initial_regs[16] = 0x7ffffffff
188 initial_sprs = {}
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
196 e.crregs[0] = 0x5
197 e.so = 0x1
198 e.ca = 0x3
199 self.add_case(Program(lst, bigendian),
200 initial_regs, initial_sprs, expected=e)
201
202 def case_addme_subfme_ca_propagation(self):
203 for flags in range(1 << 2):
204 ca = flags & 1
205 is_sub = (flags >> 1) & 1
206 if is_sub:
207 prog = Program(["subfmeo 3, 4"], bigendian)
208 else:
209 prog = Program(["addmeo 3, 4"], bigendian)
210 for i in range(-2, 3):
211 ra = i % 2 ** 64
212 with self.subTest(ra=hex(ra), ca=ca, is_sub=is_sub):
213 initial_regs = [0] * 32
214 initial_regs[4] = ra
215 initial_sprs = {}
216 xer = SelectableInt(0, 64)
217 xer[XER_bits['CA']] = ca
218 initial_sprs[special_sprs['XER']] = xer
219 e = ExpectedState(pc=4)
220 e.intregs[4] = ra
221 rb = 2 ** 64 - 1 # add 0xfff...fff *not* -1
222 expected = ca + rb
223 expected32 = ca + (rb % 2 ** 32)
224 inv_ra = ra
225 if is_sub:
226 # 64-bit bitwise not
227 inv_ra = ~ra % 2 ** 64
228 expected += inv_ra
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
236 axb = inv_ra ^ rb
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,
243 expected=e)
244
245 def case_addze(self):
246 insns = ["addze", "addze.", "addzeo", "addzeo."]
247 for choice in insns:
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
254 if '.' in choice:
255 e.crregs[0] = 0x4
256 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
257
258 def case_addis_nonzero_r0_regression(self):
259 lst = [f"addis 3, 0, 1"]
260 print(lst)
261 initial_regs = [0] * 32
262 initial_regs[0] = 5
263 e = ExpectedState(initial_regs, pc=4)
264 e.intregs[3] = 0x10000
265 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
266
267 def case_addis_nonzero_r0(self):
268 for i in range(10):
269 imm = random.randint(-(1 << 15), (1 << 15)-1)
270 lst = [f"addis 3, 0, {imm}"]
271 print(lst)
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)
278
279 def case_rand_imm(self):
280 insns = ["addi", "addis", "subfic"]
281 for i in range(10):
282 choice = random.choice(insns)
283 imm = random.randint(-(1 << 15), (1 << 15)-1)
284 lst = [f"{choice} 3, 1, {imm}"]
285 print(lst)
286 initial_regs = [0] * 32
287 initial_regs[1] = random.randint(0, (1 << 64)-1)
288
289 e = ExpectedState(pc=4)
290 e.intregs[1] = initial_regs[1]
291 if choice == "addi":
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
300 if imm < 0:
301 value += 2**64
302 carry_out = value & (1 << 64) != 0
303 value = (~initial_regs[1]+2**64 & 0xffff_ffff) + imm + 1
304 if imm < 0:
305 value += 2**32
306 carry_out32 = value & (1 << 32) != 0
307 e.intregs[3] = result & ((2**64)-1)
308 e.ca = carry_out | (carry_out32 << 1)
309
310 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
311
312 def case_0_adde(self):
313 lst = ["adde. 5, 6, 7"]
314 for i in range(10):
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)
318 initial_sprs = {}
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
330 eq = 0
331 gt = 0
332 le = 0
333 if (result & (1 << 63)) != 0:
334 le = 1
335 elif result == 0:
336 eq = 1
337 else:
338 gt = 1
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)
349
350 self.add_case(Program(lst, bigendian),
351 initial_regs, initial_sprs, expected=e)
352
353 def case_cmp(self):
354 lst = ["subf. 1, 6, 7",
355 "cmp cr2, 1, 6, 7"]
356 initial_regs = [0] * 32
357 initial_regs[6] = 0x10
358 initial_regs[7] = 0x05
359 e = ExpectedState(pc=8)
360 e.intregs[6] = 0x10
361 e.intregs[7] = 0x5
362 e.intregs[1] = 0xfffffffffffffff5
363 e.crregs[0] = 0x8
364 e.crregs[2] = 0x4
365 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
366
367 def case_cmp2(self):
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
375 e.crregs[2] = 0x2
376 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
377
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
385 e.crregs[2] = 0x2
386 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
387
388 def case_cmp3(self):
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
396 e.crregs[2] = 0x8
397 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
398
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
406 e.crregs[2] = 0x4
407 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
408
409 def case_cmpl_microwatt_0(self):
410 """microwatt 1.bin:
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
416 """
417
418 lst = ["cmpl 6, 0, 17, 10"]
419 initial_regs = [0] * 32
420 initial_regs[0x11] = 0x1c026
421 initial_regs[0xa] = 0xFEDF3FFF0001C025
422 XER = 0xe00c0000
423 CR = 0x35055050
424
425 e = ExpectedState(pc=4)
426 e.intregs[10] = 0xfedf3fff0001c025
427 e.intregs[17] = 0x1c026
428 e.crregs[0] = 0x3
429 e.crregs[1] = 0x5
430 e.crregs[3] = 0x5
431 e.crregs[4] = 0x5
432 e.crregs[6] = 0x5
433 e.so = 0x1
434 e.ov = 0x3
435 e.ca = 0x3
436
437 self.add_case(Program(lst, bigendian), initial_regs,
438 initial_sprs={'XER': XER},
439 initial_cr=CR, expected=e)
440
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
448 """
449
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
455 XER = 0xe00c0000
456 CR = 0x35055050
457
458 e = ExpectedState(pc=4)
459 e.intregs[10] = 0xfedf3fff0001c025
460 e.intregs[17] = 0x1c026
461 e.crregs[0] = 0x3
462 e.crregs[1] = 0x5
463 e.crregs[3] = 0x5
464 e.crregs[4] = 0x5
465 e.crregs[6] = 0x5
466 e.so = 0x1
467 e.ov = 0x3
468 e.ca = 0x3
469
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)
475
476 def case_cmplw_microwatt_1(self):
477 """microwatt 1.bin:
478 10d94: 40 20 96 7c cmplw cr1,r22,r4
479 gpr: 00000000ffff6dc1 <- r4
480 gpr: 0000000000000000 <- r22
481 """
482
483 lst = ["cmpl 1, 0, 22, 4"]
484 initial_regs = [0] * 32
485 initial_regs[4] = 0xffff6dc1
486 initial_regs[22] = 0
487 XER = 0xe00c0000
488 CR = 0x50759999
489
490 e = ExpectedState(pc=4)
491 e.intregs[4] = 0xffff6dc1
492 e.crregs[0] = 0x5
493 e.crregs[1] = 0x9
494 e.crregs[2] = 0x7
495 e.crregs[3] = 0x5
496 e.crregs[4] = 0x9
497 e.crregs[5] = 0x9
498 e.crregs[6] = 0x9
499 e.crregs[7] = 0x9
500 e.so = 0x1
501 e.ov = 0x3
502 e.ca = 0x3
503
504 self.add_case(Program(lst, bigendian), initial_regs,
505 initial_sprs={'XER': XER},
506 initial_cr=CR, expected=e)
507
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
514
515 """
516
517 lst = ["cmpli 5, 0, 13, 31132"]
518 initial_regs = [0] * 32
519 initial_regs[13] = 0x301fc7a7
520 XER = 0xe00c0000
521 CR = 0x90215393
522
523 e = ExpectedState(pc=4)
524 e.intregs[13] = 0x301fc7a7
525 e.crregs[0] = 0x9
526 e.crregs[2] = 0x2
527 e.crregs[3] = 0x1
528 e.crregs[4] = 0x5
529 e.crregs[5] = 0x5
530 e.crregs[6] = 0x9
531 e.crregs[7] = 0x3
532 e.so = 0x1
533 e.ov = 0x3
534 e.ca = 0x3
535
536 self.add_case(Program(lst, bigendian), initial_regs,
537 initial_sprs={'XER': XER},
538 initial_cr=CR, expected=e)
539
540 def case_extsb(self):
541 insns = ["extsb", "extsh", "extsw"]
542 for i in range(10):
543 choice = random.choice(insns)
544 lst = [f"{choice} 3, 1"]
545 print(lst)
546 initial_regs = [0] * 32
547 initial_regs[1] = random.randint(0, (1 << 64)-1)
548
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)
555 else:
556 e.intregs[3] = exts(initial_regs[1], 32) & ((1 << 64)-1)
557
558 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
559
560 def case_cmpeqb(self):
561 lst = ["cmpeqb cr1, 1, 2"]
562 for i in range(20):
563 initial_regs = [0] * 32
564 initial_regs[1] = i
565 initial_regs[2] = 0x0001030507090b0f
566
567 e = ExpectedState(pc=4)
568 e.intregs[1] = i
569 e.intregs[2] = 0x1030507090b0f
570 matlst = [0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0f]
571 for j in matlst:
572 if j == i:
573 e.crregs[1] = 0x4
574
575 self.add_case(Program(lst, bigendian), initial_regs, expected=e)