Home | History | Annotate | Line # | Download | only in opcodes
alpha-dis.c revision 1.1.1.1.2.1
      1          1.1  christos /* alpha-dis.c -- Disassemble Alpha AXP instructions
      2  1.1.1.1.2.1  pgoyette    Copyright (C) 1996-2015 Free Software Foundation, Inc.
      3          1.1  christos    Contributed by Richard Henderson <rth (at) tamu.edu>,
      4          1.1  christos    patterned after the PPC opcode handling written by Ian Lance Taylor.
      5          1.1  christos 
      6          1.1  christos    This file is part of libopcodes.
      7          1.1  christos 
      8          1.1  christos    This library is free software; you can redistribute it and/or modify
      9          1.1  christos    it under the terms of the GNU General Public License as published by
     10          1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     11          1.1  christos    any later version.
     12          1.1  christos 
     13          1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     14          1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15          1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     16          1.1  christos    License for more details.
     17          1.1  christos 
     18          1.1  christos    You should have received a copy of the GNU General Public License
     19          1.1  christos    along with this file; see the file COPYING.  If not, write to the Free
     20          1.1  christos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     21          1.1  christos    02110-1301, USA.  */
     22          1.1  christos 
     23          1.1  christos #include "sysdep.h"
     24          1.1  christos #include <stdio.h>
     25          1.1  christos #include "dis-asm.h"
     26          1.1  christos #include "opcode/alpha.h"
     27          1.1  christos 
     28          1.1  christos /* OSF register names.  */
     29          1.1  christos 
     30          1.1  christos static const char * const osf_regnames[64] = {
     31          1.1  christos   "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
     32          1.1  christos   "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
     33          1.1  christos   "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
     34          1.1  christos   "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero",
     35          1.1  christos   "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
     36          1.1  christos   "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
     37          1.1  christos   "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
     38          1.1  christos   "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
     39          1.1  christos };
     40          1.1  christos 
     41          1.1  christos /* VMS register names.  */
     42          1.1  christos 
     43          1.1  christos static const char * const vms_regnames[64] = {
     44          1.1  christos   "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
     45          1.1  christos   "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
     46          1.1  christos   "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
     47          1.1  christos   "R24", "AI", "RA", "PV", "AT", "FP", "SP", "RZ",
     48          1.1  christos   "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
     49          1.1  christos   "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15",
     50          1.1  christos   "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23",
     51          1.1  christos   "F24", "F25", "F26", "F27", "F28", "F29", "F30", "FZ"
     52          1.1  christos };
     53          1.1  christos 
     54          1.1  christos /* Disassemble Alpha instructions.  */
     55          1.1  christos 
     56          1.1  christos int
     57          1.1  christos print_insn_alpha (memaddr, info)
     58          1.1  christos      bfd_vma memaddr;
     59          1.1  christos      struct disassemble_info *info;
     60          1.1  christos {
     61          1.1  christos   static const struct alpha_opcode *opcode_index[AXP_NOPS+1];
     62          1.1  christos   const char * const * regnames;
     63          1.1  christos   const struct alpha_opcode *opcode, *opcode_end;
     64          1.1  christos   const unsigned char *opindex;
     65          1.1  christos   unsigned insn, op, isa_mask;
     66          1.1  christos   int need_comma;
     67          1.1  christos 
     68          1.1  christos   /* Initialize the majorop table the first time through */
     69          1.1  christos   if (!opcode_index[0])
     70          1.1  christos     {
     71          1.1  christos       opcode = alpha_opcodes;
     72          1.1  christos       opcode_end = opcode + alpha_num_opcodes;
     73          1.1  christos 
     74          1.1  christos       for (op = 0; op < AXP_NOPS; ++op)
     75          1.1  christos 	{
     76          1.1  christos 	  opcode_index[op] = opcode;
     77          1.1  christos 	  while (opcode < opcode_end && op == AXP_OP (opcode->opcode))
     78          1.1  christos 	    ++opcode;
     79          1.1  christos 	}
     80          1.1  christos       opcode_index[op] = opcode;
     81          1.1  christos     }
     82          1.1  christos 
     83          1.1  christos   if (info->flavour == bfd_target_evax_flavour)
     84          1.1  christos     regnames = vms_regnames;
     85          1.1  christos   else
     86          1.1  christos     regnames = osf_regnames;
     87          1.1  christos 
     88          1.1  christos   isa_mask = AXP_OPCODE_NOPAL;
     89          1.1  christos   switch (info->mach)
     90          1.1  christos     {
     91          1.1  christos     case bfd_mach_alpha_ev4:
     92          1.1  christos       isa_mask |= AXP_OPCODE_EV4;
     93          1.1  christos       break;
     94          1.1  christos     case bfd_mach_alpha_ev5:
     95          1.1  christos       isa_mask |= AXP_OPCODE_EV5;
     96          1.1  christos       break;
     97          1.1  christos     case bfd_mach_alpha_ev6:
     98          1.1  christos       isa_mask |= AXP_OPCODE_EV6;
     99          1.1  christos       break;
    100          1.1  christos     }
    101          1.1  christos 
    102          1.1  christos   /* Read the insn into a host word */
    103          1.1  christos   {
    104          1.1  christos     bfd_byte buffer[4];
    105          1.1  christos     int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
    106          1.1  christos     if (status != 0)
    107          1.1  christos       {
    108          1.1  christos 	(*info->memory_error_func) (status, memaddr, info);
    109          1.1  christos 	return -1;
    110          1.1  christos       }
    111          1.1  christos     insn = bfd_getl32 (buffer);
    112          1.1  christos   }
    113          1.1  christos 
    114          1.1  christos   /* Get the major opcode of the instruction.  */
    115          1.1  christos   op = AXP_OP (insn);
    116          1.1  christos 
    117          1.1  christos   /* Find the first match in the opcode table.  */
    118          1.1  christos   opcode_end = opcode_index[op + 1];
    119          1.1  christos   for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode)
    120          1.1  christos     {
    121          1.1  christos       if ((insn ^ opcode->opcode) & opcode->mask)
    122          1.1  christos 	continue;
    123          1.1  christos 
    124          1.1  christos       if (!(opcode->flags & isa_mask))
    125          1.1  christos 	continue;
    126          1.1  christos 
    127          1.1  christos       /* Make two passes over the operands.  First see if any of them
    128          1.1  christos 	 have extraction functions, and, if they do, make sure the
    129          1.1  christos 	 instruction is valid.  */
    130          1.1  christos       {
    131          1.1  christos 	int invalid = 0;
    132          1.1  christos 	for (opindex = opcode->operands; *opindex != 0; opindex++)
    133          1.1  christos 	  {
    134          1.1  christos 	    const struct alpha_operand *operand = alpha_operands + *opindex;
    135          1.1  christos 	    if (operand->extract)
    136          1.1  christos 	      (*operand->extract) (insn, &invalid);
    137          1.1  christos 	  }
    138          1.1  christos 	if (invalid)
    139          1.1  christos 	  continue;
    140          1.1  christos       }
    141          1.1  christos 
    142          1.1  christos       /* The instruction is valid.  */
    143          1.1  christos       goto found;
    144          1.1  christos     }
    145          1.1  christos 
    146          1.1  christos   /* No instruction found */
    147          1.1  christos   (*info->fprintf_func) (info->stream, ".long %#08x", insn);
    148          1.1  christos 
    149          1.1  christos   return 4;
    150          1.1  christos 
    151          1.1  christos found:
    152          1.1  christos   (*info->fprintf_func) (info->stream, "%s", opcode->name);
    153          1.1  christos   if (opcode->operands[0] != 0)
    154          1.1  christos     (*info->fprintf_func) (info->stream, "\t");
    155          1.1  christos 
    156          1.1  christos   /* Now extract and print the operands.  */
    157          1.1  christos   need_comma = 0;
    158          1.1  christos   for (opindex = opcode->operands; *opindex != 0; opindex++)
    159          1.1  christos     {
    160          1.1  christos       const struct alpha_operand *operand = alpha_operands + *opindex;
    161          1.1  christos       int value;
    162          1.1  christos 
    163          1.1  christos       /* Operands that are marked FAKE are simply ignored.  We
    164          1.1  christos 	 already made sure that the extract function considered
    165          1.1  christos 	 the instruction to be valid.  */
    166          1.1  christos       if ((operand->flags & AXP_OPERAND_FAKE) != 0)
    167          1.1  christos 	continue;
    168          1.1  christos 
    169          1.1  christos       /* Extract the value from the instruction.  */
    170          1.1  christos       if (operand->extract)
    171          1.1  christos 	value = (*operand->extract) (insn, (int *) NULL);
    172          1.1  christos       else
    173          1.1  christos 	{
    174          1.1  christos 	  value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
    175          1.1  christos 	  if (operand->flags & AXP_OPERAND_SIGNED)
    176          1.1  christos 	    {
    177          1.1  christos 	      int signbit = 1 << (operand->bits - 1);
    178          1.1  christos 	      value = (value ^ signbit) - signbit;
    179          1.1  christos 	    }
    180          1.1  christos 	}
    181          1.1  christos 
    182          1.1  christos       if (need_comma &&
    183          1.1  christos 	  ((operand->flags & (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA))
    184          1.1  christos 	   != AXP_OPERAND_PARENS))
    185          1.1  christos 	{
    186          1.1  christos 	  (*info->fprintf_func) (info->stream, ",");
    187          1.1  christos 	}
    188          1.1  christos       if (operand->flags & AXP_OPERAND_PARENS)
    189          1.1  christos 	(*info->fprintf_func) (info->stream, "(");
    190          1.1  christos 
    191          1.1  christos       /* Print the operand as directed by the flags.  */
    192          1.1  christos       if (operand->flags & AXP_OPERAND_IR)
    193          1.1  christos 	(*info->fprintf_func) (info->stream, "%s", regnames[value]);
    194          1.1  christos       else if (operand->flags & AXP_OPERAND_FPR)
    195          1.1  christos 	(*info->fprintf_func) (info->stream, "%s", regnames[value + 32]);
    196          1.1  christos       else if (operand->flags & AXP_OPERAND_RELATIVE)
    197          1.1  christos 	(*info->print_address_func) (memaddr + 4 + value, info);
    198          1.1  christos       else if (operand->flags & AXP_OPERAND_SIGNED)
    199          1.1  christos 	(*info->fprintf_func) (info->stream, "%d", value);
    200          1.1  christos       else
    201          1.1  christos 	(*info->fprintf_func) (info->stream, "%#x", value);
    202          1.1  christos 
    203          1.1  christos       if (operand->flags & AXP_OPERAND_PARENS)
    204          1.1  christos 	(*info->fprintf_func) (info->stream, ")");
    205          1.1  christos       need_comma = 1;
    206          1.1  christos     }
    207          1.1  christos 
    208          1.1  christos   return 4;
    209          1.1  christos }
    210