12159047fSniklas /* ppc-dis.c -- Disassemble PowerPC instructions
2*007c2a45Smiod Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004
3*007c2a45Smiod Free Software Foundation, Inc.
42159047fSniklas Written by Ian Lance Taylor, Cygnus Support
52159047fSniklas
62159047fSniklas This file is part of GDB, GAS, and the GNU binutils.
72159047fSniklas
82159047fSniklas GDB, GAS, and the GNU binutils are free software; you can redistribute
92159047fSniklas them and/or modify them under the terms of the GNU General Public
102159047fSniklas License as published by the Free Software Foundation; either version
112159047fSniklas 2, or (at your option) any later version.
122159047fSniklas
132159047fSniklas GDB, GAS, and the GNU binutils are distributed in the hope that they
142159047fSniklas will be useful, but WITHOUT ANY WARRANTY; without even the implied
152159047fSniklas warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
162159047fSniklas the GNU General Public License for more details.
172159047fSniklas
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this file; see the file COPYING. If not, write to the Free
202159047fSniklas Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
212159047fSniklas
222159047fSniklas #include <stdio.h>
232159047fSniklas #include "sysdep.h"
242159047fSniklas #include "dis-asm.h"
252159047fSniklas #include "opcode/ppc.h"
262159047fSniklas
272159047fSniklas /* This file provides several disassembler functions, all of which use
282159047fSniklas the disassembler interface defined in dis-asm.h. Several functions
292159047fSniklas are provided because this file handles disassembly for the PowerPC
302159047fSniklas in both big and little endian mode and also for the POWER (RS/6000)
312159047fSniklas chip. */
322159047fSniklas
33*007c2a45Smiod static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, int);
342159047fSniklas
35*007c2a45Smiod struct dis_private {
36*007c2a45Smiod /* Stash the result of parsing disassembler_options here. */
37*007c2a45Smiod int dialect;
38*007c2a45Smiod };
39c074d1c9Sdrahn
40c074d1c9Sdrahn /* Determine which set of machines to disassemble for. PPC403/601 or
41c074d1c9Sdrahn BookE. For convenience, also disassemble instructions supported
42c074d1c9Sdrahn by the AltiVec vector unit. */
43c074d1c9Sdrahn
44*007c2a45Smiod static int
powerpc_dialect(struct disassemble_info * info)45*007c2a45Smiod powerpc_dialect (struct disassemble_info *info)
46c074d1c9Sdrahn {
47c074d1c9Sdrahn int dialect = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC;
48c074d1c9Sdrahn
49c074d1c9Sdrahn if (BFD_DEFAULT_TARGET_SIZE == 64)
50c074d1c9Sdrahn dialect |= PPC_OPCODE_64;
51c074d1c9Sdrahn
52c074d1c9Sdrahn if (info->disassembler_options
53*007c2a45Smiod && strstr (info->disassembler_options, "booke") != NULL)
54c074d1c9Sdrahn dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
55*007c2a45Smiod else if ((info->mach == bfd_mach_ppc_e500)
56c074d1c9Sdrahn || (info->disassembler_options
57*007c2a45Smiod && strstr (info->disassembler_options, "e500") != NULL))
58c074d1c9Sdrahn {
59c074d1c9Sdrahn dialect |= PPC_OPCODE_BOOKE
60c074d1c9Sdrahn | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
61c074d1c9Sdrahn | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
62c074d1c9Sdrahn | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
63c074d1c9Sdrahn | PPC_OPCODE_RFMCI;
64c074d1c9Sdrahn /* efs* and AltiVec conflict. */
65c074d1c9Sdrahn dialect &= ~PPC_OPCODE_ALTIVEC;
66c074d1c9Sdrahn }
67*007c2a45Smiod else if (info->disassembler_options
68*007c2a45Smiod && strstr (info->disassembler_options, "efs") != NULL)
69c074d1c9Sdrahn {
70c074d1c9Sdrahn dialect |= PPC_OPCODE_EFS;
71c074d1c9Sdrahn /* efs* and AltiVec conflict. */
72c074d1c9Sdrahn dialect &= ~PPC_OPCODE_ALTIVEC;
73c074d1c9Sdrahn }
74c074d1c9Sdrahn else
75c074d1c9Sdrahn dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
76c074d1c9Sdrahn | PPC_OPCODE_COMMON);
77c074d1c9Sdrahn
78c074d1c9Sdrahn if (info->disassembler_options
79*007c2a45Smiod && strstr (info->disassembler_options, "power4") != NULL)
80c074d1c9Sdrahn dialect |= PPC_OPCODE_POWER4;
81c074d1c9Sdrahn
82*007c2a45Smiod if (info->disassembler_options
83*007c2a45Smiod && strstr (info->disassembler_options, "any") != NULL)
84*007c2a45Smiod dialect |= PPC_OPCODE_ANY;
85*007c2a45Smiod
86c074d1c9Sdrahn if (info->disassembler_options)
87c074d1c9Sdrahn {
88c074d1c9Sdrahn if (strstr (info->disassembler_options, "32") != NULL)
89c074d1c9Sdrahn dialect &= ~PPC_OPCODE_64;
90c074d1c9Sdrahn else if (strstr (info->disassembler_options, "64") != NULL)
91c074d1c9Sdrahn dialect |= PPC_OPCODE_64;
92c074d1c9Sdrahn }
93c074d1c9Sdrahn
94*007c2a45Smiod ((struct dis_private *) &info->private_data)->dialect = dialect;
95c074d1c9Sdrahn return dialect;
96c074d1c9Sdrahn }
97c074d1c9Sdrahn
98c074d1c9Sdrahn /* Print a big endian PowerPC instruction. */
992159047fSniklas
1002159047fSniklas int
print_insn_big_powerpc(bfd_vma memaddr,struct disassemble_info * info)101*007c2a45Smiod print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
1022159047fSniklas {
103*007c2a45Smiod int dialect = ((struct dis_private *) &info->private_data)->dialect;
104*007c2a45Smiod return print_insn_powerpc (memaddr, info, 1, dialect);
1052159047fSniklas }
1062159047fSniklas
107c074d1c9Sdrahn /* Print a little endian PowerPC instruction. */
1082159047fSniklas
1092159047fSniklas int
print_insn_little_powerpc(bfd_vma memaddr,struct disassemble_info * info)110*007c2a45Smiod print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
1112159047fSniklas {
112*007c2a45Smiod int dialect = ((struct dis_private *) &info->private_data)->dialect;
113*007c2a45Smiod return print_insn_powerpc (memaddr, info, 0, dialect);
1142159047fSniklas }
1152159047fSniklas
1162159047fSniklas /* Print a POWER (RS/6000) instruction. */
1172159047fSniklas
1182159047fSniklas int
print_insn_rs6000(bfd_vma memaddr,struct disassemble_info * info)119*007c2a45Smiod print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
1202159047fSniklas {
1212159047fSniklas return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
1222159047fSniklas }
1232159047fSniklas
1242159047fSniklas /* Print a PowerPC or POWER instruction. */
1252159047fSniklas
1262159047fSniklas static int
print_insn_powerpc(bfd_vma memaddr,struct disassemble_info * info,int bigendian,int dialect)127*007c2a45Smiod print_insn_powerpc (bfd_vma memaddr,
128*007c2a45Smiod struct disassemble_info *info,
129*007c2a45Smiod int bigendian,
130*007c2a45Smiod int dialect)
1312159047fSniklas {
1322159047fSniklas bfd_byte buffer[4];
1332159047fSniklas int status;
1342159047fSniklas unsigned long insn;
1352159047fSniklas const struct powerpc_opcode *opcode;
1362159047fSniklas const struct powerpc_opcode *opcode_end;
1372159047fSniklas unsigned long op;
1382159047fSniklas
139*007c2a45Smiod if (dialect == 0)
140*007c2a45Smiod dialect = powerpc_dialect (info);
141*007c2a45Smiod
1422159047fSniklas status = (*info->read_memory_func) (memaddr, buffer, 4, info);
1432159047fSniklas if (status != 0)
1442159047fSniklas {
1452159047fSniklas (*info->memory_error_func) (status, memaddr, info);
1462159047fSniklas return -1;
1472159047fSniklas }
1482159047fSniklas
1492159047fSniklas if (bigendian)
1502159047fSniklas insn = bfd_getb32 (buffer);
1512159047fSniklas else
1522159047fSniklas insn = bfd_getl32 (buffer);
1532159047fSniklas
1542159047fSniklas /* Get the major opcode of the instruction. */
1552159047fSniklas op = PPC_OP (insn);
1562159047fSniklas
1572159047fSniklas /* Find the first match in the opcode table. We could speed this up
1582159047fSniklas a bit by doing a binary search on the major opcode. */
1592159047fSniklas opcode_end = powerpc_opcodes + powerpc_num_opcodes;
160*007c2a45Smiod again:
1612159047fSniklas for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
1622159047fSniklas {
1632159047fSniklas unsigned long table_op;
1642159047fSniklas const unsigned char *opindex;
1652159047fSniklas const struct powerpc_operand *operand;
1662159047fSniklas int invalid;
1672159047fSniklas int need_comma;
1682159047fSniklas int need_paren;
1692159047fSniklas
1702159047fSniklas table_op = PPC_OP (opcode->opcode);
1712159047fSniklas if (op < table_op)
1722159047fSniklas break;
1732159047fSniklas if (op > table_op)
1742159047fSniklas continue;
1752159047fSniklas
1762159047fSniklas if ((insn & opcode->mask) != opcode->opcode
1772159047fSniklas || (opcode->flags & dialect) == 0)
1782159047fSniklas continue;
1792159047fSniklas
1802159047fSniklas /* Make two passes over the operands. First see if any of them
1812159047fSniklas have extraction functions, and, if they do, make sure the
1822159047fSniklas instruction is valid. */
1832159047fSniklas invalid = 0;
1842159047fSniklas for (opindex = opcode->operands; *opindex != 0; opindex++)
1852159047fSniklas {
1862159047fSniklas operand = powerpc_operands + *opindex;
1872159047fSniklas if (operand->extract)
188c074d1c9Sdrahn (*operand->extract) (insn, dialect, &invalid);
1892159047fSniklas }
1902159047fSniklas if (invalid)
1912159047fSniklas continue;
1922159047fSniklas
1932159047fSniklas /* The instruction is valid. */
1942159047fSniklas if (opcode->operands[0] != 0)
195*007c2a45Smiod (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
196*007c2a45Smiod else
197*007c2a45Smiod (*info->fprintf_func) (info->stream, "%s", opcode->name);
1982159047fSniklas
1992159047fSniklas /* Now extract and print the operands. */
2002159047fSniklas need_comma = 0;
2012159047fSniklas need_paren = 0;
2022159047fSniklas for (opindex = opcode->operands; *opindex != 0; opindex++)
2032159047fSniklas {
2042159047fSniklas long value;
2052159047fSniklas
2062159047fSniklas operand = powerpc_operands + *opindex;
2072159047fSniklas
2082159047fSniklas /* Operands that are marked FAKE are simply ignored. We
2092159047fSniklas already made sure that the extract function considered
2102159047fSniklas the instruction to be valid. */
2112159047fSniklas if ((operand->flags & PPC_OPERAND_FAKE) != 0)
2122159047fSniklas continue;
2132159047fSniklas
2142159047fSniklas /* Extract the value from the instruction. */
2152159047fSniklas if (operand->extract)
216*007c2a45Smiod value = (*operand->extract) (insn, dialect, &invalid);
2172159047fSniklas else
2182159047fSniklas {
2192159047fSniklas value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
2202159047fSniklas if ((operand->flags & PPC_OPERAND_SIGNED) != 0
2212159047fSniklas && (value & (1 << (operand->bits - 1))) != 0)
2222159047fSniklas value -= 1 << operand->bits;
2232159047fSniklas }
2242159047fSniklas
2252159047fSniklas /* If the operand is optional, and the value is zero, don't
2262159047fSniklas print anything. */
2272159047fSniklas if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
2282159047fSniklas && (operand->flags & PPC_OPERAND_NEXT) == 0
2292159047fSniklas && value == 0)
2302159047fSniklas continue;
2312159047fSniklas
2322159047fSniklas if (need_comma)
2332159047fSniklas {
2342159047fSniklas (*info->fprintf_func) (info->stream, ",");
2352159047fSniklas need_comma = 0;
2362159047fSniklas }
2372159047fSniklas
2382159047fSniklas /* Print the operand as directed by the flags. */
239*007c2a45Smiod if ((operand->flags & PPC_OPERAND_GPR) != 0
240*007c2a45Smiod || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
2412159047fSniklas (*info->fprintf_func) (info->stream, "r%ld", value);
2422159047fSniklas else if ((operand->flags & PPC_OPERAND_FPR) != 0)
2432159047fSniklas (*info->fprintf_func) (info->stream, "f%ld", value);
244b55d4692Sfgsch else if ((operand->flags & PPC_OPERAND_VR) != 0)
245b55d4692Sfgsch (*info->fprintf_func) (info->stream, "v%ld", value);
2462159047fSniklas else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
2472159047fSniklas (*info->print_address_func) (memaddr + value, info);
2482159047fSniklas else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
2492159047fSniklas (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
2502159047fSniklas else if ((operand->flags & PPC_OPERAND_CR) == 0
2512159047fSniklas || (dialect & PPC_OPCODE_PPC) == 0)
2522159047fSniklas (*info->fprintf_func) (info->stream, "%ld", value);
2532159047fSniklas else
2542159047fSniklas {
2552159047fSniklas if (operand->bits == 3)
2562159047fSniklas (*info->fprintf_func) (info->stream, "cr%d", value);
2572159047fSniklas else
2582159047fSniklas {
2592159047fSniklas static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
2602159047fSniklas int cr;
2612159047fSniklas int cc;
2622159047fSniklas
2632159047fSniklas cr = value >> 2;
2642159047fSniklas if (cr != 0)
265c074d1c9Sdrahn (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
2662159047fSniklas cc = value & 3;
2672159047fSniklas (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
2682159047fSniklas }
2692159047fSniklas }
2702159047fSniklas
2712159047fSniklas if (need_paren)
2722159047fSniklas {
2732159047fSniklas (*info->fprintf_func) (info->stream, ")");
2742159047fSniklas need_paren = 0;
2752159047fSniklas }
2762159047fSniklas
2772159047fSniklas if ((operand->flags & PPC_OPERAND_PARENS) == 0)
2782159047fSniklas need_comma = 1;
2792159047fSniklas else
2802159047fSniklas {
2812159047fSniklas (*info->fprintf_func) (info->stream, "(");
2822159047fSniklas need_paren = 1;
2832159047fSniklas }
2842159047fSniklas }
2852159047fSniklas
2862159047fSniklas /* We have found and printed an instruction; return. */
2872159047fSniklas return 4;
2882159047fSniklas }
2892159047fSniklas
290*007c2a45Smiod if ((dialect & PPC_OPCODE_ANY) != 0)
291*007c2a45Smiod {
292*007c2a45Smiod dialect = ~PPC_OPCODE_ANY;
293*007c2a45Smiod goto again;
294*007c2a45Smiod }
295*007c2a45Smiod
2962159047fSniklas /* We could not find a match. */
2972159047fSniklas (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
2982159047fSniklas
2992159047fSniklas return 4;
3002159047fSniklas }
301c074d1c9Sdrahn
302c074d1c9Sdrahn void
print_ppc_disassembler_options(FILE * stream)303c074d1c9Sdrahn print_ppc_disassembler_options (FILE *stream)
304c074d1c9Sdrahn {
305c074d1c9Sdrahn fprintf (stream, "\n\
306c074d1c9Sdrahn The following PPC specific disassembler options are supported for use with\n\
307c074d1c9Sdrahn the -M switch:\n");
308c074d1c9Sdrahn
309c074d1c9Sdrahn fprintf (stream, " booke|booke32|booke64 Disassemble the BookE instructions\n");
310c074d1c9Sdrahn fprintf (stream, " e500|e500x2 Disassemble the e500 instructions\n");
311c074d1c9Sdrahn fprintf (stream, " efs Disassemble the EFS instructions\n");
312c074d1c9Sdrahn fprintf (stream, " power4 Disassemble the Power4 instructions\n");
313c074d1c9Sdrahn fprintf (stream, " 32 Do not disassemble 64-bit instructions\n");
314c074d1c9Sdrahn fprintf (stream, " 64 Allow disassembly of 64-bit instructions\n");
315c074d1c9Sdrahn }
316