[PATCH 1/2] Align comments and spaces in libgloss/arm/crt0.S and newlib/libc/sys/arm/crt0.S to ease further code alignment.

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/2] Align comments and spaces in libgloss/arm/crt0.S and newlib/libc/sys/arm/crt0.S to ease further code alignment.

Alexander Fedotov
From: Alexander Fedotov <[hidden email]>

---
 libgloss/arm/crt0.S        | 135 +++++++++++++++++++------------------
 newlib/libc/sys/arm/crt0.S |  18 ++---
 2 files changed, 78 insertions(+), 75 deletions(-)

diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
index c708f63d8..1deb73aa5 100644
--- a/libgloss/arm/crt0.S
+++ b/libgloss/arm/crt0.S
@@ -68,8 +68,10 @@
 #endif
 .endm
 
+/*******************************************************************************
+* Main library startup code.
+*******************************************************************************/
  .align 0
-
  FUNC_START _mainCRTStartup
  FUNC_START _start
 #if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
@@ -90,14 +92,14 @@
 #endif
 #endif
 
-/* Start by setting up a stack */
+/* Start by setting up a stack.  */
 #ifdef ARM_RDP_MONITOR
- /*  Issue Demon SWI to read stack info */
- swi SWI_GetEnv /*  Returns command line in r0 */
- mov sp,r1 /*  and the highest memory address in r1 */
+ /*  Issue Demon SWI to read stack info.  */
+ swi SWI_GetEnv /*  Returns command line in r0.  */
+ mov sp,r1 /*  and the highest memory address in r1.  */
 
- /*  stack limit is at end of data */
- /*  allow slop for stack overflow handling and small frames */
+ /*  Stack limit is at end of data.  */
+ /*  Allow slop for stack overflow handling and small frames.  */
 #ifdef THUMB1_ONLY
  ldr r0, .LC2
  adds r0, #128
@@ -109,19 +111,19 @@
 #endif
 #else
 #ifdef ARM_RDI_MONITOR
- /*  Issue Angel SWI to read stack info */
+ /*  Issue Angel SWI to read stack info.  */
  movs r0, #AngelSWI_Reason_HeapInfo
- adr r1, .LC0 /*  point at ptr to 4 words to receive data */
+ adr r1, .LC0 /*  Point at ptr to 4 words to receive data.  */
 #ifdef THUMB_VXM
  bkpt AngelSWI
 #elif defined(__thumb2__)
- /*  We are in thumb mode for startup on armv7 architectures. */
+ /*  We are in thumb mode for startup on armv7 architectures.  */
  AngelSWIAsm (AngelSWI)
 #else
- /*  We are always in ARM mode for startup on pre armv7 archs. */
+ /*  We are always in ARM mode for startup on pre armv7 archs.  */
  AngelSWIAsm (AngelSWI_ARM)
 #endif
- ldr r0, .LC0 /*  point at values read */
+ ldr r0, .LC0 /*  Point at values read.  */
 
  /* Set __heap_limit.  */
  ldr     r1, [r0, #4]
@@ -148,14 +150,15 @@
       to skip setting sp/sl to 0 here.
     - Considering M-profile processors, We might want to initialize
       sp by the first entry of vector table and return 0 to SYS_HEAPINFO
-      semihosting call, which will be skipped here. */
+      semihosting call, which will be skipped here.  */
  cmp r1, #0
  beq .LC26
  mov sp, r1
 .LC26:
  cmp r2, #0
  beq .LC27
- /*  allow slop for stack overflow handling and small frames */
+
+ /*  Allow slop for stack overflow handling and small frames.  */
 #ifdef THUMB1_ONLY
  adds r2, #128
  adds r2, #128
@@ -163,9 +166,10 @@
 #else
  add sl, r2, #256
 #endif
+
 .LC27:
 #else
- /*  Set up the stack pointer to a fixed value */
+ /*  Set up the stack pointer to a fixed value.  */
  /*  Changes by toralf:
     - Allow linker script to provide stack via __stack symbol - see
       defintion of .Lstack
@@ -175,7 +179,7 @@
       Loosely based on init.s from ARM/Motorola example code.
               Note: Mode switch via CPSR is not allowed once in non-privileged
     mode, so we take care not to enter "User" to set up its sp,
-    and also skip most operations if already in that mode. */
+    and also skip most operations if already in that mode.  */
 
  ldr r3, .Lstack
  cmp r3, #0
@@ -192,42 +196,42 @@
  /* Note: This 'mov' is essential when starting in User, and ensures we
  always get *some* sp value for the initial mode, even if we
  have somehow missed it below (in which case it gets the same
- value as FIQ - not ideal, but better than nothing.) */
+ value as FIQ - not ideal, but better than nothing).  */
  mov sp, r3
 #ifdef PREFER_THUMB
  /* XXX Fill in stack assignments for interrupt modes.  */
 #else
  mrs r2, CPSR
- tst r2, #0x0F /* Test mode bits - in User of all are 0 */
- beq .LC23 /* "eq" means r2 AND #0x0F is 0 */
- msr     CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled */
+ tst r2, #0x0F /* Test mode bits - in User of all are 0.  */
+ beq .LC23 /* "eq" means r2 AND #0x0F is 0.  */
+ msr     CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled.  */
  mov sp, r3
- sub sl, sp, #0x1000 /* This mode also has its own sl (see below) */
+ sub sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
 
  mov r3, sl
- msr     CPSR_c, #0xD7 /* Abort mode, interrupts disabled */
+ msr     CPSR_c, #0xD7 /* Abort mode, interrupts disabled.  */
  mov sp, r3
  sub r3, r3, #0x1000
 
- msr     CPSR_c, #0xDB /* Undefined mode, interrupts disabled */
+ msr     CPSR_c, #0xDB /* Undefined mode, interrupts disabled.  */
  mov sp, r3
  sub r3, r3, #0x1000
 
- msr     CPSR_c, #0xD2 /* IRQ mode, interrupts disabled */
+ msr     CPSR_c, #0xD2 /* IRQ mode, interrupts disabled.  */
  mov sp, r3
  sub r3, r3, #0x2000
 
- msr     CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled */
+ msr     CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled.  */
 
  mov sp, r3
