-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathstart.S
More file actions
401 lines (369 loc) · 8.31 KB
/
Copy pathstart.S
File metadata and controls
401 lines (369 loc) · 8.31 KB
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
//start.S
#include "mips.h"
.text
.extern ds2_init
.extern heapInit
.extern ds2_main
.ent _start
.global _start
.type _start,@function
.set noreorder
.set noat
_start:
nop
nop
//----------------------------------------------------
// init cp0 registers.
//----------------------------------------------------
mtc0 zero, $18
mtc0 zero, $19
li t1, 0x00800000
mtc0 t1, $13
li t0, 0x0040FC00
mtc0 t0, $12
//----------------------------------------------------
// init caches, assumes a 4way*128set*32byte i/d cache
//----------------------------------------------------
li t0, 3 // enable cache for kseg0 accesses
mtc0 t0, $16 // CONFIG reg
la t0, 0x80000000 // an idx op should use a unmappable address
ori t1, t0, 0x4000 // 16kB cache
mtc0 zero, $28 // TAGLO reg
mtc0 zero, $29 // TAGHI reg
_init_cache_loop:
cache 0x8, 0(t0) // index store icache tag
//cache 0x9, 0(t0) // index store dcache tag
cache 0x1, 0(t0)
sync
bne t0, t1, _init_cache_loop
addiu t0, t0, 0x20 // 32 bytes per cache line
nop
//----------------------------------------------------
// Invalidate BTB
//----------------------------------------------------
mfc0 t0, $16, 7
nop
ori t0, 2
mtc0 t0, $16, 7
nop
//----------------------------------------------------
// clear BSS section
//----------------------------------------------------
la t0, _fbss
la t1, _end
1: sw zero, 0(t0)
bne t0, t1, 1b
addiu t0, 4
//----------------------------------------------------
// setup stack and GP, jump to C code
//----------------------------------------------------
la gp, _gp
la sp, _freemem+0x100000 //stack size = 0x100000
jal ds2_init
nop
la a0, _freemem+0x100400 // a0, parameter 1 = Heap start address
la a1, 0x82000000-0x400 // a1, parameter 2 = Heap end address
jal heapInit // Initialise the heap for malloc
nop
la t0, ds2_main
jr t0
nop
.end _start
.extern real_exception_entry
.extern GuruMeditation
.ent except_common_entry
.global except_common_entry
.type except_common_entry,@function
/* except_common_entry is code that gets copied to 3 places in memory to
* handle exceptions, so it cannot use relative jumps. It needs to fit in
* 32 bytes (8 words).
*/
except_common_entry:
la k0, real_exception_entry
jr k0
nop
nop
nop
nop
.end except_common_entry
.extern C_IntHandle
.extern exception_handler
.ent real_exception_entry
.global real_exception_entry
.type real_exception_entry,@function
/*
* real_exception_entry is the target of a jump from one of the 3 copies of
* except_common_entry. It gets called whenever a synchronous or asynchronous
* exception happens on the MIPS.
* It is crucial that this completes very quickly.
* Asynchronous exceptions (i.e. interrupts) are much more frequent than
* the rest, so they need to complete the fastest.
* Synchronous exceptions can be system calls or traps.
* After handler jumps, k0 is set to the exception code in bits 6 to 2.
*/
real_exception_entry:
ori k1, zero, (0x1f << 2)
mfc0 k0, C0_CAUSE
and k0, k0, k1 // k0 = exception code
beq zero, k0, intr_handler
ori k1, zero, (0x08 << 2) // branch delay slot
beq k0, k1, syscall_handler // exception code = 8 -> syscall
nop
beq zero, zero, exception_handler
nop
/* intr_handler is the target of a jump from real_exception_entry.
* It gets called whenever an asynchronous exception happens on the MIPS.
* It is crucial that this completes very quickly.
*/
intr_handler:
addiu sp, sp, -128
sw ra, (4*0)(sp)
sw fp, (4*1)(sp)
sw gp, (4*2)(sp)
sw t9, (4*3)(sp)
sw t8, (4*4)(sp)
sw s7, (4*5)(sp)
sw s6, (4*6)(sp)
sw s5, (4*7)(sp)
sw s4, (4*8)(sp)
sw s3, (4*9)(sp)
sw s2, (4*10)(sp)
sw s1, (4*11)(sp)
sw s0, (4*12)(sp)
sw t7, (4*13)(sp)
sw t6, (4*14)(sp)
sw t5, (4*15)(sp)
sw t4, (4*16)(sp)
sw t3, (4*17)(sp)
sw t2, (4*18)(sp)
sw t1, (4*19)(sp)
sw t0, (4*20)(sp)
sw a3, (4*21)(sp)
sw a2, (4*22)(sp)
sw a1, (4*23)(sp)
sw a0, (4*24)(sp)
sw v1, (4*25)(sp)
sw v0, (4*26)(sp)
sw AT, (4*27)(sp)
mfc0 k1, C0_STATUS
sw k1, (4*28)(sp)
mfc0 k1, C0_EPC
sw k1, (4*29)(sp)
mflo k1
sw k1, (4*30)(sp)
mfhi k1
jal C_IntHandle
sw k1, (4*31)(sp) // finish saving regs (branch delay slot)
lw ra, (4*0)(sp)
lw fp, (4*1)(sp)
lw gp, (4*2)(sp)
lw t9, (4*3)(sp)
lw t8, (4*4)(sp)
lw s7, (4*5)(sp)
lw s6, (4*6)(sp)
lw s5, (4*7)(sp)
lw s4, (4*8)(sp)
lw s3, (4*9)(sp)
lw s2, (4*10)(sp)
lw s1, (4*11)(sp)
lw s0, (4*12)(sp)
lw t7, (4*13)(sp)
lw t6, (4*14)(sp)
lw t5, (4*15)(sp)
lw t4, (4*16)(sp)
lw t3, (4*17)(sp)
lw t2, (4*18)(sp)
lw t1, (4*19)(sp)
lw t0, (4*20)(sp)
lw a3, (4*21)(sp)
lw a2, (4*22)(sp)
lw a1, (4*23)(sp)
lw a0, (4*24)(sp)
lw v1, (4*25)(sp)
lw v0, (4*26)(sp)
lw AT, (4*27)(sp)
lw k0, (4*28)(sp)
mtc0 k0, C0_STATUS
lw k0, (4*29)(sp)
mtc0 k0, C0_EPC
lw k0, (4*30)(sp)
mtlo k0
lw k0, (4*31)(sp)
mthi k0
addiu sp, sp, 128
eret
nop
/* exception_handler is the target of a jump from real_exception_entry.
* It gets called whenever a synchronous exception happens on the MIPS,
* which is not a system call.
*/
exception_handler:
addiu sp, sp, -128
sw ra, (4*0)(sp)
sw fp, (4*1)(sp)
sw gp, (4*2)(sp)
sw t9, (4*3)(sp)
sw t8, (4*4)(sp)
sw s7, (4*5)(sp)
sw s6, (4*6)(sp)
sw s5, (4*7)(sp)
sw s4, (4*8)(sp)
sw s3, (4*9)(sp)
sw s2, (4*10)(sp)
sw s1, (4*11)(sp)
sw s0, (4*12)(sp)
sw t7, (4*13)(sp)
sw t6, (4*14)(sp)
sw t5, (4*15)(sp)
sw t4, (4*16)(sp)
sw t3, (4*17)(sp)
sw t2, (4*18)(sp)
sw t1, (4*19)(sp)
sw t0, (4*20)(sp)
sw a3, (4*21)(sp)
sw a2, (4*22)(sp)
sw a1, (4*23)(sp)
sw a0, (4*24)(sp)
sw v1, (4*25)(sp)
sw v0, (4*26)(sp)
sw AT, (4*27)(sp)
mflo k1
sw k1, (4*28)(sp)
mfhi k1
sw k1, (4*29)(sp)
mfc0 k1, C0_EPC //return address
sw k1, (4*30)(sp)
mfc0 k1, C0_STATUS
sw k1, (4*31)(sp)
move a0, sp // a0, parameter #1 = sp
jal GuruMeditation
srl a1, k0, 2 // a1, parameter #2 = shifted version of CAUSE
lw ra, (4*0)(sp)
lw fp, (4*1)(sp)
lw gp, (4*2)(sp)
lw t9, (4*3)(sp)
lw t8, (4*4)(sp)
lw s7, (4*5)(sp)
lw s6, (4*6)(sp)
lw s5, (4*7)(sp)
lw s4, (4*8)(sp)
lw s3, (4*9)(sp)
lw s2, (4*10)(sp)
lw s1, (4*11)(sp)
lw s0, (4*12)(sp)
lw t7, (4*13)(sp)
lw t6, (4*14)(sp)
lw t5, (4*15)(sp)
lw t4, (4*16)(sp)
lw t3, (4*17)(sp)
lw t2, (4*18)(sp)
lw t1, (4*19)(sp)
lw t0, (4*20)(sp)
lw a3, (4*21)(sp)
lw a2, (4*22)(sp)
lw a1, (4*23)(sp)
lw a0, (4*24)(sp)
lw v1, (4*25)(sp)
lw v0, (4*26)(sp)
lw AT, (4*27)(sp)
lw k0, (4*28)(sp)
mtlo k0
lw k0, (4*29)(sp)
mthi k0
lw k0, (4*30)(sp)
addiu k0, k0, 4
mtc0 k0, C0_EPC // return address = EPC + 4
lw k0, (4*31)(sp)
mtc0 k0, C0_STATUS
addiu sp, sp, 128
eret
nop
/* syscall_handler is the target of a jump from real_exception_entry.
* It gets called whenever a system call happens on the MIPS.
* This should complete quickly.
*/
syscall_handler:
addiu sp, sp, -128
sw ra, (4*0)(sp)
sw fp, (4*1)(sp)
sw gp, (4*2)(sp)
sw t9, (4*3)(sp)
sw t8, (4*4)(sp)
sw s7, (4*5)(sp)
sw s6, (4*6)(sp)
sw s5, (4*7)(sp)
sw s4, (4*8)(sp)
sw s3, (4*9)(sp)
sw s2, (4*10)(sp)
sw s1, (4*11)(sp)
sw s0, (4*12)(sp)
sw t7, (4*13)(sp)
sw t6, (4*14)(sp)
sw t5, (4*15)(sp)
sw t4, (4*16)(sp)
sw t3, (4*17)(sp)
sw t2, (4*18)(sp)
sw t1, (4*19)(sp)
sw t0, (4*20)(sp)
sw a3, (4*21)(sp)
sw a2, (4*22)(sp)
sw a1, (4*23)(sp)
sw a0, (4*24)(sp)
sw v1, (4*25)(sp)
sw v0, (4*26)(sp)
sw AT, (4*27)(sp)
mflo k1
sw k1, (4*28)(sp)
mfhi k1
sw k1, (4*29)(sp)
mfc0 k0, C0_EPC // return address
sw k0, (4*30)(sp)
mfc0 k1, C0_STATUS
sw k1, (4*31)(sp)
lw k1, 0(k0) // k1 = opcode at EPC
sll a0, k1, 6
sra a0, a0, 12 // a0, parameter #1 = system call number
move a1, k0 // a1, parameter #2 = caller address
jal syscall_fun
move a2, sp // a2, parameter #3 = sp (branch delay slot)
lw ra, (4*0)(sp)
lw fp, (4*1)(sp)
lw gp, (4*2)(sp)
lw t9, (4*3)(sp)
lw t8, (4*4)(sp)
lw s7, (4*5)(sp)
lw s6, (4*6)(sp)
lw s5, (4*7)(sp)
lw s4, (4*8)(sp)
lw s3, (4*9)(sp)
lw s2, (4*10)(sp)
lw s1, (4*11)(sp)
lw s0, (4*12)(sp)
lw t7, (4*13)(sp)
lw t6, (4*14)(sp)
lw t5, (4*15)(sp)
lw t4, (4*16)(sp)
lw t3, (4*17)(sp)
lw t2, (4*18)(sp)
lw t1, (4*19)(sp)
lw t0, (4*20)(sp)
lw a3, (4*21)(sp)
lw a2, (4*22)(sp)
lw a1, (4*23)(sp)
lw a0, (4*24)(sp)
lw v1, (4*25)(sp)
lw v0, (4*26)(sp)
lw AT, (4*27)(sp)
lw k0, (4*28)(sp)
mtlo k0
lw k0, (4*29)(sp)
mthi k0
lw k0, (4*30)(sp)
addiu k0, k0, 4
mtc0 k0, C0_EPC // return address = EPC + 4
lw k0, (4*31)(sp)
mtc0 k0, C0_STATUS
addiu sp, sp, 128
eret
nop
.end real_exception_entry