2 * $Id: sh4x86.in,v 1.18 2007-10-03 12:19:03 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 #define precheck() load_imm32(R_EDX, (pc-sh4_x86.block_start_pc-(sh4_x86.in_delay_slot?2:0))>>1)
298 #define check_priv( ) \
299 if( !sh4_x86.priv_checked ) { \
300 sh4_x86.priv_checked = TRUE;\
302 load_spreg( R_EAX, R_SR );\
303 AND_imm32_r32( SR_MD, R_EAX );\
304 if( sh4_x86.in_delay_slot ) {\
305 JE_exit( EXIT_SLOT_ILLEGAL );\
307 JE_exit( EXIT_ILLEGAL );\
312 static void check_priv_no_precheck()
314 if( !sh4_x86.priv_checked ) {
315 sh4_x86.priv_checked = TRUE;
316 load_spreg( R_EAX, R_SR );
317 AND_imm32_r32( SR_MD, R_EAX );
318 if( sh4_x86.in_delay_slot ) {
319 JE_exit( EXIT_SLOT_ILLEGAL );
321 JE_exit( EXIT_ILLEGAL );
326 #define check_fpuen( ) \
327 if( !sh4_x86.fpuen_checked ) {\
328 sh4_x86.fpuen_checked = TRUE;\
330 load_spreg( R_EAX, R_SR );\
331 AND_imm32_r32( SR_FD, R_EAX );\
332 if( sh4_x86.in_delay_slot ) {\
333 JNE_exit(EXIT_SLOT_FPU_DISABLED);\
335 JNE_exit(EXIT_FPU_DISABLED);\
339 static void check_fpuen_no_precheck()
341 if( !sh4_x86.fpuen_checked ) {
342 sh4_x86.fpuen_checked = TRUE;
343 load_spreg( R_EAX, R_SR );
344 AND_imm32_r32( SR_FD, R_EAX );
345 if( sh4_x86.in_delay_slot ) {
346 JNE_exit(EXIT_SLOT_FPU_DISABLED);
348 JNE_exit(EXIT_FPU_DISABLED);
354 static void check_ralign16( int x86reg )
356 TEST_imm32_r32( 0x00000001, x86reg );
357 JNE_exit(EXIT_DATA_ADDR_READ);
360 static void check_walign16( int x86reg )
362 TEST_imm32_r32( 0x00000001, x86reg );
363 JNE_exit(EXIT_DATA_ADDR_WRITE);
366 static void check_ralign32( int x86reg )
368 TEST_imm32_r32( 0x00000003, x86reg );
369 JNE_exit(EXIT_DATA_ADDR_READ);
371 static void check_walign32( int x86reg )
373 TEST_imm32_r32( 0x00000003, x86reg );
374 JNE_exit(EXIT_DATA_ADDR_WRITE);
378 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
379 #define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
380 #define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
381 #define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
382 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
383 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
384 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
386 #define SLOTILLEGAL() precheck(); JMP_exit(EXIT_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1;
391 * Emit the 'start of block' assembly. Sets up the stack frame and save
394 void sh4_translate_begin_block( sh4addr_t pc )
398 load_imm32( R_EBP, (uint32_t)&sh4r );
400 sh4_x86.in_delay_slot = FALSE;
401 sh4_x86.priv_checked = FALSE;
402 sh4_x86.fpuen_checked = FALSE;
403 sh4_x86.branch_taken = FALSE;
404 sh4_x86.backpatch_posn = 0;
405 sh4_x86.block_start_pc = pc;
409 * Exit the block to an absolute PC
412 void exit_block( sh4addr_t pc, sh4addr_t endpc )
414 load_imm32( R_ECX, pc ); // 5
415 store_spreg( R_ECX, REG_OFFSET(pc) ); // 3
416 MOV_moff32_EAX( (uint32_t)xlat_get_lut_entry(pc) ); // 5
417 AND_imm8s_r32( 0xFC, R_EAX ); // 3
418 load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
419 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
425 * Exit the block with sh4r.pc already written
428 void exit_block_pcset( pc )
430 XOR_r32_r32( R_EAX, R_EAX ); // 2
431 load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
432 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
438 * Write the block trailer (exception handling block)
440 void sh4_translate_end_block( sh4addr_t pc ) {
441 if( sh4_x86.branch_taken == FALSE ) {
442 // Didn't exit unconditionally already, so write the termination here
443 exit_block( pc, pc );
445 if( sh4_x86.backpatch_posn != 0 ) {
446 uint8_t *end_ptr = xlat_output;
447 // Exception termination. Jump block for various exception codes:
448 PUSH_imm32( EXC_DATA_ADDR_READ );
449 JMP_rel8( 33, target1 );
450 PUSH_imm32( EXC_DATA_ADDR_WRITE );
451 JMP_rel8( 26, target2 );
452 PUSH_imm32( EXC_ILLEGAL );
453 JMP_rel8( 19, target3 );
454 PUSH_imm32( EXC_SLOT_ILLEGAL );
455 JMP_rel8( 12, target4 );
456 PUSH_imm32( EXC_FPU_DISABLED );
457 JMP_rel8( 5, target5 );
458 PUSH_imm32( EXC_SLOT_FPU_DISABLED );
465 load_spreg( R_ECX, REG_OFFSET(pc) );
466 ADD_r32_r32( R_EDX, R_ECX );
467 ADD_r32_r32( R_EDX, R_ECX );
468 store_spreg( R_ECX, REG_OFFSET(pc) );
469 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
470 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
472 ADD_r32_r32( R_EAX, R_ECX );
473 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
475 load_imm32( R_EAX, (uint32_t)sh4_raise_exception ); // 6
476 CALL_r32( R_EAX ); // 2
477 ADD_imm8s_r32( 4, R_ESP );
478 XOR_r32_r32( R_EAX, R_EAX );
482 sh4_x86_do_backpatch( end_ptr );
488 extern uint16_t *sh4_icache;
489 extern uint32_t sh4_icache_addr;
492 * Translate a single instruction. Delayed branches are handled specially
493 * by translating both branch and delayed instruction as a single unit (as
496 * @return true if the instruction marks the end of a basic block
499 uint32_t sh4_x86_translate_instruction( sh4addr_t pc )
502 /* Read instruction */
503 uint32_t pageaddr = pc >> 12;
504 if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
505 ir = sh4_icache[(pc&0xFFF)>>1];
507 sh4_icache = (uint16_t *)mem_get_page(pc);
508 if( ((uint32_t)sh4_icache) < MAX_IO_REGIONS ) {
509 /* If someone's actually been so daft as to try to execute out of an IO
510 * region, fallback on the full-blown memory read
513 ir = sh4_read_word(pc);
515 sh4_icache_addr = pageaddr;
516 ir = sh4_icache[(pc&0xFFF)>>1];
523 load_reg( R_EAX, Rm );
524 load_reg( R_ECX, Rn );
525 ADD_r32_r32( R_EAX, R_ECX );
526 store_reg( R_ECX, Rn );
529 load_reg( R_EAX, Rn );
530 ADD_imm8s_r32( imm, R_EAX );
531 store_reg( R_EAX, Rn );
534 load_reg( R_EAX, Rm );
535 load_reg( R_ECX, Rn );
537 ADC_r32_r32( R_EAX, R_ECX );
538 store_reg( R_ECX, Rn );
542 load_reg( R_EAX, Rm );
543 load_reg( R_ECX, Rn );
544 ADD_r32_r32( R_EAX, R_ECX );
545 store_reg( R_ECX, Rn );
549 load_reg( R_EAX, Rm );
550 load_reg( R_ECX, Rn );
551 AND_r32_r32( R_EAX, R_ECX );
552 store_reg( R_ECX, Rn );
555 load_reg( R_EAX, 0 );
556 AND_imm32_r32(imm, R_EAX);
557 store_reg( R_EAX, 0 );
559 AND.B #imm, @(R0, GBR) {:
560 load_reg( R_EAX, 0 );
561 load_spreg( R_ECX, R_GBR );
562 ADD_r32_r32( R_EAX, R_ECX );
564 call_func0(sh4_read_byte);
566 AND_imm32_r32(imm, R_EAX );
567 MEM_WRITE_BYTE( R_ECX, R_EAX );
570 load_reg( R_EAX, Rm );
571 load_reg( R_ECX, Rn );
572 CMP_r32_r32( R_EAX, R_ECX );
576 load_reg( R_EAX, 0 );
577 CMP_imm8s_r32(imm, R_EAX);
581 load_reg( R_EAX, Rm );
582 load_reg( R_ECX, Rn );
583 CMP_r32_r32( R_EAX, R_ECX );
587 load_reg( R_EAX, Rm );
588 load_reg( R_ECX, Rn );
589 CMP_r32_r32( R_EAX, R_ECX );
593 load_reg( R_EAX, Rm );
594 load_reg( R_ECX, Rn );
595 CMP_r32_r32( R_EAX, R_ECX );
599 load_reg( R_EAX, Rm );
600 load_reg( R_ECX, Rn );
601 CMP_r32_r32( R_EAX, R_ECX );
605 load_reg( R_EAX, Rn );
606 CMP_imm8s_r32( 0, R_EAX );
610 load_reg( R_EAX, Rn );
611 CMP_imm8s_r32( 0, R_EAX );
615 load_reg( R_EAX, Rm );
616 load_reg( R_ECX, Rn );
617 XOR_r32_r32( R_ECX, R_EAX );
618 TEST_r8_r8( R_AL, R_AL );
619 JE_rel8(13, target1);
620 TEST_r8_r8( R_AH, R_AH ); // 2
622 SHR_imm8_r32( 16, R_EAX ); // 3
623 TEST_r8_r8( R_AL, R_AL ); // 2
625 TEST_r8_r8( R_AH, R_AH ); // 2
632 load_reg( R_EAX, Rm );
633 load_reg( R_ECX, Rn );
634 SHR_imm8_r32( 31, R_EAX );
635 SHR_imm8_r32( 31, R_ECX );
636 store_spreg( R_EAX, R_M );
637 store_spreg( R_ECX, R_Q );
638 CMP_r32_r32( R_EAX, R_ECX );
642 XOR_r32_r32( R_EAX, R_EAX );
643 store_spreg( R_EAX, R_Q );
644 store_spreg( R_EAX, R_M );
645 store_spreg( R_EAX, R_T );
648 load_spreg( R_ECX, R_M );
649 load_reg( R_EAX, Rn );
652 SETC_r8( R_DL ); // Q'
653 CMP_sh4r_r32( R_Q, R_ECX );
655 ADD_sh4r_r32( REG_OFFSET(r[Rm]), R_EAX );
658 SUB_sh4r_r32( REG_OFFSET(r[Rm]), R_EAX );
660 store_reg( R_EAX, Rn ); // Done with Rn now
661 SETC_r8(R_AL); // tmp1
662 XOR_r8_r8( R_DL, R_AL ); // Q' = Q ^ tmp1
663 XOR_r8_r8( R_AL, R_CL ); // Q'' = Q' ^ M
664 store_spreg( R_ECX, R_Q );
665 XOR_imm8s_r32( 1, R_AL ); // T = !Q'
666 MOVZX_r8_r32( R_AL, R_EAX );
667 store_spreg( R_EAX, R_T );
670 load_reg( R_EAX, Rm );
671 load_reg( R_ECX, Rn );
673 store_spreg( R_EDX, R_MACH );
674 store_spreg( R_EAX, R_MACL );
677 load_reg( R_EAX, Rm );
678 load_reg( R_ECX, Rn );
680 store_spreg( R_EDX, R_MACH );
681 store_spreg( R_EAX, R_MACL );
684 load_reg( R_EAX, Rn );
685 ADD_imm8s_r32( -1, R_EAX );
686 store_reg( R_EAX, Rn );
690 load_reg( R_EAX, Rm );
691 MOVSX_r8_r32( R_EAX, R_EAX );
692 store_reg( R_EAX, Rn );
695 load_reg( R_EAX, Rm );
696 MOVSX_r16_r32( R_EAX, R_EAX );
697 store_reg( R_EAX, Rn );
700 load_reg( R_EAX, Rm );
701 MOVZX_r8_r32( R_EAX, R_EAX );
702 store_reg( R_EAX, Rn );
705 load_reg( R_EAX, Rm );
706 MOVZX_r16_r32( R_EAX, R_EAX );
707 store_reg( R_EAX, Rn );
710 load_reg( R_ECX, Rm );
712 check_ralign32( R_ECX );
713 load_reg( R_ECX, Rn );
714 check_ralign32( R_ECX );
715 ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) );
716 MEM_READ_LONG( R_ECX, R_EAX );
718 load_reg( R_ECX, Rm );
719 ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
720 MEM_READ_LONG( R_ECX, R_EAX );
723 ADD_r32_sh4r( R_EAX, R_MACL );
724 ADC_r32_sh4r( R_EDX, R_MACH );
726 load_spreg( R_ECX, R_S );
727 TEST_r32_r32(R_ECX, R_ECX);
729 call_func0( signsat48 );
733 load_reg( R_ECX, Rm );
735 check_ralign16( R_ECX );
736 load_reg( R_ECX, Rn );
737 check_ralign16( R_ECX );
738 ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rn]) );
739 MEM_READ_WORD( R_ECX, R_EAX );
741 load_reg( R_ECX, Rm );
742 ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) );
743 MEM_READ_WORD( R_ECX, R_EAX );
747 load_spreg( R_ECX, R_S );
748 TEST_r32_r32( R_ECX, R_ECX );
749 JE_rel8( 47, nosat );
751 ADD_r32_sh4r( R_EAX, R_MACL ); // 6
752 JNO_rel8( 51, end ); // 2
753 load_imm32( R_EDX, 1 ); // 5
754 store_spreg( R_EDX, R_MACH ); // 6
755 JS_rel8( 13, positive ); // 2
756 load_imm32( R_EAX, 0x80000000 );// 5
757 store_spreg( R_EAX, R_MACL ); // 6
758 JMP_rel8( 25, end2 ); // 2
760 JMP_TARGET(positive);
761 load_imm32( R_EAX, 0x7FFFFFFF );// 5
762 store_spreg( R_EAX, R_MACL ); // 6
763 JMP_rel8( 12, end3); // 2
766 ADD_r32_sh4r( R_EAX, R_MACL ); // 6
767 ADC_r32_sh4r( R_EDX, R_MACH ); // 6
773 load_spreg( R_EAX, R_T );
774 store_reg( R_EAX, Rn );
777 load_reg( R_EAX, Rm );
778 load_reg( R_ECX, Rn );
780 store_spreg( R_EAX, R_MACL );
783 load_reg16s( R_EAX, Rm );
784 load_reg16s( R_ECX, Rn );
786 store_spreg( R_EAX, R_MACL );
789 load_reg16u( R_EAX, Rm );
790 load_reg16u( R_ECX, Rn );
792 store_spreg( R_EAX, R_MACL );
795 load_reg( R_EAX, Rm );
797 store_reg( R_EAX, Rn );
800 load_reg( R_EAX, Rm );
801 XOR_r32_r32( R_ECX, R_ECX );
803 SBB_r32_r32( R_EAX, R_ECX );
804 store_reg( R_ECX, Rn );
808 load_reg( R_EAX, Rm );
810 store_reg( R_EAX, Rn );
813 load_reg( R_EAX, Rm );
814 load_reg( R_ECX, Rn );
815 OR_r32_r32( R_EAX, R_ECX );
816 store_reg( R_ECX, Rn );
819 load_reg( R_EAX, 0 );
820 OR_imm32_r32(imm, R_EAX);
821 store_reg( R_EAX, 0 );
823 OR.B #imm, @(R0, GBR) {:
824 load_reg( R_EAX, 0 );
825 load_spreg( R_ECX, R_GBR );
826 ADD_r32_r32( R_EAX, R_ECX );
828 call_func0(sh4_read_byte);
830 OR_imm32_r32(imm, R_EAX );
831 MEM_WRITE_BYTE( R_ECX, R_EAX );
834 load_reg( R_EAX, Rn );
837 store_reg( R_EAX, Rn );
841 load_reg( R_EAX, Rn );
844 store_reg( R_EAX, Rn );
848 load_reg( R_EAX, Rn );
850 store_reg( R_EAX, Rn );
854 load_reg( R_EAX, Rn );
856 store_reg( R_EAX, Rn );
860 /* Annoyingly enough, not directly convertible */
861 load_reg( R_EAX, Rn );
862 load_reg( R_ECX, Rm );
863 CMP_imm32_r32( 0, R_ECX );
866 NEG_r32( R_ECX ); // 2
867 AND_imm8_r8( 0x1F, R_CL ); // 3
868 JE_rel8( 4, emptysar); // 2
869 SAR_r32_CL( R_EAX ); // 2
870 JMP_rel8(10, end); // 2
872 JMP_TARGET(emptysar);
873 SAR_imm8_r32(31, R_EAX ); // 3
877 AND_imm8_r8( 0x1F, R_CL ); // 3
878 SHL_r32_CL( R_EAX ); // 2
881 store_reg( R_EAX, Rn );
884 load_reg( R_EAX, Rn );
885 load_reg( R_ECX, Rm );
886 CMP_imm32_r32( 0, R_ECX );
889 NEG_r32( R_ECX ); // 2
890 AND_imm8_r8( 0x1F, R_CL ); // 3
891 JE_rel8( 4, emptyshr );
892 SHR_r32_CL( R_EAX ); // 2
893 JMP_rel8(9, end); // 2
895 JMP_TARGET(emptyshr);
896 XOR_r32_r32( R_EAX, R_EAX );
900 AND_imm8_r8( 0x1F, R_CL ); // 3
901 SHL_r32_CL( R_EAX ); // 2
904 store_reg( R_EAX, Rn );
907 load_reg( R_EAX, Rn );
910 store_reg( R_EAX, Rn );
913 load_reg( R_EAX, Rn );
916 store_reg( R_EAX, Rn );
919 load_reg( R_EAX, Rn );
922 store_reg( R_EAX, Rn );
925 load_reg( R_EAX, Rn );
926 SHL_imm8_r32( 2, R_EAX );
927 store_reg( R_EAX, Rn );
930 load_reg( R_EAX, Rn );
931 SHL_imm8_r32( 8, R_EAX );
932 store_reg( R_EAX, Rn );
935 load_reg( R_EAX, Rn );
936 SHL_imm8_r32( 16, R_EAX );
937 store_reg( R_EAX, Rn );
940 load_reg( R_EAX, Rn );
943 store_reg( R_EAX, Rn );
946 load_reg( R_EAX, Rn );
947 SHR_imm8_r32( 2, R_EAX );
948 store_reg( R_EAX, Rn );
951 load_reg( R_EAX, Rn );
952 SHR_imm8_r32( 8, R_EAX );
953 store_reg( R_EAX, Rn );
956 load_reg( R_EAX, Rn );
957 SHR_imm8_r32( 16, R_EAX );
958 store_reg( R_EAX, Rn );
961 load_reg( R_EAX, Rm );
962 load_reg( R_ECX, Rn );
963 SUB_r32_r32( R_EAX, R_ECX );
964 store_reg( R_ECX, Rn );
967 load_reg( R_EAX, Rm );
968 load_reg( R_ECX, Rn );
970 SBB_r32_r32( R_EAX, R_ECX );
971 store_reg( R_ECX, Rn );
975 load_reg( R_EAX, Rm );
976 load_reg( R_ECX, Rn );
977 SUB_r32_r32( R_EAX, R_ECX );
978 store_reg( R_ECX, Rn );
982 load_reg( R_EAX, Rm );
983 XCHG_r8_r8( R_AL, R_AH );
984 store_reg( R_EAX, Rn );
987 load_reg( R_EAX, Rm );
988 MOV_r32_r32( R_EAX, R_ECX );
989 SHL_imm8_r32( 16, R_ECX );
990 SHR_imm8_r32( 16, R_EAX );
991 OR_r32_r32( R_EAX, R_ECX );
992 store_reg( R_ECX, Rn );
995 load_reg( R_ECX, Rn );
996 MEM_READ_BYTE( R_ECX, R_EAX );
997 TEST_r8_r8( R_AL, R_AL );
999 OR_imm8_r8( 0x80, R_AL );
1000 load_reg( R_ECX, Rn );
1001 MEM_WRITE_BYTE( R_ECX, R_EAX );
1004 load_reg( R_EAX, Rm );
1005 load_reg( R_ECX, Rn );
1006 TEST_r32_r32( R_EAX, R_ECX );
1010 load_reg( R_EAX, 0 );
1011 TEST_imm32_r32( imm, R_EAX );
1014 TST.B #imm, @(R0, GBR) {:
1015 load_reg( R_EAX, 0);
1016 load_reg( R_ECX, R_GBR);
1017 ADD_r32_r32( R_EAX, R_ECX );
1018 MEM_READ_BYTE( R_ECX, R_EAX );
1019 TEST_imm8_r8( imm, R_AL );
1023 load_reg( R_EAX, Rm );
1024 load_reg( R_ECX, Rn );
1025 XOR_r32_r32( R_EAX, R_ECX );
1026 store_reg( R_ECX, Rn );
1029 load_reg( R_EAX, 0 );
1030 XOR_imm32_r32( imm, R_EAX );
1031 store_reg( R_EAX, 0 );
1033 XOR.B #imm, @(R0, GBR) {:
1034 load_reg( R_EAX, 0 );
1035 load_spreg( R_ECX, R_GBR );
1036 ADD_r32_r32( R_EAX, R_ECX );
1038 call_func0(sh4_read_byte);
1040 XOR_imm32_r32( imm, R_EAX );
1041 MEM_WRITE_BYTE( R_ECX, R_EAX );
1044 load_reg( R_EAX, Rm );
1045 load_reg( R_ECX, Rn );
1046 SHL_imm8_r32( 16, R_EAX );
1047 SHR_imm8_r32( 16, R_ECX );
1048 OR_r32_r32( R_EAX, R_ECX );
1049 store_reg( R_ECX, Rn );
1052 /* Data move instructions */
1054 load_reg( R_EAX, Rm );
1055 store_reg( R_EAX, Rn );
1058 load_imm32( R_EAX, imm );
1059 store_reg( R_EAX, Rn );
1062 load_reg( R_EAX, Rm );
1063 load_reg( R_ECX, Rn );
1064 MEM_WRITE_BYTE( R_ECX, R_EAX );
1067 load_reg( R_EAX, Rm );
1068 load_reg( R_ECX, Rn );
1069 ADD_imm8s_r32( -1, R_ECX );
1070 store_reg( R_ECX, Rn );
1071 MEM_WRITE_BYTE( R_ECX, R_EAX );
1073 MOV.B Rm, @(R0, Rn) {:
1074 load_reg( R_EAX, 0 );
1075 load_reg( R_ECX, Rn );
1076 ADD_r32_r32( R_EAX, R_ECX );
1077 load_reg( R_EAX, Rm );
1078 MEM_WRITE_BYTE( R_ECX, R_EAX );
1080 MOV.B R0, @(disp, GBR) {:
1081 load_reg( R_EAX, 0 );
1082 load_spreg( R_ECX, R_GBR );
1083 ADD_imm32_r32( disp, R_ECX );
1084 MEM_WRITE_BYTE( R_ECX, R_EAX );
1086 MOV.B R0, @(disp, Rn) {:
1087 load_reg( R_EAX, 0 );
1088 load_reg( R_ECX, Rn );
1089 ADD_imm32_r32( disp, R_ECX );
1090 MEM_WRITE_BYTE( R_ECX, R_EAX );
1093 load_reg( R_ECX, Rm );
1094 MEM_READ_BYTE( R_ECX, R_EAX );
1095 store_reg( R_EAX, Rn );
1098 load_reg( R_ECX, Rm );
1099 MOV_r32_r32( R_ECX, R_EAX );
1100 ADD_imm8s_r32( 1, R_EAX );
1101 store_reg( R_EAX, Rm );
1102 MEM_READ_BYTE( R_ECX, R_EAX );
1103 store_reg( R_EAX, Rn );
1105 MOV.B @(R0, Rm), Rn {:
1106 load_reg( R_EAX, 0 );
1107 load_reg( R_ECX, Rm );
1108 ADD_r32_r32( R_EAX, R_ECX );
1109 MEM_READ_BYTE( R_ECX, R_EAX );
1110 store_reg( R_EAX, Rn );
1112 MOV.B @(disp, GBR), R0 {:
1113 load_spreg( R_ECX, R_GBR );
1114 ADD_imm32_r32( disp, R_ECX );
1115 MEM_READ_BYTE( R_ECX, R_EAX );
1116 store_reg( R_EAX, 0 );
1118 MOV.B @(disp, Rm), R0 {:
1119 load_reg( R_ECX, Rm );
1120 ADD_imm32_r32( disp, R_ECX );
1121 MEM_READ_BYTE( R_ECX, R_EAX );
1122 store_reg( R_EAX, 0 );
1125 load_reg( R_EAX, Rm );
1126 load_reg( R_ECX, Rn );
1128 check_walign32(R_ECX);
1129 MEM_WRITE_LONG( R_ECX, R_EAX );
1132 load_reg( R_EAX, Rm );
1133 load_reg( R_ECX, Rn );
1135 check_walign32( R_ECX );
1136 ADD_imm8s_r32( -4, R_ECX );
1137 store_reg( R_ECX, Rn );
1138 MEM_WRITE_LONG( R_ECX, R_EAX );
1140 MOV.L Rm, @(R0, Rn) {:
1141 load_reg( R_EAX, 0 );
1142 load_reg( R_ECX, Rn );
1143 ADD_r32_r32( R_EAX, R_ECX );
1145 check_walign32( R_ECX );
1146 load_reg( R_EAX, Rm );
1147 MEM_WRITE_LONG( R_ECX, R_EAX );
1149 MOV.L R0, @(disp, GBR) {:
1150 load_spreg( R_ECX, R_GBR );
1151 load_reg( R_EAX, 0 );
1152 ADD_imm32_r32( disp, R_ECX );
1154 check_walign32( R_ECX );
1155 MEM_WRITE_LONG( R_ECX, R_EAX );
1157 MOV.L Rm, @(disp, Rn) {:
1158 load_reg( R_ECX, Rn );
1159 load_reg( R_EAX, Rm );
1160 ADD_imm32_r32( disp, R_ECX );
1162 check_walign32( R_ECX );
1163 MEM_WRITE_LONG( R_ECX, R_EAX );
1166 load_reg( R_ECX, Rm );
1168 check_ralign32( R_ECX );
1169 MEM_READ_LONG( R_ECX, R_EAX );
1170 store_reg( R_EAX, Rn );
1173 load_reg( R_EAX, Rm );
1175 check_ralign32( R_EAX );
1176 MOV_r32_r32( R_EAX, R_ECX );
1177 ADD_imm8s_r32( 4, R_EAX );
1178 store_reg( R_EAX, Rm );
1179 MEM_READ_LONG( R_ECX, R_EAX );
1180 store_reg( R_EAX, Rn );
1182 MOV.L @(R0, Rm), Rn {:
1183 load_reg( R_EAX, 0 );
1184 load_reg( R_ECX, Rm );
1185 ADD_r32_r32( R_EAX, R_ECX );
1187 check_ralign32( R_ECX );
1188 MEM_READ_LONG( R_ECX, R_EAX );
1189 store_reg( R_EAX, Rn );
1191 MOV.L @(disp, GBR), R0 {:
1192 load_spreg( R_ECX, R_GBR );
1193 ADD_imm32_r32( disp, R_ECX );
1195 check_ralign32( R_ECX );
1196 MEM_READ_LONG( R_ECX, R_EAX );
1197 store_reg( R_EAX, 0 );
1199 MOV.L @(disp, PC), Rn {:
1200 if( sh4_x86.in_delay_slot ) {
1203 uint32_t target = (pc & 0xFFFFFFFC) + disp + 4;
1204 char *ptr = mem_get_region(target);
1206 MOV_moff32_EAX( (uint32_t)ptr );
1208 load_imm32( R_ECX, target );
1209 MEM_READ_LONG( R_ECX, R_EAX );
1211 store_reg( R_EAX, Rn );
1214 MOV.L @(disp, Rm), Rn {:
1215 load_reg( R_ECX, Rm );
1216 ADD_imm8s_r32( disp, R_ECX );
1218 check_ralign32( R_ECX );
1219 MEM_READ_LONG( R_ECX, R_EAX );
1220 store_reg( R_EAX, Rn );
1223 load_reg( R_ECX, Rn );
1225 check_walign16( R_ECX );
1226 load_reg( R_EAX, Rm );
1227 MEM_WRITE_WORD( R_ECX, R_EAX );
1230 load_reg( R_ECX, Rn );
1232 check_walign16( R_ECX );
1233 load_reg( R_EAX, Rm );
1234 ADD_imm8s_r32( -2, R_ECX );
1235 store_reg( R_ECX, Rn );
1236 MEM_WRITE_WORD( R_ECX, R_EAX );
1238 MOV.W Rm, @(R0, Rn) {:
1239 load_reg( R_EAX, 0 );
1240 load_reg( R_ECX, Rn );
1241 ADD_r32_r32( R_EAX, R_ECX );
1243 check_walign16( R_ECX );
1244 load_reg( R_EAX, Rm );
1245 MEM_WRITE_WORD( R_ECX, R_EAX );
1247 MOV.W R0, @(disp, GBR) {:
1248 load_spreg( R_ECX, R_GBR );
1249 load_reg( R_EAX, 0 );
1250 ADD_imm32_r32( disp, R_ECX );
1252 check_walign16( R_ECX );
1253 MEM_WRITE_WORD( R_ECX, R_EAX );
1255 MOV.W R0, @(disp, Rn) {:
1256 load_reg( R_ECX, Rn );
1257 load_reg( R_EAX, 0 );
1258 ADD_imm32_r32( disp, R_ECX );
1260 check_walign16( R_ECX );
1261 MEM_WRITE_WORD( R_ECX, R_EAX );
1264 load_reg( R_ECX, Rm );
1266 check_ralign16( R_ECX );
1267 MEM_READ_WORD( R_ECX, R_EAX );
1268 store_reg( R_EAX, Rn );
1271 load_reg( R_EAX, Rm );
1273 check_ralign16( R_EAX );
1274 MOV_r32_r32( R_EAX, R_ECX );
1275 ADD_imm8s_r32( 2, R_EAX );
1276 store_reg( R_EAX, Rm );
1277 MEM_READ_WORD( R_ECX, R_EAX );
1278 store_reg( R_EAX, Rn );
1280 MOV.W @(R0, Rm), Rn {:
1281 load_reg( R_EAX, 0 );
1282 load_reg( R_ECX, Rm );
1283 ADD_r32_r32( R_EAX, R_ECX );
1285 check_ralign16( R_ECX );
1286 MEM_READ_WORD( R_ECX, R_EAX );
1287 store_reg( R_EAX, Rn );
1289 MOV.W @(disp, GBR), R0 {:
1290 load_spreg( R_ECX, R_GBR );
1291 ADD_imm32_r32( disp, R_ECX );
1293 check_ralign16( R_ECX );
1294 MEM_READ_WORD( R_ECX, R_EAX );
1295 store_reg( R_EAX, 0 );
1297 MOV.W @(disp, PC), Rn {:
1298 if( sh4_x86.in_delay_slot ) {
1301 load_imm32( R_ECX, pc + disp + 4 );
1302 MEM_READ_WORD( R_ECX, R_EAX );
1303 store_reg( R_EAX, Rn );
1306 MOV.W @(disp, Rm), R0 {:
1307 load_reg( R_ECX, Rm );
1308 ADD_imm32_r32( disp, R_ECX );
1310 check_ralign16( R_ECX );
1311 MEM_READ_WORD( R_ECX, R_EAX );
1312 store_reg( R_EAX, 0 );
1314 MOVA @(disp, PC), R0 {:
1315 if( sh4_x86.in_delay_slot ) {
1318 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1319 store_reg( R_ECX, 0 );
1323 load_reg( R_EAX, 0 );
1324 load_reg( R_ECX, Rn );
1326 check_walign32( R_ECX );
1327 MEM_WRITE_LONG( R_ECX, R_EAX );
1330 /* Control transfer instructions */
1332 if( sh4_x86.in_delay_slot ) {
1335 CMP_imm8s_sh4r( 0, R_T );
1336 JNE_rel8( 29, nottaken );
1337 exit_block( disp + pc + 4, pc+2 );
1338 JMP_TARGET(nottaken);
1343 if( sh4_x86.in_delay_slot ) {
1346 sh4_x86.in_delay_slot = TRUE;
1347 CMP_imm8s_sh4r( 0, R_T );
1348 OP(0x0F); OP(0x85); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel32
1349 sh4_x86_translate_instruction(pc+2);
1350 exit_block( disp + pc + 4, pc+4 );
1352 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1353 sh4_x86_translate_instruction(pc+2);
1358 if( sh4_x86.in_delay_slot ) {
1361 sh4_x86.in_delay_slot = TRUE;
1362 sh4_x86_translate_instruction( pc + 2 );
1363 exit_block( disp + pc + 4, pc+4 );
1364 sh4_x86.branch_taken = TRUE;
1369 if( sh4_x86.in_delay_slot ) {
1372 load_reg( R_EAX, Rn );
1373 ADD_imm32_r32( pc + 4, R_EAX );
1374 store_spreg( R_EAX, REG_OFFSET(pc) );
1375 sh4_x86.in_delay_slot = TRUE;
1376 sh4_x86_translate_instruction( pc + 2 );
1377 exit_block_pcset(pc+2);
1378 sh4_x86.branch_taken = TRUE;
1383 if( sh4_x86.in_delay_slot ) {
1386 load_imm32( R_EAX, pc + 4 );
1387 store_spreg( R_EAX, R_PR );
1388 sh4_x86.in_delay_slot = TRUE;
1389 sh4_x86_translate_instruction( pc + 2 );
1390 exit_block( disp + pc + 4, pc+4 );
1391 sh4_x86.branch_taken = TRUE;
1396 if( sh4_x86.in_delay_slot ) {
1399 load_imm32( R_ECX, pc + 4 );
1400 store_spreg( R_ECX, R_PR );
1401 ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_ECX );
1402 store_spreg( R_ECX, REG_OFFSET(pc) );
1403 sh4_x86.in_delay_slot = TRUE;
1404 sh4_x86_translate_instruction( pc + 2 );
1405 exit_block_pcset(pc+2);
1406 sh4_x86.branch_taken = TRUE;
1411 if( sh4_x86.in_delay_slot ) {
1414 CMP_imm8s_sh4r( 0, R_T );
1415 JE_rel8( 29, nottaken );
1416 exit_block( disp + pc + 4, pc+2 );
1417 JMP_TARGET(nottaken);
1422 if( sh4_x86.in_delay_slot ) {
1425 sh4_x86.in_delay_slot = TRUE;
1426 CMP_imm8s_sh4r( 0, R_T );
1427 OP(0x0F); OP(0x84); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel32
1428 sh4_x86_translate_instruction(pc+2);
1429 exit_block( disp + pc + 4, pc+4 );
1431 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1432 sh4_x86_translate_instruction(pc+2);
1437 if( sh4_x86.in_delay_slot ) {
1440 load_reg( R_ECX, Rn );
1441 store_spreg( R_ECX, REG_OFFSET(pc) );
1442 sh4_x86.in_delay_slot = TRUE;
1443 sh4_x86_translate_instruction(pc+2);
1444 exit_block_pcset(pc+2);
1445 sh4_x86.branch_taken = TRUE;
1450 if( sh4_x86.in_delay_slot ) {
1453 load_imm32( R_EAX, pc + 4 );
1454 store_spreg( R_EAX, R_PR );
1455 load_reg( R_ECX, Rn );
1456 store_spreg( R_ECX, REG_OFFSET(pc) );
1457 sh4_x86.in_delay_slot = TRUE;
1458 sh4_x86_translate_instruction(pc+2);
1459 exit_block_pcset(pc+2);
1460 sh4_x86.branch_taken = TRUE;
1465 if( sh4_x86.in_delay_slot ) {
1469 load_spreg( R_ECX, R_SPC );
1470 store_spreg( R_ECX, REG_OFFSET(pc) );
1471 load_spreg( R_EAX, R_SSR );
1472 call_func1( sh4_write_sr, R_EAX );
1473 sh4_x86.in_delay_slot = TRUE;
1474 sh4_x86.priv_checked = FALSE;
1475 sh4_x86.fpuen_checked = FALSE;
1476 sh4_x86_translate_instruction(pc+2);
1477 exit_block_pcset(pc+2);
1478 sh4_x86.branch_taken = TRUE;
1483 if( sh4_x86.in_delay_slot ) {
1486 load_spreg( R_ECX, R_PR );
1487 store_spreg( R_ECX, REG_OFFSET(pc) );
1488 sh4_x86.in_delay_slot = TRUE;
1489 sh4_x86_translate_instruction(pc+2);
1490 exit_block_pcset(pc+2);
1491 sh4_x86.branch_taken = TRUE;
1496 if( sh4_x86.in_delay_slot ) {
1500 call_func0( sh4_raise_trap );
1501 ADD_imm8s_r32( 4, R_ESP );
1502 exit_block_pcset(pc);
1503 sh4_x86.branch_taken = TRUE;
1508 if( sh4_x86.in_delay_slot ) {
1512 JMP_exit(EXIT_ILLEGAL);
1518 XOR_r32_r32(R_EAX, R_EAX);
1519 store_spreg( R_EAX, R_MACL );
1520 store_spreg( R_EAX, R_MACH );
1539 /* Floating point moves */
1541 /* As horrible as this looks, it's actually covering 5 separate cases:
1542 * 1. 32-bit fr-to-fr (PR=0)
1543 * 2. 64-bit dr-to-dr (PR=1, FRm&1 == 0, FRn&1 == 0 )
1544 * 3. 64-bit dr-to-xd (PR=1, FRm&1 == 0, FRn&1 == 1 )
1545 * 4. 64-bit xd-to-dr (PR=1, FRm&1 == 1, FRn&1 == 0 )
1546 * 5. 64-bit xd-to-xd (PR=1, FRm&1 == 1, FRn&1 == 1 )
1549 load_spreg( R_ECX, R_FPSCR );
1550 load_fr_bank( R_EDX );
1551 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1552 JNE_rel8(8, doublesize);
1553 load_fr( R_EDX, R_EAX, FRm ); // PR=0 branch
1554 store_fr( R_EDX, R_EAX, FRn );
1557 JMP_TARGET(doublesize);
1558 load_xf_bank( R_ECX );
1559 load_fr( R_ECX, R_EAX, FRm-1 );
1561 load_fr( R_ECX, R_EDX, FRm );
1562 store_fr( R_ECX, R_EAX, FRn-1 );
1563 store_fr( R_ECX, R_EDX, FRn );
1564 } else /* FRn&1 == 0 */ {
1565 load_fr( R_ECX, R_ECX, FRm );
1566 store_fr( R_EDX, R_EAX, FRn );
1567 store_fr( R_EDX, R_ECX, FRn+1 );
1570 } else /* FRm&1 == 0 */ {
1573 load_xf_bank( R_ECX );
1574 load_fr( R_EDX, R_EAX, FRm );
1575 load_fr( R_EDX, R_EDX, FRm+1 );
1576 store_fr( R_ECX, R_EAX, FRn-1 );
1577 store_fr( R_ECX, R_EDX, FRn );
1579 } else /* FRn&1 == 0 */ {
1581 load_fr( R_EDX, R_EAX, FRm );
1582 load_fr( R_EDX, R_ECX, FRm+1 );
1583 store_fr( R_EDX, R_EAX, FRn );
1584 store_fr( R_EDX, R_ECX, FRn+1 );
1591 check_fpuen_no_precheck();
1592 load_reg( R_ECX, Rn );
1593 check_walign32( R_ECX );
1594 load_spreg( R_EDX, R_FPSCR );
1595 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1596 JNE_rel8(20, doublesize);
1597 load_fr_bank( R_EDX );
1598 load_fr( R_EDX, R_EAX, FRm );
1599 MEM_WRITE_LONG( R_ECX, R_EAX ); // 12
1601 JMP_rel8( 48, end );
1602 JMP_TARGET(doublesize);
1603 load_xf_bank( R_EDX );
1604 load_fr( R_EDX, R_EAX, FRm&0x0E );
1605 load_fr( R_EDX, R_EDX, FRm|0x01 );
1606 MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1609 JMP_rel8( 39, end );
1610 JMP_TARGET(doublesize);
1611 load_fr_bank( R_EDX );
1612 load_fr( R_EDX, R_EAX, FRm&0x0E );
1613 load_fr( R_EDX, R_EDX, FRm|0x01 );
1614 MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1620 check_fpuen_no_precheck();
1621 load_reg( R_ECX, Rm );
1622 check_ralign32( R_ECX );
1623 load_spreg( R_EDX, R_FPSCR );
1624 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1625 JNE_rel8(19, doublesize);
1626 MEM_READ_LONG( R_ECX, R_EAX );
1627 load_fr_bank( R_EDX );
1628 store_fr( R_EDX, R_EAX, FRn );
1631 JMP_TARGET(doublesize);
1632 MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1633 load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it
1634 load_xf_bank( R_EDX );
1635 store_fr( R_EDX, R_EAX, FRn&0x0E );
1636 store_fr( R_EDX, R_ECX, FRn|0x01 );
1640 JMP_TARGET(doublesize);
1641 MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1642 load_fr_bank( R_EDX );
1643 store_fr( R_EDX, R_EAX, FRn&0x0E );
1644 store_fr( R_EDX, R_ECX, FRn|0x01 );
1650 check_fpuen_no_precheck();
1651 load_reg( R_ECX, Rn );
1652 check_walign32( R_ECX );
1653 load_spreg( R_EDX, R_FPSCR );
1654 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1655 JNE_rel8(26, doublesize);
1656 load_fr_bank( R_EDX );
1657 load_fr( R_EDX, R_EAX, FRm );
1658 ADD_imm8s_r32(-4,R_ECX);
1659 store_reg( R_ECX, Rn );
1660 MEM_WRITE_LONG( R_ECX, R_EAX ); // 12
1662 JMP_rel8( 54, end );
1663 JMP_TARGET(doublesize);
1664 load_xf_bank( R_EDX );
1665 load_fr( R_EDX, R_EAX, FRm&0x0E );
1666 load_fr( R_EDX, R_EDX, FRm|0x01 );
1667 ADD_imm8s_r32(-8,R_ECX);
1668 store_reg( R_ECX, Rn );
1669 MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1672 JMP_rel8( 45, end );
1673 JMP_TARGET(doublesize);
1674 load_fr_bank( R_EDX );
1675 load_fr( R_EDX, R_EAX, FRm&0x0E );
1676 load_fr( R_EDX, R_EDX, FRm|0x01 );
1677 ADD_imm8s_r32(-8,R_ECX);
1678 store_reg( R_ECX, Rn );
1679 MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1685 check_fpuen_no_precheck();
1686 load_reg( R_ECX, Rm );
1687 check_ralign32( R_ECX );
1688 MOV_r32_r32( R_ECX, R_EAX );
1689 load_spreg( R_EDX, R_FPSCR );
1690 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1691 JNE_rel8(25, doublesize);
1692 ADD_imm8s_r32( 4, R_EAX );
1693 store_reg( R_EAX, Rm );
1694 MEM_READ_LONG( R_ECX, R_EAX );
1695 load_fr_bank( R_EDX );
1696 store_fr( R_EDX, R_EAX, FRn );
1699 JMP_TARGET(doublesize);
1700 ADD_imm8s_r32( 8, R_EAX );
1701 store_reg(R_EAX, Rm);
1702 MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1703 load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it
1704 load_xf_bank( R_EDX );
1705 store_fr( R_EDX, R_EAX, FRn&0x0E );
1706 store_fr( R_EDX, R_ECX, FRn|0x01 );
1710 ADD_imm8s_r32( 8, R_EAX );
1711 store_reg(R_EAX, Rm);
1712 MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1713 load_fr_bank( R_EDX );
1714 store_fr( R_EDX, R_EAX, FRn&0x0E );
1715 store_fr( R_EDX, R_ECX, FRn|0x01 );
1719 FMOV FRm, @(R0, Rn) {:
1721 check_fpuen_no_precheck();
1722 load_reg( R_ECX, Rn );
1723 ADD_sh4r_r32( REG_OFFSET(r[0]), R_ECX );
1724 check_walign32( R_ECX );
1725 load_spreg( R_EDX, R_FPSCR );
1726 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1727 JNE_rel8(20, doublesize);
1728 load_fr_bank( R_EDX );
1729 load_fr( R_EDX, R_EAX, FRm );
1730 MEM_WRITE_LONG( R_ECX, R_EAX ); // 12
1732 JMP_rel8( 48, end );
1733 JMP_TARGET(doublesize);
1734 load_xf_bank( R_EDX );
1735 load_fr( R_EDX, R_EAX, FRm&0x0E );
1736 load_fr( R_EDX, R_EDX, FRm|0x01 );
1737 MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1740 JMP_rel8( 39, end );
1741 JMP_TARGET(doublesize);
1742 load_fr_bank( R_EDX );
1743 load_fr( R_EDX, R_EAX, FRm&0x0E );
1744 load_fr( R_EDX, R_EDX, FRm|0x01 );
1745 MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1749 FMOV @(R0, Rm), FRn {:
1751 check_fpuen_no_precheck();
1752 load_reg( R_ECX, Rm );
1753 ADD_sh4r_r32( REG_OFFSET(r[0]), R_ECX );
1754 check_ralign32( R_ECX );
1755 load_spreg( R_EDX, R_FPSCR );
1756 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1757 JNE_rel8(19, doublesize);
1758 MEM_READ_LONG( R_ECX, R_EAX );
1759 load_fr_bank( R_EDX );
1760 store_fr( R_EDX, R_EAX, FRn );
1763 JMP_TARGET(doublesize);
1764 MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1765 load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it
1766 load_xf_bank( R_EDX );
1767 store_fr( R_EDX, R_EAX, FRn&0x0E );
1768 store_fr( R_EDX, R_ECX, FRn|0x01 );
1772 JMP_TARGET(doublesize);
1773 MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1774 load_fr_bank( R_EDX );
1775 store_fr( R_EDX, R_EAX, FRn&0x0E );
1776 store_fr( R_EDX, R_ECX, FRn|0x01 );
1780 FLDI0 FRn {: /* IFF PR=0 */
1782 load_spreg( R_ECX, R_FPSCR );
1783 TEST_imm32_r32( FPSCR_PR, R_ECX );
1785 XOR_r32_r32( R_EAX, R_EAX );
1786 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1787 store_fr( R_ECX, R_EAX, FRn );
1790 FLDI1 FRn {: /* IFF PR=0 */
1792 load_spreg( R_ECX, R_FPSCR );
1793 TEST_imm32_r32( FPSCR_PR, R_ECX );
1795 load_imm32(R_EAX, 0x3F800000);
1796 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1797 store_fr( R_ECX, R_EAX, FRn );
1803 load_spreg( R_ECX, R_FPSCR );
1804 load_spreg(R_EDX, REG_OFFSET(fr_bank));
1806 TEST_imm32_r32( FPSCR_PR, R_ECX );
1807 JNE_rel8(5, doubleprec);
1808 pop_fr( R_EDX, FRn );
1810 JMP_TARGET(doubleprec);
1811 pop_dr( R_EDX, FRn );
1816 load_spreg( R_ECX, R_FPSCR );
1817 load_fr_bank( R_EDX );
1818 TEST_imm32_r32( FPSCR_PR, R_ECX );
1819 JNE_rel8(5, doubleprec);
1820 push_fr( R_EDX, FRm );
1822 JMP_TARGET(doubleprec);
1823 push_dr( R_EDX, FRm );
1825 load_imm32( R_ECX, (uint32_t)&max_int );
1826 FILD_r32ind( R_ECX );
1828 JNA_rel8( 32, sat );
1829 load_imm32( R_ECX, (uint32_t)&min_int ); // 5
1830 FILD_r32ind( R_ECX ); // 2
1832 JAE_rel8( 21, sat2 ); // 2
1833 load_imm32( R_EAX, (uint32_t)&save_fcw );
1834 FNSTCW_r32ind( R_EAX );
1835 load_imm32( R_EDX, (uint32_t)&trunc_fcw );
1836 FLDCW_r32ind( R_EDX );
1837 FISTP_sh4r(R_FPUL); // 3
1838 FLDCW_r32ind( R_EAX );
1839 JMP_rel8( 9, end ); // 2
1843 MOV_r32ind_r32( R_ECX, R_ECX ); // 2
1844 store_spreg( R_ECX, R_FPUL );
1850 load_fr_bank( R_ECX );
1851 load_fr( R_ECX, R_EAX, FRm );
1852 store_spreg( R_EAX, R_FPUL );
1856 load_fr_bank( R_ECX );
1857 load_spreg( R_EAX, R_FPUL );
1858 store_fr( R_ECX, R_EAX, FRn );
1862 load_spreg( R_ECX, R_FPSCR );
1863 TEST_imm32_r32( FPSCR_PR, R_ECX );
1864 JE_rel8(9, end); // only when PR=1
1865 load_fr_bank( R_ECX );
1866 push_dr( R_ECX, FRm );
1872 load_spreg( R_ECX, R_FPSCR );
1873 TEST_imm32_r32( FPSCR_PR, R_ECX );
1874 JE_rel8(9, end); // only when PR=1
1875 load_fr_bank( R_ECX );
1877 pop_dr( R_ECX, FRn );
1881 /* Floating point instructions */
1884 load_spreg( R_ECX, R_FPSCR );
1885 load_fr_bank( R_EDX );
1886 TEST_imm32_r32( FPSCR_PR, R_ECX );
1887 JNE_rel8(10, doubleprec);
1888 push_fr(R_EDX, FRn); // 3
1890 pop_fr( R_EDX, FRn); //3
1891 JMP_rel8(8,end); // 2
1892 JMP_TARGET(doubleprec);
1893 push_dr(R_EDX, FRn);
1900 load_spreg( R_ECX, R_FPSCR );
1901 TEST_imm32_r32( FPSCR_PR, R_ECX );
1902 load_fr_bank( R_EDX );
1903 JNE_rel8(13,doubleprec);
1904 push_fr(R_EDX, FRm);
1905 push_fr(R_EDX, FRn);
1909 JMP_TARGET(doubleprec);
1910 push_dr(R_EDX, FRm);
1911 push_dr(R_EDX, FRn);
1918 load_spreg( R_ECX, R_FPSCR );
1919 TEST_imm32_r32( FPSCR_PR, R_ECX );
1920 load_fr_bank( R_EDX );
1921 JNE_rel8(13, doubleprec);
1922 push_fr(R_EDX, FRn);
1923 push_fr(R_EDX, FRm);
1927 JMP_TARGET(doubleprec);
1928 push_dr(R_EDX, FRn);
1929 push_dr(R_EDX, FRm);
1934 FMAC FR0, FRm, FRn {:
1936 load_spreg( R_ECX, R_FPSCR );
1937 load_spreg( R_EDX, REG_OFFSET(fr_bank));
1938 TEST_imm32_r32( FPSCR_PR, R_ECX );
1939 JNE_rel8(18, doubleprec);
1940 push_fr( R_EDX, 0 );
1941 push_fr( R_EDX, FRm );
1943 push_fr( R_EDX, FRn );
1945 pop_fr( R_EDX, FRn );
1947 JMP_TARGET(doubleprec);
1948 push_dr( R_EDX, 0 );
1949 push_dr( R_EDX, FRm );
1951 push_dr( R_EDX, FRn );
1953 pop_dr( R_EDX, FRn );
1959 load_spreg( R_ECX, R_FPSCR );
1960 TEST_imm32_r32( FPSCR_PR, R_ECX );
1961 load_fr_bank( R_EDX );
1962 JNE_rel8(13, doubleprec);
1963 push_fr(R_EDX, FRm);
1964 push_fr(R_EDX, FRn);
1968 JMP_TARGET(doubleprec);
1969 push_dr(R_EDX, FRm);
1970 push_dr(R_EDX, FRn);
1977 load_spreg( R_ECX, R_FPSCR );
1978 TEST_imm32_r32( FPSCR_PR, R_ECX );
1979 load_fr_bank( R_EDX );
1980 JNE_rel8(10, doubleprec);
1981 push_fr(R_EDX, FRn);
1985 JMP_TARGET(doubleprec);
1986 push_dr(R_EDX, FRn);
1993 load_spreg( R_ECX, R_FPSCR );
1994 TEST_imm32_r32( FPSCR_PR, R_ECX );
1995 load_fr_bank( R_EDX );
1996 JNE_rel8(12, end); // PR=0 only
1998 push_fr(R_EDX, FRn);
2006 load_spreg( R_ECX, R_FPSCR );
2007 TEST_imm32_r32( FPSCR_PR, R_ECX );
2008 load_fr_bank( R_EDX );
2009 JNE_rel8(10, doubleprec);
2010 push_fr(R_EDX, FRn);
2014 JMP_TARGET(doubleprec);
2015 push_dr(R_EDX, FRn);
2022 load_spreg( R_ECX, R_FPSCR );
2023 TEST_imm32_r32( FPSCR_PR, R_ECX );
2024 load_fr_bank( R_EDX );
2025 JNE_rel8(13, doubleprec);
2026 push_fr(R_EDX, FRn);
2027 push_fr(R_EDX, FRm);
2031 JMP_TARGET(doubleprec);
2032 push_dr(R_EDX, FRn);
2033 push_dr(R_EDX, FRm);
2041 load_spreg( R_ECX, R_FPSCR );
2042 TEST_imm32_r32( FPSCR_PR, R_ECX );
2043 load_fr_bank( R_EDX );
2044 JNE_rel8(8, doubleprec);
2045 push_fr(R_EDX, FRm);
2046 push_fr(R_EDX, FRn);
2048 JMP_TARGET(doubleprec);
2049 push_dr(R_EDX, FRm);
2050 push_dr(R_EDX, FRn);
2058 load_spreg( R_ECX, R_FPSCR );
2059 TEST_imm32_r32( FPSCR_PR, R_ECX );
2060 load_fr_bank( R_EDX );
2061 JNE_rel8(8, doubleprec);
2062 push_fr(R_EDX, FRm);
2063 push_fr(R_EDX, FRn);
2065 JMP_TARGET(doubleprec);
2066 push_dr(R_EDX, FRm);
2067 push_dr(R_EDX, FRn);
2076 load_spreg( R_ECX, R_FPSCR );
2077 TEST_imm32_r32( FPSCR_PR, R_ECX );
2078 JNE_rel8( 21, doubleprec );
2079 load_fr_bank( R_ECX );
2080 ADD_imm8s_r32( (FRn&0x0E)<<2, R_ECX );
2081 load_spreg( R_EDX, R_FPUL );
2082 call_func2( sh4_fsca, R_EDX, R_ECX );
2083 JMP_TARGET(doubleprec);
2087 load_spreg( R_ECX, R_FPSCR );
2088 TEST_imm32_r32( FPSCR_PR, R_ECX );
2089 JNE_rel8(44, doubleprec);
2091 load_fr_bank( R_ECX );
2092 push_fr( R_ECX, FVm<<2 );
2093 push_fr( R_ECX, FVn<<2 );
2095 push_fr( R_ECX, (FVm<<2)+1);
2096 push_fr( R_ECX, (FVn<<2)+1);
2099 push_fr( R_ECX, (FVm<<2)+2);
2100 push_fr( R_ECX, (FVn<<2)+2);
2103 push_fr( R_ECX, (FVm<<2)+3);
2104 push_fr( R_ECX, (FVn<<2)+3);
2107 pop_fr( R_ECX, (FVn<<2)+3);
2108 JMP_TARGET(doubleprec);
2112 load_spreg( R_ECX, R_FPSCR );
2113 TEST_imm32_r32( FPSCR_PR, R_ECX );
2114 JNE_rel8( 30, doubleprec );
2115 load_fr_bank( R_EDX ); // 3
2116 ADD_imm8s_r32( FVn<<4, R_EDX ); // 3
2117 load_xf_bank( R_ECX ); // 12
2118 call_func2( sh4_ftrv, R_EDX, R_ECX ); // 12
2119 JMP_TARGET(doubleprec);
2124 load_spreg( R_ECX, R_FPSCR );
2125 XOR_imm32_r32( FPSCR_FR, R_ECX );
2126 store_spreg( R_ECX, R_FPSCR );
2127 update_fr_bank( R_ECX );
2131 load_spreg( R_ECX, R_FPSCR );
2132 XOR_imm32_r32( FPSCR_SZ, R_ECX );
2133 store_spreg( R_ECX, R_FPSCR );
2136 /* Processor control instructions */
2138 if( sh4_x86.in_delay_slot ) {
2142 load_reg( R_EAX, Rm );
2143 call_func1( sh4_write_sr, R_EAX );
2144 sh4_x86.priv_checked = FALSE;
2145 sh4_x86.fpuen_checked = FALSE;
2149 load_reg( R_EAX, Rm );
2150 store_spreg( R_EAX, R_GBR );
2154 load_reg( R_EAX, Rm );
2155 store_spreg( R_EAX, R_VBR );
2159 load_reg( R_EAX, Rm );
2160 store_spreg( R_EAX, R_SSR );
2164 load_reg( R_EAX, Rm );
2165 store_spreg( R_EAX, R_SGR );
2169 load_reg( R_EAX, Rm );
2170 store_spreg( R_EAX, R_SPC );
2174 load_reg( R_EAX, Rm );
2175 store_spreg( R_EAX, R_DBR );
2179 load_reg( R_EAX, Rm );
2180 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
2183 load_reg( R_EAX, Rm );
2185 check_ralign32( R_EAX );
2186 MOV_r32_r32( R_EAX, R_ECX );
2187 ADD_imm8s_r32( 4, R_EAX );
2188 store_reg( R_EAX, Rm );
2189 MEM_READ_LONG( R_ECX, R_EAX );
2190 store_spreg( R_EAX, R_GBR );
2193 if( sh4_x86.in_delay_slot ) {
2197 check_priv_no_precheck();
2198 load_reg( R_EAX, Rm );
2199 check_ralign32( R_EAX );
2200 MOV_r32_r32( R_EAX, R_ECX );
2201 ADD_imm8s_r32( 4, R_EAX );
2202 store_reg( R_EAX, Rm );
2203 MEM_READ_LONG( R_ECX, R_EAX );
2204 call_func1( sh4_write_sr, R_EAX );
2205 sh4_x86.priv_checked = FALSE;
2206 sh4_x86.fpuen_checked = FALSE;
2211 check_priv_no_precheck();
2212 load_reg( R_EAX, Rm );
2213 check_ralign32( R_EAX );
2214 MOV_r32_r32( R_EAX, R_ECX );
2215 ADD_imm8s_r32( 4, R_EAX );
2216 store_reg( R_EAX, Rm );
2217 MEM_READ_LONG( R_ECX, R_EAX );
2218 store_spreg( R_EAX, R_VBR );
2222 check_priv_no_precheck();
2223 load_reg( R_EAX, Rm );
2224 check_ralign32( R_EAX );
2225 MOV_r32_r32( R_EAX, R_ECX );
2226 ADD_imm8s_r32( 4, R_EAX );
2227 store_reg( R_EAX, Rm );
2228 MEM_READ_LONG( R_ECX, R_EAX );
2229 store_spreg( R_EAX, R_SSR );
2233 check_priv_no_precheck();
2234 load_reg( R_EAX, Rm );
2235 check_ralign32( R_EAX );
2236 MOV_r32_r32( R_EAX, R_ECX );
2237 ADD_imm8s_r32( 4, R_EAX );
2238 store_reg( R_EAX, Rm );
2239 MEM_READ_LONG( R_ECX, R_EAX );
2240 store_spreg( R_EAX, R_SGR );
2244 check_priv_no_precheck();
2245 load_reg( R_EAX, Rm );
2246 check_ralign32( R_EAX );
2247 MOV_r32_r32( R_EAX, R_ECX );
2248 ADD_imm8s_r32( 4, R_EAX );
2249 store_reg( R_EAX, Rm );
2250 MEM_READ_LONG( R_ECX, R_EAX );
2251 store_spreg( R_EAX, R_SPC );
2255 check_priv_no_precheck();
2256 load_reg( R_EAX, Rm );
2257 check_ralign32( R_EAX );
2258 MOV_r32_r32( R_EAX, R_ECX );
2259 ADD_imm8s_r32( 4, R_EAX );
2260 store_reg( R_EAX, Rm );
2261 MEM_READ_LONG( R_ECX, R_EAX );
2262 store_spreg( R_EAX, R_DBR );
2264 LDC.L @Rm+, Rn_BANK {:
2266 check_priv_no_precheck();
2267 load_reg( R_EAX, Rm );
2268 check_ralign32( R_EAX );
2269 MOV_r32_r32( R_EAX, R_ECX );
2270 ADD_imm8s_r32( 4, R_EAX );
2271 store_reg( R_EAX, Rm );
2272 MEM_READ_LONG( R_ECX, R_EAX );
2273 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
2276 load_reg( R_EAX, Rm );
2277 store_spreg( R_EAX, R_FPSCR );
2278 update_fr_bank( R_EAX );
2280 LDS.L @Rm+, FPSCR {:
2281 load_reg( R_EAX, Rm );
2283 check_ralign32( R_EAX );
2284 MOV_r32_r32( R_EAX, R_ECX );
2285 ADD_imm8s_r32( 4, R_EAX );
2286 store_reg( R_EAX, Rm );
2287 MEM_READ_LONG( R_ECX, R_EAX );
2288 store_spreg( R_EAX, R_FPSCR );
2289 update_fr_bank( R_EAX );
2292 load_reg( R_EAX, Rm );
2293 store_spreg( R_EAX, R_FPUL );
2296 load_reg( R_EAX, Rm );
2298 check_ralign32( R_EAX );
2299 MOV_r32_r32( R_EAX, R_ECX );
2300 ADD_imm8s_r32( 4, R_EAX );
2301 store_reg( R_EAX, Rm );
2302 MEM_READ_LONG( R_ECX, R_EAX );
2303 store_spreg( R_EAX, R_FPUL );
2306 load_reg( R_EAX, Rm );
2307 store_spreg( R_EAX, R_MACH );
2310 load_reg( R_EAX, Rm );
2312 check_ralign32( R_EAX );
2313 MOV_r32_r32( R_EAX, R_ECX );
2314 ADD_imm8s_r32( 4, R_EAX );
2315 store_reg( R_EAX, Rm );
2316 MEM_READ_LONG( R_ECX, R_EAX );
2317 store_spreg( R_EAX, R_MACH );
2320 load_reg( R_EAX, Rm );
2321 store_spreg( R_EAX, R_MACL );
2324 load_reg( R_EAX, Rm );
2326 check_ralign32( R_EAX );
2327 MOV_r32_r32( R_EAX, R_ECX );
2328 ADD_imm8s_r32( 4, R_EAX );
2329 store_reg( R_EAX, Rm );
2330 MEM_READ_LONG( R_ECX, R_EAX );
2331 store_spreg( R_EAX, R_MACL );
2334 load_reg( R_EAX, Rm );
2335 store_spreg( R_EAX, R_PR );
2338 load_reg( R_EAX, Rm );
2340 check_ralign32( R_EAX );
2341 MOV_r32_r32( R_EAX, R_ECX );
2342 ADD_imm8s_r32( 4, R_EAX );
2343 store_reg( R_EAX, Rm );
2344 MEM_READ_LONG( R_ECX, R_EAX );
2345 store_spreg( R_EAX, R_PR );
2352 load_reg( R_EAX, Rn );
2354 AND_imm32_r32( 0xFC000000, R_EAX );
2355 CMP_imm32_r32( 0xE0000000, R_EAX );
2357 call_func0( sh4_flush_store_queue );
2359 ADD_imm8s_r32( 4, R_ESP );
2363 call_func0( sh4_sleep );
2364 sh4_x86.in_delay_slot = FALSE;
2369 call_func0(sh4_read_sr);
2370 store_reg( R_EAX, Rn );
2373 load_spreg( R_EAX, R_GBR );
2374 store_reg( R_EAX, Rn );
2378 load_spreg( R_EAX, R_VBR );
2379 store_reg( R_EAX, Rn );
2383 load_spreg( R_EAX, R_SSR );
2384 store_reg( R_EAX, Rn );
2388 load_spreg( R_EAX, R_SPC );
2389 store_reg( R_EAX, Rn );
2393 load_spreg( R_EAX, R_SGR );
2394 store_reg( R_EAX, Rn );
2398 load_spreg( R_EAX, R_DBR );
2399 store_reg( R_EAX, Rn );
2403 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2404 store_reg( R_EAX, Rn );
2408 check_priv_no_precheck();
2409 call_func0( sh4_read_sr );
2410 load_reg( R_ECX, Rn );
2411 check_walign32( R_ECX );
2412 ADD_imm8s_r32( -4, R_ECX );
2413 store_reg( R_ECX, Rn );
2414 MEM_WRITE_LONG( R_ECX, R_EAX );
2418 check_priv_no_precheck();
2419 load_reg( R_ECX, Rn );
2420 check_walign32( R_ECX );
2421 ADD_imm8s_r32( -4, R_ECX );
2422 store_reg( R_ECX, Rn );
2423 load_spreg( R_EAX, R_VBR );
2424 MEM_WRITE_LONG( R_ECX, R_EAX );
2428 check_priv_no_precheck();
2429 load_reg( R_ECX, Rn );
2430 check_walign32( R_ECX );
2431 ADD_imm8s_r32( -4, R_ECX );
2432 store_reg( R_ECX, Rn );
2433 load_spreg( R_EAX, R_SSR );
2434 MEM_WRITE_LONG( R_ECX, R_EAX );
2438 check_priv_no_precheck();
2439 load_reg( R_ECX, Rn );
2440 check_walign32( R_ECX );
2441 ADD_imm8s_r32( -4, R_ECX );
2442 store_reg( R_ECX, Rn );
2443 load_spreg( R_EAX, R_SPC );
2444 MEM_WRITE_LONG( R_ECX, R_EAX );
2448 check_priv_no_precheck();
2449 load_reg( R_ECX, Rn );
2450 check_walign32( R_ECX );
2451 ADD_imm8s_r32( -4, R_ECX );
2452 store_reg( R_ECX, Rn );
2453 load_spreg( R_EAX, R_SGR );
2454 MEM_WRITE_LONG( R_ECX, R_EAX );
2458 check_priv_no_precheck();
2459 load_reg( R_ECX, Rn );
2460 check_walign32( R_ECX );
2461 ADD_imm8s_r32( -4, R_ECX );
2462 store_reg( R_ECX, Rn );
2463 load_spreg( R_EAX, R_DBR );
2464 MEM_WRITE_LONG( R_ECX, R_EAX );
2466 STC.L Rm_BANK, @-Rn {:
2468 check_priv_no_precheck();
2469 load_reg( R_ECX, Rn );
2470 check_walign32( R_ECX );
2471 ADD_imm8s_r32( -4, R_ECX );
2472 store_reg( R_ECX, Rn );
2473 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2474 MEM_WRITE_LONG( R_ECX, R_EAX );
2477 load_reg( R_ECX, Rn );
2479 check_walign32( R_ECX );
2480 ADD_imm8s_r32( -4, R_ECX );
2481 store_reg( R_ECX, Rn );
2482 load_spreg( R_EAX, R_GBR );
2483 MEM_WRITE_LONG( R_ECX, R_EAX );
2486 load_spreg( R_EAX, R_FPSCR );
2487 store_reg( R_EAX, Rn );
2489 STS.L FPSCR, @-Rn {:
2490 load_reg( R_ECX, Rn );
2492 check_walign32( R_ECX );
2493 ADD_imm8s_r32( -4, R_ECX );
2494 store_reg( R_ECX, Rn );
2495 load_spreg( R_EAX, R_FPSCR );
2496 MEM_WRITE_LONG( R_ECX, R_EAX );
2499 load_spreg( R_EAX, R_FPUL );
2500 store_reg( R_EAX, Rn );
2503 load_reg( R_ECX, Rn );
2505 check_walign32( R_ECX );
2506 ADD_imm8s_r32( -4, R_ECX );
2507 store_reg( R_ECX, Rn );
2508 load_spreg( R_EAX, R_FPUL );
2509 MEM_WRITE_LONG( R_ECX, R_EAX );
2512 load_spreg( R_EAX, R_MACH );
2513 store_reg( R_EAX, Rn );
2516 load_reg( R_ECX, Rn );
2518 check_walign32( R_ECX );
2519 ADD_imm8s_r32( -4, R_ECX );
2520 store_reg( R_ECX, Rn );
2521 load_spreg( R_EAX, R_MACH );
2522 MEM_WRITE_LONG( R_ECX, R_EAX );
2525 load_spreg( R_EAX, R_MACL );
2526 store_reg( R_EAX, Rn );
2529 load_reg( R_ECX, Rn );
2531 check_walign32( R_ECX );
2532 ADD_imm8s_r32( -4, R_ECX );
2533 store_reg( R_ECX, Rn );
2534 load_spreg( R_EAX, R_MACL );
2535 MEM_WRITE_LONG( R_ECX, R_EAX );
2538 load_spreg( R_EAX, R_PR );
2539 store_reg( R_EAX, Rn );
2542 load_reg( R_ECX, Rn );
2544 check_walign32( R_ECX );
2545 ADD_imm8s_r32( -4, R_ECX );
2546 store_reg( R_ECX, Rn );
2547 load_spreg( R_EAX, R_PR );
2548 MEM_WRITE_LONG( R_ECX, R_EAX );
2551 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}
2553 sh4_x86.in_delay_slot = FALSE;
.