[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v21 4/7] target/avr: Add instruction translation
From: |
Richard Henderson |
Subject: |
Re: [Qemu-devel] [PATCH v21 4/7] target/avr: Add instruction translation |
Date: |
Mon, 10 Jun 2019 13:35:00 -0700 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 |
On 6/6/19 12:30 PM, Michael Rolnik wrote:
> +enum {
> + BS_NONE = 0, /* Nothing special (none of the below) */
> + BS_STOP = 1, /* We want to stop translation for any reason */
> + BS_BRANCH = 2, /* A branch condition is reached */
> + BS_EXCP = 3, /* An exception condition is reached */
> +};
This set of exit conditions is confused and incomplete.
(1) BS_BRANCH and BS_EXCP do the same thing, namely they
equate exactly to DISAS_NORETURN.
(2) BS_NONE equates exactly to DISAS_NEXT.
(3) BS_STOP is probably better named DISAS_EXIT, just so
it matches the other naming above, and that it will
result in a call to tcg_gen_exit_tb.
(4) You're missing a case that applies to indirect branches
which should use tcg_gen_lookup_and_goto_tb().
I suggest this be called DISAS_LOOKUP.
> +static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
> +{
> + TranslationBlock *tb = ctx->tb;
> +
> + if (ctx->singlestep == 0) {
> + tcg_gen_goto_tb(n);
> + tcg_gen_movi_i32(cpu_pc, dest);
> + tcg_gen_exit_tb(tb, n);
> + } else {
> + tcg_gen_movi_i32(cpu_pc, dest);
> + gen_helper_debug(cpu_env);
> + tcg_gen_exit_tb(NULL, 0);
> + }
> +}
Should set ctx->bstate = DISAS_NORETURN here, and not to BS_BRANCH in the
callers.
> + if (avr_feature(ctx->env, AVR_FEATURE_ADIW_SBIW) == false) {
> + gen_helper_unsupported(cpu_env);
> +
> + ctx->bstate = BS_EXCP;
> + return true;
> + }
It would be good to define a helper function
static bool have_feature(DisasContext *ctx, int feature)
{
if (!avr_feature(ctx->env, feature)) {
gen_helper_unsupported(cpu_env);
ctx->bstate = DISAS_NORETURN;
return false;
}
return true;
}
so that this pattern becomes
if (!have_feature(ctx, AVR_FEATURE_FOO)) {
return true;
}
// Lots of code
return true;
or
if (have_feature(ctx, AVR_FEATURE_FOO)) {
// Just a few lines
}
return true;
> +/*
> + * Returns from subroutine. The return address is loaded from the STACK.
> + * The Stack Pointer uses a preincrement scheme during RET.
> + */
> +static bool trans_RET(DisasContext *ctx, arg_RET *a)
> +{
> + gen_pop_ret(ctx, cpu_pc);
> +
> + tcg_gen_exit_tb(NULL, 0);
> +
> + ctx->bstate = BS_BRANCH;
> + return true;
> +}
With very few exceptions, the lone use of tcg_gen_exit_tb is a bug, because you
have failed to take ctx->singlestep into account.
In this case, this is one of the indirect branch places which you should be
using DISAS_LOOKUP.
> +static bool trans_RETI(DisasContext *ctx, arg_RETI *a)
> +{
> + gen_pop_ret(ctx, cpu_pc);
> +
> + tcg_gen_movi_tl(cpu_If, 1);
> +
> + tcg_gen_exit_tb(NULL, 0);
> +
> + ctx->bstate = BS_BRANCH;
> + return true;
> +}
Here you need to use DISAS_EXIT, because instructions that enable interrupts
also need to exit to the main loop so that we re-evaluate whether interrupts
need to be delivered.
> + if (ctx.singlestep) {
> + if (ctx.bstate == BS_STOP || ctx.bstate == BS_NONE) {
> + tcg_gen_movi_tl(cpu_pc, ctx.npc);
> + }
> + gen_helper_debug(cpu_env);
> + tcg_gen_exit_tb(NULL, 0);
> + } else {
> + switch (ctx.bstate) {
> + case BS_STOP:
> + case BS_NONE:
> + gen_goto_tb(&ctx, 0, ctx.npc);
> + break;
> + case BS_EXCP:
> + case BS_BRANCH:
> + tcg_gen_exit_tb(NULL, 0);
> + break;
> + default:
> + break;
> + }
> + }
Better written as
switch (ctx.bstate) {
case DISAS_NORETURN:
break;
case DISAS_NEXT:
case DISAS_CHAIN:
/* Note gen_goto_tb checks singlestep. */
gen_goto_tb(&ctx, 0, ctx.npc);
break;
case DISAS_LOOKUP:
if (!ctx.singlestep) {
tcg_gen_lookup_and_goto_ptr();
break;
}
/* fall through */
case DISAS_EXIT:
if (ctx.singlestep) {
gen_helper_debug(cpu_env);
} else {
tcg_gen_exit_tb(NULL, 0);
}
break;
default:
g_assert_not_reached();
}
r~
[Qemu-devel] [PATCH v21 6/7] target/avr: Add example board configuration, Michael Rolnik, 2019/06/06
[Qemu-devel] [PATCH v21 5/7] target/avr: Add limited support for USART and 16 bit timer peripherals, Michael Rolnik, 2019/06/06
[Qemu-devel] [PATCH v21 7/7] target/avr: Register AVR support with the rest of QEMU, the build system, and the MAINTAINERS file, Michael Rolnik, 2019/06/06
[Qemu-devel] [PATCH v21 2/7] target/avr: Add instruction helpers, Michael Rolnik, 2019/06/06