mirror of
https://github.com/ziglang/zig.git
synced 2025-12-22 06:03:16 +00:00
stage2: sparcv9: Implement basic stack load/stores
This commit is contained in:
parent
b6d7f63f34
commit
a00d69ea4a
@ -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.*));
|
try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*));
|
||||||
},
|
},
|
||||||
.stack_offset => |off| {
|
.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", .{});
|
return self.fail("TODO larger stack offsets", .{});
|
||||||
try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*));
|
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);
|
const reg = try self.copyToTmpRegister(ty, mcv);
|
||||||
return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
|
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", .{}),
|
.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 {
|
fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
||||||
if (typed_value.val.isUndef())
|
if (typed_value.val.isUndef())
|
||||||
return MCValue{ .undef = {} };
|
return MCValue{ .undef = {} };
|
||||||
|
|||||||
@ -76,6 +76,11 @@ pub fn emitMir(
|
|||||||
|
|
||||||
.sllx => @panic("TODO implement sparcv9 sllx"),
|
.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),
|
.sub => try emit.mirArithmetic3Op(inst),
|
||||||
|
|
||||||
.tcc => try emit.mirTrap(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)),
|
.@"or" => try emit.writeInstruction(Instruction.@"or"(i13, rs1, imm, rd)),
|
||||||
.save => try emit.writeInstruction(Instruction.save(i13, rs1, imm, rd)),
|
.save => try emit.writeInstruction(Instruction.save(i13, rs1, imm, rd)),
|
||||||
.restore => try emit.writeInstruction(Instruction.restore(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)),
|
.sub => try emit.writeInstruction(Instruction.sub(i13, rs1, imm, rd)),
|
||||||
else => unreachable,
|
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)),
|
.@"or" => try emit.writeInstruction(Instruction.@"or"(Register, rs1, rs2, rd)),
|
||||||
.save => try emit.writeInstruction(Instruction.save(Register, rs1, rs2, rd)),
|
.save => try emit.writeInstruction(Instruction.save(Register, rs1, rs2, rd)),
|
||||||
.restore => try emit.writeInstruction(Instruction.restore(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)),
|
.sub => try emit.writeInstruction(Instruction.sub(Register, rs1, rs2, rd)),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -94,6 +94,16 @@ pub const Inst = struct {
|
|||||||
// TODO add other operations.
|
// TODO add other operations.
|
||||||
sllx,
|
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
|
/// A.56 Subtract
|
||||||
/// Those uses the arithmetic_3op field.
|
/// Those uses the arithmetic_3op field.
|
||||||
// TODO add other operations.
|
// TODO add other operations.
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
const bits = @import("bits.zig");
|
const bits = @import("bits.zig");
|
||||||
const Register = bits.Register;
|
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
|
// There are no callee-preserved registers since the windowing
|
||||||
// mechanism already takes care of them.
|
// mechanism already takes care of them.
|
||||||
// We still need to preserve %o0-%o5, %g1, %g4, and %g5 before calling
|
// We still need to preserve %o0-%o5, %g1, %g4, and %g5 before calling
|
||||||
|
|||||||
@ -1059,6 +1059,38 @@ pub const Instruction = union(enum) {
|
|||||||
return format2a(0b100, imm, rd);
|
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 {
|
pub fn sub(comptime s2: type, rs1: Register, rs2: s2, rd: Register) Instruction {
|
||||||
return switch (s2) {
|
return switch (s2) {
|
||||||
Register => format3a(0b10, 0b00_0100, rs1, rs2, rd),
|
Register => format3a(0b10, 0b00_0100, rs1, rs2, rd),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user