filename | src/sh4/sh4x86.in |
changeset | 374:8f80a795513e |
prev | 368:36fac4c42322 |
next | 375:4627600f7f8e |
author | nkeynes |
date | Tue Sep 11 02:14:46 2007 +0000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Cache the pointer to the last FR bank (speeds fp ops up by about 10%) Implement experimental fix for FLOAT/FTRC Make read/write sr functions non-static (share with translator) Much more translator WIP |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4x86.in,v 1.4 2007-09-11 02:14:46 nkeynes Exp $
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>
23 #include "sh4/sh4core.h"
24 #include "sh4/sh4trans.h"
25 #include "sh4/x86op.h"
26 #include "clock.h"
28 #define DEFAULT_BACKPATCH_SIZE 4096
30 /**
31 * Struct to manage internal translation state. This state is not saved -
32 * it is only valid between calls to sh4_translate_begin_block() and
33 * sh4_translate_end_block()
34 */
35 struct sh4_x86_state {
36 gboolean in_delay_slot;
37 gboolean priv_checked; /* true if we've already checked the cpu mode. */
38 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
40 /* Allocated memory for the (block-wide) back-patch list */
41 uint32_t **backpatch_list;
42 uint32_t backpatch_posn;
43 uint32_t backpatch_size;
44 };
46 #define EXIT_DATA_ADDR_READ 0
47 #define EXIT_DATA_ADDR_WRITE 7
48 #define EXIT_ILLEGAL 14
49 #define EXIT_SLOT_ILLEGAL 21
50 #define EXIT_FPU_DISABLED 28
51 #define EXIT_SLOT_FPU_DISABLED 35
53 static struct sh4_x86_state sh4_x86;
55 void sh4_x86_init()
56 {
57 sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
58 sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(uint32_t *);
59 }
62 static void sh4_x86_add_backpatch( uint8_t *ptr )
63 {
64 if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
65 sh4_x86.backpatch_size <<= 1;
66 sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list, sh4_x86.backpatch_size * sizeof(uint32_t *) );
67 assert( sh4_x86.backpatch_list != NULL );
68 }
69 sh4_x86.backpatch_list[sh4_x86.backpatch_posn++] = (uint32_t *)ptr;
70 }
72 static void sh4_x86_do_backpatch( uint8_t *reloc_base )
73 {
74 unsigned int i;
75 for( i=0; i<sh4_x86.backpatch_posn; i++ ) {
76 *sh4_x86.backpatch_list[i] += (reloc_base - ((uint8_t *)sh4_x86.backpatch_list[i]) - 4);
77 }
78 }
80 #ifndef NDEBUG
81 #define MARK_JMP(x,n) uint8_t *_mark_jmp_##x = xlat_output + n
82 #define CHECK_JMP(x) assert( _mark_jmp_##x == xlat_output )
83 #else
84 #define MARK_JMP(x,n)
85 #define CHECK_JMP(x)
86 #endif
89 /**
90 * Emit an instruction to load an SH4 reg into a real register
91 */
92 static inline void load_reg( int x86reg, int sh4reg )
93 {
94 /* mov [bp+n], reg */
95 OP(0x8B);
96 OP(0x45 + (x86reg<<3));
97 OP(REG_OFFSET(r[sh4reg]));
98 }
100 static inline void load_reg16s( int x86reg, int sh4reg )
101 {
102 OP(0x0F);
103 OP(0xBF);
104 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
105 }
107 static inline void load_reg16u( int x86reg, int sh4reg )
108 {
109 OP(0x0F);
110 OP(0xB7);
111 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
113 }
115 static inline void load_spreg( int x86reg, int regoffset )
116 {
117 /* mov [bp+n], reg */
118 OP(0x8B);
119 OP(0x45 + (x86reg<<3));
120 OP(regoffset);
121 }
123 /**
124 * Emit an instruction to load an immediate value into a register
125 */
126 static inline void load_imm32( int x86reg, uint32_t value ) {
127 /* mov #value, reg */
128 OP(0xB8 + x86reg);
129 OP32(value);
130 }
132 /**
133 * Emit an instruction to store an SH4 reg (RN)
134 */
135 void static inline store_reg( int x86reg, int sh4reg ) {
136 /* mov reg, [bp+n] */
137 OP(0x89);
138 OP(0x45 + (x86reg<<3));
139 OP(REG_OFFSET(r[sh4reg]));
140 }
141 void static inline store_spreg( int x86reg, int regoffset ) {
142 /* mov reg, [bp+n] */
143 OP(0x89);
144 OP(0x45 + (x86reg<<3));
145 OP(regoffset);
146 }
149 #define load_fr_bank(bankreg) load_spreg( bankreg, REG_OFFSET(fr_bank))
151 static inline void load_xf_bank( int bankreg )
152 {
153 load_spreg( bankreg, R_FPSCR );
154 SHR_imm8_r32( (21 - 6), bankreg ); // Extract bit 21 then *64 for bank size
155 AND_imm8s_r32( 0x40, bankreg ); // Complete extraction
156 OP(0x8D); OP(0x44+(bankreg<<3)); OP(0x28+bankreg); OP(REG_OFFSET(fr)); // LEA [ebp+bankreg+disp], bankreg
157 }
159 static inline void push_fr( int bankreg, int frm )
160 {
161 OP(0xD9); OP(0x40 + bankreg); OP((frm^1)<<2); // FLD.S [bankreg + frm^1*4]
162 }
164 static inline void pop_fr( int bankreg, int frm )
165 {
166 OP(0xD9); OP(0x58 + bankreg); OP((frm^1)<<2); // FST.S [bankreg + frm^1*4]
167 }
169 static inline void push_dr( int bankreg, int frm )
170 {
171 if( frm&1 ) {
172 // this is technically undefined, but it seems to work consistently - high 32 bits
173 // loaded from FRm (32-bits), low 32bits are 0.
174 OP(0xFF); OP(0x70 + bankreg); OP((frm^1)<<2); // PUSH [bankreg + frm^1]
175 PUSH_imm32(0);
178 } else {
179 OP(0xDD); OP(0x40 + bankreg); OP(frm<<2); // FLD.D [bankreg + frm*4]
180 }
181 }
183 static inline void pop_dr( int bankreg, int frm )
184 {
185 if( frm&1 ) {
186 } else {
187 OP(0xDD); OP(0x58 + bankreg); OP(frm<<2); // FST.D [bankreg + frm*4]
188 }
189 }
191 /**
192 * Note: clobbers EAX to make the indirect call - this isn't usually
193 * a problem since the callee will usually clobber it anyway.
194 */
195 static inline void call_func0( void *ptr )
196 {
197 load_imm32(R_EAX, (uint32_t)ptr);
198 CALL_r32(R_EAX);
199 }
201 static inline void call_func1( void *ptr, int arg1 )
202 {
203 PUSH_r32(arg1);
204 call_func0(ptr);
205 ADD_imm8s_r32( -4, R_ESP );
206 }
208 static inline void call_func2( void *ptr, int arg1, int arg2 )
209 {
210 PUSH_r32(arg2);
211 PUSH_r32(arg1);
212 call_func0(ptr);
213 ADD_imm8s_r32( -4, R_ESP );
214 }
216 /* Exception checks - Note that all exception checks will clobber EAX */
217 static void check_priv( )
218 {
219 if( !sh4_x86.priv_checked ) {
220 sh4_x86.priv_checked = TRUE;
221 load_spreg( R_EAX, R_SR );
222 AND_imm32_r32( SR_MD, R_EAX );
223 if( sh4_x86.in_delay_slot ) {
224 JE_exit( EXIT_SLOT_ILLEGAL );
225 } else {
226 JE_exit( EXIT_ILLEGAL );
227 }
228 }
229 }
231 static void check_fpuen( )
232 {
233 if( !sh4_x86.fpuen_checked ) {
234 sh4_x86.fpuen_checked = TRUE;
235 load_spreg( R_EAX, R_SR );
236 AND_imm32_r32( SR_FD, R_EAX );
237 if( sh4_x86.in_delay_slot ) {
238 JNE_exit(EXIT_SLOT_FPU_DISABLED);
239 } else {
240 JNE_exit(EXIT_FPU_DISABLED);
241 }
242 }
243 }
245 static void check_ralign16( int x86reg )
246 {
247 TEST_imm32_r32( 0x00000001, x86reg );
248 JNE_exit(EXIT_DATA_ADDR_READ);
249 }
251 static void check_walign16( int x86reg )
252 {
253 TEST_imm32_r32( 0x00000001, x86reg );
254 JNE_exit(EXIT_DATA_ADDR_WRITE);
255 }
257 static void check_ralign32( int x86reg )
258 {
259 TEST_imm32_r32( 0x00000003, x86reg );
260 JNE_exit(EXIT_DATA_ADDR_READ);
261 }
262 static void check_walign32( int x86reg )
263 {
264 TEST_imm32_r32( 0x00000003, x86reg );
265 JNE_exit(EXIT_DATA_ADDR_WRITE);
266 }
269 #define UNDEF()
270 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
271 #define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
272 #define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
273 #define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
274 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
275 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
276 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
278 #define RAISE_EXCEPTION( exc ) call_func1(sh4_raise_exception, exc);
279 #define SLOTILLEGAL() RAISE_EXCEPTION(EXC_SLOT_ILLEGAL); return 1
283 /**
284 * Emit the 'start of block' assembly. Sets up the stack frame and save
285 * SI/DI as required
286 */
287 void sh4_translate_begin_block()
288 {
289 PUSH_r32(R_EBP);
290 /* mov &sh4r, ebp */
291 load_imm32( R_EBP, (uint32_t)&sh4r );
292 PUSH_r32(R_EDI);
293 PUSH_r32(R_ESI);
295 sh4_x86.in_delay_slot = FALSE;
296 sh4_x86.priv_checked = FALSE;
297 sh4_x86.fpuen_checked = FALSE;
298 sh4_x86.backpatch_posn = 0;
299 }
301 /**
302 * Exit the block early (ie branch out), conditionally or otherwise
303 */
304 void exit_block( )
305 {
306 store_spreg( R_EDI, REG_OFFSET(pc) );
307 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
308 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
309 MUL_r32( R_ESI );
310 ADD_r32_r32( R_EAX, R_ECX );
311 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
312 XOR_r32_r32( R_EAX, R_EAX );
313 POP_r32(R_ESI);
314 POP_r32(R_EDI);
315 POP_r32(R_EBP);
316 RET();
317 }
319 /**
320 * Flush any open regs back to memory, restore SI/DI/, update PC, etc
321 */
322 void sh4_translate_end_block( sh4addr_t pc ) {
323 assert( !sh4_x86.in_delay_slot ); // should never stop here
324 // Normal termination - save PC, cycle count
325 exit_block( );
327 uint8_t *end_ptr = xlat_output;
328 // Exception termination. Jump block for various exception codes:
329 PUSH_imm32( EXC_DATA_ADDR_READ );
330 JMP_rel8( 33 );
331 PUSH_imm32( EXC_DATA_ADDR_WRITE );
332 JMP_rel8( 26 );
333 PUSH_imm32( EXC_ILLEGAL );
334 JMP_rel8( 19 );
335 PUSH_imm32( EXC_SLOT_ILLEGAL );
336 JMP_rel8( 12 );
337 PUSH_imm32( EXC_FPU_DISABLED );
338 JMP_rel8( 5 );
339 PUSH_imm32( EXC_SLOT_FPU_DISABLED );
340 // target
341 load_spreg( R_ECX, REG_OFFSET(pc) );
342 ADD_r32_r32( R_ESI, R_ECX );
343 ADD_r32_r32( R_ESI, R_ECX );
344 store_spreg( R_ECX, REG_OFFSET(pc) );
345 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
346 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
347 MUL_r32( R_ESI );
348 ADD_r32_r32( R_EAX, R_ECX );
349 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
351 load_imm32( R_EAX, (uint32_t)sh4_raise_exception ); // 6
352 CALL_r32( R_EAX ); // 2
353 POP_r32(R_EBP);
354 RET();
356 sh4_x86_do_backpatch( end_ptr );
357 }
359 /**
360 * Translate a single instruction. Delayed branches are handled specially
361 * by translating both branch and delayed instruction as a single unit (as
362 *
363 *
364 * @return true if the instruction marks the end of a basic block
365 * (eg a branch or
366 */
367 uint32_t sh4_x86_translate_instruction( uint32_t pc )
368 {
369 uint16_t ir = sh4_read_word( pc );
371 %%
372 /* ALU operations */
373 ADD Rm, Rn {:
374 load_reg( R_EAX, Rm );
375 load_reg( R_ECX, Rn );
376 ADD_r32_r32( R_EAX, R_ECX );
377 store_reg( R_ECX, Rn );
378 :}
379 ADD #imm, Rn {:
380 load_reg( R_EAX, Rn );
381 ADD_imm8s_r32( imm, R_EAX );
382 store_reg( R_EAX, Rn );
383 :}
384 ADDC Rm, Rn {:
385 load_reg( R_EAX, Rm );
386 load_reg( R_ECX, Rn );
387 LDC_t();
388 ADC_r32_r32( R_EAX, R_ECX );
389 store_reg( R_ECX, Rn );
390 SETC_t();
391 :}
392 ADDV Rm, Rn {:
393 load_reg( R_EAX, Rm );
394 load_reg( R_ECX, Rn );
395 ADD_r32_r32( R_EAX, R_ECX );
396 store_reg( R_ECX, Rn );
397 SETO_t();
398 :}
399 AND Rm, Rn {:
400 load_reg( R_EAX, Rm );
401 load_reg( R_ECX, Rn );
402 AND_r32_r32( R_EAX, R_ECX );
403 store_reg( R_ECX, Rn );
404 :}
405 AND #imm, R0 {:
406 load_reg( R_EAX, 0 );
407 AND_imm32_r32(imm, R_EAX);
408 store_reg( R_EAX, 0 );
409 :}
410 AND.B #imm, @(R0, GBR) {:
411 load_reg( R_EAX, 0 );
412 load_spreg( R_ECX, R_GBR );
413 ADD_r32_r32( R_EAX, R_ECX );
414 MEM_READ_BYTE( R_ECX, R_EAX );
415 AND_imm32_r32(imm, R_ECX );
416 MEM_WRITE_BYTE( R_ECX, R_EAX );
417 :}
418 CMP/EQ Rm, Rn {:
419 load_reg( R_EAX, Rm );
420 load_reg( R_ECX, Rn );
421 CMP_r32_r32( R_EAX, R_ECX );
422 SETE_t();
423 :}
424 CMP/EQ #imm, R0 {:
425 load_reg( R_EAX, 0 );
426 CMP_imm8s_r32(imm, R_EAX);
427 SETE_t();
428 :}
429 CMP/GE Rm, Rn {:
430 load_reg( R_EAX, Rm );
431 load_reg( R_ECX, Rn );
432 CMP_r32_r32( R_EAX, R_ECX );
433 SETGE_t();
434 :}
435 CMP/GT Rm, Rn {:
436 load_reg( R_EAX, Rm );
437 load_reg( R_ECX, Rn );
438 CMP_r32_r32( R_EAX, R_ECX );
439 SETG_t();
440 :}
441 CMP/HI Rm, Rn {:
442 load_reg( R_EAX, Rm );
443 load_reg( R_ECX, Rn );
444 CMP_r32_r32( R_EAX, R_ECX );
445 SETA_t();
446 :}
447 CMP/HS Rm, Rn {:
448 load_reg( R_EAX, Rm );
449 load_reg( R_ECX, Rn );
450 CMP_r32_r32( R_EAX, R_ECX );
451 SETAE_t();
452 :}
453 CMP/PL Rn {:
454 load_reg( R_EAX, Rn );
455 CMP_imm8s_r32( 0, R_EAX );
456 SETG_t();
457 :}
458 CMP/PZ Rn {:
459 load_reg( R_EAX, Rn );
460 CMP_imm8s_r32( 0, R_EAX );
461 SETGE_t();
462 :}
463 CMP/STR Rm, Rn {:
464 load_reg( R_EAX, Rm );
465 load_reg( R_ECX, Rn );
466 XOR_r32_r32( R_ECX, R_EAX );
467 TEST_r8_r8( R_AL, R_AL );
468 JE_rel8(13);
469 TEST_r8_r8( R_AH, R_AH ); // 2
470 JE_rel8(9);
471 SHR_imm8_r32( 16, R_EAX ); // 3
472 TEST_r8_r8( R_AL, R_AL ); // 2
473 JE_rel8(2);
474 TEST_r8_r8( R_AH, R_AH ); // 2
475 SETE_t();
476 :}
477 DIV0S Rm, Rn {:
478 load_reg( R_EAX, Rm );
479 load_reg( R_ECX, Rm );
480 SHR_imm8_r32( 31, R_EAX );
481 SHR_imm8_r32( 31, R_ECX );
482 store_spreg( R_EAX, R_M );
483 store_spreg( R_ECX, R_Q );
484 CMP_r32_r32( R_EAX, R_ECX );
485 SETE_t();
486 :}
487 DIV0U {:
488 XOR_r32_r32( R_EAX, R_EAX );
489 store_spreg( R_EAX, R_Q );
490 store_spreg( R_EAX, R_M );
491 store_spreg( R_EAX, R_T );
492 :}
493 DIV1 Rm, Rn {:
494 load_reg( R_ECX, Rn );
495 LDC_t();
496 RCL1_r32( R_ECX ); // OP2
497 SETC_r32( R_EDX ); // Q
498 load_spreg( R_EAX, R_Q );
499 CMP_sh4r_r32( R_M, R_EAX );
500 JE_rel8(8);
501 ADD_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
502 JMP_rel8(3);
503 SUB_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
504 // TODO
505 :}
506 DMULS.L Rm, Rn {:
507 load_reg( R_EAX, Rm );
508 load_reg( R_ECX, Rn );
509 IMUL_r32(R_ECX);
510 store_spreg( R_EDX, R_MACH );
511 store_spreg( R_EAX, R_MACL );
512 :}
513 DMULU.L Rm, Rn {:
514 load_reg( R_EAX, Rm );
515 load_reg( R_ECX, Rn );
516 MUL_r32(R_ECX);
517 store_spreg( R_EDX, R_MACH );
518 store_spreg( R_EAX, R_MACL );
519 :}
520 DT Rn {:
521 load_reg( R_EAX, Rn );
522 ADD_imm8s_r32( -1, Rn );
523 store_reg( R_EAX, Rn );
524 SETE_t();
525 :}
526 EXTS.B Rm, Rn {:
527 load_reg( R_EAX, Rm );
528 MOVSX_r8_r32( R_EAX, R_EAX );
529 store_reg( R_EAX, Rn );
530 :}
531 EXTS.W Rm, Rn {:
532 load_reg( R_EAX, Rm );
533 MOVSX_r16_r32( R_EAX, R_EAX );
534 store_reg( R_EAX, Rn );
535 :}
536 EXTU.B Rm, Rn {:
537 load_reg( R_EAX, Rm );
538 MOVZX_r8_r32( R_EAX, R_EAX );
539 store_reg( R_EAX, Rn );
540 :}
541 EXTU.W Rm, Rn {:
542 load_reg( R_EAX, Rm );
543 MOVZX_r16_r32( R_EAX, R_EAX );
544 store_reg( R_EAX, Rn );
545 :}
546 MAC.L @Rm+, @Rn+ {: :}
547 MAC.W @Rm+, @Rn+ {: :}
548 MOVT Rn {:
549 load_spreg( R_EAX, R_T );
550 store_reg( R_EAX, Rn );
551 :}
552 MUL.L Rm, Rn {:
553 load_reg( R_EAX, Rm );
554 load_reg( R_ECX, Rn );
555 MUL_r32( R_ECX );
556 store_spreg( R_EAX, R_MACL );
557 :}
558 MULS.W Rm, Rn {:
559 load_reg16s( R_EAX, Rm );
560 load_reg16s( R_ECX, Rn );
561 MUL_r32( R_ECX );
562 store_spreg( R_EAX, R_MACL );
563 :}
564 MULU.W Rm, Rn {:
565 load_reg16u( R_EAX, Rm );
566 load_reg16u( R_ECX, Rn );
567 MUL_r32( R_ECX );
568 store_spreg( R_EAX, R_MACL );
569 :}
570 NEG Rm, Rn {:
571 load_reg( R_EAX, Rm );
572 NEG_r32( R_EAX );
573 store_reg( R_EAX, Rn );
574 :}
575 NEGC Rm, Rn {:
576 load_reg( R_EAX, Rm );
577 XOR_r32_r32( R_ECX, R_ECX );
578 LDC_t();
579 SBB_r32_r32( R_EAX, R_ECX );
580 store_reg( R_ECX, Rn );
581 SETC_t();
582 :}
583 NOT Rm, Rn {:
584 load_reg( R_EAX, Rm );
585 NOT_r32( R_EAX );
586 store_reg( R_EAX, Rn );
587 :}
588 OR Rm, Rn {:
589 load_reg( R_EAX, Rm );
590 load_reg( R_ECX, Rn );
591 OR_r32_r32( R_EAX, R_ECX );
592 store_reg( R_ECX, Rn );
593 :}
594 OR #imm, R0 {:
595 load_reg( R_EAX, 0 );
596 OR_imm32_r32(imm, R_EAX);
597 store_reg( R_EAX, 0 );
598 :}
599 OR.B #imm, @(R0, GBR) {:
600 load_reg( R_EAX, 0 );
601 load_spreg( R_ECX, R_GBR );
602 ADD_r32_r32( R_EAX, R_ECX );
603 MEM_READ_BYTE( R_ECX, R_EAX );
604 OR_imm32_r32(imm, R_ECX );
605 MEM_WRITE_BYTE( R_ECX, R_EAX );
606 :}
607 ROTCL Rn {:
608 load_reg( R_EAX, Rn );
609 LDC_t();
610 RCL1_r32( R_EAX );
611 store_reg( R_EAX, Rn );
612 SETC_t();
613 :}
614 ROTCR Rn {:
615 load_reg( R_EAX, Rn );
616 LDC_t();
617 RCR1_r32( R_EAX );
618 store_reg( R_EAX, Rn );
619 SETC_t();
620 :}
621 ROTL Rn {:
622 load_reg( R_EAX, Rn );
623 ROL1_r32( R_EAX );
624 store_reg( R_EAX, Rn );
625 SETC_t();
626 :}
627 ROTR Rn {:
628 load_reg( R_EAX, Rn );
629 ROR1_r32( R_EAX );
630 store_reg( R_EAX, Rn );
631 SETC_t();
632 :}
633 SHAD Rm, Rn {:
634 /* Annoyingly enough, not directly convertible */
635 load_reg( R_EAX, Rn );
636 load_reg( R_ECX, Rm );
637 CMP_imm32_r32( 0, R_ECX );
638 JAE_rel8(9);
640 NEG_r32( R_ECX ); // 2
641 AND_imm8_r8( 0x1F, R_CL ); // 3
642 SAR_r32_CL( R_EAX ); // 2
643 JMP_rel8(5); // 2
645 AND_imm8_r8( 0x1F, R_CL ); // 3
646 SHL_r32_CL( R_EAX ); // 2
648 store_reg( R_EAX, Rn );
649 :}
650 SHLD Rm, Rn {:
651 load_reg( R_EAX, Rn );
652 load_reg( R_ECX, Rm );
654 MOV_r32_r32( R_EAX, R_EDX );
655 SHL_r32_CL( R_EAX );
656 NEG_r32( R_ECX );
657 SHR_r32_CL( R_EDX );
658 CMP_imm8s_r32( 0, R_ECX );
659 CMOVAE_r32_r32( R_EDX, R_EAX );
660 store_reg( R_EAX, Rn );
661 :}
662 SHAL Rn {:
663 load_reg( R_EAX, Rn );
664 SHL1_r32( R_EAX );
665 store_reg( R_EAX, Rn );
666 :}
667 SHAR Rn {:
668 load_reg( R_EAX, Rn );
669 SAR1_r32( R_EAX );
670 store_reg( R_EAX, Rn );
671 :}
672 SHLL Rn {:
673 load_reg( R_EAX, Rn );
674 SHL1_r32( R_EAX );
675 store_reg( R_EAX, Rn );
676 :}
677 SHLL2 Rn {:
678 load_reg( R_EAX, Rn );
679 SHL_imm8_r32( 2, R_EAX );
680 store_reg( R_EAX, Rn );
681 :}
682 SHLL8 Rn {:
683 load_reg( R_EAX, Rn );
684 SHL_imm8_r32( 8, R_EAX );
685 store_reg( R_EAX, Rn );
686 :}
687 SHLL16 Rn {:
688 load_reg( R_EAX, Rn );
689 SHL_imm8_r32( 16, R_EAX );
690 store_reg( R_EAX, Rn );
691 :}
692 SHLR Rn {:
693 load_reg( R_EAX, Rn );
694 SHR1_r32( R_EAX );
695 store_reg( R_EAX, Rn );
696 :}
697 SHLR2 Rn {:
698 load_reg( R_EAX, Rn );
699 SHR_imm8_r32( 2, R_EAX );
700 store_reg( R_EAX, Rn );
701 :}
702 SHLR8 Rn {:
703 load_reg( R_EAX, Rn );
704 SHR_imm8_r32( 8, R_EAX );
705 store_reg( R_EAX, Rn );
706 :}
707 SHLR16 Rn {:
708 load_reg( R_EAX, Rn );
709 SHR_imm8_r32( 16, R_EAX );
710 store_reg( R_EAX, Rn );
711 :}
712 SUB Rm, Rn {:
713 load_reg( R_EAX, Rm );
714 load_reg( R_ECX, Rn );
715 SUB_r32_r32( R_EAX, R_ECX );
716 store_reg( R_ECX, Rn );
717 :}
718 SUBC Rm, Rn {:
719 load_reg( R_EAX, Rm );
720 load_reg( R_ECX, Rn );
721 LDC_t();
722 SBB_r32_r32( R_EAX, R_ECX );
723 store_reg( R_ECX, Rn );
724 :}
725 SUBV Rm, Rn {:
726 load_reg( R_EAX, Rm );
727 load_reg( R_ECX, Rn );
728 SUB_r32_r32( R_EAX, R_ECX );
729 store_reg( R_ECX, Rn );
730 SETO_t();
731 :}
732 SWAP.B Rm, Rn {:
733 load_reg( R_EAX, Rm );
734 XCHG_r8_r8( R_AL, R_AH );
735 store_reg( R_EAX, Rn );
736 :}
737 SWAP.W Rm, Rn {:
738 load_reg( R_EAX, Rm );
739 MOV_r32_r32( R_EAX, R_ECX );
740 SHL_imm8_r32( 16, R_ECX );
741 SHR_imm8_r32( 16, R_EAX );
742 OR_r32_r32( R_EAX, R_ECX );
743 store_reg( R_ECX, Rn );
744 :}
745 TAS.B @Rn {:
746 load_reg( R_ECX, Rn );
747 MEM_READ_BYTE( R_ECX, R_EAX );
748 TEST_r8_r8( R_AL, R_AL );
749 SETE_t();
750 OR_imm8_r8( 0x80, R_AL );
751 MEM_WRITE_BYTE( R_ECX, R_EAX );
752 :}
753 TST Rm, Rn {:
754 load_reg( R_EAX, Rm );
755 load_reg( R_ECX, Rn );
756 TEST_r32_r32( R_EAX, R_ECX );
757 SETE_t();
758 :}
759 TST #imm, R0 {:
760 load_reg( R_EAX, 0 );
761 TEST_imm32_r32( imm, R_EAX );
762 SETE_t();
763 :}
764 TST.B #imm, @(R0, GBR) {:
765 load_reg( R_EAX, 0);
766 load_reg( R_ECX, R_GBR);
767 ADD_r32_r32( R_EAX, R_ECX );
768 MEM_READ_BYTE( R_ECX, R_EAX );
769 TEST_imm8_r8( imm, R_EAX );
770 SETE_t();
771 :}
772 XOR Rm, Rn {:
773 load_reg( R_EAX, Rm );
774 load_reg( R_ECX, Rn );
775 XOR_r32_r32( R_EAX, R_ECX );
776 store_reg( R_ECX, Rn );
777 :}
778 XOR #imm, R0 {:
779 load_reg( R_EAX, 0 );
780 XOR_imm32_r32( imm, R_EAX );
781 store_reg( R_EAX, 0 );
782 :}
783 XOR.B #imm, @(R0, GBR) {:
784 load_reg( R_EAX, 0 );
785 load_spreg( R_ECX, R_GBR );
786 ADD_r32_r32( R_EAX, R_ECX );
787 MEM_READ_BYTE( R_ECX, R_EAX );
788 XOR_imm32_r32( imm, R_EAX );
789 MEM_WRITE_BYTE( R_ECX, R_EAX );
790 :}
791 XTRCT Rm, Rn {:
792 load_reg( R_EAX, Rm );
793 MOV_r32_r32( R_EAX, R_ECX );
794 SHR_imm8_r32( 16, R_EAX );
795 SHL_imm8_r32( 16, R_ECX );
796 OR_r32_r32( R_EAX, R_ECX );
797 store_reg( R_ECX, Rn );
798 :}
800 /* Data move instructions */
801 MOV Rm, Rn {:
802 load_reg( R_EAX, Rm );
803 store_reg( R_EAX, Rn );
804 :}
805 MOV #imm, Rn {:
806 load_imm32( R_EAX, imm );
807 store_reg( R_EAX, Rn );
808 :}
809 MOV.B Rm, @Rn {:
810 load_reg( R_EAX, Rm );
811 load_reg( R_ECX, Rn );
812 MEM_WRITE_BYTE( R_ECX, R_EAX );
813 :}
814 MOV.B Rm, @-Rn {:
815 load_reg( R_EAX, Rm );
816 load_reg( R_ECX, Rn );
817 ADD_imm8s_r32( -1, Rn );
818 store_reg( R_ECX, Rn );
819 MEM_WRITE_BYTE( R_ECX, R_EAX );
820 :}
821 MOV.B Rm, @(R0, Rn) {:
822 load_reg( R_EAX, 0 );
823 load_reg( R_ECX, Rn );
824 ADD_r32_r32( R_EAX, R_ECX );
825 load_reg( R_EAX, Rm );
826 MEM_WRITE_BYTE( R_ECX, R_EAX );
827 :}
828 MOV.B R0, @(disp, GBR) {:
829 load_reg( R_EAX, 0 );
830 load_spreg( R_ECX, R_GBR );
831 ADD_imm32_r32( disp, R_ECX );
832 MEM_WRITE_BYTE( R_ECX, R_EAX );
833 :}
834 MOV.B R0, @(disp, Rn) {:
835 load_reg( R_EAX, 0 );
836 load_reg( R_ECX, Rn );
837 ADD_imm32_r32( disp, R_ECX );
838 MEM_WRITE_BYTE( R_ECX, R_EAX );
839 :}
840 MOV.B @Rm, Rn {:
841 load_reg( R_ECX, Rm );
842 MEM_READ_BYTE( R_ECX, R_EAX );
843 store_reg( R_ECX, Rn );
844 :}
845 MOV.B @Rm+, Rn {:
846 load_reg( R_ECX, Rm );
847 MOV_r32_r32( R_ECX, R_EAX );
848 ADD_imm8s_r32( 1, R_EAX );
849 store_reg( R_EAX, Rm );
850 MEM_READ_BYTE( R_ECX, R_EAX );
851 store_reg( R_EAX, Rn );
852 :}
853 MOV.B @(R0, Rm), Rn {:
854 load_reg( R_EAX, 0 );
855 load_reg( R_ECX, Rm );
856 ADD_r32_r32( R_EAX, R_ECX );
857 MEM_READ_BYTE( R_ECX, R_EAX );
858 store_reg( R_EAX, Rn );
859 :}
860 MOV.B @(disp, GBR), R0 {:
861 load_spreg( R_ECX, R_GBR );
862 ADD_imm32_r32( disp, R_ECX );
863 MEM_READ_BYTE( R_ECX, R_EAX );
864 store_reg( R_EAX, 0 );
865 :}
866 MOV.B @(disp, Rm), R0 {:
867 load_reg( R_ECX, Rm );
868 ADD_imm32_r32( disp, R_ECX );
869 MEM_READ_BYTE( R_ECX, R_EAX );
870 store_reg( R_EAX, 0 );
871 :}
872 MOV.L Rm, @Rn {:
873 load_reg( R_EAX, Rm );
874 load_reg( R_ECX, Rn );
875 check_walign32(R_ECX);
876 MEM_WRITE_LONG( R_ECX, R_EAX );
877 :}
878 MOV.L Rm, @-Rn {:
879 load_reg( R_EAX, Rm );
880 load_reg( R_ECX, Rn );
881 check_walign32( R_ECX );
882 ADD_imm8s_r32( -4, R_ECX );
883 store_reg( R_ECX, Rn );
884 MEM_WRITE_LONG( R_ECX, R_EAX );
885 :}
886 MOV.L Rm, @(R0, Rn) {:
887 load_reg( R_EAX, 0 );
888 load_reg( R_ECX, Rn );
889 ADD_r32_r32( R_EAX, R_ECX );
890 check_walign32( R_ECX );
891 load_reg( R_EAX, Rm );
892 MEM_WRITE_LONG( R_ECX, R_EAX );
893 :}
894 MOV.L R0, @(disp, GBR) {:
895 load_spreg( R_ECX, R_GBR );
896 load_reg( R_EAX, 0 );
897 ADD_imm32_r32( disp, R_ECX );
898 check_walign32( R_ECX );
899 MEM_WRITE_LONG( R_ECX, R_EAX );
900 :}
901 MOV.L Rm, @(disp, Rn) {:
902 load_reg( R_ECX, Rn );
903 load_reg( R_EAX, Rm );
904 ADD_imm32_r32( disp, R_ECX );
905 check_walign32( R_ECX );
906 MEM_WRITE_LONG( R_ECX, R_EAX );
907 :}
908 MOV.L @Rm, Rn {:
909 load_reg( R_ECX, Rm );
910 check_ralign32( R_ECX );
911 MEM_READ_LONG( R_ECX, R_EAX );
912 store_reg( R_EAX, Rn );
913 :}
914 MOV.L @Rm+, Rn {:
915 load_reg( R_EAX, Rm );
916 check_ralign32( R_ECX );
917 MOV_r32_r32( R_EAX, R_ECX );
918 ADD_imm8s_r32( 4, R_EAX );
919 store_reg( R_EAX, Rm );
920 MEM_READ_LONG( R_ECX, R_EAX );
921 store_reg( R_EAX, Rn );
922 :}
923 MOV.L @(R0, Rm), Rn {:
924 load_reg( R_EAX, 0 );
925 load_reg( R_ECX, Rm );
926 ADD_r32_r32( R_EAX, R_ECX );
927 check_ralign32( R_ECX );
928 MEM_READ_LONG( R_ECX, R_EAX );
929 store_reg( R_EAX, Rn );
930 :}
931 MOV.L @(disp, GBR), R0 {:
932 load_spreg( R_ECX, R_GBR );
933 ADD_imm32_r32( disp, R_ECX );
934 check_ralign32( R_ECX );
935 MEM_READ_LONG( R_ECX, R_EAX );
936 store_reg( R_EAX, 0 );
937 :}
938 MOV.L @(disp, PC), Rn {:
939 if( sh4_x86.in_delay_slot ) {
940 SLOTILLEGAL();
941 } else {
942 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
943 MEM_READ_LONG( R_ECX, R_EAX );
944 store_reg( R_EAX, 0 );
945 }
946 :}
947 MOV.L @(disp, Rm), Rn {:
948 load_reg( R_ECX, Rm );
949 ADD_imm8s_r32( disp, R_ECX );
950 check_ralign32( R_ECX );
951 MEM_READ_LONG( R_ECX, R_EAX );
952 store_reg( R_EAX, Rn );
953 :}
954 MOV.W Rm, @Rn {:
955 load_reg( R_ECX, Rn );
956 check_walign16( R_ECX );
957 MEM_READ_WORD( R_ECX, R_EAX );
958 store_reg( R_EAX, Rn );
959 :}
960 MOV.W Rm, @-Rn {:
961 load_reg( R_ECX, Rn );
962 check_walign16( R_ECX );
963 load_reg( R_EAX, Rm );
964 ADD_imm8s_r32( -2, R_ECX );
965 MEM_WRITE_WORD( R_ECX, R_EAX );
966 :}
967 MOV.W Rm, @(R0, Rn) {:
968 load_reg( R_EAX, 0 );
969 load_reg( R_ECX, Rn );
970 ADD_r32_r32( R_EAX, R_ECX );
971 check_walign16( R_ECX );
972 load_reg( R_EAX, Rm );
973 MEM_WRITE_WORD( R_ECX, R_EAX );
974 :}
975 MOV.W R0, @(disp, GBR) {:
976 load_spreg( R_ECX, R_GBR );
977 load_reg( R_EAX, 0 );
978 ADD_imm32_r32( disp, R_ECX );
979 check_walign16( R_ECX );
980 MEM_WRITE_WORD( R_ECX, R_EAX );
981 :}
982 MOV.W R0, @(disp, Rn) {:
983 load_reg( R_ECX, Rn );
984 load_reg( R_EAX, 0 );
985 ADD_imm32_r32( disp, R_ECX );
986 check_walign16( R_ECX );
987 MEM_WRITE_WORD( R_ECX, R_EAX );
988 :}
989 MOV.W @Rm, Rn {:
990 load_reg( R_ECX, Rm );
991 check_ralign16( R_ECX );
992 MEM_READ_WORD( R_ECX, R_EAX );
993 store_reg( R_EAX, Rn );
994 :}
995 MOV.W @Rm+, Rn {:
996 load_reg( R_EAX, Rm );
997 check_ralign16( R_EAX );
998 MOV_r32_r32( R_EAX, R_ECX );
999 ADD_imm8s_r32( 2, R_EAX );
1000 store_reg( R_EAX, Rm );
1001 MEM_READ_WORD( R_ECX, R_EAX );
1002 store_reg( R_EAX, Rn );
1003 :}
1004 MOV.W @(R0, Rm), Rn {:
1005 load_reg( R_EAX, 0 );
1006 load_reg( R_ECX, Rm );
1007 ADD_r32_r32( R_EAX, R_ECX );
1008 check_ralign16( R_ECX );
1009 MEM_READ_WORD( R_ECX, R_EAX );
1010 store_reg( R_EAX, Rn );
1011 :}
1012 MOV.W @(disp, GBR), R0 {:
1013 load_spreg( R_ECX, R_GBR );
1014 ADD_imm32_r32( disp, R_ECX );
1015 check_ralign16( R_ECX );
1016 MEM_READ_WORD( R_ECX, R_EAX );
1017 store_reg( R_EAX, 0 );
1018 :}
1019 MOV.W @(disp, PC), Rn {:
1020 if( sh4_x86.in_delay_slot ) {
1021 SLOTILLEGAL();
1022 } else {
1023 load_imm32( R_ECX, pc + disp + 4 );
1024 MEM_READ_WORD( R_ECX, R_EAX );
1025 store_reg( R_EAX, Rn );
1026 }
1027 :}
1028 MOV.W @(disp, Rm), R0 {:
1029 load_reg( R_ECX, Rm );
1030 ADD_imm32_r32( disp, R_ECX );
1031 check_ralign16( R_ECX );
1032 MEM_READ_WORD( R_ECX, R_EAX );
1033 store_reg( R_EAX, 0 );
1034 :}
1035 MOVA @(disp, PC), R0 {:
1036 if( sh4_x86.in_delay_slot ) {
1037 SLOTILLEGAL();
1038 } else {
1039 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1040 store_reg( R_ECX, 0 );
1041 }
1042 :}
1043 MOVCA.L R0, @Rn {:
1044 load_reg( R_EAX, 0 );
1045 load_reg( R_ECX, Rn );
1046 check_walign32( R_ECX );
1047 MEM_WRITE_LONG( R_ECX, R_EAX );
1048 :}
1050 /* Control transfer instructions */
1051 BF disp {:
1052 if( sh4_x86.in_delay_slot ) {
1053 SLOTILLEGAL();
1054 } else {
1055 load_imm32( R_EDI, pc + 2 );
1056 CMP_imm8s_sh4r( 0, R_T );
1057 JNE_rel8( 5 );
1058 load_imm32( R_EDI, disp + pc + 4 );
1059 INC_r32(R_ESI);
1060 return 1;
1061 }
1062 :}
1063 BF/S disp {:
1064 if( sh4_x86.in_delay_slot ) {
1065 SLOTILLEGAL();
1066 } else {
1067 load_imm32( R_EDI, pc + 2 );
1068 CMP_imm8s_sh4r( 0, R_T );
1069 JNE_rel8( 5 );
1070 load_imm32( R_EDI, disp + pc + 4 );
1071 sh4_x86.in_delay_slot = TRUE;
1072 INC_r32(R_ESI);
1073 return 0;
1074 }
1075 :}
1076 BRA disp {:
1077 if( sh4_x86.in_delay_slot ) {
1078 SLOTILLEGAL();
1079 } else {
1080 load_imm32( R_EDI, disp + pc + 4 );
1081 sh4_x86.in_delay_slot = TRUE;
1082 INC_r32(R_ESI);
1083 return 0;
1084 }
1085 :}
1086 BRAF Rn {:
1087 if( sh4_x86.in_delay_slot ) {
1088 SLOTILLEGAL();
1089 } else {
1090 load_reg( R_EDI, Rn );
1091 sh4_x86.in_delay_slot = TRUE;
1092 INC_r32(R_ESI);
1093 return 0;
1094 }
1095 :}
1096 BSR disp {:
1097 if( sh4_x86.in_delay_slot ) {
1098 SLOTILLEGAL();
1099 } else {
1100 load_imm32( R_EAX, pc + 4 );
1101 store_spreg( R_EAX, R_PR );
1102 load_imm32( R_EDI, disp + pc + 4 );
1103 sh4_x86.in_delay_slot = TRUE;
1104 INC_r32(R_ESI);
1105 return 0;
1106 }
1107 :}
1108 BSRF Rn {:
1109 if( sh4_x86.in_delay_slot ) {
1110 SLOTILLEGAL();
1111 } else {
1112 load_imm32( R_EAX, pc + 4 );
1113 store_spreg( R_EAX, R_PR );
1114 load_reg( R_EDI, Rn );
1115 ADD_r32_r32( R_EAX, R_EDI );
1116 sh4_x86.in_delay_slot = TRUE;
1117 INC_r32(R_ESI);
1118 return 0;
1119 }
1120 :}
1121 BT disp {:
1122 if( sh4_x86.in_delay_slot ) {
1123 SLOTILLEGAL();
1124 } else {
1125 load_imm32( R_EDI, pc + 2 );
1126 CMP_imm8s_sh4r( 0, R_T );
1127 JE_rel8( 5 );
1128 load_imm32( R_EDI, disp + pc + 4 );
1129 INC_r32(R_ESI);
1130 return 1;
1131 }
1132 :}
1133 BT/S disp {:
1134 if( sh4_x86.in_delay_slot ) {
1135 SLOTILLEGAL();
1136 } else {
1137 load_imm32( R_EDI, pc + 2 );
1138 CMP_imm8s_sh4r( 0, R_T );
1139 JE_rel8( 5 );
1140 load_imm32( R_EDI, disp + pc + 4 );
1141 sh4_x86.in_delay_slot = TRUE;
1142 INC_r32(R_ESI);
1143 return 0;
1144 }
1145 :}
1146 JMP @Rn {:
1147 if( sh4_x86.in_delay_slot ) {
1148 SLOTILLEGAL();
1149 } else {
1150 load_reg( R_EDI, Rn );
1151 sh4_x86.in_delay_slot = TRUE;
1152 INC_r32(R_ESI);
1153 return 0;
1154 }
1155 :}
1156 JSR @Rn {:
1157 if( sh4_x86.in_delay_slot ) {
1158 SLOTILLEGAL();
1159 } else {
1160 load_imm32( R_EAX, pc + 4 );
1161 store_spreg( R_EAX, R_PR );
1162 load_reg( R_EDI, Rn );
1163 sh4_x86.in_delay_slot = TRUE;
1164 INC_r32(R_ESI);
1165 return 0;
1166 }
1167 :}
1168 RTE {:
1169 check_priv();
1170 if( sh4_x86.in_delay_slot ) {
1171 SLOTILLEGAL();
1172 } else {
1173 load_spreg( R_EDI, R_PR );
1174 load_spreg( R_EAX, R_SSR );
1175 call_func1( sh4_write_sr, R_EAX );
1176 sh4_x86.in_delay_slot = TRUE;
1177 INC_r32(R_ESI);
1178 return 0;
1179 }
1180 :}
1181 RTS {:
1182 if( sh4_x86.in_delay_slot ) {
1183 SLOTILLEGAL();
1184 } else {
1185 load_spreg( R_EDI, R_PR );
1186 sh4_x86.in_delay_slot = TRUE;
1187 INC_r32(R_ESI);
1188 return 0;
1189 }
1190 :}
1191 TRAPA #imm {:
1192 if( sh4_x86.in_delay_slot ) {
1193 SLOTILLEGAL();
1194 } else {
1195 // TODO: Write TRA
1196 RAISE_EXCEPTION(EXC_TRAP);
1197 }
1198 :}
1199 UNDEF {:
1200 if( sh4_x86.in_delay_slot ) {
1201 RAISE_EXCEPTION(EXC_SLOT_ILLEGAL);
1202 } else {
1203 RAISE_EXCEPTION(EXC_ILLEGAL);
1204 }
1205 return 1;
1206 :}
1208 CLRMAC {:
1209 XOR_r32_r32(R_EAX, R_EAX);
1210 store_spreg( R_EAX, R_MACL );
1211 store_spreg( R_EAX, R_MACH );
1212 :}
1213 CLRS {:
1214 CLC();
1215 SETC_sh4r(R_S);
1216 :}
1217 CLRT {:
1218 CLC();
1219 SETC_t();
1220 :}
1221 SETS {:
1222 STC();
1223 SETC_sh4r(R_S);
1224 :}
1225 SETT {:
1226 STC();
1227 SETC_t();
1228 :}
1230 /* Floating point instructions */
1231 FABS FRn {:
1232 load_spreg( R_ECX, R_FPSCR );
1233 load_spreg( R_EDX, REG_OFFSET(fr_bank) );
1234 TEST_imm32_r32( FPSCR_PR, R_ECX );
1235 JNE_rel8(10);
1236 push_fr(R_EDX, FRn); // 3
1237 FABS_st0(); // 2
1238 pop_fr( R_EDX, FRn); //3
1239 JMP_rel8(8); // 2
1240 push_dr(R_EDX, FRn);
1241 FABS_st0();
1242 pop_dr(R_EDX, FRn);
1243 :}
1244 FADD FRm, FRn {: :}
1245 FCMP/EQ FRm, FRn {: :}
1246 FCMP/GT FRm, FRn {: :}
1247 FCNVDS FRm, FPUL {: :}
1248 FCNVSD FPUL, FRn {: :}
1249 FDIV FRm, FRn {: :}
1250 FIPR FVm, FVn {: :}
1251 FLDS FRm, FPUL {: :}
1252 FLDI0 FRn {: :}
1253 FLDI1 FRn {: :}
1254 FLOAT FPUL, FRn {: :}
1255 FMAC FR0, FRm, FRn {: :}
1256 FMOV FRm, FRn {: :}
1257 FMOV FRm, @Rn {: :}
1258 FMOV FRm, @-Rn {: :}
1259 FMOV FRm, @(R0, Rn) {: :}
1260 FMOV @Rm, FRn {: :}
1261 FMOV @Rm+, FRn {: :}
1262 FMOV @(R0, Rm), FRn {: :}
1263 FMUL FRm, FRn {: :}
1264 FNEG FRn {: :}
1265 FRCHG {: :}
1266 FSCA FPUL, FRn {: :}
1267 FSCHG {: :}
1268 FSQRT FRn {: :}
1269 FSRRA FRn {: :}
1270 FSTS FPUL, FRn {: :}
1271 FSUB FRm, FRn {: :}
1272 FTRC FRm, FPUL {: :}
1273 FTRV XMTRX, FVn {: :}
1275 /* Processor control instructions */
1276 LDC Rm, SR {:
1277 load_reg( R_EAX, Rm );
1278 call_func1( sh4_write_sr, R_EAX );
1279 :}
1280 LDC Rm, GBR {:
1281 load_reg( R_EAX, Rm );
1282 store_spreg( R_EAX, R_GBR );
1283 :}
1284 LDC Rm, VBR {:
1285 load_reg( R_EAX, Rm );
1286 store_spreg( R_EAX, R_VBR );
1287 :}
1288 LDC Rm, SSR {:
1289 load_reg( R_EAX, Rm );
1290 store_spreg( R_EAX, R_SSR );
1291 :}
1292 LDC Rm, SGR {:
1293 load_reg( R_EAX, Rm );
1294 store_spreg( R_EAX, R_SGR );
1295 :}
1296 LDC Rm, SPC {:
1297 load_reg( R_EAX, Rm );
1298 store_spreg( R_EAX, R_SPC );
1299 :}
1300 LDC Rm, DBR {:
1301 load_reg( R_EAX, Rm );
1302 store_spreg( R_EAX, R_DBR );
1303 :}
1304 LDC Rm, Rn_BANK {:
1305 load_reg( R_EAX, Rm );
1306 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1307 :}
1308 LDC.L @Rm+, GBR {:
1309 load_reg( R_EAX, Rm );
1310 MOV_r32_r32( R_EAX, R_ECX );
1311 ADD_imm8s_r32( 4, R_EAX );
1312 store_reg( R_EAX, Rm );
1313 MEM_READ_LONG( R_ECX, R_EAX );
1314 store_spreg( R_EAX, R_GBR );
1315 :}
1316 LDC.L @Rm+, SR {:
1317 load_reg( R_EAX, Rm );
1318 MOV_r32_r32( R_EAX, R_ECX );
1319 ADD_imm8s_r32( 4, R_EAX );
1320 store_reg( R_EAX, Rm );
1321 MEM_READ_LONG( R_ECX, R_EAX );
1322 call_func1( sh4_write_sr, R_EAX );
1323 :}
1324 LDC.L @Rm+, VBR {:
1325 load_reg( R_EAX, Rm );
1326 MOV_r32_r32( R_EAX, R_ECX );
1327 ADD_imm8s_r32( 4, R_EAX );
1328 store_reg( R_EAX, Rm );
1329 MEM_READ_LONG( R_ECX, R_EAX );
1330 store_spreg( R_EAX, R_VBR );
1331 :}
1332 LDC.L @Rm+, SSR {:
1333 load_reg( R_EAX, Rm );
1334 MOV_r32_r32( R_EAX, R_ECX );
1335 ADD_imm8s_r32( 4, R_EAX );
1336 store_reg( R_EAX, Rm );
1337 MEM_READ_LONG( R_ECX, R_EAX );
1338 store_spreg( R_EAX, R_SSR );
1339 :}
1340 LDC.L @Rm+, SGR {:
1341 load_reg( R_EAX, Rm );
1342 MOV_r32_r32( R_EAX, R_ECX );
1343 ADD_imm8s_r32( 4, R_EAX );
1344 store_reg( R_EAX, Rm );
1345 MEM_READ_LONG( R_ECX, R_EAX );
1346 store_spreg( R_EAX, R_SGR );
1347 :}
1348 LDC.L @Rm+, SPC {:
1349 load_reg( R_EAX, Rm );
1350 MOV_r32_r32( R_EAX, R_ECX );
1351 ADD_imm8s_r32( 4, R_EAX );
1352 store_reg( R_EAX, Rm );
1353 MEM_READ_LONG( R_ECX, R_EAX );
1354 store_spreg( R_EAX, R_SPC );
1355 :}
1356 LDC.L @Rm+, DBR {:
1357 load_reg( R_EAX, Rm );
1358 MOV_r32_r32( R_EAX, R_ECX );
1359 ADD_imm8s_r32( 4, R_EAX );
1360 store_reg( R_EAX, Rm );
1361 MEM_READ_LONG( R_ECX, R_EAX );
1362 store_spreg( R_EAX, R_DBR );
1363 :}
1364 LDC.L @Rm+, Rn_BANK {:
1365 load_reg( R_EAX, Rm );
1366 MOV_r32_r32( R_EAX, R_ECX );
1367 ADD_imm8s_r32( 4, R_EAX );
1368 store_reg( R_EAX, Rm );
1369 MEM_READ_LONG( R_ECX, R_EAX );
1370 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1371 :}
1372 LDS Rm, FPSCR {:
1373 load_reg( R_EAX, Rm );
1374 store_spreg( R_EAX, R_FPSCR );
1375 :}
1376 LDS.L @Rm+, FPSCR {:
1377 load_reg( R_EAX, Rm );
1378 MOV_r32_r32( R_EAX, R_ECX );
1379 ADD_imm8s_r32( 4, R_EAX );
1380 store_reg( R_EAX, Rm );
1381 MEM_READ_LONG( R_ECX, R_EAX );
1382 store_spreg( R_EAX, R_FPSCR );
1383 :}
1384 LDS Rm, FPUL {:
1385 load_reg( R_EAX, Rm );
1386 store_spreg( R_EAX, R_FPUL );
1387 :}
1388 LDS.L @Rm+, FPUL {:
1389 load_reg( R_EAX, Rm );
1390 MOV_r32_r32( R_EAX, R_ECX );
1391 ADD_imm8s_r32( 4, R_EAX );
1392 store_reg( R_EAX, Rm );
1393 MEM_READ_LONG( R_ECX, R_EAX );
1394 store_spreg( R_EAX, R_FPUL );
1395 :}
1396 LDS Rm, MACH {:
1397 load_reg( R_EAX, Rm );
1398 store_spreg( R_EAX, R_MACH );
1399 :}
1400 LDS.L @Rm+, MACH {:
1401 load_reg( R_EAX, Rm );
1402 MOV_r32_r32( R_EAX, R_ECX );
1403 ADD_imm8s_r32( 4, R_EAX );
1404 store_reg( R_EAX, Rm );
1405 MEM_READ_LONG( R_ECX, R_EAX );
1406 store_spreg( R_EAX, R_MACH );
1407 :}
1408 LDS Rm, MACL {:
1409 load_reg( R_EAX, Rm );
1410 store_spreg( R_EAX, R_MACL );
1411 :}
1412 LDS.L @Rm+, MACL {:
1413 load_reg( R_EAX, Rm );
1414 MOV_r32_r32( R_EAX, R_ECX );
1415 ADD_imm8s_r32( 4, R_EAX );
1416 store_reg( R_EAX, Rm );
1417 MEM_READ_LONG( R_ECX, R_EAX );
1418 store_spreg( R_EAX, R_MACL );
1419 :}
1420 LDS Rm, PR {:
1421 load_reg( R_EAX, Rm );
1422 store_spreg( R_EAX, R_PR );
1423 :}
1424 LDS.L @Rm+, PR {:
1425 load_reg( R_EAX, Rm );
1426 MOV_r32_r32( R_EAX, R_ECX );
1427 ADD_imm8s_r32( 4, R_EAX );
1428 store_reg( R_EAX, Rm );
1429 MEM_READ_LONG( R_ECX, R_EAX );
1430 store_spreg( R_EAX, R_PR );
1431 :}
1432 LDTLB {: :}
1433 OCBI @Rn {: :}
1434 OCBP @Rn {: :}
1435 OCBWB @Rn {: :}
1436 PREF @Rn {:
1437 load_reg( R_EAX, Rn );
1438 PUSH_r32( R_EAX );
1439 AND_imm32_r32( 0xFC000000, R_EAX );
1440 CMP_imm32_r32( 0xE0000000, R_EAX );
1441 JNE_rel8(8);
1442 call_func0( sh4_flush_store_queue );
1443 ADD_imm8s_r32( -4, R_ESP );
1444 :}
1445 SLEEP {: /* TODO */ :}
1446 STC SR, Rn {:
1447 call_func0(sh4_read_sr);
1448 store_reg( R_EAX, Rn );
1449 :}
1450 STC GBR, Rn {:
1451 load_spreg( R_EAX, R_GBR );
1452 store_reg( R_EAX, Rn );
1453 :}
1454 STC VBR, Rn {:
1455 load_spreg( R_EAX, R_VBR );
1456 store_reg( R_EAX, Rn );
1457 :}
1458 STC SSR, Rn {:
1459 load_spreg( R_EAX, R_SSR );
1460 store_reg( R_EAX, Rn );
1461 :}
1462 STC SPC, Rn {:
1463 load_spreg( R_EAX, R_SPC );
1464 store_reg( R_EAX, Rn );
1465 :}
1466 STC SGR, Rn {:
1467 load_spreg( R_EAX, R_SGR );
1468 store_reg( R_EAX, Rn );
1469 :}
1470 STC DBR, Rn {:
1471 load_spreg( R_EAX, R_DBR );
1472 store_reg( R_EAX, Rn );
1473 :}
1474 STC Rm_BANK, Rn {:
1475 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
1476 store_reg( R_EAX, Rn );
1477 :}
1478 STC.L SR, @-Rn {:
1479 load_reg( R_ECX, Rn );
1480 ADD_imm8s_r32( -4, Rn );
1481 store_reg( R_ECX, Rn );
1482 call_func0( sh4_read_sr );
1483 MEM_WRITE_LONG( R_ECX, R_EAX );
1484 :}
1485 STC.L VBR, @-Rn {:
1486 load_reg( R_ECX, Rn );
1487 ADD_imm8s_r32( -4, Rn );
1488 store_reg( R_ECX, Rn );
1489 load_spreg( R_EAX, R_VBR );
1490 MEM_WRITE_LONG( R_ECX, R_EAX );
1491 :}
1492 STC.L SSR, @-Rn {:
1493 load_reg( R_ECX, Rn );
1494 ADD_imm8s_r32( -4, Rn );
1495 store_reg( R_ECX, Rn );
1496 load_spreg( R_EAX, R_SSR );
1497 MEM_WRITE_LONG( R_ECX, R_EAX );
1498 :}
1499 STC.L SPC, @-Rn {:
1500 load_reg( R_ECX, Rn );
1501 ADD_imm8s_r32( -4, Rn );
1502 store_reg( R_ECX, Rn );
1503 load_spreg( R_EAX, R_SPC );
1504 MEM_WRITE_LONG( R_ECX, R_EAX );
1505 :}
1506 STC.L SGR, @-Rn {:
1507 load_reg( R_ECX, Rn );
1508 ADD_imm8s_r32( -4, Rn );
1509 store_reg( R_ECX, Rn );
1510 load_spreg( R_EAX, R_SGR );
1511 MEM_WRITE_LONG( R_ECX, R_EAX );
1512 :}
1513 STC.L DBR, @-Rn {:
1514 load_reg( R_ECX, Rn );
1515 ADD_imm8s_r32( -4, Rn );
1516 store_reg( R_ECX, Rn );
1517 load_spreg( R_EAX, R_DBR );
1518 MEM_WRITE_LONG( R_ECX, R_EAX );
1519 :}
1520 STC.L Rm_BANK, @-Rn {:
1521 load_reg( R_ECX, Rn );
1522 ADD_imm8s_r32( -4, Rn );
1523 store_reg( R_ECX, Rn );
1524 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
1525 MEM_WRITE_LONG( R_ECX, R_EAX );
1526 :}
1527 STC.L GBR, @-Rn {:
1528 load_reg( R_ECX, Rn );
1529 ADD_imm8s_r32( -4, Rn );
1530 store_reg( R_ECX, Rn );
1531 load_spreg( R_EAX, R_GBR );
1532 MEM_WRITE_LONG( R_ECX, R_EAX );
1533 :}
1534 STS FPSCR, Rn {:
1535 load_spreg( R_EAX, R_FPSCR );
1536 store_reg( R_EAX, Rn );
1537 :}
1538 STS.L FPSCR, @-Rn {:
1539 load_reg( R_ECX, Rn );
1540 ADD_imm8s_r32( -4, Rn );
1541 store_reg( R_ECX, Rn );
1542 load_spreg( R_EAX, R_FPSCR );
1543 MEM_WRITE_LONG( R_ECX, R_EAX );
1544 :}
1545 STS FPUL, Rn {:
1546 load_spreg( R_EAX, R_FPUL );
1547 store_reg( R_EAX, Rn );
1548 :}
1549 STS.L FPUL, @-Rn {:
1550 load_reg( R_ECX, Rn );
1551 ADD_imm8s_r32( -4, Rn );
1552 store_reg( R_ECX, Rn );
1553 load_spreg( R_EAX, R_FPUL );
1554 MEM_WRITE_LONG( R_ECX, R_EAX );
1555 :}
1556 STS MACH, Rn {:
1557 load_spreg( R_EAX, R_MACH );
1558 store_reg( R_EAX, Rn );
1559 :}
1560 STS.L MACH, @-Rn {:
1561 load_reg( R_ECX, Rn );
1562 ADD_imm8s_r32( -4, Rn );
1563 store_reg( R_ECX, Rn );
1564 load_spreg( R_EAX, R_MACH );
1565 MEM_WRITE_LONG( R_ECX, R_EAX );
1566 :}
1567 STS MACL, Rn {:
1568 load_spreg( R_EAX, R_MACL );
1569 store_reg( R_EAX, Rn );
1570 :}
1571 STS.L MACL, @-Rn {:
1572 load_reg( R_ECX, Rn );
1573 ADD_imm8s_r32( -4, Rn );
1574 store_reg( R_ECX, Rn );
1575 load_spreg( R_EAX, R_MACL );
1576 MEM_WRITE_LONG( R_ECX, R_EAX );
1577 :}
1578 STS PR, Rn {:
1579 load_spreg( R_EAX, R_PR );
1580 store_reg( R_EAX, Rn );
1581 :}
1582 STS.L PR, @-Rn {:
1583 load_reg( R_ECX, Rn );
1584 ADD_imm8s_r32( -4, Rn );
1585 store_reg( R_ECX, Rn );
1586 load_spreg( R_EAX, R_PR );
1587 MEM_WRITE_LONG( R_ECX, R_EAX );
1588 :}
1590 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}
1591 %%
1592 INC_r32(R_ESI);
1593 if( sh4_x86.in_delay_slot ) {
1594 sh4_x86.in_delay_slot = FALSE;
1595 return 1;
1596 }
1597 return 0;
1598 }
.