From 41e6e659c5d6706bd233b9ea99c1374b599ea64a Mon Sep 17 00:00:00 2001 From: James Rowe Date: Mon, 22 Jan 2018 00:37:27 -0700 Subject: [PATCH] A64: Implement Load/Store register (unprivileged) --- src/CMakeLists.txt | 1 + src/frontend/A64/decoder/a64.inc | 18 +-- src/frontend/A64/translate/impl/impl.h | 8 +- .../impl/load_store_register_unprivileged.cpp | 147 ++++++++++++++++++ 4 files changed, 161 insertions(+), 13 deletions(-) create mode 100644 src/frontend/A64/translate/impl/load_store_register_unprivileged.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 92762683..9c174d82 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -74,6 +74,7 @@ add_library(dynarmic 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_pair.cpp + frontend/A64/translate/impl/load_store_register_unprivileged.cpp frontend/A64/translate/impl/move_wide.cpp frontend/A64/translate/impl/simd_copy.cpp frontend/A64/translate/impl/simd_three_same.cpp diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index 6c7dd821..090ef134 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -214,15 +214,15 @@ INST(LDR_imm_fpsimd_1, "LDR (immediate, SIMD&FP)", "zz111 INST(LDR_imm_fpsimd_2, "LDR (immediate, SIMD&FP)", "zz111101o1iiiiiiiiiiiinnnnnttttt") // Loads and stores - Load/Store register (unprivileged) -//INST(STTRB, "STTRB", "00111000000iiiiiiiii10nnnnnttttt") -//INST(LDTRB, "LDTRB", "00111000010iiiiiiiii10nnnnnttttt") -//INST(LDTRSB, "LDTRSB", "001110001-0iiiiiiiii10nnnnnttttt") -//INST(STTRH, "STTRH", "01111000000iiiiiiiii10nnnnnttttt") -//INST(LDTRH, "LDTRH", "01111000010iiiiiiiii10nnnnnttttt") -//INST(LDTRSH, "LDTRSH", "011110001-0iiiiiiiii10nnnnnttttt") -//INST(STTR, "STTR", "1-111000000iiiiiiiii10nnnnnttttt") -//INST(LDTR, "LDTR", "1-111000010iiiiiiiii10nnnnnttttt") -//INST(LDTRSW, "LDTRSW", "10111000100iiiiiiiii10nnnnnttttt") +INST(STTRB, "STTRB", "00111000000iiiiiiiii10nnnnnttttt") +INST(LDTRB, "LDTRB", "00111000010iiiiiiiii10nnnnnttttt") +INST(LDTRSB, "LDTRSB", "00111000oo0iiiiiiiii10nnnnnttttt") +INST(STTRH, "STTRH", "01111000000iiiiiiiii10nnnnnttttt") +INST(LDTRH, "LDTRH", "01111000010iiiiiiiii10nnnnnttttt") +INST(LDTRSH, "LDTRSH", "011110001-0iiiiiiiii10nnnnnttttt") +INST(STTR, "STTR", "1z111000000iiiiiiiii10nnnnnttttt") +INST(LDTR, "LDTR", "1z111000010iiiiiiiii10nnnnnttttt") +INST(LDTRSW, "LDTRSW", "10111000100iiiiiiiii10nnnnnttttt") // Loads and stores - Atomic memory options //INST(LDADDB, "LDADDB, LDADDAB, LDADDALB, LDADDLB", "00111000AR1sssss000000nnnnnttttt") diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index ad677315..60b16666 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -267,12 +267,12 @@ struct TranslatorVisitor final { // Loads and stores - Load/Store register (unprivileged) bool STTRB(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 LDTRH(Imm<9> imm9, Reg Rn, Reg Rt); - bool LDTRSH(Imm<9> imm9, Reg Rn, Reg Rt); - bool STTR(Imm<9> imm9, Reg Rn, Reg Rt); - bool LDTR(Imm<9> imm9, Reg Rn, Reg Rt); + bool LDTRSH(Imm<2> opc, Imm<9> imm9, Reg Rn, Reg Rt); + bool STTR(Imm<2> size, 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); // Loads and stores - Atomic memory options diff --git a/src/frontend/A64/translate/impl/load_store_register_unprivileged.cpp b/src/frontend/A64/translate/impl/load_store_register_unprivileged.cpp new file mode 100644 index 00000000..3ecb4916 --- /dev/null +++ b/src/frontend/A64/translate/impl/load_store_register_unprivileged.cpp @@ -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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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 \ No newline at end of file