Re: Can 64 bit GCC compiler use LLP64 data model?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/12/2020 00:12, Grant, Steve via Gcc-help wrote:
> Is it possible to configure the current (9.3 or 10.2) GNU GCC
> bare-metal compiler to use the LLP64 data model for targeting the
> 64-bit ARM Cortex-A53?
> 
> My current project involves porting legacy embedded C++ code that is
> running on a 32-bit Cortex-A9 processor to a 64-bit Cortex-A53
> processor.
> 
> Since this is an embedded system, many of the data structures are
> mapped to hardware memory-mapped registers.  These registers were
> defined as 'unsigned long' which the previous GCC 32-bit compiler
> defines as 32 bits in size that matches the register hardware in the
> legacy system.
> 
> I see that the GCC 64 bit compiler uses the LP64 data model where
> 'unsigned long' is 64 bits in size. Having unsigned longs go from 32
> bits to 64 would break the register memory mapping.   The data model
> LLP64 used by Win64 defines 'unsigned long' as 32 bits.  I understand
> that this is to support the legacy data structures in the Windows
> world.  I could redefine all of the memory mapped registers to
> 'unsigned int' in the source code but there are a lot of them and I'm
> concerned about destabilizing the code.
> 
> So is it possible to configure the GCC compiler to use the LLP64 data
> model?
> 
> Thanks, Steve
> 

The hardware registers should never have been defined in terms of "long"
or "int" in the first place.  These should all be given with
size-specific types (uint32_t, int32_t, etc.).  C99 has been around for
20 years - there is no excuse for getting this wrong.

My advice - without seeing the code or knowing the project, or what is
involved in changing things - would be to fix these register definitions.

Build the code with the current 32-bit target, and save the binary.

Then change every "unsigned long" to "uint32_t" (and "unsigned short" to
"uint16_t", and "unsigned char" to "uint8_t" - and similar for signed
types).

Then rebuild the code and check that the binaries match identically.


To be sure that you haven't forgotten any cases of int, long, short, or
char in the header, you can write this at the start of the header:

#define long LONG
#define int INT
#define unsigned UNSIGNED
#define short SHORT
#define char CHAR

and then at the end have

#undef long
#undef int
#undef unsigned
#undef short
#undef char

(you need that so that other headers or parts of the code can use the
standard types again.)


Once you've confirmed that everything is correct, remove these defines
again since they are cheating a bit - redefining keywords like this is
undefined behaviour.  But they can be a useful aid in cases like this.







[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux