382 lines
8.7 KiB
ArmAsm
382 lines
8.7 KiB
ArmAsm
/*
|
|
* srt0.s - standalone startup code
|
|
* .seg "data"
|
|
* .asciz "@(#)srt0.s 1.1 94/10/31"
|
|
* Copyright (c) 1986 by Sun Microsystems, Inc.
|
|
*/
|
|
.seg "text"
|
|
.align 4
|
|
|
|
#include <machine/asm_linkage.h>
|
|
#include <machine/param.h>
|
|
#include <machine/reg.h>
|
|
#include <machine/psl.h>
|
|
#include <machine/trap.h>
|
|
#include <machine/mmu.h>
|
|
#include <mon/idprom.h>
|
|
|
|
/*
|
|
* param.h defines VAC, DELAY, and CDELAY
|
|
* if we are compiling for the bootblock undef VAC
|
|
* to save on code size
|
|
*/
|
|
|
|
#ifdef BOOTBLOCK
|
|
#undef VAC
|
|
#endif
|
|
|
|
/*
|
|
* Initial interrupt priority and how to get there.
|
|
*/
|
|
#define PSR_PIL_SHIFT 8
|
|
#define PSR_PIL_INIT (13 << PSR_PIL_SHIFT)
|
|
|
|
/*
|
|
* The following variables are machine-dependent and are set in fiximp.
|
|
*/
|
|
.seg "data"
|
|
.global _Cpudelay
|
|
/*
|
|
* This variable is used in usec_delay(). See the chart in lib/sparc/misc.s.
|
|
* Srt0.s sets this value based on the actual runtime environment encountered.
|
|
* It's critical that the value be no SMALLER than required, e.g. the
|
|
* DELAY macro guarantees a MINIMUM delay, not a maximum.
|
|
*/
|
|
_Cpudelay: ! count down counter initial value
|
|
#define CPUDELAY_DEFAULT 7
|
|
.word CPUDELAY_DEFAULT ! worst case value (33 Mhz)
|
|
.global _nwindows
|
|
_nwindows:
|
|
#define NWINDOWS_DEFAULT 8
|
|
.word NWINDOWS_DEFAULT ! max # windows...mustn't be too small
|
|
.global _npmgrps
|
|
_npmgrps:
|
|
#define NPMGRPS_DEFAULT 512
|
|
.word NPMGRPS_DEFAULT ! max # pmegs
|
|
.global _vac
|
|
_vac:
|
|
#define VAC_DEFAULT 1
|
|
.word VAC_DEFAULT ! vac is there by default
|
|
.global _vac_size
|
|
_vac_size:
|
|
#define VACSIZE_DEFAULT 0x20000
|
|
.word VACSIZE_DEFAULT ! 128K
|
|
.global _vac_linesize
|
|
_vac_linesize:
|
|
#define VACLINESIZE_DEFAULT 16
|
|
.word VACLINESIZE_DEFAULT
|
|
.global _segmask
|
|
_segmask:
|
|
#define SEGMASK_DEFAULT 0x1ff
|
|
.word SEGMASK_DEFAULT ! segmask is 511 by default
|
|
.global _romp
|
|
/*
|
|
* The following variables are more or less machine-independent
|
|
* (or are set outside of fiximp).
|
|
*/
|
|
_romp:
|
|
.word 0
|
|
.global _cpudelay ! old macros:
|
|
_cpudelay: ! shift right amount to scale (n << 4)
|
|
.word 0 ! worst case value (25 Mhz)
|
|
idp:
|
|
.word 0 ! room for idprom format & mach type
|
|
.word 0
|
|
.global _environ
|
|
_environ:
|
|
.word 0 ! satisfy references from libc
|
|
exitbuf:
|
|
.skip 5*4 ! (jump_buf)exitbuf for _exit routine
|
|
|
|
.seg "text"
|
|
.align 8
|
|
.global _end
|
|
.global _edata
|
|
.global __setjmp
|
|
.global __longjmp
|
|
.global _main
|
|
.global __exit
|
|
.global __exitto
|
|
.global _start
|
|
_start:
|
|
|
|
#ifdef BOOTBLOCK
|
|
.global _begin, _bootb, _bbsize, _bbchecksum
|
|
b,a _begin
|
|
_bootb:
|
|
! should be NBLKENTRIES (64), see installboot.c
|
|
.skip 64*4 ! room for boot_tab
|
|
_bbsize: .word 0
|
|
_bbchecksum: .word 0
|
|
_begin:
|
|
#endif BOOTBLOCK
|
|
|
|
! Each standalone program is responsible for its own stack. Our strategy
|
|
! is that each program which uses this runtime code creates a stack just
|
|
! below its relocation address. Previous windows may (and probably do)
|
|
! have frames allocated on the prior stack; leave them alone. Starting with
|
|
! this window, allocate our own stack frames for our windows. (Overflows
|
|
! or a window flush would then pass seamlessly from our stack to the old.)
|
|
! RESTRICTION: A program running at some relocation address must not exec
|
|
! another which will run at the very same address: the stacks would collide.
|
|
! This is currently not a problem, as all standalone programs (boot, copy,
|
|
! kadb, unix, et al.) run at different, carefully chosen addresses...which
|
|
! is, of course, a crock.
|
|
!
|
|
! Careful: don't touch %o0 until the save, since it holds the romp
|
|
! for Forth PROMs.
|
|
!
|
|
set _start, %o1
|
|
save %o1, -SA(MINFRAME), %sp
|
|
acall:
|
|
call 1f ! get the current pc into o7
|
|
! (where _start is currently located)
|
|
sethi %hi(acall), %o3 ! relocated address of call
|
|
1:
|
|
sub %o7,acall-_start,%o0 ! address where _start is in memory
|
|
or %o3, %lo(acall), %o3 ! relocated address of call
|
|
cmp %o3, %o7
|
|
be jmpstart
|
|
.empty ! next instruction ok in delay slot
|
|
set _edata+4, %o2 ! end of program, inclusive, except bss
|
|
set _start, %o1 ! beginning of program
|
|
sub %o2, %o1, %o2 ! size of program
|
|
2:
|
|
ldd [%o0], %o4 ! relocate program
|
|
inc 8, %o0 ! bcopy
|
|
std %o4, [%o1]
|
|
deccc 8, %o2
|
|
bg 2b
|
|
inc 8, %o1
|
|
|
|
set jmpstart, %l0 ! now that it is relocated, jump to it
|
|
jmp %l0
|
|
nop
|
|
|
|
jmpstart:
|
|
set _romp, %o0 ! Stash the romp we've been saving
|
|
st %i0, [%o0]
|
|
/*
|
|
* We need to read idprom to figure out what we are.
|
|
* Put machine-dependent variables in the following registers:
|
|
* %l0 Cpudelay
|
|
* %l1 nwindows
|
|
* %l2 npmgrps
|
|
* %l3 vac
|
|
* %l4 vac_size
|
|
* %l5 vac_linesize
|
|
*/
|
|
fiximp:
|
|
set idp, %o0
|
|
call _getidprom
|
|
mov 2, %o1
|
|
cmp %o0, IDFORM_1
|
|
mov VACLINESIZE_DEFAULT, %l5
|
|
sethi %hi(VACSIZE_DEFAULT), %l4
|
|
mov VAC_DEFAULT, %l3
|
|
mov NPMGRPS_DEFAULT, %l2
|
|
mov NWINDOWS_DEFAULT, %l1
|
|
bne id_badformat
|
|
mov CPUDELAY_DEFAULT, %l0
|
|
set idp, %o1
|
|
ldub [%o1+1], %o0
|
|
#ifdef sun4
|
|
cmp %o0, IDM_SUN4
|
|
be id_sunrise ! Sunrise?
|
|
cmp %o0, IDM_SUN4_COBRA
|
|
be id_cobra ! Cobra?
|
|
cmp %o0, IDM_SUN4_STINGRAY
|
|
be id_stingray ! Stingray?
|
|
cmp %o0, IDM_SUN4_SUNRAY
|
|
be id_sunray ! Sunray?
|
|
nop
|
|
id_cobra:
|
|
set _segmask, %o1
|
|
set 0xff, %o2
|
|
st %o2, [%o1] ! set segmask to 0xff
|
|
mov 7, %l0 ! set Cpudelay to 7
|
|
mov NPMGRPS_110, %l2 ! set npmgrps
|
|
mov %g0, %l3 ! set vac to zero
|
|
ba set_delay
|
|
.empty ! use delay slot to set nwindows
|
|
/*
|
|
* All of the Cpudelay values used are for cache off.
|
|
*/
|
|
id_sunrise:
|
|
mov 7, %l1 ! set nwindows to 7
|
|
mov NPMGRPS_260, %l2 ! set npmgrps
|
|
ba set_delay
|
|
mov 1, %l0 ! set Cpudelay to 1
|
|
id_stingray:
|
|
mov 7, %l1 ! set nwindows to 7
|
|
mov NPMGRPS_330, %l2 ! set npmgrps
|
|
ba set_delay
|
|
mov 1, %l0 ! set Cpudelay to 1
|
|
id_sunray:
|
|
mov NPMGRPS_460, %l2 ! set npmgrps
|
|
mov VAC_LINESIZE_SUNRAY, %l5
|
|
mov 1, %l0 ! set Cpudelay to 1
|
|
#else sun4
|
|
/*
|
|
* XXX - This should all come from the open prom properties.
|
|
*/
|
|
mov 1, %l0 ! set Cpudelay to 1
|
|
cmp %o0, IDM_SUN4C_60
|
|
be id_campus1 ! Campus-1?
|
|
cmp %o0, IDM_SUN4C_40
|
|
be id_campus1 ! Office-1?
|
|
cmp %o0, IDM_SUN4C_65
|
|
be,a id_campus1 ! Campus-B?
|
|
mov 1, %l0 ! set Cpudelay to 1
|
|
cmp %o0, IDM_SUN4C_20
|
|
be id_campus1 ! Off-campus?
|
|
cmp %o0, IDM_SUN4C_70
|
|
be,a id_calvin ! Calvin?
|
|
mov 1, %l0 ! set Cpudelay to 1
|
|
id_campus1:
|
|
mov 7, %l1 ! set nwindows to 7
|
|
mov NPMGRPS_60, %l2 ! set npmgrps
|
|
sethi %hi(VAC_SIZE_60), %l4
|
|
mov VAC_LINESIZE_60, %l5
|
|
ba set_delay
|
|
mov %g0, %l3 ! set vac to zero
|
|
id_calvin:
|
|
mov 8, %l1 ! set nwindows to 8
|
|
mov 256, %l2 ! set npmgrps
|
|
sethi %hi(VAC_SIZE_60*2), %l4
|
|
mov VAC_LINESIZE_60*2, %l5
|
|
mov %g0, %l3 ! set vac to zero
|
|
#endif sun4
|
|
id_badformat:
|
|
set_delay:
|
|
sethi %hi(_Cpudelay), %o0
|
|
st %l0, [%o0 + %lo(_Cpudelay)] ! set Cpudelay
|
|
sethi %hi(_nwindows), %o0
|
|
st %l1, [%o0 + %lo(_nwindows)] ! set nwindows
|
|
sethi %hi(_npmgrps), %o0
|
|
st %l2, [%o0 + %lo(_npmgrps)] ! set npmgrps
|
|
sethi %hi(_vac), %o0
|
|
st %l3, [%o0 + %lo(_vac)] ! set vac
|
|
sethi %hi(_vac_size), %o0
|
|
st %l3, [%o0 + %lo(_vac_size)]
|
|
sethi %hi(_vac_linesize), %o0
|
|
#ifdef VAC
|
|
call init_cache
|
|
#endif
|
|
st %l3, [%o0 + %lo(_vac_linesize)]
|
|
set _edata, %o0 ! beginning of bss
|
|
set _end+4, %o1 ! end of bss
|
|
call _bzero ! zero the bss
|
|
sub %o1, %o0, %o1 ! size of bss
|
|
|
|
!
|
|
! Set the psr into a known state, until we are sure it is:
|
|
! supervisor mode, interrupt level >= 13, traps enabled
|
|
!
|
|
mov %psr, %o0
|
|
andn %o0, PSR_PIL, %o0
|
|
set PSR_S|PSR_PIL_INIT|PSR_ET, %o1
|
|
or %o0, %o1, %o0
|
|
mov %o0, %psr
|
|
nop; nop; nop
|
|
#ifdef sun4c
|
|
call _l14enable ! turn on level 14 interrupts
|
|
nop
|
|
#endif !sun4c
|
|
!
|
|
! Mark this spot.
|
|
!
|
|
sethi %hi(exitbuf), %o0
|
|
call __setjmp
|
|
or %o0, %lo(exitbuf), %o0
|
|
tst %o0 ! returned 1: we exit now.
|
|
bnz out
|
|
nop
|
|
call _main
|
|
mov 0, %o0 ! delay slot
|
|
! Fall through...
|
|
!
|
|
! __exit means exit NOW. We may be arbitrarily deep in the windows, so longjmp.
|
|
!
|
|
|
|
#ifndef VAC
|
|
|
|
__exit:
|
|
set exitbuf, %o0
|
|
call __longjmp
|
|
mov 1, %o1
|
|
out:
|
|
ret ! ret to prom
|
|
restore
|
|
|
|
__exitto:
|
|
save %sp, -SA(MINFRAME), %sp
|
|
set _romp, %o0 ! pass the romp to the callee
|
|
jmpl %i0, %o7 ! call thru register
|
|
ld [%o0], %o0
|
|
ret
|
|
restore
|
|
|
|
#else !VAC
|
|
|
|
__exit:
|
|
save %sp, -SA(MINFRAME), %sp
|
|
set _vac, %o0 ! check vac flag
|
|
ld [%o0], %o0
|
|
tst %o0
|
|
bz 1f
|
|
call _turnoff_cache
|
|
nop
|
|
1:
|
|
set exitbuf, %o0
|
|
call __longjmp
|
|
mov 1, %o1
|
|
out:
|
|
ret
|
|
restore
|
|
|
|
__exitto:
|
|
save %sp, -SA(MINFRAME), %sp
|
|
!
|
|
! turn off the cache if it's currently on
|
|
!
|
|
set _vac, %o0 ! check vac flag
|
|
ld [%o0], %o0
|
|
tst %o0
|
|
bz no_cache
|
|
nop
|
|
call _turnoff_cache
|
|
nop
|
|
no_cache:
|
|
set _romp, %o0 ! pass the romp to the callee
|
|
jmpl %i0, %o7 ! call thru register
|
|
ld [%o0], %o0
|
|
set _vac, %o0 ! check vac flag
|
|
ld [%o0], %o0
|
|
tst %o0
|
|
bz leave_cache_off
|
|
nop
|
|
call _turnon_cache
|
|
nop
|
|
leave_cache_off:
|
|
ret
|
|
restore
|
|
|
|
init_cache:
|
|
save %sp, -SA(MINFRAME), %sp
|
|
set _vac, %o0 ! check vac flag
|
|
ld [%o0], %o0
|
|
tst %o0
|
|
bz 1f
|
|
.empty
|
|
set _start, %o0 ! this doesn't get the stack
|
|
sethi %hi(_end), %o1
|
|
call _cache_prog ! clear the NC bits for prog's pages
|
|
or %o1, %lo(_end), %o1
|
|
call _turnon_cache
|
|
nop
|
|
1:
|
|
ret
|
|
restore
|
|
#endif VAC
|