- sub r3, r3, #0x8000 /* Min size 32k */
- bic r3, r3, #0x00FF /* Align with current 64k block */
+ sub r3, r3, #0x8000 /* Min size 32k.  */
+ bic r3, r3, #0x00FF /* Align with current 64k block.  */
  bic r3, r3, #0xFF00
 
  str r3, [r3, #-4] /* Move value into user mode sp without */
- ldmdb r3, {sp}^       /* changing modes, via '^' form of ldm */
+ ldmdb r3, {sp}^       /* changing modes, via '^' form of ldm.  */
  orr r2, r2, #0xC0 /* Back to original mode, presumably SVC, */
- msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1 */
+ msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1.  */
 #endif
 .LC23:
  /* Setup a default stack-limit in-case the code has been
@@ -243,24 +247,24 @@
  subs r2, r3, r2
  mov sl, r2
 #else
- sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl */
+ sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl.  */
 #endif
 #endif
 #endif
  /* Zero the memory in the .bss section.  */
- movs a2, #0 /* Second arg: fill value */
- mov fp, a2 /* Null frame pointer */
- mov r7, a2 /* Null frame pointer for Thumb */
+ movs a2, #0 /* Second arg: fill value.  */
+ mov fp, a2 /* Null frame pointer.  */
+ mov r7, a2 /* Null frame pointer for Thumb.  */
 
- ldr a1, .LC1 /* First arg: start of memory block */
+ ldr a1, .LC1 /* First arg: start of memory block.  */
  ldr a3, .LC2
- subs a3, a3, a1 /* Third arg: length of block */
+ subs a3, a3, a1 /* Third arg: length of block.  */
 
 
 #if __thumb__ && !defined(PREFER_THUMB)
- /* Enter Thumb mode.... */
- add a4, pc, #1 /* Get the address of the Thumb block */
- bx a4 /* Go there and start Thumb decoding  */
+ /* Enter Thumb mode...  */
+ add a4, pc, #1 /* Get the address of the Thumb block.  */
+ bx a4 /* Go there and start Thumb decoding.  */
 
  .code 16
  .global __change_mode
@@ -271,9 +275,8 @@ __change_mode:
  bl FUNCTION (memset)
 #if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
 /* Changes by toralf: Taken from libgloss/m68k/crt0.S
- * initialize target specific stuff. Only execute these
- * functions it they exist.
- */
+   initialize target specific stuff. Only execute these
+   functions it they exist.  */
  ldr r3, .Lhwinit
  cmp r3, #0
  beq .LC24
@@ -285,24 +288,24 @@ __change_mode:
  indirect_call r3
 
 .LC25:
- movs r0, #0 /*  no arguments  */
- movs r1, #0 /*  no argv either */
+ movs r0, #0 /* No arguments.  */
+ movs r1, #0 /* No argv either.  */
 #else
- /* Need to set up standard file handles */
+ /* Need to set up standard file handles.  */
  bl FUNCTION (initialise_monitor_handles)
 
 #ifdef ARM_RDP_MONITOR
- swi SWI_GetEnv /*  sets r0 to point to the command line */
+ swi SWI_GetEnv /* Sets r0 to point to the command line.  */
  movs r1, r0
 #else
  movs r0, #AngelSWI_Reason_GetCmdLine
- ldr r1, .LC30 /*  Space for command line */
+ ldr r1, .LC30 /* Space for command line.  */
  AngelSWIAsm (AngelSWI)
  ldr r1, .LC30
  ldr r1, [r1]
 #endif
- /*  Parse string at r1 */
- movs r0, #0 /*  count of arguments so far */
+ /*  Parse string at r1.  */
+ movs r0, #0 /* Count of arguments so far.  */
  /* Push a NULL argument onto the end of the list.  */
 #ifdef __thumb__
  push {r0}
@@ -310,7 +313,7 @@ __change_mode:
  stmfd sp!, {r0}
 #endif
 .LC10:
-/*  Skip leading blanks */
+/*  Skip leading blanks.  */
 #ifdef __thumb__
  ldrb r3, [r1]
  adds r1, #1
@@ -322,7 +325,7 @@ __change_mode:
  cmp r3, #' '
  beq .LC10
 
-/*  See whether we are scanning a string */
+/* See whether we are scanning a string.  */
  cmp r3, #'"'
 #ifdef __thumb__
  beq .LC20
@@ -333,17 +336,17 @@ __change_mode:
  b .LC22
 
 .LC21:
- movs r2, #' ' /*  terminator type */
- subs r1, r1, #1 /*  adjust back to point at start char */
+ movs r2, #' ' /* Terminator type.  */
+ subs r1, r1, #1 /* Adjust back to point at start char.  */
 .LC22:
 #else
  cmpne r3, #'\''
  moveq r2, r3
- movne r2, #' ' /*  terminator type */
- subne r1, r1, #1 /*  adjust back to point at start char */
+ movne r2, #' ' /* Terminator type.  */
+ subne r1, r1, #1 /* Adjust back to point at start char.  */
 #endif
 
-/*  Stack a pointer to the current argument */
+/*  Stack a pointer to the current argument.  */
 #ifdef __thumb__
  push {r1}
 #else
@@ -359,16 +362,16 @@ __change_mode:
 #endif
  cmp r3, #0
  beq .LC12
- cmp r2, r3 /*  reached terminator? */
+ cmp r2, r3 /* Reached terminator ?  */
  bne .LC11
  movs r2, #0
  subs r3, r1, #1
- strb r2, [r3] /*  terminate the arg string */
+ strb r2, [r3] /* Terminate the arg string.  */
  b .LC10
 
 .LC12:
- mov r1, sp /*  point at stacked arg pointers */
- /* We've now got the stacked args in order reverse the */
+ mov r1, sp /* Point at stacked arg pointers.  */
+ /* We've now got the stacked args in order, reverse them.  */
 #ifdef __thumb__
  movs r2, r0
  lsls r2, #2
@@ -390,10 +393,10 @@ __change_mode:
  bics r4, r5
  mov sp, r4
 #else
- add r2, sp, r0, LSL #2 /* End of args */
- mov r3, sp /* Start of args */
+ add r2, sp, r0, LSL #2 /* End of args.  */
+ mov r3, sp /* Start of args.  */
 .LC13: cmp r2, r3
- ldrhi r4,[r2, #-4] /* Reverse ends of list */
+ ldrhi r4,[r2, #-4] /* Reverse ends of list.  */
  ldrhi r5, [r3]
  strhi r5, [r2, #-4]!
  strhi r4, [r3], #4
@@ -431,7 +434,6 @@ __change_mode:
 
 #if __thumb__ && !defined(PREFER_THUMB)
  /* Come out of Thumb mode.  This code should be redundant.  */
-
  mov a4, pc
  bx a4
 
@@ -447,7 +449,6 @@ change_back:
 
  /* For Thumb, constants must be after the code since only
    positive offsets are supported for PC relative addresses.  */
-
  .align 0
 .LC0:
 #ifdef ARM_RDI_MONITOR
@@ -457,13 +458,13 @@ change_back:
  /* Changes by toralf: Provide alternative "stack" variable whose value
    may be defined externally; .Lstack will be used instead of .LC0 if
    it points to a non-0 value. Also set up references to "hooks" that
-           may be used by the application to provide additional init code. */
-
+           may be used by the application to provide additional init code.  */
 #ifdef __pe__
  .word 0x800000
 #else
  .word 0x80000 /* Top of RAM on the PIE board.  */
 #endif
+
 .Lstack:
  .word __stack
 .Lhwinit:
@@ -476,7 +477,7 @@ change_back:
    runtime (meaning "ignore setting") for the variables, when the user
    does not provide the symbols. (The linker uses a weak symbol if,
    and only if, a normal version of the same symbol isn't provided
-   e.g. by a linker script or another object file.) */
+   e.g. by a linker script or another object file.)  */
 
  .weak __stack
  .weak FUNCTION (hardware_init_hook)
diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
index 8c9f7be38..7a6b40d9a 100644
--- a/newlib/libc/sys/arm/crt0.S
+++ b/newlib/libc/sys/arm/crt0.S
@@ -50,13 +50,13 @@
  .global \name
  .thumb_func
 \name:
-.endm
+.endm
 #else
  .code 32
 .macro FUNC_START name
- .global \name
+ .global \name
 \name:
-.endm
+.endm
 #endif
 
 .macro indirect_call reg
@@ -68,8 +68,10 @@
 #endif
 .endm
 
+/*******************************************************************************
+* Main library startup code.
+*******************************************************************************/
  .align 0
-
  FUNC_START _mainCRTStartup
  FUNC_START _start
 #if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
@@ -399,7 +401,7 @@ __change_mode:
  bl FUNCTION (_init)
  movs r0, r4
  movs r1, r5
-#endif
+#endif
  bl FUNCTION (main)
 
  bl FUNCTION (exit) /* Should not return.  */
@@ -420,7 +422,7 @@ change_back:
 #endif
 
  /* For Thumb, constants must be after the code since only
-   positive offsets are supported for PC relative addresses.  */
+   positive offsets are supported for PC relative addresses.  */
  .align 0
 .LC0:
 #ifdef ARM_RDI_MONITOR
@@ -430,7 +432,7 @@ change_back:
  /* Changes by toralf: Provide alternative "stack" variable whose value
    may be defined externally; .Lstack will be used instead of .LC0 if
    it points to a non-0 value. Also set up references to "hooks" that
-           may be used by the application to provide additional init code.  */
+           may be used by the application to provide additional init code.  */
 #ifdef __pe__
  .word 0x800000
 #else
@@ -449,7 +451,7 @@ change_back:
    runtime (meaning "ignore setting") for the variables, when the user
    does not provide the symbols. (The linker uses a weak symbol if,
    and only if, a normal version of the same symbol isn't provided
-   e.g. by a linker script or another object file).  */
+   e.g. by a linker script or another object file.)  */
 
  .weak __stack
  .weak FUNCTION (hardware_init_hook)
--
2.17.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 2/2] [Arm] Stack Pointer and Stack Limit initialization refactored.

Alexander Fedotov
From: Alexander Fedotov <[hidden email]>

SP initialization changes:
  1. set default value in semihosting case as well
  2. moved existing SP & SL init code for processor modes in separate routine and made it as "hook"
  3. init SP for processor modes in Thumb mode as well

Add new macro FN_RETURN, FN_EH_START and FN_EH_END.
---
 libgloss/arm/arm.h         |  26 ++++
 libgloss/arm/crt0.S        | 277 ++++++++++++++++++++++++++-----------
 newlib/libc/sys/arm/arm.h  |  26 ++++
 newlib/libc/sys/arm/crt0.S | 277 ++++++++++++++++++++++++++-----------
 4 files changed, 440 insertions(+), 166 deletions(-)

diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
index 0489f2d92..04b3a5ac7 100644
--- a/libgloss/arm/arm.h
+++ b/libgloss/arm/arm.h
@@ -61,4 +61,30 @@
 # define HAVE_CALL_INDIRECT
 #endif
 
+/* A and R profiles (and legacy Arm).
+ Current Program Status Register (CPSR)
+ M[4:0] Mode bits. M[4] is always 1 for 32-bit modes.
+ T[5] 1: Thumb, 0: ARM instruction set
+ F[6] 1: disables FIQ
+ I[7] 1: disables IRQ
+ A[8] 1: disables imprecise aborts
+ E[9] 0: Little-endian, 1: Big-endian
+ J[24] 1: Jazelle instruction set
+ */
+#define CPSR_M_USR 0x00 /* User mode */
+#define CPSR_M_FIQ 0x01 /* Fast Interrupt mode */
+#define CPSR_M_IRQ 0x02 /* Interrupt mode */
+#define CPSR_M_SVR 0x03 /* Supervisor mode */
+#define CPSR_M_MON 0x06 /* Monitor mode */
+#define CPSR_M_ABT 0x07 /* Abort mode */
+#define CPSR_M_HYP 0x0A /* Hypervisor mode */
+#define CPSR_M_UND 0x0B /* Undefined mode */
+#define CPSR_M_SYS 0x0F /* System mode */
+#define CPSR_M_32BIT 0x10 /* 32-bit mode */
+#define CPSR_T_BIT 0x20 /* Thumb bit */
+#define CPSR_F_MASK 0x40 /* FIQ bit */
+#define CPSR_I_MASK 0x80 /* IRQ bit */
+
+#define CPSR_M_MASK 0x0F /* Mode mask except M[4] */
+
 #endif /* _LIBGLOSS_ARM_H */
diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
index 1deb73aa5..95aa3b578 100644
--- a/libgloss/arm/crt0.S
+++ b/libgloss/arm/crt0.S
@@ -59,6 +59,21 @@
 .endm
 #endif
 
+/* Annotation for EABI unwinding tables. */
+.macro FN_EH_START
+#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+ .fnstart
+#endif
+.endm
+
+.macro FN_EH_END
+#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+ /* Protect against unhandled exceptions.  */
+ .cantunwind
+ .fnend
+#endif
+.endm
+
 .macro indirect_call reg
 #ifdef HAVE_CALL_INDIRECT
  blx \reg
@@ -68,16 +83,170 @@
 #endif
 .endm
 
+/* For armv4t and newer, toolchains will transparently convert
+   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
+   for anything older than armv4t, but this should handle that
+   corner case in case anyone needs it anyway */
+.macro  FN_RETURN
+#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
+ mov pc, lr
+#else
+ bx lr
+#endif
+.endm
+
+
+
+/******************************************************************************
+* User mode only:           This routine makes default target specific Stack
+*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
+*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
+*   | SYS |               and setups a default Stack Limit in-case the code has
+*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
+*   |     |               System (User) modes.
+*   |     |
+*   +-----+ <- initial SP,
+*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
+*           and SL_usr     currently no support for checking that the heap and
+*                          stack have not collided, or that this default 64k is
+* All modes:               is enough for the program being executed. However,
+*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
+*   |     |    SL_usr      immediately cause an overflow event.
+*   | SYS |
+*   | USR | -=0x10000        We go through all execution modes and set up SP
+*   |     |                for each of them.
+*   +-----+ <- SP_sys,
+*   |     |    SP_usr      Note:
+*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
+*   |     |                  non-privileged mode, so we take care not to enter
+*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
+*   |     |                  operations if already in that mode.
+*   | IRQ | -= 0x2000
+*   |     |                Input parameters:
+* ^ +-----+ <- SP_und       - sp - Initialized SP
+* s |     |                 - r2 - May contain SL value from semihosting
+* t | UND | -= 0x1000              SYS_HEAPINFO call
+* a |     |                Scratch registers:
+* c +-----+ <- SP_und       - r1 - new value of CPSR
+* k |     |                 - r2 - intermediate value (in standalone mode)
+*   | ABT | -= 0x1000       - r3 - new SP value
+* g |     |                 - r4 - save/restore CPSR on entry/exit
+* r +-----+ <- SP_abt,
+* o |     |    SL_fiq        Declared as "weak" so that user can write and use
+* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
+* t |     |
+* h +-----+ <- initial SP,
+*           becomes SP_fiq
+*
+******************************************************************************/
+ .align 0
+ FUNC_START _stack_init
+ .weak FUNCTION (_stack_init)
+ FN_EH_START
+
+ /* M profile doesn't have CPSR register.  */
+#if (__ARM_ARCH_PROFILE != 'M')
+ /* Following code is compatible for both ARM and Thumb ISA */
+ mrs r4, CPSR
+ /* Test mode bits - in User of all are 0 */
+ tst r4, #(CPSR_M_MASK)
+ /* "eq" means r4 AND #0x0F is 0 */
+ beq .Lskip_cpu_modes
+
+ mov r3, sp /* save input SP value */
+
+ /* FIQ mode, interrupts disabled */
+ mov r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+ sub sl, sp, #0x1000 /* FIQ mode has its own SL */
+
+ /* Abort mode, interrupts disabled */
+ mov r3, sl
+ mov r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+ sub r3, r3, #0x1000
+
+ /* Undefined mode, interrupts disabled */
+ mov r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+ sub r3, r3, #0x1000
+
+ /* IRQ mode, interrupts disabled */
+ mov r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+ sub r3, r3, #0x2000
+
+ /* Supervisory mode, interrupts disabled */
+ mov r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+
+ sub r3, r3, #0x8000 /* Min size 32k */
+ bic r3, r3, #0x00FF /* Align with current 64k block */
+ bic r3, r3, #0xFF00
+
+# if __ARM_ARCH >= 4
+ /* System (shares regs with User) mode, interrupts disabled */
+ mov r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+# else
+ /* Keep this for ARMv3, but GCC actually dropped it. */
+ /* Move value into user mode sp without changing modes, */
+ /* via '^' form of ldm */
+ str r3, [r3, #-4]
+ ldmdb r3, {sp}^
+# endif
+
+ /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
+ orr r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r4
+
+.Lskip_cpu_modes:
+#endif
+
+ /* Set SL register */
+#if defined (ARM_RDI_MONITOR) /* semihosting */
+ cmp r2, #0
+ beq .Lsl_forced_zero
+ /* allow slop for stack overflow handling and small frames */
+# ifdef THUMB1_ONLY
+ adds r2, #128
+ adds r2, #128
+ mov sl, r2
+# else
+ add sl, r2, #256
+# endif
+.Lsl_forced_zero:
+
+#else /* standalone */
+ /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
+ #ifdef THUMB1_ONLY
+ movs r2, #64
+ lsls r2, r2, #10
+ subs r2, r3, r2
+ mov sl, r2
+ #else
+ /* Still assumes 256bytes below sl */
+ sub sl, r3, #64 << 10
+ #endif
+#endif
+
+ FN_RETURN
+ FN_EH_END
+
+
 /*******************************************************************************
 * Main library startup code.
 *******************************************************************************/
  .align 0
  FUNC_START _mainCRTStartup
  FUNC_START _start
-#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
- /* Annotation for EABI unwinding tables.  */
- .fnstart
-#endif
+ FN_EH_START
 
  /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards, however __ARM_ARCH_7A
  has been defined since 4.2 onwards, which is when v7-a support was added
@@ -150,36 +319,27 @@
       to skip setting sp/sl to 0 here.
     - Considering M-profile processors, We might want to initialize
       sp by the first entry of vector table and return 0 to SYS_HEAPINFO
-      semihosting call, which will be skipped here.  */
+      semihosting call, which will be skipped here.
+    - Considering R-profile processors there is no automatic SP init by hardware
+      so we need to initialize it by default value. */
+ ldr r3, .Lstack
  cmp r1, #0
  beq .LC26
- mov sp, r1
+ mov r3, r1
 .LC26:
- cmp r2, #0
- beq .LC27
+ mov sp, r3
 
- /*  Allow slop for stack overflow handling and small frames.  */
-#ifdef THUMB1_ONLY
- adds r2, #128
- adds r2, #128
- mov sl, r2
-#else
- add sl, r2, #256
-#endif
+ /* r2 (SL value) will be used in _stack_init */
+ bl FUNCTION (_stack_init)
 
-.LC27:
-#else
- /*  Set up the stack pointer to a fixed value.  */
+
+#else /* standalone */
+ /*  Set up the stack pointer to a fixed value. */
  /*  Changes by toralf:
     - Allow linker script to provide stack via __stack symbol - see
       defintion of .Lstack
     - Provide "hooks" that may be used by the application to add
-      custom init code - see .Lhwinit and .Lswinit
-    - Go through all execution modes and set up stack for each of them.
-      Loosely based on init.s from ARM/Motorola example code.
-              Note: Mode switch via CPSR is not allowed once in non-privileged
-    mode, so we take care not to enter "User" to set up its sp,
-    and also skip most operations if already in that mode.  */
+      custom init code - see .Lhwinit and .Lswinit */
 
  ldr r3, .Lstack
  cmp r3, #0
@@ -198,57 +358,10 @@
  have somehow missed it below (in which case it gets the same
  value as FIQ - not ideal, but better than nothing).  */
  mov sp, r3
-#ifdef PREFER_THUMB
- /* XXX Fill in stack assignments for interrupt modes.  */
-#else
- mrs r2, CPSR
- tst r2, #0x0F /* Test mode bits - in User of all are 0.  */
- beq .LC23 /* "eq" means r2 AND #0x0F is 0.  */
- msr     CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled.  */
- mov sp, r3
- sub sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
-
- mov r3, sl
- msr     CPSR_c, #0xD7 /* Abort mode, interrupts disabled.  */
- mov sp, r3
- sub r3, r3, #0x1000
-
- msr     CPSR_c, #0xDB /* Undefined mode, interrupts disabled.  */
- mov sp, r3
- sub r3, r3, #0x1000
 
- msr     CPSR_c, #0xD2 /* IRQ mode, interrupts disabled.  */
- mov sp, r3
- sub r3, r3, #0x2000
-
- msr     CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled.  */
+ /* we don't care of r2 value in standalone */
+ bl FUNCTION (_stack_init)
 
- mov sp, r3
- sub r3, r3, #0x8000 /* Min size 32k.  */
- bic r3, r3, #0x00FF /* Align with current 64k block.  */
- bic r3, r3, #0xFF00
-
- str r3, [r3, #-4] /* Move value into user mode sp without */
- ldmdb r3, {sp}^       /* changing modes, via '^' form of ldm.  */
- orr r2, r2, #0xC0 /* Back to original mode, presumably SVC, */
- msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1.  */
-#endif
-.LC23:
- /* Setup a default stack-limit in-case the code has been
-   compiled with "-mapcs-stack-check".  Hard-wiring this value
-   is not ideal, since there is currently no support for
-   checking that the heap and stack have not collided, or that
-   this default 64k is enough for the program being executed.
-   However, it ensures that this simple crt0 world will not
-   immediately cause an overflow event:  */
-#ifdef THUMB1_ONLY
- movs r2, #64
- lsls r2, r2, #10
- subs r2, r3, r2
- mov sl, r2
-#else
- sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl.  */
-#endif
 #endif
 #endif
  /* Zero the memory in the .bss section.  */
@@ -447,6 +560,8 @@ change_back:
  swi SWI_Exit
 #endif
 
+ FN_EH_END
+
  /* For Thumb, constants must be after the code since only
    positive offsets are supported for PC relative addresses.  */
  .align 0
@@ -464,9 +579,6 @@ change_back:
 #else
  .word 0x80000 /* Top of RAM on the PIE board.  */
 #endif
-
-.Lstack:
- .word __stack
 .Lhwinit:
  .word FUNCTION (hardware_init_hook)
 .Lswinit:
@@ -479,17 +591,16 @@ change_back:
    and only if, a normal version of the same symbol isn't provided
    e.g. by a linker script or another object file.)  */
 
- .weak __stack
  .weak FUNCTION (hardware_init_hook)
  .weak FUNCTION (software_init_hook)
 #endif
 
 #endif
-#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
- /* Protect against unhandled exceptions.  */
- .cantunwind
- .fnend
-#endif
+
+.Lstack:
+ .word __stack
+ .weak __stack
+
 .LC1:
  .word __bss_start__
 .LC2:
diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
index 0489f2d92..04b3a5ac7 100644
--- a/newlib/libc/sys/arm/arm.h
+++ b/newlib/libc/sys/arm/arm.h
@@ -61,4 +61,30 @@
 # define HAVE_CALL_INDIRECT
 #endif
 
+/* A and R profiles (and legacy Arm).
+ Current Program Status Register (CPSR)
+ M[4:0] Mode bits. M[4] is always 1 for 32-bit modes.
+ T[5] 1: Thumb, 0: ARM instruction set
+ F[6] 1: disables FIQ
+ I[7] 1: disables IRQ
+ A[8] 1: disables imprecise aborts
+ E[9] 0: Little-endian, 1: Big-endian
+ J[24] 1: Jazelle instruction set
+ */
+#define CPSR_M_USR 0x00 /* User mode */
+#define CPSR_M_FIQ 0x01 /* Fast Interrupt mode */
+#define CPSR_M_IRQ 0x02 /* Interrupt mode */
+#define CPSR_M_SVR 0x03 /* Supervisor mode */
+#define CPSR_M_MON 0x06 /* Monitor mode */
+#define CPSR_M_ABT 0x07 /* Abort mode */
+#define CPSR_M_HYP 0x0A /* Hypervisor mode */
+#define CPSR_M_UND 0x0B /* Undefined mode */
+#define CPSR_M_SYS 0x0F /* System mode */
+#define CPSR_M_32BIT 0x10 /* 32-bit mode */
+#define CPSR_T_BIT 0x20 /* Thumb bit */
+#define CPSR_F_MASK 0x40 /* FIQ bit */
+#define CPSR_I_MASK 0x80 /* IRQ bit */
+
+#define CPSR_M_MASK 0x0F /* Mode mask except M[4] */
+
 #endif /* _LIBGLOSS_ARM_H */
diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
index 7a6b40d9a..0929a435e 100644
--- a/newlib/libc/sys/arm/crt0.S
+++ b/newlib/libc/sys/arm/crt0.S
@@ -59,6 +59,21 @@
 .endm
 #endif
 
+/* Annotation for EABI unwinding tables. */
+.macro FN_EH_START
+#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+ .fnstart
+#endif
+.endm
+
+.macro FN_EH_END
+#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
+ /* Protect against unhandled exceptions.  */
+ .cantunwind
+ .fnend
+#endif
+.endm
+
 .macro indirect_call reg
 #ifdef HAVE_CALL_INDIRECT
  blx \reg
@@ -68,16 +83,170 @@
 #endif
 .endm
 
+/* For armv4t and newer, toolchains will transparently convert
+   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
+   for anything older than armv4t, but this should handle that
+   corner case in case anyone needs it anyway */
+.macro  FN_RETURN
+#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
+ mov pc, lr
+#else
+ bx lr
+#endif
+.endm
+
+
+
+/******************************************************************************
+* User mode only:           This routine makes default target specific Stack
+*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
+*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
+*   | SYS |               and setups a default Stack Limit in-case the code has
+*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
+*   |     |               System (User) modes.
+*   |     |
+*   +-----+ <- initial SP,
+*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
+*           and SL_usr     currently no support for checking that the heap and
+*                          stack have not collided, or that this default 64k is
+* All modes:               is enough for the program being executed. However,
+*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
+*   |     |    SL_usr      immediately cause an overflow event.
+*   | SYS |
+*   | USR | -=0x10000        We go through all execution modes and set up SP
+*   |     |                for each of them.
+*   +-----+ <- SP_sys,
+*   |     |    SP_usr      Note:
+*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
+*   |     |                  non-privileged mode, so we take care not to enter
+*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
+*   |     |                  operations if already in that mode.
+*   | IRQ | -= 0x2000
+*   |     |                Input parameters:
+* ^ +-----+ <- SP_und       - sp - Initialized SP
+* s |     |                 - r2 - May contain SL value from semihosting
+* t | UND | -= 0x1000              SYS_HEAPINFO call
+* a |     |                Scratch registers:
+* c +-----+ <- SP_und       - r1 - new value of CPSR
+* k |     |                 - r2 - intermediate value (in standalone mode)
+*   | ABT | -= 0x1000       - r3 - new SP value
+* g |     |                 - r4 - save/restore CPSR on entry/exit
+* r +-----+ <- SP_abt,
+* o |     |    SL_fiq        Declared as "weak" so that user can write and use
+* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
+* t |     |
+* h +-----+ <- initial SP,
+*           becomes SP_fiq
+*
+******************************************************************************/
+ .align 0
+ FUNC_START _stack_init
+ .weak FUNCTION (_stack_init)
+ FN_EH_START
+
+ /* M profile doesn't have CPSR register.  */
+#if (__ARM_ARCH_PROFILE != 'M')
+ /* Following code is compatible for both ARM and Thumb ISA */
+ mrs r4, CPSR
+ /* Test mode bits - in User of all are 0 */
+ tst r4, #(CPSR_M_MASK)
+ /* "eq" means r4 AND #0x0F is 0 */
+ beq .Lskip_cpu_modes
+
+ mov r3, sp /* save input SP value */
+
+ /* FIQ mode, interrupts disabled */
+ mov r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+ sub sl, sp, #0x1000 /* FIQ mode has its own SL */
+
+ /* Abort mode, interrupts disabled */
+ mov r3, sl
+ mov r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+ sub r3, r3, #0x1000
+
+ /* Undefined mode, interrupts disabled */
+ mov r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+ sub r3, r3, #0x1000
+
+ /* IRQ mode, interrupts disabled */
+ mov r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+ sub r3, r3, #0x2000
+
+ /* Supervisory mode, interrupts disabled */
+ mov r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+
+ sub r3, r3, #0x8000 /* Min size 32k */
+ bic r3, r3, #0x00FF /* Align with current 64k block */
+ bic r3, r3, #0xFF00
+
+# if __ARM_ARCH >= 4
+ /* System (shares regs with User) mode, interrupts disabled */
+ mov r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r1
+ mov sp, r3
+# else
+ /* Keep this for ARMv3, but GCC actually dropped it. */
+ /* Move value into user mode sp without changing modes, */
+ /* via '^' form of ldm */
+ str r3, [r3, #-4]
+ ldmdb r3, {sp}^
+# endif
+
+ /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
+ orr r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
+ msr CPSR_c, r4
+
+.Lskip_cpu_modes:
+#endif
+
+ /* Set SL register */
+#if defined (ARM_RDI_MONITOR) /* semihosting */
+ cmp r2, #0
+ beq .Lsl_forced_zero
+ /* allow slop for stack overflow handling and small frames */
+# ifdef THUMB1_ONLY
+ adds r2, #128
+ adds r2, #128
+ mov sl, r2
+# else
+ add sl, r2, #256
+# endif
+.Lsl_forced_zero:
+
+#else /* standalone */
+ /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
+ #ifdef THUMB1_ONLY
+ movs r2, #64
+ lsls r2, r2, #10
+ subs r2, r3, r2
+ mov sl, r2
+ #else
+ /* Still assumes 256bytes below sl */
+ sub sl, r3, #64 << 10
+ #endif
+#endif
+
+ FN_RETURN
+ FN_EH_END
+
+
 /*******************************************************************************
 * Main library startup code.
 *******************************************************************************/
  .align 0
  FUNC_START _mainCRTStartup
  FUNC_START _start
-#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
- /* Annotation for EABI unwinding tables.  */
- .fnstart
-#endif
+ FN_EH_START
 
 /* Start by setting up a stack.  */
 #ifdef ARM_RDP_MONITOR
@@ -130,36 +299,27 @@
       to skip setting sp/sl to 0 here.
     - Considering M-profile processors, We might want to initialize
       sp by the first entry of vector table and return 0 to SYS_HEAPINFO
-      semihosting call, which will be skipped here.  */
+      semihosting call, which will be skipped here.
+    - Considering R-profile processors there is no automatic SP init by hardware
+      so we need to initialize it by default value. */
+ ldr r3, .Lstack
  cmp r1, #0
  beq .LC26
- mov sp, r1
+ mov r3, r1
 .LC26:
- cmp r2, #0
- beq .LC27
+ mov sp, r3
 
- /*  Allow slop for stack overflow handling and small frames.  */
-#ifdef THUMB1_ONLY
- adds r2, #128
- adds r2, #128
- mov sl, r2
-#else
- add sl, r2, #256
-#endif
+ /* r2 (SL value) will be used in _stack_init */
+ bl FUNCTION (_stack_init)
 
-.LC27:
-#else
- /*  Set up the stack pointer to a fixed value.  */
+
+#else /* standalone */
+ /*  Set up the stack pointer to a fixed value. */
  /*  Changes by toralf:
     - Allow linker script to provide stack via __stack symbol - see
       defintion of .Lstack
     - Provide "hooks" that may be used by the application to add
-      custom init code - see .Lhwinit and .Lswinit
-    - Go through all execution modes and set up stack for each of them.
-      Loosely based on init.s from ARM/Motorola example code.
-              Note: Mode switch via CPSR is not allowed once in non-privileged
-    mode, so we take care not to enter "User" to set up its sp,
-    and also skip most operations if already in that mode.  */
+      custom init code - see .Lhwinit and .Lswinit */
 
  ldr r3, .Lstack
  cmp r3, #0
@@ -178,57 +338,10 @@
  have somehow missed it below (in which case it gets the same
  value as FIQ - not ideal, but better than nothing).  */
  mov sp, r3
-#ifdef PREFER_THUMB
- /* XXX Fill in stack assignments for interrupt modes.  */
-#else
- mrs r2, CPSR
- tst r2, #0x0F /* Test mode bits - in User of all are 0.  */
- beq .LC23 /* "eq" means r2 AND #0x0F is 0.  */
- msr     CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled.  */
- mov sp, r3
- sub sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
-
- mov r3, sl
- msr     CPSR_c, #0xD7 /* Abort mode, interrupts disabled.  */
- mov sp, r3
- sub r3, r3, #0x1000
-
- msr     CPSR_c, #0xDB /* Undefined mode, interrupts disabled.  */
- mov sp, r3
- sub r3, r3, #0x1000
 
- msr     CPSR_c, #0xD2 /* IRQ mode, interrupts disabled.  */
- mov sp, r3
- sub r3, r3, #0x2000
-
- msr     CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled.  */
+ /* we don't care of r2 value in standalone */
+ bl FUNCTION (_stack_init)
 
- mov sp, r3
- sub r3, r3, #0x8000 /* Min size 32k.  */
- bic r3, r3, #0x00FF /* Align with current 64k block.  */
- bic r3, r3, #0xFF00
-
- str r3, [r3, #-4] /* Move value into user mode sp without */
- ldmdb r3, {sp}^       /* changing modes, via '^' form of ldm.  */
- orr r2, r2, #0xC0 /* Back to original mode, presumably SVC, */
- msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1.  */
-#endif
-.LC23:
- /* Setup a default stack-limit in-case the code has been
-   compiled with "-mapcs-stack-check".  Hard-wiring this value
-   is not ideal, since there is currently no support for
-   checking that the heap and stack have not collided, or that
-   this default 64k is enough for the program being executed.
-   However, it ensures that this simple crt0 world will not
-   immediately cause an overflow event:  */
-#ifdef THUMB1_ONLY
- movs r2, #64
- lsls r2, r2, #10
- subs r2, r3, r2
- mov sl, r2
-#else
- sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl.  */
-#endif
 #endif
 #endif
  /* Zero the memory in the .bss section.  */
@@ -421,6 +534,8 @@ change_back:
  swi SWI_Exit
 #endif
 
+ FN_EH_END
+
  /* For Thumb, constants must be after the code since only
    positive offsets are supported for PC relative addresses.  */
  .align 0
@@ -438,9 +553,6 @@ change_back:
 #else
  .word 0x80000 /* Top of RAM on the PIE board.  */
 #endif
-
-.Lstack:
- .word __stack
 .Lhwinit:
  .word FUNCTION (hardware_init_hook)
 .Lswinit:
@@ -453,17 +565,16 @@ change_back:
    and only if, a normal version of the same symbol isn't provided
    e.g. by a linker script or another object file.)  */
 
- .weak __stack
  .weak FUNCTION (hardware_init_hook)
  .weak FUNCTION (software_init_hook)
 #endif
 
 #endif
-#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
- /* Protect against unhandled exceptions.  */
- .cantunwind
- .fnend
-#endif
+
+.Lstack:
+ .word __stack
+ .weak __stack
+
 .LC1:
  .word __bss_start__
 .LC2:
--
2.17.1

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] [Arm] Stack Pointer and Stack Limit initialization refactored.

Alexander Fedotov
Ping

On Fri, 12 Apr 2019 at 16:31, <[hidden email]> wrote:

> From: Alexander Fedotov <[hidden email]>
>
> SP initialization changes:
>   1. set default value in semihosting case as well
>   2. moved existing SP & SL init code for processor modes in separate
> routine and made it as "hook"
>   3. init SP for processor modes in Thumb mode as well
>
> Add new macro FN_RETURN, FN_EH_START and FN_EH_END.
> ---
>  libgloss/arm/arm.h         |  26 ++++
>  libgloss/arm/crt0.S        | 277 ++++++++++++++++++++++++++-----------
>  newlib/libc/sys/arm/arm.h  |  26 ++++
>  newlib/libc/sys/arm/crt0.S | 277 ++++++++++++++++++++++++++-----------
>  4 files changed, 440 insertions(+), 166 deletions(-)
>
> diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
> index 0489f2d92..04b3a5ac7 100644
> --- a/libgloss/arm/arm.h
> +++ b/libgloss/arm/arm.h
> @@ -61,4 +61,30 @@
>  # define HAVE_CALL_INDIRECT
>  #endif
>
> +/* A and R profiles (and legacy Arm).
> +       Current Program Status Register (CPSR)
> +       M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
> +       T[5]                    1: Thumb, 0: ARM instruction set
> +       F[6]                    1: disables FIQ
> +       I[7]                    1: disables IRQ
> +       A[8]                    1: disables imprecise aborts
> +       E[9]                    0: Little-endian, 1: Big-endian
> +       J[24]                   1: Jazelle instruction set
> + */
> +#define CPSR_M_USR                     0x00    /* User mode */
> +#define CPSR_M_FIQ                     0x01    /* Fast Interrupt mode */
> +#define CPSR_M_IRQ                     0x02    /* Interrupt mode */
> +#define CPSR_M_SVR                     0x03    /* Supervisor mode */
> +#define CPSR_M_MON                     0x06    /* Monitor mode */
> +#define CPSR_M_ABT                     0x07    /* Abort mode */
> +#define CPSR_M_HYP                     0x0A    /* Hypervisor mode */
> +#define CPSR_M_UND                     0x0B    /* Undefined mode */
> +#define CPSR_M_SYS                     0x0F    /* System mode */
> +#define CPSR_M_32BIT           0x10    /* 32-bit mode */
> +#define CPSR_T_BIT                     0x20    /* Thumb bit */
> +#define CPSR_F_MASK                    0x40    /* FIQ bit */
> +#define CPSR_I_MASK                    0x80    /* IRQ bit */
> +
> +#define CPSR_M_MASK                    0x0F    /* Mode mask except M[4] */
> +
>  #endif /* _LIBGLOSS_ARM_H */
> diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
> index 1deb73aa5..95aa3b578 100644
> --- a/libgloss/arm/crt0.S
> +++ b/libgloss/arm/crt0.S
> @@ -59,6 +59,21 @@
>  .endm
>  #endif
>
> +/* Annotation for EABI unwinding tables. */
> +.macro FN_EH_START
> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> +       .fnstart
> +#endif
> +.endm
> +
> +.macro FN_EH_END
> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> +       /* Protect against unhandled exceptions.  */
> +       .cantunwind
> +       .fnend
> +#endif
> +.endm
> +
>  .macro indirect_call reg
>  #ifdef HAVE_CALL_INDIRECT
>         blx \reg
> @@ -68,16 +83,170 @@
>  #endif
>  .endm
>
> +/* For armv4t and newer, toolchains will transparently convert
> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> +   for anything older than armv4t, but this should handle that
> +   corner case in case anyone needs it anyway */
> +.macro  FN_RETURN
> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> +       mov     pc, lr
> +#else
> +       bx      lr
> +#endif
> +.endm
> +
> +
> +
>
> +/******************************************************************************
> +* User mode only:           This routine makes default target specific
> Stack
> +*   +-----+ <- SL_sys,    Pointer initialization for different processor
> modes:
> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System
> (User)
> +*   | SYS |               and setups a default Stack Limit in-case the
> code has
> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ
> and
> +*   |     |               System (User) modes.
> +*   |     |
> +*   +-----+ <- initial SP,
> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since
> there is
> +*           and SL_usr     currently no support for checking that the
> heap and
> +*                          stack have not collided, or that this default
> 64k is
> +* All modes:               is enough for the program being executed.
> However,
> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
> +*   |     |    SL_usr      immediately cause an overflow event.
> +*   | SYS |
> +*   | USR | -=0x10000        We go through all execution modes and set up
> SP
> +*   |     |                for each of them.
> +*   +-----+ <- SP_sys,
> +*   |     |    SP_usr      Note:
> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
> +*   |     |                  non-privileged mode, so we take care not to
> enter
> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
> +*   |     |                  operations if already in that mode.
> +*   | IRQ | -= 0x2000
> +*   |     |                Input parameters:
> +* ^ +-----+ <- SP_und       - sp - Initialized SP
> +* s |     |                 - r2 - May contain SL value from semihosting
> +* t | UND | -= 0x1000              SYS_HEAPINFO call
> +* a |     |                Scratch registers:
> +* c +-----+ <- SP_und       - r1 - new value of CPSR
> +* k |     |                 - r2 - intermediate value (in standalone mode)
> +*   | ABT | -= 0x1000       - r3 - new SP value
> +* g |     |                 - r4 - save/restore CPSR on entry/exit
> +* r +-----+ <- SP_abt,
> +* o |     |    SL_fiq        Declared as "weak" so that user can write
> and use
> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
> +* t |     |
> +* h +-----+ <- initial SP,
> +*           becomes SP_fiq
> +*
>
> +******************************************************************************/
> +       .align  0
> +       FUNC_START      _stack_init
> +       .weak FUNCTION (_stack_init)
> +       FN_EH_START
> +
> +       /* M profile doesn't have CPSR register.  */
> +#if (__ARM_ARCH_PROFILE != 'M')
> +       /* Following code is compatible for both ARM and Thumb ISA */
> +       mrs     r4, CPSR
> +       /* Test mode bits - in User of all are 0 */
> +       tst     r4, #(CPSR_M_MASK)
> +       /* "eq" means r4 AND #0x0F is 0 */
> +       beq     .Lskip_cpu_modes
> +
> +       mov     r3, sp /* save input SP value */
> +
> +       /* FIQ mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +       sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
> +
> +       /* Abort mode, interrupts disabled */
> +       mov     r3, sl
> +       mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +       sub     r3, r3, #0x1000
> +
> +       /* Undefined mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +       sub     r3, r3, #0x1000
> +
> +       /* IRQ mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +       sub     r3, r3, #0x2000
> +
> +       /* Supervisory mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +
> +       sub     r3, r3, #0x8000 /* Min size 32k */
> +       bic     r3, r3, #0x00FF /* Align with current 64k block */
> +       bic     r3, r3, #0xFF00
> +
> +# if __ARM_ARCH >= 4
> +       /* System (shares regs with User) mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +# else
> +       /* Keep this for ARMv3, but GCC actually dropped it. */
> +       /* Move value into user mode sp without changing modes, */
> +       /* via '^' form of ldm */
> +       str     r3, [r3, #-4]
> +       ldmdb   r3, {sp}^
> +# endif
> +
> +       /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
> +       orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r4
> +
> +.Lskip_cpu_modes:
> +#endif
> +
> +       /* Set SL register */
> +#if defined (ARM_RDI_MONITOR) /* semihosting */
> +       cmp     r2, #0
> +       beq     .Lsl_forced_zero
> +       /* allow slop for stack overflow handling and small frames */
> +# ifdef THUMB1_ONLY
> +       adds    r2, #128
> +       adds    r2, #128
> +       mov     sl, r2
> +# else
> +       add     sl, r2, #256
> +# endif
> +.Lsl_forced_zero:
> +
> +#else /* standalone */
> +       /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
> +       #ifdef THUMB1_ONLY
> +       movs    r2, #64
> +       lsls    r2, r2, #10
> +       subs    r2, r3, r2
> +       mov     sl, r2
> +       #else
> +       /* Still assumes 256bytes below sl */
> +       sub     sl, r3, #64 << 10
> +       #endif
> +#endif
> +
> +       FN_RETURN
> +       FN_EH_END
> +
> +
>
>  /*******************************************************************************
>  * Main library startup code.
>
>  *******************************************************************************/
>         .align  0
>         FUNC_START      _mainCRTStartup
>         FUNC_START      _start
> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> -       /* Annotation for EABI unwinding tables.  */
> -       .fnstart
> -#endif
> +       FN_EH_START
>
>         /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards, however
> __ARM_ARCH_7A
>         has been defined since 4.2 onwards, which is when v7-a support was
> added
> @@ -150,36 +319,27 @@
>               to skip setting sp/sl to 0 here.
>             - Considering M-profile processors, We might want to initialize
>               sp by the first entry of vector table and return 0 to
> SYS_HEAPINFO
> -             semihosting call, which will be skipped here.  */
> +             semihosting call, which will be skipped here.
> +           - Considering R-profile processors there is no automatic SP
> init by hardware
> +             so we need to initialize it by default value. */
> +       ldr     r3, .Lstack
>         cmp     r1, #0
>         beq     .LC26
> -       mov     sp, r1
> +       mov     r3, r1
>  .LC26:
> -       cmp     r2, #0
> -       beq     .LC27
> +       mov     sp, r3
>
> -       /*  Allow slop for stack overflow handling and small frames.  */
> -#ifdef THUMB1_ONLY
> -       adds    r2, #128
> -       adds    r2, #128
> -       mov     sl, r2
> -#else
> -       add     sl, r2, #256
> -#endif
> +       /* r2 (SL value) will be used in _stack_init */
> +       bl FUNCTION (_stack_init)
>
> -.LC27:
> -#else
> -       /*  Set up the stack pointer to a fixed value.  */
> +
> +#else /* standalone */
> +       /*  Set up the stack pointer to a fixed value. */
>         /*  Changes by toralf:
>             - Allow linker script to provide stack via __stack symbol - see
>               defintion of .Lstack
>             - Provide "hooks" that may be used by the application to add
> -             custom init code - see .Lhwinit and .Lswinit
> -           - Go through all execution modes and set up stack for each of
> them.
> -             Loosely based on init.s from ARM/Motorola example code.
> -              Note: Mode switch via CPSR is not allowed once in
> non-privileged
> -                   mode, so we take care not to enter "User" to set up
> its sp,
> -                   and also skip most operations if already in that
> mode.  */
> +             custom init code - see .Lhwinit and .Lswinit */
>
>         ldr     r3, .Lstack
>         cmp     r3, #0
> @@ -198,57 +358,10 @@
>                  have somehow missed it below (in which case it gets the
> same
>                  value as FIQ - not ideal, but better than nothing).  */
>         mov     sp, r3
> -#ifdef PREFER_THUMB
> -       /* XXX Fill in stack assignments for interrupt modes.  */
> -#else
> -       mrs     r2, CPSR
> -       tst     r2, #0x0F       /* Test mode bits - in User of all are 0.
> */
> -       beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> -       msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> -       mov     sp, r3
> -       sub     sl, sp, #0x1000 /* This mode also has its own sl (see
> below).  */
> -
> -       mov     r3, sl
> -       msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
> -       mov     sp, r3
> -       sub     r3, r3, #0x1000
> -
> -       msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
> -       mov     sp, r3
> -       sub     r3, r3, #0x1000
>
> -       msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> -       mov     sp, r3
> -       sub     r3, r3, #0x2000
> -
> -       msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.
> */
> +       /* we don't care of r2 value in standalone */
> +       bl FUNCTION (_stack_init)
>
> -       mov     sp, r3
> -       sub     r3, r3, #0x8000 /* Min size 32k.  */
> -       bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> -       bic     r3, r3, #0xFF00
> -
> -       str     r3, [r3, #-4]   /* Move value into user mode sp without */
> -       ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.
> */
> -       orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC,
> */
> -       msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.
> */
> -#endif
> -.LC23:
> -       /* Setup a default stack-limit in-case the code has been
> -          compiled with "-mapcs-stack-check".  Hard-wiring this value
> -          is not ideal, since there is currently no support for
> -          checking that the heap and stack have not collided, or that
> -          this default 64k is enough for the program being executed.
> -          However, it ensures that this simple crt0 world will not
> -          immediately cause an overflow event:  */
> -#ifdef THUMB1_ONLY
> -       movs    r2, #64
> -       lsls    r2, r2, #10
> -       subs    r2, r3, r2
> -       mov     sl, r2
> -#else
> -       sub     sl, r3, #64 << 10       /* Still assumes 256bytes below
> sl.  */
> -#endif
>  #endif
>  #endif
>         /* Zero the memory in the .bss section.  */
> @@ -447,6 +560,8 @@ change_back:
>         swi     SWI_Exit
>  #endif
>
> +       FN_EH_END
> +
>         /* For Thumb, constants must be after the code since only
>            positive offsets are supported for PC relative addresses.  */
>         .align 0
> @@ -464,9 +579,6 @@ change_back:
>  #else
>         .word   0x80000                 /* Top of RAM on the PIE board.  */
>  #endif
> -
> -.Lstack:
> -       .word   __stack
>  .Lhwinit:
>         .word   FUNCTION (hardware_init_hook)
>  .Lswinit:
> @@ -479,17 +591,16 @@ change_back:
>            and only if, a normal version of the same symbol isn't provided
>            e.g. by a linker script or another object file.)  */
>
> -       .weak __stack
>         .weak FUNCTION (hardware_init_hook)
>         .weak FUNCTION (software_init_hook)
>  #endif
>
>  #endif
> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> -       /* Protect against unhandled exceptions.  */
> -       .cantunwind
> -       .fnend
> -#endif
> +
> +.Lstack:
> +       .word   __stack
> +       .weak   __stack
> +
>  .LC1:
>         .word   __bss_start__
>  .LC2:
> diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
> index 0489f2d92..04b3a5ac7 100644
> --- a/newlib/libc/sys/arm/arm.h
> +++ b/newlib/libc/sys/arm/arm.h
> @@ -61,4 +61,30 @@
>  # define HAVE_CALL_INDIRECT
>  #endif
>
> +/* A and R profiles (and legacy Arm).
> +       Current Program Status Register (CPSR)
> +       M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
> +       T[5]                    1: Thumb, 0: ARM instruction set
> +       F[6]                    1: disables FIQ
> +       I[7]                    1: disables IRQ
> +       A[8]                    1: disables imprecise aborts
> +       E[9]                    0: Little-endian, 1: Big-endian
> +       J[24]                   1: Jazelle instruction set
> + */
> +#define CPSR_M_USR                     0x00    /* User mode */
> +#define CPSR_M_FIQ                     0x01    /* Fast Interrupt mode */
> +#define CPSR_M_IRQ                     0x02    /* Interrupt mode */
> +#define CPSR_M_SVR                     0x03    /* Supervisor mode */
> +#define CPSR_M_MON                     0x06    /* Monitor mode */
> +#define CPSR_M_ABT                     0x07    /* Abort mode */
> +#define CPSR_M_HYP                     0x0A    /* Hypervisor mode */
> +#define CPSR_M_UND                     0x0B    /* Undefined mode */
> +#define CPSR_M_SYS                     0x0F    /* System mode */
> +#define CPSR_M_32BIT           0x10    /* 32-bit mode */
> +#define CPSR_T_BIT                     0x20    /* Thumb bit */
> +#define CPSR_F_MASK                    0x40    /* FIQ bit */
> +#define CPSR_I_MASK                    0x80    /* IRQ bit */
> +
> +#define CPSR_M_MASK                    0x0F    /* Mode mask except M[4] */
> +
>  #endif /* _LIBGLOSS_ARM_H */
> diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
> index 7a6b40d9a..0929a435e 100644
> --- a/newlib/libc/sys/arm/crt0.S
> +++ b/newlib/libc/sys/arm/crt0.S
> @@ -59,6 +59,21 @@
>  .endm
>  #endif
>
> +/* Annotation for EABI unwinding tables. */
> +.macro FN_EH_START
> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> +       .fnstart
> +#endif
> +.endm
> +
> +.macro FN_EH_END
> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> +       /* Protect against unhandled exceptions.  */
> +       .cantunwind
> +       .fnend
> +#endif
> +.endm
> +
>  .macro indirect_call reg
>  #ifdef HAVE_CALL_INDIRECT
>         blx \reg
> @@ -68,16 +83,170 @@
>  #endif
>  .endm
>
> +/* For armv4t and newer, toolchains will transparently convert
> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> +   for anything older than armv4t, but this should handle that
> +   corner case in case anyone needs it anyway */
> +.macro  FN_RETURN
> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> +       mov     pc, lr
> +#else
> +       bx      lr
> +#endif
> +.endm
> +
> +
> +
>
> +/******************************************************************************
> +* User mode only:           This routine makes default target specific
> Stack
> +*   +-----+ <- SL_sys,    Pointer initialization for different processor
> modes:
> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System
> (User)
> +*   | SYS |               and setups a default Stack Limit in-case the
> code has
> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ
> and
> +*   |     |               System (User) modes.
> +*   |     |
> +*   +-----+ <- initial SP,
> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since
> there is
> +*           and SL_usr     currently no support for checking that the
> heap and
> +*                          stack have not collided, or that this default
> 64k is
> +* All modes:               is enough for the program being executed.
> However,
> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
> +*   |     |    SL_usr      immediately cause an overflow event.
> +*   | SYS |
> +*   | USR | -=0x10000        We go through all execution modes and set up
> SP
> +*   |     |                for each of them.
> +*   +-----+ <- SP_sys,
> +*   |     |    SP_usr      Note:
> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
> +*   |     |                  non-privileged mode, so we take care not to
> enter
> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
> +*   |     |                  operations if already in that mode.
> +*   | IRQ | -= 0x2000
> +*   |     |                Input parameters:
> +* ^ +-----+ <- SP_und       - sp - Initialized SP
> +* s |     |                 - r2 - May contain SL value from semihosting
> +* t | UND | -= 0x1000              SYS_HEAPINFO call
> +* a |     |                Scratch registers:
> +* c +-----+ <- SP_und       - r1 - new value of CPSR
> +* k |     |                 - r2 - intermediate value (in standalone mode)
> +*   | ABT | -= 0x1000       - r3 - new SP value
> +* g |     |                 - r4 - save/restore CPSR on entry/exit
> +* r +-----+ <- SP_abt,
> +* o |     |    SL_fiq        Declared as "weak" so that user can write
> and use
> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
> +* t |     |
> +* h +-----+ <- initial SP,
> +*           becomes SP_fiq
> +*
>
> +******************************************************************************/
> +       .align  0
> +       FUNC_START      _stack_init
> +       .weak FUNCTION (_stack_init)
> +       FN_EH_START
> +
> +       /* M profile doesn't have CPSR register.  */
> +#if (__ARM_ARCH_PROFILE != 'M')
> +       /* Following code is compatible for both ARM and Thumb ISA */
> +       mrs     r4, CPSR
> +       /* Test mode bits - in User of all are 0 */
> +       tst     r4, #(CPSR_M_MASK)
> +       /* "eq" means r4 AND #0x0F is 0 */
> +       beq     .Lskip_cpu_modes
> +
> +       mov     r3, sp /* save input SP value */
> +
> +       /* FIQ mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +       sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
> +
> +       /* Abort mode, interrupts disabled */
> +       mov     r3, sl
> +       mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +       sub     r3, r3, #0x1000
> +
> +       /* Undefined mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +       sub     r3, r3, #0x1000
> +
> +       /* IRQ mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +       sub     r3, r3, #0x2000
> +
> +       /* Supervisory mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +
> +       sub     r3, r3, #0x8000 /* Min size 32k */
> +       bic     r3, r3, #0x00FF /* Align with current 64k block */
> +       bic     r3, r3, #0xFF00
> +
> +# if __ARM_ARCH >= 4
> +       /* System (shares regs with User) mode, interrupts disabled */
> +       mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r1
> +       mov     sp, r3
> +# else
> +       /* Keep this for ARMv3, but GCC actually dropped it. */
> +       /* Move value into user mode sp without changing modes, */
> +       /* via '^' form of ldm */
> +       str     r3, [r3, #-4]
> +       ldmdb   r3, {sp}^
> +# endif
> +
> +       /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
> +       orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> +       msr     CPSR_c, r4
> +
> +.Lskip_cpu_modes:
> +#endif
> +
> +       /* Set SL register */
> +#if defined (ARM_RDI_MONITOR) /* semihosting */
> +       cmp     r2, #0
> +       beq     .Lsl_forced_zero
> +       /* allow slop for stack overflow handling and small frames */
> +# ifdef THUMB1_ONLY
> +       adds    r2, #128
> +       adds    r2, #128
> +       mov     sl, r2
> +# else
> +       add     sl, r2, #256
> +# endif
> +.Lsl_forced_zero:
> +
> +#else /* standalone */
> +       /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
> +       #ifdef THUMB1_ONLY
> +       movs    r2, #64
> +       lsls    r2, r2, #10
> +       subs    r2, r3, r2
> +       mov     sl, r2
> +       #else
> +       /* Still assumes 256bytes below sl */
> +       sub     sl, r3, #64 << 10
> +       #endif
> +#endif
> +
> +       FN_RETURN
> +       FN_EH_END
> +
> +
>
>  /*******************************************************************************
>  * Main library startup code.
>
>  *******************************************************************************/
>         .align  0
>         FUNC_START      _mainCRTStartup
>         FUNC_START      _start
> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> -       /* Annotation for EABI unwinding tables.  */
> -       .fnstart
> -#endif
> +       FN_EH_START
>
>  /* Start by setting up a stack.  */
>  #ifdef ARM_RDP_MONITOR
> @@ -130,36 +299,27 @@
>               to skip setting sp/sl to 0 here.
>             - Considering M-profile processors, We might want to initialize
>               sp by the first entry of vector table and return 0 to
> SYS_HEAPINFO
> -             semihosting call, which will be skipped here.  */
> +             semihosting call, which will be skipped here.
> +           - Considering R-profile processors there is no automatic SP
> init by hardware
> +             so we need to initialize it by default value. */
> +       ldr     r3, .Lstack
>         cmp     r1, #0
>         beq     .LC26
> -       mov     sp, r1
> +       mov     r3, r1
>  .LC26:
> -       cmp     r2, #0
> -       beq     .LC27
> +       mov     sp, r3
>
> -       /*  Allow slop for stack overflow handling and small frames.  */
> -#ifdef THUMB1_ONLY
> -       adds    r2, #128
> -       adds    r2, #128
> -       mov     sl, r2
> -#else
> -       add     sl, r2, #256
> -#endif
> +       /* r2 (SL value) will be used in _stack_init */
> +       bl FUNCTION (_stack_init)
>
> -.LC27:
> -#else
> -       /*  Set up the stack pointer to a fixed value.  */
> +
> +#else /* standalone */
> +       /*  Set up the stack pointer to a fixed value. */
>         /*  Changes by toralf:
>             - Allow linker script to provide stack via __stack symbol - see
>               defintion of .Lstack
>             - Provide "hooks" that may be used by the application to add
> -             custom init code - see .Lhwinit and .Lswinit
> -           - Go through all execution modes and set up stack for each of
> them.
> -             Loosely based on init.s from ARM/Motorola example code.
> -              Note: Mode switch via CPSR is not allowed once in
> non-privileged
> -                   mode, so we take care not to enter "User" to set up
> its sp,
> -                   and also skip most operations if already in that
> mode.  */
> +             custom init code - see .Lhwinit and .Lswinit */
>
>         ldr     r3, .Lstack
>         cmp     r3, #0
> @@ -178,57 +338,10 @@
>                  have somehow missed it below (in which case it gets the
> same
>                  value as FIQ - not ideal, but better than nothing).  */
>         mov     sp, r3
> -#ifdef PREFER_THUMB
> -       /* XXX Fill in stack assignments for interrupt modes.  */
> -#else
> -       mrs     r2, CPSR
> -       tst     r2, #0x0F       /* Test mode bits - in User of all are 0.
> */
> -       beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> -       msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> -       mov     sp, r3
> -       sub     sl, sp, #0x1000 /* This mode also has its own sl (see
> below).  */
> -
> -       mov     r3, sl
> -       msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
> -       mov     sp, r3
> -       sub     r3, r3, #0x1000
> -
> -       msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
> -       mov     sp, r3
> -       sub     r3, r3, #0x1000
>
> -       msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> -       mov     sp, r3
> -       sub     r3, r3, #0x2000
> -
> -       msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.
> */
> +       /* we don't care of r2 value in standalone */
> +       bl FUNCTION (_stack_init)
>
> -       mov     sp, r3
> -       sub     r3, r3, #0x8000 /* Min size 32k.  */
> -       bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> -       bic     r3, r3, #0xFF00
> -
> -       str     r3, [r3, #-4]   /* Move value into user mode sp without */
> -       ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.
> */
> -       orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC,
> */
> -       msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.
> */
> -#endif
> -.LC23:
> -       /* Setup a default stack-limit in-case the code has been
> -          compiled with "-mapcs-stack-check".  Hard-wiring this value
> -          is not ideal, since there is currently no support for
> -          checking that the heap and stack have not collided, or that
> -          this default 64k is enough for the program being executed.
> -          However, it ensures that this simple crt0 world will not
> -          immediately cause an overflow event:  */
> -#ifdef THUMB1_ONLY
> -       movs    r2, #64
> -       lsls    r2, r2, #10
> -       subs    r2, r3, r2
> -       mov     sl, r2
> -#else
> -       sub     sl, r3, #64 << 10       /* Still assumes 256bytes below
> sl.  */
> -#endif
>  #endif
>  #endif
>         /* Zero the memory in the .bss section.  */
> @@ -421,6 +534,8 @@ change_back:
>         swi     SWI_Exit
>  #endif
>
> +       FN_EH_END
> +
>         /* For Thumb, constants must be after the code since only
>            positive offsets are supported for PC relative addresses.  */
>         .align 0
> @@ -438,9 +553,6 @@ change_back:
>  #else
>         .word   0x80000                 /* Top of RAM on the PIE board.  */
>  #endif
> -
> -.Lstack:
> -       .word   __stack
>  .Lhwinit:
>         .word   FUNCTION (hardware_init_hook)
>  .Lswinit:
> @@ -453,17 +565,16 @@ change_back:
>            and only if, a normal version of the same symbol isn't provided
>            e.g. by a linker script or another object file.)  */
>
> -       .weak __stack
>         .weak FUNCTION (hardware_init_hook)
>         .weak FUNCTION (software_init_hook)
>  #endif
>
>  #endif
> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> -       /* Protect against unhandled exceptions.  */
> -       .cantunwind
> -       .fnend
> -#endif
> +
> +.Lstack:
> +       .word   __stack
> +       .weak   __stack
> +
>  .LC1:
>         .word   __bss_start__
>  .LC2:
> --
> 2.17.1
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] [Arm] Stack Pointer and Stack Limit initialization refactored.

Alexander Fedotov
Ping^2

On Wed, Apr 17, 2019 at 12:17 PM Alexander Fedotov <[hidden email]> wrote:

>
> Ping
>
> On Fri, 12 Apr 2019 at 16:31, <[hidden email]> wrote:
>>
>> From: Alexander Fedotov <[hidden email]>
>>
>> SP initialization changes:
>>   1. set default value in semihosting case as well
>>   2. moved existing SP & SL init code for processor modes in separate routine and made it as "hook"
>>   3. init SP for processor modes in Thumb mode as well
>>
>> Add new macro FN_RETURN, FN_EH_START and FN_EH_END.
>> ---
>>  libgloss/arm/arm.h         |  26 ++++
>>  libgloss/arm/crt0.S        | 277 ++++++++++++++++++++++++++-----------
>>  newlib/libc/sys/arm/arm.h  |  26 ++++
>>  newlib/libc/sys/arm/crt0.S | 277 ++++++++++++++++++++++++++-----------
>>  4 files changed, 440 insertions(+), 166 deletions(-)
>>
>> diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
>> index 0489f2d92..04b3a5ac7 100644
>> --- a/libgloss/arm/arm.h
>> +++ b/libgloss/arm/arm.h
>> @@ -61,4 +61,30 @@
>>  # define HAVE_CALL_INDIRECT
>>  #endif
>>
>> +/* A and R profiles (and legacy Arm).
>> +       Current Program Status Register (CPSR)
>> +       M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
>> +       T[5]                    1: Thumb, 0: ARM instruction set
>> +       F[6]                    1: disables FIQ
>> +       I[7]                    1: disables IRQ
>> +       A[8]                    1: disables imprecise aborts
>> +       E[9]                    0: Little-endian, 1: Big-endian
>> +       J[24]                   1: Jazelle instruction set
>> + */
>> +#define CPSR_M_USR                     0x00    /* User mode */
>> +#define CPSR_M_FIQ                     0x01    /* Fast Interrupt mode */
>> +#define CPSR_M_IRQ                     0x02    /* Interrupt mode */
>> +#define CPSR_M_SVR                     0x03    /* Supervisor mode */
>> +#define CPSR_M_MON                     0x06    /* Monitor mode */
>> +#define CPSR_M_ABT                     0x07    /* Abort mode */
>> +#define CPSR_M_HYP                     0x0A    /* Hypervisor mode */
>> +#define CPSR_M_UND                     0x0B    /* Undefined mode */
>> +#define CPSR_M_SYS                     0x0F    /* System mode */
>> +#define CPSR_M_32BIT           0x10    /* 32-bit mode */
>> +#define CPSR_T_BIT                     0x20    /* Thumb bit */
>> +#define CPSR_F_MASK                    0x40    /* FIQ bit */
>> +#define CPSR_I_MASK                    0x80    /* IRQ bit */
>> +
>> +#define CPSR_M_MASK                    0x0F    /* Mode mask except M[4] */
>> +
>>  #endif /* _LIBGLOSS_ARM_H */
>> diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
>> index 1deb73aa5..95aa3b578 100644
>> --- a/libgloss/arm/crt0.S
>> +++ b/libgloss/arm/crt0.S
>> @@ -59,6 +59,21 @@
>>  .endm
>>  #endif
>>
>> +/* Annotation for EABI unwinding tables. */
>> +.macro FN_EH_START
>> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> +       .fnstart
>> +#endif
>> +.endm
>> +
>> +.macro FN_EH_END
>> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> +       /* Protect against unhandled exceptions.  */
>> +       .cantunwind
>> +       .fnend
>> +#endif
>> +.endm
>> +
>>  .macro indirect_call reg
>>  #ifdef HAVE_CALL_INDIRECT
>>         blx \reg
>> @@ -68,16 +83,170 @@
>>  #endif
>>  .endm
>>
>> +/* For armv4t and newer, toolchains will transparently convert
>> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
>> +   for anything older than armv4t, but this should handle that
>> +   corner case in case anyone needs it anyway */
>> +.macro  FN_RETURN
>> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
>> +       mov     pc, lr
>> +#else
>> +       bx      lr
>> +#endif
>> +.endm
>> +
>> +
>> +
>> +/******************************************************************************
>> +* User mode only:           This routine makes default target specific Stack
>> +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
>> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
>> +*   | SYS |               and setups a default Stack Limit in-case the code has
>> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
>> +*   |     |               System (User) modes.
>> +*   |     |
>> +*   +-----+ <- initial SP,
>> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
>> +*           and SL_usr     currently no support for checking that the heap and
>> +*                          stack have not collided, or that this default 64k is
>> +* All modes:               is enough for the program being executed. However,
>> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
>> +*   |     |    SL_usr      immediately cause an overflow event.
>> +*   | SYS |
>> +*   | USR | -=0x10000        We go through all execution modes and set up SP
>> +*   |     |                for each of them.
>> +*   +-----+ <- SP_sys,
>> +*   |     |    SP_usr      Note:
>> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
>> +*   |     |                  non-privileged mode, so we take care not to enter
>> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
>> +*   |     |                  operations if already in that mode.
>> +*   | IRQ | -= 0x2000
>> +*   |     |                Input parameters:
>> +* ^ +-----+ <- SP_und       - sp - Initialized SP
>> +* s |     |                 - r2 - May contain SL value from semihosting
>> +* t | UND | -= 0x1000              SYS_HEAPINFO call
>> +* a |     |                Scratch registers:
>> +* c +-----+ <- SP_und       - r1 - new value of CPSR
>> +* k |     |                 - r2 - intermediate value (in standalone mode)
>> +*   | ABT | -= 0x1000       - r3 - new SP value
>> +* g |     |                 - r4 - save/restore CPSR on entry/exit
>> +* r +-----+ <- SP_abt,
>> +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
>> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
>> +* t |     |
>> +* h +-----+ <- initial SP,
>> +*           becomes SP_fiq
>> +*
>> +******************************************************************************/
>> +       .align  0
>> +       FUNC_START      _stack_init
>> +       .weak FUNCTION (_stack_init)
>> +       FN_EH_START
>> +
>> +       /* M profile doesn't have CPSR register.  */
>> +#if (__ARM_ARCH_PROFILE != 'M')
>> +       /* Following code is compatible for both ARM and Thumb ISA */
>> +       mrs     r4, CPSR
>> +       /* Test mode bits - in User of all are 0 */
>> +       tst     r4, #(CPSR_M_MASK)
>> +       /* "eq" means r4 AND #0x0F is 0 */
>> +       beq     .Lskip_cpu_modes
>> +
>> +       mov     r3, sp /* save input SP value */
>> +
>> +       /* FIQ mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +       sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
>> +
>> +       /* Abort mode, interrupts disabled */
>> +       mov     r3, sl
>> +       mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +       sub     r3, r3, #0x1000
>> +
>> +       /* Undefined mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +       sub     r3, r3, #0x1000
>> +
>> +       /* IRQ mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +       sub     r3, r3, #0x2000
>> +
>> +       /* Supervisory mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +
>> +       sub     r3, r3, #0x8000 /* Min size 32k */
>> +       bic     r3, r3, #0x00FF /* Align with current 64k block */
>> +       bic     r3, r3, #0xFF00
>> +
>> +# if __ARM_ARCH >= 4
>> +       /* System (shares regs with User) mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +# else
>> +       /* Keep this for ARMv3, but GCC actually dropped it. */
>> +       /* Move value into user mode sp without changing modes, */
>> +       /* via '^' form of ldm */
>> +       str     r3, [r3, #-4]
>> +       ldmdb   r3, {sp}^
>> +# endif
>> +
>> +       /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
>> +       orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r4
>> +
>> +.Lskip_cpu_modes:
>> +#endif
>> +
>> +       /* Set SL register */
>> +#if defined (ARM_RDI_MONITOR) /* semihosting */
>> +       cmp     r2, #0
>> +       beq     .Lsl_forced_zero
>> +       /* allow slop for stack overflow handling and small frames */
>> +# ifdef THUMB1_ONLY
>> +       adds    r2, #128
>> +       adds    r2, #128
>> +       mov     sl, r2
>> +# else
>> +       add     sl, r2, #256
>> +# endif
>> +.Lsl_forced_zero:
>> +
>> +#else /* standalone */
>> +       /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
>> +       #ifdef THUMB1_ONLY
>> +       movs    r2, #64
>> +       lsls    r2, r2, #10
>> +       subs    r2, r3, r2
>> +       mov     sl, r2
>> +       #else
>> +       /* Still assumes 256bytes below sl */
>> +       sub     sl, r3, #64 << 10
>> +       #endif
>> +#endif
>> +
>> +       FN_RETURN
>> +       FN_EH_END
>> +
>> +
>>  /*******************************************************************************
>>  * Main library startup code.
>>  *******************************************************************************/
>>         .align  0
>>         FUNC_START      _mainCRTStartup
>>         FUNC_START      _start
>> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> -       /* Annotation for EABI unwinding tables.  */
>> -       .fnstart
>> -#endif
>> +       FN_EH_START
>>
>>         /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards, however __ARM_ARCH_7A
>>         has been defined since 4.2 onwards, which is when v7-a support was added
>> @@ -150,36 +319,27 @@
>>               to skip setting sp/sl to 0 here.
>>             - Considering M-profile processors, We might want to initialize
>>               sp by the first entry of vector table and return 0 to SYS_HEAPINFO
>> -             semihosting call, which will be skipped here.  */
>> +             semihosting call, which will be skipped here.
>> +           - Considering R-profile processors there is no automatic SP init by hardware
>> +             so we need to initialize it by default value. */
>> +       ldr     r3, .Lstack
>>         cmp     r1, #0
>>         beq     .LC26
>> -       mov     sp, r1
>> +       mov     r3, r1
>>  .LC26:
>> -       cmp     r2, #0
>> -       beq     .LC27
>> +       mov     sp, r3
>>
>> -       /*  Allow slop for stack overflow handling and small frames.  */
>> -#ifdef THUMB1_ONLY
>> -       adds    r2, #128
>> -       adds    r2, #128
>> -       mov     sl, r2
>> -#else
>> -       add     sl, r2, #256
>> -#endif
>> +       /* r2 (SL value) will be used in _stack_init */
>> +       bl FUNCTION (_stack_init)
>>
>> -.LC27:
>> -#else
>> -       /*  Set up the stack pointer to a fixed value.  */
>> +
>> +#else /* standalone */
>> +       /*  Set up the stack pointer to a fixed value. */
>>         /*  Changes by toralf:
>>             - Allow linker script to provide stack via __stack symbol - see
>>               defintion of .Lstack
>>             - Provide "hooks" that may be used by the application to add
>> -             custom init code - see .Lhwinit and .Lswinit
>> -           - Go through all execution modes and set up stack for each of them.
>> -             Loosely based on init.s from ARM/Motorola example code.
>> -              Note: Mode switch via CPSR is not allowed once in non-privileged
>> -                   mode, so we take care not to enter "User" to set up its sp,
>> -                   and also skip most operations if already in that mode.  */
>> +             custom init code - see .Lhwinit and .Lswinit */
>>
>>         ldr     r3, .Lstack
>>         cmp     r3, #0
>> @@ -198,57 +358,10 @@
>>                  have somehow missed it below (in which case it gets the same
>>                  value as FIQ - not ideal, but better than nothing).  */
>>         mov     sp, r3
>> -#ifdef PREFER_THUMB
>> -       /* XXX Fill in stack assignments for interrupt modes.  */
>> -#else
>> -       mrs     r2, CPSR
>> -       tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
>> -       beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
>> -       msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
>> -       mov     sp, r3
>> -       sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
>> -
>> -       mov     r3, sl
>> -       msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
>> -       mov     sp, r3
>> -       sub     r3, r3, #0x1000
>> -
>> -       msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
>> -       mov     sp, r3
>> -       sub     r3, r3, #0x1000
>>
>> -       msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
>> -       mov     sp, r3
>> -       sub     r3, r3, #0x2000
>> -
>> -       msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
>> +       /* we don't care of r2 value in standalone */
>> +       bl FUNCTION (_stack_init)
>>
>> -       mov     sp, r3
>> -       sub     r3, r3, #0x8000 /* Min size 32k.  */
>> -       bic     r3, r3, #0x00FF /* Align with current 64k block.  */
>> -       bic     r3, r3, #0xFF00
>> -
>> -       str     r3, [r3, #-4]   /* Move value into user mode sp without */
>> -       ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
>> -       orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
>> -       msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
>> -#endif
>> -.LC23:
>> -       /* Setup a default stack-limit in-case the code has been
>> -          compiled with "-mapcs-stack-check".  Hard-wiring this value
>> -          is not ideal, since there is currently no support for
>> -          checking that the heap and stack have not collided, or that
>> -          this default 64k is enough for the program being executed.
>> -          However, it ensures that this simple crt0 world will not
>> -          immediately cause an overflow event:  */
>> -#ifdef THUMB1_ONLY
>> -       movs    r2, #64
>> -       lsls    r2, r2, #10
>> -       subs    r2, r3, r2
>> -       mov     sl, r2
>> -#else
>> -       sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
>> -#endif
>>  #endif
>>  #endif
>>         /* Zero the memory in the .bss section.  */
>> @@ -447,6 +560,8 @@ change_back:
>>         swi     SWI_Exit
>>  #endif
>>
>> +       FN_EH_END
>> +
>>         /* For Thumb, constants must be after the code since only
>>            positive offsets are supported for PC relative addresses.  */
>>         .align 0
>> @@ -464,9 +579,6 @@ change_back:
>>  #else
>>         .word   0x80000                 /* Top of RAM on the PIE board.  */
>>  #endif
>> -
>> -.Lstack:
>> -       .word   __stack
>>  .Lhwinit:
>>         .word   FUNCTION (hardware_init_hook)
>>  .Lswinit:
>> @@ -479,17 +591,16 @@ change_back:
>>            and only if, a normal version of the same symbol isn't provided
>>            e.g. by a linker script or another object file.)  */
>>
>> -       .weak __stack
>>         .weak FUNCTION (hardware_init_hook)
>>         .weak FUNCTION (software_init_hook)
>>  #endif
>>
>>  #endif
>> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> -       /* Protect against unhandled exceptions.  */
>> -       .cantunwind
>> -       .fnend
>> -#endif
>> +
>> +.Lstack:
>> +       .word   __stack
>> +       .weak   __stack
>> +
>>  .LC1:
>>         .word   __bss_start__
>>  .LC2:
>> diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
>> index 0489f2d92..04b3a5ac7 100644
>> --- a/newlib/libc/sys/arm/arm.h
>> +++ b/newlib/libc/sys/arm/arm.h
>> @@ -61,4 +61,30 @@
>>  # define HAVE_CALL_INDIRECT
>>  #endif
>>
>> +/* A and R profiles (and legacy Arm).
>> +       Current Program Status Register (CPSR)
>> +       M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
>> +       T[5]                    1: Thumb, 0: ARM instruction set
>> +       F[6]                    1: disables FIQ
>> +       I[7]                    1: disables IRQ
>> +       A[8]                    1: disables imprecise aborts
>> +       E[9]                    0: Little-endian, 1: Big-endian
>> +       J[24]                   1: Jazelle instruction set
>> + */
>> +#define CPSR_M_USR                     0x00    /* User mode */
>> +#define CPSR_M_FIQ                     0x01    /* Fast Interrupt mode */
>> +#define CPSR_M_IRQ                     0x02    /* Interrupt mode */
>> +#define CPSR_M_SVR                     0x03    /* Supervisor mode */
>> +#define CPSR_M_MON                     0x06    /* Monitor mode */
>> +#define CPSR_M_ABT                     0x07    /* Abort mode */
>> +#define CPSR_M_HYP                     0x0A    /* Hypervisor mode */
>> +#define CPSR_M_UND                     0x0B    /* Undefined mode */
>> +#define CPSR_M_SYS                     0x0F    /* System mode */
>> +#define CPSR_M_32BIT           0x10    /* 32-bit mode */
>> +#define CPSR_T_BIT                     0x20    /* Thumb bit */
>> +#define CPSR_F_MASK                    0x40    /* FIQ bit */
>> +#define CPSR_I_MASK                    0x80    /* IRQ bit */
>> +
>> +#define CPSR_M_MASK                    0x0F    /* Mode mask except M[4] */
>> +
>>  #endif /* _LIBGLOSS_ARM_H */
>> diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
>> index 7a6b40d9a..0929a435e 100644
>> --- a/newlib/libc/sys/arm/crt0.S
>> +++ b/newlib/libc/sys/arm/crt0.S
>> @@ -59,6 +59,21 @@
>>  .endm
>>  #endif
>>
>> +/* Annotation for EABI unwinding tables. */
>> +.macro FN_EH_START
>> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> +       .fnstart
>> +#endif
>> +.endm
>> +
>> +.macro FN_EH_END
>> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> +       /* Protect against unhandled exceptions.  */
>> +       .cantunwind
>> +       .fnend
>> +#endif
>> +.endm
>> +
>>  .macro indirect_call reg
>>  #ifdef HAVE_CALL_INDIRECT
>>         blx \reg
>> @@ -68,16 +83,170 @@
>>  #endif
>>  .endm
>>
>> +/* For armv4t and newer, toolchains will transparently convert
>> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
>> +   for anything older than armv4t, but this should handle that
>> +   corner case in case anyone needs it anyway */
>> +.macro  FN_RETURN
>> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
>> +       mov     pc, lr
>> +#else
>> +       bx      lr
>> +#endif
>> +.endm
>> +
>> +
>> +
>> +/******************************************************************************
>> +* User mode only:           This routine makes default target specific Stack
>> +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
>> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
>> +*   | SYS |               and setups a default Stack Limit in-case the code has
>> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
>> +*   |     |               System (User) modes.
>> +*   |     |
>> +*   +-----+ <- initial SP,
>> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
>> +*           and SL_usr     currently no support for checking that the heap and
>> +*                          stack have not collided, or that this default 64k is
>> +* All modes:               is enough for the program being executed. However,
>> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
>> +*   |     |    SL_usr      immediately cause an overflow event.
>> +*   | SYS |
>> +*   | USR | -=0x10000        We go through all execution modes and set up SP
>> +*   |     |                for each of them.
>> +*   +-----+ <- SP_sys,
>> +*   |     |    SP_usr      Note:
>> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
>> +*   |     |                  non-privileged mode, so we take care not to enter
>> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
>> +*   |     |                  operations if already in that mode.
>> +*   | IRQ | -= 0x2000
>> +*   |     |                Input parameters:
>> +* ^ +-----+ <- SP_und       - sp - Initialized SP
>> +* s |     |                 - r2 - May contain SL value from semihosting
>> +* t | UND | -= 0x1000              SYS_HEAPINFO call
>> +* a |     |                Scratch registers:
>> +* c +-----+ <- SP_und       - r1 - new value of CPSR
>> +* k |     |                 - r2 - intermediate value (in standalone mode)
>> +*   | ABT | -= 0x1000       - r3 - new SP value
>> +* g |     |                 - r4 - save/restore CPSR on entry/exit
>> +* r +-----+ <- SP_abt,
>> +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
>> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
>> +* t |     |
>> +* h +-----+ <- initial SP,
>> +*           becomes SP_fiq
>> +*
>> +******************************************************************************/
>> +       .align  0
>> +       FUNC_START      _stack_init
>> +       .weak FUNCTION (_stack_init)
>> +       FN_EH_START
>> +
>> +       /* M profile doesn't have CPSR register.  */
>> +#if (__ARM_ARCH_PROFILE != 'M')
>> +       /* Following code is compatible for both ARM and Thumb ISA */
>> +       mrs     r4, CPSR
>> +       /* Test mode bits - in User of all are 0 */
>> +       tst     r4, #(CPSR_M_MASK)
>> +       /* "eq" means r4 AND #0x0F is 0 */
>> +       beq     .Lskip_cpu_modes
>> +
>> +       mov     r3, sp /* save input SP value */
>> +
>> +       /* FIQ mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +       sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
>> +
>> +       /* Abort mode, interrupts disabled */
>> +       mov     r3, sl
>> +       mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +       sub     r3, r3, #0x1000
>> +
>> +       /* Undefined mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +       sub     r3, r3, #0x1000
>> +
>> +       /* IRQ mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +       sub     r3, r3, #0x2000
>> +
>> +       /* Supervisory mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +
>> +       sub     r3, r3, #0x8000 /* Min size 32k */
>> +       bic     r3, r3, #0x00FF /* Align with current 64k block */
>> +       bic     r3, r3, #0xFF00
>> +
>> +# if __ARM_ARCH >= 4
>> +       /* System (shares regs with User) mode, interrupts disabled */
>> +       mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r1
>> +       mov     sp, r3
>> +# else
>> +       /* Keep this for ARMv3, but GCC actually dropped it. */
>> +       /* Move value into user mode sp without changing modes, */
>> +       /* via '^' form of ldm */
>> +       str     r3, [r3, #-4]
>> +       ldmdb   r3, {sp}^
>> +# endif
>> +
>> +       /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
>> +       orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
>> +       msr     CPSR_c, r4
>> +
>> +.Lskip_cpu_modes:
>> +#endif
>> +
>> +       /* Set SL register */
>> +#if defined (ARM_RDI_MONITOR) /* semihosting */
>> +       cmp     r2, #0
>> +       beq     .Lsl_forced_zero
>> +       /* allow slop for stack overflow handling and small frames */
>> +# ifdef THUMB1_ONLY
>> +       adds    r2, #128
>> +       adds    r2, #128
>> +       mov     sl, r2
>> +# else
>> +       add     sl, r2, #256
>> +# endif
>> +.Lsl_forced_zero:
>> +
>> +#else /* standalone */
>> +       /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
>> +       #ifdef THUMB1_ONLY
>> +       movs    r2, #64
>> +       lsls    r2, r2, #10
>> +       subs    r2, r3, r2
>> +       mov     sl, r2
>> +       #else
>> +       /* Still assumes 256bytes below sl */
>> +       sub     sl, r3, #64 << 10
>> +       #endif
>> +#endif
>> +
>> +       FN_RETURN
>> +       FN_EH_END
>> +
>> +
>>  /*******************************************************************************
>>  * Main library startup code.
>>  *******************************************************************************/
>>         .align  0
>>         FUNC_START      _mainCRTStartup
>>         FUNC_START      _start
>> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> -       /* Annotation for EABI unwinding tables.  */
>> -       .fnstart
>> -#endif
>> +       FN_EH_START
>>
>>  /* Start by setting up a stack.  */
>>  #ifdef ARM_RDP_MONITOR
>> @@ -130,36 +299,27 @@
>>               to skip setting sp/sl to 0 here.
>>             - Considering M-profile processors, We might want to initialize
>>               sp by the first entry of vector table and return 0 to SYS_HEAPINFO
>> -             semihosting call, which will be skipped here.  */
>> +             semihosting call, which will be skipped here.
>> +           - Considering R-profile processors there is no automatic SP init by hardware
>> +             so we need to initialize it by default value. */
>> +       ldr     r3, .Lstack
>>         cmp     r1, #0
>>         beq     .LC26
>> -       mov     sp, r1
>> +       mov     r3, r1
>>  .LC26:
>> -       cmp     r2, #0
>> -       beq     .LC27
>> +       mov     sp, r3
>>
>> -       /*  Allow slop for stack overflow handling and small frames.  */
>> -#ifdef THUMB1_ONLY
>> -       adds    r2, #128
>> -       adds    r2, #128
>> -       mov     sl, r2
>> -#else
>> -       add     sl, r2, #256
>> -#endif
>> +       /* r2 (SL value) will be used in _stack_init */
>> +       bl FUNCTION (_stack_init)
>>
>> -.LC27:
>> -#else
>> -       /*  Set up the stack pointer to a fixed value.  */
>> +
>> +#else /* standalone */
>> +       /*  Set up the stack pointer to a fixed value. */
>>         /*  Changes by toralf:
>>             - Allow linker script to provide stack via __stack symbol - see
>>               defintion of .Lstack
>>             - Provide "hooks" that may be used by the application to add
>> -             custom init code - see .Lhwinit and .Lswinit
>> -           - Go through all execution modes and set up stack for each of them.
>> -             Loosely based on init.s from ARM/Motorola example code.
>> -              Note: Mode switch via CPSR is not allowed once in non-privileged
>> -                   mode, so we take care not to enter "User" to set up its sp,
>> -                   and also skip most operations if already in that mode.  */
>> +             custom init code - see .Lhwinit and .Lswinit */
>>
>>         ldr     r3, .Lstack
>>         cmp     r3, #0
>> @@ -178,57 +338,10 @@
>>                  have somehow missed it below (in which case it gets the same
>>                  value as FIQ - not ideal, but better than nothing).  */
>>         mov     sp, r3
>> -#ifdef PREFER_THUMB
>> -       /* XXX Fill in stack assignments for interrupt modes.  */
>> -#else
>> -       mrs     r2, CPSR
>> -       tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
>> -       beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
>> -       msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
>> -       mov     sp, r3
>> -       sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
>> -
>> -       mov     r3, sl
>> -       msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
>> -       mov     sp, r3
>> -       sub     r3, r3, #0x1000
>> -
>> -       msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
>> -       mov     sp, r3
>> -       sub     r3, r3, #0x1000
>>
>> -       msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
>> -       mov     sp, r3
>> -       sub     r3, r3, #0x2000
>> -
>> -       msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
>> +       /* we don't care of r2 value in standalone */
>> +       bl FUNCTION (_stack_init)
>>
>> -       mov     sp, r3
>> -       sub     r3, r3, #0x8000 /* Min size 32k.  */
>> -       bic     r3, r3, #0x00FF /* Align with current 64k block.  */
>> -       bic     r3, r3, #0xFF00
>> -
>> -       str     r3, [r3, #-4]   /* Move value into user mode sp without */
>> -       ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
>> -       orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
>> -       msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
>> -#endif
>> -.LC23:
>> -       /* Setup a default stack-limit in-case the code has been
>> -          compiled with "-mapcs-stack-check".  Hard-wiring this value
>> -          is not ideal, since there is currently no support for
>> -          checking that the heap and stack have not collided, or that
>> -          this default 64k is enough for the program being executed.
>> -          However, it ensures that this simple crt0 world will not
>> -          immediately cause an overflow event:  */
>> -#ifdef THUMB1_ONLY
>> -       movs    r2, #64
>> -       lsls    r2, r2, #10
>> -       subs    r2, r3, r2
>> -       mov     sl, r2
>> -#else
>> -       sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
>> -#endif
>>  #endif
>>  #endif
>>         /* Zero the memory in the .bss section.  */
>> @@ -421,6 +534,8 @@ change_back:
>>         swi     SWI_Exit
>>  #endif
>>
>> +       FN_EH_END
>> +
>>         /* For Thumb, constants must be after the code since only
>>            positive offsets are supported for PC relative addresses.  */
>>         .align 0
>> @@ -438,9 +553,6 @@ change_back:
>>  #else
>>         .word   0x80000                 /* Top of RAM on the PIE board.  */
>>  #endif
>> -
>> -.Lstack:
>> -       .word   __stack
>>  .Lhwinit:
>>         .word   FUNCTION (hardware_init_hook)
>>  .Lswinit:
>> @@ -453,17 +565,16 @@ change_back:
>>            and only if, a normal version of the same symbol isn't provided
>>            e.g. by a linker script or another object file.)  */
>>
>> -       .weak __stack
>>         .weak FUNCTION (hardware_init_hook)
>>         .weak FUNCTION (software_init_hook)
>>  #endif
>>
>>  #endif
>> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>> -       /* Protect against unhandled exceptions.  */
>> -       .cantunwind
>> -       .fnend
>> -#endif
>> +
>> +.Lstack:
>> +       .word   __stack
>> +       .weak   __stack
>> +
>>  .LC1:
>>         .word   __bss_start__
>>  .LC2:
>> --
>> 2.17.1
>>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] [Arm] Stack Pointer and Stack Limit initialization refactored.

Alexander Fedotov
Ping^3

On Thu, Apr 25, 2019 at 1:21 PM Alexander Fedotov <[hidden email]> wrote:

>
> Ping^2
>
> On Wed, Apr 17, 2019 at 12:17 PM Alexander Fedotov <[hidden email]> wrote:
> >
> > Ping
> >
> > On Fri, 12 Apr 2019 at 16:31, <[hidden email]> wrote:
> >>
> >> From: Alexander Fedotov <[hidden email]>
> >>
> >> SP initialization changes:
> >>   1. set default value in semihosting case as well
> >>   2. moved existing SP & SL init code for processor modes in separate routine and made it as "hook"
> >>   3. init SP for processor modes in Thumb mode as well
> >>
> >> Add new macro FN_RETURN, FN_EH_START and FN_EH_END.
> >> ---
> >>  libgloss/arm/arm.h         |  26 ++++
> >>  libgloss/arm/crt0.S        | 277 ++++++++++++++++++++++++++-----------
> >>  newlib/libc/sys/arm/arm.h  |  26 ++++
> >>  newlib/libc/sys/arm/crt0.S | 277 ++++++++++++++++++++++++++-----------
> >>  4 files changed, 440 insertions(+), 166 deletions(-)
> >>
> >> diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
> >> index 0489f2d92..04b3a5ac7 100644
> >> --- a/libgloss/arm/arm.h
> >> +++ b/libgloss/arm/arm.h
> >> @@ -61,4 +61,30 @@
> >>  # define HAVE_CALL_INDIRECT
> >>  #endif
> >>
> >> +/* A and R profiles (and legacy Arm).
> >> +       Current Program Status Register (CPSR)
> >> +       M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
> >> +       T[5]                    1: Thumb, 0: ARM instruction set
> >> +       F[6]                    1: disables FIQ
> >> +       I[7]                    1: disables IRQ
> >> +       A[8]                    1: disables imprecise aborts
> >> +       E[9]                    0: Little-endian, 1: Big-endian
> >> +       J[24]                   1: Jazelle instruction set
> >> + */
> >> +#define CPSR_M_USR                     0x00    /* User mode */
> >> +#define CPSR_M_FIQ                     0x01    /* Fast Interrupt mode */
> >> +#define CPSR_M_IRQ                     0x02    /* Interrupt mode */
> >> +#define CPSR_M_SVR                     0x03    /* Supervisor mode */
> >> +#define CPSR_M_MON                     0x06    /* Monitor mode */
> >> +#define CPSR_M_ABT                     0x07    /* Abort mode */
> >> +#define CPSR_M_HYP                     0x0A    /* Hypervisor mode */
> >> +#define CPSR_M_UND                     0x0B    /* Undefined mode */
> >> +#define CPSR_M_SYS                     0x0F    /* System mode */
> >> +#define CPSR_M_32BIT           0x10    /* 32-bit mode */
> >> +#define CPSR_T_BIT                     0x20    /* Thumb bit */
> >> +#define CPSR_F_MASK                    0x40    /* FIQ bit */
> >> +#define CPSR_I_MASK                    0x80    /* IRQ bit */
> >> +
> >> +#define CPSR_M_MASK                    0x0F    /* Mode mask except M[4] */
> >> +
> >>  #endif /* _LIBGLOSS_ARM_H */
> >> diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
> >> index 1deb73aa5..95aa3b578 100644
> >> --- a/libgloss/arm/crt0.S
> >> +++ b/libgloss/arm/crt0.S
> >> @@ -59,6 +59,21 @@
> >>  .endm
> >>  #endif
> >>
> >> +/* Annotation for EABI unwinding tables. */
> >> +.macro FN_EH_START
> >> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> >> +       .fnstart
> >> +#endif
> >> +.endm
> >> +
> >> +.macro FN_EH_END
> >> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> >> +       /* Protect against unhandled exceptions.  */
> >> +       .cantunwind
> >> +       .fnend
> >> +#endif
> >> +.endm
> >> +
> >>  .macro indirect_call reg
> >>  #ifdef HAVE_CALL_INDIRECT
> >>         blx \reg
> >> @@ -68,16 +83,170 @@
> >>  #endif
> >>  .endm
> >>
> >> +/* For armv4t and newer, toolchains will transparently convert
> >> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> >> +   for anything older than armv4t, but this should handle that
> >> +   corner case in case anyone needs it anyway */
> >> +.macro  FN_RETURN
> >> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> >> +       mov     pc, lr
> >> +#else
> >> +       bx      lr
> >> +#endif
> >> +.endm
> >> +
> >> +
> >> +
> >> +/******************************************************************************
> >> +* User mode only:           This routine makes default target specific Stack
> >> +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
> >> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
> >> +*   | SYS |               and setups a default Stack Limit in-case the code has
> >> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
> >> +*   |     |               System (User) modes.
> >> +*   |     |
> >> +*   +-----+ <- initial SP,
> >> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
> >> +*           and SL_usr     currently no support for checking that the heap and
> >> +*                          stack have not collided, or that this default 64k is
> >> +* All modes:               is enough for the program being executed. However,
> >> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
> >> +*   |     |    SL_usr      immediately cause an overflow event.
> >> +*   | SYS |
> >> +*   | USR | -=0x10000        We go through all execution modes and set up SP
> >> +*   |     |                for each of them.
> >> +*   +-----+ <- SP_sys,
> >> +*   |     |    SP_usr      Note:
> >> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
> >> +*   |     |                  non-privileged mode, so we take care not to enter
> >> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
> >> +*   |     |                  operations if already in that mode.
> >> +*   | IRQ | -= 0x2000
> >> +*   |     |                Input parameters:
> >> +* ^ +-----+ <- SP_und       - sp - Initialized SP
> >> +* s |     |                 - r2 - May contain SL value from semihosting
> >> +* t | UND | -= 0x1000              SYS_HEAPINFO call
> >> +* a |     |                Scratch registers:
> >> +* c +-----+ <- SP_und       - r1 - new value of CPSR
> >> +* k |     |                 - r2 - intermediate value (in standalone mode)
> >> +*   | ABT | -= 0x1000       - r3 - new SP value
> >> +* g |     |                 - r4 - save/restore CPSR on entry/exit
> >> +* r +-----+ <- SP_abt,
> >> +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
> >> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
> >> +* t |     |
> >> +* h +-----+ <- initial SP,
> >> +*           becomes SP_fiq
> >> +*
> >> +******************************************************************************/
> >> +       .align  0
> >> +       FUNC_START      _stack_init
> >> +       .weak FUNCTION (_stack_init)
> >> +       FN_EH_START
> >> +
> >> +       /* M profile doesn't have CPSR register.  */
> >> +#if (__ARM_ARCH_PROFILE != 'M')
> >> +       /* Following code is compatible for both ARM and Thumb ISA */
> >> +       mrs     r4, CPSR
> >> +       /* Test mode bits - in User of all are 0 */
> >> +       tst     r4, #(CPSR_M_MASK)
> >> +       /* "eq" means r4 AND #0x0F is 0 */
> >> +       beq     .Lskip_cpu_modes
> >> +
> >> +       mov     r3, sp /* save input SP value */
> >> +
> >> +       /* FIQ mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +       sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
> >> +
> >> +       /* Abort mode, interrupts disabled */
> >> +       mov     r3, sl
> >> +       mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +       sub     r3, r3, #0x1000
> >> +
> >> +       /* Undefined mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +       sub     r3, r3, #0x1000
> >> +
> >> +       /* IRQ mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +       sub     r3, r3, #0x2000
> >> +
> >> +       /* Supervisory mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +
> >> +       sub     r3, r3, #0x8000 /* Min size 32k */
> >> +       bic     r3, r3, #0x00FF /* Align with current 64k block */
> >> +       bic     r3, r3, #0xFF00
> >> +
> >> +# if __ARM_ARCH >= 4
> >> +       /* System (shares regs with User) mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +# else
> >> +       /* Keep this for ARMv3, but GCC actually dropped it. */
> >> +       /* Move value into user mode sp without changing modes, */
> >> +       /* via '^' form of ldm */
> >> +       str     r3, [r3, #-4]
> >> +       ldmdb   r3, {sp}^
> >> +# endif
> >> +
> >> +       /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
> >> +       orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r4
> >> +
> >> +.Lskip_cpu_modes:
> >> +#endif
> >> +
> >> +       /* Set SL register */
> >> +#if defined (ARM_RDI_MONITOR) /* semihosting */
> >> +       cmp     r2, #0
> >> +       beq     .Lsl_forced_zero
> >> +       /* allow slop for stack overflow handling and small frames */
> >> +# ifdef THUMB1_ONLY
> >> +       adds    r2, #128
> >> +       adds    r2, #128
> >> +       mov     sl, r2
> >> +# else
> >> +       add     sl, r2, #256
> >> +# endif
> >> +.Lsl_forced_zero:
> >> +
> >> +#else /* standalone */
> >> +       /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
> >> +       #ifdef THUMB1_ONLY
> >> +       movs    r2, #64
> >> +       lsls    r2, r2, #10
> >> +       subs    r2, r3, r2
> >> +       mov     sl, r2
> >> +       #else
> >> +       /* Still assumes 256bytes below sl */
> >> +       sub     sl, r3, #64 << 10
> >> +       #endif
> >> +#endif
> >> +
> >> +       FN_RETURN
> >> +       FN_EH_END
> >> +
> >> +
> >>  /*******************************************************************************
> >>  * Main library startup code.
> >>  *******************************************************************************/
> >>         .align  0
> >>         FUNC_START      _mainCRTStartup
> >>         FUNC_START      _start
> >> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> >> -       /* Annotation for EABI unwinding tables.  */
> >> -       .fnstart
> >> -#endif
> >> +       FN_EH_START
> >>
> >>         /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards, however __ARM_ARCH_7A
> >>         has been defined since 4.2 onwards, which is when v7-a support was added
> >> @@ -150,36 +319,27 @@
> >>               to skip setting sp/sl to 0 here.
> >>             - Considering M-profile processors, We might want to initialize
> >>               sp by the first entry of vector table and return 0 to SYS_HEAPINFO
> >> -             semihosting call, which will be skipped here.  */
> >> +             semihosting call, which will be skipped here.
> >> +           - Considering R-profile processors there is no automatic SP init by hardware
> >> +             so we need to initialize it by default value. */
> >> +       ldr     r3, .Lstack
> >>         cmp     r1, #0
> >>         beq     .LC26
> >> -       mov     sp, r1
> >> +       mov     r3, r1
> >>  .LC26:
> >> -       cmp     r2, #0
> >> -       beq     .LC27
> >> +       mov     sp, r3
> >>
> >> -       /*  Allow slop for stack overflow handling and small frames.  */
> >> -#ifdef THUMB1_ONLY
> >> -       adds    r2, #128
> >> -       adds    r2, #128
> >> -       mov     sl, r2
> >> -#else
> >> -       add     sl, r2, #256
> >> -#endif
> >> +       /* r2 (SL value) will be used in _stack_init */
> >> +       bl FUNCTION (_stack_init)
> >>
> >> -.LC27:
> >> -#else
> >> -       /*  Set up the stack pointer to a fixed value.  */
> >> +
> >> +#else /* standalone */
> >> +       /*  Set up the stack pointer to a fixed value. */
> >>         /*  Changes by toralf:
> >>             - Allow linker script to provide stack via __stack symbol - see
> >>               defintion of .Lstack
> >>             - Provide "hooks" that may be used by the application to add
> >> -             custom init code - see .Lhwinit and .Lswinit
> >> -           - Go through all execution modes and set up stack for each of them.
> >> -             Loosely based on init.s from ARM/Motorola example code.
> >> -              Note: Mode switch via CPSR is not allowed once in non-privileged
> >> -                   mode, so we take care not to enter "User" to set up its sp,
> >> -                   and also skip most operations if already in that mode.  */
> >> +             custom init code - see .Lhwinit and .Lswinit */
> >>
> >>         ldr     r3, .Lstack
> >>         cmp     r3, #0
> >> @@ -198,57 +358,10 @@
> >>                  have somehow missed it below (in which case it gets the same
> >>                  value as FIQ - not ideal, but better than nothing).  */
> >>         mov     sp, r3
> >> -#ifdef PREFER_THUMB
> >> -       /* XXX Fill in stack assignments for interrupt modes.  */
> >> -#else
> >> -       mrs     r2, CPSR
> >> -       tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
> >> -       beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> >> -       msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> >> -       mov     sp, r3
> >> -       sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
> >> -
> >> -       mov     r3, sl
> >> -       msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
> >> -       mov     sp, r3
> >> -       sub     r3, r3, #0x1000
> >> -
> >> -       msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
> >> -       mov     sp, r3
> >> -       sub     r3, r3, #0x1000
> >>
> >> -       msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> >> -       mov     sp, r3
> >> -       sub     r3, r3, #0x2000
> >> -
> >> -       msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
> >> +       /* we don't care of r2 value in standalone */
> >> +       bl FUNCTION (_stack_init)
> >>
> >> -       mov     sp, r3
> >> -       sub     r3, r3, #0x8000 /* Min size 32k.  */
> >> -       bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> >> -       bic     r3, r3, #0xFF00
> >> -
> >> -       str     r3, [r3, #-4]   /* Move value into user mode sp without */
> >> -       ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
> >> -       orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
> >> -       msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
> >> -#endif
> >> -.LC23:
> >> -       /* Setup a default stack-limit in-case the code has been
> >> -          compiled with "-mapcs-stack-check".  Hard-wiring this value
> >> -          is not ideal, since there is currently no support for
> >> -          checking that the heap and stack have not collided, or that
> >> -          this default 64k is enough for the program being executed.
> >> -          However, it ensures that this simple crt0 world will not
> >> -          immediately cause an overflow event:  */
> >> -#ifdef THUMB1_ONLY
> >> -       movs    r2, #64
> >> -       lsls    r2, r2, #10
> >> -       subs    r2, r3, r2
> >> -       mov     sl, r2
> >> -#else
> >> -       sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
> >> -#endif
> >>  #endif
> >>  #endif
> >>         /* Zero the memory in the .bss section.  */
> >> @@ -447,6 +560,8 @@ change_back:
> >>         swi     SWI_Exit
> >>  #endif
> >>
> >> +       FN_EH_END
> >> +
> >>         /* For Thumb, constants must be after the code since only
> >>            positive offsets are supported for PC relative addresses.  */
> >>         .align 0
> >> @@ -464,9 +579,6 @@ change_back:
> >>  #else
> >>         .word   0x80000                 /* Top of RAM on the PIE board.  */
> >>  #endif
> >> -
> >> -.Lstack:
> >> -       .word   __stack
> >>  .Lhwinit:
> >>         .word   FUNCTION (hardware_init_hook)
> >>  .Lswinit:
> >> @@ -479,17 +591,16 @@ change_back:
> >>            and only if, a normal version of the same symbol isn't provided
> >>            e.g. by a linker script or another object file.)  */
> >>
> >> -       .weak __stack
> >>         .weak FUNCTION (hardware_init_hook)
> >>         .weak FUNCTION (software_init_hook)
> >>  #endif
> >>
> >>  #endif
> >> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> >> -       /* Protect against unhandled exceptions.  */
> >> -       .cantunwind
> >> -       .fnend
> >> -#endif
> >> +
> >> +.Lstack:
> >> +       .word   __stack
> >> +       .weak   __stack
> >> +
> >>  .LC1:
> >>         .word   __bss_start__
> >>  .LC2:
> >> diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
> >> index 0489f2d92..04b3a5ac7 100644
> >> --- a/newlib/libc/sys/arm/arm.h
> >> +++ b/newlib/libc/sys/arm/arm.h
> >> @@ -61,4 +61,30 @@
> >>  # define HAVE_CALL_INDIRECT
> >>  #endif
> >>
> >> +/* A and R profiles (and legacy Arm).
> >> +       Current Program Status Register (CPSR)
> >> +       M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
> >> +       T[5]                    1: Thumb, 0: ARM instruction set
> >> +       F[6]                    1: disables FIQ
> >> +       I[7]                    1: disables IRQ
> >> +       A[8]                    1: disables imprecise aborts
> >> +       E[9]                    0: Little-endian, 1: Big-endian
> >> +       J[24]                   1: Jazelle instruction set
> >> + */
> >> +#define CPSR_M_USR                     0x00    /* User mode */
> >> +#define CPSR_M_FIQ                     0x01    /* Fast Interrupt mode */
> >> +#define CPSR_M_IRQ                     0x02    /* Interrupt mode */
> >> +#define CPSR_M_SVR                     0x03    /* Supervisor mode */
> >> +#define CPSR_M_MON                     0x06    /* Monitor mode */
> >> +#define CPSR_M_ABT                     0x07    /* Abort mode */
> >> +#define CPSR_M_HYP                     0x0A    /* Hypervisor mode */
> >> +#define CPSR_M_UND                     0x0B    /* Undefined mode */
> >> +#define CPSR_M_SYS                     0x0F    /* System mode */
> >> +#define CPSR_M_32BIT           0x10    /* 32-bit mode */
> >> +#define CPSR_T_BIT                     0x20    /* Thumb bit */
> >> +#define CPSR_F_MASK                    0x40    /* FIQ bit */
> >> +#define CPSR_I_MASK                    0x80    /* IRQ bit */
> >> +
> >> +#define CPSR_M_MASK                    0x0F    /* Mode mask except M[4] */
> >> +
> >>  #endif /* _LIBGLOSS_ARM_H */
> >> diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
> >> index 7a6b40d9a..0929a435e 100644
> >> --- a/newlib/libc/sys/arm/crt0.S
> >> +++ b/newlib/libc/sys/arm/crt0.S
> >> @@ -59,6 +59,21 @@
> >>  .endm
> >>  #endif
> >>
> >> +/* Annotation for EABI unwinding tables. */
> >> +.macro FN_EH_START
> >> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> >> +       .fnstart
> >> +#endif
> >> +.endm
> >> +
> >> +.macro FN_EH_END
> >> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> >> +       /* Protect against unhandled exceptions.  */
> >> +       .cantunwind
> >> +       .fnend
> >> +#endif
> >> +.endm
> >> +
> >>  .macro indirect_call reg
> >>  #ifdef HAVE_CALL_INDIRECT
> >>         blx \reg
> >> @@ -68,16 +83,170 @@
> >>  #endif
> >>  .endm
> >>
> >> +/* For armv4t and newer, toolchains will transparently convert
> >> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> >> +   for anything older than armv4t, but this should handle that
> >> +   corner case in case anyone needs it anyway */
> >> +.macro  FN_RETURN
> >> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> >> +       mov     pc, lr
> >> +#else
> >> +       bx      lr
> >> +#endif
> >> +.endm
> >> +
> >> +
> >> +
> >> +/******************************************************************************
> >> +* User mode only:           This routine makes default target specific Stack
> >> +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
> >> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
> >> +*   | SYS |               and setups a default Stack Limit in-case the code has
> >> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
> >> +*   |     |               System (User) modes.
> >> +*   |     |
> >> +*   +-----+ <- initial SP,
> >> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
> >> +*           and SL_usr     currently no support for checking that the heap and
> >> +*                          stack have not collided, or that this default 64k is
> >> +* All modes:               is enough for the program being executed. However,
> >> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
> >> +*   |     |    SL_usr      immediately cause an overflow event.
> >> +*   | SYS |
> >> +*   | USR | -=0x10000        We go through all execution modes and set up SP
> >> +*   |     |                for each of them.
> >> +*   +-----+ <- SP_sys,
> >> +*   |     |    SP_usr      Note:
> >> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
> >> +*   |     |                  non-privileged mode, so we take care not to enter
> >> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
> >> +*   |     |                  operations if already in that mode.
> >> +*   | IRQ | -= 0x2000
> >> +*   |     |                Input parameters:
> >> +* ^ +-----+ <- SP_und       - sp - Initialized SP
> >> +* s |     |                 - r2 - May contain SL value from semihosting
> >> +* t | UND | -= 0x1000              SYS_HEAPINFO call
> >> +* a |     |                Scratch registers:
> >> +* c +-----+ <- SP_und       - r1 - new value of CPSR
> >> +* k |     |                 - r2 - intermediate value (in standalone mode)
> >> +*   | ABT | -= 0x1000       - r3 - new SP value
> >> +* g |     |                 - r4 - save/restore CPSR on entry/exit
> >> +* r +-----+ <- SP_abt,
> >> +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
> >> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
> >> +* t |     |
> >> +* h +-----+ <- initial SP,
> >> +*           becomes SP_fiq
> >> +*
> >> +******************************************************************************/
> >> +       .align  0
> >> +       FUNC_START      _stack_init
> >> +       .weak FUNCTION (_stack_init)
> >> +       FN_EH_START
> >> +
> >> +       /* M profile doesn't have CPSR register.  */
> >> +#if (__ARM_ARCH_PROFILE != 'M')
> >> +       /* Following code is compatible for both ARM and Thumb ISA */
> >> +       mrs     r4, CPSR
> >> +       /* Test mode bits - in User of all are 0 */
> >> +       tst     r4, #(CPSR_M_MASK)
> >> +       /* "eq" means r4 AND #0x0F is 0 */
> >> +       beq     .Lskip_cpu_modes
> >> +
> >> +       mov     r3, sp /* save input SP value */
> >> +
> >> +       /* FIQ mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +       sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
> >> +
> >> +       /* Abort mode, interrupts disabled */
> >> +       mov     r3, sl
> >> +       mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +       sub     r3, r3, #0x1000
> >> +
> >> +       /* Undefined mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +       sub     r3, r3, #0x1000
> >> +
> >> +       /* IRQ mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +       sub     r3, r3, #0x2000
> >> +
> >> +       /* Supervisory mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +
> >> +       sub     r3, r3, #0x8000 /* Min size 32k */
> >> +       bic     r3, r3, #0x00FF /* Align with current 64k block */
> >> +       bic     r3, r3, #0xFF00
> >> +
> >> +# if __ARM_ARCH >= 4
> >> +       /* System (shares regs with User) mode, interrupts disabled */
> >> +       mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r1
> >> +       mov     sp, r3
> >> +# else
> >> +       /* Keep this for ARMv3, but GCC actually dropped it. */
> >> +       /* Move value into user mode sp without changing modes, */
> >> +       /* via '^' form of ldm */
> >> +       str     r3, [r3, #-4]
> >> +       ldmdb   r3, {sp}^
> >> +# endif
> >> +
> >> +       /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
> >> +       orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> >> +       msr     CPSR_c, r4
> >> +
> >> +.Lskip_cpu_modes:
> >> +#endif
> >> +
> >> +       /* Set SL register */
> >> +#if defined (ARM_RDI_MONITOR) /* semihosting */
> >> +       cmp     r2, #0
> >> +       beq     .Lsl_forced_zero
> >> +       /* allow slop for stack overflow handling and small frames */
> >> +# ifdef THUMB1_ONLY
> >> +       adds    r2, #128
> >> +       adds    r2, #128
> >> +       mov     sl, r2
> >> +# else
> >> +       add     sl, r2, #256
> >> +# endif
> >> +.Lsl_forced_zero:
> >> +
> >> +#else /* standalone */
> >> +       /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
> >> +       #ifdef THUMB1_ONLY
> >> +       movs    r2, #64
> >> +       lsls    r2, r2, #10
> >> +       subs    r2, r3, r2
> >> +       mov     sl, r2
> >> +       #else
> >> +       /* Still assumes 256bytes below sl */
> >> +       sub     sl, r3, #64 << 10
> >> +       #endif
> >> +#endif
> >> +
> >> +       FN_RETURN
> >> +       FN_EH_END
> >> +
> >> +
> >>  /*******************************************************************************
> >>  * Main library startup code.
> >>  *******************************************************************************/
> >>         .align  0
> >>         FUNC_START      _mainCRTStartup
> >>         FUNC_START      _start
> >> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> >> -       /* Annotation for EABI unwinding tables.  */
> >> -       .fnstart
> >> -#endif
> >> +       FN_EH_START
> >>
> >>  /* Start by setting up a stack.  */
> >>  #ifdef ARM_RDP_MONITOR
> >> @@ -130,36 +299,27 @@
> >>               to skip setting sp/sl to 0 here.
> >>             - Considering M-profile processors, We might want to initialize
> >>               sp by the first entry of vector table and return 0 to SYS_HEAPINFO
> >> -             semihosting call, which will be skipped here.  */
> >> +             semihosting call, which will be skipped here.
> >> +           - Considering R-profile processors there is no automatic SP init by hardware
> >> +             so we need to initialize it by default value. */
> >> +       ldr     r3, .Lstack
> >>         cmp     r1, #0
> >>         beq     .LC26
> >> -       mov     sp, r1
> >> +       mov     r3, r1
> >>  .LC26:
> >> -       cmp     r2, #0
> >> -       beq     .LC27
> >> +       mov     sp, r3
> >>
> >> -       /*  Allow slop for stack overflow handling and small frames.  */
> >> -#ifdef THUMB1_ONLY
> >> -       adds    r2, #128
> >> -       adds    r2, #128
> >> -       mov     sl, r2
> >> -#else
> >> -       add     sl, r2, #256
> >> -#endif
> >> +       /* r2 (SL value) will be used in _stack_init */
> >> +       bl FUNCTION (_stack_init)
> >>
> >> -.LC27:
> >> -#else
> >> -       /*  Set up the stack pointer to a fixed value.  */
> >> +
> >> +#else /* standalone */
> >> +       /*  Set up the stack pointer to a fixed value. */
> >>         /*  Changes by toralf:
> >>             - Allow linker script to provide stack via __stack symbol - see
> >>               defintion of .Lstack
> >>             - Provide "hooks" that may be used by the application to add
> >> -             custom init code - see .Lhwinit and .Lswinit
> >> -           - Go through all execution modes and set up stack for each of them.
> >> -             Loosely based on init.s from ARM/Motorola example code.
> >> -              Note: Mode switch via CPSR is not allowed once in non-privileged
> >> -                   mode, so we take care not to enter "User" to set up its sp,
> >> -                   and also skip most operations if already in that mode.  */
> >> +             custom init code - see .Lhwinit and .Lswinit */
> >>
> >>         ldr     r3, .Lstack
> >>         cmp     r3, #0
> >> @@ -178,57 +338,10 @@
> >>                  have somehow missed it below (in which case it gets the same
> >>                  value as FIQ - not ideal, but better than nothing).  */
> >>         mov     sp, r3
> >> -#ifdef PREFER_THUMB
> >> -       /* XXX Fill in stack assignments for interrupt modes.  */
> >> -#else
> >> -       mrs     r2, CPSR
> >> -       tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
> >> -       beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> >> -       msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> >> -       mov     sp, r3
> >> -       sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
> >> -
> >> -       mov     r3, sl
> >> -       msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
> >> -       mov     sp, r3
> >> -       sub     r3, r3, #0x1000
> >> -
> >> -       msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
> >> -       mov     sp, r3
> >> -       sub     r3, r3, #0x1000
> >>
> >> -       msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> >> -       mov     sp, r3
> >> -       sub     r3, r3, #0x2000
> >> -
> >> -       msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
> >> +       /* we don't care of r2 value in standalone */
> >> +       bl FUNCTION (_stack_init)
> >>
> >> -       mov     sp, r3
> >> -       sub     r3, r3, #0x8000 /* Min size 32k.  */
> >> -       bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> >> -       bic     r3, r3, #0xFF00
> >> -
> >> -       str     r3, [r3, #-4]   /* Move value into user mode sp without */
> >> -       ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
> >> -       orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
> >> -       msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
> >> -#endif
> >> -.LC23:
> >> -       /* Setup a default stack-limit in-case the code has been
> >> -          compiled with "-mapcs-stack-check".  Hard-wiring this value
> >> -          is not ideal, since there is currently no support for
> >> -          checking that the heap and stack have not collided, or that
> >> -          this default 64k is enough for the program being executed.
> >> -          However, it ensures that this simple crt0 world will not
> >> -          immediately cause an overflow event:  */
> >> -#ifdef THUMB1_ONLY
> >> -       movs    r2, #64
> >> -       lsls    r2, r2, #10
> >> -       subs    r2, r3, r2
> >> -       mov     sl, r2
> >> -#else
> >> -       sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
> >> -#endif
> >>  #endif
> >>  #endif
> >>         /* Zero the memory in the .bss section.  */
> >> @@ -421,6 +534,8 @@ change_back:
> >>         swi     SWI_Exit
> >>  #endif
> >>
> >> +       FN_EH_END
> >> +
> >>         /* For Thumb, constants must be after the code since only
> >>            positive offsets are supported for PC relative addresses.  */
> >>         .align 0
> >> @@ -438,9 +553,6 @@ change_back:
> >>  #else
> >>         .word   0x80000                 /* Top of RAM on the PIE board.  */
> >>  #endif
> >> -
> >> -.Lstack:
> >> -       .word   __stack
> >>  .Lhwinit:
> >>         .word   FUNCTION (hardware_init_hook)
> >>  .Lswinit:
> >> @@ -453,17 +565,16 @@ change_back:
> >>            and only if, a normal version of the same symbol isn't provided
> >>            e.g. by a linker script or another object file.)  */
> >>
> >> -       .weak __stack
> >>         .weak FUNCTION (hardware_init_hook)
> >>         .weak FUNCTION (software_init_hook)
> >>  #endif
> >>
> >>  #endif
> >> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> >> -       /* Protect against unhandled exceptions.  */
> >> -       .cantunwind
> >> -       .fnend
> >> -#endif
> >> +
> >> +.Lstack:
> >> +       .word   __stack
> >> +       .weak   __stack
> >> +
> >>  .LC1:
> >>         .word   __bss_start__
> >>  .LC2:
> >> --
> >> 2.17.1
> >>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] [Arm] Stack Pointer and Stack Limit initialization refactored.

Alexander Fedotov
Ping^4

On Mon, 13 May 2019 at 16:25, Alexander Fedotov <[hidden email]> wrote:

> Ping^3
>
> On Thu, Apr 25, 2019 at 1:21 PM Alexander Fedotov <[hidden email]>
> wrote:
> >
> > Ping^2
> >
> > On Wed, Apr 17, 2019 at 12:17 PM Alexander Fedotov <[hidden email]>
> wrote:
> > >
> > > Ping
> > >
> > > On Fri, 12 Apr 2019 at 16:31, <[hidden email]> wrote:
> > >>
> > >> From: Alexander Fedotov <[hidden email]>
> > >>
> > >> SP initialization changes:
> > >>   1. set default value in semihosting case as well
> > >>   2. moved existing SP & SL init code for processor modes in separate
> routine and made it as "hook"
> > >>   3. init SP for processor modes in Thumb mode as well
> > >>
> > >> Add new macro FN_RETURN, FN_EH_START and FN_EH_END.
> > >> ---
> > >>  libgloss/arm/arm.h         |  26 ++++
> > >>  libgloss/arm/crt0.S        | 277
> ++++++++++++++++++++++++++-----------
> > >>  newlib/libc/sys/arm/arm.h  |  26 ++++
> > >>  newlib/libc/sys/arm/crt0.S | 277
> ++++++++++++++++++++++++++-----------
> > >>  4 files changed, 440 insertions(+), 166 deletions(-)
> > >>
> > >> diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
> > >> index 0489f2d92..04b3a5ac7 100644
> > >> --- a/libgloss/arm/arm.h
> > >> +++ b/libgloss/arm/arm.h
> > >> @@ -61,4 +61,30 @@
> > >>  # define HAVE_CALL_INDIRECT
> > >>  #endif
> > >>
> > >> +/* A and R profiles (and legacy Arm).
> > >> +       Current Program Status Register (CPSR)
> > >> +       M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
> > >> +       T[5]                    1: Thumb, 0: ARM instruction set
> > >> +       F[6]                    1: disables FIQ
> > >> +       I[7]                    1: disables IRQ
> > >> +       A[8]                    1: disables imprecise aborts
> > >> +       E[9]                    0: Little-endian, 1: Big-endian
> > >> +       J[24]                   1: Jazelle instruction set
> > >> + */
> > >> +#define CPSR_M_USR                     0x00    /* User mode */
> > >> +#define CPSR_M_FIQ                     0x01    /* Fast Interrupt
> mode */
> > >> +#define CPSR_M_IRQ                     0x02    /* Interrupt mode */
> > >> +#define CPSR_M_SVR                     0x03    /* Supervisor mode */
> > >> +#define CPSR_M_MON                     0x06    /* Monitor mode */
> > >> +#define CPSR_M_ABT                     0x07    /* Abort mode */
> > >> +#define CPSR_M_HYP                     0x0A    /* Hypervisor mode */
> > >> +#define CPSR_M_UND                     0x0B    /* Undefined mode */
> > >> +#define CPSR_M_SYS                     0x0F    /* System mode */
> > >> +#define CPSR_M_32BIT           0x10    /* 32-bit mode */
> > >> +#define CPSR_T_BIT                     0x20    /* Thumb bit */
> > >> +#define CPSR_F_MASK                    0x40    /* FIQ bit */
> > >> +#define CPSR_I_MASK                    0x80    /* IRQ bit */
> > >> +
> > >> +#define CPSR_M_MASK                    0x0F    /* Mode mask except
> M[4] */
> > >> +
> > >>  #endif /* _LIBGLOSS_ARM_H */
> > >> diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
> > >> index 1deb73aa5..95aa3b578 100644
> > >> --- a/libgloss/arm/crt0.S
> > >> +++ b/libgloss/arm/crt0.S
> > >> @@ -59,6 +59,21 @@
> > >>  .endm
> > >>  #endif
> > >>
> > >> +/* Annotation for EABI unwinding tables. */
> > >> +.macro FN_EH_START
> > >> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > >> +       .fnstart
> > >> +#endif
> > >> +.endm
> > >> +
> > >> +.macro FN_EH_END
> > >> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > >> +       /* Protect against unhandled exceptions.  */
> > >> +       .cantunwind
> > >> +       .fnend
> > >> +#endif
> > >> +.endm
> > >> +
> > >>  .macro indirect_call reg
> > >>  #ifdef HAVE_CALL_INDIRECT
> > >>         blx \reg
> > >> @@ -68,16 +83,170 @@
> > >>  #endif
> > >>  .endm
> > >>
> > >> +/* For armv4t and newer, toolchains will transparently convert
> > >> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> > >> +   for anything older than armv4t, but this should handle that
> > >> +   corner case in case anyone needs it anyway */
> > >> +.macro  FN_RETURN
> > >> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> > >> +       mov     pc, lr
> > >> +#else
> > >> +       bx      lr
> > >> +#endif
> > >> +.endm
> > >> +
> > >> +
> > >> +
> > >>
> +/******************************************************************************
> > >> +* User mode only:           This routine makes default target
> specific Stack
> > >> +*   +-----+ <- SL_sys,    Pointer initialization for different
> processor modes:
> > >> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor,
> System (User)
> > >> +*   | SYS |               and setups a default Stack Limit in-case
> the code has
> > >> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check"
> for FIQ and
> > >> +*   |     |               System (User) modes.
> > >> +*   |     |
> > >> +*   +-----+ <- initial SP,
> > >> +*           becomes SP_sys   Hard-wiring SL value is not ideal,
> since there is
> > >> +*           and SL_usr     currently no support for checking that
> the heap and
> > >> +*                          stack have not collided, or that this
> default 64k is
> > >> +* All modes:               is enough for the program being executed.
> However,
> > >> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world
> will not
> > >> +*   |     |    SL_usr      immediately cause an overflow event.
> > >> +*   | SYS |
> > >> +*   | USR | -=0x10000        We go through all execution modes and
> set up SP
> > >> +*   |     |                for each of them.
> > >> +*   +-----+ <- SP_sys,
> > >> +*   |     |    SP_usr      Note:
> > >> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed
> once in
> > >> +*   |     |                  non-privileged mode, so we take care
> not to enter
> > >> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip
> most
> > >> +*   |     |                  operations if already in that mode.
> > >> +*   | IRQ | -= 0x2000
> > >> +*   |     |                Input parameters:
> > >> +* ^ +-----+ <- SP_und       - sp - Initialized SP
> > >> +* s |     |                 - r2 - May contain SL value from
> semihosting
> > >> +* t | UND | -= 0x1000              SYS_HEAPINFO call
> > >> +* a |     |                Scratch registers:
> > >> +* c +-----+ <- SP_und       - r1 - new value of CPSR
> > >> +* k |     |                 - r2 - intermediate value (in standalone
> mode)
> > >> +*   | ABT | -= 0x1000       - r3 - new SP value
> > >> +* g |     |                 - r4 - save/restore CPSR on entry/exit
> > >> +* r +-----+ <- SP_abt,
> > >> +* o |     |    SL_fiq        Declared as "weak" so that user can
> write and use
> > >> +* w | FIQ | -= 0x1000      his own implementation if current doesn't
> fit.
> > >> +* t |     |
> > >> +* h +-----+ <- initial SP,
> > >> +*           becomes SP_fiq
> > >> +*
> > >>
> +******************************************************************************/
> > >> +       .align  0
> > >> +       FUNC_START      _stack_init
> > >> +       .weak FUNCTION (_stack_init)
> > >> +       FN_EH_START
> > >> +
> > >> +       /* M profile doesn't have CPSR register.  */
> > >> +#if (__ARM_ARCH_PROFILE != 'M')
> > >> +       /* Following code is compatible for both ARM and Thumb ISA */
> > >> +       mrs     r4, CPSR
> > >> +       /* Test mode bits - in User of all are 0 */
> > >> +       tst     r4, #(CPSR_M_MASK)
> > >> +       /* "eq" means r4 AND #0x0F is 0 */
> > >> +       beq     .Lskip_cpu_modes
> > >> +
> > >> +       mov     r3, sp /* save input SP value */
> > >> +
> > >> +       /* FIQ mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +       sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
> > >> +
> > >> +       /* Abort mode, interrupts disabled */
> > >> +       mov     r3, sl
> > >> +       mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +       sub     r3, r3, #0x1000
> > >> +
> > >> +       /* Undefined mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +       sub     r3, r3, #0x1000
> > >> +
> > >> +       /* IRQ mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +       sub     r3, r3, #0x2000
> > >> +
> > >> +       /* Supervisory mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +
> > >> +       sub     r3, r3, #0x8000 /* Min size 32k */
> > >> +       bic     r3, r3, #0x00FF /* Align with current 64k block */
> > >> +       bic     r3, r3, #0xFF00
> > >> +
> > >> +# if __ARM_ARCH >= 4
> > >> +       /* System (shares regs with User) mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +# else
> > >> +       /* Keep this for ARMv3, but GCC actually dropped it. */
> > >> +       /* Move value into user mode sp without changing modes, */
> > >> +       /* via '^' form of ldm */
> > >> +       str     r3, [r3, #-4]
> > >> +       ldmdb   r3, {sp}^
> > >> +# endif
> > >> +
> > >> +       /* Back to original mode, presumably SVC, with diabled
> FIQ/IRQ */
> > >> +       orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r4
> > >> +
> > >> +.Lskip_cpu_modes:
> > >> +#endif
> > >> +
> > >> +       /* Set SL register */
> > >> +#if defined (ARM_RDI_MONITOR) /* semihosting */
> > >> +       cmp     r2, #0
> > >> +       beq     .Lsl_forced_zero
> > >> +       /* allow slop for stack overflow handling and small frames */
> > >> +# ifdef THUMB1_ONLY
> > >> +       adds    r2, #128
> > >> +       adds    r2, #128
> > >> +       mov     sl, r2
> > >> +# else
> > >> +       add     sl, r2, #256
> > >> +# endif
> > >> +.Lsl_forced_zero:
> > >> +
> > >> +#else /* standalone */
> > >> +       /* r3 contains SP for System/User mode. Set SL = SP - 0x10000
> */
> > >> +       #ifdef THUMB1_ONLY
> > >> +       movs    r2, #64
> > >> +       lsls    r2, r2, #10
> > >> +       subs    r2, r3, r2
> > >> +       mov     sl, r2
> > >> +       #else
> > >> +       /* Still assumes 256bytes below sl */
> > >> +       sub     sl, r3, #64 << 10
> > >> +       #endif
> > >> +#endif
> > >> +
> > >> +       FN_RETURN
> > >> +       FN_EH_END
> > >> +
> > >> +
> > >>
> /*******************************************************************************
> > >>  * Main library startup code.
> > >>
> *******************************************************************************/
> > >>         .align  0
> > >>         FUNC_START      _mainCRTStartup
> > >>         FUNC_START      _start
> > >> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > >> -       /* Annotation for EABI unwinding tables.  */
> > >> -       .fnstart
> > >> -#endif
> > >> +       FN_EH_START
> > >>
> > >>         /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards,
> however __ARM_ARCH_7A
> > >>         has been defined since 4.2 onwards, which is when v7-a
> support was added
> > >> @@ -150,36 +319,27 @@
> > >>               to skip setting sp/sl to 0 here.
> > >>             - Considering M-profile processors, We might want to
> initialize
> > >>               sp by the first entry of vector table and return 0 to
> SYS_HEAPINFO
> > >> -             semihosting call, which will be skipped here.  */
> > >> +             semihosting call, which will be skipped here.
> > >> +           - Considering R-profile processors there is no automatic
> SP init by hardware
> > >> +             so we need to initialize it by default value. */
> > >> +       ldr     r3, .Lstack
> > >>         cmp     r1, #0
> > >>         beq     .LC26
> > >> -       mov     sp, r1
> > >> +       mov     r3, r1
> > >>  .LC26:
> > >> -       cmp     r2, #0
> > >> -       beq     .LC27
> > >> +       mov     sp, r3
> > >>
> > >> -       /*  Allow slop for stack overflow handling and small frames.
> */
> > >> -#ifdef THUMB1_ONLY
> > >> -       adds    r2, #128
> > >> -       adds    r2, #128
> > >> -       mov     sl, r2
> > >> -#else
> > >> -       add     sl, r2, #256
> > >> -#endif
> > >> +       /* r2 (SL value) will be used in _stack_init */
> > >> +       bl FUNCTION (_stack_init)
> > >>
> > >> -.LC27:
> > >> -#else
> > >> -       /*  Set up the stack pointer to a fixed value.  */
> > >> +
> > >> +#else /* standalone */
> > >> +       /*  Set up the stack pointer to a fixed value. */
> > >>         /*  Changes by toralf:
> > >>             - Allow linker script to provide stack via __stack symbol
> - see
> > >>               defintion of .Lstack
> > >>             - Provide "hooks" that may be used by the application to
> add
> > >> -             custom init code - see .Lhwinit and .Lswinit
> > >> -           - Go through all execution modes and set up stack for
> each of them.
> > >> -             Loosely based on init.s from ARM/Motorola example code.
> > >> -              Note: Mode switch via CPSR is not allowed once in
> non-privileged
> > >> -                   mode, so we take care not to enter "User" to set
> up its sp,
> > >> -                   and also skip most operations if already in that
> mode.  */
> > >> +             custom init code - see .Lhwinit and .Lswinit */
> > >>
> > >>         ldr     r3, .Lstack
> > >>         cmp     r3, #0
> > >> @@ -198,57 +358,10 @@
> > >>                  have somehow missed it below (in which case it gets
> the same
> > >>                  value as FIQ - not ideal, but better than nothing).
> */
> > >>         mov     sp, r3
> > >> -#ifdef PREFER_THUMB
> > >> -       /* XXX Fill in stack assignments for interrupt modes.  */
> > >> -#else
> > >> -       mrs     r2, CPSR
> > >> -       tst     r2, #0x0F       /* Test mode bits - in User of all
> are 0.  */
> > >> -       beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> > >> -       msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> > >> -       mov     sp, r3
> > >> -       sub     sl, sp, #0x1000 /* This mode also has its own sl (see
> below).  */
> > >> -
> > >> -       mov     r3, sl
> > >> -       msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.
> */
> > >> -       mov     sp, r3
> > >> -       sub     r3, r3, #0x1000
> > >> -
> > >> -       msr     CPSR_c, #0xDB   /* Undefined mode, interrupts
> disabled.  */
> > >> -       mov     sp, r3
> > >> -       sub     r3, r3, #0x1000
> > >>
> > >> -       msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> > >> -       mov     sp, r3
> > >> -       sub     r3, r3, #0x2000
> > >> -
> > >> -       msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts
> disabled.  */
> > >> +       /* we don't care of r2 value in standalone */
> > >> +       bl FUNCTION (_stack_init)
> > >>
> > >> -       mov     sp, r3
> > >> -       sub     r3, r3, #0x8000 /* Min size 32k.  */
> > >> -       bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> > >> -       bic     r3, r3, #0xFF00
> > >> -
> > >> -       str     r3, [r3, #-4]   /* Move value into user mode sp
> without */
> > >> -       ldmdb   r3, {sp}^       /* changing modes, via '^' form of
> ldm.  */
> > >> -       orr     r2, r2, #0xC0   /* Back to original mode, presumably
> SVC, */
> > >> -       msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced
> to 1.  */
> > >> -#endif
> > >> -.LC23:
> > >> -       /* Setup a default stack-limit in-case the code has been
> > >> -          compiled with "-mapcs-stack-check".  Hard-wiring this value
> > >> -          is not ideal, since there is currently no support for
> > >> -          checking that the heap and stack have not collided, or that
> > >> -          this default 64k is enough for the program being executed.
> > >> -          However, it ensures that this simple crt0 world will not
> > >> -          immediately cause an overflow event:  */
> > >> -#ifdef THUMB1_ONLY
> > >> -       movs    r2, #64
> > >> -       lsls    r2, r2, #10
> > >> -       subs    r2, r3, r2
> > >> -       mov     sl, r2
> > >> -#else
> > >> -       sub     sl, r3, #64 << 10       /* Still assumes 256bytes
> below sl.  */
> > >> -#endif
> > >>  #endif
> > >>  #endif
> > >>         /* Zero the memory in the .bss section.  */
> > >> @@ -447,6 +560,8 @@ change_back:
> > >>         swi     SWI_Exit
> > >>  #endif
> > >>
> > >> +       FN_EH_END
> > >> +
> > >>         /* For Thumb, constants must be after the code since only
> > >>            positive offsets are supported for PC relative addresses.
> */
> > >>         .align 0
> > >> @@ -464,9 +579,6 @@ change_back:
> > >>  #else
> > >>         .word   0x80000                 /* Top of RAM on the PIE
> board.  */
> > >>  #endif
> > >> -
> > >> -.Lstack:
> > >> -       .word   __stack
> > >>  .Lhwinit:
> > >>         .word   FUNCTION (hardware_init_hook)
> > >>  .Lswinit:
> > >> @@ -479,17 +591,16 @@ change_back:
> > >>            and only if, a normal version of the same symbol isn't
> provided
> > >>            e.g. by a linker script or another object file.)  */
> > >>
> > >> -       .weak __stack
> > >>         .weak FUNCTION (hardware_init_hook)
> > >>         .weak FUNCTION (software_init_hook)
> > >>  #endif
> > >>
> > >>  #endif
> > >> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > >> -       /* Protect against unhandled exceptions.  */
> > >> -       .cantunwind
> > >> -       .fnend
> > >> -#endif
> > >> +
> > >> +.Lstack:
> > >> +       .word   __stack
> > >> +       .weak   __stack
> > >> +
> > >>  .LC1:
> > >>         .word   __bss_start__
> > >>  .LC2:
> > >> diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
> > >> index 0489f2d92..04b3a5ac7 100644
> > >> --- a/newlib/libc/sys/arm/arm.h
> > >> +++ b/newlib/libc/sys/arm/arm.h
> > >> @@ -61,4 +61,30 @@
> > >>  # define HAVE_CALL_INDIRECT
> > >>  #endif
> > >>
> > >> +/* A and R profiles (and legacy Arm).
> > >> +       Current Program Status Register (CPSR)
> > >> +       M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
> > >> +       T[5]                    1: Thumb, 0: ARM instruction set
> > >> +       F[6]                    1: disables FIQ
> > >> +       I[7]                    1: disables IRQ
> > >> +       A[8]                    1: disables imprecise aborts
> > >> +       E[9]                    0: Little-endian, 1: Big-endian
> > >> +       J[24]                   1: Jazelle instruction set
> > >> + */
> > >> +#define CPSR_M_USR                     0x00    /* User mode */
> > >> +#define CPSR_M_FIQ                     0x01    /* Fast Interrupt
> mode */
> > >> +#define CPSR_M_IRQ                     0x02    /* Interrupt mode */
> > >> +#define CPSR_M_SVR                     0x03    /* Supervisor mode */
> > >> +#define CPSR_M_MON                     0x06    /* Monitor mode */
> > >> +#define CPSR_M_ABT                     0x07    /* Abort mode */
> > >> +#define CPSR_M_HYP                     0x0A    /* Hypervisor mode */
> > >> +#define CPSR_M_UND                     0x0B    /* Undefined mode */
> > >> +#define CPSR_M_SYS                     0x0F    /* System mode */
> > >> +#define CPSR_M_32BIT           0x10    /* 32-bit mode */
> > >> +#define CPSR_T_BIT                     0x20    /* Thumb bit */
> > >> +#define CPSR_F_MASK                    0x40    /* FIQ bit */
> > >> +#define CPSR_I_MASK                    0x80    /* IRQ bit */
> > >> +
> > >> +#define CPSR_M_MASK                    0x0F    /* Mode mask except
> M[4] */
> > >> +
> > >>  #endif /* _LIBGLOSS_ARM_H */
> > >> diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
> > >> index 7a6b40d9a..0929a435e 100644
> > >> --- a/newlib/libc/sys/arm/crt0.S
> > >> +++ b/newlib/libc/sys/arm/crt0.S
> > >> @@ -59,6 +59,21 @@
> > >>  .endm
> > >>  #endif
> > >>
> > >> +/* Annotation for EABI unwinding tables. */
> > >> +.macro FN_EH_START
> > >> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > >> +       .fnstart
> > >> +#endif
> > >> +.endm
> > >> +
> > >> +.macro FN_EH_END
> > >> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > >> +       /* Protect against unhandled exceptions.  */
> > >> +       .cantunwind
> > >> +       .fnend
> > >> +#endif
> > >> +.endm
> > >> +
> > >>  .macro indirect_call reg
> > >>  #ifdef HAVE_CALL_INDIRECT
> > >>         blx \reg
> > >> @@ -68,16 +83,170 @@
> > >>  #endif
> > >>  .endm
> > >>
> > >> +/* For armv4t and newer, toolchains will transparently convert
> > >> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> > >> +   for anything older than armv4t, but this should handle that
> > >> +   corner case in case anyone needs it anyway */
> > >> +.macro  FN_RETURN
> > >> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> > >> +       mov     pc, lr
> > >> +#else
> > >> +       bx      lr
> > >> +#endif
> > >> +.endm
> > >> +
> > >> +
> > >> +
> > >>
> +/******************************************************************************
> > >> +* User mode only:           This routine makes default target
> specific Stack
> > >> +*   +-----+ <- SL_sys,    Pointer initialization for different
> processor modes:
> > >> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor,
> System (User)
> > >> +*   | SYS |               and setups a default Stack Limit in-case
> the code has
> > >> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check"
> for FIQ and
> > >> +*   |     |               System (User) modes.
> > >> +*   |     |
> > >> +*   +-----+ <- initial SP,
> > >> +*           becomes SP_sys   Hard-wiring SL value is not ideal,
> since there is
> > >> +*           and SL_usr     currently no support for checking that
> the heap and
> > >> +*                          stack have not collided, or that this
> default 64k is
> > >> +* All modes:               is enough for the program being executed.
> However,
> > >> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world
> will not
> > >> +*   |     |    SL_usr      immediately cause an overflow event.
> > >> +*   | SYS |
> > >> +*   | USR | -=0x10000        We go through all execution modes and
> set up SP
> > >> +*   |     |                for each of them.
> > >> +*   +-----+ <- SP_sys,
> > >> +*   |     |    SP_usr      Note:
> > >> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed
> once in
> > >> +*   |     |                  non-privileged mode, so we take care
> not to enter
> > >> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip
> most
> > >> +*   |     |                  operations if already in that mode.
> > >> +*   | IRQ | -= 0x2000
> > >> +*   |     |                Input parameters:
> > >> +* ^ +-----+ <- SP_und       - sp - Initialized SP
> > >> +* s |     |                 - r2 - May contain SL value from
> semihosting
> > >> +* t | UND | -= 0x1000              SYS_HEAPINFO call
> > >> +* a |     |                Scratch registers:
> > >> +* c +-----+ <- SP_und       - r1 - new value of CPSR
> > >> +* k |     |                 - r2 - intermediate value (in standalone
> mode)
> > >> +*   | ABT | -= 0x1000       - r3 - new SP value
> > >> +* g |     |                 - r4 - save/restore CPSR on entry/exit
> > >> +* r +-----+ <- SP_abt,
> > >> +* o |     |    SL_fiq        Declared as "weak" so that user can
> write and use
> > >> +* w | FIQ | -= 0x1000      his own implementation if current doesn't
> fit.
> > >> +* t |     |
> > >> +* h +-----+ <- initial SP,
> > >> +*           becomes SP_fiq
> > >> +*
> > >>
> +******************************************************************************/
> > >> +       .align  0
> > >> +       FUNC_START      _stack_init
> > >> +       .weak FUNCTION (_stack_init)
> > >> +       FN_EH_START
> > >> +
> > >> +       /* M profile doesn't have CPSR register.  */
> > >> +#if (__ARM_ARCH_PROFILE != 'M')
> > >> +       /* Following code is compatible for both ARM and Thumb ISA */
> > >> +       mrs     r4, CPSR
> > >> +       /* Test mode bits - in User of all are 0 */
> > >> +       tst     r4, #(CPSR_M_MASK)
> > >> +       /* "eq" means r4 AND #0x0F is 0 */
> > >> +       beq     .Lskip_cpu_modes
> > >> +
> > >> +       mov     r3, sp /* save input SP value */
> > >> +
> > >> +       /* FIQ mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +       sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
> > >> +
> > >> +       /* Abort mode, interrupts disabled */
> > >> +       mov     r3, sl
> > >> +       mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +       sub     r3, r3, #0x1000
> > >> +
> > >> +       /* Undefined mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +       sub     r3, r3, #0x1000
> > >> +
> > >> +       /* IRQ mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +       sub     r3, r3, #0x2000
> > >> +
> > >> +       /* Supervisory mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +
> > >> +       sub     r3, r3, #0x8000 /* Min size 32k */
> > >> +       bic     r3, r3, #0x00FF /* Align with current 64k block */
> > >> +       bic     r3, r3, #0xFF00
> > >> +
> > >> +# if __ARM_ARCH >= 4
> > >> +       /* System (shares regs with User) mode, interrupts disabled */
> > >> +       mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r1
> > >> +       mov     sp, r3
> > >> +# else
> > >> +       /* Keep this for ARMv3, but GCC actually dropped it. */
> > >> +       /* Move value into user mode sp without changing modes, */
> > >> +       /* via '^' form of ldm */
> > >> +       str     r3, [r3, #-4]
> > >> +       ldmdb   r3, {sp}^
> > >> +# endif
> > >> +
> > >> +       /* Back to original mode, presumably SVC, with diabled
> FIQ/IRQ */
> > >> +       orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> > >> +       msr     CPSR_c, r4
> > >> +
> > >> +.Lskip_cpu_modes:
> > >> +#endif
> > >> +
> > >> +       /* Set SL register */
> > >> +#if defined (ARM_RDI_MONITOR) /* semihosting */
> > >> +       cmp     r2, #0
> > >> +       beq     .Lsl_forced_zero
> > >> +       /* allow slop for stack overflow handling and small frames */
> > >> +# ifdef THUMB1_ONLY
> > >> +       adds    r2, #128
> > >> +       adds    r2, #128
> > >> +       mov     sl, r2
> > >> +# else
> > >> +       add     sl, r2, #256
> > >> +# endif
> > >> +.Lsl_forced_zero:
> > >> +
> > >> +#else /* standalone */
> > >> +       /* r3 contains SP for System/User mode. Set SL = SP - 0x10000
> */
> > >> +       #ifdef THUMB1_ONLY
> > >> +       movs    r2, #64
> > >> +       lsls    r2, r2, #10
> > >> +       subs    r2, r3, r2
> > >> +       mov     sl, r2
> > >> +       #else
> > >> +       /* Still assumes 256bytes below sl */
> > >> +       sub     sl, r3, #64 << 10
> > >> +       #endif
> > >> +#endif
> > >> +
> > >> +       FN_RETURN
> > >> +       FN_EH_END
> > >> +
> > >> +
> > >>
> /*******************************************************************************
> > >>  * Main library startup code.
> > >>
> *******************************************************************************/
> > >>         .align  0
> > >>         FUNC_START      _mainCRTStartup
> > >>         FUNC_START      _start
> > >> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > >> -       /* Annotation for EABI unwinding tables.  */
> > >> -       .fnstart
> > >> -#endif
> > >> +       FN_EH_START
> > >>
> > >>  /* Start by setting up a stack.  */
> > >>  #ifdef ARM_RDP_MONITOR
> > >> @@ -130,36 +299,27 @@
> > >>               to skip setting sp/sl to 0 here.
> > >>             - Considering M-profile processors, We might want to
> initialize
> > >>               sp by the first entry of vector table and return 0 to
> SYS_HEAPINFO
> > >> -             semihosting call, which will be skipped here.  */
> > >> +             semihosting call, which will be skipped here.
> > >> +           - Considering R-profile processors there is no automatic
> SP init by hardware
> > >> +             so we need to initialize it by default value. */
> > >> +       ldr     r3, .Lstack
> > >>         cmp     r1, #0
> > >>         beq     .LC26
> > >> -       mov     sp, r1
> > >> +       mov     r3, r1
> > >>  .LC26:
> > >> -       cmp     r2, #0
> > >> -       beq     .LC27
> > >> +       mov     sp, r3
> > >>
> > >> -       /*  Allow slop for stack overflow handling and small frames.
> */
> > >> -#ifdef THUMB1_ONLY
> > >> -       adds    r2, #128
> > >> -       adds    r2, #128
> > >> -       mov     sl, r2
> > >> -#else
> > >> -       add     sl, r2, #256
> > >> -#endif
> > >> +       /* r2 (SL value) will be used in _stack_init */
> > >> +       bl FUNCTION (_stack_init)
> > >>
> > >> -.LC27:
> > >> -#else
> > >> -       /*  Set up the stack pointer to a fixed value.  */
> > >> +
> > >> +#else /* standalone */
> > >> +       /*  Set up the stack pointer to a fixed value. */
> > >>         /*  Changes by toralf:
> > >>             - Allow linker script to provide stack via __stack symbol
> - see
> > >>               defintion of .Lstack
> > >>             - Provide "hooks" that may be used by the application to
> add
> > >> -             custom init code - see .Lhwinit and .Lswinit
> > >> -           - Go through all execution modes and set up stack for
> each of them.
> > >> -             Loosely based on init.s from ARM/Motorola example code.
> > >> -              Note: Mode switch via CPSR is not allowed once in
> non-privileged
> > >> -                   mode, so we take care not to enter "User" to set
> up its sp,
> > >> -                   and also skip most operations if already in that
> mode.  */
> > >> +             custom init code - see .Lhwinit and .Lswinit */
> > >>
> > >>         ldr     r3, .Lstack
> > >>         cmp     r3, #0
> > >> @@ -178,57 +338,10 @@
> > >>                  have somehow missed it below (in which case it gets
> the same
> > >>                  value as FIQ - not ideal, but better than nothing).
> */
> > >>         mov     sp, r3
> > >> -#ifdef PREFER_THUMB
> > >> -       /* XXX Fill in stack assignments for interrupt modes.  */
> > >> -#else
> > >> -       mrs     r2, CPSR
> > >> -       tst     r2, #0x0F       /* Test mode bits - in User of all
> are 0.  */
> > >> -       beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> > >> -       msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> > >> -       mov     sp, r3
> > >> -       sub     sl, sp, #0x1000 /* This mode also has its own sl (see
> below).  */
> > >> -
> > >> -       mov     r3, sl
> > >> -       msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.
> */
> > >> -       mov     sp, r3
> > >> -       sub     r3, r3, #0x1000
> > >> -
> > >> -       msr     CPSR_c, #0xDB   /* Undefined mode, interrupts
> disabled.  */
> > >> -       mov     sp, r3
> > >> -       sub     r3, r3, #0x1000
> > >>
> > >> -       msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> > >> -       mov     sp, r3
> > >> -       sub     r3, r3, #0x2000
> > >> -
> > >> -       msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts
> disabled.  */
> > >> +       /* we don't care of r2 value in standalone */
> > >> +       bl FUNCTION (_stack_init)
> > >>
> > >> -       mov     sp, r3
> > >> -       sub     r3, r3, #0x8000 /* Min size 32k.  */
> > >> -       bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> > >> -       bic     r3, r3, #0xFF00
> > >> -
> > >> -       str     r3, [r3, #-4]   /* Move value into user mode sp
> without */
> > >> -       ldmdb   r3, {sp}^       /* changing modes, via '^' form of
> ldm.  */
> > >> -       orr     r2, r2, #0xC0   /* Back to original mode, presumably
> SVC, */
> > >> -       msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced
> to 1.  */
> > >> -#endif
> > >> -.LC23:
> > >> -       /* Setup a default stack-limit in-case the code has been
> > >> -          compiled with "-mapcs-stack-check".  Hard-wiring this value
> > >> -          is not ideal, since there is currently no support for
> > >> -          checking that the heap and stack have not collided, or that
> > >> -          this default 64k is enough for the program being executed.
> > >> -          However, it ensures that this simple crt0 world will not
> > >> -          immediately cause an overflow event:  */
> > >> -#ifdef THUMB1_ONLY
> > >> -       movs    r2, #64
> > >> -       lsls    r2, r2, #10
> > >> -       subs    r2, r3, r2
> > >> -       mov     sl, r2
> > >> -#else
> > >> -       sub     sl, r3, #64 << 10       /* Still assumes 256bytes
> below sl.  */
> > >> -#endif
> > >>  #endif
> > >>  #endif
> > >>         /* Zero the memory in the .bss section.  */
> > >> @@ -421,6 +534,8 @@ change_back:
> > >>         swi     SWI_Exit
> > >>  #endif
> > >>
> > >> +       FN_EH_END
> > >> +
> > >>         /* For Thumb, constants must be after the code since only
> > >>            positive offsets are supported for PC relative addresses.
> */
> > >>         .align 0
> > >> @@ -438,9 +553,6 @@ change_back:
> > >>  #else
> > >>         .word   0x80000                 /* Top of RAM on the PIE
> board.  */
> > >>  #endif
> > >> -
> > >> -.Lstack:
> > >> -       .word   __stack
> > >>  .Lhwinit:
> > >>         .word   FUNCTION (hardware_init_hook)
> > >>  .Lswinit:
> > >> @@ -453,17 +565,16 @@ change_back:
> > >>            and only if, a normal version of the same symbol isn't
> provided
> > >>            e.g. by a linker script or another object file.)  */
> > >>
> > >> -       .weak __stack
> > >>         .weak FUNCTION (hardware_init_hook)
> > >>         .weak FUNCTION (software_init_hook)
> > >>  #endif
> > >>
> > >>  #endif
> > >> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > >> -       /* Protect against unhandled exceptions.  */
> > >> -       .cantunwind
> > >> -       .fnend
> > >> -#endif
> > >> +
> > >> +.Lstack:
> > >> +       .word   __stack
> > >> +       .weak   __stack
> > >> +
> > >>  .LC1:
> > >>         .word   __bss_start__
> > >>  .LC2:
> > >> --
> > >> 2.17.1
> > >>
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/2] Align comments and spaces in libgloss/arm/crt0.S and newlib/libc/sys/arm/crt0.S to ease further code alignment.

Richard Earnshaw (lists)
In reply to this post by Alexander Fedotov
OK.

(sorry for the delay replying).

R.

On 12/04/2019 14:30, [hidden email] wrote:

> From: Alexander Fedotov <[hidden email]>
>
> ---
>   libgloss/arm/crt0.S        | 135 +++++++++++++++++++------------------
>   newlib/libc/sys/arm/crt0.S |  18 ++---
>   2 files changed, 78 insertions(+), 75 deletions(-)
>
> diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
> index c708f63d8..1deb73aa5 100644
> --- a/libgloss/arm/crt0.S
> +++ b/libgloss/arm/crt0.S
> @@ -68,8 +68,10 @@
>   #endif
>   .endm
>  
> +/*******************************************************************************
> +* Main library startup code.
> +*******************************************************************************/
>   .align 0
> -
>   FUNC_START _mainCRTStartup
>   FUNC_START _start
>   #if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> @@ -90,14 +92,14 @@
>   #endif
>   #endif
>  
> -/* Start by setting up a stack */
> +/* Start by setting up a stack.  */
>   #ifdef ARM_RDP_MONITOR
> - /*  Issue Demon SWI to read stack info */
> - swi SWI_GetEnv /*  Returns command line in r0 */
> - mov sp,r1 /*  and the highest memory address in r1 */
> + /*  Issue Demon SWI to read stack info.  */
> + swi SWI_GetEnv /*  Returns command line in r0.  */
> + mov sp,r1 /*  and the highest memory address in r1.  */
>  
> - /*  stack limit is at end of data */
> - /*  allow slop for stack overflow handling and small frames */
> + /*  Stack limit is at end of data.  */
> + /*  Allow slop for stack overflow handling and small frames.  */
>   #ifdef THUMB1_ONLY
>   ldr r0, .LC2
>   adds r0, #128
> @@ -109,19 +111,19 @@
>   #endif
>   #else
>   #ifdef ARM_RDI_MONITOR
> - /*  Issue Angel SWI to read stack info */
> + /*  Issue Angel SWI to read stack info.  */
>   movs r0, #AngelSWI_Reason_HeapInfo
> - adr r1, .LC0 /*  point at ptr to 4 words to receive data */
> + adr r1, .LC0 /*  Point at ptr to 4 words to receive data.  */
>   #ifdef THUMB_VXM
>   bkpt AngelSWI
>   #elif defined(__thumb2__)
> - /*  We are in thumb mode for startup on armv7 architectures. */
> + /*  We are in thumb mode for startup on armv7 architectures.  */
>   AngelSWIAsm (AngelSWI)
>   #else
> - /*  We are always in ARM mode for startup on pre armv7 archs. */
> + /*  We are always in ARM mode for startup on pre armv7 archs.  */
>   AngelSWIAsm (AngelSWI_ARM)
>   #endif
> - ldr r0, .LC0 /*  point at values read */
> + ldr r0, .LC0 /*  Point at values read.  */
>  
>   /* Set __heap_limit.  */
>   ldr     r1, [r0, #4]
> @@ -148,14 +150,15 @@
>        to skip setting sp/sl to 0 here.
>      - Considering M-profile processors, We might want to initialize
>        sp by the first entry of vector table and return 0 to SYS_HEAPINFO
> -      semihosting call, which will be skipped here. */
> +      semihosting call, which will be skipped here.  */
>   cmp r1, #0
>   beq .LC26
>   mov sp, r1
>   .LC26:
>   cmp r2, #0
>   beq .LC27
> - /*  allow slop for stack overflow handling and small frames */
> +
> + /*  Allow slop for stack overflow handling and small frames.  */
>   #ifdef THUMB1_ONLY
>   adds r2, #128
>   adds r2, #128
> @@ -163,9 +166,10 @@
>   #else
>   add sl, r2, #256
>   #endif
> +
>   .LC27:
>   #else
> - /*  Set up the stack pointer to a fixed value */
> + /*  Set up the stack pointer to a fixed value.  */
>   /*  Changes by toralf:
>      - Allow linker script to provide stack via __stack symbol - see
>        defintion of .Lstack
> @@ -175,7 +179,7 @@
>        Loosely based on init.s from ARM/Motorola example code.
>                 Note: Mode switch via CPSR is not allowed once in non-privileged
>      mode, so we take care not to enter "User" to set up its sp,
> -    and also skip most operations if already in that mode. */
> +    and also skip most operations if already in that mode.  */
>  
>   ldr r3, .Lstack
>   cmp r3, #0
> @@ -192,42 +196,42 @@
>   /* Note: This 'mov' is essential when starting in User, and ensures we
>   always get *some* sp value for the initial mode, even if we
>   have somehow missed it below (in which case it gets the same
> - value as FIQ - not ideal, but better than nothing.) */
> + value as FIQ - not ideal, but better than nothing).  */
>   mov sp, r3
>   #ifdef PREFER_THUMB
>   /* XXX Fill in stack assignments for interrupt modes.  */
>   #else
>   mrs r2, CPSR
> - tst r2, #0x0F /* Test mode bits - in User of all are 0 */
> - beq .LC23 /* "eq" means r2 AND #0x0F is 0 */
> - msr     CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled */
> + tst r2, #0x0F /* Test mode bits - in User of all are 0.  */
> + beq .LC23 /* "eq" means r2 AND #0x0F is 0.  */
> + msr     CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled.  */
>   mov sp, r3
> - sub sl, sp, #0x1000 /* This mode also has its own sl (see below) */
> + sub sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
>  
>   mov r3, sl
> - msr     CPSR_c, #0xD7 /* Abort mode, interrupts disabled */
> + msr     CPSR_c, #0xD7 /* Abort mode, interrupts disabled.  */
>   mov sp, r3
>   sub r3, r3, #0x1000
>  
> - msr     CPSR_c, #0xDB /* Undefined mode, interrupts disabled */
> + msr     CPSR_c, #0xDB /* Undefined mode, interrupts disabled.  */
>   mov sp, r3
>   sub r3, r3, #0x1000
>  
> - msr     CPSR_c, #0xD2 /* IRQ mode, interrupts disabled */
> + msr     CPSR_c, #0xD2 /* IRQ mode, interrupts disabled.  */
>   mov sp, r3
>   sub r3, r3, #0x2000
>  
> - msr     CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled */
> + msr     CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled.  */
>  
>   mov sp, r3
> - sub r3, r3, #0x8000 /* Min size 32k */
> - bic r3, r3, #0x00FF /* Align with current 64k block */
> + sub r3, r3, #0x8000 /* Min size 32k.  */
> + bic r3, r3, #0x00FF /* Align with current 64k block.  */
>   bic r3, r3, #0xFF00
>  
>   str r3, [r3, #-4] /* Move value into user mode sp without */
> - ldmdb r3, {sp}^       /* changing modes, via '^' form of ldm */
> + ldmdb r3, {sp}^       /* changing modes, via '^' form of ldm.  */
>   orr r2, r2, #0xC0 /* Back to original mode, presumably SVC, */
> - msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1 */
> + msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1.  */
>   #endif
>   .LC23:
>   /* Setup a default stack-limit in-case the code has been
> @@ -243,24 +247,24 @@
>   subs r2, r3, r2
>   mov sl, r2
>   #else
> - sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl */
> + sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl.  */
>   #endif
>   #endif
>   #endif
>   /* Zero the memory in the .bss section.  */
> - movs a2, #0 /* Second arg: fill value */
> - mov fp, a2 /* Null frame pointer */
> - mov r7, a2 /* Null frame pointer for Thumb */
> + movs a2, #0 /* Second arg: fill value.  */
> + mov fp, a2 /* Null frame pointer.  */
> + mov r7, a2 /* Null frame pointer for Thumb.  */
>  
> - ldr a1, .LC1 /* First arg: start of memory block */
> + ldr a1, .LC1 /* First arg: start of memory block.  */
>   ldr a3, .LC2
> - subs a3, a3, a1 /* Third arg: length of block */
> + subs a3, a3, a1 /* Third arg: length of block.  */
>  
>  
>   #if __thumb__ && !defined(PREFER_THUMB)
> - /* Enter Thumb mode.... */
> - add a4, pc, #1 /* Get the address of the Thumb block */
> - bx a4 /* Go there and start Thumb decoding  */
> + /* Enter Thumb mode...  */
> + add a4, pc, #1 /* Get the address of the Thumb block.  */
> + bx a4 /* Go there and start Thumb decoding.  */
>  
>   .code 16
>   .global __change_mode
> @@ -271,9 +275,8 @@ __change_mode:
>   bl FUNCTION (memset)
>   #if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
>   /* Changes by toralf: Taken from libgloss/m68k/crt0.S
> - * initialize target specific stuff. Only execute these
> - * functions it they exist.
> - */
> +   initialize target specific stuff. Only execute these
> +   functions it they exist.  */
>   ldr r3, .Lhwinit
>   cmp r3, #0
>   beq .LC24
> @@ -285,24 +288,24 @@ __change_mode:
>   indirect_call r3
>  
>   .LC25:
> - movs r0, #0 /*  no arguments  */
> - movs r1, #0 /*  no argv either */
> + movs r0, #0 /* No arguments.  */
> + movs r1, #0 /* No argv either.  */
>   #else
> - /* Need to set up standard file handles */
> + /* Need to set up standard file handles.  */
>   bl FUNCTION (initialise_monitor_handles)
>  
>   #ifdef ARM_RDP_MONITOR
> - swi SWI_GetEnv /*  sets r0 to point to the command line */
> + swi SWI_GetEnv /* Sets r0 to point to the command line.  */
>   movs r1, r0
>   #else
>   movs r0, #AngelSWI_Reason_GetCmdLine
> - ldr r1, .LC30 /*  Space for command line */
> + ldr r1, .LC30 /* Space for command line.  */
>   AngelSWIAsm (AngelSWI)
>   ldr r1, .LC30
>   ldr r1, [r1]
>   #endif
> - /*  Parse string at r1 */
> - movs r0, #0 /*  count of arguments so far */
> + /*  Parse string at r1.  */
> + movs r0, #0 /* Count of arguments so far.  */
>   /* Push a NULL argument onto the end of the list.  */
>   #ifdef __thumb__
>   push {r0}
> @@ -310,7 +313,7 @@ __change_mode:
>   stmfd sp!, {r0}
>   #endif
>   .LC10:
> -/*  Skip leading blanks */
> +/*  Skip leading blanks.  */
>   #ifdef __thumb__
>   ldrb r3, [r1]
>   adds r1, #1
> @@ -322,7 +325,7 @@ __change_mode:
>   cmp r3, #' '
>   beq .LC10
>  
> -/*  See whether we are scanning a string */
> +/* See whether we are scanning a string.  */
>   cmp r3, #'"'
>   #ifdef __thumb__
>   beq .LC20
> @@ -333,17 +336,17 @@ __change_mode:
>   b .LC22
>  
>   .LC21:
> - movs r2, #' ' /*  terminator type */
> - subs r1, r1, #1 /*  adjust back to point at start char */
> + movs r2, #' ' /* Terminator type.  */
> + subs r1, r1, #1 /* Adjust back to point at start char.  */
>   .LC22:
>   #else
>   cmpne r3, #'\''
>   moveq r2, r3
> - movne r2, #' ' /*  terminator type */
> - subne r1, r1, #1 /*  adjust back to point at start char */
> + movne r2, #' ' /* Terminator type.  */
> + subne r1, r1, #1 /* Adjust back to point at start char.  */
>   #endif
>  
> -/*  Stack a pointer to the current argument */
> +/*  Stack a pointer to the current argument.  */
>   #ifdef __thumb__
>   push {r1}
>   #else
> @@ -359,16 +362,16 @@ __change_mode:
>   #endif
>   cmp r3, #0
>   beq .LC12
> - cmp r2, r3 /*  reached terminator? */
> + cmp r2, r3 /* Reached terminator ?  */
>   bne .LC11
>   movs r2, #0
>   subs r3, r1, #1
> - strb r2, [r3] /*  terminate the arg string */
> + strb r2, [r3] /* Terminate the arg string.  */
>   b .LC10
>  
>   .LC12:
> - mov r1, sp /*  point at stacked arg pointers */
> - /* We've now got the stacked args in order reverse the */
> + mov r1, sp /* Point at stacked arg pointers.  */
> + /* We've now got the stacked args in order, reverse them.  */
>   #ifdef __thumb__
>   movs r2, r0
>   lsls r2, #2
> @@ -390,10 +393,10 @@ __change_mode:
>   bics r4, r5
>   mov sp, r4
>   #else
> - add r2, sp, r0, LSL #2 /* End of args */
> - mov r3, sp /* Start of args */
> + add r2, sp, r0, LSL #2 /* End of args.  */
> + mov r3, sp /* Start of args.  */
>   .LC13: cmp r2, r3
> - ldrhi r4,[r2, #-4] /* Reverse ends of list */
> + ldrhi r4,[r2, #-4] /* Reverse ends of list.  */
>   ldrhi r5, [r3]
>   strhi r5, [r2, #-4]!
>   strhi r4, [r3], #4
> @@ -431,7 +434,6 @@ __change_mode:
>  
>   #if __thumb__ && !defined(PREFER_THUMB)
>   /* Come out of Thumb mode.  This code should be redundant.  */
> -
>   mov a4, pc
>   bx a4
>  
> @@ -447,7 +449,6 @@ change_back:
>  
>   /* For Thumb, constants must be after the code since only
>     positive offsets are supported for PC relative addresses.  */
> -
>   .align 0
>   .LC0:
>   #ifdef ARM_RDI_MONITOR
> @@ -457,13 +458,13 @@ change_back:
>   /* Changes by toralf: Provide alternative "stack" variable whose value
>     may be defined externally; .Lstack will be used instead of .LC0 if
>     it points to a non-0 value. Also set up references to "hooks" that
> -           may be used by the application to provide additional init code. */
> -
> +           may be used by the application to provide additional init code.  */
>   #ifdef __pe__
>   .word 0x800000
>   #else
>   .word 0x80000 /* Top of RAM on the PIE board.  */
>   #endif
> +
>   .Lstack:
>   .word __stack
>   .Lhwinit:
> @@ -476,7 +477,7 @@ change_back:
>     runtime (meaning "ignore setting") for the variables, when the user
>     does not provide the symbols. (The linker uses a weak symbol if,
>     and only if, a normal version of the same symbol isn't provided
> -   e.g. by a linker script or another object file.) */
> +   e.g. by a linker script or another object file.)  */
>  
>   .weak __stack
>   .weak FUNCTION (hardware_init_hook)
> diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
> index 8c9f7be38..7a6b40d9a 100644
> --- a/newlib/libc/sys/arm/crt0.S
> +++ b/newlib/libc/sys/arm/crt0.S
> @@ -50,13 +50,13 @@
>   .global \name
>   .thumb_func
>   \name:
> -.endm
> +.endm
>   #else
>   .code 32
>   .macro FUNC_START name
> - .global \name
> + .global \name
>   \name:
> -.endm
> +.endm
>   #endif
>  
>   .macro indirect_call reg
> @@ -68,8 +68,10 @@
>   #endif
>   .endm
>  
> +/*******************************************************************************
> +* Main library startup code.
> +*******************************************************************************/
>   .align 0
> -
>   FUNC_START _mainCRTStartup
>   FUNC_START _start
>   #if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> @@ -399,7 +401,7 @@ __change_mode:
>   bl FUNCTION (_init)
>   movs r0, r4
>   movs r1, r5
> -#endif
> +#endif
>   bl FUNCTION (main)
>  
>   bl FUNCTION (exit) /* Should not return.  */
> @@ -420,7 +422,7 @@ change_back:
>   #endif
>  
>   /* For Thumb, constants must be after the code since only
> -   positive offsets are supported for PC relative addresses.  */
> +   positive offsets are supported for PC relative addresses.  */
>   .align 0
>   .LC0:
>   #ifdef ARM_RDI_MONITOR
> @@ -430,7 +432,7 @@ change_back:
>   /* Changes by toralf: Provide alternative "stack" variable whose value
>     may be defined externally; .Lstack will be used instead of .LC0 if
>     it points to a non-0 value. Also set up references to "hooks" that
> -           may be used by the application to provide additional init code.  */
> +           may be used by the application to provide additional init code.  */
>   #ifdef __pe__
>   .word 0x800000
>   #else
> @@ -449,7 +451,7 @@ change_back:
>     runtime (meaning "ignore setting") for the variables, when the user
>     does not provide the symbols. (The linker uses a weak symbol if,
>     and only if, a normal version of the same symbol isn't provided
> -   e.g. by a linker script or another object file).  */
> +   e.g. by a linker script or another object file.)  */
>  
>   .weak __stack
>   .weak FUNCTION (hardware_init_hook)
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] [Arm] Stack Pointer and Stack Limit initialization refactored.

Richard Earnshaw (lists)
In reply to this post by Alexander Fedotov


On 12/04/2019 14:30, [hidden email] wrote:
> From: Alexander Fedotov <[hidden email]>
>
> SP initialization changes:
>    1. set default value in semihosting case as well
>    2. moved existing SP & SL init code for processor modes in separate routine and made it as "hook"
>    3. init SP for processor modes in Thumb mode as well
>

Thanks for this, I think overall it's a definite improvement on what we
have now.  A couple of comments.

I suspect this code will not work as intended if the system starts in
secure mode.  In particular the methods of getting in and out of secure
state are not as simple as writing to the CPSR mode bits.  But the
existing code won't handle that either, so this is not regression, I
suspect.

A few of the comments are not really in house style (Sentences start
with capital letter, full stop at the end and then two spaces before the
comment close.

If you could clean up the comment style and add a note about secure
state not being supported at present, I think this is good to go in.

R.

> Add new macro FN_RETURN, FN_EH_START and FN_EH_END.
> ---
>   libgloss/arm/arm.h         |  26 ++++
>   libgloss/arm/crt0.S        | 277 ++++++++++++++++++++++++++-----------
>   newlib/libc/sys/arm/arm.h  |  26 ++++
>   newlib/libc/sys/arm/crt0.S | 277 ++++++++++++++++++++++++++-----------
>   4 files changed, 440 insertions(+), 166 deletions(-)
>
> diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
> index 0489f2d92..04b3a5ac7 100644
> --- a/libgloss/arm/arm.h
> +++ b/libgloss/arm/arm.h
> @@ -61,4 +61,30 @@
>   # define HAVE_CALL_INDIRECT
>   #endif
>  
> +/* A and R profiles (and legacy Arm).
> + Current Program Status Register (CPSR)
> + M[4:0] Mode bits. M[4] is always 1 for 32-bit modes.
> + T[5] 1: Thumb, 0: ARM instruction set
> + F[6] 1: disables FIQ
> + I[7] 1: disables IRQ
> + A[8] 1: disables imprecise aborts
> + E[9] 0: Little-endian, 1: Big-endian
> + J[24] 1: Jazelle instruction set
> + */
> +#define CPSR_M_USR 0x00 /* User mode */
> +#define CPSR_M_FIQ 0x01 /* Fast Interrupt mode */
> +#define CPSR_M_IRQ 0x02 /* Interrupt mode */
> +#define CPSR_M_SVR 0x03 /* Supervisor mode */
> +#define CPSR_M_MON 0x06 /* Monitor mode */
> +#define CPSR_M_ABT 0x07 /* Abort mode */
> +#define CPSR_M_HYP 0x0A /* Hypervisor mode */
> +#define CPSR_M_UND 0x0B /* Undefined mode */
> +#define CPSR_M_SYS 0x0F /* System mode */
> +#define CPSR_M_32BIT 0x10 /* 32-bit mode */
> +#define CPSR_T_BIT 0x20 /* Thumb bit */
> +#define CPSR_F_MASK 0x40 /* FIQ bit */
> +#define CPSR_I_MASK 0x80 /* IRQ bit */
> +
> +#define CPSR_M_MASK 0x0F /* Mode mask except M[4] */
> +
>   #endif /* _LIBGLOSS_ARM_H */
> diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
> index 1deb73aa5..95aa3b578 100644
> --- a/libgloss/arm/crt0.S
> +++ b/libgloss/arm/crt0.S
> @@ -59,6 +59,21 @@
>   .endm
>   #endif
>  
> +/* Annotation for EABI unwinding tables. */
> +.macro FN_EH_START
> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> + .fnstart
> +#endif
> +.endm
> +
> +.macro FN_EH_END
> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> + /* Protect against unhandled exceptions.  */
> + .cantunwind
> + .fnend
> +#endif
> +.endm
> +
>   .macro indirect_call reg
>   #ifdef HAVE_CALL_INDIRECT
>   blx \reg
> @@ -68,16 +83,170 @@
>   #endif
>   .endm
>  
> +/* For armv4t and newer, toolchains will transparently convert
> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> +   for anything older than armv4t, but this should handle that
> +   corner case in case anyone needs it anyway */
> +.macro  FN_RETURN
> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> + mov pc, lr
> +#else
> + bx lr
> +#endif
> +.endm
> +
> +
> +
> +/******************************************************************************
> +* User mode only:           This routine makes default target specific Stack
> +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
> +*   | SYS |               and setups a default Stack Limit in-case the code has
> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
> +*   |     |               System (User) modes.
> +*   |     |
> +*   +-----+ <- initial SP,
> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
> +*           and SL_usr     currently no support for checking that the heap and
> +*                          stack have not collided, or that this default 64k is
> +* All modes:               is enough for the program being executed. However,
> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
> +*   |     |    SL_usr      immediately cause an overflow event.
> +*   | SYS |
> +*   | USR | -=0x10000        We go through all execution modes and set up SP
> +*   |     |                for each of them.
> +*   +-----+ <- SP_sys,
> +*   |     |    SP_usr      Note:
> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
> +*   |     |                  non-privileged mode, so we take care not to enter
> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
> +*   |     |                  operations if already in that mode.
> +*   | IRQ | -= 0x2000
> +*   |     |                Input parameters:
> +* ^ +-----+ <- SP_und       - sp - Initialized SP
> +* s |     |                 - r2 - May contain SL value from semihosting
> +* t | UND | -= 0x1000              SYS_HEAPINFO call
> +* a |     |                Scratch registers:
> +* c +-----+ <- SP_und       - r1 - new value of CPSR
> +* k |     |                 - r2 - intermediate value (in standalone mode)
> +*   | ABT | -= 0x1000       - r3 - new SP value
> +* g |     |                 - r4 - save/restore CPSR on entry/exit
> +* r +-----+ <- SP_abt,
> +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
> +* t |     |
> +* h +-----+ <- initial SP,
> +*           becomes SP_fiq
> +*
> +******************************************************************************/
> + .align 0
> + FUNC_START _stack_init
> + .weak FUNCTION (_stack_init)
> + FN_EH_START
> +
> + /* M profile doesn't have CPSR register.  */
> +#if (__ARM_ARCH_PROFILE != 'M')
> + /* Following code is compatible for both ARM and Thumb ISA */
> + mrs r4, CPSR
> + /* Test mode bits - in User of all are 0 */
> + tst r4, #(CPSR_M_MASK)
> + /* "eq" means r4 AND #0x0F is 0 */
> + beq .Lskip_cpu_modes
> +
> + mov r3, sp /* save input SP value */
> +
> + /* FIQ mode, interrupts disabled */
> + mov r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> + sub sl, sp, #0x1000 /* FIQ mode has its own SL */
> +
> + /* Abort mode, interrupts disabled */
> + mov r3, sl
> + mov r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> + sub r3, r3, #0x1000
> +
> + /* Undefined mode, interrupts disabled */
> + mov r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> + sub r3, r3, #0x1000
> +
> + /* IRQ mode, interrupts disabled */
> + mov r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> + sub r3, r3, #0x2000
> +
> + /* Supervisory mode, interrupts disabled */
> + mov r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> +
> + sub r3, r3, #0x8000 /* Min size 32k */
> + bic r3, r3, #0x00FF /* Align with current 64k block */
> + bic r3, r3, #0xFF00
> +
> +# if __ARM_ARCH >= 4
> + /* System (shares regs with User) mode, interrupts disabled */
> + mov r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> +# else
> + /* Keep this for ARMv3, but GCC actually dropped it. */
> + /* Move value into user mode sp without changing modes, */
> + /* via '^' form of ldm */
> + str r3, [r3, #-4]
> + ldmdb r3, {sp}^
> +# endif
> +
> + /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
> + orr r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r4
> +
> +.Lskip_cpu_modes:
> +#endif
> +
> + /* Set SL register */
> +#if defined (ARM_RDI_MONITOR) /* semihosting */
> + cmp r2, #0
> + beq .Lsl_forced_zero
> + /* allow slop for stack overflow handling and small frames */
> +# ifdef THUMB1_ONLY
> + adds r2, #128
> + adds r2, #128
> + mov sl, r2
> +# else
> + add sl, r2, #256
> +# endif
> +.Lsl_forced_zero:
> +
> +#else /* standalone */
> + /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
> + #ifdef THUMB1_ONLY
> + movs r2, #64
> + lsls r2, r2, #10
> + subs r2, r3, r2
> + mov sl, r2
> + #else
> + /* Still assumes 256bytes below sl */
> + sub sl, r3, #64 << 10
> + #endif
> +#endif
> +
> + FN_RETURN
> + FN_EH_END
> +
> +
>   /*******************************************************************************
>   * Main library startup code.
>   *******************************************************************************/
>   .align 0
>   FUNC_START _mainCRTStartup
>   FUNC_START _start
> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> - /* Annotation for EABI unwinding tables.  */
> - .fnstart
> -#endif
> + FN_EH_START
>  
>   /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards, however __ARM_ARCH_7A
>   has been defined since 4.2 onwards, which is when v7-a support was added
> @@ -150,36 +319,27 @@
>        to skip setting sp/sl to 0 here.
>      - Considering M-profile processors, We might want to initialize
>        sp by the first entry of vector table and return 0 to SYS_HEAPINFO
> -      semihosting call, which will be skipped here.  */
> +      semihosting call, which will be skipped here.
> +    - Considering R-profile processors there is no automatic SP init by hardware
> +      so we need to initialize it by default value. */
> + ldr r3, .Lstack
>   cmp r1, #0
>   beq .LC26
> - mov sp, r1
> + mov r3, r1
>   .LC26:
> - cmp r2, #0
> - beq .LC27
> + mov sp, r3
>  
> - /*  Allow slop for stack overflow handling and small frames.  */
> -#ifdef THUMB1_ONLY
> - adds r2, #128
> - adds r2, #128
> - mov sl, r2
> -#else
> - add sl, r2, #256
> -#endif
> + /* r2 (SL value) will be used in _stack_init */
> + bl FUNCTION (_stack_init)
>  
> -.LC27:
> -#else
> - /*  Set up the stack pointer to a fixed value.  */
> +
> +#else /* standalone */
> + /*  Set up the stack pointer to a fixed value. */
>   /*  Changes by toralf:
>      - Allow linker script to provide stack via __stack symbol - see
>        defintion of .Lstack
>      - Provide "hooks" that may be used by the application to add
> -      custom init code - see .Lhwinit and .Lswinit
> -    - Go through all execution modes and set up stack for each of them.
> -      Loosely based on init.s from ARM/Motorola example code.
> -              Note: Mode switch via CPSR is not allowed once in non-privileged
> -    mode, so we take care not to enter "User" to set up its sp,
> -    and also skip most operations if already in that mode.  */
> +      custom init code - see .Lhwinit and .Lswinit */
>  
>   ldr r3, .Lstack
>   cmp r3, #0
> @@ -198,57 +358,10 @@
>   have somehow missed it below (in which case it gets the same
>   value as FIQ - not ideal, but better than nothing).  */
>   mov sp, r3
> -#ifdef PREFER_THUMB
> - /* XXX Fill in stack assignments for interrupt modes.  */
> -#else
> - mrs r2, CPSR
> - tst r2, #0x0F /* Test mode bits - in User of all are 0.  */
> - beq .LC23 /* "eq" means r2 AND #0x0F is 0.  */
> - msr     CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled.  */
> - mov sp, r3
> - sub sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
> -
> - mov r3, sl
> - msr     CPSR_c, #0xD7 /* Abort mode, interrupts disabled.  */
> - mov sp, r3
> - sub r3, r3, #0x1000
> -
> - msr     CPSR_c, #0xDB /* Undefined mode, interrupts disabled.  */
> - mov sp, r3
> - sub r3, r3, #0x1000
>  
> - msr     CPSR_c, #0xD2 /* IRQ mode, interrupts disabled.  */
> - mov sp, r3
> - sub r3, r3, #0x2000
> -
> - msr     CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled.  */
> + /* we don't care of r2 value in standalone */
> + bl FUNCTION (_stack_init)
>  
> - mov sp, r3
> - sub r3, r3, #0x8000 /* Min size 32k.  */
> - bic r3, r3, #0x00FF /* Align with current 64k block.  */
> - bic r3, r3, #0xFF00
> -
> - str r3, [r3, #-4] /* Move value into user mode sp without */
> - ldmdb r3, {sp}^       /* changing modes, via '^' form of ldm.  */
> - orr r2, r2, #0xC0 /* Back to original mode, presumably SVC, */
> - msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1.  */
> -#endif
> -.LC23:
> - /* Setup a default stack-limit in-case the code has been
> -   compiled with "-mapcs-stack-check".  Hard-wiring this value
> -   is not ideal, since there is currently no support for
> -   checking that the heap and stack have not collided, or that
> -   this default 64k is enough for the program being executed.
> -   However, it ensures that this simple crt0 world will not
> -   immediately cause an overflow event:  */
> -#ifdef THUMB1_ONLY
> - movs r2, #64
> - lsls r2, r2, #10
> - subs r2, r3, r2
> - mov sl, r2
> -#else
> - sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl.  */
> -#endif
>   #endif
>   #endif
>   /* Zero the memory in the .bss section.  */
> @@ -447,6 +560,8 @@ change_back:
>   swi SWI_Exit
>   #endif
>  
> + FN_EH_END
> +
>   /* For Thumb, constants must be after the code since only
>     positive offsets are supported for PC relative addresses.  */
>   .align 0
> @@ -464,9 +579,6 @@ change_back:
>   #else
>   .word 0x80000 /* Top of RAM on the PIE board.  */
>   #endif
> -
> -.Lstack:
> - .word __stack
>   .Lhwinit:
>   .word FUNCTION (hardware_init_hook)
>   .Lswinit:
> @@ -479,17 +591,16 @@ change_back:
>     and only if, a normal version of the same symbol isn't provided
>     e.g. by a linker script or another object file.)  */
>  
> - .weak __stack
>   .weak FUNCTION (hardware_init_hook)
>   .weak FUNCTION (software_init_hook)
>   #endif
>  
>   #endif
> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> - /* Protect against unhandled exceptions.  */
> - .cantunwind
> - .fnend
> -#endif
> +
> +.Lstack:
> + .word __stack
> + .weak __stack
> +
>   .LC1:
>   .word __bss_start__
>   .LC2:
> diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
> index 0489f2d92..04b3a5ac7 100644
> --- a/newlib/libc/sys/arm/arm.h
> +++ b/newlib/libc/sys/arm/arm.h
> @@ -61,4 +61,30 @@
>   # define HAVE_CALL_INDIRECT
>   #endif
>  
> +/* A and R profiles (and legacy Arm).
> + Current Program Status Register (CPSR)
> + M[4:0] Mode bits. M[4] is always 1 for 32-bit modes.
> + T[5] 1: Thumb, 0: ARM instruction set
> + F[6] 1: disables FIQ
> + I[7] 1: disables IRQ
> + A[8] 1: disables imprecise aborts
> + E[9] 0: Little-endian, 1: Big-endian
> + J[24] 1: Jazelle instruction set
> + */
> +#define CPSR_M_USR 0x00 /* User mode */
> +#define CPSR_M_FIQ 0x01 /* Fast Interrupt mode */
> +#define CPSR_M_IRQ 0x02 /* Interrupt mode */
> +#define CPSR_M_SVR 0x03 /* Supervisor mode */
> +#define CPSR_M_MON 0x06 /* Monitor mode */
> +#define CPSR_M_ABT 0x07 /* Abort mode */
> +#define CPSR_M_HYP 0x0A /* Hypervisor mode */
> +#define CPSR_M_UND 0x0B /* Undefined mode */
> +#define CPSR_M_SYS 0x0F /* System mode */
> +#define CPSR_M_32BIT 0x10 /* 32-bit mode */
> +#define CPSR_T_BIT 0x20 /* Thumb bit */
> +#define CPSR_F_MASK 0x40 /* FIQ bit */
> +#define CPSR_I_MASK 0x80 /* IRQ bit */
> +
> +#define CPSR_M_MASK 0x0F /* Mode mask except M[4] */
> +
>   #endif /* _LIBGLOSS_ARM_H */
> diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
> index 7a6b40d9a..0929a435e 100644
> --- a/newlib/libc/sys/arm/crt0.S
> +++ b/newlib/libc/sys/arm/crt0.S
> @@ -59,6 +59,21 @@
>   .endm
>   #endif
>  
> +/* Annotation for EABI unwinding tables. */
> +.macro FN_EH_START
> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> + .fnstart
> +#endif
> +.endm
> +
> +.macro FN_EH_END
> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> + /* Protect against unhandled exceptions.  */
> + .cantunwind
> + .fnend
> +#endif
> +.endm
> +
>   .macro indirect_call reg
>   #ifdef HAVE_CALL_INDIRECT
>   blx \reg
> @@ -68,16 +83,170 @@
>   #endif
>   .endm
>  
> +/* For armv4t and newer, toolchains will transparently convert
> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> +   for anything older than armv4t, but this should handle that
> +   corner case in case anyone needs it anyway */
> +.macro  FN_RETURN
> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> + mov pc, lr
> +#else
> + bx lr
> +#endif
> +.endm
> +
> +
> +
> +/******************************************************************************
> +* User mode only:           This routine makes default target specific Stack
> +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
> +*   | SYS |               and setups a default Stack Limit in-case the code has
> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
> +*   |     |               System (User) modes.
> +*   |     |
> +*   +-----+ <- initial SP,
> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
> +*           and SL_usr     currently no support for checking that the heap and
> +*                          stack have not collided, or that this default 64k is
> +* All modes:               is enough for the program being executed. However,
> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
> +*   |     |    SL_usr      immediately cause an overflow event.
> +*   | SYS |
> +*   | USR | -=0x10000        We go through all execution modes and set up SP
> +*   |     |                for each of them.
> +*   +-----+ <- SP_sys,
> +*   |     |    SP_usr      Note:
> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
> +*   |     |                  non-privileged mode, so we take care not to enter
> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
> +*   |     |                  operations if already in that mode.
> +*   | IRQ | -= 0x2000
> +*   |     |                Input parameters:
> +* ^ +-----+ <- SP_und       - sp - Initialized SP
> +* s |     |                 - r2 - May contain SL value from semihosting
> +* t | UND | -= 0x1000              SYS_HEAPINFO call
> +* a |     |                Scratch registers:
> +* c +-----+ <- SP_und       - r1 - new value of CPSR
> +* k |     |                 - r2 - intermediate value (in standalone mode)
> +*   | ABT | -= 0x1000       - r3 - new SP value
> +* g |     |                 - r4 - save/restore CPSR on entry/exit
> +* r +-----+ <- SP_abt,
> +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
> +* t |     |
> +* h +-----+ <- initial SP,
> +*           becomes SP_fiq
> +*
> +******************************************************************************/
> + .align 0
> + FUNC_START _stack_init
> + .weak FUNCTION (_stack_init)
> + FN_EH_START
> +
> + /* M profile doesn't have CPSR register.  */
> +#if (__ARM_ARCH_PROFILE != 'M')
> + /* Following code is compatible for both ARM and Thumb ISA */
> + mrs r4, CPSR
> + /* Test mode bits - in User of all are 0 */
> + tst r4, #(CPSR_M_MASK)
> + /* "eq" means r4 AND #0x0F is 0 */
> + beq .Lskip_cpu_modes
> +
> + mov r3, sp /* save input SP value */
> +
> + /* FIQ mode, interrupts disabled */
> + mov r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> + sub sl, sp, #0x1000 /* FIQ mode has its own SL */
> +
> + /* Abort mode, interrupts disabled */
> + mov r3, sl
> + mov r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> + sub r3, r3, #0x1000
> +
> + /* Undefined mode, interrupts disabled */
> + mov r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> + sub r3, r3, #0x1000
> +
> + /* IRQ mode, interrupts disabled */
> + mov r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> + sub r3, r3, #0x2000
> +
> + /* Supervisory mode, interrupts disabled */
> + mov r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> +
> + sub r3, r3, #0x8000 /* Min size 32k */
> + bic r3, r3, #0x00FF /* Align with current 64k block */
> + bic r3, r3, #0xFF00
> +
> +# if __ARM_ARCH >= 4
> + /* System (shares regs with User) mode, interrupts disabled */
> + mov r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r1
> + mov sp, r3
> +# else
> + /* Keep this for ARMv3, but GCC actually dropped it. */
> + /* Move value into user mode sp without changing modes, */
> + /* via '^' form of ldm */
> + str r3, [r3, #-4]
> + ldmdb r3, {sp}^
> +# endif
> +
> + /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
> + orr r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> + msr CPSR_c, r4
> +
> +.Lskip_cpu_modes:
> +#endif
> +
> + /* Set SL register */
> +#if defined (ARM_RDI_MONITOR) /* semihosting */
> + cmp r2, #0
> + beq .Lsl_forced_zero
> + /* allow slop for stack overflow handling and small frames */
> +# ifdef THUMB1_ONLY
> + adds r2, #128
> + adds r2, #128
> + mov sl, r2
> +# else
> + add sl, r2, #256
> +# endif
> +.Lsl_forced_zero:
> +
> +#else /* standalone */
> + /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
> + #ifdef THUMB1_ONLY
> + movs r2, #64
> + lsls r2, r2, #10
> + subs r2, r3, r2
> + mov sl, r2
> + #else
> + /* Still assumes 256bytes below sl */
> + sub sl, r3, #64 << 10
> + #endif
> +#endif
> +
> + FN_RETURN
> + FN_EH_END
> +
> +
>   /*******************************************************************************
>   * Main library startup code.
>   *******************************************************************************/
>   .align 0
>   FUNC_START _mainCRTStartup
>   FUNC_START _start
> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> - /* Annotation for EABI unwinding tables.  */
> - .fnstart
> -#endif
> + FN_EH_START
>  
>   /* Start by setting up a stack.  */
>   #ifdef ARM_RDP_MONITOR
> @@ -130,36 +299,27 @@
>        to skip setting sp/sl to 0 here.
>      - Considering M-profile processors, We might want to initialize
>        sp by the first entry of vector table and return 0 to SYS_HEAPINFO
> -      semihosting call, which will be skipped here.  */
> +      semihosting call, which will be skipped here.
> +    - Considering R-profile processors there is no automatic SP init by hardware
> +      so we need to initialize it by default value. */
> + ldr r3, .Lstack
>   cmp r1, #0
>   beq .LC26
> - mov sp, r1
> + mov r3, r1
>   .LC26:
> - cmp r2, #0
> - beq .LC27
> + mov sp, r3
>  
> - /*  Allow slop for stack overflow handling and small frames.  */
> -#ifdef THUMB1_ONLY
> - adds r2, #128
> - adds r2, #128
> - mov sl, r2
> -#else
> - add sl, r2, #256
> -#endif
> + /* r2 (SL value) will be used in _stack_init */
> + bl FUNCTION (_stack_init)
>  
> -.LC27:
> -#else
> - /*  Set up the stack pointer to a fixed value.  */
> +
> +#else /* standalone */
> + /*  Set up the stack pointer to a fixed value. */
>   /*  Changes by toralf:
>      - Allow linker script to provide stack via __stack symbol - see
>        defintion of .Lstack
>      - Provide "hooks" that may be used by the application to add
> -      custom init code - see .Lhwinit and .Lswinit
> -    - Go through all execution modes and set up stack for each of them.
> -      Loosely based on init.s from ARM/Motorola example code.
> -              Note: Mode switch via CPSR is not allowed once in non-privileged
> -    mode, so we take care not to enter "User" to set up its sp,
> -    and also skip most operations if already in that mode.  */
> +      custom init code - see .Lhwinit and .Lswinit */
>  
>   ldr r3, .Lstack
>   cmp r3, #0
> @@ -178,57 +338,10 @@
>   have somehow missed it below (in which case it gets the same
>   value as FIQ - not ideal, but better than nothing).  */
>   mov sp, r3
> -#ifdef PREFER_THUMB
> - /* XXX Fill in stack assignments for interrupt modes.  */
> -#else
> - mrs r2, CPSR
> - tst r2, #0x0F /* Test mode bits - in User of all are 0.  */
> - beq .LC23 /* "eq" means r2 AND #0x0F is 0.  */
> - msr     CPSR_c, #0xD1 /* FIRQ mode, interrupts disabled.  */
> - mov sp, r3
> - sub sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
> -
> - mov r3, sl
> - msr     CPSR_c, #0xD7 /* Abort mode, interrupts disabled.  */
> - mov sp, r3
> - sub r3, r3, #0x1000
> -
> - msr     CPSR_c, #0xDB /* Undefined mode, interrupts disabled.  */
> - mov sp, r3
> - sub r3, r3, #0x1000
>  
> - msr     CPSR_c, #0xD2 /* IRQ mode, interrupts disabled.  */
> - mov sp, r3
> - sub r3, r3, #0x2000
> -
> - msr     CPSR_c, #0xD3 /* Supervisory mode, interrupts disabled.  */
> + /* we don't care of r2 value in standalone */
> + bl FUNCTION (_stack_init)
>  
> - mov sp, r3
> - sub r3, r3, #0x8000 /* Min size 32k.  */
> - bic r3, r3, #0x00FF /* Align with current 64k block.  */
> - bic r3, r3, #0xFF00
> -
> - str r3, [r3, #-4] /* Move value into user mode sp without */
> - ldmdb r3, {sp}^       /* changing modes, via '^' form of ldm.  */
> - orr r2, r2, #0xC0 /* Back to original mode, presumably SVC, */
> - msr CPSR_c, r2 /* with FIQ/IRQ disable bits forced to 1.  */
> -#endif
> -.LC23:
> - /* Setup a default stack-limit in-case the code has been
> -   compiled with "-mapcs-stack-check".  Hard-wiring this value
> -   is not ideal, since there is currently no support for
> -   checking that the heap and stack have not collided, or that
> -   this default 64k is enough for the program being executed.
> -   However, it ensures that this simple crt0 world will not
> -   immediately cause an overflow event:  */
> -#ifdef THUMB1_ONLY
> - movs r2, #64
> - lsls r2, r2, #10
> - subs r2, r3, r2
> - mov sl, r2
> -#else
> - sub sl, r3, #64 << 10 /* Still assumes 256bytes below sl.  */
> -#endif
>   #endif
>   #endif
>   /* Zero the memory in the .bss section.  */
> @@ -421,6 +534,8 @@ change_back:
>   swi SWI_Exit
>   #endif
>  
> + FN_EH_END
> +
>   /* For Thumb, constants must be after the code since only
>     positive offsets are supported for PC relative addresses.  */
>   .align 0
> @@ -438,9 +553,6 @@ change_back:
>   #else
>   .word 0x80000 /* Top of RAM on the PIE board.  */
>   #endif
> -
> -.Lstack:
> - .word __stack
>   .Lhwinit:
>   .word FUNCTION (hardware_init_hook)
>   .Lswinit:
> @@ -453,17 +565,16 @@ change_back:
>     and only if, a normal version of the same symbol isn't provided
>     e.g. by a linker script or another object file.)  */
>  
> - .weak __stack
>   .weak FUNCTION (hardware_init_hook)
>   .weak FUNCTION (software_init_hook)
>   #endif
>  
>   #endif
> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> - /* Protect against unhandled exceptions.  */
> - .cantunwind
> - .fnend
> -#endif
> +
> +.Lstack:
> + .word __stack
> + .weak __stack
> +
>   .LC1:
>   .word __bss_start__
>   .LC2:
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/2] Align comments and spaces in libgloss/arm/crt0.S and newlib/libc/sys/arm/crt0.S to ease further code alignment.

Alexander Fedotov
In reply to this post by Richard Earnshaw (lists)
Hi Richard

Could you please apply it for me. I have no write permissions.

Best regards,
Alex

On Thu, Jul 18, 2019 at 12:47 PM Richard Earnshaw (lists)
<[hidden email]> wrote:

>
> OK.
>
> (sorry for the delay replying).
>
> R.
>
> On 12/04/2019 14:30, [hidden email] wrote:
> > From: Alexander Fedotov <[hidden email]>
> >
> > ---
> >   libgloss/arm/crt0.S        | 135 +++++++++++++++++++------------------
> >   newlib/libc/sys/arm/crt0.S |  18 ++---
> >   2 files changed, 78 insertions(+), 75 deletions(-)
> >
> > diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
> > index c708f63d8..1deb73aa5 100644
> > --- a/libgloss/arm/crt0.S
> > +++ b/libgloss/arm/crt0.S
> > @@ -68,8 +68,10 @@
> >   #endif
> >   .endm
> >
> > +/*******************************************************************************
> > +* Main library startup code.
> > +*******************************************************************************/
> >       .align  0
> > -
> >       FUNC_START      _mainCRTStartup
> >       FUNC_START      _start
> >   #if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > @@ -90,14 +92,14 @@
> >   #endif
> >   #endif
> >
> > -/* Start by setting up a stack */
> > +/* Start by setting up a stack.  */
> >   #ifdef ARM_RDP_MONITOR
> > -     /*  Issue Demon SWI to read stack info */
> > -     swi     SWI_GetEnv      /*  Returns command line in r0 */
> > -     mov     sp,r1           /*  and the highest memory address in r1 */
> > +     /*  Issue Demon SWI to read stack info.  */
> > +     swi     SWI_GetEnv      /*  Returns command line in r0.  */
> > +     mov     sp,r1           /*  and the highest memory address in r1.  */
> >
> > -     /*  stack limit is at end of data */
> > -     /*  allow slop for stack overflow handling and small frames */
> > +     /*  Stack limit is at end of data.  */
> > +     /*  Allow slop for stack overflow handling and small frames.  */
> >   #ifdef THUMB1_ONLY
> >       ldr     r0, .LC2
> >       adds    r0, #128
> > @@ -109,19 +111,19 @@
> >   #endif
> >   #else
> >   #ifdef ARM_RDI_MONITOR
> > -     /*  Issue Angel SWI to read stack info */
> > +     /*  Issue Angel SWI to read stack info.  */
> >       movs    r0, #AngelSWI_Reason_HeapInfo
> > -     adr     r1, .LC0        /*  point at ptr to 4 words to receive data */
> > +     adr     r1, .LC0        /*  Point at ptr to 4 words to receive data.  */
> >   #ifdef THUMB_VXM
> >       bkpt    AngelSWI
> >   #elif defined(__thumb2__)
> > -     /*  We are in thumb mode for startup on armv7 architectures. */
> > +     /*  We are in thumb mode for startup on armv7 architectures.  */
> >       AngelSWIAsm (AngelSWI)
> >   #else
> > -     /*  We are always in ARM mode for startup on pre armv7 archs. */
> > +     /*  We are always in ARM mode for startup on pre armv7 archs.  */
> >       AngelSWIAsm (AngelSWI_ARM)
> >   #endif
> > -     ldr     r0, .LC0        /*  point at values read */
> > +     ldr     r0, .LC0        /*  Point at values read.  */
> >
> >       /* Set __heap_limit.  */
> >       ldr     r1, [r0, #4]
> > @@ -148,14 +150,15 @@
> >             to skip setting sp/sl to 0 here.
> >           - Considering M-profile processors, We might want to initialize
> >             sp by the first entry of vector table and return 0 to SYS_HEAPINFO
> > -           semihosting call, which will be skipped here. */
> > +           semihosting call, which will be skipped here.  */
> >       cmp     r1, #0
> >       beq     .LC26
> >       mov     sp, r1
> >   .LC26:
> >       cmp     r2, #0
> >       beq     .LC27
> > -     /*  allow slop for stack overflow handling and small frames */
> > +
> > +     /*  Allow slop for stack overflow handling and small frames.  */
> >   #ifdef THUMB1_ONLY
> >       adds    r2, #128
> >       adds    r2, #128
> > @@ -163,9 +166,10 @@
> >   #else
> >       add     sl, r2, #256
> >   #endif
> > +
> >   .LC27:
> >   #else
> > -     /*  Set up the stack pointer to a fixed value */
> > +     /*  Set up the stack pointer to a fixed value.  */
> >       /*  Changes by toralf:
> >           - Allow linker script to provide stack via __stack symbol - see
> >             defintion of .Lstack
> > @@ -175,7 +179,7 @@
> >             Loosely based on init.s from ARM/Motorola example code.
> >                 Note: Mode switch via CPSR is not allowed once in non-privileged
> >                   mode, so we take care not to enter "User" to set up its sp,
> > -                 and also skip most operations if already in that mode. */
> > +                 and also skip most operations if already in that mode.  */
> >
> >       ldr     r3, .Lstack
> >       cmp     r3, #0
> > @@ -192,42 +196,42 @@
> >       /* Note: This 'mov' is essential when starting in User, and ensures we
> >                always get *some* sp value for the initial mode, even if we
> >                have somehow missed it below (in which case it gets the same
> > -              value as FIQ - not ideal, but better than nothing.) */
> > +              value as FIQ - not ideal, but better than nothing).  */
> >       mov     sp, r3
> >   #ifdef PREFER_THUMB
> >       /* XXX Fill in stack assignments for interrupt modes.  */
> >   #else
> >       mrs     r2, CPSR
> > -     tst     r2, #0x0F       /* Test mode bits - in User of all are 0 */
> > -     beq     .LC23           /* "eq" means r2 AND #0x0F is 0 */
> > -     msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled */
> > +     tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
> > +     beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> > +     msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> >       mov     sp, r3
> > -     sub     sl, sp, #0x1000 /* This mode also has its own sl (see below) */
> > +     sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
> >
> >       mov     r3, sl
> > -     msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled */
> > +     msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
> >       mov     sp, r3
> >       sub     r3, r3, #0x1000
> >
> > -     msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled */
> > +     msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
> >       mov     sp, r3
> >       sub     r3, r3, #0x1000
> >
> > -     msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled */
> > +     msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> >       mov     sp, r3
> >       sub     r3, r3, #0x2000
> >
> > -     msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled */
> > +     msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
> >
> >       mov     sp, r3
> > -     sub     r3, r3, #0x8000 /* Min size 32k */
> > -     bic     r3, r3, #0x00FF /* Align with current 64k block */
> > +     sub     r3, r3, #0x8000 /* Min size 32k.  */
> > +     bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> >       bic     r3, r3, #0xFF00
> >
> >       str     r3, [r3, #-4]   /* Move value into user mode sp without */
> > -     ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm */
> > +     ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
> >       orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
> > -     msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1 */
> > +     msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
> >   #endif
> >   .LC23:
> >       /* Setup a default stack-limit in-case the code has been
> > @@ -243,24 +247,24 @@
> >       subs    r2, r3, r2
> >       mov     sl, r2
> >   #else
> > -     sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl */
> > +     sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
> >   #endif
> >   #endif
> >   #endif
> >       /* Zero the memory in the .bss section.  */
> > -     movs    a2, #0                  /* Second arg: fill value */
> > -     mov     fp, a2                  /* Null frame pointer */
> > -     mov     r7, a2                  /* Null frame pointer for Thumb */
> > +     movs    a2, #0                  /* Second arg: fill value.  */
> > +     mov     fp, a2                  /* Null frame pointer.  */
> > +     mov     r7, a2                  /* Null frame pointer for Thumb.  */
> >
> > -     ldr     a1, .LC1                /* First arg: start of memory block */
> > +     ldr     a1, .LC1                /* First arg: start of memory block.  */
> >       ldr     a3, .LC2
> > -     subs    a3, a3, a1              /* Third arg: length of block */
> > +     subs    a3, a3, a1              /* Third arg: length of block.  */
> >
> >
> >   #if __thumb__ && !defined(PREFER_THUMB)
> > -     /* Enter Thumb mode.... */
> > -     add     a4, pc, #1      /* Get the address of the Thumb block */
> > -     bx      a4              /* Go there and start Thumb decoding  */
> > +     /* Enter Thumb mode...  */
> > +     add     a4, pc, #1      /* Get the address of the Thumb block.  */
> > +     bx      a4              /* Go there and start Thumb decoding.  */
> >
> >       .code 16
> >       .global __change_mode
> > @@ -271,9 +275,8 @@ __change_mode:
> >       bl      FUNCTION (memset)
> >   #if !defined (ARM_RDP_MONITOR) && !defined (ARM_RDI_MONITOR)
> >   /* Changes by toralf: Taken from libgloss/m68k/crt0.S
> > - * initialize target specific stuff. Only execute these
> > - * functions it they exist.
> > - */
> > +   initialize target specific stuff. Only execute these
> > +   functions it they exist.  */
> >       ldr     r3, .Lhwinit
> >       cmp     r3, #0
> >       beq     .LC24
> > @@ -285,24 +288,24 @@ __change_mode:
> >       indirect_call r3
> >
> >   .LC25:
> > -     movs    r0, #0          /*  no arguments  */
> > -     movs    r1, #0          /*  no argv either */
> > +     movs    r0, #0          /* No arguments.  */
> > +     movs    r1, #0          /* No argv either.  */
> >   #else
> > -     /* Need to set up standard file handles */
> > +     /* Need to set up standard file handles.  */
> >       bl      FUNCTION (initialise_monitor_handles)
> >
> >   #ifdef ARM_RDP_MONITOR
> > -     swi     SWI_GetEnv      /*  sets r0 to point to the command line */
> > +     swi     SWI_GetEnv      /* Sets r0 to point to the command line.  */
> >       movs    r1, r0
> >   #else
> >       movs    r0, #AngelSWI_Reason_GetCmdLine
> > -     ldr     r1, .LC30       /*  Space for command line */
> > +     ldr     r1, .LC30       /* Space for command line.  */
> >       AngelSWIAsm (AngelSWI)
> >       ldr     r1, .LC30
> >       ldr     r1, [r1]
> >   #endif
> > -     /*  Parse string at r1 */
> > -     movs    r0, #0          /*  count of arguments so far */
> > +     /*  Parse string at r1.  */
> > +     movs    r0, #0          /* Count of arguments so far.  */
> >       /* Push a NULL argument onto the end of the list.  */
> >   #ifdef __thumb__
> >       push    {r0}
> > @@ -310,7 +313,7 @@ __change_mode:
> >       stmfd   sp!, {r0}
> >   #endif
> >   .LC10:
> > -/*  Skip leading blanks */
> > +/*  Skip leading blanks.  */
> >   #ifdef __thumb__
> >       ldrb    r3, [r1]
> >       adds    r1, #1
> > @@ -322,7 +325,7 @@ __change_mode:
> >       cmp     r3, #' '
> >       beq     .LC10
> >
> > -/*  See whether we are scanning a string */
> > +/* See whether we are scanning a string.  */
> >       cmp     r3, #'"'
> >   #ifdef __thumb__
> >       beq     .LC20
> > @@ -333,17 +336,17 @@ __change_mode:
> >       b       .LC22
> >
> >   .LC21:
> > -     movs    r2, #' '        /*  terminator type */
> > -     subs    r1, r1, #1      /*  adjust back to point at start char */
> > +     movs    r2, #' '        /* Terminator type.  */
> > +     subs    r1, r1, #1      /* Adjust back to point at start char.  */
> >   .LC22:
> >   #else
> >       cmpne   r3, #'\''
> >       moveq   r2, r3
> > -     movne   r2, #' '        /*  terminator type */
> > -     subne   r1, r1, #1      /*  adjust back to point at start char */
> > +     movne   r2, #' '        /* Terminator type.  */
> > +     subne   r1, r1, #1      /* Adjust back to point at start char.  */
> >   #endif
> >
> > -/*  Stack a pointer to the current argument */
> > +/*  Stack a pointer to the current argument.  */
> >   #ifdef __thumb__
> >       push    {r1}
> >   #else
> > @@ -359,16 +362,16 @@ __change_mode:
> >   #endif
> >       cmp     r3, #0
> >       beq     .LC12
> > -     cmp     r2, r3          /*  reached terminator? */
> > +     cmp     r2, r3          /* Reached terminator ?  */
> >       bne     .LC11
> >       movs    r2, #0
> >       subs    r3, r1, #1
> > -     strb    r2, [r3]        /*  terminate the arg string */
> > +     strb    r2, [r3]        /* Terminate the arg string.  */
> >       b       .LC10
> >
> >   .LC12:
> > -     mov     r1, sp          /*  point at stacked arg pointers */
> > -     /* We've now got the stacked args in order reverse the */
> > +     mov     r1, sp          /* Point at stacked arg pointers.  */
> > +     /* We've now got the stacked args in order, reverse them.  */
> >   #ifdef __thumb__
> >       movs    r2, r0
> >       lsls    r2, #2
> > @@ -390,10 +393,10 @@ __change_mode:
> >       bics    r4, r5
> >       mov     sp, r4
> >   #else
> > -     add     r2, sp, r0, LSL #2      /* End of args */
> > -     mov     r3, sp                  /* Start of args */
> > +     add     r2, sp, r0, LSL #2      /* End of args.  */
> > +     mov     r3, sp                  /* Start of args.  */
> >   .LC13:      cmp     r2, r3
> > -     ldrhi   r4,[r2, #-4]            /* Reverse ends of list */
> > +     ldrhi   r4,[r2, #-4]            /* Reverse ends of list.  */
> >       ldrhi   r5, [r3]
> >       strhi   r5, [r2, #-4]!
> >       strhi   r4, [r3], #4
> > @@ -431,7 +434,6 @@ __change_mode:
> >
> >   #if __thumb__ && !defined(PREFER_THUMB)
> >       /* Come out of Thumb mode.  This code should be redundant.  */
> > -
> >       mov     a4, pc
> >       bx      a4
> >
> > @@ -447,7 +449,6 @@ change_back:
> >
> >       /* For Thumb, constants must be after the code since only
> >          positive offsets are supported for PC relative addresses.  */
> > -
> >       .align 0
> >   .LC0:
> >   #ifdef ARM_RDI_MONITOR
> > @@ -457,13 +458,13 @@ change_back:
> >       /* Changes by toralf: Provide alternative "stack" variable whose value
> >          may be defined externally; .Lstack will be used instead of .LC0 if
> >          it points to a non-0 value. Also set up references to "hooks" that
> > -           may be used by the application to provide additional init code. */
> > -
> > +           may be used by the application to provide additional init code.  */
> >   #ifdef __pe__
> >       .word   0x800000
> >   #else
> >       .word   0x80000                 /* Top of RAM on the PIE board.  */
> >   #endif
> > +
> >   .Lstack:
> >       .word   __stack
> >   .Lhwinit:
> > @@ -476,7 +477,7 @@ change_back:
> >          runtime (meaning "ignore setting") for the variables, when the user
> >          does not provide the symbols. (The linker uses a weak symbol if,
> >          and only if, a normal version of the same symbol isn't provided
> > -        e.g. by a linker script or another object file.) */
> > +        e.g. by a linker script or another object file.)  */
> >
> >       .weak __stack
> >       .weak FUNCTION (hardware_init_hook)
> > diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
> > index 8c9f7be38..7a6b40d9a 100644
> > --- a/newlib/libc/sys/arm/crt0.S
> > +++ b/newlib/libc/sys/arm/crt0.S
> > @@ -50,13 +50,13 @@
> >       .global \name
> >       .thumb_func
> >   \name:
> > -.endm
> > +.endm
> >   #else
> >       .code 32
> >   .macro FUNC_START name
> > -     .global \name
> > +     .global \name
> >   \name:
> > -.endm
> > +.endm
> >   #endif
> >
> >   .macro indirect_call reg
> > @@ -68,8 +68,10 @@
> >   #endif
> >   .endm
> >
> > +/*******************************************************************************
> > +* Main library startup code.
> > +*******************************************************************************/
> >       .align  0
> > -
> >       FUNC_START      _mainCRTStartup
> >       FUNC_START      _start
> >   #if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > @@ -399,7 +401,7 @@ __change_mode:
> >       bl      FUNCTION (_init)
> >       movs    r0, r4
> >       movs    r1, r5
> > -#endif
> > +#endif
> >       bl      FUNCTION (main)
> >
> >       bl      FUNCTION (exit)         /* Should not return.  */
> > @@ -420,7 +422,7 @@ change_back:
> >   #endif
> >
> >       /* For Thumb, constants must be after the code since only
> > -        positive offsets are supported for PC relative addresses.  */
> > +        positive offsets are supported for PC relative addresses.  */
> >       .align 0
> >   .LC0:
> >   #ifdef ARM_RDI_MONITOR
> > @@ -430,7 +432,7 @@ change_back:
> >       /* Changes by toralf: Provide alternative "stack" variable whose value
> >          may be defined externally; .Lstack will be used instead of .LC0 if
> >          it points to a non-0 value. Also set up references to "hooks" that
> > -           may be used by the application to provide additional init code.  */
> > +           may be used by the application to provide additional init code.  */
> >   #ifdef __pe__
> >       .word   0x800000
> >   #else
> > @@ -449,7 +451,7 @@ change_back:
> >          runtime (meaning "ignore setting") for the variables, when the user
> >          does not provide the symbols. (The linker uses a weak symbol if,
> >          and only if, a normal version of the same symbol isn't provided
> > -        e.g. by a linker script or another object file).  */
> > +        e.g. by a linker script or another object file.)  */
> >
> >       .weak __stack
> >       .weak FUNCTION (hardware_init_hook)
> >
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] [Arm] Stack Pointer and Stack Limit initialization refactored.

Alexander Fedotov
In reply to this post by Richard Earnshaw (lists)
On Thu, Jul 18, 2019 at 1:24 PM Richard Earnshaw (lists)
<[hidden email]> wrote:

>
>
>
> On 12/04/2019 14:30, [hidden email] wrote:
> > From: Alexander Fedotov <[hidden email]>
> >
> > SP initialization changes:
> >    1. set default value in semihosting case as well
> >    2. moved existing SP & SL init code for processor modes in separate routine and made it as "hook"
> >    3. init SP for processor modes in Thumb mode as well
> >
>
> Thanks for this, I think overall it's a definite improvement on what we
> have now.  A couple of comments.
>
> I suspect this code will not work as intended if the system starts in
> secure mode.  In particular the methods of getting in and out of secure
> state are not as simple as writing to the CPSR mode bits.  But the
> existing code won't handle that either, so this is not regression, I
> suspect.
Do you mean Secure extensions? Or something else?
If core starts in Hypervisor mode it's up to startup code indeed. Here
we should come in Suprevisor mode at least.
>
> A few of the comments are not really in house style (Sentences start
> with capital letter, full stop at the end and then two spaces before the
> comment close.
Ok.

>
> If you could clean up the comment style and add a note about secure
> state not being supported at present, I think this is good to go in.
>
> R.
>
> > Add new macro FN_RETURN, FN_EH_START and FN_EH_END.
> > ---
> >   libgloss/arm/arm.h         |  26 ++++
> >   libgloss/arm/crt0.S        | 277 ++++++++++++++++++++++++++-----------
> >   newlib/libc/sys/arm/arm.h  |  26 ++++
> >   newlib/libc/sys/arm/crt0.S | 277 ++++++++++++++++++++++++++-----------
> >   4 files changed, 440 insertions(+), 166 deletions(-)
> >
> > diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
> > index 0489f2d92..04b3a5ac7 100644
> > --- a/libgloss/arm/arm.h
> > +++ b/libgloss/arm/arm.h
> > @@ -61,4 +61,30 @@
> >   # define HAVE_CALL_INDIRECT
> >   #endif
> >
> > +/* A and R profiles (and legacy Arm).
> > +     Current Program Status Register (CPSR)
> > +     M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
> > +     T[5]                    1: Thumb, 0: ARM instruction set
> > +     F[6]                    1: disables FIQ
> > +     I[7]                    1: disables IRQ
> > +     A[8]                    1: disables imprecise aborts
> > +     E[9]                    0: Little-endian, 1: Big-endian
> > +     J[24]                   1: Jazelle instruction set
> > + */
> > +#define CPSR_M_USR                   0x00    /* User mode */
> > +#define CPSR_M_FIQ                   0x01    /* Fast Interrupt mode */
> > +#define CPSR_M_IRQ                   0x02    /* Interrupt mode */
> > +#define CPSR_M_SVR                   0x03    /* Supervisor mode */
> > +#define CPSR_M_MON                   0x06    /* Monitor mode */
> > +#define CPSR_M_ABT                   0x07    /* Abort mode */
> > +#define CPSR_M_HYP                   0x0A    /* Hypervisor mode */
> > +#define CPSR_M_UND                   0x0B    /* Undefined mode */
> > +#define CPSR_M_SYS                   0x0F    /* System mode */
> > +#define CPSR_M_32BIT         0x10    /* 32-bit mode */
> > +#define CPSR_T_BIT                   0x20    /* Thumb bit */
> > +#define CPSR_F_MASK                  0x40    /* FIQ bit */
> > +#define CPSR_I_MASK                  0x80    /* IRQ bit */
> > +
> > +#define CPSR_M_MASK                  0x0F    /* Mode mask except M[4] */
> > +
> >   #endif /* _LIBGLOSS_ARM_H */
> > diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
> > index 1deb73aa5..95aa3b578 100644
> > --- a/libgloss/arm/crt0.S
> > +++ b/libgloss/arm/crt0.S
> > @@ -59,6 +59,21 @@
> >   .endm
> >   #endif
> >
> > +/* Annotation for EABI unwinding tables. */
> > +.macro FN_EH_START
> > +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > +     .fnstart
> > +#endif
> > +.endm
> > +
> > +.macro FN_EH_END
> > +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > +     /* Protect against unhandled exceptions.  */
> > +     .cantunwind
> > +     .fnend
> > +#endif
> > +.endm
> > +
> >   .macro indirect_call reg
> >   #ifdef HAVE_CALL_INDIRECT
> >       blx \reg
> > @@ -68,16 +83,170 @@
> >   #endif
> >   .endm
> >
> > +/* For armv4t and newer, toolchains will transparently convert
> > +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> > +   for anything older than armv4t, but this should handle that
> > +   corner case in case anyone needs it anyway */
> > +.macro  FN_RETURN
> > +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> > +     mov     pc, lr
> > +#else
> > +     bx      lr
> > +#endif
> > +.endm
> > +
> > +
> > +
> > +/******************************************************************************
> > +* User mode only:           This routine makes default target specific Stack
> > +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
> > +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
> > +*   | SYS |               and setups a default Stack Limit in-case the code has
> > +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
> > +*   |     |               System (User) modes.
> > +*   |     |
> > +*   +-----+ <- initial SP,
> > +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
> > +*           and SL_usr     currently no support for checking that the heap and
> > +*                          stack have not collided, or that this default 64k is
> > +* All modes:               is enough for the program being executed. However,
> > +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
> > +*   |     |    SL_usr      immediately cause an overflow event.
> > +*   | SYS |
> > +*   | USR | -=0x10000        We go through all execution modes and set up SP
> > +*   |     |                for each of them.
> > +*   +-----+ <- SP_sys,
> > +*   |     |    SP_usr      Note:
> > +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
> > +*   |     |                  non-privileged mode, so we take care not to enter
> > +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
> > +*   |     |                  operations if already in that mode.
> > +*   | IRQ | -= 0x2000
> > +*   |     |                Input parameters:
> > +* ^ +-----+ <- SP_und       - sp - Initialized SP
> > +* s |     |                 - r2 - May contain SL value from semihosting
> > +* t | UND | -= 0x1000              SYS_HEAPINFO call
> > +* a |     |                Scratch registers:
> > +* c +-----+ <- SP_und       - r1 - new value of CPSR
> > +* k |     |                 - r2 - intermediate value (in standalone mode)
> > +*   | ABT | -= 0x1000       - r3 - new SP value
> > +* g |     |                 - r4 - save/restore CPSR on entry/exit
> > +* r +-----+ <- SP_abt,
> > +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
> > +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
> > +* t |     |
> > +* h +-----+ <- initial SP,
> > +*           becomes SP_fiq
> > +*
> > +******************************************************************************/
> > +     .align  0
> > +     FUNC_START      _stack_init
> > +     .weak FUNCTION (_stack_init)
> > +     FN_EH_START
> > +
> > +     /* M profile doesn't have CPSR register.  */
> > +#if (__ARM_ARCH_PROFILE != 'M')
> > +     /* Following code is compatible for both ARM and Thumb ISA */
> > +     mrs     r4, CPSR
> > +     /* Test mode bits - in User of all are 0 */
> > +     tst     r4, #(CPSR_M_MASK)
> > +     /* "eq" means r4 AND #0x0F is 0 */
> > +     beq     .Lskip_cpu_modes
> > +
> > +     mov     r3, sp /* save input SP value */
> > +
> > +     /* FIQ mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +     sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
> > +
> > +     /* Abort mode, interrupts disabled */
> > +     mov     r3, sl
> > +     mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +     sub     r3, r3, #0x1000
> > +
> > +     /* Undefined mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +     sub     r3, r3, #0x1000
> > +
> > +     /* IRQ mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +     sub     r3, r3, #0x2000
> > +
> > +     /* Supervisory mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +
> > +     sub     r3, r3, #0x8000 /* Min size 32k */
> > +     bic     r3, r3, #0x00FF /* Align with current 64k block */
> > +     bic     r3, r3, #0xFF00
> > +
> > +# if __ARM_ARCH >= 4
> > +     /* System (shares regs with User) mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +# else
> > +     /* Keep this for ARMv3, but GCC actually dropped it. */
> > +     /* Move value into user mode sp without changing modes, */
> > +     /* via '^' form of ldm */
> > +     str     r3, [r3, #-4]
> > +     ldmdb   r3, {sp}^
> > +# endif
> > +
> > +     /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
> > +     orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r4
> > +
> > +.Lskip_cpu_modes:
> > +#endif
> > +
> > +     /* Set SL register */
> > +#if defined (ARM_RDI_MONITOR) /* semihosting */
> > +     cmp     r2, #0
> > +     beq     .Lsl_forced_zero
> > +     /* allow slop for stack overflow handling and small frames */
> > +# ifdef THUMB1_ONLY
> > +     adds    r2, #128
> > +     adds    r2, #128
> > +     mov     sl, r2
> > +# else
> > +     add     sl, r2, #256
> > +# endif
> > +.Lsl_forced_zero:
> > +
> > +#else /* standalone */
> > +     /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
> > +     #ifdef THUMB1_ONLY
> > +     movs    r2, #64
> > +     lsls    r2, r2, #10
> > +     subs    r2, r3, r2
> > +     mov     sl, r2
> > +     #else
> > +     /* Still assumes 256bytes below sl */
> > +     sub     sl, r3, #64 << 10
> > +     #endif
> > +#endif
> > +
> > +     FN_RETURN
> > +     FN_EH_END
> > +
> > +
> >   /*******************************************************************************
> >   * Main library startup code.
> >   *******************************************************************************/
> >       .align  0
> >       FUNC_START      _mainCRTStartup
> >       FUNC_START      _start
> > -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > -     /* Annotation for EABI unwinding tables.  */
> > -     .fnstart
> > -#endif
> > +     FN_EH_START
> >
> >       /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards, however __ARM_ARCH_7A
> >       has been defined since 4.2 onwards, which is when v7-a support was added
> > @@ -150,36 +319,27 @@
> >             to skip setting sp/sl to 0 here.
> >           - Considering M-profile processors, We might want to initialize
> >             sp by the first entry of vector table and return 0 to SYS_HEAPINFO
> > -           semihosting call, which will be skipped here.  */
> > +           semihosting call, which will be skipped here.
> > +         - Considering R-profile processors there is no automatic SP init by hardware
> > +           so we need to initialize it by default value. */
> > +     ldr     r3, .Lstack
> >       cmp     r1, #0
> >       beq     .LC26
> > -     mov     sp, r1
> > +     mov     r3, r1
> >   .LC26:
> > -     cmp     r2, #0
> > -     beq     .LC27
> > +     mov     sp, r3
> >
> > -     /*  Allow slop for stack overflow handling and small frames.  */
> > -#ifdef THUMB1_ONLY
> > -     adds    r2, #128
> > -     adds    r2, #128
> > -     mov     sl, r2
> > -#else
> > -     add     sl, r2, #256
> > -#endif
> > +     /* r2 (SL value) will be used in _stack_init */
> > +     bl FUNCTION (_stack_init)
> >
> > -.LC27:
> > -#else
> > -     /*  Set up the stack pointer to a fixed value.  */
> > +
> > +#else /* standalone */
> > +     /*  Set up the stack pointer to a fixed value. */
> >       /*  Changes by toralf:
> >           - Allow linker script to provide stack via __stack symbol - see
> >             defintion of .Lstack
> >           - Provide "hooks" that may be used by the application to add
> > -           custom init code - see .Lhwinit and .Lswinit
> > -         - Go through all execution modes and set up stack for each of them.
> > -           Loosely based on init.s from ARM/Motorola example code.
> > -              Note: Mode switch via CPSR is not allowed once in non-privileged
> > -                 mode, so we take care not to enter "User" to set up its sp,
> > -                 and also skip most operations if already in that mode.  */
> > +           custom init code - see .Lhwinit and .Lswinit */
> >
> >       ldr     r3, .Lstack
> >       cmp     r3, #0
> > @@ -198,57 +358,10 @@
> >                have somehow missed it below (in which case it gets the same
> >                value as FIQ - not ideal, but better than nothing).  */
> >       mov     sp, r3
> > -#ifdef PREFER_THUMB
> > -     /* XXX Fill in stack assignments for interrupt modes.  */
> > -#else
> > -     mrs     r2, CPSR
> > -     tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
> > -     beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> > -     msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> > -     mov     sp, r3
> > -     sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
> > -
> > -     mov     r3, sl
> > -     msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
> > -     mov     sp, r3
> > -     sub     r3, r3, #0x1000
> > -
> > -     msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
> > -     mov     sp, r3
> > -     sub     r3, r3, #0x1000
> >
> > -     msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> > -     mov     sp, r3
> > -     sub     r3, r3, #0x2000
> > -
> > -     msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
> > +     /* we don't care of r2 value in standalone */
> > +     bl FUNCTION (_stack_init)
> >
> > -     mov     sp, r3
> > -     sub     r3, r3, #0x8000 /* Min size 32k.  */
> > -     bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> > -     bic     r3, r3, #0xFF00
> > -
> > -     str     r3, [r3, #-4]   /* Move value into user mode sp without */
> > -     ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
> > -     orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
> > -     msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
> > -#endif
> > -.LC23:
> > -     /* Setup a default stack-limit in-case the code has been
> > -        compiled with "-mapcs-stack-check".  Hard-wiring this value
> > -        is not ideal, since there is currently no support for
> > -        checking that the heap and stack have not collided, or that
> > -        this default 64k is enough for the program being executed.
> > -        However, it ensures that this simple crt0 world will not
> > -        immediately cause an overflow event:  */
> > -#ifdef THUMB1_ONLY
> > -     movs    r2, #64
> > -     lsls    r2, r2, #10
> > -     subs    r2, r3, r2
> > -     mov     sl, r2
> > -#else
> > -     sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
> > -#endif
> >   #endif
> >   #endif
> >       /* Zero the memory in the .bss section.  */
> > @@ -447,6 +560,8 @@ change_back:
> >       swi     SWI_Exit
> >   #endif
> >
> > +     FN_EH_END
> > +
> >       /* For Thumb, constants must be after the code since only
> >          positive offsets are supported for PC relative addresses.  */
> >       .align 0
> > @@ -464,9 +579,6 @@ change_back:
> >   #else
> >       .word   0x80000                 /* Top of RAM on the PIE board.  */
> >   #endif
> > -
> > -.Lstack:
> > -     .word   __stack
> >   .Lhwinit:
> >       .word   FUNCTION (hardware_init_hook)
> >   .Lswinit:
> > @@ -479,17 +591,16 @@ change_back:
> >          and only if, a normal version of the same symbol isn't provided
> >          e.g. by a linker script or another object file.)  */
> >
> > -     .weak __stack
> >       .weak FUNCTION (hardware_init_hook)
> >       .weak FUNCTION (software_init_hook)
> >   #endif
> >
> >   #endif
> > -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > -     /* Protect against unhandled exceptions.  */
> > -     .cantunwind
> > -     .fnend
> > -#endif
> > +
> > +.Lstack:
> > +     .word   __stack
> > +     .weak   __stack
> > +
> >   .LC1:
> >       .word   __bss_start__
> >   .LC2:
> > diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
> > index 0489f2d92..04b3a5ac7 100644
> > --- a/newlib/libc/sys/arm/arm.h
> > +++ b/newlib/libc/sys/arm/arm.h
> > @@ -61,4 +61,30 @@
> >   # define HAVE_CALL_INDIRECT
> >   #endif
> >
> > +/* A and R profiles (and legacy Arm).
> > +     Current Program Status Register (CPSR)
> > +     M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
> > +     T[5]                    1: Thumb, 0: ARM instruction set
> > +     F[6]                    1: disables FIQ
> > +     I[7]                    1: disables IRQ
> > +     A[8]                    1: disables imprecise aborts
> > +     E[9]                    0: Little-endian, 1: Big-endian
> > +     J[24]                   1: Jazelle instruction set
> > + */
> > +#define CPSR_M_USR                   0x00    /* User mode */
> > +#define CPSR_M_FIQ                   0x01    /* Fast Interrupt mode */
> > +#define CPSR_M_IRQ                   0x02    /* Interrupt mode */
> > +#define CPSR_M_SVR                   0x03    /* Supervisor mode */
> > +#define CPSR_M_MON                   0x06    /* Monitor mode */
> > +#define CPSR_M_ABT                   0x07    /* Abort mode */
> > +#define CPSR_M_HYP                   0x0A    /* Hypervisor mode */
> > +#define CPSR_M_UND                   0x0B    /* Undefined mode */
> > +#define CPSR_M_SYS                   0x0F    /* System mode */
> > +#define CPSR_M_32BIT         0x10    /* 32-bit mode */
> > +#define CPSR_T_BIT                   0x20    /* Thumb bit */
> > +#define CPSR_F_MASK                  0x40    /* FIQ bit */
> > +#define CPSR_I_MASK                  0x80    /* IRQ bit */
> > +
> > +#define CPSR_M_MASK                  0x0F    /* Mode mask except M[4] */
> > +
> >   #endif /* _LIBGLOSS_ARM_H */
> > diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
> > index 7a6b40d9a..0929a435e 100644
> > --- a/newlib/libc/sys/arm/crt0.S
> > +++ b/newlib/libc/sys/arm/crt0.S
> > @@ -59,6 +59,21 @@
> >   .endm
> >   #endif
> >
> > +/* Annotation for EABI unwinding tables. */
> > +.macro FN_EH_START
> > +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > +     .fnstart
> > +#endif
> > +.endm
> > +
> > +.macro FN_EH_END
> > +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > +     /* Protect against unhandled exceptions.  */
> > +     .cantunwind
> > +     .fnend
> > +#endif
> > +.endm
> > +
> >   .macro indirect_call reg
> >   #ifdef HAVE_CALL_INDIRECT
> >       blx \reg
> > @@ -68,16 +83,170 @@
> >   #endif
> >   .endm
> >
> > +/* For armv4t and newer, toolchains will transparently convert
> > +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
> > +   for anything older than armv4t, but this should handle that
> > +   corner case in case anyone needs it anyway */
> > +.macro  FN_RETURN
> > +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
> > +     mov     pc, lr
> > +#else
> > +     bx      lr
> > +#endif
> > +.endm
> > +
> > +
> > +
> > +/******************************************************************************
> > +* User mode only:           This routine makes default target specific Stack
> > +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
> > +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
> > +*   | SYS |               and setups a default Stack Limit in-case the code has
> > +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
> > +*   |     |               System (User) modes.
> > +*   |     |
> > +*   +-----+ <- initial SP,
> > +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
> > +*           and SL_usr     currently no support for checking that the heap and
> > +*                          stack have not collided, or that this default 64k is
> > +* All modes:               is enough for the program being executed. However,
> > +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
> > +*   |     |    SL_usr      immediately cause an overflow event.
> > +*   | SYS |
> > +*   | USR | -=0x10000        We go through all execution modes and set up SP
> > +*   |     |                for each of them.
> > +*   +-----+ <- SP_sys,
> > +*   |     |    SP_usr      Note:
> > +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
> > +*   |     |                  non-privileged mode, so we take care not to enter
> > +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
> > +*   |     |                  operations if already in that mode.
> > +*   | IRQ | -= 0x2000
> > +*   |     |                Input parameters:
> > +* ^ +-----+ <- SP_und       - sp - Initialized SP
> > +* s |     |                 - r2 - May contain SL value from semihosting
> > +* t | UND | -= 0x1000              SYS_HEAPINFO call
> > +* a |     |                Scratch registers:
> > +* c +-----+ <- SP_und       - r1 - new value of CPSR
> > +* k |     |                 - r2 - intermediate value (in standalone mode)
> > +*   | ABT | -= 0x1000       - r3 - new SP value
> > +* g |     |                 - r4 - save/restore CPSR on entry/exit
> > +* r +-----+ <- SP_abt,
> > +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
> > +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
> > +* t |     |
> > +* h +-----+ <- initial SP,
> > +*           becomes SP_fiq
> > +*
> > +******************************************************************************/
> > +     .align  0
> > +     FUNC_START      _stack_init
> > +     .weak FUNCTION (_stack_init)
> > +     FN_EH_START
> > +
> > +     /* M profile doesn't have CPSR register.  */
> > +#if (__ARM_ARCH_PROFILE != 'M')
> > +     /* Following code is compatible for both ARM and Thumb ISA */
> > +     mrs     r4, CPSR
> > +     /* Test mode bits - in User of all are 0 */
> > +     tst     r4, #(CPSR_M_MASK)
> > +     /* "eq" means r4 AND #0x0F is 0 */
> > +     beq     .Lskip_cpu_modes
> > +
> > +     mov     r3, sp /* save input SP value */
> > +
> > +     /* FIQ mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +     sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
> > +
> > +     /* Abort mode, interrupts disabled */
> > +     mov     r3, sl
> > +     mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +     sub     r3, r3, #0x1000
> > +
> > +     /* Undefined mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +     sub     r3, r3, #0x1000
> > +
> > +     /* IRQ mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +     sub     r3, r3, #0x2000
> > +
> > +     /* Supervisory mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +
> > +     sub     r3, r3, #0x8000 /* Min size 32k */
> > +     bic     r3, r3, #0x00FF /* Align with current 64k block */
> > +     bic     r3, r3, #0xFF00
> > +
> > +# if __ARM_ARCH >= 4
> > +     /* System (shares regs with User) mode, interrupts disabled */
> > +     mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r1
> > +     mov     sp, r3
> > +# else
> > +     /* Keep this for ARMv3, but GCC actually dropped it. */
> > +     /* Move value into user mode sp without changing modes, */
> > +     /* via '^' form of ldm */
> > +     str     r3, [r3, #-4]
> > +     ldmdb   r3, {sp}^
> > +# endif
> > +
> > +     /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
> > +     orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
> > +     msr     CPSR_c, r4
> > +
> > +.Lskip_cpu_modes:
> > +#endif
> > +
> > +     /* Set SL register */
> > +#if defined (ARM_RDI_MONITOR) /* semihosting */
> > +     cmp     r2, #0
> > +     beq     .Lsl_forced_zero
> > +     /* allow slop for stack overflow handling and small frames */
> > +# ifdef THUMB1_ONLY
> > +     adds    r2, #128
> > +     adds    r2, #128
> > +     mov     sl, r2
> > +# else
> > +     add     sl, r2, #256
> > +# endif
> > +.Lsl_forced_zero:
> > +
> > +#else /* standalone */
> > +     /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
> > +     #ifdef THUMB1_ONLY
> > +     movs    r2, #64
> > +     lsls    r2, r2, #10
> > +     subs    r2, r3, r2
> > +     mov     sl, r2
> > +     #else
> > +     /* Still assumes 256bytes below sl */
> > +     sub     sl, r3, #64 << 10
> > +     #endif
> > +#endif
> > +
> > +     FN_RETURN
> > +     FN_EH_END
> > +
> > +
> >   /*******************************************************************************
> >   * Main library startup code.
> >   *******************************************************************************/
> >       .align  0
> >       FUNC_START      _mainCRTStartup
> >       FUNC_START      _start
> > -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > -     /* Annotation for EABI unwinding tables.  */
> > -     .fnstart
> > -#endif
> > +     FN_EH_START
> >
> >   /* Start by setting up a stack.  */
> >   #ifdef ARM_RDP_MONITOR
> > @@ -130,36 +299,27 @@
> >             to skip setting sp/sl to 0 here.
> >           - Considering M-profile processors, We might want to initialize
> >             sp by the first entry of vector table and return 0 to SYS_HEAPINFO
> > -           semihosting call, which will be skipped here.  */
> > +           semihosting call, which will be skipped here.
> > +         - Considering R-profile processors there is no automatic SP init by hardware
> > +           so we need to initialize it by default value. */
> > +     ldr     r3, .Lstack
> >       cmp     r1, #0
> >       beq     .LC26
> > -     mov     sp, r1
> > +     mov     r3, r1
> >   .LC26:
> > -     cmp     r2, #0
> > -     beq     .LC27
> > +     mov     sp, r3
> >
> > -     /*  Allow slop for stack overflow handling and small frames.  */
> > -#ifdef THUMB1_ONLY
> > -     adds    r2, #128
> > -     adds    r2, #128
> > -     mov     sl, r2
> > -#else
> > -     add     sl, r2, #256
> > -#endif
> > +     /* r2 (SL value) will be used in _stack_init */
> > +     bl FUNCTION (_stack_init)
> >
> > -.LC27:
> > -#else
> > -     /*  Set up the stack pointer to a fixed value.  */
> > +
> > +#else /* standalone */
> > +     /*  Set up the stack pointer to a fixed value. */
> >       /*  Changes by toralf:
> >           - Allow linker script to provide stack via __stack symbol - see
> >             defintion of .Lstack
> >           - Provide "hooks" that may be used by the application to add
> > -           custom init code - see .Lhwinit and .Lswinit
> > -         - Go through all execution modes and set up stack for each of them.
> > -           Loosely based on init.s from ARM/Motorola example code.
> > -              Note: Mode switch via CPSR is not allowed once in non-privileged
> > -                 mode, so we take care not to enter "User" to set up its sp,
> > -                 and also skip most operations if already in that mode.  */
> > +           custom init code - see .Lhwinit and .Lswinit */
> >
> >       ldr     r3, .Lstack
> >       cmp     r3, #0
> > @@ -178,57 +338,10 @@
> >                have somehow missed it below (in which case it gets the same
> >                value as FIQ - not ideal, but better than nothing).  */
> >       mov     sp, r3
> > -#ifdef PREFER_THUMB
> > -     /* XXX Fill in stack assignments for interrupt modes.  */
> > -#else
> > -     mrs     r2, CPSR
> > -     tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
> > -     beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
> > -     msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
> > -     mov     sp, r3
> > -     sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
> > -
> > -     mov     r3, sl
> > -     msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
> > -     mov     sp, r3
> > -     sub     r3, r3, #0x1000
> > -
> > -     msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
> > -     mov     sp, r3
> > -     sub     r3, r3, #0x1000
> >
> > -     msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
> > -     mov     sp, r3
> > -     sub     r3, r3, #0x2000
> > -
> > -     msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
> > +     /* we don't care of r2 value in standalone */
> > +     bl FUNCTION (_stack_init)
> >
> > -     mov     sp, r3
> > -     sub     r3, r3, #0x8000 /* Min size 32k.  */
> > -     bic     r3, r3, #0x00FF /* Align with current 64k block.  */
> > -     bic     r3, r3, #0xFF00
> > -
> > -     str     r3, [r3, #-4]   /* Move value into user mode sp without */
> > -     ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
> > -     orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
> > -     msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
> > -#endif
> > -.LC23:
> > -     /* Setup a default stack-limit in-case the code has been
> > -        compiled with "-mapcs-stack-check".  Hard-wiring this value
> > -        is not ideal, since there is currently no support for
> > -        checking that the heap and stack have not collided, or that
> > -        this default 64k is enough for the program being executed.
> > -        However, it ensures that this simple crt0 world will not
> > -        immediately cause an overflow event:  */
> > -#ifdef THUMB1_ONLY
> > -     movs    r2, #64
> > -     lsls    r2, r2, #10
> > -     subs    r2, r3, r2
> > -     mov     sl, r2
> > -#else
> > -     sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
> > -#endif
> >   #endif
> >   #endif
> >       /* Zero the memory in the .bss section.  */
> > @@ -421,6 +534,8 @@ change_back:
> >       swi     SWI_Exit
> >   #endif
> >
> > +     FN_EH_END
> > +
> >       /* For Thumb, constants must be after the code since only
> >          positive offsets are supported for PC relative addresses.  */
> >       .align 0
> > @@ -438,9 +553,6 @@ change_back:
> >   #else
> >       .word   0x80000                 /* Top of RAM on the PIE board.  */
> >   #endif
> > -
> > -.Lstack:
> > -     .word   __stack
> >   .Lhwinit:
> >       .word   FUNCTION (hardware_init_hook)
> >   .Lswinit:
> > @@ -453,17 +565,16 @@ change_back:
> >          and only if, a normal version of the same symbol isn't provided
> >          e.g. by a linker script or another object file.)  */
> >
> > -     .weak __stack
> >       .weak FUNCTION (hardware_init_hook)
> >       .weak FUNCTION (software_init_hook)
> >   #endif
> >
> >   #endif
> > -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
> > -     /* Protect against unhandled exceptions.  */
> > -     .cantunwind
> > -     .fnend
> > -#endif
> > +
> > +.Lstack:
> > +     .word   __stack
> > +     .weak   __stack
> > +
> >   .LC1:
> >       .word   __bss_start__
> >   .LC2:
> >
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 2/2] [Arm] Stack Pointer and Stack Limit initialization refactored.

Richard Earnshaw (lists)


On 18/07/2019 14:59, Alexander Fedotov wrote:

> On Thu, Jul 18, 2019 at 1:24 PM Richard Earnshaw (lists)
> <[hidden email]> wrote:
>>
>>
>>
>> On 12/04/2019 14:30, [hidden email] wrote:
>>> From: Alexander Fedotov <[hidden email]>
>>>
>>> SP initialization changes:
>>>     1. set default value in semihosting case as well
>>>     2. moved existing SP & SL init code for processor modes in separate routine and made it as "hook"
>>>     3. init SP for processor modes in Thumb mode as well
>>>
>>
>> Thanks for this, I think overall it's a definite improvement on what we
>> have now.  A couple of comments.
>>
>> I suspect this code will not work as intended if the system starts in
>> secure mode.  In particular the methods of getting in and out of secure
>> state are not as simple as writing to the CPSR mode bits.  But the
>> existing code won't handle that either, so this is not regression, I
>> suspect.
> Do you mean Secure extensions? Or something else?
> If core starts in Hypervisor mode it's up to startup code indeed. Here
> we should come in Suprevisor mode at least.

See https://developer.arm.com/docs/ddi0406/latest, particularly section
B1.9.1 describing how the processor comes out of reset.

It's long and complicated, and I don't pretend to understand it all (or
even very much of it at all ;-).

You might want to take a look at
https://github.com/virtualopensystems/boot-wrapper/blob/master/boot.S 
which is some BSD-style licenced code that Arm has published.

R.

>>
>> A few of the comments are not really in house style (Sentences start
>> with capital letter, full stop at the end and then two spaces before the
>> comment close.
> Ok.
>>
>> If you could clean up the comment style and add a note about secure
>> state not being supported at present, I think this is good to go in.
>>
>> R.
>>
>>> Add new macro FN_RETURN, FN_EH_START and FN_EH_END.
>>> ---
>>>    libgloss/arm/arm.h         |  26 ++++
>>>    libgloss/arm/crt0.S        | 277 ++++++++++++++++++++++++++-----------
>>>    newlib/libc/sys/arm/arm.h  |  26 ++++
>>>    newlib/libc/sys/arm/crt0.S | 277 ++++++++++++++++++++++++++-----------
>>>    4 files changed, 440 insertions(+), 166 deletions(-)
>>>
>>> diff --git a/libgloss/arm/arm.h b/libgloss/arm/arm.h
>>> index 0489f2d92..04b3a5ac7 100644
>>> --- a/libgloss/arm/arm.h
>>> +++ b/libgloss/arm/arm.h
>>> @@ -61,4 +61,30 @@
>>>    # define HAVE_CALL_INDIRECT
>>>    #endif
>>>
>>> +/* A and R profiles (and legacy Arm).
>>> +     Current Program Status Register (CPSR)
>>> +     M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
>>> +     T[5]                    1: Thumb, 0: ARM instruction set
>>> +     F[6]                    1: disables FIQ
>>> +     I[7]                    1: disables IRQ
>>> +     A[8]                    1: disables imprecise aborts
>>> +     E[9]                    0: Little-endian, 1: Big-endian
>>> +     J[24]                   1: Jazelle instruction set
>>> + */
>>> +#define CPSR_M_USR                   0x00    /* User mode */
>>> +#define CPSR_M_FIQ                   0x01    /* Fast Interrupt mode */
>>> +#define CPSR_M_IRQ                   0x02    /* Interrupt mode */
>>> +#define CPSR_M_SVR                   0x03    /* Supervisor mode */
>>> +#define CPSR_M_MON                   0x06    /* Monitor mode */
>>> +#define CPSR_M_ABT                   0x07    /* Abort mode */
>>> +#define CPSR_M_HYP                   0x0A    /* Hypervisor mode */
>>> +#define CPSR_M_UND                   0x0B    /* Undefined mode */
>>> +#define CPSR_M_SYS                   0x0F    /* System mode */
>>> +#define CPSR_M_32BIT         0x10    /* 32-bit mode */
>>> +#define CPSR_T_BIT                   0x20    /* Thumb bit */
>>> +#define CPSR_F_MASK                  0x40    /* FIQ bit */
>>> +#define CPSR_I_MASK                  0x80    /* IRQ bit */
>>> +
>>> +#define CPSR_M_MASK                  0x0F    /* Mode mask except M[4] */
>>> +
>>>    #endif /* _LIBGLOSS_ARM_H */
>>> diff --git a/libgloss/arm/crt0.S b/libgloss/arm/crt0.S
>>> index 1deb73aa5..95aa3b578 100644
>>> --- a/libgloss/arm/crt0.S
>>> +++ b/libgloss/arm/crt0.S
>>> @@ -59,6 +59,21 @@
>>>    .endm
>>>    #endif
>>>
>>> +/* Annotation for EABI unwinding tables. */
>>> +.macro FN_EH_START
>>> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>>> +     .fnstart
>>> +#endif
>>> +.endm
>>> +
>>> +.macro FN_EH_END
>>> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>>> +     /* Protect against unhandled exceptions.  */
>>> +     .cantunwind
>>> +     .fnend
>>> +#endif
>>> +.endm
>>> +
>>>    .macro indirect_call reg
>>>    #ifdef HAVE_CALL_INDIRECT
>>>        blx \reg
>>> @@ -68,16 +83,170 @@
>>>    #endif
>>>    .endm
>>>
>>> +/* For armv4t and newer, toolchains will transparently convert
>>> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
>>> +   for anything older than armv4t, but this should handle that
>>> +   corner case in case anyone needs it anyway */
>>> +.macro  FN_RETURN
>>> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
>>> +     mov     pc, lr
>>> +#else
>>> +     bx      lr
>>> +#endif
>>> +.endm
>>> +
>>> +
>>> +
>>> +/******************************************************************************
>>> +* User mode only:           This routine makes default target specific Stack
>>> +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
>>> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
>>> +*   | SYS |               and setups a default Stack Limit in-case the code has
>>> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
>>> +*   |     |               System (User) modes.
>>> +*   |     |
>>> +*   +-----+ <- initial SP,
>>> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
>>> +*           and SL_usr     currently no support for checking that the heap and
>>> +*                          stack have not collided, or that this default 64k is
>>> +* All modes:               is enough for the program being executed. However,
>>> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
>>> +*   |     |    SL_usr      immediately cause an overflow event.
>>> +*   | SYS |
>>> +*   | USR | -=0x10000        We go through all execution modes and set up SP
>>> +*   |     |                for each of them.
>>> +*   +-----+ <- SP_sys,
>>> +*   |     |    SP_usr      Note:
>>> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
>>> +*   |     |                  non-privileged mode, so we take care not to enter
>>> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
>>> +*   |     |                  operations if already in that mode.
>>> +*   | IRQ | -= 0x2000
>>> +*   |     |                Input parameters:
>>> +* ^ +-----+ <- SP_und       - sp - Initialized SP
>>> +* s |     |                 - r2 - May contain SL value from semihosting
>>> +* t | UND | -= 0x1000              SYS_HEAPINFO call
>>> +* a |     |                Scratch registers:
>>> +* c +-----+ <- SP_und       - r1 - new value of CPSR
>>> +* k |     |                 - r2 - intermediate value (in standalone mode)
>>> +*   | ABT | -= 0x1000       - r3 - new SP value
>>> +* g |     |                 - r4 - save/restore CPSR on entry/exit
>>> +* r +-----+ <- SP_abt,
>>> +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
>>> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
>>> +* t |     |
>>> +* h +-----+ <- initial SP,
>>> +*           becomes SP_fiq
>>> +*
>>> +******************************************************************************/
>>> +     .align  0
>>> +     FUNC_START      _stack_init
>>> +     .weak FUNCTION (_stack_init)
>>> +     FN_EH_START
>>> +
>>> +     /* M profile doesn't have CPSR register.  */
>>> +#if (__ARM_ARCH_PROFILE != 'M')
>>> +     /* Following code is compatible for both ARM and Thumb ISA */
>>> +     mrs     r4, CPSR
>>> +     /* Test mode bits - in User of all are 0 */
>>> +     tst     r4, #(CPSR_M_MASK)
>>> +     /* "eq" means r4 AND #0x0F is 0 */
>>> +     beq     .Lskip_cpu_modes
>>> +
>>> +     mov     r3, sp /* save input SP value */
>>> +
>>> +     /* FIQ mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +     sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
>>> +
>>> +     /* Abort mode, interrupts disabled */
>>> +     mov     r3, sl
>>> +     mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +     sub     r3, r3, #0x1000
>>> +
>>> +     /* Undefined mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +     sub     r3, r3, #0x1000
>>> +
>>> +     /* IRQ mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +     sub     r3, r3, #0x2000
>>> +
>>> +     /* Supervisory mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +
>>> +     sub     r3, r3, #0x8000 /* Min size 32k */
>>> +     bic     r3, r3, #0x00FF /* Align with current 64k block */
>>> +     bic     r3, r3, #0xFF00
>>> +
>>> +# if __ARM_ARCH >= 4
>>> +     /* System (shares regs with User) mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +# else
>>> +     /* Keep this for ARMv3, but GCC actually dropped it. */
>>> +     /* Move value into user mode sp without changing modes, */
>>> +     /* via '^' form of ldm */
>>> +     str     r3, [r3, #-4]
>>> +     ldmdb   r3, {sp}^
>>> +# endif
>>> +
>>> +     /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
>>> +     orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r4
>>> +
>>> +.Lskip_cpu_modes:
>>> +#endif
>>> +
>>> +     /* Set SL register */
>>> +#if defined (ARM_RDI_MONITOR) /* semihosting */
>>> +     cmp     r2, #0
>>> +     beq     .Lsl_forced_zero
>>> +     /* allow slop for stack overflow handling and small frames */
>>> +# ifdef THUMB1_ONLY
>>> +     adds    r2, #128
>>> +     adds    r2, #128
>>> +     mov     sl, r2
>>> +# else
>>> +     add     sl, r2, #256
>>> +# endif
>>> +.Lsl_forced_zero:
>>> +
>>> +#else /* standalone */
>>> +     /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
>>> +     #ifdef THUMB1_ONLY
>>> +     movs    r2, #64
>>> +     lsls    r2, r2, #10
>>> +     subs    r2, r3, r2
>>> +     mov     sl, r2
>>> +     #else
>>> +     /* Still assumes 256bytes below sl */
>>> +     sub     sl, r3, #64 << 10
>>> +     #endif
>>> +#endif
>>> +
>>> +     FN_RETURN
>>> +     FN_EH_END
>>> +
>>> +
>>>    /*******************************************************************************
>>>    * Main library startup code.
>>>    *******************************************************************************/
>>>        .align  0
>>>        FUNC_START      _mainCRTStartup
>>>        FUNC_START      _start
>>> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>>> -     /* Annotation for EABI unwinding tables.  */
>>> -     .fnstart
>>> -#endif
>>> +     FN_EH_START
>>>
>>>        /* __ARM_ARCH_PROFILE is defined from GCC 4.8 onwards, however __ARM_ARCH_7A
>>>        has been defined since 4.2 onwards, which is when v7-a support was added
>>> @@ -150,36 +319,27 @@
>>>              to skip setting sp/sl to 0 here.
>>>            - Considering M-profile processors, We might want to initialize
>>>              sp by the first entry of vector table and return 0 to SYS_HEAPINFO
>>> -           semihosting call, which will be skipped here.  */
>>> +           semihosting call, which will be skipped here.
>>> +         - Considering R-profile processors there is no automatic SP init by hardware
>>> +           so we need to initialize it by default value. */
>>> +     ldr     r3, .Lstack
>>>        cmp     r1, #0
>>>        beq     .LC26
>>> -     mov     sp, r1
>>> +     mov     r3, r1
>>>    .LC26:
>>> -     cmp     r2, #0
>>> -     beq     .LC27
>>> +     mov     sp, r3
>>>
>>> -     /*  Allow slop for stack overflow handling and small frames.  */
>>> -#ifdef THUMB1_ONLY
>>> -     adds    r2, #128
>>> -     adds    r2, #128
>>> -     mov     sl, r2
>>> -#else
>>> -     add     sl, r2, #256
>>> -#endif
>>> +     /* r2 (SL value) will be used in _stack_init */
>>> +     bl FUNCTION (_stack_init)
>>>
>>> -.LC27:
>>> -#else
>>> -     /*  Set up the stack pointer to a fixed value.  */
>>> +
>>> +#else /* standalone */
>>> +     /*  Set up the stack pointer to a fixed value. */
>>>        /*  Changes by toralf:
>>>            - Allow linker script to provide stack via __stack symbol - see
>>>              defintion of .Lstack
>>>            - Provide "hooks" that may be used by the application to add
>>> -           custom init code - see .Lhwinit and .Lswinit
>>> -         - Go through all execution modes and set up stack for each of them.
>>> -           Loosely based on init.s from ARM/Motorola example code.
>>> -              Note: Mode switch via CPSR is not allowed once in non-privileged
>>> -                 mode, so we take care not to enter "User" to set up its sp,
>>> -                 and also skip most operations if already in that mode.  */
>>> +           custom init code - see .Lhwinit and .Lswinit */
>>>
>>>        ldr     r3, .Lstack
>>>        cmp     r3, #0
>>> @@ -198,57 +358,10 @@
>>>                 have somehow missed it below (in which case it gets the same
>>>                 value as FIQ - not ideal, but better than nothing).  */
>>>        mov     sp, r3
>>> -#ifdef PREFER_THUMB
>>> -     /* XXX Fill in stack assignments for interrupt modes.  */
>>> -#else
>>> -     mrs     r2, CPSR
>>> -     tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
>>> -     beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
>>> -     msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
>>> -     mov     sp, r3
>>> -     sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
>>> -
>>> -     mov     r3, sl
>>> -     msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
>>> -     mov     sp, r3
>>> -     sub     r3, r3, #0x1000
>>> -
>>> -     msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
>>> -     mov     sp, r3
>>> -     sub     r3, r3, #0x1000
>>>
>>> -     msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
>>> -     mov     sp, r3
>>> -     sub     r3, r3, #0x2000
>>> -
>>> -     msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
>>> +     /* we don't care of r2 value in standalone */
>>> +     bl FUNCTION (_stack_init)
>>>
>>> -     mov     sp, r3
>>> -     sub     r3, r3, #0x8000 /* Min size 32k.  */
>>> -     bic     r3, r3, #0x00FF /* Align with current 64k block.  */
>>> -     bic     r3, r3, #0xFF00
>>> -
>>> -     str     r3, [r3, #-4]   /* Move value into user mode sp without */
>>> -     ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
>>> -     orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
>>> -     msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
>>> -#endif
>>> -.LC23:
>>> -     /* Setup a default stack-limit in-case the code has been
>>> -        compiled with "-mapcs-stack-check".  Hard-wiring this value
>>> -        is not ideal, since there is currently no support for
>>> -        checking that the heap and stack have not collided, or that
>>> -        this default 64k is enough for the program being executed.
>>> -        However, it ensures that this simple crt0 world will not
>>> -        immediately cause an overflow event:  */
>>> -#ifdef THUMB1_ONLY
>>> -     movs    r2, #64
>>> -     lsls    r2, r2, #10
>>> -     subs    r2, r3, r2
>>> -     mov     sl, r2
>>> -#else
>>> -     sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
>>> -#endif
>>>    #endif
>>>    #endif
>>>        /* Zero the memory in the .bss section.  */
>>> @@ -447,6 +560,8 @@ change_back:
>>>        swi     SWI_Exit
>>>    #endif
>>>
>>> +     FN_EH_END
>>> +
>>>        /* For Thumb, constants must be after the code since only
>>>           positive offsets are supported for PC relative addresses.  */
>>>        .align 0
>>> @@ -464,9 +579,6 @@ change_back:
>>>    #else
>>>        .word   0x80000                 /* Top of RAM on the PIE board.  */
>>>    #endif
>>> -
>>> -.Lstack:
>>> -     .word   __stack
>>>    .Lhwinit:
>>>        .word   FUNCTION (hardware_init_hook)
>>>    .Lswinit:
>>> @@ -479,17 +591,16 @@ change_back:
>>>           and only if, a normal version of the same symbol isn't provided
>>>           e.g. by a linker script or another object file.)  */
>>>
>>> -     .weak __stack
>>>        .weak FUNCTION (hardware_init_hook)
>>>        .weak FUNCTION (software_init_hook)
>>>    #endif
>>>
>>>    #endif
>>> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>>> -     /* Protect against unhandled exceptions.  */
>>> -     .cantunwind
>>> -     .fnend
>>> -#endif
>>> +
>>> +.Lstack:
>>> +     .word   __stack
>>> +     .weak   __stack
>>> +
>>>    .LC1:
>>>        .word   __bss_start__
>>>    .LC2:
>>> diff --git a/newlib/libc/sys/arm/arm.h b/newlib/libc/sys/arm/arm.h
>>> index 0489f2d92..04b3a5ac7 100644
>>> --- a/newlib/libc/sys/arm/arm.h
>>> +++ b/newlib/libc/sys/arm/arm.h
>>> @@ -61,4 +61,30 @@
>>>    # define HAVE_CALL_INDIRECT
>>>    #endif
>>>
>>> +/* A and R profiles (and legacy Arm).
>>> +     Current Program Status Register (CPSR)
>>> +     M[4:0]          Mode bits. M[4] is always 1 for 32-bit modes.
>>> +     T[5]                    1: Thumb, 0: ARM instruction set
>>> +     F[6]                    1: disables FIQ
>>> +     I[7]                    1: disables IRQ
>>> +     A[8]                    1: disables imprecise aborts
>>> +     E[9]                    0: Little-endian, 1: Big-endian
>>> +     J[24]                   1: Jazelle instruction set
>>> + */
>>> +#define CPSR_M_USR                   0x00    /* User mode */
>>> +#define CPSR_M_FIQ                   0x01    /* Fast Interrupt mode */
>>> +#define CPSR_M_IRQ                   0x02    /* Interrupt mode */
>>> +#define CPSR_M_SVR                   0x03    /* Supervisor mode */
>>> +#define CPSR_M_MON                   0x06    /* Monitor mode */
>>> +#define CPSR_M_ABT                   0x07    /* Abort mode */
>>> +#define CPSR_M_HYP                   0x0A    /* Hypervisor mode */
>>> +#define CPSR_M_UND                   0x0B    /* Undefined mode */
>>> +#define CPSR_M_SYS                   0x0F    /* System mode */
>>> +#define CPSR_M_32BIT         0x10    /* 32-bit mode */
>>> +#define CPSR_T_BIT                   0x20    /* Thumb bit */
>>> +#define CPSR_F_MASK                  0x40    /* FIQ bit */
>>> +#define CPSR_I_MASK                  0x80    /* IRQ bit */
>>> +
>>> +#define CPSR_M_MASK                  0x0F    /* Mode mask except M[4] */
>>> +
>>>    #endif /* _LIBGLOSS_ARM_H */
>>> diff --git a/newlib/libc/sys/arm/crt0.S b/newlib/libc/sys/arm/crt0.S
>>> index 7a6b40d9a..0929a435e 100644
>>> --- a/newlib/libc/sys/arm/crt0.S
>>> +++ b/newlib/libc/sys/arm/crt0.S
>>> @@ -59,6 +59,21 @@
>>>    .endm
>>>    #endif
>>>
>>> +/* Annotation for EABI unwinding tables. */
>>> +.macro FN_EH_START
>>> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>>> +     .fnstart
>>> +#endif
>>> +.endm
>>> +
>>> +.macro FN_EH_END
>>> +#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>>> +     /* Protect against unhandled exceptions.  */
>>> +     .cantunwind
>>> +     .fnend
>>> +#endif
>>> +.endm
>>> +
>>>    .macro indirect_call reg
>>>    #ifdef HAVE_CALL_INDIRECT
>>>        blx \reg
>>> @@ -68,16 +83,170 @@
>>>    #endif
>>>    .endm
>>>
>>> +/* For armv4t and newer, toolchains will transparently convert
>>> +   'bx lr' to 'mov pc, lr' if needed. GCC has deprecated support
>>> +   for anything older than armv4t, but this should handle that
>>> +   corner case in case anyone needs it anyway */
>>> +.macro  FN_RETURN
>>> +#if __ARM_ARCH <= 4 && __ARM_ARCH_ISA_THUMB == 0
>>> +     mov     pc, lr
>>> +#else
>>> +     bx      lr
>>> +#endif
>>> +.endm
>>> +
>>> +
>>> +
>>> +/******************************************************************************
>>> +* User mode only:           This routine makes default target specific Stack
>>> +*   +-----+ <- SL_sys,    Pointer initialization for different processor modes:
>>> +*   |     |    SL_usr     FIQ, Abort, IRQ, Undefined, Supervisor, System (User)
>>> +*   | SYS |               and setups a default Stack Limit in-case the code has
>>> +*   | USR | -=0x10000     been compiled with "-mapcs-stack-check" for FIQ and
>>> +*   |     |               System (User) modes.
>>> +*   |     |
>>> +*   +-----+ <- initial SP,
>>> +*           becomes SP_sys   Hard-wiring SL value is not ideal, since there is
>>> +*           and SL_usr     currently no support for checking that the heap and
>>> +*                          stack have not collided, or that this default 64k is
>>> +* All modes:               is enough for the program being executed. However,
>>> +*   +-----+ <- SL_sys,     it ensures that this simple crt0 world will not
>>> +*   |     |    SL_usr      immediately cause an overflow event.
>>> +*   | SYS |
>>> +*   | USR | -=0x10000        We go through all execution modes and set up SP
>>> +*   |     |                for each of them.
>>> +*   +-----+ <- SP_sys,
>>> +*   |     |    SP_usr      Note:
>>> +*   | SVC | -= 0x8000        Mode switch via CPSR is not allowed once in
>>> +*   |     |                  non-privileged mode, so we take care not to enter
>>> +*   +-----+ <- SP_svc        "User" to set up its sp, and also skip most
>>> +*   |     |                  operations if already in that mode.
>>> +*   | IRQ | -= 0x2000
>>> +*   |     |                Input parameters:
>>> +* ^ +-----+ <- SP_und       - sp - Initialized SP
>>> +* s |     |                 - r2 - May contain SL value from semihosting
>>> +* t | UND | -= 0x1000              SYS_HEAPINFO call
>>> +* a |     |                Scratch registers:
>>> +* c +-----+ <- SP_und       - r1 - new value of CPSR
>>> +* k |     |                 - r2 - intermediate value (in standalone mode)
>>> +*   | ABT | -= 0x1000       - r3 - new SP value
>>> +* g |     |                 - r4 - save/restore CPSR on entry/exit
>>> +* r +-----+ <- SP_abt,
>>> +* o |     |    SL_fiq        Declared as "weak" so that user can write and use
>>> +* w | FIQ | -= 0x1000      his own implementation if current doesn't fit.
>>> +* t |     |
>>> +* h +-----+ <- initial SP,
>>> +*           becomes SP_fiq
>>> +*
>>> +******************************************************************************/
>>> +     .align  0
>>> +     FUNC_START      _stack_init
>>> +     .weak FUNCTION (_stack_init)
>>> +     FN_EH_START
>>> +
>>> +     /* M profile doesn't have CPSR register.  */
>>> +#if (__ARM_ARCH_PROFILE != 'M')
>>> +     /* Following code is compatible for both ARM and Thumb ISA */
>>> +     mrs     r4, CPSR
>>> +     /* Test mode bits - in User of all are 0 */
>>> +     tst     r4, #(CPSR_M_MASK)
>>> +     /* "eq" means r4 AND #0x0F is 0 */
>>> +     beq     .Lskip_cpu_modes
>>> +
>>> +     mov     r3, sp /* save input SP value */
>>> +
>>> +     /* FIQ mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_FIQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +     sub     sl, sp, #0x1000 /* FIQ mode has its own SL */
>>> +
>>> +     /* Abort mode, interrupts disabled */
>>> +     mov     r3, sl
>>> +     mov     r1, #(CPSR_M_ABT|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +     sub     r3, r3, #0x1000
>>> +
>>> +     /* Undefined mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_UND|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +     sub     r3, r3, #0x1000
>>> +
>>> +     /* IRQ mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_IRQ|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +     sub     r3, r3, #0x2000
>>> +
>>> +     /* Supervisory mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_SVR|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +
>>> +     sub     r3, r3, #0x8000 /* Min size 32k */
>>> +     bic     r3, r3, #0x00FF /* Align with current 64k block */
>>> +     bic     r3, r3, #0xFF00
>>> +
>>> +# if __ARM_ARCH >= 4
>>> +     /* System (shares regs with User) mode, interrupts disabled */
>>> +     mov     r1, #(CPSR_M_SYS|CPSR_M_32BIT|CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r1
>>> +     mov     sp, r3
>>> +# else
>>> +     /* Keep this for ARMv3, but GCC actually dropped it. */
>>> +     /* Move value into user mode sp without changing modes, */
>>> +     /* via '^' form of ldm */
>>> +     str     r3, [r3, #-4]
>>> +     ldmdb   r3, {sp}^
>>> +# endif
>>> +
>>> +     /* Back to original mode, presumably SVC, with diabled FIQ/IRQ */
>>> +     orr     r4, r4, #(CPSR_I_MASK|CPSR_F_MASK)
>>> +     msr     CPSR_c, r4
>>> +
>>> +.Lskip_cpu_modes:
>>> +#endif
>>> +
>>> +     /* Set SL register */
>>> +#if defined (ARM_RDI_MONITOR) /* semihosting */
>>> +     cmp     r2, #0
>>> +     beq     .Lsl_forced_zero
>>> +     /* allow slop for stack overflow handling and small frames */
>>> +# ifdef THUMB1_ONLY
>>> +     adds    r2, #128
>>> +     adds    r2, #128
>>> +     mov     sl, r2
>>> +# else
>>> +     add     sl, r2, #256
>>> +# endif
>>> +.Lsl_forced_zero:
>>> +
>>> +#else /* standalone */
>>> +     /* r3 contains SP for System/User mode. Set SL = SP - 0x10000 */
>>> +     #ifdef THUMB1_ONLY
>>> +     movs    r2, #64
>>> +     lsls    r2, r2, #10
>>> +     subs    r2, r3, r2
>>> +     mov     sl, r2
>>> +     #else
>>> +     /* Still assumes 256bytes below sl */
>>> +     sub     sl, r3, #64 << 10
>>> +     #endif
>>> +#endif
>>> +
>>> +     FN_RETURN
>>> +     FN_EH_END
>>> +
>>> +
>>>    /*******************************************************************************
>>>    * Main library startup code.
>>>    *******************************************************************************/
>>>        .align  0
>>>        FUNC_START      _mainCRTStartup
>>>        FUNC_START      _start
>>> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>>> -     /* Annotation for EABI unwinding tables.  */
>>> -     .fnstart
>>> -#endif
>>> +     FN_EH_START
>>>
>>>    /* Start by setting up a stack.  */
>>>    #ifdef ARM_RDP_MONITOR
>>> @@ -130,36 +299,27 @@
>>>              to skip setting sp/sl to 0 here.
>>>            - Considering M-profile processors, We might want to initialize
>>>              sp by the first entry of vector table and return 0 to SYS_HEAPINFO
>>> -           semihosting call, which will be skipped here.  */
>>> +           semihosting call, which will be skipped here.
>>> +         - Considering R-profile processors there is no automatic SP init by hardware
>>> +           so we need to initialize it by default value. */
>>> +     ldr     r3, .Lstack
>>>        cmp     r1, #0
>>>        beq     .LC26
>>> -     mov     sp, r1
>>> +     mov     r3, r1
>>>    .LC26:
>>> -     cmp     r2, #0
>>> -     beq     .LC27
>>> +     mov     sp, r3
>>>
>>> -     /*  Allow slop for stack overflow handling and small frames.  */
>>> -#ifdef THUMB1_ONLY
>>> -     adds    r2, #128
>>> -     adds    r2, #128
>>> -     mov     sl, r2
>>> -#else
>>> -     add     sl, r2, #256
>>> -#endif
>>> +     /* r2 (SL value) will be used in _stack_init */
>>> +     bl FUNCTION (_stack_init)
>>>
>>> -.LC27:
>>> -#else
>>> -     /*  Set up the stack pointer to a fixed value.  */
>>> +
>>> +#else /* standalone */
>>> +     /*  Set up the stack pointer to a fixed value. */
>>>        /*  Changes by toralf:
>>>            - Allow linker script to provide stack via __stack symbol - see
>>>              defintion of .Lstack
>>>            - Provide "hooks" that may be used by the application to add
>>> -           custom init code - see .Lhwinit and .Lswinit
>>> -         - Go through all execution modes and set up stack for each of them.
>>> -           Loosely based on init.s from ARM/Motorola example code.
>>> -              Note: Mode switch via CPSR is not allowed once in non-privileged
>>> -                 mode, so we take care not to enter "User" to set up its sp,
>>> -                 and also skip most operations if already in that mode.  */
>>> +           custom init code - see .Lhwinit and .Lswinit */
>>>
>>>        ldr     r3, .Lstack
>>>        cmp     r3, #0
>>> @@ -178,57 +338,10 @@
>>>                 have somehow missed it below (in which case it gets the same
>>>                 value as FIQ - not ideal, but better than nothing).  */
>>>        mov     sp, r3
>>> -#ifdef PREFER_THUMB
>>> -     /* XXX Fill in stack assignments for interrupt modes.  */
>>> -#else
>>> -     mrs     r2, CPSR
>>> -     tst     r2, #0x0F       /* Test mode bits - in User of all are 0.  */
>>> -     beq     .LC23           /* "eq" means r2 AND #0x0F is 0.  */
>>> -     msr     CPSR_c, #0xD1   /* FIRQ mode, interrupts disabled.  */
>>> -     mov     sp, r3
>>> -     sub     sl, sp, #0x1000 /* This mode also has its own sl (see below).  */
>>> -
>>> -     mov     r3, sl
>>> -     msr     CPSR_c, #0xD7   /* Abort mode, interrupts disabled.  */
>>> -     mov     sp, r3
>>> -     sub     r3, r3, #0x1000
>>> -
>>> -     msr     CPSR_c, #0xDB   /* Undefined mode, interrupts disabled.  */
>>> -     mov     sp, r3
>>> -     sub     r3, r3, #0x1000
>>>
>>> -     msr     CPSR_c, #0xD2   /* IRQ mode, interrupts disabled.  */
>>> -     mov     sp, r3
>>> -     sub     r3, r3, #0x2000
>>> -
>>> -     msr     CPSR_c, #0xD3   /* Supervisory mode, interrupts disabled.  */
>>> +     /* we don't care of r2 value in standalone */
>>> +     bl FUNCTION (_stack_init)
>>>
>>> -     mov     sp, r3
>>> -     sub     r3, r3, #0x8000 /* Min size 32k.  */
>>> -     bic     r3, r3, #0x00FF /* Align with current 64k block.  */
>>> -     bic     r3, r3, #0xFF00
>>> -
>>> -     str     r3, [r3, #-4]   /* Move value into user mode sp without */
>>> -     ldmdb   r3, {sp}^       /* changing modes, via '^' form of ldm.  */
>>> -     orr     r2, r2, #0xC0   /* Back to original mode, presumably SVC, */
>>> -     msr     CPSR_c, r2      /* with FIQ/IRQ disable bits forced to 1.  */
>>> -#endif
>>> -.LC23:
>>> -     /* Setup a default stack-limit in-case the code has been
>>> -        compiled with "-mapcs-stack-check".  Hard-wiring this value
>>> -        is not ideal, since there is currently no support for
>>> -        checking that the heap and stack have not collided, or that
>>> -        this default 64k is enough for the program being executed.
>>> -        However, it ensures that this simple crt0 world will not
>>> -        immediately cause an overflow event:  */
>>> -#ifdef THUMB1_ONLY
>>> -     movs    r2, #64
>>> -     lsls    r2, r2, #10
>>> -     subs    r2, r3, r2
>>> -     mov     sl, r2
>>> -#else
>>> -     sub     sl, r3, #64 << 10       /* Still assumes 256bytes below sl.  */
>>> -#endif
>>>    #endif
>>>    #endif
>>>        /* Zero the memory in the .bss section.  */
>>> @@ -421,6 +534,8 @@ change_back:
>>>        swi     SWI_Exit
>>>    #endif
>>>
>>> +     FN_EH_END
>>> +
>>>        /* For Thumb, constants must be after the code since only
>>>           positive offsets are supported for PC relative addresses.  */
>>>        .align 0
>>> @@ -438,9 +553,6 @@ change_back:
>>>    #else
>>>        .word   0x80000                 /* Top of RAM on the PIE board.  */
>>>    #endif
>>> -
>>> -.Lstack:
>>> -     .word   __stack
>>>    .Lhwinit:
>>>        .word   FUNCTION (hardware_init_hook)
>>>    .Lswinit:
>>> @@ -453,17 +565,16 @@ change_back:
>>>           and only if, a normal version of the same symbol isn't provided
>>>           e.g. by a linker script or another object file.)  */
>>>
>>> -     .weak __stack
>>>        .weak FUNCTION (hardware_init_hook)
>>>        .weak FUNCTION (software_init_hook)
>>>    #endif
>>>
>>>    #endif
>>> -#if defined(__ELF__) && !defined(__USING_SJLJ_EXCEPTIONS__)
>>> -     /* Protect against unhandled exceptions.  */
>>> -     .cantunwind
>>> -     .fnend
>>> -#endif
>>> +
>>> +.Lstack:
>>> +     .word   __stack
>>> +     .weak   __stack
>>> +
>>>    .LC1:
>>>        .word   __bss_start__
>>>    .LC2:
>>>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/2] Align comments and spaces in libgloss/arm/crt0.S and newlib/libc/sys/arm/crt0.S to ease further code alignment.

Corinna Vinschen
In reply to this post by Alexander Fedotov
On Jul 18 16:49, Alexander Fedotov wrote:
> Hi Richard
>
> Could you please apply it for me. I have no write permissions.

Not sure what's going on here, Richard applied it on 2019-04-12.
Am I missing something?


Corinna

--
Corinna Vinschen
Cygwin Maintainer
Red Hat

signature.asc (849 bytes) Download Attachment