OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-src/] [gdb-7.2/] [gdb-7.2-or32-1.0rc1/] [sim/] [lm32/] [traps.c] - Diff between revs 330 and 341

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 330 Rev 341
/* Lattice Mico32 exception and system call support.
/* Lattice Mico32 exception and system call support.
   Contributed by Jon Beniston <jon@beniston.com>
   Contributed by Jon Beniston <jon@beniston.com>
 
 
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#define WANT_CPU lm32bf
#define WANT_CPU lm32bf
#define WANT_CPU_LM32BF
#define WANT_CPU_LM32BF
 
 
#include "sim-main.h"
#include "sim-main.h"
#include "lm32-sim.h"
#include "lm32-sim.h"
#include "targ-vals.h"
#include "targ-vals.h"
 
 
/* Read memory function for system call interface.  */
/* Read memory function for system call interface.  */
 
 
static int
static int
syscall_read_mem (host_callback * cb, struct cb_syscall *sc,
syscall_read_mem (host_callback * cb, struct cb_syscall *sc,
                  unsigned long taddr, char *buf, int bytes)
                  unsigned long taddr, char *buf, int bytes)
{
{
  SIM_DESC sd = (SIM_DESC) sc->p1;
  SIM_DESC sd = (SIM_DESC) sc->p1;
  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
 
 
  return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
  return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
}
}
 
 
/* Write memory function for system call interface.  */
/* Write memory function for system call interface.  */
 
 
static int
static int
syscall_write_mem (host_callback * cb, struct cb_syscall *sc,
syscall_write_mem (host_callback * cb, struct cb_syscall *sc,
                   unsigned long taddr, const char *buf, int bytes)
                   unsigned long taddr, const char *buf, int bytes)
{
{
  SIM_DESC sd = (SIM_DESC) sc->p1;
  SIM_DESC sd = (SIM_DESC) sc->p1;
  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
 
 
  return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
  return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
}
}
 
 
/* Handle invalid instructions.  */
/* Handle invalid instructions.  */
 
 
SEM_PC
SEM_PC
sim_engine_invalid_insn (SIM_CPU * current_cpu, IADDR cia, SEM_PC pc)
sim_engine_invalid_insn (SIM_CPU * current_cpu, IADDR cia, SEM_PC pc)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
 
 
  sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
  sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
 
 
  return pc;
  return pc;
}
}
 
 
/* Handle divide instructions. */
/* Handle divide instructions. */
 
 
USI
USI
lm32bf_divu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2)
lm32bf_divu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);
  host_callback *cb = STATE_CALLBACK (sd);
 
 
  /* Check for divide by zero */
  /* Check for divide by zero */
  if (GET_H_GR (r1) == 0)
  if (GET_H_GR (r1) == 0)
    {
    {
      if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
      if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
        sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
        sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
      else
      else
        {
        {
          /* Save PC in exception address register.  */
          /* Save PC in exception address register.  */
          SET_H_GR (30, pc);
          SET_H_GR (30, pc);
          /* Save and clear interrupt enable.  */
          /* Save and clear interrupt enable.  */
          SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
          SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
          /* Branch to divide by zero exception handler.  */
          /* Branch to divide by zero exception handler.  */
          return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
          return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
        }
        }
    }
    }
  else
  else
    {
    {
      SET_H_GR (r2, (USI) GET_H_GR (r0) / (USI) GET_H_GR (r1));
      SET_H_GR (r2, (USI) GET_H_GR (r0) / (USI) GET_H_GR (r1));
      return pc + 4;
      return pc + 4;
    }
    }
}
}
 
 
USI
USI
lm32bf_modu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2)
lm32bf_modu_insn (SIM_CPU * current_cpu, IADDR pc, USI r0, USI r1, USI r2)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);
  host_callback *cb = STATE_CALLBACK (sd);
 
 
  /* Check for divide by zero.  */
  /* Check for divide by zero.  */
  if (GET_H_GR (r1) == 0)
  if (GET_H_GR (r1) == 0)
    {
    {
      if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
      if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
        sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
        sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGFPE);
      else
      else
        {
        {
          /* Save PC in exception address register.  */
          /* Save PC in exception address register.  */
          SET_H_GR (30, pc);
          SET_H_GR (30, pc);
          /* Save and clear interrupt enable.  */
          /* Save and clear interrupt enable.  */
          SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
          SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
          /* Branch to divide by zero exception handler.  */
          /* Branch to divide by zero exception handler.  */
          return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
          return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_DIVIDE_BY_ZERO * 32;
        }
        }
    }
    }
  else
  else
    {
    {
      SET_H_GR (r2, (USI) GET_H_GR (r0) % (USI) GET_H_GR (r1));
      SET_H_GR (r2, (USI) GET_H_GR (r0) % (USI) GET_H_GR (r1));
      return pc + 4;
      return pc + 4;
    }
    }
}
}
 
 
/* Handle break instructions.  */
/* Handle break instructions.  */
 
 
USI
USI
lm32bf_break_insn (SIM_CPU * current_cpu, IADDR pc)
lm32bf_break_insn (SIM_CPU * current_cpu, IADDR pc)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);
  host_callback *cb = STATE_CALLBACK (sd);
  /* Breakpoint.  */
  /* Breakpoint.  */
  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
  if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
    {
    {
      sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
      sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP);
      return pc;
      return pc;
    }
    }
  else
  else
    {
    {
      /* Save PC in breakpoint address register.  */
      /* Save PC in breakpoint address register.  */
      SET_H_GR (31, pc);
      SET_H_GR (31, pc);
      /* Save and clear interrupt enable.  */
      /* Save and clear interrupt enable.  */
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 2);
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 2);
      /* Branch to breakpoint exception handler.  */
      /* Branch to breakpoint exception handler.  */
      return GET_H_CSR (LM32_CSR_DEBA) + LM32_EID_BREAKPOINT * 32;
      return GET_H_CSR (LM32_CSR_DEBA) + LM32_EID_BREAKPOINT * 32;
    }
    }
}
}
 
 
/* Handle scall instructions.  */
/* Handle scall instructions.  */
 
 
USI
USI
lm32bf_scall_insn (SIM_CPU * current_cpu, IADDR pc)
lm32bf_scall_insn (SIM_CPU * current_cpu, IADDR pc)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);
  host_callback *cb = STATE_CALLBACK (sd);
 
 
  if ((STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
  if ((STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT)
      || (GET_H_GR (8) == TARGET_SYS_exit))
      || (GET_H_GR (8) == TARGET_SYS_exit))
    {
    {
      /* Delegate system call to host O/S.  */
      /* Delegate system call to host O/S.  */
      CB_SYSCALL s;
      CB_SYSCALL s;
      CB_SYSCALL_INIT (&s);
      CB_SYSCALL_INIT (&s);
      s.p1 = (PTR) sd;
      s.p1 = (PTR) sd;
      s.p2 = (PTR) current_cpu;
      s.p2 = (PTR) current_cpu;
      s.read_mem = syscall_read_mem;
      s.read_mem = syscall_read_mem;
      s.write_mem = syscall_write_mem;
      s.write_mem = syscall_write_mem;
      /* Extract parameters.  */
      /* Extract parameters.  */
      s.func = GET_H_GR (8);
      s.func = GET_H_GR (8);
      s.arg1 = GET_H_GR (1);
      s.arg1 = GET_H_GR (1);
      s.arg2 = GET_H_GR (2);
      s.arg2 = GET_H_GR (2);
      s.arg3 = GET_H_GR (3);
      s.arg3 = GET_H_GR (3);
      /* Halt the simulator if the requested system call is _exit.  */
      /* Halt the simulator if the requested system call is _exit.  */
      if (s.func == TARGET_SYS_exit)
      if (s.func == TARGET_SYS_exit)
        sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
        sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1);
      /* Perform the system call.  */
      /* Perform the system call.  */
      cb_syscall (cb, &s);
      cb_syscall (cb, &s);
      /* Store the return value in the CPU's registers.  */
      /* Store the return value in the CPU's registers.  */
      SET_H_GR (1, s.result);
      SET_H_GR (1, s.result);
      SET_H_GR (2, s.result2);
      SET_H_GR (2, s.result2);
      SET_H_GR (3, s.errcode);
      SET_H_GR (3, s.errcode);
      /* Skip over scall instruction.  */
      /* Skip over scall instruction.  */
      return pc + 4;
      return pc + 4;
    }
    }
  else
  else
    {
    {
      /* Save PC in exception address register.  */
      /* Save PC in exception address register.  */
      SET_H_GR (30, pc);
      SET_H_GR (30, pc);
      /* Save and clear interrupt enable */
      /* Save and clear interrupt enable */
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
      /* Branch to system call exception handler.  */
      /* Branch to system call exception handler.  */
      return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_SYSTEM_CALL * 32;
      return GET_H_CSR (LM32_CSR_EBA) + LM32_EID_SYSTEM_CALL * 32;
    }
    }
}
}
 
 
/* Handle b instructions.  */
/* Handle b instructions.  */
 
 
USI
USI
lm32bf_b_insn (SIM_CPU * current_cpu, USI r0, USI f_r0)
lm32bf_b_insn (SIM_CPU * current_cpu, USI r0, USI f_r0)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);
  host_callback *cb = STATE_CALLBACK (sd);
 
 
  /* Restore interrupt enable.  */
  /* Restore interrupt enable.  */
  if (f_r0 == 30)
  if (f_r0 == 30)
    SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 2) >> 1);
    SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 2) >> 1);
  else if (f_r0 == 31)
  else if (f_r0 == 31)
    SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 4) >> 2);
    SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 4) >> 2);
  return r0;
  return r0;
}
}
 
 
/* Handle wcsr instructions.  */
/* Handle wcsr instructions.  */
 
 
void
void
lm32bf_wcsr_insn (SIM_CPU * current_cpu, USI f_csr, USI r1)
lm32bf_wcsr_insn (SIM_CPU * current_cpu, USI f_csr, USI r1)
{
{
  SIM_DESC sd = CPU_STATE (current_cpu);
  SIM_DESC sd = CPU_STATE (current_cpu);
  host_callback *cb = STATE_CALLBACK (sd);
  host_callback *cb = STATE_CALLBACK (sd);
 
 
  /* Writing a 1 to IP CSR clears a bit, writing 0 has no effect.  */
  /* Writing a 1 to IP CSR clears a bit, writing 0 has no effect.  */
  if (f_csr == LM32_CSR_IP)
  if (f_csr == LM32_CSR_IP)
    SET_H_CSR (f_csr, GET_H_CSR (f_csr) & ~r1);
    SET_H_CSR (f_csr, GET_H_CSR (f_csr) & ~r1);
  else
  else
    SET_H_CSR (f_csr, r1);
    SET_H_CSR (f_csr, r1);
}
}
 
 
/* Handle signals.  */
/* Handle signals.  */
 
 
void
void
lm32_core_signal (SIM_DESC sd,
lm32_core_signal (SIM_DESC sd,
                  sim_cpu * cpu,
                  sim_cpu * cpu,
                  sim_cia cia,
                  sim_cia cia,
                  unsigned map,
                  unsigned map,
                  int nr_bytes,
                  int nr_bytes,
                  address_word addr,
                  address_word addr,
                  transfer_type transfer, sim_core_signals sig)
                  transfer_type transfer, sim_core_signals sig)
{
{
  const char *copy = (transfer == read_transfer ? "read" : "write");
  const char *copy = (transfer == read_transfer ? "read" : "write");
  address_word ip = CIA_ADDR (cia);
  address_word ip = CIA_ADDR (cia);
  SIM_CPU *current_cpu = cpu;
  SIM_CPU *current_cpu = cpu;
 
 
  switch (sig)
  switch (sig)
    {
    {
    case sim_core_unmapped_signal:
    case sim_core_unmapped_signal:
      sim_io_eprintf (sd,
      sim_io_eprintf (sd,
                      "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
                      "core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
                      nr_bytes, copy, (unsigned long) addr,
                      nr_bytes, copy, (unsigned long) addr,
                      (unsigned long) ip);
                      (unsigned long) ip);
      SET_H_GR (30, ip);
      SET_H_GR (30, ip);
      /* Save and clear interrupt enable.  */
      /* Save and clear interrupt enable.  */
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
      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);
      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_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32,
                       sim_stopped, SIM_SIGSEGV);
                       sim_stopped, SIM_SIGSEGV);
      break;
      break;
    case sim_core_unaligned_signal:
    case sim_core_unaligned_signal:
      sim_io_eprintf (sd,
      sim_io_eprintf (sd,
                      "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n",
                      "core: %d byte misaligned %s to address 0x%lx at 0x%lx\n",
                      nr_bytes, copy, (unsigned long) addr,
                      nr_bytes, copy, (unsigned long) addr,
                      (unsigned long) ip);
                      (unsigned long) ip);
      SET_H_GR (30, ip);
      SET_H_GR (30, ip);
      /* Save and clear interrupt enable.  */
      /* Save and clear interrupt enable.  */
      SET_H_CSR (LM32_CSR_IE, (GET_H_CSR (LM32_CSR_IE) & 1) << 1);
      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);
      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_engine_halt (sd, cpu, NULL, LM32_EID_DATA_BUS_ERROR * 32,
                       sim_stopped, SIM_SIGBUS);
                       sim_stopped, SIM_SIGBUS);
      break;
      break;
    default:
    default:
      sim_engine_abort (sd, cpu, cia,
      sim_engine_abort (sd, cpu, cia,
                        "sim_core_signal - internal error - bad switch");
                        "sim_core_signal - internal error - bad switch");
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.