ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/disass/m68k-dis.c
Revision: 1.1
Committed: 2000-09-25T12:44:38Z (23 years, 8 months ago) by cebix
Content type: text/plain
Branch: MAIN
Log Message:
- replaced 680x0 and 80x86 disassemblers with the ones from GNU binutils
- 680x0 disassembler shows symbolic MacOS low memory globals

File Contents

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