!
! Program first executed by the Sparc after reset.
!
#define KERNEL
#include <sun4/asm←linkage.h>
#define softcardPageSizeByte 8192
! see "SparcSoftcard.h"
#define trapBaseByte softcardPageSizeByte
! the trap vectors will be located in page 1
#define RESET←TRAP 0
#define OVERFLOW←TRAP 5
#define UNDERFLOW←TRAP 6
#define TRAP𡤃 0x83
#define NB←WINDOWS 7
! Fujitsu implementation
#define INTERRUPT←MASK 0xf00
.seg "text"
.global ←init0   ! Starts here after Reset
.global ←main
.global ←place←trap←vector
←init0:       ! First instruction after reset 
!
! set CPW and WIM to meaningfull values
!
wr   %g0, %g0, %wim ! guaranties that all windows are valid
nop
nop
nop
rd   %psr, %g1    !
and  %g1, ~0x1f, %g1  ! set CPW to 0.
and  %g1, ~0x20, %g1  ! disable traps.
and  %g1, ~0x40, %g1  ! reset PS bit.
or   %g1, INTERRUPT←MASK, %g1  ! Set PIL Bits (disable interrrupts).
wr   %g1, %g0, %psr  !
nop
wr   %g0, 2, %wim  ! mark window #1 invalid (max number of call before overflow)
nop
set   0, %fp    ! Indicates End Of Stack.
!
! Temporary sets %sp value near the end of the second page.
! *** DON'T put it in page 0. The mapping is temporary changed by init1.c ***
! 
set  ( 2 * softcardPageSizeByte ), %sp
sub %sp, MINFRAME, %sp ! decrement sp by one frame
and %sp, ~7, %sp    ! round down to 0 modulo 8
!
! Zero bss.
!
.global �ta
.global 𡤎nd
set  0, %l0
set  0, %l1
set  �ta, %l2   ! �ta is the start of the bss (double word aligned).
set  𡤎nd, %l3   ! 𡤎nd is the end of the bss
1:
std %l0, [%l2]
add  %l2, 8, %l2
subcc %l2, %l3, %g0
bne 1b
nop
!
! Sets all the traps pointers to the debugger entry point.
!
.global debug𡤎ntry
add  %g0, %g0, %g1      !  (trap number and loop index)
sethi %hi(debug𡤎ntry), %g2   !  prepare the arguments
or  %g2, %lo(debug𡤎ntry), %g2  !  (trap routine address)
trapsloop:
mov %g1, %o0       !
mov %g2, %o1       ! Place the arguments inside the right registers
call ←place←trap←vector
inc  %g1         ! inc loop index
subcc %g1, 256, %g0      ! test loop exit
bne trapsloop
nop
!
! Sets the reset trap to the debugger entry point.
!
set  RESET←TRAP, %o0      !
sethi %hi(debug𡤎ntry), %o1    ! prepare the arguments for the call
or  %o1, %lo(debug𡤎ntry), %o1   !
call place←reset←trap←vector
nop
!
! Sets the trap pointers for window←overflow, window←underflow
! and window←Save𡤊llroutines
!
.global window←overflow
.global window←underflow
.global window←save𡤊ll
set  OVERFLOW←TRAP, %o0    !
sethi %hi(window←overflow), %o1   ! prepare the arguments for the call
or  %o1, %lo(window←overflow), %o1 !
call ←place←trap←vector
nop
set  UNDERFLOW←TRAP, %o0    !
sethi %hi(window←underflow), %o1  ! prepare the arguments for the call
or  %o1, %lo(window←underflow), %o1 !
call ←place←trap←vector
nop
set  TRAP𡤃, %o0       !
sethi %hi(window←save𡤊ll), %o1   ! prepare the arguments for the call
or  %o1, %lo(window←save𡤊ll), %o1 !
call ←place←trap←vector
nop
!
! Set trap base address to trapBaseByte = page 1 ( page 0 will be used as NIL check )
!
set  trapBaseByte, %g1
wr   %g1, 0, %tbr
nop
nop
nop
!
! Enable traps interrupts are still masked
!
rd   %psr, %g1
or   %g1, 0x20, %g1  ! set ET bit
wr   %g1, 0, %psr
nop
!
!   Call a C subroutine to find out the memory size and initialize the map.
!   This subroutine returns sparcMemorySizeByte inside %o0.
!   All the VM pages from 0 to sparcMemorySizeByte/softcardPageSizeByte - 1 point
!   to distinct Real memory pages. The remaining entries of the map point at the
!   same place that page 0.
!
.global ←init←map
call ←init←map
nop
mov %o0, %l0      ! save the memory size      
mov %o0, %sp     ! set SP to its correct value (near sparcMemorySizeByte)
sub %sp, MINFRAME, %sp ! decrement sp by one frame
and %sp, ~7, %sp    ! round down to 0 modulo 8
!
!  Set the memory size (for subsequent calls to MemEnd() )
!
mov %l0, %o0
call ←SetMemEnd
nop
!
!  Set the stack size (for subsequent calls to StackEnd() or HeapEnd() )
!
set  0x100000, %o0  ! arbitrary
call ←SetStackSize
nop
!
! End of assembly code initialization.
!
ba ←init1    ! Jumps to the C init1.c program
nop
!
! leaf subroutine ←place←trap←vector
!
! Places at address trap←number *16 the instruction "b target�ress" followed by "nop"
!
! %o0 holds trap←number
! %o1 holds target�ress
!
←place←trap←vector:
sethi %hi(self), %o2
or  %o2, %lo(self), %o2  ! %o2 holds the address of the instruction "b self"
ld  [%o2] , %o3     ! %o3 holds the instruction "b self"
sll  %o0, 4, %o0     ! %o0 now holds the low part of the trap vector address
set  trapBaseByte, %o4   ! add the trap base address
add  %o0, %o4, %o0    ! %o0 now holds the trap vector address
sub %o1, %o0, %o1    ! byte offset of the vector to program location
srl  %o1, 2, %o1     ! word offset of the vector to program location
add %o3, %o1, %o3    ! %o3 holds the instruction "b target address"
! DANGEROUS overflow not tested
! Fails to produce the right code if the target is more than 8 MegaBytes away.
st  %o3, [%o0]     ! store the branch instruction
ld  [%o2 + 4] , %o3   ! %o3 holds the instruction "nop"
st  %o3, [%o0 + 4]    ! store the nop instruction
retl         ! return from leaf subroutine
nop
place←reset←trap←vector:
sethi %hi(self), %o2
or  %o2, %lo(self), %o2  ! %o2 holds the address of the instruction "b self"
ld  [%o2] , %o3     ! %o3 holds the instruction "b self"
sll  %o0, 4, %o0     ! %o0 now holds the low part of the trap vector address
set  0, %o4      ! add the trap base address
add  %o0, %o4, %o0    ! %o0 now holds the trap vector address
sub %o1, %o0, %o1    ! byte offset of the vector to program location
srl  %o1, 2, %o1     ! word offset of the vector to program location
add %o3, %o1, %o3    ! %o3 holds the instruction "b target address"
! DANGEROUS overflow not tested
! Fails to produce the right code if the target is more than 8 MegaBytes away.
st  %o3, [%o0]     ! store the branch instruction
ld  [%o2 + 4] , %o3   ! %o3 holds the instruction "nop"
st  %o3, [%o0 + 4]    ! store the nop instruction
retl         ! return from leaf subroutine
nop
self:
b self         ! template for ←place←trap←vector and place←reset←trap←vector
nop         ! subroutines. DO NOT REMOVE