Commit 45c270b1 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/rth/tags/tcg-next-201400729' into staging



tcg updates

# gpg: Signature made Mon 29 Sep 2014 19:58:04 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/tcg-next-201400729:
  tcg: Always enable TCGv type checking
  qemu/compiler: Define QEMU_ARTIFICIAL
  tcg-aarch64: Use 32-bit loads for qemu_ld_i32
  tcg-sparc: Use UMULXHI instruction
  tcg-sparc: Rename ADDX/SUBX insns
  tcg-sparc: Use ADDXC in setcond_i64
  tcg-sparc: Fix setcond_i32 uninitialized value
  tcg-sparc: Use ADDXC in addsub2_i64
  tcg-sparc: Support addsub2_i64

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 29429c72 b6c73a6d
Loading
Loading
Loading
Loading
+14 −20
Original line number Diff line number Diff line
@@ -1175,15 +1175,11 @@ static const struct sparc_opcode sparc_opcodes[] = {
{ "subcc",      F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|ASI(~0),      "1,2,d", 0, v6 },
{ "subcc",      F3(2, 0x14, 1), F3(~2, ~0x14, ~1),              "1,i,d", 0, v6 },

{ "subx",       F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0),      "1,2,d", 0, v6notv9 },
{ "subx",       F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1),              "1,i,d", 0, v6notv9 },
{ "subc",       F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0),      "1,2,d", 0, v9 },
{ "subc",       F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1),              "1,i,d", 0, v9 },
{ "subc",       F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0),      "1,2,d", 0, v6 },
{ "subc",       F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1),              "1,i,d", 0, v6 },

{ "subxcc",     F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0),      "1,2,d", 0, v6notv9 },
{ "subxcc",     F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1),              "1,i,d", 0, v6notv9 },
{ "subccc",     F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0),      "1,2,d", 0, v9 },
{ "subccc",     F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1),              "1,i,d", 0, v9 },
{ "subccc",     F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0),      "1,2,d", 0, v6 },
{ "subccc",     F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1),              "1,i,d", 0, v6 },

{ "and",        F3(2, 0x01, 0), F3(~2, ~0x01, ~0)|ASI(~0),      "1,2,d", 0, v6 },
{ "and",        F3(2, 0x01, 1), F3(~2, ~0x01, ~1),              "1,i,d", 0, v6 },
@@ -1215,19 +1211,13 @@ static const struct sparc_opcode sparc_opcodes[] = {
{ "addcc",      F3(2, 0x10, 1), F3(~2, ~0x10, ~1),              "1,i,d", 0, v6 },
{ "addcc",      F3(2, 0x10, 1), F3(~2, ~0x10, ~1),              "i,1,d", 0, v6 },

{ "addx",       F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0),      "1,2,d", 0, v6notv9 },
{ "addx",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "1,i,d", 0, v6notv9 },
{ "addx",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "i,1,d", 0, v6notv9 },
{ "addc",       F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0),      "1,2,d", 0, v9 },
{ "addc",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "1,i,d", 0, v9 },
{ "addc",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "i,1,d", 0, v9 },
{ "addc",       F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0),      "1,2,d", 0, v6 },
{ "addc",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "1,i,d", 0, v6 },
{ "addc",       F3(2, 0x08, 1), F3(~2, ~0x08, ~1),              "i,1,d", 0, v6 },

