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