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