]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/binutils/opcodes/ppc-dis.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / binutils / opcodes / ppc-dis.c
1 /* $FreeBSD$ */
2 /* ppc-dis.c -- Disassemble PowerPC instructions
3    Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004
4    Free Software Foundation, Inc.
5    Written by Ian Lance Taylor, Cygnus Support
6
7 This file is part of GDB, GAS, and the GNU binutils.
8
9 GDB, GAS, and the GNU binutils are free software; you can redistribute
10 them and/or modify them under the terms of the GNU General Public
11 License as published by the Free Software Foundation; either version
12 2, or (at your option) any later version.
13
14 GDB, GAS, and the GNU binutils are distributed in the hope that they
15 will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17 the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this file; see the file COPYING.  If not, write to the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
23 #include <stdio.h>
24 #include "sysdep.h"
25 #include "dis-asm.h"
26 #include "opcode/ppc.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 static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, int);
35
36 struct dis_private {
37   /* Stash the result of parsing disassembler_options here.  */
38   int dialect;
39 };
40
41 /* Determine which set of machines to disassemble for.  PPC403/601 or
42    BookE.  For convenience, also disassemble instructions supported
43    by the AltiVec vector unit.  */
44
45 static int
46 powerpc_dialect (struct disassemble_info *info)
47 {
48   int dialect = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC;
49   void *pd = &info->private_data;
50
51   if (BFD_DEFAULT_TARGET_SIZE == 64)
52     dialect |= PPC_OPCODE_64;
53
54   if (info->disassembler_options
55       && strstr (info->disassembler_options, "booke") != NULL)
56     dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
57   else if ((info->mach == bfd_mach_ppc_e500)
58            || (info->disassembler_options
59                && strstr (info->disassembler_options, "e500") != NULL))
60     {
61       dialect |= PPC_OPCODE_BOOKE
62         | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
63         | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
64         | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
65         | PPC_OPCODE_RFMCI;
66       /* efs* and AltiVec conflict.  */
67       dialect &= ~PPC_OPCODE_ALTIVEC;
68     }
69   else if (info->disassembler_options
70            && strstr (info->disassembler_options, "efs") != NULL)
71     {
72       dialect |= PPC_OPCODE_EFS;
73       /* efs* and AltiVec conflict.  */
74       dialect &= ~PPC_OPCODE_ALTIVEC;
75     }
76   else
77     dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
78                 | PPC_OPCODE_COMMON);
79
80   if (info->disassembler_options
81       && strstr (info->disassembler_options, "power4") != NULL)
82     dialect |= PPC_OPCODE_POWER4;
83
84   if (info->disassembler_options
85       && strstr (info->disassembler_options, "any") != NULL)
86     dialect |= PPC_OPCODE_ANY;
87
88   if (info->disassembler_options)
89     {
90       if (strstr (info->disassembler_options, "32") != NULL)
91         dialect &= ~PPC_OPCODE_64;
92       else if (strstr (info->disassembler_options, "64") != NULL)
93         dialect |= PPC_OPCODE_64;
94     }
95
96   ((struct dis_private *) pd)->dialect = dialect;
97   return dialect;
98 }
99
100 /* Print a big endian PowerPC instruction.  */
101
102 int
103 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
104 {
105   void *pd = &info->private_data;
106   int dialect = ((struct dis_private *) pd)->dialect;
107   return print_insn_powerpc (memaddr, info, 1, dialect);
108 }
109
110 /* Print a little endian PowerPC instruction.  */
111
112 int
113 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
114 {
115   void *pd = &info->private_data;
116   int dialect = ((struct dis_private *) pd)->dialect;
117   return print_insn_powerpc (memaddr, info, 0, dialect);
118 }
119
120 /* Print a POWER (RS/6000) instruction.  */
121
122 int
123 print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
124 {
125   return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
126 }
127
128 /* Print a PowerPC or POWER instruction.  */
129
130 static int
131 print_insn_powerpc (bfd_vma memaddr,
132                     struct disassemble_info *info,
133                     int bigendian,
134                     int dialect)
135 {
136   bfd_byte buffer[4];
137   int status;
138   unsigned long insn;
139   const struct powerpc_opcode *opcode;
140   const struct powerpc_opcode *opcode_end;
141   unsigned long op;
142
143   if (dialect == 0)
144     dialect = powerpc_dialect (info);
145
146   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
147   if (status != 0)
148     {
149       (*info->memory_error_func) (status, memaddr, info);
150       return -1;
151     }
152
153   if (bigendian)
154     insn = bfd_getb32 (buffer);
155   else
156     insn = bfd_getl32 (buffer);
157
158   /* Get the major opcode of the instruction.  */
159   op = PPC_OP (insn);
160
161   /* Find the first match in the opcode table.  We could speed this up
162      a bit by doing a binary search on the major opcode.  */
163   opcode_end = powerpc_opcodes + powerpc_num_opcodes;
164  again:
165   for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
166     {
167       unsigned long table_op;
168       const unsigned char *opindex;
169       const struct powerpc_operand *operand;
170       int invalid;
171       int need_comma;
172       int need_paren;
173
174       table_op = PPC_OP (opcode->opcode);
175       if (op < table_op)
176         break;
177       if (op > table_op)
178         continue;
179
180       if ((insn & opcode->mask) != opcode->opcode
181           || (opcode->flags & dialect) == 0)
182         continue;
183
184       /* Make two passes over the operands.  First see if any of them
185          have extraction functions, and, if they do, make sure the
186          instruction is valid.  */
187       invalid = 0;
188       for (opindex = opcode->operands; *opindex != 0; opindex++)
189         {
190           operand = powerpc_operands + *opindex;
191           if (operand->extract)
192             (*operand->extract) (insn, dialect, &invalid);
193         }
194       if (invalid)
195         continue;
196
197       /* The instruction is valid.  */
198       if (opcode->operands[0] != 0)
199         (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
200       else
201         (*info->fprintf_func) (info->stream, "%s", opcode->name);
202
203       /* Now extract and print the operands.  */
204       need_comma = 0;
205       need_paren = 0;
206       for (opindex = opcode->operands; *opindex != 0; opindex++)
207         {
208           long value;
209
210           operand = powerpc_operands + *opindex;
211
212           /* Operands that are marked FAKE are simply ignored.  We
213              already made sure that the extract function considered
214              the instruction to be valid.  */
215           if ((operand->flags & PPC_OPERAND_FAKE) != 0)
216             continue;
217
218           /* Extract the value from the instruction.  */
219           if (operand->extract)
220             value = (*operand->extract) (insn, dialect, &invalid);
221           else
222             {
223               value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
224               if ((operand->flags & PPC_OPERAND_SIGNED) != 0
225                   && (value & (1 << (operand->bits - 1))) != 0)
226                 value -= 1 << operand->bits;
227             }
228
229           /* If the operand is optional, and the value is zero, don't
230              print anything.  */
231           if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
232               && (operand->flags & PPC_OPERAND_NEXT) == 0
233               && value == 0)
234             continue;
235
236           if (need_comma)
237             {
238               (*info->fprintf_func) (info->stream, ",");
239               need_comma = 0;
240             }
241
242           /* Print the operand as directed by the flags.  */
243           if ((operand->flags & PPC_OPERAND_GPR) != 0
244               || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
245             (*info->fprintf_func) (info->stream, "r%ld", value);
246           else if ((operand->flags & PPC_OPERAND_FPR) != 0)
247             (*info->fprintf_func) (info->stream, "f%ld", value);
248           else if ((operand->flags & PPC_OPERAND_VR) != 0)
249             (*info->fprintf_func) (info->stream, "v%ld", value);
250           else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
251             (*info->print_address_func) (memaddr + value, info);
252           else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
253             (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
254           else if ((operand->flags & PPC_OPERAND_CR) == 0
255                    || (dialect & PPC_OPCODE_PPC) == 0)
256             (*info->fprintf_func) (info->stream, "%ld", value);
257           else
258             {
259               if (operand->bits == 3)
260                 (*info->fprintf_func) (info->stream, "cr%d", value);
261               else
262                 {
263                   static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
264                   int cr;
265                   int cc;
266
267                   cr = value >> 2;
268                   if (cr != 0)
269                     (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
270                   cc = value & 3;
271                   (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
272                 }
273             }
274
275           if (need_paren)
276             {
277               (*info->fprintf_func) (info->stream, ")");
278               need_paren = 0;
279             }
280
281           if ((operand->flags & PPC_OPERAND_PARENS) == 0)
282             need_comma = 1;
283           else
284             {
285               (*info->fprintf_func) (info->stream, "(");
286               need_paren = 1;
287             }
288         }
289
290       /* We have found and printed an instruction; return.  */
291       return 4;
292     }
293
294   if ((dialect & PPC_OPCODE_ANY) != 0)
295     {
296       dialect = ~PPC_OPCODE_ANY;
297       goto again;
298     }
299
300   /* We could not find a match.  */
301   (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
302
303   return 4;
304 }
305
306 void
307 print_ppc_disassembler_options (FILE *stream)
308 {
309   fprintf (stream, "\n\
310 The following PPC specific disassembler options are supported for use with\n\
311 the -M switch:\n");
312
313   fprintf (stream, "  booke|booke32|booke64    Disassemble the BookE instructions\n");
314   fprintf (stream, "  e500|e500x2              Disassemble the e500 instructions\n");
315   fprintf (stream, "  efs                      Disassemble the EFS instructions\n");
316   fprintf (stream, "  power4                   Disassemble the Power4 instructions\n");
317   fprintf (stream, "  32                       Do not disassemble 64-bit instructions\n");
318   fprintf (stream, "  64                       Allow disassembly of 64-bit instructions\n");
319 }