/* Lattice Mico32 exception and system call support.
   Contributed by Jon Beniston <jon@beniston.com>

   Copyright (C) 2009 Free Software Foundation, Inc.

   This file is part of GDB.

   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, see <http://www.gnu.org/licenses/>.  */

#define WANT_CPU lm32bf
#define WANT_CPU_LM32BF

#include "sim-main.h"
#include "lm32-sim.h"
#include "targ-vals.h"

/* Read memory function for system call interface.  */

static int
syscall_read_mem (host_callback * cb, struct cb_syscall *sc,
		  unsigned long taddr, char *buf, int bytes)
{
  SIM_DESC sd = (SIM_DESC) sc->p1;
  SIM_CPU *cpu = (SIM_CPU *) sc->p2;

  return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
}

/* Write memory function for system call interface.  */

static int
syscall_write_mem (host_callback * cb, struct cb_syscall *sc,
		   unsigned long taddr, const char *buf, int bytes)
{
  SIM_DESC sd = (SIM_DESC) sc->p1;
  SIM_CPU *cpu = (SIM_CPU *) sc->p2;

  return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
}

/* Handle invalid instructions.  */

SEM_PC
sim_engine_invalid_insn (SIM_CPU * current_cpu, IADDR cia, SEM_PC pc)
{
  SIM_DESC sd = CPU_STATE (current_cpu);

  sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);

  return pc;
}

/* Handle divide instructions. */

USI
lm32bf_divu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);

  /* Check for divide by zero */
  if (GET_H_GR (r1) == 0)
    {
      if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
	sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
      else
	{
	  /* Save PC in exception address register.  */
	  SET_H_GR (30, pc);
	  /* Save and clear interrupt enable.  */
	  SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
	  /* Branch to divide by zero exception handler.  */
	  return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
	}
    }
  else
    {
      SET_H_GR (r2, (USI) GET_H_GR (r0) / (USI) GET_H_GR (r1));
      return pc + 4;
    }
}

USI
lm32bf_modu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);

  /* Check for divide by zero.  */
  if (GET_H_GR (r1) == 0)
    {
      if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
	sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
      else
	{
	  /* Save PC in exception address register.  */
	  SET_H_GR (30, pc);
	  /* Save and clear interrupt enable.  */
	  SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
	  /* Branch to divide by zero exception handler.  */
	  return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
	}
    }
  else
    {
      SET_H_GR (r2, (USI) GET_H_GR (r0) % (USI) GET_H_GR (r1));
      return pc + 4;
    }
}

/* Handle break instructions.  */

USI
lm32bf_break_insn (SIM_CPU * current_cpu, IADDR pc)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);
  /* Breakpoint.  */
  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
    {
      sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
      return pc;
    }
  else
    {
      /* Save PC in breakpoint address register.  */
      SET_H_GR (31, pc);
      /* Save and clear interrupt enable.  */
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 2);
      /* Branch to breakpoint exception handler.  */
      return GET_H_CSR (LM32_CSR_DEBA) + LM32_EID_BREAKPOINT * 32;
    }
}

/* Handle scall instructions.  */

USI
lm32bf_scall_insn (SIM_CPU * current_cpu, IADDR pc)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);

  if ((STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
      || (GET_H_GR (8) == TARGET_SYS_exit))
    {
      /* Delegate system call to host O/S.  */
      CB_SYSCALL s;
      CB_SYSCALL_INIT (&s);
      s.p1 = (PTR) sd;
      s.p2 = (PTR) current_cpu;
      s.read_mem = syscall_read_mem;
      s.write_mem = syscall_write_mem;
      /* Extract parameters.  */
      s.func = GET_H_GR (8);
      s.arg1 = GET_H_GR (1);
      s.arg2 = GET_H_GR (2);
      s.arg3 = GET_H_GR (3);
      /* Halt the simulator if the requested system call is _exit.  */
      if (s.func == TARGET_SYS_exit)
	sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
      /* Perform the system call.  */
      cb_syscall (cb, &s);
      /* Store the return value in the CPU's registers.  */
      SET_H_GR (1, s.result);
      SET_H_GR (2, s.result2);
      SET_H_GR (3, s.errcode);
      /* Skip over scall instruction.  */
      return pc + 4;
    }
  else
    {
      /* Save PC in exception address register.  */
      SET_H_GR (30, pc);
      /* Save and clear interrupt enable */
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
      /* Branch to system call exception handler.  */
      return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_SYSTEM_CALL * 32;
    }
}

/* Handle b instructions.  */

USI
lm32bf_b_insn (SIM_CPU * current_cpu, USI r0, USI f_r0)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);

  /* Restore interrupt enable.  */
  if (f_r0 == 30)
    SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 2) >> 1);
  else if (f_r0 == 31)
    SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 4) >> 2);
  return r0;
}

/* Handle wcsr instructions.  */

void
lm32bf_wcsr_insn (SIM_CPU * current_cpu, USI f_csr, USI r1)
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);

  /* Writing a 1 to IP CSR clears a bit, writing 0 has no effect.  */
  if (f_csr == LM32_CSR_IP)
    SET_H_CSR (f_csr, GET_H_CSR (f_csr) & ~r1);
  else
    SET_H_CSR (f_csr, r1);
}

/* Handle signals.  */

void
lm32_core_signal (SIM_DESC sd,
		  sim_cpu * cpu,
		  sim_cia cia,
		  unsigned map,
		  int nr_bytes,
		  address_word addr,
		  transfer_type transfer, sim_core_signals sig)
{
  const char *copy = (transfer == read_transfer ? "read" : "write");
  address_word ip = CIA_ADDR (cia);
  SIM_CPU *current_cpu = cpu;

  switch (sig)
    {
    case sim_core_unmapped_signal:
      sim_io_eprintf (sd,
		      "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
		      nr_bytes, copy, (unsigned long) addr,
		      (unsigned long) ip);
      SET_H_GR (30, ip);
      /* Save and clear interrupt enable.  */
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
      CIA_SET (cpu, GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DATA_BUS_ERROR * 32);
      sim_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32,
		       sim_stopped, SIM_SIGSEGV);
      break;
    case sim_core_unaligned_signal:
      sim_io_eprintf (sd,
		      "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n",
		      nr_bytes, copy, (unsigned long) addr,
		      (unsigned long) ip);
      SET_H_GR (30, ip);
      /* Save and clear interrupt enable.  */
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
      CIA_SET (cpu, GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DATA_BUS_ERROR * 32);
      sim_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32,
		       sim_stopped, SIM_SIGBUS);
      break;
    default:
      sim_engine_abort (sd, cpu, cia,
			"sim_core_signal - internal error - bad switch");
    }
}
