update copyright dates
[deliverable/binutils-gdb.git] / opcodes / mcore-dis.c
CommitLineData
3442f309 1/* Disassemble Motorola M*Core instructions.
aa820537
AM
2 Copyright 1993, 1999, 2000, 2001, 2002, 2005, 2007
3 Free Software Foundation, Inc.
3f230321 4
9b201bb5 5 This file is part of the GNU opcodes library.
3f230321 6
9b201bb5
NC
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
3f230321 11
9b201bb5
NC
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
3f230321 21
0d8dfecf 22#include "sysdep.h"
3f230321
NC
23#include <stdio.h>
24#define STATIC_TABLE
25#define DEFINE_TABLE
26
27#include "mcore-opc.h"
28#include "dis-asm.h"
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
3f230321
NC
92print_insn_mcore (memaddr, info)
93 bfd_vma memaddr;
7f6621cd 94 struct disassemble_info *info;
3f230321 95{
6a51a8a8
AM
96 unsigned char ibytes[4];
97 fprintf_ftype fprintf = info->fprintf_func;
98 void *stream = info->stream;
99 unsigned short inst;
100 const mcore_opcode_info *op;
101 int status;
3f230321
NC
102
103 info->bytes_per_chunk = 2;
104
105 status = info->read_memory_func (memaddr, ibytes, 2, info);
106
7f6621cd 107 if (status != 0)
3f230321
NC
108 {
109 info->memory_error_func (status, memaddr, info);
110 return -1;
111 }
112
97ee9b94 113 if (info->endian == BFD_ENDIAN_BIG)
3f230321 114 inst = (ibytes[0] << 8) | ibytes[1];
97ee9b94
NC
115 else if (info->endian == BFD_ENDIAN_LITTLE)
116 inst = (ibytes[1] << 8) | ibytes[0];
117 else
118 abort ();
3f230321
NC
119
120 /* Just a linear search of the table. */
7f6621cd 121 for (op = mcore_table; op->name != 0; op++)
3f230321
NC
122 if (op->inst == (inst & imsk[op->opclass]))
123 break;
124
125 if (op->name == 0)
65be1333 126 (*fprintf) (stream, ".short 0x%04x", inst);
3f230321
NC
127 else
128 {
7f6621cd
KH
129 const char *name = grname[inst & 0x0F];
130
65be1333 131 (*fprintf) (stream, "%s", op->name);
7f6621cd 132
3f230321
NC
133 switch (op->opclass)
134 {
6a51a8a8
AM
135 case O0:
136 break;
137
138 case OT:
65be1333 139 (*fprintf) (stream, "\t%d", inst & 0x3);
6a51a8a8
AM
140 break;
141
3f230321
NC
142 case O1:
143 case JMP:
6a51a8a8 144 case JSR:
65be1333 145 (*fprintf) (stream, "\t%s", name);
6a51a8a8
AM
146 break;
147
148 case OC:
65be1333 149 (*fprintf) (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]);
6a51a8a8
AM
150 break;
151
152 case O1R1:
65be1333 153 (*fprintf) (stream, "\t%s, r1", name);
6a51a8a8
AM
154 break;
155
97ee9b94 156 case MULSH:
6a51a8a8 157 case O2:
65be1333 158 (*fprintf) (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]);
6a51a8a8
AM
159 break;
160
161 case X1:
65be1333 162 (*fprintf) (stream, "\tr1, %s", name);
6a51a8a8
AM
163 break;
164
165 case OI:
65be1333 166 (*fprintf) (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1);
6a51a8a8
AM
167 break;
168
169 case RM:
65be1333 170 (*fprintf) (stream, "\t%s-r15, (r0)", name);
6a51a8a8
AM
171 break;
172
173 case RQ:
65be1333 174 (*fprintf) (stream, "\tr4-r7, (%s)", name);
6a51a8a8
AM
175 break;
176
3f230321
NC
177 case OB:
178 case OBRa:
179 case OBRb:
180 case OBRc:
181 case SI:
182 case SIa:
183 case OMa:
184 case OMb:
6a51a8a8 185 case OMc:
65be1333 186 (*fprintf) (stream, "\t%s, %d", name, (inst >> 4) & 0x1F);
6a51a8a8
AM
187 break;
188
189 case I7:
65be1333 190 (*fprintf) (stream, "\t%s, %d", name, (inst >> 4) & 0x7F);
6a51a8a8
AM
191 break;
192
193 case LS:
65be1333
AM
194 (*fprintf) (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF],
195 name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]);
3f230321 196 break;
7f6621cd 197
3f230321
NC
198 case BR:
199 {
200 long val = inst & 0x3FF;
7f6621cd 201
3f230321
NC
202 if (inst & 0x400)
203 val |= 0xFFFFFC00;
7f6621cd 204
65be1333 205 (*fprintf) (stream, "\t0x%lx", (long)(memaddr + 2 + (val << 1)));
7f6621cd 206
3f230321
NC
207 if (strcmp (op->name, "bsr") == 0)
208 {
c1485d85 209 /* For bsr, we'll try to get a symbol for the target. */
3f230321 210 val = memaddr + 2 + (val << 1);
7f6621cd 211
3f230321
NC
212 if (info->print_address_func && val != 0)
213 {
65be1333 214 (*fprintf) (stream, "\t// ");
3f230321
NC
215 info->print_address_func (val, info);
216 }
217 }
218 }
219 break;
7f6621cd 220
3f230321
NC
221 case BL:
222 {
223 long val;
224 val = (inst & 0x000F);
65be1333
AM
225 (*fprintf) (stream, "\t%s, 0x%lx",
226 grname[(inst >> 4) & 0xF],
227 (long) (memaddr - (val << 1)));
3f230321
NC
228 }
229 break;
7f6621cd 230
3f230321
NC
231 case LR:
232 {
233 unsigned long val;
7f6621cd 234
3f230321 235 val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
7f6621cd 236
3f230321 237 status = info->read_memory_func (val, ibytes, 4, info);
7f6621cd 238 if (status != 0)
3f230321
NC
239 {
240 info->memory_error_func (status, memaddr, info);
241 break;
242 }
7f6621cd 243
97ee9b94
NC
244 if (info->endian == BFD_ENDIAN_LITTLE)
245 val = (ibytes[3] << 24) | (ibytes[2] << 16)
246 | (ibytes[1] << 8) | (ibytes[0]);
247 else
3f230321
NC
248 val = (ibytes[0] << 24) | (ibytes[1] << 16)
249 | (ibytes[2] << 8) | (ibytes[3]);
7f6621cd 250
3f230321 251 /* Removed [] around literal value to match ABI syntax 12/95. */
65be1333 252 (*fprintf) (stream, "\t%s, 0x%lX", grname[(inst >> 8) & 0xF], val);
3f230321
NC
253
254 if (val == 0)
65be1333
AM
255 (*fprintf) (stream, "\t// from address pool at 0x%lx",
256 (long) (memaddr + 2
257 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
3f230321
NC
258 }
259 break;
7f6621cd 260
3f230321
NC
261 case LJ:
262 {
263 unsigned long val;
7f6621cd 264
3f230321 265 val = (memaddr + 2 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC;
7f6621cd 266
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
NC
274 if (info->endian == BFD_ENDIAN_LITTLE)
275 val = (ibytes[3] << 24) | (ibytes[2] << 16)
276 | (ibytes[1] << 8) | (ibytes[0]);
277 else
3f230321
NC
278 val = (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. */
65be1333 282 (*fprintf) (stream, "\t0x%lX", 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 {
65be1333 286 (*fprintf) (stream, "\t// ");
3f230321
NC
287 info->print_address_func (val, info);
288 }
289 else
290 {
65be1333
AM
291 (*fprintf) (stream, "\t// from address pool at 0x%lx",
292 (long) (memaddr + 2
293 + ((inst & 0xFF) << 2)) & 0xFFFFFFFC);
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
65be1333 305 (*fprintf) (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. */
65be1333 311 (*fprintf) (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.434923 seconds and 4 git commands to generate.