aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMerryMage <[email protected]>2016-07-14 20:02:41 +0100
committerMerryMage <[email protected]>2016-07-14 20:02:41 +0100
commit4b1c27e64fc7854778df25b49d00e879643da50c (patch)
treee60281549f55767846939aefe4eb5115374b0096
parent63242924fcf5f027d82db8b90fdc149c10a43205 (diff)
downloaddynarmic-4b1c27e64fc7854778df25b49d00e879643da50c.tar.gz
dynarmic-4b1c27e64fc7854778df25b49d00e879643da50c.zip
Implement arm_ADC_imm
-rw-r--r--src/frontend/decoder/arm.h4
-rw-r--r--src/frontend/disassembler/disassembler_arm.cpp2
-rw-r--r--src/frontend/translate/translate_arm.cpp180
-rw-r--r--src/frontend/translate/translate_thumb.cpp6
-rw-r--r--tests/arm/fuzz_arm.cpp11
5 files changed, 193 insertions, 10 deletions
diff --git a/src/frontend/decoder/arm.h b/src/frontend/decoder/arm.h
index 85e83ac0..62f8cfda 100644
--- a/src/frontend/decoder/arm.h
+++ b/src/frontend/decoder/arm.h
@@ -59,7 +59,7 @@ private:
};
template <typename V>
-static const std::array<ArmMatcher<V>, 2> g_arm_instruction_table = {
+static const std::array<ArmMatcher<V>, 3> g_arm_instruction_table = {
#define INST(fn, name, bitstring) detail::detail<ArmMatcher, u32, 32>::GetMatcher<decltype(fn), fn>(name, bitstring)
@@ -88,7 +88,7 @@ static const std::array<ArmMatcher<V>, 2> g_arm_instruction_table = {
//INST(&V::arm_STC, "STC", "----110----0--------------------"), // v2
// Data Processing instructions
- //INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv"), // all
+ INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv"), // all
//INST(&V::arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm"), // all
//INST(&V::arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm"), // all
//INST(&V::arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv"), // all
diff --git a/src/frontend/disassembler/disassembler_arm.cpp b/src/frontend/disassembler/disassembler_arm.cpp
index 1f8ce1d7..0ded3cc1 100644
--- a/src/frontend/disassembler/disassembler_arm.cpp
+++ b/src/frontend/disassembler/disassembler_arm.cpp
@@ -521,7 +521,7 @@ public:
std::string DisassembleArm(u32 instruction) {
DisassemblerVisitor visitor;
auto decoder = DecodeArm<DisassemblerVisitor>(instruction);
- return !decoder ? "UNKNOWN" : decoder->call(visitor, instruction);
+ return !decoder ? Common::StringFromFormat("UNKNOWN: %x", instruction) : decoder->call(visitor, instruction);
}
} // namespace Arm
diff --git a/src/frontend/translate/translate_arm.cpp b/src/frontend/translate/translate_arm.cpp
index 80757be9..71b9fe26 100644
--- a/src/frontend/translate/translate_arm.cpp
+++ b/src/frontend/translate/translate_arm.cpp
@@ -33,7 +33,7 @@ struct ArmTranslatorVisitor final {
IREmitter ir;
ConditionalState cond_state = ConditionalState::None;
- bool TranslateThisInstruction() {
+ bool InterpretThisInstruction() {
ir.SetTerm(IR::Term::Interpret(ir.current_location));
return false;
}
@@ -80,6 +80,182 @@ struct ArmTranslatorVisitor final {
return true;
}
+ u32 rotr(u32 x, int shift) {
+ shift &= 31;
+ if (!shift) return x;
+ return (x >> shift) | (x << (32 - shift));
+ }
+
+ u32 ArmExpandImm(int rotate, Imm8 imm8) {
+ return rotr(static_cast<u32>(imm8), rotate*2);
+ }
+
+ bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ u32 imm32 = ArmExpandImm(rotate, imm8);
+ // ADC{S}<c> <Rd>, <Rn>, #<imm>
+ if (ConditionPassed(cond)) {
+ auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.GetCFlag());
+
+ if (d == Reg::PC) {
+ ASSERT(!S);
+ ir.ALUWritePC(result.result);
+ ir.SetTerm(IR::Term::ReturnToDispatch{});
+ return false;
+ }
+
+ ir.SetRegister(d, result.result);
+ if (S) {
+ ir.SetNFlag(ir.MostSignificantBit(result.result));
+ ir.SetZFlag(ir.IsZero(result.result));
+ ir.SetCFlag(result.carry);
+ ir.SetVFlag(result.overflow);
+ }
+ }
+ return true;
+ };
+
+ bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
+ return InterpretThisInstruction();
+ }
+ bool arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+ bool arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
+ return InterpretThisInstruction();
+ }
+
bool arm_SVC(Cond cond, Imm24 imm24) {
u32 imm32 = imm24;
// SVC<c> #<imm24>
@@ -91,7 +267,7 @@ struct ArmTranslatorVisitor final {
}
bool arm_UDF() {
- return TranslateThisInstruction();
+ return InterpretThisInstruction();
}
};
diff --git a/src/frontend/translate/translate_thumb.cpp b/src/frontend/translate/translate_thumb.cpp
index 7c777244..a6a1ad2a 100644
--- a/src/frontend/translate/translate_thumb.cpp
+++ b/src/frontend/translate/translate_thumb.cpp
@@ -24,7 +24,7 @@ struct ThumbTranslatorVisitor final {
IREmitter ir;
- bool TranslateThisInstruction() {
+ bool InterpretThisInstruction() {
ir.SetTerm(IR::Term::Interpret(ir.current_location));
return false;
}
@@ -441,7 +441,7 @@ struct ThumbTranslatorVisitor final {
}
bool thumb16_UDF() {
- return TranslateThisInstruction();
+ return InterpretThisInstruction();
}
bool thumb16_SVC(Imm8 imm8) {
@@ -505,7 +505,7 @@ IR::Block TranslateThumb(LocationDescriptor descriptor, MemoryRead32FuncType mem
} else {
should_continue = visitor.thumb32_UDF();
}*/
- should_continue = visitor.TranslateThisInstruction();
+ should_continue = visitor.InterpretThisInstruction();
}
visitor.ir.current_location.arm_pc += (inst_size == ThumbInstSize::Thumb16) ? 2 : 4;
diff --git a/tests/arm/fuzz_arm.cpp b/tests/arm/fuzz_arm.cpp
index 22c30368..f21108da 100644
--- a/tests/arm/fuzz_arm.cpp
+++ b/tests/arm/fuzz_arm.cpp
@@ -88,6 +88,9 @@ static void InterpreterFallback(u32 pc, Dynarmic::Jit* jit) {
InterpreterClearCache();
InterpreterMainLoop(&interp_state);
+ bool T = Dynarmic::Common::Bit<5>(interp_state.Cpsr);
+ interp_state.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC;
+
jit->Regs() = interp_state.Reg;
jit->Cpsr() = interp_state.Cpsr;
}
@@ -159,7 +162,7 @@ static bool DoesBehaviorMatch(const ARMul_State& interp, const Dynarmic::Jit& ji
}
-void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_execute_count, const size_t run_count, const std::function<u16()> instruction_generator) {
+void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_execute_count, const size_t run_count, const std::function<u32()> instruction_generator) {
// Prepare memory
code_mem.fill(0xEAFFFFFE); // b +#0
@@ -191,6 +194,10 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe
interp.NumInstrsToExecute = instructions_to_execute_count;
InterpreterMainLoop(&interp);
auto interp_write_records = write_records;
+ {
+ bool T = Dynarmic::Common::Bit<5>(interp.Cpsr);
+ interp.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC;
+ }
// Run jit
write_records.clear();
@@ -340,7 +347,7 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
};
SECTION("short blocks") {
- FuzzJitArm(5, 6, 5000, instruction_select(/*Rd_can_be_r15=*/false));
+ FuzzJitArm(5, 6, 10000, instruction_select(/*Rd_can_be_r15=*/false));
}
SECTION("long blocks") {