[1/2,aarch64] Rework fpcr fpsr getter/setter builtins

Message ID gkrwo7s8rli.fsf@arm.com
State New
Headers show
Series
  • [1/2,aarch64] Rework fpcr fpsr getter/setter builtins
Related show

Commit Message

Andrea Corallo March 10, 2020, 9:52 a.m.
Hi all,

I'd like to submit this patch introducing the following 64bit builtins
variants as FPCR and FPSR registers getter/setter:

unsigned long long __builtin_aarch64_get_fpcr64 ()
void __builtin_aarch64_set_fpcr64 (unsigned long long)
unsigned long long __builtin_aarch64_get_fpsr64 ()
void __builtin_aarch64_set_fpsr64 (unsigned long long)

Regards
  Andrea

gcc/ChangeLog:

2020-??-??  Andrea Corallo  <andrea.corallo@arm.com>

	* config/aarch64/aarch64-builtins.c (aarch64_builtins): Add enums
	for 64bits fpsr/fpcr getter setters builtin variants.
	(aarch64_init_fpsr_fpcr_builtins): New function.
	(aarch64_expand_fcr_fpsr_builtin): New function.
	(aarch64_general_expand_builtin): Modify to make use of the later.
	* config/aarch64/aarch64.md (UNSPECV_GET_FPCR64)
	(UNSPECV_SET_FPCR64, UNSPECV_GET_FPSR64, UNSPECV_SET_FPSR64): Add
	4 new unpecv.
	(set_fpcr64, get_fpcr64,set_fpsr64, get_fpsr64): New patterns.
	* doc/extend.texi (__builtin_aarch64_get_fpcr64)
	(__builtin_aarch64_set_fpcr64, __builtin_aarch64_get_fpsr64)
	(__builtin_aarch64_set_fpsr64): Add into AArch64 Built-in
	Functions.

gcc/testsuite/ChangeLog:

2020-??-??  Andrea Corallo  <andrea.corallo@arm.com>

	* gcc.target/aarch64/get_fpcr64.c: New test.
	* gcc.target/aarch64/set_fpcr64.c: New test.
	* gcc.target/aarch64/get_fpsr64.c: New test.
	* gcc.target/aarch64/set_fpsr64.c: New test.

Comments

Andrea Corallo May 28, 2020, 10:19 a.m. | #1
Andrea Corallo <andrea.corallo@arm.com> writes:

> Hi all,

>

> I'd like to submit this patch introducing the following 64bit builtins

> variants as FPCR and FPSR registers getter/setter:

>

> unsigned long long __builtin_aarch64_get_fpcr64 ()

> void __builtin_aarch64_set_fpcr64 (unsigned long long)

> unsigned long long __builtin_aarch64_get_fpsr64 ()

> void __builtin_aarch64_set_fpsr64 (unsigned long long)

>

> Regards

>   Andrea

>

> gcc/ChangeLog:

>

> 2020-??-??  Andrea Corallo  <andrea.corallo@arm.com>

>

> 	* config/aarch64/aarch64-builtins.c (aarch64_builtins): Add enums

> 	for 64bits fpsr/fpcr getter setters builtin variants.

> 	(aarch64_init_fpsr_fpcr_builtins): New function.

> 	(aarch64_expand_fcr_fpsr_builtin): New function.

> 	(aarch64_general_expand_builtin): Modify to make use of the later.

> 	* config/aarch64/aarch64.md (UNSPECV_GET_FPCR64)

> 	(UNSPECV_SET_FPCR64, UNSPECV_GET_FPSR64, UNSPECV_SET_FPSR64): Add

> 	4 new unpecv.

> 	(set_fpcr64, get_fpcr64,set_fpsr64, get_fpsr64): New patterns.

> 	* doc/extend.texi (__builtin_aarch64_get_fpcr64)

> 	(__builtin_aarch64_set_fpcr64, __builtin_aarch64_get_fpsr64)

> 	(__builtin_aarch64_set_fpsr64): Add into AArch64 Built-in

> 	Functions.

>

> gcc/testsuite/ChangeLog:

>

> 2020-??-??  Andrea Corallo  <andrea.corallo@arm.com>

>

> 	* gcc.target/aarch64/get_fpcr64.c: New test.

> 	* gcc.target/aarch64/set_fpcr64.c: New test.

> 	* gcc.target/aarch64/get_fpsr64.c: New test.

