aboutsummaryrefslogtreecommitdiff
path: root/gas/config/atof-ieee.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/atof-ieee.c')
-rw-r--r--gas/config/atof-ieee.c117
1 files changed, 115 insertions, 2 deletions
diff --git a/gas/config/atof-ieee.c b/gas/config/atof-ieee.c
index 5b1cbb5..d901f31 100644
--- a/gas/config/atof-ieee.c
+++ b/gas/config/atof-ieee.c
@@ -160,7 +160,7 @@ make_invalid_floating_point_number (LITTLENUM_TYPE *words)
char *
atof_ieee (char *str, /* Text to convert to binary. */
- int what_kind, /* 'd', 'f', 'g', 'h'. */
+ int what_kind, /* 'd', 'f', 'x', 'p'. */
LITTLENUM_TYPE *words) /* Build the binary here. */
{
/* Extra bits for zeroed low-order bits.
@@ -218,7 +218,6 @@ atof_ieee (char *str, /* Text to convert to binary. */
case 'p':
case 'P':
-
precision = P_PRECISION;
exponent_bits = -1;
break;
@@ -696,5 +695,119 @@ print_gen (gen)
return (sbuf);
}
+#endif
+
+extern const char FLT_CHARS[];
+#define MAX_LITTLENUMS 6
+
+/* This is a utility function called from various tc-*.c files. It
+ is here in order to reduce code duplication.
+
+ Turn a string at input_line_pointer into a floating point constant
+ of type TYPE (a character found in the FLT_CHARS macro), and store
+ it as LITTLENUMS in the bytes buffer LITP. The number of chars
+ emitted is stored in *SIZEP. BIG_WORDIAN is TRUE if the littlenums
+ should be emitted most significant littlenum first.
+
+ An error message is returned, or a NULL pointer if everything went OK. */
+
+char *
+ieee_md_atof (int type,
+ char *litP,
+ int *sizeP,
+ bfd_boolean big_wordian)
+{
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ int prec = 0;
+ if (strchr (FLT_CHARS, type) != NULL)
+ {
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = F_PRECISION;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = D_PRECISION;
+ break;
+
+ case 't':
+ case 'T':
+ prec = X_PRECISION;
+ type = 'x'; /* This is what atof_ieee() understands. */
+ break;
+
+ case 'x':
+ case 'X':
+ case 'p':
+ case 'P':
+#ifdef TC_M68K
+ /* Note: on the m68k there is a gap of 16 bits (one littlenum)
+ between the exponent and mantissa. Hence the precision is
+ 6 and not 5. */
+ prec = P_PRECISION + 1;
+#else
+ prec = P_PRECISION;
#endif
+ break;
+
+ default:
+ break;
+ }
+ }
+ /* The 'f' and 'd' types are always recognised, even if the target has
+ not put them into the FLT_CHARS macro. This is because the 'f' type
+ can come from the .dc.s, .dcb.s, .float or .single pseudo-ops and the
+ 'd' type from the .dc.d, .dbc.d or .double pseudo-ops.
+
+ The 'x' type is not implicitly recongised however, even though it can
+ be generated by the .dc.x and .dbc.x pseudo-ops because not all targets
+ can support floating point values that big. ie the target has to
+ explicitly allow them by putting them into FLT_CHARS. */
+ else if (type == 'f')
+ prec = F_PRECISION;
+ else if (type == 'd')
+ prec = D_PRECISION;
+
+ if (prec == 0)
+ {
+ *sizeP = 0;
+ return _("Unrecognized or unsupported floating point constant");
+ }
+
+ assert (prec <= MAX_LITTLENUMS);
+
+ t = atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer = t;
+
+ *sizeP = prec * sizeof (LITTLENUM_TYPE);
+
+ if (big_wordian)
+ {
+ for (wordP = words; prec --;)
+ {
+ md_number_to_chars (litP, (valueT) (* wordP ++), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ }
+ else
+ {
+ for (wordP = words + prec; prec --;)
+ {
+ md_number_to_chars (litP, (valueT) (* -- wordP), sizeof (LITTLENUM_TYPE));
+ litP += sizeof (LITTLENUM_TYPE);
+ }
+ }
+
+ return NULL;
+}