start.S revision 1.2 1 /* $NetBSD: start.S,v 1.2 2011/03/10 18:18:00 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 NESTED_NOPROFILE(ExceptionHandler,SIZEOF_CXTINFO,$31)
103 la k1, UserInterruptHandler
104 lw k1,0(k1)
105 bne k1,zero,Dispatch
106 mfc0 k0, MIPS_COP_0_EXC_PC
107 j k0
108 nop /* do not! pop status */
109
110 EXPORT(UserInterruptHandler)
111 .word 0
112
113 EXPORT(Dispatch)
114 /* Save state on stack */
115 addiu sp, sp, -SIZEOF_CXTINFO
116 /* save registers */
117 .set noat
118 sw AT, TS_AT(sp)
119 .set at
120 sw v0, TS_V0(sp)
121 sw v1, TS_V1(sp)
122 sw a0, TS_A0(sp)
123 sw a1, TS_A1(sp)
124 sw a2, TS_A2(sp)
125 sw a3, TS_A3(sp)
126 sw t0, TS_T0(sp)
127 sw t1, TS_T1(sp)
128 sw t2, TS_T2(sp)
129 sw t3, TS_T3(sp)
130 sw t4, TS_T4(sp)
131 sw t5, TS_T5(sp)
132 sw t6, TS_T6(sp)
133 sw t7, TS_T7(sp)
134 sw s0, TS_S0(sp)
135 sw s1, TS_S1(sp)
136 sw s2, TS_S2(sp)
137 sw s3, TS_S3(sp)
138 sw s4, TS_S4(sp)
139 sw s5, TS_S5(sp)
140 sw s6, TS_S6(sp)
141 sw s7, TS_S7(sp)
142 sw t8, TS_T8(sp)
143 sw t9, TS_T9(sp)
144 sw k0, TS_K0(sp)
145 sw k1, TS_K1(sp)
146 sw gp, TS_GP(sp)
147 /* sp: later */
148 sw fp, TS_FP(sp)
149 sw ra, TS_RA(sp)
150
151 mfc0 a0, MIPS_COP_0_STATUS
152 mflo t0
153 mfhi t1
154 sw a0, TS_SR(sp)
155 sw t0, TS_LO(sp)
156 sw t1, TS_HI(sp)
157 sw k0, TS_PC(sp)
158
159 /* Save original stack */
160 move a0,sp
161 addiu t0, sp, SIZEOF_CXTINFO
162 jalr k1
163 sw t0, TS_SP(sp)
164
165 /* Returned value is new PCXINFO */
166 move a0,v0
167
168 /* First load most registers */
169 .set noat
170 lw AT, TS_AT(a0)
171 lw v0, TS_V0(a0)
172 lw v1, TS_V1(a0)
173 /* a0 later */
174 lw a1, TS_A1(a0)
175 lw a2, TS_A2(a0)
176 lw a3, TS_A3(a0)
177 lw t0, TS_T0(a0)
178 lw t1, TS_T1(a0)
179 lw t2, TS_T2(a0)
180 lw t3, TS_T3(a0)
181 lw t4, TS_T4(a0)
182 lw t5, TS_T5(a0)
183 lw t6, TS_T6(a0)
184 lw t7, TS_T7(a0)
185 lw s0, TS_S0(a0)
186 lw s1, TS_S1(a0)
187 lw s2, TS_S2(a0)
188 lw s3, TS_S3(a0)
189 lw s4, TS_S4(a0)
190 lw s5, TS_S5(a0)
191 lw s6, TS_S6(a0)
192 lw s7, TS_S7(a0)
193 lw t8, TS_T8(a0)
194 lw t9, TS_T9(a0)
195 /* k0,k1 not restored */
196 lw gp, TS_GP(a0)
197 /* sp later */
198 lw fp, TS_FP(a0)
199 lw ra, TS_RA(a0)
200
201 lw k1, TS_HI(a0)
202 lw k0, TS_LO(a0)
203 mthi k1
204 mtlo k0
205 lw k1, TS_SR(a0)
206 mtc0 k1, MIPS_COP_0_STATUS
207 /* NB: After this instruction we cannot take any interrupts or traps
208 */
209 lw sp, TS_SP(a0)
210
211 /* Put pc into k0 */
212 lw k0, TS_PC(a0)
213 lw a0, TS_A0(a0)
214 j k0
215 rfe
216 .set at
217
218 END(ExceptionHandler)
219
220 .org 0x00000200
221 EXPORT(real_start)
222 .ent _C_LABEL(real_start)
223
224 #ifdef SECONDARY_BOOTBLOCK
225 /*
226 * If this is the program that goes into FLASH we must copy ourselves down to RAM.
227 * FLASH default on the MLx is at 0xf0000000, DRAM at 0.
228 */
229 addi a0,ra,-8 /* Compensate for the first two instructions */
230
231 /* Get the address(relative) of TextStart
232 */
233 bgezal zero, _C_LABEL(MipsStart2) /* Always jumps */
234 nop
235
236 /* All of the static data, since we are at it.
237 */
238 TextStart: /* + 0 */
239 /* Text start at final link address */
240 .int start
241
242 DataEnd: /* + 4 */
243 /* Data end == bss start */
244 .int _edata
245
246 BssEnd: /* + 8 */
247 /* Bss end */
248 .int _end
249
250 RelocToRAM: /* *+12 */
251 .int InRAM
252
253 MipsStart2:
254
255 /* Source = a0, Dst = t2 */
256 lw t2, 0(ra) /* _C_LABEL(TextStart) */
257
258 /* EndPtr = t3 */
259 /* in bdelay slot */
260
261 /* If a0 != t2 then we are running in Flash but should run in RAM
262 * In that case copy .text. Otherwise skip to .bss.
263 */
264 beq a0,t2,ZroLoop-4
265 lw t3, 4(ra) /* _C_LABEL(DataEnd) */
266
267 CpyLoop:
268 /* loop copying 2 words at a time */
269 lw t4,0(a0)
270 lw t5,4(a0)
271 addiu a0,a0,8
272 sw t4,0(t2)
273 addiu t2,t2,8
274 sltu t1,t2,t3
275 bne t1,zero,CpyLoop
276 sw t5,-4(t2)
277
278 /* zero the bss
279 */
280 lw t4, 8(ra) /* _C_LABEL(BssEnd) */
281 ZroLoop:
282 sltu t1,t3,t4
283 sw zero,0(t3)
284 bne t1,zero,ZroLoop
285 addiu t3,t3,4
286
287 /* Jump to RAM copy (below)
288 */
289 lw t1, 12(ra) /* _C_LABEL(RelocToRAM) */
290 jr t1
291 nop
292
293 /*
294 * Execute from here after copying out of FLASH into RAM
295 */
296 InRAM:
297
298 #endif /* SECONDARY_BOOTBLOCK */
299
300 /* Get a stack
301 */
302 #ifdef __GP_SUPPORT__
303 la gp, _C_LABEL (_gp)
304 #endif
305 la sp,_end
306 addiu sp,sp,(8*1024) /* BUGBUG arbitrary */
307
308 /* Jump to main
309 */
310 jal main
311 add a0,sp,zero
312
313 /* Load failed, reset the processor and jump back to the origins.
314 */
315 EXPORT(_rtt) /* ahem */
316 li t0,0x1260ff80 /* NB: On new builds this is a SYS-RESET as well */
317 mtc0 t0,MIPS_COP_0_STATUS
318
319 lui t0,(BRAM_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */
320 jr t0
321 nop
322
323 EXPORT(Stop)
324 b Stop
325 nop
326
327 END(real_start)
328
329 .set noreorder
330 .set noat
331 .set nomacro
332
333 /* void Delay(UINT32 count)
334 */
335 LEAF(Delay)
336 bne a0,zero,_C_LABEL(Delay)
337 subu a0,1
338 j ra
339 nop
340 END(Delay)
341
342 /* UINT32 GetPsr(void)
343 * Returns the PSR (coprocessor 0 status)
344 */
345 LEAF(GetPsr)
346 mfc0 v0, MIPS_COP_0_STATUS
347 j ra
348 nop
349 END(GetPsr)
350
351 /* void SetPsr(UINT32 Psr)
352 * Sets the PSR (coprocessor 0 status)
353 */
354 LEAF(SetPsr)
355 mtc0 a0,MIPS_COP_0_STATUS
356 j ra
357 nop
358 END(SetPsr)
359
360 /* UINT32 GetCause(void)
361 * Returns the Cause register (coprocessor 0)
362 */
363 LEAF(GetCause)
364 mfc0 v0,MIPS_COP_0_CAUSE
365 j ra
366 nop
367 END(GetCause)
368
369 /* UINT32 GetEpc(void)
370 * Returns the Epc register (coprocessor 0)
371 */
372 LEAF(GetEpc)
373 mfc0 v0,MIPS_COP_0_EXC_PC
374 j ra
375 nop
376 END(GetEpc)
377
378
379 /* int PutWord(UINT32 Word);
380 * Returns: 0 if ok, -1 otherwise
381 */
382 NESTED(PutWord,12,$31)
383 subu sp,sp,12
384 sw s0,8(sp)
385 sw s1,4(sp)
386 sw ra,0(sp)
387
388 or s1,a0,zero
389 /* Spit all nibbles
390 */
391 li s0,8
392 PutWordLoop:
393 srl a0,s1,32-4
394 li t0,10
395 sltu t1,a0,t0
396 bnez t1,$Digit
397 li a1,'0'
398 subu a0,a0,t0
399 li a1,'a'
400 $Digit:
401 sll s1,s1,4
402 jal PutChar
403 add a0,a0,a1
404
405 subu s0,s0,1
406 bne v0,zero,PutWordDone /* printed ok? */
407 li v0,-1
408
409 /* done yet? */
410 bne s0,zero,PutWordLoop
411 nop
412
413 /* done
414 */
415 li v0,0
416 PutWordDone:
417 lw ra,0(sp)
418 lw s1,4(sp)
419 lw s0,8(sp)
420 jr ra
421 addiu sp,sp,12
422
423 END(PutWord)
424
425 /* int Puts(char *String);
426 * Returns: 0 if ok, -1 otherwise
427 */
428 NESTED(Puts,8,$31)
429 subu sp,sp,8
430 sw s0,4(sp)
431 sw ra,0(sp)
432
433 or s0,a0,zero
434 /* Spit all chars until zero
435 */
436 PutsLoop:
437 lbu a0,0(s0)
438 addiu s0,s0,1
439 beq a0,zero,PutsDoneOk
440 nop
441 jal PutChar
442 nop
443 beq v0,zero,PutsLoop
444 nop
445
446 /* Timed out
447 */
448 b PutsDone
449 li v0,-1
450
451 /* done
452 */
453 PutsDoneOk:
454 li v0,0
455 PutsDone:
456 lw ra,0(sp)
457 lw s0,4(sp)
458 jr ra
459 addiu sp,sp,8
460
461 END(Puts)
462
463
464 /* int GetChar(void);
465 * Returns: a non-negative value if ok, -1 otherwise
466 */
467 LEAF(GetChar)
468 lui t0,(USART_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */
469 lui t1,1000 /* n*65k spins max */
470 RxNotReady:
471 lw t4,USARTST(t0) /* ChannelStatus */
472 andi t4,t4,USI_RXRDY
473 bgtz t4,$GotByte
474 subu t1,t1,1
475 /* still ok to spin? */
476 bgtz t1,RxNotReady
477 nop
478 /* Timed out
479 */
480 jr ra
481 li v0,-1
482
483 /* Gottabyte
484 */
485 $GotByte:
486 lw v0,USARTRX(t0) /* RxData */
487 jr ra
488 andi v0,0xff
489 END(GetChar)
490
491 /* int PutChar(UINT8 v);
492 * Returns: 0 if ok, -1 otherwise
493 */
494 LEAF(PutChar)
495 lui t0,(USART_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */
496 lui t1,1000 /* n*65k spins max */
497 li v0,0
498 TxNotReady:
499 lw t4,USARTST(t0) /* ChannelStatus */
500 andi t4,t4,USI_TXRDY
501 bgtz t4,TxReady
502 subu t1,t1,1
503 /* still ok to spin? */
504 bgtz t1,TxNotReady
505 nop
506 /* Timed out
507 */
508 jr ra
509 li v0,-1
510
511 /* Send it
512 */
513 TxReady:
514 jr ra
515 sw a0,USARTTX(t0)
516
517 END(PutChar)
518
519 /* Second arg is a function to call with the first arg:
520 * void switch_stack_and_call(void *arg, void (*function)(void *));
521 */
522 LEAF(switch_stack_and_call)
523 /* Get a stack and jump. It would be a very bad idea to return but..
524 */
525 #ifdef __GP_SUPPORT__
526 la gp, _C_LABEL (_gp)
527 #endif
528 la sp,_end
529 jr a1
530 addiu sp,sp,(2*1024) /* BUGBUG arbitrary */
531
532 END(switch_stack_and_call)
533
534