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