summaryrefslogtreecommitdiff
path: root/gcc/config/arm/neon.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/neon.md')
-rw-r--r--gcc/config/arm/neon.md67
1 files changed, 61 insertions, 6 deletions
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 0c312e7c336..8d10c1e5b42 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -735,7 +735,10 @@
(match_operand:SI 2 "immediate_operand" "i")))]
"TARGET_NEON"
{
- operands[2] = GEN_INT (ffs ((int) INTVAL (operands[2]) - 1));
+ int elt = ffs ((int) INTVAL (operands[2]) - 1);
+ if (BYTES_BIG_ENDIAN)
+ elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
+ operands[2] = GEN_INT (elt);
return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1";
}
@@ -757,6 +760,9 @@
int hi = (elem / half_elts) * 2;
int regno = REGNO (operands[0]);
+ if (BYTES_BIG_ENDIAN)
+ elt = half_elts - 1 - elt;
+
operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi);
operands[2] = GEN_INT (elt);
@@ -804,7 +810,15 @@
(match_operand:VD 1 "s_register_operand" "w")
(parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
"TARGET_NEON"
- "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]"
+{
+ if (BYTES_BIG_ENDIAN)
+ {
+ int elt = INTVAL (operands[2]);
+ elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
+ operands[2] = GEN_INT (elt);
+ }
+ return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]";
+}
[(set_attr "predicable" "yes")
(set_attr "neon_type" "neon_bp_simple")]
)
@@ -821,6 +835,9 @@
int hi = (INTVAL (operands[2]) / half_elts) * 2;
int regno = REGNO (operands[1]);
+ if (BYTES_BIG_ENDIAN)
+ elt = half_elts - 1 - elt;
+
operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi);
operands[2] = GEN_INT (elt);
@@ -2413,7 +2430,15 @@
(match_operand:VD 1 "s_register_operand" "w")
(parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
"TARGET_NEON"
- "vmov%?.s<V_sz_elem>\t%0, %P1[%c2]"
+{
+ if (BYTES_BIG_ENDIAN)
+ {
+ int elt = INTVAL (operands[2]);
+ elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
+ operands[2] = GEN_INT (elt);
+ }
+ return "vmov%?.s<V_sz_elem>\t%0, %P1[%c2]";
+}
[(set_attr "predicable" "yes")
(set_attr "neon_type" "neon_bp_simple")]
)
@@ -2425,7 +2450,15 @@
(match_operand:VD 1 "s_register_operand" "w")
(parallel [(match_operand:SI 2 "immediate_operand" "i")]))))]
"TARGET_NEON"
- "vmov%?.u<V_sz_elem>\t%0, %P1[%c2]"
+{
+ if (BYTES_BIG_ENDIAN)
+ {
+ int elt = INTVAL (operands[2]);
+ elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt;
+ operands[2] = GEN_INT (elt);
+ }
+ return "vmov%?.u<V_sz_elem>\t%0, %P1[%c2]";
+}
[(set_attr "predicable" "yes")
(set_attr "neon_type" "neon_bp_simple")]
)
@@ -2442,10 +2475,14 @@
int regno = REGNO (operands[1]);
unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
unsigned int elt = INTVAL (operands[2]);
+ unsigned int elt_adj = elt % halfelts;
+
+ if (BYTES_BIG_ENDIAN)
+ elt_adj = halfelts - 1 - elt_adj;
ops[0] = operands[0];
ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
- ops[2] = GEN_INT (elt % halfelts);
+ ops[2] = GEN_INT (elt_adj);
output_asm_insn ("vmov%?.s<V_sz_elem>\t%0, %P1[%c2]", ops);
return "";
@@ -2466,10 +2503,14 @@
int regno = REGNO (operands[1]);
unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2;
unsigned int elt = INTVAL (operands[2]);
+ unsigned int elt_adj = elt % halfelts;
+
+ if (BYTES_BIG_ENDIAN)
+ elt_adj = halfelts - 1 - elt_adj;
ops[0] = operands[0];
ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts));
- ops[2] = GEN_INT (elt % halfelts);
+ ops[2] = GEN_INT (elt_adj);
output_asm_insn ("vmov%?.u<V_sz_elem>\t%0, %P1[%c2]", ops);
return "";
@@ -2490,6 +2531,20 @@
neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode));
+ if (BYTES_BIG_ENDIAN)
+ {
+ /* The intrinsics are defined in terms of a model where the
+ element ordering in memory is vldm order, whereas the generic
+ RTL is defined in terms of a model where the element ordering
+ in memory is array order. Convert the lane number to conform
+ to this model. */
+ unsigned int elt = INTVAL (operands[2]);
+ unsigned int reg_nelts
+ = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode));
+ elt ^= reg_nelts - 1;
+ operands[2] = GEN_INT (elt);
+ }
+
if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) == 32)
insn = gen_vec_extract<mode> (operands[0], operands[1], operands[2]);
else