cfe...@freeRemoveuk.com.invalid wrote:
> Ref code '__pthread_callback'
>
> Ref some 26/32bit code.
> What is happening in both modes?
>
> MSR SPSR_cxsf,R0
Transfers R0 into the saved PSR register (which only exists in privileged
CPU modes - or at least that used to be the case 10 years ago ... is it
still true? :-) Does not work in USR26 or USR32 modes; works the same in
the 26-bit and 32-bit versions of any of the privileged modes.
> LDMIA R14,{R0-R14}^
Load 15 registers from wherever the current mode's R14 points - for banked
registers, the user mode registers will contain the loaded values, rather
than the current mode's version of the register.
> MOVS PC,R14
In 26-bit modes, transfer all 32 bits of R14 into R15 - i.e. bits 2-25 of
the new program counter, and the mode and flag bits in bits 0-1 and 26-31
respectively.
In 32-bit modes, transfers all 32 bits of current mode's R14 into R15 as the
new program counter and copies all 32-bits of the current (privileged)
mode's SPSR into the CPSR. i.e. restores the mode, flags and other stuff in
the PSR.
Your fragment below looks like part of a 32-bit mode callback handler (OK, I
also cheated and looked at the topic and first line of your post ;-) This
is one of the very few places in 32-bit ARM modes that you want MOVS PC,
R14.
What will have happened previously is that some interrupt or other has gone
off and all the current registers (R0-R15 and CPSR) have been dumped into
wherever it is that the contents of |L00008F24.Address| points. It's been
an alarmingly long time since I looked at this, but IIRC there's a SWI you
call to set the location of the register buffer for the OS's callback
handler. Therefore, to return from the interrupt, you need to put
everything back how it was before. Carefully. IIRC, both IRQs and FIQs are
usually disabled whilst this code is executed. The MOVS at the end will
re-clear the I and F bits.
So you load the old CPSR into SPSR (LDR r0,[R14,#&40]; MSR SPSR_all, r0),
re-load the user mode registers (the LDMIA, which does not alter your
current mode's R14 remember, only R14_usr), no-op to avoid contention during
banked register access (MOV R0, R0), load return address from the register
block into R14 (LDR R14, [R14, #&03C] (i.e. where R15 was dumped in the
register block)), and finally jump to that address and restore CPU mode,
flags and PC from the SPSR to the CPSR.
>
> ************
> MOV R0,#1
> STR R0,[R2,#&048]
> LDR R14,|L00008F24.Address|
> LDR R0,[R14,#&040]
> MSR SPSR_cxsf,R0
> LDMIA R14,{R0-R14}^
> MOV R0,R0
> LDR R14,[R14,#&03C]
> MOVS PC,R14
> ************
>
> thanks
--
Stewart Brodie