forked from ShuriZma/suyu
1
0
Fork 0

arm: Adios armemu

This commit is contained in:
Lioncash 2015-01-31 20:34:26 -05:00
parent 73a7a379d6
commit f44781fd7b
19 changed files with 166 additions and 8603 deletions

View File

@ -57,7 +57,6 @@ void Config::ReadValues() {
Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT); Settings::values.pad_sright_key = glfw_config->GetInteger("Controls", "pad_sright", GLFW_KEY_RIGHT);
// Core // Core
Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter);
Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 30); Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 30);
Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0); Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0);

View File

@ -27,7 +27,6 @@ pad_sleft =
pad_sright = pad_sright =
[Core] [Core]
cpu_core = ## 0: Interpreter (default), 1: OldInterpreter (may work better, soon to be deprecated)
gpu_refresh_rate = ## 30 (default) gpu_refresh_rate = ## 30 (default)
frame_skip = ## 0: No frameskip (default), 1 : 2x frameskip, 2 : 4x frameskip, etc. frame_skip = ## 0: No frameskip (default), 1 : 2x frameskip, 2 : 4x frameskip, etc.

View File

@ -43,7 +43,6 @@ void Config::ReadValues() {
qt_config->endGroup(); qt_config->endGroup();
qt_config->beginGroup("Core"); qt_config->beginGroup("Core");
Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt();
Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 30).toInt(); Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 30).toInt();
Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt(); Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt();
qt_config->endGroup(); qt_config->endGroup();
@ -79,7 +78,6 @@ void Config::SaveValues() {
qt_config->endGroup(); qt_config->endGroup();
qt_config->beginGroup("Core"); qt_config->beginGroup("Core");
qt_config->setValue("cpu_core", Settings::values.cpu_core);
qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate); qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate);
qt_config->setValue("frame_skip", Settings::values.frame_skip); qt_config->setValue("frame_skip", Settings::values.frame_skip);
qt_config->endGroup(); qt_config->endGroup();

View File

@ -6,13 +6,9 @@ set(SRCS
arm/dyncom/arm_dyncom_interpreter.cpp arm/dyncom/arm_dyncom_interpreter.cpp
arm/dyncom/arm_dyncom_run.cpp arm/dyncom/arm_dyncom_run.cpp
arm/dyncom/arm_dyncom_thumb.cpp arm/dyncom/arm_dyncom_thumb.cpp
arm/interpreter/arm_interpreter.cpp
arm/interpreter/armcopro.cpp arm/interpreter/armcopro.cpp
arm/interpreter/armemu.cpp
arm/interpreter/arminit.cpp arm/interpreter/arminit.cpp
arm/interpreter/armsupp.cpp arm/interpreter/armsupp.cpp
arm/interpreter/armvirt.cpp
arm/interpreter/thumbemu.cpp
arm/skyeye_common/vfp/vfp.cpp arm/skyeye_common/vfp/vfp.cpp
arm/skyeye_common/vfp/vfpdouble.cpp arm/skyeye_common/vfp/vfpdouble.cpp
arm/skyeye_common/vfp/vfpinstr.cpp arm/skyeye_common/vfp/vfpinstr.cpp
@ -108,7 +104,6 @@ set(HEADERS
arm/dyncom/arm_dyncom_interpreter.h arm/dyncom/arm_dyncom_interpreter.h
arm/dyncom/arm_dyncom_run.h arm/dyncom/arm_dyncom_run.h
arm/dyncom/arm_dyncom_thumb.h arm/dyncom/arm_dyncom_thumb.h
arm/interpreter/arm_interpreter.h
arm/skyeye_common/arm_regformat.h arm/skyeye_common/arm_regformat.h
arm/skyeye_common/armdefs.h arm/skyeye_common/armdefs.h
arm/skyeye_common/armemu.h arm/skyeye_common/armemu.h

View File

@ -34,10 +34,6 @@ enum {
THUMB = (1 << 7) THUMB = (1 << 7)
}; };
#undef BITS
#undef BIT
#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
#define BIT(s, n) ((s >> (n)) & 1)
#define RM BITS(sht_oper, 0, 3) #define RM BITS(sht_oper, 0, 3)
#define RS BITS(sht_oper, 8, 11) #define RS BITS(sht_oper, 8, 11)

View File

@ -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;
}

View File

@ -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;
};

View File

