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] = {
61 { OP65_ADC, "adc", 0, REG_A, REG_A, OF_NONE },
62 { OP65_AND, "and", 0, REG_A, REG_A, OF_NONE },
63 { OP65_ASL, "asl", 0, REG_A, REG_A, OF_NONE },
64 { OP65_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA },
65 { OP65_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA },
66 { OP65_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA | OF_FBRA },
67 { OP65_BIT, "bit", 0, REG_A, REG_NONE, OF_NONE },
68 { OP65_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA | OF_FBRA },
69 { OP65_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA | OF_FBRA },
70 { OP65_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA | OF_FBRA },
71 { OP65_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA },
72 { OP65_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE },
73 { OP65_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA },
74 { OP65_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA },
75 { OP65_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE },
76 { OP65_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE },
77 { OP65_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE },
78 { OP65_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE },
79 { OP65_CMP, "cmp", 0, REG_A, REG_NONE, OF_NONE },
80 { OP65_CPX, "cpx", 0, REG_X, REG_NONE, OF_NONE },
81 { OP65_CPY, "cpy", 0, REG_Y, REG_NONE, OF_NONE },
82 { OP65_DEA, "dea", 1, REG_A, REG_A, OF_NONE },
83 { OP65_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE },
84 { OP65_DEX, "dex", 1, REG_X, REG_X, OF_NONE },
85 { OP65_DEY, "dey", 1, REG_Y, REG_Y, OF_NONE },
86 { OP65_EOR, "eor", 0, REG_A, REG_A, OF_NONE },
87 { OP65_INA, "ina", 1, REG_A, REG_A, OF_NONE },
88 { OP65_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE },
89 { OP65_INX, "inx", 1, REG_X, REG_X, OF_NONE },
90 { OP65_INY, "iny", 1, REG_Y, REG_Y, OF_NONE },
91 { OP65_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
92 { OP65_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
93 { OP65_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA },
94 { OP65_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_FBRA },
95 { OP65_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA | OF_LBRA },
96 { OP65_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA },
97 { OP65_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_FBRA },
98 { OP65_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_CALL },
99 { OP65_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
100 { OP65_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
101 { OP65_LDA, "lda", 0, REG_NONE, REG_A, OF_LOAD },
102 { OP65_LDX, "ldx", 0, REG_NONE, REG_X, OF_LOAD },
103 { OP65_LDY, "ldy", 0, REG_NONE, REG_Y, OF_LOAD },
104 { OP65_LSR, "lsr", 0, REG_A, REG_A, OF_NONE },
105 { OP65_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE },
106 { OP65_ORA, "ora", 0, REG_A, REG_A, OF_NONE },
107 { OP65_PHA, "pha", 1, REG_A, REG_NONE, OF_NONE },
108 { OP65_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE },
109 { OP65_PHX, "phx", 1, REG_X, REG_NONE, OF_NONE },
110 { OP65_PHY, "phy", 1, REG_Y, REG_NONE, OF_NONE },
111 { OP65_PLA, "pla", 1, REG_NONE, REG_A, OF_NONE },
112 { OP65_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE },
113 { OP65_PLX, "plx", 1, REG_NONE, REG_X, OF_NONE },
114 { OP65_PLY, "ply", 1, REG_NONE, REG_Y, OF_NONE },
115 { OP65_ROL, "rol", 0, REG_A, REG_A, OF_NONE },
116 { OP65_ROR, "ror", 0, REG_A, REG_A, OF_NONE },
117 { OP65_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET },
118 { OP65_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET },
119 { OP65_SBC, "sbc", 0, REG_A, REG_A, OF_NONE },
120 { OP65_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE },
121 { OP65_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE },
122 { OP65_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE },
123 { OP65_STA, "sta", 0, REG_A, REG_NONE, OF_NONE },
124 { OP65_STX, "stx", 0, REG_X, REG_NONE, OF_NONE },
125 { OP65_STY, "sty", 0, REG_Y, REG_NONE, OF_NONE },
126 { OP65_TAX, "tax", 1, REG_A, REG_X, OF_XFR },
127 { OP65_TAY, "tay", 1, REG_A, REG_Y, OF_XFR },
128 { OP65_TRB, "trb", 0, REG_A, REG_NONE, OF_NONE },
129 { OP65_TSB, "tsb", 0, REG_A, REG_NONE, OF_NONE },
130 { OP65_TSX, "tsx", 1, REG_NONE, REG_X, OF_XFR },
131 { OP65_TXA, "txa", 1, REG_X, REG_A, OF_XFR },
132 { OP65_TXS, "txs", 1, REG_X, REG_NONE, OF_XFR },
133 { OP65_TYA, "tya", 1, REG_A, REG_A, OF_XFR },
138 /*****************************************************************************/
140 /*****************************************************************************/
144 static int Compare (const void* Key, const void* Desc)
145 /* Compare function for bsearch */
147 return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
152 const OPCDesc* FindOpcode (const char* M)
153 /* Find the given opcode and return the opcode number. If the opcode was not
154 * found, return OP65_INVALID.
160 /* Check the length of the given string, then copy it into local
161 * storage, converting it to upper case.
163 char Mnemo[sizeof (OPCTable[0].Mnemo)];
165 if (Len >= sizeof (OPCTable[0].Mnemo)) {
166 /* Invalid length means invalid opcode */
169 for (I = 0; I < Len; ++I) {
170 Mnemo[I] = tolower (M[I]);
174 /* Search for the mnemonic in the table and return the result */
175 return bsearch (Mnemo, OPCTable, OPCODE_COUNT, sizeof (OPCTable[0]), Compare);
180 unsigned GetInsnSize (opc_t OPC, am_t AM)
181 /* Return the size of the given instruction */
183 /* Get the opcode desc and check the size given there */
184 const OPCDesc* D = &OPCTable[OPC];
189 /* Check the addressing mode. */
191 case AM65_IMP: return 1;
192 case AM65_ACC: return 1;
193 case AM65_IMM: return 2;
194 case AM65_ZP: return 2;
195 case AM65_ZPX: return 2;
196 case AM65_ABS: return 3;
197 case AM65_ABSX: return 3;
198 case AM65_ABSY: return 3;
199 case AM65_ZPX_IND: return 2;
200 case AM65_ZP_INDY: return 2;
201 case AM65_ZP_IND: return 2;
203 Internal ("Invalid addressing mode");
210 unsigned char GetAMUseInfo (am_t AM)
211 /* Get usage info for the given addressing mode (addressing modes that use
212 * index registers return REG_r info for these registers).
215 /* Check the addressing mode. */
217 case AM65_ACC: return REG_A;
218 case AM65_ZPX: return REG_X;
219 case AM65_ABSX: return REG_X;
220 case AM65_ABSY: return REG_Y;
221 case AM65_ZPX_IND: return REG_X;
222 case AM65_ZP_INDY: return REG_Y;
223 default: return REG_NONE;
229 opc_t GetInverseBranch (opc_t OPC)
230 /* Return a branch that reverse the condition of the branch given in OPC */
233 case OP65_BCC: return OP65_BCS;
234 case OP65_BCS: return OP65_BCC;
235 case OP65_BEQ: return OP65_BNE;
236 case OP65_BMI: return OP65_BPL;
237 case OP65_BNE: return OP65_BEQ;
238 case OP65_BPL: return OP65_BMI;
239 case OP65_BVC: return OP65_BVS;
240 case OP65_BVS: return OP65_BVC;
241 case OP65_JCC: return OP65_JCS;
242 case OP65_JCS: return OP65_JCC;
243 case OP65_JEQ: return OP65_JNE;
244 case OP65_JMI: return OP65_JPL;
245 case OP65_JNE: return OP65_JEQ;
246 case OP65_JPL: return OP65_JMI;
247 case OP65_JVC: return OP65_JVS;
248 case OP65_JVS: return OP65_JVC;
250 Internal ("GetInverseBranch: Invalid opcode: %d", OPC);
257 opc_t MakeShortBranch (opc_t OPC)
258 /* Return the short version of the given branch. If the branch is already
259 * a short branch, return the opcode unchanged.
264 case OP65_JCC: return OP65_BCC;
266 case OP65_JCS: return OP65_BCS;
268 case OP65_JEQ: return OP65_BEQ;
270 case OP65_JMI: return OP65_BMI;
272 case OP65_JNE: return OP65_BNE;
274 case OP65_JPL: return OP65_BPL;
276 case OP65_JVC: return OP65_BVC;
278 case OP65_JVS: return OP65_BVS;
280 case OP65_JMP: return (CPU == CPU_65C02)? OP65_BRA : OP65_JMP;
282 Internal ("MakeShortBranch: Invalid opcode: %d", OPC);
289 opc_t MakeLongBranch (opc_t OPC)
290 /* Return the long version of the given branch. If the branch is already
291 * a long branch, return the opcode unchanged.
296 case OP65_JCC: return OP65_JCC;
298 case OP65_JCS: return OP65_JCS;
300 case OP65_JEQ: return OP65_JEQ;
302 case OP65_JMI: return OP65_JMI;
304 case OP65_JNE: return OP65_JNE;
306 case OP65_JPL: return OP65_JPL;
308 case OP65_JVC: return OP65_JVC;
310 case OP65_JVS: return OP65_JVS;
312 case OP65_JMP: return OP65_JMP;
314 Internal ("MakeLongBranch: Invalid opcode: %d", OPC);
321 bc_t GetBranchCond (opc_t OPC)
322 /* Get the condition for the conditional branch in OPC */
325 case OP65_BCC: return BC_CC;
326 case OP65_BCS: return BC_CS;
327 case OP65_BEQ: return BC_EQ;
328 case OP65_BMI: return BC_MI;
329 case OP65_BNE: return BC_NE;
330 case OP65_BPL: return BC_PL;
331 case OP65_BVC: return BC_VC;
332 case OP65_BVS: return BC_VS;
333 case OP65_JCC: return BC_CC;
334 case OP65_JCS: return BC_CS;
335 case OP65_JEQ: return BC_EQ;
336 case OP65_JMI: return BC_MI;
337 case OP65_JNE: return BC_NE;
338 case OP65_JPL: return BC_PL;
339 case OP65_JVC: return BC_VC;
340 case OP65_JVS: return BC_VS;
342 Internal ("GetBranchCond: Invalid opcode: %d", OPC);
349 bc_t GetInverseCond (bc_t BC)
350 /* Return the inverse condition of the given one */
353 case BC_CC: return BC_CS;
354 case BC_CS: return BC_CC;
355 case BC_EQ: return BC_NE;
356 case BC_MI: return BC_PL;
357 case BC_NE: return BC_EQ;
358 case BC_PL: return BC_MI;
359 case BC_VC: return BC_VS;
360 case BC_VS: return BC_VC;
362 Internal ("GetInverseCond: Invalid condition: %d", BC);