ia64-dis.c 9.8 KB

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