提交 b006f816 编写于 作者: P Peter Maydell

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

TCG sparc backend update for 20140428

# gpg: Signature made Mon 28 Apr 2014 19:36:55 BST using RSA key ID 4DD0279B
# gpg: Can't check signature: public key not found

* remotes/rth/tags/tcg-sparc-pull-20140428:
  tcg-sparc: Accept stores of zero
  tcg-sparc: Fix small 32-bit movi
  tcg-sparc: Fixup function argument types
  tcg-sparc: Hoist common argument loads in tcg_out_op
  tcg-sparc: Don't handle mov/movi in tcg_out_op
  tcg-sparc: Tidy check_fit_* tests
  tcg-sparc: Implement muls2_i32
  tcg-sparc: Use the RETURN instruction
  tcg-sparc: Use 64-bit registers with sparcv8plus
  tcg-sparc: Support trunc_shr_i32
  tcg-sparc: Remove most uses of TCG_TARGET_REG_BITS
  tcg: Add INDEX_op_trunc_shr_i32
  tcg: Fix missed pointer size != TCG_TARGET_REG_BITS changes
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -84,7 +84,7 @@
#define dh_is_64bit_noreturn 0
#define dh_is_64bit_i32 0
#define dh_is_64bit_i64 1
#define dh_is_64bit_ptr (TCG_TARGET_REG_BITS == 64)
#define dh_is_64bit_ptr (sizeof(void *) == 8)
#define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
#define dh_is_signed_void 0
......
......@@ -314,6 +314,11 @@ This operation would be equivalent to
dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00)
* trunc_shr_i32 t0, t1, pos
For 64-bit hosts only, right shift the 64-bit input T1 by POS and
truncate to 32-bit output T0. Depending on the host, this may be
a simple mov/shift, or may require additional canonicalization.
********* Conditional moves
......
......@@ -68,6 +68,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 1
......
......@@ -99,6 +99,7 @@ extern bool have_bmi1;
#define TCG_TARGET_HAS_mulsh_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div2_i64 1
#define TCG_TARGET_HAS_rot_i64 1
#define TCG_TARGET_HAS_ext8s_i64 1
......
......@@ -152,6 +152,7 @@ typedef enum {
#define TCG_TARGET_HAS_muluh_i64 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_mulsh_i64 0
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_new_ldst 1
......
......@@ -228,6 +228,7 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
case INDEX_op_shr_i32:
return (uint32_t)x >> (y & 31);
case INDEX_op_trunc_shr_i32:
case INDEX_op_shr_i64:
return (uint64_t)x >> (y & 63);
......@@ -830,6 +831,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
break;
case INDEX_op_trunc_shr_i32:
mask = (uint64_t)temps[args[1]].mask >> args[2];
break;
CASE_OP_32_64(shl):
if (temps[args[2]].state == TCG_TEMP_CONST) {
tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
......@@ -1021,6 +1026,17 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
}
goto do_default;
case INDEX_op_trunc_shr_i32:
if (temps[args[1]].state == TCG_TEMP_CONST) {
s->gen_opc_buf[op_index] = op_to_movi(op);
tmp = do_constant_folding(op, temps[args[1]].val, args[2]);
tcg_opt_gen_movi(gen_args, args[0], tmp);
gen_args += 2;
args += 3;
break;
}
goto do_default;
CASE_OP_32_64(add):
CASE_OP_32_64(sub):
CASE_OP_32_64(mul):
......
......@@ -96,6 +96,7 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 0
......
......@@ -69,6 +69,7 @@ typedef enum TCGReg {
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div2_i64 1
#define TCG_TARGET_HAS_rot_i64 1
......
此差异已折叠。
......@@ -24,13 +24,7 @@
#ifndef TCG_TARGET_SPARC
#define TCG_TARGET_SPARC 1
#if UINTPTR_MAX == UINT32_MAX
# define TCG_TARGET_REG_BITS 32
#elif UINTPTR_MAX == UINT64_MAX
# define TCG_TARGET_REG_BITS 64
#else
# error Unknown pointer size for tcg target
#endif
#define TCG_TARGET_REG_BITS 64
#define TCG_TARGET_NB_REGS 32
......@@ -76,7 +70,7 @@ typedef enum {
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_O6
#if TCG_TARGET_REG_BITS == 64
#ifdef __arch64__
#define TCG_TARGET_STACK_BIAS 2047
#define TCG_TARGET_STACK_ALIGN 16
#define TCG_TARGET_CALL_STACK_OFFSET (128 + 6*8 + TCG_TARGET_STACK_BIAS)
......@@ -86,7 +80,7 @@ typedef enum {
#define TCG_TARGET_CALL_STACK_OFFSET (64 + 4 + 6*4)
#endif
#if TCG_TARGET_REG_BITS == 64
#ifdef __arch64__
#define TCG_TARGET_EXTEND_ARGS 1
#endif
......@@ -112,11 +106,11 @@ typedef enum {
#define TCG_TARGET_HAS_add2_i32 1
#define TCG_TARGET_HAS_sub2_i32 1
#define TCG_TARGET_HAS_mulu2_i32 1
#define TCG_TARGET_HAS_muls2_i32 0
#define TCG_TARGET_HAS_muls2_i32 1
#define TCG_TARGET_HAS_muluh_i32 0
#define TCG_TARGET_HAS_mulsh_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_trunc_shr_i32 1
#define TCG_TARGET_HAS_div_i64 1
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_rot_i64 0
......@@ -144,7 +138,6 @@ typedef enum {
#define TCG_TARGET_HAS_muls2_i64 0
#define TCG_TARGET_HAS_muluh_i64 0
#define TCG_TARGET_HAS_mulsh_i64 0
#endif
#define TCG_TARGET_HAS_new_ldst 1
......
......@@ -1624,9 +1624,20 @@ static inline void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
static inline void tcg_gen_trunc_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
static inline void tcg_gen_trunc_shr_i64_i32(TCGv_i32 ret, TCGv_i64 arg,
unsigned int count)
{
tcg_gen_mov_i32(ret, TCGV_LOW(arg));
tcg_debug_assert(count < 64);
if (count >= 32) {
tcg_gen_shri_i32(ret, TCGV_HIGH(arg), count - 32);
} else if (count == 0) {
tcg_gen_mov_i32(ret, TCGV_LOW(arg));
} else {
TCGv_i64 t = tcg_temp_new_i64();
tcg_gen_shri_i64(t, arg, count);
tcg_gen_mov_i32(ret, TCGV_LOW(t));
tcg_temp_free_i64(t);
}
}
static inline void tcg_gen_extu_i32_i64(TCGv_i64 ret, TCGv_i32 arg)
......@@ -1727,11 +1738,21 @@ static inline void tcg_gen_ext32u_i64(TCGv_i64 ret, TCGv_i64 arg)
}
}
/* Note: we assume the target supports move between 32 and 64 bit
registers. This will probably break MIPS64 targets. */
static inline void tcg_gen_trunc_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
static inline void tcg_gen_trunc_shr_i64_i32(TCGv_i32 ret, TCGv_i64 arg,
unsigned int count)
{
tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(arg)));
tcg_debug_assert(count < 64);
if (TCG_TARGET_HAS_trunc_shr_i32) {
tcg_gen_op3i_i32(INDEX_op_trunc_shr_i32, ret,
MAKE_TCGV_I32(GET_TCGV_I64(arg)), count);
} else if (count == 0) {
tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(arg)));
} else {
TCGv_i64 t = tcg_temp_new_i64();
tcg_gen_shri_i64(t, arg, count);
tcg_gen_mov_i32(ret, MAKE_TCGV_I32(GET_TCGV_I64(t)));
tcg_temp_free_i64(t);
}
}
/* Note: we assume the target supports move between 32 and 64 bit
......@@ -2275,18 +2296,15 @@ static inline void tcg_gen_concat32_i64(TCGv_i64 dest, TCGv_i64 low,
tcg_gen_deposit_i64(dest, low, high, 32, 32);
}
static inline void tcg_gen_trunc_i64_i32(TCGv_i32 ret, TCGv_i64 arg)
{
tcg_gen_trunc_shr_i64_i32(ret, arg, 0);
}
static inline void tcg_gen_extr_i64_i32(TCGv_i32 lo, TCGv_i32 hi, TCGv_i64 arg)
{
#if TCG_TARGET_REG_BITS == 32
tcg_gen_mov_i32(lo, TCGV_LOW(arg));
tcg_gen_mov_i32(hi, TCGV_HIGH(arg));
#else
TCGv_i64 t0 = tcg_temp_new_i64();
tcg_gen_trunc_i64_i32(lo, arg);
tcg_gen_shri_i64(t0, arg, 32);
tcg_gen_trunc_i64_i32(hi, t0);
tcg_temp_free_i64(t0);
#endif
tcg_gen_trunc_shr_i64_i32(lo, arg, 0);
tcg_gen_trunc_shr_i64_i32(hi, arg, 32);
}
static inline void tcg_gen_extr32_i64(TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
......@@ -2861,7 +2879,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_muls2_tl tcg_gen_muls2_i32
#endif
#if TCG_TARGET_REG_BITS == 32
#if UINTPTR_MAX == UINT32_MAX
# define tcg_gen_ld_ptr(R, A, O) \
tcg_gen_ld_i32(TCGV_PTR_TO_NAT(R), (A), (O))
# define tcg_gen_discard_ptr(A) \
......@@ -2883,4 +2901,4 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
tcg_gen_addi_i64(TCGV_PTR_TO_NAT(R), TCGV_PTR_TO_NAT(A), (B))
# define tcg_gen_ext_i32_ptr(R, A) \
tcg_gen_ext_i32_i64(TCGV_PTR_TO_NAT(R), (A))
#endif /* TCG_TARGET_REG_BITS == 32 */
#endif /* UINTPTR_MAX == UINT32_MAX */
......@@ -147,6 +147,10 @@ DEF(rotl_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64))
DEF(rotr_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rot_i64))
DEF(deposit_i64, 1, 2, 2, IMPL64 | IMPL(TCG_TARGET_HAS_deposit_i64))
DEF(trunc_shr_i32, 1, 1, 1,
IMPL(TCG_TARGET_HAS_trunc_shr_i32)
| (TCG_TARGET_REG_BITS == 32 ? TCG_OPF_NOT_PRESENT : 0))
DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | IMPL64)
DEF(ext8s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext8s_i64))
DEF(ext16s_i64, 1, 1, 0, IMPL64 | IMPL(TCG_TARGET_HAS_ext16s_i64))
......
......@@ -664,7 +664,36 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
int nb_rets;
TCGArg *nparam;
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
#if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER)
/* We have 64-bit values in one register, but need to pass as two
separate parameters. Split them. */
int orig_sizemask = sizemask;
int orig_nargs = nargs;
TCGv_i64 retl, reth;
TCGV_UNUSED_I64(retl);
TCGV_UNUSED_I64(reth);
if (sizemask != 0) {
TCGArg *split_args = __builtin_alloca(sizeof(TCGArg) * nargs * 2);
for (i = real_args = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2);
if (is_64bit) {
TCGv_i64 orig = MAKE_TCGV_I64(args[i]);
TCGv_i32 h = tcg_temp_new_i32();
TCGv_i32 l = tcg_temp_new_i32();
tcg_gen_extr_i64_i32(l, h, orig);
split_args[real_args++] = GET_TCGV_I32(h);
split_args[real_args++] = GET_TCGV_I32(l);
} else {
split_args[real_args++] = args[i];
}
}
nargs = real_args;
args = split_args;
sizemask = 0;
}
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
for (i = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2);
int is_signed = sizemask & (2 << (i+1)*2);
......@@ -684,8 +713,23 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
*s->gen_opc_ptr++ = INDEX_op_call;
nparam = s->gen_opparam_ptr++;
if (ret != TCG_CALL_DUMMY_ARG) {
#if TCG_TARGET_REG_BITS < 64
if (sizemask & 1) {
#if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER)
if (orig_sizemask & 1) {
/* The 32-bit ABI is going to return the 64-bit value in
the %o0/%o1 register pair. Prepare for this by using
two return temporaries, and reassemble below. */
retl = tcg_temp_new_i64();
reth = tcg_temp_new_i64();
*s->gen_opparam_ptr++ = GET_TCGV_I64(reth);
*s->gen_opparam_ptr++ = GET_TCGV_I64(retl);
nb_rets = 2;
} else {
*s->gen_opparam_ptr++ = ret;
nb_rets = 1;
}
#else
if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) {
#ifdef HOST_WORDS_BIGENDIAN
*s->gen_opparam_ptr++ = ret + 1;
*s->gen_opparam_ptr++ = ret;
......@@ -694,12 +738,11 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
*s->gen_opparam_ptr++ = ret + 1;
#endif
nb_rets = 2;
} else
#endif
{
} else {
*s->gen_opparam_ptr++ = ret;
nb_rets = 1;
}
#endif
} else {
nb_rets = 0;
}
......@@ -749,7 +792,29 @@ void tcg_gen_callN(TCGContext *s, TCGv_ptr func, unsigned int flags,
/* total parameters, needed to go backward in the instruction stream */
*s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3;
#if defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
#if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER)
/* Free all of the parts we allocated above. */
for (i = real_args = 0; i < orig_nargs; ++i) {
int is_64bit = orig_sizemask & (1 << (i+1)*2);
if (is_64bit) {
TCGv_i32 h = MAKE_TCGV_I32(args[real_args++]);
TCGv_i32 l = MAKE_TCGV_I32(args[real_args++]);
tcg_temp_free_i32(h);
tcg_temp_free_i32(l);
} else {
real_args++;
}
}
if (orig_sizemask & 1) {
/* The 32-bit ABI returned two 32-bit pieces. Re-assemble them.
Note that describing these as TCGv_i64 eliminates an unnecessary
zero-extension that tcg_gen_concat_i32_i64 would create. */
tcg_gen_concat32_i64(MAKE_TCGV_I64(ret), retl, reth);
tcg_temp_free_i64(retl);
tcg_temp_free_i64(reth);
}
#elif defined(TCG_TARGET_EXTEND_ARGS) && TCG_TARGET_REG_BITS == 64
for (i = 0; i < nargs; ++i) {
int is_64bit = sizemask & (1 << (i+1)*2);
if (!is_64bit) {
......@@ -2411,6 +2476,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
ts = &s->temps[arg];
reg = tcg_target_call_oarg_regs[i];
assert(s->reg_to_temp[reg] == -1);
if (ts->fixed_reg) {
if (ts->reg != reg) {
tcg_out_mov(s, ts->type, ts->reg, reg);
......
......@@ -66,6 +66,7 @@ typedef uint64_t TCGRegSet;
#if TCG_TARGET_REG_BITS == 32
/* Turn some undef macros into false macros. */
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_div_i64 0
#define TCG_TARGET_HAS_rem_i64 0
#define TCG_TARGET_HAS_div2_i64 0
......
......@@ -82,6 +82,7 @@
#define TCG_TARGET_HAS_mulsh_i32 0
#if TCG_TARGET_REG_BITS == 64
#define TCG_TARGET_HAS_trunc_shr_i32 0
#define TCG_TARGET_HAS_bswap16_i64 1
#define TCG_TARGET_HAS_bswap32_i64 1
#define TCG_TARGET_HAS_bswap64_i64 1
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册