A64: Implement LDP, STP

This commit is contained in:
MerryMage 2018-01-10 02:05:08 +00:00
parent 25411da838
commit 243f06c613
5 changed files with 86 additions and 19 deletions

View file

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

View file

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

View file

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

View file

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

View 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