Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: start.S,v 1.4 2021/12/03 10:49:25 andvar 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, right 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     lui   sp,%hi(_end)
    526     addiu sp,%lo(_end)
    527     jr    a1
    528 	addiu sp,sp,(2*1024)          /* BUGBUG arbitrary */
    529 
    530 END(switch_stack_and_call)
    531 
    532