1/* ppc-dis.c -- Disassemble PowerPC instructions 2 Copyright (C) 1994-2017 Free Software Foundation, Inc. 3 Written by Ian Lance Taylor, Cygnus Support 4 5 This file is part of the GNU opcodes library. 6 7 This library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 It is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this file; see the file COPYING. If not, write to the 19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22#include "sysdep.h" 23#include <stdio.h> 24#include "dis-asm.h" 25#include "elf-bfd.h" 26#include "elf/ppc.h" 27#include "opintl.h" 28#include "opcode/ppc.h" 29 30/* This file provides several disassembler functions, all of which use 31 the disassembler interface defined in dis-asm.h. Several functions 32 are provided because this file handles disassembly for the PowerPC 33 in both big and little endian mode and also for the POWER (RS/6000) 34 chip. */ 35static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, 36 ppc_cpu_t); 37 38struct dis_private 39{ 40 /* Stash the result of parsing disassembler_options here. */ 41 ppc_cpu_t dialect; 42} private; 43 44#define POWERPC_DIALECT(INFO) \ 45 (((struct dis_private *) ((INFO)->private_data))->dialect) 46 47struct ppc_mopt { 48 /* Option string, without -m or -M prefix. */ 49 const char *opt; 50 /* CPU option flags. */ 51 ppc_cpu_t cpu; 52 /* Flags that should stay on, even when combined with another cpu 53 option. This should only be used for generic options like 54 "-many" or "-maltivec" where it is reasonable to add some 55 capability to another cpu selection. The added flags are sticky 56 so that, for example, "-many -me500" and "-me500 -many" result in 57 the same assembler or disassembler behaviour. Do not use 58 "sticky" for specific cpus, as this will prevent that cpu's flags 59 from overriding the defaults set in powerpc_init_dialect or a 60 prior -m option. */ 61 ppc_cpu_t sticky; 62}; 63 64struct ppc_mopt ppc_opts[] = { 65 { "403", PPC_OPCODE_PPC | PPC_OPCODE_403, 66 0 }, 67 { "405", PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405, 68 0 }, 69 { "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440 70 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI), 71 0 }, 72 { "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440 73 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI), 74 0 }, 75 { "476", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_440 76 | PPC_OPCODE_476 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5), 77 0 }, 78 { "601", PPC_OPCODE_PPC | PPC_OPCODE_601, 79 0 }, 80 { "603", PPC_OPCODE_PPC, 81 0 }, 82 { "604", PPC_OPCODE_PPC, 83 0 }, 84 { "620", PPC_OPCODE_PPC | PPC_OPCODE_64, 85 0 }, 86 { "7400", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC, 87 0 }, 88 { "7410", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC, 89 0 }, 90 { "7450", PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC, 91 0 }, 92 { "7455", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC, 93 0 }, 94 { "750cl", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS 95 , 0 }, 96 { "821", PPC_OPCODE_PPC | PPC_OPCODE_860, 97 0 }, 98 { "850", PPC_OPCODE_PPC | PPC_OPCODE_860, 99 0 }, 100 { "860", PPC_OPCODE_PPC | PPC_OPCODE_860, 101 0 }, 102 { "a2", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4 103 | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64 104 | PPC_OPCODE_A2), 105 0 }, 106 { "altivec", PPC_OPCODE_PPC, 107 PPC_OPCODE_ALTIVEC }, 108 { "any", 0, 109 PPC_OPCODE_ANY }, 110 { "booke", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE, 111 0 }, 112 { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE, 113 0 }, 114 { "cell", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 115 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC), 116 0 }, 117 { "com", PPC_OPCODE_COMMON, 118 0 }, 119 { "e200z4", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE 120 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 121 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 122 | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4), 123 0 }, 124 { "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300, 125 0 }, 126 { "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE 127 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 128 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 129 | PPC_OPCODE_E500), 130 0 }, 131 { "e500mc", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL 132 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 133 | PPC_OPCODE_E500MC), 134 0 }, 135 { "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL 136 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 137 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5 138 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7), 139 0 }, 140 { "e5500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL 141 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 142 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 143 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 144 | PPC_OPCODE_POWER7), 145 0 }, 146 { "e6500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL 147 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 148 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC 149 | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_E6500 | PPC_OPCODE_POWER4 150 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7), 151 0 }, 152 { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE 153 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 154 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 155 | PPC_OPCODE_E500), 156 0 }, 157 { "efs", PPC_OPCODE_PPC | PPC_OPCODE_EFS, 158 0 }, 159 { "power4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4, 160 0 }, 161 { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 162 | PPC_OPCODE_POWER5), 163 0 }, 164 { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 165 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC), 166 0 }, 167 { "power7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 168 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 169 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 170 0 }, 171 { "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 172 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 173 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM 174 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX), 175 0 }, 176 { "power9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 177 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 178 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 179 | PPC_OPCODE_HTM | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 180 | PPC_OPCODE_VSX | PPC_OPCODE_VSX3 ), 181 0 }, 182 { "ppc", PPC_OPCODE_PPC, 183 0 }, 184 { "ppc32", PPC_OPCODE_PPC, 185 0 }, 186 { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64, 187 0 }, 188 { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE, 189 0 }, 190 { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS, 191 0 }, 192 { "pwr", PPC_OPCODE_POWER, 193 0 }, 194 { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2, 195 0 }, 196 { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4, 197 0 }, 198 { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 199 | PPC_OPCODE_POWER5), 200 0 }, 201 { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 202 | PPC_OPCODE_POWER5), 203 0 }, 204 { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 205 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC), 206 0 }, 207 { "pwr7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 208 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 209 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 210 0 }, 211 { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 212 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 213 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM 214 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX), 215 0 }, 216 { "pwr9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 217 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 218 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 219 | PPC_OPCODE_HTM | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 220 | PPC_OPCODE_VSX | PPC_OPCODE_VSX3 ), 221 0 }, 222 { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2, 223 0 }, 224 { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS, 225 PPC_OPCODE_SPE }, 226 { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR 227 | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN), 228 0 }, 229 { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE 230 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 231 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 232 | PPC_OPCODE_E500), 233 PPC_OPCODE_VLE }, 234 { "vsx", PPC_OPCODE_PPC, 235 PPC_OPCODE_VSX }, 236 { "htm", PPC_OPCODE_PPC, 237 PPC_OPCODE_HTM }, 238}; 239 240/* Switch between Booke and VLE dialects for interlinked dumps. */ 241static ppc_cpu_t 242get_powerpc_dialect (struct disassemble_info *info) 243{ 244 ppc_cpu_t dialect = 0; 245 246 dialect = POWERPC_DIALECT (info); 247 248 /* Disassemble according to the section headers flags for VLE-mode. */ 249 if (dialect & PPC_OPCODE_VLE 250 && info->section != NULL && info->section->owner != NULL 251 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour 252 && elf_object_id (info->section->owner) == PPC32_ELF_DATA 253 && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0) 254 return dialect; 255 else 256 return dialect & ~ PPC_OPCODE_VLE; 257} 258 259/* Handle -m and -M options that set cpu type, and .machine arg. */ 260 261ppc_cpu_t 262ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg) 263{ 264 unsigned int i; 265 266 for (i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++) 267 if (strcmp (ppc_opts[i].opt, arg) == 0) 268 { 269 if (ppc_opts[i].sticky) 270 { 271 *sticky |= ppc_opts[i].sticky; 272 if ((ppc_cpu & ~*sticky) != 0) 273 break; 274 } 275 ppc_cpu = ppc_opts[i].cpu; 276 break; 277 } 278 if (i >= sizeof (ppc_opts) / sizeof (ppc_opts[0])) 279 return 0; 280 281 ppc_cpu |= *sticky; 282 return ppc_cpu; 283} 284 285/* Determine which set of machines to disassemble for. */ 286 287static void 288powerpc_init_dialect (struct disassemble_info *info) 289{ 290 ppc_cpu_t dialect = 0; 291 ppc_cpu_t sticky = 0; 292 char *arg; 293 struct dis_private *priv = calloc (sizeof (*priv), 1); 294 295 if (priv == NULL) 296 priv = &private; 297 298 switch (info->mach) 299 { 300 case bfd_mach_ppc_403: 301 case bfd_mach_ppc_403gc: 302 dialect = ppc_parse_cpu (dialect, &sticky, "403"); 303 break; 304 case bfd_mach_ppc_405: 305 dialect = ppc_parse_cpu (dialect, &sticky, "405"); 306 break; 307 case bfd_mach_ppc_601: 308 dialect = ppc_parse_cpu (dialect, &sticky, "601"); 309 break; 310 case bfd_mach_ppc_a35: 311 case bfd_mach_ppc_rs64ii: 312 case bfd_mach_ppc_rs64iii: 313 dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64; 314 break; 315 case bfd_mach_ppc_e500: 316 dialect = ppc_parse_cpu (dialect, &sticky, "e500"); 317 break; 318 case bfd_mach_ppc_e500mc: 319 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc"); 320 break; 321 case bfd_mach_ppc_e500mc64: 322 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64"); 323 break; 324 case bfd_mach_ppc_e5500: 325 dialect = ppc_parse_cpu (dialect, &sticky, "e5500"); 326 break; 327 case bfd_mach_ppc_e6500: 328 dialect = ppc_parse_cpu (dialect, &sticky, "e6500"); 329 break; 330 case bfd_mach_ppc_titan: 331 dialect = ppc_parse_cpu (dialect, &sticky, "titan"); 332 break; 333 case bfd_mach_ppc_vle: 334 dialect = ppc_parse_cpu (dialect, &sticky, "vle"); 335 break; 336 default: 337 dialect = ppc_parse_cpu (dialect, &sticky, "power9") | PPC_OPCODE_ANY; 338 } 339 340 arg = info->disassembler_options; 341 while (arg != NULL) 342 { 343 ppc_cpu_t new_cpu = 0; 344 char *end = strchr (arg, ','); 345 346 if (end != NULL) 347 *end = 0; 348 349 if ((new_cpu = ppc_parse_cpu (dialect, &sticky, arg)) != 0) 350 dialect = new_cpu; 351 else if (strcmp (arg, "32") == 0) 352 dialect &= ~(ppc_cpu_t) PPC_OPCODE_64; 353 else if (strcmp (arg, "64") == 0) 354 dialect |= PPC_OPCODE_64; 355 else 356 fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), arg); 357 358 if (end != NULL) 359 *end++ = ','; 360 arg = end; 361 } 362 363 info->private_data = priv; 364 POWERPC_DIALECT(info) = dialect; 365} 366 367#define PPC_OPCD_SEGS 64 368static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS+1]; 369#define VLE_OPCD_SEGS 32 370static unsigned short vle_opcd_indices[VLE_OPCD_SEGS+1]; 371 372/* Calculate opcode table indices to speed up disassembly, 373 and init dialect. */ 374 375void 376disassemble_init_powerpc (struct disassemble_info *info) 377{ 378 int i; 379 unsigned short last; 380 381 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0) 382 { 383 384 i = powerpc_num_opcodes; 385 while (--i >= 0) 386 { 387 unsigned op = PPC_OP (powerpc_opcodes[i].opcode); 388 389 powerpc_opcd_indices[op] = i; 390 } 391 392 last = powerpc_num_opcodes; 393 for (i = PPC_OPCD_SEGS; i > 0; --i) 394 { 395 if (powerpc_opcd_indices[i] == 0) 396 powerpc_opcd_indices[i] = last; 397 last = powerpc_opcd_indices[i]; 398 } 399 400 i = vle_num_opcodes; 401 while (--i >= 0) 402 { 403 unsigned op = VLE_OP (vle_opcodes[i].opcode, vle_opcodes[i].mask); 404 unsigned seg = VLE_OP_TO_SEG (op); 405 406 vle_opcd_indices[seg] = i; 407 } 408 409 last = vle_num_opcodes; 410 for (i = VLE_OPCD_SEGS; i > 0; --i) 411 { 412 if (vle_opcd_indices[i] == 0) 413 vle_opcd_indices[i] = last; 414 last = vle_opcd_indices[i]; 415 } 416 } 417 418 if (info->arch == bfd_arch_powerpc) 419 powerpc_init_dialect (info); 420} 421 422/* Print a big endian PowerPC instruction. */ 423 424int 425print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info) 426{ 427 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info)); 428} 429 430/* Print a little endian PowerPC instruction. */ 431 432int 433print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info) 434{ 435 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info)); 436} 437 438/* Print a POWER (RS/6000) instruction. */ 439 440int 441print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info) 442{ 443 return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER); 444} 445 446/* Extract the operand value from the PowerPC or POWER instruction. */ 447 448static long 449operand_value_powerpc (const struct powerpc_operand *operand, 450 unsigned long insn, ppc_cpu_t dialect) 451{ 452 long value; 453 int invalid; 454 /* Extract the value from the instruction. */ 455 if (operand->extract) 456 value = (*operand->extract) (insn, dialect, &invalid); 457 else 458 { 459 if (operand->shift >= 0) 460 value = (insn >> operand->shift) & operand->bitm; 461 else 462 value = (insn << -operand->shift) & operand->bitm; 463 if ((operand->flags & PPC_OPERAND_SIGNED) != 0) 464 { 465 /* BITM is always some number of zeros followed by some 466 number of ones, followed by some number of zeros. */ 467 unsigned long top = operand->bitm; 468 /* top & -top gives the rightmost 1 bit, so this 469 fills in any trailing zeros. */ 470 top |= (top & -top) - 1; 471 top &= ~(top >> 1); 472 value = (value ^ top) - top; 473 } 474 } 475 476 return value; 477} 478 479/* Determine whether the optional operand(s) should be printed. */ 480 481static int 482skip_optional_operands (const unsigned char *opindex, 483 unsigned long insn, ppc_cpu_t dialect) 484{ 485 const struct powerpc_operand *operand; 486 487 for (; *opindex != 0; opindex++) 488 { 489 operand = &powerpc_operands[*opindex]; 490 if ((operand->flags & PPC_OPERAND_NEXT) != 0 491 || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 492 && operand_value_powerpc (operand, insn, dialect) != 493 ppc_optional_operand_value (operand))) 494 return 0; 495 } 496 497 return 1; 498} 499 500/* Find a match for INSN in the opcode table, given machine DIALECT. 501 A DIALECT of -1 is special, matching all machine opcode variations. */ 502 503static const struct powerpc_opcode * 504lookup_powerpc (unsigned long insn, ppc_cpu_t dialect) 505{ 506 const struct powerpc_opcode *opcode; 507 const struct powerpc_opcode *opcode_end; 508 unsigned long op; 509 510 /* Get the major opcode of the instruction. */ 511 op = PPC_OP (insn); 512 513 /* Find the first match in the opcode table for this major opcode. */ 514 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1]; 515 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op]; 516 opcode < opcode_end; 517 ++opcode) 518 { 519 const unsigned char *opindex; 520 const struct powerpc_operand *operand; 521 int invalid; 522 523 if ((insn & opcode->mask) != opcode->opcode 524 || (dialect != (ppc_cpu_t) -1 525 && ((opcode->flags & dialect) == 0 526 || (opcode->deprecated & dialect) != 0))) 527 continue; 528 529 /* Check validity of operands. */ 530 invalid = 0; 531 for (opindex = opcode->operands; *opindex != 0; opindex++) 532 { 533 operand = powerpc_operands + *opindex; 534 if (operand->extract) 535 (*operand->extract) (insn, dialect, &invalid); 536 } 537 if (invalid) 538 continue; 539 540 return opcode; 541 } 542 543 return NULL; 544} 545 546/* Find a match for INSN in the VLE opcode table. */ 547 548static const struct powerpc_opcode * 549lookup_vle (unsigned long insn) 550{ 551 const struct powerpc_opcode *opcode; 552 const struct powerpc_opcode *opcode_end; 553 unsigned op, seg; 554 555 op = PPC_OP (insn); 556 if (op >= 0x20 && op <= 0x37) 557 { 558 /* This insn has a 4-bit opcode. */ 559 op &= 0x3c; 560 } 561 seg = VLE_OP_TO_SEG (op); 562 563 /* Find the first match in the opcode table for this major opcode. */ 564 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1]; 565 for (opcode = vle_opcodes + vle_opcd_indices[seg]; 566 opcode < opcode_end; 567 ++opcode) 568 { 569 unsigned long table_opcd = opcode->opcode; 570 unsigned long table_mask = opcode->mask; 571 bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask); 572 unsigned long insn2; 573 const unsigned char *opindex; 574 const struct powerpc_operand *operand; 575 int invalid; 576 577 insn2 = insn; 578 if (table_op_is_short) 579 insn2 >>= 16; 580 if ((insn2 & table_mask) != table_opcd) 581 continue; 582 583 /* Check validity of operands. */ 584 invalid = 0; 585 for (opindex = opcode->operands; *opindex != 0; ++opindex) 586 { 587 operand = powerpc_operands + *opindex; 588 if (operand->extract) 589 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid); 590 } 591 if (invalid) 592 continue; 593 594 return opcode; 595 } 596 597 return NULL; 598} 599 600/* Print a PowerPC or POWER instruction. */ 601 602static int 603print_insn_powerpc (bfd_vma memaddr, 604 struct disassemble_info *info, 605 int bigendian, 606 ppc_cpu_t dialect) 607{ 608 bfd_byte buffer[4]; 609 int status; 610 unsigned long insn; 611 const struct powerpc_opcode *opcode; 612 bfd_boolean insn_is_short; 613 614 status = (*info->read_memory_func) (memaddr, buffer, 4, info); 615 if (status != 0) 616 { 617 /* The final instruction may be a 2-byte VLE insn. */ 618 if ((dialect & PPC_OPCODE_VLE) != 0) 619 { 620 /* Clear buffer so unused bytes will not have garbage in them. */ 621 buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0; 622 status = (*info->read_memory_func) (memaddr, buffer, 2, info); 623 if (status != 0) 624 { 625 (*info->memory_error_func) (status, memaddr, info); 626 return -1; 627 } 628 } 629 else 630 { 631 (*info->memory_error_func) (status, memaddr, info); 632 return -1; 633 } 634 } 635 636 if (bigendian) 637 insn = bfd_getb32 (buffer); 638 else 639 insn = bfd_getl32 (buffer); 640 641 /* Get the major opcode of the insn. */ 642 opcode = NULL; 643 insn_is_short = FALSE; 644 if ((dialect & PPC_OPCODE_VLE) != 0) 645 { 646 opcode = lookup_vle (insn); 647 if (opcode != NULL) 648 insn_is_short = PPC_OP_SE_VLE(opcode->mask); 649 } 650 if (opcode == NULL) 651 opcode = lookup_powerpc (insn, dialect); 652 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0) 653 opcode = lookup_powerpc (insn, (ppc_cpu_t) -1); 654 655 if (opcode != NULL) 656 { 657 const unsigned char *opindex; 658 const struct powerpc_operand *operand; 659 int need_comma; 660 int need_paren; 661 int skip_optional; 662 663 if (opcode->operands[0] != 0) 664 (*info->fprintf_func) (info->stream, "%-7s ", opcode->name); 665 else 666 (*info->fprintf_func) (info->stream, "%s", opcode->name); 667 668 if (insn_is_short) 669 /* The operands will be fetched out of the 16-bit instruction. */ 670 insn >>= 16; 671 672 /* Now extract and print the operands. */ 673 need_comma = 0; 674 need_paren = 0; 675 skip_optional = -1; 676 for (opindex = opcode->operands; *opindex != 0; opindex++) 677 { 678 long value; 679 680 operand = powerpc_operands + *opindex; 681 682 /* Operands that are marked FAKE are simply ignored. We 683 already made sure that the extract function considered 684 the instruction to be valid. */ 685 if ((operand->flags & PPC_OPERAND_FAKE) != 0) 686 continue; 687 688 /* If all of the optional operands have the value zero, 689 then don't print any of them. */ 690 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) 691 { 692 if (skip_optional < 0) 693 skip_optional = skip_optional_operands (opindex, insn, 694 dialect); 695 if (skip_optional) 696 continue; 697 } 698 699 value = operand_value_powerpc (operand, insn, dialect); 700 701 if (need_comma) 702 { 703 (*info->fprintf_func) (info->stream, ","); 704 need_comma = 0; 705 } 706 707 /* Print the operand as directed by the flags. */ 708 if ((operand->flags & PPC_OPERAND_GPR) != 0 709 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) 710 (*info->fprintf_func) (info->stream, "r%ld", value); 711 else if ((operand->flags & PPC_OPERAND_FPR) != 0) 712 (*info->fprintf_func) (info->stream, "f%ld", value); 713 else if ((operand->flags & PPC_OPERAND_VR) != 0) 714 (*info->fprintf_func) (info->stream, "v%ld", value); 715 else if ((operand->flags & PPC_OPERAND_VSR) != 0) 716 (*info->fprintf_func) (info->stream, "vs%ld", value); 717 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) 718 (*info->print_address_func) (memaddr + value, info); 719 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) 720 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); 721 else if ((operand->flags & PPC_OPERAND_FSL) != 0) 722 (*info->fprintf_func) (info->stream, "fsl%ld", value); 723 else if ((operand->flags & PPC_OPERAND_FCR) != 0) 724 (*info->fprintf_func) (info->stream, "fcr%ld", value); 725 else if ((operand->flags & PPC_OPERAND_UDI) != 0) 726 (*info->fprintf_func) (info->stream, "%ld", value); 727 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0 728 && (((dialect & PPC_OPCODE_PPC) != 0) 729 || ((dialect & PPC_OPCODE_VLE) != 0))) 730 (*info->fprintf_func) (info->stream, "cr%ld", value); 731 else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0) 732 && (((dialect & PPC_OPCODE_PPC) != 0) 733 || ((dialect & PPC_OPCODE_VLE) != 0))) 734 { 735 static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; 736 int cr; 737 int cc; 738 739 cr = value >> 2; 740 if (cr != 0) 741 (*info->fprintf_func) (info->stream, "4*cr%d+", cr); 742 cc = value & 3; 743 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]); 744 } 745 else 746 (*info->fprintf_func) (info->stream, "%d", (int) value); 747 748 if (need_paren) 749 { 750 (*info->fprintf_func) (info->stream, ")"); 751 need_paren = 0; 752 } 753 754 if ((operand->flags & PPC_OPERAND_PARENS) == 0) 755 need_comma = 1; 756 else 757 { 758 (*info->fprintf_func) (info->stream, "("); 759 need_paren = 1; 760 } 761 } 762 763 /* We have found and printed an instruction. 764 If it was a short VLE instruction we have more to do. */ 765 if (insn_is_short) 766 { 767 memaddr += 2; 768 return 2; 769 } 770 else 771 /* Otherwise, return. */ 772 return 4; 773 } 774 775 /* We could not find a match. */ 776 (*info->fprintf_func) (info->stream, ".long 0x%lx", insn); 777 778 return 4; 779} 780 781void 782print_ppc_disassembler_options (FILE *stream) 783{ 784 unsigned int i, col; 785 786 fprintf (stream, _("\n\ 787The following PPC specific disassembler options are supported for use with\n\ 788the -M switch:\n")); 789 790 for (col = 0, i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++) 791 { 792 col += fprintf (stream, " %s,", ppc_opts[i].opt); 793 if (col > 66) 794 { 795 fprintf (stream, "\n"); 796 col = 0; 797 } 798 } 799 fprintf (stream, " 32, 64\n"); 800} 801