tcg-sparc: Use ADDXC in addsub2_i64
On T4 and newer Sparc chips we have an add-with-carry insn that takes its input from %xcc instead of %icc. Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
609ac1e164
commit
90379ca84e
@ -2042,6 +2042,9 @@ 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 },
|
||||
|
||||
};
|
||||
|
||||
static const int sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]));
|
||||
|
@ -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. */
|
||||
/* Bits present in AT_HWCAP for Sparc. */
|
||||
|
||||
#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
|
||||
#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. */
|
||||
|
||||
|
@ -209,6 +209,8 @@ 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 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 +264,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);
|
||||
@ -748,11 +754,14 @@ static void tcg_out_addsub2_i64(TCGContext *s, TCGReg rl, TCGReg rh,
|
||||
|
||||
tcg_out_arithc(s, tmp, al, bl, blconst, is_sub ? ARITH_SUBCC : ARITH_ADDCC);
|
||||
|
||||
/* Note that ADDX/SUBX take the carry-in from %icc, the 32-bit carry,
|
||||
while we want %xcc, the 64-bit carry. */
|
||||
/* ??? There is a 2011 VIS3 ADDXC insn that does take a 64-bit carry. */
|
||||
|
||||
if (bh == TCG_REG_G0) {
|
||||
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) {
|
||||
@ -1517,6 +1526,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);
|
||||
|
||||
|
@ -85,6 +85,12 @@ typedef enum {
|
||||
#define TCG_TARGET_EXTEND_ARGS 1
|
||||
#endif
|
||||
|
||||
#if defined(__VIS__) && __VIS__ >= 0x300
|
||||
#define use_vis3_instructions 1
|
||||
#else
|
||||
extern bool use_vis3_instructions;
|
||||
#endif
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_div_i32 1
|
||||
#define TCG_TARGET_HAS_rem_i32 0
|
||||
|
Loading…
Reference in New Issue
Block a user