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_multiple_structures.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/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/load_store_register_unprivileged.cpp
|
||||||
frontend/A64/translate/impl/move_wide.cpp
|
frontend/A64/translate/impl/move_wide.cpp
|
||||||
frontend/A64/translate/impl/simd_aes.cpp
|
frontend/A64/translate/impl/simd_aes.cpp
|
||||||
|
|
|
@ -239,18 +239,10 @@ INST(LDTRSW, "LDTRSW", "10111
|
||||||
//INST(LDAPR, "LDAPR", "1-11100010111111110000nnnnnttttt")
|
//INST(LDAPR, "LDAPR", "1-11100010111111110000nnnnnttttt")
|
||||||
|
|
||||||
// Loads and stores - Load/Store register (register offset)
|
// Loads and stores - Load/Store register (register offset)
|
||||||
//INST(STRB_reg, "STRB (register)", "00111000001mmmmmxxxS10nnnnnttttt")
|
INST(STRx_reg, "STRx (register)", "zz111000o01mmmmmxxxS10nnnnnttttt")
|
||||||
//INST(LDRB_reg, "LDRB (register)", "00111000011mmmmmxxxS10nnnnnttttt")
|
INST(LDRx_reg, "LDRx (register)", "zz111000o11mmmmmxxxS10nnnnnttttt")
|
||||||
//INST(LDRSB_reg, "LDRSB (register)", "001110001-1mmmmmxxxS10nnnnnttttt")
|
|
||||||
//INST(STR_reg_fpsimd, "STR (register, SIMD&FP)", "zz111100-01mmmmmxxxS10nnnnnttttt")
|
//INST(STR_reg_fpsimd, "STR (register, SIMD&FP)", "zz111100-01mmmmmxxxS10nnnnnttttt")
|
||||||
//INST(LDR_reg_fpsimd, "LDR (register, SIMD&FP)", "zz111100-11mmmmmxxxS10nnnnnttttt")
|
//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)
|
// Loads and stores - Load/Store register (pointer authentication)
|
||||||
//INST(LDRA, "LDRAA, LDRAB", "11111000MS1iiiiiiiiiW1nnnnnttttt")
|
//INST(LDRA, "LDRAA, LDRAB", "11111000MS1iiiiiiiiiW1nnnnnttttt")
|
||||||
|
|
|
@ -293,18 +293,10 @@ struct TranslatorVisitor final {
|
||||||
bool LDAPR(Reg Rn, Reg Rt);
|
bool LDAPR(Reg Rn, Reg Rt);
|
||||||
|
|
||||||
// Loads and stores - Load/Store register (register offset)
|
// Loads and stores - Load/Store register (register offset)
|
||||||
bool STRB_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 LDRB_reg(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 LDRSB_reg(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 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 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)
|
// Loads and stores - Load/Store register (pointer authentication)
|
||||||
bool LDRA(bool M, bool S, Imm<9> imm9, bool W, Reg Rn, Reg Rt);
|
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