|
|
|
@ -1,29 +1,33 @@
|
|
|
|
|
#!/usr/bin/env python |
|
|
|
|
from collections import namedtuple |
|
|
|
|
import enum |
|
|
|
|
|
|
|
|
|
Opcode = namedtuple('Opcode', ('mnemonic', 'rx', 'ry', 'addr', 'immediate')) |
|
|
|
|
class rfield(enum.Enum): |
|
|
|
|
none, reg, imm_flag = range(3) |
|
|
|
|
|
|
|
|
|
Opcode = namedtuple('Opcode', ('mnemonic', 'rx', 'ry', 'addr')) |
|
|
|
|
|
|
|
|
|
opcodes = [ |
|
|
|
|
Opcode('halt', rx=False, ry=False, addr=False, immediate=False), |
|
|
|
|
Opcode('ret', rx=False, ry=False, addr=False, immediate=False), |
|
|
|
|
|
|
|
|
|
Opcode('shl', rx=True, ry=False, addr=False, immediate=False), |
|
|
|
|
Opcode('shr', rx=True, ry=False, addr=False, immediate=False), |
|
|
|
|
Opcode('rol', rx=True, ry=False, addr=False, immediate=False), |
|
|
|
|
Opcode('ror', rx=True, ry=False, addr=False, immediate=False), |
|
|
|
|
|
|
|
|
|
Opcode('nand', rx=True, ry=True, addr=False, immediate=False), |
|
|
|
|
Opcode('and', rx=True, ry=True, addr=False, immediate=False), |
|
|
|
|
Opcode('or', rx=True, ry=True, addr=False, immediate=False), |
|
|
|
|
Opcode('xor', rx=True, ry=True, addr=False, immediate=False), |
|
|
|
|
|
|
|
|
|
Opcode('load', rx=True, ry=False, addr=True, immediate=True), |
|
|
|
|
Opcode('store', rx=False, ry=True, addr=True, immediate=False), |
|
|
|
|
|
|
|
|
|
Opcode('breq', rx=True, ry=True, addr=True, immediate=False), |
|
|
|
|
Opcode('brneq', rx=True, ry=True, addr=True, immediate=False), |
|
|
|
|
Opcode('cleq', rx=True, ry=True, addr=True, immediate=False), |
|
|
|
|
Opcode('clneq', rx=True, ry=True, addr=True, immediate=False), |
|
|
|
|
Opcode('halt', rx=rfield.none, ry=rfield.none, addr=False), |
|
|
|
|
Opcode('ret', rx=rfield.none, ry=rfield.none, addr=False), |
|
|
|
|
|
|
|
|
|
Opcode('shl', rx=rfield.reg, ry=rfield.none, addr=False), |
|
|
|
|
Opcode('shr', rx=rfield.reg, ry=rfield.none, addr=False), |
|
|
|
|
Opcode('rol', rx=rfield.reg, ry=rfield.none, addr=False), |
|
|
|
|
Opcode('ror', rx=rfield.reg, ry=rfield.none, addr=False), |
|
|
|
|
|
|
|
|
|
Opcode('nand', rx=rfield.reg, ry=rfield.reg, addr=False), |
|
|
|
|
Opcode('and', rx=rfield.reg, ry=rfield.reg, addr=False), |
|
|
|
|
Opcode('or', rx=rfield.reg, ry=rfield.reg, addr=False), |
|
|
|
|
Opcode('xor', rx=rfield.reg, ry=rfield.reg, addr=False), |
|
|
|
|
|
|
|
|
|
Opcode('load', rx=rfield.reg, ry=rfield.imm_flag, addr=True), |
|
|
|
|
Opcode('store', rx=rfield.none, ry=rfield.reg, addr=True), |
|
|
|
|
|
|
|
|
|
Opcode('breq', rx=rfield.reg, ry=rfield.reg, addr=True), |
|
|
|
|
Opcode('brneq', rx=rfield.reg, ry=rfield.reg, addr=True), |
|
|
|
|
Opcode('cleq', rx=rfield.reg, ry=rfield.reg, addr=True), |
|
|
|
|
Opcode('clneq', rx=rfield.reg, ry=rfield.reg, addr=True), |
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
Instruction = namedtuple('Instruction', ['opcode', 'rx', 'ry', 'addr', 'immediate']) |
|
|
|
@ -42,11 +46,12 @@ def segment(binary, origin):
|
|
|
|
|
rx = (byte >> 2) & 3 |
|
|
|
|
ry = byte & 3 |
|
|
|
|
|
|
|
|
|
immediate = opcodes[opcode].immediate and ry == 3 |
|
|
|
|
immediate = opcodes[opcode].ry == rfield.imm_flag and ry == 3 |
|
|
|
|
|
|
|
|
|
valid = True |
|
|
|
|
if not opcodes[opcode].rx and rx != 0: valid = False |
|
|
|
|
if not opcodes[opcode].ry and not immediate and ry != 0: valid = False |
|
|
|
|
if opcodes[opcode].rx == rfield.none and rx != 0: valid = False |
|
|
|
|
if opcodes[opcode].ry == rfield.none and ry != 0: valid = False |
|
|
|
|
if opcodes[opcode].ry == rfield.imm_flag and ry not in (0, 3): valid = False |
|
|
|
|
if opcodes[opcode].addr and not immediate and ip + 2 >= len(binary): valid = False |
|
|
|
|
if immediate and ip + 1 >= len(binary): valid = False |
|
|
|
|
|
|
|
|
@ -80,9 +85,9 @@ def disasm(binary, origin = 0):
|
|
|
|
|
else: |
|
|
|
|
mnemonic = opcodes[contents.opcode].mnemonic |
|
|
|
|
fields = [] |
|
|
|
|
if opcodes[contents.opcode].rx: |
|
|
|
|
if opcodes[contents.opcode].rx == rfield.reg: |
|
|
|
|
fields.append(f'r{contents.rx}') |
|
|
|
|
if opcodes[contents.opcode].ry: |
|
|
|
|
if opcodes[contents.opcode].ry == rfield.reg: |
|
|
|
|
fields.append(f'r{contents.ry}') |
|
|
|
|
if contents.immediate is not None: |
|
|
|
|
fields.append(f'#{contents.immediate:02x}') |
|
|
|
|