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