Home | History | Annotate | Line # | Download | only in opcodes
msp430-dis.c revision 1.6
      1  1.1  christos /* Disassemble MSP430 instructions.
      2  1.6  christos    Copyright (C) 2002-2016 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos    Contributed by Dmitry Diky <diwil (at) mail.ru>
      5  1.6  christos 
      6  1.1  christos    This file is part of the GNU opcodes library.
      7  1.1  christos 
      8  1.1  christos    This library is free software; you can redistribute it and/or modify
      9  1.1  christos    it under the terms of the GNU General Public License as published by
     10  1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     11  1.1  christos    any later version.
     12  1.1  christos 
     13  1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     14  1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15  1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     16  1.1  christos    License for more details.
     17  1.1  christos 
     18  1.1  christos    You should have received a copy of the GNU General Public License
     19  1.1  christos    along with this program; if not, write to the Free Software
     20  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21  1.1  christos    MA 02110-1301, USA.  */
     22  1.1  christos 
     23  1.1  christos #include "sysdep.h"
     24  1.1  christos #include <stdio.h>
     25  1.1  christos #include <ctype.h>
     26  1.1  christos #include <sys/types.h>
     27  1.6  christos #include <errno.h>
     28  1.1  christos 
     29  1.1  christos #include "dis-asm.h"
     30  1.1  christos #include "opintl.h"
     31  1.1  christos #include "libiberty.h"
     32  1.1  christos 
     33  1.1  christos #define DASM_SECTION
     34  1.1  christos #include "opcode/msp430.h"
     35  1.1  christos #undef DASM_SECTION
     36  1.1  christos 
     37  1.1  christos 
     38  1.1  christos #define PS(x)   (0xffff & (x))
     39  1.1  christos 
     40  1.6  christos static bfd_boolean
     41  1.6  christos msp430dis_read_two_bytes (bfd_vma            addr,
     42  1.6  christos 			  disassemble_info * info,
     43  1.6  christos 			  bfd_byte *         buffer,
     44  1.6  christos 			  char *             comm)
     45  1.1  christos {
     46  1.1  christos   int status;
     47  1.1  christos 
     48  1.1  christos   status = info->read_memory_func (addr, buffer, 2, info);
     49  1.6  christos   if (status == 0)
     50  1.6  christos     return TRUE;
     51  1.6  christos 
     52  1.6  christos   /* PR 20150: A status of EIO means that there were no more bytes left
     53  1.6  christos      to read in the current section.  This can happen when disassembling
     54  1.6  christos      interrupt vectors for example.  Avoid cluttering the output with
     55  1.6  christos      unhelpful error messages in this case.  */
     56  1.6  christos   if (status == EIO)
     57  1.6  christos     {
     58  1.6  christos       if (comm)
     59  1.6  christos 	sprintf (comm, _("Warning: disassembly unreliable - not enough bytes available"));
     60  1.6  christos     }
     61  1.6  christos   else
     62  1.1  christos     {
     63  1.1  christos       info->memory_error_func (status, addr, info);
     64  1.6  christos       if (comm)
     65  1.6  christos 	sprintf (comm, _("Error: read from memory failed"));
     66  1.6  christos     }
     67  1.6  christos 
     68  1.6  christos   return FALSE;
     69  1.6  christos }
     70  1.6  christos 
     71  1.6  christos static bfd_boolean
     72  1.6  christos msp430dis_opcode_unsigned (bfd_vma            addr,
     73  1.6  christos 			   disassemble_info * info,
     74  1.6  christos 			   unsigned short *   return_val,
     75  1.6  christos 			   char *             comm)
     76  1.6  christos {
     77  1.6  christos   bfd_byte buffer[2];
     78  1.6  christos 
     79  1.6  christos   if (msp430dis_read_two_bytes (addr, info, buffer, comm))
     80  1.6  christos     {
     81  1.6  christos       * return_val = bfd_getl16 (buffer);
     82  1.6  christos       return TRUE;
     83  1.6  christos     }
     84  1.6  christos   else
     85  1.6  christos     {
     86  1.6  christos       * return_val = 0;
     87  1.6  christos       return FALSE;
     88  1.6  christos     }
     89  1.6  christos }
     90  1.6  christos 
     91  1.6  christos static bfd_boolean
     92  1.6  christos msp430dis_opcode_signed (bfd_vma            addr,
     93  1.6  christos 			 disassemble_info * info,
     94  1.6  christos 			 signed int *       return_val,
     95  1.6  christos 			 char *             comm)
     96  1.6  christos {
     97  1.6  christos   bfd_byte buffer[2];
     98  1.6  christos 
     99  1.6  christos   if (msp430dis_read_two_bytes (addr, info, buffer, comm))
    100  1.6  christos     {
    101  1.6  christos       int status;
    102  1.6  christos 
    103  1.6  christos       status = bfd_getl_signed_16 (buffer);
    104  1.6  christos       if (status & 0x8000)
    105  1.6  christos 	status |= -1U << 16;
    106  1.6  christos       * return_val = status;
    107  1.6  christos       return TRUE;
    108  1.6  christos     }
    109  1.6  christos   else
    110  1.6  christos     {
    111  1.6  christos       * return_val = 0;
    112  1.6  christos       return FALSE;
    113  1.1  christos     }
    114  1.1  christos }
    115  1.1  christos 
    116  1.1  christos static int
    117  1.1  christos msp430_nooperands (struct msp430_opcode_s *opcode,
    118  1.1  christos 		   bfd_vma addr ATTRIBUTE_UNUSED,
    119  1.1  christos 		   unsigned short insn ATTRIBUTE_UNUSED,
    120  1.1  christos 		   char *comm,
    121  1.1  christos 		   int *cycles)
    122  1.1  christos {
    123  1.1  christos   /* Pop with constant.  */
    124  1.1  christos   if (insn == 0x43b2)
    125  1.1  christos     return 0;
    126  1.1  christos   if (insn == opcode->bin_opcode)
    127  1.1  christos     return 2;
    128  1.1  christos 
    129  1.1  christos   if (opcode->fmt == 0)
    130  1.1  christos     {
    131  1.5  christos       if ((insn & 0x0f00) != 0x0300 || (insn & 0x0f00) != 0x0200)
    132  1.1  christos 	return 0;
    133  1.1  christos 
    134  1.1  christos       strcpy (comm, "emulated...");
    135  1.1  christos       *cycles = 1;
    136  1.1  christos     }
    137  1.1  christos   else
    138  1.1  christos     {
    139  1.1  christos       strcpy (comm, "return from interupt");
    140  1.1  christos       *cycles = 5;
    141  1.1  christos     }
    142  1.1  christos 
    143  1.1  christos   return 2;
    144  1.1  christos }
    145  1.1  christos 
    146  1.1  christos static int
    147  1.1  christos print_as2_reg_name (int regno, char * op1, char * comm1,
    148  1.1  christos 		    int c2, int c3, int cd)
    149  1.1  christos {
    150  1.1  christos   switch (regno)
    151  1.1  christos     {
    152  1.1  christos     case 2:
    153  1.1  christos       sprintf (op1, "#4");
    154  1.1  christos       sprintf (comm1, "r2 As==10");
    155  1.1  christos       return c2;
    156  1.1  christos 
    157  1.1  christos     case 3:
    158  1.1  christos       sprintf (op1, "#2");
    159  1.1  christos       sprintf (comm1, "r3 As==10");
    160  1.1  christos       return c3;
    161  1.1  christos 
    162  1.1  christos     default:
    163  1.1  christos       /* Indexed register mode @Rn.  */
    164  1.1  christos       sprintf (op1, "@r%d", regno);
    165  1.1  christos       return cd;
    166  1.1  christos     }
    167  1.1  christos }
    168  1.1  christos 
    169  1.1  christos static int
    170  1.1  christos print_as3_reg_name (int regno, char * op1, char * comm1,
    171  1.1  christos 		    int c2, int c3, int cd)
    172  1.1  christos {
    173  1.1  christos   switch (regno)
    174  1.1  christos     {
    175  1.1  christos     case 2:
    176  1.1  christos       sprintf (op1, "#8");
    177  1.1  christos       sprintf (comm1, "r2 As==11");
    178  1.1  christos       return c2;
    179  1.1  christos 
    180  1.1  christos     case 3:
    181  1.1  christos       sprintf (op1, "#-1");
    182  1.1  christos       sprintf (comm1, "r3 As==11");
    183  1.1  christos       return c3;
    184  1.1  christos 
    185  1.1  christos     default:
    186  1.1  christos       /* Post incremented @Rn+.  */
    187  1.1  christos       sprintf (op1, "@r%d+", regno);
    188  1.1  christos       return cd;
    189  1.1  christos     }
    190  1.1  christos }
    191  1.1  christos 
    192  1.1  christos static int
    193  1.1  christos msp430_singleoperand (disassemble_info *info,
    194  1.1  christos 		      struct msp430_opcode_s *opcode,
    195  1.1  christos 		      bfd_vma addr,
    196  1.1  christos 		      unsigned short insn,
    197  1.1  christos 		      char *op,
    198  1.1  christos 		      char *comm,
    199  1.1  christos 		      unsigned short extension_word,
    200  1.1  christos 		      int *cycles)
    201  1.1  christos {
    202  1.1  christos   int regs = 0, regd = 0;
    203  1.1  christos   int ad = 0, as = 0;
    204  1.1  christos   int where = 0;
    205  1.1  christos   int cmd_len = 2;
    206  1.1  christos   int dst = 0;
    207  1.1  christos   int fmt;
    208  1.1  christos   int extended_dst = extension_word & 0xf;
    209  1.1  christos 
    210  1.1  christos   regd = insn & 0x0f;
    211  1.1  christos   regs = (insn & 0x0f00) >> 8;
    212  1.1  christos   as = (insn & 0x0030) >> 4;
    213  1.1  christos   ad = (insn & 0x0080) >> 7;
    214  1.1  christos 
    215  1.1  christos   if (opcode->fmt < 0)
    216  1.1  christos     fmt = (- opcode->fmt) - 1;
    217  1.1  christos   else
    218  1.1  christos     fmt = opcode->fmt;
    219  1.1  christos 
    220  1.1  christos   switch (fmt)
    221  1.1  christos     {
    222  1.1  christos     case 0:			/* Emulated work with dst register.  */
    223  1.1  christos       if (regs != 2 && regs != 3 && regs != 1)
    224  1.1  christos 	return 0;
    225  1.1  christos 
    226  1.1  christos       /* Check if not clr insn.  */
    227  1.1  christos       if (opcode->bin_opcode == 0x4300 && (ad || as))
    228  1.1  christos 	return 0;
    229  1.1  christos 
    230  1.1  christos       /* Check if really inc, incd insns.  */
    231  1.1  christos       if ((opcode->bin_opcode & 0xff00) == 0x5300 && as == 3)
    232  1.1  christos 	return 0;
    233  1.1  christos 
    234  1.1  christos       if (ad == 0)
    235  1.1  christos 	{
    236  1.1  christos 	  *cycles = 1;
    237  1.1  christos 
    238  1.1  christos 	  /* Register.  */
    239  1.1  christos 	  if (regd == 0)
    240  1.1  christos 	    {
    241  1.1  christos 	      *cycles += 1;
    242  1.1  christos 	      sprintf (op, "r0");
    243  1.1  christos 	    }
    244  1.1  christos 	  else if (regd == 1)
    245  1.1  christos 	    sprintf (op, "r1");
    246  1.1  christos 
    247  1.1  christos 	  else if (regd == 2)
    248  1.1  christos 	    sprintf (op, "r2");
    249  1.1  christos 
    250  1.1  christos 	  else
    251  1.1  christos 	    sprintf (op, "r%d", regd);
    252  1.1  christos 	}
    253  1.1  christos       else	/* ad == 1 msp430dis_opcode.  */
    254  1.1  christos 	{
    255  1.1  christos 	  if (regd == 0)
    256  1.1  christos 	    {
    257  1.1  christos 	      /* PC relative.  */
    258  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    259  1.1  christos 		{
    260  1.6  christos 		  cmd_len += 2;
    261  1.6  christos 		  *cycles = 4;
    262  1.6  christos 		  sprintf (op, "0x%04x", dst);
    263  1.6  christos 		  sprintf (comm, "PC rel. abs addr 0x%04x",
    264  1.6  christos 			   PS ((short) (addr + 2) + dst));
    265  1.6  christos 		  if (extended_dst)
    266  1.6  christos 		    {
    267  1.6  christos 		      dst |= extended_dst << 16;
    268  1.6  christos 		      sprintf (op, "0x%05x", dst);
    269  1.6  christos 		      sprintf (comm, "PC rel. abs addr 0x%05lx",
    270  1.6  christos 			       (long)((addr + 2 + dst) & 0xfffff));
    271  1.6  christos 		    }
    272  1.1  christos 		}
    273  1.1  christos 	    }
    274  1.1  christos 	  else if (regd == 2)
    275  1.1  christos 	    {
    276  1.1  christos 	      /* Absolute.  */
    277  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    278  1.1  christos 		{
    279  1.6  christos 		  cmd_len += 2;
    280  1.6  christos 		  *cycles = 4;
    281  1.6  christos 		  sprintf (op, "&0x%04x", PS (dst));
    282  1.6  christos 		  if (extended_dst)
    283  1.6  christos 		    {
    284  1.6  christos 		      dst |= extended_dst << 16;
    285  1.6  christos 		      sprintf (op, "&0x%05x", dst & 0xfffff);
    286  1.6  christos 		    }
    287  1.1  christos 		}
    288  1.1  christos 	    }
    289  1.1  christos 	  else
    290  1.1  christos 	    {
    291  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    292  1.1  christos 		{
    293  1.6  christos 		  cmd_len += 2;
    294  1.6  christos 		  *cycles = 4;
    295  1.6  christos 		  if (extended_dst)
    296  1.6  christos 		    {
    297  1.6  christos 		      dst |= extended_dst << 16;
    298  1.6  christos 		      if (dst & 0x80000)
    299  1.6  christos 			dst |= -1U << 20;
    300  1.6  christos 		    }
    301  1.6  christos 		  sprintf (op, "%d(r%d)", dst, regd);
    302  1.1  christos 		}
    303  1.1  christos 	    }
    304  1.1  christos 	}
    305  1.1  christos       break;
    306  1.1  christos 
    307  1.1  christos     case 2:	/* rrc, push, call, swpb, rra, sxt, push, call, reti etc...  */
    308  1.1  christos       if (as == 0)
    309  1.1  christos 	{
    310  1.1  christos 	  if (regd == 3)
    311  1.1  christos 	    {
    312  1.1  christos 	      /* Constsnts.  */
    313  1.1  christos 	      sprintf (op, "#0");
    314  1.1  christos 	      sprintf (comm, "r3 As==00");
    315  1.1  christos 	    }
    316  1.1  christos 	  else
    317  1.1  christos 	    {
    318  1.1  christos 	      /* Register.  */
    319  1.1  christos 	      sprintf (op, "r%d", regd);
    320  1.1  christos 	    }
    321  1.1  christos 	  *cycles = 1;
    322  1.1  christos 	}
    323  1.1  christos       else if (as == 2)
    324  1.1  christos 	{
    325  1.1  christos 	  * cycles = print_as2_reg_name (regd, op, comm, 1, 1, 3);
    326  1.1  christos 	}
    327  1.1  christos       else if (as == 3)
    328  1.1  christos 	{
    329  1.1  christos 	  if (regd == 0)
    330  1.1  christos 	    {
    331  1.1  christos 	      *cycles = 3;
    332  1.1  christos 	      /* absolute. @pc+ */
    333  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    334  1.1  christos 		{
    335  1.6  christos 		  cmd_len += 2;
    336  1.1  christos 		  sprintf (op, "#%d", dst);
    337  1.1  christos 		  if (dst > 9 || dst < 0)
    338  1.6  christos 		    sprintf (comm, "#0x%04x", PS (dst));
    339  1.6  christos 		  if (extended_dst)
    340  1.6  christos 		    {
    341  1.6  christos 		      dst |= extended_dst << 16;
    342  1.6  christos 		      if (dst & 0x80000)
    343  1.6  christos 			dst |= -1U << 20;
    344  1.6  christos 		      sprintf (op, "#%d", dst);
    345  1.6  christos 		      if (dst > 9 || dst < 0)
    346  1.6  christos 			sprintf (comm, "#0x%05x", dst);
    347  1.6  christos 		    }
    348  1.1  christos 		}
    349  1.1  christos 	    }
    350  1.1  christos 	  else
    351  1.1  christos 	    * cycles = print_as3_reg_name (regd, op, comm, 1, 1, 3);
    352  1.1  christos 	}
    353  1.1  christos       else if (as == 1)
    354  1.1  christos 	{
    355  1.1  christos 	  *cycles = 4;
    356  1.1  christos 	  if (regd == 0)
    357  1.1  christos 	    {
    358  1.1  christos 	      /* PC relative.  */
    359  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    360  1.1  christos 		{
    361  1.6  christos 		  cmd_len += 2;
    362  1.6  christos 		  sprintf (op, "0x%04x", PS (dst));
    363  1.6  christos 		  sprintf (comm, "PC rel. 0x%04x",
    364  1.6  christos 			   PS ((short) addr + 2 + dst));
    365  1.6  christos 		  if (extended_dst)
    366  1.6  christos 		    {
    367  1.6  christos 		      dst |= extended_dst << 16;
    368  1.6  christos 		      sprintf (op, "0x%05x", dst & 0xffff);
    369  1.6  christos 		      sprintf (comm, "PC rel. 0x%05lx",
    370  1.6  christos 			       (long)((addr + 2 + dst) & 0xfffff));
    371  1.6  christos 		    }
    372  1.1  christos 		}
    373  1.1  christos 	    }
    374  1.1  christos 	  else if (regd == 2)
    375  1.1  christos 	    {
    376  1.1  christos 	      /* Absolute.  */
    377  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    378  1.1  christos 		{
    379  1.6  christos 		  cmd_len += 2;
    380  1.6  christos 		  sprintf (op, "&0x%04x", PS (dst));
    381  1.6  christos 		  if (extended_dst)
    382  1.6  christos 		    {
    383  1.6  christos 		      dst |= extended_dst << 16;
    384  1.6  christos 		      sprintf (op, "&0x%05x", dst & 0xfffff);
    385  1.6  christos 		    }
    386  1.1  christos 		}
    387  1.1  christos 	    }
    388  1.1  christos 	  else if (regd == 3)
    389  1.1  christos 	    {
    390  1.1  christos 	      *cycles = 1;
    391  1.1  christos 	      sprintf (op, "#1");
    392  1.1  christos 	      sprintf (comm, "r3 As==01");
    393  1.1  christos 	    }
    394  1.1  christos 	  else
    395  1.1  christos 	    {
    396  1.1  christos 	      /* Indexed.  */
    397  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    398  1.1  christos 		{
    399  1.6  christos 		  cmd_len += 2;
    400  1.6  christos 		  if (extended_dst)
    401  1.6  christos 		    {
    402  1.6  christos 		      dst |= extended_dst << 16;
    403  1.6  christos 		      if (dst & 0x80000)
    404  1.6  christos 			dst |= -1U << 20;
    405  1.6  christos 		    }
    406  1.6  christos 		  sprintf (op, "%d(r%d)", dst, regd);
    407  1.6  christos 		  if (dst > 9 || dst < 0)
    408  1.6  christos 		    sprintf (comm, "%05x", dst);
    409  1.1  christos 		}
    410  1.1  christos 	    }
    411  1.1  christos 	}
    412  1.1  christos       break;
    413  1.1  christos 
    414  1.1  christos     case 3:			/* Jumps.  */
    415  1.1  christos       where = insn & 0x03ff;
    416  1.1  christos       if (where & 0x200)
    417  1.1  christos 	where |= ~0x03ff;
    418  1.1  christos       if (where > 512 || where < -511)
    419  1.1  christos 	return 0;
    420  1.1  christos 
    421  1.1  christos       where *= 2;
    422  1.1  christos       sprintf (op, "$%+-8d", where + 2);
    423  1.1  christos       sprintf (comm, "abs 0x%lx", (long) (addr + 2 + where));
    424  1.1  christos       *cycles = 2;
    425  1.1  christos       return 2;
    426  1.1  christos       break;
    427  1.6  christos 
    428  1.1  christos     default:
    429  1.1  christos       cmd_len = 0;
    430  1.1  christos     }
    431  1.1  christos 
    432  1.1  christos   return cmd_len;
    433  1.1  christos }
    434  1.1  christos 
    435  1.1  christos static int
    436  1.1  christos msp430_doubleoperand (disassemble_info *info,
    437  1.1  christos 		      struct msp430_opcode_s *opcode,
    438  1.1  christos 		      bfd_vma addr,
    439  1.1  christos 		      unsigned short insn,
    440  1.1  christos 		      char *op1,
    441  1.1  christos 		      char *op2,
    442  1.1  christos 		      char *comm1,
    443  1.1  christos 		      char *comm2,
    444  1.1  christos 		      unsigned short extension_word,
    445  1.1  christos 		      int *cycles)
    446  1.1  christos {
    447  1.1  christos   int regs = 0, regd = 0;
    448  1.1  christos   int ad = 0, as = 0;
    449  1.1  christos   int cmd_len = 2;
    450  1.1  christos   int dst = 0;
    451  1.1  christos   int fmt;
    452  1.1  christos   int extended_dst = extension_word & 0xf;
    453  1.1  christos   int extended_src = (extension_word >> 7) & 0xf;
    454  1.1  christos 
    455  1.1  christos   regd = insn & 0x0f;
    456  1.1  christos   regs = (insn & 0x0f00) >> 8;
    457  1.1  christos   as = (insn & 0x0030) >> 4;
    458  1.1  christos   ad = (insn & 0x0080) >> 7;
    459  1.1  christos 
    460  1.1  christos   if (opcode->fmt < 0)
    461  1.1  christos     fmt = (- opcode->fmt) - 1;
    462  1.1  christos   else
    463  1.1  christos     fmt = opcode->fmt;
    464  1.1  christos 
    465  1.1  christos   if (fmt == 0)
    466  1.1  christos     {
    467  1.1  christos       /* Special case: rla and rlc are the only 2 emulated instructions that
    468  1.1  christos 	 fall into two operand instructions.  */
    469  1.1  christos       /* With dst, there are only:
    470  1.1  christos 	 Rm       	Register,
    471  1.1  christos          x(Rm)     	Indexed,
    472  1.1  christos          0xXXXX    	Relative,
    473  1.6  christos          &0xXXXX    	Absolute
    474  1.1  christos          emulated_ins   dst
    475  1.1  christos          basic_ins      dst, dst.  */
    476  1.1  christos 
    477  1.1  christos       if (regd != regs || as != ad)
    478  1.1  christos 	return 0;		/* May be 'data' section.  */
    479  1.1  christos 
    480  1.1  christos       if (ad == 0)
    481  1.1  christos 	{
    482  1.1  christos 	  /* Register mode.  */
    483  1.1  christos 	  if (regd == 3)
    484  1.1  christos 	    {
    485  1.6  christos 	      strcpy (comm1, _("Warning: illegal as emulation instr"));
    486  1.1  christos 	      return -1;
    487  1.1  christos 	    }
    488  1.1  christos 
    489  1.1  christos 	  sprintf (op1, "r%d", regd);
    490  1.1  christos 	  *cycles = 1;
    491  1.1  christos 	}
    492  1.1  christos       else			/* ad == 1 */
    493  1.1  christos 	{
    494  1.1  christos 	  if (regd == 0)
    495  1.1  christos 	    {
    496  1.1  christos 	      /* PC relative, Symbolic.  */
    497  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    498  1.1  christos 		{
    499  1.6  christos 		  cmd_len += 4;
    500  1.6  christos 		  *cycles = 6;
    501  1.6  christos 		  sprintf (op1, "0x%04x", PS (dst));
    502  1.6  christos 		  sprintf (comm1, "PC rel. 0x%04x",
    503  1.6  christos 			   PS ((short) addr + 2 + dst));
    504  1.6  christos 		  if (extension_word)
    505  1.6  christos 		    {
    506  1.6  christos 		      dst |= extended_dst << 16;
    507  1.6  christos 		      if (dst & 0x80000)
    508  1.6  christos 			dst |= -1U << 20;
    509  1.6  christos 		      sprintf (op1, "0x%05x", dst & 0xfffff);
    510  1.6  christos 		      sprintf (comm1, "PC rel. 0x%05lx",
    511  1.6  christos 			       (long)((addr + 2 + dst) & 0xfffff));
    512  1.6  christos 		    }
    513  1.1  christos 		}
    514  1.1  christos 	    }
    515  1.1  christos 	  else if (regd == 2)
    516  1.1  christos 	    {
    517  1.1  christos 	      /* Absolute.  */
    518  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    519  1.1  christos 		{
    520  1.6  christos 		  int src;
    521  1.6  christos 
    522  1.6  christos 		  /* If the 'src' field is not the same as the dst
    523  1.6  christos 		     then this is not an rla instruction.  */
    524  1.6  christos 		  if (msp430dis_opcode_signed (addr + 4, info, &src, comm2))
    525  1.6  christos 		    {
    526  1.6  christos 		      if (src != dst)
    527  1.6  christos 			return 0;
    528  1.6  christos 		    }
    529  1.6  christos 		  cmd_len += 4;
    530  1.6  christos 		  *cycles = 6;
    531  1.6  christos 		  sprintf (op1, "&0x%04x", PS (dst));
    532  1.6  christos 		  if (extension_word)
    533  1.6  christos 		    {
    534  1.6  christos 		      dst |= extended_dst << 16;
    535  1.6  christos 		      sprintf (op1, "&0x%05x", dst & 0xfffff);
    536  1.6  christos 		    }
    537  1.1  christos 		}
    538  1.1  christos 	    }
    539  1.1  christos 	  else
    540  1.1  christos 	    {
    541  1.1  christos 	      /* Indexed.  */
    542  1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    543  1.1  christos 		{
    544  1.6  christos 		  if (extension_word)
    545  1.6  christos 		    {
    546  1.6  christos 		      dst |= extended_dst << 16;
    547  1.6  christos 		      if (dst & 0x80000)
    548  1.6  christos 			dst |= -1U << 20;
    549  1.6  christos 		    }
    550  1.6  christos 		  cmd_len += 4;
    551  1.6  christos 		  *cycles = 6;
    552  1.6  christos 		  sprintf (op1, "%d(r%d)", dst, regd);
    553  1.6  christos 		  if (dst > 9 || dst < -9)
    554  1.6  christos 		    sprintf (comm1, "#0x%05x", dst);
    555  1.1  christos 		}
    556  1.1  christos 	    }
    557  1.1  christos 	}
    558  1.1  christos 
    559  1.1  christos       *op2 = 0;
    560  1.1  christos       *comm2 = 0;
    561  1.1  christos 
    562  1.1  christos       return cmd_len;
    563  1.1  christos     }
    564  1.1  christos 
    565  1.1  christos   /* Two operands exactly.  */
    566  1.1  christos   if (ad == 0 && regd == 3)
    567  1.1  christos     {
    568  1.1  christos       /* R2/R3 are illegal as dest: may be data section.  */
    569  1.6  christos       strcpy (comm1, _("Warning: illegal as 2-op instr"));
    570  1.1  christos       return -1;
    571  1.1  christos     }
    572  1.1  christos 
    573  1.1  christos   /* Source.  */
    574  1.1  christos   if (as == 0)
    575  1.1  christos     {
    576  1.1  christos       *cycles = 1;
    577  1.1  christos       if (regs == 3)
    578  1.1  christos 	{
    579  1.1  christos 	  /* Constants.  */
    580  1.1  christos 	  sprintf (op1, "#0");
    581  1.1  christos 	  sprintf (comm1, "r3 As==00");
    582  1.1  christos 	}
    583  1.1  christos       else
    584  1.1  christos 	{
    585  1.1  christos 	  /* Register.  */
    586  1.1  christos 	  sprintf (op1, "r%d", regs);
    587  1.1  christos 	}
    588  1.1  christos     }
    589  1.1  christos   else if (as == 2)
    590  1.1  christos     {
    591  1.1  christos       * cycles = print_as2_reg_name (regs, op1, comm1, 1, 1, regs == 0 ? 3 : 2);
    592  1.1  christos     }
    593  1.1  christos   else if (as == 3)
    594  1.1  christos     {
    595  1.1  christos       if (regs == 0)
    596  1.1  christos 	{
    597  1.1  christos 	  *cycles = 3;
    598  1.1  christos 	  /* Absolute. @pc+.  */
    599  1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    600  1.6  christos 	    {
    601  1.6  christos 	      cmd_len += 2;
    602  1.1  christos 	      sprintf (op1, "#%d", dst);
    603  1.1  christos 	      if (dst > 9 || dst < 0)
    604  1.6  christos 		sprintf (comm1, "#0x%04x", PS (dst));
    605  1.6  christos 	      if (extension_word)
    606  1.6  christos 		{
    607  1.6  christos 		  dst &= 0xffff;
    608  1.6  christos 		  dst |= extended_src << 16;
    609  1.6  christos 		  if (dst & 0x80000)
    610  1.6  christos 		    dst |= -1U << 20;
    611  1.6  christos 		  sprintf (op1, "#%d", dst);
    612  1.6  christos 		  if (dst > 9 || dst < 0)
    613  1.6  christos 		    sprintf (comm1, "0x%05x", dst & 0xfffff);
    614  1.6  christos 		}
    615  1.1  christos 	    }
    616  1.1  christos 	}
    617  1.1  christos       else
    618  1.1  christos 	* cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
    619  1.1  christos     }
    620  1.1  christos   else if (as == 1)
    621  1.1  christos     {
    622  1.1  christos       if (regs == 0)
    623  1.1  christos 	{
    624  1.1  christos 	  *cycles = 4;
    625  1.1  christos 	  /* PC relative.  */
    626  1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    627  1.6  christos 	    {
    628  1.6  christos 	      cmd_len += 2;
    629  1.6  christos 	      sprintf (op1, "0x%04x", PS (dst));
    630  1.6  christos 	      sprintf (comm1, "PC rel. 0x%04x",
    631  1.6  christos 		       PS ((short) addr + 2 + dst));
    632  1.6  christos 	      if (extension_word)
    633  1.6  christos 		{
    634  1.6  christos 		  dst &= 0xffff;
    635  1.6  christos 		  dst |= extended_src << 16;
    636  1.6  christos 		  if (dst & 0x80000)
    637  1.6  christos 		    dst |= -1U << 20;
    638  1.6  christos 		  sprintf (op1, "0x%05x", dst & 0xfffff);
    639  1.6  christos 		  sprintf (comm1, "PC rel. 0x%05lx",
    640  1.6  christos 			   (long) ((addr + 2 + dst) & 0xfffff));
    641  1.6  christos 		}
    642  1.1  christos 	    }
    643  1.1  christos 	}
    644  1.1  christos       else if (regs == 2)
    645  1.1  christos 	{
    646  1.1  christos 	  *cycles = 2;
    647  1.1  christos 	  /* Absolute.  */
    648  1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    649  1.6  christos 	    {
    650  1.6  christos 	      cmd_len += 2;
    651  1.6  christos 	      sprintf (op1, "&0x%04x", PS (dst));
    652  1.6  christos 	      sprintf (comm1, "0x%04x", PS (dst));
    653  1.6  christos 	      if (extension_word)
    654  1.6  christos 		{
    655  1.6  christos 		  dst &= 0xffff;
    656  1.6  christos 		  dst |= extended_src << 16;
    657  1.6  christos 		  sprintf (op1, "&0x%05x", dst & 0xfffff);
    658  1.6  christos 		  * comm1 = 0;
    659  1.6  christos 		}
    660  1.1  christos 	    }
    661  1.1  christos 	}
    662  1.1  christos       else if (regs == 3)
    663  1.1  christos 	{
    664  1.1  christos 	  *cycles = 1;
    665  1.1  christos 	  sprintf (op1, "#1");
    666  1.1  christos 	  sprintf (comm1, "r3 As==01");
    667  1.1  christos 	}
    668  1.1  christos       else
    669  1.1  christos 	{
    670  1.1  christos 	  *cycles = 3;
    671  1.1  christos 	  /* Indexed.  */
    672  1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    673  1.1  christos 	    {
    674  1.6  christos 	      cmd_len += 2;
    675  1.6  christos 	      if (extension_word)
    676  1.6  christos 		{
    677  1.6  christos 		  dst &= 0xffff;
    678  1.6  christos 		  dst |= extended_src << 16;
    679  1.6  christos 		  if (dst & 0x80000)
    680  1.6  christos 		    dst |= -1U << 20;
    681  1.6  christos 		}
    682  1.6  christos 	      sprintf (op1, "%d(r%d)", dst, regs);
    683  1.6  christos 	      if (dst > 9 || dst < -9)
    684  1.6  christos 		sprintf (comm1, "0x%05x", dst);
    685  1.6  christos 	    }
    686  1.1  christos 	}
    687  1.1  christos     }
    688  1.1  christos 
    689  1.1  christos   /* Destination. Special care needed on addr + XXXX.  */
    690  1.1  christos 
    691  1.1  christos   if (ad == 0)
    692  1.1  christos     {
    693  1.1  christos       /* Register.  */
    694  1.1  christos       if (regd == 0)
    695  1.1  christos 	{
    696  1.1  christos 	  *cycles += 1;
    697  1.1  christos 	  sprintf (op2, "r0");
    698  1.1  christos 	}
    699  1.1  christos       else if (regd == 1)
    700  1.1  christos 	sprintf (op2, "r1");
    701  1.1  christos 
    702  1.1  christos       else if (regd == 2)
    703  1.1  christos 	sprintf (op2, "r2");
    704  1.1  christos 
    705  1.1  christos       else
    706  1.1  christos 	sprintf (op2, "r%d", regd);
    707  1.1  christos     }
    708  1.1  christos   else	/* ad == 1.  */
    709  1.1  christos     {
    710  1.1  christos       * cycles += 3;
    711  1.1  christos 
    712  1.1  christos       if (regd == 0)
    713  1.1  christos 	{
    714  1.1  christos 	  /* PC relative.  */
    715  1.1  christos 	  *cycles += 1;
    716  1.6  christos 	  if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
    717  1.6  christos 	    {
    718  1.6  christos 	      sprintf (op2, "0x%04x", PS (dst));
    719  1.6  christos 	      sprintf (comm2, "PC rel. 0x%04x",
    720  1.6  christos 		       PS ((short) addr + cmd_len + dst));
    721  1.6  christos 	      if (extension_word)
    722  1.6  christos 		{
    723  1.6  christos 		  dst |= extended_dst << 16;
    724  1.6  christos 		  if (dst & 0x80000)
    725  1.6  christos 		    dst |= -1U << 20;
    726  1.6  christos 		  sprintf (op2, "0x%05x", dst & 0xfffff);
    727  1.6  christos 		  sprintf (comm2, "PC rel. 0x%05lx",
    728  1.6  christos 			   (long)((addr + cmd_len + dst) & 0xfffff));
    729  1.6  christos 		}
    730  1.1  christos 	    }
    731  1.1  christos 	  cmd_len += 2;
    732  1.1  christos 	}
    733  1.1  christos       else if (regd == 2)
    734  1.1  christos 	{
    735  1.1  christos 	  /* Absolute.  */
    736  1.6  christos 	  if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
    737  1.1  christos 	    {
    738  1.6  christos 	      cmd_len += 2;
    739  1.6  christos 	      sprintf (op2, "&0x%04x", PS (dst));
    740  1.6  christos 	      if (extension_word)
    741  1.6  christos 		{
    742  1.6  christos 		  dst |= extended_dst << 16;
    743  1.6  christos 		  sprintf (op2, "&0x%05x", dst & 0xfffff);
    744  1.6  christos 		}
    745  1.1  christos 	    }
    746  1.1  christos 	}
    747  1.1  christos       else
    748  1.1  christos 	{
    749  1.6  christos 	  if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
    750  1.6  christos 	    {
    751  1.6  christos 	      cmd_len += 2;
    752  1.1  christos 	      if (dst > 9 || dst < 0)
    753  1.6  christos 		sprintf (comm2, "0x%04x", PS (dst));
    754  1.6  christos 	      if (extension_word)
    755  1.6  christos 		{
    756  1.6  christos 		  dst |= extended_dst << 16;
    757  1.6  christos 		  if (dst & 0x80000)
    758  1.6  christos 		    dst |= -1U << 20;
    759  1.6  christos 		  if (dst > 9 || dst < 0)
    760  1.6  christos 		    sprintf (comm2, "0x%05x", dst & 0xfffff);
    761  1.6  christos 		}
    762  1.6  christos 	      sprintf (op2, "%d(r%d)", dst, regd);
    763  1.1  christos 	    }
    764  1.1  christos 	}
    765  1.1  christos     }
    766  1.1  christos 
    767  1.1  christos   return cmd_len;
    768  1.1  christos }
    769  1.1  christos 
    770  1.1  christos static int
    771  1.1  christos msp430_branchinstr (disassemble_info *info,
    772  1.1  christos 		    struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED,
    773  1.1  christos 		    bfd_vma addr ATTRIBUTE_UNUSED,
    774  1.1  christos 		    unsigned short insn,
    775  1.1  christos 		    char *op1,
    776  1.1  christos 		    char *comm1,
    777  1.1  christos 		    int *cycles)
    778  1.1  christos {
    779  1.1  christos   int regs = 0, regd = 0;
    780  1.1  christos   int as = 0;
    781  1.1  christos   int cmd_len = 2;
    782  1.6  christos   int dst = 0;
    783  1.6  christos   unsigned short udst = 0;
    784  1.1  christos 
    785  1.1  christos   regd = insn & 0x0f;
    786  1.1  christos   regs = (insn & 0x0f00) >> 8;
    787  1.1  christos   as = (insn & 0x0030) >> 4;
    788  1.1  christos 
    789  1.1  christos   if (regd != 0)	/* Destination register is not a PC.  */
    790  1.1  christos     return 0;
    791  1.1  christos 
    792  1.1  christos   /* dst is a source register.  */
    793  1.1  christos   if (as == 0)
    794  1.1  christos     {
    795  1.1  christos       /* Constants.  */
    796  1.1  christos       if (regs == 3)
    797  1.1  christos 	{
    798  1.1  christos 	  *cycles = 1;
    799  1.1  christos 	  sprintf (op1, "#0");
    800  1.1  christos 	  sprintf (comm1, "r3 As==00");
    801  1.1  christos 	}
    802  1.1  christos       else
    803  1.1  christos 	{
    804  1.1  christos 	  /* Register.  */
    805  1.1  christos 	  *cycles = 1;
    806  1.1  christos 	  sprintf (op1, "r%d", regs);
    807  1.1  christos 	}
    808  1.1  christos     }
    809  1.1  christos   else if (as == 2)
    810  1.1  christos     {
    811  1.1  christos       * cycles = print_as2_reg_name (regs, op1, comm1, 2, 1, 2);
    812  1.1  christos     }
    813  1.1  christos   else if (as == 3)
    814  1.1  christos     {
    815  1.1  christos       if (regs == 0)
    816  1.1  christos 	{
    817  1.1  christos 	  /* Absolute. @pc+  */
    818  1.1  christos 	  *cycles = 3;
    819  1.6  christos 	  if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
    820  1.6  christos 	    {
    821  1.6  christos 	      cmd_len += 2;
    822  1.6  christos 	      sprintf (op1, "#0x%04x", PS (udst));
    823  1.6  christos 	    }
    824  1.1  christos 	}
    825  1.1  christos       else
    826  1.1  christos 	* cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
    827  1.1  christos     }
    828  1.1  christos   else if (as == 1)
    829  1.1  christos     {
    830  1.1  christos       * cycles = 3;
    831  1.1  christos 
    832  1.1  christos       if (regs == 0)
    833  1.1  christos 	{
    834  1.1  christos 	  /* PC relative.  */
    835  1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    836  1.6  christos 	    {
    837  1.6  christos 	      cmd_len += 2;
    838  1.6  christos 	      (*cycles)++;
    839  1.6  christos 	      sprintf (op1, "0x%04x", PS (dst));
    840  1.6  christos 	      sprintf (comm1, "PC rel. 0x%04x",
    841  1.6  christos 		       PS ((short) addr + 2 + dst));
    842  1.6  christos 	    }
    843  1.1  christos 	}
    844  1.1  christos       else if (regs == 2)
    845  1.1  christos 	{
    846  1.1  christos 	  /* Absolute.  */
    847  1.6  christos 	  if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
    848  1.6  christos 	    {
    849  1.6  christos 	      cmd_len += 2;
    850  1.6  christos 	      sprintf (op1, "&0x%04x", PS (udst));
    851  1.6  christos 	    }
    852  1.1  christos 	}
    853  1.1  christos       else if (regs == 3)
    854  1.1  christos 	{
    855  1.1  christos 	  (*cycles)--;
    856  1.1  christos 	  sprintf (op1, "#1");
    857  1.1  christos 	  sprintf (comm1, "r3 As==01");
    858  1.1  christos 	}
    859  1.1  christos       else
    860  1.1  christos 	{
    861  1.1  christos 	  /* Indexed.  */
    862  1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    863  1.6  christos 	    {
    864  1.6  christos 	      cmd_len += 2;
    865  1.6  christos 	      sprintf (op1, "%d(r%d)", dst, regs);
    866  1.6  christos 	    }
    867  1.1  christos 	}
    868  1.1  christos     }
    869  1.1  christos 
    870  1.1  christos   return cmd_len;
    871  1.1  christos }
    872  1.1  christos 
    873  1.1  christos static int
    874  1.1  christos msp430x_calla_instr (disassemble_info * info,
    875  1.1  christos 		     bfd_vma            addr,
    876  1.1  christos 		     unsigned short     insn,
    877  1.1  christos 		     char *             op1,
    878  1.1  christos 		     char *             comm1,
    879  1.1  christos 		     int *              cycles)
    880  1.1  christos {
    881  1.1  christos   unsigned int   ureg = insn & 0xf;
    882  1.1  christos   int            reg = insn & 0xf;
    883  1.1  christos   int            am = (insn & 0xf0) >> 4;
    884  1.1  christos   int            cmd_len = 2;
    885  1.1  christos   unsigned short udst = 0;
    886  1.6  christos   int            dst = 0;
    887  1.1  christos 
    888  1.1  christos   switch (am)
    889  1.1  christos     {
    890  1.1  christos     case 4: /* CALLA Rdst */
    891  1.1  christos       *cycles = 1;
    892  1.1  christos       sprintf (op1, "r%d", reg);
    893  1.1  christos       break;
    894  1.1  christos 
    895  1.1  christos     case 5: /* CALLA x(Rdst) */
    896  1.1  christos       *cycles = 3;
    897  1.6  christos       if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    898  1.6  christos 	{
    899  1.6  christos 	  cmd_len += 2;
    900  1.6  christos 	  sprintf (op1, "%d(r%d)", dst, reg);
    901  1.6  christos 	  if (reg == 0)
    902  1.6  christos 	    sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst));
    903  1.6  christos 	  else
    904  1.6  christos 	    sprintf (comm1, "0x%05x", dst);
    905  1.6  christos 	}
    906  1.1  christos       break;
    907  1.1  christos 
    908  1.1  christos     case 6: /* CALLA @Rdst */
    909  1.1  christos       *cycles = 2;
    910  1.1  christos       sprintf (op1, "@r%d", reg);
    911  1.1  christos       break;
    912  1.1  christos 
    913  1.1  christos     case 7: /* CALLA @Rdst+ */
    914  1.1  christos       *cycles = 2;
    915  1.1  christos       sprintf (op1, "@r%d+", reg);
    916  1.1  christos       break;
    917  1.1  christos 
    918  1.1  christos     case 8: /* CALLA &abs20 */
    919  1.6  christos       if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
    920  1.6  christos 	{
    921  1.6  christos 	  cmd_len += 2;
    922  1.6  christos 	  *cycles = 4;
    923  1.6  christos 	  sprintf (op1, "&%d", (ureg << 16) + udst);
    924  1.6  christos 	  sprintf (comm1, "0x%05x", (ureg << 16) + udst);
    925  1.6  christos 	}
    926  1.1  christos       break;
    927  1.1  christos 
    928  1.1  christos     case 9: /* CALLA pcrel-sym */
    929  1.6  christos       if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    930  1.6  christos 	{
    931  1.6  christos 	  cmd_len += 2;
    932  1.6  christos 	  *cycles = 4;
    933  1.6  christos 	  sprintf (op1, "%d(PC)", (reg << 16) + dst);
    934  1.6  christos 	  sprintf (comm1, "PC rel. 0x%05lx",
    935  1.6  christos 		   (long) (addr + 2 + dst + (reg << 16)));
    936  1.6  christos 	}
    937  1.1  christos       break;
    938  1.1  christos 
    939  1.1  christos     case 11: /* CALLA #imm20 */
    940  1.6  christos       if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
    941  1.6  christos 	{
    942  1.6  christos 	  cmd_len += 2;
    943  1.6  christos 	  *cycles = 4;
    944  1.6  christos 	  sprintf (op1, "#%d", (ureg << 16) + udst);
    945  1.6  christos 	  sprintf (comm1, "0x%05x", (ureg << 16) + udst);
    946  1.6  christos 	}
    947  1.1  christos       break;
    948  1.1  christos 
    949  1.1  christos     default:
    950  1.6  christos       strcpy (comm1, _("Warning: unrecognised CALLA addressing mode"));
    951  1.1  christos       return -1;
    952  1.1  christos     }
    953  1.1  christos 
    954  1.1  christos   return cmd_len;
    955  1.1  christos }
    956  1.1  christos 
    957  1.1  christos int
    958  1.1  christos print_insn_msp430 (bfd_vma addr, disassemble_info *info)
    959  1.1  christos {
    960  1.1  christos   void *stream = info->stream;
    961  1.1  christos   fprintf_ftype prin = info->fprintf_func;
    962  1.1  christos   struct msp430_opcode_s *opcode;
    963  1.1  christos   char op1[32], op2[32], comm1[64], comm2[64];
    964  1.1  christos   int cmd_len = 0;
    965  1.1  christos   unsigned short insn;
    966  1.1  christos   int cycles = 0;
    967  1.1  christos   char *bc = "";
    968  1.1  christos   unsigned short extension_word = 0;
    969  1.6  christos   unsigned short bits;
    970  1.1  christos 
    971  1.6  christos   if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
    972  1.1  christos     {
    973  1.1  christos       prin (stream, ".word	0xffff;	????");
    974  1.1  christos       return 2;
    975  1.1  christos     }
    976  1.1  christos 
    977  1.1  christos   if (((int) addr & 0xffff) > 0xffdf)
    978  1.1  christos     {
    979  1.1  christos       (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn);
    980  1.1  christos       return 2;
    981  1.1  christos     }
    982  1.1  christos 
    983  1.1  christos   *comm1 = 0;
    984  1.1  christos   *comm2 = 0;
    985  1.1  christos 
    986  1.1  christos   /* Check for an extension word.  */
    987  1.1  christos   if ((insn & 0xf800) == 0x1800)
    988  1.1  christos     {
    989  1.1  christos       extension_word = insn;
    990  1.1  christos       addr += 2;
    991  1.6  christos       if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
    992  1.1  christos 	{
    993  1.1  christos 	  prin (stream, ".word	0x%04x, 0xffff;	????",
    994  1.1  christos 		extension_word);
    995  1.1  christos 	  return 4;
    996  1.1  christos 	}
    997  1.1  christos    }
    998  1.1  christos 
    999  1.1  christos   for (opcode = msp430_opcodes; opcode->name; opcode++)
   1000  1.1  christos     {
   1001  1.1  christos       if ((insn & opcode->bin_mask) == opcode->bin_opcode
   1002  1.1  christos 	  && opcode->bin_opcode != 0x9300)
   1003  1.1  christos 	{
   1004  1.1  christos 	  *op1 = 0;
   1005  1.1  christos 	  *op2 = 0;
   1006  1.1  christos 	  *comm1 = 0;
   1007  1.1  christos 	  *comm2 = 0;
   1008  1.1  christos 
   1009  1.1  christos 	  /* r0 as destination. Ad should be zero.  */
   1010  1.1  christos 	  if (opcode->insn_opnumb == 3
   1011  1.1  christos 	      && (insn & 0x000f) == 0
   1012  1.1  christos 	      && (insn & 0x0080) == 0)
   1013  1.1  christos 	    {
   1014  1.1  christos 	      cmd_len +=
   1015  1.1  christos 		msp430_branchinstr (info, opcode, addr, insn, op1, comm1,
   1016  1.1  christos 				    &cycles);
   1017  1.1  christos 	      if (cmd_len)
   1018  1.1  christos 		break;
   1019  1.1  christos 	    }
   1020  1.1  christos 
   1021  1.1  christos 	  switch (opcode->insn_opnumb)
   1022  1.1  christos 	    {
   1023  1.1  christos 	      int n;
   1024  1.1  christos 	      int reg;
   1025  1.1  christos 
   1026  1.1  christos 	    case 4:
   1027  1.1  christos 	      cmd_len += msp430x_calla_instr (info, addr, insn,
   1028  1.1  christos 					      op1, comm1, & cycles);
   1029  1.1  christos 	      break;
   1030  1.1  christos 
   1031  1.1  christos 	    case 5: /* PUSHM/POPM */
   1032  1.1  christos 	      n = (insn & 0xf0) >> 4;
   1033  1.1  christos 	      reg = (insn & 0xf);
   1034  1.1  christos 
   1035  1.1  christos 	      sprintf (op1, "#%d", n + 1);
   1036  1.1  christos 	      if (opcode->bin_opcode == 0x1400)
   1037  1.1  christos 		/* PUSHM */
   1038  1.1  christos 		sprintf (op2, "r%d", reg);
   1039  1.1  christos 	      else
   1040  1.1  christos 		/* POPM */
   1041  1.1  christos 		sprintf (op2, "r%d", reg + n);
   1042  1.1  christos 	      if (insn & 0x100)
   1043  1.1  christos 		sprintf (comm1, "16-bit words");
   1044  1.1  christos 	      else
   1045  1.1  christos 		{
   1046  1.1  christos 		  sprintf (comm1, "20-bit words");
   1047  1.1  christos 		  bc =".a";
   1048  1.1  christos 		}
   1049  1.6  christos 
   1050  1.1  christos 	      cycles = 2; /*FIXME*/
   1051  1.1  christos 	      cmd_len = 2;
   1052  1.1  christos 	      break;
   1053  1.1  christos 
   1054  1.1  christos 	    case 6: /* RRAM, RRCM, RRUM, RLAM.  */
   1055  1.1  christos 	      n = ((insn >> 10) & 0x3) + 1;
   1056  1.1  christos 	      reg = (insn & 0xf);
   1057  1.1  christos 	      if ((insn & 0x10) == 0)
   1058  1.1  christos 		bc =".a";
   1059  1.1  christos 	      sprintf (op1, "#%d", n);
   1060  1.1  christos 	      sprintf (op2, "r%d", reg);
   1061  1.1  christos 	      cycles = 2; /*FIXME*/
   1062  1.1  christos 	      cmd_len = 2;
   1063  1.1  christos 	      break;
   1064  1.1  christos 
   1065  1.1  christos 	    case 8: /* ADDA, CMPA, SUBA.  */
   1066  1.1  christos 	      reg = (insn & 0xf);
   1067  1.1  christos 	      n = (insn >> 8) & 0xf;
   1068  1.1  christos 	      if (insn & 0x40)
   1069  1.1  christos 		{
   1070  1.1  christos 		  sprintf (op1, "r%d", n);
   1071  1.1  christos 		  cmd_len = 2;
   1072  1.1  christos 		}
   1073  1.1  christos 	      else
   1074  1.1  christos 		{
   1075  1.1  christos 		  n <<= 16;
   1076  1.6  christos 		  if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
   1077  1.6  christos 		    {
   1078  1.6  christos 		      n |= bits;
   1079  1.6  christos 		      sprintf (op1, "#%d", n);
   1080  1.6  christos 		      if (n > 9 || n < 0)
   1081  1.6  christos 			sprintf (comm1, "0x%05x", n);
   1082  1.6  christos 		    }
   1083  1.1  christos 		  cmd_len = 4;
   1084  1.1  christos 		}
   1085  1.1  christos 	      sprintf (op2, "r%d", reg);
   1086  1.1  christos 	      cycles = 2; /*FIXME*/
   1087  1.1  christos 	      break;
   1088  1.1  christos 
   1089  1.1  christos 	    case 9: /* MOVA */
   1090  1.1  christos 	      reg = (insn & 0xf);
   1091  1.1  christos 	      n = (insn >> 8) & 0xf;
   1092  1.1  christos 	      switch ((insn >> 4) & 0xf)
   1093  1.1  christos 		{
   1094  1.1  christos 		case 0: /* MOVA @Rsrc, Rdst */
   1095  1.1  christos 		  cmd_len = 2;
   1096  1.1  christos 		  sprintf (op1, "@r%d", n);
   1097  1.1  christos 		  if (strcmp (opcode->name, "bra") != 0)
   1098  1.1  christos 		    sprintf (op2, "r%d", reg);
   1099  1.1  christos 		  break;
   1100  1.6  christos 
   1101  1.1  christos 		case 1: /* MOVA @Rsrc+, Rdst */
   1102  1.1  christos 		  cmd_len = 2;
   1103  1.1  christos 		  if (strcmp (opcode->name, "reta") != 0)
   1104  1.1  christos 		    {
   1105  1.1  christos 		      sprintf (op1, "@r%d+", n);
   1106  1.1  christos 		      if (strcmp (opcode->name, "bra") != 0)
   1107  1.1  christos 			sprintf (op2, "r%d", reg);
   1108  1.1  christos 		    }
   1109  1.1  christos 		  break;
   1110  1.6  christos 
   1111  1.1  christos 		case 2: /* MOVA &abs20, Rdst */
   1112  1.1  christos 		  cmd_len = 4;
   1113  1.1  christos 		  n <<= 16;
   1114  1.6  christos 		  if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
   1115  1.6  christos 		    {
   1116  1.6  christos 		      n |= bits;
   1117  1.6  christos 		      sprintf (op1, "&%d", n);
   1118  1.6  christos 		      if (n > 9 || n < 0)
   1119  1.6  christos 			sprintf (comm1, "0x%05x", n);
   1120  1.6  christos 		      if (strcmp (opcode->name, "bra") != 0)
   1121  1.6  christos 			sprintf (op2, "r%d", reg);
   1122  1.6  christos 		    }
   1123  1.1  christos 		  break;
   1124  1.6  christos 
   1125  1.1  christos 		case 3: /* MOVA x(Rsrc), Rdst */
   1126  1.1  christos 		  cmd_len = 4;
   1127  1.1  christos 		  if (strcmp (opcode->name, "bra") != 0)
   1128  1.1  christos 		    sprintf (op2, "r%d", reg);
   1129  1.1  christos 		  reg = n;
   1130  1.6  christos 		  if (msp430dis_opcode_signed (addr + 2, info, &n, comm1))
   1131  1.6  christos 		    {
   1132  1.6  christos 		      sprintf (op1, "%d(r%d)", n, reg);
   1133  1.6  christos 		      if (n > 9 || n < 0)
   1134  1.6  christos 			{
   1135  1.6  christos 			  if (reg == 0)
   1136  1.6  christos 			    sprintf (comm1, "PC rel. 0x%05lx",
   1137  1.6  christos 				     (long) (addr + 2 + n));
   1138  1.6  christos 			  else
   1139  1.6  christos 			    sprintf (comm1, "0x%05x", n);
   1140  1.6  christos 			}
   1141  1.1  christos 		    }
   1142  1.1  christos 		  break;
   1143  1.1  christos 
   1144  1.1  christos 		case 6: /* MOVA Rsrc, &abs20 */
   1145  1.1  christos 		  cmd_len = 4;
   1146  1.1  christos 		  reg <<= 16;
   1147  1.6  christos 		  if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm2))
   1148  1.6  christos 		    {
   1149  1.6  christos 		      reg |= bits;
   1150  1.6  christos 		      sprintf (op1, "r%d", n);
   1151  1.6  christos 		      sprintf (op2, "&%d", reg);
   1152  1.6  christos 		      if (reg > 9 || reg < 0)
   1153  1.6  christos 			sprintf (comm2, "0x%05x", reg);
   1154  1.6  christos 		    }
   1155  1.1  christos 		  break;
   1156  1.1  christos 
   1157  1.1  christos 		case 7: /* MOVA Rsrc, x(Rdst) */
   1158  1.1  christos 		  cmd_len = 4;
   1159  1.1  christos 		  sprintf (op1, "r%d", n);
   1160  1.6  christos 		  if (msp430dis_opcode_signed (addr + 2, info, &n, comm2))
   1161  1.6  christos 		    {
   1162  1.6  christos 		      sprintf (op2, "%d(r%d)", n, reg);
   1163  1.6  christos 		      if (n > 9 || n < 0)
   1164  1.6  christos 			{
   1165  1.6  christos 			  if (reg == 0)
   1166  1.6  christos 			    sprintf (comm2, "PC rel. 0x%05lx",
   1167  1.6  christos 				     (long) (addr + 2 + n));
   1168  1.6  christos 			  else
   1169  1.6  christos 			    sprintf (comm2, "0x%05x", n);
   1170  1.6  christos 			}
   1171  1.1  christos 		    }
   1172  1.1  christos 		  break;
   1173  1.6  christos 
   1174  1.1  christos 		case 8: /* MOVA #imm20, Rdst */
   1175  1.1  christos 		  cmd_len = 4;
   1176  1.1  christos 		  n <<= 16;
   1177  1.6  christos 		  if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
   1178  1.6  christos 		    {
   1179  1.6  christos 		      n |= bits;
   1180  1.6  christos 		      if (n & 0x80000)
   1181  1.6  christos 			n |= -1U << 20;
   1182  1.6  christos 		      sprintf (op1, "#%d", n);
   1183  1.6  christos 		      if (n > 9 || n < 0)
   1184  1.6  christos 			sprintf (comm1, "0x%05x", n);
   1185  1.6  christos 		      if (strcmp (opcode->name, "bra") != 0)
   1186  1.6  christos 			sprintf (op2, "r%d", reg);
   1187  1.6  christos 		    }
   1188  1.1  christos 		  break;
   1189  1.6  christos 
   1190  1.1  christos 		case 12: /* MOVA Rsrc, Rdst */
   1191  1.1  christos 		  cmd_len = 2;
   1192  1.1  christos 		  sprintf (op1, "r%d", n);
   1193  1.1  christos 		  if (strcmp (opcode->name, "bra") != 0)
   1194  1.1  christos 		    sprintf (op2, "r%d", reg);
   1195  1.1  christos 		  break;
   1196  1.1  christos 
   1197  1.1  christos 		default:
   1198  1.1  christos 		  break;
   1199  1.1  christos 		}
   1200  1.1  christos 	      cycles = 2; /* FIXME */
   1201  1.1  christos 	      break;
   1202  1.1  christos 	    }
   1203  1.1  christos 
   1204  1.1  christos 	  if (cmd_len)
   1205  1.1  christos 	    break;
   1206  1.1  christos 
   1207  1.1  christos 	  switch (opcode->insn_opnumb)
   1208  1.1  christos 	    {
   1209  1.1  christos 	    case 0:
   1210  1.1  christos 	      cmd_len += msp430_nooperands (opcode, addr, insn, comm1, &cycles);
   1211  1.1  christos 	      break;
   1212  1.1  christos 	    case 2:
   1213  1.1  christos 	      cmd_len +=
   1214  1.1  christos 		msp430_doubleoperand (info, opcode, addr, insn, op1, op2,
   1215  1.1  christos 				      comm1, comm2,
   1216  1.1  christos 				      extension_word,
   1217  1.1  christos 				      &cycles);
   1218  1.1  christos 	      if (insn & BYTE_OPERATION)
   1219  1.1  christos 		{
   1220  1.1  christos 		  if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
   1221  1.1  christos 		    bc = ".a";
   1222  1.1  christos 		  else
   1223  1.1  christos 		    bc = ".b";
   1224  1.1  christos 		}
   1225  1.1  christos 	      else if (extension_word)
   1226  1.1  christos 		{
   1227  1.6  christos 		  if (extension_word & BYTE_OPERATION)
   1228  1.1  christos 		    bc = ".w";
   1229  1.1  christos 		  else
   1230  1.1  christos 		    {
   1231  1.1  christos 		      bc = ".?";
   1232  1.6  christos 		      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
   1233  1.1  christos 		    }
   1234  1.1  christos 		}
   1235  1.6  christos 
   1236  1.1  christos 	      break;
   1237  1.1  christos 	    case 1:
   1238  1.1  christos 	      cmd_len +=
   1239  1.1  christos 		msp430_singleoperand (info, opcode, addr, insn, op1, comm1,
   1240  1.1  christos 				      extension_word,
   1241  1.1  christos 				      &cycles);
   1242  1.1  christos 	      if (extension_word
   1243  1.1  christos 		  && (strcmp (opcode->name, "swpb") == 0
   1244  1.1  christos 		      || strcmp (opcode->name, "sxt") == 0))
   1245  1.1  christos 		{
   1246  1.1  christos 		  if (insn & BYTE_OPERATION)
   1247  1.1  christos 		    {
   1248  1.1  christos 		      bc = ".?";
   1249  1.6  christos 		      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
   1250  1.1  christos 		    }
   1251  1.1  christos 		  else if (extension_word & BYTE_OPERATION)
   1252  1.1  christos 		    bc = ".w";
   1253  1.1  christos 		  else
   1254  1.1  christos 		    bc = ".a";
   1255  1.1  christos 		}
   1256  1.1  christos 	      else if (insn & BYTE_OPERATION && opcode->fmt != 3)
   1257  1.1  christos 		{
   1258  1.1  christos 		  if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
   1259  1.1  christos 		    bc = ".a";
   1260  1.1  christos 		  else
   1261  1.1  christos 		    bc = ".b";
   1262  1.1  christos 		}
   1263  1.1  christos 	      else if (extension_word)
   1264  1.1  christos 		{
   1265  1.1  christos 		  if (extension_word & (1 << 6))
   1266  1.1  christos 		    bc = ".w";
   1267  1.1  christos 		  else
   1268  1.1  christos 		    {
   1269  1.1  christos 		      bc = ".?";
   1270  1.6  christos 		      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
   1271  1.1  christos 		    }
   1272  1.1  christos 		}
   1273  1.1  christos 	      break;
   1274  1.1  christos 	    default:
   1275  1.1  christos 	      break;
   1276  1.1  christos 	    }
   1277  1.1  christos 	}
   1278  1.1  christos 
   1279  1.1  christos       if (cmd_len)
   1280  1.1  christos 	break;
   1281  1.1  christos     }
   1282  1.1  christos 
   1283  1.1  christos   if (cmd_len < 1)
   1284  1.1  christos     {
   1285  1.1  christos       /* Unknown opcode, or invalid combination of operands.  */
   1286  1.1  christos       if (extension_word)
   1287  1.1  christos 	{
   1288  1.1  christos 	  prin (stream, ".word	0x%04x, 0x%04x;	????", extension_word, PS (insn));
   1289  1.1  christos 	  if (*comm1)
   1290  1.1  christos 	    prin (stream, "\t %s", comm1);
   1291  1.1  christos 	  return 4;
   1292  1.1  christos 	}
   1293  1.1  christos       (*prin) (stream, ".word	0x%04x;	????", PS (insn));
   1294  1.1  christos       return 2;
   1295  1.1  christos     }
   1296  1.1  christos 
   1297  1.1  christos   /* Display the repeat count (if set) for extended register mode.  */
   1298  1.1  christos   if (cmd_len == 2 && ((extension_word & 0xf) != 0))
   1299  1.1  christos     {
   1300  1.1  christos       if (extension_word & (1 << 7))
   1301  1.1  christos 	prin (stream, "rpt r%d { ", extension_word & 0xf);
   1302  1.1  christos       else
   1303  1.1  christos 	prin (stream, "rpt #%d { ", (extension_word & 0xf) + 1);
   1304  1.1  christos     }
   1305  1.1  christos 
   1306  1.6  christos   /* Special case:  RRC with an extension word and the ZC bit set is actually RRU.  */
   1307  1.6  christos   if (extension_word
   1308  1.6  christos       && (extension_word & IGNORE_CARRY_BIT)
   1309  1.6  christos       && strcmp (opcode->name, "rrc") == 0)
   1310  1.6  christos     (*prin) (stream, "rrux%s", bc);
   1311  1.6  christos   else if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x')
   1312  1.1  christos     (*prin) (stream, "%sx%s", opcode->name, bc);
   1313  1.1  christos   else
   1314  1.1  christos     (*prin) (stream, "%s%s", opcode->name, bc);
   1315  1.1  christos 
   1316  1.1  christos   if (*op1)
   1317  1.1  christos     (*prin) (stream, "\t%s", op1);
   1318  1.1  christos   if (*op2)
   1319  1.1  christos     (*prin) (stream, ",");
   1320  1.1  christos 
   1321  1.1  christos   if (strlen (op1) < 7)
   1322  1.1  christos     (*prin) (stream, "\t");
   1323  1.1  christos   if (!strlen (op1))
   1324  1.1  christos     (*prin) (stream, "\t");
   1325  1.1  christos 
   1326  1.1  christos   if (*op2)
   1327  1.1  christos     (*prin) (stream, "%s", op2);
   1328  1.1  christos   if (strlen (op2) < 8)
   1329  1.1  christos     (*prin) (stream, "\t");
   1330  1.1  christos 
   1331  1.1  christos   if (*comm1 || *comm2)
   1332  1.1  christos     (*prin) (stream, ";");
   1333  1.1  christos   else if (cycles)
   1334  1.1  christos     {
   1335  1.1  christos       if (*op2)
   1336  1.1  christos 	(*prin) (stream, ";");
   1337  1.1  christos       else
   1338  1.1  christos 	{
   1339  1.1  christos 	  if (strlen (op1) < 7)
   1340  1.1  christos 	    (*prin) (stream, ";");
   1341  1.1  christos 	  else
   1342  1.1  christos 	    (*prin) (stream, "\t;");
   1343  1.1  christos 	}
   1344  1.1  christos     }
   1345  1.1  christos   if (*comm1)
   1346  1.1  christos     (*prin) (stream, "%s", comm1);
   1347  1.1  christos   if (*comm1 && *comm2)
   1348  1.1  christos     (*prin) (stream, ",");
   1349  1.1  christos   if (*comm2)
   1350  1.1  christos     (*prin) (stream, " %s", comm2);
   1351  1.1  christos 
   1352  1.1  christos   if (extension_word)
   1353  1.1  christos     cmd_len += 2;
   1354  1.1  christos 
   1355  1.1  christos   return cmd_len;
   1356  1.1  christos }
   1357