> 	* gcc.target/aarch64/set_fpsr64.c: New test.


Hi all,

Leaving aside 2/2, I've retested this one (1/2) on top of current
master.

Regtested and bootstrapped on aarch64-linux-gnu.

Is it okay for trunk?

Regards

  Andrea
Andrea Corallo June 3, 2020, 10:10 a.m. | #2
Andrea Corallo <andrea.corallo@arm.com> writes:

> Andrea Corallo <andrea.corallo@arm.com> writes:

>

>> Hi all,

>>

>> I'd like to submit this patch introducing the following 64bit builtins

>> variants as FPCR and FPSR registers getter/setter:

>>

>> unsigned long long __builtin_aarch64_get_fpcr64 ()

>> void __builtin_aarch64_set_fpcr64 (unsigned long long)

>> unsigned long long __builtin_aarch64_get_fpsr64 ()

>> void __builtin_aarch64_set_fpsr64 (unsigned long long)

>>

>> Regards

>>   Andrea

>>

>> gcc/ChangeLog:

>>

>> 2020-??-??  Andrea Corallo  <andrea.corallo@arm.com>

>>

>> 	* config/aarch64/aarch64-builtins.c (aarch64_builtins): Add enums

>> 	for 64bits fpsr/fpcr getter setters builtin variants.

>> 	(aarch64_init_fpsr_fpcr_builtins): New function.

>> 	(aarch64_expand_fcr_fpsr_builtin): New function.

>> 	(aarch64_general_expand_builtin): Modify to make use of the later.

>> 	* config/aarch64/aarch64.md (UNSPECV_GET_FPCR64)

>> 	(UNSPECV_SET_FPCR64, UNSPECV_GET_FPSR64, UNSPECV_SET_FPSR64): Add

>> 	4 new unpecv.

>> 	(set_fpcr64, get_fpcr64,set_fpsr64, get_fpsr64): New patterns.

>> 	* doc/extend.texi (__builtin_aarch64_get_fpcr64)

>> 	(__builtin_aarch64_set_fpcr64, __builtin_aarch64_get_fpsr64)

>> 	(__builtin_aarch64_set_fpsr64): Add into AArch64 Built-in

>> 	Functions.

>>

>> gcc/testsuite/ChangeLog:

>>

>> 2020-??-??  Andrea Corallo  <andrea.corallo@arm.com>

>>

>> 	* gcc.target/aarch64/get_fpcr64.c: New test.

>> 	* gcc.target/aarch64/set_fpcr64.c: New test.

>> 	* gcc.target/aarch64/get_fpsr64.c: New test.

>> 	* gcc.target/aarch64/set_fpsr64.c: New test.

>

> Hi all,

>

> Leaving aside 2/2, I've retested this one (1/2) on top of current

> master.

>

> Regtested and bootstrapped on aarch64-linux-gnu.

>

> Is it okay for trunk?

>

> Regards

>

>   Andrea


Ping

  Andrea
Richard Sandiford June 4, 2020, 5:28 p.m. | #3
Andrea Corallo <andrea.corallo@arm.com> writes:
> Hi all,

>

> I'd like to submit this patch introducing the following 64bit builtins

> variants as FPCR and FPSR registers getter/setter:

>

> unsigned long long __builtin_aarch64_get_fpcr64 ()

> void __builtin_aarch64_set_fpcr64 (unsigned long long)

> unsigned long long __builtin_aarch64_get_fpsr64 ()

> void __builtin_aarch64_set_fpsr64 (unsigned long long)


Sound like this part is uncontroversial.  At least, if anyone objects
to it, they should have said so earlier :-)

> @@ -1240,33 +1245,65 @@ aarch64_init_memtag_builtins (void)

>  #undef AARCH64_INIT_MEMTAG_BUILTINS_DECL

>  }

>  

> -/* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group.  */

> +/* Initialize fpsr fpcr getter and setters.  */


“getters”

> @@ -1871,6 +1908,40 @@ aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)

>    return target;

>  }

>  

> +static rtx

> +aarch64_expand_fcr_fpsr_builtin (tree exp, machine_mode mode, bool getter,

> +				 bool fpsr)

