ALL: Huge upstream synch + PerRom DelaySI & CountPerOp parameters
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / x86_64 / gr4300.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - gr4300.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 "assemble.h"
24#include "regcache.h"
25#include "interpret.h"
26
27#include "api/debugger.h"
28
29#include "r4300/r4300.h"
30#include "r4300/macros.h"
31#include "r4300/interupt.h"
32#include "r4300/ops.h"
33#include "r4300/recomph.h"
34#include "r4300/exception.h"
35
36#include "memory/memory.h"
37
38#if !defined(offsetof)
39# define offsetof(TYPE,MEMBER) ((unsigned int) &((TYPE*)0)->MEMBER)
40#endif
41
42#if defined(COUNT_INSTR)
43unsigned int instr_count[132];
44char instr_name[][10] =
45{
46 "reserved", "NI", "J", "JAL", "BEQ", "BNE", "BLEZ", "BGTZ",
47 "ADDI", "ADDIU", "SLTI", "SLTIU", "ANDI", "ORI", "XORI", "LUI",
48 "BEQL", "BNEL", "BLEZL", "BGTZL", "DADDI", "DADDIU", "LDL", "LDR",
49 "LB", "LH", "LW", "LWL", "LBU", "LHU", "LWU", "LWR",
50 "SB", "SH", "SW", "SWL", "SWR", "SDL", "SDR", "LWC1",
51 "LDC1", "LD", "LL", "SWC1", "SDC1", "SD", "SC", "BLTZ",
52 "BGEZ", "BLTZL", "BGEZL", "BLTZAL", "BGEZAL", "BLTZALL", "BGEZALL", "SLL",
53 "SRL", "SRA", "SLLV", "SRLV", "SRAV", "JR", "JALR", "SYSCALL",
54 "MFHI", "MTHI", "MFLO", "MTLO", "DSLLV", "DSRLV", "DSRAV", "MULT",
55 "MULTU", "DIV", "DIVU", "DMULT", "DMULTU", "DDIV", "DDIVU", "ADD",
56 "ADDU", "SUB", "SUBU", "AND", "OR", "XOR", "NOR", "SLT",
57 "SLTU", "DADD", "DADDU", "DSUB", "DSUBU", "DSLL", "DSRL", "DSRA",
58 "TEQ", "DSLL32", "DSRL32", "DSRA32", "BC1F", "BC1T", "BC1FL", "BC1TL",
59 "TLBWI", "TLBP", "TLBR", "TLBWR", "ERET", "MFC0", "MTC0", "MFC1",
60 "DMFC1", "CFC1", "MTC1", "DMTC1", "CTC1", "f.CVT", "f.CMP", "f.ADD",
61 "f.SUB", "f.MUL", "f.DIV", "f.SQRT", "f.ABS", "f.MOV", "f.NEG", "f.ROUND",
62 "f.TRUNC", "f.CEIL", "f.FLOOR"
63};
64unsigned int instr_type[131] = { 9, 10, 6, 6, 7, 7, 7, 7, 3, 3, 4, 4, 3, 4, 4, 0,
65 7, 7, 7, 7, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 7,
67 7, 7, 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 6, 6, 10,
68 2, 2, 2, 2, 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3,
69 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
70 8, 4, 4, 4, 7, 7, 7, 7, 10, 10, 10, 10, 8, 2, 2, 2,
71 2, 2, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5,
72 5, 5, 5 };
73char instr_typename[][20] = { "Load", "Store", "Data move/convert", "32-bit math", "64-bit math", "Float Math",
74 "Jump", "Branch", "Exceptions", "Reserved", "Other" };
75#endif
76
77extern unsigned int op;
78
79static precomp_instr fake_instr;
80#ifdef COMPARE_CORE
81static long long debug_reg_storage[8];
82#endif
83
84int branch_taken = 0;
85
86/* static functions */
87
88static void genupdate_count(unsigned int addr)
89{
90#if !defined(COMPARE_CORE) && !defined(DBG)
91 mov_reg32_imm32(EAX, addr);
92 sub_xreg32_m32rel(EAX, (unsigned int*)(&last_addr));
2d262872 93 shr_reg32_imm8(EAX, 2);
94 mov_xreg32_m32rel(EDX, (void*)&count_per_op);
95 mul_reg32(EDX);
451ab91e 96 add_m32rel_xreg32((unsigned int*)(&Count), EAX);
97#else
98 mov_reg64_imm64(RAX, (unsigned long long) (dst+1));
99 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
100 mov_reg64_imm64(RAX, (unsigned long long)update_count);
101 call_reg64(RAX);
102#endif
103}
104
105static void gencheck_interupt(unsigned long long instr_structure)
106{
107 mov_xreg32_m32rel(EAX, (void*)(&next_interupt));
108 cmp_xreg32_m32rel(EAX, (void*)&Count);
109 ja_rj(0);
110 jump_start_rel8();
111
112 mov_reg64_imm64(RAX, (unsigned long long) instr_structure);
113 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
114 mov_reg64_imm64(RAX, (unsigned long long) gen_interupt);
115 call_reg64(RAX);
116
117 jump_end_rel8();
118}
119
120static void gencheck_interupt_out(unsigned int addr)
121{
122 mov_xreg32_m32rel(EAX, (void*)(&next_interupt));
123 cmp_xreg32_m32rel(EAX, (void*)&Count);
124 ja_rj(0);
125 jump_start_rel8();
126
127 mov_m32rel_imm32((unsigned int*)(&fake_instr.addr), addr);
128 mov_reg64_imm64(RAX, (unsigned long long) (&fake_instr));
129 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
130 mov_reg64_imm64(RAX, (unsigned long long) gen_interupt);
131 call_reg64(RAX);
132
133 jump_end_rel8();
134}
135
136static void genbeq_test(void)
137{
138 int rs_64bit = is64((unsigned int *)dst->f.i.rs);
139 int rt_64bit = is64((unsigned int *)dst->f.i.rt);
140
141 if (rs_64bit == 0 && rt_64bit == 0)
142 {
143 int rs = allocate_register_32((unsigned int *)dst->f.i.rs);
144 int rt = allocate_register_32((unsigned int *)dst->f.i.rt);
145
146 cmp_reg32_reg32(rs, rt);
147 sete_m8rel((unsigned char *) &branch_taken);
148 }
149 else if (rs_64bit == -1)
150 {
151 int rt = allocate_register_64((unsigned long long *)dst->f.i.rt);
152
153 cmp_xreg64_m64rel(rt, (unsigned long long *) dst->f.i.rs);
154 sete_m8rel((unsigned char *) &branch_taken);
155 }
156 else if (rt_64bit == -1)
157 {
158 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
159
160 cmp_xreg64_m64rel(rs, (unsigned long long *)dst->f.i.rt);
161 sete_m8rel((unsigned char *) &branch_taken);
162 }
163 else
164 {
165 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
166 int rt = allocate_register_64((unsigned long long *)dst->f.i.rt);
167 cmp_reg64_reg64(rs, rt);
168 sete_m8rel((unsigned char *) &branch_taken);
169 }
170}
171
172static void genbne_test(void)
173{
174 int rs_64bit = is64((unsigned int *)dst->f.i.rs);
175 int rt_64bit = is64((unsigned int *)dst->f.i.rt);
176
177 if (rs_64bit == 0 && rt_64bit == 0)
178 {
179 int rs = allocate_register_32((unsigned int *)dst->f.i.rs);
180 int rt = allocate_register_32((unsigned int *)dst->f.i.rt);
181
182 cmp_reg32_reg32(rs, rt);
183 setne_m8rel((unsigned char *) &branch_taken);
184 }
185 else if (rs_64bit == -1)
186 {
187 int rt = allocate_register_64((unsigned long long *) dst->f.i.rt);
188
189 cmp_xreg64_m64rel(rt, (unsigned long long *)dst->f.i.rs);
190 setne_m8rel((unsigned char *) &branch_taken);
191 }
192 else if (rt_64bit == -1)
193 {
194 int rs = allocate_register_64((unsigned long long *) dst->f.i.rs);
195
196 cmp_xreg64_m64rel(rs, (unsigned long long *)dst->f.i.rt);
197 setne_m8rel((unsigned char *) &branch_taken);
198 }
199 else
200 {
201 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
202 int rt = allocate_register_64((unsigned long long *)dst->f.i.rt);
203
204 cmp_reg64_reg64(rs, rt);
205 setne_m8rel((unsigned char *) &branch_taken);
206 }
207}
208
209static void genblez_test(void)
210{
211 int rs_64bit = is64((unsigned int *)dst->f.i.rs);
212
213 if (rs_64bit == 0)
214 {
215 int rs = allocate_register_32((unsigned int *)dst->f.i.rs);
216
217 cmp_reg32_imm32(rs, 0);
218 setle_m8rel((unsigned char *) &branch_taken);
219 }
220 else
221 {
222 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
223
224 cmp_reg64_imm8(rs, 0);
225 setle_m8rel((unsigned char *) &branch_taken);
226 }
227}
228
229static void genbgtz_test(void)
230{
231 int rs_64bit = is64((unsigned int *)dst->f.i.rs);
232
233 if (rs_64bit == 0)
234 {
235 int rs = allocate_register_32((unsigned int *)dst->f.i.rs);
236
237 cmp_reg32_imm32(rs, 0);
238 setg_m8rel((unsigned char *) &branch_taken);
239 }
240 else
241 {
242 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
243
244 cmp_reg64_imm8(rs, 0);
245 setg_m8rel((unsigned char *) &branch_taken);
246 }
247}
248
249static void ld_register_alloc(int *pGpr1, int *pGpr2, int *pBase1, int *pBase2)
250{
251 int gpr1, gpr2, base1, base2 = 0;
252
253#ifdef COMPARE_CORE
254 free_registers_move_start(); // to maintain parity with 32-bit core
255#endif
256
257 if (dst->f.i.rs == dst->f.i.rt)
258 {
259 allocate_register_32((unsigned int*)dst->f.r.rs); // tell regcache we need to read RS register here
260 gpr1 = allocate_register_32_w((unsigned int*)dst->f.r.rt); // tell regcache we will modify RT register during this instruction
261 gpr2 = lock_register(lru_register()); // free and lock least recently used register for usage here
262 add_reg32_imm32(gpr1, (int)dst->f.i.immediate);
263 mov_reg32_reg32(gpr2, gpr1);
264 }
265 else
266 {
267 gpr2 = allocate_register_32((unsigned int*)dst->f.r.rs); // tell regcache we need to read RS register here
268 gpr1 = allocate_register_32_w((unsigned int*)dst->f.r.rt); // tell regcache we will modify RT register during this instruction
269 free_register(gpr2); // write out gpr2 if dirty because I'm going to trash it right now
270 add_reg32_imm32(gpr2, (int)dst->f.i.immediate);
271 mov_reg32_reg32(gpr1, gpr2);
272 lock_register(gpr2); // lock the freed gpr2 it so it doesn't get returned in the lru query
273 }
274 base1 = lock_register(lru_base_register()); // get another lru register
275 if (!fast_memory)
276 {
277 base2 = lock_register(lru_base_register()); // and another one if necessary
278 unlock_register(base2);
279 }
280 unlock_register(base1); // unlock the locked registers (they are
281 unlock_register(gpr2);
282 set_register_state(gpr1, NULL, 0, 0); // clear gpr1 state because it hasn't been written yet -
283 // we don't want it to be pushed/popped around read_rdramX call
284 *pGpr1 = gpr1;
285 *pGpr2 = gpr2;
286 *pBase1 = base1;
287 *pBase2 = base2;
288}
289
290
291/* global functions */
292
293void gennotcompiled(void)
294{
295 free_registers_move_start();
296
297 mov_reg64_imm64(RAX, (unsigned long long) dst);
298 mov_memoffs64_rax((unsigned long long *) &PC); /* RIP-relative will not work here */
299 mov_reg64_imm64(RAX, (unsigned long long) cached_interpreter_table.NOTCOMPILED);
300 call_reg64(RAX);
301}
302
303void genlink_subblock(void)
304{
305 free_all_registers();
306 jmp(dst->addr+4);
307}
308
309#ifdef COMPARE_CORE
310void gendebug(void)
311{
312 free_all_registers();
313
314 mov_memoffs64_rax((unsigned long long *) &debug_reg_storage);
315 mov_reg64_imm64(RAX, (unsigned long long) &debug_reg_storage);
316 mov_preg64pimm8_reg64(RAX, 8, RBX);
317 mov_preg64pimm8_reg64(RAX, 16, RCX);
318 mov_preg64pimm8_reg64(RAX, 24, RDX);
319 mov_preg64pimm8_reg64(RAX, 32, RSP);
320 mov_preg64pimm8_reg64(RAX, 40, RBP);
321 mov_preg64pimm8_reg64(RAX, 48, RSI);
322 mov_preg64pimm8_reg64(RAX, 56, RDI);
323
324 mov_reg64_imm64(RAX, (unsigned long long) dst);
325 mov_memoffs64_rax((unsigned long long *) &PC);
326 mov_reg32_imm32(EAX, (unsigned int) src);
327 mov_memoffs32_eax((unsigned int *) &op);
328 mov_reg64_imm64(RAX, (unsigned long long) CoreCompareCallback);
329 call_reg64(RAX);
330
331 mov_reg64_imm64(RAX, (unsigned long long) &debug_reg_storage);
332 mov_reg64_preg64pimm8(RDI, RAX, 56);
333 mov_reg64_preg64pimm8(RSI, RAX, 48);
334 mov_reg64_preg64pimm8(RBP, RAX, 40);
335 mov_reg64_preg64pimm8(RSP, RAX, 32);
336 mov_reg64_preg64pimm8(RDX, RAX, 24);
337 mov_reg64_preg64pimm8(RCX, RAX, 16);
338 mov_reg64_preg64pimm8(RBX, RAX, 8);
339 mov_reg64_preg64(RAX, RAX);
340}
341#endif
342
343void gencallinterp(unsigned long addr, int jump)
344{
345 free_registers_move_start();
346
347 if (jump)
348 mov_m32rel_imm32((unsigned int*)(&dyna_interp), 1);
349
350 mov_reg64_imm64(RAX, (unsigned long long) dst);
351 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
352 mov_reg64_imm64(RAX, addr);
353 call_reg64(RAX);
354
355 if (jump)
356 {
357 mov_m32rel_imm32((unsigned int*)(&dyna_interp), 0);
358 mov_reg64_imm64(RAX, (unsigned long long)dyna_jump);
359 call_reg64(RAX);
360 }
361}
362
363void gendelayslot(void)
364{
365 mov_m32rel_imm32((void*)(&delay_slot), 1);
366 recompile_opcode();
367
368 free_all_registers();
369 genupdate_count(dst->addr+4);
370
371 mov_m32rel_imm32((void*)(&delay_slot), 0);
372}
373
374void genni(void)
375{
376#if defined(COUNT_INSTR)
377 inc_m32rel(&instr_count[1]);
378#endif
379 gencallinterp((unsigned long long)cached_interpreter_table.NI, 0);
380}
381
382void genreserved(void)
383{
384#if defined(COUNT_INSTR)
385 inc_m32rel(&instr_count[0]);
386#endif
387 gencallinterp((unsigned long long)cached_interpreter_table.RESERVED, 0);
388}
389
390void genfin_block(void)
391{
392 gencallinterp((unsigned long long)cached_interpreter_table.FIN_BLOCK, 0);
393}
394
395void gencheck_interupt_reg(void) // addr is in EAX
396{
397 mov_xreg32_m32rel(EBX, (void*)&next_interupt);
398 cmp_xreg32_m32rel(EBX, (void*)&Count);
399 ja_rj(0);
400 jump_start_rel8();
401
402 mov_m32rel_xreg32((unsigned int*)(&fake_instr.addr), EAX);
403 mov_reg64_imm64(RAX, (unsigned long long) (&fake_instr));
404 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
405 mov_reg64_imm64(RAX, (unsigned long long) gen_interupt);
406 call_reg64(RAX);
407
408 jump_end_rel8();
409}
410
411void gennop(void)
412{
413}
414
415void genj(void)
416{
417#if defined(COUNT_INSTR)
418 inc_m32rel(&instr_count[2]);
419#endif
420#ifdef INTERPRET_J
421 gencallinterp((unsigned long long)cached_interpreter_table.J, 1);
422#else
423 unsigned int naddr;
424
425 if (((dst->addr & 0xFFF) == 0xFFC &&
426 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
427 {
428 gencallinterp((unsigned long long)cached_interpreter_table.J, 1);
429 return;
430 }
431
432 gendelayslot();
433 naddr = ((dst-1)->f.j.inst_index<<2) | (dst->addr & 0xF0000000);
434
435 mov_m32rel_imm32((void*)(&last_addr), naddr);
436 gencheck_interupt((unsigned long long) &actual->block[(naddr-actual->start)/4]);
437 jmp(naddr);
438#endif
439}
440
441void genj_out(void)
442{
443#if defined(COUNT_INSTR)
444 inc_m32rel(&instr_count[2]);
445#endif
446#ifdef INTERPRET_J_OUT
447 gencallinterp((unsigned long long)cached_interpreter_table.J_OUT, 1);
448#else
449 unsigned int naddr;
450
451 if (((dst->addr & 0xFFF) == 0xFFC &&
452 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
453 {
454 gencallinterp((unsigned long long)cached_interpreter_table.J_OUT, 1);
455 return;
456 }
457
458 gendelayslot();
459 naddr = ((dst-1)->f.j.inst_index<<2) | (dst->addr & 0xF0000000);
460
461 mov_m32rel_imm32((void*)(&last_addr), naddr);
462 gencheck_interupt_out(naddr);
463 mov_m32rel_imm32(&jump_to_address, naddr);
464 mov_reg64_imm64(RAX, (unsigned long long) (dst+1));
465 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
466 mov_reg64_imm64(RAX, (unsigned long long)jump_to_func);
467 call_reg64(RAX);
468#endif
469}
470
471void genj_idle(void)
472{
473#if defined(COUNT_INSTR)
474 inc_m32rel(&instr_count[2]);
475#endif
476#ifdef INTERPRET_J_IDLE
477 gencallinterp((unsigned long long)cached_interpreter_table.J_IDLE, 1);
478#else
479 if (((dst->addr & 0xFFF) == 0xFFC &&
480 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
481 {
482 gencallinterp((unsigned long long)cached_interpreter_table.J_IDLE, 1);
483 return;
484 }
485
486 mov_xreg32_m32rel(EAX, (unsigned int *)(&next_interupt));
487 sub_xreg32_m32rel(EAX, (unsigned int *)(&Count));
488 cmp_reg32_imm8(EAX, 3);
489 jbe_rj(12);
490
491 and_eax_imm32(0xFFFFFFFC); // 5
492 add_m32rel_xreg32((unsigned int *)(&Count), EAX); // 7
493
494 genj();
495#endif
496}
497
498void genjal(void)
499{
500#if defined(COUNT_INSTR)
501 inc_m32rel(&instr_count[3]);
502#endif
503#ifdef INTERPRET_JAL
504 gencallinterp((unsigned long long)cached_interpreter_table.JAL, 1);
505#else
506 unsigned int naddr;
507
508 if (((dst->addr & 0xFFF) == 0xFFC &&
509 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
510 {
511 gencallinterp((unsigned long long)cached_interpreter_table.JAL, 1);
512 return;
513 }
514
515 gendelayslot();
516
517 mov_m32rel_imm32((unsigned int *)(reg + 31), dst->addr + 4);
518 if (((dst->addr + 4) & 0x80000000))
519 mov_m32rel_imm32((unsigned int *)(&reg[31])+1, 0xFFFFFFFF);
520 else
521 mov_m32rel_imm32((unsigned int *)(&reg[31])+1, 0);
522
523 naddr = ((dst-1)->f.j.inst_index<<2) | (dst->addr & 0xF0000000);
524
525 mov_m32rel_imm32((void*)(&last_addr), naddr);
526 gencheck_interupt((unsigned long long) &actual->block[(naddr-actual->start)/4]);
527 jmp(naddr);
528#endif
529}
530
531void genjal_out(void)
532{
533#if defined(COUNT_INSTR)
534 inc_m32rel(&instr_count[3]);
535#endif
536#ifdef INTERPRET_JAL_OUT
537 gencallinterp((unsigned long long)cached_interpreter_table.JAL_OUT, 1);
538#else
539 unsigned int naddr;
540
541 if (((dst->addr & 0xFFF) == 0xFFC &&
542 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
543 {
544 gencallinterp((unsigned long long)cached_interpreter_table.JAL_OUT, 1);
545 return;
546 }
547
548 gendelayslot();
549
550 mov_m32rel_imm32((unsigned int *)(reg + 31), dst->addr + 4);
551 if (((dst->addr + 4) & 0x80000000))
552 mov_m32rel_imm32((unsigned int *)(&reg[31])+1, 0xFFFFFFFF);
553 else
554 mov_m32rel_imm32((unsigned int *)(&reg[31])+1, 0);
555
556 naddr = ((dst-1)->f.j.inst_index<<2) | (dst->addr & 0xF0000000);
557
558 mov_m32rel_imm32((void*)(&last_addr), naddr);
559 gencheck_interupt_out(naddr);
560 mov_m32rel_imm32(&jump_to_address, naddr);
561 mov_reg64_imm64(RAX, (unsigned long long) (dst+1));
562 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
563 mov_reg64_imm64(RAX, (unsigned long long) jump_to_func);
564 call_reg64(RAX);
565#endif
566}
567
568void genjal_idle(void)
569{
570#if defined(COUNT_INSTR)
571 inc_m32rel(&instr_count[3]);
572#endif
573#ifdef INTERPRET_JAL_IDLE
574 gencallinterp((unsigned long long)cached_interpreter_table.JAL_IDLE, 1);
575#else
576 if (((dst->addr & 0xFFF) == 0xFFC &&
577 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
578 {
579 gencallinterp((unsigned long long)cached_interpreter_table.JAL_IDLE, 1);
580 return;
581 }
582
583 mov_xreg32_m32rel(EAX, (unsigned int *)(&next_interupt));
584 sub_xreg32_m32rel(EAX, (unsigned int *)(&Count));
585 cmp_reg32_imm8(EAX, 3);
586 jbe_rj(12);
587
588 and_eax_imm32(0xFFFFFFFC); // 5
589 add_m32rel_xreg32((unsigned int *)(&Count), EAX); // 7
590
591 genjal();
592#endif
593}
594
595void gentest(void)
596{
597 cmp_m32rel_imm32((unsigned int *)(&branch_taken), 0);
598 je_near_rj(0);
599 jump_start_rel32();
600
601 mov_m32rel_imm32((void*)(&last_addr), dst->addr + (dst-1)->f.i.immediate*4);
602 gencheck_interupt((unsigned long long) (dst + (dst-1)->f.i.immediate));
603 jmp(dst->addr + (dst-1)->f.i.immediate*4);
604
605 jump_end_rel32();
606
607 mov_m32rel_imm32((void*)(&last_addr), dst->addr + 4);
608 gencheck_interupt((unsigned long long)(dst + 1));
609 jmp(dst->addr + 4);
610}
611
612void genbeq(void)
613{
614#if defined(COUNT_INSTR)
615 inc_m32rel(&instr_count[4]);
616#endif
617#ifdef INTERPRET_BEQ
618 gencallinterp((unsigned long long)cached_interpreter_table.BEQ, 1);
619#else
620 if (((dst->addr & 0xFFF) == 0xFFC &&
621 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
622 {
623 gencallinterp((unsigned long long)cached_interpreter_table.BEQ, 1);
624 return;
625 }
626
627 genbeq_test();
628 gendelayslot();
629 gentest();
630#endif
631}
632
633void gentest_out(void)
634{
635 cmp_m32rel_imm32((unsigned int *)(&branch_taken), 0);
636 je_near_rj(0);
637 jump_start_rel32();
638
639 mov_m32rel_imm32((void*)(&last_addr), dst->addr + (dst-1)->f.i.immediate*4);
640 gencheck_interupt_out(dst->addr + (dst-1)->f.i.immediate*4);
641 mov_m32rel_imm32(&jump_to_address, dst->addr + (dst-1)->f.i.immediate*4);
642 mov_reg64_imm64(RAX, (unsigned long long) (dst+1));
643 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
644 mov_reg64_imm64(RAX, (unsigned long long) jump_to_func);
645 call_reg64(RAX);
646 jump_end_rel32();
647
648 mov_m32rel_imm32((void*)(&last_addr), dst->addr + 4);
649 gencheck_interupt((unsigned long long) (dst + 1));
650 jmp(dst->addr + 4);
651}
652
653void genbeq_out(void)
654{
655#if defined(COUNT_INSTR)
656 inc_m32rel(&instr_count[4]);
657#endif
658#ifdef INTERPRET_BEQ_OUT
659 gencallinterp((unsigned long long)cached_interpreter_table.BEQ_OUT, 1);
660#else
661 if (((dst->addr & 0xFFF) == 0xFFC &&
662 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
663 {
664 gencallinterp((unsigned long long)cached_interpreter_table.BEQ_OUT, 1);
665 return;
666 }
667
668 genbeq_test();
669 gendelayslot();
670 gentest_out();
671#endif
672}
673
674void gentest_idle(void)
675{
676 int reg;
677
678 reg = lru_register();
679 free_register(reg);
680
681 cmp_m32rel_imm32((unsigned int *)(&branch_taken), 0);
682 je_near_rj(0);
683 jump_start_rel32();
684
685 mov_xreg32_m32rel(reg, (unsigned int *)(&next_interupt));
686 sub_xreg32_m32rel(reg, (unsigned int *)(&Count));
687 cmp_reg32_imm8(reg, 3);
688 jbe_rj(0);
689 jump_start_rel8();
690
691 and_reg32_imm32(reg, 0xFFFFFFFC);
692 add_m32rel_xreg32((unsigned int *)(&Count), reg);
693
694 jump_end_rel8();
695 jump_end_rel32();
696}
697
698void genbeq_idle(void)
699{
700#ifdef INTERPRET_BEQ_IDLE
701 gencallinterp((unsigned long long)cached_interpreter_table.BEQ_IDLE, 1);
702#else
703 if (((dst->addr & 0xFFF) == 0xFFC &&
704 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
705 {
706 gencallinterp((unsigned long long)cached_interpreter_table.BEQ_IDLE, 1);
707 return;
708 }
709
710 genbeq_test();
711 gentest_idle();
712 genbeq();
713#endif
714}
715
716void genbne(void)
717{
718#if defined(COUNT_INSTR)
719 inc_m32rel(&instr_count[5]);
720#endif
721#ifdef INTERPRET_BNE
722 gencallinterp((unsigned long long)cached_interpreter_table.BNE, 1);
723#else
724 if (((dst->addr & 0xFFF) == 0xFFC &&
725 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
726 {
727 gencallinterp((unsigned long long)cached_interpreter_table.BNE, 1);
728 return;
729 }
730
731 genbne_test();
732 gendelayslot();
733 gentest();
734#endif
735}
736
737void genbne_out(void)
738{
739#if defined(COUNT_INSTR)
740 inc_m32rel(&instr_count[5]);
741#endif
742#ifdef INTERPRET_BNE_OUT
743 gencallinterp((unsigned long long)cached_interpreter_table.BNE_OUT, 1);
744#else
745 if (((dst->addr & 0xFFF) == 0xFFC &&
746 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
747 {
748 gencallinterp((unsigned long long)cached_interpreter_table.BNE_OUT, 1);
749 return;
750 }
751
752 genbne_test();
753 gendelayslot();
754 gentest_out();
755#endif
756}
757
758void genbne_idle(void)
759{
760#ifdef INTERPRET_BNE_IDLE
761 gencallinterp((unsigned long long)cached_interpreter_table.BNE_IDLE, 1);
762#else
763 if (((dst->addr & 0xFFF) == 0xFFC &&
764 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
765 {
766 gencallinterp((unsigned long long)cached_interpreter_table.BNE_IDLE, 1);
767 return;
768 }
769
770 genbne_test();
771 gentest_idle();
772 genbne();
773#endif
774}
775
776void genblez(void)
777{
778#if defined(COUNT_INSTR)
779 inc_m32rel(&instr_count[6]);
780#endif
781#ifdef INTERPRET_BLEZ
782 gencallinterp((unsigned long long)cached_interpreter_table.BLEZ, 1);
783#else
784 if (((dst->addr & 0xFFF) == 0xFFC &&
785 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
786 {
787 gencallinterp((unsigned long long)cached_interpreter_table.BLEZ, 1);
788 return;
789 }
790
791 genblez_test();
792 gendelayslot();
793 gentest();
794#endif
795}
796
797void genblez_out(void)
798{
799#if defined(COUNT_INSTR)
800 inc_m32rel(&instr_count[6]);
801#endif
802#ifdef INTERPRET_BLEZ_OUT
803 gencallinterp((unsigned long long)cached_interpreter_table.BLEZ_OUT, 1);
804#else
805 if (((dst->addr & 0xFFF) == 0xFFC &&
806 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
807 {
808 gencallinterp((unsigned long long)cached_interpreter_table.BLEZ_OUT, 1);
809 return;
810 }
811
812 genblez_test();
813 gendelayslot();
814 gentest_out();
815#endif
816}
817
818void genblez_idle(void)
819{
820#ifdef INTERPRET_BLEZ_IDLE
821 gencallinterp((unsigned long long)cached_interpreter_table.BLEZ_IDLE, 1);
822#else
823 if (((dst->addr & 0xFFF) == 0xFFC &&
824 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
825 {
826 gencallinterp((unsigned long long)cached_interpreter_table.BLEZ_IDLE, 1);
827 return;
828 }
829
830 genblez_test();
831 gentest_idle();
832 genblez();
833#endif
834}
835
836void genbgtz(void)
837{
838#if defined(COUNT_INSTR)
839 inc_m32rel(&instr_count[7]);
840#endif
841#ifdef INTERPRET_BGTZ
842 gencallinterp((unsigned long long)cached_interpreter_table.BGTZ, 1);
843#else
844 if (((dst->addr & 0xFFF) == 0xFFC &&
845 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
846 {
847 gencallinterp((unsigned long long)cached_interpreter_table.BGTZ, 1);
848 return;
849 }
850
851 genbgtz_test();
852 gendelayslot();
853 gentest();
854#endif
855}
856
857void genbgtz_out(void)
858{
859#if defined(COUNT_INSTR)
860 inc_m32rel(&instr_count[7]);
861#endif
862#ifdef INTERPRET_BGTZ_OUT
863 gencallinterp((unsigned long long)cached_interpreter_table.BGTZ_OUT, 1);
864#else
865 if (((dst->addr & 0xFFF) == 0xFFC &&
866 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
867 {
868 gencallinterp((unsigned long long)cached_interpreter_table.BGTZ_OUT, 1);
869 return;
870 }
871
872 genbgtz_test();
873 gendelayslot();
874 gentest_out();
875#endif
876}
877
878void genbgtz_idle(void)
879{
880#ifdef INTERPRET_BGTZ_IDLE
881 gencallinterp((unsigned long long)cached_interpreter_table.BGTZ_IDLE, 1);
882#else
883 if (((dst->addr & 0xFFF) == 0xFFC &&
884 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
885 {
886 gencallinterp((unsigned long long)cached_interpreter_table.BGTZ_IDLE, 1);
887 return;
888 }
889
890 genbgtz_test();
891 gentest_idle();
892 genbgtz();
893#endif
894}
895
896void genaddi(void)
897{
898#if defined(COUNT_INSTR)
899 inc_m32rel(&instr_count[8]);
900#endif
901#ifdef INTERPRET_ADDI
902 gencallinterp((unsigned long long)cached_interpreter_table.ADDI, 0);
903#else
904 int rs = allocate_register_32((unsigned int *)dst->f.i.rs);
905 int rt = allocate_register_32_w((unsigned int *)dst->f.i.rt);
906
907 mov_reg32_reg32(rt, rs);
908 add_reg32_imm32(rt,(int)dst->f.i.immediate);
909#endif
910}
911
912void genaddiu(void)
913{
914#if defined(COUNT_INSTR)
915 inc_m32rel(&instr_count[9]);
916#endif
917#ifdef INTERPRET_ADDIU
918 gencallinterp((unsigned long long)cached_interpreter_table.ADDIU, 0);
919#else
920 int rs = allocate_register_32((unsigned int *)dst->f.i.rs);
921 int rt = allocate_register_32_w((unsigned int *)dst->f.i.rt);
922
923 mov_reg32_reg32(rt, rs);
924 add_reg32_imm32(rt,(int)dst->f.i.immediate);
925#endif
926}
927
928void genslti(void)
929{
930#if defined(COUNT_INSTR)
931 inc_m32rel(&instr_count[10]);
932#endif
933#ifdef INTERPRET_SLTI
934 gencallinterp((unsigned long long)cached_interpreter_table.SLTI, 0);
935#else
936 int rs = allocate_register_64((unsigned long long *) dst->f.i.rs);
937 int rt = allocate_register_64_w((unsigned long long *) dst->f.i.rt);
938 int imm = (int) dst->f.i.immediate;
939
940 cmp_reg64_imm32(rs, imm);
941 setl_reg8(rt);
942 and_reg64_imm8(rt, 1);
943#endif
944}
945
946void gensltiu(void)
947{
948#if defined(COUNT_INSTR)
949 inc_m32rel(&instr_count[11]);
950#endif
951#ifdef INTERPRET_SLTIU
952 gencallinterp((unsigned long long)cached_interpreter_table.SLTIU, 0);
953#else
954 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
955 int rt = allocate_register_64_w((unsigned long long *)dst->f.i.rt);
956 int imm = (int) dst->f.i.immediate;
957
958 cmp_reg64_imm32(rs, imm);
959 setb_reg8(rt);
960 and_reg64_imm8(rt, 1);
961#endif
962}
963
964void genandi(void)
965{
966#if defined(COUNT_INSTR)
967 inc_m32rel(&instr_count[12]);
968#endif
969#ifdef INTERPRET_ANDI
970 gencallinterp((unsigned long long)cached_interpreter_table.ANDI, 0);
971#else
972 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
973 int rt = allocate_register_64_w((unsigned long long *)dst->f.i.rt);
974
975 mov_reg64_reg64(rt, rs);
976 and_reg64_imm32(rt, (unsigned short)dst->f.i.immediate);
977#endif
978}
979
980void genori(void)
981{
982#if defined(COUNT_INSTR)
983 inc_m32rel(&instr_count[13]);
984#endif
985#ifdef INTERPRET_ORI
986 gencallinterp((unsigned long long)cached_interpreter_table.ORI, 0);
987#else
988 int rs = allocate_register_64((unsigned long long *) dst->f.i.rs);
989 int rt = allocate_register_64_w((unsigned long long *) dst->f.i.rt);
990
991 mov_reg64_reg64(rt, rs);
992 or_reg64_imm32(rt, (unsigned short)dst->f.i.immediate);
993#endif
994}
995
996void genxori(void)
997{
998#if defined(COUNT_INSTR)
999 inc_m32rel(&instr_count[14]);
1000#endif
1001#ifdef INTERPRET_XORI
1002 gencallinterp((unsigned long long)cached_interpreter_table.XORI, 0);
1003#else
1004 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
1005 int rt = allocate_register_64_w((unsigned long long *)dst->f.i.rt);
1006
1007 mov_reg64_reg64(rt, rs);
1008 xor_reg64_imm32(rt, (unsigned short)dst->f.i.immediate);
1009#endif
1010}
1011
1012void genlui(void)
1013{
1014#if defined(COUNT_INSTR)
1015 inc_m32rel(&instr_count[15]);
1016#endif
1017#ifdef INTERPRET_LUI
1018 gencallinterp((unsigned long long)cached_interpreter_table.LUI, 0);
1019#else
1020 int rt = allocate_register_32_w((unsigned int *)dst->f.i.rt);
1021
1022 mov_reg32_imm32(rt, (unsigned int)dst->f.i.immediate << 16);
1023#endif
1024}
1025
1026void gentestl(void)
1027{
1028 cmp_m32rel_imm32((unsigned int *)(&branch_taken), 0);
1029 je_near_rj(0);
1030 jump_start_rel32();
1031
1032 gendelayslot();
1033 mov_m32rel_imm32((void*)(&last_addr), dst->addr + (dst-1)->f.i.immediate*4);
1034 gencheck_interupt((unsigned long long) (dst + (dst-1)->f.i.immediate));
1035 jmp(dst->addr + (dst-1)->f.i.immediate*4);
1036
1037 jump_end_rel32();
1038
1039 genupdate_count(dst->addr-4);
1040 mov_m32rel_imm32((void*)(&last_addr), dst->addr + 4);
1041 gencheck_interupt((unsigned long long) (dst + 1));
1042 jmp(dst->addr + 4);
1043}
1044
1045void genbeql(void)
1046{
1047#if defined(COUNT_INSTR)
1048 inc_m32rel(&instr_count[16]);
1049#endif
1050#ifdef INTERPRET_BEQL
1051 gencallinterp((unsigned long long)cached_interpreter_table.BEQL, 1);
1052#else
1053 if (((dst->addr & 0xFFF) == 0xFFC &&
1054 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1055 {
1056 gencallinterp((unsigned long long)cached_interpreter_table.BEQL, 1);
1057 return;
1058 }
1059
1060 genbeq_test();
1061 free_all_registers();
1062 gentestl();
1063#endif
1064}
1065
1066void gentestl_out(void)
1067{
1068 cmp_m32rel_imm32((unsigned int *)(&branch_taken), 0);
1069 je_near_rj(0);
1070 jump_start_rel32();
1071
1072 gendelayslot();
1073 mov_m32rel_imm32((void*)(&last_addr), dst->addr + (dst-1)->f.i.immediate*4);
1074 gencheck_interupt_out(dst->addr + (dst-1)->f.i.immediate*4);
1075 mov_m32rel_imm32(&jump_to_address, dst->addr + (dst-1)->f.i.immediate*4);
1076
1077 mov_reg64_imm64(RAX, (unsigned long long) (dst+1));
1078 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX);
1079 mov_reg64_imm64(RAX, (unsigned long long) jump_to_func);
1080 call_reg64(RAX);
1081
1082 jump_end_rel32();
1083
1084 genupdate_count(dst->addr-4);
1085 mov_m32rel_imm32((void*)(&last_addr), dst->addr + 4);
1086 gencheck_interupt((unsigned long long) (dst + 1));
1087 jmp(dst->addr + 4);
1088}
1089
1090void genbeql_out(void)
1091{
1092#if defined(COUNT_INSTR)
1093 inc_m32rel(&instr_count[16]);
1094#endif
1095#ifdef INTERPRET_BEQL_OUT
1096 gencallinterp((unsigned long long)cached_interpreter_table.BEQL_OUT, 1);
1097#else
1098 if (((dst->addr & 0xFFF) == 0xFFC &&
1099 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1100 {
1101 gencallinterp((unsigned long long)cached_interpreter_table.BEQL_OUT, 1);
1102 return;
1103 }
1104
1105 genbeq_test();
1106 free_all_registers();
1107 gentestl_out();
1108#endif
1109}
1110
1111void genbeql_idle(void)
1112{
1113#ifdef INTERPRET_BEQL_IDLE
1114 gencallinterp((unsigned long long)cached_interpreter_table.BEQL_IDLE, 1);
1115#else
1116 if (((dst->addr & 0xFFF) == 0xFFC &&
1117 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1118 {
1119 gencallinterp((unsigned long long)cached_interpreter_table.BEQL_IDLE, 1);
1120 return;
1121 }
1122
1123 genbeq_test();
1124 gentest_idle();
1125 genbeql();
1126#endif
1127}
1128
1129void genbnel(void)
1130{
1131#if defined(COUNT_INSTR)
1132 inc_m32rel(&instr_count[17]);
1133#endif
1134#ifdef INTERPRET_BNEL
1135 gencallinterp((unsigned long long)cached_interpreter_table.BNEL, 1);
1136#else
1137 if (((dst->addr & 0xFFF) == 0xFFC &&
1138 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1139 {
1140 gencallinterp((unsigned long long)cached_interpreter_table.BNEL, 1);
1141 return;
1142 }
1143
1144 genbne_test();
1145 free_all_registers();
1146 gentestl();
1147#endif
1148}
1149
1150void genbnel_out(void)
1151{
1152#if defined(COUNT_INSTR)
1153 inc_m32rel(&instr_count[17]);
1154#endif
1155#ifdef INTERPRET_BNEL_OUT
1156 gencallinterp((unsigned long long)cached_interpreter_table.BNEL_OUT, 1);
1157#else
1158 if (((dst->addr & 0xFFF) == 0xFFC &&
1159 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1160 {
1161 gencallinterp((unsigned long long)cached_interpreter_table.BNEL_OUT, 1);
1162 return;
1163 }
1164
1165 genbne_test();
1166 free_all_registers();
1167 gentestl_out();
1168#endif
1169}
1170
1171void genbnel_idle(void)
1172{
1173#ifdef INTERPRET_BNEL_IDLE
1174 gencallinterp((unsigned long long)cached_interpreter_table.BNEL_IDLE, 1);
1175#else
1176 if (((dst->addr & 0xFFF) == 0xFFC &&
1177 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1178 {
1179 gencallinterp((unsigned long long)cached_interpreter_table.BNEL_IDLE, 1);
1180 return;
1181 }
1182
1183 genbne_test();
1184 gentest_idle();
1185 genbnel();
1186#endif
1187}
1188
1189void genblezl(void)
1190{
1191#if defined(COUNT_INSTR)
1192 inc_m32rel(&instr_count[18]);
1193#endif
1194#ifdef INTERPRET_BLEZL
1195 gencallinterp((unsigned long long)cached_interpreter_table.BLEZL, 1);
1196#else
1197 if (((dst->addr & 0xFFF) == 0xFFC &&
1198 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1199 {
1200 gencallinterp((unsigned long long)cached_interpreter_table.BLEZL, 1);
1201 return;
1202 }
1203
1204 genblez_test();
1205 free_all_registers();
1206 gentestl();
1207#endif
1208}
1209
1210void genblezl_out(void)
1211{
1212#if defined(COUNT_INSTR)
1213 inc_m32rel(&instr_count[18]);
1214#endif
1215#ifdef INTERPRET_BLEZL_OUT
1216 gencallinterp((unsigned long long)cached_interpreter_table.BLEZL_OUT, 1);
1217#else
1218 if (((dst->addr & 0xFFF) == 0xFFC &&
1219 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1220 {
1221 gencallinterp((unsigned long long)cached_interpreter_table.BLEZL_OUT, 1);
1222 return;
1223 }
1224
1225 genblez_test();
1226 free_all_registers();
1227 gentestl_out();
1228#endif
1229}
1230
1231void genblezl_idle(void)
1232{
1233#ifdef INTERPRET_BLEZL_IDLE
1234 gencallinterp((unsigned long long)cached_interpreter_table.BLEZL_IDLE, 1);
1235#else
1236 if (((dst->addr & 0xFFF) == 0xFFC &&
1237 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1238 {
1239 gencallinterp((unsigned long long)cached_interpreter_table.BLEZL_IDLE, 1);
1240 return;
1241 }
1242
1243 genblez_test();
1244 gentest_idle();
1245 genblezl();
1246#endif
1247}
1248
1249void genbgtzl(void)
1250{
1251#if defined(COUNT_INSTR)
1252 inc_m32rel(&instr_count[19]);
1253#endif
1254#ifdef INTERPRET_BGTZL
1255 gencallinterp((unsigned long long)cached_interpreter_table.BGTZL, 1);
1256#else
1257 if (((dst->addr & 0xFFF) == 0xFFC &&
1258 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1259 {
1260 gencallinterp((unsigned long long)cached_interpreter_table.BGTZL, 1);
1261 return;
1262 }
1263
1264 genbgtz_test();
1265 free_all_registers();
1266 gentestl();
1267#endif
1268}
1269
1270void genbgtzl_out(void)
1271{
1272#if defined(COUNT_INSTR)
1273 inc_m32rel(&instr_count[19]);
1274#endif
1275#ifdef INTERPRET_BGTZL_OUT
1276 gencallinterp((unsigned long long)cached_interpreter_table.BGTZL_OUT, 1);
1277#else
1278 if (((dst->addr & 0xFFF) == 0xFFC &&
1279 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1280 {
1281 gencallinterp((unsigned long long)cached_interpreter_table.BGTZL_OUT, 1);
1282 return;
1283 }
1284
1285 genbgtz_test();
1286 free_all_registers();
1287 gentestl_out();
1288#endif
1289}
1290
1291void genbgtzl_idle(void)
1292{
1293#ifdef INTERPRET_BGTZL_IDLE
1294 gencallinterp((unsigned long long)cached_interpreter_table.BGTZL_IDLE, 1);
1295#else
1296 if (((dst->addr & 0xFFF) == 0xFFC &&
1297 (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump)
1298 {
1299 gencallinterp((unsigned long long)cached_interpreter_table.BGTZL_IDLE, 1);
1300 return;
1301 }
1302
1303 genbgtz_test();
1304 gentest_idle();
1305 genbgtzl();
1306#endif
1307}
1308
1309void gendaddi(void)
1310{
1311#if defined(COUNT_INSTR)
1312 inc_m32rel(&instr_count[20]);
1313#endif
1314#ifdef INTERPRET_DADDI
1315 gencallinterp((unsigned long long)cached_interpreter_table.DADDI, 0);
1316#else
1317 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
1318 int rt = allocate_register_64_w((unsigned long long *)dst->f.i.rt);
1319
1320 mov_reg64_reg64(rt, rs);
1321 add_reg64_imm32(rt, (int) dst->f.i.immediate);
1322#endif
1323}
1324
1325void gendaddiu(void)
1326{
1327#ifdef INTERPRET_DADDIU
1328 gencallinterp((unsigned long long)cached_interpreter_table.DADDIU, 0);
1329#else
1330 int rs = allocate_register_64((unsigned long long *)dst->f.i.rs);
1331 int rt = allocate_register_64_w((unsigned long long *)dst->f.i.rt);
1332
1333 mov_reg64_reg64(rt, rs);
1334 add_reg64_imm32(rt, (int) dst->f.i.immediate);
1335#endif
1336}
1337
1338void genldl(void)
1339{
1340#if defined(COUNT_INSTR)
1341 inc_m32rel(&instr_count[22]);
1342#endif
1343 gencallinterp((unsigned long long)cached_interpreter_table.LDL, 0);
1344}
1345
1346void genldr(void)
1347{
1348#if defined(COUNT_INSTR)
1349 inc_m32rel(&instr_count[23]);
1350#endif
1351 gencallinterp((unsigned long long)cached_interpreter_table.LDR, 0);
1352}
1353
1354void genlb(void)
1355{
1356 int gpr1, gpr2, base1, base2 = 0;
1357#if defined(COUNT_INSTR)
1358 inc_m32rel(&instr_count[24]);
1359#endif
1360#ifdef INTERPRET_LB
1361 gencallinterp((unsigned long long)cached_interpreter_table.LB, 0);
1362#else
1363 free_registers_move_start();
1364
1365 ld_register_alloc(&gpr1, &gpr2, &base1, &base2);
1366
1367 mov_reg64_imm64(base1, (unsigned long long) readmemb);
1368 if(fast_memory)
1369 {
1370 and_reg32_imm32(gpr1, 0xDF800000);
1371 cmp_reg32_imm32(gpr1, 0x80000000);
1372 }
1373 else
1374 {
1375 mov_reg64_imm64(base2, (unsigned long long) read_rdramb);
1376 shr_reg32_imm8(gpr1, 16);
1377 mov_reg64_preg64x8preg64(gpr1, gpr1, base1);
1378 cmp_reg64_reg64(gpr1, base2);
1379 }
1380 je_rj(0);
1381 jump_start_rel8();
1382
1383 mov_reg64_imm64(gpr1, (unsigned long long) (dst+1));
1384 mov_m64rel_xreg64((unsigned long long *)(&PC), gpr1);
1385 mov_m32rel_xreg32((unsigned int *)(&address), gpr2);
1386 mov_reg64_imm64(gpr1, (unsigned long long) dst->f.i.rt);
1387 mov_m64rel_xreg64((unsigned long long *)(&rdword), gpr1);
1388 shr_reg32_imm8(gpr2, 16);
1389 mov_reg64_preg64x8preg64(gpr2, gpr2, base1);
1390 call_reg64(gpr2);
1391 movsx_xreg32_m8rel(gpr1, (unsigned char *)dst->f.i.rt);
1392 jmp_imm_short(24);
1393
1394 jump_end_rel8();
1395 mov_reg64_imm64(base1, (unsigned long long) rdram); // 10
1396 and_reg32_imm32(gpr2, 0x7FFFFF); // 6
1397 xor_reg8_imm8(gpr2, 3); // 4
1398 movsx_reg32_8preg64preg64(gpr1, gpr2, base1); // 4
1399
1400 set_register_state(gpr1, (unsigned int*)dst->f.i.rt, 1, 0);
1401#endif
1402}
1403
1404void genlh(void)
1405{
1406 int gpr1, gpr2, base1, base2 = 0;
1407#if defined(COUNT_INSTR)
1408 inc_m32rel(&instr_count[25]);
1409#endif
1410#ifdef INTERPRET_LH
1411 gencallinterp((unsigned long long)cached_interpreter_table.LH, 0);
1412#else
1413 free_registers_move_start();
1414
1415 ld_register_alloc(&gpr1, &gpr2, &base1, &base2);
1416
1417 mov_reg64_imm64(base1, (unsigned long long) readmemh);
1418 if(fast_memory)
1419 {
1420 and_reg32_imm32(gpr1, 0xDF800000);
1421 cmp_reg32_imm32(gpr1, 0x80000000);
1422 }
1423 else
1424 {
1425 mov_reg64_imm64(base2, (unsigned long long) read_rdramh);
1426 shr_reg32_imm8(gpr1, 16);
1427 mov_reg64_preg64x8preg64(gpr1, gpr1, base1);
1428 cmp_reg64_reg64(gpr1, base2);
1429 }
1430 je_rj(0);
1431 jump_start_rel8();
1432
1433 mov_reg64_imm64(gpr1, (unsigned long long) (dst+1));
1434 mov_m64rel_xreg64((unsigned long long *)(&PC), gpr1);
1435 mov_m32rel_xreg32((unsigned int *)(&address), gpr2);
1436 mov_reg64_imm64(gpr1, (unsigned long long) dst->f.i.rt);
1437 mov_m64rel_xreg64((unsigned long long *)(&rdword), gpr1);
1438 shr_reg32_imm8(gpr2, 16);
1439 mov_reg64_preg64x8preg64(gpr2, gpr2, base1);
1440 call_reg64(gpr2);
1441 movsx_xreg32_m16rel(gpr1, (unsigned short *)dst->f.i.rt);
1442 jmp_imm_short(24);
1443
1444 jump_end_rel8();
1445 mov_reg64_imm64(base1, (unsigned long long) rdram); // 10
1446 and_reg32_imm32(gpr2, 0x7FFFFF); // 6
1447 xor_reg8_imm8(gpr2, 2); // 4
1448 movsx_reg32_16preg64preg64(gpr1, gpr2, base1); // 4
1449
1450 set_register_state(gpr1, (unsigned int*)dst->f.i.rt, 1, 0);
1451#endif
1452}
1453
1454void genlwl(void)
1455{
1456#if defined(COUNT_INSTR)
1457 inc_m32rel(&instr_count[27]);
1458#endif
1459 gencallinterp((unsigned long long)cached_interpreter_table.LWL, 0);
1460}
1461
1462void genlw(void)
1463{
1464 int gpr1, gpr2, base1, base2 = 0;
1465#if defined(COUNT_INSTR)
1466 inc_m32rel(&instr_count[26]);
1467#endif
1468#ifdef INTERPRET_LW
1469 gencallinterp((unsigned long long)cached_interpreter_table.LW, 0);
1470#else
1471 free_registers_move_start();
1472
1473 ld_register_alloc(&gpr1, &gpr2, &base1, &base2);
1474
1475 mov_reg64_imm64(base1, (unsigned long long) readmem);
1476 if(fast_memory)
1477 {
1478 and_reg32_imm32(gpr1, 0xDF800000);
1479 cmp_reg32_imm32(gpr1, 0x80000000);
1480 }
1481 else
1482 {
1483 mov_reg64_imm64(base2, (unsigned long long) read_rdram);
1484 shr_reg32_imm8(gpr1, 16);
1485 mov_reg64_preg64x8preg64(gpr1, gpr1, base1);
1486 cmp_reg64_reg64(gpr1, base2);
1487 }
1488 jne_rj(21);
1489
1490 mov_reg64_imm64(base1, (unsigned long long) rdram); // 10
1491 and_reg32_imm32(gpr2, 0x7FFFFF); // 6
1492 mov_reg32_preg64preg64(gpr1, gpr2, base1); // 3
1493 jmp_imm_short(0); // 2
1494 jump_start_rel8();
1495
1496 mov_reg64_imm64(gpr1, (unsigned long long) (dst+1));
1497 mov_m64rel_xreg64((unsigned long long *)(&PC), gpr1);
1498 mov_m32rel_xreg32((unsigned int *)(&address), gpr2);
1499 mov_reg64_imm64(gpr1, (unsigned long long) dst->f.i.rt);
1500 mov_m64rel_xreg64((unsigned long long *)(&rdword), gpr1);
1501 shr_reg32_imm8(gpr2, 16);
1502 mov_reg64_preg64x8preg64(gpr1, gpr2, base1);
1503 call_reg64(gpr1);
1504 mov_xreg32_m32rel(gpr1, (unsigned int *)(dst->f.i.rt));
1505
1506 jump_end_rel8();
1507
1508 set_register_state(gpr1, (unsigned int*)dst->f.i.rt, 1, 0); // set gpr1 state as dirty, and bound to r4300 reg RT
1509#endif
1510}
1511
1512void genlbu(void)
1513{
1514 int gpr1, gpr2, base1, base2 = 0;
1515#if defined(COUNT_INSTR)
1516 inc_m32rel(&instr_count[28]);
1517#endif
1518#ifdef INTERPRET_LBU
1519 gencallinterp((unsigned long long)cached_interpreter_table.LBU, 0);
1520#else
1521 free_registers_move_start();
1522
1523 ld_register_alloc(&gpr1, &gpr2, &base1, &base2);
1524
1525 mov_reg64_imm64(base1, (unsigned long long) readmemb);
1526 if(fast_memory)
1527 {
1528 and_reg32_imm32(gpr1, 0xDF800000);
1529 cmp_reg32_imm32(gpr1, 0x80000000);
1530 }
1531 else
1532 {
1533 mov_reg64_imm64(base2, (unsigned long long) read_rdramb);
1534 shr_reg32_imm8(gpr1, 16);
1535 mov_reg64_preg64x8preg64(gpr1, gpr1, base1);
1536 cmp_reg64_reg64(gpr1, base2);
1537 }
1538 je_rj(0);
1539 jump_start_rel8();
1540
1541 mov_reg64_imm64(gpr1, (unsigned long long) (dst+1));
1542 mov_m64rel_xreg64((unsigned long long *)(&PC), gpr1);
1543 mov_m32rel_xreg32((unsigned int *)(&address), gpr2);
1544 mov_reg64_imm64(gpr1, (unsigned long long) dst->f.i.rt);
1545 mov_m64rel_xreg64((unsigned long long *)(&rdword), gpr1);
1546 shr_reg32_imm8(gpr2, 16);
1547 mov_reg64_preg64x8preg64(gpr2, gpr2, base1);
1548 call_reg64(gpr2);
1549 mov_xreg32_m32rel(gpr1, (unsigned int *)dst->f.i.rt);
1550 jmp_imm_short(23);
1551
1552 jump_end_rel8();
1553 mov_reg64_imm64(base1, (unsigned long long) rdram); // 10
1554 and_reg32_imm32(gpr2, 0x7FFFFF); // 6
1555 xor_reg8_imm8(gpr2, 3); // 4
1556 mov_reg32_preg64preg64(gpr1, gpr2, base1); // 3
1557
1558 and_reg32_imm32(gpr1, 0xFF);
1559 set_register_state(gpr1, (unsigned int*)dst->f.i.rt, 1, 0);
1560#endif
1561}
1562
1563void genlhu(void)
1564{
1565 int gpr1, gpr2, base1, base2 = 0;
1566#if defined(COUNT_INSTR)
1567 inc_m32rel(&instr_count[29]);
1568#endif
1569#ifdef INTERPRET_LHU
1570 gencallinterp((unsigned long long)cached_interpreter_table.LHU, 0);
1571#else
1572 free_registers_move_start();
1573
1574 ld_register_alloc(&gpr1, &gpr2, &base1, &base2);
1575
1576 mov_reg64_imm64(base1, (unsigned long long) readmemh);
1577 if(fast_memory)
1578 {
1579 and_reg32_imm32(gpr1, 0xDF800000);
1580 cmp_reg32_imm32(gpr1, 0x80000000);
1581 }
1582 else
1583 {
1584 mov_reg64_imm64(base2, (unsigned long long) read_rdramh);
1585 shr_reg32_imm8(gpr1, 16);
1586 mov_reg64_preg64x8preg64(gpr1, gpr1, base1);
1587 cmp_reg64_reg64(gpr1, base2);
1588 }
1589 je_rj(0);
1590 jump_start_rel8();
1591
1592 mov_reg64_imm64(gpr1, (unsigned long long) (dst+1));
1593 mov_m64rel_xreg64((unsigned long long *)(&PC), gpr1);
1594 mov_m32rel_xreg32((unsigned int *)(&address), gpr2);
1595 mov_reg64_imm64(gpr1, (unsigned long long) dst->f.i.rt);
1596 mov_m64rel_xreg64((unsigned long long *)(&rdword), gpr1);
1597 shr_reg32_imm8(gpr2, 16);
1598 mov_reg64_preg64x8preg64(gpr2, gpr2, base1);
1599 call_reg64(gpr2);
1600 mov_xreg32_m32rel(gpr1, (unsigned int *)dst->f.i.rt);
1601 jmp_imm_short(23);
1602
1603 jump_end_rel8();
1604 mov_reg64_imm64(base1, (unsigned long long) rdram); // 10
1605 and_reg32_imm32(gpr2, 0x7FFFFF); // 6
1606 xor_reg8_imm8(gpr2, 2); // 4
1607 mov_reg32_preg64preg64(gpr1, gpr2, base1); // 3
1608
1609 and_reg32_imm32(gpr1, 0xFFFF);
1610 set_register_state(gpr1, (unsigned int*)dst->f.i.rt, 1, 0);
1611#endif
1612}
1613
1614void genlwr(void)
1615{
1616#if defined(COUNT_INSTR)
1617 inc_m32rel(&instr_count[31]);
1618#endif
1619 gencallinterp((unsigned long long)cached_interpreter_table.LWR, 0);
1620}
1621
1622void genlwu(void)
1623{
1624 int gpr1, gpr2, base1, base2 = 0;
1625#if defined(COUNT_INSTR)
1626 inc_m32rel(&instr_count[30]);
1627#endif
1628#ifdef INTERPRET_LWU
1629 gencallinterp((unsigned long long)cached_interpreter_table.LWU, 0);
1630#else
1631 free_registers_move_start();
1632
1633 ld_register_alloc(&gpr1, &gpr2, &base1, &base2);
1634
1635 mov_reg64_imm64(base1, (unsigned long long) readmem);
1636 if(fast_memory)
1637 {
1638 and_reg32_imm32(gpr1, 0xDF800000);
1639 cmp_reg32_imm32(gpr1, 0x80000000);
1640 }
1641 else
1642 {
1643 mov_reg64_imm64(base2, (unsigned long long) read_rdram);
1644 shr_reg32_imm8(gpr1, 16);
1645 mov_reg64_preg64x8preg64(gpr1, gpr1, base1);
1646 cmp_reg64_reg64(gpr1, base2);
1647 }
1648 je_rj(0);
1649 jump_start_rel8();
1650
1651 mov_reg64_imm64(gpr1, (unsigned long long) (dst+1));
1652 mov_m64rel_xreg64((unsigned long long *)(&PC), gpr1);
1653 mov_m32rel_xreg32((unsigned int *)(&address), gpr2);
1654 mov_reg64_imm64(gpr1, (unsigned long long) dst->f.i.rt);
1655 mov_m64rel_xreg64((unsigned long long *)(&rdword), gpr1);
1656 shr_reg32_imm8(gpr2, 16);
1657 mov_reg64_preg64x8preg64(gpr2, gpr2, base1);
1658 call_reg64(gpr2);
1659 mov_xreg32_m32rel(gpr1, (unsigned int *)dst->f.i.rt);
1660 jmp_imm_short(19);
1661
1662 jump_end_rel8();
1663 mov_reg64_imm64(base1, (unsigned long long) rdram); // 10
1664 and_reg32_imm32(gpr2, 0x7FFFFF); // 6
1665 mov_reg32_preg64preg64(gpr1, gpr2, base1); // 3
1666
1667 set_register_state(gpr1, (unsigned int*)dst->f.i.rt, 1, 1);
1668#endif
1669}
1670
1671void gensb(void)
1672{
1673#if defined(COUNT_INSTR)
1674 inc_m32rel(&instr_count[32]);
1675#endif
1676#ifdef INTERPRET_SB
1677 gencallinterp((unsigned long long)cached_interpreter_table.SB, 0);
1678#else
1679 free_registers_move_start();
1680
1681 mov_xreg8_m8rel(CL, (unsigned char *)dst->f.i.rt);
1682 mov_xreg32_m32rel(EAX, (unsigned int *)dst->f.i.rs);
1683 add_eax_imm32((int)dst->f.i.immediate);
1684 mov_reg32_reg32(EBX, EAX);
1685 mov_reg64_imm64(RSI, (unsigned long long) writememb);
1686 if(fast_memory)
1687 {
1688 and_eax_imm32(0xDF800000);
1689 cmp_eax_imm32(0x80000000);
1690 }
1691 else
1692 {
1693 mov_reg64_imm64(RDI, (unsigned long long) write_rdramb);
1694 shr_reg32_imm8(EAX, 16);
1695 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
1696 cmp_reg64_reg64(RAX, RDI);
1697 }
1698 je_rj(49);
1699
1700 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
1701 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
1702 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
1703 mov_m8rel_xreg8((unsigned char *)(&cpu_byte), CL); // 7
1704 shr_reg32_imm8(EBX, 16); // 3
1705 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
1706 call_reg64(RBX); // 2
1707 mov_xreg32_m32rel(EAX, (unsigned int *)(&address)); // 7
1708 jmp_imm_short(25); // 2
1709
1710 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
1711 mov_reg32_reg32(EAX, EBX); // 2
1712 and_reg32_imm32(EBX, 0x7FFFFF); // 6
1713 xor_reg8_imm8(BL, 3); // 4
1714 mov_preg64preg64_reg8(RBX, RSI, CL); // 3
1715
1716 mov_reg64_imm64(RSI, (unsigned long long) invalid_code);
1717 mov_reg32_reg32(EBX, EAX);
1718 shr_reg32_imm8(EBX, 12);
1719 cmp_preg64preg64_imm8(RBX, RSI, 0);
1720 jne_rj(65);
1721
1722 mov_reg64_imm64(RDI, (unsigned long long) blocks); // 10
1723 mov_reg32_reg32(ECX, EBX); // 2
1724 mov_reg64_preg64x8preg64(RBX, RBX, RDI); // 4
1725 mov_reg64_preg64pimm32(RBX, RBX, (int) offsetof(precomp_block, block)); // 7
1726 mov_reg64_imm64(RDI, (unsigned long long) cached_interpreter_table.NOTCOMPILED); // 10
1727 and_eax_imm32(0xFFF); // 5
1728 shr_reg32_imm8(EAX, 2); // 3
1729 mov_reg32_imm32(EDX, sizeof(precomp_instr)); // 5
1730 mul_reg32(EDX); // 2
1731 mov_reg64_preg64preg64pimm32(RAX, RAX, RBX, (int) offsetof(precomp_instr, ops)); // 8
1732 cmp_reg64_reg64(RAX, RDI); // 3
1733 je_rj(4); // 2
1734 mov_preg64preg64_imm8(RCX, RSI, 1); // 4
1735#endif
1736}
1737
1738void gensh(void)
1739{
1740#if defined(COUNT_INSTR)
1741 inc_m32rel(&instr_count[33]);
1742#endif
1743#ifdef INTERPRET_SH
1744 gencallinterp((unsigned long long)cached_interpreter_table.SH, 0);
1745#else
1746 free_registers_move_start();
1747
1748 mov_xreg16_m16rel(CX, (unsigned short *)dst->f.i.rt);
1749 mov_xreg32_m32rel(EAX, (unsigned int *)dst->f.i.rs);
1750 add_eax_imm32((int)dst->f.i.immediate);
1751 mov_reg32_reg32(EBX, EAX);
1752 mov_reg64_imm64(RSI, (unsigned long long) writememh);
1753 if(fast_memory)
1754 {
1755 and_eax_imm32(0xDF800000);
1756 cmp_eax_imm32(0x80000000);
1757 }
1758 else
1759 {
1760 mov_reg64_imm64(RDI, (unsigned long long) write_rdramh);
1761 shr_reg32_imm8(EAX, 16);
1762 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
1763 cmp_reg64_reg64(RAX, RDI);
1764 }
1765 je_rj(50);
1766
1767 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
1768 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
1769 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
1770 mov_m16rel_xreg16((unsigned short *)(&hword), CX); // 8
1771 shr_reg32_imm8(EBX, 16); // 3
1772 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
1773 call_reg64(RBX); // 2
1774 mov_xreg32_m32rel(EAX, (unsigned int *)(&address)); // 7
1775 jmp_imm_short(26); // 2
1776
1777 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
1778 mov_reg32_reg32(EAX, EBX); // 2
1779 and_reg32_imm32(EBX, 0x7FFFFF); // 6
1780 xor_reg8_imm8(BL, 2); // 4
1781 mov_preg64preg64_reg16(RBX, RSI, CX); // 4
1782
1783 mov_reg64_imm64(RSI, (unsigned long long) invalid_code);
1784 mov_reg32_reg32(EBX, EAX);
1785 shr_reg32_imm8(EBX, 12);
1786 cmp_preg64preg64_imm8(RBX, RSI, 0);
1787 jne_rj(65);
1788
1789 mov_reg64_imm64(RDI, (unsigned long long) blocks); // 10
1790 mov_reg32_reg32(ECX, EBX); // 2
1791 mov_reg64_preg64x8preg64(RBX, RBX, RDI); // 4
1792 mov_reg64_preg64pimm32(RBX, RBX, (int) offsetof(precomp_block, block)); // 7
1793 mov_reg64_imm64(RDI, (unsigned long long) cached_interpreter_table.NOTCOMPILED); // 10
1794 and_eax_imm32(0xFFF); // 5
1795 shr_reg32_imm8(EAX, 2); // 3
1796 mov_reg32_imm32(EDX, sizeof(precomp_instr)); // 5
1797 mul_reg32(EDX); // 2
1798 mov_reg64_preg64preg64pimm32(RAX, RAX, RBX, (int) offsetof(precomp_instr, ops)); // 8
1799 cmp_reg64_reg64(RAX, RDI); // 3
1800 je_rj(4); // 2
1801 mov_preg64preg64_imm8(RCX, RSI, 1); // 4
1802#endif
1803}
1804
1805void genswl(void)
1806{
1807#if defined(COUNT_INSTR)
1808 inc_m32rel(&instr_count[35]);
1809#endif
1810 gencallinterp((unsigned long long)cached_interpreter_table.SWL, 0);
1811}
1812
1813void gensw(void)
1814{
1815#if defined(COUNT_INSTR)
1816 inc_m32rel(&instr_count[34]);
1817#endif
1818#ifdef INTERPRET_SW
1819 gencallinterp((unsigned long long)cached_interpreter_table.SW, 0);
1820#else
1821 free_registers_move_start();
1822
1823 mov_xreg32_m32rel(ECX, (unsigned int *)dst->f.i.rt);
1824 mov_xreg32_m32rel(EAX, (unsigned int *)dst->f.i.rs);
1825 add_eax_imm32((int)dst->f.i.immediate);
1826 mov_reg32_reg32(EBX, EAX);
1827 mov_reg64_imm64(RSI, (unsigned long long) writemem);
1828 if(fast_memory)
1829 {
1830 and_eax_imm32(0xDF800000);
1831 cmp_eax_imm32(0x80000000);
1832 }
1833 else
1834 {
1835 mov_reg64_imm64(RDI, (unsigned long long) write_rdram);
1836 shr_reg32_imm8(EAX, 16);
1837 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
1838 cmp_reg64_reg64(RAX, RDI);
1839 }
1840 je_rj(49);
1841
1842 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
1843 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
1844 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
1845 mov_m32rel_xreg32((unsigned int *)(&word), ECX); // 7
1846 shr_reg32_imm8(EBX, 16); // 3
1847 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
1848 call_reg64(RBX); // 2
1849 mov_xreg32_m32rel(EAX, (unsigned int *)(&address)); // 7
1850 jmp_imm_short(21); // 2
1851
1852 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
1853 mov_reg32_reg32(EAX, EBX); // 2
1854 and_reg32_imm32(EBX, 0x7FFFFF); // 6
1855 mov_preg64preg64_reg32(RBX, RSI, ECX); // 3
1856
1857 mov_reg64_imm64(RSI, (unsigned long long) invalid_code);
1858 mov_reg32_reg32(EBX, EAX);
1859 shr_reg32_imm8(EBX, 12);
1860 cmp_preg64preg64_imm8(RBX, RSI, 0);
1861 jne_rj(65);
1862
1863 mov_reg64_imm64(RDI, (unsigned long long) blocks); // 10
1864 mov_reg32_reg32(ECX, EBX); // 2
1865 mov_reg64_preg64x8preg64(RBX, RBX, RDI); // 4
1866 mov_reg64_preg64pimm32(RBX, RBX, (int) offsetof(precomp_block, block)); // 7
1867 mov_reg64_imm64(RDI, (unsigned long long) cached_interpreter_table.NOTCOMPILED); // 10
1868 and_eax_imm32(0xFFF); // 5
1869 shr_reg32_imm8(EAX, 2); // 3
1870 mov_reg32_imm32(EDX, sizeof(precomp_instr)); // 5
1871 mul_reg32(EDX); // 2
1872 mov_reg64_preg64preg64pimm32(RAX, RAX, RBX, (int) offsetof(precomp_instr, ops)); // 8
1873 cmp_reg64_reg64(RAX, RDI); // 3
1874 je_rj(4); // 2
1875 mov_preg64preg64_imm8(RCX, RSI, 1); // 4
1876#endif
1877}
1878
1879void gensdl(void)
1880{
1881#if defined(COUNT_INSTR)
1882 inc_m32rel(&instr_count[37]);
1883#endif
1884 gencallinterp((unsigned long long)cached_interpreter_table.SDL, 0);
1885}
1886
1887void gensdr(void)
1888{
1889#if defined(COUNT_INSTR)
1890 inc_m32rel(&instr_count[38]);
1891#endif
1892 gencallinterp((unsigned long long)cached_interpreter_table.SDR, 0);
1893}
1894
1895void genswr(void)
1896{
1897#if defined(COUNT_INSTR)
1898 inc_m32rel(&instr_count[36]);
1899#endif
1900 gencallinterp((unsigned long long)cached_interpreter_table.SWR, 0);
1901}
1902
1903void gencheck_cop1_unusable(void)
1904{
1905 free_registers_move_start();
1906
1907 test_m32rel_imm32((unsigned int*)&Status, 0x20000000);
1908 jne_rj(0);
1909 jump_start_rel8();
1910
1911 gencallinterp((unsigned long long)check_cop1_unusable, 0);
1912
1913 jump_end_rel8();
1914}
1915
1916void genlwc1(void)
1917{
1918#if defined(COUNT_INSTR)
1919 inc_m32rel(&instr_count[39]);
1920#endif
1921#ifdef INTERPRET_LWC1
1922 gencallinterp((unsigned long long)cached_interpreter_table.LWC1, 0);
1923#else
1924 gencheck_cop1_unusable();
1925
1926 mov_xreg32_m32rel(EAX, (unsigned int *)(&reg[dst->f.lf.base]));
1927 add_eax_imm32((int)dst->f.lf.offset);
1928 mov_reg32_reg32(EBX, EAX);
1929 mov_reg64_imm64(RSI, (unsigned long long) readmem);
1930 if(fast_memory)
1931 {
1932 and_eax_imm32(0xDF800000);
1933 cmp_eax_imm32(0x80000000);
1934 }
1935 else
1936 {
1937 mov_reg64_imm64(RDI, (unsigned long long) read_rdram);
1938 shr_reg32_imm8(EAX, 16);
1939 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
1940 cmp_reg64_reg64(RAX, RDI);
1941 }
1942 je_rj(49);
1943
1944 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
1945 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
1946 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
1947 mov_xreg64_m64rel(RDX, (unsigned long long *)(&reg_cop1_simple[dst->f.lf.ft])); // 7
1948 mov_m64rel_xreg64((unsigned long long *)(&rdword), RDX); // 7
1949 shr_reg32_imm8(EBX, 16); // 3
1950 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
1951 call_reg64(RBX); // 2
1952 jmp_imm_short(28); // 2
1953
1954 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
1955 and_reg32_imm32(EBX, 0x7FFFFF); // 6
1956 mov_reg32_preg64preg64(EAX, RBX, RSI); // 3
1957 mov_xreg64_m64rel(RBX, (unsigned long long *)(&reg_cop1_simple[dst->f.lf.ft])); // 7
1958 mov_preg64_reg32(RBX, EAX); // 2
1959#endif
1960}
1961
1962void genldc1(void)
1963{
1964#if defined(COUNT_INSTR)
1965 inc_m32rel(&instr_count[40]);
1966#endif
1967#ifdef INTERPRET_LDC1
1968 gencallinterp((unsigned long long)cached_interpreter_table.LDC1, 0);
1969#else
1970 gencheck_cop1_unusable();
1971
1972 mov_xreg32_m32rel(EAX, (unsigned int *)(&reg[dst->f.lf.base]));
1973 add_eax_imm32((int)dst->f.lf.offset);
1974 mov_reg32_reg32(EBX, EAX);
1975 mov_reg64_imm64(RSI, (unsigned long long) readmemd);
1976 if(fast_memory)
1977 {
1978 and_eax_imm32(0xDF800000);
1979 cmp_eax_imm32(0x80000000);
1980 }
1981 else
1982 {
1983 mov_reg64_imm64(RDI, (unsigned long long) read_rdramd);
1984 shr_reg32_imm8(EAX, 16);
1985 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
1986 cmp_reg64_reg64(RAX, RDI);
1987 }
1988 je_rj(49);
1989
1990 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
1991 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
1992 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
1993 mov_xreg64_m64rel(RDX, (unsigned long long *)(&reg_cop1_double[dst->f.lf.ft])); // 7
1994 mov_m64rel_xreg64((unsigned long long *)(&rdword), RDX); // 7
1995 shr_reg32_imm8(EBX, 16); // 3
1996 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
1997 call_reg64(RBX); // 2
1998 jmp_imm_short(39); // 2
1999
2000 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
2001 and_reg32_imm32(EBX, 0x7FFFFF); // 6
2002 mov_reg64_preg64preg64(RAX, RBX, RSI); // 4
2003 mov_xreg64_m64rel(RBX, (unsigned long long *)(&reg_cop1_double[dst->f.lf.ft])); // 7
2004 mov_preg64pimm32_reg32(RBX, 4, EAX); // 6
2005 shr_reg64_imm8(RAX, 32); // 4
2006 mov_preg64_reg32(RBX, EAX); // 2
2007#endif
2008}
2009
2010void gencache(void)
2011{
2012}
2013
2014void genld(void)
2015{
2016#if defined(COUNT_INSTR)
2017 inc_m32rel(&instr_count[41]);
2018#endif
2019#ifdef INTERPRET_LD
2020 gencallinterp((unsigned long long)cached_interpreter_table.LD, 0);
2021#else
2022 free_registers_move_start();
2023
2024 mov_xreg32_m32rel(EAX, (unsigned int *)dst->f.i.rs);
2025 add_eax_imm32((int)dst->f.i.immediate);
2026 mov_reg32_reg32(EBX, EAX);
2027 mov_reg64_imm64(RSI, (unsigned long long) readmemd);
2028 if(fast_memory)
2029 {
2030 and_eax_imm32(0xDF800000);
2031 cmp_eax_imm32(0x80000000);
2032 }
2033 else
2034 {
2035 mov_reg64_imm64(RDI, (unsigned long long) read_rdramd);
2036 shr_reg32_imm8(EAX, 16);
2037 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
2038 cmp_reg64_reg64(RAX, RDI);
2039 }
2040 je_rj(59);
2041
2042 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
2043 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
2044 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
2045 mov_reg64_imm64(RAX, (unsigned long long) dst->f.i.rt); // 10
2046 mov_m64rel_xreg64((unsigned long long *)(&rdword), RAX); // 7
2047 shr_reg32_imm8(EBX, 16); // 3
2048 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
2049 call_reg64(RBX); // 2
2050 mov_xreg64_m64rel(RAX, (unsigned long long *)(dst->f.i.rt)); // 7
2051 jmp_imm_short(33); // 2
2052
2053 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
2054 and_reg32_imm32(EBX, 0x7FFFFF); // 6
2055
2056 mov_reg32_preg64preg64(EAX, RBX, RSI); // 3
2057 mov_reg32_preg64preg64pimm32(EBX, RBX, RSI, 4); // 7
2058 shl_reg64_imm8(RAX, 32); // 4
2059 or_reg64_reg64(RAX, RBX); // 3
2060
2061 set_register_state(RAX, (unsigned int*)dst->f.i.rt, 1, 1);
2062#endif
2063}
2064
2065void genswc1(void)
2066{
2067#if defined(COUNT_INSTR)
2068 inc_m32rel(&instr_count[43]);
2069#endif
2070#ifdef INTERPRET_SWC1
2071 gencallinterp((unsigned long long)cached_interpreter_table.SWC1, 0);
2072#else
2073 gencheck_cop1_unusable();
2074
2075 mov_xreg64_m64rel(RDX, (unsigned long long *)(&reg_cop1_simple[dst->f.lf.ft]));
2076 mov_reg32_preg64(ECX, RDX);
2077 mov_xreg32_m32rel(EAX, (unsigned int *)(&reg[dst->f.lf.base]));
2078 add_eax_imm32((int)dst->f.lf.offset);
2079 mov_reg32_reg32(EBX, EAX);
2080 mov_reg64_imm64(RSI, (unsigned long long) writemem);
2081 if(fast_memory)
2082 {
2083 and_eax_imm32(0xDF800000);
2084 cmp_eax_imm32(0x80000000);
2085 }
2086 else
2087 {
2088 mov_reg64_imm64(RDI, (unsigned long long) write_rdram);
2089 shr_reg32_imm8(EAX, 16);
2090 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
2091 cmp_reg64_reg64(RAX, RDI);
2092 }
2093 je_rj(49);
2094
2095 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
2096 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
2097 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
2098 mov_m32rel_xreg32((unsigned int *)(&word), ECX); // 7
2099 shr_reg32_imm8(EBX, 16); // 3
2100 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
2101 call_reg64(RBX); // 2
2102 mov_xreg32_m32rel(EAX, (unsigned int *)(&address)); // 7
2103 jmp_imm_short(21); // 2
2104
2105 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
2106 mov_reg32_reg32(EAX, EBX); // 2
2107 and_reg32_imm32(EBX, 0x7FFFFF); // 6
2108 mov_preg64preg64_reg32(RBX, RSI, ECX); // 3
2109
2110 mov_reg64_imm64(RSI, (unsigned long long) invalid_code);
2111 mov_reg32_reg32(EBX, EAX);
2112 shr_reg32_imm8(EBX, 12);
2113 cmp_preg64preg64_imm8(RBX, RSI, 0);
2114 jne_rj(65);
2115
2116 mov_reg64_imm64(RDI, (unsigned long long) blocks); // 10
2117 mov_reg32_reg32(ECX, EBX); // 2
2118 mov_reg64_preg64x8preg64(RBX, RBX, RDI); // 4
2119 mov_reg64_preg64pimm32(RBX, RBX, (int) offsetof(precomp_block, block)); // 7
2120 mov_reg64_imm64(RDI, (unsigned long long) cached_interpreter_table.NOTCOMPILED); // 10
2121 and_eax_imm32(0xFFF); // 5
2122 shr_reg32_imm8(EAX, 2); // 3
2123 mov_reg32_imm32(EDX, sizeof(precomp_instr)); // 5
2124 mul_reg32(EDX); // 2
2125 mov_reg64_preg64preg64pimm32(RAX, RAX, RBX, (int) offsetof(precomp_instr, ops)); // 8
2126 cmp_reg64_reg64(RAX, RDI); // 3
2127 je_rj(4); // 2
2128 mov_preg64preg64_imm8(RCX, RSI, 1); // 4
2129#endif
2130}
2131
2132void gensdc1(void)
2133{
2134#if defined(COUNT_INSTR)
2135 inc_m32rel(&instr_count[44]);
2136#endif
2137#ifdef INTERPRET_SDC1
2138 gencallinterp((unsigned long long)cached_interpreter_table.SDC1, 0);
2139#else
2140 gencheck_cop1_unusable();
2141
2142 mov_xreg64_m64rel(RSI, (unsigned long long *)(&reg_cop1_double[dst->f.lf.ft]));
2143 mov_reg32_preg64(ECX, RSI);
2144 mov_reg32_preg64pimm32(EDX, RSI, 4);
2145 mov_xreg32_m32rel(EAX, (unsigned int *)(&reg[dst->f.lf.base]));
2146 add_eax_imm32((int)dst->f.lf.offset);
2147 mov_reg32_reg32(EBX, EAX);
2148 mov_reg64_imm64(RSI, (unsigned long long) writememd);
2149 if(fast_memory)
2150 {
2151 and_eax_imm32(0xDF800000);
2152 cmp_eax_imm32(0x80000000);
2153 }
2154 else
2155 {
2156 mov_reg64_imm64(RDI, (unsigned long long) write_rdramd);
2157 shr_reg32_imm8(EAX, 16);
2158 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
2159 cmp_reg64_reg64(RAX, RDI);
2160 }
2161 je_rj(56);
2162
2163 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
2164 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
2165 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
2166 mov_m32rel_xreg32((unsigned int *)(&dword), ECX); // 7
2167 mov_m32rel_xreg32((unsigned int *)(&dword)+1, EDX); // 7
2168 shr_reg32_imm8(EBX, 16); // 3
2169 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
2170 call_reg64(RBX); // 2
2171 mov_xreg32_m32rel(EAX, (unsigned int *)(&address)); // 7
2172 jmp_imm_short(28); // 2
2173
2174 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
2175 mov_reg32_reg32(EAX, EBX); // 2
2176 and_reg32_imm32(EBX, 0x7FFFFF); // 6
2177 mov_preg64preg64pimm32_reg32(RBX, RSI, 4, ECX); // 7
2178 mov_preg64preg64_reg32(RBX, RSI, EDX); // 3
2179
2180 mov_reg64_imm64(RSI, (unsigned long long) invalid_code);
2181 mov_reg32_reg32(EBX, EAX);
2182 shr_reg32_imm8(EBX, 12);
2183 cmp_preg64preg64_imm8(RBX, RSI, 0);
2184 jne_rj(65);
2185
2186 mov_reg64_imm64(RDI, (unsigned long long) blocks); // 10
2187 mov_reg32_reg32(ECX, EBX); // 2
2188 mov_reg64_preg64x8preg64(RBX, RBX, RDI); // 4
2189 mov_reg64_preg64pimm32(RBX, RBX, (int) offsetof(precomp_block, block)); // 7
2190 mov_reg64_imm64(RDI, (unsigned long long) cached_interpreter_table.NOTCOMPILED); // 10
2191 and_eax_imm32(0xFFF); // 5
2192 shr_reg32_imm8(EAX, 2); // 3
2193 mov_reg32_imm32(EDX, sizeof(precomp_instr)); // 5
2194 mul_reg32(EDX); // 2
2195 mov_reg64_preg64preg64pimm32(RAX, RAX, RBX, (int) offsetof(precomp_instr, ops)); // 8
2196 cmp_reg64_reg64(RAX, RDI); // 3
2197 je_rj(4); // 2
2198 mov_preg64preg64_imm8(RCX, RSI, 1); // 4
2199#endif
2200}
2201
2202void gensd(void)
2203{
2204#if defined(COUNT_INSTR)
2205 inc_m32rel(&instr_count[45]);
2206#endif
2207#ifdef INTERPRET_SD
2208 gencallinterp((unsigned long long)cached_interpreter_table.SD, 0);
2209#else
2210 free_registers_move_start();
2211
2212 mov_xreg32_m32rel(ECX, (unsigned int *)dst->f.i.rt);
2213 mov_xreg32_m32rel(EDX, ((unsigned int *)dst->f.i.rt)+1);
2214 mov_xreg32_m32rel(EAX, (unsigned int *)dst->f.i.rs);
2215 add_eax_imm32((int)dst->f.i.immediate);
2216 mov_reg32_reg32(EBX, EAX);
2217 mov_reg64_imm64(RSI, (unsigned long long) writememd);
2218 if(fast_memory)
2219 {
2220 and_eax_imm32(0xDF800000);
2221 cmp_eax_imm32(0x80000000);
2222 }
2223 else
2224 {
2225 mov_reg64_imm64(RDI, (unsigned long long) write_rdramd);
2226 shr_reg32_imm8(EAX, 16);
2227 mov_reg64_preg64x8preg64(RAX, RAX, RSI);
2228 cmp_reg64_reg64(RAX, RDI);
2229 }
2230 je_rj(56);
2231
2232 mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); // 10
2233 mov_m64rel_xreg64((unsigned long long *)(&PC), RAX); // 7
2234 mov_m32rel_xreg32((unsigned int *)(&address), EBX); // 7
2235 mov_m32rel_xreg32((unsigned int *)(&dword), ECX); // 7
2236 mov_m32rel_xreg32((unsigned int *)(&dword)+1, EDX); // 7
2237 shr_reg32_imm8(EBX, 16); // 3
2238 mov_reg64_preg64x8preg64(RBX, RBX, RSI); // 4
2239 call_reg64(RBX); // 2
2240 mov_xreg32_m32rel(EAX, (unsigned int *)(&address)); // 7
2241 jmp_imm_short(28); // 2
2242
2243 mov_reg64_imm64(RSI, (unsigned long long) rdram); // 10
2244 mov_reg32_reg32(EAX, EBX); // 2
2245 and_reg32_imm32(EBX, 0x7FFFFF); // 6
2246 mov_preg64preg64pimm32_reg32(RBX, RSI, 4, ECX); // 7
2247 mov_preg64preg64_reg32(RBX, RSI, EDX); // 3
2248
2249 mov_reg64_imm64(RSI, (unsigned long long) invalid_code);
2250 mov_reg32_reg32(EBX, EAX);
2251 shr_reg32_imm8(EBX, 12);
2252 cmp_preg64preg64_imm8(RBX, RSI, 0);
2253 jne_rj(65);
2254
2255 mov_reg64_imm64(RDI, (unsigned long long) blocks); // 10
2256 mov_reg32_reg32(ECX, EBX); // 2
2257 mov_reg64_preg64x8preg64(RBX, RBX, RDI); // 4
2258 mov_reg64_preg64pimm32(RBX, RBX, (int) offsetof(precomp_block, block)); // 7
2259 mov_reg64_imm64(RDI, (unsigned long long) cached_interpreter_table.NOTCOMPILED); // 10
2260 and_eax_imm32(0xFFF); // 5
2261 shr_reg32_imm8(EAX, 2); // 3
2262 mov_reg32_imm32(EDX, sizeof(precomp_instr)); // 5
2263 mul_reg32(EDX); // 2
2264 mov_reg64_preg64preg64pimm32(RAX, RAX, RBX, (int) offsetof(precomp_instr, ops)); // 8
2265 cmp_reg64_reg64(RAX, RDI); // 3
2266 je_rj(4); // 2
2267 mov_preg64preg64_imm8(RCX, RSI, 1); // 4
2268#endif
2269}
2270
2271void genll(void)
2272{
2273#if defined(COUNT_INSTR)
2274 inc_m32rel(&instr_count[42]);
2275#endif
2276 gencallinterp((unsigned long long)cached_interpreter_table.LL, 0);
2277}
2278
2279void gensc(void)
2280{
2281#if defined(COUNT_INSTR)
2282 inc_m32rel(&instr_count[46]);
2283#endif
2284 gencallinterp((unsigned long long)cached_interpreter_table.SC, 0);
2285}
2286