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

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();
}