arch/tricore: Full implementation of setjmp and longjmp.

1. The original method of restoring the register context relies on
   the ret instruction, which does not conform to the semantics of
   longjmp not returning.
2. There are csa leak during longjmp and need recycle.

Signed-off-by: zhangyu117 <zhangyu117@xiaomi.com>
This commit is contained in:
zhangyu117
2026-05-21 16:26:23 +08:00
committed by Xiang Xiao
parent e087d0f79d
commit 02833038fd
2 changed files with 150 additions and 52 deletions
+17 -25
View File
@@ -30,36 +30,28 @@
#include <stdint.h>
/****************************************************************************
* Pre-processor Prototypes
****************************************************************************/
#define JB_LPCXI 0
#define JB_LA11 1
#define JB_A2 2
#define JB_A3 3
#define JB_D0 4
#define JB_D1 5
#define JB_D2 6
#define JB_D3 7
#define JB_A4 8
#define JB_A5 9
#define JB_A6 10
#define JB_A7 11
#define JB_D4 12
#define JB_D5 13
#define JB_D6 14
#define JB_D7 15
#define JB_UA11 16
#define JB_REG_NUM 17
/****************************************************************************
* Public Types
****************************************************************************/
struct setjmp_buf_s
{
uintptr_t regs[JB_REG_NUM];
uintptr_t pcxi;
uintptr_t psw;
uintptr_t sp;
uintptr_t a11;
uintptr_t d8;
uintptr_t d9;
uintptr_t d10;
uintptr_t d11;
uintptr_t a12;
uintptr_t a13;
uintptr_t a14;
uintptr_t a15;
uintptr_t d12;
uintptr_t d13;
uintptr_t d14;
uintptr_t d15;
};
/* Traditional typedef for setjmp_buf */
@@ -79,7 +71,7 @@ extern "C"
#endif
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
void longjmp(jmp_buf env, int val) noreturn_function;
#undef EXTERN
#ifdef __cplusplus
+133 -27
View File
@@ -24,13 +24,10 @@
* Included Files
****************************************************************************/
#include <string.h>
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <arch/setjmp.h>
#include <nuttx/arch.h>
#include <IfxCpu_reg.h>
#include <IfxCpu_Intrinsics.h>
/****************************************************************************
* Public Functions
@@ -38,32 +35,141 @@
int setjmp(jmp_buf env)
{
uintptr_t *regs;
uintptr_t pcxi;
env->regs[JB_UA11] = (uintptr_t)__getA11();
pcxi = __mfcr(CPU_PCXI);
regs = tricore_csa2addr(pcxi);
memcpy(env, regs, TC_CONTEXT_SIZE);
__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;
}
void longjmp(jmp_buf env, int val)
{
void *func = (void *)env->regs[JB_UA11];
uintptr_t *regs;
uintptr_t pcxi;
__asm__ __volatile__ (
#ifdef CONFIG_TRICORE_TOOLCHAIN_TASKING
"ld.w d5, [a4]0\n\t"
".Lloop:\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"
"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 %%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"
"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"
);
pcxi = __mfcr(CPU_PCXI);
regs = tricore_csa2addr(pcxi);
memcpy(regs, env, TC_CONTEXT_SIZE);
if (val == 0)
{
val = 1;
}
__moveToDataParamRet(val);
__jumpToFunctionWithLink(func);
__builtin_unreachable();
}