diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-05-10 13:09:33 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-05-10 13:09:33 +0000 |
commit | 148dfc2a8be0b237ef80b4d421f549464aa6a3d0 (patch) | |
tree | e89158b68e39a2912b76797c6a349f2e8fbf7911 | |
parent | 3acace1333d6b75628fe6e6786ad3cd2db766f0e (diff) |
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
-rw-r--r-- | translate-i386.c | 207 |
1 files changed, 150 insertions, 57 deletions
diff --git a/translate-i386.c b/translate-i386.c index 8ddf14e729..ba36bedf9e 100644 --- a/translate-i386.c +++ b/translate-i386.c @@ -2771,6 +2771,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) if (s->cpl > s->iopl || s->vm86) { /* NOTE: even for (E)CX = 0 the exception is raised */ gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; } else { if ((b & 1) == 0) ot = OT_BYTE; @@ -2788,6 +2789,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) if (s->cpl > s->iopl || s->vm86) { /* NOTE: even for (E)CX = 0 the exception is raised */ gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; } else { if ((b & 1) == 0) ot = OT_BYTE; @@ -2807,6 +2809,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) case 0xe5: if (s->cpl > s->iopl || s->vm86) { gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; } else { if ((b & 1) == 0) ot = OT_BYTE; @@ -2822,6 +2825,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) case 0xe7: if (s->cpl > s->iopl || s->vm86) { gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; } else { if ((b & 1) == 0) ot = OT_BYTE; @@ -2837,6 +2841,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) case 0xed: if (s->cpl > s->iopl || s->vm86) { gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; } else { if ((b & 1) == 0) ot = OT_BYTE; @@ -2851,6 +2856,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) case 0xef: if (s->cpl > s->iopl || s->vm86) { gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; } else { if ((b & 1) == 0) ot = OT_BYTE; @@ -2901,9 +2907,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) gen_pop_update(s); /* add stack offset */ if (s->ss32) - gen_op_addl_ESP_im(val + (2 << s->dflag)); + gen_op_addl_ESP_im(val); else - gen_op_addw_ESP_im(val + (2 << s->dflag)); + gen_op_addw_ESP_im(val); s->is_jmp = 1; break; case 0xcb: /* lret */ @@ -2921,32 +2927,31 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) s->is_jmp = 1; break; case 0xcf: /* iret */ - /* XXX: not restartable */ - /* pop offset */ - gen_pop_T0(s); - if (s->dflag == 0) - gen_op_andl_T0_ffff(); - gen_op_jmp_T0(); - gen_pop_update(s); - /* pop selector */ - gen_pop_T0(s); - gen_movl_seg_T0(s, R_CS); - gen_pop_update(s); - /* pop eflags */ - gen_pop_T0(s); - if (s->dflag) { - if (s->vm86) - gen_op_movl_eflags_T0_vm(pc_start - s->cs_base); - else - gen_op_movl_eflags_T0(); + if (s->vm86 && s->iopl != 3) { + gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; } else { - if (s->vm86) - gen_op_movw_eflags_T0_vm(pc_start - s->cs_base); - else + /* XXX: not restartable */ + /* pop offset */ + gen_pop_T0(s); + if (s->dflag == 0) + gen_op_andl_T0_ffff(); + gen_op_jmp_T0(); + gen_pop_update(s); + /* pop selector */ + gen_pop_T0(s); + gen_movl_seg_T0(s, R_CS); + gen_pop_update(s); + /* pop eflags */ + gen_pop_T0(s); + if (s->dflag) { + gen_op_movl_eflags_T0(); + } else { gen_op_movw_eflags_T0(); + } + gen_pop_update(s); + s->cc_op = CC_OP_EFLAGS; } - gen_pop_update(s); - s->cc_op = CC_OP_EFLAGS; s->is_jmp = 1; break; case 0xe8: /* call im */ @@ -3060,29 +3065,30 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) /************************/ /* flags */ case 0x9c: /* pushf */ - if (s->cc_op != CC_OP_DYNAMIC) - gen_op_set_cc_op(s->cc_op); - if (s->vm86) - gen_op_movl_T0_eflags_vm(); - else + if (s->vm86 && s->iopl != 3) { + gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; + } else { + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); gen_op_movl_T0_eflags(); - gen_push_T0(s); + gen_push_T0(s); + } break; case 0x9d: /* popf */ - gen_pop_T0(s); - if (s->dflag) { - if (s->vm86) - gen_op_movl_eflags_T0_vm(pc_start - s->cs_base); - else - gen_op_movl_eflags_T0(); + if (s->vm86 && s->iopl != 3) { + gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; } else { - if (s->vm86) - gen_op_movw_eflags_T0_vm(pc_start - s->cs_base); - else + gen_pop_T0(s); + if (s->dflag) { + gen_op_movl_eflags_T0(); + } else { gen_op_movw_eflags_T0(); + } + gen_pop_update(s); + s->cc_op = CC_OP_EFLAGS; } - gen_pop_update(s); - s->cc_op = CC_OP_EFLAGS; break; case 0x9e: /* sahf */ gen_op_mov_TN_reg[OT_BYTE][0][R_AH](); @@ -3257,28 +3263,36 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) break; case 0xfa: /* cli */ if (!s->vm86) { - if (s->cpl <= s->iopl) + if (s->cpl <= s->iopl) { gen_op_cli(); - else + } else { gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; + } } else { - if (s->iopl == 3) + if (s->iopl == 3) { gen_op_cli(); - else - gen_op_cli_vm(); + } else { + gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; + } } break; case 0xfb: /* sti */ if (!s->vm86) { - if (s->cpl <= s->iopl) + if (s->cpl <= s->iopl) { gen_op_sti(); - else + } else { gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; + } } else { - if (s->iopl == 3) + if (s->iopl == 3) { gen_op_sti(); - else - gen_op_sti_vm(pc_start - s->cs_base); + } else { + gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; + } } break; case 0x62: /* bound */ @@ -3328,11 +3342,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_cpuid(); break; case 0xf4: /* hlt */ - if (s->cpl == 0) { - /* ignored */ - } else { - gen_op_gpf(pc_start - s->cs_base); - } + /* XXX: if cpl == 0, then should do something else */ + gen_op_gpf(pc_start - s->cs_base); + s->is_jmp = 1; break; default: goto illegal_op; @@ -3817,3 +3829,84 @@ void cpu_x86_close(CPUX86State *env) { free(env); } + +static const char *cc_op_str[] = { + "DYNAMIC", + "EFLAGS", + "MUL", + "ADDB", + "ADDW", + "ADDL", + "ADCB", + "ADCW", + "ADCL", + "SUBB", + "SUBW", + "SUBL", + "SBBB", + "SBBW", + "SBBL", + "LOGICB", + "LOGICW", + "LOGICL", + "INCB", + "INCW", + "INCL", + "DECB", + "DECW", + "DECL", + "SHLB", + "SHLW", + "SHLL", + "SARB", + "SARW", + "SARL", +}; + +void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags) +{ + int eflags; + char cc_op_name[32]; + + eflags = env->eflags; + fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" + "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" + "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n", + env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], + env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], + env->eip, eflags, + eflags & DF_MASK ? 'D' : '-', + eflags & CC_O ? 'O' : '-', + eflags & CC_S ? 'S' : '-', + eflags & CC_Z ? 'Z' : '-', + eflags & CC_A ? 'A' : '-', + eflags & CC_P ? 'P' : '-', + eflags & CC_C ? 'C' : '-'); + fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n", + env->segs[R_CS], + env->segs[R_SS], + env->segs[R_DS], + env->segs[R_ES], + env->segs[R_FS], + env->segs[R_GS]); + if (flags & X86_DUMP_CCOP) { + if ((unsigned)env->cc_op < CC_OP_NB) + strcpy(cc_op_name, cc_op_str[env->cc_op]); + else + snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op); + fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n", + env->cc_src, env->cc_dst, cc_op_name); + } + if (flags & X86_DUMP_FPU) { + fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n", + (double)env->fpregs[0], + (double)env->fpregs[1], + (double)env->fpregs[2], + (double)env->fpregs[3]); + fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n", + (double)env->fpregs[4], + (double)env->fpregs[5], + (double)env->fpregs[7], + (double)env->fpregs[8]); + } +} |