Re: egcs 1.0.1 miscompiles Linux 2.0.33

Linus Torvalds (torvalds@transmeta.com)
Sun, 1 Mar 1998 13:59:56 -0800 (PST)


On Sun, 1 Mar 1998, Jeffrey A Law wrote:
>
> I'm not an x86 hacker, so it's not really clear to me how you
> would rewrite that asm. But it's clearly going to need to be
> rewritten. And until it is, I can't do much on the compiler
> side as I don't have a valid testcase.

Ok, so here's a hypothetical example that is not x86-specific. In fact it
is not specific to any CPU at all, as I made it up (and as such it is a
bad example, but it does show the basic problem..)

Let's say that this particular made up CPU has a strange way of disabling
interrupts, where it has to load the value through a special register that
gcc doesn't even know about and the instruction saves the old value in the
same register. The chip designers decided that you can only use one
specific GP register to read and write this exception register (let's call
this register "ecx" for no other reason than the fact that only intel is
so silly). So we have a instruction like this:

rdwrexception %ecx

that writes the exception register with the value in %ecx, and puts the
old exception value into %ecx.

Now, the exception register actually contains more than just the interrupt
bits, so when you want to restore the interrupt bits into the exception
register you have to do something like this:

#
# write safe value to exception register (disable everything)
# in order to get the current value
#
movl $0xffffffff,%ecx
rdwrexception %ecx

#
# mask off the interrupt bit and set it to the saved value
#
andl $0xfffffffe,%ecx
orl restore_value,%ecx
rdwrexception %ecx

And the inline assembly would look a bit like this:

#define restore_flags(restore_value) \
asm("rdwrexception %0\n\t" \
"andl $0xfffffffe,%0\n\t" \
"orl %1,%0\n\t" \
"rdwrexception %0" \
: /* no outputs */ \
:"c" (0xffffffff), \
"g" (restore_value) \
:"cx")

Now, how should I re-write this to avoid the clobber?

I could use "=c" and "0" to tell gcc that %ecx is a read-write thing and
will change. But that doesn't tell gcc that it mustn't use %ecx for the
value in "restore_value": what if somebody were to say

restore_flags(0xffffffff);

then gcc would decide that as it already has the constant 0xffffffff in
%ecx, then it should use %ecx for "restore_value" too. But that would be
wrong, because then you'd get

orl %ecx,%ecx

which wouldn't do what you wanted..

See the problem? I think that clobbers are the perfect answer, and as they
have worked for previous gcc versions for this same problem, I think it is
the _correct_ answer. I'm willing to be convinced otherwise, but I'd
really like to know how to do something like the above without using a
clobber (and without making the asm code worse: I can easily think of many
ways to "fix" the problem if I was willing to make worse assembly code).

Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu