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