libc: arm: fix setjmp abi non-conformance

As per the arm Procedure Call Standard for the Arm Architecture
section 6.1.2 [1], VFP registers s16-s31 (d8-d15, q4-q7) must be
preserved across subroutine calls.

The current setjmp/longjmp implementations preserve only the core
registers, with the jump buffer size too small to store the required
co-processor registers.

In accordance with the C Library ABI for the Arm Architecture
section 6.11 [2], this patch sets _JBTYPE to long long adjusting
_JBLEN to 20.

It also emits vfp load/store instructions depending on architectural
support, predicated at compile time on ACLE feature-test macros.

[1] https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst
[2] https://github.com/ARM-software/abi-aa/blob/main/clibabi32/clibabi32.rst
This commit is contained in:
Victor L. Do Nascimento 2022-12-13 14:51:28 +00:00 committed by Richard Earnshaw
parent 90236c3a2c
commit 15ad816ddd
3 changed files with 47 additions and 39 deletions

View File

@ -762,7 +762,7 @@ SUCH DAMAGE.
(35) - Arm Ltd (35) - Arm Ltd
Copyright (c) 2009-2018 Arm Ltd Copyright (c) 2009-2022 Arm Ltd
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View File

@ -12,9 +12,13 @@ _BEGIN_STD_C
#if defined(__arm__) || defined(__thumb__) #if defined(__arm__) || defined(__thumb__)
/* /*
* All callee preserved registers: * All callee preserved registers:
* v1 - v7, fp, ip, sp, lr, f4, f5, f6, f7 * core registers:
* r4 - r10, fp, sp, lr
* VFP registers (architectural support dependent):
* d8 - d15
*/ */
#define _JBLEN 23 #define _JBLEN 20
#define _JBTYPE long long
#endif #endif
#if defined(__aarch64__) #if defined(__aarch64__)

View File

@ -115,7 +115,7 @@ SYM (longjmp):
#else #else
#define RET tst lr, #1; \ #define RET tst lr, #1; \
moveq pc, lr ; \ moveq pc, lr ; \
.word 0xe12fff1e /* bx lr */ .inst 0xe12fff1e /* bx lr */
#endif #endif
#ifdef __thumb2__ #ifdef __thumb2__
@ -174,9 +174,12 @@ SYM (\name):
/* Save all the callee-preserved registers into the jump buffer. */ /* Save all the callee-preserved registers into the jump buffer. */
#ifdef __thumb2__ #ifdef __thumb2__
mov ip, sp mov ip, sp
stmea a1!, { v1-v7, fp, ip, lr } stmia r0!, { r4-r10, fp, ip, lr }
#else #else
stmea a1!, { v1-v7, fp, ip, sp, lr } stmia r0!, { r4-r10, fp, sp, lr }
#endif
#if defined __ARM_FP || defined __ARM_FEATURE_MVE
vstm r0, { d8-d15 }
#endif #endif
#if 0 /* Simulator does not cope with FP instructions yet. */ #if 0 /* Simulator does not cope with FP instructions yet. */
@ -186,7 +189,7 @@ SYM (\name):
#endif #endif
#endif #endif
/* When setting up the jump buffer return 0. */ /* When setting up the jump buffer return 0. */
mov a1, #0 mov r0, #0
FUNC_END setjmp FUNC_END setjmp
@ -200,10 +203,13 @@ SYM (\name):
/* Restore the registers, retrieving the state when setjmp() was called. */ /* Restore the registers, retrieving the state when setjmp() was called. */
#ifdef __thumb2__ #ifdef __thumb2__
ldmfd a1!, { v1-v7, fp, ip, lr } ldmia r0!, { r4-r10, fp, ip, lr }
mov sp, ip mov sp, ip
#else #else
ldmfd a1!, { v1-v7, fp, ip, sp, lr } ldmia r0!, { r4-r10, fp, sp, lr }
#endif
#if defined __ARM_FP || defined __ARM_FEATURE_MVE
vldm r0, { d8-d15 }
#endif #endif
#if 0 /* Simulator does not cope with FP instructions yet. */ #if 0 /* Simulator does not cope with FP instructions yet. */
@ -214,11 +220,9 @@ SYM (\name):
#endif #endif
/* Put the return value into the integer result register. /* Put the return value into the integer result register.
But if it is zero then return 1 instead. */ But if it is zero then return 1 instead. */
movs a1, a2 movs r0, r1
#ifdef __thumb2__
it eq it eq
#endif moveq r0, #1
moveq a1, #1
FUNC_END longjmp FUNC_END longjmp
#endif #endif