1 /*****************************************************************************/
5 /* Instruction encoding for the ca65 macroassembler */
9 /* (C) 1998-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
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 /*****************************************************************************/
55 /*****************************************************************************/
57 /*****************************************************************************/
61 /* Forwards for handler functions */
62 static void PutPCRel8 (const InsDesc* Ins);
63 static void PutPCRel16 (const InsDesc* Ins);
64 static void PutBlockMove (const InsDesc* Ins);
65 static void PutREP (const InsDesc* Ins);
66 static void PutSEP (const InsDesc* Ins);
67 static void PutAll (const InsDesc* Ins);
71 /* Instruction table for the 6502 */
72 #define INS_COUNT_6502 56
75 InsDesc Ins[INS_COUNT_6502];
79 { "ADC", 0x080A26C, 0x60, 0, PutAll },
80 { "AND", 0x080A26C, 0x20, 0, PutAll },
81 { "ASL", 0x000006e, 0x02, 1, PutAll },
82 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
83 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
84 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
85 { "BIT", 0x000000C, 0x00, 2, PutAll },
86 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
87 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
88 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
89 { "BRK", 0x0000001, 0x00, 0, PutAll },
90 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
91 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
92 { "CLC", 0x0000001, 0x18, 0, PutAll },
93 { "CLD", 0x0000001, 0xd8, 0, PutAll },
94 { "CLI", 0x0000001, 0x58, 0, PutAll },
95 { "CLV", 0x0000001, 0xb8, 0, PutAll },
96 { "CMP", 0x080A26C, 0xc0, 0, PutAll },
97 { "CPX", 0x080000C, 0xe0, 1, PutAll },
98 { "CPY", 0x080000C, 0xc0, 1, PutAll },
99 { "DEC", 0x000006C, 0x00, 3, PutAll },
100 { "DEX", 0x0000001, 0xca, 0, PutAll },
101 { "DEY", 0x0000001, 0x88, 0, PutAll },
102 { "EOR", 0x080A26C, 0x40, 0, PutAll },
103 { "INC", 0x000006c, 0x00, 4, PutAll },
104 { "INX", 0x0000001, 0xe8, 0, PutAll },
105 { "INY", 0x0000001, 0xc8, 0, PutAll },
106 { "JMP", 0x0000808, 0x4c, 6, PutAll },
107 { "JSR", 0x0000008, 0x20, 7, PutAll },
108 { "LDA", 0x080A26C, 0xa0, 0, PutAll },
109 { "LDX", 0x080030C, 0xa2, 1, PutAll },
110 { "LDY", 0x080006C, 0xa0, 1, PutAll },
111 { "LSR", 0x000006F, 0x42, 1, PutAll },
112 { "NOP", 0x0000001, 0xea, 0, PutAll },
113 { "ORA", 0x080A26C, 0x00, 0, PutAll },
114 { "PHA", 0x0000001, 0x48, 0, PutAll },
115 { "PHP", 0x0000001, 0x08, 0, PutAll },
116 { "PLA", 0x0000001, 0x68, 0, PutAll },
117 { "PLP", 0x0000001, 0x28, 0, PutAll },
118 { "ROL", 0x000006F, 0x22, 1, PutAll },
119 { "ROR", 0x000006F, 0x62, 1, PutAll },
120 { "RTI", 0x0000001, 0x40, 0, PutAll },
121 { "RTS", 0x0000001, 0x60, 0, PutAll },
122 { "SBC", 0x080A26C, 0xe0, 0, PutAll },
123 { "SEC", 0x0000001, 0x38, 0, PutAll },
124 { "SED", 0x0000001, 0xf8, 0, PutAll },
125 { "SEI", 0x0000001, 0x78, 0, PutAll },
126 { "STA", 0x000A26C, 0x80, 0, PutAll },
127 { "STX", 0x000010c, 0x82, 1, PutAll },
128 { "STY", 0x000002c, 0x80, 1, PutAll },
129 { "TAX", 0x0000001, 0xaa, 0, PutAll },
130 { "TAY", 0x0000001, 0xa8, 0, PutAll },
131 { "TSX", 0x0000001, 0xba, 0, PutAll },
132 { "TXA", 0x0000001, 0x8a, 0, PutAll },
133 { "TXS", 0x0000001, 0x9a, 0, PutAll },
134 { "TYA", 0x0000001, 0x98, 0, PutAll }
138 /* Instruction table for the 65SC02 */
139 #define INS_COUNT_65SC02 66
140 static const struct {
142 InsDesc Ins[INS_COUNT_65SC02];
146 { "ADC", 0x080A66C, 0x60, 0, PutAll },
147 { "AND", 0x080A66C, 0x20, 0, PutAll },
148 { "ASL", 0x000006e, 0x02, 1, PutAll },
149 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
150 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
151 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
152 { "BIT", 0x0A0006C, 0x00, 2, PutAll },
153 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
154 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
155 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
156 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
157 { "BRK", 0x0000001, 0x00, 0, PutAll },
158 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
159 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
160 { "CLC", 0x0000001, 0x18, 0, PutAll },
161 { "CLD", 0x0000001, 0xd8, 0, PutAll },
162 { "CLI", 0x0000001, 0x58, 0, PutAll },
163 { "CLV", 0x0000001, 0xb8, 0, PutAll },
164 { "CMP", 0x080A66C, 0xc0, 0, PutAll },
165 { "CPX", 0x080000C, 0xe0, 1, PutAll },
166 { "CPY", 0x080000C, 0xc0, 1, PutAll },
167 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
168 { "DEC", 0x000006F, 0x00, 3, PutAll },
169 { "DEX", 0x0000001, 0xca, 0, PutAll },
170 { "DEY", 0x0000001, 0x88, 0, PutAll },
171 { "EOR", 0x080A66C, 0x40, 0, PutAll },
172 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
173 { "INC", 0x000006f, 0x00, 4, PutAll },
174 { "INX", 0x0000001, 0xe8, 0, PutAll },
175 { "INY", 0x0000001, 0xc8, 0, PutAll },
176 { "JMP", 0x0010808, 0x4c, 6, PutAll },
177 { "JSR", 0x0000008, 0x20, 7, PutAll },
178 { "LDA", 0x080A66C, 0xa0, 0, PutAll },
179 { "LDX", 0x080030C, 0xa2, 1, PutAll },
180 { "LDY", 0x080006C, 0xa0, 1, PutAll },
181 { "LSR", 0x000006F, 0x42, 1, PutAll },
182 { "NOP", 0x0000001, 0xea, 0, PutAll },
183 { "ORA", 0x080A66C, 0x00, 0, PutAll },
184 { "PHA", 0x0000001, 0x48, 0, PutAll },
185 { "PHP", 0x0000001, 0x08, 0, PutAll },
186 { "PHX", 0x0000001, 0xda, 0, PutAll },
187 { "PHY", 0x0000001, 0x5a, 0, PutAll },
188 { "PLA", 0x0000001, 0x68, 0, PutAll },
189 { "PLP", 0x0000001, 0x28, 0, PutAll },
190 { "PLX", 0x0000001, 0xfa, 0, PutAll },
191 { "PLY", 0x0000001, 0x7a, 0, PutAll },
192 { "ROL", 0x000006F, 0x22, 1, PutAll },
193 { "ROR", 0x000006F, 0x62, 1, PutAll },
194 { "RTI", 0x0000001, 0x40, 0, PutAll },
195 { "RTS", 0x0000001, 0x60, 0, PutAll },
196 { "SBC", 0x080A66C, 0xe0, 0, PutAll },
197 { "SEC", 0x0000001, 0x38, 0, PutAll },
198 { "SED", 0x0000001, 0xf8, 0, PutAll },
199 { "SEI", 0x0000001, 0x78, 0, PutAll },
200 { "STA", 0x000A66C, 0x80, 0, PutAll },
201 { "STX", 0x000010c, 0x82, 1, PutAll },
202 { "STY", 0x000002c, 0x80, 1, PutAll },
203 { "STZ", 0x000006c, 0x04, 5, PutAll },
204 { "TAX", 0x0000001, 0xaa, 0, PutAll },
205 { "TAY", 0x0000001, 0xa8, 0, PutAll },
206 { "TRB", 0x000000c, 0x10, 1, PutAll },
207 { "TSB", 0x000000c, 0x00, 1, PutAll },
208 { "TSX", 0x0000001, 0xba, 0, PutAll },
209 { "TXA", 0x0000001, 0x8a, 0, PutAll },
210 { "TXS", 0x0000001, 0x9a, 0, PutAll },
211 { "TYA", 0x0000001, 0x98, 0, PutAll }
215 /* Instruction table for the 65816 */
216 #define INS_COUNT_65816 101
217 static const struct {
219 InsDesc Ins[INS_COUNT_65816];
223 { "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
224 { "AND", 0x0b8f6fc, 0x20, 0, PutAll },
225 { "ASL", 0x000006e, 0x02, 1, PutAll },
226 { "BCC", 0x0020000, 0x90, 0, PutPCRel8 },
227 { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 },
228 { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 },
229 { "BGE", 0x0020000, 0xb0, 0, PutPCRel8 }, /* == BCS */
230 { "BIT", 0x0a0006c, 0x00, 2, PutAll },
231 { "BLT", 0x0020000, 0x90, 0, PutPCRel8 }, /* == BCC */
232 { "BMI", 0x0020000, 0x30, 0, PutPCRel8 },
233 { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 },
234 { "BPL", 0x0020000, 0x10, 0, PutPCRel8 },
235 { "BRA", 0x0020000, 0x80, 0, PutPCRel8 },
236 { "BRK", 0x0000001, 0x00, 0, PutAll },
237 { "BRL", 0x0040000, 0x82, 0, PutPCRel16 },
238 { "BVC", 0x0020000, 0x50, 0, PutPCRel8 },
239 { "BVS", 0x0020000, 0x70, 0, PutPCRel8 },
240 { "CLC", 0x0000001, 0x18, 0, PutAll },
241 { "CLD", 0x0000001, 0xd8, 0, PutAll },
242 { "CLI", 0x0000001, 0x58, 0, PutAll },
243 { "CLV", 0x0000001, 0xb8, 0, PutAll },
244 { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll },
245 { "COP", 0x0000004, 0x02, 6, PutAll },
246 { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */
247 { "CPX", 0x0c0000c, 0xe0, 1, PutAll },
248 { "CPY", 0x0c0000c, 0xc0, 1, PutAll },
249 { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */
250 { "DEC", 0x000006F, 0x00, 3, PutAll },
251 { "DEX", 0x0000001, 0xca, 0, PutAll },
252 { "DEY", 0x0000001, 0x88, 0, PutAll },
253 { "EOR", 0x0b8f6fc, 0x40, 0, PutAll },
254 { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */
255 { "INC", 0x000006F, 0x00, 4, PutAll },
256 { "INX", 0x0000001, 0xe8, 0, PutAll },
257 { "INY", 0x0000001, 0xc8, 0, PutAll },
258 { "JML", 0x0000810, 0x5c, 1, PutAll },
259 { "JMP", 0x0010818, 0x4c, 6, PutAll },
260 { "JSL", 0x0000010, 0x20, 7, PutAll },
261 { "JSR", 0x0010018, 0x20, 7, PutAll },
262 { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll },
263 { "LDX", 0x0c0030c, 0xa2, 1, PutAll },
264 { "LDY", 0x0c0006c, 0xa0, 1, PutAll },
265 { "LSR", 0x000006F, 0x42, 1, PutAll },
266 { "MVN", 0x1000000, 0x54, 0, PutBlockMove },
267 { "MVP", 0x1000000, 0x44, 0, PutBlockMove },
268 { "NOP", 0x0000001, 0xea, 0, PutAll },
269 { "ORA", 0x0b8f6fc, 0x00, 0, PutAll },
270 { "PEA", 0x0000008, 0xf4, 6, PutAll },
271 { "PEI", 0x0800000, 0xd4, 0, PutAll },
272 { "PER", 0x0040000, 0x62, 0, PutPCRel16 },
273 { "PHA", 0x0000001, 0x48, 0, PutAll },
274 { "PHB", 0x0000001, 0x8b, 0, PutAll },
275 { "PHD", 0x0000001, 0x0b, 0, PutAll },
276 { "PHK", 0x0000001, 0x4b, 0, PutAll },
277 { "PHP", 0x0000001, 0x08, 0, PutAll },
278 { "PHX", 0x0000001, 0xda, 0, PutAll },
279 { "PHY", 0x0000001, 0x5a, 0, PutAll },
280 { "PLA", 0x0000001, 0x68, 0, PutAll },
281 { "PLB", 0x0000001, 0xab, 0, PutAll },
282 { "PLD", 0x0000001, 0x2b, 0, PutAll },
283 { "PLP", 0x0000001, 0x28, 0, PutAll },
284 { "PLX", 0x0000001, 0xfa, 0, PutAll },
285 { "PLY", 0x0000001, 0x7a, 0, PutAll },
286 { "REP", 0x0800000, 0xc2, 1, PutREP },
287 { "ROL", 0x000006F, 0x22, 1, PutAll },
288 { "ROR", 0x000006F, 0x62, 1, PutAll },
289 { "RTI", 0x0000001, 0x40, 0, PutAll },
290 { "RTL", 0x0000001, 0x6b, 0, PutAll },
291 { "RTS", 0x0000001, 0x60, 0, PutAll },
292 { "SBC", 0x0b8f6fc, 0xe0, 0, PutAll },
293 { "SEC", 0x0000001, 0x38, 0, PutAll },
294 { "SED", 0x0000001, 0xf8, 0, PutAll },
295 { "SEI", 0x0000001, 0x78, 0, PutAll },
296 { "SEP", 0x0800000, 0xe2, 1, PutSEP },
297 { "STA", 0x018f6fc, 0x80, 0, PutAll },
298 { "STP", 0x0000001, 0xdb, 0, PutAll },
299 { "STX", 0x000010c, 0x82, 1, PutAll },
300 { "STY", 0x000002c, 0x80, 1, PutAll },
301 { "STZ", 0x000006c, 0x04, 5, PutAll },
302 { "SWA", 0x0000001, 0xeb, 0, PutAll }, /* == XBA */
303 { "TAD", 0x0000001, 0x5b, 0, PutAll }, /* == TCD */
304 { "TAS", 0x0000001, 0x1b, 0, PutAll }, /* == TCS */
305 { "TAX", 0x0000001, 0xaa, 0, PutAll },
306 { "TAY", 0x0000001, 0xa8, 0, PutAll },
307 { "TCD", 0x0000001, 0x5b, 0, PutAll },
308 { "TCS", 0x0000001, 0x1b, 0, PutAll },
309 { "TDA", 0x0000001, 0x7b, 0, PutAll }, /* == TDC */
310 { "TDC", 0x0000001, 0x7b, 0, PutAll },
311 { "TRB", 0x000000c, 0x10, 1, PutAll },
312 { "TSA", 0x0000001, 0x3b, 0, PutAll }, /* == TSC */
313 { "TSB", 0x000000c, 0x00, 1, PutAll },
314 { "TSC", 0x0000001, 0x3b, 0, PutAll },
315 { "TSX", 0x0000001, 0xba, 0, PutAll },
316 { "TXA", 0x0000001, 0x8a, 0, PutAll },
317 { "TXS", 0x0000001, 0x9a, 0, PutAll },
318 { "TXY", 0x0000001, 0x9b, 0, PutAll },
319 { "TYA", 0x0000001, 0x98, 0, PutAll },
320 { "TYX", 0x0000001, 0xbb, 0, PutAll },
321 { "WAI", 0x0000001, 0xcb, 0, PutAll },
322 { "XBA", 0x0000001, 0xeb, 0, PutAll },
323 { "XCE", 0x0000001, 0xfb, 0, PutAll }
328 /* Table for the SUNPLUS CPU */
329 #include "sunplus.inc"
334 /* An array with instruction tables */
335 static const InsTable* InsTabs[CPU_COUNT] = {
336 (const InsTable*) &InsTab6502,
337 (const InsTable*) &InsTab65SC02,
338 (const InsTable*) &InsTab65816,
340 (const InsTable*) &InsTabSunPlus,
345 const InsTable* InsTab = (const InsTable*) &InsTab6502;
347 /* Table to build the effective opcode from a base opcode and an addressing
350 unsigned char EATab [9][AMI_COUNT] = {
352 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
353 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
354 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
358 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
359 0x14, 0x1C, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
370 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
390 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
401 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
407 /* Table that encodes the additional bytes for each instruction */
408 unsigned char ExtBytes [AMI_COUNT] = {
413 3, /* Absolute long */
416 3, /* Absolute long,X */
425 2, /* (Absolute,X) */
426 1, /* Relative short */
427 2, /* Relative long */
430 1, /* Immidiate accu */
431 1, /* Immidiate index */
432 1, /* Immidiate byte */
438 /*****************************************************************************/
439 /* Handler functions */
440 /*****************************************************************************/
444 static long PutImmed8 (const InsDesc* Ins)
445 /* Parse and emit an immediate 8 bit instruction. Return the value of the
446 * operand if it's available and const.
451 unsigned long AddrMode;
452 unsigned char OpCode;
455 /* Get the addressing mode used */
456 GetEA (&AddrMode, &Expr, &Bank);
458 /* From the possible addressing modes, remove the ones that are invalid
459 * for this instruction or CPU.
461 AddrMode &= Ins->AddrMode;
463 /* If we have possible zero page addressing modes, and the expression
464 * involved (if any) is not in byte range, remove the zero page addressing
467 if (Expr && (AddrMode & AM_ZP) && !IsByteExpr (Expr)) {
471 /* Check if we have any adressing modes left */
473 Error (ERR_ILLEGAL_ADDR_MODE);
476 AddrMode = BitFind (AddrMode);
478 /* Build the opcode */
479 OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode];
481 /* If we have an expression and it's const, get it's value */
482 if (Expr && IsConstExpr (Expr)) {
483 Val = GetExprVal (Expr);
486 /* Check how many extension bytes are needed and output the instruction */
487 switch (ExtBytes [AddrMode]) {
490 Emit1 (OpCode, Expr);
494 Internal ("Invalid operand byte count: %u", ExtBytes [AddrMode]);
497 /* Return the expression value */
503 static void PutPCRel8 (const InsDesc* Ins)
504 /* Handle branches with a 8 bit distance */
506 EmitPCRel (Ins->BaseCode, BranchExpr (2), 1);
511 static void PutPCRel16 (const InsDesc* Ins)
512 /* Handle branches with an 16 bit distance and PER */
514 EmitPCRel (Ins->BaseCode, BranchExpr (3), 2);
519 static void PutBlockMove (const InsDesc* Ins)
520 /* Handle the blockmove instructions */
522 Emit0 (Ins->BaseCode);
523 EmitByte (Expression ());
525 EmitByte (Expression ());
530 static void PutREP (const InsDesc* Ins)
531 /* Emit a REP instruction, track register sizes */
533 /* Use the generic handler */
534 long Val = PutImmed8 (Ins);
536 /* We track the status only for the 816 CPU and in smart mode */
537 if (CPU == CPU_65816 && SmartMode) {
539 /* Check the range for Val. */
541 /* We had an error */
542 Warning (WARN_CANNOT_TRACK_STATUS);
545 /* Index registers to 16 bit */
546 ExtBytes [AMI_IMM_INDEX] = 2;
550 ExtBytes [AMI_IMM_ACCU] = 2;
558 static void PutSEP (const InsDesc* Ins)
559 /* Emit a SEP instruction, track register sizes */
561 /* Use the generic handler */
562 long Val = PutImmed8 (Ins);
564 /* We track the status only for the 816 CPU and in smart mode */
565 if (CPU == CPU_65816 && SmartMode) {
567 /* Check the range for Val. */
569 /* We had an error */
570 Warning (WARN_CANNOT_TRACK_STATUS);
573 /* Index registers to 8 bit */
574 ExtBytes [AMI_IMM_INDEX] = 1;
578 ExtBytes [AMI_IMM_ACCU] = 1;
586 static void PutAll (const InsDesc* Ins)
587 /* Handle all other instructions */
591 unsigned long AddrModeSet;
592 unsigned char OpCode;
594 unsigned long AddrModeBit;
596 /* Get the addressing mode used */
597 GetEA (&AddrModeSet, &Expr, &Bank);
599 /* From the possible addressing modes, remove the ones that are invalid
600 * for this instruction or CPU.
602 AddrModeSet &= Ins->AddrMode;
604 /* If we have possible zero page addressing modes, and the expression
605 * involved (if any) is not in byte range, remove the zero page addressing
608 if (Expr && (AddrModeSet & AM_ZP) && !IsByteExpr (Expr)) {
609 AddrModeSet &= ~AM_ZP;
612 /* Check if we have any adressing modes left */
613 if (AddrModeSet == 0) {
614 Error (ERR_ILLEGAL_ADDR_MODE);
617 AddrMode = BitFind (AddrModeSet);
619 /* Build the opcode */
620 OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode];
622 /* Check how many extension bytes are needed and output the instruction */
623 switch (ExtBytes [AddrMode]) {
630 Emit1 (OpCode, Expr);
634 AddrModeBit = (1L << AddrMode);
635 if (CPU == CPU_65816 && (AddrModeBit & (AM_ABS | AM_ABS_X | AM_ABS_Y))) {
636 /* This is a 16 bit mode that uses an address. If in 65816,
637 * mode, force this address into 16 bit range to allow
638 * addressing inside a 64K segment.
640 Emit2 (OpCode, ForceWordExpr (Expr));
642 Emit2 (OpCode, Expr);
648 /* Separate bank given */
649 Emit3b (OpCode, Expr, Bank);
651 /* One far argument */
652 Emit3 (OpCode, Expr);
657 Internal ("Invalid operand byte count: %u", ExtBytes [AddrMode]);
664 /*****************************************************************************/
666 /*****************************************************************************/
670 static int CmpName (const void* Key, const void* Instr)
671 /* Compare function for bsearch */
673 return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
678 void SetCPU (cpu_t NewCPU)
681 /* Make sure the parameter is correct */
682 CHECK (NewCPU < CPU_COUNT);
684 /* Check if we have support for the new CPU, if so, use it */
685 if (InsTabs[NewCPU]) {
687 InsTab = InsTabs[CPU];
689 Error (ERR_CPU_NOT_SUPPORTED);
696 /* Return the current CPU */
703 int FindInstruction (const char* Ident)
704 /* Check if Ident is a valid mnemonic. If so, return the index in the
705 * instruction table. If not, return -1.
709 char Key [sizeof (I->Mnemonic)];
711 /* Accept only strings with the right length */
712 if (strlen (Ident) != sizeof (I->Mnemonic)-1) {
717 /* Make a copy, and uppercase that copy */
718 Key [0] = toupper (Ident [0]);
719 Key [1] = toupper (Ident [1]);
720 Key [2] = toupper (Ident [2]);
723 /* Search for the key */
724 I = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
729 /* Found, return the entry */
730 return I - InsTab->Ins;
736 void HandleInstruction (unsigned Index)
737 /* Handle the mnemonic with the given index */
740 PRECONDITION (Index < InsTab->Count);
742 /* Skip the mnemonic token */
745 /* Call the handler */
746 InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);