1 /*****************************************************************************/
5 /* Instruction encoding for the ca65 macroassembler */
9 /* (C) 1998-2004 Ullrich von Bassewitz */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
42 #include "assertdefs.h"
60 #include "studyexpr.h"
65 /*****************************************************************************/
67 /*****************************************************************************/
71 /* Forwards for handler functions */
72 static void PutPCRel8 (const InsDesc* Ins);
73 static void PutPCRel16 (const InsDesc* Ins);
74 static void PutBlockMove (const InsDesc* Ins);
75 static void PutBitBranch (const InsDesc* Ins);
76 static void PutREP (const InsDesc* Ins);
77 static void PutSEP (const InsDesc* Ins);
78 static void PutJMP (const InsDesc* Ins);
79 static void PutRTS (const InsDesc* Ins);
80 static void PutAll (const InsDesc* Ins);
81 static void PutSweet16 (const InsDesc* Ins);
82 static void PutSweet16Branch (const InsDesc* Ins);
86 /* Empty instruction table */
93 /* Instruction table for the 6502 */
98 sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]),
100 { "ADC", 0x080A26C, 0x60, 0, PutAll },
101 { "AND", 0x080A26C, 0x20, 0, PutAll },
102 { "ASL", 0x000006e, 0x02, 1, PutAll },
103 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
104 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
105 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
106 { "BIT", 0x000000C, 0x00, 2, PutAll },
107 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
108 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
109 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
110 { "BRK", 0x0000001, 0x00, 0, PutAll },
111 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
112 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
113 { "CLC", 0x0000001, 0x18, 0, PutAll },
114 { "CLD", 0x0000001, 0xd8, 0, PutAll },
115 { "CLI", 0x0000001, 0x58, 0, PutAll },
116 { "CLV", 0x0000001, 0xb8, 0, PutAll },
117 { "CMP", 0x080A26C, 0xc0, 0, PutAll },
118 { "CPX", 0x080000C, 0xe0, 1, PutAll },
119 { "CPY", 0x080000C, 0xc0, 1, PutAll },
120 { "DEC", 0x000006C, 0x00, 3, PutAll },
121 { "DEX", 0x0000001, 0xca, 0, PutAll },
122 { "DEY", 0x0000001, 0x88, 0, PutAll },
123 { "EOR", 0x080A26C, 0x40, 0, PutAll },
124 { "INC", 0x000006c, 0x00, 4, PutAll },
125 { "INX", 0x0000001, 0xe8, 0, PutAll },
126 { "INY", 0x0000001, 0xc8, 0, PutAll },
127 { "JMP", 0x0000808, 0x4c, 6, PutJMP },
128 { "JSR", 0x0000008, 0x20, 7, PutAll },
129 { "LDA", 0x080A26C, 0xa0, 0, PutAll },
130 { "LDX", 0x080030C, 0xa2, 1, PutAll },
131 { "LDY", 0x080006C, 0xa0, 1, PutAll },
132 { "LSR", 0x000006F, 0x42, 1, PutAll },
133 { "NOP", 0x0000001, 0xea, 0, PutAll },
134 { "ORA", 0x080A26C, 0x00, 0, PutAll },
135 { "PHA", 0x0000001, 0x48, 0, PutAll },
136 { "PHP", 0x0000001, 0x08, 0, PutAll },
137 { "PLA", 0x0000001, 0x68, 0, PutAll },
138 { "PLP", 0x0000001, 0x28, 0, PutAll },
139 { "ROL", 0x000006F, 0x22, 1, PutAll },
140 { "ROR", 0x000006F, 0x62, 1, PutAll },
141 { "RTI", 0x0000001, 0x40, 0, PutAll },
142 { "RTS", 0x0000001, 0x60, 0, PutAll },
143 { "SBC", 0x080A26C, 0xe0, 0, PutAll },
144 { "SEC", 0x0000001, 0x38, 0, PutAll },
145 { "SED", 0x0000001, 0xf8, 0, PutAll },
146 { "SEI", 0x0000001, 0x78, 0, PutAll },
147 { "STA", 0x000A26C, 0x80, 0, PutAll },
148 { "STX", 0x000010c, 0x82, 1, PutAll },
149 { "STY", 0x000002c, 0x80, 1, PutAll },
150 { "TAX", 0x0000001, 0xaa, 0, PutAll },
151 { "TAY", 0x0000001, 0xa8, 0, PutAll },
152 { "TSX", 0x0000001, 0xba, 0, PutAll },
153 { "TXA", 0x0000001, 0x8a, 0, PutAll },
154 { "TXS", 0x0000001, 0x9a, 0, PutAll },
155 { "TYA", 0x0000001, 0x98, 0, PutAll }
159 /* Instruction table for the 6502 with illegal instructions */
160 static const struct {
164 sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]),
166 { "ADC", 0x080A26C, 0x60, 0, PutAll },
167 { "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */
168 { "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */
169 { "AND", 0x080A26C, 0x20, 0, PutAll },
170 { "ARR", 0x0800000, 0x6B, 0, PutAll }, /* X */
171 { "ASL", 0x000006e, 0x02, 1, PutAll },
172 { "AXS", 0x0800000, 0xCB, 0, PutAll }, /* X */
173 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
174 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
175 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
176 { "BIT", 0x000000C, 0x00, 2, PutAll },
177 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
178 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
179 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
180 { "BRK", 0x0000001, 0x00, 0, PutAll },
181 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
182 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
183 { "CLC", 0x0000001, 0x18, 0, PutAll },
184 { "CLD", 0x0000001, 0xd8, 0, PutAll },
185 { "CLI", 0x0000001, 0x58, 0, PutAll },
186 { "CLV", 0x0000001, 0xb8, 0, PutAll },
187 { "CMP", 0x080A26C, 0xc0, 0, PutAll },
188 { "CPX", 0x080000C, 0xe0, 1, PutAll },
189 { "CPY", 0x080000C, 0xc0, 1, PutAll },
190 { "DCP", 0x000A26C, 0xC3, 0, PutAll }, /* X */
191 { "DEC", 0x000006C, 0x00, 3, PutAll },
192 { "DEX", 0x0000001, 0xca, 0, PutAll },
193 { "DEY", 0x0000001, 0x88, 0, PutAll },
194 { "EOR", 0x080A26C, 0x40, 0, PutAll },
195 { "INC", 0x000006c, 0x00, 4, PutAll },
196 { "INX", 0x0000001, 0xe8, 0, PutAll },
197 { "INY", 0x0000001, 0xc8, 0, PutAll },
198 { "ISC", 0x000A26C, 0xE3, 0, PutAll }, /* X */
199 { "JAM", 0x0000001, 0x02, 0, PutAll }, /* X */
200 { "JMP", 0x0000808, 0x4c, 6, PutJMP },
201 { "JSR", 0x0000008, 0x20, 7, PutAll },
202 { "LAS", 0x0000200, 0xBB, 0, PutAll }, /* X */
203 { "LAX", 0x000A30C, 0xA3, 1, PutAll }, /* X */
204 { "LDA", 0x080A26C, 0xa0, 0, PutAll },
205 { "LDX", 0x080030C, 0xa2, 1, PutAll },
206 { "LDY", 0x080006C, 0xa0, 1, PutAll },
207 { "LSR", 0x000006F, 0x42, 1, PutAll },
208 { "NOP", 0x0000001, 0xea, 0, PutAll },
209 { "ORA", 0x080A26C, 0x00, 0, PutAll },
210 { "PHA", 0x0000001, 0x48, 0, PutAll },
211 { "PHP", 0x0000001, 0x08, 0, PutAll },
212 { "PLA", 0x0000001, 0x68, 0, PutAll },
213 { "PLP", 0x0000001, 0x28, 0, PutAll },
214 { "RLA", 0x000A26C, 0x23, 0, PutAll }, /* X */
215 { "ROL", 0x000006F, 0x22, 1, PutAll },
216 { "ROR", 0x000006F, 0x62, 1, PutAll },
217 { "RRA", 0x000A26C, 0x63, 0, PutAll }, /* X */
218 { "RTI", 0x0000001, 0x40, 0, PutAll },
219 { "RTS", 0x0000001, 0x60, 0, PutAll },
220 { "SAX", 0x000810C, 0x83, 1, PutAll }, /* X */
221 { "SBC", 0x080A26C, 0xe0, 0, PutAll },
222 { "SEC", 0x0000001, 0x38, 0, PutAll },
223 { "SED", 0x0000001, 0xf8, 0, PutAll },
224 { "SEI", 0x0000001, 0x78, 0, PutAll },
225 { "SLO", 0x000A26C, 0x03, 0, PutAll }, /* X */
226 { "SRE", 0x000A26C, 0x43, 0, PutAll }, /* X */
227 { "STA", 0x000A26C, 0x80, 0, PutAll },
228 { "STX", 0x000010c, 0x82, 1, PutAll },
229 { "STY", 0x000002c, 0x80, 1, PutAll },
230 { "TAX", 0x0000001, 0xaa, 0, PutAll },
231 { "TAY", 0x0000001, 0xa8, 0, PutAll },
232 { "TSX", 0x0000001, 0xba, 0, PutAll },
233 { "TXA", 0x0000001, 0x8a, 0, PutAll },
234 { "TXS", 0x0000001, 0x9a, 0, PutAll },
235 { "TYA", 0x0000001, 0x98, 0, PutAll }
239 /* Instruction table for the 65SC02 */
240 static const struct {
244 sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]),
246 { "ADC", 0x080A66C, 0x60, 0, PutAll },
247 { "AND", 0x080A66C, 0x20, 0, PutAll },
248 { "ASL", 0x000006e, 0x02, 1, PutAll },
249 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
250 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
251 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
252 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
253 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
254 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
255 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
256 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
257 { "BRK", 0x0000001, 0x00, 0, PutAll },
258 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
259 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
260 { "CLC", 0x0000001, 0x18, 0, PutAll },
261 { "CLD", 0x0000001, 0xd8, 0, PutAll },
262 { "CLI", 0x0000001, 0x58, 0, PutAll },
263 { "CLV", 0x0000001, 0xb8, 0, PutAll },
264 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
265 { "CPX", 0x080000C, 0xe0, 1, PutAll },
266 { "CPY", 0x080000C, 0xc0, 1, PutAll },
267 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
268 { "DEC", 0x000006F, 0x00, 3, PutAll },
269 { "DEX", 0x0000001, 0xca, 0, PutAll },
270 { "DEY", 0x0000001, 0x88, 0, PutAll },
271 { "EOR", 0x080A66C, 0x40, 0, PutAll },
272 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
273 { "INC", 0x000006f, 0x00, 4, PutAll },
274 { "INX", 0x0000001, 0xe8, 0, PutAll },
275 { "INY", 0x0000001, 0xc8, 0, PutAll },
276 { "JMP", 0x0010808, 0x4c, 6, PutAll },
277 { "JSR", 0x0000008, 0x20, 7, PutAll },
278 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
279 { "LDX", 0x080030C, 0xa2, 1, PutAll },
280 { "LDY", 0x080006C, 0xa0, 1, PutAll },
281 { "LSR", 0x000006F, 0x42, 1, PutAll },
282 { "NOP", 0x0000001, 0xea, 0, PutAll },
283 { "ORA", 0x080A66C, 0x00, 0, PutAll },
284 { "PHA", 0x0000001, 0x48, 0, PutAll },
285 { "PHP", 0x0000001, 0x08, 0, PutAll },
286 { "PHX", 0x0000001, 0xda, 0, PutAll },
287 { "PHY", 0x0000001, 0x5a, 0, PutAll },
288 { "PLA", 0x0000001, 0x68, 0, PutAll },
289 { "PLP", 0x0000001, 0x28, 0, PutAll },
290 { "PLX", 0x0000001, 0xfa, 0, PutAll },
291 { "PLY", 0x0000001, 0x7a, 0, PutAll },
292 { "ROL", 0x000006F, 0x22, 1, PutAll },
293 { "ROR", 0x000006F, 0x62, 1, PutAll },
294 { "RTI", 0x0000001, 0x40, 0, PutAll },
295 { "RTS", 0x0000001, 0x60, 0, PutAll },
296 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
297 { "SEC", 0x0000001, 0x38, 0, PutAll },
298 { "SED", 0x0000001, 0xf8, 0, PutAll },
299 { "SEI", 0x0000001, 0x78, 0, PutAll },
300 { "STA", 0x000A66C, 0x80, 0, PutAll },
301 { "STX", 0x000010c, 0x82, 1, PutAll },
302 { "STY", 0x000002c, 0x80, 1, PutAll },
303 { "STZ", 0x000006c, 0x04, 5, PutAll },
304 { "TAX", 0x0000001, 0xaa, 0, PutAll },
305 { "TAY", 0x0000001, 0xa8, 0, PutAll },
306 { "TRB", 0x000000c, 0x10, 1, PutAll },
307 { "TSB", 0x000000c, 0x00, 1, PutAll },
308 { "TSX", 0x0000001, 0xba, 0, PutAll },
309 { "TXA", 0x0000001, 0x8a, 0, PutAll },
310 { "TXS", 0x0000001, 0x9a, 0, PutAll },
311 { "TYA", 0x0000001, 0x98, 0, PutAll }
315 /* Instruction table for the 65C02 */
316 static const struct {
320 sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]),
322 { "ADC", 0x080A66C, 0x60, 0, PutAll },
323 { "AND", 0x080A66C, 0x20, 0, PutAll },
324 { "ASL", 0x000006e, 0x02, 1, PutAll },
325 { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
326 { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
327 { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
328 { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
329 { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
330 { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
331 { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
332 { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
333 { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
334 { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
335 { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
336 { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
337 { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
338 { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
339 { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
340 { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
341 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
342 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
343 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
344 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
345 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
346 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
347 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
348 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
349 { "BRK", 0x0000001, 0x00, 0, PutAll },
350 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
351 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
352 { "CLC", 0x0000001, 0x18, 0, PutAll },
353 { "CLD", 0x0000001, 0xd8, 0, PutAll },
354 { "CLI", 0x0000001, 0x58, 0, PutAll },
355 { "CLV", 0x0000001, 0xb8, 0, PutAll },
356 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
357 { "CPX", 0x080000C, 0xe0, 1, PutAll },
358 { "CPY", 0x080000C, 0xc0, 1, PutAll },
359 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
360 { "DEC", 0x000006F, 0x00, 3, PutAll },
361 { "DEX", 0x0000001, 0xca, 0, PutAll },
362 { "DEY", 0x0000001, 0x88, 0, PutAll },
363 { "EOR", 0x080A66C, 0x40, 0, PutAll },
364 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
365 { "INC", 0x000006f, 0x00, 4, PutAll },
366 { "INX", 0x0000001, 0xe8, 0, PutAll },
367 { "INY", 0x0000001, 0xc8, 0, PutAll },
368 { "JMP", 0x0010808, 0x4c, 6, PutAll },
369 { "JSR", 0x0000008, 0x20, 7, PutAll },
370 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
371 { "LDX", 0x080030C, 0xa2, 1, PutAll },
372 { "LDY", 0x080006C, 0xa0, 1, PutAll },
373 { "LSR", 0x000006F, 0x42, 1, PutAll },
374 { "NOP", 0x0000001, 0xea, 0, PutAll },
375 { "ORA", 0x080A66C, 0x00, 0, PutAll },
376 { "PHA", 0x0000001, 0x48, 0, PutAll },
377 { "PHP", 0x0000001, 0x08, 0, PutAll },
378 { "PHX", 0x0000001, 0xda, 0, PutAll },
379 { "PHY", 0x0000001, 0x5a, 0, PutAll },
380 { "PLA", 0x0000001, 0x68, 0, PutAll },
381 { "PLP", 0x0000001, 0x28, 0, PutAll },
382 { "PLX", 0x0000001, 0xfa, 0, PutAll },
383 { "PLY", 0x0000001, 0x7a, 0, PutAll },
384 { "RMB0", 0x0000004, 0x07, 1, PutAll },
385 { "RMB1", 0x0000004, 0x17, 1, PutAll },
386 { "RMB2", 0x0000004, 0x27, 1, PutAll },
387 { "RMB3", 0x0000004, 0x37, 1, PutAll },
388 { "RMB4", 0x0000004, 0x47, 1, PutAll },
389 { "RMB5", 0x0000004, 0x57, 1, PutAll },
390 { "RMB6", 0x0000004, 0x67, 1, PutAll },
391 { "RMB7", 0x0000004, 0x77, 1, PutAll },
392 { "ROL", 0x000006F, 0x22, 1, PutAll },
393 { "ROR", 0x000006F, 0x62, 1, PutAll },
394 { "RTI", 0x0000001, 0x40, 0, PutAll },
395 { "RTS", 0x0000001, 0x60, 0, PutAll },
396 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
397 { "SEC", 0x0000001, 0x38, 0, PutAll },
398 { "SED", 0x0000001, 0xf8, 0, PutAll },
399 { "SEI", 0x0000001, 0x78, 0, PutAll },
400 { "SMB0", 0x0000004, 0x87, 1, PutAll },
401 { "SMB1", 0x0000004, 0x97, 1, PutAll },
402 { "SMB2", 0x0000004, 0xA7, 1, PutAll },
403 { "SMB3", 0x0000004, 0xB7, 1, PutAll },
404 { "SMB4", 0x0000004, 0xC7, 1, PutAll },
405 { "SMB5", 0x0000004, 0xD7, 1, PutAll },
406 { "SMB6", 0x0000004, 0xE7, 1, PutAll },
407 { "SMB7", 0x0000004, 0xF7, 1, PutAll },
408 { "STA", 0x000A66C, 0x80, 0, PutAll },
409 { "STX", 0x000010c, 0x82, 1, PutAll },
410 { "STY", 0x000002c, 0x80, 1, PutAll },
411 { "STZ", 0x000006c, 0x04, 5, PutAll },
412 { "TAX", 0x0000001, 0xaa, 0, PutAll },
413 { "TAY", 0x0000001, 0xa8, 0, PutAll },
414 { "TRB", 0x000000c, 0x10, 1, PutAll },
415 { "TSB", 0x000000c, 0x00, 1, PutAll },
416 { "TSX", 0x0000001, 0xba, 0, PutAll },
417 { "TXA", 0x0000001, 0x8a, 0, PutAll },
418 { "TXS", 0x0000001, 0x9a, 0, PutAll },
419 { "TYA", 0x0000001, 0x98, 0, PutAll }
423 /* Instruction table for the 65816 */
424 static const struct {
428 sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]),
430 { "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
431 { "AND", 0x0b8f6fc, 0x20, 0, PutAll },
432 { "ASL", 0x000006e, 0x02, 1, PutAll },
433 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
434 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
435 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
436 { "BGE", 0x0020000, 0xb0, 0, PutPCRel8 }, /* == BCS */
437 { "BIT", 0x0a0006c, 0x00, 2, PutAll },
438 { "BLT", 0x0020000, 0x90, 0, PutPCRel8 }, /* == BCC */
439 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
440 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
441 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
442 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
443 { "BRK", 0x0000001, 0x00, 0, PutAll },
444 { "BRL", 0x0040000, 0x82, 0, PutPCRel16 },
445 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
446 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
447 { "CLC", 0x0000001, 0x18, 0, PutAll },
448 { "CLD", 0x0000001, 0xd8, 0, PutAll },
449 { "CLI", 0x0000001, 0x58, 0, PutAll },
450 { "CLV", 0x0000001, 0xb8, 0, PutAll },
451 { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll },
452 { "COP", 0x0000004, 0x02, 6, PutAll },
453 { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */
454 { "CPX", 0x0c0000c, 0xe0, 1, PutAll },
455 { "CPY", 0x0c0000c, 0xc0, 1, PutAll },
456 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
457 { "DEC", 0x000006F, 0x00, 3, PutAll },
458 { "DEX", 0x0000001, 0xca, 0, PutAll },
459 { "DEY", 0x0000001, 0x88, 0, PutAll },
460 { "EOR", 0x0b8f6fc, 0x40, 0, PutAll },
461 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
462 { "INC", 0x000006F, 0x00, 4, PutAll },
463 { "INX", 0x0000001, 0xe8, 0, PutAll },
464 { "INY", 0x0000001, 0xc8, 0, PutAll },
465 { "JML", 0x0000810, 0x5c, 1, PutAll },
466 { "JMP", 0x0010818, 0x4c, 6, PutAll },
467 { "JSL", 0x0000010, 0x20, 7, PutAll },
468 { "JSR", 0x0010018, 0x20, 7, PutAll },
469 { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
470 { "LDX", 0x0c0030c, 0xa2, 1, PutAll },
471 { "LDY", 0x0c0006c, 0xa0, 1, PutAll },
472 { "LSR", 0x000006F, 0x42, 1, PutAll },
473 { "MVN", 0x1000000, 0x54, 0, PutBlockMove },
474 { "MVP", 0x1000000, 0x44, 0, PutBlockMove },
475 { "NOP", 0x0000001, 0xea, 0, PutAll },
476 { "ORA", 0x0b8f6fc, 0x00, 0, PutAll },
477 { "PEA", 0x0000008, 0xf4, 6, PutAll },
478 { "PEI", 0x0000400, 0xd4, 1, PutAll },
479 { "PER", 0x0040000, 0x62, 0, PutPCRel16 },
480 { "PHA", 0x0000001, 0x48, 0, PutAll },
481 { "PHB", 0x0000001, 0x8b, 0, PutAll },
482 { "PHD", 0x0000001, 0x0b, 0, PutAll },
483 { "PHK", 0x0000001, 0x4b, 0, PutAll },
484 { "PHP", 0x0000001, 0x08, 0, PutAll },
485 { "PHX", 0x0000001, 0xda, 0, PutAll },
486 { "PHY", 0x0000001, 0x5a, 0, PutAll },
487 { "PLA", 0x0000001, 0x68, 0, PutAll },
488 { "PLB", 0x0000001, 0xab, 0, PutAll },
489 { "PLD", 0x0000001, 0x2b, 0, PutAll },
490 { "PLP", 0x0000001, 0x28, 0, PutAll },
491 { "PLX", 0x0000001, 0xfa, 0, PutAll },
492 { "PLY", 0x0000001, 0x7a, 0, PutAll },
493 { "REP", 0x0800000, 0xc2, 1, PutREP },
494 { "ROL", 0x000006F, 0x22, 1, PutAll },
495 { "ROR", 0x000006F, 0x62, 1, PutAll },
496 { "RTI", 0x0000001, 0x40, 0, PutAll },
497 { "RTL", 0x0000001, 0x6b, 0, PutAll },
498 { "RTS", 0x0000001, 0x60, 0, PutRTS },
499 { "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
500 { "SEC", 0x0000001, 0x38, 0, PutAll },
501 { "SED", 0x0000001, 0xf8, 0, PutAll },
502 { "SEI", 0x0000001, 0x78, 0, PutAll },
503 { "SEP", 0x0800000, 0xe2, 1, PutSEP },
504 { "STA", 0x018f6fc, 0x80, 0, PutAll },
505 { "STP", 0x0000001, 0xdb, 0, PutAll },
506 { "STX", 0x000010c, 0x82, 1, PutAll },
507 { "STY", 0x000002c, 0x80, 1, PutAll },
508 { "STZ", 0x000006c, 0x04, 5, PutAll },
509 { "SWA", 0x0000001, 0xeb, 0, PutAll }, /* == XBA */
510 { "TAD", 0x0000001, 0x5b, 0, PutAll }, /* == TCD */
511 { "TAS", 0x0000001, 0x1b, 0, PutAll }, /* == TCS */
512 { "TAX", 0x0000001, 0xaa, 0, PutAll },
513 { "TAY", 0x0000001, 0xa8, 0, PutAll },
514 { "TCD", 0x0000001, 0x5b, 0, PutAll },
515 { "TCS", 0x0000001, 0x1b, 0, PutAll },
516 { "TDA", 0x0000001, 0x7b, 0, PutAll }, /* == TDC */
517 { "TDC", 0x0000001, 0x7b, 0, PutAll },
518 { "TRB", 0x000000c, 0x10, 1, PutAll },
519 { "TSA", 0x0000001, 0x3b, 0, PutAll }, /* == TSC */
520 { "TSB", 0x000000c, 0x00, 1, PutAll },
521 { "TSC", 0x0000001, 0x3b, 0, PutAll },
522 { "TSX", 0x0000001, 0xba, 0, PutAll },
523 { "TXA", 0x0000001, 0x8a, 0, PutAll },
524 { "TXS", 0x0000001, 0x9a, 0, PutAll },
525 { "TXY", 0x0000001, 0x9b, 0, PutAll },
526 { "TYA", 0x0000001, 0x98, 0, PutAll },
527 { "TYX", 0x0000001, 0xbb, 0, PutAll },
528 { "WAI", 0x0000001, 0xcb, 0, PutAll },
529 { "XBA", 0x0000001, 0xeb, 0, PutAll },
530 { "XCE", 0x0000001, 0xfb, 0, PutAll }
535 /* Table for the SUNPLUS CPU */
536 #include "sunplus.inc"
539 /* Instruction table for the SWEET16 pseudo CPU */
540 static const struct {
544 sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
546 { "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 },
547 { "BC", AMSW16_BRA, 0x03, 0, PutSweet16Branch },
548 { "BK", AMSW16_IMP, 0x0A, 0, PutSweet16 },
549 { "BM", AMSW16_BRA, 0x05, 0, PutSweet16Branch },
550 { "BM1", AMSW16_BRA, 0x08, 0, PutSweet16Branch },
551 { "BNC", AMSW16_BRA, 0x02, 0, PutSweet16Branch },
552 { "BNM1", AMSW16_BRA, 0x09, 0, PutSweet16Branch },
553 { "BNZ", AMSW16_BRA, 0x07, 0, PutSweet16Branch },
554 { "BP", AMSW16_BRA, 0x04, 0, PutSweet16Branch },
555 { "BR", AMSW16_BRA, 0x01, 0, PutSweet16Branch },
556 { "BS", AMSW16_BRA, 0x0B, 0, PutSweet16Branch },
557 { "BZ", AMSW16_BRA, 0x06, 0, PutSweet16Branch },
558 { "CPR", AMSW16_REG, 0xD0, 0, PutSweet16 },
559 { "DCR", AMSW16_REG, 0xF0, 0, PutSweet16 },
560 { "INR", AMSW16_REG, 0xE0, 0, PutSweet16 },
561 { "LD", AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 },
562 { "LDD", AMSW16_IND, 0x60, 0, PutSweet16 },
563 { "POP", AMSW16_IND, 0x80, 0, PutSweet16 },
564 { "POPD", AMSW16_IND, 0xC0, 0, PutSweet16 },
565 { "RS", AMSW16_IMP, 0x0B, 0, PutSweet16 },
566 { "RTN", AMSW16_IMP, 0x00, 0, PutSweet16 },
567 { "SET", AMSW16_IMM, 0x10, 0, PutSweet16 },
568 { "ST", AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 },
569 { "STD", AMSW16_IND, 0x70, 0, PutSweet16 },
570 { "STP", AMSW16_IND, 0x90, 0, PutSweet16 },
571 { "SUB", AMSW16_IMM, 0xB0, 0, PutSweet16 },
575 /* Instruction table for the HuC6280 (the CPU used in the PC engine) */
576 static const struct {
580 sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
582 { "ADC", 0x080A66C, 0x60, 0, PutAll },
583 { "AND", 0x080A66C, 0x20, 0, PutAll },
584 { "ASL", 0x000006e, 0x02, 1, PutAll },
585 { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch },
586 { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch },
587 { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch },
588 { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch },
589 { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch },
590 { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch },
591 { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch },
592 { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch },
593 { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch },
594 { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch },
595 { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch },
596 { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch },
597 { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch },
598 { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch },
599 { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch },
600 { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch },
601 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
602 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
603 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
604 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
605 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
606 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
607 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
608 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
609 { "BRK", 0x0000001, 0x00, 0, PutAll },
610 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
611 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
612 { "CLA", 0x0000001, 0x62, 0, PutAll },
613 { "CLC", 0x0000001, 0x18, 0, PutAll },
614 { "CLD", 0x0000001, 0xd8, 0, PutAll },
615 { "CLI", 0x0000001, 0x58, 0, PutAll },
616 { "CLV", 0x0000001, 0xb8, 0, PutAll },
617 { "CLX", 0x0000001, 0x82, 0, PutAll },
618 { "CLY", 0x0000001, 0xc2, 0, PutAll },
619 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
620 { "CPX", 0x080000C, 0xe0, 1, PutAll },
621 { "CPY", 0x080000C, 0xc0, 1, PutAll },
622 { "CSH", 0x0000001, 0xd4, 0, PutAll },
623 { "CSL", 0x0000001, 0x54, 0, PutAll },
624 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
625 { "DEC", 0x000006F, 0x00, 3, PutAll },
626 { "DEX", 0x0000001, 0xca, 0, PutAll },
627 { "DEY", 0x0000001, 0x88, 0, PutAll },
628 { "EOR", 0x080A66C, 0x40, 0, PutAll },
629 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
630 { "INC", 0x000006f, 0x00, 4, PutAll },
631 { "INX", 0x0000001, 0xe8, 0, PutAll },
632 { "INY", 0x0000001, 0xc8, 0, PutAll },
633 { "JMP", 0x0010808, 0x4c, 6, PutAll },
634 { "JSR", 0x0000008, 0x20, 7, PutAll },
635 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
636 { "LDX", 0x080030C, 0xa2, 1, PutAll },
637 { "LDY", 0x080006C, 0xa0, 1, PutAll },
638 { "LSR", 0x000006F, 0x42, 1, PutAll },
639 { "NOP", 0x0000001, 0xea, 0, PutAll },
640 { "ORA", 0x080A66C, 0x00, 0, PutAll },
641 { "PHA", 0x0000001, 0x48, 0, PutAll },
642 { "PHP", 0x0000001, 0x08, 0, PutAll },
643 { "PHX", 0x0000001, 0xda, 0, PutAll },
644 { "PHY", 0x0000001, 0x5a, 0, PutAll },
645 { "PLA", 0x0000001, 0x68, 0, PutAll },
646 { "PLP", 0x0000001, 0x28, 0, PutAll },
647 { "PLX", 0x0000001, 0xfa, 0, PutAll },
648 { "PLY", 0x0000001, 0x7a, 0, PutAll },
649 { "RMB0", 0x0000004, 0x07, 1, PutAll },
650 { "RMB1", 0x0000004, 0x17, 1, PutAll },
651 { "RMB2", 0x0000004, 0x27, 1, PutAll },
652 { "RMB3", 0x0000004, 0x37, 1, PutAll },
653 { "RMB4", 0x0000004, 0x47, 1, PutAll },
654 { "RMB5", 0x0000004, 0x57, 1, PutAll },
655 { "RMB6", 0x0000004, 0x67, 1, PutAll },
656 { "RMB7", 0x0000004, 0x77, 1, PutAll },
657 { "ROL", 0x000006F, 0x22, 1, PutAll },
658 { "ROR", 0x000006F, 0x62, 1, PutAll },
659 { "RTI", 0x0000001, 0x40, 0, PutAll },
660 { "RTS", 0x0000001, 0x60, 0, PutAll },
661 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
662 { "SAX", 0x0000001, 0x22, 0, PutAll },
663 { "SAY", 0x0000001, 0x42, 0, PutAll },
664 { "SEC", 0x0000001, 0x38, 0, PutAll },
665 { "SED", 0x0000001, 0xf8, 0, PutAll },
666 { "SEI", 0x0000001, 0x78, 0, PutAll },
667 { "SET", 0x0000001, 0xf4, 0, PutAll },
668 { "SMB0", 0x0000004, 0x87, 1, PutAll },
669 { "SMB1", 0x0000004, 0x97, 1, PutAll },
670 { "SMB2", 0x0000004, 0xA7, 1, PutAll },
671 { "SMB3", 0x0000004, 0xB7, 1, PutAll },
672 { "SMB4", 0x0000004, 0xC7, 1, PutAll },
673 { "SMB5", 0x0000004, 0xD7, 1, PutAll },
674 { "SMB6", 0x0000004, 0xE7, 1, PutAll },
675 { "SMB7", 0x0000004, 0xF7, 1, PutAll },
676 { "STA", 0x000A66C, 0x80, 0, PutAll },
677 { "STX", 0x000010c, 0x82, 1, PutAll },
678 { "STY", 0x000002c, 0x80, 1, PutAll },
679 { "STZ", 0x000006c, 0x04, 5, PutAll },
680 { "SXY", 0x0000001, 0x02, 0, PutAll },
681 { "TAX", 0x0000001, 0xaa, 0, PutAll },
682 { "TAY", 0x0000001, 0xa8, 0, PutAll },
683 { "TRB", 0x000000c, 0x10, 1, PutAll },
684 { "TSB", 0x000000c, 0x00, 1, PutAll },
685 { "TSX", 0x0000001, 0xba, 0, PutAll },
686 { "TXA", 0x0000001, 0x8a, 0, PutAll },
687 { "TXS", 0x0000001, 0x9a, 0, PutAll },
688 { "TYA", 0x0000001, 0x98, 0, PutAll }
694 /* An array with instruction tables */
695 static const InsTable* InsTabs[CPU_COUNT] = {
696 (const InsTable*) &InsTabNone,
697 (const InsTable*) &InsTab6502,
698 (const InsTable*) &InsTab6502X,
699 (const InsTable*) &InsTab65SC02,
700 (const InsTable*) &InsTab65C02,
701 (const InsTable*) &InsTab65816,
703 (const InsTable*) &InsTabSunPlus,
707 (const InsTable*) &InsTabSweet16,
708 (const InsTable*) &InsTabHuC6280,
710 const InsTable* InsTab = (const InsTable*) &InsTab6502;
712 /* Table to build the effective 65xx opcode from a base opcode and an
715 static unsigned char EATab[9][AM65I_COUNT] = {
717 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
718 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
719 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
723 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
724 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
729 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
730 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
731 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
735 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
736 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
737 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
742 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
748 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
753 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
754 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
755 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
759 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
760 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
761 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
766 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
767 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
772 /* Table to build the effective SWEET16 opcode from a base opcode and an
775 static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = {
777 0x00, 0x00, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x40, 0x20,
784 /* Table that encodes the additional bytes for each 65xx instruction */
785 unsigned char ExtBytes[AM65I_COUNT] = {
790 3, /* Absolute long */
793 3, /* Absolute long,X */
802 2, /* (Absolute,X) */
803 1, /* Relative short */
804 2, /* Relative long */
807 1, /* Immidiate accu */
808 1, /* Immidiate index */
809 1, /* Immidiate byte */
813 /* Table that encodes the additional bytes for each SWEET16 instruction */
814 static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = {
824 /*****************************************************************************/
825 /* Handler functions for 6502 derivates */
826 /*****************************************************************************/
830 static int EvalEA (const InsDesc* Ins, EffAddr* A)
831 /* Evaluate the effective address. All fields in A will be valid after calling
832 * this function. The function returns true on success and false on errors.
835 /* Get the set of possible addressing modes */
838 /* From the possible addressing modes, remove the ones that are invalid
839 * for this instruction or CPU.
841 A->AddrModeSet &= Ins->AddrMode;
843 /* If we have an expression, check it and remove any addressing modes that
844 * are too small for the expression size. Since we have to study the
845 * expression anyway, do also replace it by a simpler one if possible.
851 /* Study the expression */
852 StudyExpr (A->Expr, &ED);
854 /* Simplify it if possible */
855 A->Expr = SimplifyExpr (A->Expr, &ED);
857 /* If we don't know how big the expression is, assume the default
858 * address size for data.
860 if (ED.AddrSize == ADDR_SIZE_DEFAULT) {
861 ED.AddrSize = DataAddrSize;
865 switch (ED.AddrSize) {
868 A->AddrModeSet &= ~AM65_SET_ZP;
872 A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS);
876 /* Free any resource associated with the expression desc */
880 /* Check if we have any adressing modes left */
881 if (A->AddrModeSet == 0) {
882 Error ("Illegal addressing mode");
885 A->AddrMode = BitFind (A->AddrModeSet);
886 A->AddrModeBit = (0x01UL << A->AddrMode);
888 /* If the instruction has a one byte operand and immediate addressing is
889 * allowed but not used, check for an operand expression in the form
890 * <label or >label, where label is a far or absolute label. If found,
891 * emit a warning. This warning protects against a typo, where the '#'
892 * for the immediate operand is omitted.
894 if (A->Expr && (Ins->AddrMode & AM65_IMM) &&
895 (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) &&
896 ExtBytes[A->AddrMode] == 1) {
898 /* Found, check the expression */
899 ExprNode* Left = A->Expr->Left;
900 if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) &&
901 Left->Op == EXPR_SYMBOL &&
902 GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) {
904 /* Output a warning */
905 Warning (1, "Suspicious address expression");
909 /* Build the opcode */
910 A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode];
918 static void EmitCode (EffAddr* A)
919 /* Output code for the data in A */
921 /* Check how many extension bytes are needed and output the instruction */
922 switch (ExtBytes[A->AddrMode]) {
929 Emit1 (A->Opcode, A->Expr);
933 if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) {
934 /* This is a 16 bit mode that uses an address. If in 65816,
935 * mode, force this address into 16 bit range to allow
936 * addressing inside a 64K segment.
938 Emit2 (A->Opcode, GenWordExpr (A->Expr));
940 Emit2 (A->Opcode, A->Expr);
946 Emit3 (A->Opcode, A->Expr);
950 Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]);
957 static long PutImmed8 (const InsDesc* Ins)
958 /* Parse and emit an immediate 8 bit instruction. Return the value of the
959 * operand if it's available and const.
965 /* Evaluate the addressing mode */
966 if (EvalEA (Ins, &A) == 0) {
967 /* An error occurred */
971 /* If we have an expression and it's const, get it's value */
973 (void) IsConstExpr (A.Expr, &Val);
976 /* Check how many extension bytes are needed and output the instruction */
977 switch (ExtBytes[A.AddrMode]) {
980 Emit1 (A.Opcode, A.Expr);
984 Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]);
987 /* Return the expression value */
993 static void PutPCRel8 (const InsDesc* Ins)
994 /* Handle branches with a 8 bit distance */
996 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1001 static void PutPCRel16 (const InsDesc* Ins)
1002 /* Handle branches with an 16 bit distance and PER */
1004 EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2);
1009 static void PutBlockMove (const InsDesc* Ins)
1010 /* Handle the blockmove instructions */
1012 Emit0 (Ins->BaseCode);
1013 EmitByte (Expression ());
1015 EmitByte (Expression ());
1020 static void PutBitBranch (const InsDesc* Ins)
1021 /* Handle 65C02 branch on bit condition */
1023 Emit0 (Ins->BaseCode);
1024 EmitByte (Expression ());
1026 EmitSigned (GenBranchExpr (1), 1);
1031 static void PutREP (const InsDesc* Ins)
1032 /* Emit a REP instruction, track register sizes */
1034 /* Use the generic handler */
1035 long Val = PutImmed8 (Ins);
1037 /* We track the status only for the 816 CPU and in smart mode */
1038 if (CPU == CPU_65816 && SmartMode) {
1040 /* Check the range for Val. */
1042 /* We had an error */
1043 Warning (1, "Cannot track processor status byte");
1046 /* Index registers to 16 bit */
1047 ExtBytes[AM65I_IMM_INDEX] = 2;
1050 /* Accu to 16 bit */
1051 ExtBytes[AM65I_IMM_ACCU] = 2;
1059 static void PutSEP (const InsDesc* Ins)
1060 /* Emit a SEP instruction, track register sizes */
1062 /* Use the generic handler */
1063 long Val = PutImmed8 (Ins);
1065 /* We track the status only for the 816 CPU and in smart mode */
1066 if (CPU == CPU_65816 && SmartMode) {
1068 /* Check the range for Val. */
1070 /* We had an error */
1071 Warning (1, "Cannot track processor status byte");
1074 /* Index registers to 8 bit */
1075 ExtBytes[AM65I_IMM_INDEX] = 1;
1079 ExtBytes[AM65I_IMM_ACCU] = 1;
1087 static void PutJMP (const InsDesc* Ins)
1088 /* Handle the jump instruction for the 6502. Problem is that these chips have
1089 * a bug: If the address crosses a page, the upper byte gets not corrected and
1090 * the instruction will fail. The PutJmp function will add a linker assertion
1091 * to check for this case and is otherwise identical to PutAll.
1096 /* Evaluate the addressing mode used */
1097 if (EvalEA (Ins, &A)) {
1099 /* Check for indirect addressing */
1100 if (A.AddrModeBit & AM65_ABS_IND) {
1102 /* Compare the low byte of the expression to 0xFF to check for
1103 * a page cross. Be sure to use a copy of the expression otherwise
1104 * things will go weird later.
1106 ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF);
1108 /* Generate the message */
1109 unsigned Msg = GetStringId ("\"jmp (abs)\" across page border");
1111 /* Generate the assertion */
1112 AddAssertion (E, ASSERT_ACT_WARN, Msg);
1115 /* No error, output code */
1122 static void PutRTS (const InsDesc* Ins attribute ((unused)))
1123 /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if
1124 * the enclosing scope is FAR.
1127 if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) {
1128 Emit0 (0x6B); /* RTL */
1130 Emit0 (0x60); /* RTS */
1136 static void PutAll (const InsDesc* Ins)
1137 /* Handle all other instructions */
1141 /* Evaluate the addressing mode used */
1142 if (EvalEA (Ins, &A)) {
1143 /* No error, output code */
1150 /*****************************************************************************/
1151 /* Handler functions for SWEET16 */
1152 /*****************************************************************************/
1156 static void PutSweet16 (const InsDesc* Ins)
1157 /* Handle a generic sweet16 instruction */
1161 /* Evaluate the addressing mode used */
1164 /* From the possible addressing modes, remove the ones that are invalid
1165 * for this instruction or CPU.
1167 A.AddrModeSet &= Ins->AddrMode;
1169 /* Check if we have any adressing modes left */
1170 if (A.AddrModeSet == 0) {
1171 Error ("Illegal addressing mode");
1174 A.AddrMode = BitFind (A.AddrModeSet);
1175 A.AddrModeBit = (0x01UL << A.AddrMode);
1177 /* Build the opcode */
1178 A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg;
1180 /* Check how many extension bytes are needed and output the instruction */
1181 switch (Sweet16ExtBytes[A.AddrMode]) {
1188 Emit1 (A.Opcode, A.Expr);
1192 Emit2 (A.Opcode, A.Expr);
1196 Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]);
1203 static void PutSweet16Branch (const InsDesc* Ins)
1204 /* Handle a sweet16 branch instruction */
1206 EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1);
1211 /*****************************************************************************/
1213 /*****************************************************************************/
1217 static int CmpName (const void* Key, const void* Instr)
1218 /* Compare function for bsearch */
1220 return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
1225 void SetCPU (cpu_t NewCPU)
1228 /* Make sure the parameter is correct */
1229 CHECK (NewCPU < CPU_COUNT);
1231 /* Check if we have support for the new CPU, if so, use it */
1232 if (InsTabs[NewCPU]) {
1234 InsTab = InsTabs[CPU];
1236 Error ("CPU not supported");
1243 /* Return the current CPU */
1250 int FindInstruction (const char* Ident)
1251 /* Check if Ident is a valid mnemonic. If so, return the index in the
1252 * instruction table. If not, return -1.
1257 char Key[sizeof (ID->Mnemonic)];
1259 /* Shortcut for the "none" CPU: If there are no instructions to search
1260 * for, bail out early.
1262 if (InsTab->Count == 0) {
1267 /* Make a copy, and uppercase that copy */
1269 while (Ident[I] != '\0') {
1270 /* If the identifier is longer than the longest mnemonic, it cannot
1273 if (I >= sizeof (Key) - 1) {
1274 /* Not found, no need for further action */
1277 Key[I] = toupper ((unsigned char)Ident[I]);
1282 /* Search for the key */
1283 ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
1288 /* Found, return the entry */
1289 return ID - InsTab->Ins;
1295 void HandleInstruction (unsigned Index)
1296 /* Handle the mnemonic with the given index */
1299 PRECONDITION (Index < InsTab->Count);
1301 /* Skip the mnemonic token */
1304 /* Call the handler */
1305 InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);