xref: /nrf52832-nimble/rt-thread/libcpu/ppc/ppc405/start_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero#include <config.h>
2*10465441SEvalZero#include <asm/ppc_defs.h>
3*10465441SEvalZero
4*10465441SEvalZero/* #include <asm/cache.h> */
5*10465441SEvalZero#include "cache.h"
6*10465441SEvalZero#include <asm/ppc4xx.h>
7*10465441SEvalZero
8*10465441SEvalZero#include "context.h"
9*10465441SEvalZero
10*10465441SEvalZero#define CONFIG_SYS_DCACHE_SACR_VALUE       (0x00000000)
11*10465441SEvalZero#define CONFIG_SYS_ICACHE_SACR_VALUE                                   \
12*10465441SEvalZero        (PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + (  0 << 20)) |    \
13*10465441SEvalZero         PPC_128MB_SACR_VALUE(CONFIG_SYS_SDRAM_BASE + (128 << 20)) |    \
14*10465441SEvalZero         PPC_128MB_SACR_VALUE(CONFIG_SYS_FLASH_BASE))
15*10465441SEvalZero
16*10465441SEvalZero#define function_prolog(func_name)  .text; \
17*10465441SEvalZero                    .align 2; \
18*10465441SEvalZero                    .globl func_name; \
19*10465441SEvalZero                    func_name:
20*10465441SEvalZero#define function_epilog(func_name)  .type func_name,@function; \
21*10465441SEvalZero                    .size func_name,.-func_name
22*10465441SEvalZero
23*10465441SEvalZero/* We don't want the  MMU yet.
24*10465441SEvalZero*/
25*10465441SEvalZero#undef  MSR_KERNEL
26*10465441SEvalZero#define MSR_KERNEL ( MSR_ME  )  /* Machine Check */
27*10465441SEvalZero
28*10465441SEvalZero#define SYNC    \
29*10465441SEvalZero        sync;   \
30*10465441SEvalZero        isync
31*10465441SEvalZero
32*10465441SEvalZero/*
33*10465441SEvalZero * Macros for storing registers into and loading registers from
34*10465441SEvalZero * exception frames.
35*10465441SEvalZero */
36*10465441SEvalZero#define SAVE_GPR(n, base)       stw     n,GPR0+4*(n)(base)
37*10465441SEvalZero#define SAVE_2GPRS(n, base)     SAVE_GPR(n, base); SAVE_GPR(n+1, base)
38*10465441SEvalZero#define SAVE_4GPRS(n, base)     SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
39*10465441SEvalZero#define SAVE_8GPRS(n, base)     SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
40*10465441SEvalZero#define SAVE_10GPRS(n,base)     SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
41*10465441SEvalZero#define REST_GPR(n, base)       lwz     n,GPR0+4*(n)(base)
42*10465441SEvalZero#define REST_2GPRS(n, base)     REST_GPR(n, base); REST_GPR(n+1, base)
43*10465441SEvalZero#define REST_4GPRS(n, base)     REST_2GPRS(n, base); REST_2GPRS(n+2, base)
44*10465441SEvalZero#define REST_8GPRS(n, base)     REST_4GPRS(n, base); REST_4GPRS(n+4, base)
45*10465441SEvalZero#define REST_10GPRS(n,base)     REST_8GPRS(n, base); REST_2GPRS(n+8, base)
46*10465441SEvalZero
47*10465441SEvalZero/*
48*10465441SEvalZero * GCC sometimes accesses words at negative offsets from the stack
49*10465441SEvalZero * pointer, although the SysV ABI says it shouldn't.  To cope with
50*10465441SEvalZero * this, we leave this much untouched space on the stack on exception
51*10465441SEvalZero * entry.
52*10465441SEvalZero */
53*10465441SEvalZero#define STACK_UNDERHEAD 64
54*10465441SEvalZero
55*10465441SEvalZero/*
56*10465441SEvalZero * Exception entry code.  This code runs with address translation
57*10465441SEvalZero * turned off, i.e. using physical addresses.
58*10465441SEvalZero * We assume sprg3 has the physical address of the current
59*10465441SEvalZero * task's thread_struct.
60*10465441SEvalZero */
61*10465441SEvalZero /* Save:
62*10465441SEvalZero  * CR, r0, r1 (sp), r2, r3, r4, r5, r6, r20, r21, r22, r23,
63*10465441SEvalZero  * LR, CTR, XER, DAR, SRR0, SRR1
64*10465441SEvalZero  */
65*10465441SEvalZero#define EXCEPTION_PROLOG(reg1, reg2)    \
66*10465441SEvalZero        mtspr   SPRG0,r20;              \
67*10465441SEvalZero        mtspr   SPRG1,r21;              \
68*10465441SEvalZero        mfcr    r20;                    \
69*10465441SEvalZero        subi    r21,r1,INT_FRAME_SIZE+STACK_UNDERHEAD;  /* alloc exc. frame */\
70*10465441SEvalZero        stw     r20,_CCR(r21);  /* save registers */  \
71*10465441SEvalZero        stw     r22,GPR22(r21);         \
72*10465441SEvalZero        stw     r23,GPR23(r21);         \
73*10465441SEvalZero        mfspr   r20,SPRG0;              \
74*10465441SEvalZero        stw     r20,GPR20(r21);         \
75*10465441SEvalZero        mfspr   r22,SPRG1;              \
76*10465441SEvalZero        stw     r22,GPR21(r21);         \
77*10465441SEvalZero        mflr    r20;                    \
78*10465441SEvalZero        stw     r20,_LINK(r21);         \
79*10465441SEvalZero        mfctr   r22;                    \
80*10465441SEvalZero        stw     r22,_CTR(r21);          \
81*10465441SEvalZero        mfspr   r20,XER;                \
82*10465441SEvalZero        stw     r20,_XER(r21);          \
83*10465441SEvalZero        mfspr   r20, DAR_DEAR;          \
84*10465441SEvalZero        stw     r20,_DAR(r21);          \
85*10465441SEvalZero        mfspr   r22,reg1;               \
86*10465441SEvalZero        mfspr   r23,reg2;               \
87*10465441SEvalZero        stw     r0,GPR0(r21);           \
88*10465441SEvalZero        stw     r1,GPR1(r21);           \
89*10465441SEvalZero        stw     r2,GPR2(r21);           \
90*10465441SEvalZero        stw     r1,0(r21);/* back chain */      \
91*10465441SEvalZero        mr      r1,r21;/* set new kernel sp */  \
92*10465441SEvalZero        SAVE_4GPRS(3, r21);
93*10465441SEvalZero/*
94*10465441SEvalZero * Note: code which follows this uses cr0.eq (set if from kernel),
95*10465441SEvalZero * r21, r22 (SRR0), and r23 (SRR1).
96*10465441SEvalZero */
97*10465441SEvalZero
98*10465441SEvalZero/*
99*10465441SEvalZero * Exception vectors.
100*10465441SEvalZero *
101*10465441SEvalZero * The data words for `hdlr' and `int_return' are initialized with
102*10465441SEvalZero * OFFSET values only; they must be relocated first before they can
103*10465441SEvalZero * be used!
104*10465441SEvalZero */
105*10465441SEvalZero#define STD_EXCEPTION(n, label, hdlr)                           \
106*10465441SEvalZero        . = n;                                                  \
107*10465441SEvalZerolabel:                                                          \
108*10465441SEvalZero        EXCEPTION_PROLOG(SRR0, SRR1);                           \
109*10465441SEvalZero        lwz r3,GOT(transfer_to_handler);                        \
110*10465441SEvalZero        mtlr    r3;                                             \
111*10465441SEvalZero        addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
112*10465441SEvalZero        li      r20,MSR_KERNEL;                                 \
113*10465441SEvalZero        rlwimi  r20,r23,0,25,25;                                \
114*10465441SEvalZero        blrl;                                                   \
115*10465441SEvalZero.L_ ## label :                                                  \
116*10465441SEvalZero        .long   hdlr - _start + _START_OFFSET;                  \
117*10465441SEvalZero        .long   int_return - _start + _START_OFFSET
118*10465441SEvalZero
119*10465441SEvalZero#define CRIT_EXCEPTION(n, label, hdlr)                          \
120*10465441SEvalZero        . = n;                                                  \
121*10465441SEvalZerolabel:                                                          \
122*10465441SEvalZero        EXCEPTION_PROLOG(CSRR0, CSRR1);                         \
123*10465441SEvalZero        lwz     r3,GOT(transfer_to_handler);                    \
124*10465441SEvalZero        mtlr    r3;                                             \
125*10465441SEvalZero        addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
126*10465441SEvalZero        li      r20,(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE));     \
127*10465441SEvalZero        rlwimi  r20,r23,0,25,25;                                \
128*10465441SEvalZero        blrl;                                                   \
129*10465441SEvalZero.L_ ## label :                                                  \
130*10465441SEvalZero        .long   hdlr - _start + _START_OFFSET;                  \
131*10465441SEvalZero        .long   crit_return - _start + _START_OFFSET
132*10465441SEvalZero
133*10465441SEvalZero#define MCK_EXCEPTION(n, label, hdlr)                           \
134*10465441SEvalZero        . = n;                                                  \
135*10465441SEvalZerolabel:                                                          \
136*10465441SEvalZero        EXCEPTION_PROLOG(MCSRR0, MCSRR1);                       \
137*10465441SEvalZero        lwz r3,GOT(transfer_to_handler);                        \
138*10465441SEvalZero        mtlr    r3;                                             \
139*10465441SEvalZero        addi    r3,r1,STACK_FRAME_OVERHEAD;                     \
140*10465441SEvalZero        li  r20,(MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE));         \
141*10465441SEvalZero        rlwimi  r20,r23,0,25,25;                                \
142*10465441SEvalZero        blrl;                                                   \
143*10465441SEvalZero.L_ ## label :                                                  \
144*10465441SEvalZero        .long   hdlr - _start + _START_OFFSET;                  \
145*10465441SEvalZero        .long   mck_return - _start + _START_OFFSET
146*10465441SEvalZero
147*10465441SEvalZero
148*10465441SEvalZero/***************************************************************************
149*10465441SEvalZero *
150*10465441SEvalZero * These definitions simplify the ugly declarations necessary for GOT
151*10465441SEvalZero * definitions.
152*10465441SEvalZero *
153*10465441SEvalZero * Stolen from prepboot/bootldr.h, (C) 1998 Gabriel Paubert, [email protected]
154*10465441SEvalZero *
155*10465441SEvalZero * Uses r14 to access the GOT
156*10465441SEvalZero */
157*10465441SEvalZero
158*10465441SEvalZero#define START_GOT                               \
159*10465441SEvalZero        .section        ".got2","aw";           \
160*10465441SEvalZero.LCTOC1 = .+32768
161*10465441SEvalZero
162*10465441SEvalZero#define END_GOT                                 \
163*10465441SEvalZero        .text
164*10465441SEvalZero
165*10465441SEvalZero#define GET_GOT                                 \
166*10465441SEvalZero        bl      1f                      ;       \
167*10465441SEvalZero        .text   2                       ;       \
168*10465441SEvalZero0:      .long   .LCTOC1-1f              ;       \
169*10465441SEvalZero        .text                           ;       \
170*10465441SEvalZero1:      mflr    r14                     ;       \
171*10465441SEvalZero        lwz             r0,0b-1b(r14)   ;       \
172*10465441SEvalZero        add             r14,r0,r14              ;
173*10465441SEvalZero
174*10465441SEvalZero#define GOT_ENTRY(NAME)         .L_ ## NAME = . - .LCTOC1 ; .long NAME
175*10465441SEvalZero
176*10465441SEvalZero#define GOT(NAME)       .L_ ## NAME (r14)
177*10465441SEvalZero
178*10465441SEvalZero/*
179*10465441SEvalZero * Set up GOT: Global Offset Table
180*10465441SEvalZero *
181*10465441SEvalZero * Use r14 to access the GOT
182*10465441SEvalZero */
183*10465441SEvalZero START_GOT
184*10465441SEvalZero GOT_ENTRY(_GOT2_TABLE_)
185*10465441SEvalZero GOT_ENTRY(_FIXUP_TABLE_)
186*10465441SEvalZero
187*10465441SEvalZero GOT_ENTRY(_start)
188*10465441SEvalZero GOT_ENTRY(_start_of_vectors)
189*10465441SEvalZero GOT_ENTRY(_end_of_vectors)
190*10465441SEvalZero GOT_ENTRY(transfer_to_handler)
191*10465441SEvalZero
192*10465441SEvalZero GOT_ENTRY(__init_end)
193*10465441SEvalZero GOT_ENTRY(_end)
194*10465441SEvalZero GOT_ENTRY(__bss_start)
195*10465441SEvalZero END_GOT
196*10465441SEvalZero
197*10465441SEvalZero/*
198*10465441SEvalZero * r3 - 1st arg to board_init(): IMMP pointer
199*10465441SEvalZero * r4 - 2nd arg to board_init(): boot flag
200*10465441SEvalZero */
201*10465441SEvalZero    .text
202*10465441SEvalZeroversion_string:
203*10465441SEvalZero    .ascii "RT-Thread 0.4.0"
204*10465441SEvalZero
205*10465441SEvalZero    . = EXC_OFF_SYS_RESET
206*10465441SEvalZero_start_of_vectors:
207*10465441SEvalZero
208*10465441SEvalZero    /* Critical input. */
209*10465441SEvalZero    CRIT_EXCEPTION(0x100, CritcalInput, UnknownException)
210*10465441SEvalZero    CRIT_EXCEPTION(0x200, MachineCheck, MachineCheckException)
211*10465441SEvalZero    /* Data Storage exception. */
212*10465441SEvalZero    STD_EXCEPTION(0x300, DataStorage, UnknownException)
213*10465441SEvalZero    /* Instruction Storage exception. */
214*10465441SEvalZero    STD_EXCEPTION(0x400, InstStorage, UnknownException)
215*10465441SEvalZero
216*10465441SEvalZero    . = 0x0500
217*10465441SEvalZeroExtInterrupt:
218*10465441SEvalZero    /* save current thread stack */
219*10465441SEvalZero    subi    r1, r1, STACK_FRAME_SIZE
220*10465441SEvalZero
221*10465441SEvalZero    /* save registers   */
222*10465441SEvalZero    stw     r0,GPR0(r1)                         /* save general purpose registers 0    */
223*10465441SEvalZero    stmw    r2,GPR2(r1)                         /* save general purpose registers 2-31 */
224*10465441SEvalZero
225*10465441SEvalZero    mfusprg0 r0                                 /* save usprg0  */
226*10465441SEvalZero    stw     r0,USPRG0(r1)
227*10465441SEvalZero    mfcr    r0,                                 /* save cr      */
228*10465441SEvalZero    stw     r0,CR(r1)
229*10465441SEvalZero    mfxer   r0                                  /* save xer     */
230*10465441SEvalZero    stw     r0,XER(r1)
231*10465441SEvalZero    mfctr   r0                                  /* save ctr     */
232*10465441SEvalZero    stw     r0,CTR(r1)
233*10465441SEvalZero    mflr    r0                                  /* save lr      */
234*10465441SEvalZero    stw     r0, LR(r1)
235*10465441SEvalZero
236*10465441SEvalZero    mfsrr0  r0                                  /* save SRR0 and SRR1   */
237*10465441SEvalZero    stw     r0,SRR0(r1)
238*10465441SEvalZero    mfsrr1  r0
239*10465441SEvalZero    stw     r0,SRR1(r1)
240*10465441SEvalZero
241*10465441SEvalZero    bl rt_interrupt_enter
242*10465441SEvalZero    bl external_interrupt
243*10465441SEvalZero    bl rt_interrupt_leave
244*10465441SEvalZero
245*10465441SEvalZero    /* restore thread context */
246*10465441SEvalZero    lwz     r0,SRR1(r1)                         /* restore SRR1 and SRR0   */
247*10465441SEvalZero    mtsrr1  r0
248*10465441SEvalZero    lwz     r0,SRR0(r1)
249*10465441SEvalZero    mtsrr0  r0
250*10465441SEvalZero
251*10465441SEvalZero    lwz     r0,LR(r1)                           /* restore lr       */
252*10465441SEvalZero    mtlr    r0
253*10465441SEvalZero    lwz     r0,CTR(r1)                          /* restore ctr     */
254*10465441SEvalZero    mtctr   r0
255*10465441SEvalZero    lwz     r0,XER(r1)                          /* restore xer     */
256*10465441SEvalZero    mtxer   r0
257*10465441SEvalZero    lwz     r0,CR(r1)                           /* restore cr      */
258*10465441SEvalZero    mtcr    r0
259*10465441SEvalZero    lwz     r0,USPRG0(r1)                       /* restore usprg0  */
260*10465441SEvalZero    // mtusprg0 r0
261*10465441SEvalZero
262*10465441SEvalZero    lmw     r2, GPR2(r1)                        /* restore general register */
263*10465441SEvalZero    lwz     r0,GPR0(r1)
264*10465441SEvalZero    addi    r1, r1, STACK_FRAME_SIZE
265*10465441SEvalZero    b       rt_hw_systemcall_entry
266*10465441SEvalZero
267*10465441SEvalZero/* Alignment exception. */
268*10465441SEvalZero    . = 0x600
269*10465441SEvalZeroAlignment:
270*10465441SEvalZero    EXCEPTION_PROLOG(SRR0, SRR1)
271*10465441SEvalZero    mfspr   r4,DAR
272*10465441SEvalZero    stw     r4,_DAR(r21)
273*10465441SEvalZero    mfspr   r5,DSISR
274*10465441SEvalZero    stw     r5,_DSISR(r21)
275*10465441SEvalZero    addi    r3,r1,STACK_FRAME_OVERHEAD
276*10465441SEvalZero    li      r20,MSR_KERNEL
277*10465441SEvalZero    rlwimi  r20,r23,0,16,16     /* copy EE bit from saved MSR */
278*10465441SEvalZero    lwz     r6,GOT(transfer_to_handler)
279*10465441SEvalZero    mtlr    r6
280*10465441SEvalZero    blrl
281*10465441SEvalZero.L_Alignment:
282*10465441SEvalZero    .long   AlignmentException - _start + _START_OFFSET
283*10465441SEvalZero    .long   int_return - _start + _START_OFFSET
284*10465441SEvalZero
285*10465441SEvalZero/* Program check exception */
286*10465441SEvalZero    . = 0x700
287*10465441SEvalZeroProgramCheck:
288*10465441SEvalZero    EXCEPTION_PROLOG(SRR0, SRR1)
289*10465441SEvalZero    addi    r3,r1,STACK_FRAME_OVERHEAD
290*10465441SEvalZero    li      r20,MSR_KERNEL
291*10465441SEvalZero    rlwimi  r20,r23,0,16,16     /* copy EE bit from saved MSR */
292*10465441SEvalZero    lwz     r6,GOT(transfer_to_handler)
293*10465441SEvalZero    mtlr    r6
294*10465441SEvalZero    blrl
295*10465441SEvalZero.L_ProgramCheck:
296*10465441SEvalZero    .long   ProgramCheckException - _start + _START_OFFSET
297*10465441SEvalZero    .long   int_return - _start + _START_OFFSET
298*10465441SEvalZero
299*10465441SEvalZero    . = 0x0c00
300*10465441SEvalZeroSystemCall:
301*10465441SEvalZero    b rt_hw_systemcall_entry
302*10465441SEvalZero
303*10465441SEvalZero    . = 0x1000
304*10465441SEvalZeroPIT:
305*10465441SEvalZero    /* save current thread stack */
306*10465441SEvalZero    subi    r1, r1, STACK_FRAME_SIZE
307*10465441SEvalZero
308*10465441SEvalZero    /* save registers   */
309*10465441SEvalZero    stw     r0,GPR0(r1)                         /* save general purpose registers 0    */
310*10465441SEvalZero    stmw    r2,GPR2(r1)                         /* save general purpose registers 2-31 */
311*10465441SEvalZero
312*10465441SEvalZero    mfusprg0 r0                                 /* save usprg0  */
313*10465441SEvalZero    stw     r0,USPRG0(r1)
314*10465441SEvalZero    mfcr    r0,                                 /* save cr      */
315*10465441SEvalZero    stw     r0,CR(r1)
316*10465441SEvalZero    mfxer   r0                                  /* save xer     */
317*10465441SEvalZero    stw     r0,XER(r1)
318*10465441SEvalZero    mfctr   r0                                  /* save ctr     */
319*10465441SEvalZero    stw     r0,CTR(r1)
320*10465441SEvalZero    mflr    r0                                  /* save lr      */
321*10465441SEvalZero    stw     r0, LR(r1)
322*10465441SEvalZero
323*10465441SEvalZero    mfsrr0  r0                                  /* save SRR0 and SRR1   */
324*10465441SEvalZero    stw     r0,SRR0(r1)
325*10465441SEvalZero    mfsrr1  r0
326*10465441SEvalZero    stw     r0,SRR1(r1)
327*10465441SEvalZero
328*10465441SEvalZero    bl rt_interrupt_enter
329*10465441SEvalZero    bl DecrementerPITException
330*10465441SEvalZero    bl rt_interrupt_leave
331*10465441SEvalZero
332*10465441SEvalZero    /* restore thread context */
333*10465441SEvalZero    lwz     r0,SRR1(r1)                         /* restore SRR1 and SRR0   */
334*10465441SEvalZero    mtsrr1  r0
335*10465441SEvalZero    lwz     r0,SRR0(r1)
336*10465441SEvalZero    mtsrr0  r0
337*10465441SEvalZero
338*10465441SEvalZero    lwz     r0,LR(r1)                           /* restore lr       */
339*10465441SEvalZero    mtlr    r0
340*10465441SEvalZero    lwz     r0,CTR(r1)                          /* restore ctr     */
341*10465441SEvalZero    mtctr   r0
342*10465441SEvalZero    lwz     r0,XER(r1)                          /* restore xer     */
343*10465441SEvalZero    mtxer   r0
344*10465441SEvalZero    lwz     r0,CR(r1)                           /* restore cr      */
345*10465441SEvalZero    mtcr    r0
346*10465441SEvalZero    lwz     r0,USPRG0(r1)                       /* restore usprg0  */
347*10465441SEvalZero    // mtusprg0 r0
348*10465441SEvalZero
349*10465441SEvalZero    lmw     r2, GPR2(r1)                        /* restore general register */
350*10465441SEvalZero    lwz     r0,GPR0(r1)
351*10465441SEvalZero    addi    r1, r1, STACK_FRAME_SIZE
352*10465441SEvalZero    b       rt_hw_systemcall_entry
353*10465441SEvalZero
354*10465441SEvalZero    STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
355*10465441SEvalZero    STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
356*10465441SEvalZero
357*10465441SEvalZero    CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
358*10465441SEvalZero
359*10465441SEvalZero_end_of_vectors:
360*10465441SEvalZero    . = _START_OFFSET
361*10465441SEvalZero
362*10465441SEvalZero    /*
363*10465441SEvalZero     * start and end addresses of the BSS section
364*10465441SEvalZero     * they are taken from the linker script
365*10465441SEvalZero     */
366*10465441SEvalZero
367*10465441SEvalZero    .set    START_BSS,  __bss_start
368*10465441SEvalZero    .set    END_BSS,    __bss_end
369*10465441SEvalZero
370*10465441SEvalZero    /* stack top address exported from linker script */
371*10465441SEvalZero    .set    STACK_TOP,  __stack_top
372*10465441SEvalZero
373*10465441SEvalZero_start:
374*10465441SEvalZero    /*----------------------------------------------------------------------- */
375*10465441SEvalZero    /* Clear and set up some registers. */
376*10465441SEvalZero    /*----------------------------------------------------------------------- */
377*10465441SEvalZero    addi    r4,r0,0x0000
378*10465441SEvalZero    mtsgr   r4  /* Configure guarded attribute for performance. */
379*10465441SEvalZero    mtsler  r4  /* Configure endinanness */
380*10465441SEvalZero    mtsu0r  r4  /* and compression. */
381*10465441SEvalZero
382*10465441SEvalZero    /*------------------------------------------------------------------------
383*10465441SEvalZero     * Initialize vector tables and other registers
384*10465441SEvalZero     * set them all to 0. The Interrupt Handler implementation
385*10465441SEvalZero     * has to set these registers later on
386*10465441SEvalZero     *-----------------------------------------------------------------------*/
387*10465441SEvalZero    mtdcwr  r4
388*10465441SEvalZero    mtesr   r4          /* clear Exception Syndrome Reg */
389*10465441SEvalZero    mttcr   r4          /* clear Timer Control Reg */
390*10465441SEvalZero    mtxer   r4          /* clear Fixed-Point Exception Reg */
391*10465441SEvalZero    mtevpr  r4          /* clear Exception Vector Prefix Reg */
392*10465441SEvalZero
393*10465441SEvalZero    addi    r4,r0,(0xFFFF-0x10000)  /* set r4 to 0xFFFFFFFF (status in the */
394*10465441SEvalZero                        /* dbsr is cleared by setting bits to 1) */
395*10465441SEvalZero    mtdbsr  r4          /* clear/reset the dbsr */
396*10465441SEvalZero
397*10465441SEvalZero    /* Invalidate the i- and d-caches. */
398*10465441SEvalZero    bl      invalidate_icache
399*10465441SEvalZero    bl      invalidate_dcache
400*10465441SEvalZero
401*10465441SEvalZero    /* Set-up icache cacheability. */
402*10465441SEvalZero    lis     r4, CONFIG_SYS_ICACHE_SACR_VALUE@h
403*10465441SEvalZero    ori     r4, r4, CONFIG_SYS_ICACHE_SACR_VALUE@l
404*10465441SEvalZero    mticcr  r4
405*10465441SEvalZero    isync
406*10465441SEvalZero
407*10465441SEvalZero    /* Set-up dcache cacheability. */
408*10465441SEvalZero    lis     r4, CONFIG_SYS_DCACHE_SACR_VALUE@h
409*10465441SEvalZero    ori     r4, r4, CONFIG_SYS_DCACHE_SACR_VALUE@l
410*10465441SEvalZero    mtdccr  r4
411*10465441SEvalZero
412*10465441SEvalZero    /*----------------------------------------------------------------------- */
413*10465441SEvalZero    /* DMA Status, clear to come up clean */
414*10465441SEvalZero    /*----------------------------------------------------------------------- */
415*10465441SEvalZero    addis   r3,r0, 0xFFFF       /* Clear all existing DMA status */
416*10465441SEvalZero    ori     r3,r3, 0xFFFF
417*10465441SEvalZero    mtdcr   dmasr, r3
418*10465441SEvalZero
419*10465441SEvalZero    /* clear the BSS section */
420*10465441SEvalZero    lis     r3,START_BSS@h  // load start of BSS into r3
421*10465441SEvalZero    ori     r3,r3,START_BSS@l
422*10465441SEvalZero    lis     r4,END_BSS@h    // load end of BSS into r4
423*10465441SEvalZero    ori     r4,r4,END_BSS@l
424*10465441SEvalZero    sub     r4,r4,r3        // calculate length of BSS
425*10465441SEvalZero    srwi    r4,r4,2         // convert byte-length to word-length
426*10465441SEvalZero    li      r5,0            // zero r5
427*10465441SEvalZero    cmplw   0,r4,r5         // check to see whether length equals 0
428*10465441SEvalZero    beql    0,2f            // in case of length 0 we're already done
429*10465441SEvalZero    subi    r3,r3,4         // because of offset start 4 bytes lower
430*10465441SEvalZero    mtctr   r4              // use word-length of BSS section as counter
431*10465441SEvalZero1:  /* bss clear start */
432*10465441SEvalZero    stwu    r5,4(r3)        // zero one word of BSS section
433*10465441SEvalZero    bdnz    1b              // keep going until BSS is entirely clean
434*10465441SEvalZero2:  /* bss clear done */
435*10465441SEvalZero
436*10465441SEvalZero    /* Set up stack in the linker script defined RAM area */
437*10465441SEvalZero    lis     r1, STACK_TOP@h
438*10465441SEvalZero    ori     r1, r1, STACK_TOP@l
439*10465441SEvalZero
440*10465441SEvalZero    /* Set up a zeroized stack frame so that backtrace works right */
441*10465441SEvalZero    li      r0, 0
442*10465441SEvalZero    stwu    r0, -4(r1)
443*10465441SEvalZero    stwu    r0, -4(r1)
444*10465441SEvalZero
445*10465441SEvalZero    /*
446*10465441SEvalZero     * Set up a dummy frame to store reset vector as return address.
447*10465441SEvalZero     * this causes stack underflow to reset board.
448*10465441SEvalZero     */
449*10465441SEvalZero    stwu    r1, -8(r1)          /* Save back chain and move SP */
450*10465441SEvalZero    lis     r0, RESET_VECTOR@h  /* Address of reset vector */
451*10465441SEvalZero    ori     r0, r0, RESET_VECTOR@l
452*10465441SEvalZero    stwu    r1, -8(r1)          /* Save back chain and move SP */
453*10465441SEvalZero    stw     r0, +12(r1)         /* Save return addr (underflow vect) */
454*10465441SEvalZero
455*10465441SEvalZero    GET_GOT                     /* initialize GOT access    */
456*10465441SEvalZero
457*10465441SEvalZero    /* NEVER RETURNS! */
458*10465441SEvalZero    bl  rtthread_startup
459*10465441SEvalZero
460*10465441SEvalZero/*
461*10465441SEvalZero * Note: code which follows this uses cr0.eq (set if from kernel),
462*10465441SEvalZero * r20(new MSR), r21(trap frame), r22 (SRR0), and r23 (SRR1).
463*10465441SEvalZero */
464*10465441SEvalZero
465*10465441SEvalZero/*
466*10465441SEvalZero * This code finishes saving the registers to the exception frame
467*10465441SEvalZero * and jumps to the appropriate handler for the exception.
468*10465441SEvalZero * Register r21 is pointer into trap frame, r1 has new stack pointer.
469*10465441SEvalZero */
470*10465441SEvalZerotransfer_to_handler:
471*10465441SEvalZero    stw     r22,_NIP(r21)
472*10465441SEvalZero    lis     r22,MSR_POW@h       /* clear POW bit */
473*10465441SEvalZero    andc    r23,r23,r22         /* use normal power management */
474*10465441SEvalZero    stw     r23,_MSR(r21)       /* MSC value when the exception returns */
475*10465441SEvalZero    SAVE_GPR(7, r21)
476*10465441SEvalZero    SAVE_4GPRS(8, r21)
477*10465441SEvalZero    SAVE_8GPRS(12, r21)
478*10465441SEvalZero    SAVE_8GPRS(24, r21)
479*10465441SEvalZero    mflr    r23                 /* hdlr/int_return addr immediately follows */
480*10465441SEvalZero    andi.   r24,r23,0x3f00      /* get vector offset */
481*10465441SEvalZero    stw     r24,TRAP(r21)       /* vector address, such as 0x1000 for PIT */
482*10465441SEvalZero    li      r22,0
483*10465441SEvalZero    stw     r22,RESULT(r21)     /* clear the sc return value */
484*10465441SEvalZero    mtspr   SPRG2,r22           /* r1 is now kernel sp */
485*10465441SEvalZero    lwz     r24,0(r23)          /* virtual address of hdlr */
486*10465441SEvalZero    lwz     r23,4(r23)          /* where to go when done */
487*10465441SEvalZero    mtspr   SRR0,r24            /* hdlr */
488*10465441SEvalZero    mtspr   SRR1,r20            /* MSR_KERNEL with ME enabled */
489*10465441SEvalZero    mtlr    r23                 /* call hdlr and then return to int_return */
490*10465441SEvalZero    SYNC                        /* note r3 has address for pt_regs on stack */
491*10465441SEvalZero    rfi                         /* jump to handler, enable ME */
492*10465441SEvalZero
493*10465441SEvalZeroint_return:
494*10465441SEvalZero    addi    r3,r1,STACK_FRAME_OVERHEAD
495*10465441SEvalZero    lwz     r4,_MQ(r1)
496*10465441SEvalZero    cmpwi   r4, 0
497*10465441SEvalZero    beq     goon_return
498*10465441SEvalZeroswitch_stack:
499*10465441SEvalZero    subi    r1,r4,STACK_FRAME_OVERHEAD
500*10465441SEvalZerogoon_return:
501*10465441SEvalZero    mfmsr   r28     /* Disable interrupts */
502*10465441SEvalZero    li      r4,0
503*10465441SEvalZero    ori     r4,r4,MSR_EE    /* clear External Interrupt Enable */
504*10465441SEvalZero    ori     r4,r4,MSR_DE    /* clear Debug Interrupts Enable - 4xx */
505*10465441SEvalZero    andc    r28,r28,r4
506*10465441SEvalZero    SYNC            /* Some chip revs need this... */
507*10465441SEvalZero    mtmsr   r28
508*10465441SEvalZero    SYNC
509*10465441SEvalZero    lwz     r2,_CTR(r1)
510*10465441SEvalZero    lwz     r0,_LINK(r1)
511*10465441SEvalZero    mtctr   r2
512*10465441SEvalZero    mtlr    r0
513*10465441SEvalZero    lwz     r2,_XER(r1)
514*10465441SEvalZero    lwz     r0,_CCR(r1)
515*10465441SEvalZero    mtspr   XER,r2
516*10465441SEvalZero    mtcrf   0xFF,r0
517*10465441SEvalZero    REST_10GPRS(3, r1)
518*10465441SEvalZero    REST_10GPRS(13, r1)
519*10465441SEvalZero    REST_8GPRS(23, r1)
520*10465441SEvalZero    REST_GPR(31, r1)
521*10465441SEvalZero    lwz     r2,_NIP(r1) /* Restore environment */
522*10465441SEvalZero    lwz     r0,_MSR(r1)
523*10465441SEvalZero    mtspr   SRR0,r2
524*10465441SEvalZero    mtspr   SRR1,r0
525*10465441SEvalZero    lwz     r0,GPR0(r1)
526*10465441SEvalZero    lwz     r2,GPR2(r1)
527*10465441SEvalZero    lwz     r1,GPR1(r1)
528*10465441SEvalZero    SYNC
529*10465441SEvalZero    rfi
530*10465441SEvalZero    b       .       /* prevent prefetch past rfi */
531*10465441SEvalZero
532*10465441SEvalZerocrit_return:
533*10465441SEvalZero    mfmsr   r28     /* Disable interrupts */
534*10465441SEvalZero    li  r4,0
535*10465441SEvalZero    ori r4,r4,MSR_EE
536*10465441SEvalZero    andc    r28,r28,r4
537*10465441SEvalZero    SYNC            /* Some chip revs need this... */
538*10465441SEvalZero    mtmsr   r28
539*10465441SEvalZero    SYNC
540*10465441SEvalZero    lwz r2,_CTR(r1)
541*10465441SEvalZero    lwz r0,_LINK(r1)
542*10465441SEvalZero    mtctr   r2
543*10465441SEvalZero    mtlr    r0
544*10465441SEvalZero    lwz r2,_XER(r1)
545*10465441SEvalZero    lwz r0,_CCR(r1)
546*10465441SEvalZero    mtspr   XER,r2
547*10465441SEvalZero    mtcrf   0xFF,r0
548*10465441SEvalZero    REST_10GPRS(3, r1)
549*10465441SEvalZero    REST_10GPRS(13, r1)
550*10465441SEvalZero    REST_8GPRS(23, r1)
551*10465441SEvalZero    REST_GPR(31, r1)
552*10465441SEvalZero    lwz r2,_NIP(r1) /* Restore environment */
553*10465441SEvalZero    lwz r0,_MSR(r1)
554*10465441SEvalZero    mtspr   SPRN_CSRR0,r2
555*10465441SEvalZero    mtspr   SPRN_CSRR1,r0
556*10465441SEvalZero    lwz r0,GPR0(r1)
557*10465441SEvalZero    lwz r2,GPR2(r1)
558*10465441SEvalZero    lwz r1,GPR1(r1)
559*10465441SEvalZero    SYNC
560*10465441SEvalZero    rfci
561*10465441SEvalZero
562*10465441SEvalZeroget_pvr:
563*10465441SEvalZero    mfspr   r3, PVR
564*10465441SEvalZero    blr
565