]> git.sur5r.net Git - cc65/blobdiff - src/cc65/opcodes.c
Fixed more E_MCONST issues
[cc65] / src / cc65 / opcodes.c
index 11888de9ca4fa17d0e215ada9059ef4414150c9e..12b779ef839fc5bc7b35cb3fe337b32c27c3b32c 100644 (file)
@@ -42,6 +42,7 @@
 
 /* cc65 */
 #include "codeinfo.h"
+#include "cpu.h"
 #include "error.h"
 #include "opcodes.h"
 
 
 
 
-/* Mapper table, mnemonic --> opcode */
-static const OPCDesc OPCTable[OPC_COUNT] = {
-    { OPC_ADC, "adc", 0, REG_A,           REG_A,    OF_NONE    },
-    { OPC_AND, "and", 0, REG_A,    REG_A,    OF_NONE   },
-    { OPC_ASL, "asl", 0, REG_A,    REG_A,    OF_NONE   },
-    { OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_BIT, "bit", 0, REG_A,    REG_NONE, OF_NONE   },
-    { OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA   },
-    { OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_CMP, "cmp", 0, REG_A,    REG_NONE, OF_NONE   },
-    { OPC_CPX, "cpx", 0, REG_X,    REG_NONE, OF_NONE   },
-    { OPC_CPY, "cpy", 0, REG_Y,    REG_NONE, OF_NONE   },
-    { OPC_DEA, "dea", 1, REG_A,    REG_A,    OF_NONE   },
-    { OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_DEX, "dex", 1, REG_X,    REG_X,    OF_NONE   },
-    { OPC_DEY, "dey", 1, REG_Y,    REG_Y,    OF_NONE   },
-    { OPC_EOR, "eor", 0, REG_A,    REG_A,    OF_NONE   },
-    { OPC_INA, "ina", 1, REG_A,    REG_A,    OF_NONE   },
-    { OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_INX, "inx", 1, REG_X,    REG_X,    OF_NONE   },
-    { OPC_INY, "iny", 1, REG_Y,    REG_Y,    OF_NONE   },
-    { OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA           },
-    { OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA   },
-    { OPC_LDA, "lda", 0, REG_NONE, REG_A,    OF_NONE   },
-    { OPC_LDX, "ldx", 0, REG_NONE, REG_X,    OF_NONE   },
-    { OPC_LDY, "ldy", 0, REG_NONE, REG_Y,    OF_NONE   },
-    { OPC_LSR, "lsr", 0, REG_A,    REG_A,    OF_NONE   },
-    { OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_ORA, "ora", 0, REG_A,    REG_A,    OF_NONE   },
-    { OPC_PHA, "pha", 1, REG_A,    REG_NONE, OF_NONE   },
-    { OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_PHX, "phx", 1, REG_X,    REG_NONE, OF_NONE   },
-    { OPC_PHY, "phy", 1, REG_Y,    REG_NONE, OF_NONE   },
-    { OPC_PLA, "pla", 1, REG_NONE, REG_A,    OF_NONE   },
-    { OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_PLX, "plx", 1, REG_NONE, REG_X,    OF_NONE   },
-    { OPC_PLY, "ply", 1, REG_NONE, REG_Y,    OF_NONE   },
-    { OPC_ROL, "rol", 0, REG_A,    REG_A,    OF_NONE   },
-    { OPC_ROR, "ror", 0, REG_A,    REG_A,    OF_NONE   },
-    { OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET    },
-    { OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET    },
-    { OPC_SBC, "sbc", 0, REG_A,    REG_A,    OF_NONE   },
-    { OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE   },
-    { OPC_STA, "sta", 0, REG_A,    REG_NONE, OF_NONE   },
-    { OPC_STX, "stx", 0, REG_X,    REG_NONE, OF_NONE   },
-    { OPC_STY, "sty", 0, REG_Y,    REG_NONE, OF_NONE   },
-    { OPC_TAX, "tax", 1, REG_A,    REG_X,    OF_NONE   },
-    { OPC_TAY, "tay", 1, REG_A,    REG_Y,    OF_NONE   },
-    { OPC_TRB, "trb", 0, REG_A,    REG_NONE, OF_NONE   },
-    { OPC_TSB, "tsb", 0, REG_A,    REG_NONE, OF_NONE   },
-    { OPC_TSX, "tsx", 1, REG_NONE, REG_X,    OF_NONE   },
-    { OPC_TXA, "txa", 1, REG_X,    REG_A,    OF_NONE   },
-    { OPC_TXS, "txs", 1, REG_X,    REG_NONE, OF_NONE   },
-    { OPC_TYA, "tya", 1, REG_A,    REG_A,    OF_NONE   },
+/* Opcode description table */
+const OPCDesc OPCTable[OPC_COUNT] = {
+    { OPC_ADC, "adc", 0, REG_A,           REG_A,    OF_NONE                        },
+    { OPC_AND, "and", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_ASL, "asl", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA | OF_FBRA    },
+    { OPC_BIT, "bit", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA | OF_FBRA                     },
+    { OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA | OF_FBRA    },
+    { OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA | OF_FBRA                     },
+    { OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA                       },
+    { OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA                       },
+    { OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_CMP, "cmp", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_CPX, "cpx", 0, REG_X,    REG_NONE, OF_NONE                       },
+    { OPC_CPY, "cpy", 0, REG_Y,    REG_NONE, OF_NONE                       },
+    { OPC_DEA, "dea", 1, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_DEX, "dex", 1, REG_X,    REG_X,    OF_NONE                       },
+    { OPC_DEY, "dey", 1, REG_Y,    REG_Y,    OF_NONE                       },
+    { OPC_EOR, "eor", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_INA, "ina", 1, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_INX, "inx", 1, REG_X,    REG_X,    OF_NONE                       },
+    { OPC_INY, "iny", 1, REG_Y,    REG_Y,    OF_NONE                       },
+    { OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA },
+    { OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_FBRA    },
+    { OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA | OF_LBRA             },
+    { OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA },
+    { OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_FBRA    },
+    { OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA             },
+    { OPC_LDA, "lda", 0, REG_NONE, REG_A,    OF_LOAD                               },
+    { OPC_LDX, "ldx", 0, REG_NONE, REG_X,    OF_LOAD                       },
+    { OPC_LDY, "ldy", 0, REG_NONE, REG_Y,    OF_LOAD                       },
+    { OPC_LSR, "lsr", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_ORA, "ora", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_PHA, "pha", 1, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_PHX, "phx", 1, REG_X,    REG_NONE, OF_NONE                       },
+    { OPC_PHY, "phy", 1, REG_Y,    REG_NONE, OF_NONE                       },
+    { OPC_PLA, "pla", 1, REG_NONE, REG_A,    OF_NONE                       },
+    { OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_PLX, "plx", 1, REG_NONE, REG_X,    OF_NONE                       },
+    { OPC_PLY, "ply", 1, REG_NONE, REG_Y,    OF_NONE                       },
+    { OPC_ROL, "rol", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_ROR, "ror", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET                        },
+    { OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET                        },
+    { OPC_SBC, "sbc", 0, REG_A,    REG_A,    OF_NONE                       },
+    { OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE                       },
+    { OPC_STA, "sta", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_STX, "stx", 0, REG_X,    REG_NONE, OF_NONE                       },
+    { OPC_STY, "sty", 0, REG_Y,    REG_NONE, OF_NONE                       },
+    { OPC_TAX, "tax", 1, REG_A,    REG_X,    OF_XFR                        },
+    { OPC_TAY, "tay", 1, REG_A,    REG_Y,    OF_XFR                        },
+    { OPC_TRB, "trb", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_TSB, "tsb", 0, REG_A,    REG_NONE, OF_NONE                       },
+    { OPC_TSX, "tsx", 1, REG_NONE, REG_X,    OF_XFR                        },
+    { OPC_TXA, "txa", 1, REG_X,    REG_A,    OF_XFR                        },
+    { OPC_TXS, "txs", 1, REG_X,    REG_NONE, OF_XFR                        },
+    { OPC_TYA, "tya", 1, REG_A,    REG_A,    OF_XFR                        },
 };
 
 
@@ -180,52 +181,30 @@ unsigned GetInsnSize (opc_t OPC, am_t AM)
     /* Get the opcode desc and check the size given there */
     const OPCDesc* D = &OPCTable[OPC];
     if (D->Size != 0) {
-       return D->Size;
+       return D->Size;
     }
 
     /* Check the addressing mode. */
     switch (AM) {
-       case AM_IMP:      return 1;
-       case AM_ACC:      return 1;
-       case AM_IMM:      return 2;
-       case AM_ZP:       return 2;
-       case AM_ZPX:      return 2;
-       case AM_ABS:      return 3;
-       case AM_ABSX:     return 3;
-       case AM_ABSY:     return 3;
-       case AM_ZPX_IND:  return 2;
-       case AM_ZP_INDY:  return 2;
-       case AM_ZP_IND:   return 2;
-       default:          FAIL ("Invalid addressing mode");
+       case AM_IMP:      return 1;
+       case AM_ACC:      return 1;
+       case AM_IMM:      return 2;
+       case AM_ZP:       return 2;
+       case AM_ZPX:      return 2;
+       case AM_ABS:      return 3;
+       case AM_ABSX:     return 3;
+       case AM_ABSY:     return 3;
+       case AM_ZPX_IND:  return 2;
+       case AM_ZP_INDY:  return 2;
+       case AM_ZP_IND:   return 2;
+       default:          
+           Internal ("Invalid addressing mode");
+           return 0;
     }
 }
 
 
 
