Search
lxdream.org :: lxdream/src/sh4/sh4x86.in :: diff
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 (12 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.in Thu Aug 23 12:33:27 2007 +0000
1.2 +++ b/src/sh4/sh4x86.in Tue Aug 28 08:46:14 2007 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: sh4x86.in,v 1.1 2007-08-23 12:33:27 nkeynes Exp $
1.6 + * $Id: sh4x86.in,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 %%
1.107 /* ALU operations */
1.108 @@ -147,8 +174,6 @@
1.109 store_reg( R_ECX, Rn );
1.110 :}
1.111 AND #imm, R0 {:
1.112 - // Note: x86 AND imm8 sign-extends, SH4 version zero-extends. So
1.113 - // need to use the imm32 version
1.114 load_reg( R_EAX, 0 );
1.115 AND_imm32_r32(imm, R_EAX);
1.116 store_reg( R_EAX, 0 );
1.117 @@ -206,12 +231,39 @@
1.118 CMP_imm8s_r32( 0, R_EAX );
1.119 SETGE_t();
1.120 :}
1.121 -CMP/STR Rm, Rn {: :}
1.122 -DIV0S Rm, Rn {: :}
1.123 -DIV0U {: :}
1.124 +CMP/STR Rm, Rn {:
1.125 +:}
1.126 +DIV0S Rm, Rn {:
1.127 + load_reg( R_EAX, Rm );
1.128 + load_reg( R_ECX, Rm );
1.129 + SHR_imm8_r32( 31, R_EAX );
1.130 + SHR_imm8_r32( 31, R_ECX );
1.131 + store_spreg( R_EAX, R_M );
1.132 + store_spreg( R_ECX, R_Q );
1.133 + CMP_r32_r32( R_EAX, R_ECX );
1.134 + SETE_t();
1.135 +:}
1.136 +DIV0U {:
1.137 + XOR_r32_r32( R_EAX, R_EAX );
1.138 + store_spreg( R_EAX, R_Q );
1.139 + store_spreg( R_EAX, R_M );
1.140 + store_spreg( R_EAX, R_T );
1.141 +:}
1.142 DIV1 Rm, Rn {: :}
1.143 -DMULS.L Rm, Rn {: :}
1.144 -DMULU.L Rm, Rn {: :}
1.145 +DMULS.L Rm, Rn {:
1.146 + load_reg( R_EAX, Rm );
1.147 + load_reg( R_ECX, Rn );
1.148 + IMUL_r32(R_ECX);
1.149 + store_spreg( R_EDX, R_MACH );
1.150 + store_spreg( R_EAX, R_MACL );
1.151 +:}
1.152 +DMULU.L Rm, Rn {:
1.153 + load_reg( R_EAX, Rm );
1.154 + load_reg( R_ECX, Rn );
1.155 + MUL_r32(R_ECX);
1.156 + store_spreg( R_EDX, R_MACH );
1.157 + store_spreg( R_EAX, R_MACL );
1.158 +:}
1.159 DT Rn {:
1.160 load_reg( R_EAX, Rn );
1.161 ADD_imm8s_r32( -1, Rn );
1.162 @@ -223,17 +275,35 @@
1.163 MOVSX_r8_r32( R_EAX, R_EAX );
1.164 store_reg( R_EAX, Rn );
1.165 :}
1.166 -EXTS.W Rm, Rn {: :}
1.167 -EXTU.B Rm, Rn {: :}
1.168 -EXTU.W Rm, Rn {: :}
1.169 +EXTS.W Rm, Rn {:
1.170 + load_reg( R_EAX, Rm );
1.171 + MOVSX_r16_r32( R_EAX, R_EAX );
1.172 + store_reg( R_EAX, Rn );
1.173 +:}
1.174 +EXTU.B Rm, Rn {:
1.175 + load_reg( R_EAX, Rm );
1.176 + MOVZX_r8_r32( R_EAX, R_EAX );
1.177 + store_reg( R_EAX, Rn );
1.178 +:}
1.179 +EXTU.W Rm, Rn {:
1.180 + load_reg( R_EAX, Rm );
1.181 + MOVZX_r16_r32( R_EAX, R_EAX );
1.182 + store_reg( R_EAX, Rn );
1.183 +:}
1.184 MAC.L @Rm+, @Rn+ {: :}
1.185 MAC.W @Rm+, @Rn+ {: :}
1.186 MOVT Rn {:
1.187 load_spreg( R_EAX, R_T );
1.188 store_reg( R_EAX, Rn );
1.189 :}
1.190 -MUL.L Rm, Rn {: :}
1.191 -MULS.W Rm, Rn {: :}
1.192 +MUL.L Rm, Rn {:
1.193 + load_reg( R_EAX, Rm );
1.194 + load_reg( R_ECX, Rn );
1.195 + MUL_r32( R_ECX );
1.196 + store_spreg( R_EAX, R_MACL );
1.197 +:}
1.198 +MULS.W Rm, Rn {:
1.199 +:}
1.200 MULU.W Rm, Rn {: :}
1.201 NEG Rm, Rn {:
1.202 load_reg( R_EAX, Rm );
1.203 @@ -293,6 +363,20 @@
1.204 :}
1.205 SHAD Rm, Rn {:
1.206 /* Annoyingly enough, not directly convertible */
1.207 + load_reg( R_EAX, Rn );
1.208 + load_reg( R_ECX, Rm );
1.209 + CMP_imm32_r32( 0, R_ECX );
1.210 + JAE_rel8(9);
1.211 +
1.212 + NEG_r32( R_ECX ); // 2
1.213 + AND_imm8_r8( 0x1F, R_CL ); // 3
1.214 + SAR_r32_CL( R_EAX ); // 2
1.215 + JMP_rel8(5); // 2
1.216 +
1.217 + AND_imm8_r8( 0x1F, R_CL ); // 3
1.218 + SHL_r32_CL( R_EAX ); // 2
1.219 +
1.220 + store_reg( R_EAX, Rn );
1.221 :}
1.222 SHLD Rm, Rn {:
1.223 :}
1.224 @@ -379,8 +463,20 @@
1.225 OR_r32_r32( R_EAX, R_ECX );
1.226 store_reg( R_ECX, Rn );
1.227 :}
1.228 -TAS.B @Rn {: :}
1.229 -TST Rm, Rn {: :}
1.230 +TAS.B @Rn {:
1.231 + load_reg( R_ECX, Rn );
1.232 + MEM_READ_BYTE( R_ECX, R_EAX );
1.233 + TEST_r8_r8( R_AL, R_AL );
1.234 + SETE_t();
1.235 + OR_imm8_r8( 0x80, R_AL );
1.236 + MEM_WRITE_BYTE( R_ECX, R_EAX );
1.237 +:}
1.238 +TST Rm, Rn {:
1.239 + load_reg( R_EAX, Rm );
1.240 + load_reg( R_ECX, Rn );
1.241 + TEST_r32_r32( R_EAX, R_ECX );
1.242 + SETE_t();
1.243 +:}
1.244 TST #imm, R0 {: :}
1.245 TST.B #imm, @(R0, GBR) {: :}
1.246 XOR Rm, Rn {:
1.247 @@ -402,7 +498,13 @@
1.248 XOR_imm32_r32( imm, R_EAX );
1.249 MEM_WRITE_BYTE( R_ECX, R_EAX );
1.250 :}
1.251 -XTRCT Rm, Rn {:
1.252 +XTRCT Rm, Rn {:
1.253 + load_reg( R_EAX, Rm );
1.254 + MOV_r32_r32( R_EAX, R_ECX );
1.255 + SHR_imm8_r32( 16, R_EAX );
1.256 + SHL_imm8_r32( 16, R_ECX );
1.257 + OR_r32_r32( R_EAX, R_ECX );
1.258 + store_reg( R_ECX, Rn );
1.259 :}
1.260
1.261 /* Data move instructions */
1.262 @@ -477,30 +579,150 @@
1.263 MEM_READ_BYTE( R_ECX, R_EAX );
1.264 store_reg( R_EAX, 0 );
1.265 :}
1.266 -MOV.L Rm, @Rn {: :}
1.267 -MOV.L Rm, @-Rn {: :}
1.268 -MOV.L Rm, @(R0, Rn) {: :}
1.269 -MOV.L R0, @(disp, GBR) {: :}
1.270 -MOV.L Rm, @(disp, Rn) {: :}
1.271 -MOV.L @Rm, Rn {: :}
1.272 -MOV.L @Rm+, Rn {: :}
1.273 -MOV.L @(R0, Rm), Rn {: :}
1.274 -MOV.L @(disp, GBR), R0 {: :}
1.275 -MOV.L @(disp, PC), Rn {: :}
1.276 -MOV.L @(disp, Rm), Rn {: :}
1.277 -MOV.W Rm, @Rn {: :}
1.278 -MOV.W Rm, @-Rn {: :}
1.279 -MOV.W Rm, @(R0, Rn) {: :}
1.280 -MOV.W R0, @(disp, GBR) {: :}
1.281 -MOV.W R0, @(disp, Rn) {: :}
1.282 -MOV.W @Rm, Rn {: :}
1.283 -MOV.W @Rm+, Rn {: :}
1.284 -MOV.W @(R0, Rm), Rn {: :}
1.285 -MOV.W @(disp, GBR), R0 {: :}
1.286 -MOV.W @(disp, PC), Rn {: :}
1.287 -MOV.W @(disp, Rm), R0 {: :}
1.288 -MOVA @(disp, PC), R0 {: :}
1.289 -MOVCA.L R0, @Rn {: :}
1.290 +MOV.L Rm, @Rn {:
1.291 + load_reg( R_EAX, Rm );
1.292 + load_reg( R_ECX, Rn );
1.293 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.294 +:}
1.295 +MOV.L Rm, @-Rn {:
1.296 + load_reg( R_EAX, Rm );
1.297 + load_reg( R_ECX, Rn );
1.298 + ADD_imm8s_r32( -4, R_ECX );
1.299 + store_reg( R_ECX, Rn );
1.300 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.301 +:}
1.302 +MOV.L Rm, @(R0, Rn) {:
1.303 + load_reg( R_EAX, 0 );
1.304 + load_reg( R_ECX, Rn );
1.305 + ADD_r32_r32( R_EAX, R_ECX );
1.306 + load_reg( R_EAX, Rm );
1.307 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.308 +:}
1.309 +MOV.L R0, @(disp, GBR) {:
1.310 + load_spreg( R_ECX, R_GBR );
1.311 + load_reg( R_EAX, 0 );
1.312 + ADD_imm32_r32( disp, R_ECX );
1.313 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.314 +:}
1.315 +MOV.L Rm, @(disp, Rn) {:
1.316 + load_reg( R_ECX, Rn );
1.317 + load_reg( R_EAX, Rm );
1.318 + ADD_imm32_r32( disp, R_ECX );
1.319 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.320 +:}
1.321 +MOV.L @Rm, Rn {:
1.322 + load_reg( R_ECX, Rm );
1.323 + MEM_READ_LONG( R_ECX, R_EAX );
1.324 + store_reg( R_EAX, Rn );
1.325 +:}
1.326 +MOV.L @Rm+, Rn {:
1.327 + load_reg( R_EAX, Rm );
1.328 + MOV_r32_r32( R_EAX, R_ECX );
1.329 + ADD_imm8s_r32( 4, R_EAX );
1.330 + store_reg( R_EAX, Rm );
1.331 + MEM_READ_LONG( R_ECX, R_EAX );
1.332 + store_reg( R_EAX, Rn );
1.333 +:}
1.334 +MOV.L @(R0, Rm), Rn {:
1.335 + load_reg( R_EAX, 0 );
1.336 + load_reg( R_ECX, Rm );
1.337 + ADD_r32_r32( R_EAX, R_ECX );
1.338 + MEM_READ_LONG( R_ECX, R_EAX );
1.339 + store_reg( R_EAX, Rn );
1.340 +:}
1.341 +MOV.L @(disp, GBR), R0 {:
1.342 + load_spreg( R_ECX, R_GBR );
1.343 + ADD_imm32_r32( disp, R_ECX );
1.344 + MEM_READ_LONG( R_ECX, R_EAX );
1.345 + store_reg( R_EAX, 0 );
1.346 +:}
1.347 +MOV.L @(disp, PC), Rn {:
1.348 + load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1.349 + MEM_READ_LONG( R_ECX, R_EAX );
1.350 + store_reg( R_EAX, 0 );
1.351 +:}
1.352 +MOV.L @(disp, Rm), Rn {:
1.353 + load_reg( R_ECX, Rm );
1.354 + ADD_imm8s_r32( disp, R_ECX );
1.355 + MEM_READ_LONG( R_ECX, R_EAX );
1.356 + store_reg( R_EAX, Rn );
1.357 +:}
1.358 +MOV.W Rm, @Rn {:
1.359 + load_reg( R_ECX, Rn );
1.360 + MEM_READ_WORD( R_ECX, R_EAX );
1.361 + store_reg( R_EAX, Rn );
1.362 +:}
1.363 +MOV.W Rm, @-Rn {:
1.364 + load_reg( R_ECX, Rn );
1.365 + load_reg( R_EAX, Rm );
1.366 + ADD_imm8s_r32( -2, R_ECX );
1.367 + MEM_WRITE_WORD( R_ECX, R_EAX );
1.368 +:}
1.369 +MOV.W Rm, @(R0, Rn) {:
1.370 + load_reg( R_EAX, 0 );
1.371 + load_reg( R_ECX, Rn );
1.372 + ADD_r32_r32( R_EAX, R_ECX );
1.373 + load_reg( R_EAX, Rm );
1.374 + MEM_WRITE_WORD( R_ECX, R_EAX );
1.375 +:}
1.376 +MOV.W R0, @(disp, GBR) {:
1.377 + load_spreg( R_ECX, R_GBR );
1.378 + load_reg( R_EAX, 0 );
1.379 + ADD_imm32_r32( disp, R_ECX );
1.380 + MEM_WRITE_WORD( R_ECX, R_EAX );
1.381 +:}
1.382 +MOV.W R0, @(disp, Rn) {:
1.383 + load_reg( R_ECX, Rn );
1.384 + load_reg( R_EAX, 0 );
1.385 + ADD_imm32_r32( disp, R_ECX );
1.386 + MEM_WRITE_WORD( R_ECX, R_EAX );
1.387 +:}
1.388 +MOV.W @Rm, Rn {:
1.389 + load_reg( R_ECX, Rm );
1.390 + MEM_READ_WORD( R_ECX, R_EAX );
1.391 + store_reg( R_EAX, Rn );
1.392 +:}
1.393 +MOV.W @Rm+, Rn {:
1.394 + load_reg( R_EAX, Rm );
1.395 + MOV_r32_r32( R_EAX, R_ECX );
1.396 + ADD_imm8s_r32( 2, R_EAX );
1.397 + store_reg( R_EAX, Rm );
1.398 + MEM_READ_WORD( R_ECX, R_EAX );
1.399 + store_reg( R_EAX, Rn );
1.400 +:}
1.401 +MOV.W @(R0, Rm), Rn {:
1.402 + load_reg( R_EAX, 0 );
1.403 + load_reg( R_ECX, Rm );
1.404 + ADD_r32_r32( R_EAX, R_ECX );
1.405 + MEM_READ_WORD( R_ECX, R_EAX );
1.406 + store_reg( R_EAX, Rn );
1.407 +:}
1.408 +MOV.W @(disp, GBR), R0 {:
1.409 + load_spreg( R_ECX, R_GBR );
1.410 + ADD_imm32_r32( disp, R_ECX );
1.411 + MEM_READ_WORD( R_ECX, R_EAX );
1.412 + store_reg( R_EAX, 0 );
1.413 +:}
1.414 +MOV.W @(disp, PC), Rn {:
1.415 + load_imm32( R_ECX, pc + disp + 4 );
1.416 + MEM_READ_WORD( R_ECX, R_EAX );
1.417 + store_reg( R_EAX, Rn );
1.418 +:}
1.419 +MOV.W @(disp, Rm), R0 {:
1.420 + load_reg( R_ECX, Rm );
1.421 + ADD_imm32_r32( disp, R_ECX );
1.422 + MEM_READ_WORD( R_ECX, R_EAX );
1.423 + store_reg( R_EAX, 0 );
1.424 +:}
1.425 +MOVA @(disp, PC), R0 {:
1.426 + load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1.427 + store_reg( R_ECX, 0 );
1.428 +:}
1.429 +MOVCA.L R0, @Rn {:
1.430 + load_reg( R_EAX, 0 );
1.431 + load_reg( R_ECX, Rn );
1.432 + MEM_WRITE_LONG( R_ECX, R_EAX );
1.433 +:}
1.434
1.435 /* Control transfer instructions */
1.436 BF disp {: :}
.