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 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
56 /* Mapper table, mnemonic --> opcode */
57 static const OPCDesc OPCTable[OPC_COUNT] = {
58 { OPC_ADC, "adc", 0, REG_A, REG_A, OF_NONE },
59 { OPC_AND, "and", 0, REG_A, REG_A, OF_NONE },
60 { OPC_ASL, "asl", 0, REG_A, REG_A, OF_NONE },
61 { OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA },
62 { OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA },
63 { OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA },
64 { OPC_BIT, "bit", 0, REG_A, REG_NONE, OF_NONE },
65 { OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA },
66 { OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA },
67 { OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA },
68 { OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA },
69 { OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE },
70 { OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA },
71 { OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA },
72 { OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE },
73 { OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE },
74 { OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE },
75 { OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE },
76 { OPC_CMP, "cmp", 0, REG_A, REG_NONE, OF_NONE },
77 { OPC_CPX, "cpx", 0, REG_X, REG_NONE, OF_NONE },
78 { OPC_CPY, "cpy", 0, REG_Y, REG_NONE, OF_NONE },
79 { OPC_DEA, "dea", 1, REG_A, REG_A, OF_NONE },
80 { OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE },
81 { OPC_DEX, "dex", 1, REG_X, REG_X, OF_NONE },
82 { OPC_DEY, "dey", 1, REG_Y, REG_Y, OF_NONE },
83 { OPC_EOR, "eor", 0, REG_A, REG_A, OF_NONE },
84 { OPC_INA, "ina", 1, REG_A, REG_A, OF_NONE },
85 { OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE },
86 { OPC_INX, "inx", 1, REG_X, REG_X, OF_NONE },
87 { OPC_INY, "iny", 1, REG_Y, REG_Y, OF_NONE },
88 { OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA },
89 { OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA },
90 { OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA },
91 { OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA },
92 { OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA },
93 { OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA },
94 { OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA },
95 { OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE },
96 { OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA },
97 { OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA },
98 { OPC_LDA, "lda", 0, REG_NONE, REG_A, OF_NONE },
99 { OPC_LDX, "ldx", 0, REG_NONE, REG_X, OF_NONE },
100 { OPC_LDY, "ldy", 0, REG_NONE, REG_Y, OF_NONE },
101 { OPC_LSR, "lsr", 0, REG_A, REG_A, OF_NONE },
102 { OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE },
103 { OPC_ORA, "ora", 0, REG_A, REG_A, OF_NONE },
104 { OPC_PHA, "pha", 1, REG_A, REG_NONE, OF_NONE },
105 { OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE },
106 { OPC_PHX, "phx", 1, REG_X, REG_NONE, OF_NONE },
107 { OPC_PHY, "phy", 1, REG_Y, REG_NONE, OF_NONE },
108 { OPC_PLA, "pla", 1, REG_NONE, REG_A, OF_NONE },
109 { OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE },
110 { OPC_PLX, "plx", 1, REG_NONE, REG_X, OF_NONE },
111 { OPC_PLY, "ply", 1, REG_NONE, REG_Y, OF_NONE },
112 { OPC_ROL, "rol", 0, REG_A, REG_A, OF_NONE },
113 { OPC_ROR, "ror", 0, REG_A, REG_A, OF_NONE },
114 { OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET },
115 { OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET },
116 { OPC_SBC, "sbc", 0, REG_A, REG_A, OF_NONE },
117 { OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE },
118 { OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE },
119 { OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE },
120 { OPC_STA, "sta", 0, REG_A, REG_NONE, OF_NONE },
121 { OPC_STX, "stx", 0, REG_X, REG_NONE, OF_NONE },
122 { OPC_STY, "sty", 0, REG_Y, REG_NONE, OF_NONE },
123 { OPC_TAX, "tax", 1, REG_A, REG_X, OF_NONE },
124 { OPC_TAY, "tay", 1, REG_A, REG_Y, OF_NONE },
125 { OPC_TRB, "trb", 0, REG_A, REG_NONE, OF_NONE },
126 { OPC_TSB, "tsb", 0, REG_A, REG_NONE, OF_NONE },
127 { OPC_TSX, "tsx", 1, REG_NONE, REG_X, OF_NONE },
128 { OPC_TXA, "txa", 1, REG_X, REG_A, OF_NONE },
129 { OPC_TXS, "txs", 1, REG_X, REG_NONE, OF_NONE },
130 { OPC_TYA, "tya", 1, REG_A, REG_A, OF_NONE },
135 /*****************************************************************************/
137 /*****************************************************************************/
141 static int Compare (const void* Key, const void* Desc)
142 /* Compare function for bsearch */
144 return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
149 const OPCDesc* FindOpcode (const char* M)
150 /* Find the given opcode and return the opcode number. If the opcode was not
151 * found, return OPC_INVALID.
157 /* Check the length of the given string, then copy it into local
158 * storage, converting it to upper case.
160 char Mnemo[sizeof (OPCTable[0].Mnemo)];
162 if (Len >= sizeof (OPCTable[0].Mnemo)) {
163 /* Invalid length means invalid opcode */
166 for (I = 0; I < Len; ++I) {
167 Mnemo[I] = tolower (M[I]);
171 /* Search for the mnemonic in the table and return the result */
172 return bsearch (Mnemo, OPCTable, OPC_COUNT, sizeof (OPCTable[0]), Compare);
177 unsigned GetInsnSize (opc_t OPC, am_t AM)
178 /* Return the size of the given instruction */
180 /* Get the opcode desc and check the size given there */
181 const OPCDesc* D = &OPCTable[OPC];
186 /* Check the addressing mode. */
188 case AM_IMP: return 1;
189 case AM_ACC: return 1;
190 case AM_IMM: return 2;
191 case AM_ZP: return 2;
192 case AM_ZPX: return 2;
193 case AM_ABS: return 3;
194 case AM_ABSX: return 3;
195 case AM_ABSY: return 3;
196 case AM_ZPX_IND: return 2;
197 case AM_ZP_INDY: return 2;
198 case AM_ZP_IND: return 2;
199 default: FAIL ("Invalid addressing mode");
205 const OPCDesc* GetOPCDesc (opc_t OPC)
206 /* Get an opcode description */
208 /* Check the range */
209 PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
211 /* Return the description */
212 return &OPCTable [OPC];
217 unsigned char GetOPCInfo (opc_t OPC)
218 /* Get opcode information */
220 /* Check the range */
221 PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
223 /* Return the info */
224 return OPCTable[OPC].Info;
229 unsigned char GetAMUseInfo (am_t AM)
230 /* Get usage info for the given addressing mode (addressing modes that use
231 * index registers return REG_r info for these registers).
234 /* Check the addressing mode. */
236 case AM_ACC: return REG_A;
237 case AM_ZPX: return REG_X;
238 case AM_ABSX: return REG_X;
239 case AM_ABSY: return REG_Y;
240 case AM_ZPX_IND: return REG_X;
241 case AM_ZP_INDY: return REG_Y;
242 default: return REG_NONE;
248 opc_t GetInverseBranch (opc_t OPC)
249 /* Return a branch that reverse the condition of the branch given in OPC */
252 case OPC_BCC: return OPC_BCS;
253 case OPC_BCS: return OPC_BCC;
254 case OPC_BEQ: return OPC_BNE;
255 case OPC_BMI: return OPC_BPL;
256 case OPC_BNE: return OPC_BEQ;
257 case OPC_BPL: return OPC_BMI;
258 case OPC_BVC: return OPC_BVS;
259 case OPC_BVS: return OPC_BVC;
260 case OPC_JCC: return OPC_JCS;
261 case OPC_JCS: return OPC_JCC;
262 case OPC_JEQ: return OPC_JNE;
263 case OPC_JMI: return OPC_JPL;
264 case OPC_JNE: return OPC_JEQ;
265 case OPC_JPL: return OPC_JMI;
266 case OPC_JVC: return OPC_JVS;
267 case OPC_JVS: return OPC_JVC;
268 default: Internal ("GetInverseBranch: Invalid opcode: %d", OPC);