/* xtensa-dis.c.  Disassembly functions for Xtensa.
   Copyright 2003, 2004 Free Software Foundation, Inc.
   Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)

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

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

   GDB, GAS, and the GNU binutils are distributed in the hope that they
   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 <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include "xtensa-isa.h"
#include "ansidecl.h"
#include "libiberty.h"
#include "sysdep.h"
#include "dis-asm.h"

#include <setjmp.h>

extern xtensa_isa xtensa_default_isa;

#ifndef MAX
#define MAX(a,b) (a > b ? a : b)
#endif

int show_raw_fields;

struct dis_private
{
  bfd_byte *byte_buf;
  jmp_buf bailout;
};


static int
fetch_data (struct disassemble_info *info, bfd_vma memaddr)
{
  int length, status = 0;
  struct dis_private *priv = (struct dis_private *) info->private_data;
  int insn_size = xtensa_isa_maxlength (xtensa_default_isa);

  /* Read the maximum instruction size, padding with zeros if we go past
     the end of the text section.  This code will automatically adjust
     length when we hit the end of the buffer.  */

  memset (priv->byte_buf, 0, insn_size);
  for (length = insn_size; length > 0; length--)
    {
      status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
					  info);
      if (status == 0)
	return length;
    }
  (*info->memory_error_func) (status, memaddr, info);
  longjmp (priv->bailout, 1);
  /*NOTREACHED*/
}


static void
print_xtensa_operand (bfd_vma memaddr,
		      struct disassemble_info *info,
		      xtensa_opcode opc,
		      int opnd,
		      unsigned operand_val)
{
  xtensa_isa isa = xtensa_default_isa;
  int signed_operand_val;
    
  if (show_raw_fields)
    {
      if (operand_val < 0xa)
	(*info->fprintf_func) (info->stream, "%u", operand_val);
      else
	(*info->fprintf_func) (info->stream, "0x%x", operand_val);
      return;
    }

  (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
  signed_operand_val = (int) operand_val;

  if (xtensa_operand_is_register (isa, opc, opnd) == 0)
    {
      if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
	{
	  (void) xtensa_operand_undo_reloc (isa, opc, opnd,
					    &operand_val, memaddr);
	  info->target = operand_val;
	  (*info->print_address_func) (info->target, info);
	}
      else
	{
	  if ((signed_operand_val > -256) && (signed_operand_val < 256))
	    (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
	  else
	    (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
	}
    }
  else
    {
      int i = 1;
      xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
      (*info->fprintf_func) (info->stream, "%s%u",
			     xtensa_regfile_shortname (isa, opnd_rf),
			     operand_val);
      while (i < xtensa_operand_num_regs (isa, opc, opnd))
	{
	  operand_val++;
	  (*info->fprintf_func) (info->stream, ":%s%u",
				 xtensa_regfile_shortname (isa, opnd_rf),
				 operand_val);
	  i++;
	} 
    }
}


/* Print the Xtensa instruction at address MEMADDR on info->stream.
   Returns length of the instruction in bytes.  */

int
print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info)
{
  unsigned operand_val;
  int bytes_fetched, size, maxsize, i, n, noperands, nslots;
  xtensa_isa isa;
  xtensa_opcode opc;
  xtensa_format fmt;
  struct dis_private priv;
  static bfd_byte *byte_buf = NULL;
  static xtensa_insnbuf insn_buffer = NULL;
  static xtensa_insnbuf slot_buffer = NULL;
  int first, first_slot, valid_insn;

  if (!xtensa_default_isa)
    xtensa_default_isa = xtensa_isa_init (0, 0);

  info->target = 0;
  maxsize = xtensa_isa_maxlength (xtensa_default_isa);

  /* Set bytes_per_line to control the amount of whitespace between the hex
     values and the opcode.  For Xtensa, we always print one "chunk" and we
     vary bytes_per_chunk to determine how many bytes to print.  (objdump
     would apparently prefer that we set bytes_per_chunk to 1 and vary
     bytes_per_line but that makes it hard to fit 64-bit instructions on
     an 80-column screen.)  The value of bytes_per_line here is not exactly
     right, because objdump adds an extra space for each chunk so that the
     amount of whitespace depends on the chunk size.  Oh well, it's good
     enough....  Note that we set the minimum size to 4 to accomodate
     literal pools.  */
  info->bytes_per_line = MAX (maxsize, 4);

  /* Allocate buffers the first time through.  */
  if (!insn_buffer)
    {
      insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
      slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
      byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
    }

  priv.byte_buf = byte_buf;

  info->private_data = (void *) &priv;
  if (setjmp (priv.bailout) != 0)
      /* Error return.  */
      return -1;

  /* Don't set "isa" before the setjmp to keep the compiler from griping.  */
  isa = xtensa_default_isa;
  size = 0;
  nslots = 0;

  /* Fetch the maximum size instruction.  */
  bytes_fetched = fetch_data (info, memaddr);

  /* Copy the bytes into the decode buffer.  */
  memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
			   sizeof (xtensa_insnbuf_word)));
  xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, bytes_fetched);

  fmt = xtensa_format_decode (isa, insn_buffer);
  if (fmt == XTENSA_UNDEFINED
      || ((size = xtensa_format_length (isa, fmt)) > bytes_fetched))
    valid_insn = 0;
  else
    {
      /* Make sure all the opcodes are valid.  */
      valid_insn = 1;
      nslots = xtensa_format_num_slots (isa, fmt);
      for (n = 0; n < nslots; n++)
	{
	  xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
	  if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
	      == XTENSA_UNDEFINED)
	    {
	      valid_insn = 0;
	      break;
	    }
	}
    }

  if (!valid_insn)
    {
      (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
      return 1;
    }

  if (nslots > 1)
    (*info->fprintf_func) (info->stream, "{ ");

  first_slot = 1;
  for (n = 0; n < nslots; n++)
    {
      if (first_slot)
	first_slot = 0;
      else
	(*info->fprintf_func) (info->stream, "; ");

      xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
      opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
      (*info->fprintf_func) (info->stream, "%s",
			     xtensa_opcode_name (isa, opc));

      /* Print the operands (if any).  */
      noperands = xtensa_opcode_num_operands (isa, opc);
      first = 1;
      for (i = 0; i < noperands; i++)
	{
	  if (xtensa_operand_is_visible (isa, opc, i) == 0)
	    continue;
	  if (first)
	    {
	      (*info->fprintf_func) (info->stream, "\t");
	      first = 0;
	    }
	  else
	    (*info->fprintf_func) (info->stream, ", ");
	  (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
					   slot_buffer, &operand_val);

	  print_xtensa_operand (memaddr, info, opc, i, operand_val);
	}
    }

  if (nslots > 1)
    (*info->fprintf_func) (info->stream, " }");

  info->bytes_per_chunk = size;
  info->display_endian = info->endian;

  return size;
}

