Peter Maydell <peter.mayd...@linaro.org> writes:

> On 30 November 2016 at 07:00, Nikunj A Dadhania
> <nik...@linux.vnet.ibm.com> wrote:
>>
>> Hi,
>>
>> I was writing one instruction and hit following issue:
>>
>> [snip]/qemu/tcg/tcg.c:2039: tcg fatal error
>> qemu-ppc64le: [snip]/qemu/translate-all.c:175: tb_lock: Assertion 
>> `!have_tb_lock' failed.
>> Segmentation fault (core dumped)
>>
>> Debugging deeper found that its something to do with the variable type:
>>
>>     TCGv nb = tcg_temp_new();
>>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>>     [ Do something here]
>>     gen_set_label(l1);
>>     tcg_temp_free(nb);
>>
>> If I change the variable as "local temporary", the code works fine:
>>
>>     TCGv nb = tcg_temp_local_new();
>>     tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
>>     tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);
>>     [ Do something here]
>>     gen_set_label(l1);
>>     tcg_temp_free(nb);
>>
>> I see lot of code that is using temporaries for similar operations,
>> example target-ppc/translate.c:gen_check_align(). How is that working,
>> is this a bug there as well?
>
> You don't say what your "do something" code is doing, which
> is the critical question for whether you need a plain
> temporary or a local temporary. (See tcg/README.)

Lets bring full example here.

    TCGv nb = tcg_temp_new();
    tcg_gen_andi_tl(nb, cpu_gpr[rB(ctx->opcode)], 0xFF);
    tcg_gen_brcondi_tl(TCG_COND_EQ, nb, 0, l1);

    /* do something */
    gen_set_access_type(ctx, ACCESS_INT);
    EA = tcg_temp_new();
    gen_addr_register(ctx, EA);
    tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_LEQ);
    tcg_gen_addi_tl(EA, EA, 8);
    tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_LEQ);
    opc = tcg_const_i32(ctx->opcode);
    gen_helper_lxvl(cpu_env, opc, nb);      /* <--- That uses nb */
    tcg_temp_free_i32(opc);
    tcg_temp_free(EA);

    gen_set_label(l1);
    tcg_temp_free(nb);

> The plain temporary is only valid to the end of a basic
> block, and brcond ends a basic block. So you can free
> the temp after the brcond but you can't do anything
> else with it.

In the above case, assuming that nb is a plain temporary, case nb != 0
worked fine (by fluke?), i.e. no branch.

While when nb == 0, failed, i.e. branch taken to l1, and just free nb. I
am not using "nb" in this case.

> (This is what the PPC gen_check_align() does.)
> If you want to use 'nb' in the "do something" code then
> it must remain valid over the end of the basic block
> and you need a local temporary.

Understood, I need nb in that code, so I will use local temporary.

Regards
Nikunj


Reply via email to