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