x86_64: is there an option to always do RIP relative addressing for globals?
Mike Cui
cuicui@gmail.com
Sun Jan 23 17:55:00 GMT 2011
Hi,
I want to link a small kernel to run at 0xFFFF800000000000, all text,
data, bss will fit in a 2GB region. I noticed that the 2 code models
that I can choose from, small and kernel, require the kernel to run in
the first or last 2GB of address space, not in the middle. One option
I have is large, which turns every global function call into a
indirect call. The other option, of course, is small_pic, but that
turns every global memory reference into 2 references, and I have to
setup the GOT when loading the kernel.
If all my code and data fit in 2GB, it seems like it should be
possible for this 2GB to be located anywhere. But GCC seems to like to
generate instructions in the form of
mov $symbol, %reg
where the immediate operand $symbol is a sign extended (or zero
extended) 32-bit immediate, thus requiring symbol to be in the first
or last 2GB of address space.
If we replaced those instructions with
lea symbol(%rip), %reg
then the only requirement is that symbol is in the same 2GB region as
the current code.
Are there existing gcc options to do what I want? Is what I want even possible?
Thanks,
-Mike
Example:
extern int b[];
extern int B(int *, int);
int A() {
return B(b, b[0]);
}
Assembly emitted when with -mcmodel=kernel:
movl b(%rip), %esi
movq $b, %rdi # linker complains that relocation
record for b doesn't fit in 32-bit
jmp B
With -mcmodel=large:
movabsq $b, %rdi # 64-bit imm, instruction is HUGE
movabsq $B, %rax
movl (%rdi), %esi
jmp *%rax # indirect call!
With -mcmodel=small and -fpic:
movq b@GOTPCREL(%rip), %rdi # extra memory reference to get &b
movl (%rdi), %esi
jmp B@PLT # extra memory reference to get &B, and indirect call
What I want:
movl b(%rip), %esi
leaq b(%rip), %rdi
jmp B
More information about the Gcc-help
mailing list