From 5b562e68c2c34c576ef21525b9d405655354d982 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Sun, 30 Nov 2025 00:03:52 +0100 Subject: [PATCH] pkg/micro-ecc: fix on GCC 15.2.0 for AVR - add a work around for a (presumably) compiler bug in GCC 15.2.0 register allocation code by manually a function argument into the Y register. - add missing `"memory"` clobber to inline asm implementations. With GCC 15.2.0 the `vli_mmod_fast_secp256r1()` function would not compute correctly without the `"memory"` clobber. --- ...vr.inc-fix-compilation-on-GCC-15.2.0.patch | 51 ++++++ ...m_avr.inc-add-missing-memory-clobber.patch | 153 ++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 pkg/micro-ecc/patches/0002-asm_avr.inc-fix-compilation-on-GCC-15.2.0.patch create mode 100644 pkg/micro-ecc/patches/0003-asm_avr.inc-add-missing-memory-clobber.patch diff --git a/pkg/micro-ecc/patches/0002-asm_avr.inc-fix-compilation-on-GCC-15.2.0.patch b/pkg/micro-ecc/patches/0002-asm_avr.inc-fix-compilation-on-GCC-15.2.0.patch new file mode 100644 index 000000000000..ac3a03a64a7b --- /dev/null +++ b/pkg/micro-ecc/patches/0002-asm_avr.inc-fix-compilation-on-GCC-15.2.0.patch @@ -0,0 +1,51 @@ +From 08db99075ca9e82ed136df20bfc9855623c9b361 Mon Sep 17 00:00:00 2001 +From: Marian Buschsieweke +Date: Sun, 30 Nov 2025 11:29:21 +0100 +Subject: [PATCH] asm_avr.inc: fix compilation on GCC 15.2.0 + +Compilation with GCC 15.2.0 failed with: + + asm_avr.inc:915:5: error: cannot find a register in class 'POINTER_Y_REGS' while reloading 'asm' + +This works around the issue by manually placing right into the Y +register before the inline assembly. +--- + asm_avr.inc | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/asm_avr.inc b/asm_avr.inc +index c14bf55..6259d36 100644 +--- a/asm_avr.inc ++++ b/asm_avr.inc +@@ -905,13 +905,18 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { +- volatile uECC_word_t *r = result; + uint8_t r0 = 0; + uint8_t r1 = 0; + uint8_t r2 = 0; + uint8_t zero = 0; + uint8_t k, i; + ++ /* manually allocate right to register Y to work around bug in GCC 15.2 */ ++ register uint8_t yl asm("r28"); ++ register uint8_t yh asm("r29"); ++ yl = (uint8_t)(unsigned)right; ++ yh = (uint8_t)(((unsigned)right) >> 8); ++ + __asm__ volatile ( + "ldi %[k], 1 \n\t" /* k = 1; k < num_words; ++k */ + +@@ -986,7 +991,7 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + "st z+, %[r0] \n\t" /* Store last result byte. */ + "eor r1, r1 \n\t" /* fix r1 to be 0 again */ + +- : "+z" (result), "+x" (left), "+y" (right), ++ : "+z" (result), "+x" (left), "+r" (yl), "+r" (yh), + [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), + [zero] "+r" (zero), [num] "+r" (num_words), + [k] "=&r" (k), [i] "=&r" (i) +-- +2.52.0 + diff --git a/pkg/micro-ecc/patches/0003-asm_avr.inc-add-missing-memory-clobber.patch b/pkg/micro-ecc/patches/0003-asm_avr.inc-add-missing-memory-clobber.patch new file mode 100644 index 000000000000..adaa0c251f8c --- /dev/null +++ b/pkg/micro-ecc/patches/0003-asm_avr.inc-add-missing-memory-clobber.patch @@ -0,0 +1,153 @@ +From 03aa4f6a52e7ecedce09e0336739530261796a90 Mon Sep 17 00:00:00 2001 +From: Marian Buschsieweke +Date: Sun, 30 Nov 2025 20:13:22 +0100 +Subject: [PATCH] asm_avr.inc: add missing memory clobber + +It seems that older versions of GCC did not optimize memory accesses +across function calls. That made function calls an implicit memory +barrier, even when the function implementation was part of the current +compilation unit and the compiler could infer that a function did not +touch memory. + +With inline assembly, the compiler assumes the clobber list to be +exhaustive. If no memory clobber is given and a function does not touch +memory except for the inline assembly, the compiler may assume that +a function does not change memory contents and optimize accordingly. + +Adding the required memory clobbers fixes incorrect computations of +`vli_mmod_fast_secp256r1()` on AVR GCC 15.2.0. +--- + asm_avr.inc | 30 +++++++++++++++--------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/asm_avr.inc b/asm_avr.inc +index c14bf55..d600858 100644 +--- a/asm_avr.inc ++++ b/asm_avr.inc +@@ -42,9 +42,9 @@ uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { + "1: \n\t" + : "+x" (v) + : [num] "r" (num_words) +- : ++ : "memory" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) +- "r30", "r31", "cc" ++ , "r30", "r31", "cc" + #endif + ); + } +@@ -67,7 +67,7 @@ uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordco + "1: \n\t" + : "+x" (d), "+y" (src) + : [num] "r" ((uint8_t)(num_words * 2)) +- : "r0" ++ : "r0", "memory" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + , "r30", "r31", "cc" + #endif +@@ -102,10 +102,10 @@ uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { + : "+x" (v) + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + : [num] "r" (num_words), [jump] "r" ((uint8_t)(3 * (num_words - 1))) +- : "r0", "r30", "r31", "cc" ++ : "r0", "r30", "r31", "cc", "memory" + #else + : [num] "r" (num_words) +- : "r0", "cc" ++ : "r0", "cc", "memory" + #endif + ); + } +@@ -152,7 +152,7 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + : "+x" (left), "+y" (right), + [clb] "=&r" (carry), [rb] "=&r" (right_byte) + : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2)) +- : "r30", "r31", "cc" ++ : "r30", "r31", "cc", "memory" + ); + return carry; + } +@@ -199,7 +199,7 @@ uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + : "+x" (left), "+y" (right), + [clb] "=&r" (carry), [rb] "=&r" (right_byte) + : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2)) +- : "r30", "r31", "cc" ++ : "r30", "r31", "cc", "memory" + ); + return carry; + } +@@ -256,7 +256,7 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + : "r" (r18) + : "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r19", "r20", +- "r21", "r22", "r23", "r24", "r25", "cc" ++ "r21", "r22", "r23", "r24", "r25", "cc", "memory" + ); + } + #define asm_mult 1 +@@ -308,7 +308,7 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + : "r" (r20) + : "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", +- "r21", "r22", "r23", "r24", "r25", "r28", "r29", "cc" ++ "r21", "r22", "r23", "r24", "r25", "r28", "r29", "cc", "memory" + ); + } + #define asm_square 1 +@@ -487,7 +487,7 @@ static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { + + : "+x" (product), [carry] "+r" (carry) + : "y" (result) +- : "r0", "r18", "r19", "r30", "r31", "cc" ++ : "r0", "r18", "r19", "r30", "r31", "cc", "memory" + ); + + if (carry > 0) { +@@ -812,7 +812,7 @@ static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { + + : "+x" (product), [carry] "+r" (carry) + : "y" (result) +- : "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc" ++ : "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc", "memory" + ); + + if (carry > 0) { +@@ -859,7 +859,7 @@ uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), + [carry] "+r" (carry), [left] "=&r" (left_byte), [right] "=&r" (right_byte) + : +- : "cc" ++ : "cc", "memory" + ); + return carry; + } +@@ -892,7 +892,7 @@ uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), + [borrow] "+r" (borrow), [left] "=&r" (left_byte), [right] "=&r" (right_byte) + : +- : "cc" ++ : "cc", "memory" + ); + return borrow; + } +@@ -991,7 +991,7 @@ uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + [zero] "+r" (zero), [num] "+r" (num_words), + [k] "=&r" (k), [i] "=&r" (i) + : +- : "r0", "cc" ++ : "r0", "cc", "memory" + ); + } + #define asm_mult 1 +@@ -1080,7 +1080,7 @@ uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + [k] "=&a" (k) + : [orig] "r" (left), [max] "r" ((uint8_t)(2 * num_words)), + [num] "r" (num_words) +- : "r0", "r26", "r27", "r30", "r31", "cc" ++ : "r0", "r26", "r27", "r30", "r31", "cc", "memory" + ); + } + #define asm_square 1 +-- +2.52.0 +