1
2 #
3
4 #
5
6
7
8
9 #
10
11
12
13
14 #
15
16
17
18 include(`config-mips.m4')
19
20
21
22
23 .set noreorder # delay slots managed by hand
24 .section .text
25 .global __start
26 __start:
27 dnl li $v0, SYSCALL_nanosleep # SYS_nanosleep
28 dnl la $a0, .timespec # rqtp
29 dnl li $a1, 0 # rmtp
30 dnl syscall # syscall
31 lw $s6, ($sp) # original stack pointer
32 addi $s0, $sp, 8 # start of load area
33 addi $sp, -8 # primary fd, secondary fd
34 li $t0, -1 # secondary fd
35 sw $t0, 4($sp) # initialize secondary fd
36 .next_action:
37 lw $s2, ($s0) # action number
38 nop # delay slot
39 andi $t0, $s2, 15 # t0 = s2 & 15
40 beqz $t0, .open_file # open file?
41 li $t1, 3 # t1 = 3, delay slot
42 beq $t0, $t1, .rest_of_exec # jump to code
43 li $t1, 4 # t1 = 4, delay slot
44 beq $t0, $t1, .do_mmap_anon # anonymous mmap
45 .do_mmap:
46 lw $a0, 4($s0) # vm_address, delay slot
47 lw $v1, 8($s0) # file_offset
48 lw $a2, 12($s0) # protection
49 lw $a1, 16($s0) # length
50 lw $a3, 20($s0) # flags
51 lw $v0, ($sp) # primary fd
52 andi $t1, $s2, 16 # t1 = s2 & 16
53 beqz $t1, .do_mmap_1 # secondary fd?
54 nop # delay slot
55 lw $v0, 4($sp) # secondary fd
56 nop # delay slot
57 .do_mmap_1:
58 SYSCALL(`$v0',`$v1',`$zero',`$zero') # syscall args
59 li $v0, SYSCALL_mmap # SYS_mmap
60 syscall # syscall
61 bne $a3, $zero, .perror # perror
62 RESTORE() # delay slot, restore sp
63 lw $s5, 24($s0) # clear
64 add $t0, $a0, $a1 # t0 = length + vm_address, delay slot
65 sub $t1, $t0, $s5 # t1 = t0 - clear
66 .align:
67 beq $t0, $t1, .continue # already finished?
68 nop # delay slot
69 andi $t2, $t1, 3 # t1 & 3?
70 bnez $t2, .fillw # start filling longs
71 nop # delay slot
72 sb $zero, ($t1) # clear byte
73 addi $t1, $t1, 1 # t1++
74 j .align # continue
75 nop # delay slot
76 .fillw:
77 sub $t2, $t0, $t1 # t2 = t0 - t1
78 sltiu $t2, $t2, 32 # r2 < 32?
79 bne $t2, $zero, .fillb # fill bytes
80 nop # delay slot
81 sw $zero, ($t1) # zero word
82 addi $t1, $t1, 4 # next word
83 sw $zero, ($t1) # zero word
84 addi $t1, $t1, 4 # next word
85 sw $zero, ($t1) # zero word
86 addi $t1, $t1, 4 # next word
87 sw $zero, ($t1) # zero word
88 addi $t1, $t1, 4 # next word
89 sw $zero, ($t1) # zero word
90 addi $t1, $t1, 4 # next word
91 sw $zero, ($t1) # zero word
92 addi $t1, $t1, 4 # next word
93 sw $zero, ($t1) # zero word
94 addi $t1, $t1, 4 # next word
95 sw $zero, ($t1) # zero word
96 addi $t1, $t1, 4 # next word
97 j .fillw # fill either word or byte
98 nop # delay slot
99 .fillb:
100 beq $t0, $t1, .continue # already finished?
101 nop # delay slot
102 sb $zero, ($t1) # clear byte
103 addi $t1, $t1, 1 # t1++
104 .continue:
105 addi $s0, $s0, 28 # s0 = next action
106 j .next_action # next action
107 nop # delay slot
108 .do_mmap_anon:
109 lw $v1, 8($s0) # file_offset
110 lw $a2, 12($s0) # protection
111 lw $a1, 16($s0) # length
112 lw $a3, 20($s0) # flags
113 li $t4, -1 # fd
114 j .do_mmap_1 # do mmap
115 nop # delay slot
116 .open_file:
117 li $v0, SYSCALL_open # SYS_open
118 addi $a0, $s0, 4 # start of name
119 move $a1, $zero # flags = O_RDONLY
120 move $a2, $zero # mode = 0
121 syscall # syscall
122 bne $a3, $zero, .perror # perror
123 addi $s0, $s0, 4 # start of string, delay slot
124 move $t3, $s0 # t3 = char past separator
125 .nextc:
126 lb $t0, ($s0) # load byte
127 addi $s0, $s0, 1 # s0++
128 li $t1, 47 # directory separator `/'
129 bne $t0, $t1, .nextc1 # is separator char?
130 nop # delay slot
131 move $t3, $s0 # t3 = char past separator
132 .nextc1:
133 bnez $t0, .nextc # next character?
134 nop # delay slot
135 addi $s0, $s0, 3 # adjust for round
136 li $t2, -4 # t2 = -4
137 and $s0, $s0, $t2 # mask for round
138 andi $t0, $s2, 16 # t1 = s2 & 16
139 beqz $t0, .primary # primary fd?
140 move $t0, $sp # address of primary fd, delay slot
141 addi $t0, $t0, 4 # address of secondary fd
142 j .next_action # next action
143 .primary:
144 sw $v0, ($t0) # store fd, delay slot
145 li $v0, SYSCALL_prctl # SYS_prctl
146 li $a0, 15 # PR_SET_NAME
147 move $a1, $t3 # name
148 move $a2, $zero # arg1
149 move $a3, $zero # arg2
150 SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args
151 syscall # syscall
152 RESTORE() # restore sp
153 j .next_action # next action
154 nop # delay slot
155 .perror:
156 move $a0, $v0 # errno
157 li $v0, SYSCALL_exit # SYS_exit
158 syscall # syscall
159 .rest_of_exec:
160 move $s1, $s6 # s1 = original SP
161 lw $t0, ($s1) # argc
162 nop # delay slot
163 sll $t0, $t0, 2 # argc *= 4
164 addi $t0, $t0, 8 # argc += 8
165 add $s1, $s1, $t0 # s1 = start of envp
166 .skipenv:
167 lw $t0, ($s1) # t0 = *s1
168 addi $s1, $s1, 4 # s1++
169 bne $t0, $zero, .skipenv # skip again
170 nop # delay slot
171 la $s2, .auxvtab # address of auxv table
172 .one_auxv:
173 lw $t0, ($s1) # t0 = auxv type
174 li $t1, 10 # t1 = 10, delay slot
175 beqz $t0, .finish # is AT_IGNORE?
176 sltu $t1, $t0, $t1 # t1 = t0 < num offsets, delay slot
177 beq $t1, $zero, .next # next auxv
178 sll $t1, $t0, 2 # t1 = t0 * 4, delay slot
179 add $t1, $s2, $t1 # t1 = .auxvtab + t1
180 lw $t2, ($t1) # t2 = *t1
181 nop # delay slot
182 beqz $t2, .next # skip auxv
183 add $t2, $s0, $t2 # t2 = s0 + t2
184 lw $t2, ($t2) # t2 = *t2
185 nop # delay slot
186 sw $t2, 4($s1) # set auxv value
187 .next:
188 addi $s1, $s1, 8 # next auxv
189 j .one_auxv # next auxv
190 nop # delay slot
191 .finish:
192 lw $t0, 4($sp) # secondary fd
193 lw $s1, ($sp) # primary fd, delay slot, preserved
194 li $t2, -1 # immediate -1
195 beq $t0, $t2, .finish1 # secondary fd set?
196 li $v0, SYSCALL_close # SYS_close, delay slot
197 move $a0, $t0 # fd
198 syscall # syscall
199 li $v0, SYSCALL_close # SYS_close
200 .finish1:
201 move $a0, $s1 # primary fd
202 syscall # syscall
203 li $v0, SYSCALL_prctl # SYS_prctl
204 li $a0, 45 # PR_SET_FP_MODE
205 lw $a1, 28($s0) # fpu_mode
206 move $a2, $zero # arg3
207 move $a3, $zero # arg4
208 SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args
209 syscall # syscall
210 RESTORE() # restore sp
211 .jump:
212 move $v0, $zero # rtld_fini
213 lw $t0, 4($s0) # entry
214 move $sp, $s6 # restore stack pointer, delay slot
215 jr $t0 # enter
216 nop # delay slot
217
218 .auxvtab:
219 .long 0 # 0
220 .long 0 # 1
221 .long 0 # 2
222 .long 20 # 3 AT_PHDR
223 .long 12 # 4 AT_PHENT
224 .long 16 # 5 AT_PHNUM
225 .long 0 # 6
226 .long 24 # 7 AT_BASE
227 .long 0 # 8
228 .long 8 # 9 AT_ENTRY
229
230 .timespec:
231 .long 10
232 .long 10
233
234
235
236