1*3d8817e4Smiod /* Disassemble MN10300 instructions.
2*3d8817e4Smiod Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005
3*3d8817e4Smiod Free Software Foundation, Inc.
4*3d8817e4Smiod
5*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
6*3d8817e4Smiod it under the terms of the GNU General Public License as published by
7*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
8*3d8817e4Smiod (at your option) any later version.
9*3d8817e4Smiod
10*3d8817e4Smiod This program is distributed in the hope that it will be useful,
11*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
12*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*3d8817e4Smiod GNU General Public License for more details.
14*3d8817e4Smiod
15*3d8817e4Smiod You should have received a copy of the GNU General Public License
16*3d8817e4Smiod along with this program; if not, write to the Free Software
17*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18*3d8817e4Smiod MA 02110-1301, USA. */
19*3d8817e4Smiod
20*3d8817e4Smiod #include <stdio.h>
21*3d8817e4Smiod
22*3d8817e4Smiod #include "sysdep.h"
23*3d8817e4Smiod #include "opcode/mn10300.h"
24*3d8817e4Smiod #include "dis-asm.h"
25*3d8817e4Smiod #include "opintl.h"
26*3d8817e4Smiod
27*3d8817e4Smiod #define HAVE_AM33_2 (info->mach == AM33_2)
28*3d8817e4Smiod #define HAVE_AM33 (info->mach == AM33 || HAVE_AM33_2)
29*3d8817e4Smiod #define HAVE_AM30 (info->mach == AM30)
30*3d8817e4Smiod
31*3d8817e4Smiod static void
disassemble(bfd_vma memaddr,struct disassemble_info * info,unsigned long insn,unsigned int size)32*3d8817e4Smiod disassemble (bfd_vma memaddr,
33*3d8817e4Smiod struct disassemble_info *info,
34*3d8817e4Smiod unsigned long insn,
35*3d8817e4Smiod unsigned int size)
36*3d8817e4Smiod {
37*3d8817e4Smiod struct mn10300_opcode *op = (struct mn10300_opcode *) mn10300_opcodes;
38*3d8817e4Smiod const struct mn10300_operand *operand;
39*3d8817e4Smiod bfd_byte buffer[4];
40*3d8817e4Smiod unsigned long extension = 0;
41*3d8817e4Smiod int status, match = 0;
42*3d8817e4Smiod
43*3d8817e4Smiod /* Find the opcode. */
44*3d8817e4Smiod while (op->name)
45*3d8817e4Smiod {
46*3d8817e4Smiod int mysize, extra_shift;
47*3d8817e4Smiod
48*3d8817e4Smiod if (op->format == FMT_S0)
49*3d8817e4Smiod mysize = 1;
50*3d8817e4Smiod else if (op->format == FMT_S1
51*3d8817e4Smiod || op->format == FMT_D0)
52*3d8817e4Smiod mysize = 2;
53*3d8817e4Smiod else if (op->format == FMT_S2
54*3d8817e4Smiod || op->format == FMT_D1)
55*3d8817e4Smiod mysize = 3;
56*3d8817e4Smiod else if (op->format == FMT_S4)
57*3d8817e4Smiod mysize = 5;
58*3d8817e4Smiod else if (op->format == FMT_D2)
59*3d8817e4Smiod mysize = 4;
60*3d8817e4Smiod else if (op->format == FMT_D3)
61*3d8817e4Smiod mysize = 5;
62*3d8817e4Smiod else if (op->format == FMT_D4)
63*3d8817e4Smiod mysize = 6;
64*3d8817e4Smiod else if (op->format == FMT_D6)
65*3d8817e4Smiod mysize = 3;
66*3d8817e4Smiod else if (op->format == FMT_D7 || op->format == FMT_D10)
67*3d8817e4Smiod mysize = 4;
68*3d8817e4Smiod else if (op->format == FMT_D8)
69*3d8817e4Smiod mysize = 6;
70*3d8817e4Smiod else if (op->format == FMT_D9)
71*3d8817e4Smiod mysize = 7;
72*3d8817e4Smiod else
73*3d8817e4Smiod mysize = 7;
74*3d8817e4Smiod
75*3d8817e4Smiod if ((op->mask & insn) == op->opcode
76*3d8817e4Smiod && size == (unsigned int) mysize
77*3d8817e4Smiod && (op->machine == 0
78*3d8817e4Smiod || (op->machine == AM33_2 && HAVE_AM33_2)
79*3d8817e4Smiod || (op->machine == AM33 && HAVE_AM33)
80*3d8817e4Smiod || (op->machine == AM30 && HAVE_AM30)))
81*3d8817e4Smiod {
82*3d8817e4Smiod const unsigned char *opindex_ptr;
83*3d8817e4Smiod unsigned int nocomma;
84*3d8817e4Smiod int paren = 0;
85*3d8817e4Smiod
86*3d8817e4Smiod if (op->format == FMT_D1 || op->format == FMT_S1)
87*3d8817e4Smiod extra_shift = 8;
88*3d8817e4Smiod else if (op->format == FMT_D2 || op->format == FMT_D4
89*3d8817e4Smiod || op->format == FMT_S2 || op->format == FMT_S4
90*3d8817e4Smiod || op->format == FMT_S6 || op->format == FMT_D5)
91*3d8817e4Smiod extra_shift = 16;
92*3d8817e4Smiod else if (op->format == FMT_D7
93*3d8817e4Smiod || op->format == FMT_D8
94*3d8817e4Smiod || op->format == FMT_D9)
95*3d8817e4Smiod extra_shift = 8;
96*3d8817e4Smiod else
97*3d8817e4Smiod extra_shift = 0;
98*3d8817e4Smiod
99*3d8817e4Smiod if (size == 1 || size == 2)
100*3d8817e4Smiod extension = 0;
101*3d8817e4Smiod
102*3d8817e4Smiod else if (size == 3
103*3d8817e4Smiod && (op->format == FMT_D1
104*3d8817e4Smiod || op->opcode == 0xdf0000
105*3d8817e4Smiod || op->opcode == 0xde0000))
106*3d8817e4Smiod extension = 0;
107*3d8817e4Smiod
108*3d8817e4Smiod else if (size == 3
109*3d8817e4Smiod && op->format == FMT_D6)
110*3d8817e4Smiod extension = 0;
111*3d8817e4Smiod
112*3d8817e4Smiod else if (size == 3)
113*3d8817e4Smiod {
114*3d8817e4Smiod insn &= 0xff0000;
115*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
116*3d8817e4Smiod if (status != 0)
117*3d8817e4Smiod {
118*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
119*3d8817e4Smiod return;
120*3d8817e4Smiod }
121*3d8817e4Smiod
122*3d8817e4Smiod insn |= bfd_getl16 (buffer);
123*3d8817e4Smiod extension = 0;
124*3d8817e4Smiod }
125*3d8817e4Smiod else if (size == 4
126*3d8817e4Smiod && (op->opcode == 0xfaf80000
127*3d8817e4Smiod || op->opcode == 0xfaf00000
128*3d8817e4Smiod || op->opcode == 0xfaf40000))
129*3d8817e4Smiod extension = 0;
130*3d8817e4Smiod
131*3d8817e4Smiod else if (size == 4
132*3d8817e4Smiod && (op->format == FMT_D7
133*3d8817e4Smiod || op->format == FMT_D10))
134*3d8817e4Smiod extension = 0;
135*3d8817e4Smiod
136*3d8817e4Smiod else if (size == 4)
137*3d8817e4Smiod {
138*3d8817e4Smiod insn &= 0xffff0000;
139*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
140*3d8817e4Smiod if (status != 0)
141*3d8817e4Smiod {
142*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
143*3d8817e4Smiod return;
144*3d8817e4Smiod }
145*3d8817e4Smiod
146*3d8817e4Smiod insn |= bfd_getl16 (buffer);
147*3d8817e4Smiod extension = 0;
148*3d8817e4Smiod }
149*3d8817e4Smiod else if (size == 5 && op->opcode == 0xdc000000)
150*3d8817e4Smiod {
151*3d8817e4Smiod unsigned long temp = 0;
152*3d8817e4Smiod
153*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
154*3d8817e4Smiod if (status != 0)
155*3d8817e4Smiod {
156*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
157*3d8817e4Smiod return;
158*3d8817e4Smiod }
159*3d8817e4Smiod temp |= bfd_getl32 (buffer);
160*3d8817e4Smiod
161*3d8817e4Smiod insn &= 0xff000000;
162*3d8817e4Smiod insn |= (temp & 0xffffff00) >> 8;
163*3d8817e4Smiod extension = temp & 0xff;
164*3d8817e4Smiod }
165*3d8817e4Smiod else if (size == 5 && op->format == FMT_D3)
166*3d8817e4Smiod {
167*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
168*3d8817e4Smiod if (status != 0)
169*3d8817e4Smiod {
170*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
171*3d8817e4Smiod return;
172*3d8817e4Smiod }
173*3d8817e4Smiod insn &= 0xffff0000;
174*3d8817e4Smiod insn |= bfd_getl16 (buffer);
175*3d8817e4Smiod
176*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
177*3d8817e4Smiod if (status != 0)
178*3d8817e4Smiod {
179*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
180*3d8817e4Smiod return;
181*3d8817e4Smiod }
182*3d8817e4Smiod extension = *(unsigned char *) buffer;
183*3d8817e4Smiod }
184*3d8817e4Smiod else if (size == 5)
185*3d8817e4Smiod {
186*3d8817e4Smiod unsigned long temp = 0;
187*3d8817e4Smiod
188*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
189*3d8817e4Smiod if (status != 0)
190*3d8817e4Smiod {
191*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
192*3d8817e4Smiod return;
193*3d8817e4Smiod }
194*3d8817e4Smiod temp |= bfd_getl16 (buffer);
195*3d8817e4Smiod
196*3d8817e4Smiod insn &= 0xff0000ff;
197*3d8817e4Smiod insn |= temp << 8;
198*3d8817e4Smiod
199*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
200*3d8817e4Smiod if (status != 0)
201*3d8817e4Smiod {
202*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
203*3d8817e4Smiod return;
204*3d8817e4Smiod }
205*3d8817e4Smiod extension = *(unsigned char *) buffer;
206*3d8817e4Smiod }
207*3d8817e4Smiod else if (size == 6 && op->format == FMT_D8)
208*3d8817e4Smiod {
209*3d8817e4Smiod insn &= 0xffffff00;
210*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
211*3d8817e4Smiod if (status != 0)
212*3d8817e4Smiod {
213*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
214*3d8817e4Smiod return;
215*3d8817e4Smiod }
216*3d8817e4Smiod insn |= *(unsigned char *) buffer;
217*3d8817e4Smiod
218*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
219*3d8817e4Smiod if (status != 0)
220*3d8817e4Smiod {
221*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
222*3d8817e4Smiod return;
223*3d8817e4Smiod }
224*3d8817e4Smiod extension = bfd_getl16 (buffer);
225*3d8817e4Smiod }
226*3d8817e4Smiod else if (size == 6)
227*3d8817e4Smiod {
228*3d8817e4Smiod unsigned long temp = 0;
229*3d8817e4Smiod
230*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
231*3d8817e4Smiod if (status != 0)
232*3d8817e4Smiod {
233*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
234*3d8817e4Smiod return;
235*3d8817e4Smiod }
236*3d8817e4Smiod temp |= bfd_getl32 (buffer);
237*3d8817e4Smiod
238*3d8817e4Smiod insn &= 0xffff0000;
239*3d8817e4Smiod insn |= (temp >> 16) & 0xffff;
240*3d8817e4Smiod extension = temp & 0xffff;
241*3d8817e4Smiod }
242*3d8817e4Smiod else if (size == 7 && op->format == FMT_D9)
243*3d8817e4Smiod {
244*3d8817e4Smiod insn &= 0xffffff00;
245*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
246*3d8817e4Smiod if (status != 0)
247*3d8817e4Smiod {
248*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
249*3d8817e4Smiod return;
250*3d8817e4Smiod }
251*3d8817e4Smiod extension = bfd_getl32 (buffer);
252*3d8817e4Smiod insn |= (extension & 0xff000000) >> 24;
253*3d8817e4Smiod extension &= 0xffffff;
254*3d8817e4Smiod }
255*3d8817e4Smiod else if (size == 7 && op->opcode == 0xdd000000)
256*3d8817e4Smiod {
257*3d8817e4Smiod unsigned long temp = 0;
258*3d8817e4Smiod
259*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
260*3d8817e4Smiod if (status != 0)
261*3d8817e4Smiod {
262*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
263*3d8817e4Smiod return;
264*3d8817e4Smiod }
265*3d8817e4Smiod temp |= bfd_getl32 (buffer);
266*3d8817e4Smiod
267*3d8817e4Smiod insn &= 0xff000000;
268*3d8817e4Smiod insn |= (temp >> 8) & 0xffffff;
269*3d8817e4Smiod extension = (temp & 0xff) << 16;
270*3d8817e4Smiod
271*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
272*3d8817e4Smiod if (status != 0)
273*3d8817e4Smiod {
274*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
275*3d8817e4Smiod return;
276*3d8817e4Smiod }
277*3d8817e4Smiod extension |= bfd_getb16 (buffer);
278*3d8817e4Smiod }
279*3d8817e4Smiod else if (size == 7)
280*3d8817e4Smiod {
281*3d8817e4Smiod unsigned long temp = 0;
282*3d8817e4Smiod
283*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
284*3d8817e4Smiod if (status != 0)
285*3d8817e4Smiod {
286*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
287*3d8817e4Smiod return;
288*3d8817e4Smiod }
289*3d8817e4Smiod temp |= bfd_getl32 (buffer);
290*3d8817e4Smiod
291*3d8817e4Smiod insn &= 0xffff0000;
292*3d8817e4Smiod insn |= (temp >> 16) & 0xffff;
293*3d8817e4Smiod extension = (temp & 0xffff) << 8;
294*3d8817e4Smiod
295*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
296*3d8817e4Smiod if (status != 0)
297*3d8817e4Smiod {
298*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
299*3d8817e4Smiod return;
300*3d8817e4Smiod }
301*3d8817e4Smiod extension |= *(unsigned char *) buffer;
302*3d8817e4Smiod }
303*3d8817e4Smiod
304*3d8817e4Smiod match = 1;
305*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s\t", op->name);
306*3d8817e4Smiod
307*3d8817e4Smiod /* Now print the operands. */
308*3d8817e4Smiod for (opindex_ptr = op->operands, nocomma = 1;
309*3d8817e4Smiod *opindex_ptr != 0;
310*3d8817e4Smiod opindex_ptr++)
311*3d8817e4Smiod {
312*3d8817e4Smiod unsigned long value;
313*3d8817e4Smiod
314*3d8817e4Smiod operand = &mn10300_operands[*opindex_ptr];
315*3d8817e4Smiod
316*3d8817e4Smiod /* If this operand is a PLUS (autoincrement), then do not emit
317*3d8817e4Smiod a comma before emitting the plus. */
318*3d8817e4Smiod if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
319*3d8817e4Smiod nocomma = 1;
320*3d8817e4Smiod
321*3d8817e4Smiod if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
322*3d8817e4Smiod {
323*3d8817e4Smiod unsigned long temp;
324*3d8817e4Smiod
325*3d8817e4Smiod value = insn & ((1 << operand->bits) - 1);
326*3d8817e4Smiod value <<= (32 - operand->bits);
327*3d8817e4Smiod temp = extension >> operand->shift;
328*3d8817e4Smiod temp &= ((1 << (32 - operand->bits)) - 1);
329*3d8817e4Smiod value |= temp;
330*3d8817e4Smiod value = ((value ^ (((unsigned long) 1) << 31))
331*3d8817e4Smiod - (((unsigned long) 1) << 31));
332*3d8817e4Smiod }
333*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
334*3d8817e4Smiod {
335*3d8817e4Smiod unsigned long temp;
336*3d8817e4Smiod
337*3d8817e4Smiod value = insn & ((1 << operand->bits) - 1);
338*3d8817e4Smiod value <<= (24 - operand->bits);
339*3d8817e4Smiod temp = extension >> operand->shift;
340*3d8817e4Smiod temp &= ((1 << (24 - operand->bits)) - 1);
341*3d8817e4Smiod value |= temp;
342*3d8817e4Smiod if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
343*3d8817e4Smiod value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
344*3d8817e4Smiod }
345*3d8817e4Smiod else if ((operand->flags & (MN10300_OPERAND_FSREG
346*3d8817e4Smiod | MN10300_OPERAND_FDREG)))
347*3d8817e4Smiod {
348*3d8817e4Smiod /* See m10300-opc.c just before #define FSM0 for an
349*3d8817e4Smiod explanation of these variables. Note that
350*3d8817e4Smiod FMT-implied shifts are not taken into account for
351*3d8817e4Smiod FP registers. */
352*3d8817e4Smiod unsigned long mask_low, mask_high;
353*3d8817e4Smiod int shl_low, shr_high, shl_high;
354*3d8817e4Smiod
355*3d8817e4Smiod switch (operand->bits)
356*3d8817e4Smiod {
357*3d8817e4Smiod case 5:
358*3d8817e4Smiod /* Handle regular FP registers. */
359*3d8817e4Smiod if (operand->shift >= 0)
360*3d8817e4Smiod {
361*3d8817e4Smiod /* This is an `m' register. */
362*3d8817e4Smiod shl_low = operand->shift;
363*3d8817e4Smiod shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
364*3d8817e4Smiod }
365*3d8817e4Smiod else
366*3d8817e4Smiod {
367*3d8817e4Smiod /* This is an `n' register. */
368*3d8817e4Smiod shl_low = -operand->shift;
369*3d8817e4Smiod shl_high = shl_low / 4;
370*3d8817e4Smiod }
371*3d8817e4Smiod mask_low = 0x0f;
372*3d8817e4Smiod mask_high = 0x10;
373*3d8817e4Smiod shr_high = 4;
374*3d8817e4Smiod break;
375*3d8817e4Smiod
376*3d8817e4Smiod case 3:
377*3d8817e4Smiod /* Handle accumulators. */
378*3d8817e4Smiod shl_low = -operand->shift;
379*3d8817e4Smiod shl_high = 0;
380*3d8817e4Smiod mask_low = 0x03;
381*3d8817e4Smiod mask_high = 0x04;
382*3d8817e4Smiod shr_high = 2;
383*3d8817e4Smiod break;
384*3d8817e4Smiod
385*3d8817e4Smiod default:
386*3d8817e4Smiod abort ();
387*3d8817e4Smiod }
388*3d8817e4Smiod value = ((((insn >> shl_high) << shr_high) & mask_high)
389*3d8817e4Smiod | ((insn >> shl_low) & mask_low));
390*3d8817e4Smiod }
391*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
392*3d8817e4Smiod value = ((extension >> (operand->shift))
393*3d8817e4Smiod & ((1 << operand->bits) - 1));
394*3d8817e4Smiod
395*3d8817e4Smiod else
396*3d8817e4Smiod value = ((insn >> (operand->shift))
397*3d8817e4Smiod & ((1 << operand->bits) - 1));
398*3d8817e4Smiod
399*3d8817e4Smiod if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
400*3d8817e4Smiod /* These are properly extended by the code above. */
401*3d8817e4Smiod && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
402*3d8817e4Smiod value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
403*3d8817e4Smiod - (((unsigned long) 1) << (operand->bits - 1)));
404*3d8817e4Smiod
405*3d8817e4Smiod if (!nocomma
406*3d8817e4Smiod && (!paren
407*3d8817e4Smiod || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
408*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",");
409*3d8817e4Smiod
410*3d8817e4Smiod nocomma = 0;
411*3d8817e4Smiod
412*3d8817e4Smiod if ((operand->flags & MN10300_OPERAND_DREG) != 0)
413*3d8817e4Smiod {
414*3d8817e4Smiod value = ((insn >> (operand->shift + extra_shift))
415*3d8817e4Smiod & ((1 << operand->bits) - 1));
416*3d8817e4Smiod (*info->fprintf_func) (info->stream, "d%d", (int) value);
417*3d8817e4Smiod }
418*3d8817e4Smiod
419*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
420*3d8817e4Smiod {
421*3d8817e4Smiod value = ((insn >> (operand->shift + extra_shift))
422*3d8817e4Smiod & ((1 << operand->bits) - 1));
423*3d8817e4Smiod (*info->fprintf_func) (info->stream, "a%d", (int) value);
424*3d8817e4Smiod }
425*3d8817e4Smiod
426*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_SP) != 0)
427*3d8817e4Smiod (*info->fprintf_func) (info->stream, "sp");
428*3d8817e4Smiod
429*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
430*3d8817e4Smiod (*info->fprintf_func) (info->stream, "psw");
431*3d8817e4Smiod
432*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
433*3d8817e4Smiod (*info->fprintf_func) (info->stream, "mdr");
434*3d8817e4Smiod
435*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
436*3d8817e4Smiod {
437*3d8817e4Smiod value = ((insn >> (operand->shift + extra_shift))
438*3d8817e4Smiod & ((1 << operand->bits) - 1));
439*3d8817e4Smiod if (value < 8)
440*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d", (int) value);
441*3d8817e4Smiod else if (value < 12)
442*3d8817e4Smiod (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
443*3d8817e4Smiod else
444*3d8817e4Smiod (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
445*3d8817e4Smiod }
446*3d8817e4Smiod
447*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
448*3d8817e4Smiod {
449*3d8817e4Smiod value = ((insn >> (operand->shift + extra_shift))
450*3d8817e4Smiod & ((1 << operand->bits) - 1));
451*3d8817e4Smiod if (value == 0)
452*3d8817e4Smiod (*info->fprintf_func) (info->stream, "sp");
453*3d8817e4Smiod else
454*3d8817e4Smiod (*info->fprintf_func) (info->stream, "xr%d", (int) value);
455*3d8817e4Smiod }
456*3d8817e4Smiod
457*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
458*3d8817e4Smiod (*info->fprintf_func) (info->stream, "fs%d", (int) value);
459*3d8817e4Smiod
460*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
461*3d8817e4Smiod (*info->fprintf_func) (info->stream, "fd%d", (int) value);
462*3d8817e4Smiod
463*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
464*3d8817e4Smiod (*info->fprintf_func) (info->stream, "fpcr");
465*3d8817e4Smiod
466*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_USP) != 0)
467*3d8817e4Smiod (*info->fprintf_func) (info->stream, "usp");
468*3d8817e4Smiod
469*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
470*3d8817e4Smiod (*info->fprintf_func) (info->stream, "ssp");
471*3d8817e4Smiod
472*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
473*3d8817e4Smiod (*info->fprintf_func) (info->stream, "msp");
474*3d8817e4Smiod
475*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_PC) != 0)
476*3d8817e4Smiod (*info->fprintf_func) (info->stream, "pc");
477*3d8817e4Smiod
478*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
479*3d8817e4Smiod (*info->fprintf_func) (info->stream, "epsw");
480*3d8817e4Smiod
481*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
482*3d8817e4Smiod (*info->fprintf_func) (info->stream, "+");
483*3d8817e4Smiod
484*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
485*3d8817e4Smiod {
486*3d8817e4Smiod if (paren)
487*3d8817e4Smiod (*info->fprintf_func) (info->stream, ")");
488*3d8817e4Smiod else
489*3d8817e4Smiod {
490*3d8817e4Smiod (*info->fprintf_func) (info->stream, "(");
491*3d8817e4Smiod nocomma = 1;
492*3d8817e4Smiod }
493*3d8817e4Smiod paren = !paren;
494*3d8817e4Smiod }
495*3d8817e4Smiod
496*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
497*3d8817e4Smiod (*info->print_address_func) ((long) value + memaddr, info);
498*3d8817e4Smiod
499*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
500*3d8817e4Smiod (*info->print_address_func) (value, info);
501*3d8817e4Smiod
502*3d8817e4Smiod else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
503*3d8817e4Smiod {
504*3d8817e4Smiod int comma = 0;
505*3d8817e4Smiod
506*3d8817e4Smiod (*info->fprintf_func) (info->stream, "[");
507*3d8817e4Smiod if (value & 0x80)
508*3d8817e4Smiod {
509*3d8817e4Smiod (*info->fprintf_func) (info->stream, "d2");
510*3d8817e4Smiod comma = 1;
511*3d8817e4Smiod }
512*3d8817e4Smiod
513*3d8817e4Smiod if (value & 0x40)
514*3d8817e4Smiod {
515*3d8817e4Smiod if (comma)
516*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",");
517*3d8817e4Smiod (*info->fprintf_func) (info->stream, "d3");
518*3d8817e4Smiod comma = 1;
519*3d8817e4Smiod }
520*3d8817e4Smiod
521*3d8817e4Smiod if (value & 0x20)
522*3d8817e4Smiod {
523*3d8817e4Smiod if (comma)
524*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",");
525*3d8817e4Smiod (*info->fprintf_func) (info->stream, "a2");
526*3d8817e4Smiod comma = 1;
527*3d8817e4Smiod }
528*3d8817e4Smiod
529*3d8817e4Smiod if (value & 0x10)
530*3d8817e4Smiod {
531*3d8817e4Smiod if (comma)
532*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",");
533*3d8817e4Smiod (*info->fprintf_func) (info->stream, "a3");
534*3d8817e4Smiod comma = 1;
535*3d8817e4Smiod }
536*3d8817e4Smiod
537*3d8817e4Smiod if (value & 0x08)
538*3d8817e4Smiod {
539*3d8817e4Smiod if (comma)
540*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",");
541*3d8817e4Smiod (*info->fprintf_func) (info->stream, "other");
542*3d8817e4Smiod comma = 1;
543*3d8817e4Smiod }
544*3d8817e4Smiod
545*3d8817e4Smiod if (value & 0x04)
546*3d8817e4Smiod {
547*3d8817e4Smiod if (comma)
548*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",");
549*3d8817e4Smiod (*info->fprintf_func) (info->stream, "exreg0");
550*3d8817e4Smiod comma = 1;
551*3d8817e4Smiod }
552*3d8817e4Smiod if (value & 0x02)
553*3d8817e4Smiod {
554*3d8817e4Smiod if (comma)
555*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",");
556*3d8817e4Smiod (*info->fprintf_func) (info->stream, "exreg1");
557*3d8817e4Smiod comma = 1;
558*3d8817e4Smiod }
559*3d8817e4Smiod if (value & 0x01)
560*3d8817e4Smiod {
561*3d8817e4Smiod if (comma)
562*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",");
563*3d8817e4Smiod (*info->fprintf_func) (info->stream, "exother");
564*3d8817e4Smiod comma = 1;
565*3d8817e4Smiod }
566*3d8817e4Smiod (*info->fprintf_func) (info->stream, "]");
567*3d8817e4Smiod }
568*3d8817e4Smiod
569*3d8817e4Smiod else
570*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%ld", (long) value);
571*3d8817e4Smiod }
572*3d8817e4Smiod /* All done. */
573*3d8817e4Smiod break;
574*3d8817e4Smiod }
575*3d8817e4Smiod op++;
576*3d8817e4Smiod }
577*3d8817e4Smiod
578*3d8817e4Smiod if (!match)
579*3d8817e4Smiod /* xgettext:c-format */
580*3d8817e4Smiod (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
581*3d8817e4Smiod }
582*3d8817e4Smiod
583*3d8817e4Smiod int
print_insn_mn10300(bfd_vma memaddr,struct disassemble_info * info)584*3d8817e4Smiod print_insn_mn10300 (bfd_vma memaddr, struct disassemble_info *info)
585*3d8817e4Smiod {
586*3d8817e4Smiod int status;
587*3d8817e4Smiod bfd_byte buffer[4];
588*3d8817e4Smiod unsigned long insn;
589*3d8817e4Smiod unsigned int consume;
590*3d8817e4Smiod
591*3d8817e4Smiod /* First figure out how big the opcode is. */
592*3d8817e4Smiod status = (*info->read_memory_func) (memaddr, buffer, 1, info);
593*3d8817e4Smiod if (status != 0)
594*3d8817e4Smiod {
595*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
596*3d8817e4Smiod return -1;
597*3d8817e4Smiod }
598*3d8817e4Smiod insn = *(unsigned char *) buffer;
599*3d8817e4Smiod
600*3d8817e4Smiod /* These are one byte insns. */
601*3d8817e4Smiod if ((insn & 0xf3) == 0x00
602*3d8817e4Smiod || (insn & 0xf0) == 0x10
603*3d8817e4Smiod || (insn & 0xfc) == 0x3c
604*3d8817e4Smiod || (insn & 0xf3) == 0x41
605*3d8817e4Smiod || (insn & 0xf3) == 0x40
606*3d8817e4Smiod || (insn & 0xfc) == 0x50
607*3d8817e4Smiod || (insn & 0xfc) == 0x54
608*3d8817e4Smiod || (insn & 0xf0) == 0x60
609*3d8817e4Smiod || (insn & 0xf0) == 0x70
610*3d8817e4Smiod || ((insn & 0xf0) == 0x80
611*3d8817e4Smiod && (insn & 0x0c) >> 2 != (insn & 0x03))
612*3d8817e4Smiod || ((insn & 0xf0) == 0x90
613*3d8817e4Smiod && (insn & 0x0c) >> 2 != (insn & 0x03))
614*3d8817e4Smiod || ((insn & 0xf0) == 0xa0
615*3d8817e4Smiod && (insn & 0x0c) >> 2 != (insn & 0x03))
616*3d8817e4Smiod || ((insn & 0xf0) == 0xb0
617*3d8817e4Smiod && (insn & 0x0c) >> 2 != (insn & 0x03))
618*3d8817e4Smiod || (insn & 0xff) == 0xcb
619*3d8817e4Smiod || (insn & 0xfc) == 0xd0
620*3d8817e4Smiod || (insn & 0xfc) == 0xd4
621*3d8817e4Smiod || (insn & 0xfc) == 0xd8
622*3d8817e4Smiod || (insn & 0xf0) == 0xe0
623*3d8817e4Smiod || (insn & 0xff) == 0xff)
624*3d8817e4Smiod {
625*3d8817e4Smiod consume = 1;
626*3d8817e4Smiod }
627*3d8817e4Smiod
628*3d8817e4Smiod /* These are two byte insns. */
629*3d8817e4Smiod else if ((insn & 0xf0) == 0x80
630*3d8817e4Smiod || (insn & 0xf0) == 0x90
631*3d8817e4Smiod || (insn & 0xf0) == 0xa0
632*3d8817e4Smiod || (insn & 0xf0) == 0xb0
633*3d8817e4Smiod || (insn & 0xfc) == 0x20
634*3d8817e4Smiod || (insn & 0xfc) == 0x28
635*3d8817e4Smiod || (insn & 0xf3) == 0x43
636*3d8817e4Smiod || (insn & 0xf3) == 0x42
637*3d8817e4Smiod || (insn & 0xfc) == 0x58
638*3d8817e4Smiod || (insn & 0xfc) == 0x5c
639*3d8817e4Smiod || ((insn & 0xf0) == 0xc0
640*3d8817e4Smiod && (insn & 0xff) != 0xcb
641*3d8817e4Smiod && (insn & 0xff) != 0xcc
642*3d8817e4Smiod && (insn & 0xff) != 0xcd)
643*3d8817e4Smiod || (insn & 0xff) == 0xf0
644*3d8817e4Smiod || (insn & 0xff) == 0xf1
645*3d8817e4Smiod || (insn & 0xff) == 0xf2
646*3d8817e4Smiod || (insn & 0xff) == 0xf3
647*3d8817e4Smiod || (insn & 0xff) == 0xf4
648*3d8817e4Smiod || (insn & 0xff) == 0xf5
649*3d8817e4Smiod || (insn & 0xff) == 0xf6)
650*3d8817e4Smiod {
651*3d8817e4Smiod status = (*info->read_memory_func) (memaddr, buffer, 2, info);
652*3d8817e4Smiod if (status != 0)
653*3d8817e4Smiod {
654*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
655*3d8817e4Smiod return -1;
656*3d8817e4Smiod }
657*3d8817e4Smiod insn = bfd_getb16 (buffer);
658*3d8817e4Smiod consume = 2;
659*3d8817e4Smiod }
660*3d8817e4Smiod
661*3d8817e4Smiod /* These are three byte insns. */
662*3d8817e4Smiod else if ((insn & 0xff) == 0xf8
663*3d8817e4Smiod || (insn & 0xff) == 0xcc
664*3d8817e4Smiod || (insn & 0xff) == 0xf9
665*3d8817e4Smiod || (insn & 0xf3) == 0x01
666*3d8817e4Smiod || (insn & 0xf3) == 0x02
667*3d8817e4Smiod || (insn & 0xf3) == 0x03
668*3d8817e4Smiod || (insn & 0xfc) == 0x24
669*3d8817e4Smiod || (insn & 0xfc) == 0x2c
670*3d8817e4Smiod || (insn & 0xfc) == 0x30
671*3d8817e4Smiod || (insn & 0xfc) == 0x34
672*3d8817e4Smiod || (insn & 0xfc) == 0x38
673*3d8817e4Smiod || (insn & 0xff) == 0xde
674*3d8817e4Smiod || (insn & 0xff) == 0xdf
675*3d8817e4Smiod || (insn & 0xff) == 0xf9
676*3d8817e4Smiod || (insn & 0xff) == 0xcc)
677*3d8817e4Smiod {
678*3d8817e4Smiod status = (*info->read_memory_func) (memaddr, buffer, 2, info);
679*3d8817e4Smiod if (status != 0)
680*3d8817e4Smiod {
681*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
682*3d8817e4Smiod return -1;
683*3d8817e4Smiod }
684*3d8817e4Smiod insn = bfd_getb16 (buffer);
685*3d8817e4Smiod insn <<= 8;
686*3d8817e4Smiod status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
687*3d8817e4Smiod if (status != 0)
688*3d8817e4Smiod {
689*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
690*3d8817e4Smiod return -1;
691*3d8817e4Smiod }
692*3d8817e4Smiod insn |= *(unsigned char *) buffer;
693*3d8817e4Smiod consume = 3;
694*3d8817e4Smiod }
695*3d8817e4Smiod
696*3d8817e4Smiod /* These are four byte insns. */
697*3d8817e4Smiod else if ((insn & 0xff) == 0xfa
698*3d8817e4Smiod || (insn & 0xff) == 0xf7
699*3d8817e4Smiod || (insn & 0xff) == 0xfb)
700*3d8817e4Smiod {
701*3d8817e4Smiod status = (*info->read_memory_func) (memaddr, buffer, 4, info);
702*3d8817e4Smiod if (status != 0)
703*3d8817e4Smiod {
704*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
705*3d8817e4Smiod return -1;
706*3d8817e4Smiod }
707*3d8817e4Smiod insn = bfd_getb32 (buffer);
708*3d8817e4Smiod consume = 4;
709*3d8817e4Smiod }
710*3d8817e4Smiod
711*3d8817e4Smiod /* These are five byte insns. */
712*3d8817e4Smiod else if ((insn & 0xff) == 0xcd
713*3d8817e4Smiod || (insn & 0xff) == 0xdc)
714*3d8817e4Smiod {
715*3d8817e4Smiod status = (*info->read_memory_func) (memaddr, buffer, 4, info);
716*3d8817e4Smiod if (status != 0)
717*3d8817e4Smiod {
718*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
719*3d8817e4Smiod return -1;
720*3d8817e4Smiod }
721*3d8817e4Smiod insn = bfd_getb32 (buffer);
722*3d8817e4Smiod consume = 5;
723*3d8817e4Smiod }
724*3d8817e4Smiod
725*3d8817e4Smiod /* These are six byte insns. */
726*3d8817e4Smiod else if ((insn & 0xff) == 0xfd
727*3d8817e4Smiod || (insn & 0xff) == 0xfc)
728*3d8817e4Smiod {
729*3d8817e4Smiod status = (*info->read_memory_func) (memaddr, buffer, 4, info);
730*3d8817e4Smiod if (status != 0)
731*3d8817e4Smiod {
732*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
733*3d8817e4Smiod return -1;
734*3d8817e4Smiod }
735*3d8817e4Smiod
736*3d8817e4Smiod insn = bfd_getb32 (buffer);
737*3d8817e4Smiod consume = 6;
738*3d8817e4Smiod }
739*3d8817e4Smiod
740*3d8817e4Smiod /* Else its a seven byte insns (in theory). */
741*3d8817e4Smiod else
742*3d8817e4Smiod {
743*3d8817e4Smiod status = (*info->read_memory_func) (memaddr, buffer, 4, info);
744*3d8817e4Smiod if (status != 0)
745*3d8817e4Smiod {
746*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
747*3d8817e4Smiod return -1;
748*3d8817e4Smiod }
749*3d8817e4Smiod
750*3d8817e4Smiod insn = bfd_getb32 (buffer);
751*3d8817e4Smiod consume = 7;
752*3d8817e4Smiod /* Handle the 5-byte extended instruction codes. */
753*3d8817e4Smiod if ((insn & 0xfff80000) == 0xfe800000)
754*3d8817e4Smiod consume = 5;
755*3d8817e4Smiod }
756*3d8817e4Smiod
757*3d8817e4Smiod disassemble (memaddr, info, insn, consume);
758*3d8817e4Smiod
759*3d8817e4Smiod return consume;
760*3d8817e4Smiod }
761