OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [opcodes/] [spu-dis.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* Disassemble SPU instructions
/* Disassemble SPU instructions
 
 
   Copyright 2006, 2007 Free Software Foundation, Inc.
   Copyright 2006, 2007 Free Software Foundation, Inc.
 
 
   This file is part of the GNU opcodes library.
   This file is part of the GNU opcodes library.
 
 
   This library is free software; you can redistribute it and/or modify
   This library is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
   any later version.
 
 
   It is distributed in the hope that it will be useful, but WITHOUT
   It is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.
   License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this file; see the file COPYING.  If not, write to the
   along with this file; see the file COPYING.  If not, write to the
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */
   MA 02110-1301, USA.  */
 
 
#include <stdio.h>
#include <stdio.h>
#include "sysdep.h"
#include "sysdep.h"
#include "dis-asm.h"
#include "dis-asm.h"
#include "opcode/spu.h"
#include "opcode/spu.h"
 
 
/* This file provides a disassembler function which uses
/* This file provides a disassembler function which uses
   the disassembler interface defined in dis-asm.h.   */
   the disassembler interface defined in dis-asm.h.   */
 
 
extern const struct spu_opcode spu_opcodes[];
extern const struct spu_opcode spu_opcodes[];
extern const int spu_num_opcodes;
extern const int spu_num_opcodes;
 
 
static const struct spu_opcode *spu_disassemble_table[(1<<11)];
static const struct spu_opcode *spu_disassemble_table[(1<<11)];
 
 
static void
static void
init_spu_disassemble (void)
init_spu_disassemble (void)
{
{
  int i;
  int i;
 
 
  /* If two instructions have the same opcode then we prefer the first
  /* If two instructions have the same opcode then we prefer the first
   * one.  In most cases it is just an alternate mnemonic. */
   * one.  In most cases it is just an alternate mnemonic. */
  for (i = 0; i < spu_num_opcodes; i++)
  for (i = 0; i < spu_num_opcodes; i++)
    {
    {
      int o = spu_opcodes[i].opcode;
      int o = spu_opcodes[i].opcode;
      if (o >= (1 << 11))
      if (o >= (1 << 11))
        abort ();
        abort ();
      if (spu_disassemble_table[o] == 0)
      if (spu_disassemble_table[o] == 0)
        spu_disassemble_table[o] = &spu_opcodes[i];
        spu_disassemble_table[o] = &spu_opcodes[i];
    }
    }
}
}
 
 
/* Determine the instruction from the 10 least significant bits. */
/* Determine the instruction from the 10 least significant bits. */
static const struct spu_opcode *
static const struct spu_opcode *
get_index_for_opcode (unsigned int insn)
get_index_for_opcode (unsigned int insn)
{
{
  const struct spu_opcode *index;
  const struct spu_opcode *index;
  unsigned int opcode = insn >> (32-11);
  unsigned int opcode = insn >> (32-11);
 
 
  /* Init the table.  This assumes that element 0/opcode 0 (currently
  /* Init the table.  This assumes that element 0/opcode 0 (currently
   * NOP) is always used */
   * NOP) is always used */
  if (spu_disassemble_table[0] == 0)
  if (spu_disassemble_table[0] == 0)
    init_spu_disassemble ();
    init_spu_disassemble ();
 
 
  if ((index = spu_disassemble_table[opcode & 0x780]) != 0
  if ((index = spu_disassemble_table[opcode & 0x780]) != 0
      && index->insn_type == RRR)
      && index->insn_type == RRR)
    return index;
    return index;
 
 
  if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0
  if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0
      && (index->insn_type == RI18 || index->insn_type == LBT))
      && (index->insn_type == RI18 || index->insn_type == LBT))
    return index;
    return index;
 
 
  if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0
  if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0
      && index->insn_type == RI10)
      && index->insn_type == RI10)
    return index;
    return index;
 
 
  if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0
  if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0
      && (index->insn_type == RI16))
      && (index->insn_type == RI16))
    return index;
    return index;
 
 
  if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0
  if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0
      && (index->insn_type == RI8))
      && (index->insn_type == RI8))
    return index;
    return index;
 
 
  if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0)
  if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0)
    return index;
    return index;
 
 
  return 0;
  return 0;
}
}
 
 
/* Print a Spu instruction.  */
/* Print a Spu instruction.  */
 
 
int
int
print_insn_spu (bfd_vma memaddr, struct disassemble_info *info)
print_insn_spu (bfd_vma memaddr, struct disassemble_info *info)
{
{
  bfd_byte buffer[4];
  bfd_byte buffer[4];
  int value;
  int value;
  int hex_value;
  int hex_value;
  int status;
  int status;
  unsigned int insn;
  unsigned int insn;
  const struct spu_opcode *index;
  const struct spu_opcode *index;
  enum spu_insns tag;
  enum spu_insns tag;
 
 
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  if (status != 0)
  if (status != 0)
    {
    {
      (*info->memory_error_func) (status, memaddr, info);
      (*info->memory_error_func) (status, memaddr, info);
      return -1;
      return -1;
    }
    }
 
 
  insn = bfd_getb32 (buffer);
  insn = bfd_getb32 (buffer);
 
 
  index = get_index_for_opcode (insn);
  index = get_index_for_opcode (insn);
 
 
  if (index == 0)
  if (index == 0)
    {
    {
      (*info->fprintf_func) (info->stream, ".long 0x%x", insn);
      (*info->fprintf_func) (info->stream, ".long 0x%x", insn);
    }
    }
  else
  else
    {
    {
      int i;
      int i;
      int paren = 0;
      int paren = 0;
      tag = (enum spu_insns)(index - spu_opcodes);
      tag = (enum spu_insns)(index - spu_opcodes);
      (*info->fprintf_func) (info->stream, "%s", index->mnemonic);
      (*info->fprintf_func) (info->stream, "%s", index->mnemonic);
      if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
      if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
          || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
          || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
          || tag == M_SYNC || tag == M_HBR)
          || tag == M_SYNC || tag == M_HBR)
        {
        {
          int fb = (insn >> (32-18)) & 0x7f;
          int fb = (insn >> (32-18)) & 0x7f;
          if (fb & 0x40)
          if (fb & 0x40)
            (*info->fprintf_func) (info->stream, tag == M_SYNC ? "c" : "p");
            (*info->fprintf_func) (info->stream, tag == M_SYNC ? "c" : "p");
          if (fb & 0x20)
          if (fb & 0x20)
            (*info->fprintf_func) (info->stream, "d");
            (*info->fprintf_func) (info->stream, "d");
          if (fb & 0x10)
          if (fb & 0x10)
            (*info->fprintf_func) (info->stream, "e");
            (*info->fprintf_func) (info->stream, "e");
        }
        }
      if (index->arg[0] != 0)
      if (index->arg[0] != 0)
        (*info->fprintf_func) (info->stream, "\t");
        (*info->fprintf_func) (info->stream, "\t");
      hex_value = 0;
      hex_value = 0;
      for (i = 1;  i <= index->arg[0]; i++)
      for (i = 1;  i <= index->arg[0]; i++)
        {
        {
          int arg = index->arg[i];
          int arg = index->arg[i];
          if (arg != A_P && !paren && i > 1)
          if (arg != A_P && !paren && i > 1)
            (*info->fprintf_func) (info->stream, ",");
            (*info->fprintf_func) (info->stream, ",");
 
 
          switch (arg)
          switch (arg)
            {
            {
            case A_T:
            case A_T:
              (*info->fprintf_func) (info->stream, "$%d",
              (*info->fprintf_func) (info->stream, "$%d",
                                     DECODE_INSN_RT (insn));
                                     DECODE_INSN_RT (insn));
              break;
              break;
            case A_A:
            case A_A:
              (*info->fprintf_func) (info->stream, "$%d",
              (*info->fprintf_func) (info->stream, "$%d",
                                     DECODE_INSN_RA (insn));
                                     DECODE_INSN_RA (insn));
              break;
              break;
            case A_B:
            case A_B:
              (*info->fprintf_func) (info->stream, "$%d",
              (*info->fprintf_func) (info->stream, "$%d",
                                     DECODE_INSN_RB (insn));
                                     DECODE_INSN_RB (insn));
              break;
              break;
            case A_C:
            case A_C:
              (*info->fprintf_func) (info->stream, "$%d",
              (*info->fprintf_func) (info->stream, "$%d",
                                     DECODE_INSN_RC (insn));
                                     DECODE_INSN_RC (insn));
              break;
              break;
            case A_S:
            case A_S:
              (*info->fprintf_func) (info->stream, "$sp%d",
              (*info->fprintf_func) (info->stream, "$sp%d",
                                     DECODE_INSN_RA (insn));
                                     DECODE_INSN_RA (insn));
              break;
              break;
            case A_H:
            case A_H:
              (*info->fprintf_func) (info->stream, "$ch%d",
              (*info->fprintf_func) (info->stream, "$ch%d",
                                     DECODE_INSN_RA (insn));
                                     DECODE_INSN_RA (insn));
              break;
              break;
            case A_P:
            case A_P:
              paren++;
              paren++;
              (*info->fprintf_func) (info->stream, "(");
              (*info->fprintf_func) (info->stream, "(");
              break;
              break;
            case A_U7A:
            case A_U7A:
              (*info->fprintf_func) (info->stream, "%d",
              (*info->fprintf_func) (info->stream, "%d",
                                     173 - DECODE_INSN_U8 (insn));
                                     173 - DECODE_INSN_U8 (insn));
              break;
              break;
            case A_U7B:
            case A_U7B:
              (*info->fprintf_func) (info->stream, "%d",
              (*info->fprintf_func) (info->stream, "%d",
                                     155 - DECODE_INSN_U8 (insn));
                                     155 - DECODE_INSN_U8 (insn));
              break;
              break;
            case A_S3:
            case A_S3:
            case A_S6:
            case A_S6:
            case A_S7:
            case A_S7:
            case A_S7N:
            case A_S7N:
            case A_U3:
            case A_U3:
            case A_U5:
            case A_U5:
            case A_U6:
            case A_U6:
            case A_U7:
            case A_U7:
              hex_value = DECODE_INSN_I7 (insn);
              hex_value = DECODE_INSN_I7 (insn);
              (*info->fprintf_func) (info->stream, "%d", hex_value);
              (*info->fprintf_func) (info->stream, "%d", hex_value);
              break;
              break;
            case A_S11:
            case A_S11:
              (*info->print_address_func) (memaddr + DECODE_INSN_I9a (insn) * 4,
              (*info->print_address_func) (memaddr + DECODE_INSN_I9a (insn) * 4,
                                           info);
                                           info);
              break;
              break;
            case A_S11I:
            case A_S11I:
              (*info->print_address_func) (memaddr + DECODE_INSN_I9b (insn) * 4,
              (*info->print_address_func) (memaddr + DECODE_INSN_I9b (insn) * 4,
                                           info);
                                           info);
              break;
              break;
            case A_S10:
            case A_S10:
            case A_S10B:
            case A_S10B:
              hex_value = DECODE_INSN_I10 (insn);
              hex_value = DECODE_INSN_I10 (insn);
              (*info->fprintf_func) (info->stream, "%d", hex_value);
              (*info->fprintf_func) (info->stream, "%d", hex_value);
              break;
              break;
            case A_S14:
            case A_S14:
              hex_value = DECODE_INSN_I10 (insn) * 16;
              hex_value = DECODE_INSN_I10 (insn) * 16;
              (*info->fprintf_func) (info->stream, "%d", hex_value);
              (*info->fprintf_func) (info->stream, "%d", hex_value);
              break;
              break;
            case A_S16:
            case A_S16:
              hex_value = DECODE_INSN_I16 (insn);
              hex_value = DECODE_INSN_I16 (insn);
              (*info->fprintf_func) (info->stream, "%d", hex_value);
              (*info->fprintf_func) (info->stream, "%d", hex_value);
              break;
              break;
            case A_X16:
            case A_X16:
              hex_value = DECODE_INSN_U16 (insn);
              hex_value = DECODE_INSN_U16 (insn);
              (*info->fprintf_func) (info->stream, "%u", hex_value);
              (*info->fprintf_func) (info->stream, "%u", hex_value);
              break;
              break;
            case A_R18:
            case A_R18:
              value = DECODE_INSN_I16 (insn) * 4;
              value = DECODE_INSN_I16 (insn) * 4;
              if (value == 0)
              if (value == 0)
                (*info->fprintf_func) (info->stream, "%d", value);
                (*info->fprintf_func) (info->stream, "%d", value);
              else
              else
                {
                {
                  hex_value = memaddr + value;
                  hex_value = memaddr + value;
                  (*info->print_address_func) (hex_value & 0x3ffff, info);
                  (*info->print_address_func) (hex_value & 0x3ffff, info);
                }
                }
              break;
              break;
            case A_S18:
            case A_S18:
              value = DECODE_INSN_U16 (insn) * 4;
              value = DECODE_INSN_U16 (insn) * 4;
              if (value == 0)
              if (value == 0)
                (*info->fprintf_func) (info->stream, "%d", value);
                (*info->fprintf_func) (info->stream, "%d", value);
              else
              else
                (*info->print_address_func) (value, info);
                (*info->print_address_func) (value, info);
              break;
              break;
            case A_U18:
            case A_U18:
              value = DECODE_INSN_U18 (insn);
              value = DECODE_INSN_U18 (insn);
              if (value == 0 || !(*info->symbol_at_address_func)(0, info))
              if (value == 0 || !(*info->symbol_at_address_func)(0, info))
                {
                {
                  hex_value = value;
                  hex_value = value;
                  (*info->fprintf_func) (info->stream, "%u", value);
                  (*info->fprintf_func) (info->stream, "%u", value);
                }
                }
              else
              else
                (*info->print_address_func) (value, info);
                (*info->print_address_func) (value, info);
              break;
              break;
            case A_U14:
            case A_U14:
              hex_value = DECODE_INSN_U14 (insn);
              hex_value = DECODE_INSN_U14 (insn);
              (*info->fprintf_func) (info->stream, "%u", hex_value);
              (*info->fprintf_func) (info->stream, "%u", hex_value);
              break;
              break;
            }
            }
          if (arg != A_P && paren)
          if (arg != A_P && paren)
            {
            {
              (*info->fprintf_func) (info->stream, ")");
              (*info->fprintf_func) (info->stream, ")");
              paren--;
              paren--;
            }
            }
        }
        }
      if (hex_value > 16)
      if (hex_value > 16)
        (*info->fprintf_func) (info->stream, "\t# %x", hex_value);
        (*info->fprintf_func) (info->stream, "\t# %x", hex_value);
    }
    }
  return 4;
  return 4;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.