A32: Allow for user-adjustable per-instruction tick counts
This commit is contained in:
parent
07c614f91b
commit
93b18ee8e2
4 changed files with 28 additions and 7 deletions
|
@ -28,10 +28,13 @@ IR::Block TranslateArm(LocationDescriptor descriptor, TranslateCallbacks* tcb, c
|
|||
bool should_continue = true;
|
||||
do {
|
||||
const u32 arm_pc = visitor.ir.current_location.PC();
|
||||
visitor.current_instruction_size = 4;
|
||||
u64 ticks_for_instruction = 1;
|
||||
|
||||
if (const auto arm_instruction = tcb->MemoryReadCode(arm_pc)) {
|
||||
visitor.current_instruction_size = 4;
|
||||
|
||||
tcb->PreCodeTranslationHook(false, arm_pc, visitor.ir);
|
||||
ticks_for_instruction = tcb->GetTicksForCode(false, arm_pc, *arm_instruction);
|
||||
|
||||
if (const auto vfp_decoder = DecodeVFP<TranslatorVisitor>(*arm_instruction)) {
|
||||
should_continue = vfp_decoder->get().call(visitor, *arm_instruction);
|
||||
|
@ -43,6 +46,8 @@ IR::Block TranslateArm(LocationDescriptor descriptor, TranslateCallbacks* tcb, c
|
|||
should_continue = visitor.arm_UDF();
|
||||
}
|
||||
} else {
|
||||
visitor.current_instruction_size = 4;
|
||||
|
||||
should_continue = visitor.RaiseException(Exception::NoExecuteFault);
|
||||
}
|
||||
|
||||
|
@ -51,7 +56,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, TranslateCallbacks* tcb, c
|
|||
}
|
||||
|
||||
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4);
|
||||
block.CycleCount()++;
|
||||
block.CycleCount() += ticks_for_instruction;
|
||||
} while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir) && !single_step);
|
||||
|
||||
if (visitor.cond_state == ConditionalState::Translating || visitor.cond_state == ConditionalState::Trailing || single_step) {
|
||||
|
@ -74,9 +79,14 @@ IR::Block TranslateArm(LocationDescriptor descriptor, TranslateCallbacks* tcb, c
|
|||
bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 arm_instruction) {
|
||||
TranslatorVisitor visitor{block, descriptor, {}};
|
||||
|
||||
bool should_continue = true;
|
||||
|
||||
// TODO: Proper cond handling
|
||||
|
||||
bool should_continue = true;
|
||||
visitor.current_instruction_size = 4;
|
||||
|
||||
const u64 ticks_for_instruction = 1;
|
||||
|
||||
if (const auto vfp_decoder = DecodeVFP<TranslatorVisitor>(arm_instruction)) {
|
||||
should_continue = vfp_decoder->get().call(visitor, arm_instruction);
|
||||
} else if (const auto asimd_decoder = DecodeASIMD<TranslatorVisitor>(arm_instruction)) {
|
||||
|
@ -90,7 +100,7 @@ bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descript
|
|||
// TODO: Feedback resulting cond status to caller somehow.
|
||||
|
||||
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(4);
|
||||
block.CycleCount()++;
|
||||
block.CycleCount() += ticks_for_instruction;
|
||||
|
||||
block.SetEndLocation(visitor.ir.current_location);
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ struct TranslateCallbacks {
|
|||
// Thus function is called before the instruction at pc is interpreted.
|
||||
// IR code can be emitted by the callee prior to translation of the instruction.
|
||||
virtual void PreCodeTranslationHook(bool is_thumb, VAddr pc, A32::IREmitter& ir) = 0;
|
||||
|
||||
// How many ticks should this instruction take to execute?
|
||||
virtual std::uint64_t GetTicksForCode(bool is_thumb, VAddr vaddr, std::uint32_t instruction) = 0;
|
||||
};
|
||||
|
||||
} // namespace Dynarmic::A32
|
||||
|
|
|
@ -109,12 +109,15 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, TranslateCallbacks* tcb,
|
|||
bool should_continue = true;
|
||||
do {
|
||||
const u32 arm_pc = visitor.ir.current_location.PC();
|
||||
u64 ticks_for_instruction = 1;
|
||||
|
||||
if (const auto maybe_instruction = ReadThumbInstruction(arm_pc, tcb)) {
|
||||
const auto [thumb_instruction, inst_size] = *maybe_instruction;
|
||||
const bool is_thumb_16 = inst_size == ThumbInstSize::Thumb16;
|
||||
visitor.current_instruction_size = is_thumb_16 ? 2 : 4;
|
||||
|
||||
tcb->PreCodeTranslationHook(false, arm_pc, visitor.ir);
|
||||
tcb->PreCodeTranslationHook(true, arm_pc, visitor.ir);
|
||||
ticks_for_instruction = tcb->GetTicksForCode(true, arm_pc, thumb_instruction);
|
||||
|
||||
if (IsUnconditionalInstruction(is_thumb_16, thumb_instruction) || visitor.ThumbConditionPassed()) {
|
||||
if (is_thumb_16) {
|
||||
|
@ -143,6 +146,7 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, TranslateCallbacks* tcb,
|
|||
}
|
||||
} else {
|
||||
visitor.current_instruction_size = 2;
|
||||
|
||||
should_continue = visitor.RaiseException(Exception::NoExecuteFault);
|
||||
}
|
||||
|
||||
|
@ -151,7 +155,7 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, TranslateCallbacks* tcb,
|
|||
}
|
||||
|
||||
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(static_cast<int>(visitor.current_instruction_size)).AdvanceIT();
|
||||
block.CycleCount()++;
|
||||
block.CycleCount() += ticks_for_instruction;
|
||||
} while (should_continue && CondCanContinue(visitor.cond_state, visitor.ir) && !single_step);
|
||||
|
||||
if (visitor.cond_state == ConditionalState::Translating || visitor.cond_state == ConditionalState::Trailing || single_step) {
|
||||
|
@ -179,6 +183,8 @@ bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descri
|
|||
const bool is_thumb_16 = IsThumb16(static_cast<u16>(thumb_instruction));
|
||||
visitor.current_instruction_size = is_thumb_16 ? 2 : 4;
|
||||
|
||||
const u64 ticks_for_instruction = 1;
|
||||
|
||||
if (is_thumb_16) {
|
||||
if (const auto decoder = DecodeThumb16<TranslatorVisitor>(static_cast<u16>(thumb_instruction))) {
|
||||
should_continue = decoder->get().call(visitor, static_cast<u16>(thumb_instruction));
|
||||
|
@ -206,7 +212,7 @@ bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descri
|
|||
|
||||
const s32 advance_pc = is_thumb_16 ? 2 : 4;
|
||||
visitor.ir.current_location = visitor.ir.current_location.AdvancePC(advance_pc);
|
||||
block.CycleCount()++;
|
||||
block.CycleCount() += ticks_for_instruction;
|
||||
|
||||
block.SetEndLocation(visitor.ir.current_location);
|
||||
|
||||
|
|
|
@ -109,6 +109,8 @@ struct UserCallbacks : public TranslateCallbacks {
|
|||
virtual void AddTicks(std::uint64_t ticks) = 0;
|
||||
// How many more ticks am I allowed to execute?
|
||||
virtual std::uint64_t GetTicksRemaining() = 0;
|
||||
// How many ticks should this instruction take to execute?
|
||||
std::uint64_t GetTicksForCode(bool /*is_thumb*/, VAddr /*vaddr*/, std::uint32_t /*instruction*/) override { return 1; }
|
||||
};
|
||||
|
||||
struct UserConfig {
|
||||
|
|
Loading…
Reference in a new issue