[comp.arch] RISC hard to program?

peterd@opus.cs.mcgill.ca (Peter Deutsch) (07/13/90)

** Opinions wanted, raging debated expected. Join now! Avoid the rush! **


In article <40088@mips.mips.COM>, mark@mips.COM (Mark G. Johnson) writes:
> The June 1990 issue of _IEEE_Micro_ contains an article about the
> Morotola 68040, written by some of its designers.  The article agrees
> with some of the advertising copy, saying "The sustained
> performance level is 20 VAX-equivalent MIPS and 3 Mflops at a clock
> speed of 25 MHz."  (1st paragraph, 4th sentence).
.  .  .
> So, the data and the claim that 68040==20VAXmips  implies that the earlier
> 68020 has a "sustained performance level of 4.9 VAX-equivalent MIPS"
> (4.9 = 20/4.1).  Does anybody seriously believe this?
...
> MIPS.  This makes the 68040 a 16 VAXmips machine (at most), not 20 VAXmips
> as advertised.

> Of course the best method would be to lay hands on an actual computer
> system that uses the 68040 and benchmark it; presumably Motorola
> and/or NeXT and/or HP will do this someday.  Prediction: the SPECmark
> will be significantly below 20.0.

Background: This gives me an opportunity to raise a
question that I would like addressed. I am systems manager
for a reasonably sized comp.sci. department (about 60
machines, with a new lab or two under construction that
will take this to about 120 by the start of term).We have
a couple of Sun 3/280s, a couple of Sun 4/280s, the usual
passle of Sun 3/50s, our first SPARCs in place with more
on the way, about 1/2 dozen NeXT with more on the way,
plus the usual ragtag collection of widows and orphens (a
MIPS, a few HPs, a uVax II, etc).

My home machine used to be a Sun 3/280 (now I have a NeXT,
yes there's a few out there!) Most of our students are on
the Sun 4/280 pair, along with the usual collection of
grad student projects, imported freeware, professors'
code, etc, etc.  I myself have done fair sized programming
projects on our earlier (now departed) Vax 11/780s and the
Sun 3's (plus GASP! PCs) but my exposure to programming on
the SPARC architecture has been mostly through word of
mouth from my staff and the user community (Sigh, I must
be a _REAL_ manager now :-(

Preamble: From my own exposure to user complaints about
unportable software, etc I would allege that that the SPARC
architecture appears to be inherently less forgiving of the
programmer than the 68k architecture. I keep receiving
reports of software that ran fine on machine 'x' (often
68k machines, Vaxen etc) but that either wont compile or
wont run on the Sun 4's. I have had this explained to me
(by a defender of the SPARC architecture) as being due to
the fact that the SPARC architecture is less forgiving of
poor programming (eg byte alignment problem in structures,
ignoring warning messages, etc). It was stated to me that
"well-wrtten programs work, if not it's the programmer's
fault."

Now to the question: First, is it true that SPARC is
inherently less forgiving? If so, is it due to
"limitations" of the architecture (eg. byte-alignment
restrictions) or is this a "feature" through which sloppy
programmers are now being taught the error of their ways?

More specifically, If I accepted the rumours that porting
to the SPARC was harder as an axiom could I argue that
this was a "bug" of the architecture, not a feature, in the
same way that difficulty addressing a 65k array on an 8088
machine is a residual bug due to limited segment size of
that chip?

Now, a few caveats, disclaimers, etc. Almost all the
programming problems I have heard about were in C, which
is an inherently low level language (although at least one
very large Pascal program, a compiler project, never was
ported successfully) and perhaps this should have been
sent to comp.lang.c. I _would_ like answers to be centred
around the problems of C programmers if this is a
reasonable thing to do.

The original motivation for this posting was as a followup
to a discussion I had that originated from my observation
that I seem to hear of more porting problems with the Sun
4's than the Sun 3's. One of my staff disputed my claim,
claiming that the problem was with poor C programmers, not
the SPARC (or RISC in general).

As I have not attempted a serious program on the machine,
nor am I all that familiar with its internals, I do _NOT_
claim to be capable to make the comparison, but have
trouble swallowing the claim the bugs due to byte-alignment
restrictions showing through (if in fact, that is what is
happening) is the programmer's fault. I think the
"near/far" abomination I used to have to use in the 8088 C
compilers showed a fault of the 8088 architecture, raising
up through the language to bit the programmer (and I
understand that smarter compilers now can hid this from
me, well so my poor friends still programming DOS machines
claim).

Given the (admittedly second-hand) reports of problems, is
this not a similar hardware problem raising up through the
language? Or am I really out to lunch here? If so, I
apologize in advance, so don't flame.

Note, I am _NOT_ disputing the worth of RISC
architectures, which have given us dramatic performance
gains. I'm just asking if we've paid a price in
"servicability"?

So, here's the clincher. My collegue claims there are NO C
programs that will:
a) Pass lint on the Sun 3
b) Pass lint on the Sun 4
c) Run, giving a "correct" answer on the Sun3, without crashing.
d) Either crash or give the "wrong" answer on the Sun 4.

In effect, any crash would be due to faulty programmer,
not a faulty architecture.

Is this true? Is the reverse true (ie crash on a Sun 3,
but not on the Sun 4)? Can we draw valid conclusions about
the frequency of either? Both?


Enquiring minds want to know. If the appropriate programs
exist, I would especially like to see them (email please).
Otherwise, I'll follow comments in the groups.

I now await the verdict of others more knowledgeble than
myself...


			- peterd

kaufman@Neon.Stanford.EDU (Marc T. Kaufman) (07/13/90)

In article <2162@opus.cs.mcgill.ca> peterd@opus.cs.mcgill.ca (Peter Deutsch) writes:

>** Opinions wanted, raging debated expected. Join now! Avoid the rush! **

-Preamble: From my own exposure to user complaints about
-unportable software, etc I would allege that that the SPARC
-architecture appears to be inherently less forgiving of the
-programmer than the 68k architecture. I keep receiving
-reports of software that ran fine on machine 'x' (often
-68k machines, Vaxen etc) but that either wont compile or
-wont run on the Sun 4's. I have had this explained to me
-(by a defender of the SPARC architecture) as being due to
-the fact that the SPARC architecture is less forgiving of
-poor programming (eg byte alignment problem in structures,
-ignoring warning messages, etc). It was stated to me that
-"well-wrtten programs work, if not it's the programmer's
-fault."

SPARC requires fullword alignment for 32-bit operands and DOUBLEword
alignment (e.g. 8-bytes) for 64-bit operands, in memory.  This is more
restrictive than the 68K, which was prepared (at the 68020 and above) to
accept byte alignment for all operand sizes.  The 68000 only required 16-bit
alignment at worst, but then it was only a 16-bit machine.  I am not surprised
that there is trouble trying to use a data structure on the SPARC that was
created on a machine with less restrictive alignment requirements.

