pysvp64db: fix traversal
[openpower-isa.git] / src / openpower / test / alu / alu_cases.py
1 import random
2 from openpower.test.common import \
3 TestAccumulatorBase, skip_case, skip_case_if_flag
4 from openpower.endian import bigendian
5 from openpower.simulator.program import Program
6 from openpower.decoder.selectable_int import SelectableInt
7 from openpower.decoder.power_enums import XER_bits
8 from openpower.decoder.isa.caller import special_sprs
9 from openpower.decoder.helpers import exts
10 from openpower.test.state import ExpectedState
11 from openpower.util import log
12 from pathlib import Path
13 import gzip
14 import json
15 import sys
16 from hashlib import sha256
17 from functools import lru_cache
18
19 # output-for-v0.2.0-7-g95fdd1c.json.gz generated from:
20 # https://salsa.debian.org/Kazan-team/power-instruction-analyzer/-/commit/95fdd1c4edbd91c0a02b772ba02aa2045101d2b0
21 # running on POWER9
22 PIA_OUTPUT_URL = "https://ftp.libre-soc.org/power-instruction-analyzer/output-for-v0.2.0-7-g95fdd1c.json.gz"
23 PIA_OUTPUT_SHA256 = "2ad50464eb6c9b6bf2dad2ee16b6820a34024bc008ea86818845cf14f7f457ad"
24 PIA_OUTPUT_PATH = Path(__file__).parent / PIA_OUTPUT_URL.rpartition('/')[2]
25
26
27 def download_pia_output():
28 from urllib.request import urlopen
29 from shutil import copyfileobj
30 with PIA_OUTPUT_PATH.open("wb") as f:
31 print(f"downloading {PIA_OUTPUT_URL} to {PIA_OUTPUT_PATH}",
32 file=sys.stderr, flush=True)
33 with urlopen(PIA_OUTPUT_URL) as response:
34 copyfileobj(response, f)
35
36
37 @lru_cache(maxsize=None)
38 def read_pia_output(filter_fn=lambda _: True):
39 tried_download = False
40 while True:
41 try:
42 file_bytes = PIA_OUTPUT_PATH.read_bytes()
43 digest = sha256(file_bytes).hexdigest()
44 if digest != PIA_OUTPUT_SHA256:
45 raise Exception(f"{PIA_OUTPUT_PATH} has wrong hash, expected "
46 f"{PIA_OUTPUT_SHA256} got {digest}")
47 file_bytes = gzip.decompress(file_bytes)
48 test_cases = json.loads(file_bytes)['test_cases']
49 return list(filter(filter_fn, test_cases))
50 except:
51 if tried_download:
52 raise
53 pass
54 tried_download = True
55 download_pia_output()
56
57
58 @lru_cache(maxsize=None)
59 def get_addmeo_subfmeo_reference_cases():
60 return read_pia_output(lambda i: i['instr'] in ("addmeo", "subfmeo"))
61
62
63 def check_addmeo_subfmeo_matches_reference(instr, case_filter, out):
64 case_filter = {
65 'instr': instr,
66 'ra': '0x0', 'ca': False, 'ca32': False,
67 'so': False, 'ov': False, 'ov32': False,
68 **case_filter
69 }
70 for case in get_addmeo_subfmeo_reference_cases():
71 skip = False
72 for k, v in case_filter.items():
73 if case[k] != v:
74 skip = True
75 break
76 if skip:
77 continue
78 reference_outputs = case['native_outputs']
79 for k, v in out.items():
80 assert reference_outputs[k] == v, (
81 f"{instr} outputs don't match reference:\n"
82 f"case_filter={case_filter}\nout={out}\n"
83 f"reference_outputs={reference_outputs}")
84 log(f"PIA reference successfully matched: {case_filter}")
85 return True
86 log(f"PIA reference not found: {case_filter}")
87 return False
88
89
90 class ALUTestCase(TestAccumulatorBase):
91 @skip_case_if_flag('soc')
92 def case_addex(self):
93 lst = [f"addex 3, 4, 5, 0"]
94 program = Program(lst, bigendian)
95 values = (*range(-2, 4), ~1 << 63, (1 << 63) - 1)
96 for ra in values:
97 ra %= 1 << 64
98 for rb in values:
99 rb %= 1 << 64
100 for ov in (0, 1):
101 with self.subTest(ra=hex(ra), rb=hex(rb), ov=ov):
102 initial_regs = [0] * 32
103 initial_regs[4] = ra
104 initial_regs[5] = rb
105 initial_sprs = {}
106 xer = SelectableInt(0, 64)
107 xer[XER_bits['OV']] = ov
108 initial_sprs[special_sprs['XER']] = xer
109 e = ExpectedState(pc=4)
110 v = ra + rb + ov
111 v32 = (ra % (1 << 32)) + (rb % (1 << 32)) + ov
112 ov = v >> 64
113 ov32 = v32 >> 32
114 e.intregs[3] = v % (1 << 64)
115 e.intregs[4] = ra
116 e.intregs[5] = rb
117 e.ov = (ov32 << 1) | ov
118 self.add_case(program, initial_regs,
119 initial_sprs=initial_sprs, expected=e)
120
121 def case_nego_(self):
122 lst = [f"nego. 3, 4"]
123 initial_regs = [0] * 32
124 initial_regs[4] = 0
125 e = ExpectedState(pc=4)
126 e.intregs[3] = 0
127 e.intregs[4] = 0
128 e.so = 0
129 e.ov = 0
130 e.crregs[0] = 2
131 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
132
133 def case_1_regression(self):
134 lst = [f"add. 3, 1, 2"]
135 initial_regs = [0] * 32
136 initial_regs[1] = 0xc523e996a8ff6215
137 initial_regs[2] = 0xe1e5b9cc9864c4a8
138 e = ExpectedState(pc=4)
139 e.intregs[1] = 0xc523e996a8ff6215
140 e.intregs[2] = 0xe1e5b9cc9864c4a8
141 e.intregs[3] = 0xa709a363416426bd
142 e.crregs[0] = 0x8
143 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
144
145 def case_2_regression(self):
146 lst = [f"extsw 3, 1"]
147 initial_regs = [0] * 32
148 initial_regs[1] = 0xb6a1fc6c8576af91
149 e = ExpectedState(pc=4)
150 e.intregs[1] = 0xb6a1fc6c8576af91
151 e.intregs[3] = 0xffffffff8576af91
152 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
153
154 lst = [f"subf 3, 1, 2"]
155 initial_regs = [0] * 32
156 initial_regs[1] = 0x3d7f3f7ca24bac7b
157 initial_regs[2] = 0xf6b2ac5e13ee15c2
158 e = ExpectedState(pc=4)
159 e.intregs[1] = 0x3d7f3f7ca24bac7b
160 e.intregs[2] = 0xf6b2ac5e13ee15c2
161 e.intregs[3] = 0xb9336ce171a26947
162 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
163
164 lst = [f"subf 3, 1, 2"]
165 initial_regs = [0] * 32
166 initial_regs[1] = 0x833652d96c7c0058
167 initial_regs[2] = 0x1c27ecff8a086c1a
168 e = ExpectedState(pc=4)
169 e.intregs[1] = 0x833652d96c7c0058
170 e.intregs[2] = 0x1c27ecff8a086c1a
171 e.intregs[3] = 0x98f19a261d8c6bc2
172 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
173
174 lst = [f"extsb 3, 1"]
175 initial_regs = [0] * 32
176 initial_regs[1] = 0x7f9497aaff900ea0
177 e = ExpectedState(pc=4)
178 e.intregs[1] = 0x7f9497aaff900ea0
179 e.intregs[3] = 0xffffffffffffffa0
180 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
181
182 lst = [f"add 3, 1, 2"]
183 initial_regs = [0] * 32
184 initial_regs[1] = 0x2e08ae202742baf8
185 initial_regs[2] = 0x86c43ece9efe5baa
186 e = ExpectedState(pc=4)
187 e.intregs[1] = 0x2e08ae202742baf8
188 e.intregs[2] = 0x86c43ece9efe5baa
189 e.intregs[3] = 0xb4cceceec64116a2
190 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
191
192 def case_rand(self):
193 insns = ["add", "add.", "subf"]
194 for i in range(40):
195 choice = random.choice(insns)
196 lst = [f"{choice} 3, 1, 2"]
197 initial_regs = [0] * 32
198 initial_regs[1] = random.randint(0, (1 << 64)-1)
199 initial_regs[2] = random.randint(0, (1 << 64)-1)
200
201 e = ExpectedState(pc=4)
202 e.intregs[1] = initial_regs[1]
203 e.intregs[2] = initial_regs[2]
204 if choice == "add":
205 result = initial_regs[1] + initial_regs[2]
206 e.intregs[3] = result & ((2**64)-1)
207 elif choice == "add.":
208 result = initial_regs[1] + initial_regs[2]
209 e.intregs[3] = result & ((2**64)-1)
210 eq = 0
211 gt = 0
212 lt = 0
213 if (e.intregs[3] & (1 << 63)) != 0:
214 lt = 1
215 elif e.intregs[3] == 0:
216 eq = 1
217 else:
218 gt = 1
219 e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
220 elif choice == "subf":
221 result = ~initial_regs[1] + initial_regs[2] + 1
222 e.intregs[3] = result & ((2**64)-1)
223
224 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
225
226 def case_addme_ca_0(self):
227 insns = ["addme", "addme.", "addmeo", "addmeo."]
228 for choice in insns:
229 lst = [f"{choice} 6, 16"]
230 for value in [0x7ffffffff,
231 0xffff80000]:
232 initial_regs = [0] * 32
233 initial_regs[16] = value
234 initial_sprs = {}
235 xer = SelectableInt(0, 64)
236 xer[XER_bits['CA']] = 0 # input carry is 0 (see test below)
237 initial_sprs[special_sprs['XER']] = xer
238
239 # create expected results. pc should be 4 (one instruction)
240 e = ExpectedState(pc=4)
241 # input value should not be modified
242 e.intregs[16] = value
243 # carry-out should always occur
244 e.ca = 0x3
245 # create output value
246 if value == 0x7ffffffff:
247 e.intregs[6] = 0x7fffffffe
248 else:
249 e.intregs[6] = 0xffff7ffff
250 # CR version needs an expected CR
251 if '.' in choice:
252 e.crregs[0] = 0x4
253 self.add_case(Program(lst, bigendian),
254 initial_regs, initial_sprs,
255 expected=e)
256
257 def case_addme_ca_1(self):
258 insns = ["addme", "addme.", "addmeo", "addmeo."]
259 for choice in insns:
260 lst = [f"{choice} 6, 16"]
261 for value in [0x7ffffffff, # fails, bug #476
262 0xffff80000]:
263 initial_regs = [0] * 32
264 initial_regs[16] = value
265 initial_sprs = {}
266 xer = SelectableInt(0, 64)
267 # input carry is 1 (differs from above)
268 xer[XER_bits['CA']] = 1
269 initial_sprs[special_sprs['XER']] = xer
270 e = ExpectedState(pc=4)
271 e.intregs[16] = value
272 e.ca = 0x3
273 if value == 0x7ffffffff:
274 e.intregs[6] = 0x7ffffffff
275 else:
276 e.intregs[6] = 0xffff80000
277 if '.' in choice:
278 e.crregs[0] = 0x4
279 self.add_case(Program(lst, bigendian),
280 initial_regs, initial_sprs, expected=e)
281
282 def case_addme_ca_so_4(self):
283 """test of SO being set
284 """
285 lst = ["addmeo. 6, 16"]
286 initial_regs = [0] * 32
287 initial_regs[16] = 0x7fffffffffffffff
288 initial_sprs = {}
289 xer = SelectableInt(0, 64)
290 xer[XER_bits['CA']] = 1
291 initial_sprs[special_sprs['XER']] = xer
292 e = ExpectedState(pc=4)
293 e.intregs[16] = 0x7fffffffffffffff
294 e.intregs[6] = 0x7fffffffffffffff
295 e.ca = 0x3
296 e.crregs[0] = 0x4
297 self.add_case(Program(lst, bigendian),
298 initial_regs, initial_sprs, expected=e)
299
300 def case_addme_ca_so_3(self):
301 """bug where SO does not get passed through to CR0
302 """
303 lst = ["addme. 6, 16"]
304 initial_regs = [0] * 32
305 initial_regs[16] = 0x7ffffffff
306 initial_sprs = {}
307 xer = SelectableInt(0, 64)
308 xer[XER_bits['CA']] = 1
309 xer[XER_bits['SO']] = 1
310 initial_sprs[special_sprs['XER']] = xer
311 e = ExpectedState(pc=4)
312 e.intregs[16] = 0x7ffffffff
313 e.intregs[6] = 0x7ffffffff
314 e.crregs[0] = 0x5
315 e.so = 0x1
316 e.ca = 0x3
317 self.add_case(Program(lst, bigendian),
318 initial_regs, initial_sprs, expected=e)
319
320 def case_addme_subfme_ca_propagation(self):
321 for flags in range(1 << 2):
322 ca_in = bool(flags & 1)
323 is_sub = (flags >> 1) & 1
324 if is_sub:
325 prog = Program(["subfmeo 3, 4"], bigendian)
326 else:
327 prog = Program(["addmeo 3, 4"], bigendian)
328 for i in range(-2, 3):
329 ra = i % 2 ** 64
330 with self.subTest(ra=hex(ra), ca=ca_in, is_sub=is_sub):
331 initial_regs = [0] * 32
332 initial_regs[4] = ra
333 initial_sprs = {}
334 xer = SelectableInt(0, 64)
335 xer[XER_bits['CA']] = ca_in
336 initial_sprs[special_sprs['XER']] = xer
337 e = ExpectedState(pc=4)
338 e.intregs[4] = ra
339 rb = 2 ** 64 - 1 # add 0xfff...fff *not* -1
340 expected = ca_in + rb
341 expected32 = ca_in + (rb % 2 ** 32)
342 inv_ra = ra
343 if is_sub:
344 # 64-bit bitwise not
345 inv_ra = ~ra % 2 ** 64
346 expected += inv_ra
347 expected32 += inv_ra % 2 ** 32
348 rt_out = expected % 2 ** 64
349 e.intregs[3] = rt_out
350 ca = bool(expected >> 64)
351 ca32 = bool(expected32 >> 32)
352 e.ca = (ca32 << 1) | ca
353 # use algorithm from microwatt's calc_ov
354 # https://github.com/antonblanchard/microwatt/blob/5c6d57de3056bd08fdc1f656bc8656635a77512b/execute1.vhdl#L284
355 axb = inv_ra ^ rb
356 emsb = (expected >> 63) & 1
357 ov = ca ^ emsb and not (axb >> 63) & 1
358 e32msb = (expected32 >> 31) & 1
359 ov32 = ca32 ^ e32msb and not (axb >> 31) & 1
360 e.ov = (ov32 << 1) | ov
361 check_addmeo_subfmeo_matches_reference(
362 instr='subfmeo' if is_sub else 'addmeo',
363 case_filter={
364 'ra': f'0x{ra:X}', 'ca': ca_in,
365 }, out={
366 'rt': f'0x{rt_out:X}', 'ca': ca,
367 'ca32': ca32, 'ov': ov, 'ov32': ov32,
368 })
369 self.add_case(prog, initial_regs, initial_sprs,
370 expected=e)
371
372 def case_addze(self):
373 insns = ["addze", "addze.", "addzeo", "addzeo."]
374 for choice in insns:
375 lst = [f"{choice} 6, 16"]
376 initial_regs = [0] * 32
377 initial_regs[16] = 0x00ff00ff00ff0080
378 e = ExpectedState(pc=4)
379 e.intregs[16] = 0xff00ff00ff0080
380 e.intregs[6] = 0xff00ff00ff0080
381 if '.' in choice:
382 e.crregs[0] = 0x4
383 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
384
385 def case_addis_nonzero_r0_regression(self):
386 lst = [f"addis 3, 0, 1"]
387 print(lst)
388 initial_regs = [0] * 32
389 initial_regs[0] = 5
390 e = ExpectedState(initial_regs, pc=4)
391 e.intregs[3] = 0x10000
392 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
393
394 def case_addis_nonzero_r0(self):
395 for i in range(10):
396 imm = random.randint(-(1 << 15), (1 << 15)-1)
397 lst = [f"addis 3, 0, {imm}"]
398 print(lst)
399 initial_regs = [0] * 32
400 initial_regs[0] = random.randint(0, (1 << 64)-1)
401 e = ExpectedState(pc=4)
402 e.intregs[0] = initial_regs[0]
403 e.intregs[3] = (imm << 16) & ((1 << 64)-1)
404 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
405
406 def case_rand_imm(self):
407 insns = ["addi", "addis", "subfic"]
408 for i in range(10):
409 choice = random.choice(insns)
410 imm = random.randint(-(1 << 15), (1 << 15)-1)
411 lst = [f"{choice} 3, 1, {imm}"]
412 print(lst)
413 initial_regs = [0] * 32
414 initial_regs[1] = random.randint(0, (1 << 64)-1)
415
416 e = ExpectedState(pc=4)
417 e.intregs[1] = initial_regs[1]
418 if choice == "addi":
419 result = initial_regs[1] + imm
420 e.intregs[3] = result & ((2**64)-1)
421 elif choice == "addis":
422 result = initial_regs[1] + (imm << 16)
423 e.intregs[3] = result & ((2**64)-1)
424 elif choice == "subfic":
425 result = ~initial_regs[1] + imm + 1
426 value = (~initial_regs[1]+2**64) + (imm) + 1
427 if imm < 0:
428 value += 2**64
429 carry_out = value & (1 << 64) != 0
430 value = (~initial_regs[1]+2**64 & 0xffff_ffff) + imm + 1
431 if imm < 0:
432 value += 2**32
433 carry_out32 = value & (1 << 32) != 0
434 e.intregs[3] = result & ((2**64)-1)
435 e.ca = carry_out | (carry_out32 << 1)
436
437 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
438
439 def case_0_adde(self):
440 lst = ["adde. 5, 6, 7"]
441 for i in range(10):
442 initial_regs = [0] * 32
443 initial_regs[6] = random.randint(0, (1 << 64)-1)
444 initial_regs[7] = random.randint(0, (1 << 64)-1)
445 initial_sprs = {}
446 xer = SelectableInt(0, 64)
447 xer[XER_bits['CA']] = 1
448 initial_sprs[special_sprs['XER']] = xer
449 # calculate result *including carry* and mask it to 64-bit
450 # (if it overflows, we don't care, because this is not addeo)
451 result = 1 + initial_regs[6] + initial_regs[7]
452 # detect 65th bit as carry-out?
453 carry_out = result & (1 << 64) != 0
454 carry_out32 = (initial_regs[6] & 0xffff_ffff) + \
455 (initial_regs[7] & 0xffff_ffff) & (1 << 32) != 0
456 result = result & ((1 << 64)-1) # round
457 eq = 0
458 gt = 0
459 lt = 0
460 if (result & (1 << 63)) != 0:
461 lt = 1
462 elif result == 0:
463 eq = 1
464 else:
465 gt = 1
466 # now construct the state
467 e = ExpectedState(pc=4)
468 e.intregs[6] = initial_regs[6] # should be same as initial
469 e.intregs[7] = initial_regs[7] # should be same as initial
470 e.intregs[5] = result
471 # carry_out goes into bit 0 of ca, carry_out32 into bit 1
472 e.ca = carry_out | (carry_out32 << 1)
473 # eq goes into bit 1 of CR0, gt into bit 2, lt into bit 3.
474 # SO goes into bit 0 but overflow doesn't occur here [we hope]
475 e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
476
477 self.add_case(Program(lst, bigendian),
478 initial_regs, initial_sprs, expected=e)
479
480 def case_cmp(self):
481 lst = ["subf. 1, 6, 7",
482 "cmp cr2, 1, 6, 7"]
483 initial_regs = [0] * 32
484 initial_regs[6] = 0x10
485 initial_regs[7] = 0x05
486 e = ExpectedState(pc=8)
487 e.intregs[6] = 0x10
488 e.intregs[7] = 0x5
489 e.intregs[1] = 0xfffffffffffffff5
490 e.crregs[0] = 0x8
491 e.crregs[2] = 0x4
492 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
493
494 def case_cmp2(self):
495 lst = ["cmp cr2, 0, 2, 3"]
496 initial_regs = [0] * 32
497 initial_regs[2] = 0xffffffffaaaaaaaa
498 initial_regs[3] = 0x00000000aaaaaaaa
499 e = ExpectedState(pc=4)
500 e.intregs[2] = 0xffffffffaaaaaaaa
501 e.intregs[3] = 0xaaaaaaaa
502 e.crregs[2] = 0x2
503 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
504
505 lst = ["cmp cr2, 0, 4, 5"]
506 initial_regs = [0] * 32
507 initial_regs[4] = 0x00000000aaaaaaaa
508 initial_regs[5] = 0xffffffffaaaaaaaa
509 e = ExpectedState(pc=4)
510 e.intregs[4] = 0xaaaaaaaa
511 e.intregs[5] = 0xffffffffaaaaaaaa
512 e.crregs[2] = 0x2
513 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
514
515 def case_cmp3(self):
516 lst = ["cmp cr2, 1, 2, 3"]
517 initial_regs = [0] * 32
518 initial_regs[2] = 0xffffffffaaaaaaaa
519 initial_regs[3] = 0x00000000aaaaaaaa
520 e = ExpectedState(pc=4)
521 e.intregs[2] = 0xffffffffaaaaaaaa
522 e.intregs[3] = 0xaaaaaaaa
523 e.crregs[2] = 0x8
524 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
525
526 lst = ["cmp cr2, 1, 4, 5"]
527 initial_regs = [0] * 32
528 initial_regs[4] = 0x00000000aaaaaaaa
529 initial_regs[5] = 0xffffffffaaaaaaaa
530 e = ExpectedState(pc=4)
531 e.intregs[4] = 0xaaaaaaaa
532 e.intregs[5] = 0xffffffffaaaaaaaa
533 e.crregs[2] = 0x4
534 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
535
536 def case_cmpl_microwatt_0(self):
537 """microwatt 1.bin:
538 115b8: 40 50 d1 7c .long 0x7cd15040 # cmpl 6, 0, 17, 10
539 register_file.vhdl: Reading GPR 11 000000000001C026
540 register_file.vhdl: Reading GPR 0A FEDF3FFF0001C025
541 cr_file.vhdl: Reading CR 35055050
542 cr_file.vhdl: Writing 35055058 to CR mask 01 35055058
543 """
544
545 lst = ["cmpl 6, 0, 17, 10"]
546 initial_regs = [0] * 32
547 initial_regs[0x11] = 0x1c026
548 initial_regs[0xa] = 0xFEDF3FFF0001C025
549 XER = 0xe00c0000
550 CR = 0x35055050
551
552 e = ExpectedState(pc=4)
553 e.intregs[10] = 0xfedf3fff0001c025
554 e.intregs[17] = 0x1c026
555 e.crregs[0] = 0x3
556 e.crregs[1] = 0x5
557 e.crregs[3] = 0x5
558 e.crregs[4] = 0x5
559 e.crregs[6] = 0x5
560 e.so = 0x1
561 e.ov = 0x3
562 e.ca = 0x3
563
564 self.add_case(Program(lst, bigendian), initial_regs,
565 initial_sprs={'XER': XER},
566 initial_cr=CR, expected=e)
567
568 def case_cmpl_microwatt_0_disasm(self):
569 """microwatt 1.bin: disassembled version
570 115b8: 40 50 d1 7c .long 0x7cd15040 # cmpl 6, 0, 17, 10
571 register_file.vhdl: Reading GPR 11 000000000001C026
572 register_file.vhdl: Reading GPR 0A FEDF3FFF0001C025
573 cr_file.vhdl: Reading CR 35055050
574 cr_file.vhdl: Writing 35055058 to CR mask 01 35055058
575 """
576
577 dis = ["cmpl 6, 0, 17, 10"]
578 lst = bytes([0x40, 0x50, 0xd1, 0x7c]) # 0x7cd15040
579 initial_regs = [0] * 32
580 initial_regs[0x11] = 0x1c026
581 initial_regs[0xa] = 0xFEDF3FFF0001C025
582 XER = 0xe00c0000
583 CR = 0x35055050
584
585 e = ExpectedState(pc=4)
586 e.intregs[10] = 0xfedf3fff0001c025
587 e.intregs[17] = 0x1c026
588 e.crregs[0] = 0x3
589 e.crregs[1] = 0x5
590 e.crregs[3] = 0x5
591 e.crregs[4] = 0x5
592 e.crregs[6] = 0x5
593 e.so = 0x1
594 e.ov = 0x3
595 e.ca = 0x3
596
597 p = Program(lst, bigendian)
598 p.assembly = '\n'.join(dis)+'\n'
599 self.add_case(p, initial_regs,
600 initial_sprs={'XER': XER},
601 initial_cr=CR, expected=e)
602
603 def case_cmplw_microwatt_1(self):
604 """microwatt 1.bin:
605 10d94: 40 20 96 7c cmplw cr1,r22,r4
606 gpr: 00000000ffff6dc1 <- r4
607 gpr: 0000000000000000 <- r22
608 """
609
610 lst = ["cmpl 1, 0, 22, 4"]
611 initial_regs = [0] * 32
612 initial_regs[4] = 0xffff6dc1
613 initial_regs[22] = 0
614 XER = 0xe00c0000
615 CR = 0x50759999
616
617 e = ExpectedState(pc=4)
618 e.intregs[4] = 0xffff6dc1
619 e.crregs[0] = 0x5
620 e.crregs[1] = 0x9
621 e.crregs[2] = 0x7
622 e.crregs[3] = 0x5
623 e.crregs[4] = 0x9
624 e.crregs[5] = 0x9
625 e.crregs[6] = 0x9
626 e.crregs[7] = 0x9
627 e.so = 0x1
628 e.ov = 0x3
629 e.ca = 0x3
630
631 self.add_case(Program(lst, bigendian), initial_regs,
632 initial_sprs={'XER': XER},
633 initial_cr=CR, expected=e)
634
635 def case_cmpli_microwatt(self):
636 """microwatt 1.bin: cmpli
637 123ac: 9c 79 8d 2a cmpli cr5,0,r13,31132
638 gpr: 00000000301fc7a7 <- r13
639 cr : 0000000090215393
640 xer: so 1 ca 0 32 0 ov 0 32 0
641
642 """
643
644 lst = ["cmpli 5, 0, 13, 31132"]
645 initial_regs = [0] * 32
646 initial_regs[13] = 0x301fc7a7
647 XER = 0xe00c0000
648 CR = 0x90215393
649
650 e = ExpectedState(pc=4)
651 e.intregs[13] = 0x301fc7a7
652 e.crregs[0] = 0x9
653 e.crregs[2] = 0x2
654 e.crregs[3] = 0x1
655 e.crregs[4] = 0x5
656 e.crregs[5] = 0x5
657 e.crregs[6] = 0x9
658 e.crregs[7] = 0x3
659 e.so = 0x1
660 e.ov = 0x3
661 e.ca = 0x3
662
663 self.add_case(Program(lst, bigendian), initial_regs,
664 initial_sprs={'XER': XER},
665 initial_cr=CR, expected=e)
666
667 def case_extsb(self):
668 insns = ["extsb", "extsh", "extsw"]
669 for i in range(10):
670 choice = random.choice(insns)
671 lst = [f"{choice} 3, 1"]
672 print(lst)
673 initial_regs = [0] * 32
674 initial_regs[1] = random.randint(0, (1 << 64)-1)
675
676 e = ExpectedState(pc=4)
677 e.intregs[1] = initial_regs[1]
678 if choice == "extsb":
679 e.intregs[3] = exts(initial_regs[1], 8) & ((1 << 64)-1)
680 elif choice == "extsh":
681 e.intregs[3] = exts(initial_regs[1], 16) & ((1 << 64)-1)
682 else:
683 e.intregs[3] = exts(initial_regs[1], 32) & ((1 << 64)-1)
684
685 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
686
687 def case_cmpeqb(self):
688 lst = ["cmpeqb cr1, 1, 2"]
689 for i in range(20):
690 initial_regs = [0] * 32
691 initial_regs[1] = i
692 initial_regs[2] = 0x0001030507090b0f
693
694 e = ExpectedState(pc=4)
695 e.intregs[1] = i
696 e.intregs[2] = 0x1030507090b0f
697 matlst = [0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0f]
698 for j in matlst:
699 if j == i:
700 e.crregs[1] = 0x4
701
702 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
703
704 def case_pia_ca_ov_cases(self):
705 wanted_outputs = 'ca', 'ca32', 'ov', 'ov32', 'so'
706 # only test one variant of each instr --
707 # the variant with Rc=1 OV=1 as much as possible
708 wanted_instrs = {
709 'addi', 'paddi', 'addis', 'addo.', 'addic.', 'subfo.', 'subfic',
710 'addco.', 'subfco.', 'addeo.', 'subfeo.', 'addmeo.', 'subfmeo.',
711 'addzeo.', 'subfzeo.', 'addex', 'nego.',
712 }
713 if 'soc' in self.flags:
714 wanted_instrs.remove('addex')
715 unary_inputs = {
716 '0x0', '0x1', '0x2',
717 '0xFFFFFFFFFFFFFFFF', '0xFFFFFFFFFFFFFFFE',
718 '0x7FFFFFFFFFFFFFFE', '0x7FFFFFFFFFFFFFFF',
719 '0x8000000000000000', '0x8000000000000001',
720 '0x123456787FFFFFFE', '0x123456787FFFFFFF',
721 '0x1234567880000000', '0x1234567880000001',
722 }
723 imm_inputs = {
724 '0x0', '0x1', '0x2',
725 '0xFFFFFFFFFFFFFFFF', '0xFFFFFFFFFFFFFFFE',
726 '0xFFFFFFFFFFFF8000', '0xFFFFFFFFFFFF8001',
727 '0x7FFE', '0x7FFF', '0x8000', '0x8001',
728 }
729 binary_inputs32 = {
730 '0x0', '0x1', '0x2',
731 '0x12345678FFFFFFFF', '0x12345678FFFFFFFE',
732 '0x123456787FFFFFFE', '0x123456787FFFFFFF',
733 '0x1234567880000000', '0x1234567880000001',
734 }
735 binary_inputs64 = {
736 '0x0', '0x1', '0x2',
737 '0xFFFFFFFFFFFFFFFF', '0xFFFFFFFFFFFFFFFE',
738 '0x7FFFFFFFFFFFFFFE', '0x7FFFFFFFFFFFFFFF',
739 '0x8000000000000000', '0x8000000000000001',
740 }
741
742 def matches(case, **kwargs):
743 for k, v in kwargs.items():
744 if case[k] not in v:
745 return False
746 return True
747
748 programs = {}
749
750 for case in read_pia_output():
751 instr = case['instr']
752 if instr not in wanted_instrs:
753 continue
754 if not any(i in case['native_outputs'] for i in wanted_outputs):
755 continue
756 so_in = case.get('so', False)
757 ca_in = case.get('ca', False)
758 ca32_in = case.get('ca32', False)
759 ov_in = case.get('ov', False)
760 ov32_in = case.get('ov32', False)
761 if so_in:
762 continue
763 if ov32_in:
764 continue
765 if ca32_in:
766 continue
767 initial_regs = [0] * 32
768 initial_sprs = {}
769 xer = SelectableInt(0, 64)
770 xer[XER_bits['CA']] = ca_in
771 xer[XER_bits['OV']] = ov_in
772 initial_sprs[special_sprs['XER']] = xer
773 e = ExpectedState(pc=4)
774 e.intregs[3] = int(case['native_outputs']['rt'], 0)
775 ca_out = case['native_outputs'].get('ca', ca_in)
776 ca32_out = case['native_outputs'].get('ca32', ca32_in)
777 ov_out = case['native_outputs'].get('ov', ov_in)
778 ov32_out = case['native_outputs'].get('ov32', ov32_in)
779 so_out = case['native_outputs'].get('so', so_in)
780 e.ca = ca_out | (ca32_out << 1)
781 e.ov = ov_out | (ov32_out << 1)
782 e.so = int(so_out)
783 if 'rb' in case: # binary op
784 pass32 = matches(case, ra=binary_inputs32, rb=binary_inputs32)
785 pass64 = matches(case, ra=binary_inputs64, rb=binary_inputs64)
786 if not pass32 and not pass64:
787 continue
788 asm = f'{instr} 3, 4, 5'
789 if instr == 'addex':
790 asm += ', 0'
791 e.intregs[4] = initial_regs[4] = int(case['ra'], 0)
792 e.intregs[5] = initial_regs[5] = int(case['rb'], 0)
793 elif 'immediate' in case:
794 pass32 = matches(case, ra=binary_inputs32,
795 immediate=imm_inputs)
796 pass64 = matches(case, ra=binary_inputs64,
797 immediate=imm_inputs)
798 if not pass32 and not pass64:
799 continue
800 immediate = int(case['immediate'], 16)
801 if immediate >> 63:
802 immediate -= 1 << 64
803 asm = f'{instr} 3, 4, {immediate}'
804 e.intregs[4] = initial_regs[4] = int(case['ra'], 0)
805 else: # unary op
806 if not matches(case, ra=unary_inputs):
807 continue
808 asm = f'{instr} 3, 4'
809 e.intregs[4] = initial_regs[4] = int(case['ra'], 0)
810 if 'cr0' in case['native_outputs']:
811 cr0 = case['native_outputs']['cr0']
812 v = cr0['lt'] << 3
813 v |= cr0['gt'] << 2
814 v |= cr0['eq'] << 1
815 v |= cr0['so']
816 e.crregs[0] = v
817 with self.subTest(case=repr(case)):
818 if asm not in programs:
819 programs[asm] = Program([asm], bigendian)
820 self.add_case(programs[asm], initial_regs,
821 initial_sprs=initial_sprs, expected=e)
822
823 def case_mcrxrx(self):
824 p = Program(["mcrxrx 3"], bigendian)
825 for i in range(16):
826 initial_sprs = {}
827 xer = SelectableInt(0, 64)
828 ov = bool(i & 8)
829 ov32 = bool(i & 4)
830 ca = bool(i & 2)
831 ca32 = bool(i & 1)
832 xer[XER_bits['OV']] = ov
833 xer[XER_bits['OV32']] = ov32
834 xer[XER_bits['CA']] = ca
835 xer[XER_bits['CA32']] = ca32
836 initial_sprs[special_sprs['XER']] = xer
837 # now construct the state
838 e = ExpectedState(pc=4)
839 e.ca = (ca32 << 1) | ca
840 e.ov = (ov32 << 1) | ov
841 e.crregs[3] = i
842
843 with self.subTest(ov=ov, ov32=ov32, ca=ca, ca32=ca32):
844 self.add_case(p, initial_sprs=initial_sprs, expected=e)