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
;
127 if (IS_ENABLED(CONFIG_PPC64
))
128 dialect
|= PPC_OPCODE_64
| PPC_OPCODE_POWER4
| PPC_OPCODE_CELL
|
129 PPC_OPCODE_POWER5
| PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7
| PPC_OPCODE_POWER8
|
132 if (cpu_has_feature(CPU_FTR_TM
))
133 dialect
|= PPC_OPCODE_HTM
;
135 if (cpu_has_feature(CPU_FTR_ALTIVEC
))
136 dialect
|= PPC_OPCODE_ALTIVEC
| PPC_OPCODE_ALTIVEC2
;
138 if (cpu_has_feature(CPU_FTR_VSX
))
139 dialect
|= PPC_OPCODE_VSX
| PPC_OPCODE_VSX3
;
141 /* Get the major opcode of the insn. */
143 insn_is_short
= false;
146 opcode
= lookup_powerpc (insn
, dialect
);
147 if (opcode
== NULL
&& (dialect
& PPC_OPCODE_ANY
) != 0)
148 opcode
= lookup_powerpc (insn
, (ppc_cpu_t
) -1);
152 const unsigned char *opindex
;
153 const struct powerpc_operand
*operand
;
158 if (opcode
->operands
[0] != 0)
159 printf("%-7s ", opcode
->name
);
161 printf("%s", opcode
->name
);
164 /* The operands will be fetched out of the 16-bit instruction. */
167 /* Now extract and print the operands. */
171 for (opindex
= opcode
->operands
; *opindex
!= 0; opindex
++)
175 operand
= powerpc_operands
+ *opindex
;
177 /* Operands that are marked FAKE are simply ignored. We
178 already made sure that the extract function considered
179 the instruction to be valid. */
180 if ((operand
->flags
& PPC_OPERAND_FAKE
) != 0)
183 /* If all of the optional operands have the value zero,
184 then don't print any of them. */
185 if ((operand
->flags
& PPC_OPERAND_OPTIONAL
) != 0)
187 if (skip_optional
< 0)
188 skip_optional
= skip_optional_operands (opindex
, insn
,
194 value
= operand_value_powerpc (operand
, insn
, dialect
);
202 /* Print the operand as directed by the flags. */
203 if ((operand
->flags
& PPC_OPERAND_GPR
) != 0
204 || ((operand
->flags
& PPC_OPERAND_GPR_0
) != 0 && value
!= 0))
205 printf("r%ld", value
);
206 else if ((operand
->flags
& PPC_OPERAND_FPR
) != 0)
207 printf("f%ld", value
);
208 else if ((operand
->flags
& PPC_OPERAND_VR
) != 0)
209 printf("v%ld", value
);
210 else if ((operand
->flags
& PPC_OPERAND_VSR
) != 0)
211 printf("vs%ld", value
);
212 else if ((operand
->flags
& PPC_OPERAND_RELATIVE
) != 0)
213 print_address(memaddr
+ value
);
214 else if ((operand
->flags
& PPC_OPERAND_ABSOLUTE
) != 0)
215 print_address(value
& 0xffffffff);
216 else if ((operand
->flags
& PPC_OPERAND_FSL
) != 0)
217 printf("fsl%ld", value
);
218 else if ((operand
->flags
& PPC_OPERAND_FCR
) != 0)
219 printf("fcr%ld", value
);
220 else if ((operand
->flags
& PPC_OPERAND_UDI
) != 0)
221 printf("%ld", value
);
222 else if ((operand
->flags
& PPC_OPERAND_CR_REG
) != 0
223 && (((dialect
& PPC_OPCODE_PPC
) != 0)
224 || ((dialect
& PPC_OPCODE_VLE
) != 0)))
225 printf("cr%ld", value
);
226 else if (((operand
->flags
& PPC_OPERAND_CR_BIT
) != 0)
227 && (((dialect
& PPC_OPCODE_PPC
) != 0)
228 || ((dialect
& PPC_OPCODE_VLE
) != 0)))
230 static const char *cbnames
[4] = { "lt", "gt", "eq", "so" };
236 printf("4*cr%d+", cr
);
238 printf("%s", cbnames
[cc
]);
241 printf("%d", (int) value
);
249 if ((operand
->flags
& PPC_OPERAND_PARENS
) == 0)
258 /* We have found and printed an instruction.
259 If it was a short VLE instruction we have more to do. */
266 /* Otherwise, return. */
270 /* We could not find a match. */
271 printf(".long 0x%lx", insn
);