1 /*****************************************************************************/
5 /* Instruction encoding for the ca65 macroassembler */
9 /* (C) 1998-2000 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
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 /*****************************************************************************/
40 #include "../common/bitops.h"
52 /*****************************************************************************/
54 /*****************************************************************************/
58 /* Forwards for handler functions */
59 static void PutPCRel8 (const InsDesc* Ins);
60 static void PutPCRel16 (const InsDesc* Ins);
61 static void PutBlockMove (const InsDesc* Ins);
62 static void PutREP (const InsDesc* Ins);
63 static void PutSEP (const InsDesc* Ins);
64 static void PutAll (const InsDesc* Ins);
68 /* Instruction table for the 6502 */
69 #define INS_COUNT_6502 56
72 InsDesc Ins[INS_COUNT_6502];
76 { "ADC", 0x080A26C, 0x60, 0, PutAll },
77 { "AND", 0x080A26C, 0x20, 0, PutAll },
78 { "ASL", 0x000006e, 0x02, 1, PutAll },
79 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
80 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
81 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
82 { "BIT", 0x000000C, 0x00, 2, PutAll },
83 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
84 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
85 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
86 { "BRK", 0x0000001, 0x00, 0, PutAll },
87 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
88 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
89 { "CLC", 0x0000001, 0x18, 0, PutAll },
90 { "CLD", 0x0000001, 0xd8, 0, PutAll },
91 { "CLI", 0x0000001, 0x58, 0, PutAll },
92 { "CLV", 0x0000001, 0xb8, 0, PutAll },
93 { "CMP", 0x080A26C, 0xc0, 0, PutAll },
94 { "CPX", 0x080000C, 0xe0, 1, PutAll },
95 { "CPY", 0x080000C, 0xc0, 1, PutAll },
96 { "DEC", 0x000006C, 0x00, 3, PutAll },
97 { "DEX", 0x0000001, 0xca, 0, PutAll },
98 { "DEY", 0x0000001, 0x88, 0, PutAll },
99 { "EOR", 0x080A26C, 0x40, 0, PutAll },
100 { "INC", 0x000006c, 0x00, 4, PutAll },
101 { "INX", 0x0000001, 0xe8, 0, PutAll },
102 { "INY", 0x0000001, 0xc8, 0, PutAll },
103 { "JMP", 0x0000808, 0x4c, 6, PutAll },
104 { "JSR", 0x0000008, 0x20, 7, PutAll },
105 { "LDA", 0x080A26C, 0xa0, 0, PutAll },
106 { "LDX", 0x080030C, 0xa2, 1, PutAll },
107 { "LDY", 0x080006C, 0xa0, 1, PutAll },
108 { "LSR", 0x000006F, 0x42, 1, PutAll },
109 { "NOP", 0x0000001, 0xea, 0, PutAll },
110 { "ORA", 0x080A26C, 0x00, 0, PutAll },
111 { "PHA", 0x0000001, 0x48, 0, PutAll },
112 { "PHP", 0x0000001, 0x08, 0, PutAll },
113 { "PLA", 0x0000001, 0x68, 0, PutAll },
114 { "PLP", 0x0000001, 0x28, 0, PutAll },
115 { "ROL", 0x000006F, 0x22, 1, PutAll },
116 { "ROR", 0x000006F, 0x62, 1, PutAll },
117 { "RTI", 0x0000001, 0x40, 0, PutAll },
118 { "RTS", 0x0000001, 0x60, 0, PutAll },
119 { "SBC", 0x080A26C, 0xe0, 0, PutAll },
120 { "SEC", 0x0000001, 0x38, 0, PutAll },
121 { "SED", 0x0000001, 0xf8, 0, PutAll },
122 { "SEI", 0x0000001, 0x78, 0, PutAll },
123 { "STA", 0x000A26C, 0x80, 0, PutAll },
124 { "STX", 0x000010c, 0x82, 1, PutAll },
125 { "STY", 0x000002c, 0x80, 1, PutAll },
126 { "TAX", 0x0000001, 0xaa, 0, PutAll },
127 { "TAY", 0x0000001, 0xa8, 0, PutAll },
128 { "TSX", 0x0000001, 0xba, 0, PutAll },
129 { "TXA", 0x0000001, 0x8a, 0, PutAll },
130 { "TXS", 0x0000001, 0x9a, 0, PutAll },
131 { "TYA", 0x0000001, 0x98, 0, PutAll }
135 /* Instruction table for the 65SC02 */
136 #define INS_COUNT_65SC02 66
137 static const struct {
139 InsDesc Ins[INS_COUNT_65SC02];
143 { "ADC", 0x080A66C, 0x60, 0, PutAll },
144 { "AND", 0x080A66C, 0x20, 0, PutAll },
145 { "ASL", 0x000006e, 0x02, 1, PutAll },
146 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
147 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
148 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
149 { "BIT", 0x080006C, 0x00, 2, PutAll },
150 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
151 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
152 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
153 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
154 { "BRK", 0x0000001, 0x00, 0, PutAll },
155 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
156 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
157 { "CLC", 0x0000001, 0x18, 0, PutAll },
158 { "CLD", 0x0000001, 0xd8, 0, PutAll },
159 { "CLI", 0x0000001, 0x58, 0, PutAll },
160 { "CLV", 0x0000001, 0xb8, 0, PutAll },
161 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
162 { "CPX", 0x080000C, 0xe0, 1, PutAll },
163 { "CPY", 0x080000C, 0xc0, 1, PutAll },
164 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
165 { "DEC", 0x000006F, 0x00, 3, PutAll },
166 { "DEX", 0x0000001, 0xca, 0, PutAll },
167 { "DEY", 0x0000001, 0x88, 0, PutAll },
168 { "EOR", 0x080A66C, 0x40, 0, PutAll },
169 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
170 { "INC", 0x000006f, 0x00, 4, PutAll },
171 { "INX", 0x0000001, 0xe8, 0, PutAll },
172 { "INY", 0x0000001, 0xc8, 0, PutAll },
173 { "JMP", 0x0010808, 0x4c, 6, PutAll },
174 { "JSR", 0x0000008, 0x20, 7, PutAll },
175 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
176 { "LDX", 0x080030C, 0xa2, 1, PutAll },
177 { "LDY", 0x080006C, 0xa0, 1, PutAll },
178 { "LSR", 0x000006F, 0x42, 1, PutAll },
179 { "NOP", 0x0000001, 0xea, 0, PutAll },
180 { "ORA", 0x080A66C, 0x00, 0, PutAll },
181 { "PHA", 0x0000001, 0x48, 0, PutAll },
182 { "PHP", 0x0000001, 0x08, 0, PutAll },
183 { "PHX", 0x0000001, 0xda, 0, PutAll },
184 { "PHY", 0x0000001, 0x5a, 0, PutAll },
185 { "PLA", 0x0000001, 0x68, 0, PutAll },
186 { "PLP", 0x0000001, 0x28, 0, PutAll },
187 { "PLX", 0x0000001, 0xfa, 0, PutAll },
188 { "PLY", 0x0000001, 0x7a, 0, PutAll },
189 { "ROL", 0x000006F, 0x22, 1, PutAll },
190 { "ROR", 0x000006F, 0x62, 1, PutAll },
191 { "RTI", 0x0000001, 0x40, 0, PutAll },
192 { "RTS", 0x0000001, 0x60, 0, PutAll },
193 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
194 { "SEC", 0x0000001, 0x38, 0, PutAll },
195 { "SED", 0x0000001, 0xf8, 0, PutAll },
196 { "SEI", 0x0000001, 0x78, 0, PutAll },
197 { "STA", 0x000A66C, 0x80, 0, PutAll },
198 { "STX", 0x000010c, 0x82, 1, PutAll },
199 { "STY", 0x000002c, 0x80, 1, PutAll },
200 { "STZ", 0x000006c, 0x04, 5, PutAll },
201 { "TAX", 0x0000001, 0xaa, 0, PutAll },
202 { "TAY", 0x0000001, 0xa8, 0, PutAll },
203 { "TRB", 0x000000c, 0x10, 1, PutAll },
204 { "TSB", 0x000000c, 0x00, 1, PutAll },
205 { "TSX", 0x0000001, 0xba, 0, PutAll },
206 { "TXA", 0x0000001, 0x8a, 0, PutAll },
207 { "TXS", 0x0000001, 0x9a, 0, PutAll },
208 { "TYA", 0x0000001, 0x98, 0, PutAll }
212 /* Instruction table for the 65816 */
213 #define INS_COUNT_65816 101
214 static const struct {
216 InsDesc Ins[INS_COUNT_65816];
220 { "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
221 { "AND", 0x0b8f6fc, 0x20, 0, PutAll },
222 { "ASL", 0x000006e, 0x02, 1, PutAll },
223 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
224 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
225 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
226 { "BGE", 0x0020000, 0xb0, 0, PutPCRel8 }, /* == BCS */
227 { "BIT", 0x0a0006c, 0x00, 2, PutAll },
228 { "BLT", 0x0020000, 0x90, 0, PutPCRel8 }, /* == BCC */
229 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
230 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
231 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
232 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
233 { "BRK", 0x0000001, 0x00, 0, PutAll },
234 { "BRL", 0x0040000, 0x82, 0, PutPCRel16 },
235 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
236 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
237 { "CLC", 0x0000001, 0x18, 0, PutAll },
238 { "CLD", 0x0000001, 0xd8, 0, PutAll },
239 { "CLI", 0x0000001, 0x58, 0, PutAll },
240 { "CLV", 0x0000001, 0xb8, 0, PutAll },
241 { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll },
242 { "COP", 0x0000004, 0x02, 6, PutAll },
243 { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */
244 { "CPX", 0x0c0000c, 0xe0, 1, PutAll },
245 { "CPY", 0x0c0000c, 0xc0, 1, PutAll },
246 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
247 { "DEC", 0x000006F, 0x00, 3, PutAll },
248 { "DEX", 0x0000001, 0xca, 0, PutAll },
249 { "DEY", 0x0000001, 0x88, 0, PutAll },
250 { "EOR", 0x0b8f6fc, 0x40, 0, PutAll },
251 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
252 { "INC", 0x000006F, 0x00, 4, PutAll },
253 { "INX", 0x0000001, 0xe8, 0, PutAll },
254 { "INY", 0x0000001, 0xc8, 0, PutAll },
255 { "JML", 0x0000810, 0x5c, 1, PutAll },
256 { "JMP", 0x0010818, 0x4c, 6, PutAll },
257 { "JSL", 0x0000010, 0x20, 7, PutAll },
258 { "JSR", 0x0010018, 0x20, 7, PutAll },
259 { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
260 { "LDX", 0x0c0030c, 0xa2, 1, PutAll },
261 { "LDY", 0x0c0006c, 0xa0, 1, PutAll },
262 { "LSR", 0x000006F, 0x42, 1, PutAll },
263 { "MVN", 0x1000000, 0x54, 0, PutBlockMove },
264 { "MVP", 0x1000000, 0x44, 0, PutBlockMove },
265 { "NOP", 0x0000001, 0xea, 0, PutAll },
266 { "ORA", 0x0b8f6fc, 0x00, 0, PutAll },
267 { "PEA", 0x0000008, 0xf4, 6, PutAll },
268 { "PEI", 0x0800000, 0xd4, 0, PutAll },
269 { "PER", 0x0040000, 0x62, 0, PutPCRel16 },
270 { "PHA", 0x0000001, 0x48, 0, PutAll },
271 { "PHB", 0x0000001, 0x8b, 0, PutAll },
272 { "PHD", 0x0000001, 0x0b, 0, PutAll },
273 { "PHK", 0x0000001, 0x4b, 0, PutAll },
274 { "PHP", 0x0000001, 0x08, 0, PutAll },
275 { "PHX", 0x0000001, 0xda, 0, PutAll },
276 { "PHY", 0x0000001, 0x5a, 0, PutAll },
277 { "PLA", 0x0000001, 0x68, 0, PutAll },
278 { "PLB", 0x0000001, 0xab, 0, PutAll },
279 { "PLD", 0x0000001, 0x2b, 0, PutAll },
280 { "PLP", 0x0000001, 0x28, 0, PutAll },
281 { "PLX", 0x0000001, 0xfa, 0, PutAll },
282 { "PLY", 0x0000001, 0x7a, 0, PutAll },
283 { "REP", 0x0800000, 0xc2, 1, PutREP },
284 { "ROL", 0x000006F, 0x22, 1, PutAll },
285 { "ROR", 0x000006F, 0x62, 1, PutAll },
286 { "RTI", 0x0000001, 0x40, 0, PutAll },
287 { "RTL", 0x0000001, 0x6b, 0, PutAll },
288 { "RTS", 0x0000001, 0x60, 0, PutAll },
289 { "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
290 { "SEC", 0x0000001, 0x38, 0, PutAll },
291 { "SED", 0x0000001, 0xf8, 0, PutAll },
292 { "SEI", 0x0000001, 0x78, 0, PutAll },
293 { "SEP", 0x0800000, 0xe2, 1, PutSEP },
294 { "STA", 0x018f6fc, 0x80, 0, PutAll },
295 { "STP", 0x0000001, 0xdb, 0, PutAll },
296 { "STX", 0x000010c, 0x82, 1, PutAll },
297 { "STY", 0x000002c, 0x80, 1, PutAll },
298 { "STZ", 0x000006c, 0x04, 5, PutAll },
299 { "SWA", 0x0000001, 0xeb, 0, PutAll }, /* == XBA */
300 { "TAD", 0x0000001, 0x5b, 0, PutAll }, /* == TCD */
301 { "TAS", 0x0000001, 0x1b, 0, PutAll }, /* == TCS */
302 { "TAX", 0x0000001, 0xaa, 0, PutAll },
303 { "TAY", 0x0000001, 0xa8, 0, PutAll },
304 { "TCD", 0x0000001, 0x5b, 0, PutAll },
305 { "TCS", 0x0000001, 0x1b, 0, PutAll },
306 { "TDA", 0x0000001, 0x7b, 0, PutAll }, /* == TDC */
307 { "TDC", 0x0000001, 0x7b, 0, PutAll },
308 { "TRB", 0x000000c, 0x10, 1, PutAll },
309 { "TSA", 0x0000001, 0x3b, 0, PutAll }, /* == TSC */
310 { "TSB", 0x000000c, 0x00, 1, PutAll },
311 { "TSC", 0x0000001, 0x3b, 0, PutAll },
312 { "TSX", 0x0000001, 0xba, 0, PutAll },
313 { "TXA", 0x0000001, 0x8a, 0, PutAll },
314 { "TXS", 0x0000001, 0x9a, 0, PutAll },
315 { "TXY", 0x0000001, 0x9b, 0, PutAll },
316 { "TYA", 0x0000001, 0x98, 0, PutAll },
317 { "TYX", 0x0000001, 0xbb, 0, PutAll },
318 { "WAI", 0x0000001, 0xcb, 0, PutAll },
319 { "XBA", 0x0000001, 0xeb, 0, PutAll },
320 { "XCE", 0x0000001, 0xfb, 0, PutAll }
325 /* Table for the SUNPLUS CPU */
326 #include "sunplus.inc"
331 /* The current CPU and an array with instruction tables */
332 static enum CPUType CPU = CPU_6502;
333 static const InsTable* InsTabs[CPU_COUNT] = {
334 (const InsTable*) &InsTab6502,
335 (const InsTable*) &InsTab65SC02,
336 (const InsTable*) &InsTab65816,
338 (const InsTable*) &InsTabSunPlus,
343 const InsTable* InsTab = (const InsTable*) &InsTab6502;
345 /* Table to build the effective opcode from a base opcode and an addressing
348 unsigned char EATab [9][AMI_COUNT] = {
350 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
351 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
352 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
356 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
357 0x14, 0x1C, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
368 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
388 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
399 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
405 /* Table that encodes the additional bytes for each instruction */
406 unsigned char ExtBytes [AMI_COUNT] = {
411 3, /* Absolute long */
414 3, /* Absolute long,X */
423 2, /* (Absolute,X) */
424 1, /* Relative short */
425 2, /* Relative long */
428 1, /* Immidiate accu */
429 1, /* Immidiate index */
430 1, /* Immidiate byte */
436 /*****************************************************************************/
437 /* Handler functions */
438 /*****************************************************************************/
442 static long PutImmed8 (const InsDesc* Ins)
443 /* Parse and emit an immediate 8 bit instruction. Return the value of the
444 * operand if it's available and const.
449 unsigned long AddrMode;
450 unsigned char OpCode;
453 /* Get the addressing mode used */
454 GetEA (&AddrMode, &Expr, &Bank);
456 /* From the possible addressing modes, remove the ones that are invalid
457 * for this instruction or CPU.
459 AddrMode &= Ins->AddrMode;
461 /* If we have possible zero page addressing modes, and the expression
462 * involved (if any) is not in byte range, remove the zero page addressing
465 if (Expr && (AddrMode & AM_ZP) && !IsByteExpr (Expr)) {
469 /* Check if we have any adressing modes left */
471 Error (ERR_ILLEGAL_ADDR_MODE);
474 AddrMode = BitFind (AddrMode);
476 /* Build the opcode */
477 OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode];
479 /* If we have an expression and it's const, get it's value */
480 if (Expr && IsConstExpr (Expr)) {
481 Val = GetExprVal (Expr);
484 /* Check how many extension bytes are needed and output the instruction */
485 switch (ExtBytes [AddrMode]) {
488 Emit1 (OpCode, Expr);
492 Internal ("Invalid operand byte count: %u", ExtBytes [AddrMode]);
495 /* Return the expression value */
501 static void PutPCRel8 (const InsDesc* Ins)
502 /* Handle branches with a 8 bit distance */
504 EmitPCRel (Ins->BaseCode, BranchExpr (2), 1);
509 static void PutPCRel16 (const InsDesc* Ins)
510 /* Handle branches with an 16 bit distance and PER */
512 EmitPCRel (Ins->BaseCode, BranchExpr (3), 2);
517 static void PutBlockMove (const InsDesc* Ins)
518 /* Handle the blockmove instructions */
520 Emit0 (Ins->BaseCode);
521 EmitByte (Expression ());
523 EmitByte (Expression ());
528 static void PutREP (const InsDesc* Ins)
529 /* Emit a REP instruction, track register sizes */
531 /* Use the generic handler */
532 long Val = PutImmed8 (Ins);
534 /* We track the status only for the 816 CPU and in smart mode */
535 if (CPU == CPU_65816 && SmartMode) {
537 /* Check the range for Val. */
539 /* We had an error */
540 Warning (WARN_CANNOT_TRACK_STATUS);
543 /* Index registers to 16 bit */
544 ExtBytes [AMI_IMM_INDEX] = 2;
548 ExtBytes [AMI_IMM_ACCU] = 2;
556 static void PutSEP (const InsDesc* Ins)
557 /* Emit a SEP instruction, track register sizes */
559 /* Use the generic handler */
560 long Val = PutImmed8 (Ins);
562 /* We track the status only for the 816 CPU and in smart mode */
563 if (CPU == CPU_65816 && SmartMode) {
565 /* Check the range for Val. */
567 /* We had an error */
568 Warning (WARN_CANNOT_TRACK_STATUS);
571 /* Index registers to 8 bit */
572 ExtBytes [AMI_IMM_INDEX] = 1;
576 ExtBytes [AMI_IMM_ACCU] = 1;
584 static void PutAll (const InsDesc* Ins)
585 /* Handle all other instructions */
589 unsigned long AddrModeSet;
590 unsigned char OpCode;
592 unsigned long AddrModeBit;
594 /* Get the addressing mode used */
595 GetEA (&AddrModeSet, &Expr, &Bank);
597 /* From the possible addressing modes, remove the ones that are invalid
598 * for this instruction or CPU.
600 AddrModeSet &= Ins->AddrMode;
602 /* If we have possible zero page addressing modes, and the expression
603 * involved (if any) is not in byte range, remove the zero page addressing
606 if (Expr && (AddrModeSet & AM_ZP) && !IsByteExpr (Expr)) {
607 AddrModeSet &= ~AM_ZP;
610 /* Check if we have any adressing modes left */
611 if (AddrModeSet == 0) {
612 Error (ERR_ILLEGAL_ADDR_MODE);
615 AddrMode = BitFind (AddrModeSet);
617 /* Build the opcode */
618 OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode];
620 /* Check how many extension bytes are needed and output the instruction */
621 switch (ExtBytes [AddrMode]) {
628 Emit1 (OpCode, Expr);
632 AddrModeBit = (1L << AddrMode);
633 if (CPU == CPU_65816 && (AddrModeBit & (AM_ABS | AM_ABS_X | AM_ABS_Y))) {
634 /* This is a 16 bit mode that uses an address. If in 65816,
635 * mode, force this address into 16 bit range to allow
636 * addressing inside a 64K segment.
638 Emit2 (OpCode, ForceWordExpr (Expr));
640 Emit2 (OpCode, Expr);
646 /* Separate bank given */
647 Emit3b (OpCode, Expr, Bank);
649 /* One far argument */
650 Emit3 (OpCode, Expr);
655 Internal ("Invalid operand byte count: %u", ExtBytes [AddrMode]);
662 /*****************************************************************************/
664 /*****************************************************************************/
668 static int CmpName (const void* Key, const void* Instr)
669 /* Compare function for bsearch */
671 return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
676 void SetCPU (enum CPUType NewCPU)
679 /* Make sure the parameter is correct */
680 CHECK (NewCPU < CPU_COUNT);
682 /* Check if we have support for the new CPU, if so, use it */
683 if (InsTabs[NewCPU]) {
685 InsTab = InsTabs[CPU];
687 Error (ERR_CPU_NOT_SUPPORTED);
693 enum CPUType GetCPU (void)
694 /* Return the current CPU */
701 int FindInstruction (const char* Ident)
702 /* Check if Ident is a valid mnemonic. If so, return the index in the
703 * instruction table. If not, return -1.
707 char Key [sizeof (I->Mnemonic)];
709 /* Accept only strings with the right length */
710 if (strlen (Ident) != sizeof (I->Mnemonic)-1) {
715 /* Make a copy, and uppercase that copy */
716 Key [0] = toupper (Ident [0]);
717 Key [1] = toupper (Ident [1]);
718 Key [2] = toupper (Ident [2]);
721 /* Search for the key */
722 I = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
727 /* Found, return the entry */
728 return I - InsTab->Ins;
734 void HandleInstruction (unsigned Index)
735 /* Handle the mnemonic with the given index */
738 PRECONDITION (Index < InsTab->Count);
740 /* Skip the mnemonic token */
743 /* Call the handler */
744 InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);