aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKoakuma <koachan@protonmail.com>2022-06-13 00:25:24 +0700
committerKoakuma <koachan@protonmail.com>2022-06-24 21:08:41 +0700
commite7fde5f64e29ad5a730f18e82485dda00f658db8 (patch)
tree074f093ae025bcff4616ac78b8b62f097cf9adb6 /src
parentaccc3bad6377394531a9ee772e1f90018d058d06 (diff)
downloadzig-e7fde5f64e29ad5a730f18e82485dda00f658db8.tar.gz
zig-e7fde5f64e29ad5a730f18e82485dda00f658db8.zip
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)
Diffstat (limited to 'src')
-rw-r--r--src/arch/sparc64/CodeGen.zig60
-rw-r--r--src/arch/sparc64/Emit.zig4
-rw-r--r--src/arch/sparc64/Mir.zig26
-rw-r--r--src/arch/sparc64/bits.zig15
4 files changed, 98 insertions, 7 deletions
diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig
index 07f30fd40a..d0eee413ad 100644
--- a/src/arch/sparc64/CodeGen.zig
+++ b/src/arch/sparc64/CodeGen.zig
@@ -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| {
diff --git a/src/arch/sparc64/Emit.zig b/src/arch/sparc64/Emit.zig
index 5a082f163a..a5dc3370fb 100644
--- a/src/arch/sparc64/Emit.zig
+++ b/src/arch/sparc64/Emit.zig
@@ -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,
diff --git a/src/arch/sparc64/Mir.zig b/src/arch/sparc64/Mir.zig
index 14867dde30..a3c25ff3d5 100644
--- a/src/arch/sparc64/Mir.zig
+++ b/src/arch/sparc64/Mir.zig
@@ -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
diff --git a/src/arch/sparc64/bits.zig b/src/arch/sparc64/bits.zig
index 3ca67cb6a1..4c3e000438 100644
--- a/src/arch/sparc64/bits.zig
+++ b/src/arch/sparc64/bits.zig
@@ -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) {