start.S revision 1.1 1 /* $NetBSD: start.S,v 1.1 2011/01/26 01:18:54 pooka Exp $ */
2
3 /*-
4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code was written by Alessandro Forin and Neil Pittman
8 * at Microsoft Research and contributed to The NetBSD Foundation
9 * by Microsoft Corporation.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* Trivial support for printing stuff on the serial line from C pgms.
34 */
35 #include <mips/asm.h>
36 #include <mips/cpuregs.h>
37 #define __ASSEMBLER__ 1
38 #include <machine/emipsreg.h>
39
40 /* Offsets in the CXTINFO structure
41 */
42 #define TS_AT (1 * 4)
43 #define TS_V0 (2 * 4)
44 #define TS_V1 (3 * 4)
45 #define TS_A0 (4 * 4)
46 #define TS_A1 (5 * 4)
47 #define TS_A2 (6 * 4)
48 #define TS_A3 (7 * 4)
49 #define TS_T0 (8 * 4)
50 #define TS_T1 (9 * 4)
51 #define TS_T2 (10 * 4)
52 #define TS_T3 (11 * 4)
53 #define TS_T4 (12 * 4)
54 #define TS_T5 (13 * 4)
55 #define TS_T6 (14 * 4)
56 #define TS_T7 (15 * 4)
57 #define TS_S0 (16 * 4)
58 #define TS_S1 (17 * 4)
59 #define TS_S2 (18 * 4)
60 #define TS_S3 (19 * 4)
61 #define TS_S4 (20 * 4)
62 #define TS_S5 (21 * 4)
63 #define TS_S6 (22 * 4)
64 #define TS_S7 (23 * 4)
65 #define TS_T8 (24 * 4)
66 #define TS_T9 (25 * 4)
67 #define TS_K0 (26 * 4)
68 #define TS_K1 (27 * 4)
69 #define TS_GP (28 * 4)
70 #define TS_SP (29 * 4)
71 #define TS_FP (30 * 4)
72 #define fp s8
73 #define TS_RA (31 * 4)
74
75 #define TS_PC (32 * 4)
76 #define TS_SR (33 * 4)
77 #define TS_HI (34 * 4)
78 #define TS_LO (35 * 4)
79 #define TS_EC (36 * 4)
80 #define SIZEOF_CXTINFO (37*4)
81
82 /* PROM_MODE means the user plans to keep this code around while running an OS.
83 * So we act kind of like PROM code (BIOS?), but we live in RAM.
84 * So we need to safeguard ourselves against corruptions, some unavoidable.
85 * Like the overriding of the exception vectors, rigth where our "start" code is.
86 */
87
88 IMPORT(main,4)
89 IMPORT(_end,4)
90
91 .set noreorder
92
93 EXPORT(start)
94 bgezal zero,_C_LABEL(real_start)
95 nop
96
97
98 /* Does not handle the exception, really.
99 * But to test interrupts should be enough
100 */
101 .org 0x00000080
102 VECTOR(ExceptionHandler,0)
103 .frame sp,SIZEOF_CXTINFO,$31
104 la k1, UserInterruptHandler
105 lw k1,0(k1)
106 bne k1,zero,Dispatch
107 mfc0 k0, MIPS_COP_0_EXC_PC
108 j k0
109 nop /* do not! pop status */
110
111 EXPORT(UserInterruptHandler)
112 .word 0
113
114 EXPORT(Dispatch)
115 /* Save state on stack */
116 addiu sp, sp, -SIZEOF_CXTINFO
117 /* save registers */
118 .set noat
119 sw AT, TS_AT(sp)
120 .set at
121 sw v0, TS_V0(sp)
122 sw v1, TS_V1(sp)
123 sw a0, TS_A0(sp)
124 sw a1, TS_A1(sp)
125 sw a2, TS_A2(sp)
126 sw a3, TS_A3(sp)
127 sw t0, TS_T0(sp)
128 sw t1, TS_T1(sp)
129 sw t2, TS_T2(sp)
130 sw t3, TS_T3(sp)
131 sw t4, TS_T4(sp)
132 sw t5, TS_T5(sp)
133 sw t6, TS_T6(sp)
134 sw t7, TS_T7(sp)
135 sw s0, TS_S0(sp)
136 sw s1, TS_S1(sp)
137 sw s2, TS_S2(sp)
138 sw s3, TS_S3(sp)
139 sw s4, TS_S4(sp)
140 sw s5, TS_S5(sp)
141 sw s6, TS_S6(sp)
142 sw s7, TS_S7(sp)
143 sw t8, TS_T8(sp)
144 sw t9, TS_T9(sp)
145 sw k0, TS_K0(sp)
146 sw k1, TS_K1(sp)
147 sw gp, TS_GP(sp)
148 /* sp: later */
149 sw fp, TS_FP(sp)
150 sw ra, TS_RA(sp)
151
152 mfc0 a0, MIPS_COP_0_STATUS
153 mflo t0
154 mfhi t1
155 sw a0, TS_SR(sp)
156 sw t0, TS_LO(sp)
157 sw t1, TS_HI(sp)
158 sw k0, TS_PC(sp)
159
160 /* Save original stack */
161 move a0,sp
162 addiu t0, sp, SIZEOF_CXTINFO
163 jalr k1
164 sw t0, TS_SP(sp)
165
166 /* Returned value is new PCXINFO */
167 move a0,v0
168
169 /* First load most registers */
170 .set noat
171 lw AT, TS_AT(a0)
172 lw v0, TS_V0(a0)
173 lw v1, TS_V1(a0)
174 /* a0 later */
175 lw a1, TS_A1(a0)
176 lw a2, TS_A2(a0)
177 lw a3, TS_A3(a0)
178 lw t0, TS_T0(a0)
179 lw t1, TS_T1(a0)
180 lw t2, TS_T2(a0)
181 lw t3, TS_T3(a0)
182 lw t4, TS_T4(a0)
183 lw t5, TS_T5(a0)
184 lw t6, TS_T6(a0)
185 lw t7, TS_T7(a0)
186 lw s0, TS_S0(a0)
187 lw s1, TS_S1(a0)
188 lw s2, TS_S2(a0)
189 lw s3, TS_S3(a0)
190 lw s4, TS_S4(a0)
191 lw s5, TS_S5(a0)
192 lw s6, TS_S6(a0)
193 lw s7, TS_S7(a0)
194 lw t8, TS_T8(a0)
195 lw t9, TS_T9(a0)
196 /* k0,k1 not restored */
197 lw gp, TS_GP(a0)
198 /* sp later */
199 lw fp, TS_FP(a0)
200 lw ra, TS_RA(a0)
201
202 lw k1, TS_HI(a0)
203 lw k0, TS_LO(a0)
204 mthi k1
205 mtlo k0
206 lw k1, TS_SR(a0)
207 mtc0 k1, MIPS_COP_0_STATUS
208 /* NB: After this instruction we cannot take any interrupts or traps
209 */
210 lw sp, TS_SP(a0)
211
212 /* Put pc into k0 */
213 lw k0, TS_PC(a0)
214 lw a0, TS_A0(a0)
215 j k0
216 rfe
217 .set at
218
219 VECTOR_END(ExceptionHandler)
220
221 .org 0x00000200
222 EXPORT(real_start)
223 .ent _C_LABEL(real_start)
224
225 #ifdef SECONDARY_BOOTBLOCK
226 /*
227 * If this is the program that goes into FLASH we must copy ourselves down to RAM.
228 * FLASH default on the MLx is at 0xf0000000, DRAM at 0.
229 */
230 addi a0,ra,-8 /* Compensate for the first two instructions */
231
232 /* Get the address(relative) of TextStart
233 */
234 bgezal zero, _C_LABEL(MipsStart2) /* Always jumps */
235 nop
236
237 /* All of the static data, since we are at it.
238 */
239 TextStart: /* + 0 */
240 /* Text start at final link address */
241 .int start
242
243 DataEnd: /* + 4 */
244 /* Data end == bss start */
245 .int _edata
246
247 BssEnd: /* + 8 */
248 /* Bss end */
249 .int _end
250
251 RelocToRAM: /* *+12 */
252 .int InRAM
253
254 MipsStart2:
255
256 /* Source = a0, Dst = t2 */
257 lw t2, 0(ra) /* _C_LABEL(TextStart) */
258
259 /* EndPtr = t3 */
260 /* in bdelay slot */
261
262 /* If a0 != t2 then we are running in Flash but should run in RAM
263 * In that case copy .text. Otherwise skip to .bss.
264 */
265 beq a0,t2,ZroLoop-4
266 lw t3, 4(ra) /* _C_LABEL(DataEnd) */
267
268 CpyLoop:
269 /* loop copying 2 words at a time */
270 lw t4,0(a0)
271 lw t5,4(a0)
272 addiu a0,a0,8
273 sw t4,0(t2)
274 addiu t2,t2,8
275 sltu t1,t2,t3
276 bne t1,zero,CpyLoop
277 sw t5,-4(t2)
278
279 /* zero the bss
280 */
281 lw t4, 8(ra) /* _C_LABEL(BssEnd) */
282 ZroLoop:
283 sltu t1,t3,t4
284 sw zero,0(t3)
285 bne t1,zero,ZroLoop
286 addiu t3,t3,4
287
288 /* Jump to RAM copy (below)
289 */
290 lw t1, 12(ra) /* _C_LABEL(RelocToRAM) */
291 jr t1
292 nop
293
294 /*
295 * Execute from here after copying out of FLASH into RAM
296 */
297 InRAM:
298
299 #endif /* SECONDARY_BOOTBLOCK */
300
301 /* Get a stack
302 */
303 #ifdef __GP_SUPPORT__
304 la gp, _C_LABEL (_gp)
305 #endif
306 la sp,_end
307 addiu sp,sp,(8*1024) /* BUGBUG arbitrary */
308
309 /* Jump to main
310 */
311 jal main
312 add a0,sp,zero
313
314 /* Load failed, reset the processor and jump back to the origins.
315 */
316 EXPORT(_rtt) /* ahem */
317 li t0,0x1260ff80 /* NB: On new builds this is a SYS-RESET as well */
318 mtc0 t0,MIPS_COP_0_STATUS
319
320 lui t0,(BRAM_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */
321 jr t0
322 nop
323
324 EXPORT(Stop)
325 b Stop
326 nop
327
328 END(real_start)
329
330 .set noreorder
331 .set noat
332 .set nomacro
333
334 /* void Delay(UINT32 count)
335 */
336 LEAF(Delay)
337 bne a0,zero,_C_LABEL(Delay)
338 subu a0,1
339 j ra
340 nop
341 END(Delay)
342
343 /* UINT32 GetPsr(void)
344 * Returns the PSR (coprocessor 0 status)
345 */
346 LEAF(GetPsr)
347 mfc0 v0, MIPS_COP_0_STATUS
348 j ra
349 nop
350 END(GetPsr)
351
352 /* void SetPsr(UINT32 Psr)
353 * Sets the PSR (coprocessor 0 status)
354 */
355 LEAF(SetPsr)
356 mtc0 a0,MIPS_COP_0_STATUS
357 j ra
358 nop
359 END(SetPsr)
360
361 /* UINT32 GetCause(void)
362 * Returns the Cause register (coprocessor 0)
363 */
364 LEAF(GetCause)
365 mfc0 v0,MIPS_COP_0_CAUSE
366 j ra
367 nop
368 END(GetCause)
369
370 /* UINT32 GetEpc(void)
371 * Returns the Epc register (coprocessor 0)
372 */
373 LEAF(GetEpc)
374 mfc0 v0,MIPS_COP_0_EXC_PC
375 j ra
376 nop
377 END(GetEpc)
378
379
380 /* int PutWord(UINT32 Word);
381 * Returns: 0 if ok, -1 otherwise
382 */
383 NESTED(PutWord,12,$31)
384 subu sp,sp,12
385 sw s0,8(sp)
386 sw s1,4(sp)
387 sw ra,0(sp)
388
389 or s1,a0,zero
390 /* Spit all nibbles
391 */
392 li s0,8
393 PutWordLoop:
394 srl a0,s1,32-4
395 li t0,10
396 sltu t1,a0,t0
397 bnez t1,$Digit
398 li a1,'0'
399 subu a0,a0,t0
400 li a1,'a'
401 $Digit:
402 sll s1,s1,4
403 jal PutChar
404 add a0,a0,a1
405
406 subu s0,s0,1
407 bne v0,zero,PutWordDone /* printed ok? */
408 li v0,-1
409
410 /* done yet? */
411 bne s0,zero,PutWordLoop
412 nop
413
414 /* done
415 */
416 li v0,0
417 PutWordDone:
418 lw ra,0(sp)
419 lw s1,4(sp)
420 lw s0,8(sp)
421 jr ra
422 addiu sp,sp,12
423
424 END(PutWord)
425
426 /* int Puts(char *String);
427 * Returns: 0 if ok, -1 otherwise
428 */
429 NESTED(Puts,8,$31)
430 subu sp,sp,8
431 sw s0,4(sp)
432 sw ra,0(sp)
433
434 or s0,a0,zero
435 /* Spit all chars until zero
436 */
437 PutsLoop:
438 lbu a0,0(s0)
439 addiu s0,s0,1
440 beq a0,zero,PutsDoneOk
441 nop
442 jal PutChar
443 nop
444 beq v0,zero,PutsLoop
445 nop
446
447 /* Timed out
448 */
449 b PutsDone
450 li v0,-1
451
452 /* done
453 */
454 PutsDoneOk:
455 li v0,0
456 PutsDone:
457 lw ra,0(sp)
458 lw s0,4(sp)
459 jr ra
460 addiu sp,sp,8
461
462 END(Puts)
463
464
465 /* int GetChar(void);
466 * Returns: a non-negative value if ok, -1 otherwise
467 */
468 LEAF(GetChar)
469 lui t0,(USART_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */
470 lui t1,1000 /* n*65k spins max */
471 RxNotReady:
472 lw t4,USARTST(t0) /* ChannelStatus */
473 andi t4,t4,USI_RXRDY
474 bgtz t4,$GotByte
475 subu t1,t1,1
476 /* still ok to spin? */
477 bgtz t1,RxNotReady
478 nop
479 /* Timed out
480 */
481 jr ra
482 li v0,-1
483
484 /* Gottabyte
485 */
486 $GotByte:
487 lw v0,USARTRX(t0) /* RxData */
488 jr ra
489 andi v0,0xff
490 END(GetChar)
491
492 /* int PutChar(UINT8 v);
493 * Returns: 0 if ok, -1 otherwise
494 */
495 LEAF(PutChar)
496 lui t0,(USART_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */
497 lui t1,1000 /* n*65k spins max */
498 li v0,0
499 TxNotReady:
500 lw t4,USARTST(t0) /* ChannelStatus */
501 andi t4,t4,USI_TXRDY
502 bgtz t4,TxReady
503 subu t1,t1,1
504 /* still ok to spin? */
505 bgtz t1,TxNotReady
506 nop
507 /* Timed out
508 */
509 jr ra
510 li v0,-1
511
512 /* Send it
513 */
514 TxReady:
515 jr ra
516 sw a0,USARTTX(t0)
517
518 END(PutChar)
519
520 /* Second arg is a function to call with the first arg:
521 * void switch_stack_and_call(void *arg, void (*function)(void *));
522 */
523 LEAF(switch_stack_and_call)
524 /* Get a stack and jump. It would be a very bad idea to return but..
525 */
526 #ifdef __GP_SUPPORT__
527 la gp, _C_LABEL (_gp)
528 #endif
529 la sp,_end
530 jr a1
531 addiu sp,sp,(2*1024) /* BUGBUG arbitrary */
532
533 END(switch_stack_and_call)
534
535