GNU Linux-libre 4.14.251-gnu1
[releases.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 }