Home | History | Annotate | Line # | Download | only in opcodes
      1   1.1  christos /* Print Motorola 68k instructions.
      2  1.11  christos    Copyright (C) 1986-2024 Free Software Foundation, Inc.
      3   1.1  christos 
      4   1.1  christos    This file is part of the GNU opcodes library.
      5   1.1  christos 
      6   1.1  christos    This library is free software; you can redistribute it and/or modify
      7   1.1  christos    it under the terms of the GNU General Public License as published by
      8   1.1  christos    the Free Software Foundation; either version 3, or (at your option)
      9   1.1  christos    any later version.
     10   1.1  christos 
     11   1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     12   1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     13   1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     14   1.1  christos    License for more details.
     15   1.1  christos 
     16   1.1  christos    You should have received a copy of the GNU General Public License
     17   1.1  christos    along with this program; if not, write to the Free Software
     18   1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19   1.1  christos    MA 02110-1301, USA.  */
     20   1.1  christos 
     21   1.1  christos #include "sysdep.h"
     22   1.8  christos #include "disassemble.h"
     23   1.1  christos #include "floatformat.h"
     24   1.1  christos #include "libiberty.h"
     25   1.1  christos #include "opintl.h"
     26   1.9  christos #include "cpu-m68k.h"
     27   1.1  christos #include "opcode/m68k.h"
     28   1.1  christos 
     29   1.1  christos /* Local function prototypes.  */
     30   1.1  christos 
     31   1.1  christos const char * const fpcr_names[] =
     32   1.1  christos {
     33   1.1  christos   "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
     34   1.1  christos   "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"
     35   1.1  christos };
     36   1.1  christos 
     37   1.1  christos static char *const reg_names[] =
     38   1.1  christos {
     39   1.1  christos   "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
     40   1.1  christos   "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
     41   1.1  christos   "%ps", "%pc"
     42   1.1  christos };
     43   1.1  christos 
     44   1.1  christos /* Name of register halves for MAC/EMAC.
     45   1.1  christos    Seperate from reg_names since 'spu', 'fpl' look weird.  */
     46   1.1  christos static char *const reg_half_names[] =
     47   1.1  christos {
     48   1.1  christos   "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
     49   1.1  christos   "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
     50   1.1  christos   "%ps", "%pc"
     51   1.1  christos };
     52   1.1  christos 
     53   1.1  christos /* Sign-extend an (unsigned char).  */
     54   1.1  christos #if __STDC__ == 1
     55   1.1  christos #define COERCE_SIGNED_CHAR(ch) ((signed char) (ch))
     56   1.1  christos #else
     57   1.1  christos #define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
     58   1.1  christos #endif
     59   1.1  christos 
     60   1.7  christos /* Error code of print_insn_arg's return value.  */
     61   1.7  christos 
     62   1.7  christos enum print_insn_arg_error
     63   1.7  christos   {
     64   1.7  christos     /* An invalid operand is found.  */
     65   1.7  christos     PRINT_INSN_ARG_INVALID_OPERAND = -1,
     66   1.7  christos 
     67   1.7  christos     /* An opcode table error.  */
     68   1.7  christos     PRINT_INSN_ARG_INVALID_OP_TABLE = -2,
     69   1.7  christos 
     70   1.7  christos     /* A memory error.  */
     71   1.7  christos     PRINT_INSN_ARG_MEMORY_ERROR = -3,
     72   1.7  christos   };
     73   1.7  christos 
     74   1.1  christos /* Get a 1 byte signed integer.  */
     75   1.1  christos #define NEXTBYTE(p, val)			\
     76   1.1  christos   do						\
     77   1.1  christos     {						\
     78   1.1  christos       p += 2;					\
     79   1.1  christos       if (!FETCH_DATA (info, p))		\
     80   1.7  christos 	return PRINT_INSN_ARG_MEMORY_ERROR;	\
     81   1.1  christos       val = COERCE_SIGNED_CHAR (p[-1]);		\
     82   1.1  christos     }						\
     83   1.1  christos   while (0)
     84   1.1  christos 
     85   1.1  christos /* Get a 2 byte signed integer.  */
     86   1.1  christos #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
     87   1.1  christos 
     88   1.1  christos #define NEXTWORD(p, val, ret_val)		\
     89   1.1  christos   do						\
     90   1.1  christos     {						\
     91   1.1  christos       p += 2;					\
     92   1.1  christos       if (!FETCH_DATA (info, p))		\
     93   1.1  christos 	return ret_val;				\
     94   1.1  christos       val = COERCE16 ((p[-2] << 8) + p[-1]);	\
     95   1.1  christos     }						\
     96   1.6  christos   while (0)
     97   1.1  christos 
     98   1.1  christos /* Get a 4 byte signed integer.  */
     99   1.9  christos #define COERCE32(x) (((bfd_vma) (x) ^ 0x80000000) - 0x80000000)
    100   1.1  christos 
    101   1.1  christos #define NEXTLONG(p, val, ret_val)					\
    102   1.1  christos   do									\
    103   1.1  christos     {									\
    104   1.1  christos       p += 4;								\
    105   1.1  christos       if (!FETCH_DATA (info, p))					\
    106   1.1  christos 	return ret_val;							\
    107   1.9  christos       val = COERCE32 (((((((unsigned) p[-4] << 8) + p[-3]) << 8)	\
    108   1.9  christos 			+ p[-2]) << 8) + p[-1]);			\
    109   1.1  christos     }									\
    110   1.1  christos   while (0)
    111   1.1  christos 
    112   1.1  christos /* Get a 4 byte unsigned integer.  */
    113   1.1  christos #define NEXTULONG(p, val)						\
    114   1.1  christos   do									\
    115   1.1  christos     {									\
    116   1.1  christos       p += 4;								\
    117   1.1  christos       if (!FETCH_DATA (info, p))					\
    118   1.7  christos 	return PRINT_INSN_ARG_MEMORY_ERROR;				\
    119   1.9  christos       val = (((((((unsigned) p[-4] << 8) + p[-3]) << 8)			\
    120   1.9  christos 	       + p[-2]) << 8) + p[-1]);					\
    121   1.1  christos     }									\
    122   1.1  christos   while (0)
    123   1.1  christos 
    124   1.1  christos /* Get a single precision float.  */
    125   1.1  christos #define NEXTSINGLE(val, p)					\
    126   1.1  christos   do								\
    127   1.1  christos     {								\
    128   1.1  christos       p += 4;							\
    129   1.1  christos       if (!FETCH_DATA (info, p))				\
    130   1.7  christos 	return PRINT_INSN_ARG_MEMORY_ERROR;			\
    131   1.1  christos       floatformat_to_double (& floatformat_ieee_single_big,	\
    132   1.1  christos 			     (char *) p - 4, & val);		\
    133   1.1  christos     }								\
    134   1.1  christos   while (0)
    135   1.1  christos 
    136   1.1  christos /* Get a double precision float.  */
    137   1.1  christos #define NEXTDOUBLE(val, p)					\
    138   1.1  christos   do								\
    139   1.1  christos     {								\
    140   1.1  christos       p += 8;							\
    141   1.1  christos       if (!FETCH_DATA (info, p))				\
    142   1.7  christos 	return PRINT_INSN_ARG_MEMORY_ERROR;			\
    143   1.1  christos       floatformat_to_double (& floatformat_ieee_double_big,	\
    144   1.1  christos 			     (char *) p - 8, & val);		\
    145   1.1  christos     }								\
    146   1.1  christos   while (0)
    147   1.1  christos 
    148   1.1  christos /* Get an extended precision float.  */
    149   1.1  christos #define NEXTEXTEND(val, p)				\
    150   1.1  christos   do							\
    151   1.1  christos     {							\
    152   1.1  christos       p += 12;						\
    153   1.1  christos       if (!FETCH_DATA (info, p))			\
    154   1.7  christos 	return PRINT_INSN_ARG_MEMORY_ERROR;		\
    155   1.1  christos       floatformat_to_double (& floatformat_m68881_ext,	\
    156   1.1  christos 			     (char *) p - 12, & val);	\
    157   1.1  christos     }							\
    158   1.1  christos   while (0)
    159   1.1  christos 
    160   1.1  christos /* Need a function to convert from packed to double
    161   1.1  christos    precision.   Actually, it's easier to print a
    162   1.1  christos    packed number than a double anyway, so maybe
    163   1.1  christos    there should be a special case to handle this... */
    164   1.1  christos #define NEXTPACKED(p, val)			\
    165   1.1  christos   do						\
    166   1.1  christos     {						\
    167   1.1  christos       p += 12;					\
    168   1.1  christos       if (!FETCH_DATA (info, p))		\
    169   1.7  christos 	return PRINT_INSN_ARG_MEMORY_ERROR;	\
    170   1.1  christos       val = 0.0;				\
    171   1.1  christos     }						\
    172   1.1  christos   while (0)
    173   1.1  christos 
    174   1.1  christos 
    175   1.1  christos /* Maximum length of an instruction.  */
    177   1.1  christos #define MAXLEN 22
    178   1.1  christos 
    179   1.1  christos struct private
    180   1.1  christos {
    181   1.1  christos   /* Points to first byte not fetched.  */
    182   1.1  christos   bfd_byte *max_fetched;
    183   1.1  christos   bfd_byte the_buffer[MAXLEN];
    184   1.1  christos   bfd_vma insn_start;
    185   1.1  christos };
    186   1.1  christos 
    187   1.7  christos /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
    188   1.7  christos    to ADDR (exclusive) are valid.  Returns 1 for success, 0 on memory
    189   1.1  christos    error.  */
    190   1.1  christos #define FETCH_DATA(info, addr) \
    191   1.1  christos   ((addr) <= ((struct private *) (info->private_data))->max_fetched \
    192   1.1  christos    ? 1 : fetch_data ((info), (addr)))
    193   1.1  christos 
    194   1.1  christos static int
    195   1.1  christos fetch_data (struct disassemble_info *info, bfd_byte *addr)
    196   1.1  christos {
    197   1.1  christos   int status;
    198   1.1  christos   struct private *priv = (struct private *)info->private_data;
    199   1.1  christos   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
    200   1.1  christos 
    201   1.1  christos   status = (*info->read_memory_func) (start,
    202   1.1  christos 				      priv->max_fetched,
    203   1.1  christos 				      addr - priv->max_fetched,
    204   1.1  christos 				      info);
    205   1.1  christos   if (status != 0)
    206   1.1  christos     {
    207   1.1  christos       (*info->memory_error_func) (status, start, info);
    208   1.1  christos       return 0;
    209   1.1  christos     }
    210   1.1  christos   else
    211   1.1  christos     priv->max_fetched = addr;
    212   1.1  christos   return 1;
    213   1.1  christos }
    214   1.1  christos 
    215   1.1  christos /* This function is used to print to the bit-bucket.  */
    217  1.11  christos static int
    218   1.1  christos dummy_printer (void *file ATTRIBUTE_UNUSED,
    219   1.1  christos 	       enum disassembler_style style ATTRIBUTE_UNUSED,
    220   1.1  christos 	       const char *format ATTRIBUTE_UNUSED,
    221   1.1  christos 	       ...)
    222   1.1  christos {
    223   1.1  christos   return 0;
    224   1.1  christos }
    225   1.1  christos 
    226   1.1  christos static void
    227   1.1  christos dummy_print_address (bfd_vma vma ATTRIBUTE_UNUSED,
    228   1.1  christos 		     struct disassemble_info *info ATTRIBUTE_UNUSED)
    229   1.1  christos {
    230   1.1  christos }
    231   1.1  christos 
    232   1.1  christos /* Fetch BITS bits from a position in the instruction specified by CODE.
    233   1.1  christos    CODE is a "place to put an argument", or 'x' for a destination
    234   1.1  christos    that is a general address (mode and register).
    235   1.1  christos    BUFFER contains the instruction.
    236   1.1  christos    Returns -1 on failure.  */
    237   1.1  christos 
    238   1.1  christos static int
    239   1.1  christos fetch_arg (unsigned char *buffer,
    240   1.1  christos 	   int code,
    241   1.1  christos 	   int bits,
    242   1.1  christos 	   disassemble_info *info)
    243   1.1  christos {
    244   1.1  christos   int val = 0;
    245   1.1  christos 
    246   1.1  christos   switch (code)
    247   1.1  christos     {
    248   1.1  christos     case '/': /* MAC/EMAC mask bit.  */
    249   1.1  christos       val = buffer[3] >> 5;
    250   1.1  christos       break;
    251   1.1  christos 
    252   1.1  christos     case 'G': /* EMAC ACC load.  */
    253   1.1  christos       val = ((buffer[3] >> 3) & 0x2) | ((~buffer[1] >> 7) & 0x1);
    254   1.1  christos       break;
    255   1.1  christos 
    256   1.1  christos     case 'H': /* EMAC ACC !load.  */
    257   1.1  christos       val = ((buffer[3] >> 3) & 0x2) | ((buffer[1] >> 7) & 0x1);
    258   1.1  christos       break;
    259   1.1  christos 
    260   1.1  christos     case ']': /* EMAC ACCEXT bit.  */
    261   1.1  christos       val = buffer[0] >> 2;
    262   1.1  christos       break;
    263   1.1  christos 
    264   1.1  christos     case 'I': /* MAC/EMAC scale factor.  */
    265   1.1  christos       val = buffer[2] >> 1;
    266   1.1  christos       break;
    267   1.1  christos 
    268   1.1  christos     case 'F': /* EMAC ACCx.  */
    269   1.1  christos       val = buffer[0] >> 1;
    270   1.1  christos       break;
    271   1.1  christos 
    272   1.1  christos     case 'f':
    273   1.1  christos       val = buffer[1];
    274   1.1  christos       break;
    275   1.1  christos 
    276   1.1  christos     case 's':
    277   1.1  christos       val = buffer[1];
    278   1.1  christos       break;
    279   1.1  christos 
    280   1.1  christos     case 'd':			/* Destination, for register or quick.  */
    281   1.1  christos       val = (buffer[0] << 8) + buffer[1];
    282   1.1  christos       val >>= 9;
    283   1.1  christos       break;
    284   1.1  christos 
    285   1.1  christos     case 'x':			/* Destination, for general arg.  */
    286   1.1  christos       val = (buffer[0] << 8) + buffer[1];
    287   1.1  christos       val >>= 6;
    288   1.1  christos       break;
    289   1.1  christos 
    290   1.1  christos     case 'k':
    291   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    292   1.1  christos 	return -1;
    293   1.1  christos       val = (buffer[3] >> 4);
    294   1.1  christos       break;
    295   1.1  christos 
    296   1.1  christos     case 'C':
    297   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    298   1.1  christos 	return -1;
    299   1.1  christos       val = buffer[3];
    300   1.1  christos       break;
    301   1.1  christos 
    302   1.1  christos     case '1':
    303   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    304   1.1  christos 	return -1;
    305   1.1  christos       val = (buffer[2] << 8) + buffer[3];
    306   1.1  christos       val >>= 12;
    307   1.1  christos       break;
    308   1.1  christos 
    309   1.1  christos     case '2':
    310   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    311   1.1  christos 	return -1;
    312   1.1  christos       val = (buffer[2] << 8) + buffer[3];
    313   1.1  christos       val >>= 6;
    314   1.1  christos       break;
    315   1.1  christos 
    316   1.1  christos     case '3':
    317   1.1  christos     case 'j':
    318   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    319   1.1  christos 	return -1;
    320   1.1  christos       val = (buffer[2] << 8) + buffer[3];
    321   1.1  christos       break;
    322   1.1  christos 
    323   1.1  christos     case '4':
    324   1.1  christos       if (! FETCH_DATA (info, buffer + 5))
    325   1.1  christos 	return -1;
    326   1.1  christos       val = (buffer[4] << 8) + buffer[5];
    327   1.1  christos       val >>= 12;
    328   1.1  christos       break;
    329   1.1  christos 
    330   1.1  christos     case '5':
    331   1.1  christos       if (! FETCH_DATA (info, buffer + 5))
    332   1.1  christos 	return -1;
    333   1.1  christos       val = (buffer[4] << 8) + buffer[5];
    334   1.1  christos       val >>= 6;
    335   1.1  christos       break;
    336   1.1  christos 
    337   1.1  christos     case '6':
    338   1.1  christos       if (! FETCH_DATA (info, buffer + 5))
    339   1.1  christos 	return -1;
    340   1.1  christos       val = (buffer[4] << 8) + buffer[5];
    341   1.1  christos       break;
    342   1.1  christos 
    343   1.1  christos     case '7':
    344   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    345   1.1  christos 	return -1;
    346   1.1  christos       val = (buffer[2] << 8) + buffer[3];
    347   1.1  christos       val >>= 7;
    348   1.1  christos       break;
    349   1.1  christos 
    350   1.1  christos     case '8':
    351   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    352   1.1  christos 	return -1;
    353   1.1  christos       val = (buffer[2] << 8) + buffer[3];
    354   1.1  christos       val >>= 10;
    355   1.1  christos       break;
    356   1.1  christos 
    357   1.1  christos     case '9':
    358   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    359   1.1  christos 	return -1;
    360   1.1  christos       val = (buffer[2] << 8) + buffer[3];
    361   1.1  christos       val >>= 5;
    362   1.1  christos       break;
    363   1.1  christos 
    364   1.1  christos     case 'e':
    365   1.1  christos       val = (buffer[1] >> 6);
    366   1.1  christos       break;
    367   1.1  christos 
    368   1.1  christos     case 'E':
    369   1.1  christos       if (! FETCH_DATA (info, buffer + 3))
    370   1.1  christos 	return -1;
    371   1.1  christos       val = (buffer[2] >> 1);
    372   1.1  christos       break;
    373   1.1  christos 
    374   1.1  christos     case 'm':
    375   1.1  christos       val = (buffer[1] & 0x40 ? 0x8 : 0)
    376   1.1  christos 	| ((buffer[0] >> 1) & 0x7)
    377   1.1  christos 	| (buffer[3] & 0x80 ? 0x10 : 0);
    378   1.1  christos       break;
    379   1.1  christos 
    380   1.1  christos     case 'n':
    381   1.1  christos       val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7);
    382   1.1  christos       break;
    383   1.1  christos 
    384   1.1  christos     case 'o':
    385   1.1  christos       val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0);
    386   1.1  christos       break;
    387   1.1  christos 
    388   1.1  christos     case 'M':
    389   1.1  christos       val = (buffer[1] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
    390   1.1  christos       break;
    391   1.1  christos 
    392   1.1  christos     case 'N':
    393   1.1  christos       val = (buffer[3] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
    394   1.1  christos       break;
    395   1.1  christos 
    396   1.1  christos     case 'h':
    397   1.1  christos       val = buffer[2] >> 2;
    398   1.1  christos       break;
    399   1.1  christos 
    400   1.1  christos     default:
    401   1.1  christos       abort ();
    402   1.1  christos     }
    403   1.1  christos 
    404   1.1  christos   /* bits is never too big.  */
    405   1.1  christos   return val & ((1 << bits) - 1);
    406   1.1  christos }
    407   1.1  christos 
    408   1.1  christos /* Check if an EA is valid for a particular code.  This is required
    409   1.1  christos    for the EMAC instructions since the type of source address determines
    410   1.1  christos    if it is a EMAC-load instruciton if the EA is mode 2-5, otherwise it
    411   1.1  christos    is a non-load EMAC instruction and the bits mean register Ry.
    412   1.1  christos    A similar case exists for the movem instructions where the register
    413  1.10  christos    mask is interpreted differently for different EAs.  */
    414   1.1  christos 
    415   1.1  christos static bool
    416   1.1  christos m68k_valid_ea (char code, int val)
    417   1.1  christos {
    418   1.1  christos   int mode, mask;
    419   1.1  christos #define M(n0,n1,n2,n3,n4,n5,n6,n70,n71,n72,n73,n74) \
    420   1.1  christos   (n0 | n1 << 1 | n2 << 2 | n3 << 3 | n4 << 4 | n5 << 5 | n6 << 6 \
    421   1.1  christos    | n70 << 7 | n71 << 8 | n72 << 9 | n73 << 10 | n74 << 11)
    422   1.1  christos 
    423   1.1  christos   switch (code)
    424   1.1  christos     {
    425   1.1  christos     case '*':
    426   1.1  christos       mask = M (1,1,1,1,1,1,1,1,1,1,1,1);
    427   1.1  christos       break;
    428   1.1  christos     case '~':
    429   1.1  christos       mask = M (0,0,1,1,1,1,1,1,1,0,0,0);
    430   1.1  christos       break;
    431   1.1  christos     case '%':
    432   1.1  christos       mask = M (1,1,1,1,1,1,1,1,1,0,0,0);
    433   1.1  christos       break;
    434   1.1  christos     case ';':
    435   1.1  christos       mask = M (1,0,1,1,1,1,1,1,1,1,1,1);
    436   1.1  christos       break;
    437   1.1  christos     case '@':
    438   1.1  christos       mask = M (1,0,1,1,1,1,1,1,1,1,1,0);
    439   1.1  christos       break;
    440   1.1  christos     case '!':
    441   1.1  christos       mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
    442   1.1  christos       break;
    443   1.1  christos     case '&':
    444   1.1  christos       mask = M (0,0,1,0,0,1,1,1,1,0,0,0);
    445   1.1  christos       break;
    446   1.1  christos     case '$':
    447   1.1  christos       mask = M (1,0,1,1,1,1,1,1,1,0,0,0);
    448   1.1  christos       break;
    449   1.1  christos     case '?':
    450   1.1  christos       mask = M (1,0,1,0,0,1,1,1,1,0,0,0);
    451   1.1  christos       break;
    452   1.1  christos     case '/':
    453   1.1  christos       mask = M (1,0,1,0,0,1,1,1,1,1,1,0);
    454   1.1  christos       break;
    455   1.1  christos     case '|':
    456   1.1  christos       mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
    457   1.1  christos       break;
    458   1.1  christos     case '>':
    459   1.1  christos       mask = M (0,0,1,0,1,1,1,1,1,0,0,0);
    460   1.1  christos       break;
    461   1.1  christos     case '<':
    462   1.1  christos       mask = M (0,0,1,1,0,1,1,1,1,1,1,0);
    463   1.1  christos       break;
    464   1.1  christos     case 'm':
    465   1.1  christos       mask = M (1,1,1,1,1,0,0,0,0,0,0,0);
    466   1.1  christos       break;
    467   1.1  christos     case 'n':
    468   1.1  christos       mask = M (0,0,0,0,0,1,0,0,0,1,0,0);
    469   1.1  christos       break;
    470   1.1  christos     case 'o':
    471   1.1  christos       mask = M (0,0,0,0,0,0,1,1,1,0,1,1);
    472   1.1  christos       break;
    473   1.1  christos     case 'p':
    474   1.1  christos       mask = M (1,1,1,1,1,1,0,0,0,0,0,0);
    475   1.1  christos       break;
    476   1.1  christos     case 'q':
    477   1.1  christos       mask = M (1,0,1,1,1,1,0,0,0,0,0,0);
    478   1.1  christos       break;
    479   1.1  christos     case 'v':
    480   1.1  christos       mask = M (1,0,1,1,1,1,0,1,1,0,0,0);
    481   1.1  christos       break;
    482   1.1  christos     case 'b':
    483   1.1  christos       mask = M (1,0,1,1,1,1,0,0,0,1,0,0);
    484   1.1  christos       break;
    485   1.1  christos     case 'w':
    486   1.1  christos       mask = M (0,0,1,1,1,1,0,0,0,1,0,0);
    487   1.1  christos       break;
    488   1.1  christos     case 'y':
    489   1.1  christos       mask = M (0,0,1,0,0,1,0,0,0,0,0,0);
    490   1.1  christos       break;
    491   1.1  christos     case 'z':
    492   1.1  christos       mask = M (0,0,1,0,0,1,0,0,0,1,0,0);
    493   1.1  christos       break;
    494   1.1  christos     case '4':
    495   1.1  christos       mask = M (0,0,1,1,1,1,0,0,0,0,0,0);
    496   1.1  christos       break;
    497   1.1  christos     default:
    498   1.1  christos       abort ();
    499   1.1  christos     }
    500   1.1  christos #undef M
    501   1.1  christos 
    502   1.1  christos   mode = (val >> 3) & 7;
    503   1.1  christos   if (mode == 7)
    504   1.1  christos     mode += val & 7;
    505   1.1  christos   return (mask & (1 << mode)) != 0;
    506   1.1  christos }
    507   1.1  christos 
    508   1.1  christos /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
    509   1.1  christos    REGNO = -1 for pc, -2 for none (suppressed).  */
    510   1.1  christos 
    511   1.1  christos static void
    512   1.1  christos print_base (int regno, bfd_vma disp, disassemble_info *info)
    513   1.1  christos {
    514  1.11  christos   if (regno == -1)
    515  1.11  christos     {
    516   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%pc");
    517   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
    518   1.1  christos       (*info->print_address_func) (disp, info);
    519   1.1  christos     }
    520  1.11  christos   else
    521  1.11  christos     {
    522  1.11  christos       if (regno == -3)
    523  1.11  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_register,
    524  1.11  christos 				      "%%zpc");
    525  1.11  christos       else if (regno != -2)
    526  1.11  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_register,
    527  1.11  christos 				      "%s", reg_names[regno]);
    528  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
    529  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    530  1.11  christos 				    "%" PRIx64, (uint64_t) disp);
    531  1.11  christos     }
    532  1.11  christos }
    533  1.11  christos 
    534  1.11  christos /* Print the index register of an indexed argument, as encoded in the
    535  1.11  christos    extension word.  */
    536  1.11  christos 
    537  1.11  christos static void
    538  1.11  christos print_index_register (int ext, disassemble_info *info)
    539  1.11  christos {
    540  1.11  christos   (*info->fprintf_styled_func) (info->stream, dis_style_register,
    541  1.11  christos 				"%s", reg_names[(ext >> 12) & 0xf]);
    542  1.11  christos   (*info->fprintf_styled_func) (info->stream, dis_style_text,
    543  1.11  christos 				":%c", ext & 0x800 ? 'l' : 'w');
    544  1.11  christos   if ((ext >> 9) & 3)
    545  1.11  christos     {
    546  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, ":");
    547   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    548   1.1  christos 				    "%d", 1 << ((ext >> 9) & 3));
    549   1.1  christos     }
    550   1.1  christos }
    551   1.1  christos 
    552   1.1  christos /* Print an indexed argument.  The base register is BASEREG (-1 for pc).
    553   1.1  christos    P points to extension word, in buffer.
    554   1.1  christos    ADDR is the nominal core address of that extension word.
    555   1.1  christos    Returns NULL upon error.  */
    556   1.1  christos 
    557   1.1  christos static unsigned char *
    558   1.1  christos print_indexed (int basereg,
    559   1.1  christos 	       unsigned char *p,
    560   1.1  christos 	       bfd_vma addr,
    561   1.1  christos 	       disassemble_info *info)
    562   1.1  christos {
    563   1.1  christos   int word;
    564  1.11  christos   bfd_vma base_disp;
    565   1.1  christos   bfd_vma outer_disp;
    566   1.1  christos   bool print_index = true;
    567   1.1  christos 
    568   1.1  christos   NEXTWORD (p, word, NULL);
    569   1.1  christos 
    570   1.1  christos   /* Handle the 68000 style of indexing.  */
    571   1.1  christos 
    572   1.1  christos   if ((word & 0x100) == 0)
    573   1.1  christos     {
    574   1.1  christos       base_disp = word & 0xff;
    575   1.1  christos       if ((base_disp & 0x80) != 0)
    576   1.1  christos 	base_disp -= 0x100;
    577   1.1  christos       if (basereg == -1)
    578  1.11  christos 	base_disp += addr;
    579  1.11  christos       print_base (basereg, base_disp, info);
    580  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
    581   1.1  christos       print_index_register (word, info);
    582   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
    583   1.1  christos       return p;
    584   1.1  christos     }
    585   1.1  christos 
    586   1.1  christos   /* Handle the generalized kind.  */
    587   1.1  christos   /* First, compute the displacement to add to the base register.  */
    588   1.1  christos   if (word & 0200)
    589   1.1  christos     {
    590   1.1  christos       if (basereg == -1)
    591   1.1  christos 	basereg = -3;
    592   1.1  christos       else
    593   1.1  christos 	basereg = -2;
    594  1.11  christos     }
    595   1.1  christos   if (word & 0100)
    596   1.1  christos     print_index = false;
    597   1.1  christos   base_disp = 0;
    598   1.1  christos   switch ((word >> 4) & 3)
    599   1.1  christos     {
    600   1.1  christos     case 2:
    601   1.1  christos       NEXTWORD (p, base_disp, NULL);
    602   1.1  christos       break;
    603   1.1  christos     case 3:
    604   1.1  christos       NEXTLONG (p, base_disp, NULL);
    605   1.1  christos     }
    606   1.1  christos   if (basereg == -1)
    607   1.1  christos     base_disp += addr;
    608   1.1  christos 
    609   1.1  christos   /* Handle single-level case (not indirect).  */
    610   1.1  christos   if ((word & 7) == 0)
    611  1.11  christos     {
    612  1.11  christos       print_base (basereg, base_disp, info);
    613  1.11  christos       if (print_index)
    614  1.11  christos 	{
    615  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
    616  1.11  christos 	  print_index_register (word, info);
    617   1.1  christos 	}
    618   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
    619   1.1  christos       return p;
    620   1.1  christos     }
    621   1.1  christos 
    622   1.1  christos   /* Two level.  Compute displacement to add after indirection.  */
    623   1.1  christos   outer_disp = 0;
    624   1.1  christos   switch (word & 3)
    625   1.1  christos     {
    626   1.1  christos     case 2:
    627   1.1  christos       NEXTWORD (p, outer_disp, NULL);
    628   1.1  christos       break;
    629   1.1  christos     case 3:
    630   1.1  christos       NEXTLONG (p, outer_disp, NULL);
    631   1.1  christos     }
    632  1.11  christos 
    633   1.1  christos   print_base (basereg, base_disp, info);
    634  1.11  christos   if ((word & 4) == 0 && print_index)
    635  1.11  christos     {
    636  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
    637   1.1  christos       print_index_register (word, info);
    638  1.11  christos       print_index = false;
    639  1.11  christos     }
    640  1.11  christos   (*info->fprintf_styled_func) (info->stream, dis_style_text,
    641  1.11  christos 				")@(");
    642  1.11  christos   (*info->fprintf_styled_func) (info->stream, dis_style_address_offset,
    643  1.11  christos 				"%" PRIx64, (uint64_t) outer_disp);
    644  1.11  christos   if (print_index)
    645  1.11  christos     {
    646  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
    647  1.11  christos       print_index_register (word, info);
    648   1.1  christos     }
    649   1.1  christos   (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
    650   1.1  christos 
    651   1.1  christos   return p;
    652   1.1  christos }
    653   1.1  christos 
    654   1.1  christos #define FETCH_ARG(size, val)				\
    655   1.1  christos   do							\
    656   1.1  christos     {							\
    657   1.7  christos       val = fetch_arg (buffer, place, size, info);	\
    658   1.1  christos       if (val < 0)					\
    659   1.1  christos 	return PRINT_INSN_ARG_MEMORY_ERROR;		\
    660   1.1  christos     }							\
    661   1.1  christos   while (0)
    662   1.7  christos 
    663   1.7  christos /* Returns number of bytes "eaten" by the operand, or
    664   1.1  christos    return enum print_insn_arg_error.  ADDR is the pc for this arg to be
    665   1.1  christos    relative to.  */
    666   1.1  christos 
    667   1.1  christos static int
    668   1.1  christos print_insn_arg (const char *d,
    669   1.1  christos 		unsigned char *buffer,
    670   1.1  christos 		unsigned char *p0,
    671   1.1  christos 		bfd_vma addr,
    672   1.1  christos 		disassemble_info *info)
    673   1.1  christos {
    674   1.1  christos   int val = 0;
    675   1.1  christos   int place = d[1];
    676   1.1  christos   unsigned char *p = p0;
    677   1.1  christos   int regno;
    678   1.1  christos   const char *regname;
    679   1.1  christos   unsigned char *p1;
    680   1.1  christos   double flval;
    681   1.1  christos   int flt_p;
    682   1.1  christos   bfd_signed_vma disp;
    683   1.1  christos   unsigned int uval;
    684   1.1  christos 
    685   1.1  christos   switch (*d)
    686   1.1  christos     {
    687   1.1  christos     case 'c':		/* Cache identifier.  */
    688   1.1  christos       {
    689  1.11  christos         static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
    690  1.11  christos         FETCH_ARG (2, val);
    691   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic,
    692   1.1  christos 				      "%s", cacheFieldName[val]);
    693   1.1  christos         break;
    694   1.1  christos       }
    695   1.1  christos 
    696   1.1  christos     case 'a':		/* Address register indirect only. Cf. case '+'.  */
    697  1.11  christos       {
    698  1.11  christos 	FETCH_ARG (3, val);
    699  1.11  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_register, "%s",
    700   1.1  christos 				      reg_names[val + 8]);
    701   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
    702   1.1  christos         break;
    703   1.1  christos       }
    704   1.1  christos 
    705   1.1  christos     case '_':		/* 32-bit absolute address for move16.  */
    706   1.1  christos       {
    707   1.1  christos         NEXTULONG (p, uval);
    708   1.1  christos 	(*info->print_address_func) (uval, info);
    709   1.1  christos         break;
    710   1.1  christos       }
    711  1.11  christos 
    712   1.1  christos     case 'C':
    713   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%ccr");
    714   1.1  christos       break;
    715  1.11  christos 
    716   1.1  christos     case 'S':
    717   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%sr");
    718   1.1  christos       break;
    719  1.11  christos 
    720   1.1  christos     case 'U':
    721   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%usp");
    722   1.1  christos       break;
    723  1.11  christos 
    724   1.1  christos     case 'E':
    725   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%acc");
    726   1.1  christos       break;
    727  1.11  christos 
    728   1.1  christos     case 'G':
    729   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%macsr");
    730   1.1  christos       break;
    731  1.11  christos 
    732   1.1  christos     case 'H':
    733   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%mask");
    734   1.1  christos       break;
    735   1.1  christos 
    736   1.1  christos     case 'J':
    737   1.1  christos       {
    738   1.1  christos 	/* FIXME: There's a problem here, different m68k processors call the
    739   1.1  christos 	   same address different names.  The tables below try to get it right
    740   1.1  christos 	   using info->mach, but only for v4e.  */
    741   1.1  christos 	struct regname { char * name; int value; };
    742   1.1  christos 	static const struct regname names[] =
    743   1.1  christos 	  {
    744   1.1  christos 	    {"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
    745   1.1  christos 	    {"%tc",  0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
    746   1.1  christos 	    {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
    747   1.1  christos 	    {"%rgpiobar", 0x009}, {"%acr4",0x00c},
    748   1.1  christos 	    {"%acr5",0x00d}, {"%acr6",0x00e}, {"%acr7", 0x00f},
    749   1.1  christos 	    {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
    750   1.1  christos 	    {"%msp", 0x803}, {"%isp", 0x804},
    751   1.1  christos 	    {"%pc", 0x80f},
    752   1.1  christos 	    /* Reg c04 is sometimes called flashbar or rambar.
    753   1.1  christos 	       Reg c05 is also sometimes called rambar.  */
    754   1.1  christos 	    {"%rambar0", 0xc04}, {"%rambar1", 0xc05},
    755   1.1  christos 
    756   1.1  christos 	    /* reg c0e is sometimes called mbar2 or secmbar.
    757   1.1  christos 	       reg c0f is sometimes called mbar.  */
    758   1.1  christos 	    {"%mbar0", 0xc0e}, {"%mbar1", 0xc0f},
    759   1.1  christos 
    760   1.1  christos 	    /* Should we be calling this psr like we do in case 'Y'?  */
    761   1.1  christos 	    {"%mmusr",0x805},
    762   1.1  christos 
    763   1.1  christos 	    {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808},
    764   1.1  christos 
    765   1.1  christos 	    /* Fido added these.  */
    766   1.1  christos 	    {"%cac", 0xffe}, {"%mbo", 0xfff}
    767   1.1  christos 	};
    768   1.1  christos 	/* Alternate names for v4e (MCF5407/5445x/MCF547x/MCF548x), at least.  */
    769   1.1  christos 	static const struct regname names_v4e[] =
    770   1.1  christos 	  {
    771   1.1  christos 	    {"%asid",0x003}, {"%acr0",0x004}, {"%acr1",0x005},
    772   1.1  christos 	    {"%acr2",0x006}, {"%acr3",0x007}, {"%mmubar",0x008},
    773   1.1  christos 	  };
    774   1.1  christos 	unsigned int arch_mask;
    775   1.1  christos 
    776   1.1  christos 	arch_mask = bfd_m68k_mach_to_features (info->mach);
    777   1.1  christos 	FETCH_ARG (12, val);
    778   1.1  christos 	if (arch_mask & (mcfisa_b | mcfisa_c))
    779   1.1  christos 	  {
    780   1.1  christos 	    for (regno = ARRAY_SIZE (names_v4e); --regno >= 0;)
    781  1.11  christos 	      if (names_v4e[regno].value == val)
    782  1.11  christos 		{
    783   1.1  christos 		  (*info->fprintf_styled_func) (info->stream, dis_style_register,
    784   1.1  christos 						     "%s", names_v4e[regno].name);
    785   1.1  christos 		  break;
    786   1.1  christos 		}
    787   1.1  christos 	    if (regno >= 0)
    788   1.1  christos 	      break;
    789   1.1  christos 	  }
    790   1.1  christos 	for (regno = ARRAY_SIZE (names) - 1; regno >= 0; regno--)
    791  1.11  christos 	  if (names[regno].value == val)
    792  1.11  christos 	    {
    793   1.1  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_register,
    794   1.1  christos 					    "%s", names[regno].name);
    795   1.1  christos 	      break;
    796  1.11  christos 	    }
    797   1.1  christos 	if (regno < 0)
    798   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "0x%x", val);
    799   1.1  christos       }
    800   1.1  christos       break;
    801   1.1  christos 
    802   1.1  christos     case 'Q':
    803   1.1  christos       FETCH_ARG (3, val);
    804   1.1  christos       /* 0 means 8, except for the bkpt instruction... */
    805  1.11  christos       if (val == 0 && d[1] != 's')
    806  1.11  christos 	val = 8;
    807   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    808   1.1  christos 				    "#%d", val);
    809   1.1  christos       break;
    810   1.1  christos 
    811   1.1  christos     case 'x':
    812   1.1  christos       FETCH_ARG (3, val);
    813   1.1  christos       /* 0 means -1.  */
    814  1.11  christos       if (val == 0)
    815  1.11  christos 	val = -1;
    816   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    817   1.1  christos 				    "#%d", val);
    818   1.1  christos       break;
    819   1.1  christos 
    820  1.11  christos     case 'j':
    821  1.11  christos       FETCH_ARG (3, val);
    822   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    823   1.1  christos 				    "#%d", val+1);
    824   1.1  christos       break;
    825   1.1  christos 
    826  1.11  christos     case 'K':
    827  1.11  christos       FETCH_ARG (9, val);
    828   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    829   1.1  christos 				    "#%d", val);
    830   1.1  christos       break;
    831   1.1  christos 
    832   1.1  christos     case 'M':
    833   1.1  christos       if (place == 'h')
    834   1.1  christos 	{
    835   1.1  christos 	  static char *const scalefactor_name[] = { "<<", ">>" };
    836  1.11  christos 
    837  1.11  christos 	  FETCH_ARG (1, val);
    838   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic,
    839   1.1  christos 					"%s", scalefactor_name[val]);
    840   1.1  christos 	}
    841   1.1  christos       else
    842   1.1  christos 	{
    843   1.1  christos 	  FETCH_ARG (8, val);
    844  1.11  christos 	  if (val & 0x80)
    845  1.11  christos 	    val = val - 0x100;
    846   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    847   1.1  christos 					"#%d", val);
    848   1.1  christos 	}
    849   1.1  christos       break;
    850   1.1  christos 
    851  1.11  christos     case 'T':
    852  1.11  christos       FETCH_ARG (4, val);
    853   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    854   1.1  christos 				    "#%d", val);
    855   1.1  christos       break;
    856   1.1  christos 
    857  1.11  christos     case 'D':
    858  1.11  christos       FETCH_ARG (3, val);
    859   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
    860   1.1  christos 				    "%s", reg_names[val]);
    861   1.1  christos       break;
    862   1.1  christos 
    863  1.11  christos     case 'A':
    864  1.11  christos       FETCH_ARG (3, val);
    865   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
    866   1.1  christos 				    "%s", reg_names[val + 010]);
    867   1.1  christos       break;
    868   1.1  christos 
    869  1.11  christos     case 'R':
    870  1.11  christos       FETCH_ARG (4, val);
    871   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
    872   1.1  christos 				    "%s", reg_names[val]);
    873   1.1  christos       break;
    874   1.1  christos 
    875   1.1  christos     case 'r':
    876  1.11  christos       FETCH_ARG (4, regno);
    877  1.11  christos       if (regno > 7)
    878  1.11  christos 	{
    879  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
    880  1.11  christos 					"%s", reg_names[regno]);
    881   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
    882  1.11  christos 	}
    883  1.11  christos       else
    884  1.11  christos 	{
    885  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
    886  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
    887  1.11  christos 					"%s", reg_names[regno]);
    888   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
    889   1.1  christos 	}
    890   1.1  christos       break;
    891   1.1  christos 
    892  1.11  christos     case 'F':
    893  1.11  christos       FETCH_ARG (3, val);
    894   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
    895   1.1  christos 				    "%%fp%d", val);
    896   1.1  christos       break;
    897   1.1  christos 
    898   1.1  christos     case 'O':
    899  1.11  christos       FETCH_ARG (6, val);
    900  1.11  christos       if (val & 0x20)
    901   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_register,
    902  1.11  christos 				      "%s", reg_names[val & 7]);
    903  1.11  christos       else
    904   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    905   1.1  christos 				      "%d", val);
    906   1.1  christos       break;
    907   1.1  christos 
    908  1.11  christos     case '+':
    909  1.11  christos       FETCH_ARG (3, val);
    910  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
    911   1.1  christos 				    "%s", reg_names[val + 8]);
    912   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, "@+");
    913   1.1  christos       break;
    914   1.1  christos 
    915  1.11  christos     case '-':
    916  1.11  christos       FETCH_ARG (3, val);
    917  1.11  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
    918   1.1  christos 				    "%s", reg_names[val + 8]);
    919   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_text, "@-");
    920   1.1  christos       break;
    921   1.1  christos 
    922   1.1  christos     case 'k':
    923   1.1  christos       if (place == 'k')
    924  1.11  christos 	{
    925  1.11  christos 	  FETCH_ARG (3, val);
    926  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "{");
    927  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
    928   1.1  christos 					"%s", reg_names[val]);
    929   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "}");
    930   1.1  christos 	}
    931   1.1  christos       else if (place == 'C')
    932   1.1  christos 	{
    933   1.1  christos 	  FETCH_ARG (7, val);
    934  1.11  christos 	  if (val > 63)		/* This is a signed constant.  */
    935  1.11  christos 	    val -= 128;
    936  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "{");
    937  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    938   1.1  christos 					"#%d", val);
    939   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "}");
    940   1.7  christos 	}
    941   1.1  christos       else
    942   1.1  christos 	return PRINT_INSN_ARG_INVALID_OPERAND;
    943   1.1  christos       break;
    944   1.1  christos 
    945   1.1  christos     case '#':
    946   1.1  christos     case '^':
    947   1.1  christos       p1 = buffer + (*d == '#' ? 2 : 4);
    948   1.1  christos       if (place == 's')
    949   1.1  christos 	FETCH_ARG (4, val);
    950   1.1  christos       else if (place == 'C')
    951   1.1  christos 	FETCH_ARG (7, val);
    952   1.1  christos       else if (place == '8')
    953   1.1  christos 	FETCH_ARG (3, val);
    954   1.1  christos       else if (place == '3')
    955   1.1  christos 	FETCH_ARG (8, val);
    956   1.1  christos       else if (place == 'b')
    957   1.7  christos 	NEXTBYTE (p1, val);
    958   1.1  christos       else if (place == 'w' || place == 'W')
    959   1.7  christos 	NEXTWORD (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
    960   1.1  christos       else if (place == 'l')
    961   1.7  christos 	NEXTLONG (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
    962   1.1  christos       else
    963  1.11  christos 	return PRINT_INSN_ARG_INVALID_OP_TABLE;
    964  1.11  christos 
    965   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
    966   1.1  christos 				    "#%d", val);
    967   1.1  christos       break;
    968   1.1  christos 
    969   1.1  christos     case 'B':
    970   1.1  christos       if (place == 'b')
    971   1.1  christos 	NEXTBYTE (p, disp);
    972   1.1  christos       else if (place == 'B')
    973   1.7  christos 	disp = COERCE_SIGNED_CHAR (buffer[1]);
    974   1.1  christos       else if (place == 'w' || place == 'W')
    975   1.7  christos 	NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
    976   1.1  christos       else if (place == 'l' || place == 'L' || place == 'C')
    977   1.1  christos 	NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
    978   1.1  christos       else if (place == 'g')
    979   1.1  christos 	{
    980   1.7  christos 	  NEXTBYTE (buffer, disp);
    981   1.1  christos 	  if (disp == 0)
    982   1.7  christos 	    NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
    983   1.1  christos 	  else if (disp == -1)
    984   1.1  christos 	    NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
    985   1.1  christos 	}
    986   1.1  christos       else if (place == 'c')
    987   1.7  christos 	{
    988   1.1  christos 	  if (buffer[1] & 0x40)		/* If bit six is one, long offset.  */
    989   1.7  christos 	    NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
    990   1.1  christos 	  else
    991   1.1  christos 	    NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
    992   1.7  christos 	}
    993   1.1  christos       else
    994   1.1  christos 	return PRINT_INSN_ARG_INVALID_OP_TABLE;
    995   1.1  christos 
    996   1.1  christos       (*info->print_address_func) (addr + disp, info);
    997   1.1  christos       break;
    998   1.1  christos 
    999   1.1  christos     case 'd':
   1000   1.1  christos       {
   1001   1.7  christos 	int val1;
   1002   1.1  christos 
   1003  1.11  christos 	NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
   1004  1.11  christos 	FETCH_ARG (3, val1);
   1005  1.11  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_register,
   1006  1.11  christos 				      "%s", reg_names[val1 + 8]);
   1007  1.11  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
   1008  1.11  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_address_offset,
   1009   1.1  christos 				      "%d", val);
   1010   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
   1011   1.1  christos 	break;
   1012   1.1  christos       }
   1013   1.1  christos 
   1014  1.11  christos     case 's':
   1015  1.11  christos       FETCH_ARG (3, val);
   1016   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1017   1.1  christos 				    "%s", fpcr_names[val]);
   1018   1.1  christos       break;
   1019   1.1  christos 
   1020  1.11  christos     case 'e':
   1021  1.11  christos       FETCH_ARG (2, val);
   1022   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1023   1.1  christos 				    "%%acc%d", val);
   1024   1.1  christos       break;
   1025   1.1  christos 
   1026  1.11  christos     case 'g':
   1027  1.11  christos       FETCH_ARG (1, val);
   1028   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1029   1.1  christos 				    "%%accext%s", val == 0 ? "01" : "23");
   1030   1.1  christos       break;
   1031   1.1  christos 
   1032   1.1  christos     case 'i':
   1033  1.11  christos       FETCH_ARG (2, val);
   1034  1.11  christos       if (val == 1)
   1035   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic,
   1036  1.11  christos 				      "<<");
   1037  1.11  christos       else if (val == 3)
   1038   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic,
   1039   1.7  christos 				      ">>");
   1040   1.1  christos       else
   1041   1.1  christos 	return PRINT_INSN_ARG_INVALID_OPERAND;
   1042   1.1  christos       break;
   1043   1.1  christos 
   1044   1.1  christos     case 'I':
   1045   1.1  christos       /* Get coprocessor ID... */
   1046   1.7  christos       val = fetch_arg (buffer, 'd', 3, info);
   1047   1.1  christos       if (val < 0)
   1048  1.11  christos 	return PRINT_INSN_ARG_MEMORY_ERROR;
   1049  1.11  christos       if (val != 1)				/* Unusual coprocessor ID?  */
   1050   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_text,
   1051   1.1  christos 				      "(cpid=%d) ", val);
   1052   1.1  christos       break;
   1053   1.1  christos 
   1054   1.1  christos     case '4':
   1055   1.1  christos     case '*':
   1056   1.1  christos     case '~':
   1057   1.1  christos     case '%':
   1058   1.1  christos     case ';':
   1059   1.1  christos     case '@':
   1060   1.1  christos     case '!':
   1061   1.1  christos     case '$':
   1062   1.1  christos     case '?':
   1063   1.1  christos     case '/':
   1064   1.1  christos     case '&':
   1065   1.1  christos     case '|':
   1066   1.1  christos     case '<':
   1067   1.1  christos     case '>':
   1068   1.1  christos     case 'm':
   1069   1.1  christos     case 'n':
   1070   1.1  christos     case 'o':
   1071   1.1  christos     case 'p':
   1072   1.1  christos     case 'q':
   1073   1.1  christos     case 'v':
   1074   1.1  christos     case 'b':
   1075   1.1  christos     case 'w':
   1076   1.1  christos     case 'y':
   1077   1.1  christos     case 'z':
   1078   1.1  christos       if (place == 'd')
   1079   1.1  christos 	{
   1080   1.7  christos 	  val = fetch_arg (buffer, 'x', 6, info);
   1081   1.1  christos 	  if (val < 0)
   1082   1.1  christos 	    return PRINT_INSN_ARG_MEMORY_ERROR;
   1083   1.1  christos 	  val = ((val & 7) << 3) + ((val >> 3) & 7);
   1084   1.1  christos 	}
   1085   1.1  christos       else
   1086   1.1  christos 	{
   1087   1.7  christos 	  val = fetch_arg (buffer, 's', 6, info);
   1088   1.1  christos 	  if (val < 0)
   1089   1.1  christos 	    return PRINT_INSN_ARG_MEMORY_ERROR;
   1090   1.1  christos 	}
   1091   1.1  christos 
   1092   1.7  christos       /* If the <ea> is invalid for *d, then reject this match.  */
   1093   1.1  christos       if (!m68k_valid_ea (*d, val))
   1094   1.1  christos 	return PRINT_INSN_ARG_INVALID_OPERAND;
   1095   1.1  christos 
   1096   1.1  christos       /* Get register number assuming address register.  */
   1097   1.1  christos       regno = (val & 7) + 8;
   1098   1.1  christos       regname = reg_names[regno];
   1099   1.1  christos       switch (val >> 3)
   1100  1.11  christos 	{
   1101  1.11  christos 	case 0:
   1102   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1103   1.1  christos 					"%s", reg_names[val]);
   1104   1.1  christos 	  break;
   1105  1.11  christos 
   1106  1.11  christos 	case 1:
   1107   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1108   1.1  christos 					"%s", regname);
   1109   1.1  christos 	  break;
   1110  1.11  christos 
   1111  1.11  christos 	case 2:
   1112  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1113   1.1  christos 					"%s", regname);
   1114   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
   1115   1.1  christos 	  break;
   1116  1.11  christos 
   1117  1.11  christos 	case 3:
   1118  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1119   1.1  christos 					"%s", regname);
   1120   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "@+");
   1121   1.1  christos 	  break;
   1122  1.11  christos 
   1123  1.11  christos 	case 4:
   1124  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1125   1.1  christos 					"%s", regname);
   1126   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "@-");
   1127   1.1  christos 	  break;
   1128   1.7  christos 
   1129  1.11  christos 	case 5:
   1130  1.11  christos 	  NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
   1131  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1132  1.11  christos 					"%s", regname);
   1133  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
   1134  1.11  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_address_offset,
   1135   1.1  christos 					"%d", val);
   1136   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
   1137   1.1  christos 	  break;
   1138   1.1  christos 
   1139   1.1  christos 	case 6:
   1140   1.7  christos 	  p = print_indexed (regno, p, addr, info);
   1141   1.1  christos 	  if (p == NULL)
   1142   1.1  christos 	    return PRINT_INSN_ARG_MEMORY_ERROR;
   1143   1.1  christos 	  break;
   1144   1.1  christos 
   1145   1.1  christos 	case 7:
   1146   1.1  christos 	  switch (val & 7)
   1147   1.7  christos 	    {
   1148   1.1  christos 	    case 0:
   1149   1.1  christos 	      NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
   1150   1.1  christos 	      (*info->print_address_func) (val, info);
   1151   1.1  christos 	      break;
   1152   1.1  christos 
   1153   1.1  christos 	    case 1:
   1154   1.1  christos 	      NEXTULONG (p, uval);
   1155   1.1  christos 	      (*info->print_address_func) (uval, info);
   1156   1.1  christos 	      break;
   1157   1.7  christos 
   1158  1.11  christos 	    case 2:
   1159  1.11  christos 	      NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
   1160  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1161   1.1  christos 					    "%%pc");
   1162  1.11  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
   1163   1.1  christos 	      (*info->print_address_func) (addr + val, info);
   1164   1.1  christos 	      (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
   1165   1.1  christos 	      break;
   1166   1.1  christos 
   1167   1.1  christos 	    case 3:
   1168   1.7  christos 	      p = print_indexed (-1, p, addr, info);
   1169   1.1  christos 	      if (p == NULL)
   1170   1.1  christos 		return PRINT_INSN_ARG_MEMORY_ERROR;
   1171   1.1  christos 	      break;
   1172   1.1  christos 
   1173   1.1  christos 	    case 4:
   1174   1.1  christos 	      flt_p = 1;	/* Assume it's a float... */
   1175   1.1  christos 	      switch (place)
   1176   1.1  christos 	      {
   1177   1.1  christos 		case 'b':
   1178   1.1  christos 		  NEXTBYTE (p, val);
   1179   1.1  christos 		  flt_p = 0;
   1180   1.1  christos 		  break;
   1181   1.7  christos 
   1182   1.1  christos 		case 'w':
   1183   1.1  christos 		  NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
   1184   1.1  christos 		  flt_p = 0;
   1185   1.1  christos 		  break;
   1186   1.7  christos 
   1187   1.1  christos 		case 'l':
   1188   1.1  christos 		  NEXTLONG (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
   1189   1.1  christos 		  flt_p = 0;
   1190   1.1  christos 		  break;
   1191   1.1  christos 
   1192   1.1  christos 		case 'f':
   1193   1.1  christos 		  NEXTSINGLE (flval, p);
   1194   1.1  christos 		  break;
   1195   1.1  christos 
   1196   1.1  christos 		case 'F':
   1197   1.1  christos 		  NEXTDOUBLE (flval, p);
   1198   1.1  christos 		  break;
   1199   1.1  christos 
   1200   1.1  christos 		case 'x':
   1201   1.1  christos 		  NEXTEXTEND (flval, p);
   1202   1.1  christos 		  break;
   1203   1.1  christos 
   1204   1.1  christos 		case 'p':
   1205   1.1  christos 		  NEXTPACKED (p, flval);
   1206   1.1  christos 		  break;
   1207   1.7  christos 
   1208   1.1  christos 		default:
   1209   1.1  christos 		  return PRINT_INSN_ARG_INVALID_OPERAND;
   1210  1.11  christos 	      }
   1211  1.11  christos 	      if (flt_p)	/* Print a float? */
   1212   1.1  christos 		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1213  1.11  christos 					      "#0e%g", flval);
   1214  1.11  christos 	      else
   1215   1.1  christos 		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1216   1.1  christos 					      "#%d", val);
   1217   1.1  christos 	      break;
   1218   1.7  christos 
   1219   1.1  christos 	    default:
   1220   1.1  christos 	      return PRINT_INSN_ARG_INVALID_OPERAND;
   1221   1.1  christos 	    }
   1222   1.1  christos 	}
   1223   1.1  christos 
   1224   1.1  christos       /* If place is '/', then this is the case of the mask bit for
   1225   1.1  christos 	 mac/emac loads. Now that the arg has been printed, grab the
   1226   1.1  christos 	 mask bit and if set, add a '&' to the arg.  */
   1227   1.1  christos       if (place == '/')
   1228   1.1  christos 	{
   1229  1.11  christos 	  FETCH_ARG (1, val);
   1230   1.1  christos 	  if (val)
   1231   1.1  christos 	    info->fprintf_styled_func (info->stream, dis_style_text, "&");
   1232   1.1  christos 	}
   1233   1.1  christos       break;
   1234   1.1  christos 
   1235   1.1  christos     case 'L':
   1236   1.1  christos     case 'l':
   1237   1.1  christos 	if (place == 'w')
   1238   1.1  christos 	  {
   1239   1.7  christos 	    char doneany;
   1240   1.1  christos 	    p1 = buffer + 2;
   1241   1.1  christos 	    NEXTWORD (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
   1242   1.1  christos 	    /* Move the pointer ahead if this point is farther ahead
   1243   1.1  christos 	       than the last.  */
   1244   1.1  christos 	    p = p1 > p ? p1 : p;
   1245  1.11  christos 	    if (val == 0)
   1246  1.11  christos 	      {
   1247   1.1  christos 		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1248   1.1  christos 					      "#0");
   1249   1.1  christos 		break;
   1250   1.1  christos 	      }
   1251   1.1  christos 	    if (*d == 'l')
   1252   1.1  christos 	      {
   1253   1.1  christos 		int newval = 0;
   1254   1.1  christos 
   1255   1.1  christos 		for (regno = 0; regno < 16; ++regno)
   1256   1.1  christos 		  if (val & (0x8000 >> regno))
   1257   1.1  christos 		    newval |= 1 << regno;
   1258   1.1  christos 		val = newval;
   1259   1.1  christos 	      }
   1260   1.1  christos 	    val &= 0xffff;
   1261   1.1  christos 	    doneany = 0;
   1262   1.1  christos 	    for (regno = 0; regno < 16; ++regno)
   1263   1.1  christos 	      if (val & (1 << regno))
   1264   1.1  christos 		{
   1265   1.1  christos 		  int first_regno;
   1266  1.11  christos 
   1267  1.11  christos 		  if (doneany)
   1268   1.1  christos 		    (*info->fprintf_styled_func) (info->stream, dis_style_text,
   1269  1.11  christos 						  "/");
   1270  1.11  christos 		  doneany = 1;
   1271   1.1  christos 		  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1272   1.1  christos 						"%s", reg_names[regno]);
   1273   1.1  christos 		  first_regno = regno;
   1274   1.1  christos 		  while (val & (1 << (regno + 1)))
   1275  1.11  christos 		    ++regno;
   1276  1.11  christos 		  if (regno > first_regno)
   1277  1.11  christos 		    {
   1278  1.11  christos 		      (*info->fprintf_styled_func) (info->stream,
   1279  1.11  christos 						    dis_style_text, "-");
   1280  1.11  christos 		      (*info->fprintf_styled_func) (info->stream,
   1281  1.11  christos 						    dis_style_register, "%s",
   1282   1.1  christos 						    reg_names[regno]);
   1283   1.1  christos 		    }
   1284   1.1  christos 		}
   1285   1.1  christos 	  }
   1286   1.1  christos 	else if (place == '3')
   1287   1.1  christos 	  {
   1288   1.1  christos 	    /* `fmovem' insn.  */
   1289   1.1  christos 	    char doneany;
   1290   1.1  christos 
   1291   1.1  christos 	    FETCH_ARG (8, val);
   1292  1.11  christos 	    if (val == 0)
   1293  1.11  christos 	      {
   1294   1.1  christos 		(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1295   1.1  christos 					      "#0");
   1296   1.1  christos 		break;
   1297   1.1  christos 	      }
   1298   1.1  christos 	    if (*d == 'l')
   1299   1.1  christos 	      {
   1300   1.1  christos 		int newval = 0;
   1301   1.1  christos 
   1302   1.1  christos 		for (regno = 0; regno < 8; ++regno)
   1303   1.1  christos 		  if (val & (0x80 >> regno))
   1304   1.1  christos 		    newval |= 1 << regno;
   1305   1.1  christos 		val = newval;
   1306   1.1  christos 	      }
   1307   1.1  christos 	    val &= 0xff;
   1308   1.1  christos 	    doneany = 0;
   1309   1.1  christos 	    for (regno = 0; regno < 8; ++regno)
   1310   1.1  christos 	      if (val & (1 << regno))
   1311   1.1  christos 		{
   1312  1.11  christos 		  int first_regno;
   1313  1.11  christos 		  if (doneany)
   1314   1.1  christos 		    (*info->fprintf_styled_func) (info->stream, dis_style_text,
   1315  1.11  christos 						  "/");
   1316  1.11  christos 		  doneany = 1;
   1317   1.1  christos 		  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1318   1.1  christos 						"%%fp%d", regno);
   1319   1.1  christos 		  first_regno = regno;
   1320   1.1  christos 		  while (val & (1 << (regno + 1)))
   1321  1.11  christos 		    ++regno;
   1322  1.11  christos 		  if (regno > first_regno)
   1323  1.11  christos 		    {
   1324  1.11  christos 		      (*info->fprintf_styled_func) (info->stream,
   1325  1.11  christos 						    dis_style_text, "-");
   1326  1.11  christos 		      (*info->fprintf_styled_func) (info->stream,
   1327  1.11  christos 						    dis_style_register,
   1328   1.1  christos 						    "%%fp%d", regno);
   1329   1.1  christos 		    }
   1330   1.1  christos 		}
   1331   1.1  christos 	  }
   1332   1.1  christos 	else if (place == '8')
   1333   1.1  christos 	  {
   1334  1.11  christos 	    FETCH_ARG (3, val);
   1335  1.11  christos 	    /* fmoveml for FP status registers.  */
   1336   1.1  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1337   1.1  christos 					  "%s", fpcr_names[val]);
   1338   1.7  christos 	  }
   1339   1.1  christos 	else
   1340   1.1  christos 	  return PRINT_INSN_ARG_INVALID_OP_TABLE;
   1341   1.1  christos       break;
   1342   1.1  christos 
   1343   1.7  christos     case 'X':
   1344   1.1  christos       place = '8';
   1345   1.1  christos       /* Fall through.  */
   1346   1.1  christos     case 'Y':
   1347   1.1  christos     case 'Z':
   1348   1.1  christos     case 'W':
   1349   1.1  christos     case '0':
   1350   1.1  christos     case '1':
   1351   1.1  christos     case '2':
   1352   1.1  christos     case '3':
   1353   1.1  christos       {
   1354   1.1  christos 	char *name = 0;
   1355   1.1  christos 
   1356   1.1  christos 	FETCH_ARG (5, val);
   1357   1.1  christos 	switch (val)
   1358   1.1  christos 	  {
   1359   1.1  christos 	  case 2: name = "%tt0"; break;
   1360   1.1  christos 	  case 3: name = "%tt1"; break;
   1361   1.1  christos 	  case 0x10: name = "%tc"; break;
   1362   1.1  christos 	  case 0x11: name = "%drp"; break;
   1363   1.1  christos 	  case 0x12: name = "%srp"; break;
   1364   1.1  christos 	  case 0x13: name = "%crp"; break;
   1365   1.1  christos 	  case 0x14: name = "%cal"; break;
   1366   1.1  christos 	  case 0x15: name = "%val"; break;
   1367   1.1  christos 	  case 0x16: name = "%scc"; break;
   1368   1.1  christos 	  case 0x17: name = "%ac"; break;
   1369   1.1  christos  	  case 0x18: name = "%psr"; break;
   1370   1.1  christos 	  case 0x19: name = "%pcsr"; break;
   1371   1.1  christos 	  case 0x1c:
   1372   1.1  christos 	  case 0x1d:
   1373   1.1  christos 	    {
   1374  1.11  christos 	      int break_reg = ((buffer[3] >> 2) & 7);
   1375  1.11  christos 
   1376  1.11  christos 	      (*info->fprintf_styled_func)
   1377   1.1  christos 		(info->stream, dis_style_register,
   1378   1.1  christos 		 val == 0x1c ? "%%bad%d" : "%%bac%d", break_reg);
   1379   1.1  christos 	    }
   1380  1.11  christos 	    break;
   1381  1.11  christos 	  default:
   1382   1.1  christos 	    (*info->fprintf_styled_func) (info->stream, dis_style_text,
   1383   1.1  christos 					  "<mmu register %d>", val);
   1384  1.11  christos 	  }
   1385  1.11  christos 	if (name)
   1386   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1387   1.1  christos 					"%s", name);
   1388   1.1  christos       }
   1389   1.1  christos       break;
   1390   1.1  christos 
   1391   1.1  christos     case 'f':
   1392   1.1  christos       {
   1393   1.1  christos 	int fc;
   1394   1.1  christos 
   1395  1.11  christos 	FETCH_ARG (5, fc);
   1396  1.11  christos 	if (fc == 1)
   1397   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1398  1.11  christos 					"%%dfc");
   1399  1.11  christos 	else if (fc == 0)
   1400   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_register,
   1401   1.1  christos 					"%%sfc");
   1402  1.11  christos 	else
   1403  1.11  christos 	  /* xgettext:c-format */
   1404   1.1  christos 	  (*info->fprintf_styled_func) (info->stream, dis_style_text,
   1405   1.1  christos 					_("<function code %d>"), fc);
   1406   1.1  christos       }
   1407   1.1  christos       break;
   1408  1.11  christos 
   1409   1.1  christos     case 'V':
   1410   1.1  christos       (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%val");
   1411   1.1  christos       break;
   1412   1.1  christos 
   1413   1.1  christos     case 't':
   1414   1.1  christos       {
   1415   1.1  christos 	int level;
   1416  1.11  christos 
   1417  1.11  christos 	FETCH_ARG (3, level);
   1418   1.1  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_immediate,
   1419   1.1  christos 				      "%d", level);
   1420   1.1  christos       }
   1421   1.1  christos       break;
   1422   1.1  christos 
   1423   1.1  christos     case 'u':
   1424   1.1  christos       {
   1425   1.1  christos 	short is_upper = 0;
   1426   1.1  christos 	int reg;
   1427   1.1  christos 
   1428   1.1  christos 	FETCH_ARG (5, reg);
   1429   1.1  christos 	if (reg & 0x10)
   1430   1.1  christos 	  {
   1431   1.1  christos 	    is_upper = 1;
   1432  1.11  christos 	    reg &= 0xf;
   1433  1.11  christos 	  }
   1434  1.11  christos 	(*info->fprintf_styled_func) (info->stream, dis_style_register, "%s%s",
   1435   1.1  christos 				      reg_half_names[reg],
   1436   1.1  christos 				      is_upper ? "u" : "l");
   1437   1.1  christos       }
   1438   1.1  christos       break;
   1439   1.7  christos 
   1440   1.1  christos     default:
   1441   1.1  christos       return PRINT_INSN_ARG_INVALID_OP_TABLE;
   1442   1.1  christos     }
   1443   1.1  christos 
   1444   1.1  christos   return p - p0;
   1445   1.1  christos }
   1446   1.7  christos 
   1447   1.7  christos /* Try to match the current instruction to best and if so, return the
   1448   1.1  christos    number of bytes consumed from the instruction stream, else zero.
   1449   1.1  christos    Return -1 on memory error.  */
   1450   1.1  christos 
   1451   1.1  christos static int
   1452   1.1  christos match_insn_m68k (bfd_vma memaddr,
   1453   1.1  christos 		 disassemble_info * info,
   1454   1.1  christos 		 const struct m68k_opcode * best)
   1455   1.1  christos {
   1456   1.1  christos   unsigned char *save_p;
   1457   1.1  christos   unsigned char *p;
   1458   1.1  christos   const char *d;
   1459   1.1  christos   const char *args = best->args;
   1460   1.1  christos 
   1461  1.11  christos   struct private *priv = (struct private *) info->private_data;
   1462   1.1  christos   bfd_byte *buffer = priv->the_buffer;
   1463   1.1  christos   fprintf_styled_ftype save_printer = info->fprintf_styled_func;
   1464   1.1  christos   void (* save_print_address) (bfd_vma, struct disassemble_info *)
   1465   1.1  christos     = info->print_address_func;
   1466   1.1  christos 
   1467   1.6  christos   if (*args == '.')
   1468   1.1  christos     args++;
   1469   1.1  christos 
   1470   1.1  christos   /* Point at first word of argument data,
   1471   1.1  christos      and at descriptor for first argument.  */
   1472   1.1  christos   p = buffer + 2;
   1473   1.1  christos 
   1474   1.1  christos   /* Figure out how long the fixed-size portion of the instruction is.
   1475   1.1  christos      The only place this is stored in the opcode table is
   1476   1.1  christos      in the arguments--look for arguments which specify fields in the 2nd
   1477   1.1  christos      or 3rd words of the instruction.  */
   1478   1.1  christos   for (d = args; *d; d += 2)
   1479   1.1  christos     {
   1480   1.1  christos       /* I don't think it is necessary to be checking d[0] here;
   1481   1.1  christos 	 I suspect all this could be moved to the case statement below.  */
   1482   1.1  christos       if (d[0] == '#')
   1483   1.1  christos 	{
   1484   1.1  christos 	  if (d[1] == 'l' && p - buffer < 6)
   1485   1.1  christos 	    p = buffer + 6;
   1486   1.1  christos 	  else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8')
   1487   1.1  christos 	    p = buffer + 4;
   1488   1.1  christos 	}
   1489   1.1  christos 
   1490   1.1  christos       if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
   1491   1.1  christos 	p = buffer + 4;
   1492   1.1  christos 
   1493   1.1  christos       switch (d[1])
   1494   1.1  christos 	{
   1495   1.1  christos 	case '1':
   1496   1.1  christos 	case '2':
   1497   1.1  christos 	case '3':
   1498   1.1  christos 	case '7':
   1499   1.1  christos 	case '8':
   1500   1.1  christos 	case '9':
   1501   1.1  christos 	case 'i':
   1502   1.1  christos 	  if (p - buffer < 4)
   1503   1.1  christos 	    p = buffer + 4;
   1504   1.1  christos 	  break;
   1505   1.1  christos 	case '4':
   1506   1.1  christos 	case '5':
   1507   1.1  christos 	case '6':
   1508   1.1  christos 	  if (p - buffer < 6)
   1509   1.1  christos 	    p = buffer + 6;
   1510   1.1  christos 	  break;
   1511   1.1  christos 	default:
   1512   1.1  christos 	  break;
   1513   1.1  christos 	}
   1514   1.1  christos     }
   1515   1.1  christos 
   1516   1.1  christos   /* pflusha is an exceptions.  It takes no arguments but is two words
   1517   1.1  christos      long.  Recognize it by looking at the lower 16 bits of the mask.  */
   1518   1.1  christos   if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
   1519   1.1  christos     p = buffer + 4;
   1520   1.1  christos 
   1521   1.1  christos   /* lpstop is another exception.  It takes a one word argument but is
   1522   1.1  christos      three words long.  */
   1523   1.1  christos   if (p - buffer < 6
   1524   1.1  christos       && (best->match & 0xffff) == 0xffff
   1525   1.1  christos       && args[0] == '#'
   1526   1.1  christos       && args[1] == 'w')
   1527   1.1  christos     {
   1528   1.1  christos       /* Copy the one word argument into the usual location for a one
   1529   1.1  christos 	 word argument, to simplify printing it.  We can get away with
   1530   1.1  christos 	 this because we know exactly what the second word is, and we
   1531   1.7  christos 	 aren't going to print anything based on it.  */
   1532   1.7  christos       p = buffer + 6;
   1533   1.1  christos       if (!FETCH_DATA (info, p))
   1534   1.1  christos 	return -1;
   1535   1.1  christos       buffer[2] = buffer[4];
   1536   1.1  christos       buffer[3] = buffer[5];
   1537   1.7  christos     }
   1538   1.7  christos 
   1539   1.1  christos   if (!FETCH_DATA (info, p))
   1540   1.1  christos     return -1;
   1541   1.1  christos 
   1542  1.11  christos   save_p = p;
   1543   1.1  christos   info->print_address_func = dummy_print_address;
   1544   1.1  christos   info->fprintf_styled_func = dummy_printer;
   1545   1.1  christos 
   1546   1.1  christos   /* We scan the operands twice.  The first time we don't print anything,
   1547   1.1  christos      but look for errors.  */
   1548   1.1  christos   for (d = args; *d; d += 2)
   1549   1.1  christos     {
   1550   1.1  christos       int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
   1551   1.1  christos 
   1552   1.7  christos       if (eaten >= 0)
   1553   1.7  christos 	p += eaten;
   1554   1.1  christos       else if (eaten == PRINT_INSN_ARG_INVALID_OPERAND
   1555  1.11  christos 	       || eaten == PRINT_INSN_ARG_MEMORY_ERROR)
   1556   1.1  christos 	{
   1557   1.7  christos 	  info->fprintf_styled_func = save_printer;
   1558   1.1  christos 	  info->print_address_func = save_print_address;
   1559   1.1  christos 	  return eaten == PRINT_INSN_ARG_MEMORY_ERROR ? -1 : 0;
   1560   1.1  christos 	}
   1561   1.1  christos       else
   1562   1.1  christos 	{
   1563  1.11  christos 	  /* We must restore the print functions before trying to print the
   1564   1.1  christos 	     error message.  */
   1565  1.11  christos 	  info->fprintf_styled_func = save_printer;
   1566  1.11  christos 	  info->print_address_func = save_print_address;
   1567  1.11  christos 	  info->fprintf_styled_func (info->stream, dis_style_text,
   1568  1.11  christos 				     /* xgettext:c-format */
   1569   1.1  christos 				     _("<internal error in opcode table: %s %s>\n"),
   1570   1.1  christos 				     best->name, best->args);
   1571   1.1  christos 	  return 2;
   1572   1.1  christos 	}
   1573   1.1  christos     }
   1574  1.11  christos 
   1575   1.1  christos   p = save_p;
   1576   1.1  christos   info->fprintf_styled_func = save_printer;
   1577   1.1  christos   info->print_address_func = save_print_address;
   1578   1.1  christos 
   1579  1.11  christos   d = args;
   1580   1.1  christos 
   1581   1.1  christos   info->fprintf_styled_func (info->stream, dis_style_mnemonic, "%s", best->name);
   1582  1.11  christos 
   1583   1.1  christos   if (*d)
   1584   1.1  christos     info->fprintf_styled_func (info->stream, dis_style_text, " ");
   1585   1.1  christos 
   1586   1.1  christos   while (*d)
   1587   1.1  christos     {
   1588   1.1  christos       p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
   1589   1.1  christos       d += 2;
   1590  1.11  christos 
   1591   1.1  christos       if (*d && *(d - 2) != 'I' && *d != 'k')
   1592   1.1  christos 	info->fprintf_styled_func (info->stream, dis_style_text, ",");
   1593   1.1  christos     }
   1594   1.1  christos 
   1595   1.1  christos   return p - buffer;
   1596   1.1  christos }
   1597   1.1  christos 
   1598   1.1  christos /* Try to interpret the instruction at address MEMADDR as one that
   1599   1.7  christos    can execute on a processor with the features given by ARCH_MASK.
   1600   1.7  christos    If successful, print the instruction to INFO->STREAM and return
   1601   1.1  christos    its length in bytes.  Return 0 otherwise.  Return -1 on memory
   1602   1.1  christos    error.  */
   1603   1.1  christos 
   1604   1.1  christos static int
   1605   1.1  christos m68k_scan_mask (bfd_vma memaddr, disassemble_info *info,
   1606   1.1  christos 		unsigned int arch_mask)
   1607   1.1  christos {
   1608   1.1  christos   int i;
   1609   1.1  christos   const char *d;
   1610   1.1  christos   static const struct m68k_opcode **opcodes[16];
   1611   1.1  christos   static int numopcodes[16];
   1612   1.1  christos   int val;
   1613   1.1  christos   int major_opcode;
   1614   1.1  christos 
   1615   1.1  christos   struct private *priv = (struct private *) info->private_data;
   1616   1.1  christos   bfd_byte *buffer = priv->the_buffer;
   1617   1.1  christos 
   1618   1.1  christos   if (!opcodes[0])
   1619   1.1  christos     {
   1620   1.1  christos       /* Speed up the matching by sorting the opcode
   1621   1.1  christos 	 table on the upper four bits of the opcode.  */
   1622   1.1  christos       const struct m68k_opcode **opc_pointer[16];
   1623   1.1  christos 
   1624   1.1  christos       /* First count how many opcodes are in each of the sixteen buckets.  */
   1625   1.1  christos       for (i = 0; i < m68k_numopcodes; i++)
   1626   1.1  christos 	numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
   1627   1.1  christos 
   1628   1.1  christos       /* Then create a sorted table of pointers
   1629   1.1  christos 	 that point into the unsorted table.  */
   1630   1.1  christos       opc_pointer[0] = xmalloc (sizeof (struct m68k_opcode *)
   1631   1.1  christos 				* m68k_numopcodes);
   1632   1.1  christos       opcodes[0] = opc_pointer[0];
   1633   1.1  christos 
   1634   1.1  christos       for (i = 1; i < 16; i++)
   1635   1.1  christos 	{
   1636   1.1  christos 	  opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
   1637   1.1  christos 	  opcodes[i] = opc_pointer[i];
   1638   1.1  christos 	}
   1639   1.1  christos 
   1640   1.1  christos       for (i = 0; i < m68k_numopcodes; i++)
   1641   1.1  christos 	*opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
   1642   1.7  christos     }
   1643   1.7  christos 
   1644   1.1  christos   if (!FETCH_DATA (info, buffer + 2))
   1645   1.1  christos     return -1;
   1646   1.1  christos   major_opcode = (buffer[0] >> 4) & 15;
   1647   1.1  christos 
   1648   1.1  christos   for (i = 0; i < numopcodes[major_opcode]; i++)
   1649   1.1  christos     {
   1650   1.1  christos       const struct m68k_opcode *opc = opcodes[major_opcode][i];
   1651   1.1  christos       unsigned long opcode = opc->opcode;
   1652   1.1  christos       unsigned long match = opc->match;
   1653   1.1  christos       const char *args = opc->args;
   1654   1.1  christos 
   1655   1.1  christos       if (*args == '.')
   1656   1.1  christos 	args++;
   1657   1.1  christos 
   1658   1.1  christos       if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
   1659   1.1  christos 	  && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
   1660   1.1  christos 	  /* Only fetch the next two bytes if we need to.  */
   1661   1.1  christos 	  && (((0xffff & match) == 0)
   1662   1.1  christos 	      ||
   1663   1.1  christos 	      (FETCH_DATA (info, buffer + 4)
   1664   1.1  christos 	       && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
   1665   1.1  christos 	       && ((0xff & buffer[3] & match) == (0xff & opcode)))
   1666   1.1  christos 	      )
   1667   1.1  christos 	  && (opc->arch & arch_mask) != 0)
   1668   1.1  christos 	{
   1669   1.1  christos 	  /* Don't use for printout the variants of divul and divsl
   1670   1.1  christos 	     that have the same register number in two places.
   1671   1.1  christos 	     The more general variants will match instead.  */
   1672   1.1  christos 	  for (d = args; *d; d += 2)
   1673   1.1  christos 	    if (d[1] == 'D')
   1674   1.1  christos 	      break;
   1675   1.1  christos 
   1676   1.1  christos 	  /* Don't use for printout the variants of most floating
   1677   1.1  christos 	     point coprocessor instructions which use the same
   1678   1.1  christos 	     register number in two places, as above.  */
   1679   1.1  christos 	  if (*d == '\0')
   1680   1.1  christos 	    for (d = args; *d; d += 2)
   1681   1.1  christos 	      if (d[1] == 't')
   1682   1.1  christos 		break;
   1683   1.1  christos 
   1684   1.1  christos 	  /* Don't match fmovel with more than one register;
   1685   1.1  christos 	     wait for fmoveml.  */
   1686   1.1  christos 	  if (*d == '\0')
   1687   1.1  christos 	    {
   1688   1.1  christos 	      for (d = args; *d; d += 2)
   1689   1.1  christos 		{
   1690   1.1  christos 		  if (d[0] == 's' && d[1] == '8')
   1691   1.1  christos 		    {
   1692   1.1  christos 		      val = fetch_arg (buffer, d[1], 3, info);
   1693   1.1  christos 		      if (val < 0)
   1694   1.1  christos 			return 0;
   1695   1.1  christos 		      if ((val & (val - 1)) != 0)
   1696   1.1  christos 			break;
   1697   1.1  christos 		    }
   1698   1.1  christos 		}
   1699   1.1  christos 	    }
   1700   1.1  christos 
   1701   1.1  christos 	  /* Don't match FPU insns with non-default coprocessor ID.  */
   1702   1.1  christos 	  if (*d == '\0')
   1703   1.1  christos 	    {
   1704   1.1  christos 	      for (d = args; *d; d += 2)
   1705   1.1  christos 		{
   1706   1.1  christos 		  if (d[0] == 'I')
   1707   1.1  christos 		    {
   1708   1.1  christos 		      val = fetch_arg (buffer, 'd', 3, info);
   1709   1.1  christos 		      if (val != 1)
   1710   1.1  christos 			break;
   1711   1.1  christos 		    }
   1712   1.1  christos 		}
   1713   1.1  christos 	    }
   1714   1.1  christos 
   1715   1.1  christos 	  if (*d == '\0')
   1716   1.1  christos 	    if ((val = match_insn_m68k (memaddr, info, opc)))
   1717   1.1  christos 	      return val;
   1718   1.1  christos 	}
   1719   1.6  christos     }
   1720   1.1  christos   return 0;
   1721   1.1  christos }
   1722   1.1  christos 
   1723   1.1  christos /* Print the m68k instruction at address MEMADDR in debugged memory,
   1724   1.1  christos    on INFO->STREAM.  Returns length of the instruction, in bytes.  */
   1725   1.1  christos 
   1726   1.1  christos int
   1727   1.1  christos print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
   1728   1.1  christos {
   1729   1.1  christos   unsigned int arch_mask;
   1730   1.1  christos   struct private priv;
   1731   1.1  christos   int val;
   1732   1.1  christos 
   1733   1.1  christos   bfd_byte *buffer = priv.the_buffer;
   1734   1.1  christos 
   1735   1.1  christos   info->private_data = & priv;
   1736   1.1  christos   /* Tell objdump to use two bytes per chunk
   1737   1.1  christos      and six bytes per line for displaying raw data.  */
   1738   1.1  christos   info->bytes_per_chunk = 2;
   1739   1.1  christos   info->bytes_per_line = 6;
   1740   1.1  christos   info->display_endian = BFD_ENDIAN_BIG;
   1741   1.1  christos   priv.max_fetched = priv.the_buffer;
   1742   1.1  christos   priv.insn_start = memaddr;
   1743   1.1  christos 
   1744   1.1  christos   arch_mask = bfd_m68k_mach_to_features (info->mach);
   1745   1.1  christos   if (!arch_mask)
   1746   1.1  christos     {
   1747   1.1  christos       /* First try printing an m680x0 instruction.  Try printing a Coldfire
   1748   1.7  christos 	 one if that fails.  */
   1749   1.1  christos       val = m68k_scan_mask (memaddr, info, m68k_mask);
   1750   1.1  christos       if (val <= 0)
   1751   1.1  christos 	val = m68k_scan_mask (memaddr, info, mcf_mask);
   1752   1.1  christos     }
   1753   1.1  christos   else
   1754   1.1  christos     {
   1755   1.1  christos       val = m68k_scan_mask (memaddr, info, arch_mask);
   1756   1.1  christos     }
   1757  1.11  christos 
   1758  1.11  christos   if (val == 0)
   1759  1.11  christos     {
   1760  1.11  christos       /* Handle undefined instructions.  */
   1761  1.11  christos       info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
   1762  1.11  christos 				 ".short");
   1763  1.11  christos       info->fprintf_styled_func (info->stream, dis_style_text, " ");
   1764  1.11  christos       info->fprintf_styled_func (info->stream, dis_style_immediate,
   1765   1.1  christos 				 "0x%04x", (buffer[0] << 8) + buffer[1]);
   1766   1.1  christos     }
   1767   1.1  christos 
   1768                   return val ? val : 2;
   1769                 }
   1770