It seems to me that, if downward compatibility is absolutely required, it is
the C (or other language) compiler's fault, not the user's.  After all, the
SPARC is fast enough that executing extra code to piece together misaligned
data operands is a small price to pay. :-)

Data misalignment problems are independent of how well a program is written,
especially if the program was written for another target architecture.

Marc Kaufman (kaufman@Neon.stanford.edu)

beemster@fwi.uva.nl (Marcel Beemster) (07/13/90)

peterd@opus.cs.mcgill.ca (Peter Deutsch) writes:
>unportable software, etc I would allege that that the SPARC
>architecture appears to be inherently less forgiving of the
>programmer than the 68k architecture. I keep receiving
>reports of software that ran fine on machine 'x' (often
>68k machines, Vaxen etc) but that either wont compile or
>wont run on the Sun 4's. I have had this explained to me

>Now to the question: First, is it true that SPARC is
>inherently less forgiving?

No, not always. The following program reflects a bug that actually
occurred on software developed on a Sun-4. Things ran fine until the
software was ported to a Sun-3:

---------------
main()
{
  pr3( "Hello" , "world" , "!\n" ) ;
  pr3( "This" , "is wrong" ) ;
}

pr3( s1 , s2 , s3 )
char *s1, *s2, *s3 ;
{
  printf( "%s %s %s" , s1 , s2 , s3 ) ;
}
--------------End of program

As you see, the second call to pr3() lacks one parameter. When run
on a Sun-4, compiled with either -O or not, the output is:

hello world !
This is wrong !

When run on a Sun-3, the output is:

hello world !
This is wrong (null)

Now you might argue that the Sun-3's answer is more correct than the
Sun-4's, but in the abovementioned software the first call had left the
correct parameter on the register stack for a subsequent call. Of course
all this has more to do with parameter-passing conventions than
RISC vs. CISC.

Now this is just one counterexample. In general my feelings towards
software development are: "If it runs on s SPARC, it runs everywhere",
i.e., if you want to send reliable software out to the world, develop on
a machine with a highly optimizing compiler, not one of those
C-is-just-a-macro-assembler-kind-of-thing.

>So, here's the clincher. My collegue claims there are NO C
>programs that will:
>a) Pass lint on the Sun 3
>b) Pass lint on the Sun 4
>c) Run, giving a "correct" answer on the Sun3, without crashing.
>d) Either crash or give the "wrong" answer on the Sun 4.

pr3: variable # of args.        ts.c(9)  ::  ts.c(4)
printf returns value which is always ignored

++marcel				beemster@fwi.uva.nl
"So they destroyed their planet, why?", "That was better for the economy..."

lindsay@MATHOM.GANDALF.CS.CMU.EDU (Donald Lindsay) (07/13/90)

In article <1139@carol.fwi.uva.nl> beemster@fwi.uva.nl 
	(Marcel Beemster) writes:
>In general my feelings towards
>software development are: "If it runs on s SPARC, it runs everywhere",

It's good for portability to develop code on the _least_ forgiving
machine that you can find.

I once did it the other way around, to my sorrow.  We had a large
compiler that ran on a DEC-20, and was supposedly working.  I ported
it to a VAX with BSD 4.2, and there were no end of seg faults.  Why?
Well, the 20 had a virtual address space of 256 KW.  So, a large
compiler which generated a wild address would reference something
that existed.  In a 4 GB space, that changed.  Further, it turned out
that the average wild pointer was used for reads, gathering data
which resulted in a boolean decision.  So, there had always been a
fair chance that the branch would go the right way!

Then I ported it from the VAX to a Sun-3.  Another disaster!  Sun had
intelligently made page zero illegal, so that nul pointers would
trap.

If the original development had been done on the most unforgiving
machine, the ports would have been started a bit later - but would
have been finished sooner.

In general, the best way to develop portable code is to force the
original development to happen on two machines at once.  This means
that the original team is still there during that crucial first port.
Plus, portability issues can surface _before_ the design is frozen.

-- 
Don		D.C.Lindsay

ken@argus.UUCP (Kenneth Ng) (07/14/90)

In article <9895@pt.cs.cmu.edu>, lindsay@MATHOM.GANDALF.CS.CMU.EDU (Donald Lindsay) writes:
: It's good for portability to develop code on the _least_ forgiving
: machine that you can find.
[edit]
: In general, the best way to develop portable code is to force the 
: original development to happen on two machines at once.  This means 
: that the original team is still there during that crucial first port.
: Plus, portability issues can surface _before_ the design is frozen.

Agreed, and do it on as drastically different machines as you possibly
can.  Two word default integer and four word default integer and integers
stored big and little endin as examples.  If you really want to take a bruising
try an EBCDIC and ASCII machine :-).

The only thing I don't like about this approach is that you have to live with
the poorest machine/os/compiler implementations you want to run your software
on.  


-- 
Kenneth Ng: Post office: NJIT - CCCC, Newark New Jersey  07102
uucp !andromeda!galaxy!argus!ken *** NOT ken@bellcore.uucp ***
bitnet(prefered) ken@orion.bitnet  or ken@orion.njit.edu

mrc@Tomobiki-Cho.CAC.Washington.EDU (Mark Crispin) (07/14/90)

In article <9895@pt.cs.cmu.edu> lindsay@MATHOM.GANDALF.CS.CMU.EDU (Donald Lindsay) writes:
>In article <1139@carol.fwi.uva.nl> beemster@fwi.uva.nl 
>	(Marcel Beemster) writes:
>>In general my feelings towards
>>software development are: "If it runs on s SPARC, it runs everywhere",
>
>It's good for portability to develop code on the _least_ forgiving
>machine that you can find.
>
>I once did it the other way around, to my sorrow.  We had a large
>compiler that ran on a DEC-20, and was supposedly working.  I ported
>it to a VAX with BSD 4.2, and there were no end of seg faults.
>Then I ported it from the VAX to a Sun-3.  Another disaster!

My experience with porting code between DEC-20, VAX BSD 4.3, Sun-3,
NeXT, Sun-4, DEC RISC, Macintosh, MS-DOS, and Sequent suggests that
all of these systems are "unforgiving" in their own unique ways.  The
DEC-20 will nail you if you think that bytes are in any way related to
the unit of addressing or if you think you know in what direction the
stack grows.  MS-DOS will nail you if you think that pointers will fit
inside an int or if you use strings larger than 64K.  Macintosh will
nail you on 64K limits and memory management too -- malloc()/free() is
not how you want to use memory on a Mac.  VAXen and other
little-endian machines will nail you if you think that a 16-bit
quantity can be copied to a pair of bytes.  And so on.

