]> git.sur5r.net Git - cc65/blob - src/cc65/opcodes.c
Working on the backend
[cc65] / src / cc65 / opcodes.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 opcodes.c                                 */
4 /*                                                                           */
5 /*                  Opcode and addressing mode definitions                   */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2001     Ullrich von Bassewitz                                        */
10 /*              Wacholderweg 14                                              */
11 /*              D-70597 Stuttgart                                            */
12 /* EMail:       uz@musoftware.de                                             */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include "stdlib.h"
37 #include <string.h>
38 #include <ctype.h>
39
40 /* common */
41 #include "check.h"
42
43 /* cc65 */
44 #include "codeinfo.h"
45 #include "opcodes.h"
46
47
48
49 /*****************************************************************************/
50 /*                                   Data                                    */
51 /*****************************************************************************/
52
53
54
55 /* Mapper table, mnemonic --> opcode */
56 static const OPCDesc OPCTable[OPC_COUNT] = {
57     { "adc", OPC_ADC, CI_USE_A | CI_CHG_A       },
58     { "and", OPC_AND, CI_USE_A | CI_CHG_A       },
59     { "asl", OPC_ASL, CI_USE_A | CI_CHG_A       },
60     { "bcc", OPC_BCC, CI_CHG_NONE               },
61     { "bcs", OPC_BCS, CI_CHG_NONE               },
62     { "beq", OPC_BEQ, CI_CHG_NONE               },
63     { "bit", OPC_BIT, CI_USE_A                  },
64     { "bmi", OPC_BMI, CI_CHG_NONE               },
65     { "bne", OPC_BNE, CI_CHG_NONE               },
66     { "bpl", OPC_BPL, CI_CHG_NONE               },
67     { "bra", OPC_BRA, CI_CHG_NONE               },
68     { "brk", OPC_BRK, CI_CHG_NONE               },
69     { "bvc", OPC_BVC, CI_CHG_NONE               },
70     { "bvs", OPC_BVS, CI_CHG_NONE               },
71     { "clc", OPC_CLC, CI_CHG_NONE               },
72     { "cld", OPC_CLD, CI_CHG_NONE               },
73     { "cli", OPC_CLI, CI_CHG_NONE               },
74     { "clv", OPC_CLV, CI_CHG_NONE               },
75     { "cmp", OPC_CMP, CI_USE_A                  },
76     { "cpx", OPC_CPX, CI_USE_X                  },
77     { "cpy", OPC_CPY, CI_USE_Y                  },
78     { "dea", OPC_DEA, CI_USE_A | CI_CHG_A       },
79     { "dec", OPC_DEC, CI_NONE                   },
80     { "dex", OPC_DEX, CI_USE_X | CI_CHG_X       },
81     { "dey", OPC_DEY, CI_USE_Y | CI_CHG_Y       },
82     { "eor", OPC_EOR, CI_USE_A | CI_CHG_A       },
83     { "ina", OPC_INA, CI_USE_A | CI_CHG_A       },
84     { "inc", OPC_INC, CI_NONE                   },
85     { "inx", OPC_INX, CI_USE_X | CI_CHG_X       },
86     { "iny", OPC_INY, CI_USE_Y | CI_CHG_Y       },
87     { "jmp", OPC_JMP, CI_NONE                   },
88     { "jsr", OPC_JSR, CI_NONE                   },
89     { "lda", OPC_LDA, CI_CHG_A                  },
90     { "ldx", OPC_LDX, CI_CHG_X                  },
91     { "ldy", OPC_LDY, CI_CHG_Y                  },
92     { "lsr", OPC_LSR, CI_USE_A | CI_CHG_A       },
93     { "nop", OPC_NOP, CI_NONE                   },
94     { "ora", OPC_ORA, CI_USE_A | CI_CHG_A       },
95     { "pha", OPC_PHA, CI_USE_A                  },
96     { "php", OPC_PHP, CI_NONE                   },
97     { "phx", OPC_PHX, CI_USE_X                  },
98     { "phy", OPC_PHY, CI_USE_Y                  },
99     { "pla", OPC_PLA, CI_CHG_A                  },
100     { "plp", OPC_PLP, CI_NONE                   },
101     { "plx", OPC_PLX, CI_CHG_X                  },
102     { "ply", OPC_PLY, CI_CHG_Y                  },
103     { "rol", OPC_ROL, CI_USE_A | CI_CHG_A       },
104     { "ror", OPC_ROR, CI_USE_A | CI_CHG_A       },
105     { "rti", OPC_RTI, CI_NONE                   },
106     { "rts", OPC_RTS, CI_NONE                   },
107     { "sbc", OPC_SBC, CI_USE_A | CI_CHG_A       },
108     { "sec", OPC_SEC, CI_NONE                   },
109     { "sed", OPC_SED, CI_NONE                   },
110     { "sei", OPC_SEI, CI_NONE                   },
111     { "sta", OPC_STA, CI_USE_A                  },
112     { "stx", OPC_STX, CI_USE_X                  },
113     { "sty", OPC_STY, CI_USE_Y                  },
114     { "tax", OPC_TAX, CI_USE_A | CI_CHG_X       },
115     { "tay", OPC_TAY, CI_USE_A | CI_CHG_Y       },
116     { "trb", OPC_TRB, CI_USE_A                  },
117     { "tsb", OPC_TSB, CI_USE_A                  },
118     { "tsx", OPC_TSX, CI_CHG_X                  },
119     { "txa", OPC_TXA, CI_USE_X | CI_CHG_A       },
120     { "txs", OPC_TXS, CI_USE_X                  },
121     { "tya", OPC_TYA, CI_USE_Y | CI_CHG_A       }
122 };
123
124
125
126 /*****************************************************************************/
127 /*                                   Code                                    */
128 /*****************************************************************************/
129
130
131
132 static int Compare (const void* Key, const void* Desc)
133 /* Compare function for bsearch */
134 {
135     return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
136 }
137
138
139
140 const OPCDesc* FindOpcode (const char* M)
141 /* Find the given opcode and return the opcode number. If the opcode was not
142  * found, return OPC_INVALID.
143  */
144 {
145     unsigned I;
146     unsigned Len;
147
148     /* Check the length of the given string, then copy it into local
149      * storage, converting it to upper case.
150      */
151     char Mnemo[sizeof (OPCTable[0].Mnemo)];
152     Len = strlen (M);
153     if (Len >= sizeof (OPCTable[0].Mnemo)) {
154         /* Invalid length means invalid opcode */
155         return 0;
156     }
157     for (I = 0; I < Len; ++I) {
158         Mnemo[I] = tolower (M[I]);
159     }
160     Mnemo[I] = '\0';
161
162     /* Search for the mnemonic in the table and return the result */
163     return bsearch (Mnemo, OPCTable, OPC_COUNT, sizeof (OPCTable[0]), Compare);
164 }
165
166
167
168 unsigned GetInsnSize (opc_t OPC, am_t AM)
169 /* Return the size of the given instruction */
170 {
171     /* On the 6502 (and 65C02), the instruction size is determined only by the
172      * addressing mode.
173      */
174     switch (AM) {
175         case AM_IMP:      return 1;
176         case AM_IMM:      return 2;
177         case AM_ZP:       return 2;
178         case AM_ZPX:      return 2;
179         case AM_ABS:      return 3;
180         case AM_ABSX:     return 3;
181         case AM_ABSY:     return 3;
182         case AM_ZPX_IND:  return 2;
183         case AM_ZP_INDY:  return 2;
184         case AM_ZP_IND:   return 2;
185         case AM_BRA:      return 2;
186         default:          FAIL ("Invalid addressing mode");
187     }
188 }
189
190
191
192 const OPCDesc* GetOPCDesc (opc_t OPC)
193 /* Get an opcode description */
194 {
195     /* Check the range */
196     PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
197
198     /* Return the description */
199     return &OPCTable [OPC];
200 }
201
202
203
204