ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/disass/m68k-dis.c
Revision: 1.2
Committed: 2000-09-25T17:52:34Z (24 years, 2 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.1: +18 -32 lines
Log Message:
- updated A-Trap table
- MacOS disassembler features are turned on by "-m" option
- "rmon" -> "mon -r"
- updated docs

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