This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: multi-precision in extended asm


Still trying.  This is my first brush with gcc's extended asm
feature so I am interested in any and all feedback on my efforts.

I am writing 3 x86 accumulation functions:

   - i32 into i64
   - i32 into i128
   - i64 into i128

My current coding appears below.

The first two work because the lhs is passed as a reference and
the rhs is register-size.  I am having trouble with the third.
How do I express "please load a 64 bit input operand into %eax
and %edx according to the x86-specific A constraint"?

TIA,

/john

========================================

inline void operator += (CNumeric64& lhs, int32 rhs)
{
    asm(
        "cltd\n\t"            // replicate sign of %eax through %edx
        "addl %%eax,%0\n\t"   // sum: lhs.lo32+rhs; set carry
        "adcl %%edx,%1"       // sum: lhs.hi32+repSign(rhs)+carry
        :
        /* %0 */ "+o" (lhs.lo32),
        /* %1 */ "+o" (lhs.hi32)
        :
        /* %2 */ "a"  (rhs)     // 32 bits in %eax
        :
        "cc", "edx"
       );
}

inline void operator += (CNumeric128& lhs, int32 rhs)
{
    asm(
        "cltd\n\t"            // replicate sign of %eax through %edx
        "addl %%eax,%0\n\t"   // sum: lhs.lo32+rhs; set carry
        "adcl %%edx,%1\n\t"   // sum: lhs.lh32+repSign(rhs)+carry; set carry
        "adcl %%edx,%2\n\t"   // sum: lhs.hl32+repSign(rhs)+carry; set carry
        "adcl %%edx,%3"       // sum: lhs.hi32+repSign(rhs)+carry
        :
        /* %0 */ "+o" (lhs.lo32),
        /* %1 */ "+o" (lhs.lh32),
        /* %2 */ "+o" (lhs.hl32),
        /* %3 */ "+o" (lhs.hi32)
        :
        /* %4 */ "a"  (rhs)     // 32 bits in %eax
        :
        "cc", "edx"
       );
}

inline void operator += (CNumeric128& lhs, int64 rhs)
{
    asm(
        "addl %%eax,%0\n\t"   // sum: lhs.lo32+rhs; set carry
        "movl %%edx,%%eax\n\t"// setup for sign bit replication
        "adcl %%edx,%1\n\t"   // sum: lhs.lh32+repSign(rhs)+carry; set carry
        "cltd\n\t"            // replicate sign of %eax through %edx
        "adcl %%edx,%2"       // sum: lhs.hl32+repSign(rhs)+carry; set carry
        "adcl %%edx,%3"       // sum: lhs.hi32+repSign(rhs)+carry
        :
        /* %0 */ "+o" (lhs.lo32),
        /* %1 */ "+o" (lhs.lh32),
        /* %2 */ "+o" (lhs.hl32),
        /* %3 */ "+o" (lhs.hi32)
        :
        /* %4 */ "A" (rhs)    // 64 bits: %eax = low order, %edx = high order
        :
        "cc", "eax", "edx"
       );
}


> Given that GCC provides 64 integers across many architectures
> with only 32 bit wide registers I assume there is some general
> framework for manipulating these objects.  Is there a way to
> write a constraint that says "low order 32 bits of 64 bit
> datum" or "high order 32 bits of 64 bit datum"?
> 
> In particular how would I express "arithmetic shift right 31
> places the high 32 bits of a 64 bit integer to get a register
> filled with a copy of the sign bit" on the x86? on the ppc?
> 
> --
> John S. Yates, Jr.            508 665-6800  x897
> Netezza Inc,  Suite 100       508 665-6811 (fax)
> 1671 Worcester Rd.          Framingham, MA 01701
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]