首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止Atmel Studio gcc 6.3.1将4字节memcmp()优化为4字节直接比较?

如何防止Atmel Studio gcc 6.3.1将4字节memcmp()优化为4字节直接比较?
EN

Stack Overflow用户
提问于 2020-02-28 19:33:28
回答 1查看 201关注 0票数 1

运行爱特梅尔工作室,并提供gcc 6.3.1,为爱特梅尔/微芯片SAMV70 (ARM Cortex-M7)芯片构建固件。我有用memcmp()将4字节输入数组与4字节本地数组进行比较的代码.当使用-O0编译以禁用优化时,它工作得很好。在使用-Os优化大小或使用-O3进行最大优化时,编译器将memcmp()调用替换为直接的4字节比较(通过检查反汇编验证)。不幸的是,优化有时也会将本地4字节数组移动到未对齐的起始地址,因此尽管memcmp()可以正常工作,但直接比较会由于未对齐的访问而触发HardFault

在我看来,这是一个100%的编译器优化错误(可能是gcc,可能是Atmel添加的东西),但是我仍然坚持使用提供的编译器,所以更新不是一种选择。因此,我的实际问题是:是否有一种方法可以使优化处于启用状态,但禁用这个特定的优化?否则,我不得不强迫本地的4字节数组对齐,或者找到其他解决办法。

编译器版本:gcc version 6.3.1 20170620 (release) [ARM/embedded-6-branch revision 249437] (Atmel build: 508)

下面是一个可能触发错误的示例函数:

代码语言:javascript
复制
bool example(uint8_t *input_data)
{
    uint8_t local_data[4] = { 0x00, 0x01, 0x02, 0x03 };

    return (memcmp(input_data, local_data, 4) == 0);
}

我的代码总是传递一个4字节对齐的input_data,所以这不是一个问题,但是编译器优化将其视为理所当然是一种糟糕的形式。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-02 21:11:58

在回答我自己的问题时,尤金没有正式回答:

来自gcc ARM options

默认情况下,对所有预ARMv8 6、所有ARMv8 6-M和ARMv8 8-M基线体系结构禁用未对齐访问,并为所有其他体系结构启用

这意味着默认情况下,ARMv7-M允许未对齐访问。事实证明,这是合理的,因为从ARMv7-M架构参考手册

以下数据访问支持非对齐寻址,并且只在将CCR.UNALIGN_TRP位设置为1时才生成对齐错误,请参见配置和控制寄存器:

·非半字对齐LDR{S}H{T}和STRH{T}。

·非半字对齐TBH。

·非字对齐LDR{T}和STR{T}。

这意味着ARMv7-M支持一组有限的未对齐访问。但是,它不支持所有未对齐的访问:

以下数据访问总是生成对齐错误:

非半字对齐LDREXH和STREXH。

非字对齐LDREX和STREX。

非字对齐的LDRD、LDMIA、LDMDB、POP、最不发达国家、VLDR、VLDM和VPOP。

非字对齐STRD、STMIA、STMDB、PUSH、STC、VSTR、VSTM和VPUSH。

还包括:

对强有序和设备内存类型的

访问必须始终保持自然对齐。

因此,这是失败的条件,促使我提出了最初的问题:

启用优化的

  1. gcc用直接比较替换了一个4字节的memcmp(),这在默认情况下是允许的,因为默认情况下不对齐访问是允许的。
  2. 是包含memcmp()数据的闪存区域,位于被声明为Strongly Ordered的MPU段中,不支持非对齐访问。因此,当直接比较替换memcmp()时,数据落在未对齐的地址上,则比较触发了一个memcmp()

尤金在其最初的评论中得到了正确的修正,即将-mno-unaligned-access添加到编译器选项中。在我的例子中,这仍然允许编译器用直接的4字节比较替换memcmp(),但它也强制数据对齐4字节,允许比较成功而不触发故障条件。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60458186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档