Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86 / gregimm.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - gregimm.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 <stdio.h>
23
24 #include "assemble.h"
25 #include "interpret.h"
26
27 #include "r4300/recomph.h"
28 #include "r4300/recomp.h"
29 #include "r4300/r4300.h"
30 #include "r4300/ops.h"
31 #include "r4300/macros.h"
32
33 #include "memory/memory.h"
34
35 static void genbltz_test(void)
36 {
37    int rs_64bit = is64((unsigned int *)dst->f.i.rs);
38    
39    if (!rs_64bit)
40      {
41     int rs = allocate_register((unsigned int *)dst->f.i.rs);
42     
43     cmp_reg32_imm32(rs, 0);
44     jge_rj(12);
45     mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10
46     jmp_imm_short(10); // 2
47     mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10
48      }
49    else if (rs_64bit == -1)
50      {
51     cmp_m32_imm32(((unsigned int *)dst->f.i.rs)+1, 0);
52     jge_rj(12);
53     mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10
54     jmp_imm_short(10); // 2
55     mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10
56      }
57    else
58      {
59     int rs2 = allocate_64_register2((unsigned int *)dst->f.i.rs);
60     
61     cmp_reg32_imm32(rs2, 0);
62     jge_rj(12);
63     mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10
64     jmp_imm_short(10); // 2
65     mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10
66      }
67 }
68
69 void genbltz(void)
70 {
71 #ifdef INTERPRET_BLTZ
72    gencallinterp((unsigned int)cached_interpreter_table.BLTZ, 1);
73 #else
74    if (((dst->addr & 0xFFF) == 0xFFC && 
75        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
76      {
77     gencallinterp((unsigned int)cached_interpreter_table.BLTZ, 1);
78     return;
79      }
80    
81    genbltz_test();
82    gendelayslot();
83    gentest();
84 #endif
85 }
86
87 void genbltz_out(void)
88 {
89 #ifdef INTERPRET_BLTZ_OUT
90    gencallinterp((unsigned int)cached_interpreter_table.BLTZ_OUT, 1);
91 #else
92    if (((dst->addr & 0xFFF) == 0xFFC && 
93        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
94      {
95     gencallinterp((unsigned int)cached_interpreter_table.BLTZ_OUT, 1);
96     return;
97      }
98    
99    genbltz_test();
100    gendelayslot();
101    gentest_out();
102 #endif
103 }
104
105 void genbltz_idle(void)
106 {
107 #ifdef INTERPRET_BLTZ_IDLE
108    gencallinterp((unsigned int)cached_interpreter_table.BLTZ_IDLE, 1);
109 #else
110    if (((dst->addr & 0xFFF) == 0xFFC && 
111        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
112      {
113     gencallinterp((unsigned int)cached_interpreter_table.BLTZ_IDLE, 1);
114     return;
115      }
116    
117    genbltz_test();
118    gentest_idle();
119    genbltz();
120 #endif
121 }
122
123 static void genbgez_test(void)
124 {
125    int rs_64bit = is64((unsigned int *)dst->f.i.rs);
126    
127    if (!rs_64bit)
128      {
129     int rs = allocate_register((unsigned int *)dst->f.i.rs);
130     
131     cmp_reg32_imm32(rs, 0);
132     jl_rj(12);
133     mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10
134     jmp_imm_short(10); // 2
135     mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10
136      }
137    else if (rs_64bit == -1)
138      {
139     cmp_m32_imm32(((unsigned int *)dst->f.i.rs)+1, 0);
140     jl_rj(12);
141     mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10
142     jmp_imm_short(10); // 2
143     mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10
144      }
145    else
146      {
147     int rs2 = allocate_64_register2((unsigned int *)dst->f.i.rs);
148     
149     cmp_reg32_imm32(rs2, 0);
150     jl_rj(12);
151     mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10
152     jmp_imm_short(10); // 2
153     mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10
154      }
155 }
156
157 void genbgez(void)
158 {
159 #ifdef INTERPRET_BGEZ
160    gencallinterp((unsigned int)cached_interpreter_table.BGEZ, 1);
161 #else
162    if (((dst->addr & 0xFFF) == 0xFFC && 
163        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
164      {
165     gencallinterp((unsigned int)cached_interpreter_table.BGEZ, 1);
166     return;
167      }
168    
169    genbgez_test();
170    gendelayslot();
171    gentest();
172 #endif
173 }
174
175 void genbgez_out(void)
176 {
177 #ifdef INTERPRET_BGEZ_OUT
178    gencallinterp((unsigned int)cached_interpreter_table.BGEZ_OUT, 1);
179 #else
180    if (((dst->addr & 0xFFF) == 0xFFC && 
181        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
182      {
183     gencallinterp((unsigned int)cached_interpreter_table.BGEZ_OUT, 1);
184     return;
185      }
186    
187    genbgez_test();
188    gendelayslot();
189    gentest_out();
190 #endif
191 }
192
193 void genbgez_idle(void)
194 {
195 #ifdef INTERPRET_BGEZ_IDLE
196    gencallinterp((unsigned int)cached_interpreter_table.BGEZ_IDLE, 1);
197 #else
198    if (((dst->addr & 0xFFF) == 0xFFC && 
199        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
200      {
201     gencallinterp((unsigned int)cached_interpreter_table.BGEZ_IDLE, 1);
202     return;
203      }
204    
205    genbgez_test();
206    gentest_idle();
207    genbgez();
208 #endif
209 }
210
211 void genbltzl(void)
212 {
213 #ifdef INTERPRET_BLTZL
214    gencallinterp((unsigned int)cached_interpreter_table.BLTZL, 1);
215 #else
216    if (((dst->addr & 0xFFF) == 0xFFC && 
217        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
218      {
219     gencallinterp((unsigned int)cached_interpreter_table.BLTZL, 1);
220     return;
221      }
222    
223    genbltz_test();
224    free_all_registers();
225    gentestl();
226 #endif
227 }
228
229 void genbltzl_out(void)
230 {
231 #ifdef INTERPRET_BLTZL_OUT
232    gencallinterp((unsigned int)cached_interpreter_table.BLTZL_OUT, 1);
233 #else
234    if (((dst->addr & 0xFFF) == 0xFFC && 
235        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
236      {
237     gencallinterp((unsigned int)cached_interpreter_table.BLTZL_OUT, 1);
238     return;
239      }
240    
241    genbltz_test();
242    free_all_registers();
243    gentestl_out();
244 #endif
245 }
246
247 void genbltzl_idle(void)
248 {
249 #ifdef INTERPRET_BLTZL_IDLE
250    gencallinterp((unsigned int)cached_interpreter_table.BLTZL_IDLE, 1);
251 #else
252    if (((dst->addr & 0xFFF) == 0xFFC && 
253        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
254      {
255     gencallinterp((unsigned int)cached_interpreter_table.BLTZL_IDLE, 1);
256     return;
257      }
258    
259    genbltz_test();
260    gentest_idle();
261    genbltzl();
262 #endif
263 }
264
265 void genbgezl(void)
266 {
267 #ifdef INTERPRET_BGEZL
268    gencallinterp((unsigned int)cached_interpreter_table.BGEZL, 1);
269 #else
270    if (((dst->addr & 0xFFF) == 0xFFC && 
271        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
272      {
273     gencallinterp((unsigned int)cached_interpreter_table.BGEZL, 1);
274     return;
275      }
276    
277    genbgez_test();
278    free_all_registers();
279    gentestl();
280 #endif
281 }
282
283 void genbgezl_out(void)
284 {
285 #ifdef INTERPRET_BGEZL_OUT
286    gencallinterp((unsigned int)cached_interpreter_table.BGEZL_OUT, 1);
287 #else
288    if (((dst->addr & 0xFFF) == 0xFFC && 
289        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
290      {
291     gencallinterp((unsigned int)cached_interpreter_table.BGEZL_OUT, 1);
292     return;
293      }
294    
295    genbgez_test();
296    free_all_registers();
297    gentestl_out();
298 #endif
299 }
300
301 void genbgezl_idle(void)
302 {
303 #ifdef INTERPRET_BGEZL_IDLE
304    gencallinterp((unsigned int)cached_interpreter_table.BGEZL_IDLE, 1);
305 #else
306    if (((dst->addr & 0xFFF) == 0xFFC && 
307        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
308      {
309     gencallinterp((unsigned int)cached_interpreter_table.BGEZL_IDLE, 1);
310     return;
311      }
312    
313    genbgez_test();
314    gentest_idle();
315    genbgezl();
316 #endif
317 }
318
319 static void genbranchlink(void)
320 {
321    int r31_64bit = is64((unsigned int*)&reg[31]);
322    
323    if (!r31_64bit)
324      {
325     int r31 = allocate_register_w((unsigned int *)&reg[31]);
326     
327     mov_reg32_imm32(r31, dst->addr+8);
328      }
329    else if (r31_64bit == -1)
330      {
331     mov_m32_imm32((unsigned int *)&reg[31], dst->addr + 8);
332     if (dst->addr & 0x80000000)
333       mov_m32_imm32(((unsigned int *)&reg[31])+1, 0xFFFFFFFF);
334     else
335       mov_m32_imm32(((unsigned int *)&reg[31])+1, 0);
336      }
337    else
338      {
339     int r311 = allocate_64_register1_w((unsigned int *)&reg[31]);
340     int r312 = allocate_64_register2_w((unsigned int *)&reg[31]);
341     
342     mov_reg32_imm32(r311, dst->addr+8);
343     if (dst->addr & 0x80000000)
344       mov_reg32_imm32(r312, 0xFFFFFFFF);
345     else
346       mov_reg32_imm32(r312, 0);
347      }
348 }
349
350 void genbltzal(void)
351 {
352 #ifdef INTERPRET_BLTZAL
353    gencallinterp((unsigned int)cached_interpreter_table.BLTZAL, 1);
354 #else
355    if (((dst->addr & 0xFFF) == 0xFFC && 
356        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
357      {
358     gencallinterp((unsigned int)cached_interpreter_table.BLTZAL, 1);
359     return;
360      }
361    
362    genbltz_test();
363    genbranchlink();
364    gendelayslot();
365    gentest();
366 #endif
367 }
368
369 void genbltzal_out(void)
370 {
371 #ifdef INTERPRET_BLTZAL_OUT
372    gencallinterp((unsigned int)cached_interpreter_table.BLTZAL_OUT, 1);
373 #else
374    if (((dst->addr & 0xFFF) == 0xFFC && 
375        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
376      {
377     gencallinterp((unsigned int)cached_interpreter_table.BLTZAL_OUT, 1);
378     return;
379      }
380    
381    genbltz_test();
382    genbranchlink();
383    gendelayslot();
384    gentest_out();
385 #endif
386 }
387
388 void genbltzal_idle(void)
389 {
390 #ifdef INTERPRET_BLTZAL_IDLE
391    gencallinterp((unsigned int)cached_interpreter_table.BLTZAL_IDLE, 1);
392 #else
393    if (((dst->addr & 0xFFF) == 0xFFC && 
394        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
395      {
396     gencallinterp((unsigned int)cached_interpreter_table.BLTZAL_IDLE, 1);
397     return;
398      }
399    
400    genbltz_test();
401    genbranchlink();
402    gentest_idle();
403    genbltzal();
404 #endif
405 }
406
407 void genbgezal(void)
408 {
409 #ifdef INTERPRET_BGEZAL
410    gencallinterp((unsigned int)cached_interpreter_table.BGEZAL, 1);
411 #else
412    if (((dst->addr & 0xFFF) == 0xFFC && 
413        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
414      {
415     gencallinterp((unsigned int)cached_interpreter_table.BGEZAL, 1);
416     return;
417      }
418    
419    genbgez_test();
420    genbranchlink();
421    gendelayslot();
422    gentest();
423 #endif
424 }
425
426 void genbgezal_out(void)
427 {
428 #ifdef INTERPRET_BGEZAL_OUT
429    gencallinterp((unsigned int)cached_interpreter_table.BGEZAL_OUT, 1);
430 #else
431    if (((dst->addr & 0xFFF) == 0xFFC && 
432        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
433      {
434     gencallinterp((unsigned int)cached_interpreter_table.BGEZAL_OUT, 1);
435     return;
436      }
437    
438    genbgez_test();
439    genbranchlink();
440    gendelayslot();
441    gentest_out();
442 #endif
443 }
444
445 void genbgezal_idle(void)
446 {
447 #ifdef INTERPRET_BGEZAL_IDLE
448    gencallinterp((unsigned int)cached_interpreter_table.BGEZAL_IDLE, 1);
449 #else
450    if (((dst->addr & 0xFFF) == 0xFFC && 
451        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
452      {
453     gencallinterp((unsigned int)cached_interpreter_table.BGEZAL_IDLE, 1);
454     return;
455      }
456    
457    genbgez_test();
458    genbranchlink();
459    gentest_idle();
460    genbgezal();
461 #endif
462 }
463
464 void genbltzall(void)
465 {
466 #ifdef INTERPRET_BLTZALL
467    gencallinterp((unsigned int)cached_interpreter_table.BLTZALL, 1);
468 #else
469    if (((dst->addr & 0xFFF) == 0xFFC && 
470        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
471      {
472     gencallinterp((unsigned int)cached_interpreter_table.BLTZALL, 1);
473     return;
474      }
475    
476    genbltz_test();
477    genbranchlink();
478    free_all_registers();
479    gentestl();
480 #endif
481 }
482
483 void genbltzall_out(void)
484 {
485 #ifdef INTERPRET_BLTZALL_OUT
486    gencallinterp((unsigned int)cached_interpreter_table.BLTZALL_OUT, 1);
487 #else
488    if (((dst->addr & 0xFFF) == 0xFFC && 
489        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
490      {
491     gencallinterp((unsigned int)cached_interpreter_table.BLTZALL_OUT, 1);
492     return;
493      }
494    
495    genbltz_test();
496    genbranchlink();
497    free_all_registers();
498    gentestl_out();
499 #endif
500 }
501
502 void genbltzall_idle(void)
503 {
504 #ifdef INTERPRET_BLTZALL_IDLE
505    gencallinterp((unsigned int)cached_interpreter_table.BLTZALL_IDLE, 1);
506 #else
507    if (((dst->addr & 0xFFF) == 0xFFC && 
508        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
509      {
510     gencallinterp((unsigned int)cached_interpreter_table.BLTZALL_IDLE, 1);
511     return;
512      }
513    
514    genbltz_test();
515    genbranchlink();
516    gentest_idle();
517    genbltzall();
518 #endif
519 }
520
521 void genbgezall(void)
522 {
523 #ifdef INTERPRET_BGEZALL
524    gencallinterp((unsigned int)cached_interpreter_table.BGEZALL, 1);
525 #else
526    if (((dst->addr & 0xFFF) == 0xFFC && 
527        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
528      {
529     gencallinterp((unsigned int)cached_interpreter_table.BGEZALL, 1);
530     return;
531      }
532    
533    genbgez_test();
534    genbranchlink();
535    free_all_registers();
536    gentestl();
537 #endif
538 }
539
540 void genbgezall_out(void)
541 {
542 #ifdef INTERPRET_BGEZALL_OUT
543    gencallinterp((unsigned int)cached_interpreter_table.BGEZALL_OUT, 1);
544 #else
545    if (((dst->addr & 0xFFF) == 0xFFC && 
546        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
547      {
548     gencallinterp((unsigned int)cached_interpreter_table.BGEZALL_OUT, 1);
549     return;
550      }
551    
552    genbgez_test();
553    genbranchlink();
554    free_all_registers();
555    gentestl_out();
556 #endif
557 }
558
559 void genbgezall_idle(void)
560 {
561 #ifdef INTERPRET_BGEZALL_IDLE
562    gencallinterp((unsigned int)cached_interpreter_table.BGEZALL_IDLE, 1);
563 #else
564    if (((dst->addr & 0xFFF) == 0xFFC && 
565        (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
566      {
567     gencallinterp((unsigned int)cached_interpreter_table.BGEZALL_IDLE, 1);
568     return;
569      }
570    
571    genbgez_test();
572    genbranchlink();
573    gentest_idle();
574    genbgezall();
575 #endif
576 }
577