1f7cc78ecSespie /* Disassemble Motorola M*Core instructions.
2*d2201f2fSdrahn Copyright 1993, 1999, 2000, 2002 Free Software Foundation, Inc.
3f7cc78ecSespie
4f7cc78ecSespie This program is free software; you can redistribute it and/or modify
5f7cc78ecSespie it under the terms of the GNU General Public License as published by
6f7cc78ecSespie the Free Software Foundation; either version 2 of the License, or
7f7cc78ecSespie (at your option) any later version.
8f7cc78ecSespie
9f7cc78ecSespie This program is distributed in the hope that it will be useful,
10f7cc78ecSespie but WITHOUT ANY WARRANTY; without even the implied warranty of
11f7cc78ecSespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12f7cc78ecSespie GNU General Public License for more details.
13f7cc78ecSespie
14f7cc78ecSespie You should have received a copy of the GNU General Public License
15f7cc78ecSespie along with this program; if not, write to the Free Software
16f7cc78ecSespie Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17f7cc78ecSespie
18f7cc78ecSespie #include "sysdep.h"
19f7cc78ecSespie #include <stdio.h>
20f7cc78ecSespie #define STATIC_TABLE
21f7cc78ecSespie #define DEFINE_TABLE
22f7cc78ecSespie
23f7cc78ecSespie #include "mcore-opc.h"
24f7cc78ecSespie #include "dis-asm.h"
25f7cc78ecSespie
26f7cc78ecSespie /* Mask for each mcore_opclass: */
27*d2201f2fSdrahn static const unsigned short imsk[] = {
28f7cc78ecSespie /* O0 */ 0xFFFF,
29f7cc78ecSespie /* OT */ 0xFFFC,
30f7cc78ecSespie /* O1 */ 0xFFF0,
315f210c2aSfgsch /* OC */ 0xFE00,
32f7cc78ecSespie /* O2 */ 0xFF00,
33f7cc78ecSespie /* X1 */ 0xFFF0,
34f7cc78ecSespie /* OI */ 0xFE00,
35f7cc78ecSespie /* OB */ 0xFE00,
36f7cc78ecSespie
37f7cc78ecSespie /* OMa */ 0xFFF0,
38f7cc78ecSespie /* SI */ 0xFE00,
39f7cc78ecSespie /* I7 */ 0xF800,
40f7cc78ecSespie /* LS */ 0xF000,
41f7cc78ecSespie /* BR */ 0xF800,
42f7cc78ecSespie /* BL */ 0xFF00,
43f7cc78ecSespie /* LR */ 0xF000,
44f7cc78ecSespie /* LJ */ 0xFF00,
45f7cc78ecSespie
46f7cc78ecSespie /* RM */ 0xFFF0,
47f7cc78ecSespie /* RQ */ 0xFFF0,
48f7cc78ecSespie /* JSR */ 0xFFF0,
49f7cc78ecSespie /* JMP */ 0xFFF0,
50f7cc78ecSespie /* OBRa*/ 0xFFF0,
51f7cc78ecSespie /* OBRb*/ 0xFF80,
52f7cc78ecSespie /* OBRc*/ 0xFF00,
53f7cc78ecSespie /* OBR2*/ 0xFE00,
54f7cc78ecSespie
55f7cc78ecSespie /* O1R1*/ 0xFFF0,
56f7cc78ecSespie /* OMb */ 0xFF80,
57f7cc78ecSespie /* OMc */ 0xFF00,
58f7cc78ecSespie /* SIa */ 0xFE00,
59f7cc78ecSespie
60f7cc78ecSespie /* MULSH */ 0xFF00,
61f7cc78ecSespie /* OPSR */ 0xFFF8, /* psrset/psrclr */
62f7cc78ecSespie
63f7cc78ecSespie /* JC */ 0, /* JC,JU,JL don't appear in object */
64f7cc78ecSespie /* JU */ 0,
65f7cc78ecSespie /* JL */ 0,
66f7cc78ecSespie /* RSI */ 0,
67f7cc78ecSespie /* DO21*/ 0,
68f7cc78ecSespie /* OB2 */ 0 /* OB2 won't appear in object. */
69f7cc78ecSespie };
70f7cc78ecSespie
71*d2201f2fSdrahn static const char *grname[] = {
72f7cc78ecSespie "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
73f7cc78ecSespie "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
74f7cc78ecSespie };
75f7cc78ecSespie
76f7cc78ecSespie static const char X[] = "??";
77f7cc78ecSespie
78*d2201f2fSdrahn static const char *crname[] = {
79f7cc78ecSespie "psr", "vbr", "epsr", "fpsr", "epc", "fpc", "ss0", "ss1",
80f7cc78ecSespie "ss2", "ss3", "ss4", "gcr", "gsr", X, X, X,
81f7cc78ecSespie X, X, X, X, X, X, X, X,
82f7cc78ecSespie X, X, X, X, X, X, X, X
83f7cc78ecSespie };
84f7cc78ecSespie
85f7cc78ecSespie static const unsigned isiz[] = { 2, 0, 1, 0 };
86f7cc78ecSespie
87f7cc78ecSespie int
print_insn_mcore(memaddr,info)88f7cc78ecSespie print_insn_mcore (memaddr, info)
89f7cc78ecSespie bfd_vma memaddr;
90f7cc78ecSespie struct disassemble_info *info;
91f7cc78ecSespie {
92f7cc78ecSespie unsigned char ibytes[4];
93f7cc78ecSespie fprintf_ftype fprintf = info->fprintf_func;
94f7cc78ecSespie void *stream = info->stream;
95f7cc78ecSespie unsigned short inst;
96*d2201f2fSdrahn const mcore_opcode_info *op;
97f7cc78ecSespie int status;
98f7cc78ecSespie
99f7cc78ecSespie info->bytes_per_chunk = 2;
100f7cc78ecSespie
101f7cc78ecSespie status = info->read_memory_func (memaddr, ibytes, 2, info);
102f7cc78ecSespie
103f7cc78ecSespie if (status != 0)
104f7cc78ecSespie {
105f7cc78ecSespie info->memory_error_func (status, memaddr, info);
106f7cc78ecSespie return -1;
107f7cc78ecSespie }
108f7cc78ecSespie
109f7cc78ecSespie if (info->endian == BFD_ENDIAN_BIG)
110f7cc78ecSespie inst = (ibytes[0] << 8) | ibytes[1];
111f7cc78ecSespie else if (info->endian == BFD_ENDIAN_LITTLE)
112f7cc78ecSespie inst = (ibytes[1] << 8) | ibytes[0];
113f7cc78ecSespie else
114f7cc78ecSespie abort ();
115f7cc78ecSespie
116f7cc78ecSespie /* Just a linear search of the table. */
117f7cc78ecSespie for (op = mcore_table; op->name != 0; op++)
118f7cc78ecSespie if (op->inst == (inst & imsk[op->opclass]))
119f7cc78ecSespie break;
120f7cc78ecSespie
121f7cc78ecSespie if (op->name == 0)
122f7cc78ecSespie fprintf (stream, ".short 0x%04x", inst);
123f7cc78ecSespie else
124f7cc78ecSespie {
125f7cc78ecSespie const char *name = grname[inst & 0x0F];
126f7cc78ecSespie
127f7cc78ecSespie fprintf (stream, "%s", op->name);
128f7cc78ecSespie
129f7cc78ecSespie switch (op->opclass)
130f7cc78ecSespie {
131*d2201f2fSdrahn case O0:
132*d2201f2fSdrahn break;
133*d2201f2fSdrahn
134*d2201f2fSdrahn case OT:
135*d2201f2fSdrahn fprintf (stream, "\t%d", inst & 0x3);
136*d2201f2fSdrahn break;
137*d2201f2fSdrahn
138f7cc78ecSespie case O1:
139f7cc78ecSespie case JMP:
140*d2201f2fSdrahn case JSR:
141*d2201f2fSdrahn fprintf (stream, "\t%s", name);
142*d2201f2fSdrahn break;
143*d2201f2fSdrahn
144*d2201f2fSdrahn case OC:
145*d2201f2fSdrahn fprintf (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]);
146*d2201f2fSdrahn break;
147*d2201f2fSdrahn
148*d2201f2fSdrahn case O1R1:
149*d2201f2fSdrahn fprintf (stream, "\t%s, r1", name);
150*d2201f2fSdrahn break;
151*d2201f2fSdrahn
152f7cc78ecSespie case MULSH:
153*d2201f2fSdrahn case O2:
154*d2201f2fSdrahn fprintf (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]);
155*d2201f2fSdrahn break;
156*d2201f2fSdrahn
157*d2201f2fSdrahn case X1:
158*d2201f2fSdrahn fprintf (stream, "\tr1, %s", name);
159*d2201f2fSdrahn break;
160*d2201f2fSdrahn
161*d2201f2fSdrahn case OI:
162*d2201f2fSdrahn fprintf (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1);
163*d2201f2fSdrahn break;
164*d2201f2fSdrahn
165*d2201f2fSdrahn case RM:
166*d2201f2fSdrahn fprintf (stream, "\t%s-r15, (r0)", name);
167*d2201f2fSdrahn break;
168*d2201f2fSdrahn
169*d2201f2fSdrahn case RQ:
170*d2201f2fSdrahn fprintf (stream, "\tr4-r7, (%s)", name);
171*d2201f2fSdrahn break;
172*d2201f2fSdrahn
173f7cc78ecSespie case OB:
174f7cc78ecSespie case OBRa:
175f7cc78ecSespie case OBRb:
176f7cc78ecSespie case OBRc:
177f7cc78ecSespie case SI:
178f7cc78ecSespie case SIa:
179f7cc78ecSespie case OMa:
180f7cc78ecSespie case OMb:
181*d2201f2fSdrahn case OMc:
182*d2201f2fSdrahn fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x1F);
183*d2201f2fSdrahn break;
184*d2201f2fSdrahn
185*d2201f2fSdrahn case I7:
186*d2201f2fSdrahn fprintf (stream, "\t%s, %d", name, (inst >> 4) & 0x7F);
187*d2201f2fSdrahn break;
188*d2201f2fSdrahn
189*d2201f2fSdrahn case LS:
190*d2201f2fSdrahn fprintf (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF],
191f7cc78ecSespie name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]);
192f7cc78ecSespie break;
193f7cc78ecSespie
194f7cc78ecSespie case BR:
195f7cc78ecSespie {
196f7cc78ecSespie long val = inst & 0x3FF;
197f7cc78ecSespie
198f7cc78ecSespie if (inst & 0x400)
199f7cc78ecSespie val |= 0xFFFFFC00;
200f7cc78ecSespie
201f7cc78ecSespie fprintf (stream, "\t0x%x", memaddr + 2 + (val << 1));
202f7cc78ecSespie
203f7cc78ecSespie if (strcmp (op->name, "bsr") == 0)
204f7cc78ecSespie {
2055f210c2aSfgsch /* For bsr, we'll try to get a symbol for the target. */
206f7cc78ecSespie val = memaddr + 2 + (val << 1);
207f7cc78ecSespie
208f7cc78ecSespie if (info->print_address_func && val != 0)
209f7cc78ecSespie {
210f7cc78ecSespie fprintf (stream, "\t// ");
211f7cc78ecSespie info->print_address_func (val, info);
212f7cc78ecSespie }
213f7cc78ecSespie }
214f7cc78ecSespie }
215f7cc78ecSespie break;
216f7cc78ecSespie
217f7cc78ecSespie case BL:
218f7cc78ecSespie {
219f7cc78ecSespie long val;
220f7cc78ecSespie val = (inst & 0x000F);
221f7cc78ecSespie fprintf (stream, "\t%s, 0x%x",
222f7cc78ecSespie grname[(inst >> 4) & 0xF], memaddr - (val << 1));
223f7cc78ecSespie }
224f7cc78ecSespie break;
225f7cc78ecSespie
226f7cc78ecSespie case LR:
227f7cc78ecSespie {
228f7cc78ecSespie unsigned long val;
229f7cc78ecSespie
230f7cc78ecSespie val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
231f7cc78ecSespie
232f7cc78ecSespie status = info->read_memory_func (val, ibytes, 4, info);
233f7cc78ecSespie if (status != 0)
234f7cc78ecSespie {
235f7cc78ecSespie info->memory_error_func (status, memaddr, info);
236f7cc78ecSespie break;
237f7cc78ecSespie }
238f7cc78ecSespie
239f7cc78ecSespie if (info->endian == BFD_ENDIAN_LITTLE)
240f7cc78ecSespie val = (ibytes[3] << 24) | (ibytes[2] << 16)
241f7cc78ecSespie | (ibytes[1] << 8) | (ibytes[0]);
242f7cc78ecSespie else
243f7cc78ecSespie val = (ibytes[0] << 24) | (ibytes[1] << 16)
244f7cc78ecSespie | (ibytes[2] << 8) | (ibytes[3]);
245f7cc78ecSespie
246f7cc78ecSespie /* Removed [] around literal value to match ABI syntax 12/95. */
247f7cc78ecSespie fprintf (stream, "\t%s, 0x%X", grname[(inst >> 8) & 0xF], val);
248f7cc78ecSespie
249f7cc78ecSespie if (val == 0)
250f7cc78ecSespie fprintf (stream, "\t// from address pool at 0x%x",
251f7cc78ecSespie (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
252f7cc78ecSespie }
253f7cc78ecSespie break;
254f7cc78ecSespie
255f7cc78ecSespie case LJ:
256f7cc78ecSespie {
257f7cc78ecSespie unsigned long val;
258f7cc78ecSespie
259f7cc78ecSespie val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
260f7cc78ecSespie
261f7cc78ecSespie status = info->read_memory_func (val, ibytes, 4, info);
262f7cc78ecSespie if (status != 0)
263f7cc78ecSespie {
264f7cc78ecSespie info->memory_error_func (status, memaddr, info);
265f7cc78ecSespie break;
266f7cc78ecSespie }
267f7cc78ecSespie
268f7cc78ecSespie if (info->endian == BFD_ENDIAN_LITTLE)
269f7cc78ecSespie val = (ibytes[3] << 24) | (ibytes[2] << 16)
270f7cc78ecSespie | (ibytes[1] << 8) | (ibytes[0]);
271f7cc78ecSespie else
272f7cc78ecSespie val = (ibytes[0] << 24) | (ibytes[1] << 16)
273f7cc78ecSespie | (ibytes[2] << 8) | (ibytes[3]);
274f7cc78ecSespie
275f7cc78ecSespie /* Removed [] around literal value to match ABI syntax 12/95. */
276f7cc78ecSespie fprintf (stream, "\t0x%X", val);
277f7cc78ecSespie /* For jmpi/jsri, we'll try to get a symbol for the target. */
278f7cc78ecSespie if (info->print_address_func && val != 0)
279f7cc78ecSespie {
280f7cc78ecSespie fprintf (stream, "\t// ");
281f7cc78ecSespie info->print_address_func (val, info);
282f7cc78ecSespie }
283f7cc78ecSespie else
284f7cc78ecSespie {
285f7cc78ecSespie fprintf (stream, "\t// from address pool at 0x%x",
286f7cc78ecSespie (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
287f7cc78ecSespie }
288f7cc78ecSespie }
289f7cc78ecSespie break;
290f7cc78ecSespie
291f7cc78ecSespie case OPSR:
292f7cc78ecSespie {
293*d2201f2fSdrahn static char *fields[] = {
294f7cc78ecSespie "af", "ie", "fe", "fe,ie",
295f7cc78ecSespie "ee", "ee,ie", "ee,fe", "ee,fe,ie"
296f7cc78ecSespie };
297f7cc78ecSespie
298f7cc78ecSespie fprintf (stream, "\t%s", fields[inst & 0x7]);
299f7cc78ecSespie }
300f7cc78ecSespie break;
301f7cc78ecSespie
302f7cc78ecSespie default:
3035f210c2aSfgsch /* If the disassembler lags the instruction set. */
304f7cc78ecSespie fprintf (stream, "\tundecoded operands, inst is 0x%04x", inst);
305f7cc78ecSespie break;
306f7cc78ecSespie }
307f7cc78ecSespie }
308f7cc78ecSespie
3095f210c2aSfgsch /* Say how many bytes we consumed. */
310f7cc78ecSespie return 2;
311f7cc78ecSespie }
312