[BACK]Return to msp430-dis.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils / dist / opcodes

Annotation of src/external/gpl3/binutils/dist/opcodes/msp430-dis.c, Revision 1.1.1.5

1.1       skrll       1: /* Disassemble MSP430 instructions.
1.1.1.5 ! christos    2:    Copyright (C) 2002-2016 Free Software Foundation, Inc.
1.1.1.4   christos    3:
1.1       skrll       4:    Contributed by Dmitry Diky <diwil@mail.ru>
1.1.1.4   christos    5:
1.1       skrll       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:
1.1.1.3   christos   23: #include "sysdep.h"
1.1       skrll      24: #include <stdio.h>
                     25: #include <ctype.h>
                     26: #include <sys/types.h>
1.1.1.5 ! christos   27: #include <errno.h>
1.1       skrll      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:
1.1.1.5 ! christos   40: static bfd_boolean
        !            41: msp430dis_read_two_bytes (bfd_vma            addr,
        !            42:                          disassemble_info * info,
        !            43:                          bfd_byte *         buffer,
        !            44:                          char *             comm)
1.1       skrll      45: {
                     46:   int status;
                     47:
                     48:   status = info->read_memory_func (addr, buffer, 2, info);
1.1.1.5 ! christos   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
1.1       skrll      62:     {
                     63:       info->memory_error_func (status, addr, info);
1.1.1.5 ! christos   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;
1.1       skrll     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:     {
1.1.1.4   christos  131:       if ((insn & 0x0f00) != 0x0300 || (insn & 0x0f00) != 0x0200)
1.1       skrll     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
1.1.1.4   christos  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
1.1       skrll     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,
1.1.1.4   christos  199:                      unsigned short extension_word,
1.1       skrll     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;
1.1.1.4   christos  206:   int dst = 0;
                    207:   int fmt;
                    208:   int extended_dst = extension_word & 0xf;
1.1       skrll     209:
                    210:   regd = insn & 0x0f;
                    211:   regs = (insn & 0x0f00) >> 8;
                    212:   as = (insn & 0x0030) >> 4;
                    213:   ad = (insn & 0x0080) >> 7;
                    214:
1.1.1.4   christos  215:   if (opcode->fmt < 0)
                    216:     fmt = (- opcode->fmt) - 1;
                    217:   else
                    218:     fmt = opcode->fmt;
                    219:
                    220:   switch (fmt)
1.1       skrll     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.  */
1.1.1.5 ! christos  258:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
1.1.1.4   christos  259:                {
1.1.1.5 ! christos  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:                    }
1.1.1.4   christos  272:                }
1.1       skrll     273:            }
                    274:          else if (regd == 2)
                    275:            {
                    276:              /* Absolute.  */
1.1.1.5 ! christos  277:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
1.1.1.4   christos  278:                {
1.1.1.5 ! christos  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:                    }
1.1.1.4   christos  287:                }
1.1       skrll     288:            }
                    289:          else
                    290:            {
1.1.1.5 ! christos  291:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
1.1.1.4   christos  292:                {
1.1.1.5 ! christos  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);
1.1.1.4   christos  302:                }
1.1       skrll     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:        {
1.1.1.4   christos  325:          * cycles = print_as2_reg_name (regd, op, comm, 1, 1, 3);
1.1       skrll     326:        }
                    327:       else if (as == 3)
                    328:        {
1.1.1.4   christos  329:          if (regd == 0)
1.1       skrll     330:            {
                    331:              *cycles = 3;
                    332:              /* absolute. @pc+ */
1.1.1.5 ! christos  333:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
1.1.1.4   christos  334:                {
1.1.1.5 ! christos  335:                  cmd_len += 2;
1.1.1.4   christos  336:                  sprintf (op, "#%d", dst);
                    337:                  if (dst > 9 || dst < 0)
1.1.1.5 ! christos  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:                    }
1.1.1.4   christos  348:                }
1.1       skrll     349:            }
                    350:          else
1.1.1.4   christos  351:            * cycles = print_as3_reg_name (regd, op, comm, 1, 1, 3);
1.1       skrll     352:        }
                    353:       else if (as == 1)
                    354:        {
                    355:          *cycles = 4;
                    356:          if (regd == 0)
                    357:            {
                    358:              /* PC relative.  */
1.1.1.5 ! christos  359:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
1.1.1.4   christos  360:                {
1.1.1.5 ! christos  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:                    }
1.1.1.4   christos  372:                }
1.1       skrll     373:            }
                    374:          else if (regd == 2)
                    375:            {
                    376:              /* Absolute.  */
1.1.1.5 ! christos  377:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
1.1.1.4   christos  378:                {
1.1.1.5 ! christos  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:                    }
1.1.1.4   christos  386:                }
1.1       skrll     387:            }
                    388:          else if (regd == 3)
                    389:            {
                    390:              *cycles = 1;
                    391:              sprintf (op, "#1");
                    392:              sprintf (comm, "r3 As==01");
                    393:            }
                    394:          else
                    395:            {
1.1.1.4   christos  396:              /* Indexed.  */
1.1.1.5 ! christos  397:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm))
1.1.1.4   christos  398:                {
1.1.1.5 ! christos  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);
1.1.1.4   christos  409:                }
1.1       skrll     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);
1.1.1.4   christos  423:       sprintf (comm, "abs 0x%lx", (long) (addr + 2 + where));
1.1       skrll     424:       *cycles = 2;
                    425:       return 2;
                    426:       break;
