/* Disassemble SPU instructions

   Copyright (C) 2006-2016 Free Software Foundation, Inc.

   This file is part of the GNU opcodes library.

   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
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   It 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 file; see the file COPYING.  If not, write to the
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */

#include "sysdep.h"
#include <stdio.h>
#include "dis-asm.h"
#include "opcode/spu.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;

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

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 >= (1 << 11))
	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 *op_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 ((op_index = spu_disassemble_table[opcode & 0x780]) != 0
      && op_index->insn_type == RRR)
    return op_index;

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

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

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

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

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

  return 0;
}

/* Print a Spu instruction.  */

int
print_insn_spu (bfd_vma memaddr, struct disassemble_info *info)
{
  bfd_byte buffer[4];
  int value;
  int hex_value;
  int status;
  unsigned int insn;
  const struct spu_opcode *op_index;
  enum spu_insns tag;

  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  if (status != 0)
    {
      (*info->memory_error_func) (status, memaddr, info);
      return -1;
    }

  insn = bfd_getb32 (buffer);

  op_index = get_index_for_opcode (insn);

  if (op_index == 0)
    {
      (*info->fprintf_func) (info->stream, ".long 0x%x", insn);
    }
  else
    {
      int i;
      int paren = 0;
      tag = (enum spu_insns)(op_index - spu_opcodes);
      (*info->fprintf_func) (info->stream, "%s", op_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)
	    (*info->fprintf_func) (info->stream, tag == M_SYNC ? "c" : "p");
	  if (fb & 0x20)
	    (*info->fprintf_func) (info->stream, "d");
	  if (fb & 0x10)
	    (*info->fprintf_func) (info->stream, "e");
	}
      if (op_index->arg[0] != 0)
	(*info->fprintf_func) (info->stream, "\t");
      hex_value = 0;
      for (i = 1;  i <= op_index->arg[0]; i++)
	{
	  int arg = op_index->arg[i];
	  if (arg != A_P && !paren && i > 1)
	    (*info->fprintf_func) (info->stream, ",");

	  switch (arg)
	    {
	    case A_T:
	      (*info->fprintf_func) (info->stream, "$%d",
				     DECODE_INSN_RT (insn));
	      break;
	    case A_A:
	      (*info->fprintf_func) (info->stream, "$%d",
				     DECODE_INSN_RA (insn));
	      break;
	    case A_B:
	      (*info->fprintf_func) (info->stream, "$%d",
				     DECODE_INSN_RB (insn));
	      break;
	    case A_C:
	      (*info->fprintf_func) (info->stream, "$%d",
				     DECODE_INSN_RC (insn));
	      break;
	    case A_S:
	      (*info->fprintf_func) (info->stream, "$sp%d",
				     DECODE_INSN_RA (insn));
	      break;
	    case A_H:
	      (*info->fprintf_func) (info->stream, "$ch%d",
				     DECODE_INSN_RA (insn));
	      break;
	    case A_P:
	      paren++;
	      (*info->fprintf_func) (info->stream, "(");
	      break;
	    case A_U7A:
	      (*info->fprintf_func) (info->stream, "%d",
				     173 - DECODE_INSN_U8 (insn));
	      break;
	    case A_U7B:
	      (*info->fprintf_func) (info->stream, "%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);
	      (*info->fprintf_func) (info->stream, "%d", hex_value);
	      break;
	    case A_S11:
	      (*info->print_address_func) (memaddr + DECODE_INSN_I9a (insn) * 4,
					   info);
	      break;
	    case A_S11I:
	      (*info->print_address_func) (memaddr + DECODE_INSN_I9b (insn) * 4,
					   info);
	      break;
	    case A_S10:
	    case A_S10B:
	      hex_value = DECODE_INSN_I10 (insn);
	      (*info->fprintf_func) (info->stream, "%d", hex_value);
	      break;
	    case A_S14:
	      hex_value = DECODE_INSN_I10 (insn) * 16;
	      (*info->fprintf_func) (info->stream, "%d", hex_value);
	      break;
	    case A_S16:
	      hex_value = DECODE_INSN_I16 (insn);
	      (*info->fprintf_func) (info->stream, "%d", hex_value);
	      break;
	    case A_X16:
	      hex_value = DECODE_INSN_U16 (insn);
	      (*info->fprintf_func) (info->stream, "%u", hex_value);
	      break;
	    case A_R18:
	      value = DECODE_INSN_I16 (insn) * 4;
	      if (value == 0)
		(*info->fprintf_func) (info->stream, "%d", value);
	      else
		{
		  hex_value = memaddr + value;
		  (*info->print_address_func) (hex_value & 0x3ffff, info);
		}
	      break;
	    case A_S18:
	      value = DECODE_INSN_U16 (insn) * 4;
	      if (value == 0)
		(*info->fprintf_func) (info->stream, "%d", value);
	      else
		(*info->print_address_func) (value, info);
	      break;
	    case A_U18:
	      value = DECODE_INSN_U18 (insn);
	      if (value == 0 || !(*info->symbol_at_address_func)(0, info))
		{
		  hex_value = value;
		  (*info->fprintf_func) (info->stream, "%u", value);
		}
	      else
		(*info->print_address_func) (value, info);
	      break;
	    case A_U14:
	      hex_value = DECODE_INSN_U14 (insn);
	      (*info->fprintf_func) (info->stream, "%u", hex_value);
	      break;
	    }
	  if (arg != A_P && paren)
	    {
	      (*info->fprintf_func) (info->stream, ")");
	      paren--;
	    }
	}
      if (hex_value > 16)
	(*info->fprintf_func) (info->stream, "\t# %x", hex_value);
    }
  return 4;
}
