Commit 66c2056f authored by Richard Henderson's avatar Richard Henderson
Browse files

tcg-arm: Remove restriction on qemu_ld output register



The main intent of the patch is to allow the tlb addend register
to be changed, without tying that change to the constraint.  But
the most common side-effect seems to be to enable usage of ldrd
with the r0,r1 pair.

Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent d3e440be
Loading
Loading
Loading
Loading
+34 −24
Original line number Diff line number Diff line
@@ -181,15 +181,6 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
#endif
        break;
    case 'L':
        ct->ct |= TCG_CT_REG;
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
#ifdef CONFIG_SOFTMMU
        /* r1 is still needed to load data_reg or data_reg2,
           so don't use it. */
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
#endif
        break;

@@ -1314,8 +1305,17 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
        tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
        break;
    case 3:
        if (data_reg != TCG_REG_R1) {
            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
        } else if (data_reg2 != TCG_REG_R0) {
            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_R0);
        } else {
            tcg_out_mov_reg(s, COND_AL, TCG_REG_TMP, TCG_REG_R0);
            tcg_out_mov_reg(s, COND_AL, data_reg2, TCG_REG_R1);
            tcg_out_mov_reg(s, COND_AL, data_reg, TCG_REG_TMP);
        }
        break;
    }

@@ -1420,17 +1420,27 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
        }
        break;
    case 3:
        if (bswap) {
            tcg_out_ld32_rwb(s, COND_AL, data_reg2, addend, addr_reg);
            tcg_out_ld32_12(s, COND_AL, data_reg, addend, 4);
            tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
        } else if (use_armv6_instructions
                   && (data_reg & 1) == 0 && data_reg2 == data_reg + 1) {
            tcg_out_ldrd_r(s, COND_AL, data_reg, addr_reg, addend);
        {
            /* Be careful not to modify data_reg and data_reg2
               for the slow path below.  */
            TCGReg dl = (bswap ? data_reg2 : data_reg);
            TCGReg dh = (bswap ? data_reg : data_reg2);

            if (use_armv6_instructions && (dl & 1) == 0 && dh == dl + 1) {
                tcg_out_ldrd_r(s, COND_AL, dl, addr_reg, addend);
            } else if (dl != addend) {
                tcg_out_ld32_rwb(s, COND_AL, dl, addend, addr_reg);
                tcg_out_ld32_12(s, COND_AL, dh, addend, 4);
            } else {
            tcg_out_ld32_rwb(s, COND_AL, data_reg, addend, addr_reg);
            tcg_out_ld32_12(s, COND_AL, data_reg2, addend, 4);
                tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_TMP,
                                addend, addr_reg, SHIFT_IMM_LSL(0));
                tcg_out_ld32_12(s, COND_AL, dl, TCG_REG_TMP, 0);
                tcg_out_ld32_12(s, COND_AL, dh, TCG_REG_TMP, 4);
            }
            if (bswap) {
                tcg_out_bswap32(s, COND_AL, dh, dh);
                tcg_out_bswap32(s, COND_AL, dl, dl);
            }
        }
        break;
    }
@@ -2025,7 +2035,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
    { INDEX_op_qemu_ld16u, { "r", "l" } },
    { INDEX_op_qemu_ld16s, { "r", "l" } },
    { INDEX_op_qemu_ld32, { "r", "l" } },
    { INDEX_op_qemu_ld64, { "L", "L", "l" } },
    { INDEX_op_qemu_ld64, { "r", "r", "l" } },

    { INDEX_op_qemu_st8, { "s", "s" } },
    { INDEX_op_qemu_st16, { "s", "s" } },
@@ -2037,7 +2047,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
    { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
    { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
    { INDEX_op_qemu_ld32, { "r", "l", "l" } },
    { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
    { INDEX_op_qemu_ld64, { "r", "r", "l", "l" } },

    { INDEX_op_qemu_st8, { "s", "s", "s" } },
    { INDEX_op_qemu_st16, { "s", "s", "s" } },