Commit Diff


commit - fdc4e5ea5a5c79384231dc931bf6e53499fa23e2
commit + 728f3bb17b12048abd68be8e8007c27fe6391cfc
blob - 2727b9249b35510da80a072f48006fc5848db0f9
blob + 4f4a708a8a59aae419e3804e0e2ad6537725d0cb
--- examples/test.c
+++ examples/test.c
@@ -42,5 +42,15 @@ int main (int argc, char *argv[]) {
 
 	fclose (out);
 	fclose (in);
+
+	in = fopen ("/output.txt", "r");
+	if (in == NULL)
+		err (1, "reopen('output.txt')");
+
+	while ((ch = fgetc (in)) != EOF)
+		putchar (ch);
+
+	fclose (in);
+
 	return 0;
 }
blob - 57f058885d086e859625805b9891f484dd0b5523
blob + 1097223b6bee26ebd2770d2554da81f7992465a1
--- src/cpu.c
+++ src/cpu.c
@@ -31,12 +31,16 @@ static i64 extend (i32 x)
 #define log(fmt, ...) eprintf ("%08"PRIx64": " fmt "\n", pc - 4, __VA_ARGS__)
 void cpu_exec (u32 instr)
 {
+	[[maybe_unused]] const char *sufx;
 	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 bool aq = (instr >> 26) & 1;
+	const bool rl = (instr >> 25) & 1;
+	const u8 funct3 = (instr >> 12) & 0x7;
+	const u8 funct5 = instr >> 27;
 	const u8 funct6 = instr >> 26;
+	const u8 funct7 = instr >> 25;
 	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)
@@ -51,6 +55,13 @@ void cpu_exec (u32 instr)
 	const u16 funct10 = (funct7 << 3) | funct3;
 	const u8 shamt = imm_i & 0x3f;
 
+	sufx = (const char *[]){
+		"",
+		".rl",
+		".aq",
+		".aqrl",
+	}[(aq << 1) | rl];
+
 	u64 a, b, c;
 	switch (instr & 0x7f) {
 	case 0b0110111: // lui rd, uimm
@@ -61,6 +72,39 @@ void cpu_exec (u32 instr)
 		a = pc + imm_u - 4;
 		log ("auipc x%u, %"PRIu64 " ; %"PRIu64, (uint)rd, imm_u, a);
 		cpu_set (rd, a);
+		break;
+	case 0b0101111: // atomics
+		// TODO: actual atomics, amo* instructions
+		a = cpu_get (rs1);
+		b = cpu_get (rs2);
+		switch ((funct5 << 3) | funct3) {
+		case 0b00010'010: // lr.w
+			if (rs2 != 0)
+				goto ud;
+			log ("lr.w%s x%u, (x%u) ; *%p", sufx, (uint)rs1, (uint)rs2, (void *)a);
+			b = read_i32 (a);
+			cpu_set (rd, b);
+			break;
+		case 0b00011'010: // sc.w
+			log ("sc.w%s x%u, x%u, (x%u) ; *%p = %"PRId64, sufx, (uint)rd, (uint)rs1, (uint)rs2, (void *)a, b);
+			write_u32 (a, b);
+			cpu_set (rd, 0);
+			break;
+		case 0b00010'011: // lr.d
+			if (rs2 != 0)
+				goto ud;
+			log ("lr.d%s x%u, (x%u) ; *%p", sufx, (uint)rs1, (uint)rs2, (void *)a);
+			b = read_i64 (a);
+			cpu_set (rd, b);
+			break;
+		case 0b00011'011: // sc.w
+			log ("sc.d%s x%u, x%u, (x%u) ; *%p = %"PRId64, sufx, (uint)rd, (uint)rs1, (uint)rs2, (void *)a, b);
+			write_u64 (a, b);
+			cpu_set (rd, 0);
+			break;
+		default:
+			goto ud;
+		}
 		break;
 	case 0b1101111: // jal rd, jimm
 		log ("jal x%u, %"PRId64, (uint)rd, imm_j);