aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMerry <[email protected]>2022-11-19 21:42:13 +0000
committerMerry <[email protected]>2022-11-19 21:42:13 +0000
commit93b18ee8e2f6fa2d26b3ac8eaeffef9842b73735 (patch)
tree65e9d61ff778127222f185e0dcd2fa23c341aca4
parent07c614f91b0af5335e1f9c0653c2d75e7b5f53bd (diff)
downloaddynarmic-93b18ee8e2f6fa2d26b3ac8eaeffef9842b73735.tar.gz
dynarmic-93b18ee8e2f6fa2d26b3ac8eaeffef9842b73735.zip
A32: Allow for user-adjustable per-instruction tick counts
-rw-r--r--src/dynarmic/frontend/A32/translate/translate_arm.cpp18
-rw-r--r--src/dynarmic/frontend/A32/translate/translate_callbacks.h3
-rw-r--r--src/dynarmic/frontend/A32/translate/translate_thumb.cpp12
-rw-r--r--src/dynarmic/interface/A32/config.h2
4 files changed, 28 insertions, 7 deletions
diff --git a/src/dynarmic/frontend/A32/translate/translate_arm.cpp b/src/dynarmic/frontend/A32/translate/translate_arm.cpp
index 8db6cab9..3ee908fc 100644
--- a/src/dynarmic/frontend/A32/translate/translate_arm.cpp
+++ b/src/dynarmic/frontend/A32/translate/translate_arm.cpp
@@ -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);
diff --git a/src/dynarmic/frontend/A32/translate/translate_callbacks.h b/src/dynarmic/frontend/A32/translate/translate_callbacks.h
index a9d8e043..aab01853 100644
--- a/src/dynarmic/frontend/A32/translate/translate_callbacks.h
+++ b/src/dynarmic/frontend/A32/translate/translate_callbacks.h
@@ -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
diff --git a/src/dynarmic/frontend/A32/translate/translate_thumb.cpp b/src/dynarmic/frontend/A32/translate/translate_thumb.cpp
index a3cc4e8f..845a0679 100644
--- a/src/dynarmic/frontend/A32/translate/translate_thumb.cpp
+++ b/src/dynarmic/frontend/A32/translate/translate_thumb.cpp
@@ -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);
diff --git a/src/dynarmic/interface/A32/config.h b/src/dynarmic/interface/A32/config.h
index 32798edc..33f6e194 100644
--- a/src/dynarmic/interface/A32/config.h
+++ b/src/dynarmic/interface/A32/config.h
@@ -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 {