diff options
Diffstat (limited to 'gas/config/atof-ieee.c')
-rw-r--r-- | gas/config/atof-ieee.c | 117 |
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; +} |