diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23e7a12b..073eacc7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,6 +59,7 @@ add_library(dynarmic frontend/A64/location_descriptor.cpp frontend/A64/location_descriptor.h frontend/A64/translate/impl/data_processing_addsub.cpp + frontend/A64/translate/impl/data_processing_pcrel.cpp frontend/A64/translate/impl/impl.cpp frontend/A64/translate/impl/impl.h frontend/A64/translate/translate.cpp diff --git a/src/backend_x64/a64_emit_x64.cpp b/src/backend_x64/a64_emit_x64.cpp index 17290e62..5fbeda8a 100644 --- a/src/backend_x64/a64_emit_x64.cpp +++ b/src/backend_x64/a64_emit_x64.cpp @@ -173,8 +173,8 @@ void A64EmitX64::EmitA64SetX(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); A64::Reg reg = inst->GetArg(0).GetA64RegRef(); auto addr = qword[r15 + offsetof(A64JitState, reg) + sizeof(u64) * static_cast(reg)]; - if (args[1].IsImmediate()) { - code->mov(addr, args[1].GetImmediateU64()); + if (args[1].FitsInImmediateU32()) { + code->mov(addr, args[1].GetImmediateU32()); } else if (args[1].IsInXmm()) { Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[1]); code->movq(addr, to_store); @@ -187,8 +187,8 @@ void A64EmitX64::EmitA64SetX(A64EmitContext& ctx, IR::Inst* inst) { void A64EmitX64::EmitA64SetSP(A64EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto addr = qword[r15 + offsetof(A64JitState, sp)]; - if (args[0].IsImmediate()) { - code->mov(addr, args[0].GetImmediateU64()); + if (args[0].FitsInImmediateU32()) { + code->mov(addr, args[0].GetImmediateU32()); } else if (args[0].IsInXmm()) { Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[0]); code->movq(addr, to_store); diff --git a/src/backend_x64/reg_alloc.cpp b/src/backend_x64/reg_alloc.cpp index 7a1c14a0..25c099ca 100644 --- a/src/backend_x64/reg_alloc.cpp +++ b/src/backend_x64/reg_alloc.cpp @@ -100,6 +100,13 @@ bool Argument::IsImmediate() const { return value.IsImmediate(); } +bool Argument::FitsInImmediateU32() const { + if (!IsImmediate()) + return false; + u64 imm = ImmediateToU64(value); + return imm < 0x100000000; +} + bool Argument::GetImmediateU1() const { return value.GetU1(); } diff --git a/src/backend_x64/reg_alloc.h b/src/backend_x64/reg_alloc.h index c0a22c04..917151ce 100644 --- a/src/backend_x64/reg_alloc.h +++ b/src/backend_x64/reg_alloc.h @@ -56,6 +56,8 @@ public: IR::Type GetType() const; bool IsImmediate() const; + bool FitsInImmediateU32() const; + bool GetImmediateU1() const; u8 GetImmediateU8() const; u16 GetImmediateU16() const; diff --git a/src/frontend/A64/decoder/a64.h b/src/frontend/A64/decoder/a64.h index c992b514..bc0e7f97 100644 --- a/src/frontend/A64/decoder/a64.h +++ b/src/frontend/A64/decoder/a64.h @@ -30,8 +30,8 @@ std::vector> GetDecodeTable() { #define INST(fn, name, bitstring) Decoder::detail::detail>::GetMatcher(fn, name, bitstring) // Data processing - Immediate - PC relative addressing - //INST(&V::ADR, "ADR", "0ii10000iiiiiiiiiiiiiiiiiiiddddd"), - //INST(&V::ADRP, "ADRP", "1ii10000iiiiiiiiiiiiiiiiiiiddddd"), + INST(&V::ADR, "ADR", "0ii10000iiiiiiiiiiiiiiiiiiiddddd"), + INST(&V::ADRP, "ADRP", "1ii10000iiiiiiiiiiiiiiiiiiiddddd"), // Data processing - Immediate - Add/Sub INST(&V::ADD_imm, "ADD (immediate)", "z0010001ssiiiiiiiiiiiinnnnnddddd"), diff --git a/src/frontend/A64/translate/impl/data_processing_pcrel.cpp b/src/frontend/A64/translate/impl/data_processing_pcrel.cpp new file mode 100644 index 00000000..c599fdd0 --- /dev/null +++ b/src/frontend/A64/translate/impl/data_processing_pcrel.cpp @@ -0,0 +1,27 @@ +/* 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 { + +bool TranslatorVisitor::ADR(Imm<2> immlo, Imm<19> immhi, Reg Rd) { + u64 imm = concatenate(immhi, immlo).ZeroExtend(); + u64 base = ir.PC(); + X(64, Rd, ir.Imm64(base + imm)); + return true; +} + +bool TranslatorVisitor::ADRP(Imm<2> immlo, Imm<19> immhi, Reg Rd) { + u64 imm = concatenate(immhi, immlo).ZeroExtend() << 12; + u64 base = ir.PC() & ~u64(0xFFF); + X(64, Rd, ir.Imm64(base + imm)); + return true; +} + +} // namespace A64 +} // namespace Dynarmic