Search
lxdream.org :: lxdream/src/sh4/sh4x86.in
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4x86.in
changeset 361:be3de4ecd954
prev359:c588dce7ebde
next368:36fac4c42322
author nkeynes
date Tue Aug 28 08:46:14 2007 +0000 (13 years ago)
permissions -rw-r--r--
last change Translator WIP: fill out and correct another batch of instructions
view annotate diff log raw
     1 /**
     2  * $Id: sh4x86.in,v 1.2 2007-08-28 08:46:14 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 "sh4core.h"
    22 #include "sh4trans.h"
    23 #include "x86op.h"
    25 /**
    26  * Emit an instruction to load an SH4 reg into a real register
    27  */
    28 static inline void load_reg( int x86reg, int sh4reg ) 
    29 {
    30     /* mov [bp+n], reg */
    31     OP(0x8B);
    32     OP(0x45 + (x86reg<<3));
    33     OP(REG_OFFSET(r[sh4reg]));
    34 }
    36 static inline void load_spreg( int x86reg, int regoffset )
    37 {
    38     /* mov [bp+n], reg */
    39     OP(0x8B);
    40     OP(0x45 + (x86reg<<3));
    41     OP(regoffset);
    42 }
    44 /**
    45  * Emit an instruction to load an immediate value into a register
    46  */
    47 static inline void load_imm32( int x86reg, uint32_t value ) {
    48     /* mov #value, reg */
    49     OP(0xB8 + x86reg);
    50     OP32(value);
    51 }
    53 /**
    54  * Emit an instruction to store an SH4 reg (RN)
    55  */
    56 void static inline store_reg( int x86reg, int sh4reg ) {
    57     /* mov reg, [bp+n] */
    58     OP(0x89);
    59     OP(0x45 + (x86reg<<3));
    60     OP(REG_OFFSET(r[sh4reg]));
    61 }
    62 void static inline store_spreg( int x86reg, int regoffset ) {
    63     /* mov reg, [bp+n] */
    64     OP(0x89);
    65     OP(0x45 + (x86reg<<3));
    66     OP(regoffset);
    67 }
    69 /**
    70  * Note: clobbers EAX to make the indirect call - this isn't usually
    71  * a problem since the callee will usually clobber it anyway.
    72  */
    73 static inline void call_func0( void *ptr )
    74 {
    75     load_imm32(R_EAX, (uint32_t)ptr);
    76     OP(0xFF);
    77     MODRM_rm32_r32(R_EAX, 2);
    78 }
    80 static inline void call_func1( void *ptr, int arg1 )
    81 {
    82     PUSH_r32(arg1);
    83     call_func0(ptr);
    84     ADD_imm8s_r32( -4, R_ESP );
    85 }
    87 static inline void call_func2( void *ptr, int arg1, int arg2 )
    88 {
    89     PUSH_r32(arg2);
    90     PUSH_r32(arg1);
    91     call_func0(ptr);
    92     ADD_imm8s_r32( -4, R_ESP );
    93 }
    95 #define UNDEF()
    96 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
    97 #define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
    98 #define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
    99 #define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
   100 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
   101 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
   102 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
   105 /**
   106  * Emit the 'start of block' assembly. Sets up the stack frame and save
   107  * SI/DI as required
   108  */
   109 void sh4_translate_begin_block() {
   110     /* push ebp */
   111     *xlat_output++ = 0x50 + R_EBP;
   113     /* mov &sh4r, ebp */
   114     load_imm32( R_EBP, (uint32_t)&sh4r );
   116     /* load carry from SR */
   117 }
   119 /**
   120  * Flush any open regs back to memory, restore SI/DI/, update PC, etc
   121  */
   122 void sh4_translate_end_block( sh4addr_t pc ) {
   123     /* pop ebp */
   124     *xlat_output++ = 0x58 + R_EBP;
   126     /* ret */
   127     *xlat_output++ = 0xC3;
   128 }
   130 /**
   131  * Translate a single instruction. Delayed branches are handled specially
   132  * by translating both branch and delayed instruction as a single unit (as
   133  * 
   134  *
   135  * @return true if the instruction marks the end of a basic block
   136  * (eg a branch or 
   137  */
   138 uint32_t sh4_x86_translate_instruction( uint32_t pc )
   139 {
   140     uint16_t ir = sh4_read_word( pc );
   142 %%
   143 /* ALU operations */
   144 ADD Rm, Rn {:
   145     load_reg( R_EAX, Rm );
   146     load_reg( R_ECX, Rn );
   147     ADD_r32_r32( R_EAX, R_ECX );
   148     store_reg( R_ECX, Rn );
   149 :}
   150 ADD #imm, Rn {:  
   151     load_reg( R_EAX, Rn );
   152     ADD_imm8s_r32( imm, R_EAX );
   153     store_reg( R_EAX, Rn );
   154 :}
   155 ADDC Rm, Rn {:
   156     load_reg( R_EAX, Rm );
   157     load_reg( R_ECX, Rn );
   158     LDC_t();
   159     ADC_r32_r32( R_EAX, R_ECX );
   160     store_reg( R_ECX, Rn );
   161     SETC_t();
   162 :}
   163 ADDV Rm, Rn {:
   164     load_reg( R_EAX, Rm );
   165     load_reg( R_ECX, Rn );
   166     ADD_r32_r32( R_EAX, R_ECX );
   167     store_reg( R_ECX, Rn );
   168     SETO_t();
   169 :}
   170 AND Rm, Rn {:
   171     load_reg( R_EAX, Rm );
   172     load_reg( R_ECX, Rn );
   173     AND_r32_r32( R_EAX, R_ECX );
   174     store_reg( R_ECX, Rn );
   175 :}
   176 AND #imm, R0 {:  
   177     load_reg( R_EAX, 0 );
   178     AND_imm32_r32(imm, R_EAX); 
   179     store_reg( R_EAX, 0 );
   180 :}
   181 AND.B #imm, @(R0, GBR) {: 
   182     load_reg( R_EAX, 0 );
   183     load_spreg( R_ECX, R_GBR );
   184     ADD_r32_r32( R_EAX, R_EBX );
   185     MEM_READ_BYTE( R_ECX, R_EAX );
   186     AND_imm32_r32(imm, R_ECX );
   187     MEM_WRITE_BYTE( R_ECX, R_EAX );
   188 :}
   189 CMP/EQ Rm, Rn {:  
   190     load_reg( R_EAX, Rm );
   191     load_reg( R_ECX, Rn );
   192     CMP_r32_r32( R_EAX, R_ECX );
   193     SETE_t();
   194 :}
   195 CMP/EQ #imm, R0 {:  
   196     load_reg( R_EAX, 0 );
   197     CMP_imm8s_r32(imm, R_EAX);
   198     SETE_t();
   199 :}
   200 CMP/GE Rm, Rn {:  
   201     load_reg( R_EAX, Rm );
   202     load_reg( R_ECX, Rn );
   203     CMP_r32_r32( R_EAX, R_ECX );
   204     SETGE_t();
   205 :}
   206 CMP/GT Rm, Rn {: 
   207     load_reg( R_EAX, Rm );
   208     load_reg( R_ECX, Rn );
   209     CMP_r32_r32( R_EAX, R_ECX );
   210     SETG_t();
   211 :}
   212 CMP/HI Rm, Rn {:  
   213     load_reg( R_EAX, Rm );
   214     load_reg( R_ECX, Rn );
   215     CMP_r32_r32( R_EAX, R_ECX );
   216     SETA_t();
   217 :}
   218 CMP/HS Rm, Rn {: 
   219     load_reg( R_EAX, Rm );
   220     load_reg( R_ECX, Rn );
   221     CMP_r32_r32( R_EAX, R_ECX );
   222     SETAE_t();
   223  :}
   224 CMP/PL Rn {: 
   225     load_reg( R_EAX, Rn );
   226     CMP_imm8s_r32( 0, R_EAX );
   227     SETG_t();
   228 :}
   229 CMP/PZ Rn {:  
   230     load_reg( R_EAX, Rn );
   231     CMP_imm8s_r32( 0, R_EAX );
   232     SETGE_t();
   233 :}
   234 CMP/STR Rm, Rn {:  
   235 :}
   236 DIV0S Rm, Rn {:
   237     load_reg( R_EAX, Rm );
   238     load_reg( R_ECX, Rm );
   239     SHR_imm8_r32( 31, R_EAX );
   240     SHR_imm8_r32( 31, R_ECX );
   241     store_spreg( R_EAX, R_M );
   242     store_spreg( R_ECX, R_Q );
   243     CMP_r32_r32( R_EAX, R_ECX );
   244     SETE_t();
   245 :}
   246 DIV0U {:  
   247     XOR_r32_r32( R_EAX, R_EAX );
   248     store_spreg( R_EAX, R_Q );
   249     store_spreg( R_EAX, R_M );
   250     store_spreg( R_EAX, R_T );
   251 :}
   252 DIV1 Rm, Rn {:  :}
   253 DMULS.L Rm, Rn {:  
   254     load_reg( R_EAX, Rm );
   255     load_reg( R_ECX, Rn );
   256     IMUL_r32(R_ECX);
   257     store_spreg( R_EDX, R_MACH );
   258     store_spreg( R_EAX, R_MACL );
   259 :}
   260 DMULU.L Rm, Rn {:  
   261     load_reg( R_EAX, Rm );
   262     load_reg( R_ECX, Rn );
   263     MUL_r32(R_ECX);
   264     store_spreg( R_EDX, R_MACH );
   265     store_spreg( R_EAX, R_MACL );    
   266 :}
   267 DT Rn {:  
   268     load_reg( R_EAX, Rn );
   269     ADD_imm8s_r32( -1, Rn );
   270     store_reg( R_EAX, Rn );
   271     SETE_t();
   272 :}
   273 EXTS.B Rm, Rn {:  
   274     load_reg( R_EAX, Rm );
   275     MOVSX_r8_r32( R_EAX, R_EAX );
   276     store_reg( R_EAX, Rn );
   277 :}
   278 EXTS.W Rm, Rn {:  
   279     load_reg( R_EAX, Rm );
   280     MOVSX_r16_r32( R_EAX, R_EAX );
   281     store_reg( R_EAX, Rn );
   282 :}
   283 EXTU.B Rm, Rn {:  
   284     load_reg( R_EAX, Rm );
   285     MOVZX_r8_r32( R_EAX, R_EAX );
   286     store_reg( R_EAX, Rn );
   287 :}
   288 EXTU.W Rm, Rn {:  
   289     load_reg( R_EAX, Rm );
   290     MOVZX_r16_r32( R_EAX, R_EAX );
   291     store_reg( R_EAX, Rn );
   292 :}
   293 MAC.L @Rm+, @Rn+ {:  :}
   294 MAC.W @Rm+, @Rn+ {:  :}
   295 MOVT Rn {:  
   296     load_spreg( R_EAX, R_T );
   297     store_reg( R_EAX, Rn );
   298 :}
   299 MUL.L Rm, Rn {:  
   300     load_reg( R_EAX, Rm );
   301     load_reg( R_ECX, Rn );
   302     MUL_r32( R_ECX );
   303     store_spreg( R_EAX, R_MACL );
   304 :}
   305 MULS.W Rm, Rn {:  
   306 :}
   307 MULU.W Rm, Rn {:  :}
   308 NEG Rm, Rn {:
   309     load_reg( R_EAX, Rm );
   310     NEG_r32( R_EAX );
   311     store_reg( R_EAX, Rn );
   312 :}
   313 NEGC Rm, Rn {:  
   314     load_reg( R_EAX, Rm );
   315     XOR_r32_r32( R_ECX, R_ECX );
   316     LDC_t();
   317     SBB_r32_r32( R_EAX, R_ECX );
   318     store_reg( R_ECX, Rn );
   319     SETC_t();
   320 :}
   321 NOT Rm, Rn {:  
   322     load_reg( R_EAX, Rm );
   323     NOT_r32( R_EAX );
   324     store_reg( R_EAX, Rn );
   325 :}
   326 OR Rm, Rn {:  
   327     load_reg( R_EAX, Rm );
   328     load_reg( R_ECX, Rn );
   329     OR_r32_r32( R_EAX, R_ECX );
   330     store_reg( R_ECX, Rn );
   331 :}
   332 OR #imm, R0 {:
   333     load_reg( R_EAX, 0 );
   334     OR_imm32_r32(imm, R_EAX);
   335     store_reg( R_EAX, 0 );
   336 :}
   337 OR.B #imm, @(R0, GBR) {:  :}
   338 ROTCL Rn {:
   339     load_reg( R_EAX, Rn );
   340     LDC_t();
   341     RCL1_r32( R_EAX );
   342     store_reg( R_EAX, Rn );
   343     SETC_t();
   344 :}
   345 ROTCR Rn {:  
   346     load_reg( R_EAX, Rn );
   347     LDC_t();
   348     RCR1_r32( R_EAX );
   349     store_reg( R_EAX, Rn );
   350     SETC_t();
   351 :}
   352 ROTL Rn {:  
   353     load_reg( R_EAX, Rn );
   354     ROL1_r32( R_EAX );
   355     store_reg( R_EAX, Rn );
   356     SETC_t();
   357 :}
   358 ROTR Rn {:  
   359     load_reg( R_EAX, Rn );
   360     ROR1_r32( R_EAX );
   361     store_reg( R_EAX, Rn );
   362     SETC_t();
   363 :}
   364 SHAD Rm, Rn {:
   365     /* Annoyingly enough, not directly convertible */
   366     load_reg( R_EAX, Rn );
   367     load_reg( R_ECX, Rm );
   368     CMP_imm32_r32( 0, R_ECX );
   369     JAE_rel8(9);
   371     NEG_r32( R_ECX );      // 2
   372     AND_imm8_r8( 0x1F, R_CL ); // 3
   373     SAR_r32_CL( R_EAX );       // 2
   374     JMP_rel8(5);               // 2
   376     AND_imm8_r8( 0x1F, R_CL ); // 3
   377     SHL_r32_CL( R_EAX );       // 2
   379     store_reg( R_EAX, Rn );
   380 :}
   381 SHLD Rm, Rn {:  
   382 :}
   383 SHAL Rn {: 
   384     load_reg( R_EAX, Rn );
   385     SHL1_r32( R_EAX );
   386     store_reg( R_EAX, Rn );
   387 :}
   388 SHAR Rn {:  
   389     load_reg( R_EAX, Rn );
   390     SAR1_r32( R_EAX );
   391     store_reg( R_EAX, Rn );
   392 :}
   393 SHLL Rn {:  
   394     load_reg( R_EAX, Rn );
   395     SHL1_r32( R_EAX );
   396     store_reg( R_EAX, Rn );
   397 :}
   398 SHLL2 Rn {:
   399     load_reg( R_EAX, Rn );
   400     SHL_imm8_r32( 2, R_EAX );
   401     store_reg( R_EAX, Rn );
   402 :}
   403 SHLL8 Rn {:  
   404     load_reg( R_EAX, Rn );
   405     SHL_imm8_r32( 8, R_EAX );
   406     store_reg( R_EAX, Rn );
   407 :}
   408 SHLL16 Rn {:  
   409     load_reg( R_EAX, Rn );
   410     SHL_imm8_r32( 16, R_EAX );
   411     store_reg( R_EAX, Rn );
   412 :}
   413 SHLR Rn {:  
   414     load_reg( R_EAX, Rn );
   415     SHR1_r32( R_EAX );
   416     store_reg( R_EAX, Rn );
   417 :}
   418 SHLR2 Rn {:  
   419     load_reg( R_EAX, Rn );
   420     SHR_imm8_r32( 2, R_EAX );
   421     store_reg( R_EAX, Rn );
   422 :}
   423 SHLR8 Rn {:  
   424     load_reg( R_EAX, Rn );
   425     SHR_imm8_r32( 8, R_EAX );
   426     store_reg( R_EAX, Rn );
   427 :}
   428 SHLR16 Rn {:  
   429     load_reg( R_EAX, Rn );
   430     SHR_imm8_r32( 16, R_EAX );
   431     store_reg( R_EAX, Rn );
   432 :}
   433 SUB Rm, Rn {:  
   434     load_reg( R_EAX, Rm );
   435     load_reg( R_ECX, Rn );
   436     SUB_r32_r32( R_EAX, R_ECX );
   437     store_reg( R_ECX, Rn );
   438 :}
   439 SUBC Rm, Rn {:  
   440     load_reg( R_EAX, Rm );
   441     load_reg( R_ECX, Rn );
   442     LDC_t();
   443     SBB_r32_r32( R_EAX, R_ECX );
   444     store_reg( R_ECX, Rn );
   445 :}
   446 SUBV Rm, Rn {:  
   447     load_reg( R_EAX, Rm );
   448     load_reg( R_ECX, Rn );
   449     SUB_r32_r32( R_EAX, R_ECX );
   450     store_reg( R_ECX, Rn );
   451     SETO_t();
   452 :}
   453 SWAP.B Rm, Rn {:  
   454     load_reg( R_EAX, Rm );
   455     XCHG_r8_r8( R_AL, R_AH );
   456     store_reg( R_EAX, Rn );
   457 :}
   458 SWAP.W Rm, Rn {:  
   459     load_reg( R_EAX, Rm );
   460     MOV_r32_r32( R_EAX, R_ECX );
   461     SHL_imm8_r32( 16, R_ECX );
   462     SHR_imm8_r32( 16, R_EAX );
   463     OR_r32_r32( R_EAX, R_ECX );
   464     store_reg( R_ECX, Rn );
   465 :}
   466 TAS.B @Rn {:  
   467     load_reg( R_ECX, Rn );
   468     MEM_READ_BYTE( R_ECX, R_EAX );
   469     TEST_r8_r8( R_AL, R_AL );
   470     SETE_t();
   471     OR_imm8_r8( 0x80, R_AL );
   472     MEM_WRITE_BYTE( R_ECX, R_EAX );
   473 :}
   474 TST Rm, Rn {:  
   475     load_reg( R_EAX, Rm );
   476     load_reg( R_ECX, Rn );
   477     TEST_r32_r32( R_EAX, R_ECX );
   478     SETE_t();
   479 :}
   480 TST #imm, R0 {:  :}
   481 TST.B #imm, @(R0, GBR) {:  :}
   482 XOR Rm, Rn {:  
   483     load_reg( R_EAX, Rm );
   484     load_reg( R_ECX, Rn );
   485     XOR_r32_r32( R_EAX, R_ECX );
   486     store_reg( R_ECX, Rn );
   487 :}
   488 XOR #imm, R0 {:  
   489     load_reg( R_EAX, 0 );
   490     XOR_imm32_r32( imm, R_EAX );
   491     store_reg( R_EAX, 0 );
   492 :}
   493 XOR.B #imm, @(R0, GBR) {:  
   494     load_reg( R_EAX, 0 );
   495     load_spreg( R_ECX, R_GBR );
   496     ADD_r32_r32( R_EAX, R_ECX );
   497     MEM_READ_BYTE( R_ECX, R_EAX );
   498     XOR_imm32_r32( imm, R_EAX );
   499     MEM_WRITE_BYTE( R_ECX, R_EAX );
   500 :}
   501 XTRCT Rm, Rn {:
   502     load_reg( R_EAX, Rm );
   503     MOV_r32_r32( R_EAX, R_ECX );
   504     SHR_imm8_r32( 16, R_EAX );
   505     SHL_imm8_r32( 16, R_ECX );
   506     OR_r32_r32( R_EAX, R_ECX );
   507     store_reg( R_ECX, Rn );
   508 :}
   510 /* Data move instructions */
   511 MOV Rm, Rn {:  
   512     load_reg( R_EAX, Rm );
   513     store_reg( R_EAX, Rn );
   514 :}
   515 MOV #imm, Rn {:  
   516     load_imm32( R_EAX, imm );
   517     store_reg( R_EAX, Rn );
   518 :}
   519 MOV.B Rm, @Rn {:  
   520     load_reg( R_EAX, Rm );
   521     load_reg( R_ECX, Rn );
   522     MEM_WRITE_BYTE( R_ECX, R_EAX );
   523 :}
   524 MOV.B Rm, @-Rn {:  
   525     load_reg( R_EAX, Rm );
   526     load_reg( R_ECX, Rn );
   527     ADD_imm8s_r32( -1, Rn );
   528     store_reg( R_ECX, Rn );
   529     MEM_WRITE_BYTE( R_ECX, R_EAX );
   530 :}
   531 MOV.B Rm, @(R0, Rn) {:  
   532     load_reg( R_EAX, 0 );
   533     load_reg( R_ECX, Rn );
   534     ADD_r32_r32( R_EAX, R_ECX );
   535     load_reg( R_EAX, Rm );
   536     MEM_WRITE_BYTE( R_ECX, R_EAX );
   537 :}
   538 MOV.B R0, @(disp, GBR) {:  
   539     load_reg( R_EAX, 0 );
   540     load_spreg( R_ECX, R_GBR );
   541     ADD_imm32_r32( disp, R_ECX );
   542     MEM_WRITE_BYTE( R_ECX, R_EAX );
   543 :}
   544 MOV.B R0, @(disp, Rn) {:  
   545     load_reg( R_EAX, 0 );
   546     load_reg( R_ECX, Rn );
   547     ADD_imm32_r32( disp, R_ECX );
   548     MEM_WRITE_BYTE( R_ECX, R_EAX );
   549 :}
   550 MOV.B @Rm, Rn {:  
   551     load_reg( R_ECX, Rm );
   552     MEM_READ_BYTE( R_ECX, R_EAX );
   553     store_reg( R_ECX, Rn );
   554 :}
   555 MOV.B @Rm+, Rn {:  
   556     load_reg( R_ECX, Rm );
   557     MOV_r32_r32( R_ECX, R_EAX );
   558     ADD_imm8s_r32( 1, R_EAX );
   559     store_reg( R_EAX, Rm );
   560     MEM_READ_BYTE( R_ECX, R_EAX );
   561     store_reg( R_EAX, Rn );
   562 :}
   563 MOV.B @(R0, Rm), Rn {:  
   564     load_reg( R_EAX, 0 );
   565     load_reg( R_ECX, Rm );
   566     ADD_r32_r32( R_EAX, R_ECX );
   567     MEM_READ_BYTE( R_ECX, R_EAX );
   568     store_reg( R_EAX, Rn );
   569 :}
   570 MOV.B @(disp, GBR), R0 {:  
   571     load_spreg( R_ECX, R_GBR );
   572     ADD_imm32_r32( disp, R_ECX );
   573     MEM_READ_BYTE( R_ECX, R_EAX );
   574     store_reg( R_EAX, 0 );
   575 :}
   576 MOV.B @(disp, Rm), R0 {:  
   577     load_reg( R_ECX, Rm );
   578     ADD_imm32_r32( disp, R_ECX );
   579     MEM_READ_BYTE( R_ECX, R_EAX );
   580     store_reg( R_EAX, 0 );
   581 :}
   582 MOV.L Rm, @Rn {:  
   583     load_reg( R_EAX, Rm );
   584     load_reg( R_ECX, Rn );
   585     MEM_WRITE_LONG( R_ECX, R_EAX );
   586 :}
   587 MOV.L Rm, @-Rn {:  
   588     load_reg( R_EAX, Rm );
   589     load_reg( R_ECX, Rn );
   590     ADD_imm8s_r32( -4, R_ECX );
   591     store_reg( R_ECX, Rn );
   592     MEM_WRITE_LONG( R_ECX, R_EAX );
   593 :}
   594 MOV.L Rm, @(R0, Rn) {:  
   595     load_reg( R_EAX, 0 );
   596     load_reg( R_ECX, Rn );
   597     ADD_r32_r32( R_EAX, R_ECX );
   598     load_reg( R_EAX, Rm );
   599     MEM_WRITE_LONG( R_ECX, R_EAX );
   600 :}
   601 MOV.L R0, @(disp, GBR) {:  
   602     load_spreg( R_ECX, R_GBR );
   603     load_reg( R_EAX, 0 );
   604     ADD_imm32_r32( disp, R_ECX );
   605     MEM_WRITE_LONG( R_ECX, R_EAX );
   606 :}
   607 MOV.L Rm, @(disp, Rn) {:  
   608     load_reg( R_ECX, Rn );
   609     load_reg( R_EAX, Rm );
   610     ADD_imm32_r32( disp, R_ECX );
   611     MEM_WRITE_LONG( R_ECX, R_EAX );
   612 :}
   613 MOV.L @Rm, Rn {:  
   614     load_reg( R_ECX, Rm );
   615     MEM_READ_LONG( R_ECX, R_EAX );
   616     store_reg( R_EAX, Rn );
   617 :}
   618 MOV.L @Rm+, Rn {:  
   619     load_reg( R_EAX, Rm );
   620     MOV_r32_r32( R_EAX, R_ECX );
   621     ADD_imm8s_r32( 4, R_EAX );
   622     store_reg( R_EAX, Rm );
   623     MEM_READ_LONG( R_ECX, R_EAX );
   624     store_reg( R_EAX, Rn );
   625 :}
   626 MOV.L @(R0, Rm), Rn {:  
   627     load_reg( R_EAX, 0 );
   628     load_reg( R_ECX, Rm );
   629     ADD_r32_r32( R_EAX, R_ECX );
   630     MEM_READ_LONG( R_ECX, R_EAX );
   631     store_reg( R_EAX, Rn );
   632 :}
   633 MOV.L @(disp, GBR), R0 {:
   634     load_spreg( R_ECX, R_GBR );
   635     ADD_imm32_r32( disp, R_ECX );
   636     MEM_READ_LONG( R_ECX, R_EAX );
   637     store_reg( R_EAX, 0 );
   638 :}
   639 MOV.L @(disp, PC), Rn {:  
   640     load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
   641     MEM_READ_LONG( R_ECX, R_EAX );
   642     store_reg( R_EAX, 0 );
   643 :}
   644 MOV.L @(disp, Rm), Rn {:  
   645     load_reg( R_ECX, Rm );
   646     ADD_imm8s_r32( disp, R_ECX );
   647     MEM_READ_LONG( R_ECX, R_EAX );
   648     store_reg( R_EAX, Rn );
   649 :}
   650 MOV.W Rm, @Rn {:  
   651     load_reg( R_ECX, Rn );
   652     MEM_READ_WORD( R_ECX, R_EAX );
   653     store_reg( R_EAX, Rn );
   654 :}
   655 MOV.W Rm, @-Rn {:  
   656     load_reg( R_ECX, Rn );
   657     load_reg( R_EAX, Rm );
   658     ADD_imm8s_r32( -2, R_ECX );
   659     MEM_WRITE_WORD( R_ECX, R_EAX );
   660 :}
   661 MOV.W Rm, @(R0, Rn) {:  
   662     load_reg( R_EAX, 0 );
   663     load_reg( R_ECX, Rn );
   664     ADD_r32_r32( R_EAX, R_ECX );
   665     load_reg( R_EAX, Rm );
   666     MEM_WRITE_WORD( R_ECX, R_EAX );
   667 :}
   668 MOV.W R0, @(disp, GBR) {:  
   669     load_spreg( R_ECX, R_GBR );
   670     load_reg( R_EAX, 0 );
   671     ADD_imm32_r32( disp, R_ECX );
   672     MEM_WRITE_WORD( R_ECX, R_EAX );
   673 :}
   674 MOV.W R0, @(disp, Rn) {:  
   675     load_reg( R_ECX, Rn );
   676     load_reg( R_EAX, 0 );
   677     ADD_imm32_r32( disp, R_ECX );
   678     MEM_WRITE_WORD( R_ECX, R_EAX );
   679 :}
   680 MOV.W @Rm, Rn {:  
   681     load_reg( R_ECX, Rm );
   682     MEM_READ_WORD( R_ECX, R_EAX );
   683     store_reg( R_EAX, Rn );
   684 :}
   685 MOV.W @Rm+, Rn {:  
   686     load_reg( R_EAX, Rm );
   687     MOV_r32_r32( R_EAX, R_ECX );
   688     ADD_imm8s_r32( 2, R_EAX );
   689     store_reg( R_EAX, Rm );
   690     MEM_READ_WORD( R_ECX, R_EAX );
   691     store_reg( R_EAX, Rn );
   692 :}
   693 MOV.W @(R0, Rm), Rn {:  
   694     load_reg( R_EAX, 0 );
   695     load_reg( R_ECX, Rm );
   696     ADD_r32_r32( R_EAX, R_ECX );
   697     MEM_READ_WORD( R_ECX, R_EAX );
   698     store_reg( R_EAX, Rn );
   699 :}
   700 MOV.W @(disp, GBR), R0 {:  
   701     load_spreg( R_ECX, R_GBR );
   702     ADD_imm32_r32( disp, R_ECX );
   703     MEM_READ_WORD( R_ECX, R_EAX );
   704     store_reg( R_EAX, 0 );
   705 :}
   706 MOV.W @(disp, PC), Rn {:  
   707     load_imm32( R_ECX, pc + disp + 4 );
   708     MEM_READ_WORD( R_ECX, R_EAX );
   709     store_reg( R_EAX, Rn );
   710 :}
   711 MOV.W @(disp, Rm), R0 {:  
   712     load_reg( R_ECX, Rm );
   713     ADD_imm32_r32( disp, R_ECX );
   714     MEM_READ_WORD( R_ECX, R_EAX );
   715     store_reg( R_EAX, 0 );
   716 :}
   717 MOVA @(disp, PC), R0 {:  
   718     load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
   719     store_reg( R_ECX, 0 );
   720 :}
   721 MOVCA.L R0, @Rn {:  
   722     load_reg( R_EAX, 0 );
   723     load_reg( R_ECX, Rn );
   724     MEM_WRITE_LONG( R_ECX, R_EAX );
   725 :}
   727 /* Control transfer instructions */
   728 BF disp {:  :}
   729 BF/S disp {:  :}
   730 BRA disp {:  :}
   731 BRAF Rn {:  :}
   732 BSR disp {:  :}
   733 BSRF Rn {:  :}
   734 BT disp {:  /* If true, result PC += 4 + disp. else result PC = pc+2 */
   735     return pc + 2;
   736 :}
   737 BT/S disp {:
   739     return pc + 4;
   740 :}
   741 JMP @Rn {:  :}
   742 JSR @Rn {:  :}
   743 RTE {:  :}
   744 RTS {:  :}
   745 TRAPA #imm {:  :}
   746 UNDEF {:  :}
   748 CLRMAC {:  :}
   749 CLRS {:  :}
   750 CLRT {:  :}
   751 SETS {:  :}
   752 SETT {:  :}
   754 /* Floating point instructions */
   755 FABS FRn {:  :}
   756 FADD FRm, FRn {:  :}
   757 FCMP/EQ FRm, FRn {:  :}
   758 FCMP/GT FRm, FRn {:  :}
   759 FCNVDS FRm, FPUL {:  :}
   760 FCNVSD FPUL, FRn {:  :}
   761 FDIV FRm, FRn {:  :}
   762 FIPR FVm, FVn {:  :}
   763 FLDS FRm, FPUL {:  :}
   764 FLDI0 FRn {:  :}
   765 FLDI1 FRn {:  :}
   766 FLOAT FPUL, FRn {:  :}
   767 FMAC FR0, FRm, FRn {:  :}
   768 FMOV FRm, FRn {:  :}
   769 FMOV FRm, @Rn {:  :}
   770 FMOV FRm, @-Rn {:  :}
   771 FMOV FRm, @(R0, Rn) {:  :}
   772 FMOV @Rm, FRn {:  :}
   773 FMOV @Rm+, FRn {:  :}
   774 FMOV @(R0, Rm), FRn {:  :}
   775 FMUL FRm, FRn {:  :}
   776 FNEG FRn {:  :}
   777 FRCHG {:  :}
   778 FSCA FPUL, FRn {:  :}
   779 FSCHG {:  :}
   780 FSQRT FRn {:  :}
   781 FSRRA FRn {:  :}
   782 FSTS FPUL, FRn {:  :}
   783 FSUB FRm, FRn {:  :}
   784 FTRC FRm, FPUL {:  :}
   785 FTRV XMTRX, FVn {:  :}
   787 /* Processor control instructions */
   788 LDC Rm, SR {: /* We need to be a little careful about SR */ :}
   789 LDC Rm, GBR {: 
   790     load_reg( R_EAX, Rm );
   791     store_spreg( R_EAX, R_GBR );
   792 :}
   793 LDC Rm, VBR {:  
   794     load_reg( R_EAX, Rm );
   795     store_spreg( R_EAX, R_VBR );
   796 :}
   797 LDC Rm, SSR {:  
   798     load_reg( R_EAX, Rm );
   799     store_spreg( R_EAX, R_SSR );
   800 :}
   801 LDC Rm, SGR {:  
   802     load_reg( R_EAX, Rm );
   803     store_spreg( R_EAX, R_SGR );
   804 :}
   805 LDC Rm, SPC {:  
   806     load_reg( R_EAX, Rm );
   807     store_spreg( R_EAX, R_SPC );
   808 :}
   809 LDC Rm, DBR {:  
   810     load_reg( R_EAX, Rm );
   811     store_spreg( R_EAX, R_DBR );
   812 :}
   813 LDC Rm, Rn_BANK {:  :}
   814 LDC.L @Rm+, GBR {:  
   815     load_reg( R_EAX, Rm );
   816     MOV_r32_r32( R_EAX, R_ECX );
   817     ADD_imm8s_r32( 4, R_EAX );
   818     store_reg( R_EAX, Rm );
   819     MEM_READ_LONG( R_ECX, R_EAX );
   820     store_spreg( R_EAX, R_GBR );
   821 :}
   822 LDC.L @Rm+, SR {:  
   823 :}
   824 LDC.L @Rm+, VBR {:  
   825     load_reg( R_EAX, Rm );
   826     MOV_r32_r32( R_EAX, R_ECX );
   827     ADD_imm8s_r32( 4, R_EAX );
   828     store_reg( R_EAX, Rm );
   829     MEM_READ_LONG( R_ECX, R_EAX );
   830     store_spreg( R_EAX, R_VBR );
   831 :}
   832 LDC.L @Rm+, SSR {:
   833     load_reg( R_EAX, Rm );
   834     MOV_r32_r32( R_EAX, R_ECX );
   835     ADD_imm8s_r32( 4, R_EAX );
   836     store_reg( R_EAX, Rm );
   837     MEM_READ_LONG( R_ECX, R_EAX );
   838     store_spreg( R_EAX, R_SSR );
   839 :}
   840 LDC.L @Rm+, SGR {:  
   841     load_reg( R_EAX, Rm );
   842     MOV_r32_r32( R_EAX, R_ECX );
   843     ADD_imm8s_r32( 4, R_EAX );
   844     store_reg( R_EAX, Rm );
   845     MEM_READ_LONG( R_ECX, R_EAX );
   846     store_spreg( R_EAX, R_SGR );
   847 :}
   848 LDC.L @Rm+, SPC {:  
   849     load_reg( R_EAX, Rm );
   850     MOV_r32_r32( R_EAX, R_ECX );
   851     ADD_imm8s_r32( 4, R_EAX );
   852     store_reg( R_EAX, Rm );
   853     MEM_READ_LONG( R_ECX, R_EAX );
   854     store_spreg( R_EAX, R_SPC );
   855 :}
   856 LDC.L @Rm+, DBR {:  
   857     load_reg( R_EAX, Rm );
   858     MOV_r32_r32( R_EAX, R_ECX );
   859     ADD_imm8s_r32( 4, R_EAX );
   860     store_reg( R_EAX, Rm );
   861     MEM_READ_LONG( R_ECX, R_EAX );
   862     store_spreg( R_EAX, R_DBR );
   863 :}
   864 LDC.L @Rm+, Rn_BANK {:  
   865 :}
   866 LDS Rm, FPSCR {:  
   867     load_reg( R_EAX, Rm );
   868     store_spreg( R_EAX, R_FPSCR );
   869 :}
   870 LDS.L @Rm+, FPSCR {:  
   871     load_reg( R_EAX, Rm );
   872     MOV_r32_r32( R_EAX, R_ECX );
   873     ADD_imm8s_r32( 4, R_EAX );
   874     store_reg( R_EAX, Rm );
   875     MEM_READ_LONG( R_ECX, R_EAX );
   876     store_spreg( R_EAX, R_FPSCR );
   877 :}
   878 LDS Rm, FPUL {:  
   879     load_reg( R_EAX, Rm );
   880     store_spreg( R_EAX, R_FPUL );
   881 :}
   882 LDS.L @Rm+, FPUL {:  
   883     load_reg( R_EAX, Rm );
   884     MOV_r32_r32( R_EAX, R_ECX );
   885     ADD_imm8s_r32( 4, R_EAX );
   886     store_reg( R_EAX, Rm );
   887     MEM_READ_LONG( R_ECX, R_EAX );
   888     store_spreg( R_EAX, R_FPUL );
   889 :}
   890 LDS Rm, MACH {: 
   891     load_reg( R_EAX, Rm );
   892     store_spreg( R_EAX, R_MACH );
   893 :}
   894 LDS.L @Rm+, MACH {:  
   895     load_reg( R_EAX, Rm );
   896     MOV_r32_r32( R_EAX, R_ECX );
   897     ADD_imm8s_r32( 4, R_EAX );
   898     store_reg( R_EAX, Rm );
   899     MEM_READ_LONG( R_ECX, R_EAX );
   900     store_spreg( R_EAX, R_MACH );
   901 :}
   902 LDS Rm, MACL {:  
   903     load_reg( R_EAX, Rm );
   904     store_spreg( R_EAX, R_MACL );
   905 :}
   906 LDS.L @Rm+, MACL {:  
   907     load_reg( R_EAX, Rm );
   908     MOV_r32_r32( R_EAX, R_ECX );
   909     ADD_imm8s_r32( 4, R_EAX );
   910     store_reg( R_EAX, Rm );
   911     MEM_READ_LONG( R_ECX, R_EAX );
   912     store_spreg( R_EAX, R_MACL );
   913 :}
   914 LDS Rm, PR {:  
   915     load_reg( R_EAX, Rm );
   916     store_spreg( R_EAX, R_PR );
   917 :}
   918 LDS.L @Rm+, PR {:  
   919     load_reg( R_EAX, Rm );
   920     MOV_r32_r32( R_EAX, R_ECX );
   921     ADD_imm8s_r32( 4, R_EAX );
   922     store_reg( R_EAX, Rm );
   923     MEM_READ_LONG( R_ECX, R_EAX );
   924     store_spreg( R_EAX, R_PR );
   925 :}
   926 LDTLB {:  :}
   927 OCBI @Rn {:  :}
   928 OCBP @Rn {:  :}
   929 OCBWB @Rn {:  :}
   930 PREF @Rn {:  :}
   931 SLEEP {:  :}
   932  STC SR, Rn {:  /* TODO */
   933 :}
   934 STC GBR, Rn {:  
   935     load_spreg( R_EAX, R_GBR );
   936     store_reg( R_EAX, Rn );
   937 :}
   938 STC VBR, Rn {:  
   939     load_spreg( R_EAX, R_VBR );
   940     store_reg( R_EAX, Rn );
   941 :}
   942 STC SSR, Rn {:  
   943     load_spreg( R_EAX, R_SSR );
   944     store_reg( R_EAX, Rn );
   945 :}
   946 STC SPC, Rn {:  
   947     load_spreg( R_EAX, R_SPC );
   948     store_reg( R_EAX, Rn );
   949 :}
   950 STC SGR, Rn {:  
   951     load_spreg( R_EAX, R_SGR );
   952     store_reg( R_EAX, Rn );
   953 :}
   954 STC DBR, Rn {:  
   955     load_spreg( R_EAX, R_DBR );
   956     store_reg( R_EAX, Rn );
   957 :}
   958  STC Rm_BANK, Rn {: /* TODO */ 
   959 :}
   960  STC.L SR, @-Rn {:  /* TODO */
   961 :}
   962 STC.L VBR, @-Rn {:  
   963     load_reg( R_ECX, Rn );
   964     ADD_imm8s_r32( -4, Rn );
   965     store_reg( R_ECX, Rn );
   966     load_spreg( R_EAX, R_VBR );
   967     MEM_WRITE_LONG( R_ECX, R_EAX );
   968 :}
   969 STC.L SSR, @-Rn {:  
   970     load_reg( R_ECX, Rn );
   971     ADD_imm8s_r32( -4, Rn );
   972     store_reg( R_ECX, Rn );
   973     load_spreg( R_EAX, R_SSR );
   974     MEM_WRITE_LONG( R_ECX, R_EAX );
   975 :}
   976 STC.L SPC, @-Rn {:  
   977     load_reg( R_ECX, Rn );
   978     ADD_imm8s_r32( -4, Rn );
   979     store_reg( R_ECX, Rn );
   980     load_spreg( R_EAX, R_SPC );
   981     MEM_WRITE_LONG( R_ECX, R_EAX );
   982 :}
   983 STC.L SGR, @-Rn {:  
   984     load_reg( R_ECX, Rn );
   985     ADD_imm8s_r32( -4, Rn );
   986     store_reg( R_ECX, Rn );
   987     load_spreg( R_EAX, R_SGR );
   988     MEM_WRITE_LONG( R_ECX, R_EAX );
   989 :}
   990 STC.L DBR, @-Rn {:  
   991     load_reg( R_ECX, Rn );
   992     ADD_imm8s_r32( -4, Rn );
   993     store_reg( R_ECX, Rn );
   994     load_spreg( R_EAX, R_DBR );
   995     MEM_WRITE_LONG( R_ECX, R_EAX );
   996 :}
   997 STC.L Rm_BANK, @-Rn {:  :}
   998 STC.L GBR, @-Rn {:  
   999     load_reg( R_ECX, Rn );
  1000     ADD_imm8s_r32( -4, Rn );
  1001     store_reg( R_ECX, Rn );
  1002     load_spreg( R_EAX, R_GBR );
  1003     MEM_WRITE_LONG( R_ECX, R_EAX );
  1004 :}
  1005 STS FPSCR, Rn {:  
  1006     load_spreg( R_EAX, R_FPSCR );
  1007     store_reg( R_EAX, Rn );
  1008 :}
  1009 STS.L FPSCR, @-Rn {:  
  1010     load_reg( R_ECX, Rn );
  1011     ADD_imm8s_r32( -4, Rn );
  1012     store_reg( R_ECX, Rn );
  1013     load_spreg( R_EAX, R_FPSCR );
  1014     MEM_WRITE_LONG( R_ECX, R_EAX );
  1015 :}
  1016 STS FPUL, Rn {:  
  1017     load_spreg( R_EAX, R_FPUL );
  1018     store_reg( R_EAX, Rn );
  1019 :}
  1020 STS.L FPUL, @-Rn {:  
  1021     load_reg( R_ECX, Rn );
  1022     ADD_imm8s_r32( -4, Rn );
  1023     store_reg( R_ECX, Rn );
  1024     load_spreg( R_EAX, R_FPUL );
  1025     MEM_WRITE_LONG( R_ECX, R_EAX );
  1026 :}
  1027 STS MACH, Rn {:  
  1028     load_spreg( R_EAX, R_MACH );
  1029     store_reg( R_EAX, Rn );
  1030 :}
  1031 STS.L MACH, @-Rn {:  
  1032     load_reg( R_ECX, Rn );
  1033     ADD_imm8s_r32( -4, Rn );
  1034     store_reg( R_ECX, Rn );
  1035     load_spreg( R_EAX, R_MACH );
  1036     MEM_WRITE_LONG( R_ECX, R_EAX );
  1037 :}
  1038 STS MACL, Rn {:  
  1039     load_spreg( R_EAX, R_MACL );
  1040     store_reg( R_EAX, Rn );
  1041 :}
  1042 STS.L MACL, @-Rn {:  
  1043     load_reg( R_ECX, Rn );
  1044     ADD_imm8s_r32( -4, Rn );
  1045     store_reg( R_ECX, Rn );
  1046     load_spreg( R_EAX, R_MACL );
  1047     MEM_WRITE_LONG( R_ECX, R_EAX );
  1048 :}
  1049 STS PR, Rn {:  
  1050     load_spreg( R_EAX, R_PR );
  1051     store_reg( R_EAX, Rn );
  1052 :}
  1053 STS.L PR, @-Rn {:  
  1054     load_reg( R_ECX, Rn );
  1055     ADD_imm8s_r32( -4, Rn );
  1056     store_reg( R_ECX, Rn );
  1057     load_spreg( R_EAX, R_PR );
  1058     MEM_WRITE_LONG( R_ECX, R_EAX );
  1059 :}
  1061 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}
  1062 %%
  1064     return 0;
.