]> Git Repo - binutils.git/blob - opcodes/m68k-dis.c
19990502 sourceware import
[binutils.git] / opcodes / m68k-dis.c
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 <libiberty.h>
22 #include "opintl.h"
23
24 #include "opcode/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", "%fp", "%sp",
54   "%ps", "%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 \f
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 \f
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                         xmalloc (sizeof (struct m68k_opcode *)
204                                  * 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, " ");
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   /* Handle undefined instructions.  */
439   info->fprintf_func = save_printer;
440   info->print_address_func = save_print_address;
441   (*info->fprintf_func) (info->stream, "0%o",
442                          (buffer[0] << 8) + buffer[1]);
443   return 2;
444 }
445
446 /* Returns number of bytes "eaten" by the operand, or
447    return -1 if an invalid operand was found, or -2 if
448    an opcode tabe error was found. */
449
450 static int
451 print_insn_arg (d, buffer, p0, addr, info)
452      const char *d;
453      unsigned char *buffer;
454      unsigned char *p0;
455      bfd_vma addr;              /* PC for this arg to be relative to */
456      disassemble_info *info;
457 {
458   register int val = 0;
459   register int place = d[1];
460   register unsigned char *p = p0;
461   int regno;
462   register CONST char *regname;
463   register unsigned char *p1;
464   double flval;
465   int flt_p;
466   bfd_signed_vma disp;
467   unsigned int uval;
468
469   switch (*d)
470     {
471     case 'c':           /* cache identifier */
472       {
473         static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
474         val = fetch_arg (buffer, place, 2, info);
475         (*info->fprintf_func) (info->stream, cacheFieldName[val]);
476         break;
477       }
478
479     case 'a':           /* address register indirect only. Cf. case '+'. */
480       {
481         (*info->fprintf_func)
482           (info->stream,
483            "%s@",
484            reg_names [fetch_arg (buffer, place, 3, info) + 8]);
485         break;
486       }
487
488     case '_':           /* 32-bit absolute address for move16. */
489       {
490         uval = NEXTULONG (p);
491         (*info->print_address_func) (uval, info);
492         break;
493       }
494
495     case 'C':
496       (*info->fprintf_func) (info->stream, "%%ccr");
497       break;
498
499     case 'S':
500       (*info->fprintf_func) (info->stream, "%%sr");
501       break;
502
503     case 'U':
504       (*info->fprintf_func) (info->stream, "%%usp");
505       break;
506
507     case 'J':
508       {
509         static const struct { char *name; int value; } names[]
510           = {{"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
511              {"%tc",  0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
512              {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
513              {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
514              {"%msp", 0x803}, {"%isp", 0x804},
515
516              /* Should we be calling this psr like we do in case 'Y'?  */
517              {"%mmusr",0x805},
518
519              {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808}};
520
521         val = fetch_arg (buffer, place, 12, info);
522         for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
523           if (names[regno].value == val)
524             {
525               (*info->fprintf_func) (info->stream, "%s", names[regno].name);
526               break;
527             }
528         if (regno < 0)
529           (*info->fprintf_func) (info->stream, "%d", val);
530       }
531       break;
532
533     case 'Q':
534       val = fetch_arg (buffer, place, 3, info);
535       /* 0 means 8, except for the bkpt instruction... */
536       if (val == 0 && d[1] != 's')
537         val = 8;
538       (*info->fprintf_func) (info->stream, "#%d", val);
539       break;
540
541     case 'M':
542       val = fetch_arg (buffer, place, 8, info);
543       if (val & 0x80)
544         val = val - 0x100;
545       (*info->fprintf_func) (info->stream, "#%d", val);
546       break;
547
548     case 'T':
549       val = fetch_arg (buffer, place, 4, info);
550       (*info->fprintf_func) (info->stream, "#%d", val);
551       break;
552
553     case 'D':
554       (*info->fprintf_func) (info->stream, "%s",
555                              reg_names[fetch_arg (buffer, place, 3, info)]);
556       break;
557
558     case 'A':
559       (*info->fprintf_func)
560         (info->stream, "%s",
561          reg_names[fetch_arg (buffer, place, 3, info) + 010]);
562       break;
563
564     case 'R':
565       (*info->fprintf_func)
566         (info->stream, "%s",
567          reg_names[fetch_arg (buffer, place, 4, info)]);
568       break;
569
570     case 'r':
571       regno = fetch_arg (buffer, place, 4, info);
572       if (regno > 7)
573         (*info->fprintf_func) (info->stream, "%s@", reg_names[regno]);
574       else
575         (*info->fprintf_func) (info->stream, "@(%s)", reg_names[regno]);
576       break;
577
578     case 'F':
579       (*info->fprintf_func)
580         (info->stream, "%%fp%d",
581          fetch_arg (buffer, place, 3, info));
582       break;
583
584     case 'O':
585       val = fetch_arg (buffer, place, 6, info);
586       if (val & 0x20)
587         (*info->fprintf_func) (info->stream, "%s", reg_names [val & 7]);
588       else
589         (*info->fprintf_func) (info->stream, "%d", val);
590       break;
591
592     case '+':
593       (*info->fprintf_func)
594         (info->stream, "%s@+",
595          reg_names[fetch_arg (buffer, place, 3, info) + 8]);
596       break;
597
598     case '-':
599       (*info->fprintf_func)
600         (info->stream, "%s@-",
601          reg_names[fetch_arg (buffer, place, 3, info) + 8]);
602       break;
603
604     case 'k':
605       if (place == 'k')
606         (*info->fprintf_func)
607           (info->stream, "{%s}",
608            reg_names[fetch_arg (buffer, place, 3, info)]);
609       else if (place == 'C')
610         {
611           val = fetch_arg (buffer, place, 7, info);
612           if ( val > 63 )               /* This is a signed constant. */
613             val -= 128;
614           (*info->fprintf_func) (info->stream, "{#%d}", val);
615         }
616       else
617         return -2;
618       break;
619
620     case '#':
621     case '^':
622       p1 = buffer + (*d == '#' ? 2 : 4);
623       if (place == 's')
624         val = fetch_arg (buffer, place, 4, info);
625       else if (place == 'C')
626         val = fetch_arg (buffer, place, 7, info);
627       else if (place == '8')
628         val = fetch_arg (buffer, place, 3, info);
629       else if (place == '3')
630         val = fetch_arg (buffer, place, 8, info);
631       else if (place == 'b')
632         val = NEXTBYTE (p1);
633       else if (place == 'w' || place == 'W')
634         val = NEXTWORD (p1);
635       else if (place == 'l')
636         val = NEXTLONG (p1);
637       else
638         return -2;
639       (*info->fprintf_func) (info->stream, "#%d", val);
640       break;
641
642     case 'B':
643       if (place == 'b')
644         disp = NEXTBYTE (p);
645       else if (place == 'B')
646         disp = COERCE_SIGNED_CHAR(buffer[1]);
647       else if (place == 'w' || place == 'W')
648         disp = NEXTWORD (p);
649       else if (place == 'l' || place == 'L' || place == 'C')
650         disp = NEXTLONG (p);
651       else if (place == 'g')
652         {
653           disp = NEXTBYTE (buffer);
654           if (disp == 0)
655             disp = NEXTWORD (p);
656           else if (disp == -1)
657             disp = NEXTLONG (p);
658         }
659       else if (place == 'c')
660         {
661           if (buffer[1] & 0x40)         /* If bit six is one, long offset */
662             disp = NEXTLONG (p);
663           else
664             disp = NEXTWORD (p);
665         }
666       else
667         return -2;
668
669       (*info->print_address_func) (addr + disp, info);
670       break;
671
672     case 'd':
673       val = NEXTWORD (p);
674       (*info->fprintf_func)
675         (info->stream, "%s@(%d)",
676          reg_names[fetch_arg (buffer, place, 3, info) + 8], val);
677       break;
678
679     case 's':
680       (*info->fprintf_func) (info->stream, "%s",
681                              fpcr_names[fetch_arg (buffer, place, 3, info)]);
682       break;
683
684     case 'I':
685       /* Get coprocessor ID... */
686       val = fetch_arg (buffer, 'd', 3, info);
687       
688       if (val != 1)                             /* Unusual coprocessor ID? */
689         (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
690       break;
691
692     case '*':
693     case '~':
694     case '%':
695     case ';':
696     case '@':
697     case '!':
698     case '$':
699     case '?':
700     case '/':
701     case '&':
702     case '|':
703     case '<':
704     case '>':
705     case 'm':
706     case 'n':
707     case 'o':
708     case 'p':
709     case 'q':
710     case 'v':
711
712       if (place == 'd')
713         {
714           val = fetch_arg (buffer, 'x', 6, info);
715           val = ((val & 7) << 3) + ((val >> 3) & 7);
716         }
717       else
718         val = fetch_arg (buffer, 's', 6, info);
719
720       /* Get register number assuming address register.  */
721       regno = (val & 7) + 8;
722       regname = reg_names[regno];
723       switch (val >> 3)
724         {
725         case 0:
726           (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
727           break;
728
729         case 1:
730           (*info->fprintf_func) (info->stream, "%s", regname);
731           break;
732
733         case 2:
734           (*info->fprintf_func) (info->stream, "%s@", regname);
735           break;
736
737         case 3:
738           (*info->fprintf_func) (info->stream, "%s@+", regname);
739           break;
740
741         case 4:
742           (*info->fprintf_func) (info->stream, "%s@-", regname);
743           break;
744
745         case 5:
746           val = NEXTWORD (p);
747           (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
748           break;
749
750         case 6:
751           p = print_indexed (regno, p, addr, info);
752           break;
753
754         case 7:
755           switch (val & 7)
756             {
757             case 0:
758               val = NEXTWORD (p);
759               (*info->print_address_func) (val, info);
760               break;
761
762             case 1:
763               uval = NEXTULONG (p);
764               (*info->print_address_func) (uval, info);
765               break;
766
767             case 2:
768               val = NEXTWORD (p);
769               (*info->fprintf_func) (info->stream, "%%pc@(");
770               (*info->print_address_func) (addr + val, info);
771               (*info->fprintf_func) (info->stream, ")");
772               break;
773
774             case 3:
775               p = print_indexed (-1, p, addr, info);
776               break;
777
778             case 4:
779               flt_p = 1;        /* Assume it's a float... */
780               switch( place )
781               {
782                 case 'b':
783                   val = NEXTBYTE (p);
784                   flt_p = 0;
785                   break;
786
787                 case 'w':
788                   val = NEXTWORD (p);
789                   flt_p = 0;
790                   break;
791
792                 case 'l':
793                   val = NEXTLONG (p);
794                   flt_p = 0;
795                   break;
796
797                 case 'f':
798                   NEXTSINGLE(flval, p);
799                   break;
800
801                 case 'F':
802                   NEXTDOUBLE(flval, p);
803                   break;
804
805                 case 'x':
806                   NEXTEXTEND(flval, p);
807                   break;
808
809                 case 'p':
810                   flval = NEXTPACKED(p);
811                   break;
812
813                 default:
814                   return -1;
815               }
816               if ( flt_p )      /* Print a float? */
817                 (*info->fprintf_func) (info->stream, "#%g", flval);
818               else
819                 (*info->fprintf_func) (info->stream, "#%d", val);
820               break;
821
822             default:
823               return -1;
824             }
825         }
826       break;
827
828     case 'L':
829     case 'l':
830         if (place == 'w')
831           {
832             char doneany;
833             p1 = buffer + 2;
834             val = NEXTWORD (p1);
835             /* Move the pointer ahead if this point is farther ahead
836                than the last.  */
837             p = p1 > p ? p1 : p;
838             if (val == 0)
839               {
840                 (*info->fprintf_func) (info->stream, "#0");
841                 break;
842               }
843             if (*d == 'l')
844               {
845                 register int newval = 0;
846                 for (regno = 0; regno < 16; ++regno)
847                   if (val & (0x8000 >> regno))
848                     newval |= 1 << regno;
849                 val = newval;
850               }
851             val &= 0xffff;
852             doneany = 0;
853             for (regno = 0; regno < 16; ++regno)
854               if (val & (1 << regno))
855                 {
856                   int first_regno;
857                   if (doneany)
858                     (*info->fprintf_func) (info->stream, "/");
859                   doneany = 1;
860                   (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
861                   first_regno = regno;
862                   while (val & (1 << (regno + 1)))
863                     ++regno;
864                   if (regno > first_regno)
865                     (*info->fprintf_func) (info->stream, "-%s",
866                                            reg_names[regno]);
867                 }
868           }
869         else if (place == '3')
870           {
871             /* `fmovem' insn.  */
872             char doneany;
873             val = fetch_arg (buffer, place, 8, info);
874             if (val == 0)
875               {
876                 (*info->fprintf_func) (info->stream, "#0");
877                 break;
878               }
879             if (*d == 'l')
880               {
881                 register int newval = 0;
882                 for (regno = 0; regno < 8; ++regno)
883                   if (val & (0x80 >> regno))
884                     newval |= 1 << regno;
885                 val = newval;
886               }
887             val &= 0xff;
888             doneany = 0;
889             for (regno = 0; regno < 8; ++regno)
890               if (val & (1 << regno))
891                 {
892                   int first_regno;
893                   if (doneany)
894                     (*info->fprintf_func) (info->stream, "/");
895                   doneany = 1;
896                   (*info->fprintf_func) (info->stream, "%%fp%d", regno);
897                   first_regno = regno;
898                   while (val & (1 << (regno + 1)))
899                     ++regno;
900                   if (regno > first_regno)
901                     (*info->fprintf_func) (info->stream, "-%%fp%d", regno);
902                 }
903           }
904         else if (place == '8')
905           {
906             /* fmoveml for FP status registers */
907             (*info->fprintf_func) (info->stream, "%s",
908                                    fpcr_names[fetch_arg (buffer, place, 3,
909                                                          info)]);
910           }
911         else
912           return -2;
913       break;
914
915     case 'X':
916       place = '8';
917     case 'Y':
918     case 'Z':
919     case 'W':
920     case '0':
921     case '1':
922     case '2':
923     case '3':
924       {
925         int val = fetch_arg (buffer, place, 5, info);
926         char *name = 0;
927         switch (val)
928           {
929           case 2: name = "%tt0"; break;
930           case 3: name = "%tt1"; break;
931           case 0x10: name = "%tc"; break;
932           case 0x11: name = "%drp"; break;
933           case 0x12: name = "%srp"; break;
934           case 0x13: name = "%crp"; break;
935           case 0x14: name = "%cal"; break;
936           case 0x15: name = "%val"; break;
937           case 0x16: name = "%scc"; break;
938           case 0x17: name = "%ac"; break;
939           case 0x18: name = "%psr"; break;
940           case 0x19: name = "%pcsr"; break;
941           case 0x1c:
942           case 0x1d:
943             {
944               int break_reg = ((buffer[3] >> 2) & 7);
945               (*info->fprintf_func)
946                 (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
947                  break_reg);
948             }
949             break;
950           default:
951             (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
952           }
953         if (name)
954           (*info->fprintf_func) (info->stream, "%s", name);
955       }
956       break;
957
958     case 'f':
959       {
960         int fc = fetch_arg (buffer, place, 5, info);
961         if (fc == 1)
962           (*info->fprintf_func) (info->stream, "%%dfc");
963         else if (fc == 0)
964           (*info->fprintf_func) (info->stream, "%%sfc");
965         else
966           /* xgettext:c-format */
967           (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
968       }
969       break;
970
971     case 'V':
972       (*info->fprintf_func) (info->stream, "%%val");
973       break;
974
975     case 't':
976       {
977         int level = fetch_arg (buffer, place, 3, info);
978         (*info->fprintf_func) (info->stream, "%d", level);
979       }
980       break;
981
982     default:
983       return -2;
984     }
985
986   return p - p0;
987 }
988
989 /* Fetch BITS bits from a position in the instruction specified by CODE.
990    CODE is a "place to put an argument", or 'x' for a destination
991    that is a general address (mode and register).
992    BUFFER contains the instruction.  */
993
994 static int
995 fetch_arg (buffer, code, bits, info)
996      unsigned char *buffer;
997      int code;
998      int bits;
999      disassemble_info *info;
1000 {
1001   register int val = 0;
1002   switch (code)
1003     {
1004     case 's':
1005       val = buffer[1];
1006       break;
1007
1008     case 'd':                   /* Destination, for register or quick.  */
1009       val = (buffer[0] << 8) + buffer[1];
1010       val >>= 9;
1011       break;
1012
1013     case 'x':                   /* Destination, for general arg */
1014       val = (buffer[0] << 8) + buffer[1];
1015       val >>= 6;
1016       break;
1017
1018     case 'k':
1019       FETCH_DATA (info, buffer + 3);
1020       val = (buffer[3] >> 4);
1021       break;
1022
1023     case 'C':
1024       FETCH_DATA (info, buffer + 3);
1025       val = buffer[3];
1026       break;
1027
1028     case '1':
1029       FETCH_DATA (info, buffer + 3);
1030       val = (buffer[2] << 8) + buffer[3];
1031       val >>= 12;
1032       break;
1033
1034     case '2':
1035       FETCH_DATA (info, buffer + 3);
1036       val = (buffer[2] << 8) + buffer[3];
1037       val >>= 6;
1038       break;
1039
1040     case '3':
1041     case 'j':
1042       FETCH_DATA (info, buffer + 3);
1043       val = (buffer[2] << 8) + buffer[3];
1044       break;
1045
1046     case '4':
1047       FETCH_DATA (info, buffer + 5);
1048       val = (buffer[4] << 8) + buffer[5];
1049       val >>= 12;
1050       break;
1051
1052     case '5':
1053       FETCH_DATA (info, buffer + 5);
1054       val = (buffer[4] << 8) + buffer[5];
1055       val >>= 6;
1056       break;
1057
1058     case '6':
1059       FETCH_DATA (info, buffer + 5);
1060       val = (buffer[4] << 8) + buffer[5];
1061       break;
1062
1063     case '7':
1064       FETCH_DATA (info, buffer + 3);
1065       val = (buffer[2] << 8) + buffer[3];
1066       val >>= 7;
1067       break;
1068       
1069     case '8':
1070       FETCH_DATA (info, buffer + 3);
1071       val = (buffer[2] << 8) + buffer[3];
1072       val >>= 10;
1073       break;
1074
1075     case '9':
1076       FETCH_DATA (info, buffer + 3);
1077       val = (buffer[2] << 8) + buffer[3];
1078       val >>= 5;
1079       break;
1080
1081     case 'e':
1082       val = (buffer[1] >> 6);
1083       break;
1084
1085     default:
1086       abort ();
1087     }
1088
1089   switch (bits)
1090     {
1091     case 2:
1092       return val & 3;
1093     case 3:
1094       return val & 7;
1095     case 4:
1096       return val & 017;
1097     case 5:
1098       return val & 037;
1099     case 6:
1100       return val & 077;
1101     case 7:
1102       return val & 0177;
1103     case 8:
1104       return val & 0377;
1105     case 12:
1106       return val & 07777;
1107     default:
1108       abort ();
1109     }
1110 }
1111
1112 /* Print an indexed argument.  The base register is BASEREG (-1 for pc).
1113    P points to extension word, in buffer.
1114    ADDR is the nominal core address of that extension word.  */
1115
1116 static unsigned char *
1117 print_indexed (basereg, p, addr, info)
1118      int basereg;
1119      unsigned char *p;
1120      bfd_vma addr;
1121      disassemble_info *info;
1122 {
1123   register int word;
1124   static char *const scales[] = {"", ":2", ":4", ":8"};
1125   bfd_vma base_disp;
1126   bfd_vma outer_disp;
1127   char buf[40];
1128   char vmabuf[50];
1129
1130   word = NEXTWORD (p);
1131
1132   /* Generate the text for the index register.
1133      Where this will be output is not yet determined.  */
1134   sprintf (buf, "%s:%c%s",
1135            reg_names[(word >> 12) & 0xf],
1136            (word & 0x800) ? 'l' : 'w',
1137            scales[(word >> 9) & 3]);
1138
1139   /* Handle the 68000 style of indexing.  */
1140
1141   if ((word & 0x100) == 0)
1142     {
1143       base_disp = word & 0xff;
1144       if ((base_disp & 0x80) != 0)
1145         base_disp -= 0x100;
1146       if (basereg == -1)
1147         base_disp += addr;
1148       print_base (basereg, base_disp, info);
1149       (*info->fprintf_func) (info->stream, ",%s)", buf);
1150       return p;
1151     }
1152
1153   /* Handle the generalized kind.  */
1154   /* First, compute the displacement to add to the base register.  */
1155
1156   if (word & 0200)
1157     {
1158       if (basereg == -1)
1159         basereg = -3;
1160       else
1161         basereg = -2;
1162     }
1163   if (word & 0100)
1164     buf[0] = '\0';
1165   base_disp = 0;
1166   switch ((word >> 4) & 3)
1167     {
1168     case 2:
1169       base_disp = NEXTWORD (p);
1170       break;
1171     case 3:
1172       base_disp = NEXTLONG (p);
1173     }
1174   if (basereg == -1)
1175     base_disp += addr;
1176
1177   /* Handle single-level case (not indirect) */
1178
1179   if ((word & 7) == 0)
1180     {
1181       print_base (basereg, base_disp, info);
1182       if (buf[0] != '\0')
1183         (*info->fprintf_func) (info->stream, ",%s", buf);
1184       (*info->fprintf_func) (info->stream, ")");
1185       return p;
1186     }
1187
1188   /* Two level.  Compute displacement to add after indirection.  */
1189
1190   outer_disp = 0;
1191   switch (word & 3)
1192     {
1193     case 2:
1194       outer_disp = NEXTWORD (p);
1195       break;
1196     case 3:
1197       outer_disp = NEXTLONG (p);
1198     }
1199
1200   print_base (basereg, base_disp, info);
1201   if ((word & 4) == 0 && buf[0] != '\0')
1202     {
1203       (*info->fprintf_func) (info->stream, ",%s", buf);
1204       buf[0] = '\0';
1205     }
1206   sprintf_vma (vmabuf, outer_disp);
1207   (*info->fprintf_func) (info->stream, ")@(%s", vmabuf);
1208   if (buf[0] != '\0')
1209     (*info->fprintf_func) (info->stream, ",%s", buf);
1210   (*info->fprintf_func) (info->stream, ")");
1211
1212   return p;
1213 }
1214
1215 /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
1216    REGNO = -1 for pc, -2 for none (suppressed).  */
1217
1218 static void
1219 print_base (regno, disp, info)
1220      int regno;
1221      bfd_vma disp;
1222      disassemble_info *info;
1223 {
1224   if (regno == -1)
1225     {
1226       (*info->fprintf_func) (info->stream, "%%pc@(");
1227       (*info->print_address_func) (disp, info);
1228     }
1229   else
1230     {
1231       char buf[50];
1232
1233       if (regno == -2)
1234         (*info->fprintf_func) (info->stream, "@(");
1235       else if (regno == -3)
1236         (*info->fprintf_func) (info->stream, "%%zpc@(");
1237       else
1238         (*info->fprintf_func) (info->stream, "%s@(", reg_names[regno]);
1239
1240       sprintf_vma (buf, disp);
1241       (*info->fprintf_func) (info->stream, "%s", buf);
1242     }
1243 }
This page took 0.090559 seconds and 4 git commands to generate.