diff options
author | Lioncash <mathew1800@gmail.com> | 2015-02-01 02:34:26 +0100 |
---|---|---|
committer | Lioncash <mathew1800@gmail.com> | 2015-02-01 02:43:03 +0100 |
commit | f44781fd7b0c5f99573e917ccdd92716a99a9b0d (patch) | |
tree | ad31575f5653316488371cd654d961ce803e2c01 /src/core/arm/interpreter | |
parent | Merge pull request #512 from lioncash/assignment (diff) | |
download | yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.gz yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.bz2 yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.lz yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.xz yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.zst yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.zip |
Diffstat (limited to 'src/core/arm/interpreter')
-rw-r--r-- | src/core/arm/interpreter/arm_interpreter.cpp | 114 | ||||
-rw-r--r-- | src/core/arm/interpreter/arm_interpreter.h | 96 | ||||
-rw-r--r-- | src/core/arm/interpreter/armcopro.cpp | 254 | ||||
-rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 5648 | ||||
-rw-r--r-- | src/core/arm/interpreter/arminit.cpp | 136 | ||||
-rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 881 | ||||
-rw-r--r-- | src/core/arm/interpreter/armvirt.cpp | 165 | ||||
-rw-r--r-- | src/core/arm/interpreter/thumbemu.cpp | 513 |
8 files changed, 56 insertions, 7751 deletions
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp deleted file mode 100644 index c76d371a2..000000000 --- a/src/core/arm/interpreter/arm_interpreter.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/arm/interpreter/arm_interpreter.h" - -#include "core/core.h" - -const static cpu_config_t arm11_cpu_info = { - "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE -}; - -ARM_Interpreter::ARM_Interpreter() { - state = new ARMul_State; - - ARMul_EmulateInit(); - memset(state, 0, sizeof(ARMul_State)); - - ARMul_NewState(state); - - state->abort_model = 0; - state->cpu = (cpu_config_t*)&arm11_cpu_info; - state->bigendSig = LOW; - - ARMul_SelectProcessor(state, ARM_v6_Prop | ARM_v5_Prop | ARM_v5e_Prop); - state->lateabtSig = LOW; - - // Reset the core to initial state - ARMul_CoProInit(state); - ARMul_Reset(state); - 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; -} - -ARM_Interpreter::~ARM_Interpreter() { - delete state; -} - -void ARM_Interpreter::SetPC(u32 pc) { - state->pc = state->Reg[15] = pc; -} - -u32 ARM_Interpreter::GetPC() const { - return state->pc; -} - -u32 ARM_Interpreter::GetReg(int index) const { - return state->Reg[index]; -} - -void ARM_Interpreter::SetReg(int index, u32 value) { - state->Reg[index] = value; -} - -u32 ARM_Interpreter::GetCPSR() const { - return state->Cpsr; -} - -void ARM_Interpreter::SetCPSR(u32 cpsr) { - state->Cpsr = cpsr; -} - -u64 ARM_Interpreter::GetTicks() const { - return state->NumInstrs; -} - -void ARM_Interpreter::AddTicks(u64 ticks) { - state->NumInstrs += ticks; -} - -void ARM_Interpreter::ExecuteInstructions(int num_instructions) { - state->NumInstrsToExecute = num_instructions - 1; - ARMul_Emulate32(state); -} - -void ARM_Interpreter::SaveContext(Core::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; -} - -void ARM_Interpreter::LoadContext(const Core::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; -} - -void ARM_Interpreter::PrepareReschedule() { - state->NumInstrsToExecute = 0; -} diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h deleted file mode 100644 index e5ecc69c2..000000000 --- a/src/core/arm/interpreter/arm_interpreter.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common.h" - -#include "core/arm/arm_interface.h" -#include "core/arm/skyeye_common/armdefs.h" -#include "core/arm/skyeye_common/armemu.h" - -class ARM_Interpreter final : virtual public ARM_Interface { -public: - - ARM_Interpreter(); - ~ARM_Interpreter(); - - /** - * Set the Program Counter to an address - * @param pc Address to set PC to - */ - void SetPC(u32 pc) override; - - /* - * Get the current Program Counter - * @return Returns current PC - */ - u32 GetPC() const override; - - /** - * Get an ARM register - * @param index Register index (0-15) - * @return Returns the value in the register - */ - u32 GetReg(int index) const override; - - /** - * Set an ARM register - * @param index Register index (0-15) - * @param value Value to set register to - */ - void SetReg(int index, u32 value) override; - - /** - * Get the current CPSR register - * @return Returns the value of the CPSR register - */ - u32 GetCPSR() const override; - - /** - * Set the current CPSR register - * @param cpsr Value to set CPSR to - */ - void SetCPSR(u32 cpsr) override; - - /** - * Returns the number of clock ticks since the last reset - * @return Returns number of clock ticks - */ - u64 GetTicks() const override; - - /** - * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time) - * @param ticks Number of ticks to advance the CPU core - */ - void AddTicks(u64 ticks) override; - - /** - * Saves the current CPU context - * @param ctx Thread context to save - */ - void SaveContext(Core::ThreadContext& ctx) override; - - /** - * Loads a CPU context - * @param ctx Thread context to load - */ - void LoadContext(const Core::ThreadContext& ctx) override; - - /// Prepare core for thread reschedule (if needed to correctly handle state) - void PrepareReschedule() override; - -protected: - - /** - * Executes the given number of instructions - * @param num_instructions Number of instructions to executes - */ - void ExecuteInstructions(int num_instructions) override; - -private: - - ARMul_State* state; - -}; diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp index b4ddc3d96..bb9ca98fe 100644 --- a/src/core/arm/interpreter/armcopro.cpp +++ b/src/core/arm/interpreter/armcopro.cpp @@ -19,213 +19,45 @@ #include "core/arm/skyeye_common/armemu.h" #include "core/arm/skyeye_common/vfp/vfp.h" -//chy 2005-07-08 -//#include "ansidecl.h" -//chy ------- -//#include "iwmmxt.h" +// Dummy Co-processors. -/* Dummy Co-processors. */ - -static unsigned -NoCoPro3R(ARMul_State * state, -unsigned a, ARMword b) +static unsigned int NoCoPro3R(ARMul_State* state, unsigned int a, ARMword b) { return ARMul_CANT; } -static unsigned -NoCoPro4R(ARMul_State * state, -unsigned a, -ARMword b, ARMword c) +static unsigned int NoCoPro4R(ARMul_State* state, unsigned int a, ARMword b, ARMword c) { return ARMul_CANT; } -static unsigned -NoCoPro4W(ARMul_State * state, -unsigned a, -ARMword b, ARMword * c) +static unsigned int NoCoPro4W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c) { return ARMul_CANT; } -static unsigned -NoCoPro5R(ARMul_State * state, -unsigned a, -ARMword b, -ARMword c, ARMword d) +static unsigned int NoCoPro5R(ARMul_State* state, unsigned int a, ARMword b, ARMword c, ARMword d) { return ARMul_CANT; } -static unsigned -NoCoPro5W(ARMul_State * state, -unsigned a, -ARMword b, -ARMword * c, ARMword * d) +static unsigned int NoCoPro5W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c, ARMword* d) { return ARMul_CANT; } -/* The XScale Co-processors. */ - -/* Coprocessor 15: System Control. */ -static void write_cp14_reg(unsigned, ARMword); -static ARMword read_cp14_reg(unsigned); - -/* Check an access to a register. */ - -static unsigned -check_cp15_access(ARMul_State * state, -unsigned reg, -unsigned CRm, unsigned opcode_1, unsigned opcode_2) -{ - /* Do not allow access to these register in USER mode. */ - //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode - if (state->Mode == USER26MODE || state->Mode == USER32MODE) - return ARMul_CANT; - - /* Opcode_1should be zero. */ - if (opcode_1 != 0) - return ARMul_CANT; - - /* Different register have different access requirements. */ - switch (reg) { - case 0: - case 1: - /* CRm must be 0. Opcode_2 can be anything. */ - if (CRm != 0) - return ARMul_CANT; - break; - case 2: - case 3: - /* CRm must be 0. Opcode_2 must be zero. */ - if ((CRm != 0) || (opcode_2 != 0)) - return ARMul_CANT; - break; - case 4: - /* Access not allowed. */ - return ARMul_CANT; - case 5: - case 6: - /* Opcode_2 must be zero. CRm must be 0. */ - if ((CRm != 0) || (opcode_2 != 0)) - return ARMul_CANT; - break; - case 7: - /* Permissable combinations: - Opcode_2 CRm - 0 5 - 0 6 - 0 7 - 1 5 - 1 6 - 1 10 - 4 10 - 5 2 - 6 5 */ - switch (opcode_2) { - default: - return ARMul_CANT; - case 6: - if (CRm != 5) - return ARMul_CANT; - break; - case 5: - if (CRm != 2) - return ARMul_CANT; - break; - case 4: - if (CRm != 10) - return ARMul_CANT; - break; - case 1: - if ((CRm != 5) && (CRm != 6) && (CRm != 10)) - return ARMul_CANT; - break; - case 0: - if ((CRm < 5) || (CRm > 7)) - return ARMul_CANT; - break; - } - break; - - case 8: - /* Permissable combinations: - Opcode_2 CRm - 0 5 - 0 6 - 0 7 - 1 5 - 1 6 */ - if (opcode_2 > 1) - return ARMul_CANT; - if ((CRm < 5) || (CRm > 7)) - return ARMul_CANT; - if (opcode_2 == 1 && CRm == 7) - return ARMul_CANT; - break; - case 9: - /* Opcode_2 must be zero or one. CRm must be 1 or 2. */ - if (((CRm != 0) && (CRm != 1)) - || ((opcode_2 != 1) && (opcode_2 != 2))) - return ARMul_CANT; - break; - case 10: - /* Opcode_2 must be zero or one. CRm must be 4 or 8. */ - if (((CRm != 0) && (CRm != 1)) - || ((opcode_2 != 4) && (opcode_2 != 8))) - return ARMul_CANT; - break; - case 11: - /* Access not allowed. */ - return ARMul_CANT; - case 12: - /* Access not allowed. */ - return ARMul_CANT; - case 13: - /* Opcode_2 must be zero. CRm must be 0. */ - if ((CRm != 0) || (opcode_2 != 0)) - return ARMul_CANT; - break; - case 14: - /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */ - if (opcode_2 != 0) - return ARMul_CANT; - - if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8) - && (CRm != 9)) - return ARMul_CANT; - break; - case 15: - /* Opcode_2 must be zero. CRm must be 1. */ - if ((CRm != 1) || (opcode_2 != 0)) - return ARMul_CANT; - break; - default: - /* Should never happen. */ - return ARMul_CANT; - } - - return ARMul_DONE; -} - -/* Install co-processor instruction handlers in this routine. */ - -unsigned -ARMul_CoProInit(ARMul_State * state) +// Install co-processor instruction handlers in this routine. +unsigned int ARMul_CoProInit(ARMul_State* state) { - unsigned int i; - - /* Initialise tham all first. */ - for (i = 0; i < 16; i++) + // Initialise tham all first. + for (unsigned int i = 0; i < 16; i++) ARMul_CoProDetach(state, i); - /* Install CoPro Instruction handlers here. - The format is: - ARMul_CoProAttach (state, CP Number, Init routine, Exit routine - LDC routine, STC routine, MRC routine, MCR routine, - CDP routine, Read Reg routine, Write Reg routine). */ + // Install CoPro Instruction handlers here. + // The format is: + // ARMul_CoProAttach (state, CP Number, Init routine, Exit routine + // LDC routine, STC routine, MRC routine, MCR routine, + // CDP routine, Read Reg routine, Write Reg routine). if (state->is_v6) { ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC, VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); @@ -235,57 +67,44 @@ ARMul_CoProInit(ARMul_State * state) /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL);*/ } - //chy 2003-09-03 do it in future!!!!???? -#if 0 - if (state->is_iWMMXt) { - ARMul_CoProAttach(state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC, - NULL, NULL, IwmmxtCDP, NULL, NULL); - ARMul_CoProAttach(state, 1, NULL, NULL, NULL, NULL, - IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, - NULL); - } -#endif - /* No handlers below here. */ + // No handlers below here. - /* Call all the initialisation routines. */ - for (i = 0; i < 16; i++) + // Call all the initialisation routines. + for (unsigned int i = 0; i < 16; i++) if (state->CPInit[i]) (state->CPInit[i]) (state); return TRUE; } -/* Install co-processor finalisation routines in this routine. */ - -void -ARMul_CoProExit(ARMul_State * state) +// Install co-processor finalisation routines in this routine. +void ARMul_CoProExit(ARMul_State * state) { - register unsigned i; - - for (i = 0; i < 16; i++) + for (unsigned int i = 0; i < 16; i++) if (state->CPExit[i]) (state->CPExit[i]) (state); - for (i = 0; i < 16; i++) /* Detach all handlers. */ + // Detach all handlers. + for (unsigned int i = 0; i < 16; i++) ARMul_CoProDetach(state, i); } -/* Routines to hook Co-processors into ARMulator. */ +// Routines to hook Co-processors into ARMulator. void -ARMul_CoProAttach(ARMul_State * state, +ARMul_CoProAttach(ARMul_State* state, unsigned number, -ARMul_CPInits * init, -ARMul_CPExits * exit, -ARMul_LDCs * ldc, -ARMul_STCs * stc, -ARMul_MRCs * mrc, -ARMul_MCRs * mcr, -ARMul_MRRCs * mrrc, -ARMul_MCRRs * mcrr, -ARMul_CDPs * cdp, -ARMul_CPReads * read, ARMul_CPWrites * write) +ARMul_CPInits* init, +ARMul_CPExits* exit, +ARMul_LDCs* ldc, +ARMul_STCs* stc, +ARMul_MRCs* mrc, +ARMul_MCRs* mcr, +ARMul_MRRCs* mrrc, +ARMul_MCRRs* mcrr, +ARMul_CDPs* cdp, +ARMul_CPReads* read, ARMul_CPWrites* write) { if (init != NULL) state->CPInit[number] = init; @@ -311,8 +130,7 @@ ARMul_CPReads * read, ARMul_CPWrites * write) state->CPWrite[number] = write; } -void -ARMul_CoProDetach(ARMul_State * state, unsigned number) +void ARMul_CoProDetach(ARMul_State* state, unsigned number) { ARMul_CoProAttach(state, number, NULL, NULL, NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp deleted file mode 100644 index 7114313d6..000000000 --- a/src/core/arm/interpreter/armemu.cpp +++ /dev/null @@ -1,5648 +0,0 @@ -/* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator. - Copyright (C) 1994 Advanced RISC Machines Ltd. - Modifications to add arch. v4 support by <jsmith@cygnus.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. */ - -#include "core/arm/skyeye_common/arm_regformat.h" -#include "core/arm/skyeye_common/armdefs.h" -#include "core/arm/skyeye_common/armemu.h" -#include "core/hle/hle.h" - -static ARMword GetDPRegRHS (ARMul_State *, ARMword); -static ARMword GetDPSRegRHS (ARMul_State *, ARMword); -static void WriteR15 (ARMul_State *, ARMword); -static void WriteSR15 (ARMul_State *, ARMword); -static void WriteR15Branch (ARMul_State *, ARMword); -static ARMword GetLSRegRHS (ARMul_State *, ARMword); -static ARMword GetLS7RHS (ARMul_State *, ARMword); -static unsigned LoadWord (ARMul_State *, ARMword, ARMword); -static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int); -static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int); -static unsigned StoreWord (ARMul_State *, ARMword, ARMword); -static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword); -static unsigned StoreByte (ARMul_State *, ARMword, ARMword); -static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword); -static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword); -static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword); -static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword); -static unsigned Multiply64 (ARMul_State *, ARMword, int, int); -static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int); -static void Handle_Load_Double (ARMul_State *, ARMword); -static void Handle_Store_Double (ARMul_State *, ARMword); - -static int handle_v6_insn (ARMul_State * state, ARMword instr); - -#define LUNSIGNED (0) /* unsigned operation */ -#define LSIGNED (1) /* signed operation */ -#define LDEFAULT (0) /* default : do nothing */ -#define LSCC (1) /* set condition codes on result */ - -/* Short-hand macros for LDR/STR. */ - -/* Store post decrement writeback. */ -#define SHDOWNWB() \ - lhs = LHS ; \ - if (StoreHalfWord (state, instr, lhs)) \ - LSBase = lhs - GetLS7RHS (state, instr); - -/* Store post increment writeback. */ -#define SHUPWB() \ - lhs = LHS ; \ - if (StoreHalfWord (state, instr, lhs)) \ - LSBase = lhs + GetLS7RHS (state, instr); - -/* Store pre decrement. */ -#define SHPREDOWN() \ - (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr)); - -/* Store pre decrement writeback. */ -#define SHPREDOWNWB() \ - temp = LHS - GetLS7RHS (state, instr); \ - if (StoreHalfWord (state, instr, temp)) \ - LSBase = temp; - -/* Store pre increment. */ -#define SHPREUP() \ - (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr)); - -/* Store pre increment writeback. */ -#define SHPREUPWB() \ - temp = LHS + GetLS7RHS (state, instr); \ - if (StoreHalfWord (state, instr, temp)) \ - LSBase = temp; - -/* Load post decrement writeback. */ -#define LHPOSTDOWN() \ -{ \ - int done = 1; \ - lhs = LHS; \ - temp = lhs - GetLS7RHS (state, instr); \ - \ - switch (BITS (5, 6)) \ - { \ - case 1: /* H */ \ - if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \ - LSBase = temp; \ - break; \ - case 2: /* SB */ \ - if (LoadByte (state, instr, lhs, LSIGNED)) \ - LSBase = temp; \ - break; \ - case 3: /* SH */ \ - if (LoadHalfWord (state, instr, lhs, LSIGNED)) \ - LSBase = temp; \ - break; \ - case 0: /* SWP handled elsewhere. */ \ - default: \ - done = 0; \ - break; \ - } \ - if (done) \ - break; \ -} - -/* Load post increment writeback. */ -#define LHPOSTUP() \ -{ \ - int done = 1; \ - lhs = LHS; \ - temp = lhs + GetLS7RHS (state, instr); \ - \ - switch (BITS (5, 6)) \ - { \ - case 1: /* H */ \ - if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \ - LSBase = temp; \ - break; \ - case 2: /* SB */ \ - if (LoadByte (state, instr, lhs, LSIGNED)) \ - LSBase = temp; \ - break; \ - case 3: /* SH */ \ - if (LoadHalfWord (state, instr, lhs, LSIGNED)) \ - LSBase = temp; \ - break; \ - case 0: /* SWP handled elsewhere. */ \ - default: \ - done = 0; \ - break; \ - } \ - if (done) \ - break; \ -} - -/* Load pre decrement. */ -#define LHPREDOWN() \ -{ \ - int done = 1; \ - \ - temp = LHS - GetLS7RHS (state, instr); \ - switch (BITS (5, 6)) \ - { \ - case 1: /* H */ \ - (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \ - break; \ - case 2: /* SB */ \ - (void) LoadByte (state, instr, temp, LSIGNED); \ - break; \ - case 3: /* SH */ \ - (void) LoadHalfWord (state, instr, temp, LSIGNED); \ - break; \ - case 0: \ - /* SWP handled elsewhere. */ \ - default: \ - done = 0; \ - break; \ - } \ - if (done) \ - break; \ -} - -/* Load pre decrement writeback. */ -#define LHPREDOWNWB() \ -{ \ - int done = 1; \ - \ - temp = LHS - GetLS7RHS (state, instr); \ - switch (BITS (5, 6)) \ - { \ - case 1: /* H */ \ - if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \ - LSBase = temp; \ - break; \ - case 2: /* SB */ \ - if (LoadByte (state, instr, temp, LSIGNED)) \ - LSBase = temp; \ - break; \ - case 3: /* SH */ \ - if (LoadHalfWord (state, instr, temp, LSIGNED)) \ - LSBase = temp; \ - break; \ - case 0: \ - /* SWP handled elsewhere. */ \ - default: \ - done = 0; \ - break; \ - } \ - if (done) \ - break; \ -} - -/* Load pre increment. */ -#define LHPREUP() \ -{ \ - int done = 1; \ - \ - temp = LHS + GetLS7RHS (state, instr); \ - switch (BITS (5, 6)) \ - { \ - case 1: /* H */ \ - (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \ - break; \ - case 2: /* SB */ \ - (void) LoadByte (state, instr, temp, LSIGNED); \ - break; \ - case 3: /* SH */ \ - (void) LoadHalfWord (state, instr, temp, LSIGNED); \ - break; \ - case 0: \ - /* SWP handled elsewhere. */ \ - default: \ - done = 0; \ - break; \ - } \ - if (done) \ - break; \ -} - -/* Load pre increment writeback. */ -#define LHPREUPWB() \ -{ \ - int done = 1; \ - \ - temp = LHS + GetLS7RHS (state, instr); \ - switch (BITS (5, 6)) \ - { \ - case 1: /* H */ \ - if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \ - LSBase = temp; \ - break; \ - case 2: /* SB */ \ - if (LoadByte (state, instr, temp, LSIGNED)) \ - LSBase = temp; \ - break; \ - case 3: /* SH */ \ - if (LoadHalfWord (state, instr, temp, LSIGNED)) \ - LSBase = temp; \ - break; \ - case 0: \ - /* SWP handled elsewhere. */ \ - default: \ - done = 0; \ - break; \ - } \ - if (done) \ - break; \ -} - -/* EMULATION of ARM6. */ - -int ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr); -#ifdef MODE32 -//chy 2006-04-12, for ICE debug -int ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr) -{ - return 0; -} - -ARMword ARMul_Debug(ARMul_State * state, ARMword pc, ARMword instr) -{ - return 0; -} - -ARMword ARMul_Emulate32(ARMul_State* state) -#else -ARMword ARMul_Emulate26(ARMul_State* state) -#endif -{ - /* The PC pipeline value depends on whether ARM - or Thumb instructions are being - d. */ - ARMword isize; - ARMword instr; /* The current instruction. */ - ARMword dest = 0; /* Almost the DestBus. */ - ARMword temp; /* Ubiquitous third hand. */ - ARMword pc = 0; /* The address of the current instruction. */ - ARMword lhs; /* Almost the ABus and BBus. */ - ARMword rhs; - ARMword decoded = 0; /* Instruction pipeline. */ - ARMword loaded = 0; - ARMword decoded_addr=0; - ARMword loaded_addr=0; - ARMword have_bp=0; - - /* Execute the next instruction. */ - if (state->NextInstr < PRIMEPIPE) { - decoded = state->decoded; - loaded = state->loaded; - pc = state->pc; - //chy 2006-04-12, for ICE debug - decoded_addr=state->decoded_addr; - loaded_addr=state->loaded_addr; - } - - do { - //print_func_name(state->pc); - /* Just keep going. */ - isize = INSN_SIZE; - - switch (state->NextInstr) { - case SEQ: - /* Advance the pipeline, and an S cycle. */ - state->Reg[15] += isize; - pc += isize; - instr = decoded; - //chy 2006-04-12, for ICE debug - have_bp = ARMul_ICE_debug(state,instr,decoded_addr); - decoded = loaded; - decoded_addr=loaded_addr; - //loaded = ARMul_LoadInstrS (state, pc + (isize * 2), - // isize); - loaded_addr=pc + (isize * 2); - if (have_bp) goto TEST_EMULATE; - break; - - case NONSEQ: - /* Advance the pipeline, and an N cycle. */ - state->Reg[15] += isize; - pc += isize; - instr = decoded; - //chy 2006-04-12, for ICE debug - have_bp=ARMul_ICE_debug(state,instr,decoded_addr); - decoded = loaded; - decoded_addr=loaded_addr; - //loaded = ARMul_LoadInstrN (state, pc + (isize * 2), - // isize); - loaded_addr=pc + (isize * 2); - NORMALCYCLE; - if (have_bp) goto TEST_EMULATE; - break; - - case PCINCEDSEQ: - /* Program counter advanced, and an S cycle. */ - pc += isize; - instr = decoded; - //chy 2006-04-12, for ICE debug - have_bp=ARMul_ICE_debug(state,instr,decoded_addr); - decoded = loaded; - decoded_addr=loaded_addr; - //loaded = ARMul_LoadInstrS (state, pc + (isize * 2), - // isize); - loaded_addr=pc + (isize * 2); - NORMALCYCLE; - if (have_bp) goto TEST_EMULATE; - break; - - case PCINCEDNONSEQ: - /* Program counter advanced, and an N cycle. */ - pc += isize; - instr = decoded; - //chy 2006-04-12, for ICE debug - have_bp=ARMul_ICE_debug(state,instr,decoded_addr); - decoded = loaded; - decoded_addr=loaded_addr; - //loaded = ARMul_LoadInstrN (state, pc + (isize * 2), - // isize); - loaded_addr=pc + (isize * 2); - NORMALCYCLE; - if (have_bp) goto TEST_EMULATE; - break; - - case RESUME: - /* The program counter has been changed. */ - pc = state->Reg[15]; -#ifndef MODE32 - pc = pc & R15PCBITS; -#endif - state->Reg[15] = pc + (isize * 2); - state->Aborted = 0; - //chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU> - state->AbortAddr = 1; - - instr = ARMul_LoadInstrN (state, pc, isize); - //instr = ARMul_ReLoadInstr (state, pc, isize); - //chy 2006-04-12, for ICE debug - have_bp=ARMul_ICE_debug(state,instr,pc); - //decoded = - // ARMul_ReLoadInstr (state, pc + isize, isize); - decoded_addr=pc+isize; - //loaded = ARMul_ReLoadInstr (state, pc + isize * 2, - // isize); - loaded_addr=pc + isize * 2; - NORMALCYCLE; - if (have_bp) goto TEST_EMULATE; - break; - - default: - /* The program counter has been changed. */ - pc = state->Reg[15]; -#ifndef MODE32 - pc = pc & R15PCBITS; -#endif - state->Reg[15] = pc + (isize * 2); - state->Aborted = 0; - //chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU> - state->AbortAddr = 1; - - instr = ARMul_LoadInstrN (state, pc, isize); - - //chy 2006-04-12, for ICE debug - have_bp=ARMul_ICE_debug(state,instr,pc); - - decoded_addr=pc+isize; - - loaded_addr=pc + isize * 2; - NORMALCYCLE; - if (have_bp) goto TEST_EMULATE; - break; - } - - instr = ARMul_LoadInstrN (state, pc, isize); - state->last_instr = state->CurrInstr; - state->CurrInstr = instr; - ARMul_Debug(state, pc, instr); - - /* Any exceptions ? */ - if (state->NresetSig == LOW) { - ARMul_Abort (state, ARMul_ResetV); - break; - } else if (!state->NfiqSig && !FFLAG) { - ARMul_Abort (state, ARMul_FIQV); - break; - } else if (!state->NirqSig && !IFLAG) { - ARMul_Abort (state, ARMul_IRQV); - break; - } - - if (state->Emulate < ONCE) { - state->NextInstr = RESUME; - break; - } - - state->NumInstrs++; - -#ifdef MODET - /* Provide Thumb instruction decoding. If the processor is in Thumb - mode, then we can simply decode the Thumb instruction, and map it - to the corresponding ARM instruction (by directly loading the - instr variable, and letting the normal ARM simulator - execute). There are some caveats to ensure that the correct - pipelined PC value is used when executing Thumb code, and also for - dealing with the BL instruction. */ - if (TFLAG) { - ARMword armOp = 0; - /* Check if in Thumb mode. */ - switch (ARMul_ThumbDecode(state, pc, instr, &armOp)) { - case t_undefined: - /* This is a Thumb instruction. */ - ARMul_UndefInstr (state, instr); - goto donext; - - case t_branch: - /* Already processed. */ - //pc = state->Reg[15] - 2; - //state->pc = state->Reg[15] - 2; //ichfly why do I need that - goto donext; - - case t_decoded: - /* ARM instruction available. */ - //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp); - - if (armOp == 0xDEADC0DE) { - LOG_ERROR(Core_ARM11, "Failed to decode thumb opcode %04X at %08X", instr, pc); - } - - instr = armOp; - - /* So continue instruction decoding. */ - break; - default: - break; - } - } -#endif - /* Check the condition codes. */ - if ((temp = TOPBITS (28)) == AL) { - /* Vile deed in the need for speed. */ - goto mainswitch; - } - - /* Check the condition code. */ - switch ((int) TOPBITS (28)) { - case AL: - temp = TRUE; - break; - case NV: - - /* shenoubang add for armv7 instr dmb 2012-3-11 */ - if (state->is_v7) { - if ((instr & 0x0fffff00) == 0x057ff000) { - switch((instr >> 4) & 0xf) { - case 4: /* dsb */ - case 5: /* dmb */ - case 6: /* isb */ - // TODO: do no implemented thes instr - goto donext; - } - } - } - /* dyf add for armv6 instruct CPS 2010.9.17 */ - if (state->is_v6) { - /* clrex do nothing here temporary */ - if (instr == 0xf57ff01f) { - //printf("clrex \n"); - /* shenoubang 2012-3-14 refer the dyncom_interpreter */ - state->exclusive_tag_array[0] = 0xFFFFFFFF; - state->exclusive_access_state = 0; - goto donext; - } - - if (BITS(20, 27) == 0x10) { - if (BIT(19)) { - if (BIT(8)) { - if (BIT(18)) - state->Cpsr |= 1<<8; - else - state->Cpsr &= ~(1<<8); - } - if (BIT(7)) { - if (BIT(18)) - state->Cpsr |= 1<<7; - else - state->Cpsr &= ~(1<<7); - ASSIGNINT (state->Cpsr & INTBITS); - } - if (BIT(6)) { - if (BIT(18)) - state->Cpsr |= 1<<6; - else - state->Cpsr &= ~(1<<6); - ASSIGNINT (state->Cpsr & INTBITS); - } - } - if (BIT(17)) { - state->Cpsr |= BITS(0, 4); - printf("skyeye test state->Mode\n"); - if (state->Mode != (state->Cpsr & MODEBITS)) { - state->Mode = ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS); - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - } - } - goto donext; - } - } - if (state->is_v5) { - if (BITS (25, 27) == 5) { /* BLX(1) */ - ARMword dest; - - state->Reg[14] = pc + 4; - - /* Force entry into Thumb mode. */ - dest = pc + 8 + 1; - if (BIT (23)) - dest += (NEGBRANCH + - (BIT (24) << 1)); - else - dest += POSBRANCH + - (BIT (24) << 1); - - WriteR15Branch (state, dest); - goto donext; - } else if ((instr & 0xFC70F000) == 0xF450F000) { - /* The PLD instruction. Ignored. */ - goto donext; - } else if (((instr & 0xfe500f00) == 0xfc100100) - || ((instr & 0xfe500f00) == - 0xfc000100)) { - /* wldrw and wstrw are unconditional. */ - goto mainswitch; - } else { - /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */ - ARMul_UndefInstr (state, instr); - } - } - temp = FALSE; - break; - case EQ: - temp = ZFLAG; - break; - case NE: - temp = !ZFLAG; - break; - case VS: - temp = VFLAG; - break; - case VC: - temp = !VFLAG; - break; - case MI: - temp = NFLAG; - break; - case PL: - temp = !NFLAG; - break; - case CS: - temp = CFLAG; - break; - case CC: - temp = !CFLAG; - break; - case HI: - temp = (CFLAG && !ZFLAG); - break; - case LS: - temp = (!CFLAG || ZFLAG); - break; - case GE: - temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG)); - break; - case LT: - temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)); - break; - case GT: - temp = ((!NFLAG && !VFLAG && !ZFLAG) - || (NFLAG && VFLAG && !ZFLAG)); - break; - case LE: - temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) - || ZFLAG; - break; - } /* cc check */ - -//chy 2003-08-24 now #if 0 .... #endif process cp14, cp15.reg14, I disable it... - - /* Actual execution of instructions begins here. */ - /* If the condition codes don't match, stop here. */ - if (temp) { -mainswitch: - - /* shenoubang sbfx and ubfx instr 2012-3-16 */ - if (state->is_v6) { - unsigned int m, lsb, width, Rd, Rn, data; - Rd = Rn = lsb = width = data = m = 0; - - //printf("helloworld\n"); - if ((((int) BITS (21, 27)) == 0x3f) && (((int) BITS (4, 6)) == 0x5)) { - m = (unsigned)BITS(7, 11); - width = (unsigned)BITS(16, 20); - Rd = (unsigned)BITS(12, 15); - Rn = (unsigned)BITS(0, 3); - if ((Rd == 15) || (Rn == 15)) { - ARMul_UndefInstr (state, instr); - } else if ((m + width) < 32) { - data = state->Reg[Rn]; - state->Reg[Rd] ^= state->Reg[Rd]; - state->Reg[Rd] = ((ARMword)(data << (31 -(m + width))) >> ((31 - (m + width)) + (m))); - //SKYEYE_LOG_IN_CLR(RED, "UBFX: In %s, line = %d, Reg_src[%d] = 0x%x, Reg_d[%d] = 0x%x, m = %d, width = %d, Rd = %d, Rn = %d\n", - // __FUNCTION__, __LINE__, Rn, data, Rd, state->Reg[Rd], m, width + 1, Rd, Rn); - goto donext; - } - } // ubfx instr - else if ((((int) BITS (21, 27)) == 0x3d) && (((int) BITS (4, 6)) == 0x5)) { - int tmp = 0; - Rd = BITS(12, 15); - Rn = BITS(0, 3); - lsb = BITS(7, 11); - width = BITS(16, 20); - if ((Rd == 15) || (Rn == 15)) { - ARMul_UndefInstr (state, instr); - } else if ((lsb + width) < 32) { - state->Reg[Rd] ^= state->Reg[Rd]; - data = state->Reg[Rn]; - tmp = (data << (32 - (lsb + width + 1))); - state->Reg[Rd] = (tmp >> (32 - (lsb + width + 1))); - //SKYEYE_LOG_IN_CLR(RED, "sbfx: In %s, line = %d, pc = 0x%x, instr = 0x%x,Rd = 0x%x, Rn = 0x%x, lsb = %d, width = %d, Rs[%d] = 0x%x, Rd[%d] = 0x%x\n", - // __func__, __LINE__, pc, instr, Rd, Rn, lsb, width + 1, Rn, state->Reg[Rn], Rd, state->Reg[Rd]); - goto donext; - } - } // sbfx instr - else if ((((int)BITS(21, 27)) == 0x3e) && ((int)BITS(4, 6) == 0x1)) { - //(ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) - unsigned msb ,tmp_rn, tmp_rd, dst; - tmp_rd = tmp_rn = dst = 0; - Rd = BITS(12, 15); - Rn = BITS(0, 3); - lsb = BITS(7, 11); - msb = BITS(16, 20); //-V519 - if (Rd == 15) { - ARMul_UndefInstr (state, instr); - } else if (Rn == 15) { - data = state->Reg[Rd]; - tmp_rd = ((ARMword)(data << (31 - lsb)) >> (31 - lsb)); - dst = ((data >> msb) << (msb - lsb)); - dst = (dst << lsb) | tmp_rd; - goto donext; - } // bfc instr - else if (((msb >= lsb) && (msb < 32))) { - data = state->Reg[Rn]; - tmp_rn = ((ARMword)(data << (31 - (msb - lsb))) >> (31 - (msb - lsb))); - data = state->Reg[Rd]; - tmp_rd = ((ARMword)(data << (31 - lsb)) >> (31 - lsb)); - dst = ((data >> msb) << (msb - lsb)) | tmp_rn; - dst = (dst << lsb) | tmp_rd; - goto donext; - } // bfi instr - } - } - - switch ((int) BITS (20, 27)) { - /* Data Processing Register RHS Instructions. */ - - case 0x00: /* AND reg and MUL */ -#ifdef MODET - if (BITS (4, 11) == 0xB) { - /* STRH register offset, no write-back, down, post indexed. */ - SHDOWNWB (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - if (BITS (4, 7) == 9) { - /* MUL */ - rhs = state->Reg[MULRHSReg]; - //if (MULLHSReg == MULDESTReg) { - if(0) { /* For armv6, the restriction is removed */ - UNDEF_MULDestEQOp1; - state->Reg[MULDESTReg] = 0; - } else if (MULDESTReg != 15) - state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs; - else - UNDEF_MULPCDest; - - for (dest = 0, temp = 0; dest < 32; - dest++) - if (rhs & (1L << dest)) - temp = dest; - - /* Mult takes this many/2 I cycles. */ - ARMul_Icycles (state, ARMul_MultTable[temp], 0L); - } else { - /* AND reg. */ - rhs = DPRegRHS; - dest = LHS & rhs; - WRITEDEST (dest); - } - break; - - case 0x01: /* ANDS reg and MULS */ -#ifdef MODET - if ((BITS (4, 11) & 0xF9) == 0x9) - /* LDR register offset, no write-back, down, post indexed. */ - LHPOSTDOWN (); - /* Fall through to rest of decoding. */ -#endif - if (BITS (4, 7) == 9) { - /* MULS */ - rhs = state->Reg[MULRHSReg]; - - //if (MULLHSReg == MULDESTReg) { - if(0) { - printf("Something in %d line\n", __LINE__); - UNDEF_WARNING; - UNDEF_MULDestEQOp1; - state->Reg[MULDESTReg] = 0; - CLEARN; - SETZ; - } else if (MULDESTReg != 15) { - dest = state->Reg[MULLHSReg] * rhs; - ARMul_NegZero (state, dest); - state->Reg[MULDESTReg] = dest; - } else - UNDEF_MULPCDest; - - for (dest = 0, temp = 0; dest < 32; - dest++) - if (rhs & (1L << dest)) - temp = dest; - - /* Mult takes this many/2 I cycles. */ - ARMul_Icycles (state, ARMul_MultTable[temp], 0L); - } else { - /* ANDS reg. */ - rhs = DPSRegRHS; - dest = LHS & rhs; - WRITESDEST (dest); - } - break; - - case 0x02: /* EOR reg and MLA */ -#ifdef MODET - if (BITS (4, 11) == 0xB) { - /* STRH register offset, write-back, down, post indexed. */ - SHDOWNWB (); - break; - } -#endif - if (BITS (4, 7) == 9) { /* MLA */ - rhs = state->Reg[MULRHSReg]; -#if 0 - if (MULLHSReg == MULDESTReg) { - UNDEF_MULDestEQOp1; - state->Reg[MULDESTReg] = state->Reg[MULACCReg]; - } else if (MULDESTReg != 15) { -#endif - if (MULDESTReg != 15) { - state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg]; - } else - UNDEF_MULPCDest; - - for (dest = 0, temp = 0; dest < 32; - dest++) - if (rhs & (1L << dest)) - temp = dest; - - /* Mult takes this many/2 I cycles. */ - ARMul_Icycles (state, ARMul_MultTable[temp], 0L); - } else { - rhs = DPRegRHS; - dest = LHS ^ rhs; - WRITEDEST (dest); - } - break; - - case 0x03: /* EORS reg and MLAS */ -#ifdef MODET - if ((BITS (4, 11) & 0xF9) == 0x9) - /* LDR register offset, write-back, down, post-indexed. */ - LHPOSTDOWN (); - /* Fall through to rest of the decoding. */ -#endif - if (BITS (4, 7) == 9) { - /* MLAS */ - rhs = state->Reg[MULRHSReg]; - //if (MULLHSReg == MULDESTReg) { - if (0) { - UNDEF_MULDestEQOp1; - dest = state->Reg[MULACCReg]; - ARMul_NegZero (state, dest); - state->Reg[MULDESTReg] = dest; - } else if (MULDESTReg != 15) { - dest = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg]; - ARMul_NegZero (state, dest); - state->Reg[MULDESTReg] = dest; - } else - UNDEF_MULPCDest; - - for (dest = 0, temp = 0; dest < 32; - dest++) - if (rhs & (1L << dest)) - temp = dest; - - /* Mult takes this many/2 I cycles. */ - ARMul_Icycles (state, ARMul_MultTable[temp], 0L); - } else { - /* EORS Reg. */ - rhs = DPSRegRHS; - dest = LHS ^ rhs; - WRITESDEST (dest); - } - break; - - case 0x04: /* SUB reg */ - // Signifies UMAAL - if (state->is_v6 && BITS(4, 7) == 0x09) { - if (handle_v6_insn(state, instr)) - break; - } - -#ifdef MODET - if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, no write-back, down, post indexed. */ - SHDOWNWB (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - rhs = DPRegRHS; - dest = LHS - rhs; - WRITEDEST (dest); - break; - - case 0x05: /* SUBS reg */ -#ifdef MODET - if ((BITS (4, 7) & 0x9) == 0x9) - /* LDR immediate offset, no write-back, down, post indexed. */ - LHPOSTDOWN (); - /* Fall through to the rest of the instruction decoding. */ -#endif - lhs = LHS; - rhs = DPRegRHS; - dest = lhs - rhs; - - if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, lhs, rhs, dest); - ARMul_SubOverflow (state, lhs, rhs, dest); - } else { - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x06: /* RSB reg */ -#ifdef MODET - if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, write-back, down, post indexed. */ - SHDOWNWB (); - break; - } -#endif - rhs = DPRegRHS; - dest = rhs - LHS; - WRITEDEST (dest); - break; - - case 0x07: /* RSBS reg */ -#ifdef MODET - if ((BITS (4, 7) & 0x9) == 0x9) - /* LDR immediate offset, write-back, down, post indexed. */ - LHPOSTDOWN (); - /* Fall through to remainder of instruction decoding. */ -#endif - lhs = LHS; - rhs = DPRegRHS; - dest = rhs - lhs; - - if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, rhs, lhs, dest); - ARMul_SubOverflow (state, rhs, lhs, dest); - } else { - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x08: /* ADD reg */ -#ifdef MODET - if (BITS (4, 11) == 0xB) { - /* STRH register offset, no write-back, up, post indexed. */ - SHUPWB (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif -#ifdef MODET - if (BITS (4, 7) == 0x9) { - /* MULL */ - /* 32x32 = 64 */ - ARMul_Icycles (state, Multiply64 (state, instr, LUNSIGNED, LDEFAULT), 0L); - break; - } -#endif - rhs = DPRegRHS; - dest = LHS + rhs; - WRITEDEST (dest); - break; - - case 0x09: /* ADDS reg */ -#ifdef MODET - if ((BITS (4, 11) & 0xF9) == 0x9) - /* LDR register offset, no write-back, up, post indexed. */ - LHPOSTUP (); - /* Fall through to remaining instruction decoding. */ -#endif -#ifdef MODET - if (BITS (4, 7) == 0x9) { - /* MULL */ - /* 32x32=64 */ - ARMul_Icycles (state, Multiply64 (state, instr, LUNSIGNED, LSCC), 0L); - break; - } -#endif - lhs = LHS; - rhs = DPRegRHS; - dest = lhs + rhs; - ASSIGNZ (dest == 0); - if ((lhs | rhs) >> 30) { - /* Possible C,V,N to set. */ - ASSIGNN (NEG (dest)); - ARMul_AddCarry (state, lhs, rhs, dest); - ARMul_AddOverflow (state, lhs, rhs, dest); - } else { - CLEARN; - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x0a: /* ADC reg */ -#ifdef MODET - if (BITS (4, 11) == 0xB) { - /* STRH register offset, write-back, up, post-indexed. */ - SHUPWB (); - break; - } - if (BITS (4, 7) == 0x9) { - /* MULL */ - /* 32x32=64 */ - ARMul_Icycles (state, MultiplyAdd64 (state, instr, LUNSIGNED, LDEFAULT), 0L); - break; - } -#endif - rhs = DPRegRHS; - dest = LHS + rhs + CFLAG; - WRITEDEST (dest); - break; - - case 0x0b: /* ADCS reg */ -#ifdef MODET - if ((BITS (4, 11) & 0xF9) == 0x9) - /* LDR register offset, write-back, up, post indexed. */ - LHPOSTUP (); - /* Fall through to remaining instruction decoding. */ - if (BITS (4, 7) == 0x9) { - /* MULL */ - /* 32x32=64 */ - ARMul_Icycles (state, MultiplyAdd64 (state, instr, LUNSIGNED, LSCC), 0L); - break; - } -#endif - lhs = LHS; - rhs = DPRegRHS; - dest = lhs + rhs + CFLAG; - ASSIGNZ (dest == 0); - if ((lhs | rhs) >> 30) { - /* Possible C,V,N to set. */ - ASSIGNN (NEG (dest)); - ARMul_AddCarry (state, lhs, rhs, dest); - ARMul_AddOverflow (state, lhs, rhs, dest); - } else { - CLEARN; - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x0c: /* SBC reg */ -#ifdef MODET - if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, no write-back, up post indexed. */ - SHUPWB (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } - if (BITS (4, 7) == 0x9) { - /* MULL */ - /* 32x32=64 */ - ARMul_Icycles (state, Multiply64 (state, instr, LSIGNED, LDEFAULT), 0L); - break; - } -#endif - rhs = DPRegRHS; - dest = LHS - rhs - !CFLAG; - WRITEDEST (dest); - break; - - case 0x0d: /* SBCS reg */ -#ifdef MODET - if ((BITS (4, 7) & 0x9) == 0x9) - /* LDR immediate offset, no write-back, up, post indexed. */ - LHPOSTUP (); - - if (BITS (4, 7) == 0x9) { - /* MULL */ - /* 32x32=64 */ - ARMul_Icycles (state, Multiply64 (state, instr, LSIGNED, LSCC), 0L); - break; - } -#endif - lhs = LHS; - rhs = DPRegRHS; - dest = lhs - rhs - !CFLAG; - if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, lhs, rhs, dest); - ARMul_SubOverflow (state, lhs, rhs, dest); - } else { - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x0e: /* RSC reg */ -#ifdef MODET - if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, write-back, up, post indexed. */ - SHUPWB (); - break; - } - - if (BITS (4, 7) == 0x9) { - /* MULL */ - /* 32x32=64 */ - ARMul_Icycles (state, MultiplyAdd64 (state, instr, LSIGNED, LDEFAULT), 0L); - break; - } -#endif - rhs = DPRegRHS; - dest = rhs - LHS - !CFLAG; - WRITEDEST (dest); - break; - - case 0x0f: /* RSCS reg */ -#ifdef MODET - if ((BITS (4, 7) & 0x9) == 0x9) - /* LDR immediate offset, write-back, up, post indexed. */ - LHPOSTUP (); - /* Fall through to remaining instruction decoding. */ - - if (BITS (4, 7) == 0x9) { - /* MULL */ - /* 32x32=64 */ - ARMul_Icycles (state, MultiplyAdd64 (state, instr, LSIGNED, LSCC), 0L); - break; - } -#endif - lhs = LHS; - rhs = DPRegRHS; - dest = rhs - lhs - !CFLAG; - - if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, rhs, lhs, dest); - ARMul_SubOverflow (state, rhs, lhs, dest); - } else { - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x10: /* TST reg and MRS CPSR and SWP word. */ - if (state->is_v5e) { - if (BIT (4) == 0 && BIT (7) == 1) { - /* ElSegundo SMLAxy insn. */ - ARMword op1 = state->Reg[BITS (0, 3)]; - ARMword op2 = state->Reg[BITS (8, 11)]; - ARMword Rn = state->Reg[BITS (12, 15)]; - - if (BIT (5)) - op1 >>= 16; - if (BIT (6)) - op2 >>= 16; - op1 &= 0xFFFF; - op2 &= 0xFFFF; - if (op1 & 0x8000) - op1 -= 65536; - if (op2 & 0x8000) - op2 -= 65536; - op1 *= op2; - //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn); - if (AddOverflow(op1, Rn, op1 + Rn)) - SETQ; - state->Reg[BITS (16, 19)] = op1 + Rn; - break; - } - - if (BITS (4, 11) == 5) { - /* ElSegundo QADD insn. */ - ARMword op1 = state->Reg[BITS (0, 3)]; - ARMword op2 = state->Reg[BITS (16, 19)]; - ARMword result = op1 + op2; - if (AddOverflow(op1, op2, result)) { - result = POS (result) ? 0x80000000 : 0x7fffffff; - SETQ; - } - state->Reg[BITS (12, 15)] = result; - break; - } - } -#ifdef MODET - if (BITS (4, 11) == 0xB) { - /* STRH register offset, no write-back, down, pre indexed. */ - SHPREDOWN (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - if (BITS (4, 11) == 9) { - /* SWP */ - UNDEF_SWPPC; - temp = LHS; - BUSUSEDINCPCS; -#ifndef MODE32 - if (VECTORACCESS (temp) || ADDREXCEPT (temp)) { - INTERNALABORT (temp); - (void) ARMul_LoadWordN (state, temp); - (void) ARMul_LoadWordN (state, temp); - } else -#endif - dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]); - if (temp & 3) - DEST = ARMul_Align (state, temp, dest); - else - DEST = dest; - if (state->abortSig || state->Aborted) - TAKEABORT; - } else if ((BITS (0, 11) == 0) && (LHSReg == 15)) { /* MRS CPSR */ - UNDEF_MRSPC; - DEST = ARMul_GetCPSR(state); - } else { - UNDEF_Test; - } - break; - - case 0x11: /* TSTP reg */ -#ifdef MODET - if ((BITS (4, 11) & 0xF9) == 0x9) - /* LDR register offset, no write-back, down, pre indexed. */ - LHPREDOWN (); - /* Continue with remaining instruction decode. */ -#endif - if (DESTReg == 15) { - /* TSTP reg */ -#ifdef MODE32 - //chy 2006-02-15 if in user mode, can not set cpsr 0:23 - //from p165 of ARMARM book - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); -#else - rhs = DPRegRHS; - temp = LHS & rhs; - SETR15PSR (temp); -#endif - } else { - /* TST reg */ - rhs = DPSRegRHS; - dest = LHS & rhs; - ARMul_NegZero (state, dest); - } - break; - - case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */ - - if (state->is_v5) { - if (BITS (4, 7) == 3) { - /* BLX(2) */ - ARMword temp; - - if (TFLAG) - temp = (pc + 2) | 1; - else - temp = pc + 4; - - WriteR15Branch (state, state->Reg[RHSReg]); - state->Reg[14] = temp; - break; - } - } - - if (state->is_v5e) { - if (BIT (4) == 0 && BIT (7) == 1 && (BIT (5) == 0 || BITS (12, 15) == 0)) { - /* ElSegundo SMLAWy/SMULWy insn. */ - unsigned long long op1 = state->Reg[BITS (0, 3)]; - unsigned long long op2 = state->Reg[BITS (8, 11)]; - unsigned long long result; - - if (BIT (6)) - op2 >>= 16; - if (op1 & 0x80000000) - op1 -= 1ULL << 32; - op2 &= 0xFFFF; - if (op2 & 0x8000) - op2 -= 65536; - result = (op1 * op2) >> 16; - - if (BIT (5) == 0) { - ARMword Rn = state->Reg[BITS(12, 15)]; - - if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn))) - SETQ; - result += Rn; - } - state->Reg[BITS (16, 19)] = (ARMword)result; - break; - } - - if (BITS (4, 11) == 5) { - /* ElSegundo QSUB insn. */ - ARMword op1 = state->Reg[BITS (0, 3)]; - ARMword op2 = state->Reg[BITS (16, 19)]; - ARMword result = op1 - op2; - - if (SubOverflow - (op1, op2, result)) { - result = POS (result) ? 0x80000000 : 0x7fffffff; - SETQ; - } - - state->Reg[BITS (12, 15)] = result; - break; - } - } -#ifdef MODET - if (BITS (4, 11) == 0xB) { - /* STRH register offset, write-back, down, pre indexed. */ - SHPREDOWNWB (); - break; - } - if (BITS (4, 27) == 0x12FFF1) { - /* BX */ - WriteR15Branch (state, state->Reg[RHSReg]); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - if (state->is_v5) { - if (BITS (4, 7) == 0x7) { - //ARMword value; - //extern int SWI_vector_installed; - - /* Hardware is allowed to optionally override this - instruction and treat it as a breakpoint. Since - this is a simulator not hardware, we take the position - that if a SWI vector was not installed, then an Abort - vector was probably not installed either, and so - normally this instruction would be ignored, even if an - Abort is generated. This is a bad thing, since GDB - uses this instruction for its breakpoints (at least in - Thumb mode it does). So intercept the instruction here - and generate a breakpoint SWI instead. */ - /* Force the next instruction to be refetched. */ - state->NextInstr = RESUME; - break; - } - } - if (DESTReg == 15) { - /* MSR reg to CPSR. */ - UNDEF_MSRPC; - temp = DPRegRHS; -#ifdef MODET - /* Don't allow TBIT to be set by MSR. */ - temp &= ~TBIT; -#endif - ARMul_FixCPSR (state, instr, temp); - } else - UNDEF_Test; - - break; - - case 0x13: /* TEQP reg */ -#ifdef MODET - if ((BITS (4, 11) & 0xF9) == 0x9) - /* LDR register offset, write-back, down, pre indexed. */ - LHPREDOWNWB (); - /* Continue with remaining instruction decode. */ -#endif - if (DESTReg == 15) { - /* TEQP reg */ -#ifdef MODE32 - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); -#else - rhs = DPRegRHS; - temp = LHS ^ rhs; - SETR15PSR (temp); -#endif - } else { - /* TEQ Reg. */ - rhs = DPSRegRHS; - dest = LHS ^ rhs; - ARMul_NegZero (state, dest); - } - break; - - case 0x14: /* CMP reg and MRS SPSR and SWP byte. */ - if (state->is_v5e) { - if (BIT (4) == 0 && BIT (7) == 1) { - /* ElSegundo SMLALxy insn. */ - unsigned long long op1 = state->Reg[BITS (0, 3)]; - unsigned long long op2 = state->Reg[BITS (8, 11)]; - unsigned long long dest; - //unsigned long long result; - - if (BIT (5)) - op1 >>= 16; - if (BIT (6)) - op2 >>= 16; - op1 &= 0xFFFF; - if (op1 & 0x8000) - op1 -= 65536; - op2 &= 0xFFFF; - if (op2 & 0x8000) - op2 -= 65536; - - dest = (unsigned long long) state->Reg[BITS (16, 19)] << 32; - dest |= state->Reg[BITS (12, 15)]; - dest += op1 * op2; - state->Reg[BITS(12, 15)] = (ARMword)dest; - state->Reg[BITS(16, 19)] = (ARMword)(dest >> 32); - break; - } - - if (BITS (4, 11) == 5) { - /* ElSegundo QDADD insn. */ - ARMword op1 = state->Reg[BITS (0, 3)]; - ARMword op2 = state->Reg[BITS (16, 19)]; - ARMword op2d = op2 + op2; - ARMword result; - - if (AddOverflow - (op2, op2, op2d)) { - SETQ; - op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; - } - - result = op1 + op2d; - if (AddOverflow(op1, op2d, result)) { - SETQ; - result = POS (result) ? 0x80000000 : 0x7fffffff; - } - - state->Reg[BITS (12, 15)] = result; - break; - } - } -#ifdef MODET - if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, no write-back, down, pre indexed. */ - SHPREDOWN (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - if (BITS (4, 11) == 9) { - /* SWP */ - UNDEF_SWPPC; - temp = LHS; - BUSUSEDINCPCS; -#ifndef MODE32 - if (VECTORACCESS (temp) || ADDREXCEPT (temp)) { - INTERNALABORT (temp); - (void) ARMul_LoadByte (state, temp); - (void) ARMul_LoadByte (state, temp); - } else -#endif - DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]); - if (state->abortSig || state->Aborted) - TAKEABORT; - } else if ((BITS (0, 11) == 0) - && (LHSReg == 15)) { - /* MRS SPSR */ - UNDEF_MRSPC; - DEST = GETSPSR (state->Bank); - } else - UNDEF_Test; - - break; - - case 0x15: /* CMPP reg. */ -#ifdef MODET - if ((BITS (4, 7) & 0x9) == 0x9) - /* LDR immediate offset, no write-back, down, pre indexed. */ - LHPREDOWN (); - /* Continue with remaining instruction decode. */ -#endif - if (DESTReg == 15) { - /* CMPP reg. */ -#ifdef MODE32 - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); -#else - rhs = DPRegRHS; - temp = LHS - rhs; - SETR15PSR (temp); -#endif - } else { - /* CMP reg. */ - lhs = LHS; - rhs = DPRegRHS; - dest = lhs - rhs; - ARMul_NegZero (state, dest); - if ((lhs >= rhs) - || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, lhs, rhs, dest); - ARMul_SubOverflow (state, lhs, rhs, dest); - } else { - CLEARC; - CLEARV; - } - } - break; - - case 0x16: /* CMN reg and MSR reg to SPSR */ - if (state->is_v5e) { - if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0) { - /* ElSegundo SMULxy insn. */ - ARMword op1 = state->Reg[BITS (0, 3)]; - ARMword op2 = state->Reg[BITS (8, 11)]; - ARMword Rn = state->Reg[BITS (12, 15)]; - - if (BIT (5)) - op1 >>= 16; - if (BIT (6)) - op2 >>= 16; - op1 &= 0xFFFF; - op2 &= 0xFFFF; - if (op1 & 0x8000) - op1 -= 65536; - if (op2 & 0x8000) - op2 -= 65536; - - state->Reg[BITS (16, 19)] = op1 * op2; - break; - } - - if (BITS (4, 11) == 5) { - /* ElSegundo QDSUB insn. */ - ARMword op1 = state->Reg[BITS (0, 3)]; - ARMword op2 = state->Reg[BITS (16, 19)]; - ARMword op2d = op2 + op2; - ARMword result; - - if (AddOverflow(op2, op2, op2d)) { - SETQ; - op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; - } - - result = op1 - op2d; - if (SubOverflow(op1, op2d, result)) { - SETQ; - result = POS (result) ? 0x80000000 : 0x7fffffff; - } - - state->Reg[BITS (12, 15)] = result; - break; - } - } - - if (state->is_v5) { - if (BITS (4, 11) == 0xF1 - && BITS (16, 19) == 0xF) { - /* ARM5 CLZ insn. */ - ARMword op1 = state->Reg[BITS (0, 3)]; - int result = 32; - - if (op1) - for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1) - result++; - state->Reg[BITS (12, 15)] = result; - break; - } - } - -#ifdef MODET - if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, write-back, down, pre indexed. */ - SHPREDOWNWB (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - if (DESTReg == 15) { - /* MSR */ - UNDEF_MSRPC; - /*ARMul_FixSPSR (state, instr, - DPRegRHS);*/ - } else { - UNDEF_Test; - } - break; - - case 0x17: /* CMNP reg */ -#ifdef MODET - if ((BITS (4, 7) & 0x9) == 0x9) - /* LDR immediate offset, write-back, down, pre indexed. */ - LHPREDOWNWB (); - /* Continue with remaining instruction decoding. */ -#endif - if (DESTReg == 15) { -#ifdef MODE32 - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); -#else - rhs = DPRegRHS; - temp = LHS + rhs; - SETR15PSR (temp); -#endif - break; - } else { - /* CMN reg. */ - lhs = LHS; - rhs = DPRegRHS; - dest = lhs + rhs; - ASSIGNZ (dest == 0); - if ((lhs | rhs) >> 30) { - /* Possible C,V,N to set. */ - ASSIGNN (NEG (dest)); - ARMul_AddCarry (state, lhs, rhs, dest); - ARMul_AddOverflow (state, lhs, rhs, dest); - } else { - CLEARN; - CLEARC; - CLEARV; - } - } - break; - - case 0x18: /* ORR reg */ -#ifdef MODET - /* dyf add armv6 instr strex 2010.9.17 */ - if (state->is_v6) { - if (BITS (4, 7) == 0x9) - if (handle_v6_insn (state, instr)) - break; - } - - if (BITS (4, 11) == 0xB) { - /* STRH register offset, no write-back, up, pre indexed. */ - SHPREUP (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - rhs = DPRegRHS; - dest = LHS | rhs; - WRITEDEST (dest); - break; - - case 0x19: /* ORRS reg */ -#ifdef MODET - /* dyf add armv6 instr ldrex */ - if (state->is_v6) { - if (BITS (4, 7) == 0x9) { - if (handle_v6_insn (state, instr)) - break; - } - } - if ((BITS (4, 11) & 0xF9) == 0x9) - /* LDR register offset, no write-back, up, pre indexed. */ - LHPREUP (); - /* Continue with remaining instruction decoding. */ -#endif - rhs = DPSRegRHS; - dest = LHS | rhs; - WRITESDEST (dest); - break; - - case 0x1a: /* MOV reg */ -#ifdef MODET - if (BITS (4, 11) == 0xB) { - /* STRH register offset, write-back, up, pre indexed. */ - SHPREUPWB (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } - if (BITS(4, 11) == 0xF9) { //strexd - u32 l = LHSReg; - - bool enter = false; - - if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr)&& - state->currentexvald == (u32)ARMul_ReadWord(state, state->currentexaddr + 4)) - enter = true; - - //todo bug this and STREXD and LDREXD http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360e/CHDGJGGC.html - - if (enter) { - ARMul_StoreWordN(state, LHS, state->Reg[RHSReg]); - ARMul_StoreWordN(state,LHS + 4 , state->Reg[RHSReg + 1]); - state->Reg[DESTReg] = 0; - } else { - state->Reg[DESTReg] = 1; - } - - break; - } -#endif - dest = DPRegRHS; - WRITEDEST (dest); - break; - - case 0x1B: /* MOVS reg */ -#ifdef MODET - /* ldrexd ichfly */ - if (BITS(0, 11) == 0xF9F) { //strexd - lhs = LHS; - - state->currentexaddr = lhs; - state->currentexval = (u32)ARMul_ReadWord(state, lhs); - state->currentexvald = (u32)ARMul_ReadWord(state, lhs + 4); - - state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs); - state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs + 4); - break; - } - - if ((BITS (4, 11) & 0xF9) == 0x9) - /* LDR register offset, write-back, up, pre indexed. */ - LHPREUPWB (); - /* Continue with remaining instruction decoding. */ - -#endif - dest = DPSRegRHS; - WRITESDEST (dest); - break; - - case 0x1c: /* BIC reg */ -#ifdef MODET - /* dyf add for STREXB */ - if (state->is_v6) { - if (BITS (4, 7) == 0x9) { - if (handle_v6_insn (state, instr)) - break; - } - } - if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, no write-back, up, pre indexed. */ - SHPREUP (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } else if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - rhs = DPRegRHS; - dest = LHS & ~rhs; - WRITEDEST (dest); - break; - - case 0x1d: /* BICS reg */ -#ifdef MODET - /* ladsh P=1 U=1 W=0 L=1 S=1 H=1 */ - if (BITS(4, 7) == 0xF) { - temp = LHS + GetLS7RHS (state, instr); - LoadHalfWord (state, instr, temp, LSIGNED); - break; - } - if (BITS (4, 7) == 0xb) { - /* LDRH immediate offset, no write-back, up, pre indexed. */ - temp = LHS + GetLS7RHS (state, instr); - LoadHalfWord (state, instr, temp, LUNSIGNED); - break; - } - if (BITS (4, 7) == 0xd) { - // alex-ykl fix: 2011-07-20 missing ldrsb instruction - temp = LHS + GetLS7RHS (state, instr); - LoadByte (state, instr, temp, LSIGNED); - break; - } - - /* Continue with instruction decoding. */ - /*if ((BITS (4, 7) & 0x9) == 0x9) */ - if ((BITS (4, 7)) == 0x9) { - /* ldrexb */ - if (state->is_v6) { - if (handle_v6_insn (state, instr)) - break; - } - /* LDR immediate offset, no write-back, up, pre indexed. */ - LHPREUP (); - } - -#endif - rhs = DPSRegRHS; - dest = LHS & ~rhs; - WRITESDEST (dest); - break; - - case 0x1e: /* MVN reg */ -#ifdef MODET - if ((instr & 0x00000FF0) == 0x00000F90) { //if ((instr & 0x0FF00FF0) == 0x01e00f90) { //todo make that better ichfly - /* strexh ichfly */ - u32 l = LHSReg; - u32 r = RHSReg; - lhs = LHS; - - bool enter = false; - - if (state->currentexval == (u32)ARMul_LoadHalfWord(state, state->currentexaddr))enter = true; - - //StoreWord(state, lhs, RHS) - if (state->Aborted) { - TAKEABORT; - } - if (enter) { - ARMul_StoreHalfWord(state, lhs, RHS); - state->Reg[DESTReg] = 0; - } else { - state->Reg[DESTReg] = 1; - } - break; - } - if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, write-back, up, pre indexed. */ - SHPREUPWB (); - break; - } - if (BITS (4, 7) == 0xD) { - Handle_Load_Double (state, instr); - break; - } - if (BITS (4, 7) == 0xF) { - Handle_Store_Double (state, instr); - break; - } -#endif - dest = ~DPRegRHS; - WRITEDEST (dest); - break; - - case 0x1f: /* MVNS reg */ -#ifdef MODET - - if ((instr & 0x00000FF0) == 0x00000F90) { //(instr & 0x0FF00FF0) == 0x01f00f90)//if ((instr & 0x0FF00FF0) == 0x01f00f90) { - /* ldrexh ichfly */ - lhs = LHS; - - state->currentexaddr = lhs; - state->currentexval = (u32)ARMul_LoadHalfWord(state, lhs); - - LoadHalfWord(state, instr, lhs,0); - break; - } - - if ((BITS (4, 7) & 0x9) == 0x9) - /* LDR immediate offset, write-back, up, pre indexed. */ - LHPREUPWB (); - /* Continue instruction decoding. */ -#endif - dest = ~DPSRegRHS; - WRITESDEST (dest); - break; - - /* Data Processing Immediate RHS Instructions. */ - - case 0x20: /* AND immed */ - dest = LHS & DPImmRHS; - WRITEDEST (dest); - break; - - case 0x21: /* ANDS immed */ - DPSImmRHS; - dest = LHS & rhs; - WRITESDEST (dest); - break; - - case 0x22: /* EOR immed */ - dest = LHS ^ DPImmRHS; - WRITEDEST (dest); - break; - - case 0x23: /* EORS immed */ - DPSImmRHS; - dest = LHS ^ rhs; - WRITESDEST (dest); - break; - - case 0x24: /* SUB immed */ - dest = LHS - DPImmRHS; - WRITEDEST (dest); - break; - - case 0x25: /* SUBS immed */ - lhs = LHS; - rhs = DPImmRHS; - dest = lhs - rhs; - - if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, lhs, rhs, dest); - ARMul_SubOverflow (state, lhs, rhs, dest); - } else { - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x26: /* RSB immed */ - dest = DPImmRHS - LHS; - WRITEDEST (dest); - break; - - case 0x27: /* RSBS immed */ - lhs = LHS; - rhs = DPImmRHS; - dest = rhs - lhs; - - if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, rhs, lhs, dest); - ARMul_SubOverflow (state, rhs, lhs, dest); - } else { - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x28: /* ADD immed */ - dest = LHS + DPImmRHS; - WRITEDEST (dest); - break; - - case 0x29: /* ADDS immed */ - lhs = LHS; - rhs = DPImmRHS; - dest = lhs + rhs; - ASSIGNZ (dest == 0); - - if ((lhs | rhs) >> 30) { - /* Possible C,V,N to set. */ - ASSIGNN (NEG (dest)); - ARMul_AddCarry (state, lhs, rhs, dest); - ARMul_AddOverflow (state, lhs, rhs, dest); - } else { - CLEARN; - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x2a: /* ADC immed */ - dest = LHS + DPImmRHS + CFLAG; - WRITEDEST (dest); - break; - - case 0x2b: /* ADCS immed */ - lhs = LHS; - rhs = DPImmRHS; - dest = lhs + rhs + CFLAG; - ASSIGNZ (dest == 0); - if ((lhs | rhs) >> 30) { - /* Possible C,V,N to set. */ - ASSIGNN (NEG (dest)); - ARMul_AddCarry (state, lhs, rhs, dest); - ARMul_AddOverflow (state, lhs, rhs, dest); - } else { - CLEARN; - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x2c: /* SBC immed */ - dest = LHS - DPImmRHS - !CFLAG; - WRITEDEST (dest); - break; - - case 0x2d: /* SBCS immed */ - lhs = LHS; - rhs = DPImmRHS; - dest = lhs - rhs - !CFLAG; - if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, lhs, rhs, dest); - ARMul_SubOverflow (state, lhs, rhs, dest); - } else { - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x2e: /* RSC immed */ - dest = DPImmRHS - LHS - !CFLAG; - WRITEDEST (dest); - break; - - case 0x2f: /* RSCS immed */ - lhs = LHS; - rhs = DPImmRHS; - dest = rhs - lhs - !CFLAG; - if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, rhs, lhs, dest); - ARMul_SubOverflow (state, rhs, lhs, dest); - } else { - CLEARC; - CLEARV; - } - WRITESDEST (dest); - break; - - case 0x30: /* TST immed */ - /* shenoubang 2012-3-14*/ - if (state->is_v6) { /* movw, ARMV6, ARMv7 */ - dest ^= dest; - dest = BITS(16, 19); - dest = ((dest<<12) | BITS(0, 11)); - WRITEDEST(dest); - break; - } else { - UNDEF_Test; - break; - } - - case 0x31: /* TSTP immed */ - if (DESTReg == 15) { - /* TSTP immed. */ -#ifdef MODE32 - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); -#else - temp = LHS & DPImmRHS; - SETR15PSR (temp); -#endif - } else { - /* TST immed. */ - DPSImmRHS; - dest = LHS & rhs; - ARMul_NegZero (state, dest); - } - break; - - case 0x32: /* TEQ immed and MSR immed to CPSR */ - if (DESTReg == 15) - /* MSR immed to CPSR. */ - ARMul_FixCPSR (state, instr, - DPImmRHS); - else - UNDEF_Test; - break; - - case 0x33: /* TEQP immed */ - if (DESTReg == 15) { - /* TEQP immed. */ -#ifdef MODE32 - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); -#else - temp = LHS ^ DPImmRHS; - SETR15PSR (temp); -#endif - } else { - DPSImmRHS; /* TEQ immed */ - dest = LHS ^ rhs; - ARMul_NegZero (state, dest); - } - break; - - case 0x34: /* CMP immed */ - UNDEF_Test; - break; - - case 0x35: /* CMPP immed */ - if (DESTReg == 15) { - /* CMPP immed. */ -#ifdef MODE32 - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); -#else - temp = LHS - DPImmRHS; - SETR15PSR (temp); -#endif - break; - } else { - /* CMP immed. */ - lhs = LHS; - rhs = DPImmRHS; - dest = lhs - rhs; - ARMul_NegZero (state, dest); - - if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { - ARMul_SubCarry (state, lhs, rhs, dest); - ARMul_SubOverflow (state, lhs, rhs, dest); - } else { - CLEARC; - CLEARV; - } - } - break; - - case 0x36: /* CMN immed and MSR immed to SPSR */ - //if (DESTReg == 15) - /*ARMul0_FixSPSR (state, instr, - DPImmRHS);*/ - //else - UNDEF_Test; - break; - - case 0x37: /* CMNP immed. */ - if (DESTReg == 15) { - /* CMNP immed. */ -#ifdef MODE32 - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); -#else - temp = LHS + DPImmRHS; - SETR15PSR (temp); -#endif - break; - } else { - /* CMN immed. */ - lhs = LHS; - rhs = DPImmRHS; - dest = lhs + rhs; - ASSIGNZ (dest == 0); - if ((lhs | rhs) >> 30) { - /* Possible C,V,N to set. */ - ASSIGNN (NEG (dest)); - ARMul_AddCarry (state, lhs, rhs, dest); - ARMul_AddOverflow (state, lhs, rhs, dest); - } else { - CLEARN; - CLEARC; - CLEARV; - } - } - break; - - case 0x38: /* ORR immed. */ - dest = LHS | DPImmRHS; - WRITEDEST (dest); - break; - - case 0x39: /* ORRS immed. */ - DPSImmRHS; - dest = LHS | rhs; - WRITESDEST (dest); - break; - - case 0x3a: /* MOV immed. */ - dest = DPImmRHS; - WRITEDEST (dest); - break; - - case 0x3b: /* MOVS immed. */ - DPSImmRHS; - WRITESDEST (rhs); - break; - - case 0x3c: /* BIC immed. */ - dest = LHS & ~DPImmRHS; - WRITEDEST (dest); - break; - - case 0x3d: /* BICS immed. */ - DPSImmRHS; - dest = LHS & ~rhs; - WRITESDEST (dest); - break; - - case 0x3e: /* MVN immed. */ - dest = ~DPImmRHS; - WRITEDEST (dest); - break; - - case 0x3f: /* MVNS immed. */ - DPSImmRHS; - WRITESDEST (~rhs); - break; - - /* Single Data Transfer Immediate RHS Instructions. */ - - case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */ - lhs = LHS; - if (StoreWord (state, instr, lhs)) - LSBase = lhs - LSImmRHS; - break; - - case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */ - lhs = LHS; - if (LoadWord (state, instr, lhs)) - LSBase = lhs - LSImmRHS; - break; - - case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - lhs = LHS; - temp = lhs - LSImmRHS; - state->NtransSig = LOW; - if (StoreWord (state, instr, lhs)) - LSBase = temp; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - lhs = LHS; - state->NtransSig = LOW; - if (LoadWord (state, instr, lhs)) - LSBase = lhs - LSImmRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */ - lhs = LHS; - if (StoreByte (state, instr, lhs)) - LSBase = lhs - LSImmRHS; - break; - - case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */ - lhs = LHS; - if (LoadByte (state, instr, lhs, LUNSIGNED)) - LSBase = lhs - LSImmRHS; - break; - - case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - lhs = LHS; - state->NtransSig = LOW; - if (StoreByte (state, instr, lhs)) - LSBase = lhs - LSImmRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - lhs = LHS; - state->NtransSig = LOW; - if (LoadByte (state, instr, lhs, LUNSIGNED)) - LSBase = lhs - LSImmRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */ - lhs = LHS; - if (StoreWord (state, instr, lhs)) - LSBase = lhs + LSImmRHS; - break; - - case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */ - lhs = LHS; - if (LoadWord (state, instr, lhs)) - LSBase = lhs + LSImmRHS; - break; - - case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - lhs = LHS; - state->NtransSig = LOW; - if (StoreWord (state, instr, lhs)) - LSBase = lhs + LSImmRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - lhs = LHS; - state->NtransSig = LOW; - if (LoadWord (state, instr, lhs)) - LSBase = lhs + LSImmRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */ - lhs = LHS; - if (StoreByte (state, instr, lhs)) - LSBase = lhs + LSImmRHS; - break; - - case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */ - lhs = LHS; - if (LoadByte (state, instr, lhs, LUNSIGNED)) - LSBase = lhs + LSImmRHS; - break; - - case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - lhs = LHS; - state->NtransSig = LOW; - if (StoreByte (state, instr, lhs)) - LSBase = lhs + LSImmRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - lhs = LHS; - state->NtransSig = LOW; - if (LoadByte (state, instr, lhs, LUNSIGNED)) - LSBase = lhs + LSImmRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */ - (void) StoreWord (state, instr, LHS - LSImmRHS); - break; - - case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */ - (void) LoadWord (state, instr, LHS - LSImmRHS); - break; - - case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - temp = LHS - LSImmRHS; - if (StoreWord (state, instr, temp)) - LSBase = temp; - break; - - case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - temp = LHS - LSImmRHS; - if (LoadWord (state, instr, temp)) - LSBase = temp; - break; - - case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */ - (void) StoreByte (state, instr, LHS - LSImmRHS); - break; - - case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */ - (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED); - break; - - case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - temp = LHS - LSImmRHS; - if (StoreByte (state, instr, temp)) - LSBase = temp; - break; - - case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - temp = LHS - LSImmRHS; - if (LoadByte (state, instr, temp, LUNSIGNED)) - LSBase = temp; - break; - - case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */ - (void) StoreWord (state, instr, LHS + LSImmRHS); - break; - - case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */ - (void) LoadWord (state, instr, LHS + LSImmRHS); - break; - - case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - temp = LHS + LSImmRHS; - if (StoreWord (state, instr, temp)) - LSBase = temp; - break; - - case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - temp = LHS + LSImmRHS; - if (LoadWord (state, instr, temp)) - LSBase = temp; - break; - - case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */ - (void) StoreByte (state, instr, LHS + LSImmRHS); - break; - - case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */ - (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED); - break; - - case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - temp = LHS + LSImmRHS; - if (StoreByte (state, instr, temp)) - LSBase = temp; - break; - - case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */ - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - temp = LHS + LSImmRHS; - if (LoadByte (state, instr, temp, LUNSIGNED)) - LSBase = temp; - break; - - /* Single Data Transfer Register RHS Instructions. */ - - case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - if (StoreWord (state, instr, lhs)) - LSBase = lhs - LSRegRHS; - break; - - case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - temp = lhs - LSRegRHS; - if (LoadWord (state, instr, lhs)) - LSBase = temp; - break; - - case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - state->NtransSig = LOW; - if (StoreWord (state, instr, lhs)) - LSBase = lhs - LSRegRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - temp = lhs - LSRegRHS; - state->NtransSig = LOW; - if (LoadWord (state, instr, lhs)) - LSBase = temp; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - if (StoreByte (state, instr, lhs)) - LSBase = lhs - LSRegRHS; - break; - - case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - temp = lhs - LSRegRHS; - if (LoadByte (state, instr, lhs, LUNSIGNED)) - LSBase = temp; - break; - - case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - state->NtransSig = LOW; - if (StoreByte (state, instr, lhs)) - LSBase = lhs - LSRegRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 - && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - temp = lhs - LSRegRHS; - state->NtransSig = LOW; - if (LoadByte (state, instr, lhs, LUNSIGNED)) - LSBase = temp; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ - if ((instr & 0x70) == 0x10) { //pkhbt - u8 idest = BITS(12, 15); - u8 rfis = BITS(16, 19); - u8 rlast = BITS(0, 3); - u8 ishi = BITS(7,11); - state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000); - break; - } else if ((instr & 0x70) == 0x50) { //pkhtb - u8 rd_idx = BITS(12, 15); - u8 rn_idx = BITS(16, 19); - u8 rm_idx = BITS(0, 3); - u8 imm5 = BITS(7, 11) ? BITS(7, 11) : 31; - state->Reg[rd_idx] = ((static_cast<s32>(state->Reg[rm_idx]) >> imm5) & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000); - break; - } else if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 - && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - if (StoreWord (state, instr, lhs)) - LSBase = lhs + LSRegRHS; - break; - - case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - temp = lhs + LSRegRHS; - if (LoadWord (state, instr, lhs)) - LSBase = temp; - break; - - case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 - && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - state->NtransSig = LOW; - if (StoreWord (state, instr, lhs)) - LSBase = lhs + LSRegRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 - && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - temp = lhs + LSRegRHS; - state->NtransSig = LOW; - if (LoadWord (state, instr, lhs)) - LSBase = temp; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 - && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - if (StoreByte (state, instr, lhs)) - LSBase = lhs + LSRegRHS; - break; - - case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - temp = lhs + LSRegRHS; - if (LoadByte (state, instr, lhs, LUNSIGNED)) - LSBase = temp; - break; - - case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 - && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - state->NtransSig = LOW; - if (StoreByte (state, instr, lhs)) - LSBase = lhs + LSRegRHS; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 - && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - lhs = LHS; - temp = lhs + LSRegRHS; - state->NtransSig = LOW; - if (LoadByte (state, instr, lhs, LUNSIGNED)) - LSBase = temp; - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - break; - - case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - ARMul_UndefInstr (state, instr); - break; - } - (void) StoreWord (state, instr, LHS - LSRegRHS); - break; - - case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - (void) LoadWord (state, instr, LHS - LSRegRHS); - break; - - case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - temp = LHS - LSRegRHS; - if (StoreWord (state, instr, temp)) - LSBase = temp; - break; - - case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - temp = LHS - LSRegRHS; - if (LoadWord (state, instr, temp)) - LSBase = temp; - break; - - case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - ARMul_UndefInstr (state, instr); - break; - } - (void) StoreByte (state, instr, LHS - LSRegRHS); - break; - - case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - ARMul_UndefInstr (state, instr); - break; - } - (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED); - break; - - case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - temp = LHS - LSRegRHS; - if (StoreByte (state, instr, temp)) - LSBase = temp; - break; - - case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - temp = LHS - LSRegRHS; - if (LoadByte (state, instr, temp, LUNSIGNED)) - LSBase = temp; - break; - - case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - (void) StoreWord (state, instr, LHS + LSRegRHS); - break; - - case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - (void) LoadWord (state, instr, LHS + LSRegRHS); - break; - - case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - temp = LHS + LSRegRHS; - if (StoreWord (state, instr, temp)) - LSBase = temp; - break; - - case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - temp = LHS + LSRegRHS; - if (LoadWord (state, instr, temp)) - LSBase = temp; - break; - - case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */ - if (BIT (4)) { -#ifdef MODE32 - if (state->is_v6 && handle_v6_insn (state, instr)) - break; -#endif - - ARMul_UndefInstr (state, instr); - break; - } - (void) StoreByte (state, instr, LHS + LSRegRHS); - break; - - case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED); - break; - - case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */ - if (BIT (4)) { - ARMul_UndefInstr (state, instr); - break; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - temp = LHS + LSRegRHS; - if (StoreByte (state, instr, temp)) - LSBase = temp; - break; - - case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */ - if (BIT (4)) { - LOG_DEBUG(Core_ARM11, "got unhandled special breakpoint"); - return 1; - } - UNDEF_LSRBaseEQOffWb; - UNDEF_LSRBaseEQDestWb; - UNDEF_LSRPCBaseWb; - UNDEF_LSRPCOffWb; - temp = LHS + LSRegRHS; - if (LoadByte (state, instr, temp, LUNSIGNED)) - LSBase = temp; - break; - - /* Multiple Data Transfer Instructions. */ - - case 0x80: /* Store, No WriteBack, Post Dec. */ - STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L); - break; - - case 0x81: /* Load, No WriteBack, Post Dec. */ - LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L); - break; - - case 0x82: /* Store, WriteBack, Post Dec. */ - temp = LSBase - LSMNumRegs; - STOREMULT (instr, temp + 4L, temp); - break; - - case 0x83: /* Load, WriteBack, Post Dec. */ - temp = LSBase - LSMNumRegs; - LOADMULT (instr, temp + 4L, temp); - break; - - case 0x84: /* Store, Flags, No WriteBack, Post Dec. */ - STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L); - break; - - case 0x85: /* Load, Flags, No WriteBack, Post Dec. */ - LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L); - break; - - case 0x86: /* Store, Flags, WriteBack, Post Dec. */ - temp = LSBase - LSMNumRegs; - STORESMULT (instr, temp + 4L, temp); - break; - - case 0x87: /* Load, Flags, WriteBack, Post Dec. */ - temp = LSBase - LSMNumRegs; - LOADSMULT (instr, temp + 4L, temp); - break; - - case 0x88: /* Store, No WriteBack, Post Inc. */ - STOREMULT (instr, LSBase, 0L); - break; - - case 0x89: /* Load, No WriteBack, Post Inc. */ - LOADMULT (instr, LSBase, 0L); - break; - - case 0x8a: /* Store, WriteBack, Post Inc. */ - temp = LSBase; - STOREMULT (instr, temp, temp + LSMNumRegs); - break; - - case 0x8b: /* Load, WriteBack, Post Inc. */ - temp = LSBase; - LOADMULT (instr, temp, temp + LSMNumRegs); - break; - - case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */ - STORESMULT (instr, LSBase, 0L); - break; - - case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */ - LOADSMULT (instr, LSBase, 0L); - break; - - case 0x8e: /* Store, Flags, WriteBack, Post Inc. */ - temp = LSBase; - STORESMULT (instr, temp, temp + LSMNumRegs); - break; - - case 0x8f: /* Load, Flags, WriteBack, Post Inc. */ - temp = LSBase; - LOADSMULT (instr, temp, temp + LSMNumRegs); - break; - - case 0x90: /* Store, No WriteBack, Pre Dec. */ - STOREMULT (instr, LSBase - LSMNumRegs, 0L); - break; - - case 0x91: /* Load, No WriteBack, Pre Dec. */ - LOADMULT (instr, LSBase - LSMNumRegs, 0L); - break; - - case 0x92: /* Store, WriteBack, Pre Dec. */ - temp = LSBase - LSMNumRegs; - STOREMULT (instr, temp, temp); - break; - - case 0x93: /* Load, WriteBack, Pre Dec. */ - temp = LSBase - LSMNumRegs; - LOADMULT (instr, temp, temp); - break; - - case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */ - STORESMULT (instr, LSBase - LSMNumRegs, 0L); - break; - - case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */ - LOADSMULT (instr, LSBase - LSMNumRegs, 0L); - break; - - case 0x96: /* Store, Flags, WriteBack, Pre Dec. */ - temp = LSBase - LSMNumRegs; - STORESMULT (instr, temp, temp); - break; - - case 0x97: /* Load, Flags, WriteBack, Pre Dec. */ - temp = LSBase - LSMNumRegs; - LOADSMULT (instr, temp, temp); - break; - - case 0x98: /* Store, No WriteBack, Pre Inc. */ - STOREMULT (instr, LSBase + 4L, 0L); - break; - - case 0x99: /* Load, No WriteBack, Pre Inc. */ - LOADMULT (instr, LSBase + 4L, 0L); - break; - - case 0x9a: /* Store, WriteBack, Pre Inc. */ - temp = LSBase; - STOREMULT (instr, temp + 4L, temp + LSMNumRegs); - break; - - case 0x9b: /* Load, WriteBack, Pre Inc. */ - temp = LSBase; - LOADMULT (instr, temp + 4L, temp + LSMNumRegs); - break; - - case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */ - STORESMULT (instr, LSBase + 4L, 0L); - break; - - case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */ - LOADSMULT (instr, LSBase + 4L, 0L); - break; - - case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */ - temp = LSBase; - STORESMULT (instr, temp + 4L, temp + LSMNumRegs); - break; - - case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */ - temp = LSBase; - LOADSMULT (instr, temp + 4L, temp + LSMNumRegs); - break; - - /* Branch forward. */ - case 0xa0: - case 0xa1: - case 0xa2: - case 0xa3: - case 0xa4: - case 0xa5: - case 0xa6: - case 0xa7: - state->Reg[15] = pc + 8 + POSBRANCH; - FLUSHPIPE; - break; - - /* Branch backward. */ - case 0xa8: - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: - case 0xaf: - state->Reg[15] = pc + 8 + NEGBRANCH; - FLUSHPIPE; - break; - - /* Branch and Link forward. */ - case 0xb0: - case 0xb1: - case 0xb2: - case 0xb3: - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: - - /* Put PC into Link. */ -#ifdef MODE32 - state->Reg[14] = pc + 4; -#else - state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; -#endif - state->Reg[15] = pc + 8 + POSBRANCH; - FLUSHPIPE; - break; - - /* Branch and Link backward. */ - case 0xb8: - case 0xb9: - case 0xba: - case 0xbb: - case 0xbc: - case 0xbd: - case 0xbe: - case 0xbf: - /* Put PC into Link. */ -#ifdef MODE32 - state->Reg[14] = pc + 4; -#else - state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; -#endif - state->Reg[15] = pc + 8 + NEGBRANCH; - FLUSHPIPE; - break; - - /* Co-Processor Data Transfers. */ - case 0xc4: - if ((instr & 0x0FF00FF0) == 0xC400B10) { //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0 - state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)]; - state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)]; - break; - } else if (state->is_v5) { - /* Reading from R15 is UNPREDICTABLE. */ - if (BITS (12, 15) == 15 || BITS (16, 19) == 15) - ARMul_UndefInstr (state, instr); - /* Is access to coprocessor 0 allowed ? */ - else if (!CP_ACCESS_ALLOWED(state, CPNum)) - ARMul_UndefInstr (state, instr); - else { - /* MCRR, ARMv5TE and up */ - ARMul_MCRR (state, instr, DEST, state->Reg[LHSReg]); - break; - } - } - /* Drop through. */ - - case 0xc0: /* Store , No WriteBack , Post Dec. */ - ARMul_STC (state, instr, LHS); - break; - - case 0xc5: - if ((instr & 0x00000FF0) == 0xB10) { //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0 - state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1]; - state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1]; - break; - } else if (state->is_v5) { - /* Writes to R15 are UNPREDICATABLE. */ - if (DESTReg == 15 || LHSReg == 15) - ARMul_UndefInstr (state, instr); - /* Is access to the coprocessor allowed ? */ - else if (!CP_ACCESS_ALLOWED(state, CPNum)) { - ARMul_UndefInstr(state, instr); - } else { - /* MRRC, ARMv5TE and up */ - ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); - break; - } - } - /* Drop through. */ - - case 0xc1: /* Load , No WriteBack , Post Dec. */ - ARMul_LDC (state, instr, LHS); - break; - - case 0xc2: - case 0xc6: /* Store , WriteBack , Post Dec. */ - lhs = LHS; - state->Base = lhs - LSCOff; - ARMul_STC (state, instr, lhs); - break; - - case 0xc3: - case 0xc7: /* Load , WriteBack , Post Dec. */ - lhs = LHS; - state->Base = lhs - LSCOff; - ARMul_LDC (state, instr, lhs); - break; - - case 0xc8: - case 0xcc: /* Store , No WriteBack , Post Inc. */ - ARMul_STC (state, instr, LHS); - break; - - case 0xc9: - case 0xcd: /* Load , No WriteBack , Post Inc. */ - ARMul_LDC (state, instr, LHS); - break; - - case 0xca: - case 0xce: /* Store , WriteBack , Post Inc. */ - lhs = LHS; - state->Base = lhs + LSCOff; - ARMul_STC (state, instr, LHS); - break; - - case 0xcb: - case 0xcf: /* Load , WriteBack , Post Inc. */ - lhs = LHS; - state->Base = lhs + LSCOff; - ARMul_LDC (state, instr, LHS); - break; - - case 0xd0: - case 0xd4: /* Store , No WriteBack , Pre Dec. */ - ARMul_STC (state, instr, LHS - LSCOff); - break; - - case 0xd1: - case 0xd5: /* Load , No WriteBack , Pre Dec. */ - ARMul_LDC (state, instr, LHS - LSCOff); - break; - - case 0xd2: - case 0xd6: /* Store , WriteBack , Pre Dec. */ - lhs = LHS - LSCOff; - state->Base = lhs; - ARMul_STC (state, instr, lhs); - break; - - case 0xd3: - case 0xd7: /* Load , WriteBack , Pre Dec. */ - lhs = LHS - LSCOff; - state->Base = lhs; - ARMul_LDC (state, instr, lhs); - break; - - case 0xd8: - case 0xdc: /* Store , No WriteBack , Pre Inc. */ - ARMul_STC (state, instr, LHS + LSCOff); - break; - - case 0xd9: - case 0xdd: /* Load , No WriteBack , Pre Inc. */ - ARMul_LDC (state, instr, LHS + LSCOff); - break; - - case 0xda: - case 0xde: /* Store , WriteBack , Pre Inc. */ - lhs = LHS + LSCOff; - state->Base = lhs; - ARMul_STC (state, instr, lhs); - break; - - case 0xdb: - case 0xdf: /* Load , WriteBack , Pre Inc. */ - lhs = LHS + LSCOff; - state->Base = lhs; - ARMul_LDC (state, instr, lhs); - break; - - /* Co-Processor Register Transfers (MCR) and Data Ops. */ - - case 0xe2: - /*if (!CP_ACCESS_ALLOWED (state, CPNum)) { - ARMul_UndefInstr (state, instr); - break; - }*/ - - case 0xe0: - case 0xe4: - case 0xe6: - case 0xe8: - case 0xea: - case 0xec: - case 0xee: - if (BIT (4)) { - /* MCR. */ - if (DESTReg == 15) { - UNDEF_MCRPC; -#ifdef MODE32 - ARMul_MCR (state, instr, state->Reg[15] + isize); -#else - ARMul_MCR (state, instr, ECC | ER15INT | EMODE | ((state->Reg[15] + isize) & R15PCBITS)); -#endif - } else - ARMul_MCR (state, instr, DEST); - } else - /* CDP Part 1. */ - ARMul_CDP (state, instr); - break; - - /* Co-Processor Register Transfers (MRC) and Data Ops. */ - case 0xe1: - case 0xe3: - case 0xe5: - case 0xe7: - case 0xe9: - case 0xeb: - case 0xed: - case 0xef: - if (BIT (4)) { - /* MRC */ - temp = ARMul_MRC (state, instr); - if (DESTReg == 15) { - ASSIGNN ((temp & NBIT) != 0); - ASSIGNZ ((temp & ZBIT) != 0); - ASSIGNC ((temp & CBIT) != 0); - ASSIGNV ((temp & VBIT) != 0); - } else - DEST = temp; - } else - /* CDP Part 2. */ - ARMul_CDP (state, instr); - break; - - /* SWI instruction. */ - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - case 0xff: - //svc_Execute(state, BITS(0, 23)); - HLE::CallSVC(instr); - - break; - } - } - -#ifdef MODET -donext: -#endif - state->pc = pc; - - /* jump out every time */ - //state->EndCondition = 0; - //state->Emulate = STOP; -//chy 2006-04-12 for ICE debug -TEST_EMULATE: - if (state->Emulate == ONCE) - state->Emulate = STOP; - else if (state->Emulate != RUN) - break; - } - - while (state->NumInstrsToExecute); -exit: - state->decoded = decoded; - state->loaded = loaded; - state->pc = pc; - //chy 2006-04-12, for ICE debug - state->decoded_addr=decoded_addr; - state->loaded_addr=loaded_addr; - - return pc; - } - - static volatile void (*gen_func) (void); - - static volatile uint32_t tmp_st; - static volatile uint32_t save_st; - static volatile uint32_t save_T0; - static volatile uint32_t save_T1; - static volatile uint32_t save_T2; - - /* This routine evaluates most Data Processing register RHS's with the S - bit clear. It is intended to be called from the macro DPRegRHS, which - filters the common case of an unshifted register with in line code. */ - - static ARMword - GetDPRegRHS (ARMul_State * state, ARMword instr) { - ARMword shamt, base; - - base = RHSReg; - if (BIT (4)) { - /* Shift amount in a register. */ - UNDEF_Shift; - INCPC; -#ifndef MODE32 - if (base == 15) - base = ECC | ER15INT | R15PC | EMODE; - else -#endif - base = state->Reg[base]; - ARMul_Icycles (state, 1, 0L); - shamt = state->Reg[BITS (8, 11)] & 0xff; - switch ((int) BITS (5, 6)) { - case LSL: - if (shamt == 0) - return (base); - else if (shamt >= 32) - return (0); - else - return (base << shamt); - case LSR: - if (shamt == 0) - return (base); - else if (shamt >= 32) - return (0); - else - return (base >> shamt); - case ASR: - if (shamt == 0) - return (base); - else if (shamt >= 32) - return ((ARMword) ((int) base >> 31L)); - else - return ((ARMword) - (( int) base >> (int) shamt)); - case ROR: - shamt &= 0x1f; - if (shamt == 0) - return (base); - else - return ((base << (32 - shamt)) | - (base >> shamt)); - } - } else { - /* Shift amount is a constant. */ -#ifndef MODE32 - if (base == 15) - base = ECC | ER15INT | R15PC | EMODE; - else -#endif - base = state->Reg[base]; - shamt = BITS (7, 11); - switch ((int) BITS (5, 6)) { - case LSL: - return (base << shamt); - case LSR: - if (shamt == 0) - return (0); - else - return (base >> shamt); - case ASR: - if (shamt == 0) - return ((ARMword) (( int) base >> 31L)); - else - return ((ARMword) - (( int) base >> (int) shamt)); - case ROR: - if (shamt == 0) - /* It's an RRX. */ - return ((base >> 1) | (CFLAG << 31)); - else - return ((base << (32 - shamt)) | - (base >> shamt)); - } - } - - return 0; - } - - /* This routine evaluates most Logical Data Processing register RHS's - with the S bit set. It is intended to be called from the macro - DPSRegRHS, which filters the common case of an unshifted register - with in line code. */ - - static ARMword - GetDPSRegRHS (ARMul_State * state, ARMword instr) { - ARMword shamt, base; - - base = RHSReg; - if (BIT (4)) { - /* Shift amount in a register. */ - UNDEF_Shift; - INCPC; -#ifndef MODE32 - if (base == 15) - base = ECC | ER15INT | R15PC | EMODE; - else -#endif - base = state->Reg[base]; - ARMul_Icycles (state, 1, 0L); - shamt = state->Reg[BITS (8, 11)] & 0xff; - switch ((int) BITS (5, 6)) { - case LSL: - if (shamt == 0) - return (base); - else if (shamt == 32) { - ASSIGNC (base & 1); - return (0); - } else if (shamt > 32) { - CLEARC; - return (0); - } else { - ASSIGNC ((base >> (32 - shamt)) & 1); - return (base << shamt); - } - case LSR: - if (shamt == 0) - return (base); - else if (shamt == 32) { - ASSIGNC (base >> 31); - return (0); - } else if (shamt > 32) { - CLEARC; - return (0); - } else { - ASSIGNC ((base >> (shamt - 1)) & 1); - return (base >> shamt); - } - case ASR: - if (shamt == 0) - return (base); - else if (shamt >= 32) { - ASSIGNC (base >> 31L); - return ((ARMword) (( int) base >> 31L)); - } else { - ASSIGNC ((ARMword) - (( int) base >> - (int) (shamt - 1)) & 1); - return ((ARMword) - ((int) base >> (int) shamt)); - } - case ROR: - if (shamt == 0) - return (base); - shamt &= 0x1f; - if (shamt == 0) { - ASSIGNC (base >> 31); - return (base); - } else { - ASSIGNC ((base >> (shamt - 1)) & 1); - return ((base << (32 - shamt)) | - (base >> shamt)); - } - } - } else { - /* Shift amount is a constant. */ -#ifndef MODE32 - if (base == 15) - base = ECC | ER15INT | R15PC | EMODE; - else -#endif - base = state->Reg[base]; - shamt = BITS (7, 11); - - switch ((int) BITS (5, 6)) { - case LSL: - ASSIGNC ((base >> (32 - shamt)) & 1); - return (base << shamt); - case LSR: - if (shamt == 0) { - ASSIGNC (base >> 31); - return (0); - } else { - ASSIGNC ((base >> (shamt - 1)) & 1); - return (base >> shamt); - } - case ASR: - if (shamt == 0) { - ASSIGNC (base >> 31L); - return ((ARMword) ((int) base >> 31L)); - } else { - ASSIGNC ((ARMword) - ((int) base >> - (int) (shamt - 1)) & 1); - return ((ARMword) - (( int) base >> (int) shamt)); - } - case ROR: - if (shamt == 0) { - /* It's an RRX. */ - shamt = CFLAG; - ASSIGNC (base & 1); - return ((base >> 1) | (shamt << 31)); - } else { - ASSIGNC ((base >> (shamt - 1)) & 1); - return ((base << (32 - shamt)) | - (base >> shamt)); - } - } - } - - return 0; - } - - /* This routine handles writes to register 15 when the S bit is not set. */ - - static void - WriteR15 (ARMul_State * state, ARMword src) { - /* The ARM documentation states that the two least significant bits - are discarded when setting PC, except in the cases handled by - WriteR15Branch() below. It's probably an oversight: in THUMB - mode, the second least significant bit should probably not be - discarded. */ -#ifdef MODET - if (TFLAG) - src &= 0xfffffffe; - else -#endif - src &= 0xfffffffc; - -#ifdef MODE32 - state->Reg[15] = src & PCBITS; -#else - state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE; - ARMul_R15Altered (state); -#endif - - FLUSHPIPE; - } - - /* This routine handles writes to register 15 when the S bit is set. */ - - static void - WriteSR15 (ARMul_State * state, ARMword src) { -#ifdef MODE32 - if (state->Bank > 0) { - state->Cpsr = state->Spsr[state->Bank]; - ARMul_CPSRAltered (state); - } -#ifdef MODET - if (TFLAG) - src &= 0xfffffffe; - else -#endif - src &= 0xfffffffc; - state->Reg[15] = src & PCBITS; -#else -#ifdef MODET - if (TFLAG) - /* ARMul_R15Altered would have to support it. */ - abort (); - else -#endif - src &= 0xfffffffc; - - if (state->Bank == USERBANK) - state->Reg[15] = - (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE; - else - state->Reg[15] = src; - - ARMul_R15Altered (state); -#endif - FLUSHPIPE; - } - - /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM - will switch to Thumb mode if the least significant bit is set. */ - - static void - WriteR15Branch (ARMul_State * state, ARMword src) { -#ifdef MODET - if (src & 1) { - /* Thumb bit. */ - SETT; - state->Reg[15] = src & 0xfffffffe; - } else { - CLEART; - state->Reg[15] = src & 0xfffffffc; - } - state->Cpsr = ARMul_GetCPSR (state); - FLUSHPIPE; -#else - WriteR15 (state, src); -#endif - } - - /* This routine evaluates most Load and Store register RHS's. It is - intended to be called from the macro LSRegRHS, which filters the - common case of an unshifted register with in line code. */ - - static ARMword - GetLSRegRHS (ARMul_State * state, ARMword instr) { - ARMword shamt, base; - - base = RHSReg; -#ifndef MODE32 - if (base == 15) - /* Now forbidden, but ... */ - base = ECC | ER15INT | R15PC | EMODE; - else -#endif - base = state->Reg[base]; - - shamt = BITS (7, 11); - switch ((int) BITS (5, 6)) { - case LSL: - return (base << shamt); - case LSR: - if (shamt == 0) - return (0); - else - return (base >> shamt); - case ASR: - if (shamt == 0) - return ((ARMword) (( int) base >> 31L)); - else - return ((ARMword) (( int) base >> (int) shamt)); - case ROR: - if (shamt == 0) - /* It's an RRX. */ - return ((base >> 1) | (CFLAG << 31)); - else - return ((base << (32 - shamt)) | (base >> shamt)); - default: - break; - } - return 0; - } - - /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */ - - static ARMword - GetLS7RHS (ARMul_State * state, ARMword instr) { - if (BIT (22) == 0) { - /* Register. */ -#ifndef MODE32 - if (RHSReg == 15) - /* Now forbidden, but ... */ - return ECC | ER15INT | R15PC | EMODE; -#endif - return state->Reg[RHSReg]; - } - - /* Immediate. */ - return BITS (0, 3) | (BITS (8, 11) << 4); - } - - static unsigned - LoadWord (ARMul_State * state, ARMword instr, ARMword address) { - ARMword dest; - - BUSUSEDINCPCS; -#ifndef MODE32 - if (ADDREXCEPT (address)) - INTERNALABORT (address); -#endif - - dest = ARMul_LoadWordN (state, address); - - if (state->Aborted) { - TAKEABORT; - return state->lateabtSig; - } - if (address & 3) - dest = ARMul_Align (state, address, dest); - WRITEDESTB (dest); - ARMul_Icycles (state, 1, 0L); - - return (DESTReg != LHSReg); - } - -#ifdef MODET - /* This function does the work of loading a halfword. */ - - static unsigned - LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address, - int signextend) { - ARMword dest; - - BUSUSEDINCPCS; -#ifndef MODE32 - if (ADDREXCEPT (address)) - INTERNALABORT (address); -#endif - dest = ARMul_LoadHalfWord (state, address); - if (state->Aborted) { - TAKEABORT; - return state->lateabtSig; - } - UNDEF_LSRBPC; - if (signextend) - if (dest & 1 << (16 - 1)) - dest = (dest & ((1 << 16) - 1)) - (1 << 16); - - WRITEDEST (dest); - ARMul_Icycles (state, 1, 0L); - - return (DESTReg != LHSReg); - } - -#endif /* MODET */ - - /* This function does the work of loading a byte for a LDRB instruction. */ - - static unsigned - LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) { - ARMword dest; - - BUSUSEDINCPCS; -#ifndef MODE32 - if (ADDREXCEPT (address)) - INTERNALABORT (address); -#endif - dest = ARMul_LoadByte (state, address); - if (state->Aborted) { - TAKEABORT; - return state->lateabtSig; - } - UNDEF_LSRBPC; - if (signextend) - if (dest & 1 << (8 - 1)) - dest = (dest & ((1 << 8) - 1)) - (1 << 8); - - WRITEDEST (dest); - ARMul_Icycles (state, 1, 0L); - - return (DESTReg != LHSReg); - } - - /* This function does the work of loading two words for a LDRD instruction. */ - - static void - Handle_Load_Double (ARMul_State * state, ARMword instr) { - ARMword dest_reg; - ARMword addr_reg; - ARMword write_back = BIT (21); - ARMword immediate = BIT (22); - ARMword add_to_base = BIT (23); - ARMword pre_indexed = BIT (24); - ARMword offset; - ARMword addr; - ARMword sum; - ARMword base; - ARMword value1; - ARMword value2; - - BUSUSEDINCPCS; - - /* If the writeback bit is set, the pre-index bit must be clear. */ - if (write_back && !pre_indexed) { - ARMul_UndefInstr (state, instr); - return; - } - - /* Extract the base address register. */ - addr_reg = LHSReg; - - /* Extract the destination register and check it. */ - dest_reg = DESTReg; - - /* Destination register must be even. */ - if ((dest_reg & 1) - /* Destination register cannot be LR. */ - || (dest_reg == 14)) { - ARMul_UndefInstr (state, instr); - return; - } - - /* Compute the base address. */ - base = state->Reg[addr_reg]; - - /* Compute the offset. */ - offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state-> - Reg[RHSReg]; - - /* Compute the sum of the two. */ - if (add_to_base) - sum = base + offset; - else - sum = base - offset; - - /* If this is a pre-indexed mode use the sum. */ - if (pre_indexed) - addr = sum; - else - addr = base; - - /* The address must be aligned on a 8 byte boundary. */ - /*if (addr & 0x7) { - #ifdef ABORTS - ARMul_DATAABORT (addr); - #else - ARMul_UndefInstr (state, instr); - #endif - return; - }*/ - /* Lets just forcibly align it for now */ - //addr = (addr + 7) & ~7; - - /* For pre indexed or post indexed addressing modes, - check that the destination registers do not overlap - the address registers. */ - if ((!pre_indexed || write_back) - && (addr_reg == dest_reg || addr_reg == dest_reg + 1)) { - ARMul_UndefInstr (state, instr); - return; - } - - /* Load the words. */ - value1 = ARMul_LoadWordN (state, addr); - value2 = ARMul_LoadWordN (state, addr + 4); - - /* Check for data aborts. */ - if (state->Aborted) { - TAKEABORT; - return; - } - - ARMul_Icycles (state, 2, 0L); - - /* Store the values. */ - state->Reg[dest_reg] = value1; - state->Reg[dest_reg + 1] = value2; - - /* Do the post addressing and writeback. */ - if (!pre_indexed) - addr = sum; - - if (!pre_indexed || write_back) - state->Reg[addr_reg] = addr; - } - - /* This function does the work of storing two words for a STRD instruction. */ - - static void - Handle_Store_Double (ARMul_State * state, ARMword instr) { - ARMword src_reg; - ARMword addr_reg; - ARMword write_back = BIT (21); - ARMword immediate = BIT (22); - ARMword add_to_base = BIT (23); - ARMword pre_indexed = BIT (24); - ARMword offset; - ARMword addr; - ARMword sum; - ARMword base; - - BUSUSEDINCPCS; - - /* If the writeback bit is set, the pre-index bit must be clear. */ - if (write_back && !pre_indexed) { - ARMul_UndefInstr (state, instr); - return; - } - - /* Extract the base address register. */ - addr_reg = LHSReg; - - /* Base register cannot be PC. */ - if (addr_reg == 15) { - ARMul_UndefInstr (state, instr); - return; - } - - /* Extract the source register. */ - src_reg = DESTReg; - - /* Source register must be even. */ - if (src_reg & 1) { - ARMul_UndefInstr (state, instr); - return; - } - - /* Compute the base address. */ - base = state->Reg[addr_reg]; - - /* Compute the offset. */ - offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state-> - Reg[RHSReg]; - - /* Compute the sum of the two. */ - if (add_to_base) - sum = base + offset; - else - sum = base - offset; - - /* If this is a pre-indexed mode use the sum. */ - if (pre_indexed) - addr = sum; - else - addr = base; - - /* The address must be aligned on a 8 byte boundary. */ - /*if (addr & 0x7) { - #ifdef ABORTS - ARMul_DATAABORT (addr); - #else - ARMul_UndefInstr (state, instr); - #endif - return; - }*/ - /* Lets just forcibly align it for now */ - //addr = (addr + 7) & ~7; - - /* For pre indexed or post indexed addressing modes, - check that the destination registers do not overlap - the address registers. */ - if ((!pre_indexed || write_back) - && (addr_reg == src_reg || addr_reg == src_reg + 1)) { - ARMul_UndefInstr (state, instr); - return; - } - - /* Load the words. */ - ARMul_StoreWordN (state, addr, state->Reg[src_reg]); - ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]); - - if (state->Aborted) { - TAKEABORT; - return; - } - - /* Do the post addressing and writeback. */ - if (!pre_indexed) - addr = sum; - - if (!pre_indexed || write_back) - state->Reg[addr_reg] = addr; - } - - /* This function does the work of storing a word from a STR instruction. */ - - static unsigned - StoreWord (ARMul_State * state, ARMword instr, ARMword address) { - BUSUSEDINCPCN; -#ifndef MODE32 - if (DESTReg == 15) - state->Reg[15] = ECC | ER15INT | R15PC | EMODE; -#endif -#ifdef MODE32 - ARMul_StoreWordN (state, address, DEST); -#else - if (VECTORACCESS (address) || ADDREXCEPT (address)) { - INTERNALABORT (address); - (void) ARMul_LoadWordN (state, address); - } else - ARMul_StoreWordN (state, address, DEST); -#endif - if (state->Aborted) { - TAKEABORT; - return state->lateabtSig; - } - - return TRUE; - } - -#ifdef MODET - /* This function does the work of storing a byte for a STRH instruction. */ - - static unsigned - StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) { - BUSUSEDINCPCN; - -#ifndef MODE32 - if (DESTReg == 15) - state->Reg[15] = ECC | ER15INT | R15PC | EMODE; -#endif - -#ifdef MODE32 - ARMul_StoreHalfWord (state, address, DEST); -#else - if (VECTORACCESS (address) || ADDREXCEPT (address)) { - INTERNALABORT (address); - (void) ARMul_LoadHalfWord (state, address); - } else - ARMul_StoreHalfWord (state, address, DEST); -#endif - - if (state->Aborted) { - TAKEABORT; - return state->lateabtSig; - } - return TRUE; - } - -#endif /* MODET */ - - /* This function does the work of storing a byte for a STRB instruction. */ - - static unsigned - StoreByte (ARMul_State * state, ARMword instr, ARMword address) { - BUSUSEDINCPCN; -#ifndef MODE32 - if (DESTReg == 15) - state->Reg[15] = ECC | ER15INT | R15PC | EMODE; -#endif -#ifdef MODE32 - ARMul_StoreByte (state, address, DEST); -#else - if (VECTORACCESS (address) || ADDREXCEPT (address)) { - INTERNALABORT (address); - (void) ARMul_LoadByte (state, address); - } else - ARMul_StoreByte (state, address, DEST); -#endif - if (state->Aborted) { - TAKEABORT; - return state->lateabtSig; - } - //UNDEF_LSRBPC; - return TRUE; - } - - /* This function does the work of loading the registers listed in an LDM - instruction, when the S bit is clear. The code here is always increment - after, it's up to the caller to get the input address correct and to - handle base register modification. */ - - static void - LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) { - ARMword dest, temp; - - //UNDEF_LSMNoRegs; - //UNDEF_LSMPCBase; - //UNDEF_LSMBaseInListWb; - BUSUSEDINCPCS; -#ifndef MODE32 - if (ADDREXCEPT (address)) - INTERNALABORT (address); -#endif - /*chy 2004-05-23 may write twice - if (BIT (21) && LHSReg != 15) - LSBase = WBBase; - */ - /* N cycle first. */ - for (temp = 0; !BIT (temp); temp++); - - dest = ARMul_LoadWordN (state, address); - - if (!state->abortSig && !state->Aborted) - state->Reg[temp++] = dest; - else if (!state->Aborted) { - //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); - state->Aborted = ARMul_DataAbortV; - } - /*chy 2004-05-23 chy goto end*/ - if (state->Aborted) - goto L_ldm_makeabort; - /* S cycles from here on. */ - for (; temp < 16; temp++) - if (BIT (temp)) { - /* Load this register. */ - address += 4; - dest = ARMul_LoadWordS (state, address); - - if (!state->abortSig && !state->Aborted) - state->Reg[temp] = dest; - else if (!state->Aborted) { - /*XScale_set_fsr_far (state, - ARMul_CP15_R5_ST_ALIGN, - address);*/ - state->Aborted = ARMul_DataAbortV; - } - /*chy 2004-05-23 chy goto end */ - if (state->Aborted) - goto L_ldm_makeabort; - } - - if (BIT (15) && !state->Aborted) - /* PC is in the reg list. */ - WriteR15Branch (state, PC); - - /* To write back the final register. */ - /* ARMul_Icycles (state, 1, 0L);*/ - /*chy 2004-05-23, see below - if (state->Aborted) - { - if (BIT (21) && LHSReg != 15) - LSBase = WBBase; - - TAKEABORT; - } - */ - /*chy 2004-05-23 should compare the Abort Models*/ -L_ldm_makeabort: - /* To write back the final register. */ - ARMul_Icycles (state, 1, 0L); - - /* chy 2005-11-24, bug found by benjl@cse.unsw.edu.au, etc */ - /* - if (state->Aborted) - { - if (BIT (21) && LHSReg != 15) - if (!(state->abortSig && state->Aborted && state->lateabtSig == LOW)) - LSBase = WBBase; - TAKEABORT; - }else if (BIT (21) && LHSReg != 15) - LSBase = WBBase; - */ - if (state->Aborted) { - if (BIT (21) && LHSReg != 15) { - if (!(state->abortSig)) { - } - } - TAKEABORT; - } else if (BIT (21) && LHSReg != 15) { - LSBase = WBBase; - } - /* chy 2005-11-24, over */ - } - - /* This function does the work of loading the registers listed in an LDM - instruction, when the S bit is set. The code here is always increment - after, it's up to the caller to get the input address correct and to - handle base register modification. */ - - static void - LoadSMult (ARMul_State * state, - ARMword instr, ARMword address, ARMword WBBase) { - ARMword dest, temp; - - //UNDEF_LSMNoRegs; - //UNDEF_LSMPCBase; - //UNDEF_LSMBaseInListWb; - - BUSUSEDINCPCS; - -#ifndef MODE32 - if (ADDREXCEPT (address)) - INTERNALABORT (address); -#endif - /* chy 2004-05-23, may write twice - if (BIT (21) && LHSReg != 15) - LSBase = WBBase; - */ - if (!BIT (15) && state->Bank != USERBANK) { - /* Temporary reg bank switch. */ - (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); - UNDEF_LSMUserBankWb; - } - - /* N cycle first. */ - for (temp = 0; !BIT (temp); temp++); - - dest = ARMul_LoadWordN (state, address); - - if (!state->abortSig) - state->Reg[temp++] = dest; - else if (!state->Aborted) { - //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); - state->Aborted = ARMul_DataAbortV; - } - - /*chy 2004-05-23 chy goto end*/ - if (state->Aborted) - goto L_ldm_s_makeabort; - /* S cycles from here on. */ - for (; temp < 16; temp++) - if (BIT (temp)) { - /* Load this register. */ - address += 4; - dest = ARMul_LoadWordS (state, address); - - if (!state->abortSig && !state->Aborted) - state->Reg[temp] = dest; - else if (!state->Aborted) { - /*XScale_set_fsr_far (state, - ARMul_CP15_R5_ST_ALIGN, - address);*/ - state->Aborted = ARMul_DataAbortV; - } - /*chy 2004-05-23 chy goto end */ - if (state->Aborted) - goto L_ldm_s_makeabort; - } - - /*chy 2004-05-23 label of ldm_s_makeabort*/ -L_ldm_s_makeabort: - /*chy 2004-06-06 LSBase process should be here, not in the end of this function. Because ARMul_CPSRAltered maybe change R13(SP) R14(lr). If not, simulate INSTR ldmia sp!,[....pc]^ error.*/ - /*chy 2004-05-23 should compare the Abort Models*/ - if (state->Aborted) { - if (BIT (21) && LHSReg != 15) - if (! - (state->abortSig && state->Aborted - && state->lateabtSig == LOW)) - LSBase = WBBase; - TAKEABORT; - } else if (BIT (21) && LHSReg != 15) - LSBase = WBBase; - - if (BIT (15) && !state->Aborted) { - /* PC is in the reg list. */ -#ifdef MODE32 - //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode - if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { - state->Cpsr = GETSPSR (state->Bank); - ARMul_CPSRAltered (state); - } - - WriteR15 (state, PC); -#else - //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode - if (state->Mode == USER26MODE || state->Mode == USER32MODE ) { - /* Protect bits in user mode. */ - ASSIGNN ((state->Reg[15] & NBIT) != 0); - ASSIGNZ ((state->Reg[15] & ZBIT) != 0); - ASSIGNC ((state->Reg[15] & CBIT) != 0); - ASSIGNV ((state->Reg[15] & VBIT) != 0); - } else - ARMul_R15Altered (state); - - FLUSHPIPE; -#endif - } - - //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode - if (!BIT (15) && state->Mode != USER26MODE - && state->Mode != USER32MODE ) - /* Restore the correct bank. */ - (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); - - /* To write back the final register. */ - ARMul_Icycles (state, 1, 0L); - /* chy 2004-05-23, see below - if (state->Aborted) - { - if (BIT (21) && LHSReg != 15) - LSBase = WBBase; - - TAKEABORT; - } - */ - } - - /* This function does the work of storing the registers listed in an STM - instruction, when the S bit is clear. The code here is always increment - after, it's up to the caller to get the input address correct and to - handle base register modification. */ - - static void - StoreMult (ARMul_State * state, - ARMword instr, ARMword address, ARMword WBBase) { - ARMword temp; - - UNDEF_LSMNoRegs; - UNDEF_LSMPCBase; - UNDEF_LSMBaseInListWb; - - if (!TFLAG) - /* N-cycle, increment the PC and update the NextInstr state. */ - BUSUSEDINCPCN; - -#ifndef MODE32 - if (VECTORACCESS (address) || ADDREXCEPT (address)) - INTERNALABORT (address); - - if (BIT (15)) - PATCHR15; -#endif - - /* N cycle first. */ - for (temp = 0; !BIT (temp); temp++); - -#ifdef MODE32 - ARMul_StoreWordN (state, address, state->Reg[temp++]); -#else - if (state->Aborted) { - (void) ARMul_LoadWordN (state, address); - - /* Fake the Stores as Loads. */ - for (; temp < 16; temp++) - if (BIT (temp)) { - /* Save this register. */ - address += 4; - (void) ARMul_LoadWordS (state, address); - } - - if (BIT (21) && LHSReg != 15) - LSBase = WBBase; - TAKEABORT; - return; - } else - ARMul_StoreWordN (state, address, state->Reg[temp++]); -#endif - - if (state->abortSig && !state->Aborted) { - //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); - state->Aborted = ARMul_DataAbortV; - } - -//chy 2004-05-23, needn't store other when aborted - if (state->Aborted) - goto L_stm_takeabort; - - /* S cycles from here on. */ - for (; temp < 16; temp++) - if (BIT (temp)) { - /* Save this register. */ - address += 4; - - ARMul_StoreWordS (state, address, state->Reg[temp]); - - if (state->abortSig && !state->Aborted) { - /*XScale_set_fsr_far (state, - ARMul_CP15_R5_ST_ALIGN, - address);*/ - state->Aborted = ARMul_DataAbortV; - } - //chy 2004-05-23, needn't store other when aborted - if (state->Aborted) - goto L_stm_takeabort; - } - -//chy 2004-05-23,should compare the Abort Models -L_stm_takeabort: - if (BIT (21) && LHSReg != 15) { - if (! - (state->abortSig && state->Aborted - && state->lateabtSig == LOW)) - LSBase = WBBase; - } - if (state->Aborted) - TAKEABORT; - } - - /* This function does the work of storing the registers listed in an STM - instruction when the S bit is set. The code here is always increment - after, it's up to the caller to get the input address correct and to - handle base register modification. */ - - static void - StoreSMult (ARMul_State * state, - ARMword instr, ARMword address, ARMword WBBase) { - ARMword temp; - - UNDEF_LSMNoRegs; - UNDEF_LSMPCBase; - UNDEF_LSMBaseInListWb; - - BUSUSEDINCPCN; - -#ifndef MODE32 - if (VECTORACCESS (address) || ADDREXCEPT (address)) - INTERNALABORT (address); - - if (BIT (15)) - PATCHR15; -#endif - - if (state->Bank != USERBANK) { - /* Force User Bank. */ - (void) ARMul_SwitchMode (state, state->Mode, USER26MODE); - UNDEF_LSMUserBankWb; - } - - for (temp = 0; !BIT (temp); temp++); /* N cycle first. */ - -#ifdef MODE32 - ARMul_StoreWordN (state, address, state->Reg[temp++]); -#else - if (state->Aborted) { - (void) ARMul_LoadWordN (state, address); - - for (; temp < 16; temp++) - /* Fake the Stores as Loads. */ - if (BIT (temp)) { - /* Save this register. */ - address += 4; - - (void) ARMul_LoadWordS (state, address); - } - - if (BIT (21) && LHSReg != 15) - LSBase = WBBase; - - TAKEABORT; - return; - } else - ARMul_StoreWordN (state, address, state->Reg[temp++]); -#endif - - if (state->abortSig && !state->Aborted) { - //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); - state->Aborted = ARMul_DataAbortV; - } - -//chy 2004-05-23, needn't store other when aborted - if (state->Aborted) - goto L_stm_s_takeabort; - /* S cycles from here on. */ - for (; temp < 16; temp++) - if (BIT (temp)) { - /* Save this register. */ - address += 4; - - ARMul_StoreWordS (state, address, state->Reg[temp]); - - if (state->abortSig && !state->Aborted) { - /*XScale_set_fsr_far (state, - ARMul_CP15_R5_ST_ALIGN, - address);*/ - state->Aborted = ARMul_DataAbortV; - } - //chy 2004-05-23, needn't store other when aborted - if (state->Aborted) - goto L_stm_s_takeabort; - } - - //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode - if (state->Mode != USER26MODE && state->Mode != USER32MODE ) - /* Restore the correct bank. */ - (void) ARMul_SwitchMode (state, USER26MODE, state->Mode); - -//chy 2004-05-23,should compare the Abort Models -L_stm_s_takeabort: - if (BIT (21) && LHSReg != 15) { - if (! - (state->abortSig && state->Aborted - && state->lateabtSig == LOW)) - LSBase = WBBase; - } - - if (state->Aborted) - TAKEABORT; - } - - /* This function does the work of adding two 32bit values - together, and calculating if a carry has occurred. */ - - static ARMword - Add32 (ARMword a1, ARMword a2, int *carry) { - ARMword result = (a1 + a2); - unsigned int uresult = (unsigned int) result; - unsigned int ua1 = (unsigned int) a1; - - /* If (result == RdLo) and (state->Reg[nRdLo] == 0), - or (result > RdLo) then we have no carry. */ - if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1)) - *carry = 1; - else - *carry = 0; - - return result; - } - - /* This function does the work of multiplying - two 32bit values to give a 64bit result. */ - - static unsigned - Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) { - /* Operand register numbers. */ - int nRdHi, nRdLo, nRs, nRm; - ARMword RdHi = 0, RdLo = 0, Rm; - /* Cycle count. */ - int scount; - - nRdHi = BITS (16, 19); - nRdLo = BITS (12, 15); - nRs = BITS (8, 11); - nRm = BITS (0, 3); - - /* Needed to calculate the cycle count. */ - Rm = state->Reg[nRm]; - - /* Check for illegal operand combinations first. */ - if (nRdHi != 15 - && nRdLo != 15 - && nRs != 15 - //&& nRm != 15 && nRdHi != nRdLo && nRdHi != nRm && nRdLo != nRm) { - && nRm != 15 && nRdHi != nRdLo ) { - /* Intermediate results. */ - ARMword lo, mid1, mid2, hi; - int carry; - ARMword Rs = state->Reg[nRs]; - int sign = 0; - - if (msigned) { - /* Compute sign of result and adjust operands if necessary. */ - sign = (Rm ^ Rs) & 0x80000000; - - if (((signed int) Rm) < 0) - Rm = -Rm; - - if (((signed int) Rs) < 0) - Rs = -Rs; - } - - /* We can split the 32x32 into four 16x16 operations. This - ensures that we do not lose precision on 32bit only hosts. */ - lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF)); - mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); - mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF)); - hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); - - /* We now need to add all of these results together, taking - care to propogate the carries from the additions. */ - RdLo = Add32 (lo, (mid1 << 16), &carry); - RdHi = carry; - RdLo = Add32 (RdLo, (mid2 << 16), &carry); - RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + - ((mid2 >> 16) & 0xFFFF) + hi); - - if (sign) { - /* Negate result if necessary. */ - RdLo = ~RdLo; - RdHi = ~RdHi; - if (RdLo == 0xFFFFFFFF) { - RdLo = 0; - RdHi += 1; - } else - RdLo += 1; - } - - state->Reg[nRdLo] = RdLo; - state->Reg[nRdHi] = RdHi; - } else { - fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS, instr=0x%x\n", instr); - } - if (scc) - /* Ensure that both RdHi and RdLo are used to compute Z, - but don't let RdLo's sign bit make it to N. */ - ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); - - /* The cycle count depends on whether the instruction is a signed or - unsigned multiply, and what bits are clear in the multiplier. */ - if (msigned && (Rm & ((unsigned) 1 << 31))) - /* Invert the bits to make the check against zero. */ - Rm = ~Rm; - - if ((Rm & 0xFFFFFF00) == 0) - scount = 1; - else if ((Rm & 0xFFFF0000) == 0) - scount = 2; - else if ((Rm & 0xFF000000) == 0) - scount = 3; - else - scount = 4; - - return 2 + scount; - } - - /* This function does the work of multiplying two 32bit - values and adding a 64bit value to give a 64bit result. */ - - static unsigned - MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) { - unsigned scount; - ARMword RdLo, RdHi; - int nRdHi, nRdLo; - int carry = 0; - - nRdHi = BITS (16, 19); - nRdLo = BITS (12, 15); - - RdHi = state->Reg[nRdHi]; - RdLo = state->Reg[nRdLo]; - - scount = Multiply64 (state, instr, msigned, LDEFAULT); - - RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry); - RdHi = (RdHi + state->Reg[nRdHi]) + carry; - - state->Reg[nRdLo] = RdLo; - state->Reg[nRdHi] = RdHi; - - if (scc) - /* Ensure that both RdHi and RdLo are used to compute Z, - but don't let RdLo's sign bit make it to N. */ - ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); - - /* Extra cycle for addition. */ - return scount + 1; - } - - /* Attempt to emulate an ARMv6 instruction. - Returns non-zero upon success. */ - - static int handle_v6_insn(ARMul_State* state, ARMword instr) { - switch (BITS(20, 27)) { - case 0x03: - printf ("Unhandled v6 insn: ldr\n"); - break; - case 0x04: // UMAAL - { - const u8 rm_idx = BITS(8, 11); - const u8 rn_idx = BITS(0, 3); - const u8 rd_lo_idx = BITS(12, 15); - const u8 rd_hi_idx = BITS(16, 19); - - const u32 rm_val = state->Reg[rm_idx]; - const u32 rn_val = state->Reg[rn_idx]; - const u32 rd_lo_val = state->Reg[rd_lo_idx]; - const u32 rd_hi_val = state->Reg[rd_hi_idx]; - - const u64 result = (rn_val * rm_val) + rd_lo_val + rd_hi_val; - - state->Reg[rd_lo_idx] = (result & 0xFFFFFFFF); - state->Reg[rd_hi_idx] = ((result >> 32) & 0xFFFFFFFF); - return 1; - } - break; - case 0x06: - printf ("Unhandled v6 insn: mls/str\n"); - break; - case 0x16: - printf ("Unhandled v6 insn: smi\n"); - break; - case 0x18: - if (BITS(4, 7) == 0x9) { - /* strex */ - u32 l = LHSReg; - u32 r = RHSReg; - u32 lhs = LHS; - - bool enter = false; - - if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr))enter = true; - //StoreWord(state, lhs, RHS) - if (state->Aborted) { - TAKEABORT; - } - - if (enter) { - ARMul_StoreWordS(state, lhs, RHS); - state->Reg[DESTReg] = 0; - } - else { - state->Reg[DESTReg] = 1; - } - - return 1; - } - printf ("Unhandled v6 insn: strex\n"); - break; - case 0x19: - /* ldrex */ - if (BITS(4, 7) == 0x9) { - u32 lhs = LHS; - - state->currentexaddr = lhs; - state->currentexval = ARMul_ReadWord(state, lhs); - - LoadWord(state, instr, lhs); - return 1; - } - printf ("Unhandled v6 insn: ldrex\n"); - break; - case 0x1a: - printf ("Unhandled v6 insn: strexd\n"); - break; - case 0x1b: - printf ("Unhandled v6 insn: ldrexd\n"); - break; - case 0x1c: - if (BITS(4, 7) == 0x9) { - /* strexb */ - u32 lhs = LHS; - - bool enter = false; - - if (state->currentexval == (u32)ARMul_ReadByte(state, state->currentexaddr))enter = true; - - BUSUSEDINCPCN; - if (state->Aborted) { - TAKEABORT; - } - - if (enter) { - ARMul_StoreByte(state, lhs, RHS); - state->Reg[DESTReg] = 0; - } - else { - state->Reg[DESTReg] = 1; - } - - //printf("In %s, strexb not implemented\n", __FUNCTION__); - UNDEF_LSRBPC; - /* WRITESDEST (dest); */ - return 1; - } - printf ("Unhandled v6 insn: strexb\n"); - break; - case 0x1d: - if ((BITS(4, 7)) == 0x9) { - /* ldrexb */ - u32 lhs = LHS; - LoadByte(state, instr, lhs, LUNSIGNED); - - state->currentexaddr = lhs; - state->currentexval = (u32)ARMul_ReadByte(state, lhs); - - //state->Reg[BITS(12, 15)] = ARMul_LoadByte(state, state->Reg[BITS(16, 19)]); - //printf("ldrexb\n"); - //printf("instr is %x rm is %d\n", instr, BITS(16, 19)); - //exit(-1); - - //printf("In %s, ldrexb not implemented\n", __FUNCTION__); - return 1; - } - printf ("Unhandled v6 insn: ldrexb\n"); - break; - case 0x1e: - printf ("Unhandled v6 insn: strexh\n"); - break; - case 0x1f: - printf ("Unhandled v6 insn: ldrexh\n"); - break; - case 0x30: - printf ("Unhandled v6 insn: movw\n"); - break; - case 0x32: - printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); - break; - case 0x34: - printf ("Unhandled v6 insn: movt\n"); - break; - case 0x3f: - printf ("Unhandled v6 insn: rbit\n"); - break; - case 0x61: // SADD16, SASX, SSAX, and SSUB16 - if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 || - (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70) - { - const u8 rd_idx = BITS(12, 15); - const u8 rm_idx = BITS(0, 3); - const u8 rn_idx = BITS(16, 19); - const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF); - const s16 rn_hi = ((state->Reg[rn_idx] >> 16) & 0xFFFF); - const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF); - const s16 rm_hi = ((state->Reg[rm_idx] >> 16) & 0xFFFF); - - s32 lo_result; - s32 hi_result; - - // SADD16 - if ((instr & 0xFF0) == 0xf10) { - lo_result = (rn_lo + rm_lo); - hi_result = (rn_hi + rm_hi); - } - // SASX - else if ((instr & 0xFF0) == 0xf30) { - lo_result = (rn_lo - rm_hi); - hi_result = (rn_hi + rm_lo); - } - // SSAX - else if ((instr & 0xFF0) == 0xf50) { - lo_result = (rn_lo + rm_hi); - hi_result = (rn_hi - rm_lo); - } - // SSUB16 - else { - lo_result = (rn_lo - rm_lo); - hi_result = (rn_hi - rm_hi); - } - - state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); - - if (lo_result >= 0) { - state->GEFlag |= (1 << 16); - state->GEFlag |= (1 << 17); - } else { - state->GEFlag &= ~(1 << 16); - state->GEFlag &= ~(1 << 17); - } - - if (hi_result >= 0) { - state->GEFlag |= (1 << 18); - state->GEFlag |= (1 << 19); - } else { - state->GEFlag &= ~(1 << 18); - state->GEFlag &= ~(1 << 19); - } - - return 1; - } - // SADD8/SSUB8 - else if ((instr & 0xFF0) == 0xf90 || (instr & 0xFF0) == 0xff0) - { - const u8 rd_idx = BITS(12, 15); - const u8 rm_idx = BITS(0, 3); - const u8 rn_idx = BITS(16, 19); - const u32 rm_val = state->Reg[rm_idx]; - const u32 rn_val = state->Reg[rn_idx]; - - s32 lo_val1, lo_val2; - s32 hi_val1, hi_val2; - - // SADD8 - if ((instr & 0xFF0) == 0xf90) { - lo_val1 = (s32)(s8)(rn_val & 0xFF) + (s32)(s8)(rm_val & 0xFF); - lo_val2 = (s32)(s8)((rn_val >> 8) & 0xFF) + (s32)(s8)((rm_val >> 8) & 0xFF); - hi_val1 = (s32)(s8)((rn_val >> 16) & 0xFF) + (s32)(s8)((rm_val >> 16) & 0xFF); - hi_val2 = (s32)(s8)((rn_val >> 24) & 0xFF) + (s32)(s8)((rm_val >> 24) & 0xFF); - } - // SSUB8 - else { - lo_val1 = (s32)(s8)(rn_val & 0xFF) - (s32)(s8)(rm_val & 0xFF); - lo_val2 = (s32)(s8)((rn_val >> 8) & 0xFF) - (s32)(s8)((rm_val >> 8) & 0xFF); - hi_val1 = (s32)(s8)((rn_val >> 16) & 0xFF) - (s32)(s8)((rm_val >> 16) & 0xFF); - hi_val2 = (s32)(s8)((rn_val >> 24) & 0xFF) - (s32)(s8)((rm_val >> 24) & 0xFF); - } - - if (lo_val1 >= 0) - state->GEFlag |= (1 << 16); - else - state->GEFlag &= ~(1 << 16); - - if (lo_val2 >= 0) - state->GEFlag |= (1 << 17); - else - state->GEFlag &= ~(1 << 17); - - if (hi_val1 >= 0) - state->GEFlag |= (1 << 18); - else - state->GEFlag &= ~(1 << 18); - - if (hi_val2 >= 0) - state->GEFlag |= (1 << 19); - else - state->GEFlag &= ~(1 << 19); - - state->Reg[rd_idx] = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24)); - return 1; - } - else { - printf("Unhandled v6 insn: %08x", instr); - } - break; - case 0x62: // QADD16, QASX, QSAX, QSUB16, QADD8, and QSUB8 - { - const u8 op2 = BITS(5, 7); - - const u8 rd_idx = BITS(12, 15); - const u8 rn_idx = BITS(16, 19); - const u8 rm_idx = BITS(0, 3); - const u16 rm_lo = (state->Reg[rm_idx] & 0xFFFF); - const u16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF); - const u16 rn_lo = (state->Reg[rn_idx] & 0xFFFF); - const u16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF); - - u16 lo_result = 0; - u16 hi_result = 0; - - // QADD16 - if (op2 == 0x00) { - lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo); - hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi); - } - // QASX - else if (op2 == 0x01) { - lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi); - hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo); - } - // QSAX - else if (op2 == 0x02) { - lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi); - hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo); - } - // QSUB16 - else if (op2 == 0x03) { - lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo); - hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi); - } - // QADD8 - else if (op2 == 0x04) { - lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) | - ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8; - hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) | - ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8; - } - // QSUB8 - else if (op2 == 0x07) { - lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) | - ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8; - hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) | - ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8; - } - - state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); - return 1; - } - break; - case 0x63: - printf ("Unhandled v6 insn: shadd/shsub\n"); - break; - case 0x65: - { - u32 rd = (instr >> 12) & 0xF; - u32 rn = (instr >> 16) & 0xF; - u32 rm = (instr >> 0) & 0xF; - u32 from = state->Reg[rn]; - u32 to = state->Reg[rm]; - - if ((instr & 0xFF0) == 0xF10 || (instr & 0xFF0) == 0xF70) { // UADD16/USUB16 - u32 h1, h2; - state->Cpsr &= 0xfff0ffff; - if ((instr & 0x0F0) == 0x070) { // USUB16 - h1 = ((u16)from - (u16)to); - h2 = ((u16)(from >> 16) - (u16)(to >> 16)); - - if (!(h1 & 0xffff0000)) - state->GEFlag |= (3 << 16); - else - state->GEFlag &= ~(3 << 16); - - if (!(h2 & 0xffff0000)) - state->GEFlag |= (3 << 18); - else - state->GEFlag &= ~(3 << 18); - } - else { // UADD16 - h1 = ((u16)from + (u16)to); - h2 = ((u16)(from >> 16) + (u16)(to >> 16)); - - if (h1 & 0xffff0000) - state->GEFlag |= (3 << 16); - else - state->GEFlag &= ~(3 << 16); - - if (h2 & 0xffff0000) - state->GEFlag |= (3 << 18); - else - state->GEFlag &= ~(3 << 18); - } - - state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16)); - return 1; - } - else - if ((instr & 0xFF0) == 0xF90 || (instr & 0xFF0) == 0xFF0) { // UADD8/USUB8 - u32 b1, b2, b3, b4; - state->Cpsr &= 0xfff0ffff; - if ((instr & 0x0F0) == 0x0F0) { // USUB8 - b1 = ((u8)from - (u8)to); - b2 = ((u8)(from >> 8) - (u8)(to >> 8)); - b3 = ((u8)(from >> 16) - (u8)(to >> 16)); - b4 = ((u8)(from >> 24) - (u8)(to >> 24)); - - if (!(b1 & 0xffffff00)) - state->GEFlag |= (1 << 16); - else - state->GEFlag &= ~(1 << 16); - - if (!(b2 & 0xffffff00)) - state->GEFlag |= (1 << 17); - else - state->GEFlag &= ~(1 << 17); - - if (!(b3 & 0xffffff00)) - state->GEFlag |= (1 << 18); - else - state->GEFlag &= ~(1 << 18); - - if (!(b4 & 0xffffff00)) - state->GEFlag |= (1 << 19); - else - state->GEFlag &= ~(1 << 19); - } - else { // UADD8 - b1 = ((u8)from + (u8)to); - b2 = ((u8)(from >> 8) + (u8)(to >> 8)); - b3 = ((u8)(from >> 16) + (u8)(to >> 16)); - b4 = ((u8)(from >> 24) + (u8)(to >> 24)); - - if (b1 & 0xffffff00) - state->GEFlag |= (1 << 16); - else - state->GEFlag &= ~(1 << 16); - - if (b2 & 0xffffff00) - state->GEFlag |= (1 << 17); - else - state->GEFlag &= ~(1 << 17); - - if (b3 & 0xffffff00) - state->GEFlag |= (1 << 18); - else - state->GEFlag &= ~(1 << 18); - - if (b4 & 0xffffff00) - state->GEFlag |= (1 << 19); - else - state->GEFlag &= ~(1 << 19); - } - - state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); - return 1; - } - } - printf("Unhandled v6 insn: uasx/usax\n"); - break; - case 0x66: // UQADD16, UQASX, UQSAX, UQSUB16, UQADD8, and UQSUB8 - { - const u8 rd_idx = BITS(12, 15); - const u8 rm_idx = BITS(0, 3); - const u8 rn_idx = BITS(16, 19); - const u8 op2 = BITS(5, 7); - const u32 rm_val = state->Reg[rm_idx]; - const u32 rn_val = state->Reg[rn_idx]; - - u16 lo_val = 0; - u16 hi_val = 0; - - // UQADD16 - if (op2 == 0x00) { - lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); - hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); - } - // UQASX - else if (op2 == 0x01) { - lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); - hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); - } - // UQSAX - else if (op2 == 0x02) { - lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); - hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); - } - // UQSUB16 - else if (op2 == 0x03) { - lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); - hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); - } - // UQADD8 - else if (op2 == 0x04) { - lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | - ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; - hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | - ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; - } - // UQSUB8 - else { - lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | - ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; - hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | - ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; - } - - state->Reg[rd_idx] = ((lo_val & 0xFFFF) | hi_val << 16); - return 1; - } - break; - case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8. - { - const u8 op2 = BITS(5, 7); - - const u8 rm_idx = BITS(0, 3); - const u8 rn_idx = BITS(16, 19); - const u8 rd_idx = BITS(12, 15); - - const u32 rm_val = state->Reg[rm_idx]; - const u32 rn_val = state->Reg[rn_idx]; - - if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) - { - u32 lo_val = 0; - u32 hi_val = 0; - - // UHADD16 - if (op2 == 0x00) { - lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF); - hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); - } - // UHASX - else if (op2 == 0x01) { - lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); - hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF); - } - // UHSAX - else if (op2 == 0x02) { - lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF); - hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF); - } - // UHSUB16 - else if (op2 == 0x03) { - lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); - hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); - } - - lo_val >>= 1; - hi_val >>= 1; - - state->Reg[rd_idx] = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16); - return 1; - } - else if (op2 == 0x04 || op2 == 0x07) { - u32 sum1; - u32 sum2; - u32 sum3; - u32 sum4; - - // UHADD8 - if (op2 == 0x04) { - sum1 = (rn_val & 0xFF) + (rm_val & 0xFF); - sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF); - sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF); - sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF); - } - // UHSUB8 - else { - sum1 = (rn_val & 0xFF) - (rm_val & 0xFF); - sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF); - sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF); - sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF); - } - - sum1 >>= 1; - sum2 >>= 1; - sum3 >>= 1; - sum4 >>= 1; - - state->Reg[rd_idx] = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24); - return 1; - } - } - break; - case 0x68: - { - u32 rd = (instr >> 12) & 0xF; - u32 rn = (instr >> 16) & 0xF; - u32 rm = (instr >> 0) & 0xF; - u32 from = state->Reg[rn]; - u32 to = state->Reg[rm]; - u32 cpsr = ARMul_GetCPSR(state); - if ((instr & 0xFF0) == 0xFB0) { // SEL - u32 result; - if (cpsr & (1 << 16)) - result = from & 0xff; - else - result = to & 0xff; - if (cpsr & (1 << 17)) - result |= from & 0x0000ff00; - else - result |= to & 0x0000ff00; - if (cpsr & (1 << 18)) - result |= from & 0x00ff0000; - else - result |= to & 0x00ff0000; - if (cpsr & (1 << 19)) - result |= from & 0xff000000; - else - result |= to & 0xff000000; - state->Reg[rd] = result; - return 1; - } - } - printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); - break; - - case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB - { - const u8 op2 = BITS(5, 7); - - // SSAT16 - if (op2 == 0x01) { - const u8 rd_idx = BITS(12, 15); - const u8 rn_idx = BITS(0, 3); - const u8 num_bits = BITS(16, 19) + 1; - const s16 min = -(0x8000 >> (16 - num_bits)); - const s16 max = (0x7FFF >> (16 - num_bits)); - s16 rn_lo = (state->Reg[rn_idx]); - s16 rn_hi = (state->Reg[rn_idx] >> 16); - - if (rn_lo > max) { - rn_lo = max; - SETQ; - } else if (rn_lo < min) { - rn_lo = min; - SETQ; - } - - if (rn_hi > max) { - rn_hi = max; - SETQ; - } else if (rn_hi < min) { - rn_hi = min; - SETQ; - } - - state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16); - return 1; - } - else if (op2 == 0x03) { - const u8 rotation = BITS(10, 11) * 8; - u32 rm = ((state->Reg[BITS(0, 3)] >> rotation) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotation)) & 0xFF) & 0xFF); - if (rm & 0x80) - rm |= 0xffffff00; - - // SXTB, otherwise SXTAB - if (BITS(16, 19) == 0xf) - state->Reg[BITS(12, 15)] = rm; - else - state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; - - return 1; - } - else { - printf("Unimplemented op: SSAT"); - } - } - break; - - case 0x6b: // REV, REV16, SXTH, and SXTAH - { - const u8 op2 = BITS(5, 7); - - // REV - if (op2 == 0x01) { - DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); - return 1; - } - // REV16 - else if (op2 == 0x05) { - DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8); - return 1; - } - else if (op2 == 0x03) { - const u8 rotate = BITS(10, 11) * 8; - - u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF); - if (rm & 0x8000) - rm |= 0xffff0000; - - // SXTH, otherwise SXTAH - if (BITS(16, 19) == 15) - state->Reg[BITS(12, 15)] = rm; - else - state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; - - return 1; - } - } - break; - - case 0x6c: // UXTB16 and UXTAB16 - { - const u8 rm_idx = BITS(0, 3); - const u8 rn_idx = BITS(16, 19); - const u8 rd_idx = BITS(12, 15); - const u32 rm_val = state->Reg[rm_idx]; - const u32 rn_val = state->Reg[rn_idx]; - const u32 rotation = BITS(10, 11) * 8; - const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); - - // UXTB16 - if ((instr & 0xf03f0) == 0xf0070) { - state->Reg[rd_idx] = rotated_rm & 0x00FF00FF; - } - else { // UXTAB16 - const u8 lo_rotated = (rotated_rm & 0xFF); - const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated; - - const u8 hi_rotated = (rotated_rm >> 16) & 0xFF; - const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated; - - state->Reg[rd_idx] = ((hi_result << 16) | (lo_result & 0xFFFF)); - } - - return 1; - } - break; - case 0x6e: // USAT, USAT16, UXTB, and UXTAB - { - const u8 op2 = BITS(5, 7); - - // USAT16 - if (op2 == 0x01) { - const u8 rd_idx = BITS(12, 15); - const u8 rn_idx = BITS(0, 3); - const u8 num_bits = BITS(16, 19); - const s16 max = 0xFFFF >> (16 - num_bits); - s16 rn_lo = (state->Reg[rn_idx]); - s16 rn_hi = (state->Reg[rn_idx] >> 16); - - if (max < rn_lo) { - rn_lo = max; - SETQ; - } else if (rn_lo < 0) { - rn_lo = 0; - SETQ; - } - - if (max < rn_hi) { - rn_hi = max; - SETQ; - } else if (rn_hi < 0) { - rn_hi = 0; - SETQ; - } - - state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF); - return 1; - } - else if (op2 == 0x03) { - const u8 rotate = BITS(10, 11) * 8; - const u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFF) & 0xFF); - - if (BITS(16, 19) == 0xf) - /* UXTB */ - state->Reg[BITS(12, 15)] = rm; - else - /* UXTAB */ - state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; - - return 1; - } - else { - printf("Unimplemented op: USAT"); - } - } - break; - - case 0x6f: // UXTH, UXTAH, and REVSH. - { - const u8 op2 = BITS(5, 7); - - // REVSH - if (op2 == 0x05) { - DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8); - if (DEST & 0x8000) - DEST |= 0xffff0000; - return 1; - } - // UXTH and UXTAH - else if (op2 == 0x03) { - const u8 rotate = BITS(10, 11) * 8; - const ARMword rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF); - - // UXTH - if (BITS(16, 19) == 0xf) { - state->Reg[BITS(12, 15)] = rm; - } - // UXTAH - else { - state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm; - } - - return 1; - } - } - case 0x70: - // ichfly - // SMUAD, SMUSD, SMLAD, and SMLSD - if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 || - (instr & 0xd0) == 0x10 || (instr & 0xd0) == 0x50) - { - const u8 rd_idx = BITS(16, 19); - const u8 rn_idx = BITS(0, 3); - const u8 rm_idx = BITS(8, 11); - const u8 ra_idx = BITS(12, 15); - const bool do_swap = (BIT(5) == 1); - - u32 rm_val = state->Reg[rm_idx]; - const u32 rn_val = state->Reg[rn_idx]; - - if (do_swap) - rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); - - const s16 rm_lo = (rm_val & 0xFFFF); - const s16 rm_hi = ((rm_val >> 16) & 0xFFFF); - const s16 rn_lo = (rn_val & 0xFFFF); - const s16 rn_hi = ((rn_val >> 16) & 0xFFFF); - - const u32 product1 = (rn_lo * rm_lo); - const u32 product2 = (rn_hi * rm_hi); - - // SMUAD and SMLAD - if (BIT(6) == 0) { - state->Reg[rd_idx] = product1 + product2; - - if (BITS(12, 15) != 15) { - state->Reg[rd_idx] += state->Reg[ra_idx]; - if (ARMul_AddOverflowQ(product1 + product2, state->Reg[ra_idx])) - SETQ; - } - - if (ARMul_AddOverflowQ(product1, product2)) - SETQ; - } - // SMUSD and SMLSD - else { - state->Reg[rd_idx] = product1 - product2; - - if (BITS(12, 15) != 15) { - state->Reg[rd_idx] += state->Reg[ra_idx]; - - if (ARMul_AddOverflowQ(product1 - product2, state->Reg[ra_idx])) - SETQ; - } - } - - return 1; - } - break; - case 0x74: // SMLALD and SMLSLD - { - const u8 rm_idx = BITS(8, 11); - const u8 rn_idx = BITS(0, 3); - const u8 rdlo_idx = BITS(12, 15); - const u8 rdhi_idx = BITS(16, 19); - const bool do_swap = (BIT(5) == 1); - - const u32 rdlo_val = state->Reg[rdlo_idx]; - const u32 rdhi_val = state->Reg[rdhi_idx]; - const u32 rn_val = state->Reg[rn_idx]; - u32 rm_val = state->Reg[rm_idx]; - - if (do_swap) - rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); - - const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); - const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); - s64 result; - - // SMLALD - if (BIT(6) == 0) { - result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); - } - // SMLSLD - else { - result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); - } - - state->Reg[rdlo_idx] = (result & 0xFFFFFFFF); - state->Reg[rdhi_idx] = ((result >> 32) & 0xFFFFFFFF); - return 1; - } - break; - case 0x75: // SMMLA, SMMUL, and SMMLS - { - const u8 rm_idx = BITS(8, 11); - const u8 rn_idx = BITS(0, 3); - const u8 ra_idx = BITS(12, 15); - const u8 rd_idx = BITS(16, 19); - const bool do_round = (BIT(5) == 1); - - const u32 rm_val = state->Reg[rm_idx]; - const u32 rn_val = state->Reg[rn_idx]; - - // Assume SMMUL by default. - s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; - - if (ra_idx != 15) { - const u32 ra_val = state->Reg[ra_idx]; - - // SMMLA, otherwise SMMLS - if (BIT(6) == 0) - result += ((s64)ra_val << 32); - else - result = ((s64)ra_val << 32) - result; - } - - if (do_round) - result += 0x80000000; - - state->Reg[rd_idx] = ((result >> 32) & 0xFFFFFFFF); - return 1; - } - break; - case 0x78: - if (BITS(20, 24) == 0x18) - { - const u8 rm_idx = BITS(8, 11); - const u8 rn_idx = BITS(0, 3); - const u8 rd_idx = BITS(16, 19); - - const u32 rm_val = state->Reg[rm_idx]; - const u32 rn_val = state->Reg[rn_idx]; - - const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF); - const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF); - const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF); - const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF); - - u32 finalDif = (diff1 + diff2 + diff3 + diff4); - - // Op is USADA8 if true. - const u8 ra_idx = BITS(12, 15); - if (ra_idx != 15) - finalDif += state->Reg[ra_idx]; - - state->Reg[rd_idx] = finalDif; - return 1; - } - break; - case 0x7a: - printf ("Unhandled v6 insn: usbfx\n"); - break; - case 0x7c: - printf ("Unhandled v6 insn: bfc/bfi\n"); - break; - case 0x84: - printf ("Unhandled v6 insn: srs\n"); - break; - default: - break; - } - printf("Unhandled v6 insn: UNKNOWN: %08x %08X\n", instr, BITS(20, 27)); - return 0; - }
\ No newline at end of file diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp index 8ab5ef160..a0e041fa0 100644 --- a/src/core/arm/interpreter/arminit.cpp +++ b/src/core/arm/interpreter/arminit.cpp @@ -25,24 +25,13 @@ void ARMul_EmulateInit(); ARMul_State* ARMul_NewState(ARMul_State* state); void ARMul_Reset (ARMul_State* state); -ARMword ARMul_DoCycle(ARMul_State* state); -unsigned ARMul_DoCoPro(ARMul_State* state); -ARMword ARMul_DoProg(ARMul_State* state); -ARMword ARMul_DoInstr(ARMul_State* state); -void ARMul_Abort(ARMul_State* state, ARMword address); unsigned ARMul_MultTable[32] = { 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16 }; -ARMword ARMul_ImmedTable[4096]; /* immediate DP LHS values */ -char ARMul_BitList[256]; /* number of bits in a byte table */ - -void arm_dyncom_Abort(ARMul_State * state, ARMword vector) -{ - ARMul_Abort(state, vector); -} - +ARMword ARMul_ImmedTable[4096]; // immediate DP LHS values +char ARMul_BitList[256]; // number of bits in a byte table /***************************************************************************\ * Call this routine once to set up the emulator's tables. * @@ -51,18 +40,21 @@ void ARMul_EmulateInit() { unsigned int i, j; - for (i = 0; i < 4096; i++) { /* the values of 12 bit dp rhs's */ + // the values of 12 bit dp rhs's + for (i = 0; i < 4096; i++) { ARMul_ImmedTable[i] = ROTATER (i & 0xffL, (i >> 7L) & 0x1eL); } - for (i = 0; i < 256; ARMul_BitList[i++] = 0); /* how many bits in LSM */ + // how many bits in LSM + for (i = 0; i < 256; ARMul_BitList[i++] = 0); for (j = 1; j < 256; j <<= 1) for (i = 0; i < 256; i++) if ((i & j) > 0) ARMul_BitList[i]++; + // you always need 4 times these values for (i = 0; i < 256; i++) - ARMul_BitList[i] *= 4; /* you always need 4 times these values */ + ARMul_BitList[i] *= 4; } @@ -178,115 +170,3 @@ void ARMul_Reset(ARMul_State* state) state->NumCcycles = 0; state->NumFcycles = 0; } - - -/***************************************************************************\ -* Emulate the execution of an entire program. Start the correct emulator * -* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the * -* address of the last instruction that is executed. * -\***************************************************************************/ -ARMword ARMul_DoProg(ARMul_State* state) -{ - ARMword pc = 0; - - state->Emulate = RUN; - while (state->Emulate != STOP) { - state->Emulate = RUN; - - if (state->prog32Sig && ARMul_MODE32BIT) { - pc = ARMul_Emulate32 (state); - } - else { - //pc = ARMul_Emulate26 (state); - } - } - - return pc; -} - -/***************************************************************************\ -* Emulate the execution of one instruction. Start the correct emulator * -* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the * -* address of the instruction that is executed. * -\***************************************************************************/ -ARMword ARMul_DoInstr(ARMul_State* state) -{ - ARMword pc = 0; - - state->Emulate = ONCE; - - if (state->prog32Sig && ARMul_MODE32BIT) { - pc = ARMul_Emulate32 (state); - } - - return pc; -} - -/***************************************************************************\ -* This routine causes an Abort to occur, including selecting the correct * -* mode, register bank, and the saving of registers. Call with the * -* appropriate vector's memory address (0,4,8 ....) * -\***************************************************************************/ -void ARMul_Abort(ARMul_State* state, ARMword vector) -{ - ARMword temp; - int isize = INSN_SIZE; - int esize = (TFLAG ? 0 : 4); - int e2size = (TFLAG ? -4 : 0); - - state->Aborted = FALSE; - - if (state->prog32Sig) - if (ARMul_MODE26BIT) - temp = R15PC; - else - temp = state->Reg[15]; - else - temp = R15PC | ECC | ER15INT | EMODE; - - switch (vector) { - case ARMul_ResetV: /* RESET */ - SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE, - 0); - break; - case ARMul_UndefinedInstrV: /* Undefined Instruction */ - SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE, - isize); - break; - case ARMul_SWIV: /* Software Interrupt */ - SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, - isize); - break; - case ARMul_PrefetchAbortV: /* Prefetch Abort */ - state->AbortAddr = 1; - SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, - esize); - break; - case ARMul_DataAbortV: /* Data Abort */ - SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, - e2size); - break; - case ARMul_AddrExceptnV: /* Address Exception */ - SETABORT (IBIT, SVC26MODE, isize); - break; - case ARMul_IRQV: /* IRQ */ - SETABORT (IBIT, - state->prog32Sig ? IRQ32MODE : IRQ26MODE, - esize); - break; - case ARMul_FIQV: /* FIQ */ - SETABORT (INTBITS, - state->prog32Sig ? FIQ32MODE : FIQ26MODE, - esize); - break; - } - - if (ARMul_MODE32BIT) { - /*if (state->mmu.control & CONTROL_VECTOR) - vector += 0xffff0000; //for v4 high exception address*/ - if (state->vector_remap_flag) - vector += state->vector_remap_addr; /* support some remap function in LPC processor */ - ARMul_SetR15 (state, vector); - } else - ARMul_SetR15 (state, R15CCINTMODE | vector); -} diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index 5a8f09b22..fd90fb0a4 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp @@ -20,395 +20,13 @@ #include "core/arm/disassembler/arm_disasm.h" #include "core/mem_map.h" - -static ARMword ModeToBank (ARMword); - -/* This routine returns the value of a register from a mode. */ - -ARMword -ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) -{ - mode &= MODEBITS; - if (mode != state->Mode) - return (state->RegBank[ModeToBank ((ARMword) mode)][reg]); - else - return (state->Reg[reg]); -} - -/* This routine sets the value of a register for a mode. */ - -void -ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) -{ - mode &= MODEBITS; - if (mode != state->Mode) - state->RegBank[ModeToBank ((ARMword) mode)][reg] = value; - else - state->Reg[reg] = value; -} - -/* This routine returns the value of the PC, mode independently. */ - -ARMword -ARMul_GetPC (ARMul_State * state) -{ - if (state->Mode > SVC26MODE) - return state->Reg[15]; - else - return R15PC; -} - -/* This routine returns the value of the PC, mode independently. */ - -ARMword -ARMul_GetNextPC (ARMul_State * state) -{ - if (state->Mode > SVC26MODE) - return state->Reg[15] + INSN_SIZE; - else - return (state->Reg[15] + INSN_SIZE) & R15PCBITS; -} - -/* This routine sets the value of the PC. */ - -void -ARMul_SetPC (ARMul_State * state, ARMword value) -{ - if (ARMul_MODE32BIT) - state->Reg[15] = value & PCBITS; - else - state->Reg[15] = R15CCINTMODE | (value & R15PCBITS); - FLUSHPIPE; -} - -/* This routine returns the value of register 15, mode independently. */ - -ARMword -ARMul_GetR15 (ARMul_State * state) -{ - if (state->Mode > SVC26MODE) - return (state->Reg[15]); - else - return (R15PC | ECC | ER15INT | EMODE); -} - -/* This routine sets the value of Register 15. */ - -void -ARMul_SetR15 (ARMul_State * state, ARMword value) -{ - if (ARMul_MODE32BIT) - state->Reg[15] = value & PCBITS; - else { - state->Reg[15] = value; - ARMul_R15Altered (state); - } - FLUSHPIPE; -} - -/* This routine returns the value of the CPSR. */ - -ARMword -ARMul_GetCPSR (ARMul_State * state) -{ - //chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator - //return (CPSR | state->Cpsr); for gdb20030716 - return (CPSR); //had be tested in old skyeye with gdb5.0-5.3 -} - -/* This routine sets the value of the CPSR. */ - -void -ARMul_SetCPSR (ARMul_State * state, ARMword value) -{ - state->Cpsr = value; - ARMul_CPSRAltered (state); -} - -/* This routine does all the nasty bits involved in a write to the CPSR, - including updating the register bank, given a MSR instruction. */ - -void -ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) -{ - state->Cpsr = ARMul_GetCPSR (state); - //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode - if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { - /* In user mode, only write flags. */ - if (BIT (16)) - SETPSR_C (state->Cpsr, rhs); - if (BIT (17)) - SETPSR_X (state->Cpsr, rhs); - if (BIT (18)) - SETPSR_S (state->Cpsr, rhs); - } - if (BIT (19)) - SETPSR_F (state->Cpsr, rhs); - ARMul_CPSRAltered (state); -} - -/* Get an SPSR from the specified mode. */ - -ARMword -ARMul_GetSPSR (ARMul_State * state, ARMword mode) -{ - ARMword bank = ModeToBank (mode & MODEBITS); - - if (!BANK_CAN_ACCESS_SPSR (bank)) - return ARMul_GetCPSR (state); - - return state->Spsr[bank]; -} - -/* This routine does a write to an SPSR. */ - -void -ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) -{ - ARMword bank = ModeToBank (mode & MODEBITS); - - if (BANK_CAN_ACCESS_SPSR (bank)) - state->Spsr[bank] = value; -} - -/* This routine does a write to the current SPSR, given an MSR instruction. */ - -void -ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs) -{ - if (BANK_CAN_ACCESS_SPSR (state->Bank)) { - if (BIT (16)) - SETPSR_C (state->Spsr[state->Bank], rhs); - if (BIT (17)) - SETPSR_X (state->Spsr[state->Bank], rhs); - if (BIT (18)) - SETPSR_S (state->Spsr[state->Bank], rhs); - if (BIT (19)) - SETPSR_F (state->Spsr[state->Bank], rhs); - } -} - -/* This routine updates the state of the emulator after the Cpsr has been - changed. Both the processor flags and register bank are updated. */ - -void -ARMul_CPSRAltered (ARMul_State * state) -{ - ARMword oldmode; - - if (state->prog32Sig == LOW) - state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS); - - oldmode = state->Mode; - - /*if (state->Mode != (state->Cpsr & MODEBITS)) { - state->Mode = - ARMul_SwitchMode (state, state->Mode, - state->Cpsr & MODEBITS); - - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - }*/ - //state->Cpsr &= ~MODEBITS; - - ASSIGNINT (state->Cpsr & INTBITS); - //state->Cpsr &= ~INTBITS; - ASSIGNN ((state->Cpsr & NBIT) != 0); - //state->Cpsr &= ~NBIT; - ASSIGNZ ((state->Cpsr & ZBIT) != 0); - //state->Cpsr &= ~ZBIT; - ASSIGNC ((state->Cpsr & CBIT) != 0); - //state->Cpsr &= ~CBIT; - ASSIGNV ((state->Cpsr & VBIT) != 0); - //state->Cpsr &= ~VBIT; - ASSIGNQ ((state->Cpsr & QBIT) != 0); - //state->Cpsr &= ~QBIT; - state->GEFlag = (state->Cpsr & 0x000F0000); -#ifdef MODET - ASSIGNT ((state->Cpsr & TBIT) != 0); - //state->Cpsr &= ~TBIT; -#endif - - if (oldmode > SVC26MODE) { - if (state->Mode <= SVC26MODE) { - state->Emulate = CHANGEMODE; - state->Reg[15] = ECC | ER15INT | EMODE | R15PC; - } - } else { - if (state->Mode > SVC26MODE) { - state->Emulate = CHANGEMODE; - state->Reg[15] = R15PC; - } else - state->Reg[15] = ECC | ER15INT | EMODE | R15PC; - } -} - -/* This routine updates the state of the emulator after register 15 has - been changed. Both the processor flags and register bank are updated. - This routine should only be called from a 26 bit mode. */ - -void -ARMul_R15Altered (ARMul_State * state) -{ - if (state->Mode != R15MODE) { - state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE); - state->NtransSig = (state->Mode & 3) ? HIGH : LOW; - } - - if (state->Mode > SVC26MODE) - state->Emulate = CHANGEMODE; - - ASSIGNR15INT (R15INT); - - ASSIGNN ((state->Reg[15] & NBIT) != 0); - ASSIGNZ ((state->Reg[15] & ZBIT) != 0); - ASSIGNC ((state->Reg[15] & CBIT) != 0); - ASSIGNV ((state->Reg[15] & VBIT) != 0); -} - -/* This routine controls the saving and restoring of registers across mode - changes. The regbank matrix is largely unused, only rows 13 and 14 are - used across all modes, 8 to 14 are used for FIQ, all others use the USER - column. It's easier this way. old and new parameter are modes numbers. - Notice the side effect of changing the Bank variable. */ - -ARMword -ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) -{ - unsigned i; - ARMword oldbank; - ARMword newbank; - static int revision_value = 53; - - oldbank = ModeToBank (oldmode); - newbank = state->Bank = ModeToBank (newmode); - - /* Do we really need to do it? */ - if (oldbank != newbank) { - if (oldbank == 3 && newbank == 2) { - //printf("icounter is %d PC is %x MODE CHANGED : %d --> %d\n", state->NumInstrs, state->pc, oldbank, newbank); - if (state->NumInstrs >= 5832487) { -// printf("%d, ", state->NumInstrs + revision_value); -// printf("revision_value : %d\n", revision_value); - revision_value ++; - } - } - /* Save away the old registers. */ - switch (oldbank) { - case USERBANK: - case IRQBANK: - case SVCBANK: - case ABORTBANK: - case UNDEFBANK: - if (newbank == FIQBANK) - for (i = 8; i < 13; i++) - state->RegBank[USERBANK][i] = - state->Reg[i]; - state->RegBank[oldbank][13] = state->Reg[13]; - state->RegBank[oldbank][14] = state->Reg[14]; - break; - case FIQBANK: - for (i = 8; i < 15; i++) - state->RegBank[FIQBANK][i] = state->Reg[i]; - break; - case DUMMYBANK: - for (i = 8; i < 15; i++) - state->RegBank[DUMMYBANK][i] = 0; - break; - default: - abort (); - } - - /* Restore the new registers. */ - switch (newbank) { - case USERBANK: - case IRQBANK: - case SVCBANK: - case ABORTBANK: - case UNDEFBANK: - if (oldbank == FIQBANK) - for (i = 8; i < 13; i++) - state->Reg[i] = - state->RegBank[USERBANK][i]; - state->Reg[13] = state->RegBank[newbank][13]; - state->Reg[14] = state->RegBank[newbank][14]; - break; - case FIQBANK: - for (i = 8; i < 15; i++) - state->Reg[i] = state->RegBank[FIQBANK][i]; - break; - case DUMMYBANK: - for (i = 8; i < 15; i++) - state->Reg[i] = 0; - break; - default: - abort (); - } - } - - return newmode; -} - -/* Given a processor mode, this routine returns the - register bank that will be accessed in that mode. */ - -static ARMword -ModeToBank (ARMword mode) -{ - static ARMword bankofmode[] = { - USERBANK, FIQBANK, IRQBANK, SVCBANK, - DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, - DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, - DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, - USERBANK, FIQBANK, IRQBANK, SVCBANK, - DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK, - DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK, - DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK - }; - - if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0]))) - return DUMMYBANK; - - return bankofmode[mode]; -} - -/* Returns the register number of the nth register in a reg list. */ - -unsigned -ARMul_NthReg (ARMword instr, unsigned number) -{ - unsigned bit, upto; - - for (bit = 0, upto = 0; upto <= number; bit++) - if (BIT (bit)) - upto++; - - return (bit - 1); -} - -/* Unsigned sum of absolute difference */ +// Unsigned sum of absolute difference u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) { - if (left > right) - return left - right; + if (left > right) + return left - right; - return right - left; -} - -/* Assigns the N and Z flags depending on the value of result. */ - -void -ARMul_NegZero (ARMul_State * state, ARMword result) -{ - if (NEG (result)) { - SETN; - CLEARZ; - } else if (result == 0) { - CLEARN; - SETZ; - } else { - CLEARN; - CLEARZ; - } + return right - left; } // Add with carry, indicates if a carry-out or signed overflow occurred. @@ -441,23 +59,6 @@ bool SubOverflow(ARMword a, ARMword b, ARMword result) (POS(a) && NEG(b) && NEG(result))); } -/* Assigns the C flag after an addition of a and b to give result. */ - -void -ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) -{ - ASSIGNC ((NEG (a) && NEG (b)) || - (NEG (a) && POS (result)) || (NEG (b) && POS (result))); -} - -/* Assigns the V flag after an addition of a and b to give result. */ - -void -ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) -{ - ASSIGNV (AddOverflow (a, b, result)); -} - // Returns true if the Q flag should be set as a result of overflow. bool ARMul_AddOverflowQ(ARMword a, ARMword b) { @@ -468,24 +69,7 @@ bool ARMul_AddOverflowQ(ARMword a, ARMword b) return false; } -/* Assigns the C flag after an subtraction of a and b to give result. */ - -void -ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) -{ - ASSIGNC ((NEG (a) && POS (b)) || - (NEG (a) && POS (result)) || (POS (b) && POS (result))); -} - -/* Assigns the V flag after an subtraction of a and b to give result. */ - -void -ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) -{ - ASSIGNV (SubOverflow (a, b, result)); -} - -/* 8-bit signed saturated addition */ +// 8-bit signed saturated addition u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) { u8 result = left + right; @@ -500,7 +84,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) return result; } -/* 8-bit signed saturated subtraction */ +// 8-bit signed saturated subtraction u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) { u8 result = left - right; @@ -515,7 +99,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) return result; } -/* 16-bit signed saturated addition */ +// 16-bit signed saturated addition u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) { u16 result = left + right; @@ -530,7 +114,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) return result; } -/* 16-bit signed saturated subtraction */ +// 16-bit signed saturated subtraction u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) { u16 result = left - right; @@ -545,7 +129,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) return result; } -/* 8-bit unsigned saturated addition */ +// 8-bit unsigned saturated addition u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) { u8 result = left + right; @@ -556,7 +140,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) return result; } -/* 16-bit unsigned saturated addition */ +// 16-bit unsigned saturated addition u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) { u16 result = left + right; @@ -567,7 +151,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) return result; } -/* 8-bit unsigned saturated subtraction */ +// 8-bit unsigned saturated subtraction u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) { if (left <= right) @@ -576,7 +160,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) return left - right; } -/* 16-bit unsigned saturated subtraction */ +// 16-bit unsigned saturated subtraction u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) { if (left <= right) @@ -620,444 +204,3 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) *saturation_occurred = false; return (u32)value; } - -/* This function does the work of generating the addresses used in an - LDC instruction. The code here is always post-indexed, it's up to the - caller to get the input address correct and to handle base register - modification. It also handles the Busy-Waiting. */ - -void -ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address) -{ - unsigned cpab; - ARMword data; - - UNDEF_LSCPCBaseWb; - //printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address); - /*chy 2004-05-23 should update this function in the future,should concern dataabort*/ -// chy 2004-05-25 , fix it now,so needn't printf -// printf("SKYEYE ARMul_LDC, should update this function!!!!!\n"); - //exit(-1); - - //if (!CP_ACCESS_ALLOWED (state, CPNum)) { - if (!state->LDC[CPNum]) { - /* - printf - ("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n", - CPNum, instr, address); - */ - ARMul_UndefInstr (state, instr); - return; - } - - /*if (ADDREXCEPT (address)) - INTERNALABORT (address);*/ - - cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0); - while (cpab == ARMul_BUSY) { - ARMul_Icycles (state, 1, 0); - - if (IntPending (state)) { - cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, - instr, 0); - return; - } else - cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, - 0); - } - if (cpab == ARMul_CANT) { - /* - printf - ("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n", - CPNum, instr, address); - */ - CPTAKEABORT; - return; - } - - cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0); - data = ARMul_LoadWordN (state, address); - //chy 2004-05-25 - if (state->abortSig || state->Aborted) - goto L_ldc_takeabort; - - BUSUSEDINCPCN; -//chy 2004-05-25 - /* - if (BIT (21)) - LSBase = state->Base; - */ - - cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); - - while (cpab == ARMul_INC) { - address += 4; - data = ARMul_LoadWordN (state, address); - //chy 2004-05-25 - if (state->abortSig || state->Aborted) - goto L_ldc_takeabort; - - cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); - } - -//chy 2004-05-25 -L_ldc_takeabort: - if (BIT (21)) { - if (! - ((state->abortSig || state->Aborted) - && state->lateabtSig == LOW)) - LSBase = state->Base; - } - - if (state->abortSig || state->Aborted) - TAKEABORT; -} - -/* This function does the work of generating the addresses used in an - STC instruction. The code here is always post-indexed, it's up to the - caller to get the input address correct and to handle base register - modification. It also handles the Busy-Waiting. */ - -void -ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) -{ - unsigned cpab; - ARMword data; - - UNDEF_LSCPCBaseWb; - - //printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address); - /*chy 2004-05-23 should update this function in the future,should concern dataabort */ -// skyeye_instr_debug=0;printf("SKYEYE debug end!!!!\n"); -// chy 2004-05-25 , fix it now,so needn't printf -// printf("SKYEYE ARMul_STC, should update this function!!!!!\n"); - - //exit(-1); - //if (!CP_ACCESS_ALLOWED (state, CPNum)) { - if (!state->STC[CPNum]) { - /* - printf - ("SKYEYE ARMul_STC,NOT ALLOW, undefinstr, CPnum is %x, instr %x, addr %x\n", - CPNum, instr, address); - */ - ARMul_UndefInstr (state, instr); - return; - } - - /*if (ADDREXCEPT (address) || VECTORACCESS (address)) - INTERNALABORT (address);*/ - - cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data); - while (cpab == ARMul_BUSY) { - ARMul_Icycles (state, 1, 0); - if (IntPending (state)) { - cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, - instr, 0); - return; - } else - cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, - &data); - } - - if (cpab == ARMul_CANT) { - /* - printf - ("SKYEYE ARMul_STC,CANT, undefinstr, CPnum is %x, instr %x, addr %x\n", - CPNum, instr, address); - */ - CPTAKEABORT; - return; - } - /*#ifndef MODE32 - if (ADDREXCEPT (address) || VECTORACCESS (address)) - INTERNALABORT (address); - #endif*/ - BUSUSEDINCPCN; -//chy 2004-05-25 - /* - if (BIT (21)) - LSBase = state->Base; - */ - cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); - ARMul_StoreWordN (state, address, data); - //chy 2004-05-25 - if (state->abortSig || state->Aborted) - goto L_stc_takeabort; - - while (cpab == ARMul_INC) { - address += 4; - cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); - ARMul_StoreWordN (state, address, data); - //chy 2004-05-25 - if (state->abortSig || state->Aborted) - goto L_stc_takeabort; - } -//chy 2004-05-25 -L_stc_takeabort: - if (BIT (21)) { - if (! - ((state->abortSig || state->Aborted) - && state->lateabtSig == LOW)) - LSBase = state->Base; - } - - if (state->abortSig || state->Aborted) - TAKEABORT; -} - -/* This function does the Busy-Waiting for an MCR instruction. */ - -void -ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) -{ - unsigned cpab; - int cm = BITS(0, 3) & 0xf; - int cp = BITS(5, 7) & 0x7; - int rd = BITS(12, 15) & 0xf; - int cn = BITS(16, 19) & 0xf; - int cpopc = BITS(21, 23) & 0x7; - - if (CPNum == 15 && source == 0) //Cache flush - { - return; - } - - //printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source); - //if (!CP_ACCESS_ALLOWED (state, CPNum)) { - if (!state->MCR[CPNum]) { - //chy 2004-07-19 should fix in the future ????!!!! - LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x",CPNum, source); - ARMul_UndefInstr (state, instr); - return; - } - - //DEBUG("SKYEYE ARMul_MCR p%d, %d, r%d, c%d, c%d, %d\n", CPNum, cpopc, rd, cn, cm, cp); - //DEBUG("plutoo: MCR not implemented\n"); - //exit(1); - //return; - - cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); - - while (cpab == ARMul_BUSY) { - ARMul_Icycles (state, 1, 0); - - if (IntPending (state)) { - cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, - instr, 0); - return; - } else - cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, - source); - } - - if (cpab == ARMul_CANT) { - LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x", instr, CPNum, source); //ichfly todo - //ARMul_Abort (state, ARMul_UndefinedInstrV); - } else { - BUSUSEDINCPCN; - ARMul_Ccycles (state, 1, 0); - } -} - -/* This function does the Busy-Waiting for an MCRR instruction. */ - -void -ARMul_MCRR (ARMul_State * state, ARMword instr, ARMword source1, ARMword source2) -{ - unsigned cpab; - - //if (!CP_ACCESS_ALLOWED (state, CPNum)) { - if (!state->MCRR[CPNum]) { - ARMul_UndefInstr (state, instr); - return; - } - - cpab = (state->MCRR[CPNum]) (state, ARMul_FIRST, instr, source1, source2); - - while (cpab == ARMul_BUSY) { - ARMul_Icycles (state, 1, 0); - - if (IntPending (state)) { - cpab = (state->MCRR[CPNum]) (state, ARMul_INTERRUPT, - instr, 0, 0); - return; - } else - cpab = (state->MCRR[CPNum]) (state, ARMul_BUSY, instr, - source1, source2); - } - if (cpab == ARMul_CANT) { - printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x, source %x %x\n", __FUNCTION__, CPNum, instr, source1, source2); - ARMul_Abort (state, ARMul_UndefinedInstrV); - } else { - BUSUSEDINCPCN; - ARMul_Ccycles (state, 1, 0); - } -} - -/* This function does the Busy-Waiting for an MRC instruction. */ - -ARMword ARMul_MRC (ARMul_State * state, ARMword instr) -{ - int cm = BITS(0, 3) & 0xf; - int cp = BITS(5, 7) & 0x7; - int rd = BITS(12, 15) & 0xf; - int cn = BITS(16, 19) & 0xf; - int cpopc = BITS(21, 23) & 0x7; - - if (cn == 13 && cm == 0 && cp == 3) { //c13,c0,3; returns CPU svc buffer - ARMword result = Memory::KERNEL_MEMORY_VADDR; - - if (result != -1) { - return result; - } - } - - //DEBUG("SKYEYE ARMul_MRC p%d, %d, r%d, c%d, c%d, %d\n", CPNum, cpopc, rd, cn, cm, cp); - //DEBUG("plutoo: MRC not implemented\n"); - //return; - - unsigned cpab; - ARMword result = 0; - - //printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr); - //if (!CP_ACCESS_ALLOWED (state, CPNum)) { - if (!state->MRC[CPNum]) { - //chy 2004-07-19 should fix in the future????!!!! - LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x", CPNum, instr); - ARMul_UndefInstr (state, instr); - return -1; - } - - cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); - while (cpab == ARMul_BUSY) { - ARMul_Icycles (state, 1, 0); - if (IntPending (state)) { - cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, - instr, 0); - return (0); - } else - cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, - &result); - } - if (cpab == ARMul_CANT) { - printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr); - ARMul_Abort (state, ARMul_UndefinedInstrV); - /* Parent will destroy the flags otherwise. */ - result = ECC; - } else { - BUSUSEDINCPCN; - ARMul_Ccycles (state, 1, 0); - ARMul_Icycles (state, 1, 0); - } - - return result; -} - -/* This function does the Busy-Waiting for an MRRC instruction. (to verify) */ - -void -ARMul_MRRC (ARMul_State * state, ARMword instr, ARMword * dest1, ARMword * dest2) -{ - unsigned cpab; - ARMword result1 = 0; - ARMword result2 = 0; - - //if (!CP_ACCESS_ALLOWED (state, CPNum)) { - if (!state->MRRC[CPNum]) { - ARMul_UndefInstr (state, instr); - return; - } - - cpab = (state->MRRC[CPNum]) (state, ARMul_FIRST, instr, &result1, &result2); - while (cpab == ARMul_BUSY) { - ARMul_Icycles (state, 1, 0); - if (IntPending (state)) { - cpab = (state->MRRC[CPNum]) (state, ARMul_INTERRUPT, - instr, 0, 0); - return; - } else - cpab = (state->MRRC[CPNum]) (state, ARMul_BUSY, instr, - &result1, &result2); - } - if (cpab == ARMul_CANT) { - printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x\n", __FUNCTION__, CPNum, instr); - ARMul_Abort (state, ARMul_UndefinedInstrV); - } else { - BUSUSEDINCPCN; - ARMul_Ccycles (state, 1, 0); - ARMul_Icycles (state, 1, 0); - } - - *dest1 = result1; - *dest2 = result2; -} - -/* This function does the Busy-Waiting for an CDP instruction. */ - -void -ARMul_CDP (ARMul_State * state, ARMword instr) -{ - unsigned cpab; - - //if (!CP_ACCESS_ALLOWED (state, CPNum)) { - if (!state->CDP[CPNum]) { - ARMul_UndefInstr (state, instr); - return; - } - cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr); - while (cpab == ARMul_BUSY) { - ARMul_Icycles (state, 1, 0); - if (IntPending (state)) { - cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, - instr); - return; - } else - cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr); - } - if (cpab == ARMul_CANT) - ARMul_Abort (state, ARMul_UndefinedInstrV); - else - BUSUSEDN; -} - -/* This function handles Undefined instructions, as CP isntruction. */ - -void -ARMul_UndefInstr (ARMul_State * state, ARMword instr) -{ - std::string disasm = ARM_Disasm::Disassemble(state->pc, instr); - LOG_ERROR(Core_ARM11, "Undefined instruction!! Disasm: %s Opcode: 0x%x", disasm.c_str(), instr); - ARMul_Abort (state, ARMul_UndefinedInstrV); -} - -/* Return TRUE if an interrupt is pending, FALSE otherwise. */ - -unsigned -IntPending (ARMul_State * state) -{ - /* Any exceptions. */ - if (state->NresetSig == LOW) { - ARMul_Abort (state, ARMul_ResetV); - return TRUE; - } else if (!state->NfiqSig && !FFLAG) { - ARMul_Abort (state, ARMul_FIQV); - return TRUE; - } else if (!state->NirqSig && !IFLAG) { - ARMul_Abort (state, ARMul_IRQV); - return TRUE; - } - - return FALSE; -} - -/* Align a word access to a non word boundary. */ - -ARMword -ARMul_Align (ARMul_State* state, ARMword address, ARMword data) -{ - /* This code assumes the address is really unaligned, - as a shift by 32 is undefined in C. */ - - address = (address & 3) << 3; /* Get the word address. */ - return ((data >> address) | (data << (32 - address))); /* rot right */ -} diff --git a/src/core/arm/interpreter/armvirt.cpp b/src/core/arm/interpreter/armvirt.cpp deleted file mode 100644 index 7845d1042..000000000 --- a/src/core/arm/interpreter/armvirt.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* armvirt.c -- ARMulator virtual memory interace: ARM6 Instruction Emulator. - Copyright (C) 1994 Advanced RISC Machines Ltd. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* This file contains a complete ARMulator memory model, modelling a -"virtual memory" system. A much simpler model can be found in armfast.c, -and that model goes faster too, but has a fixed amount of memory. This -model's memory has 64K pages, allocated on demand from a 64K entry page -table. The routines PutWord and GetWord implement this. Pages are never -freed as they might be needed again. A single area of memory may be -defined to generate aborts. */ - -#include "core/arm/skyeye_common/armdefs.h" -#include "core/arm/skyeye_common/armemu.h" - -#include "core/mem_map.h" - -#define dumpstack 1 -#define dumpstacksize 0x10 -#define maxdmupaddr 0x0033a850 - -/*ARMword ARMul_GetCPSR (ARMul_State * state) { -return 0; -} -ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) { -return 0; -} -void ARMul_SetCPSR (ARMul_State * state, ARMword value) { - -} -void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) { - -}*/ - -void ARMul_Icycles(ARMul_State * state, unsigned number, ARMword address) { -} - -void ARMul_Ccycles(ARMul_State * state, unsigned number, ARMword address) { -} - -ARMword ARMul_LoadInstrS(ARMul_State * state, ARMword address, ARMword isize) { - state->NumScycles++; - -#ifdef HOURGLASS - if ((state->NumScycles & HOURGLASS_RATE) == 0) { - HOURGLASS; - } -#endif - if (isize == 2) - return (u16)Memory::Read16(address); - else - return (u32)Memory::Read32(address); -} - -ARMword ARMul_LoadInstrN(ARMul_State * state, ARMword address, ARMword isize) { - state->NumNcycles++; - - if (isize == 2) - return (u16)Memory::Read16(address); - else - return (u32)Memory::Read32(address); -} - -ARMword ARMul_ReLoadInstr(ARMul_State * state, ARMword address, ARMword isize) { - ARMword data; - - if ((isize == 2) && (address & 0x2)) { - ARMword lo; - lo = (u16)Memory::Read16(address); - return lo; - } - - data = (u32)Memory::Read32(address); - return data; -} - -ARMword ARMul_ReadWord(ARMul_State * state, ARMword address) { - ARMword data; - data = Memory::Read32(address); - return data; -} - -ARMword ARMul_LoadWordS(ARMul_State * state, ARMword address) { - state->NumScycles++; - return ARMul_ReadWord(state, address); -} - -ARMword ARMul_LoadWordN(ARMul_State * state, ARMword address) { - state->NumNcycles++; - return ARMul_ReadWord(state, address); -} - -ARMword ARMul_LoadHalfWord(ARMul_State * state, ARMword address) { - state->NumNcycles++; - return (u16)Memory::Read16(address);; -} - -ARMword ARMul_ReadByte(ARMul_State * state, ARMword address) { - return (u8)Memory::Read8(address); -} - -ARMword ARMul_LoadByte(ARMul_State * state, ARMword address) { - state->NumNcycles++; - return ARMul_ReadByte(state, address); -} - -void ARMul_StoreHalfWord(ARMul_State * state, ARMword address, ARMword data) { - state->NumNcycles++; - Memory::Write16(address, data); -} - -void ARMul_StoreByte(ARMul_State * state, ARMword address, ARMword data) { - state->NumNcycles++; - ARMul_WriteByte(state, address, data); -} - -ARMword ARMul_SwapWord(ARMul_State * state, ARMword address, ARMword data) { - ARMword temp; - state->NumNcycles++; - temp = ARMul_ReadWord(state, address); - state->NumNcycles++; - Memory::Write32(address, data); - return temp; -} - -ARMword ARMul_SwapByte(ARMul_State * state, ARMword address, ARMword data) { - ARMword temp; - temp = ARMul_LoadByte(state, address); - Memory::Write8(address, data); - return temp; -} - -void ARMul_WriteWord(ARMul_State * state, ARMword address, ARMword data) { - Memory::Write32(address, data); -} - -void ARMul_WriteByte(ARMul_State * state, ARMword address, ARMword data) -{ - Memory::Write8(address, data); -} - -void ARMul_StoreWordS(ARMul_State * state, ARMword address, ARMword data) -{ - state->NumScycles++; - ARMul_WriteWord(state, address, data); -} - -void ARMul_StoreWordN(ARMul_State * state, ARMword address, ARMword data) -{ - state->NumNcycles++; - ARMul_WriteWord(state, address, data); -} diff --git a/src/core/arm/interpreter/thumbemu.cpp b/src/core/arm/interpreter/thumbemu.cpp deleted file mode 100644 index 9cf80672d..000000000 --- a/src/core/arm/interpreter/thumbemu.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* thumbemu.c -- Thumb instruction emulation. - Copyright (C) 1996, Cygnus Software Technologies Ltd. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* 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/armdefs.h" -#include "core/arm/skyeye_common/armemu.h" -#include "core/arm/skyeye_common/armos.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 -ARMul_ThumbDecode ( - ARMul_State *state, - ARMword pc, - ARMword tinstr, - ARMword *ainstr) -{ - tdstate valid = t_decoded; /* default assumes a valid instruction */ - ARMword next_instr; - - if (state->bigendSig) { - next_instr = tinstr & 0xFFFF; - tinstr >>= 16; - } - else { - next_instr = tinstr >> 16; - tinstr &= 0xFFFF; - } - -#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) { - /* Format 4 */ - enum OpcodeType { t_norm, t_shift, t_neg, t_mul }; - struct ThumbOpcode { - ARMword opcode; - OpcodeType otype; - }; - - ThumbOpcode 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) { - *ainstr = 0xE1200030 /* base */ - |(Rs << 0); /* Rm */ - } 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 (tinstr == (ARMul_ABORTWORD & 0xffff) && - state->AbortAddr == pc) { - *ainstr = ARMul_ABORTWORD; - break; - } - /* 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 */ - 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; - } - valid = t_branch; - } - else /* UNDEFINED : cc=1110(AL) uses different format */ - valid = t_undefined; - break; - case 28: /* B */ - /* Format 18 */ - state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1) - | ((tinstr & (1 << 10)) ? - 0xFFFFF800 : 0))); - FLUSHPIPE; - valid = t_branch; - break; - case 29: - if(tinstr & 0x1) - valid = t_undefined; - else{ - /* BLX 1 for armv5t and above */ - ARMword tmp = (pc + 2); - state->Reg[15] = - (state->Reg[14] + ((tinstr & 0x07FF) << 1)) & 0xFFFFFFFC; - state->Reg[14] = (tmp | 1); - CLEART; - LOG_DEBUG(Core_ARM11, "After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x", state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1); - valid = t_branch; - FLUSHPIPE; - } - 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. */ - state->Reg[14] = state->Reg[15] - + (((tinstr & 0x07FF) << 12) - | ((tinstr & (1 << 10)) ? 0xFF800000 : 0)); - valid = t_branch; /* in-case we don't have the 2nd half */ - //tinstr = next_instr; /* move the instruction down */ - //if (((tinstr & 0xF800) >> 11) != 31) - // break; /* exit, since not correct instruction */ - /* else we fall through to process the second half of the BL */ - //pc += 2; /* point the pc at the 2nd half */ - state->Reg[15] = pc + 2; - FLUSHPIPE; - 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. */ - { - ARMword tmp = (pc + 2); - state->Reg[15] = - (state->Reg[14] + ((tinstr & 0x07FF) << 1)); - state->Reg[14] = (tmp | 1); - valid = t_branch; - FLUSHPIPE; - } - break; - } - - return valid; -} |