Home | History | Annotate | Line # | Download | only in opcodes
msp430-dis.c revision 1.11
      1   1.1  christos /* Disassemble MSP430 instructions.
      2  1.11  christos    Copyright (C) 2002-2024 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.8  christos #include "disassemble.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.10  christos static bool
     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.10  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.10  christos   return false;
     69   1.6  christos }
     70   1.6  christos 
     71  1.10  christos static bool
     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.10  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.10  christos       return false;
     88   1.6  christos     }
     89   1.6  christos }
     90   1.6  christos 
     91  1.10  christos static bool
     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.10  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.10  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.7  christos 	      else
    274   1.7  christos 		return -1;
    275   1.1  christos 	    }
    276   1.1  christos 	  else if (regd == 2)
    277   1.1  christos 	    {
    278   1.1  christos 	      /* Absolute.  */
    279   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    280   1.1  christos 		{
    281   1.6  christos 		  cmd_len += 2;
    282   1.6  christos 		  *cycles = 4;
    283   1.6  christos 		  sprintf (op, "&0x%04x", PS (dst));
    284   1.6  christos 		  if (extended_dst)
    285   1.6  christos 		    {
    286   1.6  christos 		      dst |= extended_dst << 16;
    287   1.6  christos 		      sprintf (op, "&0x%05x", dst & 0xfffff);
    288   1.6  christos 		    }
    289   1.1  christos 		}
    290   1.7  christos 	      else
    291   1.7  christos 		return -1;
    292   1.1  christos 	    }
    293   1.1  christos 	  else
    294   1.1  christos 	    {
    295   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    296   1.1  christos 		{
    297   1.6  christos 		  cmd_len += 2;
    298   1.6  christos 		  *cycles = 4;
    299   1.6  christos 		  if (extended_dst)
    300   1.6  christos 		    {
    301   1.6  christos 		      dst |= extended_dst << 16;
    302   1.6  christos 		      if (dst & 0x80000)
    303   1.6  christos 			dst |= -1U << 20;
    304   1.6  christos 		    }
    305   1.6  christos 		  sprintf (op, "%d(r%d)", dst, regd);
    306   1.1  christos 		}
    307   1.7  christos 	      else
    308   1.7  christos 		return -1;
    309   1.1  christos 	    }
    310   1.1  christos 	}
    311   1.1  christos       break;
    312   1.1  christos 
    313   1.1  christos     case 2:	/* rrc, push, call, swpb, rra, sxt, push, call, reti etc...  */
    314   1.1  christos       if (as == 0)
    315   1.1  christos 	{
    316   1.1  christos 	  if (regd == 3)
    317   1.1  christos 	    {
    318   1.1  christos 	      /* Constsnts.  */
    319   1.1  christos 	      sprintf (op, "#0");
    320   1.1  christos 	      sprintf (comm, "r3 As==00");
    321   1.1  christos 	    }
    322   1.1  christos 	  else
    323   1.1  christos 	    {
    324   1.1  christos 	      /* Register.  */
    325   1.1  christos 	      sprintf (op, "r%d", regd);
    326   1.1  christos 	    }
    327   1.1  christos 	  *cycles = 1;
    328   1.1  christos 	}
    329   1.1  christos       else if (as == 2)
    330   1.1  christos 	{
    331   1.1  christos 	  * cycles = print_as2_reg_name (regd, op, comm, 1, 1, 3);
    332   1.1  christos 	}
    333   1.1  christos       else if (as == 3)
    334   1.1  christos 	{
    335   1.1  christos 	  if (regd == 0)
    336   1.1  christos 	    {
    337   1.1  christos 	      *cycles = 3;
    338   1.1  christos 	      /* absolute. @pc+ */
    339   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    340   1.1  christos 		{
    341   1.6  christos 		  cmd_len += 2;
    342   1.1  christos 		  sprintf (op, "#%d", dst);
    343   1.1  christos 		  if (dst > 9 || dst < 0)
    344   1.6  christos 		    sprintf (comm, "#0x%04x", PS (dst));
    345   1.6  christos 		  if (extended_dst)
    346   1.6  christos 		    {
    347   1.6  christos 		      dst |= extended_dst << 16;
    348   1.6  christos 		      if (dst & 0x80000)
    349   1.6  christos 			dst |= -1U << 20;
    350   1.6  christos 		      sprintf (op, "#%d", dst);
    351   1.6  christos 		      if (dst > 9 || dst < 0)
    352   1.6  christos 			sprintf (comm, "#0x%05x", dst);
    353   1.6  christos 		    }
    354   1.1  christos 		}
    355   1.7  christos 	      else
    356   1.7  christos 		return -1;
    357   1.1  christos 	    }
    358   1.1  christos 	  else
    359   1.1  christos 	    * cycles = print_as3_reg_name (regd, op, comm, 1, 1, 3);
    360   1.1  christos 	}
    361   1.1  christos       else if (as == 1)
    362   1.1  christos 	{
    363   1.1  christos 	  *cycles = 4;
    364   1.1  christos 	  if (regd == 0)
    365   1.1  christos 	    {
    366   1.1  christos 	      /* PC relative.  */
    367   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    368   1.1  christos 		{
    369   1.6  christos 		  cmd_len += 2;
    370   1.6  christos 		  sprintf (op, "0x%04x", PS (dst));
    371   1.6  christos 		  sprintf (comm, "PC rel. 0x%04x",
    372   1.6  christos 			   PS ((short) addr + 2 + dst));
    373   1.6  christos 		  if (extended_dst)
    374   1.6  christos 		    {
    375   1.6  christos 		      dst |= extended_dst << 16;
    376   1.6  christos 		      sprintf (op, "0x%05x", dst & 0xffff);
    377   1.6  christos 		      sprintf (comm, "PC rel. 0x%05lx",
    378   1.6  christos 			       (long)((addr + 2 + dst) & 0xfffff));
    379   1.6  christos 		    }
    380   1.1  christos 		}
    381   1.7  christos 	      else
    382   1.7  christos 		return -1;
    383   1.1  christos 	    }
    384   1.1  christos 	  else if (regd == 2)
    385   1.1  christos 	    {
    386   1.1  christos 	      /* Absolute.  */
    387   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    388   1.1  christos 		{
    389   1.6  christos 		  cmd_len += 2;
    390   1.6  christos 		  sprintf (op, "&0x%04x", PS (dst));
    391   1.6  christos 		  if (extended_dst)
    392   1.6  christos 		    {
    393   1.6  christos 		      dst |= extended_dst << 16;
    394   1.6  christos 		      sprintf (op, "&0x%05x", dst & 0xfffff);
    395   1.6  christos 		    }
    396   1.1  christos 		}
    397   1.7  christos 	      else
    398   1.7  christos 		return -1;
    399   1.1  christos 	    }
    400   1.1  christos 	  else if (regd == 3)
    401   1.1  christos 	    {
    402   1.1  christos 	      *cycles = 1;
    403   1.1  christos 	      sprintf (op, "#1");
    404   1.1  christos 	      sprintf (comm, "r3 As==01");
    405   1.1  christos 	    }
    406   1.1  christos 	  else
    407   1.1  christos 	    {
    408   1.1  christos 	      /* Indexed.  */
    409   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
    410   1.1  christos 		{
    411   1.6  christos 		  cmd_len += 2;
    412   1.6  christos 		  if (extended_dst)
    413   1.6  christos 		    {
    414   1.6  christos 		      dst |= extended_dst << 16;
    415   1.6  christos 		      if (dst & 0x80000)
    416   1.6  christos 			dst |= -1U << 20;
    417   1.6  christos 		    }
    418   1.6  christos 		  sprintf (op, "%d(r%d)", dst, regd);
    419   1.6  christos 		  if (dst > 9 || dst < 0)
    420   1.6  christos 		    sprintf (comm, "%05x", dst);
    421   1.1  christos 		}
    422   1.7  christos 	      else
    423   1.7  christos 		return -1;
    424   1.1  christos 	    }
    425   1.1  christos 	}
    426   1.1  christos       break;
    427   1.1  christos 
    428   1.1  christos     case 3:			/* Jumps.  */
    429   1.1  christos       where = insn & 0x03ff;
    430   1.1  christos       if (where & 0x200)
    431   1.1  christos 	where |= ~0x03ff;
    432   1.1  christos       if (where > 512 || where < -511)
    433   1.1  christos 	return 0;
    434   1.1  christos 
    435   1.1  christos       where *= 2;
    436   1.1  christos       sprintf (op, "$%+-8d", where + 2);
    437   1.1  christos       sprintf (comm, "abs 0x%lx", (long) (addr + 2 + where));
    438   1.1  christos       *cycles = 2;
    439   1.1  christos       return 2;
    440   1.1  christos       break;
    441   1.6  christos 
    442   1.1  christos     default:
    443   1.1  christos       cmd_len = 0;
    444   1.1  christos     }
    445   1.1  christos 
    446   1.1  christos   return cmd_len;
    447   1.1  christos }
    448   1.1  christos 
    449   1.1  christos static int
    450   1.1  christos msp430_doubleoperand (disassemble_info *info,
    451   1.1  christos 		      struct msp430_opcode_s *opcode,
    452   1.1  christos 		      bfd_vma addr,
    453   1.1  christos 		      unsigned short insn,
    454   1.1  christos 		      char *op1,
    455   1.1  christos 		      char *op2,
    456   1.1  christos 		      char *comm1,
    457   1.1  christos 		      char *comm2,
    458   1.1  christos 		      unsigned short extension_word,
    459   1.1  christos 		      int *cycles)
    460   1.1  christos {
    461   1.1  christos   int regs = 0, regd = 0;
    462   1.1  christos   int ad = 0, as = 0;
    463   1.1  christos   int cmd_len = 2;
    464   1.1  christos   int dst = 0;
    465   1.1  christos   int fmt;
    466   1.1  christos   int extended_dst = extension_word & 0xf;
    467   1.1  christos   int extended_src = (extension_word >> 7) & 0xf;
    468   1.1  christos 
    469   1.1  christos   regd = insn & 0x0f;
    470   1.1  christos   regs = (insn & 0x0f00) >> 8;
    471   1.1  christos   as = (insn & 0x0030) >> 4;
    472   1.1  christos   ad = (insn & 0x0080) >> 7;
    473   1.1  christos 
    474   1.1  christos   if (opcode->fmt < 0)
    475   1.1  christos     fmt = (- opcode->fmt) - 1;
    476   1.1  christos   else
    477   1.1  christos     fmt = opcode->fmt;
    478   1.1  christos 
    479   1.1  christos   if (fmt == 0)
    480   1.1  christos     {
    481   1.1  christos       /* Special case: rla and rlc are the only 2 emulated instructions that
    482   1.1  christos 	 fall into two operand instructions.  */
    483   1.1  christos       /* With dst, there are only:
    484   1.1  christos 	 Rm       	Register,
    485   1.1  christos          x(Rm)     	Indexed,
    486   1.1  christos          0xXXXX    	Relative,
    487   1.6  christos          &0xXXXX    	Absolute
    488   1.1  christos          emulated_ins   dst
    489   1.1  christos          basic_ins      dst, dst.  */
    490   1.1  christos 
    491   1.1  christos       if (regd != regs || as != ad)
    492   1.1  christos 	return 0;		/* May be 'data' section.  */
    493   1.1  christos 
    494   1.1  christos       if (ad == 0)
    495   1.1  christos 	{
    496   1.1  christos 	  /* Register mode.  */
    497   1.1  christos 	  if (regd == 3)
    498   1.1  christos 	    {
    499   1.6  christos 	      strcpy (comm1, _("Warning: illegal as emulation instr"));
    500   1.1  christos 	      return -1;
    501   1.1  christos 	    }
    502   1.1  christos 
    503   1.1  christos 	  sprintf (op1, "r%d", regd);
    504   1.1  christos 	  *cycles = 1;
    505   1.1  christos 	}
    506   1.1  christos       else			/* ad == 1 */
    507   1.1  christos 	{
    508   1.1  christos 	  if (regd == 0)
    509   1.1  christos 	    {
    510   1.1  christos 	      /* PC relative, Symbolic.  */
    511   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    512   1.1  christos 		{
    513   1.6  christos 		  cmd_len += 4;
    514   1.6  christos 		  *cycles = 6;
    515   1.6  christos 		  sprintf (op1, "0x%04x", PS (dst));
    516   1.6  christos 		  sprintf (comm1, "PC rel. 0x%04x",
    517   1.6  christos 			   PS ((short) addr + 2 + dst));
    518   1.6  christos 		  if (extension_word)
    519   1.6  christos 		    {
    520   1.6  christos 		      dst |= extended_dst << 16;
    521   1.6  christos 		      if (dst & 0x80000)
    522   1.6  christos 			dst |= -1U << 20;
    523   1.6  christos 		      sprintf (op1, "0x%05x", dst & 0xfffff);
    524   1.6  christos 		      sprintf (comm1, "PC rel. 0x%05lx",
    525   1.6  christos 			       (long)((addr + 2 + dst) & 0xfffff));
    526   1.6  christos 		    }
    527   1.1  christos 		}
    528   1.7  christos 	      else
    529   1.7  christos 		return -1;
    530   1.1  christos 	    }
    531   1.1  christos 	  else if (regd == 2)
    532   1.1  christos 	    {
    533   1.1  christos 	      /* Absolute.  */
    534   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    535   1.1  christos 		{
    536   1.6  christos 		  int src;
    537   1.6  christos 
    538   1.6  christos 		  /* If the 'src' field is not the same as the dst
    539   1.6  christos 		     then this is not an rla instruction.  */
    540   1.6  christos 		  if (msp430dis_opcode_signed (addr + 4, info, &src, comm2))
    541   1.6  christos 		    {
    542   1.6  christos 		      if (src != dst)
    543   1.6  christos 			return 0;
    544   1.6  christos 		    }
    545   1.7  christos 		  else
    546   1.7  christos 		    return -1;
    547   1.6  christos 		  cmd_len += 4;
    548   1.6  christos 		  *cycles = 6;
    549   1.6  christos 		  sprintf (op1, "&0x%04x", PS (dst));
    550   1.6  christos 		  if (extension_word)
    551   1.6  christos 		    {
    552   1.6  christos 		      dst |= extended_dst << 16;
    553   1.6  christos 		      sprintf (op1, "&0x%05x", dst & 0xfffff);
    554   1.6  christos 		    }
    555   1.1  christos 		}
    556   1.7  christos 	      else
    557   1.7  christos 		return -1;
    558   1.1  christos 	    }
    559   1.1  christos 	  else
    560   1.1  christos 	    {
    561   1.1  christos 	      /* Indexed.  */
    562   1.6  christos 	      if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    563   1.1  christos 		{
    564   1.6  christos 		  if (extension_word)
    565   1.6  christos 		    {
    566   1.6  christos 		      dst |= extended_dst << 16;
    567   1.6  christos 		      if (dst & 0x80000)
    568   1.6  christos 			dst |= -1U << 20;
    569   1.6  christos 		    }
    570   1.6  christos 		  cmd_len += 4;
    571   1.6  christos 		  *cycles = 6;
    572   1.6  christos 		  sprintf (op1, "%d(r%d)", dst, regd);
    573   1.6  christos 		  if (dst > 9 || dst < -9)
    574   1.6  christos 		    sprintf (comm1, "#0x%05x", dst);
    575   1.1  christos 		}
    576   1.7  christos 	      else
    577   1.7  christos 		return -1;
    578   1.1  christos 	    }
    579   1.1  christos 	}
    580   1.1  christos 
    581   1.1  christos       *op2 = 0;
    582   1.1  christos       *comm2 = 0;
    583   1.1  christos 
    584   1.1  christos       return cmd_len;
    585   1.1  christos     }
    586   1.1  christos 
    587   1.1  christos   /* Two operands exactly.  */
    588   1.1  christos   if (ad == 0 && regd == 3)
    589   1.1  christos     {
    590   1.1  christos       /* R2/R3 are illegal as dest: may be data section.  */
    591   1.6  christos       strcpy (comm1, _("Warning: illegal as 2-op instr"));
    592   1.1  christos       return -1;
    593   1.1  christos     }
    594   1.1  christos 
    595   1.1  christos   /* Source.  */
    596   1.1  christos   if (as == 0)
    597   1.1  christos     {
    598   1.1  christos       *cycles = 1;
    599   1.1  christos       if (regs == 3)
    600   1.1  christos 	{
    601   1.1  christos 	  /* Constants.  */
    602   1.1  christos 	  sprintf (op1, "#0");
    603   1.1  christos 	  sprintf (comm1, "r3 As==00");
    604   1.1  christos 	}
    605   1.1  christos       else
    606   1.1  christos 	{
    607   1.1  christos 	  /* Register.  */
    608   1.1  christos 	  sprintf (op1, "r%d", regs);
    609   1.1  christos 	}
    610   1.1  christos     }
    611   1.1  christos   else if (as == 2)
    612   1.1  christos     {
    613   1.1  christos       * cycles = print_as2_reg_name (regs, op1, comm1, 1, 1, regs == 0 ? 3 : 2);
    614   1.1  christos     }
    615   1.1  christos   else if (as == 3)
    616   1.1  christos     {
    617   1.1  christos       if (regs == 0)
    618   1.1  christos 	{
    619   1.1  christos 	  *cycles = 3;
    620   1.1  christos 	  /* Absolute. @pc+.  */
    621   1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    622   1.6  christos 	    {
    623   1.6  christos 	      cmd_len += 2;
    624   1.1  christos 	      sprintf (op1, "#%d", dst);
    625   1.1  christos 	      if (dst > 9 || dst < 0)
    626   1.6  christos 		sprintf (comm1, "#0x%04x", PS (dst));
    627   1.6  christos 	      if (extension_word)
    628   1.6  christos 		{
    629   1.6  christos 		  dst &= 0xffff;
    630   1.6  christos 		  dst |= extended_src << 16;
    631   1.6  christos 		  if (dst & 0x80000)
    632   1.6  christos 		    dst |= -1U << 20;
    633   1.6  christos 		  sprintf (op1, "#%d", dst);
    634   1.6  christos 		  if (dst > 9 || dst < 0)
    635   1.6  christos 		    sprintf (comm1, "0x%05x", dst & 0xfffff);
    636   1.6  christos 		}
    637   1.1  christos 	    }
    638   1.7  christos 	  else
    639   1.7  christos 	    return -1;
    640   1.1  christos 	}
    641   1.1  christos       else
    642   1.1  christos 	* cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
    643   1.1  christos     }
    644   1.1  christos   else if (as == 1)
    645   1.1  christos     {
    646   1.1  christos       if (regs == 0)
    647   1.1  christos 	{
    648   1.1  christos 	  *cycles = 4;
    649   1.1  christos 	  /* PC relative.  */
    650   1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    651   1.6  christos 	    {
    652   1.6  christos 	      cmd_len += 2;
    653   1.6  christos 	      sprintf (op1, "0x%04x", PS (dst));
    654   1.6  christos 	      sprintf (comm1, "PC rel. 0x%04x",
    655   1.6  christos 		       PS ((short) addr + 2 + dst));
    656   1.6  christos 	      if (extension_word)
    657   1.6  christos 		{
    658   1.6  christos 		  dst &= 0xffff;
    659   1.6  christos 		  dst |= extended_src << 16;
    660   1.6  christos 		  if (dst & 0x80000)
    661   1.6  christos 		    dst |= -1U << 20;
    662   1.6  christos 		  sprintf (op1, "0x%05x", dst & 0xfffff);
    663   1.6  christos 		  sprintf (comm1, "PC rel. 0x%05lx",
    664   1.6  christos 			   (long) ((addr + 2 + dst) & 0xfffff));
    665   1.6  christos 		}
    666   1.1  christos 	    }
    667   1.7  christos 	  else
    668   1.7  christos 	    return -1;
    669   1.1  christos 	}
    670   1.1  christos       else if (regs == 2)
    671   1.1  christos 	{
    672   1.1  christos 	  *cycles = 2;
    673   1.1  christos 	  /* Absolute.  */
    674   1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    675   1.6  christos 	    {
    676   1.6  christos 	      cmd_len += 2;
    677   1.6  christos 	      sprintf (op1, "&0x%04x", PS (dst));
    678   1.6  christos 	      sprintf (comm1, "0x%04x", PS (dst));
    679   1.6  christos 	      if (extension_word)
    680   1.6  christos 		{
    681   1.6  christos 		  dst &= 0xffff;
    682   1.6  christos 		  dst |= extended_src << 16;
    683   1.6  christos 		  sprintf (op1, "&0x%05x", dst & 0xfffff);
    684   1.6  christos 		  * comm1 = 0;
    685   1.6  christos 		}
    686   1.1  christos 	    }
    687   1.7  christos 	  else
    688   1.7  christos 	    return -1;
    689   1.1  christos 	}
    690   1.1  christos       else if (regs == 3)
    691   1.1  christos 	{
    692   1.1  christos 	  *cycles = 1;
    693   1.1  christos 	  sprintf (op1, "#1");
    694   1.1  christos 	  sprintf (comm1, "r3 As==01");
    695   1.1  christos 	}
    696   1.1  christos       else
    697   1.1  christos 	{
    698   1.1  christos 	  *cycles = 3;
    699   1.1  christos 	  /* Indexed.  */
    700   1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    701   1.1  christos 	    {
    702   1.6  christos 	      cmd_len += 2;
    703   1.6  christos 	      if (extension_word)
    704   1.6  christos 		{
    705   1.6  christos 		  dst &= 0xffff;
    706   1.6  christos 		  dst |= extended_src << 16;
    707   1.6  christos 		  if (dst & 0x80000)
    708   1.6  christos 		    dst |= -1U << 20;
    709   1.6  christos 		}
    710   1.6  christos 	      sprintf (op1, "%d(r%d)", dst, regs);
    711   1.6  christos 	      if (dst > 9 || dst < -9)
    712   1.6  christos 		sprintf (comm1, "0x%05x", dst);
    713   1.6  christos 	    }
    714   1.7  christos 	  else
    715   1.7  christos 	    return -1;
    716   1.1  christos 	}
    717   1.1  christos     }
    718   1.1  christos 
    719   1.1  christos   /* Destination. Special care needed on addr + XXXX.  */
    720   1.1  christos 
    721   1.1  christos   if (ad == 0)
    722   1.1  christos     {
    723   1.1  christos       /* Register.  */
    724   1.1  christos       if (regd == 0)
    725   1.1  christos 	{
    726   1.1  christos 	  *cycles += 1;
    727   1.1  christos 	  sprintf (op2, "r0");
    728   1.1  christos 	}
    729   1.1  christos       else if (regd == 1)
    730   1.1  christos 	sprintf (op2, "r1");
    731   1.1  christos 
    732   1.1  christos       else if (regd == 2)
    733   1.1  christos 	sprintf (op2, "r2");
    734   1.1  christos 
    735   1.1  christos       else
    736   1.1  christos 	sprintf (op2, "r%d", regd);
    737   1.1  christos     }
    738   1.1  christos   else	/* ad == 1.  */
    739   1.1  christos     {
    740   1.1  christos       * cycles += 3;
    741   1.1  christos 
    742   1.1  christos       if (regd == 0)
    743   1.1  christos 	{
    744   1.1  christos 	  /* PC relative.  */
    745   1.1  christos 	  *cycles += 1;
    746   1.6  christos 	  if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
    747   1.6  christos 	    {
    748   1.6  christos 	      sprintf (op2, "0x%04x", PS (dst));
    749   1.6  christos 	      sprintf (comm2, "PC rel. 0x%04x",
    750   1.6  christos 		       PS ((short) addr + cmd_len + dst));
    751   1.6  christos 	      if (extension_word)
    752   1.6  christos 		{
    753   1.6  christos 		  dst |= extended_dst << 16;
    754   1.6  christos 		  if (dst & 0x80000)
    755   1.6  christos 		    dst |= -1U << 20;
    756   1.6  christos 		  sprintf (op2, "0x%05x", dst & 0xfffff);
    757   1.6  christos 		  sprintf (comm2, "PC rel. 0x%05lx",
    758   1.6  christos 			   (long)((addr + cmd_len + dst) & 0xfffff));
    759   1.6  christos 		}
    760   1.1  christos 	    }
    761   1.7  christos 	  else
    762   1.7  christos 	    return -1;
    763   1.1  christos 	  cmd_len += 2;
    764   1.1  christos 	}
    765   1.1  christos       else if (regd == 2)
    766   1.1  christos 	{
    767   1.1  christos 	  /* Absolute.  */
    768   1.6  christos 	  if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
    769   1.1  christos 	    {
    770   1.6  christos 	      cmd_len += 2;
    771   1.6  christos 	      sprintf (op2, "&0x%04x", PS (dst));
    772   1.6  christos 	      if (extension_word)
    773   1.6  christos 		{
    774   1.6  christos 		  dst |= extended_dst << 16;
    775   1.6  christos 		  sprintf (op2, "&0x%05x", dst & 0xfffff);
    776   1.6  christos 		}
    777   1.1  christos 	    }
    778   1.7  christos 	  else
    779   1.7  christos 	    return -1;
    780   1.1  christos 	}
    781   1.1  christos       else
    782   1.1  christos 	{
    783   1.6  christos 	  if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
    784   1.6  christos 	    {
    785   1.6  christos 	      cmd_len += 2;
    786   1.1  christos 	      if (dst > 9 || dst < 0)
    787   1.6  christos 		sprintf (comm2, "0x%04x", PS (dst));
    788   1.6  christos 	      if (extension_word)
    789   1.6  christos 		{
    790   1.6  christos 		  dst |= extended_dst << 16;
    791   1.6  christos 		  if (dst & 0x80000)
    792   1.6  christos 		    dst |= -1U << 20;
    793   1.6  christos 		  if (dst > 9 || dst < 0)
    794   1.6  christos 		    sprintf (comm2, "0x%05x", dst & 0xfffff);
    795   1.6  christos 		}
    796   1.6  christos 	      sprintf (op2, "%d(r%d)", dst, regd);
    797   1.1  christos 	    }
    798   1.7  christos 	  else
    799   1.7  christos 	    return -1;
    800   1.1  christos 	}
    801   1.1  christos     }
    802   1.1  christos 
    803   1.1  christos   return cmd_len;
    804   1.1  christos }
    805   1.1  christos 
    806   1.1  christos static int
    807   1.1  christos msp430_branchinstr (disassemble_info *info,
    808   1.1  christos 		    struct msp430_opcode_s *opcode ATTRIBUTE_UNUSED,
    809   1.1  christos 		    bfd_vma addr ATTRIBUTE_UNUSED,
    810   1.1  christos 		    unsigned short insn,
    811   1.1  christos 		    char *op1,
    812   1.1  christos 		    char *comm1,
    813   1.1  christos 		    int *cycles)
    814   1.1  christos {
    815   1.1  christos   int regs = 0, regd = 0;
    816   1.1  christos   int as = 0;
    817   1.1  christos   int cmd_len = 2;
    818   1.6  christos   int dst = 0;
    819   1.6  christos   unsigned short udst = 0;
    820   1.1  christos 
    821   1.1  christos   regd = insn & 0x0f;
    822   1.1  christos   regs = (insn & 0x0f00) >> 8;
    823   1.1  christos   as = (insn & 0x0030) >> 4;
    824   1.1  christos 
    825   1.1  christos   if (regd != 0)	/* Destination register is not a PC.  */
    826   1.1  christos     return 0;
    827   1.1  christos 
    828   1.1  christos   /* dst is a source register.  */
    829   1.1  christos   if (as == 0)
    830   1.1  christos     {
    831   1.1  christos       /* Constants.  */
    832   1.1  christos       if (regs == 3)
    833   1.1  christos 	{
    834   1.1  christos 	  *cycles = 1;
    835   1.1  christos 	  sprintf (op1, "#0");
    836   1.1  christos 	  sprintf (comm1, "r3 As==00");
    837   1.1  christos 	}
    838   1.1  christos       else
    839   1.1  christos 	{
    840   1.1  christos 	  /* Register.  */
    841   1.1  christos 	  *cycles = 1;
    842   1.1  christos 	  sprintf (op1, "r%d", regs);
    843   1.1  christos 	}
    844   1.1  christos     }
    845   1.1  christos   else if (as == 2)
    846   1.1  christos     {
    847   1.1  christos       * cycles = print_as2_reg_name (regs, op1, comm1, 2, 1, 2);
    848   1.1  christos     }
    849   1.1  christos   else if (as == 3)
    850   1.1  christos     {
    851   1.1  christos       if (regs == 0)
    852   1.1  christos 	{
    853   1.1  christos 	  /* Absolute. @pc+  */
    854   1.1  christos 	  *cycles = 3;
    855   1.6  christos 	  if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
    856   1.6  christos 	    {
    857   1.6  christos 	      cmd_len += 2;
    858   1.6  christos 	      sprintf (op1, "#0x%04x", PS (udst));
    859   1.6  christos 	    }
    860   1.7  christos 	  else
    861   1.7  christos 	    return -1;
    862   1.1  christos 	}
    863   1.1  christos       else
    864   1.1  christos 	* cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
    865   1.1  christos     }
    866   1.1  christos   else if (as == 1)
    867   1.1  christos     {
    868   1.1  christos       * cycles = 3;
    869   1.1  christos 
    870   1.1  christos       if (regs == 0)
    871   1.1  christos 	{
    872   1.1  christos 	  /* PC relative.  */
    873   1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    874   1.6  christos 	    {
    875   1.6  christos 	      cmd_len += 2;
    876   1.6  christos 	      (*cycles)++;
    877   1.6  christos 	      sprintf (op1, "0x%04x", PS (dst));
    878   1.6  christos 	      sprintf (comm1, "PC rel. 0x%04x",
    879   1.6  christos 		       PS ((short) addr + 2 + dst));
    880   1.6  christos 	    }
    881   1.7  christos 	  else
    882   1.7  christos 	    return -1;
    883   1.1  christos 	}
    884   1.1  christos       else if (regs == 2)
    885   1.1  christos 	{
    886   1.1  christos 	  /* Absolute.  */
    887   1.6  christos 	  if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
    888   1.6  christos 	    {
    889   1.6  christos 	      cmd_len += 2;
    890   1.6  christos 	      sprintf (op1, "&0x%04x", PS (udst));
    891   1.6  christos 	    }
    892   1.7  christos 	  else
    893   1.7  christos 	    return -1;
    894   1.1  christos 	}
    895   1.1  christos       else if (regs == 3)
    896   1.1  christos 	{
    897   1.1  christos 	  (*cycles)--;
    898   1.1  christos 	  sprintf (op1, "#1");
    899   1.1  christos 	  sprintf (comm1, "r3 As==01");
    900   1.1  christos 	}
    901   1.1  christos       else
    902   1.1  christos 	{
    903   1.1  christos 	  /* Indexed.  */
    904   1.6  christos 	  if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    905   1.6  christos 	    {
    906   1.6  christos 	      cmd_len += 2;
    907   1.6  christos 	      sprintf (op1, "%d(r%d)", dst, regs);
    908   1.6  christos 	    }
    909   1.7  christos 	  else
    910   1.7  christos 	    return -1;
    911   1.1  christos 	}
    912   1.1  christos     }
    913   1.1  christos 
    914   1.1  christos   return cmd_len;
    915   1.1  christos }
    916   1.1  christos 
    917   1.1  christos static int
    918   1.1  christos msp430x_calla_instr (disassemble_info * info,
    919   1.1  christos 		     bfd_vma            addr,
    920   1.1  christos 		     unsigned short     insn,
    921   1.1  christos 		     char *             op1,
    922   1.1  christos 		     char *             comm1,
    923   1.1  christos 		     int *              cycles)
    924   1.1  christos {
    925   1.1  christos   unsigned int   ureg = insn & 0xf;
    926   1.1  christos   int            reg = insn & 0xf;
    927   1.1  christos   int            am = (insn & 0xf0) >> 4;
    928   1.1  christos   int            cmd_len = 2;
    929   1.1  christos   unsigned short udst = 0;
    930   1.6  christos   int            dst = 0;
    931   1.1  christos 
    932   1.1  christos   switch (am)
    933   1.1  christos     {
    934   1.1  christos     case 4: /* CALLA Rdst */
    935   1.1  christos       *cycles = 1;
    936   1.1  christos       sprintf (op1, "r%d", reg);
    937   1.1  christos       break;
    938   1.1  christos 
    939   1.1  christos     case 5: /* CALLA x(Rdst) */
    940   1.1  christos       *cycles = 3;
    941   1.6  christos       if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    942   1.6  christos 	{
    943   1.6  christos 	  cmd_len += 2;
    944   1.6  christos 	  sprintf (op1, "%d(r%d)", dst, reg);
    945   1.6  christos 	  if (reg == 0)
    946   1.6  christos 	    sprintf (comm1, "PC rel. 0x%05lx", (long) (addr + 2 + dst));
    947   1.6  christos 	  else
    948   1.6  christos 	    sprintf (comm1, "0x%05x", dst);
    949   1.6  christos 	}
    950   1.7  christos       else
    951   1.7  christos 	return -1;
    952   1.1  christos       break;
    953   1.1  christos 
    954   1.1  christos     case 6: /* CALLA @Rdst */
    955   1.1  christos       *cycles = 2;
    956   1.1  christos       sprintf (op1, "@r%d", reg);
    957   1.1  christos       break;
    958   1.1  christos 
    959   1.1  christos     case 7: /* CALLA @Rdst+ */
    960   1.1  christos       *cycles = 2;
    961   1.1  christos       sprintf (op1, "@r%d+", reg);
    962   1.1  christos       break;
    963   1.1  christos 
    964   1.1  christos     case 8: /* CALLA &abs20 */
    965   1.6  christos       if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
    966   1.6  christos 	{
    967   1.6  christos 	  cmd_len += 2;
    968   1.6  christos 	  *cycles = 4;
    969   1.6  christos 	  sprintf (op1, "&%d", (ureg << 16) + udst);
    970   1.6  christos 	  sprintf (comm1, "0x%05x", (ureg << 16) + udst);
    971   1.6  christos 	}
    972   1.7  christos       else
    973   1.7  christos 	return -1;
    974   1.1  christos       break;
    975   1.1  christos 
    976   1.1  christos     case 9: /* CALLA pcrel-sym */
    977   1.6  christos       if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
    978   1.6  christos 	{
    979   1.6  christos 	  cmd_len += 2;
    980   1.6  christos 	  *cycles = 4;
    981   1.6  christos 	  sprintf (op1, "%d(PC)", (reg << 16) + dst);
    982   1.6  christos 	  sprintf (comm1, "PC rel. 0x%05lx",
    983   1.6  christos 		   (long) (addr + 2 + dst + (reg << 16)));
    984   1.6  christos 	}
    985   1.7  christos       else
    986   1.7  christos 	return -1;
    987   1.1  christos       break;
    988   1.1  christos 
    989   1.1  christos     case 11: /* CALLA #imm20 */
    990   1.6  christos       if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
    991   1.6  christos 	{
    992   1.6  christos 	  cmd_len += 2;
    993   1.6  christos 	  *cycles = 4;
    994   1.6  christos 	  sprintf (op1, "#%d", (ureg << 16) + udst);
    995   1.6  christos 	  sprintf (comm1, "0x%05x", (ureg << 16) + udst);
    996   1.6  christos 	}
    997   1.7  christos       else
    998   1.7  christos 	return -1;
    999   1.1  christos       break;
   1000   1.1  christos 
   1001   1.1  christos     default:
   1002   1.6  christos       strcpy (comm1, _("Warning: unrecognised CALLA addressing mode"));
   1003   1.1  christos       return -1;
   1004   1.1  christos     }
   1005   1.1  christos 
   1006   1.1  christos   return cmd_len;
   1007   1.1  christos }
   1008   1.1  christos 
   1009   1.1  christos int
   1010   1.1  christos print_insn_msp430 (bfd_vma addr, disassemble_info *info)
   1011   1.1  christos {
   1012   1.1  christos   void *stream = info->stream;
   1013   1.1  christos   fprintf_ftype prin = info->fprintf_func;
   1014   1.1  christos   struct msp430_opcode_s *opcode;
   1015   1.1  christos   char op1[32], op2[32], comm1[64], comm2[64];
   1016   1.1  christos   int cmd_len = 0;
   1017   1.1  christos   unsigned short insn;
   1018   1.1  christos   int cycles = 0;
   1019   1.1  christos   char *bc = "";
   1020   1.1  christos   unsigned short extension_word = 0;
   1021   1.6  christos   unsigned short bits;
   1022   1.1  christos 
   1023   1.6  christos   if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
   1024   1.7  christos     return -1;
   1025   1.1  christos 
   1026   1.1  christos   if (((int) addr & 0xffff) > 0xffdf)
   1027   1.1  christos     {
   1028   1.1  christos       (*prin) (stream, "interrupt service routine at 0x%04x", 0xffff & insn);
   1029   1.1  christos       return 2;
   1030   1.1  christos     }
   1031   1.1  christos 
   1032   1.1  christos   *comm1 = 0;
   1033   1.1  christos   *comm2 = 0;
   1034   1.1  christos 
   1035   1.1  christos   /* Check for an extension word.  */
   1036   1.1  christos   if ((insn & 0xf800) == 0x1800)
   1037   1.1  christos     {
   1038   1.1  christos       extension_word = insn;
   1039   1.1  christos       addr += 2;
   1040   1.6  christos       if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
   1041   1.7  christos 	return -1;
   1042   1.1  christos    }
   1043   1.1  christos 
   1044   1.1  christos   for (opcode = msp430_opcodes; opcode->name; opcode++)
   1045   1.1  christos     {
   1046   1.1  christos       if ((insn & opcode->bin_mask) == opcode->bin_opcode
   1047   1.1  christos 	  && opcode->bin_opcode != 0x9300)
   1048   1.1  christos 	{
   1049   1.1  christos 	  *op1 = 0;
   1050   1.1  christos 	  *op2 = 0;
   1051   1.1  christos 	  *comm1 = 0;
   1052   1.1  christos 	  *comm2 = 0;
   1053   1.1  christos 
   1054   1.1  christos 	  /* r0 as destination. Ad should be zero.  */
   1055   1.1  christos 	  if (opcode->insn_opnumb == 3
   1056   1.1  christos 	      && (insn & 0x000f) == 0
   1057   1.1  christos 	      && (insn & 0x0080) == 0)
   1058   1.1  christos 	    {
   1059   1.7  christos 	      int ret =
   1060   1.1  christos 		msp430_branchinstr (info, opcode, addr, insn, op1, comm1,
   1061   1.1  christos 				    &cycles);
   1062   1.7  christos 
   1063   1.7  christos 	      if (ret == -1)
   1064   1.7  christos 		return -1;
   1065   1.7  christos 	      cmd_len += ret;
   1066   1.1  christos 	      if (cmd_len)
   1067   1.1  christos 		break;
   1068   1.1  christos 	    }
   1069   1.1  christos 
   1070   1.1  christos 	  switch (opcode->insn_opnumb)
   1071   1.1  christos 	    {
   1072   1.1  christos 	      int n;
   1073   1.1  christos 	      int reg;
   1074   1.7  christos 	      int ret;
   1075   1.1  christos 
   1076   1.1  christos 	    case 4:
   1077   1.7  christos 	      ret = msp430x_calla_instr (info, addr, insn,
   1078   1.7  christos 					 op1, comm1, & cycles);
   1079   1.7  christos 	      if (ret == -1)
   1080   1.7  christos 		return -1;
   1081   1.7  christos 	      cmd_len += ret;
   1082   1.1  christos 	      break;
   1083   1.1  christos 
   1084   1.1  christos 	    case 5: /* PUSHM/POPM */
   1085   1.1  christos 	      n = (insn & 0xf0) >> 4;
   1086   1.1  christos 	      reg = (insn & 0xf);
   1087   1.1  christos 
   1088   1.1  christos 	      sprintf (op1, "#%d", n + 1);
   1089   1.1  christos 	      if (opcode->bin_opcode == 0x1400)
   1090   1.1  christos 		/* PUSHM */
   1091   1.1  christos 		sprintf (op2, "r%d", reg);
   1092   1.1  christos 	      else
   1093   1.1  christos 		/* POPM */
   1094   1.1  christos 		sprintf (op2, "r%d", reg + n);
   1095   1.1  christos 	      if (insn & 0x100)
   1096   1.1  christos 		sprintf (comm1, "16-bit words");
   1097   1.1  christos 	      else
   1098   1.1  christos 		{
   1099   1.1  christos 		  sprintf (comm1, "20-bit words");
   1100   1.1  christos 		  bc =".a";
   1101   1.1  christos 		}
   1102   1.6  christos 
   1103   1.1  christos 	      cycles = 2; /*FIXME*/
   1104   1.1  christos 	      cmd_len = 2;
   1105   1.1  christos 	      break;
   1106   1.1  christos 
   1107   1.1  christos 	    case 6: /* RRAM, RRCM, RRUM, RLAM.  */
   1108   1.1  christos 	      n = ((insn >> 10) & 0x3) + 1;
   1109   1.1  christos 	      reg = (insn & 0xf);
   1110   1.1  christos 	      if ((insn & 0x10) == 0)
   1111   1.1  christos 		bc =".a";
   1112   1.1  christos 	      sprintf (op1, "#%d", n);
   1113   1.1  christos 	      sprintf (op2, "r%d", reg);
   1114   1.1  christos 	      cycles = 2; /*FIXME*/
   1115   1.1  christos 	      cmd_len = 2;
   1116   1.1  christos 	      break;
   1117   1.1  christos 
   1118   1.1  christos 	    case 8: /* ADDA, CMPA, SUBA.  */
   1119   1.1  christos 	      reg = (insn & 0xf);
   1120   1.1  christos 	      n = (insn >> 8) & 0xf;
   1121   1.1  christos 	      if (insn & 0x40)
   1122   1.1  christos 		{
   1123   1.1  christos 		  sprintf (op1, "r%d", n);
   1124   1.1  christos 		  cmd_len = 2;
   1125   1.1  christos 		}
   1126   1.1  christos 	      else
   1127   1.1  christos 		{
   1128   1.1  christos 		  n <<= 16;
   1129   1.6  christos 		  if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
   1130   1.6  christos 		    {
   1131   1.6  christos 		      n |= bits;
   1132   1.6  christos 		      sprintf (op1, "#%d", n);
   1133   1.6  christos 		      if (n > 9 || n < 0)
   1134   1.6  christos 			sprintf (comm1, "0x%05x", n);
   1135   1.6  christos 		    }
   1136   1.7  christos 		  else
   1137   1.7  christos 		    return -1;
   1138   1.1  christos 		  cmd_len = 4;
   1139   1.1  christos 		}
   1140   1.1  christos 	      sprintf (op2, "r%d", reg);
   1141   1.1  christos 	      cycles = 2; /*FIXME*/
   1142   1.1  christos 	      break;
   1143   1.1  christos 
   1144   1.1  christos 	    case 9: /* MOVA */
   1145   1.1  christos 	      reg = (insn & 0xf);
   1146   1.1  christos 	      n = (insn >> 8) & 0xf;
   1147   1.1  christos 	      switch ((insn >> 4) & 0xf)
   1148   1.1  christos 		{
   1149   1.1  christos 		case 0: /* MOVA @Rsrc, Rdst */
   1150   1.1  christos 		  cmd_len = 2;
   1151   1.1  christos 		  sprintf (op1, "@r%d", n);
   1152   1.1  christos 		  if (strcmp (opcode->name, "bra") != 0)
   1153   1.1  christos 		    sprintf (op2, "r%d", reg);
   1154   1.1  christos 		  break;
   1155   1.6  christos 
   1156   1.1  christos 		case 1: /* MOVA @Rsrc+, Rdst */
   1157   1.1  christos 		  cmd_len = 2;
   1158   1.1  christos 		  if (strcmp (opcode->name, "reta") != 0)
   1159   1.1  christos 		    {
   1160   1.1  christos 		      sprintf (op1, "@r%d+", n);
   1161   1.1  christos 		      if (strcmp (opcode->name, "bra") != 0)
   1162   1.1  christos 			sprintf (op2, "r%d", reg);
   1163   1.1  christos 		    }
   1164   1.1  christos 		  break;
   1165   1.6  christos 
   1166   1.1  christos 		case 2: /* MOVA &abs20, Rdst */
   1167   1.1  christos 		  cmd_len = 4;
   1168   1.1  christos 		  n <<= 16;
   1169   1.6  christos 		  if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
   1170   1.6  christos 		    {
   1171   1.6  christos 		      n |= bits;
   1172   1.6  christos 		      sprintf (op1, "&%d", n);
   1173   1.6  christos 		      if (n > 9 || n < 0)
   1174   1.6  christos 			sprintf (comm1, "0x%05x", n);
   1175   1.6  christos 		      if (strcmp (opcode->name, "bra") != 0)
   1176   1.6  christos 			sprintf (op2, "r%d", reg);
   1177   1.6  christos 		    }
   1178   1.7  christos 		  else
   1179   1.7  christos 		    return -1;
   1180   1.1  christos 		  break;
   1181   1.6  christos 
   1182   1.1  christos 		case 3: /* MOVA x(Rsrc), Rdst */
   1183   1.1  christos 		  cmd_len = 4;
   1184   1.1  christos 		  if (strcmp (opcode->name, "bra") != 0)
   1185   1.1  christos 		    sprintf (op2, "r%d", reg);
   1186   1.1  christos 		  reg = n;
   1187   1.6  christos 		  if (msp430dis_opcode_signed (addr + 2, info, &n, comm1))
   1188   1.6  christos 		    {
   1189   1.6  christos 		      sprintf (op1, "%d(r%d)", n, reg);
   1190   1.6  christos 		      if (n > 9 || n < 0)
   1191   1.6  christos 			{
   1192   1.6  christos 			  if (reg == 0)
   1193   1.6  christos 			    sprintf (comm1, "PC rel. 0x%05lx",
   1194   1.6  christos 				     (long) (addr + 2 + n));
   1195   1.6  christos 			  else
   1196   1.6  christos 			    sprintf (comm1, "0x%05x", n);
   1197   1.6  christos 			}
   1198   1.1  christos 		    }
   1199   1.7  christos 		  else
   1200   1.7  christos 		    return -1;
   1201   1.1  christos 		  break;
   1202   1.1  christos 
   1203   1.1  christos 		case 6: /* MOVA Rsrc, &abs20 */
   1204   1.1  christos 		  cmd_len = 4;
   1205   1.1  christos 		  reg <<= 16;
   1206   1.6  christos 		  if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm2))
   1207   1.6  christos 		    {
   1208   1.6  christos 		      reg |= bits;
   1209   1.6  christos 		      sprintf (op1, "r%d", n);
   1210   1.6  christos 		      sprintf (op2, "&%d", reg);
   1211   1.6  christos 		      if (reg > 9 || reg < 0)
   1212   1.6  christos 			sprintf (comm2, "0x%05x", reg);
   1213   1.6  christos 		    }
   1214   1.7  christos 		  else
   1215   1.7  christos 		    return -1;
   1216   1.1  christos 		  break;
   1217   1.1  christos 
   1218   1.1  christos 		case 7: /* MOVA Rsrc, x(Rdst) */
   1219   1.1  christos 		  cmd_len = 4;
   1220   1.1  christos 		  sprintf (op1, "r%d", n);
   1221   1.6  christos 		  if (msp430dis_opcode_signed (addr + 2, info, &n, comm2))
   1222   1.6  christos 		    {
   1223   1.6  christos 		      sprintf (op2, "%d(r%d)", n, reg);
   1224   1.6  christos 		      if (n > 9 || n < 0)
   1225   1.6  christos 			{
   1226   1.6  christos 			  if (reg == 0)
   1227   1.6  christos 			    sprintf (comm2, "PC rel. 0x%05lx",
   1228   1.6  christos 				     (long) (addr + 2 + n));
   1229   1.6  christos 			  else
   1230   1.6  christos 			    sprintf (comm2, "0x%05x", n);
   1231   1.6  christos 			}
   1232   1.1  christos 		    }
   1233   1.7  christos 		  else
   1234   1.7  christos 		    return -1;
   1235   1.1  christos 		  break;
   1236   1.6  christos 
   1237   1.1  christos 		case 8: /* MOVA #imm20, Rdst */
   1238   1.1  christos 		  cmd_len = 4;
   1239   1.1  christos 		  n <<= 16;
   1240   1.6  christos 		  if (msp430dis_opcode_unsigned (addr + 2, info, &bits, comm1))
   1241   1.6  christos 		    {
   1242   1.6  christos 		      n |= bits;
   1243   1.6  christos 		      if (n & 0x80000)
   1244   1.6  christos 			n |= -1U << 20;
   1245   1.6  christos 		      sprintf (op1, "#%d", n);
   1246   1.6  christos 		      if (n > 9 || n < 0)
   1247   1.6  christos 			sprintf (comm1, "0x%05x", n);
   1248   1.6  christos 		      if (strcmp (opcode->name, "bra") != 0)
   1249   1.6  christos 			sprintf (op2, "r%d", reg);
   1250   1.6  christos 		    }
   1251   1.7  christos 		  else
   1252   1.7  christos 		    return -1;
   1253   1.1  christos 		  break;
   1254   1.6  christos 
   1255   1.1  christos 		case 12: /* MOVA Rsrc, Rdst */
   1256   1.1  christos 		  cmd_len = 2;
   1257   1.1  christos 		  sprintf (op1, "r%d", n);
   1258   1.1  christos 		  if (strcmp (opcode->name, "bra") != 0)
   1259   1.1  christos 		    sprintf (op2, "r%d", reg);
   1260   1.1  christos 		  break;
   1261   1.1  christos 
   1262   1.1  christos 		default:
   1263   1.1  christos 		  break;
   1264   1.1  christos 		}
   1265   1.1  christos 	      cycles = 2; /* FIXME */
   1266   1.1  christos 	      break;
   1267   1.1  christos 	    }
   1268   1.1  christos 
   1269   1.1  christos 	  if (cmd_len)
   1270   1.1  christos 	    break;
   1271   1.1  christos 
   1272   1.1  christos 	  switch (opcode->insn_opnumb)
   1273   1.1  christos 	    {
   1274   1.7  christos 	      int ret;
   1275   1.7  christos 
   1276   1.1  christos 	    case 0:
   1277   1.1  christos 	      cmd_len += msp430_nooperands (opcode, addr, insn, comm1, &cycles);
   1278   1.1  christos 	      break;
   1279   1.1  christos 	    case 2:
   1280   1.7  christos 	      ret =
   1281   1.1  christos 		msp430_doubleoperand (info, opcode, addr, insn, op1, op2,
   1282   1.1  christos 				      comm1, comm2,
   1283   1.1  christos 				      extension_word,
   1284   1.1  christos 				      &cycles);
   1285   1.7  christos 
   1286   1.7  christos 	      if (ret == -1)
   1287   1.7  christos 		return -1;
   1288   1.7  christos 	      cmd_len += ret;
   1289   1.1  christos 	      if (insn & BYTE_OPERATION)
   1290   1.1  christos 		{
   1291   1.1  christos 		  if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
   1292   1.1  christos 		    bc = ".a";
   1293   1.1  christos 		  else
   1294   1.1  christos 		    bc = ".b";
   1295   1.1  christos 		}
   1296   1.1  christos 	      else if (extension_word)
   1297   1.1  christos 		{
   1298   1.6  christos 		  if (extension_word & BYTE_OPERATION)
   1299   1.1  christos 		    bc = ".w";
   1300   1.1  christos 		  else
   1301   1.1  christos 		    {
   1302   1.1  christos 		      bc = ".?";
   1303   1.6  christos 		      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
   1304   1.1  christos 		    }
   1305   1.1  christos 		}
   1306   1.6  christos 
   1307   1.1  christos 	      break;
   1308   1.1  christos 	    case 1:
   1309   1.7  christos 	      ret =
   1310   1.1  christos 		msp430_singleoperand (info, opcode, addr, insn, op1, comm1,
   1311   1.1  christos 				      extension_word,
   1312   1.1  christos 				      &cycles);
   1313   1.7  christos 
   1314   1.7  christos 	      if (ret == -1)
   1315   1.7  christos 		return -1;
   1316   1.7  christos 	      cmd_len += ret;
   1317   1.1  christos 	      if (extension_word
   1318   1.1  christos 		  && (strcmp (opcode->name, "swpb") == 0
   1319   1.1  christos 		      || strcmp (opcode->name, "sxt") == 0))
   1320   1.1  christos 		{
   1321   1.1  christos 		  if (insn & BYTE_OPERATION)
   1322   1.1  christos 		    {
   1323   1.1  christos 		      bc = ".?";
   1324   1.6  christos 		      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
   1325   1.1  christos 		    }
   1326   1.1  christos 		  else if (extension_word & BYTE_OPERATION)
   1327   1.1  christos 		    bc = ".w";
   1328   1.1  christos 		  else
   1329   1.1  christos 		    bc = ".a";
   1330   1.1  christos 		}
   1331   1.1  christos 	      else if (insn & BYTE_OPERATION && opcode->fmt != 3)
   1332   1.1  christos 		{
   1333   1.1  christos 		  if (extension_word != 0 && ((extension_word & BYTE_OPERATION) == 0))
   1334   1.1  christos 		    bc = ".a";
   1335   1.1  christos 		  else
   1336   1.1  christos 		    bc = ".b";
   1337   1.1  christos 		}
   1338   1.1  christos 	      else if (extension_word)
   1339   1.1  christos 		{
   1340   1.1  christos 		  if (extension_word & (1 << 6))
   1341   1.1  christos 		    bc = ".w";
   1342   1.1  christos 		  else
   1343   1.1  christos 		    {
   1344   1.1  christos 		      bc = ".?";
   1345   1.6  christos 		      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
   1346   1.1  christos 		    }
   1347   1.1  christos 		}
   1348   1.1  christos 	      break;
   1349   1.1  christos 	    default:
   1350   1.1  christos 	      break;
   1351   1.1  christos 	    }
   1352   1.1  christos 	}
   1353   1.1  christos 
   1354   1.1  christos       if (cmd_len)
   1355   1.1  christos 	break;
   1356   1.1  christos     }
   1357   1.1  christos 
   1358   1.1  christos   if (cmd_len < 1)
   1359   1.1  christos     {
   1360   1.1  christos       /* Unknown opcode, or invalid combination of operands.  */
   1361   1.1  christos       if (extension_word)
   1362   1.1  christos 	{
   1363   1.1  christos 	  prin (stream, ".word	0x%04x, 0x%04x;	????", extension_word, PS (insn));
   1364   1.1  christos 	  if (*comm1)
   1365   1.1  christos 	    prin (stream, "\t %s", comm1);
   1366   1.1  christos 	  return 4;
   1367   1.1  christos 	}
   1368   1.1  christos       (*prin) (stream, ".word	0x%04x;	????", PS (insn));
   1369   1.1  christos       return 2;
   1370   1.1  christos     }
   1371   1.1  christos 
   1372   1.1  christos   /* Display the repeat count (if set) for extended register mode.  */
   1373   1.1  christos   if (cmd_len == 2 && ((extension_word & 0xf) != 0))
   1374   1.1  christos     {
   1375   1.1  christos       if (extension_word & (1 << 7))
   1376   1.1  christos 	prin (stream, "rpt r%d { ", extension_word & 0xf);
   1377   1.1  christos       else
   1378   1.1  christos 	prin (stream, "rpt #%d { ", (extension_word & 0xf) + 1);
   1379   1.1  christos     }
   1380   1.1  christos 
   1381   1.6  christos   /* Special case:  RRC with an extension word and the ZC bit set is actually RRU.  */
   1382   1.6  christos   if (extension_word
   1383   1.6  christos       && (extension_word & IGNORE_CARRY_BIT)
   1384   1.6  christos       && strcmp (opcode->name, "rrc") == 0)
   1385   1.6  christos     (*prin) (stream, "rrux%s", bc);
   1386   1.6  christos   else if (extension_word && opcode->name[strlen (opcode->name) - 1] != 'x')
   1387   1.1  christos     (*prin) (stream, "%sx%s", opcode->name, bc);
   1388   1.1  christos   else
   1389   1.1  christos     (*prin) (stream, "%s%s", opcode->name, bc);
   1390   1.1  christos 
   1391   1.1  christos   if (*op1)
   1392   1.1  christos     (*prin) (stream, "\t%s", op1);
   1393   1.1  christos   if (*op2)
   1394   1.1  christos     (*prin) (stream, ",");
   1395   1.1  christos 
   1396   1.1  christos   if (strlen (op1) < 7)
   1397   1.1  christos     (*prin) (stream, "\t");
   1398   1.1  christos   if (!strlen (op1))
   1399   1.1  christos     (*prin) (stream, "\t");
   1400   1.1  christos 
   1401   1.1  christos   if (*op2)
   1402   1.1  christos     (*prin) (stream, "%s", op2);
   1403   1.1  christos   if (strlen (op2) < 8)
   1404   1.1  christos     (*prin) (stream, "\t");
   1405   1.1  christos 
   1406   1.1  christos   if (*comm1 || *comm2)
   1407   1.1  christos     (*prin) (stream, ";");
   1408   1.1  christos   else if (cycles)
   1409   1.1  christos     {
   1410   1.1  christos       if (*op2)
   1411   1.1  christos 	(*prin) (stream, ";");
   1412   1.1  christos       else
   1413   1.1  christos 	{
   1414   1.1  christos 	  if (strlen (op1) < 7)
   1415   1.1  christos 	    (*prin) (stream, ";");
   1416   1.1  christos 	  else
   1417   1.1  christos 	    (*prin) (stream, "\t;");
   1418   1.1  christos 	}
   1419   1.1  christos     }
   1420   1.1  christos   if (*comm1)
   1421   1.1  christos     (*prin) (stream, "%s", comm1);
   1422   1.1  christos   if (*comm1 && *comm2)
   1423   1.1  christos     (*prin) (stream, ",");
   1424   1.1  christos   if (*comm2)
   1425   1.1  christos     (*prin) (stream, " %s", comm2);
   1426   1.1  christos 
   1427   1.1  christos   if (extension_word)
   1428   1.1  christos     cmd_len += 2;
   1429   1.1  christos 
   1430   1.1  christos   return cmd_len;
   1431   1.1  christos }
   1432