Core commit. Compile and run on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86 / gspecial.c
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
34 void 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
47 void 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
60 void 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
73 void 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
100 void 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
127 void 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
154 void 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
220 void 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
292 void 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
304 void gensync(void)
305 {
306 }
307
308 void 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
323 void 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
338 void 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
353 void 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
368 void 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
416 void 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
464 void 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
512 void 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
527 void 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
542 void 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
560 void 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
578 void gendmult(void)
579 {
580    gencallinterp((unsigned int)cached_interpreter_table.DMULT, 0);
581 }
582
583 void 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
622 void genddiv(void)
623 {
624    gencallinterp((unsigned int)cached_interpreter_table.DDIV, 0);
625 }
626
627 void genddivu(void)
628 {
629    gencallinterp((unsigned int)cached_interpreter_table.DDIVU, 0);
630 }
631
632 void 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
657 void 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
682 void 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
707 void 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
732 void 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
765 void 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
798 void 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
831 void 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
868 void 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
890 void 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
912 void 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
945 void 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
978 void 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
1011 void 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
1044 void genteq(void)
1045 {
1046    gencallinterp((unsigned int)cached_interpreter_table.TEQ, 0);
1047 }
1048
1049 void 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
1071 void 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
1093 void 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
1115 void 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
1130 void 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
1145 void 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