| ... | @@ -3919,7 +3919,7 @@ fn genSetFrameTruncatedOverflowCompare( | ... | @@ -3919,7 +3919,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3919 | const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_bits); | 3919 | const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_bits); |
| 3920 | | 3920 | |
| 3921 | const temp_regs = | 3921 | const temp_regs = |
| 3922 | try self.register_manager.allocRegs(3, .{ null, null, null }, abi.RegisterClass.gp); | 3922 | try self.register_manager.allocRegs(3, .{null} ** 3, abi.RegisterClass.gp); |
| 3923 | const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); | 3923 | const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); |
| 3924 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); | 3924 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); |
| 3925 | | 3925 | |
| ... | @@ -4000,11 +4000,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4000,11 +4000,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 4000 | const lhs_mcv = try self.resolveInst(bin_op.lhs); | 4000 | const lhs_mcv = try self.resolveInst(bin_op.lhs); |
| 4001 | const rhs_mcv = try self.resolveInst(bin_op.rhs); | 4001 | const rhs_mcv = try self.resolveInst(bin_op.rhs); |
| 4002 | | 4002 | |
| 4003 | const temp_regs = try self.register_manager.allocRegs( | 4003 | const temp_regs = |
| 4004 | 4, | 4004 | try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp); |
| 4005 | .{ null, null, null, null }, | | |
| 4006 | abi.RegisterClass.gp, | | |
| 4007 | ); | | |
| 4008 | const temp_locks = self.register_manager.lockRegsAssumeUnused(4, temp_regs); | 4005 | const temp_locks = self.register_manager.lockRegsAssumeUnused(4, temp_regs); |
| 4009 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); | 4006 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); |
| 4010 | | 4007 | |
| ... | @@ -6582,6 +6579,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6582,6 +6579,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 6582 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { | 6579 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 6583 | else => null, | 6580 | else => null, |
| 6584 | .Int => switch (ty.abiSize(mod)) { | 6581 | .Int => switch (ty.abiSize(mod)) { |
| | 6582 | 0 => unreachable, |
| 6585 | 1...8 => { | 6583 | 1...8 => { |
| 6586 | try self.spillEflagsIfOccupied(); | 6584 | try self.spillEflagsIfOccupied(); |
| 6587 | const src_mcv = try self.resolveInst(ty_op.operand); | 6585 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | @@ -6647,7 +6645,64 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6647,7 +6645,64 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void { |
| 6647 | | 6645 | |
| 6648 | break :result dst_mcv; | 6646 | break :result dst_mcv; |
| 6649 | }, | 6647 | }, |
| 6650 | else => return self.fail("TODO implement abs for {}", .{ty.fmt(mod)}), | 6648 | else => { |
| | 6649 | const abi_size: u31 = @intCast(ty.abiSize(mod)); |
| | 6650 | const limb_len = std.math.divCeil(u31, abi_size, 8) catch unreachable; |
| | 6651 | |
| | 6652 | const tmp_regs = |
| | 6653 | try self.register_manager.allocRegs(3, .{null} ** 3, abi.RegisterClass.gp); |
| | 6654 | const tmp_locks = self.register_manager.lockRegsAssumeUnused(3, tmp_regs); |
| | 6655 | defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock); |
| | 6656 | |
| | 6657 | try self.spillEflagsIfOccupied(); |
| | 6658 | const src_mcv = try self.resolveInst(ty_op.operand); |
| | 6659 | const dst_mcv = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| | 6660 | src_mcv |
| | 6661 | else |
| | 6662 | try self.allocRegOrMem(inst, false); |
| | 6663 | |
| | 6664 | try self.asmMemoryImmediate( |
| | 6665 | .{ ._, .cmp }, |
| | 6666 | try dst_mcv.address().offset((limb_len - 1) * 8).deref().mem(self, .qword), |
| | 6667 | Immediate.u(0), |
| | 6668 | ); |
| | 6669 | const positive = try self.asmJccReloc(.ns, undefined); |
| | 6670 | |
| | 6671 | try self.asmRegisterRegister(.{ ._, .xor }, tmp_regs[0].to32(), tmp_regs[0].to32()); |
| | 6672 | try self.asmRegisterRegister(.{ ._, .xor }, tmp_regs[1].to8(), tmp_regs[1].to8()); |
| | 6673 | |
| | 6674 | const neg_loop: Mir.Inst.Index = @intCast(self.mir_instructions.len); |
| | 6675 | try self.asmRegisterRegister(.{ ._, .xor }, tmp_regs[2].to32(), tmp_regs[2].to32()); |
| | 6676 | try self.asmRegisterImmediate(.{ ._r, .sh }, tmp_regs[1].to8(), Immediate.u(1)); |
| | 6677 | try self.asmRegisterMemory(.{ ._, .sbb }, tmp_regs[2].to64(), .{ |
| | 6678 | .base = .{ .frame = dst_mcv.load_frame.index }, |
| | 6679 | .mod = .{ .rm = .{ |
| | 6680 | .size = .qword, |
| | 6681 | .index = tmp_regs[0].to64(), |
| | 6682 | .scale = .@"8", |
| | 6683 | } }, |
| | 6684 | }); |
| | 6685 | try self.asmSetccRegister(.c, tmp_regs[1].to8()); |
| | 6686 | try self.asmMemoryRegister(.{ ._, .mov }, .{ |
| | 6687 | .base = .{ .frame = dst_mcv.load_frame.index }, |
| | 6688 | .mod = .{ .rm = .{ |
| | 6689 | .size = .qword, |
| | 6690 | .index = tmp_regs[0].to64(), |
| | 6691 | .scale = .@"8", |
| | 6692 | } }, |
| | 6693 | }, tmp_regs[2].to64()); |
| | 6694 | |
| | 6695 | if (self.hasFeature(.slow_incdec)) { |
| | 6696 | try self.asmRegisterImmediate(.{ ._, .add }, tmp_regs[0].to32(), Immediate.u(1)); |
| | 6697 | } else { |
| | 6698 | try self.asmRegister(.{ ._, .inc }, tmp_regs[0].to32()); |
| | 6699 | } |
| | 6700 | try self.asmRegisterImmediate(.{ ._, .cmp }, tmp_regs[0].to32(), Immediate.u(limb_len)); |
| | 6701 | _ = try self.asmJccReloc(.b, neg_loop); |
| | 6702 | |
| | 6703 | try self.performReloc(positive); |
| | 6704 | break :result dst_mcv; |
| | 6705 | }, |
| 6651 | }, | 6706 | }, |
| 6652 | .Float => return self.floatSign(inst, ty_op.operand, ty), | 6707 | .Float => return self.floatSign(inst, ty_op.operand, ty), |
| 6653 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { | 6708 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| ... | @@ -7435,7 +7490,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7435,7 +7490,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7435 | const dst_regs: [2]Register = if (field_rc.supersetOf(container_rc) and | 7490 | const dst_regs: [2]Register = if (field_rc.supersetOf(container_rc) and |
| 7436 | self.reuseOperand(inst, operand, 0, src_mcv)) src_regs else dst: { | 7491 | self.reuseOperand(inst, operand, 0, src_mcv)) src_regs else dst: { |
| 7437 | const dst_regs = | 7492 | const dst_regs = |
| 7438 | try self.register_manager.allocRegs(2, .{ null, null }, field_rc); | 7493 | try self.register_manager.allocRegs(2, .{null} ** 2, field_rc); |
| 7439 | const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs); | 7494 | const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs); |
| 7440 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); | 7495 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); |
| 7441 | | 7496 | |
| ... | @@ -8343,11 +8398,8 @@ fn genMulDivBinOp( | ... | @@ -8343,11 +8398,8 @@ fn genMulDivBinOp( |
| 8343 | .{}, | 8398 | .{}, |
| 8344 | ); | 8399 | ); |
| 8345 | | 8400 | |
| 8346 | const temp_regs = try self.register_manager.allocRegs( | 8401 | const temp_regs = |
| 8347 | 4, | 8402 | try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp); |
| 8348 | .{ null, null, null, null }, | | |
| 8349 | abi.RegisterClass.gp, | | |
| 8350 | ); | | |
| 8351 | const temp_locks = self.register_manager.lockRegs(4, temp_regs); | 8403 | const temp_locks = self.register_manager.lockRegs(4, temp_regs); |
| 8352 | defer for (temp_locks) |temp_lock| if (temp_lock) |lock| | 8404 | defer for (temp_locks) |temp_lock| if (temp_lock) |lock| |
| 8353 | self.register_manager.unlockReg(lock); | 8405 | self.register_manager.unlockReg(lock); |
| ... | @@ -8909,14 +8961,14 @@ fn genBinOp( | ... | @@ -8909,14 +8961,14 @@ fn genBinOp( |
| 8909 | const locks = self.register_manager.lockRegsAssumeUnused(2, lhs_regs); | 8961 | const locks = self.register_manager.lockRegsAssumeUnused(2, lhs_regs); |
| 8910 | break :locks .{ locks[0], locks[1] }; | 8962 | break :locks .{ locks[0], locks[1] }; |
| 8911 | }, | 8963 | }, |
| 8912 | else => .{ null, null }, | 8964 | else => .{null} ** 2, |
| 8913 | }; | 8965 | }; |
| 8914 | defer for (lhs_locks) |lhs_lock| if (lhs_lock) |lock| self.register_manager.unlockReg(lock); | 8966 | defer for (lhs_locks) |lhs_lock| if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 8915 | | 8967 | |
| 8916 | const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) { | 8968 | const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) { |
| 8917 | .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), null }, | 8969 | .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), null }, |
| 8918 | .register_pair => |rhs_regs| self.register_manager.lockRegs(2, rhs_regs), | 8970 | .register_pair => |rhs_regs| self.register_manager.lockRegs(2, rhs_regs), |
| 8919 | else => .{ null, null }, | 8971 | else => .{null} ** 2, |
| 8920 | }; | 8972 | }; |
| 8921 | defer for (rhs_locks) |rhs_lock| if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | 8973 | defer for (rhs_locks) |rhs_lock| if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 8922 | | 8974 | |
| ... | @@ -8949,7 +9001,7 @@ fn genBinOp( | ... | @@ -8949,7 +9001,7 @@ fn genBinOp( |
| 8949 | const dst_locks: [2]?RegisterLock = switch (dst_mcv) { | 9001 | const dst_locks: [2]?RegisterLock = switch (dst_mcv) { |
| 8950 | .register => |dst_reg| .{ self.register_manager.lockReg(dst_reg), null }, | 9002 | .register => |dst_reg| .{ self.register_manager.lockReg(dst_reg), null }, |
| 8951 | .register_pair => |dst_regs| self.register_manager.lockRegs(2, dst_regs), | 9003 | .register_pair => |dst_regs| self.register_manager.lockRegs(2, dst_regs), |
| 8952 | else => .{ null, null }, | 9004 | else => .{null} ** 2, |
| 8953 | }; | 9005 | }; |
| 8954 | defer for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 9006 | defer for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 8955 | | 9007 | |
| ... | @@ -8965,7 +9017,7 @@ fn genBinOp( | ... | @@ -8965,7 +9017,7 @@ fn genBinOp( |
| 8965 | const src_locks: [2]?RegisterLock = switch (src_mcv) { | 9017 | const src_locks: [2]?RegisterLock = switch (src_mcv) { |
| 8966 | .register => |src_reg| .{ self.register_manager.lockReg(src_reg), null }, | 9018 | .register => |src_reg| .{ self.register_manager.lockReg(src_reg), null }, |
| 8967 | .register_pair => |src_regs| self.register_manager.lockRegs(2, src_regs), | 9019 | .register_pair => |src_regs| self.register_manager.lockRegs(2, src_regs), |
| 8968 | else => .{ null, null }, | 9020 | else => .{null} ** 2, |
| 8969 | }; | 9021 | }; |
| 8970 | defer for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock); | 9022 | defer for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 8971 | | 9023 | |
| ... | @@ -9025,7 +9077,7 @@ fn genBinOp( | ... | @@ -9025,7 +9077,7 @@ fn genBinOp( |
| 9025 | else => dst: { | 9077 | else => dst: { |
| 9026 | const dst_regs = try self.register_manager.allocRegs( | 9078 | const dst_regs = try self.register_manager.allocRegs( |
| 9027 | 2, | 9079 | 2, |
| 9028 | .{ null, null }, | 9080 | .{null} ** 2, |
| 9029 | abi.RegisterClass.gp, | 9081 | abi.RegisterClass.gp, |
| 9030 | ); | 9082 | ); |
| 9031 | const dst_regs_locks = self.register_manager.lockRegs(2, dst_regs); | 9083 | const dst_regs_locks = self.register_manager.lockRegs(2, dst_regs); |
| ... | @@ -11631,7 +11683,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -11631,7 +11683,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 11631 | | 11683 | |
| 11632 | const regs = try self.register_manager.allocRegs( | 11684 | const regs = try self.register_manager.allocRegs( |
| 11633 | 2, | 11685 | 2, |
| 11634 | .{ null, null }, | 11686 | .{null} ** 2, |
| 11635 | abi.RegisterClass.gp, | 11687 | abi.RegisterClass.gp, |
| 11636 | ); | 11688 | ); |
| 11637 | const acc_reg = regs[0].to64(); | 11689 | const acc_reg = regs[0].to64(); |
| ... | @@ -16298,7 +16350,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -16298,7 +16350,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void { |
| 16298 | try self.spillEflagsIfOccupied(); | 16350 | try self.spillEflagsIfOccupied(); |
| 16299 | | 16351 | |
| 16300 | const tmp_regs = | 16352 | const tmp_regs = |
| 16301 | try self.register_manager.allocRegs(2, .{ null, null }, abi.RegisterClass.gp); | 16353 | try self.register_manager.allocRegs(2, .{null} ** 2, abi.RegisterClass.gp); |
| 16302 | const offset_reg = tmp_regs[0].to32(); | 16354 | const offset_reg = tmp_regs[0].to32(); |
| 16303 | const addr_reg = tmp_regs[1].to64(); | 16355 | const addr_reg = tmp_regs[1].to64(); |
| 16304 | const tmp_locks = self.register_manager.lockRegsAssumeUnused(2, tmp_regs); | 16356 | const tmp_locks = self.register_manager.lockRegsAssumeUnused(2, tmp_regs); |