saturated: Implement QASX, QSAX, UQASX, UQSAX

This commit is contained in:
MerryMage 2017-04-09 10:39:13 +01:00
parent 01abb65960
commit 1c21ae6bcd
2 changed files with 81 additions and 20 deletions

View file

@ -184,16 +184,6 @@ bool ArmTranslatorVisitor::arm_QADD16(Cond cond, Reg n, Reg d, Reg m) {
return true; return true;
} }
bool ArmTranslatorVisitor::arm_QASX(Cond cond, Reg n, Reg d, Reg m) {
UNUSED(cond, n, d, m);
return InterpretThisInstruction();
}
bool ArmTranslatorVisitor::arm_QSAX(Cond cond, Reg n, Reg d, Reg m) {
UNUSED(cond, n, d, m);
return InterpretThisInstruction();
}
bool ArmTranslatorVisitor::arm_QSUB8(Cond cond, Reg n, Reg d, Reg m) { bool ArmTranslatorVisitor::arm_QSUB8(Cond cond, Reg n, Reg d, Reg m) {
if (d == Reg::PC || n == Reg::PC || m == Reg::PC) if (d == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();
@ -230,16 +220,6 @@ bool ArmTranslatorVisitor::arm_UQADD16(Cond cond, Reg n, Reg d, Reg m) {
return true; return true;
} }
bool ArmTranslatorVisitor::arm_UQASX(Cond cond, Reg n, Reg d, Reg m) {
UNUSED(cond, n, d, m);
return InterpretThisInstruction();
}
bool ArmTranslatorVisitor::arm_UQSAX(Cond cond, Reg n, Reg d, Reg m) {
UNUSED(cond, n, d, m);
return InterpretThisInstruction();
}
bool ArmTranslatorVisitor::arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m) { bool ArmTranslatorVisitor::arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m) {
if (d == Reg::PC || n == Reg::PC || m == Reg::PC) if (d == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction(); return UnpredictableInstruction();

View file

@ -158,6 +158,87 @@ bool ArmTranslatorVisitor::arm_QDSUB(Cond cond, Reg n, Reg d, Reg m) {
return true; return true;
} }
// Parallel saturated instructions
bool ArmTranslatorVisitor::arm_QASX(Cond cond, Reg n, Reg d, Reg m) {
if (d == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
// QASX <Rd>, <Rn>, <Rm>
if (ConditionPassed(cond)) {
auto Rn = ir.GetRegister(n);
auto Rm = ir.GetRegister(m);
auto Rn_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(Rn));
auto Rn_hi = ir.SignExtendHalfToWord(MostSignificantHalf(ir, Rn));
auto Rm_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(Rm));
auto Rm_hi = ir.SignExtendHalfToWord(MostSignificantHalf(ir, Rm));
auto diff = ir.SignedSaturation(ir.Sub(Rn_lo, Rm_hi), 16).result;
auto sum = ir.SignedSaturation(ir.Add(Rn_hi, Rm_lo), 16).result;
auto result = Pack2x16To1x32(ir, diff, sum);
ir.SetRegister(d, result);
}
return true;
}
bool ArmTranslatorVisitor::arm_QSAX(Cond cond, Reg n, Reg d, Reg m) {
if (d == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
// QSAX <Rd>, <Rn>, <Rm>
if (ConditionPassed(cond)) {
auto Rn = ir.GetRegister(n);
auto Rm = ir.GetRegister(m);
auto Rn_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(Rn));
auto Rn_hi = ir.SignExtendHalfToWord(MostSignificantHalf(ir, Rn));
auto Rm_lo = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(Rm));
auto Rm_hi = ir.SignExtendHalfToWord(MostSignificantHalf(ir, Rm));
auto sum = ir.SignedSaturation(ir.Add(Rn_lo, Rm_hi), 16).result;
auto diff = ir.SignedSaturation(ir.Sub(Rn_hi, Rm_lo), 16).result;
auto result = Pack2x16To1x32(ir, sum, diff);
ir.SetRegister(d, result);
}
return true;
}
bool ArmTranslatorVisitor::arm_UQASX(Cond cond, Reg n, Reg d, Reg m) {
if (d == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
// UQASX <Rd>, <Rn>, <Rm>
if (ConditionPassed(cond)) {
auto Rn = ir.GetRegister(n);
auto Rm = ir.GetRegister(m);
auto Rn_lo = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(Rn));
auto Rn_hi = ir.ZeroExtendHalfToWord(MostSignificantHalf(ir, Rn));
auto Rm_lo = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(Rm));
auto Rm_hi = ir.ZeroExtendHalfToWord(MostSignificantHalf(ir, Rm));
auto diff = ir.UnsignedSaturation(ir.Sub(Rn_lo, Rm_hi), 16).result;
auto sum = ir.UnsignedSaturation(ir.Add(Rn_hi, Rm_lo), 16).result;
auto result = Pack2x16To1x32(ir, diff, sum);
ir.SetRegister(d, result);
}
return true;
}
bool ArmTranslatorVisitor::arm_UQSAX(Cond cond, Reg n, Reg d, Reg m) {
if (d == Reg::PC || n == Reg::PC || m == Reg::PC)
return UnpredictableInstruction();
// UQSAX <Rd>, <Rn>, <Rm>
if (ConditionPassed(cond)) {
auto Rn = ir.GetRegister(n);
auto Rm = ir.GetRegister(m);
auto Rn_lo = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(Rn));
auto Rn_hi = ir.ZeroExtendHalfToWord(MostSignificantHalf(ir, Rn));
auto Rm_lo = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(Rm));
auto Rm_hi = ir.ZeroExtendHalfToWord(MostSignificantHalf(ir, Rm));
auto sum = ir.UnsignedSaturation(ir.Add(Rn_lo, Rm_hi), 16).result;
auto diff = ir.UnsignedSaturation(ir.Sub(Rn_hi, Rm_lo), 16).result;
auto result = Pack2x16To1x32(ir, sum, diff);
ir.SetRegister(d, result);
}
return true;
}
} // namespace Arm } // namespace Arm
} // namespace Dynarmic } // namespace Dynarmic