Commit Diff


commit - 112859b68b19ef3ede8c8d6b462e29e3a4231197
commit + a8ceaca4fff83dffd72f34c096e41d5a0cdfce5c
blob - d5a600d820bf688595bba5fe8d1422b4282f2199
blob + c0e9ed862854b37f31f7b51c55cc177ce45f5806
--- .gitignore
+++ .gitignore
@@ -6,12 +6,13 @@ tools/libexec
 tools/riscv64-unknown-linux-musl
 tools/share
 tools/src
+src/syscalls.h
+src/*.o
 *.swp
 *.core
 *.o
 *.elf
 *.pdf
 rootfs
-syscalls.h
 rvemu
 
blob - c1b64dea367cf49f7f9f16f859eb4ff99407573e
blob + cc581bb65cc25b6023263787fb09d3492a7b8c5e
--- Makefile
+++ Makefile
@@ -9,8 +9,8 @@ TARGET	= riscv64-unknown-linux-musl
 CROSS	= ./tools/bin/${TARGET}
 CFLAGS	= -std=c2x -fPIC -O0 -g
 LDFLAGS	= -pie -static -lpthread
-OBJ	= rvemu.o ecall.o cpu.o exec.o
-PROGS	= test.elf hello.elf
+OBJ	= src/rvemu.o src/ecall.o src/cpu.o src/exec.o
+PROGS	= test.elf
 
 all: rvemu ${PROGS}
 
@@ -18,7 +18,7 @@ od: test.elf
 	${CROSS}-objdump -d test.elf | less
 
 clean:
-	rm -f rvemu *.o *.elf *.core syscalls.h
+	rm -f rvemu src/*.o *.elf *.core src/syscalls.h
 	rm -rf rootfs
 
 install: rvemu
@@ -35,21 +35,15 @@ run: rvemu ${PROGS}
 rvemu: ${OBJ}
 	${CC} -o $@ ${OBJ} ${LDFLAGS}
 
-ecall.o: syscalls.h
+src/ecall.o: src/syscalls.h
 
-syscalls.h: syscalls.inc
+src/syscalls.h: src/syscalls.inc
 	sed 's/^\.set \(SYS_[a-z0-9_]*\), \([0-9]*\)$$/#define \1 \2/'	\
-		< syscalls.inc > syscalls.h
+		< src/syscalls.inc > $@
 
-.c.o: rvemu.h
+.c.o: src/rvemu.h
 	${CC} -c -o $@ $< ${CFLAGS}
 
 
-.S.o: syscalls.inc
-	${CROSS}-as -o $@ $<
-
-.c.elf: linker.ld
+.c.elf:
 	${CROSS}-gcc -o $@ $<
-
-.o.elf: linker.ld
-	${CROSS}-ld -s -T linker.ld -o $@ $<
blob - 44537fe39bb4e8ea22f90917381b9327ef99beb9 (mode 644)
blob + /dev/null
--- cpu.c
+++ /dev/null
@@ -1,394 +0,0 @@
-#include "rvemu.h"
-
-static u64 regs[31];
-u64 pc;
-
-void cpu_set (size_t reg, u64 val)
-{
-	if (reg > 0)
-		regs[reg - 1] = val;
-}
-
-u64 cpu_get (size_t reg)
-{
-	return reg > 0 ? regs[reg - 1] : 0;
-}
-
-u32 cpu_fetch (void)
-{
-	const u32 i = *(const u32 *)(size_t)pc;
-	//eprintf ("%08x: %08x\n", cpu->pc, i);
-	pc += 4;
-	return i;
-}
-
-static i64 extend (i32 x)
-{
-	return x;
-}
-
-#define log(fmt, ...) eprintf ("%08llx: " fmt "\n", pc - 4, __VA_ARGS__)
-void cpu_exec (u32 instr)
-{
-	const char *name;
-	const u8 rd = (instr >> 7) & 0x1f;
-	const u8 funct3 = (instr >> 12) & 0x7;
-	const u8 rs1 = (instr >> 15) & 0x1f;
-	const u8 rs2 = (instr >> 20) & 0x1f;
-	const u8 funct7 = instr >> 25;
-	const u8 funct6 = instr >> 26;
-	const u64 imm_i = extend ((i32)instr >> 20);
-	const u64 imm_s = extend (((i32)instr >> 25 << 5) | ((instr >> 7) & 0x1f));
-	const u64 imm_b = extend (((i32)instr >> 31 << 12)
-		| (((instr >> 25) & 0x3f) << 5)
-		| (((instr >> 8) & 0xf) << 1)
-		| (((instr >> 7) & 1) << 11));
-	const u64 imm_u = extend (instr & 0xfffff000);
-	const u64 imm_j = extend (((i32)instr >> 31 << 20)
-		| (((instr >> 21) & 0x3ff) << 1)
-		| (((instr >> 20) & 1) << 11)
-		| (((instr >> 12) & 0xff) << 12));
-	const u16 funct10 = (funct7 << 3) | funct3;
-	const u8 shamt = imm_i & 0x3f;
-
-	u64 a, b, c;
-	switch (instr & 0x7f) {
-	case 0b0110111: // lui rd, uimm
-		log ("lui x%u, %llu", (uint)rd, imm_u);
-		cpu_set (rd, imm_u);
-		break;
-	case 0b0010111: // auipc rd, uimm
-		log ("auipc x%u, %llu", (uint)rd, imm_u);
-		cpu_set (rd, pc + imm_u - 4);
-		break;
-	case 0b1101111: // jal rd, jimm
-		log ("jal x%u, %lld", (uint)rd, imm_j);
-		cpu_set (rd, pc);
-		pc += imm_j - 4;
-		break;
-	case 0b1100111: // jalr rd, rs1, iimm
-		switch (funct3) {
-		case 0b000:
-			log ("jalr x%u, x%u, %lld", (uint)rd, (uint)rs1, imm_i);
-			cpu_set (rd, pc);
-			pc = cpu_get (rs1);
-			break;
-		default:
-			goto ud;
-		}
-		break;
-	case 0b1100011: // bcc rs1, rs2, bimm
-		a = cpu_get (rs1);
-		b = cpu_get (rs2);
-		switch (funct3) {
-		case 0b000:
-			name = "beq";
-			c = a == b;
-			break;
-		case 0b001:
-			name = "bne";
-			c = a != b;
-			break;
-		case 0b100:
-			name = "blt";
-			c = (i64)a < (i64)b;
-			break;
-		case 0b101:
-			name = "bge";
-			c = (i64)a >= (i64)b;
-			break;
-		case 0b110:
-			name = "bltu";
-			c = a < b;
-			break;
-		case 0b111:
-			name = "bgeu";
-			c = a >= b;
-			break;
-		default:
-			goto ud;
-		}
-		log ("%s x%u, x%u, %d", name, (uint)rs1, (uint)rs2, (int)imm_b);
-		if (c)
-			pc += imm_b - 4;
-		break;
-	case 0b0000011: // lx rd, iimm(rs1)
-		a = cpu_get (rs1) + imm_i;
-		switch (funct3) {
-		case 0b000: // lb
-			name = "lb";
-			b = (i64)read_i8 (a);
-			break;
-		case 0b001: // lh
-			name = "lh";
-			b = (i64)read_i16 (a);
-			break;
-		case 0b010: // lw
-			name = "lw";
-			b = (i64)read_i32 (a);
-			break;
-		case 0b011: // ld
-			name = "ld";
-			b = read_u64 (a);
-			break;
-		case 0b100: // lbu
-			name = "lbu";
-			b = read_u8 (a);
-			break;
-		case 0b101: // lhu
-			name = "lhu";
-			b = read_u16 (a);
-			break;
-		case 0b110: // lwu
-			name = "lwu";
-			b = read_u32 (a);
-			break;
-		default:
-			goto ud;
-		}
-		log ("%s x%u, %d(x%u)", name, (uint)rd, (int)imm_i, (uint)rs1);
-		cpu_set (rd, b);
-		break;
-	case 0b0100011: // sx rs2, simm(rs1)
-		a = cpu_get (rs2);
-		b = cpu_get (rs1) + imm_s;
-		switch (funct3) {
-		case 0b000: // sb
-			name = "sb";
-			write_u8 (b, a);
-			break;
-		case 0b001: // sh
-			name = "sh";
-			write_u16 (b, a);
-			break;
-		case 0b010: // sw
-			name = "sw";
-			write_u32 (b, a);
-			break;
-		case 0b011: // sd
-			 name = "sd";
-			 write_u64 (b, a);
-			 break;
-		default:
-			goto ud;
-		}
-		log ("%s x%u, %d(x%u)", name, (uint)rs2, (int)imm_s, (uint)rs1);
-		break;
-	case 0b0010011: // alui rd, rs1, iimm
-		a = cpu_get (rs1);
-		b = imm_i;
-		switch (funct3) {
-		case 0b000: // addi
-			name = "addi";
-			c = a + b;
-			break;
-		case 0b001: // slli
-			if (funct6 != 0)
-				goto ud;
-			name = "slli";
-			c = a << shamt;
-			break;
-		case 0b010: // slti
-			name = "slti";
-			c = (i64)a < (i64)b;
-			break;
-		case 0b011: // sltiu
-			name = "sltiu";
-			c = a < b;
-			break;
-		case 0b100: // xori
-			name = "xori";
-			c = a ^ b;
-			break;
-		case 0b101: // srli/srai
-			switch (funct6) {
-			case 0b000000:
-				name = "srli";
-				c = a >> shamt;
-				break;
-			case 0b010000:
-				name = "srai";
-				c = (i64)a >> shamt;
-				break;
-			default:
-				goto ud;
-			}
-			break;
-		case 0b110: // ori
-			name = "ori";
-			c = a | b;
-			break;
-		case 0b111: // andi
-			name = "andi";
-			c = a & b;
-			break;
-		default:
-			goto ud;
-		}
-		log ("%s x%u, x%u, %lld", name, (uint)rd, (uint)rs1, (i64)imm_i);
-		cpu_set (rd, c);
-		break;
-	case 0b0011011: // aluiw rd, rs1, iimm
-		a = cpu_get (rs1);
-		b = imm_i;
-		c = (instr >> 30) & 1;
-		switch (funct3) {
-		case 0b000: // addiw
-			name = "addiw";
-			c = a + b;
-			break;
-		case 0b001: // slliw
-			if (shamt >> 5)
-				goto ud;
-			name = "slliw";
-			c = a << shamt;
-			break;
-		case 0b101: // srliw/sraiw
-			if (shamt >> 5)
-				goto ud;
-			switch (funct7) {
-			case 0b0000000:
-				name = "srliw";
-				c = (u32)a >> shamt;
-				break;
-			case 0b0100000:
-				name = "sraiw";
-				c = (i32)a >> shamt;
-				break;
-			default:
-				goto ud;
-			}
-			break;
-		default:
-			goto ud;
-		}
-		c &= 0x00000000ffffffff;
-		c = extend (c);
-		log ("%s x%u, x%u, %lld", name, (uint)rd, (uint)rs1, (i64)imm_i);
-		cpu_set (rd, c);
-		break;
-	case 0b0110011: // alu rd, rs1, rs2
-		a = cpu_get (rs1);
-		b = cpu_get (rs2);
-		switch (funct10) {
-		case 0b0000000'000:
-			name = "add";
-			c = a + b;
-			break;
-		case 0b0000001'000:
-			name = "mul";
-			c = a * b;
-			break;
-		case 0b0100000'000:
-			name = "sub";
-			c = a - b;
-			break;
-		case 0b0000000'001:
-			name = "sll";
-			c = a << b;
-			break;
-		case 0b0000000'010:
-			name = "slt";
-			c = (i64)a < (i64)b;
-			break;
-		case 0b0000000'011:
-			name = "sltu";
-			c = a < b;
-			break;
-		case 0b0000000'100:
-			name = "xor";
-			c = a ^ b;
-			break;
-		case 0b0000001'100:
-			name = "div";
-			c = b != 0 ? (i64)a / (i64)b : -1;
-			break;
-		case 0b0000000'101:
-			name = "srl";
-			c = a >> (b & 0x3f);
-			break;
-		case 0b0000001'101:
-			name = "divu";
-			c = b != 0 ? a / b : -1;
-			break;
-		case 0b0100000'101:
-			name = "sra";
-			c = (i64)a >> (b & 0x3f);
-			break;
-		case 0b0000000'110:
-			name = "or";
-			c = a | b;
-			break;
-		case 0b0000001'110:
-			name = "rem";
-			c = b != 0 ? (i64)a % (i64)b : -1;
-			break;
-		case 0b0000000'111:
-			name = "and";
-			c = a & b;
-			break;
-		case 0b0000001'111:
-			name = "remu";
-			c = b != 0 ? a % b : -1;
-			break;
-		}
-		log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2);
-		cpu_set (rd, c);
-		break;
-	case 0b0111011: // aluw
-		a = cpu_get (rs1);
-		b = cpu_get (rs2);
-		switch (funct10) {
-		case 0b0000000'000: // addw
-			name = "addw";
-			c = a + b;
-			break;
-		case 0b0100000'000: // subw
-			name = "addw";
-			c = a - b;
-			break;
-		case 0b0000000'001: // sllw
-			name = "sllw";
-			c = a << (b & 0x1f);
-			break;
-		case 0b0000000'101: // srlw
-			name = "srlw";
-			c = a >> (b & 0x1f);
-			break;
-		case 0b0100000'101: // sraw
-			name = "sraw";
-			c = (i64)a >> (b & 0x1f);
-			break;
-		default:
-			goto ud;
-		}
-		log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2);
-		cpu_set (rd, extend ((i32)a));
-		break;
-	case 0b0001111: // fence/fence.tso/pause
-		eprintf ("%08llx: efence\n", pc - 4);
-		break;
-	case 0b1110011: // ecall/ebreak
-		if ((instr >> 20) & 1) {
-			eprintf ("%08llx: ebreak\n", pc - 4);
-			__asm __volatile__ ("int $3");
-		} else {
-			log (
-				"ecall a0=%llu, a1=%llu, a2=%llu, a3=%llu, a4=%llu, a5=%llu, a7=%llu",
-				cpu_get (10),
-				cpu_get (11),
-				cpu_get (12),
-				cpu_get (13),
-				cpu_get (14),
-				cpu_get (15),
-				cpu_get (17)
-			);
-			ecall ();
-		}
-		break;
-	default:
-	ud:
-		errx (1, "%08llx: invalid instruction: %08x", pc - 4, instr);
-	}
-}
-
blob - /dev/null
blob + 44537fe39bb4e8ea22f90917381b9327ef99beb9 (mode 644)
--- /dev/null
+++ src/cpu.c
@@ -0,0 +1,394 @@
+#include "rvemu.h"
+
+static u64 regs[31];
+u64 pc;
+
+void cpu_set (size_t reg, u64 val)
+{
+	if (reg > 0)
+		regs[reg - 1] = val;
+}
+
+u64 cpu_get (size_t reg)
+{
+	return reg > 0 ? regs[reg - 1] : 0;
+}
+
+u32 cpu_fetch (void)
+{
+	const u32 i = *(const u32 *)(size_t)pc;
+	//eprintf ("%08x: %08x\n", cpu->pc, i);
+	pc += 4;
+	return i;
+}
+
+static i64 extend (i32 x)
+{
+	return x;
+}
+
+#define log(fmt, ...) eprintf ("%08llx: " fmt "\n", pc - 4, __VA_ARGS__)
+void cpu_exec (u32 instr)
+{
+	const char *name;
+	const u8 rd = (instr >> 7) & 0x1f;
+	const u8 funct3 = (instr >> 12) & 0x7;
+	const u8 rs1 = (instr >> 15) & 0x1f;
+	const u8 rs2 = (instr >> 20) & 0x1f;
+	const u8 funct7 = instr >> 25;
+	const u8 funct6 = instr >> 26;
+	const u64 imm_i = extend ((i32)instr >> 20);
+	const u64 imm_s = extend (((i32)instr >> 25 << 5) | ((instr >> 7) & 0x1f));
+	const u64 imm_b = extend (((i32)instr >> 31 << 12)
+		| (((instr >> 25) & 0x3f) << 5)
+		| (((instr >> 8) & 0xf) << 1)
+		| (((instr >> 7) & 1) << 11));
+	const u64 imm_u = extend (instr & 0xfffff000);
+	const u64 imm_j = extend (((i32)instr >> 31 << 20)
+		| (((instr >> 21) & 0x3ff) << 1)
+		| (((instr >> 20) & 1) << 11)
+		| (((instr >> 12) & 0xff) << 12));
+	const u16 funct10 = (funct7 << 3) | funct3;
+	const u8 shamt = imm_i & 0x3f;
+
+	u64 a, b, c;
+	switch (instr & 0x7f) {
+	case 0b0110111: // lui rd, uimm
+		log ("lui x%u, %llu", (uint)rd, imm_u);
+		cpu_set (rd, imm_u);
+		break;
+	case 0b0010111: // auipc rd, uimm
+		log ("auipc x%u, %llu", (uint)rd, imm_u);
+		cpu_set (rd, pc + imm_u - 4);
+		break;
+	case 0b1101111: // jal rd, jimm
+		log ("jal x%u, %lld", (uint)rd, imm_j);
+		cpu_set (rd, pc);
+		pc += imm_j - 4;
+		break;
+	case 0b1100111: // jalr rd, rs1, iimm
+		switch (funct3) {
+		case 0b000:
+			log ("jalr x%u, x%u, %lld", (uint)rd, (uint)rs1, imm_i);
+			cpu_set (rd, pc);
+			pc = cpu_get (rs1);
+			break;
+		default:
+			goto ud;
+		}
+		break;
+	case 0b1100011: // bcc rs1, rs2, bimm
+		a = cpu_get (rs1);
+		b = cpu_get (rs2);
+		switch (funct3) {
+		case 0b000:
+			name = "beq";
+			c = a == b;
+			break;
+		case 0b001:
+			name = "bne";
+			c = a != b;
+			break;
+		case 0b100:
+			name = "blt";
+			c = (i64)a < (i64)b;
+			break;
+		case 0b101:
+			name = "bge";
+			c = (i64)a >= (i64)b;
+			break;
+		case 0b110:
+			name = "bltu";
+			c = a < b;
+			break;
+		case 0b111:
+			name = "bgeu";
+			c = a >= b;
+			break;
+		default:
+			goto ud;
+		}
+		log ("%s x%u, x%u, %d", name, (uint)rs1, (uint)rs2, (int)imm_b);
+		if (c)
+			pc += imm_b - 4;
+		break;
+	case 0b0000011: // lx rd, iimm(rs1)
+		a = cpu_get (rs1) + imm_i;
+		switch (funct3) {
+		case 0b000: // lb
+			name = "lb";
+			b = (i64)read_i8 (a);
+			break;
+		case 0b001: // lh
+			name = "lh";
+			b = (i64)read_i16 (a);
+			break;
+		case 0b010: // lw
+			name = "lw";
+			b = (i64)read_i32 (a);
+			break;
+		case 0b011: // ld
+			name = "ld";
+			b = read_u64 (a);
+			break;
+		case 0b100: // lbu
+			name = "lbu";
+			b = read_u8 (a);
+			break;
+		case 0b101: // lhu
+			name = "lhu";
+			b = read_u16 (a);
+			break;
+		case 0b110: // lwu
+			name = "lwu";
+			b = read_u32 (a);
+			break;
+		default:
+			goto ud;
+		}
+		log ("%s x%u, %d(x%u)", name, (uint)rd, (int)imm_i, (uint)rs1);
+		cpu_set (rd, b);
+		break;
+	case 0b0100011: // sx rs2, simm(rs1)
+		a = cpu_get (rs2);
+		b = cpu_get (rs1) + imm_s;
+		switch (funct3) {
+		case 0b000: // sb
+			name = "sb";
+			write_u8 (b, a);
+			break;
+		case 0b001: // sh
+			name = "sh";
+			write_u16 (b, a);
+			break;
+		case 0b010: // sw
+			name = "sw";
+			write_u32 (b, a);
+			break;
+		case 0b011: // sd
+			 name = "sd";
+			 write_u64 (b, a);
+			 break;
+		default:
+			goto ud;
+		}
+		log ("%s x%u, %d(x%u)", name, (uint)rs2, (int)imm_s, (uint)rs1);
+		break;
+	case 0b0010011: // alui rd, rs1, iimm
+		a = cpu_get (rs1);
+		b = imm_i;
+		switch (funct3) {
+		case 0b000: // addi
+			name = "addi";
+			c = a + b;
+			break;
+		case 0b001: // slli
+			if (funct6 != 0)
+				goto ud;
+			name = "slli";
+			c = a << shamt;
+			break;
+		case 0b010: // slti
+			name = "slti";
+			c = (i64)a < (i64)b;
+			break;
+		case 0b011: // sltiu
+			name = "sltiu";
+			c = a < b;
+			break;
+		case 0b100: // xori
+			name = "xori";
+			c = a ^ b;
+			break;
+		case 0b101: // srli/srai
+			switch (funct6) {
+			case 0b000000:
+				name = "srli";
+				c = a >> shamt;
+				break;
+			case 0b010000:
+				name = "srai";
+				c = (i64)a >> shamt;
+				break;
+			default:
+				goto ud;
+			}
+			break;
+		case 0b110: // ori
+			name = "ori";
+			c = a | b;
+			break;
+		case 0b111: // andi
+			name = "andi";
+			c = a & b;
+			break;
+		default:
+			goto ud;
+		}
+		log ("%s x%u, x%u, %lld", name, (uint)rd, (uint)rs1, (i64)imm_i);
+		cpu_set (rd, c);
+		break;
+	case 0b0011011: // aluiw rd, rs1, iimm
+		a = cpu_get (rs1);
+		b = imm_i;
+		c = (instr >> 30) & 1;
+		switch (funct3) {
+		case 0b000: // addiw
+			name = "addiw";
+			c = a + b;
+			break;
+		case 0b001: // slliw
+			if (shamt >> 5)
+				goto ud;
+			name = "slliw";
+			c = a << shamt;
+			break;
+		case 0b101: // srliw/sraiw
+			if (shamt >> 5)
+				goto ud;
+			switch (funct7) {
+			case 0b0000000:
+				name = "srliw";
+				c = (u32)a >> shamt;
+				break;
+			case 0b0100000:
+				name = "sraiw";
+				c = (i32)a >> shamt;
+				break;
+			default:
+				goto ud;
+			}
+			break;
+		default:
+			goto ud;
+		}
+		c &= 0x00000000ffffffff;
+		c = extend (c);
+		log ("%s x%u, x%u, %lld", name, (uint)rd, (uint)rs1, (i64)imm_i);
+		cpu_set (rd, c);
+		break;
+	case 0b0110011: // alu rd, rs1, rs2
+		a = cpu_get (rs1);
+		b = cpu_get (rs2);
+		switch (funct10) {
+		case 0b0000000'000:
+			name = "add";
+			c = a + b;
+			break;
+		case 0b0000001'000:
+			name = "mul";
+			c = a * b;
+			break;
+		case 0b0100000'000:
+			name = "sub";
+			c = a - b;
+			break;
+		case 0b0000000'001:
+			name = "sll";
+			c = a << b;
+			break;
+		case 0b0000000'010:
+			name = "slt";
+			c = (i64)a < (i64)b;
+			break;
+		case 0b0000000'011:
+			name = "sltu";
+			c = a < b;
+			break;
+		case 0b0000000'100:
+			name = "xor";
+			c = a ^ b;
+			break;
+		case 0b0000001'100:
+			name = "div";
+			c = b != 0 ? (i64)a / (i64)b : -1;
+			break;
+		case 0b0000000'101:
+			name = "srl";
+			c = a >> (b & 0x3f);
+			break;
+		case 0b0000001'101:
+			name = "divu";
+			c = b != 0 ? a / b : -1;
+			break;
+		case 0b0100000'101:
+			name = "sra";
+			c = (i64)a >> (b & 0x3f);
+			break;
+		case 0b0000000'110:
+			name = "or";
+			c = a | b;
+			break;
+		case 0b0000001'110:
+			name = "rem";
+			c = b != 0 ? (i64)a % (i64)b : -1;
+			break;
+		case 0b0000000'111:
+			name = "and";
+			c = a & b;
+			break;
+		case 0b0000001'111:
+			name = "remu";
+			c = b != 0 ? a % b : -1;
+			break;
+		}
+		log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2);
+		cpu_set (rd, c);
+		break;
+	case 0b0111011: // aluw
+		a = cpu_get (rs1);
+		b = cpu_get (rs2);
+		switch (funct10) {
+		case 0b0000000'000: // addw
+			name = "addw";
+			c = a + b;
+			break;
+		case 0b0100000'000: // subw
+			name = "addw";
+			c = a - b;
+			break;
+		case 0b0000000'001: // sllw
+			name = "sllw";
+			c = a << (b & 0x1f);
+			break;
+		case 0b0000000'101: // srlw
+			name = "srlw";
+			c = a >> (b & 0x1f);
+			break;
+		case 0b0100000'101: // sraw
+			name = "sraw";
+			c = (i64)a >> (b & 0x1f);
+			break;
+		default:
+			goto ud;
+		}
+		log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2);
+		cpu_set (rd, extend ((i32)a));
+		break;
+	case 0b0001111: // fence/fence.tso/pause
+		eprintf ("%08llx: efence\n", pc - 4);
+		break;
+	case 0b1110011: // ecall/ebreak
+		if ((instr >> 20) & 1) {
+			eprintf ("%08llx: ebreak\n", pc - 4);
+			__asm __volatile__ ("int $3");
+		} else {
+			log (
+				"ecall a0=%llu, a1=%llu, a2=%llu, a3=%llu, a4=%llu, a5=%llu, a7=%llu",
+				cpu_get (10),
+				cpu_get (11),
+				cpu_get (12),
+				cpu_get (13),
+				cpu_get (14),
+				cpu_get (15),
+				cpu_get (17)
+			);
+			ecall ();
+		}
+		break;
+	default:
+	ud:
+		errx (1, "%08llx: invalid instruction: %08x", pc - 4, instr);
+	}
+}
+
blob - /dev/null
blob + 23d31d68cbaa4919d7ea80f36ba6af592227e811 (mode 644)
--- /dev/null
+++ src/ecall.c
@@ -0,0 +1,967 @@
+#include <sys/resource.h>
+#include <sys/utsname.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/msg.h>
+#include <sys/sem.h>
+#include <sys/uio.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <errno.h>
+#include "syscalls.h"
+#include "rvemu.h"
+
+struct linux_stat64 {
+	u64 dev;
+	u64 ino;
+	u32 mode;
+	u32 nlink;
+	u32 uid;
+	u32 gid;
+	u64 rdev;
+	u64 __pad1;
+	u64 size;
+	u32 blksize;
+	u32 __pad2;
+	u64 blocks;
+	u32 atime;
+	u32 atime_ns;
+	u32 mtime;
+	u32 mtime_ns;
+	u32 ctime;
+	u32 ctime_ns;
+	u32 __unused4;
+	u32 __unused5;
+};
+
+struct linux_utsname {
+	char sysname[65];
+	char nodename[65];
+	char release[65];
+	char version[65];
+	char machine[65];
+};
+
+static int map_errno (int err)
+{
+	const int errnos[] = {
+		[EPERM]		= 1,
+		[ENOENT]	= 2,
+		[ESRCH]		= 3,
+		[EINTR]		= 4,
+		[EIO]		= 5,
+		[ENXIO]		= 6,
+		[E2BIG]		= 7,
+		[ENOEXEC]	= 8,
+		[EBADF]		= 9,
+		[ECHILD]	= 10,
+		[EAGAIN]	= 11,
+		[ENOMEM]	= 12,
+		[EACCES]	= 13,
+		[EFAULT]	= 14,
+		[ENOTBLK]	= 15,
+		[EBUSY]		= 16,
+		[EEXIST]	= 17,
+		[EXDEV]		= 18,
+		[ENODEV]	= 19,
+		[ENOTDIR]	= 20,
+		[EISDIR]	= 21,
+		[EINVAL]	= 22,
+		[ENFILE]	= 23,
+		[EMFILE]	= 24,
+		[ENOTTY]	= 25,
+		[ETXTBSY]	= 26,
+		[EFBIG]		= 27,
+		[ENOSPC]	= 28,
+		[ESPIPE]	= 29,
+		[EROFS]		= 30,
+		[EMLINK]	= 31,
+		[EPIPE]		= 32,
+		[EDOM]		= 33,
+		[ERANGE]	= 34,
+		[EDEADLK]	= 35,
+		[ENAMETOOLONG]	= 36,
+		[ENOLCK]	= 37,
+		[ENOSYS]	= 38,
+	};
+	return errnos[err];
+}
+
+static int map (int x) {
+	return x < 0 ? -map_errno (errno) : x;
+}
+
+
+static void stat_to_linux_stat (struct linux_stat64 *lst, const struct stat *st)
+{
+	memset (lst, 0, sizeof (*lst));
+	lst->dev	= st->st_dev;
+	lst->ino	= st->st_dev;
+	lst->mode	= st->st_dev;
+	lst->nlink	= st->st_dev;
+	lst->uid	= st->st_dev;
+	lst->gid	= st->st_dev;
+	lst->rdev	= st->st_dev;
+	lst->size	= st->st_dev;
+	lst->blksize	= st->st_dev;
+	lst->blocks	= st->st_dev;
+	lst->atime	= st->st_atim.tv_sec;
+	lst->atime_ns	= st->st_atim.tv_nsec;
+	lst->mtime	= st->st_mtim.tv_sec;
+	lst->mtime_ns	= st->st_mtim.tv_nsec;
+	lst->ctime	= st->st_ctim.tv_sec;
+	lst->ctime_ns	= st->st_ctim.tv_nsec;
+}
+
+static void utsname_to_linux_utsname (struct linux_utsname *lun, const struct utsname *un)
+{
+	memset (lun, 0, sizeof (*lun));
+	strlcpy (lun->sysname,	un->sysname, 65);
+	strlcpy (lun->nodename,	un->nodename, 65);
+	strlcpy (lun->release,	un->release, 65);
+	strlcpy (lun->version,	un->version, 65);
+	strlcpy (lun->machine,	un->machine, 65);
+}
+
+static int enosys (const char *sys)
+{
+	warnx ("unimplemented syscall: %s", sys);
+	return -map_errno (ENOSYS);
+}
+
+static u64 my_brk (u64 new)
+{
+	void *ptr;
+
+	if (new < brkval)
+		return brkval;
+	if (new >= 0x78000000) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	new = (new + 4095) & ~0x3ff;
+	ptr = mmap (
+		(void *)brkval,
+		new - brkval,
+		PROT_READ | PROT_WRITE,
+		MAP_PRIVATE | MAP_ANON,
+		-1,
+		0
+	);
+	if (ptr == NULL)
+		return -1;
+	brkval = new;
+	return brkval;
+}
+
+#define ptr(T, x) ((T *)(x))
+#define str(x) ptr (const char, x)
+void ecall (void)
+{
+	struct linux_stat64 lst;
+	struct linux_utsname lun;
+	struct stat st;
+	struct utsname un;
+	void *ptr;
+	const u64 a0 = cpu_get (10);
+	const u64 a1 = cpu_get (11);
+	const u64 a2 = cpu_get (12);
+	const u64 a3 = cpu_get (13);
+	const u64 a4 = cpu_get (14);
+	const u64 a5 = cpu_get (15);
+	const u64 a7 = cpu_get (17);
+	u64 ret;
+	switch (a7) {
+	case SYS_getcwd:
+		ret = enosys ("getcwd");
+		break;
+	case SYS_dup:
+		ret = map (dup ((int)a0));
+		break;
+	case SYS_dup3:
+		ret = map (dup3 ((int)a0, (int)a1, (int)a2));
+		break;
+	case SYS_fcntl:
+		ret = enosys ("fcntl");
+		break;
+	case SYS_ioctl:
+		ret = enosys ("ioctl");
+		break;
+	case SYS_flock:
+		ret = map (flock ((int)a0, (int)a1));
+		break;
+	case SYS_mknodat:
+		ret = map (mknodat ((int)a0, str (a1), (mode_t)a2, (dev_t)a3));
+
+	case SYS_mkdirat:
+		ret = map (mkdirat ((int)a0, str (a1), (mode_t)a2));
+		break;
+	case SYS_unlinkat:
+		ret = map (unlinkat ((int)a0, str (a1), (int)a2));
+		break;
+	case SYS_symlinkat:
+		ret = map (symlinkat (str (a0), (int)a1, str (a2)));
+		break;
+	case SYS_linkat:
+		ret = map (linkat ((int)a0, str (a1), (int)a2, str (a3), (int)a4));
+		break;
+	case SYS_renameat:
+		ret = map (renameat ((int)a0, str (a1), (int)a2, str (a3)));
+		break;
+	case SYS_umount:
+		ret = enosys ("umount");
+		break;
+	case SYS_mount:
+		ret = enosys ("mount");
+		break;
+	case SYS_pivot_root:
+		ret = enosys ("pivot_root");
+		break;
+	case SYS_nfsservctl:
+		ret = enosys ("nfsservctl");
+		break;
+	case SYS_statfs:
+		ret = enosys ("statfs");
+		break;
+	case SYS_fstatfs:
+		ret = enosys ("fstatfs");
+		break;
+	case SYS_truncate:
+		ret = map (truncate (str (a0), (off_t)a1));
+		break;
+		break;
+	case SYS_ftruncate:
+		ret = map (ftruncate ((int)a0, (off_t)a1));
+		break;
+	case SYS_fallocate:
+		ret = enosys ("fallocate");
+		break;
+	case SYS_faccessat:
+		ret = map (faccessat ((int)a0, str (a1), (int)a2, (int)a3));
+		break;
+	case SYS_chdir:
+		ret = map (chdir (str (a0)));
+		break;
+	case SYS_fchdir:
+		ret = map (fchdir ((int)a0));
+		break;
+	case SYS_chroot:
+		ret = map (chroot (str (a0)));
+		break;
+	case SYS_fchmod:
+		ret = map (fchmod ((int)a0, (mode_t)a1));
+		break;
+	case SYS_fchmodat:
+		ret = map (fchmodat ((int)a0, str (a1), (mode_t)a2, (int)a3));
+		break;
+	case SYS_fchownat:
+		ret = map (fchownat ((int)a0, str (a1), (uid_t)a2, (gid_t)a3, (int)a4));
+		break;
+	case SYS_fchown:
+		ret = map (fchown ((int)a0, (uid_t)a1, (gid_t)a2));
+		break;
+	case SYS_openat:
+		ret = map (openat ((int)a0, str (a1), (int)a2, (int)a3));
+		break;
+	case SYS_close:
+		ret = map (close ((int)a0));
+		break;
+	case SYS_vhangup:
+		ret = enosys ("vhangup");
+		break;
+	case SYS_pipe2:
+		ret = map (pipe2 (ptr (int, a0), (int)a1));
+		break;
+	case SYS_quotactl:
+		ret = enosys ("quotactl");
+		break;
+	case SYS_getdents64:
+		ret = enosys ("getdents64");
+		break;
+	case SYS_lseek:
+		ret = map (lseek ((int)a0, (off_t)a1, (int)a2));
+		break;
+	case SYS_read:
+		ret = map (read ((int)a0, ptr (void, a1), (size_t)a2));
+		break;
+	case SYS_write:
+		ret = map (write ((int)a0, ptr (const void, a1), (size_t)a2));
+		break;
+	case SYS_readv:
+		ret = map (readv ((int)a0, ptr (const struct iovec, a1), (int)a2));
+		break;
+	case SYS_writev:
+		ret = map (writev ((int)a0, ptr (const struct iovec, a1), (int)a2));
+		break;
+	case SYS_pread:
+		ret = map (pread ((int)a0, ptr (void, a1), (size_t)a2, (off_t)a3));
+		break;
+	case SYS_pwrite:
+		ret = map (pwrite ((int)a0, ptr (const void, a1), (size_t)a2, (off_t)a3));
+		break;
+	case SYS_preadv:
+		ret = enosys ("preadv");
+		break;
+	case SYS_pwritev:
+		ret = enosys ("pwritev");
+		break;
+	case SYS_sendfile:
+		ret = enosys ("sendfile");
+		break;
+	case SYS_pselect6:
+		ret = enosys ("pselect6");
+		break;
+	case SYS_ppoll:
+		ret = enosys ("ppoll");
+		break;
+	case SYS_signalfd4:
+		ret = enosys ("signalfd4");
+		break;
+	case SYS_vmsplice:
+		ret = enosys ("vmsplice");
+		break;
+	case SYS_splice:
+		ret = enosys ("splice");
+		break;
+	case SYS_tee:
+		ret = enosys ("tee");
+		break;
+	case SYS_readlinkat:
+		ret = map (readlinkat ((int)a0, str (a1), ptr (char, a2), (size_t)a3));
+		break;
+	case SYS_fstatat:
+		ret = map (fstatat ((int)a0, str (a1), &st, (int)a3));
+		stat_to_linux_stat (&lst, &st);
+		memcpy (ptr (void, a2), &lst, sizeof (lst));
+		break;
+	case SYS_fstat:
+		ret = map (fstat ((int)a0, &st));
+		stat_to_linux_stat (&lst, &st);
+		memcpy (ptr (void, a1), &lst, sizeof (lst));
+		break;
+	case SYS_sync:
+		sync ();
+		ret = 0;
+		break;
+	case SYS_fsync:
+		ret = map (fsync ((int)a0));
+		break;
+	case SYS_fdatasync:
+		ret = map (fdatasync ((int)a0));
+		break;
+	case SYS_sync_file_range:
+		ret = enosys ("sync_file_range");
+		break;
+	case SYS_timerfd_create:
+		ret = enosys ("timerfd_create");
+		break;
+	case SYS_timerfd_settime:
+		ret = enosys ("timerfd_settime");
+		break;
+	case SYS_timerfd_gettime:
+		ret = enosys ("timerfd_gettime");
+		break;
+	case SYS_utimensat:
+		ret = enosys ("utimensat");
+		break;
+	case SYS_acct:
+		ret = acct (str (a0));
+		break;
+	case SYS_capget:
+		ret = enosys ("capget");
+		break;
+	case SYS_capset:
+		ret = enosys ("capset");
+		break;
+	case SYS_personality:
+		ret = enosys ("personality");
+		break;
+	case SYS_exit:
+		exit (a0);
+		ret = -1;
+		break;
+	case SYS_exit_group:
+		ret = enosys ("exit_group");
+		break;
+	case SYS_waitid:
+		ret = enosys ("waitid");
+		break;
+	case SYS_set_tid_address:
+		warnx ("set_tid_address(): not implemented");
+		ret = getpid ();
+		break;
+	case SYS_unshare:
+		ret = enosys ("unshare");
+		break;
+	case SYS_futex:
+		ret = enosys ("futex");
+		break;
+	case SYS_set_robust_limit:
+		ret = enosys ("set_robust_limit");
+		break;
+	case SYS_get_robust_limit:
+		ret = enosys ("get_robust_limit");
+		break;
+	case SYS_nanosleep:
+		ret = enosys ("nanosleep");
+		break;
+	case SYS_gettimer:
+		ret = enosys ("gettimer");
+		break;
+	case SYS_settimer:
+		ret = enosys ("settimer");
+		break;
+	case SYS_kexec_load:
+		ret = enosys ("kexec_load");
+		break;
+	case SYS_kexec_init_module:
+		ret = enosys ("kexec_init_module");
+		break;
+	case SYS_kexec_delete_module:
+		ret = enosys ("kexec_delete_module");
+		break;
+	case SYS_timer_create:
+		ret = enosys ("timer_create");
+		break;
+	case SYS_timer_gettime:
+		ret = enosys ("timer_gettime");
+		break;
+	case SYS_timer_getoverrun:
+		ret = enosys ("timer_getoverrun");
+		break;
+	case SYS_timer_settime:
+		ret = enosys ("timer_settime");
+		break;
+	case SYS_timer_delete:
+		ret = enosys ("timer_delete");
+		break;
+	case SYS_clock_settime:
+		ret = enosys ("clock_settime");
+		break;
+	case SYS_clock_gettime:
+		ret = enosys ("clock_gettime");
+		break;
+	case SYS_clock_getres:
+		ret = enosys ("clock_getres");
+		break;
+	case SYS_clock_nanosleep:
+		ret = enosys ("clock_nanosleep");
+		break;
+	case SYS_syslog:
+		ret = enosys ("syslog");
+		break;
+	case SYS_ptrace:
+		ret = enosys ("ptrace");
+		break;
+	case SYS_sched_setparam:
+		ret = enosys ("sched_setparam");
+		break;
+	case SYS_sched_setscheduler:
+		ret = enosys ("sched_setscheduler");
+		break;
+	case SYS_sched_getscheduler:
+		ret = enosys ("sched_getscheduler");
+		break;
+	case SYS_sched_getparam:
+		ret = enosys ("sched_getparam");
+		break;
+	case SYS_sched_setaffinity:
+		ret = enosys ("sched_setaffinity");
+		break;
+	case SYS_sched_getaffinity:
+		ret = enosys ("sched_getaffinity");
+		break;
+	case SYS_sched_yield:
+		ret = map (sched_yield ());
+		break;
+	case SYS_sched_get_priority_max:
+		ret = map (sched_get_priority_max ((int)a0));
+		break;
+	case SYS_sched_get_priority_min:
+		ret = map (sched_get_priority_min ((int)a0));
+		break;
+	case SYS_sched_rr_get_interval:
+		ret = enosys ("sched_rr_get_interval");
+		break;
+	case SYS_restart_syscall:
+		ret = enosys ("restart_syscall");
+		break;
+	case SYS_kill:
+		ret = map (kill ((pid_t)a0, (int)a1));
+		break;
+	case SYS_tkill:
+		ret = enosys ("tkill");
+		break;
+	case SYS_tgkill:
+		ret = enosys ("tgkill");
+		break;
+	case SYS_signalstack:
+		ret = enosys ("signalstack");
+		break;
+	case SYS_sigsuspend:
+		ret = enosys ("sigsuspend");
+		break;
+	case SYS_sigaction:
+		ret = enosys ("sigaction");
+		break;
+	case SYS_rt_sigprocmask:
+		ret = enosys ("rt_sigprocmask");
+		break;
+	case SYS_sigpending:
+		ret = enosys ("sigpending");
+		break;
+	case SYS_sigtimedwait:
+		ret = enosys ("sigtimedwait");
+		break;
+	case SYS_sigqueueinfo:
+		ret = enosys ("sigqueueinfo");
+		break;
+	case SYS_sigreturn:
+		ret = enosys ("sigreturn");
+		break;
+	case SYS_setpriority:
+		ret = map (setpriority ((int)a0, (id_t)a1, (int)a2));
+		break;
+	case SYS_getpriority:
+		ret = map (getpriority ((int)a0, (id_t)a1));
+		break;
+	case SYS_reboot:
+		ret = enosys ("reboot");
+		break;
+	case SYS_setregid:
+		ret = map (setregid ((gid_t)a0, (gid_t)a1));
+		break;
+	case SYS_setgid:
+		ret = map (setgid ((gid_t)a0));
+		break;
+	case SYS_setreuid:
+		ret = map (setreuid ((uid_t)a0, (uid_t)a1));
+		break;
+	case SYS_setuid:
+		ret = map (setuid ((uid_t)a0));
+		break;
+	case SYS_setresuid:
+		ret = map (setresuid ((uid_t)a0, (uid_t)a1, (uid_t)a2));
+		break;
+	case SYS_getresuid:
+		ret = map (getresuid (ptr (uid_t, a0), ptr (uid_t, a1), ptr (uid_t, a2)));
+		break;
+	case SYS_setresgid:
+		ret = map (setresgid ((gid_t)a0, (gid_t)a1, (gid_t)a2));
+		break;
+	case SYS_getresgid:
+		ret = map (getresgid (ptr (gid_t, a0), ptr (gid_t, a1), ptr (gid_t, a2)));
+		break;
+	case SYS_setfsuid:
+		ret = enosys ("setfsuid");
+		break;
+	case SYS_setfsgid:
+		ret = enosys ("setfsgid");
+		break;
+	case SYS_times:
+		ret = enosys ("times");
+		break;
+	case SYS_setpgid:
+		ret = map (setpgid ((pid_t)a0, (pid_t)a1));
+		break;
+	case SYS_getpgid:
+		ret = map (getpgid ((pid_t)a0));
+		break;
+	case SYS_getsid:
+		ret = map (getsid ((pid_t)a0));
+		break;
+	case SYS_setsid:
+		ret = map (setsid ());
+		break;
+	case SYS_setgroups:
+		ret = enosys ("setgroups");
+		break;
+	case SYS_uname:
+		ret = map (uname (&un));
+		utsname_to_linux_utsname (&lun, &un);
+		memcpy (ptr (void, a0), &lun, sizeof (lun));
+		break;
+	case SYS_sethostname:
+		ret = enosys ("sethostname");
+		break;
+	case SYS_setdomainname:
+		ret = enosys ("setdomainname");
+		break;
+	case SYS_getrlimit:
+		ret = enosys ("getrlimit");
+		break;
+	case SYS_setrlimit:
+		ret = enosys ("setrlimit");
+		break;
+	case SYS_getrusage:
+		ret = enosys ("getrusage");
+		break;
+	case SYS_umask:
+		ret = map (umask ((mode_t)a0));
+		break;
+	case SYS_prctl:
+		ret = enosys ("prctl");
+		break;
+	case SYS_getcpu:
+		ret = enosys ("getcpu");
+		break;
+	case SYS_gettimeofday:
+		ret = enosys ("gettimeofday");
+		break;
+	case SYS_settimeofday:
+		ret = enosys ("settimeofday");
+		break;
+	case SYS_adjtimex:
+		ret = enosys ("adjtimex");
+		break;
+	case SYS_getpid:
+		ret = map (getpid ());
+		break;
+	case SYS_getuid:
+		ret = map (getuid ());
+		break;
+	case SYS_geteuid:
+		ret = map (geteuid ());
+		break;
+	case SYS_getgid:
+		ret = map (getgid ());
+		break;
+	case SYS_getegid:
+		ret = map (getegid ());
+		break;
+	case SYS_gettid:
+		ret = enosys ("gettid");
+		break;
+	case SYS_sysinfo:
+		ret = enosys ("sysinfo");
+		break;
+	case 180:
+	case 181:
+	case 182:
+	case 183:
+	case 184:
+	case 185:
+		ret = enosys ("mq_*");
+		break;
+	case SYS_msgget:
+		ret = map(msgget ((key_t)a0, (int)a1));
+		break;
+	case SYS_msgctl:
+		ret = enosys ("msgctl");
+		break;
+	case SYS_msgrcv:
+		ret = map (msgrcv ((int)a0, ptr (void, a1), (size_t)a2, (long)a3, (int)a4));
+		break;
+	case SYS_msgsnd:
+		ret = map (msgsnd ((int)a0, ptr (const void, a1), (size_t)a2, (int)a3));
+		break;
+	case SYS_semget:
+		ret = map (semget ((key_t)a0, (int)a1, (int)a2));
+		break;
+	case SYS_semctl:
+		ret = enosys ("semctl");
+		break;
+	case SYS_semtimedop:
+		ret = enosys ("semtimedop");
+		break;
+	case SYS_semop:
+		ret = enosys ("semop");
+		break;
+	case 194:
+	case 195:
+	case 196:
+	case 197:
+		ret = enosys ("shm*");
+		break;
+	case 198:
+	case 199:
+	case 200:
+	case 201:
+	case 202:
+	case 203:
+	case 204:
+	case 205:
+	case 206:
+	case 207:
+	case 208:
+	case 209:
+	case 210:
+	case 211:
+	case 212:
+		ret = enosys ("socket api");
+		break;
+	case SYS_readahead:
+		ret = enosys ("readahead");
+		break;
+	case SYS_brk:
+		ret = map (my_brk (a0));
+		break;
+	case SYS_munmap:
+		ret = map (munmap (ptr (void, a0), (size_t)a1));
+		break;
+	case SYS_mremap:
+		ret = enosys ("mremap");
+		break;
+	case SYS_add_key:
+		ret = enosys ("add_key");
+		break;
+	case SYS_request_key:
+		ret = enosys ("request_key");
+		break;
+	case SYS_keyctl:
+		ret = enosys ("keyctl");
+		break;
+	case SYS_clone:
+		if (a0 == 17 && a1 == 0) {
+			// fork
+			ret = map (fork ());
+		} else {
+			ret = enosys ("clone");
+		}
+		break;
+	case SYS_execve:
+		ret = map (my_execve (str (a0), ptr (char *, a1), ptr (char *, a2)));
+		break;
+	case SYS_mmap:
+		//eprintf ("mmap (%p, %zu, %d, %d, %d, %lld);\n", ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5);
+		ptr = mmap (ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5);
+		if (ptr == NULL) {
+			ret = -map_errno (errno);
+		} else {
+			ret = (u64)ptr;
+		}
+		break;
+	case SYS_fadvise64:
+		ret = enosys ("fadvise64");
+		break;
+	case SYS_swapon:
+		ret = enosys ("swapon");
+		break;
+	case SYS_swapoff:
+		ret = enosys ("swapoff");
+		break;
+	case SYS_mprotect:
+		ret = map (mprotect (ptr (void, a0), (size_t)a1, (int)a2));
+		break;
+	case SYS_msync:
+		ret = map (msync (ptr (void, a0), (size_t)a1, (int)a2));
+		break;
+	case SYS_mlock:
+		ret = map (mlock (ptr (void, a0), (size_t)a1));
+		break;
+	case SYS_munlock:
+		ret = map (munlock (ptr (void, a0), (size_t)a1));
+		break;
+	case SYS_mlockall:
+		ret = map (mlockall ((int)a0));
+		break;
+	case SYS_munlockall:
+		ret = map (munlockall ());
+		break;
+	case SYS_mincore:
+		ret = enosys ("mincore");
+		break;
+	case SYS_madvise:
+		ret = map (madvise (ptr (void, a0), (size_t)a1, (int)a2));
+		break;
+	case SYS_remap_file_pages:
+		ret = enosys ("remap_file_pages");
+		break;
+	case SYS_mbind:
+		ret = enosys ("mbind");
+		break;
+	case SYS_get_mempolicy:
+		ret = enosys ("get_mempolicy");
+		break;
+	case SYS_set_mempolicy:
+		ret = enosys ("set_mempolicy");
+		break;
+	case SYS_migrate_pages:
+		ret = enosys ("migrate_pages");
+		break;
+	case SYS_move_pages:
+		ret = enosys ("move_pages");
+		break;
+	case SYS_rt_tgsigqueueinfo:
+		ret = enosys ("rt_tgsigqueueinfo");
+		break;
+	case SYS_perf_event_open:
+		ret = enosys ("perf_event_open");
+		break;
+	case SYS_accept4:
+		ret = enosys ("accept4");
+		break;
+	case SYS_recvmsg:
+		ret = enosys ("recvmsg");
+		break;
+	case 244:
+	case 245:
+	case 246:
+	case 247:
+	case 248:
+	case 249:
+	case 250:
+	case 251:
+	case 252:
+	case 253:
+	case 254:
+	case 255:
+	case 256:
+	case 257:
+	case 258:
+	case 259:
+		ret = enosys ("arch-specific");
+		break;
+	case 260:
+		ret = enosys ("wait4");
+		break;
+	case SYS_prlimit64:
+		ret = enosys ("prlimit64");
+		break;
+	case SYS_fanotify_init:
+		ret = enosys ("fanotify_init");
+		break;
+	case SYS_fanotify_mark:
+		ret = enosys ("fanotify_mark");
+		break;
+	case SYS_name_to_handle_at:
+		ret = enosys ("name_to_handle_at");
+		break;
+	case SYS_open_by_handle_at:
+		ret = enosys ("open_by_handle_at");
+		break;
+	case SYS_clock_adjtime:
+		ret = enosys ("clock_adjtime");
+		break;
+	case SYS_syncfs:
+		ret = enosys ("syncfs");
+		break;
+	case SYS_setns:
+		ret = enosys ("setns");
+		break;
+	case SYS_sendmsg:
+		ret = enosys ("sendmsg");
+		break;
+	case SYS_process_vm_readv:
+		ret = enosys ("process_vm_readv");
+		break;
+	case SYS_process_vm_writev:
+		ret = enosys ("process_vm_writev");
+		break;
+	case SYS_kcmp:
+		ret = enosys ("kcmp");
+		break;
+	case SYS_finit_module:
+		ret = enosys ("finit_module");
+		break;
+	case SYS_sched_setattr:
+		ret = enosys ("sched_setattr");
+		break;
+	case SYS_sched_getattr:
+		ret = enosys ("sched_getattr");
+		break;
+	case SYS_renameat2:
+		ret = enosys ("renameat2");
+		break;
+	case SYS_seccomp:
+		ret = enosys ("seccomp");
+		break;
+	case SYS_getrandom:
+		ret = enosys ("getrandom");
+		break;
+	case SYS_memfd_create:
+		ret = enosys ("seccomp");
+		break;
+	case SYS_bpf:
+		ret = enosys ("bpf");
+		break;
+	case SYS_execveat:
+		ret = enosys ("execveat");
+		break;
+	case SYS_userfaultfd:
+		ret = enosys ("usefaultfd");
+		break;
+	case SYS_membarrier:
+		ret = enosys ("membarrier");
+		break;
+	case SYS_mlock2:
+		ret = enosys ("mlock2");
+		break;
+	case SYS_copy_file_range:
+		ret = enosys ("copy_file_range");
+		break;
+	case SYS_preadv2:
+		ret = enosys ("preadv2");
+		break;
+	case SYS_pwritev2:
+		ret = enosys ("pwritev2");
+		break;
+	case SYS_pkey_mprotect:
+		ret = enosys ("pkey_mprotect");
+		break;
+	case SYS_pkey_alloc:
+		ret = enosys ("pkey_alloc");
+		break;
+	case SYS_pkey_free:
+		ret = enosys ("pkey_free");
+		break;
+	case SYS_statx:
+		ret = enosys ("statx");
+		break;
+	case SYS_io_pgetevents:
+		ret = enosys ("io_pgetevents");
+		break;
+	case SYS_rseq:
+		ret = enosys ("rseq");
+		break;
+	case SYS_kexec_file_load:
+		ret = enosys ("kexec_file_load");
+		break;
+	case SYS_open:
+		ret = map (open ((const char *)(size_t)a0, (int)a1, (int)a2));
+		break;
+	case SYS_link:
+		ret = map (link (str (a0), str (a1)));
+		break;
+	case SYS_unlink:
+		ret = map (unlink (str (a0)));
+		break;
+	case SYS_mkdir:
+		ret = map (mkdir (str (a0), (mode_t)a1));
+		break;
+	case SYS_access:
+		ret = map (access (str (a0), (int)a1));
+		break;
+	case SYS_stat:
+		ret = map (stat (str (a0), &st));
+		stat_to_linux_stat (&lst, &st);
+		memcpy (ptr (void, a1), &lst, sizeof (lst));
+		break;
+	case SYS_lstat:
+		ret = map (lstat (str (a0), &st));
+		stat_to_linux_stat (&lst, &st);
+		memcpy (ptr (void, a1), &lst, sizeof (lst));
+		break;
+	case SYS_time:
+		ret = enosys ("time");
+		break;
+	case SYS_getmainvars:
+		ret = enosys ("getmainvars");
+		break;
+	case SYS_debug:
+		fprintf (stderr, "DEBUG: %llu\n", a0);
+		ret = 0;
+		break;
+	default:
+		warnx ("%08llx: unimplemented syscall %llu", pc - 4, a7);
+		ret = -map_errno (ENOSYS);
+		break;
+	}
+	cpu_set (REG_a0, ret);
+}
+
blob - /dev/null
blob + 66eb875ea57dc87a40bf8b6cb2d3386f35feeb06 (mode 644)
--- /dev/null
+++ src/exec.c
@@ -0,0 +1,63 @@
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include "rvemu.h"
+
+
+int is_executable (const Elf64_Ehdr *ehdr)
+{
+	return IS_ELF (*ehdr)
+		&& ehdr->e_ident[EI_CLASS] == ELFCLASS64
+		&& ehdr->e_ident[EI_DATA] == ELFDATA2LSB
+		&& ehdr->e_machine == EM_RISCV
+		;
+}
+
+int my_execve (const char *path, char **argv, char **envp)
+{
+
+	Elf64_Ehdr ehdr;
+	char buffer[256], *nl, *s, **args, **env;
+	int fd;
+
+	fd = open (path, O_RDONLY);
+	if (fd < 0)
+		return -1;
+	
+	memset (buffer, 0, sizeof (buffer));
+	read (fd, buffer, 2);
+
+	if (buffer[0] == '#' && buffer[1] == '!') {
+		read (fd, buffer, sizeof (buffer));
+		close (fd);
+
+		nl = memchr (buffer, '\n', sizeof (buffer));
+		if (nl == NULL) {
+			errno = EINVAL;
+			return -1;
+		}
+
+		*nl = '\0';
+
+		s = buffer;
+		while (isspace (*s))
+			++s;
+
+		return my_execve (s, argv, envp);
+	}
+
+	memset (&ehdr, 0, sizeof (ehdr));
+	lseek (fd, 0, SEEK_SET);
+	read (fd, &ehdr, sizeof (ehdr));
+	close (fd);
+
+	if (is_executable (&ehdr)) {
+		return execvpe ("rvemu", argv, envp);
+	}
+
+	return execve (path, argv, envp);
+}
+
blob - /dev/null
blob + a0d8b14d8d05941c2315f86aa3a6da4ba0551ba4 (mode 644)
--- /dev/null
+++ src/rvemu.c
@@ -0,0 +1,193 @@
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "rvemu.h"
+
+u64 brkval = 0;
+
+static void load_segment (int fd, Elf64_Phdr phdr)
+{
+	size_t end, len, ps;
+	int prot = 0;
+	void *addr, *ptr;
+
+
+	if (phdr.p_filesz > phdr.p_memsz)
+		errx (1, "invalid program header: p_filesz > p_memsz");
+
+	ps = getpagesize ();
+	addr = (void *)(phdr.p_vaddr & ~(ps - 1));
+	len = phdr.p_memsz + phdr.p_vaddr - (size_t)addr;
+
+	ptr = mmap (
+		addr,
+		len,
+		PROT_READ | PROT_WRITE,
+		MAP_PRIVATE | MAP_ANON,
+		-1,
+		0
+	);
+	eprintf ("mmap (%p, %#zx) = %p;\n", addr, len, ptr);
+
+	if (ptr == NULL)
+		err (1, "mmap()");
+
+	if (phdr.p_filesz > 0) {
+		lseek (fd, phdr.p_offset, SEEK_SET);
+		read (fd, (void *)phdr.p_vaddr, phdr.p_filesz);
+	}
+
+	if (phdr.p_flags & (PF_R | PF_X))
+		prot |= PROT_READ;
+	if (phdr.p_flags & PF_W)
+		prot |= PROT_WRITE;
+	if (mprotect (addr, len, prot) != 0)
+		err (1, "mprotect()");
+
+	end = phdr.p_vaddr + phdr.p_memsz;
+	if (end > brkval)
+		brkval = end;
+}
+
+static void load_image (const char *filename)
+{
+	Elf64_Ehdr ehdr;
+	int fd;
+
+	fd = open (filename, O_RDONLY);
+	if (fd < 0)
+		err (1, "open('%s')", filename);
+
+	if (read (fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
+		err (1, "read('%s')", filename);
+
+	if (!is_executable (&ehdr))
+		errx (1, "Invalid argument");
+
+	pc = ehdr.e_entry;
+
+	for (unsigned i = 0; i < ehdr.e_phnum; ++i) {
+		Elf64_Phdr phdr;
+
+		lseek (fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET);
+		if (read (fd, &phdr, ehdr.e_phentsize) != ehdr.e_phentsize)
+			err (1, "failed to read program header %u", i);
+
+		switch (phdr.p_type) {
+		case PT_NULL:
+			break;
+		case PT_LOAD:
+			load_segment (fd, phdr);
+			break;
+		case PT_INTERP:
+		case PT_DYNAMIC:
+			errx (1, "shared objects not supported");
+		default:
+			//warnx ("%u: ignoring program header: %x",
+			//	i, (unsigned)phdr.p_type);
+			break;
+		}
+	}
+	close (fd);
+}
+
+static void cpu_push (u64 val)
+{
+	cpu_set (REG_sp, cpu_get (REG_sp) - 8);
+	write_u64 (cpu_get (REG_sp), val);
+}
+
+static void setup_stack (
+	u64 stack_size,
+	int argc,
+	char **argv,
+	int envc,
+	char **envp
+) {
+	void *ptr;
+	void *stack_bottom;
+
+	// set stack pointer
+	cpu_set (REG_sp, 0x80000000);
+
+	stack_bottom = (void *)(u64)(0x80000000 - stack_size);
+	ptr = mmap (
+		stack_bottom,
+		stack_size,
+		PROT_READ | PROT_WRITE,
+		MAP_PRIVATE | MAP_ANON | MAP_STACK,
+		-1,
+		0
+	);
+
+	if (ptr != stack_bottom)
+		err (1, "failed to map stack");
+
+	// auxv
+	cpu_push (0);
+	cpu_push (0);
+	cpu_push (getegid ());
+	cpu_push (14);
+	cpu_push (getgid ());
+	cpu_push (13);
+	cpu_push (geteuid ());
+	cpu_push (12);
+	cpu_push (getuid ());
+	cpu_push (11);
+	cpu_push (getpagesize ());
+	cpu_push (6);
+
+	cpu_push (0);
+	for (int i = envc - 1; i >= 0; --i)
+		cpu_push ((u64)envp[i]);
+	cpu_push (0);
+	for (int i = argc - 1; i >= 0; --i)
+		cpu_push ((u64)argv[i]);
+	cpu_push (argc);
+}
+
+int main (int argc, char *argv[], char *envp[])
+{
+	const char *filename;
+	struct rlimit rl;
+	size_t stack_size;
+	int fd, envc;
+	char *base;
+	void *ptr;
+
+	base = basename (argv[0]);
+
+	if (strcmp (base, "rvemu") == 0) {
+		if (argc < 2)
+			errx (1, "usage: rvemu file");
+
+		filename = argv[1];
+	} else {
+		filename = argv[0];
+	}
+
+	load_image (filename);
+
+	if (getrlimit (RLIMIT_STACK, &rl) == 0) {
+		stack_size = rl.rlim_cur;
+	} else {
+		stack_size = 1 << 20;
+	}
+
+	for (envc = 0; envp[envc] != NULL; ++envc);
+
+	setup_stack (stack_size, argc, argv, envc, envp);
+
+	while (1) {
+		const u32 instr = cpu_fetch ();
+		cpu_exec (instr);
+	}
+
+	return 0;
+}
blob - /dev/null
blob + f1fa870f78600a53528abcc226d280124e392286 (mode 644)
--- /dev/null
+++ src/rvemu.h
@@ -0,0 +1,85 @@
+#include <stddef.h>
+#include <stdint.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <err.h>
+
+#define DEBUG 0
+
+#if DEBUG
+# define eprintf(...) fprintf (stderr, __VA_ARGS__)
+#else
+# define eprintf(...)
+#endif
+
+enum {
+	REG_zero,
+	REG_ra,
+	REG_sp,
+	REG_gp,
+	REG_tp,
+	REG_t0,
+	REG_t1,
+	REG_t2,
+	REG_s0,
+	REG_s1,
+	REG_a0,
+	REG_a1,
+	REG_a2,
+	REG_a3,
+	REG_a4,
+	REG_a5,
+	REG_a6,
+	REG_a7,
+	REG_s2,
+	REG_s3,
+	REG_s4,
+	REG_s5,
+	REG_s6,
+	REG_s7,
+	REG_s8,
+	REG_s9,
+	REG_s10,
+	REG_s11,
+	REG_t3,
+	REG_t4,
+	REG_t5,
+	REG_t6,
+};
+
+typedef uint8_t  u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+typedef int8_t   i8;
+typedef int16_t  i16;
+typedef int32_t  i32;
+typedef int64_t  i64;
+
+typedef unsigned int uint;
+
+extern u64 pc;
+extern u64 brkval;
+extern const char *interpreter;
+
+u32 cpu_fetch (void);
+u64 cpu_get (size_t reg);
+void cpu_set (size_t reg, u64 val);
+void cpu_exec (u32 instr);
+void ecall (void);
+int my_execve (const char *path, char **argv, char **envp);
+int is_executable (const Elf64_Ehdr *);
+
+#define read_u8(ptr)		(*(const u8 *)(size_t)(ptr))
+#define read_u16(ptr)		(*(const u16 *)(size_t)(ptr))
+#define read_u32(ptr)		(*(const u32 *)(size_t)(ptr))
+#define read_u64(ptr)		(*(const u64 *)(size_t)(ptr))
+#define read_i8(ptr)		(*(const i8 *)(size_t)(ptr))
+#define read_i16(ptr)		(*(const i16 *)(size_t)(ptr))
+#define read_i32(ptr)		(*(const i32 *)(size_t)(ptr))
+#define read_i64(ptr)		(*(const i64 *)(size_t)(ptr))
+#define write_u8(ptr, val)	(*(u8 *)(size_t)(ptr) = (val))
+#define write_u16(ptr, val)	(*(u16 *)(size_t)(ptr) = (val))
+#define write_u32(ptr, val)	(*(u32 *)(size_t)(ptr) = (val))
+#define write_u64(ptr, val)	(*(u64 *)(size_t)(ptr) = (val))
blob - /dev/null
blob + f107b56f5fe7a8f694784c2a8903a7c54f1e5c14 (mode 644)
--- /dev/null
+++ src/syscalls.inc
@@ -0,0 +1,234 @@
+.set SYS_getcwd, 17
+.set SYS_dup, 23
+.set SYS_dup3, 24
+.set SYS_fcntl, 25
+.set SYS_ioctl, 29
+.set SYS_flock, 32
+.set SYS_mknodat, 33
+.set SYS_mkdirat, 34
+.set SYS_unlinkat, 35
+.set SYS_symlinkat, 36
+.set SYS_linkat, 37
+.set SYS_renameat, 38
+.set SYS_umount, 39
+.set SYS_mount, 40
+.set SYS_pivot_root, 41
+.set SYS_nfsservctl, 42
+.set SYS_statfs, 43
+.set SYS_fstatfs, 44
+.set SYS_truncate, 45
+.set SYS_ftruncate, 46
+.set SYS_fallocate, 47
+.set SYS_faccessat, 48
+.set SYS_chdir, 49
+.set SYS_fchdir, 50
+.set SYS_chroot, 51
+.set SYS_fchmod, 52
+.set SYS_fchmodat, 53
+.set SYS_fchownat, 54
+.set SYS_fchown, 55
+.set SYS_openat, 56
+.set SYS_close, 57
+.set SYS_vhangup, 58
+.set SYS_pipe2, 59
+.set SYS_quotactl, 60
+.set SYS_getdents64, 61
+.set SYS_lseek, 62
+.set SYS_read, 63
+.set SYS_write, 64
+.set SYS_readv, 65
+.set SYS_writev, 66
+.set SYS_pread, 67
+.set SYS_pwrite, 68
+.set SYS_preadv, 69
+.set SYS_pwritev, 70
+.set SYS_sendfile, 71
+.set SYS_pselect6, 72
+.set SYS_ppoll, 73
+.set SYS_signalfd4, 74
+.set SYS_vmsplice, 75
+.set SYS_splice, 76
+.set SYS_tee, 77
+.set SYS_readlinkat, 78
+.set SYS_fstatat, 79
+.set SYS_fstat, 80
+.set SYS_sync, 81
+.set SYS_fsync, 82
+.set SYS_fdatasync, 83
+.set SYS_sync_file_range, 84
+.set SYS_timerfd_create, 85
+.set SYS_timerfd_settime, 86
+.set SYS_timerfd_gettime, 87
+.set SYS_utimensat, 88
+.set SYS_acct, 89
+.set SYS_capget, 90
+.set SYS_capset, 91
+.set SYS_personality, 92
+.set SYS_exit, 93
+.set SYS_exit_group, 94
+.set SYS_waitid, 95
+.set SYS_set_tid_address, 96
+.set SYS_unshare, 97
+.set SYS_futex, 98
+.set SYS_set_robust_limit, 99
+.set SYS_get_robust_limit, 100
+.set SYS_nanosleep, 101
+.set SYS_gettimer, 102
+.set SYS_settimer, 103
+.set SYS_kexec_load, 104
+.set SYS_kexec_init_module, 105
+.set SYS_kexec_delete_module, 106
+.set SYS_timer_create, 107
+.set SYS_timer_gettime, 108
+.set SYS_timer_getoverrun, 109
+.set SYS_timer_settime, 110
+.set SYS_timer_delete, 111
+.set SYS_clock_settime, 112
+.set SYS_clock_gettime, 113
+.set SYS_clock_getres, 114
+.set SYS_clock_nanosleep, 115
+.set SYS_syslog, 116
+.set SYS_ptrace, 117
+.set SYS_sched_setparam, 118
+.set SYS_sched_setscheduler, 119
+.set SYS_sched_getscheduler, 120
+.set SYS_sched_getparam, 121
+.set SYS_sched_setaffinity, 122
+.set SYS_sched_getaffinity, 123
+.set SYS_sched_yield, 124
+.set SYS_sched_get_priority_max, 125
+.set SYS_sched_get_priority_min, 126
+.set SYS_sched_rr_get_interval, 127
+.set SYS_restart_syscall, 128
+.set SYS_kill, 129
+.set SYS_tkill, 130
+.set SYS_tgkill, 131
+.set SYS_signalstack, 132
+.set SYS_sigsuspend, 133
+.set SYS_sigaction, 134
+.set SYS_rt_sigprocmask, 135
+.set SYS_sigpending, 136
+.set SYS_sigtimedwait, 137
+.set SYS_sigqueueinfo, 138
+.set SYS_sigreturn, 139
+.set SYS_setpriority, 140
+.set SYS_getpriority, 141
+.set SYS_reboot, 142
+.set SYS_setregid, 143
+.set SYS_setgid, 144
+.set SYS_setreuid, 145
+.set SYS_setuid, 146
+.set SYS_setresuid, 147
+.set SYS_getresuid, 148
+.set SYS_setresgid, 149
+.set SYS_getresgid, 150
+.set SYS_setfsuid, 151
+.set SYS_setfsgid, 152
+.set SYS_times, 153
+.set SYS_setpgid, 154
+.set SYS_getpgid, 155
+.set SYS_getsid, 156
+.set SYS_setsid, 158
+.set SYS_setgroups, 159
+.set SYS_uname, 160
+.set SYS_sethostname, 161
+.set SYS_setdomainname, 162
+.set SYS_getrlimit, 163
+.set SYS_setrlimit, 164
+.set SYS_getrusage, 165
+.set SYS_umask, 166
+.set SYS_prctl, 167
+.set SYS_getcpu, 168
+.set SYS_gettimeofday, 169
+.set SYS_settimeofday, 170
+.set SYS_adjtimex, 171
+.set SYS_getpid, 172
+.set SYS_getuid, 174
+.set SYS_geteuid, 175
+.set SYS_getgid, 176
+.set SYS_getegid, 177
+.set SYS_gettid, 178
+.set SYS_sysinfo, 179
+.set SYS_msgget, 186
+.set SYS_msgctl, 187
+.set SYS_msgrcv, 188
+.set SYS_msgsnd, 189
+.set SYS_semget, 190
+.set SYS_semctl, 191
+.set SYS_semtimedop, 192
+.set SYS_semop, 193
+.set SYS_readahead, 213
+.set SYS_brk, 214
+.set SYS_munmap, 215
+.set SYS_mremap, 216
+.set SYS_add_key, 217
+.set SYS_request_key, 218
+.set SYS_keyctl, 219
+.set SYS_clone, 220
+.set SYS_execve, 221
+.set SYS_mmap, 222
+.set SYS_fadvise64, 223
+.set SYS_swapon, 224
+.set SYS_swapoff, 225
+.set SYS_mprotect, 226
+.set SYS_msync, 227
+.set SYS_mlock, 228
+.set SYS_munlock, 229
+.set SYS_mlockall, 230
+.set SYS_munlockall, 231
+.set SYS_mincore, 232
+.set SYS_madvise, 233
+.set SYS_remap_file_pages, 234
+.set SYS_mbind, 235
+.set SYS_get_mempolicy, 236
+.set SYS_set_mempolicy, 237
+.set SYS_migrate_pages, 238
+.set SYS_move_pages, 239
+.set SYS_rt_tgsigqueueinfo, 240
+.set SYS_perf_event_open, 241
+.set SYS_accept4, 242
+.set SYS_recvmsg, 243
+.set SYS_prlimit64, 261
+.set SYS_fanotify_init, 262
+.set SYS_fanotify_mark, 263
+.set SYS_name_to_handle_at, 264
+.set SYS_open_by_handle_at, 265
+.set SYS_clock_adjtime, 266
+.set SYS_syncfs, 267
+.set SYS_setns, 268
+.set SYS_sendmsg, 269
+.set SYS_process_vm_readv, 270
+.set SYS_process_vm_writev, 271
+.set SYS_kcmp, 272
+.set SYS_finit_module, 273
+.set SYS_sched_setattr, 274
+.set SYS_sched_getattr, 275
+.set SYS_renameat2, 276
+.set SYS_seccomp, 277
+.set SYS_getrandom, 278
+.set SYS_memfd_create, 279
+.set SYS_bpf, 280
+.set SYS_execveat, 281
+.set SYS_userfaultfd, 282
+.set SYS_membarrier, 283
+.set SYS_mlock2, 284
+.set SYS_copy_file_range, 285
+.set SYS_preadv2, 286
+.set SYS_pwritev2, 287
+.set SYS_pkey_mprotect, 288
+.set SYS_pkey_alloc, 289
+.set SYS_pkey_free, 290
+.set SYS_statx, 291
+.set SYS_io_pgetevents, 292
+.set SYS_rseq, 293
+.set SYS_kexec_file_load, 294
+.set SYS_open, 1024
+.set SYS_link, 1025
+.set SYS_unlink, 1026
+.set SYS_mkdir, 1030
+.set SYS_access, 1033
+.set SYS_stat, 1038
+.set SYS_lstat, 1039
+.set SYS_time, 1062
+.set SYS_getmainvars, 2011
+.set SYS_debug, 2048
blob - 23d31d68cbaa4919d7ea80f36ba6af592227e811 (mode 644)
blob + /dev/null
--- ecall.c
+++ /dev/null
@@ -1,967 +0,0 @@
-#include <sys/resource.h>
-#include <sys/utsname.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/msg.h>
-#include <sys/sem.h>
-#include <sys/uio.h>
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <errno.h>
-#include "syscalls.h"
-#include "rvemu.h"
-
-struct linux_stat64 {
-	u64 dev;
-	u64 ino;
-	u32 mode;
-	u32 nlink;
-	u32 uid;
-	u32 gid;
-	u64 rdev;
-	u64 __pad1;
-	u64 size;
-	u32 blksize;
-	u32 __pad2;
-	u64 blocks;
-	u32 atime;
-	u32 atime_ns;
-	u32 mtime;
-	u32 mtime_ns;
-	u32 ctime;
-	u32 ctime_ns;
-	u32 __unused4;
-	u32 __unused5;
-};
-
-struct linux_utsname {
-	char sysname[65];
-	char nodename[65];
-	char release[65];
-	char version[65];
-	char machine[65];
-};
-
-static int map_errno (int err)
-{
-	const int errnos[] = {
-		[EPERM]		= 1,
-		[ENOENT]	= 2,
-		[ESRCH]		= 3,
-		[EINTR]		= 4,
-		[EIO]		= 5,
-		[ENXIO]		= 6,
-		[E2BIG]		= 7,
-		[ENOEXEC]	= 8,
-		[EBADF]		= 9,
-		[ECHILD]	= 10,
-		[EAGAIN]	= 11,
-		[ENOMEM]	= 12,
-		[EACCES]	= 13,
-		[EFAULT]	= 14,
-		[ENOTBLK]	= 15,
-		[EBUSY]		= 16,
-		[EEXIST]	= 17,
-		[EXDEV]		= 18,
-		[ENODEV]	= 19,
-		[ENOTDIR]	= 20,
-		[EISDIR]	= 21,
-		[EINVAL]	= 22,
-		[ENFILE]	= 23,
-		[EMFILE]	= 24,
-		[ENOTTY]	= 25,
-		[ETXTBSY]	= 26,
-		[EFBIG]		= 27,
-		[ENOSPC]	= 28,
-		[ESPIPE]	= 29,
-		[EROFS]		= 30,
-		[EMLINK]	= 31,
-		[EPIPE]		= 32,
-		[EDOM]		= 33,
-		[ERANGE]	= 34,
-		[EDEADLK]	= 35,
-		[ENAMETOOLONG]	= 36,
-		[ENOLCK]	= 37,
-		[ENOSYS]	= 38,
-	};
-	return errnos[err];
-}
-
-static int map (int x) {
-	return x < 0 ? -map_errno (errno) : x;
-}
-
-
-static void stat_to_linux_stat (struct linux_stat64 *lst, const struct stat *st)
-{
-	memset (lst, 0, sizeof (*lst));
-	lst->dev	= st->st_dev;
-	lst->ino	= st->st_dev;
-	lst->mode	= st->st_dev;
-	lst->nlink	= st->st_dev;
-	lst->uid	= st->st_dev;
-	lst->gid	= st->st_dev;
-	lst->rdev	= st->st_dev;
-	lst->size	= st->st_dev;
-	lst->blksize	= st->st_dev;
-	lst->blocks	= st->st_dev;
-	lst->atime	= st->st_atim.tv_sec;
-	lst->atime_ns	= st->st_atim.tv_nsec;
-	lst->mtime	= st->st_mtim.tv_sec;
-	lst->mtime_ns	= st->st_mtim.tv_nsec;
-	lst->ctime	= st->st_ctim.tv_sec;
-	lst->ctime_ns	= st->st_ctim.tv_nsec;
-}
-
-static void utsname_to_linux_utsname (struct linux_utsname *lun, const struct utsname *un)
-{
-	memset (lun, 0, sizeof (*lun));
-	strlcpy (lun->sysname,	un->sysname, 65);
-	strlcpy (lun->nodename,	un->nodename, 65);
-	strlcpy (lun->release,	un->release, 65);
-	strlcpy (lun->version,	un->version, 65);
-	strlcpy (lun->machine,	un->machine, 65);
-}
-
-static int enosys (const char *sys)
-{
-	warnx ("unimplemented syscall: %s", sys);
-	return -map_errno (ENOSYS);
-}
-
-static u64 my_brk (u64 new)
-{
-	void *ptr;
-
-	if (new < brkval)
-		return brkval;
-	if (new >= 0x78000000) {
-		errno = ENOMEM;
-		return -1;
-	}
-
-	new = (new + 4095) & ~0x3ff;
-	ptr = mmap (
-		(void *)brkval,
-		new - brkval,
-		PROT_READ | PROT_WRITE,
-		MAP_PRIVATE | MAP_ANON,
-		-1,
-		0
-	);
-	if (ptr == NULL)
-		return -1;
-	brkval = new;
-	return brkval;
-}
-
-#define ptr(T, x) ((T *)(x))
-#define str(x) ptr (const char, x)
-void ecall (void)
-{
-	struct linux_stat64 lst;
-	struct linux_utsname lun;
-	struct stat st;
-	struct utsname un;
-	void *ptr;
-	const u64 a0 = cpu_get (10);
-	const u64 a1 = cpu_get (11);
-	const u64 a2 = cpu_get (12);
-	const u64 a3 = cpu_get (13);
-	const u64 a4 = cpu_get (14);
-	const u64 a5 = cpu_get (15);
-	const u64 a7 = cpu_get (17);
-	u64 ret;
-	switch (a7) {
-	case SYS_getcwd:
-		ret = enosys ("getcwd");
-		break;
-	case SYS_dup:
-		ret = map (dup ((int)a0));
-		break;
-	case SYS_dup3:
-		ret = map (dup3 ((int)a0, (int)a1, (int)a2));
-		break;
-	case SYS_fcntl:
-		ret = enosys ("fcntl");
-		break;
-	case SYS_ioctl:
-		ret = enosys ("ioctl");
-		break;
-	case SYS_flock:
-		ret = map (flock ((int)a0, (int)a1));
-		break;
-	case SYS_mknodat:
-		ret = map (mknodat ((int)a0, str (a1), (mode_t)a2, (dev_t)a3));
-
-	case SYS_mkdirat:
-		ret = map (mkdirat ((int)a0, str (a1), (mode_t)a2));
-		break;
-	case SYS_unlinkat:
-		ret = map (unlinkat ((int)a0, str (a1), (int)a2));
-		break;
-	case SYS_symlinkat:
-		ret = map (symlinkat (str (a0), (int)a1, str (a2)));
-		break;
-	case SYS_linkat:
-		ret = map (linkat ((int)a0, str (a1), (int)a2, str (a3), (int)a4));
-		break;
-	case SYS_renameat:
-		ret = map (renameat ((int)a0, str (a1), (int)a2, str (a3)));
-		break;
-	case SYS_umount:
-		ret = enosys ("umount");
-		break;
-	case SYS_mount:
-		ret = enosys ("mount");
-		break;
-	case SYS_pivot_root:
-		ret = enosys ("pivot_root");
-		break;
-	case SYS_nfsservctl:
-		ret = enosys ("nfsservctl");
-		break;
-	case SYS_statfs:
-		ret = enosys ("statfs");
-		break;
-	case SYS_fstatfs:
-		ret = enosys ("fstatfs");
-		break;
-	case SYS_truncate:
-		ret = map (truncate (str (a0), (off_t)a1));
-		break;
-		break;
-	case SYS_ftruncate:
-		ret = map (ftruncate ((int)a0, (off_t)a1));
-		break;
-	case SYS_fallocate:
-		ret = enosys ("fallocate");
-		break;
-	case SYS_faccessat:
-		ret = map (faccessat ((int)a0, str (a1), (int)a2, (int)a3));
-		break;
-	case SYS_chdir:
-		ret = map (chdir (str (a0)));
-		break;
-	case SYS_fchdir:
-		ret = map (fchdir ((int)a0));
-		break;
-	case SYS_chroot:
-		ret = map (chroot (str (a0)));
-		break;
-	case SYS_fchmod:
-		ret = map (fchmod ((int)a0, (mode_t)a1));
-		break;
-	case SYS_fchmodat:
-		ret = map (fchmodat ((int)a0, str (a1), (mode_t)a2, (int)a3));
-		break;
-	case SYS_fchownat:
-		ret = map (fchownat ((int)a0, str (a1), (uid_t)a2, (gid_t)a3, (int)a4));
-		break;
-	case SYS_fchown:
-		ret = map (fchown ((int)a0, (uid_t)a1, (gid_t)a2));
-		break;
-	case SYS_openat:
-		ret = map (openat ((int)a0, str (a1), (int)a2, (int)a3));
-		break;
-	case SYS_close:
-		ret = map (close ((int)a0));
-		break;
-	case SYS_vhangup:
-		ret = enosys ("vhangup");
-		break;
-	case SYS_pipe2:
-		ret = map (pipe2 (ptr (int, a0), (int)a1));
-		break;
-	case SYS_quotactl:
-		ret = enosys ("quotactl");
-		break;
-	case SYS_getdents64:
-		ret = enosys ("getdents64");
-		break;
-	case SYS_lseek:
-		ret = map (lseek ((int)a0, (off_t)a1, (int)a2));
-		break;
-	case SYS_read:
-		ret = map (read ((int)a0, ptr (void, a1), (size_t)a2));
-		break;
-	case SYS_write:
-		ret = map (write ((int)a0, ptr (const void, a1), (size_t)a2));
-		break;
-	case SYS_readv:
-		ret = map (readv ((int)a0, ptr (const struct iovec, a1), (int)a2));
-		break;
-	case SYS_writev:
-		ret = map (writev ((int)a0, ptr (const struct iovec, a1), (int)a2));
-		break;
-	case SYS_pread:
-		ret = map (pread ((int)a0, ptr (void, a1), (size_t)a2, (off_t)a3));
-		break;
-	case SYS_pwrite:
-		ret = map (pwrite ((int)a0, ptr (const void, a1), (size_t)a2, (off_t)a3));
-		break;
-	case SYS_preadv:
-		ret = enosys ("preadv");
-		break;
-	case SYS_pwritev:
-		ret = enosys ("pwritev");
-		break;
-	case SYS_sendfile:
-		ret = enosys ("sendfile");
-		break;
-	case SYS_pselect6:
-		ret = enosys ("pselect6");
-		break;
-	case SYS_ppoll:
-		ret = enosys ("ppoll");
-		break;
-	case SYS_signalfd4:
-		ret = enosys ("signalfd4");
-		break;
-	case SYS_vmsplice:
-		ret = enosys ("vmsplice");
-		break;
-	case SYS_splice:
-		ret = enosys ("splice");
-		break;
-	case SYS_tee:
-		ret = enosys ("tee");
-		break;
-	case SYS_readlinkat:
-		ret = map (readlinkat ((int)a0, str (a1), ptr (char, a2), (size_t)a3));
-		break;
-	case SYS_fstatat:
-		ret = map (fstatat ((int)a0, str (a1), &st, (int)a3));
-		stat_to_linux_stat (&lst, &st);
-		memcpy (ptr (void, a2), &lst, sizeof (lst));
-		break;
-	case SYS_fstat:
-		ret = map (fstat ((int)a0, &st));
-		stat_to_linux_stat (&lst, &st);
-		memcpy (ptr (void, a1), &lst, sizeof (lst));
-		break;
-	case SYS_sync:
-		sync ();
-		ret = 0;
-		break;
-	case SYS_fsync:
-		ret = map (fsync ((int)a0));
-		break;
-	case SYS_fdatasync:
-		ret = map (fdatasync ((int)a0));
-		break;
-	case SYS_sync_file_range:
-		ret = enosys ("sync_file_range");
-		break;
-	case SYS_timerfd_create:
-		ret = enosys ("timerfd_create");
-		break;
-	case SYS_timerfd_settime:
-		ret = enosys ("timerfd_settime");
-		break;
-	case SYS_timerfd_gettime:
-		ret = enosys ("timerfd_gettime");
-		break;
-	case SYS_utimensat:
-		ret = enosys ("utimensat");
-		break;
-	case SYS_acct:
-		ret = acct (str (a0));
-		break;
-	case SYS_capget:
-		ret = enosys ("capget");
-		break;
-	case SYS_capset:
-		ret = enosys ("capset");
-		break;
-	case SYS_personality:
-		ret = enosys ("personality");
-		break;
-	case SYS_exit:
-		exit (a0);
-		ret = -1;
-		break;
-	case SYS_exit_group:
-		ret = enosys ("exit_group");
-		break;
-	case SYS_waitid:
-		ret = enosys ("waitid");
-		break;
-	case SYS_set_tid_address:
-		warnx ("set_tid_address(): not implemented");
-		ret = getpid ();
-		break;
-	case SYS_unshare:
-		ret = enosys ("unshare");
-		break;
-	case SYS_futex:
-		ret = enosys ("futex");
-		break;
-	case SYS_set_robust_limit:
-		ret = enosys ("set_robust_limit");
-		break;
-	case SYS_get_robust_limit:
-		ret = enosys ("get_robust_limit");
-		break;
-	case SYS_nanosleep:
-		ret = enosys ("nanosleep");
-		break;
-	case SYS_gettimer:
-		ret = enosys ("gettimer");
-		break;
-	case SYS_settimer:
-		ret = enosys ("settimer");
-		break;
-	case SYS_kexec_load:
-		ret = enosys ("kexec_load");
-		break;
-	case SYS_kexec_init_module:
-		ret = enosys ("kexec_init_module");
-		break;
-	case SYS_kexec_delete_module:
-		ret = enosys ("kexec_delete_module");
-		break;
-	case SYS_timer_create:
-		ret = enosys ("timer_create");
-		break;
-	case SYS_timer_gettime:
-		ret = enosys ("timer_gettime");
-		break;
-	case SYS_timer_getoverrun:
-		ret = enosys ("timer_getoverrun");
-		break;
-	case SYS_timer_settime:
-		ret = enosys ("timer_settime");
-		break;
-	case SYS_timer_delete:
-		ret = enosys ("timer_delete");
-		break;
-	case SYS_clock_settime:
-		ret = enosys ("clock_settime");
-		break;
-	case SYS_clock_gettime:
-		ret = enosys ("clock_gettime");
-		break;
-	case SYS_clock_getres:
-		ret = enosys ("clock_getres");
-		break;
-	case SYS_clock_nanosleep:
-		ret = enosys ("clock_nanosleep");
-		break;
-	case SYS_syslog:
-		ret = enosys ("syslog");
-		break;
-	case SYS_ptrace:
-		ret = enosys ("ptrace");
-		break;
-	case SYS_sched_setparam:
-		ret = enosys ("sched_setparam");
-		break;
-	case SYS_sched_setscheduler:
-		ret = enosys ("sched_setscheduler");
-		break;
-	case SYS_sched_getscheduler:
-		ret = enosys ("sched_getscheduler");
-		break;
-	case SYS_sched_getparam:
-		ret = enosys ("sched_getparam");
-		break;
-	case SYS_sched_setaffinity:
-		ret = enosys ("sched_setaffinity");
-		break;
-	case SYS_sched_getaffinity:
-		ret = enosys ("sched_getaffinity");
-		break;
-	case SYS_sched_yield:
-		ret = map (sched_yield ());
-		break;
-	case SYS_sched_get_priority_max:
-		ret = map (sched_get_priority_max ((int)a0));
-		break;
-	case SYS_sched_get_priority_min:
-		ret = map (sched_get_priority_min ((int)a0));
-		break;
-	case SYS_sched_rr_get_interval:
-		ret = enosys ("sched_rr_get_interval");
-		break;
-	case SYS_restart_syscall:
-		ret = enosys ("restart_syscall");
-		break;
-	case SYS_kill:
-		ret = map (kill ((pid_t)a0, (int)a1));
-		break;
-	case SYS_tkill:
-		ret = enosys ("tkill");
-		break;
-	case SYS_tgkill:
-		ret = enosys ("tgkill");
-		break;
-	case SYS_signalstack:
-		ret = enosys ("signalstack");
-		break;
-	case SYS_sigsuspend:
-		ret = enosys ("sigsuspend");
-		break;
-	case SYS_sigaction:
-		ret = enosys ("sigaction");
-		break;
-	case SYS_rt_sigprocmask:
-		ret = enosys ("rt_sigprocmask");
-		break;
-	case SYS_sigpending:
-		ret = enosys ("sigpending");
-		break;
-	case SYS_sigtimedwait:
-		ret = enosys ("sigtimedwait");
-		break;
-	case SYS_sigqueueinfo:
-		ret = enosys ("sigqueueinfo");
-		break;
-	case SYS_sigreturn:
-		ret = enosys ("sigreturn");
-		break;
-	case SYS_setpriority:
-		ret = map (setpriority ((int)a0, (id_t)a1, (int)a2));
-		break;
-	case SYS_getpriority:
-		ret = map (getpriority ((int)a0, (id_t)a1));
-		break;
-	case SYS_reboot:
-		ret = enosys ("reboot");
-		break;
-	case SYS_setregid:
-		ret = map (setregid ((gid_t)a0, (gid_t)a1));
-		break;
-	case SYS_setgid:
-		ret = map (setgid ((gid_t)a0));
-		break;
-	case SYS_setreuid:
-		ret = map (setreuid ((uid_t)a0, (uid_t)a1));
-		break;
-	case SYS_setuid:
-		ret = map (setuid ((uid_t)a0));
-		break;
-	case SYS_setresuid:
-		ret = map (setresuid ((uid_t)a0, (uid_t)a1, (uid_t)a2));
-		break;
-	case SYS_getresuid:
-		ret = map (getresuid (ptr (uid_t, a0), ptr (uid_t, a1), ptr (uid_t, a2)));
-		break;
-	case SYS_setresgid:
-		ret = map (setresgid ((gid_t)a0, (gid_t)a1, (gid_t)a2));
-		break;
-	case SYS_getresgid:
-		ret = map (getresgid (ptr (gid_t, a0), ptr (gid_t, a1), ptr (gid_t, a2)));
-		break;
-	case SYS_setfsuid:
-		ret = enosys ("setfsuid");
-		break;
-	case SYS_setfsgid:
-		ret = enosys ("setfsgid");
-		break;
-	case SYS_times:
-		ret = enosys ("times");
-		break;
-	case SYS_setpgid:
-		ret = map (setpgid ((pid_t)a0, (pid_t)a1));
-		break;
-	case SYS_getpgid:
-		ret = map (getpgid ((pid_t)a0));
-		break;
-	case SYS_getsid:
-		ret = map (getsid ((pid_t)a0));
-		break;
-	case SYS_setsid:
-		ret = map (setsid ());
-		break;
-	case SYS_setgroups:
-		ret = enosys ("setgroups");
-		break;
-	case SYS_uname:
-		ret = map (uname (&un));
-		utsname_to_linux_utsname (&lun, &un);
-		memcpy (ptr (void, a0), &lun, sizeof (lun));
-		break;
-	case SYS_sethostname:
-		ret = enosys ("sethostname");
-		break;
-	case SYS_setdomainname:
-		ret = enosys ("setdomainname");
-		break;
-	case SYS_getrlimit:
-		ret = enosys ("getrlimit");
-		break;
-	case SYS_setrlimit:
-		ret = enosys ("setrlimit");
-		break;
-	case SYS_getrusage:
-		ret = enosys ("getrusage");
-		break;
-	case SYS_umask:
-		ret = map (umask ((mode_t)a0));
-		break;
-	case SYS_prctl:
-		ret = enosys ("prctl");
-		break;
-	case SYS_getcpu:
-		ret = enosys ("getcpu");
-		break;
-	case SYS_gettimeofday:
-		ret = enosys ("gettimeofday");
-		break;
-	case SYS_settimeofday:
-		ret = enosys ("settimeofday");
-		break;
-	case SYS_adjtimex:
-		ret = enosys ("adjtimex");
-		break;
-	case SYS_getpid:
-		ret = map (getpid ());
-		break;
-	case SYS_getuid:
-		ret = map (getuid ());
-		break;
-	case SYS_geteuid:
-		ret = map (geteuid ());
-		break;
-	case SYS_getgid:
-		ret = map (getgid ());
-		break;
-	case SYS_getegid:
-		ret = map (getegid ());
-		break;
-	case SYS_gettid:
-		ret = enosys ("gettid");
-		break;
-	case SYS_sysinfo:
-		ret = enosys ("sysinfo");
-		break;
-	case 180:
-	case 181:
-	case 182:
-	case 183:
-	case 184:
-	case 185:
-		ret = enosys ("mq_*");
-		break;
-	case SYS_msgget:
-		ret = map(msgget ((key_t)a0, (int)a1));
-		break;
-	case SYS_msgctl:
-		ret = enosys ("msgctl");
-		break;
-	case SYS_msgrcv:
-		ret = map (msgrcv ((int)a0, ptr (void, a1), (size_t)a2, (long)a3, (int)a4));
-		break;
-	case SYS_msgsnd:
-		ret = map (msgsnd ((int)a0, ptr (const void, a1), (size_t)a2, (int)a3));
-		break;
-	case SYS_semget:
-		ret = map (semget ((key_t)a0, (int)a1, (int)a2));
-		break;
-	case SYS_semctl:
-		ret = enosys ("semctl");
-		break;
-	case SYS_semtimedop:
-		ret = enosys ("semtimedop");
-		break;
-	case SYS_semop:
-		ret = enosys ("semop");
-		break;
-	case 194:
-	case 195:
-	case 196:
-	case 197:
-		ret = enosys ("shm*");
-		break;
-	case 198:
-	case 199:
-	case 200:
-	case 201:
-	case 202:
-	case 203:
-	case 204:
-	case 205:
-	case 206:
-	case 207:
-	case 208:
-	case 209:
-	case 210:
-	case 211:
-	case 212:
-		ret = enosys ("socket api");
-		break;
-	case SYS_readahead:
-		ret = enosys ("readahead");
-		break;
-	case SYS_brk:
-		ret = map (my_brk (a0));
-		break;
-	case SYS_munmap:
-		ret = map (munmap (ptr (void, a0), (size_t)a1));
-		break;
-	case SYS_mremap:
-		ret = enosys ("mremap");
-		break;
-	case SYS_add_key:
-		ret = enosys ("add_key");
-		break;
-	case SYS_request_key:
-		ret = enosys ("request_key");
-		break;
-	case SYS_keyctl:
-		ret = enosys ("keyctl");
-		break;
-	case SYS_clone:
-		if (a0 == 17 && a1 == 0) {
-			// fork
-			ret = map (fork ());
-		} else {
-			ret = enosys ("clone");
-		}
-		break;
-	case SYS_execve:
-		ret = map (my_execve (str (a0), ptr (char *, a1), ptr (char *, a2)));
-		break;
-	case SYS_mmap:
-		//eprintf ("mmap (%p, %zu, %d, %d, %d, %lld);\n", ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5);
-		ptr = mmap (ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5);
-		if (ptr == NULL) {
-			ret = -map_errno (errno);
-		} else {
-			ret = (u64)ptr;
-		}
-		break;
-	case SYS_fadvise64:
-		ret = enosys ("fadvise64");
-		break;
-	case SYS_swapon:
-		ret = enosys ("swapon");
-		break;
-	case SYS_swapoff:
-		ret = enosys ("swapoff");
-		break;
-	case SYS_mprotect:
-		ret = map (mprotect (ptr (void, a0), (size_t)a1, (int)a2));
-		break;
-	case SYS_msync:
-		ret = map (msync (ptr (void, a0), (size_t)a1, (int)a2));
-		break;
-	case SYS_mlock:
-		ret = map (mlock (ptr (void, a0), (size_t)a1));
-		break;
-	case SYS_munlock:
-		ret = map (munlock (ptr (void, a0), (size_t)a1));
-		break;
-	case SYS_mlockall:
-		ret = map (mlockall ((int)a0));
-		break;
-	case SYS_munlockall:
-		ret = map (munlockall ());
-		break;
-	case SYS_mincore:
-		ret = enosys ("mincore");
-		break;
-	case SYS_madvise:
-		ret = map (madvise (ptr (void, a0), (size_t)a1, (int)a2));
-		break;
-	case SYS_remap_file_pages:
-		ret = enosys ("remap_file_pages");
-		break;
-	case SYS_mbind:
-		ret = enosys ("mbind");
-		break;
-	case SYS_get_mempolicy:
-		ret = enosys ("get_mempolicy");
-		break;
-	case SYS_set_mempolicy:
-		ret = enosys ("set_mempolicy");
-		break;
-	case SYS_migrate_pages:
-		ret = enosys ("migrate_pages");
-		break;
-	case SYS_move_pages:
-		ret = enosys ("move_pages");
-		break;
-	case SYS_rt_tgsigqueueinfo:
-		ret = enosys ("rt_tgsigqueueinfo");
-		break;
-	case SYS_perf_event_open:
-		ret = enosys ("perf_event_open");
-		break;
-	case SYS_accept4:
-		ret = enosys ("accept4");
-		break;
-	case SYS_recvmsg:
-		ret = enosys ("recvmsg");
-		break;
-	case 244:
-	case 245:
-	case 246:
-	case 247:
-	case 248:
-	case 249:
-	case 250:
-	case 251:
-	case 252:
-	case 253:
-	case 254:
-	case 255:
-	case 256:
-	case 257:
-	case 258:
-	case 259:
-		ret = enosys ("arch-specific");
-		break;
-	case 260:
-		ret = enosys ("wait4");
-		break;
-	case SYS_prlimit64:
-		ret = enosys ("prlimit64");
-		break;
-	case SYS_fanotify_init:
-		ret = enosys ("fanotify_init");
-		break;
-	case SYS_fanotify_mark:
-		ret = enosys ("fanotify_mark");
-		break;
-	case SYS_name_to_handle_at:
-		ret = enosys ("name_to_handle_at");
-		break;
-	case SYS_open_by_handle_at:
-		ret = enosys ("open_by_handle_at");
-		break;
-	case SYS_clock_adjtime:
-		ret = enosys ("clock_adjtime");
-		break;
-	case SYS_syncfs:
-		ret = enosys ("syncfs");
-		break;
-	case SYS_setns:
-		ret = enosys ("setns");
-		break;
-	case SYS_sendmsg:
-		ret = enosys ("sendmsg");
-		break;
-	case SYS_process_vm_readv:
-		ret = enosys ("process_vm_readv");
-		break;
-	case SYS_process_vm_writev:
-		ret = enosys ("process_vm_writev");
-		break;
-	case SYS_kcmp:
-		ret = enosys ("kcmp");
-		break;
-	case SYS_finit_module:
-		ret = enosys ("finit_module");
-		break;
-	case SYS_sched_setattr:
-		ret = enosys ("sched_setattr");
-		break;
-	case SYS_sched_getattr:
-		ret = enosys ("sched_getattr");
-		break;
-	case SYS_renameat2:
-		ret = enosys ("renameat2");
-		break;
-	case SYS_seccomp:
-		ret = enosys ("seccomp");
-		break;
-	case SYS_getrandom:
-		ret = enosys ("getrandom");
-		break;
-	case SYS_memfd_create:
-		ret = enosys ("seccomp");
-		break;
-	case SYS_bpf:
-		ret = enosys ("bpf");
-		break;
-	case SYS_execveat:
-		ret = enosys ("execveat");
-		break;
-	case SYS_userfaultfd:
-		ret = enosys ("usefaultfd");
-		break;
-	case SYS_membarrier:
-		ret = enosys ("membarrier");
-		break;
-	case SYS_mlock2:
-		ret = enosys ("mlock2");
-		break;
-	case SYS_copy_file_range:
-		ret = enosys ("copy_file_range");
-		break;
-	case SYS_preadv2:
-		ret = enosys ("preadv2");
-		break;
-	case SYS_pwritev2:
-		ret = enosys ("pwritev2");
-		break;
-	case SYS_pkey_mprotect:
-		ret = enosys ("pkey_mprotect");
-		break;
-	case SYS_pkey_alloc:
-		ret = enosys ("pkey_alloc");
-		break;
-	case SYS_pkey_free:
-		ret = enosys ("pkey_free");
-		break;
-	case SYS_statx:
-		ret = enosys ("statx");
-		break;
-	case SYS_io_pgetevents:
-		ret = enosys ("io_pgetevents");
-		break;
-	case SYS_rseq:
-		ret = enosys ("rseq");
-		break;
-	case SYS_kexec_file_load:
-		ret = enosys ("kexec_file_load");
-		break;
-	case SYS_open:
-		ret = map (open ((const char *)(size_t)a0, (int)a1, (int)a2));
-		break;
-	case SYS_link:
-		ret = map (link (str (a0), str (a1)));
-		break;
-	case SYS_unlink:
-		ret = map (unlink (str (a0)));
-		break;
-	case SYS_mkdir:
-		ret = map (mkdir (str (a0), (mode_t)a1));
-		break;
-	case SYS_access:
-		ret = map (access (str (a0), (int)a1));
-		break;
-	case SYS_stat:
-		ret = map (stat (str (a0), &st));
-		stat_to_linux_stat (&lst, &st);
-		memcpy (ptr (void, a1), &lst, sizeof (lst));
-		break;
-	case SYS_lstat:
-		ret = map (lstat (str (a0), &st));
-		stat_to_linux_stat (&lst, &st);
-		memcpy (ptr (void, a1), &lst, sizeof (lst));
-		break;
-	case SYS_time:
-		ret = enosys ("time");
-		break;
-	case SYS_getmainvars:
-		ret = enosys ("getmainvars");
-		break;
-	case SYS_debug:
-		fprintf (stderr, "DEBUG: %llu\n", a0);
-		ret = 0;
-		break;
-	default:
-		warnx ("%08llx: unimplemented syscall %llu", pc - 4, a7);
-		ret = -map_errno (ENOSYS);
-		break;
-	}
-	cpu_set (REG_a0, ret);
-}
-
blob - 66eb875ea57dc87a40bf8b6cb2d3386f35feeb06 (mode 644)
blob + /dev/null
--- exec.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-#include "rvemu.h"
-
-
-int is_executable (const Elf64_Ehdr *ehdr)
-{
-	return IS_ELF (*ehdr)
-		&& ehdr->e_ident[EI_CLASS] == ELFCLASS64
-		&& ehdr->e_ident[EI_DATA] == ELFDATA2LSB
-		&& ehdr->e_machine == EM_RISCV
-		;
-}
-
-int my_execve (const char *path, char **argv, char **envp)
-{
-
-	Elf64_Ehdr ehdr;
-	char buffer[256], *nl, *s, **args, **env;
-	int fd;
-
-	fd = open (path, O_RDONLY);
-	if (fd < 0)
-		return -1;
-	
-	memset (buffer, 0, sizeof (buffer));
-	read (fd, buffer, 2);
-
-	if (buffer[0] == '#' && buffer[1] == '!') {
-		read (fd, buffer, sizeof (buffer));
-		close (fd);
-
-		nl = memchr (buffer, '\n', sizeof (buffer));
-		if (nl == NULL) {
-			errno = EINVAL;
-			return -1;
-		}
-
-		*nl = '\0';
-
-		s = buffer;
-		while (isspace (*s))
-			++s;
-
-		return my_execve (s, argv, envp);
-	}
-
-	memset (&ehdr, 0, sizeof (ehdr));
-	lseek (fd, 0, SEEK_SET);
-	read (fd, &ehdr, sizeof (ehdr));
-	close (fd);
-
-	if (is_executable (&ehdr)) {
-		return execvpe ("rvemu", argv, envp);
-	}
-
-	return execve (path, argv, envp);
-}
-
blob - 8f4a68660eee0892775ff39ba5a6f7f43029bf82 (mode 644)
blob + /dev/null
--- hello.S
+++ /dev/null
@@ -1,17 +0,0 @@
-.include "syscalls.inc"
-
-.section .rodata
-str:	.string "Hello World\n"
-
-.section .text
-.global _start
-_start:
-	li a0, 1
-	la a1, str
-	li a2, 12
-	li a7, SYS_write
-	ecall
-
-	li a0, 0
-	li a7, SYS_exit
-	ecall
blob - a5826bdff3660ddabb245f576fe5539b00f2243e (mode 644)
blob + /dev/null
--- linker.ld
+++ /dev/null
@@ -1,23 +0,0 @@
-ENTRY(_start)
-
-SECTIONS {
-	. = 1M;
-
-	.text : ALIGN(4K) {
-		*(.text*)
-	}
-
-	.rodata : ALIGN(4K) {
-		*(.rodata*)
-	}
-
-	.data : ALIGN(4K) {
-		*(.data*)
-	}
-
-	.bss : ALIGN(4K) {
-		*(COMMON)
-		*(.bss*)
-	}
-
-}
blob - a0d8b14d8d05941c2315f86aa3a6da4ba0551ba4 (mode 644)
blob + /dev/null
--- rvemu.c
+++ /dev/null
@@ -1,193 +0,0 @@
-#include <sys/resource.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <libgen.h>
-#include <fcntl.h>
-#include <errno.h>
-#include "rvemu.h"
-
-u64 brkval = 0;
-
-static void load_segment (int fd, Elf64_Phdr phdr)
-{
-	size_t end, len, ps;
-	int prot = 0;
-	void *addr, *ptr;
-
-
-	if (phdr.p_filesz > phdr.p_memsz)
-		errx (1, "invalid program header: p_filesz > p_memsz");
-
-	ps = getpagesize ();
-	addr = (void *)(phdr.p_vaddr & ~(ps - 1));
-	len = phdr.p_memsz + phdr.p_vaddr - (size_t)addr;
-
-	ptr = mmap (
-		addr,
-		len,
-		PROT_READ | PROT_WRITE,
-		MAP_PRIVATE | MAP_ANON,
-		-1,
-		0
-	);
-	eprintf ("mmap (%p, %#zx) = %p;\n", addr, len, ptr);
-
-	if (ptr == NULL)
-		err (1, "mmap()");
-
-	if (phdr.p_filesz > 0) {
-		lseek (fd, phdr.p_offset, SEEK_SET);
-		read (fd, (void *)phdr.p_vaddr, phdr.p_filesz);
-	}
-
-	if (phdr.p_flags & (PF_R | PF_X))
-		prot |= PROT_READ;
-	if (phdr.p_flags & PF_W)
-		prot |= PROT_WRITE;
-	if (mprotect (addr, len, prot) != 0)
-		err (1, "mprotect()");
-
-	end = phdr.p_vaddr + phdr.p_memsz;
-	if (end > brkval)
-		brkval = end;
-}
-
-static void load_image (const char *filename)
-{
-	Elf64_Ehdr ehdr;
-	int fd;
-
-	fd = open (filename, O_RDONLY);
-	if (fd < 0)
-		err (1, "open('%s')", filename);
-
-	if (read (fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
-		err (1, "read('%s')", filename);
-
-	if (!is_executable (&ehdr))
-		errx (1, "Invalid argument");
-
-	pc = ehdr.e_entry;
-
-	for (unsigned i = 0; i < ehdr.e_phnum; ++i) {
-		Elf64_Phdr phdr;
-
-		lseek (fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET);
-		if (read (fd, &phdr, ehdr.e_phentsize) != ehdr.e_phentsize)
-			err (1, "failed to read program header %u", i);
-
-		switch (phdr.p_type) {
-		case PT_NULL:
-			break;
-		case PT_LOAD:
-			load_segment (fd, phdr);
-			break;
-		case PT_INTERP:
-		case PT_DYNAMIC:
-			errx (1, "shared objects not supported");
-		default:
-			//warnx ("%u: ignoring program header: %x",
-			//	i, (unsigned)phdr.p_type);
-			break;
-		}
-	}
-	close (fd);
-}
-
-static void cpu_push (u64 val)
-{
-	cpu_set (REG_sp, cpu_get (REG_sp) - 8);
-	write_u64 (cpu_get (REG_sp), val);
-}
-
-static void setup_stack (
-	u64 stack_size,
-	int argc,
-	char **argv,
-	int envc,
-	char **envp
-) {
-	void *ptr;
-	void *stack_bottom;
-
-	// set stack pointer
-	cpu_set (REG_sp, 0x80000000);
-
-	stack_bottom = (void *)(u64)(0x80000000 - stack_size);
-	ptr = mmap (
-		stack_bottom,
-		stack_size,
-		PROT_READ | PROT_WRITE,
-		MAP_PRIVATE | MAP_ANON | MAP_STACK,
-		-1,
-		0
-	);
-
-	if (ptr != stack_bottom)
-		err (1, "failed to map stack");
-
-	// auxv
-	cpu_push (0);
-	cpu_push (0);
-	cpu_push (getegid ());
-	cpu_push (14);
-	cpu_push (getgid ());
-	cpu_push (13);
-	cpu_push (geteuid ());
-	cpu_push (12);
-	cpu_push (getuid ());
-	cpu_push (11);
-	cpu_push (getpagesize ());
-	cpu_push (6);
-
-	cpu_push (0);
-	for (int i = envc - 1; i >= 0; --i)
-		cpu_push ((u64)envp[i]);
-	cpu_push (0);
-	for (int i = argc - 1; i >= 0; --i)
-		cpu_push ((u64)argv[i]);
-	cpu_push (argc);
-}
-
-int main (int argc, char *argv[], char *envp[])
-{
-	const char *filename;
-	struct rlimit rl;
-	size_t stack_size;
-	int fd, envc;
-	char *base;
-	void *ptr;
-
-	base = basename (argv[0]);
-
-	if (strcmp (base, "rvemu") == 0) {
-		if (argc < 2)
-			errx (1, "usage: rvemu file");
-
-		filename = argv[1];
-	} else {
-		filename = argv[0];
-	}
-
-	load_image (filename);
-
-	if (getrlimit (RLIMIT_STACK, &rl) == 0) {
-		stack_size = rl.rlim_cur;
-	} else {
-		stack_size = 1 << 20;
-	}
-
-	for (envc = 0; envp[envc] != NULL; ++envc);
-
-	setup_stack (stack_size, argc, argv, envc, envp);
-
-	while (1) {
-		const u32 instr = cpu_fetch ();
-		cpu_exec (instr);
-	}
-
-	return 0;
-}
blob - f1fa870f78600a53528abcc226d280124e392286 (mode 644)
blob + /dev/null
--- rvemu.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <stddef.h>
-#include <stdint.h>
-#include <libelf.h>
-#include <stdio.h>
-#include <err.h>
-
-#define DEBUG 0
-
-#if DEBUG
-# define eprintf(...) fprintf (stderr, __VA_ARGS__)
-#else
-# define eprintf(...)
-#endif
-
-enum {
-	REG_zero,
-	REG_ra,
-	REG_sp,
-	REG_gp,
-	REG_tp,
-	REG_t0,
-	REG_t1,
-	REG_t2,
-	REG_s0,
-	REG_s1,
-	REG_a0,
-	REG_a1,
-	REG_a2,
-	REG_a3,
-	REG_a4,
-	REG_a5,
-	REG_a6,
-	REG_a7,
-	REG_s2,
-	REG_s3,
-	REG_s4,
-	REG_s5,
-	REG_s6,
-	REG_s7,
-	REG_s8,
-	REG_s9,
-	REG_s10,
-	REG_s11,
-	REG_t3,
-	REG_t4,
-	REG_t5,
-	REG_t6,
-};
-
-typedef uint8_t  u8;
-typedef uint16_t u16;
-typedef uint32_t u32;
-typedef uint64_t u64;
-
-typedef int8_t   i8;
-typedef int16_t  i16;
-typedef int32_t  i32;
-typedef int64_t  i64;
-
-typedef unsigned int uint;
-
-extern u64 pc;
-extern u64 brkval;
-extern const char *interpreter;
-
-u32 cpu_fetch (void);
-u64 cpu_get (size_t reg);
-void cpu_set (size_t reg, u64 val);
-void cpu_exec (u32 instr);
-void ecall (void);
-int my_execve (const char *path, char **argv, char **envp);
-int is_executable (const Elf64_Ehdr *);
-
-#define read_u8(ptr)		(*(const u8 *)(size_t)(ptr))
-#define read_u16(ptr)		(*(const u16 *)(size_t)(ptr))
-#define read_u32(ptr)		(*(const u32 *)(size_t)(ptr))
-#define read_u64(ptr)		(*(const u64 *)(size_t)(ptr))
-#define read_i8(ptr)		(*(const i8 *)(size_t)(ptr))
-#define read_i16(ptr)		(*(const i16 *)(size_t)(ptr))
-#define read_i32(ptr)		(*(const i32 *)(size_t)(ptr))
-#define read_i64(ptr)		(*(const i64 *)(size_t)(ptr))
-#define write_u8(ptr, val)	(*(u8 *)(size_t)(ptr) = (val))
-#define write_u16(ptr, val)	(*(u16 *)(size_t)(ptr) = (val))
-#define write_u32(ptr, val)	(*(u32 *)(size_t)(ptr) = (val))
-#define write_u64(ptr, val)	(*(u64 *)(size_t)(ptr) = (val))
blob - f107b56f5fe7a8f694784c2a8903a7c54f1e5c14 (mode 644)
blob + /dev/null
--- syscalls.inc
+++ /dev/null
@@ -1,234 +0,0 @@
-.set SYS_getcwd, 17
-.set SYS_dup, 23
-.set SYS_dup3, 24
-.set SYS_fcntl, 25
-.set SYS_ioctl, 29
-.set SYS_flock, 32
-.set SYS_mknodat, 33
-.set SYS_mkdirat, 34
-.set SYS_unlinkat, 35
-.set SYS_symlinkat, 36
-.set SYS_linkat, 37
-.set SYS_renameat, 38
-.set SYS_umount, 39
-.set SYS_mount, 40
-.set SYS_pivot_root, 41
-.set SYS_nfsservctl, 42
-.set SYS_statfs, 43
-.set SYS_fstatfs, 44
-.set SYS_truncate, 45
-.set SYS_ftruncate, 46
-.set SYS_fallocate, 47
-.set SYS_faccessat, 48
-.set SYS_chdir, 49
-.set SYS_fchdir, 50
-.set SYS_chroot, 51
-.set SYS_fchmod, 52
-.set SYS_fchmodat, 53
-.set SYS_fchownat, 54
-.set SYS_fchown, 55
-.set SYS_openat, 56
-.set SYS_close, 57
-.set SYS_vhangup, 58
-.set SYS_pipe2, 59
-.set SYS_quotactl, 60
-.set SYS_getdents64, 61
-.set SYS_lseek, 62
-.set SYS_read, 63
-.set SYS_write, 64
-.set SYS_readv, 65
-.set SYS_writev, 66
-.set SYS_pread, 67
-.set SYS_pwrite, 68
-.set SYS_preadv, 69
-.set SYS_pwritev, 70
-.set SYS_sendfile, 71
-.set SYS_pselect6, 72
-.set SYS_ppoll, 73
-.set SYS_signalfd4, 74
-.set SYS_vmsplice, 75
-.set SYS_splice, 76
-.set SYS_tee, 77
-.set SYS_readlinkat, 78
-.set SYS_fstatat, 79
-.set SYS_fstat, 80
-.set SYS_sync, 81
-.set SYS_fsync, 82
-.set SYS_fdatasync, 83
-.set SYS_sync_file_range, 84
-.set SYS_timerfd_create, 85
-.set SYS_timerfd_settime, 86
-.set SYS_timerfd_gettime, 87
-.set SYS_utimensat, 88
-.set SYS_acct, 89
-.set SYS_capget, 90
-.set SYS_capset, 91
-.set SYS_personality, 92
-.set SYS_exit, 93
-.set SYS_exit_group, 94
-.set SYS_waitid, 95
-.set SYS_set_tid_address, 96
-.set SYS_unshare, 97
-.set SYS_futex, 98
-.set SYS_set_robust_limit, 99
-.set SYS_get_robust_limit, 100
-.set SYS_nanosleep, 101
-.set SYS_gettimer, 102
-.set SYS_settimer, 103
-.set SYS_kexec_load, 104
-.set SYS_kexec_init_module, 105
-.set SYS_kexec_delete_module, 106
-.set SYS_timer_create, 107
-.set SYS_timer_gettime, 108
-.set SYS_timer_getoverrun, 109
-.set SYS_timer_settime, 110
-.set SYS_timer_delete, 111
-.set SYS_clock_settime, 112
-.set SYS_clock_gettime, 113
-.set SYS_clock_getres, 114
-.set SYS_clock_nanosleep, 115
-.set SYS_syslog, 116
-.set SYS_ptrace, 117
-.set SYS_sched_setparam, 118
-.set SYS_sched_setscheduler, 119
-.set SYS_sched_getscheduler, 120
-.set SYS_sched_getparam, 121
-.set SYS_sched_setaffinity, 122
-.set SYS_sched_getaffinity, 123
-.set SYS_sched_yield, 124
-.set SYS_sched_get_priority_max, 125
-.set SYS_sched_get_priority_min, 126
-.set SYS_sched_rr_get_interval, 127
-.set SYS_restart_syscall, 128
-.set SYS_kill, 129
-.set SYS_tkill, 130
-.set SYS_tgkill, 131
-.set SYS_signalstack, 132
-.set SYS_sigsuspend, 133
-.set SYS_sigaction, 134
-.set SYS_rt_sigprocmask, 135
-.set SYS_sigpending, 136
-.set SYS_sigtimedwait, 137
-.set SYS_sigqueueinfo, 138
-.set SYS_sigreturn, 139
-.set SYS_setpriority, 140
-.set SYS_getpriority, 141
-.set SYS_reboot, 142
-.set SYS_setregid, 143
-.set SYS_setgid, 144
-.set SYS_setreuid, 145
-.set SYS_setuid, 146
-.set SYS_setresuid, 147
-.set SYS_getresuid, 148
-.set SYS_setresgid, 149
-.set SYS_getresgid, 150
-.set SYS_setfsuid, 151
-.set SYS_setfsgid, 152
-.set SYS_times, 153
-.set SYS_setpgid, 154
-.set SYS_getpgid, 155
-.set SYS_getsid, 156
-.set SYS_setsid, 158
-.set SYS_setgroups, 159
-.set SYS_uname, 160
-.set SYS_sethostname, 161
-.set SYS_setdomainname, 162
-.set SYS_getrlimit, 163
-.set SYS_setrlimit, 164
-.set SYS_getrusage, 165
-.set SYS_umask, 166
-.set SYS_prctl, 167
-.set SYS_getcpu, 168
-.set SYS_gettimeofday, 169
-.set SYS_settimeofday, 170
-.set SYS_adjtimex, 171
-.set SYS_getpid, 172
-.set SYS_getuid, 174
-.set SYS_geteuid, 175
-.set SYS_getgid, 176
-.set SYS_getegid, 177
-.set SYS_gettid, 178
-.set SYS_sysinfo, 179
-.set SYS_msgget, 186
-.set SYS_msgctl, 187
-.set SYS_msgrcv, 188
-.set SYS_msgsnd, 189
-.set SYS_semget, 190
-.set SYS_semctl, 191
-.set SYS_semtimedop, 192
-.set SYS_semop, 193
-.set SYS_readahead, 213
-.set SYS_brk, 214
-.set SYS_munmap, 215
-.set SYS_mremap, 216
-.set SYS_add_key, 217
-.set SYS_request_key, 218
-.set SYS_keyctl, 219
-.set SYS_clone, 220
-.set SYS_execve, 221
-.set SYS_mmap, 222
-.set SYS_fadvise64, 223
-.set SYS_swapon, 224
-.set SYS_swapoff, 225
-.set SYS_mprotect, 226
-.set SYS_msync, 227
-.set SYS_mlock, 228
-.set SYS_munlock, 229
-.set SYS_mlockall, 230
-.set SYS_munlockall, 231
-.set SYS_mincore, 232
-.set SYS_madvise, 233
-.set SYS_remap_file_pages, 234
-.set SYS_mbind, 235
-.set SYS_get_mempolicy, 236
-.set SYS_set_mempolicy, 237
-.set SYS_migrate_pages, 238
-.set SYS_move_pages, 239
-.set SYS_rt_tgsigqueueinfo, 240
-.set SYS_perf_event_open, 241
-.set SYS_accept4, 242
-.set SYS_recvmsg, 243
-.set SYS_prlimit64, 261
-.set SYS_fanotify_init, 262
-.set SYS_fanotify_mark, 263
-.set SYS_name_to_handle_at, 264
-.set SYS_open_by_handle_at, 265
-.set SYS_clock_adjtime, 266
-.set SYS_syncfs, 267
-.set SYS_setns, 268
-.set SYS_sendmsg, 269
-.set SYS_process_vm_readv, 270
-.set SYS_process_vm_writev, 271
-.set SYS_kcmp, 272
-.set SYS_finit_module, 273
-.set SYS_sched_setattr, 274
-.set SYS_sched_getattr, 275
-.set SYS_renameat2, 276
-.set SYS_seccomp, 277
-.set SYS_getrandom, 278
-.set SYS_memfd_create, 279
-.set SYS_bpf, 280
-.set SYS_execveat, 281
-.set SYS_userfaultfd, 282
-.set SYS_membarrier, 283
-.set SYS_mlock2, 284
-.set SYS_copy_file_range, 285
-.set SYS_preadv2, 286
-.set SYS_pwritev2, 287
-.set SYS_pkey_mprotect, 288
-.set SYS_pkey_alloc, 289
-.set SYS_pkey_free, 290
-.set SYS_statx, 291
-.set SYS_io_pgetevents, 292
-.set SYS_rseq, 293
-.set SYS_kexec_file_load, 294
-.set SYS_open, 1024
-.set SYS_link, 1025
-.set SYS_unlink, 1026
-.set SYS_mkdir, 1030
-.set SYS_access, 1033
-.set SYS_stat, 1038
-.set SYS_lstat, 1039
-.set SYS_time, 1062
-.set SYS_getmainvars, 2011
-.set SYS_debug, 2048