Commit 6a6739de authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20151021' into staging



Collected tcg backend patches

# gpg: Signature made Wed 21 Oct 2015 22:34:28 BST using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"

* remotes/rth/tags/pull-tcg-20151021:
  cpu-exec: Add "nochain" debug flag
  tcg/mips: Support r6 SEL{NE, EQ}Z instead of MOVN/MOVZ
  tcg/mips: Support r6 multiply/divide encodings
  tcg/mips: Support r6 JR encoding
  tcg/mips: Add use_mips32r6_instructions definition
  disas/mips: Add R6 jr/jr.hb to disassembler
  tcg-opc.h: Simplify insn_start def
  tcg/ppc: Prefer mask over andi.
  tcg/ppc: Revise goto_tb implementation
  tcg/ppc: Adjust exit_tb for change in prologue placement

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents b803894e 89a82cd4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -477,7 +477,8 @@ int cpu_exec(CPUState *cpu)
                /* see if we can patch the calling TB. When the TB
                   spans two pages, we cannot safely do a direct
                   jump. */
                if (next_tb != 0 && tb->page_addr[1] == -1) {
                if (next_tb != 0 && tb->page_addr[1] == -1
                    && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
                    tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
                                next_tb & TB_EXIT_MASK, tb);
                }
+2 −0
Original line number Diff line number Diff line
@@ -2420,9 +2420,11 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"hibernate","",        0x42000023, 0xffffffff,	0, 			0,		V1	},
{"ins",     "t,r,+A,+B", 0x7c000004, 0xfc00003f, WR_t|RD_s,    		0,		I33	},
{"jr",      "s",	0x00000008, 0xfc1fffff,	UBD|RD_s,		0,		I1	},
{"jr",      "s",	0x00000009, 0xfc1fffff,	UBD|RD_s,		0,		I32R6	}, /* jalr */
/* jr.hb is officially MIPS{32,64}R2, but it works on R1 as jr with
   the same hazard barrier effect.  */
{"jr.hb",   "s",	0x00000408, 0xfc1fffff,	UBD|RD_s,		0,		I32	},
{"jr.hb",   "s",	0x00000409, 0xfc1fffff,	UBD|RD_s,		0,		I32R6	}, /* jalr.hb */
{"j",       "s",	0x00000008, 0xfc1fffff,	UBD|RD_s,		0,		I1	}, /* jr */
/* SVR4 PIC code requires special handling for j, so it must be a
   macro.  */
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ static inline bool qemu_log_enabled(void)
#define LOG_UNIMP          (1 << 10)
#define LOG_GUEST_ERROR    (1 << 11)
#define CPU_LOG_MMU        (1 << 12)
#define CPU_LOG_TB_NOCHAIN (1 << 13)

/* Returns true if a bit is set in the current loglevel mask
 */
+3 −0
Original line number Diff line number Diff line
@@ -119,6 +119,9 @@ const QEMULogItem qemu_log_items[] = {
    { LOG_GUEST_ERROR, "guest_errors",
      "log when the guest OS does something invalid (eg accessing a\n"
      "non-existent register)" },
    { CPU_LOG_TB_NOCHAIN, "nochain",
      "do not chain compiled TBs so that \"exec\" and \"cpu\" show\n"
      "complete traces" },
    { 0, NULL, NULL },
};