> +{

> +  int icode;

> +  rtx pat;

> +  rtx target = NULL_RTX;

> +

> +  gcc_assert (mode == SImode || (mode == DImode));

> +

> +  if (getter)

> +    {

> +      if (mode == SImode)

> +	icode = fpsr ? CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;

> +      else

> +	icode = fpsr ? CODE_FOR_get_fpsr64 : CODE_FOR_get_fpcr64;

> +      target = gen_reg_rtx (mode);

> +      pat = GEN_FCN (icode) (target);

> +    }

> +  else

> +    {

> +      target = NULL_RTX;

> +      if (mode == SImode)

> +	icode = fpsr ? CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;

> +      else

> +	icode = fpsr ? CODE_FOR_set_fpsr64 : CODE_FOR_set_fpcr64;

> +      tree arg = CALL_EXPR_ARG (exp, 0);

> +      rtx op = force_reg (mode, expand_normal (arg));

> +      pat = GEN_FCN (icode) (op);

> +    }

> +  emit_insn (pat);

> +  return target;

> +}

> +

>  /* Expand an expression EXP that calls built-in function FCODE,

>     with result going to TARGET if that's convenient.  IGNORE is true

>     if the result of the builtin is ignored.  */

> @@ -1879,35 +1950,27 @@ aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,

>  				int ignore)

>  {

>    int icode;

> -  rtx pat, op0;

> +  rtx op0;

>    tree arg0;

>  

>    switch (fcode)

>      {

>      case AARCH64_BUILTIN_GET_FPCR:

> +      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, true, false);

>      case AARCH64_BUILTIN_SET_FPCR:

> +      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, false, false);

>      case AARCH64_BUILTIN_GET_FPSR:

> +      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, true, true);

>      case AARCH64_BUILTIN_SET_FPSR:

> -      if ((fcode == AARCH64_BUILTIN_GET_FPCR)

> -	  || (fcode == AARCH64_BUILTIN_GET_FPSR))

> -	{

> -	  icode = (fcode == AARCH64_BUILTIN_GET_FPSR) ?

> -	    CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;

> -	  target = gen_reg_rtx (SImode);

> -	  pat = GEN_FCN (icode) (target);

> -	}

> -      else

> -	{

> -	  target = NULL_RTX;

> -	  icode = (fcode == AARCH64_BUILTIN_SET_FPSR) ?

> -	    CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;

> -	  arg0 = CALL_EXPR_ARG (exp, 0);

> -	  op0 = force_reg (SImode, expand_normal (arg0));

> -	  pat = GEN_FCN (icode) (op0);

> -	}

> -      emit_insn (pat);

> -      return target;

> -

> +      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, false, true);

> +    case AARCH64_BUILTIN_GET_FPCR64:

> +      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, true, false);

> +    case AARCH64_BUILTIN_SET_FPCR64:

> +      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, false, false);

> +    case AARCH64_BUILTIN_GET_FPSR64:

> +      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, true, true);

> +    case AARCH64_BUILTIN_SET_FPSR64:

> +      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, false, true);

>      case AARCH64_PAUTH_BUILTIN_AUTIA1716:

>      case AARCH64_PAUTH_BUILTIN_PACIA1716:

>      case AARCH64_PAUTH_BUILTIN_AUTIB1716:

> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md

> index 7ad4e918578b..b6836710c9c2 100644

> --- a/gcc/config/aarch64/aarch64.md

> +++ b/gcc/config/aarch64/aarch64.md

> @@ -289,6 +289,10 @@

>      UNSPECV_SET_FPCR		; Represent assign of FPCR content.

>      UNSPECV_GET_FPSR		; Represent fetch of FPSR content.

>      UNSPECV_SET_FPSR		; Represent assign of FPSR content.

> +    UNSPECV_GET_FPCR64		; Represent fetch of 64 bits FPCR content.

> +    UNSPECV_SET_FPCR64		; Represent assign of 64 bits FPCR content.

> +    UNSPECV_GET_FPSR64		; Represent fetch of 64 bits FPSR content.

> +    UNSPECV_SET_FPSR64		; Represent assign of 64 bits FPSR content.

>      UNSPECV_BLOCKAGE		; Represent a blockage

>      UNSPECV_PROBE_STACK_RANGE	; Represent stack range probing.

>      UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.

> @@ -7198,6 +7202,35 @@

>    "mrs\\t%0, fpsr"

>    [(set_attr "type" "mrs")])

>  

> +;; Write 64 bits into Floating-point Control Register.

> +(define_insn "set_fpcr64"

> +  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] UNSPECV_SET_FPCR64)]

> +  ""

