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.
Use -mno-unaligned-access
flag to tell the compiler to not to use unaligned access. By default the compiler uses -munaligned-access
.