new file mode 100644
@@ -0,0 +1,84 @@
+/* Copyright (c) 2026 SiFive Inc. All rights reserved.
+
+ This copyrighted material is made available to anyone wishing to use,
+ modify, copy, or redistribute it subject to the terms and conditions
+ of the FreeBSD License. This program is distributed in the hope that
+ it will be useful, but WITHOUT ANY WARRANTY expressed or implied,
+ including the implied warranties of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. A copy of this license is available at
+ http://www.opensource.org/licenses.
+*/
+
+#ifndef _ASM_H
+#define _ASM_H
+
+/*
+ * Macros to handle different pointer/register sizes for 32/64-bit code
+ */
+#if __riscv_xlen == 64
+# define PTRLOG 3
+# define SZREG 8
+# define REG_S sd
+# define REG_L ld
+#elif __riscv_xlen == 32
+# define PTRLOG 2
+# define SZREG 4
+# define REG_S sw
+# define REG_L lw
+#else
+# error __riscv_xlen must equal 32 or 64
+#endif
+
+#ifndef __riscv_float_abi_soft
+/* For ABI uniformity, reserve 8 bytes for floats, even if double-precision
+ floating-point is not supported in hardware. */
+# define SZFREG 8
+# ifdef __riscv_float_abi_single
+# define FREG_L flw
+# define FREG_S fsw
+# elif defined(__riscv_float_abi_double)
+# define FREG_L fld
+# define FREG_S fsd
+# elif defined(__riscv_float_abi_quad)
+# define FREG_L flq
+# define FREG_S fsq
+# else
+# error unsupported FLEN
+# endif
+#endif
+
+/* Use 2-byte alignment when compressed instructions are available, since
+ they keep functions naturally aligned at 2 bytes; otherwise fall back to
+ 4-byte alignment to match the 32-bit instruction width. When landing
+ pads are enabled, force 4-byte alignment so every lpad target is aligned
+ to the 32-bit instruction width. */
+#if (defined(__riscv_c) || defined(__riscv_zca) || defined(__riscv_compressed)) && !defined(__riscv_landing_pad)
+#define _ENTRY(name) \
+ .text; \
+ .balign 2; \
+ .globl name; \
+name:
+#else
+#define _ENTRY(name) \
+ .text; \
+ .balign 4; \
+ .globl name; \
+name:
+#endif
+
+#define FUNC(name) .type name,@function
+#define END(name) \
+ .size name,.-name
+
+#if __riscv_landing_pad
+#define LPAD lpad 0
+#else
+#define LPAD
+#endif
+
+#define ENTRY(name) \
+ _ENTRY (name) \
+ .type name,@function; \
+ LPAD
+
+#endif /* _ASM_H */
@@ -10,15 +10,13 @@
*/
#include "newlib.h"
+#include "asm.h"
#=========================================================================
# crt0.S : Entry point for RISC-V user programs
#=========================================================================
- .text
- .global _start
- .type _start, @function
-_start:
+ENTRY(_start)
# Initialize global pointer
.option push
.option norelax
@@ -105,4 +103,4 @@ _start:
.weak __libc_fini_array
.dword __libc_fini_array
#endif
- .size _start, .-_start
+END(_start)
@@ -1,11 +1,7 @@
+#include <sys/asm.h>
+
#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
-.text
-.global memccpy
-.type memccpy, @function
-memccpy:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(memccpy)
beqz a3, .Lnot_found
andi a2, a2, 0xff
mv a5, a0
@@ -32,5 +28,5 @@ memccpy:
vse8.v v0, (a5)
add a0, a5, a6
ret
-.size memccpy, .-memccpy
+END(memccpy)
#endif
@@ -1,11 +1,7 @@
+#include <sys/asm.h>
+
#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
-.text
-.global memchr
-.type memchr, @function
-memchr:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(memchr)
beqz a2, .Lnot_found
andi a1, a1, 0xff
.Lloop:
@@ -30,5 +26,5 @@ memchr:
.Lfound:
add a0, a0, a4
ret
-.size memchr, .-memchr
+END(memchr)
#endif
@@ -1,11 +1,7 @@
+#include <sys/asm.h>
+
#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
-.text
-.global memcmp
-.type memcmp, @function
-memcmp:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(memcmp)
beqz a2, .Lequal
.Lloop:
vsetvli a3, a2, e8, m8, ta, ma
@@ -34,5 +30,5 @@ memcmp:
lbu a4, 0(a1)
sub a0, a0, a4
ret
-.size memcmp, .-memcmp
+END(memcmp)
#endif
@@ -9,14 +9,10 @@
http://www.opensource.org/licenses.
*/
+#include <sys/asm.h>
+
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
-.text
-.global memcpy
-.type memcpy, @function
-memcpy:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(memcpy)
mv a3, a0
beqz a2, 2f
@@ -31,18 +27,9 @@ memcpy:
2:
ret
-
- .size memcpy, .-memcpy
+END(memcpy)
#elif defined(__riscv_vector)
-.text
-.option push
-.option arch, +zve32x
-.global memcpy
-.type memcpy, @function
-memcpy:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(memcpy)
mv t0, a0 /* t0 = running dst */
mv t1, a1 /* t1 = running src */
beqz a2, .Ldone /* if n == 0, return */
@@ -85,7 +72,5 @@ memcpy:
.Ldone:
ret
-
- .size memcpy, .-memcpy
- .option pop
+END(memcpy)
#endif
@@ -9,14 +9,10 @@
http://www.opensource.org/licenses.
*/
+#include <sys/asm.h>
+
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
-.text
-.global memmove
-.type memmove, @function
-memmove:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(memmove)
beqz a2, .Ldone /* in case there are 0 bytes to be copied, return immediately */
@@ -40,17 +36,9 @@ memmove:
.Ldone:
ret
- .size memmove, .-memmove
+END(memmove)
#elif defined(__riscv_vector)
-.text
-.global memmove
-.type memmove, @function
-.option push
-.option arch, +zve32x
-memmove:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(memmove)
beqz a2, .Ldone_move /* n == 0 */
beq a0, a1, .Ldone_move /* dst == src */
@@ -135,6 +123,5 @@ memmove:
.Ldone_move:
ret
- .size memmove, .-memmove
- .option pop
+END(memmove)
#endif
@@ -1,11 +1,7 @@
+#include <sys/asm.h>
+
#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
-.text
-.global mempcpy
-.type mempcpy, @function
-mempcpy:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(mempcpy)
mv t0, a0 /* t0 = running dst */
mv t1, a1 /* t1 = running src */
beqz a2, .Ldone /* if n == 0, return */
@@ -49,6 +45,5 @@ mempcpy:
.Ldone:
mv a0, t0 /* return dst + n */
ret
-
- .size mempcpy, .-mempcpy
+END(mempcpy)
#endif
@@ -1,11 +1,7 @@
+#include <sys/asm.h>
+
#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
-.text
-.global memrchr
-.type memrchr, @function
-memrchr:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(memrchr)
andi a1, a1, 0xff
add a0, a0, a2
.Lloop:
@@ -33,5 +29,5 @@ memrchr:
.Lnohit:
li a0, 0
ret
-.size memrchr, .-memrchr
+END(memrchr)
#endif
@@ -42,18 +42,9 @@
#endif
-.text
-.global memset
-.type memset, @function
-
/* void *memset(void *s, int c, size_t n); */
-
-memset:
-#if __riscv_landing_pad
- lpad 0
-#endif
-
+ENTRY(memset)
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
mv a3, a0
beqz a2, .Ldone
@@ -323,4 +314,4 @@ memset:
.Lexit:
ret
#endif
-.size memset, .-memset
+END(memset)
@@ -1,11 +1,7 @@
+#include <sys/asm.h>
+
#if defined(__riscv_vector) && !defined(__OPTIMIZE_SIZE__) && !defined(PREFER_SIZE_OVER_SPEED)
-.text
-.global rawmemchr
-.type rawmemchr, @function
-rawmemchr:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(rawmemchr)
andi a1, a1, 0xff
.Lloop:
vsetvli t0, zero, e8, m1, ta, ma
@@ -23,5 +19,5 @@ rawmemchr:
.Lfound:
add a0, a0, a2
ret
-.size rawmemchr, .-rawmemchr
+END(rawmemchr)
#endif
@@ -12,12 +12,7 @@
#include <sys/asm.h>
/* int setjmp (jmp_buf); */
- .globl setjmp
- .type setjmp, @function
-setjmp:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(setjmp)
REG_S ra, 0*SZREG(a0)
#if __riscv_xlen == 32 && (__riscv_zilsd) && (__riscv_misaligned_fast)
sd s0, 1*SZREG(a0)
@@ -67,15 +62,10 @@ setjmp:
li a0, 0
ret
- .size setjmp, .-setjmp
+END(setjmp)
/* volatile void longjmp (jmp_buf, int); */
- .globl longjmp
- .type longjmp, @function
-longjmp:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(longjmp)
REG_L ra, 0*SZREG(a0)
#if __riscv_xlen == 32 && (__riscv_zilsd) && (__riscv_misaligned_fast)
ld s0, 1*SZREG(a0)
@@ -125,4 +115,4 @@ longjmp:
seqz a0, a1
add a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1
ret
- .size longjmp, .-longjmp
+END(longjmp)
@@ -12,13 +12,7 @@
#include <sys/asm.h>
#include "newlib.h"
-.text
-.globl strcmp
-.type strcmp, @function
-strcmp:
-#if __riscv_landing_pad
- lpad 0
-#endif
+ENTRY(strcmp)
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
.Lcompare:
@@ -240,7 +234,7 @@ strcmp:
mask:
.dword 0x7f7f7f7f7f7f7f7f
#endif
-.size strcmp, .-strcmp
+END(strcmp)
#if SZREG == 8 && !defined(__riscv_cmodel_large)
.section .srodata.cst8,"aM",@progbits,8
@@ -47,4 +47,38 @@
# endif
#endif
+/* Use 2-byte alignment when compressed instructions are available, since
+ they keep functions naturally aligned at 2 bytes; otherwise fall back to
+ 4-byte alignment to match the 32-bit instruction width. When landing
+ pads are enabled, force 4-byte alignment so every lpad target is aligned
+ to the 32-bit instruction width. */
+#if (defined(__riscv_c) || defined(__riscv_zca) || defined(__riscv_compressed)) && !defined(__riscv_landing_pad)
+#define _ENTRY(name) \
+ .text; \
+ .balign 2; \
+ .globl name; \
+name:
+#else
+#define _ENTRY(name) \
+ .text; \
+ .balign 4; \
+ .globl name; \
+name:
+#endif
+
+#define FUNC(name) .type name,@function
+#define END(name) \
+ .size name,.-name
+
+#if __riscv_landing_pad
+#define LPAD lpad 0
+#else
+#define LPAD
+#endif
+
+#define ENTRY(name) \
+ _ENTRY (name) \
+ .type name,@function; \
+ LPAD
+
#endif /* sys/asm.h */