| ... | @@ -5653,10 +5653,10 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5653,10 +5653,10 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 5653 | const dst_lock = self.register_manager.lockReg(dst_reg); | 5653 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 5654 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 5654 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 5655 | | 5655 | |
| | 5656 | const wide_ty = if (src_bits <= 8) Type.u16 else src_ty; |
| 5656 | if (self.hasFeature(.bmi)) { | 5657 | if (self.hasFeature(.bmi)) { |
| 5657 | if (src_bits <= 64) { | 5658 | if (src_bits <= 64) { |
| 5658 | const extra_bits = self.regExtraBits(src_ty) + @as(u64, if (src_bits <= 8) 8 else 0); | 5659 | const extra_bits = self.regExtraBits(src_ty) + @as(u64, if (src_bits <= 8) 8 else 0); |
| 5659 | const wide_ty = if (src_bits <= 8) Type.u16 else src_ty; | | |
| 5660 | const masked_mcv = if (extra_bits > 0) masked: { | 5660 | const masked_mcv = if (extra_bits > 0) masked: { |
| 5661 | const tmp_mcv = tmp: { | 5661 | const tmp_mcv = tmp: { |
| 5662 | if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0)) | 5662 | if (src_mcv.isImmediate() or self.liveness.operandDies(inst, 0)) |
| ... | @@ -5718,7 +5718,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5718,7 +5718,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 5718 | defer self.register_manager.unlockReg(wide_lock); | 5718 | defer self.register_manager.unlockReg(wide_lock); |
| 5719 | | 5719 | |
| 5720 | try self.truncateRegister(src_ty, wide_reg); | 5720 | try self.truncateRegister(src_ty, wide_reg); |
| 5721 | try self.genBinOpMir(.{ ._, .bsf }, Type.u16, dst_mcv, .{ .register = wide_reg }); | 5721 | try self.genBinOpMir(.{ ._, .bsf }, wide_ty, dst_mcv, .{ .register = wide_reg }); |
| 5722 | } else try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv); | 5722 | } else try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv); |
| 5723 | | 5723 | |
| 5724 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); | 5724 | const cmov_abi_size = @max(@as(u32, @intCast(dst_ty.abiSize(mod))), 2); |
| ... | @@ -5890,6 +5890,7 @@ fn genByteSwap( | ... | @@ -5890,6 +5890,7 @@ fn genByteSwap( |
| 5890 | ) !MCValue { | 5890 | ) !MCValue { |
| 5891 | const mod = self.bin_file.comp.module.?; | 5891 | const mod = self.bin_file.comp.module.?; |
| 5892 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5892 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| | 5893 | const have_movbe = self.hasFeature(.movbe); |
| 5893 | | 5894 | |
| 5894 | if (src_ty.zigTypeTag(mod) == .Vector) return self.fail( | 5895 | if (src_ty.zigTypeTag(mod) == .Vector) return self.fail( |
| 5895 | "TODO implement genByteSwap for {}", | 5896 | "TODO implement genByteSwap for {}", |
| ... | @@ -5935,46 +5936,42 @@ fn genByteSwap( | ... | @@ -5935,46 +5936,42 @@ fn genByteSwap( |
| 5935 | const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs); | 5936 | const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs); |
| 5936 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); | 5937 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); |
| 5937 | | 5938 | |
| 5938 | if (src_mcv.isMemory()) { | 5939 | for (dst_regs, 0..) |dst_reg, limb_index| { |
| 5939 | try self.asmRegisterMemory( | 5940 | if (src_mcv.isMemory()) { |
| 5940 | .{ ._, .movbe }, | 5941 | try self.asmRegisterMemory( |
| 5941 | dst_regs[0], | 5942 | .{ ._, if (have_movbe) .movbe else .mov }, |
| 5942 | try src_mcv.address().offset(8).deref().mem(self, .qword), | 5943 | dst_reg.to64(), |
| 5943 | ); | 5944 | try src_mcv.address().offset(@intCast(limb_index * 8)).deref().mem(self, .qword), |
| 5944 | try self.asmRegisterMemory(.{ ._, .movbe }, dst_regs[1], try src_mcv.mem(self, .qword)); | 5945 | ); |
| 5945 | } else for (dst_regs, src_mcv.register_pair) |dst_reg, src_reg| { | 5946 | if (!have_movbe) try self.asmRegister(.{ ._, .bswap }, dst_reg.to64()); |
| 5946 | try self.asmRegisterRegister(.{ ._, .mov }, dst_reg.to64(), src_reg.to64()); | 5947 | } else { |
| 5947 | try self.asmRegister(.{ ._, .bswap }, dst_reg.to64()); | 5948 | try self.asmRegisterRegister( |
| | 5949 | .{ ._, .mov }, |
| | 5950 | dst_reg.to64(), |
| | 5951 | src_mcv.register_pair[limb_index].to64(), |
| | 5952 | ); |
| | 5953 | try self.asmRegister(.{ ._, .bswap }, dst_reg.to64()); |
| | 5954 | } |
| 5948 | } | 5955 | } |
| 5949 | return .{ .register_pair = dst_regs }; | 5956 | return .{ .register_pair = .{ dst_regs[1], dst_regs[0] } }; |
| 5950 | }, | 5957 | }, |
| 5951 | } | 5958 | } |
| 5952 | | 5959 | |
| 5953 | if (src_mcv.isRegister()) { | 5960 | const dst_mcv: MCValue = if (mem_ok and have_movbe and src_mcv.isRegister()) |
| 5954 | const dst_mcv: MCValue = if (mem_ok) | 5961 | try self.allocRegOrMem(inst, true) |
| 5955 | try self.allocRegOrMem(inst, true) | 5962 | else |
| 5956 | else | 5963 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.gp) }; |
| 5957 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.gp) }; | 5964 | if (dst_mcv.getReg()) |dst_reg| { |
| 5958 | if (dst_mcv.isRegister()) { | 5965 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register); |
| 5959 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register); | 5966 | defer self.register_manager.unlockReg(dst_lock); |
| 5960 | defer self.register_manager.unlockReg(dst_lock); | | |
| 5961 | | | |
| 5962 | try self.genSetReg(dst_mcv.register, src_ty, src_mcv); | | |
| 5963 | switch (abi_size) { | | |
| 5964 | else => unreachable, | | |
| 5965 | 2 => try self.genBinOpMir(.{ ._l, .ro }, src_ty, dst_mcv, .{ .immediate = 8 }), | | |
| 5966 | 3...8 => try self.genUnOpMir(.{ ._, .bswap }, src_ty, dst_mcv), | | |
| 5967 | } | | |
| 5968 | } else try self.genBinOpMir(.{ ._, .movbe }, src_ty, dst_mcv, src_mcv); | | |
| 5969 | return dst_mcv; | | |
| 5970 | } | | |
| 5971 | | | |
| 5972 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); | | |
| 5973 | const dst_mcv = MCValue{ .register = dst_reg }; | | |
| 5974 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | | |
| 5975 | defer self.register_manager.unlockReg(dst_lock); | | |
| 5976 | | 5967 | |
| 5977 | try self.genBinOpMir(.{ ._, .movbe }, src_ty, dst_mcv, src_mcv); | 5968 | try self.genSetReg(dst_reg, src_ty, src_mcv); |
| | 5969 | switch (abi_size) { |
| | 5970 | else => unreachable, |
| | 5971 | 2 => try self.genBinOpMir(.{ ._l, .ro }, src_ty, dst_mcv, .{ .immediate = 8 }), |
| | 5972 | 3...8 => try self.genUnOpMir(.{ ._, .bswap }, src_ty, dst_mcv), |
| | 5973 | } |
| | 5974 | } else try self.genBinOpMir(.{ ._, .movbe }, src_ty, dst_mcv, src_mcv); |
| 5978 | return dst_mcv; | 5975 | return dst_mcv; |
| 5979 | } | 5976 | } |
| 5980 | | 5977 | |