--- a/src/sh4/sh4x86.in Sun Jan 06 12:24:18 2008 +0000 +++ b/src/sh4/sh4x86.in Thu Jan 10 08:28:37 2008 +0000 @@ -40,6 +40,8 @@ uint32_t exc_code; }; +#define MAX_RECOVERY_SIZE 2048 + /** * Struct to manage internal translation state. This state is not saved - * it is only valid between calls to sh4_translate_begin_block() and @@ -61,6 +63,8 @@ struct backpatch_record *backpatch_list; uint32_t backpatch_posn; uint32_t backpatch_size; + struct xlat_recovery_record recovery_list[MAX_RECOVERY_SIZE]; + uint32_t recovery_posn; }; #define TSTATE_NONE -1 @@ -115,6 +119,13 @@ sh4_x86.backpatch_posn++; } +void sh4_x86_add_recovery( uint32_t pc ) +{ + xlat_recovery[xlat_recovery_posn].xlat_pc = (uintptr_t)xlat_output; + xlat_recovery[xlat_recovery_posn].sh4_icount = (pc - sh4_x86.block_start_pc)>>1; + xlat_recovery_posn++; +} + /** * Emit an instruction to load an SH4 reg into a real register */ @@ -309,34 +320,27 @@ #define UNDEF() #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); } -#define MEM_READ_BYTE_PHYS( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg) -#define MEM_READ_WORD_PHYS( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg) -#define MEM_READ_LONG_PHYS( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg) -#define MEM_WRITE_BYTE_PHYS( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg) -#define MEM_WRITE_WORD_PHYS( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg) -#define MEM_WRITE_LONG_PHYS( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg) +#define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg) +#define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg) +#define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg) +#define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg) +#define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg) +#define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg) -#define MEM_READ_BYTE_VMA( addr_reg, value_reg ) call_func1(mmu_vma_to_phys_read, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); call_func1(sh4_read_byte, R_EAX); MEM_RESULT(value_reg) -#define MEM_READ_WORD_VMA( addr_reg, value_reg ) call_func1(mmu_vma_to_phys_read, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); call_func1(sh4_read_word, R_EAX); MEM_RESULT(value_reg) -#define MEM_READ_LONG_VMA( addr_reg, value_reg ) call_func1(mmu_vma_to_phys_read, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); call_func1(sh4_read_long, R_EAX); MEM_RESULT(value_reg) -#define MEM_WRITE_BYTE_VMA( addr_reg, value_reg ) call_func1(mmu_vma_to_phys_write, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); call_func2(sh4_write_byte, R_EAX, value_reg) -#define MEM_WRITE_WORD_VMA( addr_reg, value_reg ) call_func1(mmu_vma_to_phys_write, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); call_func2(sh4_write_word, R_EAX, value_reg) -#define MEM_WRITE_LONG_VMA( addr_reg, value_reg ) call_func1(mmu_vma_to_phys_write, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); call_func2(sh4_write_long, R_EAX, value_reg) +/** + * Perform MMU translation on the address in addr_reg for a read operation, iff the TLB is turned + * on, otherwise do nothing. Clobbers EAX, ECX and EDX. May raise a TLB exception or address error. + */ +#define MMU_TRANSLATE_READ( addr_reg ) if( sh4_x86.tlb_on ) { call_func1(mmu_vma_to_phys_read, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); MEM_RESULT(addr_reg); } +/** + * Perform MMU translation on the address in addr_reg for a write operation, iff the TLB is turned + * on, otherwise do nothing. Clobbers EAX, ECX and EDX. May raise a TLB exception or address error. + */ +#define MMU_TRANSLATE_WRITE( addr_reg ) if( sh4_x86.tlb_on ) { call_func1(mmu_vma_to_phys_write, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); MEM_RESULT(addr_reg); } -#define MEM_READ_BYTE( addr_reg, value_reg ) if(sh4_x86.tlb_on){MEM_READ_BYTE_VMA(addr_reg,value_reg);}else{MEM_READ_BYTE_PHYS(addr_reg, value_reg);} -#define MEM_READ_WORD( addr_reg, value_reg ) if(sh4_x86.tlb_on){MEM_READ_WORD_VMA(addr_reg,value_reg);}else{MEM_READ_WORD_PHYS(addr_reg, value_reg);} -#define MEM_READ_LONG( addr_reg, value_reg ) if(sh4_x86.tlb_on){MEM_READ_LONG_VMA(addr_reg,value_reg);}else{MEM_READ_LONG_PHYS(addr_reg, value_reg);} -#define MEM_WRITE_BYTE( addr_reg, value_reg ) if(sh4_x86.tlb_on){MEM_WRITE_BYTE_VMA(addr_reg,value_reg);}else{MEM_WRITE_BYTE_PHYS(addr_reg, value_reg);} -#define MEM_WRITE_WORD( addr_reg, value_reg ) if(sh4_x86.tlb_on){MEM_WRITE_WORD_VMA(addr_reg,value_reg);}else{MEM_WRITE_WORD_PHYS(addr_reg, value_reg);} -#define MEM_WRITE_LONG( addr_reg, value_reg ) if(sh4_x86.tlb_on){MEM_WRITE_LONG_VMA(addr_reg,value_reg);}else{MEM_WRITE_LONG_PHYS(addr_reg, value_reg);} - -#define MEM_READ_SIZE_PHYS (CALL_FUNC1_SIZE) -#define MEM_WRITE_SIZE_PHYS (CALL_FUNC2_SIZE) -#define MEM_READ_SIZE_VMA (CALL_FUNC1_SIZE + CALL_FUNC1_SIZE + 12) -#define MEM_WRITE_SIZE_VMA (CALL_FUNC1_SIZE + CALL_FUNC2_SIZE + 12) - -#define MEM_READ_SIZE (sh4_x86.tlb_on?MEM_READ_SIZE_VMA:MEM_READ_SIZE_PHYS) -#define MEM_WRITE_SIZE (sh4_x86.tlb_on?MEM_WRITE_SIZE_VMA:MEM_WRITE_SIZE_PHYS) +#define MEM_READ_SIZE (CALL_FUNC1_SIZE) +#define MEM_WRITE_SIZE (CALL_FUNC2_SIZE) +#define MMU_TRANSLATE_SIZE (sh4_x86.tlb_on ? (CALL_FUNC1_SIZE + 12) : 0 ) #define SLOTILLEGAL() JMP_exc(EXC_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1; @@ -369,6 +373,9 @@ } else { ir = sh4_read_word(pc); } + if( !sh4_x86.in_delay_slot ) { + sh4_x86_add_recovery(pc); + } %% /* ALU operations */ ADD Rm, Rn {: @@ -419,9 +426,10 @@ AND.B #imm, @(R0, GBR) {: load_reg( R_EAX, 0 ); load_spreg( R_ECX, R_GBR ); - ADD_r32_r32( R_EAX, R_ECX ); - PUSH_realigned_r32(R_ECX); - MEM_READ_BYTE( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + PUSH_realigned_r32(R_EAX); + MEM_READ_BYTE( R_EAX, R_EAX ); POP_realigned_r32(R_ECX); AND_imm32_r32(imm, R_EAX ); MEM_WRITE_BYTE( R_ECX, R_EAX ); @@ -584,18 +592,35 @@ MOVZX_r16_r32( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); :} -MAC.L @Rm+, @Rn+ {: - load_reg( R_ECX, Rm ); - check_ralign32( R_ECX ); - load_reg( R_ECX, Rn ); - check_ralign32( R_ECX ); - ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) ); - MEM_READ_LONG( R_ECX, R_EAX ); - PUSH_realigned_r32( R_EAX ); - load_reg( R_ECX, Rm ); - ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); +MAC.L @Rm+, @Rn+ {: + if( Rm == Rn ) { + load_reg( R_EAX, Rm ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + PUSH_realigned_r32( R_EAX ); + load_reg( R_EAX, Rn ); + ADD_imm8s_r32( 4, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 8, REG_OFFSET(r[Rn]) ); + // Note translate twice in case of page boundaries. Maybe worth + // adding a page-boundary check to skip the second translation + } else { + load_reg( R_EAX, Rm ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + PUSH_realigned_r32( R_EAX ); + load_reg( R_EAX, Rn ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + } + MEM_READ_LONG( R_EAX, R_EAX ); + POP_r32( R_ECX ); + PUSH_r32( R_EAX ); MEM_READ_LONG( R_ECX, R_EAX ); POP_realigned_r32( R_ECX ); + IMUL_r32( R_ECX ); ADD_r32_sh4r( R_EAX, R_MACL ); ADC_r32_sh4r( R_EDX, R_MACH ); @@ -608,15 +633,31 @@ sh4_x86.tstate = TSTATE_NONE; :} MAC.W @Rm+, @Rn+ {: - load_reg( R_ECX, Rm ); - check_ralign16( R_ECX ); - load_reg( R_ECX, Rn ); - check_ralign16( R_ECX ); - ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rn]) ); - MEM_READ_WORD( R_ECX, R_EAX ); - PUSH_realigned_r32( R_EAX ); - load_reg( R_ECX, Rm ); - ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) ); + if( Rm == Rn ) { + load_reg( R_EAX, Rm ); + check_ralign16( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + PUSH_realigned_r32( R_EAX ); + load_reg( R_EAX, Rn ); + ADD_imm8s_r32( 2, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) ); + // Note translate twice in case of page boundaries. Maybe worth + // adding a page-boundary check to skip the second translation + } else { + load_reg( R_EAX, Rm ); + check_ralign16( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + PUSH_realigned_r32( R_EAX ); + load_reg( R_EAX, Rn ); + check_ralign16( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rn]) ); + ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) ); + } + MEM_READ_WORD( R_EAX, R_EAX ); + POP_r32( R_ECX ); + PUSH_r32( R_EAX ); MEM_READ_WORD( R_ECX, R_EAX ); POP_realigned_r32( R_ECX ); IMUL_r32( R_ECX ); @@ -709,9 +750,10 @@ OR.B #imm, @(R0, GBR) {: load_reg( R_EAX, 0 ); load_spreg( R_ECX, R_GBR ); - ADD_r32_r32( R_EAX, R_ECX ); - PUSH_realigned_r32(R_ECX); - MEM_READ_BYTE( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + PUSH_realigned_r32(R_EAX); + MEM_READ_BYTE( R_EAX, R_EAX ); POP_realigned_r32(R_ECX); OR_imm32_r32(imm, R_EAX ); MEM_WRITE_BYTE( R_ECX, R_EAX ); @@ -905,12 +947,14 @@ sh4_x86.tstate = TSTATE_NONE; :} TAS.B @Rn {: - load_reg( R_ECX, Rn ); - MEM_READ_BYTE( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + MMU_TRANSLATE_WRITE( R_EAX ); + PUSH_realigned_r32( R_EAX ); + MEM_READ_BYTE( R_EAX, R_EAX ); TEST_r8_r8( R_AL, R_AL ); SETE_t(); OR_imm8_r8( 0x80, R_AL ); - load_reg( R_ECX, Rn ); + POP_realigned_r32( R_ECX ); MEM_WRITE_BYTE( R_ECX, R_EAX ); sh4_x86.tstate = TSTATE_NONE; :} @@ -930,8 +974,9 @@ TST.B #imm, @(R0, GBR) {: load_reg( R_EAX, 0); load_reg( R_ECX, R_GBR); - ADD_r32_r32( R_EAX, R_ECX ); - MEM_READ_BYTE( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_BYTE( R_EAX, R_EAX ); TEST_imm8_r8( imm, R_AL ); SETE_t(); sh4_x86.tstate = TSTATE_E; @@ -952,9 +997,10 @@ XOR.B #imm, @(R0, GBR) {: load_reg( R_EAX, 0 ); load_spreg( R_ECX, R_GBR ); - ADD_r32_r32( R_EAX, R_ECX ); - PUSH_realigned_r32(R_ECX); - MEM_READ_BYTE(R_ECX, R_EAX); + ADD_r32_r32( R_ECX, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + PUSH_realigned_r32(R_EAX); + MEM_READ_BYTE(R_EAX, R_EAX); POP_realigned_r32(R_ECX); XOR_imm32_r32( imm, R_EAX ); MEM_WRITE_BYTE( R_ECX, R_EAX ); @@ -980,150 +1026,165 @@ store_reg( R_EAX, Rn ); :} MOV.B Rm, @Rn {: - load_reg( R_EAX, Rm ); - load_reg( R_ECX, Rn ); - MEM_WRITE_BYTE( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + MEM_WRITE_BYTE( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B Rm, @-Rn {: - load_reg( R_EAX, Rm ); - load_reg( R_ECX, Rn ); - ADD_imm8s_r32( -1, R_ECX ); - store_reg( R_ECX, Rn ); - MEM_WRITE_BYTE( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + ADD_imm8s_r32( -1, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + ADD_imm8s_sh4r( -1, REG_OFFSET(r[Rn]) ); + MEM_WRITE_BYTE( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B Rm, @(R0, Rn) {: load_reg( R_EAX, 0 ); load_reg( R_ECX, Rn ); - ADD_r32_r32( R_EAX, R_ECX ); - load_reg( R_EAX, Rm ); - MEM_WRITE_BYTE( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + MEM_WRITE_BYTE( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B R0, @(disp, GBR) {: - load_reg( R_EAX, 0 ); - load_spreg( R_ECX, R_GBR ); - ADD_imm32_r32( disp, R_ECX ); - MEM_WRITE_BYTE( R_ECX, R_EAX ); + load_spreg( R_EAX, R_GBR ); + ADD_imm32_r32( disp, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, 0 ); + MEM_WRITE_BYTE( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B R0, @(disp, Rn) {: - load_reg( R_EAX, 0 ); - load_reg( R_ECX, Rn ); - ADD_imm32_r32( disp, R_ECX ); - MEM_WRITE_BYTE( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + ADD_imm32_r32( disp, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, 0 ); + MEM_WRITE_BYTE( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B @Rm, Rn {: - load_reg( R_ECX, Rm ); - MEM_READ_BYTE( R_ECX, R_EAX ); + load_reg( R_EAX, Rm ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_BYTE( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B @Rm+, Rn {: - load_reg( R_ECX, Rm ); - MOV_r32_r32( R_ECX, R_EAX ); - ADD_imm8s_r32( 1, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_BYTE( R_ECX, R_EAX ); + load_reg( R_EAX, Rm ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 1, REG_OFFSET(r[Rm]) ); + MEM_READ_BYTE( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B @(R0, Rm), Rn {: load_reg( R_EAX, 0 ); load_reg( R_ECX, Rm ); - ADD_r32_r32( R_EAX, R_ECX ); - MEM_READ_BYTE( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ) + MEM_READ_BYTE( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B @(disp, GBR), R0 {: - load_spreg( R_ECX, R_GBR ); - ADD_imm32_r32( disp, R_ECX ); - MEM_READ_BYTE( R_ECX, R_EAX ); + load_spreg( R_EAX, R_GBR ); + ADD_imm32_r32( disp, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_BYTE( R_EAX, R_EAX ); store_reg( R_EAX, 0 ); sh4_x86.tstate = TSTATE_NONE; :} MOV.B @(disp, Rm), R0 {: - load_reg( R_ECX, Rm ); - ADD_imm32_r32( disp, R_ECX ); - MEM_READ_BYTE( R_ECX, R_EAX ); + load_reg( R_EAX, Rm ); + ADD_imm32_r32( disp, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_BYTE( R_EAX, R_EAX ); store_reg( R_EAX, 0 ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L Rm, @Rn {: - load_reg( R_EAX, Rm ); - load_reg( R_ECX, Rn ); - check_walign32(R_ECX); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32(R_EAX); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L Rm, @-Rn {: - load_reg( R_EAX, Rm ); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + ADD_imm8s_r32( -4, R_EAX ); + check_walign32( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L Rm, @(R0, Rn) {: load_reg( R_EAX, 0 ); load_reg( R_ECX, Rn ); - ADD_r32_r32( R_EAX, R_ECX ); - check_walign32( R_ECX ); - load_reg( R_EAX, Rm ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + check_walign32( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L R0, @(disp, GBR) {: - load_spreg( R_ECX, R_GBR ); - load_reg( R_EAX, 0 ); - ADD_imm32_r32( disp, R_ECX ); - check_walign32( R_ECX ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_spreg( R_EAX, R_GBR ); + ADD_imm32_r32( disp, R_EAX ); + check_walign32( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, 0 ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L Rm, @(disp, Rn) {: - load_reg( R_ECX, Rn ); - load_reg( R_EAX, Rm ); - ADD_imm32_r32( disp, R_ECX ); - check_walign32( R_ECX ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + ADD_imm32_r32( disp, R_EAX ); + check_walign32( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L @Rm, Rn {: - load_reg( R_ECX, Rm ); - check_ralign32( R_ECX ); - MEM_READ_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rm ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_LONG( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L @Rm+, Rn {: load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L @(R0, Rm), Rn {: load_reg( R_EAX, 0 ); load_reg( R_ECX, Rm ); - ADD_r32_r32( R_EAX, R_ECX ); - check_ralign32( R_ECX ); - MEM_READ_LONG( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_LONG( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.L @(disp, GBR), R0 {: - load_spreg( R_ECX, R_GBR ); - ADD_imm32_r32( disp, R_ECX ); - check_ralign32( R_ECX ); - MEM_READ_LONG( R_ECX, R_EAX ); + load_spreg( R_EAX, R_GBR ); + ADD_imm32_r32( disp, R_EAX ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_LONG( R_EAX, R_EAX ); store_reg( R_EAX, 0 ); sh4_x86.tstate = TSTATE_NONE; :} @@ -1148,94 +1209,103 @@ // Note: we use sh4r.pc for the calc as we could be running at a // different virtual address than the translation was done with, // but we can safely assume that the low bits are the same. - load_imm32( R_ECX, (pc-sh4_x86.block_start_pc) + disp + 4 - (pc&0x03) ); - ADD_sh4r_r32( R_PC, R_ECX ); - MEM_READ_LONG( R_ECX, R_EAX ); + load_imm32( R_EAX, (pc-sh4_x86.block_start_pc) + disp + 4 - (pc&0x03) ); + ADD_sh4r_r32( R_PC, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_LONG( R_EAX, R_EAX ); sh4_x86.tstate = TSTATE_NONE; } store_reg( R_EAX, Rn ); } :} MOV.L @(disp, Rm), Rn {: - load_reg( R_ECX, Rm ); - ADD_imm8s_r32( disp, R_ECX ); - check_ralign32( R_ECX ); - MEM_READ_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rm ); + ADD_imm8s_r32( disp, R_EAX ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_LONG( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W Rm, @Rn {: - load_reg( R_ECX, Rn ); - check_walign16( R_ECX ); - load_reg( R_EAX, Rm ); - MEM_WRITE_WORD( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign16( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ) + load_reg( R_EDX, Rm ); + MEM_WRITE_WORD( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W Rm, @-Rn {: - load_reg( R_ECX, Rn ); - check_walign16( R_ECX ); - load_reg( R_EAX, Rm ); - ADD_imm8s_r32( -2, R_ECX ); - store_reg( R_ECX, Rn ); - MEM_WRITE_WORD( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + ADD_imm8s_r32( -2, R_EAX ); + check_walign16( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + ADD_imm8s_sh4r( -2, REG_OFFSET(r[Rn]) ); + MEM_WRITE_WORD( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W Rm, @(R0, Rn) {: load_reg( R_EAX, 0 ); load_reg( R_ECX, Rn ); - ADD_r32_r32( R_EAX, R_ECX ); - check_walign16( R_ECX ); - load_reg( R_EAX, Rm ); - MEM_WRITE_WORD( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + check_walign16( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, Rm ); + MEM_WRITE_WORD( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W R0, @(disp, GBR) {: - load_spreg( R_ECX, R_GBR ); - load_reg( R_EAX, 0 ); - ADD_imm32_r32( disp, R_ECX ); - check_walign16( R_ECX ); - MEM_WRITE_WORD( R_ECX, R_EAX ); + load_spreg( R_EAX, R_GBR ); + ADD_imm32_r32( disp, R_EAX ); + check_walign16( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, 0 ); + MEM_WRITE_WORD( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W R0, @(disp, Rn) {: - load_reg( R_ECX, Rn ); - load_reg( R_EAX, 0 ); - ADD_imm32_r32( disp, R_ECX ); - check_walign16( R_ECX ); - MEM_WRITE_WORD( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + ADD_imm32_r32( disp, R_EAX ); + check_walign16( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, 0 ); + MEM_WRITE_WORD( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W @Rm, Rn {: - load_reg( R_ECX, Rm ); - check_ralign16( R_ECX ); - MEM_READ_WORD( R_ECX, R_EAX ); + load_reg( R_EAX, Rm ); + check_ralign16( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_WORD( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W @Rm+, Rn {: load_reg( R_EAX, Rm ); check_ralign16( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 2, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_WORD( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) ); + MEM_READ_WORD( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W @(R0, Rm), Rn {: load_reg( R_EAX, 0 ); load_reg( R_ECX, Rm ); - ADD_r32_r32( R_EAX, R_ECX ); - check_ralign16( R_ECX ); - MEM_READ_WORD( R_ECX, R_EAX ); + ADD_r32_r32( R_ECX, R_EAX ); + check_ralign16( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_WORD( R_EAX, R_EAX ); store_reg( R_EAX, Rn ); sh4_x86.tstate = TSTATE_NONE; :} MOV.W @(disp, GBR), R0 {: - load_spreg( R_ECX, R_GBR ); - ADD_imm32_r32( disp, R_ECX ); - check_ralign16( R_ECX ); - MEM_READ_WORD( R_ECX, R_EAX ); + load_spreg( R_EAX, R_GBR ); + ADD_imm32_r32( disp, R_EAX ); + check_ralign16( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_WORD( R_EAX, R_EAX ); store_reg( R_EAX, 0 ); sh4_x86.tstate = TSTATE_NONE; :} @@ -1250,19 +1320,21 @@ MOV_moff32_EAX( ptr ); MOVSX_r16_r32( R_EAX, R_EAX ); } else { - load_imm32( R_ECX, (pc - sh4_x86.block_start_pc) + disp + 4 ); - ADD_sh4r_r32( R_PC, R_ECX ); - MEM_READ_WORD( R_ECX, R_EAX ); + load_imm32( R_EAX, (pc - sh4_x86.block_start_pc) + disp + 4 ); + ADD_sh4r_r32( R_PC, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_WORD( R_EAX, R_EAX ); sh4_x86.tstate = TSTATE_NONE; } store_reg( R_EAX, Rn ); } :} MOV.W @(disp, Rm), R0 {: - load_reg( R_ECX, Rm ); - ADD_imm32_r32( disp, R_ECX ); - check_ralign16( R_ECX ); - MEM_READ_WORD( R_ECX, R_EAX ); + load_reg( R_EAX, Rm ); + ADD_imm32_r32( disp, R_EAX ); + check_ralign16( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + MEM_READ_WORD( R_EAX, R_EAX ); store_reg( R_EAX, 0 ); sh4_x86.tstate = TSTATE_NONE; :} @@ -1273,13 +1345,15 @@ load_imm32( R_ECX, (pc - sh4_x86.block_start_pc) + disp + 4 - (pc&0x03) ); ADD_sh4r_r32( R_PC, R_ECX ); store_reg( R_ECX, 0 ); + sh4_x86.tstate = TSTATE_NONE; } :} MOVCA.L R0, @Rn {: - load_reg( R_EAX, 0 ); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_reg( R_EDX, 0 ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} @@ -1288,8 +1362,9 @@ if( sh4_x86.in_delay_slot ) { SLOTILLEGAL(); } else { - JT_rel8( EXIT_BLOCK_SIZE, nottaken ); - exit_block( disp + pc + 4, pc+2 ); + sh4vma_t target = disp + pc + 4; + JT_rel8( EXIT_BLOCK_REL_SIZE(target), nottaken ); + exit_block_rel(target, pc+2 ); JMP_TARGET(nottaken); return 2; } @@ -1298,6 +1373,7 @@ if( sh4_x86.in_delay_slot ) { SLOTILLEGAL(); } else { + sh4vma_t target = disp + pc + 4; sh4_x86.in_delay_slot = TRUE; if( sh4_x86.tstate == TSTATE_NONE ) { CMP_imm8s_sh4r( 1, R_T ); @@ -1305,7 +1381,7 @@ } OP(0x0F); OP(0x80+sh4_x86.tstate); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel32 sh4_translate_instruction(pc+2); - exit_block( disp + pc + 4, pc+4 ); + exit_block_rel( target, pc+4 ); // not taken *patch = (xlat_output - ((uint8_t *)patch)) - 4; sh4_translate_instruction(pc+2); @@ -1318,7 +1394,7 @@ } else { sh4_x86.in_delay_slot = TRUE; sh4_translate_instruction( pc + 2 ); - exit_block( disp + pc + 4, pc+4 ); + exit_block_rel( disp + pc + 4, pc+4 ); sh4_x86.branch_taken = TRUE; return 4; } @@ -1346,7 +1422,7 @@ store_spreg( R_EAX, R_PR ); sh4_x86.in_delay_slot = TRUE; sh4_translate_instruction( pc + 2 ); - exit_block( disp + pc + 4, pc+4 ); + exit_block_rel( disp + pc + 4, pc+4 ); sh4_x86.branch_taken = TRUE; return 4; } @@ -1371,8 +1447,9 @@ if( sh4_x86.in_delay_slot ) { SLOTILLEGAL(); } else { - JF_rel8( EXIT_BLOCK_SIZE, nottaken ); - exit_block( disp + pc + 4, pc+2 ); + sh4vma_t target = disp + pc + 4; + JF_rel8( EXIT_BLOCK_REL_SIZE(target), nottaken ); + exit_block_rel(target, pc+2 ); JMP_TARGET(nottaken); return 2; } @@ -1388,7 +1465,7 @@ } OP(0x0F); OP(0x80+(sh4_x86.tstate^1)); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel32 sh4_translate_instruction(pc+2); - exit_block( disp + pc + 4, pc+4 ); + exit_block_rel( disp + pc + 4, pc+4 ); // not taken *patch = (xlat_output - ((uint8_t *)patch)) - 4; sh4_translate_instruction(pc+2); @@ -1558,191 +1635,195 @@ :} FMOV FRm, @Rn {: check_fpuen(); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); load_spreg( R_EDX, R_FPSCR ); TEST_imm32_r32( FPSCR_SZ, R_EDX ); JNE_rel8(8 + MEM_WRITE_SIZE, doublesize); load_fr_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm ); - MEM_WRITE_LONG( R_ECX, R_EAX ); // 12 + load_fr( R_EDX, R_ECX, FRm ); + MEM_WRITE_LONG( R_EAX, R_ECX ); // 12 if( FRm&1 ) { JMP_rel8( 18 + MEM_WRITE_DOUBLE_SIZE, end ); JMP_TARGET(doublesize); load_xf_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm&0x0E ); + load_fr( R_EDX, R_ECX, FRm&0x0E ); load_fr( R_EDX, R_EDX, FRm|0x01 ); - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX ); + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX ); JMP_TARGET(end); } else { JMP_rel8( 9 + MEM_WRITE_DOUBLE_SIZE, end ); JMP_TARGET(doublesize); load_fr_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm&0x0E ); + load_fr( R_EDX, R_ECX, FRm&0x0E ); load_fr( R_EDX, R_EDX, FRm|0x01 ); - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX ); + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX ); JMP_TARGET(end); } sh4_x86.tstate = TSTATE_NONE; :} FMOV @Rm, FRn {: check_fpuen(); - load_reg( R_ECX, Rm ); - check_ralign32( R_ECX ); + load_reg( R_EAX, Rm ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); load_spreg( R_EDX, R_FPSCR ); TEST_imm32_r32( FPSCR_SZ, R_EDX ); JNE_rel8(8 + MEM_READ_SIZE, doublesize); - MEM_READ_LONG( R_ECX, R_EAX ); + MEM_READ_LONG( R_EAX, R_EAX ); load_fr_bank( R_EDX ); store_fr( R_EDX, R_EAX, FRn ); if( FRn&1 ) { JMP_rel8(21 + MEM_READ_DOUBLE_SIZE, end); JMP_TARGET(doublesize); - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX ); + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX ); load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it load_xf_bank( R_EDX ); - store_fr( R_EDX, R_EAX, FRn&0x0E ); - store_fr( R_EDX, R_ECX, FRn|0x01 ); + store_fr( R_EDX, R_ECX, FRn&0x0E ); + store_fr( R_EDX, R_EAX, FRn|0x01 ); JMP_TARGET(end); } else { JMP_rel8(9 + MEM_READ_DOUBLE_SIZE, end); JMP_TARGET(doublesize); - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX ); + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX ); load_fr_bank( R_EDX ); - store_fr( R_EDX, R_EAX, FRn&0x0E ); - store_fr( R_EDX, R_ECX, FRn|0x01 ); + store_fr( R_EDX, R_ECX, FRn&0x0E ); + store_fr( R_EDX, R_EAX, FRn|0x01 ); JMP_TARGET(end); } sh4_x86.tstate = TSTATE_NONE; :} FMOV FRm, @-Rn {: check_fpuen(); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); load_spreg( R_EDX, R_FPSCR ); TEST_imm32_r32( FPSCR_SZ, R_EDX ); - JNE_rel8(14 + MEM_WRITE_SIZE, doublesize); + JNE_rel8(15 + MEM_WRITE_SIZE + MMU_TRANSLATE_SIZE, doublesize); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); load_fr_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm ); - ADD_imm8s_r32(-4,R_ECX); - store_reg( R_ECX, Rn ); - MEM_WRITE_LONG( R_ECX, R_EAX ); // 12 + load_fr( R_EDX, R_ECX, FRm ); + ADD_imm8s_sh4r(-4,REG_OFFSET(r[Rn])); + MEM_WRITE_LONG( R_EAX, R_ECX ); // 12 if( FRm&1 ) { - JMP_rel8( 24 + MEM_WRITE_DOUBLE_SIZE, end ); + JMP_rel8( 25 + MEM_WRITE_DOUBLE_SIZE + MMU_TRANSLATE_SIZE, end ); JMP_TARGET(doublesize); + ADD_imm8s_r32(-8,R_EAX); + MMU_TRANSLATE_WRITE( R_EAX ); load_xf_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm&0x0E ); + load_fr( R_EDX, R_ECX, FRm&0x0E ); load_fr( R_EDX, R_EDX, FRm|0x01 ); - ADD_imm8s_r32(-8,R_ECX); - store_reg( R_ECX, Rn ); - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX ); + ADD_imm8s_sh4r(-8,REG_OFFSET(r[Rn])); + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX ); JMP_TARGET(end); } else { - JMP_rel8( 15 + MEM_WRITE_DOUBLE_SIZE, end ); + JMP_rel8( 16 + MEM_WRITE_DOUBLE_SIZE + MMU_TRANSLATE_SIZE, end ); JMP_TARGET(doublesize); + ADD_imm8s_r32(-8,R_EAX); + MMU_TRANSLATE_WRITE( R_EAX ); load_fr_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm&0x0E ); + load_fr( R_EDX, R_ECX, FRm&0x0E ); load_fr( R_EDX, R_EDX, FRm|0x01 ); - ADD_imm8s_r32(-8,R_ECX); - store_reg( R_ECX, Rn ); - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX ); + ADD_imm8s_sh4r(-8,REG_OFFSET(r[Rn])); + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX ); JMP_TARGET(end); } sh4_x86.tstate = TSTATE_NONE; :} FMOV @Rm+, FRn {: check_fpuen(); - load_reg( R_ECX, Rm ); - check_ralign32( R_ECX ); - MOV_r32_r32( R_ECX, R_EAX ); + load_reg( R_EAX, Rm ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); load_spreg( R_EDX, R_FPSCR ); TEST_imm32_r32( FPSCR_SZ, R_EDX ); - JNE_rel8(14 + MEM_READ_SIZE, doublesize); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + JNE_rel8(12 + MEM_READ_SIZE, doublesize); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); load_fr_bank( R_EDX ); store_fr( R_EDX, R_EAX, FRn ); if( FRn&1 ) { - JMP_rel8(27 + MEM_READ_DOUBLE_SIZE, end); + JMP_rel8(25 + MEM_READ_DOUBLE_SIZE, end); JMP_TARGET(doublesize); - ADD_imm8s_r32( 8, R_EAX ); - store_reg(R_EAX, Rm); - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX ); + ADD_imm8s_sh4r( 8, REG_OFFSET(r[Rm]) ); + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX ); load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it load_xf_bank( R_EDX ); - store_fr( R_EDX, R_EAX, FRn&0x0E ); - store_fr( R_EDX, R_ECX, FRn|0x01 ); + store_fr( R_EDX, R_ECX, FRn&0x0E ); + store_fr( R_EDX, R_EAX, FRn|0x01 ); JMP_TARGET(end); } else { - JMP_rel8(15 + MEM_READ_DOUBLE_SIZE, end); - ADD_imm8s_r32( 8, R_EAX ); - store_reg(R_EAX, Rm); - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX ); + JMP_rel8(13 + MEM_READ_DOUBLE_SIZE, end); + ADD_imm8s_sh4r( 8, REG_OFFSET(r[Rm]) ); + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX ); load_fr_bank( R_EDX ); - store_fr( R_EDX, R_EAX, FRn&0x0E ); - store_fr( R_EDX, R_ECX, FRn|0x01 ); + store_fr( R_EDX, R_ECX, FRn&0x0E ); + store_fr( R_EDX, R_EAX, FRn|0x01 ); JMP_TARGET(end); } sh4_x86.tstate = TSTATE_NONE; :} FMOV FRm, @(R0, Rn) {: check_fpuen(); - load_reg( R_ECX, Rn ); - ADD_sh4r_r32( REG_OFFSET(r[0]), R_ECX ); - check_walign32( R_ECX ); + load_reg( R_EAX, Rn ); + ADD_sh4r_r32( REG_OFFSET(r[0]), R_EAX ); + check_walign32( R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); load_spreg( R_EDX, R_FPSCR ); TEST_imm32_r32( FPSCR_SZ, R_EDX ); JNE_rel8(8 + MEM_WRITE_SIZE, doublesize); load_fr_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm ); - MEM_WRITE_LONG( R_ECX, R_EAX ); // 12 + load_fr( R_EDX, R_ECX, FRm ); + MEM_WRITE_LONG( R_EAX, R_ECX ); // 12 if( FRm&1 ) { JMP_rel8( 18 + MEM_WRITE_DOUBLE_SIZE, end ); JMP_TARGET(doublesize); load_xf_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm&0x0E ); + load_fr( R_EDX, R_ECX, FRm&0x0E ); load_fr( R_EDX, R_EDX, FRm|0x01 ); - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX ); + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX ); JMP_TARGET(end); } else { JMP_rel8( 9 + MEM_WRITE_DOUBLE_SIZE, end ); JMP_TARGET(doublesize); load_fr_bank( R_EDX ); - load_fr( R_EDX, R_EAX, FRm&0x0E ); + load_fr( R_EDX, R_ECX, FRm&0x0E ); load_fr( R_EDX, R_EDX, FRm|0x01 ); - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX ); + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX ); JMP_TARGET(end); } sh4_x86.tstate = TSTATE_NONE; :} FMOV @(R0, Rm), FRn {: check_fpuen(); - load_reg( R_ECX, Rm ); - ADD_sh4r_r32( REG_OFFSET(r[0]), R_ECX ); - check_ralign32( R_ECX ); + load_reg( R_EAX, Rm ); + ADD_sh4r_r32( REG_OFFSET(r[0]), R_EAX ); + check_ralign32( R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); load_spreg( R_EDX, R_FPSCR ); TEST_imm32_r32( FPSCR_SZ, R_EDX ); JNE_rel8(8 + MEM_READ_SIZE, doublesize); - MEM_READ_LONG( R_ECX, R_EAX ); + MEM_READ_LONG( R_EAX, R_EAX ); load_fr_bank( R_EDX ); store_fr( R_EDX, R_EAX, FRn ); if( FRn&1 ) { JMP_rel8(21 + MEM_READ_DOUBLE_SIZE, end); JMP_TARGET(doublesize); - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX ); + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX ); load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it load_xf_bank( R_EDX ); - store_fr( R_EDX, R_EAX, FRn&0x0E ); - store_fr( R_EDX, R_ECX, FRn|0x01 ); + store_fr( R_EDX, R_ECX, FRn&0x0E ); + store_fr( R_EDX, R_EAX, FRn|0x01 ); JMP_TARGET(end); } else { JMP_rel8(9 + MEM_READ_DOUBLE_SIZE, end); JMP_TARGET(doublesize); - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX ); + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX ); load_fr_bank( R_EDX ); - store_fr( R_EDX, R_EAX, FRn&0x0E ); - store_fr( R_EDX, R_ECX, FRn|0x01 ); + store_fr( R_EDX, R_ECX, FRn&0x0E ); + store_fr( R_EDX, R_EAX, FRn|0x01 ); JMP_TARGET(end); } sh4_x86.tstate = TSTATE_NONE; @@ -2183,10 +2264,9 @@ LDC.L @Rm+, GBR {: load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_GBR ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2197,10 +2277,9 @@ check_priv(); load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); call_func1( sh4_write_sr, R_EAX ); sh4_x86.priv_checked = FALSE; sh4_x86.fpuen_checked = FALSE; @@ -2211,10 +2290,9 @@ check_priv(); load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_VBR ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2222,10 +2300,9 @@ check_priv(); load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_SSR ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2233,10 +2310,9 @@ check_priv(); load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_SGR ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2244,10 +2320,9 @@ check_priv(); load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_SPC ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2255,10 +2330,9 @@ check_priv(); load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_DBR ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2266,10 +2340,9 @@ check_priv(); load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2282,10 +2355,9 @@ LDS.L @Rm+, FPSCR {: load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_FPSCR ); update_fr_bank( R_EAX ); sh4_x86.tstate = TSTATE_NONE; @@ -2297,10 +2369,9 @@ LDS.L @Rm+, FPUL {: load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_FPUL ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2311,10 +2382,9 @@ LDS.L @Rm+, MACH {: load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_MACH ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2325,10 +2395,9 @@ LDS.L @Rm+, MACL {: load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_MACL ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2339,10 +2408,9 @@ LDS.L @Rm+, PR {: load_reg( R_EAX, Rm ); check_ralign32( R_EAX ); - MOV_r32_r32( R_EAX, R_ECX ); - ADD_imm8s_r32( 4, R_EAX ); - store_reg( R_EAX, Rm ); - MEM_READ_LONG( R_ECX, R_EAX ); + MMU_TRANSLATE_READ( R_EAX ); + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) ); + MEM_READ_LONG( R_EAX, R_EAX ); store_spreg( R_EAX, R_PR ); sh4_x86.tstate = TSTATE_NONE; :} @@ -2417,81 +2485,91 @@ :} STC.L SR, @-Rn {: check_priv(); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + PUSH_realigned_r32( R_EAX ); call_func0( sh4_read_sr ); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); + POP_realigned_r32( R_ECX ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); MEM_WRITE_LONG( R_ECX, R_EAX ); sh4_x86.tstate = TSTATE_NONE; :} STC.L VBR, @-Rn {: check_priv(); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_VBR ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_VBR ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STC.L SSR, @-Rn {: check_priv(); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_SSR ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_SSR ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STC.L SPC, @-Rn {: check_priv(); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_SPC ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_SPC ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STC.L SGR, @-Rn {: check_priv(); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_SGR ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_SGR ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STC.L DBR, @-Rn {: check_priv(); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_DBR ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_DBR ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STC.L Rm_BANK, @-Rn {: check_priv(); - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, REG_OFFSET(r_bank[Rm_BANK]) ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STC.L GBR, @-Rn {: - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_GBR ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_GBR ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STS FPSCR, Rn {: @@ -2499,12 +2577,13 @@ store_reg( R_EAX, Rn ); :} STS.L FPSCR, @-Rn {: - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_FPSCR ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_FPSCR ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STS FPUL, Rn {: @@ -2512,12 +2591,13 @@ store_reg( R_EAX, Rn ); :} STS.L FPUL, @-Rn {: - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_FPUL ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_FPUL ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STS MACH, Rn {: @@ -2525,12 +2605,13 @@ store_reg( R_EAX, Rn ); :} STS.L MACH, @-Rn {: - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_MACH ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_MACH ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STS MACL, Rn {: @@ -2538,12 +2619,13 @@ store_reg( R_EAX, Rn ); :} STS.L MACL, @-Rn {: - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_MACL ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_MACL ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :} STS PR, Rn {: @@ -2551,12 +2633,13 @@ store_reg( R_EAX, Rn ); :} STS.L PR, @-Rn {: - load_reg( R_ECX, Rn ); - check_walign32( R_ECX ); - ADD_imm8s_r32( -4, R_ECX ); - store_reg( R_ECX, Rn ); - load_spreg( R_EAX, R_PR ); - MEM_WRITE_LONG( R_ECX, R_EAX ); + load_reg( R_EAX, Rn ); + check_walign32( R_EAX ); + ADD_imm8s_r32( -4, R_EAX ); + MMU_TRANSLATE_WRITE( R_EAX ); + load_spreg( R_EDX, R_PR ); + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) ); + MEM_WRITE_LONG( R_EAX, R_EDX ); sh4_x86.tstate = TSTATE_NONE; :}