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