Stop "objdump -d" from disassembling past a symbolic address.
[deliverable/binutils-gdb.git] / opcodes / mcore-dis.c
CommitLineData
3442f309 1/* Disassemble Motorola M*Core instructions.
b90efa5b 2 Copyright (C) 1993-2015 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
bdc4de1b
NC
91print_insn_mcore (bfd_vma memaddr,
92 struct disassemble_info *info)
3f230321 93{
6a51a8a8 94 unsigned char ibytes[4];
91d6fa6a 95 fprintf_ftype print_func = info->fprintf_func;
6a51a8a8
AM
96 void *stream = info->stream;
97 unsigned short inst;
98 const mcore_opcode_info *op;
99 int status;
3f230321
NC
100
101 info->bytes_per_chunk = 2;
102
103 status = info->read_memory_func (memaddr, ibytes, 2, info);
104
7f6621cd 105 if (status != 0)
3f230321
NC
106 {
107 info->memory_error_func (status, memaddr, info);
108 return -1;
109 }
110
97ee9b94 111 if (info->endian == BFD_ENDIAN_BIG)
3f230321 112 inst = (ibytes[0] << 8) | ibytes[1];
97ee9b94
NC
113 else if (info->endian == BFD_ENDIAN_LITTLE)
114 inst = (ibytes[1] << 8) | ibytes[0];
115 else
116 abort ();
3f230321
NC
117
118 /* Just a linear search of the table. */
7f6621cd 119 for (op = mcore_table; op->name != 0; op++)
3f230321
NC
120 if (op->inst == (inst & imsk[op->opclass]))
121 break;
122
123 if (op->name == 0)
91d6fa6a 124 (*print_func) (stream, ".short 0x%04x", inst);
3f230321
NC
125 else
126 {
7f6621cd
KH
127 const char *name = grname[inst & 0x0F];
128
91d6fa6a 129 (*print_func) (stream, "%s", op->name);
7f6621cd 130
3f230321
NC
131 switch (op->opclass)
132 {
6a51a8a8
AM
133 case O0:
134 break;
135
136 case OT:
91d6fa6a 137 (*print_func) (stream, "\t%d", inst & 0x3);
6a51a8a8
AM
138 break;
139
3f230321
NC
140 case O1:
141 case JMP:
6a51a8a8 142 case JSR:
91d6fa6a 143 (*print_func) (stream, "\t%s", name);
6a51a8a8
AM
144 break;
145
146 case OC:
91d6fa6a 147 (*print_func) (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]);
6a51a8a8
AM
148 break;
149
150 case O1R1:
91d6fa6a 151 (*print_func) (stream, "\t%s, r1", name);
6a51a8a8
AM
152 break;
153
97ee9b94 154 case MULSH:
6a51a8a8 155 case O2:
91d6fa6a 156 (*print_func) (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]);
6a51a8a8
AM
157 break;
158
159 case X1:
91d6fa6a 160 (*print_func) (stream, "\tr1, %s", name);
6a51a8a8
AM
161 break;
162
163 case OI:
91d6fa6a 164 (*print_func) (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1);
6a51a8a8
AM
165 break;
166
167 case RM:
91d6fa6a 168 (*print_func) (stream, "\t%s-r15, (r0)", name);
6a51a8a8
AM
169 break;
170
171 case RQ:
91d6fa6a 172 (*print_func) (stream, "\tr4-r7, (%s)", name);
6a51a8a8
AM
173 break;
174
3f230321
NC
175 case OB:
176 case OBRa:
177 case OBRb:
178 case OBRc:
179 case SI:
180 case SIa:
181 case OMa:
182 case OMb:
6a51a8a8 183 case OMc:
91d6fa6a 184 (*print_func) (stream, "\t%s, %d", name, (inst >> 4) & 0x1F);
6a51a8a8
AM
185 break;
186
187 case I7:
91d6fa6a 188 (*print_func) (stream, "\t%s, %d", name, (inst >> 4) & 0x7F);
6a51a8a8
AM
189 break;
190
191 case LS:
91d6fa6a
NC
192 (*print_func) (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF],
193 name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]);
3f230321 194 break;
7f6621cd 195
3f230321
NC
196 case BR:
197 {
198 long val = inst & 0x3FF;
7f6621cd 199
3f230321
NC
200 if (inst & 0x400)
201 val |= 0xFFFFFC00;
7f6621cd 202
91d6fa6a 203 (*print_func) (stream, "\t0x%lx", (long)(memaddr + 2 + (val << 1)));
7f6621cd 204
3f230321
NC
205 if (strcmp (op->name, "bsr") == 0)
206 {
c1485d85 207 /* For bsr, we'll try to get a symbol for the target. */
3f230321 208 val = memaddr + 2 + (val << 1);
7f6621cd 209
3f230321
NC
210 if (info->print_address_func && val != 0)
211 {
91d6fa6a 212 (*print_func) (stream, "\t// ");
3f230321
NC
213 info->print_address_func (val, info);
214 }
215 }
216 }
217 break;
7f6621cd 218
3f230321
NC
219 case BL:
220 {
221 long val;
222 val = (inst & 0x000F);
91d6fa6a
NC
223 (*print_func) (stream, "\t%s, 0x%lx",
224 grname[(inst >> 4) & 0xF],
225 (long) (memaddr - (val << 1)));
3f230321
NC
226 }
227 break;
7f6621cd 228
3f230321
NC
229 case LR:
230 {
231 unsigned long val;
7f6621cd 232
3f230321 233 val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
7f6621cd 234
bdc4de1b
NC
235 /* We are not reading an instruction, so allow
236 reads to extend beyond the next symbol. */
237 info->stop_vma = 0;
3f230321 238 status = info->read_memory_func (val, ibytes, 4, info);
7f6621cd 239 if (status != 0)
3f230321
NC
240 {
241 info->memory_error_func (status, memaddr, info);
242 break;
243 }
7f6621cd 244
97ee9b94
NC
245 if (info->endian == BFD_ENDIAN_LITTLE)
246 val = (ibytes[3] << 24) | (ibytes[2] << 16)
247 | (ibytes[1] << 8) | (ibytes[0]);
248 else
3f230321
NC
249 val = (ibytes[0] << 24) | (ibytes[1] << 16)
250 | (ibytes[2] << 8) | (ibytes[3]);
7f6621cd 251
3f230321 252 /* Removed [] around literal value to match ABI syntax 12/95. */
91d6fa6a 253 (*print_func) (stream, "\t%s, 0x%lX", grname[(inst >> 8) & 0xF], val);
3f230321
NC
254
255 if (val == 0)
91d6fa6a
NC
256 (*print_func) (stream, "\t// from address pool at 0x%lx",
257 (long) (memaddr + 2
258 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
3f230321
NC
259 }
260 break;
7f6621cd 261
3f230321
NC
262 case LJ:
263 {
264 unsigned long val;
7f6621cd 265
3f230321 266 val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
7f6621cd 267
bdc4de1b
NC
268 /* We are not reading an instruction, so allow
269 reads to extend beyond the next symbol. */
270 info->stop_vma = 0;
3f230321 271 status = info->read_memory_func (val, ibytes, 4, info);
7f6621cd 272 if (status != 0)
3f230321
NC
273 {
274 info->memory_error_func (status, memaddr, info);
275 break;
276 }
277
97ee9b94
NC
278 if (info->endian == BFD_ENDIAN_LITTLE)
279 val = (ibytes[3] << 24) | (ibytes[2] << 16)
280 | (ibytes[1] << 8) | (ibytes[0]);
281 else
3f230321
NC
282 val = (ibytes[0] << 24) | (ibytes[1] << 16)
283 | (ibytes[2] << 8) | (ibytes[3]);
7f6621cd 284
3f230321 285 /* Removed [] around literal value to match ABI syntax 12/95. */
91d6fa6a 286 (*print_func) (stream, "\t0x%lX", val);
3f230321
NC
287 /* For jmpi/jsri, we'll try to get a symbol for the target. */
288 if (info->print_address_func && val != 0)
289 {
91d6fa6a 290 (*print_func) (stream, "\t// ");
3f230321
NC
291 info->print_address_func (val, info);
292 }
293 else
294 {
91d6fa6a
NC
295 (*print_func) (stream, "\t// from address pool at 0x%lx",
296 (long) (memaddr + 2
297 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
3f230321
NC
298 }
299 }
300 break;
7f6621cd 301
97ee9b94
NC
302 case OPSR:
303 {
7f6621cd
KH
304 static char *fields[] = {
305 "af", "ie", "fe", "fe,ie",
97ee9b94
NC
306 "ee", "ee,ie", "ee,fe", "ee,fe,ie"
307 };
7f6621cd 308
91d6fa6a 309 (*print_func) (stream, "\t%s", fields[inst & 0x7]);
97ee9b94
NC
310 }
311 break;
7f6621cd 312
3f230321 313 default:
c1485d85 314 /* If the disassembler lags the instruction set. */
91d6fa6a 315 (*print_func) (stream, "\tundecoded operands, inst is 0x%04x", inst);
3f230321
NC
316 break;
317 }
318 }
7f6621cd 319
c1485d85 320 /* Say how many bytes we consumed. */
3f230321
NC
321 return 2;
322}
This page took 0.751303 seconds and 4 git commands to generate.