source: mainline/arch/mips32/src/start.S@ a0bb10ef

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a0bb10ef was 741ade3f, checked in by Ondrej Palkovsky <ondrap@…>, 19 years ago

Keep $K1 register for use as a thread local storage pointer on MIPS.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1#
2# Copyright (C) 2003-2004 Jakub Jermar
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8#
9# - Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# - Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution.
14# - The name of the author may not be used to endorse or promote products
15# derived from this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28
29#include <arch/asm/regname.h>
30#include <arch/mm/page.h>
31#include <arch/asm/boot.h>
32#include <arch/context_offset.h>
33
34.text
35
36.set noat
37.set noreorder
38.set nomacro
39
40.global kernel_image_start
41.global tlb_refill_entry
42.global cache_error_entry
43.global exception_entry
44.global userspace_asm
45
46# Which status bits should are thread-local
47#define REG_SAVE_MASK 0x1f # KSU(UM), EXL, ERL, IE
48
49# Save registers to space defined by \r
50# We will change status: Disable ERL,EXL,UM,IE
51# These changes will be automatically reversed in REGISTER_LOAD
52# SP is NOT saved as part of these registers
53.macro REGISTERS_STORE_AND_EXC_RESET r
54 sw $at,EOFFSET_AT(\r)
55 sw $v0,EOFFSET_V0(\r)
56 sw $v1,EOFFSET_V1(\r)
57 sw $a0,EOFFSET_A0(\r)
58 sw $a1,EOFFSET_A1(\r)
59 sw $a2,EOFFSET_A2(\r)
60 sw $a3,EOFFSET_A3(\r)
61 sw $t0,EOFFSET_T0(\r)
62 sw $t1,EOFFSET_T1(\r)
63 sw $t2,EOFFSET_T2(\r)
64 sw $t3,EOFFSET_T3(\r)
65 sw $t4,EOFFSET_T4(\r)
66 sw $t5,EOFFSET_T5(\r)
67 sw $t6,EOFFSET_T6(\r)
68 sw $t7,EOFFSET_T7(\r)
69 sw $t8,EOFFSET_T8(\r)
70 sw $t9,EOFFSET_T9(\r)
71
72 mflo $at
73 sw $at, EOFFSET_LO(\r)
74 mfhi $at
75 sw $at, EOFFSET_HI(\r)
76
77#ifdef CONFIG_DEBUG_ALLREGS
78 sw $s0,EOFFSET_S0(\r)
79 sw $s1,EOFFSET_S1(\r)
80 sw $s2,EOFFSET_S2(\r)
81 sw $s3,EOFFSET_S3(\r)
82 sw $s4,EOFFSET_S4(\r)
83 sw $s5,EOFFSET_S5(\r)
84 sw $s6,EOFFSET_S6(\r)
85 sw $s7,EOFFSET_S7(\r)
86 sw $s8,EOFFSET_S8(\r)
87#endif
88
89 sw $gp,EOFFSET_GP(\r)
90 sw $ra,EOFFSET_RA(\r)
91 sw $k1,EOFFSET_K1(\r)
92
93 mfc0 $t0, $status
94 mfc0 $t1, $epc
95
96 and $t2, $t0, REG_SAVE_MASK # Save only KSU,EXL,ERL,IE
97 li $t3, ~(0x1f)
98 and $t0, $t0, $t3 # Clear KSU,EXL,ERL,IE
99
100 sw $t2,EOFFSET_STATUS(\r)
101 sw $t1,EOFFSET_EPC(\r)
102 mtc0 $t0, $status
103.endm
104
105.macro REGISTERS_LOAD r
106 # Update only UM,EXR,IE from status, the rest
107 # is controlled by OS and not bound to task
108 mfc0 $t0, $status
109 lw $t1,EOFFSET_STATUS(\r)
110
111 li $t2, ~REG_SAVE_MASK # Mask UM,EXL,ERL,IE
112 and $t0, $t0, $t2
113
114 or $t0, $t0, $t1 # Copy UM,EXL,ERL,IE from saved status
115 mtc0 $t0, $status
116
117 lw $v0,EOFFSET_V0(\r)
118 lw $v1,EOFFSET_V1(\r)
119 lw $a0,EOFFSET_A0(\r)
120 lw $a1,EOFFSET_A1(\r)
121 lw $a2,EOFFSET_A2(\r)
122 lw $a3,EOFFSET_A3(\r)
123 lw $t0,EOFFSET_T0(\r)
124 lw $t1,EOFFSET_T1(\r)
125 lw $t2,EOFFSET_T2(\r)
126 lw $t3,EOFFSET_T3(\r)
127 lw $t4,EOFFSET_T4(\r)
128 lw $t5,EOFFSET_T5(\r)
129 lw $t6,EOFFSET_T6(\r)
130 lw $t7,EOFFSET_T7(\r)
131 lw $t8,EOFFSET_T8(\r)
132 lw $t9,EOFFSET_T9(\r)
133
134#ifdef CONFIG_DEBUG_ALLREGS
135 lw $s0,EOFFSET_S0(\r)
136 lw $s1,EOFFSET_S1(\r)
137 lw $s2,EOFFSET_S2(\r)
138 lw $s3,EOFFSET_S3(\r)
139 lw $s4,EOFFSET_S4(\r)
140 lw $s5,EOFFSET_S5(\r)
141 lw $s6,EOFFSET_S6(\r)
142 lw $s7,EOFFSET_S7(\r)
143 lw $s8,EOFFSET_S8(\r)
144#endif
145 lw $gp,EOFFSET_GP(\r)
146 lw $ra,EOFFSET_RA(\r)
147 lw $k1,EOFFSET_K1(\r)
148
149 lw $at,EOFFSET_LO(\r)
150 mtlo $at
151 lw $at,EOFFSET_HI(\r)
152 mthi $at
153
154 lw $at,EOFFSET_EPC(\r)
155 mtc0 $at, $epc
156
157 lw $at,EOFFSET_AT(\r)
158 lw $sp,EOFFSET_SP(\r)
159.endm
160
161# Move kernel stack pointer address to register K0
162# - if we are in user mode, load the appropriate stack
163# address
164.macro KERNEL_STACK_TO_K0
165 # If we are in user mode
166 mfc0 $k0, $status
167 andi $k0, 0x10
168
169 beq $k0, $0, 1f
170 add $k0, $sp, 0
171
172 # Move $k0 pointer to kernel stack
173 lui $k0, %hi(supervisor_sp)
174 ori $k0, $k0, %lo(supervisor_sp)
175 # Move $k0 (superveisor_sp)
176 lw $k0, 0($k0)
1771:
178.endm
179
180.org 0x0
181kernel_image_start:
182 /* Load temporary stack */
183 lui $sp, %hi(end_stack)
184 ori $sp, $sp, %lo(end_stack)
185
186 /* Not sure about this, but might be needed for PIC code???? */
187 lui $gp, 0x8000
188
189 jal main_bsp
190 nop
191
192
193 .space TEMP_STACK_SIZE
194end_stack:
195
196tlb_refill_entry:
197 j tlb_refill_handler
198 nop
199
200cache_error_entry:
201 j cache_error_handler
202 nop
203
204exception_entry:
205 j exception_handler
206 nop
207
208
209
210exception_handler:
211 KERNEL_STACK_TO_K0
212 sub $k0, REGISTER_SPACE
213 sw $sp,EOFFSET_SP($k0)
214 move $sp, $k0
215
216 mfc0 $k0, $cause
217
218 sra $k0, $k0, 0x2 # cp0_exc_cause() part 1
219 andi $k0, $k0, 0x1f # cp0_exc_cause() part 2
220 sub $k0, 8 # 8=SYSCALL
221
222 beqz $k0, syscall_shortcut
223 add $k0, 8 # Revert $k1 back to correct exc number
224
225 REGISTERS_STORE_AND_EXC_RESET $sp
226
227 move $a1, $sp
228 jal exc_dispatch # exc_dispatch(excno, register_space)
229 move $a0, $k0
230
231 REGISTERS_LOAD $sp
232 # The $sp is automatically restored to former value
233 eret
234
235# it seems that mips reserves some space on stack for varfuncs???
236#define SS_ARG4 16
237#define SS_SP EOFFSET_SP
238#define SS_STATUS EOFFSET_STATUS
239#define SS_EPC EOFFSET_EPC
240syscall_shortcut:
241 # We have a lot of space on the stack, with free use
242 mfc0 $t1, $epc
243 mfc0 $t0, $status
244 sw $t1,SS_EPC($sp) # Save EPC
245
246 and $t2, $t0, REG_SAVE_MASK # Save only KSU,EXL,ERL,IE
247 li $t3, ~(0x1f)
248 and $t0, $t0, $t3 # Clear KSU,EXL,ERL
249 ori $t0, $t0, 0x1 # Set IE
250
251 sw $t2,SS_STATUS($sp)
252 mtc0 $t0, $status
253
254 jal syscall_handler
255 sw $v0, SS_ARG4($sp) # save v0 - arg4 to stack
256
257 # restore epc+4
258 lw $t0,SS_EPC($sp)
259 addi $t0, $t0, 4
260 mtc0 $t0, $epc
261
262 # restore status
263 mfc0 $t0, $status
264 lw $t1,SS_STATUS($sp)
265
266 li $t2, ~REG_SAVE_MASK # Mask UM,EXL,ERL,IE
267 and $t0, $t0, $t2
268 or $t0, $t0, $t1 # Copy UM,EXL,ERL,IE from saved status
269 mtc0 $t0, $status
270
271 lw $sp,SS_SP($sp) # restore sp
272
273 eret
274
275tlb_refill_handler:
276 KERNEL_STACK_TO_K0
277 sub $k0, REGISTER_SPACE
278 REGISTERS_STORE_AND_EXC_RESET $k0
279 sw $sp,EOFFSET_SP($k0)
280 add $sp, $k0, 0
281
282 add $a0, $sp, 0
283 jal tlb_refill /* tlb_refill(register_space) */
284 nop
285
286 REGISTERS_LOAD $sp
287
288 eret
289
290cache_error_handler:
291 KERNEL_STACK_TO_K0
292 sub $k0, REGISTER_SPACE
293 REGISTERS_STORE_AND_EXC_RESET $k0
294 sw $sp,EOFFSET_SP($k0)
295 add $sp, $k0, 0
296
297 jal cache_error
298 nop
299
300 REGISTERS_LOAD $sp
301
302 eret
303
304userspace_asm:
305 add $sp, $a0, 0
306 add $v0, $a1, 0
307 eret
308
Note: See TracBrowser for help on using the repository browser.