tcg-ppc64: Cleanup tcg_out_movi

The test for using movi32 was sub-optimal for TCG_TYPE_I32, comparing
a signed 32-bit quantity against an unsigned 32-bit quantity.

When possible, use addi+oris for 32-bit unsigned constants.  Otherwise,
standardize on addi+oris+ori instead of addis+ori+rldicl.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2013-01-31 15:52:49 -08:00
parent 752c1fdb6d
commit 421233a146

View File

@ -480,32 +480,25 @@ static void tcg_out_movi32(TCGContext *s, TCGReg ret, int32_t arg)
}
}
static void tcg_out_movi (TCGContext *s, TCGType type,
TCGReg ret, tcg_target_long arg)
static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
tcg_target_long arg)
{
int32_t arg32 = arg;
arg = type == TCG_TYPE_I32 ? arg & 0xffffffff : arg;
if (arg == arg32) {
tcg_out_movi32 (s, ret, arg32);
}
else {
if ((uint64_t) arg >> 32) {
uint16_t h16 = arg >> 16;
uint16_t l16 = arg;
tcg_out_movi32(s, ret, arg >> 32);
if (type == TCG_TYPE_I32 || arg == (int32_t)arg) {
tcg_out_movi32(s, ret, arg);
} else if (arg == (uint32_t)arg && !(arg & 0x8000)) {
tcg_out32(s, ADDI | TAI(ret, 0, arg));
tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
} else {
int32_t high = arg >> 32;
tcg_out_movi32(s, ret, high);
if (high) {
tcg_out_shli64(s, ret, ret, 32);
if (h16) {
tcg_out32(s, ORIS | SAI(ret, ret, h16));
}
if (l16) {
tcg_out32(s, ORI | SAI(ret, ret, l16));
}
} else {
tcg_out_movi32 (s, ret, arg32);
if (arg32 < 0)
tcg_out_ext32u(s, ret, ret);
}
if (arg & 0xffff0000) {
tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
}
if (arg & 0xffff) {
tcg_out32(s, ORI | SAI(ret, ret, arg));
}
}
}