SPM: Check both MODE and SPSEL to choose the stack during SVC

The exception frame is never placed on PSP when in handler mode.
If SPSEL is 1 (PSP), it is "read as 0", which means that the SVC handler
must also check the MODE bit of the EXC_RETURN to properly know which
stack the exception frame is on.

Previously, the checking of the SPSEL bit was done in assembly in a number
of places. This patch refactors that logic out of assembly, into C code,
since the new logic is more complicated.

Note that the logic works just as well for ARMv7 and below.

This patch is initially created by:
Øyvind Rønningstad <oyvind.ronningstad@nordicsemi.no>

Change-Id: I62dda123d7a410251091c416954d2ac4904568ba
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
diff --git a/secure_fw/spm/cmsis_func/arch.c b/secure_fw/spm/cmsis_func/arch.c
index c615d13..6fe0550 100644
--- a/secure_fw/spm/cmsis_func/arch.c
+++ b/secure_fw/spm/cmsis_func/arch.c
@@ -10,7 +10,7 @@
 #include "tfm/tfm_spm_services.h"
 
 #if defined(__ICCARM__)
-uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t lr, uint32_t *msp);
+uint32_t tfm_core_svc_handler(uint32_t *msp, uint32_t *psp, uint32_t exc_return);
 #pragma required=tfm_core_svc_handler
 #endif
 
@@ -308,26 +308,23 @@
 #if !defined(__ICCARM__)
     ".syntax unified                        \n"
 #endif
-    "MRS     r0, PSP                        \n"
-    "MRS     r2, MSP                        \n"
-    "MOVS    r1, #4                         \n"
-    "MOV     r3, lr                         \n"
-    "TST     r1, r3                         \n"
+    "MRS     r0, MSP                        \n"
+    "MOV     r2, lr                         \n"
+    "MOVS    r3, #8                         \n"
+    "TST     r2, r3                         \n"
     "BNE     from_thread                    \n"
     /*
      * This branch is taken when the code is being invoked from handler mode.
      * This happens when a de-privileged interrupt handler is to be run. Seal
      * the stack before de-privileging.
      */
-    "LDR     r0, =0xFEF5EDA5                \n"
-    "MOVS    r3, r0                         \n"
-    "PUSH    {r0, r3}                       \n"
-    /* Overwrite r0 with MSP */
-    "MOV     r0, r2                         \n"
+    "LDR     r1, =0xFEF5EDA5                \n"
+    "MOVS    r3, r1                         \n"
+    "PUSH    {r1, r3}                       \n"
     "from_thread:                           \n"
-    "MOV     r1, lr                         \n"
+    "MRS     r1, PSP                        \n"
     "BL      tfm_core_svc_handler           \n"
-    "MOVS    r1, #4                         \n"
+    "MOVS    r1, #8                         \n"
     "TST     r1, r0                         \n"
     "BNE     to_thread                      \n"
     /*
@@ -345,18 +342,11 @@
 __attribute__((naked)) void SVC_Handler(void)
 {
     __ASM volatile(
-    "MOVS    r0, #4                \n" /* Check store SP in thread mode to r0 */
-    "MOV     r1, lr                \n"
-    "TST     r0, r1                \n"
-    "BEQ     handler               \n"
-    "MRS     r0, PSP               \n" /* Coming from thread mode */
-    "B       sp_stored             \n"
-    "handler:                      \n"
-    "BX      lr                    \n" /* Coming from handler mode */
-    "sp_stored:                    \n"
-    "MOV     r1, lr                \n"
-    "BL      tfm_core_svc_handler  \n"
-    "BX      r0                    \n"
+    "MRS     r0, MSP                        \n"
+    "MRS     r1, PSP                        \n"
+    "MOV     r2, lr                         \n"
+    "BL      tfm_core_svc_handler           \n"
+    "BX      r0                             \n"
     );
 }
 #endif