authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-09 01:56:28-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-09 03:11:41-04:00
log21948d754002d932f27f4f07f5f61061eb49ae1c
tree86cbf1102b873252c56284114098f04d5ec71259
parenta96c08c1d174d64ec72c404d35c0de518475f07e

x86_64: implement `@abs` of 128-bit integers


1 files changed, 62 insertions(+), 27 deletions(-)

src/arch/x86_64/CodeGen.zig+62-27
...@@ -5389,37 +5389,73 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {...@@ -5389,37 +5389,73 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
5389 const result: MCValue = result: {5389 const result: MCValue = result: {
5390 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {5390 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
5391 else => null,5391 else => null,
5392 .Int => {5392 .Int => switch (ty.abiSize(mod)) {
5393 if (ty.abiSize(mod) > 8) {5393 1...8 => {
5394 return self.fail("TODO implement abs for integer abi sizes larger than 8", .{});5394 try self.spillEflagsIfOccupied();
5395 }5395 const src_mcv = try self.resolveInst(ty_op.operand);
5396 const src_mcv = try self.resolveInst(ty_op.operand);5396 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
5397 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
53985397
5399 try self.genUnOpMir(.{ ._, .neg }, ty, dst_mcv);5398 try self.genUnOpMir(.{ ._, .neg }, ty, dst_mcv);
54005399
5401 const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2);5400 const cmov_abi_size = @max(@as(u32, @intCast(ty.abiSize(mod))), 2);
5402 switch (src_mcv) {5401 switch (src_mcv) {
5403 .register => |val_reg| try self.asmCmovccRegisterRegister(5402 .register => |val_reg| try self.asmCmovccRegisterRegister(
5404 registerAlias(dst_mcv.register, cmov_abi_size),
5405 registerAlias(val_reg, cmov_abi_size),
5406 .l,
5407 ),
5408 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
5409 registerAlias(dst_mcv.register, cmov_abi_size),
5410 src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)),
5411 .l,
5412 ),
5413 else => {
5414 const val_reg = try self.copyToTmpRegister(ty, src_mcv);
5415 try self.asmCmovccRegisterRegister(
5416 registerAlias(dst_mcv.register, cmov_abi_size),5403 registerAlias(dst_mcv.register, cmov_abi_size),
5417 registerAlias(val_reg, cmov_abi_size),5404 registerAlias(val_reg, cmov_abi_size),
5418 .l,5405 .l,
5406 ),
5407 .memory, .indirect, .load_frame => try self.asmCmovccRegisterMemory(
5408 registerAlias(dst_mcv.register, cmov_abi_size),
5409 src_mcv.mem(Memory.PtrSize.fromSize(cmov_abi_size)),
5410 .l,
5411 ),
5412 else => {
5413 const val_reg = try self.copyToTmpRegister(ty, src_mcv);
5414 try self.asmCmovccRegisterRegister(
5415 registerAlias(dst_mcv.register, cmov_abi_size),
5416 registerAlias(val_reg, cmov_abi_size),
5417 .l,
5418 );
5419 },
5420 }
5421 break :result dst_mcv;
5422 },
5423 9...16 => {
5424 try self.spillEflagsIfOccupied();
5425 const src_mcv = try self.resolveInst(ty_op.operand);
5426 const dst_mcv = if (src_mcv == .register_pair and
5427 self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: {
5428 const dst_regs = try self.register_manager.allocRegs(
5429 2,
5430 .{ inst, inst },
5431 abi.RegisterClass.gp,
5419 );5432 );
5420 },5433 const dst_mcv: MCValue = .{ .register_pair = dst_regs };
5421 }5434 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
5422 break :result dst_mcv;5435 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
5436
5437 try self.genCopy(ty, dst_mcv, src_mcv);
5438 break :dst dst_mcv;
5439 };
5440 const dst_regs = dst_mcv.register_pair;
5441 const dst_locks = self.register_manager.lockRegs(2, dst_regs);
5442 defer for (dst_locks) |dst_lock| if (dst_lock) |lock|
5443 self.register_manager.unlockReg(lock);
5444
5445 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
5446 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
5447 defer self.register_manager.unlockReg(tmp_lock);
5448
5449 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_regs[1]);
5450 try self.asmRegisterImmediate(.{ ._r, .sa }, tmp_reg, Immediate.u(63));
5451 try self.asmRegisterRegister(.{ ._, .xor }, dst_regs[0], tmp_reg);
5452 try self.asmRegisterRegister(.{ ._, .xor }, dst_regs[1], tmp_reg);
5453 try self.asmRegisterRegister(.{ ._, .sub }, dst_regs[0], tmp_reg);
5454 try self.asmRegisterRegister(.{ ._, .sbb }, dst_regs[1], tmp_reg);
5455
5456 break :result dst_mcv;
5457 },
5458 else => return self.fail("TODO implement abs for {}", .{ty.fmt(mod)}),
5423 },5459 },
5424 .Float => return self.floatSign(inst, ty_op.operand, ty),5460 .Float => return self.floatSign(inst, ty_op.operand, ty),
5425 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {5461 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
...@@ -6106,8 +6142,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -6106,8 +6142,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
6106 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);6142 const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs);
6107 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);6143 defer for (dst_locks) |lock| self.register_manager.unlockReg(lock);
61086144
6109 try self.genSetReg(dst_regs[0], Type.usize, .{ .register = src_regs[0] });6145 try self.genCopy(container_ty, .{ .register_pair = dst_regs }, src_mcv);
6110 try self.genSetReg(dst_regs[1], Type.usize, .{ .register = src_regs[1] });
6111 break :dst dst_regs;6146 break :dst dst_regs;
6112 };6147 };
6113 const dst_mcv = MCValue{ .register_pair = dst_regs };6148 const dst_mcv = MCValue{ .register_pair = dst_regs };