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