authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-20 21:16:17+07:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-05 19:34:03+02:00
logb6d7f63f34bbdb7c67abecbcd47389d2a3d28743
treeaee14c6f05d58cf1777847747a97d5a3c79070e9
parent59905a62f9da9946a797cc35a2523c9929663600

stage2: sparcv9: Implement jmpl lowering


4 files changed, 35 insertions(+), 18 deletions(-)

src/arch/sparcv9/CodeGen.zig+18-2
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1//! SPARCv9 codegen.1//! SPARCv9 codegen.
2//! This lowers AIR into MIR.2//! This lowers AIR into MIR.
3//! For now this only implements medium/low code model with absolute addressing.
4//! TODO add support for other code models.
3const std = @import("std");5const std = @import("std");
4const assert = std.debug.assert;6const assert = std.debug.assert;
5const log = std.log.scoped(.codegen);7const log = std.log.scoped(.codegen);
...@@ -884,7 +886,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -884,7 +886,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
884886
885 _ = try self.addInst(.{887 _ = try self.addInst(.{
886 .tag = .jmpl,888 .tag = .jmpl,
887 .data = .{ .branch_link_indirect = .{ .reg = .o7 } },889 .data = .{
890 .arithmetic_3op = .{
891 .is_imm = false,
892 .rd = .o7,
893 .rs1 = .o7,
894 .rs2_or_imm = .{ .rs2 = .g0 },
895 },
896 },
888 });897 });
889 } else if (func_value.castTag(.extern_fn)) |_| {898 } else if (func_value.castTag(.extern_fn)) |_| {
890 return self.fail("TODO implement calling extern functions", .{});899 return self.fail("TODO implement calling extern functions", .{});
...@@ -899,7 +908,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -899,7 +908,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
899908
900 _ = try self.addInst(.{909 _ = try self.addInst(.{
901 .tag = .jmpl,910 .tag = .jmpl,
902 .data = .{ .branch_link_indirect = .{ .reg = .o7 } },911 .data = .{
912 .arithmetic_3op = .{
913 .is_imm = false,
914 .rd = .o7,
915 .rs1 = .o7,
916 .rs2_or_imm = .{ .rs2 = .g0 },
917 },
918 },
903 });919 });
904 }920 }
905921
src/arch/sparcv9/Emit.zig+3-2
...@@ -56,8 +56,7 @@ pub fn emitMir(...@@ -56,8 +56,7 @@ pub fn emitMir(
5656
57 .call => @panic("TODO implement sparcv9 call"),57 .call => @panic("TODO implement sparcv9 call"),
5858
59 .jmpl => @panic("TODO implement sparcv9 jmpl"),59 .jmpl => try emit.mirArithmetic3Op(inst),
60 .jmpl_i => @panic("TODO implement sparcv9 jmpl to reg"),
6160
62 .ldub => try emit.mirArithmetic3Op(inst),61 .ldub => try emit.mirArithmetic3Op(inst),
63 .lduh => try emit.mirArithmetic3Op(inst),62 .lduh => try emit.mirArithmetic3Op(inst),
...@@ -163,6 +162,7 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -163,6 +162,7 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
163 const imm = data.rs2_or_imm.imm;162 const imm = data.rs2_or_imm.imm;
164 switch (tag) {163 switch (tag) {
165 .add => try emit.writeInstruction(Instruction.add(i13, rs1, imm, rd)),164 .add => try emit.writeInstruction(Instruction.add(i13, rs1, imm, rd)),
165 .jmpl => try emit.writeInstruction(Instruction.jmpl(i13, rs1, imm, rd)),
166 .ldub => try emit.writeInstruction(Instruction.ldub(i13, rs1, imm, rd)),166 .ldub => try emit.writeInstruction(Instruction.ldub(i13, rs1, imm, rd)),
167 .lduh => try emit.writeInstruction(Instruction.lduh(i13, rs1, imm, rd)),167 .lduh => try emit.writeInstruction(Instruction.lduh(i13, rs1, imm, rd)),
168 .lduw => try emit.writeInstruction(Instruction.lduw(i13, rs1, imm, rd)),168 .lduw => try emit.writeInstruction(Instruction.lduw(i13, rs1, imm, rd)),
...@@ -177,6 +177,7 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -177,6 +177,7 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
177 const rs2 = data.rs2_or_imm.rs2;177 const rs2 = data.rs2_or_imm.rs2;
178 switch (tag) {178 switch (tag) {
179 .add => try emit.writeInstruction(Instruction.add(Register, rs1, rs2, rd)),179 .add => try emit.writeInstruction(Instruction.add(Register, rs1, rs2, rd)),
180 .jmpl => try emit.writeInstruction(Instruction.jmpl(Register, rs1, rs2, rd)),
180 .ldub => try emit.writeInstruction(Instruction.ldub(Register, rs1, rs2, rd)),181 .ldub => try emit.writeInstruction(Instruction.ldub(Register, rs1, rs2, rd)),
181 .lduh => try emit.writeInstruction(Instruction.lduh(Register, rs1, rs2, rd)),182 .lduh => try emit.writeInstruction(Instruction.lduh(Register, rs1, rs2, rd)),
182 .lduw => try emit.writeInstruction(Instruction.lduw(Register, rs1, rs2, rd)),183 .lduw => try emit.writeInstruction(Instruction.lduw(Register, rs1, rs2, rd)),
src/arch/sparcv9/Mir.zig+1-11
...@@ -54,11 +54,8 @@ pub const Inst = struct {...@@ -54,11 +54,8 @@ pub const Inst = struct {
54 call,54 call,
5555
56 /// A.24 Jump and Link56 /// A.24 Jump and Link
57 /// jmpl (far direct jump) uses the branch_link field,57 /// It uses the arithmetic_3op field.
58 /// while jmpl_i (indirect jump) uses the branch_link_indirect field.
59 /// Those two MIR instructions will be lowered into SPARCv9 jmpl instruction.
60 jmpl,58 jmpl,
61 jmpl_i,
6259
63 /// A.27 Load Integer60 /// A.27 Load Integer
64 /// Those uses the arithmetic_3op field.61 /// Those uses the arithmetic_3op field.
...@@ -167,13 +164,6 @@ pub const Inst = struct {...@@ -167,13 +164,6 @@ pub const Inst = struct {
167 link: Register = .o7,164 link: Register = .o7,
168 },165 },
169166
170 /// Indirect branch and link (always unconditional).
171 /// Used by e.g. jmpl_i
172 branch_link_indirect: struct {
173 reg: Register,
174 link: Register = .o7,
175 },
176
177 /// Branch with prediction.167 /// Branch with prediction.
178 /// Used by e.g. bpcc168 /// Used by e.g. bpcc
179 branch_predict: struct {169 branch_predict: struct {
src/arch/sparcv9/bits.zig+13-3
...@@ -271,6 +271,8 @@ pub const Instruction = union(enum) {...@@ -271,6 +271,8 @@ pub const Instruction = union(enum) {
271 rd: u5,271 rd: u5,
272 op3: u6,272 op3: u6,
273 rs1: u5,273 rs1: u5,
274 // See Errata 58 of SPARCv9 specification
275 // https://sparc.org/errata-for-v9/#58
274 i: u1 = 0b1,276 i: u1 = 0b1,
275 reserved: u8 = 0b00000000,277 reserved: u8 = 0b00000000,
276 rs2: u5,278 rs2: u5,
...@@ -977,10 +979,10 @@ pub const Instruction = union(enum) {...@@ -977,10 +979,10 @@ pub const Instruction = union(enum) {
977 };979 };
978 }980 }
979981
980 pub fn @"or"(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {982 pub fn jmpl(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
981 return switch (s2) {983 return switch (s2) {
982 Register => format3a(0b10, 0b00_0010, rs1, rs2, rd),984 Register => format3a(0b10, 0b11_1000, rs1, rs2, rd),
983 i13 => format3b(0b10, 0b00_0010, rs1, rs2, rd),985 i13 => format3b(0b10, 0b11_1000, rs1, rs2, rd),
984 else => unreachable,986 else => unreachable,
985 };987 };
986 }988 }
...@@ -1017,6 +1019,14 @@ pub const Instruction = union(enum) {...@@ -1017,6 +1019,14 @@ pub const Instruction = union(enum) {
1017 };1019 };
1018 }1020 }
10191021
1022 pub fn @"or"(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
1023 return switch (s2) {
1024 Register => format3a(0b10, 0b00_0010, rs1, rs2, rd),
1025 i13 => format3b(0b10, 0b00_0010, rs1, rs2, rd),
1026 else => unreachable,
1027 };
1028 }
1029
1020 pub fn nop() Instruction {1030 pub fn nop() Instruction {
1021 return sethi(0, .g0);1031 return sethi(0, .g0);
1022 }1032 }