filename | src/sh4/sh4x86.in |
changeset | 382:fce3f4da92ab |
prev | 381:aade6c9aca4d |
next | 386:6fb10951326a |
author | nkeynes |
date | Thu Sep 13 08:28:01 2007 +0000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Fix exception handling Fix various instruction bugs |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4x86.in,v 1.9 2007-09-13 08:28:01 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 #ifndef NDEBUG
24 #define DEBUG_JUMPS 1
25 #endif
27 #include "sh4/sh4core.h"
28 #include "sh4/sh4trans.h"
29 #include "sh4/x86op.h"
30 #include "clock.h"
32 #define DEFAULT_BACKPATCH_SIZE 4096
34 /**
35 * Struct to manage internal translation state. This state is not saved -
36 * it is only valid between calls to sh4_translate_begin_block() and
37 * sh4_translate_end_block()
38 */
39 struct sh4_x86_state {
40 gboolean in_delay_slot;
41 gboolean priv_checked; /* true if we've already checked the cpu mode. */
42 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
44 /* Allocated memory for the (block-wide) back-patch list */
45 uint32_t **backpatch_list;
46 uint32_t backpatch_posn;
47 uint32_t backpatch_size;
48 };
50 #define EXIT_DATA_ADDR_READ 0
51 #define EXIT_DATA_ADDR_WRITE 7
52 #define EXIT_ILLEGAL 14
53 #define EXIT_SLOT_ILLEGAL 21
54 #define EXIT_FPU_DISABLED 28
55 #define EXIT_SLOT_FPU_DISABLED 35
57 static struct sh4_x86_state sh4_x86;
59 void sh4_x86_init()
60 {
61 sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
62 sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(uint32_t *);
63 }
66 static void sh4_x86_add_backpatch( uint8_t *ptr )
67 {
68 if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
69 sh4_x86.backpatch_size <<= 1;
70 sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list, sh4_x86.backpatch_size * sizeof(uint32_t *) );
71 assert( sh4_x86.backpatch_list != NULL );
72 }
73 sh4_x86.backpatch_list[sh4_x86.backpatch_posn++] = (uint32_t *)ptr;
74 }
76 static void sh4_x86_do_backpatch( uint8_t *reloc_base )
77 {
78 unsigned int i;
79 for( i=0; i<sh4_x86.backpatch_posn; i++ ) {
80 *sh4_x86.backpatch_list[i] += (reloc_base - ((uint8_t *)sh4_x86.backpatch_list[i]) - 4);
81 }
82 }
84 /**
85 * Emit an instruction to load an SH4 reg into a real register
86 */
87 static inline void load_reg( int x86reg, int sh4reg )
88 {
89 /* mov [bp+n], reg */
90 OP(0x8B);
91 OP(0x45 + (x86reg<<3));
92 OP(REG_OFFSET(r[sh4reg]));
93 }
95 static inline void load_reg16s( int x86reg, int sh4reg )
96 {
97 OP(0x0F);
98 OP(0xBF);
99 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
100 }
102 static inline void load_reg16u( int x86reg, int sh4reg )
103 {
104 OP(0x0F);
105 OP(0xB7);
106 MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
108 }
110 #define load_spreg( x86reg, regoff ) MOV_sh4r_r32( regoff, x86reg )
111 #define store_spreg( x86reg, regoff ) MOV_r32_sh4r( x86reg, regoff )
112 /**
113 * Emit an instruction to load an immediate value into a register
114 */
115 static inline void load_imm32( int x86reg, uint32_t value ) {
116 /* mov #value, reg */
117 OP(0xB8 + x86reg);
118 OP32(value);
119 }
121 /**
122 * Emit an instruction to store an SH4 reg (RN)
123 */
124 void static inline store_reg( int x86reg, int sh4reg ) {
125 /* mov reg, [bp+n] */
126 OP(0x89);
127 OP(0x45 + (x86reg<<3));
128 OP(REG_OFFSET(r[sh4reg]));
129 }
131 #define load_fr_bank(bankreg) load_spreg( bankreg, REG_OFFSET(fr_bank))
133 /**
134 * Load an FR register (single-precision floating point) into an integer x86
135 * register (eg for register-to-register moves)
136 */
137 void static inline load_fr( int bankreg, int x86reg, int frm )
138 {
139 OP(0x8B); OP(0x40+bankreg+(x86reg<<3)); OP((frm^1)<<2);
140 }
142 /**
143 * Store an FR register (single-precision floating point) into an integer x86
144 * register (eg for register-to-register moves)
145 */
146 void static inline store_fr( int bankreg, int x86reg, int frn )
147 {
148 OP(0x89); OP(0x40+bankreg+(x86reg<<3)); OP((frn^1)<<2);
149 }
152 /**
153 * Load a pointer to the back fp back into the specified x86 register. The
154 * bankreg must have been previously loaded with FPSCR.
155 * NB: 10 bytes
156 */
157 static inline void load_xf_bank( int bankreg )
158 {
159 SHR_imm8_r32( (21 - 6), bankreg ); // Extract bit 21 then *64 for bank size
160 AND_imm8s_r32( 0x40, bankreg ); // Complete extraction
161 OP(0x8D); OP(0x44+(bankreg<<3)); OP(0x28+bankreg); OP(REG_OFFSET(fr)); // LEA [ebp+bankreg+disp], bankreg
162 }
164 /**
165 * Push FPUL (as a 32-bit float) onto the FPU stack
166 */
167 static inline void push_fpul( )
168 {
169 OP(0xD9); OP(0x45); OP(R_FPUL);
170 }
172 /**
173 * Pop FPUL (as a 32-bit float) from the FPU stack
174 */
175 static inline void pop_fpul( )
176 {
177 OP(0xD9); OP(0x5D); OP(R_FPUL);
178 }
180 /**
181 * Push a 32-bit float onto the FPU stack, with bankreg previously loaded
182 * with the location of the current fp bank.
183 */
184 static inline void push_fr( int bankreg, int frm )
185 {
186 OP(0xD9); OP(0x40 + bankreg); OP((frm^1)<<2); // FLD.S [bankreg + frm^1*4]
187 }
189 /**
190 * Pop a 32-bit float from the FPU stack and store it back into the fp bank,
191 * with bankreg previously loaded with the location of the current fp bank.
192 */
193 static inline void pop_fr( int bankreg, int frm )
194 {
195 OP(0xD9); OP(0x58 + bankreg); OP((frm^1)<<2); // FST.S [bankreg + frm^1*4]
196 }
198 /**
199 * Push a 64-bit double onto the FPU stack, with bankreg previously loaded
200 * with the location of the current fp bank.
201 */
202 static inline void push_dr( int bankreg, int frm )
203 {
204 OP(0xDD); OP(0x40 + bankreg); OP(frm<<2); // FLD.D [bankreg + frm*4]
205 }
207 static inline void pop_dr( int bankreg, int frm )
208 {
209 OP(0xDD); OP(0x58 + bankreg); OP(frm<<2); // FST.D [bankreg + frm*4]
210 }
212 /**
213 * Note: clobbers EAX to make the indirect call - this isn't usually
214 * a problem since the callee will usually clobber it anyway.
215 */
216 static inline void call_func0( void *ptr )
217 {
218 load_imm32(R_EAX, (uint32_t)ptr);
219 CALL_r32(R_EAX);
220 }
222 static inline void call_func1( void *ptr, int arg1 )
223 {
224 PUSH_r32(arg1);
225 call_func0(ptr);
226 ADD_imm8s_r32( 4, R_ESP );
227 }
229 static inline void call_func2( void *ptr, int arg1, int arg2 )
230 {
231 PUSH_r32(arg2);
232 PUSH_r32(arg1);
233 call_func0(ptr);
234 ADD_imm8s_r32( 8, R_ESP );
235 }
237 /**
238 * Write a double (64-bit) value into memory, with the first word in arg2a, and
239 * the second in arg2b
240 * NB: 30 bytes
241 */
242 static inline void MEM_WRITE_DOUBLE( int addr, int arg2a, int arg2b )
243 {
244 ADD_imm8s_r32( 4, addr );
245 PUSH_r32(addr);
246 PUSH_r32(arg2b);
247 ADD_imm8s_r32( -4, addr );
248 PUSH_r32(addr);
249 PUSH_r32(arg2a);
250 call_func0(sh4_write_long);
251 ADD_imm8s_r32( 8, R_ESP );
252 call_func0(sh4_write_long);
253 ADD_imm8s_r32( 8, R_ESP );
254 }
256 /**
257 * Read a double (64-bit) value from memory, writing the first word into arg2a
258 * and the second into arg2b. The addr must not be in EAX
259 * NB: 27 bytes
260 */
261 static inline void MEM_READ_DOUBLE( int addr, int arg2a, int arg2b )
262 {
263 PUSH_r32(addr);
264 call_func0(sh4_read_long);
265 POP_r32(addr);
266 PUSH_r32(R_EAX);
267 ADD_imm8s_r32( 4, addr );
268 PUSH_r32(addr);
269 call_func0(sh4_read_long);
270 ADD_imm8s_r32( 4, R_ESP );
271 MOV_r32_r32( R_EAX, arg2b );
272 POP_r32(arg2a);
273 }
275 /* Exception checks - Note that all exception checks will clobber EAX */
276 static void check_priv( )
277 {
278 if( !sh4_x86.priv_checked ) {
279 sh4_x86.priv_checked = TRUE;
280 load_spreg( R_EAX, R_SR );
281 AND_imm32_r32( SR_MD, R_EAX );
282 if( sh4_x86.in_delay_slot ) {
283 JE_exit( EXIT_SLOT_ILLEGAL );
284 } else {
285 JE_exit( EXIT_ILLEGAL );
286 }
287 }
288 }
290 static void check_fpuen( )
291 {
292 if( !sh4_x86.fpuen_checked ) {
293 sh4_x86.fpuen_checked = TRUE;
294 load_spreg( R_EAX, R_SR );
295 AND_imm32_r32( SR_FD, R_EAX );
296 if( sh4_x86.in_delay_slot ) {
297 JNE_exit(EXIT_SLOT_FPU_DISABLED);
298 } else {
299 JNE_exit(EXIT_FPU_DISABLED);
300 }
301 }
302 }
304 static void check_ralign16( int x86reg )
305 {
306 TEST_imm32_r32( 0x00000001, x86reg );
307 JNE_exit(EXIT_DATA_ADDR_READ);
308 }
310 static void check_walign16( int x86reg )
311 {
312 TEST_imm32_r32( 0x00000001, x86reg );
313 JNE_exit(EXIT_DATA_ADDR_WRITE);
314 }
316 static void check_ralign32( int x86reg )
317 {
318 TEST_imm32_r32( 0x00000003, x86reg );
319 JNE_exit(EXIT_DATA_ADDR_READ);
320 }
321 static void check_walign32( int x86reg )
322 {
323 TEST_imm32_r32( 0x00000003, x86reg );
324 JNE_exit(EXIT_DATA_ADDR_WRITE);
325 }
328 #define UNDEF()
329 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
330 #define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
331 #define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
332 #define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
333 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
334 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
335 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
337 #define RAISE_EXCEPTION( exc ) call_func1(sh4_raise_exception, exc);
338 #define SLOTILLEGAL() RAISE_EXCEPTION(EXC_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1
342 /**
343 * Emit the 'start of block' assembly. Sets up the stack frame and save
344 * SI/DI as required
345 */
346 void sh4_translate_begin_block()
347 {
348 PUSH_r32(R_EBP);
349 /* mov &sh4r, ebp */
350 load_imm32( R_EBP, (uint32_t)&sh4r );
351 PUSH_r32(R_EDI);
352 PUSH_r32(R_ESI);
353 XOR_r32_r32(R_ESI, R_ESI);
355 sh4_x86.in_delay_slot = FALSE;
356 sh4_x86.priv_checked = FALSE;
357 sh4_x86.fpuen_checked = FALSE;
358 sh4_x86.backpatch_posn = 0;
359 }
361 /**
362 * Exit the block early (ie branch out), conditionally or otherwise
363 */
364 void exit_block( )
365 {
366 store_spreg( R_EDI, REG_OFFSET(pc) );
367 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
368 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
369 MUL_r32( R_ESI );
370 ADD_r32_r32( R_EAX, R_ECX );
371 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
372 load_imm32( R_EAX, 1 );
373 POP_r32(R_ESI);
374 POP_r32(R_EDI);
375 POP_r32(R_EBP);
376 RET();
377 }
379 /**
380 * Flush any open regs back to memory, restore SI/DI/, update PC, etc
381 */
382 void sh4_translate_end_block( sh4addr_t pc ) {
383 assert( !sh4_x86.in_delay_slot ); // should never stop here
384 // Normal termination - save PC, cycle count
385 exit_block( );
387 uint8_t *end_ptr = xlat_output;
388 // Exception termination. Jump block for various exception codes:
389 PUSH_imm32( EXC_DATA_ADDR_READ );
390 JMP_rel8( 33, target1 );
391 PUSH_imm32( EXC_DATA_ADDR_WRITE );
392 JMP_rel8( 26, target2 );
393 PUSH_imm32( EXC_ILLEGAL );
394 JMP_rel8( 19, target3 );
395 PUSH_imm32( EXC_SLOT_ILLEGAL );
396 JMP_rel8( 12, target4 );
397 PUSH_imm32( EXC_FPU_DISABLED );
398 JMP_rel8( 5, target5 );
399 PUSH_imm32( EXC_SLOT_FPU_DISABLED );
400 // target
401 JMP_TARGET(target1);
402 JMP_TARGET(target2);
403 JMP_TARGET(target3);
404 JMP_TARGET(target4);
405 JMP_TARGET(target5);
406 load_spreg( R_ECX, REG_OFFSET(pc) );
407 ADD_r32_r32( R_ESI, R_ECX );
408 ADD_r32_r32( R_ESI, R_ECX );
409 store_spreg( R_ECX, REG_OFFSET(pc) );
410 MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
411 load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
412 MUL_r32( R_ESI );
413 ADD_r32_r32( R_EAX, R_ECX );
414 store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
416 load_imm32( R_EAX, (uint32_t)sh4_raise_exception ); // 6
417 CALL_r32( R_EAX ); // 2
418 ADD_imm8s_r32( 4, R_ESP );
419 POP_r32(R_ESI);
420 POP_r32(R_EDI);
421 POP_r32(R_EBP);
422 RET();
424 sh4_x86_do_backpatch( end_ptr );
425 }
427 /**
428 * Translate a single instruction. Delayed branches are handled specially
429 * by translating both branch and delayed instruction as a single unit (as
430 *
431 *
432 * @return true if the instruction marks the end of a basic block
433 * (eg a branch or
434 */
435 uint32_t sh4_x86_translate_instruction( uint32_t pc )
436 {
437 uint16_t ir = sh4_read_word( pc );
439 %%
440 /* ALU operations */
441 ADD Rm, Rn {:
442 load_reg( R_EAX, Rm );
443 load_reg( R_ECX, Rn );
444 ADD_r32_r32( R_EAX, R_ECX );
445 store_reg( R_ECX, Rn );
446 :}
447 ADD #imm, Rn {:
448 load_reg( R_EAX, Rn );
449 ADD_imm8s_r32( imm, R_EAX );
450 store_reg( R_EAX, Rn );
451 :}
452 ADDC Rm, Rn {:
453 load_reg( R_EAX, Rm );
454 load_reg( R_ECX, Rn );
455 LDC_t();
456 ADC_r32_r32( R_EAX, R_ECX );
457 store_reg( R_ECX, Rn );
458 SETC_t();
459 :}
460 ADDV Rm, Rn {:
461 load_reg( R_EAX, Rm );
462 load_reg( R_ECX, Rn );
463 ADD_r32_r32( R_EAX, R_ECX );
464 store_reg( R_ECX, Rn );
465 SETO_t();
466 :}
467 AND Rm, Rn {:
468 load_reg( R_EAX, Rm );
469 load_reg( R_ECX, Rn );
470 AND_r32_r32( R_EAX, R_ECX );
471 store_reg( R_ECX, Rn );
472 :}
473 AND #imm, R0 {:
474 load_reg( R_EAX, 0 );
475 AND_imm32_r32(imm, R_EAX);
476 store_reg( R_EAX, 0 );
477 :}
478 AND.B #imm, @(R0, GBR) {:
479 load_reg( R_EAX, 0 );
480 load_spreg( R_ECX, R_GBR );
481 ADD_r32_r32( R_EAX, R_ECX );
482 MEM_READ_BYTE( R_ECX, R_EAX );
483 AND_imm32_r32(imm, R_ECX );
484 MEM_WRITE_BYTE( R_ECX, R_EAX );
485 :}
486 CMP/EQ Rm, Rn {:
487 load_reg( R_EAX, Rm );
488 load_reg( R_ECX, Rn );
489 CMP_r32_r32( R_EAX, R_ECX );
490 SETE_t();
491 :}
492 CMP/EQ #imm, R0 {:
493 load_reg( R_EAX, 0 );
494 CMP_imm8s_r32(imm, R_EAX);
495 SETE_t();
496 :}
497 CMP/GE Rm, Rn {:
498 load_reg( R_EAX, Rm );
499 load_reg( R_ECX, Rn );
500 CMP_r32_r32( R_EAX, R_ECX );
501 SETGE_t();
502 :}
503 CMP/GT Rm, Rn {:
504 load_reg( R_EAX, Rm );
505 load_reg( R_ECX, Rn );
506 CMP_r32_r32( R_EAX, R_ECX );
507 SETG_t();
508 :}
509 CMP/HI Rm, Rn {:
510 load_reg( R_EAX, Rm );
511 load_reg( R_ECX, Rn );
512 CMP_r32_r32( R_EAX, R_ECX );
513 SETA_t();
514 :}
515 CMP/HS Rm, Rn {:
516 load_reg( R_EAX, Rm );
517 load_reg( R_ECX, Rn );
518 CMP_r32_r32( R_EAX, R_ECX );
519 SETAE_t();
520 :}
521 CMP/PL Rn {:
522 load_reg( R_EAX, Rn );
523 CMP_imm8s_r32( 0, R_EAX );
524 SETG_t();
525 :}
526 CMP/PZ Rn {:
527 load_reg( R_EAX, Rn );
528 CMP_imm8s_r32( 0, R_EAX );
529 SETGE_t();
530 :}
531 CMP/STR Rm, Rn {:
532 load_reg( R_EAX, Rm );
533 load_reg( R_ECX, Rn );
534 XOR_r32_r32( R_ECX, R_EAX );
535 TEST_r8_r8( R_AL, R_AL );
536 JE_rel8(13, target1);
537 TEST_r8_r8( R_AH, R_AH ); // 2
538 JE_rel8(9, target2);
539 SHR_imm8_r32( 16, R_EAX ); // 3
540 TEST_r8_r8( R_AL, R_AL ); // 2
541 JE_rel8(2, target3);
542 TEST_r8_r8( R_AH, R_AH ); // 2
543 JMP_TARGET(target1);
544 JMP_TARGET(target2);
545 JMP_TARGET(target3);
546 SETE_t();
547 :}
548 DIV0S Rm, Rn {:
549 load_reg( R_EAX, Rm );
550 load_reg( R_ECX, Rm );
551 SHR_imm8_r32( 31, R_EAX );
552 SHR_imm8_r32( 31, R_ECX );
553 store_spreg( R_EAX, R_M );
554 store_spreg( R_ECX, R_Q );
555 CMP_r32_r32( R_EAX, R_ECX );
556 SETE_t();
557 :}
558 DIV0U {:
559 XOR_r32_r32( R_EAX, R_EAX );
560 store_spreg( R_EAX, R_Q );
561 store_spreg( R_EAX, R_M );
562 store_spreg( R_EAX, R_T );
563 :}
564 DIV1 Rm, Rn {:
565 load_reg( R_ECX, Rn );
566 LDC_t();
567 RCL1_r32( R_ECX ); // OP2
568 SETC_r32( R_EDX ); // Q
569 load_spreg( R_EAX, R_Q );
570 CMP_sh4r_r32( R_M, R_EAX );
571 JE_rel8(8,mqequal);
572 ADD_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
573 JMP_rel8(3, mqnotequal);
574 JMP_TARGET(mqequal);
575 SUB_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
576 JMP_TARGET(mqnotequal);
577 // TODO
578 :}
579 DMULS.L Rm, Rn {:
580 load_reg( R_EAX, Rm );
581 load_reg( R_ECX, Rn );
582 IMUL_r32(R_ECX);
583 store_spreg( R_EDX, R_MACH );
584 store_spreg( R_EAX, R_MACL );
585 :}
586 DMULU.L Rm, Rn {:
587 load_reg( R_EAX, Rm );
588 load_reg( R_ECX, Rn );
589 MUL_r32(R_ECX);
590 store_spreg( R_EDX, R_MACH );
591 store_spreg( R_EAX, R_MACL );
592 :}
593 DT Rn {:
594 load_reg( R_EAX, Rn );
595 ADD_imm8s_r32( -1, R_EAX );
596 store_reg( R_EAX, Rn );
597 SETE_t();
598 :}
599 EXTS.B Rm, Rn {:
600 load_reg( R_EAX, Rm );
601 MOVSX_r8_r32( R_EAX, R_EAX );
602 store_reg( R_EAX, Rn );
603 :}
604 EXTS.W Rm, Rn {:
605 load_reg( R_EAX, Rm );
606 MOVSX_r16_r32( R_EAX, R_EAX );
607 store_reg( R_EAX, Rn );
608 :}
609 EXTU.B Rm, Rn {:
610 load_reg( R_EAX, Rm );
611 MOVZX_r8_r32( R_EAX, R_EAX );
612 store_reg( R_EAX, Rn );
613 :}
614 EXTU.W Rm, Rn {:
615 load_reg( R_EAX, Rm );
616 MOVZX_r16_r32( R_EAX, R_EAX );
617 store_reg( R_EAX, Rn );
618 :}
619 MAC.L @Rm+, @Rn+ {: :}
620 MAC.W @Rm+, @Rn+ {: :}
621 MOVT Rn {:
622 load_spreg( R_EAX, R_T );
623 store_reg( R_EAX, Rn );
624 :}
625 MUL.L Rm, Rn {:
626 load_reg( R_EAX, Rm );
627 load_reg( R_ECX, Rn );
628 MUL_r32( R_ECX );
629 store_spreg( R_EAX, R_MACL );
630 :}
631 MULS.W Rm, Rn {:
632 load_reg16s( R_EAX, Rm );
633 load_reg16s( R_ECX, Rn );
634 MUL_r32( R_ECX );
635 store_spreg( R_EAX, R_MACL );
636 :}
637 MULU.W Rm, Rn {:
638 load_reg16u( R_EAX, Rm );
639 load_reg16u( R_ECX, Rn );
640 MUL_r32( R_ECX );
641 store_spreg( R_EAX, R_MACL );
642 :}
643 NEG Rm, Rn {:
644 load_reg( R_EAX, Rm );
645 NEG_r32( R_EAX );
646 store_reg( R_EAX, Rn );
647 :}
648 NEGC Rm, Rn {:
649 load_reg( R_EAX, Rm );
650 XOR_r32_r32( R_ECX, R_ECX );
651 LDC_t();
652 SBB_r32_r32( R_EAX, R_ECX );
653 store_reg( R_ECX, Rn );
654 SETC_t();
655 :}
656 NOT Rm, Rn {:
657 load_reg( R_EAX, Rm );
658 NOT_r32( R_EAX );
659 store_reg( R_EAX, Rn );
660 :}
661 OR Rm, Rn {:
662 load_reg( R_EAX, Rm );
663 load_reg( R_ECX, Rn );
664 OR_r32_r32( R_EAX, R_ECX );
665 store_reg( R_ECX, Rn );
666 :}
667 OR #imm, R0 {:
668 load_reg( R_EAX, 0 );
669 OR_imm32_r32(imm, R_EAX);
670 store_reg( R_EAX, 0 );
671 :}
672 OR.B #imm, @(R0, GBR) {:
673 load_reg( R_EAX, 0 );
674 load_spreg( R_ECX, R_GBR );
675 ADD_r32_r32( R_EAX, R_ECX );
676 MEM_READ_BYTE( R_ECX, R_EAX );
677 OR_imm32_r32(imm, R_ECX );
678 MEM_WRITE_BYTE( R_ECX, R_EAX );
679 :}
680 ROTCL Rn {:
681 load_reg( R_EAX, Rn );
682 LDC_t();
683 RCL1_r32( R_EAX );
684 store_reg( R_EAX, Rn );
685 SETC_t();
686 :}
687 ROTCR Rn {:
688 load_reg( R_EAX, Rn );
689 LDC_t();
690 RCR1_r32( R_EAX );
691 store_reg( R_EAX, Rn );
692 SETC_t();
693 :}
694 ROTL Rn {:
695 load_reg( R_EAX, Rn );
696 ROL1_r32( R_EAX );
697 store_reg( R_EAX, Rn );
698 SETC_t();
699 :}
700 ROTR Rn {:
701 load_reg( R_EAX, Rn );
702 ROR1_r32( R_EAX );
703 store_reg( R_EAX, Rn );
704 SETC_t();
705 :}
706 SHAD Rm, Rn {:
707 /* Annoyingly enough, not directly convertible */
708 load_reg( R_EAX, Rn );
709 load_reg( R_ECX, Rm );
710 CMP_imm32_r32( 0, R_ECX );
711 JGE_rel8(9, doshl);
713 NEG_r32( R_ECX ); // 2
714 AND_imm8_r8( 0x1F, R_CL ); // 3
715 SAR_r32_CL( R_EAX ); // 2
716 JMP_rel8(5, end); // 2
718 JMP_TARGET(doshl);
719 AND_imm8_r8( 0x1F, R_CL ); // 3
720 SHL_r32_CL( R_EAX ); // 2
721 JMP_TARGET(end);
722 store_reg( R_EAX, Rn );
723 :}
724 SHLD Rm, Rn {:
725 load_reg( R_EAX, Rn );
726 load_reg( R_ECX, Rm );
727 CMP_imm32_r32( 0, R_ECX );
728 JGE_rel8(9, doshl);
730 NEG_r32( R_ECX ); // 2
731 AND_imm8_r8( 0x1F, R_CL ); // 3
732 SHR_r32_CL( R_EAX ); // 2
733 JMP_rel8(5, end); // 2
735 JMP_TARGET(doshl);
736 AND_imm8_r8( 0x1F, R_CL ); // 3
737 SHL_r32_CL( R_EAX ); // 2
738 JMP_TARGET(end);
739 store_reg( R_EAX, Rn );
740 :}
741 SHAL Rn {:
742 load_reg( R_EAX, Rn );
743 SHL1_r32( R_EAX );
744 store_reg( R_EAX, Rn );
745 :}
746 SHAR Rn {:
747 load_reg( R_EAX, Rn );
748 SAR1_r32( R_EAX );
749 store_reg( R_EAX, Rn );
750 :}
751 SHLL Rn {:
752 load_reg( R_EAX, Rn );
753 SHL1_r32( R_EAX );
754 store_reg( R_EAX, Rn );
755 :}
756 SHLL2 Rn {:
757 load_reg( R_EAX, Rn );
758 SHL_imm8_r32( 2, R_EAX );
759 store_reg( R_EAX, Rn );
760 :}
761 SHLL8 Rn {:
762 load_reg( R_EAX, Rn );
763 SHL_imm8_r32( 8, R_EAX );
764 store_reg( R_EAX, Rn );
765 :}
766 SHLL16 Rn {:
767 load_reg( R_EAX, Rn );
768 SHL_imm8_r32( 16, R_EAX );
769 store_reg( R_EAX, Rn );
770 :}
771 SHLR Rn {:
772 load_reg( R_EAX, Rn );
773 SHR1_r32( R_EAX );
774 store_reg( R_EAX, Rn );
775 :}
776 SHLR2 Rn {:
777 load_reg( R_EAX, Rn );
778 SHR_imm8_r32( 2, R_EAX );
779 store_reg( R_EAX, Rn );
780 :}
781 SHLR8 Rn {:
782 load_reg( R_EAX, Rn );
783 SHR_imm8_r32( 8, R_EAX );
784 store_reg( R_EAX, Rn );
785 :}
786 SHLR16 Rn {:
787 load_reg( R_EAX, Rn );
788 SHR_imm8_r32( 16, R_EAX );
789 store_reg( R_EAX, Rn );
790 :}
791 SUB Rm, Rn {:
792 load_reg( R_EAX, Rm );
793 load_reg( R_ECX, Rn );
794 SUB_r32_r32( R_EAX, R_ECX );
795 store_reg( R_ECX, Rn );
796 :}
797 SUBC Rm, Rn {:
798 load_reg( R_EAX, Rm );
799 load_reg( R_ECX, Rn );
800 LDC_t();
801 SBB_r32_r32( R_EAX, R_ECX );
802 store_reg( R_ECX, Rn );
803 :}
804 SUBV Rm, Rn {:
805 load_reg( R_EAX, Rm );
806 load_reg( R_ECX, Rn );
807 SUB_r32_r32( R_EAX, R_ECX );
808 store_reg( R_ECX, Rn );
809 SETO_t();
810 :}
811 SWAP.B Rm, Rn {:
812 load_reg( R_EAX, Rm );
813 XCHG_r8_r8( R_AL, R_AH );
814 store_reg( R_EAX, Rn );
815 :}
816 SWAP.W Rm, Rn {:
817 load_reg( R_EAX, Rm );
818 MOV_r32_r32( R_EAX, R_ECX );
819 SHL_imm8_r32( 16, R_ECX );
820 SHR_imm8_r32( 16, R_EAX );
821 OR_r32_r32( R_EAX, R_ECX );
822 store_reg( R_ECX, Rn );
823 :}
824 TAS.B @Rn {:
825 load_reg( R_ECX, Rn );
826 MEM_READ_BYTE( R_ECX, R_EAX );
827 TEST_r8_r8( R_AL, R_AL );
828 SETE_t();
829 OR_imm8_r8( 0x80, R_AL );
830 MEM_WRITE_BYTE( R_ECX, R_EAX );
831 :}
832 TST Rm, Rn {:
833 load_reg( R_EAX, Rm );
834 load_reg( R_ECX, Rn );
835 TEST_r32_r32( R_EAX, R_ECX );
836 SETE_t();
837 :}
838 TST #imm, R0 {:
839 load_reg( R_EAX, 0 );
840 TEST_imm32_r32( imm, R_EAX );
841 SETE_t();
842 :}
843 TST.B #imm, @(R0, GBR) {:
844 load_reg( R_EAX, 0);
845 load_reg( R_ECX, R_GBR);
846 ADD_r32_r32( R_EAX, R_ECX );
847 MEM_READ_BYTE( R_ECX, R_EAX );
848 TEST_imm8_r8( imm, R_EAX );
849 SETE_t();
850 :}
851 XOR Rm, Rn {:
852 load_reg( R_EAX, Rm );
853 load_reg( R_ECX, Rn );
854 XOR_r32_r32( R_EAX, R_ECX );
855 store_reg( R_ECX, Rn );
856 :}
857 XOR #imm, R0 {:
858 load_reg( R_EAX, 0 );
859 XOR_imm32_r32( imm, R_EAX );
860 store_reg( R_EAX, 0 );
861 :}
862 XOR.B #imm, @(R0, GBR) {:
863 load_reg( R_EAX, 0 );
864 load_spreg( R_ECX, R_GBR );
865 ADD_r32_r32( R_EAX, R_ECX );
866 MEM_READ_BYTE( R_ECX, R_EAX );
867 XOR_imm32_r32( imm, R_EAX );
868 MEM_WRITE_BYTE( R_ECX, R_EAX );
869 :}
870 XTRCT Rm, Rn {:
871 load_reg( R_EAX, Rm );
872 MOV_r32_r32( R_EAX, R_ECX );
873 SHR_imm8_r32( 16, R_EAX );
874 SHL_imm8_r32( 16, R_ECX );
875 OR_r32_r32( R_EAX, R_ECX );
876 store_reg( R_ECX, Rn );
877 :}
879 /* Data move instructions */
880 MOV Rm, Rn {:
881 load_reg( R_EAX, Rm );
882 store_reg( R_EAX, Rn );
883 :}
884 MOV #imm, Rn {:
885 load_imm32( R_EAX, imm );
886 store_reg( R_EAX, Rn );
887 :}
888 MOV.B Rm, @Rn {:
889 load_reg( R_EAX, Rm );
890 load_reg( R_ECX, Rn );
891 MEM_WRITE_BYTE( R_ECX, R_EAX );
892 :}
893 MOV.B Rm, @-Rn {:
894 load_reg( R_EAX, Rm );
895 load_reg( R_ECX, Rn );
896 ADD_imm8s_r32( -1, R_ECX );
897 store_reg( R_ECX, Rn );
898 MEM_WRITE_BYTE( R_ECX, R_EAX );
899 :}
900 MOV.B Rm, @(R0, Rn) {:
901 load_reg( R_EAX, 0 );
902 load_reg( R_ECX, Rn );
903 ADD_r32_r32( R_EAX, R_ECX );
904 load_reg( R_EAX, Rm );
905 MEM_WRITE_BYTE( R_ECX, R_EAX );
906 :}
907 MOV.B R0, @(disp, GBR) {:
908 load_reg( R_EAX, 0 );
909 load_spreg( R_ECX, R_GBR );
910 ADD_imm32_r32( disp, R_ECX );
911 MEM_WRITE_BYTE( R_ECX, R_EAX );
912 :}
913 MOV.B R0, @(disp, Rn) {:
914 load_reg( R_EAX, 0 );
915 load_reg( R_ECX, Rn );
916 ADD_imm32_r32( disp, R_ECX );
917 MEM_WRITE_BYTE( R_ECX, R_EAX );
918 :}
919 MOV.B @Rm, Rn {:
920 load_reg( R_ECX, Rm );
921 MEM_READ_BYTE( R_ECX, R_EAX );
922 store_reg( R_ECX, Rn );
923 :}
924 MOV.B @Rm+, Rn {:
925 load_reg( R_ECX, Rm );
926 MOV_r32_r32( R_ECX, R_EAX );
927 ADD_imm8s_r32( 1, R_EAX );
928 store_reg( R_EAX, Rm );
929 MEM_READ_BYTE( R_ECX, R_EAX );
930 store_reg( R_EAX, Rn );
931 :}
932 MOV.B @(R0, Rm), Rn {:
933 load_reg( R_EAX, 0 );
934 load_reg( R_ECX, Rm );
935 ADD_r32_r32( R_EAX, R_ECX );
936 MEM_READ_BYTE( R_ECX, R_EAX );
937 store_reg( R_EAX, Rn );
938 :}
939 MOV.B @(disp, GBR), R0 {:
940 load_spreg( R_ECX, R_GBR );
941 ADD_imm32_r32( disp, R_ECX );
942 MEM_READ_BYTE( R_ECX, R_EAX );
943 store_reg( R_EAX, 0 );
944 :}
945 MOV.B @(disp, Rm), R0 {:
946 load_reg( R_ECX, Rm );
947 ADD_imm32_r32( disp, R_ECX );
948 MEM_READ_BYTE( R_ECX, R_EAX );
949 store_reg( R_EAX, 0 );
950 :}
951 MOV.L Rm, @Rn {:
952 load_reg( R_EAX, Rm );
953 load_reg( R_ECX, Rn );
954 check_walign32(R_ECX);
955 MEM_WRITE_LONG( R_ECX, R_EAX );
956 :}
957 MOV.L Rm, @-Rn {:
958 load_reg( R_EAX, Rm );
959 load_reg( R_ECX, Rn );
960 check_walign32( R_ECX );
961 ADD_imm8s_r32( -4, R_ECX );
962 store_reg( R_ECX, Rn );
963 MEM_WRITE_LONG( R_ECX, R_EAX );
964 :}
965 MOV.L Rm, @(R0, Rn) {:
966 load_reg( R_EAX, 0 );
967 load_reg( R_ECX, Rn );
968 ADD_r32_r32( R_EAX, R_ECX );
969 check_walign32( R_ECX );
970 load_reg( R_EAX, Rm );
971 MEM_WRITE_LONG( R_ECX, R_EAX );
972 :}
973 MOV.L R0, @(disp, GBR) {:
974 load_spreg( R_ECX, R_GBR );
975 load_reg( R_EAX, 0 );
976 ADD_imm32_r32( disp, R_ECX );
977 check_walign32( R_ECX );
978 MEM_WRITE_LONG( R_ECX, R_EAX );
979 :}
980 MOV.L Rm, @(disp, Rn) {:
981 load_reg( R_ECX, Rn );
982 load_reg( R_EAX, Rm );
983 ADD_imm32_r32( disp, R_ECX );
984 check_walign32( R_ECX );
985 MEM_WRITE_LONG( R_ECX, R_EAX );
986 :}
987 MOV.L @Rm, Rn {:
988 load_reg( R_ECX, Rm );
989 check_ralign32( R_ECX );
990 MEM_READ_LONG( R_ECX, R_EAX );
991 store_reg( R_EAX, Rn );
992 :}
993 MOV.L @Rm+, Rn {:
994 load_reg( R_EAX, Rm );
995 check_ralign32( R_EAX );
996 MOV_r32_r32( R_EAX, R_ECX );
997 ADD_imm8s_r32( 4, R_EAX );
998 store_reg( R_EAX, Rm );
999 MEM_READ_LONG( R_ECX, R_EAX );
1000 store_reg( R_EAX, Rn );
1001 :}
1002 MOV.L @(R0, Rm), Rn {:
1003 load_reg( R_EAX, 0 );
1004 load_reg( R_ECX, Rm );
1005 ADD_r32_r32( R_EAX, R_ECX );
1006 check_ralign32( R_ECX );
1007 MEM_READ_LONG( R_ECX, R_EAX );
1008 store_reg( R_EAX, Rn );
1009 :}
1010 MOV.L @(disp, GBR), R0 {:
1011 load_spreg( R_ECX, R_GBR );
1012 ADD_imm32_r32( disp, R_ECX );
1013 check_ralign32( R_ECX );
1014 MEM_READ_LONG( R_ECX, R_EAX );
1015 store_reg( R_EAX, 0 );
1016 :}
1017 MOV.L @(disp, PC), Rn {:
1018 if( sh4_x86.in_delay_slot ) {
1019 SLOTILLEGAL();
1020 } else {
1021 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1022 MEM_READ_LONG( R_ECX, R_EAX );
1023 store_reg( R_EAX, Rn );
1024 }
1025 :}
1026 MOV.L @(disp, Rm), Rn {:
1027 load_reg( R_ECX, Rm );
1028 ADD_imm8s_r32( disp, R_ECX );
1029 check_ralign32( R_ECX );
1030 MEM_READ_LONG( R_ECX, R_EAX );
1031 store_reg( R_EAX, Rn );
1032 :}
1033 MOV.W Rm, @Rn {:
1034 load_reg( R_ECX, Rn );
1035 check_walign16( R_ECX );
1036 load_reg( R_EAX, Rm );
1037 MEM_WRITE_WORD( R_ECX, R_EAX );
1038 :}
1039 MOV.W Rm, @-Rn {:
1040 load_reg( R_ECX, Rn );
1041 check_walign16( R_ECX );
1042 load_reg( R_EAX, Rm );
1043 ADD_imm8s_r32( -2, R_ECX );
1044 store_reg( R_ECX, Rn );
1045 MEM_WRITE_WORD( R_ECX, R_EAX );
1046 :}
1047 MOV.W Rm, @(R0, Rn) {:
1048 load_reg( R_EAX, 0 );
1049 load_reg( R_ECX, Rn );
1050 ADD_r32_r32( R_EAX, R_ECX );
1051 check_walign16( R_ECX );
1052 load_reg( R_EAX, Rm );
1053 MEM_WRITE_WORD( R_ECX, R_EAX );
1054 :}
1055 MOV.W R0, @(disp, GBR) {:
1056 load_spreg( R_ECX, R_GBR );
1057 load_reg( R_EAX, 0 );
1058 ADD_imm32_r32( disp, R_ECX );
1059 check_walign16( R_ECX );
1060 MEM_WRITE_WORD( R_ECX, R_EAX );
1061 :}
1062 MOV.W R0, @(disp, Rn) {:
1063 load_reg( R_ECX, Rn );
1064 load_reg( R_EAX, 0 );
1065 ADD_imm32_r32( disp, R_ECX );
1066 check_walign16( R_ECX );
1067 MEM_WRITE_WORD( R_ECX, R_EAX );
1068 :}
1069 MOV.W @Rm, Rn {:
1070 load_reg( R_ECX, Rm );
1071 check_ralign16( R_ECX );
1072 MEM_READ_WORD( R_ECX, R_EAX );
1073 store_reg( R_EAX, Rn );
1074 :}
1075 MOV.W @Rm+, Rn {:
1076 load_reg( R_EAX, Rm );
1077 check_ralign16( R_EAX );
1078 MOV_r32_r32( R_EAX, R_ECX );
1079 ADD_imm8s_r32( 2, R_EAX );
1080 store_reg( R_EAX, Rm );
1081 MEM_READ_WORD( R_ECX, R_EAX );
1082 store_reg( R_EAX, Rn );
1083 :}
1084 MOV.W @(R0, Rm), Rn {:
1085 load_reg( R_EAX, 0 );
1086 load_reg( R_ECX, Rm );
1087 ADD_r32_r32( R_EAX, R_ECX );
1088 check_ralign16( R_ECX );
1089 MEM_READ_WORD( R_ECX, R_EAX );
1090 store_reg( R_EAX, Rn );
1091 :}
1092 MOV.W @(disp, GBR), R0 {:
1093 load_spreg( R_ECX, R_GBR );
1094 ADD_imm32_r32( disp, R_ECX );
1095 check_ralign16( R_ECX );
1096 MEM_READ_WORD( R_ECX, R_EAX );
1097 store_reg( R_EAX, 0 );
1098 :}
1099 MOV.W @(disp, PC), Rn {:
1100 if( sh4_x86.in_delay_slot ) {
1101 SLOTILLEGAL();
1102 } else {
1103 load_imm32( R_ECX, pc + disp + 4 );
1104 MEM_READ_WORD( R_ECX, R_EAX );
1105 store_reg( R_EAX, Rn );
1106 }
1107 :}
1108 MOV.W @(disp, Rm), R0 {:
1109 load_reg( R_ECX, Rm );
1110 ADD_imm32_r32( disp, R_ECX );
1111 check_ralign16( R_ECX );
1112 MEM_READ_WORD( R_ECX, R_EAX );
1113 store_reg( R_EAX, 0 );
1114 :}
1115 MOVA @(disp, PC), R0 {:
1116 if( sh4_x86.in_delay_slot ) {
1117 SLOTILLEGAL();
1118 } else {
1119 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1120 store_reg( R_ECX, 0 );
1121 }
1122 :}
1123 MOVCA.L R0, @Rn {:
1124 load_reg( R_EAX, 0 );
1125 load_reg( R_ECX, Rn );
1126 check_walign32( R_ECX );
1127 MEM_WRITE_LONG( R_ECX, R_EAX );
1128 :}
1130 /* Control transfer instructions */
1131 BF disp {:
1132 if( sh4_x86.in_delay_slot ) {
1133 SLOTILLEGAL();
1134 } else {
1135 load_imm32( R_EDI, pc + 2 );
1136 CMP_imm8s_sh4r( 0, R_T );
1137 JNE_rel8( 5, nottaken );
1138 load_imm32( R_EDI, disp + pc + 4 );
1139 JMP_TARGET(nottaken);
1140 INC_r32(R_ESI);
1141 return 1;
1142 }
1143 :}
1144 BF/S disp {:
1145 if( sh4_x86.in_delay_slot ) {
1146 SLOTILLEGAL();
1147 } else {
1148 load_imm32( R_EDI, pc + 2 );
1149 CMP_imm8s_sh4r( 0, R_T );
1150 JNE_rel8( 5, nottaken );
1151 load_imm32( R_EDI, disp + pc + 4 );
1152 JMP_TARGET(nottaken);
1153 sh4_x86.in_delay_slot = TRUE;
1154 INC_r32(R_ESI);
1155 return 0;
1156 }
1157 :}
1158 BRA disp {:
1159 if( sh4_x86.in_delay_slot ) {
1160 SLOTILLEGAL();
1161 } else {
1162 load_imm32( R_EDI, disp + pc + 4 );
1163 sh4_x86.in_delay_slot = TRUE;
1164 INC_r32(R_ESI);
1165 return 0;
1166 }
1167 :}
1168 BRAF Rn {:
1169 if( sh4_x86.in_delay_slot ) {
1170 SLOTILLEGAL();
1171 } else {
1172 load_reg( R_EDI, Rn );
1173 ADD_imm32_r32( pc + 4, R_EDI );
1174 sh4_x86.in_delay_slot = TRUE;
1175 INC_r32(R_ESI);
1176 return 0;
1177 }
1178 :}
1179 BSR disp {:
1180 if( sh4_x86.in_delay_slot ) {
1181 SLOTILLEGAL();
1182 } else {
1183 load_imm32( R_EAX, pc + 4 );
1184 store_spreg( R_EAX, R_PR );
1185 load_imm32( R_EDI, disp + pc + 4 );
1186 sh4_x86.in_delay_slot = TRUE;
1187 INC_r32(R_ESI);
1188 return 0;
1189 }
1190 :}
1191 BSRF Rn {:
1192 if( sh4_x86.in_delay_slot ) {
1193 SLOTILLEGAL();
1194 } else {
1195 load_imm32( R_EAX, pc + 4 );
1196 store_spreg( R_EAX, R_PR );
1197 load_reg( R_EDI, Rn );
1198 ADD_r32_r32( R_EAX, R_EDI );
1199 sh4_x86.in_delay_slot = TRUE;
1200 INC_r32(R_ESI);
1201 return 0;
1202 }
1203 :}
1204 BT disp {:
1205 if( sh4_x86.in_delay_slot ) {
1206 SLOTILLEGAL();
1207 } else {
1208 load_imm32( R_EDI, pc + 2 );
1209 CMP_imm8s_sh4r( 0, R_T );
1210 JE_rel8( 5, nottaken );
1211 load_imm32( R_EDI, disp + pc + 4 );
1212 JMP_TARGET(nottaken);
1213 INC_r32(R_ESI);
1214 return 1;
1215 }
1216 :}
1217 BT/S disp {:
1218 if( sh4_x86.in_delay_slot ) {
1219 SLOTILLEGAL();
1220 } else {
1221 load_imm32( R_EDI, pc + 2 );
1222 CMP_imm8s_sh4r( 0, R_T );
1223 JE_rel8( 5, nottaken );
1224 load_imm32( R_EDI, disp + pc + 4 );
1225 JMP_TARGET(nottaken);
1226 sh4_x86.in_delay_slot = TRUE;
1227 INC_r32(R_ESI);
1228 return 0;
1229 }
1230 :}
1231 JMP @Rn {:
1232 if( sh4_x86.in_delay_slot ) {
1233 SLOTILLEGAL();
1234 } else {
1235 load_reg( R_EDI, Rn );
1236 sh4_x86.in_delay_slot = TRUE;
1237 INC_r32(R_ESI);
1238 return 0;
1239 }
1240 :}
1241 JSR @Rn {:
1242 if( sh4_x86.in_delay_slot ) {
1243 SLOTILLEGAL();
1244 } else {
1245 load_imm32( R_EAX, pc + 4 );
1246 store_spreg( R_EAX, R_PR );
1247 load_reg( R_EDI, Rn );
1248 sh4_x86.in_delay_slot = TRUE;
1249 INC_r32(R_ESI);
1250 return 0;
1251 }
1252 :}
1253 RTE {:
1254 check_priv();
1255 if( sh4_x86.in_delay_slot ) {
1256 SLOTILLEGAL();
1257 } else {
1258 load_spreg( R_EDI, R_PR );
1259 load_spreg( R_EAX, R_SSR );
1260 call_func1( sh4_write_sr, R_EAX );
1261 sh4_x86.in_delay_slot = TRUE;
1262 sh4_x86.priv_checked = FALSE;
1263 sh4_x86.fpuen_checked = FALSE;
1264 INC_r32(R_ESI);
1265 return 0;
1266 }
1267 :}
1268 RTS {:
1269 if( sh4_x86.in_delay_slot ) {
1270 SLOTILLEGAL();
1271 } else {
1272 load_spreg( R_EDI, R_PR );
1273 sh4_x86.in_delay_slot = TRUE;
1274 INC_r32(R_ESI);
1275 return 0;
1276 }
1277 :}
1278 TRAPA #imm {:
1279 if( sh4_x86.in_delay_slot ) {
1280 SLOTILLEGAL();
1281 } else {
1282 // TODO: Write TRA
1283 RAISE_EXCEPTION(EXC_TRAP);
1284 }
1285 :}
1286 UNDEF {:
1287 if( sh4_x86.in_delay_slot ) {
1288 SLOTILLEGAL();
1289 } else {
1290 RAISE_EXCEPTION(EXC_ILLEGAL);
1291 return 1;
1292 }
1293 :}
1295 CLRMAC {:
1296 XOR_r32_r32(R_EAX, R_EAX);
1297 store_spreg( R_EAX, R_MACL );
1298 store_spreg( R_EAX, R_MACH );
1299 :}
1300 CLRS {:
1301 CLC();
1302 SETC_sh4r(R_S);
1303 :}
1304 CLRT {:
1305 CLC();
1306 SETC_t();
1307 :}
1308 SETS {:
1309 STC();
1310 SETC_sh4r(R_S);
1311 :}
1312 SETT {:
1313 STC();
1314 SETC_t();
1315 :}
1317 /* Floating point moves */
1318 FMOV FRm, FRn {:
1319 /* As horrible as this looks, it's actually covering 5 separate cases:
1320 * 1. 32-bit fr-to-fr (PR=0)
1321 * 2. 64-bit dr-to-dr (PR=1, FRm&1 == 0, FRn&1 == 0 )
1322 * 3. 64-bit dr-to-xd (PR=1, FRm&1 == 0, FRn&1 == 1 )
1323 * 4. 64-bit xd-to-dr (PR=1, FRm&1 == 1, FRn&1 == 0 )
1324 * 5. 64-bit xd-to-xd (PR=1, FRm&1 == 1, FRn&1 == 1 )
1325 */
1326 check_fpuen();
1327 load_spreg( R_ECX, R_FPSCR );
1328 load_fr_bank( R_EDX );
1329 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1330 JNE_rel8(8, doublesize);
1331 load_fr( R_EDX, R_EAX, FRm ); // PR=0 branch
1332 store_fr( R_EDX, R_EAX, FRn );
1333 if( FRm&1 ) {
1334 JMP_rel8(22, end);
1335 JMP_TARGET(doublesize);
1336 load_xf_bank( R_ECX );
1337 load_fr( R_ECX, R_EAX, FRm-1 );
1338 if( FRn&1 ) {
1339 load_fr( R_ECX, R_EDX, FRm );
1340 store_fr( R_ECX, R_EAX, FRn-1 );
1341 store_fr( R_ECX, R_EDX, FRn );
1342 } else /* FRn&1 == 0 */ {
1343 load_fr( R_ECX, R_ECX, FRm );
1344 store_fr( R_EDX, R_EAX, FRn-1 );
1345 store_fr( R_EDX, R_ECX, FRn );
1346 }
1347 JMP_TARGET(end);
1348 } else /* FRm&1 == 0 */ {
1349 if( FRn&1 ) {
1350 JMP_rel8(22, end);
1351 load_xf_bank( R_ECX );
1352 load_fr( R_EDX, R_EAX, FRm );
1353 load_fr( R_EDX, R_EDX, FRm+1 );
1354 store_fr( R_ECX, R_EAX, FRn-1 );
1355 store_fr( R_ECX, R_EDX, FRn );
1356 JMP_TARGET(end);
1357 } else /* FRn&1 == 0 */ {
1358 JMP_rel8(12, end);
1359 load_fr( R_EDX, R_EAX, FRm );
1360 load_fr( R_EDX, R_ECX, FRm+1 );
1361 store_fr( R_EDX, R_EAX, FRn );
1362 store_fr( R_EDX, R_ECX, FRn+1 );
1363 JMP_TARGET(end);
1364 }
1365 }
1366 :}
1367 FMOV FRm, @Rn {:
1368 check_fpuen();
1369 load_reg( R_EDX, Rn );
1370 check_walign32( R_EDX );
1371 load_spreg( R_ECX, R_FPSCR );
1372 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1373 JNE_rel8(20, doublesize);
1374 load_fr_bank( R_ECX );
1375 load_fr( R_ECX, R_EAX, FRm );
1376 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1377 if( FRm&1 ) {
1378 JMP_rel8( 46, end );
1379 JMP_TARGET(doublesize);
1380 load_xf_bank( R_ECX );
1381 load_fr( R_ECX, R_EAX, FRm&0x0E );
1382 load_fr( R_ECX, R_ECX, FRm|0x01 );
1383 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1384 JMP_TARGET(end);
1385 } else {
1386 JMP_rel8( 39, end );
1387 JMP_TARGET(doublesize);
1388 load_fr_bank( R_ECX );
1389 load_fr( R_ECX, R_EAX, FRm&0x0E );
1390 load_fr( R_ECX, R_ECX, FRm|0x01 );
1391 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1392 JMP_TARGET(end);
1393 }
1394 :}
1395 FMOV @Rm, FRn {:
1396 check_fpuen();
1397 load_reg( R_EDX, Rm );
1398 check_ralign32( R_EDX );
1399 load_spreg( R_ECX, R_FPSCR );
1400 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1401 JNE_rel8(19, doublesize);
1402 MEM_READ_LONG( R_EDX, R_EAX );
1403 load_fr_bank( R_ECX );
1404 store_fr( R_ECX, R_EAX, FRn );
1405 if( FRn&1 ) {
1406 JMP_rel8(46, end);
1407 JMP_TARGET(doublesize);
1408 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1409 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1410 load_xf_bank( R_ECX );
1411 store_fr( R_ECX, R_EAX, FRn&0x0E );
1412 store_fr( R_ECX, R_EDX, FRn|0x01 );
1413 JMP_TARGET(end);
1414 } else {
1415 JMP_rel8(36, end);
1416 JMP_TARGET(doublesize);
1417 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1418 load_fr_bank( R_ECX );
1419 store_fr( R_ECX, R_EAX, FRn&0x0E );
1420 store_fr( R_ECX, R_EDX, FRn|0x01 );
1421 JMP_TARGET(end);
1422 }
1423 :}
1424 FMOV FRm, @-Rn {:
1425 check_fpuen();
1426 load_reg( R_EDX, Rn );
1427 check_walign32( R_EDX );
1428 load_spreg( R_ECX, R_FPSCR );
1429 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1430 JNE_rel8(26, doublesize);
1431 load_fr_bank( R_ECX );
1432 load_fr( R_ECX, R_EAX, FRm );
1433 ADD_imm8s_r32(-4,R_EDX);
1434 store_reg( R_EDX, Rn );
1435 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1436 if( FRm&1 ) {
1437 JMP_rel8( 52, end );
1438 JMP_TARGET(doublesize);
1439 load_xf_bank( R_ECX );
1440 load_fr( R_ECX, R_EAX, FRm&0x0E );
1441 load_fr( R_ECX, R_ECX, FRm|0x01 );
1442 ADD_imm8s_r32(-8,R_EDX);
1443 store_reg( R_EDX, Rn );
1444 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1445 JMP_TARGET(end);
1446 } else {
1447 JMP_rel8( 45, end );
1448 JMP_TARGET(doublesize);
1449 load_fr_bank( R_ECX );
1450 load_fr( R_ECX, R_EAX, FRm&0x0E );
1451 load_fr( R_ECX, R_ECX, FRm|0x01 );
1452 ADD_imm8s_r32(-8,R_EDX);
1453 store_reg( R_EDX, Rn );
1454 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1455 JMP_TARGET(end);
1456 }
1457 :}
1458 FMOV @Rm+, FRn {:
1459 check_fpuen();
1460 load_reg( R_EDX, Rm );
1461 check_ralign32( R_EDX );
1462 MOV_r32_r32( R_EDX, R_EAX );
1463 load_spreg( R_ECX, R_FPSCR );
1464 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1465 JNE_rel8(25, doublesize);
1466 ADD_imm8s_r32( 4, R_EAX );
1467 store_reg( R_EAX, Rm );
1468 MEM_READ_LONG( R_EDX, R_EAX );
1469 load_fr_bank( R_ECX );
1470 store_fr( R_ECX, R_EAX, FRn );
1471 if( FRn&1 ) {
1472 JMP_rel8(52, end);
1473 JMP_TARGET(doublesize);
1474 ADD_imm8s_r32( 8, R_EAX );
1475 store_reg(R_EAX, Rm);
1476 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1477 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1478 load_xf_bank( R_ECX );
1479 store_fr( R_ECX, R_EAX, FRn&0x0E );
1480 store_fr( R_ECX, R_EDX, FRn|0x01 );
1481 JMP_TARGET(end);
1482 } else {
1483 JMP_rel8(42, end);
1484 ADD_imm8s_r32( 8, R_EAX );
1485 store_reg(R_EAX, Rm);
1486 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1487 load_fr_bank( R_ECX );
1488 store_fr( R_ECX, R_EAX, FRn&0x0E );
1489 store_fr( R_ECX, R_EDX, FRn|0x01 );
1490 JMP_TARGET(end);
1491 }
1492 :}
1493 FMOV FRm, @(R0, Rn) {:
1494 check_fpuen();
1495 load_reg( R_EDX, Rn );
1496 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
1497 check_walign32( R_EDX );
1498 load_spreg( R_ECX, R_FPSCR );
1499 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1500 JNE_rel8(20, doublesize);
1501 load_fr_bank( R_ECX );
1502 load_fr( R_ECX, R_EAX, FRm );
1503 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1504 if( FRm&1 ) {
1505 JMP_rel8( 46, end );
1506 JMP_TARGET(doublesize);
1507 load_xf_bank( R_ECX );
1508 load_fr( R_ECX, R_EAX, FRm&0x0E );
1509 load_fr( R_ECX, R_ECX, FRm|0x01 );
1510 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1511 JMP_TARGET(end);
1512 } else {
1513 JMP_rel8( 39, end );
1514 JMP_TARGET(doublesize);
1515 load_fr_bank( R_ECX );
1516 load_fr( R_ECX, R_EAX, FRm&0x0E );
1517 load_fr( R_ECX, R_ECX, FRm|0x01 );
1518 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1519 JMP_TARGET(end);
1520 }
1521 :}
1522 FMOV @(R0, Rm), FRn {:
1523 check_fpuen();
1524 load_reg( R_EDX, Rm );
1525 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
1526 check_ralign32( R_EDX );
1527 load_spreg( R_ECX, R_FPSCR );
1528 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1529 JNE_rel8(19, doublesize);
1530 MEM_READ_LONG( R_EDX, R_EAX );
1531 load_fr_bank( R_ECX );
1532 store_fr( R_ECX, R_EAX, FRn );
1533 if( FRn&1 ) {
1534 JMP_rel8(46, end);
1535 JMP_TARGET(doublesize);
1536 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1537 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1538 load_xf_bank( R_ECX );
1539 store_fr( R_ECX, R_EAX, FRn&0x0E );
1540 store_fr( R_ECX, R_EDX, FRn|0x01 );
1541 JMP_TARGET(end);
1542 } else {
1543 JMP_rel8(36, end);
1544 JMP_TARGET(doublesize);
1545 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1546 load_fr_bank( R_ECX );
1547 store_fr( R_ECX, R_EAX, FRn&0x0E );
1548 store_fr( R_ECX, R_EDX, FRn|0x01 );
1549 JMP_TARGET(end);
1550 }
1551 :}
1552 FLDI0 FRn {: /* IFF PR=0 */
1553 check_fpuen();
1554 load_spreg( R_ECX, R_FPSCR );
1555 TEST_imm32_r32( FPSCR_PR, R_ECX );
1556 JNE_rel8(8, end);
1557 XOR_r32_r32( R_EAX, R_EAX );
1558 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1559 store_fr( R_ECX, R_EAX, FRn );
1560 JMP_TARGET(end);
1561 :}
1562 FLDI1 FRn {: /* IFF PR=0 */
1563 check_fpuen();
1564 load_spreg( R_ECX, R_FPSCR );
1565 TEST_imm32_r32( FPSCR_PR, R_ECX );
1566 JNE_rel8(11, end);
1567 load_imm32(R_EAX, 0x3F800000);
1568 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1569 store_fr( R_ECX, R_EAX, FRn );
1570 JMP_TARGET(end);
1571 :}
1573 FLOAT FPUL, FRn {:
1574 check_fpuen();
1575 load_spreg( R_ECX, R_FPSCR );
1576 load_spreg(R_EDX, REG_OFFSET(fr_bank));
1577 FILD_sh4r(R_FPUL);
1578 TEST_imm32_r32( FPSCR_PR, R_ECX );
1579 JNE_rel8(5, doubleprec);
1580 pop_fr( R_EDX, FRn );
1581 JMP_rel8(3, end);
1582 JMP_TARGET(doubleprec);
1583 pop_dr( R_EDX, FRn );
1584 JMP_TARGET(end);
1585 :}
1586 FTRC FRm, FPUL {:
1587 check_fpuen();
1588 // TODO
1589 :}
1590 FLDS FRm, FPUL {:
1591 check_fpuen();
1592 load_fr_bank( R_ECX );
1593 load_fr( R_ECX, R_EAX, FRm );
1594 store_spreg( R_EAX, R_FPUL );
1595 :}
1596 FSTS FPUL, FRn {:
1597 check_fpuen();
1598 load_fr_bank( R_ECX );
1599 load_spreg( R_EAX, R_FPUL );
1600 store_fr( R_ECX, R_EAX, FRn );
1601 :}
1602 FCNVDS FRm, FPUL {:
1603 check_fpuen();
1604 load_spreg( R_ECX, R_FPSCR );
1605 TEST_imm32_r32( FPSCR_PR, R_ECX );
1606 JE_rel8(9, end); // only when PR=1
1607 load_fr_bank( R_ECX );
1608 push_dr( R_ECX, FRm );
1609 pop_fpul();
1610 JMP_TARGET(end);
1611 :}
1612 FCNVSD FPUL, FRn {:
1613 check_fpuen();
1614 check_fpuen();
1615 load_spreg( R_ECX, R_FPSCR );
1616 TEST_imm32_r32( FPSCR_PR, R_ECX );
1617 JE_rel8(9, end); // only when PR=1
1618 load_fr_bank( R_ECX );
1619 push_fpul();
1620 pop_dr( R_ECX, FRn );
1621 JMP_TARGET(end);
1622 :}
1624 /* Floating point instructions */
1625 FABS FRn {:
1626 check_fpuen();
1627 load_spreg( R_ECX, R_FPSCR );
1628 load_fr_bank( R_EDX );
1629 TEST_imm32_r32( FPSCR_PR, R_ECX );
1630 JNE_rel8(10, doubleprec);
1631 push_fr(R_EDX, FRn); // 3
1632 FABS_st0(); // 2
1633 pop_fr( R_EDX, FRn); //3
1634 JMP_rel8(8,end); // 2
1635 JMP_TARGET(doubleprec);
1636 push_dr(R_EDX, FRn);
1637 FABS_st0();
1638 pop_dr(R_EDX, FRn);
1639 JMP_TARGET(end);
1640 :}
1641 FADD FRm, FRn {:
1642 check_fpuen();
1643 load_spreg( R_ECX, R_FPSCR );
1644 TEST_imm32_r32( FPSCR_PR, R_ECX );
1645 load_fr_bank( R_EDX );
1646 JNE_rel8(13,doubleprec);
1647 push_fr(R_EDX, FRm);
1648 push_fr(R_EDX, FRn);
1649 FADDP_st(1);
1650 pop_fr(R_EDX, FRn);
1651 JMP_rel8(11,end);
1652 JMP_TARGET(doubleprec);
1653 push_dr(R_EDX, FRm);
1654 push_dr(R_EDX, FRn);
1655 FADDP_st(1);
1656 pop_dr(R_EDX, FRn);
1657 JMP_TARGET(end);
1658 :}
1659 FDIV FRm, FRn {:
1660 check_fpuen();
1661 load_spreg( R_ECX, R_FPSCR );
1662 TEST_imm32_r32( FPSCR_PR, R_ECX );
1663 load_fr_bank( R_EDX );
1664 JNE_rel8(13, doubleprec);
1665 push_fr(R_EDX, FRn);
1666 push_fr(R_EDX, FRm);
1667 FDIVP_st(1);
1668 pop_fr(R_EDX, FRn);
1669 JMP_rel8(11, end);
1670 JMP_TARGET(doubleprec);
1671 push_dr(R_EDX, FRn);
1672 push_dr(R_EDX, FRm);
1673 FDIVP_st(1);
1674 pop_dr(R_EDX, FRn);
1675 JMP_TARGET(end);
1676 :}
1677 FMAC FR0, FRm, FRn {:
1678 check_fpuen();
1679 load_spreg( R_ECX, R_FPSCR );
1680 load_spreg( R_EDX, REG_OFFSET(fr_bank));
1681 TEST_imm32_r32( FPSCR_PR, R_ECX );
1682 JNE_rel8(18, doubleprec);
1683 push_fr( R_EDX, 0 );
1684 push_fr( R_EDX, FRm );
1685 FMULP_st(1);
1686 push_fr( R_EDX, FRn );
1687 FADDP_st(1);
1688 pop_fr( R_EDX, FRn );
1689 JMP_rel8(16, end);
1690 JMP_TARGET(doubleprec);
1691 push_dr( R_EDX, 0 );
1692 push_dr( R_EDX, FRm );
1693 FMULP_st(1);
1694 push_dr( R_EDX, FRn );
1695 FADDP_st(1);
1696 pop_dr( R_EDX, FRn );
1697 JMP_TARGET(end);
1698 :}
1700 FMUL FRm, FRn {:
1701 check_fpuen();
1702 load_spreg( R_ECX, R_FPSCR );
1703 TEST_imm32_r32( FPSCR_PR, R_ECX );
1704 load_fr_bank( R_EDX );
1705 JNE_rel8(13, doubleprec);
1706 push_fr(R_EDX, FRm);
1707 push_fr(R_EDX, FRn);
1708 FMULP_st(1);
1709 pop_fr(R_EDX, FRn);
1710 JMP_rel8(11, end);
1711 JMP_TARGET(doubleprec);
1712 push_dr(R_EDX, FRm);
1713 push_dr(R_EDX, FRn);
1714 FMULP_st(1);
1715 pop_dr(R_EDX, FRn);
1716 JMP_TARGET(end);
1717 :}
1718 FNEG FRn {:
1719 check_fpuen();
1720 load_spreg( R_ECX, R_FPSCR );
1721 TEST_imm32_r32( FPSCR_PR, R_ECX );
1722 load_fr_bank( R_EDX );
1723 JNE_rel8(10, doubleprec);
1724 push_fr(R_EDX, FRn);
1725 FCHS_st0();
1726 pop_fr(R_EDX, FRn);
1727 JMP_rel8(8, end);
1728 JMP_TARGET(doubleprec);
1729 push_dr(R_EDX, FRn);
1730 FCHS_st0();
1731 pop_dr(R_EDX, FRn);
1732 JMP_TARGET(end);
1733 :}
1734 FSRRA FRn {:
1735 check_fpuen();
1736 load_spreg( R_ECX, R_FPSCR );
1737 TEST_imm32_r32( FPSCR_PR, R_ECX );
1738 load_fr_bank( R_EDX );
1739 JNE_rel8(12, end); // PR=0 only
1740 FLD1_st0();
1741 push_fr(R_EDX, FRn);
1742 FSQRT_st0();
1743 FDIVP_st(1);
1744 pop_fr(R_EDX, FRn);
1745 JMP_TARGET(end);
1746 :}
1747 FSQRT FRn {:
1748 check_fpuen();
1749 load_spreg( R_ECX, R_FPSCR );
1750 TEST_imm32_r32( FPSCR_PR, R_ECX );
1751 load_fr_bank( R_EDX );
1752 JNE_rel8(10, doubleprec);
1753 push_fr(R_EDX, FRn);
1754 FSQRT_st0();
1755 pop_fr(R_EDX, FRn);
1756 JMP_rel8(8, end);
1757 JMP_TARGET(doubleprec);
1758 push_dr(R_EDX, FRn);
1759 FSQRT_st0();
1760 pop_dr(R_EDX, FRn);
1761 JMP_TARGET(end);
1762 :}
1763 FSUB FRm, FRn {:
1764 check_fpuen();
1765 load_spreg( R_ECX, R_FPSCR );
1766 TEST_imm32_r32( FPSCR_PR, R_ECX );
1767 load_fr_bank( R_EDX );
1768 JNE_rel8(13, doubleprec);
1769 push_fr(R_EDX, FRn);
1770 push_fr(R_EDX, FRm);
1771 FMULP_st(1);
1772 pop_fr(R_EDX, FRn);
1773 JMP_rel8(11, end);
1774 JMP_TARGET(doubleprec);
1775 push_dr(R_EDX, FRn);
1776 push_dr(R_EDX, FRm);
1777 FMULP_st(1);
1778 pop_dr(R_EDX, FRn);
1779 JMP_TARGET(end);
1780 :}
1782 FCMP/EQ FRm, FRn {:
1783 check_fpuen();
1784 load_spreg( R_ECX, R_FPSCR );
1785 TEST_imm32_r32( FPSCR_PR, R_ECX );
1786 load_fr_bank( R_EDX );
1787 JNE_rel8(8, doubleprec);
1788 push_fr(R_EDX, FRm);
1789 push_fr(R_EDX, FRn);
1790 JMP_rel8(6, end);
1791 JMP_TARGET(doubleprec);
1792 push_dr(R_EDX, FRm);
1793 push_dr(R_EDX, FRn);
1794 JMP_TARGET(end);
1795 FCOMIP_st(1);
1796 SETE_t();
1797 FPOP_st();
1798 :}
1799 FCMP/GT FRm, FRn {:
1800 check_fpuen();
1801 load_spreg( R_ECX, R_FPSCR );
1802 TEST_imm32_r32( FPSCR_PR, R_ECX );
1803 load_fr_bank( R_EDX );
1804 JNE_rel8(8, doubleprec);
1805 push_fr(R_EDX, FRm);
1806 push_fr(R_EDX, FRn);
1807 JMP_rel8(6, end);
1808 JMP_TARGET(doubleprec);
1809 push_dr(R_EDX, FRm);
1810 push_dr(R_EDX, FRn);
1811 JMP_TARGET(end);
1812 FCOMIP_st(1);
1813 SETA_t();
1814 FPOP_st();
1815 :}
1817 FSCA FPUL, FRn {:
1818 check_fpuen();
1819 :}
1820 FIPR FVm, FVn {:
1821 check_fpuen();
1822 :}
1823 FTRV XMTRX, FVn {:
1824 check_fpuen();
1825 :}
1827 FRCHG {:
1828 check_fpuen();
1829 load_spreg( R_ECX, R_FPSCR );
1830 XOR_imm32_r32( FPSCR_FR, R_ECX );
1831 store_spreg( R_ECX, R_FPSCR );
1833 :}
1834 FSCHG {:
1835 check_fpuen();
1836 load_spreg( R_ECX, R_FPSCR );
1837 XOR_imm32_r32( FPSCR_SZ, R_ECX );
1838 store_spreg( R_ECX, R_FPSCR );
1839 :}
1841 /* Processor control instructions */
1842 LDC Rm, SR {:
1843 load_reg( R_EAX, Rm );
1844 call_func1( sh4_write_sr, R_EAX );
1845 sh4_x86.priv_checked = FALSE;
1846 sh4_x86.fpuen_checked = FALSE;
1847 :}
1848 LDC Rm, GBR {:
1849 load_reg( R_EAX, Rm );
1850 store_spreg( R_EAX, R_GBR );
1851 :}
1852 LDC Rm, VBR {:
1853 load_reg( R_EAX, Rm );
1854 store_spreg( R_EAX, R_VBR );
1855 :}
1856 LDC Rm, SSR {:
1857 load_reg( R_EAX, Rm );
1858 store_spreg( R_EAX, R_SSR );
1859 :}
1860 LDC Rm, SGR {:
1861 load_reg( R_EAX, Rm );
1862 store_spreg( R_EAX, R_SGR );
1863 :}
1864 LDC Rm, SPC {:
1865 load_reg( R_EAX, Rm );
1866 store_spreg( R_EAX, R_SPC );
1867 :}
1868 LDC Rm, DBR {:
1869 load_reg( R_EAX, Rm );
1870 store_spreg( R_EAX, R_DBR );
1871 :}
1872 LDC Rm, Rn_BANK {:
1873 load_reg( R_EAX, Rm );
1874 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1875 :}
1876 LDC.L @Rm+, GBR {:
1877 load_reg( R_EAX, Rm );
1878 MOV_r32_r32( R_EAX, R_ECX );
1879 ADD_imm8s_r32( 4, R_EAX );
1880 store_reg( R_EAX, Rm );
1881 MEM_READ_LONG( R_ECX, R_EAX );
1882 store_spreg( R_EAX, R_GBR );
1883 :}
1884 LDC.L @Rm+, SR {:
1885 load_reg( R_EAX, Rm );
1886 MOV_r32_r32( R_EAX, R_ECX );
1887 ADD_imm8s_r32( 4, R_EAX );
1888 store_reg( R_EAX, Rm );
1889 MEM_READ_LONG( R_ECX, R_EAX );
1890 call_func1( sh4_write_sr, R_EAX );
1891 sh4_x86.priv_checked = FALSE;
1892 sh4_x86.fpuen_checked = FALSE;
1893 :}
1894 LDC.L @Rm+, VBR {:
1895 load_reg( R_EAX, Rm );
1896 MOV_r32_r32( R_EAX, R_ECX );
1897 ADD_imm8s_r32( 4, R_EAX );
1898 store_reg( R_EAX, Rm );
1899 MEM_READ_LONG( R_ECX, R_EAX );
1900 store_spreg( R_EAX, R_VBR );
1901 :}
1902 LDC.L @Rm+, SSR {:
1903 load_reg( R_EAX, Rm );
1904 MOV_r32_r32( R_EAX, R_ECX );
1905 ADD_imm8s_r32( 4, R_EAX );
1906 store_reg( R_EAX, Rm );
1907 MEM_READ_LONG( R_ECX, R_EAX );
1908 store_spreg( R_EAX, R_SSR );
1909 :}
1910 LDC.L @Rm+, SGR {:
1911 load_reg( R_EAX, Rm );
1912 MOV_r32_r32( R_EAX, R_ECX );
1913 ADD_imm8s_r32( 4, R_EAX );
1914 store_reg( R_EAX, Rm );
1915 MEM_READ_LONG( R_ECX, R_EAX );
1916 store_spreg( R_EAX, R_SGR );
1917 :}
1918 LDC.L @Rm+, SPC {:
1919 load_reg( R_EAX, Rm );
1920 MOV_r32_r32( R_EAX, R_ECX );
1921 ADD_imm8s_r32( 4, R_EAX );
1922 store_reg( R_EAX, Rm );
1923 MEM_READ_LONG( R_ECX, R_EAX );
1924 store_spreg( R_EAX, R_SPC );
1925 :}
1926 LDC.L @Rm+, DBR {:
1927 load_reg( R_EAX, Rm );
1928 MOV_r32_r32( R_EAX, R_ECX );
1929 ADD_imm8s_r32( 4, R_EAX );
1930 store_reg( R_EAX, Rm );
1931 MEM_READ_LONG( R_ECX, R_EAX );
1932 store_spreg( R_EAX, R_DBR );
1933 :}
1934 LDC.L @Rm+, Rn_BANK {:
1935 load_reg( R_EAX, Rm );
1936 MOV_r32_r32( R_EAX, R_ECX );
1937 ADD_imm8s_r32( 4, R_EAX );
1938 store_reg( R_EAX, Rm );
1939 MEM_READ_LONG( R_ECX, R_EAX );
1940 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1941 :}
1942 LDS Rm, FPSCR {:
1943 load_reg( R_EAX, Rm );
1944 store_spreg( R_EAX, R_FPSCR );
1945 :}
1946 LDS.L @Rm+, FPSCR {:
1947 load_reg( R_EAX, Rm );
1948 MOV_r32_r32( R_EAX, R_ECX );
1949 ADD_imm8s_r32( 4, R_EAX );
1950 store_reg( R_EAX, Rm );
1951 MEM_READ_LONG( R_ECX, R_EAX );
1952 store_spreg( R_EAX, R_FPSCR );
1953 :}
1954 LDS Rm, FPUL {:
1955 load_reg( R_EAX, Rm );
1956 store_spreg( R_EAX, R_FPUL );
1957 :}
1958 LDS.L @Rm+, FPUL {:
1959 load_reg( R_EAX, Rm );
1960 MOV_r32_r32( R_EAX, R_ECX );
1961 ADD_imm8s_r32( 4, R_EAX );
1962 store_reg( R_EAX, Rm );
1963 MEM_READ_LONG( R_ECX, R_EAX );
1964 store_spreg( R_EAX, R_FPUL );
1965 :}
1966 LDS Rm, MACH {:
1967 load_reg( R_EAX, Rm );
1968 store_spreg( R_EAX, R_MACH );
1969 :}
1970 LDS.L @Rm+, MACH {:
1971 load_reg( R_EAX, Rm );
1972 MOV_r32_r32( R_EAX, R_ECX );
1973 ADD_imm8s_r32( 4, R_EAX );
1974 store_reg( R_EAX, Rm );
1975 MEM_READ_LONG( R_ECX, R_EAX );
1976 store_spreg( R_EAX, R_MACH );
1977 :}
1978 LDS Rm, MACL {:
1979 load_reg( R_EAX, Rm );
1980 store_spreg( R_EAX, R_MACL );
1981 :}
1982 LDS.L @Rm+, MACL {:
1983 load_reg( R_EAX, Rm );
1984 MOV_r32_r32( R_EAX, R_ECX );
1985 ADD_imm8s_r32( 4, R_EAX );
1986 store_reg( R_EAX, Rm );
1987 MEM_READ_LONG( R_ECX, R_EAX );
1988 store_spreg( R_EAX, R_MACL );
1989 :}
1990 LDS Rm, PR {:
1991 load_reg( R_EAX, Rm );
1992 store_spreg( R_EAX, R_PR );
1993 :}
1994 LDS.L @Rm+, PR {:
1995 load_reg( R_EAX, Rm );
1996 MOV_r32_r32( R_EAX, R_ECX );
1997 ADD_imm8s_r32( 4, R_EAX );
1998 store_reg( R_EAX, Rm );
1999 MEM_READ_LONG( R_ECX, R_EAX );
2000 store_spreg( R_EAX, R_PR );
2001 :}
2002 LDTLB {: :}
2003 OCBI @Rn {: :}
2004 OCBP @Rn {: :}
2005 OCBWB @Rn {: :}
2006 PREF @Rn {:
2007 load_reg( R_EAX, Rn );
2008 PUSH_r32( R_EAX );
2009 AND_imm32_r32( 0xFC000000, R_EAX );
2010 CMP_imm32_r32( 0xE0000000, R_EAX );
2011 JNE_rel8(7, end);
2012 call_func0( sh4_flush_store_queue );
2013 JMP_TARGET(end);
2014 ADD_imm8s_r32( 4, R_ESP );
2015 :}
2016 SLEEP {: /* TODO */ :}
2017 STC SR, Rn {:
2018 call_func0(sh4_read_sr);
2019 store_reg( R_EAX, Rn );
2020 :}
2021 STC GBR, Rn {:
2022 load_spreg( R_EAX, R_GBR );
2023 store_reg( R_EAX, Rn );
2024 :}
2025 STC VBR, Rn {:
2026 load_spreg( R_EAX, R_VBR );
2027 store_reg( R_EAX, Rn );
2028 :}
2029 STC SSR, Rn {:
2030 load_spreg( R_EAX, R_SSR );
2031 store_reg( R_EAX, Rn );
2032 :}
2033 STC SPC, Rn {:
2034 load_spreg( R_EAX, R_SPC );
2035 store_reg( R_EAX, Rn );
2036 :}
2037 STC SGR, Rn {:
2038 load_spreg( R_EAX, R_SGR );
2039 store_reg( R_EAX, Rn );
2040 :}
2041 STC DBR, Rn {:
2042 load_spreg( R_EAX, R_DBR );
2043 store_reg( R_EAX, Rn );
2044 :}
2045 STC Rm_BANK, Rn {:
2046 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2047 store_reg( R_EAX, Rn );
2048 :}
2049 STC.L SR, @-Rn {:
2050 load_reg( R_ECX, Rn );
2051 ADD_imm8s_r32( -4, R_ECX );
2052 store_reg( R_ECX, Rn );
2053 call_func0( sh4_read_sr );
2054 MEM_WRITE_LONG( R_ECX, R_EAX );
2055 :}
2056 STC.L VBR, @-Rn {:
2057 load_reg( R_ECX, Rn );
2058 ADD_imm8s_r32( -4, R_ECX );
2059 store_reg( R_ECX, Rn );
2060 load_spreg( R_EAX, R_VBR );
2061 MEM_WRITE_LONG( R_ECX, R_EAX );
2062 :}
2063 STC.L SSR, @-Rn {:
2064 load_reg( R_ECX, Rn );
2065 ADD_imm8s_r32( -4, R_ECX );
2066 store_reg( R_ECX, Rn );
2067 load_spreg( R_EAX, R_SSR );
2068 MEM_WRITE_LONG( R_ECX, R_EAX );
2069 :}
2070 STC.L SPC, @-Rn {:
2071 load_reg( R_ECX, Rn );
2072 ADD_imm8s_r32( -4, R_ECX );
2073 store_reg( R_ECX, Rn );
2074 load_spreg( R_EAX, R_SPC );
2075 MEM_WRITE_LONG( R_ECX, R_EAX );
2076 :}
2077 STC.L SGR, @-Rn {:
2078 load_reg( R_ECX, Rn );
2079 ADD_imm8s_r32( -4, R_ECX );
2080 store_reg( R_ECX, Rn );
2081 load_spreg( R_EAX, R_SGR );
2082 MEM_WRITE_LONG( R_ECX, R_EAX );
2083 :}
2084 STC.L DBR, @-Rn {:
2085 load_reg( R_ECX, Rn );
2086 ADD_imm8s_r32( -4, R_ECX );
2087 store_reg( R_ECX, Rn );
2088 load_spreg( R_EAX, R_DBR );
2089 MEM_WRITE_LONG( R_ECX, R_EAX );
2090 :}
2091 STC.L Rm_BANK, @-Rn {:
2092 load_reg( R_ECX, Rn );
2093 ADD_imm8s_r32( -4, R_ECX );
2094 store_reg( R_ECX, Rn );
2095 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2096 MEM_WRITE_LONG( R_ECX, R_EAX );
2097 :}
2098 STC.L GBR, @-Rn {:
2099 load_reg( R_ECX, Rn );
2100 ADD_imm8s_r32( -4, R_ECX );
2101 store_reg( R_ECX, Rn );
2102 load_spreg( R_EAX, R_GBR );
2103 MEM_WRITE_LONG( R_ECX, R_EAX );
2104 :}
2105 STS FPSCR, Rn {:
2106 load_spreg( R_EAX, R_FPSCR );
2107 store_reg( R_EAX, Rn );
2108 :}
2109 STS.L FPSCR, @-Rn {:
2110 load_reg( R_ECX, Rn );
2111 ADD_imm8s_r32( -4, R_ECX );
2112 store_reg( R_ECX, Rn );
2113 load_spreg( R_EAX, R_FPSCR );
2114 MEM_WRITE_LONG( R_ECX, R_EAX );
2115 :}
2116 STS FPUL, Rn {:
2117 load_spreg( R_EAX, R_FPUL );
2118 store_reg( R_EAX, Rn );
2119 :}
2120 STS.L FPUL, @-Rn {:
2121 load_reg( R_ECX, Rn );
2122 ADD_imm8s_r32( -4, R_ECX );
2123 store_reg( R_ECX, Rn );
2124 load_spreg( R_EAX, R_FPUL );
2125 MEM_WRITE_LONG( R_ECX, R_EAX );
2126 :}
2127 STS MACH, Rn {:
2128 load_spreg( R_EAX, R_MACH );
2129 store_reg( R_EAX, Rn );
2130 :}
2131 STS.L MACH, @-Rn {:
2132 load_reg( R_ECX, Rn );
2133 ADD_imm8s_r32( -4, R_ECX );
2134 store_reg( R_ECX, Rn );
2135 load_spreg( R_EAX, R_MACH );
2136 MEM_WRITE_LONG( R_ECX, R_EAX );
2137 :}
2138 STS MACL, Rn {:
2139 load_spreg( R_EAX, R_MACL );
2140 store_reg( R_EAX, Rn );
2141 :}
2142 STS.L MACL, @-Rn {:
2143 load_reg( R_ECX, Rn );
2144 ADD_imm8s_r32( -4, R_ECX );
2145 store_reg( R_ECX, Rn );
2146 load_spreg( R_EAX, R_MACL );
2147 MEM_WRITE_LONG( R_ECX, R_EAX );
2148 :}
2149 STS PR, Rn {:
2150 load_spreg( R_EAX, R_PR );
2151 store_reg( R_EAX, Rn );
2152 :}
2153 STS.L PR, @-Rn {:
2154 load_reg( R_ECX, Rn );
2155 ADD_imm8s_r32( -4, R_ECX );
2156 store_reg( R_ECX, Rn );
2157 load_spreg( R_EAX, R_PR );
2158 MEM_WRITE_LONG( R_ECX, R_EAX );
2159 :}
2161 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}
2162 %%
2163 INC_r32(R_ESI);
2164 if( sh4_x86.in_delay_slot ) {
2165 sh4_x86.in_delay_slot = FALSE;
2166 return 1;
2167 }
2168 return 0;
2169 }
.