Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libgloss/sparc/traps.S')
-rw-r--r--libgloss/sparc/traps.S651
1 files changed, 651 insertions, 0 deletions
diff --git a/libgloss/sparc/traps.S b/libgloss/sparc/traps.S
new file mode 100644
index 000000000..b3cc96692
--- /dev/null
+++ b/libgloss/sparc/traps.S
@@ -0,0 +1,651 @@
+/*
+ * 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 trap
+ BAD_TRAP; ! 01 instruction access exception
+ TRAP(SYM(no_fpu)); ! 02 illegal instruction
+ BAD_TRAP; ! 03 privileged instruction
+ BAD_TRAP; ! 04 fp disabled
+ TRAP(SYM(win_overflow)); ! 05 window overflow
+ TRAP(SYM(win_underflow)); ! 06 window underflow
+ BAD_TRAP; ! 07 memory address not aligned
+ BAD_TRAP; ! 08 fp exception
+ BAD_TRAP; ! 09 data access exception
+ BAD_TRAP; ! 0A tag overflow
+
+ /* Trap levels from 0B to 0x10 are not defined (used for MEC init) */
+
+SYM(ercinit):
+ sethi %hi(_ERC32_MEC), %g1 ! 0B
+ sethi %hi(0x001C1000), %g2
+ or %g1,%lo(0x001C1000),%g1
+ st %g2, [%g1 + 0x10]
+ st %g0, [%g1 + 0x18] ! 0C
+ nop
+ nop
+ nop
+
+ TRAP(SYM(hard_reset)); ! 0D undefined
+ BAD_TRAP; ! 0E undefined
+ BAD_TRAP; ! 0F undefined
+ BAD_TRAP; ! 10 undefined
+
+ /*
+ * ERC32 defined traps
+ */
+
+ BAD_TRAP; ! 11 masked errors
+ BAD_TRAP; ! 12 external 1
+ BAD_TRAP; ! 13 external 2
+ BAD_TRAP; ! 14 UART A RX/TX
+ BAD_TRAP; ! 15 UART B RX/TX
+ BAD_TRAP; ! 16 correctable memory error
+ BAD_TRAP; ! 17 UART error
+ BAD_TRAP; ! 18 DMA access error
+ BAD_TRAP; ! 19 DMA timeout
+ BAD_TRAP; ! 1A external 3
+ BAD_TRAP; ! 1B external 4
+ BAD_TRAP; ! 1C general purpose timer
+ BAD_TRAP; ! 1D real time clock
+ BAD_TRAP; ! 1E external 5
+ BAD_TRAP; ! 1F watchdog timeout
+
+
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 20 - 23 undefined
+ BAD_TRAP; ! 24 cp_disabled
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 25 - 27 undefined
+ BAD_TRAP; ! 28 cp_exception
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 29 - 2B undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 2C - 2F undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30 - 33 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34 - 37 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38 - 3B undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3C - 3F undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40 - 43 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44 - 47 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48 - 4B undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4C - 4F undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50 - 53 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54 - 57 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58 - 5B undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5C - 5F undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60 - 63 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64 - 67 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68 - 6B undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6C - 6F undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70 - 73 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74 - 77 undefined
+ BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78 - 7B undefined
+ BAD_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 0
+ SOFT_TRAP; ! 81
+#else
+ TRAP(SYM(trap_low)) ! 81
+#endif
+ SOFT_TRAP; ! 82
+ TRAP(SYM(win_flush)); ! 83 flush windows SW trap
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84 - 87
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 88 - 8B
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8C - 8F
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90 - 93
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94 - 97
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98 - 9B
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9C - 9F
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A0 - A3
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A4 - A7
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A8 - AB
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! AC - AF
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B0 - B3
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B4 - B7
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B8 - BB
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! BC - BF
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C0 - C3
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C4 - C7
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C8 - CB
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! CC - CF
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D0 - D3
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D4 - D7
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D8 - DB
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! DC - DF
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E0 - E3
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E4 - E7
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E8 - EB
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! EC - EF
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F0 - F3
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F4 - F7
+ SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F8 - FB
+ SOFT_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),%o0
+ or %o0,%lo(0x01FE0),%o0
+ mov %o0, %psr ! Set valid PSR
+ nop
+
+ mov %g0, %wim ! Set window invalid mask register
+ mov %g0, %y ! Init Y-register
+ nop
+ sethi %hi(SYM(hard_reset)), %g1
+
+ mov %g1, %tbr ! Set TBR
+ sethi %hi(SP_INIT),%sp
+ or %g0, 1, %o0
+ ld [%g0], %f0 ! Check if FPU is present
+
+ tst %o0
+ bz fixiu
+ nop
+ ba fixfpu
+
+! FPU disabled trap address
+
+ clr %i0
+ jmpl %l2, %g0
+ rett %l2 + 4
+ nop
+
+
+! Wash register files (fix for 90C601E & 90C602E)
+
+fixfpu:
+
+ ld [%g0], %f0
+ ld [%g0], %f1
+ ld [%g0], %f2
+ ld [%g0], %f3
+ ld [%g0], %f4
+ ld [%g0], %f5
+ ld [%g0], %f6
+ ld [%g0], %f7
+ ld [%g0], %f8
+ ld [%g0], %f9
+ ld [%g0], %f10
+ ld [%g0], %f11
+ ld [%g0], %f12
+ ld [%g0], %f13
+ ld [%g0], %f14
+ ld [%g0], %f15
+ ld [%g0], %f16
+ ld [%g0], %f17
+ ld [%g0], %f18
+ ld [%g0], %f19
+ ld [%g0], %f20
+ ld [%g0], %f21
+ ld [%g0], %f22
+ ld [%g0], %f23
+ ld [%g0], %f24
+ ld [%g0], %f25
+ ld [%g0], %f26
+ ld [%g0], %f27
+ ld [%g0], %f28
+ ld [%g0], %f29
+ ld [%g0], %f30
+ ld [%g0], %f31
+
+fixiu:
+ clr %g1
+ clr %g2
+ clr %g3
+ clr %g4
+ clr %g5
+ clr %g6
+ clr %g7
+ set 8,%g1
+wl0:
+ clr %i0
+ clr %i1
+ clr %i2
+ clr %i3
+ clr %i4
+ clr %i5
+ clr %i6
+ clr %i7
+ clr %l0
+ clr %l1
+ clr %l2
+ clr %l3
+ clr %l4
+ clr %l5
+ clr %l6
+ clr %l7
+ save
+ subcc %g1, 1, %g1
+ bne wl0
+ nop
+
+!
+! Start the real-time clock with a tick of 150 clocks
+!
+
+rtc:
+
+ set 0x1f80000, %l0 ! MEC register base
+ set 149, %l1
+ st %l1, [%l0 + 0x84] ! RTC scaler = 149
+ set 0x0d00, %l1
+ st %l1, [%l0 + 0x98] ! Start RTC
+
+ st %g0, [%l0 + 0x64] ! Disable watchdog for now
+ ld [%l0], %g1
+ or %g1, 1, %g1
+ st %g1, [%l0] ! Enable power-down mode
+
+_init:
+ set PSR_INIT, %g1 ! Initialize psr
+ mov %g1, %psr
+ set WIM_INIT, %g1 ! Initialize WIM
+ mov %g1, %wim
+ set _trap_table, %g1 ! Initialize TBR
+ mov %g1, %tbr
+ nop;nop;nop
+
+ set PSR_INIT, %g1
+ wr %g1, 0x20, %psr ! enable traps
+ nop; 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 wim
+ srl %l0, 1, %g1 ! Rotate wim right
+ sll %l0, NUMBER_OF_REGISTER_WINDOWS - 1, %l0
+ or %l0, %g1, %g1
+
+ save %g0, %g0, %g0 ! Slip into next window
+ mov %g1, %wim ! Install the new wim
+ nop
+ nop
+ nop
+
+ std %l0, [%sp + 0 * 4] ! save L & I registers
+ std %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 %g1
+
+ jmpl %l1, %g0
+ rett %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 left
+ srl %l0, NUMBER_OF_REGISTER_WINDOWS - 1, %l0
+ or %l0, %l3, %l0
+
+ mov %l0, %wim ! Install the new wim
+
+ restore ! Users window
+ restore ! His callers window
+
+ ldd [%sp + 0 * 4], %l0 ! restore L & I registers
+ ldd [%sp + 2 * 4], %l2
+ ldd [%sp + 4 * 4], %l4
+ ldd [%sp + 6 * 4], %l6
+
+ ldd [%sp + 8 * 4], %i0
+ ldd [%sp + 10 * 4], %i2
+ ldd [%sp + 12 * 4], %i4
+ ldd [%sp + 14 * 4], %i6
+
+ save %g0, %g0, %g0 ! Back to trap window
+ save %g0, %g0, %g0
+
+ jmpl %l1, %g0
+ rett %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, %l0
+ or %l0,0xf00,%l3 ! Disable interrupts
+ mov %l3,%psr
+ nop
+ nop
+ nop
+ mov %wim, %l3
+
+ srl %l3, %l0, %l4 ! wim >> cwp
+ cmp %l4, 1
+ bne flush_window_fine ! Branch if not in the invalid window
+ nop
+
+/* Handle window overflow. We can't trap here. */
+
+ mov %g1, %l4 ! Save g1, we use it to hold the wim
+ srl %l3, 1, %g1 ! Rotate wim right
+ sll %l3, NUMBER_OF_REGISTER_WINDOWS - 1, %l3
+ or %l3, %g1, %g1
+ mov %g0, %wim ! Clear wim so that subsequent save
+ nop ! wont trap
+ nop
+ nop
+ save %g0, %g0, %g0 ! Slip into next window
+ mov %g1, %wim ! Install the new wim
+
+ std %l0, [%sp + 0 * 4] ! save L & I registers
+ std %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 %g1
+
+flush_window_fine:
+ mov %psr,%l5 ! enable traps
+ or %l5,0x20,%l5
+ mov %l5, %psr
+ nop
+ nop
+ nop
+
+ set save_buf,%l5
+ st %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, %sp
+
+ save %sp, -64, %sp ! Flush user register window to stack
+ 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 ! Make sure we have a valid window
+ save %g0, %g0, %g0
+
+ set save_buf, %l2 ! Get our return address back
+ ld [%l2],%l2
+
+ mov %psr,%l5 ! disable traps for rett
+ andn %l5,0x20,%l5
+ mov %l5,%psr
+ nop
+ nop
+ nop
+
+ jmpl %l2, %g0
+ rett %l2+4
+
+/*
+ * Read the TBR.
+ */
+ .globl SYM(rdtbr)
+SYM(rdtbr):
+ mov %tbr, %o0
+ nop
+ retl
+ nop
+
+/*
+ * Read the psr
+ */
+ .globl SYM(read_psr)
+SYM(read_psr):
+ mov %psr, %o0
+ nop
+ retl
+ nop
+
+/*
+ * Write the PSR.
+ */
+
+ .globl SYM(write_psr)
+SYM(write_psr):
+ mov %i0, %psr
+ nop
+ nop
+ nop
+ retl
+ nop
+/*
+ * Come here when no fpu exists. This just skips the offending
+ * instruction.
+ */
+ .globl SYM(no_fpu)
+SYM(no_fpu):
+ jmpl %l2, %g0
+ rett %l2+4
+
+ .globl SYM(fltr_proto)
+ .align 4
+SYM(fltr_proto): ! First level trap routine prototype
+ sethi 0, %l0
+ jmpl 0+%l0, %g0
+ nop
+ nop
+
+/*
+ * 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)), %l0
+ st %l1, [%l0 + %lo(SYM(mem_err))]
+ jmpl %l2, %g0
+ rett %l2+4
+
+ .data
+ .align 4
+ .ascii "DaTa"
+ .long SYM(sdata)
+in_trap_handler:
+ .word 0
+save_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, %l0
+ mov %wim, %l3
+
+ srl %l3, %l0, %l4 ! wim >> cwp
+ cmp %l4, 1
+ bne window_fine ! Branch if not in the invalid window
+ nop
+
+ mov %g1, %l4 ! Save g1, we use it to hold the wim
+ srl %l3, 1, %g1 ! Rotate wim right
+ sll %l3, 8-1, %l5
+ or %l5, %g1, %g1
+
+ save %g0, %g0, %g0 ! Slip into next window
+ mov %g1, %wim ! Install the new wim
+
+ std %l0, [%sp + 0 * 4] ! save L & I registers
+ std %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 g1
+
+window_fine:
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ tst %l5
+ bg recursive_trap
+ inc %l5
+
+ /* use the stack we set in the linker script */
+ sethi %hi(__trap_stack), %l6
+ or %l6,%lo(__trap_stack),%l6
+ mov %l6, %sp ! set the stack pointer
+
+recursive_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 var
+
+ std %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 implemented
+ mov %y, %l4
+ mov %tbr, %l5
+ st %l4, [%sp + (24 + 64) * 4] ! Y
+ st %l0, [%sp + (24 + 65) * 4] ! PSR
+ st %l3, [%sp + (24 + 66) * 4] ! WIM
+ st %l5, [%sp + (24 + 67) * 4] ! TBR
+ st %l1, [%sp + (24 + 68) * 4] ! PC
+ st %l2, [%sp + (24 + 69) * 4] ! NPC
+ ! CPSR and FPSR not implemented
+
+ or %l0, 0xf20, %l4
+ mov %l4, %psr ! Turn on traps, disable interrupts
+
+ call 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], %g2
+ ldd [%sp + (24 + 4) * 4], %g4
+ ldd [%sp + (24 + 6) * 4], %g6
+
+ ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox]
+ ldd [%sp + (24 + 10) * 4], %i2
+ ldd [%sp + (24 + 12) * 4], %i4
+ ldd [%sp + (24 + 14) * 4], %i6
+
+ ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR
+ ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC
+
+ restore ! Ensure that previous window is valid
+ save %g0, %g0, %g0 ! by causing a window_underflow trap
+
+ mov %l0, %y
+ mov %l1, %psr ! Make sure that traps are disabled
+ ! for rett
+
+ sethi %hi(in_trap_handler), %l4
+ ld [%lo(in_trap_handler) + %l4], %l5
+ dec %l5
+ st %l5, [%lo(in_trap_handler) + %l4]
+
+ jmpl %l2, %g0 ! Restore old PC
+ rett %l3 ! Restore old nPC
+
+