URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [newlib/] [libgloss/] [sparc/] [traps.S] - Rev 1765
Compare with Previous | Blame | View Log
/** Copyright (c) 1995, 1996, 1998 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 "asm.h"#include "slite.h".text.align 4/** The trap table has to be the first code in a boot PROM. But because* the Memory Configuration comes up thinking we only have 4K of PROM, we* cannot have a full trap table and still have room left over to* reprogram the Memory Configuration register correctly. This file* uses an abbreviated trap which has every entry which might be used* before RTEMS installs its own trap table.*/.globl _trap_table_trap_table:TRAP(SYM(ercinit)); ! 00 reset trapBAD_TRAP; ! 01 instruction access exceptionTRAP(SYM(no_fpu)); ! 02 illegal instructionBAD_TRAP; ! 03 privileged instructionBAD_TRAP; ! 04 fp disabledTRAP(SYM(win_overflow)); ! 05 window overflowTRAP(SYM(win_underflow)); ! 06 window underflowBAD_TRAP; ! 07 memory address not alignedBAD_TRAP; ! 08 fp exceptionBAD_TRAP; ! 09 data access exceptionBAD_TRAP; ! 0A tag overflow/* Trap levels from 0B to 0x10 are not defined (used for MEC init) */SYM(ercinit):sethi %hi(_ERC32_MEC), %g1 ! 0Bsethi %hi(0x001C1000), %g2or %g1,%lo(0x001C1000),%g1st %g2, [%g1 + 0x10]st %g0, [%g1 + 0x18] ! 0CnopnopnopTRAP(SYM(hard_reset)); ! 0D undefinedBAD_TRAP; ! 0E undefinedBAD_TRAP; ! 0F undefinedBAD_TRAP; ! 10 undefined/** ERC32 defined traps*/BAD_TRAP; ! 11 masked errorsBAD_TRAP; ! 12 external 1BAD_TRAP; ! 13 external 2BAD_TRAP; ! 14 UART A RX/TXBAD_TRAP; ! 15 UART B RX/TXBAD_TRAP; ! 16 correctable memory errorBAD_TRAP; ! 17 UART errorBAD_TRAP; ! 18 DMA access errorBAD_TRAP; ! 19 DMA timeoutBAD_TRAP; ! 1A external 3BAD_TRAP; ! 1B external 4BAD_TRAP; ! 1C general purpose timerBAD_TRAP; ! 1D real time clockBAD_TRAP; ! 1E external 5BAD_TRAP; ! 1F watchdog timeoutBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 20 - 23 undefinedBAD_TRAP; ! 24 cp_disabledBAD_TRAP; BAD_TRAP; BAD_TRAP; ! 25 - 27 undefinedBAD_TRAP; ! 28 cp_exceptionBAD_TRAP; BAD_TRAP; BAD_TRAP; ! 29 - 2B undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 2C - 2F undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30 - 33 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34 - 37 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38 - 3B undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3C - 3F undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40 - 43 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44 - 47 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48 - 4B undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4C - 4F undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50 - 53 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54 - 57 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58 - 5B undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5C - 5F undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60 - 63 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64 - 67 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68 - 6B undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6C - 6F undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70 - 73 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74 - 77 undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78 - 7B undefinedBAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7C - 7F undefined/** Software traps** NOTE: At the risk of being redundant... this is not a full* table. The setjmp on the SPARC requires a window flush trap* handler and RTEMS will preserve the entries that were* installed before.*/SOFT_TRAP; ! 80#if 0SOFT_TRAP; ! 81#elseTRAP(SYM(trap_low)) ! 81#endifSOFT_TRAP; ! 82TRAP(SYM(win_flush)); ! 83 flush windows SW trapSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84 - 87SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 88 - 8BSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8C - 8FSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90 - 93SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94 - 97SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98 - 9BSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9C - 9FSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A0 - A3SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A4 - A7SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A8 - ABSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! AC - AFSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B0 - B3SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B4 - B7SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B8 - BBSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! BC - BFSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C0 - C3SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C4 - C7SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C8 - CBSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! CC - CFSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D0 - D3SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D4 - D7SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D8 - DBSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! DC - DFSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E0 - E3SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E4 - E7SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E8 - EBSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! EC - EFSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F0 - F3SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F4 - F7SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F8 - FBSOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! FC - FF/** Startup code for standalone system. Wash IU and FPU (if present)* registers. The registers have to be written to initiate the parity* bits.*/.globl SYM(hard_reset)SYM(hard_reset):sethi %hi(0x01FE0),%o0or %o0,%lo(0x01FE0),%o0mov %o0, %psr ! Set valid PSRnopmov %g0, %wim ! Set window invalid mask registermov %g0, %y ! Init Y-registernopsethi %hi(SYM(hard_reset)), %g1mov %g1, %tbr ! Set TBRsethi %hi(SP_INIT),%spor %g0, 1, %o0ld [%g0], %f0 ! Check if FPU is presenttst %o0bz fixiunopba fixfpu! FPU disabled trap addressclr %i0jmpl %l2, %g0rett %l2 + 4nop! Wash register files (fix for 90C601E & 90C602E)fixfpu:ld [%g0], %f0ld [%g0], %f1ld [%g0], %f2ld [%g0], %f3ld [%g0], %f4ld [%g0], %f5ld [%g0], %f6ld [%g0], %f7ld [%g0], %f8ld [%g0], %f9ld [%g0], %f10ld [%g0], %f11ld [%g0], %f12ld [%g0], %f13ld [%g0], %f14ld [%g0], %f15ld [%g0], %f16ld [%g0], %f17ld [%g0], %f18ld [%g0], %f19ld [%g0], %f20ld [%g0], %f21ld [%g0], %f22ld [%g0], %f23ld [%g0], %f24ld [%g0], %f25ld [%g0], %f26ld [%g0], %f27ld [%g0], %f28ld [%g0], %f29ld [%g0], %f30ld [%g0], %f31fixiu:clr %g1clr %g2clr %g3clr %g4clr %g5clr %g6clr %g7set 8,%g1wl0:clr %i0clr %i1clr %i2clr %i3clr %i4clr %i5clr %i6clr %i7clr %l0clr %l1clr %l2clr %l3clr %l4clr %l5clr %l6clr %l7savesubcc %g1, 1, %g1bne wl0nop!! Start the real-time clock with a tick of 150 clocks!rtc:set 0x1f80000, %l0 ! MEC register baseset 149, %l1st %l1, [%l0 + 0x84] ! RTC scaler = 149set 0x0d00, %l1st %l1, [%l0 + 0x98] ! Start RTCst %g0, [%l0 + 0x64] ! Disable watchdog for nowld [%l0], %g1or %g1, 1, %g1st %g1, [%l0] ! Enable power-down mode_init:set PSR_INIT, %g1 ! Initialize psrmov %g1, %psrset WIM_INIT, %g1 ! Initialize WIMmov %g1, %wimset _trap_table, %g1 ! Initialize TBRmov %g1, %tbrnop;nop;nopset PSR_INIT, %g1wr %g1, 0x20, %psr ! enable trapsnop; nop; nop;call SYM(start)nop/** Register window overflow handler. Come here when save would move us* into the invalid window. This routine runs with traps disabled, and* must be careful not to touch the condition codes, as PSR is never* restored.** We are called with %l0 = wim, %l1 = pc, %l2 = npc*/.globl SYM(win_overflow)SYM(win_overflow):mov %g1, %l3 ! Save g1, we use it to hold the wimsrl %l0, 1, %g1 ! Rotate wim rightsll %l0, NUMBER_OF_REGISTER_WINDOWS - 1, %l0or %l0, %g1, %g1save %g0, %g0, %g0 ! Slip into next windowmov %g1, %wim ! Install the new wimnopnopnopstd %l0, [%sp + 0 * 4] ! save L & I registersstd %l2, [%sp + 2 * 4]std %l4, [%sp + 4 * 4]std %l6, [%sp + 6 * 4]std %i0, [%sp + 8 * 4]std %i2, [%sp + 10 * 4]std %i4, [%sp + 12 * 4]std %i6, [%sp + 14 * 4]restore ! Go back to trap window.mov %l3, %g1 ! Restore %g1jmpl %l1, %g0rett %l2/** Register window underflow handler. Come here when restore would move us* into the invalid window. This routine runs with traps disabled, and* must be careful not to touch the condition codes, as PSR is never* restored.** We are called with %l0 = wim, %l1 = pc, %l2 = npc*/.globl SYM(win_underflow)SYM(win_underflow):sll %l0, 1, %l3 ! Rotate wim leftsrl %l0, NUMBER_OF_REGISTER_WINDOWS - 1, %l0or %l0, %l3, %l0mov %l0, %wim ! Install the new wimrestore ! Users windowrestore ! His callers windowldd [%sp + 0 * 4], %l0 ! restore L & I registersldd [%sp + 2 * 4], %l2ldd [%sp + 4 * 4], %l4ldd [%sp + 6 * 4], %l6ldd [%sp + 8 * 4], %i0ldd [%sp + 10 * 4], %i2ldd [%sp + 12 * 4], %i4ldd [%sp + 14 * 4], %i6save %g0, %g0, %g0 ! Back to trap windowsave %g0, %g0, %g0jmpl %l1, %g0rett %l2/** Register window flush handler, triggered by a "ta 3" instruction.* We are called with %l0 = wim, %l1 = pc, %l2 = npc*/.globl SYM(win_flush)SYM(win_flush):mov %psr, %l0or %l0,0xf00,%l3 ! Disable interruptsmov %l3,%psrnopnopnopmov %wim, %l3srl %l3, %l0, %l4 ! wim >> cwpcmp %l4, 1bne flush_window_fine ! Branch if not in the invalid windownop/* Handle window overflow. We can't trap here. */mov %g1, %l4 ! Save g1, we use it to hold the wimsrl %l3, 1, %g1 ! Rotate wim rightsll %l3, NUMBER_OF_REGISTER_WINDOWS - 1, %l3or %l3, %g1, %g1mov %g0, %wim ! Clear wim so that subsequent savenop ! wont trapnopnopsave %g0, %g0, %g0 ! Slip into next windowmov %g1, %wim ! Install the new wimstd %l0, [%sp + 0 * 4] ! save L & I registersstd %l2, [%sp + 2 * 4]std %l4, [%sp + 4 * 4]std %l6, [%sp + 6 * 4]std %i0, [%sp + 8 * 4]std %i2, [%sp + 10 * 4]std %i4, [%sp + 12 * 4]std %i6, [%sp + 14 * 4]restore ! Go back to trap window.mov %l4, %g1 ! Restore %g1flush_window_fine:mov %psr,%l5 ! enable trapsor %l5,0x20,%l5mov %l5, %psrnopnopnopset save_buf,%l5st %l2,[%l5]! The stack pointer currently contains a bogus value [when a trap! occurs CWP is decremented and points to an unused window].! Give it something useful before we flush every window.! This does what a "save %sp,-64,$sp" would, except that CWP has! already been decremented.add %fp, -64, %spsave %sp, -64, %sp ! Flush user register window to stacksave %sp, -64, %spsave %sp, -64, %spsave %sp, -64, %spsave %sp, -64, %spsave %sp, -64, %spsave %sp, -64, %spsave %sp, -64, %sprestorerestorerestorerestorerestorerestorerestorerestorerestore ! Make sure we have a valid windowsave %g0, %g0, %g0set save_buf, %l2 ! Get our return address backld [%l2],%l2mov %psr,%l5 ! disable traps for rettandn %l5,0x20,%l5mov %l5,%psrnopnopnopjmpl %l2, %g0rett %l2+4/** Read the TBR.*/.globl SYM(rdtbr)SYM(rdtbr):mov %tbr, %o0nopretlnop/** Read the psr*/.globl SYM(read_psr)SYM(read_psr):mov %psr, %o0nopretlnop/** Write the PSR.*/.globl SYM(write_psr)SYM(write_psr):mov %i0, %psrnopnopnopretlnop/** Come here when no fpu exists. This just skips the offending* instruction.*/.globl SYM(no_fpu)SYM(no_fpu):jmpl %l2, %g0rett %l2+4.globl SYM(fltr_proto).align 4SYM(fltr_proto): ! First level trap routine prototypesethi 0, %l0jmpl 0+%l0, %g0nopnop/** Trap handler for memory errors. This just sets mem_err to be* non-zero. It assumes that l1 is non-zero. This should be safe,* as it is doubtful that 0 would ever contain code that could mem* fault. This routine will skip past the faulting instruction after* setting mem_err.*/.globl SYM(fltr_set_mem_err)SYM(fltr_set_mem_err):sethi %hi(SYM(mem_err)), %l0st %l1, [%l0 + %lo(SYM(mem_err))]jmpl %l2, %g0rett %l2+4.data.align 4.ascii "DaTa".long SYM(sdata)in_trap_handler:.word 0save_buf:.word 0 /* place to save %g1 */.word 0 /* place to save %g2 */.text.align 4/** This function is called when any SPARC trap (except window overflow* or underflow) occurs. It makes sure that the invalid register* window is still available before jumping into C code. It will also* restore the world if you return from handle_exception.*/.globl SYM(trap_low)SYM(trap_low):mov %psr, %l0mov %wim, %l3srl %l3, %l0, %l4 ! wim >> cwpcmp %l4, 1bne window_fine ! Branch if not in the invalid windownopmov %g1, %l4 ! Save g1, we use it to hold the wimsrl %l3, 1, %g1 ! Rotate wim rightsll %l3, 8-1, %l5or %l5, %g1, %g1save %g0, %g0, %g0 ! Slip into next windowmov %g1, %wim ! Install the new wimstd %l0, [%sp + 0 * 4] ! save L & I registersstd %l2, [%sp + 2 * 4]std %l4, [%sp + 4 * 4]std %l6, [%sp + 6 * 4]std %i0, [%sp + 8 * 4]std %i2, [%sp + 10 * 4]std %i4, [%sp + 12 * 4]std %i6, [%sp + 14 * 4]restore ! Go back to trap window.mov %l4, %g1 ! Restore g1window_fine:sethi %hi(in_trap_handler), %l4ld [%lo(in_trap_handler) + %l4], %l5tst %l5bg recursive_trapinc %l5/* use the stack we set in the linker script */sethi %hi(__trap_stack), %l6or %l6,%lo(__trap_stack),%l6mov %l6, %sp ! set the stack pointerrecursive_trap:st %l5, [%lo(in_trap_handler) + %l4]sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals! + hidden arg + arg spill! + doubleword alignment! + registers[72] local varstd %g0, [%sp + (24 + 0) * 4] ! registers[Gx]std %g2, [%sp + (24 + 2) * 4]std %g4, [%sp + (24 + 4) * 4]std %g6, [%sp + (24 + 6) * 4]std %i0, [%sp + (24 + 8) * 4] ! registers[Ox]std %i2, [%sp + (24 + 10) * 4]std %i4, [%sp + (24 + 12) * 4]std %i6, [%sp + (24 + 14) * 4]! F0->F31 not implementedmov %y, %l4mov %tbr, %l5st %l4, [%sp + (24 + 64) * 4] ! Yst %l0, [%sp + (24 + 65) * 4] ! PSRst %l3, [%sp + (24 + 66) * 4] ! WIMst %l5, [%sp + (24 + 67) * 4] ! TBRst %l1, [%sp + (24 + 68) * 4] ! PCst %l2, [%sp + (24 + 69) * 4] ! NPC! CPSR and FPSR not implementedor %l0, 0xf20, %l4mov %l4, %psr ! Turn on traps, disable interruptscall SYM(handle_exception)add %sp, 24 * 4, %o0 ! Pass address of registers/* Reload all of the registers that aren't on the stack */ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx]ldd [%sp + (24 + 2) * 4], %g2ldd [%sp + (24 + 4) * 4], %g4ldd [%sp + (24 + 6) * 4], %g6ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]ldd [%sp + (24 + 10) * 4], %i2ldd [%sp + (24 + 12) * 4], %i4ldd [%sp + (24 + 14) * 4], %i6ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSRldd [%sp + (24 + 68) * 4], %l2 ! PC & NPCrestore ! Ensure that previous window is validsave %g0, %g0, %g0 ! by causing a window_underflow trapmov %l0, %ymov %l1, %psr ! Make sure that traps are disabled! for rettsethi %hi(in_trap_handler), %l4ld [%lo(in_trap_handler) + %l4], %l5dec %l5st %l5, [%lo(in_trap_handler) + %l4]jmpl %l2, %g0 ! Restore old PCrett %l3 ! Restore old nPC
