summaryrefslogtreecommitdiffstats
path: root/usr/klibc/arch/sparc/crt0i.S
blob: 0220b01fcdfa4f38e001fd36ca1ddf98ba574905 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
! This file derived from the equivalent in newlib
!
! C run time start off

! This file supports:
!
! - both 32bit pointer and 64bit pointer environments (at compile time)
! - an imposed stack bias (of 2047) (at run time)
! - medium/low and medium/anywhere code models (at run time)

! Initial stack setup:
!
!    bottom of stack (higher memory address)
! 	...
!	text of environment strings
!	text of argument strings
!	envp[envc] = 0 (4/8 bytes)
!	...
!	env[0] (4/8 bytes)
!	argv[argc] = 0 (4/8 bytes)
!	...
!	argv[0] (4/8 bytes)
!	argc (4/8 bytes)
!	register save area (64 bits by 16 registers = 128 bytes)
!	top of stack (%sp)

! Stack Bias:
!
! It is the responsibility of the o/s to set this up.
! We handle both a 0 and 2047 value for the stack bias.

! Medium/Anywhere code model support:
!
! In this model %g4 points to the start of the data segment.
! The text segment can go anywhere, but %g4 points to the *data* segment.
! It is up to the compiler/linker to get this right.
!
! Since this model is statically linked the start of the data segment
! is known at link time.  Eg:
!
!	sethi	%hh(data_start), %g1
!	sethi	%lm(data_start), %g4
!	or	%g1, %hm(data_start), %g1
!	or	%g4, %lo(data_start), %g4
!	sllx	%g1, 32, %g1
!	or	%g4, %g1, %g4
!
! FIXME: For now we just assume 0.

! FIXME: if %g1 contains a non-zero value, atexit() should be invoked
! with this value.


	.text
	.align 4
	.globl _start
	.type _start, @function
_start:
	clr	%fp

! We use %g4 even if the code model is Medium/Low (simplifies the code).

	clr	%g4			! Medium/Anywhere base reg

! If there is a stack bias in effect, account for it in %g5.  Then always
! add %g5 to stack references below.  This way the code can be used with
! or without an imposed bias.

	andcc	%sp, 1, %g5
	bz,a .LNoBias
	 nop
	mov	2047, %g5
.LNoBias:
	add	%sp, %g5, %g5

! On entry, the kernel leaves room for one register frame, but
! the C API wants more free space.  Thus, we need to drop the stack
! pointer additionally.

#if TARGET_PTR_SIZE == 32
	sub	%sp, 32, %sp		! make room for incoming arguments
#else /* TARGET_PTR_SIZE == 64 */
	sub	%sp, 64, %sp		! make room for incoming arguments
#endif

! Set up pointers to the ELF data structure (argc, argv, ...)
! Pass as the first argument to __libc_init
#if TARGET_PTR_SIZE == 32
	add	%g5, 0x40, %o0
#else /* TARGET_PTR_SIZE == 64 */
	add	%g5, 0x80, %o0
#endif

	call	__libc_init
	 mov	%g1, %o1	! This is the "atexit" pointer;
				! pass as the second argument to __libc_init

! If __libc_init returns, something is hosed.  Try an illegal insn.
! If that does not work, the o/s is hosed more than we are.
	.long 0