diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bdb69936..5c28bf3a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,6 +67,7 @@ add_library(dynarmic frontend/A64/translate/impl/impl.h frontend/A64/translate/impl/load_store_load_literal.cpp frontend/A64/translate/impl/load_store_register_immediate.cpp + frontend/A64/translate/impl/load_store_register_pair.cpp frontend/A64/translate/translate.cpp frontend/A64/translate/translate.h frontend/A64/types.cpp diff --git a/src/backend_x64/a64_emit_x64.cpp b/src/backend_x64/a64_emit_x64.cpp index 31fcab69..766f19ad 100644 --- a/src/backend_x64/a64_emit_x64.cpp +++ b/src/backend_x64/a64_emit_x64.cpp @@ -94,7 +94,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) { break; } - reg_alloc.EndOfAllocScope(); + ctx.reg_alloc.EndOfAllocScope(); } reg_alloc.AssertNoMoreUses(); diff --git a/src/frontend/A64/decoder/a64.h b/src/frontend/A64/decoder/a64.h index ab18a7b2..3781a1b6 100644 --- a/src/frontend/A64/decoder/a64.h +++ b/src/frontend/A64/decoder/a64.h @@ -213,21 +213,16 @@ std::vector> GetDecodeTable() { //INST(&V::LDNP_fpsimd, "LDNP (SIMD&FP)", "oo10110001iiiiiiiuuuuunnnnnttttt"), // Loads and stores - Load/Store register pair - //INST(&V::STP_gen_1, "STP", "-010100010iiiiiiiuuuuunnnnnttttt"), - //INST(&V::STP_gen_2, "STP", "-010100110iiiiiiiuuuuunnnnnttttt"), - //INST(&V::STP_gen_3, "STP", "-010100100iiiiiiiuuuuunnnnnttttt"), - //INST(&V::LDP_gen_1, "LDP", "-010100011iiiiiiiuuuuunnnnnttttt"), - //INST(&V::LDP_gen_2, "LDP", "-010100111iiiiiiiuuuuunnnnnttttt"), - //INST(&V::LDP_gen_3, "LDP", "-010100101iiiiiiiuuuuunnnnnttttt"), + INST(&V::STP_LDP_gen, "STP/LDP", "oo10100pwLiiiiiiiuuuuunnnnnttttt"), + INST(&V::UnallocatedEncoding, "", "--1010000-----------------------"), + INST(&V::UnallocatedEncoding, "", "-110100--0----------------------"), + INST(&V::UnallocatedEncoding, "", "1110100-------------------------"), //INST(&V::STP_fpsimd_1, "STP (SIMD&FP)", "oo10110010iiiiiiiuuuuunnnnnttttt"), //INST(&V::STP_fpsimd_2, "STP (SIMD&FP)", "oo10110110iiiiiiiuuuuunnnnnttttt"), //INST(&V::STP_fpsimd_3, "STP (SIMD&FP)", "oo10110100iiiiiiiuuuuunnnnnttttt"), //INST(&V::LDP_fpsimd_1, "LDP (SIMD&FP)", "oo10110011iiiiiiiuuuuunnnnnttttt"), //INST(&V::LDP_fpsimd_2, "LDP (SIMD&FP)", "oo10110111iiiiiiiuuuuunnnnnttttt"), //INST(&V::LDP_fpsimd_3, "LDP (SIMD&FP)", "oo10110101iiiiiiiuuuuunnnnnttttt"), - //INST(&V::LDPSW_1, "LDPSW", "0110100011iiiiiiiuuuuunnnnnttttt"), - //INST(&V::LDPSW_2, "LDPSW", "0110100111iiiiiiiuuuuunnnnnttttt"), - //INST(&V::LDPSW_3, "LDPSW", "0110100101iiiiiiiuuuuunnnnnttttt"), // Loads and stores - Load/Store register (unscaled immediate) INST(&V::STURx_LDURx, "STURx/LDURx", "zz111000oo0iiiiiiiii00nnnnnttttt"), diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index 9da6b990..301c29e9 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -240,21 +240,13 @@ struct TranslatorVisitor final { bool LDNP_fpsimd(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt); // Loads and stores - Load/Store register pair - bool STP_gen_1(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); - bool STP_gen_2(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); - bool STP_gen_3(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); - bool LDP_gen_1(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); - bool LDP_gen_2(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); - bool LDP_gen_3(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); + 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 LDPSW_1(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); - bool LDPSW_2(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); - bool LDPSW_3(Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt); // 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 new file mode 100644 index 00000000..ba990899 --- /dev/null +++ b/src/frontend/A64/translate/impl/load_store_register_pair.cpp @@ -0,0 +1,79 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2018 MerryMage + * This software may be used and distributed according to the terms of the GNU + * General Public License version 2 or any later version. + */ + +#include "frontend/A64/translate/impl/impl.h" + +namespace Dynarmic { +namespace A64 { + +bool TranslatorVisitor::STP_LDP_gen(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, Imm<7> imm7, Reg Rt2, Reg Rn, Reg Rt) { + const bool postindex = !not_postindex; + + const MemOp memop = L == 1 ? MemOp::LOAD : MemOp::STORE; + if ((L == 0 && opc.Bit<0>() == 1) || opc == 0b11) + return UnallocatedEncoding(); + const bool signed_ = opc.Bit<0>() != 0; + const size_t scale = 2 + opc.Bit<1>(); + const size_t datasize = 8 << scale; + const u64 offset = imm7.SignExtend() << scale; + + if (memop == MemOp::LOAD && wback && (Rt == Rn || Rt2 == Rn) && Rn != Reg::R31) + return UnpredictableInstruction(); + if (memop == MemOp::STORE && wback && (Rt == Rn || Rt2 == Rn) && Rn != Reg::R31) + return UnpredictableInstruction(); + if (memop == MemOp::LOAD && Rt == Rt2) + return UnpredictableInstruction(); + + IR::U64 address; + IR::U32U64 data1; + IR::U32U64 data2; + const size_t dbytes = datasize / 8; + + 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::U32U64 data1 = X(datasize, Rt); + IR::U32U64 data2 = X(datasize, Rt2); + Mem(address, dbytes, AccType::NORMAL, data1); + Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, AccType::NORMAL, data2); + break; + } + case MemOp::LOAD: { + IR::U32U64 data1 = Mem(address, dbytes, AccType::NORMAL); + IR::U32U64 data2 = Mem(ir.Add(address, ir.Imm64(dbytes)), dbytes, AccType::NORMAL); + if (signed_) { + X(64, Rt, SignExtend(data1, 64)); + X(64, Rt2, SignExtend(data2, 64)); + } else { + X(datasize, Rt, data1); + X(datasize, Rt2, data2); + } + break; + } + } + + 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 A64 +} // namespace Dynarmic