initial
This commit is contained in:
commit
c501996b88
1 changed files with 142 additions and 0 deletions
142
dis.py
Normal file
142
dis.py
Normal file
|
@ -0,0 +1,142 @@
|
|||
# unsp-dasm/dis.py: work-in-progress Sunplus u'nSP disassembler
|
||||
# Copyright (c) 2024 SergioFLS <sergfls_public [the at symbol] disroot.org>
|
||||
# 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
|
||||
|
||||
OP = [int(argv[1],16), 0]
|
||||
if len(argv) >= 3:
|
||||
OP[1] = int(argv[2],16)
|
||||
|
||||
match determine_instruction_type(OP[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 = (OP[0] & 0b1111_000_000_000000) >> 12
|
||||
rd = (OP[0] & 0b0000_111_000_000000) >> 9
|
||||
im6 = OP[0] & 0b0000_000_000_111111
|
||||
|
||||
print(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 = (OP[0] & 0b1111_000_000_000000) >> 12
|
||||
rd = (OP[0] & 0b0000_111_000_000000) >> 9
|
||||
a6 = OP[0] & 0b0000_000_000_111111
|
||||
|
||||
print(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 = (OP[0] & 0b1111_000_0_000_00_000) >> 12
|
||||
rd = (OP[0] & 0b0000_111_0_000_00_000) >> 9
|
||||
shift_op = (OP[0] & 0b0000_000_0_111_00_000) >> 5
|
||||
n = (OP[0] & 0b0000_000_0_000_11_000) >> 3
|
||||
rs = OP[0] & 0b0000_000_0_000_00_111
|
||||
|
||||
print(alu_op_fmt[alu_op].format(rd, rs, shift_op_fmt[shift_op], n+1))
|
||||
case InstructionTypes.INTERRUPT:
|
||||
irq = (OP[0] & 0b01) != 0
|
||||
fiq = (OP[0] & 0b10) != 0
|
||||
|
||||
if irq and not fiq:
|
||||
print('INT IRQ;')
|
||||
elif not irq and fiq:
|
||||
print('INT FIQ;')
|
||||
elif irq and fiq:
|
||||
print('INT FIQ,IRQ;')
|
||||
else:
|
||||
print('INT OFF;')
|
||||
case InstructionTypes.FUNCTION_RETF:
|
||||
print('RETF;')
|
||||
case InstructionTypes.FUNCTION_RETI:
|
||||
print('RETI;')
|
||||
case _:
|
||||
print('unknown instruction')
|
Loading…
Reference in a new issue