📄 arch_a.s
字号:
mtspr DEC,r3
/* enable auto-reload */
oris r4,r4,TCR_ARE
mtspr TCR,r4
/* reenable global interrupts */
mtmsr r7
blr
ENDFUNC(p_asm_setupTimerIrq)
/*----------------------------------------------------------------------------
|
| FUNCTION:
|
| UVAR_t p_pos_findbit(const UVAR_t bitfield, UVAR_t rrOffset);
|
| Returns the number of the first set bit.
|
| Note:
| This code is optimized, it fits into 3 cache lines.
|
*--------------------------------------------------------------------------*/
.align 5 /* align to even 32 byte boundary */
p_pos_findbit: /* input: r3 = bitmask, r4 = offset */
/* rotate r3 right by r4, store result in r6 */
subfic r5,r4,32
rlwnm r6,r3,r5,0,31
/* r5 = 1 */
addi r5,0,1
/* if (r6 & 0x0000FFFF == 0) { r5 |= 16; r6 >>= 16 } */
rlwinm. r3,r6,0,16,31
bne ..nzero0
rlwinm r6,r6,16,16,31
ori r5,r5,16
..nzero0:
/* if (r6 & 0x000000FF == 0) { r5 |= 8; r6 >>= 8 } */
rlwinm. r3,r6,0,24,31
bne ..nzero1
rlwinm r6,r6,24,24,31
ori r5,r5,8
..nzero1:
/* if (r6 & 0x0000000F == 0) { r5 |= 4; r6 >>= 4 } */
rlwinm. r3,r6,0,28,31
bne ..nzero2
rlwinm r6,r6,28,28,31
ori r5,r5,4
..nzero2:
/* if (r6 & 0x00000003 == 0) { r5 |= 2; r6 >>= 2 } */
rlwinm. r3,r6,0,30,31
bne ..nzero3
rlwinm r6,r6,30,30,31
ori r5,r5,2
..nzero3:
/* if (r6 & 0x00000001 != 0) { r5 &= ~1; } */
rlwinm r3,r6,0,31,31
xor r5,r5,r3
/* return (r5 + r4) & 31; */
add r6,r5,r4
rlwinm r3,r6,0,27,31
blr
ENDFUNC(p_pos_findbit)
/*----------------------------------------------------------------------------
|
| FUNCTION:
|
| void p_pos_startFirstContext(void);
|
| Starts the first task.
|
*--------------------------------------------------------------------------*/
.align 2
p_pos_startFirstContext:
/* start decrementer timer interrupt: */
/* 1) clear decrementer interrupt status */
addis r3,0,TSR_DIS
mtspr TSR,r3
/* 2) enable decrementer interrupt */
mfspr r4,TCR
oris r4,r4,TCR_DIE
mtspr TCR,r4
/* get stackptr: r1 = posCurrentTask_g->stackptr */
addis r3,0,posCurrentTask_g@h
ori r3,r3,posCurrentTask_g@l
lwzx r4,0,r3
lwzx r1,0,r4
/* pop SPRs and GPRs from stack and return from interrupt */
ISR_EXIT
ENDFUNC(p_pos_startFirstContext)
/* align following code to cache line boundary,
since the last function is used seldom */
.align 5
/*----------------------------------------------------------------------------
|
| FUNCTION:
|
| void p_pos_softContextSwitch(void);
|
| Does a context switch from application level.
|
*--------------------------------------------------------------------------*/
.align 2
p_pos_softContextSwitch:
/* open new stack frame, and store R0 */
OPEN_STACKFRAME
/* push SPRs to the stack, simulate an interrupt */
mfspr r0,LR
stw r0,SF_SRR0(r1)
mfmsr r0
stw r0,SF_SRR1(r1)
mfspr r0,CTR
stw r0,SF_CTR(r1)
mfspr r0,XER
stw r0,SF_XER(r1)
mfcr r0
stw r0,SF_CR(r1)
/* push GPRs to the stack */
PUSH_GPRS
/* swap task environment and stack */
/* r3 = &posCurrentTask_g; r4 = posCurrentTask_g */
addis r3,0,posCurrentTask_g@h
ori r3,r3,posCurrentTask_g@l
lwzx r4,0,r3
/* store stackptr: posCurrentTask_g->stackptr = r1 */
stwx r1,0,r4
/* r5 = &posNextTask_g; r6 = posNextTask_g */
addis r5,0,posNextTask_g@h
ori r5,r5,posNextTask_g@l
lwzx r6,0,r5
/* posCurrentTask_g = r6 */
stwx r6,0,r3
/* get stackptr: r1 = posNextTask_g->stackptr */
lwzx r1,0,r6
/* pop SPRs and GPRs from stack and return from interrupt */
ISR_EXIT
ENDFUNC(p_pos_softContextSwitch)
/*----------------------------------------------------------------------------
|
| FUNCTION:
|
| void p_pos_intContextSwitch(void);
|
| Does a context switch from interrupt level.
|
*--------------------------------------------------------------------------*/
.align 2
p_pos_intContextSwitch:
/* r6 = posNextTask_g */
addis r5,0,posNextTask_g@h
ori r5,r5,posNextTask_g@l
lwzx r6,0,r5
/* posCurrentTask_g = r6 */
addis r4,0,posCurrentTask_g@h
ori r4,r4,posCurrentTask_g@l
stwx r6,0,r4
/* get stackptr: r1 = posNextTask_g->stackptr */
lwzx r1,0,r6
/* pop SPRs and GPRs from stack and return from interrupt */
ISR_EXIT
ENDFUNC(p_pos_intContextSwitch)
/*----------------------------------------------------------------------------
|
| FUNCTION:
|
| void p_asm_timerISR(void);
|
| Timer interrupt service routine.
| You must set up a decrementer timer interrupt with a tick rate
| of 1000 Hz. This function must be called (via direct jump)
| when the decrementer signals an interrupt.
|
*--------------------------------------------------------------------------*/
.align 2
p_asm_timerISR:
/* open new stack frame, push SPRs and GPRs to the stack */
ISR_ENTER
/* clear interrupting device */
addis r3,0,TSR_DIS
mtspr TSR,r3
/* test if pico]OS is ready to accept timer ticks */
#if (TIMERISR_TEST_OSRUNNING != 0)
addis r4,0,posRunning_g@h
ori r4,r4,posRunning_g@l
lwzx r3,0,r4
cmpi CR0,0,r3,0
beq ..osnotrdy1
#endif
/* store stack pointer when posInInterrupt_g == 0 */
#if (POSCFG_ISR_INTERRUPTABLE != 0)
addis r5,0,posInInterrupt_g@h
ori r5,r5,posInInterrupt_g@l
lwzx r3,0,r5
cmpi CR0,0,r3,0
bne ..iinoz1
#endif
/* store stackptr: posCurrentTask_g->stackptr = r1 */
addis r4,0,posCurrentTask_g@h
ori r4,r4,posCurrentTask_g@l
lwzx r5,0,r4
stwx r1,0,r5
/* set stack pointer to dedicated ISR stack memory */
#if (DEDICATED_ISR_STACK != 0)
.extern isrstack_g
addis r3,0,isrstack_g@h
ori r3,r3,isrstack_g@l
lwzx r1,0,r3
#endif
..iinoz1:
/* call pico]OS timer interrupt handler */
bl c_pos_intEnter
bl c_pos_timerInterrupt
bl c_pos_intExit /* Note: This funcion call may not return. */
/* get old stack pointer back */
#if (DEDICATED_ISR_STACK != 0)
addis r4,0,posCurrentTask_g@h
ori r4,r4,posCurrentTask_g@l
lwzx r5,0,r4
lwzx r1,0,r5
#endif
..osnotrdy1:
/* pop SPRs and GPRs from stack and return from interrupt */
ISR_EXIT
ENDFUNC(p_asm_timerISR)
/*----------------------------------------------------------------------------
|
| FUNCTION:
|
| void p_asm_extISR(void);
|
| External interrupt service routine, must be called by a direct jump.
| This function handles level and edge triggered external interrupts.
| When an interrupt happens, this function does a call to the C-function
| c_extIntHandler. (Note that a default handler is in arch_c.c)
|
| void c_extIntHandler(unsigned int uic0s, unsigned int uics1s);
|
| Parameters: uic0s and uic1s contain the status bits of the UICs.
|
*--------------------------------------------------------------------------*/
.align 2
p_asm_extISR:
/* open new stack frame, push SPRs and GPRs to the stack */
ISR_ENTER
/* test if pico]OS is ready to accept interrupts */
#if (EXTISR_TEST_OSRUNNING != 0)
addis r4,0,posRunning_g@h
ori r4,r4,posRunning_g@l
lwzx r3,0,r4
cmpi CR0,0,r3,0
beq ..osnotrdy2
#endif
/* store stack pointer when posInInterrupt_g == 0 */
#if (POSCFG_ISR_INTERRUPTABLE != 0)
addis r5,0,posInInterrupt_g@h
ori r5,r5,posInInterrupt_g@l
lwzx r3,0,r5
cmpi CR0,0,r3,0
bne ..iinoz2
#endif
/* store stackptr: posCurrentTask_g->stackptr = r1 */
addis r4,0,posCurrentTask_g@h
ori r4,r4,posCurrentTask_g@l
lwzx r5,0,r4
stwx r1,0,r5
/* set stack pointer to dedicated ISR stack memory */
#if (DEDICATED_ISR_STACK != 0)
addis r3,0,isrstack_g@h
ori r3,r3,isrstack_g@l
lwzx r1,0,r3
#endif
..iinoz2:
/* set old MSR with external interrupts disabled */
mfspr r4,SRR1
rlwinm r4,r4,0,17,15
mtmsr r4
/* enter pico]OS interrupt level */
bl c_pos_intEnter
/* load interrupt trigger type masks to regs r25 (UIC0) and r26 (UIC1) */
mfdcr r25,0xC5 /* UIC0_TR */
mfdcr r26,0xD5 /* UIC1_TR */
/* get signaled interrupts from UIC0 and UIC1: r3 (UIC0) and r4 (UIC1) */
mfdcr r3,0xC6 /* UIC0_MSR */
mfdcr r4,0xD6 /* UIC1_MSR */
/* clear edge-triggered interrupts from UIC1, then from UIC0 */
and r27,r26,r4
mtdcr 0xD0,r27 /* UIC1_SR */
and r28,r25,r3
mtdcr 0xC0,r28 /* UIC0_SR */
/* get masks of level-triggered interrupts: r27 (UIC0) and r28 (UIC1) */
andc r27,r3,r25
andc r28,r4,r26
/* Note: registers r27 and r28 are volatile, that means,
C functions that need this registers by itself will save
the old register content to the stack. */
/* Call external interrupt handler. The parameters
uic0s (=r3) and uic1s (=r4) are passed to the function. */
bl c_extIntHandler
/* clear level-triggered interrupts from UIC1 and UIC0 */
mtdcr 0xD0,r28 /* UIC1_SR */
mtdcr 0xC0,r27 /* UIC0_SR */
/* exit pico]OS interrupt level */
bl c_pos_intExit /* Note: This funcion call may not return. */
/* get old stack pointer back */
#if (DEDICATED_ISR_STACK != 0)
addis r4,0,posCurrentTask_g@h
ori r4,r4,posCurrentTask_g@l
lwzx r5,0,r4
lwzx r1,0,r5
#endif
..intex2:
/* pop SPRs and GPRs from stack and return from interrupt */
ISR_EXIT
..osnotrdy2:
/* clear pending interrupts from UIC1 and UIC0 */
mfdcr r4,0xD6 /* r4 = UIC1_MSR */
mtdcr 0xD0,r4 /* UIC1_SR = r4 */
mfdcr r3,0xC6 /* r3 = UIC0_MSR */
mtdcr 0xC0,r3 /* UIC0_SR = r3 */
b ..intex2
ENDFUNC(p_asm_extISR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -