A64: Implement STR{,B,H} (register), LDR{,B,H,SB,SH,SW} (register), PFRM (register)
This commit is contained in:
parent
d040920727
commit
56bc7825ef
4 changed files with 102 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue