Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Nov 2001 02:00:01 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        John Baldwin <jhb@FreeBSD.org>
Cc:        Peter Jeremy <peter.jeremy@alcatel.com.au>, <cvs-all@FreeBSD.org>, <cvs-committers@FreeBSD.org>
Subject:   Re: cvs commit: src/sys/i386/include atomic.h
Message-ID:  <20011123011419.Y17516-100000@delplex.bde.org>
In-Reply-To: <XFMail.011121113833.jhb@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 21 Nov 2001, John Baldwin wrote:

> On 20-Nov-01 Peter Jeremy wrote:
> > On Mon, Nov 12, 2001 at 08:57:33AM -0800, John Baldwin wrote:
> >>jhb         2001/11/12 08:57:33 PST
> >>
> >>  Modified files:
> >>    sys/i386/include     atomic.h
> >>  Log:
> >>  Use newer constraints for inline assembly for an operand that is both an
> >>  input and an output by using the '+' modifier rather than listing the
> >>  operand in both the input and output sections.
> >
> > This change still leaves the non-memory operand's constraint as "ir"
> > in all cases - this isn't correct for the char or short cases.  I have
> > some old patches to fix this.
>
> There are char and short registers and immediates in x86 asm.  The shorts will
> make the assembler insert an extra byte to change the operand size, but it will
> still compile.

Changing the operand size only works for shorts.  There is no way to reduce
to a byte register if the operand happens to be loaded into a register other
than %e[abcd]x, and the "r" operand used in atomic.h doesn't specify any
more than this.  Example:

%%%
char ch;

foo()
{
	asm("incb %4"
	    : : "a" (0xa), "b" (0xb), "c" (0xc), "d" (0xd), "ir" (ch));
}
%%%

Compiling this gives:

%%%
	.file	"z.c"
	.version	"01.01"
gcc2_compiled.:
.text
	.p2align 2,0x90
.globl foo
		.type		 foo,@function
foo:
	pushl %ebp
	movl %esp,%ebp
	pushl %edi
	pushl %esi
	pushl %ebx
	movl $10,%esi
	movl $11,%ebx
	movl $12,%ecx
	movl $13,%edx
	movb ch,%al
	movl %eax,%edi
	movl %esi,%eax
#APP
	incb %di
#NO_APP
	popl %ebx
	popl %esi
	popl %edi
	leave
	ret
.Lfe1:
		.size		 foo,.Lfe1-foo
	.comm	ch,1,1
	.ident	"[ASM_FILE_END]GCC: (c) 2.95.3 20010315 (release)"
%%%

`ch' gets loaded into %edi since none of %e[abcd]x is free, and gcc
silently generates the wrong name %di for the (not directly accessible)
byte register in the low byte of %edi.

The bugs are mostly in atomic.h and the above example.  gcc detects
the error if correct constraint "iq" is used (but it doesn't detect
that %4 can't be converted to a "q" register even if %4 is replaced
by %b4).  gcc is normally smart about loading chars into byte registers,
and atomic.h depends on this too much.

This can be fixed using messy tests involving sizeof() in the ATOMIC_ASM()
macro or by moving the constraint to the macro invocations where it is
easy to vary.  I prefer the latter, except I want the atomic functions
to have a type-generic interface which seems to require the messy tests.
The last version of Peter's fixes that I saw use the latter.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe cvs-all" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20011123011419.Y17516-100000>