ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/mon/src/disass/m68k-dis.c
Revision: 1.3
Committed: 2002-09-07T12:48:15Z (22 years ago) by gbeauche
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -0 lines
Log Message:
Add support for x86-64 disassembly
- mon.cpp (mon_init): new command is "d8664"
- mon_cmd.cpp (disassemble): handle CPU_x86_64, and make it 64-bit aware in
  address dumps
- mon_disass.cpp (disass_x86): s/bool i8086/uint32 bits/ defining the x86
  architecture "size", aka 16 => 8086, 32 => 80x86, 64 => x86-64
- Merge with GNU x86 disassembler as part of binutils 2.12.90.0.15

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 cebix 1.2 #if 1
678     (*info->fprintf_func) (info->stream, "$%08x", addr + disp);
679     #else
680 cebix 1.1 (*info->print_address_func) (addr + disp, info);
681 cebix 1.2 #endif
682 cebix 1.1 break;
683    
684     case 'd':
685     val = NEXTWORD (p);
686     (*info->fprintf_func)
687     (info->stream, "($%04x,%s)",
688     val, reg_names[fetch_arg (buffer, place, 3, info) + 8]);
689     break;
690    
691     case 's':
692     (*info->fprintf_func) (info->stream, "%s",
693     fpcr_names[fetch_arg (buffer, place, 3, info)]);
694     break;
695    
696     case 'I':
697     /* Get coprocessor ID... */
698     val = fetch_arg (buffer, 'd', 3, info);
699    
700     if (val != 1) /* Unusual coprocessor ID? */
701     (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
702     break;
703    
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 '>':
717     case 'm':
718     case 'n':
719     case 'o':
720     case 'p':
721     case 'q':
722     case 'v':
723    
724     if (place == 'd')
725     {
726     val = fetch_arg (buffer, 'x', 6, info);
727     val = ((val & 7) << 3) + ((val >> 3) & 7);
728     }
729     else
730     val = fetch_arg (buffer, 's', 6, info);
731    
732     /* Get register number assuming address register. */
733     regno = (val & 7) + 8;
734     regname = reg_names[regno];
735     switch (val >> 3)
736     {
737     case 0:
738     (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
739     break;
740    
741     case 1:
742     (*info->fprintf_func) (info->stream, "%s", regname);
743     break;
744    
745     case 2:
746     (*info->fprintf_func) (info->stream, "(%s)", regname);
747     break;
748    
749     case 3:
750     (*info->fprintf_func) (info->stream, "(%s)+", regname);
751     break;
752    
753     case 4:
754     (*info->fprintf_func) (info->stream, "-(%s)", regname);
755     break;
756    
757     case 5:
758     val = NEXTWORD (p);
759     (*info->fprintf_func) (info->stream, "($%04x,%s)", val, regname);
760     break;
761    
762     case 6:
763     p = print_indexed (regno, p, addr, info);
764     break;
765    
766     case 7:
767     switch (val & 7)
768     {
769     case 0:
770     val = NEXTWORD (p);
771     (*info->print_address_func) (val, info);
772     break;
773    
774     case 1:
775     uval = NEXTULONG (p);
776     (*info->print_address_func) (uval, info);
777     break;
778    
779     case 2:
780     val = NEXTWORD (p);
781 cebix 1.2 (*info->fprintf_func) (info->stream, "($%08x,pc)", addr + val);
782 cebix 1.1 break;
783    
784     case 3:
785     p = print_indexed (-1, p, addr, info);
786     break;
787    
788     case 4:
789     switch( place )
790     {
791     case 'b':
792     val = NEXTBYTE (p);
793     (*info->fprintf_func) (info->stream, "#$%02x", val & 0xff);
794     goto imm_printed;
795    
796     case 'w':
797     val = NEXTWORD (p);
798     (*info->fprintf_func) (info->stream, "#$%04x", val & 0xffff);
799     goto imm_printed;
800    
801     case 'l':
802     val = NEXTLONG (p);
803     (*info->fprintf_func) (info->stream, "#$%08x", val);
804     goto imm_printed;
805    
806     case 'f':
807     NEXTSINGLE(flval, p);
808     break;
809    
810     case 'F':
811     NEXTDOUBLE(flval, p);
812     break;
813    
814     case 'x':
815     NEXTEXTEND(flval, p);
816     break;
817    
818     case 'p':
819     flval = NEXTPACKED(p);
820     break;
821    
822     default:
823     return -1;
824     }
825     (*info->fprintf_func) (info->stream, "#%g", flval);
826     imm_printed:
827     break;
828    
829     default:
830     return -1;
831     }
832     }
833     break;
834    
835     case 'L':
836     case 'l':
837     if (place == 'w')
838     {
839     char doneany;
840     p1 = buffer + 2;
841     val = NEXTWORD (p1);
842     /* Move the pointer ahead if this point is farther ahead
843     than the last. */
844     p = p1 > p ? p1 : p;
845     if (val == 0)
846     {
847     (*info->fprintf_func) (info->stream, "#0");
848     break;
849     }
850     if (*d == 'l')
851     {
852     register int newval = 0;
853     for (regno = 0; regno < 16; ++regno)
854     if (val & (0x8000 >> regno))
855     newval |= 1 << regno;
856     val = newval;
857     }
858     val &= 0xffff;
859     doneany = 0;
860     for (regno = 0; regno < 16; ++regno)
861     if (val & (1 << regno))
862     {
863     int first_regno;
864     if (doneany)
865     (*info->fprintf_func) (info->stream, "/");
866     doneany = 1;
867     (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
868     first_regno = regno;
869     while (val & (1 << (regno + 1)))
870     ++regno;
871     if (regno > first_regno)
872     (*info->fprintf_func) (info->stream, "-%s",
873     reg_names[regno]);
874     }
875     }
876     else if (place == '3')
877     {
878     /* `fmovem' insn. */
879     char doneany;
880     val = fetch_arg (buffer, place, 8, info);
881     if (val == 0)
882     {
883     (*info->fprintf_func) (info->stream, "#0");
884     break;
885     }
886     if (*d == 'l')
887     {
888     register int newval = 0;
889     for (regno = 0; regno < 8; ++regno)
890     if (val & (0x80 >> regno))
891     newval |= 1 << regno;
892     val = newval;
893     }
894     val &= 0xff;
895     doneany = 0;
896     for (regno = 0; regno < 8; ++regno)
897     if (val & (1 << regno))
898     {
899     int first_regno;
900     if (doneany)
901     (*info->fprintf_func) (info->stream, "/");
902     doneany = 1;
903     (*info->fprintf_func) (info->stream, "fp%d", regno);
904     first_regno = regno;
905     while (val & (1 << (regno + 1)))
906     ++regno;
907     if (regno > first_regno)
908     (*info->fprintf_func) (info->stream, "-fp%d", regno);
909     }
910     }
911     else if (place == '8')
912     {
913     /* fmoveml for FP status registers */
914     (*info->fprintf_func) (info->stream, "%s",
915     fpcr_names[fetch_arg (buffer, place, 3,
916     info)]);
917     }
918     else
919     return -2;
920     break;
921    
922     case 'X':
923     place = '8';
924     case 'Y':
925     case 'Z':
926     case 'W':
927     case '0':
928     case '1':
929     case '2':
930     case '3':
931     {
932     int val = fetch_arg (buffer, place, 5, info);
933     char *name = 0;
934     switch (val)
935     {
936     case 2: name = "tt0"; break;
937     case 3: name = "tt1"; break;
938     case 0x10: name = "tc"; break;
939     case 0x11: name = "drp"; break;
940     case 0x12: name = "srp"; break;
941     case 0x13: name = "crp"; break;
942     case 0x14: name = "cal"; break;
943     case 0x15: name = "val"; break;
944     case 0x16: name = "scc"; break;
945     case 0x17: name = "ac"; break;
946     case 0x18: name = "psr"; break;
947     case 0x19: name = "pcsr"; break;
948     case 0x1c:
949     case 0x1d:
950     {
951     int break_reg = ((buffer[3] >> 2) & 7);
952     (*info->fprintf_func)
953     (info->stream, val == 0x1c ? "bad%d" : "bac%d",
954     break_reg);
955     }
956     break;
957     default:
958     (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
959     }
960     if (name)
961     (*info->fprintf_func) (info->stream, "%s", name);
962     }
963     break;
964    
965     case 'f':
966     {
967     int fc = fetch_arg (buffer, place, 5, info);
968     if (fc == 1)
969     (*info->fprintf_func) (info->stream, "dfc");
970     else if (fc == 0)
971     (*info->fprintf_func) (info->stream, "sfc");
972     else
973     /* xgettext:c-format */
974     (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
975     }
976     break;
977    
978     case 'V':
979     (*info->fprintf_func) (info->stream, "val");
980     break;
981    
982     case 't':
983     {
984     int level = fetch_arg (buffer, place, 3, info);
985     (*info->fprintf_func) (info->stream, "%d", level);
986     }
987     break;
988    
989     default:
990     return -2;
991     }
992    
993     return p - p0;
994     }
995    
996     /* Fetch BITS bits from a position in the instruction specified by CODE.
997     CODE is a "place to put an argument", or 'x' for a destination
998     that is a general address (mode and register).
999     BUFFER contains the instruction. */
1000    
1001     static int
1002     fetch_arg (buffer, code, bits, info)
1003     unsigned char *buffer;
1004     int code;
1005     int bits;
1006     disassemble_info *info;
1007     {
1008     register int val = 0;
1009     switch (code)
1010     {
1011     case 's':
1012     val = buffer[1];
1013     break;
1014    
1015     case 'd': /* Destination, for register or quick. */
1016     val = (buffer[0] << 8) + buffer[1];
1017     val >>= 9;
1018     break;
1019    
1020     case 'x': /* Destination, for general arg */
1021     val = (buffer[0] << 8) + buffer[1];
1022     val >>= 6;
1023     break;
1024    
1025     case 'k':
1026     FETCH_DATA (info, buffer + 3);
1027     val = (buffer[3] >> 4);
1028     break;
1029    
1030     case 'C':
1031     FETCH_DATA (info, buffer + 3);
1032     val = buffer[3];
1033     break;
1034    
1035     case '1':
1036     FETCH_DATA (info, buffer + 3);
1037     val = (buffer[2] << 8) + buffer[3];
1038     val >>= 12;
1039     break;
1040    
1041     case '2':
1042     FETCH_DATA (info, buffer + 3);
1043     val = (buffer[2] << 8) + buffer[3];
1044     val >>= 6;
1045     break;
1046    
1047     case '3':
1048     case 'j':
1049     FETCH_DATA (info, buffer + 3);
1050     val = (buffer[2] << 8) + buffer[3];
1051     break;
1052    
1053     case '4':
1054     FETCH_DATA (info, buffer + 5);
1055     val = (buffer[4] << 8) + buffer[5];
1056     val >>= 12;
1057     break;
1058    
1059     case '5':
1060     FETCH_DATA (info, buffer + 5);
1061     val = (buffer[4] << 8) + buffer[5];
1062     val >>= 6;
1063     break;
1064    
1065     case '6':
1066     FETCH_DATA (info, buffer + 5);
1067     val = (buffer[4] << 8) + buffer[5];
1068     break;
1069    
1070     case '7':
1071     FETCH_DATA (info, buffer + 3);
1072     val = (buffer[2] << 8) + buffer[3];
1073     val >>= 7;
1074     break;
1075    
1076     case '8':
1077     FETCH_DATA (info, buffer + 3);
1078     val = (buffer[2] << 8) + buffer[3];
1079     val >>= 10;
1080     break;
1081    
1082     case '9':
1083     FETCH_DATA (info, buffer + 3);
1084     val = (buffer[2] << 8) + buffer[3];
1085     val >>= 5;
1086     break;
1087    
1088     case 'e':
1089     val = (buffer[1] >> 6);
1090     break;
1091    
1092     default:
1093     abort ();
1094     }
1095    
1096     switch (bits)
1097     {
1098     case 2:
1099     return val & 3;
1100     case 3:
1101     return val & 7;
1102     case 4:
1103     return val & 017;
1104     case 5:
1105     return val & 037;
1106     case 6:
1107     return val & 077;
1108     case 7:
1109     return val & 0177;
1110     case 8:
1111     return val & 0377;
1112     case 12:
1113     return val & 07777;
1114     default:
1115     abort ();
1116     }
1117     }
1118    
1119     /* Print an indexed argument. The base register is BASEREG (-1 for pc).
1120     P points to extension word, in buffer.
1121     ADDR is the nominal core address of that extension word. */
1122    
1123     static unsigned char *
1124     print_indexed (basereg, p, addr, info)
1125     int basereg;
1126     unsigned char *p;
1127     bfd_vma addr;
1128     disassemble_info *info;
1129     {
1130     register int word;
1131     static char *const scales[] = {"", "*2", "*4", "*8"};
1132     bfd_vma base_disp;
1133     bfd_vma outer_disp;
1134     char buf[40];
1135     char vmabuf[50];
1136    
1137     word = NEXTWORD (p);
1138    
1139     /* Generate the text for the index register.
1140     Where this will be output is not yet determined. */
1141     sprintf (buf, "%s.%c%s",
1142     reg_names[(word >> 12) & 0xf],
1143     (word & 0x800) ? 'l' : 'w',
1144     scales[(word >> 9) & 3]);
1145    
1146     /* Handle the 68000 style of indexing. */
1147    
1148     if ((word & 0x100) == 0)
1149     {
1150     base_disp = word & 0xff;
1151     if ((base_disp & 0x80) != 0)
1152     base_disp -= 0x100;
1153     if (basereg == -1)
1154     base_disp += addr;
1155     (*info->fprintf_func) (info->stream, "(", buf);
1156     print_base (basereg, base_disp, info);
1157     (*info->fprintf_func) (info->stream, ",%s)", buf);
1158     return p;
1159     }
1160    
1161     /* Handle the generalized kind. */
1162     /* First, compute the displacement to add to the base register. */
1163    
1164     if (word & 0200)
1165     {
1166     if (basereg == -1)
1167     basereg = -3;
1168     else
1169     basereg = -2;
1170     }
1171     if (word & 0100)
1172     buf[0] = '\0';
1173     base_disp = 0;
1174     switch ((word >> 4) & 3)
1175     {
1176     case 2:
1177     base_disp = NEXTWORD (p);
1178     break;
1179     case 3:
1180     base_disp = NEXTLONG (p);
1181     }
1182     if (basereg == -1)
1183     base_disp += addr;
1184    
1185     /* Handle single-level case (not indirect) */
1186    
1187     if ((word & 7) == 0)
1188     {
1189     (*info->fprintf_func) (info->stream, "(");
1190     print_base (basereg, base_disp, info);
1191     if (buf[0] != '\0')
1192     (*info->fprintf_func) (info->stream, ",%s", buf);
1193     (*info->fprintf_func) (info->stream, ")");
1194     return p;
1195     }
1196    
1197     /* Two level. Compute displacement to add after indirection. */
1198    
1199     outer_disp = 0;
1200     switch (word & 3)
1201     {
1202     case 2:
1203     outer_disp = NEXTWORD (p);
1204     break;
1205     case 3:
1206     outer_disp = NEXTLONG (p);
1207     }
1208    
1209     (*info->fprintf_func) (info->stream, "([");
1210     print_base (basereg, base_disp, info);
1211     if ((word & 4) == 0 && buf[0] != '\0')
1212     {
1213     (*info->fprintf_func) (info->stream, ",%s", buf);
1214     buf[0] = '\0';
1215     }
1216     if (outer_disp)
1217     (*info->fprintf_func) (info->stream, "],$%08x", outer_disp);
1218     else
1219     (*info->fprintf_func) (info->stream, "]", outer_disp);
1220     if (buf[0] != '\0')
1221     (*info->fprintf_func) (info->stream, ",%s", buf);
1222     (*info->fprintf_func) (info->stream, ")");
1223    
1224     return p;
1225     }
1226    
1227     /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
1228     REGNO = -1 for pc, -2 for none (suppressed). */
1229    
1230     static void
1231     print_base (regno, disp, info)
1232     int regno;
1233     bfd_vma disp;
1234     disassemble_info *info;
1235     {
1236 cebix 1.2 if (regno == -1)
1237     (*info->fprintf_func) (info->stream, "$%08x,pc", disp);
1238     else {
1239     if (regno == -3)
1240     (*info->fprintf_func) (info->stream, "$%08x,zpc", disp);
1241     else if (regno == -2)
1242     (*info->print_address_func) (disp, info);
1243     else
1244     (*info->fprintf_func) (info->stream, "$%08x,%s", disp, reg_names[regno]);
1245     }
1246 cebix 1.1 }