diff options
author | bunnei <bunneidev@gmail.com> | 2014-09-13 00:34:51 +0200 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2014-10-25 20:11:39 +0200 |
commit | 53a22b84da9690865954f666694de885ccb7c286 (patch) | |
tree | 77fa8c9fb653173cc78ffd7b0110d695c3fbb772 /src/core/arm/dyncom | |
parent | ARM: Reorganized file structure to move shared SkyEye code to a more common area. (diff) | |
download | yuzu-53a22b84da9690865954f666694de885ccb7c286.tar yuzu-53a22b84da9690865954f666694de885ccb7c286.tar.gz yuzu-53a22b84da9690865954f666694de885ccb7c286.tar.bz2 yuzu-53a22b84da9690865954f666694de885ccb7c286.tar.lz yuzu-53a22b84da9690865954f666694de885ccb7c286.tar.xz yuzu-53a22b84da9690865954f666694de885ccb7c286.tar.zst yuzu-53a22b84da9690865954f666694de885ccb7c286.zip |
Diffstat (limited to '')
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom.cpp | 164 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom.h | 90 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.cpp | 402 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_dec.h | 155 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 6559 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.h | 7 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_run.cpp | 120 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_run.h | 55 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_thumb.cpp | 521 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_thumb.h | 51 |
10 files changed, 8124 insertions, 0 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp new file mode 100644 index 000000000..7a65669ef --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -0,0 +1,164 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "core/arm/skyeye_common/armcpu.h" +#include "core/arm/skyeye_common/armemu.h" +#include "core/arm/skyeye_common/vfp/vfp.h" + +#include "core/arm/dyncom/arm_dyncom.h" +#include "core/arm/dyncom/arm_dyncom_interpreter.h" + +const static cpu_config_t s_arm11_cpu_info = { + "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE +}; + +ARM_DynCom::ARM_DynCom() : ticks(0) { + state = std::unique_ptr<ARMul_State>(new ARMul_State); + + ARMul_EmulateInit(); + memset(state.get(), 0, sizeof(ARMul_State)); + + ARMul_NewState((ARMul_State*)state.get()); + + state->abort_model = 0; + state->cpu = (cpu_config_t*)&s_arm11_cpu_info; + state->bigendSig = LOW; + + ARMul_SelectProcessor(state.get(), ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); + state->lateabtSig = LOW; + mmu_init(state); + + // Reset the core to initial state + ARMul_CoProInit(state.get()); + ARMul_Reset(state.get()); + state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext + state->Emulate = 3; + + state->pc = state->Reg[15] = 0x00000000; + state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack + state->servaddr = 0xFFFF0000; + state->NirqSig = HIGH; + + VFPInit(state.get()); // Initialize the VFP + + ARMul_EmulateInit(); +} + +ARM_DynCom::~ARM_DynCom() { +} + +/** + * Set the Program Counter to an address + * @param addr Address to set PC to + */ +void ARM_DynCom::SetPC(u32 pc) { + state->pc = state->Reg[15] = pc; +} + +/* + * Get the current Program Counter + * @return Returns current PC + */ +u32 ARM_DynCom::GetPC() const { + return state->pc; +} + +/** + * Get an ARM register + * @param index Register index (0-15) + * @return Returns the value in the register + */ +u32 ARM_DynCom::GetReg(int index) const { + return state->Reg[index]; +} + +/** + * Set an ARM register + * @param index Register index (0-15) + * @param value Value to set register to + */ +void ARM_DynCom::SetReg(int index, u32 value) { + state->Reg[index] = value; +} + +/** + * Get the current CPSR register + * @return Returns the value of the CPSR register + */ +u32 ARM_DynCom::GetCPSR() const { + return state->Cpsr; +} + +/** + * Set the current CPSR register + * @param cpsr Value to set CPSR to + */ +void ARM_DynCom::SetCPSR(u32 cpsr) { + state->Cpsr = cpsr; +} + +/** + * Returns the number of clock ticks since the last reset + * @return Returns number of clock ticks + */ +u64 ARM_DynCom::GetTicks() const { + return ticks; +} + +/** + * Executes the given number of instructions + * @param num_instructions Number of instructions to executes + */ +void ARM_DynCom::ExecuteInstructions(int num_instructions) { + ticks += num_instructions; + state->NumInstrsToExecute = num_instructions; + InterpreterMainLoop(state.get()); +} + +/** + * Saves the current CPU context + * @param ctx Thread context to save + * @todo Do we need to save Reg[15] and NextInstr? + */ +void ARM_DynCom::SaveContext(ThreadContext& ctx) { + memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); + memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); + + ctx.sp = state->Reg[13]; + ctx.lr = state->Reg[14]; + ctx.pc = state->pc; + ctx.cpsr = state->Cpsr; + + ctx.fpscr = state->VFP[1]; + ctx.fpexc = state->VFP[2]; + + ctx.reg_15 = state->Reg[15]; + ctx.mode = state->NextInstr; +} + +/** + * Loads a CPU context + * @param ctx Thread context to load + * @param Do we need to load Reg[15] and NextInstr? + */ +void ARM_DynCom::LoadContext(const ThreadContext& ctx) { + memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); + memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); + + state->Reg[13] = ctx.sp; + state->Reg[14] = ctx.lr; + state->pc = ctx.pc; + state->Cpsr = ctx.cpsr; + + state->VFP[1] = ctx.fpscr; + state->VFP[2] = ctx.fpexc; + + state->Reg[15] = ctx.reg_15; + state->NextInstr = ctx.mode; +} + +/// Prepare core for thread reschedule (if needed to correctly handle state) +void ARM_DynCom::PrepareReschedule() { + state->NumInstrsToExecute = 0; +} diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h new file mode 100644 index 000000000..9f88dd139 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -0,0 +1,90 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include <memory> + +#include "common/common_types.h" + +#include "core/arm/arm_interface.h" +#include "core/arm/skyeye_common/armdefs.h" + +class ARM_DynCom final : virtual public ARM_Interface { +public: + + ARM_DynCom(); + ~ARM_DynCom(); + + /** + * Set the Program Counter to an address + * @param addr Address to set PC to + */ + void SetPC(u32 pc); + + /* + * Get the current Program Counter + * @return Returns current PC + */ + u32 GetPC() const; + + /** + * Get an ARM register + * @param index Register index (0-15) + * @return Returns the value in the register + */ + u32 GetReg(int index) const; + + /** + * Set an ARM register + * @param index Register index (0-15) + * @param value Value to set register to + */ + void SetReg(int index, u32 value); + + /** + * Get the current CPSR register + * @return Returns the value of the CPSR register + */ + u32 GetCPSR() const; + + /** + * Set the current CPSR register + * @param cpsr Value to set CPSR to + */ + void SetCPSR(u32 cpsr); + + /** + * Returns the number of clock ticks since the last reset + * @return Returns number of clock ticks + */ + u64 GetTicks() const; + + /** + * Saves the current CPU context + * @param ctx Thread context to save + */ + void SaveContext(ThreadContext& ctx); + + /** + * Loads a CPU context + * @param ctx Thread context to load + */ + void LoadContext(const ThreadContext& ctx); + + /// Prepare core for thread reschedule (if needed to correctly handle state) + void PrepareReschedule(); + + /** + * Executes the given number of instructions + * @param num_instructions Number of instructions to executes + */ + void ExecuteInstructions(int num_instructions); + +private: + + std::unique_ptr<ARMul_State> state; + u64 ticks; + +}; diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp new file mode 100644 index 000000000..5d174a08f --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp @@ -0,0 +1,402 @@ +/* Copyright (C) +* 2012 - 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_dec.cpp +* @brief Some common utility for arm decoder +* @author Michael.Kang blackfin.kang@gmail.com +* @version 7849 +* @date 2012-03-15 +*/ + +#include "core/arm/skyeye_common/arm_regformat.h" +#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/dyncom/arm_dyncom_dec.h" + +const ISEITEM arm_instruction[] = { + #define VFP_DECODE + #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" + #undef VFP_DECODE + {"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, 31, 0x00000e12, 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}, +// {"smlal" , 2 , 4 , 21, 27, 0x00000007, 4, 7, 0x00000009}, + {"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" , 2 , 0 , 23, 27, 0x00000006, 20, 21, 0x00000002}, + {"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}, + {"swi" , 1 , 0 , 24, 27, 0x0000000f}, + {"bbl" , 1 , 0 , 25, 27, 0x00000005}, +}; + +const ISEITEM arm_exclusion_code[] = { + #define VFP_DECODE_EXCLUSION + #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" + #undef VFP_DECODE_EXCLUSION + {"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}, + {"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}, + {"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} +}; + +int decode_arm_instr(uint32_t instr, int32_t *idx) +{ + int n = 0; + int base = 0; + int ret = DECODE_FAILURE; + int i = 0; + int instr_slots = sizeof(arm_instruction)/sizeof(ISEITEM); + for (i = 0; i < instr_slots; i++) + { +// ret = DECODE_SUCCESS; + n = arm_instruction[i].attribute_value; + base = 0; + 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(arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) { + break; + } + base += 3; + n --; + } + //All conditions is satisfied. + if (n == 0) + ret = DECODE_SUCCESS; + + if (ret == DECODE_SUCCESS) { + n = arm_exclusion_code[i].attribute_value; + if (n != 0) { + base = 0; + while (n) { + if (BITS(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 is satisfied. + if (n == 0) + ret = DECODE_FAILURE; + } + } + + if (ret == DECODE_SUCCESS) { + *idx = i; + return ret; + } + } + return ret; +} + diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h new file mode 100644 index 000000000..19d94f369 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_dec.h @@ -0,0 +1,155 @@ +/* Copyright (C) +* 2012 - 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_dec.h +* @brief Some common utility for arm instruction decoder +* @author Michael.Kang blackfin.kang@gmail.com +* @version 7849 +* @date 2012-03-15 +*/ + +#ifndef __ARM_DYNCOM_DEC__ +#define __ARM_DYNCOM_DEC__ + +#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1)) +#define BIT(n) ((instr >> (n)) & 1) +#define BAD do{printf("meet BAD at %s, instr is %x\n", __FUNCTION__, instr ); /*exit(0);*/}while(0); +#define ptr_N cpu->ptr_N +#define ptr_Z cpu->ptr_Z +#define ptr_C cpu->ptr_C +#define ptr_V cpu->ptr_V +#define ptr_I cpu->ptr_I +#define ptr_T cpu->ptr_T +#define ptr_CPSR cpu->ptr_gpr[16] + +/* for MUL instructions */ +/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */ +#define RDHi ((instr >> 16) & 0xF) +/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */ +#define RDLo ((instr >> 12) & 0xF) +/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */ +#define MUL_RD ((instr >> 16) & 0xF) +/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */ +#define MUL_RN ((instr >> 12) & 0xF) +/*xxxx xxxx xxxx xxxx xxxx 1111 xxxx xxxx */ +#define RS ((instr >> 8) & 0xF) + +/*xxxx xxxx xxxx xxxx 1111 xxxx xxxx xxxx */ +#define RD ((instr >> 12) & 0xF) +/*xxxx xxxx xxxx 1111 xxxx xxxx xxxx xxxx */ +#define RN ((instr >> 16) & 0xF) +/*xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 */ +#define RM (instr & 0xF) +#define BIT(n) ((instr >> (n)) & 1) +#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1)) + +/* CP15 registers */ +#define OPCODE_1 BITS(21, 23) +#define CRn BITS(16, 19) +#define CRm BITS(0, 3) +#define OPCODE_2 BITS(5, 7) + +/*xxxx xx1x xxxx xxxx xxxx xxxx xxxx xxxx */ +#define I BIT(25) +/*xxxx xxxx xxx1 xxxx xxxx xxxx xxxx xxxx */ +#define S BIT(20) + +#define SHIFT BITS(5,6) +#define SHIFT_IMM BITS(7,11) +#define IMMH BITS(8,11) +#define IMML BITS(0,3) + +#define LSPBIT BIT(24) +#define LSUBIT BIT(23) +#define LSBBIT BIT(22) +#define LSWBIT BIT(21) +#define LSLBIT BIT(20) +#define LSSHBITS BITS(5,6) +#define OFFSET12 BITS(0,11) +#define SBIT BIT(20) +#define DESTReg (BITS (12, 15)) + +/* they are in unused state, give a corrent value when using */ +#define IS_V5E 0 +#define IS_V5 0 +#define IS_V6 0 +#define LHSReg 0 + +/* temp define the using the pc reg need implement a flow */ +#define STORE_CHECK_RD_PC ADD(R(RD), CONST(INSTR_SIZE * 2)) + +#define OPERAND operand(cpu,instr,bb,NULL) +#define SCO_OPERAND(sco) operand(cpu,instr,bb,sco) +#define BOPERAND boperand(instr) + +#define CHECK_RN_PC (RN==15? ADD(AND(R(RN), CONST(~0x1)), CONST(INSTR_SIZE * 2)):R(RN)) +#define CHECK_RN_PC_WA (RN==15? ADD(AND(R(RN), CONST(~0x3)), CONST(INSTR_SIZE * 2)):R(RN)) + +#define GET_USER_MODE() (OR(ICMP_EQ(R(MODE_REG), CONST(USER32MODE)), ICMP_EQ(R(MODE_REG), CONST(SYSTEM32MODE)))) + +int decode_arm_instr(uint32_t instr, int32_t *idx); + +enum DECODE_STATUS { + DECODE_SUCCESS, + DECODE_FAILURE +}; + +struct instruction_set_encoding_item { + const char *name; + int attribute_value; + int version; + u32 content[21]; +}; + +typedef struct instruction_set_encoding_item ISEITEM; + +#define RECORD_WB(value, flag) {cpu->dyncom_engine->wb_value = value;cpu->dyncom_engine->wb_flag = flag;} +#define INIT_WB(wb_value, wb_flag) RECORD_WB(wb_value, wb_flag) + +#define EXECUTE_WB(base_reg) {if(cpu->dyncom_engine->wb_flag) \ + LET(base_reg, cpu->dyncom_engine->wb_value);} +inline int get_reg_count(uint32_t instr){ + int i = BITS(0,15); + int count = 0; + while(i){ + if(i & 1) + count ++; + i = i >> 1; + } + return count; +} + +enum ARMVER { + INVALID = 0, + ARMALL, + ARMV4, + ARMV4T, + ARMV5T, + ARMV5TE, + ARMV5TEJ, + ARMV6, + ARM1176JZF_S, + ARMVFP2, + ARMVFP3 +}; + +//extern const INSTRACT arm_instruction_action[]; +extern const ISEITEM arm_instruction[]; + +#endif diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp new file mode 100644 index 000000000..8739b8c14 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -0,0 +1,6559 @@ +/* Copyright (C) +* 2012 - 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_interpreter.cpp +* @brief The fast interpreter for arm +* @author Michael.Kang blackfin.kang@gmail.com +* @version 7849 +* @date 2012-03-15 +*/ + +#define CITRA_IGNORE_EXIT(x) + +#include <algorithm> +#include <map> +#include <stdio.h> +#include <assert.h> +#include <cstdio> +#include <vector> + +using namespace std; + +#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/armmmu.h" +#include "arm_dyncom_thumb.h" +#include "arm_dyncom_run.h" +#include "core/arm/skyeye_common/vfp/vfp.h" +/* shenoubang 2012-6-14 */ +#ifdef __WIN32__ +#include "bank_defs.h" +#endif + +#include "core/mem_map.h" +#include "core/hle/hle.h" + +enum { + 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) +}; + +#define USER_MODE_OPT 1 +#define HYBRID_MODE 0 // Enable for JIT mode + +#define THRESHOLD 1000 +#define DURATION 500 +//#define PRINT_PROFILE_INFO + +#define CHECK_RS if(RS == 15) rs += 8 +#define CHECK_RM if(RM == 15) rm += 8 + +//#define BITS(s, a, b) (((s) >> (a)) & ((1 << (1 + (b) - (a))) - 1)) +#undef BITS +#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 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) + +//#define rotr(x,n) ((((x)>>(n))&((1<<(sizeof(x) * 8)-1))|(x<<(sizeof(x)*8-n)))) +//#define rotl(x,n) ((((x)<<(n))&(-(1<<(n))))|(((x)>>(sizeof(x)*8-n))&((1<<(n))-1))) +#define rotr(x,n) ( (x >> n) | ((x & ((1 << (n + 1)) - 1)) << (32 - n)) ) + +extern void switch_mode(arm_core_t *core, uint32_t mode); +//extern bool InAPrivilegedMode(arm_core_t *core); + +typedef arm_core_t arm_processor; +typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper); + +/* exclusive memory access */ +static int exclusive_detect(ARMul_State* state, ARMword addr){ + int i; + #if 0 + for(i = 0; i < 128; i++){ + if(state->exclusive_tag_array[i] == addr) + return 0; + } + #endif + if(state->exclusive_tag == addr) + return 0; + else + return -1; +} + +static void add_exclusive_addr(ARMul_State* state, ARMword addr){ + int i; + #if 0 + for(i = 0; i < 128; i++){ + if(state->exclusive_tag_array[i] == 0xffffffff){ + state->exclusive_tag_array[i] = addr; + //DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr); + return; + } + } + DEBUG_LOG(ARM11, "In %s ,can not monitor the addr, out of array\n", __FUNCTION__); + #endif + state->exclusive_tag = addr; + return; +} + +static void remove_exclusive(ARMul_State* state, ARMword addr){ + #if 0 + int i; + for(i = 0; i < 128; i++){ + if(state->exclusive_tag_array[i] == addr){ + state->exclusive_tag_array[i] = 0xffffffff; + //DEBUG_LOG(ARM11, "In %s, remove addr 0x%x\n", __func__, addr); + return; + } + } + #endif + state->exclusive_tag = 0xFFFFFFFF; +} + + +unsigned int DPO(Immediate)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + unsigned int immed_8 = BITS(sht_oper, 0, 7); + unsigned int rotate_imm = BITS(sht_oper, 8, 11); +// DEBUG_LOG(ARM11, "immed_8 is %x\n", immed_8); +// DEBUG_LOG(ARM11, "rotate_imm is %x\n", rotate_imm); + unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2);//ROTATE_RIGHT_32(immed_8, rotate_imm * 2); +// DEBUG_LOG(ARM11, "shifter_operand : %x\n", shifter_operand); + /* set c flag */ + if (rotate_imm == 0) + cpu->shifter_carry_out = cpu->CFlag; + else + cpu->shifter_carry_out = BIT(shifter_operand, 31); + return shifter_operand; +} + +unsigned int DPO(Register)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + unsigned int rm = CHECK_READ_REG15(cpu, RM); + //if (RM == 15) rm += 8; + unsigned int shifter_operand = rm; + cpu->shifter_carry_out = cpu->CFlag; + return shifter_operand; +} + +unsigned int DPO(LogicalShiftLeftByImmediate)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + int shift_imm = BITS(sht_oper, 7, 11); + unsigned int rm = CHECK_READ_REG15(cpu, RM); + //if (RM == 15) rm += 8; + 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; +} + +unsigned int DPO(LogicalShiftLeftByRegister)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + int shifter_operand; + unsigned int rm = CHECK_READ_REG15(cpu, RM); + unsigned int rs = CHECK_READ_REG15(cpu, RS); + //if (RM == 15) rm += 8; + //if (RS == 15) rs += 8; + 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; +} + +unsigned int DPO(LogicalShiftRightByImmediate)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + //unsigned int rm = cpu->Reg[RM]; + unsigned int rm = CHECK_READ_REG15(cpu, RM); + //if (RM == 15) rm += 8; + 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; +} + +unsigned int DPO(LogicalShiftRightByRegister)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + unsigned int rs = CHECK_READ_REG15(cpu, RS); + unsigned int rm = CHECK_READ_REG15(cpu, RM); + //if (RS == 15) rs += 8; + //if (RM == 15) rm += 8; + 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; +} + +unsigned int DPO(ArithmeticShiftRightByImmediate)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + //unsigned int rm = cpu->Reg[RM]; + unsigned int rm = CHECK_READ_REG15(cpu, RM); + //if (RM == 15) rm += 8; + unsigned int shifter_operand; + int shift_imm = BITS(sht_oper, 7, 11); + if (shift_imm == 0) { + if (BIT(rm, 31)) { + shifter_operand = 0; + cpu->shifter_carry_out = BIT(rm, 31); + } else { + shifter_operand = 0xFFFFFFFF; + cpu->shifter_carry_out = BIT(rm, 31); + } + } else { + shifter_operand = static_cast<int>(rm) >> shift_imm; + cpu->shifter_carry_out = BIT(rm, shift_imm - 1); + } + return shifter_operand; +} + +unsigned int DPO(ArithmeticShiftRightByRegister)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + //unsigned int rs = cpu->Reg[RS]; + unsigned int rs = CHECK_READ_REG15(cpu, RS); + //unsigned int rm = cpu->Reg[RM]; + unsigned int rm = CHECK_READ_REG15(cpu, RM); + //if (RS == 15) rs += 8; + //if (RM == 15) rm += 8; + 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<int>(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; +} + +unsigned int DPO(RotateRightByImmediate)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + unsigned int shifter_operand; + //unsigned int rm = cpu->Reg[RM]; + unsigned int rm = CHECK_READ_REG15(cpu, RM); + //if (RM == 15) rm += 8; + 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; +} + +unsigned int DPO(RotateRightByRegister)(arm_processor *cpu, unsigned int sht_oper) +{ +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + unsigned int rm = CHECK_READ_REG15(cpu, RM); + //if (RM == 15) rm += 8; + unsigned int rs = CHECK_READ_REG15(cpu, RS); + //if (RS == 15) rs += 8; + 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); + } + #if 0 + if (cpu->icounter >= 20371544) { + DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + DEBUG_LOG(ARM11, "RM:%d\nRS:%d\n", RM, RS); + DEBUG_LOG(ARM11, "rm:0x%08x\nrs:0x%08x\n", cpu->Reg[RM], cpu->Reg[RS]); + } + #endif + return shifter_operand; +} + +//typedef unsigned int (*get_addr_fp_t)(arm_processor *cpu); +typedef struct _MiscImmeData { + unsigned int U; + unsigned int Rn; + unsigned int offset_8; +} MiscLSData; + +typedef struct _MiscRegData { + unsigned int U; + unsigned int Rn; + unsigned int Rm; +} MiscRegData; + +typedef struct _MiscImmePreIdx { + unsigned int offset_8; + unsigned int U; + unsigned int Rn; +} MiscImmePreIdx; + +typedef struct _MiscRegPreIdx { + unsigned int U; + unsigned int Rn; + unsigned int Rm; +} MiscRegPreIdx; + +typedef struct _MiscImmePstIdx { + unsigned int offset_8; + unsigned int U; + unsigned int Rn; +} MIscImmePstIdx; + +typedef struct _MiscRegPstIdx { + unsigned int Rn; + unsigned int Rm; + unsigned int U; +} MiscRegPstIdx; + +typedef struct _LSWordorUnsignedByte { +} LDnST; + +#if USER_MODE_OPT +static inline fault_t interpreter_read_memory(addr_t virt_addr, addr_t phys_addr, uint32_t &value, uint32_t size){ + switch(size) { + case 8: + value = Memory::Read8(virt_addr); + break; + case 16: + value = Memory::Read16(virt_addr); + break; + case 32: + value = Memory::Read32(virt_addr); + break; + } + return NO_FAULT; +} + +//static inline void interpreter_write_memory(void *mem_ptr, uint32_t offset, uint32_t value, int size) +static inline fault_t interpreter_write_memory(addr_t virt_addr, addr_t phys_addr, uint32_t value, uint32_t size) +{ + switch(size) { + case 8: + Memory::Write8(virt_addr, value & 0xff); + break; + case 16: + Memory::Write16(virt_addr, value & 0xffff); + break; + case 32: + Memory::Write32(virt_addr, value); + break; + } + return NO_FAULT; +} + +static inline fault_t check_address_validity(arm_core_t *core, addr_t virt_addr, addr_t *phys_addr, uint32_t rw){ + *phys_addr = virt_addr; + return NO_FAULT; +} + +#else +fault_t interpreter_read_memory(cpu_t *cpu, addr_t virt_addr, addr_t phys_addr, uint32_t &value, uint32_t size); +fault_t interpreter_write_memory(cpu_t *cpu, addr_t virt_addr, addr_t phys_addr, uint32_t value, uint32_t size); +fault_t interpreter_fetch(cpu_t *cpu, addr_t virt_addr, uint32_t &value, uint32_t size); +fault_t check_address_validity(arm_core_t *core, addr_t virt_addr, addr_t *phys_addr, uint32_t rw, tlb_type_t access_type = DATA_TLB); +#endif + +typedef fault_t (*get_addr_fp_t)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw); + +typedef struct _ldst_inst { + unsigned int inst; + get_addr_fp_t get_addr; +} ldst_inst; +#define DEBUG_MSG DEBUG_LOG(ARM11, "in %s %d\n", __FUNCTION__, __LINE__); \ + DEBUG_LOG(ARM11, "inst is %x\n", inst); \ + CITRA_IGNORE_EXIT(0) + +int CondPassed(arm_processor *cpu, unsigned int cond); +#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) +fault_t LnSWoUB(ImmediateOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + unsigned int Rn = BITS(inst, 16, 19); + unsigned int addr; + fault_t fault; + if (U_BIT) { + addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12; + } else { + addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12; + } + //if (Rn == 15) rn += 8; + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + return fault; +// return addr; +} + +fault_t LnSWoUB(RegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + unsigned int Rn = BITS(inst, 16, 19); + unsigned int Rm = BITS(inst, 0, 3); + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + //if (Rn == 15) rn += 8; + unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); + //if (Rm == 15) rm += 8; + unsigned int addr; + if (U_BIT) { + addr = rn + rm; + } else { + addr = rn - rm; + } + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + return fault; +} + +fault_t LnSWoUB(ImmediatePostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + unsigned int Rn = BITS(inst, 16, 19); + unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); + //if (Rn == 15) addr += 8; + + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if (fault) return fault; + + if (U_BIT) { + cpu->Reg[Rn] += OFFSET_12; + } else { + cpu->Reg[Rn] -= OFFSET_12; + } + return fault; +} + +fault_t LnSWoUB(ImmediatePreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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; + } + #if 0 + if (Rn == 15) { + addr += 8; + } + #endif + + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if (fault) return fault; + + if (CondPassed(cpu, BITS(inst, 28, 31))) { + cpu->Reg[Rn] = addr; + } + return fault; +} + +fault_t MLnS(RegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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 (Rn == 15) rn += 8; + //if (Rm == 15) rm += 8; + if (U_BIT) { + addr = rn + rm; + } else + addr = rn - rm; + if(BIT(inst, 20)){ /* L BIT */ + } + if(BIT(inst, 6)){ /* Sign Bit */ + } + if(BIT(inst, 5)){ /* Half Bit */ + } + + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if (fault) return fault; + + if (CondPassed(cpu, BITS(inst, 28, 31))) { + cpu->Reg[Rn] = addr; + } + return fault; +} + +fault_t LnSWoUB(RegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + unsigned int Rn = BITS(inst, 16, 19); + unsigned int Rm = BITS(inst, 0, 3); + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + //if (Rn == 15) rn += 8; + unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); + //if (Rm == 15) rm += 8; + unsigned int addr; + if (U_BIT) { + addr = rn + rm; + } else { + addr = rn - rm; + } + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if(fault) + return fault; + if (CondPassed(cpu, BITS(inst, 28, 31))) { + cpu->Reg[Rn] = addr; + } + return fault; +} +fault_t LnSWoUB(ScaledRegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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; + unsigned int addr; + + unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); + //if (Rm == 15) rm += 8; + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + //if (Rn == 15) rn += 8; + switch (shift) { + case 0: + //DEBUG_MSG; + index = rm << shift_imm; + break; + case 1: +// DEBUG_MSG; + if (shift_imm == 0) { + index = 0; + } else { + index = rm >> shift_imm; + } + break; + case 2: + DEBUG_MSG; + break; + case 3: + DEBUG_MSG; + break; + } + if (U_BIT) { + addr = rn + index; + } else + addr = rn - index; + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if(fault) + return fault; + if (CondPassed(cpu, BITS(inst, 28, 31))) { + cpu->Reg[Rn] = addr; + } + + return fault; +} + +fault_t LnSWoUB(ScaledRegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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; + unsigned int addr; + + unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); + //if (Rm == 15) rm += 8; + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + //if (Rn == 15) rn += 8; + addr = rn; + switch (shift) { + case 0: + //DEBUG_MSG; + index = rm << shift_imm; + break; + case 1: +// DEBUG_MSG; + if (shift_imm == 0) { + index = 0; + } else { + index = rm >> shift_imm; + } + break; + case 2: + DEBUG_MSG; + break; + case 3: + DEBUG_MSG; + break; + } + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if(fault) + return fault; + if (CondPassed(cpu, BITS(inst, 28, 31))) { + if (U_BIT) + cpu->Reg[Rn] += index; + else + cpu->Reg[Rn] -= index; + } + + return fault; +} + +fault_t LnSWoUB(RegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + unsigned int Rn = BITS(inst, 16, 19); + unsigned int Rm = BITS(inst, 0, 3); + unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + + unsigned int addr = rn; + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if (fault) return fault; + + if (CondPassed(cpu, BITS(inst, 28, 31))) { + if (U_BIT) { + cpu->Reg[Rn] += rm; + } else { + cpu->Reg[Rn] -= rm; + } + } + return fault; +} + +fault_t MLnS(ImmediateOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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; + #if 0 + if (Rn == 15) { + addr += 8; + } + #endif + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + return fault; +} + +fault_t MLnS(RegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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 (Rn == 15) rn += 8; + //if (Rm == 15) rm += 8; + if (U_BIT) { + addr = rn + rm; + } else + addr = rn - rm; + if(BIT(inst, 20)){ /* L BIT */ + } + if(BIT(inst, 6)){ /* Sign Bit */ + } + if(BIT(inst, 5)){ /* Half Bit */ + } + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + return fault; +} + +fault_t MLnS(ImmediatePreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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); + //if (Rn == 15) rn += 8; + +// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); + unsigned int offset_8 = (immedH << 4) | immedL; + if (U_BIT) { + addr = rn + offset_8; + } else + addr = rn - offset_8; + + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if (fault) return fault; + + if (CondPassed(cpu, BITS(inst, 28, 31))) { + cpu->Reg[Rn] = addr; + } + return fault; +} + +fault_t MLnS(ImmediatePostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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); + addr = rn; + + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if (fault) return fault; + + 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; + } + + return fault; +} +fault_t MLnS(RegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + unsigned int Rn = BITS(inst, 16, 19); + unsigned int Rm = BITS(inst, 0, 3); + unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + + unsigned int addr = rn; + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + if (fault) return fault; + + if (CondPassed(cpu, BITS(inst, 28, 31))) { + if (U_BIT) { + cpu->Reg[Rn] += rm; + } else { + cpu->Reg[Rn] -= rm; + } + } + return fault; +} + +fault_t LdnStM(DecrementBefore)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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); + //if (Rn == 15) rn += 8; + unsigned int start_addr = rn - count * 4; + unsigned int end_addr = rn - 4; + + fault = check_address_validity(cpu, end_addr, &phys_addr, rw); + virt_addr = end_addr; + if (fault) return fault; + + fault = check_address_validity(cpu, start_addr, &phys_addr, rw); + virt_addr = start_addr; + if (fault) return fault; + + if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) { + cpu->Reg[Rn] -= count * 4; + } + + return fault; +} + +fault_t LdnStM(IncrementBefore)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + unsigned int Rn = BITS(inst, 16, 19); + unsigned int i = BITS(inst, 0, 15); + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + //if (Rn == 15) rn += 8; + int count = 0; + while(i) { + if(i & 1) count ++; + i = i >> 1; + } + + unsigned int start_addr = rn + 4; + unsigned int end_addr = rn + count * 4; + + fault = check_address_validity(cpu, end_addr, &phys_addr, rw); + virt_addr = end_addr; + if (fault) return fault; + + fault = check_address_validity(cpu, start_addr, &phys_addr, rw); + virt_addr = start_addr; + if (fault) return fault; + + if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) { + cpu->Reg[Rn] += count * 4; + } + return fault; +} + +fault_t LdnStM(IncrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + unsigned int Rn = BITS(inst, 16, 19); + unsigned int i = BITS(inst, 0, 15); + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + int count = 0; + while(i) { + if(i & 1) count ++; + i = i >> 1; + } + //if (Rn == 15) rn += 8; + unsigned int start_addr = rn; + unsigned int end_addr = rn + count * 4 - 4; + + fault = check_address_validity(cpu, end_addr, &phys_addr, rw); + virt_addr = end_addr; + if (fault) return fault; + + fault = check_address_validity(cpu, start_addr, &phys_addr, rw); + virt_addr = start_addr; + if (fault) return fault; + + if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) { + cpu->Reg[Rn] += count * 4; + } + return fault; +} + +fault_t LdnStM(DecrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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); + //if (Rn == 15) rn += 8; + unsigned int start_addr = rn - count * 4 + 4; + unsigned int end_addr = rn; + + fault = check_address_validity(cpu, end_addr, &phys_addr, rw); + virt_addr = end_addr; + if (fault) return fault; + + fault = check_address_validity(cpu, start_addr, &phys_addr, rw); + if (fault) return fault; + virt_addr = start_addr; + + if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) { + cpu->Reg[Rn] -= count * 4; + } + return fault; +} + +fault_t LnSWoUB(ScaledRegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) +{ + fault_t fault; + 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; + unsigned int addr; + + unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); + //if (Rm == 15) rm += 8; + unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); + //if (Rn == 15) rn += 8; + switch (shift) { + case 0: + //DEBUG_MSG; + index = rm << shift_imm; + break; + case 1: +// DEBUG_MSG; + if (shift_imm == 0) { + index = 0; + } else { + index = rm >> shift_imm; + } + break; + case 2: + if (shift_imm == 0){ /* ASR #32 */ + if (rm >> 31) + index = 0xFFFFFFFF; + else + index = 0; + } + else { + index = static_cast<int>(rm) >> shift_imm; + } + break; + case 3: + DEBUG_MSG; + break; + } + if (U_BIT) { + addr = rn + index; + } else + addr = rn - index; + virt_addr = addr; + fault = check_address_validity(cpu, addr, &phys_addr, rw); + return fault; +} + +#define ISNEG(n) (n < 0) +#define ISPOS(n) (n >= 0) + +//enum { +// 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) +//}; + +typedef struct _arm_inst { + unsigned int idx; + unsigned int cond; + int br; + int load_r15; + char component[0]; +} arm_inst; + +typedef struct _adc_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} adc_inst; + +typedef struct _add_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} add_inst; + +typedef struct _orr_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} orr_inst; + +typedef struct _and_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} and_inst; + +typedef struct _eor_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} eor_inst; + +typedef struct _bbl_inst { + unsigned int L; + int signed_immed_24; + unsigned int next_addr; + unsigned int jmp_addr; +} bbl_inst; + +typedef struct _bx_inst { + unsigned int Rm; +} bx_inst; + +typedef struct _blx_inst { + union { + int32_t signed_immed_24; + uint32_t Rm; + } val; + unsigned int inst; +} blx_inst; + +typedef struct _clz_inst { + unsigned int Rm; + unsigned int Rd; +} clz_inst; + +typedef struct _cps_inst { + unsigned int imod0; + unsigned int imod1; + unsigned int mmod; + unsigned int A, I, F; + unsigned int mode; +} cps_inst; + +typedef struct _clrex_inst { +} clrex_inst; + +typedef struct _cpy_inst { + unsigned int Rm; + unsigned int Rd; +} cpy_inst; + +typedef struct _bic_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} bic_inst; + +typedef struct _sub_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} sub_inst; + +typedef struct _tst_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} tst_inst; + +typedef struct _cmn_inst { + unsigned int I; + //unsigned int S; + unsigned int Rn; + //unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} cmn_inst; + +typedef struct _teq_inst { + unsigned int I; + unsigned int Rn; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} teq_inst; + +typedef struct _stm_inst { + unsigned int inst; +} stm_inst; + +struct bkpt_inst { +}; + +struct blx1_inst { + unsigned int addr; +}; + +struct blx2_inst { + unsigned int Rm; +}; + +typedef struct _stc_inst { +} stc_inst; + +typedef struct _ldc_inst { +} ldc_inst; + +typedef struct _swi_inst { + unsigned int num; +} swi_inst; + +typedef struct _cmp_inst { + unsigned int I; + unsigned int Rn; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} cmp_inst; + +typedef struct _mov_inst { + unsigned int I; + unsigned int S; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} mov_inst; + +typedef struct _mvn_inst { + unsigned int I; + unsigned int S; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} mvn_inst; + +typedef struct _rev_inst { + unsigned int Rd; + unsigned int Rm; +} rev_inst; + +typedef struct _rsb_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} rsb_inst; + +typedef struct _rsc_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} rsc_inst; + +typedef struct _sbc_inst { + unsigned int I; + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int shifter_operand; + shtop_fp_t shtop_func; +} sbc_inst; + +typedef struct _mul_inst { + unsigned int S; + unsigned int Rd; + unsigned int Rs; + unsigned int Rm; +} mul_inst; + +typedef struct _smul_inst { + unsigned int Rd; + unsigned int Rs; + unsigned int Rm; + unsigned int x; + unsigned int y; +} smul_inst; + +typedef struct _umull_inst { + unsigned int S; + unsigned int RdHi; + unsigned int RdLo; + unsigned int Rs; + unsigned int Rm; +} umull_inst; +typedef struct _smlad_inst { + unsigned int m; + unsigned int Rm; + unsigned int Rd; + unsigned int Ra; + unsigned int Rn; +} smlad_inst; + +typedef struct _smla_inst { + unsigned int x; + unsigned int y; + unsigned int Rm; + unsigned int Rd; + unsigned int Rs; + unsigned int Rn; +} smla_inst; + +typedef struct _umlal_inst { + unsigned int S; + unsigned int Rm; + unsigned int Rs; + unsigned int RdHi; + unsigned int RdLo; +} umlal_inst; + +typedef struct _smlal_inst { + unsigned int S; + unsigned int Rm; + unsigned int Rs; + unsigned int RdHi; + unsigned int RdLo; +} smlal_inst; + +typedef struct _mla_inst { + unsigned int S; + unsigned int Rn; + unsigned int Rd; + unsigned int Rs; + unsigned int Rm; +} mla_inst; + +typedef 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; +} mrc_inst; + +typedef 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; +} mcr_inst; + +typedef struct _mrs_inst { + unsigned int R; + unsigned int Rd; +} mrs_inst; + +typedef struct _msr_inst { + unsigned int field_mask; + unsigned int R; + unsigned int inst; +} msr_inst; + +typedef struct _pld_inst { +} pld_inst; + +typedef struct _sxtb_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int rotate; +} sxtb_inst; + +typedef struct _sxtab_inst { + unsigned int Rd; + unsigned int Rn; + unsigned int Rm; + unsigned rotate; +} sxtab_inst; + +typedef struct _sxtah_inst { + unsigned int Rd; + unsigned int Rn; + unsigned int Rm; + unsigned int rotate; +} sxtah_inst; + +typedef struct _sxth_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int rotate; +} sxth_inst; + +typedef struct _uxtab_inst { + unsigned int Rn; + unsigned int Rd; + unsigned int rotate; + unsigned int Rm; +} uxtab_inst; + +typedef struct _uxtah_inst { + unsigned int Rn; + unsigned int Rd; + unsigned int rotate; + unsigned int Rm; +} uxtah_inst; + +typedef struct _uxth_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int rotate; +} uxth_inst; + +typedef struct _cdp_inst { + unsigned int opcode_1; + unsigned int CRn; + unsigned int CRd; + unsigned int cp_num; + unsigned int opcode_2; + unsigned int CRm; + uint32 inst; +}cdp_inst; + +typedef struct _uxtb_inst { + unsigned int Rd; + unsigned int Rm; + unsigned int rotate; +} uxtb_inst; + +typedef struct _swp_inst { + unsigned int Rn; + unsigned int Rd; + unsigned int Rm; +} swp_inst; + +typedef struct _b_2_thumb { + unsigned int imm; +}b_2_thumb; +typedef struct _b_cond_thumb { + unsigned int imm; + unsigned int cond; +}b_cond_thumb; + +typedef struct _bl_1_thumb { + unsigned int imm; +}bl_1_thumb; +typedef struct _bl_2_thumb { + unsigned int imm; +}bl_2_thumb; +typedef struct _blx_1_thumb { + unsigned int imm; + unsigned int instr; +}blx_1_thumb; + +typedef arm_inst * ARM_INST_PTR; + +#define CACHE_BUFFER_SIZE (64 * 1024 * 2000) +char inst_buf[CACHE_BUFFER_SIZE]; +int top = 0; +inline void *AllocBuffer(unsigned int size) +{ + int start = top; + top += size; + if (top > CACHE_BUFFER_SIZE) { + DEBUG_LOG(ARM11, "inst_buf is full\n"); + CITRA_IGNORE_EXIT(-1); + } + return (void *)&inst_buf[start]; +} + +int CondPassed(arm_processor *cpu, unsigned int cond) +{ + #define NFLAG cpu->NFlag + #define ZFLAG cpu->ZFlag + #define CFLAG cpu->CFlag + #define VFLAG cpu->VFlag + int temp; + switch (cond) { + case 0x0: + temp = ZFLAG; + break; + case 0x1: /* NE */ + temp = !ZFLAG; + break; + case 0x6: /* VS */ + temp = VFLAG; + break; + case 0x7: /* VC */ + temp = !VFLAG; + break; + case 0x4: /* MI */ + temp = NFLAG; + break; + case 0x5: /* PL */ + temp = !NFLAG; + break; + case 0x2: /* CS */ + temp = CFLAG; + break; + case 0x3: /* CC */ + temp = !CFLAG; + break; + case 0x8: /* HI */ + temp = (CFLAG && !ZFLAG); + break; + case 0x9: /* LS */ + temp = (!CFLAG || ZFLAG); + break; + case 0xa: /* GE */ + temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG)); + break; + case 0xb: /* LT */ + temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)); + break; + case 0xc: /* GT */ + temp = ((!NFLAG && !VFLAG && !ZFLAG) + || (NFLAG && VFLAG && !ZFLAG)); + break; + case 0xd: /* LE */ + temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) + || ZFLAG; + break; + case 0xe: /* AL */ + temp = 1; + break; + case 0xf: +// DEBUG_LOG(ARM11, "inst is %x\n"); +// DEBUG_LOG(ARM11, "icounter is %lld\n", cpu->icounter); +// CITRA_IGNORE_EXIT(-1); + temp = 1; + break; + } + return temp; +} + +enum DECODE_STATUS { + DECODE_SUCCESS, + DECODE_FAILURE +}; + +int decode_arm_instr(uint32_t instr, int32_t *idx); + +shtop_fp_t get_shtop(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 NULL; +} + +get_addr_fp_t get_calc_addr_op(unsigned int inst) +{ + /* 1 */ + if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) { +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + return LnSWoUB(ImmediateOffset); + } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) { +// DEBUG_MSG; +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + return LnSWoUB(RegisterOffset); + } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { +// DEBUG_MSG; +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + return LnSWoUB(ScaledRegisterOffset); + } else if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 1) { +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + 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) { +// DEBUG_MSG; + return LnSWoUB(RegisterPostIndexed); + } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { + return LnSWoUB(ScaledRegisterPostIndexed); +// DEBUG_MSG; + } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { + /* 2 */ +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + return MLnS(ImmediateOffset); +// DEBUG_MSG; + } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { +// DEBUG_LOG(ARM11, "line is %d\n", __LINE__); + return MLnS(RegisterOffset); +// DEBUG_MSG; + } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { +// DEBUG_LOG(ARM11, "line is %d\n", __LINE__); + return MLnS(ImmediatePreIndexed); +// DEBUG_MSG; + } 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) { +// DEBUG_MSG; + return MLnS(ImmediatePostIndexed); + } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { + //DEBUG_MSG; + return MLnS(RegisterPostIndexed); + } else if (BITS(inst, 23, 27) == 0x11) { + /* 3 */ +// DEBUG_MSG; +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + return LdnStM(IncrementAfter); + } else if (BITS(inst, 23, 27) == 0x13) { +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + return LdnStM(IncrementBefore); +// DEBUG_MSG; + } else if (BITS(inst, 23, 27) == 0x10) { +// DEBUG_MSG; +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + return LdnStM(DecrementAfter); + } else if (BITS(inst, 23, 27) == 0x12) { +// DEBUG_MSG; +// DEBUG_LOG(ARM11, "line is %d", __LINE__); + return LdnStM(DecrementBefore); + } + #if 0 + DEBUG_LOG(ARM11, "In %s Unknown addressing mode\n", __FUNCTION__); + DEBUG_LOG(ARM11, "inst:%x\n", inst); + CITRA_IGNORE_EXIT(-1); + #endif + return NULL; +} + +#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) + +#define CHECK_RN (inst_cream->Rn == 15) +#define CHECK_RM (inst_cream->Rm == 15) +#define CHECK_RS (inst_cream->Rs == 15) + + +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + if (CHECK_RN) + inst_base->load_r15 = 1; + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = get_shtop(inst); + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + if (CHECK_RN) + inst_base->load_r15 = 1; + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = get_shtop(inst); + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + if (CHECK_RN) + inst_base->load_r15 = 1; + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = get_shtop(inst); + if (inst_cream->Rd == 15) + inst_base->br = INDIRECT_BRANCH; + return inst_base; +} +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 = DIRECT_BRANCH; + + if (BIT(inst, 24)) + inst_base->br = CALL; + if (BITS(inst, 28, 31) <= 0xe) + inst_base->br |= COND; + + inst_cream->L = BIT(inst, 24); + inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; + + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + if (CHECK_RN) + inst_base->load_r15 = 1; + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = get_shtop(inst); + + if (inst_cream->Rd == 15) + inst_base->br = INDIRECT_BRANCH; + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = 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); + //DEBUG_LOG(ARM11, " blx inst is %x\n", inst); + //CITRA_IGNORE_EXIT(-1); +// DEBUG_MSG; + } + + return inst_base; +} +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 = INDIRECT_BRANCH; + + inst_cream->Rm = BITS(inst, 0, 3); + + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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; + + DEBUG_LOG(ARM11, "in func %s inst %x index %x\n", __FUNCTION__, inst, index); + return inst_base; +} +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 = NON_BRANCH; + + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 12, 15); + if (CHECK_RM) + inst_base->load_r15 = 1; + + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + if (CHECK_RN) + inst_base->load_r15 = 1; + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = get_shtop(inst); + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->I = BIT(inst, 25); + inst_cream->Rn = BITS(inst, 16, 19); + if (CHECK_RN) + inst_base->load_r15 = 1; + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = get_shtop(inst); + return inst_base; +} +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 = 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; +} +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 = 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 = get_shtop(inst); + + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + if (CHECK_RN) + inst_base->load_r15 = 1; + inst_cream->shifter_operand = BITS(inst, 0, 11); + inst_cream->shtop_func = get_shtop(inst); + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BIT(inst, 15)) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->rotate = BITS(inst, 10, 11); + if (CHECK_RM) + inst_base->load_r15 = 1; + + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} + +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} + +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + inst_cream->Rm = BITS(inst, 0, 3); + if (CHECK_RM) + inst_base->load_r15 = 1; + + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + if (CHECK_RM || CHECK_RN) + inst_base->load_r15 = 1; + + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + if (I_BIT == 0) { + inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + } else { + DEBUG_MSG; + } + #if 0 + inst_cream->get_addr = get_calc_addr_op(inst); + if(inst == 0x54f13001) { + DEBUG_LOG(ARM11, "get_calc_addr_op:%llx\n", inst_cream->get_addr); + } + #endif + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + return inst_base; +} + +ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(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 = NON_BRANCH; + + inst_cream->inst = inst; + //inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + if (I_BIT == 0) { + inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + } else { + DEBUG_MSG; + } + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = 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; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + + if (CHECK_RM || CHECK_RN || CHECK_RS) + inst_base->load_r15 = 1; + + return inst_base; +} +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 = 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 = get_shtop(inst); + + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = 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; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->R = BIT(inst, 22); + + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->field_mask = BITS(inst, 16, 19); + inst_cream->R = BIT(inst, 22); + inst_cream->inst = inst; + + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + + if (CHECK_RM || CHECK_RS) + inst_base->load_r15 = 1; + return inst_base; +} +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 = 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 = get_shtop(inst); + + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; + +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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 = get_shtop(inst); + + if (CHECK_RN) + inst_base->load_r15 = 1; + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) +{ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); + rev_inst *inst_cream = (rev_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index){ + arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); + rev_inst *inst_cream = (rev_inst *)inst_base->component; + + inst_base->cond = BITS(inst, 28, 31); + inst_base->idx = index; + inst_base->br = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->Rd = BITS(inst, 12, 15); + + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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 = get_shtop(inst); + if (CHECK_RN) + inst_base->load_r15 = 1; + + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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 = get_shtop(inst); + if (CHECK_RN) + inst_base->load_r15 = 1; + + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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 = get_shtop(inst); + if (CHECK_RN) + inst_base->load_r15 = 1; + + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->m = BIT(inst, 4); + 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); + + if (CHECK_RM ) + inst_base->load_r15 = 1; + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + + if (CHECK_RM || CHECK_RS) + inst_base->load_r15 = 1; + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + + if (CHECK_RM || CHECK_RS) + inst_base->load_r15 = 1; + return inst_base; + +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + + if (CHECK_RM || CHECK_RS) + inst_base->load_r15 = 1; + return inst_base; +} + +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + + if (CHECK_RM || CHECK_RN) + inst_base->load_r15 = 1; + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + inst_cream->rotate = BITS(inst, 10, 11); + + if (CHECK_RM) + inst_base->load_r15 = 1; + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->rotate = BITS(inst, 10, 11); + inst_cream->Rm = BITS(inst, 0, 3); + + if (CHECK_RM) + inst_base->load_r15 = 1; + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; +// inst_cream->get_addr = get_calc_addr_op(inst); + if (I_BIT == 0) { + inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + } else { + DEBUG_MSG; + } + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op(inst); + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->inst = inst; + if (I_BIT == 0) { + inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + } else { + DEBUG_MSG; + } + + if (BITS(inst, 12, 15) == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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 = get_shtop(inst); + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + if (CHECK_RN) + inst_base->load_r15 = 1; + + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->num = BITS(inst, 0, 23); + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + + inst_cream->Rn = BITS(inst, 16, 19); + inst_cream->Rd = BITS(inst, 12, 15); + inst_cream->Rm = BITS(inst, 0, 3); + + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index){ + DEBUG_LOG(ARM11, "in func %s, SXTAH untested\n", __func__); + 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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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 = get_shtop(inst); + + if (CHECK_RN) + inst_base->load_r15 = 1; + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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 = get_shtop(inst); + if (inst_cream->Rd == 15) { + inst_base->br = INDIRECT_BRANCH; + } + + if (CHECK_RN) + inst_base->load_r15 = 1; + return inst_base; +} +ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + + if (CHECK_RM || CHECK_RS) + inst_base->load_r15 = 1; + return inst_base; +} +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 = NON_BRANCH; + inst_base->load_r15 = 0; + + 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); + + if (CHECK_RM || CHECK_RS) + inst_base->load_r15 = 1; + return inst_base; +} + +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); + //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm); + inst_base->idx = index; + inst_base->br = DIRECT_BRANCH; + return inst_base; +} + +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); + //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x, cond=0x%x\n", __FUNCTION__, tinst, inst_cream->imm, inst_cream->cond); + inst_base->idx = index; + inst_base->br = DIRECT_BRANCH; + return inst_base; +} + +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)); + //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm); + + inst_base->idx = index; + inst_base->br = NON_BRANCH; + return inst_base; +} +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; + //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm); + inst_base->idx = index; + inst_base->br = DIRECT_BRANCH; + return inst_base; +} +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; + //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm); + inst_cream->instr = tinst; + inst_base->idx = index; + inst_base->br = DIRECT_BRANCH; + return inst_base; +} + +ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} +ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index){DEBUG_LOG(ARM11, "in func %s\n", __FUNCTION__);CITRA_IGNORE_EXIT(-1); return nullptr;} + + + +/* Floating point VFPv3 structures and instructions */ + +#define VFP_INTERPRETER_STRUCT +#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" +#undef VFP_INTERPRETER_STRUCT + +#define VFP_INTERPRETER_TRANS +#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" +#undef VFP_INTERPRETER_TRANS + + + +typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int); + +const transop_fp_t arm_instruction_trans[] = { + #define VFP_INTERPRETER_TABLE + #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" + #undef VFP_INTERPRETER_TABLE + 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(ldrb), + INTERPRETER_TRANSLATE(strb), + INTERPRETER_TRANSLATE(ldr), + INTERPRETER_TRANSLATE(ldrcond), + INTERPRETER_TRANSLATE(str), + INTERPRETER_TRANSLATE(cdp), + INTERPRETER_TRANSLATE(stc), + INTERPRETER_TRANSLATE(ldc), + 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) +}; + +typedef map<unsigned int, int> bb_map; +bb_map CreamCache[65536]; +bb_map ProfileCache[65536]; + +//#define USE_DUMMY_CACHE + +#ifdef USE_DUMMY_CACHE +unsigned int DummyCache[0x100000]; +#endif + +#define HASH(x) ((x + (x << 3) + (x >> 6)) % 65536) +void insert_bb(unsigned int addr, int start) +{ +#ifdef USE_DUMMY_CACHE + DummyCache[addr] = start; +#else +// CreamCache[addr] = start; + CreamCache[HASH(addr)][addr] = start; +#endif +} + +#define TRANS_THRESHOLD 65000 +int find_bb(unsigned int addr, int &start) +{ + int ret = -1; +#ifdef USE_DUMMY_CACHE + start = DummyCache[addr]; + if (start) { + ret = 0; + } else + ret = -1; +#else + bb_map::const_iterator it = CreamCache[HASH(addr)].find(addr); + if (it != CreamCache[HASH(addr)].end()) { + start = static_cast<int>(it->second); + ret = 0; +#if HYBRID_MODE +#if PROFILE +#else + /* increase the bb counter */ + if(get_bb_prof(cpu, addr, 1) == TRANS_THRESHOLD){ + push_to_compiled(cpu, addr); + } +#endif +#endif + } else { + ret = -1; + } +#endif + return ret; +} + + +enum { + FETCH_SUCCESS, + FETCH_FAILURE +}; +static tdstate decode_thumb_instr(arm_processor *cpu, uint32_t inst, addr_t addr, uint32_t *arm_inst, uint32_t* inst_size, ARM_INST_PTR* ptr_inst_base){ + /* Check if in Thumb mode. */ + tdstate ret; + ret = thumb_translate (addr, inst, arm_inst, inst_size); + if(ret == t_branch){ + /* FIXME, endian should be judged */ + uint32 tinstr; + if((addr & 0x3) != 0) + tinstr = inst >> 16; + else + tinstr = inst & 0xFFFF; + + //tinstr = inst & 0xFFFF; + int inst_index; + /* table_length */ + int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); + + switch((tinstr & 0xF800) >> 11){ + /* we will translate the thumb instruction directly here */ + /* we will translate the thumb instruction directly here */ + case 26: + case 27: + if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ + uint32 cond = (tinstr & 0x0F00) >> 8; + inst_index = table_length - 4; + //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d\n", __FUNCTION__, tinstr, inst_index); + *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); + } + else{ + /* something wrong */ + DEBUG_LOG(ARM11, "In %s, thumb decoder error\n", __FUNCTION__); + } + break; + case 28: + /* Branch 2, unconditional branch */ + inst_index = table_length - 5; + //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d\n", __FUNCTION__, tinstr, inst_index); + *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; + //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d, pc=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc); + *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); + break; + case 30: + /* For BL 1 thumb instruction*/ + inst_index = table_length - 3; + //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, bl 1 thumb index=%d, pc=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc); + *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); + break; + case 31: + /* For BL 2 thumb instruction*/ + inst_index = table_length - 2; + //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, bl 2 thumb index=%d, px=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc); + *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); + break; + default: + ret = t_undefined; + break; + } + } + return ret; +} + +#if 0 +int FetchInst(cpu_t *core, unsigned int &inst) +{ + //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t"); + arm_processor *cpu = (arm_processor *)(core->cpu_data->obj); +// fault_t fault = interpreter_read_memory(cpu->translate_pc, inst, 32); + fault_t fault = interpreter_fetch(core, cpu->translate_pc, inst, 32); + if (!core->is_user_mode) { + if (fault) { + cpu->abortSig = true; + cpu->Aborted = ARMul_PrefetchAbortV; + cpu->AbortAddr = cpu->translate_pc; + cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff; + cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->translate_pc; + return FETCH_FAILURE; + } + } + return FETCH_SUCCESS; +} +#endif + +unsigned int *InstLength; + +enum { + KEEP_GOING, + FETCH_EXCEPTION +}; + +typedef struct instruction_set_encoding_item ISEITEM; + +extern const ISEITEM arm_instruction[]; + +vector<uint64_t> code_page_set; + +void flush_bb(uint32_t addr) +{ + bb_map::iterator it; + uint32_t start; + + addr &= 0xfffff000; + for (int i = 0; i < 65536; i ++) { + for (it = CreamCache[i].begin(); it != CreamCache[i].end(); ) { + start = static_cast<uint32_t>(it->first); + //start = (start >> 12) << 12; + start &= 0xfffff000; + if (start == addr) { + //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first)); + CreamCache[i].erase(it ++); + } else + ++it; + } + } + + for (int i = 0; i < 65536; i ++) { + for (it = ProfileCache[i].begin(); it != ProfileCache[i].end(); ) { + start = static_cast<uint32_t>(it->first); + //start = (start >> 12) << 12; + start &= 0xfffff000; + if (start == addr) { + //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first)); + ProfileCache[i].erase(it ++); + } else + ++it; + } + } + + //DEBUG_LOG(ARM11, "flush bb @ %x\n", addr); +} + +//static uint32_t get_bank_addr(void *addr) +//{ +// uint64_t address = (uint64_t)addr; +// uint64_t bank0 = get_dma_addr(BANK0_START); +// if ((address >= bank0) && (address < (bank0 + BANK0_SIZE))) { +// //DEBUG_LOG(ARM11, "1.addr is %llx\n", addr); +// return ((uint64_t)addr - bank0) + BANK0_START; +// } +// return 0; +//} + +/* shenoubang add win32 2012-6-12 */ +//#ifndef __WIN32__ +//static void flush_code_cache(int signal_number, siginfo_t *si, void *unused) +//{ +// DEBUG_LOG(ARM11, "in %s, addr=0x%llx\n", __FUNCTION__, si->si_addr); +// uint64_t addr = (uint64_t)si->si_addr; +// addr = (addr >> 12) << 12; +// skyeye_backtrace(); +// #if 0 +// if (addr == 0) { +// return; +// } +// const vector<uint64_t>::iterator it = find(code_page_set.begin(), +// code_page_set.end(), +// (uint64_t)addr); +// if (it != code_page_set.end()) { +// code_page_set.erase(it); +// } +// mprotect((void *)addr, 4096, PROT_READ | PROT_WRITE); +// //DEBUG_LOG(ARM11, "[flush][ADDR:0x%08llx]\n", addr); +// uint32_t phys_addr = get_bank_addr((void *)addr); +//// DEBUG_LOG(ARM11, "[PHYSICAL][ADDR:0x%08llx]\n", phys_addr); +// flush_bb(phys_addr); +// flush_bb(phys_addr + 4096); +//#if HYBRID_MODE +// /* flush the translated BB of dyncom */ +// clear_translated_cache(phys_addr); +//#endif +// #endif +//} +//#endif /* shenoubang */ + +//void protect_code_page(uint32_t addr) +//{ +// void *mem_ptr = (void *)get_dma_addr(addr); +// mem_ptr = (void *)((long long int)mem_ptr & 0xfffffffffffff000LL); +// +// const vector<uint64_t>::iterator it = find(code_page_set.begin(), +// code_page_set.end(), +// (uint64_t)mem_ptr); +// if (it != code_page_set.end()) { +// return; +// } +// //DEBUG_LOG(ARM11, "[mprotect][ADDR:0x%08llx]\n", mem_ptr); +// /* shenoubang add win32 2012-6-12 */ +//#ifndef __WIN32__ +// struct sigaction sa; +// +// memset(&sa, 0, sizeof(sa)); +// sa.sa_flags = SA_RESTART | SA_SIGINFO; +// sa.sa_sigaction = &flush_code_cache; +// sigaction(SIGSEGV, &sa, NULL); +// +// //mprotect(mem_ptr, 4096, PROT_READ); +// +// code_page_set.push_back((uint64_t)mem_ptr); +//#endif /* shenoubang */ +//} + + + +int InterpreterTranslate(arm_processor *cpu, int &bb_start, addr_t addr) +{ + /* Decode instruction, get index */ + /* Allocate memory and init InsCream */ + /* Go on next, until terminal instruction */ + /* Save start addr of basicblock in CreamCache */ + //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t"); + //arm_processor *cpu = (arm_processor *)(core->cpu_data->obj); + ARM_INST_PTR inst_base = NULL; + unsigned int inst, inst_size = 4; + int idx; + int ret = NON_BRANCH; + int thumb = 0; + /* instruction size of basic block */ + int size = 0; + /* (R15 - 8) ? */ + //cpu->translate_pc = cpu->Reg[15]; + bb_start = top; + + if (cpu->TFlag) + thumb = THUMB; + + addr_t phys_addr; + addr_t pc_start; + fault_t fault = NO_FAULT; + //fault = check_address_validity(cpu, addr, &phys_addr, 1, INSN_TLB); + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if(fault != NO_FAULT){ + cpu->abortSig = true; + cpu->Aborted = ARMul_PrefetchAbortV; + cpu->AbortAddr = addr; + cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff; + cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr; + return FETCH_EXCEPTION; + } + pc_start = phys_addr; + //phys_addr = get_dma_addr(phys_addr); + while(ret == NON_BRANCH) { + /* shenoubang add win32 2012-6-14 */ +#ifdef __WIN32__ + mem_bank_t* bank; + if (bank = bank_ptr(addr)) { + bank->bank_read(32, phys_addr, &inst); + } + else { + DEBUG_LOG(ARM11, "SKYEYE: Read physical addr 0x%x error!!\n", phys_addr); + return FETCH_FAILURE; + } +#else + inst = Memory::Read32(phys_addr & 0xFFFFFFFC);//*(uint32_t *)(phys_addr & 0xFFFFFFFC); +#endif + //or_tag(core, phys_addr, TAG_FAST_INTERP); + + /*if (ret == FETCH_FAILURE) { + return FETCH_EXCEPTION; + }*/ + + size ++; + /* If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction */ + if (cpu->TFlag){ + //if(cpu->Cpsr & (1 << THUMB_BIT)){ + uint32_t arm_inst; + tdstate state; + state = decode_thumb_instr(cpu, inst, phys_addr, &arm_inst, &inst_size, &inst_base); + //or_tag(core, phys_addr, TAG_THUMB); + //DEBUG_LOG(ARM11, "In thumb state, arm_inst=0x%x, inst_size=0x%x, pc=0x%x\n", arm_inst, inst_size, cpu->translate_pc); + /* we have translated the branch instruction of thumb in thumb decoder */ + if(state == t_branch){ + goto translated; + } + inst = arm_inst; + } + + ret = decode_arm_instr(inst, &idx); + if (ret == DECODE_FAILURE) { + DEBUG_LOG(ARM11, "[info] : Decode failure.\tPC : [0x%x]\tInstruction : [%x]\n", phys_addr, inst); + DEBUG_LOG(ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x\n", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); + CITRA_IGNORE_EXIT(-1); + } +// DEBUG_LOG(ARM11, "PC : [0x%x] INST : %s\n", cpu->translate_pc, arm_instruction[idx].name); + inst_base = arm_instruction_trans[idx](inst, idx); +// DEBUG_LOG(ARM11, "translated @ %x INST : %x\n", cpu->translate_pc, inst); +// DEBUG_LOG(ARM11, "inst size is %d\n", InstLength[idx]); +translated: + phys_addr += inst_size; + + if ((phys_addr & 0xfff) == 0) { + inst_base->br = END_OF_PAGE; + } + ret = inst_base->br; + }; + + //DEBUG_LOG(ARM11, "In %s,insert_bb pc=0x%x, TFlag=0x%x\n", __FUNCTION__, pc_start, cpu->TFlag); + insert_bb(pc_start, bb_start); + return KEEP_GOING; +} + +#define LOG_IN_CLR skyeye_printf_in_color + +int cmp(const void *x, const void *y) +{ + return *(unsigned long long int*)x - *(unsigned long long int *)y; +} + +void InterpreterInitInstLength(unsigned long long int *ptr, size_t size) +{ + int array_size = size / sizeof(void *); + unsigned long long int *InstLabel = new unsigned long long int[array_size]; + memcpy(InstLabel, ptr, size); + qsort(InstLabel, array_size, sizeof(void *), cmp); + InstLength = new unsigned int[array_size - 4]; + for (int i = 0; i < array_size - 4; i ++) { + for (int j = 0; j < array_size; j ++) { + if (ptr[i] == InstLabel[j]) { + InstLength[i] = InstLabel[j + 1] - InstLabel[j]; + break; + } + } + } + for (int i = 0; i < array_size - 4; i ++) + DEBUG_LOG(ARM11, "[%d]:%d\n", i, InstLength[i]); +} + +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; +} + +unsigned arm_dyncom_SWI (ARMul_State * state, ARMword number); + +static bool InAPrivilegedMode(arm_core_t *core) +{ + return (core->Mode != USER32MODE); +} + +/* r15 = r15 + 8 */ +void InterpreterMainLoop(ARMul_State* state) +{ + #define CRn inst_cream->crn + #define OPCODE_2 inst_cream->opcode_2 + #define CRm inst_cream->crm + #define CP15_REG(n) cpu->CP15[CP15(n)] + #define RD cpu->Reg[inst_cream->Rd] + #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) + + #if ENABLE_ICOUNTER + #define INC_ICOUNTER cpu->icounter++; \ + if(cpu->Reg[15] > 0xc0000000) \ + cpu->kernel_icounter++; + //if (debug_function(core)) \ + if (core->check_int_flag) \ + goto END + //DEBUG_LOG(ARM11, "icounter is %llx line is %d pc is %x\n", cpu->icounter, __LINE__, cpu->Reg[15]) + #else + #define INC_ICOUNTER ; + #endif + + #define FETCH_INST if (inst_base->br != NON_BRANCH) \ + goto PROFILING; \ + inst_base = (arm_inst *)&inst_buf[ptr] +#define INC_PC(l) ptr += sizeof(arm_inst) + l + +#ifdef __GNUC__ +#define GOTO_NEXT_INST goto *InstLabel[inst_base->idx] +#else +#define GOTO_NEXT_INST switch(inst_base->idx) { \ + case 0: goto VMLA_INST; \ + case 1: goto VMLS_INST; \ + case 2: goto VNMLA_INST; \ + case 3: goto VNMLA_INST; \ + case 4: goto VNMLS_INST; \ + case 5: goto VNMUL_INST; \ + case 6: goto VMUL_INST; \ + case 7: goto VADD_INST; \ + case 8: goto VSUB_INST; \ + case 9: goto VDIV_INST; \ + case 10: goto VMOVI_INST; \ + case 11: goto VMOVR_INST; \ + case 12: goto VABS_INST; \ + case 13: goto VNEG_INST; \ + case 14: goto VSQRT_INST; \ + case 15: goto VCMP_INST; \ + case 16: goto VCMP2_INST; \ + case 17: goto VCVTBDS_INST; \ + case 18: goto VCVTBFF_INST; \ + case 19: goto VCVTBFI_INST; \ + case 20: goto VMOVBRS_INST; \ + case 21: goto VMSR_INST; \ + case 22: goto VMOVBRC_INST; \ + case 23: goto VMRS_INST; \ + case 24: goto VMOVBCR_INST; \ + case 25: goto VMOVBRRSS_INST; \ + case 26: goto VMOVBRRD_INST; \ + case 27: goto VSTR_INST; \ + case 28: goto VPUSH_INST; \ + case 29: goto VSTM_INST; \ + case 30: goto VPOP_INST; \ + case 31: goto VLDR_INST; \ + case 32: goto VLDM_INST ; \ + case 33: goto SRS_INST; \ + case 34: goto RFE_INST; \ + case 35: goto BKPT_INST; \ + case 36: goto BLX_INST; \ + case 37: goto CPS_INST; \ + case 38: goto PLD_INST; \ + case 39: goto SETEND_INST; \ + case 40: goto CLREX_INST; \ + case 41: goto REV16_INST; \ + case 42: goto USAD8_INST; \ + case 43: goto SXTB_INST; \ + case 44: goto UXTB_INST; \ + case 45: goto SXTH_INST; \ + case 46: goto SXTB16_INST; \ + case 47: goto UXTH_INST; \ + case 48: goto UXTB16_INST; \ + case 49: goto CPY_INST; \ + case 50: goto UXTAB_INST; \ + case 51: goto SSUB8_INST; \ + case 52: goto SHSUB8_INST; \ + case 53: goto SSUBADDX_INST; \ + case 54: goto STREX_INST; \ + case 55: goto STREXB_INST; \ + case 56: goto SWP_INST; \ + case 57: goto SWPB_INST; \ + case 58: goto SSUB16_INST; \ + case 59: goto SSAT16_INST; \ + case 60: goto SHSUBADDX_INST; \ + case 61: goto QSUBADDX_INST; \ + case 62: goto SHADDSUBX_INST; \ + case 63: goto SHADD8_INST; \ + case 64: goto SHADD16_INST; \ + case 65: goto SEL_INST; \ + case 66: goto SADDSUBX_INST; \ + case 67: goto SADD8_INST; \ + case 68: goto SADD16_INST; \ + case 69: goto SHSUB16_INST; \ + case 70: goto UMAAL_INST; \ + case 71: goto UXTAB16_INST; \ + case 72: goto USUBADDX_INST; \ + case 73: goto USUB8_INST; \ + case 74: goto USUB16_INST; \ + case 75: goto USAT16_INST; \ + case 76: goto USADA8_INST; \ + case 77: goto UQSUBADDX_INST; \ + case 78: goto UQSUB8_INST; \ + case 79: goto UQSUB16_INST; \ + case 80: goto UQADDSUBX_INST; \ + case 81: goto UQADD8_INST; \ + case 82: goto UQADD16_INST; \ + case 83: goto SXTAB_INST; \ + case 84: goto UHSUBADDX_INST; \ + case 85: goto UHSUB8_INST; \ + case 86: goto UHSUB16_INST; \ + case 87: goto UHADDSUBX_INST; \ + case 88: goto UHADD8_INST; \ + case 89: goto UHADD16_INST; \ + case 90: goto UADDSUBX_INST; \ + case 91: goto UADD8_INST; \ + case 92: goto UADD16_INST; \ + case 93: goto SXTAH_INST; \ + case 94: goto SXTAB16_INST; \ + case 95: goto QADD8_INST; \ + case 96: goto BXJ_INST; \ + case 97: goto CLZ_INST; \ + case 98: goto UXTAH_INST; \ + case 99: goto BX_INST; \ + case 100: goto REV_INST; \ + case 101: goto BLX_INST; \ + case 102: goto REVSH_INST; \ + case 103: goto QADD_INST; \ + case 104: goto QADD16_INST; \ + case 105: goto QADDSUBX_INST; \ + case 106: goto LDREX_INST; \ + case 107: goto QDADD_INST; \ + case 108: goto QDSUB_INST; \ + case 109: goto QSUB_INST; \ + case 110: goto LDREXB_INST; \ + case 111: goto QSUB8_INST; \ + case 112: goto QSUB16_INST; \ + case 113: goto SMUAD_INST; \ + case 114: goto SMMUL_INST; \ + case 115: goto SMUSD_INST; \ + case 116: goto SMLSD_INST; \ + case 117: goto SMLSLD_INST; \ + case 118: goto SMMLA_INST; \ + case 119: goto SMMLS_INST; \ + case 120: goto SMLALD_INST; \ + case 121: goto SMLAD_INST; \ + case 122: goto SMLAW_INST; \ + case 123: goto SMULW_INST; \ + case 124: goto PKHTB_INST; \ + case 125: goto PKHBT_INST; \ + case 126: goto SMUL_INST; \ + case 127: goto SMLAL_INST; \ + case 128: goto SMLA_INST; \ + case 129: goto MCRR_INST; \ + case 130: goto MRRC_INST; \ + case 131: goto CMP_INST; \ + case 132: goto TST_INST; \ + case 133: goto TEQ_INST; \ + case 134: goto CMN_INST; \ + case 135: goto SMULL_INST; \ + case 136: goto UMULL_INST; \ + case 137: goto UMLAL_INST; \ + case 138: goto SMLAL_INST; \ + case 139: goto MUL_INST; \ + case 140: goto MLA_INST; \ + case 141: goto SSAT_INST; \ + case 142: goto USAT_INST; \ + case 143: goto MRS_INST; \ + case 144: goto MSR_INST; \ + case 145: goto AND_INST; \ + case 146: goto BIC_INST; \ + case 147: goto LDM_INST; \ + case 148: goto EOR_INST; \ + case 149: goto ADD_INST; \ + case 150: goto RSB_INST; \ + case 151: goto RSC_INST; \ + case 152: goto SBC_INST; \ + case 153: goto ADC_INST; \ + case 154: goto SUB_INST; \ + case 155: goto ORR_INST; \ + case 156: goto MVN_INST; \ + case 157: goto MOV_INST; \ + case 158: goto STM_INST; \ + case 159: goto LDM_INST; \ + case 160: goto LDRSH_INST; \ + case 161: goto STM_INST; \ + case 162: goto LDM_INST; \ + case 163: goto LDRSB_INST; \ + case 164: goto STRD_INST; \ + case 165: goto LDRH_INST; \ + case 166: goto STRH_INST; \ + case 167: goto LDRD_INST; \ + case 168: goto STRT_INST; \ + case 169: goto STRBT_INST; \ + case 170: goto LDRBT_INST; \ + case 171: goto LDRT_INST; \ + case 172: goto MRC_INST; \ + case 173: goto MCR_INST; \ + case 174: goto MSR_INST; \ + case 175: goto LDRB_INST; \ + case 176: goto STRB_INST; \ + case 177: goto LDR_INST; \ + case 178: goto LDRCOND_INST ; \ + case 179: goto STR_INST; \ + case 180: goto CDP_INST; \ + case 181: goto STC_INST; \ + case 182: goto LDC_INST; \ + case 183: goto SWI_INST; \ + case 184: goto BBL_INST; \ + case 185: goto B_2_THUMB ; \ + case 186: goto B_COND_THUMB ; \ + case 187: goto BL_1_THUMB ; \ + case 188: goto BL_2_THUMB ; \ + case 189: goto BLX_1_THUMB ; \ + case 190: goto DISPATCH; \ + case 191: goto INIT_INST_LENGTH; \ + case 192: goto END; \ + } +#endif + + #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) + #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) +// #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((ISNEG(lop) && ISPOS(rop)) || \ + (ISNEG(lop) && ISPOS(dst)) || \ + (ISPOS(rop) && ISPOS(dst)))) + #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((dst < lop) || (dst < rop))) + #define UPDATE_CFLAG_CARRY_FROM_ADD(lop, rop, flag) (cpu->CFlag = (((uint64_t) lop + (uint64_t) rop + (uint64_t) flag) > 0xffffffff) ) + #define UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(lop, rop, flag) (cpu->CFlag = ((uint64_t) lop >= ((uint64_t) rop + (uint64_t) flag))) + #define UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop) (cpu->CFlag = (lop >= rop)) + #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) (cpu->CFlag = !(dst < lop)) + #define UPDATE_CFLAG_WITH_SC cpu->CFlag = cpu->shifter_carry_out +// #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || \ + (ISNEG(lop) && ISPOS(dst)) || \ + (ISPOS(rop) && ISPOS(dst))) + #define UPDATE_VFLAG(dst, lop, rop) (cpu->VFlag = (((lop < 0) && (rop < 0) && (dst >= 0)) || \ + ((lop >= 0) && (rop) >= 0 && (dst < 0)))) + #define UPDATE_VFLAG_WITH_NOT(dst, lop, rop) (cpu->VFlag = !(((lop < 0) && (rop < 0) && (dst >= 0)) || \ + ((lop >= 0) && (rop) >= 0 && (dst < 0)))) + #define UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop) (cpu->VFlag = (((lop ^ rop) & (lop ^ dst)) >> 31)) + + #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]) + #define CHECK_EXT_INT if (!cpu->NirqSig) { \ + if (!(cpu->Cpsr & 0x80)) { \ + goto END; \ + } \ + } + + + + //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t"); + arm_processor *cpu = state; //(arm_processor *)(core->cpu_data->obj); + +#if __GNUC__ + void *InstLabel[] = { + #define VFP_INTERPRETER_LABEL + #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" + #undef VFP_INTERPRETER_LABEL + &&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST, + &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST, + &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST, + &&SHADD8_INST,&&SHADD16_INST,&&SEL_INST,&&SADDSUBX_INST,&&SADD8_INST,&&SADD16_INST,&&SHSUB16_INST,&&UMAAL_INST,&&UXTAB16_INST, + &&USUBADDX_INST,&&USUB8_INST,&&USUB16_INST,&&USAT16_INST,&&USADA8_INST,&&UQSUBADDX_INST,&&UQSUB8_INST,&&UQSUB16_INST, + &&UQADDSUBX_INST,&&UQADD8_INST,&&UQADD16_INST,&&SXTAB_INST,&&UHSUBADDX_INST,&&UHSUB8_INST,&&UHSUB16_INST,&&UHADDSUBX_INST,&&UHADD8_INST, + &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST, + &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST, + &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST, + &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLAL_INST,&&SMLA_INST, + &&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST, + &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST, + &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST, + &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST, + &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST,&&SWI_INST,&&BBL_INST,&&B_2_THUMB, &&B_COND_THUMB, + &&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,&&INIT_INST_LENGTH,&&END + }; +#endif + arm_inst * inst_base; + unsigned int lop, rop, dst; + unsigned int addr; + unsigned int phys_addr; + unsigned int last_pc = 0; + fault_t fault; + static unsigned int last_physical_base = 0, last_logical_base = 0; + int ptr; + + LOAD_NZCVT; + DISPATCH: + { + if (cpu->NumInstrsToExecute == 0) + return; + + cpu->NumInstrsToExecute--; + + //NOTICE_LOG(ARM11, "instr!"); + + if (!cpu->NirqSig) { + if (!(cpu->Cpsr & 0x80)) { + goto END; + } + } + + if (cpu->TFlag) { + cpu->Reg[15] &= 0xfffffffe; + } else + cpu->Reg[15] &= 0xfffffffc; +#if PROFILE + /* check next instruction address is valid. */ + last_pc = cpu->Reg[15]; +#endif +#if USER_MODE_OPT + phys_addr = cpu->Reg[15]; +#else + { + if (last_logical_base == (cpu->Reg[15] & 0xfffff000)) + phys_addr = last_physical_base + (cpu->Reg[15] & 0xfff); + else { + /* check next instruction address is valid. */ + fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB); + if (fault) { + cpu->abortSig = true; + cpu->Aborted = ARMul_PrefetchAbortV; + cpu->AbortAddr = cpu->Reg[15]; + cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff; + cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15]; + goto END; + } + last_logical_base = cpu->Reg[15] & 0xfffff000; + last_physical_base = phys_addr & 0xfffff000; + } + } +#if HYBRID_MODE + /* check if the native code of dyncom is available */ + //fast_map hash_map = core->dyncom_engine->fmap; + //void * pfunc = NULL; + //PFUNC(phys_addr); + //if(pfunc){ + if(is_translated_entry(core, phys_addr)){ + int rc = JIT_RETURN_NOERR; + //DEBUG_LOG(ARM11, "enter jit icounter is %lld, pc=0x%x\n", core->icounter, cpu->Reg[15]); + SAVE_NZCVT; +// resume_timing(); + rc = cpu_run(core); + LOAD_NZCVT; + //DEBUG_LOG(ARM11, "out of jit ret is %d icounter is %lld, pc=0x%x\n", rc, core->icounter, cpu->Reg[15]); + if((rc == JIT_RETURN_FUNCNOTFOUND) || (rc == JIT_RETURN_FUNC_BLANK)){ + /* keep the tflag same with the bit in CPSR */ + //cpu->TFlag = cpu->Cpsr & (1 << THUMB_BIT); + //cpu->TFlag = cpu->Cpsr & (1 << 5); + //switch_mode(cpu, cpu->Cpsr & 0x1f); + //DEBUG_LOG(ARM11, "FUNCTION not found , pc=0x%x\n", cpu->Reg[15]); + fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB); + if (fault) { + cpu->abortSig = true; + cpu->Aborted = ARMul_PrefetchAbortV; + cpu->AbortAddr = cpu->Reg[15]; + cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff; + cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15]; + goto END; + } + last_logical_base = cpu->Reg[15] & 0xfffff000; + last_physical_base = phys_addr & 0xfffff000; + core->current_page_phys = last_physical_base; + core->current_page_effec = last_logical_base; + //push_to_compiled(core, phys_addr); + } + else{ + if((cpu->CP15[CP15(CP15_TLB_FAULT_STATUS)] & 0xf0)){ + //DEBUG_LOG(ARM11, "\n\n###############In %s, fsr=0x%x, fault_addr=0x%x, pc=0x%x\n\n", __FUNCTION__, cpu->CP15[CP15(CP15_FAULT_STATUS)], cpu->CP15[CP15(CP15_FAULT_ADDRESS)], cpu->Reg[15]); + //core->Reg[15] -= get_instr_size(cpu_dyncom); + fill_tlb(cpu); + goto END; + } + if (cpu->syscallSig) { + goto END; + } + if (cpu->abortSig) { + cpu->CP15[CP15_TLB_FAULT_STATUS - CP15_BASE] &= 0xFFFFFFF0; + goto END; + } + if (!cpu->NirqSig) { + if (!(cpu->Cpsr & 0x80)) { + goto END; + } + } + + /* if regular trap */ + cpu->Reg[15] += GET_INST_SIZE(cpu); + /*uint32_t mode = cpu->Cpsr & 0x1f; + if ((mode != cpu->Mode) && (!is_user_mode(core))) { + switch_mode(cpu, mode); + return 1; + }*/ + + goto END; + } + //phys_addr = cpu->Reg[15]; + } + else{ + if (last_logical_base == (cpu->Reg[15] & 0xfffff000)) + phys_addr = last_physical_base + (cpu->Reg[15] & 0xfff); + else { + /* check next instruction address is valid. */ + fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB); + if (fault) { + cpu->abortSig = true; + cpu->Aborted = ARMul_PrefetchAbortV; + cpu->AbortAddr = cpu->Reg[15]; + cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff; + cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15]; + goto END; + } + last_logical_base = cpu->Reg[15] & 0xfffff000; + last_physical_base = phys_addr & 0xfffff000; + } + } +#endif /* #if HYBRID_MODE */ +#endif /* #if USER_MODE_OPT */ + if (true){//if(is_fast_interp_code(core, phys_addr)){ + if (find_bb(phys_addr, ptr) == -1) + if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) + goto END; + } + else{ + if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) + goto END; + } +#if PROFILE + resume_timing(); +#endif + inst_base = (arm_inst *)&inst_buf[ptr]; + GOTO_NEXT_INST; + } + PROFILING: + { + goto DISPATCH; + } + ADC_INST: + { + INC_ICOUNTER; + adc_inst *inst_cream = (adc_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + lop = RN; + unsigned int sht_op = SHIFTER_OPERAND; + rop = SHIFTER_OPERAND + cpu->CFlag; + RD = dst = lop + rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr */ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_CARRY_FROM_ADD(lop, sht_op, cpu->CFlag); + UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(adc_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(adc_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + ADD_INST: + { + INC_ICOUNTER; + add_inst *inst_cream = (add_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + lop = RN; + if (inst_cream->Rn == 15) { + lop += 2 * GET_INST_SIZE(cpu); + } + rop = SHIFTER_OPERAND; + RD = dst = lop + rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr*/ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Cpsr & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG(dst, lop, rop); + UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(add_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(add_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + AND_INST: + { + INC_ICOUNTER; + and_inst *inst_cream = (and_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + lop = RN; + rop = SHIFTER_OPERAND; + RD = dst = lop & rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr*/ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Cpsr & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_WITH_SC; + //UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(and_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(and_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + BBL_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || 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 PROFILING; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(bbl_inst)); + goto PROFILING; + } + BIC_INST: + { + INC_ICOUNTER; + bic_inst *inst_cream = (bic_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + lop = RN; + if (inst_cream->Rn == 15) { + lop += 2 * GET_INST_SIZE(cpu); + } + rop = SHIFTER_OPERAND; +// RD = dst = lop & (rop ^ 0xffffffff); + RD = dst = lop & (~rop); + if ((inst_cream->S) && (inst_cream->Rd == 15)) { + /* cpsr = spsr */ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_WITH_SC; + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(bic_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(bic_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + BKPT_INST: + BLX_INST: + { + INC_ICOUNTER; + blx_inst *inst_cream = (blx_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + unsigned int inst = inst_cream->inst; + if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { + //LINK_RTN_ADDR; + cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu)); + if(cpu->TFlag) + cpu->Reg[14] |= 0x1; + cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe; + cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1; + //cpu->Reg[15] = cpu->Reg[BITS(inst, 0, 3)] & 0xfffffffe; + //cpu->TFlag = cpu->Reg[BITS(inst, 0, 3)] & 0x1; + } else { + cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu)); + 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] + 2 * GET_INST_SIZE(cpu) + cpu->Reg[15] = cpu->Reg[15] + 8 + + signed_int + (BIT(inst, 24) << 1); + //DEBUG_MSG; + } + INC_PC(sizeof(blx_inst)); + goto PROFILING; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); +// INC_PC(sizeof(bx_inst)); + INC_PC(sizeof(blx_inst)); + goto PROFILING; + } + BX_INST: + { + INC_ICOUNTER; + bx_inst *inst_cream = (bx_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + if (inst_cream->Rm == 15) + DEBUG_LOG(ARM11, "In %s, BX at pc %x: use of Rm = R15 is discouraged\n", __FUNCTION__, cpu->Reg[15]); + cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; + cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe; +// cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; + INC_PC(sizeof(bx_inst)); + goto PROFILING; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); +// INC_PC(sizeof(bx_inst)); + INC_PC(sizeof(bx_inst)); + goto PROFILING; + } + BXJ_INST: + CDP_INST: + { + INC_ICOUNTER; + cdp_inst *inst_cream = (cdp_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + /* FIXME, check if cp access allowed */ + #define CP_ACCESS_ALLOW 0 + if(CP_ACCESS_ALLOW){ + /* undefined instruction here */ + return; + } + ERROR_LOG(ARM11, "CDP insn inst=0x%x, pc=0x%x\n", inst_cream->inst, cpu->Reg[15]); + unsigned cpab = (cpu->CDP[inst_cream->cp_num]) (cpu, ARMul_FIRST, inst_cream->inst); + if(cpab != ARMul_DONE){ + ERROR_LOG(ARM11, "CDP insn wrong, inst=0x%x, cp_num=0x%x\n", inst_cream->inst, inst_cream->cp_num); + //CITRA_IGNORE_EXIT(-1); + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(cdp_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + + CLREX_INST: + { + INC_ICOUNTER; + remove_exclusive(cpu, 0); + cpu->exclusive_state = 0; + + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(clrex_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + CLZ_INST: + { + INC_ICOUNTER; + clz_inst *inst_cream = (clz_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + RD = clz(RM); + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(clz_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + CMN_INST: + { + INC_ICOUNTER; + cmn_inst *inst_cream = (cmn_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { +// DEBUG_LOG(ARM11, "RN is %x\n", RN); + lop = RN; + rop = SHIFTER_OPERAND; + dst = lop + rop; + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG(dst, lop, rop); + UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(cmn_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + CMP_INST: + { +// DEBUG_LOG(ARM11, "cmp inst\n"); +// DEBUG_LOG(ARM11, "pc: %x\n", cpu->Reg[15]); + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { +// DEBUG_LOG(ARM11, "r0 is %x\n", cpu->Reg[0]); + cmp_inst *inst_cream = (cmp_inst *)inst_base->component; + lop = RN; + if (inst_cream->Rn == 15) { + lop += 2 * GET_INST_SIZE(cpu); + } + rop = SHIFTER_OPERAND; + dst = lop - rop; + + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); +// UPDATE_CFLAG(dst, lop, rop); + UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); +// UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); +// UPDATE_VFLAG_WITH_NOT(dst, lop, rop); + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(cmp_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + CPS_INST: + { + INC_ICOUNTER; + cps_inst *inst_cream = (cps_inst *)inst_base->component; + uint32_t aif_val = 0; + uint32_t aif_mask = 0; + if (InAPrivilegedMode(cpu)) { + /* isInAPrivilegedMode */ + 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; + switch_mode(cpu, inst_cream->mode); + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(cps_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + CPY_INST: + { + INC_ICOUNTER; + mov_inst *inst_cream = (mov_inst *)inst_base->component; +// cpy_inst *inst_cream = (cpy_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + RD = SHIFTER_OPERAND; +// RD = RM; + if ((inst_cream->Rd == 15)) { + INC_PC(sizeof(mov_inst)); + goto PROFILING; + } + } +// DEBUG_LOG(ARM11, "cpy inst %x\n", cpu->Reg[15]); + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mov_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + EOR_INST: + { + INC_ICOUNTER; + eor_inst *inst_cream = (eor_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + lop = RN; + if (inst_cream->Rn == 15) { + lop += 2 * GET_INST_SIZE(cpu); + } + rop = SHIFTER_OPERAND; + RD = dst = lop ^ rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr*/ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_WITH_SC; +// UPDATE_CFLAG(dst, lop, rop); +// UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(eor_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(eor_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDC_INST: + { + INC_ICOUNTER; + /* NOT IMPL */ + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldc_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDM_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + int i; + unsigned int ret; + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) { + goto MMU_EXCEPTION; + } + unsigned int inst = inst_cream->inst; + if (BIT(inst, 22) && !BIT(inst, 15)) { +// DEBUG_MSG; + #if 1 + /* LDM (2) user */ + for (i = 0; i < 13; i++) { + if(BIT(inst, i)){ + #if 0 + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) { + goto MMU_EXCEPTION; + } + #endif + fault = interpreter_read_memory(addr, phys_addr, ret, 32); + //if (fault) goto MMU_EXCEPTION; + cpu->Reg[i] = ret; + addr += 4; + if ((addr & 0xfff) == 0) { + fault = check_address_validity(cpu, addr, &phys_addr, 1); + } else { + phys_addr += 4; + } + } + } + if (BIT(inst, 13)) { + #if 0 + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) { + goto MMU_EXCEPTION; + } + #endif + fault = interpreter_read_memory(addr, phys_addr, ret, 32); + //if (fault) goto MMU_EXCEPTION; + if (cpu->Mode == USER32MODE) + cpu->Reg[13] = ret; + else + cpu->Reg_usr[0] = ret; + addr += 4; + if ((addr & 0xfff) == 0) { + fault = check_address_validity(cpu, addr, &phys_addr, 1); + } else { + phys_addr += 4; + } + } + if (BIT(inst, 14)) { + #if 0 + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) { + goto MMU_EXCEPTION; + } + #endif + fault = interpreter_read_memory(addr, phys_addr, ret, 32); + //if (fault) goto MMU_EXCEPTION; + if (cpu->Mode == USER32MODE) + cpu->Reg[14] = ret; + else + cpu->Reg_usr[1] = ret; + } + #endif + } else if (!BIT(inst, 22)) { + for( i = 0; i < 16; i ++ ){ + if(BIT(inst, i)){ + //bus_read(32, addr, &ret); + #if 0 + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) { + goto MMU_EXCEPTION; + } + #endif + fault = interpreter_read_memory(addr, phys_addr, ret, 32); + if (fault) goto MMU_EXCEPTION; + /* For armv5t, should enter thumb when bits[0] is non-zero. */ + if(i == 15){ + cpu->TFlag = ret & 0x1; + ret &= 0xFFFFFFFE; + //DEBUG_LOG(ARM11, "In %s, TFlag ret=0x%x\n", __FUNCTION__, ret); + } + + cpu->Reg[i] = ret; + addr += 4; + if ((addr & 0xfff) == 0) { + fault = check_address_validity(cpu, addr, &phys_addr, 1); + } else { + phys_addr += 4; + } + } + } + } else if (BIT(inst, 22) && BIT(inst, 15)) { + for( i = 0; i < 15; i ++ ){ + if(BIT(inst, i)){ + #if 0 + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) { + goto MMU_EXCEPTION; + } + #endif + fault = interpreter_read_memory(addr, phys_addr, ret, 32); + //if (fault) goto MMU_EXCEPTION; + cpu->Reg[i] = ret; + addr += 4; + if ((addr & 0xfff) == 0) { + fault = check_address_validity(cpu, addr, &phys_addr, 1); + } else { + phys_addr += 4; + } + } + } + + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Cpsr & 0x1f); + LOAD_NZCVT; + } + #if 0 + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) { + goto MMU_EXCEPTION; + } + #endif + fault = interpreter_read_memory(addr, phys_addr, ret, 32); + if (fault) { + goto MMU_EXCEPTION; + } + cpu->Reg[15] = ret; + #if 0 + addr += 4; + phys_addr += 4; + #endif + } + if (BIT(inst, 15)) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SXTH_INST: + { + INC_ICOUNTER; + sxth_inst *inst_cream = (sxth_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(sxth_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDR_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + //if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + //bus_read(32, addr, &value); + fault = interpreter_read_memory(addr, phys_addr, value, 32); + if (BIT(CP15_REG(CP15_CONTROL), 22) == 1) + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + else { + value = ROTATE_RIGHT_32(value,(8*(addr&0x3))); + 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 PROFILING; + } + //} + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDRCOND_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if (CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + //bus_read(32, addr, &value); + fault = interpreter_read_memory(addr, phys_addr, value, 32); + if (BIT(CP15_REG(CP15_CONTROL), 22) == 1) + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + else { + value = ROTATE_RIGHT_32(value,(8*(addr&0x3))); + 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 PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + UXTH_INST: + { + INC_ICOUNTER; + uxth_inst *inst_cream = (uxth_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) + & 0xffff; + RD = operand2; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(uxth_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + UXTAH_INST: + { + INC_ICOUNTER; + uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) + & 0xffff; + RD = RN + operand2; + if (inst_cream->Rn == 15 || inst_cream->Rm == 15) { + DEBUG_LOG(ARM11, "in line %d\n", __LINE__); + CITRA_IGNORE_EXIT(-1); + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(uxtah_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDRB_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 8); + if (fault) goto MMU_EXCEPTION; + //bus_read(8, addr, &value); + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + if (BITS(inst_cream->inst, 12, 15) == 15) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDRBT_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 8); + if (fault) goto MMU_EXCEPTION; + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + if (BITS(inst_cream->inst, 12, 15) == 15) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDRD_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + /* Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0) */ + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + uint32_t rear_phys_addr; + fault = check_address_validity(cpu, addr + 4, &rear_phys_addr, 1); + if(fault){ + ERROR_LOG(ARM11, "mmu fault , should rollback the above get_addr\n"); + CITRA_IGNORE_EXIT(-1); + goto MMU_EXCEPTION; + } + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + fault = interpreter_read_memory(addr + 4, rear_phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = value; + /* 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: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + + add_exclusive_addr(cpu, phys_addr); + cpu->exclusive_state = 1; + + //bus_read(32, addr, &value); + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + if (BITS(inst_cream->inst, 12, 15) == 15) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDREXB_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 8); + if (fault) goto MMU_EXCEPTION; + + add_exclusive_addr(cpu, phys_addr); + cpu->exclusive_state = 1; + + //bus_read(8, addr, &value); + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + if (BITS(inst_cream->inst, 12, 15) == 15) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDRH_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value = 0; + fault = interpreter_read_memory(addr, phys_addr, value, 16); +// fault = interpreter_read_memory(addr, value, 32); + if (fault) goto MMU_EXCEPTION; + //if (value == 0xffff && cpu->icounter > 190000000 && cpu->icounter < 210000000) { + // value = 0xffffffff; + //} + //bus_read(16, addr, &value); +// cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value & 0xffff; + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + if (BITS(inst_cream->inst, 12, 15) == 15) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDRSB_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; +// DEBUG_LOG(ARM11, "ldrsb addr is %x\n", addr); + fault = interpreter_read_memory(addr, phys_addr, value, 8); + if (fault) goto MMU_EXCEPTION; + //bus_read(8, addr, &value); + if (BIT(value, 7)) { + value |= 0xffffff00; + } + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + if (BITS(inst_cream->inst, 12, 15) == 15) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDRSH_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 16); + if (fault) goto MMU_EXCEPTION; + //bus_read(16, addr, &value); + if (BIT(value, 15)) { + value |= 0xffff0000; + } + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + if (BITS(inst_cream->inst, 12, 15) == 15) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + LDRT_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + + if (BIT(CP15_REG(CP15_CONTROL), 22) == 1) + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; + else + cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ROTATE_RIGHT_32(value,(8*(addr&0x3))) ; + + if (BITS(inst_cream->inst, 12, 15) == 15) { + INC_PC(sizeof(ldst_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MCR_INST: + { + INC_ICOUNTER; + /* NOT IMPL */ + mcr_inst *inst_cream = (mcr_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + unsigned int inst = inst_cream->inst; + if (inst_cream->Rd == 15) { + DEBUG_MSG; + } else { + if (inst_cream->cp_num == 15) { + if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) { + //LET(RD, CONST(0x0007b000)); + //LET(RD, CONST(0x410FB760)); + //LET(CP15_MAIN_ID, R(RD)); + CP15_REG(CP15_MAIN_ID) = RD; + } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { + //LET(RD, R(CP15_CONTROL)); + CP15_REG(CP15_AUXILIARY_CONTROL) = RD; + } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { + //LET(RD, R(CP15_CONTROL)); + CP15_REG(CP15_COPROCESSOR_ACCESS_CONTROL) = RD; + } else if(CRn == 1 && CRm == 0 && OPCODE_2 == 0) { + //LET(CP15_CONTROL, R(RD)); + CP15_REG(CP15_CONTROL) = RD; + } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) { + //LET(CP15_DOMAIN_ACCESS_CONTROL, R(RD)); + CP15_REG(CP15_DOMAIN_ACCESS_CONTROL) = RD; + } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { + //LET(CP15_TRANSLATION_BASE_TABLE_0, R(RD)); + CP15_REG(CP15_TRANSLATION_BASE_TABLE_0) = RD; + } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) { + //LET(CP15_TRANSLATION_BASE_TABLE_1, R(RD)); + CP15_REG(CP15_TRANSLATION_BASE_TABLE_1) = RD; + } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) { + //LET(CP15_TRANSLATION_BASE_CONTROL, R(RD)); + CP15_REG(CP15_TRANSLATION_BASE_CONTROL) = RD; + } else if(CRn == MMU_CACHE_OPS){ + //SKYEYE_WARNING("cache operation have not implemented.\n"); + } else if(CRn == MMU_TLB_OPS){ + switch (CRm) { + case 5: /* ITLB */ + switch(OPCODE_2){ + case 0: /* invalidate all */ + //invalidate_all_tlb(state); + DEBUG_LOG(ARM11, "{TLB} [INSN] invalidate all\n"); + //remove_tlb(INSN_TLB); + //erase_all(core, INSN_TLB); + break; + case 1: /* invalidate by MVA */ + //invalidate_by_mva(state, value); + //DEBUG_LOG(ARM11, "{TLB} [INSN] invalidate by mva\n"); + //remove_tlb_by_mva(RD, INSN_TLB); + //erase_by_mva(core, RD, INSN_TLB); + break; + case 2: /* invalidate by asid */ + //invalidate_by_asid(state, value); + //DEBUG_LOG(ARM11, "{TLB} [INSN] invalidate by asid\n"); + //erase_by_asid(core, RD, INSN_TLB); + break; + default: + break; + } + + break; + case 6: /* DTLB */ + switch(OPCODE_2){ + case 0: /* invalidate all */ + //invalidate_all_tlb(state); + //remove_tlb(DATA_TLB); + //erase_all(core, DATA_TLB); + DEBUG_LOG(ARM11, "{TLB} [DATA] invalidate all\n"); + break; + case 1: /* invalidate by MVA */ + //invalidate_by_mva(state, value); + //remove_tlb_by_mva(RD, DATA_TLB); + //erase_by_mva(core, RD, DATA_TLB); + //DEBUG_LOG(ARM11, "{TLB} [DATA] invalidate by mva\n"); + break; + case 2: /* invalidate by asid */ + //invalidate_by_asid(state, value); + //remove_tlb_by_asid(RD, DATA_TLB); + //erase_by_asid(core, RD, DATA_TLB); + //DEBUG_LOG(ARM11, "{TLB} [DATA] invalidate by asid\n"); + break; + default: + break; + } + break; + case 7: /* UNIFILED TLB */ + switch(OPCODE_2){ + case 0: /* invalidate all */ + //invalidate_all_tlb(state); + //erase_all(core, INSN_TLB); + //erase_all(core, DATA_TLB); + //remove_tlb(DATA_TLB); + //remove_tlb(INSN_TLB); + //DEBUG_LOG(ARM11, "{TLB} [UNIFILED] invalidate all\n"); + break; + case 1: /* invalidate by MVA */ + //invalidate_by_mva(state, value); + //erase_by_mva(core, RD, DATA_TLB); + //erase_by_mva(core, RD, INSN_TLB); + DEBUG_LOG(ARM11, "{TLB} [UNIFILED] invalidate by mva\n"); + break; + case 2: /* invalidate by asid */ + //invalidate_by_asid(state, value); + //erase_by_asid(core, RD, DATA_TLB); + //erase_by_asid(core, RD, INSN_TLB); + DEBUG_LOG(ARM11, "{TLB} [UNIFILED] invalidate by asid\n"); + break; + default: + break; + } + break; + default: + break; + } + } else if(CRn == MMU_PID){ + if(OPCODE_2 == 0) + CP15_REG(CP15_PID) = RD; + else if(OPCODE_2 == 1) + CP15_REG(CP15_CONTEXT_ID) = RD; + else if(OPCODE_2 == 3){ + CP15_REG(CP15_THREAD_URO) = RD; + } + else{ + printf ("mmu_mcr wrote UNKNOWN - reg %d\n", CRn); + } + + } else { + DEBUG_LOG(ARM11, "mcr is not implementated. CRn is %d, CRm is %d, OPCODE_2 is %d\n", CRn, CRm, OPCODE_2); + } + } + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mcr_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MCRR_INST: + MLA_INST: + { + INC_ICOUNTER; + mla_inst *inst_cream = (mla_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + uint64_t rm = RM; + uint64_t rs = RS; + uint64_t rn = RN; + if (inst_cream->Rm == 15 || inst_cream->Rs == 15 || inst_cream->Rn == 15) { + DEBUG_LOG(ARM11, "in __line__\n", __LINE__); + CITRA_IGNORE_EXIT(-1); + } +// RD = dst = RM * RS + RN; + RD = dst = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff); + if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(mla_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mla_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MOV_INST: + { +// DEBUG_LOG(ARM11, "mov inst\n"); +// DEBUG_LOG(ARM11, "pc: %x\n", cpu->Reg[15]); +// debug_function(cpu); +// cpu->icount ++; + INC_ICOUNTER; + mov_inst *inst_cream = (mov_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + RD = dst = SHIFTER_OPERAND; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr */ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_WITH_SC; + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(mov_inst)); + goto PROFILING; + } +// return; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mov_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MRC_INST: + { + INC_ICOUNTER; + /* NOT IMPL */ + mrc_inst *inst_cream = (mrc_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + unsigned int inst = inst_cream->inst; + if (inst_cream->Rd == 15) { + DEBUG_MSG; + } + if (inst_cream->inst == 0xeef04a10) { + /* undefined instruction fmrx */ + RD = 0x20000000; + CITRA_IGNORE_EXIT(-1); + goto END; + } else { + if (inst_cream->cp_num == 15) { + if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) { + //LET(RD, CONST(0x0007b000)); + //LET(RD, CONST(0x410FB760)); + //LET(RD, R(CP15_MAIN_ID)); + RD = cpu->CP15[CP15(CP15_MAIN_ID)]; + } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) { + //LET(RD, R(CP15_CONTROL)); + RD = cpu->CP15[CP15(CP15_CONTROL)]; + } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { + //LET(RD, R(CP15_CONTROL)); + RD = cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)]; + } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { + //LET(RD, R(CP15_CONTROL)); + RD = cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)]; + } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) { + //LET(RD, R(CP15_DOMAIN_ACCESS_CONTROL)); + RD = cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)]; + } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { + //LET(RD, R(CP15_TRANSLATION_BASE_TABLE_0)); + RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)]; + } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 0) { + //LET(RD, R(CP15_FAULT_STATUS)); + RD = cpu->CP15[CP15(CP15_FAULT_STATUS)]; + } else if (CRn == 6 && CRm == 0 && OPCODE_2 == 0) { + //LET(RD, R(CP15_FAULT_ADDRESS)); + RD = cpu->CP15[CP15(CP15_FAULT_ADDRESS)]; + } else if (CRn == 0 && CRm == 0 && OPCODE_2 == 1) { + //LET(RD, R(CP15_CACHE_TYPE)); + RD = cpu->CP15[CP15(CP15_CACHE_TYPE)]; + } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 1) { + //LET(RD, R(CP15_INSTR_FAULT_STATUS)); + RD = cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)]; + } else if (CRn == 13) { + if(OPCODE_2 == 0) + RD = CP15_REG(CP15_PID); + else if(OPCODE_2 == 1) + RD = CP15_REG(CP15_CONTEXT_ID); + else if(OPCODE_2 == 3){ + RD = Memory::KERNEL_MEMORY_VADDR; + } + else{ + printf ("mmu_mrr wrote UNKNOWN - reg %d\n", CRn); + } + } + else { + DEBUG_LOG(ARM11, "mrc is not implementated. CRn is %d, CRm is %d, OPCODE_2 is %d\n", CRn, CRm, OPCODE_2); + } + } + //DEBUG_LOG(ARM11, "mrc is not implementated. CRn is %d, CRm is %d, OPCODE_2 is %d\n", CRn, CRm, OPCODE_2); + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mrc_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MRRC_INST: + MRS_INST: + { + INC_ICOUNTER; + mrs_inst *inst_cream = (mrs_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + if (inst_cream->R) { + RD = cpu->Spsr_copy; + } else { + SAVE_NZCVT; + RD = cpu->Cpsr; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mrs_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MSR_INST: + { + INC_ICOUNTER; + msr_inst *inst_cream = (msr_inst *)inst_base->component; + const uint32_t UnallocMask = 0x06f0fc00, 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 = ROTL(CONST(BITS(0, 7)), CONST(32 - rot_imm)); + operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); + } else { + //operand = R(RM); + operand = cpu->Reg[BITS(inst, 0, 3)]; + } + uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) + | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); + uint32_t mask; + if (!inst_cream->R) { + if (InAPrivilegedMode(cpu)) { + if ((operand & StateMask) != 0) { + /* UNPREDICTABLE */ + DEBUG_MSG; + } else + mask = byte_mask & (UserMask | PrivMask); + } else { + mask = byte_mask & UserMask; + } + //LET(CPSR_REG, OR(AND(R(CPSR_REG), COM(CONST(mask))), AND(operand, CONST(mask)))); + SAVE_NZCVT; + + cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); + switch_mode(cpu, cpu->Cpsr & 0x1f); + LOAD_NZCVT; + } else { + if (CurrentModeHasSPSR) { + mask = byte_mask & (UserMask | PrivMask | StateMask); + //LET(SPSR_REG, OR(AND(R(SPSR_REG), COM(CONST(mask))), AND(operand, CONST(mask)))); + cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(msr_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MUL_INST: + { + INC_ICOUNTER; + mul_inst *inst_cream = (mul_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { +// RD = dst = SHIFTER_OPERAND; + uint64_t rm = RM; + uint64_t rs = RS; + RD = dst = static_cast<uint32_t>((rm * rs) & 0xffffffff); + if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(mul_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mul_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + MVN_INST: + { + INC_ICOUNTER; + mvn_inst *inst_cream = (mvn_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { +// RD = dst = (SHIFTER_OPERAND ^ 0xffffffff); + RD = dst = ~SHIFTER_OPERAND; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr */ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_WITH_SC; + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(mvn_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(mvn_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + ORR_INST: + { + INC_ICOUNTER; + orr_inst *inst_cream = (orr_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + lop = RN; + rop = SHIFTER_OPERAND; +// DEBUG_LOG(ARM11, "lop is %x, rop is %x, r2 is %x, r3 is %x\n", lop, rop, cpu->Reg[2], cpu->Reg[3]); + RD = dst = lop | rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr*/ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_WITH_SC; +// UPDATE_CFLAG(dst, lop, rop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(orr_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(orr_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + PKHBT_INST: + PKHTB_INST: + PLD_INST: + { + INC_ICOUNTER; + /* NOT IMPL */ + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(stc_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + QADD_INST: + QADD16_INST: + QADD8_INST: + QADDSUBX_INST: + QDADD_INST: + QDSUB_INST: + QSUB_INST: + QSUB16_INST: + QSUB8_INST: + QSUBADDX_INST: + REV_INST: + { + INC_ICOUNTER; + rev_inst *inst_cream = (rev_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + RD = ((RM & 0xff) << 24) | + (((RM >> 8) & 0xff) << 16) | + (((RM >> 16) & 0xff) << 8) | + ((RM >> 24) & 0xff); + if (inst_cream->Rm == 15) { + DEBUG_LOG(ARM11, "in line %d\n", __LINE__); + CITRA_IGNORE_EXIT(-1); + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(rev_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + REV16_INST: + { + INC_ICOUNTER; + rev_inst *inst_cream = (rev_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + RD = (BITS(RM, 0, 7) << 8) | + BITS(RM, 8, 15) | + (BITS(RM, 16, 23) << 24) | + (BITS(RM, 24, 31) << 16); + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(rev_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + REVSH_INST: + RFE_INST: + RSB_INST: + { + INC_ICOUNTER; + rsb_inst *inst_cream = (rsb_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + rop = RN; + lop = SHIFTER_OPERAND; + if (inst_cream->Rn == 15) { + rop += 2 * GET_INST_SIZE(cpu);; + } + RD = dst = lop - rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr */ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); +// UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(rsb_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(rsb_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + RSC_INST: + { + INC_ICOUNTER; + rsc_inst *inst_cream = (rsc_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + //lop = RN + !cpu->CFlag; + //rop = SHIFTER_OPERAND; + //RD = dst = rop - lop; + lop = RN; + rop = SHIFTER_OPERAND; + RD = dst = rop - lop - !cpu->CFlag; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr */ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); +// UPDATE_CFLAG(dst, lop, rop); +// UPDATE_CFLAG_NOT_BORROW_FROM(rop, lop); + UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(rop, lop, !cpu->CFlag); +// cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || (ISNEG(lop) && ISPOS(dst)) || (ISPOS(rop) && ISPOS(dst))); + UPDATE_VFLAG_OVERFLOW_FROM((int)dst, (int)rop, (int)lop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(rsc_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(rsc_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SADD16_INST: + SADD8_INST: + SADDSUBX_INST: + SBC_INST: + { + INC_ICOUNTER; + sbc_inst *inst_cream = (sbc_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + lop = SHIFTER_OPERAND + !cpu->CFlag; + rop = RN; + RD = dst = rop - lop; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr */ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); +// UPDATE_CFLAG(dst, lop, rop); + //UPDATE_CFLAG_NOT_BORROW_FROM(rop, lop); + //rop = rop - !cpu->CFlag; + if(rop >= !cpu->CFlag) + UPDATE_CFLAG_NOT_BORROW_FROM(rop - !cpu->CFlag, SHIFTER_OPERAND); + else + UPDATE_CFLAG_NOT_BORROW_FROM(rop, !cpu->CFlag); +// cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || (ISNEG(lop) && ISPOS(dst)) || (ISPOS(rop) && ISPOS(dst))); + UPDATE_VFLAG_OVERFLOW_FROM(dst, rop, lop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(sbc_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(sbc_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SEL_INST: + SETEND_INST: + SHADD16_INST: + SHADD8_INST: + SHADDSUBX_INST: + SHSUB16_INST: + SHSUB8_INST: + SHSUBADDX_INST: + SMLA_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + smla_inst *inst_cream = (smla_inst *)inst_base->component; + int32_t 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 + RN; + //FIXME: UPDATE Q FLAGS + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(smla_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SMLAD_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + smlad_inst *inst_cream = (smlad_inst *)inst_base->component; + long long int rm = cpu->Reg[inst_cream->Rm]; + long long int rn = cpu->Reg[inst_cream->Rn]; + long long int ra = cpu->Reg[inst_cream->Ra]; + /* see SMUAD */ + if(inst_cream->Ra == 15) + CITRA_IGNORE_EXIT(-1); + int operand2 = (inst_cream->m)? ROTATE_RIGHT_32(rm, 16):rm; + + int half_rn, half_operand2; + half_rn = rn & 0xFFFF; + half_rn = (half_rn & 0x8000)? (0xFFFF0000|half_rn) : half_rn; + + half_operand2 = operand2 & 0xFFFF; + half_operand2 = (half_operand2 & 0x8000)? (0xFFFF0000|half_operand2) : half_operand2; + + long long int product1 = half_rn * half_operand2; + + half_rn = (rn & 0xFFFF0000) >> 16; + half_rn = (half_rn & 0x8000)? (0xFFFF0000|half_rn) : half_rn; + + half_operand2 = (operand2 & 0xFFFF0000) >> 16; + half_operand2 = (half_operand2 & 0x8000)? (0xFFFF0000|half_operand2) : half_operand2; + + long long int product2 = half_rn * half_operand2; + + long long int signed_ra = (ra & 0x80000000)? (0xFFFFFFFF00000000LL) | ra : ra; + long long int result = product1 + product2 + signed_ra; + cpu->Reg[inst_cream->Rd] = result & 0xFFFFFFFF; + /* FIXME , should check Signed overflow */ + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(umlal_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + + SMLAL_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(umlal_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SMLALXY_INST: + SMLALD_INST: + SMLAW_INST: + SMLSD_INST: + SMLSLD_INST: + SMMLA_INST: + SMMLS_INST: + SMMUL_INST: + SMUAD_INST: + SMUL_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + smul_inst *inst_cream = (smul_inst *)inst_base->component; + uint32_t 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(smul_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SMULL_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + umull_inst *inst_cream = (umull_inst *)inst_base->component; +// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst); + int64_t rm = RM; + int64_t rs = RS; + if (BIT(rm, 31)) { + rm |= 0xffffffff00000000LL; + } + if (BIT(rs, 31)) { + rs |= 0xffffffff00000000LL; + } + int64_t 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(umull_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SMULW_INST: + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + smlad_inst *inst_cream = (smlad_inst *)inst_base->component; +// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst); + int64_t rm = RM; + int64_t rn = RN; + if (inst_cream->m) + rm = BITS(rm,16 , 31); + else + rm = BITS(rm,0 , 15); + int64_t rst = rm * rn; + RD = BITS(rst, 16, 47); + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(smlad_inst)); + FETCH_INST; + GOTO_NEXT_INST; + + SMUSD_INST: + SRS_INST: + SSAT_INST: + SSAT16_INST: + SSUB16_INST: + SSUB8_INST: + SSUBADDX_INST: + STC_INST: + { + INC_ICOUNTER; + /* NOT IMPL */ + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(stc_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STM_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + unsigned int inst = inst_cream->inst; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + int i; + unsigned int Rn = BITS(inst, 16, 19); + unsigned int old_RN = cpu->Reg[Rn]; + + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + if (BIT(inst_cream->inst, 22) == 1) { +// DEBUG_MSG; + #if 1 + for (i = 0; i < 13; i++) { + if(BIT(inst_cream->inst, i)){ + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) { + goto MMU_EXCEPTION; + } + fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32); + if (fault) goto MMU_EXCEPTION; + addr += 4; + phys_addr += 4; + } + } + if (BIT(inst_cream->inst, 13)) { + if (cpu->Mode == USER32MODE) { + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) { + goto MMU_EXCEPTION; + } + fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32); + if (fault) goto MMU_EXCEPTION; + addr += 4; + phys_addr += 4; + } else { + fault = interpreter_write_memory(addr, phys_addr, cpu->Reg_usr[0], 32); + if (fault) goto MMU_EXCEPTION; + addr += 4; + phys_addr += 4; + } + } + if (BIT(inst_cream->inst, 14)) { + if (cpu->Mode == USER32MODE) { + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) { + goto MMU_EXCEPTION; + } + fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32); + if (fault) goto MMU_EXCEPTION; + addr += 4; + phys_addr += 4; + } else { + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) { + goto MMU_EXCEPTION; + } + fault = interpreter_write_memory(addr, phys_addr, cpu->Reg_usr[1], 32); + if (fault) goto MMU_EXCEPTION; + addr += 4; + phys_addr += 4; + } + } + if (BIT(inst_cream->inst, 15)) { + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) { + goto MMU_EXCEPTION; + } + fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i] + 8, 32); + if (fault) goto MMU_EXCEPTION; + } + #endif + } else { + for( i = 0; i < 15; i ++ ){ + if(BIT(inst_cream->inst, i)){ + //arch_write_memory(cpu, bb, Addr, R(i), 32); + //bus_write(32, addr, cpu->Reg[i]); + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) { + goto MMU_EXCEPTION; + } + if(i == Rn) + fault = interpreter_write_memory(addr, phys_addr, old_RN, 32); + else + fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32); + if (fault) goto MMU_EXCEPTION; + addr += 4; + phys_addr += 4; + //Addr = ADD(Addr, CONST(4)); + } + } + + /* check pc reg*/ + if(BIT(inst_cream->inst, i)){ + //arch_write_memory(cpu, bb, Addr, STOREM_CHECK_PC, 32); + //bus_write(32, addr, cpu->Reg[i] + 8); + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) { + goto MMU_EXCEPTION; + } + fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i] + 8, 32); + if (fault) goto MMU_EXCEPTION; + } + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SXTB_INST: + { + INC_ICOUNTER; + sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + if (inst_cream->Rm == 15) { + DEBUG_LOG(ARM11, "line is %d\n", __LINE__); + CITRA_IGNORE_EXIT(-1); + } + 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(sxtb_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STR_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; + //bus_write(32, addr, value); + fault = interpreter_write_memory(addr, phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + UXTB_INST: + { + INC_ICOUNTER; + uxtb_inst *inst_cream = (uxtb_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) + & 0xff; + RD = operand2; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(uxtb_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + UXTAB_INST: + { + INC_ICOUNTER; + uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) + & 0xff; + RD = RN + operand2; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(uxtab_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STRB_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; + //bus_write(8, addr, value); + fault = interpreter_write_memory(addr, phys_addr, value, 8); + if (fault) goto MMU_EXCEPTION; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STRBT_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; + //bus_write(8, addr, value); + fault = interpreter_write_memory(addr, phys_addr, value, 8); + if (fault) goto MMU_EXCEPTION; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + //if (BITS(inst_cream->inst, 12, 15) == 15) + // goto PROFILING; + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STRD_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + uint32_t rear_phys_addr; + fault = check_address_validity(cpu, addr + 4, &rear_phys_addr, 0); + if (fault){ + ERROR_LOG(ARM11, "mmu fault , should rollback the above get_addr\n"); + CITRA_IGNORE_EXIT(-1); + goto MMU_EXCEPTION; + } + + //fault = inst_cream->get_addr(cpu, inst_cream->inst, addr + 4, phys_addr + 4, 0); + //if (fault) goto MMU_EXCEPTION; + + unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; + //bus_write(32, addr, value); + fault = interpreter_write_memory(addr, phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + value = cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]; + //bus_write(32, addr, value); + fault = interpreter_write_memory(addr + 4, rear_phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STREX_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; + unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)]; + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + + int dest_reg = BITS(inst_cream->inst, 12, 15); + if((exclusive_detect(cpu, phys_addr) == 0) && (cpu->exclusive_state == 1)){ + remove_exclusive(cpu, phys_addr); + cpu->Reg[dest_reg] = 0; + cpu->exclusive_state = 0; + + // bus_write(32, addr, value); + fault = interpreter_write_memory(addr, phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + } + else{ + /* Failed to write due to mutex access */ + cpu->Reg[dest_reg] = 1; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STREXB_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; + unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)] & 0xff; + fault = check_address_validity(cpu, addr, &phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + //bus_write(8, addr, value); + int dest_reg = BITS(inst_cream->inst, 12, 15); + if((exclusive_detect(cpu, phys_addr) == 0) && (cpu->exclusive_state == 1)){ + remove_exclusive(cpu, phys_addr); + cpu->Reg[dest_reg] = 0; + cpu->exclusive_state = 0; + fault = interpreter_write_memory(addr, phys_addr, value, 8); + if (fault) goto MMU_EXCEPTION; + + } + else{ + cpu->Reg[dest_reg] = 1; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STRH_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; + //bus_write(16, addr, value); + fault = interpreter_write_memory(addr, phys_addr, value, 16); + if (fault) goto MMU_EXCEPTION; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + //if (BITS(inst_cream->inst, 12, 15) == 15) + // goto PROFILING; + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + STRT_INST: + { + INC_ICOUNTER; + ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); + if (fault) goto MMU_EXCEPTION; + unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; + //bus_write(16, addr, value); + fault = interpreter_write_memory(addr, phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(ldst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SUB_INST: + { + INC_ICOUNTER; + sub_inst *inst_cream = (sub_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + lop = RN; + if (inst_cream->Rn == 15) { + lop += 8; + } + rop = SHIFTER_OPERAND; + RD = dst = lop - rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { + /* cpsr = spsr */ + if (CurrentModeHasSPSR) { + cpu->Cpsr = cpu->Spsr_copy; + switch_mode(cpu, cpu->Spsr_copy & 0x1f); + LOAD_NZCVT; + } + } else if (inst_cream->S) { + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); +// UPDATE_CFLAG(dst, lop, rop); + UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); + // UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); + } + if (inst_cream->Rd == 15) { + INC_PC(sizeof(sub_inst)); + goto PROFILING; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(sub_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SWI_INST: + { + INC_ICOUNTER; + swi_inst *inst_cream = (swi_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + if (true){ //if (core->is_user_mode) { --> Citra only emulates user mode + //arm_dyncom_SWI(cpu, inst_cream->num); + HLE::CallSVC(Memory::Read32(cpu->Reg[15])); + } else { + cpu->syscallSig = 1; + goto END; + } + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(swi_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SWP_INST: + { + INC_ICOUNTER; + swp_inst *inst_cream = (swp_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + addr = RN; + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 32); + if (fault) goto MMU_EXCEPTION; + fault = interpreter_write_memory(addr, phys_addr, RM, 32); + if (fault) goto MMU_EXCEPTION; + + /* ROR(data, 8*UInt(address<1:0>)); */ + assert((phys_addr & 0x3) == 0); + RD = value; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(swp_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SWPB_INST: + { + INC_ICOUNTER; + swp_inst *inst_cream = (swp_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + addr = RN; + fault = check_address_validity(cpu, addr, &phys_addr, 1); + if (fault) goto MMU_EXCEPTION; + unsigned int value; + fault = interpreter_read_memory(addr, phys_addr, value, 8); + if (fault) goto MMU_EXCEPTION; + fault = interpreter_write_memory(addr, phys_addr, (RM & 0xFF), 8); + if (fault) goto MMU_EXCEPTION; + + /* FIXME */ + #if 0 + if Shared(address) then + /* ARMv6 */ + physical_address = TLB(address) + ClearExclusiveByAddress(physical_address,processor_id,1) + /* See Summary of operation on page A2-49 */ + #endif + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(swp_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SXTAB_INST: + { + INC_ICOUNTER; + sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + /* R15 should be check */ + if(inst_cream->Rn == 15 || inst_cream->Rm == 15 || inst_cream->Rd ==15){ + CITRA_IGNORE_EXIT(-1); + } + 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(uxtab_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SXTAB16_INST: + SXTAH_INST: + { + INC_ICOUNTER; + sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + /* R15 should be check */ + if(inst_cream->Rn == 15 || inst_cream->Rm == 15 || inst_cream->Rd ==15){ + CITRA_IGNORE_EXIT(-1); + } + 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(sxtah_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + SXTB16_INST: + TEQ_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + teq_inst *inst_cream = (teq_inst *)inst_base->component; + lop = RN; + if (inst_cream->Rn == 15) + lop += GET_INST_SIZE(cpu) * 2; + + rop = SHIFTER_OPERAND; + dst = lop ^ rop; + + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_WITH_SC; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(teq_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + TST_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { + tst_inst *inst_cream = (tst_inst *)inst_base->component; + lop = RN; + if (inst_cream->Rn == 15) + lop += GET_INST_SIZE(cpu) * 2; + rop = SHIFTER_OPERAND; + dst = lop & rop; + + UPDATE_NFLAG(dst); + UPDATE_ZFLAG(dst); + UPDATE_CFLAG_WITH_SC; + } + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(tst_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + UADD16_INST: + UADD8_INST: + UADDSUBX_INST: + UHADD16_INST: + UHADD8_INST: + UHADDSUBX_INST: + UHSUB16_INST: + UHSUB8_INST: + UHSUBADDX_INST: + UMAAL_INST: + UMLAL_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || 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; + //DEBUG_LOG(ARM11, "rm[%llx] * rs[%llx] = rst[%llx] | add[%llx]\n", RM, RS, rst, add); + 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(umlal_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + UMULL_INST: + { + INC_ICOUNTER; + if ((inst_base->cond == 0xe) || 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; +// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst); + 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] += GET_INST_SIZE(cpu); + INC_PC(sizeof(umull_inst)); + FETCH_INST; + GOTO_NEXT_INST; + } + B_2_THUMB: + { + INC_ICOUNTER; + b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component; + cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; + //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); + INC_PC(sizeof(b_2_thumb)); + goto PROFILING; + } + B_COND_THUMB: + { + INC_ICOUNTER; + 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; + //DEBUG_LOG(ARM11, " B_COND_THUMB: imm=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[15]); + INC_PC(sizeof(b_cond_thumb)); + goto PROFILING; + } + BL_1_THUMB: + { + INC_ICOUNTER; + bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component; + cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm; + //cpu->Reg[15] += 2; + //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); + + cpu->Reg[15] += GET_INST_SIZE(cpu); + INC_PC(sizeof(bl_1_thumb)); + FETCH_INST; + GOTO_NEXT_INST; + + } + BL_2_THUMB: + { + INC_ICOUNTER; + 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; + //DEBUG_LOG(ARM11, " BL_2_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); + INC_PC(sizeof(bl_2_thumb)); + goto PROFILING; + } + BLX_1_THUMB: + { + /* BLX 1 for armv5t and above */ + INC_ICOUNTER; + uint32 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; + //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, instr=0x%x\n", inst_cream->imm, cpu->Reg[14], inst_cream->instr); + cpu->Reg[14] = ((tmp + 2) | 1); + //(state->Reg[14] + ((tinstr & 0x07FF) << 1)) & 0xFFFFFFFC; + /* switch to arm state from thumb state */ + cpu->TFlag = 0; + //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, r15=0x%x, \n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); + INC_PC(sizeof(blx_1_thumb)); + goto PROFILING; + } + + UQADD16_INST: + UQADD8_INST: + UQADDSUBX_INST: + UQSUB16_INST: + UQSUB8_INST: + UQSUBADDX_INST: + USAD8_INST: + USADA8_INST: + USAT_INST: + USAT16_INST: + USUB16_INST: + USUB8_INST: + USUBADDX_INST: + UXTAB16_INST: + UXTB16_INST: + #define VFP_INTERPRETER_IMPL + #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" + #undef VFP_INTERPRETER_IMPL + MMU_EXCEPTION: + { + SAVE_NZCVT; + cpu->abortSig = true; + cpu->Aborted = ARMul_DataAbortV; + cpu->AbortAddr = addr; + cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff; + cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr; + return; + } + END: + { + SAVE_NZCVT; + return; + } + INIT_INST_LENGTH: + { +#if 0 + DEBUG_LOG(ARM11, "InstLabel:%d\n", sizeof(InstLabel)); + for (int i = 0; i < (sizeof(InstLabel) / sizeof(void *)); i ++) + DEBUG_LOG(ARM11, "[%llx]\n", InstLabel[i]); + DEBUG_LOG(ARM11, "InstLabel:%d\n", sizeof(InstLabel)); +#endif +#ifdef __GNUC__ + InterpreterInitInstLength((unsigned long long int *)InstLabel, sizeof(InstLabel)); +#endif +#if 0 + for (int i = 0; i < (sizeof(InstLabel) / sizeof(void *)); i ++) + DEBUG_LOG(ARM11, "[%llx]\n", InstLabel[i]); + DEBUG_LOG(ARM11, "%llx\n", InstEndLabel[1]); + DEBUG_LOG(ARM11, "%llx\n", InstLabel[1]); + DEBUG_LOG(ARM11, "%lld\n", (char *)InstEndLabel[1] - (char *)InstLabel[1]); +#endif + return; + } +} + diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h new file mode 100644 index 000000000..d73f8f65f --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h @@ -0,0 +1,7 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +void InterpreterMainLoop(ARMul_State* state); diff --git a/src/core/arm/dyncom/arm_dyncom_run.cpp b/src/core/arm/dyncom/arm_dyncom_run.cpp new file mode 100644 index 000000000..a2026cbf3 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_run.cpp @@ -0,0 +1,120 @@ +/* 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_run.cpp +* @brief The dyncom run implementation for arm +* @author Michael.Kang blackfin.kang@gmail.com +* @version 78.77 +* @date 2011-11-20 +*/ + +#include <assert.h> + +#include "core/arm/skyeye_common/armdefs.h" + +void switch_mode(arm_core_t *core, uint32_t mode) +{ + uint32_t tmp1, tmp2; + if (core->Mode == mode) { + //Mode not changed. + //printf("mode not changed\n"); + return; + } + //printf("%d --->>> %d\n", core->Mode, mode); + //printf("In %s, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter); + if (mode != USERBANK) { + switch (core->Mode) { + case USER32MODE: + core->Reg_usr[0] = core->Reg[13]; + core->Reg_usr[1] = core->Reg[14]; + break; + case IRQ32MODE: + core->Reg_irq[0] = core->Reg[13]; + core->Reg_irq[1] = core->Reg[14]; + core->Spsr[IRQBANK] = core->Spsr_copy; + break; + case SVC32MODE: + core->Reg_svc[0] = core->Reg[13]; + core->Reg_svc[1] = core->Reg[14]; + core->Spsr[SVCBANK] = core->Spsr_copy; + break; + case ABORT32MODE: + core->Reg_abort[0] = core->Reg[13]; + core->Reg_abort[1] = core->Reg[14]; + core->Spsr[ABORTBANK] = core->Spsr_copy; + break; + case UNDEF32MODE: + core->Reg_undef[0] = core->Reg[13]; + core->Reg_undef[1] = core->Reg[14]; + core->Spsr[UNDEFBANK] = core->Spsr_copy; + break; + case FIQ32MODE: + core->Reg_firq[0] = core->Reg[13]; + core->Reg_firq[1] = core->Reg[14]; + core->Spsr[FIQBANK] = core->Spsr_copy; + break; + + } + + switch (mode) { + case USER32MODE: + core->Reg[13] = core->Reg_usr[0]; + core->Reg[14] = core->Reg_usr[1]; + core->Bank = USERBANK; + break; + case IRQ32MODE: + core->Reg[13] = core->Reg_irq[0]; + core->Reg[14] = core->Reg_irq[1]; + core->Spsr_copy = core->Spsr[IRQBANK]; + core->Bank = IRQBANK; + break; + case SVC32MODE: + core->Reg[13] = core->Reg_svc[0]; + core->Reg[14] = core->Reg_svc[1]; + core->Spsr_copy = core->Spsr[SVCBANK]; + core->Bank = SVCBANK; + break; + case ABORT32MODE: + core->Reg[13] = core->Reg_abort[0]; + core->Reg[14] = core->Reg_abort[1]; + core->Spsr_copy = core->Spsr[ABORTBANK]; + core->Bank = ABORTBANK; + break; + case UNDEF32MODE: + core->Reg[13] = core->Reg_undef[0]; + core->Reg[14] = core->Reg_undef[1]; + core->Spsr_copy = core->Spsr[UNDEFBANK]; + core->Bank = UNDEFBANK; + break; + case FIQ32MODE: + core->Reg[13] = core->Reg_firq[0]; + core->Reg[14] = core->Reg_firq[1]; + core->Spsr_copy = core->Spsr[FIQBANK]; + core->Bank = FIQBANK; + break; + + } + core->Mode = mode; + //printf("In %si end, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter); + //printf("\n--------------------------------------\n"); + } + else { + printf("user mode\n"); + exit(-2); + } +} diff --git a/src/core/arm/dyncom/arm_dyncom_run.h b/src/core/arm/dyncom/arm_dyncom_run.h new file mode 100644 index 000000000..aeabeac16 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_run.h @@ -0,0 +1,55 @@ +/* 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. +* +*/ + +#ifndef __ARM_DYNCOM_RUN__ +#define __ARM_DYNCOM_RUN__ + +#include "core/arm/skyeye_common/skyeye_types.h" + +void switch_mode(arm_core_t *core, uint32_t mode); + +/* FIXME, we temporarily think thumb instruction is always 16 bit */ +static inline uint32 GET_INST_SIZE(arm_core_t* core){ + return core->TFlag? 2 : 4; +} + +/** +* @brief Read R15 and forced R15 to wold align, used address calculation +* +* @param core +* @param Rn +* +* @return +*/ +static inline addr_t CHECK_READ_REG15_WA(arm_core_t* core, int Rn){ + return (Rn == 15)? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; +} + +/** +* @brief Read R15, used to data processing with pc +* +* @param core +* @param Rn +* +* @return +*/ +static inline uint32 CHECK_READ_REG15(arm_core_t* core, int Rn){ + return (Rn == 15)? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; +} + +#endif diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp new file mode 100644 index 000000000..e10f2f9ee --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp @@ -0,0 +1,521 @@ +/* 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.c +* @brief The thumb dynamic interpreter +* @author Michael.Kang blackfin.kang@gmail.com +* @version 78.77 +* @date 2011-11-07 +*/ + +/* We can provide simple Thumb simulation by decoding the Thumb +instruction into its corresponding ARM instruction, and using the +existing ARM simulator. */ + +#include "core/arm/skyeye_common/skyeye_defs.h" + +#ifndef MODET /* required for the Thumb instruction support */ +#if 1 +#error "MODET needs to be defined for the Thumb world to work" +#else +#define MODET (1) +#endif +#endif + +#include "core/arm/skyeye_common/armos.h" +#include "core/arm/dyncom/arm_dyncom_thumb.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. */ + +tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size) +{ + tdstate valid = t_uninitialized; + ARMword next_instr; + ARMword tinstr; + tinstr = instr; + /* The endian should be judge here */ + #if 0 + if (state->bigendSig) { + next_instr = tinstr & 0xFFFF; + tinstr >>= 16; + } + else { + next_instr = tinstr >> 16; + tinstr &= 0xFFFF; + } + #endif + if((addr & 0x3) != 0) + tinstr = instr >> 16; + else + tinstr &= 0xFFFF; + + //printf("In %s, instr=0x%x, tinstr=0x%x, r15=0x%x\n", __FUNCTION__, instr, tinstr, cpu->translate_pc); +#if 1 /* debugging to catch non updates */ + *ainstr = 0xDEADC0DE; +#endif + + switch ((tinstr & 0xF800) >> 11) { + case 0: /* LSL */ + case 1: /* LSR */ + case 2: /* ASR */ + /* Format 1 */ + *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 */ + /* Format 2 */ + { + ARMword 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 */ + /* Format 3 */ + { + ARMword 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) { + typedef enum + { t_norm, t_shift, t_neg, t_mul }otype_t; + + /* Format 4 */ + struct + { + ARMword opcode; + otype_t otype; + } + 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].otype) { + 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 { + /* Format 5 */ + ARMword Rd = ((tinstr & 0x0007) >> 0); + ARMword Rs = ((tinstr & 0x0038) >> 3); + if (tinstr & (1 << 7)) + Rd += 8; + if (tinstr & (1 << 6)) + Rs += 8; + switch ((tinstr & 0x03C0) >> 6) { + 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 0x5: /* CMP Rd,Hs */ + case 0x6: /* CMP Hd,Rs */ + case 0x7: /* CMP Hd,Hs */ + *ainstr = 0xE1500000 /* base */ + | (Rd << 16) /* Rn */ + |(Rd << 12) /* Rd */ + |(Rs << 0); /* Rm */ + break; + case 0x9: /* MOV Rd,Hs */ + case 0xA: /* MOV Hd,Rs */ + case 0xB: /* MOV Hd,Hs */ + *ainstr = 0xE1A00000 /* base */ + | (Rd << 16) /* Rn */ + |(Rd << 12) /* Rd */ + |(Rs << 0); /* Rm */ + break; + case 0xC: /* BX Rs */ + case 0xD: /* BX Hs */ + *ainstr = 0xE12FFF10 /* base */ + | ((tinstr & 0x0078) >> 3); /* Rd */ + break; + case 0x0: /* UNDEFINED */ + case 0x4: /* UNDEFINED */ + case 0x8: /* UNDEFINED */ + valid = t_undefined; + break; + case 0xE: /* BLX */ + case 0xF: /* BLX */ + + //if (state->is_v5) { + if(1){ + //valid = t_branch; + #if 1 + *ainstr = 0xE1200030 /* base */ + |(Rs << 0); /* Rm */ + #endif + } else { + valid = t_undefined; + } + break; + } + } + break; + case 9: /* LDR Rd,[PC,#imm8] */ + /* Format 6 */ + *ainstr = 0xE59F0000 /* base */ + | ((tinstr & 0x0700) << (12 - 8)) /* Rd */ + |((tinstr & 0x00FF) << (2 - 0)); /* off8 */ + break; + case 10: + case 11: + /* TODO: Format 7 and Format 8 perform the same ARM encoding, so + the following could be merged into a single subset, saving on + the following boolean: */ + if ((tinstr & (1 << 9)) == 0) { + /* Format 7 */ + ARMword subset[4] = { + 0xE7800000, /* STR Rd,[Rb,Ro] */ + 0xE7C00000, /* STRB Rd,[Rb,Ro] */ + 0xE7900000, /* LDR Rd,[Rb,Ro] */ + 0xE7D00000 /* LDRB Rd,[Rb,Ro] */ + }; + *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */ + |((tinstr & 0x0007) << (12 - 0)) /* Rd */ + |((tinstr & 0x0038) << (16 - 3)) /* Rb */ + |((tinstr & 0x01C0) >> 6); /* Ro */ + } + else { + /* Format 8 */ + ARMword subset[4] = { + 0xE18000B0, /* STRH Rd,[Rb,Ro] */ + 0xE19000D0, /* LDRSB Rd,[Rb,Ro] */ + 0xE19000B0, /* LDRH Rd,[Rb,Ro] */ + 0xE19000F0 /* LDRSH Rd,[Rb,Ro] */ + }; + *ainstr = subset[(tinstr & 0x0C00) >> 10] /* 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] */ + /* Format 9 */ + { + ARMword 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] */ + /* Format 10 */ + *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] */ + /* Format 11 */ + *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 */ + /* Format 12 */ + 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) { + /* Format 13 */ + /* 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) + *ainstr = 0xEF000000 | SWI_Breakpoint; + else { + /* Format 14 */ + ARMword 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 */ + /* Format 15 */ + *ainstr = ((tinstr & (1 << 11)) /* base */ + ? 0xE8B00000 /* LDMIA */ + : 0xE8A00000) /* STMIA */ + |((tinstr & 0x0700) << (16 - 8)) /* Rb */ + |(tinstr & 0x00FF); /* mask8 */ + break; + case 26: /* Bcc */ + case 27: /* Bcc/SWI */ + if ((tinstr & 0x0F00) == 0x0F00) { + #if 0 + if (tinstr == (ARMul_ABORTWORD & 0xffff) && + state->AbortAddr == pc) { + *ainstr = ARMul_ABORTWORD; + break; + } + #endif + /* 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 |= SWI_Breakpoint; + else + *ainstr |= (tinstr & 0x00FF); + } + else if ((tinstr & 0x0F00) != 0x0E00) { + /* Format 16 */ + #if 0 + int doit = FALSE; + /* TODO: Since we are doing a switch here, we could just add + the SWI and undefined instruction checks into this + switch to same on a couple of conditionals: */ + switch ((tinstr & 0x0F00) >> 8) { + case EQ: + doit = ZFLAG; + break; + case NE: + doit = !ZFLAG; + break; + case VS: + doit = VFLAG; + break; + case VC: + doit = !VFLAG; + break; + case MI: + doit = NFLAG; + break; + case PL: + doit = !NFLAG; + break; + case CS: + doit = CFLAG; + break; + case CC: + doit = !CFLAG; + break; + case HI: + doit = (CFLAG && !ZFLAG); + break; + case LS: + doit = (!CFLAG || ZFLAG); + break; + case GE: + doit = ((!NFLAG && !VFLAG) + || (NFLAG && VFLAG)); + break; + case LT: + doit = ((NFLAG && !VFLAG) + || (!NFLAG && VFLAG)); + break; + case GT: + doit = ((!NFLAG && !VFLAG && !ZFLAG) + || (NFLAG && VFLAG && !ZFLAG)); + break; + case LE: + doit = ((NFLAG && !VFLAG) + || (!NFLAG && VFLAG)) || ZFLAG; + break; + } + if (doit) { + state->Reg[15] = (pc + 4 + + (((tinstr & 0x7F) << 1) + | ((tinstr & (1 << 7)) ? + 0xFFFFFF00 : 0))); + FLUSHPIPE; + } + #endif + valid = t_branch; + } + else /* UNDEFINED : cc=1110(AL) uses different format */ + valid = t_undefined; + break; + case 28: /* B */ + /* Format 18 */ + #if 0 + state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1) + | ((tinstr & (1 << 10)) ? + 0xFFFFF800 : 0))); + #endif + //FLUSHPIPE; + valid = t_branch; + break; + case 29: + if(tinstr & 0x1) + valid = t_undefined; + else{ + /* BLX 1 for armv5t and above */ + //printf("In %s, After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x\n", __FUNCTION__, state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1); + valid = t_branch; + } + break; + case 30: /* BL instruction 1 */ + /* Format 19 */ + /* 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 = t_branch; + break; + case 31: /* BL instruction 2 */ + /* Format 19 */ + /* 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. */ + { + #if 0 + ARMword tmp = (pc + 2); + state->Reg[15] = + (state->Reg[14] + ((tinstr & 0x07FF) << 1)); + state->Reg[14] = (tmp | 1); + #endif + valid = t_branch; + } + break; + } + *inst_size = 2; + return valid; +} diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h new file mode 100644 index 000000000..5541de9d1 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_thumb.h @@ -0,0 +1,51 @@ +/* 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 +*/ + +#ifndef __ARM_DYNCOM_THUMB_H__ +#define __ARM_DYNCOM_THUMB_H__ + +#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/skyeye_types.h" + +enum tdstate { + t_undefined, // Undefined Thumb instruction + t_decoded, // Instruction decoded to ARM equivalent + t_branch, // Thumb branch (already processed) + t_uninitialized, +}; + +tdstate +thumb_translate(addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size); +static inline uint32 get_thumb_instr(uint32 instr, addr_t pc){ + uint32 tinstr; + if ((pc & 0x3) != 0) + tinstr = instr >> 16; + else + tinstr = instr & 0xFFFF; + return tinstr; +} + +#endif |