add unit test for mcrxrx
[openpower-isa.git] / src / openpower / test / util.py
1 # SPDX-License-Identifier: LGPL-3-or-later
2 # Copyright 2023 Jacob Lifshay programmerjake@gmail.com
3
4 # Funded by NLnet Assure Programme 2021-02-052, https://nlnet.nl/assure part
5 # of Horizon 2020 EU Programme 957073.
6
7 import re
8 from openpower.insndb.asm import SVP64Asm
9 from openpower.simulator.program import Program
10 from functools import lru_cache
11
12
13 def assemble(instructions, start_pc=0, bigendian=False):
14 """ assemble `instructions`, handling labels.
15 returns a Program instance
16 """
17 return __cached_assemble(tuple(instructions), start_pc, bigendian)
18
19
20 @lru_cache(maxsize=10000)
21 def __cached_assemble(instructions, start_pc, bigendian):
22 pc = start_pc
23 labels = {}
24 out_instructions = []
25 for instr in instructions:
26 m = re.fullmatch(r" *([a-zA-Z0-9_]+): *(#.*)?", instr)
27 if m is not None:
28 name = m.group(1)
29 if name in labels:
30 raise ValueError(f"label {name!r} defined multiple times")
31 labels[name] = pc
32 continue
33 m = re.fullmatch(r" *sv\.[a-zA-Z0-9_].*", instr)
34 if m is not None:
35 pc += 8
36 else:
37 pc += 4
38 out_instructions.append((pc, instr))
39 last_pc = pc
40
41 for (idx, (pc, instr)) in enumerate(tuple(out_instructions)):
42 for (label, target) in labels.items():
43 if label in instr:
44 if pc < target:
45 sign = ""
46 addr = (target - pc + 4)
47 else:
48 sign = "-"
49 addr = (pc - target - 4)
50
51 origin = instr
52 instr = instr.replace(label, f"{sign}0x{addr:X}")
53 break
54 out_instructions[idx] = instr
55
56 for k, v in labels.items():
57 out_instructions.append(f".set {k}, . - 0x{last_pc - v:X} # 0x{v:X}")
58
59 return Program(list(SVP64Asm(out_instructions)), bigendian)