endian problems using the pack(1) pragma for data structure by the powerpc compiler

Thomas Korn Thomas.Korn@ifp-beisch.com
Thu Jul 24 14:07:00 GMT 2008


Hello all,

I have endian problems using the reference operator (&),
the deference  operator (*) or the element deference  operator (->)
together witch data structs which are compiled using pack(1).
The problems appear onlx if these data structs are located within
the litlle endian part of the memory RAM.

These are the failure patterns using the various referencing mechanisms 
(& or * or ->) for float values:

write1:          testLE1 = (testT1*)LITTLE_ENDIAN_ADDRESS;
                    testLE1->floatvalue = 50.0;

read_1a:       var = testLE1->floatvalue           ok
read_1b:       f = &testLE1->floatvalue;
                    var = *f;                                    failure

write    2:      testLE1 = (testT1*)LITTLE_ENDIAN_ADDRESS;
                    f = &testLE1->floatvalue;
                    *f = 50.0;

read_2a:       var = testLE1->floatvalue           failure
read_2b:       f = &testLE1->floatvalue;
                    var = *f;                                    ok


Used hardware (target):
Taishan board with PowerPC 440gx processor (big endian)

Development environment:
DENX Linux version 2.6.25.4
DENX ELDK version 4.1 build 2007-01-19
gcc release 4.0.0

Due to historical reasons the Linux kernel is configured so that a
small part of the memory can be used as an automated converter between 
little endian <-> big endian.
It is possible to write to a little endian address and read from the big 
endian address and vice versa.

I tried several possible invocations of the compiler, all show the same 
result :

      gcc -mcpu=440 -mno-strict-align -pedantic -Wall -O0 -o 
endian_float_pack1a endian_float_pack1a.c
      gcc -mcpu=405 -mno-strict-align -pedantic -Wall -O0 -o 
endian_float_pack1a endian_float_pack1a.c
      gcc -mcpu=405 -mno-strict-align                -Wall -O0 -o 
endian_float_pack1a endian_float_pack1a.c
      gcc -mcpu=405                                          -Wall -O0 
-o endian_float_pack1a endian_float_pack1a.c


My additional comment for the following code sample :



All accesses within the big endian part work well, regardsless of using 
pack(1) or pack(4).
Writing and reading of data structure elements with pack(4) within the 
little endian part is also ok -
but my program needs pack(1).


This is my code sample using pack(1) :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define BIG_ENDIAN_ADDRESS      0xB0000000
#define LITTLE_ENDIAN_ADDRESS   0xB0200000
#define ENDIAN_SIZE             0x100000

//#pragma pack(4)
#pragma pack(1)
typedef struct test1
{
  char  mist;
  int   intvalue;
  float floatvalue;
} testT1;
#pragma pack(0)

int main(int argc, char *argv[])
{
  testT1 *testLE1;
  float  *f, float1, float2;
  char   *ch;

  testLE1 = (testT1*)LITTLE_ENDIAN_ADDRESS;
  testLE1->floatvalue = 50.0;

  ch = (char*)&testLE1->floatvalue;
  f = &testLE1->floatvalue;
  printf("(1) %9f %9f [%02x,%02x,%02x,%02x] ", testLE1->floatvalue, *f, 
ch[0], ch[1], ch[2], ch[3]);
  float1 = testLE1->floatvalue;
  ch = (char*)&float1;
  printf("%9f [%02x,%02x,%02x,%02x] ", float1, ch[0], ch[1], ch[2], ch[3]);
  float2 = *f;
  ch = (char*)&float2;
  printf("%9f [%02x,%02x,%02x,%02x] ", float2, ch[0], ch[1], ch[2], ch[3]);
  printf("%9f\n", *(&testLE1->floatvalue));

  testLE1 = (testT1*)LITTLE_ENDIAN_ADDRESS;
  f = &testLE1->floatvalue;
  *f = 50.0;
  ch = (char*)&testLE1->floatvalue;
  f = &testLE1->floatvalue;
  printf("(2) %9f %9f [%02x,%02x,%02x,%02x] ", testLE1->floatvalue, *f, 
ch[0], ch[1], ch[2], ch[3]);
  float1 = testLE1->floatvalue;
  ch = (char*)&float1;
  printf("%9f [%02x,%02x,%02x,%02x] ", float1, ch[0], ch[1], ch[2], ch[3]);
  float2 = *f;
  ch = (char*)&float2;
  printf("%9f [%02x,%02x,%02x,%02x] ", float2, ch[0], ch[1], ch[2], ch[3]);
  printf("%9f\n", *(&testLE1->floatvalue));

  return 0;
}

If I run the program the console outputs are different :

Output onto the console using pack(4): The values in the brackets [....] 
show the byte ordering
(1) 50.000000 50.000000 [00,00,48,42] 50.000000 [42,48,00,00] 50.000000 
[42,48,00,00] 50.000000
(2) 50.000000 50.000000 [00,00,48,42] 50.000000 [42,48,00,00] 50.000000 
[42,48,00,00] 50.000000

Output onto the console using pack(1): The values in the brackets [....] 
show the byte ordering
(1) 50.000000  0.000000 [42,48,00,00] 50.000000 [42,48,00,00]  0.000000 
[00,00,48,42] 50.000000
(2)  0.000000 50.000000 [00,00,48,42]  0.000000 [00,00,48,42] 50.000000 
[42,48,00,00]  0.000000


regards
Thomas

-- 

Thomas Korn
ifp - IngenieurbÃŒro fÃŒr Prozessautomatisierung
Friedrich Werber Str. 44

D-78315 Radolfzell
Tel: (+49) 7732 98 27 89 - 13
Fax: (+49) 7732 98 27 89 - 44

Internet: www.ifp-beisch.com
EMail:    Thomas.Korn@ifp-beisch.com





More information about the Gcc mailing list