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