summaryrefslogtreecommitdiff
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 68fddc94f..1977112dd 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() {
23 23
24 ARMul_NewState((ARMul_State*)state.get()); 24 ARMul_NewState((ARMul_State*)state.get());
25 25
26 state->abort_model = 0; 26 state->abort_model = ABORT_BASE_RESTORED;
27 state->cpu = (cpu_config_t*)&s_arm11_cpu_info; 27 state->cpu = (cpu_config_t*)&s_arm11_cpu_info;
28 state->bigendSig = LOW; 28 state->bigendSig = LOW;
29 29
@@ -34,7 +34,7 @@ ARM_DynCom::ARM_DynCom() {
34 ARMul_CoProInit(state.get()); 34 ARMul_CoProInit(state.get());
35 ARMul_Reset(state.get()); 35 ARMul_Reset(state.get());
36 state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext 36 state->NextInstr = RESUME; // NOTE: This will be overwritten by LoadContext
37 state->Emulate = 3; 37 state->Emulate = RUN;
38 38
39 state->Reg[15] = 0x00000000; 39 state->Reg[15] = 0x00000000;
40 state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack 40 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 7b502e240..e7545728e 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)
74 for (unsigned int i = 0; i < 7; i++) 74 for (unsigned int i = 0; i < 7; i++)
75 state->Spsr[i] = 0; 75 state->Spsr[i] = 0;
76 76
77 state->Mode = 0; 77 state->Mode = USER32MODE;
78 78
79 state->VectorCatch = 0; 79 state->VectorCatch = 0;
80 state->Aborted = false; 80 state->Aborted = false;
@@ -82,14 +82,6 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
82 state->Inted = 3; 82 state->Inted = 3;
83 state->LastInted = 3; 83 state->LastInted = 3;
84 84
85#ifdef ARM61
86 state->prog32Sig = LOW;
87 state->data32Sig = LOW;
88#else
89 state->prog32Sig = HIGH;
90 state->data32Sig = HIGH;
91#endif
92
93 state->lateabtSig = HIGH; 85 state->lateabtSig = HIGH;
94 state->bigendSig = LOW; 86 state->bigendSig = LOW;
95 87
@@ -102,14 +94,6 @@ ARMul_State* ARMul_NewState(ARMul_State* state)
102 94
103void ARMul_SelectProcessor(ARMul_State* state, unsigned properties) 95void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
104{ 96{
105 if (properties & ARM_Fix26_Prop) {
106 state->prog32Sig = LOW;
107 state->data32Sig = LOW;
108 } else {
109 state->prog32Sig = HIGH;
110 state->data32Sig = HIGH;
111 }
112
113 state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0; 97 state->is_v4 = (properties & (ARM_v4_Prop | ARM_v5_Prop)) != 0;
114 state->is_v5 = (properties & ARM_v5_Prop) != 0; 98 state->is_v5 = (properties & ARM_v5_Prop) != 0;
115 state->is_v5e = (properties & ARM_v5e_Prop) != 0; 99 state->is_v5e = (properties & ARM_v5e_Prop) != 0;
@@ -132,15 +116,10 @@ void ARMul_SelectProcessor(ARMul_State* state, unsigned properties)
132void ARMul_Reset(ARMul_State* state) 116void ARMul_Reset(ARMul_State* state)
133{ 117{
134 state->NextInstr = 0; 118 state->NextInstr = 0;
135 if (state->prog32Sig) { 119
136 state->Reg[15] = 0; 120 state->Reg[15] = 0;
137 state->Cpsr = INTBITS | SVC32MODE; 121 state->Cpsr = INTBITS | SVC32MODE;
138 state->Mode = SVC32MODE; 122 state->Mode = SVC32MODE;
139 } else {
140 state->Reg[15] = R15INTBITS | SVC26MODE;
141 state->Cpsr = INTBITS | SVC26MODE;
142 state->Mode = SVC26MODE;
143 }
144 123
145 state->Bank = SVCBANK; 124 state->Bank = SVCBANK;
146 FLUSHPIPE; 125 FLUSHPIPE;
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index ff9296e0f..012c43c61 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -35,15 +35,27 @@
35#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) 35#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
36#define BIT(s, n) ((s >> (n)) & 1) 36#define BIT(s, n) ((s >> (n)) & 1)
37 37
38#define LOW 0 38// Signal levels
39#define HIGH 1 39enum {
40#define LOWHIGH 1 40 LOW = 0,
41#define HIGHLOW 2 41 HIGH = 1,
42 LOWHIGH = 1,
43 HIGHLOW = 2
44};
45
46// Cache types
47enum {
48 NONCACHE = 0,
49 DATACACHE = 1,
50 INSTCACHE = 2,
51};
42 52
43//the define of cachetype 53// Abort models
44#define NONCACHE 0 54enum {
45#define DATACACHE 1 55 ABORT_BASE_RESTORED = 0,
46#define INSTCACHE 2 56 ABORT_EARLY = 1,
57 ABORT_BASE_UPDATED = 2
58};
47 59
48#define POS(i) ( (~(i)) >> 31 ) 60#define POS(i) ( (~(i)) >> 31 )
49#define NEG(i) ( (i) >> 31 ) 61#define NEG(i) ( (i) >> 31 )
@@ -137,8 +149,6 @@ struct ARMul_State
137 unsigned abortSig; 149 unsigned abortSig;
138 unsigned NtransSig; 150 unsigned NtransSig;
139 unsigned bigendSig; 151 unsigned bigendSig;
140 unsigned prog32Sig;
141 unsigned data32Sig;
142 unsigned syscallSig; 152 unsigned syscallSig;
143 153
144/* 2004-05-09 chy 154/* 2004-05-09 chy
@@ -215,7 +225,6 @@ typedef ARMul_State arm_core_t;
215\***************************************************************************/ 225\***************************************************************************/
216 226
217enum { 227enum {
218 ARM_Fix26_Prop = 0x01,
219 ARM_Nexec_Prop = 0x02, 228 ARM_Nexec_Prop = 0x02,
220 ARM_Debug_Prop = 0x10, 229 ARM_Debug_Prop = 0x10,
221 ARM_Isync_Prop = ARM_Debug_Prop, 230 ARM_Isync_Prop = ARM_Debug_Prop,
@@ -230,19 +239,6 @@ enum {
230 ARM_iWMMXt_Prop = 0x800, 239 ARM_iWMMXt_Prop = 0x800,
231 ARM_PXA27X_Prop = 0x1000, 240 ARM_PXA27X_Prop = 0x1000,
232 ARM_v7_Prop = 0x2000, 241 ARM_v7_Prop = 0x2000,
233
234 // ARM2 family
235 ARM2 = ARM_Fix26_Prop,
236 ARM2as = ARM2,
237 ARM61 = ARM2,
238 ARM3 = ARM2,
239
240 // ARM6 family
241 ARM6 = ARM_Lock_Prop,
242 ARM60 = ARM6,
243 ARM600 = ARM6,
244 ARM610 = ARM6,
245 ARM620 = ARM6
246}; 242};
247 243
248/***************************************************************************\ 244/***************************************************************************\
@@ -275,10 +271,6 @@ enum {
275\***************************************************************************/ 271\***************************************************************************/
276 272
277enum { 273enum {
278 USER26MODE = 0,
279 FIQ26MODE = 1,
280 IRQ26MODE = 2,
281 SVC26MODE = 3,
282 USER32MODE = 16, 274 USER32MODE = 16,
283 FIQ32MODE = 17, 275 FIQ32MODE = 17,
284 IRQ32MODE = 18, 276 IRQ32MODE = 18,
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index beee54c9a..5d4c06837 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -76,24 +76,28 @@
76#define R15MODE (state->Reg[15] & R15MODEBITS) 76#define R15MODE (state->Reg[15] & R15MODEBITS)
77 77
78// Different ways to start the next instruction. 78// Different ways to start the next instruction.
79#define SEQ 0 79enum {
80#define NONSEQ 1 80 SEQ = 0,
81#define PCINCEDSEQ 2 81 NONSEQ = 1,
82#define PCINCEDNONSEQ 3 82 PCINCEDSEQ = 2,
83#define PRIMEPIPE 4 83 PCINCEDNONSEQ = 3,
84#define RESUME 8 84 PRIMEPIPE = 4,
85 RESUME = 8
86};
87
88// Values for Emulate.
89enum {
90 STOP = 0, // Stop
91 CHANGEMODE = 1, // Change mode
92 ONCE = 2, // Execute just one interation
93 RUN = 3 // Continuous execution
94};
85 95
86#define FLUSHPIPE state->NextInstr |= PRIMEPIPE 96#define FLUSHPIPE state->NextInstr |= PRIMEPIPE
87 97
88// Macro to rotate n right by b bits. 98// Macro to rotate n right by b bits.
89#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) 99#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b))))
90 100
91// Values for Emulate.
92#define STOP 0 // stop
93#define CHANGEMODE 1 // change mode
94#define ONCE 2 // execute just one interation
95#define RUN 3 // continuous execution
96
97// Stuff that is shared across modes. 101// Stuff that is shared across modes.
98extern unsigned ARMul_MultTable[]; // Number of I cycles for a mult. 102extern unsigned ARMul_MultTable[]; // Number of I cycles for a mult.
99extern ARMword ARMul_ImmedTable[]; // Immediate DP LHS values. 103extern 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 4c3ac845b..dcc1b6942 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) {
48 return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr)); 48 return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr));
49} 49}
50 50
51static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { 51/**
52 * Checks if the parameters in a register write call are valid and logs in the case that
53 * they are not
54 * @param base_address The first address in the sequence of registers that will be written
55 * @param size_in_bytes The number of registers that will be written
56 * @return true if the parameters are valid, false otherwise
57 */
58static bool CheckWriteParameters(u32 base_address, u32 size_in_bytes) {
52 // TODO: Return proper error codes 59 // TODO: Return proper error codes
53 if (base_address + size_in_bytes >= 0x420000) { 60 if (base_address + size_in_bytes >= 0x420000) {
54 LOG_ERROR(Service_GSP, "Write address out of range! (address=0x%08x, size=0x%08x)", 61 LOG_ERROR(Service_GSP, "Write address out of range! (address=0x%08x, size=0x%08x)",
55 base_address, size_in_bytes); 62 base_address, size_in_bytes);
56 return; 63 return false;
57 } 64 }
58 65
59 // size should be word-aligned 66 // size should be word-aligned
60 if ((size_in_bytes % 4) != 0) { 67 if ((size_in_bytes % 4) != 0) {
61 LOG_ERROR(Service_GSP, "Invalid size 0x%08x", size_in_bytes); 68 LOG_ERROR(Service_GSP, "Invalid size 0x%08x", size_in_bytes);
62 return; 69 return false;
63 } 70 }
64 71
72 return true;
73}
74
75/**
76 * Writes sequential GSP GPU hardware registers using an array of source data
77 *
78 * @param base_address The address of the first register in the sequence
79 * @param size_in_bytes The number of registers to update (size of data)
80 * @param data A pointer to the source data
81 */
82static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
83 // TODO: Return proper error codes
84 if (!CheckWriteParameters(base_address, size_in_bytes))
85 return;
86
65 while (size_in_bytes > 0) { 87 while (size_in_bytes > 0) {
66 GPU::Write<u32>(base_address + 0x1EB00000, *data); 88 GPU::Write<u32>(base_address + 0x1EB00000, *data);
67 89
@@ -71,17 +93,80 @@ static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
71 } 93 }
72} 94}
73 95
74/// Write a GSP GPU hardware register 96/**
97 * GSP_GPU::WriteHWRegs service function
98 *
99 * Writes sequential GSP GPU hardware registers
100 *
101 * Inputs:
102 * 1 : address of first GPU register
103 * 2 : number of registers to write sequentially
104 * 4 : pointer to source data array
105 */
75static void WriteHWRegs(Service::Interface* self) { 106static void WriteHWRegs(Service::Interface* self) {
76 u32* cmd_buff = Kernel::GetCommandBuffer(); 107 u32* cmd_buff = Kernel::GetCommandBuffer();
77 u32 reg_addr = cmd_buff[1]; 108 u32 reg_addr = cmd_buff[1];
78 u32 size = cmd_buff[2]; 109 u32 size = cmd_buff[2];
79 110
80 u32* src = (u32*)Memory::GetPointer(cmd_buff[0x4]); 111 u32* src = (u32*)Memory::GetPointer(cmd_buff[4]);
81 112
82 WriteHWRegs(reg_addr, size, src); 113 WriteHWRegs(reg_addr, size, src);
83} 114}
84 115
116/**
117 * Updates sequential GSP GPU hardware registers using parallel arrays of source data and masks.
118 * For each register, the value is updated only where the mask is high
119 *
120 * @param base_address The address of the first register in the sequence
121 * @param size_in_bytes The number of registers to update (size of data)
122 * @param data A pointer to the source data to use for updates
123 * @param masks A pointer to the masks
124 */
125static void WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) {
126 // TODO: Return proper error codes
127 if (!CheckWriteParameters(base_address, size_in_bytes))
128 return;
129
130 while (size_in_bytes > 0) {
131 const u32 reg_address = base_address + 0x1EB00000;
132
133 u32 reg_value;
134 GPU::Read<u32>(reg_value, reg_address);
135
136 // Update the current value of the register only for set mask bits
137 reg_value = (reg_value & ~*masks) | (*data | *masks);
138
139 GPU::Write<u32>(reg_address, reg_value);
140
141 size_in_bytes -= 4;
142 ++data;
143 ++masks;
144 base_address += 4;
145 }
146}
147
148/**
149 * GSP_GPU::WriteHWRegsWithMask service function
150 *
151 * Updates sequential GSP GPU hardware registers using masks
152 *
153 * Inputs:
154 * 1 : address of first GPU register
155 * 2 : number of registers to update sequentially
156 * 4 : pointer to source data array
157 * 6 : pointer to mask array
158 */
159static void WriteHWRegsWithMask(Service::Interface* self) {
160 u32* cmd_buff = Kernel::GetCommandBuffer();
161 u32 reg_addr = cmd_buff[1];
162 u32 size = cmd_buff[2];
163
164 u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]);
165 u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]);
166
167 WriteHWRegsWithMask(reg_addr, size, src_data, mask_data);
168}
169
85/// Read a GSP GPU hardware register 170/// Read a GSP GPU hardware register
86static void ReadHWRegs(Service::Interface* self) { 171static void ReadHWRegs(Service::Interface* self) {
87 u32* cmd_buff = Kernel::GetCommandBuffer(); 172 u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -350,7 +435,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) {
350 435
351const Interface::FunctionInfo FunctionTable[] = { 436const Interface::FunctionInfo FunctionTable[] = {
352 {0x00010082, WriteHWRegs, "WriteHWRegs"}, 437 {0x00010082, WriteHWRegs, "WriteHWRegs"},
353 {0x00020084, nullptr, "WriteHWRegsWithMask"}, 438 {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"},
354 {0x00030082, nullptr, "WriteHWRegRepeat"}, 439 {0x00030082, nullptr, "WriteHWRegRepeat"},
355 {0x00040080, ReadHWRegs, "ReadHWRegs"}, 440 {0x00040080, ReadHWRegs, "ReadHWRegs"},
356 {0x00050200, SetBufferSwap, "SetBufferSwap"}, 441 {0x00050200, SetBufferSwap, "SetBufferSwap"},