{ "addxcc",     F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0),      "1,2,d", 0, v6notv9 },
{ "addxcc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "1,i,d", 0, v6notv9 },
{ "addxcc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "i,1,d", 0, v6notv9 },
{ "addccc",     F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0),      "1,2,d", 0, v9 },
{ "addccc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "1,i,d", 0, v9 },
{ "addccc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "i,1,d", 0, v9 },
{ "addccc",     F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0),      "1,2,d", 0, v6 },
{ "addccc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "1,i,d", 0, v6 },
{ "addccc",     F3(2, 0x18, 1), F3(~2, ~0x18, ~1),              "i,1,d", 0, v6 },

{ "smul",       F3(2, 0x0b, 0), F3(~2, ~0x0b, ~0)|ASI(~0),      "1,2,d", 0, v8 },
{ "smul",       F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1),              "1,i,d", 0, v8 },
@@ -2042,6 +2032,10 @@ IMPDEP ("impdep2", 0x37),

#undef IMPDEP

{ "addxc", F3F(2, 0x36, 0x011), F3F(~2, ~0x36, ~0x011), "1,2,d", 0, v9b },
{ "addxccc", F3F(2, 0x36, 0x013), F3F(~2, ~0x36, ~0x013), "1,2,d", 0, v9b },
{ "umulxhi", F3F(2, 0x36, 0x016), F3F(~2, ~0x36, ~0x016), "1,2,d", 0, v9b },

};

static const int sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]));
+29 −8
Original line number Diff line number Diff line
@@ -473,14 +473,35 @@ typedef struct {
#define PPC_FEATURE_TRUE_LE             0x00000002
#define PPC_FEATURE_PPC_LE              0x00000001

/* Bits present in AT_HWCAP, primarily for Sparc32.  */

#define HWCAP_SPARC_FLUSH       1    /* CPU supports flush instruction. */
#define HWCAP_SPARC_STBAR       2
#define HWCAP_SPARC_SWAP        4
#define HWCAP_SPARC_MULDIV      8
#define HWCAP_SPARC_V9		16
#define HWCAP_SPARC_ULTRA3	32
/* Bits present in AT_HWCAP for Sparc.  */

#define HWCAP_SPARC_FLUSH               0x00000001
#define HWCAP_SPARC_STBAR               0x00000002
#define HWCAP_SPARC_SWAP                0x00000004
#define HWCAP_SPARC_MULDIV              0x00000008
#define HWCAP_SPARC_V9                  0x00000010
#define HWCAP_SPARC_ULTRA3              0x00000020
#define HWCAP_SPARC_BLKINIT             0x00000040
#define HWCAP_SPARC_N2                  0x00000080
#define HWCAP_SPARC_MUL32               0x00000100
#define HWCAP_SPARC_DIV32               0x00000200
#define HWCAP_SPARC_FSMULD              0x00000400
#define HWCAP_SPARC_V8PLUS              0x00000800
#define HWCAP_SPARC_POPC                0x00001000
#define HWCAP_SPARC_VIS                 0x00002000
#define HWCAP_SPARC_VIS2                0x00004000
#define HWCAP_SPARC_ASI_BLK_INIT        0x00008000
#define HWCAP_SPARC_FMAF                0x00010000
#define HWCAP_SPARC_VIS3                0x00020000
#define HWCAP_SPARC_HPC                 0x00040000
#define HWCAP_SPARC_RANDOM              0x00080000
#define HWCAP_SPARC_TRANS               0x00100000
#define HWCAP_SPARC_FJFMAU              0x00200000
#define HWCAP_SPARC_IMA                 0x00400000
#define HWCAP_SPARC_ASI_CACHE_SPARING   0x00800000
#define HWCAP_SPARC_PAUSE               0x01000000
#define HWCAP_SPARC_CBCOND              0x02000000
#define HWCAP_SPARC_CRYPTO              0x04000000

/* Bits present in AT_HWCAP for s390.  */

+6 −0
Original line number Diff line number Diff line
@@ -24,6 +24,12 @@
#define QEMU_WARN_UNUSED_RESULT
#endif

#if QEMU_GNUC_PREREQ(4, 3)
#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
#else
#define QEMU_ARTIFICIAL
#endif

#if defined(_WIN32)
# define QEMU_PACKED __attribute__((gcc_struct, packed))
#else
+15 −12
Original line number Diff line number Diff line
@@ -1007,7 +1007,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
    tcg_out_adr(s, TCG_REG_X3, lb->raddr);
    tcg_out_call(s, qemu_ld_helpers[opc & ~MO_SIGN]);
    if (opc & MO_SIGN) {
        tcg_out_sxt(s, TCG_TYPE_I64, size, lb->datalo_reg, TCG_REG_X0);
        tcg_out_sxt(s, lb->type, size, lb->datalo_reg, TCG_REG_X0);
    } else {
        tcg_out_mov(s, size == MO_64, lb->datalo_reg, TCG_REG_X0);
    }
@@ -1032,7 +1032,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
}

static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
                                TCGReg data_reg, TCGReg addr_reg,
                                TCGType ext, TCGReg data_reg, TCGReg addr_reg,
                                int mem_index, tcg_insn_unit *raddr,
                                tcg_insn_unit *label_ptr)
{
@@ -1040,6 +1040,7 @@ static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,

    label->is_ld = is_ld;
    label->opc = opc;
    label->type = ext;
    label->datalo_reg = data_reg;
    label->addrlo_reg = addr_reg;
    label->mem_index = mem_index;
@@ -1108,7 +1109,7 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp s_bits,

#endif /* CONFIG_SOFTMMU */

static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop,
static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop, TCGType ext,
                                   TCGReg data_r, TCGReg addr_r, TCGReg off_r)
{
    const TCGMemOp bswap = memop & MO_BSWAP;
@@ -1118,7 +1119,8 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop,
        tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, off_r);
        break;
    case MO_SB:
        tcg_out_ldst_r(s, I3312_LDRSBX, data_r, addr_r, off_r);
        tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW,
                       data_r, addr_r, off_r);
        break;
    case MO_UW:
        tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, off_r);
