stage2: riscv hello world
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user