aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoakuma <koachan@protonmail.com>2022-04-20 21:16:17 +0700
committerJakub Konka <kubkon@jakubkonka.com>2022-05-05 19:34:03 +0200
commitb6d7f63f34bbdb7c67abecbcd47389d2a3d28743 (patch)
treeaee14c6f05d58cf1777847747a97d5a3c79070e9
parent59905a62f9da9946a797cc35a2523c9929663600 (diff)
downloadzig-b6d7f63f34bbdb7c67abecbcd47389d2a3d28743.tar.gz
zig-b6d7f63f34bbdb7c67abecbcd47389d2a3d28743.zip
stage2: sparcv9: Implement jmpl lowering
-rw-r--r--src/arch/sparcv9/CodeGen.zig20
-rw-r--r--src/arch/sparcv9/Emit.zig5
-rw-r--r--src/arch/sparcv9/Mir.zig12
-rw-r--r--src/arch/sparcv9/bits.zig16
4 files changed, 35 insertions, 18 deletions
diff --git a/src/arch/sparcv9/CodeGen.zig b/src/arch/sparcv9/CodeGen.zig
index 7d93916fc1..ffd1dfde86 100644
--- a/src/arch/sparcv9/CodeGen.zig
+++ b/src/arch/sparcv9/CodeGen.zig
@@ -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 },
+ },
+ },
});
}
diff --git a/src/arch/sparcv9/Emit.zig b/src/arch/sparcv9/Emit.zig
index b811a3567f..a136c622e7 100644
--- a/src/arch/sparcv9/Emit.zig
+++ b/src/arch/sparcv9/Emit.zig
@@ -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)),
diff --git a/src/arch/sparcv9/Mir.zig b/src/arch/sparcv9/Mir.zig
index c79ebdcac1..21f59322cd 100644
--- a/src/arch/sparcv9/Mir.zig
+++ b/src/arch/sparcv9/Mir.zig
@@ -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 {
diff --git a/src/arch/sparcv9/bits.zig b/src/arch/sparcv9/bits.zig
index bc8b8822b7..2b50e68d32 100644
--- a/src/arch/sparcv9/bits.zig
+++ b/src/arch/sparcv9/bits.zig
@@ -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);
}