Commit 15fa08f8 authored by Richard Henderson's avatar Richard Henderson
Browse files

tcg: Dynamically allocate TCGOps



With no fixed array allocation, we can't overflow a buffer.
This will be important as optimizations related to host vectors
may expand the number of ops used.

Use QTAILQ to link the ops together.

Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent f764718d
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@

/* Helpers for instruction counting code generation.  */

static int icount_start_insn_idx;
static TCGOp *icount_start_insn;

static inline void gen_tb_start(TranslationBlock *tb)
{
@@ -26,8 +26,8 @@ static inline void gen_tb_start(TranslationBlock *tb)
        /* We emit a movi with a dummy immediate argument. Keep the insn index
         * of the movi so that we later (when we know the actual insn count)
         * can update the immediate argument with the actual insn count.  */
        icount_start_insn_idx = tcg_op_buf_count();
        tcg_gen_movi_i32(imm, 0xdeadbeef);
        icount_start_insn = tcg_last_op();

        tcg_gen_sub_i32(count, count, imm);
        tcg_temp_free_i32(imm);
@@ -48,14 +48,11 @@ static inline void gen_tb_end(TranslationBlock *tb, int num_insns)
    if (tb_cflags(tb) & CF_USE_ICOUNT) {
        /* Update the num_insn immediate parameter now that we know
         * the actual insn count.  */
        tcg_set_insn_param(icount_start_insn_idx, 1, num_insns);
        tcg_set_insn_param(icount_start_insn, 1, num_insns);
    }

    gen_set_label(tcg_ctx->exitreq_label);
    tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_REQUESTED);

    /* Terminate the linked list.  */
    tcg_ctx->gen_op_buf[tcg_ctx->gen_op_buf[0].prev].next = 0;
}

static inline void gen_io_start(void)
+5 −0
Original line number Diff line number Diff line
@@ -425,6 +425,11 @@ struct { \
                (var);                                                  \
                (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))

#define QTAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev_var) \
        for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
             (var) && ((prev_var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)), 1); \
             (var) = (prev_var))

/*
 * Tail queue access methods.
 */
+1 −1
Original line number Diff line number Diff line
@@ -11290,8 +11290,8 @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
{
    DisasContext *dc = container_of(dcbase, DisasContext, base);

    dc->insn_start_idx = tcg_op_buf_count();
    tcg_gen_insn_start(dc->pc, 0, 0);
    dc->insn_start = tcg_last_op();
}

static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+1 −1
Original line number Diff line number Diff line
@@ -12096,10 +12096,10 @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
{
    DisasContext *dc = container_of(dcbase, DisasContext, base);

    dc->insn_start_idx = tcg_op_buf_count();
    tcg_gen_insn_start(dc->pc,
                       (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
                       0);
    dc->insn_start = tcg_last_op();
}

static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
+5 −5
Original line number Diff line number Diff line
@@ -66,8 +66,8 @@ typedef struct DisasContext {
    bool ss_same_el;
    /* Bottom two bits of XScale c15_cpar coprocessor access control reg */
    int c15_cpar;
    /* TCG op index of the current insn_start.  */
    int insn_start_idx;
    /* TCG op of the current insn_start.  */
    TCGOp *insn_start;
#define TMP_A64_MAX 16
    int tmp_a64_count;
    TCGv_i64 tmp_a64[TMP_A64_MAX];
@@ -117,9 +117,9 @@ static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
    syn >>= ARM_INSN_START_WORD2_SHIFT;

    /* We check and clear insn_start_idx to catch multiple updates.  */
    assert(s->insn_start_idx != 0);
    tcg_set_insn_param(s->insn_start_idx, 2, syn);
    s->insn_start_idx = 0;
    assert(s->insn_start != NULL);
    tcg_set_insn_param(s->insn_start, 2, syn);
    s->insn_start = NULL;
}

/* is_jmp field values */
Loading