From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33275) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WCucv-0002xc-Ua for qemu-devel@nongnu.org; Mon, 10 Feb 2014 12:26:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WCucn-00026v-GM for qemu-devel@nongnu.org; Mon, 10 Feb 2014 12:26:37 -0500 From: Tom Musta Date: Mon, 10 Feb 2014 11:25:09 -0600 Message-Id: <1392053109-7606-1-git-send-email-tommusta@gmail.com> Subject: [Qemu-devel] [PATCH] target-ppc: Fix xxpermdi When T==A or T==B List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Tom Musta , qemu-ppc@nongnu.org The existing implementation of xxpermdi is defective if the target VSR is also a source VSR. This patch fixes the defect in this case but also preserves the simpler, two TCG operation implementation when the target is not once of the two sources. Signed-off-by: Tom Musta --- target-ppc/translate.c | 41 +++++++++++++++++++++++++++++++++-------- 1 files changed, 33 insertions(+), 8 deletions(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index c5c1108..ffa470f 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -7162,16 +7162,41 @@ static void gen_xxpermdi(DisasContext *ctx) gen_exception(ctx, POWERPC_EXCP_VSXU); return; } + + if (unlikely((xT(ctx->opcode) == xA(ctx->opcode)) || + (xT(ctx->opcode) == xB(ctx->opcode)))) { + TCGv_i64 xh, xl; + + xh = tcg_temp_new_i64(); + xl = tcg_temp_new_i64(); + + if ((DM(ctx->opcode) & 2) == 0) { + tcg_gen_mov_i64(xh, cpu_vsrh(xA(ctx->opcode))); + } else { + tcg_gen_mov_i64(xh, cpu_vsrl(xA(ctx->opcode))); + } + if ((DM(ctx->opcode) & 1) == 0) { + tcg_gen_mov_i64(xl, cpu_vsrh(xB(ctx->opcode))); + } else { + tcg_gen_mov_i64(xl, cpu_vsrl(xB(ctx->opcode))); + } - if ((DM(ctx->opcode) & 2) == 0) { - tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode))); - } else { - tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode))); - } - if ((DM(ctx->opcode) & 1) == 0) { - tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode))); + tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), xh); + tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), xl); + + tcg_temp_free_i64(xh); + tcg_temp_free_i64(xl); } else { - tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode))); + if ((DM(ctx->opcode) & 2) == 0) { + tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrh(xA(ctx->opcode))); + } else { + tcg_gen_mov_i64(cpu_vsrh(xT(ctx->opcode)), cpu_vsrl(xA(ctx->opcode))); + } + if ((DM(ctx->opcode) & 1) == 0) { + tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrh(xB(ctx->opcode))); + } else { + tcg_gen_mov_i64(cpu_vsrl(xT(ctx->opcode)), cpu_vsrl(xB(ctx->opcode))); + } } } -- 1.7.1