parthitce commented on code in PR #21088:
URL: https://github.com/apache/nuttx/pull/21088#discussion_r4414843144


##########
libs/libc/machine/tricore/gnu/arch_memcpy.S:
##########
@@ -0,0 +1,215 @@
+/****************************************************************************
+ * libs/libc/machine/tricore/gnu/arch_memcpy.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "libc.h"
+
+#ifdef LIBC_BUILD_MEMCPY
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* void *memcpy(void *dst, const void *src, size_t n)
+ *
+ * TriCore EABI:
+ *   dst -> %a4   src -> %a5   n -> %d4   return (dst) -> %a2
+ *
+ * Strategy (quad-word block copy, matches vendor throughput):
+ *   - n < 16, or src/dst not sharing 4-byte (word) congruence: copy byte by
+ *     byte.
+ *   - Otherwise: copy a byte prologue to reach a 4-byte boundary, then copy
+ *     16 bytes per iteration with ld.dd/st.dd (quad-word Q0 = D0:D1:D2:D3)
+ *     driven by the hardware loop instruction, then copy the < 16 byte tail.
+ *   - Quad load/store are only issued once src and dst are 4-byte aligned
+ *     (TC1.8 requires word alignment for ld.dd/st.dd, not 16-byte; this is the
+ *     same minimum the vendor Tasking memcpy relies on), so no data alignment
+ *     trap can occur.
+ *
+ * Requires the assembler to target TC1.8 for ld.dd/st.dd (see AFLAGS
+ * -Wa,-mtc18 in Make.defs / CMakeLists.txt).
+ *
+ * Q0 is a lower-context register pair group; together with the other scratch
+ * registers (%d15, %a2/%a3/%a15) it needs no CSA context save.
+ */
+
+       .text
+       .global ARCH_LIBCFUN(memcpy)
+       .type   ARCH_LIBCFUN(memcpy), %function
+
+ARCH_LIBCFUN(memcpy):
+       mov.aa  %a2, %a4                /* return value = original dst      */
+       jz      %d4, .Ldone             /* n == 0 -> nothing to do          */
+       mov.aa  %a15, %a4               /* %a15 = working dst pointer        */
+
+       mov     %d15, 16
+       jlt.u   %d4, %d15, .Lbyte_setup /* n < 16 -> byte copy              */
+
+       /* Require src and dst to share the same 8-byte congruence so that
+        * aligning dst to 8 also aligns src to 8.  (src ^ dst) & 7 == 0 ?
+        *
+        * 8-byte alignment is mandatory for DLMU targets (0xB0/0x90): the DLMU
+        * has 64-bit ECC granularity, so a quad st.dd starting at a 4-mod-8
+        * offset would partially write two 64-bit ECC words as sub-doubleword
+        * read-modify-write, corrupting shared memory. Aligning to 8 makes 
every
+        * quad write two whole 64-bit ECC words.
+        */
+
+       mov.d   %d0, %a5
+       mov.d   %d1, %a15
+       xor     %d0, %d0, %d1
+       and     %d0, %d0, 7
+       jnz     %d0, .Lshiftmerge       /* different congruence -> word 
shift-merge */
+
+       /* Prologue: copy (8 - (dst & 7)) bytes to reach an 8-byte boundary. */
+
+       mov.d   %d15, %a15
+       and     %d15, %d15, 7
+       jz      %d15, .Laligned
+       rsub    %d15, %d15, 8           /* %d15 = 8 - misalign (1..7)       */
+       sub     %d4, %d4, %d15          /* n -= prologue bytes              */
+       mov.a   %a3, %d15
+       add.a   %a3, -1
+.Lpre:
+       ld.bu   %d0, [%a5+]
+       st.b    [%a15+], %d0
+       loop    %a3, .Lpre
+
+.Laligned:
+       /* Main loop: 32 bytes per iteration (two quad copies unrolled) to
+        * halve the hardware-loop branch overhead.  chunks = n >> 5.
+        */
+
+       sh      %d15, %d4, -5           /* %d15 = n / 32                    */
+       jz      %d15, .Lquad1
+       mov.a   %a3, %d15
+       add.a   %a3, -1
+.Lqloop:
+       ld.d    %e0, [%a5+]8            /* 2x 8-byte (64-bit) block loads:  */
+       ld.d    %e2, [%a5+]8            /* flash aperture rejects 16B burst */
+       st.dd   [%a15+]16, %q0

Review Comment:
   these are TC1.8P ISA only instructions. how did you test this with TC3x 
boards?



##########
libs/libc/machine/tricore/Make.defs:
##########
@@ -24,9 +24,85 @@ ifeq ($(CONFIG_LIBC_ATOMIC_ARCH),y)
 CSRCS += arch_atomic.c
 endif
 
