summaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 64599981961..5e098461ec7 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -30904,10 +30904,18 @@ arm_coproc_builtin_available (enum unspecv builtin)
switch (builtin)
{
case VUNSPEC_CDP:
+ case VUNSPEC_LDC:
+ case VUNSPEC_LDCL:
+ case VUNSPEC_STC:
+ case VUNSPEC_STCL:
if (arm_arch4)
return true;
break;
case VUNSPEC_CDP2:
+ case VUNSPEC_LDC2:
+ case VUNSPEC_LDC2L:
+ case VUNSPEC_STC2:
+ case VUNSPEC_STC2L:
/* Only present in ARMv5*, ARMv6 (but not ARMv6-M), ARMv7* and
ARMv8-{A,M}. */
if (arm_arch5)
@@ -30918,4 +30926,55 @@ arm_coproc_builtin_available (enum unspecv builtin)
}
return false;
}
+
+/* This function returns true if OP is a valid memory operand for the ldc and
+ stc coprocessor instructions and false otherwise. */
+
+bool
+arm_coproc_ldc_stc_legitimate_address (rtx op)
+{
+ HOST_WIDE_INT range;
+ /* Has to be a memory operand. */
+ if (!MEM_P (op))
+ return false;
+
+ op = XEXP (op, 0);
+
+ /* We accept registers. */
+ if (REG_P (op))
+ return true;
+
+ switch GET_CODE (op)
+ {
+ case PLUS:
+ {
+ /* Or registers with an offset. */
+ if (!REG_P (XEXP (op, 0)))
+ return false;
+
+ op = XEXP (op, 1);
+
+ /* The offset must be an immediate though. */
+ if (!CONST_INT_P (op))
+ return false;
+
+ range = INTVAL (op);
+
+ /* Within the range of [-1020,1020]. */
+ if (!IN_RANGE (range, -1020, 1020))
+ return false;
+
+ /* And a multiple of 4. */
+ return (range % 4) == 0;
+ }
+ case PRE_INC:
+ case POST_INC:
+ case PRE_DEC:
+ case POST_DEC:
+ return REG_P (XEXP (op, 0));
+ default:
+ gcc_unreachable ();
+ }
+ return false;
+}
#include "gt-arm.h"