ppc-dis.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* ppc-dis.c -- Disassemble PowerPC instructions
  3. Copyright (C) 1994-2016 Free Software Foundation, Inc.
  4. Written by Ian Lance Taylor, Cygnus Support
  5. This file is part of GDB, GAS, and the GNU binutils.
  6. */
  7. #include <asm/cputable.h>
  8. #include <asm/cpu_has_feature.h>
  9. #include "nonstdio.h"
  10. #include "ansidecl.h"
  11. #include "ppc.h"
  12. #include "dis-asm.h"
  13. /* This file provides several disassembler functions, all of which use
  14. the disassembler interface defined in dis-asm.h. Several functions
  15. are provided because this file handles disassembly for the PowerPC
  16. in both big and little endian mode and also for the POWER (RS/6000)
  17. chip. */
  18. /* Extract the operand value from the PowerPC or POWER instruction. */
  19. static long
  20. operand_value_powerpc (const struct powerpc_operand *operand,
  21. unsigned long insn, ppc_cpu_t dialect)
  22. {
  23. long value;
  24. int invalid;
  25. /* Extract the value from the instruction. */
  26. if (operand->extract)
  27. value = (*operand->extract) (insn, dialect, &invalid);
  28. else
  29. {
  30. if (operand->shift >= 0)
  31. value = (insn >> operand->shift) & operand->bitm;
  32. else
  33. value = (insn << -operand->shift) & operand->bitm;
  34. if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
  35. {
  36. /* BITM is always some number of zeros followed by some
  37. number of ones, followed by some number of zeros. */
  38. unsigned long top = operand->bitm;
  39. /* top & -top gives the rightmost 1 bit, so this
  40. fills in any trailing zeros. */
  41. top |= (top & -top) - 1;
  42. top &= ~(top >> 1);
  43. value = (value ^ top) - top;
  44. }
  45. }
  46. return value;
  47. }
  48. /* Determine whether the optional operand(s) should be printed. */
  49. static int
  50. skip_optional_operands (const unsigned char *opindex,
  51. unsigned long insn, ppc_cpu_t dialect)
  52. {
  53. const struct powerpc_operand *operand;
  54. for (; *opindex != 0; opindex++)
  55. {
  56. operand = &powerpc_operands[*opindex];
  57. if ((operand->flags & PPC_OPERAND_NEXT) != 0
  58. || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
  59. && operand_value_powerpc (operand, insn, dialect) !=
  60. ppc_optional_operand_value (operand)))
  61. return 0;
  62. }
  63. return 1;
  64. }
  65. /* Find a match for INSN in the opcode table, given machine DIALECT.
  66. A DIALECT of -1 is special, matching all machine opcode variations. */
  67. static const struct powerpc_opcode *
  68. lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
  69. {
  70. const struct powerpc_opcode *opcode;
  71. const struct powerpc_opcode *opcode_end;
  72. opcode_end = powerpc_opcodes + powerpc_num_opcodes;
  73. /* Find the first match in the opcode table for this major opcode. */
  74. for (opcode = powerpc_opcodes; opcode < opcode_end; ++opcode)
  75. {
  76. const unsigned char *opindex;
  77. const struct powerpc_operand *operand;
  78. int invalid;
  79. if ((insn & opcode->mask) != opcode->opcode
  80. || (dialect != (ppc_cpu_t) -1
  81. && ((opcode->flags & dialect) == 0
  82. || (opcode->deprecated & dialect) != 0)))
  83. continue;
  84. /* Check validity of operands. */
  85. invalid = 0;
  86. for (opindex = opcode->operands; *opindex != 0; opindex++)
  87. {
  88. operand = powerpc_operands + *opindex;
  89. if (operand->extract)
  90. (*operand->extract) (insn, dialect, &invalid);
  91. }
  92. if (invalid)
  93. continue;
  94. return opcode;
  95. }
  96. return NULL;
  97. }
  98. /* Print a PowerPC or POWER instruction. */
  99. int print_insn_powerpc (unsigned long insn, unsigned long memaddr)
  100. {
  101. const struct powerpc_opcode *opcode;
  102. bool insn_is_short;
  103. ppc_cpu_t dialect;
  104. dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON
  105. | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
  106. if (cpu_has_feature(CPU_FTRS_POWER5))
  107. dialect |= PPC_OPCODE_POWER5;
  108. if (cpu_has_feature(CPU_FTRS_CELL))
  109. dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC);
  110. if (cpu_has_feature(CPU_FTRS_POWER6))
  111. dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC);
  112. if (cpu_has_feature(CPU_FTRS_POWER7))
  113. dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
  114. | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX);
  115. if (cpu_has_feature(CPU_FTRS_POWER8))
  116. dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
  117. | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
  118. | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX);
  119. if (cpu_has_feature(CPU_FTRS_POWER9))
  120. dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
  121. | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 | PPC_OPCODE_HTM
  122. | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
  123. | PPC_OPCODE_VSX | PPC_OPCODE_VSX3);
  124. /* Get the major opcode of the insn. */
  125. opcode = NULL;
  126. insn_is_short = false;
  127. if (opcode == NULL)
  128. opcode = lookup_powerpc (insn, dialect);
  129. if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
  130. opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
  131. if (opcode != NULL)
  132. {
  133. const unsigned char *opindex;
  134. const struct powerpc_operand *operand;
  135. int need_comma;
  136. int need_paren;
  137. int skip_optional;
  138. if (opcode->operands[0] != 0)
  139. printf("%-7s ", opcode->name);
  140. else
  141. printf("%s", opcode->name);
  142. if (insn_is_short)
  143. /* The operands will be fetched out of the 16-bit instruction. */
  144. insn >>= 16;
  145. /* Now extract and print the operands. */
  146. need_comma = 0;
  147. need_paren = 0;
  148. skip_optional = -1;
  149. for (opindex = opcode->operands; *opindex != 0; opindex++)
  150. {
  151. long value;
  152. operand = powerpc_operands + *opindex;
  153. /* Operands that are marked FAKE are simply ignored. We
  154. already made sure that the extract function considered
  155. the instruction to be valid. */
  156. if ((operand->flags & PPC_OPERAND_FAKE) != 0)
  157. continue;
  158. /* If all of the optional operands have the value zero,
  159. then don't print any of them. */
  160. if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
  161. {
  162. if (skip_optional < 0)
  163. skip_optional = skip_optional_operands (opindex, insn,
  164. dialect);
  165. if (skip_optional)
  166. continue;
  167. }
  168. value = operand_value_powerpc (operand, insn, dialect);
  169. if (need_comma)
  170. {
  171. printf(",");
  172. need_comma = 0;
  173. }
  174. /* Print the operand as directed by the flags. */
  175. if ((operand->flags & PPC_OPERAND_GPR) != 0
  176. || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
  177. printf("r%ld", value);
  178. else if ((operand->flags & PPC_OPERAND_FPR) != 0)
  179. printf("f%ld", value);
  180. else if ((operand->flags & PPC_OPERAND_VR) != 0)
  181. printf("v%ld", value);
  182. else if ((operand->flags & PPC_OPERAND_VSR) != 0)
  183. printf("vs%ld", value);
  184. else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
  185. print_address(memaddr + value);
  186. else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
  187. print_address(value & 0xffffffff);
  188. else if ((operand->flags & PPC_OPERAND_FSL) != 0)
  189. printf("fsl%ld", value);
  190. else if ((operand->flags & PPC_OPERAND_FCR) != 0)
  191. printf("fcr%ld", value);
  192. else if ((operand->flags & PPC_OPERAND_UDI) != 0)
  193. printf("%ld", value);
  194. else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
  195. && (((dialect & PPC_OPCODE_PPC) != 0)
  196. || ((dialect & PPC_OPCODE_VLE) != 0)))
  197. printf("cr%ld", value);
  198. else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
  199. && (((dialect & PPC_OPCODE_PPC) != 0)
  200. || ((dialect & PPC_OPCODE_VLE) != 0)))
  201. {
  202. static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
  203. int cr;
  204. int cc;
  205. cr = value >> 2;
  206. if (cr != 0)
  207. printf("4*cr%d+", cr);
  208. cc = value & 3;
  209. printf("%s", cbnames[cc]);
  210. }
  211. else
  212. printf("%d", (int) value);
  213. if (need_paren)
  214. {
  215. printf(")");
  216. need_paren = 0;
  217. }
  218. if ((operand->flags & PPC_OPERAND_PARENS) == 0)
  219. need_comma = 1;
  220. else
  221. {
  222. printf("(");
  223. need_paren = 1;
  224. }
  225. }
  226. /* We have found and printed an instruction.
  227. If it was a short VLE instruction we have more to do. */
  228. if (insn_is_short)
  229. {
  230. memaddr += 2;
  231. return 2;
  232. }
  233. else
  234. /* Otherwise, return. */
  235. return 4;
  236. }
  237. /* We could not find a match. */
  238. printf(".long 0x%lx", insn);
  239. return 4;
  240. }