Commit 5dd9488c09081a76ff86e0d74e56a9d98d666d64
1 parent
60cd49d5
added cmov instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@32 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
125 additions
and
65 deletions
TODO
| 1 | -- segment ops (minimal LDT/GDT support for wine) | ||
| 2 | - optimize translated cache chaining (DLL PLT like system) | 1 | - optimize translated cache chaining (DLL PLT like system) |
| 3 | - improved 16 bit support | 2 | - improved 16 bit support |
| 4 | - optimize inverse flags propagation (easy by generating intermediate | 3 | - optimize inverse flags propagation (easy by generating intermediate |
opreg_template.h
| @@ -60,6 +60,19 @@ void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void) | @@ -60,6 +60,19 @@ void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void) | ||
| 60 | REG = A0; | 60 | REG = A0; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | +/* mov T1 to REG if T0 is true */ | ||
| 64 | +void OPPROTO glue(glue(op_cmovw,REGNAME),_T1_T0)(void) | ||
| 65 | +{ | ||
| 66 | + if (T0) | ||
| 67 | + REG = (REG & 0xffff0000) | (T1 & 0xffff); | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +void OPPROTO glue(glue(op_cmovl,REGNAME),_T1_T0)(void) | ||
| 71 | +{ | ||
| 72 | + if (T0) | ||
| 73 | + REG = T1; | ||
| 74 | +} | ||
| 75 | + | ||
| 63 | /* NOTE: T0 high order bits are ignored */ | 76 | /* NOTE: T0 high order bits are ignored */ |
| 64 | void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void) | 77 | void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void) |
| 65 | { | 78 | { |
ops_template.h
| @@ -385,6 +385,7 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) | @@ -385,6 +385,7 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) | ||
| 385 | void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) | 385 | void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void) |
| 386 | { | 386 | { |
| 387 | int count, src; | 387 | int count, src; |
| 388 | + /* XXX: testing */ | ||
| 388 | count = T1 & SHIFT_MASK; | 389 | count = T1 & SHIFT_MASK; |
| 389 | if (count) { | 390 | if (count) { |
| 390 | CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C); | 391 | CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C); |
tests/test-i386.c
| @@ -3,6 +3,8 @@ | @@ -3,6 +3,8 @@ | ||
| 3 | #include <inttypes.h> | 3 | #include <inttypes.h> |
| 4 | #include <math.h> | 4 | #include <math.h> |
| 5 | 5 | ||
| 6 | +#define TEST_CMOV 0 | ||
| 7 | + | ||
| 6 | #define xglue(x, y) x ## y | 8 | #define xglue(x, y) x ## y |
| 7 | #define glue(x, y) xglue(x, y) | 9 | #define glue(x, y) xglue(x, y) |
| 8 | #define stringify(s) tostring(s) | 10 | #define stringify(s) tostring(s) |
| @@ -225,79 +227,99 @@ void test_lea(void) | @@ -225,79 +227,99 @@ void test_lea(void) | ||
| 225 | 227 | ||
| 226 | #define TEST_JCC(JCC, v1, v2)\ | 228 | #define TEST_JCC(JCC, v1, v2)\ |
| 227 | {\ | 229 | {\ |
| 230 | + int res;\ | ||
| 228 | asm("movl $1, %0\n\t"\ | 231 | asm("movl $1, %0\n\t"\ |
| 229 | "cmpl %2, %1\n\t"\ | 232 | "cmpl %2, %1\n\t"\ |
| 230 | - JCC " 1f\n\t"\ | 233 | + "j" JCC " 1f\n\t"\ |
| 231 | "movl $0, %0\n\t"\ | 234 | "movl $0, %0\n\t"\ |
| 232 | "1:\n\t"\ | 235 | "1:\n\t"\ |
| 233 | : "=r" (res)\ | 236 | : "=r" (res)\ |
| 234 | : "r" (v1), "r" (v2));\ | 237 | : "r" (v1), "r" (v2));\ |
| 235 | - printf("%-10s %d\n", JCC, res);\ | 238 | + printf("%-10s %d\n", "j" JCC, res);\ |
| 239 | +\ | ||
| 240 | + asm("movl $0, %0\n\t"\ | ||
| 241 | + "cmpl %2, %1\n\t"\ | ||
| 242 | + "set" JCC " %b0\n\t"\ | ||
| 243 | + : "=r" (res)\ | ||
| 244 | + : "r" (v1), "r" (v2));\ | ||
| 245 | + printf("%-10s %d\n", "set" JCC, res);\ | ||
| 246 | + if (TEST_CMOV) {\ | ||
| 247 | + asm("movl $0x12345678, %0\n\t"\ | ||
| 248 | + "cmpl %2, %1\n\t"\ | ||
| 249 | + "cmov" JCC "l %3, %0\n\t"\ | ||
| 250 | + : "=r" (res)\ | ||
| 251 | + : "r" (v1), "r" (v2), "m" (1));\ | ||
| 252 | + printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\ | ||
| 253 | + asm("movl $0x12345678, %0\n\t"\ | ||
| 254 | + "cmpl %2, %1\n\t"\ | ||
| 255 | + "cmov" JCC "w %w3, %w0\n\t"\ | ||
| 256 | + : "=r" (res)\ | ||
| 257 | + : "r" (v1), "r" (v2), "r" (1));\ | ||
| 258 | + printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\ | ||
| 259 | + } \ | ||
| 236 | } | 260 | } |
| 237 | 261 | ||
| 238 | /* various jump tests */ | 262 | /* various jump tests */ |
| 239 | void test_jcc(void) | 263 | void test_jcc(void) |
| 240 | { | 264 | { |
| 241 | - int res; | ||
| 242 | - | ||
| 243 | - TEST_JCC("jne", 1, 1); | ||
| 244 | - TEST_JCC("jne", 1, 0); | 265 | + TEST_JCC("ne", 1, 1); |
| 266 | + TEST_JCC("ne", 1, 0); | ||
| 245 | 267 | ||
| 246 | - TEST_JCC("je", 1, 1); | ||
| 247 | - TEST_JCC("je", 1, 0); | 268 | + TEST_JCC("e", 1, 1); |
| 269 | + TEST_JCC("e", 1, 0); | ||
| 248 | 270 | ||
| 249 | - TEST_JCC("jl", 1, 1); | ||
| 250 | - TEST_JCC("jl", 1, 0); | ||
| 251 | - TEST_JCC("jl", 1, -1); | 271 | + TEST_JCC("l", 1, 1); |
| 272 | + TEST_JCC("l", 1, 0); | ||
| 273 | + TEST_JCC("l", 1, -1); | ||
| 252 | 274 | ||
| 253 | - TEST_JCC("jle", 1, 1); | ||
| 254 | - TEST_JCC("jle", 1, 0); | ||
| 255 | - TEST_JCC("jle", 1, -1); | 275 | + TEST_JCC("le", 1, 1); |
| 276 | + TEST_JCC("le", 1, 0); | ||
| 277 | + TEST_JCC("le", 1, -1); | ||
| 256 | 278 | ||
| 257 | - TEST_JCC("jge", 1, 1); | ||
| 258 | - TEST_JCC("jge", 1, 0); | ||
| 259 | - TEST_JCC("jge", -1, 1); | 279 | + TEST_JCC("ge", 1, 1); |
| 280 | + TEST_JCC("ge", 1, 0); | ||
| 281 | + TEST_JCC("ge", -1, 1); | ||
| 260 | 282 | ||
| 261 | - TEST_JCC("jg", 1, 1); | ||
| 262 | - TEST_JCC("jg", 1, 0); | ||
| 263 | - TEST_JCC("jg", 1, -1); | 283 | + TEST_JCC("g", 1, 1); |
| 284 | + TEST_JCC("g", 1, 0); | ||
| 285 | + TEST_JCC("g", 1, -1); | ||
| 264 | 286 | ||
| 265 | - TEST_JCC("jb", 1, 1); | ||
| 266 | - TEST_JCC("jb", 1, 0); | ||
| 267 | - TEST_JCC("jb", 1, -1); | 287 | + TEST_JCC("b", 1, 1); |
| 288 | + TEST_JCC("b", 1, 0); | ||
| 289 | + TEST_JCC("b", 1, -1); | ||
| 268 | 290 | ||
| 269 | - TEST_JCC("jbe", 1, 1); | ||
| 270 | - TEST_JCC("jbe", 1, 0); | ||
| 271 | - TEST_JCC("jbe", 1, -1); | 291 | + TEST_JCC("be", 1, 1); |
| 292 | + TEST_JCC("be", 1, 0); | ||
| 293 | + TEST_JCC("be", 1, -1); | ||
| 272 | 294 | ||
| 273 | - TEST_JCC("jae", 1, 1); | ||
| 274 | - TEST_JCC("jae", 1, 0); | ||
| 275 | - TEST_JCC("jae", 1, -1); | 295 | + TEST_JCC("ae", 1, 1); |
| 296 | + TEST_JCC("ae", 1, 0); | ||
| 297 | + TEST_JCC("ae", 1, -1); | ||
| 276 | 298 | ||
| 277 | - TEST_JCC("ja", 1, 1); | ||
| 278 | - TEST_JCC("ja", 1, 0); | ||
| 279 | - TEST_JCC("ja", 1, -1); | 299 | + TEST_JCC("a", 1, 1); |
| 300 | + TEST_JCC("a", 1, 0); | ||
| 301 | + TEST_JCC("a", 1, -1); | ||
| 280 | 302 | ||
| 281 | 303 | ||
| 282 | - TEST_JCC("jp", 1, 1); | ||
| 283 | - TEST_JCC("jp", 1, 0); | 304 | + TEST_JCC("p", 1, 1); |
| 305 | + TEST_JCC("p", 1, 0); | ||
| 284 | 306 | ||
| 285 | - TEST_JCC("jnp", 1, 1); | ||
| 286 | - TEST_JCC("jnp", 1, 0); | 307 | + TEST_JCC("np", 1, 1); |
| 308 | + TEST_JCC("np", 1, 0); | ||
| 287 | 309 | ||
| 288 | - TEST_JCC("jo", 0x7fffffff, 0); | ||
| 289 | - TEST_JCC("jo", 0x7fffffff, -1); | 310 | + TEST_JCC("o", 0x7fffffff, 0); |
| 311 | + TEST_JCC("o", 0x7fffffff, -1); | ||
| 290 | 312 | ||
| 291 | - TEST_JCC("jno", 0x7fffffff, 0); | ||
| 292 | - TEST_JCC("jno", 0x7fffffff, -1); | 313 | + TEST_JCC("no", 0x7fffffff, 0); |
| 314 | + TEST_JCC("no", 0x7fffffff, -1); | ||
| 293 | 315 | ||
| 294 | - TEST_JCC("js", 0, 1); | ||
| 295 | - TEST_JCC("js", 0, -1); | ||
| 296 | - TEST_JCC("js", 0, 0); | 316 | + TEST_JCC("s", 0, 1); |
| 317 | + TEST_JCC("s", 0, -1); | ||
| 318 | + TEST_JCC("s", 0, 0); | ||
| 297 | 319 | ||
| 298 | - TEST_JCC("jns", 0, 1); | ||
| 299 | - TEST_JCC("jns", 0, -1); | ||
| 300 | - TEST_JCC("jns", 0, 0); | 320 | + TEST_JCC("ns", 0, 1); |
| 321 | + TEST_JCC("ns", 0, -1); | ||
| 322 | + TEST_JCC("ns", 0, 0); | ||
| 301 | } | 323 | } |
| 302 | 324 | ||
| 303 | #undef CC_MASK | 325 | #undef CC_MASK |
translate-i386.c
| @@ -44,19 +44,6 @@ int __op_param1, __op_param2, __op_param3; | @@ -44,19 +44,6 @@ int __op_param1, __op_param2, __op_param3; | ||
| 44 | extern FILE *logfile; | 44 | extern FILE *logfile; |
| 45 | extern int loglevel; | 45 | extern int loglevel; |
| 46 | 46 | ||
| 47 | -/* supress that */ | ||
| 48 | -static void error(const char *fmt, ...) | ||
| 49 | -{ | ||
| 50 | - va_list ap; | ||
| 51 | - | ||
| 52 | - va_start(ap, fmt); | ||
| 53 | - fprintf(stderr, "\n"); | ||
| 54 | - vfprintf(stderr, fmt, ap); | ||
| 55 | - fprintf(stderr, "\n"); | ||
| 56 | - va_end(ap); | ||
| 57 | - exit(1); | ||
| 58 | -} | ||
| 59 | - | ||
| 60 | #define PREFIX_REPZ 1 | 47 | #define PREFIX_REPZ 1 |
| 61 | #define PREFIX_REPNZ 2 | 48 | #define PREFIX_REPNZ 2 |
| 62 | #define PREFIX_LOCK 4 | 49 | #define PREFIX_LOCK 4 |
| @@ -352,6 +339,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = { | @@ -352,6 +339,29 @@ static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = { | ||
| 352 | }, | 339 | }, |
| 353 | }; | 340 | }; |
| 354 | 341 | ||
| 342 | +static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = { | ||
| 343 | + [0] = { | ||
| 344 | + gen_op_cmovw_EAX_T1_T0, | ||
| 345 | + gen_op_cmovw_ECX_T1_T0, | ||
| 346 | + gen_op_cmovw_EDX_T1_T0, | ||
| 347 | + gen_op_cmovw_EBX_T1_T0, | ||
| 348 | + gen_op_cmovw_ESP_T1_T0, | ||
| 349 | + gen_op_cmovw_EBP_T1_T0, | ||
| 350 | + gen_op_cmovw_ESI_T1_T0, | ||
| 351 | + gen_op_cmovw_EDI_T1_T0, | ||
| 352 | + }, | ||
| 353 | + [1] = { | ||
| 354 | + gen_op_cmovl_EAX_T1_T0, | ||
| 355 | + gen_op_cmovl_ECX_T1_T0, | ||
| 356 | + gen_op_cmovl_EDX_T1_T0, | ||
| 357 | + gen_op_cmovl_EBX_T1_T0, | ||
| 358 | + gen_op_cmovl_ESP_T1_T0, | ||
| 359 | + gen_op_cmovl_EBP_T1_T0, | ||
| 360 | + gen_op_cmovl_ESI_T1_T0, | ||
| 361 | + gen_op_cmovl_EDI_T1_T0, | ||
| 362 | + }, | ||
| 363 | +}; | ||
| 364 | + | ||
| 355 | static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { | 365 | static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { |
| 356 | gen_op_addl_T0_T1_cc, | 366 | gen_op_addl_T0_T1_cc, |
| 357 | gen_op_orl_T0_T1_cc, | 367 | gen_op_orl_T0_T1_cc, |
| @@ -2586,12 +2596,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2586,12 +2596,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2586 | s->is_jmp = 1; | 2596 | s->is_jmp = 1; |
| 2587 | break; | 2597 | break; |
| 2588 | 2598 | ||
| 2589 | - case 0x190 ... 0x19f: | 2599 | + case 0x190 ... 0x19f: /* setcc Gv */ |
| 2590 | modrm = ldub(s->pc++); | 2600 | modrm = ldub(s->pc++); |
| 2591 | gen_setcc(s, b); | 2601 | gen_setcc(s, b); |
| 2592 | gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); | 2602 | gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1); |
| 2593 | break; | 2603 | break; |
| 2594 | - | 2604 | + case 0x140 ... 0x14f: /* cmov Gv, Ev */ |
| 2605 | + ot = dflag ? OT_LONG : OT_WORD; | ||
| 2606 | + modrm = ldub(s->pc++); | ||
| 2607 | + reg = (modrm >> 3) & 7; | ||
| 2608 | + mod = (modrm >> 6) & 3; | ||
| 2609 | + gen_setcc(s, b); | ||
| 2610 | + if (mod != 3) { | ||
| 2611 | + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); | ||
| 2612 | + gen_op_ld_T1_A0[ot](); | ||
| 2613 | + } else { | ||
| 2614 | + rm = modrm & 7; | ||
| 2615 | + gen_op_mov_TN_reg[ot][1][rm](); | ||
| 2616 | + } | ||
| 2617 | + gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg](); | ||
| 2618 | + break; | ||
| 2619 | + | ||
| 2595 | /************************/ | 2620 | /************************/ |
| 2596 | /* flags */ | 2621 | /* flags */ |
| 2597 | case 0x9c: /* pushf */ | 2622 | case 0x9c: /* pushf */ |
| @@ -2801,7 +2826,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2801,7 +2826,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2801 | gen_op_loop[s->aflag][b & 3](val, (long)s->pc); | 2826 | gen_op_loop[s->aflag][b & 3](val, (long)s->pc); |
| 2802 | s->is_jmp = 1; | 2827 | s->is_jmp = 1; |
| 2803 | break; | 2828 | break; |
| 2804 | - case 0x1a2: /* rdtsc */ | 2829 | + case 0x131: /* rdtsc */ |
| 2805 | gen_op_rdtsc(); | 2830 | gen_op_rdtsc(); |
| 2806 | break; | 2831 | break; |
| 2807 | #if 0 | 2832 | #if 0 |
| @@ -2841,8 +2866,8 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | @@ -2841,8 +2866,8 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | ||
| 2841 | do { | 2866 | do { |
| 2842 | ret = disas_insn(dc, pc_ptr); | 2867 | ret = disas_insn(dc, pc_ptr); |
| 2843 | if (ret == -1) { | 2868 | if (ret == -1) { |
| 2844 | - error("unknown instruction at PC=0x%x B=%02x %02x %02x", | ||
| 2845 | - pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]); | 2869 | + fprintf(stderr, "unknown instruction at PC=0x%08lx B=%02x %02x %02x", |
| 2870 | + (long)pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]); | ||
| 2846 | abort(); | 2871 | abort(); |
| 2847 | } | 2872 | } |
| 2848 | pc_ptr = (void *)ret; | 2873 | pc_ptr = (void *)ret; |