/* Disassemble Motorola M*Core instructions.
   Copyright (C) 1993-2021 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 program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */

#include "sysdep.h"
#include <stdio.h>
#include "libiberty.h"
#define STATIC_TABLE
#define DEFINE_TABLE

#include "mcore-opc.h"
#include "disassemble.h"

/* Mask for each mcore_opclass: */
static const unsigned short imsk[] = {
    /* O0  */ 0xFFFF,
    /* OT  */ 0xFFFC,
    /* O1  */ 0xFFF0,
    /* OC  */ 0xFE00,
    /* O2  */ 0xFF00,
    /* X1  */ 0xFFF0,
    /* OI  */ 0xFE00,
    /* OB  */ 0xFE00,

    /* OMa */ 0xFFF0,
    /* SI  */ 0xFE00,
    /* I7  */ 0xF800,
    /* LS  */ 0xF000,
    /* BR  */ 0xF800,
    /* BL  */ 0xFF00,
    /* LR  */ 0xF000,
    /* LJ  */ 0xFF00,

    /* RM  */ 0xFFF0,
    /* RQ  */ 0xFFF0,
    /* JSR */ 0xFFF0,
    /* JMP */ 0xFFF0,
    /* OBRa*/ 0xFFF0,
    /* OBRb*/ 0xFF80,
    /* OBRc*/ 0xFF00,
    /* OBR2*/ 0xFE00,

    /* O1R1*/ 0xFFF0,
    /* OMb */ 0xFF80,
    /* OMc */ 0xFF00,
    /* SIa */ 0xFE00,

  /* MULSH */ 0xFF00,
  /* OPSR  */ 0xFFF8,   /* psrset/psrclr */

    /* JC  */ 0,		/* JC,JU,JL don't appear in object */
    /* JU  */ 0,
    /* JL  */ 0,
    /* RSI */ 0,
    /* DO21*/ 0,
    /* OB2 */ 0 		/* OB2 won't appear in object.  */
};

static const char *grname[] = {
 "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
 "r8",  "r9", "r10", "r11", "r12", "r13", "r14", "r15"
};

static const char X[] = "??";

static const char *crname[] = {
  "psr",  "vbr", "epsr", "fpsr", "epc",  "fpc",  "ss0",  "ss1",
  "ss2",  "ss3", "ss4",  "gcr",  "gsr",     X,      X,      X,
     X,      X,      X,      X,      X,     X,      X,      X,
     X,      X,      X,      X,      X,     X,      X,      X
};

static const unsigned isiz[] = { 2, 0, 1, 0 };

int
print_insn_mcore (bfd_vma memaddr,
		  struct disassemble_info *info)
{
  unsigned char ibytes[4];
  fprintf_ftype print_func = info->fprintf_func;
  void *stream = info->stream;
  unsigned int inst;
  unsigned int i;
  int status;

  info->bytes_per_chunk = 2;

  status = info->read_memory_func (memaddr, ibytes, 2, info);

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

  if (info->endian == BFD_ENDIAN_BIG)
    inst = (ibytes[0] << 8) | ibytes[1];
  else if (info->endian == BFD_ENDIAN_LITTLE)
    inst = (ibytes[1] << 8) | ibytes[0];
  else
    abort ();

  /* Just a linear search of the table.  */
  for (i = 0; i < ARRAY_SIZE (mcore_table); i++)
    if (mcore_table[i].inst == (inst & imsk[mcore_table[i].opclass]))
      break;

