This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit b4d29329f6e5be30b78b45bd5044eec40bc06f2f
Author: zhangyu117 <[email protected]>
AuthorDate: Wed Jul 15 10:04:08 2026 +0800

    libc/tricore: rewrite setjmp with asm format.
    
    Replace the inline assembly in arch_setjmp.c with standalone assembly
    sources: gnu/arch_setjmp.S for GCC and tasking/arch_setjmp.asm for
    TASKING. The PSW/PRS/IO repair in longjmp is kept.
    
    Signed-off-by: zhangyu117 <[email protected]>
---
 libs/libc/machine/tricore/CMakeLists.txt          |   8 +-
 libs/libc/machine/tricore/Make.defs               |   8 +-
 libs/libc/machine/tricore/arch_setjmp.c           | 215 ----------------------
 libs/libc/machine/tricore/gnu/arch_setjmp.S       | 169 +++++++++++++++++
 libs/libc/machine/tricore/tasking/arch_setjmp.asm | 178 ++++++++++++++++++
 5 files changed, 355 insertions(+), 223 deletions(-)

diff --git a/libs/libc/machine/tricore/CMakeLists.txt 
b/libs/libc/machine/tricore/CMakeLists.txt
index 47ceadc4905..5ccba6d5d20 100644
--- a/libs/libc/machine/tricore/CMakeLists.txt
+++ b/libs/libc/machine/tricore/CMakeLists.txt
@@ -26,10 +26,6 @@ if(CONFIG_LIBC_ATOMIC_ARCH)
   list(APPEND SRCS arch_atomic.c)
 endif()
 
-if(CONFIG_ARCH_SETJMP_H)
-  list(APPEND SRCS arch_setjmp.c)
-endif()
-
 if(CONFIG_TRICORE_TOOLCHAIN_TASKING)
   set(TRICORE_SUBDIR tasking)
   set(ASM_EXT asm)
@@ -38,6 +34,10 @@ else()
   set(ASM_EXT S)
 endif()
 
+if(CONFIG_ARCH_SETJMP_H)
+  list(APPEND SRCS ${TRICORE_SUBDIR}/arch_setjmp.${ASM_EXT})
+endif()
+
 if(CONFIG_LIBC_ARCH_MEMCPY)
   list(APPEND SRCS ${TRICORE_SUBDIR}/arch_memcpy.${ASM_EXT})
 endif()
diff --git a/libs/libc/machine/tricore/Make.defs 
b/libs/libc/machine/tricore/Make.defs
index c56d689fb23..ad3c778a9a5 100644
--- a/libs/libc/machine/tricore/Make.defs
+++ b/libs/libc/machine/tricore/Make.defs
@@ -24,10 +24,6 @@ ifeq ($(CONFIG_LIBC_ATOMIC_ARCH),y)
 CSRCS += arch_atomic.c
 endif
 
-ifeq ($(CONFIG_ARCH_SETJMP_H),y)
-CSRCS += arch_setjmp.c
-endif
-
 ifeq ($(CONFIG_TRICORE_TOOLCHAIN_TASKING),y)
 TRICORE_SUBDIR = tasking
 else
