/* This must come before any other includes.  */
#include "defs.h"

#include "sim-main.h"
#include "sim-options.h"
#include "v850_sim.h"
#include "sim-assert.h"
#include "itable.h"

#include <stdlib.h>
#include <string.h>

#include "bfd.h"

#include "target-newlib-syscall.h"

static const char * get_insn_name (sim_cpu *, int);

/* For compatibility.  */
SIM_DESC simulator;

/* V850 interrupt model.  */

enum interrupt_type
{
  int_reset,
  int_nmi,
  int_intov1,
  int_intp10,
  int_intp11,
  int_intp12,
  int_intp13,
  int_intcm4,
  num_int_types
};

const char *interrupt_names[] =
{
  "reset",
  "nmi",
  "intov1",
  "intp10",
  "intp11",
  "intp12",
  "intp13",
  "intcm4",
  NULL
};

static void
do_interrupt (SIM_DESC sd, void *data)
{
  const char **interrupt_name = (const char**)data;
  enum interrupt_type inttype;
  inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);

  /* For a hardware reset, drop everything and jump to the start
     address */
  if (inttype == int_reset)
    {
      PC = 0;
      PSW = 0x20;
      ECR = 0;
      sim_engine_restart (sd, NULL, NULL, NULL_CIA);
    }

  /* Deliver an NMI when allowed */
  if (inttype == int_nmi)
    {
      if (PSW & PSW_NP)
	{
	  /* We're already working on an NMI, so this one must wait
	     around until the previous one is done.  The processor
	     ignores subsequent NMIs, so we don't need to count them.
	     Just keep re-scheduling a single NMI until it manages to
	     be delivered */
	  if (STATE_CPU (sd, 0)->pending_nmi != NULL)
	    sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
	  STATE_CPU (sd, 0)->pending_nmi =
	    sim_events_schedule (sd, 1, do_interrupt, data);
	  return;
	}
      else
	{
	  /* NMI can be delivered.  Do not deschedule pending_nmi as
             that, if still in the event queue, is a second NMI that
             needs to be delivered later. */
	  FEPC = PC;
	  FEPSW = PSW;
	  /* Set the FECC part of the ECR. */
	  ECR &= 0x0000ffff;
	  ECR |= 0x10;
	  PSW |= PSW_NP;
	  PSW &= ~PSW_EP;
	  PSW |= PSW_ID;
	  PC = 0x10;
	  sim_engine_restart (sd, NULL, NULL, NULL_CIA);
	}
    }

  /* deliver maskable interrupt when allowed */
  if (inttype > int_nmi && inttype < num_int_types)
    {
      if ((PSW & PSW_NP) || (PSW & PSW_ID))
	{
	  /* Can't deliver this interrupt, reschedule it for later */
	  sim_events_schedule (sd, 1, do_interrupt, data);
	  return;
	}
      else
	{
	  /* save context */
	  EIPC = PC;
	  EIPSW = PSW;
	  /* Disable further interrupts.  */
	  PSW |= PSW_ID;
	  /* Indicate that we're doing interrupt not exception processing.  */
	  PSW &= ~PSW_EP;
	  /* Clear the EICC part of the ECR, will set below. */
	  ECR &= 0xffff0000;
	  switch (inttype)
	    {
	    case int_intov1:
	      PC = 0x80;
	      ECR |= 0x80;
	      break;
	    case int_intp10:
	      PC = 0x90;
	      ECR |= 0x90;
	      break;
	    case int_intp11:
	      PC = 0xa0;
	      ECR |= 0xa0;
	      break;
	    case int_intp12:
	      PC = 0xb0;
	      ECR |= 0xb0;
	      break;
	    case int_intp13:
	      PC = 0xc0;
	      ECR |= 0xc0;
	      break;
	    case int_intcm4:
	      PC = 0xd0;
	      ECR |= 0xd0;
	      break;
	    default:
	      /* Should never be possible.  */
	      sim_engine_abort (sd, NULL, NULL_CIA,
				"do_interrupt - internal error - bad switch");
	      break;
	    }
	}
      sim_engine_restart (sd, NULL, NULL, NULL_CIA);
    }
  
  /* some other interrupt? */
  sim_engine_abort (sd, NULL, NULL_CIA,
		    "do_interrupt - internal error - interrupt %d unknown",
		    inttype);
}

/* Return name of an insn, used by insn profiling.  */

static const char *
get_insn_name (sim_cpu *cpu, int i)
{
  return itable[i].name;
}

/* These default values correspond to expected usage for the chip.  */

uint32_t OP[4];

