/* OpenRISC exception, interrupts, syscall and trap support
   Copyright (C) 2017-2021 Free Software Foundation, Inc.

   This file is part of GDB, the GNU debugger.

   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_OR1K32BF
#define WANT_CPU

#include "sim-main.h"
#include "cgen-ops.h"

/* Implement the sim invalid instruction function.  This will set the error
   effective address to that of the invalid instruction then call the
   exception handler.  */

SEM_PC
sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
{
  SET_H_SYS_EEAR0 (cia);

#ifdef WANT_CPU_OR1K32BF
  or1k32bf_exception (current_cpu, cia, EXCEPT_ILLEGAL);
#endif

  return vpc;
}

/* Generate the appropriate OpenRISC fpu exception based on the status code from
   the sim fpu.  */
void
or1k32bf_fpu_error (CGEN_FPU* fpu, int status)
{
  SIM_CPU *current_cpu = (SIM_CPU *)fpu->owner;

  /* If floating point exceptions are enabled.  */
  if (GET_H_SYS_FPCSR_FPEE() != 0)
    {
      /* Set all of the status flag bits.  */
      if (status
	  & (sim_fpu_status_invalid_snan
	     | sim_fpu_status_invalid_qnan
	     | sim_fpu_status_invalid_isi
	     | sim_fpu_status_invalid_idi
	     | sim_fpu_status_invalid_zdz
	     | sim_fpu_status_invalid_imz
	     | sim_fpu_status_invalid_cvi
	     | sim_fpu_status_invalid_cmp
	     | sim_fpu_status_invalid_sqrt))
	SET_H_SYS_FPCSR_IVF (1);

      if (status & sim_fpu_status_invalid_snan)
	SET_H_SYS_FPCSR_SNF (1);

      if (status & sim_fpu_status_invalid_qnan)
	SET_H_SYS_FPCSR_QNF (1);

      if (status & sim_fpu_status_overflow)
	SET_H_SYS_FPCSR_OVF (1);

      if (status & sim_fpu_status_underflow)
	SET_H_SYS_FPCSR_UNF (1);

      if (status
	  & (sim_fpu_status_invalid_isi
	     | sim_fpu_status_invalid_idi))
	SET_H_SYS_FPCSR_INF (1);

      if (status & sim_fpu_status_invalid_div0)
	SET_H_SYS_FPCSR_DZF (1);

      if (status & sim_fpu_status_inexact)
	SET_H_SYS_FPCSR_IXF (1);

      /* If any of the exception bits were actually set.  */
      if (GET_H_SYS_FPCSR()
	  & (SPR_FIELD_MASK_SYS_FPCSR_IVF
	     | SPR_FIELD_MASK_SYS_FPCSR_SNF
	     | SPR_FIELD_MASK_SYS_FPCSR_QNF
	     | SPR_FIELD_MASK_SYS_FPCSR_OVF
	     | SPR_FIELD_MASK_SYS_FPCSR_UNF
	     | SPR_FIELD_MASK_SYS_FPCSR_INF
	     | SPR_FIELD_MASK_SYS_FPCSR_DZF
	     | SPR_FIELD_MASK_SYS_FPCSR_IXF))
	{
	  SIM_DESC sd = CPU_STATE (current_cpu);

	  /* If the sim is running in fast mode, i.e. not profiling,
	     per-instruction callbacks are not triggered which would allow
	     us to track the PC.  This means we cannot track which
	     instruction caused the FPU error.  */
	  if (STATE_RUN_FAST_P (sd) == 1)
	    sim_io_eprintf
	      (sd, "WARNING: ignoring fpu error caught in fast mode.\n");
	  else
	    or1k32bf_exception (current_cpu, GET_H_SYS_PPC (), EXCEPT_FPE);
	}
    }
}


/* Implement the OpenRISC exception function.  This is mostly used by the
   CGEN generated files.  For example, this is used when handling a
   overflow exception during a multiplication instruction. */

