Home | History | Annotate | Line # | Download | only in opcodes
      1   1.1  christos /* alpha-dis.c -- Disassemble Alpha AXP instructions
      2  1.10  christos    Copyright (C) 1996-2025 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.6  christos #include "disassemble.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.5  christos print_insn_alpha (bfd_vma memaddr, struct disassemble_info *info)
     58   1.1  christos {
     59   1.1  christos   static const struct alpha_opcode *opcode_index[AXP_NOPS+1];
     60   1.1  christos   const char * const * regnames;
     61   1.1  christos   const struct alpha_opcode *opcode, *opcode_end;
     62   1.1  christos   const unsigned char *opindex;
     63   1.1  christos   unsigned insn, op, isa_mask;
     64   1.1  christos   int need_comma;
     65   1.1  christos 
     66   1.1  christos   /* Initialize the majorop table the first time through */
     67   1.1  christos   if (!opcode_index[0])
     68   1.1  christos     {
     69   1.1  christos       opcode = alpha_opcodes;
     70   1.1  christos       opcode_end = opcode + alpha_num_opcodes;
     71   1.1  christos 
     72   1.1  christos       for (op = 0; op < AXP_NOPS; ++op)
     73   1.1  christos 	{
     74   1.1  christos 	  opcode_index[op] = opcode;
     75   1.1  christos 	  while (opcode < opcode_end && op == AXP_OP (opcode->opcode))
     76   1.1  christos 	    ++opcode;
     77   1.1  christos 	}
     78   1.1  christos       opcode_index[op] = opcode;
     79   1.1  christos     }
     80   1.1  christos 
     81   1.1  christos   if (info->flavour == bfd_target_evax_flavour)
     82   1.1  christos     regnames = vms_regnames;
     83   1.1  christos   else
     84   1.1  christos     regnames = osf_regnames;
     85   1.1  christos 
     86   1.1  christos   isa_mask = AXP_OPCODE_NOPAL;
     87   1.1  christos   switch (info->mach)
     88   1.1  christos     {
     89   1.1  christos     case bfd_mach_alpha_ev4:
     90   1.1  christos       isa_mask |= AXP_OPCODE_EV4;
     91   1.1  christos       break;
     92   1.1  christos     case bfd_mach_alpha_ev5:
     93   1.1  christos       isa_mask |= AXP_OPCODE_EV5;
     94   1.1  christos       break;
     95   1.1  christos     case bfd_mach_alpha_ev6:
     96   1.1  christos       isa_mask |= AXP_OPCODE_EV6;
     97   1.1  christos       break;
     98   1.1  christos     }
     99   1.1  christos 
    100   1.1  christos   /* Read the insn into a host word */
    101   1.1  christos   {
    102   1.1  christos     bfd_byte buffer[4];
    103   1.1  christos     int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
    104   1.1  christos     if (status != 0)
    105   1.1  christos       {
    106   1.1  christos 	(*info->memory_error_func) (status, memaddr, info);
    107   1.1  christos 	return -1;
    108   1.1  christos       }
    109   1.1  christos     insn = bfd_getl32 (buffer);
    110   1.1  christos   }
    111   1.1  christos 
    112   1.1  christos   /* Get the major opcode of the instruction.  */
    113   1.1  christos   op = AXP_OP (insn);
    114   1.1  christos 
    115   1.1  christos   /* Find the first match in the opcode table.  */
    116   1.1  christos   opcode_end = opcode_index[op + 1];
    117   1.1  christos   for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode)
    118   1.1  christos     {
    119   1.1  christos       if ((insn ^ opcode->opcode) & opcode->mask)
    120   1.1  christos 	continue;
    121   1.1  christos 
    122   1.1  christos       if (!(opcode->flags & isa_mask))
    123   1.1  christos 	continue;
    124   1.1  christos 
    125   1.1  christos       /* Make two passes over the operands.  First see if any of them
    126   1.1  christos 	 have extraction functions, and, if they do, make sure the
    127   1.1  christos 	 instruction is valid.  */
    128   1.1  christos       {
    129   1.1  christos 	int invalid = 0;
    130   1.1  christos 	for (opindex = opcode->operands; *opindex != 0; opindex++)
    131   1.1  christos 	  {
    132   1.1  christos 	    const struct alpha_operand *operand = alpha_operands + *opindex;
    133   1.1  christos 	    if (operand->extract)
    134   1.1  christos 	      (*operand->extract) (insn, &invalid);
    135   1.1  christos 	  }
    136   1.1  christos 	if (invalid)
    137   1.1  christos 	  continue;
    138   1.1  christos       }
    139   1.1  christos 
    140   1.1  christos       /* The instruction is valid.  */
    141   1.1  christos       goto found;
    142   1.1  christos     }
    143   1.1  christos 
    144   1.1  christos   /* No instruction found */
    145   1.1  christos   (*info->fprintf_func) (info->stream, ".long %#08x", insn);
    146   1.1  christos 
    147   1.1  christos   return 4;
    148   1.1  christos 
    149   1.8  christos  found:
    150   1.1  christos   (*info->fprintf_func) (info->stream, "%s", opcode->name);
    151   1.1  christos   if (opcode->operands[0] != 0)
    152   1.1  christos     (*info->fprintf_func) (info->stream, "\t");
    153   1.1  christos 
    154   1.1  christos   /* Now extract and print the operands.  */
    155   1.1  christos   need_comma = 0;
    156   1.1  christos   for (opindex = opcode->operands; *opindex != 0; opindex++)
    157   1.1  christos     {
    158   1.1  christos       const struct alpha_operand *operand = alpha_operands + *opindex;
    159   1.1  christos       int value;
    160   1.1  christos 
    161   1.1  christos       /* Operands that are marked FAKE are simply ignored.  We
    162   1.1  christos 	 already made sure that the extract function considered
    163   1.1  christos 	 the instruction to be valid.  */
    164   1.1  christos       if ((operand->flags & AXP_OPERAND_FAKE) != 0)
    165   1.1  christos 	continue;
    166   1.1  christos 
    167   1.1  christos       /* Extract the value from the instruction.  */
    168   1.1  christos       if (operand->extract)
    169   1.1  christos 	value = (*operand->extract) (insn, (int *) NULL);
    170   1.1  christos       else
    171   1.1  christos 	{
    172   1.1  christos 	  value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
    173   1.1  christos 	  if (operand->flags & AXP_OPERAND_SIGNED)
    174   1.1  christos 	    {
    175   1.1  christos 	      int signbit = 1 << (operand->bits - 1);
    176   1.1  christos 	      value = (value ^ signbit) - signbit;
    177   1.1  christos 	    }
    178   1.1  christos 	}
    179   1.1  christos 
    180   1.1  christos       if (need_comma &&
    181   1.1  christos 	  ((operand->flags & (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA))
    182   1.1  christos 	   != AXP_OPERAND_PARENS))
    183   1.1  christos 	{
    184   1.1  christos 	  (*info->fprintf_func) (info->stream, ",");
    185   1.1  christos 	}
    186   1.1  christos       if (operand->flags & AXP_OPERAND_PARENS)
    187   1.1  christos 	(*info->fprintf_func) (info->stream, "(");
    188   1.1  christos 
    189   1.1  christos       /* Print the operand as directed by the flags.  */
    190   1.1  christos       if (operand->flags & AXP_OPERAND_IR)
    191   1.1  christos 	(*info->fprintf_func) (info->stream, "%s", regnames[value]);
    192   1.1  christos       else if (operand->flags & AXP_OPERAND_FPR)
    193   1.1  christos 	(*info->fprintf_func) (info->stream, "%s", regnames[value + 32]);
    194   1.1  christos       else if (operand->flags & AXP_OPERAND_RELATIVE)
    195   1.1  christos 	(*info->print_address_func) (memaddr + 4 + value, info);
    196   1.1  christos       else if (operand->flags & AXP_OPERAND_SIGNED)
    197   1.1  christos 	(*info->fprintf_func) (info->stream, "%d", value);
    198   1.1  christos       else
    199   1.1  christos 	(*info->fprintf_func) (info->stream, "%#x", value);
    200   1.1  christos 
    201   1.1  christos       if (operand->flags & AXP_OPERAND_PARENS)
    202   1.1  christos 	(*info->fprintf_func) (info->stream, ")");
    203   1.1  christos       need_comma = 1;
    204   1.1  christos     }
    205   1.1  christos 
    206   1.1  christos   return 4;
    207   1.1  christos }
    208