Mail Archives: djgpp/2001/05/07/14:46:45
Hans-Bernhard Broeker wrote:
> In article <3AF6B070 DOT D006EAC1 AT sci DOT kun DOT nl> you wrote:
>
> > I made some macro's to push and pop registers, but it did not work when
> > I optimized the code.
>
> No surprise, as that modifies the most central register GCC expects
> you to keep your fingers off: the stack pointer. And you didn't even
> tell GCC about that.
Indeed, but I do not know a way to do so. Can you tell me?
>
>
> > So I used __volatile__ and the compile option -fno-defer-pop.
>
> Bad idea, I think. Using extended inline asm is the preferrable
> solution, almost all the time. Your own code shouldn't have to rely
> on any registers keeping their contents from one inline asm block to
> the next, or you'll be in trouble.
>
I use extended asm. But I do not know how to tell the fact that the stack is
used.
The above way of doing things works in almost all cases: except near a
return,
the pop is not deferred, like in the example below. I can hack the program
such
that no problem will occur, but I do not think that is very proper.
>
> Using extended inline assembly, you can tell gcc which values your asm
> code fragments puts into or assumes to find in which registers. Where
> possible, GCC will optimize register lifetime including your code
> block, using that information. E.g. if one of your asm blocks put
> variable "foo" into %ebx, and GCC doesn't strictly need %ebx in the
> meantime, it'll still be in there as the next asm block is entered,
> and no reloads will be necessary. Or if it is, it'll put in the
> push/pop or mov instructions itself.
Not if you reserve registers. First, I did not reserve registers, but this
resulted
in dragging register locals to the stack by the generated program. So I
reserved
all six registers. As a result, my code only compiled with -O1 after then,
since
otherwise the compiler complained about spilled registers. But if you think
I
should accept a performance loss of more than 10 percent, then I still have
the
problem of storing registers onto the stack during some program code which
is not
just a call or an inline asm. I use the following macros in my program:
#define push(value) asm volatile ("pushl %0" : : "g" (value))
#define pop(reg) asm volatile ("popl %0" : "=r" (reg))
#define call(label,retlabel) do {push (&&retlabel); goto label; retlabel: ;
} while (0)
#define ret(clobberreg) do {pop (clobberreg); goto *((void *) clobberreg); }
while (0)
This way I can use a very fast recursion in my program (I like my version
better than that
with jumps from one asm-block to another, as suggested in some online
documentation
of inline asm). The above macros are not included in the "minimal example
file" I sent:
a program that shows that the compiler sometimes defers the pops after a
call in my opinion,
despite the -fno-defer-pop option.
>
> [ BTW: a copy of your actual source would have been handy, too, not
> just the assembly listing...]
The source code is compiled in such a way that each source line precedes the
accembly
output that is associated with it (gcc -c -g -Wa,-a,-ad -O1 -fno-defer-pop
defer.cpp > defer.lst), just as suggested in the djgpp FAQs. That seemed
much more
convenient to me. You do not need to search which line is associated with
which
asm statements.
>
> --
> Hans-Bernhard Broeker (broeker AT physik DOT rwth-aachen DOT de)
> Even if all the snow were burnt, ashes would remain.
- Raw text -