From patchwork Wed Mar 2 14:06:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 8480881 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A45ACC0553 for ; Wed, 2 Mar 2016 14:06:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B3808200DE for ; Wed, 2 Mar 2016 14:06:39 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B2CF6201EC for ; Wed, 2 Mar 2016 14:06:38 +0000 (UTC) Received: from localhost ([::1]:56681 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ab7QC-0007s2-UK for patchwork-qemu-devel@patchwork.kernel.org; Wed, 02 Mar 2016 09:06:36 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58558) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ab7Py-0007nm-LU for qemu-devel@nongnu.org; Wed, 02 Mar 2016 09:06:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ab7Pv-0005hD-Eo for qemu-devel@nongnu.org; Wed, 02 Mar 2016 09:06:22 -0500 Received: from mail-wm0-x233.google.com ([2a00:1450:400c:c09::233]:35060) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ab7Pv-0005gc-49 for qemu-devel@nongnu.org; Wed, 02 Mar 2016 09:06:19 -0500 Received: by mail-wm0-x233.google.com with SMTP id l68so86972587wml.0 for ; Wed, 02 Mar 2016 06:06:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:subject:to:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=YV+GH74rT8MD6Mw5LjyUmnZn3aXOx1MzPPFbC406/Vo=; b=bo7LBRtsxLSEU1mk4s895QUPuFUMRSqCLPqvVkwvjmxSXf9Qc+i2xJXSzUI/PfMo9T edo0neISnvI0aPKE2+H3rwGJfDDO9f1mJeCy/Sb6tuRBAN/D/hsHVWLLYK49vesbH9/I 5Usqgz6uiksAELsJOmS5RMETd7uvEn0g6dryXGQkbDEwftGZHjGyVWkpfoSXOpcZO766 mKYM6op21DqjJbxLJAJfIaEXqXXII4ORO8JchI/4ArPak5xPGth+jyVOH7/zQWayXqA5 hnzR1+H4ecHJNyMfuOvU5CYTls+eLKOz6DsE3kCdhC+gu1K3zDOZJAUIySf0ZY2guhB+ R6qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:subject:to:references:from:message-id :date:user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=YV+GH74rT8MD6Mw5LjyUmnZn3aXOx1MzPPFbC406/Vo=; b=bIuqRDZkI4mkP+7ue69VD/xQp66eQCA7/CZhrkUMhvxQVPYb0BXB6P3h9nDs7Vqhg8 gghdZ3p7NGTjFBgNxpR9W5gsZ+UoCBwxRw4ny/MRO+t2eAGry1B0hDzmB27vao2Jrw6W jpzkh/LW2uUfAUQzs9cqQFr6IK0aIs+VqHgorAZpE7ExiAi6GSUAA2zHMFka4DnOSiqb FLyudlNMiNYeUt33jKfDtSldHobzcRSPWA5mMqXmn+5FQ7sWbKU6ZKExvT+z6lFuG1H0 gT2djgaXzvBwqDBA8kIQ/UrbGGp+7mStPaHpJrbLhvCixU64uqWLuAQ1dLxhEeXZMojb seqA== X-Gm-Message-State: AD7BkJJBvFscp1voi9e38T0hLShCssEnm5hJ8frmgoi0KyD0DnyMvTp9B2xWfv1kMIIAWQ== X-Received: by 10.194.89.70 with SMTP id bm6mr31554871wjb.0.1456927577753; Wed, 02 Mar 2016 06:06:17 -0800 (PST) Received: from [192.168.10.165] (94-39-138-146.adsl-ull.clienti.tiscali.it. [94.39.138.146]) by smtp.googlemail.com with ESMTPSA id b1sm35981765wjy.0.2016.03.02.06.06.15 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 02 Mar 2016 06:06:15 -0800 (PST) To: =?UTF-8?Q?Herv=c3=a9_Poussineau?= , Richard Henderson , qemu-devel References: <56D36B83.7000404@reactos.org> <56D5B170.9060006@redhat.com> <56D5F580.1070901@reactos.org> <56D6666D.8000907@twiddle.net> <56D69EEE.3090709@reactos.org> From: Paolo Bonzini Message-ID: <56D6F356.9060003@redhat.com> Date: Wed, 2 Mar 2016 15:06:14 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: <56D69EEE.3090709@reactos.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::233 Subject: Re: [Qemu-devel] [QEMU] Windows XP / Windows 95 / MS-DOS 6 regressions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On 02/03/2016 09:06, Hervé Poussineau wrote: >> > > I just reconfirmed that > d6a2914984c89fa0a3125b9842e0cbf68de79a3d~1 + > 88c73d16ad1b6c22a2ab082064d0d521f756296a works, > while > d6a2914984c89fa0a3125b9842e0cbf68de79a3d + > 88c73d16ad1b6c22a2ab082064d0d521f756296a bugchecks. > > a5af12871fd4601c44f08d9e49131e9ca13ef102 that you tested is after > d6a2914984c89fa0a3125b9842e0cbf68de79a3d which broke Windows 9x, that's > why you're seeing it broken. > > It also has been a long time that Windows 9x doesn't work with > -enable-kvm. Maybe even always... This was tricky because the faulting instruction is some kind of generated thunk. In the good QEMU it is like: 0x000000008030a4da: mov $0x16f,%ax 0x000000008030a4dd: mov %ax,%es 0x000000008030a4df: movzwl %cx,%ecx 0x000000008030a4e3: addr32 mov %es:-0x400aa28c(%ecx),%edx 0x000000008030a4ec: ljmpl $0x167,$0xbff71903 In the bad one, the address is %es:0(%ecx) and everything goes south from there. Therefore I copied the old code, changed to generate the effective address in a new temp cpu_A1, then I added a helper that gets the two effective addresses and asserts if they mismatch. Sure enough it fired on an addr16 mov %gs:(%bx),%eax The issue is that the /* ADDSEG will only be false in 16-bit mode for LEA. */ comment is false when in 32-bit mode but with an addr16 prefix. I still have to forward port it, and test on a newer commit, but the attached patch can boot Windows 98. Paolo diff --git a/target-i386/translate.c b/target-i386/translate.c index 282f4a1..0a2d091 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -61,6 +61,7 @@ /* global register indexes */ static TCGv_ptr cpu_env; static TCGv cpu_A0; +static TCGv cpu_A1; static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT; static TCGv_i32 cpu_cc_op; static TCGv cpu_regs[CPU_NB_REGS]; @@ -419,6 +420,18 @@ static inline void gen_op_add_reg_T0(TCGMemOp size, int reg) gen_op_mov_reg_v(size, reg, cpu_tmp0); } +static inline void gen_op_addl_A1_seg(DisasContext *s, int reg) +{ + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base)); + if (CODE64(s)) { + tcg_gen_ext32u_tl(cpu_A1, cpu_A1); + tcg_gen_add_tl(cpu_A1, cpu_A1, cpu_tmp0); + } else { + tcg_gen_add_tl(cpu_A1, cpu_A1, cpu_tmp0); + tcg_gen_ext32u_tl(cpu_A1, cpu_A1); + } +} + static inline void gen_op_addl_A0_seg(DisasContext *s, int reg) { tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUX86State, segs[reg].base)); @@ -485,13 +498,13 @@ static void gen_lea_v_seg(DisasContext *s, TCGv a0, int def_seg, int ovr_seg) break; case MO_16: /* 16 bit address */ - if (ovr_seg < 0) { - ovr_seg = def_seg; - } tcg_gen_ext16u_tl(cpu_A0, a0); - /* ADDSEG will only be false in 16-bit mode for LEA. */ - if (!s->addseg) { - return; + if (ovr_seg < 0) { + if (s->addseg) { + ovr_seg = def_seg; + } else { + return; + } } a0 = cpu_A0; break; @@ -1838,12 +1851,198 @@ static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c) } } +static void gen_lea_modrm_old(CPUX86State *env, DisasContext *s, int modrm) +{ + target_long disp; + int havesib; + int base; + int index; + int scale; + int mod, rm, code, override, must_add_seg; + TCGv sum; + + override = s->override; + must_add_seg = s->addseg; + if (override >= 0) + must_add_seg = 1; + mod = (modrm >> 6) & 3; + rm = modrm & 7; + + switch (s->aflag) { + case MO_64: + case MO_32: + havesib = 0; + base = rm; + index = -1; + scale = 0; + + if (base == 4) { + havesib = 1; + code = cpu_ldub_code(env, s->pc++); + scale = (code >> 6) & 3; + index = ((code >> 3) & 7) | REX_X(s); + if (index == 4) { + index = -1; /* no index */ + } + base = (code & 7); + } + base |= REX_B(s); + + switch (mod) { + case 0: + if ((base & 7) == 5) { + base = -1; + disp = (int32_t)cpu_ldl_code(env, s->pc); + s->pc += 4; + if (CODE64(s) && !havesib) { + disp += s->pc + s->rip_offset; + } + } else { + disp = 0; + } + break; + case 1: + disp = (int8_t)cpu_ldub_code(env, s->pc++); + break; + default: + case 2: + disp = (int32_t)cpu_ldl_code(env, s->pc); + s->pc += 4; + break; + } + + /* For correct popl handling with esp. */ + if (base == R_ESP && s->popl_esp_hack) { + disp += s->popl_esp_hack; + } + + /* Compute the address, with a minimum number of TCG ops. */ + TCGV_UNUSED(sum); + if (index >= 0) { + if (scale == 0) { + sum = cpu_regs[index]; + } else { + tcg_gen_shli_tl(cpu_A1, cpu_regs[index], scale); + sum = cpu_A1; + } + if (base >= 0) { + tcg_gen_add_tl(cpu_A1, sum, cpu_regs[base]); + sum = cpu_A1; + } + } else if (base >= 0) { + sum = cpu_regs[base]; + } + if (TCGV_IS_UNUSED(sum)) { + tcg_gen_movi_tl(cpu_A1, disp); + } else { + tcg_gen_addi_tl(cpu_A1, sum, disp); + } + + if (must_add_seg) { + if (override < 0) { + if (base == R_EBP || base == R_ESP) { + override = R_SS; + } else { + override = R_DS; + } + } + + tcg_gen_ld_tl(cpu_tmp0, cpu_env, + offsetof(CPUX86State, segs[override].base)); + if (CODE64(s)) { + if (s->aflag == MO_32) { + tcg_gen_ext32u_tl(cpu_A1, cpu_A1); + } + tcg_gen_add_tl(cpu_A1, cpu_A1, cpu_tmp0); + return; + } + + tcg_gen_add_tl(cpu_A1, cpu_A1, cpu_tmp0); + } + + if (s->aflag == MO_32) { + tcg_gen_ext32u_tl(cpu_A1, cpu_A1); + } + break; + + case MO_16: + switch (mod) { + case 0: + if (rm == 6) { + disp = cpu_lduw_code(env, s->pc); + s->pc += 2; + tcg_gen_movi_tl(cpu_A1, disp); + rm = 0; /* avoid SS override */ + goto no_rm; + } else { + disp = 0; + } + break; + case 1: + disp = (int8_t)cpu_ldub_code(env, s->pc++); + break; + default: + case 2: + disp = (int16_t)cpu_lduw_code(env, s->pc); + s->pc += 2; + break; + } + + sum = cpu_A1; + switch (rm) { + case 0: + tcg_gen_add_tl(cpu_A1, cpu_regs[R_EBX], cpu_regs[R_ESI]); + break; + case 1: + tcg_gen_add_tl(cpu_A1, cpu_regs[R_EBX], cpu_regs[R_EDI]); + break; + case 2: + tcg_gen_add_tl(cpu_A1, cpu_regs[R_EBP], cpu_regs[R_ESI]); + break; + case 3: + tcg_gen_add_tl(cpu_A1, cpu_regs[R_EBP], cpu_regs[R_EDI]); + break; + case 4: + sum = cpu_regs[R_ESI]; + break; + case 5: + sum = cpu_regs[R_EDI]; + break; + case 6: + sum = cpu_regs[R_EBP]; + break; + default: + case 7: + sum = cpu_regs[R_EBX]; + break; + } + tcg_gen_addi_tl(cpu_A1, sum, disp); + tcg_gen_ext16u_tl(cpu_A1, cpu_A1); + no_rm: + if (must_add_seg) { + if (override < 0) { + if (rm == 2 || rm == 3 || rm == 6) { + override = R_SS; + } else { + override = R_DS; + } + } + gen_op_addl_A1_seg(s, override); + } + break; + + default: + tcg_abort(); + } +} + static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm) { target_long disp; int havesib, base, index, scale; int mod, rm, code, def_seg, ovr_seg; TCGv sum; + target_long pc = s->pc, save_pc; def_seg = R_DS; ovr_seg = s->override; @@ -1985,6 +2184,11 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm) } gen_lea_v_seg(s, sum, def_seg, ovr_seg); + save_pc = s->pc; + s->pc = pc; + gen_lea_modrm_old(env, s, modrm); + assert(s->pc == save_pc); + gen_helper_compare(cpu_A0, cpu_A1); } static void gen_nop_modrm(CPUX86State *env, DisasContext *s, int modrm) @@ -7858,6 +8062,7 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) cpu_T[0] = tcg_temp_new(); cpu_T[1] = tcg_temp_new(); cpu_A0 = tcg_temp_new(); + cpu_A1 = tcg_temp_new(); cpu_tmp0 = tcg_temp_new(); cpu_tmp1_i64 = tcg_temp_new_i64();