A64: Implement LDP, STP
This commit is contained in:
parent
25411da838
commit
243f06c613
5 changed files with 86 additions and 19 deletions
|
@ -67,6 +67,7 @@ add_library(dynarmic
|
||||||
frontend/A64/translate/impl/impl.h
|
frontend/A64/translate/impl/impl.h
|
||||||
frontend/A64/translate/impl/load_store_load_literal.cpp
|
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_immediate.cpp
|
||||||
|
frontend/A64/translate/impl/load_store_register_pair.cpp
|
||||||
frontend/A64/translate/translate.cpp
|
frontend/A64/translate/translate.cpp
|
||||||
frontend/A64/translate/translate.h
|
frontend/A64/translate/translate.h
|
||||||
frontend/A64/types.cpp
|
frontend/A64/types.cpp
|
||||||
|
|
|
@ -94,7 +94,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_alloc.EndOfAllocScope();
|
ctx.reg_alloc.EndOfAllocScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_alloc.AssertNoMoreUses();
|
reg_alloc.AssertNoMoreUses();
|
||||||
|
|
|
@ -213,21 +213,16 @@ std::vector<Matcher<V>> GetDecodeTable() {
|
||||||
//INST(&V::LDNP_fpsimd, "LDNP (SIMD&FP)", "oo10110001iiiiiiiuuuuunnnnnttttt"),
|
//INST(&V::LDNP_fpsimd, "LDNP (SIMD&FP)", "oo10110001iiiiiiiuuuuunnnnnttttt"),
|
||||||
|
|
||||||
// Loads and stores - Load/Store register pair
|
// Loads and stores - Load/Store register pair
|
||||||
//INST(&V::STP_gen_1, "STP", "-010100010iiiiiiiuuuuunnnnnttttt"),
|
INST(&V::STP_LDP_gen, "STP/LDP", "oo10100pwLiiiiiiiuuuuunnnnnttttt"),
|
||||||
//INST(&V::STP_gen_2, "STP", "-010100110iiiiiiiuuuuunnnnnttttt"),
|
INST(&V::UnallocatedEncoding, "", "--1010000-----------------------"),
|
||||||
//INST(&V::STP_gen_3, "STP", "-010100100iiiiiiiuuuuunnnnnttttt"),
|
INST(&V::UnallocatedEncoding, "", "-110100--0----------------------"),
|
||||||
//INST(&V::LDP_gen_1, "LDP", "-010100011iiiiiiiuuuuunnnnnttttt"),
|
INST(&V::UnallocatedEncoding, "", "1110100-------------------------"),
|
||||||
//INST(&V::LDP_gen_2, "LDP", "-010100111iiiiiiiuuuuunnnnnttttt"),
|
|
||||||
//INST(&V::LDP_gen_3, "LDP", "-010100101iiiiiiiuuuuunnnnnttttt"),
|
|
||||||
//INST(&V::STP_fpsimd_1, "STP (SIMD&FP)", "oo10110010iiiiiiiuuuuunnnnnttttt"),
|
//INST(&V::STP_fpsimd_1, "STP (SIMD&FP)", "oo10110010iiiiiiiuuuuunnnnnttttt"),
|
||||||
//INST(&V::STP_fpsimd_2, "STP (SIMD&FP)", "oo10110110iiiiiiiuuuuunnnnnttttt"),
|
//INST(&V::STP_fpsimd_2, "STP (SIMD&FP)", "oo10110110iiiiiiiuuuuunnnnnttttt"),
|
||||||
//INST(&V::STP_fpsimd_3, "STP (SIMD&FP)", "oo10110100iiiiiiiuuuuunnnnnttttt"),
|
//INST(&V::STP_fpsimd_3, "STP (SIMD&FP)", "oo10110100iiiiiiiuuuuunnnnnttttt"),
|
||||||
//INST(&V::LDP_fpsimd_1, "LDP (SIMD&FP)", "oo10110011iiiiiiiuuuuunnnnnttttt"),
|
//INST(&V::LDP_fpsimd_1, "LDP (SIMD&FP)", "oo10110011iiiiiiiuuuuunnnnnttttt"),
|
||||||
//INST(&V::LDP_fpsimd_2, "LDP (SIMD&FP)", "oo10110111iiiiiiiuuuuunnnnnttttt"),
|
//INST(&V::LDP_fpsimd_2, "LDP (SIMD&FP)", "oo10110111iiiiiiiuuuuunnnnnttttt"),
|
||||||
//INST(&V::LDP_fpsimd_3, "LDP (SIMD&FP)", "oo10110101iiiiiiiuuuuunnnnnttttt"),
|
//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)
|
// Loads and stores - Load/Store register (unscaled immediate)
|
||||||
INST(&V::STURx_LDURx, "STURx/LDURx", "zz111000oo0iiiiiiiii00nnnnnttttt"),
|
INST(&V::STURx_LDURx, "STURx/LDURx", "zz111000oo0iiiiiiiii00nnnnnttttt"),
|
||||||
|
|
|
@ -240,21 +240,13 @@ struct TranslatorVisitor final {
|
||||||
bool LDNP_fpsimd(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt);
|
bool LDNP_fpsimd(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt);
|
||||||
|
|
||||||
// Loads and stores - Load/Store register pair
|
// Loads and stores - Load/Store register pair
|
||||||
bool STP_gen_1(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_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_fpsimd_1(Imm<2> opc, Imm<7> imm7, Vec Vt2, Reg Rn, Vec Vt);
|
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_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 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_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_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 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)
|
// 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);
|
bool load_store_register_immediate(bool wback, bool postindex, size_t scale, u64 offset, Imm<2> size, Imm<2> opc, Reg Rn, Reg Rt);
|
||||||
|
|
79
src/frontend/A64/translate/impl/load_store_register_pair.cpp
Normal file
79
src/frontend/A64/translate/impl/load_store_register_pair.cpp
Normal file
|
@ -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<u64>() << 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
|
Loading…
Reference in a new issue