@@ -1130,9 +1132,10 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop,
        if (bswap) {
            tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, off_r);
            tcg_out_rev16(s, data_r, data_r);
            tcg_out_sxt(s, TCG_TYPE_I64, MO_16, data_r, data_r);
            tcg_out_sxt(s, ext, MO_16, data_r, data_r);
        } else {
            tcg_out_ldst_r(s, I3312_LDRSHX, data_r, addr_r, off_r);
            tcg_out_ldst_r(s, ext ? I3312_LDRSHX : I3312_LDRSHW,
                           data_r, addr_r, off_r);
        }
        break;
    case MO_UL:
@@ -1197,18 +1200,18 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp memop,
}

static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
                            TCGMemOp memop, int mem_index)
                            TCGMemOp memop, TCGType ext, int mem_index)
{
#ifdef CONFIG_SOFTMMU
    TCGMemOp s_bits = memop & MO_SIZE;
    tcg_insn_unit *label_ptr;

    tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 1);
    tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
    add_qemu_ldst_label(s, true, memop, data_reg, addr_reg,
    tcg_out_qemu_ld_direct(s, memop, ext, data_reg, addr_reg, TCG_REG_X1);
    add_qemu_ldst_label(s, true, memop, ext, data_reg, addr_reg,
                        mem_index, s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
    tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg,
    tcg_out_qemu_ld_direct(s, memop, ext, data_reg, addr_reg,
                           GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
#endif /* CONFIG_SOFTMMU */
}
@@ -1222,7 +1225,7 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,

    tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 0);
    tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_REG_X1);
    add_qemu_ldst_label(s, false, memop, data_reg, addr_reg,
    add_qemu_ldst_label(s, false, memop, s_bits == MO_64, data_reg, addr_reg,
                        mem_index, s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
    tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg,
@@ -1515,7 +1518,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,

    case INDEX_op_qemu_ld_i32:
    case INDEX_op_qemu_ld_i64:
        tcg_out_qemu_ld(s, a0, a1, a2, args[3]);
        tcg_out_qemu_ld(s, a0, a1, a2, ext, args[3]);
        break;
    case INDEX_op_qemu_st_i32:
    case INDEX_op_qemu_st_i64:
+115 −14
Original line number Diff line number Diff line
@@ -197,8 +197,8 @@ static const int tcg_target_call_oarg_regs[] = {
#define ARITH_XOR  (INSN_OP(2) | INSN_OP3(0x03))
#define ARITH_SUB  (INSN_OP(2) | INSN_OP3(0x04))
#define ARITH_SUBCC (INSN_OP(2) | INSN_OP3(0x14))
#define ARITH_ADDX (INSN_OP(2) | INSN_OP3(0x08))
#define ARITH_SUBX (INSN_OP(2) | INSN_OP3(0x0c))
#define ARITH_ADDC (INSN_OP(2) | INSN_OP3(0x08))
#define ARITH_SUBC (INSN_OP(2) | INSN_OP3(0x0c))
#define ARITH_UMUL (INSN_OP(2) | INSN_OP3(0x0a))
#define ARITH_SMUL (INSN_OP(2) | INSN_OP3(0x0b))
#define ARITH_UDIV (INSN_OP(2) | INSN_OP3(0x0e))
@@ -209,6 +209,9 @@ static const int tcg_target_call_oarg_regs[] = {
#define ARITH_MOVCC (INSN_OP(2) | INSN_OP3(0x2c))
#define ARITH_MOVR (INSN_OP(2) | INSN_OP3(0x2f))

#define ARITH_ADDXC (INSN_OP(2) | INSN_OP3(0x36) | INSN_OPF(0x11))
#define ARITH_UMULXHI (INSN_OP(2) | INSN_OP3(0x36) | INSN_OPF(0x16))

#define SHIFT_SLL  (INSN_OP(2) | INSN_OP3(0x25))
#define SHIFT_SRL  (INSN_OP(2) | INSN_OP3(0x26))
#define SHIFT_SRA  (INSN_OP(2) | INSN_OP3(0x27))
@@ -262,6 +265,10 @@ static const int tcg_target_call_oarg_regs[] = {
#define STW_LE     (STWA  | INSN_ASI(ASI_PRIMARY_LITTLE))
#define STX_LE     (STXA  | INSN_ASI(ASI_PRIMARY_LITTLE))

#ifndef use_vis3_instructions
bool use_vis3_instructions;
#endif

static inline int check_fit_i64(int64_t val, unsigned int bits)
{
    return val == sextract64(val, 0, bits);
@@ -657,7 +664,7 @@ static void tcg_out_movcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
                                TCGReg c1, int32_t c2, int c2const)
{
    /* For 32-bit comparisons, we can play games with ADDX/SUBX.  */
    /* For 32-bit comparisons, we can play games with ADDC/SUBC.  */
    switch (cond) {
    case TCG_COND_LTU:
    case TCG_COND_GEU:
@@ -668,9 +675,12 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,
    case TCG_COND_NE:
        /* For equality, we can transform to inequality vs zero.  */
        if (c2 != 0) {
            tcg_out_arithc(s, ret, c1, c2, c2const, ARITH_XOR);
            tcg_out_arithc(s, TCG_REG_T1, c1, c2, c2const, ARITH_XOR);
            c2 = TCG_REG_T1;
        } else {
            c2 = c1;
        }
        c1 = TCG_REG_G0, c2 = ret, c2const = 0;
        c1 = TCG_REG_G0, c2const = 0;
        cond = (cond == TCG_COND_EQ ? TCG_COND_GEU : TCG_COND_LTU);
	break;

@@ -698,15 +708,32 @@ static void tcg_out_setcond_i32(TCGContext *s, TCGCond cond, TCGReg ret,

    tcg_out_cmp(s, c1, c2, c2const);
    if (cond == TCG_COND_LTU) {
        tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDX);
        tcg_out_arithi(s, ret, TCG_REG_G0, 0, ARITH_ADDC);
    } else {
        tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBX);
        tcg_out_arithi(s, ret, TCG_REG_G0, -1, ARITH_SUBC);
    }
}

static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
                                TCGReg c1, int32_t c2, int c2const)
{
    if (use_vis3_instructions) {
        switch (cond) {
        case TCG_COND_NE:
            if (c2 != 0) {
                break;
            }
            c2 = c1, c2const = 0, c1 = TCG_REG_G0;
            /* FALLTHRU */
        case TCG_COND_LTU:
            tcg_out_cmp(s, c1, c2, c2const);
            tcg_out_arith(s, ret, TCG_REG_G0, TCG_REG_G0, ARITH_ADDXC);
            return;
        default:
            break;
        }
    }

    /* For 64-bit signed comparisons vs zero, we can avoid the compare
       if the input does not overlap the output.  */
    if (c2 == 0 && !is_unsigned_cond(cond) && c1 != ret) {
@@ -719,7 +746,7 @@ static void tcg_out_setcond_i64(TCGContext *s, TCGCond cond, TCGReg ret,
    }
}

static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh,
static void tcg_out_addsub2_i32(TCGContext *s, TCGReg rl, TCGReg rh,
                                TCGReg al, TCGReg ah, int32_t bl, int blconst,
                                int32_t bh, int bhconst, int opl, int oph)
{
@@ -735,6 +762,54 @@ static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh,
    tcg_out_mov(s, TCG_TYPE_I32, rl, tmp);
}

static void tcg_out_addsub2_i64(TCGContext *s, TCGReg rl, TCGReg rh,
                                TCGReg al, TCGReg ah, int32_t bl, int blconst,
                                int32_t bh, int bhconst, bool is_sub)
{
    TCGReg tmp = TCG_REG_T1;

    /* Note that the low parts are fully consumed before tmp is set.  */
    if (rl != ah && (bhconst || rl != bh)) {
        tmp = rl;
    }

    tcg_out_arithc(s, tmp, al, bl, blconst, is_sub ? ARITH_SUBCC : ARITH_ADDCC);

    if (use_vis3_instructions && !is_sub) {
        /* Note that ADDXC doesn't accept immediates.  */
        if (bhconst && bh != 0) {
           tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_T2, bh);
           bh = TCG_REG_T2;
        }
        tcg_out_arith(s, rh, ah, bh, ARITH_ADDXC);
    } else if (bh == TCG_REG_G0) {
	/* If we have a zero, we can perform the operation in two insns,
           with the arithmetic first, and a conditional move into place.  */
	if (rh == ah) {
            tcg_out_arithi(s, TCG_REG_T2, ah, 1,
			   is_sub ? ARITH_SUB : ARITH_ADD);
            tcg_out_movcc(s, TCG_COND_LTU, MOVCC_XCC, rh, TCG_REG_T2, 0);
	} else {
            tcg_out_arithi(s, rh, ah, 1, is_sub ? ARITH_SUB : ARITH_ADD);
	    tcg_out_movcc(s, TCG_COND_GEU, MOVCC_XCC, rh, ah, 0);
	}
    } else {
        /* Otherwise adjust BH as if there is carry into T2 ... */
        if (bhconst) {
            tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_T2, bh + (is_sub ? -1 : 1));
        } else {
            tcg_out_arithi(s, TCG_REG_T2, bh, 1,
                           is_sub ? ARITH_SUB : ARITH_ADD);
        }
        /* ... smoosh T2 back to original BH if carry is clear ... */
        tcg_out_movcc(s, TCG_COND_GEU, MOVCC_XCC, TCG_REG_T2, bh, bhconst);
	/* ... and finally perform the arithmetic with the new operand.  */
        tcg_out_arith(s, rh, ah, TCG_REG_T2, is_sub ? ARITH_SUB : ARITH_ADD);
    }

    tcg_out_mov(s, TCG_TYPE_I64, rl, tmp);
}

static void tcg_out_call_nodelay(TCGContext *s, tcg_insn_unit *dest)
{
    ptrdiff_t disp = tcg_pcrel_diff(s, dest);
@@ -1264,12 +1339,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
        break;

    case INDEX_op_add2_i32:
        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], const_args[4],
                        args[5], const_args[5], ARITH_ADDCC, ARITH_ADDX);
        tcg_out_addsub2_i32(s, args[0], args[1], args[2], args[3],
                            args[4], const_args[4], args[5], const_args[5],
                            ARITH_ADDCC, ARITH_ADDC);
        break;
    case INDEX_op_sub2_i32:
        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], const_args[4],
                        args[5], const_args[5], ARITH_SUBCC, ARITH_SUBX);
        tcg_out_addsub2_i32(s, args[0], args[1], args[2], args[3],
                            args[4], const_args[4], args[5], const_args[5],
                            ARITH_SUBCC, ARITH_SUBC);
        break;
    case INDEX_op_mulu2_i32:
        c = ARITH_UMUL;
