* bfd/coff-arm.c (coff_arm_relocate_section)
[deliverable/binutils-gdb.git] / opcodes / ia64-dis.c
CommitLineData
800eeca4 1/* ia64-dis.c -- Disassemble ia64 instructions
aa820537
AM
2 Copyright 1998, 1999, 2000, 2002, 2005, 2007, 2008, 2009
3 Free Software Foundation, Inc.
800eeca4
JW
4 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
5
9b201bb5 6 This file is part of the GNU opcodes library.
800eeca4 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.
800eeca4 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.
800eeca4
JW
17
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
f4321104
NC
20 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
800eeca4
JW
22
23#include <assert.h>
24#include <string.h>
25
26#include "dis-asm.h"
27#include "opcode/ia64.h"
28
29#define NELEMS(a) ((int) (sizeof (a) / sizeof (a[0])))
30
31/* Disassemble ia64 instruction. */
32
33/* Return the instruction type for OPCODE found in unit UNIT. */
34
35static enum ia64_insn_type
36unit_to_type (ia64_insn opcode, enum ia64_unit unit)
37{
38 enum ia64_insn_type type;
39 int op;
40
41 op = IA64_OP (opcode);
42
43 if (op >= 8 && (unit == IA64_UNIT_I || unit == IA64_UNIT_M))
44 {
45 type = IA64_TYPE_A;
46 }
47 else
48 {
49 switch (unit)
50 {
51 case IA64_UNIT_I:
52 type = IA64_TYPE_I; break;
53 case IA64_UNIT_M:
54 type = IA64_TYPE_M; break;
55 case IA64_UNIT_B:
56 type = IA64_TYPE_B; break;
57 case IA64_UNIT_F:
58 type = IA64_TYPE_F; break;
59 case IA64_UNIT_L:
60 case IA64_UNIT_X:
61 type = IA64_TYPE_X; break;
62 default:
63 type = -1;
64 }
65 }
66 return type;
67}
68
69int
70print_insn_ia64 (bfd_vma memaddr, struct disassemble_info *info)
71{
d3ce72d0 72 ia64_insn t0, t1, slot[3], template_val, s_bit, insn;
800eeca4
JW
73 int slotnum, j, status, need_comma, retval, slot_multiplier;
74 const struct ia64_operand *odesc;
75 const struct ia64_opcode *idesc;
76 const char *err, *str, *tname;
77 BFD_HOST_U_64_BIT value;
78 bfd_byte bundle[16];
79 enum ia64_unit unit;
80 char regname[16];
81
82 if (info->bytes_per_line == 0)
83 info->bytes_per_line = 6;
84 info->display_endian = info->endian;
85
86 slot_multiplier = info->bytes_per_line;
87 retval = slot_multiplier;
88
89 slotnum = (((long) memaddr) & 0xf) / slot_multiplier;
90 if (slotnum > 2)
91 return -1;
92
93 memaddr -= (memaddr & 0xf);
94 status = (*info->read_memory_func) (memaddr, bundle, sizeof (bundle), info);
95 if (status != 0)
96 {
97 (*info->memory_error_func) (status, memaddr, info);
98 return -1;
99 }
100 /* bundles are always in little-endian byte order */
101 t0 = bfd_getl64 (bundle);
102 t1 = bfd_getl64 (bundle + 8);
103 s_bit = t0 & 1;
d3ce72d0 104 template_val = (t0 >> 1) & 0xf;
800eeca4
JW
105 slot[0] = (t0 >> 5) & 0x1ffffffffffLL;
106 slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
107 slot[2] = (t1 >> 23) & 0x1ffffffffffLL;
108
d3ce72d0 109 tname = ia64_templ_desc[template_val].name;
800eeca4
JW
110 if (slotnum == 0)
111 (*info->fprintf_func) (info->stream, "[%s] ", tname);
112 else
0fd3a477 113 (*info->fprintf_func) (info->stream, " ");
800eeca4 114
d3ce72d0 115 unit = ia64_templ_desc[template_val].exec_unit[slotnum];
800eeca4 116
d3ce72d0 117 if (template_val == 2 && slotnum == 1)
800eeca4
JW
118 {
119 /* skip L slot in MLI template: */
120 slotnum = 2;
139368c9 121 retval += slot_multiplier;
800eeca4
JW
122 }
123
124 insn = slot[slotnum];
125
126 if (unit == IA64_UNIT_NIL)
127 goto decoding_failed;
128
129 idesc = ia64_dis_opcode (insn, unit_to_type (insn, unit));
130 if (idesc == NULL)
131 goto decoding_failed;
132
133 /* print predicate, if any: */
134
135 if ((idesc->flags & IA64_OPCODE_NO_PRED)
136 || (insn & 0x3f) == 0)
137 (*info->fprintf_func) (info->stream, " ");
138 else
139 (*info->fprintf_func) (info->stream, "(p%02d) ", (int)(insn & 0x3f));
140
141 /* now the actual instruction: */
142
143 (*info->fprintf_func) (info->stream, "%s", idesc->name);
144 if (idesc->operands[0])
145 (*info->fprintf_func) (info->stream, " ");
146
147 need_comma = 0;
148 for (j = 0; j < NELEMS (idesc->operands) && idesc->operands[j]; ++j)
149 {
150 odesc = elf64_ia64_operands + idesc->operands[j];
151
152 if (need_comma)
153 (*info->fprintf_func) (info->stream, ",");
154
155 if (odesc - elf64_ia64_operands == IA64_OPND_IMMU64)
156 {
157 /* special case of 64 bit immediate load: */
158 value = ((insn >> 13) & 0x7f) | (((insn >> 27) & 0x1ff) << 7)
159 | (((insn >> 22) & 0x1f) << 16) | (((insn >> 21) & 0x1) << 21)
160 | (slot[1] << 22) | (((insn >> 36) & 0x1) << 63);
161 }
162 else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62)
163 {
164 /* 62-bit immediate for nop.x/break.x */
165 value = ((slot[1] & 0x1ffffffffffLL) << 21)
166 | (((insn >> 36) & 0x1) << 20)
167 | ((insn >> 6) & 0xfffff);
168 }
0228082a
RH
169 else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64)
170 {
97dd3f18 171 /* 60-bit immediate for long branches. */
0228082a
RH
172 value = (((insn >> 13) & 0xfffff)
173 | (((insn >> 36) & 1) << 59)
97dd3f18 174 | (((slot[1] >> 2) & 0x7fffffffffLL) << 20)) << 4;
0228082a 175 }
800eeca4
JW
176 else
177 {
178 err = (*odesc->extract) (odesc, insn, &value);
179 if (err)
180 {
181 (*info->fprintf_func) (info->stream, "%s", err);
182 goto done;
183 }
184 }
185
96d56e9f 186 switch (odesc->op_class)
800eeca4
JW
187 {
188 case IA64_OPND_CLASS_CST:
189 (*info->fprintf_func) (info->stream, "%s", odesc->str);
190 break;
191
192 case IA64_OPND_CLASS_REG:
193 if (odesc->str[0] == 'a' && odesc->str[1] == 'r')
194 {
195 switch (value)
196 {
197 case 0: case 1: case 2: case 3:
198 case 4: case 5: case 6: case 7:
199 sprintf (regname, "ar.k%u", (unsigned int) value);
200 break;
201 case 16: strcpy (regname, "ar.rsc"); break;
202 case 17: strcpy (regname, "ar.bsp"); break;
203 case 18: strcpy (regname, "ar.bspstore"); break;
204 case 19: strcpy (regname, "ar.rnat"); break;
80098f51
TG
205 case 21: strcpy (regname, "ar.fcr"); break;
206 case 24: strcpy (regname, "ar.eflag"); break;
207 case 25: strcpy (regname, "ar.csd"); break;
208 case 26: strcpy (regname, "ar.ssd"); break;
209 case 27: strcpy (regname, "ar.cflg"); break;
210 case 28: strcpy (regname, "ar.fsr"); break;
211 case 29: strcpy (regname, "ar.fir"); break;
212 case 30: strcpy (regname, "ar.fdr"); break;
800eeca4
JW
213 case 32: strcpy (regname, "ar.ccv"); break;
214 case 36: strcpy (regname, "ar.unat"); break;
215 case 40: strcpy (regname, "ar.fpsr"); break;
216 case 44: strcpy (regname, "ar.itc"); break;
4f8631b1 217 case 45: strcpy (regname, "ar.ruc"); break;
800eeca4
JW
218 case 64: strcpy (regname, "ar.pfs"); break;
219 case 65: strcpy (regname, "ar.lc"); break;
220 case 66: strcpy (regname, "ar.ec"); break;
221 default:
222 sprintf (regname, "ar%u", (unsigned int) value);
223 break;
224 }
225 (*info->fprintf_func) (info->stream, "%s", regname);
226 }
679936aa
TG
227 else if (odesc->str[0] == 'c' && odesc->str[1] == 'r')
228 {
229 switch (value)
230 {
231 case 0: strcpy (regname, "cr.dcr"); break;
232 case 1: strcpy (regname, "cr.itm"); break;
233 case 2: strcpy (regname, "cr.iva"); break;
234 case 8: strcpy (regname, "cr.pta"); break;
235 case 16: strcpy (regname, "cr.ipsr"); break;
236 case 17: strcpy (regname, "cr.isr"); break;
237 case 19: strcpy (regname, "cr.iip"); break;
238 case 20: strcpy (regname, "cr.ifa"); break;
239 case 21: strcpy (regname, "cr.itir"); break;
240 case 22: strcpy (regname, "cr.iipa"); break;
241 case 23: strcpy (regname, "cr.ifs"); break;
242 case 24: strcpy (regname, "cr.iim"); break;
243 case 25: strcpy (regname, "cr.iha"); break;
1ca35711
L
244 case 26: strcpy (regname, "cr.iib0"); break;
245 case 27: strcpy (regname, "cr.iib1"); break;
679936aa
TG
246 case 64: strcpy (regname, "cr.lid"); break;
247 case 65: strcpy (regname, "cr.ivr"); break;
248 case 66: strcpy (regname, "cr.tpr"); break;
249 case 67: strcpy (regname, "cr.eoi"); break;
250 case 68: strcpy (regname, "cr.irr0"); break;
251 case 69: strcpy (regname, "cr.irr1"); break;
252 case 70: strcpy (regname, "cr.irr2"); break;
253 case 71: strcpy (regname, "cr.irr3"); break;
254 case 72: strcpy (regname, "cr.itv"); break;
255 case 73: strcpy (regname, "cr.pmv"); break;
256 case 74: strcpy (regname, "cr.cmcv"); break;
257 case 80: strcpy (regname, "cr.lrr0"); break;
258 case 81: strcpy (regname, "cr.lrr1"); break;
259 default:
260 sprintf (regname, "cr%u", (unsigned int) value);
261 break;
262 }
263 (*info->fprintf_func) (info->stream, "%s", regname);
264 }
800eeca4
JW
265 else
266 (*info->fprintf_func) (info->stream, "%s%d", odesc->str, (int)value);
267 break;
268
269 case IA64_OPND_CLASS_IND:
270 (*info->fprintf_func) (info->stream, "%s[r%d]", odesc->str, (int)value);
271 break;
272
273 case IA64_OPND_CLASS_ABS:
274 str = 0;
275 if (odesc - elf64_ia64_operands == IA64_OPND_MBTYPE4)
276 switch (value)
277 {
278 case 0x0: str = "@brcst"; break;
279 case 0x8: str = "@mix"; break;
280 case 0x9: str = "@shuf"; break;
281 case 0xa: str = "@alt"; break;
282 case 0xb: str = "@rev"; break;
283 }
284
285 if (str)
286 (*info->fprintf_func) (info->stream, "%s", str);
287 else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
0fd3a477 288 (*info->fprintf_func) (info->stream, "%lld", (long long) value);
800eeca4 289 else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
0fd3a477 290 (*info->fprintf_func) (info->stream, "%llu", (long long) value);
800eeca4 291 else
0fd3a477 292 (*info->fprintf_func) (info->stream, "0x%llx", (long long) value);
800eeca4
JW
293 break;
294
295 case IA64_OPND_CLASS_REL:
296 (*info->print_address_func) (memaddr + value, info);
297 break;
298 }
299
300 need_comma = 1;
301 if (j + 1 == idesc->num_outputs)
302 {
303 (*info->fprintf_func) (info->stream, "=");
304 need_comma = 0;
305 }
306 }
d3ce72d0 307 if (slotnum + 1 == ia64_templ_desc[template_val].group_boundary
800eeca4
JW
308 || ((slotnum == 2) && s_bit))
309 (*info->fprintf_func) (info->stream, ";;");
310
311 done:
514829c3 312 ia64_free_opcode ((struct ia64_opcode *)idesc);
f9365b11 313 failed:
800eeca4
JW
314 if (slotnum == 2)
315 retval += 16 - 3*slot_multiplier;
316 return retval;
317
318 decoding_failed:
0fd3a477 319 (*info->fprintf_func) (info->stream, " data8 %#011llx", (long long) insn);
f9365b11 320 goto failed;
800eeca4 321}
This page took 0.419433 seconds and 4 git commands to generate.