It seems to me that using an ANSI compiler and ANSI-style prototyping
saves an amazing amount of time, more than initially developing on any
particular architecture.
 _____   | ____ ___|___   /__ Mark Crispin, 206 842-2385, R90/6 pilot, DoD#0105
 _|_|_  -|- ||   __|__   /  / 6158 Lariat Loop NE   "Gaijin! Gaijin!"
|_|_|_|  |\-++-  |===|  /  /  Bainbridge Island, WA "Gaijin ha doko ka?"
 --|--  /| ||||  |___|    /\  USA 98110-2098        "Niichan ha gaijin."
  /|\    | |/\| _______  /  \ "Chigau. Gaijin ja nai. Omae ha gaijin darou"
 / | \   | |__|  /   \  /    \"Iie, boku ha nihonjin." "Souka. Yappari gaijin!"
Hee, dakedo UNIX nanka wo tsukatte, umaku ikanaku temo shiranai yo.

guy@auspex.auspex.com (Guy Harris) (07/15/90)

>Preamble: From my own exposure to user complaints about
>unportable software, etc I would allege that that the SPARC
>architecture appears to be inherently less forgiving of the
>programmer than the 68k architecture.

More correctly, the SPARC implementation of C under SunOS, at least, is,
in general, less forgiving of the programmer than the 68K implementation
of C under SunOS.  Much of this is a characteristic of the architecture,
although some could perhaps be worked around in software.

The same is true of many other pairs of UNIX C implementations as well,
for reasons having to do with the architecture, with the compiler, with
the OS, etc..

>I keep receiving reports of software that ran fine on machine 'x' (often
>68k machines, Vaxen etc) but that either wont compile or
>wont run on the Sun 4's. I have had this explained to me
>(by a defender of the SPARC architecture) as being due to
>the fact that the SPARC architecture is less forgiving of
>poor programming (eg byte alignment problem in structures,
>ignoring warning messages, etc). It was stated to me that
>"well-wrtten programs work, if not it's the programmer's
>fault."

I'd agree with said defender.  I'm not sure what the "byte alignment
problem in structures" is; the SPARC C compiler puts structure members
on the boundaries they require, so it's not as if a "poorly-written
structure" can cause the program to blow up by violating an alignment
restriction.

In the Sun C implementation, by default you cannot, say, have a buffer
full of structures that are not necessarily aligned on the proper
boundary for that structure (basically, the most restrictive alignment
boundary for all the members of the structure), and just convert a
pointer to an arbitrary byte in that buffer into a pointer to a
structure and expect it to work.  However, you can specify the
"-misalign" flag to the compiler, and it will generate code that lets
you do this (basically, it tests the alignment of the pointer before
using it; if it's properly aligned, it uses it normally, otherwise it
calls a library routine to access the members of the structure.

However, there's nothing unique to SPARC about this; there's nothing
even unique to RISC about this!  I can think of machines generally
thought of as "CISC" that impose alignment restrictions similar to those
of the SPARC, e.g. all but the most recent of the AT&T WE32K chips. 
Even the PDP-11 and 68K prior to the 68020 required 2-byte alignment for
quantities larger than one byte.

>More specifically, If I accepted the rumours that porting
>to the SPARC was harder as an axiom could I argue that
>this was a "bug" of the architecture, not a feature, in the
>same way that difficulty addressing a 65k array on an 8088
>machine is a residual bug due to limited segment size of
>that chip?

You can argue anything you want.  Whether others will agree with you is
another matter. 

I, for one, would not agree with you if you made that argument.  As
shown by the "-misalign" flag to the compiler, you certainly *can*
access misaligned quantities on a SPARC; it just takes more code, and
extra work by the compiler.

While this does impose a performance penalty, so does accessing
misaligned data on the architectures with which I'm familiar that let
you do so directly.  The performance hit of doing so on SPARC (or other
strict-alignment architectures) is probably greater than that on
68020-and-up (or other loose-alignment architectures); I don't have any
numbers for that, though.

However, if references like that are sufficiently rare in most cases
that whatever performance gain was obtained by leaving hardware support
for that out of SPARC (either by devoting the circuitry to some other
function, or by removing an extra delay from the data path, or by
getting a basically-faster chip out the door sooner, or...) outweighs
the performance loss of doing misaligned accesses in software in most
cases, it may be the right thing to do to leave it out, at least for
those cases.

There may well be problems for which the cost of leaving alignment
restrictions in the instruction set outweighs whatever benefits you got
from leaving it out, but that just argues against using strict-alignment
machines for those particular problems.

Now, the alignment restriction isn't the *only* characteristic of SPARC
and its C implementations that punishes sloppy programming.  Another is
the calling sequence used for passing structures and unions to
subroutines; in most such calling sequences, you can get away with
passing a member of a union to a routine that expects the union, or vice
versa.  That's not the case with the SPARC calling sequence; I think
this is, however, the result of the choice of calling sequence used for
structures and unions 4 bytes or less long, rather than something
imposed by the instruction set architecture.

>Now, a few caveats, disclaimers, etc. Almost all the
>programming problems I have heard about were in C, which
>is an inherently low level language (although at least one
>very large Pascal program, a compiler project, never was
>ported successfully)

What machine was the target for the compiler?  If the target machine was
the same as the machine on which the compiler was being run, "porting"
is more than just recompiling - 68K machine code doesn't generally run
on SPARC machines without some extra work being involved.

>The original motivation for this posting was as a followup
>to a discussion I had that originated from my observation
>that I seem to hear of more porting problems with the Sun
>4's than the Sun 3's. One of my staff disputed my claim,
>claiming that the problem was with poor C programmers, not
>the SPARC (or RISC in general).

The bulk of the problems I've seen in porting code to SPARC have been
due to 1) the aforementioned "passing unions to routines" problem and 2)
code that "knows" how C argument lists are laid out in memory, rather
than using the "varargs" mechanism.  In neither case are those due to
alignment problems.

Neither of these are due to anything peculiar to RISC (CISC compilers
have been known to pass arguments in registers, rather than on the
stack, as well, and use of a register-based calling sequence
contributed, at least in part, to both problems), and neither would have
been problems had the programmer not cheated. 

>Given the (admittedly second-hand) reports of problems, is
>this not a similar hardware problem raising up through the
>language?

The alignment problem can be hidden by the language, at least with more
recent compilers, as I'd noted.

>Note, I am _NOT_ disputing the worth of RISC
>architectures, which have given us dramatic performance
>gains. I'm just asking if we've paid a price in
>"servicability"?

