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