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