[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] target-mips: fix branch in likely delay slot tc
From: |
Aurelien Jarno |
Subject: |
Re: [Qemu-devel] [PATCH] target-mips: fix branch in likely delay slot tcg assert |
Date: |
Sun, 28 Jul 2013 19:06:22 +0200 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Mon, Jun 24, 2013 at 05:45:39PM +0100, Yongbok Kim wrote:
> From: James Hogan <address@hidden>
>
> 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 <address@hidden>
> Signed-off-by: Yongbok Kim <address@hidden>
> ---
> 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;
Thanks, applied.
--
Aurelien Jarno GPG: 1024D/F1BCDB73
address@hidden http://www.aurel32.net