1 /*****************************************************************************/
5 /* Opcode and addressing mode definitions */
9 /* (C) 2001-2004 Ullrich von Bassewitz */
10 /* Roemerstrasse 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 /*****************************************************************************/
51 /*****************************************************************************/
53 /*****************************************************************************/
57 /* Opcode description table */
58 const OPCDesc OPCTable[OP65_COUNT] = {
61 { OP65_ADC, /* opcode */
68 { OP65_AND, /* opcode */
75 { OP65_ASL, /* opcode */
80 OF_SETF | OF_NOIMP /* flags */
82 { OP65_BCC, /* opcode */
89 { OP65_BCS, /* opcode */
96 { OP65_BEQ, /* opcode */
101 OF_CBRA | OF_ZBRA | OF_FBRA /* flags */
103 { OP65_BIT, /* opcode */
104 "bit", /* mnemonic */
110 { OP65_BMI, /* opcode */
111 "bmi", /* mnemonic */
115 OF_CBRA | OF_FBRA /* flags */
117 { OP65_BNE, /* opcode */
118 "bne", /* mnemonic */
122 OF_CBRA | OF_ZBRA | OF_FBRA /* flags */
124 { OP65_BPL, /* opcode */
125 "bpl", /* mnemonic */
129 OF_CBRA | OF_FBRA /* flags */
131 { OP65_BRA, /* opcode */
132 "bra", /* mnemonic */
138 { OP65_BRK, /* opcode */
139 "brk", /* mnemonic */
145 { OP65_BVC, /* opcode */
146 "bvc", /* mnemonic */
152 { OP65_BVS, /* opcode */
153 "bvs", /* mnemonic */
159 { OP65_CLC, /* opcode */
160 "clc", /* mnemonic */
166 { OP65_CLD, /* opcode */
167 "cld", /* mnemonic */
173 { OP65_CLI, /* opcode */
174 "cli", /* mnemonic */
180 { OP65_CLV, /* opcode */
181 "clv", /* mnemonic */
187 { OP65_CMP, /* opcode */
188 "cmp", /* mnemonic */
192 OF_SETF | OF_CMP /* flags */
194 { OP65_CPX, /* opcode */
195 "cpx", /* mnemonic */
199 OF_SETF | OF_CMP /* flags */
201 { OP65_CPY, /* opcode */
202 "cpy", /* mnemonic */
206 OF_SETF | OF_CMP /* flags */
208 { OP65_DEA, /* opcode */
209 "dea", /* mnemonic */
213 OF_REG_INCDEC | OF_SETF /* flags */
215 { OP65_DEC, /* opcode */
216 "dec", /* mnemonic */
220 OF_SETF | OF_NOIMP /* flags */
222 { OP65_DEX, /* opcode */
223 "dex", /* mnemonic */
227 OF_REG_INCDEC | OF_SETF /* flags */
229 { OP65_DEY, /* opcode */
230 "dey", /* mnemonic */
234 OF_REG_INCDEC | OF_SETF /* flags */
236 { OP65_EOR, /* opcode */
237 "eor", /* mnemonic */
243 { OP65_INA, /* opcode */
244 "ina", /* mnemonic */
248 OF_REG_INCDEC | OF_SETF /* flags */
250 { OP65_INC, /* opcode */
251 "inc", /* mnemonic */
255 OF_SETF | OF_NOIMP /* flags */
257 { OP65_INX, /* opcode */
258 "inx", /* mnemonic */
262 OF_REG_INCDEC | OF_SETF /* flags */
264 { OP65_INY, /* opcode */
265 "iny", /* mnemonic */
269 OF_REG_INCDEC | OF_SETF /* flags */
271 { OP65_JCC, /* opcode */
272 "jcc", /* mnemonic */
276 OF_CBRA | OF_LBRA /* flags */
278 { OP65_JCS, /* opcode */
279 "jcs", /* mnemonic */
283 OF_CBRA | OF_LBRA /* flags */
285 { OP65_JEQ, /* opcode */
286 "jeq", /* mnemonic */
290 OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA /* flags */
292 { OP65_JMI, /* opcode */
293 "jmi", /* mnemonic */
297 OF_CBRA | OF_LBRA | OF_FBRA /* flags */
299 { OP65_JMP, /* opcode */
300 "jmp", /* mnemonic */
304 OF_UBRA | OF_LBRA /* flags */
306 { OP65_JNE, /* opcode */
307 "jne", /* mnemonic */
311 OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA /* flags */
313 { OP65_JPL, /* opcode */
314 "jpl", /* mnemonic */
318 OF_CBRA | OF_LBRA | OF_FBRA /* flags */
320 { OP65_JSR, /* opcode */
321 "jsr", /* mnemonic */
327 { OP65_JVC, /* opcode */
328 "jvc", /* mnemonic */
332 OF_CBRA | OF_LBRA /* flags */
334 { OP65_JVS, /* opcode */
335 "jvs", /* mnemonic */
339 OF_CBRA | OF_LBRA /* flags */
341 { OP65_LDA, /* opcode */
342 "lda", /* mnemonic */
346 OF_LOAD | OF_SETF /* flags */
348 { OP65_LDX, /* opcode */
349 "ldx", /* mnemonic */
353 OF_LOAD | OF_SETF /* flags */
355 { OP65_LDY, /* opcode */
356 "ldy", /* mnemonic */
360 OF_LOAD | OF_SETF /* flags */
362 { OP65_LSR, /* opcode */
363 "lsr", /* mnemonic */
367 OF_SETF | OF_NOIMP /* flags */
369 { OP65_NOP, /* opcode */
370 "nop", /* mnemonic */
376 { OP65_ORA, /* opcode */
377 "ora", /* mnemonic */
383 { OP65_PHA, /* opcode */
384 "pha", /* mnemonic */
390 { OP65_PHP, /* opcode */
391 "php", /* mnemonic */
397 { OP65_PHX, /* opcode */
398 "phx", /* mnemonic */
404 { OP65_PHY, /* opcode */
405 "phy", /* mnemonic */
411 { OP65_PLA, /* opcode */
412 "pla", /* mnemonic */
418 { OP65_PLP, /* opcode */
419 "plp", /* mnemonic */
425 { OP65_PLX, /* opcode */
426 "plx", /* mnemonic */
432 { OP65_PLY, /* opcode */
433 "ply", /* mnemonic */
439 { OP65_ROL, /* opcode */
440 "rol", /* mnemonic */
444 OF_SETF | OF_NOIMP /* flags */
446 { OP65_ROR, /* opcode */
447 "ror", /* mnemonic */
451 OF_SETF | OF_NOIMP /* flags */
453 /* Mark RTI as "uses all registers but doesn't change them", so the
454 ** optimizer won't remove preceeding loads.
456 { OP65_RTI, /* opcode */
457 "rti", /* mnemonic */
463 { OP65_RTS, /* opcode */
464 "rts", /* mnemonic */
470 { OP65_SBC, /* opcode */
471 "sbc", /* mnemonic */
477 { OP65_SEC, /* opcode */
478 "sec", /* mnemonic */
484 { OP65_SED, /* opcode */
485 "sed", /* mnemonic */
491 { OP65_SEI, /* opcode */
492 "sei", /* mnemonic */
498 { OP65_STA, /* opcode */
499 "sta", /* mnemonic */
505 { OP65_STX, /* opcode */
506 "stx", /* mnemonic */
512 { OP65_STY, /* opcode */
513 "sty", /* mnemonic */
519 { OP65_STZ, /* opcode */
520 "stz", /* mnemonic */
526 { OP65_TAX, /* opcode */
527 "tax", /* mnemonic */
531 OF_XFR | OF_SETF /* flags */
533 { OP65_TAY, /* opcode */
534 "tay", /* mnemonic */
538 OF_XFR | OF_SETF /* flags */
540 { OP65_TRB, /* opcode */
541 "trb", /* mnemonic */
547 { OP65_TSB, /* opcode */
548 "tsb", /* mnemonic */
554 { OP65_TSX, /* opcode */
555 "tsx", /* mnemonic */
559 OF_XFR | OF_SETF /* flags */
561 { OP65_TXA, /* opcode */
562 "txa", /* mnemonic */
566 OF_XFR | OF_SETF /* flags */
568 { OP65_TXS, /* opcode */
569 "txs", /* mnemonic */
575 { OP65_TYA, /* opcode */
576 "tya", /* mnemonic */
580 OF_XFR | OF_SETF /* flags */
586 /*****************************************************************************/
588 /*****************************************************************************/
592 static int FindCmp (const void* Key, const void* Desc)
593 /* Compare function for FindOpcode */
595 return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
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.
608 /* Check the length of the given string, then copy it into local
609 ** storage, converting it to upper case.
611 char Mnemo[sizeof (OPCTable[0].Mnemo)];
613 if (Len >= sizeof (OPCTable[0].Mnemo)) {
614 /* Invalid length means invalid opcode */
617 for (I = 0; I < Len; ++I) {
618 Mnemo[I] = tolower (M[I]);
622 /* Search for the mnemonic in the table and return the result */
623 return bsearch (Mnemo, OPCTable, OP65_COUNT,
624 sizeof (OPCTable[0]), FindCmp );
629 unsigned GetInsnSize (opc_t OPC, am_t AM)
630 /* Return the size of the given instruction */
632 /* Get the opcode desc and check the size given there */
633 const OPCDesc* D = &OPCTable[OPC];
638 /* Check the addressing mode. */
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;
652 Internal ("Invalid addressing mode");
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).
664 /* Check the addressing mode. */
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;
678 opc_t GetInverseBranch (opc_t OPC)
679 /* Return a branch that reverse the condition of the branch given in 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;
699 Internal ("GetInverseBranch: Invalid opcode: %d", OPC);
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.
713 case OP65_JCC: return OP65_BCC;
715 case OP65_JCS: return OP65_BCS;
717 case OP65_JEQ: return OP65_BEQ;
719 case OP65_JMI: return OP65_BMI;
721 case OP65_JNE: return OP65_BNE;
723 case OP65_JPL: return OP65_BPL;
725 case OP65_JVC: return OP65_BVC;
727 case OP65_JVS: return OP65_BVS;
729 case OP65_JMP: return (CPUIsets[CPU] & CPU_ISET_65SC02)? OP65_BRA : OP65_JMP;
731 Internal ("MakeShortBranch: Invalid opcode: %d", OPC);
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.
745 case OP65_JCC: return OP65_JCC;
747 case OP65_JCS: return OP65_JCS;
749 case OP65_JEQ: return OP65_JEQ;
751 case OP65_JMI: return OP65_JMI;
753 case OP65_JNE: return OP65_JNE;
755 case OP65_JPL: return OP65_JPL;
757 case OP65_JVC: return OP65_JVC;
759 case OP65_JVS: return OP65_JVS;
761 case OP65_JMP: return OP65_JMP;
763 Internal ("MakeLongBranch: Invalid opcode: %d", OPC);
770 bc_t GetBranchCond (opc_t OPC)
771 /* Get the condition for the conditional branch in 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;
791 Internal ("GetBranchCond: Invalid opcode: %d", OPC);
798 bc_t GetInverseCond (bc_t BC)
799 /* Return the inverse condition of the given one */
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;
811 Internal ("GetInverseCond: Invalid condition: %d", BC);