source: branches/libc-0.6/src/binutils/opcodes/m68k-dis.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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