Possible to set the armv7 chip into using unaligned memory accesses?

  • I have an open source library that parses a complex file and reads items
    like longs and doubles that are not properly aligned.

    In googling around I've read people claiming you can get the processor
    to do this but details are scant.

    The one concrete one suggested setting "cp15 sctlr[1] (alignment bit) to 0".

    If this would work (just for my app) how would I do this? Any suggest
    other than re-write 2000 lines of code most welcome!

    David
  • On Jan 10, 2012, at 11:24 PM, David Hoerl wrote:

    > I have an open source library that parses a complex file and reads items like longs and doubles that are not properly aligned.
    >
    > In googling around I've read people claiming you can get the processor to do this but details are scant.
    >
    > The one concrete one suggested setting "cp15 sctlr[1] (alignment bit) to 0".
    >
    > If this would work (just for my app) how would I do this? Any suggest other than re-write 2000 lines of code most welcome!
    >
    > David

    Unfortunately, I've no idea if you can set a compiler-switch to make an arm v7 CPU to accept unaligned data within Xcode.

    You should have found this article on SO:
    <http://stackoverflow.com/questions/5119496/arm-unaligned-memory-access-work
    around
    >

    I fear, in order to solve the issue *properly*, you need to fix the open source library. Alignment errors are a portability issue, that is one CPU might be able to access "unaligned data" where another can't.

    Alignment errors may occur when a certain data of a primitive type T (e.g. double, long, ..) or a user defined struct is serialized at a memory address where the CPU is unable to access it, e.g.:

    // This works on Intel
    int main(int argc, const char * argv[])
    {
        char* buffer = (char*)malloc(100);
        char* p = buffer + 1;
        long double v = 1.0;
        memcpy(buffer, &v, sizeof(v));
        long double x = *((long double*)p);  // <=  may cause hardware exception

        printf("x: %Lf, address of x: %p, address of p: %p\n", x, &x, p);
        free(buffer);
    }

    In order to get the alignment of types, I know of these possibilities:
    1) Compiler vendor specific: __alignof operator (available in gcc and clang)
    2) The boost library has an alignment_of traits
    3) C++11 has alignof operator (not sure if this is implemented in clang yet)

    This article is very informative and has further pointers, too:
    <http://www.ibm.com/developerworks/library/pa-dalign/>

    Andreas _______________________________________________
    Do not post admin requests to the list. They will be ignored.
    Xcode-users mailing list      (<Xcode-users...>)
    Help/Unsubscribe/Update your Subscription:
    http://lists.apple.com/mailman/options/xcode-users/<xcode...>

    This email sent to <xcode...>
  • Hi,

    The CP15 is a system control co-processor, and in particular SCTLR is the 'System Control Register' therein [1]. It controls a bunch of stuff, and bit number 1 is defined as:

    Enables strict alignment of data to detect alignment faults in data accesses:
    0 = Strict alignment fault checking disabled. This is the reset value.
    1 = Strict alignment fault checking enabled.

    Since enabling unaligned access is the default, unless Apple explicitly changes this in iOS then it *may* just work. Have you tried, or are you actually seeing alignment faults?

    The concrete info you found refers to writing some assembly (using MCR and MRC to read the existing value, set bit 1, and then write it back) to enable unaligned access. However this will come at a performance cost since each unaligned access is now multiple fetches from memory (as the bus still requires aligned accesses)

    However the whole register is only available in privileged CPU modes, so I suspect under iOS your app would cause a fault if you tried this from user mode. (bit 0 enables/disables the system MMU!). If anything you would need a system call requesting the kernel to enable unaligned accesses for your process (echo 2 > /proc/cpu/alignment in linux, for example) but I don't know if Apple provides this.

    I don't know much at all about the iOS kernel .. there could well exist some plist setting which enables this at app launch for example (but I doubt it due to performance implications if relied upon : )

    So it looks like you may well be stuck with re-implementing the code, or finding an alternative :(

    I'm not aware of compiler options that converts unaligned code to aligned. Options such as -mno-unaligned-access simply tell the compiler what kind of environment you are running under. If you (or the kernel) can arrange for unaligned access to succeed, then the compiler is free to choose implementations of some routines (probably memcpy, memmove, etc) which exploit that fact for some performance. (again, not sure if Clang or GCC does this but the ARM compiler certainly does ...)[2]

    Hope this helps,
    DavidM

    [1] http://infocenter.arm.com/help/topic/com.arm.doc.ddi0388g/CIHFIAJC.html
    [2] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/CIHCGC
    FD.html


    On 10/01/2012, at 10:24 PM, David Hoerl wrote:

    > I have an open source library that parses a complex file and reads items like longs and doubles that are not properly aligned.
    >
    > In googling around I've read people claiming you can get the processor to do this but details are scant.
    >
    > The one concrete one suggested setting "cp15 sctlr[1] (alignment bit) to 0".
    >
    > If this would work (just for my app) how would I do this? Any suggest other than re-write 2000 lines of code most welcome!
    >
    > David
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Xcode-users mailing list      (<Xcode-users...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/xcode-users/<david.mirabito...>
    om

    >
    > This email sent to <david.mirabito...>
  • On Jan 11, 2012, at 1:11 AM, Andreas Grosam wrote:

    > Unfortunately, I've no idea if you can set a compiler-switch to make an arm v7 CPU to accept unaligned data within Xcode.

    It’s not a compiler issue, it’s a runtime issue. Setting a CPU control register has nothing to do with the compiler or toolchain.

    > Alignment errors may occur when a certain data of a primitive type T (e.g. double, long, ..) or a user defined struct is serialized at a memory address where the CPU is unable to access it, e.g.:

    I don’t think the OP’s issue is compiler struct alignment, rather reading values from pointers whose values are computed at runtime.

    —Jens
  • On Jan 10, 2012, at 2:24 PM, David Hoerl wrote:

    > I have an open source library that parses a complex file and reads items like longs and doubles that are not properly aligned.
    >
    > In googling around I've read people claiming you can get the processor to do this but details are scant.
    >
    > The one concrete one suggested setting "cp15 sctlr[1] (alignment bit) to 0".
    >
    > If this would work (just for my app) how would I do this? Any suggest other than re-write 2000 lines of code most welcome!

    How about just writing a set of wrapper accessor functions that you call any time you need to read or write longs, doubles, etc., then call them instead of accessing memory directly? Something like this. (Written in Mail so completely untested, but you get the idea.) Probably a lot less work than rewriting the whole thing.

    uint32_t SafeReadUInt32(uint32_t const* buffer)
    {
    if (buffer & (sizeof(uint32_t) - 1) == 0)
    {
      return *buffer;
    }
    else
    {
    #if defined(LITTLE_ENDIAN) && LITTLE_ENDIAN
      return (((uint8_t*)buffer)[0] << 0) |
                 (((uint8_t*)buffer)[1] << 8) |
                 (((uint8_t*)buffer)[2] << 16) |
                 (((uint8_t*)buffer)[3] << 24);
    #else
      return (((uint8_t*)buffer)[0] << 24) |
                 (((uint8_t*)buffer)[1] << 16) |
                 (((uint8_t*)buffer)[2] << 8) |
                 (((uint8_t*)buffer)[3] << 0);
    #endif
    }
    }

    void SafeWriteUInt32(uint32_t* buffer, uint32_t value)
    {
    if (buffer & (sizeof(uint32_t) - 1) == 0)
    {
      *buffer = value;
    }
    else
    {
    #if defined(LITTLE_ENDIAN) && LITTLE_ENDIAN
      ((uint8_t*)buffer)[0] = value >> 0;
      ((uint8_t*)buffer)[1] = value >> 8;
      ((uint8_t*)buffer)[2] = value >> 16;
      ((uint8_t*)buffer)[3] = value >> 24;
    #else
      ((uint8_t*)buffer)[0] = value >> 24;
      ((uint8_t*)buffer)[1] = value >> 16;
      ((uint8_t*)buffer)[2] = value >> 8;
      ((uint8_t*)buffer)[3] = value >> 0;
    #endif
    }
    }
previous month january 2012 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today