-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdisassembler.py
More file actions
executable file
·163 lines (139 loc) · 4.68 KB
/
Copy pathdisassembler.py
File metadata and controls
executable file
·163 lines (139 loc) · 4.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# Custom CPU Disassembler
ALU_NAMES = ["ADC", "SBB", "AND", "ORA", "XOR", "CMP", "CPB", "CPC"]
LOAD_NAMES = ["LDA", "LDB", "LDC", "LDD", "STA", "STB", "STC", "STD"]
FLOW_NAMES = ["JMP", "JSR", "BRA", "BSR", "RET", "RTI", "???", "???"]
REG_NAMES = ["A", "B", "C", "D", "[DC]"]
REG_REG_NAMES = ["A,B", "A,C", "A,D", "B,A", "C,A", "D,A", "B,C", "C,B"]
COND_NAMES = ["UN", "ZF", "NZ", "NF", "NN", "CF", "NC", "VF"]
SHIFT_NAMES = ["SHL A", "SHR A", "ROL A", "ROR A", "SHL B", "SHR B", "ROL B", "ROR B"]
STACK_NAMES = ["PSH A", "PSH B", "PSH DC", "PSH FL", "PLL A", "PLL B", "PLL DC", "PLL FL"]
def disassemble_at(mem, addr):
op = mem[addr]
aaa = (op >> 5) & 7
bbb = (op >> 2) & 7
cc = op & 3
mnemonic = "???"
operand = ""
size = 1
### ALU and LOAD/STORE groups
if cc in [0,1]:
### ALU
if cc == 0:
mnemonic = ALU_NAMES[aaa]
### LOAD / STORE
elif cc == 1:
mnemonic = LOAD_NAMES[aaa]
mode = bbb
if mode == 0: # immediate
val = mem[addr + 1]
operand = f"#${val:02X}"
size = 2
elif mode == 1: # absolute
lo = mem[addr + 1]
hi = mem[addr + 2]
operand = f"${(hi<<8|lo):04X}"
size = 3
elif mode == 2: # abs+B
lo = mem[addr + 1]
hi = mem[addr + 2]
operand = f"${(hi<<8|lo):04X}+B"
size = 3
elif mode == 3: # abs+C
lo = mem[addr + 1]
hi = mem[addr + 2]
operand = f"${(hi<<8|lo):04X}+C"
size = 3
elif mode == 4:
operand = "[DC]"
size = 1
elif mode == 5: # (ptr)
lo = mem[addr + 1]
hi = mem[addr + 2]
operand = f"(${(hi<<8|lo):04X})"
size = 3
elif mode == 6: # (ptr)+B
lo = mem[addr + 1]
hi = mem[addr + 2]
operand = f"(${(hi<<8|lo):04X})+B"
size = 3
elif mode == 7:
operand = "[DC+B]"
size = 1
### FLOW
elif cc == 2:
base = FLOW_NAMES[aaa]
cond = COND_NAMES[bbb]
mnemonic = base + " " + cond
# BRA/BSR relative
if aaa in (2, 3):
offset = mem[addr + 1]
if offset & 0x80:
offset -= 0x100
target = (addr + 2 + offset) & 0xFFFF
operand = f"${target:04X}"
size = 2
elif aaa == 4: # RET
size = 1
else:
# JMP/JSR absolute
lo = mem[addr + 1]
hi = mem[addr + 2]
operand = f"${(hi<<8|lo):04X}"
size = 3
### SPECIAL
elif cc == 3:
if aaa == 0: # MOV
mnemonic = "MOV" + " " + REG_REG_NAMES[bbb]
size = 1
# INC (aaa=1) and DEC (aaa=3) use REG_NAMES table to decode bbb.
elif aaa == 1: # INC
mnemonic = "INC" + " " + REG_NAMES[bbb]
size = 1
elif aaa == 2: # DEC
mnemonic = "DEC" + " " + REG_NAMES[bbb]
size = 1
elif aaa == 3: # Shifts y Rotates
operand = SHIFT_NAMES[bbb]
size = 1
elif aaa == 4: # NEG/CLR
if bbb <= 3:
mnemonic = "NEG" + " " + REG_NAMES[bbb]
elif bbb <= 7:
mnemonic = "CLR" + " " + REG_NAMES[bbb-4]
size = 1
elif aaa == 5: # Flags
if bbb == 0:
mnemonic = "CLC"
elif bbb == 1:
mnemonic = "SEC"
elif bbb == 2:
mnemonic = "CLV"
elif bbb == 4:
mnemonic = "CLI"
elif bbb == 5:
mnemonic = "SEI"
size = 1
elif aaa == 6:
mnemonic = STACK_NAMES[bbb]
size = 1
elif aaa == 7: # System
if bbb == 0:
mnemonic = "NOP"
size = 1
elif bbb == 1:
mnemonic = "LSP"
size = 3
elif bbb == 2:
mnemonic = "HLT"
size = 1
### Return operation bytes and disassembly string
if size == 1:
bytes_str = f"{op:02X}"
elif size == 2:
bytes_str = f"{op:02X} {mem[addr+1]:02X}"
else:
bytes_str = f"{op:02X} {mem[addr+1]:02X} {mem[addr+2]:02X}"
return f"0x{addr:04X}: {bytes_str:<8}\n {mnemonic} {operand}", size
def disassemble(cpu):
line, size = disassemble_at(cpu.mem, cpu.PC)
return line