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