gcc能否始终生成单词访问权限以进行注册?

时间:2017-04-13 03:56:01

标签: c gcc arm

我正在使用ARMv7平台,遇到了注册访问问题。 设备模块中的寄存器具有强大的WORD访问要求:

typedef unsigned char u8;
struct reg {
    u8 byte0; u8 byte1; u8 byte2; u8 byte3;
};

当尝试这样的c代码:reg.byte0 = 0x3时,通常gcc生成类似LDRB r1, [r0]的汇编代码,这个字节操作将导致我平台的未定义行为。 它有一个选项,以便gcc将生成代码"读取 reg ,屏蔽 byte0 "然后是dword" LDR r1,[r0]"而不是" LDRB"操作码?

更新:我想访问的目的地是SOC上的设备寄存器。它有4个字段,我们使用表示该寄存器的结构。访问像byte0这样的reg.byte0 = 3字段通常会生成字节访问汇编代码。我想知道这种c代码reg.byte0=3是否可以汇编为字访问(32位,LDR)代码。 真的很抱歉我的英语很差!

更新:这个例子只是对现实世界的简化。 linux驱动程序中也使用了volatile内存屏障。只是忘了添加例子。它是我工作的ARM11。 1)似乎memcpy对我不好,因为不同的寄存器有各种字段,我不能写所有的access-inline-function 2)使用union似乎有效,并且在完成测试时我会更新结果。

UPDATE2:只测试union,它仍无法在我的平台上运行。 我认为更好的方法是使用显式字访问,不要混淆编译器。

UPDATE3:似乎其他人发布完全相同的问题,并且已经解决了。 Force GCC to access structs with words

谢谢你们!

1 个答案:

答案 0 :(得分:0)

你可以使用内联汇编:

static inline u8 read_reg_b0(const struct reg *rp) __attribute__((always_inline)) {
    struct reg r;
    u32 tmp;
    __asm__("ldr %0, %1" : "=r" (tmp) : "m" (*rp));
    memcpy(&r, &tmp, 4);
    return r.b0;
}
static inline void write_reg_b0(struct reg *rp, u8 b0) __attribute__((always_inline)) {
    struct reg r;
    u32 tmp;
    __asm__("ldr %0, %1" : "=r" (tmp) : "m" (*rp));
    memcpy(&r, &tmp, 4);
    r.b0 = b0;
    memcpy(&tmp, &r, 4);
    __asm__("str %1, %0" : "=m" (*rp) : "r" (tmp));
}

GCC将优化memcpy但不能修改汇编指令。