2 * $Id: sh4x86.c,v 1.16 2007-09-29 05:33:02 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.
28 #include "sh4/sh4core.h"
29 #include "sh4/sh4trans.h"
30 #include "sh4/sh4mmio.h"
31 #include "sh4/x86op.h"
34 #define DEFAULT_BACKPATCH_SIZE 4096
37 * Struct to manage internal translation state. This state is not saved -
38 * it is only valid between calls to sh4_translate_begin_block() and
39 * sh4_translate_end_block()
41 struct sh4_x86_state {
42 gboolean in_delay_slot;
43 gboolean priv_checked; /* true if we've already checked the cpu mode. */
44 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
45 gboolean branch_taken; /* true if we branched unconditionally */
46 uint32_t block_start_pc;
48 /* Allocated memory for the (block-wide) back-patch list */
49 uint32_t **backpatch_list;
50 uint32_t backpatch_posn;
51 uint32_t backpatch_size;
54 #define EXIT_DATA_ADDR_READ 0
55 #define EXIT_DATA_ADDR_WRITE 7
56 #define EXIT_ILLEGAL 14
57 #define EXIT_SLOT_ILLEGAL 21
58 #define EXIT_FPU_DISABLED 28
59 #define EXIT_SLOT_FPU_DISABLED 35
61 static struct sh4_x86_state sh4_x86;
63 static uint32_t max_int = 0x7FFFFFFF;
64 static uint32_t min_int = 0x80000000;
65 static uint32_t save_fcw; /* save value for fpu control word */
66 static uint32_t trunc_fcw = 0x0F7F; /* fcw value for truncation mode */
70 sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
71 sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(uint32_t *);
75 static void sh4_x86_add_backpatch( uint8_t *ptr )
77 if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
78 sh4_x86.backpatch_size <<= 1;
79 sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list, sh4_x86.backpatch_size * sizeof(uint32_t *) );
80 assert( sh4_x86.backpatch_list != NULL );
82 sh4_x86.backpatch_list[sh4_x86.backpatch_posn++] = (uint32_t *)ptr;
85 static void sh4_x86_do_backpatch( uint8_t *reloc_base )
88 for( i=0; i<sh4_x86.backpatch_posn; i++ ) {
89 *sh4_x86.backpatch_list[i] += (reloc_base - ((uint8_t *)sh4_x86.backpatch_list[i]) - 4);
94 * Emit an instruction to load an SH4 reg into a real register
96 static inline void load_reg( int x86reg, int sh4reg )
100 OP(0x45 + (x86reg<<3));
101 OP(REG_OFFSET(r[sh4reg]));
104 static inline void load_reg16s( int x86reg, int sh4reg )
108 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
111 static inline void load_reg16u( int x86reg, int sh4reg )
115 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
119 #define load_spreg( x86reg, regoff ) MOV_sh4r_r32( regoff, x86reg )
120 #define store_spreg( x86reg, regoff ) MOV_r32_sh4r( x86reg, regoff )
122 * Emit an instruction to load an immediate value into a register
124 static inline void load_imm32( int x86reg, uint32_t value ) {
125 /* mov #value, reg */
131 * Emit an instruction to store an SH4 reg (RN)
133 void static inline store_reg( int x86reg, int sh4reg ) {
134 /* mov reg, [bp+n] */
136 OP(0x45 + (x86reg<<3));
137 OP(REG_OFFSET(r[sh4reg]));
140 #define load_fr_bank(bankreg) load_spreg( bankreg, REG_OFFSET(fr_bank))
143 * Load an FR register (single-precision floating point) into an integer x86
144 * register (eg for register-to-register moves)
146 void static inline load_fr( int bankreg, int x86reg, int frm )
148 OP(0x8B); OP(0x40+bankreg+(x86reg<<3)); OP((frm^1)<<2);
152 * Store an FR register (single-precision floating point) into an integer x86
153 * register (eg for register-to-register moves)
155 void static inline store_fr( int bankreg, int x86reg, int frn )
157 OP(0x89); OP(0x40+bankreg+(x86reg<<3)); OP((frn^1)<<2);
162 * Load a pointer to the back fp back into the specified x86 register. The
163 * bankreg must have been previously loaded with FPSCR.
166 static inline void load_xf_bank( int bankreg )
169 SHR_imm8_r32( (21 - 6), bankreg ); // Extract bit 21 then *64 for bank size
170 AND_imm8s_r32( 0x40, bankreg ); // Complete extraction
171 OP(0x8D); OP(0x44+(bankreg<<3)); OP(0x28+bankreg); OP(REG_OFFSET(fr)); // LEA [ebp+bankreg+disp], bankreg
175 * Update the fr_bank pointer based on the current fpscr value.
177 static inline void update_fr_bank( int fpscrreg )
179 SHR_imm8_r32( (21 - 6), fpscrreg ); // Extract bit 21 then *64 for bank size
180 AND_imm8s_r32( 0x40, fpscrreg ); // Complete extraction
181 OP(0x8D); OP(0x44+(fpscrreg<<3)); OP(0x28+fpscrreg); OP(REG_OFFSET(fr)); // LEA [ebp+fpscrreg+disp], fpscrreg
182 store_spreg( fpscrreg, REG_OFFSET(fr_bank) );
185 * Push FPUL (as a 32-bit float) onto the FPU stack
187 static inline void push_fpul( )
189 OP(0xD9); OP(0x45); OP(R_FPUL);
193 * Pop FPUL (as a 32-bit float) from the FPU stack
195 static inline void pop_fpul( )
197 OP(0xD9); OP(0x5D); OP(R_FPUL);
201 * Push a 32-bit float onto the FPU stack, with bankreg previously loaded
202 * with the location of the current fp bank.
204 static inline void push_fr( int bankreg, int frm )
206 OP(0xD9); OP(0x40 + bankreg); OP((frm^1)<<2); // FLD.S [bankreg + frm^1*4]
210 * Pop a 32-bit float from the FPU stack and store it back into the fp bank,
211 * with bankreg previously loaded with the location of the current fp bank.
213 static inline void pop_fr( int bankreg, int frm )
215 OP(0xD9); OP(0x58 + bankreg); OP((frm^1)<<2); // FST.S [bankreg + frm^1*4]
219 * Push a 64-bit double onto the FPU stack, with bankreg previously loaded
220 * with the location of the current fp bank.
222 static inline void push_dr( int bankreg, int frm )
224 OP(0xDD); OP(0x40 + bankreg); OP(frm<<2); // FLD.D [bankreg + frm*4]
227 static inline void pop_dr( int bankreg, int frm )
229 OP(0xDD); OP(0x58 + bankreg); OP(frm<<2); // FST.D [bankreg + frm*4]
233 * Note: clobbers EAX to make the indirect call - this isn't usually
234 * a problem since the callee will usually clobber it anyway.
236 static inline void call_func0( void *ptr )
238 load_imm32(R_EAX, (uint32_t)ptr);
242 static inline void call_func1( void *ptr, int arg1 )
246 ADD_imm8s_r32( 4, R_ESP );
249 static inline void call_func2( void *ptr, int arg1, int arg2 )
254 ADD_imm8s_r32( 8, R_ESP );
258 * Write a double (64-bit) value into memory, with the first word in arg2a, and
259 * the second in arg2b
262 static inline void MEM_WRITE_DOUBLE( int addr, int arg2a, int arg2b )
264 ADD_imm8s_r32( 4, addr );
267 ADD_imm8s_r32( -4, addr );
270 call_func0(sh4_write_long);
271 ADD_imm8s_r32( 8, R_ESP );
272 call_func0(sh4_write_long);
273 ADD_imm8s_r32( 8, R_ESP );
277 * Read a double (64-bit) value from memory, writing the first word into arg2a
278 * and the second into arg2b. The addr must not be in EAX
281 static inline void MEM_READ_DOUBLE( int addr, int arg2a, int arg2b )
284 call_func0(sh4_read_long);
287 ADD_imm8s_r32( 4, addr );
289 call_func0(sh4_read_long);
290 ADD_imm8s_r32( 4, R_ESP );
291 MOV_r32_r32( R_EAX, arg2b );
295 /* Exception checks - Note that all exception checks will clobber EAX */
296 static void check_priv( )
298 if( !sh4_x86.priv_checked ) {
299 sh4_x86.priv_checked = TRUE;
300 load_spreg( R_EAX, R_SR );
301 AND_imm32_r32( SR_MD, R_EAX );
302 if( sh4_x86.in_delay_slot ) {
303 JE_exit( EXIT_SLOT_ILLEGAL );
305 JE_exit( EXIT_ILLEGAL );
310 static void check_fpuen( )
312 if( !sh4_x86.fpuen_checked ) {
313 sh4_x86.fpuen_checked = TRUE;
314 load_spreg( R_EAX, R_SR );
315 AND_imm32_r32( SR_FD, R_EAX );
316 if( sh4_x86.in_delay_slot ) {
317 JNE_exit(EXIT_SLOT_FPU_DISABLED);
319 JNE_exit(EXIT_FPU_DISABLED);
324 static void check_ralign16( int x86reg )
326 TEST_imm32_r32( 0x00000001, x86reg );
327 JNE_exit(EXIT_DATA_ADDR_READ);
330 static void check_walign16( int x86reg )
332 TEST_imm32_r32( 0x00000001, x86reg );
333 JNE_exit(EXIT_DATA_ADDR_WRITE);
336 static void check_ralign32( int x86reg )
338 TEST_imm32_r32( 0x00000003, x86reg );
339 JNE_exit(EXIT_DATA_ADDR_READ);
341 static void check_walign32( int x86reg )
343 TEST_imm32_r32( 0x00000003, x86reg );
344 JNE_exit(EXIT_DATA_ADDR_WRITE);
348 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
349 #define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
350 #define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
351 #define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
352 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
353 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
354 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
356 #define SLOTILLEGAL() JMP_exit(EXIT_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1;
361 * Emit the 'start of block' assembly. Sets up the stack frame and save
364 void sh4_translate_begin_block( sh4addr_t pc )
368 load_imm32( R_EBP, (uint32_t)&sh4r );
370 XOR_r32_r32(R_ESI, R_ESI);
372 sh4_x86.in_delay_slot = FALSE;
373 sh4_x86.priv_checked = FALSE;
374 sh4_x86.fpuen_checked = FALSE;
375 sh4_x86.branch_taken = FALSE;
376 sh4_x86.backpatch_posn = 0;
377 sh4_x86.block_start_pc = pc;
381 * Exit the block to an absolute PC
384 void exit_block( sh4addr_t pc, sh4addr_t endpc )
386 load_imm32( R_ECX, pc ); // 5
387 store_spreg( R_ECX, REG_OFFSET(pc) ); // 3
388 MOV_moff32_EAX( (uint32_t)xlat_get_lut_entry(pc) ); // 5
389 AND_imm8s_r32( 0xFC, R_EAX ); // 3
390 load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
391 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
398 * Exit the block with sh4r.pc already written
401 void exit_block_pcset( pc )
403 XOR_r32_r32( R_EAX, R_EAX ); // 2
404 load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
405 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
412 * Write the block trailer (exception handling block)
414 void sh4_translate_end_block( sh4addr_t pc ) {
415 if( sh4_x86.branch_taken == FALSE ) {
416 // Didn't exit unconditionally already, so write the termination here
417 exit_block( pc, pc );
419 if( sh4_x86.backpatch_posn != 0 ) {
420 uint8_t *end_ptr = xlat_output;
421 // Exception termination. Jump block for various exception codes:
422 PUSH_imm32( EXC_DATA_ADDR_READ );
423 JMP_rel8( 33, target1 );
424 PUSH_imm32( EXC_DATA_ADDR_WRITE );
425 JMP_rel8( 26, target2 );
426 PUSH_imm32( EXC_ILLEGAL );
427 JMP_rel8( 19, target3 );
428 PUSH_imm32( EXC_SLOT_ILLEGAL );
429 JMP_rel8( 12, target4 );
430 PUSH_imm32( EXC_FPU_DISABLED );
431 JMP_rel8( 5, target5 );
432 PUSH_imm32( EXC_SLOT_FPU_DISABLED );
439 load_spreg( R_ECX, REG_OFFSET(pc) );
440 ADD_r32_r32( R_ESI, R_ECX );
441 ADD_r32_r32( R_ESI, R_ECX );
442 store_spreg( R_ECX, REG_OFFSET(pc) );
443 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
444 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
446 ADD_r32_r32( R_EAX, R_ECX );
447 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
449 load_imm32( R_EAX, (uint32_t)sh4_raise_exception ); // 6
450 CALL_r32( R_EAX ); // 2
451 ADD_imm8s_r32( 4, R_ESP );
452 XOR_r32_r32( R_EAX, R_EAX );
457 sh4_x86_do_backpatch( end_ptr );
463 extern uint16_t *sh4_icache;
464 extern uint32_t sh4_icache_addr;
467 * Translate a single instruction. Delayed branches are handled specially
468 * by translating both branch and delayed instruction as a single unit (as
471 * @return true if the instruction marks the end of a basic block
474 uint32_t sh4_x86_translate_instruction( sh4addr_t pc )
477 /* Read instruction */
478 uint32_t pageaddr = pc >> 12;
479 if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
480 ir = sh4_icache[(pc&0xFFF)>>1];
482 sh4_icache = (uint16_t *)mem_get_page(pc);
483 if( ((uint32_t)sh4_icache) < MAX_IO_REGIONS ) {
484 /* If someone's actually been so daft as to try to execute out of an IO
485 * region, fallback on the full-blown memory read
488 ir = sh4_read_word(pc);
490 sh4_icache_addr = pageaddr;
491 ir = sh4_icache[(pc&0xFFF)>>1];
495 switch( (ir&0xF000) >> 12 ) {
499 switch( (ir&0x80) >> 7 ) {
501 switch( (ir&0x70) >> 4 ) {
504 uint32_t Rn = ((ir>>8)&0xF);
506 call_func0(sh4_read_sr);
507 store_reg( R_EAX, Rn );
512 uint32_t Rn = ((ir>>8)&0xF);
513 load_spreg( R_EAX, R_GBR );
514 store_reg( R_EAX, Rn );
519 uint32_t Rn = ((ir>>8)&0xF);
521 load_spreg( R_EAX, R_VBR );
522 store_reg( R_EAX, Rn );
527 uint32_t Rn = ((ir>>8)&0xF);
529 load_spreg( R_EAX, R_SSR );
530 store_reg( R_EAX, Rn );
535 uint32_t Rn = ((ir>>8)&0xF);
537 load_spreg( R_EAX, R_SPC );
538 store_reg( R_EAX, Rn );
547 { /* STC Rm_BANK, Rn */
548 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm_BANK = ((ir>>4)&0x7);
550 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
551 store_reg( R_EAX, Rn );
557 switch( (ir&0xF0) >> 4 ) {
560 uint32_t Rn = ((ir>>8)&0xF);
561 if( sh4_x86.in_delay_slot ) {
564 load_imm32( R_ECX, pc + 4 );
565 store_spreg( R_ECX, R_PR );
566 ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_ECX );
567 store_spreg( R_ECX, REG_OFFSET(pc) );
568 sh4_x86.in_delay_slot = TRUE;
569 sh4_x86_translate_instruction( pc + 2 );
570 exit_block_pcset(pc+2);
571 sh4_x86.branch_taken = TRUE;
578 uint32_t Rn = ((ir>>8)&0xF);
579 if( sh4_x86.in_delay_slot ) {
582 load_reg( R_EAX, Rn );
583 ADD_imm32_r32( pc + 4, R_EAX );
584 store_spreg( R_EAX, REG_OFFSET(pc) );
585 sh4_x86.in_delay_slot = TRUE;
586 sh4_x86_translate_instruction( pc + 2 );
587 exit_block_pcset(pc+2);
588 sh4_x86.branch_taken = TRUE;
595 uint32_t Rn = ((ir>>8)&0xF);
596 load_reg( R_EAX, Rn );
598 AND_imm32_r32( 0xFC000000, R_EAX );
599 CMP_imm32_r32( 0xE0000000, R_EAX );
601 call_func0( sh4_flush_store_queue );
603 ADD_imm8s_r32( 4, R_ESP );
608 uint32_t Rn = ((ir>>8)&0xF);
613 uint32_t Rn = ((ir>>8)&0xF);
618 uint32_t Rn = ((ir>>8)&0xF);
622 { /* MOVCA.L R0, @Rn */
623 uint32_t Rn = ((ir>>8)&0xF);
624 load_reg( R_EAX, 0 );
625 load_reg( R_ECX, Rn );
626 check_walign32( R_ECX );
627 MEM_WRITE_LONG( R_ECX, R_EAX );
636 { /* MOV.B Rm, @(R0, Rn) */
637 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
638 load_reg( R_EAX, 0 );
639 load_reg( R_ECX, Rn );
640 ADD_r32_r32( R_EAX, R_ECX );
641 load_reg( R_EAX, Rm );
642 MEM_WRITE_BYTE( R_ECX, R_EAX );
646 { /* MOV.W Rm, @(R0, Rn) */
647 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
648 load_reg( R_EAX, 0 );
649 load_reg( R_ECX, Rn );
650 ADD_r32_r32( R_EAX, R_ECX );
651 check_walign16( R_ECX );
652 load_reg( R_EAX, Rm );
653 MEM_WRITE_WORD( R_ECX, R_EAX );
657 { /* MOV.L Rm, @(R0, Rn) */
658 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
659 load_reg( R_EAX, 0 );
660 load_reg( R_ECX, Rn );
661 ADD_r32_r32( R_EAX, R_ECX );
662 check_walign32( R_ECX );
663 load_reg( R_EAX, Rm );
664 MEM_WRITE_LONG( R_ECX, R_EAX );
669 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
670 load_reg( R_EAX, Rm );
671 load_reg( R_ECX, Rn );
673 store_spreg( R_EAX, R_MACL );
677 switch( (ir&0xFF0) >> 4 ) {
692 XOR_r32_r32(R_EAX, R_EAX);
693 store_spreg( R_EAX, R_MACL );
694 store_spreg( R_EAX, R_MACH );
719 switch( (ir&0xF0) >> 4 ) {
722 /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */
727 XOR_r32_r32( R_EAX, R_EAX );
728 store_spreg( R_EAX, R_Q );
729 store_spreg( R_EAX, R_M );
730 store_spreg( R_EAX, R_T );
735 uint32_t Rn = ((ir>>8)&0xF);
736 load_spreg( R_EAX, R_T );
737 store_reg( R_EAX, Rn );
746 switch( (ir&0xF0) >> 4 ) {
749 uint32_t Rn = ((ir>>8)&0xF);
750 load_spreg( R_EAX, R_MACH );
751 store_reg( R_EAX, Rn );
756 uint32_t Rn = ((ir>>8)&0xF);
757 load_spreg( R_EAX, R_MACL );
758 store_reg( R_EAX, Rn );
763 uint32_t Rn = ((ir>>8)&0xF);
764 load_spreg( R_EAX, R_PR );
765 store_reg( R_EAX, Rn );
770 uint32_t Rn = ((ir>>8)&0xF);
772 load_spreg( R_EAX, R_SGR );
773 store_reg( R_EAX, Rn );
778 uint32_t Rn = ((ir>>8)&0xF);
779 load_spreg( R_EAX, R_FPUL );
780 store_reg( R_EAX, Rn );
784 { /* STS FPSCR, Rn */
785 uint32_t Rn = ((ir>>8)&0xF);
786 load_spreg( R_EAX, R_FPSCR );
787 store_reg( R_EAX, Rn );
792 uint32_t Rn = ((ir>>8)&0xF);
794 load_spreg( R_EAX, R_DBR );
795 store_reg( R_EAX, Rn );
804 switch( (ir&0xFF0) >> 4 ) {
807 if( sh4_x86.in_delay_slot ) {
810 load_spreg( R_ECX, R_PR );
811 store_spreg( R_ECX, REG_OFFSET(pc) );
812 sh4_x86.in_delay_slot = TRUE;
813 sh4_x86_translate_instruction(pc+2);
814 exit_block_pcset(pc+2);
815 sh4_x86.branch_taken = TRUE;
823 call_func0( sh4_sleep );
824 sh4_x86.in_delay_slot = FALSE;
831 if( sh4_x86.in_delay_slot ) {
835 load_spreg( R_ECX, R_SPC );
836 store_spreg( R_ECX, REG_OFFSET(pc) );
837 load_spreg( R_EAX, R_SSR );
838 call_func1( sh4_write_sr, R_EAX );
839 sh4_x86.in_delay_slot = TRUE;
840 sh4_x86.priv_checked = FALSE;
841 sh4_x86.fpuen_checked = FALSE;
842 sh4_x86_translate_instruction(pc+2);
843 exit_block_pcset(pc+2);
844 sh4_x86.branch_taken = TRUE;
855 { /* MOV.B @(R0, Rm), Rn */
856 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
857 load_reg( R_EAX, 0 );
858 load_reg( R_ECX, Rm );
859 ADD_r32_r32( R_EAX, R_ECX );
860 MEM_READ_BYTE( R_ECX, R_EAX );
861 store_reg( R_EAX, Rn );
865 { /* MOV.W @(R0, Rm), Rn */
866 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
867 load_reg( R_EAX, 0 );
868 load_reg( R_ECX, Rm );
869 ADD_r32_r32( R_EAX, R_ECX );
870 check_ralign16( R_ECX );
871 MEM_READ_WORD( R_ECX, R_EAX );
872 store_reg( R_EAX, Rn );
876 { /* MOV.L @(R0, Rm), Rn */
877 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
878 load_reg( R_EAX, 0 );
879 load_reg( R_ECX, Rm );
880 ADD_r32_r32( R_EAX, R_ECX );
881 check_ralign32( R_ECX );
882 MEM_READ_LONG( R_ECX, R_EAX );
883 store_reg( R_EAX, Rn );
887 { /* MAC.L @Rm+, @Rn+ */
888 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
889 load_reg( R_ECX, Rm );
890 check_ralign32( R_ECX );
891 load_reg( R_ECX, Rn );
892 check_ralign32( R_ECX );
893 ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) );
894 MEM_READ_LONG( R_ECX, R_EAX );
896 load_reg( R_ECX, Rm );
897 ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
898 MEM_READ_LONG( R_ECX, R_EAX );
901 ADD_r32_sh4r( R_EAX, R_MACL );
902 ADC_r32_sh4r( R_EDX, R_MACH );
904 load_spreg( R_ECX, R_S );
905 TEST_r32_r32(R_ECX, R_ECX);
907 call_func0( signsat48 );
917 { /* MOV.L Rm, @(disp, Rn) */
918 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<2;
919 load_reg( R_ECX, Rn );
920 load_reg( R_EAX, Rm );
921 ADD_imm32_r32( disp, R_ECX );
922 check_walign32( R_ECX );
923 MEM_WRITE_LONG( R_ECX, R_EAX );
929 { /* MOV.B Rm, @Rn */
930 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
931 load_reg( R_EAX, Rm );
932 load_reg( R_ECX, Rn );
933 MEM_WRITE_BYTE( R_ECX, R_EAX );
937 { /* MOV.W Rm, @Rn */
938 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
939 load_reg( R_ECX, Rn );
940 check_walign16( R_ECX );
941 load_reg( R_EAX, Rm );
942 MEM_WRITE_WORD( R_ECX, R_EAX );
946 { /* MOV.L Rm, @Rn */
947 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
948 load_reg( R_EAX, Rm );
949 load_reg( R_ECX, Rn );
950 check_walign32(R_ECX);
951 MEM_WRITE_LONG( R_ECX, R_EAX );
955 { /* MOV.B Rm, @-Rn */
956 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
957 load_reg( R_EAX, Rm );
958 load_reg( R_ECX, Rn );
959 ADD_imm8s_r32( -1, R_ECX );
960 store_reg( R_ECX, Rn );
961 MEM_WRITE_BYTE( R_ECX, R_EAX );
965 { /* MOV.W Rm, @-Rn */
966 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
967 load_reg( R_ECX, Rn );
968 check_walign16( R_ECX );
969 load_reg( R_EAX, Rm );
970 ADD_imm8s_r32( -2, R_ECX );
971 store_reg( R_ECX, Rn );
972 MEM_WRITE_WORD( R_ECX, R_EAX );
976 { /* MOV.L Rm, @-Rn */
977 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
978 load_reg( R_EAX, Rm );
979 load_reg( R_ECX, Rn );
980 check_walign32( R_ECX );
981 ADD_imm8s_r32( -4, R_ECX );
982 store_reg( R_ECX, Rn );
983 MEM_WRITE_LONG( R_ECX, R_EAX );
988 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
989 load_reg( R_EAX, Rm );
990 load_reg( R_ECX, Rn );
991 SHR_imm8_r32( 31, R_EAX );
992 SHR_imm8_r32( 31, R_ECX );
993 store_spreg( R_EAX, R_M );
994 store_spreg( R_ECX, R_Q );
995 CMP_r32_r32( R_EAX, R_ECX );
1001 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1002 load_reg( R_EAX, Rm );
1003 load_reg( R_ECX, Rn );
1004 TEST_r32_r32( R_EAX, R_ECX );
1010 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1011 load_reg( R_EAX, Rm );
1012 load_reg( R_ECX, Rn );
1013 AND_r32_r32( R_EAX, R_ECX );
1014 store_reg( R_ECX, Rn );
1019 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1020 load_reg( R_EAX, Rm );
1021 load_reg( R_ECX, Rn );
1022 XOR_r32_r32( R_EAX, R_ECX );
1023 store_reg( R_ECX, Rn );
1028 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1029 load_reg( R_EAX, Rm );
1030 load_reg( R_ECX, Rn );
1031 OR_r32_r32( R_EAX, R_ECX );
1032 store_reg( R_ECX, Rn );
1036 { /* CMP/STR Rm, Rn */
1037 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1038 load_reg( R_EAX, Rm );
1039 load_reg( R_ECX, Rn );
1040 XOR_r32_r32( R_ECX, R_EAX );
1041 TEST_r8_r8( R_AL, R_AL );
1042 JE_rel8(13, target1);
1043 TEST_r8_r8( R_AH, R_AH ); // 2
1044 JE_rel8(9, target2);
1045 SHR_imm8_r32( 16, R_EAX ); // 3
1046 TEST_r8_r8( R_AL, R_AL ); // 2
1047 JE_rel8(2, target3);
1048 TEST_r8_r8( R_AH, R_AH ); // 2
1049 JMP_TARGET(target1);
1050 JMP_TARGET(target2);
1051 JMP_TARGET(target3);
1056 { /* XTRCT Rm, Rn */
1057 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1058 load_reg( R_EAX, Rm );
1059 load_reg( R_ECX, Rn );
1060 SHL_imm8_r32( 16, R_EAX );
1061 SHR_imm8_r32( 16, R_ECX );
1062 OR_r32_r32( R_EAX, R_ECX );
1063 store_reg( R_ECX, Rn );
1067 { /* MULU.W Rm, Rn */
1068 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1069 load_reg16u( R_EAX, Rm );
1070 load_reg16u( R_ECX, Rn );
1072 store_spreg( R_EAX, R_MACL );
1076 { /* MULS.W Rm, Rn */
1077 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1078 load_reg16s( R_EAX, Rm );
1079 load_reg16s( R_ECX, Rn );
1081 store_spreg( R_EAX, R_MACL );
1092 { /* CMP/EQ Rm, Rn */
1093 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1094 load_reg( R_EAX, Rm );
1095 load_reg( R_ECX, Rn );
1096 CMP_r32_r32( R_EAX, R_ECX );
1101 { /* CMP/HS Rm, Rn */
1102 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1103 load_reg( R_EAX, Rm );
1104 load_reg( R_ECX, Rn );
1105 CMP_r32_r32( R_EAX, R_ECX );
1110 { /* CMP/GE Rm, Rn */
1111 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1112 load_reg( R_EAX, Rm );
1113 load_reg( R_ECX, Rn );
1114 CMP_r32_r32( R_EAX, R_ECX );
1120 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1121 load_spreg( R_ECX, R_M );
1122 load_reg( R_EAX, Rn );
1125 SETC_r8( R_DL ); // Q'
1126 CMP_sh4r_r32( R_Q, R_ECX );
1127 JE_rel8(5, mqequal);
1128 ADD_sh4r_r32( REG_OFFSET(r[Rm]), R_EAX );
1130 JMP_TARGET(mqequal);
1131 SUB_sh4r_r32( REG_OFFSET(r[Rm]), R_EAX );
1133 store_reg( R_EAX, Rn ); // Done with Rn now
1134 SETC_r8(R_AL); // tmp1
1135 XOR_r8_r8( R_DL, R_AL ); // Q' = Q ^ tmp1
1136 XOR_r8_r8( R_AL, R_CL ); // Q'' = Q' ^ M
1137 store_spreg( R_ECX, R_Q );
1138 XOR_imm8s_r32( 1, R_AL ); // T = !Q'
1139 MOVZX_r8_r32( R_AL, R_EAX );
1140 store_spreg( R_EAX, R_T );
1144 { /* DMULU.L Rm, Rn */
1145 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1146 load_reg( R_EAX, Rm );
1147 load_reg( R_ECX, Rn );
1149 store_spreg( R_EDX, R_MACH );
1150 store_spreg( R_EAX, R_MACL );
1154 { /* CMP/HI Rm, Rn */
1155 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1156 load_reg( R_EAX, Rm );
1157 load_reg( R_ECX, Rn );
1158 CMP_r32_r32( R_EAX, R_ECX );
1163 { /* CMP/GT Rm, Rn */
1164 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1165 load_reg( R_EAX, Rm );
1166 load_reg( R_ECX, Rn );
1167 CMP_r32_r32( R_EAX, R_ECX );
1173 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1174 load_reg( R_EAX, Rm );
1175 load_reg( R_ECX, Rn );
1176 SUB_r32_r32( R_EAX, R_ECX );
1177 store_reg( R_ECX, Rn );
1182 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1183 load_reg( R_EAX, Rm );
1184 load_reg( R_ECX, Rn );
1186 SBB_r32_r32( R_EAX, R_ECX );
1187 store_reg( R_ECX, Rn );
1193 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1194 load_reg( R_EAX, Rm );
1195 load_reg( R_ECX, Rn );
1196 SUB_r32_r32( R_EAX, R_ECX );
1197 store_reg( R_ECX, Rn );
1203 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1204 load_reg( R_EAX, Rm );
1205 load_reg( R_ECX, Rn );
1206 ADD_r32_r32( R_EAX, R_ECX );
1207 store_reg( R_ECX, Rn );
1211 { /* DMULS.L Rm, Rn */
1212 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1213 load_reg( R_EAX, Rm );
1214 load_reg( R_ECX, Rn );
1216 store_spreg( R_EDX, R_MACH );
1217 store_spreg( R_EAX, R_MACL );
1222 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1223 load_reg( R_EAX, Rm );
1224 load_reg( R_ECX, Rn );
1226 ADC_r32_r32( R_EAX, R_ECX );
1227 store_reg( R_ECX, Rn );
1233 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1234 load_reg( R_EAX, Rm );
1235 load_reg( R_ECX, Rn );
1236 ADD_r32_r32( R_EAX, R_ECX );
1237 store_reg( R_ECX, Rn );
1249 switch( (ir&0xF0) >> 4 ) {
1252 uint32_t Rn = ((ir>>8)&0xF);
1253 load_reg( R_EAX, Rn );
1256 store_reg( R_EAX, Rn );
1261 uint32_t Rn = ((ir>>8)&0xF);
1262 load_reg( R_EAX, Rn );
1263 ADD_imm8s_r32( -1, R_EAX );
1264 store_reg( R_EAX, Rn );
1270 uint32_t Rn = ((ir>>8)&0xF);
1271 load_reg( R_EAX, Rn );
1274 store_reg( R_EAX, Rn );
1283 switch( (ir&0xF0) >> 4 ) {
1286 uint32_t Rn = ((ir>>8)&0xF);
1287 load_reg( R_EAX, Rn );
1290 store_reg( R_EAX, Rn );
1295 uint32_t Rn = ((ir>>8)&0xF);
1296 load_reg( R_EAX, Rn );
1297 CMP_imm8s_r32( 0, R_EAX );
1303 uint32_t Rn = ((ir>>8)&0xF);
1304 load_reg( R_EAX, Rn );
1307 store_reg( R_EAX, Rn );
1316 switch( (ir&0xF0) >> 4 ) {
1318 { /* STS.L MACH, @-Rn */
1319 uint32_t Rn = ((ir>>8)&0xF);
1320 load_reg( R_ECX, Rn );
1321 check_walign32( R_ECX );
1322 ADD_imm8s_r32( -4, R_ECX );
1323 store_reg( R_ECX, Rn );
1324 load_spreg( R_EAX, R_MACH );
1325 MEM_WRITE_LONG( R_ECX, R_EAX );
1329 { /* STS.L MACL, @-Rn */
1330 uint32_t Rn = ((ir>>8)&0xF);
1331 load_reg( R_ECX, Rn );
1332 check_walign32( R_ECX );
1333 ADD_imm8s_r32( -4, R_ECX );
1334 store_reg( R_ECX, Rn );
1335 load_spreg( R_EAX, R_MACL );
1336 MEM_WRITE_LONG( R_ECX, R_EAX );
1340 { /* STS.L PR, @-Rn */
1341 uint32_t Rn = ((ir>>8)&0xF);
1342 load_reg( R_ECX, Rn );
1343 check_walign32( R_ECX );
1344 ADD_imm8s_r32( -4, R_ECX );
1345 store_reg( R_ECX, Rn );
1346 load_spreg( R_EAX, R_PR );
1347 MEM_WRITE_LONG( R_ECX, R_EAX );
1351 { /* STC.L SGR, @-Rn */
1352 uint32_t Rn = ((ir>>8)&0xF);
1354 load_reg( R_ECX, Rn );
1355 check_walign32( R_ECX );
1356 ADD_imm8s_r32( -4, R_ECX );
1357 store_reg( R_ECX, Rn );
1358 load_spreg( R_EAX, R_SGR );
1359 MEM_WRITE_LONG( R_ECX, R_EAX );
1363 { /* STS.L FPUL, @-Rn */
1364 uint32_t Rn = ((ir>>8)&0xF);
1365 load_reg( R_ECX, Rn );
1366 check_walign32( R_ECX );
1367 ADD_imm8s_r32( -4, R_ECX );
1368 store_reg( R_ECX, Rn );
1369 load_spreg( R_EAX, R_FPUL );
1370 MEM_WRITE_LONG( R_ECX, R_EAX );
1374 { /* STS.L FPSCR, @-Rn */
1375 uint32_t Rn = ((ir>>8)&0xF);
1376 load_reg( R_ECX, Rn );
1377 check_walign32( R_ECX );
1378 ADD_imm8s_r32( -4, R_ECX );
1379 store_reg( R_ECX, Rn );
1380 load_spreg( R_EAX, R_FPSCR );
1381 MEM_WRITE_LONG( R_ECX, R_EAX );
1385 { /* STC.L DBR, @-Rn */
1386 uint32_t Rn = ((ir>>8)&0xF);
1388 load_reg( R_ECX, Rn );
1389 check_walign32( R_ECX );
1390 ADD_imm8s_r32( -4, R_ECX );
1391 store_reg( R_ECX, Rn );
1392 load_spreg( R_EAX, R_DBR );
1393 MEM_WRITE_LONG( R_ECX, R_EAX );
1402 switch( (ir&0x80) >> 7 ) {
1404 switch( (ir&0x70) >> 4 ) {
1406 { /* STC.L SR, @-Rn */
1407 uint32_t Rn = ((ir>>8)&0xF);
1409 call_func0( sh4_read_sr );
1410 load_reg( R_ECX, Rn );
1411 check_walign32( R_ECX );
1412 ADD_imm8s_r32( -4, R_ECX );
1413 store_reg( R_ECX, Rn );
1414 MEM_WRITE_LONG( R_ECX, R_EAX );
1418 { /* STC.L GBR, @-Rn */
1419 uint32_t Rn = ((ir>>8)&0xF);
1420 load_reg( R_ECX, Rn );
1421 check_walign32( R_ECX );
1422 ADD_imm8s_r32( -4, R_ECX );
1423 store_reg( R_ECX, Rn );
1424 load_spreg( R_EAX, R_GBR );
1425 MEM_WRITE_LONG( R_ECX, R_EAX );
1429 { /* STC.L VBR, @-Rn */
1430 uint32_t Rn = ((ir>>8)&0xF);
1432 load_reg( R_ECX, Rn );
1433 check_walign32( R_ECX );
1434 ADD_imm8s_r32( -4, R_ECX );
1435 store_reg( R_ECX, Rn );
1436 load_spreg( R_EAX, R_VBR );
1437 MEM_WRITE_LONG( R_ECX, R_EAX );
1441 { /* STC.L SSR, @-Rn */
1442 uint32_t Rn = ((ir>>8)&0xF);
1444 load_reg( R_ECX, Rn );
1445 check_walign32( R_ECX );
1446 ADD_imm8s_r32( -4, R_ECX );
1447 store_reg( R_ECX, Rn );
1448 load_spreg( R_EAX, R_SSR );
1449 MEM_WRITE_LONG( R_ECX, R_EAX );
1453 { /* STC.L SPC, @-Rn */
1454 uint32_t Rn = ((ir>>8)&0xF);
1456 load_reg( R_ECX, Rn );
1457 check_walign32( R_ECX );
1458 ADD_imm8s_r32( -4, R_ECX );
1459 store_reg( R_ECX, Rn );
1460 load_spreg( R_EAX, R_SPC );
1461 MEM_WRITE_LONG( R_ECX, R_EAX );
1470 { /* STC.L Rm_BANK, @-Rn */
1471 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm_BANK = ((ir>>4)&0x7);
1473 load_reg( R_ECX, Rn );
1474 check_walign32( R_ECX );
1475 ADD_imm8s_r32( -4, R_ECX );
1476 store_reg( R_ECX, Rn );
1477 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
1478 MEM_WRITE_LONG( R_ECX, R_EAX );
1484 switch( (ir&0xF0) >> 4 ) {
1487 uint32_t Rn = ((ir>>8)&0xF);
1488 load_reg( R_EAX, Rn );
1490 store_reg( R_EAX, Rn );
1496 uint32_t Rn = ((ir>>8)&0xF);
1497 load_reg( R_EAX, Rn );
1500 store_reg( R_EAX, Rn );
1510 switch( (ir&0xF0) >> 4 ) {
1513 uint32_t Rn = ((ir>>8)&0xF);
1514 load_reg( R_EAX, Rn );
1516 store_reg( R_EAX, Rn );
1522 uint32_t Rn = ((ir>>8)&0xF);
1523 load_reg( R_EAX, Rn );
1524 CMP_imm8s_r32( 0, R_EAX );
1530 uint32_t Rn = ((ir>>8)&0xF);
1531 load_reg( R_EAX, Rn );
1534 store_reg( R_EAX, Rn );
1544 switch( (ir&0xF0) >> 4 ) {
1546 { /* LDS.L @Rm+, MACH */
1547 uint32_t Rm = ((ir>>8)&0xF);
1548 load_reg( R_EAX, Rm );
1549 check_ralign32( R_EAX );
1550 MOV_r32_r32( R_EAX, R_ECX );
1551 ADD_imm8s_r32( 4, R_EAX );
1552 store_reg( R_EAX, Rm );
1553 MEM_READ_LONG( R_ECX, R_EAX );
1554 store_spreg( R_EAX, R_MACH );
1558 { /* LDS.L @Rm+, MACL */
1559 uint32_t Rm = ((ir>>8)&0xF);
1560 load_reg( R_EAX, Rm );
1561 check_ralign32( R_EAX );
1562 MOV_r32_r32( R_EAX, R_ECX );
1563 ADD_imm8s_r32( 4, R_EAX );
1564 store_reg( R_EAX, Rm );
1565 MEM_READ_LONG( R_ECX, R_EAX );
1566 store_spreg( R_EAX, R_MACL );
1570 { /* LDS.L @Rm+, PR */
1571 uint32_t Rm = ((ir>>8)&0xF);
1572 load_reg( R_EAX, Rm );
1573 check_ralign32( R_EAX );
1574 MOV_r32_r32( R_EAX, R_ECX );
1575 ADD_imm8s_r32( 4, R_EAX );
1576 store_reg( R_EAX, Rm );
1577 MEM_READ_LONG( R_ECX, R_EAX );
1578 store_spreg( R_EAX, R_PR );
1582 { /* LDC.L @Rm+, SGR */
1583 uint32_t Rm = ((ir>>8)&0xF);
1585 load_reg( R_EAX, Rm );
1586 check_ralign32( R_EAX );
1587 MOV_r32_r32( R_EAX, R_ECX );
1588 ADD_imm8s_r32( 4, R_EAX );
1589 store_reg( R_EAX, Rm );
1590 MEM_READ_LONG( R_ECX, R_EAX );
1591 store_spreg( R_EAX, R_SGR );
1595 { /* LDS.L @Rm+, FPUL */
1596 uint32_t Rm = ((ir>>8)&0xF);
1597 load_reg( R_EAX, Rm );
1598 check_ralign32( R_EAX );
1599 MOV_r32_r32( R_EAX, R_ECX );
1600 ADD_imm8s_r32( 4, R_EAX );
1601 store_reg( R_EAX, Rm );
1602 MEM_READ_LONG( R_ECX, R_EAX );
1603 store_spreg( R_EAX, R_FPUL );
1607 { /* LDS.L @Rm+, FPSCR */
1608 uint32_t Rm = ((ir>>8)&0xF);
1609 load_reg( R_EAX, Rm );
1610 check_ralign32( R_EAX );
1611 MOV_r32_r32( R_EAX, R_ECX );
1612 ADD_imm8s_r32( 4, R_EAX );
1613 store_reg( R_EAX, Rm );
1614 MEM_READ_LONG( R_ECX, R_EAX );
1615 store_spreg( R_EAX, R_FPSCR );
1616 update_fr_bank( R_EAX );
1620 { /* LDC.L @Rm+, DBR */
1621 uint32_t Rm = ((ir>>8)&0xF);
1623 load_reg( R_EAX, Rm );
1624 check_ralign32( R_EAX );
1625 MOV_r32_r32( R_EAX, R_ECX );
1626 ADD_imm8s_r32( 4, R_EAX );
1627 store_reg( R_EAX, Rm );
1628 MEM_READ_LONG( R_ECX, R_EAX );
1629 store_spreg( R_EAX, R_DBR );
1638 switch( (ir&0x80) >> 7 ) {
1640 switch( (ir&0x70) >> 4 ) {
1642 { /* LDC.L @Rm+, SR */
1643 uint32_t Rm = ((ir>>8)&0xF);
1644 if( sh4_x86.in_delay_slot ) {
1648 load_reg( R_EAX, Rm );
1649 check_ralign32( R_EAX );
1650 MOV_r32_r32( R_EAX, R_ECX );
1651 ADD_imm8s_r32( 4, R_EAX );
1652 store_reg( R_EAX, Rm );
1653 MEM_READ_LONG( R_ECX, R_EAX );
1654 call_func1( sh4_write_sr, R_EAX );
1655 sh4_x86.priv_checked = FALSE;
1656 sh4_x86.fpuen_checked = FALSE;
1661 { /* LDC.L @Rm+, GBR */
1662 uint32_t Rm = ((ir>>8)&0xF);
1663 load_reg( R_EAX, Rm );
1664 check_ralign32( R_EAX );
1665 MOV_r32_r32( R_EAX, R_ECX );
1666 ADD_imm8s_r32( 4, R_EAX );
1667 store_reg( R_EAX, Rm );
1668 MEM_READ_LONG( R_ECX, R_EAX );
1669 store_spreg( R_EAX, R_GBR );
1673 { /* LDC.L @Rm+, VBR */
1674 uint32_t Rm = ((ir>>8)&0xF);
1676 load_reg( R_EAX, Rm );
1677 check_ralign32( R_EAX );
1678 MOV_r32_r32( R_EAX, R_ECX );
1679 ADD_imm8s_r32( 4, R_EAX );
1680 store_reg( R_EAX, Rm );
1681 MEM_READ_LONG( R_ECX, R_EAX );
1682 store_spreg( R_EAX, R_VBR );
1686 { /* LDC.L @Rm+, SSR */
1687 uint32_t Rm = ((ir>>8)&0xF);
1689 load_reg( R_EAX, Rm );
1690 MOV_r32_r32( R_EAX, R_ECX );
1691 ADD_imm8s_r32( 4, R_EAX );
1692 store_reg( R_EAX, Rm );
1693 MEM_READ_LONG( R_ECX, R_EAX );
1694 store_spreg( R_EAX, R_SSR );
1698 { /* LDC.L @Rm+, SPC */
1699 uint32_t Rm = ((ir>>8)&0xF);
1701 load_reg( R_EAX, Rm );
1702 check_ralign32( R_EAX );
1703 MOV_r32_r32( R_EAX, R_ECX );
1704 ADD_imm8s_r32( 4, R_EAX );
1705 store_reg( R_EAX, Rm );
1706 MEM_READ_LONG( R_ECX, R_EAX );
1707 store_spreg( R_EAX, R_SPC );
1716 { /* LDC.L @Rm+, Rn_BANK */
1717 uint32_t Rm = ((ir>>8)&0xF); uint32_t Rn_BANK = ((ir>>4)&0x7);
1719 load_reg( R_EAX, Rm );
1720 check_ralign32( R_EAX );
1721 MOV_r32_r32( R_EAX, R_ECX );
1722 ADD_imm8s_r32( 4, R_EAX );
1723 store_reg( R_EAX, Rm );
1724 MEM_READ_LONG( R_ECX, R_EAX );
1725 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1731 switch( (ir&0xF0) >> 4 ) {
1734 uint32_t Rn = ((ir>>8)&0xF);
1735 load_reg( R_EAX, Rn );
1736 SHL_imm8_r32( 2, R_EAX );
1737 store_reg( R_EAX, Rn );
1742 uint32_t Rn = ((ir>>8)&0xF);
1743 load_reg( R_EAX, Rn );
1744 SHL_imm8_r32( 8, R_EAX );
1745 store_reg( R_EAX, Rn );
1750 uint32_t Rn = ((ir>>8)&0xF);
1751 load_reg( R_EAX, Rn );
1752 SHL_imm8_r32( 16, R_EAX );
1753 store_reg( R_EAX, Rn );
1762 switch( (ir&0xF0) >> 4 ) {
1765 uint32_t Rn = ((ir>>8)&0xF);
1766 load_reg( R_EAX, Rn );
1767 SHR_imm8_r32( 2, R_EAX );
1768 store_reg( R_EAX, Rn );
1773 uint32_t Rn = ((ir>>8)&0xF);
1774 load_reg( R_EAX, Rn );
1775 SHR_imm8_r32( 8, R_EAX );
1776 store_reg( R_EAX, Rn );
1781 uint32_t Rn = ((ir>>8)&0xF);
1782 load_reg( R_EAX, Rn );
1783 SHR_imm8_r32( 16, R_EAX );
1784 store_reg( R_EAX, Rn );
1793 switch( (ir&0xF0) >> 4 ) {
1795 { /* LDS Rm, MACH */
1796 uint32_t Rm = ((ir>>8)&0xF);
1797 load_reg( R_EAX, Rm );
1798 store_spreg( R_EAX, R_MACH );
1802 { /* LDS Rm, MACL */
1803 uint32_t Rm = ((ir>>8)&0xF);
1804 load_reg( R_EAX, Rm );
1805 store_spreg( R_EAX, R_MACL );
1810 uint32_t Rm = ((ir>>8)&0xF);
1811 load_reg( R_EAX, Rm );
1812 store_spreg( R_EAX, R_PR );
1817 uint32_t Rm = ((ir>>8)&0xF);
1819 load_reg( R_EAX, Rm );
1820 store_spreg( R_EAX, R_SGR );
1824 { /* LDS Rm, FPUL */
1825 uint32_t Rm = ((ir>>8)&0xF);
1826 load_reg( R_EAX, Rm );
1827 store_spreg( R_EAX, R_FPUL );
1831 { /* LDS Rm, FPSCR */
1832 uint32_t Rm = ((ir>>8)&0xF);
1833 load_reg( R_EAX, Rm );
1834 store_spreg( R_EAX, R_FPSCR );
1835 update_fr_bank( R_EAX );
1840 uint32_t Rm = ((ir>>8)&0xF);
1842 load_reg( R_EAX, Rm );
1843 store_spreg( R_EAX, R_DBR );
1852 switch( (ir&0xF0) >> 4 ) {
1855 uint32_t Rn = ((ir>>8)&0xF);
1856 if( sh4_x86.in_delay_slot ) {
1859 load_imm32( R_EAX, pc + 4 );
1860 store_spreg( R_EAX, R_PR );
1861 load_reg( R_ECX, Rn );
1862 store_spreg( R_ECX, REG_OFFSET(pc) );
1863 sh4_x86.in_delay_slot = TRUE;
1864 sh4_x86_translate_instruction(pc+2);
1865 exit_block_pcset(pc+2);
1866 sh4_x86.branch_taken = TRUE;
1873 uint32_t Rn = ((ir>>8)&0xF);
1874 load_reg( R_ECX, Rn );
1875 MEM_READ_BYTE( R_ECX, R_EAX );
1876 TEST_r8_r8( R_AL, R_AL );
1878 OR_imm8_r8( 0x80, R_AL );
1879 load_reg( R_ECX, Rn );
1880 MEM_WRITE_BYTE( R_ECX, R_EAX );
1885 uint32_t Rn = ((ir>>8)&0xF);
1886 if( sh4_x86.in_delay_slot ) {
1889 load_reg( R_ECX, Rn );
1890 store_spreg( R_ECX, REG_OFFSET(pc) );
1891 sh4_x86.in_delay_slot = TRUE;
1892 sh4_x86_translate_instruction(pc+2);
1893 exit_block_pcset(pc+2);
1894 sh4_x86.branch_taken = TRUE;
1906 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1907 /* Annoyingly enough, not directly convertible */
1908 load_reg( R_EAX, Rn );
1909 load_reg( R_ECX, Rm );
1910 CMP_imm32_r32( 0, R_ECX );
1911 JGE_rel8(16, doshl);
1913 NEG_r32( R_ECX ); // 2
1914 AND_imm8_r8( 0x1F, R_CL ); // 3
1915 JE_rel8( 4, emptysar); // 2
1916 SAR_r32_CL( R_EAX ); // 2
1917 JMP_rel8(10, end); // 2
1919 JMP_TARGET(emptysar);
1920 SAR_imm8_r32(31, R_EAX ); // 3
1924 AND_imm8_r8( 0x1F, R_CL ); // 3
1925 SHL_r32_CL( R_EAX ); // 2
1928 store_reg( R_EAX, Rn );
1933 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1934 load_reg( R_EAX, Rn );
1935 load_reg( R_ECX, Rm );
1936 CMP_imm32_r32( 0, R_ECX );
1937 JGE_rel8(15, doshl);
1939 NEG_r32( R_ECX ); // 2
1940 AND_imm8_r8( 0x1F, R_CL ); // 3
1941 JE_rel8( 4, emptyshr );
1942 SHR_r32_CL( R_EAX ); // 2
1943 JMP_rel8(9, end); // 2
1945 JMP_TARGET(emptyshr);
1946 XOR_r32_r32( R_EAX, R_EAX );
1950 AND_imm8_r8( 0x1F, R_CL ); // 3
1951 SHL_r32_CL( R_EAX ); // 2
1954 store_reg( R_EAX, Rn );
1958 switch( (ir&0x80) >> 7 ) {
1960 switch( (ir&0x70) >> 4 ) {
1963 uint32_t Rm = ((ir>>8)&0xF);
1964 if( sh4_x86.in_delay_slot ) {
1968 load_reg( R_EAX, Rm );
1969 call_func1( sh4_write_sr, R_EAX );
1970 sh4_x86.priv_checked = FALSE;
1971 sh4_x86.fpuen_checked = FALSE;
1977 uint32_t Rm = ((ir>>8)&0xF);
1978 load_reg( R_EAX, Rm );
1979 store_spreg( R_EAX, R_GBR );
1984 uint32_t Rm = ((ir>>8)&0xF);
1986 load_reg( R_EAX, Rm );
1987 store_spreg( R_EAX, R_VBR );
1992 uint32_t Rm = ((ir>>8)&0xF);
1994 load_reg( R_EAX, Rm );
1995 store_spreg( R_EAX, R_SSR );
2000 uint32_t Rm = ((ir>>8)&0xF);
2002 load_reg( R_EAX, Rm );
2003 store_spreg( R_EAX, R_SPC );
2012 { /* LDC Rm, Rn_BANK */
2013 uint32_t Rm = ((ir>>8)&0xF); uint32_t Rn_BANK = ((ir>>4)&0x7);
2015 load_reg( R_EAX, Rm );
2016 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
2022 { /* MAC.W @Rm+, @Rn+ */
2023 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2024 load_reg( R_ECX, Rm );
2025 check_ralign16( R_ECX );
2026 load_reg( R_ECX, Rn );
2027 check_ralign16( R_ECX );
2028 ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rn]) );
2029 MEM_READ_WORD( R_ECX, R_EAX );
2031 load_reg( R_ECX, Rm );
2032 ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) );
2033 MEM_READ_WORD( R_ECX, R_EAX );
2037 load_spreg( R_ECX, R_S );
2038 TEST_r32_r32( R_ECX, R_ECX );
2039 JE_rel8( 47, nosat );
2041 ADD_r32_sh4r( R_EAX, R_MACL ); // 6
2042 JNO_rel8( 51, end ); // 2
2043 load_imm32( R_EDX, 1 ); // 5
2044 store_spreg( R_EDX, R_MACH ); // 6
2045 JS_rel8( 13, positive ); // 2
2046 load_imm32( R_EAX, 0x80000000 );// 5
2047 store_spreg( R_EAX, R_MACL ); // 6
2048 JMP_rel8( 25, end2 ); // 2
2050 JMP_TARGET(positive);
2051 load_imm32( R_EAX, 0x7FFFFFFF );// 5
2052 store_spreg( R_EAX, R_MACL ); // 6
2053 JMP_rel8( 12, end3); // 2
2056 ADD_r32_sh4r( R_EAX, R_MACL ); // 6
2057 ADC_r32_sh4r( R_EDX, R_MACH ); // 6
2066 { /* MOV.L @(disp, Rm), Rn */
2067 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<2;
2068 load_reg( R_ECX, Rm );
2069 ADD_imm8s_r32( disp, R_ECX );
2070 check_ralign32( R_ECX );
2071 MEM_READ_LONG( R_ECX, R_EAX );
2072 store_reg( R_EAX, Rn );
2078 { /* MOV.B @Rm, Rn */
2079 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2080 load_reg( R_ECX, Rm );
2081 MEM_READ_BYTE( R_ECX, R_EAX );
2082 store_reg( R_EAX, Rn );
2086 { /* MOV.W @Rm, Rn */
2087 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2088 load_reg( R_ECX, Rm );
2089 check_ralign16( R_ECX );
2090 MEM_READ_WORD( R_ECX, R_EAX );
2091 store_reg( R_EAX, Rn );
2095 { /* MOV.L @Rm, Rn */
2096 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2097 load_reg( R_ECX, Rm );
2098 check_ralign32( R_ECX );
2099 MEM_READ_LONG( R_ECX, R_EAX );
2100 store_reg( R_EAX, Rn );
2105 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2106 load_reg( R_EAX, Rm );
2107 store_reg( R_EAX, Rn );
2111 { /* MOV.B @Rm+, Rn */
2112 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2113 load_reg( R_ECX, Rm );
2114 MOV_r32_r32( R_ECX, R_EAX );
2115 ADD_imm8s_r32( 1, R_EAX );
2116 store_reg( R_EAX, Rm );
2117 MEM_READ_BYTE( R_ECX, R_EAX );
2118 store_reg( R_EAX, Rn );
2122 { /* MOV.W @Rm+, Rn */
2123 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2124 load_reg( R_EAX, Rm );
2125 check_ralign16( R_EAX );
2126 MOV_r32_r32( R_EAX, R_ECX );
2127 ADD_imm8s_r32( 2, R_EAX );
2128 store_reg( R_EAX, Rm );
2129 MEM_READ_WORD( R_ECX, R_EAX );
2130 store_reg( R_EAX, Rn );
2134 { /* MOV.L @Rm+, Rn */
2135 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2136 load_reg( R_EAX, Rm );
2137 check_ralign32( R_EAX );
2138 MOV_r32_r32( R_EAX, R_ECX );
2139 ADD_imm8s_r32( 4, R_EAX );
2140 store_reg( R_EAX, Rm );
2141 MEM_READ_LONG( R_ECX, R_EAX );
2142 store_reg( R_EAX, Rn );
2147 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2148 load_reg( R_EAX, Rm );
2150 store_reg( R_EAX, Rn );
2154 { /* SWAP.B Rm, Rn */
2155 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2156 load_reg( R_EAX, Rm );
2157 XCHG_r8_r8( R_AL, R_AH );
2158 store_reg( R_EAX, Rn );
2162 { /* SWAP.W Rm, Rn */
2163 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2164 load_reg( R_EAX, Rm );
2165 MOV_r32_r32( R_EAX, R_ECX );
2166 SHL_imm8_r32( 16, R_ECX );
2167 SHR_imm8_r32( 16, R_EAX );
2168 OR_r32_r32( R_EAX, R_ECX );
2169 store_reg( R_ECX, Rn );
2174 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2175 load_reg( R_EAX, Rm );
2176 XOR_r32_r32( R_ECX, R_ECX );
2178 SBB_r32_r32( R_EAX, R_ECX );
2179 store_reg( R_ECX, Rn );
2185 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2186 load_reg( R_EAX, Rm );
2188 store_reg( R_EAX, Rn );
2192 { /* EXTU.B Rm, Rn */
2193 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2194 load_reg( R_EAX, Rm );
2195 MOVZX_r8_r32( R_EAX, R_EAX );
2196 store_reg( R_EAX, Rn );
2200 { /* EXTU.W Rm, Rn */
2201 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2202 load_reg( R_EAX, Rm );
2203 MOVZX_r16_r32( R_EAX, R_EAX );
2204 store_reg( R_EAX, Rn );
2208 { /* EXTS.B Rm, Rn */
2209 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2210 load_reg( R_EAX, Rm );
2211 MOVSX_r8_r32( R_EAX, R_EAX );
2212 store_reg( R_EAX, Rn );
2216 { /* EXTS.W Rm, Rn */
2217 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2218 load_reg( R_EAX, Rm );
2219 MOVSX_r16_r32( R_EAX, R_EAX );
2220 store_reg( R_EAX, Rn );
2226 { /* ADD #imm, Rn */
2227 uint32_t Rn = ((ir>>8)&0xF); int32_t imm = SIGNEXT8(ir&0xFF);
2228 load_reg( R_EAX, Rn );
2229 ADD_imm8s_r32( imm, R_EAX );
2230 store_reg( R_EAX, Rn );
2234 switch( (ir&0xF00) >> 8 ) {
2236 { /* MOV.B R0, @(disp, Rn) */
2237 uint32_t Rn = ((ir>>4)&0xF); uint32_t disp = (ir&0xF);
2238 load_reg( R_EAX, 0 );
2239 load_reg( R_ECX, Rn );
2240 ADD_imm32_r32( disp, R_ECX );
2241 MEM_WRITE_BYTE( R_ECX, R_EAX );
2245 { /* MOV.W R0, @(disp, Rn) */
2246 uint32_t Rn = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<1;
2247 load_reg( R_ECX, Rn );
2248 load_reg( R_EAX, 0 );
2249 ADD_imm32_r32( disp, R_ECX );
2250 check_walign16( R_ECX );
2251 MEM_WRITE_WORD( R_ECX, R_EAX );
2255 { /* MOV.B @(disp, Rm), R0 */
2256 uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF);
2257 load_reg( R_ECX, Rm );
2258 ADD_imm32_r32( disp, R_ECX );
2259 MEM_READ_BYTE( R_ECX, R_EAX );
2260 store_reg( R_EAX, 0 );
2264 { /* MOV.W @(disp, Rm), R0 */
2265 uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<1;
2266 load_reg( R_ECX, Rm );
2267 ADD_imm32_r32( disp, R_ECX );
2268 check_ralign16( R_ECX );
2269 MEM_READ_WORD( R_ECX, R_EAX );
2270 store_reg( R_EAX, 0 );
2274 { /* CMP/EQ #imm, R0 */
2275 int32_t imm = SIGNEXT8(ir&0xFF);
2276 load_reg( R_EAX, 0 );
2277 CMP_imm8s_r32(imm, R_EAX);
2283 int32_t disp = SIGNEXT8(ir&0xFF)<<1;
2284 if( sh4_x86.in_delay_slot ) {
2287 CMP_imm8s_sh4r( 0, R_T );
2288 JE_rel8( 30, nottaken );
2289 exit_block( disp + pc + 4, pc+2 );
2290 JMP_TARGET(nottaken);
2297 int32_t disp = SIGNEXT8(ir&0xFF)<<1;
2298 if( sh4_x86.in_delay_slot ) {
2301 CMP_imm8s_sh4r( 0, R_T );
2302 JNE_rel8( 30, nottaken );
2303 exit_block( disp + pc + 4, pc+2 );
2304 JMP_TARGET(nottaken);
2311 int32_t disp = SIGNEXT8(ir&0xFF)<<1;
2312 if( sh4_x86.in_delay_slot ) {
2315 sh4_x86.in_delay_slot = TRUE;
2316 CMP_imm8s_sh4r( 0, R_T );
2317 OP(0x0F); OP(0x84); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel32
2318 sh4_x86_translate_instruction(pc+2);
2319 exit_block( disp + pc + 4, pc+4 );
2321 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
2322 sh4_x86_translate_instruction(pc+2);
2329 int32_t disp = SIGNEXT8(ir&0xFF)<<1;
2330 if( sh4_x86.in_delay_slot ) {
2333 sh4_x86.in_delay_slot = TRUE;
2334 CMP_imm8s_sh4r( 0, R_T );
2335 OP(0x0F); OP(0x85); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel32
2336 sh4_x86_translate_instruction(pc+2);
2337 exit_block( disp + pc + 4, pc+4 );
2339 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
2340 sh4_x86_translate_instruction(pc+2);
2351 { /* MOV.W @(disp, PC), Rn */
2352 uint32_t Rn = ((ir>>8)&0xF); uint32_t disp = (ir&0xFF)<<1;
2353 if( sh4_x86.in_delay_slot ) {
2356 load_imm32( R_ECX, pc + disp + 4 );
2357 MEM_READ_WORD( R_ECX, R_EAX );
2358 store_reg( R_EAX, Rn );
2364 int32_t disp = SIGNEXT12(ir&0xFFF)<<1;
2365 if( sh4_x86.in_delay_slot ) {
2368 sh4_x86.in_delay_slot = TRUE;
2369 sh4_x86_translate_instruction( pc + 2 );
2370 exit_block( disp + pc + 4, pc+4 );
2371 sh4_x86.branch_taken = TRUE;
2378 int32_t disp = SIGNEXT12(ir&0xFFF)<<1;
2379 if( sh4_x86.in_delay_slot ) {
2382 load_imm32( R_EAX, pc + 4 );
2383 store_spreg( R_EAX, R_PR );
2384 sh4_x86.in_delay_slot = TRUE;
2385 sh4_x86_translate_instruction( pc + 2 );
2386 exit_block( disp + pc + 4, pc+4 );
2387 sh4_x86.branch_taken = TRUE;
2393 switch( (ir&0xF00) >> 8 ) {
2395 { /* MOV.B R0, @(disp, GBR) */
2396 uint32_t disp = (ir&0xFF);
2397 load_reg( R_EAX, 0 );
2398 load_spreg( R_ECX, R_GBR );
2399 ADD_imm32_r32( disp, R_ECX );
2400 MEM_WRITE_BYTE( R_ECX, R_EAX );
2404 { /* MOV.W R0, @(disp, GBR) */
2405 uint32_t disp = (ir&0xFF)<<1;
2406 load_spreg( R_ECX, R_GBR );
2407 load_reg( R_EAX, 0 );
2408 ADD_imm32_r32( disp, R_ECX );
2409 check_walign16( R_ECX );
2410 MEM_WRITE_WORD( R_ECX, R_EAX );
2414 { /* MOV.L R0, @(disp, GBR) */
2415 uint32_t disp = (ir&0xFF)<<2;
2416 load_spreg( R_ECX, R_GBR );
2417 load_reg( R_EAX, 0 );
2418 ADD_imm32_r32( disp, R_ECX );
2419 check_walign32( R_ECX );
2420 MEM_WRITE_LONG( R_ECX, R_EAX );
2425 uint32_t imm = (ir&0xFF);
2426 if( sh4_x86.in_delay_slot ) {
2430 call_func0( sh4_raise_trap );
2431 ADD_imm8s_r32( 4, R_ESP );
2432 exit_block_pcset(pc);
2433 sh4_x86.branch_taken = TRUE;
2439 { /* MOV.B @(disp, GBR), R0 */
2440 uint32_t disp = (ir&0xFF);
2441 load_spreg( R_ECX, R_GBR );
2442 ADD_imm32_r32( disp, R_ECX );
2443 MEM_READ_BYTE( R_ECX, R_EAX );
2444 store_reg( R_EAX, 0 );
2448 { /* MOV.W @(disp, GBR), R0 */
2449 uint32_t disp = (ir&0xFF)<<1;
2450 load_spreg( R_ECX, R_GBR );
2451 ADD_imm32_r32( disp, R_ECX );
2452 check_ralign16( R_ECX );
2453 MEM_READ_WORD( R_ECX, R_EAX );
2454 store_reg( R_EAX, 0 );
2458 { /* MOV.L @(disp, GBR), R0 */
2459 uint32_t disp = (ir&0xFF)<<2;
2460 load_spreg( R_ECX, R_GBR );
2461 ADD_imm32_r32( disp, R_ECX );
2462 check_ralign32( R_ECX );
2463 MEM_READ_LONG( R_ECX, R_EAX );
2464 store_reg( R_EAX, 0 );
2468 { /* MOVA @(disp, PC), R0 */
2469 uint32_t disp = (ir&0xFF)<<2;
2470 if( sh4_x86.in_delay_slot ) {
2473 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
2474 store_reg( R_ECX, 0 );
2479 { /* TST #imm, R0 */
2480 uint32_t imm = (ir&0xFF);
2481 load_reg( R_EAX, 0 );
2482 TEST_imm32_r32( imm, R_EAX );
2487 { /* AND #imm, R0 */
2488 uint32_t imm = (ir&0xFF);
2489 load_reg( R_EAX, 0 );
2490 AND_imm32_r32(imm, R_EAX);
2491 store_reg( R_EAX, 0 );
2495 { /* XOR #imm, R0 */
2496 uint32_t imm = (ir&0xFF);
2497 load_reg( R_EAX, 0 );
2498 XOR_imm32_r32( imm, R_EAX );
2499 store_reg( R_EAX, 0 );
2504 uint32_t imm = (ir&0xFF);
2505 load_reg( R_EAX, 0 );
2506 OR_imm32_r32(imm, R_EAX);
2507 store_reg( R_EAX, 0 );
2511 { /* TST.B #imm, @(R0, GBR) */
2512 uint32_t imm = (ir&0xFF);
2513 load_reg( R_EAX, 0);
2514 load_reg( R_ECX, R_GBR);
2515 ADD_r32_r32( R_EAX, R_ECX );
2516 MEM_READ_BYTE( R_ECX, R_EAX );
2517 TEST_imm8_r8( imm, R_AL );
2522 { /* AND.B #imm, @(R0, GBR) */
2523 uint32_t imm = (ir&0xFF);
2524 load_reg( R_EAX, 0 );
2525 load_spreg( R_ECX, R_GBR );
2526 ADD_r32_r32( R_EAX, R_ECX );
2528 call_func0(sh4_read_byte);
2530 AND_imm32_r32(imm, R_EAX );
2531 MEM_WRITE_BYTE( R_ECX, R_EAX );
2535 { /* XOR.B #imm, @(R0, GBR) */
2536 uint32_t imm = (ir&0xFF);
2537 load_reg( R_EAX, 0 );
2538 load_spreg( R_ECX, R_GBR );
2539 ADD_r32_r32( R_EAX, R_ECX );
2541 call_func0(sh4_read_byte);
2543 XOR_imm32_r32( imm, R_EAX );
2544 MEM_WRITE_BYTE( R_ECX, R_EAX );
2548 { /* OR.B #imm, @(R0, GBR) */
2549 uint32_t imm = (ir&0xFF);
2550 load_reg( R_EAX, 0 );
2551 load_spreg( R_ECX, R_GBR );
2552 ADD_r32_r32( R_EAX, R_ECX );
2554 call_func0(sh4_read_byte);
2556 OR_imm32_r32(imm, R_EAX );
2557 MEM_WRITE_BYTE( R_ECX, R_EAX );
2563 { /* MOV.L @(disp, PC), Rn */
2564 uint32_t Rn = ((ir>>8)&0xF); uint32_t disp = (ir&0xFF)<<2;
2565 if( sh4_x86.in_delay_slot ) {
2568 uint32_t target = (pc & 0xFFFFFFFC) + disp + 4;
2569 char *ptr = mem_get_region(target);
2571 MOV_moff32_EAX( (uint32_t)ptr );
2573 load_imm32( R_ECX, target );
2574 MEM_READ_LONG( R_ECX, R_EAX );
2576 store_reg( R_EAX, Rn );
2581 { /* MOV #imm, Rn */
2582 uint32_t Rn = ((ir>>8)&0xF); int32_t imm = SIGNEXT8(ir&0xFF);
2583 load_imm32( R_EAX, imm );
2584 store_reg( R_EAX, Rn );
2590 { /* FADD FRm, FRn */
2591 uint32_t FRn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2593 load_spreg( R_ECX, R_FPSCR );
2594 TEST_imm32_r32( FPSCR_PR, R_ECX );
2595 load_fr_bank( R_EDX );
2596 JNE_rel8(13,doubleprec);
2597 push_fr(R_EDX, FRm);
2598 push_fr(R_EDX, FRn);
2602 JMP_TARGET(doubleprec);
2603 push_dr(R_EDX, FRm);
2604 push_dr(R_EDX, FRn);
2611 { /* FSUB FRm, FRn */
2612 uint32_t FRn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2614 load_spreg( R_ECX, R_FPSCR );
2615 TEST_imm32_r32( FPSCR_PR, R_ECX );
2616 load_fr_bank( R_EDX );
2617 JNE_rel8(13, doubleprec);
2618 push_fr(R_EDX, FRn);
2619 push_fr(R_EDX, FRm);
2623 JMP_TARGET(doubleprec);
2624 push_dr(R_EDX, FRn);
2625 push_dr(R_EDX, FRm);
2632 { /* FMUL FRm, FRn */
2633 uint32_t FRn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2635 load_spreg( R_ECX, R_FPSCR );
2636 TEST_imm32_r32( FPSCR_PR, R_ECX );
2637 load_fr_bank( R_EDX );
2638 JNE_rel8(13, doubleprec);
2639 push_fr(R_EDX, FRm);
2640 push_fr(R_EDX, FRn);
2644 JMP_TARGET(doubleprec);
2645 push_dr(R_EDX, FRm);
2646 push_dr(R_EDX, FRn);
2653 { /* FDIV FRm, FRn */
2654 uint32_t FRn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2656 load_spreg( R_ECX, R_FPSCR );
2657 TEST_imm32_r32( FPSCR_PR, R_ECX );
2658 load_fr_bank( R_EDX );
2659 JNE_rel8(13, doubleprec);
2660 push_fr(R_EDX, FRn);
2661 push_fr(R_EDX, FRm);
2665 JMP_TARGET(doubleprec);
2666 push_dr(R_EDX, FRn);
2667 push_dr(R_EDX, FRm);
2674 { /* FCMP/EQ FRm, FRn */
2675 uint32_t FRn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2677 load_spreg( R_ECX, R_FPSCR );
2678 TEST_imm32_r32( FPSCR_PR, R_ECX );
2679 load_fr_bank( R_EDX );
2680 JNE_rel8(8, doubleprec);
2681 push_fr(R_EDX, FRm);
2682 push_fr(R_EDX, FRn);
2684 JMP_TARGET(doubleprec);
2685 push_dr(R_EDX, FRm);
2686 push_dr(R_EDX, FRn);
2694 { /* FCMP/GT FRm, FRn */
2695 uint32_t FRn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2697 load_spreg( R_ECX, R_FPSCR );
2698 TEST_imm32_r32( FPSCR_PR, R_ECX );
2699 load_fr_bank( R_EDX );
2700 JNE_rel8(8, doubleprec);
2701 push_fr(R_EDX, FRm);
2702 push_fr(R_EDX, FRn);
2704 JMP_TARGET(doubleprec);
2705 push_dr(R_EDX, FRm);
2706 push_dr(R_EDX, FRn);
2714 { /* FMOV @(R0, Rm), FRn */
2715 uint32_t FRn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2717 load_reg( R_EDX, Rm );
2718 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
2719 check_ralign32( R_EDX );
2720 load_spreg( R_ECX, R_FPSCR );
2721 TEST_imm32_r32( FPSCR_SZ, R_ECX );
2722 JNE_rel8(19, doublesize);
2723 MEM_READ_LONG( R_EDX, R_EAX );
2724 load_fr_bank( R_ECX );
2725 store_fr( R_ECX, R_EAX, FRn );
2728 JMP_TARGET(doublesize);
2729 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
2730 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
2731 load_xf_bank( R_ECX );
2732 store_fr( R_ECX, R_EAX, FRn&0x0E );
2733 store_fr( R_ECX, R_EDX, FRn|0x01 );
2737 JMP_TARGET(doublesize);
2738 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
2739 load_fr_bank( R_ECX );
2740 store_fr( R_ECX, R_EAX, FRn&0x0E );
2741 store_fr( R_ECX, R_EDX, FRn|0x01 );
2747 { /* FMOV FRm, @(R0, Rn) */
2748 uint32_t Rn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2750 load_reg( R_EDX, Rn );
2751 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
2752 check_walign32( R_EDX );
2753 load_spreg( R_ECX, R_FPSCR );
2754 TEST_imm32_r32( FPSCR_SZ, R_ECX );
2755 JNE_rel8(20, doublesize);
2756 load_fr_bank( R_ECX );
2757 load_fr( R_ECX, R_EAX, FRm );
2758 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
2760 JMP_rel8( 48, end );
2761 JMP_TARGET(doublesize);
2762 load_xf_bank( R_ECX );
2763 load_fr( R_ECX, R_EAX, FRm&0x0E );
2764 load_fr( R_ECX, R_ECX, FRm|0x01 );
2765 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
2768 JMP_rel8( 39, end );
2769 JMP_TARGET(doublesize);
2770 load_fr_bank( R_ECX );
2771 load_fr( R_ECX, R_EAX, FRm&0x0E );
2772 load_fr( R_ECX, R_ECX, FRm|0x01 );
2773 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
2779 { /* FMOV @Rm, FRn */
2780 uint32_t FRn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2782 load_reg( R_EDX, Rm );
2783 check_ralign32( R_EDX );
2784 load_spreg( R_ECX, R_FPSCR );
2785 TEST_imm32_r32( FPSCR_SZ, R_ECX );
2786 JNE_rel8(19, doublesize);
2787 MEM_READ_LONG( R_EDX, R_EAX );
2788 load_fr_bank( R_ECX );
2789 store_fr( R_ECX, R_EAX, FRn );
2792 JMP_TARGET(doublesize);
2793 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
2794 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
2795 load_xf_bank( R_ECX );
2796 store_fr( R_ECX, R_EAX, FRn&0x0E );
2797 store_fr( R_ECX, R_EDX, FRn|0x01 );
2801 JMP_TARGET(doublesize);
2802 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
2803 load_fr_bank( R_ECX );
2804 store_fr( R_ECX, R_EAX, FRn&0x0E );
2805 store_fr( R_ECX, R_EDX, FRn|0x01 );
2811 { /* FMOV @Rm+, FRn */
2812 uint32_t FRn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
2814 load_reg( R_EDX, Rm );
2815 check_ralign32( R_EDX );
2816 MOV_r32_r32( R_EDX, R_EAX );
2817 load_spreg( R_ECX, R_FPSCR );
2818 TEST_imm32_r32( FPSCR_SZ, R_ECX );
2819 JNE_rel8(25, doublesize);
2820 ADD_imm8s_r32( 4, R_EAX );
2821 store_reg( R_EAX, Rm );
2822 MEM_READ_LONG( R_EDX, R_EAX );
2823 load_fr_bank( R_ECX );
2824 store_fr( R_ECX, R_EAX, FRn );
2827 JMP_TARGET(doublesize);
2828 ADD_imm8s_r32( 8, R_EAX );
2829 store_reg(R_EAX, Rm);
2830 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
2831 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
2832 load_xf_bank( R_ECX );
2833 store_fr( R_ECX, R_EAX, FRn&0x0E );
2834 store_fr( R_ECX, R_EDX, FRn|0x01 );
2838 ADD_imm8s_r32( 8, R_EAX );
2839 store_reg(R_EAX, Rm);
2840 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
2841 load_fr_bank( R_ECX );
2842 store_fr( R_ECX, R_EAX, FRn&0x0E );
2843 store_fr( R_ECX, R_EDX, FRn|0x01 );
2849 { /* FMOV FRm, @Rn */
2850 uint32_t Rn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2852 load_reg( R_EDX, Rn );
2853 check_walign32( R_EDX );
2854 load_spreg( R_ECX, R_FPSCR );
2855 TEST_imm32_r32( FPSCR_SZ, R_ECX );
2856 JNE_rel8(20, doublesize);
2857 load_fr_bank( R_ECX );
2858 load_fr( R_ECX, R_EAX, FRm );
2859 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
2861 JMP_rel8( 48, end );
2862 JMP_TARGET(doublesize);
2863 load_xf_bank( R_ECX );
2864 load_fr( R_ECX, R_EAX, FRm&0x0E );
2865 load_fr( R_ECX, R_ECX, FRm|0x01 );
2866 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
2869 JMP_rel8( 39, end );
2870 JMP_TARGET(doublesize);
2871 load_fr_bank( R_ECX );
2872 load_fr( R_ECX, R_EAX, FRm&0x0E );
2873 load_fr( R_ECX, R_ECX, FRm|0x01 );
2874 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
2880 { /* FMOV FRm, @-Rn */
2881 uint32_t Rn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2883 load_reg( R_EDX, Rn );
2884 check_walign32( R_EDX );
2885 load_spreg( R_ECX, R_FPSCR );
2886 TEST_imm32_r32( FPSCR_SZ, R_ECX );
2887 JNE_rel8(26, doublesize);
2888 load_fr_bank( R_ECX );
2889 load_fr( R_ECX, R_EAX, FRm );
2890 ADD_imm8s_r32(-4,R_EDX);
2891 store_reg( R_EDX, Rn );
2892 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
2894 JMP_rel8( 54, end );
2895 JMP_TARGET(doublesize);
2896 load_xf_bank( R_ECX );
2897 load_fr( R_ECX, R_EAX, FRm&0x0E );
2898 load_fr( R_ECX, R_ECX, FRm|0x01 );
2899 ADD_imm8s_r32(-8,R_EDX);
2900 store_reg( R_EDX, Rn );
2901 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
2904 JMP_rel8( 45, end );
2905 JMP_TARGET(doublesize);
2906 load_fr_bank( R_ECX );
2907 load_fr( R_ECX, R_EAX, FRm&0x0E );
2908 load_fr( R_ECX, R_ECX, FRm|0x01 );
2909 ADD_imm8s_r32(-8,R_EDX);
2910 store_reg( R_EDX, Rn );
2911 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
2917 { /* FMOV FRm, FRn */
2918 uint32_t FRn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
2919 /* As horrible as this looks, it's actually covering 5 separate cases:
2920 * 1. 32-bit fr-to-fr (PR=0)
2921 * 2. 64-bit dr-to-dr (PR=1, FRm&1 == 0, FRn&1 == 0 )
2922 * 3. 64-bit dr-to-xd (PR=1, FRm&1 == 0, FRn&1 == 1 )
2923 * 4. 64-bit xd-to-dr (PR=1, FRm&1 == 1, FRn&1 == 0 )
2924 * 5. 64-bit xd-to-xd (PR=1, FRm&1 == 1, FRn&1 == 1 )
2927 load_spreg( R_ECX, R_FPSCR );
2928 load_fr_bank( R_EDX );
2929 TEST_imm32_r32( FPSCR_SZ, R_ECX );
2930 JNE_rel8(8, doublesize);
2931 load_fr( R_EDX, R_EAX, FRm ); // PR=0 branch
2932 store_fr( R_EDX, R_EAX, FRn );
2935 JMP_TARGET(doublesize);
2936 load_xf_bank( R_ECX );
2937 load_fr( R_ECX, R_EAX, FRm-1 );
2939 load_fr( R_ECX, R_EDX, FRm );
2940 store_fr( R_ECX, R_EAX, FRn-1 );
2941 store_fr( R_ECX, R_EDX, FRn );
2942 } else /* FRn&1 == 0 */ {
2943 load_fr( R_ECX, R_ECX, FRm );
2944 store_fr( R_EDX, R_EAX, FRn );
2945 store_fr( R_EDX, R_ECX, FRn+1 );
2948 } else /* FRm&1 == 0 */ {
2951 load_xf_bank( R_ECX );
2952 load_fr( R_EDX, R_EAX, FRm );
2953 load_fr( R_EDX, R_EDX, FRm+1 );
2954 store_fr( R_ECX, R_EAX, FRn-1 );
2955 store_fr( R_ECX, R_EDX, FRn );
2957 } else /* FRn&1 == 0 */ {
2959 load_fr( R_EDX, R_EAX, FRm );
2960 load_fr( R_EDX, R_ECX, FRm+1 );
2961 store_fr( R_EDX, R_EAX, FRn );
2962 store_fr( R_EDX, R_ECX, FRn+1 );
2969 switch( (ir&0xF0) >> 4 ) {
2971 { /* FSTS FPUL, FRn */
2972 uint32_t FRn = ((ir>>8)&0xF);
2974 load_fr_bank( R_ECX );
2975 load_spreg( R_EAX, R_FPUL );
2976 store_fr( R_ECX, R_EAX, FRn );
2980 { /* FLDS FRm, FPUL */
2981 uint32_t FRm = ((ir>>8)&0xF);
2983 load_fr_bank( R_ECX );
2984 load_fr( R_ECX, R_EAX, FRm );
2985 store_spreg( R_EAX, R_FPUL );
2989 { /* FLOAT FPUL, FRn */
2990 uint32_t FRn = ((ir>>8)&0xF);
2992 load_spreg( R_ECX, R_FPSCR );
2993 load_spreg(R_EDX, REG_OFFSET(fr_bank));
2995 TEST_imm32_r32( FPSCR_PR, R_ECX );
2996 JNE_rel8(5, doubleprec);
2997 pop_fr( R_EDX, FRn );
2999 JMP_TARGET(doubleprec);
3000 pop_dr( R_EDX, FRn );
3005 { /* FTRC FRm, FPUL */
3006 uint32_t FRm = ((ir>>8)&0xF);
3008 load_spreg( R_ECX, R_FPSCR );
3009 load_fr_bank( R_EDX );
3010 TEST_imm32_r32( FPSCR_PR, R_ECX );
3011 JNE_rel8(5, doubleprec);
3012 push_fr( R_EDX, FRm );
3014 JMP_TARGET(doubleprec);
3015 push_dr( R_EDX, FRm );
3017 load_imm32( R_ECX, (uint32_t)&max_int );
3018 FILD_r32ind( R_ECX );
3020 JNA_rel8( 32, sat );
3021 load_imm32( R_ECX, (uint32_t)&min_int ); // 5
3022 FILD_r32ind( R_ECX ); // 2
3024 JAE_rel8( 21, sat2 ); // 2
3025 load_imm32( R_EAX, (uint32_t)&save_fcw );
3026 FNSTCW_r32ind( R_EAX );
3027 load_imm32( R_EDX, (uint32_t)&trunc_fcw );
3028 FLDCW_r32ind( R_EDX );
3029 FISTP_sh4r(R_FPUL); // 3
3030 FLDCW_r32ind( R_EAX );
3031 JMP_rel8( 9, end ); // 2
3035 MOV_r32ind_r32( R_ECX, R_ECX ); // 2
3036 store_spreg( R_ECX, R_FPUL );
3043 uint32_t FRn = ((ir>>8)&0xF);
3045 load_spreg( R_ECX, R_FPSCR );
3046 TEST_imm32_r32( FPSCR_PR, R_ECX );
3047 load_fr_bank( R_EDX );
3048 JNE_rel8(10, doubleprec);
3049 push_fr(R_EDX, FRn);
3053 JMP_TARGET(doubleprec);
3054 push_dr(R_EDX, FRn);
3062 uint32_t FRn = ((ir>>8)&0xF);
3064 load_spreg( R_ECX, R_FPSCR );
3065 load_fr_bank( R_EDX );
3066 TEST_imm32_r32( FPSCR_PR, R_ECX );
3067 JNE_rel8(10, doubleprec);
3068 push_fr(R_EDX, FRn); // 3
3070 pop_fr( R_EDX, FRn); //3
3071 JMP_rel8(8,end); // 2
3072 JMP_TARGET(doubleprec);
3073 push_dr(R_EDX, FRn);
3081 uint32_t FRn = ((ir>>8)&0xF);
3083 load_spreg( R_ECX, R_FPSCR );
3084 TEST_imm32_r32( FPSCR_PR, R_ECX );
3085 load_fr_bank( R_EDX );
3086 JNE_rel8(10, doubleprec);
3087 push_fr(R_EDX, FRn);
3091 JMP_TARGET(doubleprec);
3092 push_dr(R_EDX, FRn);
3100 uint32_t FRn = ((ir>>8)&0xF);
3102 load_spreg( R_ECX, R_FPSCR );
3103 TEST_imm32_r32( FPSCR_PR, R_ECX );
3104 load_fr_bank( R_EDX );
3105 JNE_rel8(12, end); // PR=0 only
3107 push_fr(R_EDX, FRn);
3116 uint32_t FRn = ((ir>>8)&0xF);
3119 load_spreg( R_ECX, R_FPSCR );
3120 TEST_imm32_r32( FPSCR_PR, R_ECX );
3122 XOR_r32_r32( R_EAX, R_EAX );
3123 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
3124 store_fr( R_ECX, R_EAX, FRn );
3130 uint32_t FRn = ((ir>>8)&0xF);
3133 load_spreg( R_ECX, R_FPSCR );
3134 TEST_imm32_r32( FPSCR_PR, R_ECX );
3136 load_imm32(R_EAX, 0x3F800000);
3137 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
3138 store_fr( R_ECX, R_EAX, FRn );
3143 { /* FCNVSD FPUL, FRn */
3144 uint32_t FRn = ((ir>>8)&0xF);
3146 load_spreg( R_ECX, R_FPSCR );
3147 TEST_imm32_r32( FPSCR_PR, R_ECX );
3148 JE_rel8(9, end); // only when PR=1
3149 load_fr_bank( R_ECX );
3151 pop_dr( R_ECX, FRn );
3156 { /* FCNVDS FRm, FPUL */
3157 uint32_t FRm = ((ir>>8)&0xF);
3159 load_spreg( R_ECX, R_FPSCR );
3160 TEST_imm32_r32( FPSCR_PR, R_ECX );
3161 JE_rel8(9, end); // only when PR=1
3162 load_fr_bank( R_ECX );
3163 push_dr( R_ECX, FRm );
3169 { /* FIPR FVm, FVn */
3170 uint32_t FVn = ((ir>>10)&0x3); uint32_t FVm = ((ir>>8)&0x3);
3172 load_spreg( R_ECX, R_FPSCR );
3173 TEST_imm32_r32( FPSCR_PR, R_ECX );
3174 JNE_rel8(44, doubleprec);
3176 load_fr_bank( R_ECX );
3177 push_fr( R_ECX, FVm<<2 );
3178 push_fr( R_ECX, FVn<<2 );
3180 push_fr( R_ECX, (FVm<<2)+1);
3181 push_fr( R_ECX, (FVn<<2)+1);
3184 push_fr( R_ECX, (FVm<<2)+2);
3185 push_fr( R_ECX, (FVn<<2)+2);
3188 push_fr( R_ECX, (FVm<<2)+3);
3189 push_fr( R_ECX, (FVn<<2)+3);
3192 pop_fr( R_ECX, (FVn<<2)+3);
3193 JMP_TARGET(doubleprec);
3197 switch( (ir&0x100) >> 8 ) {
3199 { /* FSCA FPUL, FRn */
3200 uint32_t FRn = ((ir>>9)&0x7)<<1;
3202 load_spreg( R_ECX, R_FPSCR );
3203 TEST_imm32_r32( FPSCR_PR, R_ECX );
3204 JNE_rel8( 21, doubleprec );
3205 load_fr_bank( R_ECX );
3206 ADD_imm8s_r32( (FRn&0x0E)<<2, R_ECX );
3207 load_spreg( R_EDX, R_FPUL );
3208 call_func2( sh4_fsca, R_EDX, R_ECX );
3209 JMP_TARGET(doubleprec);
3213 switch( (ir&0x200) >> 9 ) {
3215 { /* FTRV XMTRX, FVn */
3216 uint32_t FVn = ((ir>>10)&0x3);
3218 load_spreg( R_ECX, R_FPSCR );
3219 TEST_imm32_r32( FPSCR_PR, R_ECX );
3220 JNE_rel8( 30, doubleprec );
3221 load_fr_bank( R_EDX ); // 3
3222 ADD_imm8s_r32( FVn<<4, R_EDX ); // 3
3223 load_xf_bank( R_ECX ); // 12
3224 call_func2( sh4_ftrv, R_EDX, R_ECX ); // 12
3225 JMP_TARGET(doubleprec);
3229 switch( (ir&0xC00) >> 10 ) {
3233 load_spreg( R_ECX, R_FPSCR );
3234 XOR_imm32_r32( FPSCR_SZ, R_ECX );
3235 store_spreg( R_ECX, R_FPSCR );
3241 load_spreg( R_ECX, R_FPSCR );
3242 XOR_imm32_r32( FPSCR_FR, R_ECX );
3243 store_spreg( R_ECX, R_FPSCR );
3244 update_fr_bank( R_ECX );
3249 if( sh4_x86.in_delay_slot ) {
3252 JMP_exit(EXIT_ILLEGAL);
3272 { /* FMAC FR0, FRm, FRn */
3273 uint32_t FRn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
3275 load_spreg( R_ECX, R_FPSCR );
3276 load_spreg( R_EDX, REG_OFFSET(fr_bank));
3277 TEST_imm32_r32( FPSCR_PR, R_ECX );
3278 JNE_rel8(18, doubleprec);
3279 push_fr( R_EDX, 0 );
3280 push_fr( R_EDX, FRm );
3282 push_fr( R_EDX, FRn );
3284 pop_fr( R_EDX, FRn );
3286 JMP_TARGET(doubleprec);
3287 push_dr( R_EDX, 0 );
3288 push_dr( R_EDX, FRm );
3290 push_dr( R_EDX, FRn );
3292 pop_dr( R_EDX, FRn );
3303 if( sh4_x86.in_delay_slot ) {
3304 ADD_imm8s_r32(2,R_ESI);
3305 sh4_x86.in_delay_slot = FALSE;
.