+ifeq ($(CONFIG_TRICORE_TOOLCHAIN_TASKING),y)
+TRICORE_SUBDIR = tasking
+else
+TRICORE_SUBDIR = gnu
+endif
+
+AFLAGS += 
${INCDIR_PREFIX}$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)machine$(DELIM)tricore
+
+# The optimized assembly routines use TC1.8 instructions (e.g. ld.dd/st.dd
+# quad-word access).  Force the assembler to target TC1.8 so the build does
+# not depend on the board's ambient platform flags.
+
+AFLAGS += -Wa,-mtc18

Review Comment:
   Only tc4x?



##########
libs/libc/machine/tricore/Kconfig:
##########
@@ -2,3 +2,145 @@
 # For a description of the syntax of this configuration file,
 # see the file kconfig-language.txt in the NuttX tools repository.
 #
+
+config TRICORE_STRING_FUNCTION
+       bool "Enable optimized TriCore specific string/memory functions"
+       default n
+       select TRICORE_MEMCPY
+       select TRICORE_MEMSET
+       select TRICORE_MEMMOVE
+       select TRICORE_MEMCMP
+       select TRICORE_MEMCHR
+       select TRICORE_STRCMP
+       select TRICORE_STRCPY
+       select TRICORE_STRLEN
+       select TRICORE_STRCHR
+       select TRICORE_STRCHRNUL
+       select TRICORE_STRNCMP
+       select TRICORE_STRNLEN
+       select TRICORE_STRNCPY
+       select TRICORE_STPCPY
+       select TRICORE_STRRCHR
+       ---help---
+               Enable the full set of TriCore assembly library functions as a
+               group: memcpy/memset/memmove/memcmp/memchr and the string ops
+               strcmp/strcpy/strlen/strchr/strchrnul/strncmp/strnlen/strncpy/
+               stpcpy/strrchr.  Real on-board benchmarks (rzcu/lzcu B2, TC4Z9)
+               show the group ahead of the BSD C versions overall, most 
functions

Review Comment:
   you have mentioned nuttx c lib, here it's BSD? which one?



##########
libs/libc/machine/tricore/Kconfig:
##########
@@ -2,3 +2,145 @@
 # For a description of the syntax of this configuration file,
 # see the file kconfig-language.txt in the NuttX tools repository.
 #
+
+config TRICORE_STRING_FUNCTION
+       bool "Enable optimized TriCore specific string/memory functions"
+       default n
+       select TRICORE_MEMCPY
+       select TRICORE_MEMSET
+       select TRICORE_MEMMOVE
+       select TRICORE_MEMCMP
+       select TRICORE_MEMCHR
+       select TRICORE_STRCMP
+       select TRICORE_STRCPY
+       select TRICORE_STRLEN
+       select TRICORE_STRCHR
+       select TRICORE_STRCHRNUL
+       select TRICORE_STRNCMP
+       select TRICORE_STRNLEN
+       select TRICORE_STRNCPY
+       select TRICORE_STPCPY
+       select TRICORE_STRRCHR
+       ---help---
+               Enable the full set of TriCore assembly library functions as a
+               group: memcpy/memset/memmove/memcmp/memchr and the string ops
+               strcmp/strcpy/strlen/strchr/strchrnul/strncmp/strnlen/strncpy/
+               stpcpy/strrchr.  Real on-board benchmarks (rzcu/lzcu B2, TC4Z9)
+               show the group ahead of the BSD C versions overall, most 
functions
+               substantially so.
+               The block-move routines (memcpy/memset/memmove) align to an 
8-byte
+               boundary before issuing quad ld.dd/st.dd so that stores to DLMU
+               shared memory (0xB0/0x90, 64-bit ECC granularity) always write 
whole
+               ECC words; memcmp/strcmp are read-only (ld.w) and carry no ECC 
risk.

Review Comment:
   16 bytes quad loads raise a bus trap on flash in the other commit, here it 
says otherwise?



