aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2021-06-16 08:55:52 +0200
committerJan Beulich <jbeulich@suse.com>2021-06-16 08:55:52 +0200
commitbb32eac5a90b2b141fed4ce490aded74134f1d75 (patch)
tree9c3a5e48cee0a436229e28481ce896ca3c10d109
parent4504a6346777d544a144683bd2a534b686fbac41 (diff)
downloadfsf-binutils-gdb-bb32eac5a90b2b141fed4ce490aded74134f1d75.zip
fsf-binutils-gdb-bb32eac5a90b2b141fed4ce490aded74134f1d75.tar.gz
fsf-binutils-gdb-bb32eac5a90b2b141fed4ce490aded74134f1d75.tar.bz2
gas: fix hex float parsing from .dcb.? directives
Unlike for .dc.? the parsing here failed to skip the colon before calling hex_float(). To avoid both variants of parsing going out of sync again, introduce a helper used by both.
-rw-r--r--gas/ChangeLog6
-rw-r--r--gas/read.c124
-rw-r--r--gas/testsuite/gas/all/float.s16
3 files changed, 75 insertions, 71 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index ebbf27f..8fa1be8 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,11 @@
2021-06-16 Jan Beulich <jbeulich@suse.com>
+ * read.c (parse_one_float): New.
+ (s_float_space, float_cons): Use it.
+ * testsuite/gas/all/float.s: Add .dc.*, .dcb.*, and .ds.* cases.
+
+2021-06-16 Jan Beulich <jbeulich@suse.com>
+
* read.c (emit_expr_with_reloc): Adjust overflow check. Drop
hibit local variable.
* write.c (fixup_segment): Differentiate signed and non-signed
diff --git a/gas/read.c b/gas/read.c
index db1011b..935b1fa 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -3616,6 +3616,51 @@ s_nops (int ignore ATTRIBUTE_UNUSED)
*p = val.X_add_number;
}
+static int
+parse_one_float (int float_type, char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT])
+{
+ int length;
+
+ SKIP_WHITESPACE ();
+
+ /* Skip any 0{letter} that may be present. Don't even check if the
+ letter is legal. Someone may invent a "z" format and this routine
+ has no use for such information. Lusers beware: you get
+ diagnostics if your input is ill-conditioned. */
+ if (input_line_pointer[0] == '0'
+ && ISALPHA (input_line_pointer[1]))
+ input_line_pointer += 2;
+
+ /* Accept :xxxx, where the x's are hex digits, for a floating point
+ with the exact digits specified. */
+ if (input_line_pointer[0] == ':')
+ {
+ ++input_line_pointer;
+ length = hex_float (float_type, temp);
+ if (length < 0)
+ {
+ ignore_rest_of_line ();
+ return length;
+ }
+ }
+ else
+ {
+ const char *err;
+
+ err = md_atof (float_type, temp, &length);
+ know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+ know (err != NULL || length > 0);
+ if (err)
+ {
+ as_bad (_("bad floating literal: %s"), err);
+ ignore_rest_of_line ();
+ return -1;
+ }
+ }
+
+ return length;
+}
+
/* This is like s_space, but the value is a floating point number with
the given precision. This is for the MRI dcb.s pseudo-op and
friends. */
@@ -3650,42 +3695,12 @@ s_float_space (int float_type)
++input_line_pointer;
- SKIP_WHITESPACE ();
-
- /* Skip any 0{letter} that may be present. Don't even check if the
- * letter is legal. */
- if (input_line_pointer[0] == '0'
- && ISALPHA (input_line_pointer[1]))
- input_line_pointer += 2;
-
- /* Accept :xxxx, where the x's are hex digits, for a floating point
- with the exact digits specified. */
- if (input_line_pointer[0] == ':')
- {
- flen = hex_float (float_type, temp);
- if (flen < 0)
- {
- ignore_rest_of_line ();
- if (flag_mri)
- mri_comment_end (stop, stopc);
- return;
- }
- }
- else
+ flen = parse_one_float (float_type, temp);
+ if (flen < 0)
{
- const char *err;
-
- err = md_atof (float_type, temp, &flen);
- know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
- know (err != NULL || flen > 0);
- if (err)
- {
- as_bad (_("bad floating literal: %s"), err);
- ignore_rest_of_line ();
- if (flag_mri)
- mri_comment_end (stop, stopc);
- return;
- }
+ if (flag_mri)
+ mri_comment_end (stop, stopc);
+ return;
}
while (--count >= 0)
@@ -4909,7 +4924,6 @@ float_cons (/* Clobbers input_line-pointer, checks end-of-line. */
{
char *p;
int length; /* Number of chars in an object. */
- const char *err; /* Error from scanning floating literal. */
char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
if (is_it_end_of_statement ())
@@ -4943,41 +4957,9 @@ float_cons (/* Clobbers input_line-pointer, checks end-of-line. */
do
{
- /* input_line_pointer->1st char of a flonum (we hope!). */
- SKIP_WHITESPACE ();
-
- /* Skip any 0{letter} that may be present. Don't even check if the
- letter is legal. Someone may invent a "z" format and this routine
- has no use for such information. Lusers beware: you get
- diagnostics if your input is ill-conditioned. */
- if (input_line_pointer[0] == '0'
- && ISALPHA (input_line_pointer[1]))
- input_line_pointer += 2;
-
- /* Accept :xxxx, where the x's are hex digits, for a floating
- point with the exact digits specified. */
- if (input_line_pointer[0] == ':')
- {
- ++input_line_pointer;
- length = hex_float (float_type, temp);
- if (length < 0)
- {
- ignore_rest_of_line ();
- return;
- }
- }
- else
- {
- err = md_atof (float_type, temp, &length);
- know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
- know (err != NULL || length > 0);
- if (err)
- {
- as_bad (_("bad floating literal: %s"), err);
- ignore_rest_of_line ();
- return;
- }
- }
+ length = parse_one_float (float_type, temp);
+ if (length < 0)
+ return;
if (!need_pass_2)
{
diff --git a/gas/testsuite/gas/all/float.s b/gas/testsuite/gas/all/float.s
index 902914f..579ca89 100644
--- a/gas/testsuite/gas/all/float.s
+++ b/gas/testsuite/gas/all/float.s
@@ -4,3 +4,19 @@ foo: .single 0r1.2345e+06
.double 0r2.718282
.double .0000000000000000000001
.double 1e-22
+
+ .dc.s 1
+ .dc.s 0f:1234
+ .dcb.s 1, 1
+ .dcb.s 1, 0s:4321
+ .ds.s 1, -1
+
+ .dc.d 1
+ .dc.d 0d:1234
+ .dcb.d 1, 1
+ .dcb.d 1, 0r:4321
+ .ds.d 1, -1
+
+ .dc.x 0x:1234
+ .dcb.x 1, 0x:4321
+ .ds.x 1, -1