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