1*3d8817e4Smiod /* Print Motorola 68k instructions.
2*3d8817e4Smiod    Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3*3d8817e4Smiod    1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4*3d8817e4Smiod    Free Software Foundation, Inc.
5*3d8817e4Smiod 
6*3d8817e4Smiod    This file is free software; you can redistribute it and/or modify
7*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
8*3d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
9*3d8817e4Smiod    (at your option) any later version.
10*3d8817e4Smiod 
11*3d8817e4Smiod    This program is distributed in the hope that it will be useful,
12*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*3d8817e4Smiod    GNU General Public License for more details.
15*3d8817e4Smiod 
16*3d8817e4Smiod    You should have received a copy of the GNU General Public License
17*3d8817e4Smiod    along with this program; if not, write to the Free Software
18*3d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19*3d8817e4Smiod    MA 02110-1301, USA.  */
20*3d8817e4Smiod 
21*3d8817e4Smiod #include "sysdep.h"
22*3d8817e4Smiod #include "dis-asm.h"
23*3d8817e4Smiod #include "floatformat.h"
24*3d8817e4Smiod #include "libiberty.h"
25*3d8817e4Smiod #include "opintl.h"
26*3d8817e4Smiod 
27*3d8817e4Smiod #include "opcode/m68k.h"
28*3d8817e4Smiod 
29*3d8817e4Smiod /* Local function prototypes.  */
30*3d8817e4Smiod 
31*3d8817e4Smiod const char * const fpcr_names[] =
32*3d8817e4Smiod {
33*3d8817e4Smiod   "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
34*3d8817e4Smiod   "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"
35*3d8817e4Smiod };
36*3d8817e4Smiod 
37*3d8817e4Smiod static char *const reg_names[] =
38*3d8817e4Smiod {
39*3d8817e4Smiod   "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
40*3d8817e4Smiod   "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
41*3d8817e4Smiod   "%ps", "%pc"
42*3d8817e4Smiod };
43*3d8817e4Smiod 
44*3d8817e4Smiod /* Name of register halves for MAC/EMAC.
45*3d8817e4Smiod    Seperate from reg_names since 'spu', 'fpl' look weird.  */
46*3d8817e4Smiod static char *const reg_half_names[] =
47*3d8817e4Smiod {
48*3d8817e4Smiod   "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
49*3d8817e4Smiod   "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
50*3d8817e4Smiod   "%ps", "%pc"
51*3d8817e4Smiod };
52*3d8817e4Smiod 
53*3d8817e4Smiod /* Sign-extend an (unsigned char).  */
54*3d8817e4Smiod #if __STDC__ == 1
55*3d8817e4Smiod #define COERCE_SIGNED_CHAR(ch) ((signed char) (ch))
56*3d8817e4Smiod #else
57*3d8817e4Smiod #define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
58*3d8817e4Smiod #endif
59*3d8817e4Smiod 
60*3d8817e4Smiod /* Get a 1 byte signed integer.  */
61*3d8817e4Smiod #define NEXTBYTE(p)  (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
62*3d8817e4Smiod 
63*3d8817e4Smiod /* Get a 2 byte signed integer.  */
64*3d8817e4Smiod #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
65*3d8817e4Smiod #define NEXTWORD(p)  \
66*3d8817e4Smiod   (p += 2, FETCH_DATA (info, p), \
67*3d8817e4Smiod    COERCE16 ((p[-2] << 8) + p[-1]))
68*3d8817e4Smiod 
69*3d8817e4Smiod /* Get a 4 byte signed integer.  */
70*3d8817e4Smiod #define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
71*3d8817e4Smiod #define NEXTLONG(p)  \
72*3d8817e4Smiod   (p += 4, FETCH_DATA (info, p), \
73*3d8817e4Smiod    (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])))
74*3d8817e4Smiod 
75*3d8817e4Smiod /* Get a 4 byte unsigned integer.  */
76*3d8817e4Smiod #define NEXTULONG(p)  \
77*3d8817e4Smiod   (p += 4, FETCH_DATA (info, p), \
78*3d8817e4Smiod    (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]))
79*3d8817e4Smiod 
80*3d8817e4Smiod /* Get a single precision float.  */
81*3d8817e4Smiod #define NEXTSINGLE(val, p) \
82*3d8817e4Smiod   (p += 4, FETCH_DATA (info, p), \
83*3d8817e4Smiod    floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val))
84*3d8817e4Smiod 
85*3d8817e4Smiod /* Get a double precision float.  */
86*3d8817e4Smiod #define NEXTDOUBLE(val, p) \
87*3d8817e4Smiod   (p += 8, FETCH_DATA (info, p), \
88*3d8817e4Smiod    floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val))
89*3d8817e4Smiod 
90*3d8817e4Smiod /* Get an extended precision float.  */
91*3d8817e4Smiod #define NEXTEXTEND(val, p) \
92*3d8817e4Smiod   (p += 12, FETCH_DATA (info, p), \
93*3d8817e4Smiod    floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val))
94*3d8817e4Smiod 
95*3d8817e4Smiod /* Need a function to convert from packed to double
96*3d8817e4Smiod    precision.   Actually, it's easier to print a
97*3d8817e4Smiod    packed number than a double anyway, so maybe
98*3d8817e4Smiod    there should be a special case to handle this... */
99*3d8817e4Smiod #define NEXTPACKED(p) \
100*3d8817e4Smiod   (p += 12, FETCH_DATA (info, p), 0.0)
101*3d8817e4Smiod 
102*3d8817e4Smiod /* Maximum length of an instruction.  */
103*3d8817e4Smiod #define MAXLEN 22
104*3d8817e4Smiod 
105*3d8817e4Smiod #include <setjmp.h>
106*3d8817e4Smiod 
107*3d8817e4Smiod struct private
108*3d8817e4Smiod {
109*3d8817e4Smiod   /* Points to first byte not fetched.  */
110*3d8817e4Smiod   bfd_byte *max_fetched;
111*3d8817e4Smiod   bfd_byte the_buffer[MAXLEN];
112*3d8817e4Smiod   bfd_vma insn_start;
113*3d8817e4Smiod   jmp_buf bailout;
114*3d8817e4Smiod };
115*3d8817e4Smiod 
116*3d8817e4Smiod /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
117*3d8817e4Smiod    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
118*3d8817e4Smiod    on error.  */
119*3d8817e4Smiod #define FETCH_DATA(info, addr) \
120*3d8817e4Smiod   ((addr) <= ((struct private *) (info->private_data))->max_fetched \
121*3d8817e4Smiod    ? 1 : fetch_data ((info), (addr)))
122*3d8817e4Smiod 
123*3d8817e4Smiod static int
fetch_data(struct disassemble_info * info,bfd_byte * addr)124*3d8817e4Smiod fetch_data (struct disassemble_info *info, bfd_byte *addr)
125*3d8817e4Smiod {
126*3d8817e4Smiod   int status;
127*3d8817e4Smiod   struct private *priv = (struct private *)info->private_data;
128*3d8817e4Smiod   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
129*3d8817e4Smiod 
130*3d8817e4Smiod   status = (*info->read_memory_func) (start,
131*3d8817e4Smiod 				      priv->max_fetched,
132*3d8817e4Smiod 				      addr - priv->max_fetched,
133*3d8817e4Smiod 				      info);
134*3d8817e4Smiod   if (status != 0)
135*3d8817e4Smiod     {
136*3d8817e4Smiod       (*info->memory_error_func) (status, start, info);
137*3d8817e4Smiod       longjmp (priv->bailout, 1);
138*3d8817e4Smiod     }
139*3d8817e4Smiod   else
140*3d8817e4Smiod     priv->max_fetched = addr;
141*3d8817e4Smiod   return 1;
142*3d8817e4Smiod }
143*3d8817e4Smiod 
144*3d8817e4Smiod /* This function is used to print to the bit-bucket.  */
145*3d8817e4Smiod static int
dummy_printer(FILE * file ATTRIBUTE_UNUSED,const char * format ATTRIBUTE_UNUSED,...)146*3d8817e4Smiod dummy_printer (FILE *file ATTRIBUTE_UNUSED,
147*3d8817e4Smiod 	       const char *format ATTRIBUTE_UNUSED,
148*3d8817e4Smiod 	       ...)
149*3d8817e4Smiod {
150*3d8817e4Smiod   return 0;
151*3d8817e4Smiod }
152*3d8817e4Smiod 
153*3d8817e4Smiod static void
dummy_print_address(bfd_vma vma ATTRIBUTE_UNUSED,struct disassemble_info * info ATTRIBUTE_UNUSED)154*3d8817e4Smiod dummy_print_address (bfd_vma vma ATTRIBUTE_UNUSED,
155*3d8817e4Smiod 		     struct disassemble_info *info ATTRIBUTE_UNUSED)
156*3d8817e4Smiod {
157*3d8817e4Smiod }
158*3d8817e4Smiod 
159*3d8817e4Smiod /* Fetch BITS bits from a position in the instruction specified by CODE.
160*3d8817e4Smiod    CODE is a "place to put an argument", or 'x' for a destination
161*3d8817e4Smiod    that is a general address (mode and register).
162*3d8817e4Smiod    BUFFER contains the instruction.  */
163*3d8817e4Smiod 
164*3d8817e4Smiod static int
fetch_arg(unsigned char * buffer,int code,int bits,disassemble_info * info)165*3d8817e4Smiod fetch_arg (unsigned char *buffer,
166*3d8817e4Smiod 	   int code,
167*3d8817e4Smiod 	   int bits,
168*3d8817e4Smiod 	   disassemble_info *info)
169*3d8817e4Smiod {
170*3d8817e4Smiod   int val = 0;
171*3d8817e4Smiod 
172*3d8817e4Smiod   switch (code)
173*3d8817e4Smiod     {
174*3d8817e4Smiod     case '/': /* MAC/EMAC mask bit.  */
175*3d8817e4Smiod       val = buffer[3] >> 5;
176*3d8817e4Smiod       break;
177*3d8817e4Smiod 
178*3d8817e4Smiod     case 'G': /* EMAC ACC load.  */
179*3d8817e4Smiod       val = ((buffer[3] >> 3) & 0x2) | ((~buffer[1] >> 7) & 0x1);
180*3d8817e4Smiod       break;
181*3d8817e4Smiod 
182*3d8817e4Smiod     case 'H': /* EMAC ACC !load.  */
183*3d8817e4Smiod       val = ((buffer[3] >> 3) & 0x2) | ((buffer[1] >> 7) & 0x1);
184*3d8817e4Smiod       break;
185*3d8817e4Smiod 
186*3d8817e4Smiod     case ']': /* EMAC ACCEXT bit.  */
187*3d8817e4Smiod       val = buffer[0] >> 2;
188*3d8817e4Smiod       break;
189*3d8817e4Smiod 
190*3d8817e4Smiod     case 'I': /* MAC/EMAC scale factor.  */
191*3d8817e4Smiod       val = buffer[2] >> 1;
192*3d8817e4Smiod       break;
193*3d8817e4Smiod 
194*3d8817e4Smiod     case 'F': /* EMAC ACCx.  */
195*3d8817e4Smiod       val = buffer[0] >> 1;
196*3d8817e4Smiod       break;
197*3d8817e4Smiod 
198*3d8817e4Smiod     case 'f':
199*3d8817e4Smiod       val = buffer[1];
200*3d8817e4Smiod       break;
201*3d8817e4Smiod 
202*3d8817e4Smiod     case 's':
203*3d8817e4Smiod       val = buffer[1];
204*3d8817e4Smiod       break;
205*3d8817e4Smiod 
206*3d8817e4Smiod     case 'd':			/* Destination, for register or quick.  */
207*3d8817e4Smiod       val = (buffer[0] << 8) + buffer[1];
208*3d8817e4Smiod       val >>= 9;
209*3d8817e4Smiod       break;
210*3d8817e4Smiod 
211*3d8817e4Smiod     case 'x':			/* Destination, for general arg.  */
212*3d8817e4Smiod       val = (buffer[0] << 8) + buffer[1];
213*3d8817e4Smiod       val >>= 6;
214*3d8817e4Smiod       break;
215*3d8817e4Smiod 
216*3d8817e4Smiod     case 'k':
217*3d8817e4Smiod       FETCH_DATA (info, buffer + 3);
218*3d8817e4Smiod       val = (buffer[3] >> 4);
219*3d8817e4Smiod       break;
220*3d8817e4Smiod 
221*3d8817e4Smiod     case 'C':
222*3d8817e4Smiod       FETCH_DATA (info, buffer + 3);
223*3d8817e4Smiod       val = buffer[3];
224*3d8817e4Smiod       break;
225*3d8817e4Smiod 
226*3d8817e4Smiod     case '1':
227*3d8817e4Smiod       FETCH_DATA (info, buffer + 3);
228*3d8817e4Smiod       val = (buffer[2] << 8) + buffer[3];
229*3d8817e4Smiod       val >>= 12;
230*3d8817e4Smiod       break;
231*3d8817e4Smiod 
232*3d8817e4Smiod     case '2':
233*3d8817e4Smiod       FETCH_DATA (info, buffer + 3);
234*3d8817e4Smiod       val = (buffer[2] << 8) + buffer[3];
235*3d8817e4Smiod       val >>= 6;
236*3d8817e4Smiod       break;
237*3d8817e4Smiod 
238*3d8817e4Smiod     case '3':
239*3d8817e4Smiod     case 'j':
240*3d8817e4Smiod       FETCH_DATA (info, buffer + 3);
241*3d8817e4Smiod       val = (buffer[2] << 8) + buffer[3];
242*3d8817e4Smiod       break;
243*3d8817e4Smiod 
244*3d8817e4Smiod     case '4':
245*3d8817e4Smiod       FETCH_DATA (info, buffer + 5);
246*3d8817e4Smiod       val = (buffer[4] << 8) + buffer[5];
247*3d8817e4Smiod       val >>= 12;
248*3d8817e4Smiod       break;
249*3d8817e4Smiod 
250*3d8817e4Smiod     case '5':
251*3d8817e4Smiod       FETCH_DATA (info, buffer + 5);
252*3d8817e4Smiod       val = (buffer[4] << 8) + buffer[5];
253*3d8817e4Smiod       val >>= 6;
254*3d8817e4Smiod       break;
255*3d8817e4Smiod 
256*3d8817e4Smiod     case '6':
257*3d8817e4Smiod       FETCH_DATA (info, buffer + 5);
258*3d8817e4Smiod       val = (buffer[4] << 8) + buffer[5];
259*3d8817e4Smiod       break;
260*3d8817e4Smiod 
261*3d8817e4Smiod     case '7':
262*3d8817e4Smiod       FETCH_DATA (info, buffer + 3);
263*3d8817e4Smiod       val = (buffer[2] << 8) + buffer[3];
264*3d8817e4Smiod       val >>= 7;
265*3d8817e4Smiod       break;
266*3d8817e4Smiod 
267*3d8817e4Smiod     case '8':
268*3d8817e4Smiod       FETCH_DATA (info, buffer + 3);
269*3d8817e4Smiod       val = (buffer[2] << 8) + buffer[3];
270*3d8817e4Smiod       val >>= 10;
271*3d8817e4Smiod       break;
272*3d8817e4Smiod 
273*3d8817e4Smiod     case '9':
274*3d8817e4Smiod       FETCH_DATA (info, buffer + 3);
275*3d8817e4Smiod       val = (buffer[2] << 8) + buffer[3];
276*3d8817e4Smiod       val >>= 5;
277*3d8817e4Smiod       break;
278*3d8817e4Smiod 
279*3d8817e4Smiod     case 'e':
280*3d8817e4Smiod       val = (buffer[1] >> 6);
281*3d8817e4Smiod       break;
282*3d8817e4Smiod 
283*3d8817e4Smiod     case 'm':
284*3d8817e4Smiod       val = (buffer[1] & 0x40 ? 0x8 : 0)
285*3d8817e4Smiod 	| ((buffer[0] >> 1) & 0x7)
286*3d8817e4Smiod 	| (buffer[3] & 0x80 ? 0x10 : 0);
287*3d8817e4Smiod       break;
288*3d8817e4Smiod 
289*3d8817e4Smiod     case 'n':
290*3d8817e4Smiod       val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7);
291*3d8817e4Smiod       break;
292*3d8817e4Smiod 
293*3d8817e4Smiod     case 'o':
294*3d8817e4Smiod       val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0);
295*3d8817e4Smiod       break;
296*3d8817e4Smiod 
297*3d8817e4Smiod     case 'M':
298*3d8817e4Smiod       val = (buffer[1] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
299*3d8817e4Smiod       break;
300*3d8817e4Smiod 
301*3d8817e4Smiod     case 'N':
302*3d8817e4Smiod       val = (buffer[3] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
303*3d8817e4Smiod       break;
304*3d8817e4Smiod 
305*3d8817e4Smiod     case 'h':
306*3d8817e4Smiod       val = buffer[2] >> 2;
307*3d8817e4Smiod       break;
308*3d8817e4Smiod 
309*3d8817e4Smiod     default:
310*3d8817e4Smiod       abort ();
311*3d8817e4Smiod     }
312*3d8817e4Smiod 
313*3d8817e4Smiod   switch (bits)
314*3d8817e4Smiod     {
315*3d8817e4Smiod     case 1:
316*3d8817e4Smiod       return val & 1;
317*3d8817e4Smiod     case 2:
318*3d8817e4Smiod       return val & 3;
319*3d8817e4Smiod     case 3:
320*3d8817e4Smiod       return val & 7;
321*3d8817e4Smiod     case 4:
322*3d8817e4Smiod       return val & 017;
323*3d8817e4Smiod     case 5:
324*3d8817e4Smiod       return val & 037;
325*3d8817e4Smiod     case 6:
326*3d8817e4Smiod       return val & 077;
327*3d8817e4Smiod     case 7:
328*3d8817e4Smiod       return val & 0177;
329*3d8817e4Smiod     case 8:
330*3d8817e4Smiod       return val & 0377;
331*3d8817e4Smiod     case 12:
332*3d8817e4Smiod       return val & 07777;
333*3d8817e4Smiod     default:
334*3d8817e4Smiod       abort ();
335*3d8817e4Smiod     }
336*3d8817e4Smiod }
337*3d8817e4Smiod 
338*3d8817e4Smiod /* Check if an EA is valid for a particular code.  This is required
339*3d8817e4Smiod    for the EMAC instructions since the type of source address determines
340*3d8817e4Smiod    if it is a EMAC-load instruciton if the EA is mode 2-5, otherwise it
341*3d8817e4Smiod    is a non-load EMAC instruction and the bits mean register Ry.
342*3d8817e4Smiod    A similar case exists for the movem instructions where the register
343*3d8817e4Smiod    mask is interpreted differently for different EAs.  */
344*3d8817e4Smiod 
345*3d8817e4Smiod static bfd_boolean
m68k_valid_ea(char code,int val)346*3d8817e4Smiod m68k_valid_ea (char code, int val)
347*3d8817e4Smiod {
348*3d8817e4Smiod   int mode, mask;
349*3d8817e4Smiod #define M(n0,n1,n2,n3,n4,n5,n6,n70,n71,n72,n73,n74) \
350*3d8817e4Smiod   (n0 | n1 << 1 | n2 << 2 | n3 << 3 | n4 << 4 | n5 << 5 | n6 << 6 \
351*3d8817e4Smiod    | n70 << 7 | n71 << 8 | n72 << 9 | n73 << 10 | n74 << 11)
352*3d8817e4Smiod 
353*3d8817e4Smiod   switch (code)
354*3d8817e4Smiod     {
355*3d8817e4Smiod     case '*':
356*3d8817e4Smiod       mask = M (1,1,1,1,1,1,1,1,1,1,1,1);
357*3d8817e4Smiod       break;
358*3d8817e4Smiod     case '~':
359*3d8817e4Smiod       mask = M (0,0,1,1,1,1,1,1,1,0,0,0);
360*3d8817e4Smiod       break;
361*3d8817e4Smiod     case '%':
362*3d8817e4Smiod       mask = M (1,1,1,1,1,1,1,1,1,0,0,0);
363*3d8817e4Smiod       break;
364*3d8817e4Smiod     case ';':
365*3d8817e4Smiod       mask = M (1,0,1,1,1,1,1,1,1,1,1,1);
366*3d8817e4Smiod       break;
367*3d8817e4Smiod     case '@':
368*3d8817e4Smiod       mask = M (1,0,1,1,1,1,1,1,1,1,1,0);
369*3d8817e4Smiod       break;
370*3d8817e4Smiod     case '!':
371*3d8817e4Smiod       mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
372*3d8817e4Smiod       break;
373*3d8817e4Smiod     case '&':
374*3d8817e4Smiod       mask = M (0,0,1,0,0,1,1,1,1,0,0,0);
375*3d8817e4Smiod       break;
376*3d8817e4Smiod     case '$':
377*3d8817e4Smiod       mask = M (1,0,1,1,1,1,1,1,1,0,0,0);
378*3d8817e4Smiod       break;
379*3d8817e4Smiod     case '?':
380*3d8817e4Smiod       mask = M (1,0,1,0,0,1,1,1,1,0,0,0);
381*3d8817e4Smiod       break;
382*3d8817e4Smiod     case '/':
383*3d8817e4Smiod       mask = M (1,0,1,0,0,1,1,1,1,1,1,0);
384*3d8817e4Smiod       break;
385*3d8817e4Smiod     case '|':
386*3d8817e4Smiod       mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
387*3d8817e4Smiod       break;
388*3d8817e4Smiod     case '>':
389*3d8817e4Smiod       mask = M (0,0,1,0,1,1,1,1,1,0,0,0);
390*3d8817e4Smiod       break;
391*3d8817e4Smiod     case '<':
392*3d8817e4Smiod       mask = M (0,0,1,1,0,1,1,1,1,1,1,0);
393*3d8817e4Smiod       break;
394*3d8817e4Smiod     case 'm':
395*3d8817e4Smiod       mask = M (1,1,1,1,1,0,0,0,0,0,0,0);
396*3d8817e4Smiod       break;
397*3d8817e4Smiod     case 'n':
398*3d8817e4Smiod       mask = M (0,0,0,0,0,1,0,0,0,1,0,0);
399*3d8817e4Smiod       break;
400*3d8817e4Smiod     case 'o':
401*3d8817e4Smiod       mask = M (0,0,0,0,0,0,1,1,1,0,1,1);
402*3d8817e4Smiod       break;
403*3d8817e4Smiod     case 'p':
404*3d8817e4Smiod       mask = M (1,1,1,1,1,1,0,0,0,0,0,0);
405*3d8817e4Smiod       break;
406*3d8817e4Smiod     case 'q':
407*3d8817e4Smiod       mask = M (1,0,1,1,1,1,0,0,0,0,0,0);
408*3d8817e4Smiod       break;
409*3d8817e4Smiod     case 'v':
410*3d8817e4Smiod       mask = M (1,0,1,1,1,1,0,1,1,0,0,0);
411*3d8817e4Smiod       break;
412*3d8817e4Smiod     case 'b':
413*3d8817e4Smiod       mask = M (1,0,1,1,1,1,0,0,0,1,0,0);
414*3d8817e4Smiod       break;
415*3d8817e4Smiod     case 'w':
416*3d8817e4Smiod       mask = M (0,0,1,1,1,1,0,0,0,1,0,0);
417*3d8817e4Smiod       break;
418*3d8817e4Smiod     case 'y':
419*3d8817e4Smiod       mask = M (0,0,1,0,0,1,0,0,0,0,0,0);
420*3d8817e4Smiod       break;
421*3d8817e4Smiod     case 'z':
422*3d8817e4Smiod       mask = M (0,0,1,0,0,1,0,0,0,1,0,0);
423*3d8817e4Smiod       break;
424*3d8817e4Smiod     case '4':
425*3d8817e4Smiod       mask = M (0,0,1,1,1,1,0,0,0,0,0,0);
426*3d8817e4Smiod       break;
427*3d8817e4Smiod     default:
428*3d8817e4Smiod       abort ();
429*3d8817e4Smiod     }
430*3d8817e4Smiod #undef M
431*3d8817e4Smiod 
432*3d8817e4Smiod   mode = (val >> 3) & 7;
433*3d8817e4Smiod   if (mode == 7)
434*3d8817e4Smiod     mode += val & 7;
435*3d8817e4Smiod   return (mask & (1 << mode)) != 0;
436*3d8817e4Smiod }
437*3d8817e4Smiod 
438*3d8817e4Smiod /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
439*3d8817e4Smiod    REGNO = -1 for pc, -2 for none (suppressed).  */
440*3d8817e4Smiod 
441*3d8817e4Smiod static void
print_base(int regno,bfd_vma disp,disassemble_info * info)442*3d8817e4Smiod print_base (int regno, bfd_vma disp, disassemble_info *info)
443*3d8817e4Smiod {
444*3d8817e4Smiod   if (regno == -1)
445*3d8817e4Smiod     {
446*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%pc@(");
447*3d8817e4Smiod       (*info->print_address_func) (disp, info);
448*3d8817e4Smiod     }
449*3d8817e4Smiod   else
450*3d8817e4Smiod     {
451*3d8817e4Smiod       char buf[50];
452*3d8817e4Smiod 
453*3d8817e4Smiod       if (regno == -2)
454*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "@(");
455*3d8817e4Smiod       else if (regno == -3)
456*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "%%zpc@(");
457*3d8817e4Smiod       else
458*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "%s@(", reg_names[regno]);
459*3d8817e4Smiod 
460*3d8817e4Smiod       sprintf_vma (buf, disp);
461*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%s", buf);
462*3d8817e4Smiod     }
463*3d8817e4Smiod }
464*3d8817e4Smiod 
465*3d8817e4Smiod /* Print an indexed argument.  The base register is BASEREG (-1 for pc).
466*3d8817e4Smiod    P points to extension word, in buffer.
467*3d8817e4Smiod    ADDR is the nominal core address of that extension word.  */
468*3d8817e4Smiod 
469*3d8817e4Smiod static unsigned char *
print_indexed(int basereg,unsigned char * p,bfd_vma addr,disassemble_info * info)470*3d8817e4Smiod print_indexed (int basereg,
471*3d8817e4Smiod 	       unsigned char *p,
472*3d8817e4Smiod 	       bfd_vma addr,
473*3d8817e4Smiod 	       disassemble_info *info)
474*3d8817e4Smiod {
475*3d8817e4Smiod   int word;
476*3d8817e4Smiod   static char *const scales[] = { "", ":2", ":4", ":8" };
477*3d8817e4Smiod   bfd_vma base_disp;
478*3d8817e4Smiod   bfd_vma outer_disp;
479*3d8817e4Smiod   char buf[40];
480*3d8817e4Smiod   char vmabuf[50];
481*3d8817e4Smiod 
482*3d8817e4Smiod   word = NEXTWORD (p);
483*3d8817e4Smiod 
484*3d8817e4Smiod   /* Generate the text for the index register.
485*3d8817e4Smiod      Where this will be output is not yet determined.  */
486*3d8817e4Smiod   sprintf (buf, "%s:%c%s",
487*3d8817e4Smiod 	   reg_names[(word >> 12) & 0xf],
488*3d8817e4Smiod 	   (word & 0x800) ? 'l' : 'w',
489*3d8817e4Smiod 	   scales[(word >> 9) & 3]);
490*3d8817e4Smiod 
491*3d8817e4Smiod   /* Handle the 68000 style of indexing.  */
492*3d8817e4Smiod 
493*3d8817e4Smiod   if ((word & 0x100) == 0)
494*3d8817e4Smiod     {
495*3d8817e4Smiod       base_disp = word & 0xff;
496*3d8817e4Smiod       if ((base_disp & 0x80) != 0)
497*3d8817e4Smiod 	base_disp -= 0x100;
498*3d8817e4Smiod       if (basereg == -1)
499*3d8817e4Smiod 	base_disp += addr;
500*3d8817e4Smiod       print_base (basereg, base_disp, info);
501*3d8817e4Smiod       (*info->fprintf_func) (info->stream, ",%s)", buf);
502*3d8817e4Smiod       return p;
503*3d8817e4Smiod     }
504*3d8817e4Smiod 
505*3d8817e4Smiod   /* Handle the generalized kind.  */
506*3d8817e4Smiod   /* First, compute the displacement to add to the base register.  */
507*3d8817e4Smiod   if (word & 0200)
508*3d8817e4Smiod     {
509*3d8817e4Smiod       if (basereg == -1)
510*3d8817e4Smiod 	basereg = -3;
511*3d8817e4Smiod       else
512*3d8817e4Smiod 	basereg = -2;
513*3d8817e4Smiod     }
514*3d8817e4Smiod   if (word & 0100)
515*3d8817e4Smiod     buf[0] = '\0';
516*3d8817e4Smiod   base_disp = 0;
517*3d8817e4Smiod   switch ((word >> 4) & 3)
518*3d8817e4Smiod     {
519*3d8817e4Smiod     case 2:
520*3d8817e4Smiod       base_disp = NEXTWORD (p);
521*3d8817e4Smiod       break;
522*3d8817e4Smiod     case 3:
523*3d8817e4Smiod       base_disp = NEXTLONG (p);
524*3d8817e4Smiod     }
525*3d8817e4Smiod   if (basereg == -1)
526*3d8817e4Smiod     base_disp += addr;
527*3d8817e4Smiod 
528*3d8817e4Smiod   /* Handle single-level case (not indirect).  */
529*3d8817e4Smiod   if ((word & 7) == 0)
530*3d8817e4Smiod     {
531*3d8817e4Smiod       print_base (basereg, base_disp, info);
532*3d8817e4Smiod       if (buf[0] != '\0')
533*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, ",%s", buf);
534*3d8817e4Smiod       (*info->fprintf_func) (info->stream, ")");
535*3d8817e4Smiod       return p;
536*3d8817e4Smiod     }
537*3d8817e4Smiod 
538*3d8817e4Smiod   /* Two level.  Compute displacement to add after indirection.  */
539*3d8817e4Smiod   outer_disp = 0;
540*3d8817e4Smiod   switch (word & 3)
541*3d8817e4Smiod     {
542*3d8817e4Smiod     case 2:
543*3d8817e4Smiod       outer_disp = NEXTWORD (p);
544*3d8817e4Smiod       break;
545*3d8817e4Smiod     case 3:
546*3d8817e4Smiod       outer_disp = NEXTLONG (p);
547*3d8817e4Smiod     }
548*3d8817e4Smiod 
549*3d8817e4Smiod   print_base (basereg, base_disp, info);
550*3d8817e4Smiod   if ((word & 4) == 0 && buf[0] != '\0')
551*3d8817e4Smiod     {
552*3d8817e4Smiod       (*info->fprintf_func) (info->stream, ",%s", buf);
553*3d8817e4Smiod       buf[0] = '\0';
554*3d8817e4Smiod     }
555*3d8817e4Smiod   sprintf_vma (vmabuf, outer_disp);
556*3d8817e4Smiod   (*info->fprintf_func) (info->stream, ")@(%s", vmabuf);
557*3d8817e4Smiod   if (buf[0] != '\0')
558*3d8817e4Smiod     (*info->fprintf_func) (info->stream, ",%s", buf);
559*3d8817e4Smiod   (*info->fprintf_func) (info->stream, ")");
560*3d8817e4Smiod 
561*3d8817e4Smiod   return p;
562*3d8817e4Smiod }
563*3d8817e4Smiod 
564*3d8817e4Smiod /* Returns number of bytes "eaten" by the operand, or
565*3d8817e4Smiod    return -1 if an invalid operand was found, or -2 if
566*3d8817e4Smiod    an opcode tabe error was found.
567*3d8817e4Smiod    ADDR is the pc for this arg to be relative to.  */
568*3d8817e4Smiod 
569*3d8817e4Smiod static int
print_insn_arg(const char * d,unsigned char * buffer,unsigned char * p0,bfd_vma addr,disassemble_info * info)570*3d8817e4Smiod print_insn_arg (const char *d,
571*3d8817e4Smiod 		unsigned char *buffer,
572*3d8817e4Smiod 		unsigned char *p0,
573*3d8817e4Smiod 		bfd_vma addr,
574*3d8817e4Smiod 		disassemble_info *info)
575*3d8817e4Smiod {
576*3d8817e4Smiod   int val = 0;
577*3d8817e4Smiod   int place = d[1];
578*3d8817e4Smiod   unsigned char *p = p0;
579*3d8817e4Smiod   int regno;
580*3d8817e4Smiod   const char *regname;
581*3d8817e4Smiod   unsigned char *p1;
582*3d8817e4Smiod   double flval;
583*3d8817e4Smiod   int flt_p;
584*3d8817e4Smiod   bfd_signed_vma disp;
585*3d8817e4Smiod   unsigned int uval;
586*3d8817e4Smiod 
587*3d8817e4Smiod   switch (*d)
588*3d8817e4Smiod     {
589*3d8817e4Smiod     case 'c':		/* Cache identifier.  */
590*3d8817e4Smiod       {
591*3d8817e4Smiod         static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
592*3d8817e4Smiod         val = fetch_arg (buffer, place, 2, info);
593*3d8817e4Smiod         (*info->fprintf_func) (info->stream, cacheFieldName[val]);
594*3d8817e4Smiod         break;
595*3d8817e4Smiod       }
596*3d8817e4Smiod 
597*3d8817e4Smiod     case 'a':		/* Address register indirect only. Cf. case '+'.  */
598*3d8817e4Smiod       {
599*3d8817e4Smiod         (*info->fprintf_func)
600*3d8817e4Smiod 	  (info->stream,
601*3d8817e4Smiod 	   "%s@",
602*3d8817e4Smiod 	   reg_names[fetch_arg (buffer, place, 3, info) + 8]);
603*3d8817e4Smiod         break;
604*3d8817e4Smiod       }
605*3d8817e4Smiod 
606*3d8817e4Smiod     case '_':		/* 32-bit absolute address for move16.  */
607*3d8817e4Smiod       {
608*3d8817e4Smiod         uval = NEXTULONG (p);
609*3d8817e4Smiod 	(*info->print_address_func) (uval, info);
610*3d8817e4Smiod         break;
611*3d8817e4Smiod       }
612*3d8817e4Smiod 
613*3d8817e4Smiod     case 'C':
614*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%ccr");
615*3d8817e4Smiod       break;
616*3d8817e4Smiod 
617*3d8817e4Smiod     case 'S':
618*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%sr");
619*3d8817e4Smiod       break;
620*3d8817e4Smiod 
621*3d8817e4Smiod     case 'U':
622*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%usp");
623*3d8817e4Smiod       break;
624*3d8817e4Smiod 
625*3d8817e4Smiod     case 'E':
626*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%acc");
627*3d8817e4Smiod       break;
628*3d8817e4Smiod 
629*3d8817e4Smiod     case 'G':
630*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%macsr");
631*3d8817e4Smiod       break;
632*3d8817e4Smiod 
633*3d8817e4Smiod     case 'H':
634*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%mask");
635*3d8817e4Smiod       break;
636*3d8817e4Smiod 
637*3d8817e4Smiod     case 'J':
638*3d8817e4Smiod       {
639*3d8817e4Smiod 	/* FIXME: There's a problem here, different m68k processors call the
640*3d8817e4Smiod 	   same address different names. This table can't get it right
641*3d8817e4Smiod 	   because it doesn't know which processor it's disassembling for.  */
642*3d8817e4Smiod 	static const struct { char *name; int value; } names[]
643*3d8817e4Smiod 	  = {{"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
644*3d8817e4Smiod 	     {"%tc",  0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
645*3d8817e4Smiod              {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
646*3d8817e4Smiod 	     {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
647*3d8817e4Smiod 	     {"%msp", 0x803}, {"%isp", 0x804},
648*3d8817e4Smiod 	     {"%flashbar", 0xc04}, {"%rambar", 0xc05}, /* mcf528x added these.  */
649*3d8817e4Smiod 
650*3d8817e4Smiod 	     /* Should we be calling this psr like we do in case 'Y'?  */
651*3d8817e4Smiod 	     {"%mmusr",0x805},
652*3d8817e4Smiod 
653*3d8817e4Smiod              {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808}};
654*3d8817e4Smiod 
655*3d8817e4Smiod 	val = fetch_arg (buffer, place, 12, info);
656*3d8817e4Smiod 	for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
657*3d8817e4Smiod 	  if (names[regno].value == val)
658*3d8817e4Smiod 	    {
659*3d8817e4Smiod 	      (*info->fprintf_func) (info->stream, "%s", names[regno].name);
660*3d8817e4Smiod 	      break;
661*3d8817e4Smiod 	    }
662*3d8817e4Smiod 	if (regno < 0)
663*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%d", val);
664*3d8817e4Smiod       }
665*3d8817e4Smiod       break;
666*3d8817e4Smiod 
667*3d8817e4Smiod     case 'Q':
668*3d8817e4Smiod       val = fetch_arg (buffer, place, 3, info);
669*3d8817e4Smiod       /* 0 means 8, except for the bkpt instruction... */
670*3d8817e4Smiod       if (val == 0 && d[1] != 's')
671*3d8817e4Smiod 	val = 8;
672*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "#%d", val);
673*3d8817e4Smiod       break;
674*3d8817e4Smiod 
675*3d8817e4Smiod     case 'x':
676*3d8817e4Smiod       val = fetch_arg (buffer, place, 3, info);
677*3d8817e4Smiod       /* 0 means -1.  */
678*3d8817e4Smiod       if (val == 0)
679*3d8817e4Smiod 	val = -1;
680*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "#%d", val);
681*3d8817e4Smiod       break;
682*3d8817e4Smiod 
683*3d8817e4Smiod     case 'M':
684*3d8817e4Smiod       if (place == 'h')
685*3d8817e4Smiod 	{
686*3d8817e4Smiod 	  static char *const scalefactor_name[] = { "<<", ">>" };
687*3d8817e4Smiod 	  val = fetch_arg (buffer, place, 1, info);
688*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, scalefactor_name[val]);
689*3d8817e4Smiod 	}
690*3d8817e4Smiod       else
691*3d8817e4Smiod 	{
692*3d8817e4Smiod 	  val = fetch_arg (buffer, place, 8, info);
693*3d8817e4Smiod 	  if (val & 0x80)
694*3d8817e4Smiod 	    val = val - 0x100;
695*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "#%d", val);
696*3d8817e4Smiod 	}
697*3d8817e4Smiod       break;
698*3d8817e4Smiod 
699*3d8817e4Smiod     case 'T':
700*3d8817e4Smiod       val = fetch_arg (buffer, place, 4, info);
701*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "#%d", val);
702*3d8817e4Smiod       break;
703*3d8817e4Smiod 
704*3d8817e4Smiod     case 'D':
705*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%s",
706*3d8817e4Smiod 			     reg_names[fetch_arg (buffer, place, 3, info)]);
707*3d8817e4Smiod       break;
708*3d8817e4Smiod 
709*3d8817e4Smiod     case 'A':
710*3d8817e4Smiod       (*info->fprintf_func)
711*3d8817e4Smiod 	(info->stream, "%s",
712*3d8817e4Smiod 	 reg_names[fetch_arg (buffer, place, 3, info) + 010]);
713*3d8817e4Smiod       break;
714*3d8817e4Smiod 
715*3d8817e4Smiod     case 'R':
716*3d8817e4Smiod       (*info->fprintf_func)
717*3d8817e4Smiod 	(info->stream, "%s",
718*3d8817e4Smiod 	 reg_names[fetch_arg (buffer, place, 4, info)]);
719*3d8817e4Smiod       break;
720*3d8817e4Smiod 
721*3d8817e4Smiod     case 'r':
722*3d8817e4Smiod       regno = fetch_arg (buffer, place, 4, info);
723*3d8817e4Smiod       if (regno > 7)
724*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "%s@", reg_names[regno]);
725*3d8817e4Smiod       else
726*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "@(%s)", reg_names[regno]);
727*3d8817e4Smiod       break;
728*3d8817e4Smiod 
729*3d8817e4Smiod     case 'F':
730*3d8817e4Smiod       (*info->fprintf_func)
731*3d8817e4Smiod 	(info->stream, "%%fp%d",
732*3d8817e4Smiod 	 fetch_arg (buffer, place, 3, info));
733*3d8817e4Smiod       break;
734*3d8817e4Smiod 
735*3d8817e4Smiod     case 'O':
736*3d8817e4Smiod       val = fetch_arg (buffer, place, 6, info);
737*3d8817e4Smiod       if (val & 0x20)
738*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "%s", reg_names[val & 7]);
739*3d8817e4Smiod       else
740*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "%d", val);
741*3d8817e4Smiod       break;
742*3d8817e4Smiod 
743*3d8817e4Smiod     case '+':
744*3d8817e4Smiod       (*info->fprintf_func)
745*3d8817e4Smiod 	(info->stream, "%s@+",
746*3d8817e4Smiod 	 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
747*3d8817e4Smiod       break;
748*3d8817e4Smiod 
749*3d8817e4Smiod     case '-':
750*3d8817e4Smiod       (*info->fprintf_func)
751*3d8817e4Smiod 	(info->stream, "%s@-",
752*3d8817e4Smiod 	 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
753*3d8817e4Smiod       break;
754*3d8817e4Smiod 
755*3d8817e4Smiod     case 'k':
756*3d8817e4Smiod       if (place == 'k')
757*3d8817e4Smiod 	(*info->fprintf_func)
758*3d8817e4Smiod 	  (info->stream, "{%s}",
759*3d8817e4Smiod 	   reg_names[fetch_arg (buffer, place, 3, info)]);
760*3d8817e4Smiod       else if (place == 'C')
761*3d8817e4Smiod 	{
762*3d8817e4Smiod 	  val = fetch_arg (buffer, place, 7, info);
763*3d8817e4Smiod 	  if (val > 63)		/* This is a signed constant.  */
764*3d8817e4Smiod 	    val -= 128;
765*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "{#%d}", val);
766*3d8817e4Smiod 	}
767*3d8817e4Smiod       else
768*3d8817e4Smiod 	return -2;
769*3d8817e4Smiod       break;
770*3d8817e4Smiod 
771*3d8817e4Smiod     case '#':
772*3d8817e4Smiod     case '^':
773*3d8817e4Smiod       p1 = buffer + (*d == '#' ? 2 : 4);
774*3d8817e4Smiod       if (place == 's')
775*3d8817e4Smiod 	val = fetch_arg (buffer, place, 4, info);
776*3d8817e4Smiod       else if (place == 'C')
777*3d8817e4Smiod 	val = fetch_arg (buffer, place, 7, info);
778*3d8817e4Smiod       else if (place == '8')
779*3d8817e4Smiod 	val = fetch_arg (buffer, place, 3, info);
780*3d8817e4Smiod       else if (place == '3')
781*3d8817e4Smiod 	val = fetch_arg (buffer, place, 8, info);
782*3d8817e4Smiod       else if (place == 'b')
783*3d8817e4Smiod 	val = NEXTBYTE (p1);
784*3d8817e4Smiod       else if (place == 'w' || place == 'W')
785*3d8817e4Smiod 	val = NEXTWORD (p1);
786*3d8817e4Smiod       else if (place == 'l')
787*3d8817e4Smiod 	val = NEXTLONG (p1);
788*3d8817e4Smiod       else
789*3d8817e4Smiod 	return -2;
790*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "#%d", val);
791*3d8817e4Smiod       break;
792*3d8817e4Smiod 
793*3d8817e4Smiod     case 'B':
794*3d8817e4Smiod       if (place == 'b')
795*3d8817e4Smiod 	disp = NEXTBYTE (p);
796*3d8817e4Smiod       else if (place == 'B')
797*3d8817e4Smiod 	disp = COERCE_SIGNED_CHAR (buffer[1]);
798*3d8817e4Smiod       else if (place == 'w' || place == 'W')
799*3d8817e4Smiod 	disp = NEXTWORD (p);
800*3d8817e4Smiod       else if (place == 'l' || place == 'L' || place == 'C')
801*3d8817e4Smiod 	disp = NEXTLONG (p);
802*3d8817e4Smiod       else if (place == 'g')
803*3d8817e4Smiod 	{
804*3d8817e4Smiod 	  disp = NEXTBYTE (buffer);
805*3d8817e4Smiod 	  if (disp == 0)
806*3d8817e4Smiod 	    disp = NEXTWORD (p);
807*3d8817e4Smiod 	  else if (disp == -1)
808*3d8817e4Smiod 	    disp = NEXTLONG (p);
809*3d8817e4Smiod 	}
810*3d8817e4Smiod       else if (place == 'c')
811*3d8817e4Smiod 	{
812*3d8817e4Smiod 	  if (buffer[1] & 0x40)		/* If bit six is one, long offset.  */
813*3d8817e4Smiod 	    disp = NEXTLONG (p);
814*3d8817e4Smiod 	  else
815*3d8817e4Smiod 	    disp = NEXTWORD (p);
816*3d8817e4Smiod 	}
817*3d8817e4Smiod       else
818*3d8817e4Smiod 	return -2;
819*3d8817e4Smiod 
820*3d8817e4Smiod       (*info->print_address_func) (addr + disp, info);
821*3d8817e4Smiod       break;
822*3d8817e4Smiod 
823*3d8817e4Smiod     case 'd':
824*3d8817e4Smiod       val = NEXTWORD (p);
825*3d8817e4Smiod       (*info->fprintf_func)
826*3d8817e4Smiod 	(info->stream, "%s@(%d)",
827*3d8817e4Smiod 	 reg_names[fetch_arg (buffer, place, 3, info) + 8], val);
828*3d8817e4Smiod       break;
829*3d8817e4Smiod 
830*3d8817e4Smiod     case 's':
831*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%s",
832*3d8817e4Smiod 			     fpcr_names[fetch_arg (buffer, place, 3, info)]);
833*3d8817e4Smiod       break;
834*3d8817e4Smiod 
835*3d8817e4Smiod     case 'e':
836*3d8817e4Smiod       val = fetch_arg(buffer, place, 2, info);
837*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%acc%d", val);
838*3d8817e4Smiod       break;
839*3d8817e4Smiod 
840*3d8817e4Smiod     case 'g':
841*3d8817e4Smiod       val = fetch_arg(buffer, place, 1, info);
842*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%accext%s", val==0 ? "01" : "23");
843*3d8817e4Smiod       break;
844*3d8817e4Smiod 
845*3d8817e4Smiod     case 'i':
846*3d8817e4Smiod       val = fetch_arg(buffer, place, 2, info);
847*3d8817e4Smiod       if (val == 1)
848*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "<<");
849*3d8817e4Smiod       else if (val == 3)
850*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, ">>");
851*3d8817e4Smiod       else
852*3d8817e4Smiod 	return -1;
853*3d8817e4Smiod       break;
854*3d8817e4Smiod 
855*3d8817e4Smiod     case 'I':
856*3d8817e4Smiod       /* Get coprocessor ID... */
857*3d8817e4Smiod       val = fetch_arg (buffer, 'd', 3, info);
858*3d8817e4Smiod 
859*3d8817e4Smiod       if (val != 1)				/* Unusual coprocessor ID?  */
860*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
861*3d8817e4Smiod       break;
862*3d8817e4Smiod 
863*3d8817e4Smiod     case '4':
864*3d8817e4Smiod     case '*':
865*3d8817e4Smiod     case '~':
866*3d8817e4Smiod     case '%':
867*3d8817e4Smiod     case ';':
868*3d8817e4Smiod     case '@':
869*3d8817e4Smiod     case '!':
870*3d8817e4Smiod     case '$':
871*3d8817e4Smiod     case '?':
872*3d8817e4Smiod     case '/':
873*3d8817e4Smiod     case '&':
874*3d8817e4Smiod     case '|':
875*3d8817e4Smiod     case '<':
876*3d8817e4Smiod     case '>':
877*3d8817e4Smiod     case 'm':
878*3d8817e4Smiod     case 'n':
879*3d8817e4Smiod     case 'o':
880*3d8817e4Smiod     case 'p':
881*3d8817e4Smiod     case 'q':
882*3d8817e4Smiod     case 'v':
883*3d8817e4Smiod     case 'b':
884*3d8817e4Smiod     case 'w':
885*3d8817e4Smiod     case 'y':
886*3d8817e4Smiod     case 'z':
887*3d8817e4Smiod       if (place == 'd')
888*3d8817e4Smiod 	{
889*3d8817e4Smiod 	  val = fetch_arg (buffer, 'x', 6, info);
890*3d8817e4Smiod 	  val = ((val & 7) << 3) + ((val >> 3) & 7);
891*3d8817e4Smiod 	}
892*3d8817e4Smiod       else
893*3d8817e4Smiod 	val = fetch_arg (buffer, 's', 6, info);
894*3d8817e4Smiod 
895*3d8817e4Smiod       /* If the <ea> is invalid for *d, then reject this match.  */
896*3d8817e4Smiod       if (!m68k_valid_ea (*d, val))
897*3d8817e4Smiod 	return -1;
898*3d8817e4Smiod 
899*3d8817e4Smiod       /* Get register number assuming address register.  */
900*3d8817e4Smiod       regno = (val & 7) + 8;
901*3d8817e4Smiod       regname = reg_names[regno];
902*3d8817e4Smiod       switch (val >> 3)
903*3d8817e4Smiod 	{
904*3d8817e4Smiod 	case 0:
905*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
906*3d8817e4Smiod 	  break;
907*3d8817e4Smiod 
908*3d8817e4Smiod 	case 1:
909*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%s", regname);
910*3d8817e4Smiod 	  break;
911*3d8817e4Smiod 
912*3d8817e4Smiod 	case 2:
913*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%s@", regname);
914*3d8817e4Smiod 	  break;
915*3d8817e4Smiod 
916*3d8817e4Smiod 	case 3:
917*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%s@+", regname);
918*3d8817e4Smiod 	  break;
919*3d8817e4Smiod 
920*3d8817e4Smiod 	case 4:
921*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%s@-", regname);
922*3d8817e4Smiod 	  break;
923*3d8817e4Smiod 
924*3d8817e4Smiod 	case 5:
925*3d8817e4Smiod 	  val = NEXTWORD (p);
926*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
927*3d8817e4Smiod 	  break;
928*3d8817e4Smiod 
929*3d8817e4Smiod 	case 6:
930*3d8817e4Smiod 	  p = print_indexed (regno, p, addr, info);
931*3d8817e4Smiod 	  break;
932*3d8817e4Smiod 
933*3d8817e4Smiod 	case 7:
934*3d8817e4Smiod 	  switch (val & 7)
935*3d8817e4Smiod 	    {
936*3d8817e4Smiod 	    case 0:
937*3d8817e4Smiod 	      val = NEXTWORD (p);
938*3d8817e4Smiod 	      (*info->print_address_func) (val, info);
939*3d8817e4Smiod 	      break;
940*3d8817e4Smiod 
941*3d8817e4Smiod 	    case 1:
942*3d8817e4Smiod 	      uval = NEXTULONG (p);
943*3d8817e4Smiod 	      (*info->print_address_func) (uval, info);
944*3d8817e4Smiod 	      break;
945*3d8817e4Smiod 
946*3d8817e4Smiod 	    case 2:
947*3d8817e4Smiod 	      val = NEXTWORD (p);
948*3d8817e4Smiod 	      (*info->fprintf_func) (info->stream, "%%pc@(");
949*3d8817e4Smiod 	      (*info->print_address_func) (addr + val, info);
950*3d8817e4Smiod 	      (*info->fprintf_func) (info->stream, ")");
951*3d8817e4Smiod 	      break;
952*3d8817e4Smiod 
953*3d8817e4Smiod 	    case 3:
954*3d8817e4Smiod 	      p = print_indexed (-1, p, addr, info);
955*3d8817e4Smiod 	      break;
956*3d8817e4Smiod 
957*3d8817e4Smiod 	    case 4:
958*3d8817e4Smiod 	      flt_p = 1;	/* Assume it's a float... */
959*3d8817e4Smiod 	      switch (place)
960*3d8817e4Smiod 	      {
961*3d8817e4Smiod 		case 'b':
962*3d8817e4Smiod 		  val = NEXTBYTE (p);
963*3d8817e4Smiod 		  flt_p = 0;
964*3d8817e4Smiod 		  break;
965*3d8817e4Smiod 
966*3d8817e4Smiod 		case 'w':
967*3d8817e4Smiod 		  val = NEXTWORD (p);
968*3d8817e4Smiod 		  flt_p = 0;
969*3d8817e4Smiod 		  break;
970*3d8817e4Smiod 
971*3d8817e4Smiod 		case 'l':
972*3d8817e4Smiod 		  val = NEXTLONG (p);
973*3d8817e4Smiod 		  flt_p = 0;
974*3d8817e4Smiod 		  break;
975*3d8817e4Smiod 
976*3d8817e4Smiod 		case 'f':
977*3d8817e4Smiod 		  NEXTSINGLE (flval, p);
978*3d8817e4Smiod 		  break;
979*3d8817e4Smiod 
980*3d8817e4Smiod 		case 'F':
981*3d8817e4Smiod 		  NEXTDOUBLE (flval, p);
982*3d8817e4Smiod 		  break;
983*3d8817e4Smiod 
984*3d8817e4Smiod 		case 'x':
985*3d8817e4Smiod 		  NEXTEXTEND (flval, p);
986*3d8817e4Smiod 		  break;
987*3d8817e4Smiod 
988*3d8817e4Smiod 		case 'p':
989*3d8817e4Smiod 		  flval = NEXTPACKED (p);
990*3d8817e4Smiod 		  break;
991*3d8817e4Smiod 
992*3d8817e4Smiod 		default:
993*3d8817e4Smiod 		  return -1;
994*3d8817e4Smiod 	      }
995*3d8817e4Smiod 	      if (flt_p)	/* Print a float? */
996*3d8817e4Smiod 		(*info->fprintf_func) (info->stream, "#%g", flval);
997*3d8817e4Smiod 	      else
998*3d8817e4Smiod 		(*info->fprintf_func) (info->stream, "#%d", val);
999*3d8817e4Smiod 	      break;
1000*3d8817e4Smiod 
1001*3d8817e4Smiod 	    default:
1002*3d8817e4Smiod 	      return -1;
1003*3d8817e4Smiod 	    }
1004*3d8817e4Smiod 	}
1005*3d8817e4Smiod 
1006*3d8817e4Smiod       /* If place is '/', then this is the case of the mask bit for
1007*3d8817e4Smiod 	 mac/emac loads. Now that the arg has been printed, grab the
1008*3d8817e4Smiod 	 mask bit and if set, add a '&' to the arg.  */
1009*3d8817e4Smiod       if (place == '/')
1010*3d8817e4Smiod 	{
1011*3d8817e4Smiod 	  val = fetch_arg (buffer, place, 1, info);
1012*3d8817e4Smiod 	  if (val)
1013*3d8817e4Smiod 	    info->fprintf_func (info->stream, "&");
1014*3d8817e4Smiod 	}
1015*3d8817e4Smiod       break;
1016*3d8817e4Smiod 
1017*3d8817e4Smiod     case 'L':
1018*3d8817e4Smiod     case 'l':
1019*3d8817e4Smiod 	if (place == 'w')
1020*3d8817e4Smiod 	  {
1021*3d8817e4Smiod 	    char doneany;
1022*3d8817e4Smiod 	    p1 = buffer + 2;
1023*3d8817e4Smiod 	    val = NEXTWORD (p1);
1024*3d8817e4Smiod 	    /* Move the pointer ahead if this point is farther ahead
1025*3d8817e4Smiod 	       than the last.  */
1026*3d8817e4Smiod 	    p = p1 > p ? p1 : p;
1027*3d8817e4Smiod 	    if (val == 0)
1028*3d8817e4Smiod 	      {
1029*3d8817e4Smiod 		(*info->fprintf_func) (info->stream, "#0");
1030*3d8817e4Smiod 		break;
1031*3d8817e4Smiod 	      }
1032*3d8817e4Smiod 	    if (*d == 'l')
1033*3d8817e4Smiod 	      {
1034*3d8817e4Smiod 		int newval = 0;
1035*3d8817e4Smiod 
1036*3d8817e4Smiod 		for (regno = 0; regno < 16; ++regno)
1037*3d8817e4Smiod 		  if (val & (0x8000 >> regno))
1038*3d8817e4Smiod 		    newval |= 1 << regno;
1039*3d8817e4Smiod 		val = newval;
1040*3d8817e4Smiod 	      }
1041*3d8817e4Smiod 	    val &= 0xffff;
1042*3d8817e4Smiod 	    doneany = 0;
1043*3d8817e4Smiod 	    for (regno = 0; regno < 16; ++regno)
1044*3d8817e4Smiod 	      if (val & (1 << regno))
1045*3d8817e4Smiod 		{
1046*3d8817e4Smiod 		  int first_regno;
1047*3d8817e4Smiod 
1048*3d8817e4Smiod 		  if (doneany)
1049*3d8817e4Smiod 		    (*info->fprintf_func) (info->stream, "/");
1050*3d8817e4Smiod 		  doneany = 1;
1051*3d8817e4Smiod 		  (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
1052*3d8817e4Smiod 		  first_regno = regno;
1053*3d8817e4Smiod 		  while (val & (1 << (regno + 1)))
1054*3d8817e4Smiod 		    ++regno;
1055*3d8817e4Smiod 		  if (regno > first_regno)
1056*3d8817e4Smiod 		    (*info->fprintf_func) (info->stream, "-%s",
1057*3d8817e4Smiod 					   reg_names[regno]);
1058*3d8817e4Smiod 		}
1059*3d8817e4Smiod 	  }
1060*3d8817e4Smiod 	else if (place == '3')
1061*3d8817e4Smiod 	  {
1062*3d8817e4Smiod 	    /* `fmovem' insn.  */
1063*3d8817e4Smiod 	    char doneany;
1064*3d8817e4Smiod 	    val = fetch_arg (buffer, place, 8, info);
1065*3d8817e4Smiod 	    if (val == 0)
1066*3d8817e4Smiod 	      {
1067*3d8817e4Smiod 		(*info->fprintf_func) (info->stream, "#0");
1068*3d8817e4Smiod 		break;
1069*3d8817e4Smiod 	      }
1070*3d8817e4Smiod 	    if (*d == 'l')
1071*3d8817e4Smiod 	      {
1072*3d8817e4Smiod 		int newval = 0;
1073*3d8817e4Smiod 
1074*3d8817e4Smiod 		for (regno = 0; regno < 8; ++regno)
1075*3d8817e4Smiod 		  if (val & (0x80 >> regno))
1076*3d8817e4Smiod 		    newval |= 1 << regno;
1077*3d8817e4Smiod 		val = newval;
1078*3d8817e4Smiod 	      }
1079*3d8817e4Smiod 	    val &= 0xff;
1080*3d8817e4Smiod 	    doneany = 0;
1081*3d8817e4Smiod 	    for (regno = 0; regno < 8; ++regno)
1082*3d8817e4Smiod 	      if (val & (1 << regno))
1083*3d8817e4Smiod 		{
1084*3d8817e4Smiod 		  int first_regno;
1085*3d8817e4Smiod 		  if (doneany)
1086*3d8817e4Smiod 		    (*info->fprintf_func) (info->stream, "/");
1087*3d8817e4Smiod 		  doneany = 1;
1088*3d8817e4Smiod 		  (*info->fprintf_func) (info->stream, "%%fp%d", regno);
1089*3d8817e4Smiod 		  first_regno = regno;
1090*3d8817e4Smiod 		  while (val & (1 << (regno + 1)))
1091*3d8817e4Smiod 		    ++regno;
1092*3d8817e4Smiod 		  if (regno > first_regno)
1093*3d8817e4Smiod 		    (*info->fprintf_func) (info->stream, "-%%fp%d", regno);
1094*3d8817e4Smiod 		}
1095*3d8817e4Smiod 	  }
1096*3d8817e4Smiod 	else if (place == '8')
1097*3d8817e4Smiod 	  {
1098*3d8817e4Smiod 	    /* fmoveml for FP status registers.  */
1099*3d8817e4Smiod 	    (*info->fprintf_func) (info->stream, "%s",
1100*3d8817e4Smiod 				   fpcr_names[fetch_arg (buffer, place, 3,
1101*3d8817e4Smiod 							 info)]);
1102*3d8817e4Smiod 	  }
1103*3d8817e4Smiod 	else
1104*3d8817e4Smiod 	  return -2;
1105*3d8817e4Smiod       break;
1106*3d8817e4Smiod 
1107*3d8817e4Smiod     case 'X':
1108*3d8817e4Smiod       place = '8';
1109*3d8817e4Smiod     case 'Y':
1110*3d8817e4Smiod     case 'Z':
1111*3d8817e4Smiod     case 'W':
1112*3d8817e4Smiod     case '0':
1113*3d8817e4Smiod     case '1':
1114*3d8817e4Smiod     case '2':
1115*3d8817e4Smiod     case '3':
1116*3d8817e4Smiod       {
1117*3d8817e4Smiod 	int val = fetch_arg (buffer, place, 5, info);
1118*3d8817e4Smiod 	char *name = 0;
1119*3d8817e4Smiod 
1120*3d8817e4Smiod 	switch (val)
1121*3d8817e4Smiod 	  {
1122*3d8817e4Smiod 	  case 2: name = "%tt0"; break;
1123*3d8817e4Smiod 	  case 3: name = "%tt1"; break;
1124*3d8817e4Smiod 	  case 0x10: name = "%tc"; break;
1125*3d8817e4Smiod 	  case 0x11: name = "%drp"; break;
1126*3d8817e4Smiod 	  case 0x12: name = "%srp"; break;
1127*3d8817e4Smiod 	  case 0x13: name = "%crp"; break;
1128*3d8817e4Smiod 	  case 0x14: name = "%cal"; break;
1129*3d8817e4Smiod 	  case 0x15: name = "%val"; break;
1130*3d8817e4Smiod 	  case 0x16: name = "%scc"; break;
1131*3d8817e4Smiod 	  case 0x17: name = "%ac"; break;
1132*3d8817e4Smiod  	  case 0x18: name = "%psr"; break;
1133*3d8817e4Smiod 	  case 0x19: name = "%pcsr"; break;
1134*3d8817e4Smiod 	  case 0x1c:
1135*3d8817e4Smiod 	  case 0x1d:
1136*3d8817e4Smiod 	    {
1137*3d8817e4Smiod 	      int break_reg = ((buffer[3] >> 2) & 7);
1138*3d8817e4Smiod 
1139*3d8817e4Smiod 	      (*info->fprintf_func)
1140*3d8817e4Smiod 		(info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
1141*3d8817e4Smiod 		 break_reg);
1142*3d8817e4Smiod 	    }
1143*3d8817e4Smiod 	    break;
1144*3d8817e4Smiod 	  default:
1145*3d8817e4Smiod 	    (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
1146*3d8817e4Smiod 	  }
1147*3d8817e4Smiod 	if (name)
1148*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%s", name);
1149*3d8817e4Smiod       }
1150*3d8817e4Smiod       break;
1151*3d8817e4Smiod 
1152*3d8817e4Smiod     case 'f':
1153*3d8817e4Smiod       {
1154*3d8817e4Smiod 	int fc = fetch_arg (buffer, place, 5, info);
1155*3d8817e4Smiod 
1156*3d8817e4Smiod 	if (fc == 1)
1157*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%%dfc");
1158*3d8817e4Smiod 	else if (fc == 0)
1159*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, "%%sfc");
1160*3d8817e4Smiod 	else
1161*3d8817e4Smiod 	  /* xgettext:c-format */
1162*3d8817e4Smiod 	  (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
1163*3d8817e4Smiod       }
1164*3d8817e4Smiod       break;
1165*3d8817e4Smiod 
1166*3d8817e4Smiod     case 'V':
1167*3d8817e4Smiod       (*info->fprintf_func) (info->stream, "%%val");
1168*3d8817e4Smiod       break;
1169*3d8817e4Smiod 
1170*3d8817e4Smiod     case 't':
1171*3d8817e4Smiod       {
1172*3d8817e4Smiod 	int level = fetch_arg (buffer, place, 3, info);
1173*3d8817e4Smiod 
1174*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "%d", level);
1175*3d8817e4Smiod       }
1176*3d8817e4Smiod       break;
1177*3d8817e4Smiod 
1178*3d8817e4Smiod     case 'u':
1179*3d8817e4Smiod       {
1180*3d8817e4Smiod 	short is_upper = 0;
1181*3d8817e4Smiod 	int reg = fetch_arg (buffer, place, 5, info);
1182*3d8817e4Smiod 
1183*3d8817e4Smiod 	if (reg & 0x10)
1184*3d8817e4Smiod 	  {
1185*3d8817e4Smiod 	    is_upper = 1;
1186*3d8817e4Smiod 	    reg &= 0xf;
1187*3d8817e4Smiod 	  }
1188*3d8817e4Smiod 	(*info->fprintf_func) (info->stream, "%s%s",
1189*3d8817e4Smiod 			       reg_half_names[reg],
1190*3d8817e4Smiod 			       is_upper ? "u" : "l");
1191*3d8817e4Smiod       }
1192*3d8817e4Smiod       break;
1193*3d8817e4Smiod 
1194*3d8817e4Smiod     default:
1195*3d8817e4Smiod       return -2;
1196*3d8817e4Smiod     }
1197*3d8817e4Smiod 
1198*3d8817e4Smiod   return p - p0;
1199*3d8817e4Smiod }
1200*3d8817e4Smiod 
1201*3d8817e4Smiod /* Try to match the current instruction to best and if so, return the
1202*3d8817e4Smiod    number of bytes consumed from the instruction stream, else zero.  */
1203*3d8817e4Smiod 
1204*3d8817e4Smiod static int
match_insn_m68k(bfd_vma memaddr,disassemble_info * info,const struct m68k_opcode * best)1205*3d8817e4Smiod match_insn_m68k (bfd_vma memaddr,
1206*3d8817e4Smiod 		 disassemble_info * info,
1207*3d8817e4Smiod 		 const struct m68k_opcode * best)
1208*3d8817e4Smiod {
1209*3d8817e4Smiod   unsigned char *save_p;
1210*3d8817e4Smiod   unsigned char *p;
1211*3d8817e4Smiod   const char *d;
1212*3d8817e4Smiod 
1213*3d8817e4Smiod   struct private *priv = (struct private *) info->private_data;
1214*3d8817e4Smiod   bfd_byte *buffer = priv->the_buffer;
1215*3d8817e4Smiod   fprintf_ftype save_printer = info->fprintf_func;
1216*3d8817e4Smiod   void (* save_print_address) (bfd_vma, struct disassemble_info *)
1217*3d8817e4Smiod     = info->print_address_func;
1218*3d8817e4Smiod 
1219*3d8817e4Smiod   /* Point at first word of argument data,
1220*3d8817e4Smiod      and at descriptor for first argument.  */
1221*3d8817e4Smiod   p = buffer + 2;
1222*3d8817e4Smiod 
1223*3d8817e4Smiod   /* Figure out how long the fixed-size portion of the instruction is.
1224*3d8817e4Smiod      The only place this is stored in the opcode table is
1225*3d8817e4Smiod      in the arguments--look for arguments which specify fields in the 2nd
1226*3d8817e4Smiod      or 3rd words of the instruction.  */
1227*3d8817e4Smiod   for (d = best->args; *d; d += 2)
1228*3d8817e4Smiod     {
1229*3d8817e4Smiod       /* I don't think it is necessary to be checking d[0] here;
1230*3d8817e4Smiod 	 I suspect all this could be moved to the case statement below.  */
1231*3d8817e4Smiod       if (d[0] == '#')
1232*3d8817e4Smiod 	{
1233*3d8817e4Smiod 	  if (d[1] == 'l' && p - buffer < 6)
1234*3d8817e4Smiod 	    p = buffer + 6;
1235*3d8817e4Smiod 	  else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8')
1236*3d8817e4Smiod 	    p = buffer + 4;
1237*3d8817e4Smiod 	}
1238*3d8817e4Smiod 
1239*3d8817e4Smiod       if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
1240*3d8817e4Smiod 	p = buffer + 4;
1241*3d8817e4Smiod 
1242*3d8817e4Smiod       switch (d[1])
1243*3d8817e4Smiod 	{
1244*3d8817e4Smiod 	case '1':
1245*3d8817e4Smiod 	case '2':
1246*3d8817e4Smiod 	case '3':
1247*3d8817e4Smiod 	case '7':
1248*3d8817e4Smiod 	case '8':
1249*3d8817e4Smiod 	case '9':
1250*3d8817e4Smiod 	case 'i':
1251*3d8817e4Smiod 	  if (p - buffer < 4)
1252*3d8817e4Smiod 	    p = buffer + 4;
1253*3d8817e4Smiod 	  break;
1254*3d8817e4Smiod 	case '4':
1255*3d8817e4Smiod 	case '5':
1256*3d8817e4Smiod 	case '6':
1257*3d8817e4Smiod 	  if (p - buffer < 6)
1258*3d8817e4Smiod 	    p = buffer + 6;
1259*3d8817e4Smiod 	  break;
1260*3d8817e4Smiod 	default:
1261*3d8817e4Smiod 	  break;
1262*3d8817e4Smiod 	}
1263*3d8817e4Smiod     }
1264*3d8817e4Smiod 
1265*3d8817e4Smiod   /* pflusha is an exceptions.  It takes no arguments but is two words
1266*3d8817e4Smiod      long.  Recognize it by looking at the lower 16 bits of the mask.  */
1267*3d8817e4Smiod   if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
1268*3d8817e4Smiod     p = buffer + 4;
1269*3d8817e4Smiod 
1270*3d8817e4Smiod   /* lpstop is another exception.  It takes a one word argument but is
1271*3d8817e4Smiod      three words long.  */
1272*3d8817e4Smiod   if (p - buffer < 6
1273*3d8817e4Smiod       && (best->match & 0xffff) == 0xffff
1274*3d8817e4Smiod       && best->args[0] == '#'
1275*3d8817e4Smiod       && best->args[1] == 'w')
1276*3d8817e4Smiod     {
1277*3d8817e4Smiod       /* Copy the one word argument into the usual location for a one
1278*3d8817e4Smiod 	 word argument, to simplify printing it.  We can get away with
1279*3d8817e4Smiod 	 this because we know exactly what the second word is, and we
1280*3d8817e4Smiod 	 aren't going to print anything based on it.  */
1281*3d8817e4Smiod       p = buffer + 6;
1282*3d8817e4Smiod       FETCH_DATA (info, p);
1283*3d8817e4Smiod       buffer[2] = buffer[4];
1284*3d8817e4Smiod       buffer[3] = buffer[5];
1285*3d8817e4Smiod     }
1286*3d8817e4Smiod 
1287*3d8817e4Smiod   FETCH_DATA (info, p);
1288*3d8817e4Smiod 
1289*3d8817e4Smiod   d = best->args;
1290*3d8817e4Smiod 
1291*3d8817e4Smiod   save_p = p;
1292*3d8817e4Smiod   info->print_address_func = dummy_print_address;
1293*3d8817e4Smiod   info->fprintf_func = (fprintf_ftype) dummy_printer;
1294*3d8817e4Smiod 
1295*3d8817e4Smiod   /* We scan the operands twice.  The first time we don't print anything,
1296*3d8817e4Smiod      but look for errors.  */
1297*3d8817e4Smiod   for (; *d; d += 2)
1298*3d8817e4Smiod     {
1299*3d8817e4Smiod       int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
1300*3d8817e4Smiod 
1301*3d8817e4Smiod       if (eaten >= 0)
1302*3d8817e4Smiod 	p += eaten;
1303*3d8817e4Smiod       else if (eaten == -1)
1304*3d8817e4Smiod 	{
1305*3d8817e4Smiod 	  info->fprintf_func = save_printer;
1306*3d8817e4Smiod 	  info->print_address_func = save_print_address;
1307*3d8817e4Smiod 	  return 0;
1308*3d8817e4Smiod 	}
1309*3d8817e4Smiod       else
1310*3d8817e4Smiod 	{
1311*3d8817e4Smiod 	  info->fprintf_func (info->stream,
1312*3d8817e4Smiod 			      /* xgettext:c-format */
1313*3d8817e4Smiod 			      _("<internal error in opcode table: %s %s>\n"),
1314*3d8817e4Smiod 			      best->name,  best->args);
1315*3d8817e4Smiod 	  info->fprintf_func = save_printer;
1316*3d8817e4Smiod 	  info->print_address_func = save_print_address;
1317*3d8817e4Smiod 	  return 2;
1318*3d8817e4Smiod 	}
1319*3d8817e4Smiod     }
1320*3d8817e4Smiod 
1321*3d8817e4Smiod   p = save_p;
1322*3d8817e4Smiod   info->fprintf_func = save_printer;
1323*3d8817e4Smiod   info->print_address_func = save_print_address;
1324*3d8817e4Smiod 
1325*3d8817e4Smiod   d = best->args;
1326*3d8817e4Smiod 
1327*3d8817e4Smiod   info->fprintf_func (info->stream, "%s", best->name);
1328*3d8817e4Smiod 
1329*3d8817e4Smiod   if (*d)
1330*3d8817e4Smiod     info->fprintf_func (info->stream, " ");
1331*3d8817e4Smiod 
1332*3d8817e4Smiod   while (*d)
1333*3d8817e4Smiod     {
1334*3d8817e4Smiod       p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
1335*3d8817e4Smiod       d += 2;
1336*3d8817e4Smiod 
1337*3d8817e4Smiod       if (*d && *(d - 2) != 'I' && *d != 'k')
1338*3d8817e4Smiod 	info->fprintf_func (info->stream, ",");
1339*3d8817e4Smiod     }
1340*3d8817e4Smiod 
1341*3d8817e4Smiod   return p - buffer;
1342*3d8817e4Smiod }
1343*3d8817e4Smiod 
1344*3d8817e4Smiod /* Try to interpret the instruction at address MEMADDR as one that
1345*3d8817e4Smiod    can execute on a processor with the features given by ARCH_MASK.
1346*3d8817e4Smiod    If successful, print the instruction to INFO->STREAM and return
1347*3d8817e4Smiod    its length in bytes.  Return 0 otherwise.  */
1348*3d8817e4Smiod 
1349*3d8817e4Smiod static int
m68k_scan_mask(bfd_vma memaddr,disassemble_info * info,unsigned int arch_mask)1350*3d8817e4Smiod m68k_scan_mask (bfd_vma memaddr, disassemble_info *info,
1351*3d8817e4Smiod 		unsigned int arch_mask)
1352*3d8817e4Smiod {
1353*3d8817e4Smiod   int i;
1354*3d8817e4Smiod   const char *d;
1355*3d8817e4Smiod   static const struct m68k_opcode **opcodes[16];
1356*3d8817e4Smiod   static int numopcodes[16];
1357*3d8817e4Smiod   int val;
1358*3d8817e4Smiod   int major_opcode;
1359*3d8817e4Smiod 
1360*3d8817e4Smiod   struct private *priv = (struct private *) info->private_data;
1361*3d8817e4Smiod   bfd_byte *buffer = priv->the_buffer;
1362*3d8817e4Smiod 
1363*3d8817e4Smiod   if (!opcodes[0])
1364*3d8817e4Smiod     {
1365*3d8817e4Smiod       /* Speed up the matching by sorting the opcode
1366*3d8817e4Smiod 	 table on the upper four bits of the opcode.  */
1367*3d8817e4Smiod       const struct m68k_opcode **opc_pointer[16];
1368*3d8817e4Smiod 
1369*3d8817e4Smiod       /* First count how many opcodes are in each of the sixteen buckets.  */
1370*3d8817e4Smiod       for (i = 0; i < m68k_numopcodes; i++)
1371*3d8817e4Smiod 	numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
1372*3d8817e4Smiod 
1373*3d8817e4Smiod       /* Then create a sorted table of pointers
1374*3d8817e4Smiod 	 that point into the unsorted table.  */
1375*3d8817e4Smiod       opc_pointer[0] = xmalloc (sizeof (struct m68k_opcode *)
1376*3d8817e4Smiod 				* m68k_numopcodes);
1377*3d8817e4Smiod       opcodes[0] = opc_pointer[0];
1378*3d8817e4Smiod 
1379*3d8817e4Smiod       for (i = 1; i < 16; i++)
1380*3d8817e4Smiod 	{
1381*3d8817e4Smiod 	  opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
1382*3d8817e4Smiod 	  opcodes[i] = opc_pointer[i];
1383*3d8817e4Smiod 	}
1384*3d8817e4Smiod 
1385*3d8817e4Smiod       for (i = 0; i < m68k_numopcodes; i++)
1386*3d8817e4Smiod 	*opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
1387*3d8817e4Smiod     }
1388*3d8817e4Smiod 
1389*3d8817e4Smiod   FETCH_DATA (info, buffer + 2);
1390*3d8817e4Smiod   major_opcode = (buffer[0] >> 4) & 15;
1391*3d8817e4Smiod 
1392*3d8817e4Smiod   for (i = 0; i < numopcodes[major_opcode]; i++)
1393*3d8817e4Smiod     {
1394*3d8817e4Smiod       const struct m68k_opcode *opc = opcodes[major_opcode][i];
1395*3d8817e4Smiod       unsigned long opcode = opc->opcode;
1396*3d8817e4Smiod       unsigned long match = opc->match;
1397*3d8817e4Smiod 
1398*3d8817e4Smiod       if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
1399*3d8817e4Smiod 	  && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
1400*3d8817e4Smiod 	  /* Only fetch the next two bytes if we need to.  */
1401*3d8817e4Smiod 	  && (((0xffff & match) == 0)
1402*3d8817e4Smiod 	      ||
1403*3d8817e4Smiod 	      (FETCH_DATA (info, buffer + 4)
1404*3d8817e4Smiod 	       && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
1405*3d8817e4Smiod 	       && ((0xff & buffer[3] & match) == (0xff & opcode)))
1406*3d8817e4Smiod 	      )
1407*3d8817e4Smiod 	  && (opc->arch & arch_mask) != 0)
1408*3d8817e4Smiod 	{
1409*3d8817e4Smiod 	  /* Don't use for printout the variants of divul and divsl
1410*3d8817e4Smiod 	     that have the same register number in two places.
1411*3d8817e4Smiod 	     The more general variants will match instead.  */
1412*3d8817e4Smiod 	  for (d = opc->args; *d; d += 2)
1413*3d8817e4Smiod 	    if (d[1] == 'D')
1414*3d8817e4Smiod 	      break;
1415*3d8817e4Smiod 
1416*3d8817e4Smiod 	  /* Don't use for printout the variants of most floating
1417*3d8817e4Smiod 	     point coprocessor instructions which use the same
1418*3d8817e4Smiod 	     register number in two places, as above.  */
1419*3d8817e4Smiod 	  if (*d == '\0')
1420*3d8817e4Smiod 	    for (d = opc->args; *d; d += 2)
1421*3d8817e4Smiod 	      if (d[1] == 't')
1422*3d8817e4Smiod 		break;
1423*3d8817e4Smiod 
1424*3d8817e4Smiod 	  /* Don't match fmovel with more than one register;
1425*3d8817e4Smiod 	     wait for fmoveml.  */
1426*3d8817e4Smiod 	  if (*d == '\0')
1427*3d8817e4Smiod 	    {
1428*3d8817e4Smiod 	      for (d = opc->args; *d; d += 2)
1429*3d8817e4Smiod 		{
1430*3d8817e4Smiod 		  if (d[0] == 's' && d[1] == '8')
1431*3d8817e4Smiod 		    {
1432*3d8817e4Smiod 		      val = fetch_arg (buffer, d[1], 3, info);
1433*3d8817e4Smiod 		      if ((val & (val - 1)) != 0)
1434*3d8817e4Smiod 			break;
1435*3d8817e4Smiod 		    }
1436*3d8817e4Smiod 		}
1437*3d8817e4Smiod 	    }
1438*3d8817e4Smiod 
1439*3d8817e4Smiod 	  /* Don't match FPU insns with non-default coprocessor ID.  */
1440*3d8817e4Smiod 	  if (*d == '\0')
1441*3d8817e4Smiod 	    {
1442*3d8817e4Smiod 	      for (d = opc->args; *d; d += 2)
1443*3d8817e4Smiod 		{
1444*3d8817e4Smiod 		  if (d[0] == 'I')
1445*3d8817e4Smiod 		    {
1446*3d8817e4Smiod 		      val = fetch_arg (buffer, 'd', 3, info);
1447*3d8817e4Smiod 		      if (val != 1)
1448*3d8817e4Smiod 			break;
1449*3d8817e4Smiod 		    }
1450*3d8817e4Smiod 		}
1451*3d8817e4Smiod 	    }
1452*3d8817e4Smiod 
1453*3d8817e4Smiod 	  if (*d == '\0')
1454*3d8817e4Smiod 	    if ((val = match_insn_m68k (memaddr, info, opc)))
1455*3d8817e4Smiod 	      return val;
1456*3d8817e4Smiod 	}
1457*3d8817e4Smiod     }
1458*3d8817e4Smiod   return 0;
1459*3d8817e4Smiod }
1460*3d8817e4Smiod 
1461*3d8817e4Smiod /* Print the m68k instruction at address MEMADDR in debugged memory,
1462*3d8817e4Smiod    on INFO->STREAM.  Returns length of the instruction, in bytes.  */
1463*3d8817e4Smiod 
1464*3d8817e4Smiod int
print_insn_m68k(bfd_vma memaddr,disassemble_info * info)1465*3d8817e4Smiod print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
1466*3d8817e4Smiod {
1467*3d8817e4Smiod   unsigned int arch_mask;
1468*3d8817e4Smiod   struct private priv;
1469*3d8817e4Smiod   int val;
1470*3d8817e4Smiod 
1471*3d8817e4Smiod   bfd_byte *buffer = priv.the_buffer;
1472*3d8817e4Smiod 
1473*3d8817e4Smiod   info->private_data = (PTR) &priv;
1474*3d8817e4Smiod   /* Tell objdump to use two bytes per chunk
1475*3d8817e4Smiod      and six bytes per line for displaying raw data.  */
1476*3d8817e4Smiod   info->bytes_per_chunk = 2;
1477*3d8817e4Smiod   info->bytes_per_line = 6;
1478*3d8817e4Smiod   info->display_endian = BFD_ENDIAN_BIG;
1479*3d8817e4Smiod   priv.max_fetched = priv.the_buffer;
1480*3d8817e4Smiod   priv.insn_start = memaddr;
1481*3d8817e4Smiod 
1482*3d8817e4Smiod   if (setjmp (priv.bailout) != 0)
1483*3d8817e4Smiod     /* Error return.  */
1484*3d8817e4Smiod     return -1;
1485*3d8817e4Smiod 
1486*3d8817e4Smiod   arch_mask = bfd_m68k_mach_to_features (info->mach);
1487*3d8817e4Smiod   if (!arch_mask)
1488*3d8817e4Smiod     {
1489*3d8817e4Smiod       /* First try printing an m680x0 instruction.  Try printing a Coldfire
1490*3d8817e4Smiod 	 one if that fails.  */
1491*3d8817e4Smiod       val = m68k_scan_mask (memaddr, info, m68k_mask);
1492*3d8817e4Smiod       if (val)
1493*3d8817e4Smiod 	return val;
1494*3d8817e4Smiod 
1495*3d8817e4Smiod       val = m68k_scan_mask (memaddr, info, mcf_mask);
1496*3d8817e4Smiod       if (val)
1497*3d8817e4Smiod 	return val;
1498*3d8817e4Smiod     }
1499*3d8817e4Smiod   else
1500*3d8817e4Smiod     {
1501*3d8817e4Smiod       val = m68k_scan_mask (memaddr, info, arch_mask);
1502*3d8817e4Smiod       if (val)
1503*3d8817e4Smiod 	return val;
1504*3d8817e4Smiod     }
1505*3d8817e4Smiod 
1506*3d8817e4Smiod   /* Handle undefined instructions.  */
1507*3d8817e4Smiod   info->fprintf_func (info->stream, "0%o", (buffer[0] << 8) + buffer[1]);
1508*3d8817e4Smiod   return 2;
1509*3d8817e4Smiod }
1510