From patchwork Mon Apr 8 22:58:23 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aurelien Jarno X-Patchwork-Id: 234926 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B08FE2C00A5 for ; Tue, 9 Apr 2013 08:59:54 +1000 (EST) Received: from localhost ([::1]:37848 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UPL2W-0007uM-Pj for incoming@patchwork.ozlabs.org; Mon, 08 Apr 2013 18:59:52 -0400 Received: from eggs.gnu.org ([208.118.235.92]:42492) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UPL1m-0007pe-Jq for qemu-devel@nongnu.org; Mon, 08 Apr 2013 18:59:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UPL1K-0000AP-Vn for qemu-devel@nongnu.org; Mon, 08 Apr 2013 18:59:06 -0400 Received: from hall.aurel32.net ([2001:470:1f15:c4f::1]:42141) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UPL1K-0008SB-EQ; Mon, 08 Apr 2013 18:58:38 -0400 Received: from [2001:470:d4ed:0:ea11:32ff:fea1:831a] (helo=ohm.aurel32.net) by hall.aurel32.net with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.72) (envelope-from ) id 1UPL16-0005ip-I7; Tue, 09 Apr 2013 00:58:24 +0200 Received: from aurel32 by ohm.aurel32.net with local (Exim 4.80) (envelope-from ) id 1UPL15-0003Y4-Dx; Tue, 09 Apr 2013 00:58:23 +0200 Date: Tue, 9 Apr 2013 00:58:23 +0200 From: Aurelien Jarno To: mdroth Message-ID: <20130408225823.GP5000@ohm.aurel32.net> References: <1364939142-30066-1-git-send-email-mdroth@linux.vnet.ibm.com> <20130403215131.GN5000@ohm.aurel32.net> <20130404222442.GA1740@vm> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20130404222442.GA1740@vm> X-Mailer: Mutt 1.5.21 (2010-09-15) User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:470:1f15:c4f::1 Cc: qemu-devel@nongnu.org, qemu-stable@nongnu.org Subject: Re: [Qemu-devel] Patch Round-up for stable 1.4.1, freeze next Tuesday 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+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org On Thu, Apr 04, 2013 at 05:24:42PM -0500, mdroth wrote: > On Wed, Apr 03, 2013 at 11:51:31PM +0200, Aurelien Jarno wrote: > > On Tue, Apr 02, 2013 at 04:45:05PM -0500, Michael Roth wrote: > > > Hi everyone, > > > > > > The following new patches are queued for QEMU stable v1.4.1: > > > > > > https://github.com/mdroth/qemu/commits/stable-1.4-staging > > > > > > The release is planned for 04-15-2013: > > > > > > http://wiki.qemu.org/Planning/1.4 > > > > > > Please CC qemu-stable@nongnu.org on any patches you think should be > > > included in the release. The cut-off date is 04-09-2013 for new patches. > > > > For the MIPS emulation, you might want to also include: > > > > 9c19eb1e205b29018f6f61c5f43db6abbe7dc0e5 target-mips: fix for incorrect multiplication with MULQ_S.PH > > a345481baa2b2fb3d54f8c9ddb58dfcaf75786df target-mips: fix for sign-issue in MULQ_W helper > > 20c334a797bf46a4ee59a6e42be6d5e7c3cda585 target-mips: fix DSP overflow macro and affected routines > > 26135ead80fa1fd13e95c162dacfd06f2ba82981 target-mips: Fix accumulator selection for MIPS16 and microMIPS > > This guy ^ has some nasty conflicts I don't trust myself with. Can you > send a version that's backported to v1.4.0 via git cherry-pick -x? > Please find it attached, sorry for the delay. From 30947b811973648636c8676f730f18a76bd9749a Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 21 Jan 2013 20:43:31 +0000 Subject: [PATCH] target-mips: Fix accumulator selection for MIPS16 and microMIPS Add accumulator arguments to gen_HILO and gen_muldiv, rather than extracting the accumulator directly from ctx->opcode. The extraction was only right for the standard encoding: MIPS16 doesn't have access to the DSP registers, while microMIPS encodes the accumulator register in a different field (bits 14 and 15). Passing the accumulator register is probably an over-generalisation for division and 64-bit multiplication, which never access anything other than HI and LO, and which always pass 0 as the new argument. Separating them felt a bit fussy though. Signed-off-by: Richard Sandiford Signed-off-by: Aurelien Jarno (cherry picked from commit 26135ead80fa1fd13e95c162dacfd06f2ba82981) Conflicts: target-mips/translate.c --- target-mips/helper.h | 4 +- target-mips/op_helper.c | 10 ++-- target-mips/translate.c | 148 ++++++++++++++++++++--------------------------- 3 files changed, 72 insertions(+), 90 deletions(-) diff --git a/target-mips/helper.h b/target-mips/helper.h index cd48738..cfe98f1 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -24,8 +24,8 @@ DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, tl, tl) #ifdef TARGET_MIPS64 DEF_HELPER_FLAGS_1(dclo, TCG_CALL_NO_RWG_SE, tl, tl) DEF_HELPER_FLAGS_1(dclz, TCG_CALL_NO_RWG_SE, tl, tl) -DEF_HELPER_3(dmult, void, env, tl, tl) -DEF_HELPER_3(dmultu, void, env, tl, tl) +DEF_HELPER_4(dmult, void, env, int, tl, tl) +DEF_HELPER_4(dmultu, void, env, int, tl, tl) #endif DEF_HELPER_3(muls, tl, env, tl, tl) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 526f84f..c054300 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -268,14 +268,16 @@ target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1, } #ifdef TARGET_MIPS64 -void helper_dmult(CPUMIPSState *env, target_ulong arg1, target_ulong arg2) +void helper_dmult(CPUMIPSState *env, int acc, target_ulong arg1, + target_ulong arg2) { - muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2); + muls64(&(env->active_tc.LO[acc]), &(env->active_tc.HI[acc]), arg1, arg2); } -void helper_dmultu(CPUMIPSState *env, target_ulong arg1, target_ulong arg2) +void helper_dmultu(CPUMIPSState *env, int acc, target_ulong arg1, + target_ulong arg2) { - mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2); + mulu64(&(env->active_tc.LO[acc]), &(env->active_tc.HI[acc]), arg1, arg2); } #endif diff --git a/target-mips/translate.c b/target-mips/translate.c index 3b77b53..9ed6477 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -2582,10 +2582,9 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, } /* Arithmetic on HI/LO registers */ -static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) +static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) { const char *opn = "hilo"; - unsigned int acc; if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) { /* Treat as NOP. */ @@ -2593,12 +2592,6 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) return; } - if (opc == OPC_MFHI || opc == OPC_MFLO) { - acc = ((ctx->opcode) >> 21) & 0x03; - } else { - acc = ((ctx->opcode) >> 11) & 0x03; - } - if (acc != 0) { check_dsp(ctx); } @@ -2661,12 +2654,11 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg) MIPS_DEBUG("%s %s", opn, regnames[reg]); } -static void gen_muldiv (DisasContext *ctx, uint32_t opc, - int rs, int rt) +static void gen_muldiv(DisasContext *ctx, uint32_t opc, + int acc, int rs, int rt) { const char *opn = "mul/div"; TCGv t0, t1; - unsigned int acc; t0 = tcg_temp_new(); t1 = tcg_temp_new(); @@ -2674,6 +2666,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, gen_load_gpr(t0, rs); gen_load_gpr(t1, rt); + if (acc != 0) { + check_dsp(ctx); + } + switch (opc) { case OPC_DIV: { @@ -2688,10 +2684,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, tcg_gen_or_tl(t2, t2, t3); tcg_gen_movi_tl(t3, 0); tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); - tcg_gen_div_tl(cpu_LO[0], t0, t1); - tcg_gen_rem_tl(cpu_HI[0], t0, t1); - tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]); - tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]); + tcg_gen_div_tl(cpu_LO[acc], t0, t1); + tcg_gen_rem_tl(cpu_HI[acc], t0, t1); + tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]); + tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]); tcg_temp_free(t3); tcg_temp_free(t2); } @@ -2704,10 +2700,10 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, tcg_gen_ext32u_tl(t0, t0); tcg_gen_ext32u_tl(t1, t1); tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); - tcg_gen_divu_tl(cpu_LO[0], t0, t1); - tcg_gen_remu_tl(cpu_HI[0], t0, t1); - tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]); - tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]); + tcg_gen_divu_tl(cpu_LO[acc], t0, t1); + tcg_gen_remu_tl(cpu_HI[acc], t0, t1); + tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]); + tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]); tcg_temp_free(t3); tcg_temp_free(t2); } @@ -2717,11 +2713,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); - acc = ((ctx->opcode) >> 11) & 0x03; - if (acc != 0) { - check_dsp(ctx); - } - tcg_gen_ext_tl_i64(t2, t0); tcg_gen_ext_tl_i64(t3, t1); tcg_gen_mul_i64(t2, t2, t3); @@ -2739,11 +2730,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); - acc = ((ctx->opcode) >> 11) & 0x03; - if (acc != 0) { - check_dsp(ctx); - } - tcg_gen_ext32u_tl(t0, t0); tcg_gen_ext32u_tl(t1, t1); tcg_gen_extu_tl_i64(t2, t0); @@ -2771,8 +2757,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, tcg_gen_or_tl(t2, t2, t3); tcg_gen_movi_tl(t3, 0); tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); - tcg_gen_div_tl(cpu_LO[0], t0, t1); - tcg_gen_rem_tl(cpu_HI[0], t0, t1); + tcg_gen_div_tl(cpu_LO[acc], t0, t1); + tcg_gen_rem_tl(cpu_HI[acc], t0, t1); tcg_temp_free(t3); tcg_temp_free(t2); } @@ -2783,19 +2769,19 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, TCGv t2 = tcg_const_tl(0); TCGv t3 = tcg_const_tl(1); tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); - tcg_gen_divu_i64(cpu_LO[0], t0, t1); - tcg_gen_remu_i64(cpu_HI[0], t0, t1); + tcg_gen_divu_i64(cpu_LO[acc], t0, t1); + tcg_gen_remu_i64(cpu_HI[acc], t0, t1); tcg_temp_free(t3); tcg_temp_free(t2); } opn = "ddivu"; break; case OPC_DMULT: - gen_helper_dmult(cpu_env, t0, t1); + gen_helper_dmult(cpu_env, acc, t0, t1); opn = "dmult"; break; case OPC_DMULTU: - gen_helper_dmultu(cpu_env, t0, t1); + gen_helper_dmultu(cpu_env, acc, t0, t1); opn = "dmultu"; break; #endif @@ -2803,10 +2789,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); - acc = ((ctx->opcode) >> 11) & 0x03; - if (acc != 0) { - check_dsp(ctx); - } tcg_gen_ext_tl_i64(t2, t0); tcg_gen_ext_tl_i64(t3, t1); @@ -2827,10 +2809,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); - acc = ((ctx->opcode) >> 11) & 0x03; - if (acc != 0) { - check_dsp(ctx); - } tcg_gen_ext32u_tl(t0, t0); tcg_gen_ext32u_tl(t1, t1); @@ -2853,10 +2831,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); - acc = ((ctx->opcode) >> 11) & 0x03; - if (acc != 0) { - check_dsp(ctx); - } tcg_gen_ext_tl_i64(t2, t0); tcg_gen_ext_tl_i64(t3, t1); @@ -2877,10 +2851,6 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc, { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); - acc = ((ctx->opcode) >> 11) & 0x03; - if (acc != 0) { - check_dsp(ctx); - } tcg_gen_ext32u_tl(t0, t0); tcg_gen_ext32u_tl(t1, t1); @@ -10143,7 +10113,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, gen_logic(ctx, OPC_NOR, rx, ry, 0); break; case RR_MFHI: - gen_HILO(ctx, OPC_MFHI, rx); + gen_HILO(ctx, OPC_MFHI, 0, rx); break; case RR_CNVT: switch (cnvt_op) { @@ -10175,7 +10145,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, } break; case RR_MFLO: - gen_HILO(ctx, OPC_MFLO, rx); + gen_HILO(ctx, OPC_MFLO, 0, rx); break; #if defined (TARGET_MIPS64) case RR_DSRA: @@ -10196,33 +10166,33 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, break; #endif case RR_MULT: - gen_muldiv(ctx, OPC_MULT, rx, ry); + gen_muldiv(ctx, OPC_MULT, 0, rx, ry); break; case RR_MULTU: - gen_muldiv(ctx, OPC_MULTU, rx, ry); + gen_muldiv(ctx, OPC_MULTU, 0, rx, ry); break; case RR_DIV: - gen_muldiv(ctx, OPC_DIV, rx, ry); + gen_muldiv(ctx, OPC_DIV, 0, rx, ry); break; case RR_DIVU: - gen_muldiv(ctx, OPC_DIVU, rx, ry); + gen_muldiv(ctx, OPC_DIVU, 0, rx, ry); break; #if defined (TARGET_MIPS64) case RR_DMULT: check_mips_64(ctx); - gen_muldiv(ctx, OPC_DMULT, rx, ry); + gen_muldiv(ctx, OPC_DMULT, 0, rx, ry); break; case RR_DMULTU: check_mips_64(ctx); - gen_muldiv(ctx, OPC_DMULTU, rx, ry); + gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry); break; case RR_DDIV: check_mips_64(ctx); - gen_muldiv(ctx, OPC_DDIV, rx, ry); + gen_muldiv(ctx, OPC_DDIV, 0, rx, ry); break; case RR_DDIVU: check_mips_64(ctx); - gen_muldiv(ctx, OPC_DDIVU, rx, ry); + gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry); break; #endif default: @@ -10931,11 +10901,11 @@ static void gen_pool16c_insn(DisasContext *ctx, int *is_branch) break; case MFHI16 + 0: case MFHI16 + 1: - gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode)); + gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode)); break; case MFLO16 + 0: case MFLO16 + 1: - gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode)); + gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); break; case BREAK16: generate_exception(ctx, EXCP_BREAK); @@ -11133,30 +11103,34 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, break; case MULT: mips32_op = OPC_MULT; - goto do_muldiv; + goto do_mul; case MULTU: mips32_op = OPC_MULTU; - goto do_muldiv; + goto do_mul; case DIV: mips32_op = OPC_DIV; - goto do_muldiv; + goto do_div; case DIVU: mips32_op = OPC_DIVU; - goto do_muldiv; + goto do_div; + do_div: + check_insn(ctx, ISA_MIPS32); + gen_muldiv(ctx, mips32_op, 0, rs, rt); + break; case MADD: mips32_op = OPC_MADD; - goto do_muldiv; + goto do_mul; case MADDU: mips32_op = OPC_MADDU; - goto do_muldiv; + goto do_mul; case MSUB: mips32_op = OPC_MSUB; - goto do_muldiv; + goto do_mul; case MSUBU: mips32_op = OPC_MSUBU; - do_muldiv: + do_mul: check_insn(ctx, ISA_MIPS32); - gen_muldiv(ctx, mips32_op, rs, rt); + gen_muldiv(ctx, mips32_op, (ctx->opcode >> 14) & 3, rs, rt); break; default: goto pool32axf_invalid; @@ -11293,18 +11267,18 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, } break; case 0x35: - switch (minor) { + switch (minor & 3) { case MFHI32: - gen_HILO(ctx, OPC_MFHI, rs); + gen_HILO(ctx, OPC_MFHI, minor >> 2, rs); break; case MFLO32: - gen_HILO(ctx, OPC_MFLO, rs); + gen_HILO(ctx, OPC_MFLO, minor >> 2, rs); break; case MTHI32: - gen_HILO(ctx, OPC_MTHI, rs); + gen_HILO(ctx, OPC_MTHI, minor >> 2, rs); break; case MTLO32: - gen_HILO(ctx, OPC_MTLO, rs); + gen_HILO(ctx, OPC_MTLO, minor >> 2, rs); break; default: goto pool32axf_invalid; @@ -14477,13 +14451,19 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_XOR: gen_logic(ctx, op1, rd, rs, rt); break; - case OPC_MULT ... OPC_DIVU: + case OPC_MULT: + case OPC_MULTU: if (sa) { check_insn(ctx, INSN_VR54XX); op1 = MASK_MUL_VR54XX(ctx->opcode); gen_mul_vr54xx(ctx, op1, rd, rs, rt); - } else - gen_muldiv(ctx, op1, rs, rt); + } else { + gen_muldiv(ctx, op1, rd & 3, rs, rt); + } + break; + case OPC_DIV: + case OPC_DIVU: + gen_muldiv(ctx, op1, 0, rs, rt); break; case OPC_JR ... OPC_JALR: gen_compute_branch(ctx, op1, 4, rs, rd, sa); @@ -14495,11 +14475,11 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; case OPC_MFHI: /* Move from HI/LO */ case OPC_MFLO: - gen_HILO(ctx, op1, rd); + gen_HILO(ctx, op1, rs & 3, rd); break; case OPC_MTHI: case OPC_MTLO: /* Move to HI/LO */ - gen_HILO(ctx, op1, rs); + gen_HILO(ctx, op1, rd & 3, rs); break; case OPC_PMON: /* Pmon entry point, also R4010 selsl */ #ifdef MIPS_STRICT_STANDARD @@ -14619,7 +14599,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_DMULT ... OPC_DDIVU: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); - gen_muldiv(ctx, op1, rs, rt); + gen_muldiv(ctx, op1, 0, rs, rt); break; #endif default: /* Invalid */ @@ -14634,7 +14614,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */ case OPC_MSUB ... OPC_MSUBU: check_insn(ctx, ISA_MIPS32); - gen_muldiv(ctx, op1, rs, rt); + gen_muldiv(ctx, op1, rd & 3, rs, rt); break; case OPC_MUL: gen_arith(ctx, op1, rd, rs, rt); -- 1.7.10.4