diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 38 | ||||
-rw-r--r-- | gas/config/atof-ieee.c | 37 | ||||
-rw-r--r-- | gas/config/tc-arm.c | 96 | ||||
-rw-r--r-- | gas/config/tc-arm.h | 4 | ||||
-rw-r--r-- | gas/doc/c-arm.texi | 33 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-bad.d | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-bad.l | 10 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-bad.s | 13 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-be.d | 11 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-eabi-alternative-format.d | 10 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-eabi-ieee-format.d | 10 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-eabi-no-format.d | 8 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-eabi.s | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-format-bad.d | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-format-bad.l | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-format-bad.s | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-format-opt-bad.d | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-format-opt-bad.l | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16-le.d | 11 | ||||
-rw-r--r-- | gas/testsuite/gas/arm/float16.s | 25 |
20 files changed, 324 insertions, 8 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 68c4002..d7e0840 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,41 @@ +2019-08-12 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. + +2019-08-12 Barnaby Wilks <barnaby.wilks@arm.com> + + * 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. + 2019-08-12 Alan Modra <amodra@gmail.com> PR 24851 diff --git a/gas/config/atof-ieee.c b/gas/config/atof-ieee.c index 9bb9e55..944c8a4 100644 --- a/gas/config/atof-ieee.c +++ b/gas/config/atof-ieee.c @@ -26,6 +26,7 @@ extern FLONUM_TYPE generic_floating_point_number; /* Precision in LittleNums. */ /* Don't count the gap in the m68k extended precision format. */ #define MAX_PRECISION 5 +#define H_PRECISION 1 #define F_PRECISION 2 #define D_PRECISION 4 #define X_PRECISION 5 @@ -190,6 +191,12 @@ atof_ieee (char *str, /* Text to convert to binary. */ switch (what_kind) { + case 'h': + case 'H': + precision = H_PRECISION; + exponent_bits = 5; + break; + case 'f': case 'F': case 's': @@ -283,8 +290,13 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) if (generic_floating_point_number.sign == 0) { if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) - as_warn (_("NaNs are not supported by this target\n")); - if (precision == F_PRECISION) + as_warn (_("NaNs are not supported by this target")); + + if (precision == H_PRECISION) + { + words[0] = 0x7fff; + } + else if (precision == F_PRECISION) { words[0] = 0x7fff; words[1] = 0xffff; @@ -322,10 +334,14 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) else if (generic_floating_point_number.sign == 'P') { if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) - as_warn (_("Infinities are not supported by this target\n")); + as_warn (_("Infinities are not supported by this target")); /* +INF: Do the right thing. */ - if (precision == F_PRECISION) + if (precision == H_PRECISION) + { + words[0] = 0x7c00; + } + else if (precision == F_PRECISION) { words[0] = 0x7f80; words[1] = 0; @@ -363,10 +379,14 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) else if (generic_floating_point_number.sign == 'N') { if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) - as_warn (_("Infinities are not supported by this target\n")); + as_warn (_("Infinities are not supported by this target")); /* Negative INF. */ - if (precision == F_PRECISION) + if (precision == H_PRECISION) + { + words[0] = 0xfc00; + } + else if (precision == F_PRECISION) { words[0] = 0xff80; words[1] = 0x0; @@ -721,6 +741,11 @@ ieee_md_atof (int type, { switch (type) { + case 'H': + case 'h': + prec = H_PRECISION; + break; + case 'f': case 'F': case 's': diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index f7bebc1..714121b 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. @@ -31240,6 +31307,22 @@ arm_parse_extension (const char *str, const arm_feature_set *opt_set, } 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) { const struct arm_cpu_option_table *opt; @@ -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/config/tc-arm.h b/gas/config/tc-arm.h index 39cc968..8a73beb 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/doc/c-arm.texi b/gas/doc/c-arm.texi index fa64217..481eddf 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 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 |