带有碎片字段和uint别名的C ++位字段

时间:2014-02-10 17:45:12

标签: c++

我正在尝试用C ++干净地表示一个32位ARM寄存器CPSR。

看起来像这样:

|31|30|29|28|27| 26 25 |24|23..20| 19..16| 15..10|9|8|7|6|5|  4..0|
| N| Z| C| V| Q|IT[1:0]| J| Resvd|GE[3:0]|IT[7:2]|E|A|I|F|T|M[4:0]|

我希望能够访问该寄存器的字段,同时还能够像32位字一样对待它。

例如,“CPSR.M”只是M字段,可读写,依此类推。此外,“CPSR”本身会将寄存器显示为uint32_t。

我想我可能至少在那里使用工会和位字段:例如:

typedef struct {
    uint32_t M               : 5;
    uint32_t T               : 1;
    uint32_t F               : 1;
    uint32_t I               : 1;
    uint32_t A               : 1;
    uint32_t E               : 1;
    uint32_t IT1             : 6;
    uint32_t GE              : 4;
    uint32_t ReservedRAZSBZP : 1;
    uint32_t J               : 1;
    uint32_t IT0             : 2;
    uint32_t Q               : 1;
    uint32_t V               : 1;
    uint32_t C               : 1;
    uint32_t Z               : 1;
    uint32_t N               : 1;
} CPSRType;

我的问题是,当它分成两部分时,我不确定如何取消引用CPSR.IT。另外,我怎么能让CPSR.IT,CPSR.M和(uint32_t)CPSR都是有效的L值?

是位域和联合的方式,还是我需要尝试别的东西?

感谢。

1 个答案:

答案 0 :(得分:1)

根据您的问题,您是否想要直接访问CPSR存储器映射寄存器,或者如果您想在读取该寄存器之后或写入该寄存器之前获取/设置不同的字段,则不是很清楚。

您可以在此注册表的本地副本CPSRType CPSR上执行以下操作:

您可以按如下方式获取IT值:

uint8_t value = (CPSR.IT1<<2) | CPSR.IT0;

您可以按如下方式设置IT值:

CPSR.IT0 = value & 0x03;
CPSR.IT1 = (value>>2) & 0x3F;

您可以按如下方式设置M值:

CPSR.M = value & 0x1F;

您可以按如下方式设置整个结构:

CPSR = *(CPSRType*)&value; // where 'value' must be a 32-bit variable

当然,您最终需要读取/写入内存映射寄存器:

CPSR = *(CPSRType*)REG_ADDRESS; // Read register
*(CPSRType*)REG_ADDRESS = CPSR; // Write register