> +  "msr\\tfpcr, %0"

> +  [(set_attr "type" "mrs")])

> +

> +;; Read Floating-point Control Register 64 bits.

> +(define_insn "get_fpcr64"

> +  [(set (match_operand:DI 0 "register_operand" "=r")

> +        (unspec_volatile:DI [(const_int 0)] UNSPECV_GET_FPCR64))]

> +  ""

> +  "mrs\\t%0, fpcr"

> +  [(set_attr "type" "mrs")])

> +

> +;; Write 64 bits into Floating-point Status Register.

> +(define_insn "set_fpsr64"

> +  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] UNSPECV_SET_FPSR64)]

> +  ""

> +  "msr\\tfpsr, %0"

> +  [(set_attr "type" "mrs")])

> +

> +;; Read Floating-point Status Register 64 bits.

> +(define_insn "get_fpsr64"

> +  [(set (match_operand:DI 0 "register_operand" "=r")

> +        (unspec_volatile:DI [(const_int 0)] UNSPECV_GET_FPSR64))]

> +  ""

> +  "mrs\\t%0, fpsr"

> +  [(set_attr "type" "mrs")])


I think instead we should replace the existing and new patterns with
something like:

(define_insn "@aarch64_get_<GET_FPSCR:name><GPI:mode>"
  [(set (...:GPI ...)
        (unspec_volatile:GPI ... GET_FPSCR))]
  "mrs... <GET_FPSCR:name>"
  ...)

for the getter and similarly for the setter, giving 2 patterns in total.
GET_FPSCR would be a define_int_iterator iterating over UNSPECV_GET_FPSR
and UNSPECV_GET_FPCR.  We wouldn't need separate unspecs for the 64-bit
versions; that would be indicated by the mode instead.

Then aarch64_expand_fcr_fpsr_builtin splits naturally into two:
one for getters and one for setters.  The getter side would need:

  gen_arch64_get (unspec_id, mode, target)

where unspec_id is UNSPECV_GET_FPSR or UNSPECV_GET_FPCR.
Similarly for the setter side.

Thanks,
Richard
Andrea Corallo June 5, 2020, 8:22 a.m. | #4
Richard Sandiford <richard.sandiford@arm.com> writes:

> Andrea Corallo <andrea.corallo@arm.com> writes:

>> Hi all,

>>

>> I'd like to submit this patch introducing the following 64bit builtins

>> variants as FPCR and FPSR registers getter/setter:

>>

>> unsigned long long __builtin_aarch64_get_fpcr64 ()

>> void __builtin_aarch64_set_fpcr64 (unsigned long long)

>> unsigned long long __builtin_aarch64_get_fpsr64 ()

>> void __builtin_aarch64_set_fpsr64 (unsigned long long)

>

> Sound like this part is uncontroversial.  At least, if anyone objects

> to it, they should have said so earlier :-)

>

>> @@ -1240,33 +1245,65 @@ aarch64_init_memtag_builtins (void)

>>  #undef AARCH64_INIT_MEMTAG_BUILTINS_DECL

>>  }

>>  

>> -/* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group.  */

>> +/* Initialize fpsr fpcr getter and setters.  */

>

> “getters”

>

>> @@ -1871,6 +1908,40 @@ aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)

>>    return target;

>>  }

>>  

>> +static rtx

>> +aarch64_expand_fcr_fpsr_builtin (tree exp, machine_mode mode, bool getter,

>> +				 bool fpsr)

>> +{

>> +  int icode;

>> +  rtx pat;

>> +  rtx target = NULL_RTX;

>> +

>> +  gcc_assert (mode == SImode || (mode == DImode));

>> +

>> +  if (getter)

>> +    {

>> +      if (mode == SImode)

>> +	icode = fpsr ? CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;

>> +      else

>> +	icode = fpsr ? CODE_FOR_get_fpsr64 : CODE_FOR_get_fpcr64;

>> +      target = gen_reg_rtx (mode);

>> +      pat = GEN_FCN (icode) (target);

>> +    }

>> +  else

>> +    {

>> +      target = NULL_RTX;

>> +      if (mode == SImode)

>> +	icode = fpsr ? CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;

>> +      else

>> +	icode = fpsr ? CODE_FOR_set_fpsr64 : CODE_FOR_set_fpcr64;

>> +      tree arg = CALL_EXPR_ARG (exp, 0);

>> +      rtx op = force_reg (mode, expand_normal (arg));

>> +      pat = GEN_FCN (icode) (op);

>> +    }

>> +  emit_insn (pat);

>> +  return target;

>> +}

