[Arm,2/3] Add support for float16 (IEEE and Alternative formats) for Arm backend.

Message ID 853c8195-148e-9c21-7a5a-59b8cdaeeafc@arm.com
State New
Headers show
Series
  • Add float16 directive for assembling 16-bit floating point numbers.
Related show

Commit Message

Barnaby Wilks July 11, 2019, 3:26 p.m.
Hello,

This is part of a patch series that implements a directive for assembling 16-bit floating point constants for Arm and AArch64.

This patch implements the float16 directive for both the IEEE 754 format and the Arm alternative format for the
Arm backend.

The syntax of the directive is:
.float16 <0-n decimal numbers>
e.g.
.float16 12.0
.float16 0.23, 433.1, 0.06

The Arm alternative format is almost identical to the IEEE 754 format, except that it doesn't
encode for NaNs or Infinity (instead an exponent of 0x1F represents a normalized number in the range
65536 to 131008).

The alternative format is documented in the reference manual:
https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf?_ga=2.72318806.49764181.1561632697-999473562.1560847439

Which format is used is controlled by the
.eabi_attribute Tag_ABI_FP_16bit_format, <...>
directive, where if
<...> = 1 then use the IEEE 754 half-precision format else if
<...> = 2 then use the Arm alternative format

Added testcases to verify the correct encoding for both formats (for both big and little endian targets),
as well as tests verifying that warnings are thrown if trying to encode NaN or Infinity when using
the Arm alternative format.
The encodings have been cross referenced with GCC's encoding for __fp16 types to ensure consistency.

Cross compiled and regtested on arm-none-eabi and arm-none-linux-gnueabihf

I don't have write access, so if it's OK then could someone commit on my behalf?

Thanks,
Barney

gas/ChangeLog:

2019-07-11  Barnaby Wilks<barnaby.wilks@arm.com>

	* config/tc-arm.c (md_atof): Set precision for float16 type.
	(enum fp_16bit_format): Add enum to represent the 2 float16 encodings.
	(arm_is_largest_exponent_ok): Check for whether to encode with the IEEE or alternative
	format.
	* config/tc-arm.h (TC_LARGEST_EXPONENT_IS_NORMAL): Macro that expands to
	arm_is_largest_exponent_ok.
	(arm_is_largest_exponent_ok): Add prototype for arm_is_largest_exponent_ok function.
	* testsuite/gas/arm/float16-bad.d: New test.
	* testsuite/gas/arm/float16-bad.l: New test.
	* testsuite/gas/arm/float16-bad.s: New test.
	* testsuite/gas/arm/float16-be.d: New test.
	* testsuite/gas/arm/float16-be.s: New test.
	* testsuite/gas/arm/float16-le.d: New test.
	* testsuite/gas/arm/float16-le.s: New test.

Comments

Richard Earnshaw (lists) July 15, 2019, 9:16 a.m. | #1
On 11/07/2019 16:26, Barnaby Wilks wrote:
> Hello,

> 

> This is part of a patch series that implements a directive for assembling 16-bit floating point constants for Arm and AArch64.

> 

> This patch implements the float16 directive for both the IEEE 754 format and the Arm alternative format for the

> Arm backend >

> The syntax of the directive is:

> .float16 <0-n decimal numbers>

> e.g.

> .float16 12.0

> .float16 0.23, 433.1, 0.06

> 

> The Arm alternative format is almost identical to the IEEE 754 format, except that it doesn't

> encode for NaNs or Infinity (instead an exponent of 0x1F represents a normalized number in the range

> 65536 to 131008).

> 

> The alternative format is documented in the reference manual:

> https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf?_ga=2.72318806.49764181.1561632697-999473562.1560847439

> 

> Which format is used is controlled by the

> .eabi_attribute Tag_ABI_FP_16bit_format, <...>

> directive, where if

> <...> = 1 then use the IEEE 754 half-precision format else if

> <...> = 2 then use the Arm alternative format

> 

> Added testcases to verify the correct encoding for both formats (for both big and little endian targets),

> as well as tests verifying that warnings are thrown if trying to encode NaN or Infinity when using

> the Arm alternative format.

> The encodings have been cross referenced with GCC's encoding for __fp16 types to ensure consistency.

> 

> Cross compiled and regtested on arm-none-eabi and arm-none-linux-gnueabihf

> 

> I don't have write access, so if it's OK then could someone commit on my behalf?

> 


Hi Barney,

thanks for the patch.

I'm not sure that using the build attributes to control selection of the 
format is the best idea.  Firstly, build attributes are not available 
when not assembling for ELF (we have PE-coff support in the assembler as 
well); secondly, build attributes should reflect what was placed in the 
assembly file, not control what goes into it.  So this is a case of the 
coach before the horse.

I think, if we want to support the Arm alternate FP format in GAS at 
all, we need either a new command line option, or a new directive (or 
possibly both).  Then the code in BFD that does automatic 
build-attribute selection should be updated to reflect the tri-state 
situation: no format specified; IEEE format specified; or ARM Alternate 
format specified.

Note that GAS can currently only reflect show build attributes that 
affect the whole file, so switching during assembly is a little dubious 
as things stand.


R.


> Thanks,

> Barney

> 

> gas/ChangeLog:

> 

> 2019-07-11  Barnaby Wilks<barnaby.wilks@arm.com>

> 

> 	* config/tc-arm.c (md_atof): Set precision for float16 type.

> 	(enum fp_16bit_format): Add enum to represent the 2 float16 encodings.

> 	(arm_is_largest_exponent_ok): Check for whether to encode with the IEEE or alternative

> 	format.

> 	* config/tc-arm.h (TC_LARGEST_EXPONENT_IS_NORMAL): Macro that expands to

> 	arm_is_largest_exponent_ok.

> 	(arm_is_largest_exponent_ok): Add prototype for arm_is_largest_exponent_ok function.

> 	* testsuite/gas/arm/float16-bad.d: New test.

> 	* testsuite/gas/arm/float16-bad.l: New test.

> 	* testsuite/gas/arm/float16-bad.s: New test.

> 	* testsuite/gas/arm/float16-be.d: New test.

> 	* testsuite/gas/arm/float16-be.s: New test.

> 	* testsuite/gas/arm/float16-le.d: New test.

> 	* testsuite/gas/arm/float16-le.s: New test.

>
Barnaby Wilks July 15, 2019, 3:44 p.m. | #2
Hi Richard,

Yep agreed, a dedicated directive would make more sense really - originally I did have something
along those lines (.ieee_fp16_format/.alternative_fp16_format directives for switching between formats), but then
changed upon finding a EABI attribute for the same thing, and seeing that was how GCC did it.
Like you say though, for files that contain a mix of float16's in both IEEE and Alternative formats what would be the
EABI attribute for that be?

