===================================================================
@@ -1653,7 +1653,7 @@ aarch64_split_128bit_move (rtx dst, rtx
machine_mode mode = GET_MODE (dst);
- gcc_assert (mode == TImode || mode == TFmode);
+ gcc_assert (mode == TImode || mode == TFmode || mode == TDmode);
gcc_assert (!(side_effects_p (src) || side_effects_p (dst)));
gcc_assert (mode == GET_MODE (src) || GET_MODE (src) == VOIDmode);
@@ -1673,11 +1673,16 @@ aarch64_split_128bit_move (rtx dst, rtx
emit_insn (gen_aarch64_movtilow_di (dst, src_lo));
emit_insn (gen_aarch64_movtihigh_di (dst, src_hi));
}
- else
+ else if (mode == TFmode)
{
emit_insn (gen_aarch64_movtflow_di (dst, src_lo));
emit_insn (gen_aarch64_movtfhigh_di (dst, src_hi));
}
+ else
+ {
+ emit_insn (gen_aarch64_movtdlow_di (dst, src_lo));
+ emit_insn (gen_aarch64_movtdhigh_di (dst, src_hi));
+ }
return;
}
else if (GP_REGNUM_P (dst_regno) && FP_REGNUM_P (src_regno))
@@ -1690,11 +1695,16 @@ aarch64_split_128bit_move (rtx dst, rtx
emit_insn (gen_aarch64_movdi_tilow (dst_lo, src));
emit_insn (gen_aarch64_movdi_tihigh (dst_hi, src));
}
- else
+ else if (mode == TFmode)
{
emit_insn (gen_aarch64_movdi_tflow (dst_lo, src));
emit_insn (gen_aarch64_movdi_tfhigh (dst_hi, src));
}
+ else if (mode == TDmode)
+ {
+ emit_insn (gen_aarch64_movdi_tdlow (dst_lo, src));
+ emit_insn (gen_aarch64_movdi_tdhigh (dst_hi, src));
+ }
return;
}
}
@@ -4420,10 +4430,11 @@ aarch64_classify_address (struct aarch64
rtx op0, op1;
/* On BE, we use load/store pair for all large int mode load/stores.
- TI/TFmode may also use a load/store pair. */
+ TI/TF/TDmode may also use a load/store pair. */
bool load_store_pair_p = (outer_code == PARALLEL
|| mode == TImode
|| mode == TFmode
+ || mode == TDmode
|| (BYTES_BIG_ENDIAN
&& aarch64_vect_struct_mode_p (mode)));
@@ -4473,7 +4484,7 @@ aarch64_classify_address (struct aarch64
info->base = op0;
info->offset = op1;
- /* TImode and TFmode values are allowed in both pairs of X
+ /* TImode and TFmode and TDmode values are allowed in both pairs of X
registers and individual Q registers. The available
address modes are:
X,X: 7-bit signed scaled offset
@@ -4482,7 +4493,7 @@ aarch64_classify_address (struct aarch64
When performing the check for pairs of X registers i.e. LDP/STP
pass down DImode since that is the natural size of the LDP/STP
instruction memory accesses. */
- if (mode == TImode || mode == TFmode)
+ if (mode == TImode || mode == TFmode || mode == TDmode)
return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
&& (offset_9bit_signed_unscaled_p (mode, offset)
|| offset_12bit_unsigned_scaled_p (mode, offset)));
@@ -4558,14 +4569,14 @@ aarch64_classify_address (struct aarch64
info->offset = XEXP (XEXP (x, 1), 1);
offset = INTVAL (info->offset);
- /* TImode and TFmode values are allowed in both pairs of X
+ /* TImode and TFmode and TDmode values are allowed in both pairs of X
registers and individual Q registers. The available
address modes are:
X,X: 7-bit signed scaled offset
Q: 9-bit signed offset
We conservatively require an offset representable in either mode.
*/
- if (mode == TImode || mode == TFmode)
+ if (mode == TImode || mode == TFmode || mode == TDmode)
return (aarch64_offset_7bit_signed_scaled_p (mode, offset)
&& offset_9bit_signed_unscaled_p (mode, offset));
@@ -4714,7 +4725,7 @@ aarch64_legitimize_address_displacement
HOST_WIDE_INT offset = INTVAL (*disp);
HOST_WIDE_INT base = offset & ~(GET_MODE_SIZE (mode) < 4 ? 0xfff : 0x3ffc);
- if (mode == TImode || mode == TFmode
+ if (mode == TImode || mode == TFmode || mode == TDmode
|| (offset & (GET_MODE_SIZE (mode) - 1)) != 0)
base = (offset + 0x100) & ~0x1ff;
@@ -5649,7 +5660,7 @@ aarch64_legitimize_address (rtx x, rtx /
/* Small negative offsets are supported. */
else if (IN_RANGE (offset, -256, 0))
base_offset = 0;
- else if (mode == TImode || mode == TFmode)
+ else if (mode == TImode || mode == TFmode || mode == TDmode)
base_offset = (offset + 0x100) & ~0x1ff;
/* Use 12-bit offset by access size. */
else
@@ -5681,6 +5692,15 @@ aarch64_constant_pool_reload_icode (mach
case TFmode:
return CODE_FOR_aarch64_reload_movcptfdi;
+ case SDmode:
+ return CODE_FOR_aarch64_reload_movcpsddi;
+
+ case DDmode:
+ return CODE_FOR_aarch64_reload_movcpdddi;
+
+ case TDmode:
+ return CODE_FOR_aarch64_reload_movcptddi;
+
case V8QImode:
return CODE_FOR_aarch64_reload_movcpv8qidi;
@@ -5731,25 +5751,27 @@ aarch64_secondary_reload (bool in_p ATTR
/* Without the TARGET_SIMD instructions we cannot move a Q register
to a Q register directly. We need a scratch. */
- if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x)
+ if (REG_P (x) && (mode == TFmode || mode == TDmode || mode == TImode) && mode == GET_MODE (x)
&& FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD
&& reg_class_subset_p (rclass, FP_REGS))
{
if (mode == TFmode)
sri->icode = CODE_FOR_aarch64_reload_movtf;
+ else if (mode == TDmode)
+ sri->icode = CODE_FOR_aarch64_reload_movtd;
else if (mode == TImode)
sri->icode = CODE_FOR_aarch64_reload_movti;
return NO_REGS;
}
- /* A TFmode or TImode memory access should be handled via an FP_REGS
+ /* A TFmode or TImode or TDmode memory access should be handled via an FP_REGS
because AArch64 has richer addressing modes for LDR/STR instructions
than LDP/STP instructions. */
if (TARGET_FLOAT && rclass == GENERAL_REGS
&& GET_MODE_SIZE (mode) == 16 && MEM_P (x))
return FP_REGS;
- if (rclass == FP_REGS && (mode == TImode || mode == TFmode) && CONSTANT_P(x))
+ if (rclass == FP_REGS && (mode == TImode || mode == TFmode || mode == TDmode) && CONSTANT_P(x))
return GENERAL_REGS;
return NO_REGS;
@@ -10215,6 +10237,10 @@ aarch64_legitimate_pic_operand_p (rtx x)
static bool
aarch64_valid_floating_const (machine_mode mode, rtx x)
{
+ /* FIXME: Handle decimal floating point constants. */
+ if (GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT)
+ return false;
+
if (!CONST_DOUBLE_P (x))
return false;
@@ -10636,6 +10662,18 @@ aarch64_gimplify_va_arg_expr (tree valis
field_t = long_double_type_node;
field_ptr_t = long_double_ptr_type_node;
break;
+ case SDmode:
+ field_t = dfloat32_type_node;
+ field_ptr_t = dfloat32_ptr_type_node;
+ break;
+ case DDmode:
+ field_t = dfloat64_type_node;
+ field_ptr_t = dfloat64_ptr_type_node;
+ break;
+ case TDmode:
+ field_t = dfloat128_type_node;
+ field_ptr_t = dfloat128_ptr_type_node;
+ break;
case HFmode:
field_t = aarch64_fp16_type_node;
field_ptr_t = aarch64_fp16_ptr_type_node;
@@ -10802,7 +10840,9 @@ aapcs_vfp_sub_candidate (const_tree type
case REAL_TYPE:
mode = TYPE_MODE (type);
if (mode != DFmode && mode != SFmode
- && mode != TFmode && mode != HFmode)
+ && mode != TFmode && mode != HFmode
+ && mode != DDmode && mode != SDmode
+ && mode != TDmode)
return -1;
if (*modep == VOIDmode)
@@ -11030,7 +11070,9 @@ aarch64_vfp_is_call_or_return_candidate
if (is_ha != NULL) *is_ha = false;
- if ((!composite_p && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ if ((!composite_p
+ && (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT))
|| aarch64_short_vector_p (type, mode))
{
*count = 1;
@@ -15028,6 +15070,9 @@ aarch64_libgcc_floating_mode_supported_p
static bool
aarch64_scalar_mode_supported_p (machine_mode mode)
{
+ if (DECIMAL_FLOAT_MODE_P (mode))
+ return default_decimal_float_supported_p ();
+
return (mode == HFmode
? true
: default_scalar_mode_supported_p (mode));
===================================================================
@@ -1081,11 +1081,11 @@ (define_insn "*movhf_aarch64"
(set_attr "simd" "yes,yes,yes,yes,*,*,*,*,*")]
)
-(define_insn "*movsf_aarch64"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
- (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
- "TARGET_FLOAT && (register_operand (operands[0], SFmode)
- || aarch64_reg_or_fp_zero (operands[1], SFmode))"
+(define_insn "*mov<mode>_aarch64"
+ [(set (match_operand:SFD 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
+ (match_operand:SFD 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
+ "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+ || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
"@
movi\\t%0.2s, #0
fmov\\t%s0, %w1
@@ -1102,11 +1102,11 @@ (define_insn "*movsf_aarch64"
(set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
)
-(define_insn "*movdf_aarch64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
- (match_operand:DF 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
- "TARGET_FLOAT && (register_operand (operands[0], DFmode)
- || aarch64_reg_or_fp_zero (operands[1], DFmode))"
+(define_insn "*mov<mode>_aarch64"
+ [(set (match_operand:DFD 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w,m,r,m ,r")
+ (match_operand:DFD 1 "general_operand" "Y ,?rY, w,w,Ufc,m,w,m,rY,r"))]
+ "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+ || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
"@
movi\\t%d0, #0
fmov\\t%d0, %x1
@@ -1123,13 +1123,13 @@ (define_insn "*movdf_aarch64"
(set_attr "simd" "yes,*,*,*,*,*,*,*,*,*")]
)
-(define_insn "*movtf_aarch64"
- [(set (match_operand:TF 0
+(define_insn "*mov<mode>_aarch64"
+ [(set (match_operand:TFD 0
"nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m")
- (match_operand:TF 1
+ (match_operand:TFD 1
"general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))]
- "TARGET_FLOAT && (register_operand (operands[0], TFmode)
- || aarch64_reg_or_fp_zero (operands[1], TFmode))"
+ "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+ || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
"@
mov\\t%0.16b, %1.16b
#
@@ -1149,8 +1149,8 @@ (define_insn "*movtf_aarch64"
)
(define_split
- [(set (match_operand:TF 0 "register_operand" "")
- (match_operand:TF 1 "aarch64_reg_or_imm" ""))]
+ [(set (match_operand:TFD 0 "register_operand" "")
+ (match_operand:TFD 1 "aarch64_reg_or_imm" ""))]
"reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
[(const_int 0)]
{
===================================================================
@@ -44,14 +44,23 @@ (define_mode_iterator GPF [SF DF])
;; Iterator for all scalar floating point modes (HF, SF, DF)
(define_mode_iterator GPF_F16 [(HF "AARCH64_ISA_F16") SF DF])
-;; Iterator for all scalar floating point modes (HF, SF, DF and TF)
-(define_mode_iterator GPF_TF_F16 [HF SF DF TF])
+;; Iterator for all scalar floating point modes (HF, SF, DF and TF [SD, DD, and TD])
+(define_mode_iterator GPF_TF_F16 [HF SF DF TF SD DD TD])
+
+;; Iterator for scalar 32bit fp modes (SF, SD)
+(define_mode_iterator SFD [SD SF])
+
+;; Iterator for scalar 64bit fp modes (DF, DD)
+(define_mode_iterator DFD [DD DF])
+
+;; Iterator for scalar 128bit fp modes (TF, TD)
+(define_mode_iterator TFD [TD TF])
;; Double vector modes.
(define_mode_iterator VDF [V2SF V4HF])
-;; Iterator for all scalar floating point modes (SF, DF and TF)
-(define_mode_iterator GPF_TF [SF DF TF])
+;; Iterator for all scalar floating point modes (SF, DF and TF [SD, DD, and TD])
+(define_mode_iterator GPF_TF [SF DF TF SD DD TD])
;; Integer vector modes.
(define_mode_iterator VDQ_I [V8QI V16QI V4HI V8HI V2SI V4SI V2DI])
@@ -224,7 +233,7 @@ (define_mode_iterator VB [V8QI V16QI])
;; 2 and 4 lane SI modes.
(define_mode_iterator VS [V2SI V4SI])
-(define_mode_iterator TX [TI TF])
+(define_mode_iterator TX [TI TF TD])
;; Opaque structure modes.
(define_mode_iterator VSTRUCT [OI CI XI])
===================================================================
@@ -14,19 +14,19 @@ _Decimal128 f = -678901.234e-6dl;
/* The first value is DPD, the second is BID. The order differs depending
on whether the target is big-endian or little-endian. */
-/* { dg-final { scan-assembler ".long\t(572653859|822183807)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(572653859|822183807)\n" } } */
-/* { dg-final { scan-assembler ".long\t(-1572863965|-1308622825)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(-1572863965|-1308622825)\n" } } */
-/* { dg-final { scan-assembler ".long\t(52|34)\n" } } */
-/* { dg-final { scan-assembler ".long\t(572784640|824180736)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(52|34)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(572784640|824180736)\n" } } */
-/* { dg-final { scan-assembler ".long\t(4736|4500)\n" } } */
-/* { dg-final { scan-assembler ".long\t(-1574174720|-1319108608)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(4736|4500)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(-1574174720|-1319108608)\n" } } */
-/* { dg-final { scan-assembler ".long\t(-1975952433|957645077)\n" } } */
-/* { dg-final { scan-assembler ".long\t(190215|132222)\n" } } */
-/* { dg-final { scan-assembler ".long\t(574193664|835452928)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(-1975952433|957645077)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(190215|132222)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(574193664|835452928)\n" } } */
-/* { dg-final { scan-assembler ".long\t(931280180|678901234)\n" } } */
-/* { dg-final { scan-assembler ".long\t(-1576681472|-1339162624)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(931280180|678901234)\n" } } */
+/* { dg-final { scan-assembler ".(word|long)\t(-1576681472|-1339162624)\n" } } */