Commit f23e5e15 authored by Richard Henderson's avatar Richard Henderson
Browse files

tcg/aarch64: Implement tcg_out_dupm_vec



The LD1R instruction does all the work.  Note that the only
useful addressing mode is a base register with no offset.

Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent 1e262b49
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -381,6 +381,9 @@ typedef enum {
    I3207_BLR       = 0xd63f0000,
    I3207_RET       = 0xd65f0000,

    /* AdvSIMD load/store single structure.  */
    I3303_LD1R      = 0x0d40c000,

    /* Load literal for loading the address at pc-relative offset */
    I3305_LDR       = 0x58000000,
    I3305_LDR_v64   = 0x5c000000,
@@ -566,7 +569,14 @@ static inline uint32_t tcg_in32(TCGContext *s)
#define tcg_out_insn(S, FMT, OP, ...) \
    glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)

static void tcg_out_insn_3305(TCGContext *s, AArch64Insn insn, int imm19, TCGReg rt)
static void tcg_out_insn_3303(TCGContext *s, AArch64Insn insn, bool q,
                              TCGReg rt, TCGReg rn, unsigned size)
{
    tcg_out32(s, insn | (rt & 0x1f) | (rn << 5) | (size << 10) | (q << 30));
}

static void tcg_out_insn_3305(TCGContext *s, AArch64Insn insn,
                              int imm19, TCGReg rt)
{
    tcg_out32(s, insn | (imm19 & 0x7ffff) << 5 | rt);
}
@@ -825,7 +835,30 @@ static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
                             TCGReg r, TCGReg base, intptr_t offset)
{
    return false;
    TCGReg temp = TCG_REG_TMP;

    if (offset < -0xffffff || offset > 0xffffff) {
        tcg_out_movi(s, TCG_TYPE_PTR, temp, offset);
        tcg_out_insn(s, 3502, ADD, 1, temp, temp, base);
        base = temp;
    } else {
        AArch64Insn add_insn = I3401_ADDI;

        if (offset < 0) {
            add_insn = I3401_SUBI;
            offset = -offset;
        }
        if (offset & 0xfff000) {
            tcg_out_insn_3401(s, add_insn, 1, temp, base, offset & 0xfff000);
            base = temp;
        }
        if (offset & 0xfff) {
            tcg_out_insn_3401(s, add_insn, 1, temp, base, offset & 0xfff);
            base = temp;
        }
    }
    tcg_out_insn(s, 3303, LD1R, type == TCG_TYPE_V128, r, base, vece);
    return true;
}

static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,