/* Predicates for `match_operand' and `match_operator'. */
/* Return TRUE if OP is a valid coprocessor memory address pattern.
- WB is true if full writeback address modes are allowed and is false
+ WB level is 2 if full writeback address modes are allowed, 1
if limited writeback address modes (POST_INC and PRE_DEC) are
- allowed. */
+ allowed and 0 if no writeback at all is supported. */
int
-arm_coproc_mem_operand (rtx op, bool wb)
+arm_coproc_mem_operand_wb (rtx op, int wb_level)
{
+ gcc_assert (wb_level == 0 || wb_level == 1 || wb_level == 2);
rtx ind;
/* Reject eliminable registers. */
/* Autoincremment addressing modes. POST_INC and PRE_DEC are
acceptable in any case (subject to verification by
- arm_address_register_rtx_p). We need WB to be true to accept
+ arm_address_register_rtx_p). We need full writeback to accept
+ PRE_INC and POST_DEC, and at least restricted writeback for
PRE_INC and POST_DEC. */
- if (GET_CODE (ind) == POST_INC
- || GET_CODE (ind) == PRE_DEC
- || (wb
- && (GET_CODE (ind) == PRE_INC
- || GET_CODE (ind) == POST_DEC)))
+ if (wb_level > 0
+ && (GET_CODE (ind) == POST_INC
+ || GET_CODE (ind) == PRE_DEC
+ || (wb_level > 1
+ && (GET_CODE (ind) == PRE_INC
+ || GET_CODE (ind) == POST_DEC))))
return arm_address_register_rtx_p (XEXP (ind, 0), 0);
- if (wb
+ if (wb_level > 1
&& (GET_CODE (ind) == POST_MODIFY || GET_CODE (ind) == PRE_MODIFY)
&& arm_address_register_rtx_p (XEXP (ind, 0), 0)
&& GET_CODE (XEXP (ind, 1)) == PLUS
return FALSE;
}
+/* Return TRUE if OP is a valid coprocessor memory address pattern.
+ WB is true if full writeback address modes are allowed and is false
+ if limited writeback address modes (POST_INC and PRE_DEC) are
+ allowed. */
+
+int arm_coproc_mem_operand (rtx op, bool wb)
+{
+ return arm_coproc_mem_operand_wb (op, wb ? 2 : 1);
+}
+
+/* Return TRUE if OP is a valid coprocessor memory address pattern in a
+ context in which no writeback address modes are allowed. */
+
+int
+arm_coproc_mem_operand_no_writeback (rtx op)
+{
+ return arm_coproc_mem_operand_wb (op, 0);
+}
+
/* This function returns TRUE on matching mode and op.
1. For given modes, check for [Rn], return TRUE for Rn <= LO_REGS.
2. For other modes, check for [Rn], return TRUE for Rn < R15 (expect R13). */
/* Globally reserved letters: acln
Puncutation letters currently used: @_|?().!#
Lower case letters currently used: bcdefhimpqtvwxyz
- Upper case letters currently used: ABCDFGHJKLMNOPQRSTU
+ Upper case letters currently used: ABCDEFGHIJKLMNOPQRSTU
Letters previously used, but now deprecated/obsolete: sVWXYZ.
Note that the global reservation for 'c' is only for CONSTANT_ADDRESS_P.
}
return;
- /* To print the memory operand with "Ux" constraint. Based on the rtx_code
- the memory operands output looks like following.
+ /* To print the memory operand with "Ux" or "Uj" constraint. Based on the
+ rtx_code the memory operands output looks like following.
1. [Rn], #+/-<imm>
2. [Rn, #+/-<imm>]!
- 3. [Rn]. */
+ 3. [Rn, #+/-<imm>]
+ 4. [Rn]. */
case 'E':
{
rtx addr;
asm_fprintf (stream, ", #%wd]!",INTVAL (postinc_reg));
}
}
+ else if (code == PLUS)
+ {
+ rtx base = XEXP (addr, 0);
+ rtx index = XEXP (addr, 1);
+
+ gcc_assert (REG_P (base) && CONST_INT_P (index));
+
+ HOST_WIDE_INT offset = INTVAL (index);
+ asm_fprintf (stream, "[%r, #%wd]", REGNO (base), offset);
+ }
else
{
gcc_assert (REG_P (addr));
struct gcc_target targetm = TARGET_INITIALIZER;
+bool
+arm_mve_mode_and_operands_type_check (machine_mode mode, rtx op0, rtx op1)
+{
+ if (!(TARGET_HAVE_MVE || TARGET_HAVE_MVE_FLOAT))
+ return true;
+ else if (mode == E_BFmode)
+ return false;
+ else if ((s_register_operand (op0, mode) && MEM_P (op1))
+ || (s_register_operand (op1, mode) && MEM_P (op0)))
+ return false;
+ return true;
+}
+
#include "gt-arm.h"
(set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")]
)
+(define_insn "*mov_load_vfp_hf16"
+ [(set (match_operand:HF 0 "s_register_operand" "=t")
+ (match_operand:HF 1 "memory_operand" "Uj"))]
+ "TARGET_HAVE_MVE_FLOAT"
+ "vldr.16\\t%0, %E1"
+)
+
+(define_insn "*mov_store_vfp_hf16"
+ [(set (match_operand:HF 0 "memory_operand" "=Uj")
+ (match_operand:HF 1 "s_register_operand" "t"))]
+ "TARGET_HAVE_MVE_FLOAT"
+ "vstr.16\\t%1, %E0"
+)
+
;; HFmode and BFmode moves
(define_insn "*mov<mode>_vfp_<mode>16"
" m,r,t,r,r,t,Dv,Um,t, F"))]
"TARGET_32BIT
&& TARGET_VFP_FP16INST
+ && arm_mve_mode_and_operands_type_check (<MODE>mode, operands[0],
+ operands[1])
&& (s_register_operand (operands[0], <MODE>mode)
|| s_register_operand (operands[1], <MODE>mode))"
{
case 6: /* S register from immediate. */
return \"vmov.f16\\t%0, %1\t%@ __<fporbf>\";
case 7: /* S register from memory. */
- if (TARGET_HAVE_MVE)
- return \"vldr.16\\t%0, %A1\";
- else
- return \"vld1.16\\t{%z0}, %A1\";
+ return \"vld1.16\\t{%z0}, %A1\";
case 8: /* Memory from S register. */
- if (TARGET_HAVE_MVE)
- return \"vstr.16\\t%1, %A0\";
- else
- return \"vst1.16\\t{%z1}, %A0\";
+ return \"vst1.16\\t{%z1}, %A0\";
case 9: /* ARM register from constant. */
{
long bits;