@@ -170,19 +170,19 @@ enum class ERegMask : Word
170170};
171171
172172// ! Make unprivileged.
173- static inline Word SetUnprivileged (Word REG_CONTROL ) noexcept
173+ __stk_attr_unused static inline Word SetUnprivileged (Word REG_CONTROL ) noexcept
174174{
175175 return (REG_CONTROL | static_cast <Word>(ERegMask::MASK_nPRIV));
176176}
177177
178178// ! Make privileged.
179- static inline Word SetPrivileged (Word REG_CONTROL ) noexcept
179+ __stk_attr_unused static inline Word SetPrivileged (Word REG_CONTROL ) noexcept
180180{
181181 return (REG_CONTROL & ~static_cast <Word>(ERegMask::MASK_nPRIV));
182182}
183183
184184// ! Set Stack Pointer selection to PSP.
185- static inline Word SetSPSelectionToPSP (Word REG_CONTROL ) noexcept
185+ __stk_attr_unused static inline Word SetSPSelectionToPSP (Word REG_CONTROL ) noexcept
186186{
187187 return (REG_CONTROL | static_cast <Word>(ERegMask::MASK_SPSEL ));
188188}
@@ -1529,13 +1529,8 @@ extern "C" void STK_SYSTICK_HANDLER()
15291529 __set_CONTROL(__get_CONTROL() | CONTROL_nPRIV_Msk)
15301530*/
15311531
1532- #ifdef __ICCARM__
1533- #define STK_ASM_BLOCK_PRIVILEGE_MODE_LOAD_ACTIVE_STACK \
1532+ #define STK_ASM_BLOCK_PRIVILEGE_MODE_LOAD_ACTIVE_STACK \
15341533 " MOV r1, %[st_active]\n " /* r1 = Stack* (already in register) */
1535- #else
1536- #define STK_ASM_BLOCK_PRIVILEGE_MODE_LOAD_ACTIVE_STACK \
1537- " LDR r1, %[st_active]\n " /* r1 = Stack* (m_stack_active) */
1538- #endif
15391534
15401535#define STK_ASM_BLOCK_PRIVILEGE_MODE \
15411536 STK_ASM_BLOCK_PRIVILEGE_MODE_LOAD_ACTIVE_STACK \
@@ -1556,6 +1551,22 @@ extern "C" void STK_SYSTICK_HANDLER()
15561551
15571552extern " C" __stk_attr_naked void STK_PENDSV_HANDLER ()
15581553{
1554+ #if (STK_ARCH_CPU_COUNT > 1U)
1555+ // Optimize register utilization and prevent compiler from using r4-r11
1556+ // registers before they are saved. Use r12 IPC scratch register for that
1557+ // and calculate offset for p_ctx only once. Instruct assembler to use
1558+ // r3, r2 for holding pointers to Idle and Active stacks.
1559+ #ifdef __ICCARM__
1560+ register Context *p_ctx = &GetContext ();
1561+ register Stack *p_st_idle = p_ctx->m_stack_idle ;
1562+ register Stack *p_st_active = p_ctx->m_stack_active ;
1563+ #else
1564+ register Context *p_ctx __asm (" r12" ) = &GetContext ();
1565+ register Stack *p_st_idle __asm (" r3" ) = p_ctx->m_stack_idle ;
1566+ register Stack *p_st_active __asm (" r2" ) = p_ctx->m_stack_active ;
1567+ #endif
1568+ #endif
1569+
15591570 __asm volatile (
15601571 STK_ASM_SYNTAX_UNIFIED
15611572
@@ -1574,7 +1585,7 @@ extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
15741585 " TST LR, #16 \n " /* test LR for 0xffffffe_, e.g. Thread mode with FP data */
15751586
15761587 " IT EQ \n " /* if result is positive */
1577- " VMOVEQ s0, s0 \n " /* force hardware lazy state preservation */
1588+ " VMOVEQ.F32 s0, s0 \n " /* force hardware lazy state preservation */
15781589
15791590 " IT EQ \n " /* if result is positive */
15801591 " VSTMDBEQ r0!, {s16-s31} \n " /* store 16 SP registers */
@@ -1607,35 +1618,29 @@ extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
16071618 // PSP_NS captures the task's Non-Secure stack mid-execution (may be inside an
16081619 // NS call that was interrupted); CONTROL_NS preserves NS privilege / stack-select.
16091620#if STK_CORTEX_M_TRUSTZONE_FRAME
1610- " MRS r2, PSPLIM \n " /* Secure PSPLIM */
1611- " MRS r3, PSPLIM_NS \n " /* Non-Secure PSPLIM */
1612- " STMDB r0!, {r2, r3} \n " /* push PSPLIM, PSPLIM_NS */
1621+ // push PSPLIM, PSPLIM_NS (equivalent to STMDB r0!, {PSPLIM, PSPLIM_NS})
1622+ " MRS r12, PSPLIM_NS \n "
1623+ " STR r12, [r0, #-4]! \n "
1624+ " MRS r12, PSPLIM \n "
1625+ " STR r12, [r0, #-4]! \n "
16131626
1614- " MRS r2, PSP_NS \n " /* Non-Secure PSP (mid-execution value) */
1615- " MRS r3, CONTROL_NS \n " /* Non-Secure CONTROL (nPRIV, SPSEL) */
1616- " STMDB r0!, {r2, r3} \n " /* push PSP_NS, CONTROL_NS */
1627+ // push PSP_NS, CONTROL_NS (equivalent to STMDB r0!, {PSP_NS, CONTROL_NS})
1628+ " MRS r12, CONTROL_NS \n "
1629+ " STR r12, [r0, #-4]! \n "
1630+ " MRS r12, PSP_NS \n "
1631+ " STR r12, [r0, #-4]! \n "
16171632#endif
16181633
16191634 // Store in GetContext().m_stack_idle.
1620- #ifdef __ICCARM__
16211635 " STR r0, [%[st_idle]] \n " /* store the first member (Stack::SP) from r0 */
1622- #else
1623- " LDR r1, %[st_idle] \n "
1624- " STR r0, [r1] \n " /* store the first member (Stack::SP) from r0 */
1625- #endif
16261636
16271637 // Set privileged/unprivileged mode for the active stack.
16281638#ifdef CONTROL_nPRIV_Msk
16291639 STK_ASM_BLOCK_PRIVILEGE_MODE
16301640#endif
16311641
16321642 // Load stack of the active task from GetContext().m_stack_active (note: keep in sync with OnTaskStart).
1633- #ifdef __ICCARM__
16341643 " LDR r0, [%[st_active]]\n " /* load the first member of Stack (Stack::SP) into r0 */
1635- #else
1636- " LDR r1, %[st_active] \n "
1637- " LDR r0, [r1] \n " /* load the first member of Stack (Stack::SP) into r0 */
1638- #endif
16391644
16401645 // ARMv8-M TrustZone: restore TrustZoneFrame fields in reverse push order.
16411646 // Pop order: PSP_NS + CONTROL_NS first (pushed last), then PSPLIM + PSPLIM_NS.
@@ -1646,13 +1651,15 @@ extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
16461651 // EXC_RETURN in LR (restored by LDMIA below) carries the S-bit that tells
16471652 // the CPU which world to return to on "BX LR" - no explicit branch needed.
16481653#if STK_CORTEX_M_TRUSTZONE_FRAME
1649- " LDMIA r0!, {r2, r3} \n " /* pop PSP_NS, CONTROL_NS */
1650- " MSR PSP_NS, r2 \n " /* restore Non-Secure PSP */
1651- " MSR CONTROL_NS, r3 \n " /* restore Non-Secure CONTROL */
1654+ " LDR r12, [r0], #4 \n " /* PSP_NS */
1655+ " MSR PSP_NS, r12 \n "
1656+ " LDR r12, [r0], #4 \n " /* CONTROL_NS */
1657+ " MSR CONTROL_NS, r12 \n "
16521658
1653- " LDMIA r0!, {r2, r3} \n " /* pop PSPLIM, PSPLIM_NS */
1654- " MSR PSPLIM, r2 \n " /* restore Secure PSPLIM */
1655- " MSR PSPLIM_NS, r3 \n " /* restore Non-Secure PSPLIM */
1659+ " LDR r12, [r0], #4 \n " /* PSPLIM */
1660+ " MSR PSPLIM, r12 \n "
1661+ " LDR r12, [r0], #4 \n " /* PSPLIM_NS */
1662+ " MSR PSPLIM_NS, r12 \n "
16561663#endif
16571664
16581665 // Restore registers of active task's CPU context:
@@ -1685,28 +1692,30 @@ extern "C" __stk_attr_naked void STK_PENDSV_HANDLER()
16851692 STK_ASM_EXIT_FROM_HANDLER " \n "
16861693
16871694 : /* output: none */
1695+ #if (STK_ARCH_CPU_COUNT > 1U)
16881696#ifdef __ICCARM__
1697+ : [st_idle] " r3" (p_st_idle),
1698+ [st_active] " r2" (p_st_active),
1699+ #else
1700+ : [st_idle] " r" (p_st_idle),
1701+ [st_active] " r" (p_st_active),
1702+ #endif
1703+ #else
16891704 : [st_idle] " r" (GetContext ().m_stack_idle ),
16901705 [st_active] " r" (GetContext ().m_stack_active ),
1691- #else
1692- : [st_idle] " m" (GetContext ().m_stack_idle ),
1693- [st_active] " m" (GetContext ().m_stack_active ),
16941706#endif
16951707 [priv_val] " i" (ACCESS_PRIVILEGED )
1696- : " r0" , " r1" /* used as a scratchpad */
1708+ : " r0" , " r1" /* used as a scratchpad */ , " memory "
16971709#if STK_CORTEX_M_TRUSTZONE_FRAME
1698- , " r2" , " r3"
1699- #endif
1700- #if defined(__ICCARM__)
1701- , " memory"
1710+ , " cc" , " r12"
17021711#endif
17031712 );
17041713}
17051714
17061715__stk_attr_naked void OnTaskStart ()
17071716{
17081717 // Note: HW_DisableInterrupts() must be called prior calling this function.
1709-
1718+
17101719 __asm volatile (
17111720 STK_ASM_SYNTAX_UNIFIED
17121721
@@ -1717,12 +1726,7 @@ __stk_attr_naked void OnTaskStart()
17171726
17181727 // Load stack of the active task from GetContext().m_stack_active (Note: keep
17191728 // in sync with OnTaskStart).
1720- #ifdef __ICCARM__
1721- " LDR r0, [%[st_active]]\n " /* IAR: load the first member of Stack (Stack::SP) into r0, %[st_active] is a pointer value register */
1722- #else
1723- " LDR r1, %[st_active] \n " /* GCC: %[st_active] is a memory address pointing to Stack* */
1724- " LDR r0, [r1] \n " /* GCC: load the first member of Stack (Stack::SP) into r0 */
1725- #endif
1729+ " LDR r0, [%[st_active]]\n " /* load the first member of Stack (Stack::SP) into r0, %[st_active] is a pointer value register */
17261730
17271731 // ARMv8-M TrustZone: restore TrustZoneFrame fields in reverse push order (see STK_PENDSV_HANDLER).
17281732 // Pop order: PSP_NS + CONTROL_NS first, then PSPLIM + PSPLIM_NS.
@@ -1772,18 +1776,14 @@ __stk_attr_naked void OnTaskStart()
17721776 STK_ASM_EXIT_FROM_HANDLER " \n "
17731777
17741778 : /* output: none */
1775- #ifdef __ICCARM__
17761779 : [st_active] " r" (GetContext ().m_stack_active ),
1777- #else
1778- : [st_active] " m" (GetContext ().m_stack_active ),
1779- #endif
17801780 [priv_val] " i" (ACCESS_PRIVILEGED )
17811781#if !STK_CORTEX_M_MANAGE_LR
17821782 , [exc_ret] " i" (STK_CORTEX_M_EXC_RETURN_THREAD_PSP )
17831783#endif
17841784 : " r0" , " r1" /* used as a scratchpad */
17851785#if STK_CORTEX_M_TRUSTZONE_FRAME
1786- , " r2" , " r3"
1786+ , " cc " , " r2" , " r3"
17871787#endif
17881788#if defined(__ICCARM__)
17891789 , " memory"
0 commit comments