home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / binutils-2.7-src.tgz / tar.out / fsf / binutils / opcodes / alpha-dis.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  236 lines

  1. /* alpha-dis.c -- Disassemble Alpha AXP instructions
  2.    Copyright 1996 Free Software Foundation, Inc.
  3.    Contributed by Richard Henderson <rth@tamu.edu>,
  4.    patterned after the PPC opcode handling written by Ian Lance Taylor.
  5.  
  6. This file is part of GDB, GAS, and the GNU binutils.
  7.  
  8. GDB, GAS, and the GNU binutils are free software; you can redistribute
  9. them and/or modify them under the terms of the GNU General Public
  10. License as published by the Free Software Foundation; either version
  11. 2, or (at your option) any later version.
  12.  
  13. GDB, GAS, and the GNU binutils are distributed in the hope that they
  14. will be useful, but WITHOUT ANY WARRANTY; without even the implied
  15. warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  16. the GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with this file; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  21.  
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include "ansidecl.h"
  25. #include "sysdep.h"
  26. #include "dis-asm.h"
  27. #include "opcode/alpha.h"
  28.  
  29. int print_insn_alpha PARAMS ((bfd_vma, struct disassemble_info *));
  30.  
  31. static const char * const alpha_ir_regnames[32] = {
  32.   "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
  33.   "s0", "s1", "s2", "s3", "s4", "s5", "fp", "a0", "a1",
  34.   "a2", "a3", "a4", "a5", "t8", "t9", "t10", "t11", 
  35.   "ra", "t12", "at", "gp", "sp", "zero"
  36. };
  37.  
  38. int
  39. print_insn_alpha(memaddr, info)
  40.      bfd_vma memaddr;
  41.      struct disassemble_info *info;
  42. {
  43.   static const struct alpha_opcode *opcode_index[AXP_NOPS+1];
  44.   static int option_regnames = 1, option_printhex = 1;
  45.   static unsigned option_target = ~0U;
  46.  
  47.   const struct alpha_opcode *opcode, *opcode_end;
  48.   unsigned insn, op;
  49.   const char *leader = "\t";
  50.  
  51.   /* Initialize the majorop table the first time through */
  52.   if (!opcode_index[0])
  53.     {
  54.       char *p, *q;
  55.  
  56.       opcode = alpha_opcodes;
  57.       opcode_end = opcode + alpha_num_opcodes;
  58.  
  59.       for (op = 0; op < AXP_NOPS; ++op)
  60.         {
  61.           opcode_index[op] = opcode;
  62.           while (opcode < opcode_end && op == AXP_OP (opcode->opcode))
  63.         ++opcode;
  64.         }
  65.       opcode_index[op] = opcode;
  66.  
  67.       p = getenv("BFD_ALPHA_DISASSEMBLE_OPTIONS");
  68.       if (p)
  69.     {
  70.       do {
  71.         int set, len;
  72.         if (*p == '!')
  73.           set = 0, ++p;
  74.         else
  75.           set = 1;
  76.  
  77.         q = strchr(p, ',');
  78.         if (!q) q = strchr(p, '\0');
  79.  
  80.         switch (len = q - p)
  81.           {
  82.           case 3:
  83.         if (strncmp("ev4", p, len) == 0)
  84.           option_target = AXP_OPCODE_EV4|AXP_OPCODE_ALL;
  85.         else if (strncmp("ev5", p, len) == 0)
  86.           option_target = AXP_OPCODE_EV5|AXP_OPCODE_ALL;
  87.         break;
  88.           case 4:
  89.         if (strncmp("ev56", p, len) == 0)
  90.           option_target = AXP_OPCODE_EV56|AXP_OPCODE_ALL;
  91.         break;
  92.           case 5:
  93.         if (strncmp("21064", p, len) == 0)
  94.           option_target = AXP_OPCODE_EV4|AXP_OPCODE_ALL;
  95.         else if (strncmp("21066", p, len) == 0)
  96.           option_target = AXP_OPCODE_EV4|AXP_OPCODE_ALL;
  97.         else if (strncmp("21164", p, len) == 0)
  98.           option_target = AXP_OPCODE_EV5|AXP_OPCODE_ALL;
  99.         break;
  100.           case 6:
  101.         if (strncmp("21164a", p, len) == 0)
  102.           option_target = AXP_OPCODE_EV56|AXP_OPCODE_ALL;
  103.         break;
  104.           case 8:
  105.         if (strncmp("regnames", p, len) == 0)
  106.           option_regnames = set;
  107.         else if (strncmp("printhex", p, len) == 0)
  108.           option_printhex = set;
  109.         break;
  110.           }
  111.  
  112.         p = q+1;
  113.       } while (*q);
  114.     }
  115.     }
  116.  
  117.   /* Read the insn into a host word */
  118.   {
  119.     bfd_byte buffer[4];
  120.     int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  121.     if (status != 0)
  122.       {
  123.         (*info->memory_error_func) (status, memaddr, info);
  124.         return -1;
  125.       }
  126.     insn = bfd_getl32 (buffer);
  127.   }
  128.  
  129.   if (option_printhex)
  130.     {
  131.       (*info->fprintf_func) (info->stream, "%s%08x", leader, insn);
  132.       leader = "  ";
  133.     }
  134.  
  135.   /* Get the major opcode of the instruction.  */
  136.   op = AXP_OP (insn);
  137.  
  138.   /* Find the first match in the opcode table.  */
  139.   opcode = opcode_index[op];
  140.   opcode_end = opcode_index[op+1];
  141.   for (; opcode < opcode_end; ++opcode)
  142.     {
  143.       const unsigned char *opindex;
  144.       int need_comma;
  145.  
  146.       if ((insn & opcode->mask) != opcode->opcode)
  147.     continue;
  148.  
  149.       if (!(opcode->flags & option_target))
  150.     continue;
  151.  
  152.       /* Make two passes over the operands.  First see if any of them
  153.      have extraction functions, and, if they do, make sure the
  154.      instruction is valid.  */
  155.       {
  156.         int invalid = 0;
  157.         for (opindex = opcode->operands; *opindex != 0; opindex++)
  158.       {
  159.             const struct alpha_operand *operand = alpha_operands + *opindex;
  160.         if (operand->extract)
  161.           (*operand->extract) (insn, &invalid);
  162.       }
  163.         if (invalid)
  164.       continue;
  165.       }
  166.  
  167.       /* The instruction is valid.  */
  168.       (*info->fprintf_func) (info->stream, "%s%-10s ", leader, opcode->name);
  169.  
  170.       /* Now extract and print the operands.  */
  171.       need_comma = 0;
  172.       for (opindex = opcode->operands; *opindex != 0; opindex++)
  173.     {
  174.           const struct alpha_operand *operand = alpha_operands + *opindex;
  175.       int value;
  176.  
  177.       /* Operands that are marked FAKE are simply ignored.  We
  178.          already made sure that the extract function considered
  179.          the instruction to be valid.  */
  180.       if ((operand->flags & AXP_OPERAND_FAKE) != 0)
  181.         continue;
  182.  
  183.       /* Extract the value from the instruction.  */
  184.       if (operand->extract)
  185.         value = (*operand->extract) (insn, (int *) NULL);
  186.       else
  187.         {
  188.           value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
  189.           if (operand->flags & AXP_OPERAND_SIGNED)
  190.         {
  191.           int signbit = 1 << (operand->bits - 1);
  192.           value = (value ^ signbit) - signbit;
  193.         }
  194.         }
  195.  
  196.       if (need_comma &&
  197.           ((operand->flags & (AXP_OPERAND_PARENS|AXP_OPERAND_COMMA))
  198.            != AXP_OPERAND_PARENS))
  199.         {
  200.           (*info->fprintf_func) (info->stream, ",");
  201.         }
  202.       if (operand->flags & AXP_OPERAND_PARENS)
  203.         (*info->fprintf_func) (info->stream, "(");
  204.  
  205.       /* Print the operand as directed by the flags.  */
  206.       if (operand->flags & AXP_OPERAND_IR)
  207.         {
  208.           if (option_regnames)
  209.         (*info->fprintf_func) (info->stream, alpha_ir_regnames[value]);
  210.           else
  211.             (*info->fprintf_func) (info->stream, "$%d", value);
  212.         }
  213.       else if (operand->flags & AXP_OPERAND_FPR)
  214.         (*info->fprintf_func) (info->stream, "$f%d", value);
  215.       else if (operand->flags & AXP_OPERAND_RELATIVE)
  216.         (*info->print_address_func) (memaddr + 4 + value, info);
  217.       else if (operand->flags & AXP_OPERAND_SIGNED)
  218.         (*info->fprintf_func) (info->stream, "%d", value);
  219.       else
  220.         (*info->fprintf_func) (info->stream, "%#x", value);
  221.  
  222.       if (operand->flags & AXP_OPERAND_PARENS)
  223.         (*info->fprintf_func) (info->stream, ")");
  224.       need_comma = 1;
  225.     }
  226.  
  227.       return 4;
  228.     }
  229.  
  230.   /* No instruction found */
  231.   if (!option_printhex)
  232.     (*info->fprintf_func) (info->stream, ".long %#08x", insn);
  233.     
  234.   return 4;
  235. }
  236.