-
Notifications
You must be signed in to change notification settings - Fork 25
/
crt0.s
193 lines (160 loc) · 3.63 KB
/
crt0.s
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
#
# $Id: crt0.s 1066 2005-04-29 10:25:23Z pixel $
# Standard startup file.
.set noat
.set noreorder
.global _start
.global _exit
# Support for _init() and _fini().
.global _init
.global _fini
.type _init, @function
.type _fini, @function
# The .weak keyword ensures there's no error if
# _init/_fini aren't defined.
.weak _init
.weak _fini
.extern _heap_size
.extern _stack
.extern _stack_size
.text
nop
nop
.ent _start
_start:
# Clear bss elf segment (static uninitalised data)
zerobss:
la $2, _fbss
la $3, _end
loop:
nop
nop
nop
sq $0,($2)
sltu $1,$2,$3
bne $1,$0,loop
addiu $2,$2,16
# Some program loaders (such as Pukklink) execute programs as a thread, but
# support passing argc and argv values via a0. This also indicates that when
# the program terminates, control should be returned to the program loader
# instead of the PS2 browser.
la $2, _args_ptr
sw $4,($2)
# Setup a thread to use
la $4, _gp
la $5, _stack
la $6, _stack_size
la $7, _args
la $8, _root
move $28,$4
addiu $3,$0,60
syscall # RFU060(gp, stack, stack_size, args, root_func)
move $29, $2
# Heap
addiu $3,$0,61
la $4, _end
la $5, _heap_size
syscall # RFU061(heap_start, heap_size)
nop
# Flush the data cache (no need to preserve regs for this call)
li $3, 0x64
move $4,$0
syscall # FlushCache(0) - Writeback data cache
# Let's try to set up the initial cwd; have to pass on argc and argv.
# That may be used for other purposes as well, such as tweaking the command
# line on the fly, while providing gnu-style "generic option system".
# Check for arguments pased via ExecPS2 or LoadExecPS2
la $2, _args
lw $3, ($2)
bnez $3, 1f
nop
# Otherwise check for arguments passed by a loader via a0 (_arg_ptr)
la $2, _args_ptr
lw $3, ($2)
beqzl $3, 2f
addu $4, $0, 0
addiu $2, $3, 4
1:
lw $4, ($2)
addiu $5, $2, 4
2:
# just get rid of it - we're not sending any args, but executing through ExecPS2, so a0 != 0, here will most likely tlbmiss occur
jal _ps2sdk_args_parse
nop
nop
# Call ps2sdk's libc initialisation.
jal _ps2sdk_libc_init
nop
# Call global constructors through _init().
la $8, _init
beqz $8, 1f # does _init() exist?
nop
jalr $8
nop
1:
# Jump main, now that environment and args are setup
ei
# Check for arguments pased via ExecPS2 or LoadExecPS2
la $2, _args
lw $3, ($2)
bnez $3, 1f
nop
# Otherwise check for arguments passed by a loader via a0 (_arg_ptr)
la $2, _args_ptr
lw $3, ($2)
beqzl $3, 2f
addu $4, $0, 0
addiu $2, $3, 4
1:
lw $4, ($2)
addiu $5, $2, 4
2:
jal main
nop
.end _start
.ent _exit
_exit:
# Call global deconstructors through _fini().
la $8, _fini
beqz $8, 3f # does _fini() exist?
nop
jalr $8
nop
3:
# Call ps2sdk's libc deinitialisation.
jal _ps2sdk_libc_deinit
nop
# If we received our program arguments in a0, then we were executed by a
# loader, and we don't want to return to the browser.
la $4, _args_ptr
lw $5, ($4)
beqz $5, 1f
move $4, $2 # main()'s return code
lw $6, ($5)
sw $0, ($6)
addiu $3, $0, 36
syscall # ExitDeleteThread(void)
# Return to the browser via Exit()
1:
addiu $3, $0, 4
syscall # Exit(void)
.end _exit
# Call ExitThread()
.ent _root
_root:
addiu $3, $0, 35
syscall
.end _root
.bss
.align 6
_args:
.space 256+16*4+4
_args_ptr:
.space 4