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