1 /* alpha-dis.c -- Disassemble Alpha AXP instructions
2 Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2007
3 Free Software Foundation, Inc.
4 Contributed by Richard Henderson <rth@tamu.edu>,
5 patterned after the PPC opcode handling written by Ian Lance Taylor.
7 This file is part of libopcodes.
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)
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.
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
27 #include "opcode/alpha.h"
29 /* OSF register names. */
31 static const char * const osf_regnames
[64] = {
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"
42 /* VMS register names. */
44 static const char * const vms_regnames
[64] = {
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"
55 /* Disassemble Alpha instructions. */
58 print_insn_alpha (memaddr
, info
)
60 struct disassemble_info
*info
;
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
;
69 /* Initialize the majorop table the first time through */
72 opcode
= alpha_opcodes
;
73 opcode_end
= opcode
+ alpha_num_opcodes
;
75 for (op
= 0; op
< AXP_NOPS
; ++op
)
77 opcode_index
[op
] = opcode
;
78 while (opcode
< opcode_end
&& op
== AXP_OP (opcode
->opcode
))
81 opcode_index
[op
] = opcode
;
84 if (info
->flavour
== bfd_target_evax_flavour
)
85 regnames
= vms_regnames
;
87 regnames
= osf_regnames
;
89 isa_mask
= AXP_OPCODE_NOPAL
;
92 case bfd_mach_alpha_ev4
:
93 isa_mask
|= AXP_OPCODE_EV4
;
95 case bfd_mach_alpha_ev5
:
96 isa_mask
|= AXP_OPCODE_EV5
;
98 case bfd_mach_alpha_ev6
:
99 isa_mask
|= AXP_OPCODE_EV6
;
103 /* Read the insn into a host word */
106 int status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
109 (*info
->memory_error_func
) (status
, memaddr
, info
);
112 insn
= bfd_getl32 (buffer
);
115 /* Get the major opcode of the instruction. */
118 /* Find the first match in the opcode table. */
119 opcode_end
= opcode_index
[op
+ 1];
120 for (opcode
= opcode_index
[op
]; opcode
< opcode_end
; ++opcode
)
122 if ((insn
^ opcode
->opcode
) & opcode
->mask
)
125 if (!(opcode
->flags
& isa_mask
))
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. */
133 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
135 const struct alpha_operand
*operand
= alpha_operands
+ *opindex
;
136 if (operand
->extract
)
137 (*operand
->extract
) (insn
, &invalid
);
143 /* The instruction is valid. */
147 /* No instruction found */
148 (*info
->fprintf_func
) (info
->stream
, ".long %#08x", insn
);
153 (*info
->fprintf_func
) (info
->stream
, "%s", opcode
->name
);
154 if (opcode
->operands
[0] != 0)
155 (*info
->fprintf_func
) (info
->stream
, "\t");
157 /* Now extract and print the operands. */
159 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
161 const struct alpha_operand
*operand
= alpha_operands
+ *opindex
;
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)
170 /* Extract the value from the instruction. */
171 if (operand
->extract
)
172 value
= (*operand
->extract
) (insn
, (int *) NULL
);
175 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
176 if (operand
->flags
& AXP_OPERAND_SIGNED
)
178 int signbit
= 1 << (operand
->bits
- 1);
179 value
= (value
^ signbit
) - signbit
;
184 ((operand
->flags
& (AXP_OPERAND_PARENS
| AXP_OPERAND_COMMA
))
185 != AXP_OPERAND_PARENS
))
187 (*info
->fprintf_func
) (info
->stream
, ",");
189 if (operand
->flags
& AXP_OPERAND_PARENS
)
190 (*info
->fprintf_func
) (info
->stream
, "(");
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
)
196 (*info
->fprintf_func
) (info
->stream
, "%s", regnames
[value
+ 32]);
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
);
202 (*info
->fprintf_func
) (info
->stream
, "%#x", value
);
204 if (operand
->flags
& AXP_OPERAND_PARENS
)
205 (*info
->fprintf_func
) (info
->stream
, ")");