cmemoryarmmemcpyarm-none-eabi-gcc

how to force arm gcc compiler to not to use 32bit access for an unaligned memory


I work on a memory which cannot handle 32bit access on an unaligned address. For unaligned addresses the memory supports 8bit level access.

In my code there is a memcpy, when I pass a unaligned address to memcpy the chip was getting stuck. Upon looking deeper I figured out the generated assembly code of memcpy is doing a 32bit access to the address regardless of whether the given address is aligned to 32bit or not. When I reduced the optimization level to O(2) then the compiler generates code which always do a 8bit access.

[Edit] : Below is the memcpy code which I am using

void* memcpy(void * restrict s1, const void * restrict s2, size_t n)
{
    char* ll = (char*)s1;
    char* rr = (char*)s2;
    for (size_t i = 0; i < n; i++) ll[i] = rr[i];
    return s1;
}

Below is the disassembly of the code

void* memcpy3(void *s1, void *s2, size_t n)
{
char* ll = (char*)s1;
char* rr = (char*)s2;
for (size_t i = 0; i < n; i++) ll[i] = rr[i];
0:  b38a        cbz r2, 66 <memcpy3+0x66>
{
2:  b4f0        push    {r4, r5, r6, r7}
4:  1d03        adds    r3, r0, #4
6:  1d0c        adds    r4, r1, #4
8:  42a0        cmp r0, r4
a:  bf38        it  cc
c:  4299        cmpcc   r1, r3
e:  d31e        bcc.n   4e <memcpy3+0x4e>
10: 2a08        cmp r2, #8
12: d91c        bls.n   4e <memcpy3+0x4e>
14: 460d        mov r5, r1
16: 4604        mov r4, r0
  for (size_t i = 0; i < n; i++) ll[i] = rr[i];
18: 2300        movs    r3, #0
1a: 0897        lsrs    r7, r2, #2
1c: f855 6b04   ldr.w   r6, [r5], #4
20: 3301        adds    r3, #1
22: 429f        cmp r7, r3
24: f844 6b04   str.w   r6, [r4], #4
28: d8f8        bhi.n   1c <memcpy3+0x1c>
2a: f022 0303   bic.w   r3, r2, #3
2e: 429a        cmp r2, r3
30: d00b        beq.n   4a <memcpy3+0x4a>
32: 56cd        ldrsb   r5, [r1, r3]
34: 1c5c        adds    r4, r3, #1
36: 42a2        cmp r2, r4
38: 54c5        strb    r5, [r0, r3]
3a: d906        bls.n   4a <memcpy3+0x4a>
3c: 570d        ldrsb   r5, [r1, r4]
3e: 3302        adds    r3, #2
40: 429a        cmp r2, r3
42: 5505        strb    r5, [r0, r4]
44: d901        bls.n   4a <memcpy3+0x4a>
46: 56ca        ldrsb   r2, [r1, r3]
48: 54c2        strb    r2, [r0, r3]
  return s1;
}
4a: bcf0        pop {r4, r5, r6, r7}
4c: 4770        bx  lr
4e: 3a01        subs    r2, #1
50: 440a        add r2, r1
52: 1e43        subs    r3, r0, #1
54: 3901        subs    r1, #1
  for (size_t i = 0; i < n; i++) ll[i] = rr[i];
56: f911 4f01   ldrsb.w r4, [r1, #1]!
5a: 4291        cmp r1, r2
5c: f803 4f01   strb.w  r4, [r3, #1]!
60: d1f9        bne.n   56 <memcpy3+0x56>
}
62: bcf0        pop {r4, r5, r6, r7}
64: 4770        bx  lr
66: 4770        bx  lr

Is it possible to configure the arm-gcc compiler to not to use a 32bit access on an unaligned address.


Solution

  • Use -mno-unaligned-access flag to tell the compiler to not to use unaligned access. By default the compiler uses -munaligned-access.