1.1.1.5 ! christos  427:
1.1       skrll     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,
1.1.1.4   christos  444:                      unsigned short extension_word,
1.1       skrll     445:                      int *cycles)
                    446: {
                    447:   int regs = 0, regd = 0;
                    448:   int ad = 0, as = 0;
                    449:   int cmd_len = 2;
1.1.1.4   christos  450:   int dst = 0;
                    451:   int fmt;
                    452:   int extended_dst = extension_word & 0xf;
                    453:   int extended_src = (extension_word >> 7) & 0xf;
1.1       skrll     454:
                    455:   regd = insn & 0x0f;
                    456:   regs = (insn & 0x0f00) >> 8;
                    457:   as = (insn & 0x0030) >> 4;
                    458:   ad = (insn & 0x0080) >> 7;
                    459:
1.1.1.4   christos  460:   if (opcode->fmt < 0)
                    461:     fmt = (- opcode->fmt) - 1;
                    462:   else
                    463:     fmt = opcode->fmt;
                    464:
                    465:   if (fmt == 0)
1.1       skrll     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,
1.1.1.4   christos  473:          &0xXXXX       Absolute
1.1       skrll     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:            {
1.1.1.5 ! christos  485:              strcpy (comm1, _("Warning: illegal as emulation instr"));
1.1       skrll     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.  */
1.1.1.5 ! christos  497:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
1.1.1.4   christos  498:                {
1.1.1.5 ! christos  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:                    }
1.1.1.4   christos  513:                }
1.1       skrll     514:            }
                    515:          else if (regd == 2)
                    516:            {
                    517:              /* Absolute.  */
1.1.1.5 ! christos  518:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
1.1.1.4   christos  519:                {
1.1.1.5 ! christos  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:                    }
1.1.1.4   christos  537:                }
1.1       skrll     538:            }
                    539:          else
                    540:            {
                    541:              /* Indexed.  */
1.1.1.5 ! christos  542:              if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
1.1.1.4   christos  543:                {
1.1.1.5 ! christos  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);
1.1.1.4   christos  555:                }
1.1       skrll     556:            }
                    557:        }
                    558:
                    559:       *op2 = 0;
                    560:       *comm2 = 0;
1.1.1.4   christos  561:
1.1       skrll     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.  */
1.1.1.5 ! christos  569:       strcpy (comm1, _("Warning: illegal as 2-op instr"));
1.1       skrll     570:       return -1;
                    571:     }
                    572:
                    573:   /* Source.  */
                    574:   if (as == 0)
                    575:     {
                    576:       *cycles = 1;
                    577:       if (regs == 3)
                    578:        {
1.1.1.4   christos  579:          /* Constants.  */
1.1       skrll     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:     {
1.1.1.4   christos  591:       * cycles = print_as2_reg_name (regs, op1, comm1, 1, 1, regs == 0 ? 3 : 2);
1.1       skrll     592:     }
                    593:   else if (as == 3)
                    594:     {
1.1.1.4   christos  595:       if (regs == 0)
1.1       skrll     596:        {
                    597:          *cycles = 3;
                    598:          /* Absolute. @pc+.  */
1.1.1.5 ! christos  599:          if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
        !           600:            {
        !           601:              cmd_len += 2;
1.1.1.4   christos  602:              sprintf (op1, "#%d", dst);
                    603:              if (dst > 9 || dst < 0)
1.1.1.5 ! christos  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:                }
1.1.1.4   christos  615:            }
1.1       skrll     616:        }
                    617:       else
1.1.1.4   christos  618:        * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
1.1       skrll     619:     }
                    620:   else if (as == 1)
                    621:     {
                    622:       if (regs == 0)
                    623:        {
                    624:          *cycles = 4;
                    625:          /* PC relative.  */
1.1.1.5 ! christos  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:                }
1.1.1.4   christos  642:            }
1.1       skrll     643:        }
                    644:       else if (regs == 2)
                    645:        {
                    646:          *cycles = 2;
                    647:          /* Absolute.  */
1.1.1.5 ! christos  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:                }
1.1.1.4   christos  660:            }
1.1       skrll     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.  */
1.1.1.5 ! christos  672:          if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
1.1.1.4   christos  673:            {
1.1.1.5 ! christos  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:            }
1.1       skrll     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;
1.1.1.5 ! christos  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:                }
1.1.1.4   christos  730:            }
1.1       skrll     731:          cmd_len += 2;
                    732:        }
                    733:       else if (regd == 2)
                    734:        {
                    735:          /* Absolute.  */
1.1.1.5 ! christos  736:          if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
1.1.1.4   christos  737:            {
1.1.1.5 ! christos  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:                }
1.1.1.4   christos  745:            }
1.1       skrll     746:        }
                    747:       else
                    748:        {
1.1.1.5 ! christos  749:          if (msp430dis_opcode_signed (addr + cmd_len, info, &dst, comm2))
        !           750:            {
        !           751:              cmd_len += 2;
1.1.1.4   christos  752:              if (dst > 9 || dst < 0)
1.1.1.5 ! christos  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);
1.1.1.4   christos  763:            }
1.1       skrll     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;
1.1.1.2   christos  780:   int as = 0;
1.1       skrll     781:   int cmd_len = 2;
1.1.1.5 ! christos  782:   int dst = 0;
        !           783:   unsigned short udst = 0;
