filename | src/sh4/sh4x86.in |
changeset | 380:2e8166bf6832 |
prev | 377:fa18743f6905 |
next | 381:aade6c9aca4d |
author | nkeynes |
date | Wed Sep 12 11:31:16 2007 +0000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Fix load_spreg/store_spreg Fix PREF Add jump target debug checking |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4x86.in,v 1.7 2007-09-12 11:31:16 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); 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 XOR_r32_r32( R_EAX, R_EAX );
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 POP_r32(R_EBP);
419 RET();
421 sh4_x86_do_backpatch( end_ptr );
422 }
424 /**
425 * Translate a single instruction. Delayed branches are handled specially
426 * by translating both branch and delayed instruction as a single unit (as
427 *
428 *
429 * @return true if the instruction marks the end of a basic block
430 * (eg a branch or
431 */
432 uint32_t sh4_x86_translate_instruction( uint32_t pc )
433 {
434 uint16_t ir = sh4_read_word( pc );
436 %%
437 /* ALU operations */
438 ADD Rm, Rn {:
439 load_reg( R_EAX, Rm );
440 load_reg( R_ECX, Rn );
441 ADD_r32_r32( R_EAX, R_ECX );
442 store_reg( R_ECX, Rn );
443 :}
444 ADD #imm, Rn {:
445 load_reg( R_EAX, Rn );
446 ADD_imm8s_r32( imm, R_EAX );
447 store_reg( R_EAX, Rn );
448 :}
449 ADDC Rm, Rn {:
450 load_reg( R_EAX, Rm );
451 load_reg( R_ECX, Rn );
452 LDC_t();
453 ADC_r32_r32( R_EAX, R_ECX );
454 store_reg( R_ECX, Rn );
455 SETC_t();
456 :}
457 ADDV Rm, Rn {:
458 load_reg( R_EAX, Rm );
459 load_reg( R_ECX, Rn );
460 ADD_r32_r32( R_EAX, R_ECX );
461 store_reg( R_ECX, Rn );
462 SETO_t();
463 :}
464 AND Rm, Rn {:
465 load_reg( R_EAX, Rm );
466 load_reg( R_ECX, Rn );
467 AND_r32_r32( R_EAX, R_ECX );
468 store_reg( R_ECX, Rn );
469 :}
470 AND #imm, R0 {:
471 load_reg( R_EAX, 0 );
472 AND_imm32_r32(imm, R_EAX);
473 store_reg( R_EAX, 0 );
474 :}
475 AND.B #imm, @(R0, GBR) {:
476 load_reg( R_EAX, 0 );
477 load_spreg( R_ECX, R_GBR );
478 ADD_r32_r32( R_EAX, R_ECX );
479 MEM_READ_BYTE( R_ECX, R_EAX );
480 AND_imm32_r32(imm, R_ECX );
481 MEM_WRITE_BYTE( R_ECX, R_EAX );
482 :}
483 CMP/EQ Rm, Rn {:
484 load_reg( R_EAX, Rm );
485 load_reg( R_ECX, Rn );
486 CMP_r32_r32( R_EAX, R_ECX );
487 SETE_t();
488 :}
489 CMP/EQ #imm, R0 {:
490 load_reg( R_EAX, 0 );
491 CMP_imm8s_r32(imm, R_EAX);
492 SETE_t();
493 :}
494 CMP/GE Rm, Rn {:
495 load_reg( R_EAX, Rm );
496 load_reg( R_ECX, Rn );
497 CMP_r32_r32( R_EAX, R_ECX );
498 SETGE_t();
499 :}
500 CMP/GT Rm, Rn {:
501 load_reg( R_EAX, Rm );
502 load_reg( R_ECX, Rn );
503 CMP_r32_r32( R_EAX, R_ECX );
504 SETG_t();
505 :}
506 CMP/HI Rm, Rn {:
507 load_reg( R_EAX, Rm );
508 load_reg( R_ECX, Rn );
509 CMP_r32_r32( R_EAX, R_ECX );
510 SETA_t();
511 :}
512 CMP/HS Rm, Rn {:
513 load_reg( R_EAX, Rm );
514 load_reg( R_ECX, Rn );
515 CMP_r32_r32( R_EAX, R_ECX );
516 SETAE_t();
517 :}
518 CMP/PL Rn {:
519 load_reg( R_EAX, Rn );
520 CMP_imm8s_r32( 0, R_EAX );
521 SETG_t();
522 :}
523 CMP/PZ Rn {:
524 load_reg( R_EAX, Rn );
525 CMP_imm8s_r32( 0, R_EAX );
526 SETGE_t();
527 :}
528 CMP/STR Rm, Rn {:
529 load_reg( R_EAX, Rm );
530 load_reg( R_ECX, Rn );
531 XOR_r32_r32( R_ECX, R_EAX );
532 TEST_r8_r8( R_AL, R_AL );
533 JE_rel8(13, target1);
534 TEST_r8_r8( R_AH, R_AH ); // 2
535 JE_rel8(9, target2);
536 SHR_imm8_r32( 16, R_EAX ); // 3
537 TEST_r8_r8( R_AL, R_AL ); // 2
538 JE_rel8(2, target3);
539 TEST_r8_r8( R_AH, R_AH ); // 2
540 JMP_TARGET(target1);
541 JMP_TARGET(target2);
542 JMP_TARGET(target3);
543 SETE_t();
544 :}
545 DIV0S Rm, Rn {:
546 load_reg( R_EAX, Rm );
547 load_reg( R_ECX, Rm );
548 SHR_imm8_r32( 31, R_EAX );
549 SHR_imm8_r32( 31, R_ECX );
550 store_spreg( R_EAX, R_M );
551 store_spreg( R_ECX, R_Q );
552 CMP_r32_r32( R_EAX, R_ECX );
553 SETE_t();
554 :}
555 DIV0U {:
556 XOR_r32_r32( R_EAX, R_EAX );
557 store_spreg( R_EAX, R_Q );
558 store_spreg( R_EAX, R_M );
559 store_spreg( R_EAX, R_T );
560 :}
561 DIV1 Rm, Rn {:
562 load_reg( R_ECX, Rn );
563 LDC_t();
564 RCL1_r32( R_ECX ); // OP2
565 SETC_r32( R_EDX ); // Q
566 load_spreg( R_EAX, R_Q );
567 CMP_sh4r_r32( R_M, R_EAX );
568 JE_rel8(8,mqequal);
569 ADD_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
570 JMP_rel8(3, mqnotequal);
571 JMP_TARGET(mqequal);
572 SUB_sh4r_r32( REG_OFFSET(r[Rm]), R_ECX );
573 JMP_TARGET(mqnotequal);
574 // TODO
575 :}
576 DMULS.L Rm, Rn {:
577 load_reg( R_EAX, Rm );
578 load_reg( R_ECX, Rn );
579 IMUL_r32(R_ECX);
580 store_spreg( R_EDX, R_MACH );
581 store_spreg( R_EAX, R_MACL );
582 :}
583 DMULU.L Rm, Rn {:
584 load_reg( R_EAX, Rm );
585 load_reg( R_ECX, Rn );
586 MUL_r32(R_ECX);
587 store_spreg( R_EDX, R_MACH );
588 store_spreg( R_EAX, R_MACL );
589 :}
590 DT Rn {:
591 load_reg( R_EAX, Rn );
592 ADD_imm8s_r32( -1, Rn );
593 store_reg( R_EAX, Rn );
594 SETE_t();
595 :}
596 EXTS.B Rm, Rn {:
597 load_reg( R_EAX, Rm );
598 MOVSX_r8_r32( R_EAX, R_EAX );
599 store_reg( R_EAX, Rn );
600 :}
601 EXTS.W Rm, Rn {:
602 load_reg( R_EAX, Rm );
603 MOVSX_r16_r32( R_EAX, R_EAX );
604 store_reg( R_EAX, Rn );
605 :}
606 EXTU.B Rm, Rn {:
607 load_reg( R_EAX, Rm );
608 MOVZX_r8_r32( R_EAX, R_EAX );
609 store_reg( R_EAX, Rn );
610 :}
611 EXTU.W Rm, Rn {:
612 load_reg( R_EAX, Rm );
613 MOVZX_r16_r32( R_EAX, R_EAX );
614 store_reg( R_EAX, Rn );
615 :}
616 MAC.L @Rm+, @Rn+ {: :}
617 MAC.W @Rm+, @Rn+ {: :}
618 MOVT Rn {:
619 load_spreg( R_EAX, R_T );
620 store_reg( R_EAX, Rn );
621 :}
622 MUL.L Rm, Rn {:
623 load_reg( R_EAX, Rm );
624 load_reg( R_ECX, Rn );
625 MUL_r32( R_ECX );
626 store_spreg( R_EAX, R_MACL );
627 :}
628 MULS.W Rm, Rn {:
629 load_reg16s( R_EAX, Rm );
630 load_reg16s( R_ECX, Rn );
631 MUL_r32( R_ECX );
632 store_spreg( R_EAX, R_MACL );
633 :}
634 MULU.W Rm, Rn {:
635 load_reg16u( R_EAX, Rm );
636 load_reg16u( R_ECX, Rn );
637 MUL_r32( R_ECX );
638 store_spreg( R_EAX, R_MACL );
639 :}
640 NEG Rm, Rn {:
641 load_reg( R_EAX, Rm );
642 NEG_r32( R_EAX );
643 store_reg( R_EAX, Rn );
644 :}
645 NEGC Rm, Rn {:
646 load_reg( R_EAX, Rm );
647 XOR_r32_r32( R_ECX, R_ECX );
648 LDC_t();
649 SBB_r32_r32( R_EAX, R_ECX );
650 store_reg( R_ECX, Rn );
651 SETC_t();
652 :}
653 NOT Rm, Rn {:
654 load_reg( R_EAX, Rm );
655 NOT_r32( R_EAX );
656 store_reg( R_EAX, Rn );
657 :}
658 OR Rm, Rn {:
659 load_reg( R_EAX, Rm );
660 load_reg( R_ECX, Rn );
661 OR_r32_r32( R_EAX, R_ECX );
662 store_reg( R_ECX, Rn );
663 :}
664 OR #imm, R0 {:
665 load_reg( R_EAX, 0 );
666 OR_imm32_r32(imm, R_EAX);
667 store_reg( R_EAX, 0 );
668 :}
669 OR.B #imm, @(R0, GBR) {:
670 load_reg( R_EAX, 0 );
671 load_spreg( R_ECX, R_GBR );
672 ADD_r32_r32( R_EAX, R_ECX );
673 MEM_READ_BYTE( R_ECX, R_EAX );
674 OR_imm32_r32(imm, R_ECX );
675 MEM_WRITE_BYTE( R_ECX, R_EAX );
676 :}
677 ROTCL Rn {:
678 load_reg( R_EAX, Rn );
679 LDC_t();
680 RCL1_r32( R_EAX );
681 store_reg( R_EAX, Rn );
682 SETC_t();
683 :}
684 ROTCR Rn {:
685 load_reg( R_EAX, Rn );
686 LDC_t();
687 RCR1_r32( R_EAX );
688 store_reg( R_EAX, Rn );
689 SETC_t();
690 :}
691 ROTL Rn {:
692 load_reg( R_EAX, Rn );
693 ROL1_r32( R_EAX );
694 store_reg( R_EAX, Rn );
695 SETC_t();
696 :}
697 ROTR Rn {:
698 load_reg( R_EAX, Rn );
699 ROR1_r32( R_EAX );
700 store_reg( R_EAX, Rn );
701 SETC_t();
702 :}
703 SHAD Rm, Rn {:
704 /* Annoyingly enough, not directly convertible */
705 load_reg( R_EAX, Rn );
706 load_reg( R_ECX, Rm );
707 CMP_imm32_r32( 0, R_ECX );
708 JAE_rel8(9, doshl);
710 NEG_r32( R_ECX ); // 2
711 AND_imm8_r8( 0x1F, R_CL ); // 3
712 SAR_r32_CL( R_EAX ); // 2
713 JMP_rel8(5, end); // 2
714 JMP_TARGET(doshl);
715 AND_imm8_r8( 0x1F, R_CL ); // 3
716 SHL_r32_CL( R_EAX ); // 2
717 JMP_TARGET(end);
718 store_reg( R_EAX, Rn );
719 :}
720 SHLD Rm, Rn {:
721 load_reg( R_EAX, Rn );
722 load_reg( R_ECX, Rm );
724 MOV_r32_r32( R_EAX, R_EDX );
725 SHL_r32_CL( R_EAX );
726 NEG_r32( R_ECX );
727 SHR_r32_CL( R_EDX );
728 CMP_imm8s_r32( 0, R_ECX );
729 CMOVAE_r32_r32( R_EDX, R_EAX );
730 store_reg( R_EAX, Rn );
731 :}
732 SHAL Rn {:
733 load_reg( R_EAX, Rn );
734 SHL1_r32( R_EAX );
735 store_reg( R_EAX, Rn );
736 :}
737 SHAR Rn {:
738 load_reg( R_EAX, Rn );
739 SAR1_r32( R_EAX );
740 store_reg( R_EAX, Rn );
741 :}
742 SHLL Rn {:
743 load_reg( R_EAX, Rn );
744 SHL1_r32( R_EAX );
745 store_reg( R_EAX, Rn );
746 :}
747 SHLL2 Rn {:
748 load_reg( R_EAX, Rn );
749 SHL_imm8_r32( 2, R_EAX );
750 store_reg( R_EAX, Rn );
751 :}
752 SHLL8 Rn {:
753 load_reg( R_EAX, Rn );
754 SHL_imm8_r32( 8, R_EAX );
755 store_reg( R_EAX, Rn );
756 :}
757 SHLL16 Rn {:
758 load_reg( R_EAX, Rn );
759 SHL_imm8_r32( 16, R_EAX );
760 store_reg( R_EAX, Rn );
761 :}
762 SHLR Rn {:
763 load_reg( R_EAX, Rn );
764 SHR1_r32( R_EAX );
765 store_reg( R_EAX, Rn );
766 :}
767 SHLR2 Rn {:
768 load_reg( R_EAX, Rn );
769 SHR_imm8_r32( 2, R_EAX );
770 store_reg( R_EAX, Rn );
771 :}
772 SHLR8 Rn {:
773 load_reg( R_EAX, Rn );
774 SHR_imm8_r32( 8, R_EAX );
775 store_reg( R_EAX, Rn );
776 :}
777 SHLR16 Rn {:
778 load_reg( R_EAX, Rn );
779 SHR_imm8_r32( 16, R_EAX );
780 store_reg( R_EAX, Rn );
781 :}
782 SUB Rm, Rn {:
783 load_reg( R_EAX, Rm );
784 load_reg( R_ECX, Rn );
785 SUB_r32_r32( R_EAX, R_ECX );
786 store_reg( R_ECX, Rn );
787 :}
788 SUBC Rm, Rn {:
789 load_reg( R_EAX, Rm );
790 load_reg( R_ECX, Rn );
791 LDC_t();
792 SBB_r32_r32( R_EAX, R_ECX );
793 store_reg( R_ECX, Rn );
794 :}
795 SUBV Rm, Rn {:
796 load_reg( R_EAX, Rm );
797 load_reg( R_ECX, Rn );
798 SUB_r32_r32( R_EAX, R_ECX );
799 store_reg( R_ECX, Rn );
800 SETO_t();
801 :}
802 SWAP.B Rm, Rn {:
803 load_reg( R_EAX, Rm );
804 XCHG_r8_r8( R_AL, R_AH );
805 store_reg( R_EAX, Rn );
806 :}
807 SWAP.W Rm, Rn {:
808 load_reg( R_EAX, Rm );
809 MOV_r32_r32( R_EAX, R_ECX );
810 SHL_imm8_r32( 16, R_ECX );
811 SHR_imm8_r32( 16, R_EAX );
812 OR_r32_r32( R_EAX, R_ECX );
813 store_reg( R_ECX, Rn );
814 :}
815 TAS.B @Rn {:
816 load_reg( R_ECX, Rn );
817 MEM_READ_BYTE( R_ECX, R_EAX );
818 TEST_r8_r8( R_AL, R_AL );
819 SETE_t();
820 OR_imm8_r8( 0x80, R_AL );
821 MEM_WRITE_BYTE( R_ECX, R_EAX );
822 :}
823 TST Rm, Rn {:
824 load_reg( R_EAX, Rm );
825 load_reg( R_ECX, Rn );
826 TEST_r32_r32( R_EAX, R_ECX );
827 SETE_t();
828 :}
829 TST #imm, R0 {:
830 load_reg( R_EAX, 0 );
831 TEST_imm32_r32( imm, R_EAX );
832 SETE_t();
833 :}
834 TST.B #imm, @(R0, GBR) {:
835 load_reg( R_EAX, 0);
836 load_reg( R_ECX, R_GBR);
837 ADD_r32_r32( R_EAX, R_ECX );
838 MEM_READ_BYTE( R_ECX, R_EAX );
839 TEST_imm8_r8( imm, R_EAX );
840 SETE_t();
841 :}
842 XOR Rm, Rn {:
843 load_reg( R_EAX, Rm );
844 load_reg( R_ECX, Rn );
845 XOR_r32_r32( R_EAX, R_ECX );
846 store_reg( R_ECX, Rn );
847 :}
848 XOR #imm, R0 {:
849 load_reg( R_EAX, 0 );
850 XOR_imm32_r32( imm, R_EAX );
851 store_reg( R_EAX, 0 );
852 :}
853 XOR.B #imm, @(R0, GBR) {:
854 load_reg( R_EAX, 0 );
855 load_spreg( R_ECX, R_GBR );
856 ADD_r32_r32( R_EAX, R_ECX );
857 MEM_READ_BYTE( R_ECX, R_EAX );
858 XOR_imm32_r32( imm, R_EAX );
859 MEM_WRITE_BYTE( R_ECX, R_EAX );
860 :}
861 XTRCT Rm, Rn {:
862 load_reg( R_EAX, Rm );
863 MOV_r32_r32( R_EAX, R_ECX );
864 SHR_imm8_r32( 16, R_EAX );
865 SHL_imm8_r32( 16, R_ECX );
866 OR_r32_r32( R_EAX, R_ECX );
867 store_reg( R_ECX, Rn );
868 :}
870 /* Data move instructions */
871 MOV Rm, Rn {:
872 load_reg( R_EAX, Rm );
873 store_reg( R_EAX, Rn );
874 :}
875 MOV #imm, Rn {:
876 load_imm32( R_EAX, imm );
877 store_reg( R_EAX, Rn );
878 :}
879 MOV.B Rm, @Rn {:
880 load_reg( R_EAX, Rm );
881 load_reg( R_ECX, Rn );
882 MEM_WRITE_BYTE( R_ECX, R_EAX );
883 :}
884 MOV.B Rm, @-Rn {:
885 load_reg( R_EAX, Rm );
886 load_reg( R_ECX, Rn );
887 ADD_imm8s_r32( -1, Rn );
888 store_reg( R_ECX, Rn );
889 MEM_WRITE_BYTE( R_ECX, R_EAX );
890 :}
891 MOV.B Rm, @(R0, Rn) {:
892 load_reg( R_EAX, 0 );
893 load_reg( R_ECX, Rn );
894 ADD_r32_r32( R_EAX, R_ECX );
895 load_reg( R_EAX, Rm );
896 MEM_WRITE_BYTE( R_ECX, R_EAX );
897 :}
898 MOV.B R0, @(disp, GBR) {:
899 load_reg( R_EAX, 0 );
900 load_spreg( R_ECX, R_GBR );
901 ADD_imm32_r32( disp, R_ECX );
902 MEM_WRITE_BYTE( R_ECX, R_EAX );
903 :}
904 MOV.B R0, @(disp, Rn) {:
905 load_reg( R_EAX, 0 );
906 load_reg( R_ECX, Rn );
907 ADD_imm32_r32( disp, R_ECX );
908 MEM_WRITE_BYTE( R_ECX, R_EAX );
909 :}
910 MOV.B @Rm, Rn {:
911 load_reg( R_ECX, Rm );
912 MEM_READ_BYTE( R_ECX, R_EAX );
913 store_reg( R_ECX, Rn );
914 :}
915 MOV.B @Rm+, Rn {:
916 load_reg( R_ECX, Rm );
917 MOV_r32_r32( R_ECX, R_EAX );
918 ADD_imm8s_r32( 1, R_EAX );
919 store_reg( R_EAX, Rm );
920 MEM_READ_BYTE( R_ECX, R_EAX );
921 store_reg( R_EAX, Rn );
922 :}
923 MOV.B @(R0, Rm), Rn {:
924 load_reg( R_EAX, 0 );
925 load_reg( R_ECX, Rm );
926 ADD_r32_r32( R_EAX, R_ECX );
927 MEM_READ_BYTE( R_ECX, R_EAX );
928 store_reg( R_EAX, Rn );
929 :}
930 MOV.B @(disp, GBR), R0 {:
931 load_spreg( R_ECX, R_GBR );
932 ADD_imm32_r32( disp, R_ECX );
933 MEM_READ_BYTE( R_ECX, R_EAX );
934 store_reg( R_EAX, 0 );
935 :}
936 MOV.B @(disp, Rm), R0 {:
937 load_reg( R_ECX, Rm );
938 ADD_imm32_r32( disp, R_ECX );
939 MEM_READ_BYTE( R_ECX, R_EAX );
940 store_reg( R_EAX, 0 );
941 :}
942 MOV.L Rm, @Rn {:
943 load_reg( R_EAX, Rm );
944 load_reg( R_ECX, Rn );
945 check_walign32(R_ECX);
946 MEM_WRITE_LONG( R_ECX, R_EAX );
947 :}
948 MOV.L Rm, @-Rn {:
949 load_reg( R_EAX, Rm );
950 load_reg( R_ECX, Rn );
951 check_walign32( R_ECX );
952 ADD_imm8s_r32( -4, R_ECX );
953 store_reg( R_ECX, Rn );
954 MEM_WRITE_LONG( R_ECX, R_EAX );
955 :}
956 MOV.L Rm, @(R0, Rn) {:
957 load_reg( R_EAX, 0 );
958 load_reg( R_ECX, Rn );
959 ADD_r32_r32( R_EAX, R_ECX );
960 check_walign32( R_ECX );
961 load_reg( R_EAX, Rm );
962 MEM_WRITE_LONG( R_ECX, R_EAX );
963 :}
964 MOV.L R0, @(disp, GBR) {:
965 load_spreg( R_ECX, R_GBR );
966 load_reg( R_EAX, 0 );
967 ADD_imm32_r32( disp, R_ECX );
968 check_walign32( R_ECX );
969 MEM_WRITE_LONG( R_ECX, R_EAX );
970 :}
971 MOV.L Rm, @(disp, Rn) {:
972 load_reg( R_ECX, Rn );
973 load_reg( R_EAX, Rm );
974 ADD_imm32_r32( disp, R_ECX );
975 check_walign32( R_ECX );
976 MEM_WRITE_LONG( R_ECX, R_EAX );
977 :}
978 MOV.L @Rm, Rn {:
979 load_reg( R_ECX, Rm );
980 check_ralign32( R_ECX );
981 MEM_READ_LONG( R_ECX, R_EAX );
982 store_reg( R_EAX, Rn );
983 :}
984 MOV.L @Rm+, Rn {:
985 load_reg( R_EAX, Rm );
986 check_ralign32( R_ECX );
987 MOV_r32_r32( R_EAX, R_ECX );
988 ADD_imm8s_r32( 4, R_EAX );
989 store_reg( R_EAX, Rm );
990 MEM_READ_LONG( R_ECX, R_EAX );
991 store_reg( R_EAX, Rn );
992 :}
993 MOV.L @(R0, Rm), Rn {:
994 load_reg( R_EAX, 0 );
995 load_reg( R_ECX, Rm );
996 ADD_r32_r32( R_EAX, R_ECX );
997 check_ralign32( R_ECX );
998 MEM_READ_LONG( R_ECX, R_EAX );
999 store_reg( R_EAX, Rn );
1000 :}
1001 MOV.L @(disp, GBR), R0 {:
1002 load_spreg( R_ECX, R_GBR );
1003 ADD_imm32_r32( disp, R_ECX );
1004 check_ralign32( R_ECX );
1005 MEM_READ_LONG( R_ECX, R_EAX );
1006 store_reg( R_EAX, 0 );
1007 :}
1008 MOV.L @(disp, PC), Rn {:
1009 if( sh4_x86.in_delay_slot ) {
1010 SLOTILLEGAL();
1011 } else {
1012 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1013 MEM_READ_LONG( R_ECX, R_EAX );
1014 store_reg( R_EAX, 0 );
1015 }
1016 :}
1017 MOV.L @(disp, Rm), Rn {:
1018 load_reg( R_ECX, Rm );
1019 ADD_imm8s_r32( disp, R_ECX );
1020 check_ralign32( R_ECX );
1021 MEM_READ_LONG( R_ECX, R_EAX );
1022 store_reg( R_EAX, Rn );
1023 :}
1024 MOV.W Rm, @Rn {:
1025 load_reg( R_ECX, Rn );
1026 check_walign16( R_ECX );
1027 MEM_READ_WORD( R_ECX, R_EAX );
1028 store_reg( R_EAX, Rn );
1029 :}
1030 MOV.W Rm, @-Rn {:
1031 load_reg( R_ECX, Rn );
1032 check_walign16( R_ECX );
1033 load_reg( R_EAX, Rm );
1034 ADD_imm8s_r32( -2, R_ECX );
1035 MEM_WRITE_WORD( R_ECX, R_EAX );
1036 :}
1037 MOV.W Rm, @(R0, Rn) {:
1038 load_reg( R_EAX, 0 );
1039 load_reg( R_ECX, Rn );
1040 ADD_r32_r32( R_EAX, R_ECX );
1041 check_walign16( R_ECX );
1042 load_reg( R_EAX, Rm );
1043 MEM_WRITE_WORD( R_ECX, R_EAX );
1044 :}
1045 MOV.W R0, @(disp, GBR) {:
1046 load_spreg( R_ECX, R_GBR );
1047 load_reg( R_EAX, 0 );
1048 ADD_imm32_r32( disp, R_ECX );
1049 check_walign16( R_ECX );
1050 MEM_WRITE_WORD( R_ECX, R_EAX );
1051 :}
1052 MOV.W R0, @(disp, Rn) {:
1053 load_reg( R_ECX, Rn );
1054 load_reg( R_EAX, 0 );
1055 ADD_imm32_r32( disp, R_ECX );
1056 check_walign16( R_ECX );
1057 MEM_WRITE_WORD( R_ECX, R_EAX );
1058 :}
1059 MOV.W @Rm, Rn {:
1060 load_reg( R_ECX, Rm );
1061 check_ralign16( R_ECX );
1062 MEM_READ_WORD( R_ECX, R_EAX );
1063 store_reg( R_EAX, Rn );
1064 :}
1065 MOV.W @Rm+, Rn {:
1066 load_reg( R_EAX, Rm );
1067 check_ralign16( R_EAX );
1068 MOV_r32_r32( R_EAX, R_ECX );
1069 ADD_imm8s_r32( 2, R_EAX );
1070 store_reg( R_EAX, Rm );
1071 MEM_READ_WORD( R_ECX, R_EAX );
1072 store_reg( R_EAX, Rn );
1073 :}
1074 MOV.W @(R0, Rm), Rn {:
1075 load_reg( R_EAX, 0 );
1076 load_reg( R_ECX, Rm );
1077 ADD_r32_r32( R_EAX, R_ECX );
1078 check_ralign16( R_ECX );
1079 MEM_READ_WORD( R_ECX, R_EAX );
1080 store_reg( R_EAX, Rn );
1081 :}
1082 MOV.W @(disp, GBR), R0 {:
1083 load_spreg( R_ECX, R_GBR );
1084 ADD_imm32_r32( disp, R_ECX );
1085 check_ralign16( R_ECX );
1086 MEM_READ_WORD( R_ECX, R_EAX );
1087 store_reg( R_EAX, 0 );
1088 :}
1089 MOV.W @(disp, PC), Rn {:
1090 if( sh4_x86.in_delay_slot ) {
1091 SLOTILLEGAL();
1092 } else {
1093 load_imm32( R_ECX, pc + disp + 4 );
1094 MEM_READ_WORD( R_ECX, R_EAX );
1095 store_reg( R_EAX, Rn );
1096 }
1097 :}
1098 MOV.W @(disp, Rm), R0 {:
1099 load_reg( R_ECX, Rm );
1100 ADD_imm32_r32( disp, R_ECX );
1101 check_ralign16( R_ECX );
1102 MEM_READ_WORD( R_ECX, R_EAX );
1103 store_reg( R_EAX, 0 );
1104 :}
1105 MOVA @(disp, PC), R0 {:
1106 if( sh4_x86.in_delay_slot ) {
1107 SLOTILLEGAL();
1108 } else {
1109 load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1110 store_reg( R_ECX, 0 );
1111 }
1112 :}
1113 MOVCA.L R0, @Rn {:
1114 load_reg( R_EAX, 0 );
1115 load_reg( R_ECX, Rn );
1116 check_walign32( R_ECX );
1117 MEM_WRITE_LONG( R_ECX, R_EAX );
1118 :}
1120 /* Control transfer instructions */
1121 BF 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 JNE_rel8( 5, nottaken );
1128 load_imm32( R_EDI, disp + pc + 4 );
1129 JMP_TARGET(nottaken);
1130 INC_r32(R_ESI);
1131 return 1;
1132 }
1133 :}
1134 BF/S disp {:
1135 if( sh4_x86.in_delay_slot ) {
1136 SLOTILLEGAL();
1137 } else {
1138 load_imm32( R_EDI, pc + 2 );
1139 CMP_imm8s_sh4r( 0, R_T );
1140 JNE_rel8( 5, nottaken );
1141 load_imm32( R_EDI, disp + pc + 4 );
1142 JMP_TARGET(nottaken);
1143 sh4_x86.in_delay_slot = TRUE;
1144 INC_r32(R_ESI);
1145 return 0;
1146 }
1147 :}
1148 BRA disp {:
1149 if( sh4_x86.in_delay_slot ) {
1150 SLOTILLEGAL();
1151 } else {
1152 load_imm32( R_EDI, disp + pc + 4 );
1153 sh4_x86.in_delay_slot = TRUE;
1154 INC_r32(R_ESI);
1155 return 0;
1156 }
1157 :}
1158 BRAF Rn {:
1159 if( sh4_x86.in_delay_slot ) {
1160 SLOTILLEGAL();
1161 } else {
1162 load_reg( R_EDI, Rn );
1163 sh4_x86.in_delay_slot = TRUE;
1164 INC_r32(R_ESI);
1165 return 0;
1166 }
1167 :}
1168 BSR disp {:
1169 if( sh4_x86.in_delay_slot ) {
1170 SLOTILLEGAL();
1171 } else {
1172 load_imm32( R_EAX, pc + 4 );
1173 store_spreg( R_EAX, R_PR );
1174 load_imm32( R_EDI, disp + pc + 4 );
1175 sh4_x86.in_delay_slot = TRUE;
1176 INC_r32(R_ESI);
1177 return 0;
1178 }
1179 :}
1180 BSRF Rn {:
1181 if( sh4_x86.in_delay_slot ) {
1182 SLOTILLEGAL();
1183 } else {
1184 load_imm32( R_EAX, pc + 4 );
1185 store_spreg( R_EAX, R_PR );
1186 load_reg( R_EDI, Rn );
1187 ADD_r32_r32( R_EAX, R_EDI );
1188 sh4_x86.in_delay_slot = TRUE;
1189 INC_r32(R_ESI);
1190 return 0;
1191 }
1192 :}
1193 BT disp {:
1194 if( sh4_x86.in_delay_slot ) {
1195 SLOTILLEGAL();
1196 } else {
1197 load_imm32( R_EDI, pc + 2 );
1198 CMP_imm8s_sh4r( 0, R_T );
1199 JE_rel8( 5, nottaken );
1200 load_imm32( R_EDI, disp + pc + 4 );
1201 JMP_TARGET(nottaken);
1202 INC_r32(R_ESI);
1203 return 1;
1204 }
1205 :}
1206 BT/S disp {:
1207 if( sh4_x86.in_delay_slot ) {
1208 SLOTILLEGAL();
1209 } else {
1210 load_imm32( R_EDI, pc + 2 );
1211 CMP_imm8s_sh4r( 0, R_T );
1212 JE_rel8( 5, nottaken );
1213 load_imm32( R_EDI, disp + pc + 4 );
1214 JMP_TARGET(nottaken);
1215 sh4_x86.in_delay_slot = TRUE;
1216 INC_r32(R_ESI);
1217 return 0;
1218 }
1219 :}
1220 JMP @Rn {:
1221 if( sh4_x86.in_delay_slot ) {
1222 SLOTILLEGAL();
1223 } else {
1224 load_reg( R_EDI, Rn );
1225 sh4_x86.in_delay_slot = TRUE;
1226 INC_r32(R_ESI);
1227 return 0;
1228 }
1229 :}
1230 JSR @Rn {:
1231 if( sh4_x86.in_delay_slot ) {
1232 SLOTILLEGAL();
1233 } else {
1234 load_imm32( R_EAX, pc + 4 );
1235 store_spreg( R_EAX, R_PR );
1236 load_reg( R_EDI, Rn );
1237 sh4_x86.in_delay_slot = TRUE;
1238 INC_r32(R_ESI);
1239 return 0;
1240 }
1241 :}
1242 RTE {:
1243 check_priv();
1244 if( sh4_x86.in_delay_slot ) {
1245 SLOTILLEGAL();
1246 } else {
1247 load_spreg( R_EDI, R_PR );
1248 load_spreg( R_EAX, R_SSR );
1249 call_func1( sh4_write_sr, R_EAX );
1250 sh4_x86.in_delay_slot = TRUE;
1251 sh4_x86.priv_checked = FALSE;
1252 sh4_x86.fpuen_checked = FALSE;
1253 INC_r32(R_ESI);
1254 return 0;
1255 }
1256 :}
1257 RTS {:
1258 if( sh4_x86.in_delay_slot ) {
1259 SLOTILLEGAL();
1260 } else {
1261 load_spreg( R_EDI, R_PR );
1262 sh4_x86.in_delay_slot = TRUE;
1263 INC_r32(R_ESI);
1264 return 0;
1265 }
1266 :}
1267 TRAPA #imm {:
1268 if( sh4_x86.in_delay_slot ) {
1269 SLOTILLEGAL();
1270 } else {
1271 // TODO: Write TRA
1272 RAISE_EXCEPTION(EXC_TRAP);
1273 }
1274 :}
1275 UNDEF {:
1276 if( sh4_x86.in_delay_slot ) {
1277 RAISE_EXCEPTION(EXC_SLOT_ILLEGAL);
1278 } else {
1279 RAISE_EXCEPTION(EXC_ILLEGAL);
1280 }
1281 return 1;
1282 :}
1284 CLRMAC {:
1285 XOR_r32_r32(R_EAX, R_EAX);
1286 store_spreg( R_EAX, R_MACL );
1287 store_spreg( R_EAX, R_MACH );
1288 :}
1289 CLRS {:
1290 CLC();
1291 SETC_sh4r(R_S);
1292 :}
1293 CLRT {:
1294 CLC();
1295 SETC_t();
1296 :}
1297 SETS {:
1298 STC();
1299 SETC_sh4r(R_S);
1300 :}
1301 SETT {:
1302 STC();
1303 SETC_t();
1304 :}
1306 /* Floating point moves */
1307 FMOV FRm, FRn {:
1308 /* As horrible as this looks, it's actually covering 5 separate cases:
1309 * 1. 32-bit fr-to-fr (PR=0)
1310 * 2. 64-bit dr-to-dr (PR=1, FRm&1 == 0, FRn&1 == 0 )
1311 * 3. 64-bit dr-to-xd (PR=1, FRm&1 == 0, FRn&1 == 1 )
1312 * 4. 64-bit xd-to-dr (PR=1, FRm&1 == 1, FRn&1 == 0 )
1313 * 5. 64-bit xd-to-xd (PR=1, FRm&1 == 1, FRn&1 == 1 )
1314 */
1315 check_fpuen();
1316 load_spreg( R_ECX, R_FPSCR );
1317 load_fr_bank( R_EDX );
1318 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1319 JNE_rel8(8, doublesize);
1320 load_fr( R_EDX, R_EAX, FRm ); // PR=0 branch
1321 store_fr( R_EDX, R_EAX, FRn );
1322 if( FRm&1 ) {
1323 JMP_rel8(22, end);
1324 JMP_TARGET(doublesize);
1325 load_xf_bank( R_ECX );
1326 load_fr( R_ECX, R_EAX, FRm-1 );
1327 if( FRn&1 ) {
1328 load_fr( R_ECX, R_EDX, FRm );
1329 store_fr( R_ECX, R_EAX, FRn-1 );
1330 store_fr( R_ECX, R_EDX, FRn );
1331 } else /* FRn&1 == 0 */ {
1332 load_fr( R_ECX, R_ECX, FRm );
1333 store_fr( R_EDX, R_EAX, FRn-1 );
1334 store_fr( R_EDX, R_ECX, FRn );
1335 }
1336 JMP_TARGET(end);
1337 } else /* FRm&1 == 0 */ {
1338 if( FRn&1 ) {
1339 JMP_rel8(22, end);
1340 load_xf_bank( R_ECX );
1341 load_fr( R_EDX, R_EAX, FRm );
1342 load_fr( R_EDX, R_EDX, FRm+1 );
1343 store_fr( R_ECX, R_EAX, FRn-1 );
1344 store_fr( R_ECX, R_EDX, FRn );
1345 JMP_TARGET(end);
1346 } else /* FRn&1 == 0 */ {
1347 JMP_rel8(12, end);
1348 load_fr( R_EDX, R_EAX, FRm );
1349 load_fr( R_EDX, R_ECX, FRm+1 );
1350 store_fr( R_EDX, R_EAX, FRn );
1351 store_fr( R_EDX, R_ECX, FRn+1 );
1352 JMP_TARGET(end);
1353 }
1354 }
1355 :}
1356 FMOV FRm, @Rn {:
1357 check_fpuen();
1358 load_reg( R_EDX, Rn );
1359 check_walign32( R_EDX );
1360 load_spreg( R_ECX, R_FPSCR );
1361 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1362 JNE_rel8(20, doublesize);
1363 load_fr_bank( R_ECX );
1364 load_fr( R_ECX, R_EAX, FRm );
1365 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1366 if( FRm&1 ) {
1367 JMP_rel8( 46, end );
1368 JMP_TARGET(doublesize);
1369 load_xf_bank( R_ECX );
1370 load_fr( R_ECX, R_EAX, FRm&0x0E );
1371 load_fr( R_ECX, R_ECX, FRm|0x01 );
1372 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1373 JMP_TARGET(end);
1374 } else {
1375 JMP_rel8( 39, end );
1376 JMP_TARGET(doublesize);
1377 load_fr_bank( R_ECX );
1378 load_fr( R_ECX, R_EAX, FRm&0x0E );
1379 load_fr( R_ECX, R_ECX, FRm|0x01 );
1380 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1381 JMP_TARGET(end);
1382 }
1383 :}
1384 FMOV @Rm, FRn {:
1385 check_fpuen();
1386 load_reg( R_EDX, Rm );
1387 check_ralign32( R_EDX );
1388 load_spreg( R_ECX, R_FPSCR );
1389 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1390 JNE_rel8(19, doublesize);
1391 MEM_READ_LONG( R_EDX, R_EAX );
1392 load_fr_bank( R_ECX );
1393 store_fr( R_ECX, R_EAX, FRn );
1394 if( FRn&1 ) {
1395 JMP_rel8(46, end);
1396 JMP_TARGET(doublesize);
1397 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1398 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1399 load_xf_bank( R_ECX );
1400 store_fr( R_ECX, R_EAX, FRn&0x0E );
1401 store_fr( R_ECX, R_EDX, FRn|0x01 );
1402 JMP_TARGET(end);
1403 } else {
1404 JMP_rel8(36, end);
1405 JMP_TARGET(doublesize);
1406 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1407 load_fr_bank( R_ECX );
1408 store_fr( R_ECX, R_EAX, FRn&0x0E );
1409 store_fr( R_ECX, R_EDX, FRn|0x01 );
1410 JMP_TARGET(end);
1411 }
1412 :}
1413 FMOV FRm, @-Rn {:
1414 check_fpuen();
1415 load_reg( R_EDX, Rn );
1416 check_walign32( R_EDX );
1417 load_spreg( R_ECX, R_FPSCR );
1418 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1419 JNE_rel8(20, doublesize);
1420 load_fr_bank( R_ECX );
1421 load_fr( R_ECX, R_EAX, FRm );
1422 ADD_imm8s_r32(-4,R_EDX);
1423 store_reg( R_EDX, Rn );
1424 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1425 if( FRm&1 ) {
1426 JMP_rel8( 46, end );
1427 JMP_TARGET(doublesize);
1428 load_xf_bank( R_ECX );
1429 load_fr( R_ECX, R_EAX, FRm&0x0E );
1430 load_fr( R_ECX, R_ECX, FRm|0x01 );
1431 ADD_imm8s_r32(-8,R_EDX);
1432 store_reg( R_EDX, Rn );
1433 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1434 JMP_TARGET(end);
1435 } else {
1436 JMP_rel8( 39, end );
1437 JMP_TARGET(doublesize);
1438 load_fr_bank( R_ECX );
1439 load_fr( R_ECX, R_EAX, FRm&0x0E );
1440 load_fr( R_ECX, R_ECX, FRm|0x01 );
1441 ADD_imm8s_r32(-8,R_EDX);
1442 store_reg( R_EDX, Rn );
1443 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1444 JMP_TARGET(end);
1445 }
1446 :}
1447 FMOV @Rm+, FRn {:
1448 check_fpuen();
1449 load_reg( R_EDX, Rm );
1450 check_ralign32( R_EDX );
1451 MOV_r32_r32( R_EDX, R_EAX );
1452 load_spreg( R_ECX, R_FPSCR );
1453 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1454 JNE_rel8(25, doublesize);
1455 ADD_imm8s_r32( 4, R_EAX );
1456 store_reg( R_EAX, Rm );
1457 MEM_READ_LONG( R_EDX, R_EAX );
1458 load_fr_bank( R_ECX );
1459 store_fr( R_ECX, R_EAX, FRn );
1460 if( FRn&1 ) {
1461 JMP_rel8(52, end);
1462 JMP_TARGET(doublesize);
1463 ADD_imm8s_r32( 8, R_EAX );
1464 store_reg(R_EAX, Rm);
1465 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1466 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1467 load_xf_bank( R_ECX );
1468 store_fr( R_ECX, R_EAX, FRn&0x0E );
1469 store_fr( R_ECX, R_EDX, FRn|0x01 );
1470 JMP_TARGET(end);
1471 } else {
1472 JMP_rel8(42, end);
1473 ADD_imm8s_r32( 8, R_EAX );
1474 store_reg(R_EAX, Rm);
1475 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1476 load_fr_bank( R_ECX );
1477 store_fr( R_ECX, R_EAX, FRn&0x0E );
1478 store_fr( R_ECX, R_EDX, FRn|0x01 );
1479 JMP_TARGET(end);
1480 }
1481 :}
1482 FMOV FRm, @(R0, Rn) {:
1483 check_fpuen();
1484 load_reg( R_EDX, Rn );
1485 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
1486 check_walign32( R_EDX );
1487 load_spreg( R_ECX, R_FPSCR );
1488 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1489 JNE_rel8(20, doublesize);
1490 load_fr_bank( R_ECX );
1491 load_fr( R_ECX, R_EAX, FRm );
1492 MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
1493 if( FRm&1 ) {
1494 JMP_rel8( 46, end );
1495 JMP_TARGET(doublesize);
1496 load_xf_bank( R_ECX );
1497 load_fr( R_ECX, R_EAX, FRm&0x0E );
1498 load_fr( R_ECX, R_ECX, FRm|0x01 );
1499 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1500 JMP_TARGET(end);
1501 } else {
1502 JMP_rel8( 39, end );
1503 JMP_TARGET(doublesize);
1504 load_fr_bank( R_ECX );
1505 load_fr( R_ECX, R_EAX, FRm&0x0E );
1506 load_fr( R_ECX, R_ECX, FRm|0x01 );
1507 MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
1508 JMP_TARGET(end);
1509 }
1510 :}
1511 FMOV @(R0, Rm), FRn {:
1512 check_fpuen();
1513 load_reg( R_EDX, Rm );
1514 ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
1515 check_ralign32( R_EDX );
1516 load_spreg( R_ECX, R_FPSCR );
1517 TEST_imm32_r32( FPSCR_SZ, R_ECX );
1518 JNE_rel8(19, doublesize);
1519 MEM_READ_LONG( R_EDX, R_EAX );
1520 load_fr_bank( R_ECX );
1521 store_fr( R_ECX, R_EAX, FRn );
1522 if( FRn&1 ) {
1523 JMP_rel8(46, end);
1524 JMP_TARGET(doublesize);
1525 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1526 load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
1527 load_xf_bank( R_ECX );
1528 store_fr( R_ECX, R_EAX, FRn&0x0E );
1529 store_fr( R_ECX, R_EDX, FRn|0x01 );
1530 JMP_TARGET(end);
1531 } else {
1532 JMP_rel8(36, end);
1533 JMP_TARGET(doublesize);
1534 MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
1535 load_fr_bank( R_ECX );
1536 store_fr( R_ECX, R_EAX, FRn&0x0E );
1537 store_fr( R_ECX, R_EDX, FRn|0x01 );
1538 JMP_TARGET(end);
1539 }
1540 :}
1541 FLDI0 FRn {: /* IFF PR=0 */
1542 check_fpuen();
1543 load_spreg( R_ECX, R_FPSCR );
1544 TEST_imm32_r32( FPSCR_PR, R_ECX );
1545 JNE_rel8(8, end);
1546 XOR_r32_r32( R_EAX, R_EAX );
1547 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1548 store_fr( R_ECX, R_EAX, FRn );
1549 JMP_TARGET(end);
1550 :}
1551 FLDI1 FRn {: /* IFF PR=0 */
1552 check_fpuen();
1553 load_spreg( R_ECX, R_FPSCR );
1554 TEST_imm32_r32( FPSCR_PR, R_ECX );
1555 JNE_rel8(11, end);
1556 load_imm32(R_EAX, 0x3F800000);
1557 load_spreg( R_ECX, REG_OFFSET(fr_bank) );
1558 store_fr( R_ECX, R_EAX, FRn );
1559 JMP_TARGET(end);
1560 :}
1562 FLOAT FPUL, FRn {:
1563 check_fpuen();
1564 load_spreg( R_ECX, R_FPSCR );
1565 load_spreg(R_EDX, REG_OFFSET(fr_bank));
1566 FILD_sh4r(R_FPUL);
1567 TEST_imm32_r32( FPSCR_PR, R_ECX );
1568 JNE_rel8(5, doubleprec);
1569 pop_fr( R_EDX, FRn );
1570 JMP_rel8(3, end);
1571 JMP_TARGET(doubleprec);
1572 pop_dr( R_EDX, FRn );
1573 JMP_TARGET(end);
1574 :}
1575 FTRC FRm, FPUL {:
1576 check_fpuen();
1577 // TODO
1578 :}
1579 FLDS FRm, FPUL {:
1580 check_fpuen();
1581 load_fr_bank( R_ECX );
1582 load_fr( R_ECX, R_EAX, FRm );
1583 store_spreg( R_EAX, R_FPUL );
1584 :}
1585 FSTS FPUL, FRn {:
1586 check_fpuen();
1587 load_fr_bank( R_ECX );
1588 load_spreg( R_EAX, R_FPUL );
1589 store_fr( R_ECX, R_EAX, FRn );
1590 :}
1591 FCNVDS FRm, FPUL {:
1592 check_fpuen();
1593 load_spreg( R_ECX, R_FPSCR );
1594 TEST_imm32_r32( FPSCR_PR, R_ECX );
1595 JE_rel8(9, end); // only when PR=1
1596 load_fr_bank( R_ECX );
1597 push_dr( R_ECX, FRm );
1598 pop_fpul();
1599 JMP_TARGET(end);
1600 :}
1601 FCNVSD FPUL, FRn {:
1602 check_fpuen();
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_fpul();
1609 pop_dr( R_ECX, FRn );
1610 JMP_TARGET(end);
1611 :}
1613 /* Floating point instructions */
1614 FABS FRn {:
1615 check_fpuen();
1616 load_spreg( R_ECX, R_FPSCR );
1617 load_fr_bank( R_EDX );
1618 TEST_imm32_r32( FPSCR_PR, R_ECX );
1619 JNE_rel8(10, doubleprec);
1620 push_fr(R_EDX, FRn); // 3
1621 FABS_st0(); // 2
1622 pop_fr( R_EDX, FRn); //3
1623 JMP_rel8(8,end); // 2
1624 JMP_TARGET(doubleprec);
1625 push_dr(R_EDX, FRn);
1626 FABS_st0();
1627 pop_dr(R_EDX, FRn);
1628 JMP_TARGET(end);
1629 :}
1630 FADD FRm, FRn {:
1631 check_fpuen();
1632 load_spreg( R_ECX, R_FPSCR );
1633 TEST_imm32_r32( FPSCR_PR, R_ECX );
1634 load_fr_bank( R_EDX );
1635 JNE_rel8(13,doubleprec);
1636 push_fr(R_EDX, FRm);
1637 push_fr(R_EDX, FRn);
1638 FADDP_st(1);
1639 pop_fr(R_EDX, FRn);
1640 JMP_rel8(11,end);
1641 JMP_TARGET(doubleprec);
1642 push_dr(R_EDX, FRm);
1643 push_dr(R_EDX, FRn);
1644 FADDP_st(1);
1645 pop_dr(R_EDX, FRn);
1646 JMP_TARGET(end);
1647 :}
1648 FDIV FRm, FRn {:
1649 check_fpuen();
1650 load_spreg( R_ECX, R_FPSCR );
1651 TEST_imm32_r32( FPSCR_PR, R_ECX );
1652 load_fr_bank( R_EDX );
1653 JNE_rel8(13, doubleprec);
1654 push_fr(R_EDX, FRn);
1655 push_fr(R_EDX, FRm);
1656 FDIVP_st(1);
1657 pop_fr(R_EDX, FRn);
1658 JMP_rel8(11, end);
1659 JMP_TARGET(doubleprec);
1660 push_dr(R_EDX, FRn);
1661 push_dr(R_EDX, FRm);
1662 FDIVP_st(1);
1663 pop_dr(R_EDX, FRn);
1664 JMP_TARGET(end);
1665 :}
1666 FMAC FR0, FRm, FRn {:
1667 check_fpuen();
1668 load_spreg( R_ECX, R_FPSCR );
1669 load_spreg( R_EDX, REG_OFFSET(fr_bank));
1670 TEST_imm32_r32( FPSCR_PR, R_ECX );
1671 JNE_rel8(18, doubleprec);
1672 push_fr( R_EDX, 0 );
1673 push_fr( R_EDX, FRm );
1674 FMULP_st(1);
1675 push_fr( R_EDX, FRn );
1676 FADDP_st(1);
1677 pop_fr( R_EDX, FRn );
1678 JMP_rel8(16, end);
1679 JMP_TARGET(doubleprec);
1680 push_dr( R_EDX, 0 );
1681 push_dr( R_EDX, FRm );
1682 FMULP_st(1);
1683 push_dr( R_EDX, FRn );
1684 FADDP_st(1);
1685 pop_dr( R_EDX, FRn );
1686 JMP_TARGET(end);
1687 :}
1689 FMUL FRm, FRn {:
1690 check_fpuen();
1691 load_spreg( R_ECX, R_FPSCR );
1692 TEST_imm32_r32( FPSCR_PR, R_ECX );
1693 load_fr_bank( R_EDX );
1694 JNE_rel8(13, doubleprec);
1695 push_fr(R_EDX, FRm);
1696 push_fr(R_EDX, FRn);
1697 FMULP_st(1);
1698 pop_fr(R_EDX, FRn);
1699 JMP_rel8(11, end);
1700 JMP_TARGET(doubleprec);
1701 push_dr(R_EDX, FRm);
1702 push_dr(R_EDX, FRn);
1703 FMULP_st(1);
1704 pop_dr(R_EDX, FRn);
1705 JMP_TARGET(end);
1706 :}
1707 FNEG FRn {:
1708 check_fpuen();
1709 load_spreg( R_ECX, R_FPSCR );
1710 TEST_imm32_r32( FPSCR_PR, R_ECX );
1711 load_fr_bank( R_EDX );
1712 JNE_rel8(10, doubleprec);
1713 push_fr(R_EDX, FRn);
1714 FCHS_st0();
1715 pop_fr(R_EDX, FRn);
1716 JMP_rel8(8, end);
1717 JMP_TARGET(doubleprec);
1718 push_dr(R_EDX, FRn);
1719 FCHS_st0();
1720 pop_dr(R_EDX, FRn);
1721 JMP_TARGET(end);
1722 :}
1723 FSRRA FRn {:
1724 check_fpuen();
1725 load_spreg( R_ECX, R_FPSCR );
1726 TEST_imm32_r32( FPSCR_PR, R_ECX );
1727 load_fr_bank( R_EDX );
1728 JNE_rel8(12, end); // PR=0 only
1729 FLD1_st0();
1730 push_fr(R_EDX, FRn);
1731 FSQRT_st0();
1732 FDIVP_st(1);
1733 pop_fr(R_EDX, FRn);
1734 JMP_TARGET(end);
1735 :}
1736 FSQRT FRn {:
1737 check_fpuen();
1738 load_spreg( R_ECX, R_FPSCR );
1739 TEST_imm32_r32( FPSCR_PR, R_ECX );
1740 load_fr_bank( R_EDX );
1741 JNE_rel8(10, doubleprec);
1742 push_fr(R_EDX, FRn);
1743 FSQRT_st0();
1744 pop_fr(R_EDX, FRn);
1745 JMP_rel8(8, end);
1746 JMP_TARGET(doubleprec);
1747 push_dr(R_EDX, FRn);
1748 FSQRT_st0();
1749 pop_dr(R_EDX, FRn);
1750 JMP_TARGET(end);
1751 :}
1752 FSUB FRm, FRn {:
1753 check_fpuen();
1754 load_spreg( R_ECX, R_FPSCR );
1755 TEST_imm32_r32( FPSCR_PR, R_ECX );
1756 load_fr_bank( R_EDX );
1757 JNE_rel8(13, doubleprec);
1758 push_fr(R_EDX, FRn);
1759 push_fr(R_EDX, FRm);
1760 FMULP_st(1);
1761 pop_fr(R_EDX, FRn);
1762 JMP_rel8(11, end);
1763 JMP_TARGET(doubleprec);
1764 push_dr(R_EDX, FRn);
1765 push_dr(R_EDX, FRm);
1766 FMULP_st(1);
1767 pop_dr(R_EDX, FRn);
1768 JMP_TARGET(end);
1769 :}
1771 FCMP/EQ FRm, FRn {:
1772 check_fpuen();
1773 load_spreg( R_ECX, R_FPSCR );
1774 TEST_imm32_r32( FPSCR_PR, R_ECX );
1775 load_fr_bank( R_EDX );
1776 JNE_rel8(8, doubleprec);
1777 push_fr(R_EDX, FRm);
1778 push_fr(R_EDX, FRn);
1779 JMP_rel8(6, end);
1780 JMP_TARGET(doubleprec);
1781 push_dr(R_EDX, FRm);
1782 push_dr(R_EDX, FRn);
1783 FCOMIP_st(1);
1784 SETE_t();
1785 FPOP_st();
1786 JMP_TARGET(end);
1787 :}
1788 FCMP/GT FRm, FRn {:
1789 check_fpuen();
1790 load_spreg( R_ECX, R_FPSCR );
1791 TEST_imm32_r32( FPSCR_PR, R_ECX );
1792 load_fr_bank( R_EDX );
1793 JNE_rel8(8, doubleprec);
1794 push_fr(R_EDX, FRm);
1795 push_fr(R_EDX, FRn);
1796 JMP_rel8(6, end);
1797 JMP_TARGET(doubleprec);
1798 push_dr(R_EDX, FRm);
1799 push_dr(R_EDX, FRn);
1800 JMP_TARGET(end);
1801 FCOMIP_st(1);
1802 SETA_t();
1803 FPOP_st();
1804 :}
1806 FSCA FPUL, FRn {:
1807 check_fpuen();
1808 :}
1809 FIPR FVm, FVn {:
1810 check_fpuen();
1811 :}
1812 FTRV XMTRX, FVn {:
1813 check_fpuen();
1814 :}
1816 FRCHG {:
1817 check_fpuen();
1818 load_spreg( R_ECX, R_FPSCR );
1819 XOR_imm32_r32( FPSCR_FR, R_ECX );
1820 store_spreg( R_ECX, R_FPSCR );
1822 :}
1823 FSCHG {:
1824 check_fpuen();
1825 load_spreg( R_ECX, R_FPSCR );
1826 XOR_imm32_r32( FPSCR_SZ, R_ECX );
1827 store_spreg( R_ECX, R_FPSCR );
1828 :}
1830 /* Processor control instructions */
1831 LDC Rm, SR {:
1832 load_reg( R_EAX, Rm );
1833 call_func1( sh4_write_sr, R_EAX );
1834 sh4_x86.priv_checked = FALSE;
1835 sh4_x86.fpuen_checked = FALSE;
1836 :}
1837 LDC Rm, GBR {:
1838 load_reg( R_EAX, Rm );
1839 store_spreg( R_EAX, R_GBR );
1840 :}
1841 LDC Rm, VBR {:
1842 load_reg( R_EAX, Rm );
1843 store_spreg( R_EAX, R_VBR );
1844 :}
1845 LDC Rm, SSR {:
1846 load_reg( R_EAX, Rm );
1847 store_spreg( R_EAX, R_SSR );
1848 :}
1849 LDC Rm, SGR {:
1850 load_reg( R_EAX, Rm );
1851 store_spreg( R_EAX, R_SGR );
1852 :}
1853 LDC Rm, SPC {:
1854 load_reg( R_EAX, Rm );
1855 store_spreg( R_EAX, R_SPC );
1856 :}
1857 LDC Rm, DBR {:
1858 load_reg( R_EAX, Rm );
1859 store_spreg( R_EAX, R_DBR );
1860 :}
1861 LDC Rm, Rn_BANK {:
1862 load_reg( R_EAX, Rm );
1863 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1864 :}
1865 LDC.L @Rm+, GBR {:
1866 load_reg( R_EAX, Rm );
1867 MOV_r32_r32( R_EAX, R_ECX );
1868 ADD_imm8s_r32( 4, R_EAX );
1869 store_reg( R_EAX, Rm );
1870 MEM_READ_LONG( R_ECX, R_EAX );
1871 store_spreg( R_EAX, R_GBR );
1872 :}
1873 LDC.L @Rm+, SR {:
1874 load_reg( R_EAX, Rm );
1875 MOV_r32_r32( R_EAX, R_ECX );
1876 ADD_imm8s_r32( 4, R_EAX );
1877 store_reg( R_EAX, Rm );
1878 MEM_READ_LONG( R_ECX, R_EAX );
1879 call_func1( sh4_write_sr, R_EAX );
1880 sh4_x86.priv_checked = FALSE;
1881 sh4_x86.fpuen_checked = FALSE;
1882 :}
1883 LDC.L @Rm+, VBR {:
1884 load_reg( R_EAX, Rm );
1885 MOV_r32_r32( R_EAX, R_ECX );
1886 ADD_imm8s_r32( 4, R_EAX );
1887 store_reg( R_EAX, Rm );
1888 MEM_READ_LONG( R_ECX, R_EAX );
1889 store_spreg( R_EAX, R_VBR );
1890 :}
1891 LDC.L @Rm+, SSR {:
1892 load_reg( R_EAX, Rm );
1893 MOV_r32_r32( R_EAX, R_ECX );
1894 ADD_imm8s_r32( 4, R_EAX );
1895 store_reg( R_EAX, Rm );
1896 MEM_READ_LONG( R_ECX, R_EAX );
1897 store_spreg( R_EAX, R_SSR );
1898 :}
1899 LDC.L @Rm+, SGR {:
1900 load_reg( R_EAX, Rm );
1901 MOV_r32_r32( R_EAX, R_ECX );
1902 ADD_imm8s_r32( 4, R_EAX );
1903 store_reg( R_EAX, Rm );
1904 MEM_READ_LONG( R_ECX, R_EAX );
1905 store_spreg( R_EAX, R_SGR );
1906 :}
1907 LDC.L @Rm+, SPC {:
1908 load_reg( R_EAX, Rm );
1909 MOV_r32_r32( R_EAX, R_ECX );
1910 ADD_imm8s_r32( 4, R_EAX );
1911 store_reg( R_EAX, Rm );
1912 MEM_READ_LONG( R_ECX, R_EAX );
1913 store_spreg( R_EAX, R_SPC );
1914 :}
1915 LDC.L @Rm+, DBR {:
1916 load_reg( R_EAX, Rm );
1917 MOV_r32_r32( R_EAX, R_ECX );
1918 ADD_imm8s_r32( 4, R_EAX );
1919 store_reg( R_EAX, Rm );
1920 MEM_READ_LONG( R_ECX, R_EAX );
1921 store_spreg( R_EAX, R_DBR );
1922 :}
1923 LDC.L @Rm+, Rn_BANK {:
1924 load_reg( R_EAX, Rm );
1925 MOV_r32_r32( R_EAX, R_ECX );
1926 ADD_imm8s_r32( 4, R_EAX );
1927 store_reg( R_EAX, Rm );
1928 MEM_READ_LONG( R_ECX, R_EAX );
1929 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1930 :}
1931 LDS Rm, FPSCR {:
1932 load_reg( R_EAX, Rm );
1933 store_spreg( R_EAX, R_FPSCR );
1934 :}
1935 LDS.L @Rm+, FPSCR {:
1936 load_reg( R_EAX, Rm );
1937 MOV_r32_r32( R_EAX, R_ECX );
1938 ADD_imm8s_r32( 4, R_EAX );
1939 store_reg( R_EAX, Rm );
1940 MEM_READ_LONG( R_ECX, R_EAX );
1941 store_spreg( R_EAX, R_FPSCR );
1942 :}
1943 LDS Rm, FPUL {:
1944 load_reg( R_EAX, Rm );
1945 store_spreg( R_EAX, R_FPUL );
1946 :}
1947 LDS.L @Rm+, FPUL {:
1948 load_reg( R_EAX, Rm );
1949 MOV_r32_r32( R_EAX, R_ECX );
1950 ADD_imm8s_r32( 4, R_EAX );
1951 store_reg( R_EAX, Rm );
1952 MEM_READ_LONG( R_ECX, R_EAX );
1953 store_spreg( R_EAX, R_FPUL );
1954 :}
1955 LDS Rm, MACH {:
1956 load_reg( R_EAX, Rm );
1957 store_spreg( R_EAX, R_MACH );
1958 :}
1959 LDS.L @Rm+, MACH {:
1960 load_reg( R_EAX, Rm );
1961 MOV_r32_r32( R_EAX, R_ECX );
1962 ADD_imm8s_r32( 4, R_EAX );
1963 store_reg( R_EAX, Rm );
1964 MEM_READ_LONG( R_ECX, R_EAX );
1965 store_spreg( R_EAX, R_MACH );
1966 :}
1967 LDS Rm, MACL {:
1968 load_reg( R_EAX, Rm );
1969 store_spreg( R_EAX, R_MACL );
1970 :}
1971 LDS.L @Rm+, MACL {:
1972 load_reg( R_EAX, Rm );
1973 MOV_r32_r32( R_EAX, R_ECX );
1974 ADD_imm8s_r32( 4, R_EAX );
1975 store_reg( R_EAX, Rm );
1976 MEM_READ_LONG( R_ECX, R_EAX );
1977 store_spreg( R_EAX, R_MACL );
1978 :}
1979 LDS Rm, PR {:
1980 load_reg( R_EAX, Rm );
1981 store_spreg( R_EAX, R_PR );
1982 :}
1983 LDS.L @Rm+, PR {:
1984 load_reg( R_EAX, Rm );
1985 MOV_r32_r32( R_EAX, R_ECX );
1986 ADD_imm8s_r32( 4, R_EAX );
1987 store_reg( R_EAX, Rm );
1988 MEM_READ_LONG( R_ECX, R_EAX );
1989 store_spreg( R_EAX, R_PR );
1990 :}
1991 LDTLB {: :}
1992 OCBI @Rn {: :}
1993 OCBP @Rn {: :}
1994 OCBWB @Rn {: :}
1995 PREF @Rn {:
1996 load_reg( R_EAX, Rn );
1997 PUSH_r32( R_EAX );
1998 AND_imm32_r32( 0xFC000000, R_EAX );
1999 CMP_imm32_r32( 0xE0000000, R_EAX );
2000 JNE_rel8(7, end);
2001 call_func0( sh4_flush_store_queue );
2002 JMP_TARGET(end);
2003 ADD_imm8s_r32( 4, R_ESP );
2004 :}
2005 SLEEP {: /* TODO */ :}
2006 STC SR, Rn {:
2007 call_func0(sh4_read_sr);
2008 store_reg( R_EAX, Rn );
2009 :}
2010 STC GBR, Rn {:
2011 load_spreg( R_EAX, R_GBR );
2012 store_reg( R_EAX, Rn );
2013 :}
2014 STC VBR, Rn {:
2015 load_spreg( R_EAX, R_VBR );
2016 store_reg( R_EAX, Rn );
2017 :}
2018 STC SSR, Rn {:
2019 load_spreg( R_EAX, R_SSR );
2020 store_reg( R_EAX, Rn );
2021 :}
2022 STC SPC, Rn {:
2023 load_spreg( R_EAX, R_SPC );
2024 store_reg( R_EAX, Rn );
2025 :}
2026 STC SGR, Rn {:
2027 load_spreg( R_EAX, R_SGR );
2028 store_reg( R_EAX, Rn );
2029 :}
2030 STC DBR, Rn {:
2031 load_spreg( R_EAX, R_DBR );
2032 store_reg( R_EAX, Rn );
2033 :}
2034 STC Rm_BANK, Rn {:
2035 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2036 store_reg( R_EAX, Rn );
2037 :}
2038 STC.L SR, @-Rn {:
2039 load_reg( R_ECX, Rn );
2040 ADD_imm8s_r32( -4, Rn );
2041 store_reg( R_ECX, Rn );
2042 call_func0( sh4_read_sr );
2043 MEM_WRITE_LONG( R_ECX, R_EAX );
2044 :}
2045 STC.L VBR, @-Rn {:
2046 load_reg( R_ECX, Rn );
2047 ADD_imm8s_r32( -4, Rn );
2048 store_reg( R_ECX, Rn );
2049 load_spreg( R_EAX, R_VBR );
2050 MEM_WRITE_LONG( R_ECX, R_EAX );
2051 :}
2052 STC.L SSR, @-Rn {:
2053 load_reg( R_ECX, Rn );
2054 ADD_imm8s_r32( -4, Rn );
2055 store_reg( R_ECX, Rn );
2056 load_spreg( R_EAX, R_SSR );
2057 MEM_WRITE_LONG( R_ECX, R_EAX );
2058 :}
2059 STC.L SPC, @-Rn {:
2060 load_reg( R_ECX, Rn );
2061 ADD_imm8s_r32( -4, Rn );
2062 store_reg( R_ECX, Rn );
2063 load_spreg( R_EAX, R_SPC );
2064 MEM_WRITE_LONG( R_ECX, R_EAX );
2065 :}
2066 STC.L SGR, @-Rn {:
2067 load_reg( R_ECX, Rn );
2068 ADD_imm8s_r32( -4, Rn );
2069 store_reg( R_ECX, Rn );
2070 load_spreg( R_EAX, R_SGR );
2071 MEM_WRITE_LONG( R_ECX, R_EAX );
2072 :}
2073 STC.L DBR, @-Rn {:
2074 load_reg( R_ECX, Rn );
2075 ADD_imm8s_r32( -4, Rn );
2076 store_reg( R_ECX, Rn );
2077 load_spreg( R_EAX, R_DBR );
2078 MEM_WRITE_LONG( R_ECX, R_EAX );
2079 :}
2080 STC.L Rm_BANK, @-Rn {:
2081 load_reg( R_ECX, Rn );
2082 ADD_imm8s_r32( -4, Rn );
2083 store_reg( R_ECX, Rn );
2084 load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
2085 MEM_WRITE_LONG( R_ECX, R_EAX );
2086 :}
2087 STC.L GBR, @-Rn {:
2088 load_reg( R_ECX, Rn );
2089 ADD_imm8s_r32( -4, Rn );
2090 store_reg( R_ECX, Rn );
2091 load_spreg( R_EAX, R_GBR );
2092 MEM_WRITE_LONG( R_ECX, R_EAX );
2093 :}
2094 STS FPSCR, Rn {:
2095 load_spreg( R_EAX, R_FPSCR );
2096 store_reg( R_EAX, Rn );
2097 :}
2098 STS.L FPSCR, @-Rn {:
2099 load_reg( R_ECX, Rn );
2100 ADD_imm8s_r32( -4, Rn );
2101 store_reg( R_ECX, Rn );
2102 load_spreg( R_EAX, R_FPSCR );
2103 MEM_WRITE_LONG( R_ECX, R_EAX );
2104 :}
2105 STS FPUL, Rn {:
2106 load_spreg( R_EAX, R_FPUL );
2107 store_reg( R_EAX, Rn );
2108 :}
2109 STS.L FPUL, @-Rn {:
2110 load_reg( R_ECX, Rn );
2111 ADD_imm8s_r32( -4, Rn );
2112 store_reg( R_ECX, Rn );
2113 load_spreg( R_EAX, R_FPUL );
2114 MEM_WRITE_LONG( R_ECX, R_EAX );
2115 :}
2116 STS MACH, Rn {:
2117 load_spreg( R_EAX, R_MACH );
2118 store_reg( R_EAX, Rn );
2119 :}
2120 STS.L MACH, @-Rn {:
2121 load_reg( R_ECX, Rn );
2122 ADD_imm8s_r32( -4, Rn );
2123 store_reg( R_ECX, Rn );
2124 load_spreg( R_EAX, R_MACH );
2125 MEM_WRITE_LONG( R_ECX, R_EAX );
2126 :}
2127 STS MACL, Rn {:
2128 load_spreg( R_EAX, R_MACL );
2129 store_reg( R_EAX, Rn );
2130 :}
2131 STS.L MACL, @-Rn {:
2132 load_reg( R_ECX, Rn );
2133 ADD_imm8s_r32( -4, Rn );
2134 store_reg( R_ECX, Rn );
2135 load_spreg( R_EAX, R_MACL );
2136 MEM_WRITE_LONG( R_ECX, R_EAX );
2137 :}
2138 STS PR, Rn {:
2139 load_spreg( R_EAX, R_PR );
2140 store_reg( R_EAX, Rn );
2141 :}
2142 STS.L PR, @-Rn {:
2143 load_reg( R_ECX, Rn );
2144 ADD_imm8s_r32( -4, Rn );
2145 store_reg( R_ECX, Rn );
2146 load_spreg( R_EAX, R_PR );
2147 MEM_WRITE_LONG( R_ECX, R_EAX );
2148 :}
2150 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}
2151 %%
2152 INC_r32(R_ESI);
2153 if( sh4_x86.in_delay_slot ) {
2154 sh4_x86.in_delay_slot = FALSE;
2155 return 1;
2156 }
2157 return 0;
2158 }
.