GNU Linux-libre 4.19.264-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
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
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 }