filename | src/sh4/sh4x86.in |
changeset | 1067:d3c00ffccfcd |
prev | 1065:bc1cc0c54917 |
prev | 946:d41ee7994db7 |
next | 1091:186558374345 |
author | nkeynes |
date | Sun Jul 05 13:54:48 2009 +1000 (14 years ago) |
permissions | -rw-r--r-- |
last change | No-op merge lxdream-mem to tip to remove head (Long since merged in actuality) |
view | annotate | diff | log | raw |
1 /**
2 * $Id$
3 *
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.
7 *
8 * Copyright (c) 2007 Nathan Keynes.
9 *
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.
14 *
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.
19 */
21 #include <assert.h>
22 #include <math.h>
24 #ifndef NDEBUG
25 #define DEBUG_JUMPS 1
26 #endif
28 #include "lxdream.h"
29 #include "sh4/sh4core.h"
30 #include "sh4/sh4trans.h"
31 #include "sh4/sh4stat.h"
32 #include "sh4/sh4mmio.h"
33 #include "sh4/mmu.h"
34 #include "xlat/xltcache.h"
35 #include "xlat/x86/x86op.h"
36 #include "clock.h"
38 #define DEFAULT_BACKPATCH_SIZE 4096
40 /* Offset of a reg relative to the sh4r structure */
41 #define REG_OFFSET(reg) (((char *)&sh4r.reg) - ((char *)&sh4r) - 128)
43 #define R_T REG_OFFSET(t)
44 #define R_Q REG_OFFSET(q)
45 #define R_S REG_OFFSET(s)
46 #define R_M REG_OFFSET(m)
47 #define R_SR REG_OFFSET(sr)
48 #define R_GBR REG_OFFSET(gbr)
49 #define R_SSR REG_OFFSET(ssr)
50 #define R_SPC REG_OFFSET(spc)
51 #define R_VBR REG_OFFSET(vbr)
52 #define R_MACH REG_OFFSET(mac)+4
53 #define R_MACL REG_OFFSET(mac)
54 #define R_PC REG_OFFSET(pc)
55 #define R_NEW_PC REG_OFFSET(new_pc)
56 #define R_PR REG_OFFSET(pr)
57 #define R_SGR REG_OFFSET(sgr)
58 #define R_FPUL REG_OFFSET(fpul)
59 #define R_FPSCR REG_OFFSET(fpscr)
60 #define R_DBR REG_OFFSET(dbr)
61 #define R_R(rn) REG_OFFSET(r[rn])
62 #define R_FR(f) REG_OFFSET(fr[0][(f)^1])
63 #define R_XF(f) REG_OFFSET(fr[1][(f)^1])
64 #define R_DR(f) REG_OFFSET(fr[(f)&1][(f)&0x0E])
65 #define R_DRL(f) REG_OFFSET(fr[(f)&1][(f)|0x01])
66 #define R_DRH(f) REG_OFFSET(fr[(f)&1][(f)&0x0E])
68 #define DELAY_NONE 0
69 #define DELAY_PC 1
70 #define DELAY_PC_PR 2
72 struct backpatch_record {
73 uint32_t fixup_offset;
74 uint32_t fixup_icount;
75 int32_t exc_code;
76 };
78 /**
79 * Struct to manage internal translation state. This state is not saved -
80 * it is only valid between calls to sh4_translate_begin_block() and
81 * sh4_translate_end_block()
82 */
83 struct sh4_x86_state {
84 int in_delay_slot;
85 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
86 gboolean branch_taken; /* true if we branched unconditionally */
87 gboolean double_prec; /* true if FPU is in double-precision mode */
88 gboolean double_size; /* true if FPU is in double-size mode */
89 gboolean sse3_enabled; /* true if host supports SSE3 instructions */
90 uint32_t block_start_pc;
91 uint32_t stack_posn; /* Trace stack height for alignment purposes */
92 int tstate;
94 /* mode flags */
95 gboolean tlb_on; /* True if tlb translation is active */
97 /* Allocated memory for the (block-wide) back-patch list */
98 struct backpatch_record *backpatch_list;
99 uint32_t backpatch_posn;
100 uint32_t backpatch_size;
101 };
103 static struct sh4_x86_state sh4_x86;
105 static uint32_t max_int = 0x7FFFFFFF;
106 static uint32_t min_int = 0x80000000;
107 static uint32_t save_fcw; /* save value for fpu control word */
108 static uint32_t trunc_fcw = 0x0F7F; /* fcw value for truncation mode */
110 gboolean is_sse3_supported()
111 {
112 uint32_t features;
114 __asm__ __volatile__(
115 "mov $0x01, %%eax\n\t"
116 "cpuid\n\t" : "=c" (features) : : "eax", "edx", "ebx");
117 return (features & 1) ? TRUE : FALSE;
118 }
120 void sh4_translate_init(void)
121 {
122 sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
123 sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(struct backpatch_record);
124 sh4_x86.sse3_enabled = is_sse3_supported();
125 }
128 static void sh4_x86_add_backpatch( uint8_t *fixup_addr, uint32_t fixup_pc, uint32_t exc_code )
129 {
130 int reloc_size = 4;
132 if( exc_code == -2 ) {
133 reloc_size = sizeof(void *);
134 }
136 if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
137 sh4_x86.backpatch_size <<= 1;
138 sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list,
139 sh4_x86.backpatch_size * sizeof(struct backpatch_record));
140 assert( sh4_x86.backpatch_list != NULL );
141 }
142 if( sh4_x86.in_delay_slot ) {
143 fixup_pc -= 2;
144 }
146 sh4_x86.backpatch_list[sh4_x86.backpatch_posn].fixup_offset =
147 (((uint8_t *)fixup_addr) - ((uint8_t *)xlat_current_block->code)) - reloc_size;
148 sh4_x86.backpatch_list[sh4_x86.backpatch_posn].fixup_icount = (fixup_pc - sh4_x86.block_start_pc)>>1;
149 sh4_x86.backpatch_list[sh4_x86.backpatch_posn].exc_code = exc_code;
150 sh4_x86.backpatch_posn++;
151 }
153 #define TSTATE_NONE -1
154 #define TSTATE_O X86_COND_O
155 #define TSTATE_C X86_COND_C
156 #define TSTATE_E X86_COND_E
157 #define TSTATE_NE X86_COND_NE
158 #define TSTATE_G X86_COND_G
159 #define TSTATE_GE X86_COND_GE
160 #define TSTATE_A X86_COND_A
161 #define TSTATE_AE X86_COND_AE
163 #define MARK_JMP8(x) uint8_t *_mark_jmp_##x = (xlat_output-1)
164 #define JMP_TARGET(x) *_mark_jmp_##x += (xlat_output - _mark_jmp_##x)
166 /* Convenience instructions */
167 #define LDC_t() CMPB_imms_rbpdisp(1,R_T); CMC()
168 #define SETE_t() SETCCB_cc_rbpdisp(X86_COND_E,R_T)
169 #define SETA_t() SETCCB_cc_rbpdisp(X86_COND_A,R_T)
170 #define SETAE_t() SETCCB_cc_rbpdisp(X86_COND_AE,R_T)
171 #define SETG_t() SETCCB_cc_rbpdisp(X86_COND_G,R_T)
172 #define SETGE_t() SETCCB_cc_rbpdisp(X86_COND_GE,R_T)
173 #define SETC_t() SETCCB_cc_rbpdisp(X86_COND_C,R_T)
174 #define SETO_t() SETCCB_cc_rbpdisp(X86_COND_O,R_T)
175 #define SETNE_t() SETCCB_cc_rbpdisp(X86_COND_NE,R_T)
176 #define SETC_r8(r1) SETCCB_cc_r8(X86_COND_C, r1)
177 #define JAE_label(label) JCC_cc_rel8(X86_COND_AE,-1); MARK_JMP8(label)
178 #define JE_label(label) JCC_cc_rel8(X86_COND_E,-1); MARK_JMP8(label)
179 #define JGE_label(label) JCC_cc_rel8(X86_COND_GE,-1); MARK_JMP8(label)
180 #define JNA_label(label) JCC_cc_rel8(X86_COND_NA,-1); MARK_JMP8(label)
181 #define JNE_label(label) JCC_cc_rel8(X86_COND_NE,-1); MARK_JMP8(label)
182 #define JNO_label(label) JCC_cc_rel8(X86_COND_NO,-1); MARK_JMP8(label)
183 #define JS_label(label) JCC_cc_rel8(X86_COND_S,-1); MARK_JMP8(label)
184 #define JMP_label(label) JMP_rel8(-1); MARK_JMP8(label)
185 #define JNE_exc(exc) JCC_cc_rel32(X86_COND_NE,0); sh4_x86_add_backpatch(xlat_output, pc, exc)
187 /** Branch if T is set (either in the current cflags, or in sh4r.t) */
188 #define JT_label(label) if( sh4_x86.tstate == TSTATE_NONE ) { \
189 CMPL_imms_rbpdisp( 1, R_T ); sh4_x86.tstate = TSTATE_E; } \
190 JCC_cc_rel8(sh4_x86.tstate,-1); MARK_JMP8(label)
192 /** Branch if T is clear (either in the current cflags or in sh4r.t) */
193 #define JF_label(label) if( sh4_x86.tstate == TSTATE_NONE ) { \
194 CMPL_imms_rbpdisp( 1, R_T ); sh4_x86.tstate = TSTATE_E; } \
195 JCC_cc_rel8(sh4_x86.tstate^1, -1); MARK_JMP8(label)
198 #define load_reg(x86reg,sh4reg) MOVL_rbpdisp_r32( REG_OFFSET(r[sh4reg]), x86reg )
199 #define store_reg(x86reg,sh4reg) MOVL_r32_rbpdisp( x86reg, REG_OFFSET(r[sh4reg]) )
201 /**
202 * Load an FR register (single-precision floating point) into an integer x86
203 * register (eg for register-to-register moves)
204 */
205 #define load_fr(reg,frm) MOVL_rbpdisp_r32( REG_OFFSET(fr[0][(frm)^1]), reg )
206 #define load_xf(reg,frm) MOVL_rbpdisp_r32( REG_OFFSET(fr[1][(frm)^1]), reg )
208 /**
209 * Load the low half of a DR register (DR or XD) into an integer x86 register
210 */
211 #define load_dr0(reg,frm) MOVL_rbpdisp_r32( REG_OFFSET(fr[frm&1][frm|0x01]), reg )
212 #define load_dr1(reg,frm) MOVL_rbpdisp_r32( REG_OFFSET(fr[frm&1][frm&0x0E]), reg )
214 /**
215 * Store an FR register (single-precision floating point) from an integer x86+
216 * register (eg for register-to-register moves)
217 */
218 #define store_fr(reg,frm) MOVL_r32_rbpdisp( reg, REG_OFFSET(fr[0][(frm)^1]) )
219 #define store_xf(reg,frm) MOVL_r32_rbpdisp( reg, REG_OFFSET(fr[1][(frm)^1]) )
221 #define store_dr0(reg,frm) MOVL_r32_rbpdisp( reg, REG_OFFSET(fr[frm&1][frm|0x01]) )
222 #define store_dr1(reg,frm) MOVL_r32_rbpdisp( reg, REG_OFFSET(fr[frm&1][frm&0x0E]) )
225 #define push_fpul() FLDF_rbpdisp(R_FPUL)
226 #define pop_fpul() FSTPF_rbpdisp(R_FPUL)
227 #define push_fr(frm) FLDF_rbpdisp( REG_OFFSET(fr[0][(frm)^1]) )
228 #define pop_fr(frm) FSTPF_rbpdisp( REG_OFFSET(fr[0][(frm)^1]) )
229 #define push_xf(frm) FLDF_rbpdisp( REG_OFFSET(fr[1][(frm)^1]) )
230 #define pop_xf(frm) FSTPF_rbpdisp( REG_OFFSET(fr[1][(frm)^1]) )
231 #define push_dr(frm) FLDD_rbpdisp( REG_OFFSET(fr[0][(frm)&0x0E]) )
232 #define pop_dr(frm) FSTPD_rbpdisp( REG_OFFSET(fr[0][(frm)&0x0E]) )
233 #define push_xdr(frm) FLDD_rbpdisp( REG_OFFSET(fr[1][(frm)&0x0E]) )
234 #define pop_xdr(frm) FSTPD_rbpdisp( REG_OFFSET(fr[1][(frm)&0x0E]) )
236 #ifdef ENABLE_SH4STATS
237 #define COUNT_INST(id) MOVL_imm32_r32( id, REG_EAX ); CALL1_ptr_r32(sh4_stats_add, REG_EAX); sh4_x86.tstate = TSTATE_NONE
238 #else
239 #define COUNT_INST(id)
240 #endif
243 /* Exception checks - Note that all exception checks will clobber EAX */
245 #define check_priv( ) \
246 if( (sh4r.xlat_sh4_mode & SR_MD) == 0 ) { \
247 if( sh4_x86.in_delay_slot ) { \
248 exit_block_exc(EXC_SLOT_ILLEGAL, (pc-2) ); \
249 } else { \
250 exit_block_exc(EXC_ILLEGAL, pc); \
251 } \
252 sh4_x86.branch_taken = TRUE; \
253 sh4_x86.in_delay_slot = DELAY_NONE; \
254 return 2; \
255 }
257 #define check_fpuen( ) \
258 if( !sh4_x86.fpuen_checked ) {\
259 sh4_x86.fpuen_checked = TRUE;\
260 MOVL_rbpdisp_r32( R_SR, REG_EAX );\
261 ANDL_imms_r32( SR_FD, REG_EAX );\
262 if( sh4_x86.in_delay_slot ) {\
263 JNE_exc(EXC_SLOT_FPU_DISABLED);\
264 } else {\
265 JNE_exc(EXC_FPU_DISABLED);\
266 }\
267 sh4_x86.tstate = TSTATE_NONE; \
268 }
270 #define check_ralign16( x86reg ) \
271 TESTL_imms_r32( 0x00000001, x86reg ); \
272 JNE_exc(EXC_DATA_ADDR_READ)
274 #define check_walign16( x86reg ) \
275 TESTL_imms_r32( 0x00000001, x86reg ); \
276 JNE_exc(EXC_DATA_ADDR_WRITE);
278 #define check_ralign32( x86reg ) \
279 TESTL_imms_r32( 0x00000003, x86reg ); \
280 JNE_exc(EXC_DATA_ADDR_READ)
282 #define check_walign32( x86reg ) \
283 TESTL_imms_r32( 0x00000003, x86reg ); \
284 JNE_exc(EXC_DATA_ADDR_WRITE);
286 #define check_ralign64( x86reg ) \
287 TESTL_imms_r32( 0x00000007, x86reg ); \
288 JNE_exc(EXC_DATA_ADDR_READ)
290 #define check_walign64( x86reg ) \
291 TESTL_imms_r32( 0x00000007, x86reg ); \
292 JNE_exc(EXC_DATA_ADDR_WRITE);
294 #define address_space() ((sh4r.xlat_sh4_mode&SR_MD) ? (uintptr_t)sh4_address_space : (uintptr_t)sh4_user_address_space)
296 #define UNDEF(ir)
297 /* Note: For SR.MD == 1 && MMUCR.AT == 0, there are no memory exceptions, so
298 * don't waste the cycles expecting them. Otherwise we need to save the exception pointer.
299 */
300 #ifdef HAVE_FRAME_ADDRESS
301 static void call_read_func(int addr_reg, int value_reg, int offset, int pc)
302 {
303 decode_address(address_space(), addr_reg);
304 if( !sh4_x86.tlb_on && (sh4r.xlat_sh4_mode & SR_MD) ) {
305 CALL1_r32disp_r32(REG_ECX, offset, addr_reg);
306 } else {
307 if( addr_reg != REG_ARG1 ) {
308 MOVL_r32_r32( addr_reg, REG_ARG1 );
309 }
310 MOVP_immptr_rptr( 0, REG_ARG2 );
311 sh4_x86_add_backpatch( xlat_output, pc, -2 );
312 CALL2_r32disp_r32_r32(REG_ECX, offset, REG_ARG1, REG_ARG2);
313 }
314 if( value_reg != REG_RESULT1 ) {
315 MOVL_r32_r32( REG_RESULT1, value_reg );
316 }
317 }
319 static void call_write_func(int addr_reg, int value_reg, int offset, int pc)
320 {
321 decode_address(address_space(), addr_reg);
322 if( !sh4_x86.tlb_on && (sh4r.xlat_sh4_mode & SR_MD) ) {
323 CALL2_r32disp_r32_r32(REG_ECX, offset, addr_reg, value_reg);
324 } else {
325 if( value_reg != REG_ARG2 ) {
326 MOVL_r32_r32( value_reg, REG_ARG2 );
327 }
328 if( addr_reg != REG_ARG1 ) {
329 MOVL_r32_r32( addr_reg, REG_ARG1 );
330 }
331 #if MAX_REG_ARG > 2
332 MOVP_immptr_rptr( 0, REG_ARG3 );
333 sh4_x86_add_backpatch( xlat_output, pc, -2 );
334 CALL3_r32disp_r32_r32_r32(REG_ECX, offset, REG_ARG1, REG_ARG2, REG_ARG3);
335 #else
336 MOVL_imm32_rspdisp( 0, 0 );
337 sh4_x86_add_backpatch( xlat_output, pc, -2 );
338 CALL3_r32disp_r32_r32_r32(REG_ECX, offset, REG_ARG1, REG_ARG2, 0);
339 #endif
340 }
341 }
342 #else
343 static void call_read_func(int addr_reg, int value_reg, int offset, int pc)
344 {
345 decode_address(address_space(), addr_reg);
346 CALL1_r32disp_r32(REG_ECX, offset, addr_reg);
347 if( value_reg != REG_RESULT1 ) {
348 MOVL_r32_r32( REG_RESULT1, value_reg );
349 }
350 }
352 static void call_write_func(int addr_reg, int value_reg, int offset, int pc)
353 {
354 decode_address(address_space(), addr_reg);
355 CALL2_r32disp_r32_r32(REG_ECX, offset, addr_reg, value_reg);
356 }
357 #endif
359 #define MEM_REGION_PTR(name) offsetof( struct mem_region_fn, name )
360 #define MEM_READ_BYTE( addr_reg, value_reg ) call_read_func(addr_reg, value_reg, MEM_REGION_PTR(read_byte), pc)
361 #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)
362 #define MEM_READ_WORD( addr_reg, value_reg ) call_read_func(addr_reg, value_reg, MEM_REGION_PTR(read_word), pc)
363 #define MEM_READ_LONG( addr_reg, value_reg ) call_read_func(addr_reg, value_reg, MEM_REGION_PTR(read_long), pc)
364 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_write_func(addr_reg, value_reg, MEM_REGION_PTR(write_byte), pc)
365 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_write_func(addr_reg, value_reg, MEM_REGION_PTR(write_word), pc)
366 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_write_func(addr_reg, value_reg, MEM_REGION_PTR(write_long), pc)
367 #define MEM_PREFETCH( addr_reg ) call_read_func(addr_reg, REG_RESULT1, MEM_REGION_PTR(prefetch), pc)
369 #define SLOTILLEGAL() exit_block_exc(EXC_SLOT_ILLEGAL, pc-2); sh4_x86.in_delay_slot = DELAY_NONE; return 2;
371 void sh4_translate_begin_block( sh4addr_t pc )
372 {
373 enter_block();
374 MOVP_immptr_rptr( ((uint8_t *)&sh4r) + 128, REG_EBP );
375 sh4_x86.in_delay_slot = FALSE;
376 sh4_x86.fpuen_checked = FALSE;
377 sh4_x86.branch_taken = FALSE;
378 sh4_x86.backpatch_posn = 0;
379 sh4_x86.block_start_pc = pc;
380 sh4_x86.tlb_on = IS_TLB_ENABLED();
381 sh4_x86.tstate = TSTATE_NONE;
382 sh4_x86.double_prec = sh4r.fpscr & FPSCR_PR;
383 sh4_x86.double_size = sh4r.fpscr & FPSCR_SZ;
384 }
387 uint32_t sh4_translate_end_block_size()
388 {
389 if( sh4_x86.backpatch_posn <= 3 ) {
390 return EPILOGUE_SIZE + (sh4_x86.backpatch_posn*24);
391 } else {
392 return EPILOGUE_SIZE + 72 + (sh4_x86.backpatch_posn-3)*27;
393 }
394 }
397 /**
398 * Embed a breakpoint into the generated code
399 */
400 void sh4_translate_emit_breakpoint( sh4vma_t pc )
401 {
402 MOVL_imm32_r32( pc, REG_EAX );
403 CALL1_ptr_r32( sh4_translate_breakpoint_hit, REG_EAX );
404 sh4_x86.tstate = TSTATE_NONE;
405 }
408 #define UNTRANSLATABLE(pc) !IS_IN_ICACHE(pc)
410 /**
411 * Exit the block with sh4r.pc already written
412 */
413 void exit_block_pcset( sh4addr_t pc )
414 {
415 MOVL_imm32_r32( ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
416 ADDL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
417 MOVL_rbpdisp_r32( R_PC, REG_ARG1 );
418 if( sh4_x86.tlb_on ) {
419 CALL1_ptr_r32(xlat_get_code_by_vma,REG_ARG1);
420 } else {
421 CALL1_ptr_r32(xlat_get_code,REG_ARG1);
422 }
423 exit_block();
424 }
426 /**
427 * Exit the block with sh4r.new_pc written with the target pc
428 */
429 void exit_block_newpcset( sh4addr_t pc )
430 {
431 MOVL_imm32_r32( ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
432 ADDL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
433 MOVL_rbpdisp_r32( R_NEW_PC, REG_ARG1 );
434 MOVL_r32_rbpdisp( REG_ARG1, R_PC );
435 if( sh4_x86.tlb_on ) {
436 CALL1_ptr_r32(xlat_get_code_by_vma,REG_ARG1);
437 } else {
438 CALL1_ptr_r32(xlat_get_code,REG_ARG1);
439 }
440 exit_block();
441 }
444 /**
445 * Exit the block to an absolute PC
446 */
447 void exit_block_abs( sh4addr_t pc, sh4addr_t endpc )
448 {
449 MOVL_imm32_r32( pc, REG_ECX );
450 MOVL_r32_rbpdisp( REG_ECX, R_PC );
451 if( IS_IN_ICACHE(pc) ) {
452 MOVP_moffptr_rax( xlat_get_lut_entry(GET_ICACHE_PHYS(pc)) );
453 ANDP_imms_rptr( -4, REG_EAX );
454 } else if( sh4_x86.tlb_on ) {
455 CALL1_ptr_r32(xlat_get_code_by_vma, REG_ECX);
456 } else {
457 CALL1_ptr_r32(xlat_get_code, REG_ECX);
458 }
459 MOVL_imm32_r32( ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
460 ADDL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
461 exit_block();
462 }
464 /**
465 * Exit the block to a relative PC
466 */
467 void exit_block_rel( sh4addr_t pc, sh4addr_t endpc )
468 {
469 MOVL_imm32_r32( pc - sh4_x86.block_start_pc, REG_ECX );
470 ADDL_rbpdisp_r32( R_PC, REG_ECX );
471 MOVL_r32_rbpdisp( REG_ECX, R_PC );
472 if( IS_IN_ICACHE(pc) ) {
473 MOVP_moffptr_rax( xlat_get_lut_entry(GET_ICACHE_PHYS(pc)) );
474 ANDP_imms_rptr( -4, REG_EAX );
475 } else if( sh4_x86.tlb_on ) {
476 CALL1_ptr_r32(xlat_get_code_by_vma, REG_ECX);
477 } else {
478 CALL1_ptr_r32(xlat_get_code, REG_ECX);
479 }
480 MOVL_imm32_r32( ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
481 ADDL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
482 exit_block();
483 }
485 /**
486 * Exit unconditionally with a general exception
487 */
488 void exit_block_exc( int code, sh4addr_t pc )
489 {
490 MOVL_imm32_r32( pc - sh4_x86.block_start_pc, REG_ECX );
491 ADDL_r32_rbpdisp( REG_ECX, R_PC );
492 MOVL_imm32_r32( ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period, REG_ECX );
493 ADDL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) );
494 MOVL_imm32_r32( code, REG_ARG1 );
495 CALL1_ptr_r32( sh4_raise_exception, REG_ARG1 );
496 MOVL_rbpdisp_r32( R_PC, REG_ARG1 );
497 if( sh4_x86.tlb_on ) {
498 CALL1_ptr_r32(xlat_get_code_by_vma,REG_ARG1);
499 } else {
500 CALL1_ptr_r32(xlat_get_code,REG_ARG1);
501 }
503 exit_block();
504 }
506 /**
507 * Embed a call to sh4_execute_instruction for situations that we
508 * can't translate (just page-crossing delay slots at the moment).
509 * Caller is responsible for setting new_pc before calling this function.
510 *
511 * Performs:
512 * Set PC = endpc
513 * Set sh4r.in_delay_slot = sh4_x86.in_delay_slot
514 * Update slice_cycle for endpc+2 (single step doesn't update slice_cycle)
515 * Call sh4_execute_instruction
516 * Call xlat_get_code_by_vma / xlat_get_code as for normal exit
517 */
518 void exit_block_emu( sh4vma_t endpc )
519 {
520 MOVL_imm32_r32( endpc - sh4_x86.block_start_pc, REG_ECX ); // 5
521 ADDL_r32_rbpdisp( REG_ECX, R_PC );
523 MOVL_imm32_r32( (((endpc - sh4_x86.block_start_pc)>>1)+1)*sh4_cpu_period, REG_ECX ); // 5
524 ADDL_r32_rbpdisp( REG_ECX, REG_OFFSET(slice_cycle) ); // 6
525 MOVL_imm32_r32( sh4_x86.in_delay_slot ? 1 : 0, REG_ECX );
526 MOVL_r32_rbpdisp( REG_ECX, REG_OFFSET(in_delay_slot) );
528 CALL_ptr( sh4_execute_instruction );
529 MOVL_rbpdisp_r32( R_PC, REG_EAX );
530 if( sh4_x86.tlb_on ) {
531 CALL1_ptr_r32(xlat_get_code_by_vma,REG_EAX);
532 } else {
533 CALL1_ptr_r32(xlat_get_code,REG_EAX);
534 }
535 exit_block();
536 }
538 /**
539 * Write the block trailer (exception handling block)
540 */
541 void sh4_translate_end_block( sh4addr_t pc ) {
542 if( sh4_x86.branch_taken == FALSE ) {
543 // Didn't exit unconditionally already, so write the termination here
544 exit_block_rel( pc, pc );
545 }
546 if( sh4_x86.backpatch_posn != 0 ) {
547 unsigned int i;
548 // Exception raised - cleanup and exit
549 uint8_t *end_ptr = xlat_output;
550 MOVL_r32_r32( REG_EDX, REG_ECX );
551 ADDL_r32_r32( REG_EDX, REG_ECX );
552 ADDL_r32_rbpdisp( REG_ECX, R_SPC );
553 MOVL_moffptr_eax( &sh4_cpu_period );
554 MULL_r32( REG_EDX );
555 ADDL_r32_rbpdisp( REG_EAX, REG_OFFSET(slice_cycle) );
556 MOVL_rbpdisp_r32( R_PC, REG_ARG1 );
557 if( sh4_x86.tlb_on ) {
558 CALL1_ptr_r32(xlat_get_code_by_vma, REG_ARG1);
559 } else {
560 CALL1_ptr_r32(xlat_get_code, REG_ARG1);
561 }
562 exit_block();
564 for( i=0; i< sh4_x86.backpatch_posn; i++ ) {
565 uint32_t *fixup_addr = (uint32_t *)&xlat_current_block->code[sh4_x86.backpatch_list[i].fixup_offset];
566 if( sh4_x86.backpatch_list[i].exc_code < 0 ) {
567 if( sh4_x86.backpatch_list[i].exc_code == -2 ) {
568 *((uintptr_t *)fixup_addr) = (uintptr_t)xlat_output;
569 } else {
570 *fixup_addr += xlat_output - (uint8_t *)&xlat_current_block->code[sh4_x86.backpatch_list[i].fixup_offset] - 4;
571 }
572 MOVL_imm32_r32( sh4_x86.backpatch_list[i].fixup_icount, REG_EDX );
573 int rel = end_ptr - xlat_output;
574 JMP_prerel(rel);
575 } else {
576 *fixup_addr += xlat_output - (uint8_t *)&xlat_current_block->code[sh4_x86.backpatch_list[i].fixup_offset] - 4;
577 MOVL_imm32_r32( sh4_x86.backpatch_list[i].exc_code, REG_ARG1 );
578 CALL1_ptr_r32( sh4_raise_exception, REG_ARG1 );
579 MOVL_imm32_r32( sh4_x86.backpatch_list[i].fixup_icount, REG_EDX );
580 int rel = end_ptr - xlat_output;
581 JMP_prerel(rel);
582 }
583 }
584 }
585 }
587 /**
588 * Translate a single instruction. Delayed branches are handled specially
589 * by translating both branch and delayed instruction as a single unit (as
590 *
591 * The instruction MUST be in the icache (assert check)
592 *
593 * @return true if the instruction marks the end of a basic block
594 * (eg a branch or
595 */
596 uint32_t sh4_translate_instruction( sh4vma_t pc )
597 {
598 uint32_t ir;
599 /* Read instruction from icache */
600 assert( IS_IN_ICACHE(pc) );
601 ir = *(uint16_t *)GET_ICACHE_PTR(pc);
603 if( !sh4_x86.in_delay_slot ) {
604 sh4_translate_add_recovery( (pc - sh4_x86.block_start_pc)>>1 );
605 }
607 /* check for breakpoints at this pc */
608 for( int i=0; i<sh4_breakpoint_count; i++ ) {
609 if( sh4_breakpoints[i].address == pc ) {
610 sh4_translate_emit_breakpoint(pc);
611 break;
612 }
613 }
614 %%
615 /* ALU operations */
616 ADD Rm, Rn {:
617 COUNT_INST(I_ADD);
618 load_reg( REG_EAX, Rm );
619 load_reg( REG_ECX, Rn );
620 ADDL_r32_r32( REG_EAX, REG_ECX );
621 store_reg( REG_ECX, Rn );
622 sh4_x86.tstate = TSTATE_NONE;
623 :}
624 ADD #imm, Rn {:
625 COUNT_INST(I_ADDI);
626 ADDL_imms_rbpdisp( imm, REG_OFFSET(r[Rn]) );
627 sh4_x86.tstate = TSTATE_NONE;
628 :}
629 ADDC Rm, Rn {:
630 COUNT_INST(I_ADDC);
631 if( sh4_x86.tstate != TSTATE_C ) {
632 LDC_t();
633 }
634 load_reg( REG_EAX, Rm );
635 load_reg( REG_ECX, Rn );
636 ADCL_r32_r32( REG_EAX, REG_ECX );
637 store_reg( REG_ECX, Rn );
638 SETC_t();
639 sh4_x86.tstate = TSTATE_C;
640 :}
641 ADDV Rm, Rn {:
642 COUNT_INST(I_ADDV);
643 load_reg( REG_EAX, Rm );
644 load_reg( REG_ECX, Rn );
645 ADDL_r32_r32( REG_EAX, REG_ECX );
646 store_reg( REG_ECX, Rn );
647 SETO_t();
648 sh4_x86.tstate = TSTATE_O;
649 :}
650 AND Rm, Rn {:
651 COUNT_INST(I_AND);
652 load_reg( REG_EAX, Rm );
653 load_reg( REG_ECX, Rn );
654 ANDL_r32_r32( REG_EAX, REG_ECX );
655 store_reg( REG_ECX, Rn );
656 sh4_x86.tstate = TSTATE_NONE;
657 :}
658 AND #imm, R0 {:
659 COUNT_INST(I_ANDI);
660 load_reg( REG_EAX, 0 );
661 ANDL_imms_r32(imm, REG_EAX);
662 store_reg( REG_EAX, 0 );
663 sh4_x86.tstate = TSTATE_NONE;
664 :}
665 AND.B #imm, @(R0, GBR) {:
666 COUNT_INST(I_ANDB);
667 load_reg( REG_EAX, 0 );
668 ADDL_rbpdisp_r32( R_GBR, REG_EAX );
669 MOVL_r32_rspdisp(REG_EAX, 0);
670 MEM_READ_BYTE_FOR_WRITE( REG_EAX, REG_EDX );
671 MOVL_rspdisp_r32(0, REG_EAX);
672 ANDL_imms_r32(imm, REG_EDX );
673 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
674 sh4_x86.tstate = TSTATE_NONE;
675 :}
676 CMP/EQ Rm, Rn {:
677 COUNT_INST(I_CMPEQ);
678 load_reg( REG_EAX, Rm );
679 load_reg( REG_ECX, Rn );
680 CMPL_r32_r32( REG_EAX, REG_ECX );
681 SETE_t();
682 sh4_x86.tstate = TSTATE_E;
683 :}
684 CMP/EQ #imm, R0 {:
685 COUNT_INST(I_CMPEQI);
686 load_reg( REG_EAX, 0 );
687 CMPL_imms_r32(imm, REG_EAX);
688 SETE_t();
689 sh4_x86.tstate = TSTATE_E;
690 :}
691 CMP/GE Rm, Rn {:
692 COUNT_INST(I_CMPGE);
693 load_reg( REG_EAX, Rm );
694 load_reg( REG_ECX, Rn );
695 CMPL_r32_r32( REG_EAX, REG_ECX );
696 SETGE_t();
697 sh4_x86.tstate = TSTATE_GE;
698 :}
699 CMP/GT Rm, Rn {:
700 COUNT_INST(I_CMPGT);
701 load_reg( REG_EAX, Rm );
702 load_reg( REG_ECX, Rn );
703 CMPL_r32_r32( REG_EAX, REG_ECX );
704 SETG_t();
705 sh4_x86.tstate = TSTATE_G;
706 :}
707 CMP/HI Rm, Rn {:
708 COUNT_INST(I_CMPHI);
709 load_reg( REG_EAX, Rm );
710 load_reg( REG_ECX, Rn );
711 CMPL_r32_r32( REG_EAX, REG_ECX );
712 SETA_t();
713 sh4_x86.tstate = TSTATE_A;
714 :}
715 CMP/HS Rm, Rn {:
716 COUNT_INST(I_CMPHS);
717 load_reg( REG_EAX, Rm );
718 load_reg( REG_ECX, Rn );
719 CMPL_r32_r32( REG_EAX, REG_ECX );
720 SETAE_t();
721 sh4_x86.tstate = TSTATE_AE;
722 :}
723 CMP/PL Rn {:
724 COUNT_INST(I_CMPPL);
725 load_reg( REG_EAX, Rn );
726 CMPL_imms_r32( 0, REG_EAX );
727 SETG_t();
728 sh4_x86.tstate = TSTATE_G;
729 :}
730 CMP/PZ Rn {:
731 COUNT_INST(I_CMPPZ);
732 load_reg( REG_EAX, Rn );
733 CMPL_imms_r32( 0, REG_EAX );
734 SETGE_t();
735 sh4_x86.tstate = TSTATE_GE;
736 :}
737 CMP/STR Rm, Rn {:
738 COUNT_INST(I_CMPSTR);
739 load_reg( REG_EAX, Rm );
740 load_reg( REG_ECX, Rn );
741 XORL_r32_r32( REG_ECX, REG_EAX );
742 TESTB_r8_r8( REG_AL, REG_AL );
743 JE_label(target1);
744 TESTB_r8_r8( REG_AH, REG_AH );
745 JE_label(target2);
746 SHRL_imm_r32( 16, REG_EAX );
747 TESTB_r8_r8( REG_AL, REG_AL );
748 JE_label(target3);
749 TESTB_r8_r8( REG_AH, REG_AH );
750 JMP_TARGET(target1);
751 JMP_TARGET(target2);
752 JMP_TARGET(target3);
753 SETE_t();
754 sh4_x86.tstate = TSTATE_E;
755 :}
756 DIV0S Rm, Rn {:
757 COUNT_INST(I_DIV0S);
758 load_reg( REG_EAX, Rm );
759 load_reg( REG_ECX, Rn );
760 SHRL_imm_r32( 31, REG_EAX );
761 SHRL_imm_r32( 31, REG_ECX );
762 MOVL_r32_rbpdisp( REG_EAX, R_M );
763 MOVL_r32_rbpdisp( REG_ECX, R_Q );
764 CMPL_r32_r32( REG_EAX, REG_ECX );
765 SETNE_t();
766 sh4_x86.tstate = TSTATE_NE;
767 :}
768 DIV0U {:
769 COUNT_INST(I_DIV0U);
770 XORL_r32_r32( REG_EAX, REG_EAX );
771 MOVL_r32_rbpdisp( REG_EAX, R_Q );
772 MOVL_r32_rbpdisp( REG_EAX, R_M );
773 MOVL_r32_rbpdisp( REG_EAX, R_T );
774 sh4_x86.tstate = TSTATE_C; // works for DIV1
775 :}
776 DIV1 Rm, Rn {:
777 COUNT_INST(I_DIV1);
778 MOVL_rbpdisp_r32( R_M, REG_ECX );
779 load_reg( REG_EAX, Rn );
780 if( sh4_x86.tstate != TSTATE_C ) {
781 LDC_t();
782 }
783 RCLL_imm_r32( 1, REG_EAX );
784 SETC_r8( REG_DL ); // Q'
785 CMPL_rbpdisp_r32( R_Q, REG_ECX );
786 JE_label(mqequal);
787 ADDL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
788 JMP_label(end);
789 JMP_TARGET(mqequal);
790 SUBL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
791 JMP_TARGET(end);
792 store_reg( REG_EAX, Rn ); // Done with Rn now
793 SETC_r8(REG_AL); // tmp1
794 XORB_r8_r8( REG_DL, REG_AL ); // Q' = Q ^ tmp1
795 XORB_r8_r8( REG_AL, REG_CL ); // Q'' = Q' ^ M
796 MOVL_r32_rbpdisp( REG_ECX, R_Q );
797 XORL_imms_r32( 1, REG_AL ); // T = !Q'
798 MOVZXL_r8_r32( REG_AL, REG_EAX );
799 MOVL_r32_rbpdisp( REG_EAX, R_T );
800 sh4_x86.tstate = TSTATE_NONE;
801 :}
802 DMULS.L Rm, Rn {:
803 COUNT_INST(I_DMULS);
804 load_reg( REG_EAX, Rm );
805 load_reg( REG_ECX, Rn );
806 IMULL_r32(REG_ECX);
807 MOVL_r32_rbpdisp( REG_EDX, R_MACH );
808 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
809 sh4_x86.tstate = TSTATE_NONE;
810 :}
811 DMULU.L Rm, Rn {:
812 COUNT_INST(I_DMULU);
813 load_reg( REG_EAX, Rm );
814 load_reg( REG_ECX, Rn );
815 MULL_r32(REG_ECX);
816 MOVL_r32_rbpdisp( REG_EDX, R_MACH );
817 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
818 sh4_x86.tstate = TSTATE_NONE;
819 :}
820 DT Rn {:
821 COUNT_INST(I_DT);
822 load_reg( REG_EAX, Rn );
823 ADDL_imms_r32( -1, REG_EAX );
824 store_reg( REG_EAX, Rn );
825 SETE_t();
826 sh4_x86.tstate = TSTATE_E;
827 :}
828 EXTS.B Rm, Rn {:
829 COUNT_INST(I_EXTSB);
830 load_reg( REG_EAX, Rm );
831 MOVSXL_r8_r32( REG_EAX, REG_EAX );
832 store_reg( REG_EAX, Rn );
833 :}
834 EXTS.W Rm, Rn {:
835 COUNT_INST(I_EXTSW);
836 load_reg( REG_EAX, Rm );
837 MOVSXL_r16_r32( REG_EAX, REG_EAX );
838 store_reg( REG_EAX, Rn );
839 :}
840 EXTU.B Rm, Rn {:
841 COUNT_INST(I_EXTUB);
842 load_reg( REG_EAX, Rm );
843 MOVZXL_r8_r32( REG_EAX, REG_EAX );
844 store_reg( REG_EAX, Rn );
845 :}
846 EXTU.W Rm, Rn {:
847 COUNT_INST(I_EXTUW);
848 load_reg( REG_EAX, Rm );
849 MOVZXL_r16_r32( REG_EAX, REG_EAX );
850 store_reg( REG_EAX, Rn );
851 :}
852 MAC.L @Rm+, @Rn+ {:
853 COUNT_INST(I_MACL);
854 if( Rm == Rn ) {
855 load_reg( REG_EAX, Rm );
856 check_ralign32( REG_EAX );
857 MEM_READ_LONG( REG_EAX, REG_EAX );
858 MOVL_r32_rspdisp(REG_EAX, 0);
859 load_reg( REG_EAX, Rm );
860 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
861 MEM_READ_LONG( REG_EAX, REG_EAX );
862 ADDL_imms_rbpdisp( 8, REG_OFFSET(r[Rn]) );
863 } else {
864 load_reg( REG_EAX, Rm );
865 check_ralign32( REG_EAX );
866 MEM_READ_LONG( REG_EAX, REG_EAX );
867 MOVL_r32_rspdisp( REG_EAX, 0 );
868 load_reg( REG_EAX, Rn );
869 check_ralign32( REG_EAX );
870 MEM_READ_LONG( REG_EAX, REG_EAX );
871 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rn]) );
872 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
873 }
875 IMULL_rspdisp( 0 );
876 ADDL_r32_rbpdisp( REG_EAX, R_MACL );
877 ADCL_r32_rbpdisp( REG_EDX, R_MACH );
879 MOVL_rbpdisp_r32( R_S, REG_ECX );
880 TESTL_r32_r32(REG_ECX, REG_ECX);
881 JE_label( nosat );
882 CALL_ptr( signsat48 );
883 JMP_TARGET( nosat );
884 sh4_x86.tstate = TSTATE_NONE;
885 :}
886 MAC.W @Rm+, @Rn+ {:
887 COUNT_INST(I_MACW);
888 if( Rm == Rn ) {
889 load_reg( REG_EAX, Rm );
890 check_ralign16( REG_EAX );
891 MEM_READ_WORD( REG_EAX, REG_EAX );
892 MOVL_r32_rspdisp( REG_EAX, 0 );
893 load_reg( REG_EAX, Rm );
894 LEAL_r32disp_r32( REG_EAX, 2, REG_EAX );
895 MEM_READ_WORD( REG_EAX, REG_EAX );
896 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rn]) );
897 // Note translate twice in case of page boundaries. Maybe worth
898 // adding a page-boundary check to skip the second translation
899 } else {
900 load_reg( REG_EAX, Rm );
901 check_ralign16( REG_EAX );
902 MEM_READ_WORD( REG_EAX, REG_EAX );
903 MOVL_r32_rspdisp( REG_EAX, 0 );
904 load_reg( REG_EAX, Rn );
905 check_ralign16( REG_EAX );
906 MEM_READ_WORD( REG_EAX, REG_EAX );
907 ADDL_imms_rbpdisp( 2, REG_OFFSET(r[Rn]) );
908 ADDL_imms_rbpdisp( 2, REG_OFFSET(r[Rm]) );
909 }
910 IMULL_rspdisp( 0 );
911 MOVL_rbpdisp_r32( R_S, REG_ECX );
912 TESTL_r32_r32( REG_ECX, REG_ECX );
913 JE_label( nosat );
915 ADDL_r32_rbpdisp( REG_EAX, R_MACL ); // 6
916 JNO_label( end ); // 2
917 MOVL_imm32_r32( 1, REG_EDX ); // 5
918 MOVL_r32_rbpdisp( REG_EDX, R_MACH ); // 6
919 JS_label( positive ); // 2
920 MOVL_imm32_r32( 0x80000000, REG_EAX );// 5
921 MOVL_r32_rbpdisp( REG_EAX, R_MACL ); // 6
922 JMP_label(end2); // 2
924 JMP_TARGET(positive);
925 MOVL_imm32_r32( 0x7FFFFFFF, REG_EAX );// 5
926 MOVL_r32_rbpdisp( REG_EAX, R_MACL ); // 6
927 JMP_label(end3); // 2
929 JMP_TARGET(nosat);
930 ADDL_r32_rbpdisp( REG_EAX, R_MACL ); // 6
931 ADCL_r32_rbpdisp( REG_EDX, R_MACH ); // 6
932 JMP_TARGET(end);
933 JMP_TARGET(end2);
934 JMP_TARGET(end3);
935 sh4_x86.tstate = TSTATE_NONE;
936 :}
937 MOVT Rn {:
938 COUNT_INST(I_MOVT);
939 MOVL_rbpdisp_r32( R_T, REG_EAX );
940 store_reg( REG_EAX, Rn );
941 :}
942 MUL.L Rm, Rn {:
943 COUNT_INST(I_MULL);
944 load_reg( REG_EAX, Rm );
945 load_reg( REG_ECX, Rn );
946 MULL_r32( REG_ECX );
947 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
948 sh4_x86.tstate = TSTATE_NONE;
949 :}
950 MULS.W Rm, Rn {:
951 COUNT_INST(I_MULSW);
952 MOVSXL_rbpdisp16_r32( R_R(Rm), REG_EAX );
953 MOVSXL_rbpdisp16_r32( R_R(Rn), REG_ECX );
954 MULL_r32( REG_ECX );
955 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
956 sh4_x86.tstate = TSTATE_NONE;
957 :}
958 MULU.W Rm, Rn {:
959 COUNT_INST(I_MULUW);
960 MOVZXL_rbpdisp16_r32( R_R(Rm), REG_EAX );
961 MOVZXL_rbpdisp16_r32( R_R(Rn), REG_ECX );
962 MULL_r32( REG_ECX );
963 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
964 sh4_x86.tstate = TSTATE_NONE;
965 :}
966 NEG Rm, Rn {:
967 COUNT_INST(I_NEG);
968 load_reg( REG_EAX, Rm );
969 NEGL_r32( REG_EAX );
970 store_reg( REG_EAX, Rn );
971 sh4_x86.tstate = TSTATE_NONE;
972 :}
973 NEGC Rm, Rn {:
974 COUNT_INST(I_NEGC);
975 load_reg( REG_EAX, Rm );
976 XORL_r32_r32( REG_ECX, REG_ECX );
977 LDC_t();
978 SBBL_r32_r32( REG_EAX, REG_ECX );
979 store_reg( REG_ECX, Rn );
980 SETC_t();
981 sh4_x86.tstate = TSTATE_C;
982 :}
983 NOT Rm, Rn {:
984 COUNT_INST(I_NOT);
985 load_reg( REG_EAX, Rm );
986 NOTL_r32( REG_EAX );
987 store_reg( REG_EAX, Rn );
988 sh4_x86.tstate = TSTATE_NONE;
989 :}
990 OR Rm, Rn {:
991 COUNT_INST(I_OR);
992 load_reg( REG_EAX, Rm );
993 load_reg( REG_ECX, Rn );
994 ORL_r32_r32( REG_EAX, REG_ECX );
995 store_reg( REG_ECX, Rn );
996 sh4_x86.tstate = TSTATE_NONE;
997 :}
998 OR #imm, R0 {:
999 COUNT_INST(I_ORI);
1000 load_reg( REG_EAX, 0 );
1001 ORL_imms_r32(imm, REG_EAX);
1002 store_reg( REG_EAX, 0 );
1003 sh4_x86.tstate = TSTATE_NONE;
1004 :}
1005 OR.B #imm, @(R0, GBR) {:
1006 COUNT_INST(I_ORB);
1007 load_reg( REG_EAX, 0 );
1008 ADDL_rbpdisp_r32( R_GBR, REG_EAX );
1009 MOVL_r32_rspdisp( REG_EAX, 0 );
1010 MEM_READ_BYTE_FOR_WRITE( REG_EAX, REG_EDX );
1011 MOVL_rspdisp_r32( 0, REG_EAX );
1012 ORL_imms_r32(imm, REG_EDX );
1013 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1014 sh4_x86.tstate = TSTATE_NONE;
1015 :}
1016 ROTCL Rn {:
1017 COUNT_INST(I_ROTCL);
1018 load_reg( REG_EAX, Rn );
1019 if( sh4_x86.tstate != TSTATE_C ) {
1020 LDC_t();
1021 }
1022 RCLL_imm_r32( 1, REG_EAX );
1023 store_reg( REG_EAX, Rn );
1024 SETC_t();
1025 sh4_x86.tstate = TSTATE_C;
1026 :}
1027 ROTCR Rn {:
1028 COUNT_INST(I_ROTCR);
1029 load_reg( REG_EAX, Rn );
1030 if( sh4_x86.tstate != TSTATE_C ) {
1031 LDC_t();
1032 }
1033 RCRL_imm_r32( 1, REG_EAX );
1034 store_reg( REG_EAX, Rn );
1035 SETC_t();
1036 sh4_x86.tstate = TSTATE_C;
1037 :}
1038 ROTL Rn {:
1039 COUNT_INST(I_ROTL);
1040 load_reg( REG_EAX, Rn );
1041 ROLL_imm_r32( 1, REG_EAX );
1042 store_reg( REG_EAX, Rn );
1043 SETC_t();
1044 sh4_x86.tstate = TSTATE_C;
1045 :}
1046 ROTR Rn {:
1047 COUNT_INST(I_ROTR);
1048 load_reg( REG_EAX, Rn );
1049 RORL_imm_r32( 1, REG_EAX );
1050 store_reg( REG_EAX, Rn );
1051 SETC_t();
1052 sh4_x86.tstate = TSTATE_C;
1053 :}
1054 SHAD Rm, Rn {:
1055 COUNT_INST(I_SHAD);
1056 /* Annoyingly enough, not directly convertible */
1057 load_reg( REG_EAX, Rn );
1058 load_reg( REG_ECX, Rm );
1059 CMPL_imms_r32( 0, REG_ECX );
1060 JGE_label(doshl);
1062 NEGL_r32( REG_ECX ); // 2
1063 ANDB_imms_r8( 0x1F, REG_CL ); // 3
1064 JE_label(emptysar); // 2
1065 SARL_cl_r32( REG_EAX ); // 2
1066 JMP_label(end); // 2
1068 JMP_TARGET(emptysar);
1069 SARL_imm_r32(31, REG_EAX ); // 3
1070 JMP_label(end2);
1072 JMP_TARGET(doshl);
1073 ANDB_imms_r8( 0x1F, REG_CL ); // 3
1074 SHLL_cl_r32( REG_EAX ); // 2
1075 JMP_TARGET(end);
1076 JMP_TARGET(end2);
1077 store_reg( REG_EAX, Rn );
1078 sh4_x86.tstate = TSTATE_NONE;
1079 :}
1080 SHLD Rm, Rn {:
1081 COUNT_INST(I_SHLD);
1082 load_reg( REG_EAX, Rn );
1083 load_reg( REG_ECX, Rm );
1084 CMPL_imms_r32( 0, REG_ECX );
1085 JGE_label(doshl);
1087 NEGL_r32( REG_ECX ); // 2
1088 ANDB_imms_r8( 0x1F, REG_CL ); // 3
1089 JE_label(emptyshr );
1090 SHRL_cl_r32( REG_EAX ); // 2
1091 JMP_label(end); // 2
1093 JMP_TARGET(emptyshr);
1094 XORL_r32_r32( REG_EAX, REG_EAX );
1095 JMP_label(end2);
1097 JMP_TARGET(doshl);
1098 ANDB_imms_r8( 0x1F, REG_CL ); // 3
1099 SHLL_cl_r32( REG_EAX ); // 2
1100 JMP_TARGET(end);
1101 JMP_TARGET(end2);
1102 store_reg( REG_EAX, Rn );
1103 sh4_x86.tstate = TSTATE_NONE;
1104 :}
1105 SHAL Rn {:
1106 COUNT_INST(I_SHAL);
1107 load_reg( REG_EAX, Rn );
1108 SHLL_imm_r32( 1, REG_EAX );
1109 SETC_t();
1110 store_reg( REG_EAX, Rn );
1111 sh4_x86.tstate = TSTATE_C;
1112 :}
1113 SHAR Rn {:
1114 COUNT_INST(I_SHAR);
1115 load_reg( REG_EAX, Rn );
1116 SARL_imm_r32( 1, REG_EAX );
1117 SETC_t();
1118 store_reg( REG_EAX, Rn );
1119 sh4_x86.tstate = TSTATE_C;
1120 :}
1121 SHLL Rn {:
1122 COUNT_INST(I_SHLL);
1123 load_reg( REG_EAX, Rn );
1124 SHLL_imm_r32( 1, REG_EAX );
1125 SETC_t();
1126 store_reg( REG_EAX, Rn );
1127 sh4_x86.tstate = TSTATE_C;
1128 :}
1129 SHLL2 Rn {:
1130 COUNT_INST(I_SHLL);
1131 load_reg( REG_EAX, Rn );
1132 SHLL_imm_r32( 2, REG_EAX );
1133 store_reg( REG_EAX, Rn );
1134 sh4_x86.tstate = TSTATE_NONE;
1135 :}
1136 SHLL8 Rn {:
1137 COUNT_INST(I_SHLL);
1138 load_reg( REG_EAX, Rn );
1139 SHLL_imm_r32( 8, REG_EAX );
1140 store_reg( REG_EAX, Rn );
1141 sh4_x86.tstate = TSTATE_NONE;
1142 :}
1143 SHLL16 Rn {:
1144 COUNT_INST(I_SHLL);
1145 load_reg( REG_EAX, Rn );
1146 SHLL_imm_r32( 16, REG_EAX );
1147 store_reg( REG_EAX, Rn );
1148 sh4_x86.tstate = TSTATE_NONE;
1149 :}
1150 SHLR Rn {:
1151 COUNT_INST(I_SHLR);
1152 load_reg( REG_EAX, Rn );
1153 SHRL_imm_r32( 1, REG_EAX );
1154 SETC_t();
1155 store_reg( REG_EAX, Rn );
1156 sh4_x86.tstate = TSTATE_C;
1157 :}
1158 SHLR2 Rn {:
1159 COUNT_INST(I_SHLR);
1160 load_reg( REG_EAX, Rn );
1161 SHRL_imm_r32( 2, REG_EAX );
1162 store_reg( REG_EAX, Rn );
1163 sh4_x86.tstate = TSTATE_NONE;
1164 :}
1165 SHLR8 Rn {:
1166 COUNT_INST(I_SHLR);
1167 load_reg( REG_EAX, Rn );
1168 SHRL_imm_r32( 8, REG_EAX );
1169 store_reg( REG_EAX, Rn );
1170 sh4_x86.tstate = TSTATE_NONE;
1171 :}
1172 SHLR16 Rn {:
1173 COUNT_INST(I_SHLR);
1174 load_reg( REG_EAX, Rn );
1175 SHRL_imm_r32( 16, REG_EAX );
1176 store_reg( REG_EAX, Rn );
1177 sh4_x86.tstate = TSTATE_NONE;
1178 :}
1179 SUB Rm, Rn {:
1180 COUNT_INST(I_SUB);
1181 load_reg( REG_EAX, Rm );
1182 load_reg( REG_ECX, Rn );
1183 SUBL_r32_r32( REG_EAX, REG_ECX );
1184 store_reg( REG_ECX, Rn );
1185 sh4_x86.tstate = TSTATE_NONE;
1186 :}
1187 SUBC Rm, Rn {:
1188 COUNT_INST(I_SUBC);
1189 load_reg( REG_EAX, Rm );
1190 load_reg( REG_ECX, Rn );
1191 if( sh4_x86.tstate != TSTATE_C ) {
1192 LDC_t();
1193 }
1194 SBBL_r32_r32( REG_EAX, REG_ECX );
1195 store_reg( REG_ECX, Rn );
1196 SETC_t();
1197 sh4_x86.tstate = TSTATE_C;
1198 :}
1199 SUBV Rm, Rn {:
1200 COUNT_INST(I_SUBV);
1201 load_reg( REG_EAX, Rm );
1202 load_reg( REG_ECX, Rn );
1203 SUBL_r32_r32( REG_EAX, REG_ECX );
1204 store_reg( REG_ECX, Rn );
1205 SETO_t();
1206 sh4_x86.tstate = TSTATE_O;
1207 :}
1208 SWAP.B Rm, Rn {:
1209 COUNT_INST(I_SWAPB);
1210 load_reg( REG_EAX, Rm );
1211 XCHGB_r8_r8( REG_AL, REG_AH ); // NB: does not touch EFLAGS
1212 store_reg( REG_EAX, Rn );
1213 :}
1214 SWAP.W Rm, Rn {:
1215 COUNT_INST(I_SWAPB);
1216 load_reg( REG_EAX, Rm );
1217 MOVL_r32_r32( REG_EAX, REG_ECX );
1218 SHLL_imm_r32( 16, REG_ECX );
1219 SHRL_imm_r32( 16, REG_EAX );
1220 ORL_r32_r32( REG_EAX, REG_ECX );
1221 store_reg( REG_ECX, Rn );
1222 sh4_x86.tstate = TSTATE_NONE;
1223 :}
1224 TAS.B @Rn {:
1225 COUNT_INST(I_TASB);
1226 load_reg( REG_EAX, Rn );
1227 MOVL_r32_rspdisp( REG_EAX, 0 );
1228 MEM_READ_BYTE_FOR_WRITE( REG_EAX, REG_EDX );
1229 TESTB_r8_r8( REG_DL, REG_DL );
1230 SETE_t();
1231 ORB_imms_r8( 0x80, REG_DL );
1232 MOVL_rspdisp_r32( 0, REG_EAX );
1233 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1234 sh4_x86.tstate = TSTATE_NONE;
1235 :}
1236 TST Rm, Rn {:
1237 COUNT_INST(I_TST);
1238 load_reg( REG_EAX, Rm );
1239 load_reg( REG_ECX, Rn );
1240 TESTL_r32_r32( REG_EAX, REG_ECX );
1241 SETE_t();
1242 sh4_x86.tstate = TSTATE_E;
1243 :}
1244 TST #imm, R0 {:
1245 COUNT_INST(I_TSTI);
1246 load_reg( REG_EAX, 0 );
1247 TESTL_imms_r32( imm, REG_EAX );
1248 SETE_t();
1249 sh4_x86.tstate = TSTATE_E;
1250 :}
1251 TST.B #imm, @(R0, GBR) {:
1252 COUNT_INST(I_TSTB);
1253 load_reg( REG_EAX, 0);
1254 ADDL_rbpdisp_r32( R_GBR, REG_EAX );
1255 MEM_READ_BYTE( REG_EAX, REG_EAX );
1256 TESTB_imms_r8( imm, REG_AL );
1257 SETE_t();
1258 sh4_x86.tstate = TSTATE_E;
1259 :}
1260 XOR Rm, Rn {:
1261 COUNT_INST(I_XOR);
1262 load_reg( REG_EAX, Rm );
1263 load_reg( REG_ECX, Rn );
1264 XORL_r32_r32( REG_EAX, REG_ECX );
1265 store_reg( REG_ECX, Rn );
1266 sh4_x86.tstate = TSTATE_NONE;
1267 :}
1268 XOR #imm, R0 {:
1269 COUNT_INST(I_XORI);
1270 load_reg( REG_EAX, 0 );
1271 XORL_imms_r32( imm, REG_EAX );
1272 store_reg( REG_EAX, 0 );
1273 sh4_x86.tstate = TSTATE_NONE;
1274 :}
1275 XOR.B #imm, @(R0, GBR) {:
1276 COUNT_INST(I_XORB);
1277 load_reg( REG_EAX, 0 );
1278 ADDL_rbpdisp_r32( R_GBR, REG_EAX );
1279 MOVL_r32_rspdisp( REG_EAX, 0 );
1280 MEM_READ_BYTE_FOR_WRITE(REG_EAX, REG_EDX);
1281 MOVL_rspdisp_r32( 0, REG_EAX );
1282 XORL_imms_r32( imm, REG_EDX );
1283 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1284 sh4_x86.tstate = TSTATE_NONE;
1285 :}
1286 XTRCT Rm, Rn {:
1287 COUNT_INST(I_XTRCT);
1288 load_reg( REG_EAX, Rm );
1289 load_reg( REG_ECX, Rn );
1290 SHLL_imm_r32( 16, REG_EAX );
1291 SHRL_imm_r32( 16, REG_ECX );
1292 ORL_r32_r32( REG_EAX, REG_ECX );
1293 store_reg( REG_ECX, Rn );
1294 sh4_x86.tstate = TSTATE_NONE;
1295 :}
1297 /* Data move instructions */
1298 MOV Rm, Rn {:
1299 COUNT_INST(I_MOV);
1300 load_reg( REG_EAX, Rm );
1301 store_reg( REG_EAX, Rn );
1302 :}
1303 MOV #imm, Rn {:
1304 COUNT_INST(I_MOVI);
1305 MOVL_imm32_r32( imm, REG_EAX );
1306 store_reg( REG_EAX, Rn );
1307 :}
1308 MOV.B Rm, @Rn {:
1309 COUNT_INST(I_MOVB);
1310 load_reg( REG_EAX, Rn );
1311 load_reg( REG_EDX, Rm );
1312 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1313 sh4_x86.tstate = TSTATE_NONE;
1314 :}
1315 MOV.B Rm, @-Rn {:
1316 COUNT_INST(I_MOVB);
1317 load_reg( REG_EAX, Rn );
1318 LEAL_r32disp_r32( REG_EAX, -1, REG_EAX );
1319 load_reg( REG_EDX, Rm );
1320 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1321 ADDL_imms_rbpdisp( -1, REG_OFFSET(r[Rn]) );
1322 sh4_x86.tstate = TSTATE_NONE;
1323 :}
1324 MOV.B Rm, @(R0, Rn) {:
1325 COUNT_INST(I_MOVB);
1326 load_reg( REG_EAX, 0 );
1327 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
1328 load_reg( REG_EDX, Rm );
1329 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1330 sh4_x86.tstate = TSTATE_NONE;
1331 :}
1332 MOV.B R0, @(disp, GBR) {:
1333 COUNT_INST(I_MOVB);
1334 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1335 ADDL_imms_r32( disp, REG_EAX );
1336 load_reg( REG_EDX, 0 );
1337 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1338 sh4_x86.tstate = TSTATE_NONE;
1339 :}
1340 MOV.B R0, @(disp, Rn) {:
1341 COUNT_INST(I_MOVB);
1342 load_reg( REG_EAX, Rn );
1343 ADDL_imms_r32( disp, REG_EAX );
1344 load_reg( REG_EDX, 0 );
1345 MEM_WRITE_BYTE( REG_EAX, REG_EDX );
1346 sh4_x86.tstate = TSTATE_NONE;
1347 :}
1348 MOV.B @Rm, Rn {:
1349 COUNT_INST(I_MOVB);
1350 load_reg( REG_EAX, Rm );
1351 MEM_READ_BYTE( REG_EAX, REG_EAX );
1352 store_reg( REG_EAX, Rn );
1353 sh4_x86.tstate = TSTATE_NONE;
1354 :}
1355 MOV.B @Rm+, Rn {:
1356 COUNT_INST(I_MOVB);
1357 load_reg( REG_EAX, Rm );
1358 MEM_READ_BYTE( REG_EAX, REG_EAX );
1359 if( Rm != Rn ) {
1360 ADDL_imms_rbpdisp( 1, REG_OFFSET(r[Rm]) );
1361 }
1362 store_reg( REG_EAX, Rn );
1363 sh4_x86.tstate = TSTATE_NONE;
1364 :}
1365 MOV.B @(R0, Rm), Rn {:
1366 COUNT_INST(I_MOVB);
1367 load_reg( REG_EAX, 0 );
1368 ADDL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
1369 MEM_READ_BYTE( REG_EAX, REG_EAX );
1370 store_reg( REG_EAX, Rn );
1371 sh4_x86.tstate = TSTATE_NONE;
1372 :}
1373 MOV.B @(disp, GBR), R0 {:
1374 COUNT_INST(I_MOVB);
1375 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1376 ADDL_imms_r32( disp, REG_EAX );
1377 MEM_READ_BYTE( REG_EAX, REG_EAX );
1378 store_reg( REG_EAX, 0 );
1379 sh4_x86.tstate = TSTATE_NONE;
1380 :}
1381 MOV.B @(disp, Rm), R0 {:
1382 COUNT_INST(I_MOVB);
1383 load_reg( REG_EAX, Rm );
1384 ADDL_imms_r32( disp, REG_EAX );
1385 MEM_READ_BYTE( REG_EAX, REG_EAX );
1386 store_reg( REG_EAX, 0 );
1387 sh4_x86.tstate = TSTATE_NONE;
1388 :}
1389 MOV.L Rm, @Rn {:
1390 COUNT_INST(I_MOVL);
1391 load_reg( REG_EAX, Rn );
1392 check_walign32(REG_EAX);
1393 MOVL_r32_r32( REG_EAX, REG_ECX );
1394 ANDL_imms_r32( 0xFC000000, REG_ECX );
1395 CMPL_imms_r32( 0xE0000000, REG_ECX );
1396 JNE_label( notsq );
1397 ANDL_imms_r32( 0x3C, REG_EAX );
1398 load_reg( REG_EDX, Rm );
1399 MOVL_r32_sib( REG_EDX, 0, REG_EBP, REG_EAX, REG_OFFSET(store_queue) );
1400 JMP_label(end);
1401 JMP_TARGET(notsq);
1402 load_reg( REG_EDX, Rm );
1403 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1404 JMP_TARGET(end);
1405 sh4_x86.tstate = TSTATE_NONE;
1406 :}
1407 MOV.L Rm, @-Rn {:
1408 COUNT_INST(I_MOVL);
1409 load_reg( REG_EAX, Rn );
1410 ADDL_imms_r32( -4, REG_EAX );
1411 check_walign32( REG_EAX );
1412 load_reg( REG_EDX, Rm );
1413 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1414 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
1415 sh4_x86.tstate = TSTATE_NONE;
1416 :}
1417 MOV.L Rm, @(R0, Rn) {:
1418 COUNT_INST(I_MOVL);
1419 load_reg( REG_EAX, 0 );
1420 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
1421 check_walign32( REG_EAX );
1422 load_reg( REG_EDX, Rm );
1423 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1424 sh4_x86.tstate = TSTATE_NONE;
1425 :}
1426 MOV.L R0, @(disp, GBR) {:
1427 COUNT_INST(I_MOVL);
1428 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1429 ADDL_imms_r32( disp, REG_EAX );
1430 check_walign32( REG_EAX );
1431 load_reg( REG_EDX, 0 );
1432 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1433 sh4_x86.tstate = TSTATE_NONE;
1434 :}
1435 MOV.L Rm, @(disp, Rn) {:
1436 COUNT_INST(I_MOVL);
1437 load_reg( REG_EAX, Rn );
1438 ADDL_imms_r32( disp, REG_EAX );
1439 check_walign32( REG_EAX );
1440 MOVL_r32_r32( REG_EAX, REG_ECX );
1441 ANDL_imms_r32( 0xFC000000, REG_ECX );
1442 CMPL_imms_r32( 0xE0000000, REG_ECX );
1443 JNE_label( notsq );
1444 ANDL_imms_r32( 0x3C, REG_EAX );
1445 load_reg( REG_EDX, Rm );
1446 MOVL_r32_sib( REG_EDX, 0, REG_EBP, REG_EAX, REG_OFFSET(store_queue) );
1447 JMP_label(end);
1448 JMP_TARGET(notsq);
1449 load_reg( REG_EDX, Rm );
1450 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1451 JMP_TARGET(end);
1452 sh4_x86.tstate = TSTATE_NONE;
1453 :}
1454 MOV.L @Rm, Rn {:
1455 COUNT_INST(I_MOVL);
1456 load_reg( REG_EAX, Rm );
1457 check_ralign32( REG_EAX );
1458 MEM_READ_LONG( REG_EAX, REG_EAX );
1459 store_reg( REG_EAX, Rn );
1460 sh4_x86.tstate = TSTATE_NONE;
1461 :}
1462 MOV.L @Rm+, Rn {:
1463 COUNT_INST(I_MOVL);
1464 load_reg( REG_EAX, Rm );
1465 check_ralign32( REG_EAX );
1466 MEM_READ_LONG( REG_EAX, REG_EAX );
1467 if( Rm != Rn ) {
1468 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
1469 }
1470 store_reg( REG_EAX, Rn );
1471 sh4_x86.tstate = TSTATE_NONE;
1472 :}
1473 MOV.L @(R0, Rm), Rn {:
1474 COUNT_INST(I_MOVL);
1475 load_reg( REG_EAX, 0 );
1476 ADDL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
1477 check_ralign32( REG_EAX );
1478 MEM_READ_LONG( REG_EAX, REG_EAX );
1479 store_reg( REG_EAX, Rn );
1480 sh4_x86.tstate = TSTATE_NONE;
1481 :}
1482 MOV.L @(disp, GBR), R0 {:
1483 COUNT_INST(I_MOVL);
1484 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1485 ADDL_imms_r32( disp, REG_EAX );
1486 check_ralign32( REG_EAX );
1487 MEM_READ_LONG( REG_EAX, REG_EAX );
1488 store_reg( REG_EAX, 0 );
1489 sh4_x86.tstate = TSTATE_NONE;
1490 :}
1491 MOV.L @(disp, PC), Rn {:
1492 COUNT_INST(I_MOVLPC);
1493 if( sh4_x86.in_delay_slot ) {
1494 SLOTILLEGAL();
1495 } else {
1496 uint32_t target = (pc & 0xFFFFFFFC) + disp + 4;
1497 if( IS_IN_ICACHE(target) ) {
1498 // If the target address is in the same page as the code, it's
1499 // pretty safe to just ref it directly and circumvent the whole
1500 // memory subsystem. (this is a big performance win)
1502 // FIXME: There's a corner-case that's not handled here when
1503 // the current code-page is in the ITLB but not in the UTLB.
1504 // (should generate a TLB miss although need to test SH4
1505 // behaviour to confirm) Unlikely to be anyone depending on this
1506 // behaviour though.
1507 sh4ptr_t ptr = GET_ICACHE_PTR(target);
1508 MOVL_moffptr_eax( ptr );
1509 } else {
1510 // Note: we use sh4r.pc for the calc as we could be running at a
1511 // different virtual address than the translation was done with,
1512 // but we can safely assume that the low bits are the same.
1513 MOVL_imm32_r32( (pc-sh4_x86.block_start_pc) + disp + 4 - (pc&0x03), REG_EAX );
1514 ADDL_rbpdisp_r32( R_PC, REG_EAX );
1515 MEM_READ_LONG( REG_EAX, REG_EAX );
1516 sh4_x86.tstate = TSTATE_NONE;
1517 }
1518 store_reg( REG_EAX, Rn );
1519 }
1520 :}
1521 MOV.L @(disp, Rm), Rn {:
1522 COUNT_INST(I_MOVL);
1523 load_reg( REG_EAX, Rm );
1524 ADDL_imms_r32( disp, REG_EAX );
1525 check_ralign32( REG_EAX );
1526 MEM_READ_LONG( REG_EAX, REG_EAX );
1527 store_reg( REG_EAX, Rn );
1528 sh4_x86.tstate = TSTATE_NONE;
1529 :}
1530 MOV.W Rm, @Rn {:
1531 COUNT_INST(I_MOVW);
1532 load_reg( REG_EAX, Rn );
1533 check_walign16( REG_EAX );
1534 load_reg( REG_EDX, Rm );
1535 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1536 sh4_x86.tstate = TSTATE_NONE;
1537 :}
1538 MOV.W Rm, @-Rn {:
1539 COUNT_INST(I_MOVW);
1540 load_reg( REG_EAX, Rn );
1541 check_walign16( REG_EAX );
1542 LEAL_r32disp_r32( REG_EAX, -2, REG_EAX );
1543 load_reg( REG_EDX, Rm );
1544 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1545 ADDL_imms_rbpdisp( -2, REG_OFFSET(r[Rn]) );
1546 sh4_x86.tstate = TSTATE_NONE;
1547 :}
1548 MOV.W Rm, @(R0, Rn) {:
1549 COUNT_INST(I_MOVW);
1550 load_reg( REG_EAX, 0 );
1551 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
1552 check_walign16( REG_EAX );
1553 load_reg( REG_EDX, Rm );
1554 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1555 sh4_x86.tstate = TSTATE_NONE;
1556 :}
1557 MOV.W R0, @(disp, GBR) {:
1558 COUNT_INST(I_MOVW);
1559 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1560 ADDL_imms_r32( disp, REG_EAX );
1561 check_walign16( REG_EAX );
1562 load_reg( REG_EDX, 0 );
1563 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1564 sh4_x86.tstate = TSTATE_NONE;
1565 :}
1566 MOV.W R0, @(disp, Rn) {:
1567 COUNT_INST(I_MOVW);
1568 load_reg( REG_EAX, Rn );
1569 ADDL_imms_r32( disp, REG_EAX );
1570 check_walign16( REG_EAX );
1571 load_reg( REG_EDX, 0 );
1572 MEM_WRITE_WORD( REG_EAX, REG_EDX );
1573 sh4_x86.tstate = TSTATE_NONE;
1574 :}
1575 MOV.W @Rm, Rn {:
1576 COUNT_INST(I_MOVW);
1577 load_reg( REG_EAX, Rm );
1578 check_ralign16( REG_EAX );
1579 MEM_READ_WORD( REG_EAX, REG_EAX );
1580 store_reg( REG_EAX, Rn );
1581 sh4_x86.tstate = TSTATE_NONE;
1582 :}
1583 MOV.W @Rm+, Rn {:
1584 COUNT_INST(I_MOVW);
1585 load_reg( REG_EAX, Rm );
1586 check_ralign16( REG_EAX );
1587 MEM_READ_WORD( REG_EAX, REG_EAX );
1588 if( Rm != Rn ) {
1589 ADDL_imms_rbpdisp( 2, REG_OFFSET(r[Rm]) );
1590 }
1591 store_reg( REG_EAX, Rn );
1592 sh4_x86.tstate = TSTATE_NONE;
1593 :}
1594 MOV.W @(R0, Rm), Rn {:
1595 COUNT_INST(I_MOVW);
1596 load_reg( REG_EAX, 0 );
1597 ADDL_rbpdisp_r32( REG_OFFSET(r[Rm]), REG_EAX );
1598 check_ralign16( REG_EAX );
1599 MEM_READ_WORD( REG_EAX, REG_EAX );
1600 store_reg( REG_EAX, Rn );
1601 sh4_x86.tstate = TSTATE_NONE;
1602 :}
1603 MOV.W @(disp, GBR), R0 {:
1604 COUNT_INST(I_MOVW);
1605 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
1606 ADDL_imms_r32( disp, REG_EAX );
1607 check_ralign16( REG_EAX );
1608 MEM_READ_WORD( REG_EAX, REG_EAX );
1609 store_reg( REG_EAX, 0 );
1610 sh4_x86.tstate = TSTATE_NONE;
1611 :}
1612 MOV.W @(disp, PC), Rn {:
1613 COUNT_INST(I_MOVW);
1614 if( sh4_x86.in_delay_slot ) {
1615 SLOTILLEGAL();
1616 } else {
1617 // See comments for MOV.L @(disp, PC), Rn
1618 uint32_t target = pc + disp + 4;
1619 if( IS_IN_ICACHE(target) ) {
1620 sh4ptr_t ptr = GET_ICACHE_PTR(target);
1621 MOVL_moffptr_eax( ptr );
1622 MOVSXL_r16_r32( REG_EAX, REG_EAX );
1623 } else {
1624 MOVL_imm32_r32( (pc - sh4_x86.block_start_pc) + disp + 4, REG_EAX );
1625 ADDL_rbpdisp_r32( R_PC, REG_EAX );
1626 MEM_READ_WORD( REG_EAX, REG_EAX );
1627 sh4_x86.tstate = TSTATE_NONE;
1628 }
1629 store_reg( REG_EAX, Rn );
1630 }
1631 :}
1632 MOV.W @(disp, Rm), R0 {:
1633 COUNT_INST(I_MOVW);
1634 load_reg( REG_EAX, Rm );
1635 ADDL_imms_r32( disp, REG_EAX );
1636 check_ralign16( REG_EAX );
1637 MEM_READ_WORD( REG_EAX, REG_EAX );
1638 store_reg( REG_EAX, 0 );
1639 sh4_x86.tstate = TSTATE_NONE;
1640 :}
1641 MOVA @(disp, PC), R0 {:
1642 COUNT_INST(I_MOVA);
1643 if( sh4_x86.in_delay_slot ) {
1644 SLOTILLEGAL();
1645 } else {
1646 MOVL_imm32_r32( (pc - sh4_x86.block_start_pc) + disp + 4 - (pc&0x03), REG_ECX );
1647 ADDL_rbpdisp_r32( R_PC, REG_ECX );
1648 store_reg( REG_ECX, 0 );
1649 sh4_x86.tstate = TSTATE_NONE;
1650 }
1651 :}
1652 MOVCA.L R0, @Rn {:
1653 COUNT_INST(I_MOVCA);
1654 load_reg( REG_EAX, Rn );
1655 check_walign32( REG_EAX );
1656 load_reg( REG_EDX, 0 );
1657 MEM_WRITE_LONG( REG_EAX, REG_EDX );
1658 sh4_x86.tstate = TSTATE_NONE;
1659 :}
1661 /* Control transfer instructions */
1662 BF disp {:
1663 COUNT_INST(I_BF);
1664 if( sh4_x86.in_delay_slot ) {
1665 SLOTILLEGAL();
1666 } else {
1667 sh4vma_t target = disp + pc + 4;
1668 JT_label( nottaken );
1669 exit_block_rel(target, pc+2 );
1670 JMP_TARGET(nottaken);
1671 return 2;
1672 }
1673 :}
1674 BF/S disp {:
1675 COUNT_INST(I_BFS);
1676 if( sh4_x86.in_delay_slot ) {
1677 SLOTILLEGAL();
1678 } else {
1679 sh4_x86.in_delay_slot = DELAY_PC;
1680 if( UNTRANSLATABLE(pc+2) ) {
1681 MOVL_imm32_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
1682 JT_label(nottaken);
1683 ADDL_imms_r32( disp, REG_EAX );
1684 JMP_TARGET(nottaken);
1685 ADDL_rbpdisp_r32( R_PC, REG_EAX );
1686 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
1687 exit_block_emu(pc+2);
1688 sh4_x86.branch_taken = TRUE;
1689 return 2;
1690 } else {
1691 if( sh4_x86.tstate == TSTATE_NONE ) {
1692 CMPL_imms_rbpdisp( 1, R_T );
1693 sh4_x86.tstate = TSTATE_E;
1694 }
1695 sh4vma_t target = disp + pc + 4;
1696 JCC_cc_rel32(sh4_x86.tstate,0);
1697 uint32_t *patch = ((uint32_t *)xlat_output)-1;
1698 int save_tstate = sh4_x86.tstate;
1699 sh4_translate_instruction(pc+2);
1700 exit_block_rel( target, pc+4 );
1702 // not taken
1703 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1704 sh4_x86.tstate = save_tstate;
1705 sh4_translate_instruction(pc+2);
1706 return 4;
1707 }
1708 }
1709 :}
1710 BRA disp {:
1711 COUNT_INST(I_BRA);
1712 if( sh4_x86.in_delay_slot ) {
1713 SLOTILLEGAL();
1714 } else {
1715 sh4_x86.in_delay_slot = DELAY_PC;
1716 sh4_x86.branch_taken = TRUE;
1717 if( UNTRANSLATABLE(pc+2) ) {
1718 MOVL_rbpdisp_r32( R_PC, REG_EAX );
1719 ADDL_imms_r32( pc + disp + 4 - sh4_x86.block_start_pc, REG_EAX );
1720 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
1721 exit_block_emu(pc+2);
1722 return 2;
1723 } else {
1724 sh4_translate_instruction( pc + 2 );
1725 exit_block_rel( disp + pc + 4, pc+4 );
1726 return 4;
1727 }
1728 }
1729 :}
1730 BRAF Rn {:
1731 COUNT_INST(I_BRAF);
1732 if( sh4_x86.in_delay_slot ) {
1733 SLOTILLEGAL();
1734 } else {
1735 MOVL_rbpdisp_r32( R_PC, REG_EAX );
1736 ADDL_imms_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
1737 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
1738 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
1739 sh4_x86.in_delay_slot = DELAY_PC;
1740 sh4_x86.tstate = TSTATE_NONE;
1741 sh4_x86.branch_taken = TRUE;
1742 if( UNTRANSLATABLE(pc+2) ) {
1743 exit_block_emu(pc+2);
1744 return 2;
1745 } else {
1746 sh4_translate_instruction( pc + 2 );
1747 exit_block_newpcset(pc+4);
1748 return 4;
1749 }
1750 }
1751 :}
1752 BSR disp {:
1753 COUNT_INST(I_BSR);
1754 if( sh4_x86.in_delay_slot ) {
1755 SLOTILLEGAL();
1756 } else {
1757 MOVL_rbpdisp_r32( R_PC, REG_EAX );
1758 ADDL_imms_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
1759 MOVL_r32_rbpdisp( REG_EAX, R_PR );
1760 sh4_x86.in_delay_slot = DELAY_PC;
1761 sh4_x86.branch_taken = TRUE;
1762 sh4_x86.tstate = TSTATE_NONE;
1763 if( UNTRANSLATABLE(pc+2) ) {
1764 ADDL_imms_r32( disp, REG_EAX );
1765 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
1766 exit_block_emu(pc+2);
1767 return 2;
1768 } else {
1769 sh4_translate_instruction( pc + 2 );
1770 exit_block_rel( disp + pc + 4, pc+4 );
1771 return 4;
1772 }
1773 }
1774 :}
1775 BSRF Rn {:
1776 COUNT_INST(I_BSRF);
1777 if( sh4_x86.in_delay_slot ) {
1778 SLOTILLEGAL();
1779 } else {
1780 MOVL_rbpdisp_r32( R_PC, REG_EAX );
1781 ADDL_imms_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
1782 MOVL_r32_rbpdisp( REG_EAX, R_PR );
1783 ADDL_rbpdisp_r32( REG_OFFSET(r[Rn]), REG_EAX );
1784 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
1786 sh4_x86.in_delay_slot = DELAY_PC;
1787 sh4_x86.tstate = TSTATE_NONE;
1788 sh4_x86.branch_taken = TRUE;
1789 if( UNTRANSLATABLE(pc+2) ) {
1790 exit_block_emu(pc+2);
1791 return 2;
1792 } else {
1793 sh4_translate_instruction( pc + 2 );
1794 exit_block_newpcset(pc+4);
1795 return 4;
1796 }
1797 }
1798 :}
1799 BT disp {:
1800 COUNT_INST(I_BT);
1801 if( sh4_x86.in_delay_slot ) {
1802 SLOTILLEGAL();
1803 } else {
1804 sh4vma_t target = disp + pc + 4;
1805 JF_label( nottaken );
1806 exit_block_rel(target, pc+2 );
1807 JMP_TARGET(nottaken);
1808 return 2;
1809 }
1810 :}
1811 BT/S disp {:
1812 COUNT_INST(I_BTS);
1813 if( sh4_x86.in_delay_slot ) {
1814 SLOTILLEGAL();
1815 } else {
1816 sh4_x86.in_delay_slot = DELAY_PC;
1817 if( UNTRANSLATABLE(pc+2) ) {
1818 MOVL_imm32_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
1819 JF_label(nottaken);
1820 ADDL_imms_r32( disp, REG_EAX );
1821 JMP_TARGET(nottaken);
1822 ADDL_rbpdisp_r32( R_PC, REG_EAX );
1823 MOVL_r32_rbpdisp( REG_EAX, R_NEW_PC );
1824 exit_block_emu(pc+2);
1825 sh4_x86.branch_taken = TRUE;
1826 return 2;
1827 } else {
1828 if( sh4_x86.tstate == TSTATE_NONE ) {
1829 CMPL_imms_rbpdisp( 1, R_T );
1830 sh4_x86.tstate = TSTATE_E;
1831 }
1832 JCC_cc_rel32(sh4_x86.tstate^1,0);
1833 uint32_t *patch = ((uint32_t *)xlat_output)-1;
1835 int save_tstate = sh4_x86.tstate;
1836 sh4_translate_instruction(pc+2);
1837 exit_block_rel( disp + pc + 4, pc+4 );
1838 // not taken
1839 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1840 sh4_x86.tstate = save_tstate;
1841 sh4_translate_instruction(pc+2);
1842 return 4;
1843 }
1844 }
1845 :}
1846 JMP @Rn {:
1847 COUNT_INST(I_JMP);
1848 if( sh4_x86.in_delay_slot ) {
1849 SLOTILLEGAL();
1850 } else {
1851 load_reg( REG_ECX, Rn );
1852 MOVL_r32_rbpdisp( REG_ECX, R_NEW_PC );
1853 sh4_x86.in_delay_slot = DELAY_PC;
1854 sh4_x86.branch_taken = TRUE;
1855 if( UNTRANSLATABLE(pc+2) ) {
1856 exit_block_emu(pc+2);
1857 return 2;
1858 } else {
1859 sh4_translate_instruction(pc+2);
1860 exit_block_newpcset(pc+4);
1861 return 4;
1862 }
1863 }
1864 :}
1865 JSR @Rn {:
1866 COUNT_INST(I_JSR);
1867 if( sh4_x86.in_delay_slot ) {
1868 SLOTILLEGAL();
1869 } else {
1870 MOVL_rbpdisp_r32( R_PC, REG_EAX );
1871 ADDL_imms_r32( pc + 4 - sh4_x86.block_start_pc, REG_EAX );
1872 MOVL_r32_rbpdisp( REG_EAX, R_PR );
1873 load_reg( REG_ECX, Rn );
1874 MOVL_r32_rbpdisp( REG_ECX, R_NEW_PC );
1875 sh4_x86.in_delay_slot = DELAY_PC;
1876 sh4_x86.branch_taken = TRUE;
1877 sh4_x86.tstate = TSTATE_NONE;
1878 if( UNTRANSLATABLE(pc+2) ) {
1879 exit_block_emu(pc+2);
1880 return 2;
1881 } else {
1882 sh4_translate_instruction(pc+2);
1883 exit_block_newpcset(pc+4);
1884 return 4;
1885 }
1886 }
1887 :}
1888 RTE {:
1889 COUNT_INST(I_RTE);
1890 if( sh4_x86.in_delay_slot ) {
1891 SLOTILLEGAL();
1892 } else {
1893 check_priv();
1894 MOVL_rbpdisp_r32( R_SPC, REG_ECX );
1895 MOVL_r32_rbpdisp( REG_ECX, R_NEW_PC );
1896 MOVL_rbpdisp_r32( R_SSR, REG_EAX );
1897 CALL1_ptr_r32( sh4_write_sr, REG_EAX );
1898 sh4_x86.in_delay_slot = DELAY_PC;
1899 sh4_x86.fpuen_checked = FALSE;
1900 sh4_x86.tstate = TSTATE_NONE;
1901 sh4_x86.branch_taken = TRUE;
1902 if( UNTRANSLATABLE(pc+2) ) {
1903 exit_block_emu(pc+2);
1904 return 2;
1905 } else {
1906 sh4_translate_instruction(pc+2);
1907 exit_block_newpcset(pc+4);
1908 return 4;
1909 }
1910 }
1911 :}
1912 RTS {:
1913 COUNT_INST(I_RTS);
1914 if( sh4_x86.in_delay_slot ) {
1915 SLOTILLEGAL();
1916 } else {
1917 MOVL_rbpdisp_r32( R_PR, REG_ECX );
1918 MOVL_r32_rbpdisp( REG_ECX, R_NEW_PC );
1919 sh4_x86.in_delay_slot = DELAY_PC;
1920 sh4_x86.branch_taken = TRUE;
1921 if( UNTRANSLATABLE(pc+2) ) {
1922 exit_block_emu(pc+2);
1923 return 2;
1924 } else {
1925 sh4_translate_instruction(pc+2);
1926 exit_block_newpcset(pc+4);
1927 return 4;
1928 }
1929 }
1930 :}
1931 TRAPA #imm {:
1932 COUNT_INST(I_TRAPA);
1933 if( sh4_x86.in_delay_slot ) {
1934 SLOTILLEGAL();
1935 } else {
1936 MOVL_imm32_r32( pc+2 - sh4_x86.block_start_pc, REG_ECX ); // 5
1937 ADDL_r32_rbpdisp( REG_ECX, R_PC );
1938 MOVL_imm32_r32( imm, REG_EAX );
1939 CALL1_ptr_r32( sh4_raise_trap, REG_EAX );
1940 sh4_x86.tstate = TSTATE_NONE;
1941 exit_block_pcset(pc+2);
1942 sh4_x86.branch_taken = TRUE;
1943 return 2;
1944 }
1945 :}
1946 UNDEF {:
1947 COUNT_INST(I_UNDEF);
1948 if( sh4_x86.in_delay_slot ) {
1949 exit_block_exc(EXC_SLOT_ILLEGAL, pc-2);
1950 } else {
1951 exit_block_exc(EXC_ILLEGAL, pc);
1952 return 2;
1953 }
1954 :}
1956 CLRMAC {:
1957 COUNT_INST(I_CLRMAC);
1958 XORL_r32_r32(REG_EAX, REG_EAX);
1959 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
1960 MOVL_r32_rbpdisp( REG_EAX, R_MACH );
1961 sh4_x86.tstate = TSTATE_NONE;
1962 :}
1963 CLRS {:
1964 COUNT_INST(I_CLRS);
1965 CLC();
1966 SETCCB_cc_rbpdisp(X86_COND_C, R_S);
1967 sh4_x86.tstate = TSTATE_NONE;
1968 :}
1969 CLRT {:
1970 COUNT_INST(I_CLRT);
1971 CLC();
1972 SETC_t();
1973 sh4_x86.tstate = TSTATE_C;
1974 :}
1975 SETS {:
1976 COUNT_INST(I_SETS);
1977 STC();
1978 SETCCB_cc_rbpdisp(X86_COND_C, R_S);
1979 sh4_x86.tstate = TSTATE_NONE;
1980 :}
1981 SETT {:
1982 COUNT_INST(I_SETT);
1983 STC();
1984 SETC_t();
1985 sh4_x86.tstate = TSTATE_C;
1986 :}
1988 /* Floating point moves */
1989 FMOV FRm, FRn {:
1990 COUNT_INST(I_FMOV1);
1991 check_fpuen();
1992 if( sh4_x86.double_size ) {
1993 load_dr0( REG_EAX, FRm );
1994 load_dr1( REG_ECX, FRm );
1995 store_dr0( REG_EAX, FRn );
1996 store_dr1( REG_ECX, FRn );
1997 } else {
1998 load_fr( REG_EAX, FRm ); // SZ=0 branch
1999 store_fr( REG_EAX, FRn );
2000 }
2001 :}
2002 FMOV FRm, @Rn {:
2003 COUNT_INST(I_FMOV2);
2004 check_fpuen();
2005 load_reg( REG_EAX, Rn );
2006 if( sh4_x86.double_size ) {
2007 check_walign64( REG_EAX );
2008 load_dr0( REG_EDX, FRm );
2009 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2010 load_reg( REG_EAX, Rn );
2011 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2012 load_dr1( REG_EDX, FRm );
2013 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2014 } else {
2015 check_walign32( REG_EAX );
2016 load_fr( REG_EDX, FRm );
2017 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2018 }
2019 sh4_x86.tstate = TSTATE_NONE;
2020 :}
2021 FMOV @Rm, FRn {:
2022 COUNT_INST(I_FMOV5);
2023 check_fpuen();
2024 load_reg( REG_EAX, Rm );
2025 if( sh4_x86.double_size ) {
2026 check_ralign64( REG_EAX );
2027 MEM_READ_LONG( REG_EAX, REG_EAX );
2028 store_dr0( REG_EAX, FRn );
2029 load_reg( REG_EAX, Rm );
2030 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2031 MEM_READ_LONG( REG_EAX, REG_EAX );
2032 store_dr1( REG_EAX, FRn );
2033 } else {
2034 check_ralign32( REG_EAX );
2035 MEM_READ_LONG( REG_EAX, REG_EAX );
2036 store_fr( REG_EAX, FRn );
2037 }
2038 sh4_x86.tstate = TSTATE_NONE;
2039 :}
2040 FMOV FRm, @-Rn {:
2041 COUNT_INST(I_FMOV3);
2042 check_fpuen();
2043 load_reg( REG_EAX, Rn );
2044 if( sh4_x86.double_size ) {
2045 check_walign64( REG_EAX );
2046 LEAL_r32disp_r32( REG_EAX, -8, REG_EAX );
2047 load_dr0( REG_EDX, FRm );
2048 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2049 load_reg( REG_EAX, Rn );
2050 LEAL_r32disp_r32( REG_EAX, -4, REG_EAX );
2051 load_dr1( REG_EDX, FRm );
2052 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2053 ADDL_imms_rbpdisp(-8,REG_OFFSET(r[Rn]));
2054 } else {
2055 check_walign32( REG_EAX );
2056 LEAL_r32disp_r32( REG_EAX, -4, REG_EAX );
2057 load_fr( REG_EDX, FRm );
2058 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2059 ADDL_imms_rbpdisp(-4,REG_OFFSET(r[Rn]));
2060 }
2061 sh4_x86.tstate = TSTATE_NONE;
2062 :}
2063 FMOV @Rm+, FRn {:
2064 COUNT_INST(I_FMOV6);
2065 check_fpuen();
2066 load_reg( REG_EAX, Rm );
2067 if( sh4_x86.double_size ) {
2068 check_ralign64( REG_EAX );
2069 MEM_READ_LONG( REG_EAX, REG_EAX );
2070 store_dr0( REG_EAX, FRn );
2071 load_reg( REG_EAX, Rm );
2072 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2073 MEM_READ_LONG( REG_EAX, REG_EAX );
2074 store_dr1( REG_EAX, FRn );
2075 ADDL_imms_rbpdisp( 8, REG_OFFSET(r[Rm]) );
2076 } else {
2077 check_ralign32( REG_EAX );
2078 MEM_READ_LONG( REG_EAX, REG_EAX );
2079 store_fr( REG_EAX, FRn );
2080 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2081 }
2082 sh4_x86.tstate = TSTATE_NONE;
2083 :}
2084 FMOV FRm, @(R0, Rn) {:
2085 COUNT_INST(I_FMOV4);
2086 check_fpuen();
2087 load_reg( REG_EAX, Rn );
2088 ADDL_rbpdisp_r32( REG_OFFSET(r[0]), REG_EAX );
2089 if( sh4_x86.double_size ) {
2090 check_walign64( REG_EAX );
2091 load_dr0( REG_EDX, FRm );
2092 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2093 load_reg( REG_EAX, Rn );
2094 ADDL_rbpdisp_r32( REG_OFFSET(r[0]), REG_EAX );
2095 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2096 load_dr1( REG_EDX, FRm );
2097 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2098 } else {
2099 check_walign32( REG_EAX );
2100 load_fr( REG_EDX, FRm );
2101 MEM_WRITE_LONG( REG_EAX, REG_EDX ); // 12
2102 }
2103 sh4_x86.tstate = TSTATE_NONE;
2104 :}
2105 FMOV @(R0, Rm), FRn {:
2106 COUNT_INST(I_FMOV7);
2107 check_fpuen();
2108 load_reg( REG_EAX, Rm );
2109 ADDL_rbpdisp_r32( REG_OFFSET(r[0]), REG_EAX );
2110 if( sh4_x86.double_size ) {
2111 check_ralign64( REG_EAX );
2112 MEM_READ_LONG( REG_EAX, REG_EAX );
2113 store_dr0( REG_EAX, FRn );
2114 load_reg( REG_EAX, Rm );
2115 ADDL_rbpdisp_r32( REG_OFFSET(r[0]), REG_EAX );
2116 LEAL_r32disp_r32( REG_EAX, 4, REG_EAX );
2117 MEM_READ_LONG( REG_EAX, REG_EAX );
2118 store_dr1( REG_EAX, FRn );
2119 } else {
2120 check_ralign32( REG_EAX );
2121 MEM_READ_LONG( REG_EAX, REG_EAX );
2122 store_fr( REG_EAX, FRn );
2123 }
2124 sh4_x86.tstate = TSTATE_NONE;
2125 :}
2126 FLDI0 FRn {: /* IFF PR=0 */
2127 COUNT_INST(I_FLDI0);
2128 check_fpuen();
2129 if( sh4_x86.double_prec == 0 ) {
2130 XORL_r32_r32( REG_EAX, REG_EAX );
2131 store_fr( REG_EAX, FRn );
2132 }
2133 sh4_x86.tstate = TSTATE_NONE;
2134 :}
2135 FLDI1 FRn {: /* IFF PR=0 */
2136 COUNT_INST(I_FLDI1);
2137 check_fpuen();
2138 if( sh4_x86.double_prec == 0 ) {
2139 MOVL_imm32_r32( 0x3F800000, REG_EAX );
2140 store_fr( REG_EAX, FRn );
2141 }
2142 :}
2144 FLOAT FPUL, FRn {:
2145 COUNT_INST(I_FLOAT);
2146 check_fpuen();
2147 FILD_rbpdisp(R_FPUL);
2148 if( sh4_x86.double_prec ) {
2149 pop_dr( FRn );
2150 } else {
2151 pop_fr( FRn );
2152 }
2153 :}
2154 FTRC FRm, FPUL {:
2155 COUNT_INST(I_FTRC);
2156 check_fpuen();
2157 if( sh4_x86.double_prec ) {
2158 push_dr( FRm );
2159 } else {
2160 push_fr( FRm );
2161 }
2162 MOVP_immptr_rptr( &max_int, REG_ECX );
2163 FILD_r32disp( REG_ECX, 0 );
2164 FCOMIP_st(1);
2165 JNA_label( sat );
2166 MOVP_immptr_rptr( &min_int, REG_ECX );
2167 FILD_r32disp( REG_ECX, 0 );
2168 FCOMIP_st(1);
2169 JAE_label( sat2 );
2170 MOVP_immptr_rptr( &save_fcw, REG_EAX );
2171 FNSTCW_r32disp( REG_EAX, 0 );
2172 MOVP_immptr_rptr( &trunc_fcw, REG_EDX );
2173 FLDCW_r32disp( REG_EDX, 0 );
2174 FISTP_rbpdisp(R_FPUL);
2175 FLDCW_r32disp( REG_EAX, 0 );
2176 JMP_label(end);
2178 JMP_TARGET(sat);
2179 JMP_TARGET(sat2);
2180 MOVL_r32disp_r32( REG_ECX, 0, REG_ECX ); // 2
2181 MOVL_r32_rbpdisp( REG_ECX, R_FPUL );
2182 FPOP_st();
2183 JMP_TARGET(end);
2184 sh4_x86.tstate = TSTATE_NONE;
2185 :}
2186 FLDS FRm, FPUL {:
2187 COUNT_INST(I_FLDS);
2188 check_fpuen();
2189 load_fr( REG_EAX, FRm );
2190 MOVL_r32_rbpdisp( REG_EAX, R_FPUL );
2191 :}
2192 FSTS FPUL, FRn {:
2193 COUNT_INST(I_FSTS);
2194 check_fpuen();
2195 MOVL_rbpdisp_r32( R_FPUL, REG_EAX );
2196 store_fr( REG_EAX, FRn );
2197 :}
2198 FCNVDS FRm, FPUL {:
2199 COUNT_INST(I_FCNVDS);
2200 check_fpuen();
2201 if( sh4_x86.double_prec ) {
2202 push_dr( FRm );
2203 pop_fpul();
2204 }
2205 :}
2206 FCNVSD FPUL, FRn {:
2207 COUNT_INST(I_FCNVSD);
2208 check_fpuen();
2209 if( sh4_x86.double_prec ) {
2210 push_fpul();
2211 pop_dr( FRn );
2212 }
2213 :}
2215 /* Floating point instructions */
2216 FABS FRn {:
2217 COUNT_INST(I_FABS);
2218 check_fpuen();
2219 if( sh4_x86.double_prec ) {
2220 push_dr(FRn);
2221 FABS_st0();
2222 pop_dr(FRn);
2223 } else {
2224 push_fr(FRn);
2225 FABS_st0();
2226 pop_fr(FRn);
2227 }
2228 :}
2229 FADD FRm, FRn {:
2230 COUNT_INST(I_FADD);
2231 check_fpuen();
2232 if( sh4_x86.double_prec ) {
2233 push_dr(FRm);
2234 push_dr(FRn);
2235 FADDP_st(1);
2236 pop_dr(FRn);
2237 } else {
2238 push_fr(FRm);
2239 push_fr(FRn);
2240 FADDP_st(1);
2241 pop_fr(FRn);
2242 }
2243 :}
2244 FDIV FRm, FRn {:
2245 COUNT_INST(I_FDIV);
2246 check_fpuen();
2247 if( sh4_x86.double_prec ) {
2248 push_dr(FRn);
2249 push_dr(FRm);
2250 FDIVP_st(1);
2251 pop_dr(FRn);
2252 } else {
2253 push_fr(FRn);
2254 push_fr(FRm);
2255 FDIVP_st(1);
2256 pop_fr(FRn);
2257 }
2258 :}
2259 FMAC FR0, FRm, FRn {:
2260 COUNT_INST(I_FMAC);
2261 check_fpuen();
2262 if( sh4_x86.double_prec ) {
2263 push_dr( 0 );
2264 push_dr( FRm );
2265 FMULP_st(1);
2266 push_dr( FRn );
2267 FADDP_st(1);
2268 pop_dr( FRn );
2269 } else {
2270 push_fr( 0 );
2271 push_fr( FRm );
2272 FMULP_st(1);
2273 push_fr( FRn );
2274 FADDP_st(1);
2275 pop_fr( FRn );
2276 }
2277 :}
2279 FMUL FRm, FRn {:
2280 COUNT_INST(I_FMUL);
2281 check_fpuen();
2282 if( sh4_x86.double_prec ) {
2283 push_dr(FRm);
2284 push_dr(FRn);
2285 FMULP_st(1);
2286 pop_dr(FRn);
2287 } else {
2288 push_fr(FRm);
2289 push_fr(FRn);
2290 FMULP_st(1);
2291 pop_fr(FRn);
2292 }
2293 :}
2294 FNEG FRn {:
2295 COUNT_INST(I_FNEG);
2296 check_fpuen();
2297 if( sh4_x86.double_prec ) {
2298 push_dr(FRn);
2299 FCHS_st0();
2300 pop_dr(FRn);
2301 } else {
2302 push_fr(FRn);
2303 FCHS_st0();
2304 pop_fr(FRn);
2305 }
2306 :}
2307 FSRRA FRn {:
2308 COUNT_INST(I_FSRRA);
2309 check_fpuen();
2310 if( sh4_x86.double_prec == 0 ) {
2311 FLD1_st0();
2312 push_fr(FRn);
2313 FSQRT_st0();
2314 FDIVP_st(1);
2315 pop_fr(FRn);
2316 }
2317 :}
2318 FSQRT FRn {:
2319 COUNT_INST(I_FSQRT);
2320 check_fpuen();
2321 if( sh4_x86.double_prec ) {
2322 push_dr(FRn);
2323 FSQRT_st0();
2324 pop_dr(FRn);
2325 } else {
2326 push_fr(FRn);
2327 FSQRT_st0();
2328 pop_fr(FRn);
2329 }
2330 :}
2331 FSUB FRm, FRn {:
2332 COUNT_INST(I_FSUB);
2333 check_fpuen();
2334 if( sh4_x86.double_prec ) {
2335 push_dr(FRn);
2336 push_dr(FRm);
2337 FSUBP_st(1);
2338 pop_dr(FRn);
2339 } else {
2340 push_fr(FRn);
2341 push_fr(FRm);
2342 FSUBP_st(1);
2343 pop_fr(FRn);
2344 }
2345 :}
2347 FCMP/EQ FRm, FRn {:
2348 COUNT_INST(I_FCMPEQ);
2349 check_fpuen();
2350 if( sh4_x86.double_prec ) {
2351 push_dr(FRm);
2352 push_dr(FRn);
2353 } else {
2354 push_fr(FRm);
2355 push_fr(FRn);
2356 }
2357 FCOMIP_st(1);
2358 SETE_t();
2359 FPOP_st();
2360 sh4_x86.tstate = TSTATE_E;
2361 :}
2362 FCMP/GT FRm, FRn {:
2363 COUNT_INST(I_FCMPGT);
2364 check_fpuen();
2365 if( sh4_x86.double_prec ) {
2366 push_dr(FRm);
2367 push_dr(FRn);
2368 } else {
2369 push_fr(FRm);
2370 push_fr(FRn);
2371 }
2372 FCOMIP_st(1);
2373 SETA_t();
2374 FPOP_st();
2375 sh4_x86.tstate = TSTATE_A;
2376 :}
2378 FSCA FPUL, FRn {:
2379 COUNT_INST(I_FSCA);
2380 check_fpuen();
2381 if( sh4_x86.double_prec == 0 ) {
2382 LEAP_rbpdisp_rptr( REG_OFFSET(fr[0][FRn&0x0E]), REG_EDX );
2383 MOVL_rbpdisp_r32( R_FPUL, REG_EAX );
2384 CALL2_ptr_r32_r32( sh4_fsca, REG_EAX, REG_EDX );
2385 }
2386 sh4_x86.tstate = TSTATE_NONE;
2387 :}
2388 FIPR FVm, FVn {:
2389 COUNT_INST(I_FIPR);
2390 check_fpuen();
2391 if( sh4_x86.double_prec == 0 ) {
2392 if( sh4_x86.sse3_enabled ) {
2393 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[0][FVm<<2]), 4 );
2394 MULPS_rbpdisp_xmm( REG_OFFSET(fr[0][FVn<<2]), 4 );
2395 HADDPS_xmm_xmm( 4, 4 );
2396 HADDPS_xmm_xmm( 4, 4 );
2397 MOVSS_xmm_rbpdisp( 4, REG_OFFSET(fr[0][(FVn<<2)+2]) );
2398 } else {
2399 push_fr( FVm<<2 );
2400 push_fr( FVn<<2 );
2401 FMULP_st(1);
2402 push_fr( (FVm<<2)+1);
2403 push_fr( (FVn<<2)+1);
2404 FMULP_st(1);
2405 FADDP_st(1);
2406 push_fr( (FVm<<2)+2);
2407 push_fr( (FVn<<2)+2);
2408 FMULP_st(1);
2409 FADDP_st(1);
2410 push_fr( (FVm<<2)+3);
2411 push_fr( (FVn<<2)+3);
2412 FMULP_st(1);
2413 FADDP_st(1);
2414 pop_fr( (FVn<<2)+3);
2415 }
2416 }
2417 :}
2418 FTRV XMTRX, FVn {:
2419 COUNT_INST(I_FTRV);
2420 check_fpuen();
2421 if( sh4_x86.double_prec == 0 ) {
2422 if( sh4_x86.sse3_enabled ) {
2423 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][0]), 1 ); // M1 M0 M3 M2
2424 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][4]), 0 ); // M5 M4 M7 M6
2425 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][8]), 3 ); // M9 M8 M11 M10
2426 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][12]), 2 );// M13 M12 M15 M14
2428 MOVSLDUP_rbpdisp_xmm( REG_OFFSET(fr[0][FVn<<2]), 4 ); // V1 V1 V3 V3
2429 MOVSHDUP_rbpdisp_xmm( REG_OFFSET(fr[0][FVn<<2]), 5 ); // V0 V0 V2 V2
2430 MOV_xmm_xmm( 4, 6 );
2431 MOV_xmm_xmm( 5, 7 );
2432 MOVLHPS_xmm_xmm( 4, 4 ); // V1 V1 V1 V1
2433 MOVHLPS_xmm_xmm( 6, 6 ); // V3 V3 V3 V3
2434 MOVLHPS_xmm_xmm( 5, 5 ); // V0 V0 V0 V0
2435 MOVHLPS_xmm_xmm( 7, 7 ); // V2 V2 V2 V2
2436 MULPS_xmm_xmm( 0, 4 );
2437 MULPS_xmm_xmm( 1, 5 );
2438 MULPS_xmm_xmm( 2, 6 );
2439 MULPS_xmm_xmm( 3, 7 );
2440 ADDPS_xmm_xmm( 5, 4 );
2441 ADDPS_xmm_xmm( 7, 6 );
2442 ADDPS_xmm_xmm( 6, 4 );
2443 MOVAPS_xmm_rbpdisp( 4, REG_OFFSET(fr[0][FVn<<2]) );
2444 } else {
2445 LEAP_rbpdisp_rptr( REG_OFFSET(fr[0][FVn<<2]), REG_EAX );
2446 CALL1_ptr_r32( sh4_ftrv, REG_EAX );
2447 }
2448 }
2449 sh4_x86.tstate = TSTATE_NONE;
2450 :}
2452 FRCHG {:
2453 COUNT_INST(I_FRCHG);
2454 check_fpuen();
2455 XORL_imms_rbpdisp( FPSCR_FR, R_FPSCR );
2456 CALL_ptr( sh4_switch_fr_banks );
2457 sh4_x86.tstate = TSTATE_NONE;
2458 :}
2459 FSCHG {:
2460 COUNT_INST(I_FSCHG);
2461 check_fpuen();
2462 XORL_imms_rbpdisp( FPSCR_SZ, R_FPSCR);
2463 XORL_imms_rbpdisp( FPSCR_SZ, REG_OFFSET(xlat_sh4_mode) );
2464 sh4_x86.tstate = TSTATE_NONE;
2465 sh4_x86.double_size = !sh4_x86.double_size;
2466 :}
2468 /* Processor control instructions */
2469 LDC Rm, SR {:
2470 COUNT_INST(I_LDCSR);
2471 if( sh4_x86.in_delay_slot ) {
2472 SLOTILLEGAL();
2473 } else {
2474 check_priv();
2475 load_reg( REG_EAX, Rm );
2476 CALL1_ptr_r32( sh4_write_sr, REG_EAX );
2477 sh4_x86.fpuen_checked = FALSE;
2478 sh4_x86.tstate = TSTATE_NONE;
2479 return 2;
2480 }
2481 :}
2482 LDC Rm, GBR {:
2483 COUNT_INST(I_LDC);
2484 load_reg( REG_EAX, Rm );
2485 MOVL_r32_rbpdisp( REG_EAX, R_GBR );
2486 :}
2487 LDC Rm, VBR {:
2488 COUNT_INST(I_LDC);
2489 check_priv();
2490 load_reg( REG_EAX, Rm );
2491 MOVL_r32_rbpdisp( REG_EAX, R_VBR );
2492 sh4_x86.tstate = TSTATE_NONE;
2493 :}
2494 LDC Rm, SSR {:
2495 COUNT_INST(I_LDC);
2496 check_priv();
2497 load_reg( REG_EAX, Rm );
2498 MOVL_r32_rbpdisp( REG_EAX, R_SSR );
2499 sh4_x86.tstate = TSTATE_NONE;
2500 :}
2501 LDC Rm, SGR {:
2502 COUNT_INST(I_LDC);
2503 check_priv();
2504 load_reg( REG_EAX, Rm );
2505 MOVL_r32_rbpdisp( REG_EAX, R_SGR );
2506 sh4_x86.tstate = TSTATE_NONE;
2507 :}
2508 LDC Rm, SPC {:
2509 COUNT_INST(I_LDC);
2510 check_priv();
2511 load_reg( REG_EAX, Rm );
2512 MOVL_r32_rbpdisp( REG_EAX, R_SPC );
2513 sh4_x86.tstate = TSTATE_NONE;
2514 :}
2515 LDC Rm, DBR {:
2516 COUNT_INST(I_LDC);
2517 check_priv();
2518 load_reg( REG_EAX, Rm );
2519 MOVL_r32_rbpdisp( REG_EAX, R_DBR );
2520 sh4_x86.tstate = TSTATE_NONE;
2521 :}
2522 LDC Rm, Rn_BANK {:
2523 COUNT_INST(I_LDC);
2524 check_priv();
2525 load_reg( REG_EAX, Rm );
2526 MOVL_r32_rbpdisp( REG_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
2527 sh4_x86.tstate = TSTATE_NONE;
2528 :}
2529 LDC.L @Rm+, GBR {:
2530 COUNT_INST(I_LDCM);
2531 load_reg( REG_EAX, Rm );
2532 check_ralign32( REG_EAX );
2533 MEM_READ_LONG( REG_EAX, REG_EAX );
2534 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2535 MOVL_r32_rbpdisp( REG_EAX, R_GBR );
2536 sh4_x86.tstate = TSTATE_NONE;
2537 :}
2538 LDC.L @Rm+, SR {:
2539 COUNT_INST(I_LDCSRM);
2540 if( sh4_x86.in_delay_slot ) {
2541 SLOTILLEGAL();
2542 } else {
2543 check_priv();
2544 load_reg( REG_EAX, Rm );
2545 check_ralign32( REG_EAX );
2546 MEM_READ_LONG( REG_EAX, REG_EAX );
2547 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2548 CALL1_ptr_r32( sh4_write_sr, REG_EAX );
2549 sh4_x86.fpuen_checked = FALSE;
2550 sh4_x86.tstate = TSTATE_NONE;
2551 return 2;
2552 }
2553 :}
2554 LDC.L @Rm+, VBR {:
2555 COUNT_INST(I_LDCM);
2556 check_priv();
2557 load_reg( REG_EAX, Rm );
2558 check_ralign32( REG_EAX );
2559 MEM_READ_LONG( REG_EAX, REG_EAX );
2560 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2561 MOVL_r32_rbpdisp( REG_EAX, R_VBR );
2562 sh4_x86.tstate = TSTATE_NONE;
2563 :}
2564 LDC.L @Rm+, SSR {:
2565 COUNT_INST(I_LDCM);
2566 check_priv();
2567 load_reg( REG_EAX, Rm );
2568 check_ralign32( REG_EAX );
2569 MEM_READ_LONG( REG_EAX, REG_EAX );
2570 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2571 MOVL_r32_rbpdisp( REG_EAX, R_SSR );
2572 sh4_x86.tstate = TSTATE_NONE;
2573 :}
2574 LDC.L @Rm+, SGR {:
2575 COUNT_INST(I_LDCM);
2576 check_priv();
2577 load_reg( REG_EAX, Rm );
2578 check_ralign32( REG_EAX );
2579 MEM_READ_LONG( REG_EAX, REG_EAX );
2580 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2581 MOVL_r32_rbpdisp( REG_EAX, R_SGR );
2582 sh4_x86.tstate = TSTATE_NONE;
2583 :}
2584 LDC.L @Rm+, SPC {:
2585 COUNT_INST(I_LDCM);
2586 check_priv();
2587 load_reg( REG_EAX, Rm );
2588 check_ralign32( REG_EAX );
2589 MEM_READ_LONG( REG_EAX, REG_EAX );
2590 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2591 MOVL_r32_rbpdisp( REG_EAX, R_SPC );
2592 sh4_x86.tstate = TSTATE_NONE;
2593 :}
2594 LDC.L @Rm+, DBR {:
2595 COUNT_INST(I_LDCM);
2596 check_priv();
2597 load_reg( REG_EAX, Rm );
2598 check_ralign32( REG_EAX );
2599 MEM_READ_LONG( REG_EAX, REG_EAX );
2600 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2601 MOVL_r32_rbpdisp( REG_EAX, R_DBR );
2602 sh4_x86.tstate = TSTATE_NONE;
2603 :}
2604 LDC.L @Rm+, Rn_BANK {:
2605 COUNT_INST(I_LDCM);
2606 check_priv();
2607 load_reg( REG_EAX, Rm );
2608 check_ralign32( REG_EAX );
2609 MEM_READ_LONG( REG_EAX, REG_EAX );
2610 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2611 MOVL_r32_rbpdisp( REG_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
2612 sh4_x86.tstate = TSTATE_NONE;
2613 :}
2614 LDS Rm, FPSCR {:
2615 COUNT_INST(I_LDSFPSCR);
2616 check_fpuen();
2617 load_reg( REG_EAX, Rm );
2618 CALL1_ptr_r32( sh4_write_fpscr, REG_EAX );
2619 sh4_x86.tstate = TSTATE_NONE;
2620 return 2;
2621 :}
2622 LDS.L @Rm+, FPSCR {:
2623 COUNT_INST(I_LDSFPSCRM);
2624 check_fpuen();
2625 load_reg( REG_EAX, Rm );
2626 check_ralign32( REG_EAX );
2627 MEM_READ_LONG( REG_EAX, REG_EAX );
2628 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2629 CALL1_ptr_r32( sh4_write_fpscr, REG_EAX );
2630 sh4_x86.tstate = TSTATE_NONE;
2631 return 2;
2632 :}
2633 LDS Rm, FPUL {:
2634 COUNT_INST(I_LDS);
2635 check_fpuen();
2636 load_reg( REG_EAX, Rm );
2637 MOVL_r32_rbpdisp( REG_EAX, R_FPUL );
2638 :}
2639 LDS.L @Rm+, FPUL {:
2640 COUNT_INST(I_LDSM);
2641 check_fpuen();
2642 load_reg( REG_EAX, Rm );
2643 check_ralign32( REG_EAX );
2644 MEM_READ_LONG( REG_EAX, REG_EAX );
2645 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2646 MOVL_r32_rbpdisp( REG_EAX, R_FPUL );
2647 sh4_x86.tstate = TSTATE_NONE;
2648 :}
2649 LDS Rm, MACH {:
2650 COUNT_INST(I_LDS);
2651 load_reg( REG_EAX, Rm );
2652 MOVL_r32_rbpdisp( REG_EAX, R_MACH );
2653 :}
2654 LDS.L @Rm+, MACH {:
2655 COUNT_INST(I_LDSM);
2656 load_reg( REG_EAX, Rm );
2657 check_ralign32( REG_EAX );
2658 MEM_READ_LONG( REG_EAX, REG_EAX );
2659 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2660 MOVL_r32_rbpdisp( REG_EAX, R_MACH );
2661 sh4_x86.tstate = TSTATE_NONE;
2662 :}
2663 LDS Rm, MACL {:
2664 COUNT_INST(I_LDS);
2665 load_reg( REG_EAX, Rm );
2666 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
2667 :}
2668 LDS.L @Rm+, MACL {:
2669 COUNT_INST(I_LDSM);
2670 load_reg( REG_EAX, Rm );
2671 check_ralign32( REG_EAX );
2672 MEM_READ_LONG( REG_EAX, REG_EAX );
2673 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2674 MOVL_r32_rbpdisp( REG_EAX, R_MACL );
2675 sh4_x86.tstate = TSTATE_NONE;
2676 :}
2677 LDS Rm, PR {:
2678 COUNT_INST(I_LDS);
2679 load_reg( REG_EAX, Rm );
2680 MOVL_r32_rbpdisp( REG_EAX, R_PR );
2681 :}
2682 LDS.L @Rm+, PR {:
2683 COUNT_INST(I_LDSM);
2684 load_reg( REG_EAX, Rm );
2685 check_ralign32( REG_EAX );
2686 MEM_READ_LONG( REG_EAX, REG_EAX );
2687 ADDL_imms_rbpdisp( 4, REG_OFFSET(r[Rm]) );
2688 MOVL_r32_rbpdisp( REG_EAX, R_PR );
2689 sh4_x86.tstate = TSTATE_NONE;
2690 :}
2691 LDTLB {:
2692 COUNT_INST(I_LDTLB);
2693 CALL_ptr( MMU_ldtlb );
2694 sh4_x86.tstate = TSTATE_NONE;
2695 :}
2696 OCBI @Rn {:
2697 COUNT_INST(I_OCBI);
2698 :}
2699 OCBP @Rn {:
2700 COUNT_INST(I_OCBP);
2701 :}
2702 OCBWB @Rn {:
2703 COUNT_INST(I_OCBWB);
2704 :}
2705 PREF @Rn {:
2706 COUNT_INST(I_PREF);
2707 load_reg( REG_EAX, Rn );
2708 MEM_PREFETCH( REG_EAX );
2709 sh4_x86.tstate = TSTATE_NONE;
2710 :}
2711 SLEEP {:
2712 COUNT_INST(I_SLEEP);
2713 check_priv();
2714 CALL_ptr( sh4_sleep );
2715 sh4_x86.tstate = TSTATE_NONE;
2716 sh4_x86.in_delay_slot = DELAY_NONE;
2717 return 2;
2718 :}
2719 STC SR, Rn {:
2720 COUNT_INST(I_STCSR);
2721 check_priv();
2722 CALL_ptr(sh4_read_sr);
2723 store_reg( REG_EAX, Rn );
2724 sh4_x86.tstate = TSTATE_NONE;
2725 :}
2726 STC GBR, Rn {:
2727 COUNT_INST(I_STC);
2728 MOVL_rbpdisp_r32( R_GBR, REG_EAX );
2729 store_reg( REG_EAX, Rn );
2730 :}
2731 STC VBR, Rn {:
2732 COUNT_INST(I_STC);
2733 check_priv();
2734 MOVL_rbpdisp_r32( R_VBR, REG_EAX );
2735 store_reg( REG_EAX, Rn );
2736 sh4_x86.tstate = TSTATE_NONE;
2737 :}
2738 STC SSR, Rn {:
2739 COUNT_INST(I_STC);
2740 check_priv();
2741 MOVL_rbpdisp_r32( R_SSR, REG_EAX );
2742 store_reg( REG_EAX, Rn );
2743 sh4_x86.tstate = TSTATE_NONE;
2744 :}
2745 STC SPC, Rn {:
2746 COUNT_INST(I_STC);
2747 check_priv();
2748 MOVL_rbpdisp_r32( R_SPC, REG_EAX );
2749 store_reg( REG_EAX, Rn );
2750 sh4_x86.tstate = TSTATE_NONE;
2751 :}
2752 STC SGR, Rn {:
2753 COUNT_INST(I_STC);
2754 check_priv();
2755 MOVL_rbpdisp_r32( R_SGR, REG_EAX );
2756 store_reg( REG_EAX, Rn );
2757 sh4_x86.tstate = TSTATE_NONE;
2758 :}
2759 STC DBR, Rn {:
2760 COUNT_INST(I_STC);
2761 check_priv();
2762 MOVL_rbpdisp_r32( R_DBR, REG_EAX );
2763 store_reg( REG_EAX, Rn );
2764 sh4_x86.tstate = TSTATE_NONE;
2765 :}
2766 STC Rm_BANK, Rn {:
2767 COUNT_INST(I_STC);
2768 check_priv();
2769 MOVL_rbpdisp_r32( REG_OFFSET(r_bank[Rm_BANK]), REG_EAX );
2770 store_reg( REG_EAX, Rn );
2771 sh4_x86.tstate = TSTATE_NONE;
2772 :}
2773 STC.L SR, @-Rn {:
2774 COUNT_INST(I_STCSRM);
2775 check_priv();
2776 CALL_ptr( sh4_read_sr );
2777 MOVL_r32_r32( REG_EAX, REG_EDX );
2778 load_reg( REG_EAX, Rn );
2779 check_walign32( REG_EAX );
2780 LEAL_r32disp_r32( REG_EAX, -4, REG_EAX );
2781 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2782 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2783 sh4_x86.tstate = TSTATE_NONE;
2784 :}
2785 STC.L VBR, @-Rn {:
2786 COUNT_INST(I_STCM);
2787 check_priv();
2788 load_reg( REG_EAX, Rn );
2789 check_walign32( REG_EAX );
2790 ADDL_imms_r32( -4, REG_EAX );
2791 MOVL_rbpdisp_r32( R_VBR, REG_EDX );
2792 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2793 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2794 sh4_x86.tstate = TSTATE_NONE;
2795 :}
2796 STC.L SSR, @-Rn {:
2797 COUNT_INST(I_STCM);
2798 check_priv();
2799 load_reg( REG_EAX, Rn );
2800 check_walign32( REG_EAX );
2801 ADDL_imms_r32( -4, REG_EAX );
2802 MOVL_rbpdisp_r32( R_SSR, REG_EDX );
2803 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2804 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2805 sh4_x86.tstate = TSTATE_NONE;
2806 :}
2807 STC.L SPC, @-Rn {:
2808 COUNT_INST(I_STCM);
2809 check_priv();
2810 load_reg( REG_EAX, Rn );
2811 check_walign32( REG_EAX );
2812 ADDL_imms_r32( -4, REG_EAX );
2813 MOVL_rbpdisp_r32( R_SPC, REG_EDX );
2814 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2815 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2816 sh4_x86.tstate = TSTATE_NONE;
2817 :}
2818 STC.L SGR, @-Rn {:
2819 COUNT_INST(I_STCM);
2820 check_priv();
2821 load_reg( REG_EAX, Rn );
2822 check_walign32( REG_EAX );
2823 ADDL_imms_r32( -4, REG_EAX );
2824 MOVL_rbpdisp_r32( R_SGR, REG_EDX );
2825 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2826 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2827 sh4_x86.tstate = TSTATE_NONE;
2828 :}
2829 STC.L DBR, @-Rn {:
2830 COUNT_INST(I_STCM);
2831 check_priv();
2832 load_reg( REG_EAX, Rn );
2833 check_walign32( REG_EAX );
2834 ADDL_imms_r32( -4, REG_EAX );
2835 MOVL_rbpdisp_r32( R_DBR, REG_EDX );
2836 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2837 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2838 sh4_x86.tstate = TSTATE_NONE;
2839 :}
2840 STC.L Rm_BANK, @-Rn {:
2841 COUNT_INST(I_STCM);
2842 check_priv();
2843 load_reg( REG_EAX, Rn );
2844 check_walign32( REG_EAX );
2845 ADDL_imms_r32( -4, REG_EAX );
2846 MOVL_rbpdisp_r32( REG_OFFSET(r_bank[Rm_BANK]), REG_EDX );
2847 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2848 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2849 sh4_x86.tstate = TSTATE_NONE;
2850 :}
2851 STC.L GBR, @-Rn {:
2852 COUNT_INST(I_STCM);
2853 load_reg( REG_EAX, Rn );
2854 check_walign32( REG_EAX );
2855 ADDL_imms_r32( -4, REG_EAX );
2856 MOVL_rbpdisp_r32( R_GBR, REG_EDX );
2857 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2858 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2859 sh4_x86.tstate = TSTATE_NONE;
2860 :}
2861 STS FPSCR, Rn {:
2862 COUNT_INST(I_STSFPSCR);
2863 check_fpuen();
2864 MOVL_rbpdisp_r32( R_FPSCR, REG_EAX );
2865 store_reg( REG_EAX, Rn );
2866 :}
2867 STS.L FPSCR, @-Rn {:
2868 COUNT_INST(I_STSFPSCRM);
2869 check_fpuen();
2870 load_reg( REG_EAX, Rn );
2871 check_walign32( REG_EAX );
2872 ADDL_imms_r32( -4, REG_EAX );
2873 MOVL_rbpdisp_r32( R_FPSCR, REG_EDX );
2874 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2875 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2876 sh4_x86.tstate = TSTATE_NONE;
2877 :}
2878 STS FPUL, Rn {:
2879 COUNT_INST(I_STS);
2880 check_fpuen();
2881 MOVL_rbpdisp_r32( R_FPUL, REG_EAX );
2882 store_reg( REG_EAX, Rn );
2883 :}
2884 STS.L FPUL, @-Rn {:
2885 COUNT_INST(I_STSM);
2886 check_fpuen();
2887 load_reg( REG_EAX, Rn );
2888 check_walign32( REG_EAX );
2889 ADDL_imms_r32( -4, REG_EAX );
2890 MOVL_rbpdisp_r32( R_FPUL, REG_EDX );
2891 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2892 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2893 sh4_x86.tstate = TSTATE_NONE;
2894 :}
2895 STS MACH, Rn {:
2896 COUNT_INST(I_STS);
2897 MOVL_rbpdisp_r32( R_MACH, REG_EAX );
2898 store_reg( REG_EAX, Rn );
2899 :}
2900 STS.L MACH, @-Rn {:
2901 COUNT_INST(I_STSM);
2902 load_reg( REG_EAX, Rn );
2903 check_walign32( REG_EAX );
2904 ADDL_imms_r32( -4, REG_EAX );
2905 MOVL_rbpdisp_r32( R_MACH, REG_EDX );
2906 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2907 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2908 sh4_x86.tstate = TSTATE_NONE;
2909 :}
2910 STS MACL, Rn {:
2911 COUNT_INST(I_STS);
2912 MOVL_rbpdisp_r32( R_MACL, REG_EAX );
2913 store_reg( REG_EAX, Rn );
2914 :}
2915 STS.L MACL, @-Rn {:
2916 COUNT_INST(I_STSM);
2917 load_reg( REG_EAX, Rn );
2918 check_walign32( REG_EAX );
2919 ADDL_imms_r32( -4, REG_EAX );
2920 MOVL_rbpdisp_r32( R_MACL, REG_EDX );
2921 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2922 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2923 sh4_x86.tstate = TSTATE_NONE;
2924 :}
2925 STS PR, Rn {:
2926 COUNT_INST(I_STS);
2927 MOVL_rbpdisp_r32( R_PR, REG_EAX );
2928 store_reg( REG_EAX, Rn );
2929 :}
2930 STS.L PR, @-Rn {:
2931 COUNT_INST(I_STSM);
2932 load_reg( REG_EAX, Rn );
2933 check_walign32( REG_EAX );
2934 ADDL_imms_r32( -4, REG_EAX );
2935 MOVL_rbpdisp_r32( R_PR, REG_EDX );
2936 MEM_WRITE_LONG( REG_EAX, REG_EDX );
2937 ADDL_imms_rbpdisp( -4, REG_OFFSET(r[Rn]) );
2938 sh4_x86.tstate = TSTATE_NONE;
2939 :}
2941 NOP {:
2942 COUNT_INST(I_NOP);
2943 /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */
2944 :}
2945 %%
2946 sh4_x86.in_delay_slot = DELAY_NONE;
2947 return 0;
2948 }
2951 /**
2952 * The unwind methods only work if we compiled with DWARF2 frame information
2953 * (ie -fexceptions), otherwise we have to use the direct frame scan.
2954 */
2955 #ifdef HAVE_EXCEPTIONS
2956 #include <unwind.h>
2958 struct UnwindInfo {
2959 uintptr_t block_start;
2960 uintptr_t block_end;
2961 void *pc;
2962 };
2964 static _Unwind_Reason_Code xlat_check_frame( struct _Unwind_Context *context, void *arg )
2965 {
2966 struct UnwindInfo *info = arg;
2967 void *pc = (void *)_Unwind_GetIP(context);
2968 if( ((uintptr_t)pc) >= info->block_start && ((uintptr_t)pc) < info->block_end ) {
2969 info->pc = pc;
2970 return _URC_NORMAL_STOP;
2971 }
2972 return _URC_NO_REASON;
2973 }
2975 void *xlat_get_native_pc( void *code, uint32_t code_size )
2976 {
2977 struct _Unwind_Exception exc;
2978 struct UnwindInfo info;
2980 info.pc = NULL;
2981 info.block_start = (uintptr_t)code;
2982 info.block_end = info.block_start + code_size;
2983 void *result = NULL;
2984 _Unwind_Backtrace( xlat_check_frame, &info );
2985 return info.pc;
2986 }
2987 #else
2988 /* Assume this is an ia32 build - amd64 should always have dwarf information */
2989 void *xlat_get_native_pc( void *code, uint32_t code_size )
2990 {
2991 void *result = NULL;
2992 asm(
2993 "mov %%ebp, %%eax\n\t"
2994 "mov $0x8, %%ecx\n\t"
2995 "mov %1, %%edx\n"
2996 "frame_loop: test %%eax, %%eax\n\t"
2997 "je frame_not_found\n\t"
2998 "cmp (%%eax), %%edx\n\t"
2999 "je frame_found\n\t"
3000 "sub $0x1, %%ecx\n\t"
3001 "je frame_not_found\n\t"
3002 "movl (%%eax), %%eax\n\t"
3003 "jmp frame_loop\n"
3004 "frame_found: movl 0x4(%%eax), %0\n"
3005 "frame_not_found:"
3006 : "=r" (result)
3007 : "r" (((uint8_t *)&sh4r) + 128 )
3008 : "eax", "ecx", "edx" );
3009 return result;
3010 }
3011 #endif
.