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