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