From patchwork Mon Jun 24 16:45:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yongbok Kim X-Patchwork-Id: 253911 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0E8EB2C0095 for ; Tue, 25 Jun 2013 02:46:20 +1000 (EST) Received: from localhost ([::1]:56682 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ur9uD-00066D-Qx for incoming@patchwork.ozlabs.org; Mon, 24 Jun 2013 12:46:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41135) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ur9to-00065v-MU for qemu-devel@nongnu.org; Mon, 24 Jun 2013 12:45:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ur9ti-0004UR-Cn for qemu-devel@nongnu.org; Mon, 24 Jun 2013 12:45:52 -0400 Received: from multi.imgtec.com ([194.200.65.239]:35037) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ur9th-0004TL-VY for qemu-devel@nongnu.org; Mon, 24 Jun 2013 12:45:46 -0400 From: Yongbok Kim To: Date: Mon, 24 Jun 2013 17:45:39 +0100 Message-ID: <1372092339-19236-1-git-send-email-yongbok.kim@imgtec.com> X-Mailer: git-send-email 1.7.4 MIME-Version: 1.0 X-Originating-IP: [192.168.14.85] X-SEF-Processed: 7_3_0_01192__2013_06_24_17_45_44 X-detected-operating-system: by eggs.gnu.org: Windows XP X-Received-From: 194.200.65.239 Cc: yongbok.kim@imgtec.com, cristian.cuna@imgtec.com, james.hogan@imgtec.com, leon.alrae@imgtec.com, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH] target-mips: fix branch in likely delay slot tcg assert 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 From: James Hogan When a branch delay slot contains another branch instruction, the code generated raises an exception, however since is_branch==1, handle_delay_slot() doesn't get called immediately. This means ctx->bstate isn't set to BS_BRANCH, and the decoder continues decoding until a non-branch instruction is found. If the first branch was a branch likely instruction then each instruction after it generates code for the unlikely case, to go to the next tb starting after the delay slot. This results in multiple goto_tb tcg ops being generated with the same exit number. When debug is enabled this hits: tcg-op.h:2589: tcg_gen_goto_tb: Assertion `(tcg_ctx.goto_tb_issue_mask & (1 << idx)) == 0' failed. This is fixed by removing is_branch entirely, and calling handle_delay_slot() if (ctx.hflags & MIPS_HFLAG_BMASK) was set prior to the current instruction being decoded. This still prevents handle_delay_slot() being called immediately after a branch but allows it to still be called after a branch within a delay slot. Signed-off-by: James Hogan Signed-off-by: Yongbok Kim --- target-mips/translate.c | 62 +++++++++++++---------------------------------- 1 files changed, 17 insertions(+), 45 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 0a53203..856e115 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -9571,8 +9571,7 @@ static void decode_i64_mips16 (DisasContext *ctx, } #endif -static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx, - int *is_branch) +static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx) { int extend = cpu_lduw_code(env, ctx->pc + 2); int op, rx, ry, funct, sa; @@ -9763,8 +9762,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx, return 4; } -static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, - int *is_branch) +static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx) { int rx, ry; int sa; @@ -9807,7 +9805,6 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS; gen_compute_branch(ctx, op, 4, rx, ry, offset); n_bytes = 4; - *is_branch = 1; break; case M16_OPC_BEQZ: gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1); @@ -10046,9 +10043,6 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, } gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0); - if (!nd) { - *is_branch = 1; - } } break; case RR_SDBBP: @@ -10193,7 +10187,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, } break; case M16_OPC_EXTEND: - decode_extended_mips16_opc(env, ctx, is_branch); + decode_extended_mips16_opc(env, ctx); n_bytes = 4; break; #if defined(TARGET_MIPS64) @@ -10802,7 +10796,7 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist, } -static void gen_pool16c_insn(DisasContext *ctx, int *is_branch) +static void gen_pool16c_insn(DisasContext *ctx) { int rd = mmreg((ctx->opcode >> 3) & 0x7); int rs = mmreg(ctx->opcode & 0x7); @@ -10864,7 +10858,6 @@ static void gen_pool16c_insn(DisasContext *ctx, int *is_branch) gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0); } - *is_branch = 1; break; case JRC16 + 0: case JRC16 + 1: @@ -10889,7 +10882,6 @@ static void gen_pool16c_insn(DisasContext *ctx, int *is_branch) gen_compute_branch(ctx, opc, 2, reg, 31, 0); } - *is_branch = 1; break; case MFHI16 + 0: case MFHI16 + 1: @@ -11020,8 +11012,7 @@ static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd, tcg_temp_free(t1); } -static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, - int *is_branch) +static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) { int extension = (ctx->opcode >> 6) & 0x3f; int minor = (ctx->opcode >> 12) & 0xf; @@ -11147,12 +11138,10 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs, case JALR: case JALR_HB: gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0); - *is_branch = 1; break; case JALRS: case JALRS_HB: gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0); - *is_branch = 1; break; default: goto pool32axf_invalid; @@ -11551,7 +11540,7 @@ static void gen_pool32fxf(DisasContext *ctx, int rt, int rs) } static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, - uint16_t insn_hw1, int *is_branch) + uint16_t insn_hw1) { int32_t offset; uint16_t insn; @@ -11685,7 +11674,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd); return; case POOL32AXF: - gen_pool32axf(env, ctx, rt, rs, is_branch); + gen_pool32axf(env, ctx, rt, rs); break; case 0x07: generate_exception(ctx, EXCP_BREAK); @@ -12048,7 +12037,6 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, mips32_op = OPC_BGTZ; do_branch: gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1); - *is_branch = 1; break; /* Traps */ @@ -12109,7 +12097,6 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, do_cp1branch: gen_compute_branch1(ctx, mips32_op, (ctx->opcode >> 18) & 0x7, imm << 1); - *is_branch = 1; break; case BPOSGE64: case BPOSGE32: @@ -12216,30 +12203,24 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, case JALX32: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset); - *is_branch = 1; break; case JALS32: offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset); - *is_branch = 1; break; case BEQ32: gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1); - *is_branch = 1; break; case BNE32: gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1); - *is_branch = 1; break; case J32: gen_compute_branch(ctx, OPC_J, 4, rt, rs, (int32_t)(ctx->opcode & 0x3FFFFFF) << 1); - *is_branch = 1; break; case JAL32: gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, (int32_t)(ctx->opcode & 0x3FFFFFF) << 1); - *is_branch = 1; break; /* Floating point (COP1) */ case LWC132: @@ -12309,7 +12290,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, } } -static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) +static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) { uint32_t op; @@ -12442,7 +12423,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b } break; case POOL16C: - gen_pool16c_insn(ctx, is_branch); + gen_pool16c_insn(ctx); break; case LWGP16: { @@ -12582,14 +12563,12 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b case B16: gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, SIMM(ctx->opcode, 0, 10) << 1); - *is_branch = 1; break; case BNEZ16: case BEQZ16: gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2, mmreg(uMIPS_RD(ctx->opcode)), 0, SIMM(ctx->opcode, 0, 7) << 1); - *is_branch = 1; break; case LI16: { @@ -12610,7 +12589,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_b generate_exception(ctx, EXCP_RI); break; default: - decode_micromips32_opc (env, ctx, op, is_branch); + decode_micromips32_opc (env, ctx, op); return 4; } @@ -14346,7 +14325,7 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, /* End MIPSDSP functions. */ -static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) +static void decode_opc (CPUMIPSState *env, DisasContext *ctx) { int32_t offset; int rs, rt, rd, sa; @@ -14460,7 +14439,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) break; case OPC_JR ... OPC_JALR: gen_compute_branch(ctx, op1, 4, rs, rd, sa); - *is_branch = 1; break; case OPC_TGE ... OPC_TEQ: /* Traps */ case OPC_TNE: @@ -15227,7 +15205,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ case OPC_BLTZAL ... OPC_BGEZALL: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2); - *is_branch = 1; break; case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ case OPC_TNEI: @@ -15243,7 +15220,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) #endif check_dsp(ctx); gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2); - *is_branch = 1; break; default: /* Invalid */ MIPS_INVAL("regimm"); @@ -15355,12 +15331,10 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_J ... OPC_JAL: /* Jump */ offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; gen_compute_branch(ctx, op, 4, rs, rt, offset); - *is_branch = 1; break; case OPC_BEQ ... OPC_BGTZ: /* Branch */ case OPC_BEQL ... OPC_BGTZL: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); - *is_branch = 1; break; case OPC_LB ... OPC_LWR: /* Load and stores */ case OPC_LL: @@ -15420,7 +15394,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) case OPC_BC1: gen_compute_branch1(ctx, MASK_BC1(ctx->opcode), (rt >> 2) & 0x7, imm << 2); - *is_branch = 1; break; case OPC_S_FMT: case OPC_D_FMT: @@ -15527,7 +15500,6 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS); offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; gen_compute_branch(ctx, op, 4, rs, rt, offset); - *is_branch = 1; break; case OPC_MDMX: check_insn(ctx, ASE_MDMX); @@ -15551,7 +15523,7 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb, int num_insns; int max_insns; int insn_bytes; - int is_branch; + int is_delay; if (search_pc) qemu_log("search pc %d\n", search_pc); @@ -15609,23 +15581,23 @@ gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb, if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); - is_branch = 0; + is_delay = ctx.hflags & MIPS_HFLAG_BMASK; if (!(ctx.hflags & MIPS_HFLAG_M16)) { ctx.opcode = cpu_ldl_code(env, ctx.pc); insn_bytes = 4; - decode_opc(env, &ctx, &is_branch); + decode_opc(env, &ctx); } else if (ctx.insn_flags & ASE_MICROMIPS) { ctx.opcode = cpu_lduw_code(env, ctx.pc); - insn_bytes = decode_micromips_opc(env, &ctx, &is_branch); + insn_bytes = decode_micromips_opc(env, &ctx); } else if (ctx.insn_flags & ASE_MIPS16) { ctx.opcode = cpu_lduw_code(env, ctx.pc); - insn_bytes = decode_mips16_opc(env, &ctx, &is_branch); + insn_bytes = decode_mips16_opc(env, &ctx); } else { generate_exception(&ctx, EXCP_RI); ctx.bstate = BS_STOP; break; } - if (!is_branch) { + if (is_delay) { handle_delay_slot(&ctx, insn_bytes); } ctx.pc += insn_bytes;