"""Generate an ISA test ROM from assembler-verified opcodes.

The opcodes below were produced by assembling isa_test.dsp with
the open21xx toolchain (as219x + ld21) and extracting the int_pm
section from the resulting ELF.  They serve as ground truth for
validating the radare2 disassembler plugin.
"""

import os
import sys


# Verified opcodes from open21xx assembler output.
# Source: examples/isa_test.dsp -> as219x -> ld21 -> dd
VERIFIED_OPCODES = [
    # Type 30: NOP
    (0x000000, "NOP"),
    # Type 6: Dreg = Imm16
    (0x412340, "AX0 = 0x1234"),
    (0x456781, "AX1 = 0x5678"),
    (0x4AAAA4, "AY0 = 0xAAAA"),
    (0x440002, "MX0 = 0x4000"),
    (0x420006, "MY0 = 0x2000"),
    # Type 7: Reg1 = Imm16
    (0x501000, "I0 = 0x0100"),
    (0x502001, "I1 = 0x0200"),
    (0x303000, "I4 = 0x0300"),
    (0x500014, "M0 = 1"),
    (0x500015, "M1 = 1"),
    (0x5FFFF7, "M3 = -1"),
    (0x300014, "M4 = 1"),
    (0x500008, "L0 = 0"),
    (0x300008, "L4 = 0"),
    (0x3000AE, "CNTR = 10"),
    # Type 17: Reg = Reg
    (0x0D00A0, "AR = AX0"),
    (0x0D00B1, "SI = AX1"),
    (0x0D00E2, "MR0 = MX0"),
    # Type 9: Compute (ALU)
    (0x22600F, "AR = AX0 + AY0"),
    (0x22E00F, "AR = AX0 - AY0"),
    (0x23800F, "AR = AX0 AND AY0"),
    (0x23A00F, "AR = AX0 OR AY0"),
    (0x23C00F, "AR = AX0 XOR AY0"),
    (0x22780F, "AR = PASS AX0"),
    (0x23380F, "AR = -AX0"),
    (0x23E00F, "AR = ABS AX0"),
    # Type 9: Compute (MAC)
    (0x20800F, "MR = MX0 * MY0 (SS)"),
    # Type 10a: Jump (unconditional, 16-bit addr)
    (0x1C0010, "JUMP _skip1"),
    (0x000000, "NOP"),
    # Type 10: Jump (conditional, 13-bit addr)
    (0x180010, "IF EQ JUMP _skip2"),
    (0x000000, "NOP"),
    # Type 10a: Call + Jump
    (0x1C0024, "CALL _sub1"),
    (0x1C0030, "JUMP _after_sub"),
    (0x000000, "NOP (in sub)"),
    # Type 20: RTS
    (0x0A00F0, "RTS"),
    (0x000000, "NOP (after sub)"),
    # Type 7: CNTR for loop
    (0x30004E, "CNTR = 4"),
    # Type 11: DO UNTIL
    (0x16002E, "DO _loop_end UNTIL CE"),
    (0x000000, "NOP (loop body)"),
    (0x000000, "NOP (loop end)"),
    # Type 15: Shift Immediate
    (0x0F0B04, "SR = LSHIFT SI BY 4 (HI)"),
    (0x0F4BFE, "SR = ASHIFT SI BY -2 (HI)"),
    # Type 18: Mode Control
    (0x0C0800, "DIS AR_SAT"),
    (0x0C0C00, "ENA AR_SAT"),
    # Type 25: Saturate MR
    (0x030000, "SAT MR"),
    # Type 33: Reg3 = short immediate
    (0x100005, "SE = 0"),
    # Type 10a: Infinite loop
    (0x1C0000, "JUMP _halt"),
]


def main():
    base_dir = os.path.dirname(os.path.abspath(__file__))
    rom_path = os.path.join(base_dir, "test_roms", "isa_test.bin")
    os.makedirs(os.path.dirname(rom_path), exist_ok=True)

    with open(rom_path, "wb") as f:
        for opcode, _label in VERIFIED_OPCODES:
            f.write(bytes([
                (opcode >> 16) & 0xFF,
                (opcode >> 8) & 0xFF,
                opcode & 0xFF,
            ]))

    print("Generated ISA test ROM with %d instructions at: %s"
          % (len(VERIFIED_OPCODES), rom_path))


if __name__ == "__main__":
    main()
