ALL: Huge upstream synch + PerRom DelaySI & CountPerOp parameters
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86 / gspecial.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - gspecial.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#include "r4300/exception.h"
33
34void gensll(void)
35{
36#ifdef INTERPRET_SLL
37 gencallinterp((unsigned int)cached_interpreter_table.SLL, 0);
38#else
39 int rt = allocate_register((unsigned int *)dst->f.r.rt);
40 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
41
42 mov_reg32_reg32(rd, rt);
43 shl_reg32_imm8(rd, dst->f.r.sa);
44#endif
45}
46
47void gensrl(void)
48{
49#ifdef INTERPRET_SRL
50 gencallinterp((unsigned int)cached_interpreter_table.SRL, 0);
51#else
52 int rt = allocate_register((unsigned int *)dst->f.r.rt);
53 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
54
55 mov_reg32_reg32(rd, rt);
56 shr_reg32_imm8(rd, dst->f.r.sa);
57#endif
58}
59
60void gensra(void)
61{
62#ifdef INTERPRET_SRA
63 gencallinterp((unsigned int)cached_interpreter_table.SRA, 0);
64#else
65 int rt = allocate_register((unsigned int *)dst->f.r.rt);
66 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
67
68 mov_reg32_reg32(rd, rt);
69 sar_reg32_imm8(rd, dst->f.r.sa);
70#endif
71}
72
73void gensllv(void)
74{
75#ifdef INTERPRET_SLLV
76 gencallinterp((unsigned int)cached_interpreter_table.SLLV, 0);
77#else
78 int rt, rd;
79 allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);
80
81 rt = allocate_register((unsigned int *)dst->f.r.rt);
82 rd = allocate_register_w((unsigned int *)dst->f.r.rd);
83
84 if (rd != ECX)
85 {
86 mov_reg32_reg32(rd, rt);
87 shl_reg32_cl(rd);
88 }
89 else
90 {
91 int temp = lru_register();
92 free_register(temp);
93 mov_reg32_reg32(temp, rt);
94 shl_reg32_cl(temp);
95 mov_reg32_reg32(rd, temp);
96 }
97#endif
98}
99
100void gensrlv(void)
101{
102#ifdef INTERPRET_SRLV
103 gencallinterp((unsigned int)cached_interpreter_table.SRLV, 0);
104#else
105 int rt, rd;
106 allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);
107
108 rt = allocate_register((unsigned int *)dst->f.r.rt);
109 rd = allocate_register_w((unsigned int *)dst->f.r.rd);
110
111 if (rd != ECX)
112 {
113 mov_reg32_reg32(rd, rt);
114 shr_reg32_cl(rd);
115 }
116 else
117 {
118 int temp = lru_register();
119 free_register(temp);
120 mov_reg32_reg32(temp, rt);
121 shr_reg32_cl(temp);
122 mov_reg32_reg32(rd, temp);
123 }
124#endif
125}
126
127void gensrav(void)
128{
129#ifdef INTERPRET_SRAV
130 gencallinterp((unsigned int)cached_interpreter_table.SRAV, 0);
131#else
132 int rt, rd;
133 allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);
134
135 rt = allocate_register((unsigned int *)dst->f.r.rt);
136 rd = allocate_register_w((unsigned int *)dst->f.r.rd);
137
138 if (rd != ECX)
139 {
140 mov_reg32_reg32(rd, rt);
141 sar_reg32_cl(rd);
142 }
143 else
144 {
145 int temp = lru_register();
146 free_register(temp);
147 mov_reg32_reg32(temp, rt);
148 sar_reg32_cl(temp);
149 mov_reg32_reg32(rd, temp);
150 }
151#endif
152}
153
154void genjr(void)
155{
156#ifdef INTERPRET_JR
157 gencallinterp((unsigned int)cached_interpreter_table.JR, 1);
158#else
159 static unsigned int precomp_instr_size = sizeof(precomp_instr);
160 unsigned int diff =
161 (unsigned int)(&dst->local_addr) - (unsigned int)(dst);
162 unsigned int diff_need =
163 (unsigned int)(&dst->reg_cache_infos.need_map) - (unsigned int)(dst);
164 unsigned int diff_wrap =
165 (unsigned int)(&dst->reg_cache_infos.jump_wrapper) - (unsigned int)(dst);
166
167 if (((dst->addr & 0xFFF) == 0xFFC &&
168 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
169 {
170 gencallinterp((unsigned int)cached_interpreter_table.JR, 1);
171 return;
172 }
173
174 free_all_registers();
175 simplify_access();
176 mov_eax_memoffs32((unsigned int *)dst->f.i.rs);
177 mov_memoffs32_eax((unsigned int *)&local_rs);
178
179 gendelayslot();
180
181 mov_eax_memoffs32((unsigned int *)&local_rs);
182 mov_memoffs32_eax((unsigned int *)&last_addr);
183
184 gencheck_interupt_reg();
185
186 mov_eax_memoffs32((unsigned int *)&local_rs);
187 mov_reg32_reg32(EBX, EAX);
188 and_eax_imm32(0xFFFFF000);
189 cmp_eax_imm32(dst_block->start & 0xFFFFF000);
190 je_near_rj(0);
191
192 jump_start_rel32();
193
194 mov_m32_reg32(&jump_to_address, EBX);
195 mov_m32_imm32((unsigned int*)(&PC), (unsigned int)(dst+1));
196 mov_reg32_imm32(EAX, (unsigned int)jump_to_func);
197 call_reg32(EAX);
198
199 jump_end_rel32();
200
201 mov_reg32_reg32(EAX, EBX);
202 sub_eax_imm32(dst_block->start);
203 shr_reg32_imm8(EAX, 2);
204 mul_m32((unsigned int *)(&precomp_instr_size));
205
206 mov_reg32_preg32pimm32(EBX, EAX, (unsigned int)(dst_block->block)+diff_need);
207 cmp_reg32_imm32(EBX, 1);
208 jne_rj(7);
209
210 add_eax_imm32((unsigned int)(dst_block->block)+diff_wrap); // 5
211 jmp_reg32(EAX); // 2
212
213 mov_reg32_preg32pimm32(EAX, EAX, (unsigned int)(dst_block->block)+diff);
214 add_reg32_m32(EAX, (unsigned int *)(&dst_block->code));
215
216 jmp_reg32(EAX);
217#endif
218}
219
220void genjalr(void)
221{
222#ifdef INTERPRET_JALR
223 gencallinterp((unsigned int)cached_interpreter_table.JALR, 0);
224#else
225 static unsigned int precomp_instr_size = sizeof(precomp_instr);
226 unsigned int diff =
227 (unsigned int)(&dst->local_addr) - (unsigned int)(dst);
228 unsigned int diff_need =
229 (unsigned int)(&dst->reg_cache_infos.need_map) - (unsigned int)(dst);
230 unsigned int diff_wrap =
231 (unsigned int)(&dst->reg_cache_infos.jump_wrapper) - (unsigned int)(dst);
232
233 if (((dst->addr & 0xFFF) == 0xFFC &&
234 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
235 {
236 gencallinterp((unsigned int)cached_interpreter_table.JALR, 1);
237 return;
238 }
239
240 free_all_registers();
241 simplify_access();
242 mov_eax_memoffs32((unsigned int *)dst->f.r.rs);
243 mov_memoffs32_eax((unsigned int *)&local_rs);
244
245 gendelayslot();
246
247 mov_m32_imm32((unsigned int *)(dst-1)->f.r.rd, dst->addr+4);
248 if ((dst->addr+4) & 0x80000000)
249 mov_m32_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0xFFFFFFFF);
250 else
251 mov_m32_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0);
252
253 mov_eax_memoffs32((unsigned int *)&local_rs);
254 mov_memoffs32_eax((unsigned int *)&last_addr);
255
256 gencheck_interupt_reg();
257
258 mov_eax_memoffs32((unsigned int *)&local_rs);
259 mov_reg32_reg32(EBX, EAX);
260 and_eax_imm32(0xFFFFF000);
261 cmp_eax_imm32(dst_block->start & 0xFFFFF000);
262 je_near_rj(0);
263
264 jump_start_rel32();
265
266 mov_m32_reg32(&jump_to_address, EBX);
267 mov_m32_imm32((unsigned int*)(&PC), (unsigned int)(dst+1));
268 mov_reg32_imm32(EAX, (unsigned int)jump_to_func);
269 call_reg32(EAX);
270
271 jump_end_rel32();
272
273 mov_reg32_reg32(EAX, EBX);
274 sub_eax_imm32(dst_block->start);
275 shr_reg32_imm8(EAX, 2);
276 mul_m32((unsigned int *)(&precomp_instr_size));
277
278 mov_reg32_preg32pimm32(EBX, EAX, (unsigned int)(dst_block->block)+diff_need);
279 cmp_reg32_imm32(EBX, 1);
280 jne_rj(7);
281
282 add_eax_imm32((unsigned int)(dst_block->block)+diff_wrap); // 5
283 jmp_reg32(EAX); // 2
284
285 mov_reg32_preg32pimm32(EAX, EAX, (unsigned int)(dst_block->block)+diff);
286 add_reg32_m32(EAX, (unsigned int *)(&dst_block->code));
287
288 jmp_reg32(EAX);
289#endif
290}
291
292void gensyscall(void)
293{
294#ifdef INTERPRET_SYSCALL
295 gencallinterp((unsigned int)cached_interpreter_table.SYSCALL, 0);
296#else
297 free_all_registers();
298 simplify_access();
299 mov_m32_imm32(&Cause, 8 << 2);
300 gencallinterp((unsigned int)exception_general, 0);
301#endif
302}
303
304void gensync(void)
305{
306}
307
308void genmfhi(void)
309{
310#ifdef INTERPRET_MFHI
311 gencallinterp((unsigned int)cached_interpreter_table.MFHI, 0);
312#else
313 int rd1 = allocate_64_register1_w((unsigned int*)dst->f.r.rd);
314 int rd2 = allocate_64_register2_w((unsigned int*)dst->f.r.rd);
315 int hi1 = allocate_64_register1((unsigned int*)&hi);
316 int hi2 = allocate_64_register2((unsigned int*)&hi);
317
318 mov_reg32_reg32(rd1, hi1);
319 mov_reg32_reg32(rd2, hi2);
320#endif
321}
322
323void genmthi(void)
324{
325#ifdef INTERPRET_MTHI
326 gencallinterp((unsigned int)cached_interpreter_table.MTHI, 0);
327#else
328 int hi1 = allocate_64_register1_w((unsigned int*)&hi);
329 int hi2 = allocate_64_register2_w((unsigned int*)&hi);
330 int rs1 = allocate_64_register1((unsigned int*)dst->f.r.rs);
331 int rs2 = allocate_64_register2((unsigned int*)dst->f.r.rs);
332
333 mov_reg32_reg32(hi1, rs1);
334 mov_reg32_reg32(hi2, rs2);
335#endif
336}
337
338void genmflo(void)
339{
340#ifdef INTERPRET_MFLO
341 gencallinterp((unsigned int)cached_interpreter_table.MFLO, 0);
342#else
343 int rd1 = allocate_64_register1_w((unsigned int*)dst->f.r.rd);
344 int rd2 = allocate_64_register2_w((unsigned int*)dst->f.r.rd);
345 int lo1 = allocate_64_register1((unsigned int*)&lo);
346 int lo2 = allocate_64_register2((unsigned int*)&lo);
347
348 mov_reg32_reg32(rd1, lo1);
349 mov_reg32_reg32(rd2, lo2);
350#endif
351}
352
353void genmtlo(void)
354{
355#ifdef INTERPRET_MTLO
356 gencallinterp((unsigned int)cached_interpreter_table.MTLO, 0);
357#else
358 int lo1 = allocate_64_register1_w((unsigned int*)&lo);
359 int lo2 = allocate_64_register2_w((unsigned int*)&lo);
360 int rs1 = allocate_64_register1((unsigned int*)dst->f.r.rs);
361 int rs2 = allocate_64_register2((unsigned int*)dst->f.r.rs);
362
363 mov_reg32_reg32(lo1, rs1);
364 mov_reg32_reg32(lo2, rs2);
365#endif
366}
367
368void gendsllv(void)
369{
370#ifdef INTERPRET_DSLLV
371 gencallinterp((unsigned int)cached_interpreter_table.DSLLV, 0);
372#else
373 int rt1, rt2, rd1, rd2;
374 allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);
375
376 rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
377 rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
378 rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
379 rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
380
381 if (rd1 != ECX && rd2 != ECX)
382 {
383 mov_reg32_reg32(rd1, rt1);
384 mov_reg32_reg32(rd2, rt2);
385 shld_reg32_reg32_cl(rd2,rd1);
386 shl_reg32_cl(rd1);
387 test_reg32_imm32(ECX, 0x20);
388 je_rj(4);
389 mov_reg32_reg32(rd2, rd1); // 2
390 xor_reg32_reg32(rd1, rd1); // 2
391 }
392 else
393 {
394 int temp1, temp2;
395 force_32(ECX);
396 temp1 = lru_register();
397 temp2 = lru_register_exc1(temp1);
398 free_register(temp1);
399 free_register(temp2);
400
401 mov_reg32_reg32(temp1, rt1);
402 mov_reg32_reg32(temp2, rt2);
403 shld_reg32_reg32_cl(temp2, temp1);
404 shl_reg32_cl(temp1);
405 test_reg32_imm32(ECX, 0x20);
406 je_rj(4);
407 mov_reg32_reg32(temp2, temp1); // 2
408 xor_reg32_reg32(temp1, temp1); // 2
409
410 mov_reg32_reg32(rd1, temp1);
411 mov_reg32_reg32(rd2, temp2);
412 }
413#endif
414}
415
416void gendsrlv(void)
417{
418#ifdef INTERPRET_DSRLV
419 gencallinterp((unsigned int)cached_interpreter_table.DSRLV, 0);
420#else
421 int rt1, rt2, rd1, rd2;
422 allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);
423
424 rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
425 rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
426 rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
427 rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
428
429 if (rd1 != ECX && rd2 != ECX)
430 {
431 mov_reg32_reg32(rd1, rt1);
432 mov_reg32_reg32(rd2, rt2);
433 shrd_reg32_reg32_cl(rd1,rd2);
434 shr_reg32_cl(rd2);
435 test_reg32_imm32(ECX, 0x20);
436 je_rj(4);
437 mov_reg32_reg32(rd1, rd2); // 2
438 xor_reg32_reg32(rd2, rd2); // 2
439 }
440 else
441 {
442 int temp1, temp2;
443 force_32(ECX);
444 temp1 = lru_register();
445 temp2 = lru_register_exc1(temp1);
446 free_register(temp1);
447 free_register(temp2);
448
449 mov_reg32_reg32(temp1, rt1);
450 mov_reg32_reg32(temp2, rt2);
451 shrd_reg32_reg32_cl(temp1, temp2);
452 shr_reg32_cl(temp2);
453 test_reg32_imm32(ECX, 0x20);
454 je_rj(4);
455 mov_reg32_reg32(temp1, temp2); // 2
456 xor_reg32_reg32(temp2, temp2); // 2
457
458 mov_reg32_reg32(rd1, temp1);
459 mov_reg32_reg32(rd2, temp2);
460 }
461#endif
462}
463
464void gendsrav(void)
465{
466#ifdef INTERPRET_DSRAV
467 gencallinterp((unsigned int)cached_interpreter_table.DSRAV, 0);
468#else
469 int rt1, rt2, rd1, rd2;
470 allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs);
471
472 rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
473 rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
474 rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
475 rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
476
477 if (rd1 != ECX && rd2 != ECX)
478 {
479 mov_reg32_reg32(rd1, rt1);
480 mov_reg32_reg32(rd2, rt2);
481 shrd_reg32_reg32_cl(rd1,rd2);
482 sar_reg32_cl(rd2);
483 test_reg32_imm32(ECX, 0x20);
484 je_rj(5);
485 mov_reg32_reg32(rd1, rd2); // 2
486 sar_reg32_imm8(rd2, 31); // 3
487 }
488 else
489 {
490 int temp1, temp2;
491 force_32(ECX);
492 temp1 = lru_register();
493 temp2 = lru_register_exc1(temp1);
494 free_register(temp1);
495 free_register(temp2);
496
497 mov_reg32_reg32(temp1, rt1);
498 mov_reg32_reg32(temp2, rt2);
499 shrd_reg32_reg32_cl(temp1, temp2);
500 sar_reg32_cl(temp2);
501 test_reg32_imm32(ECX, 0x20);
502 je_rj(5);
503 mov_reg32_reg32(temp1, temp2); // 2
504 sar_reg32_imm8(temp2, 31); // 3
505
506 mov_reg32_reg32(rd1, temp1);
507 mov_reg32_reg32(rd2, temp2);
508 }
509#endif
510}
511
512void genmult(void)
513{
514#ifdef INTERPRET_MULT
515 gencallinterp((unsigned int)cached_interpreter_table.MULT, 0);
516#else
517 int rs, rt;
518 allocate_register_manually_w(EAX, (unsigned int *)&lo, 0);
519 allocate_register_manually_w(EDX, (unsigned int *)&hi, 0);
520 rs = allocate_register((unsigned int*)dst->f.r.rs);
521 rt = allocate_register((unsigned int*)dst->f.r.rt);
522 mov_reg32_reg32(EAX, rs);
523 imul_reg32(rt);
524#endif
525}
526
527void genmultu(void)
528{
529#ifdef INTERPRET_MULTU
530 gencallinterp((unsigned int)cached_interpreter_table.MULTU, 0);
531#else
532 int rs, rt;
533 allocate_register_manually_w(EAX, (unsigned int *)&lo, 0);
534 allocate_register_manually_w(EDX, (unsigned int *)&hi, 0);
535 rs = allocate_register((unsigned int*)dst->f.r.rs);
536 rt = allocate_register((unsigned int*)dst->f.r.rt);
537 mov_reg32_reg32(EAX, rs);
538 mul_reg32(rt);
539#endif
540}
541
542void gendiv(void)
543{
544#ifdef INTERPRET_DIV
545 gencallinterp((unsigned int)cached_interpreter_table.DIV, 0);
546#else
547 int rs, rt;
548 allocate_register_manually_w(EAX, (unsigned int *)&lo, 0);
549 allocate_register_manually_w(EDX, (unsigned int *)&hi, 0);
550 rs = allocate_register((unsigned int*)dst->f.r.rs);
551 rt = allocate_register((unsigned int*)dst->f.r.rt);
552 cmp_reg32_imm32(rt, 0);
553 je_rj((rs == EAX ? 0 : 2) + 1 + 2);
554 mov_reg32_reg32(EAX, rs); // 0 or 2
555 cdq(); // 1
556 idiv_reg32(rt); // 2
557#endif
558}
559
560void gendivu(void)
561{
562#ifdef INTERPRET_DIVU
563 gencallinterp((unsigned int)cached_interpreter_table.DIVU, 0);
564#else
565 int rs, rt;
566 allocate_register_manually_w(EAX, (unsigned int *)&lo, 0);
567 allocate_register_manually_w(EDX, (unsigned int *)&hi, 0);
568 rs = allocate_register((unsigned int*)dst->f.r.rs);
569 rt = allocate_register((unsigned int*)dst->f.r.rt);
570 cmp_reg32_imm32(rt, 0);
571 je_rj((rs == EAX ? 0 : 2) + 2 + 2);
572 mov_reg32_reg32(EAX, rs); // 0 or 2
573 xor_reg32_reg32(EDX, EDX); // 2
574 div_reg32(rt); // 2
575#endif
576}
577
578void gendmult(void)
579{
580 gencallinterp((unsigned int)cached_interpreter_table.DMULT, 0);
581}
582
583void gendmultu(void)
584{
585#ifdef INTERPRET_DMULTU
586 gencallinterp((unsigned int)cached_interpreter_table.DMULTU, 0);
587#else
588 free_all_registers();
589 simplify_access();
590
591 mov_eax_memoffs32((unsigned int *)dst->f.r.rs);
592 mul_m32((unsigned int *)dst->f.r.rt); // EDX:EAX = temp1
593 mov_memoffs32_eax((unsigned int *)(&lo));
594
595 mov_reg32_reg32(EBX, EDX); // EBX = temp1>>32
596 mov_eax_memoffs32((unsigned int *)dst->f.r.rs);
597 mul_m32((unsigned int *)(dst->f.r.rt)+1);
598 add_reg32_reg32(EBX, EAX);
599 adc_reg32_imm32(EDX, 0);
600 mov_reg32_reg32(ECX, EDX); // ECX:EBX = temp2
601
602 mov_eax_memoffs32((unsigned int *)(dst->f.r.rs)+1);
603 mul_m32((unsigned int *)dst->f.r.rt); // EDX:EAX = temp3
604
605 add_reg32_reg32(EBX, EAX);
606 adc_reg32_imm32(ECX, 0); // ECX:EBX = result2
607 mov_m32_reg32((unsigned int*)(&lo)+1, EBX);
608
609 mov_reg32_reg32(ESI, EDX); // ESI = temp3>>32
610 mov_eax_memoffs32((unsigned int *)(dst->f.r.rs)+1);
611 mul_m32((unsigned int *)(dst->f.r.rt)+1);
612 add_reg32_reg32(EAX, ESI);
613 adc_reg32_imm32(EDX, 0); // EDX:EAX = temp4
614
615 add_reg32_reg32(EAX, ECX);
616 adc_reg32_imm32(EDX, 0); // EDX:EAX = result3
617 mov_memoffs32_eax((unsigned int *)(&hi));
618 mov_m32_reg32((unsigned int *)(&hi)+1, EDX);
619#endif
620}
621
622void genddiv(void)
623{
624 gencallinterp((unsigned int)cached_interpreter_table.DDIV, 0);
625}
626
627void genddivu(void)
628{
629 gencallinterp((unsigned int)cached_interpreter_table.DDIVU, 0);
630}
631
632void genadd(void)
633{
634#ifdef INTERPRET_ADD
635 gencallinterp((unsigned int)cached_interpreter_table.ADD, 0);
636#else
637 int rs = allocate_register((unsigned int *)dst->f.r.rs);
638 int rt = allocate_register((unsigned int *)dst->f.r.rt);
639 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
640
641 if (rt != rd && rs != rd)
642 {
643 mov_reg32_reg32(rd, rs);
644 add_reg32_reg32(rd, rt);
645 }
646 else
647 {
648 int temp = lru_register();
649 free_register(temp);
650 mov_reg32_reg32(temp, rs);
651 add_reg32_reg32(temp, rt);
652 mov_reg32_reg32(rd, temp);
653 }
654#endif
655}
656
657void genaddu(void)
658{
659#ifdef INTERPRET_ADDU
660 gencallinterp((unsigned int)cached_interpreter_table.ADDU, 0);
661#else
662 int rs = allocate_register((unsigned int *)dst->f.r.rs);
663 int rt = allocate_register((unsigned int *)dst->f.r.rt);
664 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
665
666 if (rt != rd && rs != rd)
667 {
668 mov_reg32_reg32(rd, rs);
669 add_reg32_reg32(rd, rt);
670 }
671 else
672 {
673 int temp = lru_register();
674 free_register(temp);
675 mov_reg32_reg32(temp, rs);
676 add_reg32_reg32(temp, rt);
677 mov_reg32_reg32(rd, temp);
678 }
679#endif
680}
681
682void gensub(void)
683{
684#ifdef INTERPRET_SUB
685 gencallinterp((unsigned int)cached_interpreter_table.SUB, 0);
686#else
687 int rs = allocate_register((unsigned int *)dst->f.r.rs);
688 int rt = allocate_register((unsigned int *)dst->f.r.rt);
689 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
690
691 if (rt != rd && rs != rd)
692 {
693 mov_reg32_reg32(rd, rs);
694 sub_reg32_reg32(rd, rt);
695 }
696 else
697 {
698 int temp = lru_register();
699 free_register(temp);
700 mov_reg32_reg32(temp, rs);
701 sub_reg32_reg32(temp, rt);
702 mov_reg32_reg32(rd, temp);
703 }
704#endif
705}
706
707void gensubu(void)
708{
709#ifdef INTERPRET_SUBU
710 gencallinterp((unsigned int)cached_interpreter_table.SUBU, 0);
711#else
712 int rs = allocate_register((unsigned int *)dst->f.r.rs);
713 int rt = allocate_register((unsigned int *)dst->f.r.rt);
714 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
715
716 if (rt != rd && rs != rd)
717 {
718 mov_reg32_reg32(rd, rs);
719 sub_reg32_reg32(rd, rt);
720 }
721 else
722 {
723 int temp = lru_register();
724 free_register(temp);
725 mov_reg32_reg32(temp, rs);
726 sub_reg32_reg32(temp, rt);
727 mov_reg32_reg32(rd, temp);
728 }
729#endif
730}
731
732void genand(void)
733{
734#ifdef INTERPRET_AND
735 gencallinterp((unsigned int)cached_interpreter_table.AND, 0);
736#else
737 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
738 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
739 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
740 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
741 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
742 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
743
744 if (rt1 != rd1 && rs1 != rd1)
745 {
746 mov_reg32_reg32(rd1, rs1);
747 mov_reg32_reg32(rd2, rs2);
748 and_reg32_reg32(rd1, rt1);
749 and_reg32_reg32(rd2, rt2);
750 }
751 else
752 {
753 int temp = lru_register();
754 free_register(temp);
755 mov_reg32_reg32(temp, rs1);
756 and_reg32_reg32(temp, rt1);
757 mov_reg32_reg32(rd1, temp);
758 mov_reg32_reg32(temp, rs2);
759 and_reg32_reg32(temp, rt2);
760 mov_reg32_reg32(rd2, temp);
761 }
762#endif
763}
764
765void genor(void)
766{
767#ifdef INTERPRET_OR
768 gencallinterp((unsigned int)cached_interpreter_table.OR, 0);
769#else
770 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
771 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
772 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
773 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
774 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
775 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
776
777 if (rt1 != rd1 && rs1 != rd1)
778 {
779 mov_reg32_reg32(rd1, rs1);
780 mov_reg32_reg32(rd2, rs2);
781 or_reg32_reg32(rd1, rt1);
782 or_reg32_reg32(rd2, rt2);
783 }
784 else
785 {
786 int temp = lru_register();
787 free_register(temp);
788 mov_reg32_reg32(temp, rs1);
789 or_reg32_reg32(temp, rt1);
790 mov_reg32_reg32(rd1, temp);
791 mov_reg32_reg32(temp, rs2);
792 or_reg32_reg32(temp, rt2);
793 mov_reg32_reg32(rd2, temp);
794 }
795#endif
796}
797
798void genxor(void)
799{
800#ifdef INTERPRET_XOR
801 gencallinterp((unsigned int)cached_interpreter_table.XOR, 0);
802#else
803 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
804 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
805 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
806 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
807 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
808 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
809
810 if (rt1 != rd1 && rs1 != rd1)
811 {
812 mov_reg32_reg32(rd1, rs1);
813 mov_reg32_reg32(rd2, rs2);
814 xor_reg32_reg32(rd1, rt1);
815 xor_reg32_reg32(rd2, rt2);
816 }
817 else
818 {
819 int temp = lru_register();
820 free_register(temp);
821 mov_reg32_reg32(temp, rs1);
822 xor_reg32_reg32(temp, rt1);
823 mov_reg32_reg32(rd1, temp);
824 mov_reg32_reg32(temp, rs2);
825 xor_reg32_reg32(temp, rt2);
826 mov_reg32_reg32(rd2, temp);
827 }
828#endif
829}
830
831void gennor(void)
832{
833#ifdef INTERPRET_NOR
834 gencallinterp((unsigned int)cached_interpreter_table.NOR, 0);
835#else
836 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
837 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
838 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
839 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
840 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
841 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
842
843 if (rt1 != rd1 && rs1 != rd1)
844 {
845 mov_reg32_reg32(rd1, rs1);
846 mov_reg32_reg32(rd2, rs2);
847 or_reg32_reg32(rd1, rt1);
848 or_reg32_reg32(rd2, rt2);
849 not_reg32(rd1);
850 not_reg32(rd2);
851 }
852 else
853 {
854 int temp = lru_register();
855 free_register(temp);
856 mov_reg32_reg32(temp, rs1);
857 or_reg32_reg32(temp, rt1);
858 mov_reg32_reg32(rd1, temp);
859 mov_reg32_reg32(temp, rs2);
860 or_reg32_reg32(temp, rt2);
861 mov_reg32_reg32(rd2, temp);
862 not_reg32(rd1);
863 not_reg32(rd2);
864 }
865#endif
866}
867
868void genslt(void)
869{
870#ifdef INTERPRET_SLT
871 gencallinterp((unsigned int)cached_interpreter_table.SLT, 0);
872#else
873 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
874 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
875 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
876 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
877 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
878
879 cmp_reg32_reg32(rs2, rt2);
880 jl_rj(13);
881 jne_rj(4); // 2
882 cmp_reg32_reg32(rs1, rt1); // 2
883 jl_rj(7); // 2
884 mov_reg32_imm32(rd, 0); // 5
885 jmp_imm_short(5); // 2
886 mov_reg32_imm32(rd, 1); // 5
887#endif
888}
889
890void gensltu(void)
891{
892#ifdef INTERPRET_SLTU
893 gencallinterp((unsigned int)cached_interpreter_table.SLTU, 0);
894#else
895 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
896 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
897 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
898 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
899 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
900
901 cmp_reg32_reg32(rs2, rt2);
902 jb_rj(13);
903 jne_rj(4); // 2
904 cmp_reg32_reg32(rs1, rt1); // 2
905 jb_rj(7); // 2
906 mov_reg32_imm32(rd, 0); // 5
907 jmp_imm_short(5); // 2
908 mov_reg32_imm32(rd, 1); // 5
909#endif
910}
911
912void gendadd(void)
913{
914#ifdef INTERPRET_DADD
915 gencallinterp((unsigned int)cached_interpreter_table.DADD, 0);
916#else
917 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
918 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
919 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
920 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
921 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
922 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
923
924 if (rt1 != rd1 && rs1 != rd1)
925 {
926 mov_reg32_reg32(rd1, rs1);
927 mov_reg32_reg32(rd2, rs2);
928 add_reg32_reg32(rd1, rt1);
929 adc_reg32_reg32(rd2, rt2);
930 }
931 else
932 {
933 int temp = lru_register();
934 free_register(temp);
935 mov_reg32_reg32(temp, rs1);
936 add_reg32_reg32(temp, rt1);
937 mov_reg32_reg32(rd1, temp);
938 mov_reg32_reg32(temp, rs2);
939 adc_reg32_reg32(temp, rt2);
940 mov_reg32_reg32(rd2, temp);
941 }
942#endif
943}
944
945void gendaddu(void)
946{
947#ifdef INTERPRET_DADDU
948 gencallinterp((unsigned int)cached_interpreter_table.DADDU, 0);
949#else
950 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
951 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
952 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
953 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
954 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
955 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
956
957 if (rt1 != rd1 && rs1 != rd1)
958 {
959 mov_reg32_reg32(rd1, rs1);
960 mov_reg32_reg32(rd2, rs2);
961 add_reg32_reg32(rd1, rt1);
962 adc_reg32_reg32(rd2, rt2);
963 }
964 else
965 {
966 int temp = lru_register();
967 free_register(temp);
968 mov_reg32_reg32(temp, rs1);
969 add_reg32_reg32(temp, rt1);
970 mov_reg32_reg32(rd1, temp);
971 mov_reg32_reg32(temp, rs2);
972 adc_reg32_reg32(temp, rt2);
973 mov_reg32_reg32(rd2, temp);
974 }
975#endif
976}
977
978void gendsub(void)
979{
980#ifdef INTERPRET_DSUB
981 gencallinterp((unsigned int)cached_interpreter_table.DSUB, 0);
982#else
983 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
984 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
985 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
986 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
987 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
988 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
989
990 if (rt1 != rd1 && rs1 != rd1)
991 {
992 mov_reg32_reg32(rd1, rs1);
993 mov_reg32_reg32(rd2, rs2);
994 sub_reg32_reg32(rd1, rt1);
995 sbb_reg32_reg32(rd2, rt2);
996 }
997 else
998 {
999 int temp = lru_register();
1000 free_register(temp);
1001 mov_reg32_reg32(temp, rs1);
1002 sub_reg32_reg32(temp, rt1);
1003 mov_reg32_reg32(rd1, temp);
1004 mov_reg32_reg32(temp, rs2);
1005 sbb_reg32_reg32(temp, rt2);
1006 mov_reg32_reg32(rd2, temp);
1007 }
1008#endif
1009}
1010
1011void gendsubu(void)
1012{
1013#ifdef INTERPRET_DSUBU
1014 gencallinterp((unsigned int)cached_interpreter_table.DSUBU, 0);
1015#else
1016 int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs);
1017 int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs);
1018 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
1019 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
1020 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
1021 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
1022
1023 if (rt1 != rd1 && rs1 != rd1)
1024 {
1025 mov_reg32_reg32(rd1, rs1);
1026 mov_reg32_reg32(rd2, rs2);
1027 sub_reg32_reg32(rd1, rt1);
1028 sbb_reg32_reg32(rd2, rt2);
1029 }
1030 else
1031 {
1032 int temp = lru_register();
1033 free_register(temp);
1034 mov_reg32_reg32(temp, rs1);
1035 sub_reg32_reg32(temp, rt1);
1036 mov_reg32_reg32(rd1, temp);
1037 mov_reg32_reg32(temp, rs2);
1038 sbb_reg32_reg32(temp, rt2);
1039 mov_reg32_reg32(rd2, temp);
1040 }
1041#endif
1042}
1043
1044void genteq(void)
1045{
1046 gencallinterp((unsigned int)cached_interpreter_table.TEQ, 0);
1047}
1048
1049void gendsll(void)
1050{
1051#ifdef INTERPRET_DSLL
1052 gencallinterp((unsigned int)cached_interpreter_table.DSLL, 0);
1053#else
1054 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
1055 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
1056 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
1057 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
1058
1059 mov_reg32_reg32(rd1, rt1);
1060 mov_reg32_reg32(rd2, rt2);
1061 shld_reg32_reg32_imm8(rd2, rd1, dst->f.r.sa);
1062 shl_reg32_imm8(rd1, dst->f.r.sa);
1063 if (dst->f.r.sa & 0x20)
1064 {
1065 mov_reg32_reg32(rd2, rd1);
1066 xor_reg32_reg32(rd1, rd1);
1067 }
1068#endif
1069}
1070
1071void gendsrl(void)
1072{
1073#ifdef INTERPRET_DSRL
1074 gencallinterp((unsigned int)cached_interpreter_table.DSRL, 0);
1075#else
1076 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
1077 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
1078 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
1079 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
1080
1081 mov_reg32_reg32(rd1, rt1);
1082 mov_reg32_reg32(rd2, rt2);
1083 shrd_reg32_reg32_imm8(rd1, rd2, dst->f.r.sa);
1084 shr_reg32_imm8(rd2, dst->f.r.sa);
1085 if (dst->f.r.sa & 0x20)
1086 {
1087 mov_reg32_reg32(rd1, rd2);
1088 xor_reg32_reg32(rd2, rd2);
1089 }
1090#endif
1091}
1092
1093void gendsra(void)
1094{
1095#ifdef INTERPRET_DSRA
1096 gencallinterp((unsigned int)cached_interpreter_table.DSRA, 0);
1097#else
1098 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
1099 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
1100 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
1101 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
1102
1103 mov_reg32_reg32(rd1, rt1);
1104 mov_reg32_reg32(rd2, rt2);
1105 shrd_reg32_reg32_imm8(rd1, rd2, dst->f.r.sa);
1106 sar_reg32_imm8(rd2, dst->f.r.sa);
1107 if (dst->f.r.sa & 0x20)
1108 {
1109 mov_reg32_reg32(rd1, rd2);
1110 sar_reg32_imm8(rd2, 31);
1111 }
1112#endif
1113}
1114
1115void gendsll32(void)
1116{
1117#ifdef INTERPRET_DSLL32
1118 gencallinterp((unsigned int)cached_interpreter_table.DSLL32, 0);
1119#else
1120 int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt);
1121 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
1122 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
1123
1124 mov_reg32_reg32(rd2, rt1);
1125 shl_reg32_imm8(rd2, dst->f.r.sa);
1126 xor_reg32_reg32(rd1, rd1);
1127#endif
1128}
1129
1130void gendsrl32(void)
1131{
1132#ifdef INTERPRET_DSRL32
1133 gencallinterp((unsigned int)cached_interpreter_table.DSRL32, 0);
1134#else
1135 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
1136 int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd);
1137 int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd);
1138
1139 mov_reg32_reg32(rd1, rt2);
1140 shr_reg32_imm8(rd1, dst->f.r.sa);
1141 xor_reg32_reg32(rd2, rd2);
1142#endif
1143}
1144
1145void gendsra32(void)
1146{
1147#ifdef INTERPRET_DSRA32
1148 gencallinterp((unsigned int)cached_interpreter_table.DSRA32, 0);
1149#else
1150 int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt);
1151 int rd = allocate_register_w((unsigned int *)dst->f.r.rd);
1152
1153 mov_reg32_reg32(rd, rt2);
1154 sar_reg32_imm8(rd, dst->f.r.sa);
1155#endif
1156}
1157