We probably have paid some such price; I suspect it was worth it.

wsd@cs.brown.edu (Wm. Scott `Spot' Draves) (07/15/90)

In article <1990Jul13.071511.22250@Neon.Stanford.EDU> kaufman@Neon.Stanford.EDU (Marc T. Kaufman) writes:


   SPARC requires fullword alignment for 32-bit operands and DOUBLEword
   alignment (e.g. 8-bytes) for 64-bit operands, in memory.  

Are you sure?  I think doubles can be loaded from 4 byte boundaries.
Witness the following code, which runs fine on this SS1:

main()
{
   char data[12];
   double d, *dp;

   dp = (double *)(data + 0);
   *dp = 66.6;
   printf("%g\n", *dp);

   dp = (double *)(data + 4);
   *dp = 66.6;
   printf("%g\n", *dp);
}

   Data misalignment problems are independent of how well a program is written,
   especially if the program was written for another target architecture.

no way.  A correctly written program will have no problems with
alignment on any architecture.  Can you give an example of correct
code that will fail?  (I am assuming that well written programs are
correct :)

   Marc Kaufman (kaufman@Neon.stanford.edu)

--

Scott Draves		Space... The Final Frontier
wsd@cs.brown.edu
uunet!brunix!wsd

guy@auspex.auspex.com (Guy Harris) (07/15/90)

 >The only thing I don't like about this approach is that you have to live with
 >the poorest machine/os/compiler implementations you want to run your software
 >on.  

And you know of some other approach to running your software on the same
set of machine/os/compiler implementations that *doesn't* require this? 
(No, "choose a smaller set of implementations" doesn't count; that's the
same approach, just with a smaller set of machines you consider
"interesting".)

tve@sprite.berkeley.edu (Thorsten von Eicken) (07/15/90)

In article <WSD.90Jul14184453@unnamed.cs.brown.edu> wsd@cs.brown.edu (Wm. Scott `Spot' Draves) writes:
>In article <1990Jul13.071511.22250@Neon.Stanford.EDU> kaufman@Neon.Stanford.EDU (Marc T. Kaufman) writes:
>>   SPARC requires fullword alignment for 32-bit operands and DOUBLEword
>>   alignment (e.g. 8-bytes) for 64-bit operands, in memory.  
>Are you sure?  I think doubles can be loaded from 4 byte boundaries.
>Witness the following code, which runs fine on this SS1:
>[sample C code removed]

This really depends on how doubles get loaded/stored.  If the compiler
uses the load-double instruction, the data better be aligned on a
double (8 byte) boundary.  If two load-word instructions are used,
word alignment is fine.  I haven't figured out when compilers use
which instructions, but I have seen both.
---
Thorsten von Eicken (tve@sprite.berkeley.edu)

schow@bcarh185.bnr.ca (Stanley T.H. Chow) (07/17/90)

In article <WSD.90Jul14184453@unnamed.cs.brown.edu> wsd@cs.brown.edu (Wm. Scott `Spot' Draves) writes:
>no way.  A correctly written program will have no problems with
>alignment on any architecture.  Can you give an example of correct
>code that will fail?  (I am assuming that well written programs are
>correct :)

The problem is, of course, how do you define "correctly written 
program". If you define code that are not portable as poorly 
written, than your statement is meaningless.


Stanley Chow        BitNet:  schow@BNR.CA
BNR		    UUCP:    ..!uunet!bnrgate!bcarh185!schow
(613) 763-2831               ..!psuvax1!BNR.CA.bitnet!schow
Me? Represent other people? Don't make them laugh so hard.

peterd@opus.cs.mcgill.ca (Peter Deutsch) (07/17/90)

[ LONG - a candidate for skipping for the faint of heart... ]

I recently posted a fairly tedious and involved question
concerning the difficulties of programming on the SPARC as
compared to the 68k architectures. I have had a number of
users complain that SPARC seems inherently less forgiving
of the programmer, and questioned whether this might not
reflect problems with the architecture. I would like to
thank all those who took the time to answer, either through
email (about 15 to date!) or by posting.

I also would like to clarify somewhat my original posting,
plus comment on some of the many email I recieved.

The general consensus among the SPARC programmers who
wrote seems to be "Yes, the architecture is more
demanding, but this was a design trade-off which yielded a
faster machine. It is documented, thus it is a feature. If
your program fails, it is invariably due to programmers
violating the rules, and is thus poor programming practice
and the fault of the programmer." (my apologies for this
gross simplification, I know the issue is more complex
than that).

The general consensus also seems to be that the
architecture may be somewhat unforgiving, but yields good
results if the rules are followed, ie it is not inherently
"buggy". One writer (I can't recall if it was in email or
a posting) alleged that SPARC is an excellent development
platform, as if your program behaves on SPARC, it should
port to almost any less rigid architecture with a minimum
of effort.

Most who wrote or posted seemed to have missed one part of
my question, where I compared the documented alignment
restrictions of SPARC with the segment pointer problems of
early C compilers on 8088 machines. Here again, a
documented hardware feature has "risen into" the language,
in this case leading to language extensions - "near" and
"far" pointers) as a "workaround". In both cases, smarter
compilers can hide much of this, but probably not all if
you program in C.

It's been a while since I programmed PCs and I'm told the
newer compilers are smart enough to work around a lot of
this, but I was also told at the time we had to worry
about it that this was a "feature" of the architecture (in
the sense that segments were a feature) and they were to
be endured as part of the price of having such a cheap,
readily accessible machine.

A couple of people took my posting as a shot at Sun, or
SPARC, which it really wasn't. I do feel that such things
as structure alignment restrictions, union passing
problems, the need for "near" or "far" pointers, etc all
reflect hardware issues rising into the software layer
and, although probably inevitable in a language such as C,
are a strike against machine architectures where they
occur.

Of course, the benefits of such compromises may outweigh
the costs (as seems to be the case in SPARC) but they
certainly don't qualify for my rigid definition of a
feature (ie if I was offered the identical machine, but
without the "feature" would I be more inclined or less
inclined to buy the machine?). I suspect that most users,
given the choice, would prefer that they not have to worry
about how to access structures, preferring to leave that
to the compiler.

For what it's worth, the SPARC alignment "feature" _does_
qualify for my less rigid definition of a feature (ie if
it's documented it's a feature, if it's not, it's a bug. ;-)

So, without wanting to prolong a discussion by prompting a
flamewar, I would thank all those who wrote in favour of
the SPARC and say that, for my vote, the known, documented
restrictions on alignment are _NOT_ a feature, but a bug.
They are to be endured as the price to pay for a faster
machine, but I wouldn't argue (as some have done) that
they constitute a feature. Your mileage may vary...


While here, I would also like to answer a couple of points
raised in one posting, so here goes:

In article <3648@auspex.auspex.com>, guy@auspex.auspex.com (Guy Harris) writes:
.  .  .
> problem in structures" is; the SPARC C compiler puts structure members
> on the boundaries they require, so it's not as if a "poorly-written
> structure" can cause the program to blow up by violating an alignment
> restriction.
> 
> In the Sun C implementation, by default you cannot, say, have a buffer
> full of structures that are not necessarily aligned on the proper
> boundary for that structure (basically, the most restrictive alignment
> boundary for all the members of the structure), and just convert a
> pointer to an arbitrary byte in that buffer into a pointer to a
> structure and expect it to work.  However, you can specify the
> "-misalign" flag to the compiler, and it will generate code that lets
> you do this (basically, it tests the alignment of the pointer before
> using it; if it's properly aligned, it uses it normally, otherwise it
> calls a library routine to access the members of the structure.
> 
> However, there's nothing unique to SPARC about this; there's nothing
> even unique to RISC about this!  I can think of machines generally
> thought of as "CISC" that impose alignment restrictions similar to those
> of the SPARC, e.g. all but the most recent of the AT&T WE32K chips. 
> Even the PDP-11 and 68K prior to the 68020 required 2-byte alignment for
> quantities larger than one byte.

Here was a particularly clear (to me!) exposition of the
issue involved (thanks!). To summarize (hopefully without
changing the poster's meaning :-), I can't easily
manipulate down to the byte level on a SPARC architecture,
without telling the compiler I want to do this, and
without taking a performance hit. Acceptable? Maybe. A
feature? Hardly. A bug? I'd say "perhaps", one we've been
conditioned to accept as a feature because the designers
documented it. And the argument that other designers
pulled the same stunt is hardly a rousing defense.

> >More specifically, If I accepted the rumours that porting
> >to the SPARC was harder as an axiom could I argue that
> >this was a "bug" of the architecture, not a feature, in the
> >same way that difficulty addressing a 65k array on an 8088
> >machine is a residual bug due to limited segment size of
> >that chip?
> 
> You can argue anything you want.  Whether others will agree with you is
> another matter. 

Well, I've cast my vote on this one, that's enough for
me...

> I, for one, would not agree with you if you made that argument.  As
> shown by the "-misalign" flag to the compiler, you certainly *can*
> access misaligned quantities on a SPARC; it just takes more code, and
> extra work by the compiler.
> 
> While this does impose a performance penalty, so does accessing
> misaligned data on the architectures with which I'm familiar that let
> you do so directly.  The performance hit of doing so on SPARC (or other
> strict-alignment architectures) is probably greater than that on
> 68020-and-up (or other loose-alignment architectures); I don't have any
> numbers for that, though.
> 
> However, if references like that are sufficiently rare in most cases
> that whatever performance gain was obtained by leaving hardware support
> for that out of SPARC (either by devoting the circuitry to some other
> function, or by removing an extra delay from the data path, or by
> getting a basically-faster chip out the door sooner, or...) outweighs
> the performance loss of doing misaligned accesses in software in most
> cases, it may be the right thing to do to leave it out, at least for
> those cases.

I know I'm bucking an entire industry trend here, as RISC
seems to have been a huge commercial success, but this
argument strikes me as suspiciously like that of a car
salesman who argues that if I'm willing to buy a car
without brakes or seatbelts, I can get one that is that
much faster or cheaper. Sure, but I _am_ getting less car.
I for one am waiting with considerable interest to see if
the 68040 arrives too late to resist this trend to
minimalist computing... :-)

> There may well be problems for which the cost of leaving alignment
> restrictions in the instruction set outweighs whatever benefits you got
> from leaving it out, but that just argues against using strict-alignment
> machines for those particular problems.

Agreed, and I agree that a lot of workstations with these
restrictions are being sold. I just can't escape the
feeling that I'm being fed a drop of snake oil here ("Sure
it's tough on you, but the machine is that much faster so
it's a feature!") To be fair, that does not appear to be
this poster's attitude, but I do sense this attitude in the
general thread I started [WARNING - GROSS GENERALIZATION! SORRY! ]

.  .  .

> >Now, a few caveats, disclaimers, etc. Almost all the
> >programming problems I have heard about were in C, which
> >is an inherently low level language (although at least one
> >very large Pascal program, a compiler project, never was
> >ported successfully)
> 
> What machine was the target for the compiler?  If the target machine was
> the same as the machine on which the compiler was being run, "porting"
> is more than just recompiling - 68K machine code doesn't generally run
> on SPARC machines without some extra work being involved.

Actually, the program was a multi-thousand line Pascal
program (!!) written on a Sun 3 to implement a compiler
for Sisal, a specialized language for either dataflow or
parallel processing (I can't remember which and the prof
concerned is involved in research in both areas). A
successful compile would give us an executable that would
take Sisal programs and output something closer to a SPARC
executable. The program, to my knowledge, was never
successfully compiled but it may _all_ be due to a buggy
Pascal compiler (no, no version numbers available). I
can't only state with confidence that they had a lot of
problems with a program that worked (apparently correctly)
on Sun 3's.

Sorry this is so hazy, but I wasn't directly involved in
any of this, I tried to make that clear in the original
posting.  Much of my concerns arose from "hearsay"
comments, from a variety of users. I am really not
qualified to teach, I'm actually soliciting testimony from
those who are.

.  .  .
> The bulk of the problems I've seen in porting code to SPARC have been
> due to 1) the aforementioned "passing unions to routines" problem and 2)
> code that "knows" how C argument lists are laid out in memory, rather
> than using the "varargs" mechanism.  In neither case are those due to
> alignment problems.
> 
> Neither of these are due to anything peculiar to RISC (CISC compilers
> have been known to pass arguments in registers, rather than on the
> stack, as well, and use of a register-based calling sequence
> contributed, at least in part, to both problems), and neither would have
> been problems had the programmer not cheated. 

I left these in as they appear to be valid comments from
someone "who knows". I figured that if you made it this
far, you were entitled to a knowledable comment or two!

> >Given the (admittedly second-hand) reports of problems, is
> >this not a similar hardware problem raising up through the
> >language?
> 
> The alignment problem can be hidden by the language, at least with more
> recent compilers, as I'd noted.
> 
> >Note, I am _NOT_ disputing the worth of RISC
> >architectures, which have given us dramatic performance
> >gains. I'm just asking if we've paid a price in
> >"servicability"?
> 
> We probably have paid some such price; I suspect it was worth it.

Fair enough. But can I assume that on everyone's wish list
for Xmas would be a SPARC architecture but without the
alignment hit? Does it matter? Some people who wrote
talked of 20k lines of code that compiled without error,
then a few hundred lines that caused grief for weeks.
There _IS_ a price being paid for this...


			- peterd

noe@unx.sas.com (Larry Noe) (07/17/90)

In article <37570@ucbvax.BERKELEY.EDU> tve@sprite.berkeley.edu (Thorsten von Eicken) writes:
>In article <WSD.90Jul14184453@unnamed.cs.brown.edu> wsd@cs.brown.edu (Wm. Scott `Spot' Draves) writes:
>>In article <1990Jul13.071511.22250@Neon.Stanford.EDU> kaufman@Neon.Stanford.EDU (Marc T. Kaufman) writes:
>>>   SPARC requires fullword alignment for 32-bit operands and DOUBLEword
>>>   alignment (e.g. 8-bytes) for 64-bit operands, in memory.  
>>Are you sure?  I think doubles can be loaded from 4 byte boundaries.
>>Witness the following code, which runs fine on this SS1:
>>[sample C code removed]
>
>This really depends on how doubles get loaded/stored.  If the compiler
>uses the load-double instruction, the data better be aligned on a
>double (8 byte) boundary.  If two load-word instructions are used,
>word alignment is fine.  I haven't figured out when compilers use
>which instructions, but I have seen both.

The compiler seems to generate ldd/std instructions for doubles that it
knows to be aligned properly: automatics, statics and globals. Accessing
a double through a pointer though generates a 2 instruction sequence. There
is a new compiler switch in 4.1 though, '-dalign' that causes the compiler
to always use ldd/std for doubles.

-- 

Larry Noe (noe@unx.sas.com)          "And I saw a sign on Easy Street,
SAS Institute Inc.                      'Be Prepared to Stop'" -- Don Henley

barmar@think.com (Barry Margolin) (07/18/90)

In article <2163@opus.cs.mcgill.ca> peterd@opus.cs.mcgill.ca (Peter Deutsch) writes:
>Of course, the benefits of such compromises may outweigh
>the costs (as seems to be the case in SPARC) but they
>certainly don't qualify for my rigid definition of a
>feature (ie if I was offered the identical machine, but
>without the "feature" would I be more inclined or less
>inclined to buy the machine?). 

I generally refer to features that I don't like as "misfeatures".  A "bug"
is when the system doesn't conform to the vendor's description.  A
misfeature is when it does conform, but the vendor's description doesn't
describe a system that behaves as I'd prefer.  Sometimes a misfeature is
due to a design choice (e.g. making aligned memory accesses faster at the
expense of unaligned accesses); other times it's simply the lack of a
feature that a user would like (e.g. a COMPILE-ALGOL-IMMEDIATE
instruction).

>I know I'm bucking an entire industry trend here, as RISC
>seems to have been a huge commercial success, but this
>argument strikes me as suspiciously like that of a car
>salesman who argues that if I'm willing to buy a car
>without brakes or seatbelts, I can get one that is that
>much faster or cheaper. Sure, but I _am_ getting less car.

It frequently depends on the application whether this is a feature or
misfeature.  Most people wouldn't buy a bicycle without brakes or multiple
speeds.  But racing bicycles have neither.  It's not a matter of "less
bicycle", but merely that the bicycle is optimized for speed rather than
user-friendliness.

Or, returning to your car analogy, what if it were the emission control
system rather than the brakes or seatbelts that were being proposed for
removal.  An environmentalist would consider this a misfeature, while a
performance enthusiast would consider it a feature.  Tradeoffs frequently
have to be made, and whether the chosen path is best depends on your
perspective.
--
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

beemster@fwi.uva.nl (Marcel Beemster) (07/18/90)

peterd@opus.cs.mcgill.ca (Peter Deutsch) writes:
>[I want no alignment restrictions] (Sorry Peter, I had to shorten it a little.)

But do you also want to pay for it? As an example take the 68040.
Suppose it has to load the following misaligned Long Word:

	Address		Data
	$0		xLLL
	$4		Lxxx

To load this Long Word starting at address $1, it actually does 3 memory
cycles (assuming cache miss). The first one to load:
	$0		xLxx,	Reading a byte.
The second one loads:
	$0		xxLL,	Reading a word.
And the third one to load:
	$1		Lxxx,	Reading the last byte.

If you don't believe me, check Section 8.2.1, page 8.8, Fig 8.4 of the
user manual. I guess they couldn't afford the smarter way (out of
microcode or something like that). And no, the second read of $0 will
not be a cache hit.

Now the question is, if you as a programmer know how misaligned access
is going to cost precious memory cycles, are you going to avoid them?
I know I do, and find the (software development) cost not that high.

++marcel					beemster@fwi.uva.nl
"So, they destroyed their planet. Why?" "That was better for the economy."

robin@oakhill.UUCP (Robin Edenfield) (07/19/90)

The 68040 will only generate multilple bus cycles for misaligned
operand accesses that are non-cachable (either because the cache
is turned off or the page is non-cachable).  Writes to write through
pages that miss in the cache can also cause multiple cycles depending
on alignment because the 68040 does not write allocate for write
through pages.

Misaligned reads (or writes to copy back pages) that are cachable
will generate a line read to load the cache.  For reads, data will
be sent directly to the IU/FPU as it is received from the bus.
For a longword read at address 1, the IU will only be stalled until
the second long word of the burst is received.  The 68040 will
generate two line reads if a misaligned operand crosses a cache line
boundary.

The manual does not clearly explain how the 68040 handles these cases
(i.e. cachable, non-cachable, no allocate on write to write through).
I have sent a correction to the appropriate people.  BTW I know the
68040 data cache works this way because I designed it.

guy@auspex.auspex.com (Guy Harris) (07/19/90)

>Here was a particularly clear (to me!) exposition of the
>issue involved (thanks!). To summarize (hopefully without
>changing the poster's meaning :-), I can't easily
>manipulate down to the byte level on a SPARC architecture,
>without telling the compiler I want to do this, and
>without taking a performance hit.

No, you can't easily access *data not aligned on its natural boundary*
without telling the compiler you want to do that.  You can load a single
byte from memory from any (byte) boundary you want.

As for the performance hit, well, even though e.g. the 68020 lets you
load up unaligned 2-byte and 4-byte quantities "in hardware", you still
take a performance hit for it (as I noted in the posting to which you're
responding).

>I know I'm bucking an entire industry trend here, as RISC
>seems to have been a huge commercial success, but this
>argument strikes me as suspiciously like that of a car
>salesman who argues that if I'm willing to buy a car
>without brakes or seatbelts, I can get one that is that
>much faster or cheaper. Sure, but I _am_ getting less car.

Nope.  It's more like "If you're willing to buy a car without an
automatic transmission, you can get one that's faster or cheaper";
that's not an *exact* analogy - can anybody suggest a more exact one? 
How *do* you do shifts at compile-time rather than run-time? :-)

>Actually, the program was a multi-thousand line Pascal
>program (!!) written on a Sun 3 to implement a compiler
>for Sisal, a specialized language for either dataflow or
>parallel processing (I can't remember which and the prof
>concerned is involved in research in both areas). A
>successful compile would give us an executable that would
>take Sisal programs and output something closer to a SPARC
>executable. The program, to my knowledge, was never
>successfully compiled but it may _all_ be due to a buggy
>Pascal compiler (no, no version numbers available).

From "never successfully compiled" can I infer, then, that the program
was never successfully *executed*, either, but that the a version of the
code generator (whatever it was that generated "something closer to a
SPARC executable") had been written to generate SPARC code?

If so, it sounds as if either:

	1) the problem was, indeed, an problem with the Pascal compiler;

or

	2) they never got the code generator to compile.

