diff --git a/tests/A32/fuzz_arm.cpp b/tests/A32/fuzz_arm.cpp index dedc63d1..b6037b6a 100644 --- a/tests/A32/fuzz_arm.cpp +++ b/tests/A32/fuzz_arm.cpp @@ -31,19 +31,18 @@ #include "ir_opt/passes.h" #include "rand_int.h" #include "testenv.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h" -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" +#include "unicorn_emu/a32_unicorn.h" using Dynarmic::Common::Bits; -static Dynarmic::A32::UserConfig GetUserConfig(ArmTestEnv* testenv) { +namespace { +Dynarmic::A32::UserConfig GetUserConfig(ArmTestEnv* testenv) { Dynarmic::A32::UserConfig user_config; user_config.enable_fast_dispatch = false; user_config.callbacks = testenv; return user_config; } -namespace { struct InstructionGenerator final { public: InstructionGenerator(const char* format, std::function is_valid = [](u32){ return true; }) : is_valid(is_valid) { @@ -92,16 +91,16 @@ private: u32 mask = 0; std::function is_valid; }; -} // namespace using WriteRecords = std::map; -static bool DoesBehaviorMatch(const ARMul_State& interp, const Dynarmic::A32::Jit& jit, const WriteRecords& interp_write_records, const WriteRecords& jit_write_records) { - return interp.Reg == jit.Regs() - && interp.ExtReg == jit.ExtRegs() - && interp.Cpsr == jit.Cpsr() - //&& interp.VFP[VFP_FPSCR] == jit.Fpscr() - && interp_write_records == jit_write_records; +bool DoesBehaviorMatch(const A32Unicorn& uni, const Dynarmic::A32::Jit& jit, + const WriteRecords& interp_write_records, const WriteRecords& jit_write_records) { + return uni.GetRegisters() == jit.Regs() && + uni.GetExtRegs() == jit.ExtRegs() && + uni.GetCpsr() == jit.Cpsr() && + // uni.GetFpscr() == jit.Fpscr() && + interp_write_records == jit_write_records; } void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_execute_count, const size_t run_count, const std::function instruction_generator) { @@ -112,34 +111,32 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe test_env.code_mem.back() = 0xEAFFFFFE; // b +#0 // Prepare test subjects - ARMul_State interp{USER32MODE}; - interp.user_callbacks = &test_env; + A32Unicorn uni{test_env}; Dynarmic::A32::Jit jit{GetUserConfig(&test_env)}; for (size_t run_number = 0; run_number < run_count; run_number++) { - interp.instruction_cache.clear(); - InterpreterClearCache(); + uni.ClearPageCache(); jit.ClearCache(); // Setup initial state - u32 initial_cpsr = 0x000001D0; + const u32 initial_cpsr = 0x000001D0; ArmTestEnv::RegisterArray initial_regs; - std::generate_n(initial_regs.begin(), 15, []{ return RandInt(0, 0xFFFFFFFF); }); + std::generate_n(initial_regs.begin(), initial_regs.size() - 1, []{ return RandInt(0, 0xFFFFFFFF); }); initial_regs[15] = 0; ArmTestEnv::ExtRegsArray initial_extregs; std::generate(initial_extregs.begin(), initial_extregs.end(), []{ return RandInt(0, 0xFFFFFFFF); }); - u32 initial_fpscr = 0x01000000 | (RandInt(0, 3) << 22); + const u32 initial_fpscr = 0x01000000 | (RandInt(0, 3) << 22); - interp.UnsetExclusiveMemoryAddress(); - interp.Cpsr = initial_cpsr; - interp.Reg = initial_regs; - interp.ExtReg = initial_extregs; - interp.VFP[VFP_FPSCR] = initial_fpscr; + uni.SetCpsr(initial_cpsr); + uni.SetRegisters(initial_regs); + uni.SetExtRegs(initial_extregs); + uni.SetFpscr(initial_fpscr); + uni.EnableFloatingPointAccess(); jit.Reset(); jit.SetCpsr(initial_cpsr); jit.Regs() = initial_regs; @@ -157,35 +154,37 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe } printf("\nInitial Register Listing: \n"); - for (int i = 0; i <= 15; i++) { - auto reg = Dynarmic::A32::RegToString(static_cast(i)); + for (size_t i = 0; i < initial_regs.size(); i++) { + const auto reg = Dynarmic::A32::RegToString(static_cast(i)); printf("%4s: %08x\n", reg, initial_regs[i]); } printf("CPSR: %08x\n", initial_cpsr); printf("FPSCR:%08x\n", initial_fpscr); - for (int i = 0; i <= 63; i++) { - printf("S%3i: %08x\n", i, initial_extregs[i]); + for (size_t i = 0; i < initial_extregs.size(); i++) { + printf("S%3zu: %08x\n", i, initial_extregs[i]); } printf("\nFinal Register Listing: \n"); - printf(" interp jit\n"); - for (int i = 0; i <= 15; i++) { - auto reg = Dynarmic::A32::RegToString(static_cast(i)); - printf("%4s: %08x %08x %s\n", reg, interp.Reg[i], jit.Regs()[i], interp.Reg[i] != jit.Regs()[i] ? "*" : ""); + printf(" unicorn jit\n"); + const auto uni_registers = uni.GetRegisters(); + for (size_t i = 0; i < uni_registers.size(); i++) { + const auto reg = Dynarmic::A32::RegToString(static_cast(i)); + printf("%4s: %08x %08x %s\n", reg, uni_registers[i], jit.Regs()[i], uni_registers[i] != jit.Regs()[i] ? "*" : ""); } - printf("CPSR: %08x %08x %s\n", interp.Cpsr, jit.Cpsr(), interp.Cpsr != jit.Cpsr() ? "*" : ""); - printf("FPSCR:%08x %08x %s\n", interp.VFP[VFP_FPSCR], jit.Fpscr(), interp.VFP[VFP_FPSCR] != jit.Fpscr() ? "*" : ""); - for (int i = 0; i <= 63; i++) { - printf("S%3i: %08x %08x %s\n", i, interp.ExtReg[i], jit.ExtRegs()[i], interp.ExtReg[i] != jit.ExtRegs()[i] ? "*" : ""); + printf("CPSR: %08x %08x %s\n", uni.GetCpsr(), jit.Cpsr(), uni.GetCpsr() != jit.Cpsr() ? "*" : ""); + printf("FPSCR:%08x %08x %s\n", uni.GetFpscr(), jit.Fpscr(), uni.GetFpscr() != jit.Fpscr() ? "*" : ""); + const auto uni_ext_regs = uni.GetExtRegs(); + for (size_t i = 0; i < uni_ext_regs.size(); i++) { + printf("S%3zu: %08x %08x %s\n", i, uni_ext_regs[i], jit.ExtRegs()[i], uni_ext_regs[i] != jit.ExtRegs()[i] ? "*" : ""); } printf("\nInterp Write Records:\n"); - for (auto& record : interp_write_records) { + for (const auto& record : interp_write_records) { printf("[%08x] = %02x\n", record.first, record.second); } printf("\nJIT Write Records:\n"); - for (auto& record : jit_write_records) { + for (const auto& record : jit_write_records) { printf("[%08x] = %02x\n", record.first, record.second); } @@ -209,12 +208,14 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe // Run interpreter test_env.modified_memory.clear(); - interp.NumInstrsToExecute = static_cast(instructions_to_execute_count); - InterpreterMainLoop(&interp); + test_env.ticks_left = instructions_to_execute_count; + uni.Run(); interp_write_records = test_env.modified_memory; { - bool T = Dynarmic::Common::Bit<5>(interp.Cpsr); - interp.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC; + const bool T = Dynarmic::Common::Bit<5>(uni.GetCpsr()); + const u32 mask = T ? 0xFFFFFFFE : 0xFFFFFFFC; + const u32 new_pc = uni.GetPC() & mask; + uni.SetPC(new_pc); } // Run jit @@ -223,9 +224,10 @@ void FuzzJitArm(const size_t instruction_count, const size_t instructions_to_exe jit.Run(); jit_write_records = test_env.modified_memory; - REQUIRE(DoesBehaviorMatch(interp, jit, interp_write_records, jit_write_records)); + REQUIRE(DoesBehaviorMatch(uni, jit, interp_write_records, jit_write_records)); } } +} // Anonymous namespace TEST_CASE( "arm: Optimization Failure (Randomized test case)", "[arm][A32]" ) { // This was a randomized test-case that was failing. diff --git a/tests/A32/fuzz_thumb.cpp b/tests/A32/fuzz_thumb.cpp index af8069f2..1db7f11f 100644 --- a/tests/A32/fuzz_thumb.cpp +++ b/tests/A32/fuzz_thumb.cpp @@ -27,8 +27,7 @@ #include "ir_opt/passes.h" #include "rand_int.h" #include "testenv.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h" -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" +#include "unicorn_emu/a32_unicorn.h" static Dynarmic::A32::UserConfig GetUserConfig(ThumbTestEnv* testenv) { Dynarmic::A32::UserConfig user_config; @@ -64,7 +63,7 @@ public: u16 inst; do { - u16 random = RandInt(0, 0xFFFF); + const u16 random = RandInt(0, 0xFFFF); inst = bits | (random & ~mask); } while (!is_valid(inst)); @@ -78,46 +77,52 @@ private: std::function is_valid; }; -static bool DoesBehaviorMatch(const ARMul_State& interp, const Dynarmic::A32::Jit& jit, WriteRecords& interp_write_records, WriteRecords& jit_write_records) { - const auto interp_regs = interp.Reg; +static bool DoesBehaviorMatch(const A32Unicorn& uni, const Dynarmic::A32::Jit& jit, + const WriteRecords& interp_write_records, const WriteRecords& jit_write_records) { + const auto interp_regs = uni.GetRegisters(); const auto jit_regs = jit.Regs(); - return std::equal(interp_regs.begin(), interp_regs.end(), jit_regs.begin(), jit_regs.end()) - && interp.Cpsr == jit.Cpsr() - && interp_write_records == jit_write_records; + return std::equal(interp_regs.begin(), interp_regs.end(), jit_regs.begin(), jit_regs.end()) && + uni.GetCpsr() == jit.Cpsr() && + interp_write_records == jit_write_records; } -static void RunInstance(size_t run_number, ThumbTestEnv& test_env, ARMul_State& interp, Dynarmic::A32::Jit& jit, const ThumbTestEnv::RegisterArray& initial_regs, +static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32Unicorn& uni, Dynarmic::A32::Jit& jit, const ThumbTestEnv::RegisterArray& initial_regs, size_t instruction_count, size_t instructions_to_execute_count) { - interp.instruction_cache.clear(); - InterpreterClearCache(); + uni.ClearPageCache(); jit.ClearCache(); // Setup initial state - interp.Cpsr = 0x000001F0; - interp.Reg = initial_regs; + uni.SetCpsr(0x000001F0); + uni.SetRegisters(initial_regs); jit.SetCpsr(0x000001F0); jit.Regs() = initial_regs; // Run interpreter test_env.modified_memory.clear(); - interp.NumInstrsToExecute = static_cast(instructions_to_execute_count); - InterpreterMainLoop(&interp); - auto interp_write_records = test_env.modified_memory; - { - bool T = Dynarmic::Common::Bit<5>(interp.Cpsr); - interp.Reg[15] &= T ? 0xFFFFFFFE : 0xFFFFFFFC; - } + test_env.ticks_left = instructions_to_execute_count; + uni.SetPC(uni.GetPC() | 1); + uni.Run(); + const bool uni_code_memory_modified = test_env.code_mem_modified_by_guest; + const auto interp_write_records = test_env.modified_memory; // Run jit + test_env.code_mem_modified_by_guest = false; test_env.modified_memory.clear(); test_env.ticks_left = instructions_to_execute_count; jit.Run(); - auto jit_write_records = test_env.modified_memory; + const bool jit_code_memory_modified = test_env.code_mem_modified_by_guest; + const auto jit_write_records = test_env.modified_memory; + test_env.code_mem_modified_by_guest = false; + + REQUIRE(uni_code_memory_modified == jit_code_memory_modified); + if (uni_code_memory_modified) { + return; + } // Compare - if (!DoesBehaviorMatch(interp, jit, interp_write_records, jit_write_records)) { + if (!DoesBehaviorMatch(uni, jit, interp_write_records, jit_write_records)) { printf("Failed at execution number %zu\n", run_number); printf("\nInstruction Listing: \n"); @@ -126,24 +131,25 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, ARMul_State& } printf("\nInitial Register Listing: \n"); - for (int i = 0; i <= 15; i++) { - printf("%4i: %08x\n", i, initial_regs[i]); + for (size_t i = 0; i < initial_regs.size(); i++) { + printf("%4zu: %08x\n", i, initial_regs[i]); } printf("\nFinal Register Listing: \n"); - printf(" interp jit\n"); - for (int i = 0; i <= 15; i++) { - printf("%4i: %08x %08x %s\n", i, interp.Reg[i], jit.Regs()[i], interp.Reg[i] != jit.Regs()[i] ? "*" : ""); + printf(" unicorn jit\n"); + const auto uni_registers = uni.GetRegisters(); + for (size_t i = 0; i < uni_registers.size(); i++) { + printf("%4zu: %08x %08x %s\n", i, uni_registers[i], jit.Regs()[i], uni_registers[i] != jit.Regs()[i] ? "*" : ""); } - printf("CPSR: %08x %08x %s\n", interp.Cpsr, jit.Cpsr(), interp.Cpsr != jit.Cpsr() ? "*" : ""); + printf("CPSR: %08x %08x %s\n", uni.GetCpsr(), jit.Cpsr(), uni.GetCpsr() != jit.Cpsr() ? "*" : ""); - printf("\nInterp Write Records:\n"); - for (auto& record : interp_write_records) { + printf("\nUnicorn Write Records:\n"); + for (const auto& record : interp_write_records) { printf("[%08x] = %02x\n", record.first, record.second); } printf("\nJIT Write Records:\n"); - for (auto& record : jit_write_records) { + for (const auto& record : jit_write_records) { printf("[%08x] = %02x\n", record.first, record.second); } @@ -175,28 +181,27 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, ARMul_State& void FuzzJitThumb(const size_t instruction_count, const size_t instructions_to_execute_count, const size_t run_count, const std::function instruction_generator) { ThumbTestEnv test_env; - // Prepare memory + // Prepare memory. test_env.code_mem.resize(instruction_count + 1); test_env.code_mem.back() = 0xE7FE; // b +#0 // Prepare test subjects - ARMul_State interp{USER32MODE}; - interp.user_callbacks = &test_env; + A32Unicorn uni{test_env}; Dynarmic::A32::Jit jit{GetUserConfig(&test_env)}; for (size_t run_number = 0; run_number < run_count; run_number++) { ThumbTestEnv::RegisterArray initial_regs; - std::generate_n(initial_regs.begin(), 15, []{ return RandInt(0, 0xFFFFFFFF); }); + std::generate_n(initial_regs.begin(), initial_regs.size() - 1, []{ return RandInt(0, 0xFFFFFFFF); }); initial_regs[15] = 0; std::generate_n(test_env.code_mem.begin(), instruction_count, instruction_generator); - RunInstance(run_number, test_env, interp, jit, initial_regs, instruction_count, instructions_to_execute_count); + RunInstance(run_number, test_env, uni, jit, initial_regs, instruction_count, instructions_to_execute_count); } } TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") { - const std::array instructions = {{ + const std::array instructions = { ThumbInstGen("00000xxxxxxxxxxx"), // LSL , , # ThumbInstGen("00001xxxxxxxxxxx"), // LSR , , # ThumbInstGen("00010xxxxxxxxxxx"), // ASR , , # @@ -224,11 +229,23 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") { [](u16 inst){ return Dynarmic::Common::Bits<0, 7>(inst) != 0; }), // Empty reg_list is UNPREDICTABLE ThumbInstGen("10111100xxxxxxxx", // POP (P = 0) [](u16 inst){ return Dynarmic::Common::Bits<0, 7>(inst) != 0; }), // Empty reg_list is UNPREDICTABLE - ThumbInstGen("1100xxxxxxxxxxxx"), // STMIA/LDMIA + ThumbInstGen("1100xxxxxxxxxxxx", // STMIA/LDMIA + [](u16 inst) { + // Ensure that the architecturally undefined case of + // the base register being within the list isn't hit. + const u32 rn = Dynarmic::Common::Bits<8, 10>(inst); + return (inst & (1U << rn)) == 0; + }), + // TODO: We should properly test against swapped + // endianness cases, however Unicorn doesn't + // expose the intended endianness of a load/store + // operation to memory through its hooks. +#if 0 ThumbInstGen("101101100101x000"), // SETEND - }}; +#endif + }; - auto instruction_select = [&]() -> u16 { + const auto instruction_select = [&]() -> u16 { size_t inst_index = RandInt(0, instructions.size() - 1); return instructions[inst_index].Generate(); @@ -248,26 +265,39 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") { } TEST_CASE("Fuzz Thumb instructions set 2 (affects PC)", "[JitX64][Thumb]") { - const std::array instructions = {{ + const std::array instructions = { + // TODO: We currently can't test BX/BLX as we have + // no way of preventing the unpredictable + // condition from occurring with the current interface. + // (bits zero and one within the specified register + // must not be address<1:0> == '10'. +#if 0 ThumbInstGen("01000111xmmmm000", // BLX/BX [](u16 inst){ - u32 Rm = Dynarmic::Common::Bits<3, 6>(inst); + const u32 Rm = Dynarmic::Common::Bits<3, 6>(inst); return Rm != 15; }), +#endif ThumbInstGen("1010oxxxxxxxxxxx"), // add to pc/sp ThumbInstGen("11100xxxxxxxxxxx"), // B ThumbInstGen("01000100h0xxxxxx"), // ADD (high registers) ThumbInstGen("01000110h0xxxxxx"), // MOV (high registers) ThumbInstGen("1101ccccxxxxxxxx", // B [](u16 inst){ - u32 c = Dynarmic::Common::Bits<9, 12>(inst); + const u32 c = Dynarmic::Common::Bits<9, 12>(inst); return c < 0b1110; // Don't want SWI or undefined instructions. }), ThumbInstGen("10110110011x0xxx"), // CPS - ThumbInstGen("10111101xxxxxxxx"), // POP (R = 1) - }}; - auto instruction_select = [&]() -> u16 { + // TODO: We currently have no control over the generated + // values when creating new pages, so we can't + // reliably test this yet. +#if 0 + ThumbInstGen("10111101xxxxxxxx"), // POP (R = 1) +#endif + }; + + const auto instruction_select = [&]() -> u16 { size_t inst_index = RandInt(0, instructions.size() - 1); return instructions[inst_index].Generate(); @@ -280,8 +310,7 @@ TEST_CASE("Verify fix for off by one error in MemoryRead32 worked", "[Thumb]") { ThumbTestEnv test_env; // Prepare test subjects - ARMul_State interp{USER32MODE}; - interp.user_callbacks = &test_env; + A32Unicorn uni{test_env}; Dynarmic::A32::Jit jit{GetUserConfig(&test_env)}; constexpr ThumbTestEnv::RegisterArray initial_regs { @@ -312,5 +341,5 @@ TEST_CASE("Verify fix for off by one error in MemoryRead32 worked", "[Thumb]") { 0xE7FE, // b +#0 }; - RunInstance(1, test_env, interp, jit, initial_regs, 5, 5); + RunInstance(1, test_env, uni, jit, initial_regs, 5, 5); } diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_dec.cpp b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_dec.cpp deleted file mode 100644 index f563e1fe..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_dec.cpp +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright 2012 Michael Kang, 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_dec.h" -#include "A32/skyeye_interpreter/skyeye_common/armsupp.h" - -const InstructionSetEncodingItem arm_instruction[] = { - { "vmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }}, - { "vmls", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }}, - { "vnmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }}, - { "vnmls", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }}, - { "vnmul", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }}, - { "vmul", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }}, - { "vadd", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }}, - { "vsub", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }}, - { "vdiv", 5, ARMVFP2, { 23, 27, 0x1D, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }}, - { "vmov(i)", 4, ARMVFP3, { 23, 27, 0x1D, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0 }}, - { "vmov(r)", 5, ARMVFP3, { 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 }}, - { "vabs", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }}, - { "vneg", 5, ARMVFP2, { 23, 27, 0x1D, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 }}, - { "vsqrt", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }}, - { "vcmp", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }}, - { "vcmp2", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40 }}, - { "vcvt(bds)", 5, ARMVFP2, { 23, 27, 0x1D, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 }}, - { "vcvt(bff)", 6, ARMVFP3, { 23, 27, 0x1D, 19, 21, 0x7, 17, 17, 0x1, 9, 11, 5, 6, 6, 1 }}, - { "vcvt(bfi)", 5, ARMVFP2, { 23, 27, 0x1D, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }}, - { "vmovbrs", 3, ARMVFP2, { 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10 }}, - { "vmsr", 2, ARMVFP2, { 20, 27, 0xEE, 0, 11, 0xA10 }}, - { "vmovbrc", 4, ARMVFP2, { 23, 27, 0x1C, 20, 20, 0x0, 8, 11, 0xB, 0, 4, 0x10 }}, - { "vmrs", 2, ARMVFP2, { 20, 27, 0xEF, 0, 11, 0xA10 }}, - { "vmovbcr", 4, ARMVFP2, { 24, 27, 0xE, 20, 20, 1, 8, 11, 0xB, 0, 4, 0x10 }}, - { "vmovbrrss", 3, ARMVFP2, { 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1 }}, - { "vmovbrrd", 3, ARMVFP2, { 21, 27, 0x62, 6, 11, 0x2C, 4, 4, 1 }}, - { "vstr", 3, ARMVFP2, { 24, 27, 0xD, 20, 21, 0, 9, 11, 5 }}, - { "vpush", 3, ARMVFP2, { 23, 27, 0x1A, 16, 21, 0x2D, 9, 11, 5 }}, - { "vstm", 3, ARMVFP2, { 25, 27, 0x6, 20, 20, 0, 9, 11, 5 }}, - { "vpop", 3, ARMVFP2, { 23, 27, 0x19, 16, 21, 0x3D, 9, 11, 5 }}, - { "vldr", 3, ARMVFP2, { 24, 27, 0xD, 20, 21, 1, 9, 11, 5 }}, - { "vldm", 3, ARMVFP2, { 25, 27, 0x6, 20, 20, 1, 9, 11, 5 }}, - - { "srs", 4, 6, { 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005 }}, - { "rfe", 4, 6, { 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a }}, - { "bkpt", 2, 3, { 20, 27, 0x00000012, 4, 7, 0x00000007 }}, - { "blx", 1, 3, { 25, 31, 0x0000007d }}, - { "cps", 3, 6, { 20, 31, 0x00000f10, 16, 16, 0x00000000, 5, 5, 0x00000000 }}, - { "pld", 4, 4, { 26, 31, 0x0000003d, 24, 24, 0x00000001, 20, 22, 0x00000005, 12, 15, 0x0000000f }}, - { "setend", 2, 6, { 16, 31, 0x0000f101, 4, 7, 0x00000000 }}, - { "clrex", 1, 6, { 0, 31, 0xf57ff01f }}, - { "rev16", 2, 6, { 16, 27, 0x000006bf, 4, 11, 0x000000fb }}, - { "usad8", 3, 6, { 20, 27, 0x00000078, 12, 15, 0x0000000f, 4, 7, 0x00000001 }}, - { "sxtb", 2, 6, { 16, 27, 0x000006af, 4, 7, 0x00000007 }}, - { "uxtb", 2, 6, { 16, 27, 0x000006ef, 4, 7, 0x00000007 }}, - { "sxth", 2, 6, { 16, 27, 0x000006bf, 4, 7, 0x00000007 }}, - { "sxtb16", 2, 6, { 16, 27, 0x0000068f, 4, 7, 0x00000007 }}, - { "uxth", 2, 6, { 16, 27, 0x000006ff, 4, 7, 0x00000007 }}, - { "uxtb16", 2, 6, { 16, 27, 0x000006cf, 4, 7, 0x00000007 }}, - { "cpy", 2, 6, { 20, 27, 0x0000001a, 4, 11, 0x00000000 }}, - { "uxtab", 2, 6, { 20, 27, 0x0000006e, 4, 9, 0x00000007 }}, - { "ssub8", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x0000000f }}, - { "shsub8", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x0000000f }}, - { "ssubaddx", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000005 }}, - { "strex", 2, 6, { 20, 27, 0x00000018, 4, 7, 0x00000009 }}, - { "strexb", 2, 7, { 20, 27, 0x0000001c, 4, 7, 0x00000009 }}, - { "swp", 2, 0, { 20, 27, 0x00000010, 4, 7, 0x00000009 }}, - { "swpb", 2, 0, { 20, 27, 0x00000014, 4, 7, 0x00000009 }}, - { "ssub16", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000007 }}, - { "ssat16", 2, 6, { 20, 27, 0x0000006a, 4, 7, 0x00000003 }}, - { "shsubaddx", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000005 }}, - { "qsubaddx", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000005 }}, - { "shaddsubx", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000003 }}, - { "shadd8", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000009 }}, - { "shadd16", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000001 }}, - { "sel", 2, 6, { 20, 27, 0x00000068, 4, 7, 0x0000000b }}, - { "saddsubx", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000003 }}, - { "sadd8", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000009 }}, - { "sadd16", 2, 6, { 20, 27, 0x00000061, 4, 7, 0x00000001 }}, - { "shsub16", 2, 6, { 20, 27, 0x00000063, 4, 7, 0x00000007 }}, - { "umaal", 2, 6, { 20, 27, 0x00000004, 4, 7, 0x00000009 }}, - { "uxtab16", 2, 6, { 20, 27, 0x0000006c, 4, 7, 0x00000007 }}, - { "usubaddx", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000005 }}, - { "usub8", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x0000000f }}, - { "usub16", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000007 }}, - { "usat16", 2, 6, { 20, 27, 0x0000006e, 4, 7, 0x00000003 }}, - { "usada8", 2, 6, { 20, 27, 0x00000078, 4, 7, 0x00000001 }}, - { "uqsubaddx", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000005 }}, - { "uqsub8", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x0000000f }}, - { "uqsub16", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000007 }}, - { "uqaddsubx", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000003 }}, - { "uqadd8", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000009 }}, - { "uqadd16", 2, 6, { 20, 27, 0x00000066, 4, 7, 0x00000001 }}, - { "sxtab", 2, 6, { 20, 27, 0x0000006a, 4, 7, 0x00000007 }}, - { "uhsubaddx", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000005 }}, - { "uhsub8", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x0000000f }}, - { "uhsub16", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000007 }}, - { "uhaddsubx", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000003 }}, - { "uhadd8", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000009 }}, - { "uhadd16", 2, 6, { 20, 27, 0x00000067, 4, 7, 0x00000001 }}, - { "uaddsubx", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000003 }}, - { "uadd8", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000009 }}, - { "uadd16", 2, 6, { 20, 27, 0x00000065, 4, 7, 0x00000001 }}, - { "sxtah", 2, 6, { 20, 27, 0x0000006b, 4, 7, 0x00000007 }}, - { "sxtab16", 2, 6, { 20, 27, 0x00000068, 4, 7, 0x00000007 }}, - { "qadd8", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000009 }}, - { "bxj", 2, 5, { 20, 27, 0x00000012, 4, 7, 0x00000002 }}, - { "clz", 2, 3, { 20, 27, 0x00000016, 4, 7, 0x00000001 }}, - { "uxtah", 2, 6, { 20, 27, 0x0000006f, 4, 7, 0x00000007 }}, - { "bx", 2, 2, { 20, 27, 0x00000012, 4, 7, 0x00000001 }}, - { "rev", 2, 6, { 20, 27, 0x0000006b, 4, 7, 0x00000003 }}, - { "blx", 2, 3, { 20, 27, 0x00000012, 4, 7, 0x00000003 }}, - { "revsh", 2, 6, { 20, 27, 0x0000006f, 4, 7, 0x0000000b }}, - { "qadd", 2, 4, { 20, 27, 0x00000010, 4, 7, 0x00000005 }}, - { "qadd16", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000001 }}, - { "qaddsubx", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000003 }}, - { "ldrex", 2, 0, { 20, 27, 0x00000019, 4, 7, 0x00000009 }}, - { "qdadd", 2, 4, { 20, 27, 0x00000014, 4, 7, 0x00000005 }}, - { "qdsub", 2, 4, { 20, 27, 0x00000016, 4, 7, 0x00000005 }}, - { "qsub", 2, 4, { 20, 27, 0x00000012, 4, 7, 0x00000005 }}, - { "ldrexb", 2, 7, { 20, 27, 0x0000001d, 4, 7, 0x00000009 }}, - { "qsub8", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x0000000f }}, - { "qsub16", 2, 6, { 20, 27, 0x00000062, 4, 7, 0x00000007 }}, - { "smuad", 4, 6, { 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001 }}, - { "smmul", 4, 6, { 20, 27, 0x00000075, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001 }}, - { "smusd", 4, 6, { 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000001, 4, 4, 0x00000001 }}, - { "smlsd", 3, 6, { 20, 27, 0x00000070, 6, 7, 0x00000001, 4, 4, 0x00000001 }}, - { "smlsld", 3, 6, { 20, 27, 0x00000074, 6, 7, 0x00000001, 4, 4, 0x00000001 }}, - { "smmla", 3, 6, { 20, 27, 0x00000075, 6, 7, 0x00000000, 4, 4, 0x00000001 }}, - { "smmls", 3, 6, { 20, 27, 0x00000075, 6, 7, 0x00000003, 4, 4, 0x00000001 }}, - { "smlald", 3, 6, { 20, 27, 0x00000074, 6, 7, 0x00000000, 4, 4, 0x00000001 }}, - { "smlad", 3, 6, { 20, 27, 0x00000070, 6, 7, 0x00000000, 4, 4, 0x00000001 }}, - { "smlaw", 3, 4, { 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000000 }}, - { "smulw", 3, 4, { 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000002 }}, - { "pkhtb", 2, 6, { 20, 27, 0x00000068, 4, 6, 0x00000005 }}, - { "pkhbt", 2, 6, { 20, 27, 0x00000068, 4, 6, 0x00000001 }}, - { "smul", 3, 4, { 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000 }}, - { "smlalxy", 3, 4, { 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000 }}, - { "smla", 3, 4, { 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000 }}, - { "mcrr", 1, 6, { 20, 27, 0x000000c4 }}, - { "mrrc", 1, 6, { 20, 27, 0x000000c5 }}, - { "cmp", 2, 0, { 26, 27, 0x00000000, 20, 24, 0x00000015 }}, - { "tst", 2, 0, { 26, 27, 0x00000000, 20, 24, 0x00000011 }}, - { "teq", 2, 0, { 26, 27, 0x00000000, 20, 24, 0x00000013 }}, - { "cmn", 2, 0, { 26, 27, 0x00000000, 20, 24, 0x00000017 }}, - { "smull", 2, 0, { 21, 27, 0x00000006, 4, 7, 0x00000009 }}, - { "umull", 2, 0, { 21, 27, 0x00000004, 4, 7, 0x00000009 }}, - { "umlal", 2, 0, { 21, 27, 0x00000005, 4, 7, 0x00000009 }}, - { "smlal", 2, 0, { 21, 27, 0x00000007, 4, 7, 0x00000009 }}, - { "mul", 2, 0, { 21, 27, 0x00000000, 4, 7, 0x00000009 }}, - { "mla", 2, 0, { 21, 27, 0x00000001, 4, 7, 0x00000009 }}, - { "ssat", 2, 6, { 21, 27, 0x00000035, 4, 5, 0x00000001 }}, - { "usat", 2, 6, { 21, 27, 0x00000037, 4, 5, 0x00000001 }}, - { "mrs", 4, 0, { 23, 27, 0x00000002, 20, 21, 0x00000000, 16, 19, 0x0000000f, 0, 11, 0x00000000 }}, - { "msr", 3, 0, { 23, 27, 0x00000002, 20, 21, 0x00000002, 4, 7, 0x00000000 }}, - { "and", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000000 }}, - { "bic", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x0000000e }}, - { "ldm", 3, 0, { 25, 27, 0x00000004, 20, 22, 0x00000005, 15, 15, 0x00000000 }}, - { "eor", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000001 }}, - { "add", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000004 }}, - { "rsb", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000003 }}, - { "rsc", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000007 }}, - { "sbc", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000006 }}, - { "adc", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000005 }}, - { "sub", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x00000002 }}, - { "orr", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x0000000c }}, - { "mvn", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x0000000f }}, - { "mov", 2, 0, { 26, 27, 0x00000000, 21, 24, 0x0000000d }}, - { "stm", 2, 0, { 25, 27, 0x00000004, 20, 22, 0x00000004 }}, - { "ldm", 4, 0, { 25, 27, 0x00000004, 22, 22, 0x00000001, 20, 20, 0x00000001, 15, 15, 0x00000001 }}, - { "ldrsh", 3, 2, { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000f }}, - { "stm", 3, 0, { 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000000 }}, - { "ldm", 3, 0, { 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000001 }}, - { "ldrsb", 3, 2, { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000d }}, - { "strd", 3, 4, { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000f }}, - { "ldrh", 3, 0, { 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000b }}, - { "strh", 3, 0, { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000b }}, - { "ldrd", 3, 4, { 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000d }}, - { "strt", 3, 0, { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000002 }}, - { "strbt", 3, 0, { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000006 }}, - { "ldrbt", 3, 0, { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000007 }}, - { "ldrt", 3, 0, { 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000003 }}, - { "mrc", 3, 6, { 24, 27, 0x0000000e, 20, 20, 0x00000001, 4, 4, 0x00000001 }}, - { "mcr", 3, 0, { 24, 27, 0x0000000e, 20, 20, 0x00000000, 4, 4, 0x00000001 }}, - { "msr", 3, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000001 }}, - { "msr", 4, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 16, 19, 0x00000004 }}, - { "msr", 5, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 19, 19, 0x00000001, 16, 17, 0x00000000 }}, - { "msr", 4, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 16, 17, 0x00000001 }}, - { "msr", 4, 0, { 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 17, 17, 0x00000001 }}, - { "ldrb", 3, 0, { 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000001 }}, - { "strb", 3, 0, { 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000000 }}, - { "ldr", 4, 0, { 28, 31, 0x0000000e, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 }}, - { "ldrcond", 3, 0, { 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 }}, - { "str", 3, 0, { 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000000 }}, - { "cdp", 2, 0, { 24, 27, 0x0000000e, 4, 4, 0x00000000 }}, - { "stc", 2, 0, { 25, 27, 0x00000006, 20, 20, 0x00000000 }}, - { "ldc", 2, 0, { 25, 27, 0x00000006, 20, 20, 0x00000001 }}, - { "ldrexd", 2, ARMV6K, { 20, 27, 0x0000001B, 4, 7, 0x00000009 }}, - { "strexd", 2, ARMV6K, { 20, 27, 0x0000001A, 4, 7, 0x00000009 }}, - { "ldrexh", 2, ARMV6K, { 20, 27, 0x0000001F, 4, 7, 0x00000009 }}, - { "strexh", 2, ARMV6K, { 20, 27, 0x0000001E, 4, 7, 0x00000009 }}, - { "nop", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000000 }}, - { "yield", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000001 }}, - { "wfe", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000002 }}, - { "wfi", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000003 }}, - { "sev", 5, ARMV6K, { 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000004 }}, - { "swi", 1, 0, { 24, 27, 0x0000000f }}, - { "bbl", 1, 0, { 25, 27, 0x00000005 }}, -}; - -const InstructionSetEncodingItem arm_exclusion_code[] = { - { "vmla", 0, ARMVFP2, { 0 }}, - { "vmls", 0, ARMVFP2, { 0 }}, - { "vnmla", 0, ARMVFP2, { 0 }}, - { "vnmls", 0, ARMVFP2, { 0 }}, - { "vnmul", 0, ARMVFP2, { 0 }}, - { "vmul", 0, ARMVFP2, { 0 }}, - { "vadd", 0, ARMVFP2, { 0 }}, - { "vsub", 0, ARMVFP2, { 0 }}, - { "vdiv", 0, ARMVFP2, { 0 }}, - { "vmov(i)", 0, ARMVFP3, { 0 }}, - { "vmov(r)", 0, ARMVFP3, { 0 }}, - { "vabs", 0, ARMVFP2, { 0 }}, - { "vneg", 0, ARMVFP2, { 0 }}, - { "vsqrt", 0, ARMVFP2, { 0 }}, - { "vcmp", 0, ARMVFP2, { 0 }}, - { "vcmp2", 0, ARMVFP2, { 0 }}, - { "vcvt(bff)", 0, ARMVFP3, { 4, 4, 1 }}, - { "vcvt(bds)", 0, ARMVFP2, { 0 }}, - { "vcvt(bfi)", 0, ARMVFP2, { 0 }}, - { "vmovbrs", 0, ARMVFP2, { 0 }}, - { "vmsr", 0, ARMVFP2, { 0 }}, - { "vmovbrc", 0, ARMVFP2, { 0 }}, - { "vmrs", 0, ARMVFP2, { 0 }}, - { "vmovbcr", 0, ARMVFP2, { 0 }}, - { "vmovbrrss", 0, ARMVFP2, { 0 }}, - { "vmovbrrd", 0, ARMVFP2, { 0 }}, - { "vstr", 0, ARMVFP2, { 0 }}, - { "vpush", 0, ARMVFP2, { 0 }}, - { "vstm", 0, ARMVFP2, { 0 }}, - { "vpop", 0, ARMVFP2, { 0 }}, - { "vldr", 0, ARMVFP2, { 0 }}, - { "vldm", 0, ARMVFP2, { 0 }}, - - { "srs", 0, 6, { 0 }}, - { "rfe", 0, 6, { 0 }}, - { "bkpt", 0, 3, { 0 }}, - { "blx", 0, 3, { 0 }}, - { "cps", 0, 6, { 0 }}, - { "pld", 0, 4, { 0 }}, - { "setend", 0, 6, { 0 }}, - { "clrex", 0, 6, { 0 }}, - { "rev16", 0, 6, { 0 }}, - { "usad8", 0, 6, { 0 }}, - { "sxtb", 0, 6, { 0 }}, - { "uxtb", 0, 6, { 0 }}, - { "sxth", 0, 6, { 0 }}, - { "sxtb16", 0, 6, { 0 }}, - { "uxth", 0, 6, { 0 }}, - { "uxtb16", 0, 6, { 0 }}, - { "cpy", 0, 6, { 0 }}, - { "uxtab", 0, 6, { 0 }}, - { "ssub8", 0, 6, { 0 }}, - { "shsub8", 0, 6, { 0 }}, - { "ssubaddx", 0, 6, { 0 }}, - { "strex", 0, 6, { 0 }}, - { "strexb", 0, 7, { 0 }}, - { "swp", 0, 0, { 0 }}, - { "swpb", 0, 0, { 0 }}, - { "ssub16", 0, 6, { 0 }}, - { "ssat16", 0, 6, { 0 }}, - { "shsubaddx", 0, 6, { 0 }}, - { "qsubaddx", 0, 6, { 0 }}, - { "shaddsubx", 0, 6, { 0 }}, - { "shadd8", 0, 6, { 0 }}, - { "shadd16", 0, 6, { 0 }}, - { "sel", 0, 6, { 0 }}, - { "saddsubx", 0, 6, { 0 }}, - { "sadd8", 0, 6, { 0 }}, - { "sadd16", 0, 6, { 0 }}, - { "shsub16", 0, 6, { 0 }}, - { "umaal", 0, 6, { 0 }}, - { "uxtab16", 0, 6, { 0 }}, - { "usubaddx", 0, 6, { 0 }}, - { "usub8", 0, 6, { 0 }}, - { "usub16", 0, 6, { 0 }}, - { "usat16", 0, 6, { 0 }}, - { "usada8", 0, 6, { 0 }}, - { "uqsubaddx", 0, 6, { 0 }}, - { "uqsub8", 0, 6, { 0 }}, - { "uqsub16", 0, 6, { 0 }}, - { "uqaddsubx", 0, 6, { 0 }}, - { "uqadd8", 0, 6, { 0 }}, - { "uqadd16", 0, 6, { 0 }}, - { "sxtab", 0, 6, { 0 }}, - { "uhsubaddx", 0, 6, { 0 }}, - { "uhsub8", 0, 6, { 0 }}, - { "uhsub16", 0, 6, { 0 }}, - { "uhaddsubx", 0, 6, { 0 }}, - { "uhadd8", 0, 6, { 0 }}, - { "uhadd16", 0, 6, { 0 }}, - { "uaddsubx", 0, 6, { 0 }}, - { "uadd8", 0, 6, { 0 }}, - { "uadd16", 0, 6, { 0 }}, - { "sxtah", 0, 6, { 0 }}, - { "sxtab16", 0, 6, { 0 }}, - { "qadd8", 0, 6, { 0 }}, - { "bxj", 0, 5, { 0 }}, - { "clz", 0, 3, { 0 }}, - { "uxtah", 0, 6, { 0 }}, - { "bx", 0, 2, { 0 }}, - { "rev", 0, 6, { 0 }}, - { "blx", 0, 3, { 0 }}, - { "revsh", 0, 6, { 0 }}, - { "qadd", 0, 4, { 0 }}, - { "qadd16", 0, 6, { 0 }}, - { "qaddsubx", 0, 6, { 0 }}, - { "ldrex", 0, 0, { 0 }}, - { "qdadd", 0, 4, { 0 }}, - { "qdsub", 0, 4, { 0 }}, - { "qsub", 0, 4, { 0 }}, - { "ldrexb", 0, 7, { 0 }}, - { "qsub8", 0, 6, { 0 }}, - { "qsub16", 0, 6, { 0 }}, - { "smuad", 0, 6, { 0 }}, - { "smmul", 0, 6, { 0 }}, - { "smusd", 0, 6, { 0 }}, - { "smlsd", 0, 6, { 0 }}, - { "smlsld", 0, 6, { 0 }}, - { "smmla", 0, 6, { 0 }}, - { "smmls", 0, 6, { 0 }}, - { "smlald", 0, 6, { 0 }}, - { "smlad", 0, 6, { 0 }}, - { "smlaw", 0, 4, { 0 }}, - { "smulw", 0, 4, { 0 }}, - { "pkhtb", 0, 6, { 0 }}, - { "pkhbt", 0, 6, { 0 }}, - { "smul", 0, 4, { 0 }}, - { "smlal", 0, 4, { 0 }}, - { "smla", 0, 4, { 0 }}, - { "mcrr", 0, 6, { 0 }}, - { "mrrc", 0, 6, { 0 }}, - { "cmp", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "tst", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "teq", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "cmn", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "smull", 0, 0, { 0 }}, - { "umull", 0, 0, { 0 }}, - { "umlal", 0, 0, { 0 }}, - { "smlal", 0, 0, { 0 }}, - { "mul", 0, 0, { 0 }}, - { "mla", 0, 0, { 0 }}, - { "ssat", 0, 6, { 0 }}, - { "usat", 0, 6, { 0 }}, - { "mrs", 0, 0, { 0 }}, - { "msr", 0, 0, { 0 }}, - { "and", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "bic", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "ldm", 0, 0, { 0 }}, - { "eor", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "add", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "rsb", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "rsc", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "sbc", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "adc", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "sub", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "orr", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "mvn", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "mov", 3, 0, { 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 }}, - { "stm", 0, 0, { 0 }}, - { "ldm", 0, 0, { 0 }}, - { "ldrsh", 0, 2, { 0 }}, - { "stm", 0, 0, { 0 }}, - { "ldm", 0, 0, { 0 }}, - { "ldrsb", 0, 2, { 0 }}, - { "strd", 0, 4, { 0 }}, - { "ldrh", 0, 0, { 0 }}, - { "strh", 0, 0, { 0 }}, - { "ldrd", 0, 4, { 0 }}, - { "strt", 0, 0, { 0 }}, - { "strbt", 0, 0, { 0 }}, - { "ldrbt", 0, 0, { 0 }}, - { "ldrt", 0, 0, { 0 }}, - { "mrc", 0, 6, { 0 }}, - { "mcr", 0, 0, { 0 }}, - { "msr", 0, 0, { 0 }}, - { "msr", 0, 0, { 0 }}, - { "msr", 0, 0, { 0 }}, - { "msr", 0, 0, { 0 }}, - { "msr", 0, 0, { 0 }}, - { "ldrb", 0, 0, { 0 }}, - { "strb", 0, 0, { 0 }}, - { "ldr", 0, 0, { 0 }}, - { "ldrcond", 1, 0, { 28, 31, 0x0000000e }}, - { "str", 0, 0, { 0 }}, - { "cdp", 0, 0, { 0 }}, - { "stc", 0, 0, { 0 }}, - { "ldc", 0, 0, { 0 }}, - { "ldrexd", 0, ARMV6K, { 0 }}, - { "strexd", 0, ARMV6K, { 0 }}, - { "ldrexh", 0, ARMV6K, { 0 }}, - { "strexh", 0, ARMV6K, { 0 }}, - { "nop", 0, ARMV6K, { 0 }}, - { "yield", 0, ARMV6K, { 0 }}, - { "wfe", 0, ARMV6K, { 0 }}, - { "wfi", 0, ARMV6K, { 0 }}, - { "sev", 0, ARMV6K, { 0 }}, - { "swi", 0, 0, { 0 }}, - { "bbl", 0, 0, { 0 }}, - - { "bl_1_thumb", 0, INVALID, { 0 }}, // Should be table[-4] - { "bl_2_thumb", 0, INVALID, { 0 }}, // Should be located at the end of the table[-3] - { "blx_1_thumb", 0, INVALID, { 0 }}, // Should be located at table[-2] - { "invalid", 0, INVALID, { 0 }} -}; - -ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { - int n = 0; - int base = 0; - int instr_slots = sizeof(arm_instruction) / sizeof(InstructionSetEncodingItem); - ARMDecodeStatus ret = ARMDecodeStatus::FAILURE; - - for (int i = 0; i < instr_slots; i++) { - n = arm_instruction[i].attribute_value; - base = 0; - - // 3DS has no VFP3 support - if (arm_instruction[i].version == ARMVFP3) - continue; - - while (n) { - if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) { - // clrex - if (instr != arm_instruction[i].content[base + 2]) { - break; - } - } else if (BITS(instr, arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) { - break; - } - base += 3; - n--; - } - - // All conditions are satisfied. - if (n == 0) - ret = ARMDecodeStatus::SUCCESS; - - if (ret == ARMDecodeStatus::SUCCESS) { - n = arm_exclusion_code[i].attribute_value; - if (n != 0) { - base = 0; - while (n) { - if (BITS(instr, arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) { - break; - } - base += 3; - n--; - } - - // All conditions are satisfied. - if (n == 0) - ret = ARMDecodeStatus::FAILURE; - } - } - - if (ret == ARMDecodeStatus::SUCCESS) { - *idx = i; - return ret; - } - } - return ret; -} diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_dec.h b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_dec.h deleted file mode 100644 index d7170e0f..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_dec.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 Michael Kang, 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -enum class ARMDecodeStatus { - SUCCESS, - FAILURE -}; - -ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); - -struct InstructionSetEncodingItem { - const char *name; - int attribute_value; - int version; - u32 content[21]; -}; - -// ARM versions -enum { - INVALID = 0, - ARMALL, - ARMV4, - ARMV4T, - ARMV5T, - ARMV5TE, - ARMV5TEJ, - ARMV6, - ARM1176JZF_S, - ARMVFP2, - ARMVFP3, - ARMV6K, -}; - -extern const InstructionSetEncodingItem arm_instruction[]; diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.cpp b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.cpp deleted file mode 100644 index fe8c6b21..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.cpp +++ /dev/null @@ -1,4250 +0,0 @@ -// Copyright 2012 Michael Kang, 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#define CITRA_IGNORE_EXIT(x) - -#ifdef _MSC_VER -#pragma warning(disable : 4244) -#endif - -#include -#include - -#include "common/assert.h" -#include "common/common_types.h" -//#include "common/logging/log.h" -//#include "common/microprofile.h" - -//#include "core/memory.h" -//#include "core/hle/svc.h" -//#include "A32/skyeye_interpreter/disassembler/arm_disasm.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_dec.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_trans.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_run.h" -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" -#include "A32/skyeye_interpreter/skyeye_common/armsupp.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp.h" - -//#include "core/gdbstub/gdbstub.h" - -#define LOG_INFO(...) do{}while(0) -#define LOG_TRACE(...) do{}while(0) - -#define RM BITS(sht_oper, 0, 3) -#define RS BITS(sht_oper, 8, 11) - -#define glue(x, y) x ## y -#define DPO(s) glue(DataProcessingOperands, s) -#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i)) -#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i)) -#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32) -#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32) - -static bool CondPassed(const ARMul_State* cpu, unsigned int cond) { - const bool n_flag = cpu->NFlag != 0; - const bool z_flag = cpu->ZFlag != 0; - const bool c_flag = cpu->CFlag != 0; - const bool v_flag = cpu->VFlag != 0; - - switch (cond) { - case ConditionCode::EQ: - return z_flag; - case ConditionCode::NE: - return !z_flag; - case ConditionCode::CS: - return c_flag; - case ConditionCode::CC: - return !c_flag; - case ConditionCode::MI: - return n_flag; - case ConditionCode::PL: - return !n_flag; - case ConditionCode::VS: - return v_flag; - case ConditionCode::VC: - return !v_flag; - case ConditionCode::HI: - return (c_flag && !z_flag); - case ConditionCode::LS: - return (!c_flag || z_flag); - case ConditionCode::GE: - return (n_flag == v_flag); - case ConditionCode::LT: - return (n_flag != v_flag); - case ConditionCode::GT: - return (!z_flag && (n_flag == v_flag)); - case ConditionCode::LE: - return (z_flag || (n_flag != v_flag)); - case ConditionCode::AL: - case ConditionCode::NV: // Unconditional - return true; - } - - return false; -} - -static unsigned int DPO(Immediate)(ARMul_State* cpu, unsigned int sht_oper) { - unsigned int immed_8 = BITS(sht_oper, 0, 7); - unsigned int rotate_imm = BITS(sht_oper, 8, 11); - unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2); - if (rotate_imm == 0) - cpu->shifter_carry_out = cpu->CFlag; - else - cpu->shifter_carry_out = BIT(shifter_operand, 31); - return shifter_operand; -} - -static unsigned int DPO(Register)(ARMul_State* cpu, unsigned int sht_oper) { - unsigned int rm = CHECK_READ_REG15(cpu, RM); - unsigned int shifter_operand = rm; - cpu->shifter_carry_out = cpu->CFlag; - return shifter_operand; -} - -static unsigned int DPO(LogicalShiftLeftByImmediate)(ARMul_State* cpu, unsigned int sht_oper) { - int shift_imm = BITS(sht_oper, 7, 11); - unsigned int rm = CHECK_READ_REG15(cpu, RM); - unsigned int shifter_operand; - if (shift_imm == 0) { - shifter_operand = rm; - cpu->shifter_carry_out = cpu->CFlag; - } else { - shifter_operand = rm << shift_imm; - cpu->shifter_carry_out = BIT(rm, 32 - shift_imm); - } - return shifter_operand; -} - -static unsigned int DPO(LogicalShiftLeftByRegister)(ARMul_State* cpu, unsigned int sht_oper) { - int shifter_operand; - unsigned int rm = CHECK_READ_REG15(cpu, RM); - unsigned int rs = CHECK_READ_REG15(cpu, RS); - if (BITS(rs, 0, 7) == 0) { - shifter_operand = rm; - cpu->shifter_carry_out = cpu->CFlag; - } else if (BITS(rs, 0, 7) < 32) { - shifter_operand = rm << BITS(rs, 0, 7); - cpu->shifter_carry_out = BIT(rm, 32 - BITS(rs, 0, 7)); - } else if (BITS(rs, 0, 7) == 32) { - shifter_operand = 0; - cpu->shifter_carry_out = BIT(rm, 0); - } else { - shifter_operand = 0; - cpu->shifter_carry_out = 0; - } - return shifter_operand; -} - -static unsigned int DPO(LogicalShiftRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) { - unsigned int rm = CHECK_READ_REG15(cpu, RM); - unsigned int shifter_operand; - int shift_imm = BITS(sht_oper, 7, 11); - if (shift_imm == 0) { - shifter_operand = 0; - cpu->shifter_carry_out = BIT(rm, 31); - } else { - shifter_operand = rm >> shift_imm; - cpu->shifter_carry_out = BIT(rm, shift_imm - 1); - } - return shifter_operand; -} - -static unsigned int DPO(LogicalShiftRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) { - unsigned int rs = CHECK_READ_REG15(cpu, RS); - unsigned int rm = CHECK_READ_REG15(cpu, RM); - unsigned int shifter_operand; - if (BITS(rs, 0, 7) == 0) { - shifter_operand = rm; - cpu->shifter_carry_out = cpu->CFlag; - } else if (BITS(rs, 0, 7) < 32) { - shifter_operand = rm >> BITS(rs, 0, 7); - cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1); - } else if (BITS(rs, 0, 7) == 32) { - shifter_operand = 0; - cpu->shifter_carry_out = BIT(rm, 31); - } else { - shifter_operand = 0; - cpu->shifter_carry_out = 0; - } - return shifter_operand; -} - -static unsigned int DPO(ArithmeticShiftRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) { - unsigned int rm = CHECK_READ_REG15(cpu, RM); - unsigned int shifter_operand; - int shift_imm = BITS(sht_oper, 7, 11); - if (shift_imm == 0) { - if (BIT(rm, 31) == 0) - shifter_operand = 0; - else - shifter_operand = 0xFFFFFFFF; - cpu->shifter_carry_out = BIT(rm, 31); - } else { - shifter_operand = static_cast(rm) >> shift_imm; - cpu->shifter_carry_out = BIT(rm, shift_imm - 1); - } - return shifter_operand; -} - -static unsigned int DPO(ArithmeticShiftRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) { - unsigned int rs = CHECK_READ_REG15(cpu, RS); - unsigned int rm = CHECK_READ_REG15(cpu, RM); - unsigned int shifter_operand; - if (BITS(rs, 0, 7) == 0) { - shifter_operand = rm; - cpu->shifter_carry_out = cpu->CFlag; - } else if (BITS(rs, 0, 7) < 32) { - shifter_operand = static_cast(rm) >> BITS(rs, 0, 7); - cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1); - } else { - if (BIT(rm, 31) == 0) - shifter_operand = 0; - else - shifter_operand = 0xffffffff; - cpu->shifter_carry_out = BIT(rm, 31); - } - return shifter_operand; -} - -static unsigned int DPO(RotateRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) { - unsigned int shifter_operand; - unsigned int rm = CHECK_READ_REG15(cpu, RM); - int shift_imm = BITS(sht_oper, 7, 11); - if (shift_imm == 0) { - shifter_operand = (cpu->CFlag << 31) | (rm >> 1); - cpu->shifter_carry_out = BIT(rm, 0); - } else { - shifter_operand = ROTATE_RIGHT_32(rm, shift_imm); - cpu->shifter_carry_out = BIT(rm, shift_imm - 1); - } - return shifter_operand; -} - -static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) { - unsigned int rm = CHECK_READ_REG15(cpu, RM); - unsigned int rs = CHECK_READ_REG15(cpu, RS); - unsigned int shifter_operand; - if (BITS(rs, 0, 7) == 0) { - shifter_operand = rm; - cpu->shifter_carry_out = cpu->CFlag; - } else if (BITS(rs, 0, 4) == 0) { - shifter_operand = rm; - cpu->shifter_carry_out = BIT(rm, 31); - } else { - shifter_operand = ROTATE_RIGHT_32(rm, BITS(rs, 0, 4)); - cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 4) - 1); - } - return shifter_operand; -} - -#define DEBUG_MSG //LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0) - -#define LnSWoUB(s) glue(LnSWoUB, s) -#define MLnS(s) glue(MLnS, s) -#define LdnStM(s) glue(LdnStM, s) - -#define W_BIT BIT(inst, 21) -#define U_BIT BIT(inst, 23) -#define I_BIT BIT(inst, 25) -#define P_BIT BIT(inst, 24) -#define OFFSET_12 BITS(inst, 0, 11) - -static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int addr; - - if (U_BIT) - addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12; - else - addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12; - - virt_addr = addr; -} - -static void LnSWoUB(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - unsigned int addr; - - if (U_BIT) - addr = rn + rm; - else - addr = rn - rm; - - virt_addr = addr; -} - -static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); - - if (U_BIT) - cpu->Reg[Rn] += OFFSET_12; - else - cpu->Reg[Rn] -= OFFSET_12; - - virt_addr = addr; -} - -static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int addr; - - if (U_BIT) - addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12; - else - addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12; - - virt_addr = addr; - - if (CondPassed(cpu, BITS(inst, 28, 31))) - cpu->Reg[Rn] = addr; -} - -static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int addr; - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - - if (U_BIT) - addr = rn + rm; - else - addr = rn - rm; - - virt_addr = addr; - - if (CondPassed(cpu, BITS(inst, 28, 31))) - cpu->Reg[Rn] = addr; -} - -static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - unsigned int addr; - - if (U_BIT) - addr = rn + rm; - else - addr = rn - rm; - - virt_addr = addr; - - if (CondPassed(cpu, BITS(inst, 28, 31))) { - cpu->Reg[Rn] = addr; - } -} - -static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int shift = BITS(inst, 5, 6); - unsigned int shift_imm = BITS(inst, 7, 11); - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int index = 0; - unsigned int addr; - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - - switch (shift) { - case 0: - index = rm << shift_imm; - break; - case 1: - if (shift_imm == 0) { - index = 0; - } else { - index = rm >> shift_imm; - } - break; - case 2: - if (shift_imm == 0) { // ASR #32 - if (BIT(rm, 31) == 1) - index = 0xFFFFFFFF; - else - index = 0; - } else { - index = static_cast(rm) >> shift_imm; - } - break; - case 3: - if (shift_imm == 0) { - index = (cpu->CFlag << 31) | (rm >> 1); - } else { - index = ROTATE_RIGHT_32(rm, shift_imm); - } - break; - } - - if (U_BIT) - addr = rn + index; - else - addr = rn - index; - - virt_addr = addr; - - if (CondPassed(cpu, BITS(inst, 28, 31))) - cpu->Reg[Rn] = addr; -} - -static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int shift = BITS(inst, 5, 6); - unsigned int shift_imm = BITS(inst, 7, 11); - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int index = 0; - unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - - switch (shift) { - case 0: - index = rm << shift_imm; - break; - case 1: - if (shift_imm == 0) { - index = 0; - } else { - index = rm >> shift_imm; - } - break; - case 2: - if (shift_imm == 0) { // ASR #32 - if (BIT(rm, 31) == 1) - index = 0xFFFFFFFF; - else - index = 0; - } else { - index = static_cast(rm) >> shift_imm; - } - break; - case 3: - if (shift_imm == 0) { - index = (cpu->CFlag << 31) | (rm >> 1); - } else { - index = ROTATE_RIGHT_32(rm, shift_imm); - } - break; - } - - virt_addr = addr; - - if (CondPassed(cpu, BITS(inst, 28, 31))) { - if (U_BIT) - cpu->Reg[Rn] += index; - else - cpu->Reg[Rn] -= index; - } -} - -static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - - virt_addr = CHECK_READ_REG15_WA(cpu, Rn); - - if (CondPassed(cpu, BITS(inst, 28, 31))) { - if (U_BIT) { - cpu->Reg[Rn] += rm; - } else { - cpu->Reg[Rn] -= rm; - } - } -} - -static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int immedL = BITS(inst, 0, 3); - unsigned int immedH = BITS(inst, 8, 11); - unsigned int Rn = BITS(inst, 16, 19); - unsigned int addr; - - unsigned int offset_8 = (immedH << 4) | immedL; - - if (U_BIT) - addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8; - else - addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8; - - virt_addr = addr; -} - -static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int addr; - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - - if (U_BIT) - addr = rn + rm; - else - addr = rn - rm; - - virt_addr = addr; -} - -static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int immedH = BITS(inst, 8, 11); - unsigned int immedL = BITS(inst, 0, 3); - unsigned int addr; - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - unsigned int offset_8 = (immedH << 4) | immedL; - - if (U_BIT) - addr = rn + offset_8; - else - addr = rn - offset_8; - - virt_addr = addr; - - if (CondPassed(cpu, BITS(inst, 28, 31))) - cpu->Reg[Rn] = addr; -} - -static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int immedH = BITS(inst, 8, 11); - unsigned int immedL = BITS(inst, 0, 3); - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - - virt_addr = rn; - - if (CondPassed(cpu, BITS(inst, 28, 31))) { - unsigned int offset_8 = (immedH << 4) | immedL; - if (U_BIT) - rn += offset_8; - else - rn -= offset_8; - - cpu->Reg[Rn] = rn; - } -} - -static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - - virt_addr = CHECK_READ_REG15_WA(cpu, Rn); - - if (CondPassed(cpu, BITS(inst, 28, 31))) { - if (U_BIT) - cpu->Reg[Rn] += rm; - else - cpu->Reg[Rn] -= rm; - } -} - -static void LdnStM(DecrementBefore)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int i = BITS(inst, 0, 15); - int count = 0; - - while (i) { - if (i & 1) count++; - i = i >> 1; - } - - virt_addr = CHECK_READ_REG15_WA(cpu, Rn) - count * 4; - - if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) - cpu->Reg[Rn] -= count * 4; -} - -static void LdnStM(IncrementBefore)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int i = BITS(inst, 0, 15); - int count = 0; - - while (i) { - if (i & 1) count++; - i = i >> 1; - } - - virt_addr = CHECK_READ_REG15_WA(cpu, Rn) + 4; - - if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) - cpu->Reg[Rn] += count * 4; -} - -static void LdnStM(IncrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int i = BITS(inst, 0, 15); - int count = 0; - - while(i) { - if (i & 1) count++; - i = i >> 1; - } - - virt_addr = CHECK_READ_REG15_WA(cpu, Rn); - - if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) - cpu->Reg[Rn] += count * 4; -} - -static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int Rn = BITS(inst, 16, 19); - unsigned int i = BITS(inst, 0, 15); - int count = 0; - while(i) { - if(i & 1) count++; - i = i >> 1; - } - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - unsigned int start_addr = rn - count * 4 + 4; - - virt_addr = start_addr; - - if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) { - cpu->Reg[Rn] -= count * 4; - } -} - -static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { - unsigned int shift = BITS(inst, 5, 6); - unsigned int shift_imm = BITS(inst, 7, 11); - unsigned int Rn = BITS(inst, 16, 19); - unsigned int Rm = BITS(inst, 0, 3); - unsigned int index = 0; - unsigned int addr; - unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); - unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); - - switch (shift) { - case 0: - index = rm << shift_imm; - break; - case 1: - if (shift_imm == 0) { - index = 0; - } else { - index = rm >> shift_imm; - } - break; - case 2: - if (shift_imm == 0) { // ASR #32 - if (BIT(rm, 31) == 1) - index = 0xFFFFFFFF; - else - index = 0; - } else { - index = static_cast(rm) >> shift_imm; - } - break; - case 3: - if (shift_imm == 0) { - index = (cpu->CFlag << 31) | (rm >> 1); - } else { - index = ROTATE_RIGHT_32(rm, shift_imm); - } - break; - } - - if (U_BIT) { - addr = rn + index; - } else - addr = rn - index; - - virt_addr = addr; -} - -shtop_fp_t GetShifterOp(unsigned int inst) { - if (BIT(inst, 25)) { - return DPO(Immediate); - } else if (BITS(inst, 4, 11) == 0) { - return DPO(Register); - } else if (BITS(inst, 4, 6) == 0) { - return DPO(LogicalShiftLeftByImmediate); - } else if (BITS(inst, 4, 7) == 1) { - return DPO(LogicalShiftLeftByRegister); - } else if (BITS(inst, 4, 6) == 2) { - return DPO(LogicalShiftRightByImmediate); - } else if (BITS(inst, 4, 7) == 3) { - return DPO(LogicalShiftRightByRegister); - } else if (BITS(inst, 4, 6) == 4) { - return DPO(ArithmeticShiftRightByImmediate); - } else if (BITS(inst, 4, 7) == 5) { - return DPO(ArithmeticShiftRightByRegister); - } else if (BITS(inst, 4, 6) == 6) { - return DPO(RotateRightByImmediate); - } else if (BITS(inst, 4, 7) == 7) { - return DPO(RotateRightByRegister); - } - return nullptr; -} - -get_addr_fp_t GetAddressingOp(unsigned int inst) { - if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) { - return LnSWoUB(ImmediateOffset); - } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) { - return LnSWoUB(RegisterOffset); - } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { - return LnSWoUB(ScaledRegisterOffset); - } else if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 1) { - return LnSWoUB(ImmediatePreIndexed); - } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BITS(inst, 4, 11) == 0) { - return LnSWoUB(RegisterPreIndexed); - } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BIT(inst, 4) == 0) { - return LnSWoUB(ScaledRegisterPreIndexed); - } else if (BITS(inst, 24, 27) == 4 && BIT(inst, 21) == 0) { - return LnSWoUB(ImmediatePostIndexed); - } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) { - return LnSWoUB(RegisterPostIndexed); - } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { - return LnSWoUB(ScaledRegisterPostIndexed); - } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { - return MLnS(ImmediateOffset); - } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { - return MLnS(RegisterOffset); - } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { - return MLnS(ImmediatePreIndexed); - } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { - return MLnS(RegisterPreIndexed); - } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { - return MLnS(ImmediatePostIndexed); - } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { - return MLnS(RegisterPostIndexed); - } else if (BITS(inst, 23, 27) == 0x11) { - return LdnStM(IncrementAfter); - } else if (BITS(inst, 23, 27) == 0x13) { - return LdnStM(IncrementBefore); - } else if (BITS(inst, 23, 27) == 0x10) { - return LdnStM(DecrementAfter); - } else if (BITS(inst, 23, 27) == 0x12) { - return LdnStM(DecrementBefore); - } - return nullptr; -} - -// Specialized for LDRT, LDRBT, STRT, and STRBT, which have specific addressing mode requirements -get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) { - if (BITS(inst, 25, 27) == 2) { - return LnSWoUB(ImmediatePostIndexed); - } else if (BITS(inst, 25, 27) == 3) { - return LnSWoUB(ScaledRegisterPostIndexed); - } - // Reaching this would indicate the thumb version - // of this instruction, however the 3DS CPU doesn't - // support this variant (the 3DS CPU is only ARMv6K, - // while this variant is added in ARMv6T2). - // So it's sufficient for citra to not implement this. - return nullptr; -} - -enum { - FETCH_SUCCESS, - FETCH_FAILURE -}; - -static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { - // Check if in Thumb mode - ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); - if (ret == ThumbDecodeStatus::BRANCH) { - int inst_index; - int table_length = (int)arm_instruction_trans_len; - u32 tinstr = GetThumbInstruction(inst, addr); - - switch ((tinstr & 0xF800) >> 11) { - case 26: - case 27: - if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ - inst_index = table_length - 4; - *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); - } else { -// LOG_ERROR(Core_ARM11, "thumb decoder error"); - ASSERT_MSG(false, "thumb decoder error"); - } - break; - case 28: - // Branch 2, unconditional branch - inst_index = table_length - 5; - *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); - break; - - case 8: - case 29: - // For BLX 1 thumb instruction - inst_index = table_length - 1; - *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); - break; - case 30: - // For BL 1 thumb instruction - inst_index = table_length - 3; - *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); - break; - case 31: - // For BL 2 thumb instruction - inst_index = table_length - 2; - *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); - break; - default: - ret = ThumbDecodeStatus::UNDEFINED; - break; - } - } - return ret; -} - -enum { - KEEP_GOING, - FETCH_EXCEPTION -}; - -//MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); - -static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) { - unsigned int inst_size = 4; - unsigned int inst = cpu->user_callbacks->MemoryReadCode(phys_addr & 0xFFFFFFFC); - - // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction - if (cpu->TFlag) { - u32 arm_inst; - ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); - - // We have translated the Thumb branch instruction in the Thumb decoder - if (state == ThumbDecodeStatus::BRANCH) { - return inst_size; - } - inst = arm_inst; - } - - int idx; - if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { -// std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); -// LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); -// LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); - ASSERT_MSG(false, "Decode failure.\tPC : [0x{:x}]\tInstruction : {} [{:x}]", phys_addr, "", inst); - ASSERT_MSG(false, "cpsr=0x{:x}, cpu->TFlag={}, r15=0x{:x}", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); - CITRA_IGNORE_EXIT(-1); - } - inst_base = arm_instruction_trans[idx](inst, idx); - - return inst_size; -} - -static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr) { -// MICROPROFILE_SCOPE(DynCom_Decode); - - // Decode instruction, get index - // Allocate memory and init InsCream - // Go on next, until terminal instruction - // Save start addr of basicblock in CreamCache - ARM_INST_PTR inst_base = nullptr; - TransExtData ret = TransExtData::NON_BRANCH; - int size = 0; // instruction size of basic block - bb_start = (int)trans_cache_buf_top; - - u32 phys_addr = addr; - u32 pc_start = cpu->Reg[15]; - - while (ret == TransExtData::NON_BRANCH) { - unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base); - - size++; - - phys_addr += inst_size; - - if ((phys_addr & 0xfff) == 0) { - inst_base->br = TransExtData::END_OF_PAGE; - } - ret = inst_base->br; - }; - - cpu->instruction_cache[pc_start] = bb_start; - - return KEEP_GOING; -} - -static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr) { -// MICROPROFILE_SCOPE(DynCom_Decode); - - ARM_INST_PTR inst_base = nullptr; - bb_start = (int)trans_cache_buf_top; - - u32 phys_addr = addr; - u32 pc_start = cpu->Reg[15]; - - InterpreterTranslateInstruction(cpu, phys_addr, inst_base); - - if (inst_base->br == TransExtData::NON_BRANCH) { - inst_base->br = TransExtData::SINGLE_STEP; - } - - cpu->instruction_cache[pc_start] = bb_start; - - return KEEP_GOING; -} - -static int clz(unsigned int x) { - int n; - if (x == 0) return (32); - n = 1; - if ((x >> 16) == 0) { n = n + 16; x = x << 16;} - if ((x >> 24) == 0) { n = n + 8; x = x << 8;} - if ((x >> 28) == 0) { n = n + 4; x = x << 4;} - if ((x >> 30) == 0) { n = n + 2; x = x << 2;} - n = n - (x >> 31); - return n; -} - -//MICROPROFILE_DEFINE(DynCom_Execute, "DynCom", "Execute", MP_RGB(255, 0, 0)); - -unsigned InterpreterMainLoop(ARMul_State* cpu) { -// MICROPROFILE_SCOPE(DynCom_Execute); - -// GDBStub::BreakpointAddress breakpoint_data; - - #undef RM - #undef RS - - #define CRn inst_cream->crn - #define OPCODE_1 inst_cream->opcode_1 - #define OPCODE_2 inst_cream->opcode_2 - #define CRm inst_cream->crm - #define RD cpu->Reg[inst_cream->Rd] - #define RD2 cpu->Reg[inst_cream->Rd + 1] - #define RN cpu->Reg[inst_cream->Rn] - #define RM cpu->Reg[inst_cream->Rm] - #define RS cpu->Reg[inst_cream->Rs] - #define RDHI cpu->Reg[inst_cream->RdHi] - #define RDLO cpu->Reg[inst_cream->RdLo] - #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4) - #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24) - #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand) - - #define FETCH_INST if (inst_base->br != TransExtData::NON_BRANCH) goto DISPATCH; \ - inst_base = (arm_inst *)&trans_cache_buf[ptr] - - #define INC_PC(l) ptr += sizeof(arm_inst) + l - #define INC_PC_STUB ptr += sizeof(arm_inst) - -#define GDB_BP_CHECK \ - cpu->Cpsr &= ~(1 << 5); \ - cpu->Cpsr |= cpu->TFlag << 5; -// if (GDBStub::g_server_enabled) { -// if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && PC == breakpoint_data.address)) { -// GDBStub::Break(); -// goto END; -// } -// } - -#define GOTO_NEXT_INST \ - GDB_BP_CHECK; \ - if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ - num_instrs++; \ - switch(inst_base->idx) { \ - case 0: goto VMLA_INST; \ - case 1: goto VMLS_INST; \ - case 2: goto VNMLA_INST; \ - case 3: goto VNMLS_INST; \ - case 4: goto VNMUL_INST; \ - case 5: goto VMUL_INST; \ - case 6: goto VADD_INST; \ - case 7: goto VSUB_INST; \ - case 8: goto VDIV_INST; \ - case 9: goto VMOVI_INST; \ - case 10: goto VMOVR_INST; \ - case 11: goto VABS_INST; \ - case 12: goto VNEG_INST; \ - case 13: goto VSQRT_INST; \ - case 14: goto VCMP_INST; \ - case 15: goto VCMP2_INST; \ - case 16: goto VCVTBDS_INST; \ - case 17: goto VCVTBFF_INST; \ - case 18: goto VCVTBFI_INST; \ - case 19: goto VMOVBRS_INST; \ - case 20: goto VMSR_INST; \ - case 21: goto VMOVBRC_INST; \ - case 22: goto VMRS_INST; \ - case 23: goto VMOVBCR_INST; \ - case 24: goto VMOVBRRSS_INST; \ - case 25: goto VMOVBRRD_INST; \ - case 26: goto VSTR_INST; \ - case 27: goto VPUSH_INST; \ - case 28: goto VSTM_INST; \ - case 29: goto VPOP_INST; \ - case 30: goto VLDR_INST; \ - case 31: goto VLDM_INST ; \ - case 32: goto SRS_INST; \ - case 33: goto RFE_INST; \ - case 34: goto BKPT_INST; \ - case 35: goto BLX_INST; \ - case 36: goto CPS_INST; \ - case 37: goto PLD_INST; \ - case 38: goto SETEND_INST; \ - case 39: goto CLREX_INST; \ - case 40: goto REV16_INST; \ - case 41: goto USAD8_INST; \ - case 42: goto SXTB_INST; \ - case 43: goto UXTB_INST; \ - case 44: goto SXTH_INST; \ - case 45: goto SXTB16_INST; \ - case 46: goto UXTH_INST; \ - case 47: goto UXTB16_INST; \ - case 48: goto CPY_INST; \ - case 49: goto UXTAB_INST; \ - case 50: goto SSUB8_INST; \ - case 51: goto SHSUB8_INST; \ - case 52: goto SSUBADDX_INST; \ - case 53: goto STREX_INST; \ - case 54: goto STREXB_INST; \ - case 55: goto SWP_INST; \ - case 56: goto SWPB_INST; \ - case 57: goto SSUB16_INST; \ - case 58: goto SSAT16_INST; \ - case 59: goto SHSUBADDX_INST; \ - case 60: goto QSUBADDX_INST; \ - case 61: goto SHADDSUBX_INST; \ - case 62: goto SHADD8_INST; \ - case 63: goto SHADD16_INST; \ - case 64: goto SEL_INST; \ - case 65: goto SADDSUBX_INST; \ - case 66: goto SADD8_INST; \ - case 67: goto SADD16_INST; \ - case 68: goto SHSUB16_INST; \ - case 69: goto UMAAL_INST; \ - case 70: goto UXTAB16_INST; \ - case 71: goto USUBADDX_INST; \ - case 72: goto USUB8_INST; \ - case 73: goto USUB16_INST; \ - case 74: goto USAT16_INST; \ - case 75: goto USADA8_INST; \ - case 76: goto UQSUBADDX_INST; \ - case 77: goto UQSUB8_INST; \ - case 78: goto UQSUB16_INST; \ - case 79: goto UQADDSUBX_INST; \ - case 80: goto UQADD8_INST; \ - case 81: goto UQADD16_INST; \ - case 82: goto SXTAB_INST; \ - case 83: goto UHSUBADDX_INST; \ - case 84: goto UHSUB8_INST; \ - case 85: goto UHSUB16_INST; \ - case 86: goto UHADDSUBX_INST; \ - case 87: goto UHADD8_INST; \ - case 88: goto UHADD16_INST; \ - case 89: goto UADDSUBX_INST; \ - case 90: goto UADD8_INST; \ - case 91: goto UADD16_INST; \ - case 92: goto SXTAH_INST; \ - case 93: goto SXTAB16_INST; \ - case 94: goto QADD8_INST; \ - case 95: goto BXJ_INST; \ - case 96: goto CLZ_INST; \ - case 97: goto UXTAH_INST; \ - case 98: goto BX_INST; \ - case 99: goto REV_INST; \ - case 100: goto BLX_INST; \ - case 101: goto REVSH_INST; \ - case 102: goto QADD_INST; \ - case 103: goto QADD16_INST; \ - case 104: goto QADDSUBX_INST; \ - case 105: goto LDREX_INST; \ - case 106: goto QDADD_INST; \ - case 107: goto QDSUB_INST; \ - case 108: goto QSUB_INST; \ - case 109: goto LDREXB_INST; \ - case 110: goto QSUB8_INST; \ - case 111: goto QSUB16_INST; \ - case 112: goto SMUAD_INST; \ - case 113: goto SMMUL_INST; \ - case 114: goto SMUSD_INST; \ - case 115: goto SMLSD_INST; \ - case 116: goto SMLSLD_INST; \ - case 117: goto SMMLA_INST; \ - case 118: goto SMMLS_INST; \ - case 119: goto SMLALD_INST; \ - case 120: goto SMLAD_INST; \ - case 121: goto SMLAW_INST; \ - case 122: goto SMULW_INST; \ - case 123: goto PKHTB_INST; \ - case 124: goto PKHBT_INST; \ - case 125: goto SMUL_INST; \ - case 126: goto SMLALXY_INST; \ - case 127: goto SMLA_INST; \ - case 128: goto MCRR_INST; \ - case 129: goto MRRC_INST; \ - case 130: goto CMP_INST; \ - case 131: goto TST_INST; \ - case 132: goto TEQ_INST; \ - case 133: goto CMN_INST; \ - case 134: goto SMULL_INST; \ - case 135: goto UMULL_INST; \ - case 136: goto UMLAL_INST; \ - case 137: goto SMLAL_INST; \ - case 138: goto MUL_INST; \ - case 139: goto MLA_INST; \ - case 140: goto SSAT_INST; \ - case 141: goto USAT_INST; \ - case 142: goto MRS_INST; \ - case 143: goto MSR_INST; \ - case 144: goto AND_INST; \ - case 145: goto BIC_INST; \ - case 146: goto LDM_INST; \ - case 147: goto EOR_INST; \ - case 148: goto ADD_INST; \ - case 149: goto RSB_INST; \ - case 150: goto RSC_INST; \ - case 151: goto SBC_INST; \ - case 152: goto ADC_INST; \ - case 153: goto SUB_INST; \ - case 154: goto ORR_INST; \ - case 155: goto MVN_INST; \ - case 156: goto MOV_INST; \ - case 157: goto STM_INST; \ - case 158: goto LDM_INST; \ - case 159: goto LDRSH_INST; \ - case 160: goto STM_INST; \ - case 161: goto LDM_INST; \ - case 162: goto LDRSB_INST; \ - case 163: goto STRD_INST; \ - case 164: goto LDRH_INST; \ - case 165: goto STRH_INST; \ - case 166: goto LDRD_INST; \ - case 167: goto STRT_INST; \ - case 168: goto STRBT_INST; \ - case 169: goto LDRBT_INST; \ - case 170: goto LDRT_INST; \ - case 171: goto MRC_INST; \ - case 172: goto MCR_INST; \ - case 173: goto MSR_INST; \ - case 174: goto MSR_INST; \ - case 175: goto MSR_INST; \ - case 176: goto MSR_INST; \ - case 177: goto MSR_INST; \ - case 178: goto LDRB_INST; \ - case 179: goto STRB_INST; \ - case 180: goto LDR_INST; \ - case 181: goto LDRCOND_INST ; \ - case 182: goto STR_INST; \ - case 183: goto CDP_INST; \ - case 184: goto STC_INST; \ - case 185: goto LDC_INST; \ - case 186: goto LDREXD_INST; \ - case 187: goto STREXD_INST; \ - case 188: goto LDREXH_INST; \ - case 189: goto STREXH_INST; \ - case 190: goto NOP_INST; \ - case 191: goto YIELD_INST; \ - case 192: goto WFE_INST; \ - case 193: goto WFI_INST; \ - case 194: goto SEV_INST; \ - case 195: goto SWI_INST; \ - case 196: goto BBL_INST; \ - case 197: goto B_2_THUMB ; \ - case 198: goto B_COND_THUMB ; \ - case 199: goto BL_1_THUMB ; \ - case 200: goto BL_2_THUMB ; \ - case 201: goto BLX_1_THUMB ; \ - case 202: goto DISPATCH; \ - case 203: goto INIT_INST_LENGTH; \ - case 204: goto END; \ - } - - #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) - #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) - #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out) - - #define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \ - (cpu->NFlag << 31) | \ - (cpu->ZFlag << 30) | \ - (cpu->CFlag << 29) | \ - (cpu->VFlag << 28) | \ - (cpu->TFlag << 5) - #define LOAD_NZCVT cpu->NFlag = (cpu->Cpsr >> 31); \ - cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \ - cpu->CFlag = (cpu->Cpsr >> 29) & 1; \ - cpu->VFlag = (cpu->Cpsr >> 28) & 1; \ - cpu->TFlag = (cpu->Cpsr >> 5) & 1; - - #define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE) - #define PC (cpu->Reg[15]) - - arm_inst* inst_base; - unsigned int addr; - unsigned int num_instrs = 0; - - int ptr; - - LOAD_NZCVT; - DISPATCH: - { - if (num_instrs >= cpu->NumInstrsToExecute) - goto END; - - if (!cpu->NirqSig) { - if (!(cpu->Cpsr & 0x80)) { - goto END; - } - } - - if (cpu->TFlag) - cpu->Reg[15] &= 0xfffffffe; - else - cpu->Reg[15] &= 0xfffffffc; - - // Find the cached instruction cream, otherwise translate it... - auto itr = cpu->instruction_cache.find(cpu->Reg[15]); - if (itr != cpu->instruction_cache.end()) { - ptr = itr->second; - } else if (cpu->NumInstrsToExecute != 1) { - if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) - goto END; - } else { - if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) - goto END; - } - - // Find breakpoint if one exists within the block -// if (GDBStub::g_server_enabled && GDBStub::IsConnected()) { -// breakpoint_data = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); -// } - - inst_base = (arm_inst *)&trans_cache_buf[ptr]; - GOTO_NEXT_INST; - } - ADC_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - adc_inst* const inst_cream = (adc_inst*)inst_base->component; - - u32 rn_val = RN; - if (inst_cream->Rn == 15) - rn_val += 2 * cpu->GetInstructionSize(); - - bool carry; - bool overflow; - RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - cpu->CFlag = carry; - cpu->VFlag = overflow; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(adc_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(adc_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - ADD_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - add_inst* const inst_cream = (add_inst*)inst_base->component; - - u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn); - - bool carry; - bool overflow; - RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - cpu->CFlag = carry; - cpu->VFlag = overflow; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(add_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(add_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - AND_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - and_inst* const inst_cream = (and_inst*)inst_base->component; - - u32 lop = RN; - u32 rop = SHIFTER_OPERAND; - - if (inst_cream->Rn == 15) - lop += 2 * cpu->GetInstructionSize(); - - RD = lop & rop; - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - UPDATE_CFLAG_WITH_SC; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(and_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(and_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - BBL_INST: - { - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - bbl_inst *inst_cream = (bbl_inst *)inst_base->component; - if (inst_cream->L) { - LINK_RTN_ADDR; - } - SET_PC; - INC_PC(sizeof(bbl_inst)); - goto DISPATCH; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(bbl_inst)); - goto DISPATCH; - } - BIC_INST: - { - bic_inst *inst_cream = (bic_inst *)inst_base->component; - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - u32 lop = RN; - if (inst_cream->Rn == 15) { - lop += 2 * cpu->GetInstructionSize(); - } - u32 rop = SHIFTER_OPERAND; - RD = lop & (~rop); - if ((inst_cream->S) && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - UPDATE_CFLAG_WITH_SC; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(bic_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(bic_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - BKPT_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { -// bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; -// LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(bkpt_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - BLX_INST: - { - blx_inst *inst_cream = (blx_inst *)inst_base->component; - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - unsigned int inst = inst_cream->inst; - if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { - const u32 jump_address = cpu->Reg[inst_cream->val.Rm]; - cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); - if(cpu->TFlag) - cpu->Reg[14] |= 0x1; - cpu->Reg[15] = jump_address & 0xfffffffe; - cpu->TFlag = jump_address & 0x1; - } else { - cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize()); - cpu->TFlag = 0x1; - int signed_int = inst_cream->val.signed_immed_24; - signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int; - signed_int = signed_int << 2; - cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1); - } - INC_PC(sizeof(blx_inst)); - goto DISPATCH; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(blx_inst)); - goto DISPATCH; - } - - BX_INST: - BXJ_INST: - { - // Note that only the 'fail' case of BXJ is emulated. This is because - // the facilities for Jazelle emulation are not implemented. - // - // According to the ARM documentation on BXJ, if setting the J bit in the APSR - // fails, then BXJ functions identically like a regular BX instruction. - // - // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle. - - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - bx_inst* const inst_cream = (bx_inst*)inst_base->component; - - u32 address = RM; - - if (inst_cream->Rm == 15) - address += 2 * cpu->GetInstructionSize(); - - cpu->TFlag = address & 1; - cpu->Reg[15] = address & 0xfffffffe; - INC_PC(sizeof(bx_inst)); - goto DISPATCH; - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(bx_inst)); - goto DISPATCH; - } - - CDP_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - // Undefined instruction here - cpu->NumInstrsToExecute = 0; - return num_instrs; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(cdp_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - CLREX_INST: - { - cpu->UnsetExclusiveMemoryAddress(); - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(clrex_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - CLZ_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - clz_inst* inst_cream = (clz_inst*)inst_base->component; - RD = clz(RM); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(clz_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - CMN_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; - - u32 rn_val = RN; - if (inst_cream->Rn == 15) - rn_val += 2 * cpu->GetInstructionSize(); - - bool carry; - bool overflow; - u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); - - UPDATE_NFLAG(result); - UPDATE_ZFLAG(result); - cpu->CFlag = carry; - cpu->VFlag = overflow; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(cmn_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - CMP_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - cmp_inst* const inst_cream = (cmp_inst*)inst_base->component; - - u32 rn_val = RN; - if (inst_cream->Rn == 15) - rn_val += 2 * cpu->GetInstructionSize(); - - bool carry; - bool overflow; - u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); - - UPDATE_NFLAG(result); - UPDATE_ZFLAG(result); - cpu->CFlag = carry; - cpu->VFlag = overflow; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(cmp_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - CPS_INST: - { - cps_inst *inst_cream = (cps_inst *)inst_base->component; - u32 aif_val = 0; - u32 aif_mask = 0; - if (cpu->InAPrivilegedMode()) { - if (inst_cream->imod1) { - if (inst_cream->A) { - aif_val |= (inst_cream->imod0 << 8); - aif_mask |= 1 << 8; - } - if (inst_cream->I) { - aif_val |= (inst_cream->imod0 << 7); - aif_mask |= 1 << 7; - } - if (inst_cream->F) { - aif_val |= (inst_cream->imod0 << 6); - aif_mask |= 1 << 6; - } - aif_mask = ~aif_mask; - cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val; - } - if (inst_cream->mmod) { - cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode; - cpu->ChangePrivilegeMode(inst_cream->mode); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(cps_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - CPY_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mov_inst* inst_cream = (mov_inst*)inst_base->component; - - RD = SHIFTER_OPERAND; - if (inst_cream->Rd == 15) { - INC_PC(sizeof(mov_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mov_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - EOR_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - eor_inst* inst_cream = (eor_inst*)inst_base->component; - - u32 lop = RN; - if (inst_cream->Rn == 15) { - lop += 2 * cpu->GetInstructionSize(); - } - u32 rop = SHIFTER_OPERAND; - RD = lop ^ rop; - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - UPDATE_CFLAG_WITH_SC; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(eor_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(eor_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDC_INST: - { - // Instruction not implemented - //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldc_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDM_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - unsigned int inst = inst_cream->inst; - if (BIT(inst, 22) && !BIT(inst, 15)) { - for (int i = 0; i < 13; i++) { - if(BIT(inst, i)) { - cpu->Reg[i] = cpu->ReadMemory32(addr); - addr += 4; - } - } - if (BIT(inst, 13)) { - if (cpu->Mode == USER32MODE) - cpu->Reg[13] = cpu->ReadMemory32(addr); - else - cpu->Reg_usr[0] = cpu->ReadMemory32(addr); - - addr += 4; - } - if (BIT(inst, 14)) { - if (cpu->Mode == USER32MODE) - cpu->Reg[14] = cpu->ReadMemory32(addr); - else - cpu->Reg_usr[1] = cpu->ReadMemory32(addr); - - addr += 4; - } - } else if (!BIT(inst, 22)) { - for(int i = 0; i < 16; i++ ){ - if(BIT(inst, i)){ - unsigned int ret = cpu->ReadMemory32(addr); - - // For armv5t, should enter thumb when bits[0] is non-zero. - if(i == 15){ - cpu->TFlag = ret & 0x1; - ret &= 0xFFFFFFFE; - } - - cpu->Reg[i] = ret; - addr += 4; - } - } - } else if (BIT(inst, 22) && BIT(inst, 15)) { - for(int i = 0; i < 15; i++ ){ - if(BIT(inst, i)){ - cpu->Reg[i] = cpu->ReadMemory32(addr); - addr += 4; - } - } - - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); - LOAD_NZCVT; - } - - cpu->Reg[15] = cpu->ReadMemory32(addr); - } - - if (BIT(inst, 15)) { - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - SXTH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - sxth_inst* inst_cream = (sxth_inst*)inst_base->component; - - unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); - if (BIT(operand2, 15)) { - operand2 |= 0xffff0000; - } else { - operand2 &= 0xffff; - } - RD = operand2; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(sxth_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDR_INST: - { - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - unsigned int value = cpu->ReadMemory32(addr); - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; - - if (BITS(inst_cream->inst, 12, 15) == 15) { - // For armv5t, should enter thumb when bits[0] is non-zero. - cpu->TFlag = value & 0x1; - cpu->Reg[15] &= 0xFFFFFFFE; - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDRCOND_INST: - { - if (CondPassed(cpu, inst_base->cond)) { - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - unsigned int value = cpu->ReadMemory32(addr); - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; - - if (BITS(inst_cream->inst, 12, 15) == 15) { - // For armv5t, should enter thumb when bits[0] is non-zero. - cpu->TFlag = value & 0x1; - cpu->Reg[15] &= 0xFFFFFFFE; - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - UXTH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - uxth_inst* inst_cream = (uxth_inst*)inst_base->component; - RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(uxth_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - UXTAH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component; - unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; - - RD = RN + operand2; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(uxtah_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDRB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDRBT_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - const u32 dest_index = BITS(inst_cream->inst, 12, 15); - const u32 previous_mode = cpu->Mode; - - cpu->ChangePrivilegeMode(USER32MODE); - const u8 value = cpu->ReadMemory8(addr); - cpu->ChangePrivilegeMode(previous_mode); - - cpu->Reg[dest_index] = value; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDRD_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0) - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - // The 3DS doesn't have LPAE (Large Physical Access Extension), so it - // wouldn't do this as a single read. - cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr); - cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4); - - // No dispatch since this operation should not modify R15 - } - cpu->Reg[15] += 4; - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - LDREX_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - unsigned int read_addr = RN; - - cpu->SetExclusiveMemoryAddress(read_addr); - - RD = cpu->ReadMemory32(read_addr); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDREXB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - unsigned int read_addr = RN; - - cpu->SetExclusiveMemoryAddress(read_addr); - - RD = cpu->ReadMemory8(read_addr); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDREXH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - unsigned int read_addr = RN; - - cpu->SetExclusiveMemoryAddress(read_addr); - - RD = cpu->ReadMemory16(read_addr); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDREXD_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - unsigned int read_addr = RN; - - cpu->SetExclusiveMemoryAddress(read_addr); - - RD = cpu->ReadMemory32(read_addr); - RD2 = cpu->ReadMemory32(read_addr + 4); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDRH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDRSB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - unsigned int value = cpu->ReadMemory8(addr); - if (BIT(value, 7)) { - value |= 0xffffff00; - } - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDRSH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - unsigned int value = cpu->ReadMemory16(addr); - if (BIT(value, 15)) { - value |= 0xffff0000; - } - cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - LDRT_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - const u32 dest_index = BITS(inst_cream->inst, 12, 15); - const u32 previous_mode = cpu->Mode; - - cpu->ChangePrivilegeMode(USER32MODE); - const u32 value = cpu->ReadMemory32(addr); - cpu->ChangePrivilegeMode(previous_mode); - - cpu->Reg[dest_index] = value; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - MCR_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mcr_inst* inst_cream = (mcr_inst*)inst_base->component; - -// unsigned int inst = inst_cream->inst; - if (inst_cream->Rd == 15) { - DEBUG_MSG; - } else { - if (inst_cream->cp_num == 15) - cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mcr_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - MCRR_INST: - { - // Stubbed, as the MPCore doesn't have any registers that are accessible - // through this instruction. - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; - -// LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", -// inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); - ASSERT_MSG(false, "MCRR executed | Coprocessor: {}, CRm {}, opc1: {}, Rt: {}, Rt2: {}", - inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mcrr_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - MLA_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mla_inst* inst_cream = (mla_inst*)inst_base->component; - - u64 rm = RM; - u64 rs = RS; - u64 rn = RN; - - RD = static_cast((rm * rs + rn) & 0xffffffff); - if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mla_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - MOV_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mov_inst* inst_cream = (mov_inst*)inst_base->component; - - RD = SHIFTER_OPERAND; - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - UPDATE_CFLAG_WITH_SC; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(mov_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mov_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - MRC_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mrc_inst* inst_cream = (mrc_inst*)inst_base->component; - - if (inst_cream->cp_num == 15) { - const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2); - - if (inst_cream->Rd == 15) { - cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000); - LOAD_NZCVT; - } else { - RD = value; - } - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mrc_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - MRRC_INST: - { - // Stubbed, as the MPCore doesn't have any registers that are accessible - // through this instruction. - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; - -// LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", -// inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); - ASSERT_MSG(false, "MRRC executed | Coprocessor: {}, CRm {}, opc1: {}, Rt: {}, Rt2: {}", - inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mcrr_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - MRS_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mrs_inst* inst_cream = (mrs_inst*)inst_base->component; - - if (inst_cream->R) { - RD = cpu->Spsr_copy; - } else { - SAVE_NZCVT; - RD = cpu->Cpsr; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mrs_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - MSR_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - msr_inst* inst_cream = (msr_inst*)inst_base->component; - const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; - unsigned int inst = inst_cream->inst; - unsigned int operand; - - if (BIT(inst, 25)) { - int rot_imm = BITS(inst, 8, 11) * 2; - operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); - } else { - operand = cpu->Reg[BITS(inst, 0, 3)]; - } - u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) - | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); - u32 mask = 0; - if (!inst_cream->R) { - if (cpu->InAPrivilegedMode()) { - if ((operand & StateMask) != 0) { - /// UNPREDICTABLE - DEBUG_MSG; - } else - mask = byte_mask & (UserMask | PrivMask); - } else { - mask = byte_mask & UserMask; - } - SAVE_NZCVT; - - cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); - cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); - LOAD_NZCVT; - } else { - if (CurrentModeHasSPSR) { - mask = byte_mask & (UserMask | PrivMask | StateMask); - cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); - } - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(msr_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - MUL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mul_inst* inst_cream = (mul_inst*)inst_base->component; - - u64 rm = RM; - u64 rs = RS; - RD = static_cast((rm * rs) & 0xffffffff); - if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mul_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - MVN_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - mvn_inst* const inst_cream = (mvn_inst*)inst_base->component; - - RD = ~SHIFTER_OPERAND; - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - UPDATE_CFLAG_WITH_SC; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(mvn_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(mvn_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - ORR_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - orr_inst* const inst_cream = (orr_inst*)inst_base->component; - - u32 lop = RN; - u32 rop = SHIFTER_OPERAND; - - if (inst_cream->Rn == 15) - lop += 2 * cpu->GetInstructionSize(); - - RD = lop | rop; - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - UPDATE_CFLAG_WITH_SC; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(orr_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(orr_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - NOP_INST: - { - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC_STUB; - FETCH_INST; - GOTO_NEXT_INST; - } - - PKHBT_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - pkh_inst *inst_cream = (pkh_inst *)inst_base->component; - RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(pkh_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - PKHTB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - pkh_inst *inst_cream = (pkh_inst *)inst_base->component; - int shift_imm = inst_cream->imm ? inst_cream->imm : 31; - RD = ((static_cast(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(pkh_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - PLD_INST: - { - // Not implemented. PLD is a hint instruction, so it's optional. - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(pld_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - QADD_INST: - QDADD_INST: - QDSUB_INST: - QSUB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - const u8 op1 = inst_cream->op1; - const u32 rm_val = RM; - const u32 rn_val = RN; - - u32 result = 0; - - // QADD - if (op1 == 0x00) { - result = rm_val + rn_val; - - if (AddOverflow(rm_val, rn_val, result)) { - result = POS(result) ? 0x80000000 : 0x7FFFFFFF; - cpu->Cpsr |= (1 << 27); - } - } - // QSUB - else if (op1 == 0x01) { - result = rm_val - rn_val; - - if (SubOverflow(rm_val, rn_val, result)) { - result = POS(result) ? 0x80000000 : 0x7FFFFFFF; - cpu->Cpsr |= (1 << 27); - } - } - // QDADD - else if (op1 == 0x02) { - u32 mul = (rn_val * 2); - - if (AddOverflow(rn_val, rn_val, rn_val * 2)) { - mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; - cpu->Cpsr |= (1 << 27); - } - - result = mul + rm_val; - - if (AddOverflow(rm_val, mul, result)) { - result = POS(result) ? 0x80000000 : 0x7FFFFFFF; - cpu->Cpsr |= (1 << 27); - } - } - // QDSUB - else if (op1 == 0x03) { - u32 mul = (rn_val * 2); - - if (AddOverflow(rn_val, rn_val, mul)) { - mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; - cpu->Cpsr |= (1 << 27); - } - - result = rm_val - mul; - - if (SubOverflow(rm_val, mul, result)) { - result = POS(result) ? 0x80000000 : 0x7FFFFFFF; - cpu->Cpsr |= (1 << 27); - } - } - - RD = result; - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - QADD8_INST: - QADD16_INST: - QADDSUBX_INST: - QSUB8_INST: - QSUB16_INST: - QSUBADDX_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - const u16 rm_lo = (RM & 0xFFFF); - const u16 rm_hi = ((RM >> 16) & 0xFFFF); - const u16 rn_lo = (RN & 0xFFFF); - const u16 rn_hi = ((RN >> 16) & 0xFFFF); - const u8 op2 = inst_cream->op2; - - u16 lo_result = 0; - u16 hi_result = 0; - - // QADD16 - if (op2 == 0x00) { - lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo); - hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi); - } - // QASX - else if (op2 == 0x01) { - lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi); - hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo); - } - // QSAX - else if (op2 == 0x02) { - lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi); - hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo); - } - // QSUB16 - else if (op2 == 0x03) { - lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo); - hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi); - } - // QADD8 - else if (op2 == 0x04) { - lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) | - ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8; - hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) | - ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8; - } - // QSUB8 - else if (op2 == 0x07) { - lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) | - ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8; - hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) | - ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8; - } - - RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - REV_INST: - REV16_INST: - REVSH_INST: - { - - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - rev_inst* const inst_cream = (rev_inst*)inst_base->component; - - const u8 op1 = inst_cream->op1; - const u8 op2 = inst_cream->op2; - - // REV - if (op1 == 0x03 && op2 == 0x01) { - RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) | ((RM >> 24) & 0xFF); - } - // REV16 - else if (op1 == 0x03 && op2 == 0x05) { - RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) | ((RM & 0xFF000000) >> 8); - } - // REVSH - else if (op1 == 0x07 && op2 == 0x05) { - RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8); - if (RD & 0x8000) - RD |= 0xffff0000; - } - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(rev_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - RFE_INST: - { - // RFE is unconditional - ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; - - u32 address = 0; - inst_cream->get_addr(cpu, inst_cream->inst, address); - - cpu->Cpsr = cpu->ReadMemory32(address); - cpu->Reg[15] = cpu->ReadMemory32(address + 4); - - INC_PC(sizeof(ldst_inst)); - goto DISPATCH; - } - - RSB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - rsb_inst* const inst_cream = (rsb_inst*)inst_base->component; - - u32 rn_val = RN; - if (inst_cream->Rn == 15) - rn_val += 2 * cpu->GetInstructionSize(); - - bool carry; - bool overflow; - RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow); - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - cpu->CFlag = carry; - cpu->VFlag = overflow; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(rsb_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(rsb_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - RSC_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; - - u32 rn_val = RN; - if (inst_cream->Rn == 15) - rn_val += 2 * cpu->GetInstructionSize(); - - bool carry; - bool overflow; - RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - cpu->CFlag = carry; - cpu->VFlag = overflow; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(rsc_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(rsc_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SADD8_INST: - SSUB8_INST: - SADD16_INST: - SADDSUBX_INST: - SSUBADDX_INST: - SSUB16_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - const u8 op2 = inst_cream->op2; - - if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { - const s16 rn_lo = (RN & 0xFFFF); - const s16 rn_hi = ((RN >> 16) & 0xFFFF); - const s16 rm_lo = (RM & 0xFFFF); - const s16 rm_hi = ((RM >> 16) & 0xFFFF); - - s32 lo_result = 0; - s32 hi_result = 0; - - // SADD16 - if (inst_cream->op2 == 0x00) { - lo_result = (rn_lo + rm_lo); - hi_result = (rn_hi + rm_hi); - } - // SASX - else if (op2 == 0x01) { - lo_result = (rn_lo - rm_hi); - hi_result = (rn_hi + rm_lo); - } - // SSAX - else if (op2 == 0x02) { - lo_result = (rn_lo + rm_hi); - hi_result = (rn_hi - rm_lo); - } - // SSUB16 - else if (op2 == 0x03) { - lo_result = (rn_lo - rm_lo); - hi_result = (rn_hi - rm_hi); - } - - RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); - - if (lo_result >= 0) { - cpu->Cpsr |= (1 << 16); - cpu->Cpsr |= (1 << 17); - } else { - cpu->Cpsr &= ~(1 << 16); - cpu->Cpsr &= ~(1 << 17); - } - - if (hi_result >= 0) { - cpu->Cpsr |= (1 << 18); - cpu->Cpsr |= (1 << 19); - } else { - cpu->Cpsr &= ~(1 << 18); - cpu->Cpsr &= ~(1 << 19); - } - } - else if (op2 == 0x04 || op2 == 0x07) { - s32 lo_val1, lo_val2; - s32 hi_val1, hi_val2; - - // SADD8 - if (op2 == 0x04) { - lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF); - lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF); - hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF); - hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF); - } - // SSUB8 - else { - lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF); - lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF); - hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF); - hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF); - } - - RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24)); - - if (lo_val1 >= 0) - cpu->Cpsr |= (1 << 16); - else - cpu->Cpsr &= ~(1 << 16); - - if (lo_val2 >= 0) - cpu->Cpsr |= (1 << 17); - else - cpu->Cpsr &= ~(1 << 17); - - if (hi_val1 >= 0) - cpu->Cpsr |= (1 << 18); - else - cpu->Cpsr &= ~(1 << 18); - - if (hi_val2 >= 0) - cpu->Cpsr |= (1 << 19); - else - cpu->Cpsr &= ~(1 << 19); - } - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SBC_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; - - u32 rn_val = RN; - if (inst_cream->Rn == 15) - rn_val += 2 * cpu->GetInstructionSize(); - - bool carry; - bool overflow; - RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - cpu->CFlag = carry; - cpu->VFlag = overflow; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(sbc_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(sbc_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SEL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - const u32 to = RM; - const u32 from = RN; - const u32 cpsr = cpu->Cpsr; - - u32 result; - if (cpsr & (1 << 16)) - result = from & 0xff; - else - result = to & 0xff; - - if (cpsr & (1 << 17)) - result |= from & 0x0000ff00; - else - result |= to & 0x0000ff00; - - if (cpsr & (1 << 18)) - result |= from & 0x00ff0000; - else - result |= to & 0x00ff0000; - - if (cpsr & (1 << 19)) - result |= from & 0xff000000; - else - result |= to & 0xff000000; - - RD = result; - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SETEND_INST: - { - // SETEND is unconditional - setend_inst* const inst_cream = (setend_inst*)inst_base->component; - const bool big_endian = (inst_cream->set_bigend == 1); - - if (big_endian) - cpu->Cpsr |= (1 << 9); - else - cpu->Cpsr &= ~(1 << 9); - -// LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(setend_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SEV_INST: - { - // Stubbed, as SEV is a hint instruction. - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - LOG_TRACE(Core_ARM11, "SEV executed."); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC_STUB; - FETCH_INST; - GOTO_NEXT_INST; - } - - SHADD8_INST: - SHADD16_INST: - SHADDSUBX_INST: - SHSUB8_INST: - SHSUB16_INST: - SHSUBADDX_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - const u8 op2 = inst_cream->op2; - const u32 rm_val = RM; - const u32 rn_val = RN; - - if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { - s32 lo_result = 0; - s32 hi_result = 0; - - // SHADD16 - if (op2 == 0x00) { - lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; - hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1; - } - // SHASX - else if (op2 == 0x01) { - lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1; - hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; - } - // SHSAX - else if (op2 == 0x02) { - lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1; - hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1; - } - // SHSUB16 - else if (op2 == 0x03) { - lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1; - hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1; - } - - RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16)); - } - else if (op2 == 0x04 || op2 == 0x07) { - s16 lo_val1, lo_val2; - s16 hi_val1, hi_val2; - - // SHADD8 - if (op2 == 0x04) { - lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1; - lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1; - - hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1; - hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1; - } - // SHSUB8 - else { - lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1; - lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1; - - hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1; - hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1; - } - - RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24); - } - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMLA_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - smla_inst* inst_cream = (smla_inst*)inst_base->component; - s32 operand1, operand2; - if (inst_cream->x == 0) - operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); - else - operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31); - - if (inst_cream->y == 0) - operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); - else - operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); - - u32 product = operand1 * operand2; - u32 result = product + RN; - if (AddOverflow(product, RN, result)) - cpu->Cpsr |= (1 << 27); - RD = result; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(smla_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMLAD_INST: - SMLSD_INST: - SMUAD_INST: - SMUSD_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - const u8 op2 = inst_cream->op2; - - u32 rm_val = cpu->Reg[inst_cream->Rm]; - const u32 rn_val = cpu->Reg[inst_cream->Rn]; - - if (inst_cream->m) - rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); - - const s16 rm_lo = (rm_val & 0xFFFF); - const s16 rm_hi = ((rm_val >> 16) & 0xFFFF); - const s16 rn_lo = (rn_val & 0xFFFF); - const s16 rn_hi = ((rn_val >> 16) & 0xFFFF); - - const u32 product1 = (rn_lo * rm_lo); - const u32 product2 = (rn_hi * rm_hi); - - // SMUAD and SMLAD - if (BIT(op2, 1) == 0) { - u32 rd_val = (product1 + product2); - - if (inst_cream->Ra != 15) { - rd_val += cpu->Reg[inst_cream->Ra]; - - if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra])) - cpu->Cpsr |= (1 << 27); - } - - RD = rd_val; - - if (ARMul_AddOverflowQ(product1, product2)) - cpu->Cpsr |= (1 << 27); - } - // SMUSD and SMLSD - else { - u32 rd_val = (product1 - product2); - - if (inst_cream->Ra != 15) { - rd_val += cpu->Reg[inst_cream->Ra]; - - if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra])) - cpu->Cpsr |= (1 << 27); - } - - RD = rd_val; - } - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(smlad_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMLAL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - umlal_inst* inst_cream = (umlal_inst*)inst_base->component; - long long int rm = RM; - long long int rs = RS; - if (BIT(rm, 31)) { - rm |= 0xffffffff00000000LL; - } - if (BIT(rs, 31)) { - rs |= 0xffffffff00000000LL; - } - long long int rst = rm * rs; - long long int rdhi32 = RDHI; - long long int hilo = (rdhi32 << 32) + RDLO; - rst += hilo; - RDLO = BITS(rst, 0, 31); - RDHI = BITS(rst, 32, 63); - if (inst_cream->S) { - cpu->NFlag = BIT(RDHI, 31); - cpu->ZFlag = (RDHI == 0 && RDLO == 0); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(umlal_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMLALXY_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; - - u64 operand1 = RN; - u64 operand2 = RM; - - if (inst_cream->x != 0) - operand1 >>= 16; - if (inst_cream->y != 0) - operand2 >>= 16; - operand1 &= 0xFFFF; - if (operand1 & 0x8000) - operand1 -= 65536; - operand2 &= 0xFFFF; - if (operand2 & 0x8000) - operand2 -= 65536; - - u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2); - RDLO = (dest & 0xFFFFFFFF); - RDHI = ((dest >> 32) & 0xFFFFFFFF); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(smlalxy_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMLAW_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - const u32 rm_val = RM; - const u32 rn_val = RN; - const u32 ra_val = cpu->Reg[inst_cream->Ra]; - const bool high = (inst_cream->m == 1); - - const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF); - const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16); - - RD = BITS(result, 16, 47); - - if ((result >> 16) != (s32)RD) - cpu->Cpsr |= (1 << 27); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(smlad_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMLALD_INST: - SMLSLD_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; - - const bool do_swap = (inst_cream->swap == 1); - const u32 rdlo_val = RDLO; - const u32 rdhi_val = RDHI; - const u32 rn_val = RN; - u32 rm_val = RM; - - if (do_swap) - rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); - - const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); - const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); - s64 result; - - // SMLALD - if (BIT(inst_cream->op2, 1) == 0) { - result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); - } - // SMLSLD - else { - result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); - } - - RDLO = (result & 0xFFFFFFFF); - RDHI = ((result >> 32) & 0xFFFFFFFF); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(smlald_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMMLA_INST: - SMMLS_INST: - SMMUL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - const u32 rm_val = RM; - const u32 rn_val = RN; - const bool do_round = (inst_cream->m == 1); - - // Assume SMMUL by default. - s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; - - if (inst_cream->Ra != 15) { - const u32 ra_val = cpu->Reg[inst_cream->Ra]; - - // SMMLA, otherwise SMMLS - if (BIT(inst_cream->op2, 1) == 0) - result += ((s64)ra_val << 32); - else - result = ((s64)ra_val << 32) - result; - } - - if (do_round) - result += 0x80000000; - - RD = ((result >> 32) & 0xFFFFFFFF); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(smlad_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMUL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - smul_inst* inst_cream = (smul_inst*)inst_base->component; - u32 operand1, operand2; - if (inst_cream->x == 0) - operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); - else - operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31); - - if (inst_cream->y == 0) - operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); - else - operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); - RD = operand1 * operand2; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(smul_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - SMULL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - umull_inst* inst_cream = (umull_inst*)inst_base->component; - s64 rm = RM; - s64 rs = RS; - if (BIT(rm, 31)) { - rm |= 0xffffffff00000000LL; - } - if (BIT(rs, 31)) { - rs |= 0xffffffff00000000LL; - } - s64 rst = rm * rs; - RDHI = BITS(rst, 32, 63); - RDLO = BITS(rst, 0, 31); - - if (inst_cream->S) { - cpu->NFlag = BIT(RDHI, 31); - cpu->ZFlag = (RDHI == 0 && RDLO == 0); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(umull_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SMULW_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF); - - s64 result = (s64)rm * (s64)(s32)RN; - RD = BITS(result, 16, 47); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(smlad_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SRS_INST: - { - // SRS is unconditional - ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; - - u32 address = 0; - inst_cream->get_addr(cpu, inst_cream->inst, address); - - cpu->WriteMemory32(address + 0, cpu->Reg[14]); - cpu->WriteMemory32(address + 4, cpu->Spsr_copy); - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SSAT_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; - - u8 shift_type = inst_cream->shift_type; - u8 shift_amount = inst_cream->imm5; - u32 rn_val = RN; - - // 32-bit ASR is encoded as an amount of 0. - if (shift_type == 1 && shift_amount == 0) - shift_amount = 31; - - if (shift_type == 0) - rn_val <<= shift_amount; - else if (shift_type == 1) - rn_val = ((s32)rn_val >> shift_amount); - - bool saturated = false; - rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated); - - if (saturated) - cpu->Cpsr |= (1 << 27); - - RD = rn_val; - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ssat_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SSAT16_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; - const u8 saturate_to = inst_cream->sat_imm; - - bool sat1 = false; - bool sat2 = false; - - RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | - ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; - - if (sat1 || sat2) - cpu->Cpsr |= (1 << 27); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ssat_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - STC_INST: - { - // Instruction not implemented - //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(stc_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STM_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - unsigned int inst = inst_cream->inst; - - unsigned int Rn = BITS(inst, 16, 19); - unsigned int old_RN = cpu->Reg[Rn]; - - inst_cream->get_addr(cpu, inst_cream->inst, addr); - if (BIT(inst_cream->inst, 22) == 1) { - for (int i = 0; i < 13; i++) { - if (BIT(inst_cream->inst, i)) { - cpu->WriteMemory32(addr, cpu->Reg[i]); - addr += 4; - } - } - if (BIT(inst_cream->inst, 13)) { - if (cpu->Mode == USER32MODE) - cpu->WriteMemory32(addr, cpu->Reg[13]); - else - cpu->WriteMemory32(addr, cpu->Reg_usr[0]); - - addr += 4; - } - if (BIT(inst_cream->inst, 14)) { - if (cpu->Mode == USER32MODE) - cpu->WriteMemory32(addr, cpu->Reg[14]); - else - cpu->WriteMemory32(addr, cpu->Reg_usr[1]); - - addr += 4; - } - if (BIT(inst_cream->inst, 15)) { - cpu->WriteMemory32(addr, cpu->Reg[15] + 8); - } - } else { - for (size_t i = 0; i < 15; i++) { - if (BIT(inst_cream->inst, i)) { - if (i == Rn) - cpu->WriteMemory32(addr, old_RN); - else - cpu->WriteMemory32(addr, cpu->Reg[i]); - - addr += 4; - } - } - - // Check PC reg - if (BIT(inst_cream->inst, 15)) { - cpu->WriteMemory32(addr, cpu->Reg[15] + 8); - } - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - SXTB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component; - - unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); - if (BIT(operand2, 7)) { - operand2 |= 0xffffff00; - } else { - operand2 &= 0xff; - } - RD = operand2; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(sxtb_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STR_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - unsigned int reg = BITS(inst_cream->inst, 12, 15); - unsigned int value = cpu->Reg[reg]; - - if (reg == 15) - value += 2 * cpu->GetInstructionSize(); - - cpu->WriteMemory32(addr, value); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - UXTB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component; - RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(uxtb_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - UXTAB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component; - - unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; - RD = RN + operand2; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(uxtab_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STRB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; - cpu->WriteMemory8(addr, value); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STRBT_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - const u32 previous_mode = cpu->Mode; - const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; - - cpu->ChangePrivilegeMode(USER32MODE); - cpu->WriteMemory8(addr, value); - cpu->ChangePrivilegeMode(previous_mode); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STRD_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - // The 3DS doesn't have the Large Physical Access Extension (LPAE) - // so STRD wouldn't store these as a single write. - cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]); - cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STREX_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - unsigned int write_addr = cpu->Reg[inst_cream->Rn]; - - if (cpu->IsExclusiveMemoryAccess(write_addr)) { - cpu->UnsetExclusiveMemoryAddress(); - cpu->WriteMemory32(write_addr, RM); - RD = 0; - } else { - // Failed to write due to mutex access - RD = 1; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STREXB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - unsigned int write_addr = cpu->Reg[inst_cream->Rn]; - - if (cpu->IsExclusiveMemoryAccess(write_addr)) { - cpu->UnsetExclusiveMemoryAddress(); - cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]); - RD = 0; - } else { - // Failed to write due to mutex access - RD = 1; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STREXD_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - unsigned int write_addr = cpu->Reg[inst_cream->Rn]; - - if (cpu->IsExclusiveMemoryAccess(write_addr)) { - cpu->UnsetExclusiveMemoryAddress(); - - const u32 rt = cpu->Reg[inst_cream->Rm + 0]; - const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; - u64 value; - - if (cpu->InBigEndianMode()) - value = (((u64)rt << 32) | rt2); - else - value = (((u64)rt2 << 32) | rt); - - cpu->WriteMemory64(write_addr, value); - RD = 0; - } - else { - // Failed to write due to mutex access - RD = 1; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STREXH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - unsigned int write_addr = cpu->Reg[inst_cream->Rn]; - - if (cpu->IsExclusiveMemoryAccess(write_addr)) { - cpu->UnsetExclusiveMemoryAddress(); - cpu->WriteMemory16(write_addr, RM); - RD = 0; - } else { - // Failed to write due to mutex access - RD = 1; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STRH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; - cpu->WriteMemory16(addr, value); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - STRT_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - inst_cream->get_addr(cpu, inst_cream->inst, addr); - - const u32 previous_mode = cpu->Mode; - const u32 rt_index = BITS(inst_cream->inst, 12, 15); - - u32 value = cpu->Reg[rt_index]; - if (rt_index == 15) - value += 2 * cpu->GetInstructionSize(); - - cpu->ChangePrivilegeMode(USER32MODE); - cpu->WriteMemory32(addr, value); - cpu->ChangePrivilegeMode(previous_mode); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ldst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - SUB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - sub_inst* const inst_cream = (sub_inst*)inst_base->component; - - u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn); - - bool carry; - bool overflow; - RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); - - if (inst_cream->S && (inst_cream->Rd == 15)) { - if (CurrentModeHasSPSR) { - cpu->Cpsr = cpu->Spsr_copy; - cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); - LOAD_NZCVT; - } - } else if (inst_cream->S) { - UPDATE_NFLAG(RD); - UPDATE_ZFLAG(RD); - cpu->CFlag = carry; - cpu->VFlag = overflow; - } - if (inst_cream->Rd == 15) { - INC_PC(sizeof(sub_inst)); - goto DISPATCH; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(sub_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - SWI_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - swi_inst* const inst_cream = (swi_inst*)inst_base->component; -// SVC::CallSVC(inst_cream->num & 0xFFFF); - cpu->user_callbacks->CallSVC(inst_cream->num & 0xFFFF); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(swi_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - SWP_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - swp_inst* inst_cream = (swp_inst*)inst_base->component; - - addr = RN; - unsigned int value = cpu->ReadMemory32(addr); - cpu->WriteMemory32(addr, RM); - - RD = value; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(swp_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - SWPB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - swp_inst* inst_cream = (swp_inst*)inst_base->component; - addr = RN; - unsigned int value = cpu->ReadMemory8(addr); - cpu->WriteMemory8(addr, (RM & 0xFF)); - RD = value; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(swp_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - SXTAB_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component; - - unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; - - // Sign extend for byte - operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2; - RD = RN + operand2; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(uxtab_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SXTAB16_INST: - SXTB16_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; - - const u8 rotation = inst_cream->rotate * 8; - u32 rm_val = RM; - u32 rn_val = RN; - - if (rotation) - rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); - - // SXTB16 - if (inst_cream->Rn == 15) { - u32 lo = (u32)(s8)rm_val; - u32 hi = (u32)(s8)(rm_val >> 16); - RD = (lo & 0xFFFF) | (hi << 16); - } - // SXTAB16 - else { - u32 lo = rn_val + (u32)(s8)(rm_val & 0xFF); - u32 hi = (rn_val >> 16) + (u32)(s8)((rm_val >> 16) & 0xFF); - RD = (lo & 0xFFFF) | (hi << 16); - } - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(sxtab_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - SXTAH_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component; - - unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; - // Sign extend for half - operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2; - RD = RN + operand2; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(sxtah_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - TEQ_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - teq_inst* const inst_cream = (teq_inst*)inst_base->component; - - u32 lop = RN; - u32 rop = SHIFTER_OPERAND; - - if (inst_cream->Rn == 15) - lop += cpu->GetInstructionSize() * 2; - - u32 result = lop ^ rop; - - UPDATE_NFLAG(result); - UPDATE_ZFLAG(result); - UPDATE_CFLAG_WITH_SC; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(teq_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - TST_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - tst_inst* const inst_cream = (tst_inst*)inst_base->component; - - u32 lop = RN; - u32 rop = SHIFTER_OPERAND; - - if (inst_cream->Rn == 15) - lop += cpu->GetInstructionSize() * 2; - - u32 result = lop & rop; - - UPDATE_NFLAG(result); - UPDATE_ZFLAG(result); - UPDATE_CFLAG_WITH_SC; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(tst_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - UADD8_INST: - UADD16_INST: - UADDSUBX_INST: - USUB8_INST: - USUB16_INST: - USUBADDX_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - const u8 op2 = inst_cream->op2; - const u32 rm_val = RM; - const u32 rn_val = RN; - - s32 lo_result = 0; - s32 hi_result = 0; - - // UADD16 - if (op2 == 0x00) { - lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); - hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); - - if (lo_result & 0xFFFF0000) { - cpu->Cpsr |= (1 << 16); - cpu->Cpsr |= (1 << 17); - } else { - cpu->Cpsr &= ~(1 << 16); - cpu->Cpsr &= ~(1 << 17); - } - - if (hi_result & 0xFFFF0000) { - cpu->Cpsr |= (1 << 18); - cpu->Cpsr |= (1 << 19); - } else { - cpu->Cpsr &= ~(1 << 18); - cpu->Cpsr &= ~(1 << 19); - } - } - // UASX - else if (op2 == 0x01) { - lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); - hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); - - if (lo_result >= 0) { - cpu->Cpsr |= (1 << 16); - cpu->Cpsr |= (1 << 17); - } else { - cpu->Cpsr &= ~(1 << 16); - cpu->Cpsr &= ~(1 << 17); - } - - if (hi_result >= 0x10000) { - cpu->Cpsr |= (1 << 18); - cpu->Cpsr |= (1 << 19); - } else { - cpu->Cpsr &= ~(1 << 18); - cpu->Cpsr &= ~(1 << 19); - } - } - // USAX - else if (op2 == 0x02) { - lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); - hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); - - if (lo_result >= 0x10000) { - cpu->Cpsr |= (1 << 16); - cpu->Cpsr |= (1 << 17); - } else { - cpu->Cpsr &= ~(1 << 16); - cpu->Cpsr &= ~(1 << 17); - } - - if (hi_result >= 0) { - cpu->Cpsr |= (1 << 18); - cpu->Cpsr |= (1 << 19); - } else { - cpu->Cpsr &= ~(1 << 18); - cpu->Cpsr &= ~(1 << 19); - } - } - // USUB16 - else if (op2 == 0x03) { - lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); - hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); - - if ((lo_result & 0xFFFF0000) == 0) { - cpu->Cpsr |= (1 << 16); - cpu->Cpsr |= (1 << 17); - } else { - cpu->Cpsr &= ~(1 << 16); - cpu->Cpsr &= ~(1 << 17); - } - - if ((hi_result & 0xFFFF0000) == 0) { - cpu->Cpsr |= (1 << 18); - cpu->Cpsr |= (1 << 19); - } else { - cpu->Cpsr &= ~(1 << 18); - cpu->Cpsr &= ~(1 << 19); - } - } - // UADD8 - else if (op2 == 0x04) { - s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); - s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); - s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); - s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); - - if (sum1 >= 0x100) - cpu->Cpsr |= (1 << 16); - else - cpu->Cpsr &= ~(1 << 16); - - if (sum2 >= 0x100) - cpu->Cpsr |= (1 << 17); - else - cpu->Cpsr &= ~(1 << 17); - - if (sum3 >= 0x100) - cpu->Cpsr |= (1 << 18); - else - cpu->Cpsr &= ~(1 << 18); - - if (sum4 >= 0x100) - cpu->Cpsr |= (1 << 19); - else - cpu->Cpsr &= ~(1 << 19); - - lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8); - hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8); - } - // USUB8 - else if (op2 == 0x07) { - s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF); - s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); - s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); - s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); - - if (diff1 >= 0) - cpu->Cpsr |= (1 << 16); - else - cpu->Cpsr &= ~(1 << 16); - - if (diff2 >= 0) - cpu->Cpsr |= (1 << 17); - else - cpu->Cpsr &= ~(1 << 17); - - if (diff3 >= 0) - cpu->Cpsr |= (1 << 18); - else - cpu->Cpsr &= ~(1 << 18); - - if (diff4 >= 0) - cpu->Cpsr |= (1 << 19); - else - cpu->Cpsr &= ~(1 << 19); - - lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8); - hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8); - } - - RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - UHADD8_INST: - UHADD16_INST: - UHADDSUBX_INST: - UHSUBADDX_INST: - UHSUB8_INST: - UHSUB16_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - const u32 rm_val = RM; - const u32 rn_val = RN; - const u8 op2 = inst_cream->op2; - - if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) - { - u32 lo_val = 0; - u32 hi_val = 0; - - // UHADD16 - if (op2 == 0x00) { - lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); - hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); - } - // UHASX - else if (op2 == 0x01) { - lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); - hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); - } - // UHSAX - else if (op2 == 0x02) { - lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); - hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); - } - // UHSUB16 - else if (op2 == 0x03) { - lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); - hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); - } - - lo_val >>= 1; - hi_val >>= 1; - - RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16); - } - else if (op2 == 0x04 || op2 == 0x07) { - u32 sum1; - u32 sum2; - u32 sum3; - u32 sum4; - - // UHADD8 - if (op2 == 0x04) { - sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); - sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); - sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); - sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); - } - // UHSUB8 - else { - sum1 = (rn_val & 0xFF) - (rm_val & 0xFF); - sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); - sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); - sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); - } - - sum1 >>= 1; - sum2 >>= 1; - sum3 >>= 1; - sum4 >>= 1; - - RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24); - } - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - UMAAL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; - const u64 rm = RM; - const u64 rn = RN; - const u64 rd_lo = RDLO; - const u64 rd_hi = RDHI; - const u64 result = (rm * rn) + rd_lo + rd_hi; - - RDLO = (result & 0xFFFFFFFF); - RDHI = ((result >> 32) & 0xFFFFFFFF); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(umaal_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - UMLAL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - umlal_inst* inst_cream = (umlal_inst*)inst_base->component; - unsigned long long int rm = RM; - unsigned long long int rs = RS; - unsigned long long int rst = rm * rs; - unsigned long long int add = ((unsigned long long) RDHI)<<32; - add += RDLO; - rst += add; - RDLO = BITS(rst, 0, 31); - RDHI = BITS(rst, 32, 63); - - if (inst_cream->S) { - cpu->NFlag = BIT(RDHI, 31); - cpu->ZFlag = (RDHI == 0 && RDLO == 0); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(umlal_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - UMULL_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - umull_inst* inst_cream = (umull_inst*)inst_base->component; - unsigned long long int rm = RM; - unsigned long long int rs = RS; - unsigned long long int rst = rm * rs; - RDHI = BITS(rst, 32, 63); - RDLO = BITS(rst, 0, 31); - - if (inst_cream->S) { - cpu->NFlag = BIT(RDHI, 31); - cpu->ZFlag = (RDHI == 0 && RDLO == 0); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(umull_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - B_2_THUMB: - { - b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component; - cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; - INC_PC(sizeof(b_2_thumb)); - goto DISPATCH; - } - B_COND_THUMB: - { - b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component; - - if(CondPassed(cpu, inst_cream->cond)) - cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; - else - cpu->Reg[15] += 2; - - INC_PC(sizeof(b_cond_thumb)); - goto DISPATCH; - } - BL_1_THUMB: - { - bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component; - cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm; - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(bl_1_thumb)); - FETCH_INST; - GOTO_NEXT_INST; - } - BL_2_THUMB: - { - bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component; - int tmp = ((cpu->Reg[15] + 2) | 1); - cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm); - cpu->Reg[14] = tmp; - INC_PC(sizeof(bl_2_thumb)); - goto DISPATCH; - } - BLX_1_THUMB: - { - // BLX 1 for armv5t and above - u32 tmp = cpu->Reg[15]; - blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component; - cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC; - cpu->Reg[14] = ((tmp + 2) | 1); - cpu->TFlag = 0; - INC_PC(sizeof(blx_1_thumb)); - goto DISPATCH; - } - - UQADD8_INST: - UQADD16_INST: - UQADDSUBX_INST: - UQSUB8_INST: - UQSUB16_INST: - UQSUBADDX_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - const u8 op2 = inst_cream->op2; - const u32 rm_val = RM; - const u32 rn_val = RN; - - u16 lo_val = 0; - u16 hi_val = 0; - - // UQADD16 - if (op2 == 0x00) { - lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); - hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); - } - // UQASX - else if (op2 == 0x01) { - lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); - hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); - } - // UQSAX - else if (op2 == 0x02) { - lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); - hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); - } - // UQSUB16 - else if (op2 == 0x03) { - lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); - hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); - } - // UQADD8 - else if (op2 == 0x04) { - lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | - ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; - hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | - ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; - } - // UQSUB8 - else { - lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | - ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; - hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | - ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; - } - - RD = ((lo_val & 0xFFFF) | hi_val << 16); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - USAD8_INST: - USADA8_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; - - const u8 ra_idx = inst_cream->Ra; - const u32 rm_val = RM; - const u32 rn_val = RN; - - const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF); - const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF); - const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF); - const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF); - - u32 finalDif = (diff1 + diff2 + diff3 + diff4); - - // Op is USADA8 if true. - if (ra_idx != 15) - finalDif += cpu->Reg[ra_idx]; - - RD = finalDif; - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(generic_arm_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - USAT_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; - - u8 shift_type = inst_cream->shift_type; - u8 shift_amount = inst_cream->imm5; - u32 rn_val = RN; - - // 32-bit ASR is encoded as an amount of 0. - if (shift_type == 1 && shift_amount == 0) - shift_amount = 31; - - if (shift_type == 0) - rn_val <<= shift_amount; - else if (shift_type == 1) - rn_val = ((s32)rn_val >> shift_amount); - - bool saturated = false; - rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated); - - if (saturated) - cpu->Cpsr |= (1 << 27); - - RD = rn_val; - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ssat_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - USAT16_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; - const u8 saturate_to = inst_cream->sat_imm; - - bool sat1 = false; - bool sat2 = false; - - RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | - ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; - - if (sat1 || sat2) - cpu->Cpsr |= (1 << 27); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(ssat_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - UXTAB16_INST: - UXTB16_INST: - { - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; - - const u8 rn_idx = inst_cream->Rn; - const u32 rm_val = RM; - const u32 rotation = inst_cream->rotate * 8; - const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); - - // UXTB16, otherwise UXTAB16 - if (rn_idx == 15) { - RD = rotated_rm & 0x00FF00FF; - } else { - const u32 rn_val = RN; - const u8 lo_rotated = (rotated_rm & 0xFF); - const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated; - const u8 hi_rotated = (rotated_rm >> 16) & 0xFF; - const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated; - - RD = ((hi_result << 16) | (lo_result & 0xFFFF)); - } - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(uxtab_inst)); - FETCH_INST; - GOTO_NEXT_INST; - } - - WFE_INST: - { - // Stubbed, as WFE is a hint instruction. - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - LOG_TRACE(Core_ARM11, "WFE executed."); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC_STUB; - FETCH_INST; - GOTO_NEXT_INST; - } - - WFI_INST: - { - // Stubbed, as WFI is a hint instruction. - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - LOG_TRACE(Core_ARM11, "WFI executed."); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC_STUB; - FETCH_INST; - GOTO_NEXT_INST; - } - - YIELD_INST: - { - // Stubbed, as YIELD is a hint instruction. - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - LOG_TRACE(Core_ARM11, "YIELD executed."); - } - - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC_STUB; - FETCH_INST; - GOTO_NEXT_INST; - } - - #define VFP_INTERPRETER_IMPL - #include "A32/skyeye_interpreter/skyeye_common/vfp/vfpinstr.cpp" - #undef VFP_INTERPRETER_IMPL - - END: - { - SAVE_NZCVT; - cpu->NumInstrsToExecute = 0; - return num_instrs; - } - INIT_INST_LENGTH: - { - cpu->NumInstrsToExecute = 0; - return num_instrs; - } -} diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h deleted file mode 100644 index 5d5b2d52..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -struct ARMul_State; - -unsigned InterpreterMainLoop(ARMul_State* state); -void InterpreterClearCache(); diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_run.h b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_run.h deleted file mode 100644 index 165f6265..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_run.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) -* 2011 - Michael.Kang blackfin.kang@gmail.com -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -#pragma once - -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" - -/** - * Checks if the PC is being read, and if so, word-aligns it. - * Used with address calculations. - * - * @param cpu The ARM CPU state instance. - * @param Rn The register being read. - * - * @return If the PC is being read, then the word-aligned PC value is returned. - * If the PC is not being read, then the value stored in the register is returned. - */ -inline u32 CHECK_READ_REG15_WA(const ARMul_State* cpu, int Rn) { - return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn]; -} - -/** - * Reads the PC. Used for data processing operations that use the PC. - * - * @param cpu The ARM CPU state instance. - * @param Rn The register being read. - * - * @return If the PC is being read, then the incremented PC value is returned. - * If the PC is not being read, then the values stored in the register is returned. - */ -inline u32 CHECK_READ_REG15(const ARMul_State* cpu, int Rn) { - return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn]; -} diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.cpp b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.cpp deleted file mode 100644 index 695276b6..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.cpp +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright 2012 Michael Kang, 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include - -// We can provide simple Thumb simulation by decoding the Thumb instruction into its corresponding -// ARM instruction, and using the existing ARM simulator. - -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.h" -#include "A32/skyeye_interpreter/skyeye_common/armsupp.h" - -// Decode a 16bit Thumb instruction. The instruction is in the low 16-bits of the tinstr field, -// with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions -// allows easier simulation of the special dual BL instruction. - -ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size) { - ThumbDecodeStatus valid = ThumbDecodeStatus::UNINITIALIZED; - u32 tinstr = GetThumbInstruction(instr, addr); - - *ainstr = 0xDEADC0DE; // Debugging to catch non updates - - switch ((tinstr & 0xF800) >> 11) { - case 0: // LSL - case 1: // LSR - case 2: // ASR - *ainstr = 0xE1B00000 // base opcode - | ((tinstr & 0x1800) >> (11 - 5)) // shift type - |((tinstr & 0x07C0) << (7 - 6)) // imm5 - |((tinstr & 0x0038) >> 3) // Rs - |((tinstr & 0x0007) << 12); // Rd - break; - - case 3: // ADD/SUB - { - static const u32 subset[4] = { - 0xE0900000, // ADDS Rd,Rs,Rn - 0xE0500000, // SUBS Rd,Rs,Rn - 0xE2900000, // ADDS Rd,Rs,#imm3 - 0xE2500000 // SUBS Rd,Rs,#imm3 - }; - // It is quicker indexing into a table, than performing switch or conditionals: - *ainstr = subset[(tinstr & 0x0600) >> 9] // base opcode - |((tinstr & 0x01C0) >> 6) // Rn or imm3 - |((tinstr & 0x0038) << (16 - 3)) // Rs - |((tinstr & 0x0007) << (12 - 0)); // Rd - } - break; - - case 4: // MOV - case 5: // CMP - case 6: // ADD - case 7: // SUB - { - static const u32 subset[4] = { - 0xE3B00000, // MOVS Rd,#imm8 - 0xE3500000, // CMP Rd,#imm8 - 0xE2900000, // ADDS Rd,Rd,#imm8 - 0xE2500000, // SUBS Rd,Rd,#imm8 - }; - - *ainstr = subset[(tinstr & 0x1800) >> 11] // base opcode - |((tinstr & 0x00FF) >> 0) // imm8 - |((tinstr & 0x0700) << (16 - 8)) // Rn - |((tinstr & 0x0700) << (12 - 8)); // Rd - } - break; - - case 8: // Arithmetic and high register transfers - - // TODO: Since the subsets for both Format 4 and Format 5 instructions are made up of - // different ARM encodings, we could save the following conditional, and just have one - // large subset - - if ((tinstr & (1 << 10)) == 0) { - enum otype { - t_norm, - t_shift, - t_neg, - t_mul - }; - - static const struct { - u32 opcode; - otype type; - } subset[16] = { - { 0xE0100000, t_norm }, // ANDS Rd,Rd,Rs - { 0xE0300000, t_norm }, // EORS Rd,Rd,Rs - { 0xE1B00010, t_shift }, // MOVS Rd,Rd,LSL Rs - { 0xE1B00030, t_shift }, // MOVS Rd,Rd,LSR Rs - { 0xE1B00050, t_shift }, // MOVS Rd,Rd,ASR Rs - { 0xE0B00000, t_norm }, // ADCS Rd,Rd,Rs - { 0xE0D00000, t_norm }, // SBCS Rd,Rd,Rs - { 0xE1B00070, t_shift }, // MOVS Rd,Rd,ROR Rs - { 0xE1100000, t_norm }, // TST Rd,Rs - { 0xE2700000, t_neg }, // RSBS Rd,Rs,#0 - { 0xE1500000, t_norm }, // CMP Rd,Rs - { 0xE1700000, t_norm }, // CMN Rd,Rs - { 0xE1900000, t_norm }, // ORRS Rd,Rd,Rs - { 0xE0100090, t_mul }, // MULS Rd,Rd,Rs - { 0xE1D00000, t_norm }, // BICS Rd,Rd,Rs - { 0xE1F00000, t_norm } // MVNS Rd,Rs - }; - - *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base - - switch (subset[(tinstr & 0x03C0) >> 6].type) { - case t_norm: - *ainstr |= ((tinstr & 0x0007) << 16) // Rn - |((tinstr & 0x0007) << 12) // Rd - |((tinstr & 0x0038) >> 3); // Rs - break; - case t_shift: - *ainstr |= ((tinstr & 0x0007) << 12) // Rd - |((tinstr & 0x0007) >> 0) // Rm - |((tinstr & 0x0038) << (8 - 3)); // Rs - break; - case t_neg: - *ainstr |= ((tinstr & 0x0007) << 12) // Rd - |((tinstr & 0x0038) << (16 - 3)); // Rn - break; - case t_mul: - *ainstr |= ((tinstr & 0x0007) << 16) // Rd - |((tinstr & 0x0007) << 8) // Rs - |((tinstr & 0x0038) >> 3); // Rm - break; - } - } else { - u32 Rd = ((tinstr & 0x0007) >> 0); - u32 Rs = ((tinstr & 0x0078) >> 3); - - if (tinstr & (1 << 7)) - Rd += 8; - - switch ((tinstr & 0x03C0) >> 6) { - case 0x0: // ADD Rd,Rd,Rs - case 0x1: // ADD Rd,Rd,Hs - case 0x2: // ADD Hd,Hd,Rs - case 0x3: // ADD Hd,Hd,Hs - *ainstr = 0xE0800000 // base - | (Rd << 16) // Rn - |(Rd << 12) // Rd - |(Rs << 0); // Rm - break; - case 0x4: // CMP Rd,Rs - case 0x5: // CMP Rd,Hs - case 0x6: // CMP Hd,Rs - case 0x7: // CMP Hd,Hs - *ainstr = 0xE1500000 // base - | (Rd << 16) // Rn - |(Rs << 0); // Rm - break; - case 0x8: // MOV Rd,Rs - case 0x9: // MOV Rd,Hs - case 0xA: // MOV Hd,Rs - case 0xB: // MOV Hd,Hs - *ainstr = 0xE1A00000 // base - |(Rd << 12) // Rd - |(Rs << 0); // Rm - break; - case 0xC: // BX Rs - case 0xD: // BX Hs - *ainstr = 0xE12FFF10 // base - | ((tinstr & 0x0078) >> 3); // Rd - break; - case 0xE: // BLX - case 0xF: // BLX - *ainstr = 0xE1200030 // base - | (Rs << 0); // Rm - break; - } - } - break; - - case 9: // LDR Rd,[PC,#imm8] - *ainstr = 0xE59F0000 // base - | ((tinstr & 0x0700) << (12 - 8)) // Rd - |((tinstr & 0x00FF) << (2 - 0)); // off8 - break; - - case 10: - case 11: - { - static const u32 subset[8] = { - 0xE7800000, // STR Rd,[Rb,Ro] - 0xE18000B0, // STRH Rd,[Rb,Ro] - 0xE7C00000, // STRB Rd,[Rb,Ro] - 0xE19000D0, // LDRSB Rd,[Rb,Ro] - 0xE7900000, // LDR Rd,[Rb,Ro] - 0xE19000B0, // LDRH Rd,[Rb,Ro] - 0xE7D00000, // LDRB Rd,[Rb,Ro] - 0xE19000F0 // LDRSH Rd,[Rb,Ro] - }; - - *ainstr = subset[(tinstr & 0xE00) >> 9] // base - |((tinstr & 0x0007) << (12 - 0)) // Rd - |((tinstr & 0x0038) << (16 - 3)) // Rb - |((tinstr & 0x01C0) >> 6); // Ro - } - break; - - case 12: // STR Rd,[Rb,#imm5] - case 13: // LDR Rd,[Rb,#imm5] - case 14: // STRB Rd,[Rb,#imm5] - case 15: // LDRB Rd,[Rb,#imm5] - { - static const u32 subset[4] = { - 0xE5800000, // STR Rd,[Rb,#imm5] - 0xE5900000, // LDR Rd,[Rb,#imm5] - 0xE5C00000, // STRB Rd,[Rb,#imm5] - 0xE5D00000 // LDRB Rd,[Rb,#imm5] - }; - // The offset range defends on whether we are transferring a byte or word value: - *ainstr = subset[(tinstr & 0x1800) >> 11] // base - |((tinstr & 0x0007) << (12 - 0)) // Rd - |((tinstr & 0x0038) << (16 - 3)) // Rb - |((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5 - } - break; - - case 16: // STRH Rd,[Rb,#imm5] - case 17: // LDRH Rd,[Rb,#imm5] - *ainstr = ((tinstr & (1 << 11)) // base - ? 0xE1D000B0 // LDRH - : 0xE1C000B0) // STRH - |((tinstr & 0x0007) << (12 - 0)) // Rd - |((tinstr & 0x0038) << (16 - 3)) // Rb - |((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble - |((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble - break; - - case 18: // STR Rd,[SP,#imm8] - case 19: // LDR Rd,[SP,#imm8] - *ainstr = ((tinstr & (1 << 11)) // base - ? 0xE59D0000 // LDR - : 0xE58D0000) // STR - |((tinstr & 0x0700) << (12 - 8)) // Rd - |((tinstr & 0x00FF) << 2); // off8 - break; - - case 20: // ADD Rd,PC,#imm8 - case 21: // ADD Rd,SP,#imm8 - - if ((tinstr & (1 << 11)) == 0) { - - // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the - // rotate immediate field, so no shift of off8 is needed. - - *ainstr = 0xE28F0F00 // base - | ((tinstr & 0x0700) << (12 - 8)) // Rd - |(tinstr & 0x00FF); // off8 - } else { - // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is needed. - *ainstr = 0xE28D0F00 // base - | ((tinstr & 0x0700) << (12 - 8)) // Rd - |(tinstr & 0x00FF); // off8 - } - break; - - case 22: - case 23: - if ((tinstr & 0x0F00) == 0x0000) { - // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30): - *ainstr = ((tinstr & (1 << 7)) // base - ? 0xE24DDF00 // SUB - : 0xE28DDF00) // ADD - |(tinstr & 0x007F); // off7 - } else if ((tinstr & 0x0F00) == 0x0e00) { - // BKPT - *ainstr = 0xEF000000 // base - | BITS(tinstr, 0, 3) // imm4 field; - | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12 - } else if ((tinstr & 0x0F00) == 0x0200) { - static const u32 subset[4] = { - 0xE6BF0070, // SXTH - 0xE6AF0070, // SXTB - 0xE6FF0070, // UXTH - 0xE6EF0070, // UXTB - }; - - *ainstr = subset[BITS(tinstr, 6, 7)] // base - | (BITS(tinstr, 0, 2) << 12) // Rd - | BITS(tinstr, 3, 5); // Rm - } else if ((tinstr & 0x0F00) == 0x600) { - if (BIT(tinstr, 5) == 0) { - // SETEND - *ainstr = 0xF1010000 // base - | (BIT(tinstr, 3) << 9); // endian specifier - } else { - // CPS - *ainstr = 0xF1080000 // base - | (BIT(tinstr, 0) << 6) // fiq bit - | (BIT(tinstr, 1) << 7) // irq bit - | (BIT(tinstr, 2) << 8) // abort bit - | (BIT(tinstr, 4) << 18); // enable bit - } - } else if ((tinstr & 0x0F00) == 0x0a00) { - static const u32 subset[4] = { - 0xE6BF0F30, // REV - 0xE6BF0FB0, // REV16 - 0, // undefined - 0xE6FF0FB0, // REVSH - }; - - size_t subset_index = BITS(tinstr, 6, 7); - - if (subset_index == 2) { - valid = ThumbDecodeStatus::UNDEFINED; - } else { - *ainstr = subset[subset_index] // base - | (BITS(tinstr, 0, 2) << 12) // Rd - | BITS(tinstr, 3, 5); // Rm - } - } else { - static const u32 subset[4] = { - 0xE92D0000, // STMDB sp!,{rlist} - 0xE92D4000, // STMDB sp!,{rlist,lr} - 0xE8BD0000, // LDMIA sp!,{rlist} - 0xE8BD8000 // LDMIA sp!,{rlist,pc} - }; - *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base - |(tinstr & 0x00FF); // mask8 - } - break; - - case 24: // STMIA - case 25: // LDMIA - if (tinstr & (1 << 11)) - { - unsigned int base = 0xE8900000; - unsigned int rn = BITS(tinstr, 8, 10); - - // Writeback - if ((tinstr & (1 << rn)) == 0) - base |= (1 << 21); - - *ainstr = base // base (LDMIA) - | (rn << 16) // Rn - | (tinstr & 0x00FF); // Register list - } - else - { - *ainstr = 0xE8A00000 // base (STMIA) - | (BITS(tinstr, 8, 10) << 16) // Rn - | (tinstr & 0x00FF); // Register list - } - break; - - case 26: // Bcc - case 27: // Bcc/SWI - if ((tinstr & 0x0F00) == 0x0F00) { - // Format 17 : SWI - *ainstr = 0xEF000000; - // Breakpoint must be handled specially. - if ((tinstr & 0x00FF) == 0x18) - *ainstr |= ((tinstr & 0x00FF) << 16); - // New breakpoint value. See gdb/arm-tdep.c - else if ((tinstr & 0x00FF) == 0xFE) - *ainstr |= 0x180000; // base |= BKPT mask - else - *ainstr |= (tinstr & 0x00FF); - } else if ((tinstr & 0x0F00) != 0x0E00) - valid = ThumbDecodeStatus::BRANCH; - else // UNDEFINED : cc=1110(AL) uses different format - valid = ThumbDecodeStatus::UNDEFINED; - - break; - - case 28: // B - valid = ThumbDecodeStatus::BRANCH; - break; - - case 29: - if (tinstr & 0x1) - valid = ThumbDecodeStatus::UNDEFINED; - else - valid = ThumbDecodeStatus::BRANCH; - break; - - case 30: // BL instruction 1 - - // There is no single ARM instruction equivalent for this Thumb instruction. To keep the - // simulation simple (from the user perspective) we check if the following instruction is - // the second half of this BL, and if it is we simulate it immediately - - valid = ThumbDecodeStatus::BRANCH; - break; - - case 31: // BL instruction 2 - - // There is no single ARM instruction equivalent for this instruction. Also, it should only - // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the - // simulation of it on its own, with undefined results if r14 is not suitably initialised. - - valid = ThumbDecodeStatus::BRANCH; - break; - } - - *inst_size = 2; - - return valid; -} diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.h b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.h deleted file mode 100644 index c1be3c73..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (C) -* 2011 - Michael.Kang blackfin.kang@gmail.com -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -*/ - -/** -* @file arm_dyncom_thumb.h -* @brief The thumb dyncom -* @author Michael.Kang blackfin.kang@gmail.com -* @version 78.77 -* @date 2011-11-07 -*/ - -#pragma once - -#include "common/common_types.h" - -enum class ThumbDecodeStatus { - UNDEFINED, // Undefined Thumb instruction - DECODED, // Instruction decoded to ARM equivalent - BRANCH, // Thumb branch (already processed) - UNINITIALIZED, -}; - -// Translates a Thumb mode instruction into its ARM equivalent. -ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u32* inst_size); - -inline u32 GetThumbInstruction(u32 instr, u32 address) { - // Normally you would need to handle instruction endianness, - // however, it is fixed to little-endian on the MPCore, so - // there's no need to check for this beforehand. - if ((address & 0x3) != 0) - return instr >> 16; - - return instr & 0xFFFF; -} diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_trans.cpp b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_trans.cpp deleted file mode 100644 index e6e346f7..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_trans.cpp +++ /dev/null @@ -1,2185 +0,0 @@ -#include - -#include "common/assert.h" -#include "common/common_types.h" - -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_trans.h" -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" -#include "A32/skyeye_interpreter/skyeye_common/armsupp.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp.h" - -#define LOG_INFO(...) do{}while(0) -#define LOG_TRACE(...) do{}while(0) - -char trans_cache_buf[TRANS_CACHE_SIZE]; -size_t trans_cache_buf_top = 0; - -static void* AllocBuffer(size_t size) { - size_t start = trans_cache_buf_top; - trans_cache_buf_top += size; - ASSERT_MSG(trans_cache_buf_top <= TRANS_CACHE_SIZE, "Translation cache is full!"); - return static_cast(&trans_cache_buf[start]); -} - -void InterpreterClearCache() { - trans_cache_buf_top = 0; -} - -#define glue(x, y) x ## y -#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) - -shtop_fp_t GetShifterOp(unsigned int inst); -get_addr_fp_t GetAddressingOp(unsigned int inst); -get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst); - -static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); - adc_inst *inst_cream = (adc_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst)); - add_inst *inst_cream = (add_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst)); - and_inst *inst_cream = (and_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) -{ - #define POSBRANCH ((inst & 0x7fffff) << 2) - #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2) - - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst)); - bbl_inst *inst_cream = (bbl_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::DIRECT_BRANCH; - - if (BIT(inst, 24)) - inst_base->br = TransExtData::CALL; - - inst_cream->L = BIT(inst, 24); - inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst)); - bic_inst *inst_cream = (bic_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst)); - bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst)); - blx_inst *inst_cream = (blx_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::INDIRECT_BRANCH; - - inst_cream->inst = inst; - if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { - inst_cream->val.Rm = BITS(inst, 0, 3); - } else { - inst_cream->val.signed_immed_24 = BITS(inst, 0, 23); - } - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); - bx_inst *inst_cream = (bx_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::INDIRECT_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(bx)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) { - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); - cdp_inst *inst_cream = (cdp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->CRm = BITS(inst, 0, 3); - inst_cream->CRd = BITS(inst, 12, 15); - inst_cream->CRn = BITS(inst, 16, 19); - inst_cream->cp_num = BITS(inst, 8, 11); - inst_cream->opcode_2 = BITS(inst, 5, 7); - inst_cream->opcode_1 = BITS(inst, 20, 23); - inst_cream->inst = inst; - - LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index); - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst)); - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst)); - clz_inst *inst_cream = (clz_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst)); - cmn_inst *inst_cream = (cmn_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst)); - cmp_inst *inst_cream = (cmp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst)); - cps_inst *inst_cream = (cps_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->imod0 = BIT(inst, 18); - inst_cream->imod1 = BIT(inst, 19); - inst_cream->mmod = BIT(inst, 17); - inst_cream->A = BIT(inst, 8); - inst_cream->I = BIT(inst, 7); - inst_cream->F = BIT(inst, 6); - inst_cream->mode = BITS(inst, 0, 4); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); - mov_inst *inst_cream = (mov_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) { - inst_base->br = TransExtData::INDIRECT_BRANCH; - } - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst)); - eor_inst *inst_cream = (eor_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst)); - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - if (BIT(inst, 15)) { - inst_base->br = TransExtData::INDIRECT_BRANCH; - } - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); - sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->rotate = BITS(inst, 10, 11); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - if (BITS(inst, 12, 15) == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - if (BITS(inst, 12, 15) == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); - uxth_inst *inst_cream = (uxth_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst)); - uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) -{ - arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH : TransExtData::NON_BRANCH; // Branch if dest is R15 - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ldrex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ldrex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ldrex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) -{ - arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); - - if (BITS(inst, 12, 15) == 15) { - inst_base->br = TransExtData::INDIRECT_BRANCH; - } - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst)); - mcr_inst *inst_cream = (mcr_inst *)inst_base->component; - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->crn = BITS(inst, 16, 19); - inst_cream->crm = BITS(inst, 0, 3); - inst_cream->opcode_1 = BITS(inst, 21, 23); - inst_cream->opcode_2 = BITS(inst, 5, 7); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->cp_num = BITS(inst, 8, 11); - inst_cream->inst = inst; - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst)); - mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->crm = BITS(inst, 0, 3); - inst_cream->opcode_1 = BITS(inst, 4, 7); - inst_cream->cp_num = BITS(inst, 8, 11); - inst_cream->rt = BITS(inst, 12, 15); - inst_cream->rt2 = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); - mla_inst *inst_cream = (mla_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 12, 15); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); - mov_inst *inst_cream = (mov_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) { - inst_base->br = TransExtData::INDIRECT_BRANCH; - } - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst)); - mrc_inst *inst_cream = (mrc_inst *)inst_base->component; - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->crn = BITS(inst, 16, 19); - inst_cream->crm = BITS(inst, 0, 3); - inst_cream->opcode_1 = BITS(inst, 21, 23); - inst_cream->opcode_2 = BITS(inst, 5, 7); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->cp_num = BITS(inst, 8, 11); - inst_cream->inst = inst; - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(mcrr)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); - mrs_inst *inst_cream = (mrs_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->R = BIT(inst, 22); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst)); - msr_inst *inst_cream = (msr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->field_mask = BITS(inst, 16, 19); - inst_cream->R = BIT(inst, 22); - inst_cream->inst = inst; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst)); - mul_inst *inst_cream = (mul_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->Rd = BITS(inst, 16, 19); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst)); - mvn_inst *inst_cream = (mvn_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) { - inst_base->br = TransExtData::INDIRECT_BRANCH; - } - return inst_base; - -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst)); - orr_inst *inst_cream = (orr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} - -// NOP introduced in ARMv6K. -static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst)); - pkh_inst *inst_cream = (pkh_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->imm = BITS(inst, 7, 11); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(pkhbt)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->op1 = BITS(inst, 21, 22); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(qadd8)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); - rev_inst* const inst_cream = (rev_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(rev)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(rev)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = AL; - inst_base->idx = index; - inst_base->br = TransExtData::INDIRECT_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst)); - rsb_inst *inst_cream = (rsb_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst)); - rsc_inst *inst_cream = (rsc_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sadd8)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst)); - sbc_inst *inst_cream = (sbc_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst)); - setend_inst* const inst_cream = (setend_inst*)inst_base->component; - - inst_base->cond = AL; - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->set_bigend = BIT(inst, 9); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(shadd8)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); - smla_inst *inst_cream = (smla_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->x = BIT(inst, 5); - inst_cream->y = BIT(inst, 6); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Rn = BITS(inst, 12, 15); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->m = BIT(inst, 5); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Ra = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smlad)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smlad)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smlad)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); - umlal_inst *inst_cream = (umlal_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->RdLo = BITS(inst, 12, 15); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst)); - smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->x = BIT(inst, 5); - inst_cream->y = BIT(inst, 6); - inst_cream->RdLo = BITS(inst, 12, 15); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->Rn = BITS(inst, 0, 4); - inst_cream->Rm = BITS(inst, 8, 11); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Ra = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->m = BIT(inst, 6); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst)); - smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->RdLo = BITS(inst, 12, 15); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->swap = BIT(inst, 5); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smlald)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); - smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->m = BIT(inst, 5); - inst_cream->Ra = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->op1 = BITS(inst, 20, 22); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smmla)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(smmla)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst)); - smul_inst *inst_cream = (smul_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - inst_cream->x = BIT(inst, 5); - inst_cream->y = BIT(inst, 6); - - return inst_base; - -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); - umull_inst *inst_cream = (umull_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->RdLo = BITS(inst, 12, 15); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); - smlad_inst *inst_cream = (smlad_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->m = BIT(inst, 6); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = AL; - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); - ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->imm5 = BITS(inst, 7, 11); - inst_cream->sat_imm = BITS(inst, 16, 20); - inst_cream->shift_type = BIT(inst, 6); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); - ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->sat_imm = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst)); - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); - sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->rotate = BITS(inst, 10, 11); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); - uxth_inst *inst_cream = (uxth_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); - uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) -{ - arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(strex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(strex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(strex)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) -{ - arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst* inst_cream = (ldst_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->inst = inst; - inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst)); - sub_inst *inst_cream = (sub_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - if (inst_cream->Rd == 15) - inst_base->br = TransExtData::INDIRECT_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst)); - swi_inst *inst_cream = (swi_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->num = BITS(inst, 0, 23); - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); - swp_inst *inst_cream = (swp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); - swp_inst *inst_cream = (swp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->Rm = BITS(inst, 0, 3); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); - sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); - sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(sxtab16)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) { - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst)); - sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst)); - teq_inst *inst_cream = (teq_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst)); - tst_inst *inst_cream = (tst_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->I = BIT(inst, 25); - inst_cream->S = BIT(inst, 20); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->shifter_operand = BITS(inst, 0, 11); - inst_cream->shtop_func = GetShifterOp(inst); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uadd8)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uhadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst)); - umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->RdLo = BITS(inst, 12, 15); - inst_cream->RdHi = BITS(inst, 16, 19); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); - umlal_inst *inst_cream = (umlal_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->RdLo = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); - umull_inst *inst_cream = (umull_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->S = BIT(inst, 20); - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rs = BITS(inst, 8, 11); - inst_cream->RdHi = BITS(inst, 16, 19); - inst_cream->RdLo = BITS(inst, 12, 15); - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb)); - b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component; - - inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0); - - inst_base->idx = index; - inst_base->br = TransExtData::DIRECT_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb)); - b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component; - - inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0)); - inst_cream->cond = ((tinst >> 8) & 0xf); - inst_base->idx = index; - inst_base->br = TransExtData::DIRECT_BRANCH; - - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb)); - bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component; - - inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0)); - - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb)); - bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component; - - inst_cream->imm = (tinst & 0x07FF) << 1; - - inst_base->idx = index; - inst_base->br = TransExtData::DIRECT_BRANCH; - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb)); - blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component; - - inst_cream->imm = (tinst & 0x07FF) << 1; - inst_cream->instr = tinst; - - inst_base->idx = index; - inst_base->br = TransExtData::DIRECT_BRANCH; - return inst_base; -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->op1 = BITS(inst, 20, 21); - inst_cream->op2 = BITS(inst, 5, 7); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uqadd8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); - generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->op1 = BITS(inst, 20, 24); - inst_cream->op2 = BITS(inst, 5, 7); - inst_cream->Rd = BITS(inst, 16, 19); - inst_cream->Rm = BITS(inst, 8, 11); - inst_cream->Rn = BITS(inst, 0, 3); - inst_cream->Ra = BITS(inst, 12, 15); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(usada8)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ssat)(inst, index); -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(ssat16)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); - uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->Rm = BITS(inst, 0, 3); - inst_cream->Rn = BITS(inst, 16, 19); - inst_cream->Rd = BITS(inst, 12, 15); - inst_cream->rotate = BITS(inst, 10, 11); - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) -{ - return INTERPRETER_TRANSLATE(uxtab16)(inst, index); -} - -static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} -static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) -{ - arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - return inst_base; -} - -// Floating point VFPv3 instructions -#define VFP_INTERPRETER_TRANS -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfpinstr.cpp" -#undef VFP_INTERPRETER_TRANS - -const transop_fp_t arm_instruction_trans[] = { - INTERPRETER_TRANSLATE(vmla), - INTERPRETER_TRANSLATE(vmls), - INTERPRETER_TRANSLATE(vnmla), - INTERPRETER_TRANSLATE(vnmls), - INTERPRETER_TRANSLATE(vnmul), - INTERPRETER_TRANSLATE(vmul), - INTERPRETER_TRANSLATE(vadd), - INTERPRETER_TRANSLATE(vsub), - INTERPRETER_TRANSLATE(vdiv), - INTERPRETER_TRANSLATE(vmovi), - INTERPRETER_TRANSLATE(vmovr), - INTERPRETER_TRANSLATE(vabs), - INTERPRETER_TRANSLATE(vneg), - INTERPRETER_TRANSLATE(vsqrt), - INTERPRETER_TRANSLATE(vcmp), - INTERPRETER_TRANSLATE(vcmp2), - INTERPRETER_TRANSLATE(vcvtbds), - INTERPRETER_TRANSLATE(vcvtbff), - INTERPRETER_TRANSLATE(vcvtbfi), - INTERPRETER_TRANSLATE(vmovbrs), - INTERPRETER_TRANSLATE(vmsr), - INTERPRETER_TRANSLATE(vmovbrc), - INTERPRETER_TRANSLATE(vmrs), - INTERPRETER_TRANSLATE(vmovbcr), - INTERPRETER_TRANSLATE(vmovbrrss), - INTERPRETER_TRANSLATE(vmovbrrd), - INTERPRETER_TRANSLATE(vstr), - INTERPRETER_TRANSLATE(vpush), - INTERPRETER_TRANSLATE(vstm), - INTERPRETER_TRANSLATE(vpop), - INTERPRETER_TRANSLATE(vldr), - INTERPRETER_TRANSLATE(vldm), - - INTERPRETER_TRANSLATE(srs), - INTERPRETER_TRANSLATE(rfe), - INTERPRETER_TRANSLATE(bkpt), - INTERPRETER_TRANSLATE(blx), - INTERPRETER_TRANSLATE(cps), - INTERPRETER_TRANSLATE(pld), - INTERPRETER_TRANSLATE(setend), - INTERPRETER_TRANSLATE(clrex), - INTERPRETER_TRANSLATE(rev16), - INTERPRETER_TRANSLATE(usad8), - INTERPRETER_TRANSLATE(sxtb), - INTERPRETER_TRANSLATE(uxtb), - INTERPRETER_TRANSLATE(sxth), - INTERPRETER_TRANSLATE(sxtb16), - INTERPRETER_TRANSLATE(uxth), - INTERPRETER_TRANSLATE(uxtb16), - INTERPRETER_TRANSLATE(cpy), - INTERPRETER_TRANSLATE(uxtab), - INTERPRETER_TRANSLATE(ssub8), - INTERPRETER_TRANSLATE(shsub8), - INTERPRETER_TRANSLATE(ssubaddx), - INTERPRETER_TRANSLATE(strex), - INTERPRETER_TRANSLATE(strexb), - INTERPRETER_TRANSLATE(swp), - INTERPRETER_TRANSLATE(swpb), - INTERPRETER_TRANSLATE(ssub16), - INTERPRETER_TRANSLATE(ssat16), - INTERPRETER_TRANSLATE(shsubaddx), - INTERPRETER_TRANSLATE(qsubaddx), - INTERPRETER_TRANSLATE(shaddsubx), - INTERPRETER_TRANSLATE(shadd8), - INTERPRETER_TRANSLATE(shadd16), - INTERPRETER_TRANSLATE(sel), - INTERPRETER_TRANSLATE(saddsubx), - INTERPRETER_TRANSLATE(sadd8), - INTERPRETER_TRANSLATE(sadd16), - INTERPRETER_TRANSLATE(shsub16), - INTERPRETER_TRANSLATE(umaal), - INTERPRETER_TRANSLATE(uxtab16), - INTERPRETER_TRANSLATE(usubaddx), - INTERPRETER_TRANSLATE(usub8), - INTERPRETER_TRANSLATE(usub16), - INTERPRETER_TRANSLATE(usat16), - INTERPRETER_TRANSLATE(usada8), - INTERPRETER_TRANSLATE(uqsubaddx), - INTERPRETER_TRANSLATE(uqsub8), - INTERPRETER_TRANSLATE(uqsub16), - INTERPRETER_TRANSLATE(uqaddsubx), - INTERPRETER_TRANSLATE(uqadd8), - INTERPRETER_TRANSLATE(uqadd16), - INTERPRETER_TRANSLATE(sxtab), - INTERPRETER_TRANSLATE(uhsubaddx), - INTERPRETER_TRANSLATE(uhsub8), - INTERPRETER_TRANSLATE(uhsub16), - INTERPRETER_TRANSLATE(uhaddsubx), - INTERPRETER_TRANSLATE(uhadd8), - INTERPRETER_TRANSLATE(uhadd16), - INTERPRETER_TRANSLATE(uaddsubx), - INTERPRETER_TRANSLATE(uadd8), - INTERPRETER_TRANSLATE(uadd16), - INTERPRETER_TRANSLATE(sxtah), - INTERPRETER_TRANSLATE(sxtab16), - INTERPRETER_TRANSLATE(qadd8), - INTERPRETER_TRANSLATE(bxj), - INTERPRETER_TRANSLATE(clz), - INTERPRETER_TRANSLATE(uxtah), - INTERPRETER_TRANSLATE(bx), - INTERPRETER_TRANSLATE(rev), - INTERPRETER_TRANSLATE(blx), - INTERPRETER_TRANSLATE(revsh), - INTERPRETER_TRANSLATE(qadd), - INTERPRETER_TRANSLATE(qadd16), - INTERPRETER_TRANSLATE(qaddsubx), - INTERPRETER_TRANSLATE(ldrex), - INTERPRETER_TRANSLATE(qdadd), - INTERPRETER_TRANSLATE(qdsub), - INTERPRETER_TRANSLATE(qsub), - INTERPRETER_TRANSLATE(ldrexb), - INTERPRETER_TRANSLATE(qsub8), - INTERPRETER_TRANSLATE(qsub16), - INTERPRETER_TRANSLATE(smuad), - INTERPRETER_TRANSLATE(smmul), - INTERPRETER_TRANSLATE(smusd), - INTERPRETER_TRANSLATE(smlsd), - INTERPRETER_TRANSLATE(smlsld), - INTERPRETER_TRANSLATE(smmla), - INTERPRETER_TRANSLATE(smmls), - INTERPRETER_TRANSLATE(smlald), - INTERPRETER_TRANSLATE(smlad), - INTERPRETER_TRANSLATE(smlaw), - INTERPRETER_TRANSLATE(smulw), - INTERPRETER_TRANSLATE(pkhtb), - INTERPRETER_TRANSLATE(pkhbt), - INTERPRETER_TRANSLATE(smul), - INTERPRETER_TRANSLATE(smlalxy), - INTERPRETER_TRANSLATE(smla), - INTERPRETER_TRANSLATE(mcrr), - INTERPRETER_TRANSLATE(mrrc), - INTERPRETER_TRANSLATE(cmp), - INTERPRETER_TRANSLATE(tst), - INTERPRETER_TRANSLATE(teq), - INTERPRETER_TRANSLATE(cmn), - INTERPRETER_TRANSLATE(smull), - INTERPRETER_TRANSLATE(umull), - INTERPRETER_TRANSLATE(umlal), - INTERPRETER_TRANSLATE(smlal), - INTERPRETER_TRANSLATE(mul), - INTERPRETER_TRANSLATE(mla), - INTERPRETER_TRANSLATE(ssat), - INTERPRETER_TRANSLATE(usat), - INTERPRETER_TRANSLATE(mrs), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(and), - INTERPRETER_TRANSLATE(bic), - INTERPRETER_TRANSLATE(ldm), - INTERPRETER_TRANSLATE(eor), - INTERPRETER_TRANSLATE(add), - INTERPRETER_TRANSLATE(rsb), - INTERPRETER_TRANSLATE(rsc), - INTERPRETER_TRANSLATE(sbc), - INTERPRETER_TRANSLATE(adc), - INTERPRETER_TRANSLATE(sub), - INTERPRETER_TRANSLATE(orr), - INTERPRETER_TRANSLATE(mvn), - INTERPRETER_TRANSLATE(mov), - INTERPRETER_TRANSLATE(stm), - INTERPRETER_TRANSLATE(ldm), - INTERPRETER_TRANSLATE(ldrsh), - INTERPRETER_TRANSLATE(stm), - INTERPRETER_TRANSLATE(ldm), - INTERPRETER_TRANSLATE(ldrsb), - INTERPRETER_TRANSLATE(strd), - INTERPRETER_TRANSLATE(ldrh), - INTERPRETER_TRANSLATE(strh), - INTERPRETER_TRANSLATE(ldrd), - INTERPRETER_TRANSLATE(strt), - INTERPRETER_TRANSLATE(strbt), - INTERPRETER_TRANSLATE(ldrbt), - INTERPRETER_TRANSLATE(ldrt), - INTERPRETER_TRANSLATE(mrc), - INTERPRETER_TRANSLATE(mcr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(msr), - INTERPRETER_TRANSLATE(ldrb), - INTERPRETER_TRANSLATE(strb), - INTERPRETER_TRANSLATE(ldr), - INTERPRETER_TRANSLATE(ldrcond), - INTERPRETER_TRANSLATE(str), - INTERPRETER_TRANSLATE(cdp), - INTERPRETER_TRANSLATE(stc), - INTERPRETER_TRANSLATE(ldc), - INTERPRETER_TRANSLATE(ldrexd), - INTERPRETER_TRANSLATE(strexd), - INTERPRETER_TRANSLATE(ldrexh), - INTERPRETER_TRANSLATE(strexh), - INTERPRETER_TRANSLATE(nop), - INTERPRETER_TRANSLATE(yield), - INTERPRETER_TRANSLATE(wfe), - INTERPRETER_TRANSLATE(wfi), - INTERPRETER_TRANSLATE(sev), - INTERPRETER_TRANSLATE(swi), - INTERPRETER_TRANSLATE(bbl), - - // All the thumb instructions should be placed the end of table - INTERPRETER_TRANSLATE(b_2_thumb), - INTERPRETER_TRANSLATE(b_cond_thumb), - INTERPRETER_TRANSLATE(bl_1_thumb), - INTERPRETER_TRANSLATE(bl_2_thumb), - INTERPRETER_TRANSLATE(blx_1_thumb) -}; - -const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); diff --git a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_trans.h b/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_trans.h deleted file mode 100644 index ce95d90b..00000000 --- a/tests/A32/skyeye_interpreter/dyncom/arm_dyncom_trans.h +++ /dev/null @@ -1,499 +0,0 @@ -struct ARMul_State; -typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); - -enum class TransExtData { - COND = (1 << 0), - NON_BRANCH = (1 << 1), - DIRECT_BRANCH = (1 << 2), - INDIRECT_BRANCH = (1 << 3), - CALL = (1 << 4), - RET = (1 << 5), - END_OF_PAGE = (1 << 6), - THUMB = (1 << 7), - SINGLE_STEP = (1 << 8) -}; - -#ifdef _MSC_VER -#pragma warning(disable:4200) -#endif -struct arm_inst { - unsigned int idx; - unsigned int cond; - TransExtData br; -#ifdef __GNUC__ - __extension__ -#endif - char component[0]; -}; - -struct generic_arm_inst { - u32 Ra; - u32 Rm; - u32 Rn; - u32 Rd; - u8 op1; - u8 op2; -}; - -struct adc_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct add_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct orr_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct and_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct eor_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct bbl_inst { - unsigned int L; - int signed_immed_24; - unsigned int next_addr; - unsigned int jmp_addr; -}; - -struct bx_inst { - unsigned int Rm; -}; - -struct blx_inst { - union { - s32 signed_immed_24; - u32 Rm; - } val; - unsigned int inst; -}; - -struct clz_inst { - unsigned int Rm; - unsigned int Rd; -}; - -struct cps_inst { - unsigned int imod0; - unsigned int imod1; - unsigned int mmod; - unsigned int A, I, F; - unsigned int mode; -}; - -struct clrex_inst { -}; - -struct cpy_inst { - unsigned int Rm; - unsigned int Rd; -}; - -struct bic_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct sub_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct tst_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct cmn_inst { - unsigned int I; - unsigned int Rn; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct teq_inst { - unsigned int I; - unsigned int Rn; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct stm_inst { - unsigned int inst; -}; - -struct bkpt_inst { - u32 imm; -}; - -struct stc_inst { -}; - -struct ldc_inst { -}; - -struct swi_inst { - unsigned int num; -}; - -struct cmp_inst { - unsigned int I; - unsigned int Rn; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct mov_inst { - unsigned int I; - unsigned int S; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct mvn_inst { - unsigned int I; - unsigned int S; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct rev_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int op1; - unsigned int op2; -}; - -struct rsb_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct rsc_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct sbc_inst { - unsigned int I; - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int shifter_operand; - shtop_fp_t shtop_func; -}; - -struct mul_inst { - unsigned int S; - unsigned int Rd; - unsigned int Rs; - unsigned int Rm; -}; - -struct smul_inst { - unsigned int Rd; - unsigned int Rs; - unsigned int Rm; - unsigned int x; - unsigned int y; -}; - -struct umull_inst { - unsigned int S; - unsigned int RdHi; - unsigned int RdLo; - unsigned int Rs; - unsigned int Rm; -}; - -struct smlad_inst { - unsigned int m; - unsigned int Rm; - unsigned int Rd; - unsigned int Ra; - unsigned int Rn; - unsigned int op1; - unsigned int op2; -}; - -struct smla_inst { - unsigned int x; - unsigned int y; - unsigned int Rm; - unsigned int Rd; - unsigned int Rs; - unsigned int Rn; -}; - -struct smlalxy_inst { - unsigned int x; - unsigned int y; - unsigned int RdLo; - unsigned int RdHi; - unsigned int Rm; - unsigned int Rn; -}; - -struct ssat_inst { - unsigned int Rn; - unsigned int Rd; - unsigned int imm5; - unsigned int sat_imm; - unsigned int shift_type; -}; - -struct umaal_inst { - unsigned int Rn; - unsigned int Rm; - unsigned int RdHi; - unsigned int RdLo; -}; - -struct umlal_inst { - unsigned int S; - unsigned int Rm; - unsigned int Rs; - unsigned int RdHi; - unsigned int RdLo; -}; - -struct smlal_inst { - unsigned int S; - unsigned int Rm; - unsigned int Rs; - unsigned int RdHi; - unsigned int RdLo; -}; - -struct smlald_inst { - unsigned int RdLo; - unsigned int RdHi; - unsigned int Rm; - unsigned int Rn; - unsigned int swap; - unsigned int op1; - unsigned int op2; -}; - -struct mla_inst { - unsigned int S; - unsigned int Rn; - unsigned int Rd; - unsigned int Rs; - unsigned int Rm; -}; - -struct mrc_inst { - unsigned int opcode_1; - unsigned int opcode_2; - unsigned int cp_num; - unsigned int crn; - unsigned int crm; - unsigned int Rd; - unsigned int inst; -}; - -struct mcr_inst { - unsigned int opcode_1; - unsigned int opcode_2; - unsigned int cp_num; - unsigned int crn; - unsigned int crm; - unsigned int Rd; - unsigned int inst; -}; - -struct mcrr_inst { - unsigned int opcode_1; - unsigned int cp_num; - unsigned int crm; - unsigned int rt; - unsigned int rt2; -}; - -struct mrs_inst { - unsigned int R; - unsigned int Rd; -}; - -struct msr_inst { - unsigned int field_mask; - unsigned int R; - unsigned int inst; -}; - -struct pld_inst { -}; - -struct sxtb_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int rotate; -}; - -struct sxtab_inst { - unsigned int Rd; - unsigned int Rn; - unsigned int Rm; - unsigned rotate; -}; - -struct sxtah_inst { - unsigned int Rd; - unsigned int Rn; - unsigned int Rm; - unsigned int rotate; -}; - -struct sxth_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int rotate; -}; - -struct uxtab_inst { - unsigned int Rn; - unsigned int Rd; - unsigned int rotate; - unsigned int Rm; -}; - -struct uxtah_inst { - unsigned int Rn; - unsigned int Rd; - unsigned int rotate; - unsigned int Rm; -}; - -struct uxth_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int rotate; -}; - -struct cdp_inst { - unsigned int opcode_1; - unsigned int CRn; - unsigned int CRd; - unsigned int cp_num; - unsigned int opcode_2; - unsigned int CRm; - unsigned int inst; -}; - -struct uxtb_inst { - unsigned int Rd; - unsigned int Rm; - unsigned int rotate; -}; - -struct swp_inst { - unsigned int Rn; - unsigned int Rd; - unsigned int Rm; -}; - -struct setend_inst { - unsigned int set_bigend; -}; - -struct b_2_thumb { - unsigned int imm; -}; -struct b_cond_thumb { - unsigned int imm; - unsigned int cond; -}; - -struct bl_1_thumb { - unsigned int imm; -}; -struct bl_2_thumb { - unsigned int imm; -}; -struct blx_1_thumb { - unsigned int imm; - unsigned int instr; -}; - -struct pkh_inst { - unsigned int Rm; - unsigned int Rn; - unsigned int Rd; - unsigned char imm; -}; - -// Floating point VFPv3 structures -#define VFP_INTERPRETER_STRUCT -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfpinstr.cpp" -#undef VFP_INTERPRETER_STRUCT - -typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr); - -struct ldst_inst { - unsigned int inst; - get_addr_fp_t get_addr; -}; - -typedef arm_inst* ARM_INST_PTR; -typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int); - -extern const transop_fp_t arm_instruction_trans[]; -extern const size_t arm_instruction_trans_len; - -#define TRANS_CACHE_SIZE (64 * 1024 * 2000) -extern char trans_cache_buf[TRANS_CACHE_SIZE]; -extern size_t trans_cache_buf_top; diff --git a/tests/A32/skyeye_interpreter/skyeye_common/arm_regformat.h b/tests/A32/skyeye_interpreter/skyeye_common/arm_regformat.h deleted file mode 100644 index 38fa97ab..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/arm_regformat.h +++ /dev/null @@ -1,187 +0,0 @@ -#pragma once - -enum { - R0 = 0, - R1, - R2, - R3, - R4, - R5, - R6, - R7, - R8, - R9, - R10, - R11, - R12, - R13, - LR, - R15, //PC, - CPSR_REG, - SPSR_REG, - - PHYS_PC, - R13_USR, - R14_USR, - R13_SVC, - R14_SVC, - R13_ABORT, - R14_ABORT, - R13_UNDEF, - R14_UNDEF, - R13_IRQ, - R14_IRQ, - R8_FIRQ, - R9_FIRQ, - R10_FIRQ, - R11_FIRQ, - R12_FIRQ, - R13_FIRQ, - R14_FIRQ, - SPSR_INVALID1, - SPSR_INVALID2, - SPSR_SVC, - SPSR_ABORT, - SPSR_UNDEF, - SPSR_IRQ, - SPSR_FIRQ, - MODE_REG, /* That is the cpsr[4 : 0], just for calculation easily */ - BANK_REG, - EXCLUSIVE_TAG, - EXCLUSIVE_STATE, - EXCLUSIVE_RESULT, - - MAX_REG_NUM, -}; - -// VFP system registers -enum VFPSystemRegister { - VFP_FPSID, - VFP_FPSCR, - VFP_FPEXC, - VFP_FPINST, - VFP_FPINST2, - VFP_MVFR0, - VFP_MVFR1, - - // Not an actual register. - // All VFP system registers should be defined above this. - VFP_SYSTEM_REGISTER_COUNT -}; - -enum CP15Register { - // c0 - Information registers - CP15_MAIN_ID, - CP15_CACHE_TYPE, - CP15_TCM_STATUS, - CP15_TLB_TYPE, - CP15_CPU_ID, - CP15_PROCESSOR_FEATURE_0, - CP15_PROCESSOR_FEATURE_1, - CP15_DEBUG_FEATURE_0, - CP15_AUXILIARY_FEATURE_0, - CP15_MEMORY_MODEL_FEATURE_0, - CP15_MEMORY_MODEL_FEATURE_1, - CP15_MEMORY_MODEL_FEATURE_2, - CP15_MEMORY_MODEL_FEATURE_3, - CP15_ISA_FEATURE_0, - CP15_ISA_FEATURE_1, - CP15_ISA_FEATURE_2, - CP15_ISA_FEATURE_3, - CP15_ISA_FEATURE_4, - - // c1 - Control registers - CP15_CONTROL, - CP15_AUXILIARY_CONTROL, - CP15_COPROCESSOR_ACCESS_CONTROL, - - // c2 - Translation table registers - CP15_TRANSLATION_BASE_TABLE_0, - CP15_TRANSLATION_BASE_TABLE_1, - CP15_TRANSLATION_BASE_CONTROL, - CP15_DOMAIN_ACCESS_CONTROL, - CP15_RESERVED, - - // c5 - Fault status registers - CP15_FAULT_STATUS, - CP15_INSTR_FAULT_STATUS, - CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS, - CP15_INST_FSR, - - // c6 - Fault Address registers - CP15_FAULT_ADDRESS, - CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS, - CP15_WFAR, - CP15_IFAR, - - // c7 - Cache operation registers - CP15_WAIT_FOR_INTERRUPT, - CP15_PHYS_ADDRESS, - CP15_INVALIDATE_INSTR_CACHE, - CP15_INVALIDATE_INSTR_CACHE_USING_MVA, - CP15_INVALIDATE_INSTR_CACHE_USING_INDEX, - CP15_FLUSH_PREFETCH_BUFFER, - CP15_FLUSH_BRANCH_TARGET_CACHE, - CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY, - CP15_INVALIDATE_DATA_CACHE, - CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA, - CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX, - CP15_INVALIDATE_DATA_AND_INSTR_CACHE, - CP15_CLEAN_DATA_CACHE, - CP15_CLEAN_DATA_CACHE_LINE_USING_MVA, - CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX, - CP15_DATA_SYNC_BARRIER, - CP15_DATA_MEMORY_BARRIER, - CP15_CLEAN_AND_INVALIDATE_DATA_CACHE, - CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA, - CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX, - - // c8 - TLB operations - CP15_INVALIDATE_ITLB, - CP15_INVALIDATE_ITLB_SINGLE_ENTRY, - CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH, - CP15_INVALIDATE_ITLB_ENTRY_ON_MVA, - CP15_INVALIDATE_DTLB, - CP15_INVALIDATE_DTLB_SINGLE_ENTRY, - CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH, - CP15_INVALIDATE_DTLB_ENTRY_ON_MVA, - CP15_INVALIDATE_UTLB, - CP15_INVALIDATE_UTLB_SINGLE_ENTRY, - CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH, - CP15_INVALIDATE_UTLB_ENTRY_ON_MVA, - - // c9 - Data cache lockdown register - CP15_DATA_CACHE_LOCKDOWN, - - // c10 - TLB/Memory map registers - CP15_TLB_LOCKDOWN, - CP15_PRIMARY_REGION_REMAP, - CP15_NORMAL_REGION_REMAP, - - // c13 - Thread related registers - CP15_PID, - CP15_CONTEXT_ID, - CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write - CP15_THREAD_URO, // Thread ID register - User Read Only (Privileged R/W) - CP15_THREAD_PRW, // Thread ID register - Privileged R/W only. - - // c15 - Performance and TLB lockdown registers - CP15_PERFORMANCE_MONITOR_CONTROL, - CP15_CYCLE_COUNTER, - CP15_COUNT_0, - CP15_COUNT_1, - CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY, - CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY, - CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS, - CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS, - CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE, - CP15_TLB_DEBUG_CONTROL, - - // Skyeye defined - CP15_TLB_FAULT_ADDR, - CP15_TLB_FAULT_STATUS, - - // Not an actual register. - // All registers should be defined above this. - CP15_REGISTER_COUNT, -}; diff --git a/tests/A32/skyeye_interpreter/skyeye_common/armstate.cpp b/tests/A32/skyeye_interpreter/skyeye_common/armstate.cpp deleted file mode 100644 index f868ea1d..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/armstate.cpp +++ /dev/null @@ -1,693 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#ifdef _MSC_VER -#pragma warning(disable : 4244) -#endif - -#include -#include "common/assert.h" -#include "common/bit_util.h" -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp.h" - -ARMul_State::ARMul_State(PrivilegeMode initial_mode) -{ - Reset(); - ChangePrivilegeMode(initial_mode); -} - -void ARMul_State::ChangePrivilegeMode(u32 new_mode) -{ - if (Mode == new_mode) - return; - - if (new_mode != USERBANK) { - switch (Mode) { - case SYSTEM32MODE: // Shares registers with user mode - case USER32MODE: - Reg_usr[0] = Reg[13]; - Reg_usr[1] = Reg[14]; - break; - case IRQ32MODE: - Reg_irq[0] = Reg[13]; - Reg_irq[1] = Reg[14]; - Spsr[IRQBANK] = Spsr_copy; - break; - case SVC32MODE: - Reg_svc[0] = Reg[13]; - Reg_svc[1] = Reg[14]; - Spsr[SVCBANK] = Spsr_copy; - break; - case ABORT32MODE: - Reg_abort[0] = Reg[13]; - Reg_abort[1] = Reg[14]; - Spsr[ABORTBANK] = Spsr_copy; - break; - case UNDEF32MODE: - Reg_undef[0] = Reg[13]; - Reg_undef[1] = Reg[14]; - Spsr[UNDEFBANK] = Spsr_copy; - break; - case FIQ32MODE: - std::copy(Reg.begin() + 8, Reg.end() - 1, Reg_firq.begin()); - Spsr[FIQBANK] = Spsr_copy; - break; - } - - switch (new_mode) { - case USER32MODE: - Reg[13] = Reg_usr[0]; - Reg[14] = Reg_usr[1]; - Bank = USERBANK; - break; - case IRQ32MODE: - Reg[13] = Reg_irq[0]; - Reg[14] = Reg_irq[1]; - Spsr_copy = Spsr[IRQBANK]; - Bank = IRQBANK; - break; - case SVC32MODE: - Reg[13] = Reg_svc[0]; - Reg[14] = Reg_svc[1]; - Spsr_copy = Spsr[SVCBANK]; - Bank = SVCBANK; - break; - case ABORT32MODE: - Reg[13] = Reg_abort[0]; - Reg[14] = Reg_abort[1]; - Spsr_copy = Spsr[ABORTBANK]; - Bank = ABORTBANK; - break; - case UNDEF32MODE: - Reg[13] = Reg_undef[0]; - Reg[14] = Reg_undef[1]; - Spsr_copy = Spsr[UNDEFBANK]; - Bank = UNDEFBANK; - break; - case FIQ32MODE: - std::copy(Reg_firq.begin(), Reg_firq.end(), Reg.begin() + 8); - Spsr_copy = Spsr[FIQBANK]; - Bank = FIQBANK; - break; - case SYSTEM32MODE: // Shares registers with user mode. - Reg[13] = Reg_usr[0]; - Reg[14] = Reg_usr[1]; - Bank = SYSTEMBANK; - break; - } - - // Set the mode bits in the APSR - Cpsr = (Cpsr & ~Mode) | new_mode; - Mode = new_mode; - } -} - -// Performs a reset -void ARMul_State::Reset() -{ - VFPInit(this); - - // Set stack pointer to the top of the stack - Reg[13] = 0x10000000; - Reg[15] = 0; - - Cpsr = INTBITS | SVC32MODE; - Mode = SVC32MODE; - Bank = SVCBANK; - - ResetMPCoreCP15Registers(); - - NresetSig = HIGH; - NfiqSig = HIGH; - NirqSig = HIGH; - NtransSig = (Mode & 3) ? HIGH : LOW; - abortSig = LOW; - - NumInstrs = 0; - Emulate = RUN; -} - -// Resets certain MPCore CP15 values to their ARM-defined reset values. -void ARMul_State::ResetMPCoreCP15Registers() -{ - // c0 - CP15[CP15_MAIN_ID] = 0x410FB024; - CP15[CP15_TLB_TYPE] = 0x00000800; - CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111; - CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001; - CP15[CP15_DEBUG_FEATURE_0] = 0x00000002; - CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103; - CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302; - CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000; - CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000; - CP15[CP15_ISA_FEATURE_0] = 0x00100011; - CP15[CP15_ISA_FEATURE_1] = 0x12002111; - CP15[CP15_ISA_FEATURE_2] = 0x11221011; - CP15[CP15_ISA_FEATURE_3] = 0x01102131; - CP15[CP15_ISA_FEATURE_4] = 0x00000141; - - // c1 - CP15[CP15_CONTROL] = 0x00054078; - CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F; - CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000; - - // c2 - CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000; - CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000; - CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000; - - // c3 - CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000; - - // c7 - CP15[CP15_PHYS_ADDRESS] = 0x00000000; - - // c9 - CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0; - - // c10 - CP15[CP15_TLB_LOCKDOWN] = 0x00000000; - CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4; - CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0; - - // c13 - CP15[CP15_PID] = 0x00000000; - CP15[CP15_CONTEXT_ID] = 0x00000000; - CP15[CP15_THREAD_UPRW] = 0x00000000; - CP15[CP15_THREAD_URO] = 0x00000000; - CP15[CP15_THREAD_PRW] = 0x00000000; - - // c15 - CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000; - CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000; - CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000; - CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000; - CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; -} - -//static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) -//{ -// if (GDBStub::g_server_enabled && GDBStub::CheckBreakpoint(address, type)) { -// LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address); -// GDBStub::Break(true); -// } -//} - -u8 ARMul_State::ReadMemory8(u32 address) const -{ -// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); - - return user_callbacks->MemoryRead8(address); -} - -u16 ARMul_State::ReadMemory16(u32 address) const -{ -// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); - - u16 data = user_callbacks->MemoryRead16(address); - - if (InBigEndianMode()) - data = Dynarmic::Common::Swap16(data); - - return data; -} - -u32 ARMul_State::ReadMemory32(u32 address) const -{ -// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); - - u32 data = user_callbacks->MemoryRead32(address); - - if (InBigEndianMode()) - data = Dynarmic::Common::Swap32(data); - - return data; -} - -u64 ARMul_State::ReadMemory64(u32 address) const -{ -// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); - - u64 data = user_callbacks->MemoryRead64(address); - - if (InBigEndianMode()) - data = Dynarmic::Common::Swap64(data); - - return data; -} - -void ARMul_State::WriteMemory8(u32 address, u8 data) -{ -// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); - - user_callbacks->MemoryWrite8(address, data); -} - -void ARMul_State::WriteMemory16(u32 address, u16 data) -{ -// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); - - if (InBigEndianMode()) - data = Dynarmic::Common::Swap16(data); - - user_callbacks->MemoryWrite16(address, data); -} - -void ARMul_State::WriteMemory32(u32 address, u32 data) -{ -// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); - - if (InBigEndianMode()) - data = Dynarmic::Common::Swap32(data); - - user_callbacks->MemoryWrite32(address, data); -} - -void ARMul_State::WriteMemory64(u32 address, u64 data) -{ -// CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); - - if (InBigEndianMode()) - data = Dynarmic::Common::Swap64(data); - - user_callbacks->MemoryWrite64(address, data); -} - - -// Reads from the CP15 registers. Used with implementation of the MRC instruction. -// Note that since the 3DS does not have the hypervisor extensions, these registers -// are not implemented. -u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const -{ - // Unprivileged registers - if (crn == 13 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 2) - return CP15[CP15_THREAD_UPRW]; - - if (opcode_2 == 3) - return CP15[CP15_THREAD_URO]; - } - - if (InAPrivilegedMode()) - { - if (crn == 0 && opcode_1 == 0) - { - if (crm == 0) - { - if (opcode_2 == 0) - return CP15[CP15_MAIN_ID]; - - if (opcode_2 == 1) - return CP15[CP15_CACHE_TYPE]; - - if (opcode_2 == 3) - return CP15[CP15_TLB_TYPE]; - - if (opcode_2 == 5) - return CP15[CP15_CPU_ID]; - } - else if (crm == 1) - { - if (opcode_2 == 0) - return CP15[CP15_PROCESSOR_FEATURE_0]; - - if (opcode_2 == 1) - return CP15[CP15_PROCESSOR_FEATURE_1]; - - if (opcode_2 == 2) - return CP15[CP15_DEBUG_FEATURE_0]; - - if (opcode_2 == 4) - return CP15[CP15_MEMORY_MODEL_FEATURE_0]; - - if (opcode_2 == 5) - return CP15[CP15_MEMORY_MODEL_FEATURE_1]; - - if (opcode_2 == 6) - return CP15[CP15_MEMORY_MODEL_FEATURE_2]; - - if (opcode_2 == 7) - return CP15[CP15_MEMORY_MODEL_FEATURE_3]; - } - else if (crm == 2) - { - if (opcode_2 == 0) - return CP15[CP15_ISA_FEATURE_0]; - - if (opcode_2 == 1) - return CP15[CP15_ISA_FEATURE_1]; - - if (opcode_2 == 2) - return CP15[CP15_ISA_FEATURE_2]; - - if (opcode_2 == 3) - return CP15[CP15_ISA_FEATURE_3]; - - if (opcode_2 == 4) - return CP15[CP15_ISA_FEATURE_4]; - } - } - - if (crn == 1 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - return CP15[CP15_CONTROL]; - - if (opcode_2 == 1) - return CP15[CP15_AUXILIARY_CONTROL]; - - if (opcode_2 == 2) - return CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; - } - - if (crn == 2 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - return CP15[CP15_TRANSLATION_BASE_TABLE_0]; - - if (opcode_2 == 1) - return CP15[CP15_TRANSLATION_BASE_TABLE_1]; - - if (opcode_2 == 2) - return CP15[CP15_TRANSLATION_BASE_CONTROL]; - } - - if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) - return CP15[CP15_DOMAIN_ACCESS_CONTROL]; - - if (crn == 5 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - return CP15[CP15_FAULT_STATUS]; - - if (opcode_2 == 1) - return CP15[CP15_INSTR_FAULT_STATUS]; - } - - if (crn == 6 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - return CP15[CP15_FAULT_ADDRESS]; - - if (opcode_2 == 1) - return CP15[CP15_WFAR]; - } - - if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0) - return CP15[CP15_PHYS_ADDRESS]; - - if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) - return CP15[CP15_DATA_CACHE_LOCKDOWN]; - - if (crn == 10 && opcode_1 == 0) - { - if (crm == 0 && opcode_2 == 0) - return CP15[CP15_TLB_LOCKDOWN]; - - if (crm == 2) - { - if (opcode_2 == 0) - return CP15[CP15_PRIMARY_REGION_REMAP]; - - if (opcode_2 == 1) - return CP15[CP15_NORMAL_REGION_REMAP]; - } - } - - if (crn == 13 && crm == 0) - { - if (opcode_2 == 0) - return CP15[CP15_PID]; - - if (opcode_2 == 1) - return CP15[CP15_CONTEXT_ID]; - - if (opcode_2 == 4) - return CP15[CP15_THREAD_PRW]; - } - - if (crn == 15) - { - if (opcode_1 == 0 && crm == 12) - { - if (opcode_2 == 0) - return CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; - - if (opcode_2 == 1) - return CP15[CP15_CYCLE_COUNTER]; - - if (opcode_2 == 2) - return CP15[CP15_COUNT_0]; - - if (opcode_2 == 3) - return CP15[CP15_COUNT_1]; - } - - if (opcode_1 == 5 && opcode_2 == 2) - { - if (crm == 5) - return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; - - if (crm == 6) - return CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS]; - - if (crm == 7) - return CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE]; - } - - if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) - return CP15[CP15_TLB_DEBUG_CONTROL]; - } - } - -// LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); - ASSERT_MSG(false, "MRC CRn={}, CRm={}, OP1={} OP2={} is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); - return 0; -} - -// Write to the CP15 registers. Used with implementation of the MCR instruction. -// Note that since the 3DS does not have the hypervisor extensions, these registers -// are not implemented. -void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) -{ - if (InAPrivilegedMode()) - { - if (crn == 1 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - CP15[CP15_CONTROL] = value; - else if (opcode_2 == 1) - CP15[CP15_AUXILIARY_CONTROL] = value; - else if (opcode_2 == 2) - CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; - } - else if (crn == 2 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; - else if (opcode_2 == 1) - CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; - else if (opcode_2 == 2) - CP15[CP15_TRANSLATION_BASE_CONTROL] = value; - } - else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) - { - CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; - } - else if (crn == 5 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - CP15[CP15_FAULT_STATUS] = value; - else if (opcode_2 == 1) - CP15[CP15_INSTR_FAULT_STATUS] = value; - } - else if (crn == 6 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - CP15[CP15_FAULT_ADDRESS] = value; - else if (opcode_2 == 1) - CP15[CP15_WFAR] = value; - } - else if (crn == 7 && opcode_1 == 0) - { - if (crm == 0 && opcode_2 == 4) - { - CP15[CP15_WAIT_FOR_INTERRUPT] = value; - } - else if (crm == 4 && opcode_2 == 0) - { - // NOTE: Not entirely accurate. This should do permission checks. - //CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); - } - else if (crm == 5) - { - if (opcode_2 == 0) - CP15[CP15_INVALIDATE_INSTR_CACHE] = value; - else if (opcode_2 == 1) - CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value; - else if (opcode_2 == 2) - CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value; - else if (opcode_2 == 6) - CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; - else if (opcode_2 == 7) - CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; - } - else if (crm == 6) - { - if (opcode_2 == 0) - CP15[CP15_INVALIDATE_DATA_CACHE] = value; - else if (opcode_2 == 1) - CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; - else if (opcode_2 == 2) - CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; - } - else if (crm == 7 && opcode_2 == 0) - { - CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; - } - else if (crm == 10) - { - if (opcode_2 == 0) - CP15[CP15_CLEAN_DATA_CACHE] = value; - else if (opcode_2 == 1) - CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; - else if (opcode_2 == 2) - CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; - } - else if (crm == 14) - { - if (opcode_2 == 0) - CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; - else if (opcode_2 == 1) - CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; - else if (opcode_2 == 2) - CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; - } - } - else if (crn == 8 && opcode_1 == 0) - { - if (crm == 5) - { - if (opcode_2 == 0) - CP15[CP15_INVALIDATE_ITLB] = value; - else if (opcode_2 == 1) - CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value; - else if (opcode_2 == 2) - CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; - else if (opcode_2 == 3) - CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; - } - else if (crm == 6) - { - if (opcode_2 == 0) - CP15[CP15_INVALIDATE_DTLB] = value; - else if (opcode_2 == 1) - CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value; - else if (opcode_2 == 2) - CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; - else if (opcode_2 == 3) - CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; - } - else if (crm == 7) - { - if (opcode_2 == 0) - CP15[CP15_INVALIDATE_UTLB] = value; - else if (opcode_2 == 1) - CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value; - else if (opcode_2 == 2) - CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value; - else if (opcode_2 == 3) - CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; - } - } - else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) - { - CP15[CP15_DATA_CACHE_LOCKDOWN] = value; - } - else if (crn == 10 && opcode_1 == 0) - { - if (crm == 0 && opcode_2 == 0) - { - CP15[CP15_TLB_LOCKDOWN] = value; - } - else if (crm == 2) - { - if (opcode_2 == 0) - CP15[CP15_PRIMARY_REGION_REMAP] = value; - else if (opcode_2 == 1) - CP15[CP15_NORMAL_REGION_REMAP] = value; - } - } - else if (crn == 13 && opcode_1 == 0 && crm == 0) - { - if (opcode_2 == 0) - CP15[CP15_PID] = value; - else if (opcode_2 == 1) - CP15[CP15_CONTEXT_ID] = value; - else if (opcode_2 == 3) - CP15[CP15_THREAD_URO] = value; - else if (opcode_2 == 4) - CP15[CP15_THREAD_PRW] = value; - } - else if (crn == 15) - { - if (opcode_1 == 0 && crm == 12) - { - if (opcode_2 == 0) - CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; - else if (opcode_2 == 1) - CP15[CP15_CYCLE_COUNTER] = value; - else if (opcode_2 == 2) - CP15[CP15_COUNT_0] = value; - else if (opcode_2 == 3) - CP15[CP15_COUNT_1] = value; - } - else if (opcode_1 == 5) - { - if (crm == 4) - { - if (opcode_2 == 2) - CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; - else if (opcode_2 == 4) - CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; - } - else if (crm == 5 && opcode_2 == 2) - { - CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; - } - else if (crm == 6 && opcode_2 == 2) - { - CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; - } - else if (crm == 7 && opcode_2 == 2) - { - CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; - } - } - else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) - { - CP15[CP15_TLB_DEBUG_CONTROL] = value; - } - } - } - - // Unprivileged registers - if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) - { - CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; - } - else if (crn == 7 && opcode_1 == 0 && crm == 10) - { - if (opcode_2 == 4) - CP15[CP15_DATA_SYNC_BARRIER] = value; - else if (opcode_2 == 5) - CP15[CP15_DATA_MEMORY_BARRIER] = value; - } - else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) - { - CP15[CP15_THREAD_UPRW] = value; - } -} diff --git a/tests/A32/skyeye_interpreter/skyeye_common/armstate.h b/tests/A32/skyeye_interpreter/skyeye_common/armstate.h deleted file mode 100644 index 4fdf20ed..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/armstate.h +++ /dev/null @@ -1,256 +0,0 @@ -/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator. - Copyright (C) 1994 Advanced RISC Machines Ltd. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#pragma once - -#include -#include - -#include - -#include "common/common_types.h" -#include "A32/skyeye_interpreter/skyeye_common/arm_regformat.h" - -// Signal levels -enum { - LOW = 0, - HIGH = 1, - LOWHIGH = 1, - HIGHLOW = 2 -}; - -// Cache types -enum { - NONCACHE = 0, - DATACACHE = 1, - INSTCACHE = 2, -}; - -// ARM privilege modes -enum PrivilegeMode { - USER32MODE = 16, - FIQ32MODE = 17, - IRQ32MODE = 18, - SVC32MODE = 19, - ABORT32MODE = 23, - UNDEF32MODE = 27, - SYSTEM32MODE = 31 -}; - -// ARM privilege mode register banks -enum { - USERBANK = 0, - FIQBANK = 1, - IRQBANK = 2, - SVCBANK = 3, - ABORTBANK = 4, - UNDEFBANK = 5, - DUMMYBANK = 6, - SYSTEMBANK = 7 -}; - -// Hardware vector addresses -enum { - ARMResetV = 0, - ARMUndefinedInstrV = 4, - ARMSWIV = 8, - ARMPrefetchAbortV = 12, - ARMDataAbortV = 16, - ARMAddrExceptnV = 20, - ARMIRQV = 24, - ARMFIQV = 28, - ARMErrorV = 32, // This is an offset, not an address! - - ARMul_ResetV = ARMResetV, - ARMul_UndefinedInstrV = ARMUndefinedInstrV, - ARMul_SWIV = ARMSWIV, - ARMul_PrefetchAbortV = ARMPrefetchAbortV, - ARMul_DataAbortV = ARMDataAbortV, - ARMul_AddrExceptnV = ARMAddrExceptnV, - ARMul_IRQV = ARMIRQV, - ARMul_FIQV = ARMFIQV -}; - -// Coprocessor status values -enum { - ARMul_FIRST = 0, - ARMul_TRANSFER = 1, - ARMul_BUSY = 2, - ARMul_DATA = 3, - ARMul_INTERRUPT = 4, - ARMul_DONE = 0, - ARMul_CANT = 1, - ARMul_INC = 3 -}; - -// Instruction condition codes -enum ConditionCode { - EQ = 0, - NE = 1, - CS = 2, - CC = 3, - MI = 4, - PL = 5, - VS = 6, - VC = 7, - HI = 8, - LS = 9, - GE = 10, - LT = 11, - GT = 12, - LE = 13, - AL = 14, - NV = 15, -}; - -// Flags for use with the APSR. -enum : u32 { - NBIT = (1U << 31U), - ZBIT = (1 << 30), - CBIT = (1 << 29), - VBIT = (1 << 28), - QBIT = (1 << 27), - JBIT = (1 << 24), - EBIT = (1 << 9), - ABIT = (1 << 8), - IBIT = (1 << 7), - FBIT = (1 << 6), - TBIT = (1 << 5), - - // Masks for groups of bits in the APSR. - MODEBITS = 0x1F, - INTBITS = 0x1C0, -}; - -// Values for Emulate. -enum { - STOP = 0, // Stop - CHANGEMODE = 1, // Change mode - ONCE = 2, // Execute just one iteration - RUN = 3 // Continuous execution -}; - - -struct ARMul_State final -{ -public: - explicit ARMul_State(PrivilegeMode initial_mode); - - void ChangePrivilegeMode(u32 new_mode); - void Reset(); - - // Reads/writes data in big/little endian format based on the - // state of the E (endian) bit in the APSR. - u8 ReadMemory8(u32 address) const; - u16 ReadMemory16(u32 address) const; - u32 ReadMemory32(u32 address) const; - u64 ReadMemory64(u32 address) const; - void WriteMemory8(u32 address, u8 data); - void WriteMemory16(u32 address, u16 data); - void WriteMemory32(u32 address, u32 data); - void WriteMemory64(u32 address, u64 data); - - u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; - void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); - - // Exclusive memory access functions - bool IsExclusiveMemoryAccess(u32 address) const { - return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK); - } - void SetExclusiveMemoryAddress(u32 address) { - exclusive_tag = address & RESERVATION_GRANULE_MASK; - exclusive_state = true; - } - void UnsetExclusiveMemoryAddress() { - exclusive_tag = 0xFFFFFFFF; - exclusive_state = false; - } - - // Whether or not the given CPU is in big endian mode (E bit is set) - bool InBigEndianMode() const { - return (Cpsr & (1 << 9)) != 0; - } - // Whether or not the given CPU is in a mode other than user mode. - bool InAPrivilegedMode() const { - return (Mode != USER32MODE); - } - // Note that for the 3DS, a Thumb instruction will only ever be - // two bytes in size. Thus we don't need to worry about ThumbEE - // or Thumb-2 where instructions can be 4 bytes in length. - u32 GetInstructionSize() const { - return TFlag ? 2 : 4; - } - - std::array Reg{}; // The current register file - std::array Reg_usr{}; - std::array Reg_svc{}; // R13_SVC R14_SVC - std::array Reg_abort{}; // R13_ABORT R14_ABORT - std::array Reg_undef{}; // R13 UNDEF R14 UNDEF - std::array Reg_irq{}; // R13_IRQ R14_IRQ - std::array Reg_firq{}; // R8---R14 FIRQ - std::array Spsr{}; // The exception psr's - std::array CP15{}; - - // FPSID, FPSCR, and FPEXC - std::array VFP{}; - - // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31). - // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31), - // and only 32 singleword registers are accessible (S0-S31). - std::array ExtReg{}; - - u32 Emulate; // To start and stop emulation - u32 Cpsr; // The current PSR - u32 Spsr_copy; - u32 phys_pc; - - u32 Mode; // The current mode - u32 Bank; // The current register bank - - u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed - unsigned int shifter_carry_out; - - u32 TFlag; // Thumb state - - unsigned long long NumInstrs; // The number of instructions executed - unsigned NumInstrsToExecute; - - unsigned NresetSig; // Reset the processor - unsigned NfiqSig; - unsigned NirqSig; - - unsigned abortSig; - unsigned NtransSig; - unsigned bigendSig; - unsigned syscallSig; - - // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per - // process for our purposes), not per ARMul_State (which tracks CPU core state). - std::unordered_map instruction_cache; - - void ResetMPCoreCP15Registers(); - - // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. - // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to - // support LDR/STREXD. - static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; - - u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode - bool exclusive_state; - - Dynarmic::A32::UserCallbacks* user_callbacks; -}; diff --git a/tests/A32/skyeye_interpreter/skyeye_common/armsupp.cpp b/tests/A32/skyeye_interpreter/skyeye_common/armsupp.cpp deleted file mode 100644 index d268a89a..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/armsupp.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator. - Copyright (C) 1994 Advanced RISC Machines Ltd. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -//#include "common/logging/log.h" - -#include "A32/skyeye_interpreter/skyeye_common/arm_regformat.h" -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" -#include "A32/skyeye_interpreter/skyeye_common/armsupp.h" - -// Unsigned sum of absolute difference -u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) -{ - if (left > right) - return left - right; - - return right - left; -} - -// Add with carry, indicates if a carry-out or signed overflow occurred. -u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) -{ - u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; - s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; - u64 result = (unsigned_sum & 0xFFFFFFFF); - - if (carry_out_occurred) - *carry_out_occurred = (result != unsigned_sum); - - if (overflow_occurred) - *overflow_occurred = ((s64)(s32)result != signed_sum); - - return (u32)result; -} - -// Compute whether an addition of A and B, giving RESULT, overflowed. -bool AddOverflow(u32 a, u32 b, u32 result) -{ - return ((NEG(a) && NEG(b) && POS(result)) || - (POS(a) && POS(b) && NEG(result))); -} - -// Compute whether a subtraction of A and B, giving RESULT, overflowed. -bool SubOverflow(u32 a, u32 b, u32 result) -{ - return ((NEG(a) && POS(b) && POS(result)) || - (POS(a) && NEG(b) && NEG(result))); -} - -// Returns true if the Q flag should be set as a result of overflow. -bool ARMul_AddOverflowQ(u32 a, u32 b) -{ - u32 result = a + b; - if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) - return true; - - return false; -} - -// 8-bit signed saturated addition -u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) -{ - u8 result = left + right; - - if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { - if (left & 0x80) - result = 0x80; - else - result = 0x7F; - } - - return result; -} - -// 8-bit signed saturated subtraction -u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) -{ - u8 result = left - right; - - if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { - if (left & 0x80) - result = 0x80; - else - result = 0x7F; - } - - return result; -} - -// 16-bit signed saturated addition -u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) -{ - u16 result = left + right; - - if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { - if (left & 0x8000) - result = 0x8000; - else - result = 0x7FFF; - } - - return result; -} - -// 16-bit signed saturated subtraction -u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) -{ - u16 result = left - right; - - if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { - if (left & 0x8000) - result = 0x8000; - else - result = 0x7FFF; - } - - return result; -} - -// 8-bit unsigned saturated addition -u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) -{ - u8 result = left + right; - - if (result < left) - result = 0xFF; - - return result; -} - -// 16-bit unsigned saturated addition -u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) -{ - u16 result = left + right; - - if (result < left) - result = 0xFFFF; - - return result; -} - -// 8-bit unsigned saturated subtraction -u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) -{ - if (left <= right) - return 0; - - return left - right; -} - -// 16-bit unsigned saturated subtraction -u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) -{ - if (left <= right) - return 0; - - return left - right; -} - -// Signed saturation. -u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) -{ - const u32 max = (1 << shift) - 1; - const s32 top = (value >> shift); - - if (top > 0) { - *saturation_occurred = true; - return max; - } - else if (top < -1) { - *saturation_occurred = true; - return ~max; - } - - *saturation_occurred = false; - return (u32)value; -} - -// Unsigned saturation -u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) -{ - const u32 max = (1 << shift) - 1; - - if (value < 0) { - *saturation_occurred = true; - return 0; - } else if ((u32)value > max) { - *saturation_occurred = true; - return max; - } - - *saturation_occurred = false; - return (u32)value; -} diff --git a/tests/A32/skyeye_interpreter/skyeye_common/armsupp.h b/tests/A32/skyeye_interpreter/skyeye_common/armsupp.h deleted file mode 100644 index 391309fa..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/armsupp.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_types.h" - -#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) -#define BIT(s, n) ((s >> (n)) & 1) - -#define POS(i) ( (~(i)) >> 31 ) -#define NEG(i) ( (i) >> 31 ) - -bool AddOverflow(u32, u32, u32); -bool SubOverflow(u32, u32, u32); - -u32 AddWithCarry(u32, u32, u32, bool*, bool*); -bool ARMul_AddOverflowQ(u32, u32); - -u8 ARMul_SignedSaturatedAdd8(u8, u8); -u8 ARMul_SignedSaturatedSub8(u8, u8); -u16 ARMul_SignedSaturatedAdd16(u16, u16); -u16 ARMul_SignedSaturatedSub16(u16, u16); - -u8 ARMul_UnsignedSaturatedAdd8(u8, u8); -u16 ARMul_UnsignedSaturatedAdd16(u16, u16); -u8 ARMul_UnsignedSaturatedSub8(u8, u8); -u16 ARMul_UnsignedSaturatedSub16(u16, u16); -u8 ARMul_UnsignedAbsoluteDifference(u8, u8); -u32 ARMul_SignedSatQ(s32, u8, bool*); -u32 ARMul_UnsignedSatQ(s32, u8, bool*); diff --git a/tests/A32/skyeye_interpreter/skyeye_common/vfp/asm_vfp.h b/tests/A32/skyeye_interpreter/skyeye_common/vfp/asm_vfp.h deleted file mode 100644 index 1187924f..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/vfp/asm_vfp.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * arch/arm/include/asm/vfp.h - * - * VFP register definitions. - * First, the standard VFP set. - */ - -#pragma once - -// ARM11 MPCore FPSID Information -// Note that these are used as values and not as flags. -enum : u32 { - VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0 - VFP_FPSID_SW = 0, // Software emulation bit value - VFP_FPSID_SUBARCH = 0x1, // Subarchitecture version number - VFP_FPSID_PARTNUM = 0x20, // Part number - VFP_FPSID_VARIANT = 0xB, // Variant number - VFP_FPSID_REVISION = 0x4 // Revision number -}; - -// FPEXC bits -enum : u32 { - FPEXC_EX = (1U << 31U), - FPEXC_EN = (1 << 30), - FPEXC_DEX = (1 << 29), - FPEXC_FP2V = (1 << 28), - FPEXC_VV = (1 << 27), - FPEXC_TFV = (1 << 26), - FPEXC_LENGTH_BIT = (8), - FPEXC_LENGTH_MASK = (7 << FPEXC_LENGTH_BIT), - FPEXC_IDF = (1 << 7), - FPEXC_IXF = (1 << 4), - FPEXC_UFF = (1 << 3), - FPEXC_OFF = (1 << 2), - FPEXC_DZF = (1 << 1), - FPEXC_IOF = (1 << 0), - FPEXC_TRAP_MASK = (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF) -}; - -// FPSCR Flags -enum : u32 { - FPSCR_NFLAG = (1U << 31U), // Negative condition flag - FPSCR_ZFLAG = (1 << 30), // Zero condition flag - FPSCR_CFLAG = (1 << 29), // Carry condition flag - FPSCR_VFLAG = (1 << 28), // Overflow condition flag - - FPSCR_QC = (1 << 27), // Cumulative saturation bit - FPSCR_AHP = (1 << 26), // Alternative half-precision control bit - FPSCR_DEFAULT_NAN = (1 << 25), // Default NaN mode control bit - FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit - FPSCR_RMODE_MASK = (3 << 22), // Rounding Mode bit mask - FPSCR_STRIDE_MASK = (3 << 20), // Vector stride bit mask - FPSCR_LENGTH_MASK = (7 << 16), // Vector length bit mask - - FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable. - FPSCR_IXE = (1 << 12), // Inexact exception trap enable - FPSCR_UFE = (1 << 11), // Undeflow exception trap enable - FPSCR_OFE = (1 << 10), // Overflow exception trap enable - FPSCR_DZE = (1 << 9), // Division by Zero exception trap enable - FPSCR_IOE = (1 << 8), // Invalid Operation exception trap enable - - FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit - FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit - FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit - FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit - FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit - FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit -}; - -// FPSCR bit offsets -enum : u32 { - FPSCR_RMODE_BIT = 22, - FPSCR_STRIDE_BIT = 20, - FPSCR_LENGTH_BIT = 16, -}; - -// FPSCR rounding modes -enum : u32 { - FPSCR_ROUND_NEAREST = (0 << 22), - FPSCR_ROUND_PLUSINF = (1 << 22), - FPSCR_ROUND_MINUSINF = (2 << 22), - FPSCR_ROUND_TOZERO = (3 << 22) -}; diff --git a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp.cpp b/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp.cpp deleted file mode 100644 index e969dc48..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - armvfp.c - ARM VFPv3 emulation unit - Copyright (C) 2003 Skyeye Develop Group - for help please send mail to - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Note: this file handles interface with arm core and vfp registers */ - -#include "common/assert.h" -#include "common/common_types.h" - -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/asm_vfp.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp.h" - -#define LOG_INFO(...) do{}while(0) -#define LOG_TRACE(...) do{}while(0) - -void VFPInit(ARMul_State* state) -{ - state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | - VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; - state->VFP[VFP_FPEXC] = 0; - state->VFP[VFP_FPSCR] = 0; - - // ARM11 MPCore instruction register reset values. - state->VFP[VFP_FPINST] = 0xEE000A00; - state->VFP[VFP_FPINST2] = 0; - - // ARM11 MPCore feature register values. - state->VFP[VFP_MVFR0] = 0x11111111; - state->VFP[VFP_MVFR1] = 0; -} - -void VMOVBRS(ARMul_State* state, u32 to_arm, [[maybe_unused]] u32 t, u32 n, u32* value) -{ - if (to_arm) - { - *value = state->ExtReg[n]; - } - else - { - state->ExtReg[n] = *value; - } -} - -void VMOVBRRD(ARMul_State* state, u32 to_arm, [[maybe_unused]] u32 t, [[maybe_unused]] u32 t2, - u32 n, u32* value1, u32* value2) -{ - if (to_arm) - { - *value2 = state->ExtReg[n*2+1]; - *value1 = state->ExtReg[n*2]; - } - else - { - state->ExtReg[n*2+1] = *value2; - state->ExtReg[n*2] = *value1; - } -} -void VMOVBRRSS(ARMul_State* state, u32 to_arm, [[maybe_unused]] u32 t, [[maybe_unused]] u32 t2, - u32 n, u32* value1, u32* value2) -{ - if (to_arm) - { - *value1 = state->ExtReg[n+0]; - *value2 = state->ExtReg[n+1]; - } - else - { - state->ExtReg[n+0] = *value1; - state->ExtReg[n+1] = *value2; - } -} - -void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) -{ - if (single) - { - state->ExtReg[d] = imm; - } - else - { - /* Check endian please */ - state->ExtReg[d*2+1] = imm; - state->ExtReg[d*2] = 0; - } -} -void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) -{ - if (single) - { - state->ExtReg[d] = state->ExtReg[m]; - } - else - { - /* Check endian please */ - state->ExtReg[d*2+1] = state->ExtReg[m*2+1]; - state->ExtReg[d*2] = state->ExtReg[m*2]; - } -} - -/* Miscellaneous functions */ -s32 vfp_get_float(ARMul_State* state, unsigned int reg) -{ - LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]", reg, state->ExtReg[reg]); - return state->ExtReg[reg]; -} - -void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) -{ - LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]", reg, val); - state->ExtReg[reg] = val; -} - -u64 vfp_get_double(ARMul_State* state, unsigned int reg) -{ - u64 result = ((u64) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2]; - LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]", reg * 2 + 1, reg * 2, result); - return result; -} - -void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) -{ - LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]", reg * 2 + 1, reg * 2, (u32)(val >> 32), (u32)(val & 0xffffffff)); - state->ExtReg[reg*2] = (u32) (val & 0xffffffff); - state->ExtReg[reg*2+1] = (u32) (val>>32); -} - -/* - * Process bitmask of exception conditions. (from vfpmodule.c) - */ -void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x", exceptions); - - if (exceptions == VFP_EXCEPTION_ERROR) { - ASSERT_MSG(false, "unhandled bounce {:08x}", inst); - } - - /* - * If any of the status flags are set, update the FPSCR. - * Comparison instructions always return at least one of - * these flags set. - */ - if (exceptions & (FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG)) - fpscr &= ~(FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG); - - fpscr |= exceptions; - - state->VFP[VFP_FPSCR] = fpscr; -} diff --git a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp.h b/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp.h deleted file mode 100644 index 550dc6ff..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - vfp/vfp.h - ARM VFPv3 emulation unit - vfp interface - Copyright (C) 2003 Skyeye Develop Group - for help please send mail to - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#pragma once - -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */ - -#define LOG_INFO(...) do{}while(0) -#define LOG_TRACE(...) do{}while(0) - -#define VFP_DEBUG_UNTESTED(x) LOG_TRACE(Core_ARM11, "in func %s, " #x " untested", __FUNCTION__); -#define CHECK_VFP_ENABLED -#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - -void VFPInit(ARMul_State* state); - -s32 vfp_get_float(ARMul_State* state, u32 reg); -void vfp_put_float(ARMul_State* state, s32 val, u32 reg); -u64 vfp_get_double(ARMul_State* state, u32 reg); -void vfp_put_double(ARMul_State* state, u64 val, u32 reg); -void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr); -u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); -u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); - -void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value); -void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2); -void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2); -void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm); -void VMOVR(ARMul_State* state, u32 single, u32 d, u32 imm); diff --git a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp_helper.h b/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp_helper.h deleted file mode 100644 index 5da7f483..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfp_helper.h +++ /dev/null @@ -1,448 +0,0 @@ -/* - vfp/vfp.h - ARM VFPv3 emulation unit - SoftFloat lib helper - Copyright (C) 2003 Skyeye Develop Group - for help please send mail to - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * The following code is derivative from Linux Android kernel vfp - * floating point support. - * - * Copyright (C) 2004 ARM Limited. - * Written by Deep Blue Solutions Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#pragma once - -#include -#include "common/common_types.h" -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/asm_vfp.h" - -#define LOG_INFO(...) do{}while(0) -#define LOG_TRACE(...) do{}while(0) - -#define do_div(n, base) {n/=base;} - -enum : u32 { - FOP_MASK = 0x00b00040, - FOP_FMAC = 0x00000000, - FOP_FNMAC = 0x00000040, - FOP_FMSC = 0x00100000, - FOP_FNMSC = 0x00100040, - FOP_FMUL = 0x00200000, - FOP_FNMUL = 0x00200040, - FOP_FADD = 0x00300000, - FOP_FSUB = 0x00300040, - FOP_FDIV = 0x00800000, - FOP_EXT = 0x00b00040 -}; - -#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4) - -enum : u32 { - FEXT_MASK = 0x000f0080, - FEXT_FCPY = 0x00000000, - FEXT_FABS = 0x00000080, - FEXT_FNEG = 0x00010000, - FEXT_FSQRT = 0x00010080, - FEXT_FCMP = 0x00040000, - FEXT_FCMPE = 0x00040080, - FEXT_FCMPZ = 0x00050000, - FEXT_FCMPEZ = 0x00050080, - FEXT_FCVT = 0x00070080, - FEXT_FUITO = 0x00080000, - FEXT_FSITO = 0x00080080, - FEXT_FTOUI = 0x000c0000, - FEXT_FTOUIZ = 0x000c0080, - FEXT_FTOSI = 0x000d0000, - FEXT_FTOSIZ = 0x000d0080 -}; - -#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) - -#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) -#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18) -#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) -#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1) -#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) -#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3) - -#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00) - -inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) -{ - if (shift) { - if (shift < 32) - val = val >> shift | ((val << (32 - shift)) != 0); - else - val = val != 0; - } - return val; -} - -inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) -{ - if (shift) { - if (shift < 64) - val = val >> shift | ((val << (64 - shift)) != 0); - else - val = val != 0; - } - return val; -} - -inline u32 vfp_hi64to32jamming(u64 val) -{ - u32 v; - u32 highval = val >> 32; - u32 lowval = val & 0xffffffff; - - if (lowval >= 1) - v = highval | 1; - else - v = highval; - - return v; -} - -inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) -{ - *resl = nl + ml; - *resh = nh + mh; - if (*resl < nl) - *resh += 1; -} - -inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) -{ - *resl = nl - ml; - *resh = nh - mh; - if (*resl > nl) - *resh -= 1; -} - -inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m) -{ - u32 nh, nl, mh, ml; - u64 rh, rma, rmb, rl; - - nl = static_cast(n); - ml = static_cast(m); - rl = (u64)nl * ml; - - nh = n >> 32; - rma = (u64)nh * ml; - - mh = m >> 32; - rmb = (u64)nl * mh; - rma += rmb; - - rh = (u64)nh * mh; - rh += ((u64)(rma < rmb) << 32) + (rma >> 32); - - rma <<= 32; - rl += rma; - rh += (rl < rma); - - *resl = rl; - *resh = rh; -} - -inline void shift64left(u64* resh, u64* resl, u64 n) -{ - *resh = n >> 63; - *resl = n << 1; -} - -inline u64 vfp_hi64multiply64(u64 n, u64 m) -{ - u64 rh, rl; - mul64to128(&rh, &rl, n, m); - return rh | (rl != 0); -} - -inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) -{ - u64 mh, ml, remh, reml, termh, terml, z; - - if (nh >= m) - return ~0ULL; - mh = m >> 32; - if (mh << 32 <= nh) { - z = 0xffffffff00000000ULL; - } else { - z = nh; - do_div(z, mh); - z <<= 32; - } - mul64to128(&termh, &terml, m, z); - sub128(&remh, &reml, nh, nl, termh, terml); - ml = m << 32; - while ((s64)remh < 0) { - z -= 0x100000000ULL; - add128(&remh, &reml, remh, reml, mh, ml); - } - remh = (remh << 32) | (reml >> 32); - if (mh << 32 <= remh) { - z |= 0xffffffff; - } else { - do_div(remh, mh); - z |= remh; - } - return z; -} - -// Operations on unpacked elements -#define vfp_sign_negate(sign) (sign ^ 0x8000) - -// Single-precision -struct vfp_single { - s16 exponent; - u16 sign; - u32 significand; -}; - -// VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa -// VFP_SINGLE_EXPONENT_BITS - number of bits in the exponent -// VFP_SINGLE_LOW_BITS - number of low bits in the unpacked significand -// which are not propagated to the float upon packing. -#define VFP_SINGLE_MANTISSA_BITS (23) -#define VFP_SINGLE_EXPONENT_BITS (8) -#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2) -#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1) - -// The bit in an unpacked float which indicates that it is a quiet NaN -#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS)) - -// Operations on packed single-precision numbers -#define vfp_single_packed_sign(v) ((v) & 0x80000000) -#define vfp_single_packed_negate(v) ((v) ^ 0x80000000) -#define vfp_single_packed_abs(v) ((v) & ~0x80000000) -#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) -#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) - -enum : u32 { - VFP_NUMBER = (1 << 0), - VFP_ZERO = (1 << 1), - VFP_DENORMAL = (1 << 2), - VFP_INFINITY = (1 << 3), - VFP_NAN = (1 << 4), - VFP_NAN_SIGNAL = (1 << 5), - - VFP_QNAN = (VFP_NAN), - VFP_SNAN = (VFP_NAN|VFP_NAN_SIGNAL) -}; - -inline int vfp_single_type(const vfp_single* s) -{ - int type = VFP_NUMBER; - if (s->exponent == 255) { - if (s->significand == 0) - type = VFP_INFINITY; - else if (s->significand & VFP_SINGLE_SIGNIFICAND_QNAN) - type = VFP_QNAN; - else - type = VFP_SNAN; - } else if (s->exponent == 0) { - if (s->significand == 0) - type |= VFP_ZERO; - else - type |= VFP_DENORMAL; - } - return type; -} - -// Unpack a single-precision float. Note that this returns the magnitude -// of the single-precision float mantissa with the 1. if necessary, -// aligned to bit 30. -inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) -{ - u32 exceptions = 0; - s->sign = vfp_single_packed_sign(val) >> 16; - s->exponent = vfp_single_packed_exponent(val); - - u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2; - if (s->exponent && s->exponent != 255) - significand |= 0x40000000; - s->significand = significand; - - // If flush-to-zero mode is enabled, turn the denormal into zero. - // On a VFPv2 architecture, the sign of the zero is always positive. - if ((fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_single_type(s) & VFP_DENORMAL) != 0) { - s->sign = 0; - s->exponent = 0; - s->significand = 0; - exceptions |= FPSCR_IDC; - } - return exceptions; -} - -// Re-pack a single-precision float. This assumes that the float is -// already normalised such that the MSB is bit 30, _not_ bit 31. -inline s32 vfp_single_pack(const vfp_single* s) -{ - u32 val = (s->sign << 16) + - (s->exponent << VFP_SINGLE_MANTISSA_BITS) + - (s->significand >> VFP_SINGLE_LOW_BITS); - return (s32)val; -} - - -u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, const char* func); - -// Double-precision -struct vfp_double { - s16 exponent; - u16 sign; - u64 significand; -}; - -#define VFP_DOUBLE_MANTISSA_BITS (52) -#define VFP_DOUBLE_EXPONENT_BITS (11) -#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2) -#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1) - -// The bit in an unpacked double which indicates that it is a quiet NaN -#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS)) - -// Operations on packed single-precision numbers -#define vfp_double_packed_sign(v) ((v) & (1ULL << 63)) -#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63)) -#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63)) -#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) -#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) - -inline int vfp_double_type(const vfp_double* s) -{ - int type = VFP_NUMBER; - if (s->exponent == 2047) { - if (s->significand == 0) - type = VFP_INFINITY; - else if (s->significand & VFP_DOUBLE_SIGNIFICAND_QNAN) - type = VFP_QNAN; - else - type = VFP_SNAN; - } else if (s->exponent == 0) { - if (s->significand == 0) - type |= VFP_ZERO; - else - type |= VFP_DENORMAL; - } - return type; -} - -// Unpack a double-precision float. Note that this returns the magnitude -// of the double-precision float mantissa with the 1. if necessary, -// aligned to bit 62. -inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) -{ - u32 exceptions = 0; - s->sign = vfp_double_packed_sign(val) >> 48; - s->exponent = vfp_double_packed_exponent(val); - - u64 significand = ((u64)val << (64 - VFP_DOUBLE_MANTISSA_BITS)) >> 2; - if (s->exponent && s->exponent != 2047) - significand |= (1ULL << 62); - s->significand = significand; - - // If flush-to-zero mode is enabled, turn the denormal into zero. - // On a VFPv2 architecture, the sign of the zero is always positive. - if ((fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_double_type(s) & VFP_DENORMAL) != 0) { - s->sign = 0; - s->exponent = 0; - s->significand = 0; - exceptions |= FPSCR_IDC; - } - return exceptions; -} - -// Re-pack a double-precision float. This assumes that the float is -// already normalised such that the MSB is bit 30, _not_ bit 31. -inline s64 vfp_double_pack(const vfp_double* s) -{ - u64 val = ((u64)s->sign << 48) + - ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) + - (s->significand >> VFP_DOUBLE_LOW_BITS); - return (s64)val; -} - -u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand); - -// A special flag to tell the normalisation code not to normalise. -#define VFP_NAN_FLAG 0x100 - -// A bit pattern used to indicate the initial (unset) value of the -// exception mask, in case nothing handles an instruction. This -// doesn't include the NAN flag, which get masked out before -// we check for an error. -#define VFP_EXCEPTION_ERROR ((u32)-1 & ~VFP_NAN_FLAG) - -// A flag to tell vfp instruction type. -// OP_SCALAR - This operation always operates in scalar mode -// OP_SD - The instruction exceptionally writes to a single precision result. -// OP_DD - The instruction exceptionally writes to a double precision result. -// OP_SM - The instruction exceptionally reads from a single precision operand. -enum : u32 { - OP_SCALAR = (1 << 0), - OP_SD = (1 << 1), - OP_DD = (1 << 1), - OP_SM = (1 << 2) -}; - -struct op { - u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr); - u32 flags; -}; - -inline u32 fls(u32 x) -{ - int r = 32; - - if (!x) - return 0; - if (!(x & 0xffff0000u)) { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) { - x <<= 1; - r -= 1; - } - return r; - -} - -u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr); -u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double *vdm, u32 fpscr); -u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, const char* func); diff --git a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpdouble.cpp b/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpdouble.cpp deleted file mode 100644 index 41c7a8a1..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpdouble.cpp +++ /dev/null @@ -1,1312 +0,0 @@ -/* - vfp/vfpdouble.c - ARM VFPv3 emulation unit - SoftFloat double instruction - Copyright (C) 2003 Skyeye Develop Group - for help please send mail to - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * This code is derived in part from : - * - Android kernel - * - John R. Housers softfloat library, which - * carries the following notice: - * - * =========================================================================== - * This C source file is part of the SoftFloat IEC/IEEE Floating-point - * Arithmetic Package, Release 2. - * - * Written by John R. Hauser. This work was made possible in part by the - * International Computer Science Institute, located at Suite 600, 1947 Center - * Street, Berkeley, California 94704. Funding was partially provided by the - * National Science Foundation under grant MIP-9311980. The original version - * of this code was written as part of a project to build a fixed-point vector - * processor in collaboration with the University of California at Berkeley, - * overseen by Profs. Nelson Morgan and John Wawrzynek. More information - * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ - * arithmetic/softfloat.html'. - * - * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort - * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT - * TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO - * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY - * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. - * - * Derivative works are acceptable, even for commercial purposes, so long as - * (1) they include prominent notice that the work is derivative, and (2) they - * include prominent notice akin to these three paragraphs for those parts of - * this code that are retained. - * =========================================================================== - */ - -#ifdef _MSC_VER -#pragma warning(disable : 4100 4244 4245) -#endif - -#include -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp_helper.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/asm_vfp.h" - -#define LOG_INFO(...) do{}while(0) -#define LOG_TRACE(...) do{}while(0) - -static struct vfp_double vfp_double_default_qnan = { - 2047, - 0, - VFP_DOUBLE_SIGNIFICAND_QNAN, -}; - -static void vfp_double_dump([[maybe_unused]] const char *str, [[maybe_unused]] vfp_double *d) -{ - LOG_TRACE(Core_ARM11, "VFP: %s: sign=%d exponent=%d significand=%016llx", - str, d->sign != 0, d->exponent, d->significand); -} - -static void vfp_double_normalise_denormal(struct vfp_double *vd) -{ - int bits = 31 - fls((u32)(vd->significand >> 32)); - if (bits == 31) - bits = 63 - fls((u32)vd->significand); - - vfp_double_dump("normalise_denormal: in", vd); - - if (bits) { - vd->exponent -= bits - 1; - vd->significand <<= bits; - } - - vfp_double_dump("normalise_denormal: out", vd); -} - -u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double *vd, u32 fpscr, - [[maybe_unused]] const char *func) -{ - u64 significand, incr; - int exponent, shift, underflow; - u32 rmode; - u32 exceptions = 0; - - vfp_double_dump("pack: in", vd); - - /* - * Infinities and NaNs are a special case. - */ - if (vd->exponent == 2047 && (vd->significand == 0 || exceptions)) - goto pack; - - /* - * Special-case zero. - */ - if (vd->significand == 0) { - vd->exponent = 0; - goto pack; - } - - exponent = vd->exponent; - significand = vd->significand; - - shift = 32 - fls((u32)(significand >> 32)); - if (shift == 32) - shift = 64 - fls((u32)significand); - if (shift) { - exponent -= shift; - significand <<= shift; - } - -#if 1 - vd->exponent = exponent; - vd->significand = significand; - vfp_double_dump("pack: normalised", vd); -#endif - - /* - * Tiny number? - */ - underflow = exponent < 0; - if (underflow) { - significand = vfp_shiftright64jamming(significand, -exponent); - exponent = 0; -#if 1 - vd->exponent = exponent; - vd->significand = significand; - vfp_double_dump("pack: tiny number", vd); -#endif - if (!(significand & ((1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1))) - underflow = 0; - } - - /* - * Select rounding increment. - */ - incr = 0; - rmode = fpscr & FPSCR_RMODE_MASK; - - if (rmode == FPSCR_ROUND_NEAREST) { - incr = 1ULL << VFP_DOUBLE_LOW_BITS; - if ((significand & (1ULL << (VFP_DOUBLE_LOW_BITS + 1))) == 0) - incr -= 1; - } else if (rmode == FPSCR_ROUND_TOZERO) { - incr = 0; - } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0)) - incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1; - - LOG_TRACE(Core_ARM11, "VFP: rounding increment = 0x%08llx", incr); - - /* - * Is our rounding going to overflow? - */ - if ((significand + incr) < significand) { - exponent += 1; - significand = (significand >> 1) | (significand & 1); - incr >>= 1; -#if 1 - vd->exponent = exponent; - vd->significand = significand; - vfp_double_dump("pack: overflow", vd); -#endif - } - - /* - * If any of the low bits (which will be shifted out of the - * number) are non-zero, the result is inexact. - */ - if (significand & ((1 << (VFP_DOUBLE_LOW_BITS + 1)) - 1)) - exceptions |= FPSCR_IXC; - - /* - * Do our rounding. - */ - significand += incr; - - /* - * Infinity? - */ - if (exponent >= 2046) { - exceptions |= FPSCR_OFC | FPSCR_IXC; - if (incr == 0) { - vd->exponent = 2045; - vd->significand = 0x7fffffffffffffffULL; - } else { - vd->exponent = 2047; /* infinity */ - vd->significand = 0; - } - } else { - if (significand >> (VFP_DOUBLE_LOW_BITS + 1) == 0) - exponent = 0; - if (exponent || significand > 0x8000000000000000ULL) - underflow = 0; - if (underflow) - exceptions |= FPSCR_UFC; - vd->exponent = exponent; - vd->significand = significand >> 1; - } - -pack: - vfp_double_dump("pack: final", vd); - { - s64 d = vfp_double_pack(vd); - LOG_TRACE(Core_ARM11, "VFP: %s: d(d%d)=%016llx exceptions=%08x", func, - dd, d, exceptions); - vfp_put_double(state, d, dd); - } - return exceptions; -} - -/* - * Propagate the NaN, setting exceptions if it is signalling. - * 'n' is always a NaN. 'm' may be a number, NaN or infinity. - */ -static u32 -vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn, - struct vfp_double *vdm, u32 fpscr) -{ - struct vfp_double *nan; - int tn, tm = 0; - - tn = vfp_double_type(vdn); - - if (vdm) - tm = vfp_double_type(vdm); - - if (fpscr & FPSCR_DEFAULT_NAN) - /* - * Default NaN mode - always returns a quiet NaN - */ - nan = &vfp_double_default_qnan; - else { - /* - * Contemporary mode - select the first signalling - * NAN, or if neither are signalling, the first - * quiet NAN. - */ - if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN)) - nan = vdn; - else - nan = vdm; - /* - * Make the NaN quiet. - */ - nan->significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; - } - - *vdd = *nan; - - /* - * If one was a signalling NAN, raise invalid operation. - */ - return (tn == VFP_SNAN || tm == VFP_SNAN) ? u32(FPSCR_IOC) : u32(VFP_NAN_FLAG); -} - -/* - * Extended operations - */ -static u32 vfp_double_fabs(ARMul_State* state, int dd, [[maybe_unused]] int unused, int dm, - [[maybe_unused]] u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd); - return 0; -} - -static u32 vfp_double_fcpy(ARMul_State* state, int dd, [[maybe_unused]] int unused, int dm, - [[maybe_unused]] u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_put_double(state, vfp_get_double(state, dm), dd); - return 0; -} - -static u32 vfp_double_fneg(ARMul_State* state, int dd, [[maybe_unused]] int unused, int dm, - [[maybe_unused]] u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd); - return 0; -} - -static u32 vfp_double_fsqrt(ARMul_State* state, int dd, [[maybe_unused]] int unused, int dm, - u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double vdm, vdd, *vdp; - int ret, tm; - u32 exceptions = 0; - - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - - tm = vfp_double_type(&vdm); - if (tm & (VFP_NAN|VFP_INFINITY)) { - vdp = &vdd; - - if (tm & VFP_NAN) - ret = vfp_propagate_nan(vdp, &vdm, nullptr, fpscr); - else if (vdm.sign == 0) { -sqrt_copy: - vdp = &vdm; - ret = 0; - } else { -sqrt_invalid: - vdp = &vfp_double_default_qnan; - ret = FPSCR_IOC; - } - vfp_put_double(state, vfp_double_pack(vdp), dd); - return ret; - } - - /* - * sqrt(+/- 0) == +/- 0 - */ - if (tm & VFP_ZERO) - goto sqrt_copy; - - /* - * Normalise a denormalised number - */ - if (tm & VFP_DENORMAL) - vfp_double_normalise_denormal(&vdm); - - /* - * sqrt(<0) = invalid - */ - if (vdm.sign) - goto sqrt_invalid; - - vfp_double_dump("sqrt", &vdm); - - /* - * Estimate the square root. - */ - vdd.sign = 0; - vdd.exponent = ((vdm.exponent - 1023) >> 1) + 1023; - vdd.significand = (u64)vfp_estimate_sqrt_significand(vdm.exponent, vdm.significand >> 32) << 31; - - vfp_double_dump("sqrt estimate1", &vdd); - - vdm.significand >>= 1 + (vdm.exponent & 1); - vdd.significand += 2 + vfp_estimate_div128to64(vdm.significand, 0, vdd.significand); - - vfp_double_dump("sqrt estimate2", &vdd); - - /* - * And now adjust. - */ - if ((vdd.significand & VFP_DOUBLE_LOW_BITS_MASK) <= 5) { - if (vdd.significand < 2) { - vdd.significand = ~0ULL; - } else { - u64 termh, terml, remh, reml; - vdm.significand <<= 2; - mul64to128(&termh, &terml, vdd.significand, vdd.significand); - sub128(&remh, &reml, vdm.significand, 0, termh, terml); - while ((s64)remh < 0) { - vdd.significand -= 1; - shift64left(&termh, &terml, vdd.significand); - terml |= 1; - add128(&remh, &reml, remh, reml, termh, terml); - } - vdd.significand |= (remh | reml) != 0; - } - } - vdd.significand = vfp_shiftright64jamming(vdd.significand, 1); - - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fsqrt"); - return exceptions; -} - -/* - * Equal := ZC - * Less than := N - * Greater than := C - * Unordered := CV - */ -static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, s64 m, - [[maybe_unused]] u32 fpscr) -{ - s64 d; - u32 ret = 0; - - LOG_TRACE(Core_ARM11, "In %s, state=0x%p, fpscr=0x%x", __FUNCTION__, state, fpscr); - if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) { - ret |= FPSCR_CFLAG | FPSCR_VFLAG; - if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) - /* - * Signalling NaN, or signalling on quiet NaN - */ - ret |= FPSCR_IOC; - } - - d = vfp_get_double(state, dd); - if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) { - ret |= FPSCR_CFLAG | FPSCR_VFLAG; - if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) - /* - * Signalling NaN, or signalling on quiet NaN - */ - ret |= FPSCR_IOC; - } - - if (ret == 0) { - //printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m); - if (d == m || vfp_double_packed_abs(d | m) == 0) { - /* - * equal - */ - ret |= FPSCR_ZFLAG | FPSCR_CFLAG; - //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret); - } else if (vfp_double_packed_sign(d ^ m)) { - /* - * different signs - */ - if (vfp_double_packed_sign(d)) - /* - * d is negative, so d < m - */ - ret |= FPSCR_NFLAG; - else - /* - * d is positive, so d > m - */ - ret |= FPSCR_CFLAG; - } else if ((vfp_double_packed_sign(d) != 0) ^ (d < m)) { - /* - * d < m - */ - ret |= FPSCR_NFLAG; - } else if ((vfp_double_packed_sign(d) != 0) ^ (d > m)) { - /* - * d > m - */ - ret |= FPSCR_CFLAG; - } - } - LOG_TRACE(Core_ARM11, "In %s, state=0x%p, ret=0x%x", __FUNCTION__, state, ret); - - return ret; -} - -static u32 vfp_double_fcmp(ARMul_State* state, int dd, [[maybe_unused]] int unused, int dm, - u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_compare(state, dd, 0, vfp_get_double(state, dm), fpscr); -} - -static u32 vfp_double_fcmpe(ARMul_State* state, int dd, [[maybe_unused]] int unused, int dm, - u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_compare(state, dd, 1, vfp_get_double(state, dm), fpscr); -} - -static u32 vfp_double_fcmpz(ARMul_State* state, int dd, [[maybe_unused]] int unused, [[maybe_unused]] int dm, - u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_compare(state, dd, 0, 0, fpscr); -} - -static u32 vfp_double_fcmpez(ARMul_State* state, int dd, [[maybe_unused]] int unused, [[maybe_unused]] int dm, - u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_compare(state, dd, 1, 0, fpscr); -} - -static u32 vfp_double_fcvts(ARMul_State* state, int sd, [[maybe_unused]] int unused, int dm, - u32 fpscr) -{ - struct vfp_double vdm; - struct vfp_single vsd; - int tm; - u32 exceptions = 0; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - - tm = vfp_double_type(&vdm); - - /* - * If we have a signalling NaN, signal invalid operation. - */ - if (tm == VFP_SNAN) - exceptions = FPSCR_IOC; - - if (tm & VFP_DENORMAL) - vfp_double_normalise_denormal(&vdm); - - vsd.sign = vdm.sign; - vsd.significand = vfp_hi64to32jamming(vdm.significand); - - /* - * If we have an infinity or a NaN, the exponent must be 255 - */ - if (tm & (VFP_INFINITY|VFP_NAN)) { - vsd.exponent = 255; - if (tm == VFP_QNAN) - vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN; - goto pack_nan; - } else if (tm & VFP_ZERO) - vsd.exponent = 0; - else - vsd.exponent = vdm.exponent - (1023 - 127); - - exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fcvts"); - return exceptions; - -pack_nan: - vfp_put_float(state, vfp_single_pack(&vsd), sd); - return exceptions; -} - -static u32 vfp_double_fuito(ARMul_State* state, int dd, [[maybe_unused]] int unused, int dm, - u32 fpscr) -{ - struct vfp_double vdm; - u32 exceptions = 0; - u32 m = vfp_get_float(state, dm); - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vdm.sign = 0; - vdm.exponent = 1023 + 63 - 1; - vdm.significand = (u64)m; - - exceptions |= vfp_double_normaliseround(state, dd, &vdm, fpscr, "fuito"); - return exceptions; -} - -static u32 vfp_double_fsito(ARMul_State* state, int dd, [[maybe_unused]] int unused, int dm, - u32 fpscr) -{ - struct vfp_double vdm; - u32 exceptions = 0; - u32 m = vfp_get_float(state, dm); - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vdm.sign = (m & 0x80000000) >> 16; - vdm.exponent = 1023 + 63 - 1; - vdm.significand = vdm.sign ? (~m + 1) : m; - - exceptions |= vfp_double_normaliseround(state, dd, &vdm, fpscr, "fsito"); - return exceptions; -} - -static u32 vfp_double_ftoui(ARMul_State* state, int sd, [[maybe_unused]] int unused, int dm, - u32 fpscr) -{ - struct vfp_double vdm; - u32 d, exceptions = 0; - int rmode = fpscr & FPSCR_RMODE_MASK; - int tm; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - - /* - * Do we have a denormalised number? - */ - tm = vfp_double_type(&vdm); - if (tm & VFP_DENORMAL) - exceptions |= FPSCR_IDC; - - if (tm & VFP_NAN) - vdm.sign = 1; - - if (vdm.exponent >= 1023 + 32) { - d = vdm.sign ? 0 : 0xffffffff; - exceptions = FPSCR_IOC; - } else if (vdm.exponent >= 1023) { - int shift = 1023 + 63 - vdm.exponent; - u64 rem, incr = 0; - - /* - * 2^0 <= m < 2^32-2^8 - */ - d = (u32)((vdm.significand << 1) >> shift); - rem = vdm.significand << (65 - shift); - - if (rmode == FPSCR_ROUND_NEAREST) { - incr = 0x8000000000000000ULL; - if ((d & 1) == 0) - incr -= 1; - } else if (rmode == FPSCR_ROUND_TOZERO) { - incr = 0; - } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) { - incr = ~0ULL; - } - - if ((rem + incr) < rem) { - if (d < 0xffffffff) - d += 1; - else - exceptions |= FPSCR_IOC; - } - - if (d && vdm.sign) { - d = 0; - exceptions |= FPSCR_IOC; - } else if (rem) - exceptions |= FPSCR_IXC; - } else { - d = 0; - if (vdm.exponent | vdm.significand) { - if (rmode == FPSCR_ROUND_NEAREST) { - if (vdm.exponent >= 1022) { - d = vdm.sign ? 0 : 1; - exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC; - } else { - exceptions |= FPSCR_IXC; - } - } else if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) { - d = 1; - exceptions |= FPSCR_IXC; - } else if (rmode == FPSCR_ROUND_MINUSINF) { - exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC; - } else { - exceptions |= FPSCR_IXC; - } - } - } - - LOG_TRACE(Core_ARM11, "VFP: ftoui: d(s%d)=%08x exceptions=%08x", sd, d, exceptions); - - vfp_put_float(state, d, sd); - - return exceptions; -} - -static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_ftoui(state, sd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); -} - -static u32 vfp_double_ftosi(ARMul_State* state, int sd, [[maybe_unused]] int unused, int dm, - u32 fpscr) -{ - struct vfp_double vdm; - u32 d, exceptions = 0; - int rmode = fpscr & FPSCR_RMODE_MASK; - int tm; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - vfp_double_dump("VDM", &vdm); - - /* - * Do we have denormalised number? - */ - tm = vfp_double_type(&vdm); - if (tm & VFP_DENORMAL) - exceptions |= FPSCR_IDC; - - if (tm & VFP_NAN) { - d = 0; - exceptions |= FPSCR_IOC; - } else if (vdm.exponent >= 1023 + 31) { - d = 0x7fffffff; - if (vdm.sign) - d = ~d; - exceptions |= FPSCR_IOC; - } else if (vdm.exponent >= 1023) { - int shift = 1023 + 63 - vdm.exponent; /* 58 */ - u64 rem, incr = 0; - - d = (u32)((vdm.significand << 1) >> shift); - rem = vdm.significand << (65 - shift); - - if (rmode == FPSCR_ROUND_NEAREST) { - incr = 0x8000000000000000ULL; - if ((d & 1) == 0) - incr -= 1; - } else if (rmode == FPSCR_ROUND_TOZERO) { - incr = 0; - } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vdm.sign != 0)) { - incr = ~0ULL; - } - - if ((rem + incr) < rem && d < 0xffffffff) - d += 1; - if (d > (0x7fffffffU + (vdm.sign != 0))) { - d = (0x7fffffffU + (vdm.sign != 0)); - exceptions |= FPSCR_IOC; - } else if (rem) - exceptions |= FPSCR_IXC; - - if (vdm.sign) - d = (~d + 1); - } else { - d = 0; - if (vdm.exponent | vdm.significand) { - exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_NEAREST) { - if (vdm.exponent >= 1022) { - d = vdm.sign ? 0xffffffff : 1; - } else { - d = 0; - } - } else if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) { - d = 1; - } else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { - d = 0xffffffff; - } - } - } - - LOG_TRACE(Core_ARM11, "VFP: ftosi: d(s%d)=%08x exceptions=%08x", sd, d, exceptions); - - vfp_put_float(state, (s32)d, sd); - - return exceptions; -} - -static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_ftosi(state, dd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); -} - -static struct op fops_ext[] = { - { vfp_double_fcpy, 0 }, //0x00000000 - FEXT_FCPY - { vfp_double_fabs, 0 }, //0x00000001 - FEXT_FABS - { vfp_double_fneg, 0 }, //0x00000002 - FEXT_FNEG - { vfp_double_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { vfp_double_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP - { vfp_double_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE - { vfp_double_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ - { vfp_double_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT - { vfp_double_fuito, OP_SCALAR|OP_SM }, //0x00000010 - FEXT_FUITO - { vfp_double_fsito, OP_SCALAR|OP_SM }, //0x00000011 - FEXT_FSITO - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { vfp_double_ftoui, OP_SCALAR|OP_SD }, //0x00000018 - FEXT_FTOUI - { vfp_double_ftouiz, OP_SCALAR|OP_SD }, //0x00000019 - FEXT_FTOUIZ - { vfp_double_ftosi, OP_SCALAR|OP_SD }, //0x0000001A - FEXT_FTOSI - { vfp_double_ftosiz, OP_SCALAR|OP_SD }, //0x0000001B - FEXT_FTOSIZ -}; - -static u32 -vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn, - struct vfp_double *vdm, u32 fpscr) -{ - struct vfp_double *vdp; - u32 exceptions = 0; - int tn, tm; - - tn = vfp_double_type(vdn); - tm = vfp_double_type(vdm); - - if (tn & tm & VFP_INFINITY) { - /* - * Two infinities. Are they different signs? - */ - if (vdn->sign ^ vdm->sign) { - /* - * different signs -> invalid - */ - exceptions = FPSCR_IOC; - vdp = &vfp_double_default_qnan; - } else { - /* - * same signs -> valid - */ - vdp = vdn; - } - } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) { - /* - * One infinity and one number -> infinity - */ - vdp = vdn; - } else { - /* - * 'n' is a NaN of some type - */ - return vfp_propagate_nan(vdd, vdn, vdm, fpscr); - } - *vdd = *vdp; - return exceptions; -} - -u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_double *vdm, u32 fpscr) -{ - u32 exp_diff; - u64 m_sig; - - if (vdn->significand & (1ULL << 63) || - vdm->significand & (1ULL << 63)) { - LOG_INFO(Core_ARM11, "VFP: bad FP values in %s", __func__); - vfp_double_dump("VDN", vdn); - vfp_double_dump("VDM", vdm); - } - - /* - * Ensure that 'n' is the largest magnitude number. Note that - * if 'n' and 'm' have equal exponents, we do not swap them. - * This ensures that NaN propagation works correctly. - */ - if (vdn->exponent < vdm->exponent) { - std::swap(vdm, vdn); - } - - /* - * Is 'n' an infinity or a NaN? Note that 'm' may be a number, - * infinity or a NaN here. - */ - if (vdn->exponent == 2047) - return vfp_double_fadd_nonnumber(vdd, vdn, vdm, fpscr); - - /* - * We have two proper numbers, where 'vdn' is the larger magnitude. - * - * Copy 'n' to 'd' before doing the arithmetic. - */ - *vdd = *vdn; - - /* - * Align 'm' with the result. - */ - exp_diff = vdn->exponent - vdm->exponent; - m_sig = vfp_shiftright64jamming(vdm->significand, exp_diff); - - /* - * If the signs are different, we are really subtracting. - */ - if (vdn->sign ^ vdm->sign) { - m_sig = vdn->significand - m_sig; - if ((s64)m_sig < 0) { - vdd->sign = vfp_sign_negate(vdd->sign); - m_sig = (~m_sig + 1); - } else if (m_sig == 0) { - vdd->sign = (fpscr & FPSCR_RMODE_MASK) == - FPSCR_ROUND_MINUSINF ? 0x8000 : 0; - } - } else { - m_sig += vdn->significand; - } - vdd->significand = m_sig; - - return 0; -} - -u32 -vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, - struct vfp_double *vdm, u32 fpscr) -{ - vfp_double_dump("VDN", vdn); - vfp_double_dump("VDM", vdm); - - /* - * Ensure that 'n' is the largest magnitude number. Note that - * if 'n' and 'm' have equal exponents, we do not swap them. - * This ensures that NaN propagation works correctly. - */ - if (vdn->exponent < vdm->exponent) { - std::swap(vdm, vdn); - LOG_TRACE(Core_ARM11, "VFP: swapping M <-> N"); - } - - vdd->sign = vdn->sign ^ vdm->sign; - - /* - * If 'n' is an infinity or NaN, handle it. 'm' may be anything. - */ - if (vdn->exponent == 2047) { - if (vdn->significand || (vdm->exponent == 2047 && vdm->significand)) - return vfp_propagate_nan(vdd, vdn, vdm, fpscr); - if ((vdm->exponent | vdm->significand) == 0) { - *vdd = vfp_double_default_qnan; - return FPSCR_IOC; - } - vdd->exponent = vdn->exponent; - vdd->significand = 0; - return 0; - } - - /* - * If 'm' is zero, the result is always zero. In this case, - * 'n' may be zero or a number, but it doesn't matter which. - */ - if ((vdm->exponent | vdm->significand) == 0) { - vdd->exponent = 0; - vdd->significand = 0; - return 0; - } - - /* - * We add 2 to the destination exponent for the same reason - * as the addition case - though this time we have +1 from - * each input operand. - */ - vdd->exponent = vdn->exponent + vdm->exponent - 1023 + 2; - vdd->significand = vfp_hi64multiply64(vdn->significand, vdm->significand); - - vfp_double_dump("VDD", vdd); - return 0; -} - -#define NEG_MULTIPLY (1 << 0) -#define NEG_SUBTRACT (1 << 1) - -static u32 -vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, const char *func) -{ - struct vfp_double vdd, vdp, vdn, vdm; - u32 exceptions = 0; - - exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); - if (vdn.exponent == 0 && vdn.significand) - vfp_double_normalise_denormal(&vdn); - - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - if (vdm.exponent == 0 && vdm.significand) - vfp_double_normalise_denormal(&vdm); - - exceptions |= vfp_double_multiply(&vdp, &vdn, &vdm, fpscr); - if (negate & NEG_MULTIPLY) - vdp.sign = vfp_sign_negate(vdp.sign); - - exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dd), fpscr); - if (vdn.exponent == 0 && vdn.significand != 0) - vfp_double_normalise_denormal(&vdn); - - if (negate & NEG_SUBTRACT) - vdn.sign = vfp_sign_negate(vdn.sign); - - exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr); - - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, func); - return exceptions; -} - -/* - * Standard operations - */ - -/* - * sd = sd + (sn * sm) - */ -static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac"); -} - -/* - * sd = sd - (sn * sm) - */ -static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac"); -} - -/* - * sd = -sd + (sn * sm) - */ -static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc"); -} - -/* - * sd = -sd - (sn * sm) - */ -static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); -} - -/* - * sd = sn * sm - */ -static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - struct vfp_double vdd, vdn, vdm; - u32 exceptions = 0; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); - if (vdn.exponent == 0 && vdn.significand) - vfp_double_normalise_denormal(&vdn); - - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - if (vdm.exponent == 0 && vdm.significand) - vfp_double_normalise_denormal(&vdm); - - exceptions |= vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); - - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fmul"); - return exceptions; -} - -/* - * sd = -(sn * sm) - */ -static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - struct vfp_double vdd, vdn, vdm; - u32 exceptions = 0; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); - if (vdn.exponent == 0 && vdn.significand) - vfp_double_normalise_denormal(&vdn); - - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - if (vdm.exponent == 0 && vdm.significand) - vfp_double_normalise_denormal(&vdm); - - exceptions |= vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); - vdd.sign = vfp_sign_negate(vdd.sign); - - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fnmul"); - return exceptions; -} - -/* - * sd = sn + sm - */ -static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - struct vfp_double vdd, vdn, vdm; - u32 exceptions = 0; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); - if (vdn.exponent == 0 && vdn.significand) - vfp_double_normalise_denormal(&vdn); - - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - if (vdm.exponent == 0 && vdm.significand) - vfp_double_normalise_denormal(&vdm); - - exceptions |= vfp_double_add(&vdd, &vdn, &vdm, fpscr); - - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fadd"); - return exceptions; -} - -/* - * sd = sn - sm - */ -static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - struct vfp_double vdd, vdn, vdm; - u32 exceptions = 0; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); - if (vdn.exponent == 0 && vdn.significand) - vfp_double_normalise_denormal(&vdn); - - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - if (vdm.exponent == 0 && vdm.significand) - vfp_double_normalise_denormal(&vdm); - - /* - * Subtraction is like addition, but with a negated operand. - */ - vdm.sign = vfp_sign_negate(vdm.sign); - - exceptions |= vfp_double_add(&vdd, &vdn, &vdm, fpscr); - - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fsub"); - return exceptions; -} - -/* - * sd = sn / sm - */ -static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) -{ - struct vfp_double vdd, vdn, vdm; - u32 exceptions = 0; - int tm, tn; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); - exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); - - vdd.sign = vdn.sign ^ vdm.sign; - - tn = vfp_double_type(&vdn); - tm = vfp_double_type(&vdm); - - /* - * Is n a NAN? - */ - if (tn & VFP_NAN) - goto vdn_nan; - - /* - * Is m a NAN? - */ - if (tm & VFP_NAN) - goto vdm_nan; - - /* - * If n and m are infinity, the result is invalid - * If n and m are zero, the result is invalid - */ - if (tm & tn & (VFP_INFINITY|VFP_ZERO)) - goto invalid; - - /* - * If n is infinity, the result is infinity - */ - if (tn & VFP_INFINITY) - goto infinity; - - /* - * If m is zero, raise div0 exceptions - */ - if (tm & VFP_ZERO) - goto divzero; - - /* - * If m is infinity, or n is zero, the result is zero - */ - if (tm & VFP_INFINITY || tn & VFP_ZERO) - goto zero; - - if (tn & VFP_DENORMAL) - vfp_double_normalise_denormal(&vdn); - if (tm & VFP_DENORMAL) - vfp_double_normalise_denormal(&vdm); - - /* - * Ok, we have two numbers, we can perform division. - */ - vdd.exponent = vdn.exponent - vdm.exponent + 1023 - 1; - vdm.significand <<= 1; - if (vdm.significand <= (2 * vdn.significand)) { - vdn.significand >>= 1; - vdd.exponent++; - } - vdd.significand = vfp_estimate_div128to64(vdn.significand, 0, vdm.significand); - if ((vdd.significand & 0x1ff) <= 2) { - u64 termh, terml, remh, reml; - mul64to128(&termh, &terml, vdm.significand, vdd.significand); - sub128(&remh, &reml, vdn.significand, 0, termh, terml); - while ((s64)remh < 0) { - vdd.significand -= 1; - add128(&remh, &reml, remh, reml, 0, vdm.significand); - } - vdd.significand |= (reml != 0); - } - - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fdiv"); - return exceptions; - -vdn_nan: - exceptions |= vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr); -pack: - vfp_put_double(state, vfp_double_pack(&vdd), dd); - return exceptions; - -vdm_nan: - exceptions |= vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr); - goto pack; - -zero: - vdd.exponent = 0; - vdd.significand = 0; - goto pack; - -divzero: - exceptions |= FPSCR_DZC; -infinity: - vdd.exponent = 2047; - vdd.significand = 0; - goto pack; - -invalid: - vfp_put_double(state, vfp_double_pack(&vfp_double_default_qnan), dd); - exceptions |= FPSCR_IOC; - return exceptions; -} - -static struct op fops[] = { - { vfp_double_fmac, 0 }, - { vfp_double_fmsc, 0 }, - { vfp_double_fmul, 0 }, - { vfp_double_fadd, 0 }, - { vfp_double_fnmac, 0 }, - { vfp_double_fnmsc, 0 }, - { vfp_double_fnmul, 0 }, - { vfp_double_fsub, 0 }, - { vfp_double_fdiv, 0 }, -}; - -#define FREG_BANK(x) ((x) & 0x0c) -#define FREG_IDX(x) ((x) & 3) - -u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) -{ - u32 op = inst & FOP_MASK; - u32 exceptions = 0; - unsigned int dest; - unsigned int dn = vfp_get_dn(inst); - unsigned int dm; - unsigned int vecitr, veclen, vecstride; - struct op *fop; - - LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)); - - fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)]; - - /* - * fcvtds takes an sN register number as destination, not dN. - * It also always operates on scalars. - */ - if (fop->flags & OP_SD) - dest = vfp_get_sd(inst); - else - dest = vfp_get_dd(inst); - - /* - * f[us]ito takes a sN operand, not a dN operand. - */ - if (fop->flags & OP_SM) - dm = vfp_get_sm(inst); - else - dm = vfp_get_dm(inst); - - /* - * If destination bank is zero, vector length is always '1'. - * ARM DDI0100F C5.1.3, C5.3.2. - */ - if ((fop->flags & OP_SCALAR) || (FREG_BANK(dest) == 0)) - veclen = 0; - else - veclen = fpscr & FPSCR_LENGTH_MASK; - - LOG_TRACE(Core_ARM11, "VFP: vecstride=%u veclen=%u", vecstride, - (veclen >> FPSCR_LENGTH_BIT) + 1); - - if (!fop->fn) { - printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst)); - goto invalid; - } - - for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { - u32 except; -// char type; - -// type = (fop->flags & OP_SD) ? 's' : 'd'; - if (op == FOP_EXT) - LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = op[%u] (d%u)", - vecitr >> FPSCR_LENGTH_BIT, - type, dest, dn, dm); - else - LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)", - vecitr >> FPSCR_LENGTH_BIT, - type, dest, dn, FOP_TO_IDX(op), dm); - - except = fop->fn(state, dest, dn, dm, fpscr); - LOG_TRACE(Core_ARM11, "VFP: itr%d: exceptions=%08x", - vecitr >> FPSCR_LENGTH_BIT, except); - - exceptions |= except; - - /* - * CHECK: It appears to be undefined whether we stop when - * we encounter an exception. We continue. - */ - dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 3); - dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 3); - if (FREG_BANK(dm) != 0) - dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 3); - } - return exceptions; - -invalid: - return ~0; -} diff --git a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpinstr.cpp b/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpinstr.cpp deleted file mode 100644 index 1a98d011..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpinstr.cpp +++ /dev/null @@ -1,1788 +0,0 @@ -// Copyright 2012 Michael Kang, 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -/* Notice: this file should not be compiled as is, and is meant to be - included in other files only. */ - -/* ----------------------------------------------------------------------- */ -/* CDP instructions */ -/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ - -/* ----------------------------------------------------------------------- */ -/* VMLA */ -/* cond 1110 0D00 Vn-- Vd-- 101X N0M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmla_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmla_inst)); - vmla_inst *inst_cream = (vmla_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMLA_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmla_inst *inst_cream = (vmla_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmla_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VNMLS */ -/* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmls_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmls_inst)); - vmls_inst *inst_cream = (vmls_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMLS_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmls_inst *inst_cream = (vmls_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmls_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VNMLA */ -/* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vnmla_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmla_inst)); - vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VNMLA_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vnmla_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VNMLS */ -/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */ - -#ifdef VFP_INTERPRETER_STRUCT -struct vnmls_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmls_inst)); - vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VNMLS_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vnmls_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VNMUL */ -/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vnmul_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmul_inst)); - vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VNMUL_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vnmul_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VMUL */ -/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmul_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmul_inst)); - vmul_inst *inst_cream = (vmul_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMUL_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmul_inst *inst_cream = (vmul_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmul_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VADD */ -/* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vadd_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vadd_inst)); - vadd_inst *inst_cream = (vadd_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VADD_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vadd_inst *inst_cream = (vadd_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vadd_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VSUB */ -/* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vsub_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsub_inst)); - vsub_inst *inst_cream = (vsub_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VSUB_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vsub_inst *inst_cream = (vsub_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vsub_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VDIV */ -/* cond 1110 1D00 Vn-- Vd-- 101X N0M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vdiv_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vdiv_inst)); - vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VDIV_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vdiv_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VMOVI move immediate */ -/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */ -/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmovi_inst { - unsigned int single; - unsigned int d; - unsigned int imm; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovi_inst)); - vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->single = BIT(inst, 8) == 0; - inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4); - unsigned int imm8 = BITS(inst, 16, 19) << 4 | BITS(inst, 0, 3); - if (inst_cream->single) - inst_cream->imm = BIT(imm8, 7)<<31 | (BIT(imm8, 6)==0)<<30 | (BIT(imm8, 6) ? 0x1f : 0)<<25 | BITS(imm8, 0, 5)<<19; - else - inst_cream->imm = BIT(imm8, 7)<<31 | (BIT(imm8, 6)==0)<<30 | (BIT(imm8, 6) ? 0xff : 0)<<22 | BITS(imm8, 0, 5)<<16; - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMOVI_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component; - - VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmovi_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VMOVR move register */ -/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */ -/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmovr_inst { - unsigned int single; - unsigned int d; - unsigned int m; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovr_inst)); - vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->single = BIT(inst, 8) == 0; - inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4); - inst_cream->m = (inst_cream->single ? BITS(inst, 0, 3)<<1 | BIT(inst, 5) : BITS(inst, 0, 3) | BIT(inst, 5)<<4); - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMOVR_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component; - - VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmovr_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VABS */ -/* cond 1110 1D11 0000 Vd-- 101X 11M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -typedef struct _vabs_inst { - unsigned int instr; - unsigned int dp_operation; -} vabs_inst; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vabs_inst)); - vabs_inst *inst_cream = (vabs_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VABS_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vabs_inst *inst_cream = (vabs_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vabs_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VNEG */ -/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ - -#ifdef VFP_INTERPRETER_STRUCT -struct vneg_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vneg_inst)); - vneg_inst *inst_cream = (vneg_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VNEG_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vneg_inst *inst_cream = (vneg_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vneg_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VSQRT */ -/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vsqrt_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsqrt_inst)); - vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VSQRT_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vsqrt_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VCMP VCMPE */ -/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */ -#ifdef VFP_INTERPRETER_STRUCT -struct vcmp_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp_inst)); - vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VCMP_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vcmp_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VCMP VCMPE */ -/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */ -#ifdef VFP_INTERPRETER_STRUCT -struct vcmp2_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp2_inst)); - vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VCMP2_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vcmp2_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VCVTBDS between double and single */ -/* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vcvtbds_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbds_inst)); - vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VCVTBDS_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vcvtbds_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VCVTBFF between floating point and fixed point */ -/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vcvtbff_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) -{ - VFP_DEBUG_UNTESTED(VCVTBFF); - - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbff_inst)); - vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VCVTBFF_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vcvtbff_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VCVTBFI between floating point and integer */ -/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ -#ifdef VFP_INTERPRETER_STRUCT -struct vcvtbfi_inst { - unsigned int instr; - unsigned int dp_operation; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbfi_inst)); - vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->dp_operation = BIT(inst, 8); - inst_cream->instr = inst; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VCVTBFI_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component; - - int ret; - - if (inst_cream->dp_operation) - ret = vfp_double_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - else - ret = vfp_single_cpdo(cpu, inst_cream->instr, cpu->VFP[VFP_FPSCR]); - - CHECK_VFP_CDP_RET; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vcvtbfi_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* MRC / MCR instructions */ -/* cond 1110 AAAL XXXX XXXX 101C XBB1 XXXX */ -/* cond 1110 op11 CRn- Rt-- copr op21 CRm- */ - -/* ----------------------------------------------------------------------- */ -/* VMOVBRS between register and single precision */ -/* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */ -/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmovbrs_inst { - unsigned int to_arm; - unsigned int t; - unsigned int n; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrs_inst)); - vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->to_arm = BIT(inst, 20) == 1; - inst_cream->t = BITS(inst, 12, 15); - inst_cream->n = BIT(inst, 7) | BITS(inst, 16, 19)<<1; - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMOVBRS_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component; - - VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmovbrs_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VMSR */ -/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */ -/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmsr_inst { - unsigned int reg; - unsigned int Rt; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmsr_inst)); - vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->reg = BITS(inst, 16, 19); - inst_cream->Rt = BITS(inst, 12, 15); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMSR_INST: -{ - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled , - and in privileged mode */ - /* Exceptions must be checked, according to v7 ref manual */ - CHECK_VFP_ENABLED; - - vmsr_inst* const inst_cream = (vmsr_inst*)inst_base->component; - - unsigned int reg = inst_cream->reg; - unsigned int rt = inst_cream->Rt; - - if (reg == 1) - { - cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; - } - else if (cpu->InAPrivilegedMode()) - { - if (reg == 8) - cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; - else if (reg == 9) - cpu->VFP[VFP_FPINST] = cpu->Reg[rt]; - else if (reg == 10) - cpu->VFP[VFP_FPINST2] = cpu->Reg[rt]; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmsr_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VMOVBRC register to scalar */ -/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */ -/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmovbrc_inst { - unsigned int esize; - unsigned int index; - unsigned int d; - unsigned int t; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrc_inst)); - vmovbrc_inst *inst_cream = (vmovbrc_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4; - inst_cream->t = BITS(inst, 12, 15); - /* VFP variant of instruction */ - inst_cream->esize = 32; - inst_cream->index = BIT(inst, 21); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMOVBRC_INST: -{ - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmovbrc_inst* const inst_cream = (vmovbrc_inst*)inst_base->component; - - cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t]; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmovbrc_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VMRS */ -/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */ -/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmrs_inst { - unsigned int reg; - unsigned int Rt; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmrs_inst)); - vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->reg = BITS(inst, 16, 19); - inst_cream->Rt = BITS(inst, 12, 15); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMRS_INST: -{ - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled, - and in privileged mode */ - /* Exceptions must be checked, according to v7 ref manual */ - CHECK_VFP_ENABLED; - - vmrs_inst* const inst_cream = (vmrs_inst*)inst_base->component; - - unsigned int reg = inst_cream->reg; - unsigned int rt = inst_cream->Rt; - - if (reg == 1) // FPSCR - { - if (rt != 15) - { - cpu->Reg[rt] = cpu->VFP[VFP_FPSCR]; - } - else - { - cpu->NFlag = (cpu->VFP[VFP_FPSCR] >> 31) & 1; - cpu->ZFlag = (cpu->VFP[VFP_FPSCR] >> 30) & 1; - cpu->CFlag = (cpu->VFP[VFP_FPSCR] >> 29) & 1; - cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1; - } - } - else if (reg == 0) - { - cpu->Reg[rt] = cpu->VFP[VFP_FPSID]; - } - else if (reg == 6) - { - cpu->Reg[rt] = cpu->VFP[VFP_MVFR1]; - } - else if (reg == 7) - { - cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; - } - else if (cpu->InAPrivilegedMode()) - { - if (reg == 8) - cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; - else if (reg == 9) - cpu->Reg[rt] = cpu->VFP[VFP_FPINST]; - else if (reg == 10) - cpu->Reg[rt] = cpu->VFP[VFP_FPINST2]; - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmrs_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VMOVBCR scalar to register */ -/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */ -/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MCR */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmovbcr_inst { - unsigned int esize; - unsigned int index; - unsigned int d; - unsigned int t; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbcr_inst)); - vmovbcr_inst *inst_cream = (vmovbcr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4; - inst_cream->t = BITS(inst, 12, 15); - /* VFP variant of instruction */ - inst_cream->esize = 32; - inst_cream->index = BIT(inst, 21); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMOVBCR_INST: -{ - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmovbcr_inst* const inst_cream = (vmovbcr_inst*) inst_base->component; - - cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmovbcr_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* MRRC / MCRR instructions */ -/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ -/* cond 1100 0100 Rt2- Rt-- copr opc1 CRm- MCRR */ - -/* ----------------------------------------------------------------------- */ -/* VMOVBRRSS between 2 registers to 2 singles */ -/* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */ -/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmovbrrss_inst { - unsigned int to_arm; - unsigned int t; - unsigned int t2; - unsigned int m; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrss_inst)); - vmovbrrss_inst *inst_cream = (vmovbrrss_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->to_arm = BIT(inst, 20) == 1; - inst_cream->t = BITS(inst, 12, 15); - inst_cream->t2 = BITS(inst, 16, 19); - inst_cream->m = BITS(inst, 0, 3)<<1|BIT(inst, 5); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMOVBRRSS_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmovbrrss_inst* const inst_cream = (vmovbrrss_inst*)inst_base->component; - - VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, - &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmovbrrss_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VMOVBRRD between 2 registers and 1 double */ -/* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */ -/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ -#ifdef VFP_INTERPRETER_STRUCT -struct vmovbrrd_inst { - unsigned int to_arm; - unsigned int t; - unsigned int t2; - unsigned int m; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrd_inst)); - vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->to_arm = BIT(inst, 20) == 1; - inst_cream->t = BITS(inst, 12, 15); - inst_cream->t2 = BITS(inst, 16, 19); - inst_cream->m = BIT(inst, 5)<<4 | BITS(inst, 0, 3); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VMOVBRRD_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component; - - VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, - &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vmovbrrd_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* LDC/STC between 2 registers and 1 double */ -/* cond 110X XXX1 Rn-- CRd- copr imm- imm- LDC */ -/* cond 110X XXX0 Rn-- CRd- copr imm8 imm8 STC */ - -/* ----------------------------------------------------------------------- */ -/* VSTR */ -/* cond 1101 UD00 Rn-- Vd-- 101X imm8 imm8 */ -#ifdef VFP_INTERPRETER_STRUCT -struct vstr_inst { - unsigned int single; - unsigned int n; - unsigned int d; - unsigned int imm32; - unsigned int add; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstr_inst)); - vstr_inst *inst_cream = (vstr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->single = BIT(inst, 8) == 0; - inst_cream->add = BIT(inst, 23); - inst_cream->imm32 = BITS(inst, 0,7) << 2; - inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); - inst_cream->n = BITS(inst, 16, 19); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VSTR_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vstr_inst *inst_cream = (vstr_inst *)inst_base->component; - - unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); - addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); - - if (inst_cream->single) - { - cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]); - } - else - { - const u32 word1 = cpu->ExtReg[inst_cream->d*2+0]; - const u32 word2 = cpu->ExtReg[inst_cream->d*2+1]; - - if (cpu->InBigEndianMode()) { - cpu->WriteMemory32(addr + 0, word2); - cpu->WriteMemory32(addr + 4, word1); - } else { - cpu->WriteMemory32(addr + 0, word1); - cpu->WriteMemory32(addr + 4, word2); - } - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vstr_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VPUSH */ -/* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */ -#ifdef VFP_INTERPRETER_STRUCT -struct vpush_inst { - unsigned int single; - unsigned int d; - unsigned int imm32; - unsigned int regs; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpush_inst)); - vpush_inst *inst_cream = (vpush_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->single = BIT(inst, 8) == 0; - inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); - inst_cream->imm32 = BITS(inst, 0, 7)<<2; - inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VPUSH_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vpush_inst *inst_cream = (vpush_inst *)inst_base->component; - - addr = cpu->Reg[R13] - inst_cream->imm32; - - for (unsigned int i = 0; i < inst_cream->regs; i++) - { - if (inst_cream->single) - { - cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); - addr += 4; - } - else - { - const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; - const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; - - if (cpu->InBigEndianMode()) { - cpu->WriteMemory32(addr + 0, word2); - cpu->WriteMemory32(addr + 4, word1); - } else { - cpu->WriteMemory32(addr + 0, word1); - cpu->WriteMemory32(addr + 4, word2); - } - - addr += 8; - } - } - - cpu->Reg[R13] -= inst_cream->imm32; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vpush_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VSTM */ -/* cond 110P UDW0 Rn-- Vd-- 101X imm8 imm8 */ -#ifdef VFP_INTERPRETER_STRUCT -struct vstm_inst { - unsigned int single; - unsigned int add; - unsigned int wback; - unsigned int d; - unsigned int n; - unsigned int imm32; - unsigned int regs; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstm_inst)); - vstm_inst *inst_cream = (vstm_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->single = BIT(inst, 8) == 0; - inst_cream->add = BIT(inst, 23); - inst_cream->wback = BIT(inst, 21); - inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); - inst_cream->n = BITS(inst, 16, 19); - inst_cream->imm32 = BITS(inst, 0, 7)<<2; - inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VSTM_INST: /* encoding 1 */ -{ - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vstm_inst* inst_cream = (vstm_inst*)inst_base->component; - - u32 address = cpu->Reg[inst_cream->n]; - - // Only possible in ARM mode, where PC accesses have an 8 byte offset. - if (inst_cream->n == 15) - address += 8; - - if (inst_cream->add == 0) - address -= inst_cream->imm32; - - for (unsigned int i = 0; i < inst_cream->regs; i++) - { - if (inst_cream->single) - { - cpu->WriteMemory32(address, cpu->ExtReg[inst_cream->d+i]); - address += 4; - } - else - { - const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; - const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; - - if (cpu->InBigEndianMode()) { - cpu->WriteMemory32(address + 0, word2); - cpu->WriteMemory32(address + 4, word1); - } else { - cpu->WriteMemory32(address + 0, word1); - cpu->WriteMemory32(address + 4, word2); - } - - address += 8; - } - } - if (inst_cream->wback) { - cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 : - cpu->Reg[inst_cream->n] - inst_cream->imm32); - } - } - cpu->Reg[15] += 4; - INC_PC(sizeof(vstm_inst)); - - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VPOP */ -/* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */ -#ifdef VFP_INTERPRETER_STRUCT -struct vpop_inst { - unsigned int single; - unsigned int d; - unsigned int imm32; - unsigned int regs; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpop_inst)); - vpop_inst *inst_cream = (vpop_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->single = BIT(inst, 8) == 0; - inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15)<<1)|BIT(inst, 22) : BITS(inst, 12, 15)|(BIT(inst, 22)<<4)); - inst_cream->imm32 = BITS(inst, 0, 7)<<2; - inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VPOP_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vpop_inst *inst_cream = (vpop_inst *)inst_base->component; - - addr = cpu->Reg[R13]; - - for (unsigned int i = 0; i < inst_cream->regs; i++) - { - if (inst_cream->single) - { - cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); - addr += 4; - } - else - { - const u32 word1 = cpu->ReadMemory32(addr + 0); - const u32 word2 = cpu->ReadMemory32(addr + 4); - - if (cpu->InBigEndianMode()) { - cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; - cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; - } else { - cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; - cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; - } - - addr += 8; - } - } - cpu->Reg[R13] += inst_cream->imm32; - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vpop_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - - -/* ----------------------------------------------------------------------- */ -/* VLDR */ -/* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */ -#ifdef VFP_INTERPRETER_STRUCT -struct vldr_inst { - unsigned int single; - unsigned int n; - unsigned int d; - unsigned int imm32; - unsigned int add; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldr_inst)); - vldr_inst *inst_cream = (vldr_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->single = BIT(inst, 8) == 0; - inst_cream->add = BIT(inst, 23); - inst_cream->imm32 = BITS(inst, 0,7) << 2; - inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); - inst_cream->n = BITS(inst, 16, 19); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VLDR_INST: -{ - if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vldr_inst *inst_cream = (vldr_inst *)inst_base->component; - - unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); - addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); - - if (inst_cream->single) - { - cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr); - } - else - { - const u32 word1 = cpu->ReadMemory32(addr + 0); - const u32 word2 = cpu->ReadMemory32(addr + 4); - - if (cpu->InBigEndianMode()) { - cpu->ExtReg[inst_cream->d*2+0] = word2; - cpu->ExtReg[inst_cream->d*2+1] = word1; - } else { - cpu->ExtReg[inst_cream->d*2+0] = word1; - cpu->ExtReg[inst_cream->d*2+1] = word2; - } - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vldr_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif - -/* ----------------------------------------------------------------------- */ -/* VLDM */ -/* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */ -#ifdef VFP_INTERPRETER_STRUCT -struct vldm_inst { - unsigned int single; - unsigned int add; - unsigned int wback; - unsigned int d; - unsigned int n; - unsigned int imm32; - unsigned int regs; -}; -#endif -#ifdef VFP_INTERPRETER_TRANS -static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) -{ - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldm_inst)); - vldm_inst *inst_cream = (vldm_inst *)inst_base->component; - - inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = TransExtData::NON_BRANCH; - - inst_cream->single = BIT(inst, 8) == 0; - inst_cream->add = BIT(inst, 23); - inst_cream->wback = BIT(inst, 21); - inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); - inst_cream->n = BITS(inst, 16, 19); - inst_cream->imm32 = BITS(inst, 0, 7)<<2; - inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); - - return inst_base; -} -#endif -#ifdef VFP_INTERPRETER_IMPL -VLDM_INST: -{ - if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { - CHECK_VFP_ENABLED; - - vldm_inst* inst_cream = (vldm_inst*)inst_base->component; - - u32 address = cpu->Reg[inst_cream->n]; - - // Only possible in ARM mode, where PC accesses have an 8 byte offset. - if (inst_cream->n == 15) - address += 8; - - if (inst_cream->add == 0) - address -= inst_cream->imm32; - - for (unsigned int i = 0; i < inst_cream->regs; i++) - { - if (inst_cream->single) - { - cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(address); - address += 4; - } - else - { - const u32 word1 = cpu->ReadMemory32(address + 0); - const u32 word2 = cpu->ReadMemory32(address + 4); - - if (cpu->InBigEndianMode()) { - cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; - cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; - } else { - cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; - cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; - } - - address += 8; - } - } - if (inst_cream->wback) { - cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 : - cpu->Reg[inst_cream->n] - inst_cream->imm32); - } - } - cpu->Reg[15] += cpu->GetInstructionSize(); - INC_PC(sizeof(vldm_inst)); - FETCH_INST; - GOTO_NEXT_INST; -} -#endif diff --git a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpsingle.cpp b/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpsingle.cpp deleted file mode 100644 index 7b2d1b72..00000000 --- a/tests/A32/skyeye_interpreter/skyeye_common/vfp/vfpsingle.cpp +++ /dev/null @@ -1,1339 +0,0 @@ -/* - vfp/vfpsingle.c - ARM VFPv3 emulation unit - SoftFloat single instruction - Copyright (C) 2003 Skyeye Develop Group - for help please send mail to - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* - * This code is derived in part from : - * - Android kernel - * - John R. Housers softfloat library, which - * carries the following notice: - * - * =========================================================================== - * This C source file is part of the SoftFloat IEC/IEEE Floating-point - * Arithmetic Package, Release 2. - * - * Written by John R. Hauser. This work was made possible in part by the - * International Computer Science Institute, located at Suite 600, 1947 Center - * Street, Berkeley, California 94704. Funding was partially provided by the - * National Science Foundation under grant MIP-9311980. The original version - * of this code was written as part of a project to build a fixed-point vector - * processor in collaboration with the University of California at Berkeley, - * overseen by Profs. Nelson Morgan and John Wawrzynek. More information - * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ - * arithmetic/softfloat.html'. - * - * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort - * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT - * TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO - * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY - * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. - * - * Derivative works are acceptable, even for commercial purposes, so long as - * (1) they include prominent notice that the work is derivative, and (2) they - * include prominent notice akin to these three paragraphs for those parts of - * this code that are retained. - * =========================================================================== - */ - -#ifdef _MSC_VER -#pragma warning(disable : 4244 4245) -#endif - -#include -#include - -#include "common/assert.h" -#include "common/common_types.h" - -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp_helper.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/asm_vfp.h" -#include "A32/skyeye_interpreter/skyeye_common/vfp/vfp.h" - -#define LOG_INFO(...) do{}while(0) -#define LOG_TRACE(...) do{}while(0) -#define LOG_WARNING(...) do{}while(0) - -static struct vfp_single vfp_single_default_qnan = { - 255, - 0, - VFP_SINGLE_SIGNIFICAND_QNAN, -}; - -static void vfp_single_dump([[maybe_unused]] const char *str, [[maybe_unused]] vfp_single *s) -{ - LOG_TRACE(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x", - str, s->sign != 0, s->exponent, s->significand); -} - -static void vfp_single_normalise_denormal(struct vfp_single *vs) -{ - int bits = 31 - fls(vs->significand); - - vfp_single_dump("normalise_denormal: in", vs); - - if (bits) { - vs->exponent -= bits - 1; - vs->significand <<= bits; - } - - vfp_single_dump("normalise_denormal: out", vs); -} - - -u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single *vs, u32 fpscr, - [[maybe_unused]] const char *func) -{ - u32 significand, incr, rmode; - int exponent, shift, underflow; - u32 exceptions = 0; - - vfp_single_dump("pack: in", vs); - - /* - * Infinities and NaNs are a special case. - */ - if (vs->exponent == 255 && (vs->significand == 0 || exceptions)) - goto pack; - - /* - * Special-case zero. - */ - if (vs->significand == 0) { - vs->exponent = 0; - goto pack; - } - - exponent = vs->exponent; - significand = vs->significand; - - /* - * Normalise first. Note that we shift the significand up to - * bit 31, so we have VFP_SINGLE_LOW_BITS + 1 below the least - * significant bit. - */ - shift = 32 - fls(significand); - if (shift < 32 && shift) { - exponent -= shift; - significand <<= shift; - } - -#if 1 - vs->exponent = exponent; - vs->significand = significand; - vfp_single_dump("pack: normalised", vs); -#endif - - /* - * Tiny number? - */ - underflow = exponent < 0; - if (underflow) { - significand = vfp_shiftright32jamming(significand, -exponent); - exponent = 0; -#if 1 - vs->exponent = exponent; - vs->significand = significand; - vfp_single_dump("pack: tiny number", vs); -#endif - if (!(significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1))) - underflow = 0; - } - - /* - * Select rounding increment. - */ - incr = 0; - rmode = fpscr & FPSCR_RMODE_MASK; - - if (rmode == FPSCR_ROUND_NEAREST) { - incr = 1 << VFP_SINGLE_LOW_BITS; - if ((significand & (1 << (VFP_SINGLE_LOW_BITS + 1))) == 0) - incr -= 1; - } else if (rmode == FPSCR_ROUND_TOZERO) { - incr = 0; - } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vs->sign != 0)) - incr = (1 << (VFP_SINGLE_LOW_BITS + 1)) - 1; - - LOG_TRACE(Core_ARM11, "rounding increment = 0x%08x", incr); - - /* - * Is our rounding going to overflow? - */ - if ((significand + incr) < significand) { - exponent += 1; - significand = (significand >> 1) | (significand & 1); - incr >>= 1; -#if 1 - vs->exponent = exponent; - vs->significand = significand; - vfp_single_dump("pack: overflow", vs); -#endif - } - - /* - * If any of the low bits (which will be shifted out of the - * number) are non-zero, the result is inexact. - */ - if (significand & ((1 << (VFP_SINGLE_LOW_BITS + 1)) - 1)) - exceptions |= FPSCR_IXC; - - /* - * Do our rounding. - */ - significand += incr; - - /* - * Infinity? - */ - if (exponent >= 254) { - exceptions |= FPSCR_OFC | FPSCR_IXC; - if (incr == 0) { - vs->exponent = 253; - vs->significand = 0x7fffffff; - } else { - vs->exponent = 255; /* infinity */ - vs->significand = 0; - } - } else { - if (significand >> (VFP_SINGLE_LOW_BITS + 1) == 0) - exponent = 0; - if (exponent || significand > 0x80000000) - underflow = 0; - if (underflow) - exceptions |= FPSCR_UFC; - vs->exponent = exponent; - vs->significand = significand >> 1; - } - -pack: - vfp_single_dump("pack: final", vs); - { - s32 d = vfp_single_pack(vs); - LOG_TRACE(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func, - sd, d, exceptions); - vfp_put_float(state, d, sd); - } - - return exceptions; -} - -/* - * Propagate the NaN, setting exceptions if it is signalling. - * 'n' is always a NaN. 'm' may be a number, NaN or infinity. - */ -static u32 -vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, - struct vfp_single *vsm, u32 fpscr) -{ - struct vfp_single *nan; - int tn, tm = 0; - - tn = vfp_single_type(vsn); - - if (vsm) - tm = vfp_single_type(vsm); - - if (fpscr & FPSCR_DEFAULT_NAN) - /* - * Default NaN mode - always returns a quiet NaN - */ - nan = &vfp_single_default_qnan; - else { - /* - * Contemporary mode - select the first signalling - * NAN, or if neither are signalling, the first - * quiet NAN. - */ - if (tn == VFP_SNAN || (tm != VFP_SNAN && tn == VFP_QNAN)) - nan = vsn; - else - nan = vsm; - /* - * Make the NaN quiet. - */ - nan->significand |= VFP_SINGLE_SIGNIFICAND_QNAN; - } - - *vsd = *nan; - - /* - * If one was a signalling NAN, raise invalid operation. - */ - return (tn == VFP_SNAN || tm == VFP_SNAN) ? u32(FPSCR_IOC) : u32(VFP_NAN_FLAG); -} - - -/* - * Extended operations - */ -static u32 vfp_single_fabs(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - [[maybe_unused]] u32 fpscr) -{ - vfp_put_float(state, vfp_single_packed_abs(m), sd); - return 0; -} - -static u32 vfp_single_fcpy(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - [[maybe_unused]] u32 fpscr) -{ - vfp_put_float(state, m, sd); - return 0; -} - -static u32 vfp_single_fneg(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - [[maybe_unused]] u32 fpscr) -{ - vfp_put_float(state, vfp_single_packed_negate(m), sd); - return 0; -} - -static const u16 sqrt_oddadjust[] = { - 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0, - 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67 -}; - -static const u16 sqrt_evenadjust[] = { - 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e, - 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002 -}; - -u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) -{ - int index; - u32 z, a; - - if ((significand & 0xc0000000) != 0x40000000) { - LOG_TRACE(Core_ARM11, "invalid significand"); - } - - a = significand << 1; - index = (a >> 27) & 15; - if (exponent & 1) { - z = 0x4000 + (a >> 17) - sqrt_oddadjust[index]; - z = ((a / z) << 14) + (z << 15); - a >>= 1; - } else { - z = 0x8000 + (a >> 17) - sqrt_evenadjust[index]; - z = a / z + z; - z = (z >= 0x20000) ? 0xffff8000 : (z << 15); - if (z <= a) - return (s32)a >> 1; - } - { - u64 v = (u64)a << 31; - do_div(v, z); - return (u32)(v + (z >> 1)); - } -} - -static u32 vfp_single_fsqrt(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - u32 fpscr) -{ - struct vfp_single vsm, vsd, *vsp; - int ret, tm; - u32 exceptions = 0; - - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - tm = vfp_single_type(&vsm); - if (tm & (VFP_NAN|VFP_INFINITY)) { - vsp = &vsd; - - if (tm & VFP_NAN) - ret = vfp_propagate_nan(vsp, &vsm, nullptr, fpscr); - else if (vsm.sign == 0) { -sqrt_copy: - vsp = &vsm; - ret = 0; - } else { -sqrt_invalid: - vsp = &vfp_single_default_qnan; - ret = FPSCR_IOC; - } - vfp_put_float(state, vfp_single_pack(vsp), sd); - return ret; - } - - /* - * sqrt(+/- 0) == +/- 0 - */ - if (tm & VFP_ZERO) - goto sqrt_copy; - - /* - * Normalise a denormalised number - */ - if (tm & VFP_DENORMAL) - vfp_single_normalise_denormal(&vsm); - - /* - * sqrt(<0) = invalid - */ - if (vsm.sign) - goto sqrt_invalid; - - vfp_single_dump("sqrt", &vsm); - - /* - * Estimate the square root. - */ - vsd.sign = 0; - vsd.exponent = ((vsm.exponent - 127) >> 1) + 127; - vsd.significand = vfp_estimate_sqrt_significand(vsm.exponent, vsm.significand) + 2; - - vfp_single_dump("sqrt estimate", &vsd); - - /* - * And now adjust. - */ - if ((vsd.significand & VFP_SINGLE_LOW_BITS_MASK) <= 5) { - if (vsd.significand < 2) { - vsd.significand = 0xffffffff; - } else { - u64 term; - s64 rem; - vsm.significand <<= static_cast((vsm.exponent & 1) == 0); - term = (u64)vsd.significand * vsd.significand; - rem = ((u64)vsm.significand << 32) - term; - - LOG_TRACE(Core_ARM11, "term=%016" PRIx64 "rem=%016" PRIx64, term, rem); - - while (rem < 0) { - vsd.significand -= 1; - rem += ((u64)vsd.significand << 1) | 1; - } - vsd.significand |= rem != 0; - } - } - vsd.significand = vfp_shiftright32jamming(vsd.significand, 1); - - exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fsqrt"); - return exceptions; -} - -/* - * Equal := ZC - * Less than := N - * Greater than := C - * Unordered := CV - */ -static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, - [[maybe_unused]] u32 fpscr) -{ - s32 d; - u32 ret = 0; - - d = vfp_get_float(state, sd); - if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) { - ret |= FPSCR_CFLAG | FPSCR_VFLAG; - if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) - /* - * Signalling NaN, or signalling on quiet NaN - */ - ret |= FPSCR_IOC; - } - - if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) { - ret |= FPSCR_CFLAG | FPSCR_VFLAG; - if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) - /* - * Signalling NaN, or signalling on quiet NaN - */ - ret |= FPSCR_IOC; - } - - if (ret == 0) { - if (d == m || vfp_single_packed_abs(d | m) == 0) { - /* - * equal - */ - ret |= FPSCR_ZFLAG | FPSCR_CFLAG; - } else if (vfp_single_packed_sign(d ^ m)) { - /* - * different signs - */ - if (vfp_single_packed_sign(d)) - /* - * d is negative, so d < m - */ - ret |= FPSCR_NFLAG; - else - /* - * d is positive, so d > m - */ - ret |= FPSCR_CFLAG; - } else if ((vfp_single_packed_sign(d) != 0) ^ (d < m)) { - /* - * d < m - */ - ret |= FPSCR_NFLAG; - } else if ((vfp_single_packed_sign(d) != 0) ^ (d > m)) { - /* - * d > m - */ - ret |= FPSCR_CFLAG; - } - } - return ret; -} - -static u32 vfp_single_fcmp(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - u32 fpscr) -{ - return vfp_compare(state, sd, 0, m, fpscr); -} - -static u32 vfp_single_fcmpe(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - u32 fpscr) -{ - return vfp_compare(state, sd, 1, m, fpscr); -} - -static u32 vfp_single_fcmpz(ARMul_State* state, int sd, [[maybe_unused]] int unused, - [[maybe_unused]] s32 m, u32 fpscr) -{ - return vfp_compare(state, sd, 0, 0, fpscr); -} - -static u32 vfp_single_fcmpez(ARMul_State* state, int sd, [[maybe_unused]] int unused, - [[maybe_unused]] s32 m, u32 fpscr) -{ - return vfp_compare(state, sd, 1, 0, fpscr); -} - -static u32 vfp_single_fcvtd(ARMul_State* state, int dd, [[maybe_unused]] int unused, s32 m, - u32 fpscr) -{ - struct vfp_single vsm; - struct vfp_double vdd; - int tm; - u32 exceptions = 0; - - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - - tm = vfp_single_type(&vsm); - - /* - * If we have a signalling NaN, signal invalid operation. - */ - if (tm == VFP_SNAN) - exceptions |= FPSCR_IOC; - - if (tm & VFP_DENORMAL) - vfp_single_normalise_denormal(&vsm); - - vdd.sign = vsm.sign; - vdd.significand = (u64)vsm.significand << 32; - - /* - * If we have an infinity or NaN, the exponent must be 2047. - */ - if (tm & (VFP_INFINITY|VFP_NAN)) { - vdd.exponent = 2047; - if (tm == VFP_QNAN) - vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; - goto pack_nan; - } else if (tm & VFP_ZERO) - vdd.exponent = 0; - else - vdd.exponent = vsm.exponent + (1023 - 127); - - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fcvtd"); - return exceptions; - -pack_nan: - vfp_put_double(state, vfp_double_pack(&vdd), dd); - return exceptions; -} - -static u32 vfp_single_fuito(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - u32 fpscr) -{ - struct vfp_single vs; - u32 exceptions = 0; - - vs.sign = 0; - vs.exponent = 127 + 31 - 1; - vs.significand = (u32)m; - - exceptions |= vfp_single_normaliseround(state, sd, &vs, fpscr, "fuito"); - return exceptions; -} - -static u32 vfp_single_fsito(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - u32 fpscr) -{ - struct vfp_single vs; - u32 exceptions = 0; - - vs.sign = (m & 0x80000000) >> 16; - vs.exponent = 127 + 31 - 1; - vs.significand = vs.sign ? -m : m; - - exceptions |= vfp_single_normaliseround(state, sd, &vs, fpscr, "fsito"); - return exceptions; -} - -static u32 vfp_single_ftoui(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - u32 fpscr) -{ - struct vfp_single vsm; - u32 d, exceptions = 0; - int rmode = fpscr & FPSCR_RMODE_MASK; - int tm; - - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - vfp_single_dump("VSM", &vsm); - - /* - * Do we have a denormalised number? - */ - tm = vfp_single_type(&vsm); - if (tm & VFP_DENORMAL) - exceptions |= FPSCR_IDC; - - if (tm & VFP_NAN) - vsm.sign = 1; - - if (vsm.exponent >= 127 + 32) { - d = vsm.sign ? 0 : 0xffffffff; - exceptions |= FPSCR_IOC; - } else if (vsm.exponent >= 127) { - int shift = 127 + 31 - vsm.exponent; - u32 rem, incr = 0; - - /* - * 2^0 <= m < 2^32-2^8 - */ - d = (vsm.significand << 1) >> shift; - if (shift > 0) { - rem = (vsm.significand << 1) << (32 - shift); - } else { - rem = 0; - } - - if (rmode == FPSCR_ROUND_NEAREST) { - incr = 0x80000000; - if ((d & 1) == 0) - incr -= 1; - } else if (rmode == FPSCR_ROUND_TOZERO) { - incr = 0; - } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) { - incr = ~0; - } - - if ((rem + incr) < rem) { - if (d < 0xffffffff) - d += 1; - else - exceptions |= FPSCR_IOC; - } - - if (d && vsm.sign) { - d = 0; - exceptions |= FPSCR_IOC; - } else if (rem) - exceptions |= FPSCR_IXC; - } else { - d = 0; - if (vsm.exponent | vsm.significand) { - if (rmode == FPSCR_ROUND_NEAREST) { - if (vsm.exponent >= 126) { - d = vsm.sign ? 0 : 1; - exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC; - } else { - exceptions |= FPSCR_IXC; - } - } else if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) { - d = 1; - exceptions |= FPSCR_IXC; - } else if (rmode == FPSCR_ROUND_MINUSINF) { - exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC; - } else { - exceptions |= FPSCR_IXC; - } - } - } - - LOG_TRACE(Core_ARM11, "ftoui: d(s%d)=%08x exceptions=%08x", sd, d, exceptions); - - vfp_put_float(state, d, sd); - - return exceptions; -} - -static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) -{ - return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); -} - -static u32 vfp_single_ftosi(ARMul_State* state, int sd, [[maybe_unused]] int unused, s32 m, - u32 fpscr) -{ - struct vfp_single vsm; - u32 d, exceptions = 0; - int rmode = fpscr & FPSCR_RMODE_MASK; - int tm; - - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - vfp_single_dump("VSM", &vsm); - - /* - * Do we have a denormalised number? - */ - tm = vfp_single_type(&vsm); - if (vfp_single_type(&vsm) & VFP_DENORMAL) - exceptions |= FPSCR_IDC; - - if (tm & VFP_NAN) { - d = 0; - exceptions |= FPSCR_IOC; - } else if (vsm.exponent >= 127 + 31) { - /* - * m >= 2^31-2^7: invalid - */ - d = 0x7fffffff; - if (vsm.sign) - d = ~d; - exceptions |= FPSCR_IOC; - } else if (vsm.exponent >= 127) { - int shift = 127 + 31 - vsm.exponent; - u32 rem, incr = 0; - - /* 2^0 <= m <= 2^31-2^7 */ - d = (vsm.significand << 1) >> shift; - rem = (vsm.significand << 1) << (32 - shift); - - if (rmode == FPSCR_ROUND_NEAREST) { - incr = 0x80000000; - if ((d & 1) == 0) - incr -= 1; - } else if (rmode == FPSCR_ROUND_TOZERO) { - incr = 0; - } else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vsm.sign != 0)) { - incr = ~0; - } - - if ((rem + incr) < rem && d < 0xffffffff) - d += 1; - if (d > (0x7fffffffu + (vsm.sign != 0))) { - d = (0x7fffffffu + (vsm.sign != 0)); - exceptions |= FPSCR_IOC; - } else if (rem) - exceptions |= FPSCR_IXC; - - if (vsm.sign) - d = (~d + 1); - } else { - d = 0; - if (vsm.exponent | vsm.significand) { - exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_NEAREST) { - if (vsm.exponent >= 126) - d = vsm.sign ? 0xffffffff : 1; - } else if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) { - d = 1; - } else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { - d = 0xffffffff; - } - } - } - - LOG_TRACE(Core_ARM11, "ftosi: d(s%d)=%08x exceptions=%08x", sd, d, exceptions); - - vfp_put_float(state, (s32)d, sd); - - return exceptions; -} - -static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) -{ - return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); -} - -static struct op fops_ext[] = { - { vfp_single_fcpy, 0 }, //0x00000000 - FEXT_FCPY - { vfp_single_fabs, 0 }, //0x00000001 - FEXT_FABS - { vfp_single_fneg, 0 }, //0x00000002 - FEXT_FNEG - { vfp_single_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { vfp_single_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP - { vfp_single_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE - { vfp_single_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ - { vfp_single_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { vfp_single_fcvtd, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT - { vfp_single_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO - { vfp_single_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { nullptr, 0 }, - { vfp_single_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI - { vfp_single_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ - { vfp_single_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI - { vfp_single_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ -}; - - - - - -static u32 -vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn, - struct vfp_single *vsm, u32 fpscr) -{ - struct vfp_single *vsp; - u32 exceptions = 0; - int tn, tm; - - tn = vfp_single_type(vsn); - tm = vfp_single_type(vsm); - - if (tn & tm & VFP_INFINITY) { - /* - * Two infinities. Are they different signs? - */ - if (vsn->sign ^ vsm->sign) { - /* - * different signs -> invalid - */ - exceptions |= FPSCR_IOC; - vsp = &vfp_single_default_qnan; - } else { - /* - * same signs -> valid - */ - vsp = vsn; - } - } else if (tn & VFP_INFINITY && tm & VFP_NUMBER) { - /* - * One infinity and one number -> infinity - */ - vsp = vsn; - } else { - /* - * 'n' is a NaN of some type - */ - return vfp_propagate_nan(vsd, vsn, vsm, fpscr); - } - *vsd = *vsp; - return exceptions; -} - -static u32 -vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn, - struct vfp_single *vsm, u32 fpscr) -{ - u32 exp_diff, m_sig; - - if (vsn->significand & 0x80000000 || - vsm->significand & 0x80000000) { - LOG_WARNING(Core_ARM11, "bad FP values"); - vfp_single_dump("VSN", vsn); - vfp_single_dump("VSM", vsm); - } - - /* - * Ensure that 'n' is the largest magnitude number. Note that - * if 'n' and 'm' have equal exponents, we do not swap them. - * This ensures that NaN propagation works correctly. - */ - if (vsn->exponent < vsm->exponent) { - std::swap(vsm, vsn); - } - - /* - * Is 'n' an infinity or a NaN? Note that 'm' may be a number, - * infinity or a NaN here. - */ - if (vsn->exponent == 255) - return vfp_single_fadd_nonnumber(vsd, vsn, vsm, fpscr); - - /* - * We have two proper numbers, where 'vsn' is the larger magnitude. - * - * Copy 'n' to 'd' before doing the arithmetic. - */ - *vsd = *vsn; - - /* - * Align both numbers. - */ - exp_diff = vsn->exponent - vsm->exponent; - m_sig = vfp_shiftright32jamming(vsm->significand, exp_diff); - - /* - * If the signs are different, we are really subtracting. - */ - if (vsn->sign ^ vsm->sign) { - m_sig = vsn->significand - m_sig; - if ((s32)m_sig < 0) { - vsd->sign = vfp_sign_negate(vsd->sign); - m_sig = (~m_sig + 1); - } else if (m_sig == 0) { - vsd->sign = (fpscr & FPSCR_RMODE_MASK) == - FPSCR_ROUND_MINUSINF ? 0x8000 : 0; - } - } else { - m_sig = vsn->significand + m_sig; - } - vsd->significand = m_sig; - - return 0; -} - -static u32 -vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr) -{ - vfp_single_dump("VSN", vsn); - vfp_single_dump("VSM", vsm); - - /* - * Ensure that 'n' is the largest magnitude number. Note that - * if 'n' and 'm' have equal exponents, we do not swap them. - * This ensures that NaN propagation works correctly. - */ - if (vsn->exponent < vsm->exponent) { - std::swap(vsm, vsn); - LOG_TRACE(Core_ARM11, "swapping M <-> N"); - } - - vsd->sign = vsn->sign ^ vsm->sign; - - /* - * If 'n' is an infinity or NaN, handle it. 'm' may be anything. - */ - if (vsn->exponent == 255) { - if (vsn->significand || (vsm->exponent == 255 && vsm->significand)) - return vfp_propagate_nan(vsd, vsn, vsm, fpscr); - if ((vsm->exponent | vsm->significand) == 0) { - *vsd = vfp_single_default_qnan; - return FPSCR_IOC; - } - vsd->exponent = vsn->exponent; - vsd->significand = 0; - return 0; - } - - /* - * If 'm' is zero, the result is always zero. In this case, - * 'n' may be zero or a number, but it doesn't matter which. - */ - if ((vsm->exponent | vsm->significand) == 0) { - vsd->exponent = 0; - vsd->significand = 0; - return 0; - } - - /* - * We add 2 to the destination exponent for the same reason as - * the addition case - though this time we have +1 from each - * input operand. - */ - vsd->exponent = vsn->exponent + vsm->exponent - 127 + 2; - vsd->significand = vfp_hi64to32jamming((u64)vsn->significand * vsm->significand); - - vfp_single_dump("VSD", vsd); - return 0; -} - -#define NEG_MULTIPLY (1 << 0) -#define NEG_SUBTRACT (1 << 1) - -static u32 -vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, const char *func) -{ - vfp_single vsd, vsp, vsn, vsm; - u32 exceptions = 0; - s32 v; - - v = vfp_get_float(state, sn); - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, v); - exceptions |= vfp_single_unpack(&vsn, v, fpscr); - if (vsn.exponent == 0 && vsn.significand) - vfp_single_normalise_denormal(&vsn); - - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - if (vsm.exponent == 0 && vsm.significand) - vfp_single_normalise_denormal(&vsm); - - exceptions |= vfp_single_multiply(&vsp, &vsn, &vsm, fpscr); - - if (negate & NEG_MULTIPLY) - vsp.sign = vfp_sign_negate(vsp.sign); - - v = vfp_get_float(state, sd); - LOG_TRACE(Core_ARM11, "s%u = %08x", sd, v); - exceptions |= vfp_single_unpack(&vsn, v, fpscr); - if (vsn.exponent == 0 && vsn.significand != 0) - vfp_single_normalise_denormal(&vsn); - - if (negate & NEG_SUBTRACT) - vsn.sign = vfp_sign_negate(vsn.sign); - - exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr); - - exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, func); - return exceptions; -} - -/* - * Standard operations - */ - -/* - * sd = sd + (sn * sm) - */ -static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - u32 exceptions = 0; - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); - exceptions |= vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac"); - return exceptions; -} - -/* - * sd = sd - (sn * sm) - */ -static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - // TODO: this one has its arguments inverted, investigate. - LOG_TRACE(Core_ARM11, "s%u = %08x", sd, sn); - return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac"); -} - -/* - * sd = -sd + (sn * sm) - */ -static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); - return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc"); -} - -/* - * sd = -sd - (sn * sm) - */ -static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); - return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); -} - -/* - * sd = sn * sm - */ -static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - struct vfp_single vsd, vsn, vsm; - u32 exceptions = 0; - s32 n = vfp_get_float(state, sn); - - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, n); - - exceptions |= vfp_single_unpack(&vsn, n, fpscr); - if (vsn.exponent == 0 && vsn.significand) - vfp_single_normalise_denormal(&vsn); - - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - if (vsm.exponent == 0 && vsm.significand) - vfp_single_normalise_denormal(&vsm); - - exceptions |= vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); - - exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fmul"); - return exceptions; -} - -/* - * sd = -(sn * sm) - */ -static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - struct vfp_single vsd, vsn, vsm; - u32 exceptions = 0; - s32 n = vfp_get_float(state, sn); - - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, n); - - exceptions |= vfp_single_unpack(&vsn, n, fpscr); - if (vsn.exponent == 0 && vsn.significand) - vfp_single_normalise_denormal(&vsn); - - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - if (vsm.exponent == 0 && vsm.significand) - vfp_single_normalise_denormal(&vsm); - - exceptions |= vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); - vsd.sign = vfp_sign_negate(vsd.sign); - - exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fnmul"); - return exceptions; -} - -/* - * sd = sn + sm - */ -static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - struct vfp_single vsd, vsn, vsm; - u32 exceptions = 0; - s32 n = vfp_get_float(state, sn); - - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, n); - - /* - * Unpack and normalise denormals. - */ - exceptions |= vfp_single_unpack(&vsn, n, fpscr); - if (vsn.exponent == 0 && vsn.significand) - vfp_single_normalise_denormal(&vsn); - - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - if (vsm.exponent == 0 && vsm.significand) - vfp_single_normalise_denormal(&vsm); - - exceptions |= vfp_single_add(&vsd, &vsn, &vsm, fpscr); - - exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fadd"); - return exceptions; -} - -/* - * sd = sn - sm - */ -static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); - /* - * Subtraction is addition with one sign inverted. - */ - if (m != 0x7FC00000) // Only negate if m isn't NaN. - m = vfp_single_packed_negate(m); - - return vfp_single_fadd(state, sd, sn, m, fpscr); -} - -/* - * sd = sn / sm - */ -static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) -{ - struct vfp_single vsd, vsn, vsm; - u32 exceptions = 0; - s32 n = vfp_get_float(state, sn); - int tm, tn; - - LOG_TRACE(Core_ARM11, "s%u = %08x", sn, n); - - exceptions |= vfp_single_unpack(&vsn, n, fpscr); - exceptions |= vfp_single_unpack(&vsm, m, fpscr); - - vsd.sign = vsn.sign ^ vsm.sign; - - tn = vfp_single_type(&vsn); - tm = vfp_single_type(&vsm); - - /* - * Is n a NAN? - */ - if (tn & VFP_NAN) - goto vsn_nan; - - /* - * Is m a NAN? - */ - if (tm & VFP_NAN) - goto vsm_nan; - - /* - * If n and m are infinity, the result is invalid - * If n and m are zero, the result is invalid - */ - if (tm & tn & (VFP_INFINITY|VFP_ZERO)) - goto invalid; - - /* - * If n is infinity, the result is infinity - */ - if (tn & VFP_INFINITY) - goto infinity; - - /* - * If m is zero, raise div0 exception - */ - if (tm & VFP_ZERO) - goto divzero; - - /* - * If m is infinity, or n is zero, the result is zero - */ - if (tm & VFP_INFINITY || tn & VFP_ZERO) - goto zero; - - if (tn & VFP_DENORMAL) - vfp_single_normalise_denormal(&vsn); - if (tm & VFP_DENORMAL) - vfp_single_normalise_denormal(&vsm); - - /* - * Ok, we have two numbers, we can perform division. - */ - vsd.exponent = vsn.exponent - vsm.exponent + 127 - 1; - vsm.significand <<= 1; - if (vsm.significand <= (2 * vsn.significand)) { - vsn.significand >>= 1; - vsd.exponent++; - } - { - u64 significand = (u64)vsn.significand << 32; - do_div(significand, vsm.significand); - vsd.significand = (u32)significand; - } - if ((vsd.significand & 0x3f) == 0) - vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32); - - exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fdiv"); - return exceptions; - -vsn_nan: - exceptions |= vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); -pack: - vfp_put_float(state, vfp_single_pack(&vsd), sd); - return exceptions; - -vsm_nan: - exceptions |= vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr); - goto pack; - -zero: - vsd.exponent = 0; - vsd.significand = 0; - goto pack; - -divzero: - exceptions |= FPSCR_DZC; -infinity: - vsd.exponent = 255; - vsd.significand = 0; - goto pack; - -invalid: - vfp_put_float(state, vfp_single_pack(&vfp_single_default_qnan), sd); - exceptions |= FPSCR_IOC; - return exceptions; -} - -static struct op fops[] = { - { vfp_single_fmac, 0 }, - { vfp_single_fmsc, 0 }, - { vfp_single_fmul, 0 }, - { vfp_single_fadd, 0 }, - { vfp_single_fnmac, 0 }, - { vfp_single_fnmsc, 0 }, - { vfp_single_fnmul, 0 }, - { vfp_single_fsub, 0 }, - { vfp_single_fdiv, 0 }, -}; - -#define FREG_BANK(x) ((x) & 0x18) -#define FREG_IDX(x) ((x) & 7) - -u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) -{ - u32 op = inst & FOP_MASK; - u32 exceptions = 0; - unsigned int dest; - unsigned int sn = vfp_get_sn(inst); - unsigned int sm = vfp_get_sm(inst); - unsigned int vecitr, veclen, vecstride; - struct op *fop; - - vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); - - fop = (op == FOP_EXT) ? &fops_ext[FEXT_TO_IDX(inst)] : &fops[FOP_TO_IDX(op)]; - - /* - * fcvtsd takes a dN register number as destination, not sN. - * Technically, if bit 0 of dd is set, this is an invalid - * instruction. However, we ignore this for efficiency. - * It also only operates on scalars. - */ - if (fop->flags & OP_DD) - dest = vfp_get_dd(inst); - else - dest = vfp_get_sd(inst); - - /* - * If destination bank is zero, vector length is always '1'. - * ARM DDI0100F C5.1.3, C5.3.2. - */ - if ((fop->flags & OP_SCALAR) || FREG_BANK(dest) == 0) - veclen = 0; - else - veclen = fpscr & FPSCR_LENGTH_MASK; - - LOG_TRACE(Core_ARM11, "vecstride=%u veclen=%u", vecstride, - (veclen >> FPSCR_LENGTH_BIT) + 1); - - if (!fop->fn) { - ASSERT_MSG(false, "could not find single op {}, inst=0x{:08x}@0x{:08x}", FEXT_TO_IDX(inst), inst, state->Reg[15]); - goto invalid; - } - - for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) { - s32 m = vfp_get_float(state, sm); - u32 except; - - if (op == FOP_EXT) - LOG_TRACE(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)", - vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, - sm, m); - else - LOG_TRACE(Core_ARM11, "itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)", - vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, - FOP_TO_IDX(op), sm, m); - - except = fop->fn(state, dest, sn, m, fpscr); - LOG_TRACE(Core_ARM11, "itr%d: exceptions=%08x", - vecitr >> FPSCR_LENGTH_BIT, except); - - exceptions |= except; - - /* - * CHECK: It appears to be undefined whether we stop when - * we encounter an exception. We continue. - */ - dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7); - sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7); - if (FREG_BANK(sm) != 0) - sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7); - } - return exceptions; - -invalid: - return (u32)-1; -} diff --git a/tests/A32/test_thumb_instructions.cpp b/tests/A32/test_thumb_instructions.cpp index 0108ab53..8c0ac18f 100644 --- a/tests/A32/test_thumb_instructions.cpp +++ b/tests/A32/test_thumb_instructions.cpp @@ -9,8 +9,6 @@ #include #include "common/common_types.h" -#include "A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h" -#include "A32/skyeye_interpreter/skyeye_common/armstate.h" #include "testenv.h" static Dynarmic::A32::UserConfig GetUserConfig(ThumbTestEnv* testenv) { diff --git a/tests/A32/testenv.h b/tests/A32/testenv.h index 9feec677..a1968ff3 100644 --- a/tests/A32/testenv.h +++ b/tests/A32/testenv.h @@ -17,9 +17,10 @@ #include "common/assert.h" #include "common/common_types.h" -template +template class A32TestEnv final : public Dynarmic::A32::UserCallbacks { public: + using InstructionType = InstructionType_; using RegisterArray = std::array; using ExtRegsArray = std::array; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 92d15ffd..21f86e31 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,27 +1,4 @@ add_executable(dynarmic_tests - A32/fuzz_arm.cpp - A32/fuzz_thumb.cpp - A32/skyeye_interpreter/dyncom/arm_dyncom_dec.cpp - A32/skyeye_interpreter/dyncom/arm_dyncom_dec.h - A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.cpp - A32/skyeye_interpreter/dyncom/arm_dyncom_interpreter.h - A32/skyeye_interpreter/dyncom/arm_dyncom_run.h - A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.cpp - A32/skyeye_interpreter/dyncom/arm_dyncom_thumb.h - A32/skyeye_interpreter/dyncom/arm_dyncom_trans.cpp - A32/skyeye_interpreter/dyncom/arm_dyncom_trans.h - A32/skyeye_interpreter/skyeye_common/arm_regformat.h - A32/skyeye_interpreter/skyeye_common/armstate.cpp - A32/skyeye_interpreter/skyeye_common/armstate.h - A32/skyeye_interpreter/skyeye_common/armsupp.cpp - A32/skyeye_interpreter/skyeye_common/armsupp.h - A32/skyeye_interpreter/skyeye_common/vfp/asm_vfp.h - A32/skyeye_interpreter/skyeye_common/vfp/vfp.cpp - A32/skyeye_interpreter/skyeye_common/vfp/vfp.h - A32/skyeye_interpreter/skyeye_common/vfp/vfp_helper.h - A32/skyeye_interpreter/skyeye_common/vfp/vfpdouble.cpp - A32/skyeye_interpreter/skyeye_common/vfp/vfpinstr.cpp - A32/skyeye_interpreter/skyeye_common/vfp/vfpsingle.cpp A32/test_arm_disassembler.cpp A32/test_thumb_instructions.cpp A32/testenv.h @@ -39,6 +16,8 @@ add_executable(dynarmic_tests if (DYNARMIC_TESTS_USE_UNICORN) target_sources(dynarmic_tests PRIVATE + A32/fuzz_arm.cpp + A32/fuzz_thumb.cpp A64/fuzz_with_unicorn.cpp A64/verify_unicorn.cpp fuzz_util.cpp diff --git a/tests/unicorn_emu/a32_unicorn.cpp b/tests/unicorn_emu/a32_unicorn.cpp index ce07a331..7dd487a5 100644 --- a/tests/unicorn_emu/a32_unicorn.cpp +++ b/tests/unicorn_emu/a32_unicorn.cpp @@ -4,6 +4,7 @@ * General Public License version 2 or any later version. */ +#include #include "A32/testenv.h" #include "a32_unicorn.h" #include "common/assert.h" @@ -19,23 +20,31 @@ constexpr u32 BEGIN_ADDRESS = 0; constexpr u32 END_ADDRESS = ~u32(0); -A32Unicorn::A32Unicorn(ArmTestEnv& testenv) : testenv(testenv) { - CHECKED(uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc)); +template +A32Unicorn::A32Unicorn(TestEnvironment& testenv) : testenv{testenv} { + constexpr uc_mode open_mode = std::is_same_v ? UC_MODE_ARM : UC_MODE_THUMB; + + CHECKED(uc_open(UC_ARCH_ARM, open_mode, &uc)); CHECKED(uc_hook_add(uc, &intr_hook, UC_HOOK_INTR, (void*)InterruptHook, this, BEGIN_ADDRESS, END_ADDRESS)); CHECKED(uc_hook_add(uc, &mem_invalid_hook, UC_HOOK_MEM_INVALID, (void*)UnmappedMemoryHook, this, BEGIN_ADDRESS, END_ADDRESS)); CHECKED(uc_hook_add(uc, &mem_write_prot_hook, UC_HOOK_MEM_WRITE, (void*)MemoryWriteHook, this, BEGIN_ADDRESS, END_ADDRESS)); } -A32Unicorn::~A32Unicorn() { +template +A32Unicorn::~A32Unicorn() { ClearPageCache(); CHECKED(uc_hook_del(uc, intr_hook)); CHECKED(uc_hook_del(uc, mem_invalid_hook)); CHECKED(uc_close(uc)); } -void A32Unicorn::Run() { +template +void A32Unicorn::Run() { + // Thumb execution mode requires the LSB to be set to 1. + constexpr u64 mask = std::is_same_v ? 0 : 1; + while (testenv.ticks_left > 0) { - CHECKED(uc_emu_start(uc, GetPC(), END_ADDRESS, 0, 1)); + CHECKED(uc_emu_start(uc, GetPC() | mask, END_ADDRESS, 0, 1)); testenv.ticks_left--; if (!testenv.interrupts.empty() || testenv.code_mem_modified_by_guest) { return; @@ -43,63 +52,72 @@ void A32Unicorn::Run() { } } -u32 A32Unicorn::GetPC() const { +template +u32 A32Unicorn::GetPC() const { u32 pc; CHECKED(uc_reg_read(uc, UC_ARM_REG_PC, &pc)); return pc; } -void A32Unicorn::SetPC(u32 value) { +template +void A32Unicorn::SetPC(u32 value) { CHECKED(uc_reg_write(uc, UC_ARM_REG_PC, &value)); } -u32 A32Unicorn::GetSP() const { +template +u32 A32Unicorn::GetSP() const { u32 sp; CHECKED(uc_reg_read(uc, UC_ARM_REG_SP, &sp)); return sp; } -void A32Unicorn::SetSP(u32 value) { +template +void A32Unicorn::SetSP(u32 value) { CHECKED(uc_reg_write(uc, UC_ARM_REG_SP, &value)); } -constexpr std::array gpr_ids{ +constexpr std::array gpr_ids{ UC_ARM_REG_R0, UC_ARM_REG_R1, UC_ARM_REG_R2, UC_ARM_REG_R3, UC_ARM_REG_R4, UC_ARM_REG_R5, UC_ARM_REG_R6, UC_ARM_REG_R7, UC_ARM_REG_R8, UC_ARM_REG_R9, UC_ARM_REG_R10, UC_ARM_REG_R11, UC_ARM_REG_R12, UC_ARM_REG_R13, UC_ARM_REG_R14, UC_ARM_REG_R15, }; -A32Unicorn::RegisterArray A32Unicorn::GetRegisters() const { - RegisterArray regs; - RegisterPtrArray ptrs; - for (size_t i = 0; i < ptrs.size(); ++i) +template +Unicorn::A32::RegisterArray A32Unicorn::GetRegisters() const { + Unicorn::A32::RegisterArray regs; + Unicorn::A32::RegisterPtrArray ptrs; + for (size_t i = 0; i < ptrs.size(); ++i) { ptrs[i] = ®s[i]; + } CHECKED(uc_reg_read_batch(uc, const_cast(gpr_ids.data()), - reinterpret_cast(ptrs.data()), num_gprs)); + reinterpret_cast(ptrs.data()), Unicorn::A32::num_gprs)); return regs; } -void A32Unicorn::SetRegisters(const RegisterArray& value) { - RegisterConstPtrArray ptrs; - for (size_t i = 0; i < ptrs.size(); ++i) +template +void A32Unicorn::SetRegisters(const RegisterArray& value) { + Unicorn::A32::RegisterConstPtrArray ptrs; + for (size_t i = 0; i < ptrs.size(); ++i) { ptrs[i] = &value[i]; + } CHECKED(uc_reg_write_batch(uc, const_cast(gpr_ids.data()), reinterpret_cast(const_cast(ptrs.data())), ptrs.size())); } -using DoubleExtRegPtrArray = std::array; -using DoubleExtRegConstPtrArray = std::array; +using DoubleExtRegPtrArray = std::array; +using DoubleExtRegConstPtrArray = std::array; -constexpr std::array double_ext_reg_ids{ +constexpr std::array double_ext_reg_ids{ UC_ARM_REG_D0, UC_ARM_REG_D1, UC_ARM_REG_D2, UC_ARM_REG_D3, UC_ARM_REG_D4, UC_ARM_REG_D5, UC_ARM_REG_D6, UC_ARM_REG_D7, UC_ARM_REG_D8, UC_ARM_REG_D9, UC_ARM_REG_D10, UC_ARM_REG_D11, UC_ARM_REG_D12, UC_ARM_REG_D13, UC_ARM_REG_D14, UC_ARM_REG_D15, UC_ARM_REG_D16, UC_ARM_REG_D17, UC_ARM_REG_D18, UC_ARM_REG_D19, UC_ARM_REG_D20, UC_ARM_REG_D21, UC_ARM_REG_D22, UC_ARM_REG_D23, UC_ARM_REG_D24, UC_ARM_REG_D25, UC_ARM_REG_D26, UC_ARM_REG_D27, UC_ARM_REG_D28, UC_ARM_REG_D29, UC_ARM_REG_D30, UC_ARM_REG_D31, }; -A32Unicorn::ExtRegArray A32Unicorn::GetExtRegs() const { - ExtRegArray ext_regs; +template +Unicorn::A32::ExtRegArray A32Unicorn::GetExtRegs() const { + Unicorn::A32::ExtRegArray ext_regs; DoubleExtRegPtrArray ptrs; for (size_t i = 0; i < ptrs.size(); ++i) ptrs[i] = &ext_regs[i*2]; @@ -110,43 +128,69 @@ A32Unicorn::ExtRegArray A32Unicorn::GetExtRegs() const { return ext_regs; } -void A32Unicorn::SetExtRegs(const ExtRegArray& value) { +template +void A32Unicorn::SetExtRegs(const ExtRegArray& value) { DoubleExtRegConstPtrArray ptrs; - for (size_t i = 0; i < ptrs.size(); ++i) + for (size_t i = 0; i < ptrs.size(); ++i) { ptrs[i] = &value[i*2]; + } CHECKED(uc_reg_write_batch(uc, const_cast(double_ext_reg_ids.data()), reinterpret_cast(const_cast(ptrs.data())), ptrs.size())); } -u32 A32Unicorn::GetFpscr() const { +template +u32 A32Unicorn::GetFpscr() const { u32 fpsr; CHECKED(uc_reg_read(uc, UC_ARM_REG_FPSCR, &fpsr)); return fpsr; } -void A32Unicorn::SetFpscr(u32 value) { +template +void A32Unicorn::SetFpscr(u32 value) { CHECKED(uc_reg_write(uc, UC_ARM_REG_FPSCR, &value)); } -u32 A32Unicorn::GetCpsr() const { +template +u32 A32Unicorn::GetFpexc() const { + u32 value = 0; + CHECKED(uc_reg_read(uc, UC_ARM_REG_FPEXC, &value)); + return value; +} + +template +void A32Unicorn::SetFpexc(u32 value) { + CHECKED(uc_reg_write(uc, UC_ARM_REG_FPEXC, &value)); +} + +template +u32 A32Unicorn::GetCpsr() const { u32 pstate; CHECKED(uc_reg_read(uc, UC_ARM_REG_CPSR, &pstate)); return pstate; } -void A32Unicorn::SetCpsr(u32 value) { +template +void A32Unicorn::SetCpsr(u32 value) { CHECKED(uc_reg_write(uc, UC_ARM_REG_CPSR, &value)); } -void A32Unicorn::ClearPageCache() { +template +void A32Unicorn::EnableFloatingPointAccess() { + const u32 new_fpexc = GetFpexc() | (1U << 30); + SetFpexc(new_fpexc); +} + +template +void A32Unicorn::ClearPageCache() { for (const auto& page : pages) { CHECKED(uc_mem_unmap(uc, page->address, 4096)); } pages.clear(); } -void A32Unicorn::DumpMemoryInformation() { +template +void A32Unicorn::DumpMemoryInformation() { uc_mem_region* regions; u32 count; CHECKED(uc_mem_regions(uc, ®ions, &count)); @@ -158,7 +202,8 @@ void A32Unicorn::DumpMemoryInformation() { CHECKED(uc_free(regions)); } -void A32Unicorn::InterruptHook(uc_engine* /*uc*/, u32 int_number, void* user_data) { +template +void A32Unicorn::InterruptHook(uc_engine* /*uc*/, u32 int_number, void* user_data) { auto* this_ = static_cast(user_data); u32 esr = 0; @@ -177,15 +222,17 @@ void A32Unicorn::InterruptHook(uc_engine* /*uc*/, u32 int_number, void* user_dat } } -bool A32Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type /*type*/, u32 start_address, int size, u64 /*value*/, void* user_data) { +template +bool A32Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type /*type*/, u32 start_address, int size, u64 /*value*/, void* user_data) { auto* this_ = static_cast(user_data); const auto generate_page = [&](u32 base_address) { // printf("generate_page(%x)\n", base_address); const u32 permissions = [&]() -> u32 { - if (base_address < this_->testenv.code_mem.size() * 4) + if (base_address < this_->testenv.code_mem.size() * sizeof(typename TestEnvironment::InstructionType)) { return UC_PROT_READ | UC_PROT_EXEC; + } return UC_PROT_READ; }(); @@ -220,7 +267,8 @@ bool A32Unicorn::UnmappedMemoryHook(uc_engine* uc, uc_mem_type /*type*/, u32 sta return true; } -bool A32Unicorn::MemoryWriteHook(uc_engine* /*uc*/, uc_mem_type /*type*/, u32 start_address, int size, u64 value, void* user_data) { +template +bool A32Unicorn::MemoryWriteHook(uc_engine* /*uc*/, uc_mem_type /*type*/, u32 start_address, int size, u64 value, void* user_data) { auto* this_ = static_cast(user_data); switch (size) { @@ -242,3 +290,6 @@ bool A32Unicorn::MemoryWriteHook(uc_engine* /*uc*/, uc_mem_type /*type*/, u32 st return true; } + +template class A32Unicorn; +template class A32Unicorn; diff --git a/tests/unicorn_emu/a32_unicorn.h b/tests/unicorn_emu/a32_unicorn.h index 378ca792..bbac40f1 100644 --- a/tests/unicorn_emu/a32_unicorn.h +++ b/tests/unicorn_emu/a32_unicorn.h @@ -15,17 +15,23 @@ #include "A32/testenv.h" +namespace Unicorn::A32 { +static constexpr size_t num_gprs = 16; +static constexpr size_t num_ext_regs = 64; + +using ExtRegArray = std::array; +using RegisterArray = std::array; +using RegisterPtrArray = std::array; +using RegisterConstPtrArray = std::array; +} // namespace Unicorn::A32 + +template class A32Unicorn final { public: - static constexpr size_t num_gprs = 16; - using RegisterArray = std::array; - using RegisterPtrArray = std::array; - using RegisterConstPtrArray = std::array; + using ExtRegArray = Unicorn::A32::ExtRegArray; + using RegisterArray = Unicorn::A32::RegisterArray; - static constexpr size_t num_ext_regs = 64; - using ExtRegArray = std::array; - - explicit A32Unicorn(ArmTestEnv& testenv); + explicit A32Unicorn(TestEnvironment& testenv); ~A32Unicorn(); void Run(); @@ -45,9 +51,14 @@ public: u32 GetFpscr() const; void SetFpscr(u32 value); + u32 GetFpexc() const; + void SetFpexc(u32 value); + u32 GetCpsr() const; void SetCpsr(u32 value); + void EnableFloatingPointAccess(); + void ClearPageCache(); void DumpMemoryInformation(); @@ -62,7 +73,7 @@ private: std::array data; }; - ArmTestEnv& testenv; + TestEnvironment& testenv; uc_engine* uc{}; uc_hook intr_hook{}; uc_hook mem_invalid_hook{};