• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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