2 * $Id: sh4x86.in,v 1.8 2007-09-12 11:41:43 nkeynes Exp $
4 * SH4 => x86 translation. This version does no real optimization, it just
5 * outputs straight-line x86 code - it mainly exists to provide a baseline
6 * to test the optimizing versions against.
8 * Copyright (c) 2007 Nathan Keynes.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
27 #include "sh4/sh4core.h"
28 #include "sh4/sh4trans.h"
29 #include "sh4/x86op.h"
32 #define DEFAULT_BACKPATCH_SIZE 4096
35 * Struct to manage internal translation state. This state is not saved -
36 * it is only valid between calls to sh4_translate_begin_block() and
37 * sh4_translate_end_block()
39 struct sh4_x86_state {
40 gboolean in_delay_slot;
41 gboolean priv_checked; /* true if we've already checked the cpu mode. */
42 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
44 /* Allocated memory for the (block-wide) back-patch list */
45 uint32_t **backpatch_list;
46 uint32_t backpatch_posn;
47 uint32_t backpatch_size;
50 #define EXIT_DATA_ADDR_READ 0
51 #define EXIT_DATA_ADDR_WRITE 7
52 #define EXIT_ILLEGAL 14
53 #define EXIT_SLOT_ILLEGAL 21
54 #define EXIT_FPU_DISABLED 28
55 #define EXIT_SLOT_FPU_DISABLED 35
57 static struct sh4_x86_state sh4_x86;
61 sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
62 sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(uint32_t *);
66 static void sh4_x86_add_backpatch( uint8_t *ptr )
68 if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
69 sh4_x86.backpatch_size <<= 1;
70 sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list, sh4_x86.backpatch_size * sizeof(uint32_t *) );
71 assert( sh4_x86.backpatch_list != NULL );
73 sh4_x86.backpatch_list[sh4_x86.backpatch_posn++] = (uint32_t *)ptr;
76 static void sh4_x86_do_backpatch( uint8_t *reloc_base )
79 for( i=0; i<sh4_x86.backpatch_posn; i++ ) {
80 *sh4_x86.backpatch_list[i] += (reloc_base - ((uint8_t *)sh4_x86.backpatch_list[i]) - 4);
85 * Emit an instruction to load an SH4 reg into a real register
87 static inline void load_reg( int x86reg, int sh4reg )
91 OP(0x45 + (x86reg<<3));
92 OP(REG_OFFSET(r[sh4reg]));
95 static inline void load_reg16s( int x86reg, int sh4reg )
99 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
102 static inline void load_reg16u( int x86reg, int sh4reg )
106 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
110 #define load_spreg( x86reg, regoff ) MOV_sh4r_r32( regoff, x86reg )
111 #define store_spreg( x86reg, regoff ) MOV_r32_sh4r( x86reg, regoff )
113 * Emit an instruction to load an immediate value into a register
115 static inline void load_imm32( int x86reg, uint32_t value ) {
116 /* mov #value, reg */
122 * Emit an instruction to store an SH4 reg (RN)
124 void static inline store_reg( int x86reg, int sh4reg ) {
125 /* mov reg, [bp+n] */
127 OP(0x45 + (x86reg<<3));
128 OP(REG_OFFSET(r[sh4reg]));
131 #define load_fr_bank(bankreg) load_spreg( bankreg, REG_OFFSET(fr_bank))
134 * Load an FR register (single-precision floating point) into an integer x86
135 * register (eg for register-to-register moves)
137 void static inline load_fr( int bankreg, int x86reg, int frm )
139 OP(0x8B); OP(0x40+bankreg+(x86reg<<3)); OP((frm^1)<<2);
143 * Store an FR register (single-precision floating point) into an integer x86
144 * register (eg for register-to-register moves)
146 void static inline store_fr( int bankreg, int x86reg, int frn )
148 OP(0x89); OP(0x40+bankreg+(x86reg<<3)); OP((frn^1)<<2);
153 * Load a pointer to the back fp back into the specified x86 register. The
154 * bankreg must have been previously loaded with FPSCR.
157 static inline void load_xf_bank( int bankreg )
159 SHR_imm8_r32( (21 - 6), bankreg ); // Extract bit 21 then *64 for bank size
160 AND_imm8s_r32( 0x40, bankreg ); // Complete extraction
161 OP(0x8D); OP(0x44+(bankreg<<3)); OP(0x28+bankreg); OP(REG_OFFSET(fr)); // LEA [ebp+bankreg+disp], bankreg
165 * Push FPUL (as a 32-bit float) onto the FPU stack
167 static inline void push_fpul( )
169 OP(0xD9); OP(0x45); OP(R_FPUL);
173 * Pop FPUL (as a 32-bit float) from the FPU stack
175 static inline void pop_fpul( )
177 OP(0xD9); OP(0x5D); OP(R_FPUL);
181 * Push a 32-bit float onto the FPU stack, with bankreg previously loaded
182 * with the location of the current fp bank.
184 static inline void push_fr( int bankreg, int frm )
186 OP(0xD9); OP(0x40 + bankreg); OP((frm^1)<<2); // FLD.S [bankreg + frm^1*4]
190 * Pop a 32-bit float from the FPU stack and store it back into the fp bank,
191 * with bankreg previously loaded with the location of the current fp bank.
193 static inline void pop_fr( int bankreg, int frm )
195 OP(0xD9); OP(0x58 + bankreg); OP((frm^1)<<2); // FST.S [bankreg + frm^1*4]
199 * Push a 64-bit double onto the FPU stack, with bankreg previously loaded
200 * with the location of the current fp bank.
202 static inline void push_dr( int bankreg, int frm )
204 OP(0xDD); OP(0x40 + bankreg); OP(frm<<2); // FLD.D [bankreg + frm*4]
207 static inline void pop_dr( int bankreg, int frm )
209 OP(0xDD); OP(0x58 + bankreg); OP(frm<<2); // FST.D [bankreg + frm*4]
213 * Note: clobbers EAX to make the indirect call - this isn't usually
214 * a problem since the callee will usually clobber it anyway.
216 static inline void call_func0( void *ptr )
218 load_imm32(R_EAX, (uint32_t)ptr);
222 static inline void call_func1( void *ptr, int arg1 )
226 ADD_imm8s_r32( 4, R_ESP );
229 static inline void call_func2( void *ptr, int arg1, int arg2 )
234 ADD_imm8s_r32( 8, R_ESP );
238 * Write a double (64-bit) value into memory, with the first word in arg2a, and
239 * the second in arg2b
242 static inline void MEM_WRITE_DOUBLE( int addr, int arg2a, int arg2b )
244 ADD_imm8s_r32( 4, addr );
247 ADD_imm8s_r32( -4, addr );
250 call_func0(sh4_write_long);
251 ADD_imm8s_r32( 8, R_ESP );
252 call_func0(sh4_write_long);
253 ADD_imm8s_r32( 8, R_ESP );
257 * Read a double (64-bit) value from memory, writing the first word into arg2a
258 * and the second into arg2b. The addr must not be in EAX
261 static inline void MEM_READ_DOUBLE( int addr, int arg2a, int arg2b )
264 call_func0(sh4_read_long);
267 ADD_imm8s_r32( 4, addr );
269 call_func0(sh4_read_long);
270 ADD_imm8s_r32( 4, R_ESP );
271 MOV_r32_r32( R_EAX, arg2b );
275 /* Exception checks - Note that all exception checks will clobber EAX */
276 static void check_priv( )
278 if( !sh4_x86.priv_checked ) {
279 sh4_x86.priv_checked = TRUE;
280 load_spreg( R_EAX, R_SR );
281 AND_imm32_r32( SR_MD, R_EAX );
282 if( sh4_x86.in_delay_slot ) {
283 JE_exit( EXIT_SLOT_ILLEGAL );
285 JE_exit( EXIT_ILLEGAL );
290 static void check_fpuen( )
292 if( !sh4_x86.fpuen_checked ) {
293 sh4_x86.fpuen_checked = TRUE;
294 load_spreg( R_EAX, R_SR );
295 AND_imm32_r32( SR_FD, R_EAX );
296 if( sh4_x86.in_delay_slot ) {
297 JNE_exit(EXIT_SLOT_FPU_DISABLED);
299 JNE_exit(EXIT_FPU_DISABLED);
304 static void check_ralign16( int x86reg )
306 TEST_imm32_r32( 0x00000001, x86reg );
307 JNE_exit(EXIT_DATA_ADDR_READ);
310 static void check_walign16( int x86reg )
312 TEST_imm32_r32( 0x00000001, x86reg );
313 JNE_exit(EXIT_DATA_ADDR_WRITE);
316 static void check_ralign32( int x86reg )
318 TEST_imm32_r32( 0x00000003, x86reg );
319 JNE_exit(EXIT_DATA_ADDR_READ);
321 static void check_walign32( int x86reg )
323 TEST_imm32_r32( 0x00000003, x86reg );
324 JNE_exit(EXIT_DATA_ADDR_WRITE);
329 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
330 #define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
331 #define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
332 #define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
333 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
334 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
335 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
337 #define RAISE_EXCEPTION( exc ) call_func1(sh4_raise_exception, exc);
338 #define SLOTILLEGAL() RAISE_EXCEPTION(EXC_SLOT_ILLEGAL); return 1
343 * Emit the 'start of block' assembly. Sets up the stack frame and save
346 void sh4_translate_begin_block()
350 load_imm32( R_EBP, (uint32_t)&sh4r );
353 XOR_r32_r32(R_ESI, R_ESI);
355 sh4_x86.in_delay_slot = FALSE;
356 sh4_x86.priv_checked = FALSE;
357 sh4_x86.fpuen_checked = FALSE;
358 sh4_x86.backpatch_posn = 0;
362 * Exit the block early (ie branch out), conditionally or otherwise
366 store_spreg( R_EDI, REG_OFFSET(pc) );
367 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
368 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
370 ADD_r32_r32( R_EAX, R_ECX );
371 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
372 load_imm32( R_EAX, 1 );
380 * Flush any open regs back to memory, restore SI/DI/, update PC, etc
382 void sh4_translate_end_block( sh4addr_t pc ) {
383 assert( !sh4_x86.in_delay_slot ); // should never stop here
384 // Normal termination - save PC, cycle count
387 uint8_t *end_ptr = xlat_output;
388 // Exception termination. Jump block for various exception codes:
389 PUSH_imm32( EXC_DATA_ADDR_READ );
390 JMP_rel8( 33, target1 );
391 PUSH_imm32( EXC_DATA_ADDR_WRITE );
392 JMP_rel8( 26, target2 );
393 PUSH_imm32( EXC_ILLEGAL );
394 JMP_rel8( 19, target3 );
395 PUSH_imm32( EXC_SLOT_ILLEGAL );
396 JMP_rel8( 12, target4 );
397 PUSH_imm32( EXC_FPU_DISABLED );
398 JMP_rel8( 5, target5 );
399 PUSH_imm32( EXC_SLOT_FPU_DISABLED );
406 load_spreg( R_ECX, REG_OFFSET(pc) );
407 ADD_r32_r32( R_ESI, R_ECX );
408 ADD_r32_r32( R_ESI, R_ECX );
409 store_spreg( R_ECX, REG_OFFSET(pc) );
410 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
411 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
413 ADD_r32_r32( R_EAX, R_ECX );
414 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
416 load_imm32( R_EAX, (uint32_t)sh4_raise_exception ); // 6
417 CALL_r32( R_EAX ); // 2
421 sh4_x86_do_backpatch( end_ptr );
425 * Translate a single instruction. Delayed branches are handled specially
426 * by translating both branch and delayed instruction as a single unit (as
429 * @return true if the instruction marks the end of a basic block
432 uint32_t sh4_x86_translate_instruction( uint32_t pc )
434 uint16_t ir = sh4_read_word( pc );
439 load_reg( R_EAX, Rm );
440 load_reg( R_ECX, Rn );
441 ADD_r32_r32( R_EAX, R_ECX );
442 store_reg( R_ECX, Rn );
445 load_reg( R_EAX, Rn );
446 ADD_imm8s_r32( imm, R_EAX );
447 store_reg( R_EAX, Rn );
450 load_reg( R_EAX, Rm );
451 load_reg( R_ECX, Rn );
453 ADC_r32_r32( R_EAX, R_ECX );
454 store_reg( R_ECX, Rn );
458 load_reg( R_EAX, Rm );
459 load_reg( R_ECX, Rn );
460 ADD_r32_r32( R_EAX, R_ECX );
461 store_reg( R_ECX, Rn );
465 load_reg( R_EAX, Rm );
466 load_reg( R_ECX, Rn );
467 AND_r32_r32( R_EAX, R_ECX );
468 store_reg( R_ECX, Rn );
471 load_reg( R_EAX, 0 );
472 AND_imm32_r32(imm, R_EAX);
473 store_reg( R_EAX, 0 );
475 AND.B #imm, @(R0, GBR) {:
476 load_reg( R_EAX, 0 );
477 load_spreg( R_ECX, R_GBR );
478 ADD_r32_r32( R_EAX, R_ECX );
479 MEM_READ_BYTE( R_ECX, R_EAX );
480 AND_imm32_r32(imm, R_ECX );
481 MEM_WRITE_BYTE( R_ECX, R_EAX );
484 load_reg( R_EAX, Rm );
485 load_reg( R_ECX, Rn );
486 CMP_r32_r32( R_EAX, R_ECX );
490 load_reg( R_EAX, 0 );
491 CMP_imm8s_r32(imm, R_EAX);
495 load_reg( R_EAX, Rm );
496 load_reg( R_ECX, Rn );
497 CMP_r32_r32( R_EAX, R_ECX );
501 load_reg( R_EAX, Rm );
502 load_reg( R_ECX, Rn );
503 CMP_r32_r32( R_EAX, R_ECX );
507 load_reg( R_EAX, Rm );
508 load_reg( R_ECX, Rn );
509 CMP_r32_r32( R_EAX, R_ECX );
513 load_reg( R_EAX, Rm );
514 load_reg( R_ECX, Rn );
515 CMP_r32_r32( R_EAX, R_ECX );
519 load_reg( R_EAX, Rn );
520 CMP_imm8s_r32( 0, R_EAX );
524 load_reg( R_EAX, Rn );
525 CMP_imm8s_r32( 0, R_EAX );
529 load_reg( R_EAX, Rm );
530 load_reg( R_ECX, Rn );
531 XOR_r32_r32( R_ECX, R_EAX );
532 TEST_r8_r8( R_AL, R_AL );
533 JE_rel8(13, target1);
534 TEST_r8_r8( R_AH, R_AH ); // 2
536 SHR_imm8_r32( 16, R_EAX ); // 3
537 TEST_r8_r8( R_AL, R_AL ); // 2
539 TEST_r8_r8( R_AH, R_AH ); // 2
546 load_reg( R_EAX, Rm );
547 load_reg( R_ECX, Rm );
548 SHR_imm8_r32( 31, R_EAX );
549 SHR_imm8_r32( 31, R_ECX );
550 store_spreg( R_EAX, R_M );
551 store_spreg( R_ECX, R_Q );
552 CMP_r32_r32( R_EAX, R_ECX );
556 XOR_r32_r32( R_EAX, R_EAX );
557 store_spreg( R_EAX, R_Q );
558 store_spreg( R_EAX, R_M );
559 store_spreg( R_EAX, R_T );
562 load_reg( R_ECX, Rn );
564 RCL1_r32( R_ECX ); // OP2
565 SETC_r32( R_EDX ); // Q
566 load_spreg( R_EAX, R_Q );
567 CMP_sh4r_r32( R_M, R_EAX );
569 ADD_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
570 JMP_rel8(3, mqnotequal);
572 SUB_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
573 JMP_TARGET(mqnotequal);
577 load_reg( R_EAX, Rm );
578 load_reg( R_ECX, Rn );
580 store_spreg( R_EDX, R_MACH );
581 store_spreg( R_EAX, R_MACL );
584 load_reg( R_EAX, Rm );
585 load_reg( R_ECX, Rn );
587 store_spreg( R_EDX, R_MACH );
588 store_spreg( R_EAX, R_MACL );
591 load_reg( R_EAX, Rn );
592 ADD_imm8s_r32( -1, Rn );
593 store_reg( R_EAX, Rn );
597 load_reg( R_EAX, Rm );
598 MOVSX_r8_r32( R_EAX, R_EAX );
599 store_reg( R_EAX, Rn );
602 load_reg( R_EAX, Rm );
603 MOVSX_r16_r32( R_EAX, R_EAX );
604 store_reg( R_EAX, Rn );
607 load_reg( R_EAX, Rm );
608 MOVZX_r8_r32( R_EAX, R_EAX );
609 store_reg( R_EAX, Rn );
612 load_reg( R_EAX, Rm );
613 MOVZX_r16_r32( R_EAX, R_EAX );
614 store_reg( R_EAX, Rn );
616 MAC.L @Rm+, @Rn+ {: :}
617 MAC.W @Rm+, @Rn+ {: :}
619 load_spreg( R_EAX, R_T );
620 store_reg( R_EAX, Rn );
623 load_reg( R_EAX, Rm );
624 load_reg( R_ECX, Rn );
626 store_spreg( R_EAX, R_MACL );
629 load_reg16s( R_EAX, Rm );
630 load_reg16s( R_ECX, Rn );
632 store_spreg( R_EAX, R_MACL );
635 load_reg16u( R_EAX, Rm );
636 load_reg16u( R_ECX, Rn );
638 store_spreg( R_EAX, R_MACL );
641 load_reg( R_EAX, Rm );
643 store_reg( R_EAX, Rn );
646 load_reg( R_EAX, Rm );
647 XOR_r32_r32( R_ECX, R_ECX );
649 SBB_r32_r32( R_EAX, R_ECX );
650 store_reg( R_ECX, Rn );
654 load_reg( R_EAX, Rm );
656 store_reg( R_EAX, Rn );
659 load_reg( R_EAX, Rm );
660 load_reg( R_ECX, Rn );
661 OR_r32_r32( R_EAX, R_ECX );
662 store_reg( R_ECX, Rn );
665 load_reg( R_EAX, 0 );
666 OR_imm32_r32(imm, R_EAX);
667 store_reg( R_EAX, 0 );
669 OR.B #imm, @(R0, GBR) {:
670 load_reg( R_EAX, 0 );
671 load_spreg( R_ECX, R_GBR );
672 ADD_r32_r32( R_EAX, R_ECX );
673 MEM_READ_BYTE( R_ECX, R_EAX );
674 OR_imm32_r32(imm, R_ECX );
675 MEM_WRITE_BYTE( R_ECX, R_EAX );
678 load_reg( R_EAX, Rn );
681 store_reg( R_EAX, Rn );
685 load_reg( R_EAX, Rn );
688 store_reg( R_EAX, Rn );
692 load_reg( R_EAX, Rn );
694 store_reg( R_EAX, Rn );
698 load_reg( R_EAX, Rn );
700 store_reg( R_EAX, Rn );
704 /* Annoyingly enough, not directly convertible */
705 load_reg( R_EAX, Rn );
706 load_reg( R_ECX, Rm );
707 CMP_imm32_r32( 0, R_ECX );
710 NEG_r32( R_ECX ); // 2
711 AND_imm8_r8( 0x1F, R_CL ); // 3
712 SAR_r32_CL( R_EAX ); // 2
713 JMP_rel8(5, end); // 2
715 AND_imm8_r8( 0x1F, R_CL ); // 3
716 SHL_r32_CL( R_EAX ); // 2
718 store_reg( R_EAX, Rn );
721 load_reg( R_EAX, Rn );
722 load_reg( R_ECX, Rm );
724 MOV_r32_r32( R_EAX, R_EDX );
728 CMP_imm8s_r32( 0, R_ECX );
729 CMOVAE_r32_r32( R_EDX, R_EAX );
730 store_reg( R_EAX, Rn );
733 load_reg( R_EAX, Rn );
735 store_reg( R_EAX, Rn );
738 load_reg( R_EAX, Rn );
740 store_reg( R_EAX, Rn );
743 load_reg( R_EAX, Rn );
745 store_reg( R_EAX, Rn );
748 load_reg( R_EAX, Rn );
749 SHL_imm8_r32( 2, R_EAX );
750 store_reg( R_EAX, Rn );
753 load_reg( R_EAX, Rn );
754 SHL_imm8_r32( 8, R_EAX );
755 store_reg( R_EAX, Rn );
758 load_reg( R_EAX, Rn );
759 SHL_imm8_r32( 16, R_EAX );
760 store_reg( R_EAX, Rn );
763 load_reg( R_EAX, Rn );
765 store_reg( R_EAX, Rn );
768 load_reg( R_EAX, Rn );
769 SHR_imm8_r32( 2, R_EAX );
770 store_reg( R_EAX, Rn );
773 load_reg( R_EAX, Rn );
774 SHR_imm8_r32( 8, R_EAX );
775 store_reg( R_EAX, Rn );
778 load_reg( R_EAX, Rn );
779 SHR_imm8_r32( 16, R_EAX );
780 store_reg( R_EAX, Rn );
783 load_reg( R_EAX, Rm );
784 load_reg( R_ECX, Rn );
785 SUB_r32_r32( R_EAX, R_ECX );
786 store_reg( R_ECX, Rn );
789 load_reg( R_EAX, Rm );
790 load_reg( R_ECX, Rn );
792 SBB_r32_r32( R_EAX, R_ECX );
793 store_reg( R_ECX, Rn );
796 load_reg( R_EAX, Rm );
797 load_reg( R_ECX, Rn );
798 SUB_r32_r32( R_EAX, R_ECX );
799 store_reg( R_ECX, Rn );
803 load_reg( R_EAX, Rm );
804 XCHG_r8_r8( R_AL, R_AH );
805 store_reg( R_EAX, Rn );
808 load_reg( R_EAX, Rm );
809 MOV_r32_r32( R_EAX, R_ECX );
810 SHL_imm8_r32( 16, R_ECX );
811 SHR_imm8_r32( 16, R_EAX );
812 OR_r32_r32( R_EAX, R_ECX );
813 store_reg( R_ECX, Rn );
816 load_reg( R_ECX, Rn );
817 MEM_READ_BYTE( R_ECX, R_EAX );
818 TEST_r8_r8( R_AL, R_AL );
820 OR_imm8_r8( 0x80, R_AL );
821 MEM_WRITE_BYTE( R_ECX, R_EAX );
824 load_reg( R_EAX, Rm );
825 load_reg( R_ECX, Rn );
826 TEST_r32_r32( R_EAX, R_ECX );
830 load_reg( R_EAX, 0 );
831 TEST_imm32_r32( imm, R_EAX );
834 TST.B #imm, @(R0, GBR) {:
836 load_reg( R_ECX, R_GBR);
837 ADD_r32_r32( R_EAX, R_ECX );
838 MEM_READ_BYTE( R_ECX, R_EAX );
839 TEST_imm8_r8( imm, R_EAX );
843 load_reg( R_EAX, Rm );
844 load_reg( R_ECX, Rn );
845 XOR_r32_r32( R_EAX, R_ECX );
846 store_reg( R_ECX, Rn );
849 load_reg( R_EAX, 0 );
850 XOR_imm32_r32( imm, R_EAX );
851 store_reg( R_EAX, 0 );
853 XOR.B #imm, @(R0, GBR) {:
854 load_reg( R_EAX, 0 );
855 load_spreg( R_ECX, R_GBR );
856 ADD_r32_r32( R_EAX, R_ECX );
857 MEM_READ_BYTE( R_ECX, R_EAX );
858 XOR_imm32_r32( imm, R_EAX );
859 MEM_WRITE_BYTE( R_ECX, R_EAX );
862 load_reg( R_EAX, Rm );
863 MOV_r32_r32( R_EAX, R_ECX );
864 SHR_imm8_r32( 16, R_EAX );
865 SHL_imm8_r32( 16, R_ECX );
866 OR_r32_r32( R_EAX, R_ECX );
867 store_reg( R_ECX, Rn );
870 /* Data move instructions */
872 load_reg( R_EAX, Rm );
873 store_reg( R_EAX, Rn );
876 load_imm32( R_EAX, imm );
877 store_reg( R_EAX, Rn );
880 load_reg( R_EAX, Rm );
881 load_reg( R_ECX, Rn );
882 MEM_WRITE_BYTE( R_ECX, R_EAX );
885 load_reg( R_EAX, Rm );
886 load_reg( R_ECX, Rn );
887 ADD_imm8s_r32( -1, Rn );
888 store_reg( R_ECX, Rn );
889 MEM_WRITE_BYTE( R_ECX, R_EAX );
891 MOV.B Rm, @(R0, Rn) {:
892 load_reg( R_EAX, 0 );
893 load_reg( R_ECX, Rn );
894 ADD_r32_r32( R_EAX, R_ECX );
895 load_reg( R_EAX, Rm );
896 MEM_WRITE_BYTE( R_ECX, R_EAX );
898 MOV.B R0, @(disp, GBR) {:
899 load_reg( R_EAX, 0 );
900 load_spreg( R_ECX, R_GBR );
901 ADD_imm32_r32( disp, R_ECX );
902 MEM_WRITE_BYTE( R_ECX, R_EAX );
904 MOV.B R0, @(disp, Rn) {:
905 load_reg( R_EAX, 0 );
906 load_reg( R_ECX, Rn );
907 ADD_imm32_r32( disp, R_ECX );
908 MEM_WRITE_BYTE( R_ECX, R_EAX );
911 load_reg( R_ECX, Rm );
912 MEM_READ_BYTE( R_ECX, R_EAX );
913 store_reg( R_ECX, Rn );
916 load_reg( R_ECX, Rm );
917 MOV_r32_r32( R_ECX, R_EAX );
918 ADD_imm8s_r32( 1, R_EAX );
919 store_reg( R_EAX, Rm );
920 MEM_READ_BYTE( R_ECX, R_EAX );
921 store_reg( R_EAX, Rn );
923 MOV.B @(R0, Rm), Rn {:
924 load_reg( R_EAX, 0 );
925 load_reg( R_ECX, Rm );
926 ADD_r32_r32( R_EAX, R_ECX );
927 MEM_READ_BYTE( R_ECX, R_EAX );
928 store_reg( R_EAX, Rn );
930 MOV.B @(disp, GBR), R0 {:
931 load_spreg( R_ECX, R_GBR );
932 ADD_imm32_r32( disp, R_ECX );
933 MEM_READ_BYTE( R_ECX, R_EAX );
934 store_reg( R_EAX, 0 );
936 MOV.B @(disp, Rm), R0 {:
937 load_reg( R_ECX, Rm );
938 ADD_imm32_r32( disp, R_ECX );
939 MEM_READ_BYTE( R_ECX, R_EAX );
940 store_reg( R_EAX, 0 );
943 load_reg( R_EAX, Rm );
944 load_reg( R_ECX, Rn );
945 check_walign32(R_ECX);
946 MEM_WRITE_LONG( R_ECX, R_EAX );
949 load_reg( R_EAX, Rm );
950 load_reg( R_ECX, Rn );
951 check_walign32( R_ECX );
952 ADD_imm8s_r32( -4, R_ECX );
953 store_reg( R_ECX, Rn );
954 MEM_WRITE_LONG( R_ECX, R_EAX );
956 MOV.L Rm, @(R0, Rn) {:
957 load_reg( R_EAX, 0 );
958 load_reg( R_ECX, Rn );
959 ADD_r32_r32( R_EAX, R_ECX );
960 check_walign32( R_ECX );
961 load_reg( R_EAX, Rm );
962 MEM_WRITE_LONG( R_ECX, R_EAX );
964 MOV.L R0, @(disp, GBR) {:
965 load_spreg( R_ECX, R_GBR );
966 load_reg( R_EAX, 0 );
967 ADD_imm32_r32( disp, R_ECX );
968 check_walign32( R_ECX );
969 MEM_WRITE_LONG( R_ECX, R_EAX );
971 MOV.L Rm, @(disp, Rn) {:
972 load_reg( R_ECX, Rn );
973 load_reg( R_EAX, Rm );
974 ADD_imm32_r32( disp, R_ECX );
975 check_walign32( R_ECX );
976 MEM_WRITE_LONG( R_ECX, R_EAX );
979 load_reg( R_ECX, Rm );
980 check_ralign32( R_ECX );
981 MEM_READ_LONG( R_ECX, R_EAX );
982 store_reg( R_EAX, Rn );
985 load_reg( R_EAX, Rm );
986 check_ralign32( R_ECX );
987 MOV_r32_r32( R_EAX, R_ECX );
988 ADD_imm8s_r32( 4, R_EAX );
989 store_reg( R_EAX, Rm );
990 MEM_READ_LONG( R_ECX, R_EAX );
991 store_reg( R_EAX, Rn );
993 MOV.L @(R0, Rm), Rn {:
994 load_reg( R_EAX, 0 );
995 load_reg( R_ECX, Rm );
996 ADD_r32_r32( R_EAX, R_ECX );
997 check_ralign32( R_ECX );
998 MEM_READ_LONG( R_ECX, R_EAX );
999 store_reg( R_EAX, Rn );
1001 MOV.L @(disp, GBR), R0 {:
1002 load_spreg( R_ECX, R_GBR );
1003 ADD_imm32_r32( disp, R_ECX );
1004 check_ralign32( R_ECX );
1005 MEM_READ_LONG( R_ECX, R_EAX );
1006 store_reg( R_EAX, 0 );
1008 MOV.L @(disp, PC), Rn {:
1009 if( sh4_x86.in_delay_slot ) {
1012 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1013 MEM_READ_LONG( R_ECX, R_EAX );
1014 store_reg( R_EAX, 0 );
1017 MOV.L @(disp, Rm), Rn {:
1018 load_reg( R_ECX, Rm );
1019 ADD_imm8s_r32( disp, R_ECX );
1020 check_ralign32( R_ECX );
1021 MEM_READ_LONG( R_ECX, R_EAX );
1022 store_reg( R_EAX, Rn );
1025 load_reg( R_ECX, Rn );
1026 check_walign16( R_ECX );
1027 MEM_READ_WORD( R_ECX, R_EAX );
1028 store_reg( R_EAX, Rn );
1031 load_reg( R_ECX, Rn );
1032 check_walign16( R_ECX );
1033 load_reg( R_EAX, Rm );
1034 ADD_imm8s_r32( -2, R_ECX );
1035 MEM_WRITE_WORD( R_ECX, R_EAX );
1037 MOV.W Rm, @(R0, Rn) {:
1038 load_reg( R_EAX, 0 );
1039 load_reg( R_ECX, Rn );
1040 ADD_r32_r32( R_EAX, R_ECX );
1041 check_walign16( R_ECX );
1042 load_reg( R_EAX, Rm );
1043 MEM_WRITE_WORD( R_ECX, R_EAX );
1045 MOV.W R0, @(disp, GBR) {:
1046 load_spreg( R_ECX, R_GBR );
1047 load_reg( R_EAX, 0 );
1048 ADD_imm32_r32( disp, R_ECX );
1049 check_walign16( R_ECX );
1050 MEM_WRITE_WORD( R_ECX, R_EAX );
1052 MOV.W R0, @(disp, Rn) {:
1053 load_reg( R_ECX, Rn );
1054 load_reg( R_EAX, 0 );
1055 ADD_imm32_r32( disp, R_ECX );
1056 check_walign16( R_ECX );
1057 MEM_WRITE_WORD( R_ECX, R_EAX );
1060 load_reg( R_ECX, Rm );
1061 check_ralign16( R_ECX );
1062 MEM_READ_WORD( R_ECX, R_EAX );
1063 store_reg( R_EAX, Rn );
1066 load_reg( R_EAX, Rm );
1067 check_ralign16( R_EAX );
1068 MOV_r32_r32( R_EAX, R_ECX );
1069 ADD_imm8s_r32( 2, R_EAX );
1070 store_reg( R_EAX, Rm );
1071 MEM_READ_WORD( R_ECX, R_EAX );
1072 store_reg( R_EAX, Rn );
1074 MOV.W @(R0, Rm), Rn {:
1075 load_reg( R_EAX, 0 );
1076 load_reg( R_ECX, Rm );
1077 ADD_r32_r32( R_EAX, R_ECX );
1078 check_ralign16( R_ECX );
1079 MEM_READ_WORD( R_ECX, R_EAX );
1080 store_reg( R_EAX, Rn );
1082 MOV.W @(disp, GBR), R0 {:
1083 load_spreg( R_ECX, R_GBR );
1084 ADD_imm32_r32( disp, R_ECX );
1085 check_ralign16( R_ECX );
1086 MEM_READ_WORD( R_ECX, R_EAX );
1087 store_reg( R_EAX, 0 );
1089 MOV.W @(disp, PC), Rn {:
1090 if( sh4_x86.in_delay_slot ) {
1093 load_imm32( R_ECX, pc + disp + 4 );
1094 MEM_READ_WORD( R_ECX, R_EAX );
1095 store_reg( R_EAX, Rn );
1098 MOV.W @(disp, Rm), R0 {:
1099 load_reg( R_ECX, Rm );
1100 ADD_imm32_r32( disp, R_ECX );
1101 check_ralign16( R_ECX );
1102 MEM_READ_WORD( R_ECX, R_EAX );
1103 store_reg( R_EAX, 0 );
1105 MOVA @(disp, PC), R0 {:
1106 if( sh4_x86.in_delay_slot ) {
1109 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1110 store_reg( R_ECX, 0 );
1114 load_reg( R_EAX, 0 );
1115 load_reg( R_ECX, Rn );
1116 check_walign32( R_ECX );
1117 MEM_WRITE_LONG( R_ECX, R_EAX );
1120 /* Control transfer instructions */
1122 if( sh4_x86.in_delay_slot ) {
1125 load_imm32( R_EDI, pc + 2 );
1126 CMP_imm8s_sh4r( 0, R_T );
1127 JNE_rel8( 5, nottaken );
1128 load_imm32( R_EDI, disp + pc + 4 );
1129 JMP_TARGET(nottaken);
1135 if( sh4_x86.in_delay_slot ) {
1138 load_imm32( R_EDI, pc + 2 );
1139 CMP_imm8s_sh4r( 0, R_T );
1140 JNE_rel8( 5, nottaken );
1141 load_imm32( R_EDI, disp + pc + 4 );
1142 JMP_TARGET(nottaken);
1143 sh4_x86.in_delay_slot = TRUE;
1149 if( sh4_x86.in_delay_slot ) {
1152 load_imm32( R_EDI, disp + pc + 4 );
1153 sh4_x86.in_delay_slot = TRUE;
1159 if( sh4_x86.in_delay_slot ) {
1162 load_reg( R_EDI, Rn );
1163 sh4_x86.in_delay_slot = TRUE;
1169 if( sh4_x86.in_delay_slot ) {
1172 load_imm32( R_EAX, pc + 4 );
1173 store_spreg( R_EAX, R_PR );
1174 load_imm32( R_EDI, disp + pc + 4 );
1175 sh4_x86.in_delay_slot = TRUE;
1181 if( sh4_x86.in_delay_slot ) {
1184 load_imm32( R_EAX, pc + 4 );
1185 store_spreg( R_EAX, R_PR );
1186 load_reg( R_EDI, Rn );
1187 ADD_r32_r32( R_EAX, R_EDI );
1188 sh4_x86.in_delay_slot = TRUE;
1194 if( sh4_x86.in_delay_slot ) {
1197 load_imm32( R_EDI, pc + 2 );
1198 CMP_imm8s_sh4r( 0, R_T );
1199 JE_rel8( 5, nottaken );
1200 load_imm32( R_EDI, disp + pc + 4 );
1201 JMP_TARGET(nottaken);
1207 if( sh4_x86.in_delay_slot ) {
1210 load_imm32( R_EDI, pc + 2 );
1211 CMP_imm8s_sh4r( 0, R_T );
1212 JE_rel8( 5, nottaken );
1213 load_imm32( R_EDI, disp + pc + 4 );
1214 JMP_TARGET(nottaken);
1215 sh4_x86.in_delay_slot = TRUE;
1221 if( sh4_x86.in_delay_slot ) {
1224 load_reg( R_EDI, Rn );
1225 sh4_x86.in_delay_slot = TRUE;
1231 if( sh4_x86.in_delay_slot ) {
1234 load_imm32( R_EAX, pc + 4 );
1235 store_spreg( R_EAX, R_PR );
1236 load_reg( R_EDI, Rn );
1237 sh4_x86.in_delay_slot = TRUE;
1244 if( sh4_x86.in_delay_slot ) {
1247 load_spreg( R_EDI, R_PR );
1248 load_spreg( R_EAX, R_SSR );
1249 call_func1( sh4_write_sr, R_EAX );
1250 sh4_x86.in_delay_slot = TRUE;
1251 sh4_x86.priv_checked = FALSE;
1252 sh4_x86.fpuen_checked = FALSE;
1258 if( sh4_x86.in_delay_slot ) {
1261 load_spreg( R_EDI, R_PR );
1262 sh4_x86.in_delay_slot = TRUE;
1268 if( sh4_x86.in_delay_slot ) {
1272 RAISE_EXCEPTION(EXC_TRAP);
1276 if( sh4_x86.in_delay_slot ) {
1277 RAISE_EXCEPTION(EXC_SLOT_ILLEGAL);
1279 RAISE_EXCEPTION(EXC_ILLEGAL);
1285 XOR_r32_r32(R_EAX, R_EAX);
1286 store_spreg( R_EAX, R_MACL );
1287 store_spreg( R_EAX, R_MACH );
1306 /* Floating point moves */
1308 /* As horrible as this looks, it's actually covering 5 separate cases:
1309 * 1. 32-bit fr-to-fr (PR=0)
1310 * 2. 64-bit dr-to-dr (PR=1, FRm&1 == 0, FRn&1 == 0 )
1311 * 3. 64-bit dr-to-xd (PR=1, FRm&1 == 0, FRn&1 == 1 )
1312 * 4. 64-bit xd-to-dr (PR=1, FRm&1 == 1, FRn&1 == 0 )
1313 * 5. 64-bit xd-to-xd (PR=1, FRm&1 == 1, FRn&1 == 1 )
1316 load_spreg( R_ECX, R_FPSCR );
1317 load_fr_bank( R_EDX );
1318 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1319 JNE_rel8(8, doublesize);
1320 load_fr( R_EDX, R_EAX, FRm ); // PR=0 branch
1321 store_fr( R_EDX, R_EAX, FRn );
1324 JMP_TARGET(doublesize);
1325 load_xf_bank( R_ECX );
1326 load_fr( R_ECX, R_EAX, FRm-1 );
1328 load_fr( R_ECX, R_EDX, FRm );
1329 store_fr( R_ECX, R_EAX, FRn-1 );
1330 store_fr( R_ECX, R_EDX, FRn );
1331 } else /* FRn&1 == 0 */ {
1332 load_fr( R_ECX, R_ECX, FRm );
1333 store_fr( R_EDX, R_EAX, FRn-1 );
1334 store_fr( R_EDX, R_ECX, FRn );
1337 } else /* FRm&1 == 0 */ {
1340 load_xf_bank( R_ECX );
1341 load_fr( R_EDX, R_EAX, FRm );
1342 load_fr( R_EDX, R_EDX, FRm+1 );
1343 store_fr( R_ECX, R_EAX, FRn-1 );
1344 store_fr( R_ECX, R_EDX, FRn );
1346 } else /* FRn&1 == 0 */ {
1348 load_fr( R_EDX, R_EAX, FRm );
1349 load_fr( R_EDX, R_ECX, FRm+1 );
1350 store_fr( R_EDX, R_EAX, FRn );
1351 store_fr( R_EDX, R_ECX, FRn+1 );
1358 load_reg( R_EDX, Rn );
1359 check_walign32( R_EDX );
1360 load_spreg( R_ECX, R_FPSCR );
1361 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1362 JNE_rel8(20, doublesize);
1363 load_fr_bank( R_ECX );
1364 load_fr( R_ECX, R_EAX, FRm );
1365 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1367 JMP_rel8( 46, end );
1368 JMP_TARGET(doublesize);
1369 load_xf_bank( R_ECX );
1370 load_fr( R_ECX, R_EAX, FRm&0x0E );
1371 load_fr( R_ECX, R_ECX, FRm|0x01 );
1372 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1375 JMP_rel8( 39, end );
1376 JMP_TARGET(doublesize);
1377 load_fr_bank( R_ECX );
1378 load_fr( R_ECX, R_EAX, FRm&0x0E );
1379 load_fr( R_ECX, R_ECX, FRm|0x01 );
1380 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1386 load_reg( R_EDX, Rm );
1387 check_ralign32( R_EDX );
1388 load_spreg( R_ECX, R_FPSCR );
1389 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1390 JNE_rel8(19, doublesize);
1391 MEM_READ_LONG( R_EDX, R_EAX );
1392 load_fr_bank( R_ECX );
1393 store_fr( R_ECX, R_EAX, FRn );
1396 JMP_TARGET(doublesize);
1397 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1398 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1399 load_xf_bank( R_ECX );
1400 store_fr( R_ECX, R_EAX, FRn&0x0E );
1401 store_fr( R_ECX, R_EDX, FRn|0x01 );
1405 JMP_TARGET(doublesize);
1406 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1407 load_fr_bank( R_ECX );
1408 store_fr( R_ECX, R_EAX, FRn&0x0E );
1409 store_fr( R_ECX, R_EDX, FRn|0x01 );
1415 load_reg( R_EDX, Rn );
1416 check_walign32( R_EDX );
1417 load_spreg( R_ECX, R_FPSCR );
1418 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1419 JNE_rel8(20, doublesize);
1420 load_fr_bank( R_ECX );
1421 load_fr( R_ECX, R_EAX, FRm );
1422 ADD_imm8s_r32(-4,R_EDX);
1423 store_reg( R_EDX, Rn );
1424 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1426 JMP_rel8( 46, end );
1427 JMP_TARGET(doublesize);
1428 load_xf_bank( R_ECX );
1429 load_fr( R_ECX, R_EAX, FRm&0x0E );
1430 load_fr( R_ECX, R_ECX, FRm|0x01 );
1431 ADD_imm8s_r32(-8,R_EDX);
1432 store_reg( R_EDX, Rn );
1433 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1436 JMP_rel8( 39, end );
1437 JMP_TARGET(doublesize);
1438 load_fr_bank( R_ECX );
1439 load_fr( R_ECX, R_EAX, FRm&0x0E );
1440 load_fr( R_ECX, R_ECX, FRm|0x01 );
1441 ADD_imm8s_r32(-8,R_EDX);
1442 store_reg( R_EDX, Rn );
1443 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1449 load_reg( R_EDX, Rm );
1450 check_ralign32( R_EDX );
1451 MOV_r32_r32( R_EDX, R_EAX );
1452 load_spreg( R_ECX, R_FPSCR );
1453 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1454 JNE_rel8(25, doublesize);
1455 ADD_imm8s_r32( 4, R_EAX );
1456 store_reg( R_EAX, Rm );
1457 MEM_READ_LONG( R_EDX, R_EAX );
1458 load_fr_bank( R_ECX );
1459 store_fr( R_ECX, R_EAX, FRn );
1462 JMP_TARGET(doublesize);
1463 ADD_imm8s_r32( 8, R_EAX );
1464 store_reg(R_EAX, Rm);
1465 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1466 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1467 load_xf_bank( R_ECX );
1468 store_fr( R_ECX, R_EAX, FRn&0x0E );
1469 store_fr( R_ECX, R_EDX, FRn|0x01 );
1473 ADD_imm8s_r32( 8, R_EAX );
1474 store_reg(R_EAX, Rm);
1475 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1476 load_fr_bank( R_ECX );
1477 store_fr( R_ECX, R_EAX, FRn&0x0E );
1478 store_fr( R_ECX, R_EDX, FRn|0x01 );
1482 FMOV FRm, @(R0, Rn) {:
1484 load_reg( R_EDX, Rn );
1485 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
1486 check_walign32( R_EDX );
1487 load_spreg( R_ECX, R_FPSCR );
1488 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1489 JNE_rel8(20, doublesize);
1490 load_fr_bank( R_ECX );
1491 load_fr( R_ECX, R_EAX, FRm );
1492 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1494 JMP_rel8( 46, end );
1495 JMP_TARGET(doublesize);
1496 load_xf_bank( R_ECX );
1497 load_fr( R_ECX, R_EAX, FRm&0x0E );
1498 load_fr( R_ECX, R_ECX, FRm|0x01 );
1499 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1502 JMP_rel8( 39, end );
1503 JMP_TARGET(doublesize);
1504 load_fr_bank( R_ECX );
1505 load_fr( R_ECX, R_EAX, FRm&0x0E );
1506 load_fr( R_ECX, R_ECX, FRm|0x01 );
1507 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1511 FMOV @(R0, Rm), FRn {:
1513 load_reg( R_EDX, Rm );
1514 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
1515 check_ralign32( R_EDX );
1516 load_spreg( R_ECX, R_FPSCR );
1517 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1518 JNE_rel8(19, doublesize);
1519 MEM_READ_LONG( R_EDX, R_EAX );
1520 load_fr_bank( R_ECX );
1521 store_fr( R_ECX, R_EAX, FRn );
1524 JMP_TARGET(doublesize);
1525 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1526 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1527 load_xf_bank( R_ECX );
1528 store_fr( R_ECX, R_EAX, FRn&0x0E );
1529 store_fr( R_ECX, R_EDX, FRn|0x01 );
1533 JMP_TARGET(doublesize);
1534 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1535 load_fr_bank( R_ECX );
1536 store_fr( R_ECX, R_EAX, FRn&0x0E );
1537 store_fr( R_ECX, R_EDX, FRn|0x01 );
1541 FLDI0 FRn {: /* IFF PR=0 */
1543 load_spreg( R_ECX, R_FPSCR );
1544 TEST_imm32_r32( FPSCR_PR, R_ECX );
1546 XOR_r32_r32( R_EAX, R_EAX );
1547 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1548 store_fr( R_ECX, R_EAX, FRn );
1551 FLDI1 FRn {: /* IFF PR=0 */
1553 load_spreg( R_ECX, R_FPSCR );
1554 TEST_imm32_r32( FPSCR_PR, R_ECX );
1556 load_imm32(R_EAX, 0x3F800000);
1557 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1558 store_fr( R_ECX, R_EAX, FRn );
1564 load_spreg( R_ECX, R_FPSCR );
1565 load_spreg(R_EDX, REG_OFFSET(fr_bank));
1567 TEST_imm32_r32( FPSCR_PR, R_ECX );
1568 JNE_rel8(5, doubleprec);
1569 pop_fr( R_EDX, FRn );
1571 JMP_TARGET(doubleprec);
1572 pop_dr( R_EDX, FRn );
1581 load_fr_bank( R_ECX );
1582 load_fr( R_ECX, R_EAX, FRm );
1583 store_spreg( R_EAX, R_FPUL );
1587 load_fr_bank( R_ECX );
1588 load_spreg( R_EAX, R_FPUL );
1589 store_fr( R_ECX, R_EAX, FRn );
1593 load_spreg( R_ECX, R_FPSCR );
1594 TEST_imm32_r32( FPSCR_PR, R_ECX );
1595 JE_rel8(9, end); // only when PR=1
1596 load_fr_bank( R_ECX );
1597 push_dr( R_ECX, FRm );
1604 load_spreg( R_ECX, R_FPSCR );
1605 TEST_imm32_r32( FPSCR_PR, R_ECX );
1606 JE_rel8(9, end); // only when PR=1
1607 load_fr_bank( R_ECX );
1609 pop_dr( R_ECX, FRn );
1613 /* Floating point instructions */
1616 load_spreg( R_ECX, R_FPSCR );
1617 load_fr_bank( R_EDX );
1618 TEST_imm32_r32( FPSCR_PR, R_ECX );
1619 JNE_rel8(10, doubleprec);
1620 push_fr(R_EDX, FRn); // 3
1622 pop_fr( R_EDX, FRn); //3
1623 JMP_rel8(8,end); // 2
1624 JMP_TARGET(doubleprec);
1625 push_dr(R_EDX, FRn);
1632 load_spreg( R_ECX, R_FPSCR );
1633 TEST_imm32_r32( FPSCR_PR, R_ECX );
1634 load_fr_bank( R_EDX );
1635 JNE_rel8(13,doubleprec);
1636 push_fr(R_EDX, FRm);
1637 push_fr(R_EDX, FRn);
1641 JMP_TARGET(doubleprec);
1642 push_dr(R_EDX, FRm);
1643 push_dr(R_EDX, FRn);
1650 load_spreg( R_ECX, R_FPSCR );
1651 TEST_imm32_r32( FPSCR_PR, R_ECX );
1652 load_fr_bank( R_EDX );
1653 JNE_rel8(13, doubleprec);
1654 push_fr(R_EDX, FRn);
1655 push_fr(R_EDX, FRm);
1659 JMP_TARGET(doubleprec);
1660 push_dr(R_EDX, FRn);
1661 push_dr(R_EDX, FRm);
1666 FMAC FR0, FRm, FRn {:
1668 load_spreg( R_ECX, R_FPSCR );
1669 load_spreg( R_EDX, REG_OFFSET(fr_bank));
1670 TEST_imm32_r32( FPSCR_PR, R_ECX );
1671 JNE_rel8(18, doubleprec);
1672 push_fr( R_EDX, 0 );
1673 push_fr( R_EDX, FRm );
1675 push_fr( R_EDX, FRn );
1677 pop_fr( R_EDX, FRn );
1679 JMP_TARGET(doubleprec);
1680 push_dr( R_EDX, 0 );
1681 push_dr( R_EDX, FRm );
1683 push_dr( R_EDX, FRn );
1685 pop_dr( R_EDX, FRn );
1691 load_spreg( R_ECX, R_FPSCR );
1692 TEST_imm32_r32( FPSCR_PR, R_ECX );
1693 load_fr_bank( R_EDX );
1694 JNE_rel8(13, doubleprec);
1695 push_fr(R_EDX, FRm);
1696 push_fr(R_EDX, FRn);
1700 JMP_TARGET(doubleprec);
1701 push_dr(R_EDX, FRm);
1702 push_dr(R_EDX, FRn);
1709 load_spreg( R_ECX, R_FPSCR );
1710 TEST_imm32_r32( FPSCR_PR, R_ECX );
1711 load_fr_bank( R_EDX );
1712 JNE_rel8(10, doubleprec);
1713 push_fr(R_EDX, FRn);
1717 JMP_TARGET(doubleprec);
1718 push_dr(R_EDX, FRn);
1725 load_spreg( R_ECX, R_FPSCR );
1726 TEST_imm32_r32( FPSCR_PR, R_ECX );
1727 load_fr_bank( R_EDX );
1728 JNE_rel8(12, end); // PR=0 only
1730 push_fr(R_EDX, FRn);
1738 load_spreg( R_ECX, R_FPSCR );
1739 TEST_imm32_r32( FPSCR_PR, R_ECX );
1740 load_fr_bank( R_EDX );
1741 JNE_rel8(10, doubleprec);
1742 push_fr(R_EDX, FRn);
1746 JMP_TARGET(doubleprec);
1747 push_dr(R_EDX, FRn);
1754 load_spreg( R_ECX, R_FPSCR );
1755 TEST_imm32_r32( FPSCR_PR, R_ECX );
1756 load_fr_bank( R_EDX );
1757 JNE_rel8(13, doubleprec);
1758 push_fr(R_EDX, FRn);
1759 push_fr(R_EDX, FRm);
1763 JMP_TARGET(doubleprec);
1764 push_dr(R_EDX, FRn);
1765 push_dr(R_EDX, FRm);
1773 load_spreg( R_ECX, R_FPSCR );
1774 TEST_imm32_r32( FPSCR_PR, R_ECX );
1775 load_fr_bank( R_EDX );
1776 JNE_rel8(8, doubleprec);
1777 push_fr(R_EDX, FRm);
1778 push_fr(R_EDX, FRn);
1780 JMP_TARGET(doubleprec);
1781 push_dr(R_EDX, FRm);
1782 push_dr(R_EDX, FRn);
1790 load_spreg( R_ECX, R_FPSCR );
1791 TEST_imm32_r32( FPSCR_PR, R_ECX );
1792 load_fr_bank( R_EDX );
1793 JNE_rel8(8, doubleprec);
1794 push_fr(R_EDX, FRm);
1795 push_fr(R_EDX, FRn);
1797 JMP_TARGET(doubleprec);
1798 push_dr(R_EDX, FRm);
1799 push_dr(R_EDX, FRn);
1818 load_spreg( R_ECX, R_FPSCR );
1819 XOR_imm32_r32( FPSCR_FR, R_ECX );
1820 store_spreg( R_ECX, R_FPSCR );
1825 load_spreg( R_ECX, R_FPSCR );
1826 XOR_imm32_r32( FPSCR_SZ, R_ECX );
1827 store_spreg( R_ECX, R_FPSCR );
1830 /* Processor control instructions */
1832 load_reg( R_EAX, Rm );
1833 call_func1( sh4_write_sr, R_EAX );
1834 sh4_x86.priv_checked = FALSE;
1835 sh4_x86.fpuen_checked = FALSE;
1838 load_reg( R_EAX, Rm );
1839 store_spreg( R_EAX, R_GBR );
1842 load_reg( R_EAX, Rm );
1843 store_spreg( R_EAX, R_VBR );
1846 load_reg( R_EAX, Rm );
1847 store_spreg( R_EAX, R_SSR );
1850 load_reg( R_EAX, Rm );
1851 store_spreg( R_EAX, R_SGR );
1854 load_reg( R_EAX, Rm );
1855 store_spreg( R_EAX, R_SPC );
1858 load_reg( R_EAX, Rm );
1859 store_spreg( R_EAX, R_DBR );
1862 load_reg( R_EAX, Rm );
1863 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1866 load_reg( R_EAX, Rm );
1867 MOV_r32_r32( R_EAX, R_ECX );
1868 ADD_imm8s_r32( 4, R_EAX );
1869 store_reg( R_EAX, Rm );
1870 MEM_READ_LONG( R_ECX, R_EAX );
1871 store_spreg( R_EAX, R_GBR );
1874 load_reg( R_EAX, Rm );
1875 MOV_r32_r32( R_EAX, R_ECX );
1876 ADD_imm8s_r32( 4, R_EAX );
1877 store_reg( R_EAX, Rm );
1878 MEM_READ_LONG( R_ECX, R_EAX );
1879 call_func1( sh4_write_sr, R_EAX );
1880 sh4_x86.priv_checked = FALSE;
1881 sh4_x86.fpuen_checked = FALSE;
1884 load_reg( R_EAX, Rm );
1885 MOV_r32_r32( R_EAX, R_ECX );
1886 ADD_imm8s_r32( 4, R_EAX );
1887 store_reg( R_EAX, Rm );
1888 MEM_READ_LONG( R_ECX, R_EAX );
1889 store_spreg( R_EAX, R_VBR );
1892 load_reg( R_EAX, Rm );
1893 MOV_r32_r32( R_EAX, R_ECX );
1894 ADD_imm8s_r32( 4, R_EAX );
1895 store_reg( R_EAX, Rm );
1896 MEM_READ_LONG( R_ECX, R_EAX );
1897 store_spreg( R_EAX, R_SSR );
1900 load_reg( R_EAX, Rm );
1901 MOV_r32_r32( R_EAX, R_ECX );
1902 ADD_imm8s_r32( 4, R_EAX );
1903 store_reg( R_EAX, Rm );
1904 MEM_READ_LONG( R_ECX, R_EAX );
1905 store_spreg( R_EAX, R_SGR );
1908 load_reg( R_EAX, Rm );
1909 MOV_r32_r32( R_EAX, R_ECX );
1910 ADD_imm8s_r32( 4, R_EAX );
1911 store_reg( R_EAX, Rm );
1912 MEM_READ_LONG( R_ECX, R_EAX );
1913 store_spreg( R_EAX, R_SPC );
1916 load_reg( R_EAX, Rm );
1917 MOV_r32_r32( R_EAX, R_ECX );
1918 ADD_imm8s_r32( 4, R_EAX );
1919 store_reg( R_EAX, Rm );
1920 MEM_READ_LONG( R_ECX, R_EAX );
1921 store_spreg( R_EAX, R_DBR );
1923 LDC.L @Rm+, Rn_BANK {:
1924 load_reg( R_EAX, Rm );
1925 MOV_r32_r32( R_EAX, R_ECX );
1926 ADD_imm8s_r32( 4, R_EAX );
1927 store_reg( R_EAX, Rm );
1928 MEM_READ_LONG( R_ECX, R_EAX );
1929 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1932 load_reg( R_EAX, Rm );
1933 store_spreg( R_EAX, R_FPSCR );
1935 LDS.L @Rm+, FPSCR {:
1936 load_reg( R_EAX, Rm );
1937 MOV_r32_r32( R_EAX, R_ECX );
1938 ADD_imm8s_r32( 4, R_EAX );
1939 store_reg( R_EAX, Rm );
1940 MEM_READ_LONG( R_ECX, R_EAX );
1941 store_spreg( R_EAX, R_FPSCR );
1944 load_reg( R_EAX, Rm );
1945 store_spreg( R_EAX, R_FPUL );
1948 load_reg( R_EAX, Rm );
1949 MOV_r32_r32( R_EAX, R_ECX );
1950 ADD_imm8s_r32( 4, R_EAX );
1951 store_reg( R_EAX, Rm );
1952 MEM_READ_LONG( R_ECX, R_EAX );
1953 store_spreg( R_EAX, R_FPUL );
1956 load_reg( R_EAX, Rm );
1957 store_spreg( R_EAX, R_MACH );
1960 load_reg( R_EAX, Rm );
1961 MOV_r32_r32( R_EAX, R_ECX );
1962 ADD_imm8s_r32( 4, R_EAX );
1963 store_reg( R_EAX, Rm );
1964 MEM_READ_LONG( R_ECX, R_EAX );
1965 store_spreg( R_EAX, R_MACH );
1968 load_reg( R_EAX, Rm );
1969 store_spreg( R_EAX, R_MACL );
1972 load_reg( R_EAX, Rm );
1973 MOV_r32_r32( R_EAX, R_ECX );
1974 ADD_imm8s_r32( 4, R_EAX );
1975 store_reg( R_EAX, Rm );
1976 MEM_READ_LONG( R_ECX, R_EAX );
1977 store_spreg( R_EAX, R_MACL );
1980 load_reg( R_EAX, Rm );
1981 store_spreg( R_EAX, R_PR );
1984 load_reg( R_EAX, Rm );
1985 MOV_r32_r32( R_EAX, R_ECX );
1986 ADD_imm8s_r32( 4, R_EAX );
1987 store_reg( R_EAX, Rm );
1988 MEM_READ_LONG( R_ECX, R_EAX );
1989 store_spreg( R_EAX, R_PR );
1996 load_reg( R_EAX, Rn );
1998 AND_imm32_r32( 0xFC000000, R_EAX );
1999 CMP_imm32_r32( 0xE0000000, R_EAX );
2001 call_func0( sh4_flush_store_queue );
2003 ADD_imm8s_r32( 4, R_ESP );
2005 SLEEP {: /* TODO */ :}
2007 call_func0(sh4_read_sr);
2008 store_reg( R_EAX, Rn );
2011 load_spreg( R_EAX, R_GBR );
2012 store_reg( R_EAX, Rn );
2015 load_spreg( R_EAX, R_VBR );
2016 store_reg( R_EAX, Rn );
2019 load_spreg( R_EAX, R_SSR );
2020 store_reg( R_EAX, Rn );
2023 load_spreg( R_EAX, R_SPC );
2024 store_reg( R_EAX, Rn );
2027 load_spreg( R_EAX, R_SGR );
2028 store_reg( R_EAX, Rn );
2031 load_spreg( R_EAX, R_DBR );
2032 store_reg( R_EAX, Rn );
2035 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2036 store_reg( R_EAX, Rn );
2039 load_reg( R_ECX, Rn );
2040 ADD_imm8s_r32( -4, Rn );
2041 store_reg( R_ECX, Rn );
2042 call_func0( sh4_read_sr );
2043 MEM_WRITE_LONG( R_ECX, R_EAX );
2046 load_reg( R_ECX, Rn );
2047 ADD_imm8s_r32( -4, Rn );
2048 store_reg( R_ECX, Rn );
2049 load_spreg( R_EAX, R_VBR );
2050 MEM_WRITE_LONG( R_ECX, R_EAX );
2053 load_reg( R_ECX, Rn );
2054 ADD_imm8s_r32( -4, Rn );
2055 store_reg( R_ECX, Rn );
2056 load_spreg( R_EAX, R_SSR );
2057 MEM_WRITE_LONG( R_ECX, R_EAX );
2060 load_reg( R_ECX, Rn );
2061 ADD_imm8s_r32( -4, Rn );
2062 store_reg( R_ECX, Rn );
2063 load_spreg( R_EAX, R_SPC );
2064 MEM_WRITE_LONG( R_ECX, R_EAX );
2067 load_reg( R_ECX, Rn );
2068 ADD_imm8s_r32( -4, Rn );
2069 store_reg( R_ECX, Rn );
2070 load_spreg( R_EAX, R_SGR );
2071 MEM_WRITE_LONG( R_ECX, R_EAX );
2074 load_reg( R_ECX, Rn );
2075 ADD_imm8s_r32( -4, Rn );
2076 store_reg( R_ECX, Rn );
2077 load_spreg( R_EAX, R_DBR );
2078 MEM_WRITE_LONG( R_ECX, R_EAX );
2080 STC.L Rm_BANK, @-Rn {:
2081 load_reg( R_ECX, Rn );
2082 ADD_imm8s_r32( -4, Rn );
2083 store_reg( R_ECX, Rn );
2084 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2085 MEM_WRITE_LONG( R_ECX, R_EAX );
2088 load_reg( R_ECX, Rn );
2089 ADD_imm8s_r32( -4, Rn );
2090 store_reg( R_ECX, Rn );
2091 load_spreg( R_EAX, R_GBR );
2092 MEM_WRITE_LONG( R_ECX, R_EAX );
2095 load_spreg( R_EAX, R_FPSCR );
2096 store_reg( R_EAX, Rn );
2098 STS.L FPSCR, @-Rn {:
2099 load_reg( R_ECX, Rn );
2100 ADD_imm8s_r32( -4, Rn );
2101 store_reg( R_ECX, Rn );
2102 load_spreg( R_EAX, R_FPSCR );
2103 MEM_WRITE_LONG( R_ECX, R_EAX );
2106 load_spreg( R_EAX, R_FPUL );
2107 store_reg( R_EAX, Rn );
2110 load_reg( R_ECX, Rn );
2111 ADD_imm8s_r32( -4, Rn );
2112 store_reg( R_ECX, Rn );
2113 load_spreg( R_EAX, R_FPUL );
2114 MEM_WRITE_LONG( R_ECX, R_EAX );
2117 load_spreg( R_EAX, R_MACH );
2118 store_reg( R_EAX, Rn );
2121 load_reg( R_ECX, Rn );
2122 ADD_imm8s_r32( -4, Rn );
2123 store_reg( R_ECX, Rn );
2124 load_spreg( R_EAX, R_MACH );
2125 MEM_WRITE_LONG( R_ECX, R_EAX );
2128 load_spreg( R_EAX, R_MACL );
2129 store_reg( R_EAX, Rn );
2132 load_reg( R_ECX, Rn );
2133 ADD_imm8s_r32( -4, Rn );
2134 store_reg( R_ECX, Rn );
2135 load_spreg( R_EAX, R_MACL );
2136 MEM_WRITE_LONG( R_ECX, R_EAX );
2139 load_spreg( R_EAX, R_PR );
2140 store_reg( R_EAX, Rn );
2143 load_reg( R_ECX, Rn );
2144 ADD_imm8s_r32( -4, Rn );
2145 store_reg( R_ECX, Rn );
2146 load_spreg( R_EAX, R_PR );
2147 MEM_WRITE_LONG( R_ECX, R_EAX );
2150 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}
2153 if( sh4_x86.in_delay_slot ) {
2154 sh4_x86.in_delay_slot = FALSE;
.