首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >高字节序(SPARC)处理器上的位域排序

高字节序(SPARC)处理器上的位域排序
EN

Stack Overflow用户
提问于 2012-12-12 00:58:45
回答 1查看 623关注 0票数 3

考虑下面的代码:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

#define FORCE_CAST(var, type) *(type*)&var

struct processor_status_register
{
unsigned int cwp:5;
unsigned int et:1;
unsigned int ps:1;
unsigned int s:1;
unsigned int pil:4;
unsigned int ef:1;
unsigned int ec:1;
unsigned int reserved:6;

unsigned int c:1;
unsigned int v:1;
unsigned int z:1;
unsigned int n:1;

unsigned int ver:4;
unsigned int impl:4;
}__attribute__ ((__packed__));



struct registers
{
       unsigned long* registerSet;
       unsigned long* globalRegisters;
       unsigned long* cwptr;
       unsigned long wim, tbr, y, pc, npc;
       unsigned short registerWindows;

       /* Though Intel x86 architecture allows un-aligned memory access, SPARC mandates memory accesses to be 8 byte aligned. Without __attribute__ ((aligned (8))) or a preceding dummy byte e.g. unsigned short dummyByte, the code below crashes with a dreaded Bus error and Core dump. For more details, follow the links below:

        http://blog.jgc.org/2007/04/debugging-solaris-bus-error-caused-by.html
        https://groups.google.com/forum/?fromgroups=#!topic/comp.unix.solaris/8SgFiMudGL4
*/

       struct processor_status_register __attribute__ ((aligned (8))) psr;
}__attribute__ ((__packed__));


int getBit(unsigned long bitStream, int position)
{
int bit;
bit = (bitStream & (1 << position)) >> position;
return bit;
}


char* showBits(unsigned long bitStream, int startPosition, int endPosition)
{
// Allocate one extra byte for NULL character
char* bits = (char*)malloc(endPosition - startPosition + 2);
int bitIndex;
for(bitIndex = 0; bitIndex <= endPosition; bitIndex++)
bits[bitIndex] = (getBit(bitStream, endPosition - bitIndex)) ? '1' : '0';
bits[bitIndex] = '\0';
return bits;
}


int main()
{
struct registers sparcRegisters; short isLittleEndian;

// Check for Endianness
        unsigned long checkEndian = 0x00000001;
        if(*((char*)(&checkEndian)))
            {printf("Little Endian\n"); isLittleEndian = 1;} // Little
Endian architecture detected
        else
            {printf("Big Endian\n"); isLittleEndian = 0;} // Big
Endian architecture detected

unsigned long registerValue = 0xF30010A7;

unsigned long swappedRegisterValue = isLittleEndian ? registerValue :
__builtin_bswap32(registerValue);

sparcRegisters.psr = FORCE_CAST(swappedRegisterValue, struct
processor_status_register);
registerValue = isLittleEndian ? FORCE_CAST (sparcRegisters.psr,
unsigned long) : __builtin_bswap32(FORCE_CAST (sparcRegisters.psr,
unsigned long));
printf("\nPSR=0x%0X, IMPL=%u, VER=%u, CWP=%u\n", registerValue,
sparcRegisters.psr.impl, sparcRegisters.psr.ver,
sparcRegisters.psr.cwp);
printf("PSR=%s\n",showBits(registerValue, 0, 31));

sparcRegisters.psr.cwp = 7;
sparcRegisters.psr.et = 1;
sparcRegisters.psr.ps = 0;
sparcRegisters.psr.s = 1;
sparcRegisters.psr.pil = 0;
sparcRegisters.psr.ef = 0;
sparcRegisters.psr.ec = 0;
sparcRegisters.psr.reserved = 0;
sparcRegisters.psr.c = 0;
sparcRegisters.psr.v = 0;
sparcRegisters.psr.z = 0;
sparcRegisters.psr.n = 0;
sparcRegisters.psr.ver = 3;
sparcRegisters.psr.impl = 0xF;

registerValue = isLittleEndian ? FORCE_CAST (sparcRegisters.psr,
unsigned long) : __builtin_bswap32(FORCE_CAST (sparcRegisters.psr,
unsigned long));

printf("\nPSR=0x%0X, IMPL=%u, VER=%u, CWP=%u\n", registerValue,
sparcRegisters.psr.impl, sparcRegisters.psr.ver,
sparcRegisters.psr.cwp);

printf("PSR=%s\n\n",showBits(registerValue, 0, 31));

return 0;
}  

我已经在Solaris 10 on SPARC上使用了gcc-4.7.2来编译以下代码,以产生Big-Endian输出:

代码语言:javascript
复制
Big Endian

PSR=0xF30010A7, IMPL=3, VER=15, CWP=20
PSR=11110011000000000001000010100111

PSR=0x3F00003D, IMPL=15, VER=3, CWP=7
PSR=00111111000000000000000000111101

我已经在Ubuntu-10.04上使用了gcc-4.4,在Intel-x86上编译了以下代码,以产生Little-Endian输出:

代码语言:javascript
复制
Little Endian

PSR=0xF30010A7, IMPL=15, VER=3, CWP=7
PSR=11110011000000000001000010100111

PSR=0xF30000A7, IMPL=15, VER=3, CWP=7
PSR=11110011000000000000000010100111

虽然后者与预期不谋而合,但有谁能解释一下Big-Endian对应物吗?考虑到showBits()方法是正确的,那么PSR=0x3F00003D如何产生IMPL=15、VER=3、CWP=7值呢?在Big-Endian系统中,位字段在内存中是如何排列和解释的?

EN

回答 1

Stack Overflow用户

发布于 2012-12-20 04:58:00

...PSR=0x3F00003D会产生IMPL=15,VER=3,CWP=7值吗?

它不能。我不知道你为什么要调用__builtin_bswap32,但是0x3F00003D并不代表你初始化时sparcRegisters结构的内存。

让我们检查一下这段代码:

代码语言:javascript
复制
sparcRegisters.psr.cwp = 7;
sparcRegisters.psr.et = 1;
sparcRegisters.psr.ps = 0;
sparcRegisters.psr.s = 1;
sparcRegisters.psr.pil = 0;
sparcRegisters.psr.ef = 0;
sparcRegisters.psr.ec = 0;
sparcRegisters.psr.reserved = 0;
sparcRegisters.psr.c = 0;
sparcRegisters.psr.v = 0;
sparcRegisters.psr.z = 0;
sparcRegisters.psr.n = 0;
sparcRegisters.psr.ver = 3;
sparcRegisters.psr.impl = 0xF;

具体的翻译如下:

代码语言:javascript
复制
7 => 00111
1 => 1
0 => 0
1 => 1
0 => 0000
0 => 0
0 => 0
0 => 000000
0 => 0
0 => 0
0 => 0
0 => 0
3 => 0011
F => 1111

因此,内存中的结构变为0011110100000000000000000000111111,其大端为0x3D00003F。

您可以使用以下代码进行确认(在solaris中使用CC进行测试):

代码语言:javascript
复制
#include <stdio.h>
#include <string.h>

struct processor_status_register
{
   unsigned int cwp:5;
   unsigned int et:1;
   unsigned int ps:1;
   unsigned int s:1;
   unsigned int pil:4;
   unsigned int ef:1;
   unsigned int ec:1;
   unsigned int reserved:6;

   unsigned int c:1;
   unsigned int v:1;
   unsigned int z:1;
   unsigned int n:1;

   unsigned int ver:4;
   unsigned int impl:4;
}__attribute__ ((__packed__));

int getBit(unsigned long bitStream, int position)
{
   int bit;
   bit = (bitStream & (1 << position)) >> position;
   return bit;
}

char* showBits(unsigned long bitStream, int startPosition, int endPosition)
{
   // Allocate one extra byte for NULL character
   static char bits[33];
   memset(bits, 0, 33);
   int bitIndex;
   for(bitIndex = 0; bitIndex <= endPosition; bitIndex++)
   {
      bits[bitIndex] = (getBit(bitStream, endPosition - bitIndex)) ? '1' : '0';
   }
   return bits;
}

int main()
{
   processor_status_register psr;
   psr.cwp = 7;
   psr.et = 1;
   psr.ps = 0;
   psr.s = 1;
   psr.pil = 0;
   psr.ef = 0;
   psr.ec = 0;
   psr.reserved = 0;
   psr.c = 0;
   psr.v = 0;
   psr.z = 0;
   psr.n = 0;
   psr.ver = 3;
   psr.impl = 0xF;

   unsigned long registerValue = 0;

   memcpy(&registerValue, &psr, sizeof(registerValue));
   printf("\nPSR=0x%0X, IMPL=%u, VER=%u, CWP=%u\n", registerValue,
      psr.impl, psr.ver,
      psr.cwp);

   printf("PSR=%s\n\n",showBits(registerValue, 0, 31)); 

   return 0;
}

此命令的输出为:

代码语言:javascript
复制
PSR=0x3D00003F, IMPL=15, VER=3, CWP=7
PSR=00111101000000000000000000111111
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13824870

复制
相关文章

相似问题

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