This could be solved by just restricting to one format (in which
case a command line option may make more sense), or by inventing
a new EABI attribute? (I'm don't really know much about that, so have no idea if it's feasible).

Regards,

Barney

On 7/15/19 10:16 AM, Richard Earnshaw (lists) wrote:
>

>

> On 11/07/2019 16:26, Barnaby Wilks wrote:

>> Hello,

>>

>> This is part of a patch series that implements a directive for 

>> assembling 16-bit floating point constants for Arm and AArch64.

>>

>> This patch implements the float16 directive for both the IEEE 754 

>> format and the Arm alternative format for the

>> Arm backend >

>> The syntax of the directive is:

>> .float16 <0-n decimal numbers>

>> e.g.

>> .float16 12.0

>> .float16 0.23, 433.1, 0.06

>>

>> The Arm alternative format is almost identical to the IEEE 754 

>> format, except that it doesn't

>> encode for NaNs or Infinity (instead an exponent of 0x1F represents a 

>> normalized number in the range

>> 65536 to 131008).

>>

>> The alternative format is documented in the reference manual:

>> https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf?_ga=2.72318806.49764181.1561632697-999473562.1560847439 

>>

>>

>> Which format is used is controlled by the

>> .eabi_attribute Tag_ABI_FP_16bit_format, <...>

>> directive, where if

>> <...> = 1 then use the IEEE 754 half-precision format else if

>> <...> = 2 then use the Arm alternative format

>>

>> Added testcases to verify the correct encoding for both formats (for 

>> both big and little endian targets),

>> as well as tests verifying that warnings are thrown if trying to 

>> encode NaN or Infinity when using

>> the Arm alternative format.

>> The encodings have been cross referenced with GCC's encoding for 

>> __fp16 types to ensure consistency.

>>

>> Cross compiled and regtested on arm-none-eabi and 

>> arm-none-linux-gnueabihf

>>

>> I don't have write access, so if it's OK then could someone commit on 

>> my behalf?

>>

>

> Hi Barney,

>

> thanks for the patch.

>

> I'm not sure that using the build attributes to control selection of 

> the format is the best idea.  Firstly, build attributes are not 

> available when not assembling for ELF (we have PE-coff support in the 

> assembler as well); secondly, build attributes should reflect what was 

> placed in the assembly file, not control what goes into it.  So this 

> is a case of the coach before the horse.

>

> I think, if we want to support the Arm alternate FP format in GAS at 

> all, we need either a new command line option, or a new directive (or 

> possibly both).  Then the code in BFD that does automatic 

> build-attribute selection should be updated to reflect the tri-state 

> situation: no format specified; IEEE format specified; or ARM 

> Alternate format specified.

>

> Note that GAS can currently only reflect show build attributes that 

> affect the whole file, so switching during assembly is a little 

> dubious as things stand.

>

>

> R.

>

>

>> Thanks,

>> Barney

>>

>> gas/ChangeLog:

>>

>> 2019-07-11  Barnaby Wilks<barnaby.wilks@arm.com>

>>

>>     * config/tc-arm.c (md_atof): Set precision for float16 type.

>>     (enum fp_16bit_format): Add enum to represent the 2 float16 

>> encodings.

>>     (arm_is_largest_exponent_ok): Check for whether to encode with 

>> the IEEE or alternative

>>     format.

>>     * config/tc-arm.h (TC_LARGEST_EXPONENT_IS_NORMAL): Macro that 

>> expands to

>>     arm_is_largest_exponent_ok.

>>     (arm_is_largest_exponent_ok): Add prototype for 

>> arm_is_largest_exponent_ok function.

>>     * testsuite/gas/arm/float16-bad.d: New test.

>>     * testsuite/gas/arm/float16-bad.l: New test.

>>     * testsuite/gas/arm/float16-bad.s: New test.

>>     * testsuite/gas/arm/float16-be.d: New test.

>>     * testsuite/gas/arm/float16-be.s: New test.

>>     * testsuite/gas/arm/float16-le.d: New test.

>>     * testsuite/gas/arm/float16-le.s: New test.

>>
Richard Earnshaw (lists) July 15, 2019, 4:11 p.m. | #3
On 15/07/2019 16:44, Barnaby Wilks wrote:
> Hi Richard,

> 

> Yep agreed, a dedicated directive would make more sense really - originally I did have something

> along those lines (.ieee_fp16_format/.alternative_fp16_format directives for switching between formats), but then

> changed upon finding a EABI attribute for the same thing, and seeing that was how GCC did it.

> Like you say though, for files that contain a mix of float16's in both IEEE and Alternative formats what would be the

> EABI attribute for that be?

> 

> This could be solved by just restricting to one format (in which

> case a command line option may make more sense), or by inventing

> a new EABI attribute? (I'm don't really know much about that, so have no idea if it's feasible).

> 


GCC already has the command-line option 
-mfp16-format=(none|ieee|alternative).  I'd suggest we have the same, 
and have an assembly attribute directive with a similar style.

For the directive, however, the default can be a little more lax: I 
think the assembler should start in a mode where the format is 
'tentatively ieee' format.  Then, if a .float16 appears with no format 
override, we'd make that an explicit format selection.  At the end of 
assembly, when then generating build attributes (if doing that 
automatically, we'd update the build attributes if the format is at that 
point explicit.

The tentative nature is important to avoid changing behaviour for 
existing files: we don't want them to start writing out additional build 
attributes that they did not generate previously, however, ieee format 
is far more common than than alternative format, so requiring users to 
always specify this before ever using .float16 would be a little awkward.

R.

> Regards,

> 

> Barney

> 

> On 7/15/19 10:16 AM, Richard Earnshaw (lists) wrote:

>>

>>

>> On 11/07/2019 16:26, Barnaby Wilks wrote:

>>> Hello,

>>>

>>> This is part of a patch series that implements a directive for

>>> assembling 16-bit floating point constants for Arm and AArch64.

>>>

>>> This patch implements the float16 directive for both the IEEE 754

>>> format and the Arm alternative format for the

>>> Arm backend >

>>> The syntax of the directive is:

>>> .float16 <0-n decimal numbers>

>>> e.g.

>>> .float16 12.0

>>> .float16 0.23, 433.1, 0.06

>>>

>>> The Arm alternative format is almost identical to the IEEE 754

>>> format, except that it doesn't

>>> encode for NaNs or Infinity (instead an exponent of 0x1F represents a

>>> normalized number in the range

>>> 65536 to 131008).

>>>

>>> The alternative format is documented in the reference manual:

>>> https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf?_ga=2.72318806.49764181.1561632697-999473562.1560847439

>>>

>>>

>>> Which format is used is controlled by the

>>> .eabi_attribute Tag_ABI_FP_16bit_format, <...>

>>> directive, where if

>>> <...> = 1 then use the IEEE 754 half-precision format else if

>>> <...> = 2 then use the Arm alternative format

>>>

>>> Added testcases to verify the correct encoding for both formats (for

>>> both big and little endian targets),

>>> as well as tests verifying that warnings are thrown if trying to

>>> encode NaN or Infinity when using

>>> the Arm alternative format.

>>> The encodings have been cross referenced with GCC's encoding for

>>> __fp16 types to ensure consistency.

>>>

>>> Cross compiled and regtested on arm-none-eabi and

>>> arm-none-linux-gnueabihf

>>>

>>> I don't have write access, so if it's OK then could someone commit on

>>> my behalf?

>>>

>>

>> Hi Barney,

>>

>> thanks for the patch.

>>

>> I'm not sure that using the build attributes to control selection of

>> the format is the best idea.  Firstly, build attributes are not

>> available when not assembling for ELF (we have PE-coff support in the

>> assembler as well); secondly, build attributes should reflect what was

>> placed in the assembly file, not control what goes into it.  So this

>> is a case of the coach before the horse.

>>

>> I think, if we want to support the Arm alternate FP format in GAS at

>> all, we need either a new command line option, or a new directive (or

>> possibly both).  Then the code in BFD that does automatic

>> build-attribute selection should be updated to reflect the tri-state

>> situation: no format specified; IEEE format specified; or ARM

>> Alternate format specified.

>>

>> Note that GAS can currently only reflect show build attributes that

>> affect the whole file, so switching during assembly is a little

>> dubious as things stand.

>>

>>

>> R.

>>

>>

>>> Thanks,

>>> Barney

>>>

>>> gas/ChangeLog:

>>>

>>> 2019-07-11  Barnaby Wilks<barnaby.wilks@arm.com>

>>>

>>>      * config/tc-arm.c (md_atof): Set precision for float16 type.

>>>      (enum fp_16bit_format): Add enum to represent the 2 float16

>>> encodings.

>>>      (arm_is_largest_exponent_ok): Check for whether to encode with

>>> the IEEE or alternative

>>>      format.

>>>      * config/tc-arm.h (TC_LARGEST_EXPONENT_IS_NORMAL): Macro that

>>> expands to

>>>      arm_is_largest_exponent_ok.

>>>      (arm_is_largest_exponent_ok): Add prototype for

>>> arm_is_largest_exponent_ok function.

>>>      * testsuite/gas/arm/float16-bad.d: New test.

>>>      * testsuite/gas/arm/float16-bad.l: New test.

>>>      * testsuite/gas/arm/float16-bad.s: New test.

>>>      * testsuite/gas/arm/float16-be.d: New test.

>>>      * testsuite/gas/arm/float16-be.s: New test.

>>>      * testsuite/gas/arm/float16-le.d: New test.

>>>      * testsuite/gas/arm/float16-le.s: New test.

>>>
Tamar Christina July 16, 2019, 1:59 a.m. | #4
Introducing a new directive for this seems counter intuitive to me. Particularly you open up some room for user error to happen more easily especially with inline assembly.

You also then have to Orchestrate gcc to emit these as well in order for the file to be logically consistent with the command line options the user specified. If this is a directive gcc has to emit it as well.

Lastly it also duplicates information. Now the user has two directives to set when using fp16 in an arm assembly file and also opens up the weird possibility to have your built attribute be different from the "encoding type" directive which is a bit nonsensical.

Personally I would say If you're really keen on doing this that I'd much rather have either two float16 directives or for the float16 directive to take an optional "format" specifier rather than commandline options which would complicate support in gcc.

The fact that some platforms like PE don't support built attribute aren't an issue, as those platforms already wouldn't be able to switch formats and be stuck at the "default" one. In fact do we even support fp16 on these non-elf platforms.

Regards,
Tamar

________________________________________
From: binutils-owner@sourceware.org <binutils-owner@sourceware.org> on behalf of Richard Earnshaw (lists) <Richard.Earnshaw@arm.com>

Sent: Monday, July 15, 2019 5:11:25 PM
To: Barnaby Wilks; binutils@sourceware.org
Cc: nd; nickc@redhat.com; Ramana Radhakrishnan
Subject: Re: [PATCH][binutils][Arm][2/3] Add support for float16 (IEEE and Alternative formats) for Arm backend.



On 15/07/2019 16:44, Barnaby Wilks wrote:
> Hi Richard,

>

> Yep agreed, a dedicated directive would make more sense really - originally I did have something

> along those lines (.ieee_fp16_format/.alternative_fp16_format directives for switching between formats), but then

> changed upon finding a EABI attribute for the same thing, and seeing that was how GCC did it.

> Like you say though, for files that contain a mix of float16's in both IEEE and Alternative formats what would be the

> EABI attribute for that be?

>

> This could be solved by just restricting to one format (in which

> case a command line option may make more sense), or by inventing

> a new EABI attribute? (I'm don't really know much about that, so have no idea if it's feasible).

>


GCC already has the command-line option
-mfp16-format=(none|ieee|alternative).  I'd suggest we have the same,
and have an assembly attribute directive with a similar style.

For the directive, however, the default can be a little more lax: I
think the assembler should start in a mode where the format is
'tentatively ieee' format.  Then, if a .float16 appears with no format
override, we'd make that an explicit format selection.  At the end of
assembly, when then generating build attributes (if doing that
automatically, we'd update the build attributes if the format is at that
point explicit.

The tentative nature is important to avoid changing behaviour for
existing files: we don't want them to start writing out additional build
attributes that they did not generate previously, however, ieee format
is far more common than than alternative format, so requiring users to
always specify this before ever using .float16 would be a little awkward.

R.

> Regards,

>

> Barney

>

> On 7/15/19 10:16 AM, Richard Earnshaw (lists) wrote:

>>

>>

>> On 11/07/2019 16:26, Barnaby Wilks wrote:

>>> Hello,

>>>

>>> This is part of a patch series that implements a directive for

>>> assembling 16-bit floating point constants for Arm and AArch64.

>>>

>>> This patch implements the float16 directive for both the IEEE 754

>>> format and the Arm alternative format for the

>>> Arm backend >

>>> The syntax of the directive is:

>>> .float16 <0-n decimal numbers>

>>> e.g.

>>> .float16 12.0

>>> .float16 0.23, 433.1, 0.06

>>>

>>> The Arm alternative format is almost identical to the IEEE 754

>>> format, except that it doesn't

>>> encode for NaNs or Infinity (instead an exponent of 0x1F represents a

>>> normalized number in the range

>>> 65536 to 131008).

>>>

>>> The alternative format is documented in the reference manual:

>>> https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf?_ga=2.72318806.49764181.1561632697-999473562.1560847439

>>>

>>>

>>> Which format is used is controlled by the

>>> .eabi_attribute Tag_ABI_FP_16bit_format, <...>

>>> directive, where if

>>> <...> = 1 then use the IEEE 754 half-precision format else if

>>> <...> = 2 then use the Arm alternative format

>>>

>>> Added testcases to verify the correct encoding for both formats (for

>>> both big and little endian targets),

>>> as well as tests verifying that warnings are thrown if trying to

>>> encode NaN or Infinity when using

>>> the Arm alternative format.

>>> The encodings have been cross referenced with GCC's encoding for

>>> __fp16 types to ensure consistency.

>>>

>>> Cross compiled and regtested on arm-none-eabi and

>>> arm-none-linux-gnueabihf

>>>

>>> I don't have write access, so if it's OK then could someone commit on

>>> my behalf?

>>>

>>

>> Hi Barney,

>>

>> thanks for the patch.

>>

>> I'm not sure that using the build attributes to control selection of

>> the format is the best idea.  Firstly, build attributes are not

>> available when not assembling for ELF (we have PE-coff support in the

>> assembler as well); secondly, build attributes should reflect what was

>> placed in the assembly file, not control what goes into it.  So this

>> is a case of the coach before the horse.

>>

>> I think, if we want to support the Arm alternate FP format in GAS at

>> all, we need either a new command line option, or a new directive (or

>> possibly both).  Then the code in BFD that does automatic

>> build-attribute selection should be updated to reflect the tri-state

>> situation: no format specified; IEEE format specified; or ARM

>> Alternate format specified.

>>

>> Note that GAS can currently only reflect show build attributes that

>> affect the whole file, so switching during assembly is a little

>> dubious as things stand.

>>

>>

>> R.

>>

>>

>>> Thanks,

>>> Barney

>>>

>>> gas/ChangeLog:

>>>

>>> 2019-07-11  Barnaby Wilks<barnaby.wilks@arm.com>

>>>

>>>      * config/tc-arm.c (md_atof): Set precision for float16 type.

>>>      (enum fp_16bit_format): Add enum to represent the 2 float16

>>> encodings.

>>>      (arm_is_largest_exponent_ok): Check for whether to encode with

>>> the IEEE or alternative

>>>      format.

>>>      * config/tc-arm.h (TC_LARGEST_EXPONENT_IS_NORMAL): Macro that

>>> expands to

>>>      arm_is_largest_exponent_ok.

>>>      (arm_is_largest_exponent_ok): Add prototype for

>>> arm_is_largest_exponent_ok function.

>>>      * testsuite/gas/arm/float16-bad.d: New test.

>>>      * testsuite/gas/arm/float16-bad.l: New test.

>>>      * testsuite/gas/arm/float16-bad.s: New test.

>>>      * testsuite/gas/arm/float16-be.d: New test.

>>>      * testsuite/gas/arm/float16-be.s: New test.

>>>      * testsuite/gas/arm/float16-le.d: New test.

>>>      * testsuite/gas/arm/float16-le.s: New test.

>>>
Richard Earnshaw (lists) July 17, 2019, 3:29 p.m. | #5
On 16/07/2019 02:59, Tamar Christina wrote:
> 

> Introducing a new directive for this seems counter intuitive to me. Particularly you open up some room for user error to happen more easily especially with inline assembly.


I expect the main usecase for this to be completely hand-written 
assembly.  GCC never outputs any .float type directives but translates 
the values it needs directly into the appropriate decimal constants for 
the encoded values.

> 

> You also then have to Orchestrate gcc to emit these as well in order for the file to be logically consistent with the command line options the user specified. If this is a directive gcc has to emit it as well.


No, see above.

> 

> Lastly it also duplicates information. Now the user has two directives to set when using fp16 in an arm assembly file and also opens up the weird possibility to have your built attribute be different from the "encoding type" directive which is a bit nonsensical.


No, it doesn't.  We can get gas to add the relevant build attributes 
when generating the output, if needed based on what directives the user 
actually put into their code (and whether or not they made use of the 
controlling option).  So no more duplication than we have for, say, .cpu 
or .arch.

> 

> Personally I would say If you're really keen on doing this that I'd much rather have either two float16 directives or for the float16 directive to take an optional "format" specifier rather than commandline options which would complicate support in gcc.

> 

> The fact that some platforms like PE don't support built attribute aren't an issue, as those platforms already wouldn't be able to switch formats and be stuck at the "default" one. In fact do we even support fp16 on these non-elf platforms.


It is an issue.  The attributes are stored in elf-specific extensions 
for the BFD.  They don't exist in COFF.  Furthermore, coff users simply 
don't expect to do this in their assembly code.

Finally, build attributes are pretty non-intuitive in their encoding. 
Expecting users to understand the value system is an insane idea.

R.

> 

> Regards,

> Tamar

> 

> ________________________________________

> From: binutils-owner@sourceware.org <binutils-owner@sourceware.org> on behalf of Richard Earnshaw (lists) <Richard.Earnshaw@arm.com>

> Sent: Monday, July 15, 2019 5:11:25 PM

> To: Barnaby Wilks; binutils@sourceware.org

> Cc: nd; nickc@redhat.com; Ramana Radhakrishnan

> Subject: Re: [PATCH][binutils][Arm][2/3] Add support for float16 (IEEE and Alternative formats) for Arm backend.

> 

> 

> 

> On 15/07/2019 16:44, Barnaby Wilks wrote:

>> Hi Richard,

>>

>> Yep agreed, a dedicated directive would make more sense really - originally I did have something

>> along those lines (.ieee_fp16_format/.alternative_fp16_format directives for switching between formats), but then

>> changed upon finding a EABI attribute for the same thing, and seeing that was how GCC did it.

>> Like you say though, for files that contain a mix of float16's in both IEEE and Alternative formats what would be the

>> EABI attribute for that be?

>>

>> This could be solved by just restricting to one format (in which

>> case a command line option may make more sense), or by inventing

>> a new EABI attribute? (I'm don't really know much about that, so have no idea if it's feasible).

>>

> 

> GCC already has the command-line option

> -mfp16-format=(none|ieee|alternative).  I'd suggest we have the same,

> and have an assembly attribute directive with a similar style.

> 

> For the directive, however, the default can be a little more lax: I

> think the assembler should start in a mode where the format is

> 'tentatively ieee' format.  Then, if a .float16 appears with no format

> override, we'd make that an explicit format selection.  At the end of

> assembly, when then generating build attributes (if doing that

> automatically, we'd update the build attributes if the format is at that

> point explicit.

> 

> The tentative nature is important to avoid changing behaviour for

> existing files: we don't want them to start writing out additional build

> attributes that they did not generate previously, however, ieee format

> is far more common than than alternative format, so requiring users to

> always specify this before ever using .float16 would be a little awkward.

> 

> R.

> 

>> Regards,

>>

>> Barney

>>

>> On 7/15/19 10:16 AM, Richard Earnshaw (lists) wrote:

>>>

>>>

>>> On 11/07/2019 16:26, Barnaby Wilks wrote:

>>>> Hello,

>>>>

>>>> This is part of a patch series that implements a directive for

>>>> assembling 16-bit floating point constants for Arm and AArch64.

>>>>

>>>> This patch implements the float16 directive for both the IEEE 754

>>>> format and the Arm alternative format for the

>>>> Arm backend >

>>>> The syntax of the directive is:

>>>> .float16 <0-n decimal numbers>

>>>> e.g.

>>>> .float16 12.0

>>>> .float16 0.23, 433.1, 0.06

>>>>

>>>> The Arm alternative format is almost identical to the IEEE 754

>>>> format, except that it doesn't

>>>> encode for NaNs or Infinity (instead an exponent of 0x1F represents a

>>>> normalized number in the range

>>>> 65536 to 131008).

>>>>

>>>> The alternative format is documented in the reference manual:

>>>> https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf?_ga=2.72318806.49764181.1561632697-999473562.1560847439

>>>>

>>>>

>>>> Which format is used is controlled by the

>>>> .eabi_attribute Tag_ABI_FP_16bit_format, <...>

>>>> directive, where if

>>>> <...> = 1 then use the IEEE 754 half-precision format else if

>>>> <...> = 2 then use the Arm alternative format

>>>>

>>>> Added testcases to verify the correct encoding for both formats (for

>>>> both big and little endian targets),

>>>> as well as tests verifying that warnings are thrown if trying to

>>>> encode NaN or Infinity when using

>>>> the Arm alternative format.

>>>> The encodings have been cross referenced with GCC's encoding for

>>>> __fp16 types to ensure consistency.

>>>>

>>>> Cross compiled and regtested on arm-none-eabi and

>>>> arm-none-linux-gnueabihf

>>>>

>>>> I don't have write access, so if it's OK then could someone commit on

>>>> my behalf?

>>>>

>>>

>>> Hi Barney,

>>>

>>> thanks for the patch.

>>>

>>> I'm not sure that using the build attributes to control selection of

>>> the format is the best idea.  Firstly, build attributes are not

>>> available when not assembling for ELF (we have PE-coff support in the

>>> assembler as well); secondly, build attributes should reflect what was

>>> placed in the assembly file, not control what goes into it.  So this

>>> is a case of the coach before the horse.

>>>

>>> I think, if we want to support the Arm alternate FP format in GAS at

>>> all, we need either a new command line option, or a new directive (or

>>> possibly both).  Then the code in BFD that does automatic

>>> build-attribute selection should be updated to reflect the tri-state

>>> situation: no format specified; IEEE format specified; or ARM

>>> Alternate format specified.

>>>

>>> Note that GAS can currently only reflect show build attributes that

>>> affect the whole file, so switching during assembly is a little

>>> dubious as things stand.

>>>

>>>

>>> R.

>>>

>>>

>>>> Thanks,

>>>> Barney

>>>>

>>>> gas/ChangeLog:

>>>>

>>>> 2019-07-11  Barnaby Wilks<barnaby.wilks@arm.com>

>>>>

>>>>       * config/tc-arm.c (md_atof): Set precision for float16 type.

>>>>       (enum fp_16bit_format): Add enum to represent the 2 float16

>>>> encodings.

>>>>       (arm_is_largest_exponent_ok): Check for whether to encode with

>>>> the IEEE or alternative

>>>>       format.

>>>>       * config/tc-arm.h (TC_LARGEST_EXPONENT_IS_NORMAL): Macro that

>>>> expands to

>>>>       arm_is_largest_exponent_ok.

>>>>       (arm_is_largest_exponent_ok): Add prototype for

>>>> arm_is_largest_exponent_ok function.

>>>>       * testsuite/gas/arm/float16-bad.d: New test.

>>>>       * testsuite/gas/arm/float16-bad.l: New test.

>>>>       * testsuite/gas/arm/float16-bad.s: New test.

>>>>       * testsuite/gas/arm/float16-be.d: New test.

>>>>       * testsuite/gas/arm/float16-be.s: New test.

>>>>       * testsuite/gas/arm/float16-le.d: New test.

>>>>       * testsuite/gas/arm/float16-le.s: New test.

>>>>
Barnaby Wilks Aug. 8, 2019, 4:07 p.m. | #6
Hello,

This is a reworked version of the original patch (https://sourceware.org/ml/binutils/2019-07/msg00116.html) - now the format
used to encode the float16's is controlled by the .float16_format directive and a -mfp16-format option instead of being controlled
by the Tag_ABI_FP_16bit_format EABI attribute.

This is part of a patch series that implements a directive for assembling 16-bit floating point constants for Arm and AArch64.

This patch implements the float16 directive for both the IEEE 754 format and the Arm alternative format for the
Arm backend.

The syntax of the directive is:
.float16 <0-n decimal numbers>
e.g.
.float16 12.0
.float16 0.23, 433.1, 0.06

The Arm alternative format is almost identical to the IEEE 754 format, except that it doesn't
encode for NaNs or Infinity (instead an exponent of 0x1F represents a normalized number in the range
65536 to 131008).

The alternative format is documented in the reference manual:
https://static.docs.arm.com/ddi0487/db/DDI0487D_b_armv8_arm.pdf?_ga=2.72318806.49764181.1561632697-999473562.1560847439

Which format is used is controlled by the
.float16_format <format>
directive, where if
<format> = ieee, then use the IEEE 754 half-precision format else if
<format> = alternative, then use the Arm alternative format

Or the format can be set on the command line via the -mfp16-format option that has a similar syntax.
-mfp16-format=<ieee|alternative>. This also fixes the format and it cannot be changed by any directives.

Once the format has been set (either by the command line option or a directive) it cannot be changed,
and any attempts to change it (i.e. with the float16_format directive) will result in a warning and the
line being ignored.

For ELF targets the appropriate EABI attribute will be written out at the end of assembling
if the format has been explicitly specified. If no format has been explicitly specified then no
EABI attributes will be written.

If the format is not explicitly specified then any float16 directives are encoding using the IEEE 754-2008
format by default until the format is fixed or changed with the float16_format directive.

Added testcases to verify the correct encoding for both formats (for both big and little endian targets),
as well as tests verifying that warnings are thrown if trying to encode NaN or Infinity when using
the Arm alternative format. Tests verifying that trying to set different formats is as expected (i.e.
only use the first specified format) and tests to verify that (for ELF targets) EABI attributes are written
(or not written) correctly.
The encodings have been cross referenced with GCC's encoding for __fp16 types to ensure consistency.

Cross compiled and regtested on arm-none-eabi and arm-none-linux-gnueabihf

I don't have write access, so if it's OK then could someone commit on my behalf?

Thanks,
Barney

gas/ChangeLog:

2019-08-29  Barnaby Wilks<barnaby.wilks@arm.com>

	* config/tc-arm.c (enum fp_16bit_format): Add enum to represent the 2 float16 encodings.
	(md_atof): Set precision for float16 type.
	(arm_is_largest_exponent_ok): Check for whether to encode with the IEEE or alternative
	format.
	(set_fp16_format): Parse a float16_format directive.
	(arm_parse_fp16_opt): Parse the fp16-format command line option.
	(aeabi_set_public_attributes): For ELF encode the FP16 format EABI attribute.
	* config/tc-arm.h (TC_LARGEST_EXPONENT_IS_NORMAL): Macro that expands to
	arm_is_largest_exponent_ok.
	(arm_is_largest_exponent_ok): Add prototype for arm_is_largest_exponent_ok function.
	* doc/c-arm.texi: Add documentation for .float16, .float16_format and -mfp16-format=
	* testsuite/gas/arm/float16-bad.d: New test.
	* testsuite/gas/arm/float16-bad.l: New test.
	* testsuite/gas/arm/float16-bad.s: New test.
	* testsuite/gas/arm/float16-be.d: New test.
	* testsuite/gas/arm/float16-format-bad.d: New test.
	* testsuite/gas/arm/float16-format-bad.l: New test.
	* testsuite/gas/arm/float16-format-bad.s: New test.
	* testsuite/gas/arm/float16-format-opt-bad.d: New test.
	* testsuite/gas/arm/float16-format-opt-bad.l: New test.
	* testsuite/gas/arm/float16-le.d: New test.
	* testsuite/gas/arm/float16.s: New test.
	* testsuite/gas/arm/float16-eabi-alternative-format.d: New test.
	* testsuite/gas/arm/float16-eabi-ieee-format.d: New test.
	* testsuite/gas/arm/float16-eabi-no-format.d: New test.
	* testsuite/gas/arm/float16-eabi.s: New test.
diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h
index 39cc9680b96524c730c15fff1af22b180b9c70d1..8a73bebe6c5b5a027242d02f18b6d51273abcacb 100644
--- a/gas/config/tc-arm.h
+++ b/gas/config/tc-arm.h
@@ -385,3 +385,7 @@ extern char arm_line_separator_chars[];
 
 #define TC_EQUAL_IN_INSN(c, s) arm_tc_equal_in_insn ((c), (s))
 extern bfd_boolean arm_tc_equal_in_insn (int, char *);
+
+#define TC_LARGEST_EXPONENT_IS_NORMAL(PRECISION) \
+	arm_is_largest_exponent_ok ((PRECISION))
+int arm_is_largest_exponent_ok (int precision);
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index f7bebc1b5a40ac9b9702e8963240b45d5c91d6a1..714121b0c2b4705904ecf3700beffc9b6d6622db 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -1037,7 +1037,7 @@ const char EXP_CHARS[] = "eE";
 /* As in 0f12.456  */
 /* or	 0d1.2345e12  */
 
-const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+const char FLT_CHARS[] = "rRsSfFdDxXeEpPHh";
 
 /* Prefix characters that indicate the start of an immediate
    value.  */
@@ -1047,6 +1047,16 @@ const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
 
 #define skip_whitespace(str)  do { if (*(str) == ' ') ++(str); } while (0)
 
+enum fp_16bit_format
+{
+  ARM_FP16_FORMAT_IEEE		= 0x1,
+  ARM_FP16_FORMAT_ALTERNATIVE	= 0x2,
+  ARM_FP16_FORMAT_DEFAULT	= 0x3
+};
+
+static enum fp_16bit_format fp16_format = ARM_FP16_FORMAT_DEFAULT;
+
+
 static inline int
 skip_past_char (char ** str, char c)
 {
@@ -1188,6 +1198,11 @@ md_atof (int type, char * litP, int * sizeP)
 
   switch (type)
     {
+    case 'H':
+    case 'h':
+      prec = 1;
+      break;
+
     case 'f':
     case 'F':
     case 's':
@@ -4925,6 +4940,55 @@ pe_directive_secrel (int dummy ATTRIBUTE_UNUSED)
 }
 #endif /* TE_PE */
 
+int
+arm_is_largest_exponent_ok (int precision)
+{
+  /* precision == 1 ensures that this will only return
+     true for 16 bit floats.  */
+  return (precision == 1) && (fp16_format == ARM_FP16_FORMAT_ALTERNATIVE);
+}
+
+static void
+set_fp16_format (int dummy ATTRIBUTE_UNUSED)
+{
+  char saved_char;
+  char* name;
+  enum fp_16bit_format new_format;
+
+  new_format = ARM_FP16_FORMAT_DEFAULT;
+
+  name = input_line_pointer;
+  while (*input_line_pointer && !ISSPACE (*input_line_pointer))
+    input_line_pointer++;
+
+  saved_char = *input_line_pointer;
+  *input_line_pointer = 0;
+
+  if (strcasecmp (name, "ieee") == 0)
+    new_format = ARM_FP16_FORMAT_IEEE;
+  else if (strcasecmp (name, "alternative") == 0)
+    new_format = ARM_FP16_FORMAT_ALTERNATIVE;
+  else
+    {
+      as_bad (_("unrecognised float16 format \"%s\""), name);
+      goto cleanup;
+    }
+
+  /* Only set fp16_format if it is still the default (aka not already
+     been set yet).  */
+  if (fp16_format == ARM_FP16_FORMAT_DEFAULT)
+    fp16_format = new_format;
+  else
+    {
+      if (new_format != fp16_format)
+	as_warn (_("float16 format cannot be set more than once, ignoring."));
+    }
+
+cleanup:
+  *input_line_pointer = saved_char;
+  ignore_rest_of_line ();
+}
+
 /* This table describes all the machine specific pseudo-ops the assembler
    has to support.  The fields are:
      pseudo-op name without dot
@@ -5002,9 +5066,12 @@ const pseudo_typeS md_pseudo_table[] =
   {"asmfunc",      s_ccs_asmfunc,    0},
   {"endasmfunc",   s_ccs_endasmfunc, 0},
 
+  {"float16", float_cons, 'h' },
+  {"float16_format", set_fp16_format, 0 },
+
   { 0, 0, 0 }
 };
-
+
 /* Parser functions used exclusively in instruction operands.  */
 
 /* Generic immediate-value read function for use in insn parsing.
@@ -31239,6 +31306,22 @@ arm_parse_extension (const char *str, const arm_feature_set *opt_set,
   return TRUE;
 }
 
+static bfd_boolean
+arm_parse_fp16_opt (const char *str)
+{
+  if (strcasecmp (str, "ieee") == 0)
+    fp16_format = ARM_FP16_FORMAT_IEEE;
+  else if (strcasecmp (str, "alternative") == 0)
+    fp16_format = ARM_FP16_FORMAT_ALTERNATIVE;
+  else
+    {
+      as_bad (_("unrecognised float16 format \"%s\""), str);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 static bfd_boolean
 arm_parse_cpu (const char *str)
 {
@@ -31430,6 +31513,12 @@ struct arm_long_option_table arm_long_opts[] =
    arm_parse_it_mode, NULL},
   {"mccs", N_("\t\t\t  TI CodeComposer Studio syntax compatibility mode"),
    arm_ccs_mode, NULL},
+  {"mfp16-format=",
+   N_("[ieee|alternative]\n\
+                          set the encoding for half precision floating point "
+			  "numbers to IEEE\n\
+                          or Arm alternative format."),
+   arm_parse_fp16_opt, NULL },
   {NULL, NULL, 0, NULL}
 };
 
@@ -32011,6 +32100,9 @@ aeabi_set_public_attributes (void)
     virt_sec |= 2;
   if (virt_sec != 0)
     aeabi_set_attribute_int (Tag_Virtualization_use, virt_sec);
+
+  if (fp16_format != ARM_FP16_FORMAT_DEFAULT)
+    aeabi_set_attribute_int (Tag_ABI_FP_16bit_format, fp16_format);
 }
 
 /* Post relaxation hook.  Recompute ARM attributes now that relaxation is
diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi
index fa642177b2c3b7605feecce37d8b4d21fb1a1e0a..481eddf0cfe6a4483717fab9dd21b3c185340fc0 100644
--- a/gas/doc/c-arm.texi
+++ b/gas/doc/c-arm.texi
@@ -493,6 +493,22 @@ The default is dependent on the processor selected.  For Architecture 5 or
 later, the default is to assemble for VFP instructions; for earlier
 architectures the default is to assemble for FPA instructions.
 
+@cindex @code{-mfp16-format=} command-line option
+@item -mfp16-format=@var{format}
+This option specifies the half-precision floating point format to use
+when assembling floating point numbers emitted by the @code{.float16}
+directive.
+The following format options are recognized:
+@code{ieee},
+@code{alternative}.
+If @code{ieee} is specified then the IEEE 754-2008 half-precision floating
+point format is used, if @code{alternative} is specified then the Arm
+alternative half-precision format is used. If this option is set on the
+command line then the format is fixed and cannot be changed with
+the @code{float16_format} directive. If this value is not set then
+the IEEE 754-2008 format is used until the format is explicitly set with
+the @code{float16_format} directive.
+
 @cindex @code{-mthumb} command-line option, ARM
 @item -mthumb
 This option specifies that the assembler should start assembling Thumb
@@ -934,6 +950,23 @@ or ABIs.
 
 @c FFFFFFFFFFFFFFFFFFFFFFFFFF
 
+@cindex @code{.float16} directive, ARM
+@item .float16 @var{value [,...,value_n]}
+Place the half precision floating point representation of one or more
+floating-point values into the current section. The exact format of the
+encoding is specified by @code{.float16_format}. If the format has not
+been explicitly set yet (either via the @code{.float16_format} directive or
+the command line option) then the IEEE 754-2008 format is used.
+
+@cindex @code{.float16_format} directive, ARM
+@item .float16_format @var{format}
+Set the format to use when encoding float16 values emitted by
+the @code{.float16} directive.
+Once the format has been set it cannot be changed.
+@code{format} should be one of the following: @code{ieee} (encode in
+the IEEE 754-2008 half precision format) or @code{alternative} (encode in
+the Arm alternative half precision format).
+
 @anchor{arm_fnend}
 @cindex @code{.fnend} directive, ARM
 @item .fnend
diff --git a/gas/testsuite/gas/arm/float16-bad.d b/gas/testsuite/gas/arm/float16-bad.d
new file mode 100644
index 0000000000000000000000000000000000000000..8eac0af5cbb8671e61f18939d723599db4f948a6
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-bad.d
@@ -0,0 +1,3 @@
+# name: Invalid float16 literals (IEEE 754 & Alternative)
+# source: float16-bad.s
+# error_output: float16-bad.l
diff --git a/gas/testsuite/gas/arm/float16-bad.l b/gas/testsuite/gas/arm/float16-bad.l
new file mode 100644
index 0000000000000000000000000000000000000000..83978b7571cac2644379d3ca1896f609ba87ce30
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-bad.l
@@ -0,0 +1,10 @@
+[^:]*: Assembler messages:
+[^:]*:2: Error: cannot create floating-point number
+[^:]*:3: Error: cannot create floating-point number
+[^:]*:4: Error: cannot create floating-point number
+[^:]*:7: Warning: NaNs are not supported by this target
+[^:]*:8: Warning: NaNs are not supported by this target
+[^:]*:9: Warning: NaNs are not supported by this target
+[^:]*:11: Warning: Infinities are not supported by this target
+[^:]*:12: Warning: Infinities are not supported by this target
+[^:]*:13: Warning: Infinities are not supported by this target
diff --git a/gas/testsuite/gas/arm/float16-bad.s b/gas/testsuite/gas/arm/float16-bad.s
new file mode 100644
index 0000000000000000000000000000000000000000..6f09073b83ce90e0d342ac0364aba1813445f97b
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-bad.s
@@ -0,0 +1,13 @@
+.data
+	.float16 9999999999999.0
+	.float16 -999999999999.0
+	.float16 131008.0
+
+.float16_format alternative
+	.float16 NaN
+	.float16 -NaN
+	.float16 +NaN
+
+	.float16 Inf
+	.float16 -Inf
+	.float16 +Inf
diff --git a/gas/testsuite/gas/arm/float16-be.d b/gas/testsuite/gas/arm/float16-be.d
new file mode 100644
index 0000000000000000000000000000000000000000..e31d9fbf432ca7e8f30896acb90184e4ebe949cd
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-be.d
@@ -0,0 +1,11 @@
+# name: Big endian float16 literals (IEEE 754 & Alternative)
+# source: float16.s
+# objdump: -s --section=.data
+# as: -mbig-endian
+
+.*: +file format .*arm.*
+
+Contents of section \.data:
+ 0000 4a002fdf 1c197bff 000103ff 04003c00.*
+ 0010 3c017fff 7c00fc00 00008000 bc00bbe7.*
+ 0020 fbff4200 4a00603e 38567fff ffff7204.*
diff --git a/gas/testsuite/gas/arm/float16-eabi-alternative-format.d b/gas/testsuite/gas/arm/float16-eabi-alternative-format.d
new file mode 100644
index 0000000000000000000000000000000000000000..0729a5ccc215dfd38955b0e7d78d17c78155c0f7
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-eabi-alternative-format.d
@@ -0,0 +1,10 @@
+# name: Tag_ABI_FP_16bit_format EABI attribute written for Arm alternative format.
+# readelf: -A
+# notarget: *-*pe *-*-wince
+# source: float16-eabi.s
+# as: -mfp16-format=alternative
+Attribute Section: aeabi
+File Attributes
+  Tag_ARM_ISA_use: Yes
+  Tag_THUMB_ISA_use: Thumb-1
+  Tag_ABI_FP_16bit_format: Alternative Format
diff --git a/gas/testsuite/gas/arm/float16-eabi-ieee-format.d b/gas/testsuite/gas/arm/float16-eabi-ieee-format.d
new file mode 100644
index 0000000000000000000000000000000000000000..d02ed73fb00a76b4e0b2adf87e409bad5de7157f
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-eabi-ieee-format.d
@@ -0,0 +1,10 @@
+# name: Tag_ABI_FP_16bit_format written for IEEE float16 format.
+# readelf: -A
+# notarget: *-*pe *-*wince
+# source: float16-eabi.s
+# as: -mfp16-format=ieee
+Attribute Section: aeabi
+File Attributes
+  Tag_ARM_ISA_use: Yes
+  Tag_THUMB_ISA_use: Thumb-1
+  Tag_ABI_FP_16bit_format: IEEE 754
diff --git a/gas/testsuite/gas/arm/float16-eabi-no-format.d b/gas/testsuite/gas/arm/float16-eabi-no-format.d
new file mode 100644
index 0000000000000000000000000000000000000000..0d54f844218dfae227ace986aa11a92cc89e7161
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-eabi-no-format.d
@@ -0,0 +1,8 @@
+# name: Tag_ABI_FP_16bit_format EABI attribute not written when format not specified
+# readelf: -A
+# notarget: *-*pe *-*-wince
+# source: float16-eabi.s
+Attribute Section: aeabi
+File Attributes
+  Tag_ARM_ISA_use: Yes
+  Tag_THUMB_ISA_use: Thumb-1
diff --git a/gas/testsuite/gas/arm/float16-eabi.s b/gas/testsuite/gas/arm/float16-eabi.s
new file mode 100644
index 0000000000000000000000000000000000000000..91836378efca128e0add894e150304a75676565b
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-eabi.s
@@ -0,0 +1,2 @@
+.float16 10.1
+.float16 0.5
diff --git a/gas/testsuite/gas/arm/float16-format-bad.d b/gas/testsuite/gas/arm/float16-format-bad.d
new file mode 100644
index 0000000000000000000000000000000000000000..38da287a1a8064e8ad67cc192644b7f08968f0da
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-format-bad.d
@@ -0,0 +1,3 @@
+# name: Invalid float16 formats
+# source: float16-format-bad.s
+# error_output: float16-format-bad.l
diff --git a/gas/testsuite/gas/arm/float16-format-bad.l b/gas/testsuite/gas/arm/float16-format-bad.l
new file mode 100644
index 0000000000000000000000000000000000000000..1f2356fcf1304e0b5ac021fc93a23a84affe2b13
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-format-bad.l
@@ -0,0 +1,5 @@
+[^:]*: Assembler messages:
+[^:]*:2: Warning: float16 format cannot be set more than once, ignoring.
+[^:]*:3: Error: unrecognised float16 format "monkeys"
+[^:]*:4: Error: unrecognised float16 format "..."
+[^:]*:5: Error: unrecognised float16 format ""
diff --git a/gas/testsuite/gas/arm/float16-format-bad.s b/gas/testsuite/gas/arm/float16-format-bad.s
new file mode 100644
index 0000000000000000000000000000000000000000..69e99e5496efd8b6483650dca83e6b5a3471c5a3
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-format-bad.s
@@ -0,0 +1,5 @@
+.float16_format ieee
+.float16_format alternative
+.float16_format monkeys
+.float16_format ...
+.float16_format
diff --git a/gas/testsuite/gas/arm/float16-format-opt-bad.d b/gas/testsuite/gas/arm/float16-format-opt-bad.d
new file mode 100644
index 0000000000000000000000000000000000000000..861125800da501da31681b5fd4621a76eca1585f
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-format-opt-bad.d
@@ -0,0 +1,4 @@
+# name: Invalid combination of command line arguments and directives
+# source: float16.s
+# error_output: float16-format-opt-bad.l
+# as: -mfp16-format=ieee
diff --git a/gas/testsuite/gas/arm/float16-format-opt-bad.l b/gas/testsuite/gas/arm/float16-format-opt-bad.l
new file mode 100644
index 0000000000000000000000000000000000000000..6743c93ba6953f46c86cbff2e12ba867ca7b689a
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-format-opt-bad.l
@@ -0,0 +1,4 @@
+[^:]*: Assembler messages:
+[^:]*:21: Warning: float16 format cannot be set more than once, ignoring.
+[^:]*:23: Error: cannot create floating-point number
+[^:]*:24: Error: cannot create floating-point number
diff --git a/gas/testsuite/gas/arm/float16-le.d b/gas/testsuite/gas/arm/float16-le.d
new file mode 100644
index 0000000000000000000000000000000000000000..c1fe7c20dc6dfe1dd6f4e27d9fa2186676488c59
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-le.d
@@ -0,0 +1,11 @@
+# name: Little endian float16 literals (IEEE 754 & Alternative)
+# source: float16.s
+# objdump: -s --section=.data
+# as: -mlittle-endian
+
+.*: +file format .*arm.*
+
+Contents of section \.data:
+ 0000 004adf2f 191cff7b 0100ff03 0004003c.*
+ 0010 013cff7f 007c00fc 00000080 00bce7bb.*
+ 0020 fffb0042 004a3e60 5638ff7f ffff0472.*
diff --git a/gas/testsuite/gas/arm/float16.s b/gas/testsuite/gas/arm/float16.s
new file mode 100644
index 0000000000000000000000000000000000000000..3a295c593c59325fc85a20a9d37ac898a058588e
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16.s
@@ -0,0 +1,25 @@
+.data
+	.float16 12.0
+	.float16 0.123
+	.float16 0.004
+	.float16 65504
+	.float16 5.9605e-8
+	.float16 6.0976e-5
+	.float16 6.1035e-5
+	.float16 1
+	.float16 1.001
+	.float16 NaN
+	.float16 +Inf
+	.float16 -Inf
+	.float16 +0
+	.float16 -0
+	.float16 -1
+	.float16 -0.98765
+	.float16 -65504
+	.float16 3.0, 12.0, 543.123
+
+.float16_format alternative
+	.float16 0.542
+	.float16 131008.0
+	.float16 -131008.0
+	.float16 12323.1234
Nick Clifton Aug. 9, 2019, 12:31 p.m. | #7
Hi Barnaby,

> Cross compiled and regtested on arm-none-eabi and arm-none-linux-gnueabihf


Are you sure ?  I am seeing the following new assembler failures when I test the patch:

  FAIL: Invalid float16 literals (IEEE 754 & Alternative)
  FAIL: Big endian float16 literals (IEEE 754 & Alternative)
  FAIL: Tag_ABI_FP_16bit_format EABI attribute written for Arm alternative format.
  FAIL: Tag_ABI_FP_16bit_format written for IEEE float16 format.
  FAIL: Tag_ABI_FP_16bit_format EABI attribute not written when format not specified
  FAIL: Invalid combination of command line arguments and directives
  FAIL: Little endian float16 literals (IEEE 754 & Alternative)

(This is with lots of different configurations of ARM based toolchains).

The problem seems to be the same with all of the tests.  Eg:

  gas/testsuite/gas/arm/float16.s: Assembler messages:
  gas/testsuite/gas/arm/float16.s:2: Error: cannot create floating-point number
  gas/testsuite/gas/arm/float16.s:2: Error: junk at end of line, first unrecognized character is `1'

It looks like the patch is maybe missing a change to atof_ieee.c to handle the 'h'
format maybe ?

Cheers
  Nick
Barnaby Wilks Aug. 9, 2019, 1:11 p.m. | #8
Hi Nick,

On 8/9/19 1:31 PM, Nick Clifton wrote:

> Hi Barnaby,

>

>> Cross compiled and regtested on arm-none-eabi and arm-none-linux-gnueabihf

> Are you sure ?  I am seeing the following new assembler failures when I test the patch:

>

>    FAIL: Invalid float16 literals (IEEE 754 & Alternative)

>    FAIL: Big endian float16 literals (IEEE 754 & Alternative)

>    FAIL: Tag_ABI_FP_16bit_format EABI attribute written for Arm alternative format.

>    FAIL: Tag_ABI_FP_16bit_format written for IEEE float16 format.

>    FAIL: Tag_ABI_FP_16bit_format EABI attribute not written when format not specified

>    FAIL: Invalid combination of command line arguments and directives

>    FAIL: Little endian float16 literals (IEEE 754 & Alternative)

>

> (This is with lots of different configurations of ARM based toolchains).

>

> The problem seems to be the same with all of the tests.  Eg:

>

>    gas/testsuite/gas/arm/float16.s: Assembler messages:

>    gas/testsuite/gas/arm/float16.s:2: Error: cannot create floating-point number

>    gas/testsuite/gas/arm/float16.s:2: Error: junk at end of line, first unrecognized character is `1'

>

> It looks like the patch is maybe missing a change to atof_ieee.c to handle the 'h'

> format maybe ?


Ah yeah, both the Arm and AArch64 patches require the changes to atof_ieee.c in
	[PATCH][binutils][1/3] Generic support for IEEE 754 floating point numbers.
	( https://sourceware.org/ml/binutils/2019-07/msg00115.html )

The generic patch add support for the 'h' format, which is (as you say) needed for this patch to work,
otherwise it will rather unhelpfully error.

Apologies for forgetting to mention this, it would have been a useful thing to point out :)

>

> Cheers

>    Nick


Regards,

Barney
Nick Clifton Aug. 12, 2019, 10:12 a.m. | #9
Hi Barnaby,

> The generic patch add support for the 'h' format, which is (as you say) needed for this patch to work,

> otherwise it will rather unhelpfully error.

> 

> Apologies for forgetting to mention this, it would have been a useful thing to point out :)


Ah - that explains it.  In which case both patches are now approved and applied. :-)

Cheers
  Nick
Alan Modra Aug. 14, 2019, 4:49 a.m. | #10
arm-nto  +FAIL: Little endian float16 literals (IEEE 754 & Alternative)
arm-pe  +FAIL: Little endian float16 literals (IEEE 754 & Alternative)
arm-wince-pe  +FAIL: Little endian float16 literals (IEEE 754 & Alternative)

-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h
index 39cc9680b96524c730c15fff1af22b180b9c70d1..8a73bebe6c5b5a027242d02f18b6d51273abcacb 100644
--- a/gas/config/tc-arm.h
+++ b/gas/config/tc-arm.h
@@ -385,3 +385,7 @@  extern char arm_line_separator_chars[];
 
 #define TC_EQUAL_IN_INSN(c, s) arm_tc_equal_in_insn ((c), (s))
 extern bfd_boolean arm_tc_equal_in_insn (int, char *);
+
+#define TC_LARGEST_EXPONENT_IS_NORMAL(PRECISION) \
+	arm_is_largest_exponent_ok ((PRECISION))
+int arm_is_largest_exponent_ok (int precision);
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index b70028f7c2e31c179196b3c9ea9665fbf4b0159f..6176fea2bb523990d660fbcc39bc12007a459809 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -1037,7 +1037,7 @@  const char EXP_CHARS[] = "eE";
 /* As in 0f12.456  */
 /* or	 0d1.2345e12  */
 
-const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+const char FLT_CHARS[] = "rRsSfFdDxXeEpPHh";
 
 /* Prefix characters that indicate the start of an immediate
    value.  */
@@ -1188,6 +1188,11 @@  md_atof (int type, char * litP, int * sizeP)
 
   switch (type)
     {
+    case 'H':
+    case 'h':
+      prec = 1;
+      break;
+
     case 'f':
     case 'F':
     case 's':
@@ -4925,6 +4930,21 @@  pe_directive_secrel (int dummy ATTRIBUTE_UNUSED)
 }
 #endif /* TE_PE */
 
+enum fp_16bit_format
+{
+  ARM_FP16_FORMAT_IEEE        = 0x1,
+  ARM_FP16_FORMAT_ALTERNATIVE = 0x2
+};
+
+int arm_is_largest_exponent_ok (int precision)
+{
+  const int fp16_format = bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
+		  Tag_ABI_FP_16bit_format);
+
+  /* precision == 1 ensures that this will only return true for 16 bit floats. */
+  return (precision == 1) && (fp16_format == ARM_FP16_FORMAT_ALTERNATIVE);
+}
+
 /* This table describes all the machine specific pseudo-ops the assembler
    has to support.  The fields are:
      pseudo-op name without dot
@@ -5002,9 +5022,11 @@  const pseudo_typeS md_pseudo_table[] =
   {"asmfunc",      s_ccs_asmfunc,    0},
   {"endasmfunc",   s_ccs_endasmfunc, 0},
 
+  {"float16", float_cons, 'h'},
+
   { 0, 0, 0 }
 };
-
+
 /* Parser functions used exclusively in instruction operands.  */
 
 /* Generic immediate-value read function for use in insn parsing.
diff --git a/gas/testsuite/gas/arm/float16-bad.d b/gas/testsuite/gas/arm/float16-bad.d
new file mode 100644
index 0000000000000000000000000000000000000000..8eac0af5cbb8671e61f18939d723599db4f948a6
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-bad.d
@@ -0,0 +1,3 @@ 
+# name: Invalid float16 literals (IEEE 754 & Alternative)
+# source: float16-bad.s
+# error_output: float16-bad.l
diff --git a/gas/testsuite/gas/arm/float16-bad.l b/gas/testsuite/gas/arm/float16-bad.l
new file mode 100644
index 0000000000000000000000000000000000000000..83978b7571cac2644379d3ca1896f609ba87ce30
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-bad.l
@@ -0,0 +1,10 @@ 
+[^:]*: Assembler messages:
+[^:]*:2: Error: cannot create floating-point number
+[^:]*:3: Error: cannot create floating-point number
+[^:]*:4: Error: cannot create floating-point number
+[^:]*:7: Warning: NaNs are not supported by this target
+[^:]*:8: Warning: NaNs are not supported by this target
+[^:]*:9: Warning: NaNs are not supported by this target
+[^:]*:11: Warning: Infinities are not supported by this target
+[^:]*:12: Warning: Infinities are not supported by this target
+[^:]*:13: Warning: Infinities are not supported by this target
diff --git a/gas/testsuite/gas/arm/float16-bad.s b/gas/testsuite/gas/arm/float16-bad.s
new file mode 100644
index 0000000000000000000000000000000000000000..cb97c605b8c7dd5bffbf4d13ced71d22124202ed
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-bad.s
@@ -0,0 +1,13 @@ 
+.data
+	.float16 9999999999999.0
+	.float16 -999999999999.0
+	.float16 131008.0
+
+.eabi_attribute Tag_ABI_FP_16bit_format, 2
+	.float16 NaN
+	.float16 -NaN
+	.float16 +NaN
+
+	.float16 Inf
+	.float16 -Inf
+	.float16 +Inf
diff --git a/gas/testsuite/gas/arm/float16-be.d b/gas/testsuite/gas/arm/float16-be.d
new file mode 100644
index 0000000000000000000000000000000000000000..214c7f7a6ceee423ee505ac38eada9f6c9cf0fbf
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-be.d
@@ -0,0 +1,12 @@ 
+# name: Big endian float16 literals (IEEE 754 & Alternative)
+# source: float16-be.s
+# objdump: -s --section=.data
+# as: -mbig-endian
+
+.*: +file format .*arm.*
+
+Contents of section \.data:
+ 0000 4a002fdf 1c197bff 000103ff 04003c00.*
+ 0010 3c017fff 7c00fc00 00008000 bc00bbe7.*
+ 0020 fbff4200 4a00603e 38567fff ffff7204.*
+ 0030 7fff7c00.*
diff --git a/gas/testsuite/gas/arm/float16-be.s b/gas/testsuite/gas/arm/float16-be.s
new file mode 100644
index 0000000000000000000000000000000000000000..0cdecbd7c971313e5963a6e158041400a899da8a
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-be.s
@@ -0,0 +1,29 @@ 
+.data
+	.float16 12.0
+	.float16 0.123
+	.float16 0.004
+	.float16 65504
+	.float16 5.9605e-8
+	.float16 6.0976e-5
+	.float16 6.1035e-5
+	.float16 1
+	.float16 1.001
+	.float16 NaN
+	.float16 +Inf
+	.float16 -Inf
+	.float16 +0
+	.float16 -0
+	.float16 -1
+	.float16 -0.98765
+	.float16 -65504
+	.float16 3.0, 12.0, 543.123
+
+.eabi_attribute Tag_ABI_FP_16bit_format, 2
+	.float16 0.542
+	.float16 131008.0
+	.float16 -131008.0
+	.float16 12323.1234
+
+.eabi_attribute Tag_ABI_FP_16bit_format, 1
+	.float16 NaN
+	.float16 Inf
diff --git a/gas/testsuite/gas/arm/float16-le.d b/gas/testsuite/gas/arm/float16-le.d
new file mode 100644
index 0000000000000000000000000000000000000000..0efb068c5b3a4f5deed3b5ecc9b9aceb08561163
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-le.d
@@ -0,0 +1,12 @@ 
+# name: Little endian float16 literals (IEEE 754 & Alternative)
+# source: float16-le.s
+# objdump: -s --section=.data
+# as: -mlittle-endian
+
+.*: +file format .*arm.*
+
+Contents of section \.data:
+ 0000 004adf2f 191cff7b 0100ff03 0004003c.*
+ 0010 013cff7f 007c00fc 00000080 00bce7bb.*
+ 0020 fffb0042 004a3e60 5638ff7f ffff0472.*
+ 0030 ff7f007c.*
diff --git a/gas/testsuite/gas/arm/float16-le.s b/gas/testsuite/gas/arm/float16-le.s
new file mode 100644
index 0000000000000000000000000000000000000000..0cdecbd7c971313e5963a6e158041400a899da8a
--- /dev/null
+++ b/gas/testsuite/gas/arm/float16-le.s
@@ -0,0 +1,29 @@ 
+.data
+	.float16 12.0
+	.float16 0.123
+	.float16 0.004
+	.float16 65504
+	.float16 5.9605e-8
+	.float16 6.0976e-5
+	.float16 6.1035e-5
+	.float16 1
+	.float16 1.001
+	.float16 NaN
+	.float16 +Inf
+	.float16 -Inf
+	.float16 +0
+	.float16 -0
+	.float16 -1
+	.float16 -0.98765
+	.float16 -65504
+	.float16 3.0, 12.0, 543.123
+
+.eabi_attribute Tag_ABI_FP_16bit_format, 2
+	.float16 0.542
+	.float16 131008.0
+	.float16 -131008.0
+	.float16 12323.1234
+
+.eabi_attribute Tag_ABI_FP_16bit_format, 1
+	.float16 NaN
+	.float16 Inf