From 88ae7fce52659d95a13be45fcb40f265fd803271 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Fri, 26 Jan 2018 18:36:33 +0000 Subject: [PATCH] A64: Implement LDP (SIMD&FP) and STP (SIMD&FP) --- src/frontend/A64/decoder/a64.inc | 10 +-- src/frontend/A64/translate/impl/impl.h | 7 +- .../impl/load_store_register_pair.cpp | 65 +++++++++++++++++++ 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 861054dc..37a4ab68 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -184,14 +184,8 @@ INST(PRFM_lit, "PRFM (literal)", "11011 // Loads and stores - Load/Store register pair INST(STP_LDP_gen, "STP/LDP", "oo10100pwLiiiiiiiuuuuunnnnnttttt") INST(UnallocatedEncoding, "", "--1010000-----------------------") -INST(UnallocatedEncoding, "", "-110100--0----------------------") -INST(UnallocatedEncoding, "", "1110100-------------------------") -//INST(STP_fpsimd_1, "STP (SIMD&FP)", "oo10110010iiiiiiiuuuuunnnnnttttt") -//INST(STP_fpsimd_2, "STP (SIMD&FP)", "oo10110110iiiiiiiuuuuunnnnnttttt") -//INST(STP_fpsimd_3, "STP (SIMD&FP)", "oo10110100iiiiiiiuuuuunnnnnttttt") -//INST(LDP_fpsimd_1, "LDP (SIMD&FP)", "oo10110011iiiiiiiuuuuunnnnnttttt") -//INST(LDP_fpsimd_2, "LDP (SIMD&FP)", "oo10110111iiiiiiiuuuuunnnnnttttt") -//INST(LDP_fpsimd_3, "LDP (SIMD&FP)", "oo10110101iiiiiiiuuuuunnnnnttttt") +INST(STP_LDP_fpsimd, "STP/LDP (SIMD&FP)", "oo10110pwLiiiiiiiuuuuunnnnnttttt") +INST(UnallocatedEncoding, "", "--1011000-----------------------") // Loads and stores - Load/Store register (unscaled immediate) INST(STURx_LDURx, "STURx/LDURx", "zz111000oo0iiiiiiiii00nnnnnttttt") diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index 38dee0bd..e94d251e 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -243,12 +243,7 @@ struct TranslatorVisitor final { // Loads and stores - Load/Store register pair bool STP_LDP_gen(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); - bool STP_fpsimd_1(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt); - bool STP_fpsimd_2(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt); - bool STP_fpsimd_3(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt); - bool LDP_fpsimd_1(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt); - bool LDP_fpsimd_2(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt); - bool LDP_fpsimd_3(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt); + bool STP_LDP_fpsimd(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt); // Loads and stores - Load/Store register (immediate) bool load_store_register_immediate(bool wback, bool postindex, size_t scale, u64 offset, Imm<2> size, Imm<2> opc, Reg Rn, Reg Rt); diff --git a/src/frontend/A64/translate/impl/load_store_register_pair.cpp b/src/frontend/A64/translate/impl/load_store_register_pair.cpp index 7a8bdca6..a3f044e7 100644 --- a/src/frontend/A64/translate/impl/load_store_register_pair.cpp +++ b/src/frontend/A64/translate/impl/load_store_register_pair.cpp @@ -74,4 +74,69 @@ bool TranslatorVisitor::STP_LDP_gen(Imm<2> opc, bool not_postindex, bool wback, return true; } +bool TranslatorVisitor::STP_LDP_fpsimd(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt) { + const bool postindex = !not_postindex; + + const MemOp memop = L == 1 ? MemOp::LOAD : MemOp::STORE; + if (opc == 0b11) + return UnallocatedEncoding(); + const size_t scale = 2 + opc.ZeroExtend(); + const size_t datasize = 8 << scale; + const u64 offset = imm7.SignExtend() << scale; + + const size_t dbytes = datasize / 8; + + if (memop == MemOp::LOAD && Vt == Vt2) + return UnpredictableInstruction(); + + IR::U64 address; + + if (Rn == Reg::SP) + // TODO: Check SP Alignment + address = SP(64); + else + address = X(64, Rn); + + if (!postindex) + address = ir.Add(address, ir.Imm64(offset)); + + switch (memop) { + case MemOp::STORE: { + IR::UAnyU128 data1 = V(datasize, Vt); + IR::UAnyU128 data2 = V(datasize, Vt2); + if (datasize != 128) { + data1 = ir.VectorGetElement(datasize, data1, 0); + data2 = ir.VectorGetElement(datasize, data2, 0); + } + Mem(address, dbytes, AccType::VEC, data1); + Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, AccType::VEC, data2); + break; + } + case MemOp::LOAD: { + IR::UAnyU128 data1 = Mem(address, dbytes, AccType::VEC); + IR::UAnyU128 data2 = Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, AccType::VEC); + if (datasize != 128) { + data1 = ir.ZeroExtendToQuad(data1); + data2 = ir.ZeroExtendToQuad(data2); + } + V(datasize, Vt, data1); + V(datasize, Vt2, data2); + break; + } + case MemOp::PREFETCH: + UNREACHABLE(); + } + + if (wback) { + if (postindex) + address = ir.Add(address, ir.Imm64(offset)); + if (Rn == Reg::SP) + SP(64, address); + else + X(64, Rn, address); + } + + return true; +} + } // namespace Dynarmic::A64