Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
From 08db99075ca9e82ed136df20bfc9855623c9b361 Mon Sep 17 00:00:00 2001
From: Marian Buschsieweke <[email protected]>
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

Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
From 03aa4f6a52e7ecedce09e0336739530261796a90 Mon Sep 17 00:00:00 2001
From: Marian Buschsieweke <[email protected]>
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