Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86_64 / gregimm.c
CommitLineData
451ab91e 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
36static 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
61void 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
82void 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
103void 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
121static 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
144void 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
165void 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
186void 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
204void 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
225void 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
246void 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
264void 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
285void 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
306void 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
324static 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
351void 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
373void 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
395void 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
414void 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
436void 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
458void 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
477void 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
499void 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
521void 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
540void 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
562void 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
584void 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