diff options
-rw-r--r-- | Makefile | 16 | ||||
-rw-r--r-- | rv.S | 37 | ||||
-rw-r--r-- | rv.c | 85 |
3 files changed, 92 insertions, 46 deletions
@@ -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 @@ -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 @@ -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)); } } |