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 /*****************************************************************************/
52 /*****************************************************************************/
54 /*****************************************************************************/
58 /* Mapper table, mnemonic --> opcode */
59 static const OPCDesc OPCTable[OPC_COUNT] = {
60 { "adc", OPC_ADC, 0, CI_USE_A | CI_CHG_A },
61 { "and", OPC_AND, 0, CI_USE_A | CI_CHG_A },
62 { "asl", OPC_ASL, 0, CI_USE_A | CI_CHG_A },
63 { "bcc", OPC_BCC, 2, CI_BRA },
64 { "bcs", OPC_BCS, 2, CI_BRA },
65 { "beq", OPC_BEQ, 2, CI_BRA },
66 { "bit", OPC_BIT, 0, CI_USE_A },
67 { "bmi", OPC_BMI, 2, CI_BRA },
68 { "bne", OPC_BNE, 2, CI_BRA },
69 { "bpl", OPC_BPL, 2, CI_BRA },
70 { "bra", OPC_BRA, 2, CI_BRA },
71 { "brk", OPC_BRK, 1, CI_NONE },
72 { "bvc", OPC_BVC, 2, CI_BRA },
73 { "bvs", OPC_BVS, 2, CI_BRA },
74 { "clc", OPC_CLC, 1, CI_CHG_NONE },
75 { "cld", OPC_CLD, 1, CI_CHG_NONE },
76 { "cli", OPC_CLI, 1, CI_CHG_NONE },
77 { "clv", OPC_CLV, 1, CI_CHG_NONE },
78 { "cmp", OPC_CMP, 0, CI_USE_A },
79 { "cpx", OPC_CPX, 0, CI_USE_X },
80 { "cpy", OPC_CPY, 0, CI_USE_Y },
81 { "dea", OPC_DEA, 1, CI_USE_A | CI_CHG_A },
82 { "dec", OPC_DEC, 0, CI_NONE },
83 { "dex", OPC_DEX, 1, CI_USE_X | CI_CHG_X },
84 { "dey", OPC_DEY, 1, CI_USE_Y | CI_CHG_Y },
85 { "eor", OPC_EOR, 0, CI_USE_A | CI_CHG_A },
86 { "ina", OPC_INA, 1, CI_USE_A | CI_CHG_A },
87 { "inc", OPC_INC, 0, CI_NONE },
88 { "inx", OPC_INX, 1, CI_USE_X | CI_CHG_X },
89 { "iny", OPC_INY, 1, CI_USE_Y | CI_CHG_Y },
90 { "jcc", OPC_JCC, 5, CI_BRA },
91 { "jcs", OPC_JCS, 5, CI_BRA },
92 { "jeq", OPC_JEQ, 5, CI_BRA },
93 { "jmi", OPC_JMI, 5, CI_BRA },
94 { "jmp", OPC_JMP, 3, CI_BRA },
95 { "jne", OPC_JNE, 5, CI_BRA },
96 { "jpl", OPC_JPL, 5, CI_BRA },
97 { "jsr", OPC_JSR, 3, CI_NONE },
98 { "jvc", OPC_JVC, 5, CI_BRA },
99 { "jvs", OPC_JVS, 5, CI_BRA },
100 { "lda", OPC_LDA, 0, CI_CHG_A },
101 { "ldx", OPC_LDX, 0, CI_CHG_X },
102 { "ldy", OPC_LDY, 0, CI_CHG_Y },
103 { "lsr", OPC_LSR, 0, CI_USE_A | CI_CHG_A },
104 { "nop", OPC_NOP, 1, CI_NONE },
105 { "ora", OPC_ORA, 0, CI_USE_A | CI_CHG_A },
106 { "pha", OPC_PHA, 1, CI_USE_A },
107 { "php", OPC_PHP, 1, CI_NONE },
108 { "phx", OPC_PHX, 1, CI_USE_X },
109 { "phy", OPC_PHY, 1, CI_USE_Y },
110 { "pla", OPC_PLA, 1, CI_CHG_A },
111 { "plp", OPC_PLP, 1, CI_NONE },
112 { "plx", OPC_PLX, 1, CI_CHG_X },
113 { "ply", OPC_PLY, 1, CI_CHG_Y },
114 { "rol", OPC_ROL, 0, CI_USE_A | CI_CHG_A },
115 { "ror", OPC_ROR, 0, CI_USE_A | CI_CHG_A },
116 { "rti", OPC_RTI, 1, CI_NONE },
117 { "rts", OPC_RTS, 1, CI_NONE },
118 { "sbc", OPC_SBC, 0, CI_USE_A | CI_CHG_A },
119 { "sec", OPC_SEC, 1, CI_NONE },
120 { "sed", OPC_SED, 1, CI_NONE },
121 { "sei", OPC_SEI, 1, CI_NONE },
122 { "sta", OPC_STA, 0, CI_USE_A },
123 { "stx", OPC_STX, 0, CI_USE_X },
124 { "sty", OPC_STY, 0, CI_USE_Y },
125 { "tax", OPC_TAX, 1, CI_USE_A | CI_CHG_X },
126 { "tay", OPC_TAY, 1, CI_USE_A | CI_CHG_Y },
127 { "trb", OPC_TRB, 0, CI_USE_A },
128 { "tsb", OPC_TSB, 0, CI_USE_A },
129 { "tsx", OPC_TSX, 1, CI_CHG_X },
130 { "txa", OPC_TXA, 1, CI_USE_X | CI_CHG_A },
131 { "txs", OPC_TXS, 1, CI_USE_X },
132 { "tya", OPC_TYA, 1, CI_USE_Y | CI_CHG_A }
137 /*****************************************************************************/
139 /*****************************************************************************/
143 static int Compare (const void* Key, const void* Desc)
144 /* Compare function for bsearch */
146 return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
151 const OPCDesc* FindOpcode (const char* M)
152 /* Find the given opcode and return the opcode number. If the opcode was not
153 * found, return OPC_INVALID.
159 /* Check the length of the given string, then copy it into local
160 * storage, converting it to upper case.
162 char Mnemo[sizeof (OPCTable[0].Mnemo)];
164 if (Len >= sizeof (OPCTable[0].Mnemo)) {
165 /* Invalid length means invalid opcode */
168 for (I = 0; I < Len; ++I) {
169 Mnemo[I] = tolower (M[I]);
173 /* Search for the mnemonic in the table and return the result */
174 return bsearch (Mnemo, OPCTable, OPC_COUNT, sizeof (OPCTable[0]), Compare);
179 unsigned GetInsnSize (opc_t OPC, am_t AM)
180 /* Return the size of the given instruction */
182 /* Get the opcode desc and check the size given there */
183 const OPCDesc* D = &OPCTable[OPC];
188 /* Check the addressing mode. */
190 case AM_IMP: return 1;
191 case AM_ACC: return 1;
192 case AM_IMM: return 2;
193 case AM_ZP: return 2;
194 case AM_ZPX: return 2;
195 case AM_ABS: return 3;
196 case AM_ABSX: return 3;
197 case AM_ABSY: return 3;
198 case AM_ZPX_IND: return 2;
199 case AM_ZP_INDY: return 2;
200 case AM_ZP_IND: return 2;
201 default: FAIL ("Invalid addressing mode");
207 const OPCDesc* GetOPCDesc (opc_t OPC)
208 /* Get an opcode description */
210 /* Check the range */
211 PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
213 /* Return the description */
214 return &OPCTable [OPC];
219 unsigned GetAMUseInfo (am_t AM)
220 /* Get usage info for the given addressing mode (addressing modes that use
221 * index registers return CI_USE... info for these registers).
224 /* Check the addressing mode. */
226 case AM_ACC: return CI_USE_A;
227 case AM_ZPX: return CI_USE_X;
228 case AM_ABSX: return CI_USE_X;
229 case AM_ABSY: return CI_USE_Y;
230 case AM_ZPX_IND: return CI_USE_X;
231 case AM_ZP_INDY: return CI_USE_Y;
232 default: return CI_USE_NONE;
238 opc_t GetInverseBranch (opc_t OPC)
239 /* Return a brahcn that reverse the condition of the branch given in OPC */
242 case OPC_BCC: return OPC_BCS;
243 case OPC_BCS: return OPC_BCC;
244 case OPC_BEQ: return OPC_BNE;
245 case OPC_BMI: return OPC_BPL;
246 case OPC_BNE: return OPC_BEQ;
247 case OPC_BPL: return OPC_BMI;
248 case OPC_BVC: return OPC_BVS;
249 case OPC_BVS: return OPC_BVC;
250 case OPC_JCC: return OPC_JCS;
251 case OPC_JCS: return OPC_JCC;
252 case OPC_JEQ: return OPC_JNE;
253 case OPC_JMI: return OPC_JPL;
254 case OPC_JNE: return OPC_JEQ;
255 case OPC_JPL: return OPC_JMI;
256 case OPC_JVC: return OPC_JVS;
257 case OPC_JVS: return OPC_JVC;
258 default: Internal ("GetInverseBranch: Invalid opcode: %d", OPC);