!
!   traps.s  Takes care of traps routines.
!
#define KERNEL
#include <sun4/asm←linkage.h>
#define INTERRUPT←MASK 0xf00
#define NB←WINDOWS 7
! Fujitsu implementation
!**********************************************************************
!
!   Debugger entry point. Dumps the registers,
!   enables traps and jumps to the C debbuger.
!
!**********************************************************************
.seg "text"
.global debug𡤎ntry
debug𡤎ntry:
mov  %y,  %l4      !
mov  %psr, %l5      !
mov  %wim,%l6      ! Moves %y, %psr, %wim and %tbr into locals
mov  %tbr, %l7      !
!
! If current window is invalid then make it valid
! allowed to use the only 2 remaining registers %l0 and %l3
!
set   1, %l0
sll   %l0, %l5, %l0  ! creates the current window position pattern
and  %l0, %l6, %l0  ! compare with %wim
tst   %l0
be   debug1    ! if window valid nothing to do.
nop
!   Make window valid
wr   %g0, 0, %wim  ! IMPORTANT otherwise restore will fail in some cases
save  %g0, %g0, %g0  ! go to the next window and don't add anything
SAVE←WINDOW (%sp)   ! writes the registers on the memory stack
restore %g0, %g0, %g0  ! go back to the trap window
!   moves the invalid bit in the %wim
and  %l6, ((1 << NB←WINDOWS) - 1), %l0
srl   %l0, 1, %l0  !
tst   %l0    ! Rotates the low order bits of %l0 left
bne  debug2   !
nop       !
set   (1 << (NB←WINDOWS - 1)), %l0  ! <- Implementation dependant
debug2:       !
wr   %l0, 0, %wim ! writes back the new %wim
debug1:
!
! Set interrupt level to 0xF in order to avoid recursively taking interrupts
!
rd   %psr, %l0
or   %l0, INTERRUPT←MASK, %l0  ! set PIL bits
wr   %l0, 0, %psr
nop      !
nop      ! Wait for %psr to settle
nop      !
!
! ReEnable traps
!
rd   %psr, %l0
or   %l0, 0x20, %l0  ! set ET bit
wr   %l0, 0, %psr
nop      !
nop      ! Wait for %psr to settle
nop      !
sub  %fp, (24 * 4), %sp  ! leave room for the globals also
!
!  store global registers on the stack
!
std  %g0, [%fp - (8-0) *4]
std  %g2, [%fp - (8-2) *4]
std  %g4, [%fp - (8-4) *4]
std  %g6, [%fp - (8-6) *4]
!
!  Push everything on the stack
!
set NB←WINDOWS, %g1
debug3:
save  %sp, - 64, %sp
dec  %g1
tst   %g1
bne  debug3
nop
set NB←WINDOWS, %g1
debug4:
restore %g0, %g0, %g0
dec  %g1
tst   %g1
bne  debug4
nop
!
! Multiway branch to the different interrupt routines
!  (will join back at label returnFromTrap)
!
srl   %l7, 4, %l0    !
and  %l0, 0xff, %l0   ! Trap number into %l0
subcc  %l0, 0x13, %g0  !
be   SparcToSparcInt  ! SparcToSparc Interrupt level
nop        !
subcc  %l0, 0x14, %g0   !
be   IOPToSparcInt   ! IOPToSparc Interrupt level
nop         !
subcc  %l0, 0x17, %g0  !
be   MesaToSparcInt  ! MesaToSparc Interrupt level
nop        !
subcc  %l0, 0x18, %g0   !
be   PeriphAInt    ! PeriphA Interrupt level
nop         !
subcc  %l0, 0x1b, %g0  !
be   PeriphBInt   ! PeriphB Interrupt level
nop        !
subcc  %l0, 0x1c, %g0   !
be   PeriphCInt    ! PeriphC Interrupt level
nop         !
subcc  %l0, 0x17, %g0  !
be   AbortInt    ! Abort Interrupt level
nop        !
SparcToSparcInt:
IOPToSparcInt:
MesaToSparcInt:
PeriphCInt:
AbortInt:
!   *** TO BE CLEANED ***
! Prepares to enter the C debugger
! Clear the SparcToSparcInterrupt state bit and reset PIL to 0
!
.global ←SparcSoftcardOps←ResetSparcToSparcInt
call  ←SparcSoftcardOps←ResetSparcToSparcInt
nop
rd   %psr, %l0        !
and  %l0, ~INTERRUPT←MASK, %l0  ! reset PIL bits
wr   %l0, 0, %psr        !
nop       !
nop       ! Wait for %psr to settle
nop       !
!
! Enters the C debugger. %o0 holds the %sp address.
!
mov  %sp, %o0
call  �ug  ! Enters the C debugger.
nop
ba returnFromTrap  ! Joins the standard restore phase
nop
PeriphAInt:
!
!  Trap routine when interrupted by periph A
!  (now real time clock)
!
! Inc ←RealTimeClockHigh
set   ←RealTimeClockHigh, %l0
ld   [%l0 + 0], %l3
inc  %l3     ! increments RealTimeClockHigh
st   %l3, [%l0 + 0]
! Resets PeriphA Interrupt
set   0, %o0  ! InterruptNumber←interruptA=0
call ←SparcSoftcardOps←ResetPeriphInt
nop
ba returnFromTrap  ! Joins the standard restore phase
nop
.seg "data"
.align 4
.global ←RealTimeClockHigh
←RealTimeClockHigh:
.long 0
.seg "text"
PeriphBInt:
!
!  Trap routine when interrupted by periph B
!  (now DMAEnd)
!
! Resets PeriphB Interrupt
set   1, %o0  ! InterruptNumber←interruptB = 1
call ←SparcSoftcardOps←ResetPeriphInt
nop
call ←PIInterrupt   ! executes the core of the routine
nop
ba returnFromTrap  ! Joins the standard restore phase
nop
!
! Returns from trap. All the registers have to be reloaded.
! This part of the code is entered with trap enabled
! Be carefull with ET and PIL bits in %psr
!
returnFromTrap:
RESTORE←WINDOW (%sp) ! updates the current in and local to the content of the stack
!
!  The previous window is ALWAYS invalid => It has to be restored before rett
!   (Otherwise a reset trap occurs)
!
restore %g0, %g0, %g0  !
save  %g0, %g0, %g0  ! Restore previous window
rd   %psr, %l0   !
and  %l0, ~0x20, %l0  ! Disable traps
wr   %l0, 0, %psr   !
!
!  If the CWP bits in %psr have been touched you are in trouble...
!
ldd  [%fp - (8-0) *4], %g0  !
ldd  [%fp - (8-2) *4], %g2  !  Reloads globals
ldd  [%fp - (8-4) *4], %g4  !
ldd  [%fp - (8-6) *4], %g6  !
!
!  If the ET bit in %psr has been touched you can be in trouble...
!
wr   %l4, 0, %y     !
wr   %l5, 0, %psr     ! Restores %y, %psr and %tbr.
wr   %l7, 0, %tbr     ! Do NOT restore %wim
nop
nop
nop
!
! Return to the trapping program
!
jmpl  %l1, %g0  ! two standard steps
rett  %l2    ! to return from trap
nop
!***************************************************************
!
!   JCC version of window←save𡤊ll (alias trap 3)
!
!***************************************************************
.seg "text"
.global window←save𡤊ll
window←save𡤊ll:
!
! If current window is invalid then make it valid
! allowed to use the only the local registers remaining (not %l1 and %l2)
!
mov  %psr, %l5      !
mov  %wim,%l6      ! Moves %psr and %wim into locals
set   1, %l0
sll   %l0, %l5, %l0     ! creates the current window position pattern
and  %l0, %l6, %l0     ! compare with %wim
tst   %l0
be   saveall1       ! if window valid nothing to do.
nop
!
!   Make window valid
!
wr   %g0, 0, %wim  ! IMPORTANT otherwise restore will fail in some cases
save  %g0, %g0, %g0  ! go to the next window and don't add anything
SAVE←WINDOW (%sp)   ! writes the registers on the memory stack
restore %g0, %g0, %g0  ! go back to the trap window
!   moves the invalid bit in the %wim
and  %l6, ((1 << NB←WINDOWS) - 1), %l0
srl   %l0, 1, %l0  !
tst   %l0    ! Rotates the low order bits of %l0 left
bne  saveall2   !
nop       !
set   (1 << (NB←WINDOWS - 1)), %l0  ! <- Implementation dependant
saveall2:       !
wr   %l0, 0, %wim ! writes back the new %wim
saveall1:
!
! ReEnable traps
!
rd   %psr, %l0
or   %l0, 0x20, %l0  ! set ET bit
wr   %l0, 0, %psr
nop      !
nop      ! Wait for %psr to settle
nop      !
!
!  Push everything on the stack
!
mov  %g1, %l0   ! save %g1
set NB←WINDOWS, %g1
saveall3:
save  %sp, - 64, %sp
dec  %g1
tst   %g1
bne  saveall3
nop
set NB←WINDOWS, %g1
saveall4:
restore %g0, %g0, %g0
dec  %g1
tst   %g1
bne  saveall4
nop
mov  %l0, %g1   ! restore %g1
!
! Disable traps
!
rd   %psr, %l0   !
and  %l0, ~0x20, %l0  ! Disable traps
wr   %l0, 0, %psr   !
nop      !
nop      ! Wait for %psr to settle
nop      !
!
! Return to the trapping program AFTER the trapping instruction
!
jmpl  %l2, %g0  ! two standard steps
rett  %l2 + 4   ! to return from trap after the trapping instruction
nop
!***************************************************************
!
!   JCC version of window←overflow and window←underflow traps
!
!***************************************************************
.seg "text"
.global window←overflow
window←overflow:
!
! Current window is marked invalid. Next window must
! be saved and marked invalid
!
rd   %wim, %l0   ! saves %wim
wr   %g0, 0, %wim  ! clear %wim -> disable futher overflows or underflows
save  %g0, %g0, %g0  ! go to the next window and don't add anything
SAVE←WINDOW (%sp)   ! writes the registers on the memory stack
ld   [%g0 + 0], %l0  !
sub  %sp, %l0, %l0  !
tst   %l0     !
bpos  1f      ! *** DEBUG find lowest value of the stack ( TB Removed) ***
nop        !
st   %sp, [%g0 + 0]  !
1:
restore %g0, %g0, %g0  ! go back to the trap window
! moves the invalid bit in the %wim
and  %l0, ((1 << NB←WINDOWS) - 1), %l0
! extract the correct bits <- Implementation dependant
srl   %l0, 1, %l0  !
tst   %l0    ! Rotates the low order bits of %l0 left
bne  label0    !
nop       !
set   (1 << (NB←WINDOWS - 1)), %l0  ! <- Implementation dependant
label0:       !
wr   %l0, 0, %wim ! writes back the new %wim
nop       ! wait for the %wim to settle
nop
jmpl  %l1, %g0  ! two standard steps
rett  %l2    ! to return from trap
nop
.global window←underflow
window←underflow:
!
! Previous window is last active window. The window before that
! is marked invalid and must be restored. The window before that
! becomes the new invalid window.
!
rd   %wim, %l0   ! saves %wim
wr   %g0, 0, %wim  ! clear %wim -> disable futher overflows or underflows
restore %g0, %g0, %g0  ! back two windows to point
restore %g0, %g0, %g0  ! to the registers to be restored.
RESTORE←WINDOW (%sp) ! loads the registers from the memory stack
save  %g0, %g0, %g0  ! again to the trap window
save  %g0, %g0, %g0
! moves the invalid bit in the %wim
and  %l0, ((1 << NB←WINDOWS) - 1), %l0
! extract the correct bits <- Implementation dependant
sll   %l0, 1, %l0  !
cmp  %l0, (1 << NB←WINDOWS)   ! <- Implementation dependant
bne  label1    !
nop       !
set   1, %l0   !
label1:       !
wr   %l0, 0, %wim ! writes back the new %wim
nop       ! wait for the %wim to settle
nop
jmpl  %l1, %g0  ! two standard steps
rett  %l2    ! to return from trap
nop