>> +

>>  /* Expand an expression EXP that calls built-in function FCODE,

>>     with result going to TARGET if that's convenient.  IGNORE is true

>>     if the result of the builtin is ignored.  */

>> @@ -1879,35 +1950,27 @@ aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,

>>  				int ignore)

>>  {

>>    int icode;

>> -  rtx pat, op0;

>> +  rtx op0;

>>    tree arg0;

>>  

>>    switch (fcode)

>>      {

>>      case AARCH64_BUILTIN_GET_FPCR:

>> +      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, true, false);

>>      case AARCH64_BUILTIN_SET_FPCR:

>> +      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, false, false);

>>      case AARCH64_BUILTIN_GET_FPSR:

>> +      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, true, true);

>>      case AARCH64_BUILTIN_SET_FPSR:

>> -      if ((fcode == AARCH64_BUILTIN_GET_FPCR)

>> -	  || (fcode == AARCH64_BUILTIN_GET_FPSR))

>> -	{

>> -	  icode = (fcode == AARCH64_BUILTIN_GET_FPSR) ?

>> -	    CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;

>> -	  target = gen_reg_rtx (SImode);

>> -	  pat = GEN_FCN (icode) (target);

>> -	}

>> -      else

>> -	{

>> -	  target = NULL_RTX;

>> -	  icode = (fcode == AARCH64_BUILTIN_SET_FPSR) ?

>> -	    CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;

>> -	  arg0 = CALL_EXPR_ARG (exp, 0);

>> -	  op0 = force_reg (SImode, expand_normal (arg0));

>> -	  pat = GEN_FCN (icode) (op0);

>> -	}

>> -      emit_insn (pat);

>> -      return target;

>> -

>> +      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, false, true);

>> +    case AARCH64_BUILTIN_GET_FPCR64:

>> +      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, true, false);

>> +    case AARCH64_BUILTIN_SET_FPCR64:

>> +      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, false, false);

>> +    case AARCH64_BUILTIN_GET_FPSR64:

>> +      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, true, true);

>> +    case AARCH64_BUILTIN_SET_FPSR64:

>> +      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, false, true);

>>      case AARCH64_PAUTH_BUILTIN_AUTIA1716:

>>      case AARCH64_PAUTH_BUILTIN_PACIA1716:

>>      case AARCH64_PAUTH_BUILTIN_AUTIB1716:

>> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md

>> index 7ad4e918578b..b6836710c9c2 100644

>> --- a/gcc/config/aarch64/aarch64.md

>> +++ b/gcc/config/aarch64/aarch64.md

>> @@ -289,6 +289,10 @@

>>      UNSPECV_SET_FPCR		; Represent assign of FPCR content.

>>      UNSPECV_GET_FPSR		; Represent fetch of FPSR content.

>>      UNSPECV_SET_FPSR		; Represent assign of FPSR content.

>> +    UNSPECV_GET_FPCR64		; Represent fetch of 64 bits FPCR content.

>> +    UNSPECV_SET_FPCR64		; Represent assign of 64 bits FPCR content.

>> +    UNSPECV_GET_FPSR64		; Represent fetch of 64 bits FPSR content.

>> +    UNSPECV_SET_FPSR64		; Represent assign of 64 bits FPSR content.

>>      UNSPECV_BLOCKAGE		; Represent a blockage

>>      UNSPECV_PROBE_STACK_RANGE	; Represent stack range probing.

>>      UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.

>> @@ -7198,6 +7202,35 @@

>>    "mrs\\t%0, fpsr"

>>    [(set_attr "type" "mrs")])

>>  

>> +;; Write 64 bits into Floating-point Control Register.

>> +(define_insn "set_fpcr64"

>> +  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] UNSPECV_SET_FPCR64)]

>> +  ""

>> +  "msr\\tfpcr, %0"

>> +  [(set_attr "type" "mrs")])

>> +

>> +;; Read Floating-point Control Register 64 bits.

>> +(define_insn "get_fpcr64"

>> +  [(set (match_operand:DI 0 "register_operand" "=r")

>> +        (unspec_volatile:DI [(const_int 0)] UNSPECV_GET_FPCR64))]

>> +  ""

>> +  "mrs\\t%0, fpcr"

>> +  [(set_attr "type" "mrs")])