@ -19,213 +19,45 @@
#include "core/arm/skyeye_common/armemu.h" #include "core/arm/skyeye_common/armemu.h"
#include "core/arm/skyeye_common/vfp/vfp.h" #include "core/arm/skyeye_common/vfp/vfp.h"
//chy 2005-07-08 // Dummy Co-processors.
//#include "ansidecl.h"
//chy -------
//#include "iwmmxt.h"
/* Dummy Co-processors. */ static unsigned int NoCoPro3R(ARMul_State* state, unsigned int a, ARMword b)
static unsigned
NoCoPro3R(ARMul_State * state,
unsigned a, ARMword b)
{ {
return ARMul_CANT; return ARMul_CANT;
} }
static unsigned static unsigned int NoCoPro4R(ARMul_State* state, unsigned int a, ARMword b, ARMword c)
NoCoPro4R(ARMul_State * state,
unsigned a,
ARMword b, ARMword c)
{ {
return ARMul_CANT; return ARMul_CANT;
} }
static unsigned static unsigned int NoCoPro4W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c)
NoCoPro4W(ARMul_State * state,
unsigned a,
ARMword b, ARMword * c)
{ {
return ARMul_CANT; return ARMul_CANT;
} }
static unsigned static unsigned int NoCoPro5R(ARMul_State* state, unsigned int a, ARMword b, ARMword c, ARMword d)
NoCoPro5R(ARMul_State * state,
unsigned a,
ARMword b,
ARMword c, ARMword d)
{ {
return ARMul_CANT; return ARMul_CANT;
} }
static unsigned static unsigned int NoCoPro5W(ARMul_State* state, unsigned int a, ARMword b, ARMword* c, ARMword* d)
NoCoPro5W(ARMul_State * state,
unsigned a,
ARMword b,
ARMword * c, ARMword * d)
{ {
return ARMul_CANT; return ARMul_CANT;
} }
/* The XScale Co-processors. */ // Install co-processor instruction handlers in this routine.
unsigned int ARMul_CoProInit(ARMul_State* state)
/* 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. */ // Initialise tham all first.
//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode for (unsigned int i = 0; i < 16; i++)
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)
{
unsigned int i;
/* Initialise tham all first. */
for (i = 0; i < 16; i++)
ARMul_CoProDetach(state, i); ARMul_CoProDetach(state, i);
/* Install CoPro Instruction handlers here. // Install CoPro Instruction handlers here.
The format is: // The format is:
ARMul_CoProAttach (state, CP Number, Init routine, Exit routine // ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
LDC routine, STC routine, MRC routine, MCR routine, // LDC routine, STC routine, MRC routine, MCR routine,
CDP routine, Read Reg routine, Write Reg routine). */ // CDP routine, Read Reg routine, Write Reg routine).
if (state->is_v6) { if (state->is_v6) {
ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC, ARMul_CoProAttach(state, 10, VFPInit, NULL, VFPLDC, VFPSTC,
VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL);
@ -235,43 +67,30 @@ ARMul_CoProInit(ARMul_State * state)
/*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, /*ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
MMUMRC, MMUMCR, NULL, NULL, 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, // No handlers below here.
IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL,
NULL);
}
#endif
/* No handlers below here. */
/* Call all the initialisation routines. */ // Call all the initialisation routines.
for (i = 0; i < 16; i++) for (unsigned int i = 0; i < 16; i++)
if (state->CPInit[i]) if (state->CPInit[i])
(state->CPInit[i]) (state); (state->CPInit[i]) (state);
return TRUE; return TRUE;
} }
/* Install co-processor finalisation routines in this routine. */ // Install co-processor finalisation routines in this routine.
void ARMul_CoProExit(ARMul_State * state)
void
ARMul_CoProExit(ARMul_State * state)
{ {
register unsigned i; for (unsigned int i = 0; i < 16; i++)
for (i = 0; i < 16; i++)
if (state->CPExit[i]) if (state->CPExit[i])
(state->CPExit[i]) (state); (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); ARMul_CoProDetach(state, i);
} }
/* Routines to hook Co-processors into ARMulator. */ // Routines to hook Co-processors into ARMulator.
void void
ARMul_CoProAttach(ARMul_State* state, ARMul_CoProAttach(ARMul_State* state,
@ -311,8 +130,7 @@ ARMul_CPReads * read, ARMul_CPWrites * write)
state->CPWrite[number] = write; state->CPWrite[number] = write;
} }
void void ARMul_CoProDetach(ARMul_State* state, unsigned number)
ARMul_CoProDetach(ARMul_State * state, unsigned number)
{ {
ARMul_CoProAttach(state, number, NULL, NULL, ARMul_CoProAttach(state, number, NULL, NULL,
NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,

File diff suppressed because it is too large Load Diff

View File

@ -25,24 +25,13 @@
void ARMul_EmulateInit(); void ARMul_EmulateInit();
ARMul_State* ARMul_NewState(ARMul_State* state); ARMul_State* ARMul_NewState(ARMul_State* state);
void ARMul_Reset (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] = { unsigned ARMul_MultTable[32] = {
1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 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 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16
}; };
ARMword ARMul_ImmedTable[4096]; /* immediate DP LHS values */ ARMword ARMul_ImmedTable[4096]; // immediate DP LHS values
char ARMul_BitList[256]; /* number of bits in a byte table */ char ARMul_BitList[256]; // number of bits in a byte table
void arm_dyncom_Abort(ARMul_State * state, ARMword vector)
{
ARMul_Abort(state, vector);
}
/***************************************************************************\ /***************************************************************************\
* Call this routine once to set up the emulator's tables. * * Call this routine once to set up the emulator's tables. *
@ -51,18 +40,21 @@ void ARMul_EmulateInit()
{ {
unsigned int i, j; 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); 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 (j = 1; j < 256; j <<= 1)
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
if ((i & j) > 0) if ((i & j) > 0)
ARMul_BitList[i]++; ARMul_BitList[i]++;
// you always need 4 times these values
for (i = 0; i < 256; i++) 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->NumCcycles = 0;
state->NumFcycles = 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);
}

View File

@ -20,372 +20,7 @@
#include "core/arm/disassembler/arm_disasm.h" #include "core/arm/disassembler/arm_disasm.h"
#include "core/mem_map.h" #include "core/mem_map.h"
// Unsigned sum of absolute difference
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 */
u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
{ {
if (left > right) if (left > right)
@ -394,23 +29,6 @@ u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
return right - left; 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;
}
}
// Add with carry, indicates if a carry-out or signed overflow occurred. // Add with carry, indicates if a carry-out or signed overflow occurred.
u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred)
{ {
@ -441,23 +59,6 @@ bool SubOverflow(ARMword a, ARMword b, ARMword result)
(POS(a) && NEG(b) && NEG(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. // Returns true if the Q flag should be set as a result of overflow.
bool ARMul_AddOverflowQ(ARMword a, ARMword b) bool ARMul_AddOverflowQ(ARMword a, ARMword b)
{ {
@ -468,24 +69,7 @@ bool ARMul_AddOverflowQ(ARMword a, ARMword b)
return false; return false;
} }
/* Assigns the C flag after an subtraction of a and b to give result. */ // 8-bit signed saturated addition
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 */
u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
{ {
u8 result = left + right; u8 result = left + right;
@ -500,7 +84,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
return result; return result;
} }
/* 8-bit signed saturated subtraction */ // 8-bit signed saturated subtraction
u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
{ {
u8 result = left - right; u8 result = left - right;
@ -515,7 +99,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
return result; return result;
} }
/* 16-bit signed saturated addition */ // 16-bit signed saturated addition
u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
{ {
u16 result = left + right; u16 result = left + right;
@ -530,7 +114,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
return result; return result;
} }
/* 16-bit signed saturated subtraction */ // 16-bit signed saturated subtraction
u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
{ {
u16 result = left - right; u16 result = left - right;
@ -545,7 +129,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
return result; return result;
} }
/* 8-bit unsigned saturated addition */ // 8-bit unsigned saturated addition
u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
{ {
u8 result = left + right; u8 result = left + right;
@ -556,7 +140,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
return result; return result;
} }
/* 16-bit unsigned saturated addition */ // 16-bit unsigned saturated addition
u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
{ {
u16 result = left + right; u16 result = left + right;
@ -567,7 +151,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
return result; return result;
} }
/* 8-bit unsigned saturated subtraction */ // 8-bit unsigned saturated subtraction
u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
{ {
if (left <= right) if (left <= right)
@ -576,7 +160,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
return left - right; return left - right;
} }
/* 16-bit unsigned saturated subtraction */ // 16-bit unsigned saturated subtraction
u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
{ {
if (left <= right) if (left <= right)
@ -620,444 +204,3 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
*saturation_occurred = false; *saturation_occurred = false;
return (u32)value; 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 */
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -32,6 +32,9 @@
#include "core/arm/skyeye_common/armmmu.h" #include "core/arm/skyeye_common/armmmu.h"
#include "core/arm/skyeye_common/skyeye_defs.h" #include "core/arm/skyeye_common/skyeye_defs.h"
#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
#define BIT(s, n) ((s >> (n)) & 1)
#ifndef FALSE #ifndef FALSE
#define FALSE 0 #define FALSE 0
#define TRUE 1 #define TRUE 1
@ -287,15 +290,6 @@ enum {
ARM620 = ARM6 ARM620 = ARM6
}; };
/***************************************************************************\
* Macros to extract instruction fields *
\***************************************************************************/
#define BIT(n) ( (ARMword)(instr>>(n))&1) /* bit n of instruction */
#define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) ) /* bits m to n of instr */
#define TOPBITS(n) (instr >> (n)) /* bits 31 to n of instr */
/***************************************************************************\ /***************************************************************************\
* The hardware vector addresses * * The hardware vector addresses *
\***************************************************************************/ \***************************************************************************/
@ -339,13 +333,6 @@ enum {
SYSTEM32MODE = 31 SYSTEM32MODE = 31
}; };
#define ARM32BITMODE (state->Mode > 3)
#define ARM26BITMODE (state->Mode <= 3)
#define ARMMODE (state->Mode)
#define ARMul_MODEBITS 0x1fL
#define ARMul_MODE32BIT ARM32BITMODE
#define ARMul_MODE26BIT ARM26BITMODE
enum { enum {
USERBANK = 0, USERBANK = 0,
FIQBANK = 1, FIQBANK = 1,
@ -357,10 +344,6 @@ enum {
SYSTEMBANK = USERBANK SYSTEMBANK = USERBANK
}; };
#define BANK_CAN_ACCESS_SPSR(bank) \
((bank) != USERBANK && (bank) != SYSTEMBANK && (bank) != DUMMYBANK)
/***************************************************************************\ /***************************************************************************\
* Definitons of things in the emulator * * Definitons of things in the emulator *
\***************************************************************************/ \***************************************************************************/
@ -373,84 +356,6 @@ extern void ARMul_Reset(ARMul_State* state);
} }
#endif #endif
extern ARMul_State* ARMul_NewState(ARMul_State* state); extern ARMul_State* ARMul_NewState(ARMul_State* state);
extern ARMword ARMul_DoProg(ARMul_State* state);
extern ARMword ARMul_DoInstr(ARMul_State* state);
/***************************************************************************\
* Useful support routines *
\***************************************************************************/
extern ARMword ARMul_GetReg (ARMul_State* state, unsigned mode, unsigned reg);
extern void ARMul_SetReg (ARMul_State* state, unsigned mode, unsigned reg, ARMword value);
extern ARMword ARMul_GetPC(ARMul_State* state);
extern ARMword ARMul_GetNextPC(ARMul_State* state);
extern void ARMul_SetPC(ARMul_State* state, ARMword value);
extern ARMword ARMul_GetR15(ARMul_State* state);
extern void ARMul_SetR15(ARMul_State* state, ARMword value);
extern ARMword ARMul_GetCPSR(ARMul_State* state);
extern void ARMul_SetCPSR(ARMul_State* state, ARMword value);
extern ARMword ARMul_GetSPSR(ARMul_State* state, ARMword mode);
extern void ARMul_SetSPSR(ARMul_State* state, ARMword mode, ARMword value);
/***************************************************************************\
* Definitons of things to handle aborts *
\***************************************************************************/
extern void ARMul_Abort(ARMul_State* state, ARMword address);
#ifdef MODET
#define ARMul_ABORTWORD (state->TFlag ? 0xefffdfff : 0xefffffff) /* SWI -1 */
#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
state->AbortAddr = (address & (state->TFlag ? ~1L : ~3L))
#else
#define ARMul_ABORTWORD 0xefffffff /* SWI -1 */
#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
state->AbortAddr = (address & ~3L)
#endif
#define ARMul_DATAABORT(address) state->abortSig = HIGH ; \
state->Aborted = ARMul_DataAbortV ;
#define ARMul_CLEARABORT state->abortSig = LOW
/***************************************************************************\
* Definitons of things in the memory interface *
\***************************************************************************/
extern unsigned ARMul_MemoryInit(ARMul_State* state, unsigned int initmemsize);
extern void ARMul_MemoryExit(ARMul_State* state);
extern ARMword ARMul_LoadInstrS(ARMul_State* state, ARMword address, ARMword isize);
extern ARMword ARMul_LoadInstrN(ARMul_State* state, ARMword address, ARMword isize);
#ifdef __cplusplus
extern "C" {
#endif
extern ARMword ARMul_ReLoadInstr(ARMul_State* state, ARMword address, ARMword isize);
#ifdef __cplusplus
}
#endif
extern ARMword ARMul_LoadWordS(ARMul_State* state, ARMword address);
extern ARMword ARMul_LoadWordN(ARMul_State* state, ARMword address);
extern ARMword ARMul_LoadHalfWord(ARMul_State* state, ARMword address);
extern ARMword ARMul_LoadByte(ARMul_State* state, ARMword address);
extern void ARMul_StoreWordS(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_StoreWordN(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_StoreHalfWord(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_StoreByte(ARMul_State* state, ARMword address, ARMword data);
extern ARMword ARMul_SwapWord(ARMul_State* state, ARMword address, ARMword data);
extern ARMword ARMul_SwapByte(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_Icycles(ARMul_State* state, unsigned number, ARMword address);
extern void ARMul_Ccycles(ARMul_State* state, unsigned number, ARMword address);
extern ARMword ARMul_ReadWord(ARMul_State* state, ARMword address);
extern ARMword ARMul_ReadByte(ARMul_State* state, ARMword address);
extern void ARMul_WriteWord(ARMul_State* state, ARMword address, ARMword data);
extern void ARMul_WriteByte(ARMul_State* state, ARMword address, ARMword data);
extern ARMword ARMul_MemAccess(ARMul_State* state, ARMword, ARMword,
ARMword, ARMword, ARMword, ARMword, ARMword,
ARMword, ARMword, ARMword);
/***************************************************************************\ /***************************************************************************\
* Definitons of things in the co-processor interface * * Definitons of things in the co-processor interface *
@ -495,37 +400,10 @@ enum {
ARMul_CP15_DBCON_E0 = 0x0003 ARMul_CP15_DBCON_E0 = 0x0003
}; };
extern unsigned ARMul_CoProInit(ARMul_State* state);
extern void ARMul_CoProExit(ARMul_State* state);
extern void 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);
extern void ARMul_CoProDetach(ARMul_State* state, unsigned number);
/***************************************************************************\ /***************************************************************************\
* Definitons of things in the host environment * * Definitons of things in the host environment *
\***************************************************************************/ \***************************************************************************/
extern unsigned ARMul_OSInit(ARMul_State* state);
extern void ARMul_OSExit(ARMul_State* state);
#ifdef __cplusplus
extern "C" {
#endif
extern unsigned ARMul_OSHandleSWI(ARMul_State* state, ARMword number);
#ifdef __cplusplus
}
#endif
extern ARMword ARMul_OSLastErrorP(ARMul_State* state);
extern ARMword ARMul_Debug(ARMul_State* state, ARMword pc, ARMword instr);
extern unsigned ARMul_OSException(ARMul_State* state, ARMword vector, ARMword pc);
enum ConditionCode { enum ConditionCode {
EQ = 0, EQ = 0,
NE = 1, NE = 1,
@ -545,40 +423,9 @@ enum ConditionCode {
NV = 15, NV = 15,
}; };
#ifndef NFLAG
#define NFLAG state->NFlag
#endif //NFLAG
#ifndef ZFLAG
#define ZFLAG state->ZFlag
#endif //ZFLAG
#ifndef CFLAG
#define CFLAG state->CFlag
#endif //CFLAG
#ifndef VFLAG
#define VFLAG state->VFlag
#endif //VFLAG
#ifndef IFLAG
#define IFLAG (state->IFFlags >> 1)
#endif //IFLAG
#ifndef FFLAG
#define FFLAG (state->IFFlags & 1)
#endif //FFLAG
#ifndef IFFLAGS
#define IFFLAGS state->IFFlags
#endif //VFLAG
extern bool AddOverflow(ARMword, ARMword, ARMword); extern bool AddOverflow(ARMword, ARMword, ARMword);
extern bool SubOverflow(ARMword, ARMword, ARMword); extern bool SubOverflow(ARMword, ARMword, ARMword);
extern void ARMul_UndefInstr(ARMul_State*, ARMword);
extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword);
extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword);
extern void ARMul_SelectProcessor(ARMul_State*, unsigned); extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
extern u32 AddWithCarry(u32, u32, u32, bool*, bool*); extern u32 AddWithCarry(u32, u32, u32, bool*, bool*);

View File

@ -19,12 +19,6 @@
#include "core/arm/skyeye_common/armdefs.h" #include "core/arm/skyeye_common/armdefs.h"
/* Shift Opcodes. */
#define LSL 0
#define LSR 1
#define ASR 2
#define ROR 3
/* Macros to twiddle the status flags and mode. */ /* Macros to twiddle the status flags and mode. */
#define NBIT ((unsigned)1L << 31) #define NBIT ((unsigned)1L << 31)
#define ZBIT (1L << 30) #define ZBIT (1L << 30)
@ -38,73 +32,6 @@
#define R15FBIT (1L << 26) #define R15FBIT (1L << 26)
#define R15IFBITS (3L << 26) #define R15IFBITS (3L << 26)
#ifdef MODET /* Thumb support. */
/* ??? This bit is actually in the low order bit of the PC in the hardware.
It isn't clear if the simulator needs to model that or not. */
#define TBIT (1L << 5)
#define TFLAG state->TFlag
#define SETT state->TFlag = 1
#define CLEART state->TFlag = 0
#define ASSIGNT(res) state->TFlag = res
#define INSN_SIZE (TFLAG ? 2 : 4)
#else
#define INSN_SIZE 4
#endif
/*add armv6 CPSR feature*/
#define EFLAG state->EFlag
#define SETE state->EFlag = 1
#define CLEARE state->EFlag = 0
#define ASSIGNE(res) state->NFlag = res
#define AFLAG state->AFlag
#define SETA state->AFlag = 1
#define CLEARA state->AFlag = 0
#define ASSIGNA(res) state->NFlag = res
#define QFLAG state->QFlag
#define SETQ state->QFlag = 1
#define CLEARQ state->AFlag = 0
#define ASSIGNQ(res) state->QFlag = res
/* add end */
#define NFLAG state->NFlag
#define SETN state->NFlag = 1
#define CLEARN state->NFlag = 0
#define ASSIGNN(res) state->NFlag = res
#define ZFLAG state->ZFlag
#define SETZ state->ZFlag = 1
#define CLEARZ state->ZFlag = 0
#define ASSIGNZ(res) state->ZFlag = res
#define CFLAG state->CFlag
#define SETC state->CFlag = 1
#define CLEARC state->CFlag = 0
#define ASSIGNC(res) state->CFlag = res
#define VFLAG state->VFlag
#define SETV state->VFlag = 1
#define CLEARV state->VFlag = 0
#define ASSIGNV(res) state->VFlag = res
#define SFLAG state->SFlag
#define SETS state->SFlag = 1
#define CLEARS state->SFlag = 0
#define ASSIGNS(res) state->SFlag = res
#define IFLAG (state->IFFlags >> 1)
#define FFLAG (state->IFFlags & 1)
#define IFFLAGS state->IFFlags
#define ASSIGNINT(res) state->IFFlags = (((res) >> 6) & 3)
#define ASSIGNR15INT(res) state->IFFlags = (((res) >> 26) & 3) ;
#define PSR_FBITS (0xff000000L)
#define PSR_SBITS (0x00ff0000L)
#define PSR_XBITS (0x0000ff00L)
#define PSR_CBITS (0x000000ffL)
#if defined MODE32 || defined MODET #if defined MODE32 || defined MODET
#define CCBITS (0xf8000000L) #define CCBITS (0xf8000000L)
#else #else
@ -128,7 +55,6 @@
#define R15PCBITS (0x03fffffcL) #define R15PCBITS (0x03fffffcL)
#endif #endif
#define R15PCMODEBITS (0x03ffffffL)
#define R15MODEBITS (0x3L) #define R15MODEBITS (0x3L)
#ifdef MODE32 #ifdef MODE32
@ -149,106 +75,7 @@
#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS)) #define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))
#define R15MODE (state->Reg[15] & R15MODEBITS) #define R15MODE (state->Reg[15] & R15MODEBITS)
#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (QFLAG << 27)) // Different ways to start the next instruction.
#define EINT (IFFLAGS << 6)
#define ER15INT (IFFLAGS << 26)
#define EMODE (state->Mode)
#define EGEBITS (state->GEFlag & 0x000F0000)
#ifdef MODET
#define CPSR (ECC | EGEBITS | (EFLAG << 9) | (AFLAG << 8) | EINT | (TFLAG << 5) | EMODE)
#else
#define CPSR (ECC | EINT | EMODE)
#endif
#ifdef MODE32
#define PATCHR15
#else
#define PATCHR15 state->Reg[15] = ECC | ER15INT | EMODE | R15PC
#endif
#define GETSPSR(bank) (ARMul_GetSPSR (state, EMODE))
#define SETPSR_F(d,s) d = ((d) & ~PSR_FBITS) | ((s) & PSR_FBITS)
#define SETPSR_S(d,s) d = ((d) & ~PSR_SBITS) | ((s) & PSR_SBITS)
#define SETPSR_X(d,s) d = ((d) & ~PSR_XBITS) | ((s) & PSR_XBITS)
#define SETPSR_C(d,s) d = ((d) & ~PSR_CBITS) | ((s) & PSR_CBITS)
#define SETR15PSR(s) \
do \
{ \
if (state->Mode == USER26MODE) \
{ \
state->Reg[15] = ((s) & CCBITS) | R15PC | ER15INT | EMODE; \
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 \
{ \
state->Reg[15] = R15PC | ((s) & (CCBITS | R15INTBITS | R15MODEBITS)); \
ARMul_R15Altered (state); \
} \
} \
while (0)
#define SETABORT(i, m, d) \
do \
{ \
int SETABORT_mode = (m); \
\
ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state)); \
ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT)) \
| (i) | SETABORT_mode)); \
state->Reg[14] = temp - (d); \
} \
while (0)
#ifndef MODE32
#define VECTORS 0x20
#define LEGALADDR 0x03ffffff
#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig)
#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig)
#endif
#define INTERNALABORT(address) \
do \
{ \
if (address < VECTORS) \
state->Aborted = ARMul_DataAbortV; \
else \
state->Aborted = ARMul_AddrExceptnV; \
} \
while (0)
#ifdef MODE32
#define TAKEABORT ARMul_Abort (state, ARMul_DataAbortV)
#else
#define TAKEABORT \
do \
{ \
if (state->Aborted == ARMul_AddrExceptnV) \
ARMul_Abort (state, ARMul_AddrExceptnV); \
else \
ARMul_Abort (state, ARMul_DataAbortV); \
} \
while (0)
#endif
#define CPTAKEABORT \
do \
{ \
if (!state->Aborted) \
ARMul_Abort (state, ARMul_UndefinedInstrV); \
else if (state->Aborted == ARMul_AddrExceptnV) \
ARMul_Abort (state, ARMul_AddrExceptnV); \
else \
ARMul_Abort (state, ARMul_DataAbortV); \
} \
while (0);
/* Different ways to start the next instruction. */
#define SEQ 0 #define SEQ 0
#define NONSEQ 1 #define NONSEQ 1
#define PCINCEDSEQ 2 #define PCINCEDSEQ 2
@ -256,349 +83,23 @@
#define PRIMEPIPE 4 #define PRIMEPIPE 4
#define RESUME 8 #define RESUME 8
/************************************/
/* shenoubang 2012-3-11 */
/* for armv7 DBG DMB DSB instr*/
/************************************/
#define MBReqTypes_Writes 0
#define MBReqTypes_All 1
#define NORMALCYCLE state->NextInstr = 0
#define BUSUSEDN state->NextInstr |= 1 /* The next fetch will be an N cycle. */
#define BUSUSEDINCPCS \
do \
{ \
if (! state->is_v4) \
{ \
/* A standard PC inc and an S cycle. */ \
state->Reg[15] += INSN_SIZE; \
state->NextInstr = (state->NextInstr & 0xff) | 2; \
} \
} \
while (0)
#define BUSUSEDINCPCN \
do \
{ \
if (state->is_v4) \
BUSUSEDN; \
else \
{ \
/* A standard PC inc and an N cycle. */ \
state->Reg[15] += INSN_SIZE; \
state->NextInstr |= 3; \
} \
} \
while (0)
#define INCPC \
do \
{ \
/* A standard PC inc. */ \
state->Reg[15] += INSN_SIZE; \
state->NextInstr |= 2; \
} \
while (0)
#define FLUSHPIPE state->NextInstr |= PRIMEPIPE #define FLUSHPIPE state->NextInstr |= PRIMEPIPE
/* Cycle based emulation. */ // Macro to rotate n right by b bits.
#define OUTPUTCP(i,a,b)
#define NCYCLE
#define SCYCLE
#define ICYCLE
#define CCYCLE
#define NEXTCYCLE(c)
/* Macros to extract parts of instructions. */
#define DESTReg (BITS (12, 15))
#define LHSReg (BITS (16, 19))
#define RHSReg (BITS ( 0, 3))
#define DEST (state->Reg[DESTReg])
#ifdef MODE32
#ifdef MODET
#define LHS ((LHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[LHSReg]))
#define RHS ((RHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[RHSReg]))
#else
#define LHS (state->Reg[LHSReg])
#define RHS (state->Reg[RHSReg])
#endif
#else
#define LHS ((LHSReg == 15) ? R15PC : (state->Reg[LHSReg]))
#define RHS ((RHSReg == 15) ? R15PC : (state->Reg[RHSReg]))
#endif
#define MULDESTReg (BITS (16, 19))
#define MULLHSReg (BITS ( 0, 3))
#define MULRHSReg (BITS ( 8, 11))
#define MULACCReg (BITS (12, 15))
#define DPImmRHS (ARMul_ImmedTable[BITS(0, 11)])
#define DPSImmRHS temp = BITS(0,11) ; \
rhs = ARMul_ImmedTable[temp] ; \
if (temp > 255) /* There was a shift. */ \
ASSIGNC (rhs >> 31) ;
#ifdef MODE32
#define DPRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \
: GetDPRegRHS (state, instr))
#define DPSRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \
: GetDPSRegRHS (state, instr))
#else
#define DPRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
: GetDPRegRHS (state, instr))
#define DPSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
: GetDPSRegRHS (state, instr))
#endif
#define LSBase state->Reg[LHSReg]
#define LSImmRHS (BITS(0,11))
#ifdef MODE32
#define LSRegRHS ((BITS (4, 11) == 0) ? state->Reg[RHSReg] \
: GetLSRegRHS (state, instr))
#else
#define LSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \
: GetLSRegRHS (state, instr))
#endif
#define LSMNumRegs ((ARMword) ARMul_BitList[BITS (0, 7)] + \
(ARMword) ARMul_BitList[BITS (8, 15)] )
#define LSMBaseFirst ((LHSReg == 0 && BIT (0)) || \
(BIT (LHSReg) && BITS (0, LHSReg - 1) == 0))
#define SWAPSRC (state->Reg[RHSReg])
#define LSCOff (BITS (0, 7) << 2)
#define CPNum BITS (8, 11)
/* Determine if access to coprocessor CP is permitted.
The XScale has a register in CP15 which controls access to CP0 - CP13. */
//chy 2003-09-03, new CP_ACCESS_ALLOWED
/*
#define CP_ACCESS_ALLOWED(STATE, CP) \
( ((CP) >= 14) \
|| (! (STATE)->is_XScale) \
|| (read_cp15_reg (15, 0, 1) & (1 << (CP))))
*/
#define CP_ACCESS_ALLOWED(STATE, CP) \
( ((CP) >= 14) ) \
/* Macro to rotate n right by b bits. */
#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) #define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))
/* Macros to store results of instructions. */ // Values for Emulate.
#define WRITEDEST(d) \ #define STOP 0 // stop
do \ #define CHANGEMODE 1 // change mode
{ \ #define ONCE 2 // execute just one interation
if (DESTReg == 15) \ #define RUN 3 // continuous execution
WriteR15 (state, d); \
else \
DEST = d; \
} \
while (0)
#define WRITESDEST(d) \ // Stuff that is shared across modes.
do \ extern unsigned ARMul_MultTable[]; // Number of I cycles for a mult.
{ \ extern ARMword ARMul_ImmedTable[]; // Immediate DP LHS values.
if (DESTReg == 15) \ extern char ARMul_BitList[]; // Number of bits in a byte table.
WriteSR15 (state, d); \
else \
{ \
DEST = d; \
ARMul_NegZero (state, d); \
} \
} \
while (0)
#define WRITEDESTB(d) \ // Coprocessor support functions.
do \
{ \
if (DESTReg == 15){ \
WriteR15Branch (state, d); \
} \
else{ \
DEST = d; \
} \
} \
while (0)
#define BYTETOBUS(data) ((data & 0xff) | \
((data & 0xff) << 8) | \
((data & 0xff) << 16) | \
((data & 0xff) << 24))
#define BUSTOBYTE(address, data) \
do \
{ \
if (state->bigendSig) \
temp = (data >> (((address ^ 3) & 3) << 3)) & 0xff; \
else \
temp = (data >> ((address & 3) << 3)) & 0xff; \
} \
while (0)
#define LOADMULT(instr, address, wb) LoadMult (state, instr, address, wb)
#define LOADSMULT(instr, address, wb) LoadSMult (state, instr, address, wb)
#define STOREMULT(instr, address, wb) StoreMult (state, instr, address, wb)
#define STORESMULT(instr, address, wb) StoreSMult (state, instr, address, wb)
#define POSBRANCH ((instr & 0x7fffff) << 2)
#define NEGBRANCH ((0xff000000 |(instr & 0xffffff)) << 2)
/* Values for Emulate. */
#define STOP 0 /* stop */
#define CHANGEMODE 1 /* change mode */
#define ONCE 2 /* execute just one interation */
#define RUN 3 /* continuous execution */
/* Stuff that is shared across modes. */
extern unsigned ARMul_MultTable[]; /* Number of I cycles for a mult. */
extern ARMword ARMul_ImmedTable[]; /* Immediate DP LHS values. */
extern char ARMul_BitList[]; /* Number of bits in a byte table. */
#define EVENTLISTSIZE 1024L
/* Thumb support. */
typedef enum
{
t_undefined, /* Undefined Thumb instruction. */
t_decoded, /* Instruction decoded to ARM equivalent. */
t_branch /* Thumb branch (already processed). */
}
tdstate;
/*********************************************************************************
* Check all the possible undef or unpredict behavior, Some of them probably is
* out-of-updated with the newer ISA.
* -- Michael.Kang
********************************************************************************/
#define UNDEF_WARNING LOG_WARNING(Core_ARM11, "undefined or unpredicted behavior for arm instruction.");
/* Macros to scrutinize instructions. */
#define UNDEF_Test UNDEF_WARNING
//#define UNDEF_Test
//#define UNDEF_Shift UNDEF_WARNING
#define UNDEF_Shift
//#define UNDEF_MSRPC UNDEF_WARNING
#define UNDEF_MSRPC
//#define UNDEF_MRSPC UNDEF_WARNING
#define UNDEF_MRSPC
#define UNDEF_MULPCDest UNDEF_WARNING
//#define UNDEF_MULPCDest
#define UNDEF_MULDestEQOp1 UNDEF_WARNING
//#define UNDEF_MULDestEQOp1
//#define UNDEF_LSRBPC UNDEF_WARNING
#define UNDEF_LSRBPC
//#define UNDEF_LSRBaseEQOffWb UNDEF_WARNING
#define UNDEF_LSRBaseEQOffWb
//#define UNDEF_LSRBaseEQDestWb UNDEF_WARNING
#define UNDEF_LSRBaseEQDestWb
//#define UNDEF_LSRPCBaseWb UNDEF_WARNING
#define UNDEF_LSRPCBaseWb
//#define UNDEF_LSRPCOffWb UNDEF_WARNING
#define UNDEF_LSRPCOffWb
//#define UNDEF_LSMNoRegs UNDEF_WARNING
#define UNDEF_LSMNoRegs
//#define UNDEF_LSMPCBase UNDEF_WARNING
#define UNDEF_LSMPCBase
//#define UNDEF_LSMUserBankWb UNDEF_WARNING
#define UNDEF_LSMUserBankWb
//#define UNDEF_LSMBaseInListWb UNDEF_WARNING
#define UNDEF_LSMBaseInListWb
#define UNDEF_SWPPC UNDEF_WARNING
//#define UNDEF_SWPPC
#define UNDEF_CoProHS UNDEF_WARNING
//#define UNDEF_CoProHS
#define UNDEF_MCRPC UNDEF_WARNING
//#define UNDEF_MCRPC
//#define UNDEF_LSCPCBaseWb UNDEF_WARNING
#define UNDEF_LSCPCBaseWb
#define UNDEF_UndefNotBounced UNDEF_WARNING
//#define UNDEF_UndefNotBounced
#define UNDEF_ShortInt UNDEF_WARNING
//#define UNDEF_ShortInt
#define UNDEF_IllegalMode UNDEF_WARNING
//#define UNDEF_IllegalMode
#define UNDEF_Prog32SigChange UNDEF_WARNING
//#define UNDEF_Prog32SigChange
#define UNDEF_Data32SigChange UNDEF_WARNING
//#define UNDEF_Data32SigChange
/* Prototypes for exported functions. */
extern unsigned ARMul_NthReg (ARMword, unsigned);
/* Prototypes for exported functions. */
#ifdef __cplusplus
extern "C" {
#endif
extern ARMword ARMul_Emulate26 (ARMul_State *);
extern ARMword ARMul_Emulate32 (ARMul_State *);
#ifdef __cplusplus
}
#endif
extern unsigned IntPending (ARMul_State *);
extern void ARMul_CPSRAltered (ARMul_State *);
extern void ARMul_R15Altered (ARMul_State *);
extern ARMword ARMul_GetPC (ARMul_State *);
extern ARMword ARMul_GetNextPC (ARMul_State *);
extern ARMword ARMul_GetR15 (ARMul_State *);
extern ARMword ARMul_GetCPSR (ARMul_State *);
extern void ARMul_NegZero (ARMul_State *, ARMword);
extern void ARMul_SetPC (ARMul_State *, ARMword);
extern void ARMul_SetR15 (ARMul_State *, ARMword);
extern void ARMul_SetCPSR (ARMul_State *, ARMword);
extern ARMword ARMul_GetSPSR (ARMul_State *, ARMword);
extern void ARMul_Abort26 (ARMul_State *, ARMword);
extern void ARMul_Abort32 (ARMul_State *, ARMword);
extern ARMword ARMul_MRC (ARMul_State *, ARMword);
extern void ARMul_MRRC (ARMul_State *, ARMword, ARMword *, ARMword *);
extern void ARMul_CDP (ARMul_State *, ARMword);
extern void ARMul_LDC (ARMul_State *, ARMword, ARMword);
extern void ARMul_STC (ARMul_State *, ARMword, ARMword);
extern void ARMul_MCR (ARMul_State *, ARMword, ARMword);
extern void ARMul_MCRR (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_SetSPSR (ARMul_State *, ARMword, ARMword);
extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
extern ARMword ARMul_Align (ARMul_State *, ARMword, ARMword);
extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);
extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword);
extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword);
extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *);
extern ARMword ARMul_GetReg (ARMul_State *, unsigned, unsigned);
extern void ARMul_SetReg (ARMul_State *, unsigned, unsigned, ARMword);
/* Coprocessor support functions. */
extern unsigned ARMul_CoProInit (ARMul_State *); extern unsigned ARMul_CoProInit (ARMul_State *);
extern void ARMul_CoProExit (ARMul_State *); extern void ARMul_CoProExit (ARMul_State *);
extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *, extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *,
@ -606,18 +107,3 @@ extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *,
ARMul_MRCs *, ARMul_MCRs *, ARMul_MRRCs *, ARMul_MCRRs *, ARMul_MRCs *, ARMul_MCRs *, ARMul_MRRCs *, ARMul_MCRRs *,
ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *); ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *);
extern void ARMul_CoProDetach (ARMul_State *, unsigned); extern void ARMul_CoProDetach (ARMul_State *, unsigned);
extern ARMword read_cp15_reg (unsigned, unsigned, unsigned);
extern unsigned DSPLDC4 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPMCR4 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPMRC4 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPSTC4 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPCDP4 (ARMul_State *, unsigned, ARMword);
extern unsigned DSPMCR5 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPMRC5 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPLDC5 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPSTC5 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPCDP5 (ARMul_State *, unsigned, ARMword);
extern unsigned DSPMCR6 (ARMul_State *, unsigned, ARMword, ARMword);
extern unsigned DSPMRC6 (ARMul_State *, unsigned, ARMword, ARMword *);
extern unsigned DSPCDP6 (ARMul_State *, unsigned, ARMword);

