Path: utzoo!mnetor!uunet!husc6!mit-eddie!uw-beaver!cornell!rochester!ur-tut!sunybcs!boulder!hao!scdpyr!cruff From: cruff@scdpyr.UUCP (Craig Ruff) Newsgroups: comp.arch Subject: Re: Bad RISC (Warning: very long reply) Message-ID: <287@scdpyr.UUCP> Date: 2 Mar 88 16:48:54 GMT References: <216@wsccs.UUCP> Reply-To: cruff@scdpyr.UUCP (Craig Ruff) Organization: Natl Ctr Atmospheric Research, Boulder, CO Lines: 130 Keywords: SUN RISC In article <216@wsccs.UUCP> terry@wsccs.UUCP (terry) writes: >>We have been able to port to all machines we attempted, except ... SUN's new >>... RISC machine ... > 1) The processor thinks in words (bus-words) always; this means if > you want to do something, even if it is manipulation of character > data, it is stored in words. The problem comes in that the C > compiler on the machine did not make that distinction, and broke > on parameter passes to functions, where a single character element > is sign-extended to int to be passed. This means that the top bits > were not cleared. As this was the portable C compiler, I blame it > on the architecture not taking normal (read existing) operations > into account. If the chip supported byte references, this would not > have happened. Wrong. According to "The SPARC Architecture Manual", the SPARC includes load operations for both signed and unsigned bytes and words. Store operations are present for both bytes and words. As far as C goes, both chars and shorts are extended to ints before being used in arithmetic or logical operations and when being passed to functions as parameters. The choice about signed/unsigned chars during extension is usually made by the compiler writers, with large hints from the underlying machine. If you are relying on operations being done at byte or word sizes from C source code, you are relying on a compiler dependent feature. As far as data alignment goes, the "Porting Software to SPARC Systems" manual states "all quantities must be aligned on boundaries corresponding to their sizes". This means a char followed by an int will have 3 bytes padding between. This is true for many machines. > 2) Implicit type casting, which tries to take advantage of the register > architecture of the machine it runs on does not always work as is > expected: > > float val = 314.15926535; > float j; > > j = val % 75.0123; > > or something similar using an integer-only operator does not > correctly truncate values past the decimal. All compilers I know of complain about non-integral operands for the % operator. K&R does not define a floating mod operator. > 3) Non-aligned var-args code not using the varargs definition, but > rather relying on the method a standard architecture machine has > of plunking arguments into a function (no, I do *NOT* refer herein > to the argument push order!) stack to be read by a function leaves > it indeterminate as to whether the function arguments are pointers > or what. For instance > > int foo; > > foo = 'x'; /* possibly buggy implicit cast*/ > printf( "the character %c has an ascii value of "); > printf( "%d decimal and %x hex", foo, foo); > > apparently works, but if you write your own function output and call > it in place of printf, using the argc/argv style of parameter > passing, the processor apparently confuses the stack. (Yes, I > _know_ function prototypes would probably alleviate this, but > until some kind soul rewrites all the C code out there, I will > almost always be referring to K&R C). I don't see what your example has to do with varargs. When using varargs, you must pay close attention to the manual. When you pass values that are widened (char -> short -> int, float -> double), you must use the widest type in the va_arg call, then assign that to a variable of the appropriate size. You must also pay attention to signed/unsigned distinctions. The value passed to a function (i.e. pointer verses value) is alway defined for C. Non-pointer values (including whole structures and unions) are passed by value. Pointers (variables and explicit addresses (&var)) are passed by value, which happens to be an address. > 4) Passing back pointers from functions whose type is resolved by the > linker is dangerous (I don't write code like this anyway, but if > you want an example try 'gets()'), and passing integer values back > to character assignment statements (getc()) is also unhappy. Agree. This is guaranteed to cause problems. According to the manual page for getc, the warning section talks about this. > I also realize that even if you accept my examples at face value, they >appear to be flaws in the portable C compiler, some of which can be taken out >simply by adding an baroque code generator capable of producing the workarounds >for you... macro's to replace the instructions which aren't there because it is >a RISC machine. Such macro's sort of defeat the purpose of having a RISC >machine... what's the use of having a 'more compact' instruction set if you >just have to generate more of them? None of your examples point to flaws in the portable C compiler. I gather the macros you are refering to are the assembler macros that map common operations into actual machine instructions. Since this mapping is mostly one onto one, these are equivalent, but just easier for humans (including compiler writers) to understand. RISC does not imply more compact instructions, just regular instructions. > I can't really be a bigot about having to write extra code to make >a machine do something it apparently wasn't designed to do... after all, I >run MS-DOS on my Amiga and dBase III .cmd files on a VAX ...but I feel that >either their developement tools need a rewrite (how are you going to fix the >assembler? :-) ) or the manner in which RISC design at Sun is approached >needs reconsideration. You appear to be way off base here. >My definition of portable: Everthing I write, everthing my friends write, and >everthing I run that was written by somebody else, should run with minor >changes. These changes should only be necessary as symptoms of differences >in O/S implementation philosophy, and not as differences in basic structure. >The programmer should know about the hardware he is running on in order to >make appropriate design decisions as far as speed of operation, but he should >not be _required_ to know (brow-beaten into it). A user should never know, >or even suspect. If a company says they run UNIX V.3, I should be able to >take my UNIX V.3 software off my 3B2 (or Arete 1100, or NCR Tower, etc) and >compile it with the same flags and have it run exactly the same. I agree, but this is the real world. :-) >Other definition of portability: If it ran on UNIX and you ported it to VMS >so that all you had to do was #define UNIX or VMS, it should be relatively >trivial to port it to other machines, even those running Atari DOS wedge on a >6502 :-). Not always. Unix and VMS are more alike than different compared to many micros and mainframe operating systems. -- Craig Ruff NCAR INTERNET: cruff@scdpyr.UCAR.EDU (303) 497-1211 P.O. Box 3000 CSNET: cruff@ncar.CSNET Boulder, CO 80307 UUCP: cruff@scdpyr.UUCP