Skip to content

Commit 1696361

Browse files
authored
Merge pull request #479 from pillo79/pr-fix-472
llext: use naked trampolines for compiler ABI helpers
2 parents 8ed7e79 + b6cb3ba commit 1696361

2 files changed

Lines changed: 106 additions & 41 deletions

File tree

cores/arduino/llext_wrappers.c

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,24 @@
6262
__real_##name(a); \
6363
}
6464

65+
/*
66+
* Naked trampoline for compiler ABI helpers (__aeabi_*).
67+
*
68+
* ARM RTABI passes doubles in core registers r0:r1 / r2:r3 regardless of
69+
* -mfloat-abi=hard. A C wrapper compiled with -Os generates "ldr r3, [pc, #0]"
70+
* which clobbers r3 (the high-word of the second double argument) before the
71+
* tail-call, corrupting the comparison result.
72+
*
73+
* The naked trampoline uses r12 (ip, AAPCS inter-procedure scratch register)
74+
* which is never an argument register, so r0–r3 and d0–d7 are untouched.
75+
*/
76+
#define VN(name) \
77+
__attribute__((naked)) void name(void) { \
78+
__asm__("movw r12, #:lower16:__real_" #name "\n\t" \
79+
"movt r12, #:upper16:__real_" #name "\n\t" \
80+
"bx r12"); \
81+
}
82+
6583
/* string.h */
6684
W3(void *, memcpy, void *, const void *, size_t)
6785
W3(void *, memmove, void *, const void *, size_t)
@@ -144,9 +162,42 @@ W1(float, sinf, float)
144162
W1(float, sqrtf, float)
145163
W1(float, tanf, float)
146164

147-
/* compiler double helper functions */
148-
W2(double, __aeabi_dadd, double, double)
149-
W2(int, __aeabi_dcmpgt, double, double)
165+
/* compiler ABI helpers: need to preserve all RTABI argument registers */
166+
/* double arithmetic */
167+
VN(__aeabi_dadd)
168+
VN(__aeabi_dsub)
169+
VN(__aeabi_dmul)
170+
VN(__aeabi_ddiv)
171+
/* double comparisons */
172+
VN(__aeabi_dcmpeq)
173+
VN(__aeabi_dcmplt)
174+
VN(__aeabi_dcmple)
175+
VN(__aeabi_dcmpgt)
176+
VN(__aeabi_dcmpge)
177+
VN(__aeabi_dcmpun)
178+
/* float comparisons */
179+
VN(__aeabi_fcmple)
180+
VN(__aeabi_fcmpun)
181+
/* double <-> integer conversions */
182+
VN(__aeabi_d2iz)
183+
VN(__aeabi_d2uiz)
184+
VN(__aeabi_d2lz)
185+
VN(__aeabi_i2d)
186+
VN(__aeabi_ui2d)
187+
VN(__aeabi_l2d)
188+
VN(__aeabi_ul2d)
189+
/* float <-> double / integer conversions */
190+
VN(__aeabi_d2f)
191+
VN(__aeabi_f2d)
192+
VN(__aeabi_l2f)
193+
VN(__aeabi_ul2f)
194+
/* integer division */
195+
VN(__aeabi_idiv)
196+
VN(__aeabi_uidiv)
197+
VN(__aeabi_idivmod)
198+
VN(__aeabi_uidivmod)
199+
VN(__aeabi_ldivmod)
200+
VN(__aeabi_uldivmod)
150201

151202
/* stdio.h */
152203
W1(int, puts, const char *)

loader/llext_exports.c

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
#include <time.h>
1717
#include <zephyr/drivers/pinctrl.h>
1818

19-
#define FORCE_EXPORT_SYM(name) \
20-
extern void name(void); \
21-
EXPORT_SYMBOL(name);
19+
#define FORCE_EXPORT_SYM(name) \
20+
extern void name(void); \
21+
EXPORT_SYMBOL(name);
2222

2323
/*
2424
* Libc functions are exported with a __real_ prefix so that the sketch
@@ -28,6 +28,14 @@
2828
*/
2929
#define EXPORT_LIBC_SYM(name) EXPORT_SYMBOL_NAMED(name, __real_##name)
3030

31+
/*
32+
* ARM RTABI __aeabi_* functions need naked assembly trampolines to avoid
33+
* corrupting argument registers with standard C function prologue/epilogue.
34+
*/
35+
#define EXPORT_AEABI_SYM(name) \
36+
extern void name(void); \
37+
EXPORT_LIBC_SYM(name)
38+
3139
// string.h
3240
EXPORT_LIBC_SYM(memcpy);
3341
EXPORT_LIBC_SYM(memmove);
@@ -290,8 +298,8 @@ EXPORT_SYMBOL(k_work_schedule_for_queue);
290298
EXPORT_SYMBOL(k_work_reschedule_for_queue);
291299
EXPORT_SYMBOL(k_work_queue_start);
292300
EXPORT_SYMBOL(k_work_submit_to_queue);
293-
//FORCE_EXPORT_SYM(k_timer_user_data_set);
294-
//FORCE_EXPORT_SYM(k_timer_start);
301+
// FORCE_EXPORT_SYM(k_timer_user_data_set);
302+
// FORCE_EXPORT_SYM(k_timer_start);
295303

