mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 07:40:13 +00:00
JitX64: Initial implementation of JitX64 compiler
This commit is contained in:
parent
e34c66d62b
commit
b9a852b048
@ -266,11 +266,36 @@ set(HEADERS
|
||||
|
||||
if(ARCHITECTURE_x86_64)
|
||||
set(SRCS ${SRCS}
|
||||
arm/jit_x64/cond.cpp
|
||||
arm/jit_x64/instructions/barrier.cpp
|
||||
arm/jit_x64/instructions/branch.cpp
|
||||
arm/jit_x64/instructions/coprocessor.cpp
|
||||
arm/jit_x64/instructions/data_processing.cpp
|
||||
arm/jit_x64/instructions/exception_generating.cpp
|
||||
arm/jit_x64/instructions/extension.cpp
|
||||
arm/jit_x64/instructions/hint.cpp
|
||||
arm/jit_x64/instructions/load_store.cpp
|
||||
arm/jit_x64/instructions/misc.cpp
|
||||
arm/jit_x64/instructions/usad.cpp
|
||||
arm/jit_x64/instructions/packing.cpp
|
||||
arm/jit_x64/instructions/reversal.cpp
|
||||
arm/jit_x64/instructions/saturation.cpp
|
||||
arm/jit_x64/instructions/multiply.cpp
|
||||
arm/jit_x64/instructions/parallel_add_subtract_modulo.cpp
|
||||
arm/jit_x64/instructions/parallel_add_subtract_saturating.cpp
|
||||
arm/jit_x64/instructions/parallel_add_subtract_halving.cpp
|
||||
arm/jit_x64/instructions/qadd_qsub.cpp
|
||||
arm/jit_x64/instructions/synchronisation.cpp
|
||||
arm/jit_x64/instructions/status_register.cpp
|
||||
arm/jit_x64/instructions/thumb.cpp
|
||||
arm/jit_x64/interpret.cpp
|
||||
arm/jit_x64/jit_x64.cpp
|
||||
arm/jit_x64/reg_alloc.cpp
|
||||
)
|
||||
|
||||
set(HEADERS ${HEADERS}
|
||||
arm/jit_x64/common.h
|
||||
arm/jit_x64/jit_x64.h
|
||||
arm/jit_x64/reg_alloc.h
|
||||
)
|
||||
endif()
|
||||
|
145
src/core/arm/jit_x64/cond.cpp
Normal file
145
src/core/arm/jit_x64/cond.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
void JitX64::CondManager::Init(JitX64* jit_) {
|
||||
jit = jit_;
|
||||
current_cond = ConditionCode::AL;
|
||||
flags_dirty = false;
|
||||
current_cond_fixup = {};
|
||||
}
|
||||
|
||||
void JitX64::CondManager::CompileCond(const ConditionCode new_cond) {
|
||||
if (current_cond == new_cond && !flags_dirty)
|
||||
return;
|
||||
|
||||
if (current_cond != ConditionCode::AL && current_cond != ConditionCode::NV) {
|
||||
jit->reg_alloc.FlushEverything();
|
||||
ASSERT(current_cond_fixup.ptr);
|
||||
jit->code->SetJumpTarget(current_cond_fixup);
|
||||
current_cond_fixup.ptr = nullptr;
|
||||
}
|
||||
|
||||
if (new_cond != ConditionCode::AL && new_cond != ConditionCode::NV) {
|
||||
CCFlags cc;
|
||||
|
||||
switch (new_cond) {
|
||||
case ConditionCode::EQ: //z
|
||||
jit->code->CMP(8, jit->MJitStateZFlag(), Imm8(0));
|
||||
cc = CC_E;
|
||||
break;
|
||||
case ConditionCode::NE: //!z
|
||||
jit->code->CMP(8, jit->MJitStateZFlag(), Imm8(0));
|
||||
cc = CC_NE;
|
||||
break;
|
||||
case ConditionCode::CS: //c
|
||||
jit->code->CMP(8, jit->MJitStateCFlag(), Imm8(0));
|
||||
cc = CC_E;
|
||||
break;
|
||||
case ConditionCode::CC: //!c
|
||||
jit->code->CMP(8, jit->MJitStateCFlag(), Imm8(0));
|
||||
cc = CC_NE;
|
||||
break;
|
||||
case ConditionCode::MI: //n
|
||||
jit->code->CMP(8, jit->MJitStateNFlag(), Imm8(0));
|
||||
cc = CC_E;
|
||||
break;
|
||||
case ConditionCode::PL: //!n
|
||||
jit->code->CMP(8, jit->MJitStateNFlag(), Imm8(0));
|
||||
cc = CC_NE;
|
||||
break;
|
||||
case ConditionCode::VS: //v
|
||||
jit->code->CMP(8, jit->MJitStateVFlag(), Imm8(0));
|
||||
cc = CC_E;
|
||||
break;
|
||||
case ConditionCode::VC: //!v
|
||||
jit->code->CMP(8, jit->MJitStateVFlag(), Imm8(0));
|
||||
cc = CC_NE;
|
||||
break;
|
||||
case ConditionCode::HI: { //c & !z
|
||||
const X64Reg tmp = jit->reg_alloc.AllocAndLockTemp();
|
||||
jit->code->MOVZX(64, 8, tmp, jit->MJitStateZFlag());
|
||||
jit->code->CMP(8, jit->MJitStateCFlag(), R(tmp));
|
||||
cc = CC_BE;
|
||||
jit->reg_alloc.UnlockTemp(tmp);
|
||||
break;
|
||||
}
|
||||
case ConditionCode::LS: { //!c | z
|
||||
const X64Reg tmp = jit->reg_alloc.AllocAndLockTemp();
|
||||
jit->code->MOVZX(64, 8, tmp, jit->MJitStateZFlag());
|
||||
jit->code->CMP(8, jit->MJitStateCFlag(), R(tmp));
|
||||
cc = CC_A;
|
||||
jit->reg_alloc.UnlockTemp(tmp);
|
||||
break;
|
||||
}
|
||||
case ConditionCode::GE: { // n == v
|
||||
const X64Reg tmp = jit->reg_alloc.AllocAndLockTemp();
|
||||
jit->code->MOVZX(64, 8, tmp, jit->MJitStateVFlag());
|
||||
jit->code->CMP(8, jit->MJitStateNFlag(), R(tmp));
|
||||
cc = CC_NE;
|
||||
jit->reg_alloc.UnlockTemp(tmp);
|
||||
break;
|
||||
}
|
||||
case ConditionCode::LT: { // n != v
|
||||
const X64Reg tmp = jit->reg_alloc.AllocAndLockTemp();
|
||||
jit->code->MOVZX(64, 8, tmp, jit->MJitStateVFlag());
|
||||
jit->code->CMP(8, jit->MJitStateNFlag(), R(tmp));
|
||||
cc = CC_E;
|
||||
jit->reg_alloc.UnlockTemp(tmp);
|
||||
break;
|
||||
}
|
||||
case ConditionCode::GT: { // !z & (n == v)
|
||||
const X64Reg tmp = jit->reg_alloc.AllocAndLockTemp();
|
||||
jit->code->MOVZX(64, 8, tmp, jit->MJitStateNFlag());
|
||||
jit->code->XOR(8, R(tmp), jit->MJitStateVFlag());
|
||||
jit->code->OR(8, R(tmp), jit->MJitStateZFlag());
|
||||
jit->code->TEST(8, R(tmp), R(tmp));
|
||||
cc = CC_NZ;
|
||||
jit->reg_alloc.UnlockTemp(tmp);
|
||||
break;
|
||||
}
|
||||
case ConditionCode::LE: { // z | (n != v)
|
||||
X64Reg tmp = jit->reg_alloc.AllocAndLockTemp();
|
||||
jit->code->MOVZX(64, 8, tmp, jit->MJitStateNFlag());
|
||||
jit->code->XOR(8, R(tmp), jit->MJitStateVFlag());
|
||||
jit->code->OR(8, R(tmp), jit->MJitStateZFlag());
|
||||
jit->code->TEST(8, R(tmp), R(tmp));
|
||||
cc = CC_Z;
|
||||
jit->reg_alloc.UnlockTemp(tmp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
jit->reg_alloc.FlushEverything();
|
||||
this->current_cond_fixup = jit->code->J_CC(cc, true);
|
||||
}
|
||||
|
||||
current_cond = new_cond;
|
||||
flags_dirty = false;
|
||||
}
|
||||
|
||||
void JitX64::CondManager::Always() {
|
||||
CompileCond(ConditionCode::AL);
|
||||
}
|
||||
|
||||
void JitX64::CondManager::FlagsDirty() {
|
||||
flags_dirty = true;
|
||||
}
|
||||
|
||||
ConditionCode JitX64::CondManager::CurrentCond() {
|
||||
return current_cond;
|
||||
}
|
||||
|
||||
}
|
13
src/core/arm/jit_x64/instructions/barrier.cpp
Normal file
13
src/core/arm/jit_x64/instructions/barrier.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::DMB() { CompileInterpretInstruction(); }
|
||||
void JitX64::DSB() { CompileInterpretInstruction(); }
|
||||
void JitX64::ISB() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
16
src/core/arm/jit_x64/instructions/branch.cpp
Normal file
16
src/core/arm/jit_x64/instructions/branch.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::B(Cond cond, ArmImm24 imm24) { CompileInterpretInstruction(); }
|
||||
void JitX64::BL(Cond cond, ArmImm24 imm24) { CompileInterpretInstruction(); }
|
||||
void JitX64::BLX_imm(bool H, ArmImm24 imm24) { CompileInterpretInstruction(); }
|
||||
void JitX64::BLX_reg(Cond cond, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::BX(Cond cond, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::BXJ(Cond cond, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
17
src/core/arm/jit_x64/instructions/coprocessor.cpp
Normal file
17
src/core/arm/jit_x64/instructions/coprocessor.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::CDP() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDC() { CompileInterpretInstruction(); }
|
||||
void JitX64::MCR() { CompileInterpretInstruction(); }
|
||||
void JitX64::MCRR() { CompileInterpretInstruction(); }
|
||||
void JitX64::MRC() { CompileInterpretInstruction(); }
|
||||
void JitX64::MRRC() { CompileInterpretInstruction(); }
|
||||
void JitX64::STC() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
58
src/core/arm/jit_x64/instructions/data_processing.cpp
Normal file
58
src/core/arm/jit_x64/instructions/data_processing.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::ADC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::ADC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::ADC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::ADD_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::ADD_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::ADD_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::AND_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::AND_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::AND_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::BIC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::BIC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::BIC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::CMN_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::CMN_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::CMN_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::CMP_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::CMP_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::CMP_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::EOR_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::EOR_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::EOR_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::MOV_imm(Cond cond, bool S, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::MOV_reg(Cond cond, bool S, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::MOV_rsr(Cond cond, bool S, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::MVN_imm(Cond cond, bool S, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::MVN_reg(Cond cond, bool S, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::MVN_rsr(Cond cond, bool S, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::ORR_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::ORR_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::ORR_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::RSB_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::RSB_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::RSB_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::RSC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::RSC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::RSC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::SBC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::SBC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::SBC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::SUB_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::SUB_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::SUB_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::TEQ_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::TEQ_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::TEQ_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::TST_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) { CompileInterpretInstruction(); }
|
||||
void JitX64::TST_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
void JitX64::TST_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
15
src/core/arm/jit_x64/instructions/exception_generating.cpp
Normal file
15
src/core/arm/jit_x64/instructions/exception_generating.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::BKPT() { CompileInterpretInstruction(); }
|
||||
void JitX64::HVC() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMC() { CompileInterpretInstruction(); }
|
||||
void JitX64::SVC() { CompileInterpretInstruction(); }
|
||||
void JitX64::UDF() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
22
src/core/arm/jit_x64/instructions/extension.cpp
Normal file
22
src/core/arm/jit_x64/instructions/extension.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::SXTAB() { CompileInterpretInstruction(); }
|
||||
void JitX64::SXTAB16() { CompileInterpretInstruction(); }
|
||||
void JitX64::SXTAH() { CompileInterpretInstruction(); }
|
||||
void JitX64::SXTB() { CompileInterpretInstruction(); }
|
||||
void JitX64::SXTB16() { CompileInterpretInstruction(); }
|
||||
void JitX64::SXTH() { CompileInterpretInstruction(); }
|
||||
void JitX64::UXTAB() { CompileInterpretInstruction(); }
|
||||
void JitX64::UXTAB16() { CompileInterpretInstruction(); }
|
||||
void JitX64::UXTAH() { CompileInterpretInstruction(); }
|
||||
void JitX64::UXTB() { CompileInterpretInstruction(); }
|
||||
void JitX64::UXTB16() { CompileInterpretInstruction(); }
|
||||
void JitX64::UXTH() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
13
src/core/arm/jit_x64/instructions/hint.cpp
Normal file
13
src/core/arm/jit_x64/instructions/hint.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::DBG() { CompileInterpretInstruction(); }
|
||||
void JitX64::PLD() { CompileInterpretInstruction(); }
|
||||
void JitX64::PLI() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
43
src/core/arm/jit_x64/instructions/load_store.cpp
Normal file
43
src/core/arm/jit_x64/instructions/load_store.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
// Load/Store instructions
|
||||
void JitX64::LDR_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDR_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRB_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRB_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRBT() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRD_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRD_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRH_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRH_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRHT() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRSB_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRSB_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRSBT() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRSH_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRSH_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRSHT() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDRT() { CompileInterpretInstruction(); }
|
||||
void JitX64::STR_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::STR_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRB_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRB_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRBT() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRD_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRD_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRH_imm() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRH_reg() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRHT() { CompileInterpretInstruction(); }
|
||||
void JitX64::STRT() { CompileInterpretInstruction(); }
|
||||
|
||||
// Load/Store multiple instructions
|
||||
void JitX64::LDM() { CompileInterpretInstruction(); }
|
||||
void JitX64::STM() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
14
src/core/arm/jit_x64/instructions/misc.cpp
Normal file
14
src/core/arm/jit_x64/instructions/misc.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::CLZ() { CompileInterpretInstruction(); }
|
||||
void JitX64::ERET() { CompileInterpretInstruction(); }
|
||||
void JitX64::NOP() { CompileInterpretInstruction(); }
|
||||
void JitX64::SEL() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
43
src/core/arm/jit_x64/instructions/multiply.cpp
Normal file
43
src/core/arm/jit_x64/instructions/multiply.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
// Multiply (Normal) instructions
|
||||
void JitX64::MLA() { CompileInterpretInstruction(); }
|
||||
void JitX64::MLS() { CompileInterpretInstruction(); }
|
||||
void JitX64::MUL() { CompileInterpretInstruction(); }
|
||||
|
||||
// Multiply (Long) instructions
|
||||
void JitX64::SMLAL() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMULL() { CompileInterpretInstruction(); }
|
||||
void JitX64::UMAAL() { CompileInterpretInstruction(); }
|
||||
void JitX64::UMLAL() { CompileInterpretInstruction(); }
|
||||
void JitX64::UMULL() { CompileInterpretInstruction(); }
|
||||
|
||||
// Multiply (Halfword) instructions
|
||||
void JitX64::SMLALxy() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMLAxy() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMULxy() { CompileInterpretInstruction(); }
|
||||
|
||||
// Multiply (word by halfword) instructions
|
||||
void JitX64::SMLAWy() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMULWy() { CompileInterpretInstruction(); }
|
||||
|
||||
// Multiply (Most significant word) instructions
|
||||
void JitX64::SMMLA() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMMLS() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMMUL() { CompileInterpretInstruction(); }
|
||||
|
||||
// Multiply (Dual) instructions
|
||||
void JitX64::SMLAD() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMLALD() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMLSD() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMLSLD() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMUAD() { CompileInterpretInstruction(); }
|
||||
void JitX64::SMUSD() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
11
src/core/arm/jit_x64/instructions/packing.cpp
Normal file
11
src/core/arm/jit_x64/instructions/packing.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::PKH() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::SHADD8() { CompileInterpretInstruction(); }
|
||||
void JitX64::SHADD16() { CompileInterpretInstruction(); }
|
||||
void JitX64::SHASX() { CompileInterpretInstruction(); }
|
||||
void JitX64::SHSAX() { CompileInterpretInstruction(); }
|
||||
void JitX64::SHSUB8() { CompileInterpretInstruction(); }
|
||||
void JitX64::SHSUB16() { CompileInterpretInstruction(); }
|
||||
void JitX64::UHADD8() { CompileInterpretInstruction(); }
|
||||
void JitX64::UHADD16() { CompileInterpretInstruction(); }
|
||||
void JitX64::UHASX() { CompileInterpretInstruction(); }
|
||||
void JitX64::UHSAX() { CompileInterpretInstruction(); }
|
||||
void JitX64::UHSUB8() { CompileInterpretInstruction(); }
|
||||
void JitX64::UHSUB16() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::SADD8() { CompileInterpretInstruction(); }
|
||||
void JitX64::SADD16() { CompileInterpretInstruction(); }
|
||||
void JitX64::SASX() { CompileInterpretInstruction(); }
|
||||
void JitX64::SSAX() { CompileInterpretInstruction(); }
|
||||
void JitX64::SSUB8() { CompileInterpretInstruction(); }
|
||||
void JitX64::SSUB16() { CompileInterpretInstruction(); }
|
||||
void JitX64::UADD8() { CompileInterpretInstruction(); }
|
||||
void JitX64::UADD16() { CompileInterpretInstruction(); }
|
||||
void JitX64::UASX() { CompileInterpretInstruction(); }
|
||||
void JitX64::USAX() { CompileInterpretInstruction(); }
|
||||
void JitX64::USUB8() { CompileInterpretInstruction(); }
|
||||
void JitX64::USUB16() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::QADD8() { CompileInterpretInstruction(); }
|
||||
void JitX64::QADD16() { CompileInterpretInstruction(); }
|
||||
void JitX64::QASX() { CompileInterpretInstruction(); }
|
||||
void JitX64::QSAX() { CompileInterpretInstruction(); }
|
||||
void JitX64::QSUB8() { CompileInterpretInstruction(); }
|
||||
void JitX64::QSUB16() { CompileInterpretInstruction(); }
|
||||
void JitX64::UQADD8() { CompileInterpretInstruction(); }
|
||||
void JitX64::UQADD16() { CompileInterpretInstruction(); }
|
||||
void JitX64::UQASX() { CompileInterpretInstruction(); }
|
||||
void JitX64::UQSAX() { CompileInterpretInstruction(); }
|
||||
void JitX64::UQSUB8() { CompileInterpretInstruction(); }
|
||||
void JitX64::UQSUB16() { CompileInterpretInstruction(); }
|
||||
|
||||
|
||||
}
|
14
src/core/arm/jit_x64/instructions/qadd_qsub.cpp
Normal file
14
src/core/arm/jit_x64/instructions/qadd_qsub.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::QADD() { CompileInterpretInstruction(); }
|
||||
void JitX64::QSUB() { CompileInterpretInstruction(); }
|
||||
void JitX64::QDADD() { CompileInterpretInstruction(); }
|
||||
void JitX64::QDSUB() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
14
src/core/arm/jit_x64/instructions/reversal.cpp
Normal file
14
src/core/arm/jit_x64/instructions/reversal.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::RBIT() { CompileInterpretInstruction(); }
|
||||
void JitX64::REV() { CompileInterpretInstruction(); }
|
||||
void JitX64::REV16() { CompileInterpretInstruction(); }
|
||||
void JitX64::REVSH() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
14
src/core/arm/jit_x64/instructions/saturation.cpp
Normal file
14
src/core/arm/jit_x64/instructions/saturation.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::SSAT() { CompileInterpretInstruction(); }
|
||||
void JitX64::SSAT16() { CompileInterpretInstruction(); }
|
||||
void JitX64::USAT() { CompileInterpretInstruction(); }
|
||||
void JitX64::USAT16() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
16
src/core/arm/jit_x64/instructions/status_register.cpp
Normal file
16
src/core/arm/jit_x64/instructions/status_register.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::CPS() { CompileInterpretInstruction(); }
|
||||
void JitX64::MRS() { CompileInterpretInstruction(); }
|
||||
void JitX64::MSR() { CompileInterpretInstruction(); }
|
||||
void JitX64::RFE() { CompileInterpretInstruction(); }
|
||||
void JitX64::SETEND() { CompileInterpretInstruction(); }
|
||||
void JitX64::SRS() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
20
src/core/arm/jit_x64/instructions/synchronisation.cpp
Normal file
20
src/core/arm/jit_x64/instructions/synchronisation.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::CLREX() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDREX() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDREXB() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDREXD() { CompileInterpretInstruction(); }
|
||||
void JitX64::LDREXH() { CompileInterpretInstruction(); }
|
||||
void JitX64::STREX() { CompileInterpretInstruction(); }
|
||||
void JitX64::STREXB() { CompileInterpretInstruction(); }
|
||||
void JitX64::STREXD() { CompileInterpretInstruction(); }
|
||||
void JitX64::STREXH() { CompileInterpretInstruction(); }
|
||||
void JitX64::SWP() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
12
src/core/arm/jit_x64/instructions/thumb.cpp
Normal file
12
src/core/arm/jit_x64/instructions/thumb.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::thumb_BLX_prefix(ArmImm11 imm11) { CompileInterpretInstruction(); }
|
||||
void JitX64::thumb_BLX_suffix(bool L, ArmImm11 imm11) { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
12
src/core/arm/jit_x64/instructions/usad.cpp
Normal file
12
src/core/arm/jit_x64/instructions/usad.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
void JitX64::USAD8() { CompileInterpretInstruction(); }
|
||||
void JitX64::USADA8() { CompileInterpretInstruction(); }
|
||||
|
||||
}
|
73
src/core/arm/jit_x64/interpret.cpp
Normal file
73
src/core/arm/jit_x64/interpret.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/x64/abi.h"
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
|
||||
extern unsigned InterpreterMainLoop(ARMul_State* cpu);
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
static JitState* CallInterpreter(JitState* jit_state, u64 pc, u64 TFlag, u64 EFlag) {
|
||||
ARMul_State* cpu = &jit_state->cpu_state;
|
||||
|
||||
cpu->Reg[15] = pc;
|
||||
|
||||
cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) |
|
||||
(cpu->NFlag << 31) |
|
||||
(cpu->ZFlag << 30) |
|
||||
(cpu->CFlag << 29) |
|
||||
(cpu->VFlag << 28) |
|
||||
(cpu->TFlag << 5);
|
||||
|
||||
if (jit_state->cycles_remaining > 0) {
|
||||
#if 0
|
||||
cpu->NumInstrsToExecute = jit_state->cycles_remaining;
|
||||
if (cpu->NumInstrsToExecute > 100) cpu->NumInstrsToExecute = 100;
|
||||
jit_state->cycles_remaining -= InterpreterMainLoop(cpu);
|
||||
#else
|
||||
cpu->NumInstrsToExecute = 1;
|
||||
jit_state->cycles_remaining -= InterpreterMainLoop(cpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
return jit_state;
|
||||
}
|
||||
|
||||
void JitX64::CompileInterpretInstruction() {
|
||||
cond_manager.Always();
|
||||
reg_alloc.FlushEverything();
|
||||
|
||||
CompileUpdateCycles();
|
||||
|
||||
ASSERT(reg_alloc.JitStateReg() != RSP);
|
||||
code->MOV(64, R(RSP), MJitStateHostReturnRSP());
|
||||
code->MOV(64, R(Gen::ABI_PARAM1), R(reg_alloc.JitStateReg()));
|
||||
code->MOV(64, R(Gen::ABI_PARAM2), Imm64(current.arm_pc));
|
||||
code->MOV(64, R(Gen::ABI_PARAM3), Imm64(current.TFlag));
|
||||
code->MOV(64, R(Gen::ABI_PARAM4), Imm64(current.EFlag));
|
||||
|
||||
const void *const fn = &CallInterpreter;
|
||||
|
||||
const u64 distance = reinterpret_cast<u64>(fn) - (reinterpret_cast<u64>(code->GetCodePtr()) + 5);
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) {
|
||||
// Far call
|
||||
code->MOV(64, R(RAX), ImmPtr(fn));
|
||||
code->CALLptr(R(RAX));
|
||||
} else {
|
||||
code->CALL(fn);
|
||||
}
|
||||
|
||||
code->MOV(64, R(reg_alloc.JitStateReg()), R(Gen::ABI_RETURN));
|
||||
|
||||
// Return to dispatch
|
||||
code->JMPptr(MJitStateHostReturnRIP());
|
||||
|
||||
stop_compilation = true;
|
||||
}
|
||||
|
||||
}
|
174
src/core/arm/jit_x64/jit_x64.cpp
Normal file
174
src/core/arm/jit_x64/jit_x64.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/arm/jit_x64/jit_x64.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
JitX64::JitX64(XEmitter* code_) : code(code_) {}
|
||||
|
||||
CodePtr JitX64::GetBB(u32 pc, bool TFlag, bool EFlag) {
|
||||
const LocationDescriptor desc = { pc, TFlag, EFlag };
|
||||
|
||||
if (basic_blocks.find(desc) == basic_blocks.end()) {
|
||||
return Compile(pc, TFlag, EFlag);
|
||||
}
|
||||
|
||||
return basic_blocks[desc];
|
||||
}
|
||||
|
||||
CodePtr JitX64::Compile(u32 pc, bool TFlag, bool EFlag) {
|
||||
const CodePtr bb = code->GetWritableCodePtr();
|
||||
const LocationDescriptor desc = { pc, TFlag, EFlag };
|
||||
ASSERT(basic_blocks.find(desc) == basic_blocks.end());
|
||||
basic_blocks[desc] = bb;
|
||||
Patch(desc, bb);
|
||||
|
||||
reg_alloc.Init(code);
|
||||
cond_manager.Init(this);
|
||||
current = desc;
|
||||
instructions_compiled = 0;
|
||||
stop_compilation = false;
|
||||
|
||||
do {
|
||||
instructions_compiled++;
|
||||
|
||||
if (current.TFlag) {
|
||||
CompileSingleThumbInstruction();
|
||||
} else {
|
||||
CompileSingleArmInstruction();
|
||||
}
|
||||
} while (!stop_compilation && ((current.arm_pc & 0xFFF) != 0));
|
||||
|
||||
if (!stop_compilation) {
|
||||
// We're stopping compilation because we've reached a page boundary.
|
||||
cond_manager.Always();
|
||||
CompileUpdateCycles();
|
||||
CompileJumpToBB(current.arm_pc);
|
||||
}
|
||||
|
||||
// Insert easily searchable byte sequence for ease of lookup in memory dumps.
|
||||
code->NOP();
|
||||
code->INT3();
|
||||
code->NOP();
|
||||
|
||||
return bb;
|
||||
}
|
||||
|
||||
void JitX64::CompileUpdateCycles() {
|
||||
// We're just taking one instruction == one cycle.
|
||||
if (instructions_compiled) {
|
||||
code->SUB(32, MJitStateCycleCount(), Imm32(instructions_compiled));
|
||||
}
|
||||
instructions_compiled = 0;
|
||||
}
|
||||
|
||||
void JitX64::CompileJumpToBB(u32 new_pc) {
|
||||
ASSERT(instructions_compiled == 0);
|
||||
|
||||
reg_alloc.FlushEverything();
|
||||
code->CMP(32, MJitStateCycleCount(), Imm8(0));
|
||||
|
||||
const LocationDescriptor new_desc = { new_pc, current.TFlag, current.EFlag };
|
||||
patch_jmp_locations[new_desc].emplace_back(code->GetWritableCodePtr());
|
||||
if (basic_blocks.find(new_desc) == basic_blocks.end()) {
|
||||
code->NOP(6); // Leave enough space for a jg instruction.
|
||||
} else {
|
||||
code->J_CC(CC_G, basic_blocks[new_desc], true);
|
||||
}
|
||||
|
||||
code->MOV(32, MJitStateArmPC(), Imm32(new_pc));
|
||||
code->JMPptr(MJitStateHostReturnRIP());
|
||||
}
|
||||
|
||||
void JitX64::Patch(LocationDescriptor desc, CodePtr bb) {
|
||||
const CodePtr save_code_ptr = code->GetWritableCodePtr();
|
||||
|
||||
for (CodePtr location : patch_jmp_locations[desc]) {
|
||||
code->SetCodePtr(location);
|
||||
code->J_CC(CC_G, bb, true);
|
||||
ASSERT(code->GetCodePtr() - location == 6);
|
||||
}
|
||||
|
||||
code->SetCodePtr(save_code_ptr);
|
||||
}
|
||||
|
||||
void JitX64::CompileSingleArmInstruction() {
|
||||
u32 inst = Memory::Read32(current.arm_pc & 0xFFFFFFFC);
|
||||
|
||||
ArmDecoder::DecodeArm(inst).Visit(this, inst);
|
||||
}
|
||||
|
||||
void JitX64::CompileSingleThumbInstruction() {
|
||||
u32 inst_u32 = Memory::Read32(current.arm_pc & 0xFFFFFFFC);
|
||||
if ((current.arm_pc & 0x3) != 0) {
|
||||
inst_u32 >>= 16;
|
||||
}
|
||||
inst_u32 &= 0xFFFFF;
|
||||
u16 inst = inst_u32;
|
||||
|
||||
ArmDecoder::DecodeThumb(inst).Visit(this, inst);
|
||||
}
|
||||
|
||||
// Convenience functions:
|
||||
// We static_assert types because anything that calls these functions makes those assumptions.
|
||||
// If the types of the variables are changed please update all code that calls these functions.
|
||||
|
||||
Gen::OpArg JitX64::MJitStateCycleCount() {
|
||||
static_assert(std::is_same<decltype(JitState::cycles_remaining), s32>::value, "JitState::cycles_remaining must be s32");
|
||||
|
||||
return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, cycles_remaining));
|
||||
}
|
||||
|
||||
Gen::OpArg JitX64::MJitStateArmPC() {
|
||||
static_assert(std::is_same<decltype(JitState::cpu_state), ARMul_State>::value, "JitState::cpu_state must be ARMul_State");
|
||||
static_assert(std::is_same<decltype(ARMul_State::Reg), std::array<u32, 16>>::value, "ARMul_State::Reg must be std::array<u32, 16>");
|
||||
|
||||
return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, cpu_state) + offsetof(ARMul_State, Reg) + 15 * sizeof(u32));
|
||||
}
|
||||
|
||||
Gen::OpArg JitX64::MJitStateHostReturnRIP() {
|
||||
static_assert(std::is_same<decltype(JitState::return_RIP), u64>::value, "JitState::return_RIP must be u64");
|
||||
|
||||
return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, return_RIP));
|
||||
}
|
||||
|
||||
Gen::OpArg JitX64::MJitStateHostReturnRSP() {
|
||||
static_assert(std::is_same<decltype(JitState::save_host_RSP), u64>::value, "JitState::save_host_RSP must be u64");
|
||||
|
||||
return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, save_host_RSP));
|
||||
}
|
||||
|
||||
Gen::OpArg JitX64::MJitStateZFlag() {
|
||||
static_assert(std::is_same<decltype(JitState::cpu_state), ARMul_State>::value, "JitState::cpu_state must be ARMul_State");
|
||||
static_assert(std::is_same<decltype(ARMul_State::ZFlag), u32>::value, "ZFlag must be u32");
|
||||
|
||||
return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, cpu_state) + offsetof(ARMul_State, ZFlag));
|
||||
}
|
||||
|
||||
Gen::OpArg JitX64::MJitStateCFlag() {
|
||||
static_assert(std::is_same<decltype(JitState::cpu_state), ARMul_State>::value, "JitState::cpu_state must be ARMul_State");
|
||||
static_assert(std::is_same<decltype(ARMul_State::CFlag), u32>::value, "CFlag must be u32");
|
||||
|
||||
return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, cpu_state) + offsetof(ARMul_State, CFlag));
|
||||
}
|
||||
|
||||
Gen::OpArg JitX64::MJitStateNFlag() {
|
||||
static_assert(std::is_same<decltype(JitState::cpu_state), ARMul_State>::value, "JitState::cpu_state must be ARMul_State");
|
||||
static_assert(std::is_same<decltype(ARMul_State::NFlag), u32>::value, "NFlag must be u32");
|
||||
|
||||
return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, cpu_state) + offsetof(ARMul_State, NFlag));
|
||||
}
|
||||
|
||||
Gen::OpArg JitX64::MJitStateVFlag() {
|
||||
static_assert(std::is_same<decltype(JitState::cpu_state), ARMul_State>::value, "JitState::cpu_state must be ARMul_State");
|
||||
static_assert(std::is_same<decltype(ARMul_State::VFlag), u32>::value, "VFlag must be u32");
|
||||
|
||||
return Gen::MDisp(reg_alloc.JitStateReg(), offsetof(JitState, cpu_state) + offsetof(ARMul_State, VFlag));
|
||||
}
|
||||
|
||||
}
|
368
src/core/arm/jit_x64/jit_x64.h
Normal file
368
src/core/arm/jit_x64/jit_x64.h
Normal file
@ -0,0 +1,368 @@
|
||||
// Copyright 2016 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/x64/emitter.h"
|
||||
|
||||
#include "core/arm/decoder/decoder.h"
|
||||
#include "core/arm/jit_x64/common.h"
|
||||
#include "core/arm/jit_x64/reg_alloc.h"
|
||||
|
||||
namespace JitX64 {
|
||||
|
||||
using CodePtr = u8*;
|
||||
|
||||
struct LocationDescriptor {
|
||||
u32 arm_pc;
|
||||
bool TFlag; ///< Thumb / ARM
|
||||
bool EFlag; ///< Big / Little Endian
|
||||
|
||||
bool operator == (const LocationDescriptor& o) const {
|
||||
return std::tie(arm_pc, TFlag, EFlag) == std::tie(o.arm_pc, o.TFlag, o.EFlag);
|
||||
}
|
||||
};
|
||||
|
||||
struct LocationDescriptorHash {
|
||||
size_t operator()(const LocationDescriptor& x) const {
|
||||
return std::hash<u64>()((u64)x.arm_pc ^ ((u64)x.TFlag << 32) ^ ((u64)x.EFlag << 33));
|
||||
}
|
||||
};
|
||||
|
||||
class JitX64 final : private ArmDecoder::Visitor {
|
||||
private:
|
||||
Gen::XEmitter* code;
|
||||
|
||||
RegAlloc reg_alloc;
|
||||
|
||||
/// ARM pc -> x64 code block
|
||||
std::unordered_map<LocationDescriptor, CodePtr, LocationDescriptorHash> basic_blocks;
|
||||
|
||||
public:
|
||||
JitX64() = delete;
|
||||
JitX64(Gen::XEmitter* code_);
|
||||
virtual ~JitX64() override {}
|
||||
|
||||
CodePtr GetBB(u32 pc, bool TFlag, bool EFlag);
|
||||
|
||||
/// Returns a pointer to the compiled basic block.
|
||||
CodePtr Compile(u32 pc, bool TFlag, bool EFlag);
|
||||
|
||||
private:
|
||||
LocationDescriptor current;
|
||||
unsigned instructions_compiled;
|
||||
bool stop_compilation;
|
||||
|
||||
size_t GetInstSize() { return current.TFlag ? 2 : 4; }
|
||||
void CompileSingleArmInstruction();
|
||||
void CompileSingleThumbInstruction();
|
||||
|
||||
/// Updates the cycle count in JitState and sets instructions_compiled to zero.
|
||||
void CompileUpdateCycles();
|
||||
|
||||
/// If a basic_block starting at ARM pc is compiled -> these locations need to be patched
|
||||
std::unordered_map<LocationDescriptor, std::vector<CodePtr>, LocationDescriptorHash> patch_jmp_locations;
|
||||
/// Update JitState cycle count before calling this function. This function may instead update JitState PC and return to dispatcher.
|
||||
void CompileJumpToBB(u32 arm_pc);
|
||||
/// Patch missing jumps (fill in after CompileJumpToBB).
|
||||
void Patch(LocationDescriptor desc, CodePtr bb);
|
||||
|
||||
private:
|
||||
/// Convenience functions
|
||||
Gen::OpArg MJitStateCycleCount();
|
||||
Gen::OpArg MJitStateArmPC();
|
||||
Gen::OpArg MJitStateHostReturnRIP();
|
||||
Gen::OpArg MJitStateHostReturnRSP();
|
||||
Gen::OpArg MJitStateZFlag();
|
||||
Gen::OpArg MJitStateCFlag();
|
||||
Gen::OpArg MJitStateNFlag();
|
||||
Gen::OpArg MJitStateVFlag();
|
||||
|
||||
private:
|
||||
struct CondManager {
|
||||
private:
|
||||
JitX64* jit;
|
||||
ConditionCode current_cond;
|
||||
bool flags_dirty;
|
||||
Gen::FixupBranch current_cond_fixup;
|
||||
public:
|
||||
void Init(JitX64* jit_);
|
||||
void CompileCond(ConditionCode cond);
|
||||
void Always();
|
||||
void FlagsDirty();
|
||||
ConditionCode CurrentCond();
|
||||
} cond_manager;
|
||||
|
||||
private:
|
||||
void CompileInterpretInstruction();
|
||||
|
||||
// Barrier instructions
|
||||
virtual void DMB() override;
|
||||
virtual void DSB() override;
|
||||
virtual void ISB() override;
|
||||
|
||||
// Branch instructions
|
||||
virtual void B(Cond cond, ArmImm24 imm24) override;
|
||||
virtual void BL(Cond cond, ArmImm24 imm24) override;
|
||||
virtual void BLX_imm(bool H, ArmImm24 imm24) override;
|
||||
virtual void BLX_reg(Cond cond, ArmReg Rm) override;
|
||||
virtual void BX(Cond cond, ArmReg Rm) override;
|
||||
virtual void BXJ(Cond cond, ArmReg Rm) override;
|
||||
|
||||
// Coprocessor instructions
|
||||
virtual void CDP() override;
|
||||
virtual void LDC() override;
|
||||
virtual void MCR() override;
|
||||
virtual void MCRR() override;
|
||||
virtual void MRC() override;
|
||||
virtual void MRRC() override;
|
||||
virtual void STC() override;
|
||||
|
||||
// Data processing instructions
|
||||
virtual void ADC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void ADC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void ADC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void ADD_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void ADD_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void ADD_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void AND_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void AND_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void AND_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void BIC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void BIC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void BIC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void CMN_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) override;
|
||||
virtual void CMN_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void CMN_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void CMP_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) override;
|
||||
virtual void CMP_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void CMP_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void EOR_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void EOR_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void EOR_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void MOV_imm(Cond cond, bool S, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void MOV_reg(Cond cond, bool S, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void MOV_rsr(Cond cond, bool S, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void MVN_imm(Cond cond, bool S, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void MVN_reg(Cond cond, bool S, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void MVN_rsr(Cond cond, bool S, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void ORR_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void ORR_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void ORR_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void RSB_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void RSB_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void RSB_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void RSC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void RSC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void RSC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void SBC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void SBC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void SBC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void SUB_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
virtual void SUB_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void SUB_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void TEQ_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) override;
|
||||
virtual void TEQ_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void TEQ_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void TST_imm(Cond cond, ArmReg Rn, int rotate, ArmImm8 imm8) override;
|
||||
virtual void TST_reg(Cond cond, ArmReg Rn, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
virtual void TST_rsr(Cond cond, ArmReg Rn, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
|
||||
// Exception generation instructions
|
||||
virtual void BKPT() override;
|
||||
virtual void HVC() override;
|
||||
virtual void SMC() override;
|
||||
virtual void SVC() override;
|
||||
virtual void UDF() override;
|
||||
|
||||
// Extension functions
|
||||
virtual void SXTAB() override;
|
||||
virtual void SXTAB16() override;
|
||||
virtual void SXTAH() override;
|
||||
virtual void SXTB() override;
|
||||
virtual void SXTB16() override;
|
||||
virtual void SXTH() override;
|
||||
virtual void UXTAB() override;
|
||||
virtual void UXTAB16() override;
|
||||
virtual void UXTAH() override;
|
||||
virtual void UXTB() override;
|
||||
virtual void UXTB16() override;
|
||||
virtual void UXTH() override;
|
||||
|
||||
// Hint instructions
|
||||
virtual void DBG() override;
|
||||
virtual void PLD() override;
|
||||
virtual void PLI() override;
|
||||
|
||||
// Load/Store instructions
|
||||
virtual void LDR_imm() override;
|
||||
virtual void LDR_reg() override;
|
||||
virtual void LDRB_imm() override;
|
||||
virtual void LDRB_reg() override;
|
||||
virtual void LDRBT() override;
|
||||
virtual void LDRD_imm() override;
|
||||
virtual void LDRD_reg() override;
|
||||
virtual void LDRH_imm() override;
|
||||
virtual void LDRH_reg() override;
|
||||
virtual void LDRHT() override;
|
||||
virtual void LDRSB_imm() override;
|
||||
virtual void LDRSB_reg() override;
|
||||
virtual void LDRSBT() override;
|
||||
virtual void LDRSH_imm() override;
|
||||
virtual void LDRSH_reg() override;
|
||||
virtual void LDRSHT() override;
|
||||
virtual void LDRT() override;
|
||||
virtual void STR_imm() override;
|
||||
virtual void STR_reg() override;
|
||||
virtual void STRB_imm() override;
|
||||
virtual void STRB_reg() override;
|
||||
virtual void STRBT() override;
|
||||
virtual void STRD_imm() override;
|
||||
virtual void STRD_reg() override;
|
||||
virtual void STRH_imm() override;
|
||||
virtual void STRH_reg() override;
|
||||
virtual void STRHT() override;
|
||||
virtual void STRT() override;
|
||||
|
||||
// Load/Store multiple instructions
|
||||
virtual void LDM() override;
|
||||
virtual void STM() override;
|
||||
|
||||
// Miscellaneous instructions
|
||||
virtual void CLZ() override;
|
||||
virtual void ERET() override;
|
||||
virtual void NOP() override;
|
||||
virtual void SEL() override;
|
||||
|
||||
// Unsigned sum of absolute difference functions
|
||||
virtual void USAD8() override;
|
||||
virtual void USADA8() override;
|
||||
|
||||
// Packing instructions
|
||||
virtual void PKH() override;
|
||||
|
||||
// Reversal instructions
|
||||
virtual void RBIT() override;
|
||||
virtual void REV() override;
|
||||
virtual void REV16() override;
|
||||
virtual void REVSH() override;
|
||||
|
||||
// Saturation instructions
|
||||
virtual void SSAT() override;
|
||||
virtual void SSAT16() override;
|
||||
virtual void USAT() override;
|
||||
virtual void USAT16() override;
|
||||
|
||||
// Multiply (Normal) instructions
|
||||
virtual void MLA() override;
|
||||
virtual void MLS() override;
|
||||
virtual void MUL() override;
|
||||
|
||||
// Multiply (Long) instructions
|
||||
virtual void SMLAL() override;
|
||||
virtual void SMULL() override;
|
||||
virtual void UMAAL() override;
|
||||
virtual void UMLAL() override;
|
||||
virtual void UMULL() override;
|
||||
|
||||
// Multiply (Halfword) instructions
|
||||
virtual void SMLALxy() override;
|
||||
virtual void SMLAxy() override;
|
||||
virtual void SMULxy() override;
|
||||
|
||||
// Multiply (word by halfword) instructions
|
||||
virtual void SMLAWy() override;
|
||||
virtual void SMULWy() override;
|
||||
|
||||
// Multiply (Most significant word) instructions
|
||||
virtual void SMMLA() override;
|
||||
virtual void SMMLS() override;
|
||||
virtual void SMMUL() override;
|
||||
|
||||
// Multiply (Dual) instructions
|
||||
virtual void SMLAD() override;
|
||||
virtual void SMLALD() override;
|
||||
virtual void SMLSD() override;
|
||||
virtual void SMLSLD() override;
|
||||
virtual void SMUAD() override;
|
||||
virtual void SMUSD() override;
|
||||
|
||||
// Parallel Add/Subtract (Modulo arithmetic) instructions
|
||||
virtual void SADD8() override;
|
||||
virtual void SADD16() override;
|
||||
virtual void SASX() override;
|
||||
virtual void SSAX() override;
|
||||
virtual void SSUB8() override;
|
||||
virtual void SSUB16() override;
|
||||
virtual void UADD8() override;
|
||||
virtual void UADD16() override;
|
||||
virtual void UASX() override;
|
||||
virtual void USAX() override;
|
||||
virtual void USUB8() override;
|
||||
virtual void USUB16() override;
|
||||
|
||||
// Parallel Add/Subtract (Saturating) instructions
|
||||
virtual void QADD8() override;
|
||||
virtual void QADD16() override;
|
||||
virtual void QASX() override;
|
||||
virtual void QSAX() override;
|
||||
virtual void QSUB8() override;
|
||||
virtual void QSUB16() override;
|
||||
virtual void UQADD8() override;
|
||||
virtual void UQADD16() override;
|
||||
virtual void UQASX() override;
|
||||
virtual void UQSAX() override;
|
||||
virtual void UQSUB8() override;
|
||||
virtual void UQSUB16() override;
|
||||
|
||||
// Parallel Add/Subtract (Halving) instructions
|
||||
virtual void SHADD8() override;
|
||||
virtual void SHADD16() override;
|
||||
virtual void SHASX() override;
|
||||
virtual void SHSAX() override;
|
||||
virtual void SHSUB8() override;
|
||||
virtual void SHSUB16() override;
|
||||
virtual void UHADD8() override;
|
||||
virtual void UHADD16() override;
|
||||
virtual void UHASX() override;
|
||||
virtual void UHSAX() override;
|
||||
virtual void UHSUB8() override;
|
||||
virtual void UHSUB16() override;
|
||||
|
||||
// Saturated Add/Subtract instructions
|
||||
virtual void QADD() override;
|
||||
virtual void QSUB() override;
|
||||
virtual void QDADD() override;
|
||||
virtual void QDSUB() override;
|
||||
|
||||
// Synchronization Primitive instructions
|
||||
virtual void CLREX() override;
|
||||
virtual void LDREX() override;
|
||||
virtual void LDREXB() override;
|
||||
virtual void LDREXD() override;
|
||||
virtual void LDREXH() override;
|
||||
virtual void STREX() override;
|
||||
virtual void STREXB() override;
|
||||
virtual void STREXD() override;
|
||||
virtual void STREXH() override;
|
||||
virtual void SWP() override;
|
||||
|
||||
// Status register access instructions
|
||||
virtual void CPS() override;
|
||||
virtual void MRS() override;
|
||||
virtual void MSR() override;
|
||||
virtual void RFE() override;
|
||||
virtual void SETEND() override;
|
||||
virtual void SRS() override;
|
||||
|
||||
// Thumb specific instructions
|
||||
virtual void thumb_BLX_prefix(ArmImm11 imm11) override;
|
||||
virtual void thumb_BLX_suffix(bool L, ArmImm11 imm11) override;
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user