diff options
Diffstat (limited to 'lib/unwarminder/get_sp.S')
-rw-r--r-- | lib/unwarminder/get_sp.S | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/lib/unwarminder/get_sp.S b/lib/unwarminder/get_sp.S new file mode 100644 index 0000000000..29356b3ec3 --- /dev/null +++ b/lib/unwarminder/get_sp.S | |||
@@ -0,0 +1,34 @@ | |||
1 | #include "config.h" | ||
2 | /* On native platform we protect ourself by disabling interrupts | ||
3 | * then we check current processor mode. If we are called | ||
4 | * from exception we need to save state and switch to SYS and | ||
5 | * after obtaining SP we restore everything from saved state. | ||
6 | * | ||
7 | * On RaaA we are called in USER mode most probably and | ||
8 | * cpsr mangling is restricted. We simply copy SP value | ||
9 | * in this situation | ||
10 | */ | ||
11 | .section .text | ||
12 | .type __get_sp,%function | ||
13 | .global __get_sp | ||
14 | |||
15 | __get_sp: | ||
16 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
17 | mrs r1, cpsr /* save current state */ | ||
18 | orr r0, r1, #0xc0 | ||
19 | msr cpsr, r0 /* disable IRQ and FIQ */ | ||
20 | and r0, r1, #0x1f /* get current mode */ | ||
21 | cmp r0, #0x1f /* are we in sys mode? */ | ||
22 | beq get_sp | ||
23 | call_from_exception: | ||
24 | mrs r0, spsr /* get saved state */ | ||
25 | and r0, r0, #0x1f /* get mode bits */ | ||
26 | orr r0, r0, #0xc0 /* no FIQ no IRQ */ | ||
27 | msr cpsr, r0 /* change mode */ | ||
28 | get_sp: | ||
29 | #endif | ||
30 | mov r0, sp /* get SP */ | ||
31 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
32 | msr cpsr, r1 /* restore mode */ | ||
33 | #endif | ||
34 | .size __get_sp, . - __get_sp | ||