0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <asm/cputable.h>
0011 #include <asm/cpu_has_feature.h>
0012 #include "nonstdio.h"
0013 #include "ansidecl.h"
0014 #include "ppc.h"
0015 #include "dis-asm.h"
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 static long
0026 operand_value_powerpc (const struct powerpc_operand *operand,
0027 unsigned long insn, ppc_cpu_t dialect)
0028 {
0029 long value;
0030 int invalid;
0031
0032 if (operand->extract)
0033 value = (*operand->extract) (insn, dialect, &invalid);
0034 else
0035 {
0036 if (operand->shift >= 0)
0037 value = (insn >> operand->shift) & operand->bitm;
0038 else
0039 value = (insn << -operand->shift) & operand->bitm;
0040 if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
0041 {
0042
0043
0044 unsigned long top = operand->bitm;
0045
0046
0047 top |= (top & -top) - 1;
0048 top &= ~(top >> 1);
0049 value = (value ^ top) - top;
0050 }
0051 }
0052
0053 return value;
0054 }
0055
0056
0057
0058 static int
0059 skip_optional_operands (const unsigned char *opindex,
0060 unsigned long insn, ppc_cpu_t dialect)
0061 {
0062 const struct powerpc_operand *operand;
0063
0064 for (; *opindex != 0; opindex++)
0065 {
0066 operand = &powerpc_operands[*opindex];
0067 if ((operand->flags & PPC_OPERAND_NEXT) != 0
0068 || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
0069 && operand_value_powerpc (operand, insn, dialect) !=
0070 ppc_optional_operand_value (operand)))
0071 return 0;
0072 }
0073
0074 return 1;
0075 }
0076
0077
0078
0079
0080 static const struct powerpc_opcode *
0081 lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
0082 {
0083 const struct powerpc_opcode *opcode;
0084 const struct powerpc_opcode *opcode_end;
0085
0086 opcode_end = powerpc_opcodes + powerpc_num_opcodes;
0087
0088 for (opcode = powerpc_opcodes; opcode < opcode_end; ++opcode)
0089 {
0090 const unsigned char *opindex;
0091 const struct powerpc_operand *operand;
0092 int invalid;
0093
0094 if ((insn & opcode->mask) != opcode->opcode
0095 || (dialect != (ppc_cpu_t) -1
0096 && ((opcode->flags & dialect) == 0
0097 || (opcode->deprecated & dialect) != 0)))
0098 continue;
0099
0100
0101 invalid = 0;
0102 for (opindex = opcode->operands; *opindex != 0; opindex++)
0103 {
0104 operand = powerpc_operands + *opindex;
0105 if (operand->extract)
0106 (*operand->extract) (insn, dialect, &invalid);
0107 }
0108 if (invalid)
0109 continue;
0110
0111 return opcode;
0112 }
0113
0114 return NULL;
0115 }
0116
0117
0118
0119 int print_insn_powerpc (unsigned long insn, unsigned long memaddr)
0120 {
0121 const struct powerpc_opcode *opcode;
0122 bool insn_is_short;
0123 ppc_cpu_t dialect;
0124
0125 dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON
0126 | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
0127
0128 if (cpu_has_feature(CPU_FTRS_POWER5))
0129 dialect |= PPC_OPCODE_POWER5;
0130
0131 if (cpu_has_feature(CPU_FTRS_CELL))
0132 dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC);
0133
0134 if (cpu_has_feature(CPU_FTRS_POWER6))
0135 dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC);
0136
0137 if (cpu_has_feature(CPU_FTRS_POWER7))
0138 dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
0139 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX);
0140
0141 if (cpu_has_feature(CPU_FTRS_POWER8))
0142 dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
0143 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
0144 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX);
0145
0146 if (cpu_has_feature(CPU_FTRS_POWER9))
0147 dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
0148 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 | PPC_OPCODE_HTM
0149 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
0150 | PPC_OPCODE_VSX | PPC_OPCODE_VSX3);
0151
0152
0153 opcode = NULL;
0154 insn_is_short = false;
0155
0156 if (opcode == NULL)
0157 opcode = lookup_powerpc (insn, dialect);
0158 if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
0159 opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
0160
0161 if (opcode != NULL)
0162 {
0163 const unsigned char *opindex;
0164 const struct powerpc_operand *operand;
0165 int need_comma;
0166 int need_paren;
0167 int skip_optional;
0168
0169 if (opcode->operands[0] != 0)
0170 printf("%-7s ", opcode->name);
0171 else
0172 printf("%s", opcode->name);
0173
0174 if (insn_is_short)
0175
0176 insn >>= 16;
0177
0178
0179 need_comma = 0;
0180 need_paren = 0;
0181 skip_optional = -1;
0182 for (opindex = opcode->operands; *opindex != 0; opindex++)
0183 {
0184 long value;
0185
0186 operand = powerpc_operands + *opindex;
0187
0188
0189
0190
0191 if ((operand->flags & PPC_OPERAND_FAKE) != 0)
0192 continue;
0193
0194
0195
0196 if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
0197 {
0198 if (skip_optional < 0)
0199 skip_optional = skip_optional_operands (opindex, insn,
0200 dialect);
0201 if (skip_optional)
0202 continue;
0203 }
0204
0205 value = operand_value_powerpc (operand, insn, dialect);
0206
0207 if (need_comma)
0208 {
0209 printf(",");
0210 need_comma = 0;
0211 }
0212
0213
0214 if ((operand->flags & PPC_OPERAND_GPR) != 0
0215 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
0216 printf("r%ld", value);
0217 else if ((operand->flags & PPC_OPERAND_FPR) != 0)
0218 printf("f%ld", value);
0219 else if ((operand->flags & PPC_OPERAND_VR) != 0)
0220 printf("v%ld", value);
0221 else if ((operand->flags & PPC_OPERAND_VSR) != 0)
0222 printf("vs%ld", value);
0223 else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
0224 print_address(memaddr + value);
0225 else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
0226 print_address(value & 0xffffffff);
0227 else if ((operand->flags & PPC_OPERAND_FSL) != 0)
0228 printf("fsl%ld", value);
0229 else if ((operand->flags & PPC_OPERAND_FCR) != 0)
0230 printf("fcr%ld", value);
0231 else if ((operand->flags & PPC_OPERAND_UDI) != 0)
0232 printf("%ld", value);
0233 else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
0234 && (((dialect & PPC_OPCODE_PPC) != 0)
0235 || ((dialect & PPC_OPCODE_VLE) != 0)))
0236 printf("cr%ld", value);
0237 else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
0238 && (((dialect & PPC_OPCODE_PPC) != 0)
0239 || ((dialect & PPC_OPCODE_VLE) != 0)))
0240 {
0241 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
0242 int cr;
0243 int cc;
0244
0245 cr = value >> 2;
0246 if (cr != 0)
0247 printf("4*cr%d+", cr);
0248 cc = value & 3;
0249 printf("%s", cbnames[cc]);
0250 }
0251 else
0252 printf("%d", (int) value);
0253
0254 if (need_paren)
0255 {
0256 printf(")");
0257 need_paren = 0;
0258 }
0259
0260 if ((operand->flags & PPC_OPERAND_PARENS) == 0)
0261 need_comma = 1;
0262 else
0263 {
0264 printf("(");
0265 need_paren = 1;
0266 }
0267 }
0268
0269
0270
0271 if (insn_is_short)
0272 {
0273 memaddr += 2;
0274 return 2;
0275 }
0276 else
0277
0278 return 4;
0279 }
0280
0281
0282 printf(".long 0x%lx", insn);
0283
0284 return 4;
0285 }