-const OPCDesc* GetOPCDesc (opc_t OPC)
-/* Get an opcode description */
-{
-    /* Check the range */
-    PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
-
-    /* Return the description */
-    return &OPCTable [OPC];
-}
-
-
-
-unsigned char GetOPCInfo (opc_t OPC)
-/* Get opcode information */
-{
-    /* Check the range */
-    PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
-
-    /* Return the info */
-    return OPCTable[OPC].Info;
-}
-
-
-
 unsigned char GetAMUseInfo (am_t AM)
 /* Get usage info for the given addressing mode (addressing modes that use
  * index registers return REG_r info for these registers).
@@ -265,7 +244,161 @@ opc_t GetInverseBranch (opc_t OPC)
                case OPC_JPL:   return OPC_JMI;
                case OPC_JVC:   return OPC_JVS;
                case OPC_JVS:   return OPC_JVC;
-       default:        Internal ("GetInverseBranch: Invalid opcode: %d", OPC);
+       default:        
+           Internal ("GetInverseBranch: Invalid opcode: %d", OPC);
+           return 0;
+    }
+}
+
+
+
+opc_t MakeShortBranch (opc_t OPC)
+/* Return the short version of the given branch. If the branch is already
+ * a short branch, return the opcode unchanged.
+ */
+{
+    switch (OPC) {
+               case OPC_BCC:
+               case OPC_JCC:   return OPC_BCC;
+               case OPC_BCS:
+               case OPC_JCS:   return OPC_BCS;
+               case OPC_BEQ:
+               case OPC_JEQ:   return OPC_BEQ;
+               case OPC_BMI:
+               case OPC_JMI:   return OPC_BMI;
+               case OPC_BNE:
+               case OPC_JNE:   return OPC_BNE;
+               case OPC_BPL:
+               case OPC_JPL:   return OPC_BPL;
+               case OPC_BVC:
+               case OPC_JVC:   return OPC_BVC;
+               case OPC_BVS:
+               case OPC_JVS:   return OPC_BVS;
+               case OPC_BRA:
+       case OPC_JMP:   return (CPU == CPU_65C02)? OPC_BRA : OPC_JMP;
+               default:        
+           Internal ("GetShortBranch: Invalid opcode: %d", OPC);
+           return 0;
+    }
+}
+
+
+
+opc_t MakeLongBranch (opc_t OPC)
+/* Return the long version of the given branch. If the branch is already
+ * a long branch, return the opcode unchanged.
+ */
+{
+    switch (OPC) {
+               case OPC_BCC:
+               case OPC_JCC:   return OPC_JCC;
+               case OPC_BCS:
+               case OPC_JCS:   return OPC_JCS;
+               case OPC_BEQ:
+               case OPC_JEQ:   return OPC_JEQ;
+               case OPC_BMI:
+               case OPC_JMI:   return OPC_JMI;
+               case OPC_BNE:
+               case OPC_JNE:   return OPC_JNE;
+               case OPC_BPL:
+               case OPC_JPL:   return OPC_JPL;
+               case OPC_BVC:
+               case OPC_JVC:   return OPC_JVC;
+               case OPC_BVS:
+               case OPC_JVS:   return OPC_JVS;
+       case OPC_BRA:
+       case OPC_JMP:   return OPC_JMP;
+               default:        
+           Internal ("GetShortBranch: Invalid opcode: %d", OPC);
+           return 0;
+    }
+}
+
+
+
+bc_t GetBranchCond (opc_t OPC)
+/* Get the condition for the conditional branch in OPC */
+{
+    switch (OPC) {
+               case OPC_BCC:   return BC_CC;
+               case OPC_BCS:   return BC_CS;
+               case OPC_BEQ:   return BC_EQ;
+               case OPC_BMI:   return BC_MI;
+               case OPC_BNE:   return BC_NE;
+               case OPC_BPL:   return BC_PL;
+               case OPC_BVC:   return BC_VC;
+               case OPC_BVS:   return BC_VS;
+               case OPC_JCC:   return BC_CC;
+               case OPC_JCS:   return BC_CS;
+               case OPC_JEQ:   return BC_EQ;
+               case OPC_JMI:   return BC_MI;
+               case OPC_JNE:   return BC_NE;
+               case OPC_JPL:   return BC_PL;
+               case OPC_JVC:   return BC_VC;
+               case OPC_JVS:   return BC_VS;
+       default:        
+           Internal ("GetBranchCond: Invalid opcode: %d", OPC);
+           return 0;
+    }
+}
+
+
+
+bc_t GetInverseCond (bc_t BC)
+/* Return the inverse condition of the given one */
+{
+    switch (BC) {
+               case BC_CC:     return BC_CS;
+               case BC_CS:     return BC_CC;
+               case BC_EQ:     return BC_NE;
+               case BC_MI:     return BC_PL;
+               case BC_NE:     return BC_EQ;
+               case BC_PL:     return BC_MI;
+               case BC_VC:     return BC_VS;
+               case BC_VS:     return BC_VC;
+       default:        
+           Internal ("GetInverseCond: Invalid condition: %d", BC);
+           return 0;
+    }
+}
+
+
+
+opc_t GetLongBranch (bc_t BC)
+/* Return a long branch for the given branch condition */
+{
+    switch (BC) {
+       case BC_CC:     return OPC_JCC;
+       case BC_CS:     return OPC_JCS;
+       case BC_EQ:     return OPC_JEQ;
+       case BC_MI:     return OPC_JMI;
+       case BC_NE:     return OPC_JNE;
+       case BC_PL:     return OPC_JPL;
+       case BC_VC:     return OPC_JVC;
+       case BC_VS:     return OPC_JVS;
+               default:        
+           Internal ("GetLongBranch: Invalid condition: %d", BC);
+           return 0;
+    }
+}
+
+
+
+opc_t GetShortBranch (bc_t BC)
+/* Return a short branch for the given branch condition */
+{
+    switch (BC) {
+               case BC_CC:     return OPC_BCC;
+               case BC_CS:     return OPC_BCS;
+               case BC_EQ:     return OPC_BEQ;
+               case BC_MI:     return OPC_BMI;
+               case BC_NE:     return OPC_BNE;
+               case BC_PL:     return OPC_BPL;
+               case BC_VC:     return OPC_BVC;
+               case BC_VS:     return OPC_BVS;
+               default:        
+           Internal ("GetShortBranch: Invalid condition: %d", BC);
+           return 0;
     }
 }