This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c/52146] New: [x32] - Wrong code to access addresses 0x80000000 to 0xFFFFFFFF
- From: "steffen-schmidt at siemens dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 07 Feb 2012 08:55:17 +0000
- Subject: [Bug c/52146] New: [x32] - Wrong code to access addresses 0x80000000 to 0xFFFFFFFF
- Auto-submitted: auto-generated
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: unassigned@gcc.gnu.org
ReportedBy: steffen-schmidt@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)