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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [newlib/] [libgloss/] [sparc/] [erc32-stub.c] - Diff between revs 40 and 1765

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

Rev 40 Rev 1765
/*
/*
 * 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
  asm(" save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        save %sp, -64, %sp
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
        restore
");
");
 
 
  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) "
  asm(" .globl " STRINGSYM(breakinst) "
        " STRINGSYM(breakinst) ": ta 128+1
        " STRINGSYM(breakinst) ": ta 128+1
        nop
        nop
        nop
        nop
      ");
      ");
}
}
 
 
/*
/*
 * 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
  asm("ta 0
        nop
        nop
        nop
        nop
      ");
      ");
}
}
 
 
/*
/*
 * 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
  asm("ta 0
        nop
        nop
        nop
        nop
      ");
      ");
}
}
 
 
/*
/*
 * 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
  asm ("call 0
        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.