| ... | @@ -6164,17 +6164,16 @@ fn genByteSwap( | ... | @@ -6164,17 +6164,16 @@ fn genByteSwap( |
| 6164 | "TODO implement genByteSwap for {}", | 6164 | "TODO implement genByteSwap for {}", |
| 6165 | .{src_ty.fmt(mod)}, | 6165 | .{src_ty.fmt(mod)}, |
| 6166 | ); | 6166 | ); |
| 6167 | const abi_size: u32 = @intCast(src_ty.abiSize(mod)); | 6167 | |
| 6168 | const src_lock = switch (src_mcv) { | 6168 | const src_lock = switch (src_mcv) { |
| 6169 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), | 6169 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 6170 | else => null, | 6170 | else => null, |
| 6171 | }; | 6171 | }; |
| 6172 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); | 6172 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 6173 | | 6173 | |
| | 6174 | const abi_size: u32 = @intCast(src_ty.abiSize(mod)); |
| 6174 | switch (abi_size) { | 6175 | switch (abi_size) { |
| 6175 | else => return self.fail("TODO implement genByteSwap for {}", .{ | 6176 | 0 => unreachable, |
| 6176 | src_ty.fmt(mod), | | |
| 6177 | }), | | |
| 6178 | 1 => return if ((mem_ok or src_mcv.isRegister()) and | 6177 | 1 => return if ((mem_ok or src_mcv.isRegister()) and |
| 6179 | self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) | 6178 | self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 6180 | src_mcv | 6179 | src_mcv |
| ... | @@ -6223,6 +6222,83 @@ fn genByteSwap( | ... | @@ -6223,6 +6222,83 @@ fn genByteSwap( |
| 6223 | } | 6222 | } |
| 6224 | return .{ .register_pair = .{ dst_regs[1], dst_regs[0] } }; | 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 | const dst_mcv: MCValue = if (mem_ok and have_movbe and src_mcv.isRegister()) | 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,20 +6324,20 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void { |
| 6248 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6324 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6249 | | 6325 | |
| 6250 | const src_ty = self.typeOf(ty_op.operand); | 6326 | const src_ty = self.typeOf(ty_op.operand); |
| 6251 | const abi_size: u32 = @intCast(src_ty.abiSize(mod)); | 6327 | const src_bits: u32 = @intCast(src_ty.bitSize(mod)); |
| 6252 | const bit_size: u32 = @intCast(src_ty.bitSize(mod)); | | |
| 6253 | const src_mcv = try self.resolveInst(ty_op.operand); | 6328 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 6254 | | 6329 | |
| 6255 | const dst_mcv = try self.genByteSwap(inst, src_ty, src_mcv, true); | 6330 | const dst_mcv = try self.genByteSwap(inst, src_ty, src_mcv, true); |
| 6256 | | 6331 | try self.genShiftBinOpMir( |
| 6257 | const extra_bits = abi_size * 8 - bit_size; | 6332 | .{ ._r, switch (if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned) { |
| 6258 | const signedness: std.builtin.Signedness = | 6333 | .signed => .sa, |
| 6259 | if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned; | 6334 | .unsigned => .sh, |
| 6260 | if (extra_bits > 0) try self.genShiftBinOpMir(switch (signedness) { | 6335 | } }, |
| 6261 | .signed => .{ ._r, .sa }, | 6336 | src_ty, |
| 6262 | .unsigned => .{ ._r, .sh }, | 6337 | dst_mcv, |
| 6263 | }, src_ty, dst_mcv, Type.u8, .{ .immediate = extra_bits }); | 6338 | if (src_bits > 256) Type.u16 else Type.u8, |
| 6264 | | 6339 | .{ .immediate = src_ty.abiSize(mod) * 8 - src_bits }, |
| | 6340 | ); |
| 6265 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); | 6341 | return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none }); |
| 6266 | } | 6342 | } |
| 6267 | | 6343 | |