/* tilepro-dis.c.  Disassembly routines for the TILEPro architecture.
   Copyright (C) 2011-2021 Free Software Foundation, Inc.

   This file is part of the GNU opcodes library.

   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 3 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 "sysdep.h"
#include <stddef.h>
#include <assert.h>
#include "bfd.h"
#include "elf/tilepro.h"
#include "elf-bfd.h"
#include "disassemble.h"
#include "opcode/tilepro.h"


#define TREG_ZERO 63

static int
contains_insn (tilepro_mnemonic expected_mnemonic,
	       int expected_first_operand,
	       int expected_second_operand,
	       bfd_vma memaddr,
	       int *last_operand_ret,
	       disassemble_info *info)
{
  struct tilepro_decoded_instruction
    decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE];
  bfd_byte opbuf[TILEPRO_BUNDLE_SIZE_IN_BYTES];
  int i, num_instructions;

  if ((*info->read_memory_func) (memaddr, opbuf,
				 TILEPRO_BUNDLE_SIZE_IN_BYTES, info) != 0)
    /* If we cannot even read the memory, it obviously does not have the
       instruction for which we are looking. */
    return 0;

  /* Parse the instructions in the bundle. */
  num_instructions = parse_insn_tilepro (bfd_getl64 (opbuf), memaddr, decoded);

  for (i = 0; i < num_instructions; i++)
    {
      const struct tilepro_opcode *opcode = decoded[i].opcode;

      if (opcode->mnemonic != expected_mnemonic)
	continue;

      if (expected_first_operand != -1
	  && decoded[i].operand_values[0] != expected_first_operand)
	continue;

      if (expected_second_operand != -1
	  && decoded[i].operand_values[1] != expected_second_operand)
	continue;

      *last_operand_ret = decoded[i].operand_values[opcode->num_operands - 1];
      return 1;
    }

  /* No match. */
  return 0;
}


int
print_insn_tilepro (bfd_vma memaddr, disassemble_info *info)
{
  struct tilepro_decoded_instruction
    decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE];
  bfd_byte opbuf[TILEPRO_BUNDLE_SIZE_IN_BYTES];
  int status, i, num_instructions, num_printed;
  tilepro_mnemonic padding_mnemonic;

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

  info->bytes_per_line = TILEPRO_BUNDLE_SIZE_IN_BYTES;
  info->bytes_per_chunk = TILEPRO_BUNDLE_SIZE_IN_BYTES;
  info->octets_per_byte = 1;
  info->display_endian = BFD_ENDIAN_LITTLE;

  /* Parse the instructions in the bundle.  */
  num_instructions = parse_insn_tilepro (bfd_getl64 (opbuf), memaddr, decoded);

  /* Print the instructions in the bundle.  */
  info->fprintf_func (info->stream, "{ ");
  num_printed = 0;

  /* Determine which nop opcode is used for padding and should be skipped.  */
  padding_mnemonic = TILEPRO_OPC_FNOP;
  for (i = 0; i < num_instructions; i++)
    {
      if (!decoded[i].opcode->can_bundle)
	{
	  /* Instructions that cannot be bundled are padded out with nops,
	     rather than fnops. Displaying them is always clutter.  */
	  padding_mnemonic = TILEPRO_OPC_NOP;
	  break;
	}
    }

  for (i = 0; i < num_instructions; i++)
    {
      const struct tilepro_opcode *opcode = decoded[i].opcode;
      const char *name;
      int j;

      /* Do not print out fnops, unless everything is an fnop, in
	 which case we will print out just the last one.  */
      if (opcode->mnemonic == padding_mnemonic
	  && (num_printed > 0 || i + 1 < num_instructions))
	continue;

      if (num_printed > 0)
	info->fprintf_func (info->stream, " ; ");
      ++num_printed;

      name = opcode->name;
      if (name == NULL)
	name = "<invalid>";
      info->fprintf_func (info->stream, "%s", name);

      for (j = 0; j < opcode->num_operands; j++)
	{
	  int num;
	  const struct tilepro_operand *op;
	  const char *spr_name;

	  if (j > 0)
	    info->fprintf_func (info->stream, ",");
	  info->fprintf_func (info->stream, " ");

	  num = decoded[i].operand_values[j];

	  op = decoded[i].operands[j];
	  switch (op->type)
	    {
	    case TILEPRO_OP_TYPE_REGISTER:
	      info->fprintf_func (info->stream, "%s",
				  tilepro_register_names[num]);
	      break;

	    case TILEPRO_OP_TYPE_SPR:
	      spr_name = get_tilepro_spr_name(num);
	      if (spr_name != NULL)
		info->fprintf_func (info->stream, "%s", spr_name);
	      else
		info->fprintf_func (info->stream, "%d", num);
	      break;

	    case TILEPRO_OP_TYPE_IMMEDIATE:
	      {
		bfd_vma addr = 0;
		int found_addr = 0;
		int addr_piece;

		switch (opcode->mnemonic)
		  {
		  case TILEPRO_OPC_ADDLI:
		    if (contains_insn (TILEPRO_OPC_AULI,
				       decoded[i].operand_values[1],
				       TREG_ZERO,
				       memaddr - TILEPRO_BUNDLE_SIZE_IN_BYTES,
				       &addr_piece,
				       info))
		      {
			addr = num + (addr_piece << 16);
			found_addr = 1;
		      }
		    break;

		  case TILEPRO_OPC_AULI:
		    if (contains_insn (TILEPRO_OPC_MOVELI,
				       decoded[i].operand_values[1],
				       -1,
				       memaddr - TILEPRO_BUNDLE_SIZE_IN_BYTES,
				       &addr_piece,
				       info))
		      {
			addr = (num << 16) + addr_piece;
			found_addr = 1;
		      }
		    break;

		  default:
		    /* Operand does not look like a constructed address.  */
		    break;
		  }

		info->fprintf_func (info->stream, "%d", num);

		if (found_addr)
		  {
		    info->fprintf_func (info->stream, " /* ");
		    info->print_address_func (addr, info);
		    info->fprintf_func (info->stream, " */");
		  }
	      }
	      break;

	    case TILEPRO_OP_TYPE_ADDRESS:
	      info->print_address_func ((bfd_vma)(unsigned int) num, info);
	      break;

	    default:
	      abort ();
	    }
	}
    }
  info->fprintf_func (info->stream, " }");

  return TILEPRO_BUNDLE_SIZE_IN_BYTES;
}
