diff options
Diffstat (limited to 'gas/config')
-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 |
3 files changed, 129 insertions, 8 deletions
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); |