/* Disassemble SPU instructions

   Copyright 2006 Free Software Foundation, Inc.

   This file is part of GDB, GAS, and the GNU binutils.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <linux/string.h>
#include "nonstdio.h"
#include "ansidecl.h"
#include "spu.h"
#include "dis-asm.h"

/* This file provides a disassembler function which uses
   the disassembler interface defined in dis-asm.h.   */

extern const struct spu_opcode spu_opcodes[];
extern const int spu_num_opcodes;

#define SPU_DISASM_TBL_SIZE (1 << 11)
static const struct spu_opcode *spu_disassemble_table[SPU_DISASM_TBL_SIZE];

static void
init_spu_disassemble (void)
{
  int i;

  /* If two instructions have the same opcode then we prefer the first
   * one.  In most cases it is just an alternate mnemonic. */
  for (i = 0; i < spu_num_opcodes; i++)
    {
      int o = spu_opcodes[i].opcode;
      if (o >= SPU_DISASM_TBL_SIZE)
	continue; /* abort (); */
      if (spu_disassemble_table[o] == 0)
	spu_disassemble_table[o] = &spu_opcodes[i];
    }
}

/* Determine the instruction from the 10 least significant bits. */
static const struct spu_opcode *
get_index_for_opcode (unsigned int insn)
{
  const struct spu_opcode *index;
  unsigned int opcode = insn >> (32-11);

  /* Init the table.  This assumes that element 0/opcode 0 (currently
   * NOP) is always used */
  if (spu_disassemble_table[0] == 0)
    init_spu_disassemble ();

  if ((index = spu_disassemble_table[opcode & 0x780]) != 0
      && index->insn_type == RRR)
    return index;

  if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0
      && (index->insn_type == RI18 || index->insn_type == LBT))
    return index;

  if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0
      && index->insn_type == RI10)
    return index;

  if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0
      && (index->insn_type == RI16))
    return index;

  if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0
      && (index->insn_type == RI8))
    return index;

  if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0)
    return index;

  return NULL;
}

/* Print a Spu instruction.  */

int
print_insn_spu (unsigned long insn, unsigned long memaddr)
{
  int value;
  int hex_value;
  const struct spu_opcode *index;
  enum spu_insns tag;

  index = get_index_for_opcode (insn);

  if (index == 0)
    {
      printf(".long 0x%x", insn);
    }
  else
    {
      int i;
      int paren = 0;
      tag = (enum spu_insns)(index - spu_opcodes);
      printf("%s", index->mnemonic);
      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_SYNC || tag == M_HBR)
	{
	  int fb = (insn >> (32-18)) & 0x7f;
	  if (fb & 0x40)
	    printf(tag == M_SYNC ? "c" : "p");
	  if (fb & 0x20)
	    printf("d");
	  if (fb & 0x10)
	    printf("e");
	}
      if (index->arg[0] != 0)
	printf("\t");
      hex_value = 0;
      for (i = 1;  i <= index->arg[0]; i++)
	{
	  int arg = index->arg[i];
	  if (arg != A_P && !paren && i > 1)
	    printf(",");

	  switch (arg)
	    {
	    case A_T:
	      printf("$%d",
				     DECODE_INSN_RT (insn));
	      break;
	    case A_A:
	      printf("$%d",
				     DECODE_INSN_RA (insn));
	      break;
	    case A_B:
	      printf("$%d",
				     DECODE_INSN_RB (insn));
	      break;
	    case A_C:
	      printf("$%d",
				     DECODE_INSN_RC (insn));
	      break;
	    case A_S:
	      printf("$sp%d",
				     DECODE_INSN_RA (insn));
	      break;
	    case A_H:
	      printf("$ch%d",
				     DECODE_INSN_RA (insn));
	      break;
	    case A_P:
	      paren++;
	      printf("(");
	      break;
	    case A_U7A:
	      printf("%d",
				     173 - DECODE_INSN_U8 (insn));
	      break;
	    case A_U7B:
	      printf("%d",
				     155 - DECODE_INSN_U8 (insn));
	      break;
	    case A_S3:
	    case A_S6:
	    case A_S7:
	    case A_S7N:
	    case A_U3:
	    case A_U5:
	    case A_U6:
	    case A_U7:
	      hex_value = DECODE_INSN_I7 (insn);
	      printf("%d", hex_value);
	      break;
	    case A_S11:
	      print_address(memaddr + DECODE_INSN_I9a (insn) * 4);
	      break;
	    case A_S11I:
	      print_address(memaddr + DECODE_INSN_I9b (insn) * 4);
	      break;
	    case A_S10:
	    case A_S10B:
	      hex_value = DECODE_INSN_I10 (insn);
	      printf("%d", hex_value);
	      break;
	    case A_S14:
	      hex_value = DECODE_INSN_I10 (insn) * 16;
	      printf("%d", hex_value);
	      break;
	    case A_S16:
	      hex_value = DECODE_INSN_I16 (insn);
	      printf("%d", hex_value);
	      break;
	    case A_X16:
	      hex_value = DECODE_INSN_U16 (insn);
	      printf("%u", hex_value);
	      break;
	    case A_R18:
	      value = DECODE_INSN_I16 (insn) * 4;
	      if (value == 0)
		printf("%d", value);
	      else
		{
		  hex_value = memaddr + value;
		  print_address(hex_value & 0x3ffff);
		}
	      break;
	    case A_S18:
	      value = DECODE_INSN_U16 (insn) * 4;
	      if (value == 0)
		printf("%d", value);
	      else
		print_address(value);
	      break;
	    case A_U18:
	      value = DECODE_INSN_U18 (insn);
	      if (value == 0 || 1)
		{
		  hex_value = value;
		  printf("%u", value);
		}
	      else
		print_address(value);
	      break;
	    case A_U14:
	      hex_value = DECODE_INSN_U14 (insn);
	      printf("%u", hex_value);
	      break;
	    }
	  if (arg != A_P && paren)
	    {
	      printf(")");
	      paren--;
	    }
	}
      if (hex_value > 16)
	printf("\t# %x", hex_value);
    }
  return 4;
}
