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
6 This file is part of GDB, GAS, and the GNU binutils.
10 #include <asm/cputable.h>
11 #include <asm/cpu_has_feature.h>
17 /* This file provides several disassembler functions, all of which use
18 the disassembler interface defined in dis-asm.h. Several functions
19 are provided because this file handles disassembly for the PowerPC
20 in both big and little endian mode and also for the POWER (RS/6000)
23 /* Extract the operand value from the PowerPC or POWER instruction. */
26 operand_value_powerpc (const struct powerpc_operand
*operand
,
27 unsigned long insn
, ppc_cpu_t dialect
)
31 /* Extract the value from the instruction. */
33 value
= (*operand
->extract
) (insn
, dialect
, &invalid
);
36 if (operand
->shift
>= 0)
37 value
= (insn
>> operand
->shift
) & operand
->bitm
;
39 value
= (insn
<< -operand
->shift
) & operand
->bitm
;
40 if ((operand
->flags
& PPC_OPERAND_SIGNED
) != 0)
42 /* BITM is always some number of zeros followed by some
43 number of ones, followed by some number of zeros. */
44 unsigned long top
= operand
->bitm
;
45 /* top & -top gives the rightmost 1 bit, so this
46 fills in any trailing zeros. */
47 top
|= (top
& -top
) - 1;
49 value
= (value
^ top
) - top
;
56 /* Determine whether the optional operand(s) should be printed. */
59 skip_optional_operands (const unsigned char *opindex
,
60 unsigned long insn
, ppc_cpu_t dialect
)
62 const struct powerpc_operand
*operand
;
64 for (; *opindex
!= 0; opindex
++)
66 operand
= &powerpc_operands
[*opindex
];
67 if ((operand
->flags
& PPC_OPERAND_NEXT
) != 0
68 || ((operand
->flags
& PPC_OPERAND_OPTIONAL
) != 0
69 && operand_value_powerpc (operand
, insn
, dialect
) !=
70 ppc_optional_operand_value (operand
)))
77 /* Find a match for INSN in the opcode table, given machine DIALECT.
78 A DIALECT of -1 is special, matching all machine opcode variations. */
80 static const struct powerpc_opcode
*
81 lookup_powerpc (unsigned long insn
, ppc_cpu_t dialect
)
83 const struct powerpc_opcode
*opcode
;
84 const struct powerpc_opcode
*opcode_end
;
86 opcode_end
= powerpc_opcodes
+ powerpc_num_opcodes
;
87 /* Find the first match in the opcode table for this major opcode. */
88 for (opcode
= powerpc_opcodes
; opcode
< opcode_end
; ++opcode
)
90 const unsigned char *opindex
;
91 const struct powerpc_operand
*operand
;
94 if ((insn
& opcode
->mask
) != opcode
->opcode
95 || (dialect
!= (ppc_cpu_t
) -1
96 && ((opcode
->flags
& dialect
) == 0
97 || (opcode
->deprecated
& dialect
) != 0)))
100 /* Check validity of operands. */
102 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
104 operand
= powerpc_operands
+ *opindex
;
105 if (operand
->extract
)
106 (*operand
->extract
) (insn
, dialect
, &invalid
);
117 /* Print a PowerPC or POWER instruction. */
119 int print_insn_powerpc (unsigned long insn
, unsigned long memaddr
)
121 const struct powerpc_opcode
*opcode
;
125 dialect
= PPC_OPCODE_PPC
| PPC_OPCODE_COMMON
126 | PPC_OPCODE_64
| PPC_OPCODE_POWER4
| PPC_OPCODE_ALTIVEC
;
128 if (cpu_has_feature(CPU_FTRS_POWER5
))
129 dialect
|= PPC_OPCODE_POWER5
;
131 if (cpu_has_feature(CPU_FTRS_CELL
))
132 dialect
|= (PPC_OPCODE_CELL
| PPC_OPCODE_ALTIVEC
);
134 if (cpu_has_feature(CPU_FTRS_POWER6
))
135 dialect
|= (PPC_OPCODE_POWER5
| PPC_OPCODE_POWER6
| PPC_OPCODE_ALTIVEC
);
137 if (cpu_has_feature(CPU_FTRS_POWER7
))
138 dialect
|= (PPC_OPCODE_POWER5
| PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7
139 | PPC_OPCODE_ALTIVEC
| PPC_OPCODE_VSX
);
141 if (cpu_has_feature(CPU_FTRS_POWER8
))
142 dialect
|= (PPC_OPCODE_POWER5
| PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7
143 | PPC_OPCODE_POWER8
| PPC_OPCODE_HTM
144 | PPC_OPCODE_ALTIVEC
| PPC_OPCODE_ALTIVEC2
| PPC_OPCODE_VSX
);
146 if (cpu_has_feature(CPU_FTRS_POWER9
))
147 dialect
|= (PPC_OPCODE_POWER5
| PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7
148 | PPC_OPCODE_POWER8
| PPC_OPCODE_POWER9
| PPC_OPCODE_HTM
149 | PPC_OPCODE_ALTIVEC
| PPC_OPCODE_ALTIVEC2
150 | PPC_OPCODE_VSX
| PPC_OPCODE_VSX3
);
152 /* Get the major opcode of the insn. */
154 insn_is_short
= false;
157 opcode
= lookup_powerpc (insn
, dialect
);
158 if (opcode
== NULL
&& (dialect
& PPC_OPCODE_ANY
) != 0)
159 opcode
= lookup_powerpc (insn
, (ppc_cpu_t
) -1);
163 const unsigned char *opindex
;
164 const struct powerpc_operand
*operand
;
169 if (opcode
->operands
[0] != 0)
170 printf("%-7s ", opcode
->name
);
172 printf("%s", opcode
->name
);
175 /* The operands will be fetched out of the 16-bit instruction. */
178 /* Now extract and print the operands. */
182 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
186 operand
= powerpc_operands
+ *opindex
;
188 /* Operands that are marked FAKE are simply ignored. We
189 already made sure that the extract function considered
190 the instruction to be valid. */
191 if ((operand
->flags
& PPC_OPERAND_FAKE
) != 0)
194 /* If all of the optional operands have the value zero,
195 then don't print any of them. */
196 if ((operand
->flags
& PPC_OPERAND_OPTIONAL
) != 0)
198 if (skip_optional
< 0)
199 skip_optional
= skip_optional_operands (opindex
, insn
,
205 value
= operand_value_powerpc (operand
, insn
, dialect
);
213 /* Print the operand as directed by the flags. */
214 if ((operand
->flags
& PPC_OPERAND_GPR
) != 0
215 || ((operand
->flags
& PPC_OPERAND_GPR_0
) != 0 && value
!= 0))
216 printf("r%ld", value
);
217 else if ((operand
->flags
& PPC_OPERAND_FPR
) != 0)
218 printf("f%ld", value
);
219 else if ((operand
->flags
& PPC_OPERAND_VR
) != 0)
220 printf("v%ld", value
);
221 else if ((operand
->flags
& PPC_OPERAND_VSR
) != 0)
222 printf("vs%ld", value
);
223 else if ((operand
->flags
& PPC_OPERAND_RELATIVE
) != 0)
224 print_address(memaddr
+ value
);
225 else if ((operand
->flags
& PPC_OPERAND_ABSOLUTE
) != 0)
226 print_address(value
& 0xffffffff);
227 else if ((operand
->flags
& PPC_OPERAND_FSL
) != 0)
228 printf("fsl%ld", value
);
229 else if ((operand
->flags
& PPC_OPERAND_FCR
) != 0)
230 printf("fcr%ld", value
);
231 else if ((operand
->flags
& PPC_OPERAND_UDI
) != 0)
232 printf("%ld", value
);
233 else if ((operand
->flags
& PPC_OPERAND_CR_REG
) != 0
234 && (((dialect
& PPC_OPCODE_PPC
) != 0)
235 || ((dialect
& PPC_OPCODE_VLE
) != 0)))
236 printf("cr%ld", value
);
237 else if (((operand
->flags
& PPC_OPERAND_CR_BIT
) != 0)
238 && (((dialect
& PPC_OPCODE_PPC
) != 0)
239 || ((dialect
& PPC_OPCODE_VLE
) != 0)))
241 static const char *cbnames
[4] = { "lt", "gt", "eq", "so" };
247 printf("4*cr%d+", cr
);
249 printf("%s", cbnames
[cc
]);
252 printf("%d", (int) value
);
260 if ((operand
->flags
& PPC_OPERAND_PARENS
) == 0)
269 /* We have found and printed an instruction.
270 If it was a short VLE instruction we have more to do. */
277 /* Otherwise, return. */
281 /* We could not find a match. */
282 printf(".long 0x%lx", insn
);