| author | |
| committer | |
| log | b6d7f63f34bbdb7c67abecbcd47389d2a3d28743 |
| tree | aee14c6f05d58cf1777847747a97d5a3c79070e9 |
| parent | 59905a62f9da9946a797cc35a2523c9929663600 |
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. | ||
| 3 | const std = @import("std"); | 5 | const std = @import("std"); |
| 4 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 5 | const log = std.log.scoped(.codegen); | 7 | const 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. |
| 884 | 886 | ||
| 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. |
| 899 | 908 | ||
| 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 | } |
| 905 | 921 |
src/arch/sparcv9/Emit.zig+3-2| ... | @@ -56,8 +56,7 @@ pub fn emitMir( | ... | @@ -56,8 +56,7 @@ pub fn emitMir( |
| 56 | 56 | ||
| 57 | .call => @panic("TODO implement sparcv9 call"), | 57 | .call => @panic("TODO implement sparcv9 call"), |
| 58 | 58 | ||
| 59 | .jmpl => @panic("TODO implement sparcv9 jmpl"), | 59 | .jmpl => try emit.mirArithmetic3Op(inst), |
| 60 | .jmpl_i => @panic("TODO implement sparcv9 jmpl to reg"), | ||
| 61 | 60 | ||
| 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, |
| 55 | 55 | ||
| 56 | /// A.24 Jump and Link | 56 | /// 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, | ||
| 62 | 59 | ||
| 63 | /// A.27 Load Integer | 60 | /// 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 | }, |
| 169 | 166 | ||
| 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. bpcc | 168 | /// 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 | } |
| 979 | 981 | ||
| 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 | } |
| 1019 | 1021 | ||
| 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 | } |