mirror of
https://github.com/ziglang/zig.git
synced 2026-01-06 13:33:21 +00:00
stage2: sparc64: Introduce condition_register MCValue type
Introduce condition_register MCValue type for future uses with BPr/MOVr (mostly when needing to compare a signed value with zero)
This commit is contained in:
parent
accc3bad63
commit
e7fde5f64e
@ -96,6 +96,9 @@ stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{},
|
||||
/// Tracks the current instruction allocated to the condition flags
|
||||
condition_flags_inst: ?Air.Inst.Index = null,
|
||||
|
||||
/// Tracks the current instruction allocated to the condition register
|
||||
condition_register_inst: ?Air.Inst.Index = null,
|
||||
|
||||
/// Offset from the stack base, representing the end of the stack frame.
|
||||
max_end_stack: u32 = 0,
|
||||
/// Represents the current end stack offset. If there is no existing slot
|
||||
@ -148,6 +151,13 @@ const MCValue = union(enum) {
|
||||
cond: Instruction.Condition,
|
||||
ccr: Instruction.CCR,
|
||||
},
|
||||
/// The value is in the specified Register. The value is 1 (if
|
||||
/// the type is u1) or true (if the type in bool) iff the
|
||||
/// specified condition is true.
|
||||
condition_register: struct {
|
||||
cond: Instruction.RCondition,
|
||||
reg: Register,
|
||||
},
|
||||
|
||||
fn isMemory(mcv: MCValue) bool {
|
||||
return switch (mcv) {
|
||||
@ -171,6 +181,8 @@ const MCValue = union(enum) {
|
||||
|
||||
.immediate,
|
||||
.memory,
|
||||
.condition_flags,
|
||||
.condition_register,
|
||||
.ptr_stack_offset,
|
||||
.undef,
|
||||
=> false,
|
||||
@ -1748,7 +1760,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = try self.addInst(.{
|
||||
.tag = .movcc,
|
||||
.data = .{
|
||||
.conditional_move = .{
|
||||
.conditional_move_int = .{
|
||||
.ccr = rwo.flag.ccr,
|
||||
.cond = .{ .icond = rwo.flag.cond },
|
||||
.is_imm = true,
|
||||
@ -2401,6 +2413,17 @@ fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index {
|
||||
},
|
||||
},
|
||||
}),
|
||||
.condition_register => |reg| try self.addInst(.{
|
||||
.tag = .bpr,
|
||||
.data = .{
|
||||
.branch_predict_reg = .{
|
||||
.rs1 = reg.reg,
|
||||
// Here we map to the opposite condition because the jump is to the false branch.
|
||||
.cond = reg.cond.negate(),
|
||||
.inst = undefined, // Will be filled by performReloc
|
||||
},
|
||||
},
|
||||
}),
|
||||
else => blk: {
|
||||
const reg = switch (condition) {
|
||||
.register => |r| r,
|
||||
@ -2655,7 +2678,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
||||
_ = try self.addInst(.{
|
||||
.tag = .movcc,
|
||||
.data = .{
|
||||
.conditional_move = .{
|
||||
.conditional_move_int = .{
|
||||
.ccr = ccr,
|
||||
.cond = condition,
|
||||
.is_imm = true,
|
||||
@ -2665,6 +2688,34 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
||||
},
|
||||
});
|
||||
},
|
||||
.condition_register => |op| {
|
||||
const condition = op.cond;
|
||||
const register = op.reg;
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .mov,
|
||||
.data = .{
|
||||
.arithmetic_2op = .{
|
||||
.is_imm = false,
|
||||
.rs1 = reg,
|
||||
.rs2_or_imm = .{ .rs2 = .g0 },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .movr,
|
||||
.data = .{
|
||||
.conditional_move_reg = .{
|
||||
.cond = condition,
|
||||
.is_imm = true,
|
||||
.rd = reg,
|
||||
.rs1 = register,
|
||||
.rs2_or_imm = .{ .imm = 1 },
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
.undef => {
|
||||
if (!self.wantSafety())
|
||||
return; // The already existing value will do just fine.
|
||||
@ -2832,6 +2883,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
|
||||
}
|
||||
},
|
||||
.condition_flags,
|
||||
.condition_register,
|
||||
.immediate,
|
||||
.ptr_stack_offset,
|
||||
=> {
|
||||
@ -2872,7 +2924,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
|
||||
_ = try self.addInst(.{
|
||||
.tag = .movcc,
|
||||
.data = .{
|
||||
.conditional_move = .{
|
||||
.conditional_move_int = .{
|
||||
.ccr = rwo.flag.ccr,
|
||||
.cond = .{ .icond = rwo.flag.cond },
|
||||
.is_imm = true,
|
||||
@ -3124,6 +3176,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
|
||||
.unreach => unreachable,
|
||||
.dead => unreachable,
|
||||
.condition_flags,
|
||||
.condition_register,
|
||||
.register_with_overflow,
|
||||
=> unreachable, // cannot hold an address
|
||||
.immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),
|
||||
@ -3475,6 +3528,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
|
||||
.unreach => unreachable,
|
||||
.dead => unreachable,
|
||||
.condition_flags,
|
||||
.condition_register,
|
||||
.register_with_overflow,
|
||||
=> unreachable, // cannot hold an address
|
||||
.immediate => |imm| {
|
||||
|
||||
@ -99,6 +99,8 @@ pub fn emitMir(
|
||||
|
||||
.movcc => try emit.mirConditionalMove(inst),
|
||||
|
||||
.movr => @panic("TODO implement sparc64 movr"),
|
||||
|
||||
.mulx => try emit.mirArithmetic3Op(inst),
|
||||
|
||||
.nop => try emit.mirNop(),
|
||||
@ -314,7 +316,7 @@ fn mirConditionalMove(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
|
||||
switch (tag) {
|
||||
.movcc => {
|
||||
const data = emit.mir.instructions.items(.data)[inst].conditional_move;
|
||||
const data = emit.mir.instructions.items(.data)[inst].conditional_move_int;
|
||||
if (data.is_imm) {
|
||||
try emit.writeInstruction(Instruction.movcc(
|
||||
i11,
|
||||
|
||||
@ -78,9 +78,13 @@ pub const Inst = struct {
|
||||
xnor,
|
||||
|
||||
/// A.35 Move Integer Register on Condition (MOVcc)
|
||||
/// This uses the conditional_move field.
|
||||
/// This uses the conditional_move_int field.
|
||||
movcc,
|
||||
|
||||
/// A.36 Move Integer Register on Register Condition (MOVr)
|
||||
/// This uses the conditional_move_reg field.
|
||||
movr,
|
||||
|
||||
/// A.37 Multiply and Divide (64-bit)
|
||||
/// This uses the arithmetic_3op field.
|
||||
// TODO add other operations.
|
||||
@ -230,12 +234,12 @@ pub const Inst = struct {
|
||||
inst: Index,
|
||||
},
|
||||
|
||||
/// Conditional move.
|
||||
/// Conditional move, checking the integer status code
|
||||
/// if is_imm true then it uses the imm field of rs2_or_imm,
|
||||
/// otherwise it uses rs2 field.
|
||||
///
|
||||
/// Used by e.g. movcc
|
||||
conditional_move: struct {
|
||||
conditional_move_int: struct {
|
||||
is_imm: bool,
|
||||
ccr: Instruction.CCR,
|
||||
cond: Instruction.Condition,
|
||||
@ -246,6 +250,22 @@ pub const Inst = struct {
|
||||
},
|
||||
},
|
||||
|
||||
/// Conditional move, comparing a register's content with zero
|
||||
/// if is_imm true then it uses the imm field of rs2_or_imm,
|
||||
/// otherwise it uses rs2 field.
|
||||
///
|
||||
/// Used by e.g. movr
|
||||
conditional_move_reg: struct {
|
||||
is_imm: bool,
|
||||
cond: Instruction.RCondition,
|
||||
rd: Register,
|
||||
rs1: Register,
|
||||
rs2_or_imm: union {
|
||||
rs2: Register,
|
||||
imm: i10,
|
||||
},
|
||||
},
|
||||
|
||||
/// No additional data
|
||||
///
|
||||
/// Used by e.g. flushw
|
||||
|
||||
@ -475,6 +475,21 @@ pub const Instruction = union(enum) {
|
||||
ne_zero,
|
||||
gt_zero,
|
||||
ge_zero,
|
||||
|
||||
/// Returns the condition which is true iff the given condition is
|
||||
/// false (if such a condition exists).
|
||||
pub fn negate(cond: RCondition) RCondition {
|
||||
return switch (cond) {
|
||||
.eq_zero => .ne_zero,
|
||||
.ne_zero => .eq_zero,
|
||||
.lt_zero => .ge_zero,
|
||||
.ge_zero => .lt_zero,
|
||||
.le_zero => .gt_zero,
|
||||
.gt_zero => .le_zero,
|
||||
.reserved1 => unreachable,
|
||||
.reserved2 => unreachable,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const ASI = enum(u8) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user