A64: Handle reserved instruction cases more specifically where applicable
These are cases that are defined as reserved within the ARMv8 reference manual, so we can handle them as such instead of as unallocated encodings. While this doesn't actually change emulated behavior, it does at least allow the JIT to generate the more appropriate exception.
This commit is contained in:
parent
e7361148db
commit
8309d49588
7 changed files with 60 additions and 30 deletions
|
@ -11,7 +11,9 @@ namespace Dynarmic::A64 {
|
|||
|
||||
bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
|
||||
const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
|
||||
if (size > 3) return UnallocatedEncoding();
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
|
||||
const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
|
||||
|
@ -26,8 +28,13 @@ bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
|
|||
|
||||
bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
|
||||
const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
|
||||
if (size > 3) return UnallocatedEncoding();
|
||||
if (size == 3 && !Q) return ReservedValue();
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
if (size == 3 && !Q) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
|
||||
const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
|
||||
|
@ -43,8 +50,14 @@ bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
|
|||
|
||||
bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
|
||||
const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
|
||||
if (size > 3) return UnallocatedEncoding();
|
||||
if (size == 3 && !Q) return ReservedValue();
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
if (size == 3 && !Q) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = 8 << size;
|
||||
const size_t datasize = Q ? 128 : 64;
|
||||
|
||||
|
@ -59,8 +72,13 @@ bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
|
|||
|
||||
bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
|
||||
const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
|
||||
if (size == 2 && !Q) return UnallocatedEncoding();
|
||||
if (size > 2) return UnallocatedEncoding();
|
||||
if (size == 2 && !Q) {
|
||||
return UnallocatedEncoding();
|
||||
}
|
||||
|
||||
if (size > 2) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
|
||||
const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
|
||||
|
@ -77,9 +95,17 @@ bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
|
|||
|
||||
bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
|
||||
const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
|
||||
if (size < 3 && Q) return UnallocatedEncoding();
|
||||
if (size == 3 && !Q) return UnallocatedEncoding();
|
||||
if (size > 3) return UnallocatedEncoding();
|
||||
if (size < 3 && Q) {
|
||||
return UnallocatedEncoding();
|
||||
}
|
||||
|
||||
if (size == 3 && !Q) {
|
||||
return UnallocatedEncoding();
|
||||
}
|
||||
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t idxdsize = imm5.Bit<4>() ? 128 : 64;
|
||||
const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
|
||||
|
@ -96,7 +122,9 @@ bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
|
|||
|
||||
bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
|
||||
const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
|
||||
if (size > 3) return UnallocatedEncoding();
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t index = imm5.ZeroExtend<size_t>() >> (size + 1);
|
||||
const size_t esize = 8 << size;
|
||||
|
@ -111,7 +139,9 @@ bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
|
|||
|
||||
bool TranslatorVisitor::INS_elt(Imm<5> imm5, Imm<4> imm4, Vec Vn, Vec Vd) {
|
||||
const size_t size = Common::LowestSetBit(imm5.ZeroExtend());
|
||||
if (size > 3) return UnallocatedEncoding();
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t dst_index = imm5.ZeroExtend<size_t>() >> (size + 1);
|
||||
const size_t src_index = imm4.ZeroExtend<size_t>() >> size;
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Dynarmic::A64 {
|
|||
|
||||
bool TranslatorVisitor::EXT(bool Q, Vec Vm, Imm<4> imm4, Vec Vn, Vec Vd) {
|
||||
if (!Q && imm4.Bit<3>()) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t datasize = Q ? 128 : 64;
|
||||
|
|
|
@ -157,11 +157,11 @@ bool ShiftAndInsert(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec
|
|||
bool ShiftRightNarrowing(TranslatorVisitor& v, Imm<4> immh, Imm<3> immb, Vec Vn, Vec Vd,
|
||||
Narrowing narrowing, Signedness signedness) {
|
||||
if (immh == 0b0000) {
|
||||
return v.UnallocatedEncoding();
|
||||
return v.ReservedValue();
|
||||
}
|
||||
|
||||
if (immh.Bit<3>()) {
|
||||
return v.UnallocatedEncoding();
|
||||
return v.ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = 8 << Common::HighestSetBit(immh.ZeroExtend());
|
||||
|
|
|
@ -154,7 +154,7 @@ bool TranslatorVisitor::FCVTPU_2(bool sz, Vec Vn, Vec Vd) {
|
|||
|
||||
bool TranslatorVisitor::FCVTXN_1(bool sz, Vec Vn, Vec Vd) {
|
||||
if (!sz) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const IR::U64 element = V_scalar(64, Vn);
|
||||
|
|
|
@ -27,7 +27,7 @@ enum class ExtraBehavior {
|
|||
bool MultiplyByElement(TranslatorVisitor& v, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H,
|
||||
Vec Vn, Vec Vd, ExtraBehavior extra_behavior) {
|
||||
if (sz && L == 1) {
|
||||
return v.UnallocatedEncoding();
|
||||
return v.ReservedValue();
|
||||
}
|
||||
|
||||
const size_t idxdsize = H == 1 ? 128 : 64;
|
||||
|
@ -78,7 +78,7 @@ bool TranslatorVisitor::FMULX_elt_2(bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Im
|
|||
|
||||
bool TranslatorVisitor::SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
|
||||
if (size == 0b00 || size == 0b11) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = 8 << size.ZeroExtend();
|
||||
|
@ -96,7 +96,7 @@ bool TranslatorVisitor::SQDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vm
|
|||
|
||||
bool TranslatorVisitor::SQRDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
|
||||
if (size == 0b00 || size == 0b11) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = 8 << size.ZeroExtend();
|
||||
|
@ -114,7 +114,7 @@ bool TranslatorVisitor::SQRDMULH_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> V
|
|||
|
||||
bool TranslatorVisitor::SQDMULL_elt_1(Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
|
||||
if (size == 0b00 || size == 0b11) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = 8 << size.ZeroExtend();
|
||||
|
|
|
@ -55,11 +55,11 @@ bool TranslatorVisitor::UDOT_vec(bool Q, Imm<2> size, Vec Vm, Vec Vn, Vec Vd) {
|
|||
|
||||
bool TranslatorVisitor::FCMLA_vec(bool Q, Imm<2> size, Vec Vm, Imm<2> rot, Vec Vn, Vec Vd) {
|
||||
if (size == 0) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
if (!Q && size == 0b11) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = 8U << size.ZeroExtend();
|
||||
|
@ -128,11 +128,11 @@ bool TranslatorVisitor::FCMLA_vec(bool Q, Imm<2> size, Vec Vm, Imm<2> rot, Vec V
|
|||
|
||||
bool TranslatorVisitor::FCADD_vec(bool Q, Imm<2> size, Vec Vm, Imm<1> rot, Vec Vn, Vec Vd) {
|
||||
if (size == 0) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
if (!Q && size == 0b11) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = 8U << size.ZeroExtend();
|
||||
|
|
|
@ -28,7 +28,7 @@ enum class ExtraBehavior {
|
|||
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) {
|
||||
if (size != 0b01 && size != 0b10) {
|
||||
return v.UnallocatedEncoding();
|
||||
return v.ReservedValue();
|
||||
}
|
||||
|
||||
const auto [index, Vm] = Combine(size, H, L, M, Vmlo);
|
||||
|
@ -54,7 +54,7 @@ bool MultiplyByElement(TranslatorVisitor& v, bool Q, Imm<2> size, Imm<1> L, Imm<
|
|||
bool FPMultiplyByElement(TranslatorVisitor& v, bool Q, bool sz, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd,
|
||||
ExtraBehavior extra_behavior) {
|
||||
if (sz && L == 1) {
|
||||
return v.UnallocatedEncoding();
|
||||
return v.ReservedValue();
|
||||
}
|
||||
if (sz && !Q) {
|
||||
return v.ReservedValue();
|
||||
|
@ -133,7 +133,7 @@ enum class Signedness {
|
|||
bool MultiplyLong(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, Signedness sign) {
|
||||
if (size == 0b00 || size == 0b11) {
|
||||
return v.UnallocatedEncoding();
|
||||
return v.ReservedValue();
|
||||
}
|
||||
|
||||
const size_t idxsize = H == 1 ? 128 : 64;
|
||||
|
@ -217,7 +217,7 @@ bool TranslatorVisitor::SMULL_elt(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4
|
|||
|
||||
bool TranslatorVisitor::SQDMULL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
|
||||
if (size == 0b00 || size == 0b11) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t part = Q ? 1 : 0;
|
||||
|
@ -237,7 +237,7 @@ bool TranslatorVisitor::SQDMULL_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, I
|
|||
|
||||
bool TranslatorVisitor::SQDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
|
||||
if (size == 0b00 || size == 0b11) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t idxsize = H == 1 ? 128 : 64;
|
||||
|
@ -256,7 +256,7 @@ bool TranslatorVisitor::SQDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, I
|
|||
|
||||
bool TranslatorVisitor::SQRDMULH_elt_2(bool Q, Imm<2> size, Imm<1> L, Imm<1> M, Imm<4> Vmlo, Imm<1> H, Vec Vn, Vec Vd) {
|
||||
if (size == 0b00 || size == 0b11) {
|
||||
return UnallocatedEncoding();
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
const size_t idxsize = H == 1 ? 128 : 64;
|
||||
|
|
Loading…
Reference in a new issue