| ... | ... | @@ -6164,17 +6164,16 @@ fn genByteSwap( |
| 6164 | 6164 | "TODO implement genByteSwap for {}", |
| 6165 | 6165 | .{src_ty.fmt(mod)}, |
| 6166 | 6166 | ); |
| 6167 | | const abi_size: u32 = @intCast(src_ty.abiSize(mod)); |
| 6167 | |
| 6168 | 6168 | const src_lock = switch (src_mcv) { |
| 6169 | 6169 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 6170 | 6170 | else => null, |
| 6171 | 6171 | }; |
| 6172 | 6172 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 6173 | 6173 | |
| 6174 | const abi_size: u32 = @intCast(src_ty.abiSize(mod)); |
| 6174 | 6175 | switch (abi_size) { |
| 6175 | | else => return self.fail("TODO implement genByteSwap for {}", .{ |
| 6176 | | src_ty.fmt(mod), |
| 6177 | | }), |
| 6176 | 0 => unreachable, |
| 6178 | 6177 | 1 => return if ((mem_ok or src_mcv.isRegister()) and |
| 6179 | 6178 | self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 6180 | 6179 | src_mcv |
| ... | ... | @@ -6223,6 +6222,83 @@ fn genByteSwap( |
| 6223 | 6222 | } |
| 6224 | 6223 | return .{ .register_pair = .{ dst_regs[1], dst_regs[0] } }; |
| 6225 | 6224 | }, |
| 6225 | else => { |
| 6226 | const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable; |
| 6227 | |
| 6228 | const temp_regs = |
| 6229 | try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp); |
| 6230 | const temp_locks = self.register_manager.lockRegs(4, temp_regs); |
| 6231 | defer for (temp_locks) |temp_lock| if (temp_lock) |lock| |
| 6232 | self.register_manager.unlockReg(lock); |
| 6233 | |
| 6234 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 6235 | try self.asmRegisterRegister(.{ ._, .xor }, temp_regs[0].to32(), temp_regs[0].to32()); |
| 6236 | try self.asmRegisterImmediate( |
| 6237 | .{ ._, .mov }, |
| 6238 | temp_regs[1].to32(), |
| 6239 | Immediate.u(limbs_len - 1), |
| 6240 | ); |
| 6241 | |
| 6242 | const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len); |
| 6243 | try self.asmRegisterMemory( |
| 6244 | .{ ._, if (have_movbe) .movbe else .mov }, |
| 6245 | temp_regs[2].to64(), |
| 6246 | .{ |
| 6247 | .base = .{ .frame = dst_mcv.load_frame.index }, |
| 6248 | .mod = .{ .rm = .{ |
| 6249 | .size = .qword, |
| 6250 | .index = temp_regs[0].to64(), |
| 6251 | .scale = .@"8", |
| 6252 | .disp = dst_mcv.load_frame.off, |
| 6253 | } }, |
| 6254 | }, |
| 6255 | ); |
| 6256 | try self.asmRegisterMemory( |
| 6257 | .{ ._, if (have_movbe) .movbe else .mov }, |
| 6258 | temp_regs[3].to64(), |
| 6259 | .{ |
| 6260 | .base = .{ .frame = dst_mcv.load_frame.index }, |
| 6261 | .mod = .{ .rm = .{ |
| 6262 | .size = .qword, |
| 6263 | .index = temp_regs[1].to64(), |
| 6264 | .scale = .@"8", |
| 6265 | .disp = dst_mcv.load_frame.off, |
| 6266 | } }, |
| 6267 | }, |
| 6268 | ); |
| 6269 | if (!have_movbe) { |
| 6270 | try self.asmRegister(.{ ._, .bswap }, temp_regs[2].to64()); |
| 6271 | try self.asmRegister(.{ ._, .bswap }, temp_regs[3].to64()); |
| 6272 | } |
| 6273 | try self.asmMemoryRegister(.{ ._, .mov }, .{ |
| 6274 | .base = .{ .frame = dst_mcv.load_frame.index }, |
| 6275 | .mod = .{ .rm = .{ |
| 6276 | .size = .qword, |
| 6277 | .index = temp_regs[0].to64(), |
| 6278 | .scale = .@"8", |
| 6279 | .disp = dst_mcv.load_frame.off, |
| 6280 | } }, |
| 6281 | }, temp_regs[3].to64()); |
| 6282 | try self.asmMemoryRegister(.{ ._, .mov }, .{ |
| 6283 | .base = .{ .frame = dst_mcv.load_frame.index }, |
| 6284 | .mod = .{ .rm = .{ |
| 6285 | .size = .qword, |
| 6286 | .index = temp_regs[1].to64(), |
| 6287 | .scale = .@"8", |
| 6288 | .disp = dst_mcv.load_frame.off, |
| 6289 | } }, |
| 6290 | }, temp_regs[2].to64()); |
| 6291 | if (self.hasFeature(.slow_incdec)) { |
| 6292 | try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1)); |
| 6293 | try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), Immediate.u(1)); |
| 6294 | } else { |
| 6295 | try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32()); |
| 6296 | try self.asmRegister(.{ ._, .dec }, temp_regs[1].to32()); |
| 6297 | } |
| 6298 | try self.asmRegisterRegister(.{ ._, .cmp }, temp_regs[0].to32(), temp_regs[1].to32()); |
| 6299 | _ = try self.asmJccReloc(.be, loop); |
| 6300 | return dst_mcv; |
| 6301 | }, |
| 6226 | 6302 | } |
| 6227 | 6303 | |
| 6228 | 6304 | const dst_mcv: MCValue = if (mem_ok and have_movbe and src_mcv.isRegister()) |
| ... | ... | @@ -6248,20 +6324,20 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 6248 | 6324 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6249 | 6325 | |
| 6250 | 6326 | const src_ty = self.typeOf(ty_op.operand); |
| 6251 | | const abi_size: u32 = @intCast(src_ty.abiSize(mod)); |
| 6252 | | const bit_size: u32 = @intCast(src_ty.bitSize(mod)); |
| 6327 | const src_bits: u32 = @intCast(src_ty.bitSize(mod)); |
| 6253 | 6328 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 6254 | 6329 | |
| 6255 | 6330 | const dst_mcv = try self.genByteSwap(inst, src_ty, src_mcv, true); |
| 6256 | | |
| 6257 | | const extra_bits = abi_size * 8 - bit_size; |
| 6258 | | const signedness: std.builtin.Signedness = |
| 6259 | | if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned; |
| 6260 | | if (extra_bits > 0) try self.genShiftBinOpMir(switch (signedness) { |
| 6261 | | .signed => .{ ._r, .sa }, |
| 6262 | | .unsigned => .{ ._r, .sh }, |
| 6263 | | }, src_ty, dst_mcv, Type.u8, .{ .immediate = extra_bits }); |
| 6264 | | |
| 6331 | try self.genShiftBinOpMir( |
| 6332 | .{ ._r, switch (if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned) { |
| 6333 | .signed => .sa, |
| 6334 | .unsigned => .sh, |
| 6335 | } }, |
| 6336 | src_ty, |
| 6337 | dst_mcv, |
| 6338 | if (src_bits > 256) Type.u16 else Type.u8, |
| 6339 | .{ .immediate = src_ty.abiSize(mod) * 8 - src_bits }, |
| 6340 | ); |
| 6265 | 6341 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 6266 | 6342 | } |
| 6267 | 6343 | |