/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
.file "sbcp.s"
#include <sys/asm_linkage.h>
#include <sys/link.h>
#include <sys/syscall.h>
#define PIC_SETUP(r) \
mov %o7, %g1; \
9: call 8f; \
sethi %hi(_GLOBAL_OFFSET_TABLE_ - (9b - .)), %r; \
8: or %r, %lo(_GLOBAL_OFFSET_TABLE_ - (9b - .)), %r; \
add %r, %o7, %r; \
mov %g1, %o7
#define FUNC(x) \
.section ".text"; \
.align 4; \
.type x, #function; \
x:
#define ENOSYS 90 /* 4.x ENOSYS */
/* derived from <sys/exechdr.h>, which we can't include */
#define A_MAGIC 0x02 /* offset of a_magic field */
#define A_ENTRY 0x14 /* offset of a_entry field */
#define ZMAGIC 0413 /* magic number for demand paged executable */
.global atexit, errno
!
! _start - execution starts here (after the runtime linker runs)
!
! The SPARC ABI defines our "environment" at this point, see page 3-34.
! Register the exit handler, register the trap0 handler, find the
! entry point, and jump to it. We depend on the stack (argv, envp)
! being compatible between 4.x and 5.x. We also depend on the
! runtime linker to set up ``environ''.
!
ENTRY_NP(_start)
tst %g1 ! is there a handler to register?
bz 1f ! no
nop
mov %g1, %o0
call atexit ! yes, register it with atexit()
nop
1:
!
! Aside from a value in %g1, there were no arguments explicitly
! passed to this routine, but we do know how our initial stack has
! been setup by the kernel. The stack format is documented in:
! usr/src/cmd/sgs/rtld/sparc/boot.s
! usr/src/cmd/sgs/rtld/sparcv9/boot.s
!
! Since we want to invoke the following c initalization routine:
! sbcp_init(int argc, char *argv[], char *envp[]))
! we need to troll through the stack to setup it's argument values.
!
save %sp, -SA(MINFRAME + EB_MAX_SIZE32), %sp
ldn [%fp + WINDOWSIZE + STACK_BIAS], %o0 ! get argc
add %fp, + WINDOWSIZE + CPTRSIZE + STACK_BIAS, %o1 ! get argv
add %o0, 1, %l0 ! add 1 to argc for last element of 0
sll %l0, CPTRSHIFT, %l0 ! multiply argc by pointer size
add %o1, %l0, %o2 ! and add to argv to get envp
call sbcp_init ! Call our c initalization routine
nop
restore
PIC_SETUP(g2)
ld [%g2+trap0], %g1
ta 9
! jump to the main program's entry point
sethi %hi(0x2000), %o0
lduh [%o0 + A_MAGIC], %g1
cmp %g1, ZMAGIC ! is it a ZMAGIC executable?
be,a 1f ! yes,
ld [%o0 + A_ENTRY], %o0 ! get entry point
1: ! else, assume entry point is 0x2000
jmp %o0
nop
SET_SIZE(_start)
!
! trap0 - glue between 4.x syscall trap and 5.x BCP routine
!
! enter with:
! %g1 syscall number
! %g6 return address (after trap instruction)
!
! We used to use %g7, but that conflicts with threading code
! which uses %g7 as the curthread pointer. That is why we
! changed to using %g6 instead.
!
! We use an extra window to save the %o registers we're entered
! with (which the 4.x system call stubs depend on) and to allow
! recursive traps (e.g., from a signal handler).
!
FUNC(trap0)
save %sp, -SA(MINFRAME), %sp
tst %g1
be 1f
nop
mov %i0, %o0
mov %i1, %o1
mov %i2, %o2
mov %i3, %o3
mov %i4, %o4
mov %i5, %o5
ba,a 2f
1:
! indir syscall
mov %i0, %g1
mov %i1, %o0
mov %i2, %o1
mov %i3, %o2
mov %i4, %o3
mov %i5, %o4
ld [%fp + MINFRAME], %o5
2:
sll %g1, 4, %l1
PIC_SETUP(l0)
ld [%l0+sysent], %l0
add %l1, %l0, %l1
jmp %l1 ! jump into branch table
nop
SET_SIZE(trap0)
FUNC(trap0rtn)
cmp %o0, -1
bne 1f
addcc %g0, %g0, %g0 ! psr &= ~C
PIC_SETUP(o1)
ld [%o1+errno], %o1
ld [%o1], %o0
subcc %g0, 1, %g0 ! psr |= C
1:
mov %o0, %i0
restore
jmp %g6
nop
SET_SIZE(trap0rtn)
!
! nullsys
!
FUNC(nullsys)
clr %o0
b,a trap0rtn
SET_SIZE(nullsys)
!
! nosys
!
FUNC(nosys)
set ENOSYS, %o1
PIC_SETUP(g2)
ld [%g2+errno], %g2
st %o1, [%g2]
set -1, %o0
b,a trap0rtn
SET_SIZE(nosys)
!
! Have to #include the sysent table and stubs so that all
! symbols referenced between here and there are "static"
! to this module so the assembler can resolve them without
! the linker needing to deal with them at run time.
!
#include "sysent.s"