diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index ec58615773..46373bee76 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -1105,6 +1105,33 @@ impl Inst { } } + /// Choose which instruction to use for comparing two values for equality. + pub(crate) fn equals(ty: Type, from: RegMem, to: Writable) -> Inst { + match ty { + types::I8X16 => Inst::xmm_rm_r(SseOpcode::Pcmpeqb, from, to), + types::I16X8 => Inst::xmm_rm_r(SseOpcode::Pcmpeqw, from, to), + types::I32X4 => Inst::xmm_rm_r(SseOpcode::Pcmpeqd, from, to), + types::I64X2 => Inst::xmm_rm_r(SseOpcode::Pcmpeqq, from, to), + types::F32X4 => { + Inst::xmm_rm_r_imm(SseOpcode::Cmpps, from, to, FcmpImm::Equal.encode(), false) + } + types::F64X2 => { + Inst::xmm_rm_r_imm(SseOpcode::Cmppd, from, to, FcmpImm::Equal.encode(), false) + } + _ => unimplemented!("unimplemented type for Inst::equals: {}", ty), + } + } + + /// Choose which instruction to use for computing a bitwise XOR on two values. + pub(crate) fn xor(ty: Type, from: RegMem, to: Writable) -> Inst { + match ty { + types::F32X4 => Inst::xmm_rm_r(SseOpcode::Xorps, from, to), + types::F64X2 => Inst::xmm_rm_r(SseOpcode::Xorpd, from, to), + _ if ty.is_vector() => Inst::xmm_rm_r(SseOpcode::Pxor, from, to), + _ => unimplemented!("unimplemented type for Inst::xor: {}", ty), + } + } + /// Choose which instruction to use for loading a register value from memory. For loads smaller /// than 64 bits, this method expects a way to extend the value (i.e. [ExtKind::SignExtend], /// [ExtKind::ZeroExtend]); loads with no extension necessary will ignore this. diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index 30ce3915fd..8df89a6643 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -892,15 +892,18 @@ fn lower_insn_to_regs>( Opcode::Bnot => { let ty = ty.unwrap(); + let size = ty.bytes() as u8; + let src = put_input_in_reg(ctx, inputs[0]); + let dst = get_output_reg(ctx, outputs[0]); + ctx.emit(Inst::gen_move(dst, src, ty)); + if ty.is_vector() { - unimplemented!("vector bnot"); + let tmp = ctx.alloc_tmp(RegClass::V128, ty); + ctx.emit(Inst::equals(ty, RegMem::from(tmp), tmp)); + ctx.emit(Inst::xor(ty, RegMem::from(tmp), dst)); } else if ty.is_bool() { unimplemented!("bool bnot") } else { - let size = ty.bytes() as u8; - let src = put_input_in_reg(ctx, inputs[0]); - let dst = get_output_reg(ctx, outputs[0]); - ctx.emit(Inst::gen_move(dst, src, ty)); ctx.emit(Inst::not(size, dst)); } }