Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / pure_interp.c
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
43 static precomp_instr interp_PC;
44 unsigned int op;
45
46 static 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
100 #include "interpreter.def"
101
102 // two functions are defined from the macros above but never used
103 // these prototype declarations will prevent a warning
104 #if defined(__GNUC__)
105   void JR_IDLE(void) __attribute__((used));
106   void JALR_IDLE(void) __attribute__((used));
107 #endif
108
109 static 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
386 static 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
400 void 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 }