Commit 148dfc2a8be0b237ef80b4d421f549464aa6a3d0
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,6 +2771,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2771 | if (s->cpl > s->iopl || s->vm86) { | 2771 | if (s->cpl > s->iopl || s->vm86) { |
| 2772 | /* NOTE: even for (E)CX = 0 the exception is raised */ | 2772 | /* NOTE: even for (E)CX = 0 the exception is raised */ |
| 2773 | gen_op_gpf(pc_start - s->cs_base); | 2773 | gen_op_gpf(pc_start - s->cs_base); |
| 2774 | + s->is_jmp = 1; | ||
| 2774 | } else { | 2775 | } else { |
| 2775 | if ((b & 1) == 0) | 2776 | if ((b & 1) == 0) |
| 2776 | ot = OT_BYTE; | 2777 | ot = OT_BYTE; |
| @@ -2788,6 +2789,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2788,6 +2789,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2788 | if (s->cpl > s->iopl || s->vm86) { | 2789 | if (s->cpl > s->iopl || s->vm86) { |
| 2789 | /* NOTE: even for (E)CX = 0 the exception is raised */ | 2790 | /* NOTE: even for (E)CX = 0 the exception is raised */ |
| 2790 | gen_op_gpf(pc_start - s->cs_base); | 2791 | gen_op_gpf(pc_start - s->cs_base); |
| 2792 | + s->is_jmp = 1; | ||
| 2791 | } else { | 2793 | } else { |
| 2792 | if ((b & 1) == 0) | 2794 | if ((b & 1) == 0) |
| 2793 | ot = OT_BYTE; | 2795 | ot = OT_BYTE; |
| @@ -2807,6 +2809,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2807,6 +2809,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2807 | case 0xe5: | 2809 | case 0xe5: |
| 2808 | if (s->cpl > s->iopl || s->vm86) { | 2810 | if (s->cpl > s->iopl || s->vm86) { |
| 2809 | gen_op_gpf(pc_start - s->cs_base); | 2811 | gen_op_gpf(pc_start - s->cs_base); |
| 2812 | + s->is_jmp = 1; | ||
| 2810 | } else { | 2813 | } else { |
| 2811 | if ((b & 1) == 0) | 2814 | if ((b & 1) == 0) |
| 2812 | ot = OT_BYTE; | 2815 | ot = OT_BYTE; |
| @@ -2822,6 +2825,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2822,6 +2825,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2822 | case 0xe7: | 2825 | case 0xe7: |
| 2823 | if (s->cpl > s->iopl || s->vm86) { | 2826 | if (s->cpl > s->iopl || s->vm86) { |
| 2824 | gen_op_gpf(pc_start - s->cs_base); | 2827 | gen_op_gpf(pc_start - s->cs_base); |
| 2828 | + s->is_jmp = 1; | ||
| 2825 | } else { | 2829 | } else { |
| 2826 | if ((b & 1) == 0) | 2830 | if ((b & 1) == 0) |
| 2827 | ot = OT_BYTE; | 2831 | ot = OT_BYTE; |
| @@ -2837,6 +2841,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2837,6 +2841,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2837 | case 0xed: | 2841 | case 0xed: |
| 2838 | if (s->cpl > s->iopl || s->vm86) { | 2842 | if (s->cpl > s->iopl || s->vm86) { |
| 2839 | gen_op_gpf(pc_start - s->cs_base); | 2843 | gen_op_gpf(pc_start - s->cs_base); |
| 2844 | + s->is_jmp = 1; | ||
| 2840 | } else { | 2845 | } else { |
| 2841 | if ((b & 1) == 0) | 2846 | if ((b & 1) == 0) |
| 2842 | ot = OT_BYTE; | 2847 | ot = OT_BYTE; |
| @@ -2851,6 +2856,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2851,6 +2856,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2851 | case 0xef: | 2856 | case 0xef: |
| 2852 | if (s->cpl > s->iopl || s->vm86) { | 2857 | if (s->cpl > s->iopl || s->vm86) { |
| 2853 | gen_op_gpf(pc_start - s->cs_base); | 2858 | gen_op_gpf(pc_start - s->cs_base); |
| 2859 | + s->is_jmp = 1; | ||
| 2854 | } else { | 2860 | } else { |
| 2855 | if ((b & 1) == 0) | 2861 | if ((b & 1) == 0) |
| 2856 | ot = OT_BYTE; | 2862 | ot = OT_BYTE; |
| @@ -2901,9 +2907,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2901,9 +2907,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2901 | gen_pop_update(s); | 2907 | gen_pop_update(s); |
| 2902 | /* add stack offset */ | 2908 | /* add stack offset */ |
| 2903 | if (s->ss32) | 2909 | if (s->ss32) |
| 2904 | - gen_op_addl_ESP_im(val + (2 << s->dflag)); | 2910 | + gen_op_addl_ESP_im(val); |
| 2905 | else | 2911 | else |
| 2906 | - gen_op_addw_ESP_im(val + (2 << s->dflag)); | 2912 | + gen_op_addw_ESP_im(val); |
| 2907 | s->is_jmp = 1; | 2913 | s->is_jmp = 1; |
| 2908 | break; | 2914 | break; |
| 2909 | case 0xcb: /* lret */ | 2915 | case 0xcb: /* lret */ |
| @@ -2921,32 +2927,31 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2921,32 +2927,31 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2921 | s->is_jmp = 1; | 2927 | s->is_jmp = 1; |
| 2922 | break; | 2928 | break; |
| 2923 | case 0xcf: /* iret */ | 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 | } else { | 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 | gen_op_movw_eflags_T0(); | 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 | s->is_jmp = 1; | 2955 | s->is_jmp = 1; |
| 2951 | break; | 2956 | break; |
| 2952 | case 0xe8: /* call im */ | 2957 | case 0xe8: /* call im */ |
| @@ -3060,29 +3065,30 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3060,29 +3065,30 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3060 | /************************/ | 3065 | /************************/ |
| 3061 | /* flags */ | 3066 | /* flags */ |
| 3062 | case 0x9c: /* pushf */ | 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 | gen_op_movl_T0_eflags(); | 3074 | gen_op_movl_T0_eflags(); |
| 3069 | - gen_push_T0(s); | 3075 | + gen_push_T0(s); |
| 3076 | + } | ||
| 3070 | break; | 3077 | break; |
| 3071 | case 0x9d: /* popf */ | 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 | } else { | 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 | gen_op_movw_eflags_T0(); | 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 | break; | 3092 | break; |
| 3087 | case 0x9e: /* sahf */ | 3093 | case 0x9e: /* sahf */ |
| 3088 | gen_op_mov_TN_reg[OT_BYTE][0][R_AH](); | 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,28 +3263,36 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3257 | break; | 3263 | break; |
| 3258 | case 0xfa: /* cli */ | 3264 | case 0xfa: /* cli */ |
| 3259 | if (!s->vm86) { | 3265 | if (!s->vm86) { |
| 3260 | - if (s->cpl <= s->iopl) | 3266 | + if (s->cpl <= s->iopl) { |
| 3261 | gen_op_cli(); | 3267 | gen_op_cli(); |
| 3262 | - else | 3268 | + } else { |
| 3263 | gen_op_gpf(pc_start - s->cs_base); | 3269 | gen_op_gpf(pc_start - s->cs_base); |
| 3270 | + s->is_jmp = 1; | ||
| 3271 | + } | ||
| 3264 | } else { | 3272 | } else { |
| 3265 | - if (s->iopl == 3) | 3273 | + if (s->iopl == 3) { |
| 3266 | gen_op_cli(); | 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 | break; | 3280 | break; |
| 3271 | case 0xfb: /* sti */ | 3281 | case 0xfb: /* sti */ |
| 3272 | if (!s->vm86) { | 3282 | if (!s->vm86) { |
| 3273 | - if (s->cpl <= s->iopl) | 3283 | + if (s->cpl <= s->iopl) { |
| 3274 | gen_op_sti(); | 3284 | gen_op_sti(); |
| 3275 | - else | 3285 | + } else { |
| 3276 | gen_op_gpf(pc_start - s->cs_base); | 3286 | gen_op_gpf(pc_start - s->cs_base); |
| 3287 | + s->is_jmp = 1; | ||
| 3288 | + } | ||
| 3277 | } else { | 3289 | } else { |
| 3278 | - if (s->iopl == 3) | 3290 | + if (s->iopl == 3) { |
| 3279 | gen_op_sti(); | 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 | break; | 3297 | break; |
| 3284 | case 0x62: /* bound */ | 3298 | case 0x62: /* bound */ |
| @@ -3328,11 +3342,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3328,11 +3342,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3328 | gen_op_cpuid(); | 3342 | gen_op_cpuid(); |
| 3329 | break; | 3343 | break; |
| 3330 | case 0xf4: /* hlt */ | 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 | break; | 3348 | break; |
| 3337 | default: | 3349 | default: |
| 3338 | goto illegal_op; | 3350 | goto illegal_op; |
| @@ -3817,3 +3829,84 @@ void cpu_x86_close(CPUX86State *env) | @@ -3817,3 +3829,84 @@ void cpu_x86_close(CPUX86State *env) | ||
| 3817 | { | 3829 | { |
| 3818 | free(env); | 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 | +} |