652 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			652 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
/*
 | 
						|
 * 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
 | 
						|
 | 
						|
 |