[Ffmpeg-devel] Re: Broken trunk on AMD64 with PIC enabled

Trent Piepho xyzzy
Wed Apr 4 07:51:45 CEST 2007

On Tue, 3 Apr 2007, Loren Merritt wrote:
> gcc uses extra instructions
> non-PIC:
>    mov foo(rcx, rdx, 2), eax
> PIC:
>    lea foo(rip), rax
>    lea (rax, rdx, 2), rax
>    mov (rax, rcx, 1), eax

#if !(PIC) || !(AMD64)
/* on ia-32, we can use TEXTRELs instead of pic code */
#define RIPSIBMOV(inst, sym, base, index, scale, dest) \
	#inst " " #sym "(%" #base ",%" #index "," #scale "), %" #dest "\n\t"

/* amd64 must be truely pic, no TEXTRELs */
#define RIPSIBMOV(inst, sym, index, base, scale, dest) \
       "lea " #sym "(%%rip), %q" #dest "\n\t" \
       "lea (%q" #dest ",%" #index "," #scale "), %q" #dest "\n\t" \
       #inst " (%q" #dest ",%" #base ",1), %" #dest "\n\t"

static int foo[256];
int bar() {
    int x;
    asm(RIPSIBMOV(movzbl, foo, %rcx, %rdx, 2, 0) : "=r"(x));
    return x;

Produces the non-PIC code:
	movzbl foo(%rcx,%rdx,2), %eax

Or (I think) the AMD-64 PIC code:
        lea foo(%rip), %rax
        lea (%rax,%rcx,2), %rax
        movzbl (%rax,%rdx,1), %eax

Of course, this only works for 'mov' type instunctions that don't depend on
the previous value of the dest register.  For non-MOV instrunctions, you
either need an extra scratch register or need to clobber either the base or
index register.

When possible, you're probably better off using an "m" constaint and
letting gcc calculate the address.

Producing PIC ia32 inline asm is left as an exercise to the reader.

More information about the ffmpeg-devel mailing list