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.
29 #include "sh4/sh4core.h"
30 #include "sh4/sh4dasm.h"
31 #include "sh4/sh4trans.h"
32 #include "sh4/sh4stat.h"
33 #include "sh4/sh4mmio.h"
35 #include "xlat/xltcache.h"
36 #include "xlat/x86/x86op.h"
37 #include "x86dasm/x86dasm.h"
40 #define DEFAULT_BACKPATCH_SIZE 4096
42 /* Offset of a reg relative to the sh4r structure */
43 #define REG_OFFSET(reg) (((char *)&sh4r.reg) - ((char *)&sh4r) - 128)
45 #define R_T REG_OFFSET(t)
46 #define R_Q REG_OFFSET(q)
47 #define R_S REG_OFFSET(s)
48 #define R_M REG_OFFSET(m)
49 #define R_SR REG_OFFSET(sr)
50 #define R_GBR REG_OFFSET(gbr)
51 #define R_SSR REG_OFFSET(ssr)
52 #define R_SPC REG_OFFSET(spc)
53 #define R_VBR REG_OFFSET(vbr)
54 #define R_MACH REG_OFFSET(mac)+4
55 #define R_MACL REG_OFFSET(mac)
56 #define R_PC REG_OFFSET(pc)
57 #define R_NEW_PC REG_OFFSET(new_pc)
58 #define R_PR REG_OFFSET(pr)
59 #define R_SGR REG_OFFSET(sgr)
60 #define R_FPUL REG_OFFSET(fpul)
61 #define R_FPSCR REG_OFFSET(fpscr)
62 #define R_DBR REG_OFFSET(dbr)
63 #define R_R(rn) REG_OFFSET(r[rn])
64 #define R_FR(f) REG_OFFSET(fr[0][(f)^1])
65 #define R_XF(f) REG_OFFSET(fr[1][(f)^1])
66 #define R_DR(f) REG_OFFSET(fr[(f)&1][(f)&0x0E])
67 #define R_DRL(f) REG_OFFSET(fr[(f)&1][(f)|0x01])
68 #define R_DRH(f) REG_OFFSET(fr[(f)&1][(f)&0x0E])
74 #define SH4_MODE_UNKNOWN -1
76 struct backpatch_record {
77 uint32_t fixup_offset;
78 uint32_t fixup_icount;
83 * Struct to manage internal translation state. This state is not saved -
84 * it is only valid between calls to sh4_translate_begin_block() and
85 * sh4_translate_end_block()
87 struct sh4_x86_state {
90 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
91 gboolean branch_taken; /* true if we branched unconditionally */
92 gboolean double_prec; /* true if FPU is in double-precision mode */
93 gboolean double_size; /* true if FPU is in double-size mode */
94 gboolean sse3_enabled; /* true if host supports SSE3 instructions */
95 uint32_t block_start_pc;
96 uint32_t stack_posn; /* Trace stack height for alignment purposes */
97 uint32_t sh4_mode; /* Mirror of sh4r.xlat_sh4_mode */
101 gboolean tlb_on; /* True if tlb translation is active */
102 struct mem_region_fn **priv_address_space;
103 struct mem_region_fn **user_address_space;
105 /* Instrumentation */
106 xlat_block_begin_callback_t begin_callback;
107 xlat_block_end_callback_t end_callback;
109 gboolean profile_blocks;
111 /* Allocated memory for the (block-wide) back-patch list */
112 struct backpatch_record *backpatch_list;
113 uint32_t backpatch_posn;
114 uint32_t backpatch_size;
117 static struct sh4_x86_state sh4_x86;
119 static uint32_t max_int = 0x7FFFFFFF;
120 static uint32_t min_int = 0x80000000;
121 static uint32_t save_fcw; /* save value for fpu control word */
122 static uint32_t trunc_fcw = 0x0F7F; /* fcw value for truncation mode */
124 static void FASTCALL sh4_translate_get_code_and_backpatch( uint32_t pc );
126 static struct x86_symbol x86_symbol_table[] = {
127 { "sh4r+128", ((char *)&sh4r)+128 },
128 { "sh4_cpu_period", &sh4_cpu_period },
129 { "sh4_address_space", NULL },
130 { "sh4_user_address_space", NULL },
131 { "sh4_translate_breakpoint_hit", sh4_translate_breakpoint_hit },
132 { "sh4_translate_get_code_and_backpatch", sh4_translate_get_code_and_backpatch },
133 { "sh4_write_fpscr", sh4_write_fpscr },
134 { "sh4_write_sr", sh4_write_sr },
135 { "sh4_read_sr", sh4_read_sr },
136 { "sh4_raise_exception", sh4_raise_exception },
137 { "sh4_sleep", sh4_sleep },
138 { "sh4_fsca", sh4_fsca },
139 { "sh4_ftrv", sh4_ftrv },
140 { "sh4_switch_fr_banks", sh4_switch_fr_banks },
141 { "sh4_execute_instruction", sh4_execute_instruction },
142 { "signsat48", signsat48 },
143 { "xlat_get_code_by_vma", xlat_get_code_by_vma },
144 { "xlat_get_code", xlat_get_code }
148 gboolean is_sse3_supported()
152 __asm__ __volatile__(
153 "mov $0x01, %%eax\n\t"
154 "cpuid\n\t" : "=c" (features) : : "eax", "edx", "ebx");
155 return (features & 1) ? TRUE : FALSE;
158 void sh4_translate_set_address_space( struct mem_region_fn **priv, struct mem_region_fn **user )
160 sh4_x86.priv_address_space = priv;
161 sh4_x86.user_address_space = user;
162 x86_symbol_table[2].ptr = priv;
163 x86_symbol_table[3].ptr = user;
166 void sh4_translate_init(void)
168 sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
169 sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(struct backpatch_record);
170 sh4_x86.begin_callback = NULL;
171 sh4_x86.end_callback = NULL;
172 sh4_translate_set_address_space( sh4_address_space, sh4_user_address_space );
173 sh4_x86.fastmem = TRUE;
174 sh4_x86.profile_blocks = FALSE;
175 sh4_x86.sse3_enabled = is_sse3_supported();
177 x86_set_symtab( x86_symbol_table, sizeof(x86_symbol_table)/sizeof(struct x86_symbol) );
180 void sh4_translate_set_callbacks( xlat_block_begin_callback_t begin, xlat_block_end_callback_t end )
182 sh4_x86.begin_callback = begin;
183 sh4_x86.end_callback = end;
186 void sh4_translate_set_fastmem( gboolean flag )
188 sh4_x86.fastmem = flag;
191 void sh4_translate_set_profile_blocks( gboolean flag )
193 sh4_x86.profile_blocks = flag;
196 gboolean sh4_translate_get_profile_blocks()
198 return sh4_x86.profile_blocks;
202 * Disassemble the given translated code block, and it's source SH4 code block
203 * side-by-side. The current native pc will be marked if non-null.
205 void sh4_translate_disasm_block( FILE *out, void *code, sh4addr_t source_start, void *native_pc )
210 uintptr_t target_start = (uintptr_t)code, target_pc;
211 uintptr_t target_end = target_start + xlat_get_code_size(code);
212 uint32_t source_pc = source_start;
213 uint32_t source_end = source_pc;
214 xlat_recovery_record_t source_recov_table = XLAT_RECOVERY_TABLE(code);
215 xlat_recovery_record_t source_recov_end = source_recov_table + XLAT_BLOCK_FOR_CODE(code)->recover_table_size - 1;
217 for( target_pc = target_start; target_pc < target_end; ) {
218 uintptr_t pc2 = x86_disasm_instruction( target_pc, buf, sizeof(buf), op );
219 #if SIZEOF_VOID_P == 8
220 fprintf( out, "%c%016lx: %-30s %-40s", (target_pc == (uintptr_t)native_pc ? '*' : ' '),
221 target_pc, op, buf );
223 fprintf( out, "%c%08lx: %-30s %-40s", (target_pc == (uintptr_t)native_pc ? '*' : ' '),
224 target_pc, op, buf );
226 if( source_recov_table < source_recov_end &&
227 target_pc >= (target_start + source_recov_table->xlat_offset) ) {
228 source_recov_table++;
229 if( source_end < (source_start + (source_recov_table->sh4_icount)*2) )
230 source_end = source_start + (source_recov_table->sh4_icount)*2;
233 if( source_pc < source_end ) {
234 uint32_t source_pc2 = sh4_disasm_instruction( source_pc, buf, sizeof(buf), op );
235 fprintf( out, " %08X: %s %s\n", source_pc, op, buf );
236 source_pc = source_pc2;
238 fprintf( out, "\n" );
244 while( source_pc < source_end ) {
245 uint32_t source_pc2 = sh4_disasm_instruction( source_pc, buf, sizeof(buf), op );
246 fprintf( out, "%*c %08X: %s %s\n", 72,' ', source_pc, op, buf );
247 source_pc = source_pc2;
251 static void sh4_x86_add_backpatch( uint8_t *fixup_addr, uint32_t fixup_pc, uint32_t exc_code )
255 if( exc_code == -2 ) {
256 reloc_size = sizeof(void *);
259 if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
260 sh4_x86.backpatch_size <<= 1;
261 sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list,
262 sh4_x86.backpatch_size * sizeof(struct backpatch_record));
263 assert( sh4_x86.backpatch_list != NULL );
265 if( sh4_x86.in_delay_slot ) {
269 sh4_x86.backpatch_list[sh4_x86.backpatch_posn].fixup_offset =
270 (((uint8_t *)fixup_addr) - ((uint8_t *)xlat_current_block->code)) - reloc_size;
271 sh4_x86.backpatch_list[sh4_x86.backpatch_posn].fixup_icount = (fixup_pc - sh4_x86.block_start_pc)>>1;
272 sh4_x86.backpatch_list[sh4_x86.backpatch_posn].exc_code = exc_code;
273 sh4_x86.backpatch_posn++;
276 #define TSTATE_NONE -1
277 #define TSTATE_O X86_COND_O
278 #define TSTATE_C X86_COND_C
279 #define TSTATE_E X86_COND_E
280 #define TSTATE_NE X86_COND_NE
281 #define TSTATE_G X86_COND_G
282 #define TSTATE_GE X86_COND_GE
283 #define TSTATE_A X86_COND_A
284 #define TSTATE_AE X86_COND_AE
286 #define MARK_JMP8(x) uint8_t *_mark_jmp_##x = (xlat_output-1)
287 #define JMP_TARGET(x) *_mark_jmp_##x += (xlat_output - _mark_jmp_##x)
289 /* Convenience instructions */
290 #define LDC_t() CMPB_imms_rbpdisp(1,R_T); CMC()
291 #define SETE_t() SETCCB_cc_rbpdisp(X86_COND_E,R_T)
292 #define SETA_t() SETCCB_cc_rbpdisp(X86_COND_A,R_T)
293 #define SETAE_t() SETCCB_cc_rbpdisp(X86_COND_AE,R_T)
294 #define SETG_t() SETCCB_cc_rbpdisp(X86_COND_G,R_T)
295 #define SETGE_t() SETCCB_cc_rbpdisp(X86_COND_GE,R_T)
296 #define SETC_t() SETCCB_cc_rbpdisp(X86_COND_C,R_T)
297 #define SETO_t() SETCCB_cc_rbpdisp(X86_COND_O,R_T)
298 #define SETNE_t() SETCCB_cc_rbpdisp(X86_COND_NE,R_T)
299 #define SETC_r8(r1) SETCCB_cc_r8(X86_COND_C, r1)
300 #define JAE_label(label) JCC_cc_rel8(X86_COND_AE,-1); MARK_JMP8(label)
301 #define JBE_label(label) JCC_cc_rel8(X86_COND_BE,-1); MARK_JMP8(label)
302 #define JE_label(label) JCC_cc_rel8(X86_COND_E,-1); MARK_JMP8(label)
303 #define JGE_label(label) JCC_cc_rel8(X86_COND_GE,-1); MARK_JMP8(label)
304 #define JNA_label(label) JCC_cc_rel8(X86_COND_NA,-1); MARK_JMP8(label)
305 #define JNE_label(label) JCC_cc_rel8(X86_COND_NE,-1); MARK_JMP8(label)
306 #define JNO_label(label) JCC_cc_rel8(X86_COND_NO,-1); MARK_JMP8(label)
307 #define JS_label(label) JCC_cc_rel8(X86_COND_S,-1); MARK_JMP8(label)
308 #define JMP_label(label) JMP_rel8(-1); MARK_JMP8(label)
309 #define JNE_exc(exc) JCC_cc_rel32(X86_COND_NE,0); sh4_x86_add_backpatch(xlat_output, pc, exc)
311 /** Branch if T is set (either in the current cflags, or in sh4r.t) */
312 #define JT_label(label) if( sh4_x86.tstate == TSTATE_NONE ) { \
313 CMPL_imms_rbpdisp( 1, R_T ); sh4_x86.tstate = TSTATE_E; } \
314 JCC_cc_rel8(sh4_x86.tstate,-1); MARK_JMP8(label)
316 /** Branch if T is clear (either in the current cflags or in sh4r.t) */
317 #define JF_label(label) if( sh4_x86.tstate == TSTATE_NONE ) { \
318 CMPL_imms_rbpdisp( 1, R_T ); sh4_x86.tstate = TSTATE_E; } \
319 JCC_cc_rel8(sh4_x86.tstate^1, -1); MARK_JMP8(label)
322 #define load_reg(x86reg,sh4reg) MOVL_rbpdisp_r32( REG_OFFSET(r[sh4reg]), x86reg )
323 #define store_reg(x86reg,sh4reg) MOVL_r32_rbpdisp( x86reg, REG_OFFSET(r[sh4reg]) )
326 * Load an FR register (single-precision floating point) into an integer x86
327 * register (eg for register-to-register moves)
329 #define load_fr(reg,frm) MOVL_rbpdisp_r32( REG_OFFSET(fr[0][(frm)^1]), reg )
330 #define load_xf(reg,frm) MOVL_rbpdisp_r32( REG_OFFSET(fr[1][(frm)^1]), reg )
333 * Load the low half of a DR register (DR or XD) into an integer x86 register
335 #define load_dr0(reg,frm) MOVL_rbpdisp_r32( REG_OFFSET(fr[frm&1][frm|0x01]), reg )
336 #define load_dr1(reg,frm) MOVL_rbpdisp_r32( REG_OFFSET(fr[frm&1][frm&0x0E]), reg )
339 * Store an FR register (single-precision floating point) from an integer x86+
340 * register (eg for register-to-register moves)
342 #define store_fr(reg,frm) MOVL_r32_rbpdisp( reg, REG_OFFSET(fr[0][(frm)^1]) )
343 #define store_xf(reg,frm) MOVL_r32_rbpdisp( reg, REG_OFFSET(fr[1][(frm)^1]) )
345 #define store_dr0(reg,frm) MOVL_r32_rbpdisp( reg, REG_OFFSET(fr[frm&1][frm|0x01]) )
346 #define store_dr1(reg,frm) MOVL_r32_rbpdisp( reg, REG_OFFSET(fr[frm&1][frm&0x0E]) )
349 #define push_fpul() FLDF_rbpdisp(R_FPUL)
350 #define pop_fpul() FSTPF_rbpdisp(R_FPUL)
351 #define push_fr(frm) FLDF_rbpdisp( REG_OFFSET(fr[0][(frm)^1]) )
352 #define pop_fr(frm) FSTPF_rbpdisp( REG_OFFSET(fr[0][(frm)^1]) )
353 #define push_xf(frm) FLDF_rbpdisp( REG_OFFSET(fr[1][(frm)^1]) )
354 #define pop_xf(frm) FSTPF_rbpdisp( REG_OFFSET(fr[1][(frm)^1]) )
355 #define push_dr(frm) FLDD_rbpdisp( REG_OFFSET(fr[0][(frm)&0x0E]) )
356 #define pop_dr(frm) FSTPD_rbpdisp( REG_OFFSET(fr[0][(frm)&0x0E]) )
357 #define push_xdr(frm) FLDD_rbpdisp( REG_OFFSET(fr[1][(frm)&0x0E]) )
358 #define pop_xdr(frm) FSTPD_rbpdisp( REG_OFFSET(fr[1][(frm)&0x0E]) )
360 #ifdef ENABLE_SH4STATS
361 #define COUNT_INST(id) MOVL_imm32_r32( id, REG_EAX ); CALL1_ptr_r32(sh4_stats_add, REG_EAX); sh4_x86.tstate = TSTATE_NONE
363 #define COUNT_INST(id)
367 /* Exception checks - Note that all exception checks will clobber EAX */
369 #define check_priv( ) \
370 if( (sh4_x86.sh4_mode & SR_MD) == 0 ) { \
371 if( sh4_x86.in_delay_slot ) { \
372 exit_block_exc(EXC_SLOT_ILLEGAL, (pc-2), 4 ); \
374 exit_block_exc(EXC_ILLEGAL, pc, 2); \
376 sh4_x86.branch_taken = TRUE; \
377 sh4_x86.in_delay_slot = DELAY_NONE; \
381 #define check_fpuen( ) \
382 if( !sh4_x86.fpuen_checked ) {\
383 sh4_x86.fpuen_checked = TRUE;\
384 MOVL_rbpdisp_r32( R_SR, REG_EAX );\
385 ANDL_imms_r32( SR_FD, REG_EAX );\
386 if( sh4_x86.in_delay_slot ) {\
387 JNE_exc(EXC_SLOT_FPU_DISABLED);\
389 JNE_exc(EXC_FPU_DISABLED);\
391 sh4_x86.tstate = TSTATE_NONE; \
394 #define check_ralign16( x86reg ) \
395 TESTL_imms_r32( 0x00000001, x86reg ); \
396 JNE_exc(EXC_DATA_ADDR_READ)
398 #define check_walign16( x86reg ) \
399 TESTL_imms_r32( 0x00000001, x86reg ); \
400 JNE_exc(EXC_DATA_ADDR_WRITE);
402 #define check_ralign32( x86reg ) \
403 TESTL_imms_r32( 0x00000003, x86reg ); \
404 JNE_exc(EXC_DATA_ADDR_READ)
406 #define check_walign32( x86reg ) \
407 TESTL_imms_r32( 0x00000003, x86reg ); \
408 JNE_exc(EXC_DATA_ADDR_WRITE);
410 #define check_ralign64( x86reg ) \
411 TESTL_imms_r32( 0x00000007, x86reg ); \
412 JNE_exc(EXC_DATA_ADDR_READ)
414 #define check_walign64( x86reg ) \
415 TESTL_imms_r32( 0x00000007, x86reg ); \
416 JNE_exc(EXC_DATA_ADDR_WRITE);
418 #define address_space() ((sh4_x86.sh4_mode&SR_MD) ? (uintptr_t)sh4_x86.priv_address_space : (uintptr_t)sh4_x86.user_address_space)
421 /* Note: For SR.MD == 1 && MMUCR.AT == 0, there are no memory exceptions, so
422 * don't waste the cycles expecting them. Otherwise we need to save the exception pointer.
424 #ifdef HAVE_FRAME_ADDRESS
425 static void call_read_func(int addr_reg, int value_reg, int offset, int pc)
427 decode_address(address_space(), addr_reg);
428 if( !sh4_x86.tlb_on && (sh4_x86.sh4_mode & SR_MD) ) {
429 CALL1_r32disp_r32(REG_ECX, offset, addr_reg);
431 if( addr_reg != REG_ARG1 ) {
432 MOVL_r32_r32( addr_reg, REG_ARG1 );
434 MOVP_immptr_rptr( 0, REG_ARG2 );
435 sh4_x86_add_backpatch( xlat_output, pc, -2 );
436 CALL2_r32disp_r32_r32(REG_ECX, offset, REG_ARG1, REG_ARG2);
438 if( value_reg != REG_RESULT1 ) {
439 MOVL_r32_r32( REG_RESULT1, value_reg );
443 static void call_write_func(int addr_reg, int value_reg, int offset, int pc)
445 decode_address(address_space(), addr_reg);
446 if( !sh4_x86.tlb_on && (sh4_x86.sh4_mode & SR_MD) ) {
447 CALL2_r32disp_r32_r32(REG_ECX, offset, addr_reg, value_reg);
449 if( value_reg != REG_ARG2 ) {
450 MOVL_r32_r32( value_reg, REG_ARG2 );
452 if( addr_reg != REG_ARG1 ) {
453 MOVL_r32_r32( addr_reg, REG_ARG1 );
456 MOVP_immptr_rptr( 0, REG_ARG3 );
457 sh4_x86_add_backpatch( xlat_output, pc, -2 );
458 CALL3_r32disp_r32_r32_r32(REG_ECX, offset, REG_ARG1, REG_ARG2, REG_ARG3);
460 MOVL_imm32_rspdisp( 0, 0 );
461 sh4_x86_add_backpatch( xlat_output, pc, -2 );
462 CALL3_r32disp_r32_r32_r32(REG_ECX, offset, REG_ARG1, REG_ARG2, 0);
467 static void call_read_func(int addr_reg, int value_reg, int offset, int pc)
469 decode_address(address_space(), addr_reg);
470 CALL1_r32disp_r32(REG_ECX, offset, addr_reg);
471 if( value_reg != REG_RESULT1 ) {
472 MOVL_r32_r32( REG_RESULT1, value_reg );
476 static void call_write_func(int addr_reg, int value_reg, int offset, int pc)
478 decode_address(address_space(), addr_reg);
479 CALL2_r32disp_r32_r32(REG_ECX, offset, addr_reg, value_reg);
483 #define MEM_REGION_PTR(name) offsetof( struct mem_region_fn, name )
484 #define MEM_READ_BYTE( addr_reg, value_reg ) call_read_func(addr_reg, value_reg, MEM_REGION_PTR(read_byte), pc)
485 #define MEM_READ_BYTE_FOR_WRITE( addr_reg, value_reg ) call_read_func( addr_reg, value_reg, MEM_REGION_PTR(read_byte_for_write), pc)
486 #define MEM_READ_WORD( addr_reg, value_reg ) call_read_func(addr_reg, value_reg, MEM_REGION_PTR(read_word), pc)
487 #define MEM_READ_LONG( addr_reg, value_reg ) call_read_func(addr_reg, value_reg, MEM_REGION_PTR(read_long), pc)
488 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_write_func(addr_reg, value_reg, MEM_REGION_PTR(write_byte), pc)
489 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_write_func(addr_reg, value_reg, MEM_REGION_PTR(write_word), pc)
490 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_write_func(addr_reg, value_reg, MEM_REGION_PTR(write_long), pc)
491 #define MEM_PREFETCH( addr_reg ) call_read_func(addr_reg, REG_RESULT1, MEM_REGION_PTR(prefetch), pc)
493 #define SLOTILLEGAL() exit_block_exc(EXC_SLOT_ILLEGAL, pc-2, 4); sh4_x86.in_delay_slot = DELAY_NONE; return 2;
495 /** Offset of xlat_sh4_mode field relative to the code pointer */
496 #define XLAT_SH4_MODE_CODE_OFFSET (int32_t)(offsetof(struct xlat_cache_block, xlat_sh4_mode) - offsetof(struct xlat_cache_block,code) )
497 #define XLAT_CHAIN_CODE_OFFSET (int32_t)(offsetof(struct xlat_cache_block, chain) - offsetof(struct xlat_cache_block,code) )
498 #define XLAT_ACTIVE_CODE_OFFSET (int32_t)(offsetof(struct xlat_cache_block, active) - offsetof(struct xlat_cache_block,code) )
500 void sh4_translate_begin_block( sh4addr_t pc )
502 sh4_x86.code = xlat_output;
503 sh4_x86.in_delay_slot = FALSE;
504 sh4_x86.fpuen_checked = FALSE;
505 sh4_x86.branch_taken = FALSE;
506 sh4_x86.backpatch_posn = 0;
507 sh4_x86.block_start_pc = pc;
508 sh4_x86.tlb_on = IS_TLB_ENABLED();
509 sh4_x86.tstate = TSTATE_NONE;
510 sh4_x86.double_prec = sh4r.fpscr & FPSCR_PR;
511 sh4_x86.double_size = sh4r.fpscr & FPSCR_SZ;
512 sh4_x86.sh4_mode = sh4r.xlat_sh4_mode;
514 if( sh4_x86.begin_callback ) {
515 CALL_ptr( sh4_x86.begin_callback );
517 if( sh4_x86.profile_blocks ) {
518 MOVP_immptr_rptr( sh4_x86.code + XLAT_ACTIVE_CODE_OFFSET, REG_EAX );
519 ADDL_imms_r32disp( 1, REG_EAX, 0 );
524 uint32_t sh4_translate_end_block_size()
526 uint32_t epilogue_size = EPILOGUE_SIZE;
527 if( sh4_x86.end_callback ) {
528 epilogue_size += (CALL1_PTR_MIN_SIZE - 1);
530 if( sh4_x86.backpatch_posn <= 3 ) {
531 epilogue_size += (sh4_x86.backpatch_posn*(12+CALL1_PTR_MIN_SIZE));
533 epilogue_size += (3*(12+CALL1_PTR_MIN_SIZE)) + (sh4_x86.backpatch_posn-3)*(15+CALL1_PTR_MIN_SIZE);
535 return epilogue_size;
540 * Embed a breakpoint into the generated code
542 void sh4_translate_emit_breakpoint( sh4vma_t pc )
544 MOVL_imm32_r32( pc, REG_EAX );
545 CALL1_ptr_r32( sh4_translate_breakpoint_hit, REG_EAX );
546 sh4_x86.tstate = TSTATE_NONE;
550 #define UNTRANSLATABLE(pc) !IS_IN_ICACHE(pc)
553 * Test if the loaded target code pointer in %eax is valid, and if so jump
554 * directly into it, bypassing the normal exit.
556 static void jump_next_block()
558 uint8_t *ptr = xlat_output;
559 TESTP_rptr_rptr(REG_EAX, REG_EAX);
561 if( sh4_x86.sh4_mode == SH4_MODE_UNKNOWN ) {
562 /* sr/fpscr was changed, possibly updated xlat_sh4_mode, so reload it */
563 MOVL_rbpdisp_r32( REG_OFFSET(xlat_sh4_mode), REG_ECX );
564 CMPL_r32_r32disp( REG_ECX, REG_EAX, XLAT_SH4_MODE_CODE_OFFSET );
566 CMPL_imms_r32disp( sh4_x86.sh4_mode, REG_EAX, XLAT_SH4_MODE_CODE_OFFSET );
568 JNE_label(wrongmode);
569 LEAP_rptrdisp_rptr(REG_EAX, PROLOGUE_SIZE,REG_EAX);
570 if( sh4_x86.end_callback ) {
571 /* Note this does leave the stack out of alignment, but doesn't matter
572 * for what we're currently using it for.
575 MOVP_immptr_rptr(sh4_x86.end_callback, REG_ECX);
580 JMP_TARGET(wrongmode);
581 MOVP_rptrdisp_rptr( REG_EAX, XLAT_CHAIN_CODE_OFFSET, REG_EAX );
582 int rel = ptr - xlat_output;
590 static void FASTCALL sh4_translate_get_code_and_backpatch( uint32_t pc )
592 uint8_t *target = (uint8_t *)xlat_get_code_by_vma(pc);
593 while( target != NULL && sh4r.xlat_sh4_mode != XLAT_BLOCK_MODE(target) ) {
594 target = XLAT_BLOCK_CHAIN(target);
596 if( target == NULL ) {
597 target = sh4_translate_basic_block( pc );
599 uint8_t *backpatch = ((uint8_t *)__builtin_return_address(0)) - (CALL1_PTR_MIN_SIZE);
601 *(uint32_t *)(backpatch+1) = (uint32_t)(target-backpatch)+PROLOGUE_SIZE-5;
602 *(void **)(backpatch+5) = XLAT_BLOCK_FOR_CODE(target)->use_list;
603 XLAT_BLOCK_FOR_CODE(target)->use_list = backpatch;
605 uint8_t **retptr = ((uint8_t **)__builtin_frame_address(0))+1;
606 assert( *retptr == ((uint8_t *)__builtin_return_address(0)) );
610 static void emit_translate_and_backpatch()
612 /* NB: this is either 7 bytes (i386) or 12 bytes (x86-64) */
613 CALL1_ptr_r32(sh4_translate_get_code_and_backpatch, REG_ARG1);
615 /* When patched, the jmp instruction will be 5 bytes (either platform) -
616 * we need to reserve sizeof(void*) bytes for the use-list
619 if( sizeof(void*) == 8 ) {
627 * If we're jumping to a fixed address (or at least fixed relative to the
628 * current PC, then we can do a direct branch. REG_ARG1 should contain
629 * the PC at this point.
631 static void jump_next_block_fixed_pc( sh4addr_t pc )
633 if( IS_IN_ICACHE(pc) ) {
634 if( sh4_x86.sh4_mode != SH4_MODE_UNKNOWN && sh4_x86.end_callback == NULL ) {
635 /* Fixed address, in cache, and fixed SH4 mode - generate a call to the
636 * fetch-and-backpatch routine, which will replace the call with a branch */
637 emit_translate_and_backpatch();
640 MOVP_moffptr_rax( xlat_get_lut_entry(GET_ICACHE_PHYS(pc)) );
641 ANDP_imms_rptr( -4, REG_EAX );
643 } else if( sh4_x86.tlb_on ) {
644 CALL1_ptr_r32(xlat_get_code_by_vma, REG_ARG1);
646 CALL1_ptr_r32(xlat_get_code, REG_ARG1);
653 void sh4_translate_unlink_block( void *use_list )
655 uint8_t *tmp = xlat_output; /* In case something is active, which should never happen */
656 void *next = use_list;
657 while( next != NULL ) {
658 xlat_output = (uint8_t *)next;
659 next = *(void **)(xlat_output+5);
660 emit_translate_and_backpatch();
667 static void exit_block()
670 if( sh4_x86.end_callback ) {
671 MOVP_immptr_rptr(sh4_x86.end_callback, REG_ECX);
679 * Exit the block with sh4r.pc already written
681 void exit_block_pcset( sh4addr_t pc )
683 MOVL_imm32_r32( ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
684 ADDL_rbpdisp_r32( REG_OFFSET(slice_cycle), REG_ECX );
685 MOVL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
686 CMPL_r32_rbpdisp( REG_ECX, REG_OFFSET(event_pending) );
688 MOVL_rbpdisp_r32( R_PC, REG_ARG1 );
689 if( sh4_x86.tlb_on ) {
690 CALL1_ptr_r32(xlat_get_code_by_vma,REG_ARG1);
692 CALL1_ptr_r32(xlat_get_code,REG_ARG1);
696 JMP_TARGET(exitloop);
701 * Exit the block with sh4r.new_pc written with the target pc
703 void exit_block_newpcset( sh4addr_t pc )
705 MOVL_imm32_r32( ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
706 ADDL_rbpdisp_r32( REG_OFFSET(slice_cycle), REG_ECX );
707 MOVL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
708 MOVL_rbpdisp_r32( R_NEW_PC, REG_ARG1 );
709 MOVL_r32_rbpdisp( REG_ARG1, R_PC );
710 CMPL_r32_rbpdisp( REG_ECX, REG_OFFSET(event_pending) );
712 if( sh4_x86.tlb_on ) {
713 CALL1_ptr_r32(xlat_get_code_by_vma,REG_ARG1);
715 CALL1_ptr_r32(xlat_get_code,REG_ARG1);
719 JMP_TARGET(exitloop);
725 * Exit the block to an absolute PC
727 void exit_block_abs( sh4addr_t pc, sh4addr_t endpc )
729 MOVL_imm32_r32( ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
730 ADDL_rbpdisp_r32( REG_OFFSET(slice_cycle), REG_ECX );
731 MOVL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
733 MOVL_imm32_r32( pc, REG_ARG1 );
734 MOVL_r32_rbpdisp( REG_ARG1, R_PC );
735 CMPL_r32_rbpdisp( REG_ECX, REG_OFFSET(event_pending) );
737 jump_next_block_fixed_pc(pc);
738 JMP_TARGET(exitloop);
743 * Exit the block to a relative PC
745 void exit_block_rel( sh4addr_t pc, sh4addr_t endpc )
747 MOVL_imm32_r32( ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
748 ADDL_rbpdisp_r32( REG_OFFSET(slice_cycle), REG_ECX );
749 MOVL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
751 if( pc == sh4_x86.block_start_pc && sh4_x86.sh4_mode == sh4r.xlat_sh4_mode ) {
752 /* Special case for tight loops - the PC doesn't change, and
753 * we already know the target address. Just check events pending before
756 CMPL_r32_rbpdisp( REG_ECX, REG_OFFSET(event_pending) );
757 uint32_t backdisp = ((uintptr_t)(sh4_x86.code - xlat_output)) + PROLOGUE_SIZE;
758 JCC_cc_prerel(X86_COND_A, backdisp);
760 MOVL_imm32_r32( pc - sh4_x86.block_start_pc, REG_ARG1 );
761 ADDL_rbpdisp_r32( R_PC, REG_ARG1 );
762 MOVL_r32_rbpdisp( REG_ARG1, R_PC );
763 CMPL_r32_rbpdisp( REG_ECX, REG_OFFSET(event_pending) );
764 JBE_label(exitloop2);
766 jump_next_block_fixed_pc(pc);
767 JMP_TARGET(exitloop2);
773 * Exit unconditionally with a general exception
775 void exit_block_exc( int code, sh4addr_t pc, int inst_adjust )
777 MOVL_imm32_r32( pc - sh4_x86.block_start_pc, REG_ECX );
778 ADDL_r32_rbpdisp( REG_ECX, R_PC );
779 MOVL_imm32_r32( ((pc - sh4_x86.block_start_pc + inst_adjust)>>1)*sh4_cpu_period, REG_ECX );
780 ADDL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
781 MOVL_imm32_r32( code, REG_ARG1 );
782 CALL1_ptr_r32( sh4_raise_exception, REG_ARG1 );
787 * Embed a call to sh4_execute_instruction for situations that we
788 * can't translate (just page-crossing delay slots at the moment).
789 * Caller is responsible for setting new_pc before calling this function.
793 * Set sh4r.in_delay_slot = sh4_x86.in_delay_slot
794 * Update slice_cycle for endpc+2 (single step doesn't update slice_cycle)
795 * Call sh4_execute_instruction
796 * Call xlat_get_code_by_vma / xlat_get_code as for normal exit
798 void exit_block_emu( sh4vma_t endpc )
800 MOVL_imm32_r32( endpc - sh4_x86.block_start_pc, REG_ECX ); // 5
801 ADDL_r32_rbpdisp( REG_ECX, R_PC );
803 MOVL_imm32_r32( (((endpc - sh4_x86.block_start_pc)>>1)+1)*sh4_cpu_period, REG_ECX ); // 5
804 ADDL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) ); // 6
805 MOVL_imm32_r32( sh4_x86.in_delay_slot ? 1 : 0, REG_ECX );
806 MOVL_r32_rbpdisp( REG_ECX, REG_OFFSET(in_delay_slot) );
808 CALL_ptr( sh4_execute_instruction );
813 * Write the block trailer (exception handling block)
815 void sh4_translate_end_block( sh4addr_t pc ) {
816 if( sh4_x86.branch_taken == FALSE ) {
817 // Didn't exit unconditionally already, so write the termination here
818 exit_block_rel( pc, pc );
820 if( sh4_x86.backpatch_posn != 0 ) {
822 // Exception raised - cleanup and exit
823 uint8_t *end_ptr = xlat_output;
824 MOVL_r32_r32( REG_EDX, REG_ECX );
825 ADDL_r32_r32( REG_EDX, REG_ECX );
826 ADDL_r32_rbpdisp( REG_ECX, R_SPC );
827 MOVL_moffptr_eax( &sh4_cpu_period );
828 INC_r32( REG_EDX ); /* Add 1 for the aborting instruction itself */
830 ADDL_r32_rbpdisp( REG_EAX, REG_OFFSET(slice_cycle) );
833 for( i=0; i< sh4_x86.backpatch_posn; i++ ) {
834 uint32_t *fixup_addr = (uint32_t *)&xlat_current_block->code[sh4_x86.backpatch_list[i].fixup_offset];
835 if( sh4_x86.backpatch_list[i].exc_code < 0 ) {
836 if( sh4_x86.backpatch_list[i].exc_code == -2 ) {
837 *((uintptr_t *)fixup_addr) = (uintptr_t)xlat_output;
839 *fixup_addr += xlat_output - (uint8_t *)&xlat_current_block->code[sh4_x86.backpatch_list[i].fixup_offset] - 4;
841 MOVL_imm32_r32( sh4_x86.backpatch_list[i].fixup_icount, REG_EDX );
842 int rel = end_ptr - xlat_output;
845 *fixup_addr += xlat_output - (uint8_t *)&xlat_current_block->code[sh4_x86.backpatch_list[i].fixup_offset] - 4;
846 MOVL_imm32_r32( sh4_x86.backpatch_list[i].exc_code, REG_ARG1 );
847 CALL1_ptr_r32( sh4_raise_exception, REG_ARG1 );
848 MOVL_imm32_r32( sh4_x86.backpatch_list[i].fixup_icount, REG_EDX );
849 int rel = end_ptr - xlat_output;
857 * Translate a single instruction. Delayed branches are handled specially
858 * by translating both branch and delayed instruction as a single unit (as
860 * The instruction MUST be in the icache (assert check)
862 * @return true if the instruction marks the end of a basic block
865 uint32_t sh4_translate_instruction( sh4vma_t pc )
868 /* Read instruction from icache */
869 assert( IS_IN_ICACHE(pc) );
870 ir = *(uint16_t *)GET_ICACHE_PTR(pc);
872 if( !sh4_x86.in_delay_slot ) {
873 sh4_translate_add_recovery( (pc - sh4_x86.block_start_pc)>>1 );
876 /* check for breakpoints at this pc */
877 for( int i=0; i<sh4_breakpoint_count; i++ ) {
878 if( sh4_breakpoints[i].address == pc ) {
879 sh4_translate_emit_breakpoint(pc);
887 load_reg( REG_EAX, Rm );
888 load_reg( REG_ECX, Rn );
889 ADDL_r32_r32( REG_EAX, REG_ECX );
890 store_reg( REG_ECX, Rn );
891 sh4_x86.tstate = TSTATE_NONE;
895 ADDL_imms_rbpdisp( imm, REG_OFFSET(r[Rn]) );
896 sh4_x86.tstate = TSTATE_NONE;
900 if( sh4_x86.tstate != TSTATE_C ) {
903 load_reg( REG_EAX, Rm );
904 load_reg( REG_ECX, Rn );
905 ADCL_r32_r32( REG_EAX, REG_ECX );
906 store_reg( REG_ECX, Rn );
908 sh4_x86.tstate = TSTATE_C;
912 load_reg( REG_EAX, Rm );
913 load_reg( REG_ECX, Rn );
914 ADDL_r32_r32( REG_EAX, REG_ECX );
915 store_reg( REG_ECX, Rn );
917 sh4_x86.tstate = TSTATE_O;
921 load_reg( REG_EAX, Rm );
922 load_reg( REG_ECX, Rn );
923 ANDL_r32_r32( REG_EAX, REG_ECX );
924 store_reg( REG_ECX, Rn );
925 sh4_x86.tstate = TSTATE_NONE;
929 load_reg( REG_EAX, 0 );
930 ANDL_imms_r32(imm, REG_EAX);
931 store_reg( REG_EAX, 0 );
932 sh4_x86.tstate = TSTATE_NONE;
934 AND.B #imm, @(R0, GBR) {:
936 load_reg( REG_EAX, 0 );
937 ADDL_rbpdisp_r32( R_GBR, REG_EAX );
938 MOVL_r32_rspdisp(REG_EAX, 0);
939 MEM_READ_BYTE_FOR_WRITE( REG_EAX, REG_EDX );
940 MOVL_rspdisp_r32(0, REG_EAX);
941 ANDL_imms_r32(imm, REG_EDX );
942 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
943 sh4_x86.tstate = TSTATE_NONE;
947 load_reg( REG_EAX, Rm );
948 load_reg( REG_ECX, Rn );
949 CMPL_r32_r32( REG_EAX, REG_ECX );
951 sh4_x86.tstate = TSTATE_E;
954 COUNT_INST(I_CMPEQI);
955 load_reg( REG_EAX, 0 );
956 CMPL_imms_r32(imm, REG_EAX);
958 sh4_x86.tstate = TSTATE_E;
962 load_reg( REG_EAX, Rm );
963 load_reg( REG_ECX, Rn );
964 CMPL_r32_r32( REG_EAX, REG_ECX );
966 sh4_x86.tstate = TSTATE_GE;
970 load_reg( REG_EAX, Rm );
971 load_reg( REG_ECX, Rn );
972 CMPL_r32_r32( REG_EAX, REG_ECX );
974 sh4_x86.tstate = TSTATE_G;
978 load_reg( REG_EAX, Rm );
979 load_reg( REG_ECX, Rn );
980 CMPL_r32_r32( REG_EAX, REG_ECX );
982 sh4_x86.tstate = TSTATE_A;
986 load_reg( REG_EAX, Rm );
987 load_reg( REG_ECX, Rn );
988 CMPL_r32_r32( REG_EAX, REG_ECX );
990 sh4_x86.tstate = TSTATE_AE;
994 load_reg( REG_EAX, Rn );
995 CMPL_imms_r32( 0, REG_EAX );
997 sh4_x86.tstate = TSTATE_G;
1000 COUNT_INST(I_CMPPZ);
1001 load_reg( REG_EAX, Rn );
1002 CMPL_imms_r32( 0, REG_EAX );
1004 sh4_x86.tstate = TSTATE_GE;
1007 COUNT_INST(I_CMPSTR);
1008 load_reg( REG_EAX, Rm );
1009 load_reg( REG_ECX, Rn );
1010 XORL_r32_r32( REG_ECX, REG_EAX );
1011 TESTB_r8_r8( REG_AL, REG_AL );
1013 TESTB_r8_r8( REG_AH, REG_AH );
1015 SHRL_imm_r32( 16, REG_EAX );
1016 TESTB_r8_r8( REG_AL, REG_AL );
1018 TESTB_r8_r8( REG_AH, REG_AH );
1019 JMP_TARGET(target1);
1020 JMP_TARGET(target2);
1021 JMP_TARGET(target3);
1023 sh4_x86.tstate = TSTATE_E;
1026 COUNT_INST(I_DIV0S);
1027 load_reg( REG_EAX, Rm );
1028 load_reg( REG_ECX, Rn );
1029 SHRL_imm_r32( 31, REG_EAX );
1030 SHRL_imm_r32( 31, REG_ECX );
1031 MOVL_r32_rbpdisp( REG_EAX, R_M );
1032 MOVL_r32_rbpdisp( REG_ECX, R_Q );
1033 CMPL_r32_r32( REG_EAX, REG_ECX );
1035 sh4_x86.tstate = TSTATE_NE;
1038 COUNT_INST(I_DIV0U);
1039 XORL_r32_r32( REG_EAX, REG_EAX );
1040 MOVL_r32_rbpdisp( REG_EAX, R_Q );
1041 MOVL_r32_rbpdisp( REG_EAX, R_M );
1042 MOVL_r32_rbpdisp( REG_EAX, R_T );
1043 sh4_x86.tstate = TSTATE_C; // works for DIV1
1047 MOVL_rbpdisp_r32( R_M, REG_ECX );
1048 load_reg( REG_EAX, Rn );
1049 if( sh4_x86.tstate != TSTATE_C ) {
1052 RCLL_imm_r32( 1, REG_EAX );
1053 SETC_r8( REG_DL ); // Q'
1054 CMPL_rbpdisp_r32( R_Q, REG_ECX );
1056 ADDL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
1058 JMP_TARGET(mqequal);
1059 SUBL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
1061 store_reg( REG_EAX, Rn ); // Done with Rn now
1062 SETC_r8(REG_AL); // tmp1
1063 XORB_r8_r8( REG_DL, REG_AL ); // Q' = Q ^ tmp1
1064 XORB_r8_r8( REG_AL, REG_CL ); // Q'' = Q' ^ M
1065 MOVL_r32_rbpdisp( REG_ECX, R_Q );
1066 XORL_imms_r32( 1, REG_AL ); // T = !Q'
1067 MOVZXL_r8_r32( REG_AL, REG_EAX );
1068 MOVL_r32_rbpdisp( REG_EAX, R_T );
1069 sh4_x86.tstate = TSTATE_NONE;
1072 COUNT_INST(I_DMULS);
1073 load_reg( REG_EAX, Rm );
1074 load_reg( REG_ECX, Rn );
1076 MOVL_r32_rbpdisp( REG_EDX, R_MACH );
1077 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
1078 sh4_x86.tstate = TSTATE_NONE;
1081 COUNT_INST(I_DMULU);
1082 load_reg( REG_EAX, Rm );
1083 load_reg( REG_ECX, Rn );
1085 MOVL_r32_rbpdisp( REG_EDX, R_MACH );
1086 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
1087 sh4_x86.tstate = TSTATE_NONE;
1091 load_reg( REG_EAX, Rn );
1092 ADDL_imms_r32( -1, REG_EAX );
1093 store_reg( REG_EAX, Rn );
1095 sh4_x86.tstate = TSTATE_E;
1098 COUNT_INST(I_EXTSB);
1099 load_reg( REG_EAX, Rm );
1100 MOVSXL_r8_r32( REG_EAX, REG_EAX );
1101 store_reg( REG_EAX, Rn );
1104 COUNT_INST(I_EXTSW);
1105 load_reg( REG_EAX, Rm );
1106 MOVSXL_r16_r32( REG_EAX, REG_EAX );
1107 store_reg( REG_EAX, Rn );
1110 COUNT_INST(I_EXTUB);
1111 load_reg( REG_EAX, Rm );
1112 MOVZXL_r8_r32( REG_EAX, REG_EAX );
1113 store_reg( REG_EAX, Rn );
1116 COUNT_INST(I_EXTUW);
1117 load_reg( REG_EAX, Rm );
1118 MOVZXL_r16_r32( REG_EAX, REG_EAX );
1119 store_reg( REG_EAX, Rn );
1124 load_reg( REG_EAX, Rm );
1125 check_ralign32( REG_EAX );
1126 MEM_READ_LONG( REG_EAX, REG_EAX );
1127 MOVL_r32_rspdisp(REG_EAX, 0);
1128 load_reg( REG_EAX, Rm );
1129 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
1130 MEM_READ_LONG( REG_EAX, REG_EAX );
1131 ADDL_imms_rbpdisp( 8, REG_OFFSET(r[Rn]) );
1133 load_reg( REG_EAX, Rm );
1134 check_ralign32( REG_EAX );
1135 MEM_READ_LONG( REG_EAX, REG_EAX );
1136 MOVL_r32_rspdisp( REG_EAX, 0 );
1137 load_reg( REG_EAX, Rn );
1138 check_ralign32( REG_EAX );
1139 MEM_READ_LONG( REG_EAX, REG_EAX );
1140 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rn]) );
1141 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
1145 ADDL_r32_rbpdisp( REG_EAX, R_MACL );
1146 ADCL_r32_rbpdisp( REG_EDX, R_MACH );
1148 MOVL_rbpdisp_r32( R_S, REG_ECX );
1149 TESTL_r32_r32(REG_ECX, REG_ECX);
1151 CALL_ptr( signsat48 );
1152 JMP_TARGET( nosat );
1153 sh4_x86.tstate = TSTATE_NONE;
1158 load_reg( REG_EAX, Rm );
1159 check_ralign16( REG_EAX );
1160 MEM_READ_WORD( REG_EAX, REG_EAX );
1161 MOVL_r32_rspdisp( REG_EAX, 0 );
1162 load_reg( REG_EAX, Rm );
1163 LEAL_r32disp_r32( REG_EAX, 2, REG_EAX );
1164 MEM_READ_WORD( REG_EAX, REG_EAX );
1165 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rn]) );
1166 // Note translate twice in case of page boundaries. Maybe worth
1167 // adding a page-boundary check to skip the second translation
1169 load_reg( REG_EAX, Rn );
1170 check_ralign16( REG_EAX );
1171 MEM_READ_WORD( REG_EAX, REG_EAX );
1172 MOVL_r32_rspdisp( REG_EAX, 0 );
1173 load_reg( REG_EAX, Rm );
1174 check_ralign16( REG_EAX );
1175 MEM_READ_WORD( REG_EAX, REG_EAX );
1176 ADDL_imms_rbpdisp( 2, REG_OFFSET(r[Rn]) );
1177 ADDL_imms_rbpdisp( 2, REG_OFFSET(r[Rm]) );
1180 MOVL_rbpdisp_r32( R_S, REG_ECX );
1181 TESTL_r32_r32( REG_ECX, REG_ECX );
1184 ADDL_r32_rbpdisp( REG_EAX, R_MACL ); // 6
1185 JNO_label( end ); // 2
1186 MOVL_imm32_r32( 1, REG_EDX ); // 5
1187 MOVL_r32_rbpdisp( REG_EDX, R_MACH ); // 6
1188 JS_label( positive ); // 2
1189 MOVL_imm32_r32( 0x80000000, REG_EAX );// 5
1190 MOVL_r32_rbpdisp( REG_EAX, R_MACL ); // 6
1191 JMP_label(end2); // 2
1193 JMP_TARGET(positive);
1194 MOVL_imm32_r32( 0x7FFFFFFF, REG_EAX );// 5
1195 MOVL_r32_rbpdisp( REG_EAX, R_MACL ); // 6
1196 JMP_label(end3); // 2
1199 ADDL_r32_rbpdisp( REG_EAX, R_MACL ); // 6
1200 ADCL_r32_rbpdisp( REG_EDX, R_MACH ); // 6
1204 sh4_x86.tstate = TSTATE_NONE;
1208 MOVL_rbpdisp_r32( R_T, REG_EAX );
1209 store_reg( REG_EAX, Rn );
1213 load_reg( REG_EAX, Rm );
1214 load_reg( REG_ECX, Rn );
1215 MULL_r32( REG_ECX );
1216 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
1217 sh4_x86.tstate = TSTATE_NONE;
1220 COUNT_INST(I_MULSW);
1221 MOVSXL_rbpdisp16_r32( R_R(Rm), REG_EAX );
1222 MOVSXL_rbpdisp16_r32( R_R(Rn), REG_ECX );
1223 MULL_r32( REG_ECX );
1224 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
1225 sh4_x86.tstate = TSTATE_NONE;
1228 COUNT_INST(I_MULUW);
1229 MOVZXL_rbpdisp16_r32( R_R(Rm), REG_EAX );
1230 MOVZXL_rbpdisp16_r32( R_R(Rn), REG_ECX );
1231 MULL_r32( REG_ECX );
1232 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
1233 sh4_x86.tstate = TSTATE_NONE;
1237 load_reg( REG_EAX, Rm );
1238 NEGL_r32( REG_EAX );
1239 store_reg( REG_EAX, Rn );
1240 sh4_x86.tstate = TSTATE_NONE;
1244 load_reg( REG_EAX, Rm );
1245 XORL_r32_r32( REG_ECX, REG_ECX );
1247 SBBL_r32_r32( REG_EAX, REG_ECX );
1248 store_reg( REG_ECX, Rn );
1250 sh4_x86.tstate = TSTATE_C;
1254 load_reg( REG_EAX, Rm );
1255 NOTL_r32( REG_EAX );
1256 store_reg( REG_EAX, Rn );
1257 sh4_x86.tstate = TSTATE_NONE;
1261 load_reg( REG_EAX, Rm );
1262 load_reg( REG_ECX, Rn );
1263 ORL_r32_r32( REG_EAX, REG_ECX );
1264 store_reg( REG_ECX, Rn );
1265 sh4_x86.tstate = TSTATE_NONE;
1269 load_reg( REG_EAX, 0 );
1270 ORL_imms_r32(imm, REG_EAX);
1271 store_reg( REG_EAX, 0 );
1272 sh4_x86.tstate = TSTATE_NONE;
1274 OR.B #imm, @(R0, GBR) {:
1276 load_reg( REG_EAX, 0 );
1277 ADDL_rbpdisp_r32( R_GBR, REG_EAX );
1278 MOVL_r32_rspdisp( REG_EAX, 0 );
1279 MEM_READ_BYTE_FOR_WRITE( REG_EAX, REG_EDX );
1280 MOVL_rspdisp_r32( 0, REG_EAX );
1281 ORL_imms_r32(imm, REG_EDX );
1282 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1283 sh4_x86.tstate = TSTATE_NONE;
1286 COUNT_INST(I_ROTCL);
1287 load_reg( REG_EAX, Rn );
1288 if( sh4_x86.tstate != TSTATE_C ) {
1291 RCLL_imm_r32( 1, REG_EAX );
1292 store_reg( REG_EAX, Rn );
1294 sh4_x86.tstate = TSTATE_C;
1297 COUNT_INST(I_ROTCR);
1298 load_reg( REG_EAX, Rn );
1299 if( sh4_x86.tstate != TSTATE_C ) {
1302 RCRL_imm_r32( 1, REG_EAX );
1303 store_reg( REG_EAX, Rn );
1305 sh4_x86.tstate = TSTATE_C;
1309 load_reg( REG_EAX, Rn );
1310 ROLL_imm_r32( 1, REG_EAX );
1311 store_reg( REG_EAX, Rn );
1313 sh4_x86.tstate = TSTATE_C;
1317 load_reg( REG_EAX, Rn );
1318 RORL_imm_r32( 1, REG_EAX );
1319 store_reg( REG_EAX, Rn );
1321 sh4_x86.tstate = TSTATE_C;
1325 /* Annoyingly enough, not directly convertible */
1326 load_reg( REG_EAX, Rn );
1327 load_reg( REG_ECX, Rm );
1328 CMPL_imms_r32( 0, REG_ECX );
1331 NEGL_r32( REG_ECX ); // 2
1332 ANDB_imms_r8( 0x1F, REG_CL ); // 3
1333 JE_label(emptysar); // 2
1334 SARL_cl_r32( REG_EAX ); // 2
1335 JMP_label(end); // 2
1337 JMP_TARGET(emptysar);
1338 SARL_imm_r32(31, REG_EAX ); // 3
1342 ANDB_imms_r8( 0x1F, REG_CL ); // 3
1343 SHLL_cl_r32( REG_EAX ); // 2
1346 store_reg( REG_EAX, Rn );
1347 sh4_x86.tstate = TSTATE_NONE;
1351 load_reg( REG_EAX, Rn );
1352 load_reg( REG_ECX, Rm );
1353 CMPL_imms_r32( 0, REG_ECX );
1356 NEGL_r32( REG_ECX ); // 2
1357 ANDB_imms_r8( 0x1F, REG_CL ); // 3
1358 JE_label(emptyshr );
1359 SHRL_cl_r32( REG_EAX ); // 2
1360 JMP_label(end); // 2
1362 JMP_TARGET(emptyshr);
1363 XORL_r32_r32( REG_EAX, REG_EAX );
1367 ANDB_imms_r8( 0x1F, REG_CL ); // 3
1368 SHLL_cl_r32( REG_EAX ); // 2
1371 store_reg( REG_EAX, Rn );
1372 sh4_x86.tstate = TSTATE_NONE;
1376 load_reg( REG_EAX, Rn );
1377 SHLL_imm_r32( 1, REG_EAX );
1379 store_reg( REG_EAX, Rn );
1380 sh4_x86.tstate = TSTATE_C;
1384 load_reg( REG_EAX, Rn );
1385 SARL_imm_r32( 1, REG_EAX );
1387 store_reg( REG_EAX, Rn );
1388 sh4_x86.tstate = TSTATE_C;
1392 load_reg( REG_EAX, Rn );
1393 SHLL_imm_r32( 1, REG_EAX );
1395 store_reg( REG_EAX, Rn );
1396 sh4_x86.tstate = TSTATE_C;
1400 load_reg( REG_EAX, Rn );
1401 SHLL_imm_r32( 2, REG_EAX );
1402 store_reg( REG_EAX, Rn );
1403 sh4_x86.tstate = TSTATE_NONE;
1407 load_reg( REG_EAX, Rn );
1408 SHLL_imm_r32( 8, REG_EAX );
1409 store_reg( REG_EAX, Rn );
1410 sh4_x86.tstate = TSTATE_NONE;
1414 load_reg( REG_EAX, Rn );
1415 SHLL_imm_r32( 16, REG_EAX );
1416 store_reg( REG_EAX, Rn );
1417 sh4_x86.tstate = TSTATE_NONE;
1421 load_reg( REG_EAX, Rn );
1422 SHRL_imm_r32( 1, REG_EAX );
1424 store_reg( REG_EAX, Rn );
1425 sh4_x86.tstate = TSTATE_C;
1429 load_reg( REG_EAX, Rn );
1430 SHRL_imm_r32( 2, REG_EAX );
1431 store_reg( REG_EAX, Rn );
1432 sh4_x86.tstate = TSTATE_NONE;
1436 load_reg( REG_EAX, Rn );
1437 SHRL_imm_r32( 8, REG_EAX );
1438 store_reg( REG_EAX, Rn );
1439 sh4_x86.tstate = TSTATE_NONE;
1443 load_reg( REG_EAX, Rn );
1444 SHRL_imm_r32( 16, REG_EAX );
1445 store_reg( REG_EAX, Rn );
1446 sh4_x86.tstate = TSTATE_NONE;
1450 load_reg( REG_EAX, Rm );
1451 load_reg( REG_ECX, Rn );
1452 SUBL_r32_r32( REG_EAX, REG_ECX );
1453 store_reg( REG_ECX, Rn );
1454 sh4_x86.tstate = TSTATE_NONE;
1458 load_reg( REG_EAX, Rm );
1459 load_reg( REG_ECX, Rn );
1460 if( sh4_x86.tstate != TSTATE_C ) {
1463 SBBL_r32_r32( REG_EAX, REG_ECX );
1464 store_reg( REG_ECX, Rn );
1466 sh4_x86.tstate = TSTATE_C;
1470 load_reg( REG_EAX, Rm );
1471 load_reg( REG_ECX, Rn );
1472 SUBL_r32_r32( REG_EAX, REG_ECX );
1473 store_reg( REG_ECX, Rn );
1475 sh4_x86.tstate = TSTATE_O;
1478 COUNT_INST(I_SWAPB);
1479 load_reg( REG_EAX, Rm );
1480 XCHGB_r8_r8( REG_AL, REG_AH ); // NB: does not touch EFLAGS
1481 store_reg( REG_EAX, Rn );
1484 COUNT_INST(I_SWAPB);
1485 load_reg( REG_EAX, Rm );
1486 MOVL_r32_r32( REG_EAX, REG_ECX );
1487 SHLL_imm_r32( 16, REG_ECX );
1488 SHRL_imm_r32( 16, REG_EAX );
1489 ORL_r32_r32( REG_EAX, REG_ECX );
1490 store_reg( REG_ECX, Rn );
1491 sh4_x86.tstate = TSTATE_NONE;
1495 load_reg( REG_EAX, Rn );
1496 MOVL_r32_rspdisp( REG_EAX, 0 );
1497 MEM_READ_BYTE_FOR_WRITE( REG_EAX, REG_EDX );
1498 TESTB_r8_r8( REG_DL, REG_DL );
1500 ORB_imms_r8( 0x80, REG_DL );
1501 MOVL_rspdisp_r32( 0, REG_EAX );
1502 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1503 sh4_x86.tstate = TSTATE_NONE;
1507 load_reg( REG_EAX, Rm );
1508 load_reg( REG_ECX, Rn );
1509 TESTL_r32_r32( REG_EAX, REG_ECX );
1511 sh4_x86.tstate = TSTATE_E;
1515 load_reg( REG_EAX, 0 );
1516 TESTL_imms_r32( imm, REG_EAX );
1518 sh4_x86.tstate = TSTATE_E;
1520 TST.B #imm, @(R0, GBR) {:
1522 load_reg( REG_EAX, 0);
1523 ADDL_rbpdisp_r32( R_GBR, REG_EAX );
1524 MEM_READ_BYTE( REG_EAX, REG_EAX );
1525 TESTB_imms_r8( imm, REG_AL );
1527 sh4_x86.tstate = TSTATE_E;
1531 load_reg( REG_EAX, Rm );
1532 load_reg( REG_ECX, Rn );
1533 XORL_r32_r32( REG_EAX, REG_ECX );
1534 store_reg( REG_ECX, Rn );
1535 sh4_x86.tstate = TSTATE_NONE;
1539 load_reg( REG_EAX, 0 );
1540 XORL_imms_r32( imm, REG_EAX );
1541 store_reg( REG_EAX, 0 );
1542 sh4_x86.tstate = TSTATE_NONE;
1544 XOR.B #imm, @(R0, GBR) {:
1546 load_reg( REG_EAX, 0 );
1547 ADDL_rbpdisp_r32( R_GBR, REG_EAX );
1548 MOVL_r32_rspdisp( REG_EAX, 0 );
1549 MEM_READ_BYTE_FOR_WRITE(REG_EAX, REG_EDX);
1550 MOVL_rspdisp_r32( 0, REG_EAX );
1551 XORL_imms_r32( imm, REG_EDX );
1552 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1553 sh4_x86.tstate = TSTATE_NONE;
1556 COUNT_INST(I_XTRCT);
1557 load_reg( REG_EAX, Rm );
1558 load_reg( REG_ECX, Rn );
1559 SHLL_imm_r32( 16, REG_EAX );
1560 SHRL_imm_r32( 16, REG_ECX );
1561 ORL_r32_r32( REG_EAX, REG_ECX );
1562 store_reg( REG_ECX, Rn );
1563 sh4_x86.tstate = TSTATE_NONE;
1566 /* Data move instructions */
1569 load_reg( REG_EAX, Rm );
1570 store_reg( REG_EAX, Rn );
1574 MOVL_imm32_r32( imm, REG_EAX );
1575 store_reg( REG_EAX, Rn );
1579 load_reg( REG_EAX, Rn );
1580 load_reg( REG_EDX, Rm );
1581 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1582 sh4_x86.tstate = TSTATE_NONE;
1586 load_reg( REG_EAX, Rn );
1587 LEAL_r32disp_r32( REG_EAX, -1, REG_EAX );
1588 load_reg( REG_EDX, Rm );
1589 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1590 ADDL_imms_rbpdisp( -1, REG_OFFSET(r[Rn]) );
1591 sh4_x86.tstate = TSTATE_NONE;
1593 MOV.B Rm, @(R0, Rn) {:
1595 load_reg( REG_EAX, 0 );
1596 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
1597 load_reg( REG_EDX, Rm );
1598 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1599 sh4_x86.tstate = TSTATE_NONE;
1601 MOV.B R0, @(disp, GBR) {:
1603 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1604 ADDL_imms_r32( disp, REG_EAX );
1605 load_reg( REG_EDX, 0 );
1606 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1607 sh4_x86.tstate = TSTATE_NONE;
1609 MOV.B R0, @(disp, Rn) {:
1611 load_reg( REG_EAX, Rn );
1612 ADDL_imms_r32( disp, REG_EAX );
1613 load_reg( REG_EDX, 0 );
1614 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1615 sh4_x86.tstate = TSTATE_NONE;
1619 load_reg( REG_EAX, Rm );
1620 MEM_READ_BYTE( REG_EAX, REG_EAX );
1621 store_reg( REG_EAX, Rn );
1622 sh4_x86.tstate = TSTATE_NONE;
1626 load_reg( REG_EAX, Rm );
1627 MEM_READ_BYTE( REG_EAX, REG_EAX );
1629 ADDL_imms_rbpdisp( 1, REG_OFFSET(r[Rm]) );
1631 store_reg( REG_EAX, Rn );
1632 sh4_x86.tstate = TSTATE_NONE;
1634 MOV.B @(R0, Rm), Rn {:
1636 load_reg( REG_EAX, 0 );
1637 ADDL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
1638 MEM_READ_BYTE( REG_EAX, REG_EAX );
1639 store_reg( REG_EAX, Rn );
1640 sh4_x86.tstate = TSTATE_NONE;
1642 MOV.B @(disp, GBR), R0 {:
1644 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1645 ADDL_imms_r32( disp, REG_EAX );
1646 MEM_READ_BYTE( REG_EAX, REG_EAX );
1647 store_reg( REG_EAX, 0 );
1648 sh4_x86.tstate = TSTATE_NONE;
1650 MOV.B @(disp, Rm), R0 {:
1652 load_reg( REG_EAX, Rm );
1653 ADDL_imms_r32( disp, REG_EAX );
1654 MEM_READ_BYTE( REG_EAX, REG_EAX );
1655 store_reg( REG_EAX, 0 );
1656 sh4_x86.tstate = TSTATE_NONE;
1660 load_reg( REG_EAX, Rn );
1661 check_walign32(REG_EAX);
1662 MOVL_r32_r32( REG_EAX, REG_ECX );
1663 ANDL_imms_r32( 0xFC000000, REG_ECX );
1664 CMPL_imms_r32( 0xE0000000, REG_ECX );
1666 ANDL_imms_r32( 0x3C, REG_EAX );
1667 load_reg( REG_EDX, Rm );
1668 MOVL_r32_sib( REG_EDX, 0, REG_EBP, REG_EAX, REG_OFFSET(store_queue) );
1671 load_reg( REG_EDX, Rm );
1672 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1674 sh4_x86.tstate = TSTATE_NONE;
1678 load_reg( REG_EAX, Rn );
1679 ADDL_imms_r32( -4, REG_EAX );
1680 check_walign32( REG_EAX );
1681 load_reg( REG_EDX, Rm );
1682 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1683 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
1684 sh4_x86.tstate = TSTATE_NONE;
1686 MOV.L Rm, @(R0, Rn) {:
1688 load_reg( REG_EAX, 0 );
1689 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
1690 check_walign32( REG_EAX );
1691 load_reg( REG_EDX, Rm );
1692 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1693 sh4_x86.tstate = TSTATE_NONE;
1695 MOV.L R0, @(disp, GBR) {:
1697 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1698 ADDL_imms_r32( disp, REG_EAX );
1699 check_walign32( REG_EAX );
1700 load_reg( REG_EDX, 0 );
1701 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1702 sh4_x86.tstate = TSTATE_NONE;
1704 MOV.L Rm, @(disp, Rn) {:
1706 load_reg( REG_EAX, Rn );
1707 ADDL_imms_r32( disp, REG_EAX );
1708 check_walign32( REG_EAX );
1709 MOVL_r32_r32( REG_EAX, REG_ECX );
1710 ANDL_imms_r32( 0xFC000000, REG_ECX );
1711 CMPL_imms_r32( 0xE0000000, REG_ECX );
1713 ANDL_imms_r32( 0x3C, REG_EAX );
1714 load_reg( REG_EDX, Rm );
1715 MOVL_r32_sib( REG_EDX, 0, REG_EBP, REG_EAX, REG_OFFSET(store_queue) );
1718 load_reg( REG_EDX, Rm );
1719 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1721 sh4_x86.tstate = TSTATE_NONE;
1725 load_reg( REG_EAX, Rm );
1726 check_ralign32( REG_EAX );
1727 MEM_READ_LONG( REG_EAX, REG_EAX );
1728 store_reg( REG_EAX, Rn );
1729 sh4_x86.tstate = TSTATE_NONE;
1733 load_reg( REG_EAX, Rm );
1734 check_ralign32( REG_EAX );
1735 MEM_READ_LONG( REG_EAX, REG_EAX );
1737 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
1739 store_reg( REG_EAX, Rn );
1740 sh4_x86.tstate = TSTATE_NONE;
1742 MOV.L @(R0, Rm), Rn {:
1744 load_reg( REG_EAX, 0 );
1745 ADDL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
1746 check_ralign32( REG_EAX );
1747 MEM_READ_LONG( REG_EAX, REG_EAX );
1748 store_reg( REG_EAX, Rn );
1749 sh4_x86.tstate = TSTATE_NONE;
1751 MOV.L @(disp, GBR), R0 {:
1753 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1754 ADDL_imms_r32( disp, REG_EAX );
1755 check_ralign32( REG_EAX );
1756 MEM_READ_LONG( REG_EAX, REG_EAX );
1757 store_reg( REG_EAX, 0 );
1758 sh4_x86.tstate = TSTATE_NONE;
1760 MOV.L @(disp, PC), Rn {:
1761 COUNT_INST(I_MOVLPC);
1762 if( sh4_x86.in_delay_slot ) {
1765 uint32_t target = (pc & 0xFFFFFFFC) + disp + 4;
1766 if( sh4_x86.fastmem && IS_IN_ICACHE(target) ) {
1767 // If the target address is in the same page as the code, it's
1768 // pretty safe to just ref it directly and circumvent the whole
1769 // memory subsystem. (this is a big performance win)
1771 // FIXME: There's a corner-case that's not handled here when
1772 // the current code-page is in the ITLB but not in the UTLB.
1773 // (should generate a TLB miss although need to test SH4
1774 // behaviour to confirm) Unlikely to be anyone depending on this
1775 // behaviour though.
1776 sh4ptr_t ptr = GET_ICACHE_PTR(target);
1777 MOVL_moffptr_eax( ptr );
1779 // Note: we use sh4r.pc for the calc as we could be running at a
1780 // different virtual address than the translation was done with,
1781 // but we can safely assume that the low bits are the same.
1782 MOVL_imm32_r32( (pc-sh4_x86.block_start_pc) + disp + 4 - (pc&0x03), REG_EAX );
1783 ADDL_rbpdisp_r32( R_PC, REG_EAX );
1784 MEM_READ_LONG( REG_EAX, REG_EAX );
1785 sh4_x86.tstate = TSTATE_NONE;
1787 store_reg( REG_EAX, Rn );
1790 MOV.L @(disp, Rm), Rn {:
1792 load_reg( REG_EAX, Rm );
1793 ADDL_imms_r32( disp, REG_EAX );
1794 check_ralign32( REG_EAX );
1795 MEM_READ_LONG( REG_EAX, REG_EAX );
1796 store_reg( REG_EAX, Rn );
1797 sh4_x86.tstate = TSTATE_NONE;
1801 load_reg( REG_EAX, Rn );
1802 check_walign16( REG_EAX );
1803 load_reg( REG_EDX, Rm );
1804 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1805 sh4_x86.tstate = TSTATE_NONE;
1809 load_reg( REG_EAX, Rn );
1810 check_walign16( REG_EAX );
1811 LEAL_r32disp_r32( REG_EAX, -2, REG_EAX );
1812 load_reg( REG_EDX, Rm );
1813 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1814 ADDL_imms_rbpdisp( -2, REG_OFFSET(r[Rn]) );
1815 sh4_x86.tstate = TSTATE_NONE;
1817 MOV.W Rm, @(R0, Rn) {:
1819 load_reg( REG_EAX, 0 );
1820 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
1821 check_walign16( REG_EAX );
1822 load_reg( REG_EDX, Rm );
1823 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1824 sh4_x86.tstate = TSTATE_NONE;
1826 MOV.W R0, @(disp, GBR) {:
1828 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1829 ADDL_imms_r32( disp, REG_EAX );
1830 check_walign16( REG_EAX );
1831 load_reg( REG_EDX, 0 );
1832 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1833 sh4_x86.tstate = TSTATE_NONE;
1835 MOV.W R0, @(disp, Rn) {:
1837 load_reg( REG_EAX, Rn );
1838 ADDL_imms_r32( disp, REG_EAX );
1839 check_walign16( REG_EAX );
1840 load_reg( REG_EDX, 0 );
1841 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1842 sh4_x86.tstate = TSTATE_NONE;
1846 load_reg( REG_EAX, Rm );
1847 check_ralign16( REG_EAX );
1848 MEM_READ_WORD( REG_EAX, REG_EAX );
1849 store_reg( REG_EAX, Rn );
1850 sh4_x86.tstate = TSTATE_NONE;
1854 load_reg( REG_EAX, Rm );
1855 check_ralign16( REG_EAX );
1856 MEM_READ_WORD( REG_EAX, REG_EAX );
1858 ADDL_imms_rbpdisp( 2, REG_OFFSET(r[Rm]) );
1860 store_reg( REG_EAX, Rn );
1861 sh4_x86.tstate = TSTATE_NONE;
1863 MOV.W @(R0, Rm), Rn {:
1865 load_reg( REG_EAX, 0 );
1866 ADDL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
1867 check_ralign16( REG_EAX );
1868 MEM_READ_WORD( REG_EAX, REG_EAX );
1869 store_reg( REG_EAX, Rn );
1870 sh4_x86.tstate = TSTATE_NONE;
1872 MOV.W @(disp, GBR), R0 {:
1874 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1875 ADDL_imms_r32( disp, REG_EAX );
1876 check_ralign16( REG_EAX );
1877 MEM_READ_WORD( REG_EAX, REG_EAX );
1878 store_reg( REG_EAX, 0 );
1879 sh4_x86.tstate = TSTATE_NONE;
1881 MOV.W @(disp, PC), Rn {:
1883 if( sh4_x86.in_delay_slot ) {
1886 // See comments for MOV.L @(disp, PC), Rn
1887 uint32_t target = pc + disp + 4;
1888 if( sh4_x86.fastmem && IS_IN_ICACHE(target) ) {
1889 sh4ptr_t ptr = GET_ICACHE_PTR(target);
1890 MOVL_moffptr_eax( ptr );
1891 MOVSXL_r16_r32( REG_EAX, REG_EAX );
1893 MOVL_imm32_r32( (pc - sh4_x86.block_start_pc) + disp + 4, REG_EAX );
1894 ADDL_rbpdisp_r32( R_PC, REG_EAX );
1895 MEM_READ_WORD( REG_EAX, REG_EAX );
1896 sh4_x86.tstate = TSTATE_NONE;
1898 store_reg( REG_EAX, Rn );
1901 MOV.W @(disp, Rm), R0 {:
1903 load_reg( REG_EAX, Rm );
1904 ADDL_imms_r32( disp, REG_EAX );
1905 check_ralign16( REG_EAX );
1906 MEM_READ_WORD( REG_EAX, REG_EAX );
1907 store_reg( REG_EAX, 0 );
1908 sh4_x86.tstate = TSTATE_NONE;
1910 MOVA @(disp, PC), R0 {:
1912 if( sh4_x86.in_delay_slot ) {
1915 MOVL_imm32_r32( (pc - sh4_x86.block_start_pc) + disp + 4 - (pc&0x03), REG_ECX );
1916 ADDL_rbpdisp_r32( R_PC, REG_ECX );
1917 store_reg( REG_ECX, 0 );
1918 sh4_x86.tstate = TSTATE_NONE;
1922 COUNT_INST(I_MOVCA);
1923 load_reg( REG_EAX, Rn );
1924 check_walign32( REG_EAX );
1925 load_reg( REG_EDX, 0 );
1926 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1927 sh4_x86.tstate = TSTATE_NONE;
1930 /* Control transfer instructions */
1933 if( sh4_x86.in_delay_slot ) {
1936 sh4vma_t target = disp + pc + 4;
1937 JT_label( nottaken );
1938 exit_block_rel(target, pc+2 );
1939 JMP_TARGET(nottaken);
1945 if( sh4_x86.in_delay_slot ) {
1948 sh4_x86.in_delay_slot = DELAY_PC;
1949 if( UNTRANSLATABLE(pc+2) ) {
1950 MOVL_imm32_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
1952 ADDL_imms_r32( disp, REG_EAX );
1953 JMP_TARGET(nottaken);
1954 ADDL_rbpdisp_r32( R_PC, REG_EAX );
1955 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
1956 exit_block_emu(pc+2);
1957 sh4_x86.branch_taken = TRUE;
1960 if( sh4_x86.tstate == TSTATE_NONE ) {
1961 CMPL_imms_rbpdisp( 1, R_T );
1962 sh4_x86.tstate = TSTATE_E;
1964 sh4vma_t target = disp + pc + 4;
1965 JCC_cc_rel32(sh4_x86.tstate,0);
1966 uint32_t *patch = ((uint32_t *)xlat_output)-1;
1967 int save_tstate = sh4_x86.tstate;
1968 sh4_translate_instruction(pc+2);
1969 sh4_x86.in_delay_slot = DELAY_PC; /* Cleared by sh4_translate_instruction */
1970 exit_block_rel( target, pc+4 );
1973 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1974 sh4_x86.tstate = save_tstate;
1975 sh4_translate_instruction(pc+2);
1982 if( sh4_x86.in_delay_slot ) {
1985 sh4_x86.in_delay_slot = DELAY_PC;
1986 sh4_x86.branch_taken = TRUE;
1987 if( UNTRANSLATABLE(pc+2) ) {
1988 MOVL_rbpdisp_r32( R_PC, REG_EAX );
1989 ADDL_imms_r32( pc + disp + 4 - sh4_x86.block_start_pc, REG_EAX );
1990 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
1991 exit_block_emu(pc+2);
1994 sh4_translate_instruction( pc + 2 );
1995 exit_block_rel( disp + pc + 4, pc+4 );
2002 if( sh4_x86.in_delay_slot ) {
2005 MOVL_rbpdisp_r32( R_PC, REG_EAX );
2006 ADDL_imms_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
2007 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
2008 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
2009 sh4_x86.in_delay_slot = DELAY_PC;
2010 sh4_x86.tstate = TSTATE_NONE;
2011 sh4_x86.branch_taken = TRUE;
2012 if( UNTRANSLATABLE(pc+2) ) {
2013 exit_block_emu(pc+2);
2016 sh4_translate_instruction( pc + 2 );
2017 exit_block_newpcset(pc+4);
2024 if( sh4_x86.in_delay_slot ) {
2027 MOVL_rbpdisp_r32( R_PC, REG_EAX );
2028 ADDL_imms_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
2029 MOVL_r32_rbpdisp( REG_EAX, R_PR );
2030 sh4_x86.in_delay_slot = DELAY_PC;
2031 sh4_x86.branch_taken = TRUE;
2032 sh4_x86.tstate = TSTATE_NONE;
2033 if( UNTRANSLATABLE(pc+2) ) {
2034 ADDL_imms_r32( disp, REG_EAX );
2035 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
2036 exit_block_emu(pc+2);
2039 sh4_translate_instruction( pc + 2 );
2040 exit_block_rel( disp + pc + 4, pc+4 );
2047 if( sh4_x86.in_delay_slot ) {
2050 MOVL_rbpdisp_r32( R_PC, REG_EAX );
2051 ADDL_imms_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
2052 MOVL_r32_rbpdisp( REG_EAX, R_PR );
2053 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
2054 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
2056 sh4_x86.in_delay_slot = DELAY_PC;
2057 sh4_x86.tstate = TSTATE_NONE;
2058 sh4_x86.branch_taken = TRUE;
2059 if( UNTRANSLATABLE(pc+2) ) {
2060 exit_block_emu(pc+2);
2063 sh4_translate_instruction( pc + 2 );
2064 exit_block_newpcset(pc+4);
2071 if( sh4_x86.in_delay_slot ) {
2074 sh4vma_t target = disp + pc + 4;
2075 JF_label( nottaken );
2076 exit_block_rel(target, pc+2 );
2077 JMP_TARGET(nottaken);
2083 if( sh4_x86.in_delay_slot ) {
2086 sh4_x86.in_delay_slot = DELAY_PC;
2087 if( UNTRANSLATABLE(pc+2) ) {
2088 MOVL_imm32_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
2090 ADDL_imms_r32( disp, REG_EAX );
2091 JMP_TARGET(nottaken);
2092 ADDL_rbpdisp_r32( R_PC, REG_EAX );
2093 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
2094 exit_block_emu(pc+2);
2095 sh4_x86.branch_taken = TRUE;
2098 if( sh4_x86.tstate == TSTATE_NONE ) {
2099 CMPL_imms_rbpdisp( 1, R_T );
2100 sh4_x86.tstate = TSTATE_E;
2102 JCC_cc_rel32(sh4_x86.tstate^1,0);
2103 uint32_t *patch = ((uint32_t *)xlat_output)-1;
2105 int save_tstate = sh4_x86.tstate;
2106 sh4_translate_instruction(pc+2);
2107 sh4_x86.in_delay_slot = DELAY_PC; /* Cleared by sh4_translate_instruction */
2108 exit_block_rel( disp + pc + 4, pc+4 );
2110 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
2111 sh4_x86.tstate = save_tstate;
2112 sh4_translate_instruction(pc+2);
2119 if( sh4_x86.in_delay_slot ) {
2122 load_reg( REG_ECX, Rn );
2123 MOVL_r32_rbpdisp( REG_ECX, R_NEW_PC );
2124 sh4_x86.in_delay_slot = DELAY_PC;
2125 sh4_x86.branch_taken = TRUE;
2126 if( UNTRANSLATABLE(pc+2) ) {
2127 exit_block_emu(pc+2);
2130 sh4_translate_instruction(pc+2);
2131 exit_block_newpcset(pc+4);
2138 if( sh4_x86.in_delay_slot ) {
2141 MOVL_rbpdisp_r32( R_PC, REG_EAX );
2142 ADDL_imms_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
2143 MOVL_r32_rbpdisp( REG_EAX, R_PR );
2144 load_reg( REG_ECX, Rn );
2145 MOVL_r32_rbpdisp( REG_ECX, R_NEW_PC );
2146 sh4_x86.in_delay_slot = DELAY_PC;
2147 sh4_x86.branch_taken = TRUE;
2148 sh4_x86.tstate = TSTATE_NONE;
2149 if( UNTRANSLATABLE(pc+2) ) {
2150 exit_block_emu(pc+2);
2153 sh4_translate_instruction(pc+2);
2154 exit_block_newpcset(pc+4);
2161 if( sh4_x86.in_delay_slot ) {
2165 MOVL_rbpdisp_r32( R_SPC, REG_ECX );
2166 MOVL_r32_rbpdisp( REG_ECX, R_NEW_PC );
2167 MOVL_rbpdisp_r32( R_SSR, REG_EAX );
2168 CALL1_ptr_r32( sh4_write_sr, REG_EAX );
2169 sh4_x86.in_delay_slot = DELAY_PC;
2170 sh4_x86.fpuen_checked = FALSE;
2171 sh4_x86.tstate = TSTATE_NONE;
2172 sh4_x86.branch_taken = TRUE;
2173 sh4_x86.sh4_mode = SH4_MODE_UNKNOWN;
2174 if( UNTRANSLATABLE(pc+2) ) {
2175 exit_block_emu(pc+2);
2178 sh4_translate_instruction(pc+2);
2179 exit_block_newpcset(pc+4);
2186 if( sh4_x86.in_delay_slot ) {
2189 MOVL_rbpdisp_r32( R_PR, REG_ECX );
2190 MOVL_r32_rbpdisp( REG_ECX, R_NEW_PC );
2191 sh4_x86.in_delay_slot = DELAY_PC;
2192 sh4_x86.branch_taken = TRUE;
2193 if( UNTRANSLATABLE(pc+2) ) {
2194 exit_block_emu(pc+2);
2197 sh4_translate_instruction(pc+2);
2198 exit_block_newpcset(pc+4);
2204 COUNT_INST(I_TRAPA);
2205 if( sh4_x86.in_delay_slot ) {
2208 MOVL_imm32_r32( pc+2 - sh4_x86.block_start_pc, REG_ECX ); // 5
2209 ADDL_r32_rbpdisp( REG_ECX, R_PC );
2210 MOVL_imm32_r32( imm, REG_EAX );
2211 CALL1_ptr_r32( sh4_raise_trap, REG_EAX );
2212 sh4_x86.tstate = TSTATE_NONE;
2213 exit_block_pcset(pc+2);
2214 sh4_x86.branch_taken = TRUE;
2219 COUNT_INST(I_UNDEF);
2220 if( sh4_x86.in_delay_slot ) {
2221 exit_block_exc(EXC_SLOT_ILLEGAL, pc-2, 4);
2223 exit_block_exc(EXC_ILLEGAL, pc, 2);
2229 COUNT_INST(I_CLRMAC);
2230 XORL_r32_r32(REG_EAX, REG_EAX);
2231 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
2232 MOVL_r32_rbpdisp( REG_EAX, R_MACH );
2233 sh4_x86.tstate = TSTATE_NONE;
2238 SETCCB_cc_rbpdisp(X86_COND_C, R_S);
2239 sh4_x86.tstate = TSTATE_NONE;
2245 sh4_x86.tstate = TSTATE_C;
2250 SETCCB_cc_rbpdisp(X86_COND_C, R_S);
2251 sh4_x86.tstate = TSTATE_NONE;
2257 sh4_x86.tstate = TSTATE_C;
2260 /* Floating point moves */
2262 COUNT_INST(I_FMOV1);
2264 if( sh4_x86.double_size ) {
2265 load_dr0( REG_EAX, FRm );
2266 load_dr1( REG_ECX, FRm );
2267 store_dr0( REG_EAX, FRn );
2268 store_dr1( REG_ECX, FRn );
2270 load_fr( REG_EAX, FRm ); // SZ=0 branch
2271 store_fr( REG_EAX, FRn );
2275 COUNT_INST(I_FMOV2);
2277 load_reg( REG_EAX, Rn );
2278 if( sh4_x86.double_size ) {
2279 check_walign64( REG_EAX );
2280 load_dr0( REG_EDX, FRm );
2281 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2282 load_reg( REG_EAX, Rn );
2283 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2284 load_dr1( REG_EDX, FRm );
2285 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2287 check_walign32( REG_EAX );
2288 load_fr( REG_EDX, FRm );
2289 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2291 sh4_x86.tstate = TSTATE_NONE;
2294 COUNT_INST(I_FMOV5);
2296 load_reg( REG_EAX, Rm );
2297 if( sh4_x86.double_size ) {
2298 check_ralign64( REG_EAX );
2299 MEM_READ_LONG( REG_EAX, REG_EAX );
2300 store_dr0( REG_EAX, FRn );
2301 load_reg( REG_EAX, Rm );
2302 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2303 MEM_READ_LONG( REG_EAX, REG_EAX );
2304 store_dr1( REG_EAX, FRn );
2306 check_ralign32( REG_EAX );
2307 MEM_READ_LONG( REG_EAX, REG_EAX );
2308 store_fr( REG_EAX, FRn );
2310 sh4_x86.tstate = TSTATE_NONE;
2313 COUNT_INST(I_FMOV3);
2315 load_reg( REG_EAX, Rn );
2316 if( sh4_x86.double_size ) {
2317 check_walign64( REG_EAX );
2318 LEAL_r32disp_r32( REG_EAX, -8, REG_EAX );
2319 load_dr0( REG_EDX, FRm );
2320 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2321 load_reg( REG_EAX, Rn );
2322 LEAL_r32disp_r32( REG_EAX, -4, REG_EAX );
2323 load_dr1( REG_EDX, FRm );
2324 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2325 ADDL_imms_rbpdisp(-8,REG_OFFSET(r[Rn]));
2327 check_walign32( REG_EAX );
2328 LEAL_r32disp_r32( REG_EAX, -4, REG_EAX );
2329 load_fr( REG_EDX, FRm );
2330 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2331 ADDL_imms_rbpdisp(-4,REG_OFFSET(r[Rn]));
2333 sh4_x86.tstate = TSTATE_NONE;
2336 COUNT_INST(I_FMOV6);
2338 load_reg( REG_EAX, Rm );
2339 if( sh4_x86.double_size ) {
2340 check_ralign64( REG_EAX );
2341 MEM_READ_LONG( REG_EAX, REG_EAX );
2342 store_dr0( REG_EAX, FRn );
2343 load_reg( REG_EAX, Rm );
2344 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2345 MEM_READ_LONG( REG_EAX, REG_EAX );
2346 store_dr1( REG_EAX, FRn );
2347 ADDL_imms_rbpdisp( 8, REG_OFFSET(r[Rm]) );
2349 check_ralign32( REG_EAX );
2350 MEM_READ_LONG( REG_EAX, REG_EAX );
2351 store_fr( REG_EAX, FRn );
2352 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2354 sh4_x86.tstate = TSTATE_NONE;
2356 FMOV FRm, @(R0, Rn) {:
2357 COUNT_INST(I_FMOV4);
2359 load_reg( REG_EAX, Rn );
2360 ADDL_rbpdisp_r32( REG_OFFSET(r[0]), REG_EAX );
2361 if( sh4_x86.double_size ) {
2362 check_walign64( REG_EAX );
2363 load_dr0( REG_EDX, FRm );
2364 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2365 load_reg( REG_EAX, Rn );
2366 ADDL_rbpdisp_r32( REG_OFFSET(r[0]), REG_EAX );
2367 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2368 load_dr1( REG_EDX, FRm );
2369 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2371 check_walign32( REG_EAX );
2372 load_fr( REG_EDX, FRm );
2373 MEM_WRITE_LONG( REG_EAX, REG_EDX ); // 12
2375 sh4_x86.tstate = TSTATE_NONE;
2377 FMOV @(R0, Rm), FRn {:
2378 COUNT_INST(I_FMOV7);
2380 load_reg( REG_EAX, Rm );
2381 ADDL_rbpdisp_r32( REG_OFFSET(r[0]), REG_EAX );
2382 if( sh4_x86.double_size ) {
2383 check_ralign64( REG_EAX );
2384 MEM_READ_LONG( REG_EAX, REG_EAX );
2385 store_dr0( REG_EAX, FRn );
2386 load_reg( REG_EAX, Rm );
2387 ADDL_rbpdisp_r32( REG_OFFSET(r[0]), REG_EAX );
2388 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2389 MEM_READ_LONG( REG_EAX, REG_EAX );
2390 store_dr1( REG_EAX, FRn );
2392 check_ralign32( REG_EAX );
2393 MEM_READ_LONG( REG_EAX, REG_EAX );
2394 store_fr( REG_EAX, FRn );
2396 sh4_x86.tstate = TSTATE_NONE;
2398 FLDI0 FRn {: /* IFF PR=0 */
2399 COUNT_INST(I_FLDI0);
2401 if( sh4_x86.double_prec == 0 ) {
2402 XORL_r32_r32( REG_EAX, REG_EAX );
2403 store_fr( REG_EAX, FRn );
2405 sh4_x86.tstate = TSTATE_NONE;
2407 FLDI1 FRn {: /* IFF PR=0 */
2408 COUNT_INST(I_FLDI1);
2410 if( sh4_x86.double_prec == 0 ) {
2411 MOVL_imm32_r32( 0x3F800000, REG_EAX );
2412 store_fr( REG_EAX, FRn );
2417 COUNT_INST(I_FLOAT);
2419 FILD_rbpdisp(R_FPUL);
2420 if( sh4_x86.double_prec ) {
2429 if( sh4_x86.double_prec ) {
2434 MOVP_immptr_rptr( &max_int, REG_ECX );
2435 FILD_r32disp( REG_ECX, 0 );
2438 MOVP_immptr_rptr( &min_int, REG_ECX );
2439 FILD_r32disp( REG_ECX, 0 );
2442 MOVP_immptr_rptr( &save_fcw, REG_EAX );
2443 FNSTCW_r32disp( REG_EAX, 0 );
2444 MOVP_immptr_rptr( &trunc_fcw, REG_EDX );
2445 FLDCW_r32disp( REG_EDX, 0 );
2446 FISTP_rbpdisp(R_FPUL);
2447 FLDCW_r32disp( REG_EAX, 0 );
2452 MOVL_r32disp_r32( REG_ECX, 0, REG_ECX ); // 2
2453 MOVL_r32_rbpdisp( REG_ECX, R_FPUL );
2456 sh4_x86.tstate = TSTATE_NONE;
2461 load_fr( REG_EAX, FRm );
2462 MOVL_r32_rbpdisp( REG_EAX, R_FPUL );
2467 MOVL_rbpdisp_r32( R_FPUL, REG_EAX );
2468 store_fr( REG_EAX, FRn );
2471 COUNT_INST(I_FCNVDS);
2473 if( sh4_x86.double_prec ) {
2479 COUNT_INST(I_FCNVSD);
2481 if( sh4_x86.double_prec ) {
2487 /* Floating point instructions */
2491 if( sh4_x86.double_prec ) {
2504 if( sh4_x86.double_prec ) {
2519 if( sh4_x86.double_prec ) {
2531 FMAC FR0, FRm, FRn {:
2534 if( sh4_x86.double_prec ) {
2554 if( sh4_x86.double_prec ) {
2569 if( sh4_x86.double_prec ) {
2580 COUNT_INST(I_FSRRA);
2582 if( sh4_x86.double_prec == 0 ) {
2591 COUNT_INST(I_FSQRT);
2593 if( sh4_x86.double_prec ) {
2606 if( sh4_x86.double_prec ) {
2620 COUNT_INST(I_FCMPEQ);
2622 if( sh4_x86.double_prec ) {
2632 sh4_x86.tstate = TSTATE_E;
2635 COUNT_INST(I_FCMPGT);
2637 if( sh4_x86.double_prec ) {
2647 sh4_x86.tstate = TSTATE_A;
2653 if( sh4_x86.double_prec == 0 ) {
2654 LEAP_rbpdisp_rptr( REG_OFFSET(fr[0][FRn&0x0E]), REG_EDX );
2655 MOVL_rbpdisp_r32( R_FPUL, REG_EAX );
2656 CALL2_ptr_r32_r32( sh4_fsca, REG_EAX, REG_EDX );
2658 sh4_x86.tstate = TSTATE_NONE;
2663 if( sh4_x86.double_prec == 0 ) {
2664 if( sh4_x86.sse3_enabled ) {
2665 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[0][FVm<<2]), 4 );
2666 MULPS_rbpdisp_xmm( REG_OFFSET(fr[0][FVn<<2]), 4 );
2667 HADDPS_xmm_xmm( 4, 4 );
2668 HADDPS_xmm_xmm( 4, 4 );
2669 MOVSS_xmm_rbpdisp( 4, REG_OFFSET(fr[0][(FVn<<2)+2]) );
2674 push_fr( (FVm<<2)+1);
2675 push_fr( (FVn<<2)+1);
2678 push_fr( (FVm<<2)+2);
2679 push_fr( (FVn<<2)+2);
2682 push_fr( (FVm<<2)+3);
2683 push_fr( (FVn<<2)+3);
2686 pop_fr( (FVn<<2)+3);
2693 if( sh4_x86.double_prec == 0 ) {
2694 if( sh4_x86.sse3_enabled && sh4_x86.begin_callback == NULL ) {
2695 /* FIXME: For now, disable this inlining when we're running in shadow mode -
2696 * it gives slightly different results from the emu core. Need to
2697 * fix the precision so both give the right results.
2699 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][0]), 1 ); // M1 M0 M3 M2
2700 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][4]), 0 ); // M5 M4 M7 M6
2701 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][8]), 3 ); // M9 M8 M11 M10
2702 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][12]), 2 );// M13 M12 M15 M14
2704 MOVSLDUP_rbpdisp_xmm( REG_OFFSET(fr[0][FVn<<2]), 4 ); // V1 V1 V3 V3
2705 MOVSHDUP_rbpdisp_xmm( REG_OFFSET(fr[0][FVn<<2]), 5 ); // V0 V0 V2 V2
2706 MOV_xmm_xmm( 4, 6 );
2707 MOV_xmm_xmm( 5, 7 );
2708 MOVLHPS_xmm_xmm( 4, 4 ); // V1 V1 V1 V1
2709 MOVHLPS_xmm_xmm( 6, 6 ); // V3 V3 V3 V3
2710 MOVLHPS_xmm_xmm( 5, 5 ); // V0 V0 V0 V0
2711 MOVHLPS_xmm_xmm( 7, 7 ); // V2 V2 V2 V2
2712 MULPS_xmm_xmm( 0, 4 );
2713 MULPS_xmm_xmm( 1, 5 );
2714 MULPS_xmm_xmm( 2, 6 );
2715 MULPS_xmm_xmm( 3, 7 );
2716 ADDPS_xmm_xmm( 5, 4 );
2717 ADDPS_xmm_xmm( 7, 6 );
2718 ADDPS_xmm_xmm( 6, 4 );
2719 MOVAPS_xmm_rbpdisp( 4, REG_OFFSET(fr[0][FVn<<2]) );
2721 LEAP_rbpdisp_rptr( REG_OFFSET(fr[0][FVn<<2]), REG_EAX );
2722 CALL1_ptr_r32( sh4_ftrv, REG_EAX );
2725 sh4_x86.tstate = TSTATE_NONE;
2729 COUNT_INST(I_FRCHG);
2731 XORL_imms_rbpdisp( FPSCR_FR, R_FPSCR );
2732 CALL_ptr( sh4_switch_fr_banks );
2733 sh4_x86.tstate = TSTATE_NONE;
2736 COUNT_INST(I_FSCHG);
2738 XORL_imms_rbpdisp( FPSCR_SZ, R_FPSCR);
2739 XORL_imms_rbpdisp( FPSCR_SZ, REG_OFFSET(xlat_sh4_mode) );
2740 sh4_x86.tstate = TSTATE_NONE;
2741 sh4_x86.double_size = !sh4_x86.double_size;
2742 sh4_x86.sh4_mode = sh4_x86.sh4_mode ^ FPSCR_SZ;
2745 /* Processor control instructions */
2747 COUNT_INST(I_LDCSR);
2748 if( sh4_x86.in_delay_slot ) {
2752 load_reg( REG_EAX, Rm );
2753 CALL1_ptr_r32( sh4_write_sr, REG_EAX );
2754 sh4_x86.fpuen_checked = FALSE;
2755 sh4_x86.tstate = TSTATE_NONE;
2756 sh4_x86.sh4_mode = SH4_MODE_UNKNOWN;
2762 load_reg( REG_EAX, Rm );
2763 MOVL_r32_rbpdisp( REG_EAX, R_GBR );
2768 load_reg( REG_EAX, Rm );
2769 MOVL_r32_rbpdisp( REG_EAX, R_VBR );
2770 sh4_x86.tstate = TSTATE_NONE;
2775 load_reg( REG_EAX, Rm );
2776 MOVL_r32_rbpdisp( REG_EAX, R_SSR );
2777 sh4_x86.tstate = TSTATE_NONE;
2782 load_reg( REG_EAX, Rm );
2783 MOVL_r32_rbpdisp( REG_EAX, R_SGR );
2784 sh4_x86.tstate = TSTATE_NONE;
2789 load_reg( REG_EAX, Rm );
2790 MOVL_r32_rbpdisp( REG_EAX, R_SPC );
2791 sh4_x86.tstate = TSTATE_NONE;
2796 load_reg( REG_EAX, Rm );
2797 MOVL_r32_rbpdisp( REG_EAX, R_DBR );
2798 sh4_x86.tstate = TSTATE_NONE;
2803 load_reg( REG_EAX, Rm );
2804 MOVL_r32_rbpdisp( REG_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
2805 sh4_x86.tstate = TSTATE_NONE;
2809 load_reg( REG_EAX, Rm );
2810 check_ralign32( REG_EAX );
2811 MEM_READ_LONG( REG_EAX, REG_EAX );
2812 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2813 MOVL_r32_rbpdisp( REG_EAX, R_GBR );
2814 sh4_x86.tstate = TSTATE_NONE;
2817 COUNT_INST(I_LDCSRM);
2818 if( sh4_x86.in_delay_slot ) {
2822 load_reg( REG_EAX, Rm );
2823 check_ralign32( REG_EAX );
2824 MEM_READ_LONG( REG_EAX, REG_EAX );
2825 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2826 CALL1_ptr_r32( sh4_write_sr, REG_EAX );
2827 sh4_x86.fpuen_checked = FALSE;
2828 sh4_x86.tstate = TSTATE_NONE;
2829 sh4_x86.sh4_mode = SH4_MODE_UNKNOWN;
2836 load_reg( REG_EAX, Rm );
2837 check_ralign32( REG_EAX );
2838 MEM_READ_LONG( REG_EAX, REG_EAX );
2839 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2840 MOVL_r32_rbpdisp( REG_EAX, R_VBR );
2841 sh4_x86.tstate = TSTATE_NONE;
2846 load_reg( REG_EAX, Rm );
2847 check_ralign32( REG_EAX );
2848 MEM_READ_LONG( REG_EAX, REG_EAX );
2849 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2850 MOVL_r32_rbpdisp( REG_EAX, R_SSR );
2851 sh4_x86.tstate = TSTATE_NONE;
2856 load_reg( REG_EAX, Rm );
2857 check_ralign32( REG_EAX );
2858 MEM_READ_LONG( REG_EAX, REG_EAX );
2859 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2860 MOVL_r32_rbpdisp( REG_EAX, R_SGR );
2861 sh4_x86.tstate = TSTATE_NONE;
2866 load_reg( REG_EAX, Rm );
2867 check_ralign32( REG_EAX );
2868 MEM_READ_LONG( REG_EAX, REG_EAX );
2869 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2870 MOVL_r32_rbpdisp( REG_EAX, R_SPC );
2871 sh4_x86.tstate = TSTATE_NONE;
2876 load_reg( REG_EAX, Rm );
2877 check_ralign32( REG_EAX );
2878 MEM_READ_LONG( REG_EAX, REG_EAX );
2879 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2880 MOVL_r32_rbpdisp( REG_EAX, R_DBR );
2881 sh4_x86.tstate = TSTATE_NONE;
2883 LDC.L @Rm+, Rn_BANK {:
2886 load_reg( REG_EAX, Rm );
2887 check_ralign32( REG_EAX );
2888 MEM_READ_LONG( REG_EAX, REG_EAX );
2889 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2890 MOVL_r32_rbpdisp( REG_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
2891 sh4_x86.tstate = TSTATE_NONE;
2894 COUNT_INST(I_LDSFPSCR);
2896 load_reg( REG_EAX, Rm );
2897 CALL1_ptr_r32( sh4_write_fpscr, REG_EAX );
2898 sh4_x86.tstate = TSTATE_NONE;
2899 sh4_x86.sh4_mode = SH4_MODE_UNKNOWN;
2902 LDS.L @Rm+, FPSCR {:
2903 COUNT_INST(I_LDSFPSCRM);
2905 load_reg( REG_EAX, Rm );
2906 check_ralign32( REG_EAX );
2907 MEM_READ_LONG( REG_EAX, REG_EAX );
2908 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2909 CALL1_ptr_r32( sh4_write_fpscr, REG_EAX );
2910 sh4_x86.tstate = TSTATE_NONE;
2911 sh4_x86.sh4_mode = SH4_MODE_UNKNOWN;
2917 load_reg( REG_EAX, Rm );
2918 MOVL_r32_rbpdisp( REG_EAX, R_FPUL );
2923 load_reg( REG_EAX, Rm );
2924 check_ralign32( REG_EAX );
2925 MEM_READ_LONG( REG_EAX, REG_EAX );
2926 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2927 MOVL_r32_rbpdisp( REG_EAX, R_FPUL );
2928 sh4_x86.tstate = TSTATE_NONE;
2932 load_reg( REG_EAX, Rm );
2933 MOVL_r32_rbpdisp( REG_EAX, R_MACH );
2937 load_reg( REG_EAX, Rm );
2938 check_ralign32( REG_EAX );
2939 MEM_READ_LONG( REG_EAX, REG_EAX );
2940 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2941 MOVL_r32_rbpdisp( REG_EAX, R_MACH );
2942 sh4_x86.tstate = TSTATE_NONE;
2946 load_reg( REG_EAX, Rm );
2947 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
2951 load_reg( REG_EAX, Rm );
2952 check_ralign32( REG_EAX );
2953 MEM_READ_LONG( REG_EAX, REG_EAX );
2954 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2955 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
2956 sh4_x86.tstate = TSTATE_NONE;
2960 load_reg( REG_EAX, Rm );
2961 MOVL_r32_rbpdisp( REG_EAX, R_PR );
2965 load_reg( REG_EAX, Rm );
2966 check_ralign32( REG_EAX );
2967 MEM_READ_LONG( REG_EAX, REG_EAX );
2968 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2969 MOVL_r32_rbpdisp( REG_EAX, R_PR );
2970 sh4_x86.tstate = TSTATE_NONE;
2973 COUNT_INST(I_LDTLB);
2974 CALL_ptr( MMU_ldtlb );
2975 sh4_x86.tstate = TSTATE_NONE;
2984 COUNT_INST(I_OCBWB);
2988 load_reg( REG_EAX, Rn );
2989 MEM_PREFETCH( REG_EAX );
2990 sh4_x86.tstate = TSTATE_NONE;
2993 COUNT_INST(I_SLEEP);
2995 CALL_ptr( sh4_sleep );
2996 sh4_x86.tstate = TSTATE_NONE;
2997 sh4_x86.in_delay_slot = DELAY_NONE;
3001 COUNT_INST(I_STCSR);
3003 CALL_ptr(sh4_read_sr);
3004 store_reg( REG_EAX, Rn );
3005 sh4_x86.tstate = TSTATE_NONE;
3009 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
3010 store_reg( REG_EAX, Rn );
3015 MOVL_rbpdisp_r32( R_VBR, REG_EAX );
3016 store_reg( REG_EAX, Rn );
3017 sh4_x86.tstate = TSTATE_NONE;
3022 MOVL_rbpdisp_r32( R_SSR, REG_EAX );
3023 store_reg( REG_EAX, Rn );
3024 sh4_x86.tstate = TSTATE_NONE;
3029 MOVL_rbpdisp_r32( R_SPC, REG_EAX );
3030 store_reg( REG_EAX, Rn );
3031 sh4_x86.tstate = TSTATE_NONE;
3036 MOVL_rbpdisp_r32( R_SGR, REG_EAX );
3037 store_reg( REG_EAX, Rn );
3038 sh4_x86.tstate = TSTATE_NONE;
3043 MOVL_rbpdisp_r32( R_DBR, REG_EAX );
3044 store_reg( REG_EAX, Rn );
3045 sh4_x86.tstate = TSTATE_NONE;
3050 MOVL_rbpdisp_r32( REG_OFFSET(r_bank[Rm_BANK]), REG_EAX );
3051 store_reg( REG_EAX, Rn );
3052 sh4_x86.tstate = TSTATE_NONE;
3055 COUNT_INST(I_STCSRM);
3057 CALL_ptr( sh4_read_sr );
3058 MOVL_r32_r32( REG_EAX, REG_EDX );
3059 load_reg( REG_EAX, Rn );
3060 check_walign32( REG_EAX );
3061 LEAL_r32disp_r32( REG_EAX, -4, REG_EAX );
3062 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3063 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3064 sh4_x86.tstate = TSTATE_NONE;
3069 load_reg( REG_EAX, Rn );
3070 check_walign32( REG_EAX );
3071 ADDL_imms_r32( -4, REG_EAX );
3072 MOVL_rbpdisp_r32( R_VBR, REG_EDX );
3073 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3074 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3075 sh4_x86.tstate = TSTATE_NONE;
3080 load_reg( REG_EAX, Rn );
3081 check_walign32( REG_EAX );
3082 ADDL_imms_r32( -4, REG_EAX );
3083 MOVL_rbpdisp_r32( R_SSR, REG_EDX );
3084 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3085 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3086 sh4_x86.tstate = TSTATE_NONE;
3091 load_reg( REG_EAX, Rn );
3092 check_walign32( REG_EAX );
3093 ADDL_imms_r32( -4, REG_EAX );
3094 MOVL_rbpdisp_r32( R_SPC, REG_EDX );
3095 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3096 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3097 sh4_x86.tstate = TSTATE_NONE;
3102 load_reg( REG_EAX, Rn );
3103 check_walign32( REG_EAX );
3104 ADDL_imms_r32( -4, REG_EAX );
3105 MOVL_rbpdisp_r32( R_SGR, REG_EDX );
3106 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3107 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3108 sh4_x86.tstate = TSTATE_NONE;
3113 load_reg( REG_EAX, Rn );
3114 check_walign32( REG_EAX );
3115 ADDL_imms_r32( -4, REG_EAX );
3116 MOVL_rbpdisp_r32( R_DBR, REG_EDX );
3117 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3118 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3119 sh4_x86.tstate = TSTATE_NONE;
3121 STC.L Rm_BANK, @-Rn {:
3124 load_reg( REG_EAX, Rn );
3125 check_walign32( REG_EAX );
3126 ADDL_imms_r32( -4, REG_EAX );
3127 MOVL_rbpdisp_r32( REG_OFFSET(r_bank[Rm_BANK]), REG_EDX );
3128 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3129 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3130 sh4_x86.tstate = TSTATE_NONE;
3134 load_reg( REG_EAX, Rn );
3135 check_walign32( REG_EAX );
3136 ADDL_imms_r32( -4, REG_EAX );
3137 MOVL_rbpdisp_r32( R_GBR, REG_EDX );
3138 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3139 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3140 sh4_x86.tstate = TSTATE_NONE;
3143 COUNT_INST(I_STSFPSCR);
3145 MOVL_rbpdisp_r32( R_FPSCR, REG_EAX );
3146 store_reg( REG_EAX, Rn );
3148 STS.L FPSCR, @-Rn {:
3149 COUNT_INST(I_STSFPSCRM);
3151 load_reg( REG_EAX, Rn );
3152 check_walign32( REG_EAX );
3153 ADDL_imms_r32( -4, REG_EAX );
3154 MOVL_rbpdisp_r32( R_FPSCR, REG_EDX );
3155 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3156 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3157 sh4_x86.tstate = TSTATE_NONE;
3162 MOVL_rbpdisp_r32( R_FPUL, REG_EAX );
3163 store_reg( REG_EAX, Rn );
3168 load_reg( REG_EAX, Rn );
3169 check_walign32( REG_EAX );
3170 ADDL_imms_r32( -4, REG_EAX );
3171 MOVL_rbpdisp_r32( R_FPUL, REG_EDX );
3172 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3173 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3174 sh4_x86.tstate = TSTATE_NONE;
3178 MOVL_rbpdisp_r32( R_MACH, REG_EAX );
3179 store_reg( REG_EAX, Rn );
3183 load_reg( REG_EAX, Rn );
3184 check_walign32( REG_EAX );
3185 ADDL_imms_r32( -4, REG_EAX );
3186 MOVL_rbpdisp_r32( R_MACH, REG_EDX );
3187 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3188 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3189 sh4_x86.tstate = TSTATE_NONE;
3193 MOVL_rbpdisp_r32( R_MACL, REG_EAX );
3194 store_reg( REG_EAX, Rn );
3198 load_reg( REG_EAX, Rn );
3199 check_walign32( REG_EAX );
3200 ADDL_imms_r32( -4, REG_EAX );
3201 MOVL_rbpdisp_r32( R_MACL, REG_EDX );
3202 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3203 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3204 sh4_x86.tstate = TSTATE_NONE;
3208 MOVL_rbpdisp_r32( R_PR, REG_EAX );
3209 store_reg( REG_EAX, Rn );
3213 load_reg( REG_EAX, Rn );
3214 check_walign32( REG_EAX );
3215 ADDL_imms_r32( -4, REG_EAX );
3216 MOVL_rbpdisp_r32( R_PR, REG_EDX );
3217 MEM_WRITE_LONG( REG_EAX, REG_EDX );
3218 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
3219 sh4_x86.tstate = TSTATE_NONE;
3224 /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */
3227 sh4_x86.in_delay_slot = DELAY_NONE;
3233 * The unwind methods only work if we compiled with DWARF2 frame information
3234 * (ie -fexceptions), otherwise we have to use the direct frame scan.
3236 #ifdef HAVE_EXCEPTIONS
3240 uintptr_t block_start;
3241 uintptr_t block_end;
3245 static _Unwind_Reason_Code xlat_check_frame( struct _Unwind_Context *context, void *arg )
3247 struct UnwindInfo *info = arg;
3248 void *pc = (void *)_Unwind_GetIP(context);
3249 if( ((uintptr_t)pc) >= info->block_start && ((uintptr_t)pc) < info->block_end ) {
3251 return _URC_NORMAL_STOP;
3253 return _URC_NO_REASON;
3256 void *xlat_get_native_pc( void *code, uint32_t code_size )
3258 struct _Unwind_Exception exc;
3259 struct UnwindInfo info;
3262 info.block_start = (uintptr_t)code;
3263 info.block_end = info.block_start + code_size;
3264 void *result = NULL;
3265 _Unwind_Backtrace( xlat_check_frame, &info );
3269 /* Assume this is an ia32 build - amd64 should always have dwarf information */
3270 void *xlat_get_native_pc( void *code, uint32_t code_size )
3272 void *result = NULL;
3274 "mov %%ebp, %%eax\n\t"
3275 "mov $0x8, %%ecx\n\t"
3277 "frame_loop: test %%eax, %%eax\n\t"
3278 "je frame_not_found\n\t"
3279 "cmp (%%eax), %%edx\n\t"
3280 "je frame_found\n\t"
3281 "sub $0x1, %%ecx\n\t"
3282 "je frame_not_found\n\t"
3283 "movl (%%eax), %%eax\n\t"
3285 "frame_found: movl 0x4(%%eax), %0\n"
3288 : "r" (((uint8_t *)&sh4r) + 128 )
3289 : "eax", "ecx", "edx" );
.