A64: Implement Load/Store register (unprivileged)
This commit is contained in:
parent
01a26fa644
commit
41e6e659c5
4 changed files with 161 additions and 13 deletions
|
@ -74,6 +74,7 @@ add_library(dynarmic
|
||||||
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/impl/load_store_register_pair.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_copy.cpp
|
frontend/A64/translate/impl/simd_copy.cpp
|
||||||
frontend/A64/translate/impl/simd_three_same.cpp
|
frontend/A64/translate/impl/simd_three_same.cpp
|
||||||
|
|
|
@ -214,15 +214,15 @@ INST(LDR_imm_fpsimd_1, "LDR (immediate, SIMD&FP)", "zz111
|
||||||
INST(LDR_imm_fpsimd_2, "LDR (immediate, SIMD&FP)", "zz111101o1iiiiiiiiiiiinnnnnttttt")
|
INST(LDR_imm_fpsimd_2, "LDR (immediate, SIMD&FP)", "zz111101o1iiiiiiiiiiiinnnnnttttt")
|
||||||
|
|
||||||
// Loads and stores - Load/Store register (unprivileged)
|
// Loads and stores - Load/Store register (unprivileged)
|
||||||
//INST(STTRB, "STTRB", "00111000000iiiiiiiii10nnnnnttttt")
|
INST(STTRB, "STTRB", "00111000000iiiiiiiii10nnnnnttttt")
|
||||||
//INST(LDTRB, "LDTRB", "00111000010iiiiiiiii10nnnnnttttt")
|
INST(LDTRB, "LDTRB", "00111000010iiiiiiiii10nnnnnttttt")
|
||||||
//INST(LDTRSB, "LDTRSB", "001110001-0iiiiiiiii10nnnnnttttt")
|
INST(LDTRSB, "LDTRSB", "00111000oo0iiiiiiiii10nnnnnttttt")
|
||||||
//INST(STTRH, "STTRH", "01111000000iiiiiiiii10nnnnnttttt")
|
INST(STTRH, "STTRH", "01111000000iiiiiiiii10nnnnnttttt")
|
||||||
//INST(LDTRH, "LDTRH", "01111000010iiiiiiiii10nnnnnttttt")
|
INST(LDTRH, "LDTRH", "01111000010iiiiiiiii10nnnnnttttt")
|
||||||
//INST(LDTRSH, "LDTRSH", "011110001-0iiiiiiiii10nnnnnttttt")
|
INST(LDTRSH, "LDTRSH", "011110001-0iiiiiiiii10nnnnnttttt")
|
||||||
//INST(STTR, "STTR", "1-111000000iiiiiiiii10nnnnnttttt")
|
INST(STTR, "STTR", "1z111000000iiiiiiiii10nnnnnttttt")
|
||||||
//INST(LDTR, "LDTR", "1-111000010iiiiiiiii10nnnnnttttt")
|
INST(LDTR, "LDTR", "1z111000010iiiiiiiii10nnnnnttttt")
|
||||||
//INST(LDTRSW, "LDTRSW", "10111000100iiiiiiiii10nnnnnttttt")
|
INST(LDTRSW, "LDTRSW", "10111000100iiiiiiiii10nnnnnttttt")
|
||||||
|
|
||||||
// Loads and stores - Atomic memory options
|
// Loads and stores - Atomic memory options
|
||||||
//INST(LDADDB, "LDADDB, LDADDAB, LDADDALB, LDADDLB", "00111000AR1sssss000000nnnnnttttt")
|
//INST(LDADDB, "LDADDB, LDADDAB, LDADDALB, LDADDLB", "00111000AR1sssss000000nnnnnttttt")
|
||||||
|
|
|
@ -267,12 +267,12 @@ struct TranslatorVisitor final {
|
||||||
// Loads and stores - Load/Store register (unprivileged)
|
// Loads and stores - Load/Store register (unprivileged)
|
||||||
bool STTRB(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool STTRB(Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
bool LDTRB(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool LDTRB(Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
bool LDTRSB(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool LDTRSB(Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
bool STTRH(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool STTRH(Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
bool LDTRH(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool LDTRH(Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
bool LDTRSH(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool LDTRSH(Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
bool STTR(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool STTR(Imm<2> size, Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
bool LDTR(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool LDTR(Imm<2> size, Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
bool LDTRSW(Imm<9> imm9, Reg Rn, Reg Rt);
|
bool LDTRSW(Imm<9> imm9, Reg Rn, Reg Rt);
|
||||||
|
|
||||||
// Loads and stores - Atomic memory options
|
// Loads and stores - Atomic memory options
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/* 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 {
|
||||||
|
|
||||||
|
static bool store_register(TranslatorVisitor& tv, IREmitter& ir, const size_t datasize, Imm<9> imm9,
|
||||||
|
Reg Rn, Reg Rt) {
|
||||||
|
const u64 offset = imm9.ZeroExtend<u64>();
|
||||||
|
AccType acctype = AccType::UNPRIV;
|
||||||
|
IR::U64 address;
|
||||||
|
|
||||||
|
if (Rn == Reg::SP) {
|
||||||
|
// TODO: Check Stack Alignment
|
||||||
|
address = tv.SP(datasize);
|
||||||
|
} else {
|
||||||
|
address = tv.X(datasize, Rn);
|
||||||
|
}
|
||||||
|
address = ir.Add(address, ir.Imm64(offset));
|
||||||
|
IR::UAny data = tv.X(datasize, Rt);
|
||||||
|
tv.Mem(address, datasize / 8, acctype, data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool load_register(TranslatorVisitor& tv, IREmitter& ir, const size_t datasize, Imm<9> imm9,
|
||||||
|
Reg Rn, Reg Rt) {
|
||||||
|
const u64 offset = imm9.ZeroExtend<u64>();
|
||||||
|
AccType acctype = AccType::UNPRIV;
|
||||||
|
IR::U64 address;
|
||||||
|
|
||||||
|
if (Rn == Reg::SP) {
|
||||||
|
// TODO: Check Stack Alignment
|
||||||
|
address = tv.SP(datasize);
|
||||||
|
} else {
|
||||||
|
address = tv.X(datasize, Rn);
|
||||||
|
}
|
||||||
|
address = ir.Add(address, ir.Imm64(offset));
|
||||||
|
IR::UAny data = tv.Mem(address, datasize / 8, acctype);
|
||||||
|
tv.X(datasize, Rt, tv.ZeroExtend(data, 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool load_register_signed(TranslatorVisitor& tv, IREmitter& ir, const size_t datasize,
|
||||||
|
Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
const u64 offset = imm9.ZeroExtend<u64>();
|
||||||
|
AccType acctype = AccType::UNPRIV;
|
||||||
|
MemOp memop;
|
||||||
|
bool signed_;
|
||||||
|
size_t regsize;
|
||||||
|
if (opc.Bit<1>() == 0) {
|
||||||
|
// store or zero-extending load
|
||||||
|
memop = opc.Bit<0>() ? MemOp::LOAD : MemOp::STORE;
|
||||||
|
regsize = 32;
|
||||||
|
signed_ = false;
|
||||||
|
} else {
|
||||||
|
// sign-extending load
|
||||||
|
memop = MemOp::LOAD;
|
||||||
|
regsize = opc.Bit<0>() ? 32 : 64;
|
||||||
|
signed_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 address;
|
||||||
|
if (Rn == Reg::SP) {
|
||||||
|
// TODO: Check Stack Alignment
|
||||||
|
address = tv.SP(datasize);
|
||||||
|
} else {
|
||||||
|
address = tv.X(datasize, Rn);
|
||||||
|
}
|
||||||
|
address = ir.Add(address, ir.Imm64(offset));
|
||||||
|
|
||||||
|
switch (memop) {
|
||||||
|
case MemOp::STORE:
|
||||||
|
tv.Mem(address, datasize / 8, acctype, tv.X(datasize, Rt));
|
||||||
|
break;
|
||||||
|
case MemOp::LOAD: {
|
||||||
|
IR::U8 data = tv.Mem(address, datasize / 8, acctype);
|
||||||
|
if (signed_) {
|
||||||
|
tv.X(datasize, Rt, tv.SignExtend(data, regsize));
|
||||||
|
} else {
|
||||||
|
tv.X(datasize, Rt, tv.ZeroExtend(data, regsize));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MemOp::PREFETCH:
|
||||||
|
// Prefetch(address, Rt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::STTRB(Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
return store_register(*this, ir, 8, imm9, Rn, Rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::STTRH(Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
return store_register(*this, ir, 16, imm9, Rn, Rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::STTR(Imm<2> size, Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
const size_t scale = size.ZeroExtend<size_t>();
|
||||||
|
const size_t datasize = 8 << scale;
|
||||||
|
return store_register(*this, ir, datasize, imm9, Rn, Rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::LDTRB(Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
return load_register(*this, ir, 8, imm9, Rn, Rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::LDTRH(Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
return load_register(*this, ir, 16, imm9, Rn, Rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::LDTR(Imm<2> size, Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
const size_t scale = size.ZeroExtend<size_t>();
|
||||||
|
const size_t datasize = 8 << scale;
|
||||||
|
return load_register(*this, ir, datasize, imm9, Rn, Rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::LDTRSB(Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
return load_register_signed(*this, ir, 8, opc, imm9, Rn, Rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::LDTRSH(Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
return load_register_signed(*this, ir, 16, opc, imm9, Rn, Rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::LDTRSW(Imm<9> imm9, Reg Rn, Reg Rt) {
|
||||||
|
const u64 offset = imm9.ZeroExtend<u64>();
|
||||||
|
AccType acctype = AccType::UNPRIV;
|
||||||
|
IR::U64 address;
|
||||||
|
|
||||||
|
if (Rn == Reg::SP) {
|
||||||
|
// TODO: Check Stack Alignment
|
||||||
|
address = SP(32);
|
||||||
|
} else {
|
||||||
|
address = X(32, Rn);
|
||||||
|
}
|
||||||
|
address = ir.Add(address, ir.Imm64(offset));
|
||||||
|
IR::UAny data = Mem(address, 4, acctype);
|
||||||
|
X(32, Rt, SignExtend(data, 64));
|
||||||
|
}
|
||||||
|
} // namespace A64
|
||||||
|
} // namespace Dynarmic
|
Loading…
Reference in a new issue