OSDN Git Service

Add powerpc cell support.
[pf3gnuchains/pf3gnuchains3x.git] / opcodes / ppc-dis.c
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 <stdio.h>
23 #include "sysdep.h"
24 #include "dis-asm.h"
25 #include "opcode/ppc.h"
26
27 /* This file provides several disassembler functions, all of which use
28    the disassembler interface defined in dis-asm.h.  Several functions
29    are provided because this file handles disassembly for the PowerPC
30    in both big and little endian mode and also for the POWER (RS/6000)
31    chip.  */
32
33 static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, int);
34
35 /* Determine which set of machines to disassemble for.  PPC403/601 or
36    BookE.  For convenience, also disassemble instructions supported
37    by the AltiVec vector unit.  */
38
39 static int
40 powerpc_dialect (struct disassemble_info *info)
41 {
42   int dialect = PPC_OPCODE_PPC;
43
44   if (BFD_DEFAULT_TARGET_SIZE == 64)
45     dialect |= PPC_OPCODE_64;
46
47   if (info->disassembler_options
48       && strstr (info->disassembler_options, "booke") != NULL)
49     dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
50   else if ((info->mach == bfd_mach_ppc_e500)
51            || (info->disassembler_options
52                && strstr (info->disassembler_options, "e500") != NULL))
53     dialect |= (PPC_OPCODE_BOOKE
54                 | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
55                 | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
56                 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
57                 | PPC_OPCODE_RFMCI);
58   else if (info->disassembler_options
59            && strstr (info->disassembler_options, "efs") != NULL)
60     dialect |= PPC_OPCODE_EFS;
61   else if (info->disassembler_options
62            && strstr (info->disassembler_options, "e300") != NULL)
63     dialect |= PPC_OPCODE_E300 | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON;
64   else
65     dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
66                 | PPC_OPCODE_COMMON | PPC_OPCODE_ALTIVEC);
67
68   if (info->disassembler_options
69       && strstr (info->disassembler_options, "power4") != NULL)
70     dialect |= PPC_OPCODE_POWER4;
71
72   if (info->disassembler_options
73       && strstr (info->disassembler_options, "power5") != NULL)
74     dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5;
75
76   if (info->disassembler_options
77       && strstr (info->disassembler_options, "cell") != NULL)
78     dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC;
79
80   if (info->disassembler_options
81       && strstr (info->disassembler_options, "power6") != NULL)
82     dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC;
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   info->private_data = (char *) 0 + 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   int dialect = (char *) info->private_data - (char *) 0;
106   return print_insn_powerpc (memaddr, info, 1, dialect);
107 }
108
109 /* Print a little endian PowerPC instruction.  */
110
111 int
112 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
113 {
114   int dialect = (char *) info->private_data - (char *) 0;
115   return print_insn_powerpc (memaddr, info, 0, dialect);
116 }
117
118 /* Print a POWER (RS/6000) instruction.  */
119
120 int
121 print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
122 {
123   return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
124 }
125
126 /* Print a PowerPC or POWER instruction.  */
127
128 static int
129 print_insn_powerpc (bfd_vma memaddr,
130                     struct disassemble_info *info,
131                     int bigendian,
132                     int dialect)
133 {
134   bfd_byte buffer[4];
135   int status;
136   unsigned long insn;
137   const struct powerpc_opcode *opcode;
138   const struct powerpc_opcode *opcode_end;
139   unsigned long op;
140
141   if (dialect == 0)
142     dialect = powerpc_dialect (info);
143
144   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
145   if (status != 0)
146     {
147       (*info->memory_error_func) (status, memaddr, info);
148       return -1;
149     }
150
151   if (bigendian)
152     insn = bfd_getb32 (buffer);
153   else
154     insn = bfd_getl32 (buffer);
155
156   /* Get the major opcode of the instruction.  */
157   op = PPC_OP (insn);
158
159   /* Find the first match in the opcode table.  We could speed this up
160      a bit by doing a binary search on the major opcode.  */
161   opcode_end = powerpc_opcodes + powerpc_num_opcodes;
162  again:
163   for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
164     {
165       unsigned long table_op;
166       const unsigned char *opindex;
167       const struct powerpc_operand *operand;
168       int invalid;
169       int need_comma;
170       int need_paren;
171
172       table_op = PPC_OP (opcode->opcode);
173       if (op < table_op)
174         break;
175       if (op > table_op)
176         continue;
177
178       if ((insn & opcode->mask) != opcode->opcode
179           || (opcode->flags & dialect) == 0)
180         continue;
181
182       /* Make two passes over the operands.  First see if any of them
183          have extraction functions, and, if they do, make sure the
184          instruction is valid.  */
185       invalid = 0;
186       for (opindex = opcode->operands; *opindex != 0; opindex++)
187         {
188           operand = powerpc_operands + *opindex;
189           if (operand->extract)
190             (*operand->extract) (insn, dialect, &invalid);
191         }
192       if (invalid)
193         continue;
194
195       /* The instruction is valid.  */
196       if (opcode->operands[0] != 0)
197         (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
198       else
199         (*info->fprintf_func) (info->stream, "%s", opcode->name);
200
201       /* Now extract and print the operands.  */
202       need_comma = 0;
203       need_paren = 0;
204       for (opindex = opcode->operands; *opindex != 0; opindex++)
205         {
206           long value;
207
208           operand = powerpc_operands + *opindex;
209
210           /* Operands that are marked FAKE are simply ignored.  We
211              already made sure that the extract function considered
212              the instruction to be valid.  */
213           if ((operand->flags & PPC_OPERAND_FAKE) != 0)
214             continue;
215
216           /* Extract the value from the instruction.  */
217           if (operand->extract)
218             value = (*operand->extract) (insn, dialect, &invalid);
219           else
220             {
221               value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
222               if ((operand->flags & PPC_OPERAND_SIGNED) != 0
223                   && (value & (1 << (operand->bits - 1))) != 0)
224                 value -= 1 << operand->bits;
225             }
226
227           /* If the operand is optional, and the value is zero, don't
228              print anything.  */
229           if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
230               && (operand->flags & PPC_OPERAND_NEXT) == 0
231               && value == 0)
232             continue;
233
234           if (need_comma)
235             {
236               (*info->fprintf_func) (info->stream, ",");
237               need_comma = 0;
238             }
239
240           /* Print the operand as directed by the flags.  */
241           if ((operand->flags & PPC_OPERAND_GPR) != 0
242               || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
243             (*info->fprintf_func) (info->stream, "r%ld", value);
244           else if ((operand->flags & PPC_OPERAND_FPR) != 0)
245             (*info->fprintf_func) (info->stream, "f%ld", value);
246           else if ((operand->flags & PPC_OPERAND_VR) != 0)
247             (*info->fprintf_func) (info->stream, "v%ld", value);
248           else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
249             (*info->print_address_func) (memaddr + value, info);
250           else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
251             (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
252           else if ((operand->flags & PPC_OPERAND_CR) == 0
253                    || (dialect & PPC_OPCODE_PPC) == 0)
254             (*info->fprintf_func) (info->stream, "%ld", value);
255           else
256             {
257               if (operand->bits == 3)
258                 (*info->fprintf_func) (info->stream, "cr%ld", value);
259               else
260                 {
261                   static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
262                   int cr;
263                   int cc;
264
265                   cr = value >> 2;
266                   if (cr != 0)
267                     (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
268                   cc = value & 3;
269                   (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
270                 }
271             }
272
273           if (need_paren)
274             {
275               (*info->fprintf_func) (info->stream, ")");
276               need_paren = 0;
277             }
278
279           if ((operand->flags & PPC_OPERAND_PARENS) == 0)
280             need_comma = 1;
281           else
282             {
283               (*info->fprintf_func) (info->stream, "(");
284               need_paren = 1;
285             }
286         }
287
288       /* We have found and printed an instruction; return.  */
289       return 4;
290     }
291
292   if ((dialect & PPC_OPCODE_ANY) != 0)
293     {
294       dialect = ~PPC_OPCODE_ANY;
295       goto again;
296     }
297
298   /* We could not find a match.  */
299   (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
300
301   return 4;
302 }
303
304 void
305 print_ppc_disassembler_options (FILE *stream)
306 {
307   fprintf (stream, "\n\
308 The following PPC specific disassembler options are supported for use with\n\
309 the -M switch:\n");
310
311   fprintf (stream, "  booke|booke32|booke64    Disassemble the BookE instructions\n");
312   fprintf (stream, "  e300                     Disassemble the e300 instructions\n");
313   fprintf (stream, "  e500|e500x2              Disassemble the e500 instructions\n");
314   fprintf (stream, "  efs                      Disassemble the EFS instructions\n");
315   fprintf (stream, "  power4                   Disassemble the Power4 instructions\n");
316   fprintf (stream, "  power5                   Disassemble the Power5 instructions\n");
317   fprintf (stream, "  power6                   Disassemble the Power6 instructions\n");
318   fprintf (stream, "  32                       Do not disassemble 64-bit instructions\n");
319   fprintf (stream, "  64                       Allow disassembly of 64-bit instructions\n");
320 }