1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* ppc-dis.c -- Disassemble PowerPC instructions 3 Copyright (C) 1994-2016 Free Software Foundation, Inc. 4 Written by Ian Lance Taylor, Cygnus Support 5 6 This file is part of GDB, GAS, and the GNU binutils. 7 8 */ 9 10 #include <asm/cputable.h> 11 #include <asm/cpu_has_feature.h> 12 #include "nonstdio.h" 13 #include "ansidecl.h" 14 #include "ppc.h" 15 #include "dis-asm.h" 16 17 /* This file provides several disassembler functions, all of which use 18 the disassembler interface defined in dis-asm.h. Several functions 19 are provided because this file handles disassembly for the PowerPC 20 in both big and little endian mode and also for the POWER (RS/6000) 21 chip. */ 22 23 /* Extract the operand value from the PowerPC or POWER instruction. */ 24 25 static long 26 operand_value_powerpc (const struct powerpc_operand *operand, 27 unsigned long insn, ppc_cpu_t dialect) 28 { 29 long value; 30 int invalid; 31 /* Extract the value from the instruction. */ 32 if (operand->extract) 33 value = (*operand->extract) (insn, dialect, &invalid); 34 else 35 { 36 if (operand->shift >= 0) 37 value = (insn >> operand->shift) & operand->bitm; 38 else 39 value = (insn << -operand->shift) & operand->bitm; 40 if ((operand->flags & PPC_OPERAND_SIGNED) != 0) 41 { 42 /* BITM is always some number of zeros followed by some 43 number of ones, followed by some number of zeros. */ 44 unsigned long top = operand->bitm; 45 /* top & -top gives the rightmost 1 bit, so this 46 fills in any trailing zeros. */ 47 top |= (top & -top) - 1; 48 top &= ~(top >> 1); 49 value = (value ^ top) - top; 50 } 51 } 52 53 return value; 54 } 55 56 /* Determine whether the optional operand(s) should be printed. */ 57 58 static int 59 skip_optional_operands (const unsigned char *opindex, 60 unsigned long insn, ppc_cpu_t dialect) 61 { 62 const struct powerpc_operand *operand; 63 64 for (; *opindex != 0; opindex++) 65 { 66 operand = &powerpc_operands[*opindex]; 67 if ((operand->flags & PPC_OPERAND_NEXT) != 0 68 || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 69 && operand_value_powerpc (operand, insn, dialect) != 70 ppc_optional_operand_value (operand))) 71 return 0; 72 } 73 74 return 1; 75 } 76 77 /* Find a match for INSN in the opcode table, given machine DIALECT. 78 A DIALECT of -1 is special, matching all machine opcode variations. */ 79 80 static const struct powerpc_opcode * 81 lookup_powerpc (unsigned long insn, ppc_cpu_t dialect) 82 { 83 const struct powerpc_opcode *opcode; 84 const struct powerpc_opcode *opcode_end; 85 86 opcode_end = powerpc_opcodes + powerpc_num_opcodes; 87 /* Find the first match in the opcode table for this major opcode. */ 88 for (opcode = powerpc_opcodes; opcode < opcode_end; ++opcode) 89 { 90 const unsigned char *opindex; 91 const struct powerpc_operand *operand; 92 int invalid; 93 94 if ((insn & opcode->mask) != opcode->opcode 95 || (dialect != (ppc_cpu_t) -1 96 && ((opcode->flags & dialect) == 0 97 || (opcode->deprecated & dialect) != 0))) 98 continue; 99 100 /* Check validity of operands. */ 101 invalid = 0; 102 for (opindex = opcode->operands; *opindex != 0; opindex++) 103 { 104 operand = powerpc_operands + *opindex; 105 if (operand->extract) 106 (*operand->extract) (insn, dialect, &invalid); 107 } 108 if (invalid) 109 continue; 110 111 return opcode; 112 } 113 114 return NULL; 115 } 116 117 /* Print a PowerPC or POWER instruction. */ 118 119 int print_insn_powerpc (unsigned long insn, unsigned long memaddr) 120 { 121 const struct powerpc_opcode *opcode; 122 bool insn_is_short; 123 ppc_cpu_t dialect; 124 125 dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON; 126 127 if (IS_ENABLED(CONFIG_PPC64)) 128 dialect |= PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | 129 PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | 130 PPC_OPCODE_POWER9; 131 132 if (cpu_has_feature(CPU_FTR_TM)) 133 dialect |= PPC_OPCODE_HTM; 134 135 if (cpu_has_feature(CPU_FTR_ALTIVEC)) 136 dialect |= PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2; 137 138 if (cpu_has_feature(CPU_FTR_VSX)) 139 dialect |= PPC_OPCODE_VSX | PPC_OPCODE_VSX3; 140 141 /* Get the major opcode of the insn. */ 142 opcode = NULL; 143 insn_is_short = false; 144 145 if (opcode == NULL) 146 opcode = lookup_powerpc (insn, dialect); 147 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0) 148 opcode = lookup_powerpc (insn, (ppc_cpu_t) -1); 149 150 if (opcode != NULL) 151 { 152 const unsigned char *opindex; 153 const struct powerpc_operand *operand; 154 int need_comma; 155 int need_paren; 156 int skip_optional; 157 158 if (opcode->operands[0] != 0) 159 printf("%-7s ", opcode->name); 160 else 161 printf("%s", opcode->name); 162 163 if (insn_is_short) 164 /* The operands will be fetched out of the 16-bit instruction. */ 165 insn >>= 16; 166 167 /* Now extract and print the operands. */ 168 need_comma = 0; 169 need_paren = 0; 170 skip_optional = -1; 171 for (opindex = opcode->operands; *opindex != 0; opindex++) 172 { 173 long value; 174 175 operand = powerpc_operands + *opindex; 176 177 /* Operands that are marked FAKE are simply ignored. We 178 already made sure that the extract function considered 179 the instruction to be valid. */ 180 if ((operand->flags & PPC_OPERAND_FAKE) != 0) 181 continue; 182 183 /* If all of the optional operands have the value zero, 184 then don't print any of them. */ 185 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) 186 { 187 if (skip_optional < 0) 188 skip_optional = skip_optional_operands (opindex, insn, 189 dialect); 190 if (skip_optional) 191 continue; 192 } 193 194 value = operand_value_powerpc (operand, insn, dialect); 195 196 if (need_comma) 197 { 198 printf(","); 199 need_comma = 0; 200 } 201 202 /* Print the operand as directed by the flags. */ 203 if ((operand->flags & PPC_OPERAND_GPR) != 0 204 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) 205 printf("r%ld", value); 206 else if ((operand->flags & PPC_OPERAND_FPR) != 0) 207 printf("f%ld", value); 208 else if ((operand->flags & PPC_OPERAND_VR) != 0) 209 printf("v%ld", value); 210 else if ((operand->flags & PPC_OPERAND_VSR) != 0) 211 printf("vs%ld", value); 212 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) 213 print_address(memaddr + value); 214 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) 215 print_address(value & 0xffffffff); 216 else if ((operand->flags & PPC_OPERAND_FSL) != 0) 217 printf("fsl%ld", value); 218 else if ((operand->flags & PPC_OPERAND_FCR) != 0) 219 printf("fcr%ld", value); 220 else if ((operand->flags & PPC_OPERAND_UDI) != 0) 221 printf("%ld", value); 222 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0 223 && (((dialect & PPC_OPCODE_PPC) != 0) 224 || ((dialect & PPC_OPCODE_VLE) != 0))) 225 printf("cr%ld", value); 226 else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0) 227 && (((dialect & PPC_OPCODE_PPC) != 0) 228 || ((dialect & PPC_OPCODE_VLE) != 0))) 229 { 230 static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; 231 int cr; 232 int cc; 233 234 cr = value >> 2; 235 if (cr != 0) 236 printf("4*cr%d+", cr); 237 cc = value & 3; 238 printf("%s", cbnames[cc]); 239 } 240 else 241 printf("%d", (int) value); 242 243 if (need_paren) 244 { 245 printf(")"); 246 need_paren = 0; 247 } 248 249 if ((operand->flags & PPC_OPERAND_PARENS) == 0) 250 need_comma = 1; 251 else 252 { 253 printf("("); 254 need_paren = 1; 255 } 256 } 257 258 /* We have found and printed an instruction. 259 If it was a short VLE instruction we have more to do. */ 260 if (insn_is_short) 261 { 262 memaddr += 2; 263 return 2; 264 } 265 else 266 /* Otherwise, return. */ 267 return 4; 268 } 269 270 /* We could not find a match. */ 271 printf(".long 0x%lx", insn); 272 273 return 4; 274 } 275