aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMerry <[email protected]>2024-01-28 10:16:10 +0000
committerMerry <[email protected]>2024-01-28 10:19:15 +0000
commitf8e38809e97d54ec9fa9bcf4414da172a31834ae (patch)
tree7793fd00a41ecb207c372611ad82987a2a5877e0
parent8398d7ef7e3de08469aa6837c0f67c573f1b96f5 (diff)
downloaddynarmic-f8e38809e97d54ec9fa9bcf4414da172a31834ae.tar.gz
dynarmic-f8e38809e97d54ec9fa9bcf4414da172a31834ae.zip
A32: Implement VRINT{N,X,A,Z,M,P} (ASIMD)
-rw-r--r--src/dynarmic/frontend/A32/decoder/asimd.inc12
-rw-r--r--src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h6
-rw-r--r--src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp40
3 files changed, 52 insertions, 6 deletions
diff --git a/src/dynarmic/frontend/A32/decoder/asimd.inc b/src/dynarmic/frontend/A32/decoder/asimd.inc
index a9b5486d..1170e2e7 100644
--- a/src/dynarmic/frontend/A32/decoder/asimd.inc
+++ b/src/dynarmic/frontend/A32/decoder/asimd.inc
@@ -125,12 +125,12 @@ INST(asimd_VMOVN, "VMOVN", "111100111D11zz10dddd001
INST(asimd_VQMOVUN, "VQMOVUN", "111100111D11zz10dddd001001M0mmmm") // ASIMD
INST(asimd_VQMOVN, "VQMOVN", "111100111D11zz10dddd00101oM0mmmm") // ASIMD
INST(asimd_VSHLL_max, "VSHLL_max", "111100111D11zz10dddd001100M0mmmm") // ASIMD
-INST(arm_UDF, "UNALLOCATED (VRINTN)", "111100111-11--10----01000--0----")
-INST(arm_UDF, "UNALLOCATED (VRINTX)", "111100111-11--10----01001--0----")
-INST(arm_UDF, "UNALLOCATED (VRINTA)", "111100111-11--10----01010--0----")
-INST(arm_UDF, "UNALLOCATED (VRINTZ)", "111100111-11--10----01011--0----")
-INST(arm_UDF, "UNALLOCATED (VRINTM)", "111100111-11--10----01101--0----")
-INST(arm_UDF, "UNALLOCATED (VRINTP)", "111100111-11--10----01111--0----")
+INST(asimd_VRINTN, "VRINTN", "111100111D11zz10dddd01000QM0mmmm") // v8
+INST(asimd_VRINTX, "VRINTX", "111100111D11zz10dddd01001QM0mmmm") // v8
+INST(asimd_VRINTA, "VRINTA", "111100111D11zz10dddd01010QM0mmmm") // v8
+INST(asimd_VRINTZ, "VRINTZ", "111100111D11zz10dddd01011QM0mmmm") // v8
+INST(asimd_VRINTM, "VRINTM", "111100111D11zz10dddd01101QM0mmmm") // v8
+INST(asimd_VRINTP, "VRINTP", "111100111D11zz10dddd01111QM0mmmm") // v8
INST(asimd_VCVT_half, "VCVT (half-precision)", "111100111D11zz10dddd011o00M0mmmm") // ASIMD
INST(arm_UDF, "UNALLOCATED", "111100111-11--10----011-01-0----") // ASIMD
INST(arm_UDF, "UNALLOCATED (VCVTA)", "111100111-11--11----0000---0----")
diff --git a/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h b/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h
index 2516235f..857df24d 100644
--- a/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h
+++ b/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h
@@ -950,6 +950,12 @@ struct TranslatorVisitor final {
bool asimd_VQMOVUN(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
bool asimd_VQMOVN(bool D, size_t sz, size_t Vd, bool op, bool M, size_t Vm);
bool asimd_VSHLL_max(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
+ bool asimd_VRINTN(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
+ bool asimd_VRINTX(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
+ bool asimd_VRINTA(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
+ bool asimd_VRINTZ(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
+ bool asimd_VRINTM(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
+ bool asimd_VRINTP(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
bool asimd_VCVT_half(bool D, size_t sz, size_t Vd, bool op, bool M, size_t Vm);
bool asimd_VRECPE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
bool asimd_VRSQRTE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
diff --git a/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp b/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp
index 4c859bcd..4a93576b 100644
--- a/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp
+++ b/src/dynarmic/frontend/A32/translate/impl/asimd_two_regs_misc.cpp
@@ -102,6 +102,27 @@ bool PairedAddOperation(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool
return true;
}
+bool RoundFloatToInteger(TranslatorVisitor& v, bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm, bool exact, FP::RoundingMode rounding_mode) {
+ if (Q && (mcl::bit::get_bit<0>(Vd) || mcl::bit::get_bit<0>(Vm))) {
+ return v.UndefinedInstruction();
+ }
+
+ if (sz != 0b10) {
+ return v.UndefinedInstruction(); // TODO: FP16
+ }
+
+ const size_t esize = 8 << sz;
+
+ const auto d = ToVector(Q, Vd, D);
+ const auto m = ToVector(Q, Vm, M);
+
+ const auto reg_m = v.ir.GetVector(m);
+ const auto result = v.ir.FPVectorRoundInt(esize, reg_m, rounding_mode, exact, false);
+
+ v.ir.SetVector(d, result);
+ return true;
+}
+
} // Anonymous namespace
bool TranslatorVisitor::asimd_VREV(bool D, size_t sz, size_t Vd, size_t op, bool Q, bool M, size_t Vm) {
@@ -590,6 +611,25 @@ bool TranslatorVisitor::asimd_VSHLL_max(bool D, size_t sz, size_t Vd, bool M, si
return true;
}
+bool TranslatorVisitor::asimd_VRINTN(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm) {
+ return RoundFloatToInteger(*this, D, sz, Vd, Q, M, Vm, false, FP::RoundingMode::ToNearest_TieEven);
+}
+bool TranslatorVisitor::asimd_VRINTX(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm) {
+ return RoundFloatToInteger(*this, D, sz, Vd, Q, M, Vm, true, FP::RoundingMode::ToNearest_TieEven);
+}
+bool TranslatorVisitor::asimd_VRINTA(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm) {
+ return RoundFloatToInteger(*this, D, sz, Vd, Q, M, Vm, false, FP::RoundingMode::ToNearest_TieAwayFromZero);
+}
+bool TranslatorVisitor::asimd_VRINTZ(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm) {
+ return RoundFloatToInteger(*this, D, sz, Vd, Q, M, Vm, false, FP::RoundingMode::TowardsZero);
+}
+bool TranslatorVisitor::asimd_VRINTM(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm) {
+ return RoundFloatToInteger(*this, D, sz, Vd, Q, M, Vm, false, FP::RoundingMode::TowardsMinusInfinity);
+}
+bool TranslatorVisitor::asimd_VRINTP(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm) {
+ return RoundFloatToInteger(*this, D, sz, Vd, Q, M, Vm, false, FP::RoundingMode::TowardsPlusInfinity);
+}
+
bool TranslatorVisitor::asimd_VCVT_half(bool D, size_t sz, size_t Vd, bool half_to_single, bool M, size_t Vm) {
if (sz != 0b01) {
return UndefinedInstruction();