mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 09:40:15 +00:00
JitX64: Implement synchronisation instructions
This commit is contained in:
parent
8bd590ed99
commit
1f8217a09b
@ -295,6 +295,7 @@ if(ARCHITECTURE_x86_64)
|
|||||||
|
|
||||||
set(HEADERS ${HEADERS}
|
set(HEADERS ${HEADERS}
|
||||||
arm/jit_x64/common.h
|
arm/jit_x64/common.h
|
||||||
|
arm/jit_x64/instructions/helper/load_store.h
|
||||||
arm/jit_x64/interface.h
|
arm/jit_x64/interface.h
|
||||||
arm/jit_x64/jit_x64.h
|
arm/jit_x64/jit_x64.h
|
||||||
arm/jit_x64/reg_alloc.h
|
arm/jit_x64/reg_alloc.h
|
||||||
|
@ -114,7 +114,7 @@ static std::unique_ptr<Matcher> MakeMatcher(const char format[32], Function fn)
|
|||||||
return std::unique_ptr<Matcher>(std::move(ret));
|
return std::unique_ptr<Matcher>(std::move(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::array<Instruction, 220> arm_instruction_table = {{
|
static const std::array<Instruction, 221> arm_instruction_table = {{
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
{ "BLX (immediate)", MakeMatcher<2>("1111101hvvvvvvvvvvvvvvvvvvvvvvvv", &Visitor::BLX_imm) }, // ARMv5
|
{ "BLX (immediate)", MakeMatcher<2>("1111101hvvvvvvvvvvvvvvvvvvvvvvvv", &Visitor::BLX_imm) }, // ARMv5
|
||||||
{ "BLX (register)", MakeMatcher<2>("cccc000100101111111111110011mmmm", &Visitor::BLX_reg) }, // ARMv5
|
{ "BLX (register)", MakeMatcher<2>("cccc000100101111111111110011mmmm", &Visitor::BLX_reg) }, // ARMv5
|
||||||
@ -217,15 +217,16 @@ static const std::array<Instruction, 220> arm_instruction_table = {{
|
|||||||
|
|
||||||
// Synchronization Primitive instructions
|
// Synchronization Primitive instructions
|
||||||
{ "CLREX", MakeMatcher<0>("11110101011111111111000000011111", &Visitor::CLREX) }, // ARMv6K
|
{ "CLREX", MakeMatcher<0>("11110101011111111111000000011111", &Visitor::CLREX) }, // ARMv6K
|
||||||
{ "LDREX", MakeMatcher<0>("----00011001--------111110011111", &Visitor::LDREX) }, // ARMv6
|
{ "LDREX", MakeMatcher<3>("cccc00011001nnnndddd111110011111", &Visitor::LDREX) }, // ARMv6
|
||||||
{ "LDREXB", MakeMatcher<0>("----00011101--------111110011111", &Visitor::LDREXB) }, // ARMv6K
|
{ "LDREXB", MakeMatcher<3>("cccc00011101nnnndddd111110011111", &Visitor::LDREXB) }, // ARMv6K
|
||||||
{ "LDREXD", MakeMatcher<0>("----00011011--------111110011111", &Visitor::LDREXD) }, // ARMv6K
|
{ "LDREXD", MakeMatcher<3>("cccc00011011nnnndddd111110011111", &Visitor::LDREXD) }, // ARMv6K
|
||||||
{ "LDREXH", MakeMatcher<0>("----00011111--------111110011111", &Visitor::LDREXH) }, // ARMv6K
|
{ "LDREXH", MakeMatcher<3>("cccc00011111nnnndddd111110011111", &Visitor::LDREXH) }, // ARMv6K
|
||||||
{ "STREX", MakeMatcher<0>("----00011000--------11111001----", &Visitor::STREX) }, // ARMv6
|
{ "STREX", MakeMatcher<4>("cccc00011000nnnndddd11111001mmmm", &Visitor::STREX) }, // ARMv6
|
||||||
{ "STREXB", MakeMatcher<0>("----00011100--------11111001----", &Visitor::STREXB) }, // ARMv6K
|
{ "STREXB", MakeMatcher<4>("cccc00011100nnnndddd11111001mmmm", &Visitor::STREXB) }, // ARMv6K
|
||||||
{ "STREXD", MakeMatcher<0>("----00011010--------11111001----", &Visitor::STREXD) }, // ARMv6K
|
{ "STREXD", MakeMatcher<4>("cccc00011010nnnndddd11111001mmmm", &Visitor::STREXD) }, // ARMv6K
|
||||||
{ "STREXH", MakeMatcher<0>("----00011110--------11111001----", &Visitor::STREXH) }, // ARMv6K
|
{ "STREXH", MakeMatcher<4>("cccc00011110nnnndddd11111001mmmm", &Visitor::STREXH) }, // ARMv6K
|
||||||
{ "SWP", MakeMatcher<0>("----00010-00--------00001001----", &Visitor::SWP) }, // ARMv2S
|
{ "SWP", MakeMatcher<4>("cccc00010000nnnndddd00001001mmmm", &Visitor::SWP) }, // ARMv2S (Deprecated in ARMv6)
|
||||||
|
{ "SWPB", MakeMatcher<4>("cccc00010100nnnndddd00001001mmmm", &Visitor::SWPB) }, // ARMv2S (Deprecated in ARMv6)
|
||||||
|
|
||||||
// Load/Store instructions
|
// Load/Store instructions
|
||||||
{ "LDR (imm)", MakeMatcher<7>("cccc010pu0w1nnnnddddvvvvvvvvvvvv", &Visitor::LDR_imm) },
|
{ "LDR (imm)", MakeMatcher<7>("cccc010pu0w1nnnnddddvvvvvvvvvvvv", &Visitor::LDR_imm) },
|
||||||
|
@ -302,15 +302,16 @@ public:
|
|||||||
|
|
||||||
// Synchronization Primitive instructions
|
// Synchronization Primitive instructions
|
||||||
virtual void CLREX() = 0;
|
virtual void CLREX() = 0;
|
||||||
virtual void LDREX() = 0;
|
virtual void LDREX(Cond cond, Register Rn, Register Rd) = 0;
|
||||||
virtual void LDREXB() = 0;
|
virtual void LDREXB(Cond cond, Register Rn, Register Rd) = 0;
|
||||||
virtual void LDREXD() = 0;
|
virtual void LDREXD(Cond cond, Register Rn, Register Rd) = 0;
|
||||||
virtual void LDREXH() = 0;
|
virtual void LDREXH(Cond cond, Register Rn, Register Rd) = 0;
|
||||||
virtual void STREX() = 0;
|
virtual void STREX(Cond cond, Register Rn, Register Rd, Register Rm) = 0;
|
||||||
virtual void STREXB() = 0;
|
virtual void STREXB(Cond cond, Register Rn, Register Rd, Register Rm) = 0;
|
||||||
virtual void STREXD() = 0;
|
virtual void STREXD(Cond cond, Register Rn, Register Rd, Register Rm) = 0;
|
||||||
virtual void STREXH() = 0;
|
virtual void STREXH(Cond cond, Register Rn, Register Rd, Register Rm) = 0;
|
||||||
virtual void SWP() = 0;
|
virtual void SWP(Cond cond, Register Rn, Register Rd, Register Rm) = 0;
|
||||||
|
virtual void SWPB(Cond cond, Register Rn, Register Rd, Register Rm) = 0;
|
||||||
|
|
||||||
// Status register access instructions
|
// Status register access instructions
|
||||||
virtual void CPS() = 0;
|
virtual void CPS() = 0;
|
||||||
|
76
src/core/arm/jit_x64/instructions/helper/load_store.h
Normal file
76
src/core/arm/jit_x64/instructions/helper/load_store.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2016 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "common/swap.h"
|
||||||
|
|
||||||
|
#include "core/memory.h"
|
||||||
|
|
||||||
|
namespace JitX64 {
|
||||||
|
|
||||||
|
// TODO: Set up an appropriately mapped region of memory to use instead of compiling CALL instructions.
|
||||||
|
|
||||||
|
constexpr u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
|
||||||
|
|
||||||
|
static u64 Load64LE(u32 addr) {
|
||||||
|
// TODO: Improve this.
|
||||||
|
return Memory::Read32(addr) | (static_cast<u64>(Memory::Read32(addr + 4)) << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 Load64BE(u32 addr) {
|
||||||
|
// TODO: Improve this.
|
||||||
|
return Common::swap32(Memory::Read32(addr)) | (static_cast<u64>(Common::swap32(Memory::Read32(addr + 4))) << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Store64LE(u32 addr, u32 v1, u32 v2) {
|
||||||
|
Memory::Write32(addr, v1);
|
||||||
|
Memory::Write32(addr + 4, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Store64BE(u32 addr, u32 v1, u32 v2) {
|
||||||
|
Memory::Write32(addr, Common::swap32(v2));
|
||||||
|
Memory::Write32(addr + 4, Common::swap32(v1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 Load32LE(u32 addr) {
|
||||||
|
return Memory::Read32(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 Load32BE(u32 addr) {
|
||||||
|
return Common::swap32(Memory::Read32(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Store32LE(u32 addr, u32 value) {
|
||||||
|
Memory::Write32(addr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Store32BE(u32 addr, u32 value) {
|
||||||
|
Memory::Write32(addr, Common::swap32(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static u16 Load16LE(u32 addr) {
|
||||||
|
return Memory::Read16(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u16 Load16BE(u32 addr) {
|
||||||
|
return Common::swap16(Memory::Read16(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Store16LE(u32 addr, u16 value) {
|
||||||
|
Memory::Write16(addr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Store16BE(u32 addr, u16 value) {
|
||||||
|
Memory::Write16(addr, Common::swap16(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 Load8(u32 addr) {
|
||||||
|
return Memory::Read8(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Store8(u32 addr, u8 value) {
|
||||||
|
Memory::Write8(addr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace JitX64
|
@ -7,11 +7,11 @@
|
|||||||
#include "common/x64/abi.h"
|
#include "common/x64/abi.h"
|
||||||
|
|
||||||
#include "core/arm/jit_x64/jit_x64.h"
|
#include "core/arm/jit_x64/jit_x64.h"
|
||||||
#include "core/memory.h"
|
#include "core/arm/jit_x64/instructions/helper/load_store.h"
|
||||||
|
|
||||||
namespace JitX64 {
|
namespace JitX64 {
|
||||||
|
|
||||||
// TODO: Loads from constant memory regions can be turned into immediate constant loads.
|
// TODO: Optimization: Loads from read-only memory regions can be turned into immediate constant loads.
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
@ -168,68 +168,6 @@ void JitX64::LoadAndStoreWordOrUnsignedByte_ScaledRegisterPostIndexed(X64Reg des
|
|||||||
reg_alloc.UnlockArm(Rn_index);
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Set up an appropriately mapped region of memory to use instead of compiling CALL instructions.
|
|
||||||
|
|
||||||
static u64 Load64LE(u32 addr) {
|
|
||||||
// TODO: Improve this.
|
|
||||||
return Memory::Read32(addr) | (static_cast<u64>(Memory::Read32(addr + 4)) << 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u64 Load64BE(u32 addr) {
|
|
||||||
// TODO: Improve this.
|
|
||||||
return Common::swap32(Memory::Read32(addr)) | (static_cast<u64>(Common::swap32(Memory::Read32(addr + 4))) << 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Store64LE(u32 addr, u32 v1, u32 v2) {
|
|
||||||
Memory::Write32(addr, v1);
|
|
||||||
Memory::Write32(addr + 4, v2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Store64BE(u32 addr, u32 v1, u32 v2) {
|
|
||||||
Memory::Write32(addr, Common::swap32(v1));
|
|
||||||
Memory::Write32(addr+4, Common::swap32(v2));
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 Load32LE(u32 addr) {
|
|
||||||
return Memory::Read32(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 Load32BE(u32 addr) {
|
|
||||||
return Common::swap32(Memory::Read32(addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Store32LE(u32 addr, u32 value) {
|
|
||||||
Memory::Write32(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Store32BE(u32 addr, u32 value) {
|
|
||||||
Memory::Write32(addr, Common::swap32(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
static u16 Load16LE(u32 addr) {
|
|
||||||
return Memory::Read16(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u16 Load16BE(u32 addr) {
|
|
||||||
return Common::swap16(Memory::Read16(addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Store16LE(u32 addr, u16 value) {
|
|
||||||
Memory::Write16(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Store16BE(u32 addr, u16 value) {
|
|
||||||
Memory::Write16(addr, Common::swap16(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 Load8(u32 addr) {
|
|
||||||
return Memory::Read8(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Store8(u32 addr, u8 value) {
|
|
||||||
Memory::Write8(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GetValueOfRegister(XEmitter* code, RegAlloc& reg_alloc, u32 r15_value, X64Reg x64_reg, ArmReg arm_reg) {
|
static void GetValueOfRegister(XEmitter* code, RegAlloc& reg_alloc, u32 r15_value, X64Reg x64_reg, ArmReg arm_reg) {
|
||||||
if (arm_reg != 15) {
|
if (arm_reg != 15) {
|
||||||
OpArg Rd = reg_alloc.LockArmForRead(arm_reg);
|
OpArg Rd = reg_alloc.LockArmForRead(arm_reg);
|
||||||
@ -389,9 +327,6 @@ void JitX64::LDRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) {
|
void JitX64::STR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
// Rd_index == R15 is IMPLEMENTATION DEFINED
|
// Rd_index == R15 is IMPLEMENTATION DEFINED
|
||||||
@ -414,15 +349,10 @@ void JitX64::STR_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
reg_alloc.UnlockX64(ABI_PARAM1);
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
reg_alloc.UnlockX64(ABI_PARAM2);
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
|
||||||
// TODO: Exclusive stuff
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) {
|
void JitX64::STR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
// Rd_index == R15 is IMPLEMENTATION DEFINED
|
// Rd_index == R15 is IMPLEMENTATION DEFINED
|
||||||
@ -445,15 +375,10 @@ void JitX64::STR_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
reg_alloc.UnlockX64(ABI_PARAM1);
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
reg_alloc.UnlockX64(ABI_PARAM2);
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
|
||||||
// TODO: Exclusive stuff
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) {
|
void JitX64::STRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm12 imm12) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
|
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
|
||||||
@ -476,15 +401,10 @@ void JitX64::STRB_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
reg_alloc.UnlockX64(ABI_PARAM1);
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
reg_alloc.UnlockX64(ABI_PARAM2);
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
|
||||||
//TODO: Exclusive stuff
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) {
|
void JitX64::STRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm5 imm5, ShiftType shift, ArmReg Rm_index) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
|
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
|
||||||
@ -507,8 +427,6 @@ void JitX64::STRB_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
reg_alloc.UnlockX64(ABI_PARAM1);
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
reg_alloc.UnlockX64(ABI_PARAM2);
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
|
||||||
//TODO: Exclusive stuff
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,9 +689,6 @@ void JitX64::LDRSH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
|
void JitX64::STRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
|
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
|
||||||
@ -799,15 +714,10 @@ void JitX64::STRD_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
reg_alloc.UnlockX64(ABI_PARAM2);
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
reg_alloc.UnlockX64(ABI_PARAM3);
|
reg_alloc.UnlockX64(ABI_PARAM3);
|
||||||
|
|
||||||
// TODO: Exclusive stuff.
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
void JitX64::STRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
|
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
|
||||||
@ -835,15 +745,10 @@ void JitX64::STRD_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
reg_alloc.UnlockX64(ABI_PARAM2);
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
reg_alloc.UnlockX64(ABI_PARAM3);
|
reg_alloc.UnlockX64(ABI_PARAM3);
|
||||||
|
|
||||||
// TODO: Exclusive stuff.
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
|
void JitX64::STRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmImm4 imm8a, ArmImm4 imm8b) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
|
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
|
||||||
@ -866,15 +771,10 @@ void JitX64::STRH_imm(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
reg_alloc.UnlockX64(ABI_PARAM1);
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
reg_alloc.UnlockX64(ABI_PARAM2);
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
|
||||||
// TODO: Exclusive stuff.
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
void JitX64::STRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
|
ASSERT_MSG(Rd_index != 15, "UNPREDICTABLE");
|
||||||
@ -897,8 +797,6 @@ void JitX64::STRH_reg(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmReg
|
|||||||
reg_alloc.UnlockX64(ABI_PARAM1);
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
reg_alloc.UnlockX64(ABI_PARAM2);
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
|
||||||
// TODO: Exclusive stuff.
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1114,9 +1012,6 @@ static void ExecuteSTMBE(u32 start_address, u16 reg_list, JitState* jit_state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JitX64::STM(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRegList list) {
|
void JitX64::STM(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRegList list) {
|
||||||
CompileInterpretInstruction();
|
|
||||||
return;
|
|
||||||
|
|
||||||
cond_manager.CompileCond((ConditionCode)cond);
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
ASSERT_MSG(Rn_index != 15, "UNPREDICTABLE");
|
ASSERT_MSG(Rn_index != 15, "UNPREDICTABLE");
|
||||||
@ -1129,8 +1024,6 @@ void JitX64::STM(Cond cond, bool P, bool U, bool W, ArmReg Rn_index, ArmRegList
|
|||||||
LoadAndStoreMultiple_Helper(code, reg_alloc, P, U, W, Rn_index, list,
|
LoadAndStoreMultiple_Helper(code, reg_alloc, P, U, W, Rn_index, list,
|
||||||
[this](){ CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? &ExecuteSTMLE : &ExecuteSTMBE)); });
|
[this](){ CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? &ExecuteSTMLE : &ExecuteSTMBE)); });
|
||||||
|
|
||||||
// TODO: Exclusive stuff
|
|
||||||
|
|
||||||
current.arm_pc += GetInstSize();
|
current.arm_pc += GetInstSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,19 +2,296 @@
|
|||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/x64/abi.h"
|
||||||
|
|
||||||
#include "core/arm/jit_x64/jit_x64.h"
|
#include "core/arm/jit_x64/jit_x64.h"
|
||||||
|
#include "core/arm/jit_x64/instructions/helper/load_store.h"
|
||||||
|
|
||||||
namespace JitX64 {
|
namespace JitX64 {
|
||||||
|
|
||||||
void JitX64::CLREX() { CompileInterpretInstruction(); }
|
using namespace Gen;
|
||||||
void JitX64::LDREX() { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::LDREXB() { CompileInterpretInstruction(); }
|
void JitX64::CLREX() {
|
||||||
void JitX64::LDREXD() { CompileInterpretInstruction(); }
|
cond_manager.Always();
|
||||||
void JitX64::LDREXH() { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::STREX() { CompileInterpretInstruction(); }
|
code->MOV(32, MJitStateExclusiveTag(), Imm32(0xFFFFFFFF));
|
||||||
void JitX64::STREXB() { CompileInterpretInstruction(); }
|
code->MOV(8, MJitStateExclusiveState(), Imm8(0));
|
||||||
void JitX64::STREXD() { CompileInterpretInstruction(); }
|
|
||||||
void JitX64::STREXH() { CompileInterpretInstruction(); }
|
current.arm_pc += GetInstSize();
|
||||||
void JitX64::SWP() { CompileInterpretInstruction(); }
|
}
|
||||||
|
|
||||||
|
void ExclusiveLoadCommon(XEmitter* code, RegAlloc& reg_alloc, OpArg exclusive_state, OpArg exclusive_tag, ArmReg Rn_index, ArmReg Rd_index) {
|
||||||
|
ASSERT_MSG(Rn_index != 15 && Rd_index != 15, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
code->MOV(8, exclusive_state, Imm8(1));
|
||||||
|
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM1);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM1);
|
||||||
|
|
||||||
|
OpArg Rn = reg_alloc.LockArmForRead(Rn_index);
|
||||||
|
code->MOV(32, R(ABI_PARAM1), Rn);
|
||||||
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
|
|
||||||
|
code->MOV(32, exclusive_tag, R(ABI_PARAM1));
|
||||||
|
code->AND(32, exclusive_tag, Imm32(RESERVATION_GRANULE_MASK));
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::LDREX(Cond cond, ArmReg Rn_index, ArmReg Rd_index) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
ASSERT_MSG(Rn_index != 15 && Rd_index != 15, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
ExclusiveLoadCommon(code, reg_alloc, MJitStateExclusiveState(), MJitStateExclusiveTag(), Rn_index, Rd_index);
|
||||||
|
CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? &Load32LE : &Load32BE));
|
||||||
|
|
||||||
|
reg_alloc.LockX64(ABI_RETURN);
|
||||||
|
|
||||||
|
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
|
||||||
|
code->MOV(32, R(Rd), R(ABI_RETURN));
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_RETURN);
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::LDREXB(Cond cond, ArmReg Rn_index, ArmReg Rd_index) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
ASSERT_MSG(Rn_index != 15 && Rd_index != 15, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
ExclusiveLoadCommon(code, reg_alloc, MJitStateExclusiveState(), MJitStateExclusiveTag(), Rn_index, Rd_index);
|
||||||
|
CompileCallHost(reinterpret_cast<const void* const>(&Load8));
|
||||||
|
|
||||||
|
reg_alloc.LockX64(ABI_RETURN);
|
||||||
|
|
||||||
|
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
|
||||||
|
code->MOVZX(32, 8, Rd, R(ABI_RETURN));
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_RETURN);
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::LDREXD(Cond cond, ArmReg Rn_index, ArmReg Rd_index) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
ASSERT_MSG(Rd_index % 2 == 0, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rd_index < 14, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rn_index != 15, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
ExclusiveLoadCommon(code, reg_alloc, MJitStateExclusiveState(), MJitStateExclusiveTag(), Rn_index, Rd_index);
|
||||||
|
CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? Load64LE : Load64BE));
|
||||||
|
|
||||||
|
reg_alloc.LockX64(ABI_RETURN);
|
||||||
|
|
||||||
|
X64Reg Rd0 = reg_alloc.BindArmForWrite(Rd_index + 0);
|
||||||
|
X64Reg Rd1 = reg_alloc.BindArmForWrite(Rd_index + 1);
|
||||||
|
code->MOV(64, R(Rd0), R(ABI_RETURN));
|
||||||
|
code->SHR(64, R(ABI_RETURN), Imm8(32));
|
||||||
|
code->MOV(32, R(Rd1), R(ABI_RETURN));
|
||||||
|
reg_alloc.UnlockArm(Rd_index + 0);
|
||||||
|
reg_alloc.UnlockArm(Rd_index + 1);
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_RETURN);
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::LDREXH(Cond cond, ArmReg Rn_index, ArmReg Rd_index) {
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
ASSERT_MSG(Rn_index != 15 && Rd_index != 15, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
ExclusiveLoadCommon(code, reg_alloc, MJitStateExclusiveState(), MJitStateExclusiveTag(), Rn_index, Rd_index);
|
||||||
|
CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? Load16LE : Load16BE));
|
||||||
|
|
||||||
|
reg_alloc.LockX64(ABI_RETURN);
|
||||||
|
|
||||||
|
X64Reg Rd = reg_alloc.BindArmForWrite(Rd_index);
|
||||||
|
code->MOVZX(32, 16, Rd, R(ABI_RETURN));
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_RETURN);
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExclusiveStoreCommon(XEmitter* code, RegAlloc& reg_alloc, OpArg exclusive_state, OpArg exclusive_tag, ArmReg Rn_index, ArmReg Rd_index, std::function<void()> do_memory_access) {
|
||||||
|
OpArg Rn = reg_alloc.LockArmForRead(Rn_index);
|
||||||
|
OpArg Rd = reg_alloc.LockArmForWrite(Rd_index);
|
||||||
|
|
||||||
|
code->MOV(32, Rd, Imm8(1)); // First, assume we failed.
|
||||||
|
|
||||||
|
code->MOV(32, R(ABI_PARAM1), Rn);
|
||||||
|
|
||||||
|
code->BT(8, exclusive_state, Imm8(0));
|
||||||
|
auto jmp_to_end1 = code->J_CC(CC_NC);
|
||||||
|
|
||||||
|
code->MOV(32, R(ABI_PARAM2), R(ABI_PARAM1));
|
||||||
|
code->AND(32, R(ABI_PARAM2), Imm32(RESERVATION_GRANULE_MASK));
|
||||||
|
code->CMP(32, R(ABI_PARAM2), exclusive_tag);
|
||||||
|
auto jmp_to_end2 = code->J_CC(CC_NE);
|
||||||
|
|
||||||
|
// Exclsuive monitor pass
|
||||||
|
code->MOV(32, Rd, Imm8(0)); // Okay, actually we passed.
|
||||||
|
code->MOV(8, exclusive_state, Imm8(0)); // Unset exclusive memory acecss.
|
||||||
|
code->MOV(32, exclusive_tag, Imm32(0xFFFFFFFF)); // Unset exclusive memory acecss.
|
||||||
|
|
||||||
|
do_memory_access();
|
||||||
|
|
||||||
|
code->SetJumpTarget(jmp_to_end1);
|
||||||
|
code->SetJumpTarget(jmp_to_end2);
|
||||||
|
|
||||||
|
reg_alloc.UnlockArm(Rd_index);
|
||||||
|
reg_alloc.UnlockArm(Rn_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::STREX(Cond cond, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
||||||
|
CompileInterpretInstruction();
|
||||||
|
return;
|
||||||
|
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
ASSERT_MSG(Rn_index != 15 && Rd_index != 15 && Rm_index != 15, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rd_index != Rn_index && Rd_index != Rm_index, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM1);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM1);
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM2);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM2);
|
||||||
|
|
||||||
|
OpArg Rm = reg_alloc.LockArmForRead(Rm_index);
|
||||||
|
|
||||||
|
ExclusiveStoreCommon(code, reg_alloc, MJitStateExclusiveState(), MJitStateExclusiveTag(),
|
||||||
|
Rn_index, Rd_index,
|
||||||
|
[&](){
|
||||||
|
code->MOV(32, R(ABI_PARAM2), Rm);
|
||||||
|
CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? &Store32LE : &Store32BE));
|
||||||
|
});
|
||||||
|
|
||||||
|
reg_alloc.UnlockArm(Rm_index);
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::STREXB(Cond cond, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
||||||
|
CompileInterpretInstruction();
|
||||||
|
return;
|
||||||
|
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
ASSERT_MSG(Rn_index != 15 && Rd_index != 15 && Rm_index != 15, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rd_index != Rn_index && Rd_index != Rm_index, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM1);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM1);
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM2);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM2);
|
||||||
|
|
||||||
|
OpArg Rm = reg_alloc.LockArmForRead(Rm_index);
|
||||||
|
|
||||||
|
ExclusiveStoreCommon(code, reg_alloc, MJitStateExclusiveState(), MJitStateExclusiveTag(),
|
||||||
|
Rn_index, Rd_index,
|
||||||
|
[&]() {
|
||||||
|
code->MOV(32, R(ABI_PARAM2), Rm);
|
||||||
|
CompileCallHost(reinterpret_cast<const void* const>(&Store8));
|
||||||
|
});
|
||||||
|
|
||||||
|
reg_alloc.UnlockArm(Rm_index);
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::STREXD(Cond cond, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
||||||
|
CompileInterpretInstruction();
|
||||||
|
return;
|
||||||
|
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
ASSERT_MSG(Rn_index != 15 && Rd_index != 15 && Rm_index != 15, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rm_index != 14, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rd_index != Rn_index && Rd_index != Rm_index, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rd_index != Rm_index + 1, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rm_index % 2 == 0, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM1);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM1);
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM2);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM2);
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM3);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM3);
|
||||||
|
|
||||||
|
OpArg Rm0 = reg_alloc.LockArmForRead(Rm_index + 0);
|
||||||
|
OpArg Rm1 = reg_alloc.LockArmForRead(Rm_index + 1);
|
||||||
|
|
||||||
|
ExclusiveStoreCommon(code, reg_alloc, MJitStateExclusiveState(), MJitStateExclusiveTag(),
|
||||||
|
Rn_index, Rd_index,
|
||||||
|
[&]() {
|
||||||
|
code->MOV(32, R(ABI_PARAM2), Rm0);
|
||||||
|
code->MOV(32, R(ABI_PARAM3), Rm1);
|
||||||
|
CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? &Store64LE : &Store64BE));
|
||||||
|
});
|
||||||
|
|
||||||
|
reg_alloc.UnlockArm(Rm_index + 1);
|
||||||
|
reg_alloc.UnlockArm(Rm_index + 0);
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM3);
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::STREXH(Cond cond, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
||||||
|
CompileInterpretInstruction();
|
||||||
|
return;
|
||||||
|
|
||||||
|
cond_manager.CompileCond((ConditionCode)cond);
|
||||||
|
|
||||||
|
ASSERT_MSG(Rn_index != 15 && Rd_index != 15 && Rm_index != 15, "UNPREDICTABLE");
|
||||||
|
ASSERT_MSG(Rd_index != Rn_index && Rd_index != Rm_index, "UNPREDICTABLE");
|
||||||
|
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM1);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM1);
|
||||||
|
reg_alloc.FlushX64(ABI_PARAM2);
|
||||||
|
reg_alloc.LockX64(ABI_PARAM2);
|
||||||
|
|
||||||
|
OpArg Rm = reg_alloc.LockArmForRead(Rm_index);
|
||||||
|
|
||||||
|
ExclusiveStoreCommon(code, reg_alloc, MJitStateExclusiveState(), MJitStateExclusiveTag(),
|
||||||
|
Rn_index, Rd_index,
|
||||||
|
[&]() {
|
||||||
|
code->MOV(32, R(ABI_PARAM2), Rm);
|
||||||
|
CompileCallHost(reinterpret_cast<const void* const>(!current.EFlag ? &Store16LE : &Store16BE));
|
||||||
|
});
|
||||||
|
|
||||||
|
reg_alloc.UnlockArm(Rm_index);
|
||||||
|
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM2);
|
||||||
|
reg_alloc.UnlockX64(ABI_PARAM1);
|
||||||
|
|
||||||
|
current.arm_pc += GetInstSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::SWP(Cond cond, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
||||||
|
CompileInterpretInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitX64::SWPB(Cond cond, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rm_index) {
|
||||||
|
CompileInterpretInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -51,7 +51,6 @@ CodePtr JitX64::Compile(u32 pc, bool TFlag, bool EFlag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reg_alloc.AssertNoLocked();
|
reg_alloc.AssertNoLocked();
|
||||||
reg_alloc.FlushEverything();
|
|
||||||
} while (!stop_compilation && ((current.arm_pc & 0xFFF) != 0));
|
} while (!stop_compilation && ((current.arm_pc & 0xFFF) != 0));
|
||||||
|
|
||||||
if (!stop_compilation) {
|
if (!stop_compilation) {
|
||||||
|
@ -399,15 +399,16 @@ private:
|
|||||||
|
|
||||||
// Synchronization Primitive instructions
|
// Synchronization Primitive instructions
|
||||||
void CLREX() override;
|
void CLREX() override;
|
||||||
void LDREX() override;
|
void LDREX(Cond cond, ArmReg Rn, ArmReg Rd) override;
|
||||||
void LDREXB() override;
|
void LDREXB(Cond cond, ArmReg Rn, ArmReg Rd) override;
|
||||||
void LDREXD() override;
|
void LDREXD(Cond cond, ArmReg Rn, ArmReg Rd) override;
|
||||||
void LDREXH() override;
|
void LDREXH(Cond cond, ArmReg Rn, ArmReg Rd) override;
|
||||||
void STREX() override;
|
void STREX(Cond cond, ArmReg Rn, ArmReg Rd, ArmReg Rm) override;
|
||||||
void STREXB() override;
|
void STREXB(Cond cond, ArmReg Rn, ArmReg Rd, ArmReg Rm) override;
|
||||||
void STREXD() override;
|
void STREXD(Cond cond, ArmReg Rn, ArmReg Rd, ArmReg Rm) override;
|
||||||
void STREXH() override;
|
void STREXH(Cond cond, ArmReg Rn, ArmReg Rd, ArmReg Rm) override;
|
||||||
void SWP() override;
|
void SWP(Cond cond, ArmReg Rn, ArmReg Rd, ArmReg Rm) override;
|
||||||
|
void SWPB(Cond cond, ArmReg Rn, ArmReg Rd, ArmReg Rm) override;
|
||||||
|
|
||||||
// Status register access instructions
|
// Status register access instructions
|
||||||
void CPS() override;
|
void CPS() override;
|
||||||
|
Loading…
Reference in New Issue
Block a user