In both cases, the most likely problem would seem to be generating code
for SPARC - either in the Pascal compiler (Sun's compilers, at least,
have a mostly common front end for all architectures, so it's the back
end where I'd expect big differences betwen Sun-3 and SPARC).  SPARC is
different enough from the 68K (as are a number of other architecturs,
some of which even allow unaligned accesses) that there's no reason to
assume *a priori* that the big problem there had anything to do with
alignment.

>Fair enough. But can I assume that on everyone's wish list
>for Xmas would be a SPARC architecture but without the
>alignment hit?

If I could get it with the same performance (i.e., no performance loss
for properly-aligned references), without sacrificing any capabilities,
and at a minimal extra cost, I'd take it; however, the lack of hardware
support for unaligned references has, as I noted, not really gotten in
my way, so I can think of lots of things I'd put before that on my Xmas
list.

jgriffit@nyx.UUCP (Jonathan C. Griffitts) (07/19/90)

In article <WSD.90Jul14184453@unnamed.cs.brown.edu> wsd@cs.brown.edu (Wm. Scott `Spot' Draves) writes:
>
>>   Data misalignment problems are independent of how well a program is written,
>>   especially if the program was written for another target architecture.
>
>no way.  A correctly written program will have no problems with
>alignment on any architecture.  Can you give an example of correct
>code that will fail?  (I am assuming that well written programs are
>correct :)
>

How about a case I have personal experience with:  a language interpreter 
that executes precompiled binary code sequences.  The program originally ran
on PCs that make no requirement for int and long alignments, so the code
sequences were packed together in the obvious way (making use of sizeof()
operators to determine how far to advance the execution pointer).  When 
this program was ported to a 68000, the alignment requirement caused a lot 
of changes.  

It's not a hard problem to solve in any particular case, but we had to make
sure that every case was found.  Not trivial.  This was written in C, by
the way.

Something to keep in mind when writing code that might need to be portable!

				--Jonathan Griffitts
				AnyWare Engineering
				(303) 442-0556

jbuck@galileo.berkeley.edu (Joe Buck) (07/20/90)

In article <3241@bnr-rsc.UUCP>, schow@bcarh185.bnr.ca (Stanley T.H.
Chow) writes:
>In article <WSD.90Jul14184453@unnamed.cs.brown.edu> wsd@cs.brown.edu
(Wm. Scott `Spot' Draves) writes:
>>no way.  A correctly written program will have no problems with
>>alignment on any architecture.  Can you give an example of correct
>>code that will fail?  (I am assuming that well written programs are
>>correct :)

> The problem is, of course, how do you define "correctly written 
> program". If you define code that are not portable as poorly 
> written, than your statement is meaningless.

If the program, when run through lint, does not print "possible pointer
alignment problem" except for pointer values returned by malloc, and does
not generate any other lint messages, it will not crash when compiled on
another architecture because of an alignment problem.

C programs that are UNNECESSARILY non-portable are poorly written.  Programs
that blithely assume int, long, and pointers are the same thing out of
programmer laziness or that throw casts around with abandon are poorly
written.

Sometimes machine-specific code is required.  Such code should be isolated
and commented well.  Even if, when you write the program, you think it
doesn't need to be portable, chances are at some point down the road
you, or someone else, will need to port it.  Either make this job easy,
or leave your name off the code, because some future programmer will
curse your name otherwise.

--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

dwm@wo.msc.umn.edu (Don Mears) (07/20/90)

In <37655@ucbvax.BERKELEY.EDU>, jbuck@galileo.berkeley.edu (Joe Buck) writes:
>If the program, when run through lint, does not print "possible pointer
>alignment problem" except for pointer values returned by malloc, and does
>not generate any other lint messages, it will not crash when compiled on
>another architecture because of an alignment problem.

For what it's worth here are 2 programs that pass lint and run on a 68000 
based Sun-3 and abort due to alignment errors on a SPARC Sun-4:

main() { int i[2], *j = i; 
	(void) printf("%d\n", *(int *) ((int)j + 2));   }

union u { int i; int *ip} un; int ai[10];
main() { un.ip = ai; un.i++; (void)printf("%d\n", *un.ip); }

Lint never guarantees correctness.   Even still, I prefer the CPU that runs
fast over the one that hides stupidisms from me.   

jbuck@galileo.berkeley.edu (Joe Buck) (07/20/90)

In article <2174@uc.msc.umn.edu>, dwm@wo.msc.umn.edu (Don Mears) writes:
[ I wrote ]
> >If the program, when run through lint, does not print "possible pointer
> >alignment problem" except for pointer values returned by malloc, and does
> >not generate any other lint messages, it will not crash when compiled on
> >another architecture because of an alignment problem.
> 
> For what it's worth here are 2 programs that pass lint and run on a 68000 
> based Sun-3 and abort due to alignment errors on a SPARC Sun-4:

Don then gives two programs -- the first one casts back and forth between
a pointer and an int to force incorrect alignment of the pointer; the second
screws around with unions, writing the union as an int and then reading it
as a pointer.  His second program would also crash a PDP-11.

Good point, Don.  Writing a union as one type and reading it as another is
a non-portable operation, and lint won't complain.  This type of thing should
never be done without surrounding comments explaining the assumptions (for
example, is the machine big-endian or little-endian?  What required alignment
is assumed?  What is assumed about the relative sizes of data types?  Etc).

Casting between ints and
pointers is also dangerous, as I said elsewhere in my article.  Lint isn't
perfect, but it's a valuable tool, and I question the professionality of
Unix programmers who don't use it.


--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

jack@cwi.nl (Jack Jansen) (07/23/90)

It seems that we're slowly drifting to another issue: there is no way to
tell the C compiler that is should not use any fillers in structures,
even though this results in inefficient code. If you have
structure layout that is dictated, like a network packet, for instance,
I would like to be able to tell the compiler 'I know this structure
is unaligned, but please keep it so and generate inefficient code'.

I had to port some tcp/ip stuff to a strict alignment machine, and there
is a 32-bit field on a non-32 bit boundary somewhere in the IP header
(I think, the details might be wrong, it's long ago).
This meant I had to pack and unpack the field by hand. yuck.
--
--
Een volk dat voor tirannen zwicht	| Oral:     Jack Jansen
zal meer dan lijf en goed verliezen	| Internet: jack@cwi.nl
dan dooft het licht			| Uucp:     hp4nl!cwi.nl!jack

jkenton@pinocchio.encore.com (Jeff Kenton) (07/24/90)

From article <1878@charon.cwi.nl>, by jack@cwi.nl (Jack Jansen):
> 
> I had to port some tcp/ip stuff to a strict alignment machine, and there
> is a 32-bit field on a non-32 bit boundary somewhere in the IP header
>

The "correct answer" to this seems to be something of a religious question.
It depends on whether you think network packets are defined as structures
or as byte streams.  If you call them structures you have both alignment
problems and big-endian/little-endian problems.  If you call them byte
streams you have neither problem, but the code looks uglier.


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      jeff kenton  ---	temporarily at jkenton@pinocchio.encore.com	 
		   ---  always at (617) 894-4508  ---
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

jgk@osc.COM (Joe Keane) (07/25/90)

In article <12281@encore.Encore.COM> jkenton@pinocchio.encore.com (Jeff
Kenton) writes:
>The "correct answer" to this seems to be something of a religious question.
>It depends on whether you think network packets are defined as structures
>or as byte streams.  If you call them structures you have both alignment
>problems and big-endian/little-endian problems.  If you call them byte
>streams you have neither problem, but the code looks uglier.

In my opinion, almost all of the whining about alignment comes from people who
write code with `write(fd, some_struct_pointer, sizeof (struct foo))' and
expect it to be portable.  Never mind alignment, think about machines with
different type sizes, different byte order, or different floating-point
formats.  You can do it, but don't cry to me when it stops working.

Network packets are defined as a sequence of bytes.  The second arguments to
read and write are char pointers.  This suggests that you should only read and
write arrays of bytes.  You can convert between these and whatever internal
form you want.

It may seem like a pain to do this, but it pays off.  I wrote programs which
read and write complicated data formats, with weird floating-point numbers and
all.  Then i went to a machine with a different byte order and floating-point
format, and they ran fine, without changing a single line of code.

meissner@osf.org (Michael Meissner) (07/25/90)

In article <9895@pt.cs.cmu.edu> lindsay@MATHOM.GANDALF.CS.CMU.EDU
(Donald Lindsay) writes:

| In article <1139@carol.fwi.uva.nl> beemster@fwi.uva.nl 
| 	(Marcel Beemster) writes:
| >In general my feelings towards
| >software development are: "If it runs on s SPARC, it runs everywhere",
| 
| It's good for portability to develop code on the _least_ forgiving
| machine that you can find.

Back when I worked at Data General, some of us (and a lot of
customers) thought the DG MV/Eclipse computers were the least
forgiving.  Among it's features:

   1)	Four different representations for pointers (2 different bit,
	1 byte, and 1 word/double word pointers).  The bit pointers
	were rarely used in high level languages.  One format used two
	double words, one for the word, and the other as a positive
	offset from that word.  The other format had the word address
	shifted left 4 bits, and the bit offset inserted.  The word
	pointer format used the top bit for indirection if the
	instruction itself used indirection, and the next 3 bits were
	the segment/ring bits, with 0 being the OS, and 7 being user
	programs.  The byte pointer format shifted everything left one
	bit, dropping the indirection bit.  This meant that for user
	programs the use of a byte pointer where a word pointer was
	expected or vica versa would cause a segmentation violation.

	Because multiple indirections where not used in the high level
	languages, it meant for user programs, you could check at
	runtime whether a pointer was of the appropriate sex, by
	looking at the top bit.  This lead to several C compiler
	options to insert such checks in user code, and to enable the
	checks in the library.  Typically though if a program had been
	linted, it would be passing type correct pointers (except to
	qsort though) and all would be fine.  It was really amazing to
	find how many sloppy programs there out there.

	Because 'all struct pointers smell the same' rules, to allow
	pointing to an unknown structure, all structure and unions
	were required to be aligned on a 16-bit word boundary.

   2)	Dereferencing a null pointer always caused a segmentation
	violation (inward address trap in MV-speak), since ring 0 was
	the operating system, and protected from outer rings except
	for calls to a protected gate list.  There was no way with
	linker switches to get it to change behavior.

   3)	Characters were unsigned by default, since there was no sign
	extending load byte sequence.  I did put in a compiler option
	for VAX weanies who couldn't read the warning in K&R that
	plain chars might be unsigned.

   4)	Shifting signed ints right was logical rather than arithmetic
	(again K&R allows this) because the arithmetic shift was
	slower than logical (which in itself was no speed demon).

   5)	The MV hardware stack grew upwards from low memory, rather
	than downwards as it is in nearly every other machine in
	existance.  It was also surprizing the number of people who
	still do not use varargs/stdargs (I just got a request in
	today to add a GCC option to add a warning for this case,
	since we are uncovering it in porting commands to OSF/1).

	Another side effect of the stack growing the 'wrong' way, is
	that it causes havoc for sbrk, since it wants to grow in the
	same direction.

   6)	The compiler and linker reordered variables based on the size
	and alignment of the variables.  Thus programs that expect
	successive extern (or auto) declarations to be contigous were
	surprized.

   7)	The floating point format used is the IBM 360 format rather
	than the newer IEEE format.  This meant you got more exponent
	range for floats, and less for doubles as compared to IEEE.
	Also because the base is in hex, and not binary, it leads to a
	loss of average precision of 2-3 bits.  The one kludge it did
	allow was the single precision format was exactly the same as
	the double precision format, except for the extra bits.

   8)	The MV is big endian which causes the usual problems when
	importing little endian VAX code (ie, taking the address of an
	int, and treating the pointer a pointer to a character).

We did have some companies who ported their software to our machines
thank us for finding the bugs in their code.  Of course we had the
others who said that their code ran on two different flavors of VAX,
and therefore was portable.
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA

Do apple growers tell their kids money doesn't grow on bushes?