1.1       skrll     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:     {
1.1.1.4   christos  811:       * cycles = print_as2_reg_name (regs, op1, comm1, 2, 1, 2);
1.1       skrll     812:     }
                    813:   else if (as == 3)
                    814:     {
1.1.1.4   christos  815:       if (regs == 0)
1.1       skrll     816:        {
                    817:          /* Absolute. @pc+  */
                    818:          *cycles = 3;
1.1.1.5 ! christos  819:          if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
        !           820:            {
        !           821:              cmd_len += 2;
        !           822:              sprintf (op1, "#0x%04x", PS (udst));
        !           823:            }
1.1       skrll     824:        }
                    825:       else
1.1.1.4   christos  826:        * cycles = print_as3_reg_name (regs, op1, comm1, 1, 1, 2);
1.1       skrll     827:     }
                    828:   else if (as == 1)
                    829:     {
                    830:       * cycles = 3;
                    831:
                    832:       if (regs == 0)
                    833:        {
                    834:          /* PC relative.  */
1.1.1.5 ! christos  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:            }
1.1       skrll     843:        }
                    844:       else if (regs == 2)
                    845:        {
                    846:          /* Absolute.  */
1.1.1.5 ! christos  847:          if (msp430dis_opcode_unsigned (addr + 2, info, &udst, comm1))
        !           848:            {
        !           849:              cmd_len += 2;
        !           850:              sprintf (op1, "&0x%04x", PS (udst));
        !           851:            }
1.1       skrll     852:        }
                    853:       else if (regs == 3)
                    854:        {
                    855:          (*cycles)--;
                    856:          sprintf (op1, "#1");
                    857:          sprintf (comm1, "r3 As==01");
                    858:        }
                    859:       else
                    860:        {
1.1.1.4   christos  861:          /* Indexed.  */
1.1.1.5 ! christos  862:          if (msp430dis_opcode_signed (addr + 2, info, &dst, comm1))
        !           863:            {
        !           864:              cmd_len += 2;
        !           865:              sprintf (op1, "%d(r%d)", dst, regs);
        !           866:            }
1.1       skrll     867:        }
                    868:     }
                    869:
                    870:   return cmd_len;
                    871: }
                    872:
1.1.1.4   christos  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;
1.1.1.5 ! christos  886:   int            dst = 0;
1.1.1.4   christos  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;
1.1.1.5 ! christos  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:        }
1.1.1.4   christos  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 */
1.1.1.5 ! christos  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:        }
1.1.1.4   christos  926:       break;
                    927:
                    928:     case 9: /* CALLA pcrel-sym */
1.1.1.5 ! christos  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:        }
1.1.1.4   christos  937:       break;
                    938:
                    939:     case 11: /* CALLA #imm20 */
1.1.1.5 ! christos  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:        }
1.1.1.4   christos  947:       break;
                    948:
                    949:     default:
1.1.1.5 ! christos  950:       strcpy (comm1, _("Warning: unrecognised CALLA addressing mode"));
1.1.1.4   christos  951:       return -1;
                    952:     }
                    953:
                    954:   return cmd_len;
                    955: }
                    956:
1.1       skrll     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 = "";
1.1.1.4   christos  968:   unsigned short extension_word = 0;
1.1.1.5 ! christos  969:   unsigned short bits;
1.1       skrll     970:
1.1.1.5 ! christos  971:   if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
1.1.1.4   christos  972:     {
                    973:       prin (stream, ".word     0xffff; ????");
                    974:       return 2;
                    975:     }
