1 /* Capstone Disassembly Engine */
2 /* MOS65XX Backend by Sebastian Macke <sebastian@macke.de> 2018 */
3
4 #include "capstone/mos65xx.h"
5 #include "MOS65XXDisassembler.h"
6
7 typedef struct OpInfo {
8 mos65xx_insn ins;
9 mos65xx_address_mode am;
10 } OpInfo;
11
12 static const struct OpInfo OpInfoTable[]= {
13 { MOS65XX_INS_BRK , MOS65XX_AM_IMP }, // 0x00
14 { MOS65XX_INS_ORA , MOS65XX_AM_INDX }, // 0x01
15 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x02
16 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x03
17 { MOS65XX_INS_NOP , MOS65XX_AM_ZP }, // 0x04
18 { MOS65XX_INS_ORA , MOS65XX_AM_ZP }, // 0x05
19 { MOS65XX_INS_ASL , MOS65XX_AM_ZP }, // 0x06
20 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x07
21 { MOS65XX_INS_PHP , MOS65XX_AM_IMP }, // 0x08
22 { MOS65XX_INS_ORA , MOS65XX_AM_IMM }, // 0x09
23 { MOS65XX_INS_ASL , MOS65XX_AM_ACC }, // 0x0a
24 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x0b
25 { MOS65XX_INS_NOP , MOS65XX_AM_ABS }, // 0x0c
26 { MOS65XX_INS_ORA , MOS65XX_AM_ABS }, // 0x0d
27 { MOS65XX_INS_ASL , MOS65XX_AM_ABS }, // 0x0e
28 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x0f
29 { MOS65XX_INS_BPL , MOS65XX_AM_REL }, // 0x10
30 { MOS65XX_INS_ORA , MOS65XX_AM_INDY }, // 0x11
31 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x12
32 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x13
33 { MOS65XX_INS_NOP , MOS65XX_AM_ZPX }, // 0x14
34 { MOS65XX_INS_ORA , MOS65XX_AM_ZPX }, // 0x15
35 { MOS65XX_INS_ASL , MOS65XX_AM_ZPX }, // 0x16
36 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x17
37 { MOS65XX_INS_CLC , MOS65XX_AM_IMP }, // 0x18
38 { MOS65XX_INS_ORA , MOS65XX_AM_ABSY }, // 0x19
39 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0x1a
40 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x1b
41 { MOS65XX_INS_NOP , MOS65XX_AM_ABS }, // 0x1c
42 { MOS65XX_INS_ORA , MOS65XX_AM_ABSX }, // 0x1d
43 { MOS65XX_INS_ASL , MOS65XX_AM_ABSX }, // 0x1e
44 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x1f
45 { MOS65XX_INS_JSR , MOS65XX_AM_ABS }, // 0x20
46 { MOS65XX_INS_AND , MOS65XX_AM_INDX }, // 0x21
47 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x22
48 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x23
49 { MOS65XX_INS_BIT , MOS65XX_AM_ZP }, // 0x24
50 { MOS65XX_INS_AND , MOS65XX_AM_ZP }, // 0x25
51 { MOS65XX_INS_ROL , MOS65XX_AM_ZP }, // 0x26
52 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x27
53 { MOS65XX_INS_PLP , MOS65XX_AM_IMP }, // 0x28
54 { MOS65XX_INS_AND , MOS65XX_AM_IMM }, // 0x29
55 { MOS65XX_INS_ROL , MOS65XX_AM_ACC }, // 0x2a
56 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x2b
57 { MOS65XX_INS_BIT , MOS65XX_AM_ABS }, // 0x2c
58 { MOS65XX_INS_AND , MOS65XX_AM_ABS }, // 0x2d
59 { MOS65XX_INS_ROL , MOS65XX_AM_ABS }, // 0x2e
60 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x2f
61 { MOS65XX_INS_BMI , MOS65XX_AM_REL }, // 0x30
62 { MOS65XX_INS_AND , MOS65XX_AM_INDY }, // 0x31
63 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x32
64 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x33
65 { MOS65XX_INS_NOP , MOS65XX_AM_ZPX }, // 0x34
66 { MOS65XX_INS_AND , MOS65XX_AM_ZPX }, // 0x35
67 { MOS65XX_INS_ROL , MOS65XX_AM_ZPX }, // 0x36
68 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x37
69 { MOS65XX_INS_SEC , MOS65XX_AM_IMP }, // 0x38
70 { MOS65XX_INS_AND , MOS65XX_AM_ABSY }, // 0x39
71 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0x3a
72 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x3b
73 { MOS65XX_INS_NOP , MOS65XX_AM_ABSX }, // 0x3c
74 { MOS65XX_INS_AND , MOS65XX_AM_ABSX }, // 0x3d
75 { MOS65XX_INS_ROL , MOS65XX_AM_ABSX }, // 0x3e
76 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x3f
77 { MOS65XX_INS_RTI , MOS65XX_AM_IMP }, // 0x40
78 { MOS65XX_INS_EOR , MOS65XX_AM_INDX }, // 0x41
79 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x42
80 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x43
81 { MOS65XX_INS_NOP , MOS65XX_AM_ZP }, // 0x44
82 { MOS65XX_INS_EOR , MOS65XX_AM_ZP }, // 0x45
83 { MOS65XX_INS_LSR , MOS65XX_AM_ZP }, // 0x46
84 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x47
85 { MOS65XX_INS_PHA , MOS65XX_AM_IMP }, // 0x48
86 { MOS65XX_INS_EOR , MOS65XX_AM_IMM }, // 0x49
87 { MOS65XX_INS_LSR , MOS65XX_AM_ACC }, // 0x4a
88 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x4b
89 { MOS65XX_INS_JMP , MOS65XX_AM_ABS }, // 0x4c
90 { MOS65XX_INS_EOR , MOS65XX_AM_ABS }, // 0x4d
91 { MOS65XX_INS_LSR , MOS65XX_AM_ABS }, // 0x4e
92 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x4f
93 { MOS65XX_INS_BVC , MOS65XX_AM_REL }, // 0x50
94 { MOS65XX_INS_EOR , MOS65XX_AM_INDY }, // 0x51
95 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x52
96 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x53
97 { MOS65XX_INS_NOP , MOS65XX_AM_ZPX }, // 0x54
98 { MOS65XX_INS_EOR , MOS65XX_AM_ZPX }, // 0x55
99 { MOS65XX_INS_LSR , MOS65XX_AM_ZPX }, // 0x56
100 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x57
101 { MOS65XX_INS_CLI , MOS65XX_AM_IMP }, // 0x58
102 { MOS65XX_INS_EOR , MOS65XX_AM_ABSY }, // 0x59
103 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0x5a
104 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x5b
105 { MOS65XX_INS_NOP , MOS65XX_AM_ABSX }, // 0x5c
106 { MOS65XX_INS_EOR , MOS65XX_AM_ABSX }, // 0x5d
107 { MOS65XX_INS_LSR , MOS65XX_AM_ABSX }, // 0x5e
108 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x5f
109 { MOS65XX_INS_RTS , MOS65XX_AM_IMP }, // 0x60
110 { MOS65XX_INS_ADC , MOS65XX_AM_INDX }, // 0x61
111 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x62
112 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x63
113 { MOS65XX_INS_NOP , MOS65XX_AM_ZP }, // 0x64
114 { MOS65XX_INS_ADC , MOS65XX_AM_ZP }, // 0x65
115 { MOS65XX_INS_ROR , MOS65XX_AM_ZP }, // 0x66
116 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x67
117 { MOS65XX_INS_PLA , MOS65XX_AM_IMP }, // 0x68
118 { MOS65XX_INS_ADC , MOS65XX_AM_IMM }, // 0x69
119 { MOS65XX_INS_ROR , MOS65XX_AM_ACC }, // 0x6a
120 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x6b
121 { MOS65XX_INS_JMP , MOS65XX_AM_IND }, // 0x6c
122 { MOS65XX_INS_ADC , MOS65XX_AM_ABS }, // 0x6d
123 { MOS65XX_INS_ROR , MOS65XX_AM_ABS }, // 0x6e
124 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x6f
125 { MOS65XX_INS_BVS , MOS65XX_AM_REL }, // 0x70
126 { MOS65XX_INS_ADC , MOS65XX_AM_INDY }, // 0x71
127 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x72
128 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x73
129 { MOS65XX_INS_NOP , MOS65XX_AM_ZPX }, // 0x74
130 { MOS65XX_INS_ADC , MOS65XX_AM_ZPX }, // 0x75
131 { MOS65XX_INS_ROR , MOS65XX_AM_ZPX }, // 0x76
132 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x77
133 { MOS65XX_INS_SEI , MOS65XX_AM_IMP }, // 0x78
134 { MOS65XX_INS_ADC , MOS65XX_AM_ABSY }, // 0x79
135 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0x7a
136 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x7b
137 { MOS65XX_INS_NOP , MOS65XX_AM_ABSX }, // 0x7c
138 { MOS65XX_INS_ADC , MOS65XX_AM_ABSX }, // 0x7d
139 { MOS65XX_INS_ROR , MOS65XX_AM_ABSX }, // 0x7e
140 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x7f
141 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0x80
142 { MOS65XX_INS_STA , MOS65XX_AM_INDX }, // 0x81
143 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0x82
144 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x83
145 { MOS65XX_INS_STY , MOS65XX_AM_ZP }, // 0x84
146 { MOS65XX_INS_STA , MOS65XX_AM_ZP }, // 0x85
147 { MOS65XX_INS_STX , MOS65XX_AM_ZP }, // 0x86
148 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x87
149 { MOS65XX_INS_DEY , MOS65XX_AM_IMP }, // 0x88
150 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0x89
151 { MOS65XX_INS_TXA , MOS65XX_AM_IMP }, // 0x8a
152 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x8b
153 { MOS65XX_INS_STY , MOS65XX_AM_ABS }, // 0x8c
154 { MOS65XX_INS_STA , MOS65XX_AM_ABS }, // 0x8d
155 { MOS65XX_INS_STX , MOS65XX_AM_ABS }, // 0x8e
156 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x8f
157 { MOS65XX_INS_BCC , MOS65XX_AM_REL }, // 0x90
158 { MOS65XX_INS_STA , MOS65XX_AM_INDY }, // 0x91
159 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x92
160 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x93
161 { MOS65XX_INS_STY , MOS65XX_AM_ZPX }, // 0x94
162 { MOS65XX_INS_STA , MOS65XX_AM_ZPX }, // 0x95
163 { MOS65XX_INS_STX , MOS65XX_AM_ZPY }, // 0x96
164 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x97
165 { MOS65XX_INS_TYA , MOS65XX_AM_IMP }, // 0x98
166 { MOS65XX_INS_STA , MOS65XX_AM_ABSY }, // 0x99
167 { MOS65XX_INS_TXS , MOS65XX_AM_IMP }, // 0x9a
168 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x9b
169 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x9c
170 { MOS65XX_INS_STA , MOS65XX_AM_ABSX }, // 0x9d
171 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x9e
172 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0x9f
173 { MOS65XX_INS_LDY , MOS65XX_AM_IMM }, // 0xa0
174 { MOS65XX_INS_LDA , MOS65XX_AM_INDX }, // 0xa1
175 { MOS65XX_INS_LDX , MOS65XX_AM_IMM }, // 0xa2
176 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xa3
177 { MOS65XX_INS_LDY , MOS65XX_AM_ZP }, // 0xa4
178 { MOS65XX_INS_LDA , MOS65XX_AM_ZP }, // 0xa5
179 { MOS65XX_INS_LDX , MOS65XX_AM_ZP }, // 0xa6
180 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xa7
181 { MOS65XX_INS_TAY , MOS65XX_AM_IMP }, // 0xa8
182 { MOS65XX_INS_LDA , MOS65XX_AM_IMM }, // 0xa9
183 { MOS65XX_INS_TAX , MOS65XX_AM_IMP }, // 0xaa
184 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xab
185 { MOS65XX_INS_LDY , MOS65XX_AM_ABS }, // 0xac
186 { MOS65XX_INS_LDA , MOS65XX_AM_ABS }, // 0xad
187 { MOS65XX_INS_LDX , MOS65XX_AM_ABS }, // 0xae
188 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xaf
189 { MOS65XX_INS_BCS , MOS65XX_AM_REL }, // 0xb0
190 { MOS65XX_INS_LDA , MOS65XX_AM_INDY }, // 0xb1
191 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xb2
192 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xb3
193 { MOS65XX_INS_LDY , MOS65XX_AM_ZPX }, // 0xb4
194 { MOS65XX_INS_LDA , MOS65XX_AM_ZPX }, // 0xb5
195 { MOS65XX_INS_LDX , MOS65XX_AM_ZPY }, // 0xb6
196 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xb7
197 { MOS65XX_INS_CLV , MOS65XX_AM_IMP }, // 0xb8
198 { MOS65XX_INS_LDA , MOS65XX_AM_ABSY }, // 0xb9
199 { MOS65XX_INS_TSX , MOS65XX_AM_IMP }, // 0xba
200 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xbb
201 { MOS65XX_INS_LDY , MOS65XX_AM_ABSX }, // 0xbc
202 { MOS65XX_INS_LDA , MOS65XX_AM_ABSX }, // 0xbd
203 { MOS65XX_INS_LDX , MOS65XX_AM_ABSY }, // 0xbe
204 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xbf
205 { MOS65XX_INS_CPY , MOS65XX_AM_IMM }, // 0xc0
206 { MOS65XX_INS_CMP , MOS65XX_AM_INDX }, // 0xc1
207 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0xc2
208 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xc3
209 { MOS65XX_INS_CPY , MOS65XX_AM_ZP }, // 0xc4
210 { MOS65XX_INS_CMP , MOS65XX_AM_ZP }, // 0xc5
211 { MOS65XX_INS_DEC , MOS65XX_AM_ZP }, // 0xc6
212 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xc7
213 { MOS65XX_INS_INY , MOS65XX_AM_IMP }, // 0xc8
214 { MOS65XX_INS_CMP , MOS65XX_AM_IMM }, // 0xc9
215 { MOS65XX_INS_DEX , MOS65XX_AM_IMP }, // 0xca
216 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xcb
217 { MOS65XX_INS_CPY , MOS65XX_AM_ABS }, // 0xcc
218 { MOS65XX_INS_CMP , MOS65XX_AM_ABS }, // 0xcd
219 { MOS65XX_INS_DEC , MOS65XX_AM_ABS }, // 0xce
220 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xcf
221 { MOS65XX_INS_BNE , MOS65XX_AM_REL }, // 0xd0
222 { MOS65XX_INS_CMP , MOS65XX_AM_INDY }, // 0xd1
223 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xd2
224 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xd3
225 { MOS65XX_INS_NOP , MOS65XX_AM_ZPX }, // 0xd4
226 { MOS65XX_INS_CMP , MOS65XX_AM_ZPX }, // 0xd5
227 { MOS65XX_INS_DEC , MOS65XX_AM_ZPX }, // 0xd6
228 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xd7
229 { MOS65XX_INS_CLD , MOS65XX_AM_IMP }, // 0xd8
230 { MOS65XX_INS_CMP , MOS65XX_AM_ABSY }, // 0xd9
231 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0xda
232 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xdb
233 { MOS65XX_INS_NOP , MOS65XX_AM_ABSX }, // 0xdc
234 { MOS65XX_INS_CMP , MOS65XX_AM_ABSX }, // 0xdd
235 { MOS65XX_INS_DEC , MOS65XX_AM_ABSX }, // 0xde
236 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xdf
237 { MOS65XX_INS_CPX , MOS65XX_AM_IMM }, // 0xe0
238 { MOS65XX_INS_SBC , MOS65XX_AM_INDX }, // 0xe1
239 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0xe2
240 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xe3
241 { MOS65XX_INS_CPX , MOS65XX_AM_ZP }, // 0xe4
242 { MOS65XX_INS_SBC , MOS65XX_AM_ZP }, // 0xe5
243 { MOS65XX_INS_INC , MOS65XX_AM_ZP }, // 0xe6
244 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xe7
245 { MOS65XX_INS_INX , MOS65XX_AM_IMP }, // 0xe8
246 { MOS65XX_INS_SBC , MOS65XX_AM_IMM }, // 0xe9
247 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0xea
248 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xeb
249 { MOS65XX_INS_CPX , MOS65XX_AM_ABS }, // 0xec
250 { MOS65XX_INS_SBC , MOS65XX_AM_ABS }, // 0xed
251 { MOS65XX_INS_INC , MOS65XX_AM_ABS }, // 0xee
252 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xef
253 { MOS65XX_INS_BEQ , MOS65XX_AM_REL }, // 0xf0
254 { MOS65XX_INS_SBC , MOS65XX_AM_INDY }, // 0xf1
255 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xf2
256 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xf3
257 { MOS65XX_INS_NOP , MOS65XX_AM_ZPX }, // 0xf4
258 { MOS65XX_INS_SBC , MOS65XX_AM_ZPX }, // 0xf5
259 { MOS65XX_INS_INC , MOS65XX_AM_ZPX }, // 0xf6
260 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xf7
261 { MOS65XX_INS_SED , MOS65XX_AM_IMP }, // 0xf8
262 { MOS65XX_INS_SBC , MOS65XX_AM_ABSY }, // 0xf9
263 { MOS65XX_INS_NOP , MOS65XX_AM_IMP }, // 0xfa
264 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xfb
265 { MOS65XX_INS_NOP , MOS65XX_AM_ABSX }, // 0xfc
266 { MOS65XX_INS_SBC , MOS65XX_AM_ABSX }, // 0xfd
267 { MOS65XX_INS_INC , MOS65XX_AM_ABSX }, // 0xfe
268 { MOS65XX_INS_INVALID, MOS65XX_AM_NONE }, // 0xff
269 };
270
271 static const char* RegNames[] = {
272 "invalid", "A", "X", "Y", "P", "SP"
273 };
274
275 #ifndef CAPSTONE_DIET
276 static const char* GroupNames[] = {
277 NULL,
278 "jump",
279 "call",
280 "ret",
281 NULL,
282 "iret",
283 "branch_relative"
284 };
285
286 typedef struct InstructionInfo {
287 const char* name;
288 mos65xx_group_type group_type;
289 mos65xx_reg write, read;
290 bool modifies_status;
291 } InstructionInfo;
292
293 static const struct InstructionInfo InstructionInfoTable[]= {
294 { "invalid", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, false },
295 { "adc", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true },
296 { "and", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true },
297 { "asl", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
298 { "bcc", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false },
299 { "bcs", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false },
300 { "beq", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false },
301 { "bit", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
302 { "bmi", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false },
303 { "bne", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false },
304 { "bpl", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false },
305 { "brk", MOS65XX_GRP_INVALID, MOS65XX_REG_SP, MOS65XX_REG_INVALID, false },
306 { "bvc", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false },
307 { "bvs", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false },
308 { "clc", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
309 { "cld", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
310 { "cli", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
311 { "clv", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
312 { "cmp", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_ACC, true },
313 { "cpx", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_X, true },
314 { "cpy", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_Y, true },
315 { "dec", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
316 { "dex", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_X, true },
317 { "dey", MOS65XX_GRP_INVALID, MOS65XX_REG_Y, MOS65XX_REG_Y, true },
318 { "eor", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
319 { "inc", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
320 { "inx", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_X, true },
321 { "iny", MOS65XX_GRP_INVALID, MOS65XX_REG_Y, MOS65XX_REG_Y, true },
322 { "jmp", MOS65XX_GRP_JUMP, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, false },
323 { "jsr", MOS65XX_GRP_CALL, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, false },
324 { "lda", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true },
325 { "ldx", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_INVALID, true },
326 { "ldy", MOS65XX_GRP_INVALID, MOS65XX_REG_Y, MOS65XX_REG_INVALID, true },
327 { "lsr", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
328 { "nop", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, false },
329 { "ora", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true },
330 { "pha", MOS65XX_GRP_INVALID, MOS65XX_REG_SP, MOS65XX_REG_ACC, false },
331 { "pla", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_SP, true },
332 { "php", MOS65XX_GRP_INVALID, MOS65XX_REG_SP, MOS65XX_REG_P, false },
333 { "plp", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_SP, true },
334 { "rol", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
335 { "ror", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
336 { "rti", MOS65XX_GRP_IRET, MOS65XX_REG_SP, MOS65XX_REG_INVALID, true },
337 { "rts", MOS65XX_GRP_RET, MOS65XX_REG_SP, MOS65XX_REG_INVALID, false },
338 { "sbc", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true },
339 { "sec", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
340 { "sed", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
341 { "sei", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true },
342 { "sta", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_ACC, false },
343 { "stx", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_X, false },
344 { "sty", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_Y, false },
345 { "tax", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_ACC, true },
346 { "tay", MOS65XX_GRP_INVALID, MOS65XX_REG_Y, MOS65XX_REG_ACC, true },
347 { "tsx", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_SP, true },
348 { "txa", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_X, true },
349 { "txs", MOS65XX_GRP_INVALID, MOS65XX_REG_SP, MOS65XX_REG_X, true },
350 { "tya", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_Y, true },
351 };
352 #endif
353
getInstructionLength(mos65xx_address_mode am)354 static int getInstructionLength(mos65xx_address_mode am)
355 {
356 switch(am) {
357 case MOS65XX_AM_NONE:
358 case MOS65XX_AM_ACC:
359 case MOS65XX_AM_IMP:
360 return 1;
361
362 case MOS65XX_AM_IMM:
363 case MOS65XX_AM_ZPX:
364 case MOS65XX_AM_ZPY:
365 case MOS65XX_AM_ZP:
366 case MOS65XX_AM_REL:
367 case MOS65XX_AM_INDX:
368 case MOS65XX_AM_INDY:
369 return 2;
370
371 case MOS65XX_AM_ABS:
372 case MOS65XX_AM_ABSX:
373 case MOS65XX_AM_ABSY:
374 case MOS65XX_AM_IND:
375 return 3;
376 default:
377 return 1;
378 }
379 }
380
381 #ifndef CAPSTONE_DIET
fillDetails(MCInst * MI,unsigned char opcode)382 static void fillDetails(MCInst *MI, unsigned char opcode)
383 {
384 cs_detail *detail = MI->flat_insn->detail;
385 mos65xx_insn ins = OpInfoTable[opcode].ins;
386 mos65xx_address_mode am = OpInfoTable[opcode].am;
387
388 detail->mos65xx.am = am;
389 detail->mos65xx.modifies_flags = InstructionInfoTable[ins].modifies_status;
390 detail->groups_count = 0;
391 detail->regs_read_count = 0;
392 detail->regs_write_count = 0;
393 detail->mos65xx.op_count = 0;
394
395 if (InstructionInfoTable[ins].group_type != MOS65XX_GRP_INVALID) {
396 detail->groups[0] = InstructionInfoTable[ins].group_type;
397 detail->groups_count++;
398 }
399
400 if (InstructionInfoTable[ins].read != MOS65XX_REG_INVALID) {
401 detail->regs_read[detail->regs_read_count++] = InstructionInfoTable[ins].read;
402 } else if (OpInfoTable[opcode].am == MOS65XX_AM_ACC) {
403 detail->regs_read[detail->regs_read_count++] = MOS65XX_REG_ACC;
404 } else if (OpInfoTable[opcode].am == MOS65XX_AM_INDY || OpInfoTable[opcode].am == MOS65XX_AM_ABSY || OpInfoTable[opcode].am == MOS65XX_AM_ZPY) {
405 detail->regs_read[detail->regs_read_count++] = MOS65XX_REG_Y;
406 } else if (OpInfoTable[opcode].am == MOS65XX_AM_INDX || OpInfoTable[opcode].am == MOS65XX_AM_ABSX || OpInfoTable[opcode].am == MOS65XX_AM_ZPX) {
407 detail->regs_read[detail->regs_read_count++] = MOS65XX_REG_X;
408 }
409
410 if (InstructionInfoTable[ins].write != MOS65XX_REG_INVALID) {
411 detail->regs_write[detail->regs_write_count++] = InstructionInfoTable[ins].write;
412 } else if (OpInfoTable[opcode].am == MOS65XX_AM_ACC) {
413 detail->regs_write[detail->regs_write_count++] = MOS65XX_REG_ACC;
414 }
415
416 if (InstructionInfoTable[ins].modifies_status) {
417 detail->regs_write[detail->regs_write_count++] = MOS65XX_REG_P;
418 }
419
420 switch(am) {
421 case MOS65XX_AM_IMP:
422 case MOS65XX_AM_REL:
423 break;
424 case MOS65XX_AM_IMM:
425 detail->mos65xx.operands[detail->mos65xx.op_count].type = MOS65XX_OP_IMM;
426 detail->mos65xx.operands[detail->mos65xx.op_count].mem = MI->Operands[0].ImmVal;
427 detail->mos65xx.op_count++;
428 break;
429 case MOS65XX_AM_ACC:
430 detail->mos65xx.operands[detail->mos65xx.op_count].type = MOS65XX_OP_REG;
431 detail->mos65xx.operands[detail->mos65xx.op_count].reg = MOS65XX_REG_ACC;
432 detail->mos65xx.op_count++;
433 break;
434 default:
435 detail->mos65xx.operands[detail->mos65xx.op_count].type = MOS65XX_OP_MEM;
436 detail->mos65xx.operands[detail->mos65xx.op_count].mem = MI->Operands[0].ImmVal;
437 detail->mos65xx.op_count++;
438 break;
439 }
440 }
441 #endif
442
MOS65XX_printInst(MCInst * MI,struct SStream * O,void * PrinterInfo)443 void MOS65XX_printInst(MCInst *MI, struct SStream *O, void *PrinterInfo)
444 {
445 #ifndef CAPSTONE_DIET
446 unsigned char opcode = MI->Opcode;
447 unsigned int value = MI->Operands[0].ImmVal;
448
449 SStream_concat0(O, InstructionInfoTable[OpInfoTable[MI->Opcode].ins].name);
450
451 switch (OpInfoTable[opcode].am) {
452 default:
453 break;
454
455 case MOS65XX_AM_IMP:
456 break;
457
458 case MOS65XX_AM_ACC:
459 SStream_concat(O, " a");
460 break;
461
462 case MOS65XX_AM_ABS:
463 SStream_concat(O, " $0x%04x", value);
464 break;
465
466 case MOS65XX_AM_IMM:
467 SStream_concat(O, " #$0x%02x", value);
468 break;
469
470 case MOS65XX_AM_ZP:
471 SStream_concat(O, " $0x%02x", value);
472 break;
473
474 case MOS65XX_AM_ABSX:
475 SStream_concat(O, " $0x%04x, x", value);
476 break;
477
478 case MOS65XX_AM_ABSY:
479 SStream_concat(O, " $0x%04x, y", value);
480 break;
481
482 case MOS65XX_AM_ZPX:
483 SStream_concat(O, " $0x%02x, x", value);
484 break;
485
486 case MOS65XX_AM_ZPY:
487 SStream_concat(O, " $0x%02x, y", value);
488 break;
489
490 case MOS65XX_AM_REL:
491 SStream_concat(O, " $0x%04x", MI->address + (signed char) value + 2);
492 break;
493
494 case MOS65XX_AM_IND:
495 SStream_concat(O, " ($0x%04x)", value);
496 break;
497
498 case MOS65XX_AM_INDX:
499 SStream_concat(O, " ($0x%02x, x)", value);
500 break;
501
502 case MOS65XX_AM_INDY:
503 SStream_concat(O, " ($0x%02x), y", value);
504 break;
505 }
506 #endif
507 }
508
MOS65XX_getInstruction(csh ud,const uint8_t * code,size_t code_len,MCInst * MI,uint16_t * size,uint64_t address,void * inst_info)509 bool MOS65XX_getInstruction(csh ud, const uint8_t *code, size_t code_len,
510 MCInst *MI, uint16_t *size, uint64_t address, void *inst_info)
511 {
512 unsigned char opcode;
513 unsigned char len;
514 mos65xx_insn ins;
515
516 if (code_len == 0) {
517 *size = 1;
518 return false;
519 }
520
521 opcode = code[0];
522 ins = OpInfoTable[opcode].ins;
523 if (ins == MOS65XX_INS_INVALID) {
524 *size = 1;
525 return false;
526 }
527
528 len = getInstructionLength(OpInfoTable[opcode].am);
529 if (code_len < len) {
530 *size = 1;
531 return false;
532 }
533
534 MI->address = address;
535 MI->Opcode = opcode;
536 MI->OpcodePub = ins;
537 MI->size = 0;
538
539 *size = len;
540 if (len == 2) {
541 MCOperand_CreateImm0(MI, code[1]);
542 } else
543 if (len == 3) {
544 MCOperand_CreateImm0(MI, (code[2]<<8) | code[1]);
545 }
546 #ifndef CAPSTONE_DIET
547 if (MI->flat_insn->detail) {
548 fillDetails(MI, opcode);
549 }
550 #endif
551
552 return true;
553 }
554
MOS65XX_insn_name(csh handle,unsigned int id)555 const char *MOS65XX_insn_name(csh handle, unsigned int id)
556 {
557 #ifdef CAPSTONE_DIET
558 return NULL;
559 #else
560 if (id >= ARR_SIZE(InstructionInfoTable)) {
561 return NULL;
562 }
563 return InstructionInfoTable[id].name;
564 #endif
565 }
566
MOS65XX_reg_name(csh handle,unsigned int reg)567 const char* MOS65XX_reg_name(csh handle, unsigned int reg)
568 {
569 #ifdef CAPSTONE_DIET
570 return NULL;
571 #else
572 if (reg >= ARR_SIZE(RegNames)) {
573 return NULL;
574 }
575 return RegNames[(int)reg];
576 #endif
577 }
578
MOS65XX_get_insn_id(cs_struct * h,cs_insn * insn,unsigned int id)579 void MOS65XX_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
580 {
581 if (id < 256) {
582 insn->id = OpInfoTable[id].ins;
583 }
584 }
585
MOS65XX_group_name(csh handle,unsigned int id)586 const char *MOS65XX_group_name(csh handle, unsigned int id)
587 {
588 #ifdef CAPSTONE_DIET
589 return NULL;
590 #else
591 if (id >= ARR_SIZE(GroupNames)) {
592 return NULL;
593 }
594 return GroupNames[(int)id];
595 #endif
596 }
597