CORE: Few fixes from mupen64plus-ae
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / pure_interp.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - pure_interp.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2002 Hacktarux *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22#include <stdlib.h>
23#include <math.h>
24
25#include "api/m64p_types.h"
26#include "api/callbacks.h"
27#include "api/debugger.h"
28#include "memory/memory.h"
29#include "main/rom.h"
30#include "osal/preproc.h"
31
32#include "r4300.h"
33#include "ops.h"
34#include "exception.h"
35#include "macros.h"
36#include "interupt.h"
37
38#ifdef DBG
39#include "debugger/dbg_types.h"
40#include "debugger/debugger.h"
41#endif
42
43static precomp_instr interp_PC;
44unsigned int op;
45
46static void prefetch(void);
47
48#define PCADDR interp_PC.addr
49#define ADD_TO_PC(x) interp_PC.addr += x*4;
50#define DECLARE_INSTRUCTION(name) static void name(void)
51#define DECLARE_JUMP(name, destination, condition, link, likely, cop1) \
52 static void name(void) \
53 { \
54 const int take_jump = (condition); \
55 const unsigned int jump_target = (destination); \
56 long long int *link_register = (link); \
57 if (cop1 && check_cop1_unusable()) return; \
58 if (!likely || take_jump) \
59 { \
60 interp_PC.addr += 4; \
61 delay_slot=1; \
62 prefetch(); \
63 PC->ops(); \
64 update_count(); \
65 delay_slot=0; \
66 if (take_jump && !skip_jump) \
67 { \
68 if (link_register != &reg[0]) \
69 { \
70 *link_register=interp_PC.addr; \
71 sign_extended(*link_register); \
72 } \
73 interp_PC.addr = jump_target; \
74 } \
75 } \
76 else \
77 { \
78 interp_PC.addr += 8; \
79 update_count(); \
80 } \
81 last_addr = interp_PC.addr; \
82 if (next_interupt <= Count) gen_interupt(); \
83 } \
84 static void name##_IDLE(void) \
85 { \
86 const int take_jump = (condition); \
87 int skip; \
88 if (cop1 && check_cop1_unusable()) return; \
89 if (take_jump) \
90 { \
91 update_count(); \
92 skip = next_interupt - Count; \
93 if (skip > 3) Count += (skip & 0xFFFFFFFC); \
94 else name(); \
95 } \
96 else name(); \
97 }
98#define CHECK_MEMORY()
99
451ab91e 100// two functions are defined from the macros above but never used
101// these prototype declarations will prevent a warning
102#if defined(__GNUC__)
7b232824 103 static void JR_IDLE(void) __attribute__((used));
104 static void JALR_IDLE(void) __attribute__((used));
451ab91e 105#endif
106
7b232824 107#include "interpreter.def"
108
451ab91e 109static cpu_instruction_table pure_interpreter_table = {
110 LB,
111 LBU,
112 LH,
113 LHU,
114 LW,
115 LWL,
116 LWR,
117 SB,
118 SH,
119 SW,
120 SWL,
121 SWR,
122
123 LD,
124 LDL,
125 LDR,
126 LL,
127 LWU,
128 SC,
129 SD,
130 SDL,
131 SDR,
132 SYNC,
133
134 ADDI,
135 ADDIU,
136 SLTI,
137 SLTIU,
138 ANDI,
139 ORI,
140 XORI,
141 LUI,
142
143 DADDI,
144 DADDIU,
145
146 ADD,
147 ADDU,
148 SUB,
149 SUBU,
150 SLT,
151 SLTU,
152 AND,
153 OR,
154 XOR,
155 NOR,
156
157 DADD,
158 DADDU,
159 DSUB,
160 DSUBU,
161
162 MULT,
163 MULTU,
164 DIV,
165 DIVU,
166 MFHI,
167 MTHI,
168 MFLO,
169 MTLO,
170
171 DMULT,
172 DMULTU,
173 DDIV,
174 DDIVU,
175
176 J,
177 J, // _OUT (unused)
178 J_IDLE,
179 JAL,
180 JAL, // _OUT (unused)
181 JAL_IDLE,
182 JR,
183 JALR,
184 BEQ,
185 BEQ, // _OUT (unused)
186 BEQ_IDLE,
187 BNE,
188 BNE, // _OUT (unused)
189 BNE_IDLE,
190 BLEZ,
191 BLEZ, // _OUT (unused)
192 BLEZ_IDLE,
193 BGTZ,
194 BGTZ, // _OUT (unused)
195 BGTZ_IDLE,
196 BLTZ,
197 BLTZ, // _OUT (unused)
198 BLTZ_IDLE,
199 BGEZ,
200 BGEZ, // _OUT (unused)
201 BGEZ_IDLE,
202 BLTZAL,
203 BLTZAL, // _OUT (unused)
204 BLTZAL_IDLE,
205 BGEZAL,
206 BGEZAL, // _OUT (unused)
207 BGEZAL_IDLE,
208
209 BEQL,
210 BEQL, // _OUT (unused)
211 BEQL_IDLE,
212 BNEL,
213 BNEL, // _OUT (unused)
214 BNEL_IDLE,
215 BLEZL,
216 BLEZL, // _OUT (unused)
217 BLEZL_IDLE,
218 BGTZL,
219 BGTZL, // _OUT (unused)
220 BGTZL_IDLE,
221 BLTZL,
222 BLTZL, // _OUT (unused)
223 BLTZL_IDLE,
224 BGEZL,
225 BGEZL, // _OUT (unused)
226 BGEZL_IDLE,
227 BLTZALL,
228 BLTZALL, // _OUT (unused)
229 BLTZALL_IDLE,
230 BGEZALL,
231 BGEZALL, // _OUT (unused)
232 BGEZALL_IDLE,
233 BC1TL,
234 BC1TL, // _OUT (unused)
235 BC1TL_IDLE,
236 BC1FL,
237 BC1FL, // _OUT (unused)
238 BC1FL_IDLE,
239
240 SLL,
241 SRL,
242 SRA,
243 SLLV,
244 SRLV,
245 SRAV,
246
247 DSLL,
248 DSRL,
249 DSRA,
250 DSLLV,
251 DSRLV,
252 DSRAV,
253 DSLL32,
254 DSRL32,
255 DSRA32,
256
257 MTC0,
258 MFC0,
259
260 TLBR,
261 TLBWI,
262 TLBWR,
263 TLBP,
264 CACHE,
265 ERET,
266
267 LWC1,
268 SWC1,
269 MTC1,
270 MFC1,
271 CTC1,
272 CFC1,
273 BC1T,
274 BC1T, // _OUT (unused)
275 BC1T_IDLE,
276 BC1F,
277 BC1F, // _OUT (unused)
278 BC1F_IDLE,
279
280 DMFC1,
281 DMTC1,
282 LDC1,
283 SDC1,
284
285 CVT_S_D,
286 CVT_S_W,
287 CVT_S_L,
288 CVT_D_S,
289 CVT_D_W,
290 CVT_D_L,
291 CVT_W_S,
292 CVT_W_D,
293 CVT_L_S,
294 CVT_L_D,
295
296 ROUND_W_S,
297 ROUND_W_D,
298 ROUND_L_S,
299 ROUND_L_D,
300
301 TRUNC_W_S,
302 TRUNC_W_D,
303 TRUNC_L_S,
304 TRUNC_L_D,
305
306 CEIL_W_S,
307 CEIL_W_D,
308 CEIL_L_S,
309 CEIL_L_D,
310
311 FLOOR_W_S,
312 FLOOR_W_D,
313 FLOOR_L_S,
314 FLOOR_L_D,
315
316 ADD_S,
317 ADD_D,
318
319 SUB_S,
320 SUB_D,
321
322 MUL_S,
323 MUL_D,
324
325 DIV_S,
326 DIV_D,
327
328 ABS_S,
329 ABS_D,
330
331 MOV_S,
332 MOV_D,
333
334 NEG_S,
335 NEG_D,
336
337 SQRT_S,
338 SQRT_D,
339
340 C_F_S,
341 C_F_D,
342 C_UN_S,
343 C_UN_D,
344 C_EQ_S,
345 C_EQ_D,
346 C_UEQ_S,
347 C_UEQ_D,
348 C_OLT_S,
349 C_OLT_D,
350 C_ULT_S,
351 C_ULT_D,
352 C_OLE_S,
353 C_OLE_D,
354 C_ULE_S,
355 C_ULE_D,
356 C_SF_S,
357 C_SF_D,
358 C_NGLE_S,
359 C_NGLE_D,
360 C_SEQ_S,
361 C_SEQ_D,
362 C_NGL_S,
363 C_NGL_D,
364 C_LT_S,
365 C_LT_D,
366 C_NGE_S,
367 C_NGE_D,
368 C_LE_S,
369 C_LE_D,
370 C_NGT_S,
371 C_NGT_D,
372
373 SYSCALL,
374
375 TEQ,
376
377 NOP,
378 RESERVED,
379 NI,
380
381 NULL, // FIN_BLOCK
382 NULL, // NOTCOMPILED
383 NULL, // NOTCOMPILED2
384};
385
386static void prefetch(void)
387{
388 unsigned int *mem = fast_mem_access(interp_PC.addr);
389 if (mem != NULL)
390 {
391 prefetch_opcode(mem[0], mem[1]);
392 }
393 else
394 {
395 DebugMessage(M64MSG_ERROR, "prefetch() execute address :%x", PC->addr);
396 stop=1;
397 }
398}
399
400void pure_interpreter(void)
401{
402 stop=0;
403 PC = &interp_PC;
404 PC->addr = last_addr = 0xa4000040;
405
406/*#ifdef DBG
407 if (g_DebuggerActive)
408 update_debugger(PC->addr);
409#endif*/
410
411 current_instruction_table = pure_interpreter_table;
412
413 while (!stop)
414 {
415 prefetch();
416#ifdef COMPARE_CORE
417 CoreCompareCallback();
418#endif
419#ifdef DBG
420 if (g_DebuggerActive) update_debugger(PC->addr);
421#endif
422 PC->ops();
423 }
424}