1 /*
2 * HT Editor
3 * ppcopc.cc
4 *
5 * Copyright (C) 1999-2003 Sebastian Biallas (sb@biallas.net)
6 * Copyright 1994 Free Software Foundation, Inc.
7 * Written by Ian Lance Taylor, Cygnus Support
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include <cstdio>
24 #include "avropc.h"
25
extract_rr(uint32 insn,bool * invalid)26 static uint32 extract_rr(uint32 insn, bool *invalid)
27 {
28 return (insn & 0xf) | ((insn >> 5) & 0x10);
29 }
30
extract_rrd(uint32 insn,bool * invalid)31 static uint32 extract_rrd(uint32 insn, bool *invalid)
32 {
33 uint32 d = (insn >> 4) & 0x1f;
34 uint32 r = (insn & 0xf) | ((insn >> 5) & 0x10);
35 *invalid = r != d;
36 return 0;
37 }
38
extract_q(uint32 insn,bool * invalid)39 static uint32 extract_q(uint32 insn, bool *invalid)
40 {
41 return ((insn >> 8) & 0x20)
42 | ((insn >> 7) & 0x18)
43 | (insn & 0x7);
44 }
45
extract_k6(uint32 insn,bool * invalid)46 static uint32 extract_k6(uint32 insn, bool *invalid)
47 {
48 return (insn & 0xf) | ((insn >> 2) & 0x30);
49 }
50
extract_k8(uint32 insn,bool * invalid)51 static uint32 extract_k8(uint32 insn, bool *invalid)
52 {
53 return (insn & 0xf) | ((insn >> 4) & 0xf0);
54 }
55
extract_k16(uint32 insn,bool * invalid)56 static uint32 extract_k16(uint32 insn, bool *invalid)
57 {
58 return insn >> 16;
59 }
60
extract_rel22(uint32 insn,bool * invalid)61 static uint32 extract_rel22(uint32 insn, bool *invalid)
62 {
63 return (((insn << 12) & 0x003e0000)
64 | ((insn & 1) << 16)
65 | (insn >> 16)) << 1;
66 }
67
extract_a6(uint32 insn,bool * invalid)68 static uint32 extract_a6(uint32 insn, bool *invalid)
69 {
70 return (insn & 0xf) | ((insn >> 5) & 0x30);
71 }
72
73 #undef UNUSED
74
75 const struct avr_operand avr_operands[] =
76 {
77 /* The zero index is used to indicate the end of the list of
78 operands. */
79
80 // bit, shr, add, scale, extract
81
82 #define UNUSED 0
83 { 0, 0, 0, 0 },
84
85 #define Rd UNUSED + 1
86 { 5, 4, 0, 0, 0, AVR_OPERAND_GPR },
87
88 #define Rd16 Rd + 1
89 { 4, 4, 16, 0, 0, AVR_OPERAND_GPR },
90
91 #define Rd23 Rd16 + 1
92 { 3, 4, 16, 0, 0, AVR_OPERAND_GPR },
93
94 #define RdW Rd23 + 1
95 { 4, 4, 0, 1, 0, AVR_OPERAND_GPR_2 },
96
97 #define RdW24 RdW + 1
98 { 2, 4, 24, 1, 0, AVR_OPERAND_GPR_2 },
99
100 #define Rr RdW24 + 1
101 { 5, 0, 0, 0, extract_rr, AVR_OPERAND_GPR },
102
103 #define Rr16 Rr + 1
104 { 4, 0, 16, 0, 0, AVR_OPERAND_GPR },
105
106 #define Rr23 Rr16 + 1
107 { 3, 0, 16, 0, 0, AVR_OPERAND_GPR },
108
109 #define RrW Rr23 + 1
110 { 4, 0, 0, 1, 0, AVR_OPERAND_GPR_2 },
111
112 #define Rrd RrW + 1
113 { 5, 0, 0, 0, extract_rrd, AVR_OPERAND_FAKE },
114
115 #define K6 Rrd + 1
116 { 6, 0, 0, 0, extract_k6, AVR_OPERAND_IMM },
117
118 #define K8 K6 + 1
119 { 8, 0, 0, 0, extract_k8, AVR_OPERAND_IMM },
120
121 #define k16 K8 + 1
122 { 16, 0, 0, 0, extract_k16, AVR_OPERAND_IMM },
123
124 #define b3 k16 + 1
125 { 3, 0, 0, 0, 0, AVR_OPERAND_IMM },
126
127 #define A5 b3 + 1
128 { 5, 3, 0, 0, 0, AVR_OPERAND_IMM },
129
130 #define A6 A5 + 1
131 { 6, 0, 0, 0, extract_a6, AVR_OPERAND_IMM },
132
133 #define Rel7 A6 + 1
134 { 7, 3, 0, 1, 0, AVR_OPERAND_REL | AVR_OPERAND_SIGNED },
135
136 #define Rel12 Rel7 + 1
137 { 12, 0, 0, 1, 0, AVR_OPERAND_REL | AVR_OPERAND_SIGNED },
138
139 #define Rel22 Rel12 + 1
140 { 22, 0, 0, 0, extract_rel22, AVR_OPERAND_ABS },
141
142 #define X Rel22 + 1
143 { 0, 0, 0, 0, 0, AVR_OPERAND_X },
144 #define XP X + 1
145 { 0, 0, 0, 0, 0, AVR_OPERAND_XP },
146 #define XM XP + 1
147 { 0, 0, 0, 0, 0, AVR_OPERAND_XM },
148
149 #define Y XM + 1
150 { 0, 0, 0, 0, 0, AVR_OPERAND_Y },
151 #define YP Y + 1
152 { 0, 0, 0, 0, 0, AVR_OPERAND_YP },
153 #define YM YP + 1
154 { 0, 0, 0, 0, 0, AVR_OPERAND_YM },
155 #define Yq YM + 1
156 { 6, 0, 0, 0, extract_q, AVR_OPERAND_Yq },
157
158 #define Z Yq + 1
159 { 0, 0, 0, 0, 0, AVR_OPERAND_Z },
160 #define ZP Z + 1
161 { 0, 0, 0, 0, 0, AVR_OPERAND_ZP },
162 #define ZM ZP + 1
163 { 0, 0, 0, 0, 0, AVR_OPERAND_ZM },
164 #define Zq ZM + 1
165 { 6, 0, 0, 0, extract_q, AVR_OPERAND_Zq },
166
167 };
168
169
170 #define OP_MASK 0xffff
171 #define OP_1MASK 0xf000
172 #define OP_2MASK 0xfc00
173 #define OP_3MASK 0xff00
174 #define OP_4MASK 0xff88
175 #define OP_5MASK 0xfe08
176 #define OP_6MASK 0xfe0f
177 #define OP_7MASK 0xfc07
178 #define OP_8MASK 0xff0f
179 #define OP_9MASK 0xd208
180 #define OP_10MASK 0xf800
181 #define OP_11MASK 0xfe0e
182
183 const struct avr_opcode avr_opcodes[] = {
184 { "nop", OP_MASK, 0x0000, {0} },
185
186 { "muls", OP_3MASK, 0x0200, {Rd16, Rr16} },
187 { "mulsu", OP_4MASK, 0x0300, {Rd23, Rr23} },
188
189 { "movw", OP_3MASK, 0x0100, {RdW, RrW} },
190
191 { "cpi", OP_1MASK, 0x3000, {Rd16, K8} },
192 { "sbci", OP_1MASK, 0x4000, {Rd16, K8} },
193 { "subi", OP_1MASK, 0x5000, {Rd16, K8} },
194 { "ori", OP_1MASK, 0x6000, {Rd16, K8} },
195 { "andi", OP_1MASK, 0x7000, {Rd16, K8} },
196 { "ldi", OP_1MASK, 0xe000, {Rd16, K8} },
197
198 { "rjmp", OP_1MASK, 0xc000, {Rel12} },
199 { "rcall", OP_1MASK, 0xd000, {Rel12} },
200
201 { "clr", OP_2MASK, 0x2400, {Rd, Rrd} },
202 { "lsl", OP_2MASK, 0x0c00, {Rd, Rrd} },
203 { "rol", OP_2MASK, 0x1c00, {Rd, Rrd} },
204 { "tst", OP_2MASK, 0x2000, {Rd, Rrd} },
205
206 { "adc", OP_2MASK, 0x1c00, {Rd, Rr} },
207 { "add", OP_2MASK, 0x0c00, {Rd, Rr} },
208 { "and", OP_2MASK, 0x2000, {Rd, Rr} },
209 { "cp", OP_2MASK, 0x1400, {Rd, Rr} },
210 { "cpc", OP_2MASK, 0x0400, {Rd, Rr} },
211 { "cpse", OP_2MASK, 0x1000, {Rd, Rr} },
212 { "eor", OP_2MASK, 0x2400, {Rd, Rr} },
213 { "mov", OP_2MASK, 0x2c00, {Rd, Rr} },
214 { "mul", OP_2MASK, 0x9c00, {Rd, Rr} },
215 { "or", OP_2MASK, 0x2800, {Rd, Rr} },
216 { "sbc", OP_2MASK, 0x0800, {Rd, Rr} },
217 { "sub", OP_2MASK, 0x1800, {Rd, Rr} },
218
219 { "break", OP_MASK, 0x9594, {0} },
220 { "clc", OP_MASK, 0x9488, {0} },
221 { "clh", OP_MASK, 0x94d8, {0} },
222 { "cli", OP_MASK, 0x94f8, {0} },
223 { "cln", OP_MASK, 0x94a8, {0} },
224 { "cls", OP_MASK, 0x94c8, {0} },
225 { "clt", OP_MASK, 0x94e8, {0} },
226 { "clv", OP_MASK, 0x94b8, {0} },
227 { "clz", OP_MASK, 0x9498, {0} },
228 { "eicall", OP_MASK, 0x9519, {0} },
229 { "eijmp", OP_MASK, 0x9419, {0} },
230 { "icall", OP_MASK, 0x9509, {0} },
231 { "ijmp", OP_MASK, 0x9409, {0} },
232 { "ret", OP_MASK, 0x9508, {0} },
233 { "reti", OP_MASK, 0x9518, {0} },
234 { "sec", OP_MASK, 0x9408, {0} },
235 { "seh", OP_MASK, 0x9458, {0} },
236 { "sei", OP_MASK, 0x9478, {0} },
237 { "sen", OP_MASK, 0x9428, {0} },
238 { "ses", OP_MASK, 0x9448, {0} },
239 { "set", OP_MASK, 0x9468, {0} },
240 { "sev", OP_MASK, 0x9438, {0} },
241 { "sez", OP_MASK, 0x9418, {0} },
242 { "sleep", OP_MASK, 0x9588, {0} },
243 { "wdr", OP_MASK, 0x95a8, {0} },
244
245 { "spm", OP_MASK, 0x95e8, {ZP} },
246
247 { "elpm", OP_MASK, 0x95d8, {0} },
248 { "elpm", OP_6MASK, 0x9006, {Rd, Z} },
249 { "elpm", OP_6MASK, 0x9007, {Rd, ZP} },
250 { "lpm", OP_MASK, 0x95c8, {0} },
251 { "lpm", OP_6MASK, 0x9004, {Rd, Z} },
252 { "lpm", OP_6MASK, 0x9005, {Rd, ZP} },
253 { "ld", OP_6MASK, 0x900c, {Rd, X} },
254 { "ld", OP_6MASK, 0x900d, {Rd, XP} },
255 { "ld", OP_6MASK, 0x900e, {Rd, XM} },
256 { "ld", OP_6MASK, 0x8008, {Rd, Y} },
257 { "ldd", OP_9MASK, 0x8008, {Rd, Yq} },
258 { "ld", OP_6MASK, 0x9009, {Rd, YP} },
259 { "ld", OP_6MASK, 0x900a, {Rd, YM} },
260 { "ld", OP_6MASK, 0x8000, {Rd, Z} },
261 { "ldd", OP_9MASK, 0x8000, {Rd, Zq} },
262 { "ld", OP_6MASK, 0x9001, {Rd, ZP} },
263 { "ld", OP_6MASK, 0x9002, {Rd, ZM} },
264
265 { "st", OP_6MASK, 0x920c, {X, Rd} },
266 { "st", OP_6MASK, 0x920d, {XP, Rd} },
267 { "st", OP_6MASK, 0x920e, {XM, Rd} },
268 { "st", OP_6MASK, 0x8208, {Y, Rd} },
269 { "std", OP_9MASK, 0x8208, {Yq, Rd} },
270 { "st", OP_6MASK, 0x9209, {YP, Rd} },
271 { "st", OP_6MASK, 0x920a, {YM, Rd} },
272 { "st", OP_6MASK, 0x8200, {Z, Rd} },
273 { "std", OP_9MASK, 0x8200, {Zq, Rd} },
274 { "st", OP_6MASK, 0x9201, {ZP, Rd} },
275 { "st", OP_6MASK, 0x9202, {ZM, Rd} },
276
277
278 { "adiw", OP_3MASK, 0x9600, {RdW24, K6} },
279 { "sbiw", OP_3MASK, 0x9700, {RdW24, K6} },
280
281 { "asr", OP_6MASK, 0x9405, {Rd} },
282 { "com", OP_6MASK, 0x9400, {Rd} },
283 { "dec", OP_6MASK, 0x940a, {Rd} },
284 { "inc", OP_6MASK, 0x9403, {Rd} },
285 { "lsr", OP_6MASK, 0x9406, {Rd} },
286 { "neg", OP_6MASK, 0x9401, {Rd} },
287 { "pop", OP_6MASK, 0x900f, {Rd} },
288 { "push", OP_6MASK, 0x920f, {Rd} },
289 { "ror", OP_6MASK, 0x9407, {Rd} },
290 { "swap", OP_6MASK, 0x9402, {Rd} },
291
292 { "cbi", OP_3MASK, 0x9800, {A5, b3} },
293 { "sbi", OP_3MASK, 0x9a00, {A5, b3} },
294 { "sbic", OP_3MASK, 0x9900, {A5, b3} },
295 { "sbis", OP_3MASK, 0x9b00, {A5, b3} },
296
297
298 { "call", OP_11MASK, 0x940e, {Rel22} },
299 { "jmp", OP_11MASK, 0x940c, {Rel22} },
300
301 { "lds", OP_6MASK, 0x9000, {Rd, k16} },
302 { "sts", OP_6MASK, 0x9200, {k16, Rd} },
303
304 { "in", OP_10MASK, 0xb000, {Rd, A6} },
305 { "out", OP_10MASK, 0xb800, {A6, Rd} },
306
307 { "ser", OP_8MASK, 0xef0f, {Rd16} },
308
309 { "brcc", OP_7MASK, 0xf400, {Rel7} },
310 { "brcs", OP_7MASK, 0xf000, {Rel7} },
311 { "breq", OP_7MASK, 0xf001, {Rel7} },
312 { "brge", OP_7MASK, 0xf404, {Rel7} },
313 { "brhc", OP_7MASK, 0xf405, {Rel7} },
314 { "brhs", OP_7MASK, 0xf005, {Rel7} },
315 { "brid", OP_7MASK, 0xf407, {Rel7} },
316 { "brie", OP_7MASK, 0xf007, {Rel7} },
317 { "brlo", OP_7MASK, 0xf000, {Rel7} },
318 { "brlt", OP_7MASK, 0xf004, {Rel7} },
319 { "brmi", OP_7MASK, 0xf002, {Rel7} },
320 { "brne", OP_7MASK, 0xf401, {Rel7} },
321 { "brpl", OP_7MASK, 0xf402, {Rel7} },
322 { "brsh", OP_7MASK, 0xf400, {Rel7} },
323 { "brtc", OP_7MASK, 0xf406, {Rel7} },
324 { "brts", OP_7MASK, 0xf006, {Rel7} },
325 { "brvc", OP_7MASK, 0xf403, {Rel7} },
326 { "brvs", OP_7MASK, 0xf003, {Rel7} },
327
328 { "bld", OP_5MASK, 0xf800, {Rd, b3} },
329 { "bst", OP_5MASK, 0xfa00, {Rd, b3} },
330 { "sbrc", OP_5MASK, 0xfc00, {Rd, b3} },
331 { "sbrs", OP_5MASK, 0xfe00, {Rd, b3} },
332
333 };
334
335 const int avr_num_opcodes =
336 sizeof (avr_opcodes) / sizeof (avr_opcodes[0]);
337
338