>> +

>> +;; Write 64 bits into Floating-point Status Register.

>> +(define_insn "set_fpsr64"

>> +  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] UNSPECV_SET_FPSR64)]

>> +  ""

>> +  "msr\\tfpsr, %0"

>> +  [(set_attr "type" "mrs")])

>> +

>> +;; Read Floating-point Status Register 64 bits.

>> +(define_insn "get_fpsr64"

>> +  [(set (match_operand:DI 0 "register_operand" "=r")

>> +        (unspec_volatile:DI [(const_int 0)] UNSPECV_GET_FPSR64))]

>> +  ""

>> +  "mrs\\t%0, fpsr"

>> +  [(set_attr "type" "mrs")])

>

> I think instead we should replace the existing and new patterns with

> something like:

>

> (define_insn "@aarch64_get_<GET_FPSCR:name><GPI:mode>"

>   [(set (...:GPI ...)

>         (unspec_volatile:GPI ... GET_FPSCR))]

>   "mrs... <GET_FPSCR:name>"

>   ...)

>

> for the getter and similarly for the setter, giving 2 patterns in total.

> GET_FPSCR would be a define_int_iterator iterating over UNSPECV_GET_FPSR

> and UNSPECV_GET_FPCR.  We wouldn't need separate unspecs for the 64-bit

> versions; that would be indicated by the mode instead.

>

> Then aarch64_expand_fcr_fpsr_builtin splits naturally into two:

> one for getters and one for setters.  The getter side would need:

>

>   gen_arch64_get (unspec_id, mode, target)

>

> where unspec_id is UNSPECV_GET_FPSR or UNSPECV_GET_FPCR.

> Similarly for the setter side.

>

> Thanks,

> Richard


Thanks for the review, I'll update the patch.

  Andrea

Patch

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 9c9c6d86ae29..b3ffa3893c08 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -443,6 +443,11 @@  enum aarch64_builtins
   AARCH64_BUILTIN_GET_FPSR,
   AARCH64_BUILTIN_SET_FPSR,
 
+  AARCH64_BUILTIN_GET_FPCR64,
+  AARCH64_BUILTIN_SET_FPCR64,
+  AARCH64_BUILTIN_GET_FPSR64,
+  AARCH64_BUILTIN_SET_FPSR64,
+
   AARCH64_BUILTIN_RSQRT_DF,
   AARCH64_BUILTIN_RSQRT_SF,
   AARCH64_BUILTIN_RSQRT_V2DF,
@@ -1240,33 +1245,65 @@  aarch64_init_memtag_builtins (void)
 #undef AARCH64_INIT_MEMTAG_BUILTINS_DECL
 }
 
-/* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group.  */
+/* Initialize fpsr fpcr getter and setters.  */
 
-void
-aarch64_general_init_builtins (void)
+static void
+aarch64_init_fpsr_fpcr_builtins (void)
 {
-  tree ftype_set_fpr
+  tree ftype_set
     = build_function_type_list (void_type_node, unsigned_type_node, NULL);
-  tree ftype_get_fpr
+  tree ftype_get
     = build_function_type_list (unsigned_type_node, NULL);
 
   aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
     = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr",
-				   ftype_get_fpr,
+				   ftype_get,
 				   AARCH64_BUILTIN_GET_FPCR);
   aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
     = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr",
-				   ftype_set_fpr,
+				   ftype_set,
 				   AARCH64_BUILTIN_SET_FPCR);
   aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
     = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr",
-				   ftype_get_fpr,
+				   ftype_get,
 				   AARCH64_BUILTIN_GET_FPSR);
   aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
     = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr",
-				   ftype_set_fpr,
+				   ftype_set,
 				   AARCH64_BUILTIN_SET_FPSR);
 
