authorgravatar for pfg@pfg.pwpfg <pfg@pfg.pw> 2020-08-04 01:17:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-04 14:38:33-07:00
log1fd99ed32427be59567130c0304c743a22e6eb60
tree2ab34aa94e2470fbe9eee5f89dc07373e9a1b98f
parent52ae2b10aaba858185c1f3a224a4042f6b632a29

stage2: riscv hello world


2 files changed, 89 insertions(+), 34 deletions(-)

src-self-hosted/codegen.zig+65-22
...@@ -1028,8 +1028,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1028,8 +1028,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1028 .mode = @enumToInt(Instructions.CallBreak.Mode.ebreak),1028 .mode = @enumToInt(Instructions.CallBreak.Mode.ebreak),
1029 });1029 });
10301030
1031 try self.code.resize(self.code.items.len + 4);1031 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full);
1032 mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full);
1033 },1032 },
1034 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),1033 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),
1035 }1034 }
...@@ -1351,8 +1350,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1351,8 +1350,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1351 .mode = @enumToInt(Instructions.CallBreak.Mode.ecall),1350 .mode = @enumToInt(Instructions.CallBreak.Mode.ecall),
1352 });1351 });
13531352
1354 try self.code.resize(self.code.items.len + 4);1353 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full);
1355 mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full);
1356 } else {1354 } else {
1357 return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{});1355 return self.fail(inst.base.src, "TODO implement support for more riscv64 assembly instructions", .{});
1358 }1356 }
...@@ -1546,29 +1544,74 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1546,29 +1544,74 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1546 fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void {1544 fn genSetReg(self: *Self, src: usize, reg: Register, mcv: MCValue) InnerError!void {
1547 switch (arch) {1545 switch (arch) {
1548 .riscv64 => switch (mcv) {1546 .riscv64 => switch (mcv) {
1549 .immediate => |x| {1547 .dead => unreachable,
1550 if (x > math.maxInt(u11)) {1548 .ptr_stack_offset => unreachable,
1551 return self.fail(src, "TODO genSetReg 12+ bit immediates for riscv64", .{});1549 .ptr_embedded_in_code => unreachable,
1550 .unreach, .none => return, // Nothing to do.
1551 .undef => {
1552 if (!self.wantSafety())
1553 return; // The already existing value will do just fine.
1554 // Write the debug undefined value.
1555 switch (reg.size()) {
1556 64 => return self.genSetReg(src, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }),
1557 else => unreachable,
1552 }1558 }
1553 const Instruction = packed struct {1559 },
1554 opcode: u7,1560 .immediate => |unsigned_x| {
1555 rd: u5,1561 const x = @bitCast(i64, unsigned_x);
1556 mode: u3,1562 if (math.minInt(i12) <= x and x <= math.maxInt(i12)) {
1557 rsi1: u5,1563 const instruction = @bitCast(u32, Instructions.Addi{
1558 imm: u11,1564 .mode = @enumToInt(Instructions.Addi.Mode.addi),
1559 signextend: u1 = 0,1565 .imm = @truncate(i12, x),
1560 };1566 .rs1 = Register.zero.id(),
1561 const full = @bitCast(u32, Instructions.Addi{1567 .rd = reg.id(),
1562 .imm = @intCast(u11, x),1568 });
1563 .rsi1 = Register.zero.id(),1569
1564 .mode = @enumToInt(Instructions.Addi.Mode.addi),1570 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), instruction);
1571 return;
1572 }
1573 if (math.minInt(i32) <= x and x <= math.maxInt(i32)) {
1574 const split = @bitCast(packed struct {
1575 low12: i12,
1576 up20: i20,
1577 }, @truncate(i32, x));
1578 if (split.low12 < 0) return self.fail(src, "TODO support riscv64 genSetReg i32 immediates with 12th bit set to 1", .{});
1579
1580 const lui = @bitCast(u32, Instructions.Lui{
1581 .imm = split.up20,
1582 .rd = reg.id(),
1583 });
1584 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), lui);
1585
1586 const addi = @bitCast(u32, Instructions.Addi{
1587 .mode = @enumToInt(Instructions.Addi.Mode.addi),
1588 .imm = @truncate(i12, split.low12),
1589 .rs1 = reg.id(),
1590 .rd = reg.id(),
1591 });
1592 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), addi);
1593 return;
1594 }
1595 return self.fail(src, "TODO genSetReg 33-64 bit immediates for riscv64", .{}); // glhf
1596 },
1597 .memory => |addr| {
1598 // The value is in memory at a hard-coded address.
1599 // If the type is a pointer, it means the pointer address is at this memory location.
1600 try self.genSetReg(src, reg, .{ .immediate = addr });
1601
1602 const ld = @bitCast(u32, Instructions.Load{
1603 .mode = @enumToInt(Instructions.Load.Mode.ld),
1604 .rs1 = reg.id(),
1565 .rd = reg.id(),1605 .rd = reg.id(),
1606 .offset = 0,
1566 });1607 });
15671608
1568 try self.code.resize(self.code.items.len + 4);1609 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), ld);
1569 mem.writeIntLittle(u32, self.code.items[self.code.items.len - 4 ..][0..4], full);1610 // LOAD imm=[i12 offset = 0], rs1 =
1611
1612 // return self.fail("TODO implement genSetReg memory for riscv64");
1570 },1613 },
1571 else => return self.fail(src, "TODO implement getSetReg for riscv64 MCValue {}", .{mcv}),1614 else => return self.fail(src, "TODO implement getSetReg for riscv64 {}", .{mcv}),
1572 },1615 },
1573 .x86_64 => switch (mcv) {1616 .x86_64 => switch (mcv) {
1574 .dead => unreachable,1617 .dead => unreachable,
src-self-hosted/codegen/riscv64.zig+24-12
...@@ -5,29 +5,41 @@ pub const Instructions = struct {...@@ -5,29 +5,41 @@ pub const Instructions = struct {
5 unused1: u5 = 0,5 unused1: u5 = 0,
6 unused2: u3 = 0,6 unused2: u3 = 0,
7 unused3: u5 = 0,7 unused3: u5 = 0,
8 mode: u12,8 mode: u12, //: Mode
9 };9 };
10 pub const Addi = packed struct {10 pub const Addi = packed struct {
11 pub const Mode = packed enum(u3) { addi = 0b000, slti = 0b010, sltiu = 0b011, xori = 0b100, ori = 0b110, andi = 0b111 };11 pub const Mode = packed enum(u3) { addi = 0b000, slti = 0b010, sltiu = 0b011, xori = 0b100, ori = 0b110, andi = 0b111 };
12 opcode: u7 = 0b0010011,12 opcode: u7 = 0b0010011,
13 rd: u5,13 rd: u5,
14 mode: u3,14 mode: u3, //: Mode
15 rsi1: u5,15 rs1: u5,
16 imm: u11,16 imm: i12,
17 signextend: u1 = 0,17 };
18 pub const Lui = packed struct {
19 opcode: u7 = 0b0110111,
20 rd: u5,
21 imm: i20,
22 };
23 pub const Load = packed struct {
24 pub const Mode = packed enum(u3) { ld = 0b011, lwu = 0b110 };
25 opcode: u7 = 0b0000011,
26 rd: u5,
27 mode: u3, //: Mode
28 rs1: u5,
29 offset: i12,
18 };30 };
19};31};
2032
21// zig fmt: off33// zig fmt: off
22pub const Register = enum(u8) {34pub const Register = enum(u8) {
23 // 64 bit registers35 // 64 bit registers
24 zero = 0, // zero36 zero, // zero
25 ra = 1, // return address. caller saved37 ra, // return address. caller saved
26 sp = 2, // stack pointer. callee saved.38 sp, // stack pointer. callee saved.
27 gp = 3, // global pointer39 gp, // global pointer
28 tp = 4, // thread pointer40 tp, // thread pointer
29 t0 = 5, t1 = 6, t2 = 7, // temporaries. caller saved.41 t0, t1, t2, // temporaries. caller saved.
30 s0 = 8, // s0/fp, callee saved.42 s0, // s0/fp, callee saved.
31 s1, // callee saved.43 s1, // callee saved.
32 a0, a1, // fn args/return values. caller saved.44 a0, a1, // fn args/return values. caller saved.
33 a2, a3, a4, a5, a6, a7, // fn args. caller saved.45 a2, a3, a4, a5, a6, a7, // fn args. caller saved.