1 /* alpha-dis.c -- Disassemble Alpha AXP instructions
2 Copyright (C) 1996-2024 Free Software Foundation, Inc.
3 Contributed by Richard Henderson <rth@tamu.edu>,
4 patterned after the PPC opcode handling written by Ian Lance Taylor.
6 This file is part of libopcodes.
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)
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.
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
25 #include "disassemble.h"
26 #include "opcode/alpha.h"
28 /* OSF register names. */
30 static const char * const osf_regnames
[64] = {
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"
41 /* VMS register names. */
43 static const char * const vms_regnames
[64] = {
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"
54 /* Disassemble Alpha instructions. */
57 print_insn_alpha (bfd_vma memaddr
, struct disassemble_info
*info
)
59 static const struct alpha_opcode
*opcode_index
[AXP_NOPS
+1];
60 const char * const * regnames
;
61 const struct alpha_opcode
*opcode
, *opcode_end
;
62 const unsigned char *opindex
;
63 unsigned insn
, op
, isa_mask
;
66 /* Initialize the majorop table the first time through */
69 opcode
= alpha_opcodes
;
70 opcode_end
= opcode
+ alpha_num_opcodes
;
72 for (op
= 0; op
< AXP_NOPS
; ++op
)
74 opcode_index
[op
] = opcode
;
75 while (opcode
< opcode_end
&& op
== AXP_OP (opcode
->opcode
))
78 opcode_index
[op
] = opcode
;
81 if (info
->flavour
== bfd_target_evax_flavour
)
82 regnames
= vms_regnames
;
84 regnames
= osf_regnames
;
86 isa_mask
= AXP_OPCODE_NOPAL
;
89 case bfd_mach_alpha_ev4
:
90 isa_mask
|= AXP_OPCODE_EV4
;
92 case bfd_mach_alpha_ev5
:
93 isa_mask
|= AXP_OPCODE_EV5
;
95 case bfd_mach_alpha_ev6
:
96 isa_mask
|= AXP_OPCODE_EV6
;
100 /* Read the insn into a host word */
103 int status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
106 (*info
->memory_error_func
) (status
, memaddr
, info
);
109 insn
= bfd_getl32 (buffer
);
112 /* Get the major opcode of the instruction. */
115 /* Find the first match in the opcode table. */
116 opcode_end
= opcode_index
[op
+ 1];
117 for (opcode
= opcode_index
[op
]; opcode
< opcode_end
; ++opcode
)
119 if ((insn
^ opcode
->opcode
) & opcode
->mask
)
122 if (!(opcode
->flags
& isa_mask
))
125 /* Make two passes over the operands. First see if any of them
126 have extraction functions, and, if they do, make sure the
127 instruction is valid. */
130 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
132 const struct alpha_operand
*operand
= alpha_operands
+ *opindex
;
133 if (operand
->extract
)
134 (*operand
->extract
) (insn
, &invalid
);
140 /* The instruction is valid. */
144 /* No instruction found */
145 (*info
->fprintf_func
) (info
->stream
, ".long %#08x", insn
);
150 (*info
->fprintf_func
) (info
->stream
, "%s", opcode
->name
);
151 if (opcode
->operands
[0] != 0)
152 (*info
->fprintf_func
) (info
->stream
, "\t");
154 /* Now extract and print the operands. */
156 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
158 const struct alpha_operand
*operand
= alpha_operands
+ *opindex
;
161 /* Operands that are marked FAKE are simply ignored. We
162 already made sure that the extract function considered
163 the instruction to be valid. */
164 if ((operand
->flags
& AXP_OPERAND_FAKE
) != 0)
167 /* Extract the value from the instruction. */
168 if (operand
->extract
)
169 value
= (*operand
->extract
) (insn
, (int *) NULL
);
172 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
173 if (operand
->flags
& AXP_OPERAND_SIGNED
)
175 int signbit
= 1 << (operand
->bits
- 1);
176 value
= (value
^ signbit
) - signbit
;
181 ((operand
->flags
& (AXP_OPERAND_PARENS
| AXP_OPERAND_COMMA
))
182 != AXP_OPERAND_PARENS
))
184 (*info
->fprintf_func
) (info
->stream
, ",");
186 if (operand
->flags
& AXP_OPERAND_PARENS
)
187 (*info
->fprintf_func
) (info
->stream
, "(");
189 /* Print the operand as directed by the flags. */
190 if (operand
->flags
& AXP_OPERAND_IR
)
191 (*info
->fprintf_func
) (info
->stream
, "%s", regnames
[value
]);
192 else if (operand
->flags
& AXP_OPERAND_FPR
)
193 (*info
->fprintf_func
) (info
->stream
, "%s", regnames
[value
+ 32]);
194 else if (operand
->flags
& AXP_OPERAND_RELATIVE
)
195 (*info
->print_address_func
) (memaddr
+ 4 + value
, info
);
196 else if (operand
->flags
& AXP_OPERAND_SIGNED
)
197 (*info
->fprintf_func
) (info
->stream
, "%d", value
);
199 (*info
->fprintf_func
) (info
->stream
, "%#x", value
);
201 if (operand
->flags
& AXP_OPERAND_PARENS
)
202 (*info
->fprintf_func
) (info
->stream
, ")");