1.1       skrll     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:
1.1.1.4   christos  986:   /* Check for an extension word.  */
                    987:   if ((insn & 0xf800) == 0x1800)
                    988:     {
                    989:       extension_word = insn;
                    990:       addr += 2;
1.1.1.5 ! christos  991:       if (! msp430dis_opcode_unsigned (addr, info, &insn, NULL))
1.1.1.4   christos  992:        {
                    993:          prin (stream, ".word  0x%04x, 0xffff; ????",
                    994:                extension_word);
                    995:          return 4;
                    996:        }
                    997:    }
                    998:
1.1       skrll     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.  */
1.1.1.4   christos 1010:          if (opcode->insn_opnumb == 3
                   1011:              && (insn & 0x000f) == 0
                   1012:              && (insn & 0x0080) == 0)
1.1       skrll    1013:            {
1.1.1.4   christos 1014:              cmd_len +=
1.1       skrll    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:            {
1.1.1.4   christos 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;
1.1.1.5 ! christos 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:                    }
1.1.1.4   christos 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;
1.1.1.5 ! christos 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:                    }
1.1.1.4   christos 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;
1.1.1.5 ! christos 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:                        }
1.1.1.4   christos 1141:                    }
                   1142:                  break;
                   1143:
                   1144:                case 6: /* MOVA Rsrc, &abs20 */
                   1145:                  cmd_len = 4;
                   1146:                  reg <<= 16;
1.1.1.5 ! christos 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:                    }
1.1.1.4   christos 1155:                  break;
                   1156:
                   1157:                case 7: /* MOVA Rsrc, x(Rdst) */
                   1158:                  cmd_len = 4;
                   1159:                  sprintf (op1, "r%d", n);
1.1.1.5 ! christos 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:                        }
1.1.1.4   christos 1171:                    }
                   1172:                  break;
                   1173:
                   1174:                case 8: /* MOVA #imm20, Rdst */
                   1175:                  cmd_len = 4;
                   1176:                  n <<= 16;
1.1.1.5 ! christos 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:                    }
1.1.1.4   christos 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:            {
1.1       skrll    1209:            case 0:
1.1.1.4   christos 1210:              cmd_len += msp430_nooperands (opcode, addr, insn, comm1, &cycles);
1.1       skrll    1211:              break;
                   1212:            case 2:
1.1.1.4   christos 1213:              cmd_len +=
1.1       skrll    1214:                msp430_doubleoperand (info, opcode, addr, insn, op1, op2,
1.1.1.4   christos 1215:                                      comm1, comm2,
                   1216:                                      extension_word,
                   1217:                                      &cycles);
1.1       skrll    1218:              if (insn & BYTE_OPERATION)
1.1.1.4   christos 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:                {
1.1.1.5 ! christos 1227:                  if (extension_word & BYTE_OPERATION)
1.1.1.4   christos 1228:                    bc = ".w";
                   1229:                  else
                   1230:                    {
                   1231:                      bc = ".?";
1.1.1.5 ! christos 1232:                      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1.1.1.4   christos 1233:                    }
                   1234:                }
                   1235:
1.1       skrll    1236:              break;
                   1237:            case 1:
1.1.1.4   christos 1238:              cmd_len +=
1.1       skrll    1239:                msp430_singleoperand (info, opcode, addr, insn, op1, comm1,
1.1.1.4   christos 1240:                                      extension_word,
1.1       skrll    1241:                                      &cycles);
1.1.1.4   christos 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 = ".?";
1.1.1.5 ! christos 1249:                      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1.1.1.4   christos 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 = ".?";
1.1.1.5 ! christos 1270:                      sprintf (comm2, _("Warning: reserved use of A/L and B/W bits detected"));
1.1.1.4   christos 1271:                    }
                   1272:                }
1.1       skrll    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.  */
1.1.1.4   christos 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:        }
1.1       skrll    1293:       (*prin) (stream, ".word  0x%04x; ????", PS (insn));
                   1294:       return 2;
                   1295:     }
                   1296:
1.1.1.4   christos 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:
1.1.1.5 ! christos 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')
1.1.1.4   christos 1312:     (*prin) (stream, "%sx%s", opcode->name, bc);
                   1313:   else
                   1314:     (*prin) (stream, "%s%s", opcode->name, bc);
1.1       skrll    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);
1.1.1.4   christos 1351:
                   1352:   if (extension_word)
                   1353:     cmd_len += 2;
                   1354:
1.1       skrll    1355:   return cmd_len;
                   1356: }

CVSweb <webmaster@jp.NetBSD.org>