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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [newlib-1.18.0/] [libgloss/] [sparc/] [erc32-stub.c] - Diff between revs 816 and 829

Only display areas with differences | Details | Blame | View Log

Rev 816 Rev 829
/*
/*
 * Copyright (c) 1996 Cygnus Support
 * Copyright (c) 1996 Cygnus Support
 *
 *
 * The authors hereby grant permission to use, copy, modify, distribute,
 * The authors hereby grant permission to use, copy, modify, distribute,
 * and license this software and its documentation for any purpose, provided
 * and license this software and its documentation for any purpose, provided
 * that existing copyright notices are retained in all copies and that this
 * that existing copyright notices are retained in all copies and that this
 * notice is included verbatim in any distributions. No written agreement,
 * notice is included verbatim in any distributions. No written agreement,
 * license, or royalty fee is required for any of the authorized uses.
 * license, or royalty fee is required for any of the authorized uses.
 * Modifications to this software may be copyrighted by their authors
 * Modifications to this software may be copyrighted by their authors
 * and need not follow the licensing terms described here, provided that
 * and need not follow the licensing terms described here, provided that
 * the new terms are clearly indicated on the first page of each file where
 * the new terms are clearly indicated on the first page of each file where
 * they apply.
 * they apply.
 */
 */
 
 
#include <string.h>
#include <string.h>
#include <signal.h>
#include <signal.h>
#include "debug.h"
#include "debug.h"
#include "asm.h"
#include "asm.h"
#include "slite.h"
#include "slite.h"
 
 
extern unsigned long rdtbr();
extern unsigned long rdtbr();
extern struct trap_entry fltr_proto;
extern struct trap_entry fltr_proto;
extern void trap_low();
extern void trap_low();
exception_t default_trap_hook = trap_low;
exception_t default_trap_hook = trap_low;
void target_reset();
void target_reset();
void flush_i_cache();
void flush_i_cache();
char *target_read_registers(unsigned long *);
char *target_read_registers(unsigned long *);
char *target_write_registers(unsigned long *);
char *target_write_registers(unsigned long *);
char *target_dump_state(unsigned long *);
char *target_dump_state(unsigned long *);
 
 
#define NUMREGS 72
#define NUMREGS 72
 
 
/* Number of bytes of registers.  */
/* Number of bytes of registers.  */
#define NUMREGBYTES (NUMREGS * 4)
#define NUMREGBYTES (NUMREGS * 4)
 
 
enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
                 O0, O1, O2, O3, O4, O5, SP, O7,
                 O0, O1, O2, O3, O4, O5, SP, O7,
                 L0, L1, L2, L3, L4, L5, L6, L7,
                 L0, L1, L2, L3, L4, L5, L6, L7,
                 I0, I1, I2, I3, I4, I5, FP, I7,
                 I0, I1, I2, I3, I4, I5, FP, I7,
 
 
                 F0, F1, F2, F3, F4, F5, F6, F7,
                 F0, F1, F2, F3, F4, F5, F6, F7,
                 F8, F9, F10, F11, F12, F13, F14, F15,
                 F8, F9, F10, F11, F12, F13, F14, F15,
                 F16, F17, F18, F19, F20, F21, F22, F23,
                 F16, F17, F18, F19, F20, F21, F22, F23,
                 F24, F25, F26, F27, F28, F29, F30, F31,
                 F24, F25, F26, F27, F28, F29, F30, F31,
                 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
                 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
 
 
/*
/*
 * Each entry in the trap vector occupies four words, typically a jump
 * Each entry in the trap vector occupies four words, typically a jump
 * to the processing routine.
 * to the processing routine.
 */
 */
