xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/m68k-dis.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* Print Motorola 68k instructions.
2b55d4692Sfgsch    Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3*007c2a45Smiod    1998, 1999, 2000, 2001, 2002, 2003
4fddef416Sniklas    Free Software Foundation, Inc.
52159047fSniklas 
62159047fSniklas    This file is free software; you can redistribute it and/or modify
72159047fSniklas    it under the terms of the GNU General Public License as published by
82159047fSniklas    the Free Software Foundation; either version 2 of the License, or
92159047fSniklas    (at your option) any later version.
102159047fSniklas 
112159047fSniklas    This program is distributed in the hope that it will be useful,
122159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
132159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
142159047fSniklas    GNU General Public License for more details.
152159047fSniklas 
162159047fSniklas    You should have received a copy of the GNU General Public License
172159047fSniklas    along with this program; if not, write to the Free Software
182159047fSniklas    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
192159047fSniklas 
20f7cc78ecSespie #include "sysdep.h"
212159047fSniklas #include "dis-asm.h"
222159047fSniklas #include "floatformat.h"
23c074d1c9Sdrahn #include "libiberty.h"
24f7cc78ecSespie #include "opintl.h"
252159047fSniklas 
262159047fSniklas #include "opcode/m68k.h"
272159047fSniklas 
282159047fSniklas /* Local function prototypes */
292159047fSniklas 
302159047fSniklas static int
31fddef416Sniklas fetch_data PARAMS ((struct disassemble_info *, bfd_byte *));
32fddef416Sniklas 
33fddef416Sniklas static void
34fddef416Sniklas dummy_print_address PARAMS ((bfd_vma, struct disassemble_info *));
35fddef416Sniklas 
36fddef416Sniklas static int
372159047fSniklas fetch_arg PARAMS ((unsigned char *, int, int, disassemble_info *));
382159047fSniklas 
392159047fSniklas static void
402159047fSniklas print_base PARAMS ((int, bfd_vma, disassemble_info *));
412159047fSniklas 
422159047fSniklas static unsigned char *
432159047fSniklas print_indexed PARAMS ((int, unsigned char *, bfd_vma, disassemble_info *));
442159047fSniklas 
452159047fSniklas static int
462159047fSniklas print_insn_arg PARAMS ((const char *, unsigned char *, unsigned char *,
472159047fSniklas 			bfd_vma, disassemble_info *));
482159047fSniklas 
49c074d1c9Sdrahn const char * const fpcr_names[] = {
502159047fSniklas     "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
51b55d4692Sfgsch     "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"
52b55d4692Sfgsch };
532159047fSniklas 
54c074d1c9Sdrahn static char *const reg_names[] = {
552159047fSniklas     "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
562159047fSniklas     "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
57b55d4692Sfgsch     "%ps", "%pc"
58b55d4692Sfgsch };
592159047fSniklas 
602159047fSniklas /* Sign-extend an (unsigned char). */
612159047fSniklas #if __STDC__ == 1
622159047fSniklas #define COERCE_SIGNED_CHAR(ch) ((signed char) (ch))
632159047fSniklas #else
642159047fSniklas #define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
652159047fSniklas #endif
662159047fSniklas 
672159047fSniklas /* Get a 1 byte signed integer.  */
682159047fSniklas #define NEXTBYTE(p)  (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
692159047fSniklas 
702159047fSniklas /* Get a 2 byte signed integer.  */
712159047fSniklas #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
722159047fSniklas #define NEXTWORD(p)  \
732159047fSniklas   (p += 2, FETCH_DATA (info, p), \
742159047fSniklas    COERCE16 ((p[-2] << 8) + p[-1]))
752159047fSniklas 
762159047fSniklas /* Get a 4 byte signed integer.  */
77f7cc78ecSespie #define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
782159047fSniklas #define NEXTLONG(p)  \
792159047fSniklas   (p += 4, FETCH_DATA (info, p), \
802159047fSniklas    (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])))
812159047fSniklas 
82f7cc78ecSespie /* Get a 4 byte unsigned integer.  */
83f7cc78ecSespie #define NEXTULONG(p)  \
84f7cc78ecSespie   (p += 4, FETCH_DATA (info, p), \
85f7cc78ecSespie    (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]))
86f7cc78ecSespie 
87fddef416Sniklas /* Get a single precision float.  */
882159047fSniklas #define NEXTSINGLE(val, p) \
89fddef416Sniklas   (p += 4, FETCH_DATA (info, p), \
90fddef416Sniklas    floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val))
912159047fSniklas 
92fddef416Sniklas /* Get a double precision float.  */
932159047fSniklas #define NEXTDOUBLE(val, p) \
94fddef416Sniklas   (p += 8, FETCH_DATA (info, p), \
95fddef416Sniklas    floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val))
962159047fSniklas 
97fddef416Sniklas /* Get an extended precision float.  */
98fddef416Sniklas #define NEXTEXTEND(val, p) \
99fddef416Sniklas   (p += 12, FETCH_DATA (info, p), \
100fddef416Sniklas    floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val))
1012159047fSniklas 
1022159047fSniklas /* Need a function to convert from packed to double
1032159047fSniklas    precision.   Actually, it's easier to print a
1042159047fSniklas    packed number than a double anyway, so maybe
1052159047fSniklas    there should be a special case to handle this... */
1062159047fSniklas #define NEXTPACKED(p) \
1072159047fSniklas   (p += 12, FETCH_DATA (info, p), 0.0)
1082159047fSniklas 
1092159047fSniklas /* Maximum length of an instruction.  */
1102159047fSniklas #define MAXLEN 22
1112159047fSniklas 
1122159047fSniklas #include <setjmp.h>
1132159047fSniklas 
114c074d1c9Sdrahn struct private {
1152159047fSniklas   /* Points to first byte not fetched.  */
1162159047fSniklas   bfd_byte *max_fetched;
1172159047fSniklas   bfd_byte the_buffer[MAXLEN];
1182159047fSniklas   bfd_vma insn_start;
1192159047fSniklas   jmp_buf bailout;
1202159047fSniklas };
1212159047fSniklas 
1222159047fSniklas /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
1232159047fSniklas    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
1242159047fSniklas    on error.  */
1252159047fSniklas #define FETCH_DATA(info, addr) \
1262159047fSniklas   ((addr) <= ((struct private *) (info->private_data))->max_fetched \
1272159047fSniklas    ? 1 : fetch_data ((info), (addr)))
1282159047fSniklas 
1292159047fSniklas static int
fetch_data(info,addr)1302159047fSniklas fetch_data (info, addr)
1312159047fSniklas      struct disassemble_info *info;
1322159047fSniklas      bfd_byte *addr;
1332159047fSniklas {
1342159047fSniklas   int status;
1352159047fSniklas   struct private *priv = (struct private *)info->private_data;
1362159047fSniklas   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
1372159047fSniklas 
1382159047fSniklas   status = (*info->read_memory_func) (start,
1392159047fSniklas 				      priv->max_fetched,
1402159047fSniklas 				      addr - priv->max_fetched,
1412159047fSniklas 				      info);
1422159047fSniklas   if (status != 0)
1432159047fSniklas     {
1442159047fSniklas       (*info->memory_error_func) (status, start, info);
1452159047fSniklas       longjmp (priv->bailout, 1);
1462159047fSniklas     }
1472159047fSniklas   else
1482159047fSniklas     priv->max_fetched = addr;
1492159047fSniklas   return 1;
1502159047fSniklas }
1512159047fSniklas 
1522159047fSniklas /* This function is used to print to the bit-bucket. */
1532159047fSniklas static int
1542159047fSniklas #ifdef __STDC__
dummy_printer(FILE * file ATTRIBUTE_UNUSED,const char * format ATTRIBUTE_UNUSED,...)155b55d4692Sfgsch dummy_printer (FILE *file ATTRIBUTE_UNUSED,
156b55d4692Sfgsch 	       const char *format ATTRIBUTE_UNUSED, ...)
1572159047fSniklas #else
158c074d1c9Sdrahn dummy_printer (file)
159c074d1c9Sdrahn      FILE *file ATTRIBUTE_UNUSED;
1602159047fSniklas #endif
161c074d1c9Sdrahn {
162c074d1c9Sdrahn   return 0;
163c074d1c9Sdrahn }
1642159047fSniklas 
165fddef416Sniklas static void
dummy_print_address(vma,info)1662159047fSniklas dummy_print_address (vma, info)
167b55d4692Sfgsch      bfd_vma vma ATTRIBUTE_UNUSED;
168b55d4692Sfgsch      struct disassemble_info *info ATTRIBUTE_UNUSED;
1692159047fSniklas {
1702159047fSniklas }
1712159047fSniklas 
1722159047fSniklas /* Print the m68k instruction at address MEMADDR in debugged memory,
1732159047fSniklas    on INFO->STREAM.  Returns length of the instruction, in bytes.  */
1742159047fSniklas 
1752159047fSniklas int
print_insn_m68k(memaddr,info)1762159047fSniklas print_insn_m68k (memaddr, info)
1772159047fSniklas      bfd_vma memaddr;
1782159047fSniklas      disassemble_info *info;
1792159047fSniklas {
1802159047fSniklas   register int i;
1812159047fSniklas   register unsigned char *p;
1822159047fSniklas   unsigned char *save_p;
1832159047fSniklas   register const char *d;
1842159047fSniklas   register unsigned long bestmask;
185b55d4692Sfgsch   const struct m68k_opcode *best;
186f7cc78ecSespie   unsigned int arch_mask;
1872159047fSniklas   struct private priv;
1882159047fSniklas   bfd_byte *buffer = priv.the_buffer;
1892159047fSniklas   fprintf_ftype save_printer = info->fprintf_func;
1902159047fSniklas   void (*save_print_address) PARAMS ((bfd_vma, struct disassemble_info *))
1912159047fSniklas     = info->print_address_func;
192fddef416Sniklas   int major_opcode;
193fddef416Sniklas   static int numopcodes[16];
194fddef416Sniklas   static const struct m68k_opcode **opcodes[16];
195fddef416Sniklas 
196fddef416Sniklas   if (!opcodes[0])
197fddef416Sniklas     {
198fddef416Sniklas       /* Speed up the matching by sorting the opcode table on the upper
199fddef416Sniklas 	 four bits of the opcode.  */
200fddef416Sniklas       const struct m68k_opcode **opc_pointer[16];
201fddef416Sniklas 
202fddef416Sniklas       /* First count how many opcodes are in each of the sixteen buckets.  */
203fddef416Sniklas       for (i = 0; i < m68k_numopcodes; i++)
204fddef416Sniklas 	numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
205fddef416Sniklas 
206fddef416Sniklas       /* Then create a sorted table of pointers that point into the
207fddef416Sniklas 	 unsorted table.  */
208fddef416Sniklas       opc_pointer[0] = ((const struct m68k_opcode **)
209fddef416Sniklas 			xmalloc (sizeof (struct m68k_opcode *)
210fddef416Sniklas 				 * m68k_numopcodes));
211fddef416Sniklas       opcodes[0] = opc_pointer[0];
212fddef416Sniklas       for (i = 1; i < 16; i++)
213fddef416Sniklas 	{
214fddef416Sniklas 	  opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
215fddef416Sniklas 	  opcodes[i] = opc_pointer[i];
216fddef416Sniklas 	}
217fddef416Sniklas 
218fddef416Sniklas       for (i = 0; i < m68k_numopcodes; i++)
219fddef416Sniklas 	*opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
220fddef416Sniklas 
221fddef416Sniklas     }
2222159047fSniklas 
2232159047fSniklas   info->private_data = (PTR) &priv;
224fddef416Sniklas   /* Tell objdump to use two bytes per chunk and six bytes per line for
225fddef416Sniklas      displaying raw data.  */
226fddef416Sniklas   info->bytes_per_chunk = 2;
227fddef416Sniklas   info->bytes_per_line = 6;
228fddef416Sniklas   info->display_endian = BFD_ENDIAN_BIG;
2292159047fSniklas   priv.max_fetched = priv.the_buffer;
2302159047fSniklas   priv.insn_start = memaddr;
2312159047fSniklas   if (setjmp (priv.bailout) != 0)
2322159047fSniklas     /* Error return.  */
2332159047fSniklas     return -1;
2342159047fSniklas 
235b55d4692Sfgsch   best = NULL;
236f7cc78ecSespie   switch (info->mach)
237f7cc78ecSespie     {
238f7cc78ecSespie     default:
239f7cc78ecSespie     case 0:
240f7cc78ecSespie       arch_mask = (unsigned int) -1;
241f7cc78ecSespie       break;
242f7cc78ecSespie     case bfd_mach_m68000:
243f7cc78ecSespie       arch_mask = m68000;
244f7cc78ecSespie       break;
245f7cc78ecSespie     case bfd_mach_m68008:
246f7cc78ecSespie       arch_mask = m68008;
247f7cc78ecSespie       break;
248f7cc78ecSespie     case bfd_mach_m68010:
249f7cc78ecSespie       arch_mask = m68010;
250f7cc78ecSespie       break;
251f7cc78ecSespie     case bfd_mach_m68020:
252f7cc78ecSespie       arch_mask = m68020;
253f7cc78ecSespie       break;
254f7cc78ecSespie     case bfd_mach_m68030:
255f7cc78ecSespie       arch_mask = m68030;
256f7cc78ecSespie       break;
257f7cc78ecSespie     case bfd_mach_m68040:
258f7cc78ecSespie       arch_mask = m68040;
259f7cc78ecSespie       break;
260f7cc78ecSespie     case bfd_mach_m68060:
261f7cc78ecSespie       arch_mask = m68060;
262f7cc78ecSespie       break;
263b55d4692Sfgsch     case bfd_mach_mcf5200:
264b55d4692Sfgsch       arch_mask = mcf5200;
265b55d4692Sfgsch       break;
266*007c2a45Smiod     case bfd_mach_mcf528x:
267*007c2a45Smiod       arch_mask = mcf528x;
268*007c2a45Smiod       break;
269b55d4692Sfgsch     case bfd_mach_mcf5206e:
270b55d4692Sfgsch       arch_mask = mcf5206e;
271b55d4692Sfgsch       break;
272b55d4692Sfgsch     case bfd_mach_mcf5307:
273b55d4692Sfgsch       arch_mask = mcf5307;
274b55d4692Sfgsch       break;
275b55d4692Sfgsch     case bfd_mach_mcf5407:
276b55d4692Sfgsch       arch_mask = mcf5407;
277b55d4692Sfgsch       break;
278f7cc78ecSespie     }
279f7cc78ecSespie 
280f7cc78ecSespie   arch_mask |= m68881 | m68851;
281f7cc78ecSespie 
2822159047fSniklas   bestmask = 0;
2832159047fSniklas   FETCH_DATA (info, buffer + 2);
284fddef416Sniklas   major_opcode = (buffer[0] >> 4) & 15;
285fddef416Sniklas   for (i = 0; i < numopcodes[major_opcode]; i++)
2862159047fSniklas     {
287fddef416Sniklas       const struct m68k_opcode *opc = opcodes[major_opcode][i];
2882159047fSniklas       unsigned long opcode = opc->opcode;
2892159047fSniklas       unsigned long match = opc->match;
2902159047fSniklas 
2912159047fSniklas       if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
2922159047fSniklas 	  && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
2932159047fSniklas 	  /* Only fetch the next two bytes if we need to.  */
2942159047fSniklas 	  && (((0xffff & match) == 0)
2952159047fSniklas 	      ||
2962159047fSniklas 	      (FETCH_DATA (info, buffer + 4)
2972159047fSniklas 	       && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
2982159047fSniklas 	       && ((0xff & buffer[3] & match) == (0xff & opcode)))
299f7cc78ecSespie 	      )
300f7cc78ecSespie 	  && (opc->arch & arch_mask) != 0)
3012159047fSniklas 	{
3022159047fSniklas 	  /* Don't use for printout the variants of divul and divsl
3032159047fSniklas 	     that have the same register number in two places.
3042159047fSniklas 	     The more general variants will match instead.  */
3052159047fSniklas 	  for (d = opc->args; *d; d += 2)
3062159047fSniklas 	    if (d[1] == 'D')
3072159047fSniklas 	      break;
3082159047fSniklas 
3092159047fSniklas 	  /* Don't use for printout the variants of most floating
3102159047fSniklas 	     point coprocessor instructions which use the same
3112159047fSniklas 	     register number in two places, as above. */
3122159047fSniklas 	  if (*d == '\0')
3132159047fSniklas 	    for (d = opc->args; *d; d += 2)
3142159047fSniklas 	      if (d[1] == 't')
3152159047fSniklas 		break;
3162159047fSniklas 
3172159047fSniklas 	  /* Don't match fmovel with more than one register; wait for
3182159047fSniklas              fmoveml.  */
3192159047fSniklas 	  if (*d == '\0')
3202159047fSniklas 	    {
3212159047fSniklas 	      for (d = opc->args; *d; d += 2)
3222159047fSniklas 		{
3232159047fSniklas 		  if (d[0] == 's' && d[1] == '8')
3242159047fSniklas 		    {
3252159047fSniklas 		      int val;
3262159047fSniklas 
3272159047fSniklas 		      val = fetch_arg (buffer, d[1], 3, info);
3282159047fSniklas 		      if ((val & (val - 1)) != 0)
3292159047fSniklas 			break;
3302159047fSniklas 		    }
3312159047fSniklas 		}
3322159047fSniklas 	    }
3332159047fSniklas 
3342159047fSniklas 	  if (*d == '\0' && match > bestmask)
3352159047fSniklas 	    {
3362159047fSniklas 	      best = opc;
3372159047fSniklas 	      bestmask = match;
3382159047fSniklas 	    }
3392159047fSniklas 	}
3402159047fSniklas     }
3412159047fSniklas 
342b55d4692Sfgsch   if (best == NULL)
3432159047fSniklas     goto invalid;
3442159047fSniklas 
3452159047fSniklas   /* Point at first word of argument data,
3462159047fSniklas      and at descriptor for first argument.  */
3472159047fSniklas   p = buffer + 2;
3482159047fSniklas 
3492159047fSniklas   /* Figure out how long the fixed-size portion of the instruction is.
3502159047fSniklas      The only place this is stored in the opcode table is
3512159047fSniklas      in the arguments--look for arguments which specify fields in the 2nd
3522159047fSniklas      or 3rd words of the instruction.  */
3532159047fSniklas   for (d = best->args; *d; d += 2)
3542159047fSniklas     {
3552159047fSniklas       /* I don't think it is necessary to be checking d[0] here; I suspect
3562159047fSniklas 	 all this could be moved to the case statement below.  */
3572159047fSniklas       if (d[0] == '#')
3582159047fSniklas 	{
3592159047fSniklas 	  if (d[1] == 'l' && p - buffer < 6)
3602159047fSniklas 	    p = buffer + 6;
3612159047fSniklas 	  else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8')
3622159047fSniklas 	    p = buffer + 4;
3632159047fSniklas 	}
3642159047fSniklas       if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
3652159047fSniklas 	p = buffer + 4;
3662159047fSniklas       switch (d[1])
3672159047fSniklas 	{
3682159047fSniklas 	case '1':
3692159047fSniklas 	case '2':
3702159047fSniklas 	case '3':
3712159047fSniklas 	case '7':
3722159047fSniklas 	case '8':
3732159047fSniklas 	case '9':
3742159047fSniklas 	case 'i':
3752159047fSniklas 	  if (p - buffer < 4)
3762159047fSniklas 	    p = buffer + 4;
3772159047fSniklas 	  break;
3782159047fSniklas 	case '4':
3792159047fSniklas 	case '5':
3802159047fSniklas 	case '6':
3812159047fSniklas 	  if (p - buffer < 6)
3822159047fSniklas 	    p = buffer + 6;
3832159047fSniklas 	  break;
3842159047fSniklas 	default:
3852159047fSniklas 	  break;
3862159047fSniklas 	}
3872159047fSniklas     }
388f7cc78ecSespie 
389f7cc78ecSespie   /* pflusha is an exceptions.  It takes no arguments but is two words
390f7cc78ecSespie      long.  Recognize it by looking at the lower 16 bits of the mask.  */
3912159047fSniklas   if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
3922159047fSniklas     p = buffer + 4;
3932159047fSniklas 
394f7cc78ecSespie   /* lpstop is another exception.  It takes a one word argument but is
395f7cc78ecSespie      three words long.  */
396f7cc78ecSespie   if (p - buffer < 6
397f7cc78ecSespie       && (best->match & 0xffff) == 0xffff
398f7cc78ecSespie       && best->args[0] == '#'
399f7cc78ecSespie       && best->args[1] == 'w')
400f7cc78ecSespie     {
401f7cc78ecSespie       /* Copy the one word argument into the usual location for a one
402f7cc78ecSespie 	 word argument, to simplify printing it.  We can get away with
403f7cc78ecSespie 	 this because we know exactly what the second word is, and we
404f7cc78ecSespie 	 aren't going to print anything based on it.  */
405f7cc78ecSespie       p = buffer + 6;
406f7cc78ecSespie       FETCH_DATA (info, p);
407f7cc78ecSespie       buffer[2] = buffer[4];
408f7cc78ecSespie       buffer[3] = buffer[5];
409f7cc78ecSespie     }
410f7cc78ecSespie 
4112159047fSniklas   FETCH_DATA (info, p);
4122159047fSniklas 
4132159047fSniklas   d = best->args;
4142159047fSniklas 
415*007c2a45Smiod   /* We scan the operands twice.  The first time we don't print anything,
4162159047fSniklas      but look for errors. */
4172159047fSniklas 
4182159047fSniklas   save_p = p;
4192159047fSniklas   info->print_address_func = dummy_print_address;
4202159047fSniklas   info->fprintf_func = (fprintf_ftype) dummy_printer;
4212159047fSniklas   for (; *d; d += 2)
4222159047fSniklas     {
423f7cc78ecSespie       int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
4242159047fSniklas       if (eaten >= 0)
4252159047fSniklas 	p += eaten;
4262159047fSniklas       else if (eaten == -1)
4272159047fSniklas 	goto invalid;
4282159047fSniklas       else
4292159047fSniklas 	{
4302159047fSniklas 	  (*info->fprintf_func) (info->stream,
431f7cc78ecSespie 				 /* xgettext:c-format */
432f7cc78ecSespie 				 _("<internal error in opcode table: %s %s>\n"),
4332159047fSniklas 				 best->name,
4342159047fSniklas 				 best->args);
4352159047fSniklas 	  goto invalid;
4362159047fSniklas 	}
4372159047fSniklas 
4382159047fSniklas     }
4392159047fSniklas   p = save_p;
4402159047fSniklas   info->fprintf_func = save_printer;
4412159047fSniklas   info->print_address_func = save_print_address;
4422159047fSniklas 
4432159047fSniklas   d = best->args;
4442159047fSniklas 
4452159047fSniklas   (*info->fprintf_func) (info->stream, "%s", best->name);
4462159047fSniklas 
4472159047fSniklas   if (*d)
4482159047fSniklas     (*info->fprintf_func) (info->stream, " ");
4492159047fSniklas 
4502159047fSniklas   while (*d)
4512159047fSniklas     {
452f7cc78ecSespie       p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
4532159047fSniklas       d += 2;
4542159047fSniklas       if (*d && *(d - 2) != 'I' && *d != 'k')
4552159047fSniklas 	(*info->fprintf_func) (info->stream, ",");
4562159047fSniklas     }
4572159047fSniklas   return p - buffer;
4582159047fSniklas 
4592159047fSniklas  invalid:
4602159047fSniklas   /* Handle undefined instructions.  */
4612159047fSniklas   info->fprintf_func = save_printer;
4622159047fSniklas   info->print_address_func = save_print_address;
4632159047fSniklas   (*info->fprintf_func) (info->stream, "0%o",
4642159047fSniklas 			 (buffer[0] << 8) + buffer[1]);
4652159047fSniklas   return 2;
4662159047fSniklas }
4672159047fSniklas 
4682159047fSniklas /* Returns number of bytes "eaten" by the operand, or
4692159047fSniklas    return -1 if an invalid operand was found, or -2 if
4702159047fSniklas    an opcode tabe error was found. */
4712159047fSniklas 
4722159047fSniklas static int
print_insn_arg(d,buffer,p0,addr,info)4732159047fSniklas print_insn_arg (d, buffer, p0, addr, info)
4742159047fSniklas      const char *d;
4752159047fSniklas      unsigned char *buffer;
4762159047fSniklas      unsigned char *p0;
4772159047fSniklas      bfd_vma addr;		/* PC for this arg to be relative to */
4782159047fSniklas      disassemble_info *info;
4792159047fSniklas {
4802159047fSniklas   register int val = 0;
4812159047fSniklas   register int place = d[1];
4822159047fSniklas   register unsigned char *p = p0;
4832159047fSniklas   int regno;
484c074d1c9Sdrahn   register const char *regname;
4852159047fSniklas   register unsigned char *p1;
4862159047fSniklas   double flval;
4872159047fSniklas   int flt_p;
488f7cc78ecSespie   bfd_signed_vma disp;
489f7cc78ecSespie   unsigned int uval;
4902159047fSniklas 
4912159047fSniklas   switch (*d)
4922159047fSniklas     {
4932159047fSniklas     case 'c':		/* cache identifier */
4942159047fSniklas       {
4952159047fSniklas         static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
4962159047fSniklas         val = fetch_arg (buffer, place, 2, info);
4972159047fSniklas         (*info->fprintf_func) (info->stream, cacheFieldName[val]);
4982159047fSniklas         break;
4992159047fSniklas       }
5002159047fSniklas 
5012159047fSniklas     case 'a':		/* address register indirect only. Cf. case '+'. */
5022159047fSniklas       {
5032159047fSniklas         (*info->fprintf_func)
5042159047fSniklas 	  (info->stream,
5052159047fSniklas 	   "%s@",
5062159047fSniklas 	   reg_names[fetch_arg (buffer, place, 3, info) + 8]);
5072159047fSniklas         break;
5082159047fSniklas       }
5092159047fSniklas 
5102159047fSniklas     case '_':		/* 32-bit absolute address for move16. */
5112159047fSniklas       {
512f7cc78ecSespie         uval = NEXTULONG (p);
513f7cc78ecSespie 	(*info->print_address_func) (uval, info);
5142159047fSniklas         break;
5152159047fSniklas       }
5162159047fSniklas 
5172159047fSniklas     case 'C':
5182159047fSniklas       (*info->fprintf_func) (info->stream, "%%ccr");
5192159047fSniklas       break;
5202159047fSniklas 
5212159047fSniklas     case 'S':
5222159047fSniklas       (*info->fprintf_func) (info->stream, "%%sr");
5232159047fSniklas       break;
5242159047fSniklas 
5252159047fSniklas     case 'U':
5262159047fSniklas       (*info->fprintf_func) (info->stream, "%%usp");
5272159047fSniklas       break;
5282159047fSniklas 
529f7cc78ecSespie     case 'E':
530f7cc78ecSespie       (*info->fprintf_func) (info->stream, "%%acc");
531f7cc78ecSespie       break;
532f7cc78ecSespie 
533f7cc78ecSespie     case 'G':
534f7cc78ecSespie       (*info->fprintf_func) (info->stream, "%%macsr");
535f7cc78ecSespie       break;
536f7cc78ecSespie 
537f7cc78ecSespie     case 'H':
538f7cc78ecSespie       (*info->fprintf_func) (info->stream, "%%mask");
539f7cc78ecSespie       break;
540f7cc78ecSespie 
5412159047fSniklas     case 'J':
5422159047fSniklas       {
543*007c2a45Smiod 	/* FIXME: There's a problem here, different m68k processors call the
544*007c2a45Smiod 	   same address different names. This table can't get it right
545*007c2a45Smiod 	   because it doesn't know which processor it's disassembling for.  */
5462159047fSniklas 	static const struct { char *name; int value; } names[]
5472159047fSniklas 	  = {{"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
5482159047fSniklas 	     {"%tc",  0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
5492159047fSniklas              {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
5502159047fSniklas 	     {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
551fddef416Sniklas 	     {"%msp", 0x803}, {"%isp", 0x804},
552*007c2a45Smiod 	     {"%flashbar", 0xc04}, {"%rambar", 0xc05}, /* mcf528x added these.  */
5532159047fSniklas 
5542159047fSniklas 	     /* Should we be calling this psr like we do in case 'Y'?  */
5552159047fSniklas 	     {"%mmusr",0x805},
5562159047fSniklas 
5572159047fSniklas              {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808}};
5582159047fSniklas 
5592159047fSniklas 	val = fetch_arg (buffer, place, 12, info);
5602159047fSniklas 	for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
5612159047fSniklas 	  if (names[regno].value == val)
5622159047fSniklas 	    {
5632159047fSniklas 	      (*info->fprintf_func) (info->stream, "%s", names[regno].name);
5642159047fSniklas 	      break;
5652159047fSniklas 	    }
5662159047fSniklas 	if (regno < 0)
5672159047fSniklas 	  (*info->fprintf_func) (info->stream, "%d", val);
5682159047fSniklas       }
5692159047fSniklas       break;
5702159047fSniklas 
5712159047fSniklas     case 'Q':
5722159047fSniklas       val = fetch_arg (buffer, place, 3, info);
5732159047fSniklas       /* 0 means 8, except for the bkpt instruction... */
5742159047fSniklas       if (val == 0 && d[1] != 's')
5752159047fSniklas 	val = 8;
5762159047fSniklas       (*info->fprintf_func) (info->stream, "#%d", val);
5772159047fSniklas       break;
5782159047fSniklas 
579*007c2a45Smiod     case 'x':
580*007c2a45Smiod       val = fetch_arg (buffer, place, 3, info);
581*007c2a45Smiod       /* 0 means -1.  */
582*007c2a45Smiod       if (val == 0)
583*007c2a45Smiod 	val = -1;
584*007c2a45Smiod       (*info->fprintf_func) (info->stream, "#%d", val);
585*007c2a45Smiod       break;
586*007c2a45Smiod 
5872159047fSniklas     case 'M':
588f7cc78ecSespie       if (place == 'h')
589f7cc78ecSespie 	{
590f7cc78ecSespie 	  static char *const scalefactor_name[] = { "<<", ">>" };
591f7cc78ecSespie 	  val = fetch_arg (buffer, place, 1, info);
592f7cc78ecSespie 	  (*info->fprintf_func) (info->stream, scalefactor_name[val]);
593f7cc78ecSespie 	}
594f7cc78ecSespie       else
595f7cc78ecSespie 	{
5962159047fSniklas 	  val = fetch_arg (buffer, place, 8, info);
5972159047fSniklas 	  if (val & 0x80)
5982159047fSniklas 	    val = val - 0x100;
5992159047fSniklas 	  (*info->fprintf_func) (info->stream, "#%d", val);
600f7cc78ecSespie 	}
6012159047fSniklas       break;
6022159047fSniklas 
6032159047fSniklas     case 'T':
6042159047fSniklas       val = fetch_arg (buffer, place, 4, info);
6052159047fSniklas       (*info->fprintf_func) (info->stream, "#%d", val);
6062159047fSniklas       break;
6072159047fSniklas 
6082159047fSniklas     case 'D':
6092159047fSniklas       (*info->fprintf_func) (info->stream, "%s",
6102159047fSniklas 			     reg_names[fetch_arg (buffer, place, 3, info)]);
6112159047fSniklas       break;
6122159047fSniklas 
6132159047fSniklas     case 'A':
6142159047fSniklas       (*info->fprintf_func)
6152159047fSniklas 	(info->stream, "%s",
6162159047fSniklas 	 reg_names[fetch_arg (buffer, place, 3, info) + 010]);
6172159047fSniklas       break;
6182159047fSniklas 
6192159047fSniklas     case 'R':
6202159047fSniklas       (*info->fprintf_func)
6212159047fSniklas 	(info->stream, "%s",
6222159047fSniklas 	 reg_names[fetch_arg (buffer, place, 4, info)]);
6232159047fSniklas       break;
6242159047fSniklas 
6252159047fSniklas     case 'r':
6262159047fSniklas       regno = fetch_arg (buffer, place, 4, info);
6272159047fSniklas       if (regno > 7)
6282159047fSniklas 	(*info->fprintf_func) (info->stream, "%s@", reg_names[regno]);
6292159047fSniklas       else
6302159047fSniklas 	(*info->fprintf_func) (info->stream, "@(%s)", reg_names[regno]);
6312159047fSniklas       break;
6322159047fSniklas 
6332159047fSniklas     case 'F':
6342159047fSniklas       (*info->fprintf_func)
6352159047fSniklas 	(info->stream, "%%fp%d",
6362159047fSniklas 	 fetch_arg (buffer, place, 3, info));
6372159047fSniklas       break;
6382159047fSniklas 
6392159047fSniklas     case 'O':
6402159047fSniklas       val = fetch_arg (buffer, place, 6, info);
6412159047fSniklas       if (val & 0x20)
6422159047fSniklas 	(*info->fprintf_func) (info->stream, "%s", reg_names[val & 7]);
6432159047fSniklas       else
6442159047fSniklas 	(*info->fprintf_func) (info->stream, "%d", val);
6452159047fSniklas       break;
6462159047fSniklas 
6472159047fSniklas     case '+':
6482159047fSniklas       (*info->fprintf_func)
6492159047fSniklas 	(info->stream, "%s@+",
6502159047fSniklas 	 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
6512159047fSniklas       break;
6522159047fSniklas 
6532159047fSniklas     case '-':
6542159047fSniklas       (*info->fprintf_func)
6552159047fSniklas 	(info->stream, "%s@-",
6562159047fSniklas 	 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
6572159047fSniklas       break;
6582159047fSniklas 
6592159047fSniklas     case 'k':
6602159047fSniklas       if (place == 'k')
6612159047fSniklas 	(*info->fprintf_func)
6622159047fSniklas 	  (info->stream, "{%s}",
6632159047fSniklas 	   reg_names[fetch_arg (buffer, place, 3, info)]);
6642159047fSniklas       else if (place == 'C')
6652159047fSniklas 	{
6662159047fSniklas 	  val = fetch_arg (buffer, place, 7, info);
6672159047fSniklas 	  if (val > 63)		/* This is a signed constant. */
6682159047fSniklas 	    val -= 128;
6692159047fSniklas 	  (*info->fprintf_func) (info->stream, "{#%d}", val);
6702159047fSniklas 	}
6712159047fSniklas       else
6722159047fSniklas 	return -2;
6732159047fSniklas       break;
6742159047fSniklas 
6752159047fSniklas     case '#':
6762159047fSniklas     case '^':
6772159047fSniklas       p1 = buffer + (*d == '#' ? 2 : 4);
6782159047fSniklas       if (place == 's')
6792159047fSniklas 	val = fetch_arg (buffer, place, 4, info);
6802159047fSniklas       else if (place == 'C')
6812159047fSniklas 	val = fetch_arg (buffer, place, 7, info);
6822159047fSniklas       else if (place == '8')
6832159047fSniklas 	val = fetch_arg (buffer, place, 3, info);
6842159047fSniklas       else if (place == '3')
6852159047fSniklas 	val = fetch_arg (buffer, place, 8, info);
6862159047fSniklas       else if (place == 'b')
6872159047fSniklas 	val = NEXTBYTE (p1);
6882159047fSniklas       else if (place == 'w' || place == 'W')
6892159047fSniklas 	val = NEXTWORD (p1);
6902159047fSniklas       else if (place == 'l')
6912159047fSniklas 	val = NEXTLONG (p1);
6922159047fSniklas       else
6932159047fSniklas 	return -2;
6942159047fSniklas       (*info->fprintf_func) (info->stream, "#%d", val);
6952159047fSniklas       break;
6962159047fSniklas 
6972159047fSniklas     case 'B':
6982159047fSniklas       if (place == 'b')
699f7cc78ecSespie 	disp = NEXTBYTE (p);
7002159047fSniklas       else if (place == 'B')
701f7cc78ecSespie 	disp = COERCE_SIGNED_CHAR (buffer[1]);
7022159047fSniklas       else if (place == 'w' || place == 'W')
703f7cc78ecSespie 	disp = NEXTWORD (p);
7042159047fSniklas       else if (place == 'l' || place == 'L' || place == 'C')
705f7cc78ecSespie 	disp = NEXTLONG (p);
7062159047fSniklas       else if (place == 'g')
7072159047fSniklas 	{
708f7cc78ecSespie 	  disp = NEXTBYTE (buffer);
709f7cc78ecSespie 	  if (disp == 0)
710f7cc78ecSespie 	    disp = NEXTWORD (p);
711f7cc78ecSespie 	  else if (disp == -1)
712f7cc78ecSespie 	    disp = NEXTLONG (p);
7132159047fSniklas 	}
7142159047fSniklas       else if (place == 'c')
7152159047fSniklas 	{
7162159047fSniklas 	  if (buffer[1] & 0x40)		/* If bit six is one, long offset */
717f7cc78ecSespie 	    disp = NEXTLONG (p);
7182159047fSniklas 	  else
719f7cc78ecSespie 	    disp = NEXTWORD (p);
7202159047fSniklas 	}
7212159047fSniklas       else
7222159047fSniklas 	return -2;
7232159047fSniklas 
724f7cc78ecSespie       (*info->print_address_func) (addr + disp, info);
7252159047fSniklas       break;
7262159047fSniklas 
7272159047fSniklas     case 'd':
7282159047fSniklas       val = NEXTWORD (p);
7292159047fSniklas       (*info->fprintf_func)
7302159047fSniklas 	(info->stream, "%s@(%d)",
731fddef416Sniklas 	 reg_names[fetch_arg (buffer, place, 3, info) + 8], val);
7322159047fSniklas       break;
7332159047fSniklas 
7342159047fSniklas     case 's':
7352159047fSniklas       (*info->fprintf_func) (info->stream, "%s",
7362159047fSniklas 			     fpcr_names[fetch_arg (buffer, place, 3, info)]);
7372159047fSniklas       break;
7382159047fSniklas 
7392159047fSniklas     case 'I':
7402159047fSniklas       /* Get coprocessor ID... */
7412159047fSniklas       val = fetch_arg (buffer, 'd', 3, info);
7422159047fSniklas 
7432159047fSniklas       if (val != 1)				/* Unusual coprocessor ID? */
7442159047fSniklas 	(*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
7452159047fSniklas       break;
7462159047fSniklas 
7472159047fSniklas     case '*':
7482159047fSniklas     case '~':
7492159047fSniklas     case '%':
7502159047fSniklas     case ';':
7512159047fSniklas     case '@':
7522159047fSniklas     case '!':
7532159047fSniklas     case '$':
7542159047fSniklas     case '?':
7552159047fSniklas     case '/':
7562159047fSniklas     case '&':
7572159047fSniklas     case '|':
758fddef416Sniklas     case '<':
759fddef416Sniklas     case '>':
760f7cc78ecSespie     case 'm':
761f7cc78ecSespie     case 'n':
762f7cc78ecSespie     case 'o':
763f7cc78ecSespie     case 'p':
764f7cc78ecSespie     case 'q':
765f7cc78ecSespie     case 'v':
766*007c2a45Smiod     case 'b':
767*007c2a45Smiod     case 'w':
768*007c2a45Smiod     case 'y':
769*007c2a45Smiod     case 'z':
7702159047fSniklas       if (place == 'd')
7712159047fSniklas 	{
7722159047fSniklas 	  val = fetch_arg (buffer, 'x', 6, info);
7732159047fSniklas 	  val = ((val & 7) << 3) + ((val >> 3) & 7);
7742159047fSniklas 	}
7752159047fSniklas       else
7762159047fSniklas 	val = fetch_arg (buffer, 's', 6, info);
7772159047fSniklas 
7782159047fSniklas       /* Get register number assuming address register.  */
7792159047fSniklas       regno = (val & 7) + 8;
7802159047fSniklas       regname = reg_names[regno];
7812159047fSniklas       switch (val >> 3)
7822159047fSniklas 	{
7832159047fSniklas 	case 0:
7842159047fSniklas 	  (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
7852159047fSniklas 	  break;
7862159047fSniklas 
7872159047fSniklas 	case 1:
7882159047fSniklas 	  (*info->fprintf_func) (info->stream, "%s", regname);
7892159047fSniklas 	  break;
7902159047fSniklas 
7912159047fSniklas 	case 2:
7922159047fSniklas 	  (*info->fprintf_func) (info->stream, "%s@", regname);
7932159047fSniklas 	  break;
7942159047fSniklas 
7952159047fSniklas 	case 3:
7962159047fSniklas 	  (*info->fprintf_func) (info->stream, "%s@+", regname);
7972159047fSniklas 	  break;
7982159047fSniklas 
7992159047fSniklas 	case 4:
8002159047fSniklas 	  (*info->fprintf_func) (info->stream, "%s@-", regname);
8012159047fSniklas 	  break;
8022159047fSniklas 
8032159047fSniklas 	case 5:
8042159047fSniklas 	  val = NEXTWORD (p);
8052159047fSniklas 	  (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
8062159047fSniklas 	  break;
8072159047fSniklas 
8082159047fSniklas 	case 6:
8092159047fSniklas 	  p = print_indexed (regno, p, addr, info);
8102159047fSniklas 	  break;
8112159047fSniklas 
8122159047fSniklas 	case 7:
8132159047fSniklas 	  switch (val & 7)
8142159047fSniklas 	    {
8152159047fSniklas 	    case 0:
8162159047fSniklas 	      val = NEXTWORD (p);
8172159047fSniklas 	      (*info->print_address_func) (val, info);
8182159047fSniklas 	      break;
8192159047fSniklas 
8202159047fSniklas 	    case 1:
821f7cc78ecSespie 	      uval = NEXTULONG (p);
822f7cc78ecSespie 	      (*info->print_address_func) (uval, info);
8232159047fSniklas 	      break;
8242159047fSniklas 
8252159047fSniklas 	    case 2:
8262159047fSniklas 	      val = NEXTWORD (p);
827f7cc78ecSespie 	      (*info->fprintf_func) (info->stream, "%%pc@(");
8282159047fSniklas 	      (*info->print_address_func) (addr + val, info);
829f7cc78ecSespie 	      (*info->fprintf_func) (info->stream, ")");
8302159047fSniklas 	      break;
8312159047fSniklas 
8322159047fSniklas 	    case 3:
8332159047fSniklas 	      p = print_indexed (-1, p, addr, info);
8342159047fSniklas 	      break;
8352159047fSniklas 
8362159047fSniklas 	    case 4:
8372159047fSniklas 	      flt_p = 1;	/* Assume it's a float... */
8382159047fSniklas 	      switch (place)
8392159047fSniklas 	      {
8402159047fSniklas 		case 'b':
8412159047fSniklas 		  val = NEXTBYTE (p);
8422159047fSniklas 		  flt_p = 0;
8432159047fSniklas 		  break;
8442159047fSniklas 
8452159047fSniklas 		case 'w':
8462159047fSniklas 		  val = NEXTWORD (p);
8472159047fSniklas 		  flt_p = 0;
8482159047fSniklas 		  break;
8492159047fSniklas 
8502159047fSniklas 		case 'l':
8512159047fSniklas 		  val = NEXTLONG (p);
8522159047fSniklas 		  flt_p = 0;
8532159047fSniklas 		  break;
8542159047fSniklas 
8552159047fSniklas 		case 'f':
8562159047fSniklas 		  NEXTSINGLE (flval, p);
8572159047fSniklas 		  break;
8582159047fSniklas 
8592159047fSniklas 		case 'F':
8602159047fSniklas 		  NEXTDOUBLE (flval, p);
8612159047fSniklas 		  break;
8622159047fSniklas 
8632159047fSniklas 		case 'x':
864fddef416Sniklas 		  NEXTEXTEND (flval, p);
8652159047fSniklas 		  break;
8662159047fSniklas 
8672159047fSniklas 		case 'p':
8682159047fSniklas 		  flval = NEXTPACKED (p);
8692159047fSniklas 		  break;
8702159047fSniklas 
8712159047fSniklas 		default:
8722159047fSniklas 		  return -1;
8732159047fSniklas 	      }
8742159047fSniklas 	      if (flt_p)	/* Print a float? */
8752159047fSniklas 		(*info->fprintf_func) (info->stream, "#%g", flval);
8762159047fSniklas 	      else
8772159047fSniklas 		(*info->fprintf_func) (info->stream, "#%d", val);
8782159047fSniklas 	      break;
8792159047fSniklas 
8802159047fSniklas 	    default:
8812159047fSniklas 	      return -1;
8822159047fSniklas 	    }
8832159047fSniklas 	}
8842159047fSniklas       break;
8852159047fSniklas 
8862159047fSniklas     case 'L':
8872159047fSniklas     case 'l':
8882159047fSniklas 	if (place == 'w')
8892159047fSniklas 	  {
8902159047fSniklas 	    char doneany;
8912159047fSniklas 	    p1 = buffer + 2;
8922159047fSniklas 	    val = NEXTWORD (p1);
8932159047fSniklas 	    /* Move the pointer ahead if this point is farther ahead
8942159047fSniklas 	       than the last.  */
8952159047fSniklas 	    p = p1 > p ? p1 : p;
8962159047fSniklas 	    if (val == 0)
8972159047fSniklas 	      {
8982159047fSniklas 		(*info->fprintf_func) (info->stream, "#0");
8992159047fSniklas 		break;
9002159047fSniklas 	      }
9012159047fSniklas 	    if (*d == 'l')
9022159047fSniklas 	      {
9032159047fSniklas 		register int newval = 0;
9042159047fSniklas 		for (regno = 0; regno < 16; ++regno)
9052159047fSniklas 		  if (val & (0x8000 >> regno))
9062159047fSniklas 		    newval |= 1 << regno;
9072159047fSniklas 		val = newval;
9082159047fSniklas 	      }
9092159047fSniklas 	    val &= 0xffff;
9102159047fSniklas 	    doneany = 0;
9112159047fSniklas 	    for (regno = 0; regno < 16; ++regno)
9122159047fSniklas 	      if (val & (1 << regno))
9132159047fSniklas 		{
9142159047fSniklas 		  int first_regno;
9152159047fSniklas 		  if (doneany)
9162159047fSniklas 		    (*info->fprintf_func) (info->stream, "/");
9172159047fSniklas 		  doneany = 1;
9182159047fSniklas 		  (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
9192159047fSniklas 		  first_regno = regno;
9202159047fSniklas 		  while (val & (1 << (regno + 1)))
9212159047fSniklas 		    ++regno;
9222159047fSniklas 		  if (regno > first_regno)
9232159047fSniklas 		    (*info->fprintf_func) (info->stream, "-%s",
9242159047fSniklas 					   reg_names[regno]);
9252159047fSniklas 		}
9262159047fSniklas 	  }
9272159047fSniklas 	else if (place == '3')
9282159047fSniklas 	  {
9292159047fSniklas 	    /* `fmovem' insn.  */
9302159047fSniklas 	    char doneany;
9312159047fSniklas 	    val = fetch_arg (buffer, place, 8, info);
9322159047fSniklas 	    if (val == 0)
9332159047fSniklas 	      {
9342159047fSniklas 		(*info->fprintf_func) (info->stream, "#0");
9352159047fSniklas 		break;
9362159047fSniklas 	      }
9372159047fSniklas 	    if (*d == 'l')
9382159047fSniklas 	      {
9392159047fSniklas 		register int newval = 0;
9402159047fSniklas 		for (regno = 0; regno < 8; ++regno)
9412159047fSniklas 		  if (val & (0x80 >> regno))
9422159047fSniklas 		    newval |= 1 << regno;
9432159047fSniklas 		val = newval;
9442159047fSniklas 	      }
9452159047fSniklas 	    val &= 0xff;
9462159047fSniklas 	    doneany = 0;
9472159047fSniklas 	    for (regno = 0; regno < 8; ++regno)
9482159047fSniklas 	      if (val & (1 << regno))
9492159047fSniklas 		{
9502159047fSniklas 		  int first_regno;
9512159047fSniklas 		  if (doneany)
9522159047fSniklas 		    (*info->fprintf_func) (info->stream, "/");
9532159047fSniklas 		  doneany = 1;
9542159047fSniklas 		  (*info->fprintf_func) (info->stream, "%%fp%d", regno);
9552159047fSniklas 		  first_regno = regno;
9562159047fSniklas 		  while (val & (1 << (regno + 1)))
9572159047fSniklas 		    ++regno;
9582159047fSniklas 		  if (regno > first_regno)
9592159047fSniklas 		    (*info->fprintf_func) (info->stream, "-%%fp%d", regno);
9602159047fSniklas 		}
9612159047fSniklas 	  }
9622159047fSniklas 	else if (place == '8')
9632159047fSniklas 	  {
9642159047fSniklas 	    /* fmoveml for FP status registers */
9652159047fSniklas 	    (*info->fprintf_func) (info->stream, "%s",
9662159047fSniklas 				   fpcr_names[fetch_arg (buffer, place, 3,
9672159047fSniklas 							 info)]);
9682159047fSniklas 	  }
9692159047fSniklas 	else
9702159047fSniklas 	  return -2;
9712159047fSniklas       break;
9722159047fSniklas 
9732159047fSniklas     case 'X':
9742159047fSniklas       place = '8';
9752159047fSniklas     case 'Y':
9762159047fSniklas     case 'Z':
9772159047fSniklas     case 'W':
9782159047fSniklas     case '0':
9792159047fSniklas     case '1':
9802159047fSniklas     case '2':
9812159047fSniklas     case '3':
9822159047fSniklas       {
9832159047fSniklas 	int val = fetch_arg (buffer, place, 5, info);
9842159047fSniklas 	char *name = 0;
9852159047fSniklas 	switch (val)
9862159047fSniklas 	  {
9872159047fSniklas 	  case 2: name = "%tt0"; break;
9882159047fSniklas 	  case 3: name = "%tt1"; break;
9892159047fSniklas 	  case 0x10: name = "%tc"; break;
9902159047fSniklas 	  case 0x11: name = "%drp"; break;
9912159047fSniklas 	  case 0x12: name = "%srp"; break;
9922159047fSniklas 	  case 0x13: name = "%crp"; break;
9932159047fSniklas 	  case 0x14: name = "%cal"; break;
9942159047fSniklas 	  case 0x15: name = "%val"; break;
9952159047fSniklas 	  case 0x16: name = "%scc"; break;
9962159047fSniklas 	  case 0x17: name = "%ac"; break;
9972159047fSniklas  	  case 0x18: name = "%psr"; break;
9982159047fSniklas 	  case 0x19: name = "%pcsr"; break;
9992159047fSniklas 	  case 0x1c:
10002159047fSniklas 	  case 0x1d:
10012159047fSniklas 	    {
10022159047fSniklas 	      int break_reg = ((buffer[3] >> 2) & 7);
10032159047fSniklas 	      (*info->fprintf_func)
10042159047fSniklas 		(info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
10052159047fSniklas 		 break_reg);
10062159047fSniklas 	    }
10072159047fSniklas 	    break;
10082159047fSniklas 	  default:
10092159047fSniklas 	    (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
10102159047fSniklas 	  }
10112159047fSniklas 	if (name)
10122159047fSniklas 	  (*info->fprintf_func) (info->stream, "%s", name);
10132159047fSniklas       }
10142159047fSniklas       break;
10152159047fSniklas 
10162159047fSniklas     case 'f':
10172159047fSniklas       {
10182159047fSniklas 	int fc = fetch_arg (buffer, place, 5, info);
10192159047fSniklas 	if (fc == 1)
10202159047fSniklas 	  (*info->fprintf_func) (info->stream, "%%dfc");
10212159047fSniklas 	else if (fc == 0)
10222159047fSniklas 	  (*info->fprintf_func) (info->stream, "%%sfc");
10232159047fSniklas 	else
1024f7cc78ecSespie 	  /* xgettext:c-format */
1025f7cc78ecSespie 	  (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
10262159047fSniklas       }
10272159047fSniklas       break;
10282159047fSniklas 
10292159047fSniklas     case 'V':
10302159047fSniklas       (*info->fprintf_func) (info->stream, "%%val");
10312159047fSniklas       break;
10322159047fSniklas 
10332159047fSniklas     case 't':
10342159047fSniklas       {
10352159047fSniklas 	int level = fetch_arg (buffer, place, 3, info);
10362159047fSniklas 	(*info->fprintf_func) (info->stream, "%d", level);
10372159047fSniklas       }
10382159047fSniklas       break;
10392159047fSniklas 
1040f7cc78ecSespie     case 'u':
1041f7cc78ecSespie       {
1042f7cc78ecSespie 	short is_upper = 0;
1043f7cc78ecSespie 	int reg = fetch_arg (buffer, place, 5, info);
1044f7cc78ecSespie 
1045f7cc78ecSespie 	if (reg & 0x10)
1046f7cc78ecSespie 	  {
1047f7cc78ecSespie 	    is_upper = 1;
1048f7cc78ecSespie 	    reg &= 0xf;
1049f7cc78ecSespie 	  }
1050f7cc78ecSespie 	(*info->fprintf_func) (info->stream, "%s%s",
1051f7cc78ecSespie 			       reg_names[reg],
1052f7cc78ecSespie 			       is_upper ? "u" : "l");
1053f7cc78ecSespie       }
1054f7cc78ecSespie       break;
1055f7cc78ecSespie 
10562159047fSniklas     default:
10572159047fSniklas       return -2;
10582159047fSniklas     }
10592159047fSniklas 
10602159047fSniklas   return p - p0;
10612159047fSniklas }
10622159047fSniklas 
10632159047fSniklas /* Fetch BITS bits from a position in the instruction specified by CODE.
10642159047fSniklas    CODE is a "place to put an argument", or 'x' for a destination
10652159047fSniklas    that is a general address (mode and register).
10662159047fSniklas    BUFFER contains the instruction.  */
10672159047fSniklas 
10682159047fSniklas static int
fetch_arg(buffer,code,bits,info)10692159047fSniklas fetch_arg (buffer, code, bits, info)
10702159047fSniklas      unsigned char *buffer;
10712159047fSniklas      int code;
10722159047fSniklas      int bits;
10732159047fSniklas      disassemble_info *info;
10742159047fSniklas {
10752159047fSniklas   register int val = 0;
10762159047fSniklas   switch (code)
10772159047fSniklas     {
10782159047fSniklas     case 's':
10792159047fSniklas       val = buffer[1];
10802159047fSniklas       break;
10812159047fSniklas 
10822159047fSniklas     case 'd':			/* Destination, for register or quick.  */
10832159047fSniklas       val = (buffer[0] << 8) + buffer[1];
10842159047fSniklas       val >>= 9;
10852159047fSniklas       break;
10862159047fSniklas 
10872159047fSniklas     case 'x':			/* Destination, for general arg */
10882159047fSniklas       val = (buffer[0] << 8) + buffer[1];
10892159047fSniklas       val >>= 6;
10902159047fSniklas       break;
10912159047fSniklas 
10922159047fSniklas     case 'k':
10932159047fSniklas       FETCH_DATA (info, buffer + 3);
10942159047fSniklas       val = (buffer[3] >> 4);
10952159047fSniklas       break;
10962159047fSniklas 
10972159047fSniklas     case 'C':
10982159047fSniklas       FETCH_DATA (info, buffer + 3);
10992159047fSniklas       val = buffer[3];
11002159047fSniklas       break;
11012159047fSniklas 
11022159047fSniklas     case '1':
11032159047fSniklas       FETCH_DATA (info, buffer + 3);
11042159047fSniklas       val = (buffer[2] << 8) + buffer[3];
11052159047fSniklas       val >>= 12;
11062159047fSniklas       break;
11072159047fSniklas 
11082159047fSniklas     case '2':
11092159047fSniklas       FETCH_DATA (info, buffer + 3);
11102159047fSniklas       val = (buffer[2] << 8) + buffer[3];
11112159047fSniklas       val >>= 6;
11122159047fSniklas       break;
11132159047fSniklas 
11142159047fSniklas     case '3':
11152159047fSniklas     case 'j':
11162159047fSniklas       FETCH_DATA (info, buffer + 3);
11172159047fSniklas       val = (buffer[2] << 8) + buffer[3];
11182159047fSniklas       break;
11192159047fSniklas 
11202159047fSniklas     case '4':
11212159047fSniklas       FETCH_DATA (info, buffer + 5);
11222159047fSniklas       val = (buffer[4] << 8) + buffer[5];
11232159047fSniklas       val >>= 12;
11242159047fSniklas       break;
11252159047fSniklas 
11262159047fSniklas     case '5':
11272159047fSniklas       FETCH_DATA (info, buffer + 5);
11282159047fSniklas       val = (buffer[4] << 8) + buffer[5];
11292159047fSniklas       val >>= 6;
11302159047fSniklas       break;
11312159047fSniklas 
11322159047fSniklas     case '6':
11332159047fSniklas       FETCH_DATA (info, buffer + 5);
11342159047fSniklas       val = (buffer[4] << 8) + buffer[5];
11352159047fSniklas       break;
11362159047fSniklas 
11372159047fSniklas     case '7':
11382159047fSniklas       FETCH_DATA (info, buffer + 3);
11392159047fSniklas       val = (buffer[2] << 8) + buffer[3];
11402159047fSniklas       val >>= 7;
11412159047fSniklas       break;
11422159047fSniklas 
11432159047fSniklas     case '8':
11442159047fSniklas       FETCH_DATA (info, buffer + 3);
11452159047fSniklas       val = (buffer[2] << 8) + buffer[3];
11462159047fSniklas       val >>= 10;
11472159047fSniklas       break;
11482159047fSniklas 
11492159047fSniklas     case '9':
11502159047fSniklas       FETCH_DATA (info, buffer + 3);
11512159047fSniklas       val = (buffer[2] << 8) + buffer[3];
11522159047fSniklas       val >>= 5;
11532159047fSniklas       break;
11542159047fSniklas 
11552159047fSniklas     case 'e':
11562159047fSniklas       val = (buffer[1] >> 6);
11572159047fSniklas       break;
11582159047fSniklas 
1159f7cc78ecSespie     case 'm':
1160f7cc78ecSespie       val = (buffer[1] & 0x40 ? 0x8 : 0)
1161f7cc78ecSespie 	| ((buffer[0] >> 1) & 0x7)
1162f7cc78ecSespie 	| (buffer[3] & 0x80 ? 0x10 : 0);
1163f7cc78ecSespie       break;
1164f7cc78ecSespie 
1165f7cc78ecSespie     case 'n':
1166f7cc78ecSespie       val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7);
1167f7cc78ecSespie       break;
1168f7cc78ecSespie 
1169f7cc78ecSespie     case 'o':
1170f7cc78ecSespie       val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0);
1171f7cc78ecSespie       break;
1172f7cc78ecSespie 
1173f7cc78ecSespie     case 'M':
1174f7cc78ecSespie       val = buffer[1] | (buffer[3] & 0x40 ? 0x10 : 0);
1175f7cc78ecSespie       break;
1176f7cc78ecSespie 
1177f7cc78ecSespie     case 'N':
1178f7cc78ecSespie       val = buffer[3] | (buffer[3] & 0x40 ? 0x10 : 0);
1179f7cc78ecSespie       break;
1180f7cc78ecSespie 
1181f7cc78ecSespie     case 'h':
1182f7cc78ecSespie       val = buffer[2] >> 2;
1183f7cc78ecSespie       break;
1184f7cc78ecSespie 
11852159047fSniklas     default:
11862159047fSniklas       abort ();
11872159047fSniklas     }
11882159047fSniklas 
11892159047fSniklas   switch (bits)
11902159047fSniklas     {
1191f7cc78ecSespie     case 1:
1192f7cc78ecSespie       return val & 1;
11932159047fSniklas     case 2:
11942159047fSniklas       return val & 3;
11952159047fSniklas     case 3:
11962159047fSniklas       return val & 7;
11972159047fSniklas     case 4:
11982159047fSniklas       return val & 017;
11992159047fSniklas     case 5:
12002159047fSniklas       return val & 037;
12012159047fSniklas     case 6:
12022159047fSniklas       return val & 077;
12032159047fSniklas     case 7:
12042159047fSniklas       return val & 0177;
12052159047fSniklas     case 8:
12062159047fSniklas       return val & 0377;
12072159047fSniklas     case 12:
12082159047fSniklas       return val & 07777;
12092159047fSniklas     default:
12102159047fSniklas       abort ();
12112159047fSniklas     }
12122159047fSniklas }
12132159047fSniklas 
12142159047fSniklas /* Print an indexed argument.  The base register is BASEREG (-1 for pc).
12152159047fSniklas    P points to extension word, in buffer.
12162159047fSniklas    ADDR is the nominal core address of that extension word.  */
12172159047fSniklas 
12182159047fSniklas static unsigned char *
print_indexed(basereg,p,addr,info)12192159047fSniklas print_indexed (basereg, p, addr, info)
12202159047fSniklas      int basereg;
12212159047fSniklas      unsigned char *p;
12222159047fSniklas      bfd_vma addr;
12232159047fSniklas      disassemble_info *info;
12242159047fSniklas {
12252159047fSniklas   register int word;
12262159047fSniklas   static char *const scales[] = { "", ":2", ":4", ":8" };
12272159047fSniklas   bfd_vma base_disp;
12282159047fSniklas   bfd_vma outer_disp;
12292159047fSniklas   char buf[40];
12302159047fSniklas   char vmabuf[50];
12312159047fSniklas 
12322159047fSniklas   word = NEXTWORD (p);
12332159047fSniklas 
12342159047fSniklas   /* Generate the text for the index register.
12352159047fSniklas      Where this will be output is not yet determined.  */
12362159047fSniklas   sprintf (buf, "%s:%c%s",
12372159047fSniklas 	   reg_names[(word >> 12) & 0xf],
12382159047fSniklas 	   (word & 0x800) ? 'l' : 'w',
12392159047fSniklas 	   scales[(word >> 9) & 3]);
12402159047fSniklas 
12412159047fSniklas   /* Handle the 68000 style of indexing.  */
12422159047fSniklas 
12432159047fSniklas   if ((word & 0x100) == 0)
12442159047fSniklas     {
1245f7cc78ecSespie       base_disp = word & 0xff;
1246f7cc78ecSespie       if ((base_disp & 0x80) != 0)
1247f7cc78ecSespie 	base_disp -= 0x100;
12482159047fSniklas       if (basereg == -1)
1249f7cc78ecSespie 	base_disp += addr;
1250f7cc78ecSespie       print_base (basereg, base_disp, info);
12512159047fSniklas       (*info->fprintf_func) (info->stream, ",%s)", buf);
12522159047fSniklas       return p;
12532159047fSniklas     }
12542159047fSniklas 
12552159047fSniklas   /* Handle the generalized kind.  */
12562159047fSniklas   /* First, compute the displacement to add to the base register.  */
12572159047fSniklas 
12582159047fSniklas   if (word & 0200)
12592159047fSniklas     {
12602159047fSniklas       if (basereg == -1)
12612159047fSniklas 	basereg = -3;
12622159047fSniklas       else
12632159047fSniklas 	basereg = -2;
12642159047fSniklas     }
12652159047fSniklas   if (word & 0100)
12662159047fSniklas     buf[0] = '\0';
12672159047fSniklas   base_disp = 0;
12682159047fSniklas   switch ((word >> 4) & 3)
12692159047fSniklas     {
12702159047fSniklas     case 2:
12712159047fSniklas       base_disp = NEXTWORD (p);
12722159047fSniklas       break;
12732159047fSniklas     case 3:
12742159047fSniklas       base_disp = NEXTLONG (p);
12752159047fSniklas     }
12762159047fSniklas   if (basereg == -1)
12772159047fSniklas     base_disp += addr;
12782159047fSniklas 
12792159047fSniklas   /* Handle single-level case (not indirect) */
12802159047fSniklas 
12812159047fSniklas   if ((word & 7) == 0)
12822159047fSniklas     {
12832159047fSniklas       print_base (basereg, base_disp, info);
12842159047fSniklas       if (buf[0] != '\0')
12852159047fSniklas 	(*info->fprintf_func) (info->stream, ",%s", buf);
12862159047fSniklas       (*info->fprintf_func) (info->stream, ")");
12872159047fSniklas       return p;
12882159047fSniklas     }
12892159047fSniklas 
12902159047fSniklas   /* Two level.  Compute displacement to add after indirection.  */
12912159047fSniklas 
12922159047fSniklas   outer_disp = 0;
12932159047fSniklas   switch (word & 3)
12942159047fSniklas     {
12952159047fSniklas     case 2:
12962159047fSniklas       outer_disp = NEXTWORD (p);
12972159047fSniklas       break;
12982159047fSniklas     case 3:
12992159047fSniklas       outer_disp = NEXTLONG (p);
13002159047fSniklas     }
13012159047fSniklas 
13022159047fSniklas   print_base (basereg, base_disp, info);
13032159047fSniklas   if ((word & 4) == 0 && buf[0] != '\0')
13042159047fSniklas     {
13052159047fSniklas       (*info->fprintf_func) (info->stream, ",%s", buf);
13062159047fSniklas       buf[0] = '\0';
13072159047fSniklas     }
13082159047fSniklas   sprintf_vma (vmabuf, outer_disp);
13092159047fSniklas   (*info->fprintf_func) (info->stream, ")@(%s", vmabuf);
13102159047fSniklas   if (buf[0] != '\0')
13112159047fSniklas     (*info->fprintf_func) (info->stream, ",%s", buf);
13122159047fSniklas   (*info->fprintf_func) (info->stream, ")");
13132159047fSniklas 
13142159047fSniklas   return p;
13152159047fSniklas }
13162159047fSniklas 
13172159047fSniklas /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
13182159047fSniklas    REGNO = -1 for pc, -2 for none (suppressed).  */
13192159047fSniklas 
13202159047fSniklas static void
print_base(regno,disp,info)13212159047fSniklas print_base (regno, disp, info)
13222159047fSniklas      int regno;
13232159047fSniklas      bfd_vma disp;
13242159047fSniklas      disassemble_info *info;
13252159047fSniklas {
13262159047fSniklas   if (regno == -1)
13272159047fSniklas     {
13282159047fSniklas       (*info->fprintf_func) (info->stream, "%%pc@(");
13292159047fSniklas       (*info->print_address_func) (disp, info);
13302159047fSniklas     }
13312159047fSniklas   else
13322159047fSniklas     {
13332159047fSniklas       char buf[50];
13342159047fSniklas 
13352159047fSniklas       if (regno == -2)
13362159047fSniklas 	(*info->fprintf_func) (info->stream, "@(");
13372159047fSniklas       else if (regno == -3)
13382159047fSniklas 	(*info->fprintf_func) (info->stream, "%%zpc@(");
13392159047fSniklas       else
13402159047fSniklas 	(*info->fprintf_func) (info->stream, "%s@(", reg_names[regno]);
13412159047fSniklas 
13422159047fSniklas       sprintf_vma (buf, disp);
13432159047fSniklas       (*info->fprintf_func) (info->stream, "%s", buf);
13442159047fSniklas     }
13452159047fSniklas }
1346