A64: Implement STR{,B,H} (register), LDR{,B,H,SB,SH,SW} (register), PFRM (register)

This commit is contained in:
MerryMage 2018-02-04 12:18:57 +00:00
parent d040920727
commit 56bc7825ef
4 changed files with 102 additions and 20 deletions

View file

@ -83,6 +83,7 @@ add_library(dynarmic
frontend/A64/translate/impl/load_store_multiple_structures.cpp
frontend/A64/translate/impl/load_store_register_immediate.cpp
frontend/A64/translate/impl/load_store_register_pair.cpp
frontend/A64/translate/impl/load_store_register_register_offset.cpp
frontend/A64/translate/impl/load_store_register_unprivileged.cpp
frontend/A64/translate/impl/move_wide.cpp
frontend/A64/translate/impl/simd_aes.cpp

View file

@ -239,18 +239,10 @@ INST(LDTRSW, "LDTRSW", "10111
//INST(LDAPR, "LDAPR", "1-11100010111111110000nnnnnttttt")
// Loads and stores - Load/Store register (register offset)
//INST(STRB_reg, "STRB (register)", "00111000001mmmmmxxxS10nnnnnttttt")
//INST(LDRB_reg, "LDRB (register)", "00111000011mmmmmxxxS10nnnnnttttt")
//INST(LDRSB_reg, "LDRSB (register)", "001110001-1mmmmmxxxS10nnnnnttttt")
INST(STRx_reg, "STRx (register)", "zz111000o01mmmmmxxxS10nnnnnttttt")
INST(LDRx_reg, "LDRx (register)", "zz111000o11mmmmmxxxS10nnnnnttttt")
//INST(STR_reg_fpsimd, "STR (register, SIMD&FP)", "zz111100-01mmmmmxxxS10nnnnnttttt")
//INST(LDR_reg_fpsimd, "LDR (register, SIMD&FP)", "zz111100-11mmmmmxxxS10nnnnnttttt")
//INST(STRH_reg, "STRH (register)", "01111000001mmmmmxxxS10nnnnnttttt")
//INST(LDRH_reg, "LDRH (register)", "01111000011mmmmmxxxS10nnnnnttttt")
//INST(LDRSH_reg, "LDRSH (register)", "011110001-1mmmmmxxxS10nnnnnttttt")
//INST(STR_reg_gen, "STR (register)", "1-111000001mmmmmxxxS10nnnnnttttt")
//INST(LDR_reg_gen, "LDR (register)", "1-111000011mmmmmxxxS10nnnnnttttt")
//INST(LDRSW_reg, "LDRSW (register)", "10111000101mmmmmxxxS10nnnnnttttt")
//INST(PRFM_reg, "PRFM (register)", "11111000101mmmmmxxxS10nnnnnttttt")
// Loads and stores - Load/Store register (pointer authentication)
//INST(LDRA, "LDRAA, LDRAB", "11111000MS1iiiiiiiiiW1nnnnnttttt")

View file

@ -293,18 +293,10 @@ struct TranslatorVisitor final {
bool LDAPR(Reg Rn, Reg Rt);
// Loads and stores - Load/Store register (register offset)
bool STRB_reg(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool LDRB_reg(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool LDRSB_reg(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool STRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool LDRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool STR_reg_fpsimd(Imm<2> size, Reg Rm, Imm<3> option, bool S, Reg Rn, Vec Vt);
bool LDR_reg_fpsimd(Imm<2> size, Reg Rm, Imm<3> option, bool S, Reg Rn, Vec Vt);
bool STRH_reg(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool LDRH_reg(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool LDRSH_reg(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool STR_reg_gen(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool LDR_reg_gen(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool LDRSW_reg(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
bool PRFM_reg(Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt);
// Loads and stores - Load/Store register (pointer authentication)
bool LDRA(bool M, bool S, Imm<9> imm9, bool W, Reg Rn, Reg Rt);

View file

@ -0,0 +1,97 @@
/* 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::A64 {
static bool SharedDecodeAndOperation(TranslatorVisitor& tv, IREmitter& ir, size_t scale, u8 shift, Imm<2> size, Imm<1> opc_1, Imm<1> opc_0, Reg Rm, Imm<3> option, Reg Rn, Reg Rt) {
// Shared Decode
const AccType acctype = AccType::NORMAL;
MemOp memop;
size_t regsize = 64;
bool signed_ = false;
if (opc_1 == 0) {
memop = opc_0 == 1 ? MemOp::LOAD : MemOp::STORE;
regsize = size == 0b11 ? 64 : 32;
signed_ = false;
} else if (size == 0b11) {
memop = MemOp::PREFETCH;
if (opc_0 == 1) {
return tv.UnallocatedEncoding();
}
} else {
memop = MemOp::LOAD;
if (size == 0b10 && opc_0 == 1) {
return tv.UnallocatedEncoding();
}
regsize = opc_0 == 1 ? 32 : 64;
signed_ = true;
}
const size_t datasize = 8 << scale;
// Operation
const IR::U64 offset = tv.ExtendReg(64, Rm, option, shift);
IR::U64 address;
if (Rn == Reg::SP) {
// TODO: Check SP alignment
address = tv.SP(64);
} else {
address = tv.X(64, Rn);
}
address = ir.Add(address, offset);
switch (memop) {
case MemOp::STORE: {
IR::UAny data = tv.X(datasize, Rt);
tv.Mem(address, datasize / 8, acctype, data);
break;
}
case MemOp::LOAD: {
IR::UAny data = tv.Mem(address, datasize / 8, acctype);
if (signed_) {
tv.X(regsize, Rt, tv.SignExtend(data, regsize));
} else {
tv.X(regsize, Rt, tv.ZeroExtend(data, regsize));
}
break;
}
case MemOp::PREFETCH:
// TODO: Prefetch
break;
default:
UNREACHABLE();
}
return true;
}
bool TranslatorVisitor::STRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt) {
const Imm<1> opc_0{0};
const size_t scale = size.ZeroExtend<size_t>();
const u8 shift = S ? static_cast<u8>(scale) : 0;
if (!option.Bit<1>()) {
return UnallocatedEncoding();
}
return SharedDecodeAndOperation(*this, ir, scale, shift, size, opc_1, opc_0, Rm, option, Rn, Rt);
}
bool TranslatorVisitor::LDRx_reg(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3> option, bool S, Reg Rn, Reg Rt) {
const Imm<1> opc_0{1};
const size_t scale = size.ZeroExtend<size_t>();
const u8 shift = S ? static_cast<u8>(scale) : 0;
if (!option.Bit<1>()) {
return UnallocatedEncoding();
}
return SharedDecodeAndOperation(*this, ir, scale, shift, size, opc_1, opc_0, Rm, option, Rn, Rt);
}
} // namespace Dynarmic::A64