translate: Return by bool in helpers where applicable

Gets rid of a bit of duplication regarding the early-out cases and makes
all helpers functions consistent (previously some had a return type of
bool, while others had a return type of void).
This commit is contained in:
Lioncash 2018-07-22 16:55:40 -04:00 committed by MerryMage
parent d65b056eba
commit 3447c82656
6 changed files with 132 additions and 268 deletions

View file

@ -7,13 +7,13 @@
#include "frontend/A64/translate/impl/impl.h" #include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic::A64 { namespace Dynarmic::A64 {
namespace {
enum class SM3TTVariant { enum class SM3TTVariant {
A, A,
B, B,
}; };
static void SM3TT1(TranslatorVisitor& v, Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd, SM3TTVariant behavior) { bool SM3TT1(TranslatorVisitor& v, Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd, SM3TTVariant behavior) {
const IR::U128 d = v.ir.GetQ(Vd); const IR::U128 d = v.ir.GetQ(Vd);
const IR::U128 m = v.ir.GetQ(Vm); const IR::U128 m = v.ir.GetQ(Vm);
const IR::U128 n = v.ir.GetQ(Vn); const IR::U128 n = v.ir.GetQ(Vn);
@ -45,9 +45,10 @@ static void SM3TT1(TranslatorVisitor& v, Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd, SM
const IR::U128 result = v.ir.VectorSetElement(32, tmp3, 3, final_tt1); const IR::U128 result = v.ir.VectorSetElement(32, tmp3, 3, final_tt1);
v.ir.SetQ(Vd, result); v.ir.SetQ(Vd, result);
return true;
} }
static void SM3TT2(TranslatorVisitor& v, Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd, SM3TTVariant behavior) { bool SM3TT2(TranslatorVisitor& v, Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd, SM3TTVariant behavior) {
const IR::U128 d = v.ir.GetQ(Vd); const IR::U128 d = v.ir.GetQ(Vd);
const IR::U128 m = v.ir.GetQ(Vm); const IR::U128 m = v.ir.GetQ(Vm);
const IR::U128 n = v.ir.GetQ(Vn); const IR::U128 n = v.ir.GetQ(Vn);
@ -79,26 +80,24 @@ static void SM3TT2(TranslatorVisitor& v, Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd, SM
const IR::U128 result = v.ir.VectorSetElement(32, tmp3, 3, top_result); const IR::U128 result = v.ir.VectorSetElement(32, tmp3, 3, top_result);
v.ir.SetQ(Vd, result); v.ir.SetQ(Vd, result);
return true;
} }
} // Anonymous namespace
bool TranslatorVisitor::SM3TT1A(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) { bool TranslatorVisitor::SM3TT1A(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) {
SM3TT1(*this, Vm, imm2, Vn, Vd, SM3TTVariant::A); return SM3TT1(*this, Vm, imm2, Vn, Vd, SM3TTVariant::A);
return true;
} }
bool TranslatorVisitor::SM3TT1B(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) { bool TranslatorVisitor::SM3TT1B(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) {
SM3TT1(*this, Vm, imm2, Vn, Vd, SM3TTVariant::B); return SM3TT1(*this, Vm, imm2, Vn, Vd, SM3TTVariant::B);
return true;
} }
bool TranslatorVisitor::SM3TT2A(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) { bool TranslatorVisitor::SM3TT2A(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) {
SM3TT2(*this, Vm, imm2, Vn, Vd, SM3TTVariant::A); return SM3TT2(*this, Vm, imm2, Vn, Vd, SM3TTVariant::A);
return true;
} }
bool TranslatorVisitor::SM3TT2B(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) { bool TranslatorVisitor::SM3TT2B(Vec Vm, Imm<2> imm2, Vec Vn, Vec Vd) {
SM3TT2(*this, Vm, imm2, Vn, Vd, SM3TTVariant::B); return SM3TT2(*this, Vm, imm2, Vn, Vd, SM3TTVariant::B);
return true;
} }
} // namespace Dynarmic::A64 } // namespace Dynarmic::A64

View file

@ -14,8 +14,12 @@ enum class Transposition {
TRN2, TRN2,
}; };
void VectorTranspose(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, bool VectorTranspose(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd,
Transposition type) { Transposition type) {
if (!Q && size == 0b11) {
return v.ReservedValue();
}
const size_t datasize = Q ? 128 : 64; const size_t datasize = Q ? 128 : 64;
const u8 esize = static_cast<u8>(8 << size.ZeroExtend()); const u8 esize = static_cast<u8>(8 << size.ZeroExtend());
@ -61,6 +65,7 @@ void VectorTranspose(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn,
}(); }();
v.V(datasize, Vd, result); v.V(datasize, Vd, result);
return true;
} }
enum class UnzipType { enum class UnzipType {
@ -68,7 +73,11 @@ enum class UnzipType {
Odd, Odd,
}; };
void VectorUnzip(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, UnzipType type) { bool VectorUnzip(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, UnzipType type) {
if (size == 0b11 && !Q) {
return v.ReservedValue();
}
const size_t datasize = Q ? 128 : 64; const size_t datasize = Q ? 128 : 64;
const size_t esize = 8 << size.ZeroExtend(); const size_t esize = 8 << size.ZeroExtend();
@ -86,43 +95,24 @@ void VectorUnzip(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec
} }
v.V(datasize, Vd, result); v.V(datasize, Vd, result);
return true;
} }
} // Anonymous namespace } // Anonymous namespace
bool TranslatorVisitor::TRN1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::TRN1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
if (!Q && size == 0b11) { return VectorTranspose(*this, Q, size, Vm, Vn, Vd, Transposition::TRN1);
return ReservedValue();
}
VectorTranspose(*this, Q, size, Vm, Vn, Vd, Transposition::TRN1);
return true;
} }
bool TranslatorVisitor::TRN2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::TRN2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
if (!Q && size == 0b11) { return VectorTranspose(*this, Q, size, Vm, Vn, Vd, Transposition::TRN2);
return ReservedValue();
}
VectorTranspose(*this, Q, size, Vm, Vn, Vd, Transposition::TRN2);
return true;
} }
bool TranslatorVisitor::UZP1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::UZP1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
if (size == 0b11 && !Q) { return VectorUnzip(*this, Q, size, Vm, Vn, Vd, UnzipType::Even);
return ReservedValue();
}
VectorUnzip(*this, Q, size, Vm, Vn, Vd, UnzipType::Even);
return true;
} }
bool TranslatorVisitor::UZP2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::UZP2(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
if (size == 0b11 && !Q) { return VectorUnzip(*this, Q, size, Vm, Vn, Vd, UnzipType::Odd);
return ReservedValue();
}
VectorUnzip(*this, Q, size, Vm, Vn, Vd, UnzipType::Odd);
return true;
} }
bool TranslatorVisitor::ZIP1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::ZIP1(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {

View file

@ -18,8 +18,12 @@ enum class Signedness {
Unsigned, Unsigned,
}; };
void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, bool ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
ShiftExtraBehavior behavior, Signedness signedness) { ShiftExtraBehavior behavior, Signedness signedness) {
if (!immh.Bit<3>()) {
return v.ReservedValue();
}
const size_t esize = 64; const size_t esize = 64;
const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend()); const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend());
@ -37,10 +41,15 @@ void ShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
} }
v.V_scalar(esize, Vd, result); v.V_scalar(esize, Vd, result);
return true;
} }
void RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, bool RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
ShiftExtraBehavior behavior, Signedness signedness) { ShiftExtraBehavior behavior, Signedness signedness) {
if (!immh.Bit<3>()) {
return v.ReservedValue();
}
const size_t esize = 64; const size_t esize = 64;
const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend()); const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend());
@ -64,6 +73,7 @@ void RoundingShiftRight(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn,
}(); }();
v.V_scalar(esize, Vd, result); v.V_scalar(esize, Vd, result);
return true;
} }
enum class ShiftDirection { enum class ShiftDirection {
@ -71,8 +81,12 @@ enum class ShiftDirection {
Right, Right,
}; };
void ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, bool ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
ShiftDirection direction) { ShiftDirection direction) {
if (!immh.Bit<3>()) {
return v.ReservedValue();
}
const size_t esize = 64; const size_t esize = 64;
const u8 shift_amount = [&] { const u8 shift_amount = [&] {
@ -104,6 +118,7 @@ void ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec
const IR::U64 result = v.ir.Or(v.ir.And(operand2, v.ir.Not(v.ir.Imm64(mask))), shifted); const IR::U64 result = v.ir.Or(v.ir.And(operand2, v.ir.Not(v.ir.Imm64(mask))), shifted);
v.V_scalar(esize, Vd, result); v.V_scalar(esize, Vd, result);
return true;
} }
bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness sign) { bool ScalarFPConvertWithRound(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, Signedness sign) {
@ -153,57 +168,27 @@ bool TranslatorVisitor::FCVTZU_fix_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
} }
bool TranslatorVisitor::SLI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SLI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return ShiftAndInsert(*this, immh, immb, Vn, Vd, ShiftDirection::Left);
return ReservedValue();
}
ShiftAndInsert(*this, immh, immb, Vn, Vd, ShiftDirection::Left);
return true;
} }
bool TranslatorVisitor::SRI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SRI_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return ShiftAndInsert(*this, immh, immb, Vn, Vd, ShiftDirection::Right);
return ReservedValue();
}
ShiftAndInsert(*this, immh, immb, Vn, Vd, ShiftDirection::Right);
return true;
} }
bool TranslatorVisitor::SRSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SRSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return ReservedValue();
}
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::SRSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SRSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return ReservedValue();
}
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::SSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return ReservedValue();
}
ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::SSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return ReservedValue();
}
ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::SHL_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SHL_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
@ -222,39 +207,19 @@ bool TranslatorVisitor::SHL_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
} }
bool TranslatorVisitor::URSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::URSHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return ReservedValue();
}
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return true;
} }
bool TranslatorVisitor::URSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::URSRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return ReservedValue();
}
RoundingShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return true;
} }
bool TranslatorVisitor::USHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::USHR_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return ReservedValue();
}
ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return true;
} }
bool TranslatorVisitor::USRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::USRA_1(Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (!immh.Bit<3>()) { return ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return ReservedValue();
}
ShiftRight(*this, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return true;
} }
} // namespace Dynarmic::A64 } // namespace Dynarmic::A64

