Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ppc-dis.c
Go to the documentation of this file.
1 /* ppc-dis.c -- Disassemble PowerPC instructions
2  Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006
3  Free Software Foundation, Inc.
4  Written by Ian Lance Taylor, Cygnus Support
5 
6 This file is part of GDB, GAS, and the GNU binutils.
7 
8 GDB, GAS, and the GNU binutils are free software; you can redistribute
9 them and/or modify them under the terms of the GNU General Public
10 License as published by the Free Software Foundation; either version
11 2, or (at your option) any later version.
12 
13 GDB, GAS, and the GNU binutils are distributed in the hope that they
14 will be useful, but WITHOUT ANY WARRANTY; without even the implied
15 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16 the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this file; see the file COPYING. If not, write to the Free
20 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
21 
22 #include <asm/cputable.h>
23 #include "nonstdio.h"
24 #include "ansidecl.h"
25 #include "ppc.h"
26 #include "dis-asm.h"
27 
28 /* Print a PowerPC or POWER instruction. */
29 
30 int
31 print_insn_powerpc (unsigned long insn, unsigned long memaddr)
32 {
33  const struct powerpc_opcode *opcode;
34  const struct powerpc_opcode *opcode_end;
35  unsigned long op;
36  int dialect;
37 
40 
42  dialect |= PPC_OPCODE_POWER5;
43 
46 
49 
50  /* Get the major opcode of the instruction. */
51  op = PPC_OP (insn);
52 
53  /* Find the first match in the opcode table. We could speed this up
54  a bit by doing a binary search on the major opcode. */
55  opcode_end = powerpc_opcodes + powerpc_num_opcodes;
56  again:
57  for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
58  {
59  unsigned long table_op;
60  const unsigned char *opindex;
61  const struct powerpc_operand *operand;
62  int invalid;
63  int need_comma;
64  int need_paren;
65 
66  table_op = PPC_OP (opcode->opcode);
67  if (op < table_op)
68  break;
69  if (op > table_op)
70  continue;
71 
72  if ((insn & opcode->mask) != opcode->opcode
73  || (opcode->flags & dialect) == 0)
74  continue;
75 
76  /* Make two passes over the operands. First see if any of them
77  have extraction functions, and, if they do, make sure the
78  instruction is valid. */
79  invalid = 0;
80  for (opindex = opcode->operands; *opindex != 0; opindex++)
81  {
82  operand = powerpc_operands + *opindex;
83  if (operand->extract)
84  (*operand->extract) (insn, dialect, &invalid);
85  }
86  if (invalid)
87  continue;
88 
89  /* The instruction is valid. */
90  printf("%s", opcode->name);
91  if (opcode->operands[0] != 0)
92  printf("\t");
93 
94  /* Now extract and print the operands. */
95  need_comma = 0;
96  need_paren = 0;
97  for (opindex = opcode->operands; *opindex != 0; opindex++)
98  {
99  long value;
100 
101  operand = powerpc_operands + *opindex;
102 
103  /* Operands that are marked FAKE are simply ignored. We
104  already made sure that the extract function considered
105  the instruction to be valid. */
106  if ((operand->flags & PPC_OPERAND_FAKE) != 0)
107  continue;
108 
109  /* Extract the value from the instruction. */
110  if (operand->extract)
111  value = (*operand->extract) (insn, dialect, &invalid);
112  else
113  {
114  value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
115  if ((operand->flags & PPC_OPERAND_SIGNED) != 0
116  && (value & (1 << (operand->bits - 1))) != 0)
117  value -= 1 << operand->bits;
118  }
119 
120  /* If the operand is optional, and the value is zero, don't
121  print anything. */
122  if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
123  && (operand->flags & PPC_OPERAND_NEXT) == 0
124  && value == 0)
125  continue;
126 
127  if (need_comma)
128  {
129  printf(",");
130  need_comma = 0;
131  }
132 
133  /* Print the operand as directed by the flags. */
134  if ((operand->flags & PPC_OPERAND_GPR) != 0
135  || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
136  printf("r%ld", value);
137  else if ((operand->flags & PPC_OPERAND_FPR) != 0)
138  printf("f%ld", value);
139  else if ((operand->flags & PPC_OPERAND_VR) != 0)
140  printf("v%ld", value);
141  else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
142  print_address (memaddr + value);
143  else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
144  print_address (value & 0xffffffff);
145  else if ((operand->flags & PPC_OPERAND_CR) == 0
146  || (dialect & PPC_OPCODE_PPC) == 0)
147  printf("%ld", value);
148  else
149  {
150  if (operand->bits == 3)
151  printf("cr%ld", value);
152  else
153  {
154  static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
155  int cr;
156  int cc;
157 
158  cr = value >> 2;
159  if (cr != 0)
160  printf("4*cr%d+", cr);
161  cc = value & 3;
162  printf("%s", cbnames[cc]);
163  }
164  }
165 
166  if (need_paren)
167  {
168  printf(")");
169  need_paren = 0;
170  }
171 
172  if ((operand->flags & PPC_OPERAND_PARENS) == 0)
173  need_comma = 1;
174  else
175  {
176  printf("(");
177  need_paren = 1;
178  }
179  }
180 
181  /* We have found and printed an instruction; return. */
182  return 4;
183  }
184 
185  if ((dialect & PPC_OPCODE_ANY) != 0)
186  {
187  dialect = ~PPC_OPCODE_ANY;
188  goto again;
189  }
190 
191  /* We could not find a match. */
192  printf(".long 0x%lx", insn);
193 
194  return 4;
195 }