]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - arch/powerpc/xmon/ppc-dis.c
Merge branch 'fixes' of git://git.armlinux.org.uk/~rmk/linux-arm
[mirror_ubuntu-bionic-kernel.git] / arch / powerpc / xmon / ppc-dis.c
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
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
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 *
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 unsigned long op;
97
98 /* Get the major opcode of the instruction. */
99 op = PPC_OP (insn);
100
101 opcode_end = powerpc_opcodes + powerpc_num_opcodes;
102 /* Find the first match in the opcode table for this major opcode. */
103 for (opcode = powerpc_opcodes; opcode < opcode_end; ++opcode)
104 {
105 const unsigned char *opindex;
106 const struct powerpc_operand *operand;
107 int invalid;
108
109 if ((insn & opcode->mask) != opcode->opcode
110 || (dialect != (ppc_cpu_t) -1
111 && ((opcode->flags & dialect) == 0
112 || (opcode->deprecated & dialect) != 0)))
113 continue;
114
115 /* Check validity of operands. */
116 invalid = 0;
117 for (opindex = opcode->operands; *opindex != 0; opindex++)
118 {
119 operand = powerpc_operands + *opindex;
120 if (operand->extract)
121 (*operand->extract) (insn, dialect, &invalid);
122 }
123 if (invalid)
124 continue;
125
126 return opcode;
127 }
128
129 return NULL;
130 }
131
132 /* Print a PowerPC or POWER instruction. */
133
134 int print_insn_powerpc (unsigned long insn, unsigned long memaddr)
135 {
136 const struct powerpc_opcode *opcode;
137 bool insn_is_short;
138 ppc_cpu_t dialect;
139
140 dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON
141 | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
142
143 if (cpu_has_feature(CPU_FTRS_POWER5))
144 dialect |= PPC_OPCODE_POWER5;
145
146 if (cpu_has_feature(CPU_FTRS_CELL))
147 dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC);
148
149 if (cpu_has_feature(CPU_FTRS_POWER6))
150 dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC);
151
152 if (cpu_has_feature(CPU_FTRS_POWER7))
153 dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
154 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX);
155
156 if (cpu_has_feature(CPU_FTRS_POWER8))
157 dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
158 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
159 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX);
160
161 if (cpu_has_feature(CPU_FTRS_POWER9))
162 dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
163 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 | PPC_OPCODE_HTM
164 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
165 | PPC_OPCODE_VSX | PPC_OPCODE_VSX3),
166
167 /* Get the major opcode of the insn. */
168 opcode = NULL;
169 insn_is_short = false;
170
171 if (opcode == NULL)
172 opcode = lookup_powerpc (insn, dialect);
173 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
174 opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
175
176 if (opcode != NULL)
177 {
178 const unsigned char *opindex;
179 const struct powerpc_operand *operand;
180 int need_comma;
181 int need_paren;
182 int skip_optional;
183
184 if (opcode->operands[0] != 0)
185 printf("%-7s ", opcode->name);
186 else
187 printf("%s", opcode->name);
188
189 if (insn_is_short)
190 /* The operands will be fetched out of the 16-bit instruction. */
191 insn >>= 16;
192
193 /* Now extract and print the operands. */
194 need_comma = 0;
195 need_paren = 0;
196 skip_optional = -1;
197 for (opindex = opcode->operands; *opindex != 0; opindex++)
198 {
199 long value;
200
201 operand = powerpc_operands + *opindex;
202
203 /* Operands that are marked FAKE are simply ignored. We
204 already made sure that the extract function considered
205 the instruction to be valid. */
206 if ((operand->flags & PPC_OPERAND_FAKE) != 0)
207 continue;
208
209 /* If all of the optional operands have the value zero,
210 then don't print any of them. */
211 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
212 {
213 if (skip_optional < 0)
214 skip_optional = skip_optional_operands (opindex, insn,
215 dialect);
216 if (skip_optional)
217 continue;
218 }
219
220 value = operand_value_powerpc (operand, insn, dialect);
221
222 if (need_comma)
223 {
224 printf(",");
225 need_comma = 0;
226 }
227
228 /* Print the operand as directed by the flags. */
229 if ((operand->flags & PPC_OPERAND_GPR) != 0
230 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
231 printf("r%ld", value);
232 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
233 printf("f%ld", value);
234 else if ((operand->flags & PPC_OPERAND_VR) != 0)
235 printf("v%ld", value);
236 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
237 printf("vs%ld", value);
238 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
239 print_address(memaddr + value);
240 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
241 print_address(value & 0xffffffff);
242 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
243 printf("fsl%ld", value);
244 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
245 printf("fcr%ld", value);
246 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
247 printf("%ld", value);
248 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
249 && (((dialect & PPC_OPCODE_PPC) != 0)
250 || ((dialect & PPC_OPCODE_VLE) != 0)))
251 printf("cr%ld", value);
252 else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
253 && (((dialect & PPC_OPCODE_PPC) != 0)
254 || ((dialect & PPC_OPCODE_VLE) != 0)))
255 {
256 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
257 int cr;
258 int cc;
259
260 cr = value >> 2;
261 if (cr != 0)
262 printf("4*cr%d+", cr);
263 cc = value & 3;
264 printf("%s", cbnames[cc]);
265 }
266 else
267 printf("%d", (int) value);
268
269 if (need_paren)
270 {
271 printf(")");
272 need_paren = 0;
273 }
274
275 if ((operand->flags & PPC_OPERAND_PARENS) == 0)
276 need_comma = 1;
277 else
278 {
279 printf("(");
280 need_paren = 1;
281 }
282 }
283
284 /* We have found and printed an instruction.
285 If it was a short VLE instruction we have more to do. */
286 if (insn_is_short)
287 {
288 memaddr += 2;
289 return 2;
290 }
291 else
292 /* Otherwise, return. */
293 return 4;
294 }
295
296 /* We could not find a match. */
297 printf(".long 0x%lx", insn);
298
299 return 4;
300 }