alpha-dis.c 6.2 KB

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