+  ftype_set
+    = build_function_type_list (void_type_node, long_long_unsigned_type_node,
+				NULL);
+  ftype_get
+    = build_function_type_list (long_long_unsigned_type_node, NULL);
+
+  aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR64]
+    = aarch64_general_add_builtin ("__builtin_aarch64_get_fpcr64",
+				   ftype_get,
+				   AARCH64_BUILTIN_GET_FPCR64);
+  aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR64]
+    = aarch64_general_add_builtin ("__builtin_aarch64_set_fpcr64",
+				   ftype_set,
+				   AARCH64_BUILTIN_SET_FPCR64);
+  aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR64]
+    = aarch64_general_add_builtin ("__builtin_aarch64_get_fpsr64",
+				   ftype_get,
+				   AARCH64_BUILTIN_GET_FPSR64);
+  aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR64]
+    = aarch64_general_add_builtin ("__builtin_aarch64_set_fpsr64",
+				   ftype_set,
+				   AARCH64_BUILTIN_SET_FPSR64);
+}
+
+/* Initialize all builtins in the AARCH64_BUILTIN_GENERAL group.  */
+
+void
+aarch64_general_init_builtins (void)
+{
+
+  aarch64_init_fpsr_fpcr_builtins ();
+
   aarch64_init_fp16_types ();
 
   aarch64_init_bf16_types ();
@@ -1871,6 +1908,40 @@  aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)
   return target;
 }
 
+static rtx
+aarch64_expand_fcr_fpsr_builtin (tree exp, machine_mode mode, bool getter,
+				 bool fpsr)
+{
+  int icode;
+  rtx pat;
+  rtx target = NULL_RTX;
+
+  gcc_assert (mode == SImode || (mode == DImode));
+
+  if (getter)
+    {
+      if (mode == SImode)
+	icode = fpsr ? CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;
+      else
+	icode = fpsr ? CODE_FOR_get_fpsr64 : CODE_FOR_get_fpcr64;
+      target = gen_reg_rtx (mode);
+      pat = GEN_FCN (icode) (target);
+    }
+  else
+    {
+      target = NULL_RTX;
+      if (mode == SImode)
+	icode = fpsr ? CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;
+      else
+	icode = fpsr ? CODE_FOR_set_fpsr64 : CODE_FOR_set_fpcr64;
+      tree arg = CALL_EXPR_ARG (exp, 0);
+      rtx op = force_reg (mode, expand_normal (arg));
+      pat = GEN_FCN (icode) (op);
+    }
+  emit_insn (pat);
+  return target;
+}
+
 /* Expand an expression EXP that calls built-in function FCODE,
    with result going to TARGET if that's convenient.  IGNORE is true
    if the result of the builtin is ignored.  */
@@ -1879,35 +1950,27 @@  aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
 				int ignore)
 {
   int icode;
-  rtx pat, op0;
+  rtx op0;
   tree arg0;
 
   switch (fcode)
     {
     case AARCH64_BUILTIN_GET_FPCR:
+      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, true, false);
     case AARCH64_BUILTIN_SET_FPCR:
+      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, false, false);
     case AARCH64_BUILTIN_GET_FPSR:
+      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, true, true);
     case AARCH64_BUILTIN_SET_FPSR:
-      if ((fcode == AARCH64_BUILTIN_GET_FPCR)
-	  || (fcode == AARCH64_BUILTIN_GET_FPSR))
-	{
-	  icode = (fcode == AARCH64_BUILTIN_GET_FPSR) ?
-	    CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;
-	  target = gen_reg_rtx (SImode);
-	  pat = GEN_FCN (icode) (target);
-	}
-      else
-	{
-	  target = NULL_RTX;
-	  icode = (fcode == AARCH64_BUILTIN_SET_FPSR) ?
-	    CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;
-	  arg0 = CALL_EXPR_ARG (exp, 0);
-	  op0 = force_reg (SImode, expand_normal (arg0));
-	  pat = GEN_FCN (icode) (op0);
-	}
-      emit_insn (pat);
-      return target;
-
+      return aarch64_expand_fcr_fpsr_builtin (exp, SImode, false, true);
+    case AARCH64_BUILTIN_GET_FPCR64:
+      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, true, false);
+    case AARCH64_BUILTIN_SET_FPCR64:
+      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, false, false);
+    case AARCH64_BUILTIN_GET_FPSR64:
+      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, true, true);
+    case AARCH64_BUILTIN_SET_FPSR64:
+      return aarch64_expand_fcr_fpsr_builtin (exp, DImode, false, true);
     case AARCH64_PAUTH_BUILTIN_AUTIA1716:
     case AARCH64_PAUTH_BUILTIN_PACIA1716:
     case AARCH64_PAUTH_BUILTIN_AUTIB1716:
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 7ad4e918578b..b6836710c9c2 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -289,6 +289,10 @@ 
     UNSPECV_SET_FPCR		; Represent assign of FPCR content.
     UNSPECV_GET_FPSR		; Represent fetch of FPSR content.
     UNSPECV_SET_FPSR		; Represent assign of FPSR content.
