aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile16
-rw-r--r--rv.S37
-rw-r--r--rv.c85
3 files changed, 92 insertions, 46 deletions
diff --git a/Makefile b/Makefile
index dc34210..54bccfb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,19 +1,29 @@
.POSIX:
-# riscv-gnu-toolchain w/ --with-arch=rv64gcv + GCC 13.1
TOOLCHAIN=/home/yuuta/toolchain13/bin/
CROSS=riscv64-unknown-linux-gnu-
_T=$(TOOLCHAIN)$(CROSS)
-run: rv.exe
+debug: rv.exe
+ # -L: See riscv-gnu-toolchain README.
+ # QEMU needs to locate ld.so
+ # or chroot which I'm too lazy to setup
qemu-riscv64 \
+ -L $(TOOLCHAIN)/../sysroot/ \
-g 10000 \
-cpu rv64,v=true,zba=true,vlen=256 \
./rv.exe &
$(_T)gdb -ex 'target remote localhost:10000' -tui ./rv.exe
+run: rv.exe
+ qemu-riscv64 \
+ -L $(TOOLCHAIN)/../sysroot/ \
+ -cpu rv64,v=true,zba=true,vlen=256 \
+ ./rv.exe
+
rv.exe: rv.c.o rv.s.o
- $(_T)ld -o rv.exe rv.c.o rv.s.o
+ # I gave up linking glibc myself
+ $(_T)gcc -O0 -o rv.exe rv.c.o rv.s.o
rv.c.o: rv.c
$(_T)gcc -O2 -march=rv64imv -g -c -o rv.c.o rv.c
diff --git a/rv.S b/rv.S
index b999a41..73e8281 100644
--- a/rv.S
+++ b/rv.S
@@ -1,16 +1,7 @@
-.section .rodata
-STR:
- .string "Hello, World!"
- .zero 242
-
-SH1:
- .incbin "/usr/bin/bash"
-
-SH2:
- .incbin "/usr/bin/systemctl"
-
.section .text
-memcpy: # void *memcpy(a0 dst, a1 src, a2 n)
+.global memcpy_asm
+# Note the calling convention.
+memcpy_asm: # void *memcpy(a0 dst, a1 src, a2 n)
mv t1, a0 # dst1
loop:
vsetvli t0, a2, e8, m8, ta, ma # VL = min(a2, 8 * VLEN / 8)
@@ -22,7 +13,8 @@ loop:
bnez a2, loop # if (n) goto loop
ret
-memcmp: # bool memcmp(a0 s0, a1 s1, a2 n)
+.global memcmp_asm
+memcmp_asm: # bool memcmp(a0 s0, a1 s1, a2 n)
vsetvli t0, a2, e8, m8, ta, ma
vle8.v v8, (a0) # [v8, v15] = s0
vle8.v v16, (a1) # [v16, v23] = s1
@@ -37,22 +29,3 @@ memcmp: # bool memcmp(a0 s0, a1 s1, a2 n)
memcmp_ret:
mv a0, t1 # Copy t1 to return value
ret
-
-exit:
- li a7, 93
- ecall
- jr ra
-
-.global _start
-_start:
- addi sp, sp, -256
- li a2, 130 # n
- la a1, STR # src
- mv a0, sp # dst
- jal memcpy_c
- li a2, 128 # n
- mv a1, sp # src
- la a0, STR # dst
- jal memcmp
- addi sp, sp, 256
- jal exit
diff --git a/rv.c b/rv.c
index b0f239d..572ac5d 100644
--- a/rv.c
+++ b/rv.c
@@ -1,5 +1,18 @@
#include <riscv_vector.h>
#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+
+static int fd_rand = -1;
+
+void *memcpy_asm(void *dst, const void *src, size_t n);
+
+bool memcmp_asm(const void *s0, const void *s1, size_t n);
void *memcpy_c(void *dst, const void *src, size_t n) {
void *dst2 = dst;
@@ -14,22 +27,72 @@ void *memcpy_c(void *dst, const void *src, size_t n) {
return dst;
}
-bool memcmp_c(void *s1, void *s2, size_t n) {
+bool memcmp_c(const void *s1, const void *s2, size_t n) {
while (n) {
size_t vl = __riscv_vsetvl_e8m8(n);
vuint8m8_t v1 = __riscv_vle8_v_u8m8(s1, vl);
- vuint8m8_t v2 = __riscv_vle8_v_u8m8(s1, vl);
- vuint8m8_t vd = __riscv_vle8_v_u8m8(s1, vl);
+ vuint8m8_t v2 = __riscv_vle8_v_u8m8(s2, vl);
+ vbool1_t vd = __riscv_vmsne_vv_u8m8_b1(v1, v2, vl);
+ if (__riscv_vcpop_m_b1(vd, vl)) {
+ return true;
+ }
+ s1 += vl;
+ s2 += vl;
+ n -= vl;
}
+ return false;
}
-bool memcmp_naive(void *s1, void *s2, size_t n) {
- while (n) {
- if (*((char *) s1) != *((char *) s2)) {
- return true;
- }
- s1 ++;
- s2 ++;
- n --;
+void ass_fail(const char *ass, const char *file, unsigned int line,
+ const char *func, char *dst, char *src, size_t n) {
+ printf("ass_fail\n");
+ printf("ASSERTION FAIL: %s (%s:%u, %s, %u)\nDST:",
+ ass, file, line, func, n);
+ for (unsigned int i = 0; i < n; i ++) {
+ printf("%x", dst[i]);
+ }
+ printf("SRC:");
+ for (unsigned int i = 0; i < n; i ++) {
+ printf("%x", src[i]);
+ }
+ printf("---\n");
+ assert(0);
+}
+
+#define ass(expr) \
+((expr) \
+ ? __ASSERT_VOID_CAST (0) \
+ : ass_fail(#expr, __FILE__, __LINE__, __ASSERT_FUNCTION, dst, src, n))
+
+
+int main(int argc, char **argv) {
+ char dst[2048];
+ char src[sizeof(dst)];
+ size_t n;
+ setvbuf(stdout, NULL, _IONBF, 0);
+ fd_rand = open("/dev/urandom", 0, O_RDONLY);
+ srand(time(NULL));
+ for (unsigned int i = 0; i < 100000; i ++) {
+ n = rand() % sizeof(src) + 1;
+ read(fd_rand, src, n);
+
+ printf("Testing memcpy: %p[%x] -> %p (%u)\n", src, src[0], dst, n);
+ memcpy_c(dst, src, n);
+ ass(!memcmp(dst, src, n));
+ }
+ for (unsigned int i = 0; i < 100000; i ++) {
+ n = rand() % sizeof(src) + 1;
+ read(fd_rand, dst, n);
+ read(fd_rand, src, n);
+ if (!memcmp(dst, src, n)) continue;
+
+ printf("Testing memcmp: %p[%x] == %p[%x] (%u)\n", src, src[0],
+ dst, dst[0], n);
+ ass(memcmp_c(dst, src, n));
+ ass(memcmp_asm(dst, src, n));
+
+ memcpy(dst, src, n);
+ ass(!memcmp_c(dst, src, n));
+ ass(!memcmp_asm(dst, src, n));
}
}