Search
lxdream.org :: lxdream :: r361:be3de4ecd954
lxdream 0.9.1
released Jun 29
Download Now
changeset361:be3de4ecd954
parent360:dff4a3bbac0c
child362:dc40e2064dc4
authornkeynes
dateTue Aug 28 08:46:14 2007 +0000 (16 years ago)
Translator WIP: fill out and correct another batch of instructions
src/sh4/sh4x86.c
src/sh4/sh4x86.in
src/sh4/x86op.h
1.1 --- a/src/sh4/sh4x86.c Thu Aug 23 12:34:43 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:
2.1 --- a/src/sh4/sh4x86.in Thu Aug 23 12:34:43 2007 +0000
2.2 +++ b/src/sh4/sh4x86.in Tue Aug 28 08:46:14 2007 +0000
2.3 @@ -1,5 +1,5 @@
2.4 /**
2.5 - * $Id: sh4x86.in,v 1.1 2007-08-23 12:33:27 nkeynes Exp $
2.6 + * $Id: sh4x86.in,v 1.2 2007-08-28 08:46:14 nkeynes Exp $
2.7 *
2.8 * SH4 => x86 translation. This version does no real optimization, it just
2.9 * outputs straight-line x86 code - it mainly exists to provide a baseline
2.10 @@ -28,27 +28,19 @@
2.11 static inline void load_reg( int x86reg, int sh4reg )
2.12 {
2.13 /* mov [bp+n], reg */
2.14 - OP(0x89);
2.15 - OP(0x45 + x86reg<<3);
2.16 + OP(0x8B);
2.17 + OP(0x45 + (x86reg<<3));
2.18 OP(REG_OFFSET(r[sh4reg]));
2.19 }
2.20
2.21 static inline void load_spreg( int x86reg, int regoffset )
2.22 {
2.23 /* mov [bp+n], reg */
2.24 - OP(0x89);
2.25 - OP(0x45 + x86reg<<3);
2.26 + OP(0x8B);
2.27 + OP(0x45 + (x86reg<<3));
2.28 OP(regoffset);
2.29 }
2.30
2.31 -#define UNDEF()
2.32 -#define MEM_READ_BYTE( addr_reg, value_reg )
2.33 -#define MEM_READ_WORD( addr_reg, value_reg )
2.34 -#define MEM_READ_LONG( addr_reg, value_reg )
2.35 -#define MEM_WRITE_BYTE( addr_reg, value_reg )
2.36 -#define MEM_WRITE_WORD( addr_reg, value_reg )
2.37 -#define MEM_WRITE_LONG( addr_reg, value_reg )
2.38 -
2.39 /**
2.40 * Emit an instruction to load an immediate value into a register
2.41 */
2.42 @@ -63,17 +55,52 @@
2.43 */
2.44 void static inline store_reg( int x86reg, int sh4reg ) {
2.45 /* mov reg, [bp+n] */
2.46 - OP(0x8B);
2.47 - OP(0x45 + x86reg<<3);
2.48 + OP(0x89);
2.49 + OP(0x45 + (x86reg<<3));
2.50 OP(REG_OFFSET(r[sh4reg]));
2.51 }
2.52 void static inline store_spreg( int x86reg, int regoffset ) {
2.53 /* mov reg, [bp+n] */
2.54 - OP(0x8B);
2.55 - OP(0x45 + x86reg<<3);
2.56 + OP(0x89);
2.57 + OP(0x45 + (x86reg<<3));
2.58 OP(regoffset);
2.59 }
2.60
2.61 +/**
2.62 + * Note: clobbers EAX to make the indirect call - this isn't usually
2.63 + * a problem since the callee will usually clobber it anyway.
2.64 + */
2.65 +static inline void call_func0( void *ptr )
2.66 +{
2.67 + load_imm32(R_EAX, (uint32_t)ptr);
2.68 + OP(0xFF);
2.69 + MODRM_rm32_r32(R_EAX, 2);
2.70 +}
2.71 +
2.72 +static inline void call_func1( void *ptr, int arg1 )
2.73 +{
2.74 + PUSH_r32(arg1);
2.75 + call_func0(ptr);
2.76 + ADD_imm8s_r32( -4, R_ESP );
2.77 +}
2.78 +
2.79 +static inline void call_func2( void *ptr, int arg1, int arg2 )
2.80 +{
2.81 + PUSH_r32(arg2);
2.82 + PUSH_r32(arg1);
2.83 + call_func0(ptr);
2.84 + ADD_imm8s_r32( -4, R_ESP );
2.85 +}
2.86 +
2.87 +#define UNDEF()
2.88 +#define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
2.89 +#define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
2.90 +#define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
2.91 +#define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
2.92 +#define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
2.93 +#define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
2.94 +#define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
2.95 +
2.96
2.97 /**
2.98 * Emit the 'start of block' assembly. Sets up the stack frame and save
2.99 @@ -110,7 +137,7 @@
2.100 */
2.101 uint32_t sh4_x86_translate_instruction( uint32_t pc )
2.102 {
2.103 - uint16_t ir = 0;
2.104 + uint16_t ir = sh4_read_word( pc );
2.105
2.106 %%
2.107 /* ALU operations */
2.108 @@ -147,8 +174,6 @@
2.109 store_reg( R_ECX, Rn );
2.110 :}
2.111 AND #imm, R0 {:
2.112 - // Note: x86 AND imm8 sign-extends, SH4 version zero-extends. So
2.113 - // need to use the imm32 version
2.114 load_reg( R_EAX, 0 );
2.115 AND_imm32_r32(imm, R_EAX);
2.116 store_reg( R_EAX, 0 );
2.117 @@ -206,12 +231,39 @@
2.118 CMP_imm8s_r32( 0, R_EAX );
2.119 SETGE_t();
2.120 :}
2.121 -CMP/STR Rm, Rn {: :}
2.122 -DIV0S Rm, Rn {: :}
2.123 -DIV0U {: :}
2.124 +CMP/STR Rm, Rn {:
2.125 +:}
2.126 +DIV0S Rm, Rn {:
2.127 + load_reg( R_EAX, Rm );
2.128 + load_reg( R_ECX, Rm );
2.129 + SHR_imm8_r32( 31, R_EAX );
2.130 + SHR_imm8_r32( 31, R_ECX );
2.131 + store_spreg( R_EAX, R_M );
2.132 + store_spreg( R_ECX, R_Q );
2.133 + CMP_r32_r32( R_EAX, R_ECX );
2.134 + SETE_t();
2.135 +:}
2.136 +DIV0U {:
2.137 + XOR_r32_r32( R_EAX, R_EAX );
2.138 + store_spreg( R_EAX, R_Q );
2.139 + store_spreg( R_EAX, R_M );
2.140 + store_spreg( R_EAX, R_T );
2.141 +:}
2.142 DIV1 Rm, Rn {: :}
2.143 -DMULS.L Rm, Rn {: :}
2.144 -DMULU.L Rm, Rn {: :}
2.145 +DMULS.L Rm, Rn {:
2.146 + load_reg( R_EAX, Rm );
2.147 + load_reg( R_ECX, Rn );
2.148 + IMUL_r32(R_ECX);
2.149 + store_spreg( R_EDX, R_MACH );
2.150 + store_spreg( R_EAX, R_MACL );
2.151 +:}
2.152 +DMULU.L Rm, Rn {:
2.153 + load_reg( R_EAX, Rm );
2.154 + load_reg( R_ECX, Rn );
2.155 + MUL_r32(R_ECX);
2.156 + store_spreg( R_EDX, R_MACH );
2.157 + store_spreg( R_EAX, R_MACL );
2.158 +:}
2.159 DT Rn {:
2.160 load_reg( R_EAX, Rn );
2.161 ADD_imm8s_r32( -1, Rn );
2.162 @@ -223,17 +275,35 @@
2.163 MOVSX_r8_r32( R_EAX, R_EAX );
2.164 store_reg( R_EAX, Rn );
2.165 :}
2.166 -EXTS.W Rm, Rn {: :}
2.167 -EXTU.B Rm, Rn {: :}
2.168 -EXTU.W Rm, Rn {: :}
2.169 +EXTS.W Rm, Rn {:
2.170 + load_reg( R_EAX, Rm );
2.171 + MOVSX_r16_r32( R_EAX, R_EAX );
2.172 + store_reg( R_EAX, Rn );
2.173 +:}
2.174 +EXTU.B Rm, Rn {:
2.175 + load_reg( R_EAX, Rm );
2.176 + MOVZX_r8_r32( R_EAX, R_EAX );
2.177 + store_reg( R_EAX, Rn );
2.178 +:}
2.179 +EXTU.W Rm, Rn {:
2.180 + load_reg( R_EAX, Rm );
2.181 + MOVZX_r16_r32( R_EAX, R_EAX );
2.182 + store_reg( R_EAX, Rn );
2.183 +:}
2.184 MAC.L @Rm+, @Rn+ {: :}
2.185 MAC.W @Rm+, @Rn+ {: :}
2.186 MOVT Rn {:
2.187 load_spreg( R_EAX, R_T );
2.188 store_reg( R_EAX, Rn );
2.189 :}
2.190 -MUL.L Rm, Rn {: :}
2.191 -MULS.W Rm, Rn {: :}
2.192 +MUL.L Rm, Rn {:
2.193 + load_reg( R_EAX, Rm );
2.194 + load_reg( R_ECX, Rn );
2.195 + MUL_r32( R_ECX );
2.196 + store_spreg( R_EAX, R_MACL );
2.197 +:}
2.198 +MULS.W Rm, Rn {:
2.199 +:}
2.200 MULU.W Rm, Rn {: :}
2.201 NEG Rm, Rn {:
2.202 load_reg( R_EAX, Rm );
2.203 @@ -293,6 +363,20 @@
2.204 :}
2.205 SHAD Rm, Rn {:
2.206 /* Annoyingly enough, not directly convertible */
2.207 + load_reg( R_EAX, Rn );
2.208 + load_reg( R_ECX, Rm );
2.209 + CMP_imm32_r32( 0, R_ECX );
2.210 + JAE_rel8(9);
2.211 +
2.212 + NEG_r32( R_ECX ); // 2
2.213 + AND_imm8_r8( 0x1F, R_CL ); // 3
2.214 + SAR_r32_CL( R_EAX ); // 2
2.215 + JMP_rel8(5); // 2
2.216 +
2.217 + AND_imm8_r8( 0x1F, R_CL ); // 3
2.218 + SHL_r32_CL( R_EAX ); // 2
2.219 +
2.220 + store_reg( R_EAX, Rn );
2.221 :}
2.222 SHLD Rm, Rn {:
2.223 :}
2.224 @@ -379,8 +463,20 @@
2.225 OR_r32_r32( R_EAX, R_ECX );
2.226 store_reg( R_ECX, Rn );
2.227 :}
2.228 -TAS.B @Rn {: :}
2.229 -TST Rm, Rn {: :}
2.230 +TAS.B @Rn {:
2.231 + load_reg( R_ECX, Rn );
2.232 + MEM_READ_BYTE( R_ECX, R_EAX );
2.233 + TEST_r8_r8( R_AL, R_AL );
2.234 + SETE_t();
2.235 + OR_imm8_r8( 0x80, R_AL );
2.236 + MEM_WRITE_BYTE( R_ECX, R_EAX );
2.237 +:}
2.238 +TST Rm, Rn {:
2.239 + load_reg( R_EAX, Rm );
2.240 + load_reg( R_ECX, Rn );
2.241 + TEST_r32_r32( R_EAX, R_ECX );
2.242 + SETE_t();
2.243 +:}
2.244 TST #imm, R0 {: :}
2.245 TST.B #imm, @(R0, GBR) {: :}
2.246 XOR Rm, Rn {:
2.247 @@ -402,7 +498,13 @@
2.248 XOR_imm32_r32( imm, R_EAX );
2.249 MEM_WRITE_BYTE( R_ECX, R_EAX );
2.250 :}
2.251 -XTRCT Rm, Rn {:
2.252 +XTRCT Rm, Rn {:
2.253 + load_reg( R_EAX, Rm );
2.254 + MOV_r32_r32( R_EAX, R_ECX );
2.255 + SHR_imm8_r32( 16, R_EAX );
2.256 + SHL_imm8_r32( 16, R_ECX );
2.257 + OR_r32_r32( R_EAX, R_ECX );
2.258 + store_reg( R_ECX, Rn );
2.259 :}
2.260
2.261 /* Data move instructions */
2.262 @@ -477,30 +579,150 @@
2.263 MEM_READ_BYTE( R_ECX, R_EAX );
2.264 store_reg( R_EAX, 0 );
2.265 :}
2.266 -MOV.L Rm, @Rn {: :}
2.267 -MOV.L Rm, @-Rn {: :}
2.268 -MOV.L Rm, @(R0, Rn) {: :}
2.269 -MOV.L R0, @(disp, GBR) {: :}
2.270 -MOV.L Rm, @(disp, Rn) {: :}
2.271 -MOV.L @Rm, Rn {: :}
2.272 -MOV.L @Rm+, Rn {: :}
2.273 -MOV.L @(R0, Rm), Rn {: :}
2.274 -MOV.L @(disp, GBR), R0 {: :}
2.275 -MOV.L @(disp, PC), Rn {: :}
2.276 -MOV.L @(disp, Rm), Rn {: :}
2.277 -MOV.W Rm, @Rn {: :}
2.278 -MOV.W Rm, @-Rn {: :}
2.279 -MOV.W Rm, @(R0, Rn) {: :}
2.280 -MOV.W R0, @(disp, GBR) {: :}
2.281 -MOV.W R0, @(disp, Rn) {: :}
2.282 -MOV.W @Rm, Rn {: :}
2.283 -MOV.W @Rm+, Rn {: :}
2.284 -MOV.W @(R0, Rm), Rn {: :}
2.285 -MOV.W @(disp, GBR), R0 {: :}
2.286 -MOV.W @(disp, PC), Rn {: :}
2.287 -MOV.W @(disp, Rm), R0 {: :}
2.288 -MOVA @(disp, PC), R0 {: :}
2.289 -MOVCA.L R0, @Rn {: :}
2.290 +MOV.L Rm, @Rn {:
2.291 + load_reg( R_EAX, Rm );
2.292 + load_reg( R_ECX, Rn );
2.293 + MEM_WRITE_LONG( R_ECX, R_EAX );
2.294 +:}
2.295 +MOV.L Rm, @-Rn {:
2.296 + load_reg( R_EAX, Rm );
2.297 + load_reg( R_ECX, Rn );
2.298 + ADD_imm8s_r32( -4, R_ECX );
2.299 + store_reg( R_ECX, Rn );
2.300 + MEM_WRITE_LONG( R_ECX, R_EAX );
2.301 +:}
2.302 +MOV.L Rm, @(R0, Rn) {:
2.303 + load_reg( R_EAX, 0 );
2.304 + load_reg( R_ECX, Rn );
2.305 + ADD_r32_r32( R_EAX, R_ECX );
2.306 + load_reg( R_EAX, Rm );
2.307 + MEM_WRITE_LONG( R_ECX, R_EAX );
2.308 +:}
2.309 +MOV.L R0, @(disp, GBR) {:
2.310 + load_spreg( R_ECX, R_GBR );
2.311 + load_reg( R_EAX, 0 );
2.312 + ADD_imm32_r32( disp, R_ECX );
2.313 + MEM_WRITE_LONG( R_ECX, R_EAX );
2.314 +:}
2.315 +MOV.L Rm, @(disp, Rn) {:
2.316 + load_reg( R_ECX, Rn );
2.317 + load_reg( R_EAX, Rm );
2.318 + ADD_imm32_r32( disp, R_ECX );
2.319 + MEM_WRITE_LONG( R_ECX, R_EAX );
2.320 +:}
2.321 +MOV.L @Rm, Rn {:
2.322 + load_reg( R_ECX, Rm );
2.323 + MEM_READ_LONG( R_ECX, R_EAX );
2.324 + store_reg( R_EAX, Rn );
2.325 +:}
2.326 +MOV.L @Rm+, Rn {:
2.327 + load_reg( R_EAX, Rm );
2.328 + MOV_r32_r32( R_EAX, R_ECX );
2.329 + ADD_imm8s_r32( 4, R_EAX );
2.330 + store_reg( R_EAX, Rm );
2.331 + MEM_READ_LONG( R_ECX, R_EAX );
2.332 + store_reg( R_EAX, Rn );
2.333 +:}
2.334 +MOV.L @(R0, Rm), Rn {:
2.335 + load_reg( R_EAX, 0 );
2.336 + load_reg( R_ECX, Rm );
2.337 + ADD_r32_r32( R_EAX, R_ECX );
2.338 + MEM_READ_LONG( R_ECX, R_EAX );
2.339 + store_reg( R_EAX, Rn );
2.340 +:}
2.341 +MOV.L @(disp, GBR), R0 {:
2.342 + load_spreg( R_ECX, R_GBR );
2.343 + ADD_imm32_r32( disp, R_ECX );
2.344 + MEM_READ_LONG( R_ECX, R_EAX );
2.345 + store_reg( R_EAX, 0 );
2.346 +:}
2.347 +MOV.L @(disp, PC), Rn {:
2.348 + load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
2.349 + MEM_READ_LONG( R_ECX, R_EAX );
2.350 + store_reg( R_EAX, 0 );
2.351 +:}
2.352 +MOV.L @(disp, Rm), Rn {:
2.353 + load_reg( R_ECX, Rm );
2.354 + ADD_imm8s_r32( disp, R_ECX );
2.355 + MEM_READ_LONG( R_ECX, R_EAX );
2.356 + store_reg( R_EAX, Rn );
2.357 +:}
2.358 +MOV.W Rm, @Rn {:
2.359 + load_reg( R_ECX, Rn );
2.360 + MEM_READ_WORD( R_ECX, R_EAX );
2.361 + store_reg( R_EAX, Rn );
2.362 +:}
2.363 +MOV.W Rm, @-Rn {:
2.364 + load_reg( R_ECX, Rn );
2.365 + load_reg( R_EAX, Rm );
2.366 + ADD_imm8s_r32( -2, R_ECX );
2.367 + MEM_WRITE_WORD( R_ECX, R_EAX );
2.368 +:}
2.369 +MOV.W Rm, @(R0, Rn) {:
2.370 + load_reg( R_EAX, 0 );
2.371 + load_reg( R_ECX, Rn );
2.372 + ADD_r32_r32( R_EAX, R_ECX );
2.373 + load_reg( R_EAX, Rm );
2.374 + MEM_WRITE_WORD( R_ECX, R_EAX );
2.375 +:}
2.376 +MOV.W R0, @(disp, GBR) {:
2.377 + load_spreg( R_ECX, R_GBR );
2.378 + load_reg( R_EAX, 0 );
2.379 + ADD_imm32_r32( disp, R_ECX );
2.380 + MEM_WRITE_WORD( R_ECX, R_EAX );
2.381 +:}
2.382 +MOV.W R0, @(disp, Rn) {:
2.383 + load_reg( R_ECX, Rn );
2.384 + load_reg( R_EAX, 0 );
2.385 + ADD_imm32_r32( disp, R_ECX );
2.386 + MEM_WRITE_WORD( R_ECX, R_EAX );
2.387 +:}
2.388 +MOV.W @Rm, Rn {:
2.389 + load_reg( R_ECX, Rm );
2.390 + MEM_READ_WORD( R_ECX, R_EAX );
2.391 + store_reg( R_EAX, Rn );
2.392 +:}
2.393 +MOV.W @Rm+, Rn {:
2.394 + load_reg( R_EAX, Rm );
2.395 + MOV_r32_r32( R_EAX, R_ECX );
2.396 + ADD_imm8s_r32( 2, R_EAX );
2.397 + store_reg( R_EAX, Rm );
2.398 + MEM_READ_WORD( R_ECX, R_EAX );
2.399 + store_reg( R_EAX, Rn );
2.400 +:}
2.401 +MOV.W @(R0, Rm), Rn {:
2.402 + load_reg( R_EAX, 0 );
2.403 + load_reg( R_ECX, Rm );
2.404 + ADD_r32_r32( R_EAX, R_ECX );
2.405 + MEM_READ_WORD( R_ECX, R_EAX );
2.406 + store_reg( R_EAX, Rn );
2.407 +:}
2.408 +MOV.W @(disp, GBR), R0 {:
2.409 + load_spreg( R_ECX, R_GBR );
2.410 + ADD_imm32_r32( disp, R_ECX );
2.411 + MEM_READ_WORD( R_ECX, R_EAX );
2.412 + store_reg( R_EAX, 0 );
2.413 +:}
2.414 +MOV.W @(disp, PC), Rn {:
2.415 + load_imm32( R_ECX, pc + disp + 4 );
2.416 + MEM_READ_WORD( R_ECX, R_EAX );
2.417 + store_reg( R_EAX, Rn );
2.418 +:}
2.419 +MOV.W @(disp, Rm), R0 {:
2.420 + load_reg( R_ECX, Rm );
2.421 + ADD_imm32_r32( disp, R_ECX );
2.422 + MEM_READ_WORD( R_ECX, R_EAX );
2.423 + store_reg( R_EAX, 0 );
2.424 +:}
2.425 +MOVA @(disp, PC), R0 {:
2.426 + load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
2.427 + store_reg( R_ECX, 0 );
2.428 +:}
2.429 +MOVCA.L R0, @Rn {:
2.430 + load_reg( R_EAX, 0 );
2.431 + load_reg( R_ECX, Rn );
2.432 + MEM_WRITE_LONG( R_ECX, R_EAX );
2.433 +:}
2.434
2.435 /* Control transfer instructions */
2.436 BF disp {: :}
3.1 --- a/src/sh4/x86op.h Thu Aug 23 12:34:43 2007 +0000
3.2 +++ b/src/sh4/x86op.h Tue Aug 28 08:46:14 2007 +0000
3.3 @@ -1,5 +1,5 @@
3.4 /**
3.5 - * $Id: x86op.h,v 1.1 2007-08-23 12:33:27 nkeynes Exp $
3.6 + * $Id: x86op.h,v 1.2 2007-08-28 08:46:14 nkeynes Exp $
3.7 *
3.8 * Definitions of x86 opcodes for use by the translator.
3.9 *
3.10 @@ -39,13 +39,16 @@
3.11 #define R_BH 7
3.12
3.13
3.14 -#define OP(x) *xlat_output++ = x
3.15 -#define OP32(x) *((uint32_t *)xlat_output) = x; xlat_output+=2
3.16 +#define OP(x) *xlat_output++ = (x)
3.17 +#define OP32(x) *((uint32_t *)xlat_output) = (x); xlat_output+=4
3.18
3.19 /* Offset of a reg relative to the sh4r structure */
3.20 #define REG_OFFSET(reg) (((char *)&sh4r.reg) - ((char *)&sh4r))
3.21
3.22 #define R_T REG_OFFSET(t)
3.23 +#define R_Q REG_OFFSET(q)
3.24 +#define R_S REG_OFFSET(s)
3.25 +#define R_M REG_OFFSET(m)
3.26 #define R_GBR REG_OFFSET(gbr)
3.27 #define R_SSR REG_OFFSET(ssr)
3.28 #define R_SPC REG_OFFSET(spc)
3.29 @@ -82,6 +85,7 @@
3.30 #define CMC() OP(0xF5)
3.31 #define CMP_r32_r32(r1,r2) OP(0x3B); MODRM_rm32_r32(r1,r2)
3.32 #define CMP_imm8s_r32(imm,r1) OP(0x83); MODRM_rm32_r32(r1,7); OP(imm)
3.33 +#define JMP_rel8(rel) OP(0xEB); OP(rel)
3.34 #define MOV_r32_ebp8(r1,disp) OP(0x89); MODRM_r32_ebp8(r1,disp)
3.35 #define MOV_r32_ebp32(r1,disp) OP(0x89); MODRM_r32_ebp32(r1,disp)
3.36 #define MOV_ebp8_r32(r1,disp) OP(0x8B); MODRM_r32_ebp8(r1,disp)
3.37 @@ -94,6 +98,7 @@
3.38 #define NOT_r32(r1) OP(0xF7); MODRM_rm32_r32(r1,2)
3.39 #define OR_r32_r32(r1,r2) OP(0x0B); MODRM_rm32_r32(r1,r2)
3.40 #define OR_imm32_r32(imm,r1) OP(0x81); MODRM_rm32_r32(r1,1); OP32(imm)
3.41 +#define PUSH_r32(r1) OP(0x50 + r1)
3.42 #define RCL1_r32(r1) OP(0xD1); MODRM_rm32_r32(r1,2)
3.43 #define RCR1_r32(r1) OP(0xD1); MODRM_rm32_r32(r1,3)
3.44 #define RET() OP(0xC3)
3.45 @@ -112,9 +117,18 @@
3.46 #define XOR_r32_r32(r1,r2) OP(0x33); MODRM_rm32_r32(r1,r2)
3.47 #define XOR_imm32_r32(imm,r1) OP(0x81); MODRM_rm32_r32(r1,6); OP32(imm)
3.48
3.49 -#define ADD_imm32_r32(imm32,r1)
3.50 -#define MOV_r32_r32(r1,r2)
3.51 -#define XCHG_r8_r8(r1,r2)
3.52 +#define ADD_imm32_r32(imm32,r1) OP(0x81); MODRM_rm32_r32(r1,0); OP32(imm32)
3.53 +#define AND_imm8_r8(imm8, r1) OP(0x80); MODRM_rm32_r32(r1,4); OP(imm8)
3.54 +#define CMP_imm32_r32(imm32, r1) OP(0x81); MODRM_rm32_r32(r1,7); OP32(imm32)
3.55 +#define MOV_r32_r32(r1,r2) OP(0x89); MODRM_r32_rm32(r1,r2)
3.56 +#define MUL_r32(r1) OP(0xF7); MODRM_rm32_r32(r1,4)
3.57 +#define IMUL_r32(r1) OP(0xF7); MODRM_rm32_r32(r1,5)
3.58 +#define OR_imm8_r8(imm,r1) OP(0x80); MODRM_rm32_r32(r1,1)
3.59 +#define TEST_r8_r8(r1,r2) OP(0x84); MODRM_r32_rm32(r1,r2)
3.60 +#define SAR_r32_CL(r1) OP(0xD3); MODRM_rm32_r32(r1,7)
3.61 +#define SHR_r32_CL(r1) OP(0xD3); MODRM_rm32_r32(r1,5)
3.62 +#define SHL_r32_CL(r1) OP(0xD3); MODRM_rm32_r32(r1,4)
3.63 +#define XCHG_r8_r8(r1,r2) OP(0x86); MODRM_rm32_r32(r1,r2)
3.64
3.65 /* Conditional branches */
3.66 #define JE_rel8(rel) OP(0x74); OP(rel)
.