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