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 /*****************************************************************************/
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 /* The current CPU and an array with instruction tables */
335 static enum CPUType CPU = CPU_6502;
336 static const InsTable* InsTabs[CPU_COUNT] = {
337 (const InsTable*) &InsTab6502,
338 (const InsTable*) &InsTab65SC02,
339 (const InsTable*) &InsTab65816,
341 (const InsTable*) &InsTabSunPlus,
346 const InsTable* InsTab = (const InsTable*) &InsTab6502;
348 /* Table to build the effective opcode from a base opcode and an addressing
351 unsigned char EATab [9][AMI_COUNT] = {
353 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F,
354 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01,
355 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09,
359 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00,
360 0x14, 0x1C, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00,
371 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
390 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
391 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00,
402 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
408 /* Table that encodes the additional bytes for each instruction */
409 unsigned char ExtBytes [AMI_COUNT] = {
414 3, /* Absolute long */
417 3, /* Absolute long,X */
426 2, /* (Absolute,X) */
427 1, /* Relative short */
428 2, /* Relative long */
431 1, /* Immidiate accu */
432 1, /* Immidiate index */
433 1, /* Immidiate byte */
439 /*****************************************************************************/
440 /* Handler functions */
441 /*****************************************************************************/
445 static long PutImmed8 (const InsDesc* Ins)
446 /* Parse and emit an immediate 8 bit instruction. Return the value of the
447 * operand if it's available and const.
452 unsigned long AddrMode;
453 unsigned char OpCode;
456 /* Get the addressing mode used */
457 GetEA (&AddrMode, &Expr, &Bank);
459 /* From the possible addressing modes, remove the ones that are invalid
460 * for this instruction or CPU.
462 AddrMode &= Ins->AddrMode;
464 /* If we have possible zero page addressing modes, and the expression
465 * involved (if any) is not in byte range, remove the zero page addressing
468 if (Expr && (AddrMode & AM_ZP) && !IsByteExpr (Expr)) {
472 /* Check if we have any adressing modes left */
474 Error (ERR_ILLEGAL_ADDR_MODE);
477 AddrMode = BitFind (AddrMode);
479 /* Build the opcode */
480 OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode];
482 /* If we have an expression and it's const, get it's value */
483 if (Expr && IsConstExpr (Expr)) {
484 Val = GetExprVal (Expr);
487 /* Check how many extension bytes are needed and output the instruction */
488 switch (ExtBytes [AddrMode]) {
491 Emit1 (OpCode, Expr);
495 Internal ("Invalid operand byte count: %u", ExtBytes [AddrMode]);
498 /* Return the expression value */
504 static void PutPCRel8 (const InsDesc* Ins)
505 /* Handle branches with a 8 bit distance */
507 EmitPCRel (Ins->BaseCode, BranchExpr (2), 1);
512 static void PutPCRel16 (const InsDesc* Ins)
513 /* Handle branches with an 16 bit distance and PER */
515 EmitPCRel (Ins->BaseCode, BranchExpr (3), 2);
520 static void PutBlockMove (const InsDesc* Ins)
521 /* Handle the blockmove instructions */
523 Emit0 (Ins->BaseCode);
524 EmitByte (Expression ());
526 EmitByte (Expression ());
531 static void PutREP (const InsDesc* Ins)
532 /* Emit a REP instruction, track register sizes */
534 /* Use the generic handler */
535 long Val = PutImmed8 (Ins);
537 /* We track the status only for the 816 CPU and in smart mode */
538 if (CPU == CPU_65816 && SmartMode) {
540 /* Check the range for Val. */
542 /* We had an error */
543 Warning (WARN_CANNOT_TRACK_STATUS);
546 /* Index registers to 16 bit */
547 ExtBytes [AMI_IMM_INDEX] = 2;
551 ExtBytes [AMI_IMM_ACCU] = 2;
559 static void PutSEP (const InsDesc* Ins)
560 /* Emit a SEP instruction, track register sizes */
562 /* Use the generic handler */
563 long Val = PutImmed8 (Ins);
565 /* We track the status only for the 816 CPU and in smart mode */
566 if (CPU == CPU_65816 && SmartMode) {
568 /* Check the range for Val. */
570 /* We had an error */
571 Warning (WARN_CANNOT_TRACK_STATUS);
574 /* Index registers to 8 bit */
575 ExtBytes [AMI_IMM_INDEX] = 1;
579 ExtBytes [AMI_IMM_ACCU] = 1;
587 static void PutAll (const InsDesc* Ins)
588 /* Handle all other instructions */
592 unsigned long AddrModeSet;
593 unsigned char OpCode;
595 unsigned long AddrModeBit;
597 /* Get the addressing mode used */
598 GetEA (&AddrModeSet, &Expr, &Bank);
600 /* From the possible addressing modes, remove the ones that are invalid
601 * for this instruction or CPU.
603 AddrModeSet &= Ins->AddrMode;
605 /* If we have possible zero page addressing modes, and the expression
606 * involved (if any) is not in byte range, remove the zero page addressing
609 if (Expr && (AddrModeSet & AM_ZP) && !IsByteExpr (Expr)) {
610 AddrModeSet &= ~AM_ZP;
613 /* Check if we have any adressing modes left */
614 if (AddrModeSet == 0) {
615 Error (ERR_ILLEGAL_ADDR_MODE);
618 AddrMode = BitFind (AddrModeSet);
620 /* Build the opcode */
621 OpCode = Ins->BaseCode | EATab [Ins->ExtCode][AddrMode];
623 /* Check how many extension bytes are needed and output the instruction */
624 switch (ExtBytes [AddrMode]) {
631 Emit1 (OpCode, Expr);
635 AddrModeBit = (1L << AddrMode);
636 if (CPU == CPU_65816 && (AddrModeBit & (AM_ABS | AM_ABS_X | AM_ABS_Y))) {
637 /* This is a 16 bit mode that uses an address. If in 65816,
638 * mode, force this address into 16 bit range to allow
639 * addressing inside a 64K segment.
641 Emit2 (OpCode, ForceWordExpr (Expr));
643 Emit2 (OpCode, Expr);
649 /* Separate bank given */
650 Emit3b (OpCode, Expr, Bank);
652 /* One far argument */
653 Emit3 (OpCode, Expr);
658 Internal ("Invalid operand byte count: %u", ExtBytes [AddrMode]);
665 /*****************************************************************************/
667 /*****************************************************************************/
671 static int CmpName (const void* Key, const void* Instr)
672 /* Compare function for bsearch */
674 return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic);
679 void SetCPU (enum CPUType NewCPU)
682 /* Make sure the parameter is correct */
683 CHECK (NewCPU < CPU_COUNT);
685 /* Check if we have support for the new CPU, if so, use it */
686 if (InsTabs[NewCPU]) {
688 InsTab = InsTabs[CPU];
690 Error (ERR_CPU_NOT_SUPPORTED);
696 enum CPUType GetCPU (void)
697 /* Return the current CPU */
704 int FindInstruction (const char* Ident)
705 /* Check if Ident is a valid mnemonic. If so, return the index in the
706 * instruction table. If not, return -1.
710 char Key [sizeof (I->Mnemonic)];
712 /* Accept only strings with the right length */
713 if (strlen (Ident) != sizeof (I->Mnemonic)-1) {
718 /* Make a copy, and uppercase that copy */
719 Key [0] = toupper (Ident [0]);
720 Key [1] = toupper (Ident [1]);
721 Key [2] = toupper (Ident [2]);
724 /* Search for the key */
725 I = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName);
730 /* Found, return the entry */
731 return I - InsTab->Ins;
737 void HandleInstruction (unsigned Index)
738 /* Handle the mnemonic with the given index */
741 PRECONDITION (Index < InsTab->Count);
743 /* Skip the mnemonic token */
746 /* Call the handler */
747 InsTab->Ins[Index].Emit (&InsTab->Ins[Index]);