1 /*****************************************************************************/
5 /* Opcode and addressing mode definitions */
9 /* (C) 2001 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
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[OPCODE_COUNT] = {
60 /* Opcodes for the virtual stack machine */
61 { OPC_CALL, /* opcode */
62 "call", /* mnemonic */
66 OF_CPU_VM | OF_CALL /* flags */
68 { OPC_ENTER, /* opcode */
69 "enter", /* mnemonic */
75 { OPC_JMP, /* opcode */
76 "jump", /* mnemonic */
80 OF_CPU_VM | OF_UBRA /* flags */
82 { OPC_LDA, /* opcode */
87 OF_CPU_VM | OF_LOAD /* flags */
89 { OPC_LDAX, /* opcode */
90 "ldax", /* mnemonic */
94 OF_CPU_VM | OF_LOAD /* flags */
96 { OPC_LDEAX, /* opcode */
97 "ldeax", /* mnemonic */
101 OF_CPU_VM | OF_LOAD /* flags */
103 { OPC_LEA, /* opcode */
104 "lea", /* mnemonic */
108 OF_CPU_VM /* flags */
110 { OPC_LEAVE, /* opcode */
111 "leave", /* mnemonic */
115 OF_CPU_VM /* flags */
117 { OPC_PHA, /* opcode */
118 "pha", /* mnemonic */
122 OF_CPU_VM /* flags */
124 { OPC_PHAX, /* opcode */
125 "phax", /* mnemonic */
129 OF_CPU_VM /* flags */
131 { OPC_PHEAX, /* opcode */
132 "pheax", /* mnemonic */
136 OF_CPU_VM /* flags */
138 { OPC_SPACE, /* opcode */
139 "space", /* mnemonic */
143 OF_CPU_VM /* flags */
145 { OPC_STA, /* opcode */
146 "sta", /* mnemonic */
150 OF_CPU_VM /* flags */
152 { OPC_STAX, /* opcode */
153 "stax", /* mnemonic */
157 OF_CPU_VM /* flags */
159 { OPC_STEAX, /* opcode */
160 "steax", /* mnemonic */
164 OF_CPU_VM /* flags */
168 { OP65_ADC, /* opcode */
169 "adc", /* mnemonic */
175 { OP65_AND, /* opcode */
176 "and", /* mnemonic */
182 { OP65_ASL, /* opcode */
183 "asl", /* mnemonic */
189 { OP65_BCC, /* opcode */
190 "bcc", /* mnemonic */
196 { OP65_BCS, /* opcode */
197 "bcs", /* mnemonic */
203 { OP65_BEQ, /* opcode */
204 "beq", /* mnemonic */
208 OF_CBRA | OF_ZBRA | OF_FBRA /* flags */
210 { OP65_BIT, /* opcode */
211 "bit", /* mnemonic */
217 { OP65_BMI, /* opcode */
218 "bmi", /* mnemonic */
222 OF_CBRA | OF_FBRA /* flags */
224 { OP65_BNE, /* opcode */
225 "bne", /* mnemonic */
229 OF_CBRA | OF_ZBRA | OF_FBRA /* flags */
231 { OP65_BPL, /* opcode */
232 "bpl", /* mnemonic */
236 OF_CBRA | OF_FBRA /* flags */
238 { OP65_BRA, /* opcode */
239 "bra", /* mnemonic */
245 { OP65_BRK, /* opcode */
246 "brk", /* mnemonic */
252 { OP65_BVC, /* opcode */
253 "bvc", /* mnemonic */
259 { OP65_BVS, /* opcode */
260 "bvs", /* mnemonic */
266 { OP65_CLC, /* opcode */
267 "clc", /* mnemonic */
273 { OP65_CLD, /* opcode */
274 "cld", /* mnemonic */
280 { OP65_CLI, /* opcode */
281 "cli", /* mnemonic */
287 { OP65_CLV, /* opcode */
288 "clv", /* mnemonic */
294 { OP65_CMP, /* opcode */
295 "cmp", /* mnemonic */
301 { OP65_CPX, /* opcode */
302 "cpx", /* mnemonic */
308 { OP65_CPY, /* opcode */
309 "cpy", /* mnemonic */
315 { OP65_DEA, /* opcode */
316 "dea", /* mnemonic */
322 { OP65_DEC, /* opcode */
323 "dec", /* mnemonic */
329 { OP65_DEX, /* opcode */
330 "dex", /* mnemonic */
336 { OP65_DEY, /* opcode */
337 "dey", /* mnemonic */
343 { OP65_EOR, /* opcode */
344 "eor", /* mnemonic */
350 { OP65_INA, /* opcode */
351 "ina", /* mnemonic */
357 { OP65_INC, /* opcode */
358 "inc", /* mnemonic */
364 { OP65_INX, /* opcode */
365 "inx", /* mnemonic */
371 { OP65_INY, /* opcode */
372 "iny", /* mnemonic */
378 { OP65_JCC, /* opcode */
379 "jcc", /* mnemonic */
383 OF_CBRA | OF_LBRA /* flags */
385 { OP65_JCS, /* opcode */
386 "jcs", /* mnemonic */
390 OF_CBRA | OF_LBRA /* flags */
392 { OP65_JEQ, /* opcode */
393 "jeq", /* mnemonic */
397 OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA /* flags */
399 { OP65_JMI, /* opcode */
400 "jmi", /* mnemonic */
404 OF_CBRA | OF_LBRA | OF_FBRA /* flags */
406 { OP65_JMP, /* opcode */
407 "jmp", /* mnemonic */
411 OF_UBRA | OF_LBRA /* flags */
413 { OP65_JNE, /* opcode */
414 "jne", /* mnemonic */
418 OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA /* flags */
420 { OP65_JPL, /* opcode */
421 "jpl", /* mnemonic */
425 OF_CBRA | OF_LBRA | OF_FBRA /* flags */
427 { OP65_JSR, /* opcode */
428 "jsr", /* mnemonic */
434 { OP65_JVC, /* opcode */
435 "jvc", /* mnemonic */
439 OF_CBRA | OF_LBRA /* flags */
441 { OP65_JVS, /* opcode */
442 "jvs", /* mnemonic */
446 OF_CBRA | OF_LBRA /* flags */
448 { OP65_LDA, /* opcode */
449 "lda", /* mnemonic */
455 { OP65_LDX, /* opcode */
456 "ldx", /* mnemonic */
462 { OP65_LDY, /* opcode */
463 "ldy", /* mnemonic */
469 { OP65_LSR, /* opcode */
470 "lsr", /* mnemonic */
476 { OP65_NOP, /* opcode */
477 "nop", /* mnemonic */
483 { OP65_ORA, /* opcode */
484 "ora", /* mnemonic */
490 { OP65_PHA, /* opcode */
491 "pha", /* mnemonic */
497 { OP65_PHP, /* opcode */
498 "php", /* mnemonic */
504 { OP65_PHX, /* opcode */
505 "phx", /* mnemonic */
511 { OP65_PHY, /* opcode */
512 "phy", /* mnemonic */
518 { OP65_PLA, /* opcode */
519 "pla", /* mnemonic */
525 { OP65_PLP, /* opcode */
526 "plp", /* mnemonic */
532 { OP65_PLX, /* opcode */
533 "plx", /* mnemonic */
539 { OP65_PLY, /* opcode */
540 "ply", /* mnemonic */
546 { OP65_ROL, /* opcode */
547 "rol", /* mnemonic */
553 { OP65_ROR, /* opcode */
554 "ror", /* mnemonic */
560 { OP65_RTI, /* opcode */
561 "rti", /* mnemonic */
567 { OP65_RTS, /* opcode */
568 "rts", /* mnemonic */
574 { OP65_SBC, /* opcode */
575 "sbc", /* mnemonic */
581 { OP65_SEC, /* opcode */
582 "sec", /* mnemonic */
588 { OP65_SED, /* opcode */
589 "sed", /* mnemonic */
595 { OP65_SEI, /* opcode */
596 "sei", /* mnemonic */
602 { OP65_STA, /* opcode */
603 "sta", /* mnemonic */
609 { OP65_STX, /* opcode */
610 "stx", /* mnemonic */
616 { OP65_STY, /* opcode */
617 "sty", /* mnemonic */
623 { OP65_TAX, /* opcode */
624 "tax", /* mnemonic */
630 { OP65_TAY, /* opcode */
631 "tay", /* mnemonic */
637 { OP65_TRB, /* opcode */
638 "trb", /* mnemonic */
644 { OP65_TSB, /* opcode */
645 "tsb", /* mnemonic */
651 { OP65_TSX, /* opcode */
652 "tsx", /* mnemonic */
658 { OP65_TXA, /* opcode */
659 "txa", /* mnemonic */
665 { OP65_TXS, /* opcode */
666 "txs", /* mnemonic */
672 { OP65_TYA, /* opcode */
673 "tya", /* mnemonic */
683 /*****************************************************************************/
685 /*****************************************************************************/
689 static int FindCmp (const void* Key, const void* Desc)
690 /* Compare function for FindOpcode */
692 return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
697 const OPCDesc* FindOP65 (const char* M)
698 /* Find the given opcode and return the opcode number. If the opcode was not
699 * found, return NULL.
705 /* Check the length of the given string, then copy it into local
706 * storage, converting it to upper case.
708 char Mnemo[sizeof (OPCTable[0].Mnemo)];
710 if (Len >= sizeof (OPCTable[0].Mnemo)) {
711 /* Invalid length means invalid opcode */
714 for (I = 0; I < Len; ++I) {
715 Mnemo[I] = tolower (M[I]);
719 /* Search for the mnemonic in the table and return the result */
720 return bsearch (Mnemo, OPCTable+OP65_FIRST, OP65_COUNT,
721 sizeof (OPCTable[0]), FindCmp );
726 unsigned GetInsnSize (opc_t OPC, am_t AM)
727 /* Return the size of the given instruction */
729 /* Get the opcode desc and check the size given there */
730 const OPCDesc* D = &OPCTable[OPC];
735 /* Check the addressing mode. */
737 case AM65_IMP: return 1;
738 case AM65_ACC: return 1;
739 case AM65_IMM: return 2;
740 case AM65_ZP: return 2;
741 case AM65_ZPX: return 2;
742 case AM65_ABS: return 3;
743 case AM65_ABSX: return 3;
744 case AM65_ABSY: return 3;
745 case AM65_ZPX_IND: return 2;
746 case AM65_ZP_INDY: return 2;
747 case AM65_ZP_IND: return 2;
749 Internal ("Invalid addressing mode");
756 unsigned char GetAMUseInfo (am_t AM)
757 /* Get usage info for the given addressing mode (addressing modes that use
758 * index registers return REG_r info for these registers).
761 /* Check the addressing mode. */
763 case AM65_ACC: return REG_A;
764 case AM65_ZPX: return REG_X;
765 case AM65_ABSX: return REG_X;
766 case AM65_ABSY: return REG_Y;
767 case AM65_ZPX_IND: return REG_X;
768 case AM65_ZP_INDY: return REG_Y;
769 default: return REG_NONE;
775 opc_t GetInverseBranch (opc_t OPC)
776 /* Return a branch that reverse the condition of the branch given in OPC */
779 case OP65_BCC: return OP65_BCS;
780 case OP65_BCS: return OP65_BCC;
781 case OP65_BEQ: return OP65_BNE;
782 case OP65_BMI: return OP65_BPL;
783 case OP65_BNE: return OP65_BEQ;
784 case OP65_BPL: return OP65_BMI;
785 case OP65_BVC: return OP65_BVS;
786 case OP65_BVS: return OP65_BVC;
787 case OP65_JCC: return OP65_JCS;
788 case OP65_JCS: return OP65_JCC;
789 case OP65_JEQ: return OP65_JNE;
790 case OP65_JMI: return OP65_JPL;
791 case OP65_JNE: return OP65_JEQ;
792 case OP65_JPL: return OP65_JMI;
793 case OP65_JVC: return OP65_JVS;
794 case OP65_JVS: return OP65_JVC;
796 Internal ("GetInverseBranch: Invalid opcode: %d", OPC);
803 opc_t MakeShortBranch (opc_t OPC)
804 /* Return the short version of the given branch. If the branch is already
805 * a short branch, return the opcode unchanged.
810 case OP65_JCC: return OP65_BCC;
812 case OP65_JCS: return OP65_BCS;
814 case OP65_JEQ: return OP65_BEQ;
816 case OP65_JMI: return OP65_BMI;
818 case OP65_JNE: return OP65_BNE;
820 case OP65_JPL: return OP65_BPL;
822 case OP65_JVC: return OP65_BVC;
824 case OP65_JVS: return OP65_BVS;
826 case OP65_JMP: return (CPU == CPU_65C02)? OP65_BRA : OP65_JMP;
828 Internal ("MakeShortBranch: Invalid opcode: %d", OPC);
835 opc_t MakeLongBranch (opc_t OPC)
836 /* Return the long version of the given branch. If the branch is already
837 * a long branch, return the opcode unchanged.
842 case OP65_JCC: return OP65_JCC;
844 case OP65_JCS: return OP65_JCS;
846 case OP65_JEQ: return OP65_JEQ;
848 case OP65_JMI: return OP65_JMI;
850 case OP65_JNE: return OP65_JNE;
852 case OP65_JPL: return OP65_JPL;
854 case OP65_JVC: return OP65_JVC;
856 case OP65_JVS: return OP65_JVS;
858 case OP65_JMP: return OP65_JMP;
860 Internal ("MakeLongBranch: Invalid opcode: %d", OPC);
867 bc_t GetBranchCond (opc_t OPC)
868 /* Get the condition for the conditional branch in OPC */
871 case OP65_BCC: return BC_CC;
872 case OP65_BCS: return BC_CS;
873 case OP65_BEQ: return BC_EQ;
874 case OP65_BMI: return BC_MI;
875 case OP65_BNE: return BC_NE;
876 case OP65_BPL: return BC_PL;
877 case OP65_BVC: return BC_VC;
878 case OP65_BVS: return BC_VS;
879 case OP65_JCC: return BC_CC;
880 case OP65_JCS: return BC_CS;
881 case OP65_JEQ: return BC_EQ;
882 case OP65_JMI: return BC_MI;
883 case OP65_JNE: return BC_NE;
884 case OP65_JPL: return BC_PL;
885 case OP65_JVC: return BC_VC;
886 case OP65_JVS: return BC_VS;
888 Internal ("GetBranchCond: Invalid opcode: %d", OPC);
895 bc_t GetInverseCond (bc_t BC)
896 /* Return the inverse condition of the given one */
899 case BC_CC: return BC_CS;
900 case BC_CS: return BC_CC;
901 case BC_EQ: return BC_NE;
902 case BC_MI: return BC_PL;
903 case BC_NE: return BC_EQ;
904 case BC_PL: return BC_MI;
905 case BC_VC: return BC_VS;
906 case BC_VS: return BC_VC;
908 Internal ("GetInverseCond: Invalid condition: %d", BC);