Commit 04d57cfa authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch...


Merge remote-tracking branch 'remotes/edgar/tags/edgar/xilinx-next-2019-11-12.for-upstream' into staging

For upstream

# gpg: Signature made Tue 12 Nov 2019 15:41:43 GMT
# gpg:                using RSA key AC44FEDC14F7F1EBEDBF415129C596780F6BCA83
# gpg: Good signature from "Edgar E. Iglesias (Xilinx key) <edgar.iglesias@xilinx.com>" [unknown]
# gpg:                 aka "Edgar E. Iglesias <edgar.iglesias@gmail.com>" [full]
# Primary key fingerprint: AC44 FEDC 14F7 F1EB EDBF  4151 29C5 9678 0F6B CA83

* remotes/edgar/tags/edgar/xilinx-next-2019-11-12.for-upstream:
  target/microblaze: Plug temp leak around eval_cond_jmp()
  target/microblaze: Plug temp leaks with delay slot setup
  target/microblaze: Plug temp leaks for loads/stores

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 2a7e7c3e c49a41b0
Loading
Loading
Loading
Loading
+38 −39
Original line number Diff line number Diff line
@@ -962,17 +962,7 @@ static void dec_load(DisasContext *dc)
        switch (size) {
            case 1:
            {
                /* 00 -> 11
                   01 -> 10
                   10 -> 10
                   11 -> 00 */
                TCGv low = tcg_temp_new();

                tcg_gen_andi_tl(low, addr, 3);
                tcg_gen_sub_tl(low, tcg_const_tl(3), low);
                tcg_gen_andi_tl(addr, addr, ~3);
                tcg_gen_or_tl(addr, addr, low);
                tcg_temp_free(low);
                tcg_gen_xori_tl(addr, addr, 3);
                break;
            }

@@ -1006,9 +996,16 @@ static void dec_load(DisasContext *dc)
    tcg_gen_qemu_ld_i32(v, addr, mem_index, mop);

    if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
        TCGv_i32 t0 = tcg_const_i32(0);
        TCGv_i32 treg = tcg_const_i32(dc->rd);
        TCGv_i32 tsize = tcg_const_i32(size - 1);

        tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc);
        gen_helper_memalign(cpu_env, addr, tcg_const_i32(dc->rd),
                            tcg_const_i32(0), tcg_const_i32(size - 1));
        gen_helper_memalign(cpu_env, addr, treg, t0, tsize);

        tcg_temp_free_i32(t0);
        tcg_temp_free_i32(treg);
        tcg_temp_free_i32(tsize);
    }

    if (ex) {
@@ -1095,17 +1092,7 @@ static void dec_store(DisasContext *dc)
        switch (size) {
            case 1:
            {
                /* 00 -> 11
                   01 -> 10
                   10 -> 10
                   11 -> 00 */
                TCGv low = tcg_temp_new();

                tcg_gen_andi_tl(low, addr, 3);
                tcg_gen_sub_tl(low, tcg_const_tl(3), low);
                tcg_gen_andi_tl(addr, addr, ~3);
                tcg_gen_or_tl(addr, addr, low);
                tcg_temp_free(low);
                tcg_gen_xori_tl(addr, addr, 3);
                break;
            }

@@ -1124,6 +1111,10 @@ static void dec_store(DisasContext *dc)

    /* Verify alignment if needed.  */
    if ((dc->cpu->env.pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
        TCGv_i32 t1 = tcg_const_i32(1);
        TCGv_i32 treg = tcg_const_i32(dc->rd);
        TCGv_i32 tsize = tcg_const_i32(size - 1);

        tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc);
        /* FIXME: if the alignment is wrong, we should restore the value
         *        in memory. One possible way to achieve this is to probe
@@ -1131,8 +1122,11 @@ static void dec_store(DisasContext *dc)
         *        the alignment checks in between the probe and the mem
         *        access.
         */
        gen_helper_memalign(cpu_env, addr, tcg_const_i32(dc->rd),
                            tcg_const_i32(1), tcg_const_i32(size - 1));
        gen_helper_memalign(cpu_env, addr, treg, t1, tsize);

        tcg_temp_free_i32(t1);
        tcg_temp_free_i32(treg);
        tcg_temp_free_i32(tsize);
    }

    if (ex) {
@@ -1183,6 +1177,17 @@ static void eval_cond_jmp(DisasContext *dc, TCGv_i64 pc_true, TCGv_i64 pc_false)
    tcg_temp_free_i64(tmp_zero);
}

static void dec_setup_dslot(DisasContext *dc)
{
        TCGv_i32 tmp = tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG));

        dc->delayed_branch = 2;
        dc->tb_flags |= D_FLAG;

        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUMBState, bimm));
        tcg_temp_free_i32(tmp);
}

static void dec_bcc(DisasContext *dc)
{
    unsigned int cc;
@@ -1194,10 +1199,7 @@ static void dec_bcc(DisasContext *dc)

    dc->delayed_branch = 1;
    if (dslot) {
        dc->delayed_branch = 2;
        dc->tb_flags |= D_FLAG;
        tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                      cpu_env, offsetof(CPUMBState, bimm));
        dec_setup_dslot(dc);
    }

    if (dec_alu_op_b_is_small_imm(dc)) {
@@ -1256,10 +1258,7 @@ static void dec_br(DisasContext *dc)

    dc->delayed_branch = 1;
    if (dslot) {
        dc->delayed_branch = 2;
        dc->tb_flags |= D_FLAG;
        tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                      cpu_env, offsetof(CPUMBState, bimm));
        dec_setup_dslot(dc);
    }
    if (link && dc->rd)
        tcg_gen_movi_i32(cpu_R[dc->rd], dc->pc);
@@ -1361,10 +1360,7 @@ static void dec_rts(DisasContext *dc)
        return;
    }

    dc->delayed_branch = 2;
    dc->tb_flags |= D_FLAG;
    tcg_gen_st_i32(tcg_const_i32(dc->type_b && (dc->tb_flags & IMM_FLAG)),
                  cpu_env, offsetof(CPUMBState, bimm));
    dec_setup_dslot(dc);

    if (i_bit) {
        LOG_DIS("rtid ir=%x\n", dc->ir);
@@ -1685,7 +1681,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
                dc->tb_flags &= ~D_FLAG;
                /* If it is a direct jump, try direct chaining.  */
                if (dc->jmp == JMP_INDIRECT) {
                    eval_cond_jmp(dc, env_btarget, tcg_const_i64(dc->pc));
                    TCGv_i64 tmp_pc = tcg_const_i64(dc->pc);
                    eval_cond_jmp(dc, env_btarget, tmp_pc);
                    tcg_temp_free_i64(tmp_pc);

                    dc->is_jmp = DISAS_JUMP;
                } else if (dc->jmp == JMP_DIRECT) {
                    t_sync_flags(dc);