PortingFromX86ToARM

Applications that work fine on x86, may crash or have various bugs when compiled for arm and run on Nokia 770. This page is intended to provide some information about possible sources of these bugs and help in finding and fixing them.

The most important difference is that arm cpu requires all the memory access operations to be aligned (32-bit memory accesses aligned at 4-byte boundary, 16-bit accesses aligned at 2-byte boundary respectively). Also beware of struct packing and alignment.

The 2006 Maemo gcc respects the #pragma pack compiler directive.

To align variables, use

    attribute

((aligned(4))):

    char somedata [] <ul>attribute</ul>((aligned (4))) = {
    .......
    };

Note that QEMU does not handle unaligned memory access in the same way as the real device, so these errors will not be apparent if you test the application in Scratchbox. QEMU simply allows unaligned access; the ARM CPU in the Nokia 770 discards the lowest address bits and lets the access through to an address a couple of bytes earlier than the program expected. This behavior can by echoing a number to /proc/cpu/alignment; the values are

 1 - Generate warnings when user programs perform misaligned accesses
 2 - Enable fixup of misaligned access from user programs
 4 - Generate signal when user programs perform misaligned accesses

and can be combined using binary OR. See http://www.nslu2-linux.org/wiki/Info/Alignment

gcc has an option -Wcast-align that can provide some warnings.

    - Wcast-align
        Warn whenever a pointer is cast such that the required alignment
        of the target is increased.  For example, warn if a "char *" is
        cast to an "int *" on machines where integers can only be
        accessed at two- or four-byte boundaries.

Right now this page is just a stub, it should be extended with the information posted in this forum thread: http://www.internettablettalk.com/forums/showthread.php?t=2668

See also http://wiki.debian.org/ArmEabiPort

The best solution to alignment and endianness (not a problem between X86 and ARM) problems is to unpack byte streams into structs by hand. Rather than doing this:

        char *cp;
        int i;

        i = *((int *)cp);

do this instead:

        char *cp;
        int i;

        i = (cp[0] << 8) | (cp[1] & 0xff);

The pleasant property of the latter is that it completely eliminates the htons() confusion that often results. "Do I need to convert this one or not?". It forces you to think about a byte stream as a stream of bytes which get interpreted as words or longs. It may seem like the latter code is less efficient, but any reasonable C compiler's peephole analyzer will produce the best possible code.