+    UNSPECV_GET_FPCR64		; Represent fetch of 64 bits FPCR content.
+    UNSPECV_SET_FPCR64		; Represent assign of 64 bits FPCR content.
+    UNSPECV_GET_FPSR64		; Represent fetch of 64 bits FPSR content.
+    UNSPECV_SET_FPSR64		; Represent assign of 64 bits FPSR content.
     UNSPECV_BLOCKAGE		; Represent a blockage
     UNSPECV_PROBE_STACK_RANGE	; Represent stack range probing.
     UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
@@ -7198,6 +7202,35 @@ 
   "mrs\\t%0, fpsr"
   [(set_attr "type" "mrs")])
 
+;; Write 64 bits into Floating-point Control Register.
+(define_insn "set_fpcr64"
+  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] UNSPECV_SET_FPCR64)]
+  ""
+  "msr\\tfpcr, %0"
+  [(set_attr "type" "mrs")])
+
+;; Read Floating-point Control Register 64 bits.
+(define_insn "get_fpcr64"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (unspec_volatile:DI [(const_int 0)] UNSPECV_GET_FPCR64))]
+  ""
+  "mrs\\t%0, fpcr"
+  [(set_attr "type" "mrs")])
+
+;; Write 64 bits into Floating-point Status Register.
+(define_insn "set_fpsr64"
+  [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")] UNSPECV_SET_FPSR64)]
+  ""
+  "msr\\tfpsr, %0"
+  [(set_attr "type" "mrs")])
+
+;; Read Floating-point Status Register 64 bits.
+(define_insn "get_fpsr64"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (unspec_volatile:DI [(const_int 0)] UNSPECV_GET_FPSR64))]
+  ""
+  "mrs\\t%0, fpsr"
+  [(set_attr "type" "mrs")])
 
 ;; Define the subtract-one-and-jump insns so loop.c
 ;; knows what to generate.
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 11b79a5852c1..2ec30537146a 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13768,6 +13768,12 @@  unsigned int __builtin_aarch64_get_fpcr ()
 void __builtin_aarch64_set_fpcr (unsigned int)
 unsigned int __builtin_aarch64_get_fpsr ()
 void __builtin_aarch64_set_fpsr (unsigned int)
+
+unsigned long long __builtin_aarch64_get_fpcr64 ()
+void __builtin_aarch64_set_fpcr64 (unsigned long long)
+unsigned long long __builtin_aarch64_get_fpsr64 ()
+void __builtin_aarch64_set_fpsr64 (unsigned long long)
+
 @end smallexample
 
 @node Alpha Built-in Functions
diff --git a/gcc/testsuite/gcc.target/aarch64/get_fpcr64.c b/gcc/testsuite/gcc.target/aarch64/get_fpcr64.c
new file mode 100644
index 000000000000..9fed91fe2053
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/get_fpcr64.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+long long unsigned
+get_fpcr64 ()
+{
+  return __builtin_aarch64_get_fpcr64 ();
+}
+
+/* { dg-final { scan-assembler-times "mrs.*fpcr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/get_fpsr64.c b/gcc/testsuite/gcc.target/aarch64/get_fpsr64.c
new file mode 100644
index 000000000000..f5d8f76d9382
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/get_fpsr64.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+long long unsigned
+get_fpsr64 ()
+{
+  return __builtin_aarch64_get_fpsr64 ();
+}
+
+/* { dg-final { scan-assembler-times "mrs.*fpsr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/set_fpcr64.c b/gcc/testsuite/gcc.target/aarch64/set_fpcr64.c
new file mode 100644
index 000000000000..2390abff4d17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/set_fpcr64.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+set_fpcr64 (long long unsigned x)
+{
+  return __builtin_aarch64_set_fpcr64 (x);
+}
+
+/* { dg-final { scan-assembler-times "msr.*fpcr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/set_fpsr64.c b/gcc/testsuite/gcc.target/aarch64/set_fpsr64.c
new file mode 100644
index 000000000000..0ed3da2bce87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/set_fpsr64.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+set_fpsr64 (long long unsigned x)
+{
+  return __builtin_aarch64_set_fpsr64 (x);
+}
+
+/* { dg-final { scan-assembler-times "msr.*fpsr" 1 } } */