s/sanitize-m32rx/sanitize-cygnus/
[deliverable/binutils-gdb.git] / opcodes / alpha-dis.c
CommitLineData
e7bc7bc3
ILT
1/* alpha-dis.c -- Disassemble Alpha AXP instructions
2 Copyright 1996 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
30static int print_insn_alpha
31 PARAMS ((bfd_vma, struct disassemble_info *, const char * const *, int));
32
33/* Disassemble Alpha instructions using OSF register names. */
34
35int
36print_insn_alpha_osf (memaddr, info)
37 bfd_vma memaddr;
38 struct disassemble_info *info;
39{
40 static const char * const osf_regnames[64] = {
41 "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
42 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
43 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
44 "t10", "t11", "ra", "t12", "at", "gp", "sp", "zero",
45 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
46 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
47 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
48 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
49 };
50
d82a4ac0 51 return print_insn_alpha (memaddr, info, osf_regnames, AXP_OPCODE_ALL);
e7bc7bc3
ILT
52}
53
54/* Disassemble Alpha instructions using VMS register names. */
55
56int
57print_insn_alpha_vms (memaddr, info)
58 bfd_vma memaddr;
59 struct disassemble_info *info;
60{
61 static const char * const vms_regnames[64] = {
62 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
63 "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15",
64 "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23",
65 "R24", "AI", "RA", "PV", "AT", "FP", "SP", "RZ",
66 "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
67 "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15",
68 "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23",
69 "F24", "F25", "F26", "F27", "F28", "F29", "F30", "FZ"
70 };
71
d82a4ac0 72 return print_insn_alpha (memaddr, info, vms_regnames, AXP_OPCODE_ALL);
e7bc7bc3
ILT
73}
74
75/* Disassemble Alpha instructions. */
76
77static int
78print_insn_alpha (memaddr, info, regnames, cpumask)
79 bfd_vma memaddr;
80 struct disassemble_info *info;
81 const char * const * regnames;
82 int cpumask;
83{
84 static const struct alpha_opcode *opcode_index[AXP_NOPS+1];
85 const struct alpha_opcode *opcode, *opcode_end;
86 const unsigned char *opindex;
87 unsigned insn, op;
88 int need_comma;
89
90 /* Initialize the majorop table the first time through */
91 if (!opcode_index[0])
92 {
93 opcode = alpha_opcodes;
94 opcode_end = opcode + alpha_num_opcodes;
95
96 for (op = 0; op < AXP_NOPS; ++op)
97 {
98 opcode_index[op] = opcode;
99 while (opcode < opcode_end && op == AXP_OP (opcode->opcode))
100 ++opcode;
101 }
102 opcode_index[op] = opcode;
103 }
104
105 /* Read the insn into a host word */
106 {
107 bfd_byte buffer[4];
108 int status = (*info->read_memory_func) (memaddr, buffer, 4, info);
109 if (status != 0)
110 {
111 (*info->memory_error_func) (status, memaddr, info);
112 return -1;
113 }
114 insn = bfd_getl32 (buffer);
115 }
116
117 /* Get the major opcode of the instruction. */
118 op = AXP_OP (insn);
119
120 /* Find the first match in the opcode table. */
121 opcode_end = opcode_index[op+1];
122 for (opcode = opcode_index[op]; opcode < opcode_end; ++opcode)
123 {
124 if ((insn & opcode->mask) != opcode->opcode)
125 continue;
126
127 if (!(opcode->flags & cpumask))
128 continue;
129
130 /* Make two passes over the operands. First see if any of them
131 have extraction functions, and, if they do, make sure the
132 instruction is valid. */
133 {
134 int invalid = 0;
135 for (opindex = opcode->operands; *opindex != 0; opindex++)
136 {
137 const struct alpha_operand *operand = alpha_operands + *opindex;
138 if (operand->extract)
139 (*operand->extract) (insn, &invalid);
140 }
141 if (invalid)
142 continue;
143 }
144
145 /* The instruction is valid. */
146 goto found;
147 }
148
149 /* No instruction found */
150 (*info->fprintf_func) (info->stream, ".long %#08x", insn);
151
152 return 4;
153
154found:
155 (*info->fprintf_func) (info->stream, "%s", opcode->name);
156 if (opcode->operands[0] != 0)
157 (*info->fprintf_func) (info->stream, "\t");
158
159 /* Now extract and print the operands. */
160 need_comma = 0;
161 for (opindex = opcode->operands; *opindex != 0; opindex++)
162 {
163 const struct alpha_operand *operand = alpha_operands + *opindex;
164 int value;
165
166 /* Operands that are marked FAKE are simply ignored. We
167 already made sure that the extract function considered
168 the instruction to be valid. */
169 if ((operand->flags & AXP_OPERAND_FAKE) != 0)
170 continue;
171
172 /* Extract the value from the instruction. */
173 if (operand->extract)
174 value = (*operand->extract) (insn, (int *) NULL);
175 else
176 {
177 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
178 if (operand->flags & AXP_OPERAND_SIGNED)
179 {
180 int signbit = 1 << (operand->bits - 1);
181 value = (value ^ signbit) - signbit;
182 }
183 }
184
185 if (need_comma &&
186 ((operand->flags & (AXP_OPERAND_PARENS|AXP_OPERAND_COMMA))
187 != AXP_OPERAND_PARENS))
188 {
189 (*info->fprintf_func) (info->stream, ",");
190 }
191 if (operand->flags & AXP_OPERAND_PARENS)
192 (*info->fprintf_func) (info->stream, "(");
193
194 /* Print the operand as directed by the flags. */
195 if (operand->flags & AXP_OPERAND_IR)
196 (*info->fprintf_func) (info->stream, "%s", regnames[value]);
197 else if (operand->flags & AXP_OPERAND_FPR)
198 (*info->fprintf_func) (info->stream, "%s", regnames[value+32]);
199 else if (operand->flags & AXP_OPERAND_RELATIVE)
200 (*info->print_address_func) (memaddr + 4 + value, info);
201 else if (operand->flags & AXP_OPERAND_SIGNED)
202 (*info->fprintf_func) (info->stream, "%d", value);
203 else
204 (*info->fprintf_func) (info->stream, "%#x", value);
205
206 if (operand->flags & AXP_OPERAND_PARENS)
207 (*info->fprintf_func) (info->stream, ")");
208 need_comma = 1;
209 }
210
211 return 4;
212}
This page took 0.105345 seconds and 4 git commands to generate.