Format all code with new clang-format
This commit is contained in:
@@ -202,11 +202,11 @@ typedef struct _UNWIND_INFO {
|
||||
uint8_t FrameOffset : 4;
|
||||
UNWIND_CODE UnwindCode[1];
|
||||
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
|
||||
* union {
|
||||
* OPTIONAL ULONG ExceptionHandler;
|
||||
* OPTIONAL ULONG FunctionEntry;
|
||||
* };
|
||||
* OPTIONAL ULONG ExceptionData[]; */
|
||||
* union {
|
||||
* OPTIONAL ULONG ExceptionHandler;
|
||||
* OPTIONAL ULONG FunctionEntry;
|
||||
* };
|
||||
* OPTIONAL ULONG ExceptionData[]; */
|
||||
} UNWIND_INFO, *PUNWIND_INFO;
|
||||
|
||||
void Win32X64CodeCache::InitializeUnwindEntry(uint8_t* unwind_entry_address,
|
||||
|
||||
@@ -600,78 +600,78 @@ static const vec128_t xmm_consts[] = {
|
||||
/* XMMZero */ vec128f(0.0f),
|
||||
/* XMMOne */ vec128f(1.0f),
|
||||
/* XMMNegativeOne */ vec128f(-1.0f, -1.0f, -1.0f, -1.0f),
|
||||
/* XMMFFFF */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu),
|
||||
/* XMMMaskX16Y16 */ vec128i(0x0000FFFFu, 0xFFFF0000u, 0x00000000u,
|
||||
0x00000000u),
|
||||
/* XMMFlipX16Y16 */ vec128i(0x00008000u, 0x00000000u, 0x00000000u,
|
||||
0x00000000u),
|
||||
/* XMMFFFF */
|
||||
vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu),
|
||||
/* XMMMaskX16Y16 */
|
||||
vec128i(0x0000FFFFu, 0xFFFF0000u, 0x00000000u, 0x00000000u),
|
||||
/* XMMFlipX16Y16 */
|
||||
vec128i(0x00008000u, 0x00000000u, 0x00000000u, 0x00000000u),
|
||||
/* XMMFixX16Y16 */ vec128f(-32768.0f, 0.0f, 0.0f, 0.0f),
|
||||
/* XMMNormalizeX16Y16 */ vec128f(
|
||||
1.0f / 32767.0f, 1.0f / (32767.0f * 65536.0f), 0.0f, 0.0f),
|
||||
/* XMMNormalizeX16Y16 */
|
||||
vec128f(1.0f / 32767.0f, 1.0f / (32767.0f * 65536.0f), 0.0f, 0.0f),
|
||||
/* XMM0001 */ vec128f(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
/* XMM3301 */ vec128f(3.0f, 3.0f, 0.0f, 1.0f),
|
||||
/* XMM3333 */ vec128f(3.0f, 3.0f, 3.0f, 3.0f),
|
||||
/* XMMSignMaskPS */ vec128i(0x80000000u, 0x80000000u, 0x80000000u,
|
||||
0x80000000u),
|
||||
/* XMMSignMaskPD */ vec128i(0x00000000u, 0x80000000u, 0x00000000u,
|
||||
0x80000000u),
|
||||
/* XMMAbsMaskPS */ vec128i(0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu,
|
||||
0x7FFFFFFFu),
|
||||
/* XMMAbsMaskPD */ vec128i(0xFFFFFFFFu, 0x7FFFFFFFu, 0xFFFFFFFFu,
|
||||
0x7FFFFFFFu),
|
||||
/* XMMByteSwapMask */ vec128i(0x00010203u, 0x04050607u, 0x08090A0Bu,
|
||||
0x0C0D0E0Fu),
|
||||
/* XMMByteOrderMask */ vec128i(0x01000302u, 0x05040706u, 0x09080B0Au,
|
||||
0x0D0C0F0Eu),
|
||||
/* XMMSignMaskPS */
|
||||
vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
||||
/* XMMSignMaskPD */
|
||||
vec128i(0x00000000u, 0x80000000u, 0x00000000u, 0x80000000u),
|
||||
/* XMMAbsMaskPS */
|
||||
vec128i(0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu),
|
||||
/* XMMAbsMaskPD */
|
||||
vec128i(0xFFFFFFFFu, 0x7FFFFFFFu, 0xFFFFFFFFu, 0x7FFFFFFFu),
|
||||
/* XMMByteSwapMask */
|
||||
vec128i(0x00010203u, 0x04050607u, 0x08090A0Bu, 0x0C0D0E0Fu),
|
||||
/* XMMByteOrderMask */
|
||||
vec128i(0x01000302u, 0x05040706u, 0x09080B0Au, 0x0D0C0F0Eu),
|
||||
/* XMMPermuteControl15 */ vec128b(15),
|
||||
/* XMMPermuteByteMask */ vec128b(0x1F),
|
||||
/* XMMPackD3DCOLORSat */ vec128i(0x404000FFu),
|
||||
/* XMMPackD3DCOLOR */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0x0C000408u),
|
||||
/* XMMUnpackD3DCOLOR */ vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du, 0xFFFFFF0Cu,
|
||||
0xFFFFFF0Fu),
|
||||
/* XMMPackFLOAT16_2 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0x01000302u),
|
||||
/* XMMUnpackFLOAT16_2 */ vec128i(0x0D0C0F0Eu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu),
|
||||
/* XMMPackFLOAT16_4 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0x05040706u,
|
||||
0x01000302u),
|
||||
/* XMMUnpackFLOAT16_4 */ vec128i(0x09080B0Au, 0x0D0C0F0Eu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu),
|
||||
/* XMMPackD3DCOLOR */
|
||||
vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x0C000408u),
|
||||
/* XMMUnpackD3DCOLOR */
|
||||
vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du, 0xFFFFFF0Cu, 0xFFFFFF0Fu),
|
||||
/* XMMPackFLOAT16_2 */
|
||||
vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x01000302u),
|
||||
/* XMMUnpackFLOAT16_2 */
|
||||
vec128i(0x0D0C0F0Eu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu),
|
||||
/* XMMPackFLOAT16_4 */
|
||||
vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0x05040706u, 0x01000302u),
|
||||
/* XMMUnpackFLOAT16_4 */
|
||||
vec128i(0x09080B0Au, 0x0D0C0F0Eu, 0xFFFFFFFFu, 0xFFFFFFFFu),
|
||||
/* XMMPackSHORT_Min */ vec128i(0x403F8001u),
|
||||
/* XMMPackSHORT_Max */ vec128i(0x40407FFFu),
|
||||
/* XMMPackSHORT_2 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0x01000504u),
|
||||
/* XMMPackSHORT_4 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0x01000504u,
|
||||
0x09080D0Cu),
|
||||
/* XMMUnpackSHORT_2 */ vec128i(0xFFFF0F0Eu, 0xFFFF0D0Cu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu),
|
||||
/* XMMUnpackSHORT_4 */ vec128i(0xFFFF0B0Au, 0xFFFF0908u, 0xFFFF0F0Eu,
|
||||
0xFFFF0D0Cu),
|
||||
/* XMMPackSHORT_2 */
|
||||
vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x01000504u),
|
||||
/* XMMPackSHORT_4 */
|
||||
vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0x01000504u, 0x09080D0Cu),
|
||||
/* XMMUnpackSHORT_2 */
|
||||
vec128i(0xFFFF0F0Eu, 0xFFFF0D0Cu, 0xFFFFFFFFu, 0xFFFFFFFFu),
|
||||
/* XMMUnpackSHORT_4 */
|
||||
vec128i(0xFFFF0B0Au, 0xFFFF0908u, 0xFFFF0F0Eu, 0xFFFF0D0Cu),
|
||||
/* XMMOneOver255 */ vec128f(1.0f / 255.0f),
|
||||
/* XMMMaskEvenPI16 */ vec128i(0x0000FFFFu, 0x0000FFFFu, 0x0000FFFFu,
|
||||
0x0000FFFFu),
|
||||
/* XMMShiftMaskEvenPI16 */ vec128i(0x0000000Fu, 0x0000000Fu, 0x0000000Fu,
|
||||
0x0000000Fu),
|
||||
/* XMMShiftMaskPS */ vec128i(0x0000001Fu, 0x0000001Fu, 0x0000001Fu,
|
||||
0x0000001Fu),
|
||||
/* XMMShiftByteMask */ vec128i(0x000000FFu, 0x000000FFu, 0x000000FFu,
|
||||
0x000000FFu),
|
||||
/* XMMSwapWordMask */ vec128i(0x03030303u, 0x03030303u, 0x03030303u,
|
||||
0x03030303u),
|
||||
/* XMMUnsignedDwordMax */ vec128i(0xFFFFFFFFu, 0x00000000u, 0xFFFFFFFFu,
|
||||
0x00000000u),
|
||||
/* XMMMaskEvenPI16 */
|
||||
vec128i(0x0000FFFFu, 0x0000FFFFu, 0x0000FFFFu, 0x0000FFFFu),
|
||||
/* XMMShiftMaskEvenPI16 */
|
||||
vec128i(0x0000000Fu, 0x0000000Fu, 0x0000000Fu, 0x0000000Fu),
|
||||
/* XMMShiftMaskPS */
|
||||
vec128i(0x0000001Fu, 0x0000001Fu, 0x0000001Fu, 0x0000001Fu),
|
||||
/* XMMShiftByteMask */
|
||||
vec128i(0x000000FFu, 0x000000FFu, 0x000000FFu, 0x000000FFu),
|
||||
/* XMMSwapWordMask */
|
||||
vec128i(0x03030303u, 0x03030303u, 0x03030303u, 0x03030303u),
|
||||
/* XMMUnsignedDwordMax */
|
||||
vec128i(0xFFFFFFFFu, 0x00000000u, 0xFFFFFFFFu, 0x00000000u),
|
||||
/* XMM255 */ vec128f(255.0f),
|
||||
/* XMMPI32 */ vec128i(32),
|
||||
/* XMMSignMaskI8 */ vec128i(0x80808080u, 0x80808080u, 0x80808080u,
|
||||
0x80808080u),
|
||||
/* XMMSignMaskI16 */ vec128i(0x80008000u, 0x80008000u, 0x80008000u,
|
||||
0x80008000u),
|
||||
/* XMMSignMaskI32 */ vec128i(0x80000000u, 0x80000000u, 0x80000000u,
|
||||
0x80000000u),
|
||||
/* XMMSignMaskF32 */ vec128i(0x80000000u, 0x80000000u, 0x80000000u,
|
||||
0x80000000u),
|
||||
/* XMMSignMaskI8 */
|
||||
vec128i(0x80808080u, 0x80808080u, 0x80808080u, 0x80808080u),
|
||||
/* XMMSignMaskI16 */
|
||||
vec128i(0x80008000u, 0x80008000u, 0x80008000u, 0x80008000u),
|
||||
/* XMMSignMaskI32 */
|
||||
vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
||||
/* XMMSignMaskF32 */
|
||||
vec128i(0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u),
|
||||
/* XMMShortMinPS */ vec128f(SHRT_MIN),
|
||||
/* XMMShortMaxPS */ vec128f(SHRT_MAX),
|
||||
/* XMMIntMin */ vec128i(INT_MIN),
|
||||
|
||||
@@ -2988,8 +2988,9 @@ EMITTER_OPCODE_TABLE(OPCODE_IS_NAN, IS_NAN_F32, IS_NAN_F64);
|
||||
struct COMPARE_EQ_I8
|
||||
: Sequence<COMPARE_EQ_I8, I<OPCODE_COMPARE_EQ, I8Op, I8Op, I8Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeCompareOp(e, i, [](X64Emitter& e, const Reg8& src1,
|
||||
const Reg8& src2) { e.cmp(src1, src2); },
|
||||
EmitCommutativeCompareOp(e, i,
|
||||
[](X64Emitter& e, const Reg8& src1,
|
||||
const Reg8& src2) { e.cmp(src1, src2); },
|
||||
[](X64Emitter& e, const Reg8& src1,
|
||||
int32_t constant) { e.cmp(src1, constant); });
|
||||
e.sete(i.dest);
|
||||
@@ -2998,8 +2999,9 @@ struct COMPARE_EQ_I8
|
||||
struct COMPARE_EQ_I16
|
||||
: Sequence<COMPARE_EQ_I16, I<OPCODE_COMPARE_EQ, I8Op, I16Op, I16Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeCompareOp(e, i, [](X64Emitter& e, const Reg16& src1,
|
||||
const Reg16& src2) { e.cmp(src1, src2); },
|
||||
EmitCommutativeCompareOp(e, i,
|
||||
[](X64Emitter& e, const Reg16& src1,
|
||||
const Reg16& src2) { e.cmp(src1, src2); },
|
||||
[](X64Emitter& e, const Reg16& src1,
|
||||
int32_t constant) { e.cmp(src1, constant); });
|
||||
e.sete(i.dest);
|
||||
@@ -3008,8 +3010,9 @@ struct COMPARE_EQ_I16
|
||||
struct COMPARE_EQ_I32
|
||||
: Sequence<COMPARE_EQ_I32, I<OPCODE_COMPARE_EQ, I8Op, I32Op, I32Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeCompareOp(e, i, [](X64Emitter& e, const Reg32& src1,
|
||||
const Reg32& src2) { e.cmp(src1, src2); },
|
||||
EmitCommutativeCompareOp(e, i,
|
||||
[](X64Emitter& e, const Reg32& src1,
|
||||
const Reg32& src2) { e.cmp(src1, src2); },
|
||||
[](X64Emitter& e, const Reg32& src1,
|
||||
int32_t constant) { e.cmp(src1, constant); });
|
||||
e.sete(i.dest);
|
||||
@@ -3018,8 +3021,9 @@ struct COMPARE_EQ_I32
|
||||
struct COMPARE_EQ_I64
|
||||
: Sequence<COMPARE_EQ_I64, I<OPCODE_COMPARE_EQ, I8Op, I64Op, I64Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeCompareOp(e, i, [](X64Emitter& e, const Reg64& src1,
|
||||
const Reg64& src2) { e.cmp(src1, src2); },
|
||||
EmitCommutativeCompareOp(e, i,
|
||||
[](X64Emitter& e, const Reg64& src1,
|
||||
const Reg64& src2) { e.cmp(src1, src2); },
|
||||
[](X64Emitter& e, const Reg64& src1,
|
||||
int32_t constant) { e.cmp(src1, constant); });
|
||||
e.sete(i.dest);
|
||||
@@ -3055,8 +3059,9 @@ EMITTER_OPCODE_TABLE(OPCODE_COMPARE_EQ, COMPARE_EQ_I8, COMPARE_EQ_I16,
|
||||
struct COMPARE_NE_I8
|
||||
: Sequence<COMPARE_NE_I8, I<OPCODE_COMPARE_NE, I8Op, I8Op, I8Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeCompareOp(e, i, [](X64Emitter& e, const Reg8& src1,
|
||||
const Reg8& src2) { e.cmp(src1, src2); },
|
||||
EmitCommutativeCompareOp(e, i,
|
||||
[](X64Emitter& e, const Reg8& src1,
|
||||
const Reg8& src2) { e.cmp(src1, src2); },
|
||||
[](X64Emitter& e, const Reg8& src1,
|
||||
int32_t constant) { e.cmp(src1, constant); });
|
||||
e.setne(i.dest);
|
||||
@@ -3065,8 +3070,9 @@ struct COMPARE_NE_I8
|
||||
struct COMPARE_NE_I16
|
||||
: Sequence<COMPARE_NE_I16, I<OPCODE_COMPARE_NE, I8Op, I16Op, I16Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeCompareOp(e, i, [](X64Emitter& e, const Reg16& src1,
|
||||
const Reg16& src2) { e.cmp(src1, src2); },
|
||||
EmitCommutativeCompareOp(e, i,
|
||||
[](X64Emitter& e, const Reg16& src1,
|
||||
const Reg16& src2) { e.cmp(src1, src2); },
|
||||
[](X64Emitter& e, const Reg16& src1,
|
||||
int32_t constant) { e.cmp(src1, constant); });
|
||||
e.setne(i.dest);
|
||||
@@ -3075,8 +3081,9 @@ struct COMPARE_NE_I16
|
||||
struct COMPARE_NE_I32
|
||||
: Sequence<COMPARE_NE_I32, I<OPCODE_COMPARE_NE, I8Op, I32Op, I32Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeCompareOp(e, i, [](X64Emitter& e, const Reg32& src1,
|
||||
const Reg32& src2) { e.cmp(src1, src2); },
|
||||
EmitCommutativeCompareOp(e, i,
|
||||
[](X64Emitter& e, const Reg32& src1,
|
||||
const Reg32& src2) { e.cmp(src1, src2); },
|
||||
[](X64Emitter& e, const Reg32& src1,
|
||||
int32_t constant) { e.cmp(src1, constant); });
|
||||
e.setne(i.dest);
|
||||
@@ -3085,8 +3092,9 @@ struct COMPARE_NE_I32
|
||||
struct COMPARE_NE_I64
|
||||
: Sequence<COMPARE_NE_I64, I<OPCODE_COMPARE_NE, I8Op, I64Op, I64Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeCompareOp(e, i, [](X64Emitter& e, const Reg64& src1,
|
||||
const Reg64& src2) { e.cmp(src1, src2); },
|
||||
EmitCommutativeCompareOp(e, i,
|
||||
[](X64Emitter& e, const Reg64& src1,
|
||||
const Reg64& src2) { e.cmp(src1, src2); },
|
||||
[](X64Emitter& e, const Reg64& src1,
|
||||
int32_t constant) { e.cmp(src1, constant); });
|
||||
e.setne(i.dest);
|
||||
@@ -3421,8 +3429,10 @@ EMITTER_OPCODE_TABLE(OPCODE_VECTOR_COMPARE_UGE, VECTOR_COMPARE_UGE_V128);
|
||||
template <typename SEQ, typename REG, typename ARGS>
|
||||
void EmitAddXX(X64Emitter& e, const ARGS& i) {
|
||||
SEQ::EmitCommutativeBinaryOp(
|
||||
e, i, [](X64Emitter& e, const REG& dest_src,
|
||||
const REG& src) { e.add(dest_src, src); },
|
||||
e, i,
|
||||
[](X64Emitter& e, const REG& dest_src, const REG& src) {
|
||||
e.add(dest_src, src);
|
||||
},
|
||||
[](X64Emitter& e, const REG& dest_src, int32_t constant) {
|
||||
e.add(dest_src, constant);
|
||||
});
|
||||
@@ -3491,8 +3501,10 @@ void EmitAddCarryXX(X64Emitter& e, const ARGS& i) {
|
||||
e.sahf();
|
||||
}
|
||||
SEQ::EmitCommutativeBinaryOp(
|
||||
e, i, [](X64Emitter& e, const REG& dest_src,
|
||||
const REG& src) { e.adc(dest_src, src); },
|
||||
e, i,
|
||||
[](X64Emitter& e, const REG& dest_src, const REG& src) {
|
||||
e.adc(dest_src, src);
|
||||
},
|
||||
[](X64Emitter& e, const REG& dest_src, int32_t constant) {
|
||||
e.adc(dest_src, constant);
|
||||
});
|
||||
@@ -3530,105 +3542,110 @@ EMITTER_OPCODE_TABLE(OPCODE_ADD_CARRY, ADD_CARRY_I8, ADD_CARRY_I16,
|
||||
struct VECTOR_ADD
|
||||
: Sequence<VECTOR_ADD, I<OPCODE_VECTOR_ADD, V128Op, V128Op, V128Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
Xmm src1, Xmm src2) {
|
||||
const TypeName part_type = static_cast<TypeName>(i.instr->flags & 0xFF);
|
||||
const uint32_t arithmetic_flags = i.instr->flags >> 8;
|
||||
bool is_unsigned = !!(arithmetic_flags & ARITHMETIC_UNSIGNED);
|
||||
bool saturate = !!(arithmetic_flags & ARITHMETIC_SATURATE);
|
||||
switch (part_type) {
|
||||
case INT8_TYPE:
|
||||
if (saturate) {
|
||||
// TODO(benvanik): trace DID_SATURATE
|
||||
if (is_unsigned) {
|
||||
e.vpaddusb(dest, src1, src2);
|
||||
} else {
|
||||
e.vpaddsb(dest, src1, src2);
|
||||
}
|
||||
} else {
|
||||
e.vpaddb(dest, src1, src2);
|
||||
}
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
if (saturate) {
|
||||
// TODO(benvanik): trace DID_SATURATE
|
||||
if (is_unsigned) {
|
||||
e.vpaddusw(dest, src1, src2);
|
||||
} else {
|
||||
e.vpaddsw(dest, src1, src2);
|
||||
}
|
||||
} else {
|
||||
e.vpaddw(dest, src1, src2);
|
||||
}
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
if (saturate) {
|
||||
if (is_unsigned) {
|
||||
// xmm0 is the only temp register that can be used by src1/src2.
|
||||
e.vpaddd(e.xmm1, src1, src2);
|
||||
|
||||
// If result is smaller than either of the inputs, we've
|
||||
// overflowed (only need to check one input)
|
||||
// if (src1 > res) then overflowed
|
||||
// http://locklessinc.com/articles/sat_arithmetic/
|
||||
e.vpxor(e.xmm2, src1, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||
e.vpxor(e.xmm0, e.xmm1, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||
e.vpcmpgtd(e.xmm0, e.xmm2, e.xmm0);
|
||||
e.vpor(dest, e.xmm1, e.xmm0);
|
||||
} else {
|
||||
// Preserve the sources.
|
||||
if (dest == src1) {
|
||||
e.vmovdqa(e.xmm2, src1);
|
||||
src1 = e.xmm2;
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i, [&i](X64Emitter& e, const Xmm& dest, Xmm src1, Xmm src2) {
|
||||
const TypeName part_type =
|
||||
static_cast<TypeName>(i.instr->flags & 0xFF);
|
||||
const uint32_t arithmetic_flags = i.instr->flags >> 8;
|
||||
bool is_unsigned = !!(arithmetic_flags & ARITHMETIC_UNSIGNED);
|
||||
bool saturate = !!(arithmetic_flags & ARITHMETIC_SATURATE);
|
||||
switch (part_type) {
|
||||
case INT8_TYPE:
|
||||
if (saturate) {
|
||||
// TODO(benvanik): trace DID_SATURATE
|
||||
if (is_unsigned) {
|
||||
e.vpaddusb(dest, src1, src2);
|
||||
} else {
|
||||
e.vpaddsb(dest, src1, src2);
|
||||
}
|
||||
} else {
|
||||
e.vpaddb(dest, src1, src2);
|
||||
}
|
||||
if (dest == src2) {
|
||||
e.vmovdqa(e.xmm1, src2);
|
||||
src2 = e.xmm1;
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
if (saturate) {
|
||||
// TODO(benvanik): trace DID_SATURATE
|
||||
if (is_unsigned) {
|
||||
e.vpaddusw(dest, src1, src2);
|
||||
} else {
|
||||
e.vpaddsw(dest, src1, src2);
|
||||
}
|
||||
} else {
|
||||
e.vpaddw(dest, src1, src2);
|
||||
}
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
if (saturate) {
|
||||
if (is_unsigned) {
|
||||
// xmm0 is the only temp register that can be used by
|
||||
// src1/src2.
|
||||
e.vpaddd(e.xmm1, src1, src2);
|
||||
|
||||
// xmm0 is the only temp register that can be used by src1/src2.
|
||||
e.vpaddd(dest, src1, src2);
|
||||
// If result is smaller than either of the inputs, we've
|
||||
// overflowed (only need to check one input)
|
||||
// if (src1 > res) then overflowed
|
||||
// http://locklessinc.com/articles/sat_arithmetic/
|
||||
e.vpxor(e.xmm2, src1, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||
e.vpxor(e.xmm0, e.xmm1, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||
e.vpcmpgtd(e.xmm0, e.xmm2, e.xmm0);
|
||||
e.vpor(dest, e.xmm1, e.xmm0);
|
||||
} else {
|
||||
// Preserve the sources.
|
||||
if (dest == src1) {
|
||||
e.vmovdqa(e.xmm2, src1);
|
||||
src1 = e.xmm2;
|
||||
}
|
||||
if (dest == src2) {
|
||||
e.vmovdqa(e.xmm1, src2);
|
||||
src2 = e.xmm1;
|
||||
}
|
||||
|
||||
// Overflow results if two inputs are the same sign and the result
|
||||
// isn't the same sign.
|
||||
// if ((s32b)(~(src1 ^ src2) & (src1 ^ res)) < 0) then overflowed
|
||||
// http://locklessinc.com/articles/sat_arithmetic/
|
||||
e.vpxor(e.xmm1, src1, src2);
|
||||
// xmm0 is the only temp register that can be used by
|
||||
// src1/src2.
|
||||
e.vpaddd(dest, src1, src2);
|
||||
|
||||
// Move src1 to xmm0 in-case it was the same register as the dest.
|
||||
// This kills src2 if it's a constant.
|
||||
if (src1 != e.xmm0) {
|
||||
e.vmovdqa(e.xmm0, src1);
|
||||
src1 = e.xmm0;
|
||||
// Overflow results if two inputs are the same sign and the
|
||||
// result isn't the same sign. if ((s32b)(~(src1 ^ src2) &
|
||||
// (src1 ^ res)) < 0) then overflowed
|
||||
// http://locklessinc.com/articles/sat_arithmetic/
|
||||
e.vpxor(e.xmm1, src1, src2);
|
||||
|
||||
// Move src1 to xmm0 in-case it was the same register as the
|
||||
// dest. This kills src2 if it's a constant.
|
||||
if (src1 != e.xmm0) {
|
||||
e.vmovdqa(e.xmm0, src1);
|
||||
src1 = e.xmm0;
|
||||
}
|
||||
|
||||
e.vpxor(e.xmm2, src1, dest);
|
||||
e.vpandn(e.xmm1, e.xmm1, e.xmm2);
|
||||
|
||||
// High bit of xmm1 is now set if overflowed.
|
||||
|
||||
// Set any negative overflowed elements of src1 to INT_MIN
|
||||
e.vpand(e.xmm2, src1, e.xmm1);
|
||||
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMSignMaskI32),
|
||||
e.xmm2);
|
||||
|
||||
// Set any positive overflowed elements of src1 to INT_MAX
|
||||
e.vpandn(e.xmm2, src1, e.xmm1);
|
||||
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMAbsMaskPS),
|
||||
e.xmm2);
|
||||
}
|
||||
} else {
|
||||
e.vpaddd(dest, src1, src2);
|
||||
}
|
||||
|
||||
e.vpxor(e.xmm2, src1, dest);
|
||||
e.vpandn(e.xmm1, e.xmm1, e.xmm2);
|
||||
|
||||
// High bit of xmm1 is now set if overflowed.
|
||||
|
||||
// Set any negative overflowed elements of src1 to INT_MIN
|
||||
e.vpand(e.xmm2, src1, e.xmm1);
|
||||
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMSignMaskI32), e.xmm2);
|
||||
|
||||
// Set any positive overflowed elements of src1 to INT_MAX
|
||||
e.vpandn(e.xmm2, src1, e.xmm1);
|
||||
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMAbsMaskPS), e.xmm2);
|
||||
}
|
||||
} else {
|
||||
e.vpaddd(dest, src1, src2);
|
||||
break;
|
||||
case FLOAT32_TYPE:
|
||||
assert_false(is_unsigned);
|
||||
assert_false(saturate);
|
||||
e.vaddps(dest, src1, src2);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(part_type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLOAT32_TYPE:
|
||||
assert_false(is_unsigned);
|
||||
assert_false(saturate);
|
||||
e.vaddps(dest, src1, src2);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(part_type);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(OPCODE_VECTOR_ADD, VECTOR_ADD);
|
||||
@@ -3640,8 +3657,10 @@ EMITTER_OPCODE_TABLE(OPCODE_VECTOR_ADD, VECTOR_ADD);
|
||||
template <typename SEQ, typename REG, typename ARGS>
|
||||
void EmitSubXX(X64Emitter& e, const ARGS& i) {
|
||||
SEQ::EmitAssociativeBinaryOp(
|
||||
e, i, [](X64Emitter& e, const REG& dest_src,
|
||||
const REG& src) { e.sub(dest_src, src); },
|
||||
e, i,
|
||||
[](X64Emitter& e, const REG& dest_src, const REG& src) {
|
||||
e.sub(dest_src, src);
|
||||
},
|
||||
[](X64Emitter& e, const REG& dest_src, int32_t constant) {
|
||||
e.sub(dest_src, constant);
|
||||
});
|
||||
@@ -3693,104 +3712,109 @@ EMITTER_OPCODE_TABLE(OPCODE_SUB, SUB_I8, SUB_I16, SUB_I32, SUB_I64, SUB_F32,
|
||||
struct VECTOR_SUB
|
||||
: Sequence<VECTOR_SUB, I<OPCODE_VECTOR_SUB, V128Op, V128Op, V128Op>> {
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
Xmm src1, Xmm src2) {
|
||||
const TypeName part_type = static_cast<TypeName>(i.instr->flags & 0xFF);
|
||||
const uint32_t arithmetic_flags = i.instr->flags >> 8;
|
||||
bool is_unsigned = !!(arithmetic_flags & ARITHMETIC_UNSIGNED);
|
||||
bool saturate = !!(arithmetic_flags & ARITHMETIC_SATURATE);
|
||||
switch (part_type) {
|
||||
case INT8_TYPE:
|
||||
if (saturate) {
|
||||
// TODO(benvanik): trace DID_SATURATE
|
||||
if (is_unsigned) {
|
||||
e.vpsubusb(dest, src1, src2);
|
||||
} else {
|
||||
e.vpsubsb(dest, src1, src2);
|
||||
}
|
||||
} else {
|
||||
e.vpsubb(dest, src1, src2);
|
||||
}
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
if (saturate) {
|
||||
// TODO(benvanik): trace DID_SATURATE
|
||||
if (is_unsigned) {
|
||||
e.vpsubusw(dest, src1, src2);
|
||||
} else {
|
||||
e.vpsubsw(dest, src1, src2);
|
||||
}
|
||||
} else {
|
||||
e.vpsubw(dest, src1, src2);
|
||||
}
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
if (saturate) {
|
||||
if (is_unsigned) {
|
||||
// xmm0 is the only temp register that can be used by src1/src2.
|
||||
e.vpsubd(e.xmm1, src1, src2);
|
||||
|
||||
// If result is greater than either of the inputs, we've
|
||||
// underflowed (only need to check one input)
|
||||
// if (res > src1) then underflowed
|
||||
// http://locklessinc.com/articles/sat_arithmetic/
|
||||
e.vpxor(e.xmm2, src1, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||
e.vpxor(e.xmm0, e.xmm1, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||
e.vpcmpgtd(e.xmm0, e.xmm0, e.xmm2);
|
||||
e.vpandn(dest, e.xmm0, e.xmm1);
|
||||
} else {
|
||||
// Preserve the sources.
|
||||
if (dest == src1) {
|
||||
e.vmovdqa(e.xmm2, src1);
|
||||
src1 = e.xmm2;
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i, [&i](X64Emitter& e, const Xmm& dest, Xmm src1, Xmm src2) {
|
||||
const TypeName part_type =
|
||||
static_cast<TypeName>(i.instr->flags & 0xFF);
|
||||
const uint32_t arithmetic_flags = i.instr->flags >> 8;
|
||||
bool is_unsigned = !!(arithmetic_flags & ARITHMETIC_UNSIGNED);
|
||||
bool saturate = !!(arithmetic_flags & ARITHMETIC_SATURATE);
|
||||
switch (part_type) {
|
||||
case INT8_TYPE:
|
||||
if (saturate) {
|
||||
// TODO(benvanik): trace DID_SATURATE
|
||||
if (is_unsigned) {
|
||||
e.vpsubusb(dest, src1, src2);
|
||||
} else {
|
||||
e.vpsubsb(dest, src1, src2);
|
||||
}
|
||||
} else {
|
||||
e.vpsubb(dest, src1, src2);
|
||||
}
|
||||
if (dest == src2) {
|
||||
e.vmovdqa(e.xmm1, src2);
|
||||
src2 = e.xmm1;
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
if (saturate) {
|
||||
// TODO(benvanik): trace DID_SATURATE
|
||||
if (is_unsigned) {
|
||||
e.vpsubusw(dest, src1, src2);
|
||||
} else {
|
||||
e.vpsubsw(dest, src1, src2);
|
||||
}
|
||||
} else {
|
||||
e.vpsubw(dest, src1, src2);
|
||||
}
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
if (saturate) {
|
||||
if (is_unsigned) {
|
||||
// xmm0 is the only temp register that can be used by
|
||||
// src1/src2.
|
||||
e.vpsubd(e.xmm1, src1, src2);
|
||||
|
||||
// xmm0 is the only temp register that can be used by src1/src2.
|
||||
e.vpsubd(dest, src1, src2);
|
||||
// If result is greater than either of the inputs, we've
|
||||
// underflowed (only need to check one input)
|
||||
// if (res > src1) then underflowed
|
||||
// http://locklessinc.com/articles/sat_arithmetic/
|
||||
e.vpxor(e.xmm2, src1, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||
e.vpxor(e.xmm0, e.xmm1, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||
e.vpcmpgtd(e.xmm0, e.xmm0, e.xmm2);
|
||||
e.vpandn(dest, e.xmm0, e.xmm1);
|
||||
} else {
|
||||
// Preserve the sources.
|
||||
if (dest == src1) {
|
||||
e.vmovdqa(e.xmm2, src1);
|
||||
src1 = e.xmm2;
|
||||
}
|
||||
if (dest == src2) {
|
||||
e.vmovdqa(e.xmm1, src2);
|
||||
src2 = e.xmm1;
|
||||
}
|
||||
|
||||
// We can only overflow if the signs of the operands are opposite.
|
||||
// If signs are opposite and result sign isn't the same as src1's
|
||||
// sign, we've overflowed.
|
||||
// if ((s32b)((src1 ^ src2) & (src1 ^ res)) < 0) then overflowed
|
||||
// http://locklessinc.com/articles/sat_arithmetic/
|
||||
e.vpxor(e.xmm1, src1, src2);
|
||||
// xmm0 is the only temp register that can be used by
|
||||
// src1/src2.
|
||||
e.vpsubd(dest, src1, src2);
|
||||
|
||||
// Move src1 to xmm0 in-case it's the same register as the dest.
|
||||
// This kills src2 if it's a constant.
|
||||
if (src1 != e.xmm0) {
|
||||
e.vmovdqa(e.xmm0, src1);
|
||||
src1 = e.xmm0;
|
||||
// We can only overflow if the signs of the operands are
|
||||
// opposite. If signs are opposite and result sign isn't the
|
||||
// same as src1's sign, we've overflowed. if ((s32b)((src1 ^
|
||||
// src2) & (src1 ^ res)) < 0) then overflowed
|
||||
// http://locklessinc.com/articles/sat_arithmetic/
|
||||
e.vpxor(e.xmm1, src1, src2);
|
||||
|
||||
// Move src1 to xmm0 in-case it's the same register as the
|
||||
// dest. This kills src2 if it's a constant.
|
||||
if (src1 != e.xmm0) {
|
||||
e.vmovdqa(e.xmm0, src1);
|
||||
src1 = e.xmm0;
|
||||
}
|
||||
|
||||
e.vpxor(e.xmm2, src1, dest);
|
||||
e.vpand(e.xmm1, e.xmm1, e.xmm2);
|
||||
|
||||
// High bit of xmm1 is now set if overflowed.
|
||||
|
||||
// Set any negative overflowed elements of src1 to INT_MIN
|
||||
e.vpand(e.xmm2, src1, e.xmm1);
|
||||
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMSignMaskI32),
|
||||
e.xmm2);
|
||||
|
||||
// Set any positive overflowed elements of src1 to INT_MAX
|
||||
e.vpandn(e.xmm2, src1, e.xmm1);
|
||||
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMAbsMaskPS),
|
||||
e.xmm2);
|
||||
}
|
||||
} else {
|
||||
e.vpsubd(dest, src1, src2);
|
||||
}
|
||||
|
||||
e.vpxor(e.xmm2, src1, dest);
|
||||
e.vpand(e.xmm1, e.xmm1, e.xmm2);
|
||||
|
||||
// High bit of xmm1 is now set if overflowed.
|
||||
|
||||
// Set any negative overflowed elements of src1 to INT_MIN
|
||||
e.vpand(e.xmm2, src1, e.xmm1);
|
||||
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMSignMaskI32), e.xmm2);
|
||||
|
||||
// Set any positive overflowed elements of src1 to INT_MAX
|
||||
e.vpandn(e.xmm2, src1, e.xmm1);
|
||||
e.vblendvps(dest, dest, e.GetXmmConstPtr(XMMAbsMaskPS), e.xmm2);
|
||||
}
|
||||
} else {
|
||||
e.vpsubd(dest, src1, src2);
|
||||
break;
|
||||
case FLOAT32_TYPE:
|
||||
e.vsubps(dest, src1, src2);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(part_type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FLOAT32_TYPE:
|
||||
e.vsubps(dest, src1, src2);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(part_type);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(OPCODE_VECTOR_SUB, VECTOR_SUB);
|
||||
@@ -4469,24 +4493,26 @@ struct MUL_ADD_F32
|
||||
|
||||
// FMA extension
|
||||
if (e.IsFeatureEnabled(kX64EmitFMA)) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
const Xmm& src1, const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmadd213ss(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmadd213ss(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmadd231ss(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovss(i.dest, src1);
|
||||
e.vfmadd213ss(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i,
|
||||
[&i](X64Emitter& e, const Xmm& dest, const Xmm& src1,
|
||||
const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmadd213ss(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmadd213ss(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmadd231ss(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovss(i.dest, src1);
|
||||
e.vfmadd213ss(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Xmm src3;
|
||||
if (i.src3.is_constant) {
|
||||
@@ -4526,24 +4552,26 @@ struct MUL_ADD_F64
|
||||
|
||||
// FMA extension
|
||||
if (e.IsFeatureEnabled(kX64EmitFMA)) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
const Xmm& src1, const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmadd213sd(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmadd213sd(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmadd231sd(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovsd(i.dest, src1);
|
||||
e.vfmadd213sd(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i,
|
||||
[&i](X64Emitter& e, const Xmm& dest, const Xmm& src1,
|
||||
const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmadd213sd(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmadd213sd(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmadd231sd(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovsd(i.dest, src1);
|
||||
e.vfmadd213sd(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Xmm src3;
|
||||
if (i.src3.is_constant) {
|
||||
@@ -4589,24 +4617,26 @@ struct MUL_ADD_V128
|
||||
// than vmul+vadd and it'd be nice to know why. Until we know, it's
|
||||
// disabled so tests pass.
|
||||
if (false && e.IsFeatureEnabled(kX64EmitFMA)) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
const Xmm& src1, const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmadd213ps(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmadd213ps(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmadd231ps(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovdqa(i.dest, src1);
|
||||
e.vfmadd213ps(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i,
|
||||
[&i](X64Emitter& e, const Xmm& dest, const Xmm& src1,
|
||||
const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmadd213ps(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmadd213ps(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmadd231ps(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovdqa(i.dest, src1);
|
||||
e.vfmadd213ps(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Xmm src3;
|
||||
if (i.src3.is_constant) {
|
||||
@@ -4660,24 +4690,26 @@ struct MUL_SUB_F32
|
||||
|
||||
// FMA extension
|
||||
if (e.IsFeatureEnabled(kX64EmitFMA)) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
const Xmm& src1, const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmsub213ss(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmsub213ss(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmsub231ss(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovss(i.dest, src1);
|
||||
e.vfmsub213ss(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i,
|
||||
[&i](X64Emitter& e, const Xmm& dest, const Xmm& src1,
|
||||
const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmsub213ss(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmsub213ss(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmsub231ss(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovss(i.dest, src1);
|
||||
e.vfmsub213ss(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Xmm src3;
|
||||
if (i.src3.is_constant) {
|
||||
@@ -4717,24 +4749,26 @@ struct MUL_SUB_F64
|
||||
|
||||
// FMA extension
|
||||
if (e.IsFeatureEnabled(kX64EmitFMA)) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
const Xmm& src1, const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmsub213sd(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmsub213sd(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmsub231sd(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovsd(i.dest, src1);
|
||||
e.vfmsub213sd(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i,
|
||||
[&i](X64Emitter& e, const Xmm& dest, const Xmm& src1,
|
||||
const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmsub213sd(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmsub213sd(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmsub231sd(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovsd(i.dest, src1);
|
||||
e.vfmsub213sd(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Xmm src3;
|
||||
if (i.src3.is_constant) {
|
||||
@@ -4778,24 +4812,26 @@ struct MUL_SUB_V128
|
||||
|
||||
// FMA extension
|
||||
if (e.IsFeatureEnabled(kX64EmitFMA)) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
const Xmm& src1, const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmsub213ps(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmsub213ps(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmsub231ps(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovdqa(i.dest, src1);
|
||||
e.vfmsub213ps(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i,
|
||||
[&i](X64Emitter& e, const Xmm& dest, const Xmm& src1,
|
||||
const Xmm& src2) {
|
||||
Xmm src3 = i.src3.is_constant ? e.xmm1 : i.src3;
|
||||
if (i.src3.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm1, i.src3.constant());
|
||||
}
|
||||
if (i.dest == src1) {
|
||||
e.vfmsub213ps(i.dest, src2, src3);
|
||||
} else if (i.dest == src2) {
|
||||
e.vfmsub213ps(i.dest, src1, src3);
|
||||
} else if (i.dest == i.src3) {
|
||||
e.vfmsub231ps(i.dest, src1, src2);
|
||||
} else {
|
||||
// Dest not equal to anything
|
||||
e.vmovdqa(i.dest, src1);
|
||||
e.vfmsub213ps(i.dest, src2, src3);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Xmm src3;
|
||||
if (i.src3.is_constant) {
|
||||
@@ -5098,8 +5134,10 @@ EMITTER_OPCODE_TABLE(OPCODE_DOT_PRODUCT_4, DOT_PRODUCT_4_V128);
|
||||
template <typename SEQ, typename REG, typename ARGS>
|
||||
void EmitAndXX(X64Emitter& e, const ARGS& i) {
|
||||
SEQ::EmitCommutativeBinaryOp(
|
||||
e, i, [](X64Emitter& e, const REG& dest_src,
|
||||
const REG& src) { e.and_(dest_src, src); },
|
||||
e, i,
|
||||
[](X64Emitter& e, const REG& dest_src, const REG& src) {
|
||||
e.and_(dest_src, src);
|
||||
},
|
||||
[](X64Emitter& e, const REG& dest_src, int32_t constant) {
|
||||
e.and_(dest_src, constant);
|
||||
});
|
||||
@@ -5141,8 +5179,10 @@ EMITTER_OPCODE_TABLE(OPCODE_AND, AND_I8, AND_I16, AND_I32, AND_I64, AND_V128);
|
||||
template <typename SEQ, typename REG, typename ARGS>
|
||||
void EmitOrXX(X64Emitter& e, const ARGS& i) {
|
||||
SEQ::EmitCommutativeBinaryOp(
|
||||
e, i, [](X64Emitter& e, const REG& dest_src,
|
||||
const REG& src) { e.or_(dest_src, src); },
|
||||
e, i,
|
||||
[](X64Emitter& e, const REG& dest_src, const REG& src) {
|
||||
e.or_(dest_src, src);
|
||||
},
|
||||
[](X64Emitter& e, const REG& dest_src, int32_t constant) {
|
||||
e.or_(dest_src, constant);
|
||||
});
|
||||
@@ -5184,8 +5224,10 @@ EMITTER_OPCODE_TABLE(OPCODE_OR, OR_I8, OR_I16, OR_I32, OR_I64, OR_V128);
|
||||
template <typename SEQ, typename REG, typename ARGS>
|
||||
void EmitXorXX(X64Emitter& e, const ARGS& i) {
|
||||
SEQ::EmitCommutativeBinaryOp(
|
||||
e, i, [](X64Emitter& e, const REG& dest_src,
|
||||
const REG& src) { e.xor_(dest_src, src); },
|
||||
e, i,
|
||||
[](X64Emitter& e, const REG& dest_src, const REG& src) {
|
||||
e.xor_(dest_src, src);
|
||||
},
|
||||
[](X64Emitter& e, const REG& dest_src, int32_t constant) {
|
||||
e.xor_(dest_src, constant);
|
||||
});
|
||||
@@ -6209,57 +6251,59 @@ struct VECTOR_AVERAGE
|
||||
return _mm_load_si128(reinterpret_cast<__m128i*>(value));
|
||||
}
|
||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||
EmitCommutativeBinaryXmmOp(e, i, [&i](X64Emitter& e, const Xmm& dest,
|
||||
const Xmm& src1, const Xmm& src2) {
|
||||
const TypeName part_type = static_cast<TypeName>(i.instr->flags & 0xFF);
|
||||
const uint32_t arithmetic_flags = i.instr->flags >> 8;
|
||||
bool is_unsigned = !!(arithmetic_flags & ARITHMETIC_UNSIGNED);
|
||||
switch (part_type) {
|
||||
case INT8_TYPE:
|
||||
if (is_unsigned) {
|
||||
e.vpavgb(dest, src1, src2);
|
||||
} else {
|
||||
assert_always();
|
||||
EmitCommutativeBinaryXmmOp(
|
||||
e, i,
|
||||
[&i](X64Emitter& e, const Xmm& dest, const Xmm& src1, const Xmm& src2) {
|
||||
const TypeName part_type =
|
||||
static_cast<TypeName>(i.instr->flags & 0xFF);
|
||||
const uint32_t arithmetic_flags = i.instr->flags >> 8;
|
||||
bool is_unsigned = !!(arithmetic_flags & ARITHMETIC_UNSIGNED);
|
||||
switch (part_type) {
|
||||
case INT8_TYPE:
|
||||
if (is_unsigned) {
|
||||
e.vpavgb(dest, src1, src2);
|
||||
} else {
|
||||
assert_always();
|
||||
}
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
if (is_unsigned) {
|
||||
e.vpavgw(dest, src1, src2);
|
||||
} else {
|
||||
assert_always();
|
||||
}
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
// No 32bit averages in AVX.
|
||||
if (is_unsigned) {
|
||||
if (i.src2.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm0, i.src2.constant());
|
||||
e.lea(e.r9, e.StashXmm(1, e.xmm0));
|
||||
} else {
|
||||
e.lea(e.r9, e.StashXmm(1, i.src2));
|
||||
}
|
||||
e.lea(e.r8, e.StashXmm(0, i.src1));
|
||||
e.CallNativeSafe(
|
||||
reinterpret_cast<void*>(EmulateVectorAverageUnsignedI32));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
} else {
|
||||
if (i.src2.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm0, i.src2.constant());
|
||||
e.lea(e.r9, e.StashXmm(1, e.xmm0));
|
||||
} else {
|
||||
e.lea(e.r9, e.StashXmm(1, i.src2));
|
||||
}
|
||||
e.lea(e.r8, e.StashXmm(0, i.src1));
|
||||
e.CallNativeSafe(
|
||||
reinterpret_cast<void*>(EmulateVectorAverageSignedI32));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(part_type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
if (is_unsigned) {
|
||||
e.vpavgw(dest, src1, src2);
|
||||
} else {
|
||||
assert_always();
|
||||
}
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
// No 32bit averages in AVX.
|
||||
if (is_unsigned) {
|
||||
if (i.src2.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm0, i.src2.constant());
|
||||
e.lea(e.r9, e.StashXmm(1, e.xmm0));
|
||||
} else {
|
||||
e.lea(e.r9, e.StashXmm(1, i.src2));
|
||||
}
|
||||
e.lea(e.r8, e.StashXmm(0, i.src1));
|
||||
e.CallNativeSafe(
|
||||
reinterpret_cast<void*>(EmulateVectorAverageUnsignedI32));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
} else {
|
||||
if (i.src2.is_constant) {
|
||||
e.LoadConstantXmm(e.xmm0, i.src2.constant());
|
||||
e.lea(e.r9, e.StashXmm(1, e.xmm0));
|
||||
} else {
|
||||
e.lea(e.r9, e.StashXmm(1, i.src2));
|
||||
}
|
||||
e.lea(e.r8, e.StashXmm(0, i.src1));
|
||||
e.CallNativeSafe(
|
||||
reinterpret_cast<void*>(EmulateVectorAverageSignedI32));
|
||||
e.vmovaps(i.dest, e.xmm0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(part_type);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
EMITTER_OPCODE_TABLE(OPCODE_VECTOR_AVERAGE, VECTOR_AVERAGE);
|
||||
|
||||
@@ -420,7 +420,7 @@ bool RegisterAllocationPass::SpillOneRegister(HIRBuilder* builder, Block* block,
|
||||
auto new_value = builder->LoadLocal(spill_value->local_slot);
|
||||
auto spill_load = builder->last_instr();
|
||||
spill_load->MoveBefore(next_use->instr);
|
||||
// Note: implicit first use added.
|
||||
// Note: implicit first use added.
|
||||
|
||||
#if ASSERT_NO_CYCLES
|
||||
builder->AssertNoCycles();
|
||||
|
||||
@@ -1963,7 +1963,10 @@ Value* HIRBuilder::CountLeadingZeros(Value* value) {
|
||||
|
||||
if (value->IsConstantZero()) {
|
||||
static const uint8_t zeros[] = {
|
||||
8, 16, 32, 64,
|
||||
8,
|
||||
16,
|
||||
32,
|
||||
64,
|
||||
};
|
||||
assert_true(value->type <= INT64_TYPE);
|
||||
return LoadConstantUint8(zeros[value->type]);
|
||||
|
||||
@@ -15,7 +15,10 @@ namespace hir {
|
||||
|
||||
#define DEFINE_OPCODE(num, name, sig, flags) \
|
||||
const OpcodeInfo num##_info = { \
|
||||
flags, sig, name, num, \
|
||||
flags, \
|
||||
sig, \
|
||||
name, \
|
||||
num, \
|
||||
};
|
||||
#include "xenia/cpu/hir/opcodes.inl"
|
||||
#undef DEFINE_OPCODE
|
||||
|
||||
@@ -87,8 +87,7 @@ enum PackType : uint16_t {
|
||||
PACK_TYPE_16_IN_32 = 7,
|
||||
|
||||
PACK_TYPE_MODE = 0x000F, // just to get the mode
|
||||
|
||||
// Unpack to low or high parts.
|
||||
// Unpack to low or high parts.
|
||||
PACK_TYPE_TO_LO = 0 << 12,
|
||||
PACK_TYPE_TO_HI = 1 << 12,
|
||||
|
||||
|
||||
@@ -52,7 +52,12 @@ bool MMIOHandler::RegisterRange(uint32_t virtual_address, uint32_t mask,
|
||||
MMIOReadCallback read_callback,
|
||||
MMIOWriteCallback write_callback) {
|
||||
mapped_ranges_.push_back({
|
||||
virtual_address, mask, size, context, read_callback, write_callback,
|
||||
virtual_address,
|
||||
mask,
|
||||
size,
|
||||
context,
|
||||
read_callback,
|
||||
write_callback,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2073,7 +2073,7 @@ int InstrEmit_vpkd3d128(PPCHIRBuilder& f, const InstrData& i) {
|
||||
uint32_t control = kIdentityPermuteMask; // original
|
||||
switch (pack) {
|
||||
case 1: // VPACK_32
|
||||
// VPACK_32 & shift = 3 puts lower 32 bits in x (leftmost slot).
|
||||
// VPACK_32 & shift = 3 puts lower 32 bits in x (leftmost slot).
|
||||
switch (shift) {
|
||||
case 0:
|
||||
control = MakePermuteMask(0, 0, 0, 1, 0, 2, 1, 3);
|
||||
|
||||
@@ -143,7 +143,7 @@ int InstrEmit_branch(PPCHIRBuilder& f, const char* src, uint64_t cia,
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace ppc
|
||||
|
||||
int InstrEmit_bx(PPCHIRBuilder& f, const InstrData& i) {
|
||||
// if AA then
|
||||
@@ -799,6 +799,6 @@ void RegisterEmitCategoryControl() {
|
||||
XEREGISTERINSTR(mtmsrd);
|
||||
}
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
} // namespace xe
|
||||
|
||||
@@ -341,14 +341,16 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(GuestFunction* function) {
|
||||
if (ends_block) {
|
||||
in_block = false;
|
||||
block_map[block_start] = {
|
||||
block_start, address,
|
||||
block_start,
|
||||
address,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (in_block) {
|
||||
block_map[block_start] = {
|
||||
block_start, end_address,
|
||||
block_start,
|
||||
end_address,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,10 @@ using xe::cpu::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("ADD_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -90,9 +91,10 @@ TEST_CASE("ADD_I8", "[instr]") {
|
||||
|
||||
TEST_CASE("ADD_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT16_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT16_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -162,9 +164,10 @@ TEST_CASE("ADD_I16", "[instr]") {
|
||||
|
||||
TEST_CASE("ADD_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT32_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT32_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -304,9 +307,10 @@ TEST_CASE("ADD_I64", "[instr]") {
|
||||
|
||||
TEST_CASE("ADD_F32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreFPR(b, 3, b.Convert(b.Add(b.Convert(LoadFPR(b, 4), FLOAT32_TYPE),
|
||||
b.Convert(LoadFPR(b, 5), FLOAT32_TYPE)),
|
||||
FLOAT64_TYPE));
|
||||
StoreFPR(b, 3,
|
||||
b.Convert(b.Add(b.Convert(LoadFPR(b, 4), FLOAT32_TYPE),
|
||||
b.Convert(LoadFPR(b, 5), FLOAT32_TYPE)),
|
||||
FLOAT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -19,10 +19,11 @@ using xe::cpu::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("EXTRACT_INT8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
INT8_TYPE),
|
||||
INT64_TYPE));
|
||||
StoreGPR(
|
||||
b, 3,
|
||||
b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 4), INT8_TYPE), INT8_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
@@ -42,9 +43,10 @@ TEST_CASE("EXTRACT_INT8", "[instr]") {
|
||||
TEST_CASE("EXTRACT_INT8_CONSTANT", "[instr]") {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
TestFunction([i](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i),
|
||||
INT8_TYPE),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(
|
||||
b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i), INT8_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
@@ -62,10 +64,11 @@ TEST_CASE("EXTRACT_INT8_CONSTANT", "[instr]") {
|
||||
|
||||
TEST_CASE("EXTRACT_INT16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
INT16_TYPE),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(
|
||||
b.Extract(LoadVR(b, 4), b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
INT16_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
@@ -85,9 +88,10 @@ TEST_CASE("EXTRACT_INT16", "[instr]") {
|
||||
TEST_CASE("EXTRACT_INT16_CONSTANT", "[instr]") {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
TestFunction([i](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i),
|
||||
INT16_TYPE),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(
|
||||
b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i), INT16_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
@@ -104,10 +108,11 @@ TEST_CASE("EXTRACT_INT16_CONSTANT", "[instr]") {
|
||||
|
||||
TEST_CASE("EXTRACT_INT32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
INT32_TYPE),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(
|
||||
b.Extract(LoadVR(b, 4), b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
INT32_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
@@ -126,9 +131,10 @@ TEST_CASE("EXTRACT_INT32", "[instr]") {
|
||||
TEST_CASE("EXTRACT_INT32_CONSTANT", "[instr]") {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
TestFunction([i](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i),
|
||||
INT32_TYPE),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(
|
||||
b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i), INT32_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
|
||||
@@ -20,8 +20,9 @@ using xe::cpu::ppc::PPCContext;
|
||||
TEST_CASE("INSERT_INT8", "[instr]") {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
TestFunction test([i](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
StoreVR(b, 3,
|
||||
b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -44,8 +45,9 @@ TEST_CASE("INSERT_INT8", "[instr]") {
|
||||
TEST_CASE("INSERT_INT16", "[instr]") {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
TestFunction test([i](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT16_TYPE)));
|
||||
StoreVR(b, 3,
|
||||
b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT16_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -66,8 +68,9 @@ TEST_CASE("INSERT_INT16", "[instr]") {
|
||||
TEST_CASE("INSERT_INT32", "[instr]") {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
TestFunction test([i](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT32_TYPE)));
|
||||
StoreVR(b, 3,
|
||||
b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT32_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -19,8 +19,9 @@ TEST_CASE("PERMUTE_V128_BY_INT32_CONSTANT", "[instr]") {
|
||||
{
|
||||
uint32_t mask = MakePermuteMask(0, 0, 0, 1, 0, 2, 0, 3);
|
||||
TestFunction([mask](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4),
|
||||
LoadVR(b, 5), INT32_TYPE));
|
||||
StoreVR(b, 3,
|
||||
b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4), LoadVR(b, 5),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
@@ -36,8 +37,9 @@ TEST_CASE("PERMUTE_V128_BY_INT32_CONSTANT", "[instr]") {
|
||||
{
|
||||
uint32_t mask = MakePermuteMask(1, 0, 1, 1, 1, 2, 1, 3);
|
||||
TestFunction([mask](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4),
|
||||
LoadVR(b, 5), INT32_TYPE));
|
||||
StoreVR(b, 3,
|
||||
b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4), LoadVR(b, 5),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
@@ -53,8 +55,9 @@ TEST_CASE("PERMUTE_V128_BY_INT32_CONSTANT", "[instr]") {
|
||||
{
|
||||
uint32_t mask = MakePermuteMask(0, 3, 0, 2, 0, 1, 0, 0);
|
||||
TestFunction([mask](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4),
|
||||
LoadVR(b, 5), INT32_TYPE));
|
||||
StoreVR(b, 3,
|
||||
b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4), LoadVR(b, 5),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
@@ -70,8 +73,9 @@ TEST_CASE("PERMUTE_V128_BY_INT32_CONSTANT", "[instr]") {
|
||||
{
|
||||
uint32_t mask = MakePermuteMask(1, 3, 1, 2, 1, 1, 1, 0);
|
||||
TestFunction([mask](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4),
|
||||
LoadVR(b, 5), INT32_TYPE));
|
||||
StoreVR(b, 3,
|
||||
b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4), LoadVR(b, 5),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace xe {
|
||||
namespace cpu {
|
||||
namespace sandbox {
|
||||
|
||||
using xe::cpu::ppc::PPCContext;
|
||||
using xe::cpu::Runtime;
|
||||
using xe::cpu::ppc::PPCContext;
|
||||
|
||||
// TODO(benvanik): simple memory? move more into core?
|
||||
|
||||
|
||||
@@ -16,9 +16,10 @@ using xe::cpu::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("SHA_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -70,9 +71,10 @@ TEST_CASE("SHA_I8", "[instr]") {
|
||||
|
||||
TEST_CASE("SHA_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -124,9 +126,10 @@ TEST_CASE("SHA_I16", "[instr]") {
|
||||
|
||||
TEST_CASE("SHA_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -178,8 +181,9 @@ TEST_CASE("SHA_I32", "[instr]") {
|
||||
|
||||
TEST_CASE("SHA_I64", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.Sha(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
StoreGPR(b, 3,
|
||||
b.Sha(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -16,9 +16,10 @@ using xe::cpu::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("SHL_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -70,9 +71,10 @@ TEST_CASE("SHL_I8", "[instr]") {
|
||||
|
||||
TEST_CASE("SHL_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -124,9 +126,10 @@ TEST_CASE("SHL_I16", "[instr]") {
|
||||
|
||||
TEST_CASE("SHL_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -178,8 +181,9 @@ TEST_CASE("SHL_I32", "[instr]") {
|
||||
|
||||
TEST_CASE("SHL_I64", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.Shl(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
StoreGPR(b, 3,
|
||||
b.Shl(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -17,9 +17,10 @@ using xe::cpu::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("SHR_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -71,9 +72,10 @@ TEST_CASE("SHR_I8", "[instr]") {
|
||||
|
||||
TEST_CASE("SHR_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -125,9 +127,10 @@ TEST_CASE("SHR_I16", "[instr]") {
|
||||
|
||||
TEST_CASE("SHR_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -179,8 +182,9 @@ TEST_CASE("SHR_I32", "[instr]") {
|
||||
|
||||
TEST_CASE("SHR_I64", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.Shr(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
StoreGPR(b, 3,
|
||||
b.Shr(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -47,8 +47,9 @@ TEST_CASE("VECTOR_ADD_I8", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I8_SAT_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
StoreVR(b, 3,
|
||||
b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -73,8 +74,9 @@ TEST_CASE("VECTOR_ADD_I8_SAT_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I8_SAT_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -124,8 +126,9 @@ TEST_CASE("VECTOR_ADD_I16", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I16_SAT_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
StoreVR(b, 3,
|
||||
b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -150,8 +153,9 @@ TEST_CASE("VECTOR_ADD_I16_SAT_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I16_SAT_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -201,8 +205,9 @@ TEST_CASE("VECTOR_ADD_I32", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I32_SAT_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
StoreVR(b, 3,
|
||||
b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -236,8 +241,9 @@ TEST_CASE("VECTOR_ADD_I32_SAT_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I32_SAT_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -39,8 +39,9 @@ TEST_CASE("VECTOR_MAX_I8_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I8_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -75,8 +76,9 @@ TEST_CASE("VECTOR_MAX_I16_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I16_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -108,8 +110,9 @@ TEST_CASE("VECTOR_MAX_I32_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I32_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -39,8 +39,9 @@ TEST_CASE("VECTOR_MIN_I8_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I8_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -75,8 +76,9 @@ TEST_CASE("VECTOR_MIN_I16_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I16_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -108,8 +110,9 @@ TEST_CASE("VECTOR_MIN_I32_SIGNED", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I32_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
StoreVR(b, 3,
|
||||
b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -37,10 +37,12 @@ TEST_CASE("VECTOR_SHA_I8", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I8_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), b.LoadConstantVec128(vec128b(
|
||||
0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorSha(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128b(0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -76,9 +78,11 @@ TEST_CASE("VECTOR_SHA_I16", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I16_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), b.LoadConstantVec128(vec128s(
|
||||
0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorSha(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128s(0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -122,12 +126,14 @@ TEST_CASE("VECTOR_SHA_I32", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I32_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4, b.VectorSha(LoadVR(b, 5),
|
||||
b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorSha(LoadVR(b, 4), b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(
|
||||
b, 4,
|
||||
b.VectorSha(LoadVR(b, 5), b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -37,10 +37,12 @@ TEST_CASE("VECTOR_SHL_I8", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I8_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), b.LoadConstantVec128(vec128b(
|
||||
0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorShl(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128b(0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -76,9 +78,11 @@ TEST_CASE("VECTOR_SHL_I16", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I16_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), b.LoadConstantVec128(vec128s(
|
||||
0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorShl(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128s(0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -122,12 +126,14 @@ TEST_CASE("VECTOR_SHL_I32", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I32_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4, b.VectorShl(LoadVR(b, 5),
|
||||
b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorShl(LoadVR(b, 4), b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(
|
||||
b, 4,
|
||||
b.VectorShl(LoadVR(b, 5), b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
@@ -37,10 +37,12 @@ TEST_CASE("VECTOR_SHR_I8", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I8_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), b.LoadConstantVec128(vec128b(
|
||||
0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorShr(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128b(0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -76,9 +78,11 @@ TEST_CASE("VECTOR_SHR_I16", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I16_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), b.LoadConstantVec128(vec128s(
|
||||
0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorShr(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128s(0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
@@ -122,12 +126,14 @@ TEST_CASE("VECTOR_SHR_I32", "[instr]") {
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I32_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4, b.VectorShr(LoadVR(b, 5),
|
||||
b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
StoreVR(
|
||||
b, 3,
|
||||
b.VectorShr(LoadVR(b, 4), b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(
|
||||
b, 4,
|
||||
b.VectorShr(LoadVR(b, 5), b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
|
||||
Reference in New Issue
Block a user