Search
lxdream.org :: lxdream/src/sh4/sh4x86.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4x86.c
changeset 361:be3de4ecd954
prev359:c588dce7ebde
next368:36fac4c42322
author nkeynes
date Tue Aug 28 08:46:14 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Translator WIP: fill out and correct another batch of instructions
file annotate diff log raw
1.1 --- a/src/sh4/sh4x86.c Thu Aug 23 12:33:27 2007 +0000
1.2 +++ b/src/sh4/sh4x86.c Tue Aug 28 08:46:14 2007 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: sh4x86.c,v 1.1 2007-08-23 12:33:27 nkeynes Exp $
1.6 + * $Id: sh4x86.c,v 1.2 2007-08-28 08:46:14 nkeynes Exp $
1.7 *
1.8 * SH4 => x86 translation. This version does no real optimization, it just
1.9 * outputs straight-line x86 code - it mainly exists to provide a baseline
1.10 @@ -28,27 +28,19 @@
1.11 static inline void load_reg( int x86reg, int sh4reg )
1.12 {
1.13 /* mov [bp+n], reg */
1.14 - OP(0x89);
1.15 - OP(0x45 + x86reg<<3);
1.16 + OP(0x8B);
1.17 + OP(0x45 + (x86reg<<3));
1.18 OP(REG_OFFSET(r[sh4reg]));
1.19 }
1.20
1.21 static inline void load_spreg( int x86reg, int regoffset )
1.22 {
1.23 /* mov [bp+n], reg */
1.24 - OP(0x89);
1.25 - OP(0x45 + x86reg<<3);
1.26 + OP(0x8B);
1.27 + OP(0x45 + (x86reg<<3));
1.28 OP(regoffset);
1.29 }
1.30
1.31 -#define UNDEF()
1.32 -#define MEM_READ_BYTE( addr_reg, value_reg )
1.33 -#define MEM_READ_WORD( addr_reg, value_reg )
1.34 -#define MEM_READ_LONG( addr_reg, value_reg )
1.35 -#define MEM_WRITE_BYTE( addr_reg, value_reg )
1.36 -#define MEM_WRITE_WORD( addr_reg, value_reg )
1.37 -#define MEM_WRITE_LONG( addr_reg, value_reg )
1.38 -
1.39 /**
1.40 * Emit an instruction to load an immediate value into a register
1.41 */
1.42 @@ -63,17 +55,52 @@
1.43 */
1.44 void static inline store_reg( int x86reg, int sh4reg ) {
1.45 /* mov reg, [bp+n] */
1.46 - OP(0x8B);
1.47 - OP(0x45 + x86reg<<3);
1.48 + OP(0x89);
1.49 + OP(0x45 + (x86reg<<3));
1.50 OP(REG_OFFSET(r[sh4reg]));
1.51 }
1.52 void static inline store_spreg( int x86reg, int regoffset ) {
1.53 /* mov reg, [bp+n] */
1.54 - OP(0x8B);
1.55 - OP(0x45 + x86reg<<3);
1.56 + OP(0x89);
1.57 + OP(0x45 + (x86reg<<3));
1.58 OP(regoffset);
1.59 }
1.60
1.61 +/**
1.62 + * Note: clobbers EAX to make the indirect call - this isn't usually
1.63 + * a problem since the callee will usually clobber it anyway.
1.64 + */
1.65 +static inline void call_func0( void *ptr )
1.66 +{
1.67 + load_imm32(R_EAX, (uint32_t)ptr);
1.68 + OP(0xFF);
1.69 + MODRM_rm32_r32(R_EAX, 2);
1.70 +}
1.71 +
1.72 +static inline void call_func1( void *ptr, int arg1 )
1.73 +{
1.74 + PUSH_r32(arg1);
1.75 + call_func0(ptr);
1.76 + ADD_imm8s_r32( -4, R_ESP );
1.77 +}
1.78 +
1.79 +static inline void call_func2( void *ptr, int arg1, int arg2 )
1.80 +{
1.81 + PUSH_r32(arg2);
1.82 + PUSH_r32(arg1);
1.83 + call_func0(ptr);
1.84 + ADD_imm8s_r32( -4, R_ESP );
1.85 +}
1.86 +
1.87 +#define UNDEF()
1.88 +#define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
1.89 +#define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
1.90 +#define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
1.91 +#define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
1.92 +#define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
1.93 +#define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
1.94 +#define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
1.95 +
1.96
1.97 /**
1.98 * Emit the 'start of block' assembly. Sets up the stack frame and save
1.99 @@ -110,7 +137,7 @@
1.100 */
1.101 uint32_t sh4_x86_translate_instruction( uint32_t pc )
1.102 {
1.103 - uint16_t ir = 0;
1.104 + uint16_t ir = sh4_read_word( pc );
1.105
1.106 switch( (ir&0xF000) >> 12 ) {
1.107 case 0x0:
1.108 @@ -201,6 +228,9 @@
1.109 case 0xC:
1.110 { /* MOVCA.L R0, @Rn */
1.111 uint32_t Rn = ((ir>>8)&0xF);
1.112 + load_reg( R_EAX, 0 );
1.113 + load_reg( R_ECX, Rn );
1.114 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.115 }
1.116 break;
1.117 default:
1.118 @@ -221,16 +251,30 @@
1.119 case 0x5:
1.120 { /* MOV.W Rm, @(R0, Rn) */
1.121 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.122 + load_reg( R_EAX, 0 );
1.123 + load_reg( R_ECX, Rn );
1.124 + ADD_r32_r32( R_EAX, R_ECX );
1.125 + load_reg( R_EAX, Rm );
1.126 + MEM_WRITE_WORD( R_ECX, R_EAX );
1.127 }
1.128 break;
1.129 case 0x6:
1.130 { /* MOV.L Rm, @(R0, Rn) */
1.131 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.132 + load_reg( R_EAX, 0 );
1.133 + load_reg( R_ECX, Rn );
1.134 + ADD_r32_r32( R_EAX, R_ECX );
1.135 + load_reg( R_EAX, Rm );
1.136 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.137 }
1.138 break;
1.139 case 0x7:
1.140 { /* MUL.L Rm, Rn */
1.141 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.142 + load_reg( R_EAX, Rm );
1.143 + load_reg( R_ECX, Rn );
1.144 + MUL_r32( R_ECX );
1.145 + store_spreg( R_EAX, R_MACL );
1.146 }
1.147 break;
1.148 case 0x8:
1.149 @@ -273,6 +317,10 @@
1.150 break;
1.151 case 0x1:
1.152 { /* DIV0U */
1.153 + XOR_r32_r32( R_EAX, R_EAX );
1.154 + store_spreg( R_EAX, R_Q );
1.155 + store_spreg( R_EAX, R_M );
1.156 + store_spreg( R_EAX, R_T );
1.157 }
1.158 break;
1.159 case 0x2:
1.160 @@ -375,11 +423,21 @@
1.161 case 0xD:
1.162 { /* MOV.W @(R0, Rm), Rn */
1.163 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.164 + load_reg( R_EAX, 0 );
1.165 + load_reg( R_ECX, Rm );
1.166 + ADD_r32_r32( R_EAX, R_ECX );
1.167 + MEM_READ_WORD( R_ECX, R_EAX );
1.168 + store_reg( R_EAX, Rn );
1.169 }
1.170 break;
1.171 case 0xE:
1.172 { /* MOV.L @(R0, Rm), Rn */
1.173 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.174 + load_reg( R_EAX, 0 );
1.175 + load_reg( R_ECX, Rm );
1.176 + ADD_r32_r32( R_EAX, R_ECX );
1.177 + MEM_READ_LONG( R_ECX, R_EAX );
1.178 + store_reg( R_EAX, Rn );
1.179 }
1.180 break;
1.181 case 0xF:
1.182 @@ -395,6 +453,10 @@
1.183 case 0x1:
1.184 { /* MOV.L Rm, @(disp, Rn) */
1.185 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<2;
1.186 + load_reg( R_ECX, Rn );
1.187 + load_reg( R_EAX, Rm );
1.188 + ADD_imm32_r32( disp, R_ECX );
1.189 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.190 }
1.191 break;
1.192 case 0x2:
1.193 @@ -410,11 +472,17 @@
1.194 case 0x1:
1.195 { /* MOV.W Rm, @Rn */
1.196 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.197 + load_reg( R_ECX, Rn );
1.198 + MEM_READ_WORD( R_ECX, R_EAX );
1.199 + store_reg( R_EAX, Rn );
1.200 }
1.201 break;
1.202 case 0x2:
1.203 { /* MOV.L Rm, @Rn */
1.204 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.205 + load_reg( R_EAX, Rm );
1.206 + load_reg( R_ECX, Rn );
1.207 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.208 }
1.209 break;
1.210 case 0x4:
1.211 @@ -430,21 +498,42 @@
1.212 case 0x5:
1.213 { /* MOV.W Rm, @-Rn */
1.214 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.215 + load_reg( R_ECX, Rn );
1.216 + load_reg( R_EAX, Rm );
1.217 + ADD_imm8s_r32( -2, R_ECX );
1.218 + MEM_WRITE_WORD( R_ECX, R_EAX );
1.219 }
1.220 break;
1.221 case 0x6:
1.222 { /* MOV.L Rm, @-Rn */
1.223 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.224 + load_reg( R_EAX, Rm );
1.225 + load_reg( R_ECX, Rn );
1.226 + ADD_imm8s_r32( -4, R_ECX );
1.227 + store_reg( R_ECX, Rn );
1.228 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.229 }
1.230 break;
1.231 case 0x7:
1.232 { /* DIV0S Rm, Rn */
1.233 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.234 + load_reg( R_EAX, Rm );
1.235 + load_reg( R_ECX, Rm );
1.236 + SHR_imm8_r32( 31, R_EAX );
1.237 + SHR_imm8_r32( 31, R_ECX );
1.238 + store_spreg( R_EAX, R_M );
1.239 + store_spreg( R_ECX, R_Q );
1.240 + CMP_r32_r32( R_EAX, R_ECX );
1.241 + SETE_t();
1.242 }
1.243 break;
1.244 case 0x8:
1.245 { /* TST Rm, Rn */
1.246 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.247 + load_reg( R_EAX, Rm );
1.248 + load_reg( R_ECX, Rn );
1.249 + TEST_r32_r32( R_EAX, R_ECX );
1.250 + SETE_t();
1.251 }
1.252 break;
1.253 case 0x9:
1.254 @@ -482,6 +571,12 @@
1.255 case 0xD:
1.256 { /* XTRCT Rm, Rn */
1.257 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.258 + load_reg( R_EAX, Rm );
1.259 + MOV_r32_r32( R_EAX, R_ECX );
1.260 + SHR_imm8_r32( 16, R_EAX );
1.261 + SHL_imm8_r32( 16, R_ECX );
1.262 + OR_r32_r32( R_EAX, R_ECX );
1.263 + store_reg( R_ECX, Rn );
1.264 }
1.265 break;
1.266 case 0xE:
1.267 @@ -536,6 +631,11 @@
1.268 case 0x5:
1.269 { /* DMULU.L Rm, Rn */
1.270 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.271 + load_reg( R_EAX, Rm );
1.272 + load_reg( R_ECX, Rn );
1.273 + MUL_r32(R_ECX);
1.274 + store_spreg( R_EDX, R_MACH );
1.275 + store_spreg( R_EAX, R_MACL );
1.276 }
1.277 break;
1.278 case 0x6:
1.279 @@ -597,6 +697,11 @@
1.280 case 0xD:
1.281 { /* DMULS.L Rm, Rn */
1.282 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.283 + load_reg( R_EAX, Rm );
1.284 + load_reg( R_ECX, Rn );
1.285 + IMUL_r32(R_ECX);
1.286 + store_spreg( R_EDX, R_MACH );
1.287 + store_spreg( R_EAX, R_MACL );
1.288 }
1.289 break;
1.290 case 0xE:
1.291 @@ -1166,6 +1271,12 @@
1.292 case 0x1:
1.293 { /* TAS.B @Rn */
1.294 uint32_t Rn = ((ir>>8)&0xF);
1.295 + load_reg( R_ECX, Rn );
1.296 + MEM_READ_BYTE( R_ECX, R_EAX );
1.297 + TEST_r8_r8( R_AL, R_AL );
1.298 + SETE_t();
1.299 + OR_imm8_r8( 0x80, R_AL );
1.300 + MEM_WRITE_BYTE( R_ECX, R_EAX );
1.301 }
1.302 break;
1.303 case 0x2:
1.304 @@ -1182,6 +1293,20 @@
1.305 { /* SHAD Rm, Rn */
1.306 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.307 /* Annoyingly enough, not directly convertible */
1.308 + load_reg( R_EAX, Rn );
1.309 + load_reg( R_ECX, Rm );
1.310 + CMP_imm32_r32( 0, R_ECX );
1.311 + JAE_rel8(9);
1.312 +
1.313 + NEG_r32( R_ECX ); // 2
1.314 + AND_imm8_r8( 0x1F, R_CL ); // 3
1.315 + SAR_r32_CL( R_EAX ); // 2
1.316 + JMP_rel8(5); // 2
1.317 +
1.318 + AND_imm8_r8( 0x1F, R_CL ); // 3
1.319 + SHL_r32_CL( R_EAX ); // 2
1.320 +
1.321 + store_reg( R_EAX, Rn );
1.322 }
1.323 break;
1.324 case 0xD:
1.325 @@ -1249,6 +1374,10 @@
1.326 case 0x5:
1.327 { /* MOV.L @(disp, Rm), Rn */
1.328 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<2;
1.329 + load_reg( R_ECX, Rm );
1.330 + ADD_imm8s_r32( disp, R_ECX );
1.331 + MEM_READ_LONG( R_ECX, R_EAX );
1.332 + store_reg( R_EAX, Rn );
1.333 }
1.334 break;
1.335 case 0x6:
1.336 @@ -1264,11 +1393,17 @@
1.337 case 0x1:
1.338 { /* MOV.W @Rm, Rn */
1.339 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.340 + load_reg( R_ECX, Rm );
1.341 + MEM_READ_WORD( R_ECX, R_EAX );
1.342 + store_reg( R_EAX, Rn );
1.343 }
1.344 break;
1.345 case 0x2:
1.346 { /* MOV.L @Rm, Rn */
1.347 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.348 + load_reg( R_ECX, Rm );
1.349 + MEM_READ_LONG( R_ECX, R_EAX );
1.350 + store_reg( R_EAX, Rn );
1.351 }
1.352 break;
1.353 case 0x3:
1.354 @@ -1292,11 +1427,23 @@
1.355 case 0x5:
1.356 { /* MOV.W @Rm+, Rn */
1.357 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.358 + load_reg( R_EAX, Rm );
1.359 + MOV_r32_r32( R_EAX, R_ECX );
1.360 + ADD_imm8s_r32( 2, R_EAX );
1.361 + store_reg( R_EAX, Rm );
1.362 + MEM_READ_WORD( R_ECX, R_EAX );
1.363 + store_reg( R_EAX, Rn );
1.364 }
1.365 break;
1.366 case 0x6:
1.367 { /* MOV.L @Rm+, Rn */
1.368 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.369 + load_reg( R_EAX, Rm );
1.370 + MOV_r32_r32( R_EAX, R_ECX );
1.371 + ADD_imm8s_r32( 4, R_EAX );
1.372 + store_reg( R_EAX, Rm );
1.373 + MEM_READ_LONG( R_ECX, R_EAX );
1.374 + store_reg( R_EAX, Rn );
1.375 }
1.376 break;
1.377 case 0x7:
1.378 @@ -1348,11 +1495,17 @@
1.379 case 0xC:
1.380 { /* EXTU.B Rm, Rn */
1.381 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.382 + load_reg( R_EAX, Rm );
1.383 + MOVZX_r8_r32( R_EAX, R_EAX );
1.384 + store_reg( R_EAX, Rn );
1.385 }
1.386 break;
1.387 case 0xD:
1.388 { /* EXTU.W Rm, Rn */
1.389 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.390 + load_reg( R_EAX, Rm );
1.391 + MOVZX_r16_r32( R_EAX, R_EAX );
1.392 + store_reg( R_EAX, Rn );
1.393 }
1.394 break;
1.395 case 0xE:
1.396 @@ -1366,6 +1519,9 @@
1.397 case 0xF:
1.398 { /* EXTS.W Rm, Rn */
1.399 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.400 + load_reg( R_EAX, Rm );
1.401 + MOVSX_r16_r32( R_EAX, R_EAX );
1.402 + store_reg( R_EAX, Rn );
1.403 }
1.404 break;
1.405 }
1.406 @@ -1392,6 +1548,10 @@
1.407 case 0x1:
1.408 { /* MOV.W R0, @(disp, Rn) */
1.409 uint32_t Rn = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<1;
1.410 + load_reg( R_ECX, Rn );
1.411 + load_reg( R_EAX, 0 );
1.412 + ADD_imm32_r32( disp, R_ECX );
1.413 + MEM_WRITE_WORD( R_ECX, R_EAX );
1.414 }
1.415 break;
1.416 case 0x4:
1.417 @@ -1406,6 +1566,10 @@
1.418 case 0x5:
1.419 { /* MOV.W @(disp, Rm), R0 */
1.420 uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<1;
1.421 + load_reg( R_ECX, Rm );
1.422 + ADD_imm32_r32( disp, R_ECX );
1.423 + MEM_READ_WORD( R_ECX, R_EAX );
1.424 + store_reg( R_EAX, 0 );
1.425 }
1.426 break;
1.427 case 0x8:
1.428 @@ -1447,6 +1611,9 @@
1.429 case 0x9:
1.430 { /* MOV.W @(disp, PC), Rn */
1.431 uint32_t Rn = ((ir>>8)&0xF); uint32_t disp = (ir&0xFF)<<1;
1.432 + load_imm32( R_ECX, pc + disp + 4 );
1.433 + MEM_READ_WORD( R_ECX, R_EAX );
1.434 + store_reg( R_EAX, Rn );
1.435 }
1.436 break;
1.437 case 0xA:
1.438 @@ -1473,11 +1640,19 @@
1.439 case 0x1:
1.440 { /* MOV.W R0, @(disp, GBR) */
1.441 uint32_t disp = (ir&0xFF)<<1;
1.442 + load_spreg( R_ECX, R_GBR );
1.443 + load_reg( R_EAX, 0 );
1.444 + ADD_imm32_r32( disp, R_ECX );
1.445 + MEM_WRITE_WORD( R_ECX, R_EAX );
1.446 }
1.447 break;
1.448 case 0x2:
1.449 { /* MOV.L R0, @(disp, GBR) */
1.450 uint32_t disp = (ir&0xFF)<<2;
1.451 + load_spreg( R_ECX, R_GBR );
1.452 + load_reg( R_EAX, 0 );
1.453 + ADD_imm32_r32( disp, R_ECX );
1.454 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.455 }
1.456 break;
1.457 case 0x3:
1.458 @@ -1497,16 +1672,26 @@
1.459 case 0x5:
1.460 { /* MOV.W @(disp, GBR), R0 */
1.461 uint32_t disp = (ir&0xFF)<<1;
1.462 + load_spreg( R_ECX, R_GBR );
1.463 + ADD_imm32_r32( disp, R_ECX );
1.464 + MEM_READ_WORD( R_ECX, R_EAX );
1.465 + store_reg( R_EAX, 0 );
1.466 }
1.467 break;
1.468 case 0x6:
1.469 { /* MOV.L @(disp, GBR), R0 */
1.470 uint32_t disp = (ir&0xFF)<<2;
1.471 + load_spreg( R_ECX, R_GBR );
1.472 + ADD_imm32_r32( disp, R_ECX );
1.473 + MEM_READ_LONG( R_ECX, R_EAX );
1.474 + store_reg( R_EAX, 0 );
1.475 }
1.476 break;
1.477 case 0x7:
1.478 { /* MOVA @(disp, PC), R0 */
1.479 uint32_t disp = (ir&0xFF)<<2;
1.480 + load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1.481 + store_reg( R_ECX, 0 );
1.482 }
1.483 break;
1.484 case 0x8:
1.485 @@ -1517,8 +1702,6 @@
1.486 case 0x9:
1.487 { /* AND #imm, R0 */
1.488 uint32_t imm = (ir&0xFF);
1.489 - // Note: x86 AND imm8 sign-extends, SH4 version zero-extends. So
1.490 - // need to use the imm32 version
1.491 load_reg( R_EAX, 0 );
1.492 AND_imm32_r32(imm, R_EAX);
1.493 store_reg( R_EAX, 0 );
1.494 @@ -1577,6 +1760,9 @@
1.495 case 0xD:
1.496 { /* MOV.L @(disp, PC), Rn */
1.497 uint32_t Rn = ((ir>>8)&0xF); uint32_t disp = (ir&0xFF)<<2;
1.498 + load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1.499 + MEM_READ_LONG( R_ECX, R_EAX );
1.500 + store_reg( R_EAX, 0 );
1.501 }
1.502 break;
1.503 case 0xE:
.