@@ -42,6 +38,10 @@ AFLAGS += 
${INCDIR_PREFIX}$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)machine$(DELI
 
 AFLAGS += -Wa,-mtc18
 
+ifeq ($(CONFIG_ARCH_SETJMP_H),y)
+ASRCS += arch_setjmp.S
+endif
+
 ifeq ($(CONFIG_LIBC_ARCH_MEMCPY),y)
 ASRCS += arch_memcpy.S
 endif
diff --git a/libs/libc/machine/tricore/arch_setjmp.c 
b/libs/libc/machine/tricore/arch_setjmp.c
deleted file mode 100644
index 41072d240f0..00000000000
--- a/libs/libc/machine/tricore/arch_setjmp.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/****************************************************************************
- * libs/libc/machine/tricore/arch_setjmp.c
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-
-#include <nuttx/compiler.h>
-#include <arch/setjmp.h>
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-int setjmp(jmp_buf env)
-{
-  __asm__ __volatile__ (
-#ifdef CONFIG_TRICORE_TOOLCHAIN_TASKING
-    "st.a   [a4]12, a11\n\t"
-    "movh.a a11, #@HIS(.Lsaveregs)\n\t"
-    "lea    a11, [a11]@LOS(.Lsaveregs)\n\t"
-    "ret\n\t"
-    ".Lsaveregs:\n\t"
-    "st.a   [a4]8, sp\n\t"
-    "st.a   [a4]32, a12\n\t"
-    "st.a   [a4]36, a13\n\t"
-    "st.a   [a4]40, a14\n\t"
-    "st.a   [a4]44, a15\n\t"
-    "st.w   [a4]16, d8\n\t"
-    "st.w   [a4]20, d9\n\t"
-    "st.w   [a4]24, d10\n\t"
-    "st.w   [a4]28, d11\n\t"
-    "st.w   [a4]48, d12\n\t"
-    "st.w   [a4]52, d13\n\t"
-    "st.w   [a4]56, d14\n\t"
-    "st.w   [a4]60, d15\n\t"
-    "mfcr   d2, #0xfe00\n\t"
-    "st.w   [a4]0, d2\n\t"
-    "mfcr   d2, #0xfe04\n\t"
-    "st.w   [a4]4, d2\n\t"
-    "ld.a   a2, [a4]12\n\t"
-    "mov    d2, #0\n\t"
-    "ji     a2\n\t"
-#else
-    "st.a   [%%a4]12, %%a11\n\t"
-    "movh.a %%a11, hi:.Lsaveregs\n\t"
-    "lea    %%a11, [%%a11] lo:.Lsaveregs\n\t"
-    "ret\n\t"
-    ".Lsaveregs:\n\t"
-    "st.a   [%%a4]8, %%sp\n\t"
-    "st.a   [%%a4]32, %%a12\n\t"
-    "st.a   [%%a4]36, %%a13\n\t"
-    "st.a   [%%a4]40, %%a14\n\t"
-    "st.a   [%%a4]44, %%a15\n\t"
-    "st.w   [%%a4]16, %%d8\n\t"
-    "st.w   [%%a4]20, %%d9\n\t"
-    "st.w   [%%a4]24, %%d10\n\t"
-    "st.w   [%%a4]28, %%d11\n\t"
-    "st.w   [%%a4]48, %%d12\n\t"
-    "st.w   [%%a4]52, %%d13\n\t"
-    "st.w   [%%a4]56, %%d14\n\t"
-    "st.w   [%%a4]60, %%d15\n\t"
-    "mfcr   %%d2, 0xfe00\n\t"
-    "st.w   [%%a4]0, %%d2\n\t"
-    "mfcr   %%d2, 0xfe04\n\t"
-    "st.w   [%%a4]4, %%d2\n\t"
-    "ld.a   %%a2, [%%a4]12\n\t"
-    "mov    %%d2, 0\n\t"
-    "ji     %%a2\n\t"
-#endif
-    ::: "memory"
-  );
-  return 0;
-}
-
-/* The CSA unwind loop below uses `ret` in .Lupper to release one Upper
- * Context per iteration.  The hardware side-effect of `ret` is that the
- * popped UC's PSW becomes the active PSW, which may put the CPU into
- * user mode / wrong PRS even though longjmp itself runs in supervisor
- * mode.  The next access to env (a4) would then fault on the MPU, since
- * jmp_buf may live in kernel-protected memory.
- *
- * To keep the unwind loop running in a known-safe context, the head of
- * .Lloop forces PSW.IO=Supervisor and PSW.PRS=0 on every iteration.
- * Once the loop terminates, the original PSW saved at setjmp time
- * (env->psw) is restored before the indirect jump back to the setjmp
- * call site.
- *
- * PSW layout on TC1.6.2 / TC1.8:
- *   bit 15    = PRS[2]
- *   bit 14    = S    (alternate master tag selector, must preserve)
- *   bit 13:12 = PRS[1:0]
- *   bit 11:10 = IO   (0b10 = Supervisor)
- */
-
-void longjmp(jmp_buf env, int val)
-{
-  __asm__ __volatile__ (
-#ifdef CONFIG_TRICORE_TOOLCHAIN_TASKING
-    "ld.w   d5, [a4]0\n\t"
-    ".Lloop:\n\t"
-    "mfcr   d3, #0xfe04\n\t"
-    "mov    d2, #2\n\t"
-    "insert d3, d3, d2, #10, #4\n\t"
-    "mov    d2, #0\n\t"
-    "insert d3, d3, d2, #15, #1\n\t"
-    "mtcr   #0xfe04, d3\n\t"
-    "isync\n\t"
-    "mfcr   d2, #0xfe00\n\t"
-    "jne    d2, d5, .Lrelease\n\t"
-    "max.u  d2, d4, #1\n\t"
-    "ld.a   a2, [a4]12\n\t"
-    "ld.a   sp, [a4]8\n\t"
-    "ld.a   a12, [a4]32\n\t"
-    "ld.a   a13, [a4]36\n\t"
-    "ld.a   a14, [a4]40\n\t"
-    "ld.a   a15, [a4]44\n\t"
-    "ld.w   d8, [a4]16\n\t"
-    "ld.w   d9, [a4]20\n\t"
-    "ld.w   d10, [a4]24\n\t"
-    "ld.w   d11, [a4]28\n\t"
-    "ld.w   d12, [a4]48\n\t"
-    "ld.w   d13, [a4]52\n\t"
-    "ld.w   d14, [a4]56\n\t"
-    "ld.w   d15, [a4]60\n\t"
-    "ld.w   d3, [a4]4\n\t"
-    "mtcr   #0xfe04, d3\n\t"
-    "isync\n\t"
-    "ji     a2\n\t"
-    ".Lrelease:\n\t"
-    "jnz.t  d2, #20, .Lupper\n\t"
-    "mov.aa a15, a4\n\t"
-    "mov    d15, d4\n\t"
-    "mov    d14, d5\n\t"
-    "rslcx\n\t"
-    "mov    d4, d15\n\t"
-    "mov    d5, d14\n\t"
-    "mov.aa a4, a15\n\t"
-    "j      .Lloop\n\t"
-    ".Lupper:\n\t"
-    "movh.a a11, #@HIS(.Lloop)\n\t"
-    "lea    a11, [a11]@LOS(.Lloop)\n\t"
-    "ret\n\t"
-#else
-    "ld.w   %%d5, [%%a4]0\n\t"
-    ".Lloop:\n\t"
-    "mfcr   %%d3, 0xfe04\n\t"
-    "mov    %%d2, 2\n\t"
-    "insert %%d3, %%d3, %%d2, 10, 4\n\t"
-    "mov    %%d2, 0\n\t"
-    "insert %%d3, %%d3, %%d2, 15, 1\n\t"
-    "mtcr   0xfe04, %%d3\n\t"
-    "isync\n\t"
-    "mfcr   %%d2, 0xfe00\n\t"
-    "jne    %%d2, %%d5, .Lrelease\n\t"
-    "max.u  %%d2, %%d4, 1\n\t"
-    "ld.a   %%a2, [%%a4]12\n\t"
-    "ld.a   %%sp, [%%a4]8\n\t"
-    "ld.a   %%a12, [%%a4]32\n\t"
-    "ld.a   %%a13, [%%a4]36\n\t"
-    "ld.a   %%a14, [%%a4]40\n\t"
-    "ld.a   %%a15, [%%a4]44\n\t"
-    "ld.w   %%d8, [%%a4]16\n\t"
-    "ld.w   %%d9, [%%a4]20\n\t"
-    "ld.w   %%d10, [%%a4]24\n\t"
-    "ld.w   %%d11, [%%a4]28\n\t"
-    "ld.w   %%d12, [%%a4]48\n\t"
-    "ld.w   %%d13, [%%a4]52\n\t"
-    "ld.w %%d14, [%%a4]56\n\t"
-    "ld.w   %%d15, [%%a4]60\n\t"
-    "ld.w   %%d3, [%%a4]4\n\t"
-    "mtcr   0xfe04, %%d3\n\t"
-    "isync\n\t"
-    "ji     %%a2\n\t"
-    ".Lrelease:\n\t"
-    "jnz.t  %%d2, 20, .Lupper\n\t"
-    "mov.aa %%a15, %%a4\n\t"
-    "mov    %%d15, %%d4\n\t"
-    "mov    %%d14, %%d5\n\t"
-    "rslcx\n\t"
-    "mov    %%d4, %%d15\n\t"
-    "mov    %%d5, %%d14\n\t"
-    "mov.aa %%a4, %%a15\n\t"
-    "j      .Lloop\n\t"
-    ".Lupper:\n\t"
-    "movh.a %%a11, hi:.Lloop\n\t"
-    "lea    %%a11, [%%a11] lo:.Lloop\n\t"
-    "ret\n\t"
-#endif
-    ::: "memory"
-  );
-
-  __builtin_unreachable();
-}
diff --git a/libs/libc/machine/tricore/gnu/arch_setjmp.S 
b/libs/libc/machine/tricore/gnu/arch_setjmp.S
new file mode 100644
index 00000000000..54baa354f79
--- /dev/null
+++ b/libs/libc/machine/tricore/gnu/arch_setjmp.S
@@ -0,0 +1,169 @@
+/****************************************************************************
+ * libs/libc/machine/tricore/gnu/arch_setjmp.S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: setjmp
+ *
+ * Description:
+ *   int setjmp(jmp_buf env)
+ *
+ *   TriCore EABI:
+ *     env -> %a4   return value -> %d2
+ *
+ *   jmp_buf layout (struct setjmp_buf_s, see arch/tricore/include/setjmp.h):
+ *     0: pcxi   4: psw    8: sp    12: a11
+ *    16: d8    20: d9    24: d10   28: d11
+ *    32: a12   36: a13   40: a14   44: a15
+ *    48: d12   52: d13   56: d14   60: d15
+ *
+ *   On entry %a11 holds the caller's return address (TriCore call ABI).
+ *   Save it into env[12] first, then repoint %a11 at .Lsaveregs and execute
+ *   `ret' which jumps through %a11.  The fall-through at .Lsaveregs stores
+ *   the remaining callee-saved registers and the PCXI/PSW control registers,
+ *   loads the saved return address into %a2, sets %d2 = 0, and jumps back
+ *   to the caller.  longjmp() returns through the same path with a nonzero
+ *   %d2.
+ *
+ ****************************************************************************/
+
+       .text
+       .global setjmp
+       .type   setjmp, %function
+
+setjmp:
+       st.a    [%a4]12, %a11           /* save return address             */
+       movh.a  %a11, hi:.Lsaveregs
+       lea     %a11, [%a11] lo:.Lsaveregs
+       ret                             /* jump to .Lsaveregs via %a11     */
+.Lsaveregs:
+       st.a    [%a4]8, %sp
+       st.a    [%a4]32, %a12
+       st.a    [%a4]36, %a13
+       st.a    [%a4]40, %a14
+       st.a    [%a4]44, %a15
+       st.w    [%a4]16, %d8
+       st.w    [%a4]20, %d9
+       st.w    [%a4]24, %d10
+       st.w    [%a4]28, %d11
+       st.w    [%a4]48, %d12
+       st.w    [%a4]52, %d13
+       st.w    [%a4]56, %d14
+       st.w    [%a4]60, %d15
+       mfcr    %d2, 0xfe00
+       st.w    [%a4]0, %d2             /* save PCXI                       */
+       mfcr    %d2, 0xfe04
+       st.w    [%a4]4, %d2             /* save PSW                        */
+       ld.a    %a2, [%a4]12            /* %a2 = return address            */
+       mov     %d2, 0                  /* setjmp returns 0                */
+       ji      %a2                     /* back to caller                  */
+       .size   setjmp, . - setjmp
+
+/****************************************************************************
+ * Name: longjmp
+ *
+ * Description:
+ *   void longjmp(jmp_buf env, int val) noreturn
+ *
+ *   TriCore EABI:
+ *     env -> %a4   val -> %d4
+ *
+ *   Unwind the CSA chain (releasing lower/upper contexts one at a time)
+ *   until the active PCXI matches the one saved by setjmp.  At that point
+ *   the register banks are at the same depth as at setjmp time, so
+ *   restoring the callee-saved registers, PSW and return address proceeds.
+ *   The result passed back equals max(val, 1) per POSIX.
+ *   The unwind loop forces PSW.IO = Supervisor and PSW.PRS[2] = 0 on every
+ *   iteration so that the `ret'-released upper contexts do not drop the CPU
+ *   into user mode while env is still being accessed.  Once the loop exits,
+ *   the original PSW saved at setjmp time is restored before the indirect
+ *   jump back to the setjmp call site.
+ *
+ *   PSW layout (TC1.6.2 / TC1.8):
+ *     bit 15      = PRS[2]
+ *     bit 14      = S    (alternate master tag selector, preserve)
+ *     bit 13:12   = PRS[1:0]
+ *     bit 11:10   = IO   (0b10 = Supervisor)
+ *
+ ****************************************************************************/
+
+       .global longjmp
+       .type   longjmp, %function
+
+longjmp:
+       ld.w    %d5, [%a4]0             /* %d5 = saved PCXI                */
+.Lloop:
+       mfcr    %d3, 0xfe04             /* %d3 = current PSW               */
+       mov     %d2, 2
+       insert  %d3, %d3, %d2, 10, 4    /* PSW.IO = 2 (supervisor)         */
+       mov     %d2, 0
+       insert  %d3, %d3, %d2, 15, 1    /* clear PSW.PRS[2]                */
+       mtcr    0xfe04, %d3
+       isync
+       mfcr    %d2, 0xfe00             /* %d2 = current PCXI              */
+       jne     %d2, %d5, .Lrelease     /* depth mismatch -> unwind one    */
+
+       /* Matching depth: restore registers and return. */
+
+       max.u   %d2, %d4, 1             /* %d2 = max(val, 1)               */
+       ld.a    %a2, [%a4]12            /* %a2 = saved return address      */
+       ld.a    %sp, [%a4]8
+       ld.a    %a12, [%a4]32
+       ld.a    %a13, [%a4]36
+       ld.a    %a14, [%a4]40
+       ld.a    %a15, [%a4]44
+       ld.w    %d8, [%a4]16
+       ld.w    %d9, [%a4]20
+       ld.w    %d10, [%a4]24
+       ld.w    %d11, [%a4]28
+       ld.w    %d12, [%a4]48
+       ld.w    %d13, [%a4]52
+       ld.w    %d14, [%a4]56
+       ld.w    %d15, [%a4]60
+       ld.w    %d3, [%a4]4             /* saved PSW                       */
+       mtcr    0xfe04, %d3
+       isync
+       ji      %a2                     /* return to setjmp call site      */
+
+.Lrelease:
+       jnz.t   %d2, 20, .Lupper        /* PCXI.UL = 1 -> release upper    */
+
+       /* Release one lower context, preserving env/val across rslcx. */
+
+       mov.aa  %a15, %a4
+       mov     %d15, %d4
+       mov     %d14, %d5
+       rslcx
+       mov     %d4, %d15
+       mov     %d5, %d14
+       mov.aa  %a4, %a15
+       j       .Lloop
+
+.Lupper:
+       /* Release one upper context via `ret' (restores the upper context
+        * from CSA and jumps through %a11).  Point %a11 back at .Lloop so
+        * we re-enter the depth check after the release.
+        */
+
+       movh.a  %a11, hi:.Lloop
+       lea     %a11, [%a11] lo:.Lloop
+       ret
+       .size   longjmp, . - longjmp
diff --git a/libs/libc/machine/tricore/tasking/arch_setjmp.asm 
b/libs/libc/machine/tricore/tasking/arch_setjmp.asm
new file mode 100644
index 00000000000..e6bc178bd2f
--- /dev/null
+++ b/libs/libc/machine/tricore/tasking/arch_setjmp.asm
@@ -0,0 +1,178 @@
+;****************************************************************************
+; libs/libc/machine/tricore/tasking/arch_setjmp.asm
+;
+; SPDX-License-Identifier: Apache-2.0
+;
+; Licensed to the Apache Software Foundation (ASF) under one or more
+; contributor license agreements.  See the NOTICE file distributed with
+; this work for additional information regarding copyright ownership.  The
+; ASF licenses this file to you under the Apache License, Version 2.0 (the
+; "License"); you may not use this file except in compliance with the
+; License.  You may obtain a copy of the License at
+;
+;   http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+; License for the specific language governing permissions and limitations
+; under the License.
+;
+;****************************************************************************
+;
+; Tasking (astc) port of the GNU arch_setjmp.S.  Same instruction sequence;
+; only the assembler syntax differs.  Machine code matches the GNU version.
+;
+;****************************************************************************
+; Name: setjmp
+;
+; Description:
+;   int setjmp(jmp_buf env)
+;
+;   TriCore EABI:
+;     env -> a4   return value -> d2
+;
+;   jmp_buf layout (struct setjmp_buf_s, arch/tricore/include/setjmp.h):
+;     0: pcxi   4: psw    8: sp    12: a11
+;    16: d8    20: d9    24: d10   28: d11
+;    32: a12   36: a13   40: a14   44: a15
+;    48: d12   52: d13   56: d14   60: d15
+;
+;   On entry a11 holds the caller's return address (TriCore call ABI).
+;   Save it into env[12] first, then repoint a11 at .Lsaveregs and execute
+;   `ret' which jumps through a11.  The fall-through at .Lsaveregs stores
+;   the remaining callee-saved registers and the PCXI/PSW control registers,
+;   loads the saved return address into a2, sets d2 = 0, and jumps back
+;   to the caller.  longjmp() returns through the same path with a nonzero
+;   d2.
+;
+;****************************************************************************
+
+       .sdecl  '.text.setjmp',code
+       .sect   '.text.setjmp'
+       .global setjmp
+
+setjmp:        .type   func
+       st.a    [a4]12, a11             ; save return address
+       movh.a  a11, #@HIS(.Lsaveregs)
+       lea     a11, [a11]@LOS(.Lsaveregs)
+       ret                             ; jump to .Lsaveregs via a11
+.Lsaveregs:
+       st.a    [a4]8, sp
+       st.a    [a4]32, a12
+       st.a    [a4]36, a13
+       st.a    [a4]40, a14
+       st.a    [a4]44, a15
+       st.w    [a4]16, d8
+       st.w    [a4]20, d9
+       st.w    [a4]24, d10
+       st.w    [a4]28, d11
+       st.w    [a4]48, d12
+       st.w    [a4]52, d13
+       st.w    [a4]56, d14
+       st.w    [a4]60, d15
+       mfcr    d2, #0xfe00
+       st.w    [a4]0, d2               ; save PCXI
+       mfcr    d2, #0xfe04
+       st.w    [a4]4, d2               ; save PSW
+       ld.a    a2, [a4]12              ; a2 = return address
+       mov     d2, #0                  ; setjmp returns 0
+       ji      a2                      ; back to caller
+.Lsetjmp_end:
+
+       .size   setjmp, .Lsetjmp_end-setjmp
+
+;****************************************************************************
+; Name: longjmp
+;
+; Description:
+;   void longjmp(jmp_buf env, int val) noreturn
+;
+;   TriCore EABI:
+;     env -> a4   val -> d4
+;
+;   Unwind the CSA chain (releasing lower/upper contexts one at a time)
+;   until the active PCXI matches the one saved by setjmp.  At that point
+;   the register banks are at the same depth as at setjmp time, so
+;   restoring the callee-saved registers, PSW and return address proceeds.
+;   The result passed back equals max(val, 1) per POSIX.
+;
+;   The unwind loop forces PSW.IO = Supervisor and PSW.PRS[2] = 0 on every
+;   iteration so that the `ret'-released upper contexts do not drop the CPU
+;   into user mode while env is still being accessed.  Once the loop exits,
+;   the original PSW saved at setjmp time is restored before the indirect
+;   jump back to the setjmp call site.
+;
+;   PSW layout (TC1.6.2 / TC1.8):
+;     bit 15      = PRS[2]
+;     bit 14      = S    (alternate master tag selector, preserve)
+;     bit 13:12   = PRS[1:0]
+;     bit 11:10   = IO   (0b10 = Supervisor)
+;
+;****************************************************************************
+
+       .sdecl  '.text.longjmp',code
+       .sect   '.text.longjmp'
+       .global longjmp
+
+longjmp:       .type   func
+       ld.w    d5, [a4]0               ; d5 = saved PCXI
+.Lloop:
+       mfcr    d3, #0xfe04             ; d3 = current PSW
+       mov     d2, #2
+       insert  d3, d3, d2, #10, #4     ; PSW.IO = 2 (supervisor)
+       mov     d2, #0
+       insert  d3, d3, d2, #15, #1     ; clear PSW.PRS[2]
+       mtcr    #0xfe04, d3
+       isync
+       mfcr    d2, #0xfe00             ; d2 = current PCXI
+       jne     d2, d5, .Lrelease       ; depth mismatch -> unwind one
+
+       ; Matching depth: restore registers and return.
+
+       max.u   d2, d4, #1              ; d2 = max(val, 1)
+       ld.a    a2, [a4]12              ; a2 = saved return address
+       ld.a    sp, [a4]8
+       ld.a    a12, [a4]32
+       ld.a    a13, [a4]36
+       ld.a    a14, [a4]40
+       ld.a    a15, [a4]44
+       ld.w    d8, [a4]16
+       ld.w    d9, [a4]20
+       ld.w    d10, [a4]24
+       ld.w    d11, [a4]28
+       ld.w    d12, [a4]48
+       ld.w    d13, [a4]52
+       ld.w    d14, [a4]56
+       ld.w    d15, [a4]60
+       ld.w    d3, [a4]4               ; saved PSW
+       mtcr    #0xfe04, d3
+       isync
+       ji      a2                      ; return to setjmp call site
+
+.Lrelease:
+       jnz.t   d2, #20, .Lupper        ; PCXI.UL = 1 -> release upper
+
+       ; Release one lower context, preserving env/val across rslcx.
+
+       mov.aa  a15, a4
+       mov     d15, d4
+       mov     d14, d5
+       rslcx
+       mov     d4, d15
+       mov     d5, d14
+       mov.aa  a4, a15
+       j       .Lloop
+
+.Lupper:
+       ; Release one upper context via `ret' (restores the upper context
+       ; from CSA and jumps through a11).  Point a11 back at .Lloop so
+       ; we re-enter the depth check after the release.
+
+       movh.a  a11, #@HIS(.Lloop)
+       lea     a11, [a11]@LOS(.Lloop)
+       ret
+.Llongjmp_end:
+
+       .size   longjmp, .Llongjmp_end-longjmp
+       .end

Reply via email to