Commit 9f754620 authored by Richard Henderson's avatar Richard Henderson
Browse files

tcg: Reduce max TB opcode count



Also, assert that we don't overflow any of two different offsets into
the TB. Both unwind and goto_tb both record a uint16_t for later use.

This fixes an arm-softmmu test case utilizing NEON in which there is
a TB generated that runs to 7800 opcodes, and compiles to 96k on an
x86_64 host.  This overflows the 16-bit offset in which we record the
goto_tb reset offset.  Because of that overflow, we install a jump
destination that goes to neverland.  Boom.

With this reduced op count, the same TB compiles to about 48k for
aarch64, ppc64le, and x86_64 hosts, and neither assertion fires.

Cc: qemu-stable@nongnu.org
Reported-by: default avatar"Jason A. Donenfeld" <Jason@zx2c4.com>
Reviewed-by: default avatarPhilippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent 0ac20318
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1733,7 +1733,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
            tcg_out_insn(s, 3305, LDR, offset, TCG_REG_TMP);
        }
        tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
        s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
        set_jmp_reset_offset(s, a0);
        break;

    case INDEX_op_goto_ptr:
+1 −1
Original line number Diff line number Diff line
@@ -1822,7 +1822,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
                tcg_out_movi32(s, COND_AL, base, ptr - dil);
            }
            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, base, dil);
            s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s);
            set_jmp_reset_offset(s, args[0]);
        }
        break;
    case INDEX_op_goto_ptr:
+1 −1
Original line number Diff line number Diff line
@@ -2245,7 +2245,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
            tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
                                 (intptr_t)(s->tb_jmp_target_addr + a0));
        }
        s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
        set_jmp_reset_offset(s, a0);
        break;
    case INDEX_op_goto_ptr:
        /* jmp to the given host address (could be epilogue) */
+1 −1
Original line number Diff line number Diff line
@@ -1744,7 +1744,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
        }
        tcg_out_nop(s);
        s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
        set_jmp_reset_offset(s, a0);
        break;
    case INDEX_op_goto_ptr:
        /* jmp to the given host address (could be epilogue) */
+2 −2
Original line number Diff line number Diff line
@@ -2025,10 +2025,10 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
        }
        tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR);
        tcg_out32(s, BCCTR | BO_ALWAYS);
        s->tb_jmp_reset_offset[args[0]] = c = tcg_current_code_size(s);
        set_jmp_reset_offset(s, args[0]);
        if (USE_REG_TB) {
            /* For the unlinked case, need to reset TCG_REG_TB.  */
            c = -c;
            c = -tcg_current_code_size(s);
            assert(c == (int16_t)c);
            tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, c));
        }
Loading