+82 −8
Original line number Diff line number Diff line
@@ -288,16 +288,24 @@ typedef enum {
    OPC_SRLV     = OPC_SPECIAL | 0x06,
    OPC_ROTRV    = OPC_SPECIAL | (0x01 <<  6) | 0x06,
    OPC_SRAV     = OPC_SPECIAL | 0x07,
    OPC_JR       = OPC_SPECIAL | 0x08,
    OPC_JR_R5    = OPC_SPECIAL | 0x08,
    OPC_JALR     = OPC_SPECIAL | 0x09,
    OPC_MOVZ     = OPC_SPECIAL | 0x0A,
    OPC_MOVN     = OPC_SPECIAL | 0x0B,
    OPC_MFHI     = OPC_SPECIAL | 0x10,
    OPC_MFLO     = OPC_SPECIAL | 0x12,
    OPC_MULT     = OPC_SPECIAL | 0x18,
    OPC_MUL_R6   = OPC_SPECIAL | (0x02 <<  6) | 0x18,
    OPC_MUH      = OPC_SPECIAL | (0x03 <<  6) | 0x18,
    OPC_MULTU    = OPC_SPECIAL | 0x19,
    OPC_MULU     = OPC_SPECIAL | (0x02 <<  6) | 0x19,
    OPC_MUHU     = OPC_SPECIAL | (0x03 <<  6) | 0x19,
    OPC_DIV      = OPC_SPECIAL | 0x1A,
    OPC_DIV_R6   = OPC_SPECIAL | (0x02 <<  6) | 0x1A,
    OPC_MOD      = OPC_SPECIAL | (0x03 <<  6) | 0x1A,
    OPC_DIVU     = OPC_SPECIAL | 0x1B,
    OPC_DIVU_R6  = OPC_SPECIAL | (0x02 <<  6) | 0x1B,
    OPC_MODU     = OPC_SPECIAL | (0x03 <<  6) | 0x1B,
    OPC_ADDU     = OPC_SPECIAL | 0x21,
    OPC_SUBU     = OPC_SPECIAL | 0x23,
    OPC_AND      = OPC_SPECIAL | 0x24,
@@ -306,13 +314,15 @@ typedef enum {
    OPC_NOR      = OPC_SPECIAL | 0x27,
    OPC_SLT      = OPC_SPECIAL | 0x2A,
    OPC_SLTU     = OPC_SPECIAL | 0x2B,
    OPC_SELEQZ   = OPC_SPECIAL | 0x35,
    OPC_SELNEZ   = OPC_SPECIAL | 0x37,

    OPC_REGIMM   = 0x01 << 26,
    OPC_BLTZ     = OPC_REGIMM | (0x00 << 16),
    OPC_BGEZ     = OPC_REGIMM | (0x01 << 16),

    OPC_SPECIAL2 = 0x1c << 26,
    OPC_MUL      = OPC_SPECIAL2 | 0x002,
    OPC_MUL_R5   = OPC_SPECIAL2 | 0x002,

    OPC_SPECIAL3 = 0x1f << 26,
    OPC_EXT      = OPC_SPECIAL3 | 0x000,
@@ -320,6 +330,15 @@ typedef enum {
    OPC_WSBH     = OPC_SPECIAL3 | 0x0a0,
    OPC_SEB      = OPC_SPECIAL3 | 0x420,
    OPC_SEH      = OPC_SPECIAL3 | 0x620,

    /* MIPS r6 doesn't have JR, JALR should be used instead */
    OPC_JR       = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,

    /*
     * MIPS r6 replaces MUL with an alternative encoding which is
     * backwards-compatible at the assembly level.
     */
    OPC_MUL      = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
} MIPSInsn;

/*
@@ -841,13 +860,20 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
}

static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
                            TCGReg c1, TCGReg c2, TCGReg v)
                            TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
{
    MIPSInsn m_opc = OPC_MOVN;
    bool eqz = false;

    /* If one of the values is zero, put it last to match SEL*Z instructions */
    if (use_mips32r6_instructions && v1 == 0) {
        v1 = v2;
        v2 = 0;
        cond = tcg_invert_cond(cond);
    }

    switch (cond) {
    case TCG_COND_EQ:
        m_opc = OPC_MOVZ;
        eqz = true;
        /* FALLTHRU */
    case TCG_COND_NE:
        if (c2 != 0) {
@@ -860,14 +886,32 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
        /* Minimize code size by preferring a compare not requiring INV.  */
        if (mips_cmp_map[cond] & MIPS_CMP_INV) {
            cond = tcg_invert_cond(cond);
            m_opc = OPC_MOVZ;
            eqz = true;
        }
        tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
        c1 = TCG_TMP0;
        break;
    }

    tcg_out_opc_reg(s, m_opc, ret, v, c1);
    if (use_mips32r6_instructions) {
        MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
        MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;

        if (v2 != 0) {
            tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
        }
        tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
        if (v2 != 0) {
            tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
        }
    } else {
        MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;

        tcg_out_opc_reg(s, m_opc, ret, v1, c1);

        /* This should be guaranteed via constraints */
        tcg_debug_assert(v2 == ret);
    }
}

static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
@@ -1445,21 +1489,45 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
        i1 = OPC_MULT, i2 = OPC_MFLO;
        goto do_hilo1;
    case INDEX_op_mulsh_i32:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_MUH, a0, a1, a2);
            break;
        }
        i1 = OPC_MULT, i2 = OPC_MFHI;
        goto do_hilo1;
    case INDEX_op_muluh_i32:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_MUHU, a0, a1, a2);
            break;
        }
        i1 = OPC_MULTU, i2 = OPC_MFHI;
        goto do_hilo1;
    case INDEX_op_div_i32:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
            break;
        }
        i1 = OPC_DIV, i2 = OPC_MFLO;
        goto do_hilo1;
    case INDEX_op_divu_i32:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
            break;
        }
        i1 = OPC_DIVU, i2 = OPC_MFLO;
        goto do_hilo1;
    case INDEX_op_rem_i32:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
            break;
        }
        i1 = OPC_DIV, i2 = OPC_MFHI;
        goto do_hilo1;
    case INDEX_op_remu_i32:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
            break;
        }
        i1 = OPC_DIVU, i2 = OPC_MFHI;
    do_hilo1:
        tcg_out_opc_reg(s, i1, 0, a1, a2);
@@ -1536,7 +1604,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
        break;

    case INDEX_op_movcond_i32:
        tcg_out_movcond(s, args[5], a0, a1, a2, args[3]);
        tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
        break;

    case INDEX_op_setcond_i32:
@@ -1592,8 +1660,10 @@ static const TCGTargetOpDef mips_op_defs[] = {

    { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
#if !use_mips32r6_instructions
    { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
#endif
    { INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } },
    { INDEX_op_muluh_i32, { "r", "rZ", "rZ" } },
    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
@@ -1623,7 +1693,11 @@ static const TCGTargetOpDef mips_op_defs[] = {
    { INDEX_op_deposit_i32, { "r", "0", "rZ" } },

    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
#if use_mips32r6_instructions
    { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
#else
    { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
#endif
    { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
    { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },

Loading