Commit 1fd99ed324

pfg <pfg@pfg.pw>
2020-08-04 10:17:08
stage2: riscv hello world
1 parent 52ae2b1
Changed files (2)
src-self-hosted
src-self-hosted/codegen/riscv64.zig
@@ -5,29 +5,41 @@ pub const Instructions = struct {
         unused1: u5 = 0,
         unused2: u3 = 0,
         unused3: u5 = 0,
-        mode: u12,
+        mode: u12, //: Mode
     };
     pub const Addi = packed struct {
         pub const Mode = packed enum(u3) { addi = 0b000, slti = 0b010, sltiu = 0b011, xori = 0b100, ori = 0b110, andi = 0b111 };
         opcode: u7 = 0b0010011,
         rd: u5,
-        mode: u3,
-        rsi1: u5,
-        imm: u11,
-        signextend: u1 = 0,
+        mode: u3, //: Mode
+        rs1: u5,
+        imm: i12,
+    };
+    pub const Lui = packed struct {
+        opcode: u7 = 0b0110111,
+        rd: u5,
+        imm: i20,
+    };
+    pub const Load = packed struct {
+        pub const Mode = packed enum(u3) { ld = 0b011, lwu = 0b110 };
+        opcode: u7 = 0b0000011,
+        rd: u5,
+        mode: u3, //: Mode
+        rs1: u5,
+        offset: i12,
     };
 };
 
 // zig fmt: off
 pub const Register = enum(u8) {
     // 64 bit registers
-    zero = 0, // zero
-    ra = 1, // return address. caller saved
-    sp = 2, // stack pointer. callee saved.
-    gp = 3, // global pointer
-    tp = 4, // thread pointer
-    t0 = 5, t1 = 6, t2 = 7, // temporaries. caller saved.
-    s0 = 8, // s0/fp, callee saved.
+    zero, // zero
+    ra, // return address. caller saved
+    sp, // stack pointer. callee saved.
+    gp, // global pointer
+    tp, // thread pointer
+    t0, t1, t2, // temporaries. caller saved.
+    s0, // s0/fp, callee saved.
     s1, // callee saved.
     a0, a1, // fn args/return values. caller saved.
     a2, a3, a4, a5, a6, a7, // fn args. caller saved.
src-self-hosted/codegen.zig
@@ -1028,8 +1028,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                         .mode = @enumToInt(Instructions.CallBreak.Mode.ebreak),
                     });
 
-                    try self.code.resize(self.code.items.len + 4);
-                    mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full);
+                    mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full);
                 },
                 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),
             }
@@ -1351,8 +1350,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
                             .mode = @enumToInt(Instructions.CallBreak.Mode.ecall),
                         });
 
-                        try self.code.resize(self.code.items.len + 4);
-                        mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full);
+                        mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full);
                     } else {
                         return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{});
                     }
@@ -1546,29 +1544,74 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
         fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void {
             switch (arch) {
                 .riscv64 => switch (mcv) {
-                    .immediate => |x| {
-                        if (x > math.maxInt(u11)) {
-                            return self.fail(src, "TODO genSetReg 12+ bit immediates for riscv64", .{});
+                    .dead => unreachable,
+                    .ptr_stack_offset => unreachable,
+                    .ptr_embedded_in_code => unreachable,
+                    .unreach, .none => return, // Nothing to do.
+                    .undef => {
+                        if (!self.wantSafety())
+                            return; // The already existing value will do just fine.
+                        // Write the debug undefined value.
+                        switch (reg.size()) {
+                            64 => return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }),
+                            else => unreachable,
                         }
-                        const Instruction = packed struct {
-                            opcode: u7,
-                            rd: u5,
-                            mode: u3,
-                            rsi1: u5,
-                            imm: u11,
-                            signextend: u1 = 0,
-                        };
-                        const full = @bitCast(u32, Instructions.Addi{
-                            .imm = @intCast(u11, x),
-                            .rsi1 = Register.zero.id(),
-                            .mode = @enumToInt(Instructions.Addi.Mode.addi),
+                    },
+                    .immediate => |unsigned_x| {
+                        const x = @bitCast(i64, unsigned_x);
+                        if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {
+                            const instruction = @bitCast(u32, Instructions.Addi{
+                                .mode = @enumToInt(Instructions.Addi.Mode.addi),
+                                .imm = @truncate(i12, x),
+                                .rs1 = Register.zero.id(),
+                                .rd = reg.id(),
+                            });
+
+                            mem.writeIntLittle(u32, try self.code.addManyAsArray(4), instruction);
+                            return;
+                        }
+                        if (math.minInt(i32) <= x and x <= math.maxInt(i32)) {
+                            const split = @bitCast(packed struct {
+                                low12: i12,
+                                up20: i20,
+                            }, @truncate(i32, x));
+                            if (split.low12 < 0) return self.fail(src, "TODO support riscv64 genSetReg i32 immediates with 12th bit set to 1", .{});
+
+                            const lui = @bitCast(u32, Instructions.Lui{
+                                .imm = split.up20,
+                                .rd = reg.id(),
+                            });
+                            mem.writeIntLittle(u32, try self.code.addManyAsArray(4), lui);
+
+                            const addi = @bitCast(u32, Instructions.Addi{
+                                .mode = @enumToInt(Instructions.Addi.Mode.addi),
+                                .imm = @truncate(i12, split.low12),
+                                .rs1 = reg.id(),
+                                .rd = reg.id(),
+                            });
+                            mem.writeIntLittle(u32, try self.code.addManyAsArray(4), addi);
+                            return;
+                        }
+                        return self.fail(src, "TODO genSetReg 33-64 bit immediates for riscv64", .{}); // glhf
+                    },
+                    .memory => |addr| {
+                        // The value is in memory at a hard-coded address.
+                        // If the type is a pointer, it means the pointer address is at this memory location.
+                        try self.genSetReg(src, reg, .{ .immediate = addr });
+
+                        const ld = @bitCast(u32, Instructions.Load{
+                            .mode = @enumToInt(Instructions.Load.Mode.ld),
+                            .rs1 = reg.id(),
                             .rd = reg.id(),
+                            .offset = 0,
                         });
 
-                        try self.code.resize(self.code.items.len + 4);
-                        mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full);
+                        mem.writeIntLittle(u32, try self.code.addManyAsArray(4), ld);
+                        // LOAD imm=[i12 offset = 0], rs1 =
+
+                        // return self.fail("TODO implement genSetReg memory for riscv64");
                     },
-                    else => return self.fail(src, "TODO implement getSetReg for riscv64 MCValue {}", .{mcv}),
+                    else => return self.fail(src, "TODO implement getSetReg for riscv64 {}", .{mcv}),
                 },
                 .x86_64 => switch (mcv) {
                     .dead => unreachable,