I am using the gcc cross compiler on a windows machine for an ARM CortexA9 for a bare metal application. For direct memory mapping I need to access the address 0x8000_0000. I use the following C-Code:
#define PORTBASE_A 0x80000000
unsigned int volatile * const portA = (unsigned int *) PORTBASE_A;
#define PORTBASE_B 0x70000000
unsigned int volatile * const portB = (unsigned int *) PORTBASE_B;
#define PORTBASE_C 0x080000000
unsigned int volatile * const portC = (unsigned int *) PORTBASE_C;
printf("Portbase_A %p \n",(unsigned int *) portA); // Portbase_A 0xffffffff80000000
printf("Portbase_B %p \n",(unsigned int *) portB); // Portbase_B 0x70000000
printf("Portbase_C %p \n",(unsigned int *) portC); // Portbase_C 0xffffffff80000000
printf("%d\n", sizeof(unsigned int *)); //4
Using printf("Portbase_A %p \n",(unsigned int *) portA);
leads to the output
Portbase_A 0xffffffff80000000
.
Question
Why do I get 64bit address (0xffffffff80000000) despite the fact that my target machine is a 32-bit machine. I realise that in 0x8000_0000 the leading bit is a one, but why does this result in a 1-padding of 32 leading bits? Is this some sort of an artefact due to cross compilling?
Many thanks for replies.
For completeness this is a visualization of my scatter-file. scatter-file visualisation
From a standard point of view, according to C99: 6.3.2.3
quote:
5 An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.56)
As the result is implementation-defined, it should be described by the implementation. Ie. by the compiler. gcc documentation about implementation defined behavior of pointers says that:
The result of converting a pointer to an integer or vice versa (C90 6.3.4, C99 and C11 6.3.2.3).
A cast from pointer to integer ....
A cast from integer to pointer discards most-significant bits if the pointer representation is smaller than the integer type, extends according to the signedness of the integer type if the pointer representation is larger than the integer type, otherwise the bits are unchanged.
I assume (read as: guess) that on your platform:
int
is 4 bytesBoth constants 0x80000000
and 0x70000000
have the type int
. The pointer has 8 bytes. When you do (unsigned int *)PORTBASE_A
the compiler has to cast an int
variable to 8 bytes. Your compiler generates code that does twos complement sign extension, ie. the most-significant bit is repeated for all the extra bits in the extra 4 bytes when casting from int
to a pointer. Because of that, the resulting value has the extra bits set to 1.
User contributions licensed under CC BY-SA 3.0