Elimination of all floating point code in the tiny assembler
jacob navia
jacob@jacob.remcomp.fr
Sun Sep 10 17:41:15 GMT 2023
GAS has its own floating point code in very high precision. This code is quite cumbersome, and never used. All compilers emit floating point numbers as 32 or 64 bit integers, so, the directives for reading floating point numbers go unused.
Still, I maintained all those directives just in case. Internally, they all lead to a call to strtold(), that does all the work done previously by the floating point code in the assembler. The resulting long double is then down-casted to the appropriate precision (double, single, half).
This will cater all the needs of an assembler.
The gains are impressive: Around 1500 lines of floating point code are gone. From the standpoint of the maintaining GAS this should make quite a difference, since the code that was erased is completely incomprehensible unless you get into it after at least a week of work. True, it is running, but it could become a big maintenance problem somewhere in the future.
And, above all, it is never used! I have yet to see any compiler that uses it. For people using GAS, the directives .double, etc are largely enough.
True, back when this code was written, maybe the C library wasn’t as advanced as it is today, strtold I think it is C99, and the floating point code is way older.
This situation is clearly described in the (funny) comments:
/*
* Seems atof_machine can backscan through generic_bignum and hit whatever
* happens to be loaded before it in memory. And its way too complicated for
* me to fix right. Thus a hack. JF: Just make generic_bignum bigger,and
* never write into the early words,thus they'll always be zero. I hate Dean's
* floating-point code. Bleh.
*/
That is a very old comment. GNU developers have fought long battles to maintain this code… let’s forget it.
Of course these are personal thoughts, no need to do anything right now. But if anyone is interested, here is my new version of parse_one_float:
/* DISCLAIMER:
* Here I give up any copyright rights that I may or may not have for this code and declare it property of GNU
*/
static int parse_one_float(int float_type,char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT])
{
int length;
SKIP_WHITESPACE();
/* 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 { // New code
long double ld;
double d; float f; _Float16 f16;
errno=0;
ld = strtold(input_line_pointer,&input_line_pointer);
if (errno) goto err;
switch (float_type) {
case 'H': case 'h':
f16 = ld;
length = 2;
memcpy(temp,&f16,2);
break;
case 'f': case 'F': case 's': case 'S':
f = ld;
length = 4;
memcpy(temp,&f,4);
break;
case 'd': case 'D': case 'r': case 'R':
d = ld;
length = 8;
memcpy(temp,&d,8);
break;
default:
err:
as_bad("bad floating point literal");
ignore_rest_of_line();
return (-1);
}
}
SKIP_WHITESPACE();
return length;
}
You see?
It is TRIVIAL to follow, and even a total noob will understand it!
Jacob
More information about the Binutils
mailing list