firmware: split ARM classic & Cortex-M thread implementations

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit af4ff3e270ba1549521ce2e9aa246cc860a969f3
Author: Aidan MacDonald <[email protected]>
Date:   Mon Jan 12 11:01:41 2026 +0000

    firmware: split ARM classic & Cortex-M thread implementations
    
    The implementations diverge enough that it is too confusing
    to support them in the same source file; split them so it
    is easier to understand.
    
    Change-Id: Ic2f91c75e8a9bb605241441f2caed841585f5b87

diff --git a/firmware/asm/arm/thread.c b/firmware/asm/arm/thread-classic.c
similarity index 88%
rename from firmware/asm/arm/thread.c
rename to firmware/asm/arm/thread-classic.c
index 1ef836b128..d2014fc951 100644
--- a/firmware/asm/arm/thread.c
+++ b/firmware/asm/arm/thread-classic.c
@@ -29,11 +29,7 @@ static void __attribute__((naked)) USED_ATTR start_thread(void)
 {
     /* r0 = context */
     asm volatile (
-#if defined(CPU_ARM_MICRO) && ARCH_VERSION >= 7
-        "ldr    sp, [r0, #36]            \n" /* Load initial sp */
-#else
         "ldr    sp, [r0, #32]            \n" /* Load initial sp */
-#endif
         "ldr    r4, [r0, #40]            \n" /* start in r4 since it's non-volatile */
         "mov    r1, #0                   \n" /* Mark thread as running */
         "str    r1, [r0, #40]            \n"
@@ -65,12 +61,7 @@ static void __attribute__((naked)) USED_ATTR start_thread(void)
 static inline void store_context(void* addr)
 {
     asm volatile(
-#if defined(CPU_ARM_MICRO) && ARCH_VERSION >= 7
-        "stmia  %0, { r4-r11, lr }     \n"
-        "str    sp, [%0, #36]          \n"
-#else
         "stmia  %0, { r4-r11, sp, lr } \n"
-#endif
         : : "r" (addr)
     );
 }
@@ -94,16 +85,8 @@ static inline void load_context(const void* addr)
         "ldmiane %0, { r0, pc }         \n"
 #endif
 
-#if defined(CPU_ARM_MICRO) && ARCH_VERSION >= 7
-        "mov     r0, %0                 \n"
-        "ldmia   r0, { r4-r11, lr }     \n"
-        "ldr     sp, [r0, #36]          \n"
-#else
         "ldmia   %0, { r4-r11, sp, lr } \n" /* Load regs r4 to r14 from context */
-#endif
         END_ARM_ASM_SYNTAX_UNIFIED
         : : "r" (addr) : "r0" /* only! */
     );
 }
-
-
diff --git a/firmware/asm/arm/thread.h b/firmware/asm/arm/thread-classic.h
similarity index 75%
rename from firmware/asm/arm/thread.h
rename to firmware/asm/arm/thread-classic.h
index 1cfc3741da..533a088979 100644
--- a/firmware/asm/arm/thread.h
+++ b/firmware/asm/arm/thread-classic.h
@@ -21,20 +21,6 @@
 
 #include "config.h"
 
-#if defined(CPU_ARM_MICRO) && ARCH_VERSION >= 7
-/*
- * Cortex-M cannot load/store SP with ldm/stm so we need to store it
- * separately. This makes it slightly more efficient to store SP last
- * so as not to split the register list.
- */
-struct regs
-{
-    uint32_t r[8];  /*  0-28 - Registers r4-r11 */
-    uint32_t lr;    /*    32 - r14 (lr) */
-    uint32_t sp;    /*    36 - Stack pointer (r13) */
-    uint32_t start; /*    40 - Thread start address, or NULL when started */
-};
-#else
 struct regs
 {
     uint32_t r[8];  /*  0-28 - Registers r4-r11 */
@@ -42,7 +28,6 @@ struct regs
     uint32_t lr;    /*    36 - r14 (lr) */
     uint32_t start; /*    40 - Thread start address, or NULL when started */
 };
-#endif
 
 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
   #include <errno.h>
