Commit 6e0d8677cb443e7408c0b7a25a93c6596d7fa380
1 parent
cd31fefa
converted string OPs and LOOP insns to TCG
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4494 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
147 additions
and
294 deletions
target-i386/op.c
| @@ -263,55 +263,6 @@ void OPPROTO op_cmpxchg8b(void) | @@ -263,55 +263,6 @@ void OPPROTO op_cmpxchg8b(void) | ||
| 263 | 263 | ||
| 264 | #endif | 264 | #endif |
| 265 | 265 | ||
| 266 | -/* string ops helpers */ | ||
| 267 | - | ||
| 268 | -void OPPROTO op_addl_ESI_T0(void) | ||
| 269 | -{ | ||
| 270 | - ESI = (uint32_t)(ESI + T0); | ||
| 271 | -} | ||
| 272 | - | ||
| 273 | -void OPPROTO op_addw_ESI_T0(void) | ||
| 274 | -{ | ||
| 275 | - ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff); | ||
| 276 | -} | ||
| 277 | - | ||
| 278 | -void OPPROTO op_addl_EDI_T0(void) | ||
| 279 | -{ | ||
| 280 | - EDI = (uint32_t)(EDI + T0); | ||
| 281 | -} | ||
| 282 | - | ||
| 283 | -void OPPROTO op_addw_EDI_T0(void) | ||
| 284 | -{ | ||
| 285 | - EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff); | ||
| 286 | -} | ||
| 287 | - | ||
| 288 | -void OPPROTO op_decl_ECX(void) | ||
| 289 | -{ | ||
| 290 | - ECX = (uint32_t)(ECX - 1); | ||
| 291 | -} | ||
| 292 | - | ||
| 293 | -void OPPROTO op_decw_ECX(void) | ||
| 294 | -{ | ||
| 295 | - ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff); | ||
| 296 | -} | ||
| 297 | - | ||
| 298 | -#ifdef TARGET_X86_64 | ||
| 299 | -void OPPROTO op_addq_ESI_T0(void) | ||
| 300 | -{ | ||
| 301 | - ESI = (ESI + T0); | ||
| 302 | -} | ||
| 303 | - | ||
| 304 | -void OPPROTO op_addq_EDI_T0(void) | ||
| 305 | -{ | ||
| 306 | - EDI = (EDI + T0); | ||
| 307 | -} | ||
| 308 | - | ||
| 309 | -void OPPROTO op_decq_ECX(void) | ||
| 310 | -{ | ||
| 311 | - ECX--; | ||
| 312 | -} | ||
| 313 | -#endif | ||
| 314 | - | ||
| 315 | /* bcd */ | 266 | /* bcd */ |
| 316 | 267 | ||
| 317 | void OPPROTO op_aam(void) | 268 | void OPPROTO op_aam(void) |
| @@ -460,13 +411,6 @@ void OPPROTO op_jnz_T0_label(void) | @@ -460,13 +411,6 @@ void OPPROTO op_jnz_T0_label(void) | ||
| 460 | FORCE_RET(); | 411 | FORCE_RET(); |
| 461 | } | 412 | } |
| 462 | 413 | ||
| 463 | -void OPPROTO op_jz_T0_label(void) | ||
| 464 | -{ | ||
| 465 | - if (!T0) | ||
| 466 | - GOTO_LABEL_PARAM(1); | ||
| 467 | - FORCE_RET(); | ||
| 468 | -} | ||
| 469 | - | ||
| 470 | /* slow set cases (compute x86 flags) */ | 414 | /* slow set cases (compute x86 flags) */ |
| 471 | void OPPROTO op_seto_T0_cc(void) | 415 | void OPPROTO op_seto_T0_cc(void) |
| 472 | { | 416 | { |
| @@ -527,11 +471,6 @@ void OPPROTO op_xor_T0_1(void) | @@ -527,11 +471,6 @@ void OPPROTO op_xor_T0_1(void) | ||
| 527 | T0 ^= 1; | 471 | T0 ^= 1; |
| 528 | } | 472 | } |
| 529 | 473 | ||
| 530 | -void OPPROTO op_mov_T0_cc(void) | ||
| 531 | -{ | ||
| 532 | - T0 = cc_table[CC_OP].compute_all(); | ||
| 533 | -} | ||
| 534 | - | ||
| 535 | /* XXX: clear VIF/VIP in all ops ? */ | 474 | /* XXX: clear VIF/VIP in all ops ? */ |
| 536 | 475 | ||
| 537 | void OPPROTO op_movl_eflags_T0(void) | 476 | void OPPROTO op_movl_eflags_T0(void) |
target-i386/ops_template.h
| @@ -118,40 +118,6 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void) | @@ -118,40 +118,6 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void) | ||
| 118 | FORCE_RET(); | 118 | FORCE_RET(); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | -/* oldies */ | ||
| 122 | - | ||
| 123 | -#if DATA_BITS >= 16 | ||
| 124 | - | ||
| 125 | -void OPPROTO glue(op_loopnz, SUFFIX)(void) | ||
| 126 | -{ | ||
| 127 | - if ((DATA_TYPE)ECX != 0 && !(T0 & CC_Z)) | ||
| 128 | - GOTO_LABEL_PARAM(1); | ||
| 129 | - FORCE_RET(); | ||
| 130 | -} | ||
| 131 | - | ||
| 132 | -void OPPROTO glue(op_loopz, SUFFIX)(void) | ||
| 133 | -{ | ||
| 134 | - if ((DATA_TYPE)ECX != 0 && (T0 & CC_Z)) | ||
| 135 | - GOTO_LABEL_PARAM(1); | ||
| 136 | - FORCE_RET(); | ||
| 137 | -} | ||
| 138 | - | ||
| 139 | -void OPPROTO glue(op_jz_ecx, SUFFIX)(void) | ||
| 140 | -{ | ||
| 141 | - if ((DATA_TYPE)ECX == 0) | ||
| 142 | - GOTO_LABEL_PARAM(1); | ||
| 143 | - FORCE_RET(); | ||
| 144 | -} | ||
| 145 | - | ||
| 146 | -void OPPROTO glue(op_jnz_ecx, SUFFIX)(void) | ||
| 147 | -{ | ||
| 148 | - if ((DATA_TYPE)ECX != 0) | ||
| 149 | - GOTO_LABEL_PARAM(1); | ||
| 150 | - FORCE_RET(); | ||
| 151 | -} | ||
| 152 | - | ||
| 153 | -#endif | ||
| 154 | - | ||
| 155 | /* various optimized set cases */ | 121 | /* various optimized set cases */ |
| 156 | 122 | ||
| 157 | void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void) | 123 | void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void) |
| @@ -200,13 +166,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) | @@ -200,13 +166,6 @@ void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void) | ||
| 200 | T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2); | 166 | T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2); |
| 201 | } | 167 | } |
| 202 | 168 | ||
| 203 | -/* string operations */ | ||
| 204 | - | ||
| 205 | -void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void) | ||
| 206 | -{ | ||
| 207 | - T0 = DF << SHIFT; | ||
| 208 | -} | ||
| 209 | - | ||
| 210 | #undef DATA_BITS | 169 | #undef DATA_BITS |
| 211 | #undef SHIFT_MASK | 170 | #undef SHIFT_MASK |
| 212 | #undef SHIFT1_MASK | 171 | #undef SHIFT1_MASK |
target-i386/translate.c
| @@ -402,31 +402,57 @@ static inline void gen_op_jmp_T0(void) | @@ -402,31 +402,57 @@ static inline void gen_op_jmp_T0(void) | ||
| 402 | tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip)); | 402 | tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip)); |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | -static inline void gen_op_addw_ESP_im(int32_t val) | 405 | +static inline void gen_op_add_reg_im(int size, int reg, int32_t val) |
| 406 | { | 406 | { |
| 407 | - tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); | ||
| 408 | - tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); | ||
| 409 | - tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]) + REG_W_OFFSET); | 407 | + switch(size) { |
| 408 | + case 0: | ||
| 409 | + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 410 | + tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); | ||
| 411 | + tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); | ||
| 412 | + break; | ||
| 413 | + case 1: | ||
| 414 | + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 415 | + tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); | ||
| 416 | +#ifdef TARGET_X86_64 | ||
| 417 | + tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff); | ||
| 418 | +#endif | ||
| 419 | + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 420 | + break; | ||
| 421 | +#ifdef TARGET_X86_64 | ||
| 422 | + case 2: | ||
| 423 | + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 424 | + tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); | ||
| 425 | + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 426 | + break; | ||
| 427 | +#endif | ||
| 428 | + } | ||
| 410 | } | 429 | } |
| 411 | 430 | ||
| 412 | -static inline void gen_op_addl_ESP_im(int32_t val) | 431 | +static inline void gen_op_add_reg_T0(int size, int reg) |
| 413 | { | 432 | { |
| 414 | - tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); | ||
| 415 | - tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); | 433 | + switch(size) { |
| 434 | + case 0: | ||
| 435 | + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 436 | + tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); | ||
| 437 | + tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); | ||
| 438 | + break; | ||
| 439 | + case 1: | ||
| 440 | + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 441 | + tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); | ||
| 416 | #ifdef TARGET_X86_64 | 442 | #ifdef TARGET_X86_64 |
| 417 | - tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff); | 443 | + tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff); |
| 418 | #endif | 444 | #endif |
| 419 | - tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); | ||
| 420 | -} | ||
| 421 | - | 445 | + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); |
| 446 | + break; | ||
| 422 | #ifdef TARGET_X86_64 | 447 | #ifdef TARGET_X86_64 |
| 423 | -static inline void gen_op_addq_ESP_im(int32_t val) | ||
| 424 | -{ | ||
| 425 | - tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); | ||
| 426 | - tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); | ||
| 427 | - tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); | ||
| 428 | -} | 448 | + case 2: |
| 449 | + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 450 | + tcg_gen_add_tl(cpu_tmp0, cpu_tmp0, cpu_T[0]); | ||
| 451 | + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); | ||
| 452 | + break; | ||
| 429 | #endif | 453 | #endif |
| 454 | + } | ||
| 455 | +} | ||
| 430 | 456 | ||
| 431 | static inline void gen_op_set_cc_op(int32_t val) | 457 | static inline void gen_op_set_cc_op(int32_t val) |
| 432 | { | 458 | { |
| @@ -663,30 +689,59 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s) | @@ -663,30 +689,59 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s) | ||
| 663 | } | 689 | } |
| 664 | } | 690 | } |
| 665 | 691 | ||
| 666 | -static GenOpFunc *gen_op_movl_T0_Dshift[4] = { | ||
| 667 | - gen_op_movl_T0_Dshiftb, | ||
| 668 | - gen_op_movl_T0_Dshiftw, | ||
| 669 | - gen_op_movl_T0_Dshiftl, | ||
| 670 | - X86_64_ONLY(gen_op_movl_T0_Dshiftq), | 692 | +static inline void gen_op_movl_T0_Dshift(int ot) |
| 693 | +{ | ||
| 694 | + tcg_gen_ld32s_tl(cpu_T[0], cpu_env, offsetof(CPUState, df)); | ||
| 695 | + tcg_gen_shli_tl(cpu_T[0], cpu_T[0], ot); | ||
| 671 | }; | 696 | }; |
| 672 | 697 | ||
| 673 | -static GenOpFunc1 *gen_op_jnz_ecx[3] = { | ||
| 674 | - gen_op_jnz_ecxw, | ||
| 675 | - gen_op_jnz_ecxl, | ||
| 676 | - X86_64_ONLY(gen_op_jnz_ecxq), | ||
| 677 | -}; | 698 | +static void gen_extu(int ot, TCGv reg) |
| 699 | +{ | ||
| 700 | + switch(ot) { | ||
| 701 | + case OT_BYTE: | ||
| 702 | + tcg_gen_ext8u_tl(reg, reg); | ||
| 703 | + break; | ||
| 704 | + case OT_WORD: | ||
| 705 | + tcg_gen_ext16u_tl(reg, reg); | ||
| 706 | + break; | ||
| 707 | + case OT_LONG: | ||
| 708 | + tcg_gen_ext32u_tl(reg, reg); | ||
| 709 | + break; | ||
| 710 | + default: | ||
| 711 | + break; | ||
| 712 | + } | ||
| 713 | +} | ||
| 678 | 714 | ||
| 679 | -static GenOpFunc1 *gen_op_jz_ecx[3] = { | ||
| 680 | - gen_op_jz_ecxw, | ||
| 681 | - gen_op_jz_ecxl, | ||
| 682 | - X86_64_ONLY(gen_op_jz_ecxq), | ||
| 683 | -}; | 715 | +static void gen_exts(int ot, TCGv reg) |
| 716 | +{ | ||
| 717 | + switch(ot) { | ||
| 718 | + case OT_BYTE: | ||
| 719 | + tcg_gen_ext8s_tl(reg, reg); | ||
| 720 | + break; | ||
| 721 | + case OT_WORD: | ||
| 722 | + tcg_gen_ext16s_tl(reg, reg); | ||
| 723 | + break; | ||
| 724 | + case OT_LONG: | ||
| 725 | + tcg_gen_ext32s_tl(reg, reg); | ||
| 726 | + break; | ||
| 727 | + default: | ||
| 728 | + break; | ||
| 729 | + } | ||
| 730 | +} | ||
| 684 | 731 | ||
| 685 | -static GenOpFunc *gen_op_dec_ECX[3] = { | ||
| 686 | - gen_op_decw_ECX, | ||
| 687 | - gen_op_decl_ECX, | ||
| 688 | - X86_64_ONLY(gen_op_decq_ECX), | ||
| 689 | -}; | 732 | +static inline void gen_op_jnz_ecx(int size, int label1) |
| 733 | +{ | ||
| 734 | + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX])); | ||
| 735 | + gen_extu(size + 1, cpu_tmp0); | ||
| 736 | + tcg_gen_brcond_tl(TCG_COND_NE, cpu_tmp0, tcg_const_tl(0), label1); | ||
| 737 | +} | ||
| 738 | + | ||
| 739 | +static inline void gen_op_jz_ecx(int size, int label1) | ||
| 740 | +{ | ||
| 741 | + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ECX])); | ||
| 742 | + gen_extu(size + 1, cpu_tmp0); | ||
| 743 | + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_tmp0, tcg_const_tl(0), label1); | ||
| 744 | +} | ||
| 690 | 745 | ||
| 691 | static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = { | 746 | static GenOpFunc1 *gen_op_string_jnz_sub[2][4] = { |
| 692 | { | 747 | { |
| @@ -760,20 +815,9 @@ static inline void gen_movs(DisasContext *s, int ot) | @@ -760,20 +815,9 @@ static inline void gen_movs(DisasContext *s, int ot) | ||
| 760 | gen_op_ld_T0_A0(ot + s->mem_index); | 815 | gen_op_ld_T0_A0(ot + s->mem_index); |
| 761 | gen_string_movl_A0_EDI(s); | 816 | gen_string_movl_A0_EDI(s); |
| 762 | gen_op_st_T0_A0(ot + s->mem_index); | 817 | gen_op_st_T0_A0(ot + s->mem_index); |
| 763 | - gen_op_movl_T0_Dshift[ot](); | ||
| 764 | -#ifdef TARGET_X86_64 | ||
| 765 | - if (s->aflag == 2) { | ||
| 766 | - gen_op_addq_ESI_T0(); | ||
| 767 | - gen_op_addq_EDI_T0(); | ||
| 768 | - } else | ||
| 769 | -#endif | ||
| 770 | - if (s->aflag) { | ||
| 771 | - gen_op_addl_ESI_T0(); | ||
| 772 | - gen_op_addl_EDI_T0(); | ||
| 773 | - } else { | ||
| 774 | - gen_op_addw_ESI_T0(); | ||
| 775 | - gen_op_addw_EDI_T0(); | ||
| 776 | - } | 818 | + gen_op_movl_T0_Dshift(ot); |
| 819 | + gen_op_add_reg_T0(s->aflag, R_ESI); | ||
| 820 | + gen_op_add_reg_T0(s->aflag, R_EDI); | ||
| 777 | } | 821 | } |
| 778 | 822 | ||
| 779 | static inline void gen_update_cc_op(DisasContext *s) | 823 | static inline void gen_update_cc_op(DisasContext *s) |
| @@ -822,7 +866,7 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) | @@ -822,7 +866,7 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) | ||
| 822 | 866 | ||
| 823 | l1 = gen_new_label(); | 867 | l1 = gen_new_label(); |
| 824 | l2 = gen_new_label(); | 868 | l2 = gen_new_label(); |
| 825 | - gen_op_jnz_ecx[s->aflag](l1); | 869 | + gen_op_jnz_ecx(s->aflag, l1); |
| 826 | gen_set_label(l2); | 870 | gen_set_label(l2); |
| 827 | gen_jmp_tb(s, next_eip, 1); | 871 | gen_jmp_tb(s, next_eip, 1); |
| 828 | gen_set_label(l1); | 872 | gen_set_label(l1); |
| @@ -834,17 +878,8 @@ static inline void gen_stos(DisasContext *s, int ot) | @@ -834,17 +878,8 @@ static inline void gen_stos(DisasContext *s, int ot) | ||
| 834 | gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); | 878 | gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); |
| 835 | gen_string_movl_A0_EDI(s); | 879 | gen_string_movl_A0_EDI(s); |
| 836 | gen_op_st_T0_A0(ot + s->mem_index); | 880 | gen_op_st_T0_A0(ot + s->mem_index); |
| 837 | - gen_op_movl_T0_Dshift[ot](); | ||
| 838 | -#ifdef TARGET_X86_64 | ||
| 839 | - if (s->aflag == 2) { | ||
| 840 | - gen_op_addq_EDI_T0(); | ||
| 841 | - } else | ||
| 842 | -#endif | ||
| 843 | - if (s->aflag) { | ||
| 844 | - gen_op_addl_EDI_T0(); | ||
| 845 | - } else { | ||
| 846 | - gen_op_addw_EDI_T0(); | ||
| 847 | - } | 881 | + gen_op_movl_T0_Dshift(ot); |
| 882 | + gen_op_add_reg_T0(s->aflag, R_EDI); | ||
| 848 | } | 883 | } |
| 849 | 884 | ||
| 850 | static inline void gen_lods(DisasContext *s, int ot) | 885 | static inline void gen_lods(DisasContext *s, int ot) |
| @@ -852,17 +887,8 @@ static inline void gen_lods(DisasContext *s, int ot) | @@ -852,17 +887,8 @@ static inline void gen_lods(DisasContext *s, int ot) | ||
| 852 | gen_string_movl_A0_ESI(s); | 887 | gen_string_movl_A0_ESI(s); |
| 853 | gen_op_ld_T0_A0(ot + s->mem_index); | 888 | gen_op_ld_T0_A0(ot + s->mem_index); |
| 854 | gen_op_mov_reg_T0(ot, R_EAX); | 889 | gen_op_mov_reg_T0(ot, R_EAX); |
| 855 | - gen_op_movl_T0_Dshift[ot](); | ||
| 856 | -#ifdef TARGET_X86_64 | ||
| 857 | - if (s->aflag == 2) { | ||
| 858 | - gen_op_addq_ESI_T0(); | ||
| 859 | - } else | ||
| 860 | -#endif | ||
| 861 | - if (s->aflag) { | ||
| 862 | - gen_op_addl_ESI_T0(); | ||
| 863 | - } else { | ||
| 864 | - gen_op_addw_ESI_T0(); | ||
| 865 | - } | 890 | + gen_op_movl_T0_Dshift(ot); |
| 891 | + gen_op_add_reg_T0(s->aflag, R_ESI); | ||
| 866 | } | 892 | } |
| 867 | 893 | ||
| 868 | static inline void gen_scas(DisasContext *s, int ot) | 894 | static inline void gen_scas(DisasContext *s, int ot) |
| @@ -871,17 +897,8 @@ static inline void gen_scas(DisasContext *s, int ot) | @@ -871,17 +897,8 @@ static inline void gen_scas(DisasContext *s, int ot) | ||
| 871 | gen_string_movl_A0_EDI(s); | 897 | gen_string_movl_A0_EDI(s); |
| 872 | gen_op_ld_T1_A0(ot + s->mem_index); | 898 | gen_op_ld_T1_A0(ot + s->mem_index); |
| 873 | gen_op_cmpl_T0_T1_cc(); | 899 | gen_op_cmpl_T0_T1_cc(); |
| 874 | - gen_op_movl_T0_Dshift[ot](); | ||
| 875 | -#ifdef TARGET_X86_64 | ||
| 876 | - if (s->aflag == 2) { | ||
| 877 | - gen_op_addq_EDI_T0(); | ||
| 878 | - } else | ||
| 879 | -#endif | ||
| 880 | - if (s->aflag) { | ||
| 881 | - gen_op_addl_EDI_T0(); | ||
| 882 | - } else { | ||
| 883 | - gen_op_addw_EDI_T0(); | ||
| 884 | - } | 900 | + gen_op_movl_T0_Dshift(ot); |
| 901 | + gen_op_add_reg_T0(s->aflag, R_EDI); | ||
| 885 | } | 902 | } |
| 886 | 903 | ||
| 887 | static inline void gen_cmps(DisasContext *s, int ot) | 904 | static inline void gen_cmps(DisasContext *s, int ot) |
| @@ -891,25 +908,16 @@ static inline void gen_cmps(DisasContext *s, int ot) | @@ -891,25 +908,16 @@ static inline void gen_cmps(DisasContext *s, int ot) | ||
| 891 | gen_string_movl_A0_EDI(s); | 908 | gen_string_movl_A0_EDI(s); |
| 892 | gen_op_ld_T1_A0(ot + s->mem_index); | 909 | gen_op_ld_T1_A0(ot + s->mem_index); |
| 893 | gen_op_cmpl_T0_T1_cc(); | 910 | gen_op_cmpl_T0_T1_cc(); |
| 894 | - gen_op_movl_T0_Dshift[ot](); | ||
| 895 | -#ifdef TARGET_X86_64 | ||
| 896 | - if (s->aflag == 2) { | ||
| 897 | - gen_op_addq_ESI_T0(); | ||
| 898 | - gen_op_addq_EDI_T0(); | ||
| 899 | - } else | ||
| 900 | -#endif | ||
| 901 | - if (s->aflag) { | ||
| 902 | - gen_op_addl_ESI_T0(); | ||
| 903 | - gen_op_addl_EDI_T0(); | ||
| 904 | - } else { | ||
| 905 | - gen_op_addw_ESI_T0(); | ||
| 906 | - gen_op_addw_EDI_T0(); | ||
| 907 | - } | 911 | + gen_op_movl_T0_Dshift(ot); |
| 912 | + gen_op_add_reg_T0(s->aflag, R_ESI); | ||
| 913 | + gen_op_add_reg_T0(s->aflag, R_EDI); | ||
| 908 | } | 914 | } |
| 909 | 915 | ||
| 910 | static inline void gen_ins(DisasContext *s, int ot) | 916 | static inline void gen_ins(DisasContext *s, int ot) |
| 911 | { | 917 | { |
| 912 | gen_string_movl_A0_EDI(s); | 918 | gen_string_movl_A0_EDI(s); |
| 919 | + /* Note: we must do this dummy write first to be restartable in | ||
| 920 | + case of page fault. */ | ||
| 913 | gen_op_movl_T0_0(); | 921 | gen_op_movl_T0_0(); |
| 914 | gen_op_st_T0_A0(ot + s->mem_index); | 922 | gen_op_st_T0_A0(ot + s->mem_index); |
| 915 | gen_op_mov_TN_reg(OT_WORD, 1, R_EDX); | 923 | gen_op_mov_TN_reg(OT_WORD, 1, R_EDX); |
| @@ -917,17 +925,8 @@ static inline void gen_ins(DisasContext *s, int ot) | @@ -917,17 +925,8 @@ static inline void gen_ins(DisasContext *s, int ot) | ||
| 917 | tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); | 925 | tcg_gen_andi_i32(cpu_tmp2_i32, cpu_tmp2_i32, 0xffff); |
| 918 | tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[0], cpu_tmp2_i32); | 926 | tcg_gen_helper_1_1(helper_in_func[ot], cpu_T[0], cpu_tmp2_i32); |
| 919 | gen_op_st_T0_A0(ot + s->mem_index); | 927 | gen_op_st_T0_A0(ot + s->mem_index); |
| 920 | - gen_op_movl_T0_Dshift[ot](); | ||
| 921 | -#ifdef TARGET_X86_64 | ||
| 922 | - if (s->aflag == 2) { | ||
| 923 | - gen_op_addq_EDI_T0(); | ||
| 924 | - } else | ||
| 925 | -#endif | ||
| 926 | - if (s->aflag) { | ||
| 927 | - gen_op_addl_EDI_T0(); | ||
| 928 | - } else { | ||
| 929 | - gen_op_addw_EDI_T0(); | ||
| 930 | - } | 928 | + gen_op_movl_T0_Dshift(ot); |
| 929 | + gen_op_add_reg_T0(s->aflag, R_EDI); | ||
| 931 | } | 930 | } |
| 932 | 931 | ||
| 933 | static inline void gen_outs(DisasContext *s, int ot) | 932 | static inline void gen_outs(DisasContext *s, int ot) |
| @@ -941,17 +940,8 @@ static inline void gen_outs(DisasContext *s, int ot) | @@ -941,17 +940,8 @@ static inline void gen_outs(DisasContext *s, int ot) | ||
| 941 | tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]); | 940 | tcg_gen_trunc_tl_i32(cpu_tmp3_i32, cpu_T[0]); |
| 942 | tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2_i32, cpu_tmp3_i32); | 941 | tcg_gen_helper_0_2(helper_out_func[ot], cpu_tmp2_i32, cpu_tmp3_i32); |
| 943 | 942 | ||
| 944 | - gen_op_movl_T0_Dshift[ot](); | ||
| 945 | -#ifdef TARGET_X86_64 | ||
| 946 | - if (s->aflag == 2) { | ||
| 947 | - gen_op_addq_ESI_T0(); | ||
| 948 | - } else | ||
| 949 | -#endif | ||
| 950 | - if (s->aflag) { | ||
| 951 | - gen_op_addl_ESI_T0(); | ||
| 952 | - } else { | ||
| 953 | - gen_op_addw_ESI_T0(); | ||
| 954 | - } | 943 | + gen_op_movl_T0_Dshift(ot); |
| 944 | + gen_op_add_reg_T0(s->aflag, R_ESI); | ||
| 955 | } | 945 | } |
| 956 | 946 | ||
| 957 | /* same method as Valgrind : we generate jumps to current or next | 947 | /* same method as Valgrind : we generate jumps to current or next |
| @@ -964,11 +954,11 @@ static inline void gen_repz_ ## op(DisasContext *s, int ot, \ | @@ -964,11 +954,11 @@ static inline void gen_repz_ ## op(DisasContext *s, int ot, \ | ||
| 964 | gen_update_cc_op(s); \ | 954 | gen_update_cc_op(s); \ |
| 965 | l2 = gen_jz_ecx_string(s, next_eip); \ | 955 | l2 = gen_jz_ecx_string(s, next_eip); \ |
| 966 | gen_ ## op(s, ot); \ | 956 | gen_ ## op(s, ot); \ |
| 967 | - gen_op_dec_ECX[s->aflag](); \ | 957 | + gen_op_add_reg_im(s->aflag, R_ECX, -1); \ |
| 968 | /* a loop would cause two single step exceptions if ECX = 1 \ | 958 | /* a loop would cause two single step exceptions if ECX = 1 \ |
| 969 | before rep string_insn */ \ | 959 | before rep string_insn */ \ |
| 970 | if (!s->jmp_opt) \ | 960 | if (!s->jmp_opt) \ |
| 971 | - gen_op_jz_ecx[s->aflag](l2); \ | 961 | + gen_op_jz_ecx(s->aflag, l2); \ |
| 972 | gen_jmp(s, cur_eip); \ | 962 | gen_jmp(s, cur_eip); \ |
| 973 | } | 963 | } |
| 974 | 964 | ||
| @@ -982,11 +972,11 @@ static inline void gen_repz_ ## op(DisasContext *s, int ot, \ | @@ -982,11 +972,11 @@ static inline void gen_repz_ ## op(DisasContext *s, int ot, \ | ||
| 982 | gen_update_cc_op(s); \ | 972 | gen_update_cc_op(s); \ |
| 983 | l2 = gen_jz_ecx_string(s, next_eip); \ | 973 | l2 = gen_jz_ecx_string(s, next_eip); \ |
| 984 | gen_ ## op(s, ot); \ | 974 | gen_ ## op(s, ot); \ |
| 985 | - gen_op_dec_ECX[s->aflag](); \ | 975 | + gen_op_add_reg_im(s->aflag, R_ECX, -1); \ |
| 986 | gen_op_set_cc_op(CC_OP_SUBB + ot); \ | 976 | gen_op_set_cc_op(CC_OP_SUBB + ot); \ |
| 987 | gen_op_string_jnz_sub[nz][ot](l2);\ | 977 | gen_op_string_jnz_sub[nz][ot](l2);\ |
| 988 | if (!s->jmp_opt) \ | 978 | if (!s->jmp_opt) \ |
| 989 | - gen_op_jz_ecx[s->aflag](l2); \ | 979 | + gen_op_jz_ecx(s->aflag, l2); \ |
| 990 | gen_jmp(s, cur_eip); \ | 980 | gen_jmp(s, cur_eip); \ |
| 991 | } | 981 | } |
| 992 | 982 | ||
| @@ -1053,25 +1043,6 @@ static GenOpFunc1 *gen_jcc_sub[4][8] = { | @@ -1053,25 +1043,6 @@ static GenOpFunc1 *gen_jcc_sub[4][8] = { | ||
| 1053 | }, | 1043 | }, |
| 1054 | #endif | 1044 | #endif |
| 1055 | }; | 1045 | }; |
| 1056 | -static GenOpFunc1 *gen_op_loop[3][4] = { | ||
| 1057 | - [0] = { | ||
| 1058 | - gen_op_loopnzw, | ||
| 1059 | - gen_op_loopzw, | ||
| 1060 | - gen_op_jnz_ecxw, | ||
| 1061 | - }, | ||
| 1062 | - [1] = { | ||
| 1063 | - gen_op_loopnzl, | ||
| 1064 | - gen_op_loopzl, | ||
| 1065 | - gen_op_jnz_ecxl, | ||
| 1066 | - }, | ||
| 1067 | -#ifdef TARGET_X86_64 | ||
| 1068 | - [2] = { | ||
| 1069 | - gen_op_loopnzq, | ||
| 1070 | - gen_op_loopzq, | ||
| 1071 | - gen_op_jnz_ecxq, | ||
| 1072 | - }, | ||
| 1073 | -#endif | ||
| 1074 | -}; | ||
| 1075 | 1046 | ||
| 1076 | static GenOpFunc *gen_setcc_slow[8] = { | 1047 | static GenOpFunc *gen_setcc_slow[8] = { |
| 1077 | gen_op_seto_T0_cc, | 1048 | gen_op_seto_T0_cc, |
| @@ -1316,40 +1287,6 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) | @@ -1316,40 +1287,6 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) | ||
| 1316 | tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); | 1287 | tcg_gen_mov_tl(cpu_cc_dst, cpu_T[0]); |
| 1317 | } | 1288 | } |
| 1318 | 1289 | ||
| 1319 | -static void gen_extu(int ot, TCGv reg) | ||
| 1320 | -{ | ||
| 1321 | - switch(ot) { | ||
| 1322 | - case OT_BYTE: | ||
| 1323 | - tcg_gen_ext8u_tl(reg, reg); | ||
| 1324 | - break; | ||
| 1325 | - case OT_WORD: | ||
| 1326 | - tcg_gen_ext16u_tl(reg, reg); | ||
| 1327 | - break; | ||
| 1328 | - case OT_LONG: | ||
| 1329 | - tcg_gen_ext32u_tl(reg, reg); | ||
| 1330 | - break; | ||
| 1331 | - default: | ||
| 1332 | - break; | ||
| 1333 | - } | ||
| 1334 | -} | ||
| 1335 | - | ||
| 1336 | -static void gen_exts(int ot, TCGv reg) | ||
| 1337 | -{ | ||
| 1338 | - switch(ot) { | ||
| 1339 | - case OT_BYTE: | ||
| 1340 | - tcg_gen_ext8s_tl(reg, reg); | ||
| 1341 | - break; | ||
| 1342 | - case OT_WORD: | ||
| 1343 | - tcg_gen_ext16s_tl(reg, reg); | ||
| 1344 | - break; | ||
| 1345 | - case OT_LONG: | ||
| 1346 | - tcg_gen_ext32s_tl(reg, reg); | ||
| 1347 | - break; | ||
| 1348 | - default: | ||
| 1349 | - break; | ||
| 1350 | - } | ||
| 1351 | -} | ||
| 1352 | - | ||
| 1353 | /* XXX: add faster immediate case */ | 1290 | /* XXX: add faster immediate case */ |
| 1354 | static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, | 1291 | static void gen_shift_rm_T1(DisasContext *s, int ot, int op1, |
| 1355 | int is_right, int is_arith) | 1292 | int is_right, int is_arith) |
| @@ -2318,13 +2255,13 @@ static inline void gen_stack_update(DisasContext *s, int addend) | @@ -2318,13 +2255,13 @@ static inline void gen_stack_update(DisasContext *s, int addend) | ||
| 2318 | { | 2255 | { |
| 2319 | #ifdef TARGET_X86_64 | 2256 | #ifdef TARGET_X86_64 |
| 2320 | if (CODE64(s)) { | 2257 | if (CODE64(s)) { |
| 2321 | - gen_op_addq_ESP_im(addend); | 2258 | + gen_op_add_reg_im(2, R_ESP, addend); |
| 2322 | } else | 2259 | } else |
| 2323 | #endif | 2260 | #endif |
| 2324 | if (s->ss32) { | 2261 | if (s->ss32) { |
| 2325 | - gen_op_addl_ESP_im(addend); | 2262 | + gen_op_add_reg_im(1, R_ESP, addend); |
| 2326 | } else { | 2263 | } else { |
| 2327 | - gen_op_addw_ESP_im(addend); | 2264 | + gen_op_add_reg_im(0, R_ESP, addend); |
| 2328 | } | 2265 | } |
| 2329 | } | 2266 | } |
| 2330 | 2267 | ||
| @@ -6066,13 +6003,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6066,13 +6003,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6066 | break; | 6003 | break; |
| 6067 | case 0xe0: /* loopnz */ | 6004 | case 0xe0: /* loopnz */ |
| 6068 | case 0xe1: /* loopz */ | 6005 | case 0xe1: /* loopz */ |
| 6069 | - if (s->cc_op != CC_OP_DYNAMIC) | ||
| 6070 | - gen_op_set_cc_op(s->cc_op); | ||
| 6071 | - /* FALL THRU */ | ||
| 6072 | case 0xe2: /* loop */ | 6006 | case 0xe2: /* loop */ |
| 6073 | case 0xe3: /* jecxz */ | 6007 | case 0xe3: /* jecxz */ |
| 6074 | { | 6008 | { |
| 6075 | - int l1, l2; | 6009 | + int l1, l2, l3; |
| 6076 | 6010 | ||
| 6077 | tval = (int8_t)insn_get(s, OT_BYTE); | 6011 | tval = (int8_t)insn_get(s, OT_BYTE); |
| 6078 | next_eip = s->pc - s->cs_base; | 6012 | next_eip = s->pc - s->cs_base; |
| @@ -6082,18 +6016,39 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | @@ -6082,18 +6016,39 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) | ||
| 6082 | 6016 | ||
| 6083 | l1 = gen_new_label(); | 6017 | l1 = gen_new_label(); |
| 6084 | l2 = gen_new_label(); | 6018 | l2 = gen_new_label(); |
| 6019 | + l3 = gen_new_label(); | ||
| 6085 | b &= 3; | 6020 | b &= 3; |
| 6086 | - if (b == 3) { | ||
| 6087 | - gen_op_jz_ecx[s->aflag](l1); | ||
| 6088 | - } else { | ||
| 6089 | - gen_op_dec_ECX[s->aflag](); | ||
| 6090 | - if (b <= 1) | ||
| 6091 | - gen_op_mov_T0_cc(); | ||
| 6092 | - gen_op_loop[s->aflag][b](l1); | 6021 | + switch(b) { |
| 6022 | + case 0: /* loopnz */ | ||
| 6023 | + case 1: /* loopz */ | ||
| 6024 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 6025 | + gen_op_set_cc_op(s->cc_op); | ||
| 6026 | + gen_op_add_reg_im(s->aflag, R_ECX, -1); | ||
| 6027 | + gen_op_jz_ecx(s->aflag, l3); | ||
| 6028 | + gen_compute_eflags(cpu_tmp0); | ||
| 6029 | + tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, CC_Z); | ||
| 6030 | + if (b == 0) { | ||
| 6031 | + tcg_gen_brcond_tl(TCG_COND_EQ, | ||
| 6032 | + cpu_tmp0, tcg_const_tl(0), l1); | ||
| 6033 | + } else { | ||
| 6034 | + tcg_gen_brcond_tl(TCG_COND_NE, | ||
| 6035 | + cpu_tmp0, tcg_const_tl(0), l1); | ||
| 6036 | + } | ||
| 6037 | + break; | ||
| 6038 | + case 2: /* loop */ | ||
| 6039 | + gen_op_add_reg_im(s->aflag, R_ECX, -1); | ||
| 6040 | + gen_op_jnz_ecx(s->aflag, l1); | ||
| 6041 | + break; | ||
| 6042 | + default: | ||
| 6043 | + case 3: /* jcxz */ | ||
| 6044 | + gen_op_jz_ecx(s->aflag, l1); | ||
| 6045 | + break; | ||
| 6093 | } | 6046 | } |
| 6094 | 6047 | ||
| 6048 | + gen_set_label(l3); | ||
| 6095 | gen_jmp_im(next_eip); | 6049 | gen_jmp_im(next_eip); |
| 6096 | gen_op_jmp_label(l2); | 6050 | gen_op_jmp_label(l2); |
| 6051 | + | ||
| 6097 | gen_set_label(l1); | 6052 | gen_set_label(l1); |
| 6098 | gen_jmp_im(tval); | 6053 | gen_jmp_im(tval); |
| 6099 | gen_set_label(l2); | 6054 | gen_set_label(l2); |