From fbe70d5d13fd2c52adb4e95ae96a39612da3be4a Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 13 Sep 2023 23:22:33 -0700 Subject: [PATCH] generalize assemble() fn so other test cases can easily use it --- .../test/algorithms/svp64_utf_8_validation.py | 46 +--------------- src/openpower/test/util.py | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 45 deletions(-) create mode 100644 src/openpower/test/util.py diff --git a/src/openpower/test/algorithms/svp64_utf_8_validation.py b/src/openpower/test/algorithms/svp64_utf_8_validation.py index 054fd481..8b7698a7 100644 --- a/src/openpower/test/algorithms/svp64_utf_8_validation.py +++ b/src/openpower/test/algorithms/svp64_utf_8_validation.py @@ -2,12 +2,9 @@ # Copyright 2022 Jacob Lifshay import enum -import re -from openpower.decoder.selectable_int import SelectableInt -from openpower.simulator.program import Program from openpower.test.common import TestAccumulatorBase, skip_case +from openpower.test.util import assemble from openpower.test.state import ExpectedState -from openpower.insndb.asm import SVP64Asm from cached_property import cached_property @@ -285,47 +282,6 @@ def svp64_utf8_validation_asm(): ] -def assemble(instructions, start_pc=0): - pc = start_pc - labels = {} - out_instructions = [] - for instr in instructions: - m = re.fullmatch(r" *([a-zA-Z0-9_]+): *(#.*)?", instr) - if m is not None: - name = m.group(1) - if name in labels: - raise ValueError(f"label {name!r} defined multiple times") - labels[name] = pc - continue - m = re.fullmatch(r" *sv\.[a-zA-Z0-9_].*", instr) - if m is not None: - pc += 8 - else: - pc += 4 - out_instructions.append((pc, instr)) - last_pc = pc - - for (idx, (pc, instr)) in enumerate(tuple(out_instructions)): - for (label, target) in labels.items(): - if label in instr: - if pc < target: - sign = "" - addr = (target - pc + 4) - else: - sign = "-" - addr = (pc - target - 4) - - origin = instr - instr = instr.replace(label, f"{sign}0x{addr:X}") - break - out_instructions[idx] = instr - - for k, v in labels.items(): - out_instructions.append(f".set {k}, . - 0x{last_pc - v:X} # 0x{v:X}") - - return Program(list(SVP64Asm(out_instructions)), 0) - - class SVP64UTF8ValidationTestCase(TestAccumulatorBase): def __init__(self): self.__seen_cases = set() diff --git a/src/openpower/test/util.py b/src/openpower/test/util.py new file mode 100644 index 00000000..88243555 --- /dev/null +++ b/src/openpower/test/util.py @@ -0,0 +1,53 @@ +import re +from openpower.insndb.asm import SVP64Asm +from openpower.simulator.program import Program +from functools import lru_cache + + +def assemble(instructions, start_pc=0, bigendian=False): + """ assemble `instructions`, handling labels. + returns a Program instance + """ + return __cached_assemble(tuple(instructions), start_pc, bigendian) + + +@lru_cache(maxsize=10000) +def __cached_assemble(instructions, start_pc, bigendian): + pc = start_pc + labels = {} + out_instructions = [] + for instr in instructions: + m = re.fullmatch(r" *([a-zA-Z0-9_]+): *(#.*)?", instr) + if m is not None: + name = m.group(1) + if name in labels: + raise ValueError(f"label {name!r} defined multiple times") + labels[name] = pc + continue + m = re.fullmatch(r" *sv\.[a-zA-Z0-9_].*", instr) + if m is not None: + pc += 8 + else: + pc += 4 + out_instructions.append((pc, instr)) + last_pc = pc + + for (idx, (pc, instr)) in enumerate(tuple(out_instructions)): + for (label, target) in labels.items(): + if label in instr: + if pc < target: + sign = "" + addr = (target - pc + 4) + else: + sign = "-" + addr = (pc - target - 4) + + origin = instr + instr = instr.replace(label, f"{sign}0x{addr:X}") + break + out_instructions[idx] = instr + + for k, v in labels.items(): + out_instructions.append(f".set {k}, . - 0x{last_pc - v:X} # 0x{v:X}") + + return Program(list(SVP64Asm(out_instructions)), bigendian) -- 2.30.2