Files
seta75D 2e8a93c394 Init
2021-10-11 18:20:23 -03:00

263 lines
6.6 KiB
ArmAsm

.data
.asciz "@(#)locore.s 1.1 92/07/30 SMI"
.even
.text
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
#include <sys/errno.h>
#include <sys/param.h>
#include <machine/asm_linkage.h>
#include <machine/mmu.h>
#include <machine/psl.h>
/*
* The debug stack. This must be the first thing in the data
* segment (other than an sccs string) so that we don't stomp
* on anything important. We get a red zone below this stack
* for free when the text is write protected. Since the debugger
* is loaded with the "-N" flag, we pad this stack by a page
* because when the page level protection is done, we will lose
* part of this stack. Thus the usable stack will be at least
* MIN_STACK_SZ bytes and at most MIN_STACK_SZ+NBPG bytes.
*/
#define MIN_STACK_SZ 0x2000
.data
.globl _estack
. = . + NBPG + MIN_STACK_SZ
_estack: | end (top) of debugger stack
.text
#define SAVEALL() \
clrw sp@-;\
movl sp,sp@-;\
moveml #0xfffe,sp@-;\
movc dfc,d1;\
movc sfc,d0;\
moveml #0xc000,sp@-
#define RESTOREALL() \
moveml sp@+,#0x0003;\
movc d0,sfc;\
movc d1,dfc;\
moveml sp@+,#0x7fff;\
addqw #6,sp
/*
* Debugger receives control at the label `_start' which
* must be at offset zero in this file; this file must
* be the first thing in the boot image. At start
* is a struct dvec.
*/
ENTRY(start)
bra 0f | dv_entry
.long _trap | dv_trap
.long _pagesused | dv_pages
.long _scbsync | dv_scbsync
.long 0
/*
* First we must figure out if we are running in correctly adjusted
* addresses. If so, we must have been called via a jsr to _start
* and thus we just want to call the command interpreter. If not,
* then we continue to run in the wrong adddress. All of the code
* must be carefully written to be position independent code, since
* we are linked for running out of high addresses, but we get control
* running in low addresses. We run off the stack set up by the caller.
*/
#ifndef sun3x
#ifndef CTXSIZE
#define CTXSIZE (NBSG * NSEGMAP)
#endif !CTXSIZE
#endif !sun3x
0:
movl a0,sp@- | save a0
#ifndef sun3x
movl d0,sp@- | and d0
#endif sun3x
leax: lea pc@(_start-(leax+2)),a0 | a0 = true current location of _start
#ifndef sun3x
movl a0,d0 | get a copy that we can play with
andl #CTXSIZE-1,d0 | mask off unused virtual bits to
movl d0,a0 | avoid believing them
movl sp@+,d0 | restore d0, we don't need it anymore
#endif sun3x
cmpl #_start,a0 | is desired value == current value?
movl sp@+,a0 | restore a0 - NOTE, cc not affected
beq docall | if relocated already, go to docall()
| first time through, still be careful
lea _startup,a1 | virtual startup address
subl #_start,a1 | subtract off virtual load address
addl a0,a1 | a1 has adjusted startup
pea a0@
jsr a1@ | CALL(startup)(real);
addqw #4,sp
jmp cont:l | force non-PC rel branch
cont:
/*
* PHEW! Now we are running with correct addresses
* and can use non-position independent code.
*/
jsr _main
rts | should not return
/*
* This is where we break into when we catch a breakpoint
*/
ENTRY(trap)
movw #SR_HIGH,sr
SAVEALL()
jsr _cmd
ret:
RESTOREALL()
rte
/*
* This is where we break into when trace trap is taken
*/
ENTRY(trace)
tstl _dotrace | are we expecting this?
jeq ktraceret | if not branch
movw #SR_HIGH,sr
SAVEALL()
jsr _cmd
tstl d0 | test return value
jeq ret | if 0, then simply return
RESTOREALL() | else restore regs and
| pass trace exception to debuggee
ktraceret: | go to kernel's trace routine
movl _ktrace,sp@- | push address to goto
rts | and get there as if nothing happened
/*
* This is where we call to enter debugger (i.e. from
* monitor command or an explicit call from kernel).
*/
.data
pcsave: .long 0
.text
docall:
movl sp@+,pcsave | copy return pc
clrw sp@- | zero out fake fmt value
movl pcsave,sp@- | push return pc
movw sr,sp@-
movw #SR_HIGH,sr
SAVEALL()
jsr _cmd
jra ret
ENTRY(fault)
movw #SR_HIGH,sr
SAVEALL()
/*
* Reset the sfc and dfc to FC_MAP to avoid problems if the
* monitor was dorking with these registers. We don't have
* to worry about the current contents of sfc and dfc as
* they are restored to the original value before returning
* to the program being debugged.
*/
lea FC_MAP,a0
movc a0,dfc
movc a0,sfc
jsr _faulterr | call fault handler
jsr _cmd | not resolved, go into debugger
jra ret | try to return back now
ENTRY(getvbr)
movc vbr,d0
rts
/*
* peekl(addr)
*
* peekl() and pokel() are like the standard peek (peekc) and
* poke (pokec) functions except they use longwords and set
* errno to EFAULT on failure (so that succeeding w/ -1 looks
* different than a failure).
*/
ENTRY(peekl)
movl sp@(4),a0 | Get address to probe
movc vbr,a1 | get vbr
movl a1@(8),d1 | save bus error handler
movl #BEhand,a1@(8) | set up our own handler
movl sp,a1 | save current stack pointer
movl a0,d0
btst #0,d0 | See if odd address
bne BEhand | Yes, the probe fails.
movl a0@,d0 | Read a longword.
PAexit:
movc vbr,a1 | get vbr
movl d1,a1@(8) | restore bus error handler
rts
BEhand:
movl a1,sp | Restore stack after bus error
moveq #-1,d0 | Set result of -1, indicating fault.
movl #EFAULT,_errno | Indicate failure using errno
bra PAexit
ENTRY(pokel)
movl sp@(4),a0 | Get address to probe
movc vbr,a1 | get vbr
movl a1@(8),d1 | save bus error handler
movl #BEhand,a1@(8) | set up our own handler
movl sp,a1 | save current stack pointer
movl sp@(8),a0@ | Write a longword
| A fault in the movl will vector us to BEhand above.
moveq #0,d0 | It worked; return 0 as result.
bra PAexit | restores bus error handler and returns - above
/*
* Peekc is so named to avoid a naming conflict
* with adb which has a variable named peekc
*/
ENTRY(Peekc)
movl sp@(4),a0 | Get address to probe
movc vbr,a1 | get vbr
movl a1@(8),d1 | save bus error handler
movl #BEhand,a1@(8) | set up our own handler
movl sp,a1 | save current stack pointer
moveq #0,d0 | Clear upper half
movb a0@,d0 | Read a byte
| A fault in the movb will vector us to BEhand above.
bra PAexit | restores bus error handler and returns - above
/*
* Return current sp value to caller
*/
ENTRY(getsp)
movl sp,d0
rts
#if defined(sun3) || defined(sun3x)
/*
* Flush '20 or '30 instruction cache
*/
ENTRY(flush20)
movc cacr,d0 | get current cache control register
#ifdef sun3
orl #CACHE_CLEAR,d0 | or in clear flag
#endif sun3
#ifdef sun3x
orl #ICACHE_CLEAR,d0 | or in clear flag
#endif sun3x
movc d0,cacr | clear cache (regardless of state)
rts
#endif sun3 || sun3x
ENTRY(_exitto)
movl sp@(4),a0 | Address to call.
jsr a0@ | Jump to callee using caller's stack.
rts