aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKoakuma <koachan@protonmail.com>2022-04-21 04:52:50 +0700
committerJakub Konka <kubkon@jakubkonka.com>2022-05-05 19:34:04 +0200
commita00d69ea4a8c6e21ca99daa10d3b324609f3ef24 (patch)
tree6bbd589fb83ee38da6438ef2977c767693912cfa /src
parentb6d7f63f34bbdb7c67abecbcd47389d2a3d28743 (diff)
downloadzig-a00d69ea4a8c6e21ca99daa10d3b324609f3ef24.tar.gz
zig-a00d69ea4a8c6e21ca99daa10d3b324609f3ef24.zip
stage2: sparcv9: Implement basic stack load/stores
Diffstat (limited to 'src')
-rw-r--r--src/arch/sparcv9/CodeGen.zig74
-rw-r--r--src/arch/sparcv9/Emit.zig13
-rw-r--r--src/arch/sparcv9/Mir.zig10
-rw-r--r--src/arch/sparcv9/abi.zig5
-rw-r--r--src/arch/sparcv9/bits.zig32
5 files changed, 132 insertions, 2 deletions
diff --git a/src/arch/sparcv9/CodeGen.zig b/src/arch/sparcv9/CodeGen.zig
index ffd1dfde86..ca31297888 100644
--- a/src/arch/sparcv9/CodeGen.zig
+++ b/src/arch/sparcv9/CodeGen.zig
@@ -1351,7 +1351,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*));
},
.stack_offset => |off| {
- const simm13 = math.cast(u12, off) catch
+ const biased_offset = off + abi.stack_bias;
+ const simm13 = math.cast(i13, biased_offset) catch
return self.fail("TODO larger stack offsets", .{});
try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*));
},
@@ -1381,11 +1382,80 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
const reg = try self.copyToTmpRegister(ty, mcv);
return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
},
- .register => return self.fail("TODO implement storing types abi_size={}", .{abi_size}),
+ .register => |reg| {
+ const biased_offset = stack_offset + abi.stack_bias;
+ const simm13 = math.cast(i13, biased_offset) catch
+ return self.fail("TODO larger stack offsets", .{});
+ return self.genStore(reg, .sp, i13, simm13, abi_size);
+ },
.memory, .stack_offset => return self.fail("TODO implement memcpy", .{}),
}
}
+fn genStore(self: *Self, value_reg: Register, addr_reg: Register, comptime off_type: type, off: off_type, abi_size: u64) !void {
+ assert(off_type == Register or off_type == i13);
+
+ const is_imm = (off_type == i13);
+ const rs2_or_imm = if (is_imm) .{ .imm = off } else .{ .rs2 = off };
+
+ switch (abi_size) {
+ 1 => {
+ _ = try self.addInst(.{
+ .tag = .stb,
+ .data = .{
+ .arithmetic_3op = .{
+ .is_imm = is_imm,
+ .rd = value_reg,
+ .rs1 = addr_reg,
+ .rs2_or_imm = rs2_or_imm,
+ },
+ },
+ });
+ },
+ 2 => {
+ _ = try self.addInst(.{
+ .tag = .sth,
+ .data = .{
+ .arithmetic_3op = .{
+ .is_imm = is_imm,
+ .rd = value_reg,
+ .rs1 = addr_reg,
+ .rs2_or_imm = rs2_or_imm,
+ },
+ },
+ });
+ },
+ 4 => {
+ _ = try self.addInst(.{
+ .tag = .stw,
+ .data = .{
+ .arithmetic_3op = .{
+ .is_imm = is_imm,
+ .rd = value_reg,
+ .rs1 = addr_reg,
+ .rs2_or_imm = rs2_or_imm,
+ },
+ },
+ });
+ },
+ 8 => {
+ _ = try self.addInst(.{
+ .tag = .stx,
+ .data = .{
+ .arithmetic_3op = .{
+ .is_imm = is_imm,
+ .rd = value_reg,
+ .rs1 = addr_reg,
+ .rs2_or_imm = rs2_or_imm,
+ },
+ },
+ });
+ },
+ 3, 5, 6, 7 => return self.fail("TODO: genLoad for more abi_sizes", .{}),
+ else => unreachable,
+ }
+}
+
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
if (typed_value.val.isUndef())
return MCValue{ .undef = {} };
diff --git a/src/arch/sparcv9/Emit.zig b/src/arch/sparcv9/Emit.zig
index a136c622e7..91dcb4fd5f 100644
--- a/src/arch/sparcv9/Emit.zig
+++ b/src/arch/sparcv9/Emit.zig
@@ -76,6 +76,11 @@ pub fn emitMir(
.sllx => @panic("TODO implement sparcv9 sllx"),
+ .stb => try emit.mirArithmetic3Op(inst),
+ .sth => try emit.mirArithmetic3Op(inst),
+ .stw => try emit.mirArithmetic3Op(inst),
+ .stx => try emit.mirArithmetic3Op(inst),
+
.sub => try emit.mirArithmetic3Op(inst),
.tcc => try emit.mirTrap(inst),
@@ -170,6 +175,10 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
.@"or" => try emit.writeInstruction(Instruction.@"or"(i13, rs1, imm, rd)),
.save => try emit.writeInstruction(Instruction.save(i13, rs1, imm, rd)),
.restore => try emit.writeInstruction(Instruction.restore(i13, rs1, imm, rd)),
+ .stb => try emit.writeInstruction(Instruction.stb(i13, rs1, imm, rd)),
+ .sth => try emit.writeInstruction(Instruction.sth(i13, rs1, imm, rd)),
+ .stw => try emit.writeInstruction(Instruction.stw(i13, rs1, imm, rd)),
+ .stx => try emit.writeInstruction(Instruction.stx(i13, rs1, imm, rd)),
.sub => try emit.writeInstruction(Instruction.sub(i13, rs1, imm, rd)),
else => unreachable,
}
@@ -185,6 +194,10 @@ fn mirArithmetic3Op(emit: *Emit, inst: Mir.Inst.Index) !void {
.@"or" => try emit.writeInstruction(Instruction.@"or"(Register, rs1, rs2, rd)),
.save => try emit.writeInstruction(Instruction.save(Register, rs1, rs2, rd)),
.restore => try emit.writeInstruction(Instruction.restore(Register, rs1, rs2, rd)),
+ .stb => try emit.writeInstruction(Instruction.stb(Register, rs1, rs2, rd)),
+ .sth => try emit.writeInstruction(Instruction.sth(Register, rs1, rs2, rd)),
+ .stw => try emit.writeInstruction(Instruction.stw(Register, rs1, rs2, rd)),
+ .stx => try emit.writeInstruction(Instruction.stx(Register, rs1, rs2, rd)),
.sub => try emit.writeInstruction(Instruction.sub(Register, rs1, rs2, rd)),
else => unreachable,
}
diff --git a/src/arch/sparcv9/Mir.zig b/src/arch/sparcv9/Mir.zig
index 21f59322cd..54f147f415 100644
--- a/src/arch/sparcv9/Mir.zig
+++ b/src/arch/sparcv9/Mir.zig
@@ -94,6 +94,16 @@ pub const Inst = struct {
// TODO add other operations.
sllx,
+ /// A.54 Store Integer
+ /// This uses the arithmetic_3op field.
+ /// Note that the std variant of this instruction is deprecated, so do not emit
+ /// it unless specifically requested (e.g. by inline assembly).
+ // TODO add other operations.
+ stb,
+ sth,
+ stw,
+ stx,
+
/// A.56 Subtract
/// Those uses the arithmetic_3op field.
// TODO add other operations.
diff --git a/src/arch/sparcv9/abi.zig b/src/arch/sparcv9/abi.zig
index 4cb10a99ea..ae72f270be 100644
--- a/src/arch/sparcv9/abi.zig
+++ b/src/arch/sparcv9/abi.zig
@@ -1,6 +1,11 @@
const bits = @import("bits.zig");
const Register = bits.Register;
+// On SPARCv9, %sp points to top of stack + stack bias,
+// and %fp points to top of previous frame + stack bias.
+// See: Registers and the Stack Frame, page 3P-8, SCD 2.4.1.
+pub const stack_bias = 2047;
+
// There are no callee-preserved registers since the windowing
// mechanism already takes care of them.
// We still need to preserve %o0-%o5, %g1, %g4, and %g5 before calling
diff --git a/src/arch/sparcv9/bits.zig b/src/arch/sparcv9/bits.zig
index 2b50e68d32..e66b24f617 100644
--- a/src/arch/sparcv9/bits.zig
+++ b/src/arch/sparcv9/bits.zig
@@ -1059,6 +1059,38 @@ pub const Instruction = union(enum) {
return format2a(0b100, imm, rd);
}
+ pub fn stb(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3a(0b11, 0b00_0101, rs1, rs2, rd),
+ i13 => format3b(0b11, 0b00_0101, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
+ pub fn sth(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3a(0b11, 0b00_0110, rs1, rs2, rd),
+ i13 => format3b(0b11, 0b00_0110, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
+ pub fn stw(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3a(0b11, 0b00_0100, rs1, rs2, rd),
+ i13 => format3b(0b11, 0b00_0100, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
+ pub fn stx(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
+ return switch (s2) {
+ Register => format3a(0b11, 0b00_1110, rs1, rs2, rd),
+ i13 => format3b(0b11, 0b00_1110, rs1, rs2, rd),
+ else => unreachable,
+ };
+ }
+
pub fn sub(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
return switch (s2) {
Register => format3a(0b10, 0b00_0100, rs1, rs2, rd),