struct trap_entry {
struct trap_entry {
  unsigned sethi_filler:10;
  unsigned sethi_filler:10;
  unsigned sethi_imm22:22;
  unsigned sethi_imm22:22;
  unsigned jmpl_filler:19;
  unsigned jmpl_filler:19;
  unsigned jmpl_simm13:13;
  unsigned jmpl_simm13:13;
  unsigned long filler[2];
  unsigned long filler[2];
};
};
 
 
/*
/*
 * This table contains the mapping between SPARC hardware trap types, and
 * This table contains the mapping between SPARC hardware trap types, and
 * signals, which are primarily what GDB understands.  It also indicates
 * signals, which are primarily what GDB understands.  It also indicates
 * which hardware traps we need to commandeer when initializing the stub.
 * which hardware traps we need to commandeer when initializing the stub.
 */
 */
struct trap_info hard_trap_info[] = {
struct trap_info hard_trap_info[] = {
  {1, SIGSEGV},                 /* instruction access error */
  {1, SIGSEGV},                 /* instruction access error */
  {2, SIGILL},                  /* privileged instruction */
  {2, SIGILL},                  /* privileged instruction */
  {3, SIGILL},                  /* illegal instruction */
  {3, SIGILL},                  /* illegal instruction */
  {4, SIGEMT},                  /* fp disabled */
  {4, SIGEMT},                  /* fp disabled */
  {36, SIGEMT},                 /* cp disabled */
  {36, SIGEMT},                 /* cp disabled */
  {7, SIGBUS},                  /* mem address not aligned */
  {7, SIGBUS},                  /* mem address not aligned */
  {9, SIGSEGV},                 /* data access exception */
  {9, SIGSEGV},                 /* data access exception */
  {10, SIGEMT},                 /* tag overflow */
  {10, SIGEMT},                 /* tag overflow */
  {128+1, SIGTRAP},             /* ta 1 - normal breakpoint instruction */
  {128+1, SIGTRAP},             /* ta 1 - normal breakpoint instruction */
  {0, 0}                  /* Must be last */
  {0, 0}                  /* Must be last */
};
};
 
 
extern struct trap_entry fltr_proto;
extern struct trap_entry fltr_proto;
void
void
exception_handler (int tt, unsigned long routine)
exception_handler (int tt, unsigned long routine)
{
{
  struct trap_entry *tb;        /* Trap vector base address */
  struct trap_entry *tb;        /* Trap vector base address */
 
 
  DEBUG (1, "Entering exception_handler()");
  DEBUG (1, "Entering exception_handler()");
  if (tt != 256) {
  if (tt != 256) {
    tb = (struct trap_entry *) (rdtbr() & ~0xfff);
    tb = (struct trap_entry *) (rdtbr() & ~0xfff);
  } else {
  } else {
    tt = 255;
    tt = 255;
    tb = (struct trap_entry *) 0;
    tb = (struct trap_entry *) 0;
  }
  }
 
 
  tb[tt] = fltr_proto;
  tb[tt] = fltr_proto;
 
 
  tb[tt].sethi_imm22 = routine >> 10;
  tb[tt].sethi_imm22 = routine >> 10;
  tb[tt].jmpl_simm13 = routine & 0x3ff;
  tb[tt].jmpl_simm13 = routine & 0x3ff;
 
 
  DEBUG (1, "Leaving exception_handler()");
  DEBUG (1, "Leaving exception_handler()");
}
}
 
 
/*
/*
 * This is so we can trap a memory fault when reading or writing
 * This is so we can trap a memory fault when reading or writing
 * directly to memory.
 * directly to memory.
 */
 */
void
void
set_mem_fault_trap(enable)
set_mem_fault_trap(enable)
     int enable;
     int enable;
{
{
  extern void fltr_set_mem_err();
  extern void fltr_set_mem_err();
 
 
  DEBUG (1, "Entering set_mem_fault_trap()");
  DEBUG (1, "Entering set_mem_fault_trap()");
 
 
  mem_err = 0;
  mem_err = 0;
 
 
  if (enable)
  if (enable)
    exception_handler(9, (unsigned long)fltr_set_mem_err);
    exception_handler(9, (unsigned long)fltr_set_mem_err);
  else
  else
    exception_handler(9, (unsigned long)trap_low);
    exception_handler(9, (unsigned long)trap_low);
 
 
  DEBUG (1, "Leaving set_mem_fault_trap()");
  DEBUG (1, "Leaving set_mem_fault_trap()");
}
}
 
 
/*
/*
 * This function does all command procesing for interfacing to gdb.  It
 * This function does all command procesing for interfacing to gdb.  It
 * returns 1 if you should skip the instruction at the trap address, 0
 * returns 1 if you should skip the instruction at the trap address, 0
 * otherwise.
 * otherwise.
 */
 */
