Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* ppc-dis.c -- Disassemble PowerPC instructions
0003    Copyright (C) 1994-2016 Free Software Foundation, Inc.
0004    Written by Ian Lance Taylor, Cygnus Support
0005 
0006 This file is part of GDB, GAS, and the GNU binutils.
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 /* This file provides several disassembler functions, all of which use
0018    the disassembler interface defined in dis-asm.h.  Several functions
0019    are provided because this file handles disassembly for the PowerPC
0020    in both big and little endian mode and also for the POWER (RS/6000)
0021    chip.  */
0022 
0023 /* Extract the operand value from the PowerPC or POWER instruction.  */
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   /* Extract the value from the instruction.  */
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       /* BITM is always some number of zeros followed by some
0043          number of ones, followed by some number of zeros.  */
0044       unsigned long top = operand->bitm;
0045       /* top & -top gives the rightmost 1 bit, so this
0046          fills in any trailing zeros.  */
0047       top |= (top & -top) - 1;
0048       top &= ~(top >> 1);
0049       value = (value ^ top) - top;
0050     }
0051     }
0052 
0053   return value;
0054 }
0055 
0056 /* Determine whether the optional operand(s) should be printed.  */
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 /* Find a match for INSN in the opcode table, given machine DIALECT.
0078    A DIALECT of -1 is special, matching all machine opcode variations.  */
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   /* Find the first match in the opcode table for this major opcode.  */
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       /* Check validity of operands.  */
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 /* Print a PowerPC or POWER instruction.  */
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   /* Get the major opcode of the insn.  */
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         /* The operands will be fetched out of the 16-bit instruction.  */
0176         insn >>= 16;
0177 
0178       /* Now extract and print the operands.  */
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       /* Operands that are marked FAKE are simply ignored.  We
0189          already made sure that the extract function considered
0190          the instruction to be valid.  */
0191       if ((operand->flags & PPC_OPERAND_FAKE) != 0)
0192         continue;
0193 
0194       /* If all of the optional operands have the value zero,
0195          then don't print any of them.  */
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       /* Print the operand as directed by the flags.  */
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       /* We have found and printed an instruction.
0270          If it was a short VLE instruction we have more to do.  */
0271       if (insn_is_short)
0272         {
0273           memaddr += 2;
0274           return 2;
0275         }
0276       else
0277         /* Otherwise, return.  */
0278         return 4;
0279     }
0280 
0281   /* We could not find a match.  */
0282   printf(".long 0x%lx", insn);
0283 
0284   return 4;
0285 }