More signed overflow fixes
[deliverable/binutils-gdb.git] / opcodes / mcore-dis.c
CommitLineData
3442f309 1/* Disassemble Motorola M*Core instructions.
82704155 2 Copyright (C) 1993-2019 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 22#include <stdio.h>
5703197e 23#include "libiberty.h"
3f230321
NC
24#define STATIC_TABLE
25#define DEFINE_TABLE
26
27#include "mcore-opc.h"
88c1242d 28#include "disassemble.h"
3f230321 29
9cac79d3 30/* Mask for each mcore_opclass: */
7f6621cd 31static const unsigned short imsk[] = {
9cac79d3
NC
32 /* O0 */ 0xFFFF,
33 /* OT */ 0xFFFC,
34 /* O1 */ 0xFFF0,
710c2d97 35 /* OC */ 0xFE00,
9cac79d3
NC
36 /* O2 */ 0xFF00,
37 /* X1 */ 0xFFF0,
38 /* OI */ 0xFE00,
39 /* OB */ 0xFE00,
7f6621cd 40
9cac79d3
NC
41 /* OMa */ 0xFFF0,
42 /* SI */ 0xFE00,
43 /* I7 */ 0xF800,
44 /* LS */ 0xF000,
45 /* BR */ 0xF800,
46 /* BL */ 0xFF00,
47 /* LR */ 0xF000,
48 /* LJ */ 0xFF00,
7f6621cd 49
9cac79d3
NC
50 /* RM */ 0xFFF0,
51 /* RQ */ 0xFFF0,
52 /* JSR */ 0xFFF0,
53 /* JMP */ 0xFFF0,
54 /* OBRa*/ 0xFFF0,
55 /* OBRb*/ 0xFF80,
56 /* OBRc*/ 0xFF00,
57 /* OBR2*/ 0xFE00,
7f6621cd 58
9cac79d3
NC
59 /* O1R1*/ 0xFFF0,
60 /* OMb */ 0xFF80,
61 /* OMc */ 0xFF00,
62 /* SIa */ 0xFE00,
63
7f6621cd 64 /* MULSH */ 0xFF00,
97ee9b94 65 /* OPSR */ 0xFFF8, /* psrset/psrclr */
7f6621cd 66
3f230321
NC
67 /* JC */ 0, /* JC,JU,JL don't appear in object */
68 /* JU */ 0,
69 /* JL */ 0,
70 /* RSI */ 0,
71 /* DO21*/ 0,
7f6621cd 72 /* OB2 */ 0 /* OB2 won't appear in object. */
3f230321
NC
73};
74
7f6621cd 75static const char *grname[] = {
3f230321
NC
76 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
77 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
78};
79
80static const char X[] = "??";
81
7f6621cd 82static const char *crname[] = {
3f230321
NC
83 "psr", "vbr", "epsr", "fpsr", "epc", "fpc", "ss0", "ss1",
84 "ss2", "ss3", "ss4", "gcr", "gsr", X, X, X,
85 X, X, X, X, X, X, X, X,
86 X, X, X, X, X, X, X, X
87};
88
89static const unsigned isiz[] = { 2, 0, 1, 0 };
90
7f6621cd 91int
bdc4de1b
NC
92print_insn_mcore (bfd_vma memaddr,
93 struct disassemble_info *info)
3f230321 94{
6a51a8a8 95 unsigned char ibytes[4];
91d6fa6a 96 fprintf_ftype print_func = info->fprintf_func;
6a51a8a8
AM
97 void *stream = info->stream;
98 unsigned short inst;
5703197e 99 unsigned int i;
6a51a8a8 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. */
5703197e
TS
120 for (i = 0; i < ARRAY_SIZE (mcore_table); i++)
121 if (mcore_table[i].inst == (inst & imsk[mcore_table[i].opclass]))
3f230321
NC
122 break;
123
5703197e 124 if (i == ARRAY_SIZE (mcore_table))
91d6fa6a 125 (*print_func) (stream, ".short 0x%04x", inst);
3f230321
NC
126 else
127 {
7f6621cd
KH
128 const char *name = grname[inst & 0x0F];
129
5703197e 130 (*print_func) (stream, "%s", mcore_table[i].name);
7f6621cd 131
5703197e 132 switch (mcore_table[i].opclass)
3f230321 133 {
6a51a8a8
AM
134 case O0:
135 break;
136
137 case OT:
91d6fa6a 138 (*print_func) (stream, "\t%d", inst & 0x3);
6a51a8a8
AM
139 break;
140
3f230321
NC
141 case O1:
142 case JMP:
6a51a8a8 143 case JSR:
91d6fa6a 144 (*print_func) (stream, "\t%s", name);
6a51a8a8
AM
145 break;
146
147 case OC:
91d6fa6a 148 (*print_func) (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]);
6a51a8a8
AM
149 break;
150
151 case O1R1:
91d6fa6a 152 (*print_func) (stream, "\t%s, r1", name);
6a51a8a8
AM
153 break;
154
97ee9b94 155 case MULSH:
6a51a8a8 156 case O2:
91d6fa6a 157 (*print_func) (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]);
6a51a8a8
AM
158 break;
159
160 case X1:
91d6fa6a 161 (*print_func) (stream, "\tr1, %s", name);
6a51a8a8
AM
162 break;
163
164 case OI:
91d6fa6a 165 (*print_func) (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1);
6a51a8a8
AM
166 break;
167
168 case RM:
91d6fa6a 169 (*print_func) (stream, "\t%s-r15, (r0)", name);
6a51a8a8
AM
170 break;
171
172 case RQ:
91d6fa6a 173 (*print_func) (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:
91d6fa6a 185 (*print_func) (stream, "\t%s, %d", name, (inst >> 4) & 0x1F);
6a51a8a8
AM
186 break;
187
188 case I7:
91d6fa6a 189 (*print_func) (stream, "\t%s, %d", name, (inst >> 4) & 0x7F);
6a51a8a8
AM
190 break;
191
192 case LS:
91d6fa6a
NC
193 (*print_func) (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 {
2480b6fa 199 uint32_t val = ((inst & 0x3FF) ^ 0x400) - 0x400;
7f6621cd 200
2480b6fa
AM
201 val = memaddr + 2 + (val << 1);
202 (*print_func) (stream, "\t0x%x", val);
7f6621cd 203
5703197e 204 if (strcmp (mcore_table[i].name, "bsr") == 0)
3f230321 205 {
c1485d85 206 /* For bsr, we'll try to get a symbol for the target. */
3f230321
NC
207 if (info->print_address_func && val != 0)
208 {
91d6fa6a 209 (*print_func) (stream, "\t// ");
3f230321
NC
210 info->print_address_func (val, info);
211 }
212 }
213 }
214 break;
7f6621cd 215
3f230321
NC
216 case BL:
217 {
2480b6fa
AM
218 uint32_t val = inst & 0x000F;
219 (*print_func) (stream, "\t%s, 0x%x",
91d6fa6a 220 grname[(inst >> 4) & 0xF],
2480b6fa 221 (uint32_t) (memaddr - (val << 1)));
3f230321
NC
222 }
223 break;
7f6621cd 224
3f230321
NC
225 case LR:
226 {
2480b6fa 227 uint32_t val;
7f6621cd 228
2480b6fa 229 val = (memaddr + 2 + ((inst & 0xFF) << 2)) & ~3;
7f6621cd 230
bdc4de1b
NC
231 /* We are not reading an instruction, so allow
232 reads to extend beyond the next symbol. */
233 info->stop_vma = 0;
3f230321 234 status = info->read_memory_func (val, ibytes, 4, info);
7f6621cd 235 if (status != 0)
3f230321
NC
236 {
237 info->memory_error_func (status, memaddr, info);
238 break;
239 }
7f6621cd 240
97ee9b94 241 if (info->endian == BFD_ENDIAN_LITTLE)
2480b6fa
AM
242 val = (((unsigned) ibytes[3] << 24) | (ibytes[2] << 16)
243 | (ibytes[1] << 8) | (ibytes[0]));
97ee9b94 244 else
2480b6fa
AM
245 val = (((unsigned) ibytes[0] << 24) | (ibytes[1] << 16)
246 | (ibytes[2] << 8) | (ibytes[3]));
7f6621cd 247
3f230321 248 /* Removed [] around literal value to match ABI syntax 12/95. */
2480b6fa 249 (*print_func) (stream, "\t%s, 0x%X", grname[(inst >> 8) & 0xF], val);
3f230321
NC
250
251 if (val == 0)
2480b6fa
AM
252 (*print_func) (stream, "\t// from address pool at 0x%x",
253 (uint32_t) (memaddr + 2
254 + ((inst & 0xFF) << 2)) & ~3);
3f230321
NC
255 }
256 break;
7f6621cd 257
3f230321
NC
258 case LJ:
259 {
2480b6fa 260 uint32_t val;
7f6621cd 261
2480b6fa 262 val = (memaddr + 2 + ((inst & 0xFF) << 2)) & ~3;
7f6621cd 263
bdc4de1b
NC
264 /* We are not reading an instruction, so allow
265 reads to extend beyond the next symbol. */
266 info->stop_vma = 0;
3f230321 267 status = info->read_memory_func (val, ibytes, 4, info);
7f6621cd 268 if (status != 0)
3f230321
NC
269 {
270 info->memory_error_func (status, memaddr, info);
271 break;
272 }
273
97ee9b94 274 if (info->endian == BFD_ENDIAN_LITTLE)
2480b6fa
AM
275 val = (((unsigned) ibytes[3] << 24) | (ibytes[2] << 16)
276 | (ibytes[1] << 8) | (ibytes[0]));
97ee9b94 277 else
2480b6fa
AM
278 val = (((unsigned) ibytes[0] << 24) | (ibytes[1] << 16)
279 | (ibytes[2] << 8) | (ibytes[3]));
7f6621cd 280
3f230321 281 /* Removed [] around literal value to match ABI syntax 12/95. */
2480b6fa 282 (*print_func) (stream, "\t0x%X", val);
3f230321
NC
283 /* For jmpi/jsri, we'll try to get a symbol for the target. */
284 if (info->print_address_func && val != 0)
285 {
91d6fa6a 286 (*print_func) (stream, "\t// ");
3f230321
NC
287 info->print_address_func (val, info);
288 }
289 else
290 {
2480b6fa
AM
291 (*print_func) (stream, "\t// from address pool at 0x%x",
292 (uint32_t) (memaddr + 2
293 + ((inst & 0xFF) << 2)) & ~3);
3f230321
NC
294 }
295 }
296 break;
7f6621cd 297
97ee9b94
NC
298 case OPSR:
299 {
7f6621cd
KH
300 static char *fields[] = {
301 "af", "ie", "fe", "fe,ie",
97ee9b94
NC
302 "ee", "ee,ie", "ee,fe", "ee,fe,ie"
303 };
7f6621cd 304
91d6fa6a 305 (*print_func) (stream, "\t%s", fields[inst & 0x7]);
97ee9b94
NC
306 }
307 break;
7f6621cd 308
3f230321 309 default:
c1485d85 310 /* If the disassembler lags the instruction set. */
91d6fa6a 311 (*print_func) (stream, "\tundecoded operands, inst is 0x%04x", inst);
3f230321
NC
312 break;
313 }
314 }
7f6621cd 315
c1485d85 316 /* Say how many bytes we consumed. */
3f230321
NC
317 return 2;
318}
This page took 0.957357 seconds and 4 git commands to generate.