A64: Implement LDP (SIMD&FP) and STP (SIMD&FP)
This commit is contained in:
parent
d497464c9f
commit
88ae7fce52
3 changed files with 68 additions and 14 deletions
|
@ -184,14 +184,8 @@ INST(PRFM_lit, "PRFM (literal)", "11011
|
||||||
// Loads and stores - Load/Store register pair
|
// Loads and stores - Load/Store register pair
|
||||||
INST(STP_LDP_gen, "STP/LDP", "oo10100pwLiiiiiiiuuuuunnnnnttttt")
|
INST(STP_LDP_gen, "STP/LDP", "oo10100pwLiiiiiiiuuuuunnnnnttttt")
|
||||||
INST(UnallocatedEncoding, "", "--1010000-----------------------")
|
INST(UnallocatedEncoding, "", "--1010000-----------------------")
|
||||||
INST(UnallocatedEncoding, "", "-110100--0----------------------")
|
INST(STP_LDP_fpsimd, "STP/LDP (SIMD&FP)", "oo10110pwLiiiiiiiuuuuunnnnnttttt")
|
||||||
INST(UnallocatedEncoding, "", "1110100-------------------------")
|
INST(UnallocatedEncoding, "", "--1011000-----------------------")
|
||||||
//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")
|
|
||||||
|
|
||||||
// Loads and stores - Load/Store register (unscaled immediate)
|
// Loads and stores - Load/Store register (unscaled immediate)
|
||||||
INST(STURx_LDURx, "STURx/LDURx", "zz111000oo0iiiiiiiii00nnnnnttttt")
|
INST(STURx_LDURx, "STURx/LDURx", "zz111000oo0iiiiiiiii00nnnnnttttt")
|
||||||
|
|
|
@ -243,12 +243,7 @@ struct TranslatorVisitor final {
|
||||||
|
|
||||||
// Loads and stores - Load/Store register pair
|
// 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_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_LDP_fpsimd(Imm<2> opc, bool not_postindex, bool wback, Imm<1> L, 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);
|
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
|
@ -74,4 +74,69 @@ bool TranslatorVisitor::STP_LDP_gen(Imm<2> opc, bool not_postindex, bool wback,
|
||||||
return true;
|
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
|
} // namespace Dynarmic::A64
|
||||||
|
|
Loading…
Reference in a new issue