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