296304
EXPORT_SYMBOL(time);
297305
EXPORT_SYMBOL(sys_clock_settime);
@@ -316,39 +324,45 @@ EXPORT_SYMBOL(ring_buf_area_finish);
316324
#endif
317325

318326
EXPORT_SYMBOL(sys_clock_cycle_get_32);
319-
FORCE_EXPORT_SYM(__aeabi_dcmpun);
320-
FORCE_EXPORT_SYM(__aeabi_dcmple);
321-
FORCE_EXPORT_SYM(__aeabi_d2lz);
322-
FORCE_EXPORT_SYM(__aeabi_uldivmod);
323-
FORCE_EXPORT_SYM(__aeabi_ui2d);
324-
FORCE_EXPORT_SYM(__aeabi_dcmplt);
325-
FORCE_EXPORT_SYM(__aeabi_ddiv);
326-
FORCE_EXPORT_SYM(__aeabi_dmul);
327-
FORCE_EXPORT_SYM(__aeabi_d2f);
328-
FORCE_EXPORT_SYM(__aeabi_fcmpun);
329-
extern double __aeabi_dadd(double, double);
330-
EXPORT_LIBC_SYM(__aeabi_dadd);
331-
FORCE_EXPORT_SYM(__aeabi_fcmple);
332-
FORCE_EXPORT_SYM(__aeabi_idiv);
333-
extern int __aeabi_dcmpgt(double, double);
334-
EXPORT_LIBC_SYM(__aeabi_dcmpgt);
335-
FORCE_EXPORT_SYM(__aeabi_dsub);
336-
FORCE_EXPORT_SYM(__aeabi_i2d);
337-
FORCE_EXPORT_SYM(__aeabi_uidiv);
338-
FORCE_EXPORT_SYM(__aeabi_l2d);
339-
FORCE_EXPORT_SYM(__aeabi_d2uiz);
340-
FORCE_EXPORT_SYM(__aeabi_uidivmod);
341-
FORCE_EXPORT_SYM(__aeabi_dcmpeq);
342-
FORCE_EXPORT_SYM(__aeabi_d2iz);
343-
FORCE_EXPORT_SYM(__aeabi_f2d);
344-
FORCE_EXPORT_SYM(__aeabi_ul2d);
345-
FORCE_EXPORT_SYM(__aeabi_l2f);
346-
FORCE_EXPORT_SYM(__aeabi_idivmod);
347-
FORCE_EXPORT_SYM(__aeabi_ldivmod);
348-
FORCE_EXPORT_SYM(__aeabi_ul2f);
349-
FORCE_EXPORT_SYM(__aeabi_dcmpge);
350-
351-
#if defined (CONFIG_CPP)
327+
328+
/* compiler ABI helpers: exported as __real_##name for VN() trampolines in llext_wrappers.c */
329+
/* double arithmetic */
330+
EXPORT_AEABI_SYM(__aeabi_dadd);
331+
EXPORT_AEABI_SYM(__aeabi_dsub);
332+
EXPORT_AEABI_SYM(__aeabi_dmul);
333+
EXPORT_AEABI_SYM(__aeabi_ddiv);
334+
/* double comparisons */
335+
EXPORT_AEABI_SYM(__aeabi_dcmpeq);
336+
EXPORT_AEABI_SYM(__aeabi_dcmplt);
337+
EXPORT_AEABI_SYM(__aeabi_dcmple);
338+
EXPORT_AEABI_SYM(__aeabi_dcmpgt);
339+
EXPORT_AEABI_SYM(__aeabi_dcmpge);
340+
EXPORT_AEABI_SYM(__aeabi_dcmpun);
341+
/* float comparisons */
342+
EXPORT_AEABI_SYM(__aeabi_fcmple);
343+
EXPORT_AEABI_SYM(__aeabi_fcmpun);
344+
/* double <-> integer conversions */
345+
EXPORT_AEABI_SYM(__aeabi_d2iz);
346+
EXPORT_AEABI_SYM(__aeabi_d2uiz);
347+
EXPORT_AEABI_SYM(__aeabi_d2lz);
348+
EXPORT_AEABI_SYM(__aeabi_i2d);
349+
EXPORT_AEABI_SYM(__aeabi_ui2d);
350+
EXPORT_AEABI_SYM(__aeabi_l2d);
351+
EXPORT_AEABI_SYM(__aeabi_ul2d);
352+
/* float <-> double / integer conversions */
353+
EXPORT_AEABI_SYM(__aeabi_d2f);
354+
EXPORT_AEABI_SYM(__aeabi_f2d);
355+
EXPORT_AEABI_SYM(__aeabi_l2f);
356+
EXPORT_AEABI_SYM(__aeabi_ul2f);
357+
/* integer division */
358+
EXPORT_AEABI_SYM(__aeabi_idiv);
359+
EXPORT_AEABI_SYM(__aeabi_uidiv);
360+
EXPORT_AEABI_SYM(__aeabi_idivmod);
361+
EXPORT_AEABI_SYM(__aeabi_uidivmod);
362+
EXPORT_AEABI_SYM(__aeabi_ldivmod);
363+
EXPORT_AEABI_SYM(__aeabi_uldivmod);
364+
365+
#if defined(CONFIG_CPP)
352366
FORCE_EXPORT_SYM(__cxa_pure_virtual);
353367
#endif
354368

0 commit comments

Comments
 (0)