Mail Archives: djgpp/1992/06/30/14:11:29
Hi
I am converting a recent random number generator package (by George Marsaglia
and Arif Zaman) for use with GCC on the PC. The original routines were
written in assembler, but, since I am going to use them also on other computers,
I am rewriting them in C, using the "asm" instruction only for a few
instructions which would be much slower if coded in C.
To do this, I read the section "Assembler instructions with C expression
operands", in "Using and porting GNU CC". I had no problems when using
instructions not related to the numeric processor, but I have some doubts
about usage of 80387 instructions.
To be specific, I would like to write a routine of the form
float
RSuni(void)
{
float random_float;
.
. /* instructions converting a 31 bit integer
. (from an external array) into a float,
. assigning the result to random_float */
return random_float;
}
and/or (for GNU CC):
#define RSuni() \
({ \
float random_float; \
. \
. /* instructions converting a 31 bit integer \
. (from an external array) into a float, \
. assigning the result to random_float */ \
random_float; \
})
The conversion from the 31 bit int (a positive 32 bit int) to random_float
is made dividing by 2^p, where p=-31 except when the first byte of the int
is 0 (in this case, another leading byte is generated and p is decremented
by 7).
The original assembler program does this scaling by loading p and the integer
into the 80387 stack and then using the "fscale" and "fstp st(1)" instructions.
This leaves the result in the top register of the floating-point stack.
I tried to code this as follows:
register float random_float asm ("%st");
.
. /* C code .... */
.
asm volatile ("fildl %1; fildl %2; fscale; fstp %%st(1)"
: "=f" (random_float)
: "g" (p), "g" (the_integer_to_be_converted) );
return random_float;
/* or simply "random_float;", if defined as a macro */
GCC did not accept the above, saying "Output constant 0 must specify
a single register". I then replaced "=f" with "=%st" and no errors
were reported.
Is this OK (and safe)? I expect this to always leave the result
(random_float) on the stack top, ready to be used in subsequent
calculations.
But I expect trouble when the 80387 stack is almost full immediately
before the above is run. Will GCC take care of this problem if I
specify (in the asm instruction) all or some (which?) of the stack
registers as clobbered? Perhaps I could get the answers by trial and
error, but I haven't got much time for it (also, this is only the second
time I use assembler).
I am using GCC 2.01 (DJGPP 1.06)
Thanks in advance for any information.
(Also, many thanks to DJ for DJGPP!)
- Raw text -