root/arch/powerpc/xmon/ppc-dis.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. operand_value_powerpc
  2. skip_optional_operands
  3. lookup_powerpc
  4. print_insn_powerpc

   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             | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
 127 
 128   if (cpu_has_feature(CPU_FTRS_POWER5))
 129     dialect |= PPC_OPCODE_POWER5;
 130 
 131   if (cpu_has_feature(CPU_FTRS_CELL))
 132     dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC);
 133 
 134   if (cpu_has_feature(CPU_FTRS_POWER6))
 135     dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC);
 136 
 137   if (cpu_has_feature(CPU_FTRS_POWER7))
 138     dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
 139                 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX);
 140 
 141   if (cpu_has_feature(CPU_FTRS_POWER8))
 142     dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
 143                 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
 144                 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX);
 145 
 146   if (cpu_has_feature(CPU_FTRS_POWER9))
 147     dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
 148                 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 | PPC_OPCODE_HTM
 149                 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
 150                 | PPC_OPCODE_VSX | PPC_OPCODE_VSX3);
 151 
 152   /* Get the major opcode of the insn.  */
 153   opcode = NULL;
 154   insn_is_short = false;
 155 
 156   if (opcode == NULL)
 157     opcode = lookup_powerpc (insn, dialect);
 158   if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
 159     opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
 160 
 161   if (opcode != NULL)
 162     {
 163       const unsigned char *opindex;
 164       const struct powerpc_operand *operand;
 165       int need_comma;
 166       int need_paren;
 167       int skip_optional;
 168 
 169       if (opcode->operands[0] != 0)
 170         printf("%-7s ", opcode->name);
 171       else
 172         printf("%s", opcode->name);
 173 
 174       if (insn_is_short)
 175         /* The operands will be fetched out of the 16-bit instruction.  */
 176         insn >>= 16;
 177 
 178       /* Now extract and print the operands.  */
 179       need_comma = 0;
 180       need_paren = 0;
 181       skip_optional = -1;
 182       for (opindex = opcode->operands; *opindex != 0; opindex++)
 183         {
 184           long value;
 185 
 186           operand = powerpc_operands + *opindex;
 187 
 188           /* Operands that are marked FAKE are simply ignored.  We
 189              already made sure that the extract function considered
 190              the instruction to be valid.  */
 191           if ((operand->flags & PPC_OPERAND_FAKE) != 0)
 192             continue;
 193 
 194           /* If all of the optional operands have the value zero,
 195              then don't print any of them.  */
 196           if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
 197             {
 198               if (skip_optional < 0)
 199                 skip_optional = skip_optional_operands (opindex, insn,
 200                                                         dialect);
 201               if (skip_optional)
 202                 continue;
 203             }
 204 
 205           value = operand_value_powerpc (operand, insn, dialect);
 206 
 207           if (need_comma)
 208             {
 209               printf(",");
 210               need_comma = 0;
 211             }
 212 
 213           /* Print the operand as directed by the flags.  */
 214           if ((operand->flags & PPC_OPERAND_GPR) != 0
 215               || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
 216             printf("r%ld", value);
 217           else if ((operand->flags & PPC_OPERAND_FPR) != 0)
 218             printf("f%ld", value);
 219           else if ((operand->flags & PPC_OPERAND_VR) != 0)
 220             printf("v%ld", value);
 221           else if ((operand->flags & PPC_OPERAND_VSR) != 0)
 222             printf("vs%ld", value);
 223           else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
 224             print_address(memaddr + value);
 225           else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
 226             print_address(value & 0xffffffff);
 227           else if ((operand->flags & PPC_OPERAND_FSL) != 0)
 228             printf("fsl%ld", value);
 229           else if ((operand->flags & PPC_OPERAND_FCR) != 0)
 230             printf("fcr%ld", value);
 231           else if ((operand->flags & PPC_OPERAND_UDI) != 0)
 232             printf("%ld", value);
 233           else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
 234                    && (((dialect & PPC_OPCODE_PPC) != 0)
 235                        || ((dialect & PPC_OPCODE_VLE) != 0)))
 236             printf("cr%ld", value);
 237           else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
 238                    && (((dialect & PPC_OPCODE_PPC) != 0)
 239                        || ((dialect & PPC_OPCODE_VLE) != 0)))
 240             {
 241               static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
 242               int cr;
 243               int cc;
 244 
 245               cr = value >> 2;
 246               if (cr != 0)
 247                 printf("4*cr%d+", cr);
 248               cc = value & 3;
 249               printf("%s", cbnames[cc]);
 250             }
 251           else
 252             printf("%d", (int) value);
 253 
 254           if (need_paren)
 255             {
 256               printf(")");
 257               need_paren = 0;
 258             }
 259 
 260           if ((operand->flags & PPC_OPERAND_PARENS) == 0)
 261             need_comma = 1;
 262           else
 263             {
 264               printf("(");
 265               need_paren = 1;
 266             }
 267         }
 268 
 269       /* We have found and printed an instruction.
 270          If it was a short VLE instruction we have more to do.  */
 271       if (insn_is_short)
 272         {
 273           memaddr += 2;
 274           return 2;
 275         }
 276       else
 277         /* Otherwise, return.  */
 278         return 4;
 279     }
 280 
 281   /* We could not find a match.  */
 282   printf(".long 0x%lx", insn);
 283 
 284   return 4;
 285 }

/* [<][>][^][v][top][bottom][index][help] */