Fic PR 17045: Add FLAG_JSR attribute to DBT, REIT, RTD and TRAP insns.
[deliverable/binutils-gdb.git] / opcodes / m68k-dis.c
CommitLineData
5d0734a7 1/* Print Motorola 68k instructions.
84be8dcf
ILT
2 Copyright 1986, 87, 89, 91, 92, 93, 94, 95, 96, 1997
3 Free Software Foundation, Inc.
5d0734a7
JK
4
5This file is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
dbf7e45f 17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
5d0734a7
JK
18
19#include "dis-asm.h"
029e2524 20#include "floatformat.h"
84be8dcf 21#include <libiberty.h>
5d0734a7 22
5d0734a7
JK
23#include "opcode/m68k.h"
24
5d0734a7
JK
25/* Local function prototypes */
26
4df3dd02
ILT
27static int
28fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
29
30static void
31dummy_print_address PARAMS ((bfd_vma, struct disassemble_info *));
32
5d0734a7 33static int
cbe61cc6 34fetch_arg PARAMS ((unsigned char *, int, int, disassemble_info *));
5d0734a7
JK
35
36static void
dbf7e45f 37print_base PARAMS ((int, bfd_vma, disassemble_info*));
5d0734a7
JK
38
39static unsigned char *
40print_indexed PARAMS ((int, unsigned char *, bfd_vma, disassemble_info *));
41
029e2524 42static int
dbf7e45f
ILT
43print_insn_arg PARAMS ((const char *, unsigned char *, unsigned char *,
44 bfd_vma, disassemble_info *));
5d0734a7 45
5d0734a7 46CONST char * CONST fpcr_names[] = {
dbf7e45f
ILT
47 "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
48 "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"};
5d0734a7 49
dbf7e45f
ILT
50static char *const reg_names[] = {
51 "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
52 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
53 "%ps", "%pc"};
5d0734a7 54
029e2524
KR
55/* Sign-extend an (unsigned char). */
56#if __STDC__ == 1
57#define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
58#else
59#define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128)
60#endif
5d0734a7 61
029e2524 62/* Get a 1 byte signed integer. */
5d0734a7
JK
63#define NEXTBYTE(p) (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
64
029e2524
KR
65/* Get a 2 byte signed integer. */
66#define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
5d0734a7
JK
67#define NEXTWORD(p) \
68 (p += 2, FETCH_DATA (info, p), \
029e2524 69 COERCE16 ((p[-2] << 8) + p[-1]))
5d0734a7 70
029e2524
KR
71/* Get a 4 byte signed integer. */
72#define COERCE32(x) ((int) (((x) ^ 0x80000000) - 0x80000000))
5d0734a7
JK
73#define NEXTLONG(p) \
74 (p += 4, FETCH_DATA (info, p), \
029e2524 75 (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])))
5d0734a7 76
4df3dd02 77/* Get a single precision float. */
5d0734a7 78#define NEXTSINGLE(val, p) \
4df3dd02
ILT
79 (p += 4, FETCH_DATA (info, p), \
80 floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val))
5d0734a7 81
4df3dd02 82/* Get a double precision float. */
5d0734a7 83#define NEXTDOUBLE(val, p) \
4df3dd02
ILT
84 (p += 8, FETCH_DATA (info, p), \
85 floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val))
5d0734a7 86
4df3dd02
ILT
87/* Get an extended precision float. */
88#define NEXTEXTEND(val, p) \
89 (p += 12, FETCH_DATA (info, p), \
90 floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val))
5d0734a7
JK
91
92/* Need a function to convert from packed to double
93 precision. Actually, it's easier to print a
94 packed number than a double anyway, so maybe
95 there should be a special case to handle this... */
96#define NEXTPACKED(p) \
97 (p += 12, FETCH_DATA (info, p), 0.0)
98
99\f
100/* Maximum length of an instruction. */
101#define MAXLEN 22
102
103#include <setjmp.h>
104
105struct private
106{
107 /* Points to first byte not fetched. */
108 bfd_byte *max_fetched;
109 bfd_byte the_buffer[MAXLEN];
110 bfd_vma insn_start;
111 jmp_buf bailout;
112};
113
114/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
115 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
116 on error. */
117#define FETCH_DATA(info, addr) \
118 ((addr) <= ((struct private *)(info->private_data))->max_fetched \
119 ? 1 : fetch_data ((info), (addr)))
120
121static int
122fetch_data (info, addr)
123 struct disassemble_info *info;
124 bfd_byte *addr;
125{
126 int status;
127 struct private *priv = (struct private *)info->private_data;
128 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
129
130 status = (*info->read_memory_func) (start,
131 priv->max_fetched,
132 addr - priv->max_fetched,
133 info);
134 if (status != 0)
135 {
136 (*info->memory_error_func) (status, start, info);
05545edc 137 longjmp (priv->bailout, 1);
5d0734a7
JK
138 }
139 else
140 priv->max_fetched = addr;
141 return 1;
142}
143\f
029e2524
KR
144/* This function is used to print to the bit-bucket. */
145static int
146#ifdef __STDC__
147dummy_printer (FILE * file, const char * format, ...)
148#else
149dummy_printer (file) FILE *file;
150#endif
151 { return 0; }
152
4df3dd02 153static void
029e2524
KR
154dummy_print_address (vma, info)
155 bfd_vma vma;
5d0734a7 156 struct disassemble_info *info;
5d0734a7 157{
029e2524
KR
158}
159
5d0734a7 160/* Print the m68k instruction at address MEMADDR in debugged memory,
029e2524 161 on INFO->STREAM. Returns length of the instruction, in bytes. */
5d0734a7
JK
162
163int
164print_insn_m68k (memaddr, info)
165 bfd_vma memaddr;
166 disassemble_info *info;
167{
168 register int i;
169 register unsigned char *p;
029e2524 170 unsigned char *save_p;
dbf7e45f 171 register const char *d;
5d0734a7 172 register unsigned long bestmask;
029e2524 173 const struct m68k_opcode *best = 0;
5d0734a7
JK
174 struct private priv;
175 bfd_byte *buffer = priv.the_buffer;
029e2524
KR
176 fprintf_ftype save_printer = info->fprintf_func;
177 void (*save_print_address) PARAMS((bfd_vma, struct disassemble_info*))
178 = info->print_address_func;
84be8dcf
ILT
179 int major_opcode;
180 static int numopcodes[16];
181 static const struct m68k_opcode **opcodes[16];
182
183 if (!opcodes[0])
184 {
185 /* Speed up the matching by sorting the opcode table on the upper
186 four bits of the opcode. */
187 const struct m68k_opcode **opc_pointer[16];
188
189 /* First count how many opcodes are in each of the sixteen buckets. */
190 for (i = 0; i < m68k_numopcodes; i++)
191 numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
192
193 /* Then create a sorted table of pointers that point into the
194 unsorted table. */
195 opc_pointer[0] = ((const struct m68k_opcode **)
196 xmalloc (sizeof (struct m68k_opcode *)
197 * m68k_numopcodes));
198 opcodes[0] = opc_pointer[0];
199 for (i = 1; i < 16; i++)
200 {
201 opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
202 opcodes[i] = opc_pointer[i];
203 }
204
205 for (i = 0; i < m68k_numopcodes; i++)
206 *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
207
208 }
5d0734a7
JK
209
210 info->private_data = (PTR) &priv;
4df3dd02
ILT
211 /* Tell objdump to use two bytes per chunk and six bytes per line for
212 displaying raw data. */
213 info->bytes_per_chunk = 2;
214 info->bytes_per_line = 6;
215 info->display_endian = BFD_ENDIAN_BIG;
5d0734a7
JK
216 priv.max_fetched = priv.the_buffer;
217 priv.insn_start = memaddr;
218 if (setjmp (priv.bailout) != 0)
219 /* Error return. */
220 return -1;
221
222 bestmask = 0;
5d0734a7 223 FETCH_DATA (info, buffer + 2);
84be8dcf
ILT
224 major_opcode = (buffer[0] >> 4) & 15;
225 for (i = 0; i < numopcodes[major_opcode]; i++)
5d0734a7 226 {
84be8dcf 227 const struct m68k_opcode *opc = opcodes[major_opcode][i];
029e2524
KR
228 unsigned long opcode = opc->opcode;
229 unsigned long match = opc->match;
230
5d0734a7
JK
231 if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
232 && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
233 /* Only fetch the next two bytes if we need to. */
234 && (((0xffff & match) == 0)
235 ||
236 (FETCH_DATA (info, buffer + 4)
237 && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
238 && ((0xff & buffer[3] & match) == (0xff & opcode)))
239 ))
240 {
241 /* Don't use for printout the variants of divul and divsl
242 that have the same register number in two places.
243 The more general variants will match instead. */
029e2524 244 for (d = opc->args; *d; d += 2)
5d0734a7
JK
245 if (d[1] == 'D')
246 break;
247
248 /* Don't use for printout the variants of most floating
249 point coprocessor instructions which use the same
250 register number in two places, as above. */
84be8dcf 251 if (*d == '\0')
029e2524 252 for (d = opc->args; *d; d += 2)
5d0734a7
JK
253 if (d[1] == 't')
254 break;
255
84be8dcf
ILT
256 /* Don't match fmovel with more than one register; wait for
257 fmoveml. */
258 if (*d == '\0')
259 {
260 for (d = opc->args; *d; d += 2)
261 {
262 if (d[0] == 's' && d[1] == '8')
263 {
264 int val;
265
266 val = fetch_arg (buffer, d[1], 3, info);
267 if ((val & (val - 1)) != 0)
268 break;
269 }
270 }
271 }
272
273 if (*d == '\0' && match > bestmask)
5d0734a7 274 {
029e2524 275 best = opc;
5d0734a7
JK
276 bestmask = match;
277 }
278 }
279 }
280
029e2524
KR
281 if (best == 0)
282 goto invalid;
5d0734a7
JK
283
284 /* Point at first word of argument data,
285 and at descriptor for first argument. */
286 p = buffer + 2;
287
e6fb7139
JK
288 /* Figure out how long the fixed-size portion of the instruction is.
289 The only place this is stored in the opcode table is
290 in the arguments--look for arguments which specify fields in the 2nd
291 or 3rd words of the instruction. */
029e2524 292 for (d = best->args; *d; d += 2)
5d0734a7 293 {
e6fb7139
JK
294 /* I don't think it is necessary to be checking d[0] here; I suspect
295 all this could be moved to the case statement below. */
5d0734a7
JK
296 if (d[0] == '#')
297 {
298 if (d[1] == 'l' && p - buffer < 6)
299 p = buffer + 6;
300 else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
301 p = buffer + 4;
302 }
5d0734a7
JK
303 if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
304 p = buffer + 4;
e6fb7139
JK
305 switch (d[1])
306 {
307 case '1':
308 case '2':
309 case '3':
310 case '7':
311 case '8':
312 case '9':
029e2524 313 case 'i':
e6fb7139
JK
314 if (p - buffer < 4)
315 p = buffer + 4;
316 break;
317 case '4':
318 case '5':
319 case '6':
320 if (p - buffer < 6)
321 p = buffer + 6;
322 break;
323 default:
324 break;
325 }
5d0734a7 326 }
4df3dd02
ILT
327
328 /* pflusha is an exceptions. It takes no arguments but is two words
329 long. Recognize it by looking at the lower 16 bits of the mask. */
dbf7e45f 330 if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
e6fb7139 331 p = buffer + 4;
4df3dd02
ILT
332
333 /* lpstop is another exception. It takes a one word argument but is
334 three words long. */
335 if (p - buffer < 6
336 && (best->match & 0xffff) == 0xffff
337 && best->args[0] == '#'
338 && best->args[1] == 'w')
339 {
340 /* Copy the one word argument into the usual location for a one
341 word argument, to simplify printing it. We can get away with
342 this because we know exactly what the second word is, and we
343 aren't going to print anything based on it. */
344 p = buffer + 6;
345 FETCH_DATA (info, p);
346 buffer[2] = buffer[4];
347 buffer[3] = buffer[5];
348 }
349
5d0734a7
JK
350 FETCH_DATA (info, p);
351
029e2524
KR
352 d = best->args;
353
354 /* We can the operands twice. The first time we don't print anything,
355 but look for errors. */
356
357 save_p = p;
358 info->print_address_func = dummy_print_address;
359 info->fprintf_func = (fprintf_ftype)dummy_printer;
360 for ( ; *d; d += 2)
361 {
362 int eaten = print_insn_arg (d, buffer, p, memaddr + p - buffer, info);
363 if (eaten >= 0)
364 p += eaten;
365 else if (eaten == -1)
366 goto invalid;
367 else
368 {
369 (*info->fprintf_func)(info->stream,
370 "<internal error in opcode table: %s %s>\n",
371 best->name,
372 best->args);
373 goto invalid;
374 }
375
376 }
377 p = save_p;
378 info->fprintf_func = save_printer;
379 info->print_address_func = save_print_address;
380
381 d = best->args;
382
383 (*info->fprintf_func) (info->stream, "%s", best->name);
5d0734a7
JK
384
385 if (*d)
386 (*info->fprintf_func) (info->stream, " ");
387
388 while (*d)
389 {
029e2524 390 p += print_insn_arg (d, buffer, p, memaddr + p - buffer, info);
5d0734a7
JK
391 d += 2;
392 if (*d && *(d - 2) != 'I' && *d != 'k')
393 (*info->fprintf_func) (info->stream, ",");
394 }
395 return p - buffer;
029e2524
KR
396
397 invalid:
398 /* Handle undefined instructions. */
399 info->fprintf_func = save_printer;
400 info->print_address_func = save_print_address;
401 (*info->fprintf_func) (info->stream, "0%o",
402 (buffer[0] << 8) + buffer[1]);
403 return 2;
5d0734a7
JK
404}
405
029e2524
KR
406/* Returns number of bytes "eaten" by the operand, or
407 return -1 if an invalid operand was found, or -2 if
408 an opcode tabe error was found. */
409
410static int
411print_insn_arg (d, buffer, p0, addr, info)
dbf7e45f 412 const char *d;
5d0734a7 413 unsigned char *buffer;
029e2524 414 unsigned char *p0;
5d0734a7
JK
415 bfd_vma addr; /* PC for this arg to be relative to */
416 disassemble_info *info;
417{
418 register int val = 0;
419 register int place = d[1];
029e2524 420 register unsigned char *p = p0;
5d0734a7
JK
421 int regno;
422 register CONST char *regname;
423 register unsigned char *p1;
424 double flval;
425 int flt_p;
426
427 switch (*d)
428 {
429 case 'c': /* cache identifier */
430 {
dbf7e45f 431 static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
5d0734a7
JK
432 val = fetch_arg (buffer, place, 2, info);
433 (*info->fprintf_func) (info->stream, cacheFieldName[val]);
434 break;
435 }
436
437 case 'a': /* address register indirect only. Cf. case '+'. */
438 {
439 (*info->fprintf_func)
440 (info->stream,
441 "%s@",
442 reg_names [fetch_arg (buffer, place, 3, info) + 8]);
443 break;
444 }
445
446 case '_': /* 32-bit absolute address for move16. */
447 {
448 val = NEXTLONG (p);
e6fb7139 449 (*info->print_address_func) (val, info);
5d0734a7
JK
450 break;
451 }
452
453 case 'C':
dbf7e45f 454 (*info->fprintf_func) (info->stream, "%%ccr");
5d0734a7
JK
455 break;
456
457 case 'S':
dbf7e45f 458 (*info->fprintf_func) (info->stream, "%%sr");
5d0734a7
JK
459 break;
460
461 case 'U':
dbf7e45f 462 (*info->fprintf_func) (info->stream, "%%usp");
5d0734a7
JK
463 break;
464
465 case 'J':
466 {
dbf7e45f
ILT
467 static const struct { char *name; int value; } names[]
468 = {{"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
469 {"%tc", 0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
470 {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
471 {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
4df3dd02 472 {"%msp", 0x803}, {"%isp", 0x804},
e6fb7139
JK
473
474 /* Should we be calling this psr like we do in case 'Y'? */
dbf7e45f 475 {"%mmusr",0x805},
e6fb7139 476
dbf7e45f 477 {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808}};
5d0734a7
JK
478
479 val = fetch_arg (buffer, place, 12, info);
480 for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
481 if (names[regno].value == val)
482 {
dbf7e45f 483 (*info->fprintf_func) (info->stream, "%s", names[regno].name);
5d0734a7
JK
484 break;
485 }
486 if (regno < 0)
487 (*info->fprintf_func) (info->stream, "%d", val);
488 }
489 break;
490
491 case 'Q':
492 val = fetch_arg (buffer, place, 3, info);
493 /* 0 means 8, except for the bkpt instruction... */
494 if (val == 0 && d[1] != 's')
495 val = 8;
496 (*info->fprintf_func) (info->stream, "#%d", val);
497 break;
498
499 case 'M':
500 val = fetch_arg (buffer, place, 8, info);
501 if (val & 0x80)
502 val = val - 0x100;
503 (*info->fprintf_func) (info->stream, "#%d", val);
504 break;
505
506 case 'T':
507 val = fetch_arg (buffer, place, 4, info);
508 (*info->fprintf_func) (info->stream, "#%d", val);
509 break;
510
511 case 'D':
512 (*info->fprintf_func) (info->stream, "%s",
513 reg_names[fetch_arg (buffer, place, 3, info)]);
514 break;
515
516 case 'A':
517 (*info->fprintf_func)
518 (info->stream, "%s",
519 reg_names[fetch_arg (buffer, place, 3, info) + 010]);
520 break;
521
522 case 'R':
523 (*info->fprintf_func)
524 (info->stream, "%s",
525 reg_names[fetch_arg (buffer, place, 4, info)]);
526 break;
527
528 case 'r':
dbf7e45f
ILT
529 regno = fetch_arg (buffer, place, 4, info);
530 if (regno > 7)
531 (*info->fprintf_func) (info->stream, "%s@", reg_names[regno]);
532 else
533 (*info->fprintf_func) (info->stream, "@(%s)", reg_names[regno]);
5d0734a7
JK
534 break;
535
536 case 'F':
537 (*info->fprintf_func)
dbf7e45f 538 (info->stream, "%%fp%d",
5d0734a7
JK
539 fetch_arg (buffer, place, 3, info));
540 break;
541
542 case 'O':
543 val = fetch_arg (buffer, place, 6, info);
544 if (val & 0x20)
545 (*info->fprintf_func) (info->stream, "%s", reg_names [val & 7]);
546 else
547 (*info->fprintf_func) (info->stream, "%d", val);
548 break;
549
550 case '+':
551 (*info->fprintf_func)
552 (info->stream, "%s@+",
553 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
554 break;
555
556 case '-':
557 (*info->fprintf_func)
558 (info->stream, "%s@-",
559 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
560 break;
561
562 case 'k':
563 if (place == 'k')
564 (*info->fprintf_func)
565 (info->stream, "{%s}",
566 reg_names[fetch_arg (buffer, place, 3, info)]);
567 else if (place == 'C')
568 {
569 val = fetch_arg (buffer, place, 7, info);
570 if ( val > 63 ) /* This is a signed constant. */
571 val -= 128;
572 (*info->fprintf_func) (info->stream, "{#%d}", val);
573 }
574 else
029e2524 575 return -2;
5d0734a7
JK
576 break;
577
578 case '#':
579 case '^':
580 p1 = buffer + (*d == '#' ? 2 : 4);
581 if (place == 's')
582 val = fetch_arg (buffer, place, 4, info);
583 else if (place == 'C')
584 val = fetch_arg (buffer, place, 7, info);
585 else if (place == '8')
586 val = fetch_arg (buffer, place, 3, info);
587 else if (place == '3')
588 val = fetch_arg (buffer, place, 8, info);
589 else if (place == 'b')
590 val = NEXTBYTE (p1);
dbf7e45f 591 else if (place == 'w' || place == 'W')
5d0734a7
JK
592 val = NEXTWORD (p1);
593 else if (place == 'l')
594 val = NEXTLONG (p1);
595 else
029e2524 596 return -2;
5d0734a7
JK
597 (*info->fprintf_func) (info->stream, "#%d", val);
598 break;
599
600 case 'B':
601 if (place == 'b')
602 val = NEXTBYTE (p);
603 else if (place == 'B')
604 val = COERCE_SIGNED_CHAR(buffer[1]);
605 else if (place == 'w' || place == 'W')
606 val = NEXTWORD (p);
dbf7e45f 607 else if (place == 'l' || place == 'L' || place == 'C')
5d0734a7
JK
608 val = NEXTLONG (p);
609 else if (place == 'g')
610 {
611 val = NEXTBYTE (buffer);
612 if (val == 0)
613 val = NEXTWORD (p);
614 else if (val == -1)
615 val = NEXTLONG (p);
616 }
617 else if (place == 'c')
618 {
619 if (buffer[1] & 0x40) /* If bit six is one, long offset */
620 val = NEXTLONG (p);
621 else
622 val = NEXTWORD (p);
623 }
624 else
029e2524 625 return -2;
5d0734a7 626
e6fb7139 627 (*info->print_address_func) (addr + val, info);
5d0734a7
JK
628 break;
629
630 case 'd':
631 val = NEXTWORD (p);
632 (*info->fprintf_func)
633 (info->stream, "%s@(%d)",
4df3dd02 634 reg_names[fetch_arg (buffer, place, 3, info) + 8], val);
5d0734a7
JK
635 break;
636
637 case 's':
638 (*info->fprintf_func) (info->stream, "%s",
639 fpcr_names[fetch_arg (buffer, place, 3, info)]);
640 break;
641
642 case 'I':
643 /* Get coprocessor ID... */
644 val = fetch_arg (buffer, 'd', 3, info);
645
646 if (val != 1) /* Unusual coprocessor ID? */
647 (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
5d0734a7
JK
648 break;
649
650 case '*':
651 case '~':
652 case '%':
653 case ';':
654 case '@':
655 case '!':
656 case '$':
657 case '?':
658 case '/':
659 case '&':
e6fb7139 660 case '|':
84be8dcf
ILT
661 case '<':
662 case '>':
5d0734a7
JK
663
664 if (place == 'd')
665 {
666 val = fetch_arg (buffer, 'x', 6, info);
667 val = ((val & 7) << 3) + ((val >> 3) & 7);
668 }
669 else
670 val = fetch_arg (buffer, 's', 6, info);
671
672 /* Get register number assuming address register. */
673 regno = (val & 7) + 8;
674 regname = reg_names[regno];
675 switch (val >> 3)
676 {
677 case 0:
678 (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
679 break;
680
681 case 1:
682 (*info->fprintf_func) (info->stream, "%s", regname);
683 break;
684
685 case 2:
686 (*info->fprintf_func) (info->stream, "%s@", regname);
687 break;
688
689 case 3:
690 (*info->fprintf_func) (info->stream, "%s@+", regname);
691 break;
692
693 case 4:
694 (*info->fprintf_func) (info->stream, "%s@-", regname);
695 break;
696
697 case 5:
698 val = NEXTWORD (p);
699 (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
700 break;
701
702 case 6:
703 p = print_indexed (regno, p, addr, info);
704 break;
705
706 case 7:
707 switch (val & 7)
708 {
709 case 0:
710 val = NEXTWORD (p);
e6fb7139 711 (*info->print_address_func) (val, info);
5d0734a7
JK
712 break;
713
714 case 1:
715 val = NEXTLONG (p);
e6fb7139 716 (*info->print_address_func) (val, info);
5d0734a7
JK
717 break;
718
719 case 2:
720 val = NEXTWORD (p);
4df3dd02 721 (*info->fprintf_func) (info->stream, "%%pc@(");
e6fb7139 722 (*info->print_address_func) (addr + val, info);
4df3dd02 723 (*info->fprintf_func) (info->stream, ")");
5d0734a7
JK
724 break;
725
726 case 3:
727 p = print_indexed (-1, p, addr, info);
728 break;
729
730 case 4:
731 flt_p = 1; /* Assume it's a float... */
732 switch( place )
733 {
734 case 'b':
735 val = NEXTBYTE (p);
736 flt_p = 0;
737 break;
738
739 case 'w':
740 val = NEXTWORD (p);
741 flt_p = 0;
742 break;
743
744 case 'l':
745 val = NEXTLONG (p);
746 flt_p = 0;
747 break;
748
749 case 'f':
750 NEXTSINGLE(flval, p);
751 break;
752
753 case 'F':
754 NEXTDOUBLE(flval, p);
755 break;
756
757 case 'x':
4df3dd02 758 NEXTEXTEND(flval, p);
5d0734a7
JK
759 break;
760
761 case 'p':
762 flval = NEXTPACKED(p);
763 break;
764
765 default:
029e2524 766 return -1;
5d0734a7
JK
767 }
768 if ( flt_p ) /* Print a float? */
769 (*info->fprintf_func) (info->stream, "#%g", flval);
770 else
771 (*info->fprintf_func) (info->stream, "#%d", val);
772 break;
773
774 default:
029e2524 775 return -1;
5d0734a7
JK
776 }
777 }
778 break;
779
780 case 'L':
781 case 'l':
782 if (place == 'w')
783 {
784 char doneany;
785 p1 = buffer + 2;
786 val = NEXTWORD (p1);
787 /* Move the pointer ahead if this point is farther ahead
788 than the last. */
789 p = p1 > p ? p1 : p;
790 if (val == 0)
791 {
792 (*info->fprintf_func) (info->stream, "#0");
793 break;
794 }
795 if (*d == 'l')
796 {
797 register int newval = 0;
798 for (regno = 0; regno < 16; ++regno)
799 if (val & (0x8000 >> regno))
800 newval |= 1 << regno;
801 val = newval;
802 }
803 val &= 0xffff;
804 doneany = 0;
805 for (regno = 0; regno < 16; ++regno)
806 if (val & (1 << regno))
807 {
808 int first_regno;
809 if (doneany)
810 (*info->fprintf_func) (info->stream, "/");
811 doneany = 1;
812 (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
813 first_regno = regno;
814 while (val & (1 << (regno + 1)))
815 ++regno;
816 if (regno > first_regno)
817 (*info->fprintf_func) (info->stream, "-%s",
818 reg_names[regno]);
819 }
820 }
821 else if (place == '3')
822 {
823 /* `fmovem' insn. */
824 char doneany;
825 val = fetch_arg (buffer, place, 8, info);
826 if (val == 0)
827 {
828 (*info->fprintf_func) (info->stream, "#0");
829 break;
830 }
831 if (*d == 'l')
832 {
833 register int newval = 0;
834 for (regno = 0; regno < 8; ++regno)
835 if (val & (0x80 >> regno))
836 newval |= 1 << regno;
837 val = newval;
838 }
839 val &= 0xff;
840 doneany = 0;
841 for (regno = 0; regno < 8; ++regno)
842 if (val & (1 << regno))
843 {
844 int first_regno;
845 if (doneany)
846 (*info->fprintf_func) (info->stream, "/");
847 doneany = 1;
dbf7e45f 848 (*info->fprintf_func) (info->stream, "%%fp%d", regno);
5d0734a7
JK
849 first_regno = regno;
850 while (val & (1 << (regno + 1)))
851 ++regno;
852 if (regno > first_regno)
dbf7e45f 853 (*info->fprintf_func) (info->stream, "-%%fp%d", regno);
5d0734a7
JK
854 }
855 }
84be8dcf
ILT
856 else if (place == '8')
857 {
858 /* fmoveml for FP status registers */
859 (*info->fprintf_func) (info->stream, "%s",
860 fpcr_names[fetch_arg (buffer, place, 3,
861 info)]);
862 }
5d0734a7 863 else
029e2524 864 return -2;
5d0734a7
JK
865 break;
866
e6fb7139
JK
867 case 'X':
868 place = '8';
869 case 'Y':
870 case 'Z':
871 case 'W':
dbf7e45f
ILT
872 case '0':
873 case '1':
874 case '2':
e6fb7139 875 case '3':
e6fb7139
JK
876 {
877 int val = fetch_arg (buffer, place, 5, info);
878 char *name = 0;
879 switch (val)
880 {
dbf7e45f
ILT
881 case 2: name = "%tt0"; break;
882 case 3: name = "%tt1"; break;
883 case 0x10: name = "%tc"; break;
884 case 0x11: name = "%drp"; break;
885 case 0x12: name = "%srp"; break;
886 case 0x13: name = "%crp"; break;
887 case 0x14: name = "%cal"; break;
888 case 0x15: name = "%val"; break;
889 case 0x16: name = "%scc"; break;
890 case 0x17: name = "%ac"; break;
891 case 0x18: name = "%psr"; break;
892 case 0x19: name = "%pcsr"; break;
e6fb7139
JK
893 case 0x1c:
894 case 0x1d:
895 {
896 int break_reg = ((buffer[3] >> 2) & 7);
897 (*info->fprintf_func)
dbf7e45f 898 (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
e6fb7139
JK
899 break_reg);
900 }
901 break;
902 default:
903 (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
904 }
905 if (name)
dbf7e45f 906 (*info->fprintf_func) (info->stream, "%s", name);
e6fb7139
JK
907 }
908 break;
909
910 case 'f':
911 {
912 int fc = fetch_arg (buffer, place, 5, info);
913 if (fc == 1)
dbf7e45f 914 (*info->fprintf_func) (info->stream, "%%dfc");
e6fb7139 915 else if (fc == 0)
dbf7e45f 916 (*info->fprintf_func) (info->stream, "%%sfc");
e6fb7139
JK
917 else
918 (*info->fprintf_func) (info->stream, "<function code %d>", fc);
919 }
920 break;
921
922 case 'V':
dbf7e45f 923 (*info->fprintf_func) (info->stream, "%%val");
e6fb7139
JK
924 break;
925
926 case 't':
927 {
928 int level = fetch_arg (buffer, place, 3, info);
929 (*info->fprintf_func) (info->stream, "%d", level);
930 }
931 break;
932
029e2524
KR
933 default:
934 return -2;
5d0734a7
JK
935 }
936
029e2524 937 return p - p0;
5d0734a7
JK
938}
939
940/* Fetch BITS bits from a position in the instruction specified by CODE.
941 CODE is a "place to put an argument", or 'x' for a destination
942 that is a general address (mode and register).
943 BUFFER contains the instruction. */
944
945static int
946fetch_arg (buffer, code, bits, info)
947 unsigned char *buffer;
948 int code;
949 int bits;
950 disassemble_info *info;
951{
952 register int val = 0;
953 switch (code)
954 {
955 case 's':
956 val = buffer[1];
957 break;
958
959 case 'd': /* Destination, for register or quick. */
960 val = (buffer[0] << 8) + buffer[1];
961 val >>= 9;
962 break;
963
964 case 'x': /* Destination, for general arg */
965 val = (buffer[0] << 8) + buffer[1];
966 val >>= 6;
967 break;
968
969 case 'k':
970 FETCH_DATA (info, buffer + 3);
971 val = (buffer[3] >> 4);
972 break;
973
974 case 'C':
975 FETCH_DATA (info, buffer + 3);
976 val = buffer[3];
977 break;
978
979 case '1':
980 FETCH_DATA (info, buffer + 3);
981 val = (buffer[2] << 8) + buffer[3];
982 val >>= 12;
983 break;
984
985 case '2':
986 FETCH_DATA (info, buffer + 3);
987 val = (buffer[2] << 8) + buffer[3];
988 val >>= 6;
989 break;
990
991 case '3':
992 case 'j':
993 FETCH_DATA (info, buffer + 3);
994 val = (buffer[2] << 8) + buffer[3];
995 break;
996
997 case '4':
998 FETCH_DATA (info, buffer + 5);
999 val = (buffer[4] << 8) + buffer[5];
1000 val >>= 12;
1001 break;
1002
1003 case '5':
1004 FETCH_DATA (info, buffer + 5);
1005 val = (buffer[4] << 8) + buffer[5];
1006 val >>= 6;
1007 break;
1008
1009 case '6':
1010 FETCH_DATA (info, buffer + 5);
1011 val = (buffer[4] << 8) + buffer[5];
1012 break;
1013
1014 case '7':
1015 FETCH_DATA (info, buffer + 3);
1016 val = (buffer[2] << 8) + buffer[3];
1017 val >>= 7;
1018 break;
1019
1020 case '8':
1021 FETCH_DATA (info, buffer + 3);
1022 val = (buffer[2] << 8) + buffer[3];
1023 val >>= 10;
1024 break;
1025
1026 case '9':
1027 FETCH_DATA (info, buffer + 3);
1028 val = (buffer[2] << 8) + buffer[3];
1029 val >>= 5;
1030 break;
1031
1032 case 'e':
1033 val = (buffer[1] >> 6);
1034 break;
1035
1036 default:
1037 abort ();
1038 }
1039
1040 switch (bits)
1041 {
1042 case 2:
1043 return val & 3;
1044 case 3:
1045 return val & 7;
1046 case 4:
1047 return val & 017;
1048 case 5:
1049 return val & 037;
1050 case 6:
1051 return val & 077;
1052 case 7:
1053 return val & 0177;
1054 case 8:
1055 return val & 0377;
1056 case 12:
1057 return val & 07777;
1058 default:
1059 abort ();
1060 }
1061}
1062
1063/* Print an indexed argument. The base register is BASEREG (-1 for pc).
1064 P points to extension word, in buffer.
1065 ADDR is the nominal core address of that extension word. */
1066
1067static unsigned char *
1068print_indexed (basereg, p, addr, info)
1069 int basereg;
1070 unsigned char *p;
1071 bfd_vma addr;
1072 disassemble_info *info;
1073{
1074 register int word;
dbf7e45f
ILT
1075 static char *const scales[] = {"", ":2", ":4", ":8"};
1076 bfd_vma base_disp;
1077 bfd_vma outer_disp;
5d0734a7 1078 char buf[40];
dbf7e45f 1079 char vmabuf[50];
5d0734a7
JK
1080
1081 word = NEXTWORD (p);
1082
1083 /* Generate the text for the index register.
1084 Where this will be output is not yet determined. */
dbf7e45f 1085 sprintf (buf, "%s:%c%s",
5d0734a7
JK
1086 reg_names[(word >> 12) & 0xf],
1087 (word & 0x800) ? 'l' : 'w',
1088 scales[(word >> 9) & 3]);
1089
1090 /* Handle the 68000 style of indexing. */
1091
1092 if ((word & 0x100) == 0)
1093 {
dbf7e45f
ILT
1094 word &= 0xff;
1095 if ((word & 0x80) != 0)
1096 word -= 0x100;
1097 if (basereg == -1)
1098 word += addr;
1099 print_base (basereg, word, info);
1100 (*info->fprintf_func) (info->stream, ",%s)", buf);
5d0734a7
JK
1101 return p;
1102 }
1103
1104 /* Handle the generalized kind. */
1105 /* First, compute the displacement to add to the base register. */
1106
1107 if (word & 0200)
dbf7e45f
ILT
1108 {
1109 if (basereg == -1)
1110 basereg = -3;
1111 else
1112 basereg = -2;
1113 }
5d0734a7 1114 if (word & 0100)
dbf7e45f 1115 buf[0] = '\0';
5d0734a7
JK
1116 base_disp = 0;
1117 switch ((word >> 4) & 3)
1118 {
1119 case 2:
1120 base_disp = NEXTWORD (p);
1121 break;
1122 case 3:
1123 base_disp = NEXTLONG (p);
1124 }
1125 if (basereg == -1)
1126 base_disp += addr;
1127
1128 /* Handle single-level case (not indirect) */
1129
1130 if ((word & 7) == 0)
1131 {
1132 print_base (basereg, base_disp, info);
dbf7e45f
ILT
1133 if (buf[0] != '\0')
1134 (*info->fprintf_func) (info->stream, ",%s", buf);
1135 (*info->fprintf_func) (info->stream, ")");
5d0734a7
JK
1136 return p;
1137 }
1138
1139 /* Two level. Compute displacement to add after indirection. */
1140
1141 outer_disp = 0;
1142 switch (word & 3)
1143 {
1144 case 2:
1145 outer_disp = NEXTWORD (p);
1146 break;
1147 case 3:
1148 outer_disp = NEXTLONG (p);
1149 }
1150
5d0734a7 1151 print_base (basereg, base_disp, info);
dbf7e45f
ILT
1152 if ((word & 4) == 0 && buf[0] != '\0')
1153 {
1154 (*info->fprintf_func) (info->stream, ",%s", buf);
1155 buf[0] = '\0';
1156 }
1157 sprintf_vma (vmabuf, outer_disp);
1158 (*info->fprintf_func) (info->stream, ")@(%s", vmabuf);
1159 if (buf[0] != '\0')
1160 (*info->fprintf_func) (info->stream, ",%s", buf);
1161 (*info->fprintf_func) (info->stream, ")");
5d0734a7
JK
1162
1163 return p;
1164}
1165
1166/* Print a base register REGNO and displacement DISP, on INFO->STREAM.
1167 REGNO = -1 for pc, -2 for none (suppressed). */
1168
1169static void
1170print_base (regno, disp, info)
1171 int regno;
dbf7e45f 1172 bfd_vma disp;
5d0734a7
JK
1173 disassemble_info *info;
1174{
dbf7e45f
ILT
1175 if (regno == -1)
1176 {
1177 (*info->fprintf_func) (info->stream, "%%pc@(");
1178 (*info->print_address_func) (disp, info);
1179 }
5d0734a7 1180 else
dbf7e45f
ILT
1181 {
1182 char buf[50];
1183
1184 if (regno == -2)
1185 (*info->fprintf_func) (info->stream, "@(");
1186 else if (regno == -3)
1187 (*info->fprintf_func) (info->stream, "%%zpc@(");
1188 else
1189 (*info->fprintf_func) (info->stream, "%s@(", reg_names[regno]);
1190
1191 sprintf_vma (buf, disp);
1192 (*info->fprintf_func) (info->stream, "%s", buf);
1193 }
5d0734a7 1194}
This page took 0.298095 seconds and 4 git commands to generate.