2 * $Id: sh4x86.in,v 1.6 2007-09-12 09:17:24 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.
23 #include "sh4/sh4core.h"
24 #include "sh4/sh4trans.h"
25 #include "sh4/x86op.h"
28 #define DEFAULT_BACKPATCH_SIZE 4096
31 * Struct to manage internal translation state. This state is not saved -
32 * it is only valid between calls to sh4_translate_begin_block() and
33 * sh4_translate_end_block()
35 struct sh4_x86_state {
36 gboolean in_delay_slot;
37 gboolean priv_checked; /* true if we've already checked the cpu mode. */
38 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
40 /* Allocated memory for the (block-wide) back-patch list */
41 uint32_t **backpatch_list;
42 uint32_t backpatch_posn;
43 uint32_t backpatch_size;
46 #define EXIT_DATA_ADDR_READ 0
47 #define EXIT_DATA_ADDR_WRITE 7
48 #define EXIT_ILLEGAL 14
49 #define EXIT_SLOT_ILLEGAL 21
50 #define EXIT_FPU_DISABLED 28
51 #define EXIT_SLOT_FPU_DISABLED 35
53 static struct sh4_x86_state sh4_x86;
57 sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
58 sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(uint32_t *);
62 static void sh4_x86_add_backpatch( uint8_t *ptr )
64 if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
65 sh4_x86.backpatch_size <<= 1;
66 sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list, sh4_x86.backpatch_size * sizeof(uint32_t *) );
67 assert( sh4_x86.backpatch_list != NULL );
69 sh4_x86.backpatch_list[sh4_x86.backpatch_posn++] = (uint32_t *)ptr;
72 static void sh4_x86_do_backpatch( uint8_t *reloc_base )
75 for( i=0; i<sh4_x86.backpatch_posn; i++ ) {
76 *sh4_x86.backpatch_list[i] += (reloc_base - ((uint8_t *)sh4_x86.backpatch_list[i]) - 4);
81 #define MARK_JMP(x,n) uint8_t *_mark_jmp_##x = xlat_output + n
82 #define CHECK_JMP(x) assert( _mark_jmp_##x == xlat_output )
90 * Emit an instruction to load an SH4 reg into a real register
92 static inline void load_reg( int x86reg, int sh4reg )
96 OP(0x45 + (x86reg<<3));
97 OP(REG_OFFSET(r[sh4reg]));
100 static inline void load_reg16s( int x86reg, int sh4reg )
104 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
107 static inline void load_reg16u( int x86reg, int sh4reg )
111 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
115 static inline void load_spreg( int x86reg, int regoffset )
117 /* mov [bp+n], reg */
119 OP(0x45 + (x86reg<<3));
124 * Emit an instruction to load an immediate value into a register
126 static inline void load_imm32( int x86reg, uint32_t value ) {
127 /* mov #value, reg */
133 * Emit an instruction to store an SH4 reg (RN)
135 void static inline store_reg( int x86reg, int sh4reg ) {
136 /* mov reg, [bp+n] */
138 OP(0x45 + (x86reg<<3));
139 OP(REG_OFFSET(r[sh4reg]));
141 void static inline store_spreg( int x86reg, int regoffset ) {
142 /* mov reg, [bp+n] */
144 OP(0x45 + (x86reg<<3));
149 #define load_fr_bank(bankreg) load_spreg( bankreg, REG_OFFSET(fr_bank))
152 * Load an FR register (single-precision floating point) into an integer x86
153 * register (eg for register-to-register moves)
155 void static inline load_fr( int bankreg, int x86reg, int frm )
157 OP(0x8B); OP(0x40+bankreg+(x86reg<<3)); OP((frm^1)<<2);
161 * Store an FR register (single-precision floating point) into an integer x86
162 * register (eg for register-to-register moves)
164 void static inline store_fr( int bankreg, int x86reg, int frn )
166 OP(0x89); OP(0x40+bankreg+(x86reg<<3)); OP((frn^1)<<2);
171 * Load a pointer to the back fp back into the specified x86 register. The
172 * bankreg must have been previously loaded with FPSCR.
175 static inline void load_xf_bank( int bankreg )
177 SHR_imm8_r32( (21 - 6), bankreg ); // Extract bit 21 then *64 for bank size
178 AND_imm8s_r32( 0x40, bankreg ); // Complete extraction
179 OP(0x8D); OP(0x44+(bankreg<<3)); OP(0x28+bankreg); OP(REG_OFFSET(fr)); // LEA [ebp+bankreg+disp], bankreg
183 * Push FPUL (as a 32-bit float) onto the FPU stack
185 static inline void push_fpul( )
187 OP(0xD9); OP(0x45); OP(R_FPUL);
191 * Pop FPUL (as a 32-bit float) from the FPU stack
193 static inline void pop_fpul( )
195 OP(0xD9); OP(0x5D); OP(R_FPUL);
199 * Push a 32-bit float onto the FPU stack, with bankreg previously loaded
200 * with the location of the current fp bank.
202 static inline void push_fr( int bankreg, int frm )
204 OP(0xD9); OP(0x40 + bankreg); OP((frm^1)<<2); // FLD.S [bankreg + frm^1*4]
208 * Pop a 32-bit float from the FPU stack and store it back into the fp bank,
209 * with bankreg previously loaded with the location of the current fp bank.
211 static inline void pop_fr( int bankreg, int frm )
213 OP(0xD9); OP(0x58 + bankreg); OP((frm^1)<<2); // FST.S [bankreg + frm^1*4]
217 * Push a 64-bit double onto the FPU stack, with bankreg previously loaded
218 * with the location of the current fp bank.
220 static inline void push_dr( int bankreg, int frm )
222 OP(0xDD); OP(0x40 + bankreg); OP(frm<<2); // FLD.D [bankreg + frm*4]
225 static inline void pop_dr( int bankreg, int frm )
227 OP(0xDD); OP(0x58 + bankreg); OP(frm<<2); // FST.D [bankreg + frm*4]
231 * Note: clobbers EAX to make the indirect call - this isn't usually
232 * a problem since the callee will usually clobber it anyway.
234 static inline void call_func0( void *ptr )
236 load_imm32(R_EAX, (uint32_t)ptr);
240 static inline void call_func1( void *ptr, int arg1 )
244 ADD_imm8s_r32( 4, R_ESP );
247 static inline void call_func2( void *ptr, int arg1, int arg2 )
252 ADD_imm8s_r32( 8, R_ESP );
256 * Write a double (64-bit) value into memory, with the first word in arg2a, and
257 * the second in arg2b
260 static inline void MEM_WRITE_DOUBLE( int addr, int arg2a, int arg2b )
262 ADD_imm8s_r32( 4, addr );
265 ADD_imm8s_r32( -4, addr );
268 call_func0(sh4_write_long);
269 ADD_imm8s_r32( 8, R_ESP );
270 call_func0(sh4_write_long);
271 ADD_imm8s_r32( 8, R_ESP );
275 * Read a double (64-bit) value from memory, writing the first word into arg2a
276 * and the second into arg2b. The addr must not be in EAX
279 static inline void MEM_READ_DOUBLE( int addr, int arg2a, int arg2b )
282 call_func0(sh4_read_long);
285 ADD_imm8s_r32( 4, addr );
287 call_func0(sh4_read_long);
288 ADD_imm8s_r32( 4, R_ESP );
289 MOV_r32_r32( R_EAX, arg2b );
293 /* Exception checks - Note that all exception checks will clobber EAX */
294 static void check_priv( )
296 if( !sh4_x86.priv_checked ) {
297 sh4_x86.priv_checked = TRUE;
298 load_spreg( R_EAX, R_SR );
299 AND_imm32_r32( SR_MD, R_EAX );
300 if( sh4_x86.in_delay_slot ) {
301 JE_exit( EXIT_SLOT_ILLEGAL );
303 JE_exit( EXIT_ILLEGAL );
308 static void check_fpuen( )
310 if( !sh4_x86.fpuen_checked ) {
311 sh4_x86.fpuen_checked = TRUE;
312 load_spreg( R_EAX, R_SR );
313 AND_imm32_r32( SR_FD, R_EAX );
314 if( sh4_x86.in_delay_slot ) {
315 JNE_exit(EXIT_SLOT_FPU_DISABLED);
317 JNE_exit(EXIT_FPU_DISABLED);
322 static void check_ralign16( int x86reg )
324 TEST_imm32_r32( 0x00000001, x86reg );
325 JNE_exit(EXIT_DATA_ADDR_READ);
328 static void check_walign16( int x86reg )
330 TEST_imm32_r32( 0x00000001, x86reg );
331 JNE_exit(EXIT_DATA_ADDR_WRITE);
334 static void check_ralign32( int x86reg )
336 TEST_imm32_r32( 0x00000003, x86reg );
337 JNE_exit(EXIT_DATA_ADDR_READ);
339 static void check_walign32( int x86reg )
341 TEST_imm32_r32( 0x00000003, x86reg );
342 JNE_exit(EXIT_DATA_ADDR_WRITE);
347 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
348 #define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
349 #define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
350 #define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
351 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
352 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
353 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
355 #define RAISE_EXCEPTION( exc ) call_func1(sh4_raise_exception, exc);
356 #define SLOTILLEGAL() RAISE_EXCEPTION(EXC_SLOT_ILLEGAL); return 1
361 * Emit the 'start of block' assembly. Sets up the stack frame and save
364 void sh4_translate_begin_block()
368 load_imm32( R_EBP, (uint32_t)&sh4r );
372 sh4_x86.in_delay_slot = FALSE;
373 sh4_x86.priv_checked = FALSE;
374 sh4_x86.fpuen_checked = FALSE;
375 sh4_x86.backpatch_posn = 0;
379 * Exit the block early (ie branch out), conditionally or otherwise
383 store_spreg( R_EDI, REG_OFFSET(pc) );
384 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
385 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
387 ADD_r32_r32( R_EAX, R_ECX );
388 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
389 XOR_r32_r32( R_EAX, R_EAX );
397 * Flush any open regs back to memory, restore SI/DI/, update PC, etc
399 void sh4_translate_end_block( sh4addr_t pc ) {
400 assert( !sh4_x86.in_delay_slot ); // should never stop here
401 // Normal termination - save PC, cycle count
404 uint8_t *end_ptr = xlat_output;
405 // Exception termination. Jump block for various exception codes:
406 PUSH_imm32( EXC_DATA_ADDR_READ );
408 PUSH_imm32( EXC_DATA_ADDR_WRITE );
410 PUSH_imm32( EXC_ILLEGAL );
412 PUSH_imm32( EXC_SLOT_ILLEGAL );
414 PUSH_imm32( EXC_FPU_DISABLED );
416 PUSH_imm32( EXC_SLOT_FPU_DISABLED );
418 load_spreg( R_ECX, REG_OFFSET(pc) );
419 ADD_r32_r32( R_ESI, R_ECX );
420 ADD_r32_r32( R_ESI, R_ECX );
421 store_spreg( R_ECX, REG_OFFSET(pc) );
422 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
423 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
425 ADD_r32_r32( R_EAX, R_ECX );
426 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
428 load_imm32( R_EAX, (uint32_t)sh4_raise_exception ); // 6
429 CALL_r32( R_EAX ); // 2
433 sh4_x86_do_backpatch( end_ptr );
437 * Translate a single instruction. Delayed branches are handled specially
438 * by translating both branch and delayed instruction as a single unit (as
441 * @return true if the instruction marks the end of a basic block
444 uint32_t sh4_x86_translate_instruction( uint32_t pc )
446 uint16_t ir = sh4_read_word( pc );
451 load_reg( R_EAX, Rm );
452 load_reg( R_ECX, Rn );
453 ADD_r32_r32( R_EAX, R_ECX );
454 store_reg( R_ECX, Rn );
457 load_reg( R_EAX, Rn );
458 ADD_imm8s_r32( imm, R_EAX );
459 store_reg( R_EAX, Rn );
462 load_reg( R_EAX, Rm );
463 load_reg( R_ECX, Rn );
465 ADC_r32_r32( R_EAX, R_ECX );
466 store_reg( R_ECX, Rn );
470 load_reg( R_EAX, Rm );
471 load_reg( R_ECX, Rn );
472 ADD_r32_r32( R_EAX, R_ECX );
473 store_reg( R_ECX, Rn );
477 load_reg( R_EAX, Rm );
478 load_reg( R_ECX, Rn );
479 AND_r32_r32( R_EAX, R_ECX );
480 store_reg( R_ECX, Rn );
483 load_reg( R_EAX, 0 );
484 AND_imm32_r32(imm, R_EAX);
485 store_reg( R_EAX, 0 );
487 AND.B #imm, @(R0, GBR) {:
488 load_reg( R_EAX, 0 );
489 load_spreg( R_ECX, R_GBR );
490 ADD_r32_r32( R_EAX, R_ECX );
491 MEM_READ_BYTE( R_ECX, R_EAX );
492 AND_imm32_r32(imm, R_ECX );
493 MEM_WRITE_BYTE( R_ECX, R_EAX );
496 load_reg( R_EAX, Rm );
497 load_reg( R_ECX, Rn );
498 CMP_r32_r32( R_EAX, R_ECX );
502 load_reg( R_EAX, 0 );
503 CMP_imm8s_r32(imm, R_EAX);
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, Rm );
520 load_reg( R_ECX, Rn );
521 CMP_r32_r32( R_EAX, R_ECX );
525 load_reg( R_EAX, Rm );
526 load_reg( R_ECX, Rn );
527 CMP_r32_r32( R_EAX, R_ECX );
531 load_reg( R_EAX, Rn );
532 CMP_imm8s_r32( 0, R_EAX );
536 load_reg( R_EAX, Rn );
537 CMP_imm8s_r32( 0, R_EAX );
541 load_reg( R_EAX, Rm );
542 load_reg( R_ECX, Rn );
543 XOR_r32_r32( R_ECX, R_EAX );
544 TEST_r8_r8( R_AL, R_AL );
546 TEST_r8_r8( R_AH, R_AH ); // 2
548 SHR_imm8_r32( 16, R_EAX ); // 3
549 TEST_r8_r8( R_AL, R_AL ); // 2
551 TEST_r8_r8( R_AH, R_AH ); // 2
555 load_reg( R_EAX, Rm );
556 load_reg( R_ECX, Rm );
557 SHR_imm8_r32( 31, R_EAX );
558 SHR_imm8_r32( 31, R_ECX );
559 store_spreg( R_EAX, R_M );
560 store_spreg( R_ECX, R_Q );
561 CMP_r32_r32( R_EAX, R_ECX );
565 XOR_r32_r32( R_EAX, R_EAX );
566 store_spreg( R_EAX, R_Q );
567 store_spreg( R_EAX, R_M );
568 store_spreg( R_EAX, R_T );
571 load_reg( R_ECX, Rn );
573 RCL1_r32( R_ECX ); // OP2
574 SETC_r32( R_EDX ); // Q
575 load_spreg( R_EAX, R_Q );
576 CMP_sh4r_r32( R_M, R_EAX );
578 ADD_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
580 SUB_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
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, Rm );
592 load_reg( R_ECX, Rn );
594 store_spreg( R_EDX, R_MACH );
595 store_spreg( R_EAX, R_MACL );
598 load_reg( R_EAX, Rn );
599 ADD_imm8s_r32( -1, Rn );
600 store_reg( R_EAX, Rn );
604 load_reg( R_EAX, Rm );
605 MOVSX_r8_r32( R_EAX, R_EAX );
606 store_reg( R_EAX, Rn );
609 load_reg( R_EAX, Rm );
610 MOVSX_r16_r32( R_EAX, R_EAX );
611 store_reg( R_EAX, Rn );
614 load_reg( R_EAX, Rm );
615 MOVZX_r8_r32( R_EAX, R_EAX );
616 store_reg( R_EAX, Rn );
619 load_reg( R_EAX, Rm );
620 MOVZX_r16_r32( R_EAX, R_EAX );
621 store_reg( R_EAX, Rn );
623 MAC.L @Rm+, @Rn+ {: :}
624 MAC.W @Rm+, @Rn+ {: :}
626 load_spreg( R_EAX, R_T );
627 store_reg( R_EAX, Rn );
630 load_reg( R_EAX, Rm );
631 load_reg( R_ECX, Rn );
633 store_spreg( R_EAX, R_MACL );
636 load_reg16s( R_EAX, Rm );
637 load_reg16s( R_ECX, Rn );
639 store_spreg( R_EAX, R_MACL );
642 load_reg16u( R_EAX, Rm );
643 load_reg16u( R_ECX, Rn );
645 store_spreg( R_EAX, R_MACL );
648 load_reg( R_EAX, Rm );
650 store_reg( R_EAX, Rn );
653 load_reg( R_EAX, Rm );
654 XOR_r32_r32( R_ECX, R_ECX );
656 SBB_r32_r32( R_EAX, R_ECX );
657 store_reg( R_ECX, Rn );
661 load_reg( R_EAX, Rm );
663 store_reg( R_EAX, Rn );
666 load_reg( R_EAX, Rm );
667 load_reg( R_ECX, Rn );
668 OR_r32_r32( R_EAX, R_ECX );
669 store_reg( R_ECX, Rn );
672 load_reg( R_EAX, 0 );
673 OR_imm32_r32(imm, R_EAX);
674 store_reg( R_EAX, 0 );
676 OR.B #imm, @(R0, GBR) {:
677 load_reg( R_EAX, 0 );
678 load_spreg( R_ECX, R_GBR );
679 ADD_r32_r32( R_EAX, R_ECX );
680 MEM_READ_BYTE( R_ECX, R_EAX );
681 OR_imm32_r32(imm, R_ECX );
682 MEM_WRITE_BYTE( R_ECX, R_EAX );
685 load_reg( R_EAX, Rn );
688 store_reg( R_EAX, Rn );
692 load_reg( R_EAX, Rn );
695 store_reg( R_EAX, Rn );
699 load_reg( R_EAX, Rn );
701 store_reg( R_EAX, Rn );
705 load_reg( R_EAX, Rn );
707 store_reg( R_EAX, Rn );
711 /* Annoyingly enough, not directly convertible */
712 load_reg( R_EAX, Rn );
713 load_reg( R_ECX, Rm );
714 CMP_imm32_r32( 0, R_ECX );
717 NEG_r32( R_ECX ); // 2
718 AND_imm8_r8( 0x1F, R_CL ); // 3
719 SAR_r32_CL( R_EAX ); // 2
722 AND_imm8_r8( 0x1F, R_CL ); // 3
723 SHL_r32_CL( R_EAX ); // 2
725 store_reg( R_EAX, Rn );
728 load_reg( R_EAX, Rn );
729 load_reg( R_ECX, Rm );
731 MOV_r32_r32( R_EAX, R_EDX );
735 CMP_imm8s_r32( 0, R_ECX );
736 CMOVAE_r32_r32( R_EDX, R_EAX );
737 store_reg( R_EAX, Rn );
740 load_reg( R_EAX, Rn );
742 store_reg( R_EAX, Rn );
745 load_reg( R_EAX, Rn );
747 store_reg( R_EAX, Rn );
750 load_reg( R_EAX, Rn );
752 store_reg( R_EAX, Rn );
755 load_reg( R_EAX, Rn );
756 SHL_imm8_r32( 2, R_EAX );
757 store_reg( R_EAX, Rn );
760 load_reg( R_EAX, Rn );
761 SHL_imm8_r32( 8, R_EAX );
762 store_reg( R_EAX, Rn );
765 load_reg( R_EAX, Rn );
766 SHL_imm8_r32( 16, R_EAX );
767 store_reg( R_EAX, Rn );
770 load_reg( R_EAX, Rn );
772 store_reg( R_EAX, Rn );
775 load_reg( R_EAX, Rn );
776 SHR_imm8_r32( 2, R_EAX );
777 store_reg( R_EAX, Rn );
780 load_reg( R_EAX, Rn );
781 SHR_imm8_r32( 8, R_EAX );
782 store_reg( R_EAX, Rn );
785 load_reg( R_EAX, Rn );
786 SHR_imm8_r32( 16, R_EAX );
787 store_reg( R_EAX, Rn );
790 load_reg( R_EAX, Rm );
791 load_reg( R_ECX, Rn );
792 SUB_r32_r32( R_EAX, R_ECX );
793 store_reg( R_ECX, Rn );
796 load_reg( R_EAX, Rm );
797 load_reg( R_ECX, Rn );
799 SBB_r32_r32( R_EAX, R_ECX );
800 store_reg( R_ECX, Rn );
803 load_reg( R_EAX, Rm );
804 load_reg( R_ECX, Rn );
805 SUB_r32_r32( R_EAX, R_ECX );
806 store_reg( R_ECX, Rn );
810 load_reg( R_EAX, Rm );
811 XCHG_r8_r8( R_AL, R_AH );
812 store_reg( R_EAX, Rn );
815 load_reg( R_EAX, Rm );
816 MOV_r32_r32( R_EAX, R_ECX );
817 SHL_imm8_r32( 16, R_ECX );
818 SHR_imm8_r32( 16, R_EAX );
819 OR_r32_r32( R_EAX, R_ECX );
820 store_reg( R_ECX, Rn );
823 load_reg( R_ECX, Rn );
824 MEM_READ_BYTE( R_ECX, R_EAX );
825 TEST_r8_r8( R_AL, R_AL );
827 OR_imm8_r8( 0x80, R_AL );
828 MEM_WRITE_BYTE( R_ECX, R_EAX );
831 load_reg( R_EAX, Rm );
832 load_reg( R_ECX, Rn );
833 TEST_r32_r32( R_EAX, R_ECX );
837 load_reg( R_EAX, 0 );
838 TEST_imm32_r32( imm, R_EAX );
841 TST.B #imm, @(R0, GBR) {:
843 load_reg( R_ECX, R_GBR);
844 ADD_r32_r32( R_EAX, R_ECX );
845 MEM_READ_BYTE( R_ECX, R_EAX );
846 TEST_imm8_r8( imm, R_EAX );
850 load_reg( R_EAX, Rm );
851 load_reg( R_ECX, Rn );
852 XOR_r32_r32( R_EAX, R_ECX );
853 store_reg( R_ECX, Rn );
856 load_reg( R_EAX, 0 );
857 XOR_imm32_r32( imm, R_EAX );
858 store_reg( R_EAX, 0 );
860 XOR.B #imm, @(R0, GBR) {:
861 load_reg( R_EAX, 0 );
862 load_spreg( R_ECX, R_GBR );
863 ADD_r32_r32( R_EAX, R_ECX );
864 MEM_READ_BYTE( R_ECX, R_EAX );
865 XOR_imm32_r32( imm, R_EAX );
866 MEM_WRITE_BYTE( R_ECX, R_EAX );
869 load_reg( R_EAX, Rm );
870 MOV_r32_r32( R_EAX, R_ECX );
871 SHR_imm8_r32( 16, R_EAX );
872 SHL_imm8_r32( 16, R_ECX );
873 OR_r32_r32( R_EAX, R_ECX );
874 store_reg( R_ECX, Rn );
877 /* Data move instructions */
879 load_reg( R_EAX, Rm );
880 store_reg( R_EAX, Rn );
883 load_imm32( R_EAX, imm );
884 store_reg( R_EAX, Rn );
887 load_reg( R_EAX, Rm );
888 load_reg( R_ECX, Rn );
889 MEM_WRITE_BYTE( R_ECX, R_EAX );
892 load_reg( R_EAX, Rm );
893 load_reg( R_ECX, Rn );
894 ADD_imm8s_r32( -1, Rn );
895 store_reg( R_ECX, Rn );
896 MEM_WRITE_BYTE( R_ECX, R_EAX );
898 MOV.B Rm, @(R0, Rn) {:
899 load_reg( R_EAX, 0 );
900 load_reg( R_ECX, Rn );
901 ADD_r32_r32( R_EAX, R_ECX );
902 load_reg( R_EAX, Rm );
903 MEM_WRITE_BYTE( R_ECX, R_EAX );
905 MOV.B R0, @(disp, GBR) {:
906 load_reg( R_EAX, 0 );
907 load_spreg( R_ECX, R_GBR );
908 ADD_imm32_r32( disp, R_ECX );
909 MEM_WRITE_BYTE( R_ECX, R_EAX );
911 MOV.B R0, @(disp, Rn) {:
912 load_reg( R_EAX, 0 );
913 load_reg( R_ECX, Rn );
914 ADD_imm32_r32( disp, R_ECX );
915 MEM_WRITE_BYTE( R_ECX, R_EAX );
918 load_reg( R_ECX, Rm );
919 MEM_READ_BYTE( R_ECX, R_EAX );
920 store_reg( R_ECX, Rn );
923 load_reg( R_ECX, Rm );
924 MOV_r32_r32( R_ECX, R_EAX );
925 ADD_imm8s_r32( 1, R_EAX );
926 store_reg( R_EAX, Rm );
927 MEM_READ_BYTE( R_ECX, R_EAX );
928 store_reg( R_EAX, Rn );
930 MOV.B @(R0, Rm), Rn {:
931 load_reg( R_EAX, 0 );
932 load_reg( R_ECX, Rm );
933 ADD_r32_r32( R_EAX, R_ECX );
934 MEM_READ_BYTE( R_ECX, R_EAX );
935 store_reg( R_EAX, Rn );
937 MOV.B @(disp, GBR), R0 {:
938 load_spreg( R_ECX, R_GBR );
939 ADD_imm32_r32( disp, R_ECX );
940 MEM_READ_BYTE( R_ECX, R_EAX );
941 store_reg( R_EAX, 0 );
943 MOV.B @(disp, Rm), R0 {:
944 load_reg( R_ECX, Rm );
945 ADD_imm32_r32( disp, R_ECX );
946 MEM_READ_BYTE( R_ECX, R_EAX );
947 store_reg( R_EAX, 0 );
950 load_reg( R_EAX, Rm );
951 load_reg( R_ECX, Rn );
952 check_walign32(R_ECX);
953 MEM_WRITE_LONG( R_ECX, R_EAX );
956 load_reg( R_EAX, Rm );
957 load_reg( R_ECX, Rn );
958 check_walign32( R_ECX );
959 ADD_imm8s_r32( -4, R_ECX );
960 store_reg( R_ECX, Rn );
961 MEM_WRITE_LONG( R_ECX, R_EAX );
963 MOV.L Rm, @(R0, Rn) {:
964 load_reg( R_EAX, 0 );
965 load_reg( R_ECX, Rn );
966 ADD_r32_r32( R_EAX, R_ECX );
967 check_walign32( R_ECX );
968 load_reg( R_EAX, Rm );
969 MEM_WRITE_LONG( R_ECX, R_EAX );
971 MOV.L R0, @(disp, GBR) {:
972 load_spreg( R_ECX, R_GBR );
973 load_reg( R_EAX, 0 );
974 ADD_imm32_r32( disp, R_ECX );
975 check_walign32( R_ECX );
976 MEM_WRITE_LONG( R_ECX, R_EAX );
978 MOV.L Rm, @(disp, Rn) {:
979 load_reg( R_ECX, Rn );
980 load_reg( R_EAX, Rm );
981 ADD_imm32_r32( disp, R_ECX );
982 check_walign32( R_ECX );
983 MEM_WRITE_LONG( R_ECX, R_EAX );
986 load_reg( R_ECX, Rm );
987 check_ralign32( R_ECX );
988 MEM_READ_LONG( R_ECX, R_EAX );
989 store_reg( R_EAX, Rn );
992 load_reg( R_EAX, Rm );
993 check_ralign32( R_ECX );
994 MOV_r32_r32( R_EAX, R_ECX );
995 ADD_imm8s_r32( 4, R_EAX );
996 store_reg( R_EAX, Rm );
997 MEM_READ_LONG( R_ECX, R_EAX );
998 store_reg( R_EAX, Rn );
1000 MOV.L @(R0, Rm), Rn {:
1001 load_reg( R_EAX, 0 );
1002 load_reg( R_ECX, Rm );
1003 ADD_r32_r32( R_EAX, R_ECX );
1004 check_ralign32( R_ECX );
1005 MEM_READ_LONG( R_ECX, R_EAX );
1006 store_reg( R_EAX, Rn );
1008 MOV.L @(disp, GBR), R0 {:
1009 load_spreg( R_ECX, R_GBR );
1010 ADD_imm32_r32( disp, R_ECX );
1011 check_ralign32( R_ECX );
1012 MEM_READ_LONG( R_ECX, R_EAX );
1013 store_reg( R_EAX, 0 );
1015 MOV.L @(disp, PC), Rn {:
1016 if( sh4_x86.in_delay_slot ) {
1019 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1020 MEM_READ_LONG( R_ECX, R_EAX );
1021 store_reg( R_EAX, 0 );
1024 MOV.L @(disp, Rm), Rn {:
1025 load_reg( R_ECX, Rm );
1026 ADD_imm8s_r32( disp, R_ECX );
1027 check_ralign32( R_ECX );
1028 MEM_READ_LONG( R_ECX, R_EAX );
1029 store_reg( R_EAX, Rn );
1032 load_reg( R_ECX, Rn );
1033 check_walign16( R_ECX );
1034 MEM_READ_WORD( R_ECX, R_EAX );
1035 store_reg( R_EAX, Rn );
1038 load_reg( R_ECX, Rn );
1039 check_walign16( R_ECX );
1040 load_reg( R_EAX, Rm );
1041 ADD_imm8s_r32( -2, R_ECX );
1042 MEM_WRITE_WORD( R_ECX, R_EAX );
1044 MOV.W Rm, @(R0, Rn) {:
1045 load_reg( R_EAX, 0 );
1046 load_reg( R_ECX, Rn );
1047 ADD_r32_r32( R_EAX, R_ECX );
1048 check_walign16( R_ECX );
1049 load_reg( R_EAX, Rm );
1050 MEM_WRITE_WORD( R_ECX, R_EAX );
1052 MOV.W R0, @(disp, GBR) {:
1053 load_spreg( R_ECX, R_GBR );
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 );
1059 MOV.W R0, @(disp, Rn) {:
1060 load_reg( R_ECX, Rn );
1061 load_reg( R_EAX, 0 );
1062 ADD_imm32_r32( disp, R_ECX );
1063 check_walign16( R_ECX );
1064 MEM_WRITE_WORD( R_ECX, R_EAX );
1067 load_reg( R_ECX, Rm );
1068 check_ralign16( R_ECX );
1069 MEM_READ_WORD( R_ECX, R_EAX );
1070 store_reg( R_EAX, Rn );
1073 load_reg( R_EAX, Rm );
1074 check_ralign16( R_EAX );
1075 MOV_r32_r32( R_EAX, R_ECX );
1076 ADD_imm8s_r32( 2, R_EAX );
1077 store_reg( R_EAX, Rm );
1078 MEM_READ_WORD( R_ECX, R_EAX );
1079 store_reg( R_EAX, Rn );
1081 MOV.W @(R0, Rm), Rn {:
1082 load_reg( R_EAX, 0 );
1083 load_reg( R_ECX, Rm );
1084 ADD_r32_r32( R_EAX, R_ECX );
1085 check_ralign16( R_ECX );
1086 MEM_READ_WORD( R_ECX, R_EAX );
1087 store_reg( R_EAX, Rn );
1089 MOV.W @(disp, GBR), R0 {:
1090 load_spreg( R_ECX, R_GBR );
1091 ADD_imm32_r32( disp, R_ECX );
1092 check_ralign16( R_ECX );
1093 MEM_READ_WORD( R_ECX, R_EAX );
1094 store_reg( R_EAX, 0 );
1096 MOV.W @(disp, PC), Rn {:
1097 if( sh4_x86.in_delay_slot ) {
1100 load_imm32( R_ECX, pc + disp + 4 );
1101 MEM_READ_WORD( R_ECX, R_EAX );
1102 store_reg( R_EAX, Rn );
1105 MOV.W @(disp, Rm), R0 {:
1106 load_reg( R_ECX, Rm );
1107 ADD_imm32_r32( disp, R_ECX );
1108 check_ralign16( R_ECX );
1109 MEM_READ_WORD( R_ECX, R_EAX );
1110 store_reg( R_EAX, 0 );
1112 MOVA @(disp, PC), R0 {:
1113 if( sh4_x86.in_delay_slot ) {
1116 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1117 store_reg( R_ECX, 0 );
1121 load_reg( R_EAX, 0 );
1122 load_reg( R_ECX, Rn );
1123 check_walign32( R_ECX );
1124 MEM_WRITE_LONG( R_ECX, R_EAX );
1127 /* Control transfer instructions */
1129 if( sh4_x86.in_delay_slot ) {
1132 load_imm32( R_EDI, pc + 2 );
1133 CMP_imm8s_sh4r( 0, R_T );
1135 load_imm32( R_EDI, disp + pc + 4 );
1141 if( sh4_x86.in_delay_slot ) {
1144 load_imm32( R_EDI, pc + 2 );
1145 CMP_imm8s_sh4r( 0, R_T );
1147 load_imm32( R_EDI, disp + pc + 4 );
1148 sh4_x86.in_delay_slot = TRUE;
1154 if( sh4_x86.in_delay_slot ) {
1157 load_imm32( R_EDI, disp + pc + 4 );
1158 sh4_x86.in_delay_slot = TRUE;
1164 if( sh4_x86.in_delay_slot ) {
1167 load_reg( R_EDI, Rn );
1168 sh4_x86.in_delay_slot = TRUE;
1174 if( sh4_x86.in_delay_slot ) {
1177 load_imm32( R_EAX, pc + 4 );
1178 store_spreg( R_EAX, R_PR );
1179 load_imm32( R_EDI, disp + pc + 4 );
1180 sh4_x86.in_delay_slot = TRUE;
1186 if( sh4_x86.in_delay_slot ) {
1189 load_imm32( R_EAX, pc + 4 );
1190 store_spreg( R_EAX, R_PR );
1191 load_reg( R_EDI, Rn );
1192 ADD_r32_r32( R_EAX, R_EDI );
1193 sh4_x86.in_delay_slot = TRUE;
1199 if( sh4_x86.in_delay_slot ) {
1202 load_imm32( R_EDI, pc + 2 );
1203 CMP_imm8s_sh4r( 0, R_T );
1205 load_imm32( R_EDI, disp + pc + 4 );
1211 if( sh4_x86.in_delay_slot ) {
1214 load_imm32( R_EDI, pc + 2 );
1215 CMP_imm8s_sh4r( 0, R_T );
1217 load_imm32( R_EDI, disp + pc + 4 );
1218 sh4_x86.in_delay_slot = TRUE;
1224 if( sh4_x86.in_delay_slot ) {
1227 load_reg( R_EDI, Rn );
1228 sh4_x86.in_delay_slot = TRUE;
1234 if( sh4_x86.in_delay_slot ) {
1237 load_imm32( R_EAX, pc + 4 );
1238 store_spreg( R_EAX, R_PR );
1239 load_reg( R_EDI, Rn );
1240 sh4_x86.in_delay_slot = TRUE;
1247 if( sh4_x86.in_delay_slot ) {
1250 load_spreg( R_EDI, R_PR );
1251 load_spreg( R_EAX, R_SSR );
1252 call_func1( sh4_write_sr, R_EAX );
1253 sh4_x86.in_delay_slot = TRUE;
1254 sh4_x86.priv_checked = FALSE;
1255 sh4_x86.fpuen_checked = FALSE;
1261 if( sh4_x86.in_delay_slot ) {
1264 load_spreg( R_EDI, R_PR );
1265 sh4_x86.in_delay_slot = TRUE;
1271 if( sh4_x86.in_delay_slot ) {
1275 RAISE_EXCEPTION(EXC_TRAP);
1279 if( sh4_x86.in_delay_slot ) {
1280 RAISE_EXCEPTION(EXC_SLOT_ILLEGAL);
1282 RAISE_EXCEPTION(EXC_ILLEGAL);
1288 XOR_r32_r32(R_EAX, R_EAX);
1289 store_spreg( R_EAX, R_MACL );
1290 store_spreg( R_EAX, R_MACH );
1309 /* Floating point moves */
1311 /* As horrible as this looks, it's actually covering 5 separate cases:
1312 * 1. 32-bit fr-to-fr (PR=0)
1313 * 2. 64-bit dr-to-dr (PR=1, FRm&1 == 0, FRn&1 == 0 )
1314 * 3. 64-bit dr-to-xd (PR=1, FRm&1 == 0, FRn&1 == 1 )
1315 * 4. 64-bit xd-to-dr (PR=1, FRm&1 == 1, FRn&1 == 0 )
1316 * 5. 64-bit xd-to-xd (PR=1, FRm&1 == 1, FRn&1 == 1 )
1319 load_spreg( R_ECX, R_FPSCR );
1320 load_fr_bank( R_EDX );
1321 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1323 load_fr( R_EDX, R_EAX, FRm ); // PR=0 branch
1324 store_fr( R_EDX, R_EAX, FRn );
1327 load_xf_bank( R_ECX );
1328 load_fr( R_ECX, R_EAX, FRm-1 );
1330 load_fr( R_ECX, R_EDX, FRm );
1331 store_fr( R_ECX, R_EAX, FRn-1 );
1332 store_fr( R_ECX, R_EDX, FRn );
1333 } else /* FRn&1 == 0 */ {
1334 load_fr( R_ECX, R_ECX, FRm );
1335 store_fr( R_EDX, R_EAX, FRn-1 );
1336 store_fr( R_EDX, R_ECX, FRn );
1338 } else /* FRm&1 == 0 */ {
1341 load_xf_bank( R_ECX );
1342 load_fr( R_EDX, R_EAX, FRm );
1343 load_fr( R_EDX, R_EDX, FRm+1 );
1344 store_fr( R_ECX, R_EAX, FRn-1 );
1345 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 );
1357 load_reg( R_EDX, Rn );
1358 check_walign32( R_EDX );
1359 load_spreg( R_ECX, R_FPSCR );
1360 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1362 load_fr_bank( R_ECX );
1363 load_fr( R_ECX, R_EAX, FRm );
1364 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1367 load_xf_bank( R_ECX );
1370 load_fr_bank( R_ECX );
1372 load_fr( R_ECX, R_EAX, FRm&0x0E );
1373 load_fr( R_ECX, R_ECX, FRm|0x01 );
1374 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1378 load_reg( R_EDX, Rm );
1379 check_ralign32( R_EDX );
1380 load_spreg( R_ECX, R_FPSCR );
1381 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1383 MEM_READ_LONG( R_EDX, R_EAX );
1384 load_fr_bank( R_ECX );
1385 store_fr( R_ECX, R_EAX, FRn );
1388 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1389 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1390 load_xf_bank( R_ECX );
1393 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1394 load_fr_bank( R_ECX );
1396 store_fr( R_ECX, R_EAX, FRn&0x0E );
1397 store_fr( R_ECX, R_EDX, FRn|0x01 );
1401 load_reg( R_EDX, Rn );
1402 check_walign32( R_EDX );
1403 load_spreg( R_ECX, R_FPSCR );
1404 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1406 load_fr_bank( R_ECX );
1407 load_fr( R_ECX, R_EAX, FRm );
1408 ADD_imm8s_r32(-4,R_EDX);
1409 store_reg( R_EDX, Rn );
1410 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1413 load_xf_bank( R_ECX );
1416 load_fr_bank( R_ECX );
1418 load_fr( R_ECX, R_EAX, FRm&0x0E );
1419 load_fr( R_ECX, R_ECX, FRm|0x01 );
1420 ADD_imm8s_r32(-8,R_EDX);
1421 store_reg( R_EDX, Rn );
1422 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1426 load_reg( R_EDX, Rm );
1427 check_ralign32( R_EDX );
1428 MOV_r32_r32( R_EDX, R_EAX );
1429 load_spreg( R_ECX, R_FPSCR );
1430 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1432 ADD_imm8s_r32( 4, R_EAX );
1433 store_reg( R_EAX, Rm );
1434 MEM_READ_LONG( R_EDX, R_EAX );
1435 load_fr_bank( R_ECX );
1436 store_fr( R_ECX, R_EAX, FRn );
1439 ADD_imm8s_r32( 8, R_EAX );
1440 store_reg(R_EAX, Rm);
1441 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1442 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1443 load_xf_bank( R_ECX );
1446 ADD_imm8s_r32( 8, R_EAX );
1447 store_reg(R_EAX, Rm);
1448 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1449 load_fr_bank( R_ECX );
1451 store_fr( R_ECX, R_EAX, FRn&0x0E );
1452 store_fr( R_ECX, R_EDX, FRn|0x01 );
1454 FMOV FRm, @(R0, Rn) {:
1456 load_reg( R_EDX, Rn );
1457 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
1458 check_walign32( R_EDX );
1459 load_spreg( R_ECX, R_FPSCR );
1460 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1462 load_fr_bank( R_ECX );
1463 load_fr( R_ECX, R_EAX, FRm );
1464 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1467 load_xf_bank( R_ECX );
1470 load_fr_bank( R_ECX );
1472 load_fr( R_ECX, R_EAX, FRm&0x0E );
1473 load_fr( R_ECX, R_ECX, FRm|0x01 );
1474 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1476 FMOV @(R0, Rm), FRn {:
1478 load_reg( R_EDX, Rm );
1479 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
1480 check_ralign32( R_EDX );
1481 load_spreg( R_ECX, R_FPSCR );
1482 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1484 MEM_READ_LONG( R_EDX, R_EAX );
1485 load_fr_bank( R_ECX );
1486 store_fr( R_ECX, R_EAX, FRn );
1489 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1490 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1491 load_xf_bank( R_ECX );
1494 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1495 load_fr_bank( R_ECX );
1497 store_fr( R_ECX, R_EAX, FRn&0x0E );
1498 store_fr( R_ECX, R_EDX, FRn|0x01 );
1500 FLDI0 FRn {: /* IFF PR=0 */
1502 load_spreg( R_ECX, R_FPSCR );
1503 TEST_imm32_r32( FPSCR_PR, R_ECX );
1505 XOR_r32_r32( R_EAX, R_EAX );
1506 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1507 store_fr( R_ECX, R_EAX, FRn );
1509 FLDI1 FRn {: /* IFF PR=0 */
1511 load_spreg( R_ECX, R_FPSCR );
1512 TEST_imm32_r32( FPSCR_PR, R_ECX );
1514 load_imm32(R_EAX, 0x3F800000);
1515 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1516 store_fr( R_ECX, R_EAX, FRn );
1521 load_spreg( R_ECX, R_FPSCR );
1522 load_spreg(R_EDX, REG_OFFSET(fr_bank));
1524 TEST_imm32_r32( FPSCR_PR, R_ECX );
1526 pop_fr( R_EDX, FRn );
1528 pop_dr( R_EDX, FRn );
1536 load_fr_bank( R_ECX );
1537 load_fr( R_ECX, R_EAX, FRm );
1538 store_spreg( R_EAX, R_FPUL );
1542 load_fr_bank( R_ECX );
1543 load_spreg( R_EAX, R_FPUL );
1544 store_fr( R_ECX, R_EAX, FRn );
1548 load_spreg( R_ECX, R_FPSCR );
1549 TEST_imm32_r32( FPSCR_PR, R_ECX );
1550 JE_rel8(9); // only when PR=1
1551 load_fr_bank( R_ECX );
1552 push_dr( R_ECX, FRm );
1558 load_spreg( R_ECX, R_FPSCR );
1559 TEST_imm32_r32( FPSCR_PR, R_ECX );
1560 JE_rel8(9); // only when PR=1
1561 load_fr_bank( R_ECX );
1563 pop_dr( R_ECX, FRn );
1566 /* Floating point instructions */
1569 load_spreg( R_ECX, R_FPSCR );
1570 load_fr_bank( R_EDX );
1571 TEST_imm32_r32( FPSCR_PR, R_ECX );
1573 push_fr(R_EDX, FRn); // 3
1575 pop_fr( R_EDX, FRn); //3
1577 push_dr(R_EDX, FRn);
1583 load_spreg( R_ECX, R_FPSCR );
1584 TEST_imm32_r32( FPSCR_PR, R_ECX );
1585 load_fr_bank( R_EDX );
1587 push_fr(R_EDX, FRm);
1588 push_fr(R_EDX, FRn);
1592 push_dr(R_EDX, FRm);
1593 push_dr(R_EDX, FRn);
1599 load_spreg( R_ECX, R_FPSCR );
1600 TEST_imm32_r32( FPSCR_PR, R_ECX );
1601 load_fr_bank( R_EDX );
1603 push_fr(R_EDX, FRn);
1604 push_fr(R_EDX, FRm);
1608 push_dr(R_EDX, FRn);
1609 push_dr(R_EDX, FRm);
1613 FMAC FR0, FRm, FRn {:
1615 load_spreg( R_ECX, R_FPSCR );
1616 load_spreg( R_EDX, REG_OFFSET(fr_bank));
1617 TEST_imm32_r32( FPSCR_PR, R_ECX );
1619 push_fr( R_EDX, 0 );
1620 push_fr( R_EDX, FRm );
1622 push_fr( R_EDX, FRn );
1624 pop_fr( R_EDX, FRn );
1626 push_dr( R_EDX, 0 );
1627 push_dr( R_EDX, FRm );
1629 push_dr( R_EDX, FRn );
1631 pop_dr( R_EDX, FRn );
1636 load_spreg( R_ECX, R_FPSCR );
1637 TEST_imm32_r32( FPSCR_PR, R_ECX );
1638 load_fr_bank( R_EDX );
1640 push_fr(R_EDX, FRm);
1641 push_fr(R_EDX, FRn);
1645 push_dr(R_EDX, FRm);
1646 push_dr(R_EDX, FRn);
1652 load_spreg( R_ECX, R_FPSCR );
1653 TEST_imm32_r32( FPSCR_PR, R_ECX );
1654 load_fr_bank( R_EDX );
1656 push_fr(R_EDX, FRn);
1660 push_dr(R_EDX, FRn);
1666 load_spreg( R_ECX, R_FPSCR );
1667 TEST_imm32_r32( FPSCR_PR, R_ECX );
1668 load_fr_bank( R_EDX );
1669 JNE_rel8(12); // PR=0 only
1671 push_fr(R_EDX, FRn);
1678 load_spreg( R_ECX, R_FPSCR );
1679 TEST_imm32_r32( FPSCR_PR, R_ECX );
1680 load_fr_bank( R_EDX );
1682 push_fr(R_EDX, FRn);
1686 push_dr(R_EDX, FRn);
1692 load_spreg( R_ECX, R_FPSCR );
1693 TEST_imm32_r32( FPSCR_PR, R_ECX );
1694 load_fr_bank( R_EDX );
1696 push_fr(R_EDX, FRn);
1697 push_fr(R_EDX, FRm);
1701 push_dr(R_EDX, FRn);
1702 push_dr(R_EDX, FRm);
1709 load_spreg( R_ECX, R_FPSCR );
1710 TEST_imm32_r32( FPSCR_PR, R_ECX );
1711 load_fr_bank( R_EDX );
1713 push_fr(R_EDX, FRm);
1714 push_fr(R_EDX, FRn);
1716 push_dr(R_EDX, FRm);
1717 push_dr(R_EDX, FRn);
1724 load_spreg( R_ECX, R_FPSCR );
1725 TEST_imm32_r32( FPSCR_PR, R_ECX );
1726 load_fr_bank( R_EDX );
1728 push_fr(R_EDX, FRm);
1729 push_fr(R_EDX, FRn);
1731 push_dr(R_EDX, FRm);
1732 push_dr(R_EDX, FRn);
1750 load_spreg( R_ECX, R_FPSCR );
1751 XOR_imm32_r32( FPSCR_FR, R_ECX );
1752 store_spreg( R_ECX, R_FPSCR );
1757 load_spreg( R_ECX, R_FPSCR );
1758 XOR_imm32_r32( FPSCR_SZ, R_ECX );
1759 store_spreg( R_ECX, R_FPSCR );
1762 /* Processor control instructions */
1764 load_reg( R_EAX, Rm );
1765 call_func1( sh4_write_sr, R_EAX );
1766 sh4_x86.priv_checked = FALSE;
1767 sh4_x86.fpuen_checked = FALSE;
1770 load_reg( R_EAX, Rm );
1771 store_spreg( R_EAX, R_GBR );
1774 load_reg( R_EAX, Rm );
1775 store_spreg( R_EAX, R_VBR );
1778 load_reg( R_EAX, Rm );
1779 store_spreg( R_EAX, R_SSR );
1782 load_reg( R_EAX, Rm );
1783 store_spreg( R_EAX, R_SGR );
1786 load_reg( R_EAX, Rm );
1787 store_spreg( R_EAX, R_SPC );
1790 load_reg( R_EAX, Rm );
1791 store_spreg( R_EAX, R_DBR );
1794 load_reg( R_EAX, Rm );
1795 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1798 load_reg( R_EAX, Rm );
1799 MOV_r32_r32( R_EAX, R_ECX );
1800 ADD_imm8s_r32( 4, R_EAX );
1801 store_reg( R_EAX, Rm );
1802 MEM_READ_LONG( R_ECX, R_EAX );
1803 store_spreg( R_EAX, R_GBR );
1806 load_reg( R_EAX, Rm );
1807 MOV_r32_r32( R_EAX, R_ECX );
1808 ADD_imm8s_r32( 4, R_EAX );
1809 store_reg( R_EAX, Rm );
1810 MEM_READ_LONG( R_ECX, R_EAX );
1811 call_func1( sh4_write_sr, R_EAX );
1812 sh4_x86.priv_checked = FALSE;
1813 sh4_x86.fpuen_checked = FALSE;
1816 load_reg( R_EAX, Rm );
1817 MOV_r32_r32( R_EAX, R_ECX );
1818 ADD_imm8s_r32( 4, R_EAX );
1819 store_reg( R_EAX, Rm );
1820 MEM_READ_LONG( R_ECX, R_EAX );
1821 store_spreg( R_EAX, R_VBR );
1824 load_reg( R_EAX, Rm );
1825 MOV_r32_r32( R_EAX, R_ECX );
1826 ADD_imm8s_r32( 4, R_EAX );
1827 store_reg( R_EAX, Rm );
1828 MEM_READ_LONG( R_ECX, R_EAX );
1829 store_spreg( R_EAX, R_SSR );
1832 load_reg( R_EAX, Rm );
1833 MOV_r32_r32( R_EAX, R_ECX );
1834 ADD_imm8s_r32( 4, R_EAX );
1835 store_reg( R_EAX, Rm );
1836 MEM_READ_LONG( R_ECX, R_EAX );
1837 store_spreg( R_EAX, R_SGR );
1840 load_reg( R_EAX, Rm );
1841 MOV_r32_r32( R_EAX, R_ECX );
1842 ADD_imm8s_r32( 4, R_EAX );
1843 store_reg( R_EAX, Rm );
1844 MEM_READ_LONG( R_ECX, R_EAX );
1845 store_spreg( R_EAX, R_SPC );
1848 load_reg( R_EAX, Rm );
1849 MOV_r32_r32( R_EAX, R_ECX );
1850 ADD_imm8s_r32( 4, R_EAX );
1851 store_reg( R_EAX, Rm );
1852 MEM_READ_LONG( R_ECX, R_EAX );
1853 store_spreg( R_EAX, R_DBR );
1855 LDC.L @Rm+, Rn_BANK {:
1856 load_reg( R_EAX, Rm );
1857 MOV_r32_r32( R_EAX, R_ECX );
1858 ADD_imm8s_r32( 4, R_EAX );
1859 store_reg( R_EAX, Rm );
1860 MEM_READ_LONG( R_ECX, R_EAX );
1861 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1864 load_reg( R_EAX, Rm );
1865 store_spreg( R_EAX, R_FPSCR );
1867 LDS.L @Rm+, FPSCR {:
1868 load_reg( R_EAX, Rm );
1869 MOV_r32_r32( R_EAX, R_ECX );
1870 ADD_imm8s_r32( 4, R_EAX );
1871 store_reg( R_EAX, Rm );
1872 MEM_READ_LONG( R_ECX, R_EAX );
1873 store_spreg( R_EAX, R_FPSCR );
1876 load_reg( R_EAX, Rm );
1877 store_spreg( R_EAX, R_FPUL );
1880 load_reg( R_EAX, Rm );
1881 MOV_r32_r32( R_EAX, R_ECX );
1882 ADD_imm8s_r32( 4, R_EAX );
1883 store_reg( R_EAX, Rm );
1884 MEM_READ_LONG( R_ECX, R_EAX );
1885 store_spreg( R_EAX, R_FPUL );
1888 load_reg( R_EAX, Rm );
1889 store_spreg( R_EAX, R_MACH );
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_MACH );
1900 load_reg( R_EAX, Rm );
1901 store_spreg( R_EAX, R_MACL );
1904 load_reg( R_EAX, Rm );
1905 MOV_r32_r32( R_EAX, R_ECX );
1906 ADD_imm8s_r32( 4, R_EAX );
1907 store_reg( R_EAX, Rm );
1908 MEM_READ_LONG( R_ECX, R_EAX );
1909 store_spreg( R_EAX, R_MACL );
1912 load_reg( R_EAX, Rm );
1913 store_spreg( R_EAX, R_PR );
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_PR );
1928 load_reg( R_EAX, Rn );
1930 AND_imm32_r32( 0xFC000000, R_EAX );
1931 CMP_imm32_r32( 0xE0000000, R_EAX );
1933 call_func0( sh4_flush_store_queue );
1934 ADD_imm8s_r32( 4, R_ESP );
1936 SLEEP {: /* TODO */ :}
1938 call_func0(sh4_read_sr);
1939 store_reg( R_EAX, Rn );
1942 load_spreg( R_EAX, R_GBR );
1943 store_reg( R_EAX, Rn );
1946 load_spreg( R_EAX, R_VBR );
1947 store_reg( R_EAX, Rn );
1950 load_spreg( R_EAX, R_SSR );
1951 store_reg( R_EAX, Rn );
1954 load_spreg( R_EAX, R_SPC );
1955 store_reg( R_EAX, Rn );
1958 load_spreg( R_EAX, R_SGR );
1959 store_reg( R_EAX, Rn );
1962 load_spreg( R_EAX, R_DBR );
1963 store_reg( R_EAX, Rn );
1966 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
1967 store_reg( R_EAX, Rn );
1970 load_reg( R_ECX, Rn );
1971 ADD_imm8s_r32( -4, Rn );
1972 store_reg( R_ECX, Rn );
1973 call_func0( sh4_read_sr );
1974 MEM_WRITE_LONG( R_ECX, R_EAX );
1977 load_reg( R_ECX, Rn );
1978 ADD_imm8s_r32( -4, Rn );
1979 store_reg( R_ECX, Rn );
1980 load_spreg( R_EAX, R_VBR );
1981 MEM_WRITE_LONG( R_ECX, R_EAX );
1984 load_reg( R_ECX, Rn );
1985 ADD_imm8s_r32( -4, Rn );
1986 store_reg( R_ECX, Rn );
1987 load_spreg( R_EAX, R_SSR );
1988 MEM_WRITE_LONG( R_ECX, R_EAX );
1991 load_reg( R_ECX, Rn );
1992 ADD_imm8s_r32( -4, Rn );
1993 store_reg( R_ECX, Rn );
1994 load_spreg( R_EAX, R_SPC );
1995 MEM_WRITE_LONG( R_ECX, R_EAX );
1998 load_reg( R_ECX, Rn );
1999 ADD_imm8s_r32( -4, Rn );
2000 store_reg( R_ECX, Rn );
2001 load_spreg( R_EAX, R_SGR );
2002 MEM_WRITE_LONG( R_ECX, R_EAX );
2005 load_reg( R_ECX, Rn );
2006 ADD_imm8s_r32( -4, Rn );
2007 store_reg( R_ECX, Rn );
2008 load_spreg( R_EAX, R_DBR );
2009 MEM_WRITE_LONG( R_ECX, R_EAX );
2011 STC.L Rm_BANK, @-Rn {:
2012 load_reg( R_ECX, Rn );
2013 ADD_imm8s_r32( -4, Rn );
2014 store_reg( R_ECX, Rn );
2015 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2016 MEM_WRITE_LONG( R_ECX, R_EAX );
2019 load_reg( R_ECX, Rn );
2020 ADD_imm8s_r32( -4, Rn );
2021 store_reg( R_ECX, Rn );
2022 load_spreg( R_EAX, R_GBR );
2023 MEM_WRITE_LONG( R_ECX, R_EAX );
2026 load_spreg( R_EAX, R_FPSCR );
2027 store_reg( R_EAX, Rn );
2029 STS.L FPSCR, @-Rn {:
2030 load_reg( R_ECX, Rn );
2031 ADD_imm8s_r32( -4, Rn );
2032 store_reg( R_ECX, Rn );
2033 load_spreg( R_EAX, R_FPSCR );
2034 MEM_WRITE_LONG( R_ECX, R_EAX );
2037 load_spreg( R_EAX, R_FPUL );
2038 store_reg( R_EAX, Rn );
2041 load_reg( R_ECX, Rn );
2042 ADD_imm8s_r32( -4, Rn );
2043 store_reg( R_ECX, Rn );
2044 load_spreg( R_EAX, R_FPUL );
2045 MEM_WRITE_LONG( R_ECX, R_EAX );
2048 load_spreg( R_EAX, R_MACH );
2049 store_reg( R_EAX, Rn );
2052 load_reg( R_ECX, Rn );
2053 ADD_imm8s_r32( -4, Rn );
2054 store_reg( R_ECX, Rn );
2055 load_spreg( R_EAX, R_MACH );
2056 MEM_WRITE_LONG( R_ECX, R_EAX );
2059 load_spreg( R_EAX, R_MACL );
2060 store_reg( R_EAX, Rn );
2063 load_reg( R_ECX, Rn );
2064 ADD_imm8s_r32( -4, Rn );
2065 store_reg( R_ECX, Rn );
2066 load_spreg( R_EAX, R_MACL );
2067 MEM_WRITE_LONG( R_ECX, R_EAX );
2070 load_spreg( R_EAX, R_PR );
2071 store_reg( R_EAX, Rn );
2074 load_reg( R_ECX, Rn );
2075 ADD_imm8s_r32( -4, Rn );
2076 store_reg( R_ECX, Rn );
2077 load_spreg( R_EAX, R_PR );
2078 MEM_WRITE_LONG( R_ECX, R_EAX );
2081 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}
2084 if( sh4_x86.in_delay_slot ) {
2085 sh4_x86.in_delay_slot = FALSE;
.