authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-08 06:03:38+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-12 05:25:07+01:00
logc6b3db8910dc250a32aef49a2d5951bd0c24e5db
tree0ce12431eefad8a9727c4ce912c4e4010dd823af
parent7c9a96111c373599a55c9a04ea04f56b1dd76318

x86_64: implement `@abs` of big integers


1 files changed, 72 insertions(+), 20 deletions(-)

src/arch/x86_64/CodeGen.zig+72-20
......@@ -3919,7 +3919,7 @@ fn genSetFrameTruncatedOverflowCompare(
39193919 const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_bits);
39203920
39213921 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);
39233923 const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);
39243924 defer for (temp_locks) |lock| self.register_manager.unlockReg(lock);
39253925
......@@ -4000,11 +4000,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
40004000 const lhs_mcv = try self.resolveInst(bin_op.lhs);
40014001 const rhs_mcv = try self.resolveInst(bin_op.rhs);
40024002
4003 const temp_regs = try self.register_manager.allocRegs(
4004 4,
4005 .{ null, null, null, null },
4006 abi.RegisterClass.gp,
4007 );
4003 const temp_regs =
4004 try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp);
40084005 const temp_locks = self.register_manager.lockRegsAssumeUnused(4, temp_regs);
40094006 defer for (temp_locks) |lock| self.register_manager.unlockReg(lock);
40104007
......@@ -6582,6 +6579,7 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
65826579 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
65836580 else => null,
65846581 .Int => switch (ty.abiSize(mod)) {
6582 0 => unreachable,
65856583 1...8 => {
65866584 try self.spillEflagsIfOccupied();
65876585 const src_mcv = try self.resolveInst(ty_op.operand);
......@@ -6647,7 +6645,64 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
66476645
66486646 break :result dst_mcv;
66496647 },
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 },
66516706 },
66526707 .Float => return self.floatSign(inst, ty_op.operand, ty),
66536708 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
......@@ -7435,7 +7490,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
74357490 const dst_regs: [2]Register = if (field_rc.supersetOf(container_rc) and
74367491 self.reuseOperand(inst, operand, 0, src_mcv)) src_regs else dst: {
74377492 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);
74397494 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
74407495 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
74417496
......@@ -8343,11 +8398,8 @@ fn genMulDivBinOp(
83438398 .{},
83448399 );
83458400
8346 const temp_regs = try self.register_manager.allocRegs(
8347 4,
8348 .{ null, null, null, null },
8349 abi.RegisterClass.gp,
8350 );
8401 const temp_regs =
8402 try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp);
83518403 const temp_locks = self.register_manager.lockRegs(4, temp_regs);
83528404 defer for (temp_locks) |temp_lock| if (temp_lock) |lock|
83538405 self.register_manager.unlockReg(lock);
......@@ -8909,14 +8961,14 @@ fn genBinOp(
89098961 const locks = self.register_manager.lockRegsAssumeUnused(2, lhs_regs);
89108962 break :locks .{ locks[0], locks[1] };
89118963 },
8912 else => .{ null, null },
8964 else => .{null} ** 2,
89138965 };
89148966 defer for (lhs_locks) |lhs_lock| if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
89158967
89168968 const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) {
89178969 .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), null },
89188970 .register_pair => |rhs_regs| self.register_manager.lockRegs(2, rhs_regs),
8919 else => .{ null, null },
8971 else => .{null} ** 2,
89208972 };
89218973 defer for (rhs_locks) |rhs_lock| if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
89228974
......@@ -8949,7 +9001,7 @@ fn genBinOp(
89499001 const dst_locks: [2]?RegisterLock = switch (dst_mcv) {
89509002 .register => |dst_reg| .{ self.register_manager.lockReg(dst_reg), null },
89519003 .register_pair => |dst_regs| self.register_manager.lockRegs(2, dst_regs),
8952 else => .{ null, null },
9004 else => .{null} ** 2,
89539005 };
89549006 defer for (dst_locks) |dst_lock| if (dst_lock) |lock| self.register_manager.unlockReg(lock);
89559007
......@@ -8965,7 +9017,7 @@ fn genBinOp(
89659017 const src_locks: [2]?RegisterLock = switch (src_mcv) {
89669018 .register => |src_reg| .{ self.register_manager.lockReg(src_reg), null },
89679019 .register_pair => |src_regs| self.register_manager.lockRegs(2, src_regs),
8968 else => .{ null, null },
9020 else => .{null} ** 2,
89699021 };
89709022 defer for (src_locks) |src_lock| if (src_lock) |lock| self.register_manager.unlockReg(lock);
89719023
......@@ -9025,7 +9077,7 @@ fn genBinOp(
90259077 else => dst: {
90269078 const dst_regs = try self.register_manager.allocRegs(
90279079 2,
9028 .{ null, null },
9080 .{null} ** 2,
90299081 abi.RegisterClass.gp,
90309082 );
90319083 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 {
1163111683
1163211684 const regs = try self.register_manager.allocRegs(
1163311685 2,
11634 .{ null, null },
11686 .{null} ** 2,
1163511687 abi.RegisterClass.gp,
1163611688 );
1163711689 const acc_reg = regs[0].to64();
......@@ -16298,7 +16350,7 @@ fn airVaArg(self: *Self, inst: Air.Inst.Index) !void {
1629816350 try self.spillEflagsIfOccupied();
1629916351
1630016352 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);
1630216354 const offset_reg = tmp_regs[0].to32();
1630316355 const addr_reg = tmp_regs[1].to64();
1630416356 const tmp_locks = self.register_manager.lockRegsAssumeUnused(2, tmp_regs);