xref: /nrf52832-nimble/rt-thread/libcpu/ppc/ppc405/context_gcc.S (revision 042d53a763ad75cb1465103098bb88c245d95138)
1#include "context.h"
2#define SPRG0	0x110	/* Special Purpose Register General 0 */
3#define SPRG1	0x111	/* Special Purpose Register General 1 */
4
5    .globl rt_hw_interrupt_disable
6    .globl rt_hw_interrupt_enable
7    .globl rt_hw_context_switch
8    .globl rt_hw_context_switch_to
9    .globl rt_hw_context_switch_interrupt
10    .globl rt_hw_systemcall_entry
11
12/*
13 * rt_base_t rt_hw_interrupt_disable();
14 * return the interrupt status and disable interrupt
15 */
16#if 0
17rt_hw_interrupt_disable:
18    mfmsr   r3          /* Disable interrupts */
19    li      r4,0
20    ori     r4,r4,MSR_EE
21    andc    r4,r4,r3
22    SYNC                /* Some chip revs need this... */
23    mtmsr   r4
24    SYNC
25    blr
26#else
27rt_hw_interrupt_disable:
28    addis  r4, r0, 0xFFFD
29    ori    r4, r4, 0x7FFF
30    mfmsr  r3
31    and    r4, r4, 3                                      /* Clear bits 14 and 16, corresponding to...   */
32    mtmsr  r4                                            /* ...critical and non-critical interrupts     */
33    blr
34#endif
35
36/*
37 * void rt_hw_interrupt_enable(rt_base_t level);
38 * restore interrupt
39 */
40rt_hw_interrupt_enable:
41    mtmsr   r3
42    SYNC
43    blr
44
45/*
46 * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
47 * r3 --> from
48 * r4 --> to
49 *
50 * r1: stack pointer
51 */
52rt_hw_systemcall_entry:
53    mtspr   SPRG0,r3                            /* save r3 to SPRG0 */
54    mtspr   SPRG1,r4                            /* save r4 to SPRG1 */
55
56    lis     r3,rt_thread_switch_interrput_flag@h
57    ori     r3,r3,rt_thread_switch_interrput_flag@l
58    lwz     r4,0(r3)
59    cmpi    cr0,0,r4,0x0                        /* whether is 0     */
60    beq     _no_switch                          /* no switch, exit  */
61    li      r4,0x0                              /* set rt_thread_switch_interrput_flag to 0 */
62    stw     r4,0(r3)
63
64    /* load from thread to r3 */
65    lis     r3,rt_interrupt_from_thread@h       /* set rt_interrupt_from_thread */
66    ori     r3,r3,rt_interrupt_from_thread@l
67    lwz     r3,0(r3)
68
69    cmpi    cr0,0,r3,0x0                        /* whether is 0 */
70    beq     _restore                            /* it's first switch, goto _restore */
71
72    /* save r1:sp to thread[from] stack pointer */
73    subi    r1, r1, STACK_FRAME_SIZE
74    stw     r1, 0(r3)
75
76    /* restore r3, r4 from SPRG */
77    mfspr   r3,SPRG0
78    mfspr   r4,SPRG0
79
80    /* save registers   */
81    stw     r0,GPR0(r1)                         /* save general purpose registers 0    */
82    stmw    r2,GPR2(r1)                         /* save general purpose registers 2-31 */
83
84    mfusprg0 r0                                 /* save usprg0  */
85    stw     r0,USPRG0(r1)
86    mfcr    r0,                                 /* save cr      */
87    stw     r0,CR(r1)
88    mfxer   r0                                  /* save xer     */
89    stw     r0,XER(r1)
90    mfctr   r0                                  /* save ctr     */
91    stw     r0,CTR(r1)
92    mflr    r0                                  /* save lr      */
93    stw     r0, LR(r1)
94
95    mfsrr0  r0                                  /* save SRR0 and SRR1   */
96    stw     r0,SRR0(r1)
97    mfsrr1  r0
98    stw     r0,SRR1(r1)
99
100_restore:
101    /* get thread[to] stack pointer */
102    lis     r4,rt_interrupt_to_thread@h
103    ori     r4,r4,rt_interrupt_to_thread@l
104    lwz     r1,0(r4)
105    lwz     r1,0(r1)
106
107    lwz     r0,SRR1(r1)                         /* restore SRR1 and SRR0   */
108    mtsrr1  r0
109    lwz     r0,SRR0(r1)
110    mtsrr0  r0
111
112    lwz     r0,LR(r1)                           /* restore lr       */
113    mtlr    r0
114    lwz     r0,CTR(r1)                          /* restore ctr     */
115    mtctr   r0
116    lwz     r0,XER(r1)                          /* restore xer     */
117    mtxer   r0
118    lwz     r0,CR(r1)                           /* restore cr      */
119    mtcr    r0
120    lwz     r0,USPRG0(r1)                       /* restore usprg0  */
121    // mtusprg0 r0
122
123    lmw     r2, GPR2(r1)                        /* restore general register */
124    lwz     r0,GPR0(r1)
125    addi    r1, r1, STACK_FRAME_SIZE
126    /* RFI will restore status register and thus the correct priority*/
127    rfi
128
129_no_switch:
130    /* restore r3, r4 from SPRG */
131    mfspr   r3,SPRG0
132    mfspr   r4,SPRG0
133    rfi
134
135    /* void rt_hw_context_switch_to(to); */
136    .globl rt_hw_context_switch_to
137rt_hw_context_switch_to:
138    /* set rt_thread_switch_interrput_flag = 1 */
139    lis     r5,rt_thread_switch_interrput_flag@h
140    ori     r5,r5,rt_thread_switch_interrput_flag@l
141    li      r6, 0x01
142    stw     r6,0(r5)
143
144    /* set rt_interrupt_from_thread = 0 */
145    lis     r5,rt_interrupt_from_thread@h
146    ori     r5,r5,rt_interrupt_from_thread@l
147    li      r6, 0x00
148    stw     r6,0(r5)
149
150    /* set rt_interrupt_from_thread = to */
151    lis     r5,rt_interrupt_to_thread@h
152    ori     r5,r5,rt_interrupt_to_thread@l
153    stw     r3,0(r5)
154
155    /* trigger a system call */
156    sc
157
158    blr
159
160    /* void rt_hw_context_switch(from, to); */
161    .globl rt_hw_context_switch
162rt_hw_context_switch:
163    /* compare rt_thread_switch_interrupt_flag and set it */
164    lis     r5,rt_thread_switch_interrput_flag@h
165    ori     r5,r5,rt_thread_switch_interrput_flag@l
166    lwz     r6,0(r5)
167    cmpi    cr0,0,r6,0x1                        /* whether is 1 */
168    beq     _reswitch                           /* set already, goto _reswitch */
169    li      r6,0x1                              /* set rt_thread_switch_interrput_flag to 1*/
170    stw     r6,0(r5)
171
172    /* set rt_interrupt_from_thread to 'from' */
173    lis     r5,rt_interrupt_from_thread@h
174    ori     r5,r5,rt_interrupt_from_thread@l
175    stw     r3,0(r5)
176
177_reswitch:
178    /* set rt_interrupt_to_thread to 'to' */
179    lis     r6,rt_interrupt_to_thread@h
180    ori     r6,r6,rt_interrupt_to_thread@l
181    stw     r4,0(r6)
182
183    /* trigger a system call */
184    sc
185
186    blr
187
188    .globl rt_hw_context_switch_interrupt
189rt_hw_context_switch_interrupt:
190    /* compare rt_thread_switch_interrupt_flag and set it */
191    lis     r5,rt_thread_switch_interrput_flag@h
192    ori     r5,r5,rt_thread_switch_interrput_flag@l
193    lwz     r6,0(r5)
194    cmpi    cr0,0,r6,0x1                        /* whether is 1 */
195    beq     _int_reswitch                       /* set already, goto _reswitch */
196    li      r6,0x1                              /* set rt_thread_switch_interrput_flag to 1*/
197    stw     r6,0(r5)
198
199    /* set rt_interrupt_from_thread to 'from' */
200    lis     r5,rt_interrupt_from_thread@h
201    ori     r5,r5,rt_interrupt_from_thread@l
202    stw     r3,0(r5)
203
204_int_reswitch:
205    /* set rt_interrupt_to_thread to 'to' */
206    lis     r6,rt_interrupt_to_thread@h
207    ori     r6,r6,rt_interrupt_to_thread@l
208    stw     r4,0(r6)
209
210    blr
211