void
or1k32bf_exception (sim_cpu *current_cpu, USI pc, USI exnum)
{
  SIM_DESC sd = CPU_STATE (current_cpu);

  if (exnum == EXCEPT_TRAP)
    {
      /* Trap, used for breakpoints, sends control back to gdb breakpoint
	 handling.  */
      sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
    }
  else
    {

      /* Calculate the exception program counter.  */
      switch (exnum)
	{
	case EXCEPT_RESET:
	  break;

	case EXCEPT_FPE:
	case EXCEPT_SYSCALL:
	  SET_H_SYS_EPCR0 (pc + 4 - (current_cpu->delay_slot ? 4 : 0));
	  break;

	case EXCEPT_BUSERR:
	case EXCEPT_ALIGN:
	case EXCEPT_ILLEGAL:
	case EXCEPT_RANGE:
	  SET_H_SYS_EPCR0 (pc - (current_cpu->delay_slot ? 4 : 0));
	  break;

	default:
	  sim_io_error (sd, "unexpected exception 0x%x raised at PC 0x%08x",
			exnum, pc);
	  break;
	}

      /* Store the current SR into ESR0.  */
      SET_H_SYS_ESR0 (GET_H_SYS_SR ());

      /* Indicate in SR if the failed instruction is in delay slot or not.  */
      SET_H_SYS_SR_DSX (current_cpu->delay_slot);

      current_cpu->next_delay_slot = 0;

      /* Jump program counter into handler.  */
      IADDR handler_pc =
	(GET_H_SYS_SR_EPH ()? 0xf0000000 : 0x00000000) + (exnum << 8);

      sim_engine_restart (sd, current_cpu, NULL, handler_pc);
    }
}

/* Implement the return from exception instruction.  This is used to return
   the CPU to its previous state from within an exception handler.  */

void
or1k32bf_rfe (sim_cpu *current_cpu)
{
  SET_H_SYS_SR (GET_H_SYS_ESR0 ());
  SET_H_SYS_SR_FO (1);

  current_cpu->next_delay_slot = 0;

  sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL,
		      GET_H_SYS_EPCR0 ());
}

/* Implement the move from SPR instruction.  This is used to read from the
   CPU's special purpose registers.  */

USI
or1k32bf_mfspr (sim_cpu *current_cpu, USI addr)
{
  SIM_DESC sd = CPU_STATE (current_cpu);

  if (!GET_H_SYS_SR_SM () && !GET_H_SYS_SR_SUMRA ())
    {
      sim_io_eprintf (sd, "WARNING: l.mfspr in user mode (SR 0x%x)\n",
		      GET_H_SYS_SR ());
      return 0;
    }

  if (addr >= NUM_SPR)
    goto bad_address;

  SI val = GET_H_SPR (addr);

  switch (addr)
    {

    case SPR_ADDR (SYS, VR):
    case SPR_ADDR (SYS, UPR):
    case SPR_ADDR (SYS, CPUCFGR):
    case SPR_ADDR (SYS, SR):
    case SPR_ADDR (SYS, PPC):
    case SPR_ADDR (SYS, FPCSR):
    case SPR_ADDR (SYS, EPCR0):
    case SPR_ADDR (MAC, MACLO):
    case SPR_ADDR (MAC, MACHI):
      break;

    default:
      if (addr < SPR_ADDR (SYS, GPR0) || addr > SPR_ADDR (SYS, GPR511))
	goto bad_address;
      break;

    }

  return val;

bad_address:
  sim_io_eprintf (sd, "WARNING: l.mfspr with invalid SPR address 0x%x\n", addr);
  return 0;

}

/* Implement the move to SPR instruction.  This is used to write too the
   CPU's special purpose registers.  */

void
or1k32bf_mtspr (sim_cpu *current_cpu, USI addr, USI val)
{
  SIM_DESC sd = CPU_STATE (current_cpu);

  if (!GET_H_SYS_SR_SM () && !GET_H_SYS_SR_SUMRA ())
    {
      sim_io_eprintf
	(sd, "WARNING: l.mtspr with address 0x%x in user mode (SR 0x%x)\n",
	 addr, GET_H_SYS_SR ());
      return;
    }

  if (addr >= NUM_SPR)
    goto bad_address;

  switch (addr)
    {

    case SPR_ADDR (SYS, FPCSR):
    case SPR_ADDR (SYS, EPCR0):
    case SPR_ADDR (SYS, ESR0):
    case SPR_ADDR (MAC, MACHI):
    case SPR_ADDR (MAC, MACLO):
      SET_H_SPR (addr, val);
      break;

    case SPR_ADDR (SYS, SR):
      SET_H_SPR (addr, val);
      SET_H_SYS_SR_FO (1);
      break;

    case SPR_ADDR (SYS, NPC):
      current_cpu->next_delay_slot = 0;

      sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, val);
      break;

    case SPR_ADDR (TICK, TTMR):
      /* Allow some registers to be silently cleared.  */
      if (val != 0)
	sim_io_eprintf
	  (sd, "WARNING: l.mtspr to SPR address 0x%x with invalid value 0x%x\n",
	   addr, val);
      break;

    default:
      if (addr >= SPR_ADDR (SYS, GPR0) && addr <= SPR_ADDR (SYS, GPR511))
	SET_H_SPR (addr, val);
      else
	goto bad_address;
      break;

    }

  return;

bad_address:
  sim_io_eprintf (sd, "WARNING: l.mtspr with invalid SPR address 0x%x\n", addr);

}
