diff --git a/src/core/cpu_recompiler_code_generator.h b/src/core/cpu_recompiler_code_generator.h index 123da732e..3364407b6 100644 --- a/src/core/cpu_recompiler_code_generator.h +++ b/src/core/cpu_recompiler_code_generator.h @@ -80,6 +80,8 @@ public: // Branching, generates two paths. void EmitBranch(Condition condition, Reg lr_reg, Value&& branch_target); + void EmitBranchIfBitClear(HostReg reg, RegSize size, u8 bit, LabelType* label); + void EmitBindLabel(LabelType* label); // Raising exception if condition is true. void EmitRaiseException(Exception excode, Condition condition = Condition::Always); diff --git a/src/core/cpu_recompiler_code_generator_aarch64.cpp b/src/core/cpu_recompiler_code_generator_aarch64.cpp index 2d5575fb5..0e85b0ae7 100644 --- a/src/core/cpu_recompiler_code_generator_aarch64.cpp +++ b/src/core/cpu_recompiler_code_generator_aarch64.cpp @@ -1541,6 +1541,27 @@ void CodeGenerator::EmitBranch(Condition condition, Reg lr_reg, Value&& branch_t m_register_cache.InvalidateGuestRegister(lr_reg); } +void CodeGenerator::EmitBranchIfBitClear(HostReg reg, RegSize size, u8 bit, LabelType* label) +{ + switch (size) + { + case RegSize_8: + case RegSize_16: + case RegSize_32: + m_emit->tbz(GetHostReg32(reg), bit, label); + break; + + default: + UnreachableCode(); + break; + } +} + +void CodeGenerator::EmitBindLabel(LabelType* label) +{ + m_emit->Bind(label); +} + void CodeGenerator::EmitRaiseException(Exception excode, Condition condition /* = Condition::Always */) { if (condition == Condition::Always) diff --git a/src/core/cpu_recompiler_code_generator_x64.cpp b/src/core/cpu_recompiler_code_generator_x64.cpp index b4709af8e..fb377775f 100644 --- a/src/core/cpu_recompiler_code_generator_x64.cpp +++ b/src/core/cpu_recompiler_code_generator_x64.cpp @@ -1937,6 +1937,36 @@ void CodeGenerator::EmitBranch(Condition condition, Reg lr_reg, Value&& branch_t m_register_cache.InvalidateGuestRegister(lr_reg); } +void CodeGenerator::EmitBranchIfBitClear(HostReg reg, RegSize size, u8 bit, LabelType* label) +{ + switch (size) + { + case RegSize_8: + m_emit->bt(GetHostReg8(reg), bit); + m_emit->jnc(*label); + break; + + case RegSize_16: + m_emit->bt(GetHostReg16(reg), bit); + m_emit->jnc(*label); + break; + + case RegSize_32: + m_emit->bt(GetHostReg32(reg), bit); + m_emit->jnc(*label); + break; + + default: + UnreachableCode(); + break; + } +} + +void CodeGenerator::EmitBindLabel(LabelType* label) +{ + m_emit->L(*label); +} + void CodeGenerator::EmitRaiseException(Exception excode, Condition condition /* = Condition::Always */) { if (condition == Condition::Always) diff --git a/src/core/cpu_recompiler_types.h b/src/core/cpu_recompiler_types.h index 9d5522729..e0ead1128 100644 --- a/src/core/cpu_recompiler_types.h +++ b/src/core/cpu_recompiler_types.h @@ -52,6 +52,7 @@ enum class Condition : u8 using HostReg = Xbyak::Operand::Code; using CodeEmitter = Xbyak::CodeGenerator; +using LabelType = Xbyak::Label; enum : u32 { HostReg_Count = 16 @@ -70,6 +71,7 @@ constexpr bool SHIFTS_ARE_IMPLICITLY_MASKED = true; using HostReg = unsigned; using CodeEmitter = vixl::aarch64::MacroAssembler; +using LabelType = vixl::aarch64::Label; enum : u32 { HostReg_Count = vixl::aarch64::kNumberOfRegisters