ChangeLog rotatation and copyright year update
[deliverable/binutils-gdb.git] / opcodes / alpha-dis.c
CommitLineData
252b5132 1/* alpha-dis.c -- Disassemble Alpha AXP instructions
b90efa5b 2 Copyright (C) 1996-2015 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>
252b5132
RH
25#include "dis-asm.h"
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
57print_insn_alpha (memaddr, info)
58 bfd_vma memaddr;
59 struct disassemble_info *info;
60{
61 static const struct alpha_opcode *opcode_index[AXP_NOPS+1];
62 const char * const * regnames;
63 const struct alpha_opcode *opcode, *opcode_end;
64 const unsigned char *opindex;
65 unsigned insn, op, isa_mask;
66 int need_comma;
67
68 /* Initialize the majorop table the first time through */
69 if (!opcode_index[0])
70 {
71 opcode = alpha_opcodes;
72 opcode_end = opcode + alpha_num_opcodes;
73
74 for (op = 0; op < AXP_NOPS; ++op)
33822a8e
KH
75 {
76 opcode_index[op] = opcode;
77 while (opcode < opcode_end && op == AXP_OP (opcode->opcode))
252b5132 78 ++opcode;
33822a8e 79 }
252b5132
RH
80 opcode_index[op] = opcode;
81 }
82
83 if (info->flavour == bfd_target_evax_flavour)
84 regnames = vms_regnames;
85 else
86 regnames = osf_regnames;
87
88 isa_mask = AXP_OPCODE_NOPAL;
89 switch (info->mach)
90 {
91 case bfd_mach_alpha_ev4:
92 isa_mask |= AXP_OPCODE_EV4;
93 break;
94 case bfd_mach_alpha_ev5:
95 isa_mask |= AXP_OPCODE_EV5;
96 break;
97 case bfd_mach_alpha_ev6:
98 isa_mask |= AXP_OPCODE_EV6;
99 break;
100 }
101
102 /* Read the insn into a host word */
103 {
104 bfd_byte buffer[4];
105 int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
106 if (status != 0)
107 {
33822a8e
KH
108 (*info->memory_error_func) (status, memaddr, info);
109 return -1;
252b5132
RH
110 }
111 insn = bfd_getl32 (buffer);
112 }
113
114 /* Get the major opcode of the instruction. */
115 op = AXP_OP (insn);
116
117 /* Find the first match in the opcode table. */
33822a8e 118 opcode_end = opcode_index[op + 1];
252b5132
RH
119 for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode)
120 {
98c02720 121 if ((insn ^ opcode->opcode) & opcode->mask)
252b5132
RH
122 continue;
123
124 if (!(opcode->flags & isa_mask))
125 continue;
126
127 /* Make two passes over the operands. First see if any of them
128 have extraction functions, and, if they do, make sure the
129 instruction is valid. */
130 {
33822a8e
KH
131 int invalid = 0;
132 for (opindex = opcode->operands; *opindex != 0; opindex++)
252b5132 133 {
33822a8e 134 const struct alpha_operand *operand = alpha_operands + *opindex;
252b5132
RH
135 if (operand->extract)
136 (*operand->extract) (insn, &invalid);
137 }
33822a8e 138 if (invalid)
252b5132
RH
139 continue;
140 }
141
142 /* The instruction is valid. */
143 goto found;
144 }
145
146 /* No instruction found */
147 (*info->fprintf_func) (info->stream, ".long %#08x", insn);
33822a8e 148
252b5132
RH
149 return 4;
150
151found:
152 (*info->fprintf_func) (info->stream, "%s", opcode->name);
153 if (opcode->operands[0] != 0)
154 (*info->fprintf_func) (info->stream, "\t");
155
156 /* Now extract and print the operands. */
157 need_comma = 0;
158 for (opindex = opcode->operands; *opindex != 0; opindex++)
159 {
160 const struct alpha_operand *operand = alpha_operands + *opindex;
161 int value;
162
163 /* Operands that are marked FAKE are simply ignored. We
164 already made sure that the extract function considered
165 the instruction to be valid. */
166 if ((operand->flags & AXP_OPERAND_FAKE) != 0)
167 continue;
168
169 /* Extract the value from the instruction. */
170 if (operand->extract)
171 value = (*operand->extract) (insn, (int *) NULL);
172 else
173 {
174 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
175 if (operand->flags & AXP_OPERAND_SIGNED)
176 {
177 int signbit = 1 << (operand->bits - 1);
178 value = (value ^ signbit) - signbit;
179 }
180 }
181
182 if (need_comma &&
33822a8e 183 ((operand->flags & (AXP_OPERAND_PARENS | AXP_OPERAND_COMMA))
252b5132
RH
184 != AXP_OPERAND_PARENS))
185 {
186 (*info->fprintf_func) (info->stream, ",");
187 }
188 if (operand->flags & AXP_OPERAND_PARENS)
189 (*info->fprintf_func) (info->stream, "(");
190
191 /* Print the operand as directed by the flags. */
192 if (operand->flags & AXP_OPERAND_IR)
193 (*info->fprintf_func) (info->stream, "%s", regnames[value]);
194 else if (operand->flags & AXP_OPERAND_FPR)
33822a8e 195 (*info->fprintf_func) (info->stream, "%s", regnames[value + 32]);
252b5132
RH
196 else if (operand->flags & AXP_OPERAND_RELATIVE)
197 (*info->print_address_func) (memaddr + 4 + value, info);
198 else if (operand->flags & AXP_OPERAND_SIGNED)
199 (*info->fprintf_func) (info->stream, "%d", value);
200 else
201 (*info->fprintf_func) (info->stream, "%#x", value);
202
203 if (operand->flags & AXP_OPERAND_PARENS)
204 (*info->fprintf_func) (info->stream, ")");
205 need_comma = 1;
206 }
207
208 return 4;
209}
This page took 0.743473 seconds and 4 git commands to generate.