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