bool aarch64_emit_approx_sqrt (rtx, rtx, bool);
tree aarch64_vector_load_decl (tree);
void aarch64_expand_call (rtx, rtx, rtx, bool);
+bool aarch64_expand_cpymem_mops (rtx *, bool);
bool aarch64_expand_cpymem (rtx *);
bool aarch64_expand_setmem (rtx *);
bool aarch64_float_const_zero_rtx_p (rtx);
*dst = aarch64_progress_pointer (*dst);
}
-/* Expand a cpymem using the MOPS extension. OPERANDS are taken
- from the cpymem pattern. Return true iff we succeeded. */
-static bool
-aarch64_expand_cpymem_mops (rtx *operands)
+/* Expand a cpymem/movmem using the MOPS extension. OPERANDS are taken
+ from the cpymem/movmem pattern. IS_MEMMOVE is true if this is a memmove
+ rather than memcpy. Return true iff we succeeded. */
+bool
+aarch64_expand_cpymem_mops (rtx *operands, bool is_memmove = false)
{
if (!TARGET_MOPS)
return false;
rtx dst_mem = replace_equiv_address (operands[0], dst_addr);
rtx src_mem = replace_equiv_address (operands[1], src_addr);
rtx sz_reg = copy_to_mode_reg (DImode, operands[2]);
- emit_insn (gen_aarch64_cpymemdi (dst_mem, src_mem, sz_reg));
-
+ if (is_memmove)
+ emit_insn (gen_aarch64_movmemdi (dst_mem, src_mem, sz_reg));
+ else
+ emit_insn (gen_aarch64_cpymemdi (dst_mem, src_mem, sz_reg));
return true;
}
}
)
-(define_insn "aarch64_movmemdi"
+(define_expand "aarch64_movmemdi"
+ [(parallel
+ [(set (match_operand 2) (const_int 0))
+ (clobber (match_dup 3))
+ (clobber (match_dup 4))
+ (clobber (reg:CC CC_REGNUM))
+ (set (match_operand 0)
+ (unspec:BLK [(match_operand 1) (match_dup 2)] UNSPEC_MOVMEM))])]
+ "TARGET_MOPS"
+ {
+ operands[3] = XEXP (operands[0], 0);
+ operands[4] = XEXP (operands[1], 0);
+ }
+)
+
+(define_insn "*aarch64_movmemdi"
[(parallel [
(set (match_operand:DI 2 "register_operand" "+&r") (const_int 0))
(clobber (match_operand:DI 0 "register_operand" "+&r"))
&& INTVAL (sz_reg) < aarch64_mops_memmove_size_threshold)
FAIL;
- rtx addr_dst = XEXP (operands[0], 0);
- rtx addr_src = XEXP (operands[1], 0);
-
- if (!REG_P (sz_reg))
- sz_reg = force_reg (DImode, sz_reg);
- if (!REG_P (addr_dst))
- addr_dst = force_reg (DImode, addr_dst);
- if (!REG_P (addr_src))
- addr_src = force_reg (DImode, addr_src);
- emit_insn (gen_aarch64_movmemdi (addr_dst, addr_src, sz_reg));
- DONE;
+ if (aarch64_expand_cpymem_mops (operands, true))
+ DONE;
+ FAIL;
}
)
*res = z;
}
+/*
+** move1:
+** mov (x[0-9]+), x0
+** cpyp \[\1\]!, \[x1\]!, x2!
+** cpym \[\1\]!, \[x1\]!, x2!
+** cpye \[\1\]!, \[x1\]!, x2!
+** str x0, \[x3\]
+** ret
+*/
+void
+move1 (int *x, int *y, long z, int **res)
+{
+ __builtin_memmove (x, y, z);
+ *res = x;
+}
+
+/*
+** move2:
+** mov (x[0-9]+), x1
+** cpyp \[x0\]!, \[\1\]!, x2!
+** cpym \[x0\]!, \[\1\]!, x2!
+** cpye \[x0\]!, \[\1\]!, x2!
+** str x1, \[x3\]
+** ret
+*/
+void
+move2 (int *x, int *y, long z, int **res)
+{
+ __builtin_memmove (x, y, z);
+ *res = y;
+}
+
+/*
+** move3:
+** mov (x[0-9]+), x2
+** cpyp \[x0\]!, \[x1\]!, \1!
+** cpym \[x0\]!, \[x1\]!, \1!
+** cpye \[x0\]!, \[x1\]!, \1!
+** str x2, \[x3\]
+** ret
+*/
+void
+move3 (int *x, int *y, long z, long *res)
+{
+ __builtin_memmove (x, y, z);
+ *res = z;
+}
+
/*
** set1:
** mov (x[0-9]+), x0