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