##########
libs/libc/machine/tricore/gnu/arch_strcpy.S:
##########
@@ -0,0 +1,165 @@
+/****************************************************************************
+ * libs/libc/machine/tricore/gnu/arch_strcpy.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "libc.h"
+
+#ifdef LIBC_BUILD_STRCPY
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* char *strcpy(char *dest, const char *src)
+ *
+ * TriCore EABI:
+ *   dest -> %a4   src -> %a5   return (dest) -> %a2
+ *
+ * Strategy (word-at-a-time with NUL detection, shift-merge for misaligned
+ * src, matching the memcpy shift-merge design):
+ *   - Byte prologue copies until dest reaches a 4-byte boundary, stopping if
+ *     a NUL is copied.  Keeping dest 4-aligned lets every bulk store be an
+ *     aligned st.w (safe, fast).
+ *   - Same congruence (src also 4-aligned): word loop reads an aligned word,
+ *     tests for a zero byte with hz = (w - 0x01010101) & ~w & 0x80808080; if
+ *     none, store the whole word and advance; on a hit, finish byte-wise so
+ *     nothing past the NUL is written.
+ *   - Different congruence: shift-merge.  Read aligned source words and
+ *     funnel-merge (preload >> sb, next << (32 - sb)) into a logical word,
+ *     run the same zero-byte test, and store aligned st.w until a word holds
+ *     a NUL; then finish byte-wise from the logical src pointer.
+ *   - The final (NUL-bearing) word is always resolved byte-by-byte so no
+ *     bytes beyond the terminator are written to dest.
+ *
+ * All source reads are ld.w (4-byte, aligned), so this routine is safe for
+ * memory-mapped flash (which rejects >8-byte burst reads) and never reads
+ * across a page boundary.
+ *
+ * Uses only scratch registers (%d0-%d9/%d15, %a3/%a6/%a15) plus the %a2
+ * return value; no CSA context save required.
+ */
+
+       .text
+       .global ARCH_LIBCFUN(strcpy)
+       .type   ARCH_LIBCFUN(strcpy), %function
+
+ARCH_LIBCFUN(strcpy):
+       mov.aa  %a2, %a4                /* return value = original dest     */
+       mov.aa  %a15, %a4               /* %a15 = working dst pointer       */
+
+       /* DETECTNULL constants: %d2 = 0x01010101, %d3 = 0x80808080. */
+
+       movh    %d2, 0x0101
+       addi    %d2, %d2, 0x0101
+       sh      %d3, %d2, 7
+
+       /* Byte prologue: copy until dst (%a15) reaches an 8-byte boundary. */
+
+.Lpre:
+       mov.d   %d0, %a15
+       and     %d0, %d0, 7
+       jz      %d0, .Ldst_ok           /* dst 8-aligned -> bulk path       */
+       ld.bu   %d0, [%a5+]
+       st.b    [%a15+], %d0
+       jnz     %d0, .Lpre              /* nonzero -> keep prologue         */
+       ret                             /* copied NUL in prologue -> done   */
+
+.Ldst_ok:
+       /* dst 8-aligned.  Is src also 8-aligned (same congruence)? */
+
+       mov.d   %d0, %a5
+       and     %d0, %d0, 7
+       jnz     %d0, .Lsrc_lt8
+
+       /* 8-byte aligned copy: ld.d + two 32-bit DETECTNULL, st.d. */
+
+.Lword8:
+       ld.d    %e0, [%a5]              /* d0:d1 = 8 bytes src (8-aligned)  */
+       sub     %d4, %d0, %d2           /* low word zero-byte test          */
+       andn    %d4, %d4, %d0
+       and     %d4, %d4, %d3
+       sub     %d5, %d1, %d2           /* high word zero-byte test         */
+       andn    %d5, %d5, %d1
+       and     %d5, %d5, %d3
+       or      %d4, %d4, %d5           /* NUL anywhere in these 8 bytes?   */
+       jnz     %d4, .Lbyte             /* NUL -> finish byte-wise (a5 kept) */
+       st.d    [%a15+]8, %e0           /* store whole 8 bytes (dst 8-align) */
+       lea     %a5, [%a5]8             /* a5 += 8 (add.a const4 range -8..7) */
+       j       .Lword8
+
+.Lsrc_lt8:
+       /* src not 8-aligned.  4-aligned -> word copy; else shift-merge. */
+
+       and     %d0, %d0, 3             /* d0 = src & 3 (d0 held src & 7)   */
+       jnz     %d0, .Lshiftmerge
+
+       /* Same 4-byte congruence: aligned word copy with NUL detection. */
+
+.Lword:
+       ld.w    %d1, [%a5]              /* w = *src (4-byte aligned)        */
+       sub     %d4, %d1, %d2           /* zero-byte test                   */
+       andn    %d4, %d4, %d1
+       and     %d4, %d4, %d3
+       jnz     %d4, .Lbyte             /* NUL in word -> finish byte-wise  */
+       st.w    [%a15+]4, %d1           /* store whole word                 */
+       add.a   %a5, 4
+       j       .Lword
+
+.Lbyte:
+       /* Final word (or unaligned/short tail): copy byte-by-byte incl. NUL. */
+
+       ld.bu   %d0, [%a5+]
+       st.b    [%a15+], %d0
+       jnz     %d0, .Lbyte
+       ret
+
+.Lshiftmerge:
+       /* Misaligned src.  sb = (src & 3) * 8, sc = 32 - sb. */
+
+       sh      %d8, %d0, 3             /* %d8 = shift_bits (misalign*8)    */
+       rsub    %d9, %d8, 32            /* %d9 = 32 - shift_bits            */
+       rsub    %d7, %d8, 0             /* %d7 = -shift_bits (logical >>)   */
+       mov.d   %d0, %a5
+       andn    %d0, %d0, 3             /* src_al = src & ~3                */
+       mov.a   %a6, %d0
+       ld.w    %d5, [%a6+]4            /* preload first aligned word       */
+
+.Lsm_loop:
+       ld.w    %d6, [%a6+]4            /* next aligned word                */

Review Comment:
   Next aligned word is loaded before checking current word for NUL so it can 
read one word past the terminator and fault at end of a memory or MPU range



##########
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

Review Comment:
   ditto



##########
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               */

Review Comment:
   longjmp is user callable function, mtcr is Supervisor only



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to