| ... | ... | @@ -96,6 +96,9 @@ stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{}, |
| 96 | 96 | /// Tracks the current instruction allocated to the condition flags |
| 97 | 97 | condition_flags_inst: ?Air.Inst.Index = null, |
| 98 | 98 | |
| 99 | /// Tracks the current instruction allocated to the condition register |
| 100 | condition_register_inst: ?Air.Inst.Index = null, |
| 101 | |
| 99 | 102 | /// Offset from the stack base, representing the end of the stack frame. |
| 100 | 103 | max_end_stack: u32 = 0, |
| 101 | 104 | /// Represents the current end stack offset. If there is no existing slot |
| ... | ... | @@ -148,6 +151,13 @@ const MCValue = union(enum) { |
| 148 | 151 | cond: Instruction.Condition, |
| 149 | 152 | ccr: Instruction.CCR, |
| 150 | 153 | }, |
| 154 | /// The value is in the specified Register. The value is 1 (if |
| 155 | /// the type is u1) or true (if the type in bool) iff the |
| 156 | /// specified condition is true. |
| 157 | condition_register: struct { |
| 158 | cond: Instruction.RCondition, |
| 159 | reg: Register, |
| 160 | }, |
| 151 | 161 | |
| 152 | 162 | fn isMemory(mcv: MCValue) bool { |
| 153 | 163 | return switch (mcv) { |
| ... | ... | @@ -171,6 +181,8 @@ const MCValue = union(enum) { |
| 171 | 181 | |
| 172 | 182 | .immediate, |
| 173 | 183 | .memory, |
| 184 | .condition_flags, |
| 185 | .condition_register, |
| 174 | 186 | .ptr_stack_offset, |
| 175 | 187 | .undef, |
| 176 | 188 | => false, |
| ... | ... | @@ -1748,7 +1760,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1748 | 1760 | _ = try self.addInst(.{ |
| 1749 | 1761 | .tag = .movcc, |
| 1750 | 1762 | .data = .{ |
| 1751 | | .conditional_move = .{ |
| 1763 | .conditional_move_int = .{ |
| 1752 | 1764 | .ccr = rwo.flag.ccr, |
| 1753 | 1765 | .cond = .{ .icond = rwo.flag.cond }, |
| 1754 | 1766 | .is_imm = true, |
| ... | ... | @@ -2401,6 +2413,17 @@ fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index { |
| 2401 | 2413 | }, |
| 2402 | 2414 | }, |
| 2403 | 2415 | }), |
| 2416 | .condition_register => |reg| try self.addInst(.{ |
| 2417 | .tag = .bpr, |
| 2418 | .data = .{ |
| 2419 | .branch_predict_reg = .{ |
| 2420 | .rs1 = reg.reg, |
| 2421 | // Here we map to the opposite condition because the jump is to the false branch. |
| 2422 | .cond = reg.cond.negate(), |
| 2423 | .inst = undefined, // Will be filled by performReloc |
| 2424 | }, |
| 2425 | }, |
| 2426 | }), |
| 2404 | 2427 | else => blk: { |
| 2405 | 2428 | const reg = switch (condition) { |
| 2406 | 2429 | .register => |r| r, |
| ... | ... | @@ -2655,7 +2678,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2655 | 2678 | _ = try self.addInst(.{ |
| 2656 | 2679 | .tag = .movcc, |
| 2657 | 2680 | .data = .{ |
| 2658 | | .conditional_move = .{ |
| 2681 | .conditional_move_int = .{ |
| 2659 | 2682 | .ccr = ccr, |
| 2660 | 2683 | .cond = condition, |
| 2661 | 2684 | .is_imm = true, |
| ... | ... | @@ -2665,6 +2688,34 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2665 | 2688 | }, |
| 2666 | 2689 | }); |
| 2667 | 2690 | }, |
| 2691 | .condition_register => |op| { |
| 2692 | const condition = op.cond; |
| 2693 | const register = op.reg; |
| 2694 | |
| 2695 | _ = try self.addInst(.{ |
| 2696 | .tag = .mov, |
| 2697 | .data = .{ |
| 2698 | .arithmetic_2op = .{ |
| 2699 | .is_imm = false, |
| 2700 | .rs1 = reg, |
| 2701 | .rs2_or_imm = .{ .rs2 = .g0 }, |
| 2702 | }, |
| 2703 | }, |
| 2704 | }); |
| 2705 | |
| 2706 | _ = try self.addInst(.{ |
| 2707 | .tag = .movr, |
| 2708 | .data = .{ |
| 2709 | .conditional_move_reg = .{ |
| 2710 | .cond = condition, |
| 2711 | .is_imm = true, |
| 2712 | .rd = reg, |
| 2713 | .rs1 = register, |
| 2714 | .rs2_or_imm = .{ .imm = 1 }, |
| 2715 | }, |
| 2716 | }, |
| 2717 | }); |
| 2718 | }, |
| 2668 | 2719 | .undef => { |
| 2669 | 2720 | if (!self.wantSafety()) |
| 2670 | 2721 | 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 |
| 2832 | 2883 | } |
| 2833 | 2884 | }, |
| 2834 | 2885 | .condition_flags, |
| 2886 | .condition_register, |
| 2835 | 2887 | .immediate, |
| 2836 | 2888 | .ptr_stack_offset, |
| 2837 | 2889 | => { |
| ... | ... | @@ -2872,7 +2924,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2872 | 2924 | _ = try self.addInst(.{ |
| 2873 | 2925 | .tag = .movcc, |
| 2874 | 2926 | .data = .{ |
| 2875 | | .conditional_move = .{ |
| 2927 | .conditional_move_int = .{ |
| 2876 | 2928 | .ccr = rwo.flag.ccr, |
| 2877 | 2929 | .cond = .{ .icond = rwo.flag.cond }, |
| 2878 | 2930 | .is_imm = true, |
| ... | ... | @@ -3124,6 +3176,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 3124 | 3176 | .unreach => unreachable, |
| 3125 | 3177 | .dead => unreachable, |
| 3126 | 3178 | .condition_flags, |
| 3179 | .condition_register, |
| 3127 | 3180 | .register_with_overflow, |
| 3128 | 3181 | => unreachable, // cannot hold an address |
| 3129 | 3182 | .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 |
| 3475 | 3528 | .unreach => unreachable, |
| 3476 | 3529 | .dead => unreachable, |
| 3477 | 3530 | .condition_flags, |
| 3531 | .condition_register, |
| 3478 | 3532 | .register_with_overflow, |
| 3479 | 3533 | => unreachable, // cannot hold an address |
| 3480 | 3534 | .immediate => |imm| { |