1 /* ppc-dis.c -- Disassemble PowerPC instructions 2 Copyright (C) 1994-2022 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 "disassemble.h" 25 #include "elf-bfd.h" 26 #include "elf/ppc.h" 27 #include "opintl.h" 28 #include "opcode/ppc.h" 29 #include "libiberty.h" 30 31 /* This file provides several disassembler functions, all of which use 32 the disassembler interface defined in dis-asm.h. Several functions 33 are provided because this file handles disassembly for the PowerPC 34 in both big and little endian mode and also for the POWER (RS/6000) 35 chip. */ 36 static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, 37 ppc_cpu_t); 38 39 struct dis_private 40 { 41 /* Stash the result of parsing disassembler_options here. */ 42 ppc_cpu_t dialect; 43 44 /* .got and .plt sections. NAME is set to NULL if not present. */ 45 struct sec_buf { 46 asection *sec; 47 bfd_byte *buf; 48 const char *name; 49 } special[2]; 50 }; 51 52 static inline struct dis_private * 53 private_data (struct disassemble_info *info) 54 { 55 return (struct dis_private *) info->private_data; 56 } 57 58 struct ppc_mopt { 59 /* Option string, without -m or -M prefix. */ 60 const char *opt; 61 /* CPU option flags. */ 62 ppc_cpu_t cpu; 63 /* Flags that should stay on, even when combined with another cpu 64 option. This should only be used for generic options like 65 "-many" or "-maltivec" where it is reasonable to add some 66 capability to another cpu selection. The added flags are sticky 67 so that, for example, "-many -me500" and "-me500 -many" result in 68 the same assembler or disassembler behaviour. Do not use 69 "sticky" for specific cpus, as this will prevent that cpu's flags 70 from overriding the defaults set in powerpc_init_dialect or a 71 prior -m option. */ 72 ppc_cpu_t sticky; 73 }; 74 75 struct ppc_mopt ppc_opts[] = { 76 { "403", PPC_OPCODE_PPC | PPC_OPCODE_403, 77 0 }, 78 { "405", PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405, 79 0 }, 80 { "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440 81 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI), 82 0 }, 83 { "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440 84 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI), 85 0 }, 86 { "476", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_476 87 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5), 88 0 }, 89 { "601", PPC_OPCODE_PPC | PPC_OPCODE_601, 90 0 }, 91 { "603", PPC_OPCODE_PPC, 92 0 }, 93 { "604", PPC_OPCODE_PPC, 94 0 }, 95 { "620", PPC_OPCODE_PPC | PPC_OPCODE_64, 96 0 }, 97 { "7400", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC, 98 0 }, 99 { "7410", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC, 100 0 }, 101 { "7450", PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC, 102 0 }, 103 { "7455", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC, 104 0 }, 105 { "750cl", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS 106 , 0 }, 107 { "gekko", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS 108 , 0 }, 109 { "broadway", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS 110 , 0 }, 111 { "821", PPC_OPCODE_PPC | PPC_OPCODE_860, 112 0 }, 113 { "850", PPC_OPCODE_PPC | PPC_OPCODE_860, 114 0 }, 115 { "860", PPC_OPCODE_PPC | PPC_OPCODE_860, 116 0 }, 117 { "a2", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4 118 | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64 119 | PPC_OPCODE_A2), 120 0 }, 121 { "altivec", PPC_OPCODE_PPC, 122 PPC_OPCODE_ALTIVEC }, 123 { "any", PPC_OPCODE_PPC, 124 PPC_OPCODE_ANY }, 125 { "booke", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE, 126 0 }, 127 { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE, 128 0 }, 129 { "cell", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 130 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC), 131 0 }, 132 { "com", PPC_OPCODE_COMMON, 133 0 }, 134 { "e200z2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_LSP 135 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 136 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 137 | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4 138 | PPC_OPCODE_EFS2), 139 0 }, 140 { "e200z4", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE 141 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 142 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 143 | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4 144 | PPC_OPCODE_EFS2), 145 0 }, 146 { "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300, 147 0 }, 148 { "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE 149 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 150 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 151 | PPC_OPCODE_E500), 152 0 }, 153 { "e500mc", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL 154 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 155 | PPC_OPCODE_E500MC), 156 0 }, 157 { "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL 158 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 159 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5 160 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7), 161 0 }, 162 { "e5500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL 163 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 164 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 165 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7), 166 0 }, 167 { "e6500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL 168 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 169 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC 170 | PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4 171 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7), 172 0 }, 173 { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE 174 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 175 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 176 | PPC_OPCODE_E500), 177 0 }, 178 { "efs", PPC_OPCODE_PPC | PPC_OPCODE_EFS, 179 0 }, 180 { "efs2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2, 181 0 }, 182 { "lsp", PPC_OPCODE_PPC, 183 PPC_OPCODE_LSP }, 184 { "power4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4, 185 0 }, 186 { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 187 | PPC_OPCODE_POWER5), 188 0 }, 189 { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 190 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC), 191 0 }, 192 { "power7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 193 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 194 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 195 0 }, 196 { "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 197 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 198 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 199 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 200 0 }, 201 { "power9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 202 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 203 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 204 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 205 0 }, 206 { "power10", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 207 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 208 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 209 | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 210 0 }, 211 { "libresoc",(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_POWER9 214 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX | PPC_OPCODE_SVP64), 215 0 }, 216 { "future", (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_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX 220 | PPC_OPCODE_FUTURE), 221 0 }, 222 { "ppc", PPC_OPCODE_PPC, 223 0 }, 224 { "ppc32", PPC_OPCODE_PPC, 225 0 }, 226 { "32", PPC_OPCODE_PPC, 227 0 }, 228 { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64, 229 0 }, 230 { "64", PPC_OPCODE_PPC | PPC_OPCODE_64, 231 0 }, 232 { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE, 233 0 }, 234 { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS, 235 0 }, 236 { "pwr", PPC_OPCODE_POWER, 237 0 }, 238 { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2, 239 0 }, 240 { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4, 241 0 }, 242 { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 243 | PPC_OPCODE_POWER5), 244 0 }, 245 { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 246 | PPC_OPCODE_POWER5), 247 0 }, 248 { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4 249 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC), 250 0 }, 251 { "pwr7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 252 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 253 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 254 0 }, 255 { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 256 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 257 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 258 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 259 0 }, 260 { "pwr9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 261 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 262 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 263 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 264 0 }, 265 { "pwr10", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64 266 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 267 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 268 | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX), 269 0 }, 270 { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2, 271 0 }, 272 { "raw", PPC_OPCODE_PPC, 273 PPC_OPCODE_RAW }, 274 { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS, 275 PPC_OPCODE_SPE }, 276 { "spe2", PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE, 277 PPC_OPCODE_SPE2 }, 278 { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR 279 | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN), 280 0 }, 281 { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE 282 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK 283 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI 284 | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2), 285 PPC_OPCODE_VLE }, 286 { "vsx", PPC_OPCODE_PPC, 287 PPC_OPCODE_VSX }, 288 }; 289 290 /* Switch between Booke and VLE dialects for interlinked dumps. */ 291 static ppc_cpu_t 292 get_powerpc_dialect (struct disassemble_info *info) 293 { 294 ppc_cpu_t dialect = 0; 295 296 if (info->private_data) 297 dialect = private_data (info)->dialect; 298 299 /* Disassemble according to the section headers flags for VLE-mode. */ 300 if (dialect & PPC_OPCODE_VLE 301 && info->section != NULL && info->section->owner != NULL 302 && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour 303 && elf_object_id (info->section->owner) == PPC32_ELF_DATA 304 && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0) 305 return dialect; 306 else 307 return dialect & ~ PPC_OPCODE_VLE; 308 } 309 310 /* Handle -m and -M options that set cpu type, and .machine arg. */ 311 312 ppc_cpu_t 313 ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg) 314 { 315 unsigned int i; 316 317 for (i = 0; i < ARRAY_SIZE (ppc_opts); i++) 318 if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0) 319 { 320 if (ppc_opts[i].sticky) 321 { 322 *sticky |= ppc_opts[i].sticky; 323 if ((ppc_cpu & ~*sticky) != 0) 324 break; 325 } 326 ppc_cpu = ppc_opts[i].cpu; 327 break; 328 } 329 if (i >= ARRAY_SIZE (ppc_opts)) 330 return 0; 331 332 /* SPE and LSP are mutually exclusive, don't allow them both in 333 sticky options. However do allow them both in ppc_cpu, so that 334 for example, -mvle -mlsp enables both SPE and LSP for assembly. */ 335 if ((ppc_opts[i].sticky & PPC_OPCODE_LSP) != 0) 336 *sticky &= ~(PPC_OPCODE_SPE | PPC_OPCODE_SPE2); 337 else if ((ppc_opts[i].sticky & (PPC_OPCODE_SPE | PPC_OPCODE_SPE2)) != 0) 338 *sticky &= ~PPC_OPCODE_LSP; 339 ppc_cpu |= *sticky; 340 341 return ppc_cpu; 342 } 343 344 /* Determine which set of machines to disassemble for. */ 345 346 static void 347 powerpc_init_dialect (struct disassemble_info *info) 348 { 349 ppc_cpu_t dialect = 0; 350 ppc_cpu_t sticky = 0; 351 struct dis_private *priv = calloc (sizeof (*priv), 1); 352 353 if (priv == NULL) 354 return; 355 356 switch (info->mach) 357 { 358 case bfd_mach_ppc_403: 359 case bfd_mach_ppc_403gc: 360 dialect = ppc_parse_cpu (dialect, &sticky, "403"); 361 break; 362 case bfd_mach_ppc_405: 363 dialect = ppc_parse_cpu (dialect, &sticky, "405"); 364 break; 365 case bfd_mach_ppc_601: 366 dialect = ppc_parse_cpu (dialect, &sticky, "601"); 367 break; 368 case bfd_mach_ppc_750: 369 dialect = ppc_parse_cpu (dialect, &sticky, "750cl"); 370 break; 371 case bfd_mach_ppc_a35: 372 case bfd_mach_ppc_rs64ii: 373 case bfd_mach_ppc_rs64iii: 374 dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64; 375 break; 376 case bfd_mach_ppc_e500: 377 dialect = ppc_parse_cpu (dialect, &sticky, "e500"); 378 break; 379 case bfd_mach_ppc_e500mc: 380 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc"); 381 break; 382 case bfd_mach_ppc_e500mc64: 383 dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64"); 384 break; 385 case bfd_mach_ppc_e5500: 386 dialect = ppc_parse_cpu (dialect, &sticky, "e5500"); 387 break; 388 case bfd_mach_ppc_e6500: 389 dialect = ppc_parse_cpu (dialect, &sticky, "e6500"); 390 break; 391 case bfd_mach_ppc_titan: 392 dialect = ppc_parse_cpu (dialect, &sticky, "titan"); 393 break; 394 case bfd_mach_ppc_vle: 395 dialect = ppc_parse_cpu (dialect, &sticky, "vle"); 396 break; 397 default: 398 if (info->arch == bfd_arch_powerpc) 399 dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY; 400 else 401 dialect = ppc_parse_cpu (dialect, &sticky, "pwr"); 402 break; 403 } 404 405 const char *opt; 406 FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options) 407 { 408 ppc_cpu_t new_cpu = 0; 409 410 if (disassembler_options_cmp (opt, "32") == 0) 411 dialect &= ~(ppc_cpu_t) PPC_OPCODE_64; 412 else if (disassembler_options_cmp (opt, "64") == 0) 413 dialect |= PPC_OPCODE_64; 414 else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0) 415 dialect = new_cpu; 416 else 417 /* xgettext: c-format */ 418 opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt); 419 } 420 421 info->private_data = priv; 422 private_data (info)->dialect = dialect; 423 } 424 425 #define PPC_OPCD_SEGS (1 + PPC_OP (-1)) 426 static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1]; 427 #define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1)) 428 static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1]; 429 #define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff))) 430 static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1]; 431 #define LSP_OPCD_SEGS (1 + LSP_OP_TO_SEG (-1)) 432 static unsigned short lsp_opcd_indices[LSP_OPCD_SEGS + 1]; 433 #define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1))) 434 static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1]; 435 436 static bool 437 ppc_symbol_is_valid (asymbol *sym, 438 struct disassemble_info *info ATTRIBUTE_UNUSED) 439 { 440 elf_symbol_type * est; 441 442 if (sym == NULL) 443 return false; 444 445 est = elf_symbol_from (sym); 446 447 /* Ignore ELF hidden, local, no-type symbols. 448 These are generated by annobin. */ 449 if (est != NULL 450 && ELF_ST_VISIBILITY (est->internal_elf_sym.st_other) == STV_HIDDEN 451 && ELF_ST_BIND (est->internal_elf_sym.st_info) == STB_LOCAL 452 && ELF_ST_TYPE (est->internal_elf_sym.st_info) == STT_NOTYPE) 453 return false; 454 455 return true; 456 } 457 458 /* Calculate opcode table indices to speed up disassembly, 459 and init dialect. */ 460 461 void 462 disassemble_init_powerpc (struct disassemble_info *info) 463 { 464 info->symbol_is_valid = ppc_symbol_is_valid; 465 466 if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0) 467 { 468 unsigned seg, idx, op; 469 470 /* PPC opcodes */ 471 for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++) 472 { 473 powerpc_opcd_indices[seg] = idx; 474 for (; idx < powerpc_num_opcodes; idx++) 475 if (seg < PPC_OP (powerpc_opcodes[idx].opcode)) 476 break; 477 } 478 479 /* 64-bit prefix opcodes */ 480 for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++) 481 { 482 prefix_opcd_indices[seg] = idx; 483 for (; idx < prefix_num_opcodes; idx++) 484 if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode)) 485 break; 486 } 487 488 /* VLE opcodes */ 489 for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++) 490 { 491 vle_opcd_indices[seg] = idx; 492 for (; idx < vle_num_opcodes; idx++) 493 { 494 op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask); 495 if (seg < VLE_OP_TO_SEG (op)) 496 break; 497 } 498 } 499 500 /* LSP opcodes */ 501 for (seg = 0, idx = 0; seg <= LSP_OPCD_SEGS; seg++) 502 { 503 lsp_opcd_indices[seg] = idx; 504 for (; idx < lsp_num_opcodes; idx++) 505 if (seg < LSP_OP_TO_SEG (lsp_opcodes[idx].opcode)) 506 break; 507 } 508 509 /* SPE2 opcodes */ 510 for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++) 511 { 512 spe2_opcd_indices[seg] = idx; 513 for (; idx < spe2_num_opcodes; idx++) 514 { 515 op = SPE2_XOP (spe2_opcodes[idx].opcode); 516 if (seg < SPE2_XOP_TO_SEG (op)) 517 break; 518 } 519 } 520 } 521 522 powerpc_init_dialect (info); 523 if (info->private_data != NULL) 524 { 525 private_data (info)->special[0].name = ".got"; 526 private_data (info)->special[1].name = ".plt"; 527 } 528 } 529 530 /* Print a big endian PowerPC instruction. */ 531 532 int 533 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info) 534 { 535 return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info)); 536 } 537 538 /* Print a little endian PowerPC instruction. */ 539 540 int 541 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info) 542 { 543 return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info)); 544 } 545 546 /* Extract the operand value from the PowerPC or POWER instruction. */ 547 548 static int64_t 549 operand_value_powerpc (const struct powerpc_operand *operand, 550 uint64_t insn, ppc_cpu_t dialect) 551 { 552 int64_t value; 553 int invalid = 0; 554 /* Extract the value from the instruction. */ 555 if (operand->extract) 556 value = (*operand->extract) (insn, dialect, &invalid); 557 else 558 { 559 if (operand->shift >= 0) 560 value = (insn >> operand->shift) & operand->bitm; 561 else 562 value = (insn << -operand->shift) & operand->bitm; 563 if ((operand->flags & PPC_OPERAND_SIGNED) != 0) 564 { 565 /* BITM is always some number of zeros followed by some 566 number of ones, followed by some number of zeros. */ 567 uint64_t top = operand->bitm; 568 /* top & -top gives the rightmost 1 bit, so this 569 fills in any trailing zeros. */ 570 top |= (top & -top) - 1; 571 top &= ~(top >> 1); 572 value = (value ^ top) - top; 573 } 574 } 575 576 if ((operand->flags & PPC_OPERAND_NONZERO) != 0) 577 ++value; 578 579 return value; 580 } 581 582 /* Determine whether the optional operand(s) should be printed. */ 583 584 static bool 585 skip_optional_operands (const ppc_opindex_t *opindex, 586 uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel) 587 { 588 const struct powerpc_operand *operand; 589 int num_optional; 590 591 for (num_optional = 0; *opindex != 0; opindex++) 592 { 593 operand = &powerpc_operands[*opindex]; 594 if ((operand->flags & PPC_OPERAND_NEXT) != 0) 595 return false; 596 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) 597 { 598 int64_t value = operand_value_powerpc (operand, insn, dialect); 599 600 if (operand->shift == 52) 601 *is_pcrel = value != 0; 602 603 /* Negative count is used as a flag to extract function. */ 604 --num_optional; 605 if (value != ppc_optional_operand_value (operand, insn, dialect, 606 num_optional)) 607 return false; 608 } 609 } 610 611 return true; 612 } 613 614 /* Find a match for INSN in the opcode table, given machine DIALECT. */ 615 616 static const struct powerpc_opcode * 617 lookup_powerpc (uint64_t insn, ppc_cpu_t dialect) 618 { 619 const struct powerpc_opcode *opcode, *opcode_end; 620 unsigned long op; 621 622 /* Get the major opcode of the instruction. */ 623 op = PPC_OP (insn); 624 625 /* Find the first match in the opcode table for this major opcode. */ 626 opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1]; 627 for (opcode = powerpc_opcodes + powerpc_opcd_indices[op]; 628 opcode < opcode_end; 629 ++opcode) 630 { 631 const ppc_opindex_t *opindex; 632 const struct powerpc_operand *operand; 633 int invalid; 634 635 if ((insn & opcode->mask) != opcode->opcode 636 || ((dialect & PPC_OPCODE_ANY) == 0 637 && ((opcode->flags & dialect) == 0 638 || (opcode->deprecated & dialect) != 0)) 639 || (opcode->deprecated & dialect & PPC_OPCODE_RAW) != 0) 640 continue; 641 642 /* Check validity of operands. */ 643 invalid = 0; 644 for (opindex = opcode->operands; *opindex != 0; opindex++) 645 { 646 operand = powerpc_operands + *opindex; 647 if (operand->extract) 648 (*operand->extract) (insn, dialect, &invalid); 649 } 650 if (invalid) 651 continue; 652 653 return opcode; 654 } 655 656 return NULL; 657 } 658 659 /* Find a match for INSN in the PREFIX opcode table. */ 660 661 static const struct powerpc_opcode * 662 lookup_prefix (uint64_t insn, ppc_cpu_t dialect) 663 { 664 const struct powerpc_opcode *opcode, *opcode_end; 665 unsigned long seg; 666 667 /* Get the opcode segment of the instruction. */ 668 seg = PPC_PREFIX_SEG (insn); 669 670 /* Find the first match in the opcode table for this major opcode. */ 671 opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1]; 672 for (opcode = prefix_opcodes + prefix_opcd_indices[seg]; 673 opcode < opcode_end; 674 ++opcode) 675 { 676 const ppc_opindex_t *opindex; 677 const struct powerpc_operand *operand; 678 int invalid; 679 680 if ((insn & opcode->mask) != opcode->opcode 681 || ((dialect & PPC_OPCODE_ANY) == 0 682 && (opcode->flags & dialect) == 0) 683 || (opcode->deprecated & dialect) != 0) 684 continue; 685 686 /* Check validity of operands. */ 687 invalid = 0; 688 for (opindex = opcode->operands; *opindex != 0; opindex++) 689 { 690 operand = powerpc_operands + *opindex; 691 if (operand->extract) 692 (*operand->extract) (insn, dialect, &invalid); 693 } 694 if (invalid) 695 continue; 696 697 return opcode; 698 } 699 700 return NULL; 701 } 702 703 /* Find a match for INSN in the VLE opcode table. */ 704 705 static const struct powerpc_opcode * 706 lookup_vle (uint64_t insn, ppc_cpu_t dialect) 707 { 708 const struct powerpc_opcode *opcode; 709 const struct powerpc_opcode *opcode_end; 710 unsigned op, seg; 711 712 op = PPC_OP (insn); 713 if (op >= 0x20 && op <= 0x37) 714 { 715 /* This insn has a 4-bit opcode. */ 716 op &= 0x3c; 717 } 718 seg = VLE_OP_TO_SEG (op); 719 720 /* Find the first match in the opcode table for this major opcode. */ 721 opcode_end = vle_opcodes + vle_opcd_indices[seg + 1]; 722 for (opcode = vle_opcodes + vle_opcd_indices[seg]; 723 opcode < opcode_end; 724 ++opcode) 725 { 726 uint64_t table_opcd = opcode->opcode; 727 uint64_t table_mask = opcode->mask; 728 bool table_op_is_short = PPC_OP_SE_VLE(table_mask); 729 uint64_t insn2; 730 const ppc_opindex_t *opindex; 731 const struct powerpc_operand *operand; 732 int invalid; 733 734 insn2 = insn; 735 if (table_op_is_short) 736 insn2 >>= 16; 737 if ((insn2 & table_mask) != table_opcd 738 || (opcode->deprecated & dialect) != 0) 739 continue; 740 741 /* Check validity of operands. */ 742 invalid = 0; 743 for (opindex = opcode->operands; *opindex != 0; ++opindex) 744 { 745 operand = powerpc_operands + *opindex; 746 if (operand->extract) 747 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid); 748 } 749 if (invalid) 750 continue; 751 752 return opcode; 753 } 754 755 return NULL; 756 } 757 758 /* Find a match for INSN in the LSP opcode table. */ 759 760 static const struct powerpc_opcode * 761 lookup_lsp (uint64_t insn, ppc_cpu_t dialect) 762 { 763 const struct powerpc_opcode *opcode, *opcode_end; 764 unsigned op, seg; 765 766 op = PPC_OP (insn); 767 if (op != 0x4) 768 return NULL; 769 770 seg = LSP_OP_TO_SEG (insn); 771 772 /* Find the first match in the opcode table for this opcode. */ 773 opcode_end = lsp_opcodes + lsp_opcd_indices[seg + 1]; 774 for (opcode = lsp_opcodes + lsp_opcd_indices[seg]; 775 opcode < opcode_end; 776 ++opcode) 777 { 778 const ppc_opindex_t *opindex; 779 const struct powerpc_operand *operand; 780 int invalid; 781 782 if ((insn & opcode->mask) != opcode->opcode 783 || (opcode->deprecated & dialect) != 0) 784 continue; 785 786 /* Check validity of operands. */ 787 invalid = 0; 788 for (opindex = opcode->operands; *opindex != 0; ++opindex) 789 { 790 operand = powerpc_operands + *opindex; 791 if (operand->extract) 792 (*operand->extract) (insn, (ppc_cpu_t) 0, &invalid); 793 } 794 if (invalid) 795 continue; 796 797 return opcode; 798 } 799 800 return NULL; 801 } 802 803 /* Find a match for INSN in the SPE2 opcode table. */ 804 805 static const struct powerpc_opcode * 806 lookup_spe2 (uint64_t insn, ppc_cpu_t dialect) 807 { 808 const struct powerpc_opcode *opcode, *opcode_end; 809 unsigned op, xop, seg; 810 811 op = PPC_OP (insn); 812 if (op != 0x4) 813 { 814 /* This is not SPE2 insn. 815 * All SPE2 instructions have OP=4 and differs by XOP */ 816 return NULL; 817 } 818 xop = SPE2_XOP (insn); 819 seg = SPE2_XOP_TO_SEG (xop); 820 821 /* Find the first match in the opcode table for this opcode. */ 822 opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1]; 823 for (opcode = spe2_opcodes + spe2_opcd_indices[seg]; 824 opcode < opcode_end; 825 ++opcode) 826 { 827 uint64_t table_opcd = opcode->opcode; 828 uint64_t table_mask = opcode->mask; 829 uint64_t insn2; 830 const ppc_opindex_t *opindex; 831 const struct powerpc_operand *operand; 832 int invalid; 833 834 insn2 = insn; 835 if ((insn2 & table_mask) != table_opcd 836 || (opcode->deprecated & dialect) != 0) 837 continue; 838 839 /* Check validity of operands. */ 840 invalid = 0; 841 for (opindex = opcode->operands; *opindex != 0; ++opindex) 842 { 843 operand = powerpc_operands + *opindex; 844 if (operand->extract) 845 (*operand->extract) (insn, (ppc_cpu_t)0, &invalid); 846 } 847 if (invalid) 848 continue; 849 850 return opcode; 851 } 852 853 return NULL; 854 } 855 856 static arelent * 857 bsearch_reloc (arelent **lo, arelent **hi, bfd_vma vma) 858 { 859 while (lo < hi) 860 { 861 arelent **mid = lo + (hi - lo) / 2; 862 arelent *rel = *mid; 863 864 if (vma < rel->address) 865 hi = mid; 866 else if (vma > rel->address) 867 lo = mid + 1; 868 else 869 return rel; 870 } 871 return NULL; 872 } 873 874 static bool 875 print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info) 876 { 877 if (sb->name != NULL) 878 { 879 asection *s = sb->sec; 880 if (s == NULL) 881 { 882 s = bfd_get_section_by_name (info->section->owner, sb->name); 883 sb->sec = s; 884 if (s == NULL) 885 sb->name = NULL; 886 } 887 if (s != NULL 888 && vma >= s->vma 889 && vma < s->vma + s->size) 890 { 891 asymbol *sym = NULL; 892 uint64_t ent = 0; 893 if (info->dynrelcount > 0) 894 { 895 arelent **lo = info->dynrelbuf; 896 arelent **hi = lo + info->dynrelcount; 897 arelent *rel = bsearch_reloc (lo, hi, vma); 898 if (rel != NULL && rel->sym_ptr_ptr != NULL) 899 sym = *rel->sym_ptr_ptr; 900 } 901 if (sym == NULL && (s->flags & SEC_HAS_CONTENTS) != 0) 902 { 903 if (sb->buf == NULL 904 && !bfd_malloc_and_get_section (s->owner, s, &sb->buf)) 905 sb->name = NULL; 906 if (sb->buf != NULL) 907 { 908 ent = bfd_get_64 (s->owner, sb->buf + (vma - s->vma)); 909 if (ent != 0) 910 sym = (*info->symbol_at_address_func) (ent, info); 911 } 912 } 913 (*info->fprintf_styled_func) (info->stream, dis_style_text, " ["); 914 if (sym != NULL) 915 { 916 (*info->fprintf_styled_func) (info->stream, dis_style_symbol, 917 "%s", bfd_asymbol_name (sym)); 918 (*info->fprintf_styled_func) (info->stream, dis_style_text, "@"); 919 (*info->fprintf_styled_func) (info->stream, dis_style_symbol, 920 "%s", sb->name + 1); 921 } 922 else 923 { 924 (*info->fprintf_styled_func) (info->stream, dis_style_address, 925 "%" PRIx64, ent); 926 (*info->fprintf_styled_func) (info->stream, dis_style_text, "@"); 927 (*info->fprintf_styled_func) (info->stream, dis_style_symbol, 928 "%s", sb->name + 1); 929 } 930 (*info->fprintf_styled_func) (info->stream, dis_style_text, "]"); 931 return true; 932 } 933 } 934 return false; 935 } 936 937 /* Print a PowerPC or POWER instruction. */ 938 939 static int 940 print_insn_powerpc (bfd_vma memaddr, 941 struct disassemble_info *info, 942 int bigendian, 943 ppc_cpu_t dialect) 944 { 945 bfd_byte buffer[4]; 946 int status; 947 uint64_t insn; 948 const struct powerpc_opcode *opcode; 949 int insn_length = 4; /* Assume we have a normal 4-byte instruction. */ 950 951 status = (*info->read_memory_func) (memaddr, buffer, 4, info); 952 953 /* The final instruction may be a 2-byte VLE insn. */ 954 if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0) 955 { 956 /* Clear buffer so unused bytes will not have garbage in them. */ 957 buffer[2] = buffer[3] = 0; 958 status = (*info->read_memory_func) (memaddr, buffer, 2, info); 959 insn_length = 2; 960 } 961 962 if (status != 0) 963 { 964 (*info->memory_error_func) (status, memaddr, info); 965 return -1; 966 } 967 968 if (bigendian) 969 insn = bfd_getb32 (buffer); 970 else 971 insn = bfd_getl32 (buffer); 972 973 /* Get the major opcode of the insn. */ 974 opcode = NULL; 975 if ((dialect & PPC_OPCODE_POWER10) != 0 976 && PPC_OP (insn) == 0x1) 977 { 978 uint64_t temp_insn, suffix; 979 status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info); 980 if (status == 0) 981 { 982 if (bigendian) 983 suffix = bfd_getb32 (buffer); 984 else 985 suffix = bfd_getl32 (buffer); 986 temp_insn = (insn << 32) | suffix; 987 opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY); 988 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0) 989 opcode = lookup_prefix (temp_insn, dialect); 990 if (opcode != NULL) 991 { 992 insn = temp_insn; 993 insn_length = 8; 994 if ((info->flags & WIDE_OUTPUT) != 0) 995 info->bytes_per_line = 8; 996 } 997 } 998 } 999 if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0) 1000 { 1001 opcode = lookup_vle (insn, dialect); 1002 if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask)) 1003 { 1004 /* The operands will be fetched out of the 16-bit instruction. */ 1005 insn >>= 16; 1006 insn_length = 2; 1007 } 1008 } 1009 if (opcode == NULL && insn_length == 4) 1010 { 1011 if ((dialect & PPC_OPCODE_LSP) != 0) 1012 opcode = lookup_lsp (insn, dialect); 1013 if ((dialect & PPC_OPCODE_SPE2) != 0) 1014 opcode = lookup_spe2 (insn, dialect); 1015 if (opcode == NULL) 1016 opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY); 1017 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0) 1018 opcode = lookup_powerpc (insn, dialect); 1019 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0) 1020 opcode = lookup_spe2 (insn, dialect); 1021 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0) 1022 opcode = lookup_lsp (insn, dialect); 1023 } 1024 1025 if (opcode != NULL) 1026 { 1027 const ppc_opindex_t *opindex; 1028 const struct powerpc_operand *operand; 1029 enum { 1030 need_comma = 0, 1031 need_1space = 1, 1032 need_2spaces = 2, 1033 need_3spaces = 3, 1034 need_4spaces = 4, 1035 need_5spaces = 5, 1036 need_6spaces = 6, 1037 need_7spaces = 7, 1038 need_paren 1039 } op_separator; 1040 bool skip_optional; 1041 bool is_pcrel; 1042 uint64_t d34; 1043 int blanks; 1044 1045 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, 1046 "%s", opcode->name); 1047 /* gdb fprintf_styled_func doesn't return count printed. */ 1048 blanks = 8 - strlen (opcode->name); 1049 if (blanks <= 0) 1050 blanks = 1; 1051 1052 /* Now extract and print the operands. */ 1053 op_separator = blanks; 1054 skip_optional = false; 1055 is_pcrel = false; 1056 d34 = 0; 1057 for (opindex = opcode->operands; *opindex != 0; opindex++) 1058 { 1059 int64_t value; 1060 1061 operand = powerpc_operands + *opindex; 1062 1063 /* If all of the optional operands past this one have their 1064 default value, then don't print any of them. Except in 1065 raw mode, print them all. */ 1066 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 1067 && (dialect & PPC_OPCODE_RAW) == 0) 1068 { 1069 if (!skip_optional) 1070 skip_optional = skip_optional_operands (opindex, insn, 1071 dialect, &is_pcrel); 1072 if (skip_optional) 1073 continue; 1074 } 1075 1076 value = operand_value_powerpc (operand, insn, dialect); 1077 1078 if (op_separator == need_comma) 1079 (*info->fprintf_styled_func) (info->stream, dis_style_text, ","); 1080 else if (op_separator == need_paren) 1081 (*info->fprintf_styled_func) (info->stream, dis_style_text, "("); 1082 else 1083 (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s", 1084 op_separator, " "); 1085 1086 /* Print the operand as directed by the flags. */ 1087 if ((operand->flags & PPC_OPERAND_GPR) != 0 1088 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) 1089 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1090 "r%" PRId64, value); 1091 else if ((operand->flags & PPC_OPERAND_FPR) != 0) 1092 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1093 "f%" PRId64, value); 1094 else if ((operand->flags & PPC_OPERAND_VR) != 0) 1095 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1096 "v%" PRId64, value); 1097 else if ((operand->flags & PPC_OPERAND_VSR) != 0) 1098 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1099 "vs%" PRId64, value); 1100 else if ((operand->flags & PPC_OPERAND_DMR) != 0) 1101 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1102 "dm%" PRId64, value); 1103 else if ((operand->flags & PPC_OPERAND_ACC) != 0) 1104 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1105 "a%" PRId64, value); 1106 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) 1107 (*info->print_address_func) (memaddr + value, info); 1108 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) 1109 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); 1110 else if ((operand->flags & PPC_OPERAND_FSL) != 0) 1111 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1112 "fsl%" PRId64, value); 1113 else if ((operand->flags & PPC_OPERAND_FCR) != 0) 1114 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1115 "fcr%" PRId64, value); 1116 else if ((operand->flags & PPC_OPERAND_UDI) != 0) 1117 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1118 "%" PRId64, value); 1119 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0 1120 && (operand->flags & PPC_OPERAND_CR_BIT) == 0 1121 && (((dialect & PPC_OPCODE_PPC) != 0) 1122 || ((dialect & PPC_OPCODE_VLE) != 0))) 1123 (*info->fprintf_styled_func) (info->stream, dis_style_register, 1124 "cr%" PRId64, value); 1125 else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0 1126 && (operand->flags & PPC_OPERAND_CR_REG) == 0 1127 && (((dialect & PPC_OPCODE_PPC) != 0) 1128 || ((dialect & PPC_OPCODE_VLE) != 0))) 1129 { 1130 static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; 1131 int cr; 1132 int cc; 1133 1134 cr = value >> 2; 1135 cc = value & 3; 1136 if (cr != 0) 1137 { 1138 (*info->fprintf_styled_func) (info->stream, dis_style_text, 1139 "4*"); 1140 (*info->fprintf_styled_func) (info->stream, 1141 dis_style_register, 1142 "cr%d", cr); 1143 (*info->fprintf_styled_func) (info->stream, dis_style_text, 1144 "+"); 1145 } 1146 1147 (*info->fprintf_styled_func) (info->stream, 1148 dis_style_sub_mnemonic, 1149 "%s", cbnames[cc]); 1150 } 1151 else 1152 { 1153 /* An immediate, but what style? */ 1154 enum disassembler_style style; 1155 1156 if ((operand->flags & PPC_OPERAND_PARENS) != 0) 1157 style = dis_style_address_offset; 1158 else 1159 style = dis_style_immediate; 1160 1161 (*info->fprintf_styled_func) (info->stream, style, 1162 "%" PRId64, value); 1163 } 1164 1165 if (operand->shift == 52) 1166 is_pcrel = value != 0; 1167 else if (operand->bitm == UINT64_C (0x3ffffffff)) 1168 d34 = value; 1169 1170 if (op_separator == need_paren) 1171 (*info->fprintf_styled_func) (info->stream, dis_style_text, ")"); 1172 1173 op_separator = need_comma; 1174 if ((operand->flags & PPC_OPERAND_PARENS) != 0) 1175 op_separator = need_paren; 1176 } 1177 1178 if (is_pcrel) 1179 { 1180 d34 += memaddr; 1181 (*info->fprintf_styled_func) (info->stream, 1182 dis_style_comment_start, 1183 "\t# %" PRIx64, d34); 1184 asymbol *sym = (*info->symbol_at_address_func) (d34, info); 1185 if (sym) 1186 (*info->fprintf_styled_func) (info->stream, dis_style_text, 1187 " <%s>", bfd_asymbol_name (sym)); 1188 1189 if (info->private_data != NULL 1190 && info->section != NULL 1191 && info->section->owner != NULL 1192 && (bfd_get_file_flags (info->section->owner) 1193 & (EXEC_P | DYNAMIC)) != 0 1194 && ((insn & ((-1ULL << 50) | (0x3fULL << 26))) 1195 == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */)) 1196 { 1197 for (int i = 0; i < 2; i++) 1198 if (print_got_plt (private_data (info)->special + i, d34, info)) 1199 break; 1200 } 1201 } 1202 1203 /* We have found and printed an instruction. */ 1204 return insn_length; 1205 } 1206 1207 /* We could not find a match. */ 1208 if (insn_length == 4) 1209 (*info->fprintf_styled_func) (info->stream, 1210 dis_style_assembler_directive, ".long"); 1211 else 1212 { 1213 (*info->fprintf_styled_func) (info->stream, 1214 dis_style_assembler_directive, ".word"); 1215 insn >>= 16; 1216 } 1217 (*info->fprintf_styled_func) (info->stream, dis_style_text, " "); 1218 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x", 1219 (unsigned int) insn); 1220 1221 1222 return insn_length; 1223 } 1224 1225 const disasm_options_and_args_t * 1226 disassembler_options_powerpc (void) 1227 { 1228 static disasm_options_and_args_t *opts_and_args; 1229 1230 if (opts_and_args == NULL) 1231 { 1232 size_t i, num_options = ARRAY_SIZE (ppc_opts); 1233 disasm_options_t *opts; 1234 1235 opts_and_args = XNEW (disasm_options_and_args_t); 1236 opts_and_args->args = NULL; 1237 1238 opts = &opts_and_args->options; 1239 opts->name = XNEWVEC (const char *, num_options + 1); 1240 opts->description = NULL; 1241 opts->arg = NULL; 1242 for (i = 0; i < num_options; i++) 1243 opts->name[i] = ppc_opts[i].opt; 1244 /* The array we return must be NULL terminated. */ 1245 opts->name[i] = NULL; 1246 } 1247 1248 return opts_and_args; 1249 } 1250 1251 void 1252 print_ppc_disassembler_options (FILE *stream) 1253 { 1254 unsigned int i, col; 1255 1256 fprintf (stream, _("\n\ 1257 The following PPC specific disassembler options are supported for use with\n\ 1258 the -M switch:\n")); 1259 1260 for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++) 1261 { 1262 col += fprintf (stream, " %s,", ppc_opts[i].opt); 1263 if (col > 66) 1264 { 1265 fprintf (stream, "\n"); 1266 col = 0; 1267 } 1268 } 1269 fprintf (stream, "\n"); 1270 } 1271