aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog38
-rw-r--r--gas/config/atof-ieee.c37
-rw-r--r--gas/config/tc-arm.c96
-rw-r--r--gas/config/tc-arm.h4
-rw-r--r--gas/doc/c-arm.texi33
-rw-r--r--gas/testsuite/gas/arm/float16-bad.d3
-rw-r--r--gas/testsuite/gas/arm/float16-bad.l10
-rw-r--r--gas/testsuite/gas/arm/float16-bad.s13
-rw-r--r--gas/testsuite/gas/arm/float16-be.d11
-rw-r--r--gas/testsuite/gas/arm/float16-eabi-alternative-format.d10
-rw-r--r--gas/testsuite/gas/arm/float16-eabi-ieee-format.d10
-rw-r--r--gas/testsuite/gas/arm/float16-eabi-no-format.d8
-rw-r--r--gas/testsuite/gas/arm/float16-eabi.s2
-rw-r--r--gas/testsuite/gas/arm/float16-format-bad.d3
-rw-r--r--gas/testsuite/gas/arm/float16-format-bad.l5
-rw-r--r--gas/testsuite/gas/arm/float16-format-bad.s5
-rw-r--r--gas/testsuite/gas/arm/float16-format-opt-bad.d4
-rw-r--r--gas/testsuite/gas/arm/float16-format-opt-bad.l4
-rw-r--r--gas/testsuite/gas/arm/float16-le.d11
-rw-r--r--gas/testsuite/gas/arm/float16.s25
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