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