This raises some interesting surprises when we start working with the bootrom sources. Our gcc cross compiler also treats longs as 4 byte objects, so this generally is not a problem. The trouble arises when we start feeding some of that code to a native x86 compiler for a modern 64 bit system. A long in that world is now 8 bytes (64 bits).
With that background, consider the following error that I just ran into when assembling sun3/trap.s. We have the following line of code:
subql #sizeofintstack,d0I get the error:
../sun3/trap.s:357: Error: operands mismatch -- statement `subql #0x18,d0' ignoredNotice that the value 0x18 has been substituted for "sizeofintstack". This is indeed an error because the Q form of the sub instruction only allows a 3 bit immediate value (1-8) and the value 0x18 is clearly out of this range.
This value comes from the file sun3/assym.h, which we generated by running the helper utility genassym.c on our x86 system. You can probably see where this is heading.
#define sizeofintstack 0x18The line in tools/genassym.c that generates this is:
printf("#define sizeofintstack 0x%x\n", sizeof(struct intstack));This structure is define in sun3/m68vectors.h as follows:
struct intstack { short i_sr; /* Stacked status register */ long i_pc; /* Program counter of error */ short i_fvo; /* Format & vector offset */ };A quick inspection of this would make us think that this is an 8 byte item. How does it end up 0x18 bytes in size (24 bytes)? Each element of the structure gets padded to be aligned on an 8 byte boundary for the x86, that is how.
It won't be enough just to change "long" to u32 in this case like I hoped. We will need to also tell the compiler not to pad the structure. Something like the following would do it:
struct intstack { int16 i_sr; /* Stacked status register */ int32 i_pc; /* Program counter of error */ int16 i_fvo; /* Format & vector offset */ } __attribute__((packed));This raises several questions. Here we are concerned with getting the native x86 compiler and the cross compiler for the m68k to handle things in the same way. This is only a concern for the genassym.c program, and only a small part of the bootrom code is exposed to genassym.c
However it may be necessary to force structure packing for the cross compiler, and this remains to be seen. The Sun programmers didn't need to worry about this. Clearly their compiler both treated a long as a 4 byte item and did not do structure padding for short values.
Along with "long" any pointers may be sources of trouble because on a 64 bit x86, a pointer is a 64 bit object, whereas on the m68k it is a 32 bit object.
We don't need to worry about the use of "long" in the context of the m68k cross compiler, but I am worried about possible structure padding that may be done by gcc that was not done by the sun compiler. To investigate this issue of padding I put together a test case, then used "objdump" to inspect the generated code. After doing this with the following code, I am satisfied that the m68k cross compiler is not doing anything surprising with padding.
/* Does gcc pad structures ? */ struct xyz { short aa; int bb; short cc; short dd; struct xyz *next; }; struct xyz *p; void check ( void ) { int i1, i2, i3; p = (struct xyz *) 0; i1 = sizeof(struct xyz); i2 = (int) &(p->cc); i3 = (int) &(p->next); }
Tom's Computer Info / tom@mmto.org