@@ -1351,6 +1428,17 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
    case INDEX_op_movcond_i64:
        tcg_out_movcond_i64(s, args[5], a0, a1, a2, c2, args[3], const_args[3]);
        break;
    case INDEX_op_add2_i64:
        tcg_out_addsub2_i64(s, args[0], args[1], args[2], args[3], args[4],
                            const_args[4], args[5], const_args[5], false);
        break;
    case INDEX_op_sub2_i64:
        tcg_out_addsub2_i64(s, args[0], args[1], args[2], args[3], args[4],
                            const_args[4], args[5], const_args[5], true);
        break;
    case INDEX_op_muluh_i64:
        tcg_out_arith(s, args[0], args[1], args[2], ARITH_UMULXHI);
        break;

    gen_arith:
        tcg_out_arithc(s, a0, a1, a2, c2, c);
@@ -1449,6 +1537,10 @@ static const TCGTargetOpDef sparc_op_defs[] = {
    { INDEX_op_setcond_i64, { "R", "RZ", "RJ" } },
    { INDEX_op_movcond_i64, { "R", "RZ", "RJ", "RI", "0" } },

    { INDEX_op_add2_i64, { "R", "R", "RZ", "RZ", "RJ", "RI" } },
    { INDEX_op_sub2_i64, { "R", "R", "RZ", "RZ", "RJ", "RI" } },
    { INDEX_op_muluh_i64, { "R", "RZ", "RZ" } },

    { INDEX_op_qemu_ld_i32, { "r", "A" } },
    { INDEX_op_qemu_ld_i64, { "R", "A" } },
    { INDEX_op_qemu_st_i32, { "sZ", "A" } },
@@ -1459,6 +1551,15 @@ static const TCGTargetOpDef sparc_op_defs[] = {

static void tcg_target_init(TCGContext *s)
{
    /* Only probe for the platform and capabilities if we havn't already
       determined maximum values at compile time.  */
#ifndef use_vis3_instructions
    {
        unsigned long hwcap = qemu_getauxval(AT_HWCAP);
        use_vis3_instructions = (hwcap & HWCAP_SPARC_VIS3) != 0;
    }
#endif

    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, ALL_64);

Loading