451ab91e |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - gspecial.c * |
3 | * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * |
4 | * Copyright (C) 2002 Hacktarux * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
20 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
21 | |
22 | #include <stdio.h> |
23 | |
24 | #include "assemble.h" |
25 | #include "interpret.h" |
26 | |
27 | #include "r4300/recomph.h" |
28 | #include "r4300/recomp.h" |
29 | #include "r4300/r4300.h" |
30 | #include "r4300/ops.h" |
31 | #include "r4300/macros.h" |
32 | #include "r4300/exception.h" |
33 | |
34 | void gensll(void) |
35 | { |
36 | #ifdef INTERPRET_SLL |
37 | gencallinterp((unsigned int)cached_interpreter_table.SLL, 0); |
38 | #else |
39 | int rt = allocate_register((unsigned int *)dst->f.r.rt); |
40 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
41 | |
42 | mov_reg32_reg32(rd, rt); |
43 | shl_reg32_imm8(rd, dst->f.r.sa); |
44 | #endif |
45 | } |
46 | |
47 | void gensrl(void) |
48 | { |
49 | #ifdef INTERPRET_SRL |
50 | gencallinterp((unsigned int)cached_interpreter_table.SRL, 0); |
51 | #else |
52 | int rt = allocate_register((unsigned int *)dst->f.r.rt); |
53 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
54 | |
55 | mov_reg32_reg32(rd, rt); |
56 | shr_reg32_imm8(rd, dst->f.r.sa); |
57 | #endif |
58 | } |
59 | |
60 | void gensra(void) |
61 | { |
62 | #ifdef INTERPRET_SRA |
63 | gencallinterp((unsigned int)cached_interpreter_table.SRA, 0); |
64 | #else |
65 | int rt = allocate_register((unsigned int *)dst->f.r.rt); |
66 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
67 | |
68 | mov_reg32_reg32(rd, rt); |
69 | sar_reg32_imm8(rd, dst->f.r.sa); |
70 | #endif |
71 | } |
72 | |
73 | void gensllv(void) |
74 | { |
75 | #ifdef INTERPRET_SLLV |
76 | gencallinterp((unsigned int)cached_interpreter_table.SLLV, 0); |
77 | #else |
78 | int rt, rd; |
79 | allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs); |
80 | |
81 | rt = allocate_register((unsigned int *)dst->f.r.rt); |
82 | rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
83 | |
84 | if (rd != ECX) |
85 | { |
86 | mov_reg32_reg32(rd, rt); |
87 | shl_reg32_cl(rd); |
88 | } |
89 | else |
90 | { |
91 | int temp = lru_register(); |
92 | free_register(temp); |
93 | mov_reg32_reg32(temp, rt); |
94 | shl_reg32_cl(temp); |
95 | mov_reg32_reg32(rd, temp); |
96 | } |
97 | #endif |
98 | } |
99 | |
100 | void gensrlv(void) |
101 | { |
102 | #ifdef INTERPRET_SRLV |
103 | gencallinterp((unsigned int)cached_interpreter_table.SRLV, 0); |
104 | #else |
105 | int rt, rd; |
106 | allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs); |
107 | |
108 | rt = allocate_register((unsigned int *)dst->f.r.rt); |
109 | rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
110 | |
111 | if (rd != ECX) |
112 | { |
113 | mov_reg32_reg32(rd, rt); |
114 | shr_reg32_cl(rd); |
115 | } |
116 | else |
117 | { |
118 | int temp = lru_register(); |
119 | free_register(temp); |
120 | mov_reg32_reg32(temp, rt); |
121 | shr_reg32_cl(temp); |
122 | mov_reg32_reg32(rd, temp); |
123 | } |
124 | #endif |
125 | } |
126 | |
127 | void gensrav(void) |
128 | { |
129 | #ifdef INTERPRET_SRAV |
130 | gencallinterp((unsigned int)cached_interpreter_table.SRAV, 0); |
131 | #else |
132 | int rt, rd; |
133 | allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs); |
134 | |
135 | rt = allocate_register((unsigned int *)dst->f.r.rt); |
136 | rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
137 | |
138 | if (rd != ECX) |
139 | { |
140 | mov_reg32_reg32(rd, rt); |
141 | sar_reg32_cl(rd); |
142 | } |
143 | else |
144 | { |
145 | int temp = lru_register(); |
146 | free_register(temp); |
147 | mov_reg32_reg32(temp, rt); |
148 | sar_reg32_cl(temp); |
149 | mov_reg32_reg32(rd, temp); |
150 | } |
151 | #endif |
152 | } |
153 | |
154 | void genjr(void) |
155 | { |
156 | #ifdef INTERPRET_JR |
157 | gencallinterp((unsigned int)cached_interpreter_table.JR, 1); |
158 | #else |
159 | static unsigned int precomp_instr_size = sizeof(precomp_instr); |
160 | unsigned int diff = |
161 | (unsigned int)(&dst->local_addr) - (unsigned int)(dst); |
162 | unsigned int diff_need = |
163 | (unsigned int)(&dst->reg_cache_infos.need_map) - (unsigned int)(dst); |
164 | unsigned int diff_wrap = |
165 | (unsigned int)(&dst->reg_cache_infos.jump_wrapper) - (unsigned int)(dst); |
166 | |
167 | if (((dst->addr & 0xFFF) == 0xFFC && |
168 | (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump) |
169 | { |
170 | gencallinterp((unsigned int)cached_interpreter_table.JR, 1); |
171 | return; |
172 | } |
173 | |
174 | free_all_registers(); |
175 | simplify_access(); |
176 | mov_eax_memoffs32((unsigned int *)dst->f.i.rs); |
177 | mov_memoffs32_eax((unsigned int *)&local_rs); |
178 | |
179 | gendelayslot(); |
180 | |
181 | mov_eax_memoffs32((unsigned int *)&local_rs); |
182 | mov_memoffs32_eax((unsigned int *)&last_addr); |
183 | |
184 | gencheck_interupt_reg(); |
185 | |
186 | mov_eax_memoffs32((unsigned int *)&local_rs); |
187 | mov_reg32_reg32(EBX, EAX); |
188 | and_eax_imm32(0xFFFFF000); |
189 | cmp_eax_imm32(dst_block->start & 0xFFFFF000); |
190 | je_near_rj(0); |
191 | |
192 | jump_start_rel32(); |
193 | |
194 | mov_m32_reg32(&jump_to_address, EBX); |
195 | mov_m32_imm32((unsigned int*)(&PC), (unsigned int)(dst+1)); |
196 | mov_reg32_imm32(EAX, (unsigned int)jump_to_func); |
197 | call_reg32(EAX); |
198 | |
199 | jump_end_rel32(); |
200 | |
201 | mov_reg32_reg32(EAX, EBX); |
202 | sub_eax_imm32(dst_block->start); |
203 | shr_reg32_imm8(EAX, 2); |
204 | mul_m32((unsigned int *)(&precomp_instr_size)); |
205 | |
206 | mov_reg32_preg32pimm32(EBX, EAX, (unsigned int)(dst_block->block)+diff_need); |
207 | cmp_reg32_imm32(EBX, 1); |
208 | jne_rj(7); |
209 | |
210 | add_eax_imm32((unsigned int)(dst_block->block)+diff_wrap); // 5 |
211 | jmp_reg32(EAX); // 2 |
212 | |
213 | mov_reg32_preg32pimm32(EAX, EAX, (unsigned int)(dst_block->block)+diff); |
214 | add_reg32_m32(EAX, (unsigned int *)(&dst_block->code)); |
215 | |
216 | jmp_reg32(EAX); |
217 | #endif |
218 | } |
219 | |
220 | void genjalr(void) |
221 | { |
222 | #ifdef INTERPRET_JALR |
223 | gencallinterp((unsigned int)cached_interpreter_table.JALR, 0); |
224 | #else |
225 | static unsigned int precomp_instr_size = sizeof(precomp_instr); |
226 | unsigned int diff = |
227 | (unsigned int)(&dst->local_addr) - (unsigned int)(dst); |
228 | unsigned int diff_need = |
229 | (unsigned int)(&dst->reg_cache_infos.need_map) - (unsigned int)(dst); |
230 | unsigned int diff_wrap = |
231 | (unsigned int)(&dst->reg_cache_infos.jump_wrapper) - (unsigned int)(dst); |
232 | |
233 | if (((dst->addr & 0xFFF) == 0xFFC && |
234 | (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump) |
235 | { |
236 | gencallinterp((unsigned int)cached_interpreter_table.JALR, 1); |
237 | return; |
238 | } |
239 | |
240 | free_all_registers(); |
241 | simplify_access(); |
242 | mov_eax_memoffs32((unsigned int *)dst->f.r.rs); |
243 | mov_memoffs32_eax((unsigned int *)&local_rs); |
244 | |
245 | gendelayslot(); |
246 | |
247 | mov_m32_imm32((unsigned int *)(dst-1)->f.r.rd, dst->addr+4); |
248 | if ((dst->addr+4) & 0x80000000) |
249 | mov_m32_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0xFFFFFFFF); |
250 | else |
251 | mov_m32_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0); |
252 | |
253 | mov_eax_memoffs32((unsigned int *)&local_rs); |
254 | mov_memoffs32_eax((unsigned int *)&last_addr); |
255 | |
256 | gencheck_interupt_reg(); |
257 | |
258 | mov_eax_memoffs32((unsigned int *)&local_rs); |
259 | mov_reg32_reg32(EBX, EAX); |
260 | and_eax_imm32(0xFFFFF000); |
261 | cmp_eax_imm32(dst_block->start & 0xFFFFF000); |
262 | je_near_rj(0); |
263 | |
264 | jump_start_rel32(); |
265 | |
266 | mov_m32_reg32(&jump_to_address, EBX); |
267 | mov_m32_imm32((unsigned int*)(&PC), (unsigned int)(dst+1)); |
268 | mov_reg32_imm32(EAX, (unsigned int)jump_to_func); |
269 | call_reg32(EAX); |
270 | |
271 | jump_end_rel32(); |
272 | |
273 | mov_reg32_reg32(EAX, EBX); |
274 | sub_eax_imm32(dst_block->start); |
275 | shr_reg32_imm8(EAX, 2); |
276 | mul_m32((unsigned int *)(&precomp_instr_size)); |
277 | |
278 | mov_reg32_preg32pimm32(EBX, EAX, (unsigned int)(dst_block->block)+diff_need); |
279 | cmp_reg32_imm32(EBX, 1); |
280 | jne_rj(7); |
281 | |
282 | add_eax_imm32((unsigned int)(dst_block->block)+diff_wrap); // 5 |
283 | jmp_reg32(EAX); // 2 |
284 | |
285 | mov_reg32_preg32pimm32(EAX, EAX, (unsigned int)(dst_block->block)+diff); |
286 | add_reg32_m32(EAX, (unsigned int *)(&dst_block->code)); |
287 | |
288 | jmp_reg32(EAX); |
289 | #endif |
290 | } |
291 | |
292 | void gensyscall(void) |
293 | { |
294 | #ifdef INTERPRET_SYSCALL |
295 | gencallinterp((unsigned int)cached_interpreter_table.SYSCALL, 0); |
296 | #else |
297 | free_all_registers(); |
298 | simplify_access(); |
299 | mov_m32_imm32(&Cause, 8 << 2); |
300 | gencallinterp((unsigned int)exception_general, 0); |
301 | #endif |
302 | } |
303 | |
304 | void gensync(void) |
305 | { |
306 | } |
307 | |
308 | void genmfhi(void) |
309 | { |
310 | #ifdef INTERPRET_MFHI |
311 | gencallinterp((unsigned int)cached_interpreter_table.MFHI, 0); |
312 | #else |
313 | int rd1 = allocate_64_register1_w((unsigned int*)dst->f.r.rd); |
314 | int rd2 = allocate_64_register2_w((unsigned int*)dst->f.r.rd); |
315 | int hi1 = allocate_64_register1((unsigned int*)&hi); |
316 | int hi2 = allocate_64_register2((unsigned int*)&hi); |
317 | |
318 | mov_reg32_reg32(rd1, hi1); |
319 | mov_reg32_reg32(rd2, hi2); |
320 | #endif |
321 | } |
322 | |
323 | void genmthi(void) |
324 | { |
325 | #ifdef INTERPRET_MTHI |
326 | gencallinterp((unsigned int)cached_interpreter_table.MTHI, 0); |
327 | #else |
328 | int hi1 = allocate_64_register1_w((unsigned int*)&hi); |
329 | int hi2 = allocate_64_register2_w((unsigned int*)&hi); |
330 | int rs1 = allocate_64_register1((unsigned int*)dst->f.r.rs); |
331 | int rs2 = allocate_64_register2((unsigned int*)dst->f.r.rs); |
332 | |
333 | mov_reg32_reg32(hi1, rs1); |
334 | mov_reg32_reg32(hi2, rs2); |
335 | #endif |
336 | } |
337 | |
338 | void genmflo(void) |
339 | { |
340 | #ifdef INTERPRET_MFLO |
341 | gencallinterp((unsigned int)cached_interpreter_table.MFLO, 0); |
342 | #else |
343 | int rd1 = allocate_64_register1_w((unsigned int*)dst->f.r.rd); |
344 | int rd2 = allocate_64_register2_w((unsigned int*)dst->f.r.rd); |
345 | int lo1 = allocate_64_register1((unsigned int*)&lo); |
346 | int lo2 = allocate_64_register2((unsigned int*)&lo); |
347 | |
348 | mov_reg32_reg32(rd1, lo1); |
349 | mov_reg32_reg32(rd2, lo2); |
350 | #endif |
351 | } |
352 | |
353 | void genmtlo(void) |
354 | { |
355 | #ifdef INTERPRET_MTLO |
356 | gencallinterp((unsigned int)cached_interpreter_table.MTLO, 0); |
357 | #else |
358 | int lo1 = allocate_64_register1_w((unsigned int*)&lo); |
359 | int lo2 = allocate_64_register2_w((unsigned int*)&lo); |
360 | int rs1 = allocate_64_register1((unsigned int*)dst->f.r.rs); |
361 | int rs2 = allocate_64_register2((unsigned int*)dst->f.r.rs); |
362 | |
363 | mov_reg32_reg32(lo1, rs1); |
364 | mov_reg32_reg32(lo2, rs2); |
365 | #endif |
366 | } |
367 | |
368 | void gendsllv(void) |
369 | { |
370 | #ifdef INTERPRET_DSLLV |
371 | gencallinterp((unsigned int)cached_interpreter_table.DSLLV, 0); |
372 | #else |
373 | int rt1, rt2, rd1, rd2; |
374 | allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs); |
375 | |
376 | rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
377 | rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
378 | rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
379 | rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
380 | |
381 | if (rd1 != ECX && rd2 != ECX) |
382 | { |
383 | mov_reg32_reg32(rd1, rt1); |
384 | mov_reg32_reg32(rd2, rt2); |
385 | shld_reg32_reg32_cl(rd2,rd1); |
386 | shl_reg32_cl(rd1); |
387 | test_reg32_imm32(ECX, 0x20); |
388 | je_rj(4); |
389 | mov_reg32_reg32(rd2, rd1); // 2 |
390 | xor_reg32_reg32(rd1, rd1); // 2 |
391 | } |
392 | else |
393 | { |
394 | int temp1, temp2; |
395 | force_32(ECX); |
396 | temp1 = lru_register(); |
397 | temp2 = lru_register_exc1(temp1); |
398 | free_register(temp1); |
399 | free_register(temp2); |
400 | |
401 | mov_reg32_reg32(temp1, rt1); |
402 | mov_reg32_reg32(temp2, rt2); |
403 | shld_reg32_reg32_cl(temp2, temp1); |
404 | shl_reg32_cl(temp1); |
405 | test_reg32_imm32(ECX, 0x20); |
406 | je_rj(4); |
407 | mov_reg32_reg32(temp2, temp1); // 2 |
408 | xor_reg32_reg32(temp1, temp1); // 2 |
409 | |
410 | mov_reg32_reg32(rd1, temp1); |
411 | mov_reg32_reg32(rd2, temp2); |
412 | } |
413 | #endif |
414 | } |
415 | |
416 | void gendsrlv(void) |
417 | { |
418 | #ifdef INTERPRET_DSRLV |
419 | gencallinterp((unsigned int)cached_interpreter_table.DSRLV, 0); |
420 | #else |
421 | int rt1, rt2, rd1, rd2; |
422 | allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs); |
423 | |
424 | rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
425 | rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
426 | rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
427 | rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
428 | |
429 | if (rd1 != ECX && rd2 != ECX) |
430 | { |
431 | mov_reg32_reg32(rd1, rt1); |
432 | mov_reg32_reg32(rd2, rt2); |
433 | shrd_reg32_reg32_cl(rd1,rd2); |
434 | shr_reg32_cl(rd2); |
435 | test_reg32_imm32(ECX, 0x20); |
436 | je_rj(4); |
437 | mov_reg32_reg32(rd1, rd2); // 2 |
438 | xor_reg32_reg32(rd2, rd2); // 2 |
439 | } |
440 | else |
441 | { |
442 | int temp1, temp2; |
443 | force_32(ECX); |
444 | temp1 = lru_register(); |
445 | temp2 = lru_register_exc1(temp1); |
446 | free_register(temp1); |
447 | free_register(temp2); |
448 | |
449 | mov_reg32_reg32(temp1, rt1); |
450 | mov_reg32_reg32(temp2, rt2); |
451 | shrd_reg32_reg32_cl(temp1, temp2); |
452 | shr_reg32_cl(temp2); |
453 | test_reg32_imm32(ECX, 0x20); |
454 | je_rj(4); |
455 | mov_reg32_reg32(temp1, temp2); // 2 |
456 | xor_reg32_reg32(temp2, temp2); // 2 |
457 | |
458 | mov_reg32_reg32(rd1, temp1); |
459 | mov_reg32_reg32(rd2, temp2); |
460 | } |
461 | #endif |
462 | } |
463 | |
464 | void gendsrav(void) |
465 | { |
466 | #ifdef INTERPRET_DSRAV |
467 | gencallinterp((unsigned int)cached_interpreter_table.DSRAV, 0); |
468 | #else |
469 | int rt1, rt2, rd1, rd2; |
470 | allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs); |
471 | |
472 | rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
473 | rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
474 | rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
475 | rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
476 | |
477 | if (rd1 != ECX && rd2 != ECX) |
478 | { |
479 | mov_reg32_reg32(rd1, rt1); |
480 | mov_reg32_reg32(rd2, rt2); |
481 | shrd_reg32_reg32_cl(rd1,rd2); |
482 | sar_reg32_cl(rd2); |
483 | test_reg32_imm32(ECX, 0x20); |
484 | je_rj(5); |
485 | mov_reg32_reg32(rd1, rd2); // 2 |
486 | sar_reg32_imm8(rd2, 31); // 3 |
487 | } |
488 | else |
489 | { |
490 | int temp1, temp2; |
491 | force_32(ECX); |
492 | temp1 = lru_register(); |
493 | temp2 = lru_register_exc1(temp1); |
494 | free_register(temp1); |
495 | free_register(temp2); |
496 | |
497 | mov_reg32_reg32(temp1, rt1); |
498 | mov_reg32_reg32(temp2, rt2); |
499 | shrd_reg32_reg32_cl(temp1, temp2); |
500 | sar_reg32_cl(temp2); |
501 | test_reg32_imm32(ECX, 0x20); |
502 | je_rj(5); |
503 | mov_reg32_reg32(temp1, temp2); // 2 |
504 | sar_reg32_imm8(temp2, 31); // 3 |
505 | |
506 | mov_reg32_reg32(rd1, temp1); |
507 | mov_reg32_reg32(rd2, temp2); |
508 | } |
509 | #endif |
510 | } |
511 | |
512 | void genmult(void) |
513 | { |
514 | #ifdef INTERPRET_MULT |
515 | gencallinterp((unsigned int)cached_interpreter_table.MULT, 0); |
516 | #else |
517 | int rs, rt; |
518 | allocate_register_manually_w(EAX, (unsigned int *)&lo, 0); |
519 | allocate_register_manually_w(EDX, (unsigned int *)&hi, 0); |
520 | rs = allocate_register((unsigned int*)dst->f.r.rs); |
521 | rt = allocate_register((unsigned int*)dst->f.r.rt); |
522 | mov_reg32_reg32(EAX, rs); |
523 | imul_reg32(rt); |
524 | #endif |
525 | } |
526 | |
527 | void genmultu(void) |
528 | { |
529 | #ifdef INTERPRET_MULTU |
530 | gencallinterp((unsigned int)cached_interpreter_table.MULTU, 0); |
531 | #else |
532 | int rs, rt; |
533 | allocate_register_manually_w(EAX, (unsigned int *)&lo, 0); |
534 | allocate_register_manually_w(EDX, (unsigned int *)&hi, 0); |
535 | rs = allocate_register((unsigned int*)dst->f.r.rs); |
536 | rt = allocate_register((unsigned int*)dst->f.r.rt); |
537 | mov_reg32_reg32(EAX, rs); |
538 | mul_reg32(rt); |
539 | #endif |
540 | } |
541 | |
542 | void gendiv(void) |
543 | { |
544 | #ifdef INTERPRET_DIV |
545 | gencallinterp((unsigned int)cached_interpreter_table.DIV, 0); |
546 | #else |
547 | int rs, rt; |
548 | allocate_register_manually_w(EAX, (unsigned int *)&lo, 0); |
549 | allocate_register_manually_w(EDX, (unsigned int *)&hi, 0); |
550 | rs = allocate_register((unsigned int*)dst->f.r.rs); |
551 | rt = allocate_register((unsigned int*)dst->f.r.rt); |
552 | cmp_reg32_imm32(rt, 0); |
553 | je_rj((rs == EAX ? 0 : 2) + 1 + 2); |
554 | mov_reg32_reg32(EAX, rs); // 0 or 2 |
555 | cdq(); // 1 |
556 | idiv_reg32(rt); // 2 |
557 | #endif |
558 | } |
559 | |
560 | void gendivu(void) |
561 | { |
562 | #ifdef INTERPRET_DIVU |
563 | gencallinterp((unsigned int)cached_interpreter_table.DIVU, 0); |
564 | #else |
565 | int rs, rt; |
566 | allocate_register_manually_w(EAX, (unsigned int *)&lo, 0); |
567 | allocate_register_manually_w(EDX, (unsigned int *)&hi, 0); |
568 | rs = allocate_register((unsigned int*)dst->f.r.rs); |
569 | rt = allocate_register((unsigned int*)dst->f.r.rt); |
570 | cmp_reg32_imm32(rt, 0); |
571 | je_rj((rs == EAX ? 0 : 2) + 2 + 2); |
572 | mov_reg32_reg32(EAX, rs); // 0 or 2 |
573 | xor_reg32_reg32(EDX, EDX); // 2 |
574 | div_reg32(rt); // 2 |
575 | #endif |
576 | } |
577 | |
578 | void gendmult(void) |
579 | { |
580 | gencallinterp((unsigned int)cached_interpreter_table.DMULT, 0); |
581 | } |
582 | |
583 | void gendmultu(void) |
584 | { |
585 | #ifdef INTERPRET_DMULTU |
586 | gencallinterp((unsigned int)cached_interpreter_table.DMULTU, 0); |
587 | #else |
588 | free_all_registers(); |
589 | simplify_access(); |
590 | |
591 | mov_eax_memoffs32((unsigned int *)dst->f.r.rs); |
592 | mul_m32((unsigned int *)dst->f.r.rt); // EDX:EAX = temp1 |
593 | mov_memoffs32_eax((unsigned int *)(&lo)); |
594 | |
595 | mov_reg32_reg32(EBX, EDX); // EBX = temp1>>32 |
596 | mov_eax_memoffs32((unsigned int *)dst->f.r.rs); |
597 | mul_m32((unsigned int *)(dst->f.r.rt)+1); |
598 | add_reg32_reg32(EBX, EAX); |
599 | adc_reg32_imm32(EDX, 0); |
600 | mov_reg32_reg32(ECX, EDX); // ECX:EBX = temp2 |
601 | |
602 | mov_eax_memoffs32((unsigned int *)(dst->f.r.rs)+1); |
603 | mul_m32((unsigned int *)dst->f.r.rt); // EDX:EAX = temp3 |
604 | |
605 | add_reg32_reg32(EBX, EAX); |
606 | adc_reg32_imm32(ECX, 0); // ECX:EBX = result2 |
607 | mov_m32_reg32((unsigned int*)(&lo)+1, EBX); |
608 | |
609 | mov_reg32_reg32(ESI, EDX); // ESI = temp3>>32 |
610 | mov_eax_memoffs32((unsigned int *)(dst->f.r.rs)+1); |
611 | mul_m32((unsigned int *)(dst->f.r.rt)+1); |
612 | add_reg32_reg32(EAX, ESI); |
613 | adc_reg32_imm32(EDX, 0); // EDX:EAX = temp4 |
614 | |
615 | add_reg32_reg32(EAX, ECX); |
616 | adc_reg32_imm32(EDX, 0); // EDX:EAX = result3 |
617 | mov_memoffs32_eax((unsigned int *)(&hi)); |
618 | mov_m32_reg32((unsigned int *)(&hi)+1, EDX); |
619 | #endif |
620 | } |
621 | |
622 | void genddiv(void) |
623 | { |
624 | gencallinterp((unsigned int)cached_interpreter_table.DDIV, 0); |
625 | } |
626 | |
627 | void genddivu(void) |
628 | { |
629 | gencallinterp((unsigned int)cached_interpreter_table.DDIVU, 0); |
630 | } |
631 | |
632 | void genadd(void) |
633 | { |
634 | #ifdef INTERPRET_ADD |
635 | gencallinterp((unsigned int)cached_interpreter_table.ADD, 0); |
636 | #else |
637 | int rs = allocate_register((unsigned int *)dst->f.r.rs); |
638 | int rt = allocate_register((unsigned int *)dst->f.r.rt); |
639 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
640 | |
641 | if (rt != rd && rs != rd) |
642 | { |
643 | mov_reg32_reg32(rd, rs); |
644 | add_reg32_reg32(rd, rt); |
645 | } |
646 | else |
647 | { |
648 | int temp = lru_register(); |
649 | free_register(temp); |
650 | mov_reg32_reg32(temp, rs); |
651 | add_reg32_reg32(temp, rt); |
652 | mov_reg32_reg32(rd, temp); |
653 | } |
654 | #endif |
655 | } |
656 | |
657 | void genaddu(void) |
658 | { |
659 | #ifdef INTERPRET_ADDU |
660 | gencallinterp((unsigned int)cached_interpreter_table.ADDU, 0); |
661 | #else |
662 | int rs = allocate_register((unsigned int *)dst->f.r.rs); |
663 | int rt = allocate_register((unsigned int *)dst->f.r.rt); |
664 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
665 | |
666 | if (rt != rd && rs != rd) |
667 | { |
668 | mov_reg32_reg32(rd, rs); |
669 | add_reg32_reg32(rd, rt); |
670 | } |
671 | else |
672 | { |
673 | int temp = lru_register(); |
674 | free_register(temp); |
675 | mov_reg32_reg32(temp, rs); |
676 | add_reg32_reg32(temp, rt); |
677 | mov_reg32_reg32(rd, temp); |
678 | } |
679 | #endif |
680 | } |
681 | |
682 | void gensub(void) |
683 | { |
684 | #ifdef INTERPRET_SUB |
685 | gencallinterp((unsigned int)cached_interpreter_table.SUB, 0); |
686 | #else |
687 | int rs = allocate_register((unsigned int *)dst->f.r.rs); |
688 | int rt = allocate_register((unsigned int *)dst->f.r.rt); |
689 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
690 | |
691 | if (rt != rd && rs != rd) |
692 | { |
693 | mov_reg32_reg32(rd, rs); |
694 | sub_reg32_reg32(rd, rt); |
695 | } |
696 | else |
697 | { |
698 | int temp = lru_register(); |
699 | free_register(temp); |
700 | mov_reg32_reg32(temp, rs); |
701 | sub_reg32_reg32(temp, rt); |
702 | mov_reg32_reg32(rd, temp); |
703 | } |
704 | #endif |
705 | } |
706 | |
707 | void gensubu(void) |
708 | { |
709 | #ifdef INTERPRET_SUBU |
710 | gencallinterp((unsigned int)cached_interpreter_table.SUBU, 0); |
711 | #else |
712 | int rs = allocate_register((unsigned int *)dst->f.r.rs); |
713 | int rt = allocate_register((unsigned int *)dst->f.r.rt); |
714 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
715 | |
716 | if (rt != rd && rs != rd) |
717 | { |
718 | mov_reg32_reg32(rd, rs); |
719 | sub_reg32_reg32(rd, rt); |
720 | } |
721 | else |
722 | { |
723 | int temp = lru_register(); |
724 | free_register(temp); |
725 | mov_reg32_reg32(temp, rs); |
726 | sub_reg32_reg32(temp, rt); |
727 | mov_reg32_reg32(rd, temp); |
728 | } |
729 | #endif |
730 | } |
731 | |
732 | void genand(void) |
733 | { |
734 | #ifdef INTERPRET_AND |
735 | gencallinterp((unsigned int)cached_interpreter_table.AND, 0); |
736 | #else |
737 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
738 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
739 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
740 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
741 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
742 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
743 | |
744 | if (rt1 != rd1 && rs1 != rd1) |
745 | { |
746 | mov_reg32_reg32(rd1, rs1); |
747 | mov_reg32_reg32(rd2, rs2); |
748 | and_reg32_reg32(rd1, rt1); |
749 | and_reg32_reg32(rd2, rt2); |
750 | } |
751 | else |
752 | { |
753 | int temp = lru_register(); |
754 | free_register(temp); |
755 | mov_reg32_reg32(temp, rs1); |
756 | and_reg32_reg32(temp, rt1); |
757 | mov_reg32_reg32(rd1, temp); |
758 | mov_reg32_reg32(temp, rs2); |
759 | and_reg32_reg32(temp, rt2); |
760 | mov_reg32_reg32(rd2, temp); |
761 | } |
762 | #endif |
763 | } |
764 | |
765 | void genor(void) |
766 | { |
767 | #ifdef INTERPRET_OR |
768 | gencallinterp((unsigned int)cached_interpreter_table.OR, 0); |
769 | #else |
770 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
771 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
772 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
773 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
774 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
775 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
776 | |
777 | if (rt1 != rd1 && rs1 != rd1) |
778 | { |
779 | mov_reg32_reg32(rd1, rs1); |
780 | mov_reg32_reg32(rd2, rs2); |
781 | or_reg32_reg32(rd1, rt1); |
782 | or_reg32_reg32(rd2, rt2); |
783 | } |
784 | else |
785 | { |
786 | int temp = lru_register(); |
787 | free_register(temp); |
788 | mov_reg32_reg32(temp, rs1); |
789 | or_reg32_reg32(temp, rt1); |
790 | mov_reg32_reg32(rd1, temp); |
791 | mov_reg32_reg32(temp, rs2); |
792 | or_reg32_reg32(temp, rt2); |
793 | mov_reg32_reg32(rd2, temp); |
794 | } |
795 | #endif |
796 | } |
797 | |
798 | void genxor(void) |
799 | { |
800 | #ifdef INTERPRET_XOR |
801 | gencallinterp((unsigned int)cached_interpreter_table.XOR, 0); |
802 | #else |
803 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
804 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
805 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
806 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
807 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
808 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
809 | |
810 | if (rt1 != rd1 && rs1 != rd1) |
811 | { |
812 | mov_reg32_reg32(rd1, rs1); |
813 | mov_reg32_reg32(rd2, rs2); |
814 | xor_reg32_reg32(rd1, rt1); |
815 | xor_reg32_reg32(rd2, rt2); |
816 | } |
817 | else |
818 | { |
819 | int temp = lru_register(); |
820 | free_register(temp); |
821 | mov_reg32_reg32(temp, rs1); |
822 | xor_reg32_reg32(temp, rt1); |
823 | mov_reg32_reg32(rd1, temp); |
824 | mov_reg32_reg32(temp, rs2); |
825 | xor_reg32_reg32(temp, rt2); |
826 | mov_reg32_reg32(rd2, temp); |
827 | } |
828 | #endif |
829 | } |
830 | |
831 | void gennor(void) |
832 | { |
833 | #ifdef INTERPRET_NOR |
834 | gencallinterp((unsigned int)cached_interpreter_table.NOR, 0); |
835 | #else |
836 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
837 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
838 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
839 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
840 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
841 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
842 | |
843 | if (rt1 != rd1 && rs1 != rd1) |
844 | { |
845 | mov_reg32_reg32(rd1, rs1); |
846 | mov_reg32_reg32(rd2, rs2); |
847 | or_reg32_reg32(rd1, rt1); |
848 | or_reg32_reg32(rd2, rt2); |
849 | not_reg32(rd1); |
850 | not_reg32(rd2); |
851 | } |
852 | else |
853 | { |
854 | int temp = lru_register(); |
855 | free_register(temp); |
856 | mov_reg32_reg32(temp, rs1); |
857 | or_reg32_reg32(temp, rt1); |
858 | mov_reg32_reg32(rd1, temp); |
859 | mov_reg32_reg32(temp, rs2); |
860 | or_reg32_reg32(temp, rt2); |
861 | mov_reg32_reg32(rd2, temp); |
862 | not_reg32(rd1); |
863 | not_reg32(rd2); |
864 | } |
865 | #endif |
866 | } |
867 | |
868 | void genslt(void) |
869 | { |
870 | #ifdef INTERPRET_SLT |
871 | gencallinterp((unsigned int)cached_interpreter_table.SLT, 0); |
872 | #else |
873 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
874 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
875 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
876 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
877 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
878 | |
879 | cmp_reg32_reg32(rs2, rt2); |
880 | jl_rj(13); |
881 | jne_rj(4); // 2 |
882 | cmp_reg32_reg32(rs1, rt1); // 2 |
883 | jl_rj(7); // 2 |
884 | mov_reg32_imm32(rd, 0); // 5 |
885 | jmp_imm_short(5); // 2 |
886 | mov_reg32_imm32(rd, 1); // 5 |
887 | #endif |
888 | } |
889 | |
890 | void gensltu(void) |
891 | { |
892 | #ifdef INTERPRET_SLTU |
893 | gencallinterp((unsigned int)cached_interpreter_table.SLTU, 0); |
894 | #else |
895 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
896 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
897 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
898 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
899 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
900 | |
901 | cmp_reg32_reg32(rs2, rt2); |
902 | jb_rj(13); |
903 | jne_rj(4); // 2 |
904 | cmp_reg32_reg32(rs1, rt1); // 2 |
905 | jb_rj(7); // 2 |
906 | mov_reg32_imm32(rd, 0); // 5 |
907 | jmp_imm_short(5); // 2 |
908 | mov_reg32_imm32(rd, 1); // 5 |
909 | #endif |
910 | } |
911 | |
912 | void gendadd(void) |
913 | { |
914 | #ifdef INTERPRET_DADD |
915 | gencallinterp((unsigned int)cached_interpreter_table.DADD, 0); |
916 | #else |
917 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
918 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
919 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
920 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
921 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
922 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
923 | |
924 | if (rt1 != rd1 && rs1 != rd1) |
925 | { |
926 | mov_reg32_reg32(rd1, rs1); |
927 | mov_reg32_reg32(rd2, rs2); |
928 | add_reg32_reg32(rd1, rt1); |
929 | adc_reg32_reg32(rd2, rt2); |
930 | } |
931 | else |
932 | { |
933 | int temp = lru_register(); |
934 | free_register(temp); |
935 | mov_reg32_reg32(temp, rs1); |
936 | add_reg32_reg32(temp, rt1); |
937 | mov_reg32_reg32(rd1, temp); |
938 | mov_reg32_reg32(temp, rs2); |
939 | adc_reg32_reg32(temp, rt2); |
940 | mov_reg32_reg32(rd2, temp); |
941 | } |
942 | #endif |
943 | } |
944 | |
945 | void gendaddu(void) |
946 | { |
947 | #ifdef INTERPRET_DADDU |
948 | gencallinterp((unsigned int)cached_interpreter_table.DADDU, 0); |
949 | #else |
950 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
951 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
952 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
953 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
954 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
955 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
956 | |
957 | if (rt1 != rd1 && rs1 != rd1) |
958 | { |
959 | mov_reg32_reg32(rd1, rs1); |
960 | mov_reg32_reg32(rd2, rs2); |
961 | add_reg32_reg32(rd1, rt1); |
962 | adc_reg32_reg32(rd2, rt2); |
963 | } |
964 | else |
965 | { |
966 | int temp = lru_register(); |
967 | free_register(temp); |
968 | mov_reg32_reg32(temp, rs1); |
969 | add_reg32_reg32(temp, rt1); |
970 | mov_reg32_reg32(rd1, temp); |
971 | mov_reg32_reg32(temp, rs2); |
972 | adc_reg32_reg32(temp, rt2); |
973 | mov_reg32_reg32(rd2, temp); |
974 | } |
975 | #endif |
976 | } |
977 | |
978 | void gendsub(void) |
979 | { |
980 | #ifdef INTERPRET_DSUB |
981 | gencallinterp((unsigned int)cached_interpreter_table.DSUB, 0); |
982 | #else |
983 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
984 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
985 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
986 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
987 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
988 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
989 | |
990 | if (rt1 != rd1 && rs1 != rd1) |
991 | { |
992 | mov_reg32_reg32(rd1, rs1); |
993 | mov_reg32_reg32(rd2, rs2); |
994 | sub_reg32_reg32(rd1, rt1); |
995 | sbb_reg32_reg32(rd2, rt2); |
996 | } |
997 | else |
998 | { |
999 | int temp = lru_register(); |
1000 | free_register(temp); |
1001 | mov_reg32_reg32(temp, rs1); |
1002 | sub_reg32_reg32(temp, rt1); |
1003 | mov_reg32_reg32(rd1, temp); |
1004 | mov_reg32_reg32(temp, rs2); |
1005 | sbb_reg32_reg32(temp, rt2); |
1006 | mov_reg32_reg32(rd2, temp); |
1007 | } |
1008 | #endif |
1009 | } |
1010 | |
1011 | void gendsubu(void) |
1012 | { |
1013 | #ifdef INTERPRET_DSUBU |
1014 | gencallinterp((unsigned int)cached_interpreter_table.DSUBU, 0); |
1015 | #else |
1016 | int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); |
1017 | int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); |
1018 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
1019 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
1020 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
1021 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
1022 | |
1023 | if (rt1 != rd1 && rs1 != rd1) |
1024 | { |
1025 | mov_reg32_reg32(rd1, rs1); |
1026 | mov_reg32_reg32(rd2, rs2); |
1027 | sub_reg32_reg32(rd1, rt1); |
1028 | sbb_reg32_reg32(rd2, rt2); |
1029 | } |
1030 | else |
1031 | { |
1032 | int temp = lru_register(); |
1033 | free_register(temp); |
1034 | mov_reg32_reg32(temp, rs1); |
1035 | sub_reg32_reg32(temp, rt1); |
1036 | mov_reg32_reg32(rd1, temp); |
1037 | mov_reg32_reg32(temp, rs2); |
1038 | sbb_reg32_reg32(temp, rt2); |
1039 | mov_reg32_reg32(rd2, temp); |
1040 | } |
1041 | #endif |
1042 | } |
1043 | |
1044 | void genteq(void) |
1045 | { |
1046 | gencallinterp((unsigned int)cached_interpreter_table.TEQ, 0); |
1047 | } |
1048 | |
1049 | void gendsll(void) |
1050 | { |
1051 | #ifdef INTERPRET_DSLL |
1052 | gencallinterp((unsigned int)cached_interpreter_table.DSLL, 0); |
1053 | #else |
1054 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
1055 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
1056 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
1057 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
1058 | |
1059 | mov_reg32_reg32(rd1, rt1); |
1060 | mov_reg32_reg32(rd2, rt2); |
1061 | shld_reg32_reg32_imm8(rd2, rd1, dst->f.r.sa); |
1062 | shl_reg32_imm8(rd1, dst->f.r.sa); |
1063 | if (dst->f.r.sa & 0x20) |
1064 | { |
1065 | mov_reg32_reg32(rd2, rd1); |
1066 | xor_reg32_reg32(rd1, rd1); |
1067 | } |
1068 | #endif |
1069 | } |
1070 | |
1071 | void gendsrl(void) |
1072 | { |
1073 | #ifdef INTERPRET_DSRL |
1074 | gencallinterp((unsigned int)cached_interpreter_table.DSRL, 0); |
1075 | #else |
1076 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
1077 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
1078 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
1079 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
1080 | |
1081 | mov_reg32_reg32(rd1, rt1); |
1082 | mov_reg32_reg32(rd2, rt2); |
1083 | shrd_reg32_reg32_imm8(rd1, rd2, dst->f.r.sa); |
1084 | shr_reg32_imm8(rd2, dst->f.r.sa); |
1085 | if (dst->f.r.sa & 0x20) |
1086 | { |
1087 | mov_reg32_reg32(rd1, rd2); |
1088 | xor_reg32_reg32(rd2, rd2); |
1089 | } |
1090 | #endif |
1091 | } |
1092 | |
1093 | void gendsra(void) |
1094 | { |
1095 | #ifdef INTERPRET_DSRA |
1096 | gencallinterp((unsigned int)cached_interpreter_table.DSRA, 0); |
1097 | #else |
1098 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
1099 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
1100 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
1101 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
1102 | |
1103 | mov_reg32_reg32(rd1, rt1); |
1104 | mov_reg32_reg32(rd2, rt2); |
1105 | shrd_reg32_reg32_imm8(rd1, rd2, dst->f.r.sa); |
1106 | sar_reg32_imm8(rd2, dst->f.r.sa); |
1107 | if (dst->f.r.sa & 0x20) |
1108 | { |
1109 | mov_reg32_reg32(rd1, rd2); |
1110 | sar_reg32_imm8(rd2, 31); |
1111 | } |
1112 | #endif |
1113 | } |
1114 | |
1115 | void gendsll32(void) |
1116 | { |
1117 | #ifdef INTERPRET_DSLL32 |
1118 | gencallinterp((unsigned int)cached_interpreter_table.DSLL32, 0); |
1119 | #else |
1120 | int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); |
1121 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
1122 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
1123 | |
1124 | mov_reg32_reg32(rd2, rt1); |
1125 | shl_reg32_imm8(rd2, dst->f.r.sa); |
1126 | xor_reg32_reg32(rd1, rd1); |
1127 | #endif |
1128 | } |
1129 | |
1130 | void gendsrl32(void) |
1131 | { |
1132 | #ifdef INTERPRET_DSRL32 |
1133 | gencallinterp((unsigned int)cached_interpreter_table.DSRL32, 0); |
1134 | #else |
1135 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
1136 | int rd1 = allocate_64_register1_w((unsigned int *)dst->f.r.rd); |
1137 | int rd2 = allocate_64_register2_w((unsigned int *)dst->f.r.rd); |
1138 | |
1139 | mov_reg32_reg32(rd1, rt2); |
1140 | shr_reg32_imm8(rd1, dst->f.r.sa); |
1141 | xor_reg32_reg32(rd2, rd2); |
1142 | #endif |
1143 | } |
1144 | |
1145 | void gendsra32(void) |
1146 | { |
1147 | #ifdef INTERPRET_DSRA32 |
1148 | gencallinterp((unsigned int)cached_interpreter_table.DSRA32, 0); |
1149 | #else |
1150 | int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); |
1151 | int rd = allocate_register_w((unsigned int *)dst->f.r.rd); |
1152 | |
1153 | mov_reg32_reg32(rd, rt2); |
1154 | sar_reg32_imm8(rd, dst->f.r.sa); |
1155 | #endif |
1156 | } |
1157 | |