如何强制 arm gcc 编译器不对未对齐的内存使用 32 位访问

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

我正在处理无法处理未对齐地址上的 32 位访问的内存。对于未对齐的地址,内存支持 8 位级别的访问。

在我的代码中有一个 memcpy,当我将一个未对齐的地址传递给 memcpy 时,芯片卡住了。 深入了解后,我发现生成的 memcpy 汇编代码正在对地址进行 32 位访问,而不管给定地址是否与 32 位对齐。当我将优化级别降低到 O(2) 时,编译器会生成始终执行 8 位访问的代码。

[编辑]:下面是我正在使用的 memcpy 代码

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;
}

下面是代码的反汇编

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

是否可以将 arm-gcc 编译器配置为不对未对齐的地址使用 32 位访问。

使用-mno-unaligned-access标志告诉编译器不要使用未对齐访问。默认情况下,编译器使用 -munaligned-access.

使用“-mcpu=”标志设置处理器类型,而不是“-march=”,因为它涵盖了更多选项。

处理器确定是否允许对总线接口进行未对齐访问。但是在访问内存设备之前,未对齐的访问将被翻译成更小的部分。说内存不支持未对齐访问确实没有意义,因为无论内核做什么,它都看不到它们。