aboutsummaryrefslogtreecommitdiffstats
path: root/exec
diff options
context:
space:
mode:
authorPo Lu2025-04-14 21:28:15 +0800
committerPo Lu2025-04-14 21:31:07 +0800
commit74df372398dbc90f6c0185f1701af28129073de7 (patch)
tree2ef25ec64d9d6845029801bef81422415b2d9ccf /exec
parent4918de1699152e98c7aaa3ecb21795a3cbd05194 (diff)
downloademacs-74df372398dbc90f6c0185f1701af28129073de7.tar.gz
emacs-74df372398dbc90f6c0185f1701af28129073de7.zip
Port recent changes to mipsel systems
* exec/exec.c (exec_0): Don't disable AT_EXECFN substitution on MIPS systems. * exec/loader-aarch64.s (skip_environ): Correct typo in commentary. * exec/loader-mips64el.s: Add a disclaimer that this file is currently inoperable. * exec/loader-mipsel.s (__start): Move environment and argument vectors and produce and replace AT_EXECFN. Clear stack before proceeding to circumvent an oversight in glibc.
Diffstat (limited to 'exec')
-rw-r--r--exec/config-mips.m4.in2
-rw-r--r--exec/exec.c13
-rw-r--r--exec/loader-aarch64.s2
-rw-r--r--exec/loader-mips64el.s2
-rw-r--r--exec/loader-mipsel.s306
5 files changed, 224 insertions, 101 deletions
diff --git a/exec/config-mips.m4.in b/exec/config-mips.m4.in
index c42bbbad2ec..1c9a4c293a6 100644
--- a/exec/config-mips.m4.in
+++ b/exec/config-mips.m4.in
@@ -18,6 +18,7 @@ dnl You should have received a copy of the GNU General Public License
18dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 18dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 19
20define(`SYSCALL_open', `ifelse(`@MIPS_N32@',`yes',`6002',`4005')') 20define(`SYSCALL_open', `ifelse(`@MIPS_N32@',`yes',`6002',`4005')')
21dnl define(`SYSCALL_openat', `ifelse(`@MIPS_N32@',`yes',`6251',`4288')')
21define(`SYSCALL_close', `ifelse(`@MIPS_N32@',`yes',`6003',`4006')') 22define(`SYSCALL_close', `ifelse(`@MIPS_N32@',`yes',`6003',`4006')')
22define(`SYSCALL_mmap', `ifelse(`@MIPS_N32@',`yes',`6009',`4090')') 23define(`SYSCALL_mmap', `ifelse(`@MIPS_N32@',`yes',`6009',`4090')')
23define(`SYSCALL_nanosleep', `ifelse(`@MIPS_N32@',`yes',`6034',`4166')') 24define(`SYSCALL_nanosleep', `ifelse(`@MIPS_N32@',`yes',`6034',`4166')')
@@ -34,6 +35,7 @@ define(`SYSCALL', `ifelse(`@MIPS_N32@',`yes',` move $a4, $1
34 sw $4, 28($sp)')') 35 sw $4, 28($sp)')')
35 36
36define(`RESTORE', `ifelse(`@MIPS_N32@',`yes',` nop',` addi $sp, 32')') 37define(`RESTORE', `ifelse(`@MIPS_N32@',`yes',` nop',` addi $sp, 32')')
38define(`FP', `ifelse(`@MIPS_N32@',`yes',`$s8',`$fp')')
37 39
38dnl For mips64. Some assemblers don't want to assemble `daddi'. 40dnl For mips64. Some assemblers don't want to assemble `daddi'.
39define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $2 41define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $2
diff --git a/exec/exec.c b/exec/exec.c
index 7a8ef2c3a1a..b9c3e4ec92a 100644
--- a/exec/exec.c
+++ b/exec/exec.c
@@ -231,10 +231,10 @@ struct exec_jump_command
231 /* The value of AT_BASE inside the aux vector. */ 231 /* The value of AT_BASE inside the aux vector. */
232 USER_WORD at_base; 232 USER_WORD at_base;
233 233
234#if defined __mips__ && !defined MIPS_NABI 234#if defined __mips__
235 /* The FPU mode to apply. */ 235 /* The FPU mode to apply. Not used when !MIPS_NABI. */
236 USER_WORD fpu_mode; 236 USER_WORD fpu_mode;
237#endif /* defined __mips__ && !defined MIPS_NABI */ 237#endif /* defined __mips__ */
238}; 238};
239 239
240 240
@@ -916,9 +916,7 @@ exec_0 (char *name, struct exec_tracee *tracee,
916 program_header program; 916 program_header program;
917 USER_WORD entry, program_entry, offset; 917 USER_WORD entry, program_entry, offset;
918 USER_WORD header_offset; 918 USER_WORD header_offset;
919#ifndef __mips__
920 USER_WORD name_len, aligned_len; 919 USER_WORD name_len, aligned_len;
921#endif /* !__mips__ */
922 struct exec_jump_command jump; 920 struct exec_jump_command jump;
923#if defined __mips__ && !defined MIPS_NABI 921#if defined __mips__ && !defined MIPS_NABI
924 int fpu_mode; 922 int fpu_mode;
@@ -1132,6 +1130,8 @@ exec_0 (char *name, struct exec_tracee *tracee,
1132 fpu_mode = FP_FRE; 1130 fpu_mode = FP_FRE;
1133 1131
1134 jump.fpu_mode = fpu_mode; 1132 jump.fpu_mode = fpu_mode;
1133#elif defined __mips__
1134 jump.fpu_mode = 0;
1135#endif /* defined __mips__ && !defined MIPS_NABI */ 1135#endif /* defined __mips__ && !defined MIPS_NABI */
1136 1136
1137 /* The offset used for at_phdr should be that of the first 1137 /* The offset used for at_phdr should be that of the first
@@ -1149,8 +1149,6 @@ exec_0 (char *name, struct exec_tracee *tracee,
1149 sizeof jump); 1149 sizeof jump);
1150 loader_area_used += sizeof jump; 1150 loader_area_used += sizeof jump;
1151 1151
1152 /* TODO: MIPS support. */
1153#ifndef __mips__
1154 /* Copy the length of NAME and NAME itself to the loader area. */ 1152 /* Copy the length of NAME and NAME itself to the loader area. */
1155 name_len = strlen (name); 1153 name_len = strlen (name);
1156 aligned_len = ((name_len + 1 + sizeof name_len - 1) 1154 aligned_len = ((name_len + 1 + sizeof name_len - 1)
@@ -1167,7 +1165,6 @@ exec_0 (char *name, struct exec_tracee *tracee,
1167 offset = aligned_len - (name_len + 1); 1165 offset = aligned_len - (name_len + 1);
1168 while (offset--) 1166 while (offset--)
1169 loader_area[loader_area_used++] = '\0'; 1167 loader_area[loader_area_used++] = '\0';
1170#endif /* !__mips__ */
1171 1168
1172 /* Close the file descriptor and return the number of bytes 1169 /* Close the file descriptor and return the number of bytes
1173 used. */ 1170 used. */
diff --git a/exec/loader-aarch64.s b/exec/loader-aarch64.s
index 376f439417f..d3c565bf3f8 100644
--- a/exec/loader-aarch64.s
+++ b/exec/loader-aarch64.s
@@ -144,7 +144,7 @@ skip_environ:
144 and x7, x7, -8 // align value 144 and x7, x7, -8 // align value
145 add x4, x7, x4 // destination argc 145 add x4, x7, x4 // destination argc
146 and x4, x4, -16 // align destination argc 146 and x4, x4, -16 // align destination argc
147 // Load values that must be into registers x14-x19. 147 // Load values that must be preserved into registers x14-x19.
148 // x14 = cmd->entry 148 // x14 = cmd->entry
149 // x15 = cmd->at_entry 149 // x15 = cmd->at_entry
150 // x16 = cmd->at_phent 150 // x16 = cmd->at_phent
diff --git a/exec/loader-mips64el.s b/exec/loader-mips64el.s
index 491b7ccfb60..1493af3c309 100644
--- a/exec/loader-mips64el.s
+++ b/exec/loader-mips64el.s
@@ -15,6 +15,8 @@
15# You should have received a copy of the GNU General Public License 15# You should have received a copy of the GNU General Public License
16# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 16# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
17 17
18 /* NOTE: this file is presently non-functional. */
19
18include(`config-mips.m4') 20include(`config-mips.m4')
19 21
20 .set noreorder # delay slots managed by hand 22 .set noreorder # delay slots managed by hand
diff --git a/exec/loader-mipsel.s b/exec/loader-mipsel.s
index 9ffe7e928e7..bf90493e726 100644
--- a/exec/loader-mipsel.s
+++ b/exec/loader-mipsel.s
@@ -15,34 +15,34 @@
15# You should have received a copy of the GNU General Public License 15# You should have received a copy of the GNU General Public License
16# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 16# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
17 17
18include(`config-mips.m4') 18 include(`config-mips.m4')
19 19
20# Make sure not to use t4 through t7, in order to maintain portability 20## Beware: $t0-$t4 alias the syscall (and function, but they are not
21# with N32 ABI systems. 21## material in this context) argument registers on N32 systems, and
22## mustn't be relied upon to hold arguments to `SYSCALL'.
22 23
23 .set noreorder # delay slots managed by hand 24 .set noreorder # delay slots managed by hand
24 .section .text 25 .section .text
25 .global __start 26 .global __start
26__start: 27__start:
27dnl li $v0, SYSCALL_nanosleep # SYS_nanosleep 28 ## li $v0, SYSCALL_nanosleep # SYS_nanosleep
28dnl la $a0, .timespec # rqtp 29 ## la $a0, timespec # rqtp
29dnl li $a1, 0 # rmtp 30 ## li $a1, 0 # rmtp
30dnl syscall # syscall 31 ## syscall # syscall
31 lw $s6, ($sp) # original stack pointer 32 lw $s6, ($sp) # original stack pointer
32 addi $s0, $sp, 8 # start of load area 33 addi $s0, $sp, 8 # start of load area
33 addi $sp, -8 # primary fd, secondary fd 34 addi $sp, -8 # primary fd, secondary fd
34 li $t0, -1 # secondary fd 35 li $t0, -1 # secondary fd
35 sw $t0, 4($sp) # initialize secondary fd 36 sw $t0, 4($sp) # initialize secondary fd
36.next_action: 37next_action:
37 lw $s2, ($s0) # action number 38 lw $s2, ($s0) # action number
38 nop # delay slot
39 andi $t0, $s2, 15 # t0 = s2 & 15 39 andi $t0, $s2, 15 # t0 = s2 & 15
40 beqz $t0, .open_file # open file? 40 beqz $t0, open_file # open file?
41 li $t1, 3 # t1 = 3, delay slot 41 li $t1, 3 # t1 = 3, delay slot
42 beq $t0, $t1, .rest_of_exec # jump to code 42 beq $t0, $t1, rest_of_exec # jump to code
43 li $t1, 4 # t1 = 4, delay slot 43 li $t1, 4 # t1 = 4, delay slot
44 beq $t0, $t1, .do_mmap_anon # anonymous mmap 44 beq $t0, $t1, do_mmap_anon # anonymous mmap
45.do_mmap: 45do_mmap:
46 lw $a0, 4($s0) # vm_address, delay slot 46 lw $a0, 4($s0) # vm_address, delay slot
47 lw $v1, 8($s0) # file_offset 47 lw $v1, 8($s0) # file_offset
48 lw $a2, 12($s0) # protection 48 lw $a2, 12($s0) # protection
@@ -50,33 +50,33 @@ dnl syscall # syscall
50 lw $a3, 20($s0) # flags 50 lw $a3, 20($s0) # flags
51 lw $v0, ($sp) # primary fd 51 lw $v0, ($sp) # primary fd
52 andi $t1, $s2, 16 # t1 = s2 & 16 52 andi $t1, $s2, 16 # t1 = s2 & 16
53 beqz $t1, .do_mmap_1 # secondary fd? 53 beqz $t1, do_mmap_1 # secondary fd?
54 nop # delay slot 54 nop # delay slot
55 lw $v0, 4($sp) # secondary fd 55 lw $v0, 4($sp) # secondary fd
56 nop # delay slot 56 nop # delay slot
57.do_mmap_1: 57do_mmap_1:
58SYSCALL(`$v0',`$v1',`$zero',`$zero') # syscall args 58SYSCALL(`$v0',`$v1',`$zero',`$zero') # syscall args
59 li $v0, SYSCALL_mmap # SYS_mmap 59 li $v0, SYSCALL_mmap # SYS_mmap
60 syscall # syscall 60 syscall # syscall
61 bne $a3, $zero, .perror # perror 61 bnez $a3, perror # perror
62RESTORE() # delay slot, restore sp 62RESTORE() # delay slot, restore sp
63 lw $s5, 24($s0) # clear 63 lw $s5, 24($s0) # clear
64 add $t0, $a0, $a1 # t0 = length + vm_address, delay slot 64 add $t0, $a0, $a1 # t0 = length + vm_address, delay slot
65 sub $t1, $t0, $s5 # t1 = t0 - clear 65 sub $t1, $t0, $s5 # t1 = t0 - clear
66.align: 66align:
67 beq $t0, $t1, .continue # already finished? 67 beq $t0, $t1, continue # already finished?
68 nop # delay slot 68 nop # delay slot
69 andi $t2, $t1, 3 # t1 & 3? 69 andi $t2, $t1, 3 # t1 & 3?
70 bnez $t2, .fillw # start filling longs 70 bnez $t2, fillw # start filling longs
71 nop # delay slot 71 nop # delay slot
72 sb $zero, ($t1) # clear byte 72 sb $zero, ($t1) # clear byte
73 addi $t1, $t1, 1 # t1++ 73 addi $t1, $t1, 1 # t1++
74 j .align # continue 74 j align # continue
75 nop # delay slot 75 nop # delay slot
76.fillw: 76fillw:
77 sub $t2, $t0, $t1 # t2 = t0 - t1 77 sub $t2, $t0, $t1 # t2 = t0 - t1
78 sltiu $t2, $t2, 32 # r2 < 32? 78 sltiu $t2, $t2, 32 # r2 < 32?
79 bne $t2, $zero, .fillb # fill bytes 79 bne $t2, $zero, fillb # fill bytes
80 nop # delay slot 80 nop # delay slot
81 sw $zero, ($t1) # zero word 81 sw $zero, ($t1) # zero word
82 addi $t1, $t1, 4 # next word 82 addi $t1, $t1, 4 # next word
@@ -94,53 +94,52 @@ RESTORE() # delay slot, restore sp
94 addi $t1, $t1, 4 # next word 94 addi $t1, $t1, 4 # next word
95 sw $zero, ($t1) # zero word 95 sw $zero, ($t1) # zero word
96 addi $t1, $t1, 4 # next word 96 addi $t1, $t1, 4 # next word
97 j .fillw # fill either word or byte 97 j fillw # fill either word or byte
98 nop # delay slot 98 nop # delay slot
99.fillb: 99fillb:
100 beq $t0, $t1, .continue # already finished? 100 beq $t0, $t1, continue # already finished?
101 nop # delay slot 101 nop # delay slot
102 sb $zero, ($t1) # clear byte 102 sb $zero, ($t1) # clear byte
103 addi $t1, $t1, 1 # t1++ 103 addi $t1, $t1, 1 # t1++
104.continue: 104continue:
105 addi $s0, $s0, 28 # s0 = next action 105 addi $s0, $s0, 28 # s0 = next action
106 j .next_action # next action 106 j next_action # next action
107 nop # delay slot 107 nop # delay slot
108.do_mmap_anon: 108do_mmap_anon:
109 lw $v1, 8($s0) # file_offset 109 lw $v1, 8($s0) # file_offset
110 lw $a2, 12($s0) # protection 110 lw $a2, 12($s0) # protection
111 lw $a1, 16($s0) # length 111 lw $a1, 16($s0) # length
112 lw $a3, 20($s0) # flags 112 lw $a3, 20($s0) # flags
113 li $t4, -1 # fd 113 j do_mmap_1 # do mmap
114 j .do_mmap_1 # do mmap 114 li $v0, -1 # fd, delay slot
115 nop # delay slot 115open_file:
116.open_file:
117 li $v0, SYSCALL_open # SYS_open 116 li $v0, SYSCALL_open # SYS_open
118 addi $a0, $s0, 4 # start of name 117 addi $a0, $s0, 4 # start of name
119 move $a1, $zero # flags = O_RDONLY 118 move $a1, $zero # flags = O_RDONLY
120 move $a2, $zero # mode = 0 119 move $a2, $zero # mode = 0
121 syscall # syscall 120 syscall # syscall
122 bne $a3, $zero, .perror # perror 121 bne $a3, $zero, perror # perror
123 addi $s0, $s0, 4 # start of string, delay slot 122 addi $s0, $s0, 4 # start of string, delay slot
124 move $t3, $s0 # t3 = char past separator 123 move $t3, $s0 # t3 = char past separator
125.nextc: 124nextc:
126 lb $t0, ($s0) # load byte 125 lb $t0, ($s0) # load byte
127 addi $s0, $s0, 1 # s0++ 126 addi $s0, $s0, 1 # s0++
128 li $t1, 47 # directory separator `/' 127 li $t1, 47 # directory separator `/'
129 bne $t0, $t1, .nextc1 # is separator char? 128 bne $t0, $t1, nextc1 # is separator char?
130 nop # delay slot 129 nop # delay slot
131 move $t3, $s0 # t3 = char past separator 130 move $t3, $s0 # t3 = char past separator
132.nextc1: 131nextc1:
133 bnez $t0, .nextc # next character? 132 bnez $t0, nextc # next character?
134 nop # delay slot 133 nop # delay slot
135 addi $s0, $s0, 3 # adjust for round 134 addi $s0, $s0, 3 # adjust for round
136 li $t2, -4 # t2 = -4 135 li $t2, -4 # t2 = -4
137 and $s0, $s0, $t2 # mask for round 136 and $s0, $s0, $t2 # mask for round
138 andi $t0, $s2, 16 # t1 = s2 & 16 137 andi $t0, $s2, 16 # t1 = s2 & 16
139 beqz $t0, .primary # primary fd? 138 beqz $t0, primary # primary fd?
140 move $t0, $sp # address of primary fd, delay slot 139 move $t0, $sp # address of primary fd, delay slot
141 addi $t0, $t0, 4 # address of secondary fd 140 addi $t0, $t0, 4 # address of secondary fd
142 j .next_action # next action 141 j next_action # next action
143.primary: 142primary:
144 sw $v0, ($t0) # store fd, delay slot 143 sw $v0, ($t0) # store fd, delay slot
145 li $v0, SYSCALL_prctl # SYS_prctl 144 li $v0, SYSCALL_prctl # SYS_prctl
146 li $a0, 15 # PR_SET_NAME 145 li $a0, 15 # PR_SET_NAME
@@ -150,86 +149,209 @@ RESTORE() # delay slot, restore sp
150SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args 149SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args
151 syscall # syscall 150 syscall # syscall
152RESTORE() # restore sp 151RESTORE() # restore sp
153 j .next_action # next action 152 j next_action # next action
154 nop # delay slot 153 nop # delay slot
155.perror: 154perror:
156 move $a0, $v0 # errno 155 move $a0, $v0 # errno
157 li $v0, SYSCALL_exit # SYS_exit 156 li $v0, SYSCALL_exit # SYS_exit
158 syscall # syscall 157 syscall # syscall
159.rest_of_exec: 158rest_of_exec:
160 move $s1, $s6 # s1 = original SP 159 move $s1, $s6 # s1 = original SP
161 lw $t0, ($s1) # argc 160 lw $t0, ($s1) # argc
162 nop # delay slot 161 nop # delay slot
163 sll $t0, $t0, 2 # argc *= 4 162 sll $t0, $t0, 2 # argc *= 4
164 addi $t0, $t0, 8 # argc += 8 163 addi $t0, $t0, 8 # argc += 8
165 add $s1, $s1, $t0 # s1 = start of envp 164 add $s1, $s1, $t0 # s1 = start of envp
166.skipenv: 165skip_environ:
167 lw $t0, ($s1) # t0 = *s1 166 /* Locate the auxiliary vector. */
1671: lw $t0, ($s1) # t0 = *s1
168 bnez $t0, 1b # skip environment entry
168 addi $s1, $s1, 4 # s1++ 169 addi $s1, $s1, 4 # s1++
169 bne $t0, $zero, .skipenv # skip again 170 move $s2, $s1 # $s2 = end of environment
170 nop # delay slot 1711: lw $t0, ($s1) # t0 = *s1
171 la $s2, .auxvtab # address of auxv table 172 bnez $t0, 1b # skip auxiliary vector entry
172.one_auxv: 173 addi $s1, $s1, 8 # (Elf32_auxv_t *) s1++
173 lw $t0, ($s1) # t0 = auxv type 174 /* Decide how many bytes must be copied and where to
174 li $t1, 10 # t1 = 10, delay slot 175 save the file name. Move the stack pointer to a safe
175 beqz $t0, .finish # is AT_IGNORE? 176 position below any data that must be preserved. */
176 sltu $t1, $t0, $t1 # t1 = t0 < num offsets, delay slot 177 lw $t1, 32($s0) # length of string
177 beq $t1, $zero, .next # next auxv 178 addi $t1, $t1, 1
178 sll $t1, $t0, 2 # t1 = t0 * 4, delay slot 179 addi $t2, $s0, 36 # pointer to string
179 add $t1, $s2, $t1 # t1 = .auxvtab + t1 180 sub $t3, $s1, $s6 # number of bytes in vectors
180 lw $t2, ($t1) # t2 = *t1 181 sub $t0, $s1, $t1 # position of string
181 nop # delay slot 182 and $t0, $t0, -16 # align value
182 beqz $t2, .next # skip auxv 183 sub $t3, $t0, $t3 # position of argc
183 add $t2, $s0, $t2 # t2 = s0 + t2 184 and $t3, $t3, -16 # align value
184 lw $t2, ($t2) # t2 = *t2 185 /* Move the stack pointer and save required information.
185 nop # delay slot 186 4(FP) = secondary/interpreter fd.
186 sw $t2, 4($s1) # set auxv value 187 0(FP) = primary/executable fd.
187.next: 188 -4(FP) = cmd->entry
188 addi $s1, $s1, 8 # next auxv 189 -8(FP) = cmd->at_entry
189 j .one_auxv # next auxv 190 -12(FP) = cmd->at_phent
190 nop # delay slot 191 -16(FP) = cmd->at_phnum
191.finish: 192 -20(FP) = cmd->at_phdr
192 lw $t0, 4($sp) # secondary fd 193 -24(FP) = cmd->at_base
193 lw $s1, ($sp) # primary fd, delay slot, preserved 194 -28(FP) = cmd->fpu_mode (only significant when N32)
195 $sp = copy of string. */
196 move $t4, $sp # current sp
197 sub $t5, $t3, $sp # new argc - current sp
198 bleu $t5, -8, 1f # more than two slots apart
199 addi $sp, $t3, -8 # $sp = two slots below new argc
200 j 2f # skip copying fds
2011: move $sp, $t4 # retain current sp
202 lw $t5, ($t4) # old primary fd
203 sw $t5, ($sp) # save the same
204 lw $t5, 4($t4) # old interpreter fd
205 sw $t5, 4($sp) # save the same
2062: move FP, $sp # set base pointer
207 addi $sp, $sp, -28 # command data
208 lw $t5, 4($s0) # entry
209 lw $t6, 8($s0) # at_entry
210 sw $t5, -4(FP) # save entry
211 sw $t6, -8(FP) # save at_entry
212 lw $t5, 12($s0) # at_phent
213 lw $t6, 16($s0) # at_phnum
214 sw $t5, -12(FP) # save at_phent
215 sw $t6, -16(FP) # save at_phnum
216 lw $t5, 20($s0) # at_phdr
217 lw $t6, 24($s0) # at_base
218 sw $t5, -20(FP) # save at_phdr
219 sw $t6, -24(FP) # save at_base
220 lw $t5, 28($s0) # fpu_mode
221 sw $t5, -28(FP) # save fpu_mode
222 sub $sp, $sp, $t1 # space for string
223 /* Save the input string. */
224 add $t5, $t2, $t1 # end of source ($t2)
225 move $t6, $sp # dst
226 move $s0, $t1 # $s0 = length of string
227 /* src = $t2, dst = $t6 */
228 bgeu $t2, $t5, 2f # there already?
229 nop
2301: lb $t1, ($t2) # $t1 = *$t2
231 addi $t2, $t2, 1 # $t2++
232 addi $t6, $t6, 1 # $t6++
233 bltu $t2, $t5, 1b
234 sb $t1, -1($t6) # *($t6 - 1) = $t1
2352: move $s3, $sp # copy of string
236 and $sp, $sp, -16 # align stack
237copy_env_and_args:
238 /* Copy argc, argv, and the environment array.
239 $t4 = destination, $t5 = src, $s2 = src_end */
240 move $t4, $t3 # destination of argc
241 move $t5, $s6 # original SP
242 bgeu $t5, $s2, 2f # there already?
243 nop
2441: lw $t1, ($t5) # $t1 = *src
245 addi $t5, $t5, 4 # src++
246 addi $t4, $t4, 4 # dst++
247 bltu $t5, $s2, 1b # src < src_end
248 sw $t1, -4($t4) # *(dst - 4) = $t1
249copy_auxv:
250 /* $t4 = destination, $t5 = first auxval. */
2512: lw $t1, ($t5) # a_type
252 lw $t2, 4($t5) # a_un.a_val
253 addi $t4, $t4, 8 # (Elf32_auxv_t *) dst++
254 addi $t5, $t5, 8 # (Elf32_auxv_t *) src++
255 beqz $t1, 8f # AT_NULL
256 li $t6, 3
257 beq $t1, $t6, 1f # AT_PHDR
258 li $t6, 4
259 beq $t1, $t6, 2f # AT_PHENT
260 li $t6, 5
261 beq $t1, $t6, 3f # AT_PHNUM
262 li $t6, 9
263 beq $t1, $t6, 4f # AT_ENTRY
264 li $t6, 7
265 beq $t1, $t6, 5f # AT_BASE
266 li $t6, 31
267 beq $t1, $t6, 6f # AT_EXECFN
268 nop
269 b 7f
270 nop
2711: b 7f
272 lw $t2, -20(FP)
2732: b 7f
274 lw $t2, -12(FP)
2753: b 7f
276 lw $t2, -16(FP)
2774: b 7f
278 lw $t2, -8(FP)
2795: b 7f
280 lw $t2, -24(FP)
2816: b 7f
282 move $t2, $t0
2837: sw $t1, -8($t4) # dst->a_type
284 j copy_auxv
285 sw $t2, -4($t4) # dst->a_un.a_val
286 /* Copy the final element. */
2878: sw $t1, -8($t4) # dst->a_type
288 sw $t2, -4($t4) # dst->a_un.a_val
289finish:
290 /* Copy the string to its position in auxv
291 (src = $s3, dst = $t0). */
292 add $t1, $s3, $s0 # src end
293 bgeu $s3, $t1, 2f # there already?
294 nop
2951: lb $t2, ($s3) # c = *src
296 addi $s3, $s3, 1 # *src++
297 addi $t0, $t0, 1 # dst++
298 bltu $s3, $t1, 1b
299 sb $t2, -1($t0) # *(dst - 1) = c
300 /* Save variables. */
3012: move $s6, $t3 # new stack pointer
302 lw $t4, 4(FP) # secondary fd
303 lw $s1, (FP) # primary fd, delay slot, preserved
194 li $t2, -1 # immediate -1 304 li $t2, -1 # immediate -1
195 beq $t0, $t2, .finish1 # secondary fd set? 305 beq $t4, $t2, finish1 # secondary fd set?
196 li $v0, SYSCALL_close # SYS_close, delay slot 306 li $v0, SYSCALL_close # SYS_close, delay slot
197 move $a0, $t0 # fd 307 move $a0, $t4 # fd
198 syscall # syscall 308 syscall # syscall
199 li $v0, SYSCALL_close # SYS_close 309 li $v0, SYSCALL_close # SYS_close
200.finish1: 310finish1:
201 move $a0, $s1 # primary fd 311 move $a0, $s1 # primary fd
202 syscall # syscall 312 syscall # syscall
203 li $v0, SYSCALL_prctl # SYS_prctl 313 li $v0, SYSCALL_prctl # SYS_prctl
204 li $a0, 45 # PR_SET_FP_MODE 314 li $a0, 45 # PR_SET_FP_MODE
205 lw $a1, 28($s0) # fpu_mode 315 lw $a1, -28(FP) # fpu_mode
206 move $a2, $zero # arg3 316 move $a2, $zero # arg3
207 move $a3, $zero # arg4 317 move $a3, $zero # arg4
208SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args 318SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args
209 syscall # syscall 319 syscall # syscall
210RESTORE() # restore sp 320RESTORE() # restore sp
211.jump: 321jump:
212 move $v0, $zero # rtld_fini 322 move $v0, $zero # rtld_fini
213 lw $t0, 4($s0) # entry 323 lw $t9, -4(FP) # entry
214 move $sp, $s6 # restore stack pointer, delay slot 324 move $sp, $s6 # restore stack pointer, delay slot
215 jr $t0 # enter 325 /* Clear at least one page's worth of stack. glibc on mipsel
216 nop # delay slot 326 copies certain fields from the stack to the `link_map'
327 structure representing ld.so, which are not subsequently
328 replaced if otherwise than zero.
217 329
218.auxvtab: 330 XXX: report this glibc bug? */
219 .long 0 # 0 331 addi $v0, $sp, -4096
220 .long 0 # 1 332 and $v0, $v0, -4095
221 .long 0 # 2 3331: sw $zero, ($v0) # copy 32 byte blocks
222 .long 20 # 3 AT_PHDR 334 sw $zero, 4($v0)
223 .long 12 # 4 AT_PHENT 335 sw $zero, 8($v0)
224 .long 16 # 5 AT_PHNUM 336 sw $zero, 12($v0)
225 .long 0 # 6 337 sw $zero, 16($v0)
226 .long 24 # 7 AT_BASE 338 sw $zero, 20($v0)
227 .long 0 # 8 339 sw $zero, 24($v0)
228 .long 8 # 9 AT_ENTRY 340 sw $zero, 28($v0)
341 addi $v0, $v0, 32
342 sub $t0, $sp, $v0 # remainder
343 bge $t0, 32, 1b # test remainder
344 nop # copy 4 byte blocks
345 beqz $t0, 2f
3461: addi $v0, $v0, 4
347 bltu $v0, $sp, 1b
348 sw $zero, -4($v0)
3492: jr $t9 # enter
350 nop # delay slot
229 351
230.timespec: 352## timespec:
231 .long 10 353## .long 10
232 .long 10 354## .long 10
233 355
234# Local Variables: 356# Local Variables:
235# asm-comment-char: ?# 357# asm-comment-char: ?#