static sim_cia
v850_pc_get (sim_cpu *cpu)
{
  return PC;
}

static void
v850_pc_set (sim_cpu *cpu, sim_cia pc)
{
  PC = pc;
}

static int v850_reg_fetch (SIM_CPU *, int, void *, int);
static int v850_reg_store (SIM_CPU *, int, const void *, int);

SIM_DESC
sim_open (SIM_OPEN_KIND    kind,
	  host_callback *  cb,
	  struct bfd *     abfd,
	  char * const *   argv)
{
  int i;
  SIM_DESC sd = sim_state_alloc (kind, cb);
  int mach;

  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);

  /* Set default options before parsing user options.  */
  current_target_byte_order = BFD_ENDIAN_LITTLE;
  cb->syscall_map = cb_v850_syscall_map;

  /* The cpu data is kept in a separately allocated chunk of memory.  */
  if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
    return 0;

  /* for compatibility */
  simulator = sd;

  /* FIXME: should be better way of setting up interrupts */
  STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
  STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;

  /* Initialize the mechanism for doing insn profiling.  */
  CPU_INSN_NAME (STATE_CPU (sd, 0)) = get_insn_name;
  CPU_MAX_INSNS (STATE_CPU (sd, 0)) = nr_itable_entries;

  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
    return 0;

  /* Allocate core managed memory */

  /* "Mirror" the ROM addresses below 1MB. */
  sim_do_commandf (sd, "memory region 0,0x100000,0x%x", V850_ROM_SIZE);
  /* Chunk of ram adjacent to rom */
  sim_do_commandf (sd, "memory region 0x100000,0x%x", V850_LOW_END-0x100000);
  /* peripheral I/O region - mirror 1K across 4k (0x1000) */
  sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
  /* similarly if in the internal RAM region */
  sim_do_command (sd, "memory region 0xffe000,0x1000,1024");

  /* The parser will print an error message for us, so we silently return.  */
  if (sim_parse_args (sd, argv) != SIM_RC_OK)
    {
      /* Uninstall the modules to avoid memory leaks,
	 file descriptor leaks, etc.  */
      sim_module_uninstall (sd);
      return 0;
    }

  /* check for/establish the a reference program image */
  if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
    {
      sim_module_uninstall (sd);
      return 0;
    }

  /* establish any remaining configuration options */
  if (sim_config (sd) != SIM_RC_OK)
    {
      sim_module_uninstall (sd);
      return 0;
    }

  if (sim_post_argv_init (sd) != SIM_RC_OK)
    {
      /* Uninstall the modules to avoid memory leaks,
	 file descriptor leaks, etc.  */
      sim_module_uninstall (sd);
      return 0;
    }


  /* determine the machine type */
  if (STATE_ARCHITECTURE (sd) != NULL
      && (STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850
	  || STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850_rh850))
    mach = STATE_ARCHITECTURE (sd)->mach;
  else
    mach = bfd_mach_v850; /* default */

  /* set machine specific configuration */
  switch (mach)
    {
    case bfd_mach_v850:
    case bfd_mach_v850e:
    case bfd_mach_v850e1:
    case bfd_mach_v850e2:
    case bfd_mach_v850e2v3:
    case bfd_mach_v850e3v5:
      STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT
				     | PSW_CY | PSW_OV | PSW_S | PSW_Z);
      break;
    }

  /* CPU specific initialization.  */
  for (i = 0; i < MAX_NR_PROCESSORS; ++i)
    {
      SIM_CPU *cpu = STATE_CPU (sd, i);

      CPU_REG_FETCH (cpu) = v850_reg_fetch;
      CPU_REG_STORE (cpu) = v850_reg_store;
      CPU_PC_FETCH (cpu) = v850_pc_get;
      CPU_PC_STORE (cpu) = v850_pc_set;
    }

  return sd;
}

SIM_RC
sim_create_inferior (SIM_DESC      sd,
		     struct bfd *  prog_bfd,
		     char * const *argv,
		     char * const *env)
{
  memset (&State, 0, sizeof (State));
  if (prog_bfd != NULL)
    PC = bfd_get_start_address (prog_bfd);
  return SIM_RC_OK;
}

static int
v850_reg_fetch (SIM_CPU *cpu, int rn, void *memory, int length)
{
  *(uint32_t*)memory = H2T_4 (State.regs[rn]);
  return -1;
}

static int
v850_reg_store (SIM_CPU *cpu, int rn, const void *memory, int length)
{
  State.regs[rn] = T2H_4 (*(uint32_t *) memory);
  return length;
}
