[PATCH 2/4] riscv: use memory operands for inline assembly load/store

Jussi Kivilinna <[email protected]> Wed, 29 Jul 2026 19:34:22 +0300
Newsgroups gmane.comp.encryption.gpg.libgcrypt.devel
Message-ID <[email protected]>
* cipher/cipher-gcm-riscv-zbb-zbc.c (load_aligned_u64x2)
(store_aligned_u64x2): Use memory operand instead of register operand
with offset in assembly template and 'memory' clobber.
(load_unaligned_u64x2): Skip alignment check when Zicclsm is enabled.
* cipher/crc-riscv-zbb-zbc.c (load_aligned_u32, load_aligned_u64x2):
Use memory operand instead of register operand with offset in assembly
template and 'memory' clobber.
--

'memory' clobber forced compiler to spill values around every load and
store. Memory operand describes accessed object exactly, so clobber is
not needed and compiler can select addressing mode itself.

Signed-off-by: Jussi Kivilinna <[email protected]>
---
 cipher/cipher-gcm-riscv-zbb-zbc.c | 36 ++++++++++++++-----------------
 cipher/crc-riscv-zbb-zbc.c        | 15 ++++++-------
 2 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/cipher/cipher-gcm-riscv-zbb-zbc.c b/cipher/cipher-gcm-riscv-zbb-zbc.c
index e32bfafe..1e97cb5c 100644
--- a/cipher/cipher-gcm-riscv-zbb-zbc.c
+++ b/cipher/cipher-gcm-riscv-zbb-zbc.c
@@ -43,14 +43,12 @@ load_aligned_u64x2(const void *ptr)
 {
   u64x2 vec;
 
-  asm ("ld %0, 0(%1)"
+  asm ("ld %0, %1"
        : "=r" (vec.val[0])
-       : "r" (ptr)
-       : "memory");
-  asm ("ld %0, 8(%1)"
+       : "m" (((const bufhelp_u64_t *)ptr)[0]));
+  asm ("ld %0, %1"
        : "=r" (vec.val[1])
-       : "r" (ptr)
-       : "memory");
+       : "m" (((const bufhelp_u64_t *)ptr)[1]));
 
   return vec;
 }
@@ -58,12 +56,8 @@ load_aligned_u64x2(const void *ptr)
 static ASM_FUNC_ATTR_INLINE u64x2
 load_unaligned_u64x2(const void *ptr)
 {
-  if (((uintptr_t)ptr & 7) == 0)
-    {
-      /* aligned load */
-      return load_aligned_u64x2(ptr);
-    }
-  else
+#if !(defined(__riscv_zicclsm) && (__riscv_zicclsm >= 1000000))
+  if (UNLIKELY(((uintptr_t)ptr & 7) != 0))
     {
       /* unaligned load */
       const bufhelp_u64_t *ptr_u64 = ptr;
@@ -72,19 +66,21 @@ load_unaligned_u64x2(const void *ptr)
       vec.val[1] = ptr_u64[1].a;
       return vec;
     }
+#endif
+
+  /* aligned load */
+  return load_aligned_u64x2(ptr);
 }
 
 static ASM_FUNC_ATTR_INLINE void
 store_aligned_u64x2(void *ptr, u64x2 vec)
 {
-  asm ("sd %0, 0(%1)"
-       :
-       : "r" (vec.val[0]), "r" (ptr)
-       : "memory");
-  asm ("sd %0, 8(%1)"
-       :
-       : "r" (vec.val[1]), "r" (ptr)
-       : "memory");
+  asm ("sd %1, %0"
+       : "=m" (((bufhelp_u64_t *)ptr)[0])
+       : "r" (vec.val[0]));
+  asm ("sd %1, %0"
+       : "=m" (((bufhelp_u64_t *)ptr)[1])
+       : "r" (vec.val[1]));
 }
 
 static ASM_FUNC_ATTR_INLINE u64
diff --git a/cipher/crc-riscv-zbb-zbc.c b/cipher/crc-riscv-zbb-zbc.c
index 0915fa6c..bec6806f 100644
--- a/cipher/crc-riscv-zbb-zbc.c
+++ b/cipher/crc-riscv-zbb-zbc.c
@@ -152,10 +152,9 @@ static ASM_FUNC_ATTR_INLINE u64
 load_aligned_u32(const void *ptr)
 {
   u64 out;
-  asm ("lw %0, 0(%1)"
+  asm ("lw %0, %1"
        : "=r" (out)
-       : "r" (ptr)
-       : "memory");
+       : "m" (((const bufhelp_u32_t *)ptr)[0]));
   return out;
 }
 
@@ -164,14 +163,12 @@ load_aligned_u64x2(const void *ptr)
 {
   u64x2 vec;
 
-  asm ("ld %0, 0(%1)"
+  asm ("ld %0, %1"
        : "=r" (vec.lo)
-       : "r" (ptr)
-       : "memory");
-  asm ("ld %0, 8(%1)"
+       : "m" (((const bufhelp_u64_t *)ptr)[0]));
+  asm ("ld %0, %1"
        : "=r" (vec.hi)
-       : "r" (ptr)
-       : "memory");
+       : "m" (((const bufhelp_u64_t *)ptr)[1]));
 
   return vec;
 }
-- 
2.53.0