rokicki@rocky.STANFORD.EDU (Tomas Rokicki) (02/14/88)
I just tracked down this bug that took me immense amounts of time to find, and I discovered something about Manx C. I found out that one of my friends had also run into and wasted hours finding this anomaly. Specifically, Manx C does not long-word align structures containing long words! (It also doesn't apparently long-word align long words.) The ramifications of this are two-fold: - Programs compiled with Manx C and then run on a 68020 system will run slower, as some (probably half) of their long word accesses will need two memory accesses instead of one. - You cannot statically allocate anything that needs to be on a long word boundary; for instance, packets. (Not that you should anyway, as they should be MEMF_PUBLIC, but with the current release that doesn't matter anyway.) Anything that will be converted to a BPTR and back will have problems. Oh yeah, this is Manx 3.4b. I can't think of any good way to fix this problem; I refuse to recompile all my programs with 32-bit ints. Why did Manx do this? The only case where it costs anything is in passing arguments to subroutines; all other occurances would cost very little memory at all. And subroutine arguments could be handled as they are now, or perhaps modified. I don't care. What does Lattice do (4.0), anyone out there know? -tom
dillon@CORY.BERKELEY.EDU (Matt Dillon) (02/14/88)
>I just tracked down this bug that took me immense amounts of time >to find, and I discovered something about Manx C. I found out that >one of my friends had also run into and wasted hours finding this >anomaly. Specifically, Manx C does not long-word align structures >containing long words! (It also doesn't apparently long-word align >long words.) The ramifications of this are two-fold: It might not be preferable, but can hardly be called a bug. Remember that warning a lonnngg time ago about declaring such items as FileInfoBlocks auto? You can't for the very reason that they require longword alignment and since longwords don't, no assumption can be made as to the alignment the compiler used. The only solution is to AllocMem() the structure, or to use such generally unportable features as the +A link option in Aztec's linker (force a module to be aligned on a longword boundry). In the latter case, only a partial fix is obtained. There are assembly level constructs that allow you to align items however you wish but, of course, this requires inline assembly. -Matt
rokicki@rocky.STANFORD.EDU (Tomas Rokicki) (02/14/88)
dillon@CORY.BERKELEY.EDU (Matt Dillon) writes: > > (Manx don't put longword entities on longword boundaries . . .) > It might not be preferable, but can hardly be called a bug. > Remember that warning a lonnngg time ago about declaring such items as > FileInfoBlocks auto? You can't for the very reason that they require > longword alignment and since longwords don't, no assumption can be made > as to the alignment the compiler used. Any compiler for a 68000/68020 machine, that does not do everything reasonable to put longword structures on longword boundaries, is buggy. Period. The Amiga is most certainly a 68000/68020 machine. I wonder how much slower those 68020 machines run because all of the Manx compiled commercial software (at least those with 16-bit ints) don't have their longwords aligned correctly? The costs are absolutely minimal, with the sole exception of passing mixed longword and 16-bit arguments to functions, in which case the costs are fair. I can't imagine any excuse for such behavior. -tom
dillon@CORY.BERKELEY.EDU (Matt Dillon) (02/15/88)
>>dillon@CORY.BERKELEY.EDU (Matt Dillon) writes: >>> > (Manx don't put longword entities on longword boundaries . . .) >>> It might not be preferable, but can hardly be called a bug. >>> Remember that warning a lonnngg time ago about declaring such items as >>> FileInfoBlocks auto? You can't for the very reason that they require >>> longword alignment and since longwords don't, no assumption can be made >>> as to the alignment the compiler used. >> >>Any compiler for a 68000/68020 machine, that does not do everything >>reasonable to put longword structures on longword boundaries, is buggy. >>Period. The Amiga is most certainly a 68000/68020 machine. I wonder >>how much slower those 68020 machines run because all of the Manx >>compiled commercial software (at least those with 16-bit ints) don't >>have their longwords aligned correctly? I wouldn't mind seeing a compile time option to fix the problem, but there are just as many reasons for NOT wanting them on longword boundries. You might want a more compact structure. C-A sure did, and... If you were to make longword alignment the default, your C compiler would suddenly become totally incompatible with almost every Amiga structure in existance. For example: struct Menu, &menu.MenuName relative to &menu.NextMenu is on a word boundry. struct MenuItem, Node, Message, and thus IORequest, IOStdReq, etc..... -Matt
rokicki@rocky.STANFORD.EDU (Tomas Rokicki) (02/15/88)
> You might want a more compact structure. > > C-A sure did, and... > > If you were to make longword alignment the default, your C compiler > would suddenly become totally incompatible with almost every Amiga structure > in existance. > > For example: struct Menu, &menu.MenuName relative to &menu.NextMenu > is on a word boundry. struct MenuItem, Node, Message, and thus IORequest, > IOStdReq, etc..... > > -Matt Oh my, I didn't realize the problem was quite so deep seated! Even the Amiga software wasn't really designed with the 68020 in mind, then! I always order my structures so longwords stay on longword boundaries. You should lose at most three bytes per structure. And the structures are ingrained enough so they will not change . . . You are absolutely correct, though, about Amiga structures not being organized around a 32-bit word, even at the lowest level (struct Node{struct Node *ln_Succ,*ln_Pred; UBYTE ln_type;BYTE ln_Pri;char *ln_Name;};). Ouch, ouch, double ouch. Putting in a SHORT ln_Pad would have added 2 bytes to this 14-byte structure; I think that would have been a worthwhile tradeoff. No use crying over spilt milk, I guess. But if some new, later Amiga does have such changes that most code needs recompiling to run (for instance, MEMF_PUBLIC enforced due to an MMU or some such) then it might be worthwhile to investigate the cost of making this change. -tom
manx@well.UUCP (Jim Goodnow II) (02/15/88)
In article <1042@rocky.STANFORD.EDU> rokicki@rocky.STANFORD.EDU (Tomas Rokicki) writes: >..... Specifically, Manx C does not long-word align structures >containing long words! (It also doesn't apparently long-word align >long words.) The ramifications of this are two-fold: > >- Programs compiled with Manx C and then run on a 68020 system will >run slower, as some (probably half) of their long word accesses will >need two memory accesses instead of one. > >- You cannot statically allocate anything that needs to be on a long >word boundary; for instance, packets. (Not that you should anyway, as >they should be MEMF_PUBLIC, but with the current release that doesn't >matter anyway.) Anything that will be converted to a BPTR and back >will have problems. > ...... >-tom First off, there is a definite penalty with long-word aligning data unless all your data consists of longs. Worst case would be that every char or short would generate an extra two bytes of filler to align the next item. This would be true regardless of whether int is 32 bits. Second, the number of programs running on 68020 systems is pretty much a minority at present. There will be an option for alignment in a future version of the compiler to rectify this. Third, data items allocated on the stack cannot be guaranteed to be allocated on long word boundaries when passing some arguments as shorts without making the function preamble more complicated. Fourth, you can use malloc() or AllocMem() which both are guaranteed to be aligned to a long word boundary. Finally, I can find nothing in the dpANSI standard about alignment requirements of static data objects. I might have missed it, I've only been working with it for a couple of weeks. To say it's a bug is a little strong, maybe a desired feature??? :-) Jim Goodnow II Disclaimer: I work for Manx, so I don't gotta give none...
cmcmanis%pepper@Sun.COM (Chuck McManis) (02/16/88)
Tom Rokicki wrote : > I just tracked down this bug that took me immense amounts of time > to find, and I discovered something about Manx C. I found out that > one of my friends had also run into and wasted hours finding this > anomaly. Specifically, Manx C does not long-word align structures > containing long words! (It also doesn't apparently long-word align > long words.) > Correct-a-mundo! Since the 68000 can load longwords on odd word addresses neither C compiler cares to put them on longword boundaries. It does align them on word boundaries however. So you can very cruftily get around the problem (in the case of the FileInfoBlock that Matt mentioned) like so : short mem[(sizeof(struct FileInfoBlock) >> 1)+1]; struct FileInfoBlock *fi; fi = (struct FileInfoBlock *)(((ULONG)(mem) & 3) ? &mem[1] : &mem[0]); Now, is that gross code or what? --Chuck McManis uucp: {anywhere}!sun!cmcmanis BIX: cmcmanis ARPAnet: cmcmanis@sun.com These opinions are my own and no one elses, but you knew that didn't you.
dillon@CORY.BERKELEY.EDU (Matt Dillon) (02/16/88)
> short mem[(sizeof(struct FileInfoBlock) >> 1)+1]; > struct FileInfoBlock *fi; > > fi = (struct FileInfoBlock *)(((ULONG)(mem) & 3) ? &mem[1] : &mem[0]); > >Now, is that gross code or what? >--Chuck McManis Definately, but it sure beats having to AllocMem() the block. It would be nice if one could have a salloc() call ... allocate memory off the stack. Although Aztec (and lattice?) use a frame pointer, they apparaently also push and pop the registers using the stack pointer, so the call would have to be implemented like: ptr = salloc(bytes) (allocates on a longword boundry) spop() pops the allocated stack frame, must call before return statement / end of subroutine. -Matt
jesup@pawl20.pawl.rpi.edu (Randell E. Jesup) (02/17/88)
In article <8802160646.AA14996@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes: > ptr = salloc(bytes) (allocates on a longword boundry) > spop() pops the allocated stack frame, must > call before return statement / end of > subroutine. Actually, spop() isn't needed before an exit at all. Lattice (and I'm fairly sure Manx) use the unlink instruction, which will restore the old stack pointer. The only thing to watch out for is stack overflow. // Randell Jesup Lunge Software Development // Dedicated Amiga Programmer 13 Frear Ave, Troy, NY 12180 \\// beowulf!lunge!jesup@steinmetz.UUCP (518) 272-2942 \/ (uunet!steinmetz!beowulf!lunge!jesup) BIX: rjesup
dillon@CORY.BERKELEY.EDU (Matt Dillon) (02/18/88)
:In article <8802160646.AA14996@cory.Berkeley.EDU> dillon@CORY.BERKELEY.EDU (Matt Dillon) writes:
:> ptr = salloc(bytes) (allocates on a longword boundry)
:> spop() pops the allocated stack frame, must
:> call before return statement / end of
:> subroutine.
:
: Actually, spop() isn't needed before an exit at all. Lattice
:(and I'm fairly sure Manx) use the unlink instruction, which will restore
:the old stack pointer. The only thing to watch out for is stack overflow.
Yes, they do use LINK/UNLK, but they also use MOVEM REGS,-(SP) to
save registers, and before the RTS do a MOVEM (SP)+,REGS. If the SP isn't
in the right place, a bogus set of registers will be restored.
-Matt