aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-10-09 01:56:28 -0400
committerJacob Young <jacobly0@users.noreply.github.com>2023-10-09 03:11:41 -0400
commit21948d754002d932f27f4f07f5f61061eb49ae1c (patch)
tree86cbf1102b873252c56284114098f04d5ec71259 /src
parenta96c08c1d174d64ec72c404d35c0de518475f07e (diff)
downloadzig-21948d754002d932f27f4f07f5f61061eb49ae1c.tar.gz
zig-21948d754002d932f27f4f07f5f61061eb49ae1c.zip
x86_64: implement `@abs` of 128-bit integers
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/CodeGen.zig89
1 files changed, 62 insertions, 27 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 341dd9edd0..70032da0d6 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -5389,37 +5389,73 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
const result: MCValue = result: {
const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
else => null,
- .Int => {
- if (ty.abiSize(mod) > 8) {
- return self.fail("TODO implement abs for integer abi sizes larger than 8", .{});
- }
- const src_mcv = try self.resolveInst(ty_op.operand);
- const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
+ .Int => switch (ty.abiSize(mod)) {
+ 1...8 => {
+ try self.spillEflagsIfOccupied();
+ const src_mcv = try self.resolveInst(ty_op.operand);
+ const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
- try self.genUnOpMir(.{ ._, .neg }, ty, dst_mcv);
+ try self.genUnOpMir(.{ ._, .neg }, ty, dst_mcv);
- const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2);
- switch (src_mcv) {
- .register => |val_reg| try self.asmCmovccRegisterRegister(
- registerAlias(dst_mcv.register, cmov_abi_size),
- registerAlias(val_reg, cmov_abi_size),
- .l,
- ),
- .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
- registerAlias(dst_mcv.register, cmov_abi_size),
- src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)),
- .l,
- ),
- else => {
- const val_reg = try self.copyToTmpRegister(ty, src_mcv);
- try self.asmCmovccRegisterRegister(
+ const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2);
+ switch (src_mcv) {
+ .register => |val_reg| try self.asmCmovccRegisterRegister(
registerAlias(dst_mcv.register, cmov_abi_size),
registerAlias(val_reg, cmov_abi_size),
.l,
+ ),
+ .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
+ registerAlias(dst_mcv.register, cmov_abi_size),
+ src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)),
+ .l,
+ ),
+ else => {
+ const val_reg = try self.copyToTmpRegister(ty, src_mcv);
+ try self.asmCmovccRegisterRegister(
+ registerAlias(dst_mcv.register, cmov_abi_size),
+ registerAlias(val_reg, cmov_abi_size),
+ .l,
+ );
+ },
+ }
+ break :result dst_mcv;
+ },
+ 9...16 => {
+ try self.spillEflagsIfOccupied();
+ const src_mcv = try self.resolveInst(ty_op.operand);
+ const dst_mcv = if (src_mcv == .register_pair and
+ self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
+ const dst_regs = try self.register_manager.allocRegs(
+ 2,
+ .{ inst, inst },
+ abi.RegisterClass.gp,
);
- },
- }
- break :result dst_mcv;
+ const dst_mcv: MCValue = .{ .register_pair = dst_regs };
+ const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
+ defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
+
+ try self.genCopy(ty, dst_mcv, src_mcv);
+ break :dst dst_mcv;
+ };
+ const dst_regs = dst_mcv.register_pair;
+ const dst_locks = self.register_manager.lockRegs(2, dst_regs);
+ defer for (dst_locks) |dst_lock| if (dst_lock) |lock|
+ self.register_manager.unlockReg(lock);
+
+ const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
+ const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
+ defer self.register_manager.unlockReg(tmp_lock);
+
+ try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_regs[1]);
+ try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, Immediate.u(63));
+ try self.asmRegisterRegister(.{ ._, .xor }, dst_regs[0], tmp_reg);
+ try self.asmRegisterRegister(.{ ._, .xor }, dst_regs[1], tmp_reg);
+ try self.asmRegisterRegister(.{ ._, .sub }, dst_regs[0], tmp_reg);
+ try self.asmRegisterRegister(.{ ._, .sbb }, dst_regs[1], tmp_reg);
+
+ break :result dst_mcv;
+ },
+ else => return self.fail("TODO implement abs for {}", .{ty.fmt(mod)}),
},
.Float => return self.floatSign(inst, ty_op.operand, ty),
.Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
@@ -6106,8 +6142,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
- try self.genSetReg(dst_regs[0], Type.usize, .{ .register = src_regs[0] });
- try self.genSetReg(dst_regs[1], Type.usize, .{ .register = src_regs[1] });
+ try self.genCopy(container_ty, .{ .register_pair = dst_regs }, src_mcv);
break :dst dst_regs;
};
const dst_mcv = MCValue{ .register_pair = dst_regs };