source: trunk/src/binutils/opcodes/m68k-dis.c@ 529

Last change on this file since 529 was 10, checked in by bird, 22 years ago

Initial revision

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