[JIT, x64] Add and implement OPCODE_AND_NOT
Verified the x64 implementation using `xenia-cpu-ppc-tests`.
This commit is contained in:
@@ -2627,6 +2627,80 @@ struct AND_V128 : Sequence<AND_V128, I<OPCODE_AND, V128Op, V128Op, V128Op>> {
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(OPCODE_AND, AND_I8, AND_I16, AND_I32, AND_I64, AND_V128);
|
||||
|
||||
// ============================================================================
|
||||
// OPCODE_AND_NOT
|
||||
// ============================================================================
|
||||
template <typename SEQ, typename REG, typename ARGS>
|
||||
void EmitAndNotXX(X64Emitter& e, const ARGS& i) {
|
||||
if (i.src1.is_constant) {
|
||||
if (i.src2.is_constant) {
|
||||
// Both constants.
|
||||
e.mov(i.dest, i.src1.constant() & ~i.src2.constant());
|
||||
} else {
|
||||
// src1 constant.
|
||||
e.mov(i.dest, i.src2.constant());
|
||||
e.not_(i.dest);
|
||||
e.and_(i.dest, i.src1);
|
||||
}
|
||||
} else if (i.src2.is_constant) {
|
||||
// src2 constant.
|
||||
if (i.dest == i.src1) {
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, ~i.src2.constant());
|
||||
e.and_(i.dest, temp);
|
||||
} else {
|
||||
e.mov(i.dest, i.src1);
|
||||
auto temp = GetTempReg<typename decltype(i.src2)::reg_type>(e);
|
||||
e.mov(temp, ~i.src2.constant());
|
||||
e.and_(i.dest, temp);
|
||||
}
|
||||
} else {
|
||||
// neither are constant
|
||||
if (i.dest == i.src2) {
|
||||
e.not_(i.dest);
|
||||
e.and_(i.dest, i.src1);
|
||||
} else {
|
||||
e.mov(i.dest, i.src2);
|
||||
e.not_(i.dest);
|
||||
e.and_(i.dest, i.src1);
|
||||
}
|
||||
}
|
||||
}
|
||||
struct AND_NOT_I8 : Sequence<AND_NOT_I8, I<OPCODE_AND_NOT, I8Op, I8Op, I8Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitAndNotXX<AND_NOT_I8, Reg8>(e, i);
|
||||
}
|
||||
};
|
||||
struct AND_NOT_I16
|
||||
: Sequence<AND_NOT_I16, I<OPCODE_AND_NOT, I16Op, I16Op, I16Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitAndNotXX<AND_NOT_I16, Reg16>(e, i);
|
||||
}
|
||||
};
|
||||
struct AND_NOT_I32
|
||||
: Sequence<AND_NOT_I32, I<OPCODE_AND_NOT, I32Op, I32Op, I32Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitAndNotXX<AND_NOT_I32, Reg32>(e, i);
|
||||
}
|
||||
};
|
||||
struct AND_NOT_I64
|
||||
: Sequence<AND_NOT_I64, I<OPCODE_AND_NOT, I64Op, I64Op, I64Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitAndNotXX<AND_NOT_I64, Reg64>(e, i);
|
||||
}
|
||||
};
|
||||
struct AND_NOT_V128
|
||||
: Sequence<AND_NOT_V128, I<OPCODE_AND_NOT, V128Op, V128Op, V128Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeBinaryXmmOp(e, i,
|
||||
[](X64Emitter& e, Xmm dest, Xmm src1, Xmm src2) {
|
||||
e.vpandn(dest, src2, src1);
|
||||
});
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(OPCODE_AND_NOT, AND_NOT_I8, AND_NOT_I16, AND_NOT_I32,
|
||||
AND_NOT_I64, AND_NOT_V128);
|
||||
|
||||
// ============================================================================
|
||||
// OPCODE_OR
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user