rt-thread-official/libcpu/ppc/ppc405/context_gcc.S

211 lines
6.5 KiB
ArmAsm

#include "context.h"
#define SPRG0 0x110 /* Special Purpose Register General 0 */
#define SPRG1 0x111 /* Special Purpose Register General 1 */
.globl rt_hw_interrupt_disable
.globl rt_hw_interrupt_enable
.globl rt_hw_context_switch
.globl rt_hw_context_switch_to
.globl rt_hw_context_switch_interrupt
.globl rt_hw_systemcall_entry
/*
* rt_base_t rt_hw_interrupt_disable();
* return the interrupt status and disable interrupt
*/
#if 0
rt_hw_interrupt_disable:
mfmsr r3 /* Disable interrupts */
li r4,0
ori r4,r4,MSR_EE
andc r4,r4,r3
SYNC /* Some chip revs need this... */
mtmsr r4
SYNC
blr
#else
rt_hw_interrupt_disable:
addis r4, r0, 0xFFFD
ori r4, r4, 0x7FFF
mfmsr r3
and r4, r4, 3 /* Clear bits 14 and 16, corresponding to... */
mtmsr r4 /* ...critical and non-critical interrupts */
blr
#endif
/*
* void rt_hw_interrupt_enable(rt_base_t level);
* restore interrupt
*/
rt_hw_interrupt_enable:
mtmsr r3
SYNC
blr
/*
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
* r3 --> from
* r4 --> to
*
* r1: stack pointer
*/
rt_hw_systemcall_entry:
mtspr SPRG0,r3 /* save r3 to SPRG0 */
mtspr SPRG1,r4 /* save r4 to SPRG1 */
lis r3,rt_thread_switch_interrput_flag@h
ori r3,r3,rt_thread_switch_interrput_flag@l
lwz r4,0(r3)
cmpi cr0,0,r4,0x0 /* whether is 0 */
beq _no_switch /* no switch, exit */
li r4,0x0 /* set rt_thread_switch_interrput_flag to 0 */
stw r4,0(r3)
/* load from thread to r3 */
lis r3,rt_interrupt_from_thread@h /* set rt_interrupt_from_thread */
ori r3,r3,rt_interrupt_from_thread@l
lwz r3,0(r3)
cmpi cr0,0,r3,0x0 /* whether is 0 */
beq _restore /* it's first switch, goto _restore */
/* save r1:sp to thread[from] stack pointer */
subi r1, r1, STACK_FRAME_SIZE
stw r1, 0(r3)
/* restore r3, r4 from SPRG */
mfspr r3,SPRG0
mfspr r4,SPRG0
/* save registers */
stw r0,GPR0(r1) /* save general purpose registers 0 */
stmw r2,GPR2(r1) /* save general purpose registers 2-31 */
mfusprg0 r0 /* save usprg0 */
stw r0,USPRG0(r1)
mfcr r0, /* save cr */
stw r0,CR(r1)
mfxer r0 /* save xer */
stw r0,XER(r1)
mfctr r0 /* save ctr */
stw r0,CTR(r1)
mflr r0 /* save lr */
stw r0, LR(r1)
mfsrr0 r0 /* save SRR0 and SRR1 */
stw r0,SRR0(r1)
mfsrr1 r0
stw r0,SRR1(r1)
_restore:
/* get thread[to] stack pointer */
lis r4,rt_interrupt_to_thread@h
ori r4,r4,rt_interrupt_to_thread@l
lwz r1,0(r4)
lwz r1,0(r1)
lwz r0,SRR1(r1) /* restore SRR1 and SRR0 */
mtsrr1 r0
lwz r0,SRR0(r1)
mtsrr0 r0
lwz r0,LR(r1) /* restore lr */
mtlr r0
lwz r0,CTR(r1) /* restore ctr */
mtctr r0
lwz r0,XER(r1) /* restore xer */
mtxer r0
lwz r0,CR(r1) /* restore cr */
mtcr r0
lwz r0,USPRG0(r1) /* restore usprg0 */
// mtusprg0 r0
lmw r2, GPR2(r1) /* restore general register */
lwz r0,GPR0(r1)
addi r1, r1, STACK_FRAME_SIZE
/* RFI will restore status register and thus the correct priority*/
rfi
_no_switch:
/* restore r3, r4 from SPRG */
mfspr r3,SPRG0
mfspr r4,SPRG0
rfi
/* void rt_hw_context_switch_to(to); */
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
/* set rt_thread_switch_interrput_flag = 1 */
lis r5,rt_thread_switch_interrput_flag@h
ori r5,r5,rt_thread_switch_interrput_flag@l
li r6, 0x01
stw r6,0(r5)
/* set rt_interrupt_from_thread = 0 */
lis r5,rt_interrupt_from_thread@h
ori r5,r5,rt_interrupt_from_thread@l
li r6, 0x00
stw r6,0(r5)
/* set rt_interrupt_from_thread = to */
lis r5,rt_interrupt_to_thread@h
ori r5,r5,rt_interrupt_to_thread@l
stw r3,0(r5)
/* trigger a system call */
sc
blr
/* void rt_hw_context_switch(from, to); */
.globl rt_hw_context_switch
rt_hw_context_switch:
/* compare rt_thread_switch_interrupt_flag and set it */
lis r5,rt_thread_switch_interrput_flag@h
ori r5,r5,rt_thread_switch_interrput_flag@l
lwz r6,0(r5)
cmpi cr0,0,r6,0x1 /* whether is 1 */
beq _reswitch /* set already, goto _reswitch */
li r6,0x1 /* set rt_thread_switch_interrput_flag to 1*/
stw r6,0(r5)
/* set rt_interrupt_from_thread to 'from' */
lis r5,rt_interrupt_from_thread@h
ori r5,r5,rt_interrupt_from_thread@l
stw r3,0(r5)
_reswitch:
/* set rt_interrupt_to_thread to 'to' */
lis r6,rt_interrupt_to_thread@h
ori r6,r6,rt_interrupt_to_thread@l
stw r4,0(r6)
/* trigger a system call */
sc
blr
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
/* compare rt_thread_switch_interrupt_flag and set it */
lis r5,rt_thread_switch_interrput_flag@h
ori r5,r5,rt_thread_switch_interrput_flag@l
lwz r6,0(r5)
cmpi cr0,0,r6,0x1 /* whether is 1 */
beq _int_reswitch /* set already, goto _reswitch */
li r6,0x1 /* set rt_thread_switch_interrput_flag to 1*/
stw r6,0(r5)
/* set rt_interrupt_from_thread to 'from' */
lis r5,rt_interrupt_from_thread@h
ori r5,r5,rt_interrupt_from_thread@l
stw r3,0(r5)
_int_reswitch:
/* set rt_interrupt_to_thread to 'to' */
lis r6,rt_interrupt_to_thread@h
ori r6,r6,rt_interrupt_to_thread@l
stw r4,0(r6)
blr