Commit bc06e19828

joachimschmidt557 <joachim.schmidt557@outlook.com>
2021-04-27 10:12:59
stage2 riscv64: cleanup code and add tests
1 parent da9da76
Changed files (3)
src
codegen
test
src/codegen/riscv64.zig
@@ -1,5 +1,7 @@
 const std = @import("std");
 const DW = std.dwarf;
+const assert = std.debug.assert;
+const testing = std.testing;
 
 // TODO: this is only tagged to facilitate the monstrosity.
 // Once packed structs work make it packed.
@@ -110,7 +112,7 @@ pub const Instruction = union(enum) {
     // -- less burden on callsite, bonus semantic checking
     fn bType(op: u7, fn3: u3, r1: Register, r2: Register, imm: i13) Instruction {
         const umm = @bitCast(u13, imm);
-        if (umm % 2 != 0) @panic("Internal error: misaligned branch target");
+        assert(umm % 2 == 0); // misaligned branch target
 
         return Instruction{
             .B = .{
@@ -140,15 +142,15 @@ pub const Instruction = union(enum) {
     }
 
     fn jType(op: u7, rd: Register, imm: i21) Instruction {
-        const umm = @bitcast(u21, imm);
-        if (umm % 2 != 0) @panic("Internal error: misaligned jump target");
+        const umm = @bitCast(u21, imm);
+        assert(umm % 2 == 0); // misaligned jump target
 
         return Instruction{
             .J = .{
                 .opcode = op,
                 .rd = @enumToInt(rd),
                 .imm1_10 = @truncate(u10, umm >> 1),
-                .imm11 = @truncate(u1, umm >> 1),
+                .imm11 = @truncate(u1, umm >> 11),
                 .imm12_19 = @truncate(u8, umm >> 12),
                 .imm20 = @truncate(u1, umm >> 20),
             },
@@ -340,27 +342,27 @@ pub const Instruction = union(enum) {
 
     // Branch
 
-    pub fn beq(r1: Register, r2: Register, offset: u13) Instruction {
+    pub fn beq(r1: Register, r2: Register, offset: i13) Instruction {
         return bType(0b1100011, 0b000, r1, r2, offset);
     }
 
-    pub fn bne(r1: Register, r2: Register, offset: u13) Instruction {
+    pub fn bne(r1: Register, r2: Register, offset: i13) Instruction {
         return bType(0b1100011, 0b001, r1, r2, offset);
     }
 
-    pub fn blt(r1: Register, r2: Register, offset: u13) Instruction {
+    pub fn blt(r1: Register, r2: Register, offset: i13) Instruction {
         return bType(0b1100011, 0b100, r1, r2, offset);
     }
 
-    pub fn bge(r1: Register, r2: Register, offset: u13) Instruction {
+    pub fn bge(r1: Register, r2: Register, offset: i13) Instruction {
         return bType(0b1100011, 0b101, r1, r2, offset);
     }
 
-    pub fn bltu(r1: Register, r2: Register, offset: u13) Instruction {
+    pub fn bltu(r1: Register, r2: Register, offset: i13) Instruction {
         return bType(0b1100011, 0b110, r1, r2, offset);
     }
 
-    pub fn bgeu(r1: Register, r2: Register, offset: u13) Instruction {
+    pub fn bgeu(r1: Register, r2: Register, offset: i13) Instruction {
         return bType(0b1100011, 0b111, r1, r2, offset);
     }
 
@@ -431,3 +433,38 @@ pub const Register = enum(u5) {
 pub const callee_preserved_regs = [_]Register{
     .s0, .s1, .s2, .s3, .s4, .s5, .s6, .s7, .s8, .s9, .s10, .s11,
 };
+
+test "serialize instructions" {
+    const Testcase = struct {
+        inst: Instruction,
+        expected: u32,
+    };
+
+    const testcases = [_]Testcase{
+        .{ // add t6, zero, zero
+            .inst = Instruction.add(.t6, .zero, .zero),
+            .expected = 0b0000000_00000_00000_000_11111_0110011,
+        },
+        .{ // sd s0, 0x7f(s0)
+            .inst = Instruction.sd(.s0, 0x7f, .s0),
+            .expected = 0b0000011_01000_01000_011_11111_0100011,
+        },
+        .{ // bne s0, s1, 0x42
+            .inst = Instruction.bne(.s0, .s1, 0x42),
+            .expected = 0b0_000010_01001_01000_001_0001_0_1100011,
+        },
+        .{ // j 0x1a
+            .inst = Instruction.jal(.zero, 0x1a),
+            .expected = 0b0_0000001101_0_00000000_00000_1101111,
+        },
+        .{ // ebreak
+            .inst = Instruction.ebreak,
+            .expected = 0b000000000001_00000_000_00000_1110011,
+        },
+    };
+
+    for (testcases) |case| {
+        const actual = case.inst.toU32();
+        testing.expectEqual(case.expected, actual);
+    }
+}
test/stage2/riscv64.zig
@@ -0,0 +1,45 @@
+const std = @import("std");
+const TestContext = @import("../../src/test.zig").TestContext;
+
+const linux_riscv64 = std.zig.CrossTarget{
+    .cpu_arch = .riscv64,
+    .os_tag = .linux,
+};
+
+pub fn addCases(ctx: *TestContext) !void {
+    {
+        var case = ctx.exe("riscv64 hello world", linux_riscv64);
+        // Regular old hello world
+        case.addCompareOutput(
+            \\export fn _start() noreturn {
+            \\    print();
+            \\
+            \\    exit();
+            \\}
+            \\
+            \\fn print() void {
+            \\    asm volatile ("ecall"
+            \\        :
+            \\        : [number] "{a7}" (64),
+            \\          [arg1] "{a0}" (1),
+            \\          [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
+            \\          [arg3] "{a2}" ("Hello, World!\n".len)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    return;
+            \\}
+            \\
+            \\fn exit() noreturn {
+            \\    asm volatile ("ecall"
+            \\        :
+            \\        : [number] "{a7}" (94),
+            \\          [arg1] "{a0}" (0)
+            \\        : "rcx", "r11", "memory"
+            \\    );
+            \\    unreachable;
+            \\}
+        ,
+            "Hello, World!\n",
+        );
+    }
+}
test/stage2/test.zig
@@ -11,11 +11,6 @@ const linux_x64 = std.zig.CrossTarget{
     .os_tag = .linux,
 };
 
-const linux_riscv64 = std.zig.CrossTarget{
-    .cpu_arch = .riscv64,
-    .os_tag = .linux,
-};
-
 pub fn addCases(ctx: *TestContext) !void {
     try @import("cbe.zig").addCases(ctx);
     try @import("spu-ii.zig").addCases(ctx);
@@ -24,6 +19,7 @@ pub fn addCases(ctx: *TestContext) !void {
     try @import("llvm.zig").addCases(ctx);
     try @import("wasm.zig").addCases(ctx);
     try @import("darwin.zig").addCases(ctx);
+    try @import("riscv64.zig").addCases(ctx);
 
     {
         var case = ctx.exe("hello world with updates", linux_x64);
@@ -137,42 +133,6 @@ pub fn addCases(ctx: *TestContext) !void {
         );
     }
 
-    {
-        var case = ctx.exe("riscv64 hello world", linux_riscv64);
-        // Regular old hello world
-        case.addCompareOutput(
-            \\export fn _start() noreturn {
-            \\    print();
-            \\
-            \\    exit();
-            \\}
-            \\
-            \\fn print() void {
-            \\    asm volatile ("ecall"
-            \\        :
-            \\        : [number] "{a7}" (64),
-            \\          [arg1] "{a0}" (1),
-            \\          [arg2] "{a1}" (@ptrToInt("Hello, World!\n")),
-            \\          [arg3] "{a2}" ("Hello, World!\n".len)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    return;
-            \\}
-            \\
-            \\fn exit() noreturn {
-            \\    asm volatile ("ecall"
-            \\        :
-            \\        : [number] "{a7}" (94),
-            \\          [arg1] "{a0}" (0)
-            \\        : "rcx", "r11", "memory"
-            \\    );
-            \\    unreachable;
-            \\}
-        ,
-            "Hello, World!\n",
-        );
-    }
-
     {
         var case = ctx.exe("adding numbers at comptime", linux_x64);
         case.addCompareOutput(
@@ -1048,7 +1008,7 @@ pub fn addCases(ctx: *TestContext) !void {
             "Hello, World!\n",
         );
         try case.files.append(.{
-            .src =
+            .src = 
             \\pub fn print() void {
             \\    asm volatile ("syscall"
             \\        :
@@ -1085,7 +1045,7 @@ pub fn addCases(ctx: *TestContext) !void {
             &.{":2:25: error: 'print' is private"},
         );
         try case.files.append(.{
-            .src =
+            .src = 
             \\fn print() void {
             \\    asm volatile ("syscall"
             \\        :