1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* opcodes.c */ |
4 | /* */ |
5 | /* Opcode and addressing mode definitions */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 2001-2004 Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | #include "stdlib.h" |
37 | #include <string.h> |
38 | #include <ctype.h> |
39 | |
40 | /* common */ |
41 | #include "check.h" |
42 | #include "cpu.h" |
43 | |
44 | /* cc65 */ |
45 | #include "codeinfo.h" |
46 | #include "error.h" |
47 | #include "opcodes.h" |
48 | |
49 | |
50 | |
51 | /*****************************************************************************/ |
52 | /* Data */ |
53 | /*****************************************************************************/ |
54 | |
55 | |
56 | |
57 | /* Opcode description table */ |
58 | const OPCDesc OPCTable[OP65_COUNT] = { |
59 | |
60 | /* 65XX opcodes */ |
61 | { OP65_ADC, /* opcode */ |
62 | "adc" , /* mnemonic */ |
63 | 0, /* size */ |
64 | REG_A, /* use */ |
65 | REG_A, /* chg */ |
66 | OF_SETF /* flags */ |
67 | }, |
68 | { OP65_AND, /* opcode */ |
69 | "and" , /* mnemonic */ |
70 | 0, /* size */ |
71 | REG_A, /* use */ |
72 | REG_A, /* chg */ |
73 | OF_SETF /* flags */ |
74 | }, |
75 | { OP65_ASL, /* opcode */ |
76 | "asl" , /* mnemonic */ |
77 | 0, /* size */ |
78 | REG_NONE, /* use */ |
79 | REG_NONE, /* chg */ |
80 | OF_SETF | OF_NOIMP /* flags */ |
81 | }, |
82 | { OP65_BCC, /* opcode */ |
83 | "bcc" , /* mnemonic */ |
84 | 2, /* size */ |
85 | REG_NONE, /* use */ |
86 | REG_NONE, /* chg */ |
87 | OF_CBRA /* flags */ |
88 | }, |
89 | { OP65_BCS, /* opcode */ |
90 | "bcs" , /* mnemonic */ |
91 | 2, /* size */ |
92 | REG_NONE, /* use */ |
93 | REG_NONE, /* chg */ |
94 | OF_CBRA /* flags */ |
95 | }, |
96 | { OP65_BEQ, /* opcode */ |
97 | "beq" , /* mnemonic */ |
98 | 2, /* size */ |
99 | REG_NONE, /* use */ |
100 | REG_NONE, /* chg */ |
101 | OF_CBRA | OF_ZBRA | OF_FBRA /* flags */ |
102 | }, |
103 | { OP65_BIT, /* opcode */ |
104 | "bit" , /* mnemonic */ |
105 | 0, /* size */ |
106 | REG_A, /* use */ |
107 | REG_NONE, /* chg */ |
108 | OF_SETF /* flags */ |
109 | }, |
110 | { OP65_BMI, /* opcode */ |
111 | "bmi" , /* mnemonic */ |
112 | 2, /* size */ |
113 | REG_NONE, /* use */ |
114 | REG_NONE, /* chg */ |
115 | OF_CBRA | OF_FBRA /* flags */ |
116 | }, |
117 | { OP65_BNE, /* opcode */ |
118 | "bne" , /* mnemonic */ |
119 | 2, /* size */ |
120 | REG_NONE, /* use */ |
121 | REG_NONE, /* chg */ |
122 | OF_CBRA | OF_ZBRA | OF_FBRA /* flags */ |
123 | }, |
124 | { OP65_BPL, /* opcode */ |
125 | "bpl" , /* mnemonic */ |
126 | 2, /* size */ |
127 | REG_NONE, /* use */ |
128 | REG_NONE, /* chg */ |
129 | OF_CBRA | OF_FBRA /* flags */ |
130 | }, |
131 | { OP65_BRA, /* opcode */ |
132 | "bra" , /* mnemonic */ |
133 | 2, /* size */ |
134 | REG_NONE, /* use */ |
135 | REG_NONE, /* chg */ |
136 | OF_UBRA /* flags */ |
137 | }, |
138 | { OP65_BRK, /* opcode */ |
139 | "brk" , /* mnemonic */ |
140 | 1, /* size */ |
141 | REG_NONE, /* use */ |
142 | REG_NONE, /* chg */ |
143 | OF_NONE /* flags */ |
144 | }, |
145 | { OP65_BVC, /* opcode */ |
146 | "bvc" , /* mnemonic */ |
147 | 2, /* size */ |
148 | REG_NONE, /* use */ |
149 | REG_NONE, /* chg */ |
150 | OF_CBRA /* flags */ |
151 | }, |
152 | { OP65_BVS, /* opcode */ |
153 | "bvs" , /* mnemonic */ |
154 | 2, /* size */ |
155 | REG_NONE, /* use */ |
156 | REG_NONE, /* chg */ |
157 | OF_CBRA /* flags */ |
158 | }, |
159 | { OP65_CLC, /* opcode */ |
160 | "clc" , /* mnemonic */ |
161 | 1, /* size */ |
162 | REG_NONE, /* use */ |
163 | REG_NONE, /* chg */ |
164 | OF_NONE /* flags */ |
165 | }, |
166 | { OP65_CLD, /* opcode */ |
167 | "cld" , /* mnemonic */ |
168 | 1, /* size */ |
169 | REG_NONE, /* use */ |
170 | REG_NONE, /* chg */ |
171 | OF_NONE /* flags */ |
172 | }, |
173 | { OP65_CLI, /* opcode */ |
174 | "cli" , /* mnemonic */ |
175 | 1, /* size */ |
176 | REG_NONE, /* use */ |
177 | REG_NONE, /* chg */ |
178 | OF_NONE /* flags */ |
179 | }, |
180 | { OP65_CLV, /* opcode */ |
181 | "clv" , /* mnemonic */ |
182 | 1, /* size */ |
183 | REG_NONE, /* use */ |
184 | REG_NONE, /* chg */ |
185 | OF_NONE /* flags */ |
186 | }, |
187 | { OP65_CMP, /* opcode */ |
188 | "cmp" , /* mnemonic */ |
189 | 0, /* size */ |
190 | REG_A, /* use */ |
191 | REG_NONE, /* chg */ |
192 | OF_SETF | OF_CMP /* flags */ |
193 | }, |
194 | { OP65_CPX, /* opcode */ |
195 | "cpx" , /* mnemonic */ |
196 | 0, /* size */ |
197 | REG_X, /* use */ |
198 | REG_NONE, /* chg */ |
199 | OF_SETF | OF_CMP /* flags */ |
200 | }, |
201 | { OP65_CPY, /* opcode */ |
202 | "cpy" , /* mnemonic */ |
203 | 0, /* size */ |
204 | REG_Y, /* use */ |
205 | REG_NONE, /* chg */ |
206 | OF_SETF | OF_CMP /* flags */ |
207 | }, |
208 | { OP65_DEA, /* opcode */ |
209 | "dea" , /* mnemonic */ |
210 | 1, /* size */ |
211 | REG_A, /* use */ |
212 | REG_A, /* chg */ |
213 | OF_REG_INCDEC | OF_SETF /* flags */ |
214 | }, |
215 | { OP65_DEC, /* opcode */ |
216 | "dec" , /* mnemonic */ |
217 | 0, /* size */ |
218 | REG_NONE, /* use */ |
219 | REG_NONE, /* chg */ |
220 | OF_SETF | OF_NOIMP /* flags */ |
221 | }, |
222 | { OP65_DEX, /* opcode */ |
223 | "dex" , /* mnemonic */ |
224 | 1, /* size */ |
225 | REG_X, /* use */ |
226 | REG_X, /* chg */ |
227 | OF_REG_INCDEC | OF_SETF /* flags */ |
228 | }, |
229 | { OP65_DEY, /* opcode */ |
230 | "dey" , /* mnemonic */ |
231 | 1, /* size */ |
232 | REG_Y, /* use */ |
233 | REG_Y, /* chg */ |
234 | OF_REG_INCDEC | OF_SETF /* flags */ |
235 | }, |
236 | { OP65_EOR, /* opcode */ |
237 | "eor" , /* mnemonic */ |
238 | 0, /* size */ |
239 | REG_A, /* use */ |
240 | REG_A, /* chg */ |
241 | OF_SETF /* flags */ |
242 | }, |
243 | { OP65_INA, /* opcode */ |
244 | "ina" , /* mnemonic */ |
245 | 1, /* size */ |
246 | REG_A, /* use */ |
247 | REG_A, /* chg */ |
248 | OF_REG_INCDEC | OF_SETF /* flags */ |
249 | }, |
250 | { OP65_INC, /* opcode */ |
251 | "inc" , /* mnemonic */ |
252 | 0, /* size */ |
253 | REG_NONE, /* use */ |
254 | REG_NONE, /* chg */ |
255 | OF_SETF | OF_NOIMP /* flags */ |
256 | }, |
257 | { OP65_INX, /* opcode */ |
258 | "inx" , /* mnemonic */ |
259 | 1, /* size */ |
260 | REG_X, /* use */ |
261 | REG_X, /* chg */ |
262 | OF_REG_INCDEC | OF_SETF /* flags */ |
263 | }, |
264 | { OP65_INY, /* opcode */ |
265 | "iny" , /* mnemonic */ |
266 | 1, /* size */ |
267 | REG_Y, /* use */ |
268 | REG_Y, /* chg */ |
269 | OF_REG_INCDEC | OF_SETF /* flags */ |
270 | }, |
271 | { OP65_JCC, /* opcode */ |
272 | "jcc" , /* mnemonic */ |
273 | 5, /* size */ |
274 | REG_NONE, /* use */ |
275 | REG_NONE, /* chg */ |
276 | OF_CBRA | OF_LBRA /* flags */ |
277 | }, |
278 | { OP65_JCS, /* opcode */ |
279 | "jcs" , /* mnemonic */ |
280 | 5, /* size */ |
281 | REG_NONE, /* use */ |
282 | REG_NONE, /* chg */ |
283 | OF_CBRA | OF_LBRA /* flags */ |
284 | }, |
285 | { OP65_JEQ, /* opcode */ |
286 | "jeq" , /* mnemonic */ |
287 | 5, /* size */ |
288 | REG_NONE, /* use */ |
289 | REG_NONE, /* chg */ |
290 | OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA /* flags */ |
291 | }, |
292 | { OP65_JMI, /* opcode */ |
293 | "jmi" , /* mnemonic */ |
294 | 5, /* size */ |
295 | REG_NONE, /* use */ |
296 | REG_NONE, /* chg */ |
297 | OF_CBRA | OF_LBRA | OF_FBRA /* flags */ |
298 | }, |
299 | { OP65_JMP, /* opcode */ |
300 | "jmp" , /* mnemonic */ |
301 | 3, /* size */ |
302 | REG_NONE, /* use */ |
303 | REG_NONE, /* chg */ |
304 | OF_UBRA | OF_LBRA /* flags */ |
305 | }, |
306 | { OP65_JNE, /* opcode */ |
307 | "jne" , /* mnemonic */ |
308 | 5, /* size */ |
309 | REG_NONE, /* use */ |
310 | REG_NONE, /* chg */ |
311 | OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA /* flags */ |
312 | }, |
313 | { OP65_JPL, /* opcode */ |
314 | "jpl" , /* mnemonic */ |
315 | 5, /* size */ |
316 | REG_NONE, /* use */ |
317 | REG_NONE, /* chg */ |
318 | OF_CBRA | OF_LBRA | OF_FBRA /* flags */ |
319 | }, |
320 | { OP65_JSR, /* opcode */ |
321 | "jsr" , /* mnemonic */ |
322 | 3, /* size */ |
323 | REG_NONE, /* use */ |
324 | REG_NONE, /* chg */ |
325 | OF_CALL /* flags */ |
326 | }, |
327 | { OP65_JVC, /* opcode */ |
328 | "jvc" , /* mnemonic */ |
329 | 5, /* size */ |
330 | REG_NONE, /* use */ |
331 | REG_NONE, /* chg */ |
332 | OF_CBRA | OF_LBRA /* flags */ |
333 | }, |
334 | { OP65_JVS, /* opcode */ |
335 | "jvs" , /* mnemonic */ |
336 | 5, /* size */ |
337 | REG_NONE, /* use */ |
338 | REG_NONE, /* chg */ |
339 | OF_CBRA | OF_LBRA /* flags */ |
340 | }, |
341 | { OP65_LDA, /* opcode */ |
342 | "lda" , /* mnemonic */ |
343 | 0, /* size */ |
344 | REG_NONE, /* use */ |
345 | REG_A, /* chg */ |
346 | OF_LOAD | OF_SETF /* flags */ |
347 | }, |
348 | { OP65_LDX, /* opcode */ |
349 | "ldx" , /* mnemonic */ |
350 | 0, /* size */ |
351 | REG_NONE, /* use */ |
352 | REG_X, /* chg */ |
353 | OF_LOAD | OF_SETF /* flags */ |
354 | }, |
355 | { OP65_LDY, /* opcode */ |
356 | "ldy" , /* mnemonic */ |
357 | 0, /* size */ |
358 | REG_NONE, /* use */ |
359 | REG_Y, /* chg */ |
360 | OF_LOAD | OF_SETF /* flags */ |
361 | }, |
362 | { OP65_LSR, /* opcode */ |
363 | "lsr" , /* mnemonic */ |
364 | 0, /* size */ |
365 | REG_NONE, /* use */ |
366 | REG_NONE, /* chg */ |
367 | OF_SETF | OF_NOIMP /* flags */ |
368 | }, |
369 | { OP65_NOP, /* opcode */ |
370 | "nop" , /* mnemonic */ |
371 | 1, /* size */ |
372 | REG_NONE, /* use */ |
373 | REG_NONE, /* chg */ |
374 | OF_NONE /* flags */ |
375 | }, |
376 | { OP65_ORA, /* opcode */ |
377 | "ora" , /* mnemonic */ |
378 | 0, /* size */ |
379 | REG_A, /* use */ |
380 | REG_A, /* chg */ |
381 | OF_SETF /* flags */ |
382 | }, |
383 | { OP65_PHA, /* opcode */ |
384 | "pha" , /* mnemonic */ |
385 | 1, /* size */ |
386 | REG_A, /* use */ |
387 | REG_NONE, /* chg */ |
388 | OF_NONE /* flags */ |
389 | }, |
390 | { OP65_PHP, /* opcode */ |
391 | "php" , /* mnemonic */ |
392 | 1, /* size */ |
393 | REG_NONE, /* use */ |
394 | REG_NONE, /* chg */ |
395 | OF_NONE /* flags */ |
396 | }, |
397 | { OP65_PHX, /* opcode */ |
398 | "phx" , /* mnemonic */ |
399 | 1, /* size */ |
400 | REG_X, /* use */ |
401 | REG_NONE, /* chg */ |
402 | OF_NONE /* flags */ |
403 | }, |
404 | { OP65_PHY, /* opcode */ |
405 | "phy" , /* mnemonic */ |
406 | 1, /* size */ |
407 | REG_Y, /* use */ |
408 | REG_NONE, /* chg */ |
409 | OF_NONE /* flags */ |
410 | }, |
411 | { OP65_PLA, /* opcode */ |
412 | "pla" , /* mnemonic */ |
413 | 1, /* size */ |
414 | REG_NONE, /* use */ |
415 | REG_A, /* chg */ |
416 | OF_SETF /* flags */ |
417 | }, |
418 | { OP65_PLP, /* opcode */ |
419 | "plp" , /* mnemonic */ |
420 | 1, /* size */ |
421 | REG_NONE, /* use */ |
422 | REG_NONE, /* chg */ |
423 | OF_NONE /* flags */ |
424 | }, |
425 | { OP65_PLX, /* opcode */ |
426 | "plx" , /* mnemonic */ |
427 | 1, /* size */ |
428 | REG_NONE, /* use */ |
429 | REG_X, /* chg */ |
430 | OF_SETF /* flags */ |
431 | }, |
432 | { OP65_PLY, /* opcode */ |
433 | "ply" , /* mnemonic */ |
434 | 1, /* size */ |
435 | REG_NONE, /* use */ |
436 | REG_Y, /* chg */ |
437 | OF_SETF /* flags */ |
438 | }, |
439 | { OP65_ROL, /* opcode */ |
440 | "rol" , /* mnemonic */ |
441 | 0, /* size */ |
442 | REG_NONE, /* use */ |
443 | REG_NONE, /* chg */ |
444 | OF_SETF | OF_NOIMP /* flags */ |
445 | }, |
446 | { OP65_ROR, /* opcode */ |
447 | "ror" , /* mnemonic */ |
448 | 0, /* size */ |
449 | REG_NONE, /* use */ |
450 | REG_NONE, /* chg */ |
451 | OF_SETF | OF_NOIMP /* flags */ |
452 | }, |
453 | /* Mark RTI as "uses all registers but doesn't change them", so the |
454 | ** optimizer won't remove preceeding loads. |
455 | */ |
456 | { OP65_RTI, /* opcode */ |
457 | "rti" , /* mnemonic */ |
458 | 1, /* size */ |
459 | REG_AXY, /* use */ |
460 | REG_NONE, /* chg */ |
461 | OF_RET /* flags */ |
462 | }, |
463 | { OP65_RTS, /* opcode */ |
464 | "rts" , /* mnemonic */ |
465 | 1, /* size */ |
466 | REG_NONE, /* use */ |
467 | REG_NONE, /* chg */ |
468 | OF_RET /* flags */ |
469 | }, |
470 | { OP65_SBC, /* opcode */ |
471 | "sbc" , /* mnemonic */ |
472 | 0, /* size */ |
473 | REG_A, /* use */ |
474 | REG_A, /* chg */ |
475 | OF_SETF /* flags */ |
476 | }, |
477 | { OP65_SEC, /* opcode */ |
478 | "sec" , /* mnemonic */ |
479 | 1, /* size */ |
480 | REG_NONE, /* use */ |
481 | REG_NONE, /* chg */ |
482 | OF_NONE /* flags */ |
483 | }, |
484 | { OP65_SED, /* opcode */ |
485 | "sed" , /* mnemonic */ |
486 | 1, /* size */ |
487 | REG_NONE, /* use */ |
488 | REG_NONE, /* chg */ |
489 | OF_NONE /* flags */ |
490 | }, |
491 | { OP65_SEI, /* opcode */ |
492 | "sei" , /* mnemonic */ |
493 | 1, /* size */ |
494 | REG_NONE, /* use */ |
495 | REG_NONE, /* chg */ |
496 | OF_NONE /* flags */ |
497 | }, |
498 | { OP65_STA, /* opcode */ |
499 | "sta" , /* mnemonic */ |
500 | 0, /* size */ |
501 | REG_A, /* use */ |
502 | REG_NONE, /* chg */ |
503 | OF_STORE /* flags */ |
504 | }, |
505 | { OP65_STX, /* opcode */ |
506 | "stx" , /* mnemonic */ |
507 | 0, /* size */ |
508 | REG_X, /* use */ |
509 | REG_NONE, /* chg */ |
510 | OF_STORE /* flags */ |
511 | }, |
512 | { OP65_STY, /* opcode */ |
513 | "sty" , /* mnemonic */ |
514 | 0, /* size */ |
515 | REG_Y, /* use */ |
516 | REG_NONE, /* chg */ |
517 | OF_STORE /* flags */ |
518 | }, |
519 | { OP65_STZ, /* opcode */ |
520 | "stz" , /* mnemonic */ |
521 | 0, /* size */ |
522 | REG_NONE, /* use */ |
523 | REG_NONE, /* chg */ |
524 | OF_STORE /* flags */ |
525 | }, |
526 | { OP65_TAX, /* opcode */ |
527 | "tax" , /* mnemonic */ |
528 | 1, /* size */ |
529 | REG_A, /* use */ |
530 | REG_X, /* chg */ |
531 | OF_XFR | OF_SETF /* flags */ |
532 | }, |
533 | { OP65_TAY, /* opcode */ |
534 | "tay" , /* mnemonic */ |
535 | 1, /* size */ |
536 | REG_A, /* use */ |
537 | REG_Y, /* chg */ |
538 | OF_XFR | OF_SETF /* flags */ |
539 | }, |
540 | { OP65_TRB, /* opcode */ |
541 | "trb" , /* mnemonic */ |
542 | 0, /* size */ |
543 | REG_A, /* use */ |
544 | REG_NONE, /* chg */ |
545 | OF_SETF /* flags */ |
546 | }, |
547 | { OP65_TSB, /* opcode */ |
548 | "tsb" , /* mnemonic */ |
549 | 0, /* size */ |
550 | REG_A, /* use */ |
551 | REG_NONE, /* chg */ |
552 | OF_SETF /* flags */ |
553 | }, |
554 | { OP65_TSX, /* opcode */ |
555 | "tsx" , /* mnemonic */ |
556 | 1, /* size */ |
557 | REG_NONE, /* use */ |
558 | REG_X, /* chg */ |
559 | OF_XFR | OF_SETF /* flags */ |
560 | }, |
561 | { OP65_TXA, /* opcode */ |
562 | "txa" , /* mnemonic */ |
563 | 1, /* size */ |
564 | REG_X, /* use */ |
565 | REG_A, /* chg */ |
566 | OF_XFR | OF_SETF /* flags */ |
567 | }, |
568 | { OP65_TXS, /* opcode */ |
569 | "txs" , /* mnemonic */ |
570 | 1, /* size */ |
571 | REG_X, /* use */ |
572 | REG_NONE, /* chg */ |
573 | OF_XFR /* flags */ |
574 | }, |
575 | { OP65_TYA, /* opcode */ |
576 | "tya" , /* mnemonic */ |
577 | 1, /* size */ |
578 | REG_Y, /* use */ |
579 | REG_A, /* chg */ |
580 | OF_XFR | OF_SETF /* flags */ |
581 | }, |
582 | }; |
583 | |
584 | |
585 | |
586 | /*****************************************************************************/ |
587 | /* Code */ |
588 | /*****************************************************************************/ |
589 | |
590 | |
591 | |
592 | static int FindCmp (const void* Key, const void* Desc) |
593 | /* Compare function for FindOpcode */ |
594 | { |
595 | return strcmp (Key, ((OPCDesc*)Desc)->Mnemo); |
596 | } |
597 | |
598 | |
599 | |
600 | const OPCDesc* FindOP65 (const char* M) |
601 | /* Find the given opcode and return the opcode number. If the opcode was not |
602 | ** found, return NULL. |
603 | */ |
604 | { |
605 | unsigned I; |
606 | unsigned Len; |
607 | |
608 | /* Check the length of the given string, then copy it into local |
609 | ** storage, converting it to upper case. |
610 | */ |
611 | char Mnemo[sizeof (OPCTable[0].Mnemo)]; |
612 | Len = strlen (M); |
613 | if (Len >= sizeof (OPCTable[0].Mnemo)) { |
614 | /* Invalid length means invalid opcode */ |
615 | return 0; |
616 | } |
617 | for (I = 0; I < Len; ++I) { |
618 | Mnemo[I] = tolower (M[I]); |
619 | } |
620 | Mnemo[I] = '\0'; |
621 | |
622 | /* Search for the mnemonic in the table and return the result */ |
623 | return bsearch (Mnemo, OPCTable, OP65_COUNT, |
624 | sizeof (OPCTable[0]), FindCmp ); |
625 | } |
626 | |
627 | |
628 | |
629 | unsigned GetInsnSize (opc_t OPC, am_t AM) |
630 | /* Return the size of the given instruction */ |
631 | { |
632 | /* Get the opcode desc and check the size given there */ |
633 | const OPCDesc* D = &OPCTable[OPC]; |
634 | if (D->Size != 0) { |
635 | return D->Size; |
636 | } |
637 | |
638 | /* Check the addressing mode. */ |
639 | switch (AM) { |
640 | case AM65_IMP: return 1; |
641 | case AM65_ACC: return 1; |
642 | case AM65_IMM: return 2; |
643 | case AM65_ZP: return 2; |
644 | case AM65_ZPX: return 2; |
645 | case AM65_ABS: return 3; |
646 | case AM65_ABSX: return 3; |
647 | case AM65_ABSY: return 3; |
648 | case AM65_ZPX_IND: return 2; |
649 | case AM65_ZP_INDY: return 2; |
650 | case AM65_ZP_IND: return 2; |
651 | default: |
652 | Internal ("Invalid addressing mode" ); |
653 | return 0; |
654 | } |
655 | } |
656 | |
657 | |
658 | |
659 | unsigned char GetAMUseInfo (am_t AM) |
660 | /* Get usage info for the given addressing mode (addressing modes that use |
661 | ** index registers return REG_r info for these registers). |
662 | */ |
663 | { |
664 | /* Check the addressing mode. */ |
665 | switch (AM) { |
666 | case AM65_ACC: return REG_A; |
667 | case AM65_ZPX: return REG_X; |
668 | case AM65_ABSX: return REG_X; |
669 | case AM65_ABSY: return REG_Y; |
670 | case AM65_ZPX_IND: return REG_X; |
671 | case AM65_ZP_INDY: return REG_Y; |
672 | default: return REG_NONE; |
673 | } |
674 | } |
675 | |
676 | |
677 | |
678 | opc_t GetInverseBranch (opc_t OPC) |
679 | /* Return a branch that reverse the condition of the branch given in OPC */ |
680 | { |
681 | switch (OPC) { |
682 | case OP65_BCC: return OP65_BCS; |
683 | case OP65_BCS: return OP65_BCC; |
684 | case OP65_BEQ: return OP65_BNE; |
685 | case OP65_BMI: return OP65_BPL; |
686 | case OP65_BNE: return OP65_BEQ; |
687 | case OP65_BPL: return OP65_BMI; |
688 | case OP65_BVC: return OP65_BVS; |
689 | case OP65_BVS: return OP65_BVC; |
690 | case OP65_JCC: return OP65_JCS; |
691 | case OP65_JCS: return OP65_JCC; |
692 | case OP65_JEQ: return OP65_JNE; |
693 | case OP65_JMI: return OP65_JPL; |
694 | case OP65_JNE: return OP65_JEQ; |
695 | case OP65_JPL: return OP65_JMI; |
696 | case OP65_JVC: return OP65_JVS; |
697 | case OP65_JVS: return OP65_JVC; |
698 | default: |
699 | Internal ("GetInverseBranch: Invalid opcode: %d" , OPC); |
700 | return 0; |
701 | } |
702 | } |
703 | |
704 | |
705 | |
706 | opc_t MakeShortBranch (opc_t OPC) |
707 | /* Return the short version of the given branch. If the branch is already |
708 | ** a short branch, return the opcode unchanged. |
709 | */ |
710 | { |
711 | switch (OPC) { |
712 | case OP65_BCC: |
713 | case OP65_JCC: return OP65_BCC; |
714 | case OP65_BCS: |
715 | case OP65_JCS: return OP65_BCS; |
716 | case OP65_BEQ: |
717 | case OP65_JEQ: return OP65_BEQ; |
718 | case OP65_BMI: |
719 | case OP65_JMI: return OP65_BMI; |
720 | case OP65_BNE: |
721 | case OP65_JNE: return OP65_BNE; |
722 | case OP65_BPL: |
723 | case OP65_JPL: return OP65_BPL; |
724 | case OP65_BVC: |
725 | case OP65_JVC: return OP65_BVC; |
726 | case OP65_BVS: |
727 | case OP65_JVS: return OP65_BVS; |
728 | case OP65_BRA: |
729 | case OP65_JMP: return (CPUIsets[CPU] & CPU_ISET_65SC02)? OP65_BRA : OP65_JMP; |
730 | default: |
731 | Internal ("MakeShortBranch: Invalid opcode: %d" , OPC); |
732 | return 0; |
733 | } |
734 | } |
735 | |
736 | |
737 | |
738 | opc_t MakeLongBranch (opc_t OPC) |
739 | /* Return the long version of the given branch. If the branch is already |
740 | ** a long branch, return the opcode unchanged. |
741 | */ |
742 | { |
743 | switch (OPC) { |
744 | case OP65_BCC: |
745 | case OP65_JCC: return OP65_JCC; |
746 | case OP65_BCS: |
747 | case OP65_JCS: return OP65_JCS; |
748 | case OP65_BEQ: |
749 | case OP65_JEQ: return OP65_JEQ; |
750 | case OP65_BMI: |
751 | case OP65_JMI: return OP65_JMI; |
752 | case OP65_BNE: |
753 | case OP65_JNE: return OP65_JNE; |
754 | case OP65_BPL: |
755 | case OP65_JPL: return OP65_JPL; |
756 | case OP65_BVC: |
757 | case OP65_JVC: return OP65_JVC; |
758 | case OP65_BVS: |
759 | case OP65_JVS: return OP65_JVS; |
760 | case OP65_BRA: |
761 | case OP65_JMP: return OP65_JMP; |
762 | default: |
763 | Internal ("MakeLongBranch: Invalid opcode: %d" , OPC); |
764 | return 0; |
765 | } |
766 | } |
767 | |
768 | |
769 | |
770 | bc_t GetBranchCond (opc_t OPC) |
771 | /* Get the condition for the conditional branch in OPC */ |
772 | { |
773 | switch (OPC) { |
774 | case OP65_BCC: return BC_CC; |
775 | case OP65_BCS: return BC_CS; |
776 | case OP65_BEQ: return BC_EQ; |
777 | case OP65_BMI: return BC_MI; |
778 | case OP65_BNE: return BC_NE; |
779 | case OP65_BPL: return BC_PL; |
780 | case OP65_BVC: return BC_VC; |
781 | case OP65_BVS: return BC_VS; |
782 | case OP65_JCC: return BC_CC; |
783 | case OP65_JCS: return BC_CS; |
784 | case OP65_JEQ: return BC_EQ; |
785 | case OP65_JMI: return BC_MI; |
786 | case OP65_JNE: return BC_NE; |
787 | case OP65_JPL: return BC_PL; |
788 | case OP65_JVC: return BC_VC; |
789 | case OP65_JVS: return BC_VS; |
790 | default: |
791 | Internal ("GetBranchCond: Invalid opcode: %d" , OPC); |
792 | return 0; |
793 | } |
794 | } |
795 | |
796 | |
797 | |
798 | bc_t GetInverseCond (bc_t BC) |
799 | /* Return the inverse condition of the given one */ |
800 | { |
801 | switch (BC) { |
802 | case BC_CC: return BC_CS; |
803 | case BC_CS: return BC_CC; |
804 | case BC_EQ: return BC_NE; |
805 | case BC_MI: return BC_PL; |
806 | case BC_NE: return BC_EQ; |
807 | case BC_PL: return BC_MI; |
808 | case BC_VC: return BC_VS; |
809 | case BC_VS: return BC_VC; |
810 | default: |
811 | Internal ("GetInverseCond: Invalid condition: %d" , BC); |
812 | return 0; |
813 | } |
814 | } |
815 | |