gcc 总是可以生成对寄存器的字访问吗?

标签 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 将生成代码“read reg,mask byte0”,然后生成双字“LDR r1,[r0]”而不是“LDRB”操作码?

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

更新:该示例只是现实世界的简化。 volatile 内存屏障也用于linux驱动程序。只是忘记添加示例。我正在研究ARM11。 1)似乎memcpy对我来说不太好,因为不同的寄存器有不同的字段,我无法编写所有的access-inline-function 2)使用union似乎有效,我将在完成测试时更新结果。

更新2:仅测试union,它仍然无法在我的平台上工作。 我认为更好的方法是使用显式的字访问并且不要混淆编译器。

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

谢谢你们!

最佳答案

您可以使用内联汇编:

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 但无法修改汇编指令。

关于gcc 总是可以生成对寄存器的字访问吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43383271/

相关文章:

c - 霍斯普尔算法

c - ld : warning: directory not found for option: -LC_ID_DYLIB=/usr/lib

c - 编译内核模块时 Makefile 忽略 '-isystem' 标志

c++ - 在 ARM 上编译 ChromeDriver

linux - _start 可以作为缩略图函数吗?

c - 使用 Qt Creator(不使用任何类型的 Qt 框架)时的 C(非 C++)程序的 printf

sigwaitinfo() 可以等待进程信号掩码的超集吗?

c++ - 创建可以存储 secret 信息的 C++ 应用程序

c - 单独文件中的线程函数与 pthread 和 make

android - 如何重命名arm elf .so文件中的动态符号?