stage2: riscv 0 argument non-nested function calls
parent
1fd99ed324
commit
0b53a2d996
|
@ -1024,8 +1024,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
try self.code.append(0xcc); // int3
|
||||
},
|
||||
.riscv64 => {
|
||||
const full = @bitCast(u32, Instructions.CallBreak{
|
||||
.mode = @enumToInt(Instructions.CallBreak.Mode.ebreak),
|
||||
const full = @bitCast(u32, instructions.CallBreak{
|
||||
.mode = @enumToInt(instructions.CallBreak.Mode.ebreak),
|
||||
});
|
||||
|
||||
mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full);
|
||||
|
@ -1092,6 +1092,31 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});
|
||||
}
|
||||
},
|
||||
.riscv64 => {
|
||||
if (info.args.len > 0) return self.fail(inst.base.src, "TODO implement fn args for {}", .{self.target.cpu.arch});
|
||||
|
||||
if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
|
||||
if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
|
||||
const func = func_val.func;
|
||||
const got = &self.bin_file.program_headers.items[self.bin_file.phdr_got_index.?];
|
||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.offset_table_index * ptr_bytes);
|
||||
|
||||
try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });
|
||||
const jalr = instructions.Jalr{
|
||||
.rd = Register.ra.id(),
|
||||
.rs1 = Register.ra.id(),
|
||||
.offset = 0,
|
||||
};
|
||||
mem.writeIntLittle(u32, try self.code.addManyAsArray(4), @bitCast(u32, jalr));
|
||||
} else {
|
||||
return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else {
|
||||
return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{});
|
||||
}
|
||||
},
|
||||
else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}),
|
||||
}
|
||||
|
||||
|
@ -1140,6 +1165,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
self.code.items[self.code.items.len - 5] = 0xe9; // jmp rel32
|
||||
try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
|
||||
},
|
||||
.riscv64 => {
|
||||
const jalr = instructions.Jalr{
|
||||
.rd = Register.zero.id(),
|
||||
.rs1 = Register.ra.id(),
|
||||
.offset = 0,
|
||||
};
|
||||
mem.writeIntLittle(u32, try self.code.addManyAsArray(4), @bitCast(u32, jalr));
|
||||
},
|
||||
else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),
|
||||
}
|
||||
return .unreach;
|
||||
|
@ -1346,8 +1379,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
}
|
||||
|
||||
if (mem.eql(u8, inst.asm_source, "ecall")) {
|
||||
const full = @bitCast(u32, Instructions.CallBreak{
|
||||
.mode = @enumToInt(Instructions.CallBreak.Mode.ecall),
|
||||
const full = @bitCast(u32, instructions.CallBreak{
|
||||
.mode = @enumToInt(instructions.CallBreak.Mode.ecall),
|
||||
});
|
||||
|
||||
mem.writeIntLittle(u32, try self.code.addManyAsArray(4), full);
|
||||
|
@ -1560,8 +1593,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
.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),
|
||||
const instruction = @bitCast(u32, instructions.Addi{
|
||||
.mode = @enumToInt(instructions.Addi.Mode.addi),
|
||||
.imm = @truncate(i12, x),
|
||||
.rs1 = Register.zero.id(),
|
||||
.rd = reg.id(),
|
||||
|
@ -1577,14 +1610,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
}, @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{
|
||||
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),
|
||||
const addi = @bitCast(u32, instructions.Addi{
|
||||
.mode = @enumToInt(instructions.Addi.Mode.addi),
|
||||
.imm = @truncate(i12, split.low12),
|
||||
.rs1 = reg.id(),
|
||||
.rd = reg.id(),
|
||||
|
@ -1592,6 +1625,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
mem.writeIntLittle(u32, try self.code.addManyAsArray(4), addi);
|
||||
return;
|
||||
}
|
||||
// li rd, immediate
|
||||
// "Myriad sequences"
|
||||
return self.fail(src, "TODO genSetReg 33-64 bit immediates for riscv64", .{}); // glhf
|
||||
},
|
||||
.memory => |addr| {
|
||||
|
@ -1599,8 +1634,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
// 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),
|
||||
const ld = @bitCast(u32, instructions.Load{
|
||||
.mode = @enumToInt(instructions.Load.Mode.ld),
|
||||
.rs1 = reg.id(),
|
||||
.rd = reg.id(),
|
||||
.offset = 0,
|
||||
|
@ -2046,6 +2081,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||
const FreeRegInt = @Type(.{ .Int = .{ .is_signed = false, .bits = callee_preserved_regs.len } });
|
||||
|
||||
fn parseRegName(name: []const u8) ?Register {
|
||||
if (@hasDecl(Register, "parseRegName")) {
|
||||
return Register.parseRegName(name);
|
||||
}
|
||||
return std.meta.stringToEnum(Register, name);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
pub const Instructions = struct {
|
||||
const std = @import("std");
|
||||
|
||||
pub const instructions = struct {
|
||||
pub const CallBreak = packed struct {
|
||||
pub const Mode = packed enum(u12) { ecall, ebreak };
|
||||
opcode: u7 = 0b1110011,
|
||||
|
@ -7,6 +9,7 @@ pub const Instructions = struct {
|
|||
unused3: u5 = 0,
|
||||
mode: u12, //: Mode
|
||||
};
|
||||
// I-type
|
||||
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,
|
||||
|
@ -20,6 +23,7 @@ pub const Instructions = struct {
|
|||
rd: u5,
|
||||
imm: i20,
|
||||
};
|
||||
// I_type
|
||||
pub const Load = packed struct {
|
||||
pub const Mode = packed enum(u3) { ld = 0b011, lwu = 0b110 };
|
||||
opcode: u7 = 0b0000011,
|
||||
|
@ -28,9 +32,24 @@ pub const Instructions = struct {
|
|||
rs1: u5,
|
||||
offset: i12,
|
||||
};
|
||||
// I-type
|
||||
pub const Jalr = packed struct {
|
||||
opcode: u7 = 0b1100111,
|
||||
rd: u5,
|
||||
mode: u3 = 0,
|
||||
rs1: u5,
|
||||
offset: i12,
|
||||
};
|
||||
};
|
||||
|
||||
// zig fmt: off
|
||||
pub const RawRegister = enum(u8) {
|
||||
x0, x1, x2, x3, x4, x5, x6, x7,
|
||||
x8, x9, x10, x11, x12, x13, x14, x15,
|
||||
x16, x17, x18, x19, x20, x21, x22, x23,
|
||||
x24, x25, x26, x27, x28, x29, x30, x31,
|
||||
};
|
||||
|
||||
pub const Register = enum(u8) {
|
||||
// 64 bit registers
|
||||
zero, // zero
|
||||
|
@ -45,6 +64,12 @@ pub const Register = enum(u8) {
|
|||
a2, a3, a4, a5, a6, a7, // fn args. caller saved.
|
||||
s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, // saved registers. callee saved.
|
||||
t3, t4, t5, t6, // caller saved
|
||||
|
||||
pub fn parseRegName(name: []const u8) ?Register {
|
||||
if(std.meta.stringToEnum(Register, name)) |reg| return reg;
|
||||
if(std.meta.stringToEnum(RawRegister, name)) |rawreg| return @intToEnum(Register, @enumToInt(rawreg));
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the bit-width of the register.
|
||||
pub fn size(self: @This()) u7 {
|
||||
|
@ -58,8 +83,7 @@ pub const Register = enum(u8) {
|
|||
return self;
|
||||
}
|
||||
|
||||
/// Returns the register's id. This is used in practically every opcode the
|
||||
/// riscv64 has.
|
||||
/// Returns the register's id.
|
||||
pub fn id(self: @This()) u5 {
|
||||
return @truncate(u5, @enumToInt(self));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue