Commit 148dfc2a8be0b237ef80b4d421f549464aa6a3d0

Authored by bellard
1 parent 3acace13

fixed GPF generation - fixed 'lret im' instruction (main fix for dosemu) - fixed HLT instruction


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@141 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 150 additions and 57 deletions
translate-i386.c
... ... @@ -2771,6 +2771,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2771 2771 if (s->cpl > s->iopl || s->vm86) {
2772 2772 /* NOTE: even for (E)CX = 0 the exception is raised */
2773 2773 gen_op_gpf(pc_start - s->cs_base);
  2774 + s->is_jmp = 1;
2774 2775 } else {
2775 2776 if ((b & 1) == 0)
2776 2777 ot = OT_BYTE;
... ... @@ -2788,6 +2789,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2788 2789 if (s->cpl > s->iopl || s->vm86) {
2789 2790 /* NOTE: even for (E)CX = 0 the exception is raised */
2790 2791 gen_op_gpf(pc_start - s->cs_base);
  2792 + s->is_jmp = 1;
2791 2793 } else {
2792 2794 if ((b & 1) == 0)
2793 2795 ot = OT_BYTE;
... ... @@ -2807,6 +2809,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2807 2809 case 0xe5:
2808 2810 if (s->cpl > s->iopl || s->vm86) {
2809 2811 gen_op_gpf(pc_start - s->cs_base);
  2812 + s->is_jmp = 1;
2810 2813 } else {
2811 2814 if ((b & 1) == 0)
2812 2815 ot = OT_BYTE;
... ... @@ -2822,6 +2825,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2822 2825 case 0xe7:
2823 2826 if (s->cpl > s->iopl || s->vm86) {
2824 2827 gen_op_gpf(pc_start - s->cs_base);
  2828 + s->is_jmp = 1;
2825 2829 } else {
2826 2830 if ((b & 1) == 0)
2827 2831 ot = OT_BYTE;
... ... @@ -2837,6 +2841,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2837 2841 case 0xed:
2838 2842 if (s->cpl > s->iopl || s->vm86) {
2839 2843 gen_op_gpf(pc_start - s->cs_base);
  2844 + s->is_jmp = 1;
2840 2845 } else {
2841 2846 if ((b & 1) == 0)
2842 2847 ot = OT_BYTE;
... ... @@ -2851,6 +2856,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2851 2856 case 0xef:
2852 2857 if (s->cpl > s->iopl || s->vm86) {
2853 2858 gen_op_gpf(pc_start - s->cs_base);
  2859 + s->is_jmp = 1;
2854 2860 } else {
2855 2861 if ((b & 1) == 0)
2856 2862 ot = OT_BYTE;
... ... @@ -2901,9 +2907,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2901 2907 gen_pop_update(s);
2902 2908 /* add stack offset */
2903 2909 if (s->ss32)
2904   - gen_op_addl_ESP_im(val + (2 << s->dflag));
  2910 + gen_op_addl_ESP_im(val);
2905 2911 else
2906   - gen_op_addw_ESP_im(val + (2 << s->dflag));
  2912 + gen_op_addw_ESP_im(val);
2907 2913 s->is_jmp = 1;
2908 2914 break;
2909 2915 case 0xcb: /* lret */
... ... @@ -2921,32 +2927,31 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2921 2927 s->is_jmp = 1;
2922 2928 break;
2923 2929 case 0xcf: /* iret */
2924   - /* XXX: not restartable */
2925   - /* pop offset */
2926   - gen_pop_T0(s);
2927   - if (s->dflag == 0)
2928   - gen_op_andl_T0_ffff();
2929   - gen_op_jmp_T0();
2930   - gen_pop_update(s);
2931   - /* pop selector */
2932   - gen_pop_T0(s);
2933   - gen_movl_seg_T0(s, R_CS);
2934   - gen_pop_update(s);
2935   - /* pop eflags */
2936   - gen_pop_T0(s);
2937   - if (s->dflag) {
2938   - if (s->vm86)
2939   - gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
2940   - else
2941   - gen_op_movl_eflags_T0();
  2930 + if (s->vm86 && s->iopl != 3) {
  2931 + gen_op_gpf(pc_start - s->cs_base);
  2932 + s->is_jmp = 1;
2942 2933 } else {
2943   - if (s->vm86)
2944   - gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
2945   - else
  2934 + /* XXX: not restartable */
  2935 + /* pop offset */
  2936 + gen_pop_T0(s);
  2937 + if (s->dflag == 0)
  2938 + gen_op_andl_T0_ffff();
  2939 + gen_op_jmp_T0();
  2940 + gen_pop_update(s);
  2941 + /* pop selector */
  2942 + gen_pop_T0(s);
  2943 + gen_movl_seg_T0(s, R_CS);
  2944 + gen_pop_update(s);
  2945 + /* pop eflags */
  2946 + gen_pop_T0(s);
  2947 + if (s->dflag) {
  2948 + gen_op_movl_eflags_T0();
  2949 + } else {
2946 2950 gen_op_movw_eflags_T0();
  2951 + }
  2952 + gen_pop_update(s);
  2953 + s->cc_op = CC_OP_EFLAGS;
2947 2954 }
2948   - gen_pop_update(s);
2949   - s->cc_op = CC_OP_EFLAGS;
2950 2955 s->is_jmp = 1;
2951 2956 break;
2952 2957 case 0xe8: /* call im */
... ... @@ -3060,29 +3065,30 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3060 3065 /************************/
3061 3066 /* flags */
3062 3067 case 0x9c: /* pushf */
3063   - if (s->cc_op != CC_OP_DYNAMIC)
3064   - gen_op_set_cc_op(s->cc_op);
3065   - if (s->vm86)
3066   - gen_op_movl_T0_eflags_vm();
3067   - else
  3068 + if (s->vm86 && s->iopl != 3) {
  3069 + gen_op_gpf(pc_start - s->cs_base);
  3070 + s->is_jmp = 1;
  3071 + } else {
  3072 + if (s->cc_op != CC_OP_DYNAMIC)
  3073 + gen_op_set_cc_op(s->cc_op);
3068 3074 gen_op_movl_T0_eflags();
3069   - gen_push_T0(s);
  3075 + gen_push_T0(s);
  3076 + }
3070 3077 break;
3071 3078 case 0x9d: /* popf */
3072   - gen_pop_T0(s);
3073   - if (s->dflag) {
3074   - if (s->vm86)
3075   - gen_op_movl_eflags_T0_vm(pc_start - s->cs_base);
3076   - else
3077   - gen_op_movl_eflags_T0();
  3079 + if (s->vm86 && s->iopl != 3) {
  3080 + gen_op_gpf(pc_start - s->cs_base);
  3081 + s->is_jmp = 1;
3078 3082 } else {
3079   - if (s->vm86)
3080   - gen_op_movw_eflags_T0_vm(pc_start - s->cs_base);
3081   - else
  3083 + gen_pop_T0(s);
  3084 + if (s->dflag) {
  3085 + gen_op_movl_eflags_T0();
  3086 + } else {
3082 3087 gen_op_movw_eflags_T0();
  3088 + }
  3089 + gen_pop_update(s);
  3090 + s->cc_op = CC_OP_EFLAGS;
3083 3091 }
3084   - gen_pop_update(s);
3085   - s->cc_op = CC_OP_EFLAGS;
3086 3092 break;
3087 3093 case 0x9e: /* sahf */
3088 3094 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
... ... @@ -3257,28 +3263,36 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3257 3263 break;
3258 3264 case 0xfa: /* cli */
3259 3265 if (!s->vm86) {
3260   - if (s->cpl <= s->iopl)
  3266 + if (s->cpl <= s->iopl) {
3261 3267 gen_op_cli();
3262   - else
  3268 + } else {
3263 3269 gen_op_gpf(pc_start - s->cs_base);
  3270 + s->is_jmp = 1;
  3271 + }
3264 3272 } else {
3265   - if (s->iopl == 3)
  3273 + if (s->iopl == 3) {
3266 3274 gen_op_cli();
3267   - else
3268   - gen_op_cli_vm();
  3275 + } else {
  3276 + gen_op_gpf(pc_start - s->cs_base);
  3277 + s->is_jmp = 1;
  3278 + }
3269 3279 }
3270 3280 break;
3271 3281 case 0xfb: /* sti */
3272 3282 if (!s->vm86) {
3273   - if (s->cpl <= s->iopl)
  3283 + if (s->cpl <= s->iopl) {
3274 3284 gen_op_sti();
3275   - else
  3285 + } else {
3276 3286 gen_op_gpf(pc_start - s->cs_base);
  3287 + s->is_jmp = 1;
  3288 + }
3277 3289 } else {
3278   - if (s->iopl == 3)
  3290 + if (s->iopl == 3) {
3279 3291 gen_op_sti();
3280   - else
3281   - gen_op_sti_vm(pc_start - s->cs_base);
  3292 + } else {
  3293 + gen_op_gpf(pc_start - s->cs_base);
  3294 + s->is_jmp = 1;
  3295 + }
3282 3296 }
3283 3297 break;
3284 3298 case 0x62: /* bound */
... ... @@ -3328,11 +3342,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3328 3342 gen_op_cpuid();
3329 3343 break;
3330 3344 case 0xf4: /* hlt */
3331   - if (s->cpl == 0) {
3332   - /* ignored */
3333   - } else {
3334   - gen_op_gpf(pc_start - s->cs_base);
3335   - }
  3345 + /* XXX: if cpl == 0, then should do something else */
  3346 + gen_op_gpf(pc_start - s->cs_base);
  3347 + s->is_jmp = 1;
3336 3348 break;
3337 3349 default:
3338 3350 goto illegal_op;
... ... @@ -3817,3 +3829,84 @@ void cpu_x86_close(CPUX86State *env)
3817 3829 {
3818 3830 free(env);
3819 3831 }
  3832 +
  3833 +static const char *cc_op_str[] = {
  3834 + "DYNAMIC",
  3835 + "EFLAGS",
  3836 + "MUL",
  3837 + "ADDB",
  3838 + "ADDW",
  3839 + "ADDL",
  3840 + "ADCB",
  3841 + "ADCW",
  3842 + "ADCL",
  3843 + "SUBB",
  3844 + "SUBW",
  3845 + "SUBL",
  3846 + "SBBB",
  3847 + "SBBW",
  3848 + "SBBL",
  3849 + "LOGICB",
  3850 + "LOGICW",
  3851 + "LOGICL",
  3852 + "INCB",
  3853 + "INCW",
  3854 + "INCL",
  3855 + "DECB",
  3856 + "DECW",
  3857 + "DECL",
  3858 + "SHLB",
  3859 + "SHLW",
  3860 + "SHLL",
  3861 + "SARB",
  3862 + "SARW",
  3863 + "SARL",
  3864 +};
  3865 +
  3866 +void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
  3867 +{
  3868 + int eflags;
  3869 + char cc_op_name[32];
  3870 +
  3871 + eflags = env->eflags;
  3872 + fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
  3873 + "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
  3874 + "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
  3875 + env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
  3876 + env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
  3877 + env->eip, eflags,
  3878 + eflags & DF_MASK ? 'D' : '-',
  3879 + eflags & CC_O ? 'O' : '-',
  3880 + eflags & CC_S ? 'S' : '-',
  3881 + eflags & CC_Z ? 'Z' : '-',
  3882 + eflags & CC_A ? 'A' : '-',
  3883 + eflags & CC_P ? 'P' : '-',
  3884 + eflags & CC_C ? 'C' : '-');
  3885 + fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
  3886 + env->segs[R_CS],
  3887 + env->segs[R_SS],
  3888 + env->segs[R_DS],
  3889 + env->segs[R_ES],
  3890 + env->segs[R_FS],
  3891 + env->segs[R_GS]);
  3892 + if (flags & X86_DUMP_CCOP) {
  3893 + if ((unsigned)env->cc_op < CC_OP_NB)
  3894 + strcpy(cc_op_name, cc_op_str[env->cc_op]);
  3895 + else
  3896 + snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
  3897 + fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
  3898 + env->cc_src, env->cc_dst, cc_op_name);
  3899 + }
  3900 + if (flags & X86_DUMP_FPU) {
  3901 + fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
  3902 + (double)env->fpregs[0],
  3903 + (double)env->fpregs[1],
  3904 + (double)env->fpregs[2],
  3905 + (double)env->fpregs[3]);
  3906 + fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
  3907 + (double)env->fpregs[4],
  3908 + (double)env->fpregs[5],
  3909 + (double)env->fpregs[7],
  3910 + (double)env->fpregs[8]);
  3911 + }
  3912 +}
... ...