字节序
描述数值在内存中的每一个字节排列顺序。
举例说明,以一个32位4字节为例,数值0x1234_5678的小端字节序和大端字节序描述如下:
1. 小端字节序
字节 | 3 | 2 | 1 | 0 |
0x12 | 0x34 | 0x56 | 0x78 |
2. 大端字节序
字节 | 3 | 2 | 1 | 0 |
0x78 | 0x56 | 0x34 | 0x12 |
需要注意的是:
- 字节序仅仅描述字节之间的位置关系,并不描述字节内部位序关系。
- 对于一个特定的CPU体系结构,位序和字节序保持一致。
大端字节序主要是Power体系结构和网络传输设备。那么小端字节序的CPU和网络之间的进行数据转换时,需进行字节序转换。
飞腾CPU上的字节序
飞腾CPU支持小端字节序。
飞腾CPU上的字节转换指令
飞腾CPU提供五种字节转换指令,具体操作如下
REV <Wd>, <Wn>
REV <Xd>, <Xn> // REV64 <Xd>, <Xn> 这两条指令是一样的
REV16 <Wd>, <Wn>
REV16 <Xd>, <Xn>
REV32 <Xd>, <Xn>
下面我们用一个32位0x12345678和一个64位0x01234567_89abcdef来介绍上面五种操作的效果。
1. REV <Wd>, <Wn>
字节 | 3 | 2 | 1 | 0 |
操作前 | 0x12 | 0x34 | 0x56 | 0x78 |
操作后 | 0x78 | 0x56 | 0x34 | 0x12 |
2. REV <Xd>, <Xn>
字节 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
操作前 | 0x01 | 0x23 | 0x45 | 0x67 | 0x89 | 0xab | 0xcd | 0xef |
操作后 | 0xef | 0xcd | 0xab | 0x89 | 0x67 | 0x45 | 0x23 | 0x01 |
3. REV16 <Wd>, <Wn>
字节 | 3 | 2 | 1 | 0 |
操作前 | 0x12 | 0x34 | 0x56 | 0x78 |
操作后 | 0x34 | 0x12 | 0x78 | 0x56 |
4. REV16 <Xd>, <Xn>
字节 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
操作前 | 0x01 | 0x23 | 0x45 | 0x67 | 0x89 | 0xab | 0xcd | 0xef |
操作后 | 0x23 | 0x01 | 0x67 | 0x45 | 0xab | 0x89 | 0xef | 0xcd |
5. REV32 <Xd>, <Xn>
字节 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
操作前 | 0x01 | 0x23 | 0x45 | 0x67 | 0x89 | 0xab | 0xcd | 0xef |
操作后 | 0x67 | 0x45 | 0x23 | 0x01 | 0xef | 0xcd | 0xab | 0x89 |
基于上述指令可以实现字节转换的C语言函数为
inline __attribute_const__ __u32 __arch_swab16(__u16 x)
{
__asm__("rev16 %w0, %w1" : "=r" (x) : "r" (x));
return x;
}
inline __attribute_const__ __u32 __arch_swab32(__u32 x)
{
__asm__("rev %w0, %w1" : "=r" (x) : "r" (x));
return x;
}
inline __attribute_const__ __u64 __arch_swab64(__u64 x)
{
__asm__("rev %x0, %x1" : "=r" (x) : "r" (x));
return x;
}
inline __attribute_const__ __u32 __arch_swahw32(__u32 x)
{
__asm__ __volatile__ ("rev32 %x0, %x1\nrev16 %x0, %x0" : "=r" (x) : "r" (x));
return x;
}
inline __attribute_const__ __u32 __arch_swahb32(__u32 x)
{
__asm__("rev16 %w0, %w1" : "=r" (x) : "r" (x));
return x;
}
上述函数的具体意义与下面宏分别对应
#define ___constant_swab16(x) ((__u16)( \
(((__u16)(x) & (__u16)0x00ffU) << 8) | \
(((__u16)(x) & (__u16)0xff00U) >> 8)))
#define ___constant_swab32(x) ((__u32)( \
(((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
(((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
(((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
(((__u32)(x) & (__u32)0xff000000UL) >> 24)))
#define ___constant_swab64(x) ((__u64)( \
(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \
(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \
(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56)))
#define ___constant_swahw32(x) ((__u32)( \
(((__u32)(x) & (__u32)0x0000ffffUL) << 16) | \
(((__u32)(x) & (__u32)0xffff0000UL) >> 16)))
#define ___constant_swahb32(x) ((__u32)( \
(((__u32)(x) & (__u32)0x00ff00ffUL) << 8) | \
(((__u32)(x) & (__u32)0xff00ff00UL) >> 8)))