extern void breakinst();
extern void breakinst();
 
 
void
void
handle_exception (registers)
handle_exception (registers)
     unsigned long *registers;
     unsigned long *registers;
{
{
  int sigval;
  int sigval;
 
 
  /* First, we must force all of the windows to be spilled out */
  /* First, we must force all of the windows to be spilled out */
 
 
  DEBUG (1, "Entering handle_exception()");
  DEBUG (1, "Entering handle_exception()");
 
 
/*  asm("mov %g0, %wim ; nop; nop; nop"); */
/*  asm("mov %g0, %wim ; nop; nop; nop"); */
  asm(" save %sp, -64, %sp      \n\
  asm(" save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        save %sp, -64, %sp      \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
        restore                 \n\
");
");
 
 
  if (registers[PC] == (unsigned long)breakinst) {
  if (registers[PC] == (unsigned long)breakinst) {
    registers[PC] = registers[NPC];
    registers[PC] = registers[NPC];
    registers[NPC] += 4;
    registers[NPC] += 4;
  }
  }
 
 
  /* get the last know signal number from the trap register */
  /* get the last know signal number from the trap register */
  sigval = computeSignal((registers[TBR] >> 4) & 0xff);
  sigval = computeSignal((registers[TBR] >> 4) & 0xff);
 
 
  /* call the main command processing loop for gdb */
  /* call the main command processing loop for gdb */
  gdb_event_loop (sigval, registers);
  gdb_event_loop (sigval, registers);
}
}
 
 
/*
/*
 * This function will generate a breakpoint exception.  It is used at the
 * This function will generate a breakpoint exception.  It is used at the
 * beginning of a program to sync up with a debugger and can be used
 * beginning of a program to sync up with a debugger and can be used
 * otherwise as a quick means to stop program execution and "break" into
 * otherwise as a quick means to stop program execution and "break" into
 * the debugger.
 * the debugger.
 */
 */
void
void
breakpoint()
breakpoint()
{
{
  DEBUG (1, "Entering breakpoint()");
  DEBUG (1, "Entering breakpoint()");
 
 
  if (!initialized)
  if (!initialized)
    return;
    return;
 
 
  asm(" .globl " STRINGSYM(breakinst) "         \n\
  asm(" .globl " STRINGSYM(breakinst) "         \n\
        " STRINGSYM(breakinst) ": ta 128+1      \n\
        " STRINGSYM(breakinst) ": ta 128+1      \n\
        nop                                     \n\
        nop                                     \n\
        nop                                     \n\
        nop                                     \n\
      ");
      ");
}
}
 
 
/*
/*
 * This is just a test vector for debugging excpetions.
 * This is just a test vector for debugging excpetions.
 */
 */
void
void
bad_trap(tt)
bad_trap(tt)
int tt;
int tt;
{
{
  print ("Got a bad trap #");
  print ("Got a bad trap #");
  outbyte (tt);
  outbyte (tt);
  outbyte ('\n');
  outbyte ('\n');
  asm("ta 0             \n\
  asm("ta 0             \n\
        nop             \n\
        nop             \n\
        nop             \n\
        nop             \n\
      ");
      ");
}
}
 
 
/*
/*
 * This is just a test vector for debugging excpetions.
 * This is just a test vector for debugging excpetions.
 */
 */
void
void
soft_trap(tt)
soft_trap(tt)
int tt;
int tt;
{
{
  print ("Got a soft trap #");
  print ("Got a soft trap #");
  outbyte (tt);
  outbyte (tt);
  outbyte ('\n');
  outbyte ('\n');
  asm("ta 0             \n\
  asm("ta 0             \n\
        nop             \n\
        nop             \n\
        nop             \n\
        nop             \n\
      ");
      ");
}
}
 
 
/*
/*
 * Flush the instruction cache.  We need to do this for the debugger stub so
 * Flush the instruction cache.  We need to do this for the debugger stub so
 * that breakpoints, et. al. become visible to the instruction stream after
 * that breakpoints, et. al. become visible to the instruction stream after
 * storing them in memory.
 * storing them in memory.
 *
 *
 * For the sparclite, we need to do something here, but for a standard
 * For the sparclite, we need to do something here, but for a standard
 * sparc (which SIS simulates), we don't.
 * sparc (which SIS simulates), we don't.
 */
 */
 
 
void
void
flush_i_cache ()
flush_i_cache ()
{
{
}
}
 
 
/*
/*
 * This will reset the processor, so we never return from here.
 * This will reset the processor, so we never return from here.
 */
 */
void
void
target_reset()
target_reset()
{
{
  asm ("call 0          \n\
  asm ("call 0          \n\
        nop ");
        nop ");
}
}
 
 
/*
/*
 * g - read registers.
 * g - read registers.
 *      no params.
 *      no params.
 *      returns a vector of words, size is NUM_REGS.
 *      returns a vector of words, size is NUM_REGS.
 */
 */
char *
char *
target_read_registers(unsigned long *registers)
target_read_registers(unsigned long *registers)
{
{
  char *ptr;
  char *ptr;
  unsigned long *sp;
  unsigned long *sp;
 
 
  DEBUG (1, "In target_read_registers()");
  DEBUG (1, "In target_read_registers()");
 
 
  ptr = packet_out_buf;
  ptr = packet_out_buf;
  ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
  ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */
  ptr = mem2hex((unsigned char *)(sp + 0), ptr, 16 * 4, 0); /* L & I regs */
  ptr = mem2hex((unsigned char *)(sp + 0), ptr, 16 * 4, 0); /* L & I regs */
  memset(ptr, '0', 32 * 8); /* Floating point */
  memset(ptr, '0', 32 * 8); /* Floating point */
  mem2hex((char *)&registers[Y],
  mem2hex((char *)&registers[Y],
          ptr + 32 * 4 * 2,
          ptr + 32 * 4 * 2,
          8 * 4,
          8 * 4,
          0);            /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
          0);            /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
  return (ptr);
  return (ptr);
}
}
 
 
/*
/*
 * G - write registers.
 * G - write registers.
 *      param is a vector of words, size is NUM_REGS.
 *      param is a vector of words, size is NUM_REGS.
 *      returns an OK or an error number.
 *      returns an OK or an error number.
 */
 */
char *
char *
target_write_registers(unsigned long *registers)
target_write_registers(unsigned long *registers)
{
{
  unsigned char *ptr;
  unsigned char *ptr;
  unsigned long *sp;
  unsigned long *sp;
  unsigned long *newsp, psr;
  unsigned long *newsp, psr;
 
 
  DEBUG (1, "In target_write_registers()");
  DEBUG (1, "In target_write_registers()");
 
 
  psr = registers[PSR];
  psr = registers[PSR];
 
 
  ptr = &packet_in_buf[1];
  ptr = &packet_in_buf[1];
 
 
  hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
  hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */
  hex2mem(ptr + 16 * 4 * 2, (unsigned char *)(sp + 0), 16 * 4, 0); /* L & I regs */
  hex2mem(ptr + 16 * 4 * 2, (unsigned char *)(sp + 0), 16 * 4, 0); /* L & I regs */
  hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
  hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y],
          8 * 4, 0);     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
          8 * 4, 0);     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
 
 
  /*
  /*
   * see if the stack pointer has moved.  If so, then copy the saved
   * see if the stack pointer has moved.  If so, then copy the saved
   * locals and ins to the new location.  This keeps the window
   * locals and ins to the new location.  This keeps the window
   * overflow and underflow routines happy.
   * overflow and underflow routines happy.
   */
   */
 
 
  newsp = (unsigned long *)registers[SP];
  newsp = (unsigned long *)registers[SP];
  if (sp != newsp)
  if (sp != newsp)
    sp = memcpy(newsp, sp, 16 * 4);
    sp = memcpy(newsp, sp, 16 * 4);
 
 
  /* Don't allow CWP to be modified. */
  /* Don't allow CWP to be modified. */
 
 
  if (psr != registers[PSR])
  if (psr != registers[PSR])
    registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
    registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
 
 
  return (ptr);
  return (ptr);
}
}
 
 
char *
char *
target_dump_state(unsigned long *registers)
target_dump_state(unsigned long *registers)
{
{
  int tt;                       /* Trap type */
  int tt;                       /* Trap type */
  int sigval;
  int sigval;
  char *ptr;
  char *ptr;
  unsigned long *sp;
  unsigned long *sp;
 
 
  DEBUG (1, "In target_dump_state()");
  DEBUG (1, "In target_dump_state()");
 
 
  sp = (unsigned long *)registers[SP];
  sp = (unsigned long *)registers[SP];
 
 
  tt = (registers[TBR] >> 4) & 0xff;
  tt = (registers[TBR] >> 4) & 0xff;
 
 
  /* reply to host that an exception has occurred */
  /* reply to host that an exception has occurred */
  sigval = computeSignal(tt);
  sigval = computeSignal(tt);
  ptr = packet_out_buf;
  ptr = packet_out_buf;
 
 
  *ptr++ = 'T';
  *ptr++ = 'T';
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval >> 4];
  *ptr++ = hexchars[sigval & 0xf];
  *ptr++ = hexchars[sigval & 0xf];
 
 
  *ptr++ = hexchars[PC >> 4];
  *ptr++ = hexchars[PC >> 4];
  *ptr++ = hexchars[PC & 0xf];
  *ptr++ = hexchars[PC & 0xf];
  *ptr++ = ':';
  *ptr++ = ':';
  ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);
  ptr = mem2hex((unsigned char *)&registers[PC], ptr, 4, 0);
  *ptr++ = ';';
  *ptr++ = ';';
 
 
  *ptr++ = hexchars[FP >> 4];
  *ptr++ = hexchars[FP >> 4];
  *ptr++ = hexchars[FP & 0xf];
  *ptr++ = hexchars[FP & 0xf];
  *ptr++ = ':';
  *ptr++ = ':';
  ptr = mem2hex((unsigned char *)(sp + 8 + 6), ptr, 4, 0); /* FP */
  ptr = mem2hex((unsigned char *)(sp + 8 + 6), ptr, 4, 0); /* FP */
  *ptr++ = ';';
  *ptr++ = ';';
 
 
  *ptr++ = hexchars[SP >> 4];
  *ptr++ = hexchars[SP >> 4];
  *ptr++ = hexchars[SP & 0xf];
  *ptr++ = hexchars[SP & 0xf];
  *ptr++ = ':';
  *ptr++ = ':';
  ptr = mem2hex((unsigned char *)&sp, ptr, 4, 0);
  ptr = mem2hex((unsigned char *)&sp, ptr, 4, 0);
  *ptr++ = ';';
  *ptr++ = ';';
 
 
  *ptr++ = hexchars[NPC >> 4];
  *ptr++ = hexchars[NPC >> 4];
 
 
  return (packet_out_buf);
  return (packet_out_buf);
}
}
 
 
void
void
write_pc(unsigned long *registers, unsigned long addr)
write_pc(unsigned long *registers, unsigned long addr)
{
{
  DEBUG (1, "In write_pc");
  DEBUG (1, "In write_pc");
 
 
  registers[PC] = addr;
  registers[PC] = addr;
  registers[NPC] = addr + 4;
  registers[NPC] = addr + 4;
}
}
 
 

powered by: WebSVN 2.1.0

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