aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp4
-rw-r--r--src/core/arm/interpreter/arminit.cpp31
-rw-r--r--src/core/arm/skyeye_common/armdefs.h48
-rw-r--r--src/core/arm/skyeye_common/armemu.h28
-rw-r--r--src/core/hle/service/gsp_gpu.cpp97
5 files changed, 134 insertions, 74 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 68fddc94..1977112d 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -23,7 +23,7 @@ ARM_DynCom::ARM_DynCom() {
ARMul_NewState((ARMul_State*)state.get());
- state->abort_model = 0;
+ state->abort_model = ABORT_BASE_RESTORED;
state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
state->bigendSig = LOW;
@@ -34,7 +34,7 @@ ARM_DynCom::ARM_DynCom() {
ARMul_CoProInit(state.get());
ARMul_Reset(state.get());
state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
- state->Emulate = 3;
+ state->Emulate = RUN;
state->Reg[15] = 0x00000000;
state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index 7b502e24..e7545728 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -74,7 +74,7 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
for (unsigned int i = 0; i < 7; i++)
state->Spsr[i] = 0;
- state->Mode = 0;
+ state->Mode = USER32MODE;
state->VectorCatch = 0;
state->Aborted = false;
@@ -82,14 +82,6 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
state->Inted = 3;
state->LastInted = 3;
-#ifdef ARM61
- state->prog32Sig = LOW;
- state->data32Sig = LOW;
-#else
- state->prog32Sig = HIGH;
- state->data32Sig = HIGH;
-#endif
-
state->lateabtSig = HIGH;
state->bigendSig = LOW;
@@ -102,14 +94,6 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
{
- if (properties & ARM_Fix26_Prop) {
- state->prog32Sig = LOW;
- state->data32Sig = LOW;
- } else {
- state->prog32Sig = HIGH;
- state->data32Sig = HIGH;
- }
-
state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
state->is_v5 = (properties & ARM_v5_Prop) != 0;
state->is_v5e = (properties & ARM_v5e_Prop) != 0;
@@ -132,15 +116,10 @@ void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
void ARMul_Reset(ARMul_State* state)
{
state->NextInstr = 0;
- if (state->prog32Sig) {
- state->Reg[15] = 0;
- state->Cpsr = INTBITS | SVC32MODE;
- state->Mode = SVC32MODE;
- } else {
- state->Reg[15] = R15INTBITS | SVC26MODE;
- state->Cpsr = INTBITS | SVC26MODE;
- state->Mode = SVC26MODE;
- }
+
+ state->Reg[15] = 0;
+ state->Cpsr = INTBITS | SVC32MODE;
+ state->Mode = SVC32MODE;
state->Bank = SVCBANK;
FLUSHPIPE;
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index ff9296e0..012c43c6 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -35,15 +35,27 @@
#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 LOW 0
-#define HIGH 1
-#define LOWHIGH 1
-#define HIGHLOW 2
+// Signal levels
+enum {
+ LOW = 0,
+ HIGH = 1,
+ LOWHIGH = 1,
+ HIGHLOW = 2
+};
+
+// Cache types
+enum {
+ NONCACHE = 0,
+ DATACACHE = 1,
+ INSTCACHE = 2,
+};
-//the define of cachetype
-#define NONCACHE 0
-#define DATACACHE 1
-#define INSTCACHE 2
+// Abort models
+enum {
+ ABORT_BASE_RESTORED = 0,
+ ABORT_EARLY = 1,
+ ABORT_BASE_UPDATED = 2
+};
#define POS(i) ( (~(i)) >> 31 )
#define NEG(i) ( (i) >> 31 )
@@ -137,8 +149,6 @@ struct ARMul_State
unsigned abortSig;
unsigned NtransSig;
unsigned bigendSig;
- unsigned prog32Sig;
- unsigned data32Sig;
unsigned syscallSig;
/* 2004-05-09 chy
@@ -215,7 +225,6 @@ typedef ARMul_State arm_core_t;
\***************************************************************************/
enum {
- ARM_Fix26_Prop = 0x01,
ARM_Nexec_Prop = 0x02,
ARM_Debug_Prop = 0x10,
ARM_Isync_Prop = ARM_Debug_Prop,
@@ -230,19 +239,6 @@ enum {
ARM_iWMMXt_Prop = 0x800,
ARM_PXA27X_Prop = 0x1000,
ARM_v7_Prop = 0x2000,
-
- // ARM2 family
- ARM2 = ARM_Fix26_Prop,
- ARM2as = ARM2,
- ARM61 = ARM2,
- ARM3 = ARM2,
-
- // ARM6 family
- ARM6 = ARM_Lock_Prop,
- ARM60 = ARM6,
- ARM600 = ARM6,
- ARM610 = ARM6,
- ARM620 = ARM6
};
/***************************************************************************\
@@ -275,10 +271,6 @@ enum {
\***************************************************************************/
enum {
- USER26MODE = 0,
- FIQ26MODE = 1,
- IRQ26MODE = 2,
- SVC26MODE = 3,
USER32MODE = 16,
FIQ32MODE = 17,
IRQ32MODE = 18,
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index beee54c9..5d4c0683 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -76,24 +76,28 @@
#define R15MODE (state->Reg[15] & R15MODEBITS)
// Different ways to start the next instruction.
-#define SEQ 0
-#define NONSEQ 1
-#define PCINCEDSEQ 2
-#define PCINCEDNONSEQ 3
-#define PRIMEPIPE 4
-#define RESUME 8
+enum {
+ SEQ = 0,
+ NONSEQ = 1,
+ PCINCEDSEQ = 2,
+ PCINCEDNONSEQ = 3,
+ PRIMEPIPE = 4,
+ RESUME = 8
+};
+
+// Values for Emulate.
+enum {
+ STOP = 0, // Stop
+ CHANGEMODE = 1, // Change mode
+ ONCE = 2, // Execute just one interation
+ RUN = 3 // Continuous execution
+};
#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
// Macro to rotate n right by b bits.
#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))
-// 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.
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 4c3ac845..dcc1b694 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -48,20 +48,42 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr));
}
-static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
+/**
+ * Checks if the parameters in a register write call are valid and logs in the case that
+ * they are not
+ * @param base_address The first address in the sequence of registers that will be written
+ * @param size_in_bytes The number of registers that will be written
+ * @return true if the parameters are valid, false otherwise
+ */
+static bool CheckWriteParameters(u32 base_address, u32 size_in_bytes) {
// TODO: Return proper error codes
if (base_address + size_in_bytes >= 0x420000) {
LOG_ERROR(Service_GSP, "Write address out of range! (address=0x%08x, size=0x%08x)",
base_address, size_in_bytes);
- return;
+ return false;
}
// size should be word-aligned
if ((size_in_bytes % 4) != 0) {
LOG_ERROR(Service_GSP, "Invalid size 0x%08x", size_in_bytes);
- return;
+ return false;
}
+ return true;
+}
+
+/**
+ * Writes sequential GSP GPU hardware registers using an array of source data
+ *
+ * @param base_address The address of the first register in the sequence
+ * @param size_in_bytes The number of registers to update (size of data)
+ * @param data A pointer to the source data
+ */
+static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
+ // TODO: Return proper error codes
+ if (!CheckWriteParameters(base_address, size_in_bytes))
+ return;
+
while (size_in_bytes > 0) {
GPU::Write<u32>(base_address + 0x1EB00000, *data);
@@ -71,17 +93,80 @@ static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
}
}
-/// Write a GSP GPU hardware register
+/**
+ * GSP_GPU::WriteHWRegs service function
+ *
+ * Writes sequential GSP GPU hardware registers
+ *
+ * Inputs:
+ * 1 : address of first GPU register
+ * 2 : number of registers to write sequentially
+ * 4 : pointer to source data array
+ */
static void WriteHWRegs(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 reg_addr = cmd_buff[1];
u32 size = cmd_buff[2];
- u32* src = (u32*)Memory::GetPointer(cmd_buff[0x4]);
+ u32* src = (u32*)Memory::GetPointer(cmd_buff[4]);
WriteHWRegs(reg_addr, size, src);
}
+/**
+ * Updates sequential GSP GPU hardware registers using parallel arrays of source data and masks.
+ * For each register, the value is updated only where the mask is high
+ *
+ * @param base_address The address of the first register in the sequence
+ * @param size_in_bytes The number of registers to update (size of data)
+ * @param data A pointer to the source data to use for updates
+ * @param masks A pointer to the masks
+ */
+static void WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) {
+ // TODO: Return proper error codes
+ if (!CheckWriteParameters(base_address, size_in_bytes))
+ return;
+
+ while (size_in_bytes > 0) {
+ const u32 reg_address = base_address + 0x1EB00000;
+
+ u32 reg_value;
+ GPU::Read<u32>(reg_value, reg_address);
+
+ // Update the current value of the register only for set mask bits
+ reg_value = (reg_value & ~*masks) | (*data | *masks);
+
+ GPU::Write<u32>(reg_address, reg_value);
+
+ size_in_bytes -= 4;
+ ++data;
+ ++masks;
+ base_address += 4;
+ }
+}
+
+/**
+ * GSP_GPU::WriteHWRegsWithMask service function
+ *
+ * Updates sequential GSP GPU hardware registers using masks
+ *
+ * Inputs:
+ * 1 : address of first GPU register
+ * 2 : number of registers to update sequentially
+ * 4 : pointer to source data array
+ * 6 : pointer to mask array
+ */
+static void WriteHWRegsWithMask(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 reg_addr = cmd_buff[1];
+ u32 size = cmd_buff[2];
+
+ u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]);
+ u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]);
+
+ WriteHWRegsWithMask(reg_addr, size, src_data, mask_data);
+}
+
/// Read a GSP GPU hardware register
static void ReadHWRegs(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -350,7 +435,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) {
const Interface::FunctionInfo FunctionTable[] = {
{0x00010082, WriteHWRegs, "WriteHWRegs"},
- {0x00020084, nullptr, "WriteHWRegsWithMask"},
+ {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"},
{0x00030082, nullptr, "WriteHWRegRepeat"},
{0x00040080, ReadHWRegs, "ReadHWRegs"},
{0x00050200, SetBufferSwap, "SetBufferSwap"},