xref: /openbmc/linux/arch/powerpc/xmon/ppc-dis.c (revision a36954f5)
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 }
301