1 # SPDX-License-Identifier: LGPL-3-or-later
2 # Copyright 2023 Jacob Lifshay programmerjake@gmail.com
4 # Funded by NLnet Assure Programme 2021-02-052, https://nlnet.nl/assure part
5 # of Horizon 2020 EU Programme 957073.
8 from openpower
.insndb
.asm
import SVP64Asm
9 from openpower
.simulator
.program
import Program
10 from functools
import lru_cache
13 def assemble(instructions
, start_pc
=0, bigendian
=False):
14 """ assemble `instructions`, handling labels.
15 returns a Program instance
17 return __cached_assemble(tuple(instructions
), start_pc
, bigendian
)
20 @lru_cache(maxsize
=10000)
21 def __cached_assemble(instructions
, start_pc
, bigendian
):
25 for instr
in instructions
:
26 m
= re
.fullmatch(r
" *([a-zA-Z0-9_.$]+): *(#.*)?", instr
)
30 raise ValueError(f
"label {name!r} defined multiple times")
33 m
= re
.fullmatch(r
" *sv\.[a-zA-Z0-9_].*", instr
)
38 out_instructions
.append((pc
, instr
))
41 for (idx
, (pc
, instr
)) in enumerate(tuple(out_instructions
)):
46 label
= match
.group(1)
47 target
= labels
.get(label
)
48 if target
is not None:
52 addr
= (target
- pc
+ 4)
55 addr
= (pc
- target
- 4)
56 return f
"{sign}0x{addr:X}"
61 # gas symbols start with any alphabetic or _ . $
63 # gas symbols continue with any alphanumeric or _ . $
64 cont
= "[a-zA-Z0-9_.$]"
65 # look for symbols that don't have preceding/succeeding `cont`
66 instr
= re
.sub(f
"({start}{cont}*)", replace
, instr
)
67 out_instructions
[idx
] = instr
69 for k
, v
in labels
.items():
70 out_instructions
.append(f
".set {k}, . - 0x{last_pc - v:X} # 0x{v:X}")
72 return Program(list(SVP64Asm(out_instructions
)), bigendian
)