stage2: sparcv9: Implement jmpl lowering
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
//! SPARCv9 codegen.
|
||||
//! This lowers AIR into MIR.
|
||||
//! For now this only implements medium/low code model with absolute addressing.
|
||||
//! TODO add support for other code models.
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.codegen);
|
||||
@@ -884,7 +886,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .jmpl,
|
||||
.data = .{ .branch_link_indirect = .{ .reg = .o7 } },
|
||||
.data = .{
|
||||
.arithmetic_3op = .{
|
||||
.is_imm = false,
|
||||
.rd = .o7,
|
||||
.rs1 = .o7,
|
||||
.rs2_or_imm = .{ .rs2 = .g0 },
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |_| {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
@@ -899,7 +908,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .jmpl,
|
||||
.data = .{ .branch_link_indirect = .{ .reg = .o7 } },
|
||||
.data = .{
|
||||
.arithmetic_3op = .{
|
||||
.is_imm = false,
|
||||
.rd = .o7,
|
||||
.rs1 = .o7,
|
||||
.rs2_or_imm = .{ .rs2 = .g0 },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -56,8 +56,7 @@ pub fn emitMir(
|
||||
|
||||
.call => @panic("TODO implement sparcv9 call"),
|
||||
|
||||
.jmpl => @panic("TODO implement sparcv9 jmpl"),
|
||||
.jmpl_i => @panic("TODO implement sparcv9 jmpl to reg"),
|
||||
.jmpl => try emit.mirArithmetic3Op(inst),
|
||||
|
||||
.ldub => try emit.mirArithmetic3Op(inst),
|
||||
.lduh => try emit.mirArithmetic3Op(inst),
|
||||
@@ -163,6 +162,7 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const imm = data.rs2_or_imm.imm;
|
||||
switch (tag) {
|
||||
.add => try emit.writeInstruction(Instruction.add(i13, rs1, imm, rd)),
|
||||
.jmpl => try emit.writeInstruction(Instruction.jmpl(i13, rs1, imm, rd)),
|
||||
.ldub => try emit.writeInstruction(Instruction.ldub(i13, rs1, imm, rd)),
|
||||
.lduh => try emit.writeInstruction(Instruction.lduh(i13, rs1, imm, rd)),
|
||||
.lduw => try emit.writeInstruction(Instruction.lduw(i13, rs1, imm, rd)),
|
||||
@@ -177,6 +177,7 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const rs2 = data.rs2_or_imm.rs2;
|
||||
switch (tag) {
|
||||
.add => try emit.writeInstruction(Instruction.add(Register, rs1, rs2, rd)),
|
||||
.jmpl => try emit.writeInstruction(Instruction.jmpl(Register, rs1, rs2, rd)),
|
||||
.ldub => try emit.writeInstruction(Instruction.ldub(Register, rs1, rs2, rd)),
|
||||
.lduh => try emit.writeInstruction(Instruction.lduh(Register, rs1, rs2, rd)),
|
||||
.lduw => try emit.writeInstruction(Instruction.lduw(Register, rs1, rs2, rd)),
|
||||
|
||||
@@ -54,11 +54,8 @@ pub const Inst = struct {
|
||||
call,
|
||||
|
||||
/// A.24 Jump and Link
|
||||
/// jmpl (far direct jump) uses the branch_link field,
|
||||
/// while jmpl_i (indirect jump) uses the branch_link_indirect field.
|
||||
/// Those two MIR instructions will be lowered into SPARCv9 jmpl instruction.
|
||||
/// It uses the arithmetic_3op field.
|
||||
jmpl,
|
||||
jmpl_i,
|
||||
|
||||
/// A.27 Load Integer
|
||||
/// Those uses the arithmetic_3op field.
|
||||
@@ -167,13 +164,6 @@ pub const Inst = struct {
|
||||
link: Register = .o7,
|
||||
},
|
||||
|
||||
/// Indirect branch and link (always unconditional).
|
||||
/// Used by e.g. jmpl_i
|
||||
branch_link_indirect: struct {
|
||||
reg: Register,
|
||||
link: Register = .o7,
|
||||
},
|
||||
|
||||
/// Branch with prediction.
|
||||
/// Used by e.g. bpcc
|
||||
branch_predict: struct {
|
||||
|
||||
@@ -271,6 +271,8 @@ pub const Instruction = union(enum) {
|
||||
rd: u5,
|
||||
op3: u6,
|
||||
rs1: u5,
|
||||
// See Errata 58 of SPARCv9 specification
|
||||
// https://sparc.org/errata-for-v9/#58
|
||||
i: u1 = 0b1,
|
||||
reserved: u8 = 0b00000000,
|
||||
rs2: u5,
|
||||
@@ -977,10 +979,10 @@ pub const Instruction = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn @"or"(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
|
||||
pub fn jmpl(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
|
||||
return switch (s2) {
|
||||
Register => format3a(0b10, 0b00_0010, rs1, rs2, rd),
|
||||
i13 => format3b(0b10, 0b00_0010, rs1, rs2, rd),
|
||||
Register => format3a(0b10, 0b11_1000, rs1, rs2, rd),
|
||||
i13 => format3b(0b10, 0b11_1000, rs1, rs2, rd),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
@@ -1017,6 +1019,14 @@ pub const Instruction = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn @"or"(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
|
||||
return switch (s2) {
|
||||
Register => format3a(0b10, 0b00_0010, rs1, rs2, rd),
|
||||
i13 => format3b(0b10, 0b00_0010, rs1, rs2, rd),
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn nop() Instruction {
|
||||
return sethi(0, .g0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user