Home | History | Annotate | Line # | Download | only in opcodes
pdp11-dis.c revision 1.1.1.3.2.1
      1          1.1     skrll /* Print DEC PDP-11 instructions.
      2  1.1.1.3.2.1  pgoyette    Copyright (C) 2001-2016 Free Software Foundation, Inc.
      3          1.1     skrll 
      4          1.1     skrll    This file is part of the GNU opcodes library.
      5          1.1     skrll 
      6          1.1     skrll    This library is free software; you can redistribute it and/or modify
      7          1.1     skrll    it under the terms of the GNU General Public License as published by
      8          1.1     skrll    the Free Software Foundation; either version 3, or (at your option)
      9          1.1     skrll    any later version.
     10          1.1     skrll 
     11          1.1     skrll    It is distributed in the hope that it will be useful, but WITHOUT
     12          1.1     skrll    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     13          1.1     skrll    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     14          1.1     skrll    License for more details.
     15          1.1     skrll 
     16          1.1     skrll    You should have received a copy of the GNU General Public License
     17          1.1     skrll    along with this program; if not, write to the Free Software
     18          1.1     skrll    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19          1.1     skrll    MA 02110-1301, USA.  */
     20          1.1     skrll 
     21          1.1     skrll #include "sysdep.h"
     22          1.1     skrll #include "dis-asm.h"
     23          1.1     skrll #include "opcode/pdp11.h"
     24          1.1     skrll 
     25          1.1     skrll #define AFTER_INSTRUCTION	"\t"
     26          1.1     skrll #define OPERAND_SEPARATOR	", "
     27          1.1     skrll 
     28          1.1     skrll #define JUMP	0x1000	/* Flag that this operand is used in a jump.  */
     29          1.1     skrll 
     30          1.1     skrll #define FPRINTF	(*info->fprintf_func)
     31          1.1     skrll #define F	info->stream
     32          1.1     skrll 
     33          1.1     skrll /* Sign-extend a 16-bit number in an int.  */
     34          1.1     skrll #define SIGN_BITS	(8 * sizeof (int) - 16)
     35          1.1     skrll #define sign_extend(x) (((x) << SIGN_BITS) >> SIGN_BITS)
     36          1.1     skrll 
     37          1.1     skrll static int
     38          1.1     skrll read_word (bfd_vma memaddr, int *word, disassemble_info *info)
     39          1.1     skrll {
     40          1.1     skrll   int status;
     41          1.1     skrll   bfd_byte x[2];
     42          1.1     skrll 
     43          1.1     skrll   status = (*info->read_memory_func) (memaddr, x, 2, info);
     44          1.1     skrll   if (status != 0)
     45          1.1     skrll     return -1;
     46          1.1     skrll 
     47          1.1     skrll   *word = x[1] << 8 | x[0];
     48          1.1     skrll   return 0;
     49          1.1     skrll }
     50          1.1     skrll 
     51          1.1     skrll static void
     52          1.1     skrll print_signed_octal (int n, disassemble_info *info)
     53          1.1     skrll {
     54          1.1     skrll   if (n < 0)
     55          1.1     skrll     FPRINTF (F, "-%o", -n);
     56          1.1     skrll   else
     57          1.1     skrll     FPRINTF (F, "%o", n);
     58          1.1     skrll }
     59          1.1     skrll 
     60          1.1     skrll static void
     61          1.1     skrll print_reg (int reg, disassemble_info *info)
     62          1.1     skrll {
     63          1.1     skrll   /* Mask off the addressing mode, if any.  */
     64          1.1     skrll   reg &= 7;
     65          1.1     skrll 
     66          1.1     skrll   switch (reg)
     67          1.1     skrll     {
     68          1.1     skrll     case 0: case 1: case 2: case 3: case 4: case 5:
     69          1.1     skrll 		FPRINTF (F, "r%d", reg); break;
     70          1.1     skrll     case 6:	FPRINTF (F, "sp"); break;
     71          1.1     skrll     case 7:	FPRINTF (F, "pc"); break;
     72          1.1     skrll     default: ;	/* error */
     73          1.1     skrll     }
     74          1.1     skrll }
     75          1.1     skrll 
     76          1.1     skrll static void
     77          1.1     skrll print_freg (int freg, disassemble_info *info)
     78          1.1     skrll {
     79          1.1     skrll   FPRINTF (F, "fr%d", freg);
     80          1.1     skrll }
     81          1.1     skrll 
     82          1.1     skrll static int
     83          1.1     skrll print_operand (bfd_vma *memaddr, int code, disassemble_info *info)
     84          1.1     skrll {
     85          1.1     skrll   int mode = (code >> 3) & 7;
     86          1.1     skrll   int reg = code & 7;
     87          1.1     skrll   int disp;
     88          1.1     skrll 
     89          1.1     skrll   switch (mode)
     90          1.1     skrll     {
     91          1.1     skrll     case 0:
     92          1.1     skrll       print_reg (reg, info);
     93          1.1     skrll       break;
     94          1.1     skrll     case 1:
     95          1.1     skrll       FPRINTF (F, "(");
     96          1.1     skrll       print_reg (reg, info);
     97          1.1     skrll       FPRINTF (F, ")");
     98          1.1     skrll       break;
     99          1.1     skrll     case 2:
    100          1.1     skrll       if (reg == 7)
    101          1.1     skrll 	{
    102          1.1     skrll 	  int data;
    103          1.1     skrll 
    104          1.1     skrll 	  if (read_word (*memaddr, &data, info) < 0)
    105          1.1     skrll 	    return -1;
    106          1.1     skrll 	  FPRINTF (F, "$");
    107          1.1     skrll 	  print_signed_octal (sign_extend (data), info);
    108          1.1     skrll 	  *memaddr += 2;
    109          1.1     skrll 	}
    110          1.1     skrll       else
    111          1.1     skrll 	{
    112          1.1     skrll 	  FPRINTF (F, "(");
    113          1.1     skrll 	  print_reg (reg, info);
    114          1.1     skrll 	  FPRINTF (F, ")+");
    115          1.1     skrll 	}
    116          1.1     skrll 	break;
    117          1.1     skrll     case 3:
    118          1.1     skrll       if (reg == 7)
    119          1.1     skrll 	{
    120          1.1     skrll 	  int address;
    121          1.1     skrll 
    122          1.1     skrll 	  if (read_word (*memaddr, &address, info) < 0)
    123          1.1     skrll 	    return -1;
    124          1.1     skrll 	  FPRINTF (F, "*$%o", address);
    125          1.1     skrll 	  *memaddr += 2;
    126          1.1     skrll 	}
    127          1.1     skrll       else
    128          1.1     skrll 	{
    129          1.1     skrll 	  FPRINTF (F, "*(");
    130          1.1     skrll 	  print_reg (reg, info);
    131          1.1     skrll 	  FPRINTF (F, ")+");
    132          1.1     skrll 	}
    133          1.1     skrll 	break;
    134          1.1     skrll     case 4:
    135          1.1     skrll       FPRINTF (F, "-(");
    136          1.1     skrll       print_reg (reg, info);
    137          1.1     skrll       FPRINTF (F, ")");
    138          1.1     skrll       break;
    139          1.1     skrll     case 5:
    140          1.1     skrll       FPRINTF (F, "*-(");
    141          1.1     skrll       print_reg (reg, info);
    142          1.1     skrll       FPRINTF (F, ")");
    143          1.1     skrll       break;
    144          1.1     skrll     case 6:
    145          1.1     skrll     case 7:
    146          1.1     skrll       if (read_word (*memaddr, &disp, info) < 0)
    147          1.1     skrll 	return -1;
    148          1.1     skrll       *memaddr += 2;
    149          1.1     skrll       if (reg == 7)
    150          1.1     skrll 	{
    151          1.1     skrll 	  bfd_vma address = *memaddr + sign_extend (disp);
    152          1.1     skrll 
    153          1.1     skrll 	  if (mode == 7)
    154          1.1     skrll 	    FPRINTF (F, "*");
    155          1.1     skrll 	  if (!(code & JUMP))
    156          1.1     skrll 	    FPRINTF (F, "$");
    157          1.1     skrll 	  (*info->print_address_func) (address, info);
    158          1.1     skrll 	}
    159          1.1     skrll       else
    160          1.1     skrll 	{
    161          1.1     skrll 	  if (mode == 7)
    162          1.1     skrll 	    FPRINTF (F, "*");
    163          1.1     skrll 	  print_signed_octal (sign_extend (disp), info);
    164          1.1     skrll 	  FPRINTF (F, "(");
    165          1.1     skrll 	  print_reg (reg, info);
    166          1.1     skrll 	  FPRINTF (F, ")");
    167          1.1     skrll 	}
    168          1.1     skrll       break;
    169          1.1     skrll     }
    170          1.1     skrll 
    171          1.1     skrll   return 0;
    172          1.1     skrll }
    173          1.1     skrll 
    174          1.1     skrll static int
    175          1.1     skrll print_foperand (bfd_vma *memaddr, int code, disassemble_info *info)
    176          1.1     skrll {
    177          1.1     skrll   int mode = (code >> 3) & 7;
    178          1.1     skrll   int reg = code & 7;
    179          1.1     skrll 
    180          1.1     skrll   if (mode == 0)
    181          1.1     skrll     print_freg (reg, info);
    182          1.1     skrll   else
    183          1.1     skrll     return print_operand (memaddr, code, info);
    184          1.1     skrll 
    185          1.1     skrll   return 0;
    186          1.1     skrll }
    187          1.1     skrll 
    188          1.1     skrll /* Print the PDP-11 instruction at address MEMADDR in debugged memory,
    189          1.1     skrll    on INFO->STREAM.  Returns length of the instruction, in bytes.  */
    190          1.1     skrll 
    191          1.1     skrll int
    192          1.1     skrll print_insn_pdp11 (bfd_vma memaddr, disassemble_info *info)
    193          1.1     skrll {
    194          1.1     skrll   bfd_vma start_memaddr = memaddr;
    195          1.1     skrll   int opcode;
    196          1.1     skrll   int src, dst;
    197          1.1     skrll   int i;
    198          1.1     skrll 
    199          1.1     skrll   info->bytes_per_line = 6;
    200          1.1     skrll   info->bytes_per_chunk = 2;
    201          1.1     skrll   info->display_endian = BFD_ENDIAN_LITTLE;
    202          1.1     skrll 
    203          1.1     skrll   if (read_word (memaddr, &opcode, info) != 0)
    204          1.1     skrll     return -1;
    205          1.1     skrll   memaddr += 2;
    206          1.1     skrll 
    207          1.1     skrll   src = (opcode >> 6) & 0x3f;
    208          1.1     skrll   dst = opcode & 0x3f;
    209          1.1     skrll 
    210          1.1     skrll   for (i = 0; i < pdp11_num_opcodes; i++)
    211          1.1     skrll     {
    212          1.1     skrll #define OP pdp11_opcodes[i]
    213          1.1     skrll       if ((opcode & OP.mask) == OP.opcode)
    214          1.1     skrll 	switch (OP.type)
    215          1.1     skrll 	  {
    216          1.1     skrll 	  case PDP11_OPCODE_NO_OPS:
    217      1.1.1.2  christos 	    FPRINTF (F, "%s", OP.name);
    218          1.1     skrll 	    goto done;
    219          1.1     skrll 	  case PDP11_OPCODE_REG:
    220      1.1.1.2  christos 	    FPRINTF (F, "%s", OP.name);
    221          1.1     skrll 	    FPRINTF (F, AFTER_INSTRUCTION);
    222          1.1     skrll 	    print_reg (dst, info);
    223          1.1     skrll 	    goto done;
    224          1.1     skrll 	  case PDP11_OPCODE_OP:
    225      1.1.1.2  christos 	    FPRINTF (F, "%s", OP.name);
    226          1.1     skrll 	    FPRINTF (F, AFTER_INSTRUCTION);
    227          1.1     skrll 	    if (strcmp (OP.name, "jmp") == 0)
    228          1.1     skrll 	      dst |= JUMP;
    229          1.1     skrll 	    if (print_operand (&memaddr, dst, info) < 0)
    230          1.1     skrll 	      return -1;
    231          1.1     skrll 	    goto done;
    232          1.1     skrll 	  case PDP11_OPCODE_FOP:
    233      1.1.1.2  christos 	    FPRINTF (F, "%s", OP.name);
    234          1.1     skrll 	    FPRINTF (F, AFTER_INSTRUCTION);
    235          1.1     skrll 	    if (strcmp (OP.name, "jmp") == 0)
    236          1.1     skrll 	      dst |= JUMP;
    237          1.1     skrll 	    if (print_foperand (&memaddr, dst, info) < 0)
    238          1.1     skrll 	      return -1;
    239          1.1     skrll 	    goto done;
    240          1.1     skrll 	  case PDP11_OPCODE_REG_OP:
    241      1.1.1.2  christos 	    FPRINTF (F, "%s", OP.name);
    242          1.1     skrll 	    FPRINTF (F, AFTER_INSTRUCTION);
    243          1.1     skrll 	    print_reg (src, info);
    244          1.1     skrll 	    FPRINTF (F, OPERAND_SEPARATOR);
    245          1.1     skrll 	    if (strcmp (OP.name, "jsr") == 0)
    246          1.1     skrll 	      dst |= JUMP;
    247          1.1     skrll 	    if (print_operand (&memaddr, dst, info) < 0)
    248          1.1     skrll 	      return -1;
    249          1.1     skrll 	    goto done;
    250          1.1     skrll 	  case PDP11_OPCODE_REG_OP_REV:
    251      1.1.1.2  christos 	    FPRINTF (F, "%s", OP.name);
    252          1.1     skrll 	    FPRINTF (F, AFTER_INSTRUCTION);
    253          1.1     skrll 	    if (print_operand (&memaddr, dst, info) < 0)
    254          1.1     skrll 	      return -1;
    255          1.1     skrll 	    FPRINTF (F, OPERAND_SEPARATOR);
    256          1.1     skrll 	    print_reg (src, info);
    257          1.1     skrll 	    goto done;
    258          1.1     skrll 	  case PDP11_OPCODE_AC_FOP:
    259          1.1     skrll 	    {
    260          1.1     skrll 	      int ac = (opcode & 0xe0) >> 6;
    261      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    262          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    263          1.1     skrll 	      print_freg (ac, info);
    264          1.1     skrll 	      FPRINTF (F, OPERAND_SEPARATOR);
    265          1.1     skrll 	      if (print_foperand (&memaddr, dst, info) < 0)
    266          1.1     skrll 		return -1;
    267          1.1     skrll 	      goto done;
    268          1.1     skrll 	    }
    269          1.1     skrll 	  case PDP11_OPCODE_FOP_AC:
    270          1.1     skrll 	    {
    271          1.1     skrll 	      int ac = (opcode & 0xe0) >> 6;
    272      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    273          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    274          1.1     skrll 	      if (print_foperand (&memaddr, dst, info) < 0)
    275          1.1     skrll 		return -1;
    276          1.1     skrll 	      FPRINTF (F, OPERAND_SEPARATOR);
    277          1.1     skrll 	      print_freg (ac, info);
    278          1.1     skrll 	      goto done;
    279          1.1     skrll 	    }
    280          1.1     skrll 	  case PDP11_OPCODE_AC_OP:
    281          1.1     skrll 	    {
    282          1.1     skrll 	      int ac = (opcode & 0xe0) >> 6;
    283      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    284          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    285          1.1     skrll 	      print_freg (ac, info);
    286          1.1     skrll 	      FPRINTF (F, OPERAND_SEPARATOR);
    287          1.1     skrll 	      if (print_operand (&memaddr, dst, info) < 0)
    288          1.1     skrll 		return -1;
    289          1.1     skrll 	      goto done;
    290          1.1     skrll 	    }
    291          1.1     skrll 	  case PDP11_OPCODE_OP_AC:
    292          1.1     skrll 	    {
    293          1.1     skrll 	      int ac = (opcode & 0xe0) >> 6;
    294      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    295          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    296          1.1     skrll 	      if (print_operand (&memaddr, dst, info) < 0)
    297          1.1     skrll 		return -1;
    298          1.1     skrll 	      FPRINTF (F, OPERAND_SEPARATOR);
    299          1.1     skrll 	      print_freg (ac, info);
    300          1.1     skrll 	      goto done;
    301          1.1     skrll 	    }
    302          1.1     skrll 	  case PDP11_OPCODE_OP_OP:
    303      1.1.1.2  christos 	    FPRINTF (F, "%s", OP.name);
    304          1.1     skrll 	    FPRINTF (F, AFTER_INSTRUCTION);
    305          1.1     skrll 	    if (print_operand (&memaddr, src, info) < 0)
    306          1.1     skrll 	      return -1;
    307          1.1     skrll 	    FPRINTF (F, OPERAND_SEPARATOR);
    308          1.1     skrll 	    if (print_operand (&memaddr, dst, info) < 0)
    309          1.1     skrll 	      return -1;
    310          1.1     skrll 	    goto done;
    311          1.1     skrll 	  case PDP11_OPCODE_DISPL:
    312          1.1     skrll 	    {
    313          1.1     skrll 	      int displ = (opcode & 0xff) << 8;
    314          1.1     skrll 	      bfd_vma address = memaddr + (sign_extend (displ) >> 7);
    315      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    316          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    317          1.1     skrll 	      (*info->print_address_func) (address, info);
    318          1.1     skrll 	      goto done;
    319          1.1     skrll 	    }
    320          1.1     skrll 	  case PDP11_OPCODE_REG_DISPL:
    321          1.1     skrll 	    {
    322          1.1     skrll 	      int displ = (opcode & 0x3f) << 10;
    323          1.1     skrll 	      bfd_vma address = memaddr - (displ >> 9);
    324          1.1     skrll 
    325      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    326          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    327          1.1     skrll 	      print_reg (src, info);
    328          1.1     skrll 	      FPRINTF (F, OPERAND_SEPARATOR);
    329          1.1     skrll 	      (*info->print_address_func) (address, info);
    330          1.1     skrll 	      goto done;
    331          1.1     skrll 	    }
    332          1.1     skrll 	  case PDP11_OPCODE_IMM8:
    333          1.1     skrll 	    {
    334          1.1     skrll 	      int code = opcode & 0xff;
    335      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    336          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    337          1.1     skrll 	      FPRINTF (F, "%o", code);
    338          1.1     skrll 	      goto done;
    339          1.1     skrll 	    }
    340          1.1     skrll 	  case PDP11_OPCODE_IMM6:
    341          1.1     skrll 	    {
    342          1.1     skrll 	      int code = opcode & 0x3f;
    343      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    344          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    345          1.1     skrll 	      FPRINTF (F, "%o", code);
    346          1.1     skrll 	      goto done;
    347          1.1     skrll 	    }
    348          1.1     skrll 	  case PDP11_OPCODE_IMM3:
    349          1.1     skrll 	    {
    350          1.1     skrll 	      int code = opcode & 7;
    351      1.1.1.2  christos 	      FPRINTF (F, "%s", OP.name);
    352          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    353          1.1     skrll 	      FPRINTF (F, "%o", code);
    354          1.1     skrll 	      goto done;
    355          1.1     skrll 	    }
    356          1.1     skrll 	  case PDP11_OPCODE_ILLEGAL:
    357          1.1     skrll 	    {
    358          1.1     skrll 	      FPRINTF (F, ".word");
    359          1.1     skrll 	      FPRINTF (F, AFTER_INSTRUCTION);
    360          1.1     skrll 	      FPRINTF (F, "%o", opcode);
    361          1.1     skrll 	      goto done;
    362          1.1     skrll 	    }
    363          1.1     skrll 	  default:
    364          1.1     skrll 	    /* TODO: is this a proper way of signalling an error? */
    365          1.1     skrll 	    FPRINTF (F, "<internal error: unrecognized instruction type>");
    366          1.1     skrll 	    return -1;
    367          1.1     skrll 	  }
    368          1.1     skrll #undef OP
    369          1.1     skrll     }
    370          1.1     skrll  done:
    371          1.1     skrll 
    372          1.1     skrll   return memaddr - start_memaddr;
    373          1.1     skrll }
    374