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,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 +}