Merge branch 'master' of https://github.com/xenia-project/xenia into canary_experimental
This commit is contained in:
@@ -99,6 +99,19 @@ struct VECTOR_CONVERT_F2I
|
|||||||
e.ChangeMxcsrMode(MXCSRMode::Vmx);
|
e.ChangeMxcsrMode(MXCSRMode::Vmx);
|
||||||
Xmm src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
|
Xmm src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
|
||||||
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
if (i.instr->flags & ARITHMETIC_UNSIGNED) {
|
||||||
|
if (e.IsFeatureEnabled(kX64EmitAVX512Ortho)) {
|
||||||
|
Opmask mask = e.k1;
|
||||||
|
// Mask positive values and unordered values
|
||||||
|
// _CMP_NLT_UQ
|
||||||
|
e.vcmpps(mask, i.src1, e.GetXmmConstPtr(XMMZero), 0x15);
|
||||||
|
|
||||||
|
// vcvttps2udq will saturate overflowing positive values and unordered
|
||||||
|
// values to UINT_MAX. Mask registers will write zero everywhere
|
||||||
|
// else (negative values)
|
||||||
|
e.vcvttps2udq(i.dest.reg() | mask | e.T_z, i.src1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// clamp to min 0
|
// clamp to min 0
|
||||||
e.vmaxps(e.xmm0, src1, e.GetXmmConstPtr(XMMZero));
|
e.vmaxps(e.xmm0, src1, e.GetXmmConstPtr(XMMZero));
|
||||||
|
|
||||||
@@ -621,6 +634,15 @@ struct VECTOR_ADD
|
|||||||
case INT32_TYPE:
|
case INT32_TYPE:
|
||||||
if (saturate) {
|
if (saturate) {
|
||||||
if (is_unsigned) {
|
if (is_unsigned) {
|
||||||
|
if (e.IsFeatureEnabled(kX64EmitAVX512Ortho)) {
|
||||||
|
e.vpaddd(dest, src1, src2);
|
||||||
|
Opmask saturate = e.k1;
|
||||||
|
// _mm_cmplt_epu32_mask
|
||||||
|
e.vpcmpud(saturate, dest, src1, 0x1);
|
||||||
|
e.vpternlogd(dest | saturate, dest, dest, 0xFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// xmm0 is the only temp register that can be used by
|
// xmm0 is the only temp register that can be used by
|
||||||
// src1/src2.
|
// src1/src2.
|
||||||
e.vpaddd(e.xmm1, src1, src2);
|
e.vpaddd(e.xmm1, src1, src2);
|
||||||
@@ -637,6 +659,20 @@ struct VECTOR_ADD
|
|||||||
} else {
|
} else {
|
||||||
e.vpaddd(e.xmm1, src1, src2);
|
e.vpaddd(e.xmm1, src1, src2);
|
||||||
|
|
||||||
|
if (e.IsFeatureEnabled(kX64EmitAVX512Ortho |
|
||||||
|
kX64EmitAVX512DQ)) {
|
||||||
|
e.vmovdqa32(e.xmm3, src1);
|
||||||
|
e.vpternlogd(e.xmm3, e.xmm1, src2, 0b00100100);
|
||||||
|
|
||||||
|
const Opmask saturate = e.k1;
|
||||||
|
e.vpmovd2m(saturate, e.xmm3);
|
||||||
|
|
||||||
|
e.vpsrad(e.xmm2, e.xmm1, 31);
|
||||||
|
e.vpxord(e.xmm2, e.xmm2, e.GetXmmConstPtr(XMMSignMaskI32));
|
||||||
|
e.vpblendmd(dest | saturate, e.xmm1, e.xmm2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Overflow results if two inputs are the same sign and the
|
// Overflow results if two inputs are the same sign and the
|
||||||
// result isn't the same sign. if ((s32b)(~(src1 ^ src2) &
|
// result isn't the same sign. if ((s32b)(~(src1 ^ src2) &
|
||||||
// (src1 ^ res)) < 0) then overflowed
|
// (src1 ^ res)) < 0) then overflowed
|
||||||
|
|||||||
@@ -2839,6 +2839,10 @@ struct NOT_I64 : Sequence<NOT_I64, I<OPCODE_NOT, I64Op, I64Op>> {
|
|||||||
};
|
};
|
||||||
struct NOT_V128 : Sequence<NOT_V128, I<OPCODE_NOT, V128Op, V128Op>> {
|
struct NOT_V128 : Sequence<NOT_V128, I<OPCODE_NOT, V128Op, V128Op>> {
|
||||||
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
|
if (e.IsFeatureEnabled(kX64EmitAVX512Ortho)) {
|
||||||
|
e.vpternlogd(i.dest, i.src1, i.src1, 0b01010101);
|
||||||
|
return;
|
||||||
|
}
|
||||||
SimdDomain domain = e.DeduceSimdDomain(i.src1.value);
|
SimdDomain domain = e.DeduceSimdDomain(i.src1.value);
|
||||||
if (domain == SimdDomain::FLOATING) {
|
if (domain == SimdDomain::FLOATING) {
|
||||||
e.vxorps(i.dest, i.src1, e.GetXmmConstPtr(XMMFFFF /* FF... */));
|
e.vxorps(i.dest, i.src1, e.GetXmmConstPtr(XMMFFFF /* FF... */));
|
||||||
|
|||||||
@@ -349,8 +349,8 @@ class TestRunner {
|
|||||||
uint32_t expected = std::strtoul(ccs, nullptr, 16);
|
uint32_t expected = std::strtoul(ccs, nullptr, 16);
|
||||||
uint8_t actual = *p;
|
uint8_t actual = *p;
|
||||||
|
|
||||||
expecteds.AppendFormat(" %02X", expected);
|
expecteds.AppendFormat(" {:02X}", expected);
|
||||||
actuals.AppendFormat(" %02X", actual);
|
actuals.AppendFormat(" {:02X}", actual);
|
||||||
|
|
||||||
if (expected != actual) {
|
if (expected != actual) {
|
||||||
any_failed = true;
|
any_failed = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user