@@ -534,20 +534,65 @@ static inline void tcg_out_movr_sp(TCGContext *s, bool ext,
}
static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
- tcg_target_long value)
+ tcg_target_long svalue)
{
- AArch64Insn insn = INSN_MOVZ;
+ tcg_target_ulong value = svalue;
+ AArch64Insn insn;
+ bool ext = true;
+ int wantinv, shift;
if (type == TCG_TYPE_I32) {
- value = (uint32_t)value;
+ value = (uint32_t)svalue;
+ svalue = (int32_t)svalue;
+ ext = false;
+ } else if ((value & ~0xffffffffull) == 0) {
+ svalue = (int32_t)svalue;
+ ext = false;
+ }
+
+ /* Check small positive values. */
+ if ((value & ~0xffffull) == 0) {
+ tcg_fmt_Rd_uimm_s(s, INSN_MOVZ, 0, rd, value, 0);
+ return;
+ }
+ /* Check small negative values. */
+ if ((~svalue & 0xffffull) == 0) {
+ tcg_fmt_Rd_uimm_s(s, INSN_MOVN, ext, rd, ~svalue, 0);
+ return;
}
+ /* Check for bitfield immediates. */
+ if (is_limm(svalue)) {
+ tcg_fmt_Rdn_limm(s, INSN_ORRI, ext, rd, TCG_REG_XZR, svalue);
+ return;
+ }
+
+ /* Would it take fewer insns to begin with MOVN? */
+ insn = INSN_MOVZ;
+ wantinv = 0;
+ wantinv += (value & 0x000000000000ffffull) == 0;
+ wantinv += (value & 0x00000000ffff0000ull) == 0;
+ wantinv += (value & 0x0000ffff00000000ull) == 0;
+ wantinv += (value & 0xffff000000000000ull) == 0;
+ wantinv = -wantinv;
+ wantinv += (~value & 0x000000000000ffffull) == 0;
+ wantinv += (~value & 0x00000000ffff0000ull) == 0;
+ wantinv += (~value & 0x0000ffff00000000ull) == 0;
+ wantinv += (~value & 0xffff000000000000ull) == 0;
+ if (wantinv > 0) {
+ insn = INSN_MOVN;
+ value = ~value;
+ }
+
+ shift = ctz64(value) & (63 & -16);
+ tcg_fmt_Rd_uimm_s(s, insn, ext, rd, value >> shift, shift);
+ value &= ~(0xffffUL << shift);
- do {
- unsigned shift = ctz64(value) & (63 & -16);
- tcg_fmt_Rd_uimm_s(s, insn, shift >= 32, rd, value >> shift, shift);
+ while (value) {
+ shift = ctz64(value) & (63 & -16);
+ tcg_fmt_Rd_uimm_s(s, INSN_MOVK, ext, rd,
+ (value ^ -(wantinv > 0)) >> shift, shift);
value &= ~(0xffffUL << shift);
- insn = INSN_MOVK;
- } while (value);
+ }
}
static inline void tcg_out_ldst_r(TCGContext *s,
Handle small positive and negative numbers early. Check for logical immediates. Check if using MOVN for the first set helps. Signed-off-by: Richard Henderson <rth@twiddle.net> --- tcg/aarch64/tcg-target.c | 61 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 8 deletions(-)