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)); |
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 | |
105 | static 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 | |
120 | static 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 | |
136 | static 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 | |
172 | static 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 | |
209 | static 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 | |
229 | static 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 | |
249 | static 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 | |
293 | void 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 | |
303 | void genlink_subblock(void) |
304 | { |
305 | free_all_registers(); |
306 | jmp(dst->addr+4); |
307 | } |
308 | |
309 | #ifdef COMPARE_CORE |
310 | void 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 | |
343 | void 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 | |
363 | void 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 | |
374 | void 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 | |
382 | void 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 | |
390 | void genfin_block(void) |
391 | { |
392 | gencallinterp((unsigned long long)cached_interpreter_table.FIN_BLOCK, 0); |
393 | } |
394 | |
395 | void 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 | |
411 | void gennop(void) |
412 | { |
413 | } |
414 | |
415 | void 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 | |
441 | void 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 | |
471 | void 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 | |
498 | void 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 *)(®[31])+1, 0xFFFFFFFF); |
520 | else |
521 | mov_m32rel_imm32((unsigned int *)(®[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 | |
531 | void 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 *)(®[31])+1, 0xFFFFFFFF); |
553 | else |
554 | mov_m32rel_imm32((unsigned int *)(®[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 | |
568 | void 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 | |
595 | void 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 | |
612 | void 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 | |
633 | void 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 | |
653 | void 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 | |
674 | void 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 | |
698 | void 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 | |
716 | void 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 | |
737 | void 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 | |
758 | void 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 | |
776 | void 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 | |
797 | void 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 | |
818 | void 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 | |
836 | void 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 | |
857 | void 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 | |
878 | void 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 | |
896 | void 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 | |
912 | void 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 | |
928 | void 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 | |
946 | void 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 | |
964 | void 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 | |
980 | void 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 | |
996 | void 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 | |
1012 | void 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 | |
1026 | void 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 | |
1045 | void 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 | |
1066 | void 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 | |
1090 | void 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 | |
1111 | void 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 | |
1129 | void 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 | |
1150 | void 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 | |
1171 | void 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 | |
1189 | void 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 | |
1210 | void 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 | |
1231 | void 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 | |
1249 | void 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 | |
1270 | void 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 | |
1291 | void 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 | |
1309 | void 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 | |
1325 | void 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 | |
1338 | void 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 | |
1346 | void 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 | |
1354 | void 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 | |
1404 | void 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 | |
1454 | void 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 | |
1462 | void 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 | |
1512 | void 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 | |
1563 | void 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 | |
1614 | void 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 | |
1622 | void 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 | |
1671 | void 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 | |
1738 | void 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 | |
1805 | void 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 | |
1813 | void 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 | |
1879 | void 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 | |
1887 | void 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 | |
1895 | void 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 | |
1903 | void 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 | |
1916 | void 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 *)(®[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 *)(®_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 *)(®_cop1_simple[dst->f.lf.ft])); // 7 |
1958 | mov_preg64_reg32(RBX, EAX); // 2 |
1959 | #endif |
1960 | } |
1961 | |
1962 | void 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 *)(®[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 *)(®_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 *)(®_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 | |
2010 | void gencache(void) |
2011 | { |
2012 | } |
2013 | |
2014 | void 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 | |
2065 | void 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 *)(®_cop1_simple[dst->f.lf.ft])); |
2076 | mov_reg32_preg64(ECX, RDX); |
2077 | mov_xreg32_m32rel(EAX, (unsigned int *)(®[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 | |
2132 | void 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 *)(®_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 *)(®[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 | |
2202 | void 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 | |
2271 | void 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 | |
2279 | void 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 | |