1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* instr.c */ |
4 | /* */ |
5 | /* Instruction encoding for the ca65 macroassembler */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 1998-2012, Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | #include <stdlib.h> |
37 | #include <string.h> |
38 | #include <ctype.h> |
39 | |
40 | /* common */ |
41 | #include "addrsize.h" |
42 | #include "attrib.h" |
43 | #include "bitops.h" |
44 | #include "check.h" |
45 | #include "mmodel.h" |
46 | |
47 | /* ca65 */ |
48 | #include "asserts.h" |
49 | #include "ea.h" |
50 | #include "ea65.h" |
51 | #include "easw16.h" |
52 | #include "error.h" |
53 | #include "expr.h" |
54 | #include "global.h" |
55 | #include "instr.h" |
56 | #include "nexttok.h" |
57 | #include "objcode.h" |
58 | #include "spool.h" |
59 | #include "studyexpr.h" |
60 | #include "symtab.h" |
61 | |
62 | |
63 | |
64 | /*****************************************************************************/ |
65 | /* Forwards */ |
66 | /*****************************************************************************/ |
67 | |
68 | |
69 | |
70 | static void PutPCRel8 (const InsDesc* Ins); |
71 | /* Handle branches with a 8 bit distance */ |
72 | |
73 | static void PutPCRel16 (const InsDesc* Ins); |
74 | /* Handle branches with an 16 bit distance and PER */ |
75 | |
76 | static void PutPCRel4510 (const InsDesc* Ins); |
77 | /* Handle branches with a 16 bit distance for 4510 */ |
78 | |
79 | static void PutBlockMove (const InsDesc* Ins); |
80 | /* Handle the blockmove instructions (65816) */ |
81 | |
82 | static void PutBlockTransfer (const InsDesc* Ins); |
83 | /* Handle the block transfer instructions (HuC6280) */ |
84 | |
85 | static void PutBitBranch (const InsDesc* Ins); |
86 | /* Handle 65C02 branch on bit condition */ |
87 | |
88 | static void PutREP (const InsDesc* Ins); |
89 | /* Emit a REP instruction, track register sizes */ |
90 | |
91 | static void PutSEP (const InsDesc* Ins); |
92 | /* Emit a SEP instruction (65816), track register sizes */ |
93 | |
94 | static void PutTAMn (const InsDesc* Ins); |
95 | /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with |
96 | ** implicit addressing mode, the opcode byte in the table is actually the |
97 | ** second operand byte. The TAM instruction is the more generic form, it takes |
98 | ** an immediate argument. |
99 | */ |
100 | |
101 | static void PutTMA (const InsDesc* Ins); |
102 | /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit |
103 | ** in the argument byte may be set. |
104 | */ |
105 | |
106 | static void PutTMAn (const InsDesc* Ins); |
107 | /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with |
108 | ** implicit addressing mode, the opcode byte in the table is actually the |
109 | ** second operand byte. The TAM instruction is the more generic form, it takes |
110 | ** an immediate argument. |
111 | */ |
112 | |
113 | static void PutTST (const InsDesc* Ins); |
114 | /* Emit a TST instruction (HuC6280). */ |
115 | |
116 | static void PutJMP (const InsDesc* Ins); |
117 | /* Handle the jump instruction for the 6502. Problem is that these chips have |
118 | ** a bug: If the address crosses a page, the upper byte gets not corrected and |
119 | ** the instruction will fail. The PutJmp function will add a linker assertion |
120 | ** to check for this case and is otherwise identical to PutAll. |
121 | */ |
122 | |
123 | static void PutRTS (const InsDesc* Ins attribute ((unused))); |
124 | /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if |
125 | ** the enclosing scope is FAR. |
126 | */ |
127 | |
128 | static void PutAll (const InsDesc* Ins); |
129 | /* Handle all other instructions */ |
130 | |
131 | static void Put4510 (const InsDesc* Ins); |
132 | /* Handle instructions of 4510 not matching any EATab */ |
133 | |
134 | static void PutSweet16 (const InsDesc* Ins); |
135 | /* Handle a generic sweet16 instruction */ |
136 | |
137 | static void PutSweet16Branch (const InsDesc* Ins); |
138 | /* Handle a sweet16 branch instruction */ |
139 | |
140 | |
141 | |
142 | /*****************************************************************************/ |
143 | /* Data */ |
144 | /*****************************************************************************/ |
145 | |
146 | |
147 | |
148 | /* Empty instruction table */ |
149 | static const struct { |
150 | unsigned Count; |
151 | } InsTabNone = { |
152 | 0 |
153 | }; |
154 | |
155 | /* Instruction table for the 6502 */ |
156 | static const struct { |
157 | unsigned Count; |
158 | InsDesc Ins[56]; |
159 | } InsTab6502 = { |
160 | sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]), |
161 | { |
162 | { "ADC" , 0x080A26C, 0x60, 0, PutAll }, |
163 | { "AND" , 0x080A26C, 0x20, 0, PutAll }, |
164 | { "ASL" , 0x000006e, 0x02, 1, PutAll }, |
165 | { "BCC" , 0x0020000, 0x90, 0, PutPCRel8 }, |
166 | { "BCS" , 0x0020000, 0xb0, 0, PutPCRel8 }, |
167 | { "BEQ" , 0x0020000, 0xf0, 0, PutPCRel8 }, |
168 | { "BIT" , 0x000000C, 0x00, 2, PutAll }, |
169 | { "BMI" , 0x0020000, 0x30, 0, PutPCRel8 }, |
170 | { "BNE" , 0x0020000, 0xd0, 0, PutPCRel8 }, |
171 | { "BPL" , 0x0020000, 0x10, 0, PutPCRel8 }, |
172 | { "BRK" , 0x0000001, 0x00, 0, PutAll }, |
173 | { "BVC" , 0x0020000, 0x50, 0, PutPCRel8 }, |
174 | { "BVS" , 0x0020000, 0x70, 0, PutPCRel8 }, |
175 | { "CLC" , 0x0000001, 0x18, 0, PutAll }, |
176 | { "CLD" , 0x0000001, 0xd8, 0, PutAll }, |
177 | { "CLI" , 0x0000001, 0x58, 0, PutAll }, |
178 | { "CLV" , 0x0000001, 0xb8, 0, PutAll }, |
179 | { "CMP" , 0x080A26C, 0xc0, 0, PutAll }, |
180 | { "CPX" , 0x080000C, 0xe0, 1, PutAll }, |
181 | { "CPY" , 0x080000C, 0xc0, 1, PutAll }, |
182 | { "DEC" , 0x000006C, 0x00, 3, PutAll }, |
183 | { "DEX" , 0x0000001, 0xca, 0, PutAll }, |
184 | { "DEY" , 0x0000001, 0x88, 0, PutAll }, |
185 | { "EOR" , 0x080A26C, 0x40, 0, PutAll }, |
186 | { "INC" , 0x000006c, 0x00, 4, PutAll }, |
187 | { "INX" , 0x0000001, 0xe8, 0, PutAll }, |
188 | { "INY" , 0x0000001, 0xc8, 0, PutAll }, |
189 | { "JMP" , 0x0000808, 0x4c, 6, PutJMP }, |
190 | { "JSR" , 0x0000008, 0x20, 7, PutAll }, |
191 | { "LDA" , 0x080A26C, 0xa0, 0, PutAll }, |
192 | { "LDX" , 0x080030C, 0xa2, 1, PutAll }, |
193 | { "LDY" , 0x080006C, 0xa0, 1, PutAll }, |
194 | { "LSR" , 0x000006F, 0x42, 1, PutAll }, |
195 | { "NOP" , 0x0000001, 0xea, 0, PutAll }, |
196 | { "ORA" , 0x080A26C, 0x00, 0, PutAll }, |
197 | { "PHA" , 0x0000001, 0x48, 0, PutAll }, |
198 | { "PHP" , 0x0000001, 0x08, 0, PutAll }, |
199 | { "PLA" , 0x0000001, 0x68, 0, PutAll }, |
200 | { "PLP" , 0x0000001, 0x28, 0, PutAll }, |
201 | { "ROL" , 0x000006F, 0x22, 1, PutAll }, |
202 | { "ROR" , 0x000006F, 0x62, 1, PutAll }, |
203 | { "RTI" , 0x0000001, 0x40, 0, PutAll }, |
204 | { "RTS" , 0x0000001, 0x60, 0, PutAll }, |
205 | { "SBC" , 0x080A26C, 0xe0, 0, PutAll }, |
206 | { "SEC" , 0x0000001, 0x38, 0, PutAll }, |
207 | { "SED" , 0x0000001, 0xf8, 0, PutAll }, |
208 | { "SEI" , 0x0000001, 0x78, 0, PutAll }, |
209 | { "STA" , 0x000A26C, 0x80, 0, PutAll }, |
210 | { "STX" , 0x000010c, 0x82, 1, PutAll }, |
211 | { "STY" , 0x000002c, 0x80, 1, PutAll }, |
212 | { "TAX" , 0x0000001, 0xaa, 0, PutAll }, |
213 | { "TAY" , 0x0000001, 0xa8, 0, PutAll }, |
214 | { "TSX" , 0x0000001, 0xba, 0, PutAll }, |
215 | { "TXA" , 0x0000001, 0x8a, 0, PutAll }, |
216 | { "TXS" , 0x0000001, 0x9a, 0, PutAll }, |
217 | { "TYA" , 0x0000001, 0x98, 0, PutAll } |
218 | } |
219 | }; |
220 | |
221 | /* Instruction table for the 6502 with illegal instructions */ |
222 | static const struct { |
223 | unsigned Count; |
224 | InsDesc Ins[75]; |
225 | } InsTab6502X = { |
226 | sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]), |
227 | { |
228 | { "ADC" , 0x080A26C, 0x60, 0, PutAll }, |
229 | { "ALR" , 0x0800000, 0x4B, 0, PutAll }, /* X */ |
230 | { "ANC" , 0x0800000, 0x0B, 0, PutAll }, /* X */ |
231 | { "AND" , 0x080A26C, 0x20, 0, PutAll }, |
232 | { "ANE" , 0x0800000, 0x8B, 0, PutAll }, /* X */ |
233 | { "ARR" , 0x0800000, 0x6B, 0, PutAll }, /* X */ |
234 | { "ASL" , 0x000006e, 0x02, 1, PutAll }, |
235 | { "AXS" , 0x0800000, 0xCB, 0, PutAll }, /* X */ |
236 | { "BCC" , 0x0020000, 0x90, 0, PutPCRel8 }, |
237 | { "BCS" , 0x0020000, 0xb0, 0, PutPCRel8 }, |
238 | { "BEQ" , 0x0020000, 0xf0, 0, PutPCRel8 }, |
239 | { "BIT" , 0x000000C, 0x00, 2, PutAll }, |
240 | { "BMI" , 0x0020000, 0x30, 0, PutPCRel8 }, |
241 | { "BNE" , 0x0020000, 0xd0, 0, PutPCRel8 }, |
242 | { "BPL" , 0x0020000, 0x10, 0, PutPCRel8 }, |
243 | { "BRK" , 0x0000001, 0x00, 0, PutAll }, |
244 | { "BVC" , 0x0020000, 0x50, 0, PutPCRel8 }, |
245 | { "BVS" , 0x0020000, 0x70, 0, PutPCRel8 }, |
246 | { "CLC" , 0x0000001, 0x18, 0, PutAll }, |
247 | { "CLD" , 0x0000001, 0xd8, 0, PutAll }, |
248 | { "CLI" , 0x0000001, 0x58, 0, PutAll }, |
249 | { "CLV" , 0x0000001, 0xb8, 0, PutAll }, |
250 | { "CMP" , 0x080A26C, 0xc0, 0, PutAll }, |
251 | { "CPX" , 0x080000C, 0xe0, 1, PutAll }, |
252 | { "CPY" , 0x080000C, 0xc0, 1, PutAll }, |
253 | { "DCP" , 0x000A26C, 0xC3, 0, PutAll }, /* X */ |
254 | { "DEC" , 0x000006C, 0x00, 3, PutAll }, |
255 | { "DEX" , 0x0000001, 0xca, 0, PutAll }, |
256 | { "DEY" , 0x0000001, 0x88, 0, PutAll }, |
257 | { "EOR" , 0x080A26C, 0x40, 0, PutAll }, |
258 | { "INC" , 0x000006c, 0x00, 4, PutAll }, |
259 | { "INX" , 0x0000001, 0xe8, 0, PutAll }, |
260 | { "INY" , 0x0000001, 0xc8, 0, PutAll }, |
261 | { "ISC" , 0x000A26C, 0xE3, 0, PutAll }, /* X */ |
262 | { "JAM" , 0x0000001, 0x02, 0, PutAll }, /* X */ |
263 | { "JMP" , 0x0000808, 0x4c, 6, PutJMP }, |
264 | { "JSR" , 0x0000008, 0x20, 7, PutAll }, |
265 | { "LAS" , 0x0000200, 0xBB, 0, PutAll }, /* X */ |
266 | { "LAX" , 0x080A30C, 0xA3, 11, PutAll }, /* X */ |
267 | { "LDA" , 0x080A26C, 0xa0, 0, PutAll }, |
268 | { "LDX" , 0x080030C, 0xa2, 1, PutAll }, |
269 | { "LDY" , 0x080006C, 0xa0, 1, PutAll }, |
270 | { "LSR" , 0x000006F, 0x42, 1, PutAll }, |
271 | { "NOP" , 0x080006D, 0x00, 10, PutAll }, /* X */ |
272 | { "ORA" , 0x080A26C, 0x00, 0, PutAll }, |
273 | { "PHA" , 0x0000001, 0x48, 0, PutAll }, |
274 | { "PHP" , 0x0000001, 0x08, 0, PutAll }, |
275 | { "PLA" , 0x0000001, 0x68, 0, PutAll }, |
276 | { "PLP" , 0x0000001, 0x28, 0, PutAll }, |
277 | { "RLA" , 0x000A26C, 0x23, 0, PutAll }, /* X */ |
278 | { "ROL" , 0x000006F, 0x22, 1, PutAll }, |
279 | { "ROR" , 0x000006F, 0x62, 1, PutAll }, |
280 | { "RRA" , 0x000A26C, 0x63, 0, PutAll }, /* X */ |
281 | { "RTI" , 0x0000001, 0x40, 0, PutAll }, |
282 | { "RTS" , 0x0000001, 0x60, 0, PutAll }, |
283 | { "SAX" , 0x000810C, 0x83, 1, PutAll }, /* X */ |
284 | { "SBC" , 0x080A26C, 0xe0, 0, PutAll }, |
285 | { "SEC" , 0x0000001, 0x38, 0, PutAll }, |
286 | { "SED" , 0x0000001, 0xf8, 0, PutAll }, |
287 | { "SEI" , 0x0000001, 0x78, 0, PutAll }, |
288 | { "SHA" , 0x0002200, 0x93, 1, PutAll }, /* X */ |
289 | { "SHX" , 0x0000200, 0x9e, 1, PutAll }, /* X */ |
290 | { "SHY" , 0x0000040, 0x9c, 1, PutAll }, /* X */ |
291 | { "SLO" , 0x000A26C, 0x03, 0, PutAll }, /* X */ |
292 | { "SRE" , 0x000A26C, 0x43, 0, PutAll }, /* X */ |
293 | { "STA" , 0x000A26C, 0x80, 0, PutAll }, |
294 | { "STX" , 0x000010c, 0x82, 1, PutAll }, |
295 | { "STY" , 0x000002c, 0x80, 1, PutAll }, |
296 | { "TAS" , 0x0000200, 0x9b, 0, PutAll }, /* X */ |
297 | { "TAX" , 0x0000001, 0xaa, 0, PutAll }, |
298 | { "TAY" , 0x0000001, 0xa8, 0, PutAll }, |
299 | { "TSX" , 0x0000001, 0xba, 0, PutAll }, |
300 | { "TXA" , 0x0000001, 0x8a, 0, PutAll }, |
301 | { "TXS" , 0x0000001, 0x9a, 0, PutAll }, |
302 | { "TYA" , 0x0000001, 0x98, 0, PutAll } |
303 | } |
304 | }; |
305 | |
306 | /* Instruction table for the 65SC02 */ |
307 | static const struct { |
308 | unsigned Count; |
309 | InsDesc Ins[66]; |
310 | } InsTab65SC02 = { |
311 | sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]), |
312 | { |
313 | { "ADC" , 0x080A66C, 0x60, 0, PutAll }, |
314 | { "AND" , 0x080A66C, 0x20, 0, PutAll }, |
315 | { "ASL" , 0x000006e, 0x02, 1, PutAll }, |
316 | { "BCC" , 0x0020000, 0x90, 0, PutPCRel8 }, |
317 | { "BCS" , 0x0020000, 0xb0, 0, PutPCRel8 }, |
318 | { "BEQ" , 0x0020000, 0xf0, 0, PutPCRel8 }, |
319 | { "BIT" , 0x0A0006C, 0x00, 2, PutAll }, |
320 | { "BMI" , 0x0020000, 0x30, 0, PutPCRel8 }, |
321 | { "BNE" , 0x0020000, 0xd0, 0, PutPCRel8 }, |
322 | { "BPL" , 0x0020000, 0x10, 0, PutPCRel8 }, |
323 | { "BRA" , 0x0020000, 0x80, 0, PutPCRel8 }, |
324 | { "BRK" , 0x0000001, 0x00, 0, PutAll }, |
325 | { "BVC" , 0x0020000, 0x50, 0, PutPCRel8 }, |
326 | { "BVS" , 0x0020000, 0x70, 0, PutPCRel8 }, |
327 | { "CLC" , 0x0000001, 0x18, 0, PutAll }, |
328 | { "CLD" , 0x0000001, 0xd8, 0, PutAll }, |
329 | { "CLI" , 0x0000001, 0x58, 0, PutAll }, |
330 | { "CLV" , 0x0000001, 0xb8, 0, PutAll }, |
331 | { "CMP" , 0x080A66C, 0xc0, 0, PutAll }, |
332 | { "CPX" , 0x080000C, 0xe0, 1, PutAll }, |
333 | { "CPY" , 0x080000C, 0xc0, 1, PutAll }, |
334 | { "DEA" , 0x0000001, 0x00, 3, PutAll }, /* == DEC */ |
335 | { "DEC" , 0x000006F, 0x00, 3, PutAll }, |
336 | { "DEX" , 0x0000001, 0xca, 0, PutAll }, |
337 | { "DEY" , 0x0000001, 0x88, 0, PutAll }, |
338 | { "EOR" , 0x080A66C, 0x40, 0, PutAll }, |
339 | { "INA" , 0x0000001, 0x00, 4, PutAll }, /* == INC */ |
340 | { "INC" , 0x000006f, 0x00, 4, PutAll }, |
341 | { "INX" , 0x0000001, 0xe8, 0, PutAll }, |
342 | { "INY" , 0x0000001, 0xc8, 0, PutAll }, |
343 | { "JMP" , 0x0010808, 0x4c, 6, PutAll }, |
344 | { "JSR" , 0x0000008, 0x20, 7, PutAll }, |
345 | { "LDA" , 0x080A66C, 0xa0, 0, PutAll }, |
346 | { "LDX" , 0x080030C, 0xa2, 1, PutAll }, |
347 | { "LDY" , 0x080006C, 0xa0, 1, PutAll }, |
348 | { "LSR" , 0x000006F, 0x42, 1, PutAll }, |
349 | { "NOP" , 0x0000001, 0xea, 0, PutAll }, |
350 | { "ORA" , 0x080A66C, 0x00, 0, PutAll }, |
351 | { "PHA" , 0x0000001, 0x48, 0, PutAll }, |
352 | { "PHP" , 0x0000001, 0x08, 0, PutAll }, |
353 | { "PHX" , 0x0000001, 0xda, 0, PutAll }, |
354 | { "PHY" , 0x0000001, 0x5a, 0, PutAll }, |
355 | { "PLA" , 0x0000001, 0x68, 0, PutAll }, |
356 | { "PLP" , 0x0000001, 0x28, 0, PutAll }, |
357 | { "PLX" , 0x0000001, 0xfa, 0, PutAll }, |
358 | { "PLY" , 0x0000001, 0x7a, 0, PutAll }, |
359 | { "ROL" , 0x000006F, 0x22, 1, PutAll }, |
360 | { "ROR" , 0x000006F, 0x62, 1, PutAll }, |
361 | { "RTI" , 0x0000001, 0x40, 0, PutAll }, |
362 | { "RTS" , 0x0000001, 0x60, 0, PutAll }, |
363 | { "SBC" , 0x080A66C, 0xe0, 0, PutAll }, |
364 | { "SEC" , 0x0000001, 0x38, 0, PutAll }, |
365 | { "SED" , 0x0000001, 0xf8, 0, PutAll }, |
366 | { "SEI" , 0x0000001, 0x78, 0, PutAll }, |
367 | { "STA" , 0x000A66C, 0x80, 0, PutAll }, |
368 | { "STX" , 0x000010c, 0x82, 1, PutAll }, |
369 | { "STY" , 0x000002c, 0x80, 1, PutAll }, |
370 | { "STZ" , 0x000006c, 0x04, 5, PutAll }, |
371 | { "TAX" , 0x0000001, 0xaa, 0, PutAll }, |
372 | { "TAY" , 0x0000001, 0xa8, 0, PutAll }, |
373 | { "TRB" , 0x000000c, 0x10, 1, PutAll }, |
374 | { "TSB" , 0x000000c, 0x00, 1, PutAll }, |
375 | { "TSX" , 0x0000001, 0xba, 0, PutAll }, |
376 | { "TXA" , 0x0000001, 0x8a, 0, PutAll }, |
377 | { "TXS" , 0x0000001, 0x9a, 0, PutAll }, |
378 | { "TYA" , 0x0000001, 0x98, 0, PutAll } |
379 | } |
380 | }; |
381 | |
382 | /* Instruction table for the 65C02 */ |
383 | static const struct { |
384 | unsigned Count; |
385 | InsDesc Ins[100]; |
386 | } InsTab65C02 = { |
387 | sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]), |
388 | { |
389 | { "ADC" , 0x080A66C, 0x60, 0, PutAll }, |
390 | { "AND" , 0x080A66C, 0x20, 0, PutAll }, |
391 | { "ASL" , 0x000006e, 0x02, 1, PutAll }, |
392 | { "BBR0" , 0x0000000, 0x0F, 0, PutBitBranch }, |
393 | { "BBR1" , 0x0000000, 0x1F, 0, PutBitBranch }, |
394 | { "BBR2" , 0x0000000, 0x2F, 0, PutBitBranch }, |
395 | { "BBR3" , 0x0000000, 0x3F, 0, PutBitBranch }, |
396 | { "BBR4" , 0x0000000, 0x4F, 0, PutBitBranch }, |
397 | { "BBR5" , 0x0000000, 0x5F, 0, PutBitBranch }, |
398 | { "BBR6" , 0x0000000, 0x6F, 0, PutBitBranch }, |
399 | { "BBR7" , 0x0000000, 0x7F, 0, PutBitBranch }, |
400 | { "BBS0" , 0x0000000, 0x8F, 0, PutBitBranch }, |
401 | { "BBS1" , 0x0000000, 0x9F, 0, PutBitBranch }, |
402 | { "BBS2" , 0x0000000, 0xAF, 0, PutBitBranch }, |
403 | { "BBS3" , 0x0000000, 0xBF, 0, PutBitBranch }, |
404 | { "BBS4" , 0x0000000, 0xCF, 0, PutBitBranch }, |
405 | { "BBS5" , 0x0000000, 0xDF, 0, PutBitBranch }, |
406 | { "BBS6" , 0x0000000, 0xEF, 0, PutBitBranch }, |
407 | { "BBS7" , 0x0000000, 0xFF, 0, PutBitBranch }, |
408 | { "BCC" , 0x0020000, 0x90, 0, PutPCRel8 }, |
409 | { "BCS" , 0x0020000, 0xb0, 0, PutPCRel8 }, |
410 | { "BEQ" , 0x0020000, 0xf0, 0, PutPCRel8 }, |
411 | { "BIT" , 0x0A0006C, 0x00, 2, PutAll }, |
412 | { "BMI" , 0x0020000, 0x30, 0, PutPCRel8 }, |
413 | { "BNE" , 0x0020000, 0xd0, 0, PutPCRel8 }, |
414 | { "BPL" , 0x0020000, 0x10, 0, PutPCRel8 }, |
415 | { "BRA" , 0x0020000, 0x80, 0, PutPCRel8 }, |
416 | { "BRK" , 0x0000001, 0x00, 0, PutAll }, |
417 | { "BVC" , 0x0020000, 0x50, 0, PutPCRel8 }, |
418 | { "BVS" , 0x0020000, 0x70, 0, PutPCRel8 }, |
419 | { "CLC" , 0x0000001, 0x18, 0, PutAll }, |
420 | { "CLD" , 0x0000001, 0xd8, 0, PutAll }, |
421 | { "CLI" , 0x0000001, 0x58, 0, PutAll }, |
422 | { "CLV" , 0x0000001, 0xb8, 0, PutAll }, |
423 | { "CMP" , 0x080A66C, 0xc0, 0, PutAll }, |
424 | { "CPX" , 0x080000C, 0xe0, 1, PutAll }, |
425 | { "CPY" , 0x080000C, 0xc0, 1, PutAll }, |
426 | { "DEA" , 0x0000001, 0x00, 3, PutAll }, /* == DEC */ |
427 | { "DEC" , 0x000006F, 0x00, 3, PutAll }, |
428 | { "DEX" , 0x0000001, 0xca, 0, PutAll }, |
429 | { "DEY" , 0x0000001, 0x88, 0, PutAll }, |
430 | { "EOR" , 0x080A66C, 0x40, 0, PutAll }, |
431 | { "INA" , 0x0000001, 0x00, 4, PutAll }, /* == INC */ |
432 | { "INC" , 0x000006f, 0x00, 4, PutAll }, |
433 | { "INX" , 0x0000001, 0xe8, 0, PutAll }, |
434 | { "INY" , 0x0000001, 0xc8, 0, PutAll }, |
435 | { "JMP" , 0x0010808, 0x4c, 6, PutAll }, |
436 | { "JSR" , 0x0000008, 0x20, 7, PutAll }, |
437 | { "LDA" , 0x080A66C, 0xa0, 0, PutAll }, |
438 | { "LDX" , 0x080030C, 0xa2, 1, PutAll }, |
439 | { "LDY" , 0x080006C, 0xa0, 1, PutAll }, |
440 | { "LSR" , 0x000006F, 0x42, 1, PutAll }, |
441 | { "NOP" , 0x0000001, 0xea, 0, PutAll }, |
442 | { "ORA" , 0x080A66C, 0x00, 0, PutAll }, |
443 | { "PHA" , 0x0000001, 0x48, 0, PutAll }, |
444 | { "PHP" , 0x0000001, 0x08, 0, PutAll }, |
445 | { "PHX" , 0x0000001, 0xda, 0, PutAll }, |
446 | { "PHY" , 0x0000001, 0x5a, 0, PutAll }, |
447 | { "PLA" , 0x0000001, 0x68, 0, PutAll }, |
448 | { "PLP" , 0x0000001, 0x28, 0, PutAll }, |
449 | { "PLX" , 0x0000001, 0xfa, 0, PutAll }, |
450 | { "PLY" , 0x0000001, 0x7a, 0, PutAll }, |
451 | { "RMB0" , 0x0000004, 0x07, 1, PutAll }, |
452 | { "RMB1" , 0x0000004, 0x17, 1, PutAll }, |
453 | { "RMB2" , 0x0000004, 0x27, 1, PutAll }, |
454 | { "RMB3" , 0x0000004, 0x37, 1, PutAll }, |
455 | { "RMB4" , 0x0000004, 0x47, 1, PutAll }, |
456 | { "RMB5" , 0x0000004, 0x57, 1, PutAll }, |
457 | { "RMB6" , 0x0000004, 0x67, 1, PutAll }, |
458 | { "RMB7" , 0x0000004, 0x77, 1, PutAll }, |
459 | { "ROL" , 0x000006F, 0x22, 1, PutAll }, |
460 | { "ROR" , 0x000006F, 0x62, 1, PutAll }, |
461 | { "RTI" , 0x0000001, 0x40, 0, PutAll }, |
462 | { "RTS" , 0x0000001, 0x60, 0, PutAll }, |
463 | { "SBC" , 0x080A66C, 0xe0, 0, PutAll }, |
464 | { "SEC" , 0x0000001, 0x38, 0, PutAll }, |
465 | { "SED" , 0x0000001, 0xf8, 0, PutAll }, |
466 | { "SEI" , 0x0000001, 0x78, 0, PutAll }, |
467 | { "SMB0" , 0x0000004, 0x87, 1, PutAll }, |
468 | { "SMB1" , 0x0000004, 0x97, 1, PutAll }, |
469 | { "SMB2" , 0x0000004, 0xA7, 1, PutAll }, |
470 | { "SMB3" , 0x0000004, 0xB7, 1, PutAll }, |
471 | { "SMB4" , 0x0000004, 0xC7, 1, PutAll }, |
472 | { "SMB5" , 0x0000004, 0xD7, 1, PutAll }, |
473 | { "SMB6" , 0x0000004, 0xE7, 1, PutAll }, |
474 | { "SMB7" , 0x0000004, 0xF7, 1, PutAll }, |
475 | { "STA" , 0x000A66C, 0x80, 0, PutAll }, |
476 | { "STP" , 0x0000001, 0xdb, 0, PutAll }, |
477 | { "STX" , 0x000010c, 0x82, 1, PutAll }, |
478 | { "STY" , 0x000002c, 0x80, 1, PutAll }, |
479 | { "STZ" , 0x000006c, 0x04, 5, PutAll }, |
480 | { "TAX" , 0x0000001, 0xaa, 0, PutAll }, |
481 | { "TAY" , 0x0000001, 0xa8, 0, PutAll }, |
482 | { "TRB" , 0x000000c, 0x10, 1, PutAll }, |
483 | { "TSB" , 0x000000c, 0x00, 1, PutAll }, |
484 | { "TSX" , 0x0000001, 0xba, 0, PutAll }, |
485 | { "TXA" , 0x0000001, 0x8a, 0, PutAll }, |
486 | { "TXS" , 0x0000001, 0x9a, 0, PutAll }, |
487 | { "TYA" , 0x0000001, 0x98, 0, PutAll }, |
488 | { "WAI" , 0x0000001, 0xcb, 0, PutAll } |
489 | } |
490 | }; |
491 | |
492 | /* Instruction table for the 4510 */ |
493 | static const struct { |
494 | unsigned Count; |
495 | InsDesc Ins[133]; |
496 | } InsTab4510 = { |
497 | sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]), |
498 | { |
499 | { "ADC" , 0x080A66C, 0x60, 0, PutAll }, |
500 | { "AND" , 0x080A66C, 0x20, 0, PutAll }, |
501 | { "ASL" , 0x000006e, 0x02, 1, PutAll }, |
502 | { "ASR" , 0x0000026, 0x43, 0, Put4510 }, |
503 | { "ASW" , 0x0000008, 0xcb, 6, PutAll }, |
504 | { "BBR0" , 0x0000000, 0x0F, 0, PutBitBranch }, |
505 | { "BBR1" , 0x0000000, 0x1F, 0, PutBitBranch }, |
506 | { "BBR2" , 0x0000000, 0x2F, 0, PutBitBranch }, |
507 | { "BBR3" , 0x0000000, 0x3F, 0, PutBitBranch }, |
508 | { "BBR4" , 0x0000000, 0x4F, 0, PutBitBranch }, |
509 | { "BBR5" , 0x0000000, 0x5F, 0, PutBitBranch }, |
510 | { "BBR6" , 0x0000000, 0x6F, 0, PutBitBranch }, |
511 | { "BBR7" , 0x0000000, 0x7F, 0, PutBitBranch }, |
512 | { "BBS0" , 0x0000000, 0x8F, 0, PutBitBranch }, |
513 | { "BBS1" , 0x0000000, 0x9F, 0, PutBitBranch }, |
514 | { "BBS2" , 0x0000000, 0xAF, 0, PutBitBranch }, |
515 | { "BBS3" , 0x0000000, 0xBF, 0, PutBitBranch }, |
516 | { "BBS4" , 0x0000000, 0xCF, 0, PutBitBranch }, |
517 | { "BBS5" , 0x0000000, 0xDF, 0, PutBitBranch }, |
518 | { "BBS6" , 0x0000000, 0xEF, 0, PutBitBranch }, |
519 | { "BBS7" , 0x0000000, 0xFF, 0, PutBitBranch }, |
520 | { "BCC" , 0x0020000, 0x90, 0, PutPCRel8 }, |
521 | { "BCS" , 0x0020000, 0xb0, 0, PutPCRel8 }, |
522 | { "BEQ" , 0x0020000, 0xf0, 0, PutPCRel8 }, |
523 | { "BIT" , 0x0A0006C, 0x00, 2, PutAll }, |
524 | { "BMI" , 0x0020000, 0x30, 0, PutPCRel8 }, |
525 | { "BNE" , 0x0020000, 0xd0, 0, PutPCRel8 }, |
526 | { "BPL" , 0x0020000, 0x10, 0, PutPCRel8 }, |
527 | { "BRA" , 0x0020000, 0x80, 0, PutPCRel8 }, |
528 | { "BRK" , 0x0000001, 0x00, 0, PutAll }, |
529 | { "BSR" , 0x0040000, 0x63, 0, PutPCRel4510 }, |
530 | { "BVC" , 0x0020000, 0x50, 0, PutPCRel8 }, |
531 | { "BVS" , 0x0020000, 0x70, 0, PutPCRel8 }, |
532 | { "CLC" , 0x0000001, 0x18, 0, PutAll }, |
533 | { "CLD" , 0x0000001, 0xd8, 0, PutAll }, |
534 | { "CLE" , 0x0000001, 0x02, 0, PutAll }, |
535 | { "CLI" , 0x0000001, 0x58, 0, PutAll }, |
536 | { "CLV" , 0x0000001, 0xb8, 0, PutAll }, |
537 | { "CMP" , 0x080A66C, 0xc0, 0, PutAll }, |
538 | { "CPX" , 0x080000C, 0xe0, 1, PutAll }, |
539 | { "CPY" , 0x080000C, 0xc0, 1, PutAll }, |
540 | { "CPZ" , 0x080000C, 0xd0, 1, Put4510 }, |
541 | { "DEA" , 0x0000001, 0x00, 3, PutAll }, /* == DEC */ |
542 | { "DEC" , 0x000006F, 0x00, 3, PutAll }, |
543 | { "DEW" , 0x0000004, 0xc3, 9, PutAll }, |
544 | { "DEX" , 0x0000001, 0xca, 0, PutAll }, |
545 | { "DEY" , 0x0000001, 0x88, 0, PutAll }, |
546 | { "DEZ" , 0x0000001, 0x3B, 0, PutAll }, |
547 | { "EOM" , 0x0000001, 0xea, 0, PutAll }, |
548 | { "EOR" , 0x080A66C, 0x40, 0, PutAll }, |
549 | { "INA" , 0x0000001, 0x00, 4, PutAll }, /* == INC */ |
550 | { "INC" , 0x000006f, 0x00, 4, PutAll }, |
551 | { "INW" , 0x0000004, 0xe3, 9, PutAll }, |
552 | { "INX" , 0x0000001, 0xe8, 0, PutAll }, |
553 | { "INY" , 0x0000001, 0xc8, 0, PutAll }, |
554 | { "INZ" , 0x0000001, 0x1B, 0, PutAll }, |
555 | { "JMP" , 0x0010808, 0x4c, 6, PutAll }, |
556 | { "JSR" , 0x0010808, 0x20, 7, Put4510 }, |
557 | { "LBCC" , 0x0040000, 0x93, 0, PutPCRel4510 }, |
558 | { "LBCS" , 0x0040000, 0xb3, 0, PutPCRel4510 }, |
559 | { "LBEQ" , 0x0040000, 0xf3, 0, PutPCRel4510 }, |
560 | { "LBMI" , 0x0040000, 0x33, 0, PutPCRel4510 }, |
561 | { "LBNE" , 0x0040000, 0xd3, 0, PutPCRel4510 }, |
562 | { "LBPL" , 0x0040000, 0x13, 0, PutPCRel4510 }, |
563 | { "LBRA" , 0x0040000, 0x83, 0, PutPCRel4510 }, |
564 | { "LBVC" , 0x0040000, 0x53, 0, PutPCRel4510 }, |
565 | { "LBVS" , 0x0040000, 0x73, 0, PutPCRel4510 }, |
566 | { "LDA" , 0x090A66C, 0xa0, 0, Put4510 }, |
567 | { "LDX" , 0x080030C, 0xa2, 1, PutAll }, |
568 | { "LDY" , 0x080006C, 0xa0, 1, PutAll }, |
569 | { "LDZ" , 0x0800048, 0xa3, 1, Put4510 }, |
570 | { "LSR" , 0x000006F, 0x42, 1, PutAll }, |
571 | { "MAP" , 0x0000001, 0x5C, 0, PutAll }, |
572 | { "NEG" , 0x0000001, 0x42, 0, PutAll }, |
573 | { "NOP" , 0x0000001, 0xea, 0, PutAll }, /* == EOM */ |
574 | { "ORA" , 0x080A66C, 0x00, 0, PutAll }, |
575 | { "PHA" , 0x0000001, 0x48, 0, PutAll }, |
576 | { "PHD" , 0x8000008, 0xf4, 1, PutAll }, /* == PHW */ |
577 | { "PHP" , 0x0000001, 0x08, 0, PutAll }, |
578 | { "PHW" , 0x8000008, 0xf4, 1, PutAll }, |
579 | { "PHX" , 0x0000001, 0xda, 0, PutAll }, |
580 | { "PHY" , 0x0000001, 0x5a, 0, PutAll }, |
581 | { "PHZ" , 0x0000001, 0xdb, 0, PutAll }, |
582 | { "PLA" , 0x0000001, 0x68, 0, PutAll }, |
583 | { "PLP" , 0x0000001, 0x28, 0, PutAll }, |
584 | { "PLX" , 0x0000001, 0xfa, 0, PutAll }, |
585 | { "PLY" , 0x0000001, 0x7a, 0, PutAll }, |
586 | { "PLZ" , 0x0000001, 0xfb, 0, PutAll }, |
587 | { "RMB0" , 0x0000004, 0x07, 1, PutAll }, |
588 | { "RMB1" , 0x0000004, 0x17, 1, PutAll }, |
589 | { "RMB2" , 0x0000004, 0x27, 1, PutAll }, |
590 | { "RMB3" , 0x0000004, 0x37, 1, PutAll }, |
591 | { "RMB4" , 0x0000004, 0x47, 1, PutAll }, |
592 | { "RMB5" , 0x0000004, 0x57, 1, PutAll }, |
593 | { "RMB6" , 0x0000004, 0x67, 1, PutAll }, |
594 | { "RMB7" , 0x0000004, 0x77, 1, PutAll }, |
595 | { "ROL" , 0x000006F, 0x22, 1, PutAll }, |
596 | { "ROR" , 0x000006F, 0x62, 1, PutAll }, |
597 | { "ROW" , 0x0000008, 0xeb, 6, PutAll }, |
598 | { "RTI" , 0x0000001, 0x40, 0, PutAll }, |
599 | { "RTN" , 0x0800000, 0x62, 1, PutAll }, |
600 | { "RTS" , 0x0000001, 0x60, 0, PutAll }, |
601 | { "SBC" , 0x080A66C, 0xe0, 0, PutAll }, |
602 | { "SEC" , 0x0000001, 0x38, 0, PutAll }, |
603 | { "SED" , 0x0000001, 0xf8, 0, PutAll }, |
604 | { "SEE" , 0x0000001, 0x03, 0, PutAll }, |
605 | { "SEI" , 0x0000001, 0x78, 0, PutAll }, |
606 | { "SMB0" , 0x0000004, 0x87, 1, PutAll }, |
607 | { "SMB1" , 0x0000004, 0x97, 1, PutAll }, |
608 | { "SMB2" , 0x0000004, 0xA7, 1, PutAll }, |
609 | { "SMB3" , 0x0000004, 0xB7, 1, PutAll }, |
610 | { "SMB4" , 0x0000004, 0xC7, 1, PutAll }, |
611 | { "SMB5" , 0x0000004, 0xD7, 1, PutAll }, |
612 | { "SMB6" , 0x0000004, 0xE7, 1, PutAll }, |
613 | { "SMB7" , 0x0000004, 0xF7, 1, PutAll }, |
614 | { "STA" , 0x010A66C, 0x80, 0, Put4510 }, |
615 | { "STX" , 0x000030c, 0x82, 1, Put4510 }, |
616 | { "STY" , 0x000006c, 0x80, 1, Put4510 }, |
617 | { "STZ" , 0x000006c, 0x04, 5, PutAll }, |
618 | { "TAB" , 0x0000001, 0x5b, 0, PutAll }, |
619 | { "TAX" , 0x0000001, 0xaa, 0, PutAll }, |
620 | { "TAY" , 0x0000001, 0xa8, 0, PutAll }, |
621 | { "TAZ" , 0x0000001, 0x4b, 0, PutAll }, |
622 | { "TBA" , 0x0000001, 0x7b, 0, PutAll }, |
623 | { "TRB" , 0x000000c, 0x10, 1, PutAll }, |
624 | { "TSB" , 0x000000c, 0x00, 1, PutAll }, |
625 | { "TSX" , 0x0000001, 0xba, 0, PutAll }, |
626 | { "TSY" , 0x0000001, 0x0b, 0, PutAll }, |
627 | { "TXA" , 0x0000001, 0x8a, 0, PutAll }, |
628 | { "TXS" , 0x0000001, 0x9a, 0, PutAll }, |
629 | { "TYA" , 0x0000001, 0x98, 0, PutAll }, |
630 | { "TYS" , 0x0000001, 0x2b, 0, PutAll }, |
631 | { "TZA" , 0x0000001, 0x6b, 0, PutAll }, |
632 | } |
633 | }; |
634 | |
635 | /* Instruction table for the 65816 */ |
636 | static const struct { |
637 | unsigned Count; |
638 | InsDesc Ins[100]; |
639 | } InsTab65816 = { |
640 | sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]), |
641 | { |
642 | { "ADC" , 0x0b8f6fc, 0x60, 0, PutAll }, |
643 | { "AND" , 0x0b8f6fc, 0x20, 0, PutAll }, |
644 | { "ASL" , 0x000006e, 0x02, 1, PutAll }, |
645 | { "BCC" , 0x0020000, 0x90, 0, PutPCRel8 }, |
646 | { "BCS" , 0x0020000, 0xb0, 0, PutPCRel8 }, |
647 | { "BEQ" , 0x0020000, 0xf0, 0, PutPCRel8 }, |
648 | { "BIT" , 0x0a0006c, 0x00, 2, PutAll }, |
649 | { "BMI" , 0x0020000, 0x30, 0, PutPCRel8 }, |
650 | { "BNE" , 0x0020000, 0xd0, 0, PutPCRel8 }, |
651 | { "BPL" , 0x0020000, 0x10, 0, PutPCRel8 }, |
652 | { "BRA" , 0x0020000, 0x80, 0, PutPCRel8 }, |
653 | { "BRK" , 0x0000005, 0x00, 6, PutAll }, |
654 | { "BRL" , 0x0040000, 0x82, 0, PutPCRel16 }, |
655 | { "BVC" , 0x0020000, 0x50, 0, PutPCRel8 }, |
656 | { "BVS" , 0x0020000, 0x70, 0, PutPCRel8 }, |
657 | { "CLC" , 0x0000001, 0x18, 0, PutAll }, |
658 | { "CLD" , 0x0000001, 0xd8, 0, PutAll }, |
659 | { "CLI" , 0x0000001, 0x58, 0, PutAll }, |
660 | { "CLV" , 0x0000001, 0xb8, 0, PutAll }, |
661 | { "CMP" , 0x0b8f6fc, 0xc0, 0, PutAll }, |
662 | { "COP" , 0x0000004, 0x02, 6, PutAll }, |
663 | { "CPA" , 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */ |
664 | { "CPX" , 0x0c0000c, 0xe0, 1, PutAll }, |
665 | { "CPY" , 0x0c0000c, 0xc0, 1, PutAll }, |
666 | { "DEA" , 0x0000001, 0x00, 3, PutAll }, /* == DEC */ |
667 | { "DEC" , 0x000006F, 0x00, 3, PutAll }, |
668 | { "DEX" , 0x0000001, 0xca, 0, PutAll }, |
669 | { "DEY" , 0x0000001, 0x88, 0, PutAll }, |
670 | { "EOR" , 0x0b8f6fc, 0x40, 0, PutAll }, |
671 | { "INA" , 0x0000001, 0x00, 4, PutAll }, /* == INC */ |
672 | { "INC" , 0x000006F, 0x00, 4, PutAll }, |
673 | { "INX" , 0x0000001, 0xe8, 0, PutAll }, |
674 | { "INY" , 0x0000001, 0xc8, 0, PutAll }, |
675 | { "JML" , 0x4000010, 0x5c, 1, PutAll }, |
676 | { "JMP" , 0x4010818, 0x4c, 6, PutAll }, |
677 | { "JSL" , 0x0000010, 0x20, 7, PutAll }, |
678 | { "JSR" , 0x0010018, 0x20, 7, PutAll }, |
679 | { "LDA" , 0x0b8f6fc, 0xa0, 0, PutAll }, |
680 | { "LDX" , 0x0c0030c, 0xa2, 1, PutAll }, |
681 | { "LDY" , 0x0c0006c, 0xa0, 1, PutAll }, |
682 | { "LSR" , 0x000006F, 0x42, 1, PutAll }, |
683 | { "MVN" , 0x1000000, 0x54, 0, PutBlockMove }, |
684 | { "MVP" , 0x1000000, 0x44, 0, PutBlockMove }, |
685 | { "NOP" , 0x0000001, 0xea, 0, PutAll }, |
686 | { "ORA" , 0x0b8f6fc, 0x00, 0, PutAll }, |
687 | { "PEA" , 0x0000008, 0xf4, 6, PutAll }, |
688 | { "PEI" , 0x0000400, 0xd4, 1, PutAll }, |
689 | { "PER" , 0x0040000, 0x62, 0, PutPCRel16 }, |
690 | { "PHA" , 0x0000001, 0x48, 0, PutAll }, |
691 | { "PHB" , 0x0000001, 0x8b, 0, PutAll }, |
692 | { "PHD" , 0x0000001, 0x0b, 0, PutAll }, |
693 | { "PHK" , 0x0000001, 0x4b, 0, PutAll }, |
694 | { "PHP" , 0x0000001, 0x08, 0, PutAll }, |
695 | { "PHX" , 0x0000001, 0xda, 0, PutAll }, |
696 | { "PHY" , 0x0000001, 0x5a, 0, PutAll }, |
697 | { "PLA" , 0x0000001, 0x68, 0, PutAll }, |
698 | { "PLB" , 0x0000001, 0xab, 0, PutAll }, |
699 | { "PLD" , 0x0000001, 0x2b, 0, PutAll }, |
700 | { "PLP" , 0x0000001, 0x28, 0, PutAll }, |
701 | { "PLX" , 0x0000001, 0xfa, 0, PutAll }, |
702 | { "PLY" , 0x0000001, 0x7a, 0, PutAll }, |
703 | { "REP" , 0x0800000, 0xc2, 1, PutREP }, |
704 | { "ROL" , 0x000006F, 0x22, 1, PutAll }, |
705 | { "ROR" , 0x000006F, 0x62, 1, PutAll }, |
706 | { "RTI" , 0x0000001, 0x40, 0, PutAll }, |
707 | { "RTL" , 0x0000001, 0x6b, 0, PutAll }, |
708 | { "RTS" , 0x0000001, 0x60, 0, PutRTS }, |
709 | { "SBC" , 0x0b8f6fc, 0xe0, 0, PutAll }, |
710 | { "SEC" , 0x0000001, 0x38, 0, PutAll }, |
711 | { "SED" , 0x0000001, 0xf8, 0, PutAll }, |
712 | { "SEI" , 0x0000001, 0x78, 0, PutAll }, |
713 | { "SEP" , 0x0800000, 0xe2, 1, PutSEP }, |
714 | { "STA" , 0x018f6fc, 0x80, 0, PutAll }, |
715 | { "STP" , 0x0000001, 0xdb, 0, PutAll }, |
716 | { "STX" , 0x000010c, 0x82, 1, PutAll }, |
717 | { "STY" , 0x000002c, 0x80, 1, PutAll }, |
718 | { "STZ" , 0x000006c, 0x04, 5, PutAll }, |
719 | { "SWA" , 0x0000001, 0xeb, 0, PutAll }, /* == XBA */ |
720 | { "TAD" , 0x0000001, 0x5b, 0, PutAll }, /* == TCD */ |
721 | { "TAS" , 0x0000001, 0x1b, 0, PutAll }, /* == TCS */ |
722 | { "TAX" , 0x0000001, 0xaa, 0, PutAll }, |
723 | { "TAY" , 0x0000001, 0xa8, 0, PutAll }, |
724 | { "TCD" , 0x0000001, 0x5b, 0, PutAll }, |
725 | { "TCS" , 0x0000001, 0x1b, 0, PutAll }, |
726 | { "TDA" , 0x0000001, 0x7b, 0, PutAll }, /* == TDC */ |
727 | { "TDC" , 0x0000001, 0x7b, 0, PutAll }, |
728 | { "TRB" , 0x000000c, 0x10, 1, PutAll }, |
729 | { "TSA" , 0x0000001, 0x3b, 0, PutAll }, /* == TSC */ |
730 | { "TSB" , 0x000000c, 0x00, 1, PutAll }, |
731 | { "TSC" , 0x0000001, 0x3b, 0, PutAll }, |
732 | { "TSX" , 0x0000001, 0xba, 0, PutAll }, |
733 | { "TXA" , 0x0000001, 0x8a, 0, PutAll }, |
734 | { "TXS" , 0x0000001, 0x9a, 0, PutAll }, |
735 | { "TXY" , 0x0000001, 0x9b, 0, PutAll }, |
736 | { "TYA" , 0x0000001, 0x98, 0, PutAll }, |
737 | { "TYX" , 0x0000001, 0xbb, 0, PutAll }, |
738 | { "WAI" , 0x0000001, 0xcb, 0, PutAll }, |
739 | { "WDM" , 0x0000004, 0x42, 6, PutAll }, |
740 | { "XBA" , 0x0000001, 0xeb, 0, PutAll }, |
741 | { "XCE" , 0x0000001, 0xfb, 0, PutAll } |
742 | } |
743 | }; |
744 | |
745 | /* Instruction table for the SWEET16 pseudo CPU */ |
746 | static const struct { |
747 | unsigned Count; |
748 | InsDesc Ins[26]; |
749 | } InsTabSweet16 = { |
750 | sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]), |
751 | { |
752 | { "ADD" , AMSW16_REG, 0xA0, 0, PutSweet16 }, |
753 | { "BC" , AMSW16_BRA, 0x03, 0, PutSweet16Branch }, |
754 | { "BK" , AMSW16_IMP, 0x0A, 0, PutSweet16 }, |
755 | { "BM" , AMSW16_BRA, 0x05, 0, PutSweet16Branch }, |
756 | { "BM1" , AMSW16_BRA, 0x08, 0, PutSweet16Branch }, |
757 | { "BNC" , AMSW16_BRA, 0x02, 0, PutSweet16Branch }, |
758 | { "BNM1" , AMSW16_BRA, 0x09, 0, PutSweet16Branch }, |
759 | { "BNZ" , AMSW16_BRA, 0x07, 0, PutSweet16Branch }, |
760 | { "BP" , AMSW16_BRA, 0x04, 0, PutSweet16Branch }, |
761 | { "BR" , AMSW16_BRA, 0x01, 0, PutSweet16Branch }, |
762 | { "BS" , AMSW16_BRA, 0x0C, 0, PutSweet16Branch }, |
763 | { "BZ" , AMSW16_BRA, 0x06, 0, PutSweet16Branch }, |
764 | { "CPR" , AMSW16_REG, 0xD0, 0, PutSweet16 }, |
765 | { "DCR" , AMSW16_REG, 0xF0, 0, PutSweet16 }, |
766 | { "INR" , AMSW16_REG, 0xE0, 0, PutSweet16 }, |
767 | { "LD" , AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 }, |
768 | { "LDD" , AMSW16_IND, 0x60, 0, PutSweet16 }, |
769 | { "POP" , AMSW16_IND, 0x80, 0, PutSweet16 }, |
770 | { "POPD" , AMSW16_IND, 0xC0, 0, PutSweet16 }, |
771 | { "RS" , AMSW16_IMP, 0x0B, 0, PutSweet16 }, |
772 | { "RTN" , AMSW16_IMP, 0x00, 0, PutSweet16 }, |
773 | { "SET" , AMSW16_IMM, 0x10, 0, PutSweet16 }, |
774 | { "ST" , AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 }, |
775 | { "STD" , AMSW16_IND, 0x70, 0, PutSweet16 }, |
776 | { "STP" , AMSW16_IND, 0x90, 0, PutSweet16 }, |
777 | { "SUB" , AMSW16_REG, 0xB0, 0, PutSweet16 }, |
778 | } |
779 | }; |
780 | |
781 | /* Instruction table for the HuC6280 (the CPU used in the PC engine) */ |
782 | static const struct { |
783 | unsigned Count; |
784 | InsDesc Ins[135]; |
785 | } InsTabHuC6280 = { |
786 | sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]), |
787 | { |
788 | { "ADC" , 0x080A66C, 0x60, 0, PutAll }, |
789 | { "AND" , 0x080A66C, 0x20, 0, PutAll }, |
790 | { "ASL" , 0x000006e, 0x02, 1, PutAll }, |
791 | { "BBR0" , 0x0000000, 0x0F, 0, PutBitBranch }, |
792 | { "BBR1" , 0x0000000, 0x1F, 0, PutBitBranch }, |
793 | { "BBR2" , 0x0000000, 0x2F, 0, PutBitBranch }, |
794 | { "BBR3" , 0x0000000, 0x3F, 0, PutBitBranch }, |
795 | { "BBR4" , 0x0000000, 0x4F, 0, PutBitBranch }, |
796 | { "BBR5" , 0x0000000, 0x5F, 0, PutBitBranch }, |
797 | { "BBR6" , 0x0000000, 0x6F, 0, PutBitBranch }, |
798 | { "BBR7" , 0x0000000, 0x7F, 0, PutBitBranch }, |
799 | { "BBS0" , 0x0000000, 0x8F, 0, PutBitBranch }, |
800 | { "BBS1" , 0x0000000, 0x9F, 0, PutBitBranch }, |
801 | { "BBS2" , 0x0000000, 0xAF, 0, PutBitBranch }, |
802 | { "BBS3" , 0x0000000, 0xBF, 0, PutBitBranch }, |
803 | { "BBS4" , 0x0000000, 0xCF, 0, PutBitBranch }, |
804 | { "BBS5" , 0x0000000, 0xDF, 0, PutBitBranch }, |
805 | { "BBS6" , 0x0000000, 0xEF, 0, PutBitBranch }, |
806 | { "BBS7" , 0x0000000, 0xFF, 0, PutBitBranch }, |
807 | { "BCC" , 0x0020000, 0x90, 0, PutPCRel8 }, |
808 | { "BCS" , 0x0020000, 0xb0, 0, PutPCRel8 }, |
809 | { "BEQ" , 0x0020000, 0xf0, 0, PutPCRel8 }, |
810 | { "BIT" , 0x0A0006C, 0x00, 2, PutAll }, |
811 | { "BMI" , 0x0020000, 0x30, 0, PutPCRel8 }, |
812 | { "BNE" , 0x0020000, 0xd0, 0, PutPCRel8 }, |
813 | { "BPL" , 0x0020000, 0x10, 0, PutPCRel8 }, |
814 | { "BRA" , 0x0020000, 0x80, 0, PutPCRel8 }, |
815 | { "BRK" , 0x0000001, 0x00, 0, PutAll }, |
816 | { "BSR" , 0x0020000, 0x44, 0, PutPCRel8 }, |
817 | { "BVC" , 0x0020000, 0x50, 0, PutPCRel8 }, |
818 | { "BVS" , 0x0020000, 0x70, 0, PutPCRel8 }, |
819 | { "CLA" , 0x0000001, 0x62, 0, PutAll }, |
820 | { "CLC" , 0x0000001, 0x18, 0, PutAll }, |
821 | { "CLD" , 0x0000001, 0xd8, 0, PutAll }, |
822 | { "CLI" , 0x0000001, 0x58, 0, PutAll }, |
823 | { "CLV" , 0x0000001, 0xb8, 0, PutAll }, |
824 | { "CLX" , 0x0000001, 0x82, 0, PutAll }, |
825 | { "CLY" , 0x0000001, 0xc2, 0, PutAll }, |
826 | { "CMP" , 0x080A66C, 0xc0, 0, PutAll }, |
827 | { "CPX" , 0x080000C, 0xe0, 1, PutAll }, |
828 | { "CPY" , 0x080000C, 0xc0, 1, PutAll }, |
829 | { "CSH" , 0x0000001, 0xd4, 0, PutAll }, |
830 | { "CSL" , 0x0000001, 0x54, 0, PutAll }, |
831 | { "DEA" , 0x0000001, 0x00, 3, PutAll }, /* == DEC */ |
832 | { "DEC" , 0x000006F, 0x00, 3, PutAll }, |
833 | { "DEX" , 0x0000001, 0xca, 0, PutAll }, |
834 | { "DEY" , 0x0000001, 0x88, 0, PutAll }, |
835 | { "EOR" , 0x080A66C, 0x40, 0, PutAll }, |
836 | { "INA" , 0x0000001, 0x00, 4, PutAll }, /* == INC */ |
837 | { "INC" , 0x000006f, 0x00, 4, PutAll }, |
838 | { "INX" , 0x0000001, 0xe8, 0, PutAll }, |
839 | { "INY" , 0x0000001, 0xc8, 0, PutAll }, |
840 | { "JMP" , 0x0010808, 0x4c, 6, PutAll }, |
841 | { "JSR" , 0x0000008, 0x20, 7, PutAll }, |
842 | { "LDA" , 0x080A66C, 0xa0, 0, PutAll }, |
843 | { "LDX" , 0x080030C, 0xa2, 1, PutAll }, |
844 | { "LDY" , 0x080006C, 0xa0, 1, PutAll }, |
845 | { "LSR" , 0x000006F, 0x42, 1, PutAll }, |
846 | { "NOP" , 0x0000001, 0xea, 0, PutAll }, |
847 | { "ORA" , 0x080A66C, 0x00, 0, PutAll }, |
848 | { "PHA" , 0x0000001, 0x48, 0, PutAll }, |
849 | { "PHP" , 0x0000001, 0x08, 0, PutAll }, |
850 | { "PHX" , 0x0000001, 0xda, 0, PutAll }, |
851 | { "PHY" , 0x0000001, 0x5a, 0, PutAll }, |
852 | { "PLA" , 0x0000001, 0x68, 0, PutAll }, |
853 | { "PLP" , 0x0000001, 0x28, 0, PutAll }, |
854 | { "PLX" , 0x0000001, 0xfa, 0, PutAll }, |
855 | { "PLY" , 0x0000001, 0x7a, 0, PutAll }, |
856 | { "RMB0" , 0x0000004, 0x07, 1, PutAll }, |
857 | { "RMB1" , 0x0000004, 0x17, 1, PutAll }, |
858 | { "RMB2" , 0x0000004, 0x27, 1, PutAll }, |
859 | { "RMB3" , 0x0000004, 0x37, 1, PutAll }, |
860 | { "RMB4" , 0x0000004, 0x47, 1, PutAll }, |
861 | { "RMB5" , 0x0000004, 0x57, 1, PutAll }, |
862 | { "RMB6" , 0x0000004, 0x67, 1, PutAll }, |
863 | { "RMB7" , 0x0000004, 0x77, 1, PutAll }, |
864 | { "ROL" , 0x000006F, 0x22, 1, PutAll }, |
865 | { "ROR" , 0x000006F, 0x62, 1, PutAll }, |
866 | { "RTI" , 0x0000001, 0x40, 0, PutAll }, |
867 | { "RTS" , 0x0000001, 0x60, 0, PutAll }, |
868 | { "SAX" , 0x0000001, 0x22, 0, PutAll }, |
869 | { "SAY" , 0x0000001, 0x42, 0, PutAll }, |
870 | { "SBC" , 0x080A66C, 0xe0, 0, PutAll }, |
871 | { "SEC" , 0x0000001, 0x38, 0, PutAll }, |
872 | { "SED" , 0x0000001, 0xf8, 0, PutAll }, |
873 | { "SEI" , 0x0000001, 0x78, 0, PutAll }, |
874 | { "SET" , 0x0000001, 0xf4, 0, PutAll }, |
875 | { "SMB0" , 0x0000004, 0x87, 1, PutAll }, |
876 | { "SMB1" , 0x0000004, 0x97, 1, PutAll }, |
877 | { "SMB2" , 0x0000004, 0xA7, 1, PutAll }, |
878 | { "SMB3" , 0x0000004, 0xB7, 1, PutAll }, |
879 | { "SMB4" , 0x0000004, 0xC7, 1, PutAll }, |
880 | { "SMB5" , 0x0000004, 0xD7, 1, PutAll }, |
881 | { "SMB6" , 0x0000004, 0xE7, 1, PutAll }, |
882 | { "SMB7" , 0x0000004, 0xF7, 1, PutAll }, |
883 | { "ST0" , 0x0800000, 0x03, 1, PutAll }, |
884 | { "ST1" , 0x0800000, 0x13, 1, PutAll }, |
885 | { "ST2" , 0x0800000, 0x23, 1, PutAll }, |
886 | { "STA" , 0x000A66C, 0x80, 0, PutAll }, |
887 | { "STX" , 0x000010c, 0x82, 1, PutAll }, |
888 | { "STY" , 0x000002c, 0x80, 1, PutAll }, |
889 | { "STZ" , 0x000006c, 0x04, 5, PutAll }, |
890 | { "SXY" , 0x0000001, 0x02, 0, PutAll }, |
891 | { "TAI" , 0x2000000, 0xf3, 0, PutBlockTransfer }, |
892 | { "TAM" , 0x0800000, 0x53, 1, PutAll }, |
893 | { "TAM0" , 0x0000001, 0x01, 0, PutTAMn}, |
894 | { "TAM1" , 0x0000001, 0x02, 0, PutTAMn}, |
895 | { "TAM2" , 0x0000001, 0x04, 0, PutTAMn}, |
896 | { "TAM3" , 0x0000001, 0x08, 0, PutTAMn}, |
897 | { "TAM4" , 0x0000001, 0x10, 0, PutTAMn}, |
898 | { "TAM5" , 0x0000001, 0x20, 0, PutTAMn}, |
899 | { "TAM6" , 0x0000001, 0x40, 0, PutTAMn}, |
900 | { "TAM7" , 0x0000001, 0x80, 0, PutTAMn}, |
901 | { "TAX" , 0x0000001, 0xaa, 0, PutAll }, |
902 | { "TAY" , 0x0000001, 0xa8, 0, PutAll }, |
903 | { "TDD" , 0x2000000, 0xc3, 0, PutBlockTransfer }, |
904 | { "TIA" , 0x2000000, 0xe3, 0, PutBlockTransfer }, |
905 | { "TII" , 0x2000000, 0x73, 0, PutBlockTransfer }, |
906 | { "TIN" , 0x2000000, 0xD3, 0, PutBlockTransfer }, |
907 | { "TMA" , 0x0800000, 0x43, 1, PutTMA }, |
908 | { "TMA0" , 0x0000001, 0x01, 0, PutTMAn}, |
909 | { "TMA1" , 0x0000001, 0x02, 0, PutTMAn}, |
910 | { "TMA2" , 0x0000001, 0x04, 0, PutTMAn}, |
911 | { "TMA3" , 0x0000001, 0x08, 0, PutTMAn}, |
912 | { "TMA4" , 0x0000001, 0x10, 0, PutTMAn}, |
913 | { "TMA5" , 0x0000001, 0x20, 0, PutTMAn}, |
914 | { "TMA6" , 0x0000001, 0x40, 0, PutTMAn}, |
915 | { "TMA7" , 0x0000001, 0x80, 0, PutTMAn}, |
916 | { "TRB" , 0x000000c, 0x10, 1, PutAll }, |
917 | { "TSB" , 0x000000c, 0x00, 1, PutAll }, |
918 | { "TST" , 0x000006c, 0x83, 9, PutTST }, |
919 | { "TSX" , 0x0000001, 0xba, 0, PutAll }, |
920 | { "TXA" , 0x0000001, 0x8a, 0, PutAll }, |
921 | { "TXS" , 0x0000001, 0x9a, 0, PutAll }, |
922 | { "TYA" , 0x0000001, 0x98, 0, PutAll } |
923 | } |
924 | }; |
925 | |
926 | |
927 | |
928 | /* An array with instruction tables */ |
929 | static const InsTable* InsTabs[CPU_COUNT] = { |
930 | (const InsTable*) &InsTabNone, |
931 | (const InsTable*) &InsTab6502, |
932 | (const InsTable*) &InsTab6502X, |
933 | (const InsTable*) &InsTab65SC02, |
934 | (const InsTable*) &InsTab65C02, |
935 | (const InsTable*) &InsTab65816, |
936 | (const InsTable*) &InsTabSweet16, |
937 | (const InsTable*) &InsTabHuC6280, |
938 | 0, /* Mitsubishi 740 */ |
939 | (const InsTable*) &InsTab4510, |
940 | }; |
941 | const InsTable* InsTab = (const InsTable*) &InsTab6502; |
942 | |
943 | /* Table to build the effective 65xx opcode from a base opcode and an |
944 | ** addressing mode. (The value in the table is ORed with the base opcode) |
945 | */ |
946 | static unsigned char EATab[12][AM65I_COUNT] = { |
947 | { /* Table 0 */ |
948 | 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F, |
949 | 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01, |
950 | 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09, |
951 | 0x00, 0x00, 0x00, 0x00 |
952 | }, |
953 | { /* Table 1 */ |
954 | 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00, |
955 | 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, |
956 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
957 | 0x00, 0x00, 0x80, 0x00 |
958 | }, |
959 | { /* Table 2 */ |
960 | 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00, |
961 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
962 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, |
963 | 0x00, 0x00, 0x00, 0x00 |
964 | }, |
965 | { /* Table 3 */ |
966 | 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00, |
967 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
968 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
969 | 0x00, 0x00, 0x00, 0x00 |
970 | }, |
971 | { /* Table 4 */ |
972 | 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00, |
973 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
974 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
975 | 0x00, 0x00, 0x00, 0x00 |
976 | }, |
977 | { /* Table 5 */ |
978 | 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00, |
979 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
980 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
981 | 0x00, 0x00, 0x00, 0x00 |
982 | }, |
983 | { /* Table 6 */ |
984 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, |
985 | 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, |
986 | 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
987 | 0x00, 0x00, 0x90, 0x00 |
988 | }, |
989 | { /* Table 7 (Subroutine opcodes) */ |
990 | 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, |
991 | 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, |
992 | 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
993 | 0x00, 0x00, 0x00, 0x00 |
994 | }, |
995 | { /* Table 8 */ |
996 | 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00, |
997 | 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, |
998 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, |
999 | 0x00, 0x00, 0x00, 0x00 |
1000 | }, |
1001 | { /* Table 9 */ |
1002 | 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00, |
1003 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1004 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1005 | 0x00, 0x00, 0x00, 0x00 |
1006 | }, |
1007 | { /* Table 10 (NOPs) */ |
1008 | 0xea, 0x00, 0x04, 0x0c, 0x00, 0x14, 0x1c, 0x00, |
1009 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1010 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, |
1011 | 0x00, 0x00, 0x00, 0x00 |
1012 | }, |
1013 | { /* Table 11 (LAX) */ |
1014 | 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00, |
1015 | 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, |
1016 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, |
1017 | 0x00, 0x00, 0x80, 0x00 |
1018 | }, |
1019 | }; |
1020 | |
1021 | /* Table to build the effective SWEET16 opcode from a base opcode and an |
1022 | ** addressing mode. |
1023 | */ |
1024 | static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = { |
1025 | { /* Table 0 */ |
1026 | 0x00, 0x00, 0x00, 0x00, 0x00, |
1027 | }, |
1028 | { /* Table 1 */ |
1029 | 0x00, 0x00, 0x00, 0x40, 0x20, |
1030 | }, |
1031 | }; |
1032 | |
1033 | /* Table that encodes the additional bytes for each 65xx instruction */ |
1034 | unsigned char ExtBytes[AM65I_COUNT] = { |
1035 | 0, /* Implicit */ |
1036 | 0, /* Accu */ |
1037 | 1, /* Direct */ |
1038 | 2, /* Absolute */ |
1039 | 3, /* Absolute long */ |
1040 | 1, /* Direct,X */ |
1041 | 2, /* Absolute,X */ |
1042 | 3, /* Absolute long,X */ |
1043 | 1, /* Direct,Y */ |
1044 | 2, /* Absolute,Y */ |
1045 | 1, /* (Direct) */ |
1046 | 2, /* (Absolute) */ |
1047 | 1, /* [Direct] */ |
1048 | 1, /* (Direct),Y */ |
1049 | 1, /* [Direct],Y */ |
1050 | 1, /* (Direct,X) */ |
1051 | 2, /* (Absolute,X) */ |
1052 | 1, /* Relative short */ |
1053 | 2, /* Relative long */ |
1054 | 1, /* r,s */ |
1055 | 1, /* (r,s),y */ |
1056 | 1, /* Immidiate accu */ |
1057 | 1, /* Immidiate index */ |
1058 | 1, /* Immidiate byte */ |
1059 | 2, /* Blockmove (65816) */ |
1060 | 7, /* Block transfer (HuC6280) */ |
1061 | 2, /* Absolute Indirect long */ |
1062 | 2, /* Immidiate word */ |
1063 | }; |
1064 | |
1065 | /* Table that encodes the additional bytes for each SWEET16 instruction */ |
1066 | static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = { |
1067 | 0, /* AMSW16_IMP */ |
1068 | 1, /* AMSW16_BRA */ |
1069 | 2, /* AMSW16_IMM */ |
1070 | 0, /* AMSW16_IND */ |
1071 | 0, /* AMSW16_REG */ |
1072 | }; |
1073 | |
1074 | |
1075 | |
1076 | /*****************************************************************************/ |
1077 | /* Handler functions for 6502 derivates */ |
1078 | /*****************************************************************************/ |
1079 | |
1080 | |
1081 | |
1082 | static int EvalEA (const InsDesc* Ins, EffAddr* A) |
1083 | /* Evaluate the effective address. All fields in A will be valid after calling |
1084 | ** this function. The function returns true on success and false on errors. |
1085 | */ |
1086 | { |
1087 | /* Get the set of possible addressing modes */ |
1088 | GetEA (A); |
1089 | |
1090 | /* From the possible addressing modes, remove the ones that are invalid |
1091 | ** for this instruction or CPU. |
1092 | */ |
1093 | A->AddrModeSet &= Ins->AddrMode; |
1094 | |
1095 | /* If we have an expression, check it and remove any addressing modes that |
1096 | ** are too small for the expression size. Since we have to study the |
1097 | ** expression anyway, do also replace it by a simpler one if possible. |
1098 | */ |
1099 | if (A->Expr) { |
1100 | ExprDesc ED; |
1101 | ED_Init (&ED); |
1102 | |
1103 | /* Study the expression */ |
1104 | StudyExpr (A->Expr, &ED); |
1105 | |
1106 | /* Simplify it if possible */ |
1107 | A->Expr = SimplifyExpr (A->Expr, &ED); |
1108 | |
1109 | if (ED.AddrSize == ADDR_SIZE_DEFAULT) { |
1110 | /* We don't know how big the expression is. If the instruction |
1111 | ** allows just one addressing mode, assume this as address size |
1112 | ** for the expression. Otherwise assume the default address size |
1113 | ** for data. |
1114 | */ |
1115 | if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) { |
1116 | ED.AddrSize = ADDR_SIZE_ZP; |
1117 | } else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) { |
1118 | ED.AddrSize = ADDR_SIZE_ABS; |
1119 | } else if ((A->AddrModeSet & ~AM65_ALL_FAR) == 0) { |
1120 | ED.AddrSize = ADDR_SIZE_FAR; |
1121 | } else { |
1122 | ED.AddrSize = DataAddrSize; |
1123 | /* If the default address size of the data segment is unequal |
1124 | ** to zero page addressing, but zero page addressing is |
1125 | ** allowed by the instruction, mark all symbols in the |
1126 | ** expression tree. This mark will be checked at end of |
1127 | ** assembly, and a warning is issued, if a zero page symbol |
1128 | ** was guessed wrong here. |
1129 | */ |
1130 | if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) { |
1131 | ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP); |
1132 | } |
1133 | } |
1134 | } |
1135 | |
1136 | /* Check the size */ |
1137 | switch (ED.AddrSize) { |
1138 | |
1139 | case ADDR_SIZE_ABS: |
1140 | A->AddrModeSet &= ~AM65_SET_ZP; |
1141 | break; |
1142 | |
1143 | case ADDR_SIZE_FAR: |
1144 | A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS); |
1145 | break; |
1146 | } |
1147 | |
1148 | /* Free any resource associated with the expression desc */ |
1149 | ED_Done (&ED); |
1150 | } |
1151 | |
1152 | /* Check if we have any adressing modes left */ |
1153 | if (A->AddrModeSet == 0) { |
1154 | Error ("Illegal addressing mode" ); |
1155 | return 0; |
1156 | } |
1157 | A->AddrMode = BitFind (A->AddrModeSet); |
1158 | A->AddrModeBit = (0x01UL << A->AddrMode); |
1159 | |
1160 | /* If the instruction has a one byte operand and immediate addressing is |
1161 | ** allowed but not used, check for an operand expression in the form |
1162 | ** <label or >label, where label is a far or absolute label. If found, |
1163 | ** emit a warning. This warning protects against a typo, where the '#' |
1164 | ** for the immediate operand is omitted. |
1165 | */ |
1166 | if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM) && |
1167 | (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) && |
1168 | ExtBytes[A->AddrMode] == 1) { |
1169 | |
1170 | /* Found, check the expression */ |
1171 | ExprNode* Left = A->Expr->Left; |
1172 | if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) && |
1173 | Left->Op == EXPR_SYMBOL && |
1174 | GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) { |
1175 | |
1176 | /* Output a warning */ |
1177 | Warning (1, "Suspicious address expression" ); |
1178 | } |
1179 | } |
1180 | |
1181 | /* Build the opcode */ |
1182 | A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode]; |
1183 | |
1184 | /* If feature force_range is active, and we have immediate addressing mode, |
1185 | ** limit the expression to the maximum possible value. |
1186 | */ |
1187 | if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX || |
1188 | A->AddrMode == AM65I_IMM_IMPLICIT || A->AddrMode == AM65I_IMM_IMPLICIT_WORD) { |
1189 | if (ForceRange && A->Expr) { |
1190 | A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]); |
1191 | } |
1192 | } |
1193 | |
1194 | /* Success */ |
1195 | return 1; |
1196 | } |
1197 | |
1198 | |
1199 | |
1200 | static void EmitCode (EffAddr* A) |
1201 | /* Output code for the data in A */ |
1202 | { |
1203 | /* Check how many extension bytes are needed and output the instruction */ |
1204 | switch (ExtBytes[A->AddrMode]) { |
1205 | |
1206 | case 0: |
1207 | Emit0 (A->Opcode); |
1208 | break; |
1209 | |
1210 | case 1: |
1211 | Emit1 (A->Opcode, A->Expr); |
1212 | break; |
1213 | |
1214 | case 2: |
1215 | if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) { |
1216 | /* This is a 16 bit mode that uses an address. If in 65816, |
1217 | ** mode, force this address into 16 bit range to allow |
1218 | ** addressing inside a 64K segment. |
1219 | */ |
1220 | Emit2 (A->Opcode, GenNearAddrExpr (A->Expr)); |
1221 | } else { |
1222 | Emit2 (A->Opcode, A->Expr); |
1223 | } |
1224 | break; |
1225 | |
1226 | case 3: |
1227 | /* Far argument */ |
1228 | Emit3 (A->Opcode, A->Expr); |
1229 | break; |
1230 | |
1231 | default: |
1232 | Internal ("Invalid operand byte count: %u" , ExtBytes[A->AddrMode]); |
1233 | |
1234 | } |
1235 | } |
1236 | |
1237 | |
1238 | |
1239 | static long PutImmed8 (const InsDesc* Ins) |
1240 | /* Parse and emit an immediate 8 bit instruction. Return the value of the |
1241 | ** operand if it's available and const. |
1242 | */ |
1243 | { |
1244 | EffAddr A; |
1245 | long Val = -1; |
1246 | |
1247 | /* Evaluate the addressing mode */ |
1248 | if (EvalEA (Ins, &A) == 0) { |
1249 | /* An error occurred */ |
1250 | return -1L; |
1251 | } |
1252 | |
1253 | /* If we have an expression and it's const, get it's value */ |
1254 | if (A.Expr) { |
1255 | (void) IsConstExpr (A.Expr, &Val); |
1256 | } |
1257 | |
1258 | /* Check how many extension bytes are needed and output the instruction */ |
1259 | switch (ExtBytes[A.AddrMode]) { |
1260 | |
1261 | case 1: |
1262 | Emit1 (A.Opcode, A.Expr); |
1263 | break; |
1264 | |
1265 | default: |
1266 | Internal ("Invalid operand byte count: %u" , ExtBytes[A.AddrMode]); |
1267 | } |
1268 | |
1269 | /* Return the expression value */ |
1270 | return Val; |
1271 | } |
1272 | |
1273 | |
1274 | |
1275 | static void PutPCRel8 (const InsDesc* Ins) |
1276 | /* Handle branches with a 8 bit distance */ |
1277 | { |
1278 | EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1); |
1279 | } |
1280 | |
1281 | |
1282 | |
1283 | static void PutPCRel16 (const InsDesc* Ins) |
1284 | /* Handle branches with an 16 bit distance and PER */ |
1285 | { |
1286 | EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2); |
1287 | } |
1288 | |
1289 | |
1290 | |
1291 | static void PutPCRel4510 (const InsDesc* Ins) |
1292 | /* Handle branches with a 16 bit distance */ |
1293 | { |
1294 | /* 16 bit branch opcode is 8 bit branch opcode or'ed with 0x03 */ |
1295 | EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 2); |
1296 | } |
1297 | |
1298 | |
1299 | |
1300 | static void PutBlockMove (const InsDesc* Ins) |
1301 | /* Handle the blockmove instructions (65816) */ |
1302 | { |
1303 | ExprNode* Arg1; |
1304 | ExprNode* Arg2; |
1305 | |
1306 | Emit0 (Ins->BaseCode); |
1307 | |
1308 | if (CurTok.Tok == TOK_HASH) { |
1309 | /* The operand is a bank-byte expression. */ |
1310 | NextTok (); |
1311 | Arg1 = Expression (); |
1312 | } else { |
1313 | /* The operand is a far-address expression. |
1314 | ** Use only its bank part. |
1315 | */ |
1316 | Arg1 = FuncBankByte (); |
1317 | } |
1318 | ConsumeComma (); |
1319 | |
1320 | if (CurTok.Tok == TOK_HASH) { |
1321 | NextTok (); |
1322 | Arg2 = Expression (); |
1323 | } else { |
1324 | Arg2 = FuncBankByte (); |
1325 | } |
1326 | |
1327 | /* The operands are written in Assembly code as source, destination; |
1328 | ** but, they're assembled as <destination> <source>. |
1329 | */ |
1330 | EmitByte (Arg2); |
1331 | EmitByte (Arg1); |
1332 | } |
1333 | |
1334 | |
1335 | |
1336 | static void PutBlockTransfer (const InsDesc* Ins) |
1337 | /* Handle the block transfer instructions (HuC6280) */ |
1338 | { |
1339 | Emit0 (Ins->BaseCode); |
1340 | EmitWord (Expression ()); |
1341 | ConsumeComma (); |
1342 | EmitWord (Expression ()); |
1343 | ConsumeComma (); |
1344 | EmitWord (Expression ()); |
1345 | } |
1346 | |
1347 | |
1348 | |
1349 | static void PutBitBranch (const InsDesc* Ins) |
1350 | /* Handle 65C02 branch on bit condition */ |
1351 | { |
1352 | Emit0 (Ins->BaseCode); |
1353 | EmitByte (Expression ()); |
1354 | ConsumeComma (); |
1355 | EmitSigned (GenBranchExpr (1), 1); |
1356 | } |
1357 | |
1358 | |
1359 | |
1360 | static void PutREP (const InsDesc* Ins) |
1361 | /* Emit a REP instruction, track register sizes */ |
1362 | { |
1363 | /* Use the generic handler */ |
1364 | long Val = PutImmed8 (Ins); |
1365 | |
1366 | /* We track the status only for the 816 CPU and in smart mode */ |
1367 | if (CPU == CPU_65816 && SmartMode) { |
1368 | |
1369 | /* Check the range for Val. */ |
1370 | if (Val < 0) { |
1371 | /* We had an error */ |
1372 | Warning (1, "Cannot track processor status byte" ); |
1373 | } else { |
1374 | if (Val & 0x10) { |
1375 | /* Index registers to 16 bit */ |
1376 | ExtBytes[AM65I_IMM_INDEX] = 2; |
1377 | } |
1378 | if (Val & 0x20) { |
1379 | /* Accu to 16 bit */ |
1380 | ExtBytes[AM65I_IMM_ACCU] = 2; |
1381 | } |
1382 | } |
1383 | } |
1384 | } |
1385 | |
1386 | |
1387 | |
1388 | static void PutSEP (const InsDesc* Ins) |
1389 | /* Emit a SEP instruction (65816), track register sizes */ |
1390 | { |
1391 | /* Use the generic handler */ |
1392 | long Val = PutImmed8 (Ins); |
1393 | |
1394 | /* We track the status only for the 816 CPU and in smart mode */ |
1395 | if (CPU == CPU_65816 && SmartMode) { |
1396 | |
1397 | /* Check the range for Val. */ |
1398 | if (Val < 0) { |
1399 | /* We had an error */ |
1400 | Warning (1, "Cannot track processor status byte" ); |
1401 | } else { |
1402 | if (Val & 0x10) { |
1403 | /* Index registers to 8 bit */ |
1404 | ExtBytes[AM65I_IMM_INDEX] = 1; |
1405 | } |
1406 | if (Val & 0x20) { |
1407 | /* Accu to 8 bit */ |
1408 | ExtBytes[AM65I_IMM_ACCU] = 1; |
1409 | } |
1410 | } |
1411 | } |
1412 | } |
1413 | |
1414 | |
1415 | |
1416 | static void PutTAMn (const InsDesc* Ins) |
1417 | /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with |
1418 | ** implicit addressing mode, the opcode byte in the table is actually the |
1419 | ** second operand byte. The TAM instruction is the more generic form, it takes |
1420 | ** an immediate argument. |
1421 | */ |
1422 | { |
1423 | /* Emit the TAM opcode itself */ |
1424 | Emit0 (0x53); |
1425 | |
1426 | /* Emit the argument, which is the opcode from the table */ |
1427 | Emit0 (Ins->BaseCode); |
1428 | } |
1429 | |
1430 | |
1431 | |
1432 | static void PutTMA (const InsDesc* Ins) |
1433 | /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit |
1434 | ** in the argument byte may be set. |
1435 | */ |
1436 | { |
1437 | /* Use the generic handler */ |
1438 | long Val = PutImmed8 (Ins); |
1439 | |
1440 | /* Check the range for Val. */ |
1441 | if (Val < 0) { |
1442 | /* We had an error */ |
1443 | Warning (1, "Cannot check argument of TMA instruction" ); |
1444 | } else { |
1445 | /* Make sure just one bit is set */ |
1446 | if ((Val & (Val - 1)) != 0) { |
1447 | Error ("Argument to TAM must be a power of two" ); |
1448 | } |
1449 | } |
1450 | } |
1451 | |
1452 | |
1453 | |
1454 | static void PutTMAn (const InsDesc* Ins) |
1455 | /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with |
1456 | ** implicit addressing mode, the opcode byte in the table is actually the |
1457 | ** second operand byte. The TAM instruction is the more generic form, it takes |
1458 | ** an immediate argument. |
1459 | */ |
1460 | { |
1461 | /* Emit the TMA opcode itself */ |
1462 | Emit0 (0x43); |
1463 | |
1464 | /* Emit the argument, which is the opcode from the table */ |
1465 | Emit0 (Ins->BaseCode); |
1466 | } |
1467 | |
1468 | |
1469 | |
1470 | static void PutTST (const InsDesc* Ins) |
1471 | /* Emit a TST instruction (HuC6280). */ |
1472 | { |
1473 | ExprNode* Arg1; |
1474 | EffAddr A; |
1475 | |
1476 | /* The first argument is always an immediate byte */ |
1477 | if (CurTok.Tok != TOK_HASH) { |
1478 | ErrorSkip ("Invalid addressing mode" ); |
1479 | return; |
1480 | } |
1481 | NextTok (); |
1482 | Arg1 = Expression (); |
1483 | |
1484 | /* Second argument follows */ |
1485 | ConsumeComma (); |
1486 | |
1487 | /* For the second argument, we use the standard function */ |
1488 | if (EvalEA (Ins, &A)) { |
1489 | |
1490 | /* No error, output code */ |
1491 | Emit1 (A.Opcode, Arg1); |
1492 | |
1493 | /* Check how many extension bytes are needed and output the instruction */ |
1494 | switch (ExtBytes[A.AddrMode]) { |
1495 | |
1496 | case 1: |
1497 | EmitByte (A.Expr); |
1498 | break; |
1499 | |
1500 | case 2: |
1501 | EmitWord (A.Expr); |
1502 | break; |
1503 | } |
1504 | } |
1505 | } |
1506 | |
1507 | |
1508 | |
1509 | static void PutJMP (const InsDesc* Ins) |
1510 | /* Handle the jump instruction for the 6502. Problem is that these chips have |
1511 | ** a bug: If the address crosses a page, the upper byte gets not corrected and |
1512 | ** the instruction will fail. The PutJmp function will add a linker assertion |
1513 | ** to check for this case and is otherwise identical to PutAll. |
1514 | */ |
1515 | { |
1516 | EffAddr A; |
1517 | |
1518 | /* Evaluate the addressing mode used */ |
1519 | if (EvalEA (Ins, &A)) { |
1520 | |
1521 | /* Check for indirect addressing */ |
1522 | if (A.AddrModeBit & AM65_ABS_IND) { |
1523 | |
1524 | /* Compare the low byte of the expression to 0xFF to check for |
1525 | ** a page cross. Be sure to use a copy of the expression otherwise |
1526 | ** things will go weird later. |
1527 | */ |
1528 | ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF); |
1529 | |
1530 | /* Generate the message */ |
1531 | unsigned Msg = GetStringId ("\"jmp (abs)\" across page border" ); |
1532 | |
1533 | /* Generate the assertion */ |
1534 | AddAssertion (E, ASSERT_ACT_WARN, Msg); |
1535 | } |
1536 | |
1537 | /* No error, output code */ |
1538 | EmitCode (&A); |
1539 | } |
1540 | } |
1541 | |
1542 | |
1543 | |
1544 | static void PutRTS (const InsDesc* Ins attribute ((unused))) |
1545 | /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if |
1546 | ** the enclosing scope is FAR. |
1547 | */ |
1548 | { |
1549 | if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) { |
1550 | Emit0 (0x6B); /* RTL */ |
1551 | } else { |
1552 | Emit0 (0x60); /* RTS */ |
1553 | } |
1554 | } |
1555 | |
1556 | |
1557 | |
1558 | static void PutAll (const InsDesc* Ins) |
1559 | /* Handle all other instructions */ |
1560 | { |
1561 | EffAddr A; |
1562 | |
1563 | /* Evaluate the addressing mode used */ |
1564 | if (EvalEA (Ins, &A)) { |
1565 | /* No error, output code */ |
1566 | EmitCode (&A); |
1567 | } |
1568 | } |
1569 | |
1570 | |
1571 | |
1572 | static void Put4510 (const InsDesc* Ins) |
1573 | /* Handle all other instructions, with modifications for 4510 */ |
1574 | { |
1575 | /* The 4510 uses all 256 possible opcodes, so the last ones were crammed |
1576 | ** in where an opcode was still undefined. As a result, some of those |
1577 | ** don't follow any rules for encoding the addressmodes. So the EATab |
1578 | ** approach does not work always. In this function, the wrongly calculated |
1579 | ** opcode is replaced by the correct one "on the fly". Suggestions for a |
1580 | ** better approach are welcome. |
1581 | ** |
1582 | ** These are: |
1583 | ** $47 -> $44 : ASR $12 |
1584 | ** $57 -> $54 : ASR $12,X |
1585 | ** $93 -> $82 : STA ($12,SP),Y |
1586 | ** $9c -> $8b : STY $1234,X |
1587 | ** $9e -> $9b : STX $1234,Y |
1588 | ** $af -> $ab : LDZ $1234 |
1589 | ** $bf -> $bb : LDZ $1234,X |
1590 | ** $b3 -> $e2 : LDA ($12,SP),Y |
1591 | ** $d0 -> $c2 : CPZ #$00 |
1592 | ** $fc -> $23 : JSR ($1234,X) |
1593 | */ |
1594 | EffAddr A; |
1595 | |
1596 | /* Evaluate the addressing mode used */ |
1597 | if (EvalEA (Ins, &A)) { |
1598 | switch (A.Opcode) { |
1599 | case 0x47: A.Opcode = 0x44; break; |
1600 | case 0x57: A.Opcode = 0x54; break; |
1601 | case 0x93: A.Opcode = 0x82; break; |
1602 | case 0x9C: A.Opcode = 0x8B; break; |
1603 | case 0x9E: A.Opcode = 0x9B; break; |
1604 | case 0xAF: A.Opcode = 0xAB; break; |
1605 | case 0xBF: A.Opcode = 0xBB; break; |
1606 | case 0xB3: A.Opcode = 0xE2; break; |
1607 | case 0xD0: A.Opcode = 0xC2; break; |
1608 | case 0xFC: A.Opcode = 0x23; break; |
1609 | default: /* Keep opcode as it is */ break; |
1610 | } |
1611 | |
1612 | /* No error, output code */ |
1613 | EmitCode (&A); |
1614 | } |
1615 | } |
1616 | |
1617 | |
1618 | |
1619 | /*****************************************************************************/ |
1620 | /* Handler functions for SWEET16 */ |
1621 | /*****************************************************************************/ |
1622 | |
1623 | |
1624 | |
1625 | static void PutSweet16 (const InsDesc* Ins) |
1626 | /* Handle a generic sweet16 instruction */ |
1627 | { |
1628 | EffAddr A; |
1629 | |
1630 | /* Evaluate the addressing mode used */ |
1631 | GetSweet16EA (&A); |
1632 | |
1633 | /* From the possible addressing modes, remove the ones that are invalid |
1634 | ** for this instruction or CPU. |
1635 | */ |
1636 | A.AddrModeSet &= Ins->AddrMode; |
1637 | |
1638 | /* Check if we have any adressing modes left */ |
1639 | if (A.AddrModeSet == 0) { |
1640 | Error ("Illegal addressing mode" ); |
1641 | return; |
1642 | } |
1643 | A.AddrMode = BitFind (A.AddrModeSet); |
1644 | A.AddrModeBit = (0x01UL << A.AddrMode); |
1645 | |
1646 | /* Build the opcode */ |
1647 | A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg; |
1648 | |
1649 | /* Check how many extension bytes are needed and output the instruction */ |
1650 | switch (Sweet16ExtBytes[A.AddrMode]) { |
1651 | |
1652 | case 0: |
1653 | Emit0 (A.Opcode); |
1654 | break; |
1655 | |
1656 | case 1: |
1657 | Emit1 (A.Opcode, A.Expr); |
1658 | break; |
1659 | |
1660 | case 2: |
1661 | Emit2 (A.Opcode, A.Expr); |
1662 | break; |
1663 | |
1664 | default: |
1665 | Internal ("Invalid operand byte count: %u" , Sweet16ExtBytes[A.AddrMode]); |
1666 | |
1667 | } |
1668 | } |
1669 | |
1670 | |
1671 | |
1672 | static void PutSweet16Branch (const InsDesc* Ins) |
1673 | /* Handle a sweet16 branch instruction */ |
1674 | { |
1675 | EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1); |
1676 | } |
1677 | |
1678 | |
1679 | |
1680 | /*****************************************************************************/ |
1681 | /* Code */ |
1682 | /*****************************************************************************/ |
1683 | |
1684 | |
1685 | |
1686 | static int CmpName (const void* Key, const void* Instr) |
1687 | /* Compare function for bsearch */ |
1688 | { |
1689 | return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic); |
1690 | } |
1691 | |
1692 | |
1693 | |
1694 | void SetCPU (cpu_t NewCPU) |
1695 | /* Set a new CPU */ |
1696 | { |
1697 | /* Make sure the parameter is correct */ |
1698 | CHECK (NewCPU < CPU_COUNT); |
1699 | |
1700 | /* Check if we have support for the new CPU, if so, use it */ |
1701 | if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) { |
1702 | CPU = NewCPU; |
1703 | InsTab = InsTabs[CPU]; |
1704 | } else { |
1705 | Error ("CPU not supported" ); |
1706 | } |
1707 | } |
1708 | |
1709 | |
1710 | |
1711 | cpu_t GetCPU (void) |
1712 | /* Return the current CPU */ |
1713 | { |
1714 | return CPU; |
1715 | } |
1716 | |
1717 | |
1718 | |
1719 | int FindInstruction (const StrBuf* Ident) |
1720 | /* Check if Ident is a valid mnemonic. If so, return the index in the |
1721 | ** instruction table. If not, return -1. |
1722 | */ |
1723 | { |
1724 | unsigned I; |
1725 | const InsDesc* ID; |
1726 | char Key[sizeof (ID->Mnemonic)]; |
1727 | |
1728 | /* Shortcut for the "none" CPU: If there are no instructions to search |
1729 | ** for, bail out early. |
1730 | */ |
1731 | if (InsTab->Count == 0) { |
1732 | /* Not found */ |
1733 | return -1; |
1734 | } |
1735 | |
1736 | /* Make a copy, and uppercase that copy */ |
1737 | I = 0; |
1738 | while (I < SB_GetLen (Ident)) { |
1739 | /* If the identifier is longer than the longest mnemonic, it cannot |
1740 | ** be one. |
1741 | */ |
1742 | if (I >= sizeof (Key) - 1) { |
1743 | /* Not found, no need for further action */ |
1744 | return -1; |
1745 | } |
1746 | Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I)); |
1747 | ++I; |
1748 | } |
1749 | Key[I] = '\0'; |
1750 | |
1751 | /* Search for the key */ |
1752 | ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName); |
1753 | if (ID == 0) { |
1754 | /* Not found */ |
1755 | return -1; |
1756 | } else { |
1757 | /* Found, return the entry */ |
1758 | return ID - InsTab->Ins; |
1759 | } |
1760 | } |
1761 | |
1762 | |
1763 | |
1764 | void HandleInstruction (unsigned Index) |
1765 | /* Handle the mnemonic with the given index */ |
1766 | { |
1767 | /* Safety check */ |
1768 | PRECONDITION (Index < InsTab->Count); |
1769 | |
1770 | /* Skip the mnemonic token */ |
1771 | NextTok (); |
1772 | |
1773 | /* Call the handler */ |
1774 | InsTab->Ins[Index].Emit (&InsTab->Ins[Index]); |
1775 | } |
1776 | |