View File

@ -43,12 +43,12 @@ unsigned VFPInit(ARMul_State* state)
unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value) unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
{ {
/* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
int CoProc = BITS (8, 11); /* 10 or 11 */ int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
int OPC_1 = BITS (21, 23); int OPC_1 = BITS(instr, 21, 23);
int Rt = BITS (12, 15); int Rt = BITS(instr, 12, 15);
int CRn = BITS (16, 19); int CRn = BITS(instr, 16, 19);
int CRm = BITS (0, 3); int CRm = BITS(instr, 0, 3);
int OPC_2 = BITS (5, 7); int OPC_2 = BITS(instr, 5, 7);
/* TODO check access permission */ /* TODO check access permission */
@ -60,7 +60,7 @@ unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
{ {
/* VMOV r to s */ /* VMOV r to s */
/* Transfering Rt is not mandatory, as the value of interest is pointed by value */ /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, value); VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, value);
return ARMul_DONE; return ARMul_DONE;
} }
@ -79,12 +79,12 @@ unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value) unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
{ {
/* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
int CoProc = BITS (8, 11); /* 10 or 11 */ int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
int OPC_1 = BITS (21, 23); int OPC_1 = BITS(instr, 21, 23);
int Rt = BITS (12, 15); int Rt = BITS(instr, 12, 15);
int CRn = BITS (16, 19); int CRn = BITS(instr, 16, 19);
int CRm = BITS (0, 3); int CRm = BITS(instr, 0, 3);
int OPC_2 = BITS (5, 7); int OPC_2 = BITS(instr, 5, 7);
/* TODO check access permission */ /* TODO check access permission */
@ -95,7 +95,7 @@ unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
{ {
/* VMOV s to r */ /* VMOV s to r */
/* Transfering Rt is not mandatory, as the value of interest is pointed by value */ /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, &value); VMOVBRS(state, BIT(instr, 20), Rt, BIT(instr, 7)|CRn<<1, &value);
return ARMul_DONE; return ARMul_DONE;
} }
@ -126,24 +126,24 @@ unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2) unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2)
{ {
/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
int CoProc = BITS (8, 11); /* 10 or 11 */ int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
int OPC_1 = BITS (4, 7); int OPC_1 = BITS(instr, 4, 7);
int Rt = BITS (12, 15); int Rt = BITS(instr, 12, 15);
int Rt2 = BITS (16, 19); int Rt2 = BITS(instr, 16, 19);
int CRm = BITS (0, 3); int CRm = BITS(instr, 0, 3);
if (CoProc == 10 || CoProc == 11) if (CoProc == 10 || CoProc == 11)
{ {
if (CoProc == 10 && (OPC_1 & 0xD) == 1) if (CoProc == 10 && (OPC_1 & 0xD) == 1)
{ {
VMOVBRRSS(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, value1, value2); VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
return ARMul_DONE; return ARMul_DONE;
} }
if (CoProc == 11 && (OPC_1 & 0xD) == 1) if (CoProc == 11 && (OPC_1 & 0xD) == 1)
{ {
/* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */ /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, value1, value2); VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, value1, value2);
return ARMul_DONE; return ARMul_DONE;
} }
} }
@ -156,11 +156,11 @@ unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32*
unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2) unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2)
{ {
/* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
int CoProc = BITS (8, 11); /* 10 or 11 */ int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
int OPC_1 = BITS (4, 7); int OPC_1 = BITS(instr, 4, 7);
int Rt = BITS (12, 15); int Rt = BITS(instr, 12, 15);
int Rt2 = BITS (16, 19); int Rt2 = BITS(instr, 16, 19);
int CRm = BITS (0, 3); int CRm = BITS(instr, 0, 3);
/* TODO check access permission */ /* TODO check access permission */
@ -170,14 +170,14 @@ unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 v
{ {
if (CoProc == 10 && (OPC_1 & 0xD) == 1) if (CoProc == 10 && (OPC_1 & 0xD) == 1)
{ {
VMOVBRRSS(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, &value1, &value2); VMOVBRRSS(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
return ARMul_DONE; return ARMul_DONE;
} }
if (CoProc == 11 && (OPC_1 & 0xD) == 1) if (CoProc == 11 && (OPC_1 & 0xD) == 1)
{ {
/* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */ /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, &value1, &value2); VMOVBRRD(state, BIT(instr, 20), Rt, Rt2, BIT(instr, 5)<<4|CRm, &value1, &value2);
return ARMul_DONE; return ARMul_DONE;
} }
} }
@ -190,14 +190,14 @@ unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 v
unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value) unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
{ {
/* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */ /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
int CoProc = BITS (8, 11); /* 10 or 11 */ int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
int CRd = BITS (12, 15); int CRd = BITS(instr, 12, 15);
int Rn = BITS (16, 19); int Rn = BITS(instr, 16, 19);
int imm8 = BITS (0, 7); int imm8 = BITS(instr, 0, 7);
int P = BIT(24); int P = BIT(instr, 24);
int U = BIT(23); int U = BIT(instr, 23);
int D = BIT(22); int D = BIT(instr, 22);
int W = BIT(21); int W = BIT(instr, 21);
/* TODO check access permission */ /* TODO check access permission */
@ -239,14 +239,14 @@ unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value) unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
{ {
/* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
int CoProc = BITS (8, 11); /* 10 or 11 */ int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
int CRd = BITS (12, 15); int CRd = BITS(instr, 12, 15);
int Rn = BITS (16, 19); int Rn = BITS(instr, 16, 19);
int imm8 = BITS (0, 7); int imm8 = BITS(instr, 0, 7);
int P = BIT(24); int P = BIT(instr, 24);
int U = BIT(23); int U = BIT(instr, 23);
int D = BIT(22); int D = BIT(instr, 22);
int W = BIT(21); int W = BIT(instr, 21);
/* TODO check access permission */ /* TODO check access permission */
@ -277,57 +277,12 @@ unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr) unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
{ {
/* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */ /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
int CoProc = BITS (8, 11); /* 10 or 11 */ int CoProc = BITS(instr, 8, 11); /* 10 or 11 */
int OPC_1 = BITS (20, 23); int OPC_1 = BITS(instr, 20, 23);
int CRd = BITS (12, 15); int CRd = BITS(instr, 12, 15);
int CRn = BITS (16, 19); int CRn = BITS(instr, 16, 19);
int CRm = BITS (0, 3); int CRm = BITS(instr, 0, 3);
int OPC_2 = BITS (5, 7); int OPC_2 = BITS(instr, 5, 7);
//ichfly
/*if ((instr & 0x0FBF0FD0) == 0x0EB70AC0) //vcvt.f64.f32 d8, s16 (s is bit 0-3 and LSB bit 22) (d is bit 12 - 15 MSB is Bit 6)
{
struct vfp_double vdd;
struct vfp_single vsd;
int dn = BITS(12, 15) + (BIT(22) << 4);
int sd = (BITS(0, 3) << 1) + BIT(5);
s32 n = vfp_get_float(state, sd);
vfp_single_unpack(&vsd, n);
if (vsd.exponent & 0x80)
{
vdd.exponent = (vsd.exponent&~0x80) | 0x400;
}
else
{
vdd.exponent = vsd.exponent | 0x380;
}
vdd.sign = vsd.sign;
vdd.significand = (u64)(vsd.significand & ~0xC0000000) << 32; // I have no idea why but the 2 uppern bits are not from the significand
vfp_put_double(state, vfp_double_pack(&vdd), dn);
return ARMul_DONE;
}
if ((instr & 0x0FBF0FD0) == 0x0EB70BC0) //vcvt.f32.f64 s15, d6
{
struct vfp_double vdd;
struct vfp_single vsd;
int sd = BITS(0, 3) + (BIT(5) << 4);
int dn = (BITS(12, 15) << 1) + BIT(22);
vfp_double_unpack(&vdd, vfp_get_double(state, sd));
if (vdd.exponent & 0x400) //todo if the exponent is to low or to high for this convert
{
vsd.exponent = (vdd.exponent) | 0x80;
}
else
{
vsd.exponent = vdd.exponent & ~0x80;
}
vsd.exponent &= 0xFF;
// vsd.exponent = vdd.exponent >> 3;
vsd.sign = vdd.sign;
vsd.significand = ((u64)(vdd.significand ) >> 32)& ~0xC0000000;
vfp_put_float(state, vfp_single_pack(&vsd), dn);
return ARMul_DONE;
}*/
/* TODO check access permission */ /* TODO check access permission */
@ -335,17 +290,17 @@ unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
if (CoProc == 10 || CoProc == 11) if (CoProc == 10 || CoProc == 11)
{ {
if ((OPC_1 & 0xB) == 0xB && BITS(4, 7) == 0) if ((OPC_1 & 0xB) == 0xB && BITS(instr, 4, 7) == 0)
{ {
unsigned int single = BIT(8) == 0; unsigned int single = BIT(instr, 8) == 0;
unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4); unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
unsigned int imm; unsigned int imm;
instr = BITS(16, 19) << 4 | BITS(0, 3); /* FIXME dirty workaround to get a correct imm */ instr = BITS(instr, 16, 19) << 4 | BITS(instr, 0, 3); // FIXME dirty workaround to get a correct imm
if (single) if (single)
imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0x1f : 0)<<25 | BITS(0, 5)<<19; imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0x1f : 0)<<25 | BITS(instr, 0, 5)<<19;
else else
imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0xff : 0)<<22 | BITS(0, 5)<<16; imm = BIT(instr, 7)<<31 | (BIT(instr, 6)==0)<<30 | (BIT(instr, 6) ? 0xff : 0)<<22 | BITS(instr, 0, 5)<<16;
VMOVI(state, single, d, imm); VMOVI(state, single, d, imm);
return ARMul_DONE; return ARMul_DONE;
@ -353,9 +308,9 @@ unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2) if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2)
{ {
unsigned int single = BIT(8) == 0; unsigned int single = BIT(instr, 8) == 0;
unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4); unsigned int d = (single ? BITS(instr, 12,15)<<1 | BIT(instr, 22) : BITS(instr, 12,15) | BIT(instr, 22)<<4);
unsigned int m = (single ? BITS( 0, 3)<<1 | BIT( 5) : BITS( 0, 3) | BIT( 5)<<4);; unsigned int m = (single ? BITS(instr, 0, 3)<<1 | BIT(instr, 5) : BITS(instr, 0, 3) | BIT(instr, 5)<<4);
VMOVR(state, single, d, m); VMOVR(state, single, d, m);
return ARMul_DONE; return ARMul_DONE;
} }
@ -477,11 +432,11 @@ int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
static int single_reg, add, d, n, imm32, regs; static int single_reg, add, d, n, imm32, regs;
if (type == ARMul_FIRST) if (type == ARMul_FIRST)
{ {
single_reg = BIT(8) == 0; /* Double precision */ single_reg = BIT(instr, 8) == 0; // Double precision
add = BIT(23); /* */ add = BIT(instr, 23);
imm32 = BITS(0,7)<<2; /* may not be used */ imm32 = BITS(instr, 0,7)<<2; // may not be used
d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); /* Base register */
n = BITS(16, 19); /* destination register */ n = BITS(instr, 16, 19); // destination register
i = 0; i = 0;
regs = 1; regs = 1;
@ -519,10 +474,10 @@ int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value)
static int single_regs, add, wback, d, n, imm32, regs; static int single_regs, add, wback, d, n, imm32, regs;
if (type == ARMul_FIRST) if (type == ARMul_FIRST)
{ {
single_regs = BIT(8) == 0; /* Single precision */ single_regs = BIT(instr, 8) == 0; // Single precision
d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
imm32 = BITS(0,7)<<2; /* may not be used */ imm32 = BITS(instr, 0,7)<<2; // may not be used
regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FSTMX if regs is odd */ regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FSTMX if regs is odd
state->Reg[R13] = state->Reg[R13] - imm32; state->Reg[R13] = state->Reg[R13] - imm32;
@ -561,13 +516,13 @@ int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
static int single_regs, add, wback, d, n, imm32, regs; static int single_regs, add, wback, d, n, imm32, regs;
if (type == ARMul_FIRST) if (type == ARMul_FIRST)
{ {
single_regs = BIT(8) == 0; /* Single precision */ single_regs = BIT(instr, 8) == 0; // Single precision
add = BIT(23); /* */ add = BIT(instr, 23);
wback = BIT(21); /* write-back */ wback = BIT(instr, 21); // write-back
d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
n = BITS(16, 19); /* destination register */ n = BITS(instr, 16, 19); // destination register
imm32 = BITS(0,7) * 4; /* may not be used */ imm32 = BITS(instr, 0,7) * 4; // may not be used
regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FSTMX if regs is odd */ regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FSTMX if regs is odd
if (wback) { if (wback) {
state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32); state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
@ -610,10 +565,10 @@ int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value)
static int single_regs, add, wback, d, n, imm32, regs; static int single_regs, add, wback, d, n, imm32, regs;
if (type == ARMul_FIRST) if (type == ARMul_FIRST)
{ {
single_regs = BIT(8) == 0; /* Single precision */ single_regs = BIT(instr, 8) == 0; // Single precision
d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
imm32 = BITS(0,7)<<2; /* may not be used */ imm32 = BITS(instr, 0, 7)<<2; // may not be used
regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FLDMX if regs is odd */ regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 1, 7); // FLDMX if regs is odd
state->Reg[R13] = state->Reg[R13] + imm32; state->Reg[R13] = state->Reg[R13] + imm32;
@ -656,11 +611,11 @@ int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value)
static int single_reg, add, d, n, imm32, regs; static int single_reg, add, d, n, imm32, regs;
if (type == ARMul_FIRST) if (type == ARMul_FIRST)
{ {
single_reg = BIT(8) == 0; /* Double precision */ single_reg = BIT(instr, 8) == 0; // Double precision
add = BIT(23); /* */ add = BIT(instr, 23);
imm32 = BITS(0,7)<<2; /* may not be used */ imm32 = BITS(instr, 0, 7)<<2; // may not be used
d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ d = single_reg ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
n = BITS(16, 19); /* destination register */ n = BITS(instr, 16, 19); // destination register
i = 0; i = 0;
regs = 1; regs = 1;
@ -702,13 +657,13 @@ int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value)
static int single_regs, add, wback, d, n, imm32, regs; static int single_regs, add, wback, d, n, imm32, regs;
if (type == ARMul_FIRST) if (type == ARMul_FIRST)
{ {
single_regs = BIT(8) == 0; /* Single precision */ single_regs = BIT(instr, 8) == 0; // Single precision
add = BIT(23); /* */ add = BIT(instr, 23);
wback = BIT(21); /* write-back */ wback = BIT(instr, 21); // write-back
d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */ d = single_regs ? BITS(instr, 12, 15)<<1|BIT(instr, 22) : BIT(instr, 22)<<4|BITS(instr, 12, 15); // Base register
n = BITS(16, 19); /* destination register */ n = BITS(instr, 16, 19); // destination register
imm32 = BITS(0,7) * 4; /* may not be used */ imm32 = BITS(instr, 0, 7) * 4; // may not be used
regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FLDMX if regs is odd */ regs = single_regs ? BITS(instr, 0, 7) : BITS(instr, 0, 7)>>1; // FLDMX if regs is odd
if (wback) { if (wback) {
state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32); state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
@ -787,8 +742,7 @@ void vfp_put_float(arm_core_t* state, int32_t val, unsigned int reg)
uint64_t vfp_get_double(arm_core_t* state, unsigned int reg) uint64_t vfp_get_double(arm_core_t* state, unsigned int reg)
{ {
uint64_t result; uint64_t result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
result = ((uint64_t) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]\n", reg * 2 + 1, reg * 2, result); LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]\n", reg * 2 + 1, reg * 2, result);
return result; return result;
} }

View File

@ -10,7 +10,6 @@
#include "core/settings.h" #include "core/settings.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/arm/disassembler/arm_disasm.h" #include "core/arm/disassembler/arm_disasm.h"
#include "core/arm/interpreter/arm_interpreter.h"
#include "core/arm/dyncom/arm_dyncom.h" #include "core/arm/dyncom/arm_dyncom.h"
#include "core/hle/hle.h" #include "core/hle/hle.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
@ -59,17 +58,8 @@ void Stop() {
int Init() { int Init() {
LOG_DEBUG(Core, "initialized OK"); LOG_DEBUG(Core, "initialized OK");
g_sys_core = new ARM_Interpreter(); g_sys_core = new ARM_DynCom();
switch (Settings::values.cpu_core) {
case CPU_Interpreter:
g_app_core = new ARM_DynCom(); g_app_core = new ARM_DynCom();
break;
case CPU_OldInterpreter:
default:
g_app_core = new ARM_Interpreter();
break;
}
return 0; return 0;
} }

View File

@ -12,11 +12,6 @@ class ARM_Interface;
namespace Core { namespace Core {
enum CPUCore {
CPU_Interpreter,
CPU_OldInterpreter,
};
struct ThreadContext { struct ThreadContext {
u32 cpu_registers[13]; u32 cpu_registers[13];
u32 sp; u32 sp;

View File

@ -29,7 +29,6 @@ struct Values {
int pad_sright_key; int pad_sright_key;
// Core // Core
int cpu_core;
int gpu_refresh_rate; int gpu_refresh_rate;
int frame_skip; int frame_skip;