  if (i == ARRAY_SIZE (mcore_table))
    (*print_func) (stream, ".short 0x%04x", inst);
  else
    {
      const char *name = grname[inst & 0x0F];

      (*print_func) (stream, "%s", mcore_table[i].name);

      switch (mcore_table[i].opclass)
	{
	case O0:
	  break;

	case OT:
	  (*print_func) (stream, "\t%d", inst & 0x3);
	  break;

	case O1:
	case JMP:
	case JSR:
	  (*print_func) (stream, "\t%s", name);
	  break;

	case OC:
	  (*print_func) (stream, "\t%s, %s", name, crname[(inst >> 4) & 0x1F]);
	  break;

	case O1R1:
	  (*print_func) (stream, "\t%s, r1", name);
	  break;

	case MULSH:
	case O2:
	  (*print_func) (stream, "\t%s, %s", name, grname[(inst >> 4) & 0xF]);
	  break;

	case X1:
	  (*print_func) (stream, "\tr1, %s", name);
	  break;

	case OI:
	  (*print_func) (stream, "\t%s, %d", name, ((inst >> 4) & 0x1F) + 1);
	  break;

	case RM:
	  (*print_func) (stream, "\t%s-r15, (r0)", name);
	  break;

	case RQ:
	  (*print_func) (stream, "\tr4-r7, (%s)", name);
	  break;

	case OB:
	case OBRa:
	case OBRb:
	case OBRc:
	case SI:
	case SIa:
	case OMa:
	case OMb:
	case OMc:
	  (*print_func) (stream, "\t%s, %d", name, (inst >> 4) & 0x1F);
	  break;

	case I7:
	  (*print_func) (stream, "\t%s, %d", name, (inst >> 4) & 0x7F);
	  break;

	case LS:
	  (*print_func) (stream, "\t%s, (%s, %d)", grname[(inst >> 8) & 0xF],
			 name, ((inst >> 4) & 0xF) << isiz[(inst >> 13) & 3]);
	  break;

	case BR:
	  {
	    uint32_t val = ((inst & 0x3FF) ^ 0x400) - 0x400;

	    val = memaddr + 2 + (val << 1);
	    (*print_func) (stream, "\t0x%x", val);

	    if (strcmp (mcore_table[i].name, "bsr") == 0)
	      {
		/* For bsr, we'll try to get a symbol for the target.  */
		if (info->print_address_func && val != 0)
		  {
		    (*print_func) (stream, "\t// ");
		    info->print_address_func (val, info);
		  }
	      }
	  }
	  break;

	case BL:
	  {
	    uint32_t val = memaddr + 2 + ((inst | ~0xF) << 1);

	    (*print_func) (stream, "\t%s, 0x%x",
			   grname[(inst >> 4) & 0xF], val);
	  }
	  break;

	case LR:
	  {
	    uint32_t val;

	    val = (memaddr + 2 + ((inst & 0xFF) << 2)) & ~3;

	    /* We are not reading an instruction, so allow
	       reads to extend beyond the next symbol.  */
	    info->stop_vma = 0;
	    status = info->read_memory_func (val, ibytes, 4, info);
	    if (status != 0)
	      {
		info->memory_error_func (status, memaddr, info);
		break;
	      }

	    if (info->endian == BFD_ENDIAN_LITTLE)
	      val = (((unsigned) ibytes[3] << 24) | (ibytes[2] << 16)
		     | (ibytes[1] << 8) | (ibytes[0]));
	    else
	      val = (((unsigned) ibytes[0] << 24) | (ibytes[1] << 16)
		     | (ibytes[2] << 8) | (ibytes[3]));

	    /* Removed [] around literal value to match ABI syntax 12/95.  */
	    (*print_func) (stream, "\t%s, 0x%X", grname[(inst >> 8) & 0xF], val);

	    if (val == 0)
	      (*print_func) (stream, "\t// from address pool at 0x%x",
			     (uint32_t) (memaddr + 2
					 + ((inst & 0xFF) << 2)) & ~3);
	  }
	  break;

	case LJ:
	  {
	    uint32_t val;

	    val = (memaddr + 2 + ((inst & 0xFF) << 2)) & ~3;

	    /* We are not reading an instruction, so allow
	       reads to extend beyond the next symbol.  */
	    info->stop_vma = 0;
	    status = info->read_memory_func (val, ibytes, 4, info);
	    if (status != 0)
	      {
		info->memory_error_func (status, memaddr, info);
		break;
	      }

	    if (info->endian == BFD_ENDIAN_LITTLE)
	      val = (((unsigned) ibytes[3] << 24) | (ibytes[2] << 16)
		     | (ibytes[1] << 8) | (ibytes[0]));
	    else
	      val = (((unsigned) ibytes[0] << 24) | (ibytes[1] << 16)
		     | (ibytes[2] << 8) | (ibytes[3]));

	    /* Removed [] around literal value to match ABI syntax 12/95.  */
	    (*print_func) (stream, "\t0x%X", val);
	    /* For jmpi/jsri, we'll try to get a symbol for the target.  */
	    if (info->print_address_func && val != 0)
	      {
		(*print_func) (stream, "\t// ");
		info->print_address_func (val, info);
	      }
	    else
	      {
		(*print_func) (stream, "\t// from address pool at 0x%x",
			       (uint32_t) (memaddr + 2
					   + ((inst & 0xFF) << 2)) & ~3);
	      }
	  }
	  break;

	case OPSR:
	  {
	    static char *fields[] = {
	      "af", "ie",    "fe",    "fe,ie",
	      "ee", "ee,ie", "ee,fe", "ee,fe,ie"
	    };

	    (*print_func) (stream, "\t%s", fields[inst & 0x7]);
	  }
	  break;

	default:
	  /* If the disassembler lags the instruction set.  */
	  (*print_func) (stream, "\tundecoded operands, inst is 0x%04x", inst);
	  break;
	}
    }

  /* Say how many bytes we consumed.  */
  return 2;
}
