| /* |
| * 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" |