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