diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 864ff6cc..f194b17e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -69,6 +69,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/move_wide.cpp frontend/A64/translate/translate.cpp frontend/A64/translate/translate.h frontend/A64/types.cpp diff --git a/src/backend_x64/a64_emit_x64.cpp b/src/backend_x64/a64_emit_x64.cpp index dd31bdac..0106c66e 100644 --- a/src/backend_x64/a64_emit_x64.cpp +++ b/src/backend_x64/a64_emit_x64.cpp @@ -166,8 +166,8 @@ void A64EmitX64::EmitA64SetW(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].GetImmediateU32()); + if (args[1].FitsInImmediateS32()) { + code->mov(addr, args[1].GetImmediateS32()); } else { // TODO: zext tracking, xmm variant Xbyak::Reg64 to_store = ctx.reg_alloc.UseScratchGpr(args[1]); diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index ae1638de..c609fc5f 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -15,9 +15,9 @@ INST(EOR_imm, "EOR (immediate)", "z1010 INST(ANDS_imm, "ANDS (immediate)", "z11100100Nrrrrrrssssssnnnnnddddd") // Data processing - Immediate - Move Wide -//INST(MOVN, "MOVN", "z00100101ssiiiiiiiiiiiiiiiiddddd") -//INST(MOVZ, "MOVZ", "z10100101ssiiiiiiiiiiiiiiiiddddd") -//INST(MOVK, "MOVK", "z11100101ssiiiiiiiiiiiiiiiiddddd") +INST(MOVN, "MOVN", "z00100101ssiiiiiiiiiiiiiiiiddddd") +INST(MOVZ, "MOVZ", "z10100101ssiiiiiiiiiiiiiiiiddddd") +INST(MOVK, "MOVK", "z11100101ssiiiiiiiiiiiiiiiiddddd") // Data processing - Immediate - Bitfield //INST(SBFM, "SBFM", "z00100110Nrrrrrrssssssnnnnnddddd") diff --git a/src/frontend/A64/translate/impl/move_wide.cpp b/src/frontend/A64/translate/impl/move_wide.cpp new file mode 100644 index 00000000..ec14c496 --- /dev/null +++ b/src/frontend/A64/translate/impl/move_wide.cpp @@ -0,0 +1,57 @@ +/* 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::MOVN(bool sf, Imm<2> hw, Imm<16> imm16, Reg Rd) { + size_t datasize = sf ? 64 : 32; + + if (!sf && hw.Bit<1>()) return UnallocatedEncoding(); + size_t pos = hw.ZeroExtend() << 4; + + u64 value = imm16.ZeroExtend() << pos; + value = ~value; + auto result = I(datasize, value); + X(datasize, Rd, result); + + return true; +} + +bool TranslatorVisitor::MOVZ(bool sf, Imm<2> hw, Imm<16> imm16, Reg Rd) { + size_t datasize = sf ? 64 : 32; + + if (!sf && hw.Bit<1>()) return UnallocatedEncoding(); + size_t pos = hw.ZeroExtend() << 4; + + u64 value = imm16.ZeroExtend() << pos; + auto result = I(datasize, value); + X(datasize, Rd, result); + + return true; +} + +bool TranslatorVisitor::MOVK(bool sf, Imm<2> hw, Imm<16> imm16, Reg Rd) { + size_t datasize = sf ? 64 : 32; + + if (!sf && hw.Bit<1>()) return UnallocatedEncoding(); + size_t pos = hw.ZeroExtend() << 4; + + auto result = X(datasize, Rd); + u64 mask = u64(0xFFFF) << pos; + u64 value = imm16.ZeroExtend() << pos; + result = ir.And(result, I(datasize, ~mask)); + result = ir.Or(result, I(datasize, value)); + X(datasize, Rd, result); + + return true; +} + + +} // namespace A64 +} // namespace Dynarmic