Subject: inconsistent operand constraints in 'asm' in unaligned.h:66 using gcc 3.4

From: "Bradley D. LaRonde" <[email-masked]>
Date: Thu, 22 Apr 2004 23:22:40 -0400

gcc 3.4 complians about:

include/asm/unaligned.h:66: error: inconsistent operand constraints in an
`asm'

from linux CVS 2.4 branch.  That's:

/*
 * Store doubleword ununaligned.
 */
static inline void __stq_u(unsigned long __val, unsigned long long * __addr)
{
        __asm__("usw\t%1, %0\n\t"
                "usw\t%D1, 4+%0"
                : "=m" (*__addr)
                : "r" (__val));
}

I was baffled by the "%D1" syntax until Thiemo Seufer pointed out that %D1
assembled to "one register higher than the register chosen for %1".
Ooooookay.  But gcc complains about a constraint problem.  Maybe "r" and
"%Dn" don't get along (long)?

Anyway... what about __val's type?  I would expect that to be "unsigned long
long" for -mabi=32.  Otherwise will "%D" get what the asm author expected?
If I do change it to "unsigned long long" then I get two of the constraint
errors.  Ooooookay.  Anyone got a constraint that means "consecutive
register pair"?

I finally decided to punt and write:

static inline void __stq_u(unsigned long long __val, unsigned long long *
__addr)
{
        *__addr = __val;
}

Is this OK?  Is there a better solution?

Regards,
Brad

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Fri, 23 Apr 2004 15:07:43 +0200 (CEST)

>         __asm__("usw\t%1, %0\n\t"

 As usually recent gcc is invaluable in finding dubious constructs. ;-)

> Is this OK?  Is there a better solution?

 No.  Yes.

 Reviving old tricks about unaligned data I've come with the following
implementation:

void __stq_u(unsigned long long __val, unsigned long long *__addr)
{
	typedef struct {
		unsigned long long v __attribute__((packed));
	} ull_u_t;
	ull_u_t *a = (ull_u_t *)__addr;

        a->v = __val;
}

which yields a nice and desirable code:

unaligned.o:     file format elf32-tradlittlemips

Disassembly of section .text:

00000000 <__stq_u>:
   0:	a8c40003 	swl	a0,3(a2)
   4:	b8c40000 	swr	a0,0(a2)
   8:	a8c50007 	swl	a1,7(a2)
   c:	03e00008 	jr	ra
  10:	b8c50004 	swr	a1,4(a2)
	...

I'm pretty sure it works fine with gcc 2.95.x as well -- for Alpha it used
to, even with such antiques as egcs 1.1.2.

 Ralf, I can see 2.6 already does the right thing -- I suppose you won't
mind me backporting (copying?) it?

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

---

From: Ralf Baechle <[email-masked]>
Date: Fri, 23 Apr 2004 15:14:45 +0200

> mind me backporting (copying?) it?

I certainly won't.  I think the 2.4 implementation was originally written
necessary upto egcs 1.0 which were generating correct but very inefficient
code for __attribute((packed)).

  Ralf