1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
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:
31:
32:
33:
34: static enum ia64_insn_type
35: unit_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:
68: int
69: print_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:
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
112: (*info->fprintf_func) (info->stream, " ");
113:
114: unit = ia64_templ_desc[template].exec_unit[slotnum];
115:
116: if (template == 2 && slotnum == 1)
117: {
118:
119: slotnum = 2;
120: retval += slot_multiplier;
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:
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:
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:
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:
164: value = ((slot[1] & 0x1ffffffffffLL) << 21)
165: | (((insn >> 36) & 0x1) << 20)
166: | ((insn >> 6) & 0xfffff);
167: }
168: else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64)
169: {
170:
171: value = (((insn >> 13) & 0xfffff)
172: | (((insn >> 36) & 1) << 59)
173: | (((slot[1] >> 2) & 0x7fffffffffLL) << 20)) << 4;
174: }
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;
204: case 32: strcpy (regname, "ar.ccv"); break;
205: case 36: strcpy (regname, "ar.unat"); break;
206: case 40: strcpy (regname, "ar.fpsr"); break;
207: case 44: strcpy (regname, "ar.itc"); break;
208: case 64: strcpy (regname, "ar.pfs"); break;
209: case 65: strcpy (regname, "ar.lc"); break;
210: case 66: strcpy (regname, "ar.ec"); break;
211: default:
212: sprintf (regname, "ar%u", (unsigned int) value);
213: break;
214: }
215: (*info->fprintf_func) (info->stream, "%s", regname);
216: }
217: else
218: (*info->fprintf_func) (info->stream, "%s%d", odesc->str, (int)value);
219: break;
220:
221: case IA64_OPND_CLASS_IND:
222: (*info->fprintf_func) (info->stream, "%s[r%d]", odesc->str, (int)value);
223: break;
224:
225: case IA64_OPND_CLASS_ABS:
226: str = 0;
227: if (odesc - elf64_ia64_operands == IA64_OPND_MBTYPE4)
228: switch (value)
229: {
230: case 0x0: str = "@brcst"; break;
231: case 0x8: str = "@mix"; break;
232: case 0x9: str = "@shuf"; break;
233: case 0xa: str = "@alt"; break;
234: case 0xb: str = "@rev"; break;
235: }
236:
237: if (str)
238: (*info->fprintf_func) (info->stream, "%s", str);
239: else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
240: (*info->fprintf_func) (info->stream, "%lld", (long long) value);
241: else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
242: (*info->fprintf_func) (info->stream, "%llu", (long long) value);
243: else
244: (*info->fprintf_func) (info->stream, "0x%llx", (long long) value);
245: break;
246:
247: case IA64_OPND_CLASS_REL:
248: (*info->print_address_func) (memaddr + value, info);
249: break;
250: }
251:
252: need_comma = 1;
253: if (j + 1 == idesc->num_outputs)
254: {
255: (*info->fprintf_func) (info->stream, "=");
256: need_comma = 0;
257: }
258: }
259: if (slotnum + 1 == ia64_templ_desc[template].group_boundary
260: || ((slotnum == 2) && s_bit))
261: (*info->fprintf_func) (info->stream, ";;");
262:
263: done:
264: ia64_free_opcode ((struct ia64_opcode *)idesc);
265: failed:
266: if (slotnum == 2)
267: retval += 16 - 3*slot_multiplier;
268: return retval;
269:
270: decoding_failed:
271: (*info->fprintf_func) (info->stream, " data8 %#011llx", (long long) insn);
272: goto failed;
273: }