ppc-dis.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. if (IS_ENABLED(CONFIG_PPC64))
  106. dialect |= PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_CELL |
  107. PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 |
  108. PPC_OPCODE_POWER9;
  109. if (cpu_has_feature(CPU_FTR_TM))
  110. dialect |= PPC_OPCODE_HTM;
  111. if (cpu_has_feature(CPU_FTR_ALTIVEC))
  112. dialect |= PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2;
  113. if (cpu_has_feature(CPU_FTR_VSX))
  114. dialect |= PPC_OPCODE_VSX | PPC_OPCODE_VSX3;
  115. /* Get the major opcode of the insn. */
  116. opcode = NULL;
  117. insn_is_short = false;
  118. if (opcode == NULL)
  119. opcode = lookup_powerpc (insn, dialect);
  120. if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
  121. opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
  122. if (opcode != NULL)
  123. {
  124. const unsigned char *opindex;
  125. const struct powerpc_operand *operand;
  126. int need_comma;
  127. int need_paren;
  128. int skip_optional;
  129. if (opcode->operands[0] != 0)
  130. printf("%-7s ", opcode->name);
  131. else
  132. printf("%s", opcode->name);
  133. if (insn_is_short)
  134. /* The operands will be fetched out of the 16-bit instruction. */
  135. insn >>= 16;
  136. /* Now extract and print the operands. */
  137. need_comma = 0;
  138. need_paren = 0;
  139. skip_optional = -1;
  140. for (opindex = opcode->operands; *opindex != 0; opindex++)
  141. {
  142. long value;
  143. operand = powerpc_operands + *opindex;
  144. /* Operands that are marked FAKE are simply ignored. We
  145. already made sure that the extract function considered
  146. the instruction to be valid. */
  147. if ((operand->flags & PPC_OPERAND_FAKE) != 0)
  148. continue;
  149. /* If all of the optional operands have the value zero,
  150. then don't print any of them. */
  151. if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
  152. {
  153. if (skip_optional < 0)
  154. skip_optional = skip_optional_operands (opindex, insn,
  155. dialect);
  156. if (skip_optional)
  157. continue;
  158. }
  159. value = operand_value_powerpc (operand, insn, dialect);
  160. if (need_comma)
  161. {
  162. printf(",");
  163. need_comma = 0;
  164. }
  165. /* Print the operand as directed by the flags. */
  166. if ((operand->flags & PPC_OPERAND_GPR) != 0
  167. || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
  168. printf("r%ld", value);
  169. else if ((operand->flags & PPC_OPERAND_FPR) != 0)
  170. printf("f%ld", value);
  171. else if ((operand->flags & PPC_OPERAND_VR) != 0)
  172. printf("v%ld", value);
  173. else if ((operand->flags & PPC_OPERAND_VSR) != 0)
  174. printf("vs%ld", value);
  175. else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
  176. print_address(memaddr + value);
  177. else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
  178. print_address(value & 0xffffffff);
  179. else if ((operand->flags & PPC_OPERAND_FSL) != 0)
  180. printf("fsl%ld", value);
  181. else if ((operand->flags & PPC_OPERAND_FCR) != 0)
  182. printf("fcr%ld", value);
  183. else if ((operand->flags & PPC_OPERAND_UDI) != 0)
  184. printf("%ld", value);
  185. else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
  186. && (((dialect & PPC_OPCODE_PPC) != 0)
  187. || ((dialect & PPC_OPCODE_VLE) != 0)))
  188. printf("cr%ld", value);
  189. else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
  190. && (((dialect & PPC_OPCODE_PPC) != 0)
  191. || ((dialect & PPC_OPCODE_VLE) != 0)))
  192. {
  193. static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
  194. int cr;
  195. int cc;
  196. cr = value >> 2;
  197. if (cr != 0)
  198. printf("4*cr%d+", cr);
  199. cc = value & 3;
  200. printf("%s", cbnames[cc]);
  201. }
  202. else
  203. printf("%d", (int) value);
  204. if (need_paren)
  205. {
  206. printf(")");
  207. need_paren = 0;
  208. }
  209. if ((operand->flags & PPC_OPERAND_PARENS) == 0)
  210. need_comma = 1;
  211. else
  212. {
  213. printf("(");
  214. need_paren = 1;
  215. }
  216. }
  217. /* We have found and printed an instruction.
  218. If it was a short VLE instruction we have more to do. */
  219. if (insn_is_short)
  220. {
  221. memaddr += 2;
  222. return 2;
  223. }
  224. else
  225. /* Otherwise, return. */
  226. return 4;
  227. }
  228. /* We could not find a match. */
  229. printf(".long 0x%lx", insn);
  230. return 4;
  231. }