A64: Implement LDP (SIMD&FP) and STP (SIMD&FP)

This commit is contained in:
MerryMage 2018-01-26 18:36:33 +00:00
parent d497464c9f
commit 88ae7fce52
3 changed files with 68 additions and 14 deletions

View file

@ -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")

View file

@ -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);

View file

@ -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<size_t>();
const size_t datasize = 8 << scale;
const u64 offset = imm7.SignExtend<u64>() << 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