diff --git a/firmware/asm/arm/thread-micro.c b/firmware/asm/arm/thread-micro.c
new file mode 100644
index 0000000000..9ad329b55d
--- /dev/null
+++ b/firmware/asm/arm/thread-micro.c
@@ -0,0 +1,88 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Thom Johansen
+ * Copyright (C) 2026 by Aidan MacDonald
+ *
+ * Threading support for ARM Cortex-M targets
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+/*---------------------------------------------------------------------------
+ * Start the thread running and terminate it if it returns
+ *---------------------------------------------------------------------------
+ */
+static void __attribute__((naked)) USED_ATTR start_thread(void)
+{
+    /* r0 = context */
+    asm volatile (
+        "ldr    sp, [r0, #36]            \n" /* Load initial sp */
+        "ldr    r4, [r0, #40]            \n" /* start in r4 since it's non-volatile */
+        "mov    r1, #0                   \n" /* Mark thread as running */
+        "str    r1, [r0, #40]            \n"
+        "mov    lr, pc                   \n" /* Call thread function */
+        "bx     r4                       \n"
+    ); /* No clobber list - new thread doesn't care */
+    thread_exit();
+}
+
+/* For startup, place context pointer in r4 slot, start_thread pointer in r5
+ * slot, and thread function pointer in context.start. See load_context for
+ * what happens when thread is initially going to run. */
+#define THREAD_STARTUP_INIT(core, thread, function) \
+    ({ (thread)->context.r[0] = (uint32_t)&(thread)->context,  \
+       (thread)->context.r[1] = (uint32_t)start_thread, \
+       (thread)->context.start = (uint32_t)function; })
+
+
+/*---------------------------------------------------------------------------
+ * Store non-volatile context.
+ *---------------------------------------------------------------------------
+ */
+static inline void store_context(void* addr)
+{
+    asm volatile(
+        "stmia  %0, { r4-r11, lr }     \n"
+        "str    sp, [%0, #36]          \n"
+        : : "r" (addr)
+    );
+}
+
+/*---------------------------------------------------------------------------
+ * Load non-volatile context.
+ *---------------------------------------------------------------------------
+ */
+static inline void load_context(const void* addr)
+{
+    asm volatile(
+        BEGIN_ARM_ASM_SYNTAX_UNIFIED
+
+        "ldr     r0, [%0, #40]          \n" /* Load start pointer */
+        "cmp     r0, #0                 \n" /* Check for NULL */
+
+        /* If not already running, jump to start */
+        "ldmiane %0, { r0, pc }         \n"
+
+        /* Load regs r4 to r14 from context */
+        "mov     r0, %0                 \n"
+        "ldmia   r0, { r4-r11, lr }     \n"
+        "ldr     sp, [r0, #36]          \n"
+
+        END_ARM_ASM_SYNTAX_UNIFIED
+        : : "r" (addr) : "r0" /* only! */
+    );
+}
diff --git a/firmware/asm/arm/thread-micro.h b/firmware/asm/arm/thread-micro.h
new file mode 100644
index 0000000000..67c5b4de80
--- /dev/null
+++ b/firmware/asm/arm/thread-micro.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Ulf Ralberg
+ * Copyright (C) 2026 by Aidan MacDonald
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+
+/*
+ * Cortex-M cannot load/store SP with ldm/stm so we need to store it
+ * separately. This makes it slightly more efficient to store SP last
+ * so as not to split the register list.
+ */
+struct regs
+{
+    uint32_t r[8];  /*  0-28 - Registers r4-r11 */
+    uint32_t lr;    /*    32 - r14 (lr) */
+    uint32_t sp;    /*    36 - Stack pointer (r13) */
+    uint32_t start; /*    40 - Thread start address, or NULL when started */
+};
+
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
+# include <errno.h>
+#else
+# define DEFAULT_STACK_SIZE 0x400  /* Bytes */
+#endif
diff --git a/firmware/asm/thread.c b/firmware/asm/thread.c
index c7779b3054..e639cadc73 100644
--- a/firmware/asm/thread.c
+++ b/firmware/asm/thread.c
@@ -5,8 +5,10 @@
   #include "thread-unix.c"
 
   /* Now the CPU-specific implementations */
-#elif defined(CPU_ARM)
-  #include "arm/thread.c"
+#elif defined(CPU_ARM_CLASSIC) || defined(CPU_ARM_APPLICATION)
+  #include "arm/thread-classic.c"
+#elif defined(CPU_ARM_MICRO)
+  #include "arm/thread-micro.c"
 #elif defined(CPU_COLDFIRE)
   #include "m68k/thread.c"
 #elif defined(CPU_MIPS)
diff --git a/firmware/asm/thread.h b/firmware/asm/thread.h
index 831de9ae8d..6301b0cb05 100644
--- a/firmware/asm/thread.h
+++ b/firmware/asm/thread.h
@@ -59,8 +59,10 @@ struct regs
   #elif defined(HAVE_WIN32_FIBER_THREADS)
     #define DEFAULT_STACK_SIZE 0x1000 /* Bytes */
   #endif
-#elif defined(CPU_ARM)
-  #include "arm/thread.h"
+#elif defined(CPU_ARM_CLASSIC) || defined(CPU_ARM_APPLICATION)
+  #include "arm/thread-classic.h"
+#elif defined(CPU_ARM_MICRO)
+  #include "arm/thread-micro.h"
 #elif defined(CPU_COLDFIRE)
   #include "m68k/thread.h"
 #elif defined(CPU_MIPS)
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.