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

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

DEFINITIONS

This source file includes following definitions.
  1. init_spu_disassemble
  2. get_index_for_opcode
  3. print_insn_spu

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* Disassemble SPU instructions
   3 
   4    Copyright 2006 Free Software Foundation, Inc.
   5 
   6    This file is part of GDB, GAS, and the GNU binutils.
   7 
   8  */
   9 
  10 #include <linux/string.h>
  11 #include "nonstdio.h"
  12 #include "ansidecl.h"
  13 #include "spu.h"
  14 #include "dis-asm.h"
  15 
  16 /* This file provides a disassembler function which uses
  17    the disassembler interface defined in dis-asm.h.   */
  18 
  19 extern const struct spu_opcode spu_opcodes[];
  20 extern const int spu_num_opcodes;
  21 
  22 #define SPU_DISASM_TBL_SIZE (1 << 11)
  23 static const struct spu_opcode *spu_disassemble_table[SPU_DISASM_TBL_SIZE];
  24 
  25 static void
  26 init_spu_disassemble (void)
  27 {
  28   int i;
  29 
  30   /* If two instructions have the same opcode then we prefer the first
  31    * one.  In most cases it is just an alternate mnemonic. */
  32   for (i = 0; i < spu_num_opcodes; i++)
  33     {
  34       int o = spu_opcodes[i].opcode;
  35       if (o >= SPU_DISASM_TBL_SIZE)
  36         continue; /* abort (); */
  37       if (spu_disassemble_table[o] == 0)
  38         spu_disassemble_table[o] = &spu_opcodes[i];
  39     }
  40 }
  41 
  42 /* Determine the instruction from the 10 least significant bits. */
  43 static const struct spu_opcode *
  44 get_index_for_opcode (unsigned int insn)
  45 {
  46   const struct spu_opcode *index;
  47   unsigned int opcode = insn >> (32-11);
  48 
  49   /* Init the table.  This assumes that element 0/opcode 0 (currently
  50    * NOP) is always used */
  51   if (spu_disassemble_table[0] == 0)
  52     init_spu_disassemble ();
  53 
  54   if ((index = spu_disassemble_table[opcode & 0x780]) != 0
  55       && index->insn_type == RRR)
  56     return index;
  57 
  58   if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0
  59       && (index->insn_type == RI18 || index->insn_type == LBT))
  60     return index;
  61 
  62   if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0
  63       && index->insn_type == RI10)
  64     return index;
  65 
  66   if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0
  67       && (index->insn_type == RI16))
  68     return index;
  69 
  70   if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0
  71       && (index->insn_type == RI8))
  72     return index;
  73 
  74   if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0)
  75     return index;
  76 
  77   return NULL;
  78 }
  79 
  80 /* Print a Spu instruction.  */
  81 
  82 int
  83 print_insn_spu (unsigned long insn, unsigned long memaddr)
  84 {
  85   int value;
  86   int hex_value;
  87   const struct spu_opcode *index;
  88   enum spu_insns tag;
  89 
  90   index = get_index_for_opcode (insn);
  91 
  92   if (index == 0)
  93     {
  94       printf(".long 0x%lx", insn);
  95     }
  96   else
  97     {
  98       int i;
  99       int paren = 0;
 100       tag = (enum spu_insns)(index - spu_opcodes);
 101       printf("%s", index->mnemonic);
 102       if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
 103           || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
 104           || tag == M_SYNC || tag == M_HBR)
 105         {
 106           int fb = (insn >> (32-18)) & 0x7f;
 107           if (fb & 0x40)
 108             printf(tag == M_SYNC ? "c" : "p");
 109           if (fb & 0x20)
 110             printf("d");
 111           if (fb & 0x10)
 112             printf("e");
 113         }
 114       if (index->arg[0] != 0)
 115         printf("\t");
 116       hex_value = 0;
 117       for (i = 1;  i <= index->arg[0]; i++)
 118         {
 119           int arg = index->arg[i];
 120           if (arg != A_P && !paren && i > 1)
 121             printf(",");
 122 
 123           switch (arg)
 124             {
 125             case A_T:
 126               printf("$%lu",
 127                                      DECODE_INSN_RT (insn));
 128               break;
 129             case A_A:
 130               printf("$%lu",
 131                                      DECODE_INSN_RA (insn));
 132               break;
 133             case A_B:
 134               printf("$%lu",
 135                                      DECODE_INSN_RB (insn));
 136               break;
 137             case A_C:
 138               printf("$%lu",
 139                                      DECODE_INSN_RC (insn));
 140               break;
 141             case A_S:
 142               printf("$sp%lu",
 143                                      DECODE_INSN_RA (insn));
 144               break;
 145             case A_H:
 146               printf("$ch%lu",
 147                                      DECODE_INSN_RA (insn));
 148               break;
 149             case A_P:
 150               paren++;
 151               printf("(");
 152               break;
 153             case A_U7A:
 154               printf("%lu",
 155                                      173 - DECODE_INSN_U8 (insn));
 156               break;
 157             case A_U7B:
 158               printf("%lu",
 159                                      155 - DECODE_INSN_U8 (insn));
 160               break;
 161             case A_S3:
 162             case A_S6:
 163             case A_S7:
 164             case A_S7N:
 165             case A_U3:
 166             case A_U5:
 167             case A_U6:
 168             case A_U7:
 169               hex_value = DECODE_INSN_I7 (insn);
 170               printf("%d", hex_value);
 171               break;
 172             case A_S11:
 173               print_address(memaddr + DECODE_INSN_I9a (insn) * 4);
 174               break;
 175             case A_S11I:
 176               print_address(memaddr + DECODE_INSN_I9b (insn) * 4);
 177               break;
 178             case A_S10:
 179             case A_S10B:
 180               hex_value = DECODE_INSN_I10 (insn);
 181               printf("%d", hex_value);
 182               break;
 183             case A_S14:
 184               hex_value = DECODE_INSN_I10 (insn) * 16;
 185               printf("%d", hex_value);
 186               break;
 187             case A_S16:
 188               hex_value = DECODE_INSN_I16 (insn);
 189               printf("%d", hex_value);
 190               break;
 191             case A_X16:
 192               hex_value = DECODE_INSN_U16 (insn);
 193               printf("%u", hex_value);
 194               break;
 195             case A_R18:
 196               value = DECODE_INSN_I16 (insn) * 4;
 197               if (value == 0)
 198                 printf("%d", value);
 199               else
 200                 {
 201                   hex_value = memaddr + value;
 202                   print_address(hex_value & 0x3ffff);
 203                 }
 204               break;
 205             case A_S18:
 206               value = DECODE_INSN_U16 (insn) * 4;
 207               if (value == 0)
 208                 printf("%d", value);
 209               else
 210                 print_address(value);
 211               break;
 212             case A_U18:
 213               value = DECODE_INSN_U18 (insn);
 214               if (value == 0 || 1)
 215                 {
 216                   hex_value = value;
 217                   printf("%u", value);
 218                 }
 219               else
 220                 print_address(value);
 221               break;
 222             case A_U14:
 223               hex_value = DECODE_INSN_U14 (insn);
 224               printf("%u", hex_value);
 225               break;
 226             }
 227           if (arg != A_P && paren)
 228             {
 229               printf(")");
 230               paren--;
 231             }
 232         }
 233       if (hex_value > 16)
 234         printf("\t# %x", hex_value);
 235     }
 236   return 4;
 237 }

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