diff options
| author | Koakuma <koachan@protonmail.com> | 2022-06-13 00:25:24 +0700 |
|---|---|---|
| committer | Koakuma <koachan@protonmail.com> | 2022-06-24 21:08:41 +0700 |
| commit | e7fde5f64e29ad5a730f18e82485dda00f658db8 (patch) | |
| tree | 074f093ae025bcff4616ac78b8b62f097cf9adb6 /src | |
| parent | accc3bad6377394531a9ee772e1f90018d058d06 (diff) | |
| download | zig-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.zig | 60 | ||||
| -rw-r--r-- | src/arch/sparc64/Emit.zig | 4 | ||||
| -rw-r--r-- | src/arch/sparc64/Mir.zig | 26 | ||||
| -rw-r--r-- | src/arch/sparc64/bits.zig | 15 |
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) { |
