xref: /netbsd/sys/arch/emips/stand/common/start.S (revision 6550d01e)
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
93EXPORT(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
102VECTOR(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
111EXPORT(UserInterruptHandler)
112    .word 0
113
114EXPORT(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
219VECTOR_END(ExceptionHandler)
220
221     .org 0x00000200
222EXPORT(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     */
239TextStart:                                /* + 0 */
240    /* Text start at final link address */
241    .int    start
242
243DataEnd:                                  /* + 4 */
244    /* Data end == bss start */
245    .int    _edata
246
247BssEnd:                                   /* + 8 */
248    /* Bss end */
249    .int    _end
250
251RelocToRAM:                               /* *+12 */
252    .int    InRAM
253
254MipsStart2:
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
268CpyLoop:
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)  */
282ZroLoop:
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     */
297InRAM:
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     */
316EXPORT(_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
324EXPORT(Stop)
325	b     Stop
326    nop
327
328END(real_start)
329
330        .set noreorder
331        .set noat
332        .set nomacro
333
334/* void Delay(UINT32 count)
335 */
336LEAF(Delay)
337    bne    a0,zero,_C_LABEL(Delay)
338    subu   a0,1
339    j      ra
340    nop
341END(Delay)
342
343/* UINT32 GetPsr(void)
344 * Returns the PSR (coprocessor 0 status)
345 */
346LEAF(GetPsr)
347    mfc0   v0, MIPS_COP_0_STATUS
348    j      ra
349    nop
350END(GetPsr)
351
352/* void SetPsr(UINT32 Psr)
353 * Sets the PSR (coprocessor 0 status)
354 */
355LEAF(SetPsr)
356    mtc0   a0,MIPS_COP_0_STATUS
357    j      ra
358    nop
359END(SetPsr)
360
361/* UINT32 GetCause(void)
362 * Returns the Cause register (coprocessor 0)
363 */
364LEAF(GetCause)
365    mfc0   v0,MIPS_COP_0_CAUSE
366    j      ra
367    nop
368END(GetCause)
369
370/* UINT32 GetEpc(void)
371 * Returns the Epc register (coprocessor 0)
372 */
373LEAF(GetEpc)
374    mfc0   v0,MIPS_COP_0_EXC_PC
375    j      ra
376    nop
377END(GetEpc)
378
379
380/* int PutWord(UINT32 Word);
381 * Returns: 0 if ok, -1 otherwise
382 */
383NESTED(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
393PutWordLoop:
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
417PutWordDone:
418    lw     ra,0(sp)
419    lw     s1,4(sp)
420    lw     s0,8(sp)
421    jr     ra
422    addiu  sp,sp,12
423
424END(PutWord)
425
426/* int Puts(char *String);
427 * Returns: 0 if ok, -1 otherwise
428 */
429NESTED(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     */
437PutsLoop:
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     */
454PutsDoneOk:
455    li     v0,0
456PutsDone:
457    lw     ra,0(sp)
458    lw     s0,4(sp)
459    jr     ra
460    addiu  sp,sp,8
461
462END(Puts)
463
464
465/* int GetChar(void);
466 * Returns: a non-negative value if ok, -1 otherwise
467 */
468LEAF(GetChar)
469    lui    t0,(USART_DEFAULT_ADDRESS>>16) /* nb: knows about 16bit chop */
470    lui    t1,1000          /* n*65k spins max */
471RxNotReady:
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
490END(GetChar)
491
492/* int PutChar(UINT8 v);
493 * Returns: 0 if ok, -1 otherwise
494 */
495LEAF(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
499TxNotReady:
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     */
514TxReady:
515    jr     ra
516    sw     a0,USARTTX(t0)
517
518END(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 */
523LEAF(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
533END(switch_stack_and_call)
534
535