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