# unsp-dasm/dis.py: work-in-progress Sunplus u'nSP disassembler # Copyright (c) 2024 SergioFLS # SPDX-License-Identifier: MIT-0 # Reference: unSP ISA-1.2 Manual by Sunplus Technology (2004) from sys import argv from enum import Enum, auto class InstructionTypes(Enum): DATAPROCESSING_ALU6IMM = auto() DATAPROCESSING_ALU6DIR = auto() DATAPROCESSING_SHFT = auto() INTERRUPT = auto() FUNCTION_RETF = auto() FUNCTION_RETI = auto() UNKNOWN = auto() DATAPROCESSING_ALU6IMM_MASK = 0b0000_000_111_000000 DATAPROCESSING_ALU6IMM_UNIQUE = 0b0000_000_001_000000 DATAPROCESSING_ALU6DIR_MASK = 0b0000_000_111_000000 DATAPROCESSING_ALU6DIR_UNIQUE = 0b0000_000_111_000000 DATAPROCESSING_SHFT_MASK = 0b0000_000_1_000_00_000 DATAPROCESSING_SHFT_UNIQUE = 0b0000_000_1_000_00_000 INTERRUPT_MASK = 0b1111_000_1111111_00 INTERRUPT_UNIQUE = 0b1111_000_1010000_00 FUNCTION_RETF_MASK = 0b1111111111111111 FUNCTION_RETF_UNIQUE = 0b1001101010010000 FUNCTION_RETI_MASK = 0b1111111111111111 FUNCTION_RETI_UNIQUE = 0b1001101010011000 def determine_instruction_type(opcode: int): if (opcode & DATAPROCESSING_ALU6IMM_MASK) == DATAPROCESSING_ALU6IMM_UNIQUE: return InstructionTypes.DATAPROCESSING_ALU6IMM elif (opcode & DATAPROCESSING_ALU6DIR_MASK) == DATAPROCESSING_ALU6DIR_UNIQUE: return InstructionTypes.DATAPROCESSING_ALU6DIR elif (opcode & DATAPROCESSING_SHFT_MASK) == DATAPROCESSING_SHFT_UNIQUE: return InstructionTypes.DATAPROCESSING_SHFT elif (opcode & INTERRUPT_MASK) == INTERRUPT_UNIQUE: return InstructionTypes.INTERRUPT elif (opcode & FUNCTION_RETF_MASK) == FUNCTION_RETF_UNIQUE: return InstructionTypes.FUNCTION_RETF elif (opcode & FUNCTION_RETI_MASK) == FUNCTION_RETI_UNIQUE: return InstructionTypes.FUNCTION_RETI else: return InstructionTypes.UNKNOWN def disassemble(opcode: list): match determine_instruction_type(opcode[0]): case InstructionTypes.DATAPROCESSING_ALU6IMM: alu_op_fmt = { 0b0000: 'R{0} += {1};', 0b0001: 'R{0} += {1}, Carry;', 0b0010: 'R{0} -= {1};', 0b0011: 'R{0} -= {1}, Carry;', 0b0100: 'CMP R{0}, {1};', 0b0110: 'R{0} =- {1};', 0b1000: 'R{0} ^= {1};', 0b1001: 'R{0} = {1};', 0b1010: 'R{0} |= {1};', 0b1011: 'R{0} &= {1};', 0b1100: 'TEST R{0}, {1};', } alu_op = (opcode[0] & 0b1111_000_000_000000) >> 12 rd = (opcode[0] & 0b0000_111_000_000000) >> 9 im6 = opcode[0] & 0b0000_000_000_111111 return alu_op_fmt[alu_op].format(rd, im6) case InstructionTypes.DATAPROCESSING_ALU6DIR: alu_op_fmt = { 0b0000: 'R{0} += [{1}];', 0b0001: 'R{0} += [{1}], Carry;', 0b0010: 'R{0} -= [{1}];', 0b0011: 'R{0} -= [{1}], Carry;', 0b0100: 'CMP R{0}, [{1}];', 0b0110: 'R{0} =- [{1}];', 0b1000: 'R{0} ^= [{1}];', 0b1001: 'R{0} = [{1}];', 0b1010: 'R{0} |= [{1}];', 0b1011: 'R{0} &= [{1}];', 0b1100: 'TEST R{0}, [{1}];', } alu_op = (opcode[0] & 0b1111_000_000_000000) >> 12 rd = (opcode[0] & 0b0000_111_000_000000) >> 9 a6 = opcode[0] & 0b0000_000_000_111111 return alu_op_fmt[alu_op].format(rd, a6) case InstructionTypes.DATAPROCESSING_SHFT: shift_op_fmt = { 0b000: '', 0b001: 'ASR', 0b010: 'LSL', 0b011: 'LSR', 0b100: 'ROL', 0b101: 'ROR', } alu_op_fmt = { 0b0000: 'R{0} += R{1} {2} {3};', 0b0001: 'R{0} += R{1} {2} {3}, Carry;', 0b0010: 'R{0} -= R{1} {2} {3};', 0b0011: 'R{0} -= R{1} {2} {3}, Carry;', 0b0100: 'CMP R{0}, R{1} {2} {3};', 0b0110: 'R{0} =- R{1} {2} {3};', 0b1000: 'R{0} ^= R{1} {2} {3};', 0b1001: 'R{0} = R{1} {2} {3};', 0b1010: 'R{0} |= R{1} {2} {3};', 0b1011: 'R{0} &= R{1} {2} {3};', 0b1100: 'TEST R{0}, R{1} {2} {3};', } alu_op = (opcode[0] & 0b1111_000_0_000_00_000) >> 12 rd = (opcode[0] & 0b0000_111_0_000_00_000) >> 9 shift_op = (opcode[0] & 0b0000_000_0_111_00_000) >> 5 n = (opcode[0] & 0b0000_000_0_000_11_000) >> 3 rs = opcode[0] & 0b0000_000_0_000_00_111 return alu_op_fmt[alu_op].format(rd, rs, shift_op_fmt[shift_op], n+1) case InstructionTypes.INTERRUPT: irq = (opcode[0] & 0b01) != 0 fiq = (opcode[0] & 0b10) != 0 if irq and not fiq: return 'INT IRQ;' elif not irq and fiq: return 'INT FIQ;' elif irq and fiq: return 'INT FIQ,IRQ;' else: return 'INT OFF;' case InstructionTypes.FUNCTION_RETF: return 'RETF;' case InstructionTypes.FUNCTION_RETI: return 'RETI;' case _: return 'unknown instruction'