From 5312fe52e9ae6fd108f161a271315eb2821246eb Mon Sep 17 00:00:00 2001 From: Barnaby Wilks Date: Mon, 12 Aug 2019 11:08:36 +0100 Subject: Add generic and ARM specific support for half-precision IEEE 754 floating point numbers to the assembler. Half precision floating point numbers will be encoded using the IEEE 754 half precision floating point format - 16 bits in total, 1 for sign, 5 for exponent and 10 bits of mantissa. 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 directive, where if = ieee, then use the IEEE 754 half-precision format else if = 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=. 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. gas * 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. * config/atof-ieee.c (H_PRECISION): Macro for precision of float16 type. (atof_ieee): Set precision and exponent bits for encoding float16 types. (gen_to_words): NaN and Infinity encoding for float16. (ieee_md_atof): Set precision for encoding float16 type. --- gas/testsuite/gas/arm/float16-bad.d | 3 +++ gas/testsuite/gas/arm/float16-bad.l | 10 +++++++++ gas/testsuite/gas/arm/float16-bad.s | 13 +++++++++++ gas/testsuite/gas/arm/float16-be.d | 11 ++++++++++ .../gas/arm/float16-eabi-alternative-format.d | 10 +++++++++ gas/testsuite/gas/arm/float16-eabi-ieee-format.d | 10 +++++++++ gas/testsuite/gas/arm/float16-eabi-no-format.d | 8 +++++++ gas/testsuite/gas/arm/float16-eabi.s | 2 ++ gas/testsuite/gas/arm/float16-format-bad.d | 3 +++ gas/testsuite/gas/arm/float16-format-bad.l | 5 +++++ gas/testsuite/gas/arm/float16-format-bad.s | 5 +++++ gas/testsuite/gas/arm/float16-format-opt-bad.d | 4 ++++ gas/testsuite/gas/arm/float16-format-opt-bad.l | 4 ++++ gas/testsuite/gas/arm/float16-le.d | 11 ++++++++++ gas/testsuite/gas/arm/float16.s | 25 ++++++++++++++++++++++ 15 files changed, 124 insertions(+) create mode 100644 gas/testsuite/gas/arm/float16-bad.d create mode 100644 gas/testsuite/gas/arm/float16-bad.l create mode 100644 gas/testsuite/gas/arm/float16-bad.s create mode 100644 gas/testsuite/gas/arm/float16-be.d create mode 100644 gas/testsuite/gas/arm/float16-eabi-alternative-format.d create mode 100644 gas/testsuite/gas/arm/float16-eabi-ieee-format.d create mode 100644 gas/testsuite/gas/arm/float16-eabi-no-format.d create mode 100644 gas/testsuite/gas/arm/float16-eabi.s create mode 100644 gas/testsuite/gas/arm/float16-format-bad.d create mode 100644 gas/testsuite/gas/arm/float16-format-bad.l create mode 100644 gas/testsuite/gas/arm/float16-format-bad.s create mode 100644 gas/testsuite/gas/arm/float16-format-opt-bad.d create mode 100644 gas/testsuite/gas/arm/float16-format-opt-bad.l create mode 100644 gas/testsuite/gas/arm/float16-le.d create mode 100644 gas/testsuite/gas/arm/float16.s (limited to 'gas/testsuite') diff --git a/gas/testsuite/gas/arm/float16-bad.d b/gas/testsuite/gas/arm/float16-bad.d new file mode 100644 index 0000000..8eac0af --- /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 0000000..83978b7 --- /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 0000000..6f09073 --- /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 0000000..e31d9fb --- /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 0000000..0729a5c --- /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 0000000..d02ed73 --- /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 0000000..0d54f84 --- /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 0000000..9183637 --- /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 0000000..38da287 --- /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 0000000..1f2356f --- /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 0000000..69e99e5 --- /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 0000000..8611258 --- /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 0000000..6743c93 --- /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 0000000..c1fe7c2 --- /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 0000000..3a295c5 --- /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 -- cgit v1.1