ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/disass/m68k-dis.c
Revision: 1.6
Committed: 2004-06-14T14:37:09Z (20 years, 3 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: release_3-2, HEAD
Changes since 1.5: +9 -5 lines
Log Message:
Even more m68k disassembler fixes.

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