delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1992/06/30/14:11:29

Date: Tue, 30 Jun 92 18:23:52 PRT
From: "Jose M. Cerqueira Esteves" <FESTEVES%PTEARN AT clvm DOT clarkson DOT edu>
Subject: 387 instructions in asm.
To: djgpp AT sun DOT soe DOT clarkson DOT edu

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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019