ALL: Huge upstream synch + PerRom DelaySI & CountPerOp parameters
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86_64 / gspecial.c
CommitLineData
451ab91e 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
39void 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
55void 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
71void 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
87void 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
117void 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
147void 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
177void 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
246void 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
321void 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
336void gensync(void)
337{
338}
339
340void 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
355void 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
370void 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
385void 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
400void 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
432void 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
464void 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
496void 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
514void 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
532void 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
553void 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
574void 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
582void 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
600void 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
608void 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
616void 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
640void 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
664void 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
691void 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
718void 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
742void 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
766void 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
790void 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
821void 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
839void 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
857void 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
881void 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
905void 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
932void 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
959void 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
967void 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
983void 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
999void 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
1015void 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
1031void 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
1047void 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