View file

@ -8,7 +8,7 @@
#include "frontend/A64/translate/impl/impl.h" #include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic::A64 { namespace Dynarmic::A64 {
namespace {
enum class ShiftExtraBehavior { enum class ShiftExtraBehavior {
None, None,
Accumulate, Accumulate,
@ -20,8 +20,16 @@ enum class Signedness {
Unsigned Unsigned
}; };
static void ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, bool ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
ShiftExtraBehavior behavior, Signedness signedness) { ShiftExtraBehavior behavior, Signedness signedness) {
if (immh == 0b0000) {
return v.DecodeError();
}
if (immh.Bit<3>() && !Q) {
return v.ReservedValue();
}
const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend()); const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend());
const size_t datasize = Q ? 128 : 64; const size_t datasize = Q ? 128 : 64;
@ -41,10 +49,19 @@ static void ShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, V
} }
v.V(datasize, Vd, result); v.V(datasize, Vd, result);
return true;
} }
static void RoundingShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, bool RoundingShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
ShiftExtraBehavior behavior, Signedness signedness) { ShiftExtraBehavior behavior, Signedness signedness) {
if (immh == 0b0000) {
return v.DecodeError();
}
if (!Q && immh.Bit<3>()) {
return v.ReservedValue();
}
const size_t datasize = Q ? 128 : 64; const size_t datasize = Q ? 128 : 64;
const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend()); const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend());
const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend()); const u8 shift_amount = static_cast<u8>((esize * 2) - concatenate(immh, immb).ZeroExtend());
@ -68,10 +85,19 @@ static void RoundingShiftRight(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3>
} }
v.V(datasize, Vd, corrected_result); v.V(datasize, Vd, corrected_result);
return true;
} }
static void ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, bool ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
ShiftExtraBehavior behavior) { ShiftExtraBehavior behavior) {
if (immh == 0b0000) {
return v.DecodeError();
}
if (immh.Bit<3>()) {
return v.ReservedValue();
}
const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend()); const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend());
const size_t source_esize = 2 * esize; const size_t source_esize = 2 * esize;
const size_t part = Q ? 1 : 0; const size_t part = Q ? 1 : 0;
@ -90,10 +116,19 @@ static void ShiftRightNarrowing(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3
v.ir.VectorLogicalShiftRight(source_esize, operand, shift_amount)); v.ir.VectorLogicalShiftRight(source_esize, operand, shift_amount));
v.Vpart(64, Vd, part, result); v.Vpart(64, Vd, part, result);
return true;
} }
static void ShiftLeftLong(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd, bool ShiftLeftLong(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
Signedness signedness) { Signedness signedness) {
if (immh == 0b0000) {
return v.DecodeError();
}
if (immh.Bit<3>()) {
return v.ReservedValue();
}
const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend()); const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend());
const size_t datasize = 64; const size_t datasize = 64;
const size_t part = Q ? 1 : 0; const size_t part = Q ? 1 : 0;
@ -110,56 +145,24 @@ static void ShiftLeftLong(TranslatorVisitor& v, bool Q, Imm<4> immh, Imm<3> immb
const IR::U128 result = v.ir.VectorLogicalShiftLeft(2 * esize, expanded_operand, shift_amount); const IR::U128 result = v.ir.VectorLogicalShiftLeft(2 * esize, expanded_operand, shift_amount);
v.V(2 * datasize, Vd, result); v.V(2 * datasize, Vd, result);
return true;
} }
} // Anonymous namespace
bool TranslatorVisitor::SSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return ShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return DecodeError();
}
if (immh.Bit<3>() && !Q) {
return ReservedValue();
}
ShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::SRSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SRSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return RoundingShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return DecodeError();
}
if (!Q && immh.Bit<3>()) {
return ReservedValue();
}
RoundingShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::SRSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SRSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return RoundingShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return DecodeError();
}
if (!Q && immh.Bit<3>()) {
return ReservedValue();
}
RoundingShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::SSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return ShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return DecodeError();
}
if (immh.Bit<3>() && !Q) {
return ReservedValue();
}
ShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::SHL_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SHL_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
@ -182,103 +185,35 @@ bool TranslatorVisitor::SHL_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd)
} }
bool TranslatorVisitor::SHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None);
return DecodeError();
}
if (immh.Bit<3>()) {
return ReservedValue();
}
ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None);
return true;
} }
bool TranslatorVisitor::RSHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::RSHRN(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Round);
return DecodeError();
}
if (immh.Bit<3>()) {
return ReservedValue();
}
ShiftRightNarrowing(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Round);
return true;
} }
bool TranslatorVisitor::SSHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SSHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return ShiftLeftLong(*this, Q, immh, immb, Vn, Vd, Signedness::Signed);
return DecodeError();
}
if (immh.Bit<3>()) {
return ReservedValue();
}
ShiftLeftLong(*this, Q, immh, immb, Vn, Vd, Signedness::Signed);
return true;
} }
bool TranslatorVisitor::URSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::URSHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return RoundingShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return DecodeError();
}
if (!Q && immh.Bit<3>()) {
return ReservedValue();
}
RoundingShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return true;
} }
bool TranslatorVisitor::URSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::URSRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return RoundingShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return DecodeError();
}
if (!Q && immh.Bit<3>()) {
return ReservedValue();
}
RoundingShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return true;
} }
bool TranslatorVisitor::USHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::USHR_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return ShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return DecodeError();
}
if (immh.Bit<3>() && !Q) {
return ReservedValue();
}
ShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::None, Signedness::Unsigned);
return true;
} }
bool TranslatorVisitor::USRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::USRA_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return ShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return DecodeError();
}
if (immh.Bit<3>() && !Q) {
return ReservedValue();
}
ShiftRight(*this, Q, immh, immb, Vn, Vd, ShiftExtraBehavior::Accumulate, Signedness::Unsigned);
return true;
} }
bool TranslatorVisitor::USHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::USHLL(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {
if (immh == 0b0000) { return ShiftLeftLong(*this, Q, immh, immb, Vn, Vd, Signedness::Unsigned);
return DecodeError();
}
if (immh.Bit<3>()) {
return ReservedValue();
}
ShiftLeftLong(*this, Q, immh, immb, Vn, Vd, Signedness::Unsigned);
return true;
} }
bool TranslatorVisitor::SRI_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) { bool TranslatorVisitor::SRI_2(bool Q, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd) {

View file

@ -18,8 +18,12 @@ enum class ExtraBehavior {
Round Round
}; };
static void HighNarrowingOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd, bool HighNarrowingOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd,
HighNarrowingOp op, ExtraBehavior behavior) { HighNarrowingOp op, ExtraBehavior behavior) {
if (size == 0b11) {
return v.ReservedValue();
}
const size_t part = Q; const size_t part = Q;
const size_t esize = 8 << size.ZeroExtend(); const size_t esize = 8 << size.ZeroExtend();
const size_t doubled_esize = 2 * esize; const size_t doubled_esize = 2 * esize;
@ -43,6 +47,7 @@ static void HighNarrowingOperation(TranslatorVisitor& v, bool Q, Imm<2> size, Ve
v.ir.VectorLogicalShiftRight(doubled_esize, wide, static_cast<u8>(esize))); v.ir.VectorLogicalShiftRight(doubled_esize, wide, static_cast<u8>(esize)));
v.Vpart(64, Vd, part, result); v.Vpart(64, Vd, part, result);
return true;
} }
enum class AbsDiffExtraBehavior { enum class AbsDiffExtraBehavior {
@ -252,39 +257,19 @@ bool TranslatorVisitor::MUL_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
} }
bool TranslatorVisitor::ADDHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::ADDHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
if (size == 0b11) { return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, HighNarrowingOp::Add, ExtraBehavior::None);
return ReservedValue();
}
HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, HighNarrowingOp::Add, ExtraBehavior::None);
return true;
} }
bool TranslatorVisitor::RADDHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::RADDHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
if (size == 0b11) { return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, HighNarrowingOp::Add, ExtraBehavior::Round);
return ReservedValue();
}
HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, HighNarrowingOp::Add, ExtraBehavior::Round);
return true;
} }
bool TranslatorVisitor::SUBHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::SUBHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
if (size == 0b11) { return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, HighNarrowingOp::Subtract, ExtraBehavior::None);
return ReservedValue();
}
HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, HighNarrowingOp::Subtract, ExtraBehavior::None);
return true;
} }
bool TranslatorVisitor::RSUBHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::RSUBHN(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
if (size == 0b11) { return HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, HighNarrowingOp::Subtract, ExtraBehavior::Round);
return ReservedValue();
}
HighNarrowingOperation(*this, Q, size, Vm, Vn, Vd, HighNarrowingOp::Subtract, ExtraBehavior::Round);
return true;
} }
bool TranslatorVisitor::SHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) { bool TranslatorVisitor::SHADD(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {

View file

@ -23,8 +23,12 @@ enum class ExtraBehavior {
Subtract, Subtract,
}; };
void MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd, bool MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd,
ExtraBehavior extra_behavior) { ExtraBehavior extra_behavior) {
if (size != 0b01 && size != 0b10) {
return v.UnallocatedEncoding();
}
const auto [index, Vm] = Combine(size, H, L, M, Vmlo); const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
const size_t idxdsize = H == 1 ? 128 : 64; const size_t idxdsize = H == 1 ? 128 : 64;
const size_t esize = 8 << size.ZeroExtend(); const size_t esize = 8 << size.ZeroExtend();
@ -42,34 +46,20 @@ void MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<
} }
v.V(datasize, Vd, result); v.V(datasize, Vd, result);
return true;
} }
} // Anonymous namespace } // Anonymous namespace
bool TranslatorVisitor::MLA_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) { bool TranslatorVisitor::MLA_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
if (size != 0b01 && size != 0b10) { return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Accumulate);
return UnallocatedEncoding();
}
MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Accumulate);
return true;
} }
bool TranslatorVisitor::MLS_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) { bool TranslatorVisitor::MLS_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
if (size != 0b01 && size != 0b10) { return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Subtract);
return UnallocatedEncoding();
}
MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::Subtract);
return true;
} }
bool TranslatorVisitor::MUL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) { bool TranslatorVisitor::MUL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
if (size != 0b01 && size != 0b10) { return MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::None);
return UnallocatedEncoding();
}
MultiplyByElement(*this, Q, size, L, M, Vmlo, H, Vn, Vd, ExtraBehavior::None);
return true;
} }
bool TranslatorVisitor::FMUL_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) { bool TranslatorVisitor::FMUL_elt_4(bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {