diff options
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r-- | gcc/config/arm/arm.c | 59 |
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" |