source: trunk/binutils/opcodes/mcore-dis.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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