http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52146
Bug #: 52146 Summary: [x32] - Wrong code to access addresses 0x80000000 to 0xFFFFFFFF Classification: Unclassified Product: gcc Version: 4.6.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassig...@gcc.gnu.org ReportedBy: steffen-schm...@siemens.com Created attachment 26596 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=26596 C code resulting in wrong instructions when compiled with -mx32 and O1 or higher When accessing memory addresses in the region 0x80000000 to 0xFFFFFFFF starting from optimization -O1 or higher -mx32 GCC seems to generate faulty assembler instructions. Using -mx32 GCC will generate code for x86_64 target but using 4 byte pointers (instead of 8 byte pointers when using -m64). Nonetheless we're running on a x86_64 64bit machine. The example shows the problem: typedef unsigned int uint32_t; volatile uint32_t * apic_tpr_addr = (uint32_t*)0xfee00080; *apic_tpr_addr = 0; GCC -mx32 generates the following assembler instructions: movl $0, -18874240 On on x86 32bit system, this instruction would be correct, movl uses signed addresses as destination when directly accessing memory. On an x86_64 system, on the other hand, this instruction does not refer to address 0xFEE00080, but to 0xFFFFFFFFFEE00080, because the signed address is interpreted in 64bit by the processor, which leads to an error. GCC -m64 generates the correct instructions: xorl %eax, %eax movabsl %eax, 4276093056 It seems to be necessary to use movabsl instruction instead of movl. The problem does not occur by forcing access to memory via a register: volatile uintptr_t ptr = 0xfee00080; volatile uint32_t * apic_tpr_addr = (uint32_t*)ptr; *apic_tpr_addr = 0; In this case -mx32 GCC generates the follwoing code: movl $-18874240, -4(%esp) movl -4(%esp), %eax movl $0, (%eax) Here the access to memory is correct, using 32bit register eax Code generated by -m64 GCC looks similar, but using 64bit addresses and registers. movl $4276093056, %eax movq %rax, -8(%rsp) movq -8(%rsp), %rax movl $0, (%rax)