[comp.sys.mips] Redefinition of left shift operator

edgar@portia.Stanford.EDU (Edgar Holmann) (08/23/89)

Has the left shift operator been redefined in the MIPS systems from the typical
shift to a modulo type shift?  By this I mean:
   i << j
redefined to
   i << (j % 32)
This is evident when you shift by a quantity larger than or equal to the int
size (32).  When j is a constant, the compiler issues a warning message (when
using the optimizer level 2 or 3).  Now, I see that nobody should be shifting
by a constant larger than 32 but what about shifting by another variable when
creating a mask?  Thus, a simple statement of the form
   (1L << j) - 1
or
   ~(~0 << j)
now has to have a conditional to handle the case when j is 32.  I have tried
this on an R3000 running Ultrix 3.1 with cc1.31.  The same result is obtained
in an R2000.

Is this considered a "feature" of the mips compiler or is it something that
will get changed in a new release?

edgar

rudy@mips.COM (Rudy Wang) (08/23/89)

In article <4724@portia.Stanford.EDU> edgar@Neon.Stanford.EDU (Edgar Holmann) writes:
>
>Has the left shift operator been redefined in the MIPS systems from the typical
>shift to a modulo type shift?  By this I mean:
>   i << j
>redefined to
>   i << (j % 32)
>This is evident when you shift by a quantity larger than or equal to the int
>size (32).  When j is a constant, the compiler issues a warning message (when
>using the optimizer level 2 or 3).  Now, I see that nobody should be shifting
>by a constant larger than 32 but what about shifting by another variable when
>creating a mask?  Thus, a simple statement of the form
>   (1L << j) - 1
>or
>   ~(~0 << j)
>now has to have a conditional to handle the case when j is 32.  I have tried
>this on an R3000 running Ultrix 3.1 with cc1.31.  The same result is obtained
>in an R2000.
>
>Is this considered a "feature" of the mips compiler or is it something that
>will get changed in a new release?
>
>edgar

Please read the definition of the "shift operators" on page 189 of the 1st
edition "The C programming language" (page 206 of the 2nd edition, says the
same thing).

When the shift amount is greater than or equal to the length of the object
in bits, the result is undefined!

In Mips' case, it simply chooses to shift the amount modula 32 (or just
to use the lower 5 bits).  Please see page A-63 of the Mips R2000 RISC
architecture, by Kane.

-- 
UUCP:	{ames,decwrl,prls,pyramid}!mips!rudy	(or rudy@mips.com)
DDD:	408-991-0247 Rudy Wang			(or 408-720-1700, Ext. 247)
USPS:	MIPS Computer Systems, 930 Arques, Sunnyvale, CA 94086-3650
Quote:	"Time sure is fun when you're having flies!" - Kermit the frog

earl@wright.mips.com (Earl Killian) (08/23/89)

In article <4724@portia.Stanford.EDU>, edgar@portia (Edgar Holmann) writes:

>Has the left shift operator been redefined in the MIPS systems from
>the typical shift to a modulo type shift?  By this I mean:
>   i << j
>redefined to
>   i << (j % 32)

The C language does not define shifts < 0 or >= the size of the type,
so any program where the above statements differ is illegal.  This
allows compilers to generate a raw shift instruction, which is in line
with C's efficiency goals.  All instruction set architectures (ISAs)
that I know take the shift count modulo some small power of two (e.g.
32-256).  The MIPS ISA in particular takes the shift count modulo 32,
which gives different results on illegal programs than say a 68000,
which takes the shift count modulo 64.

So the bottom line is that you need to use conditionals when your
shift count is of larger range.  If C shifts were defined for shifts
>= size of the type, then all variable shifts would require the
compiler to generate the conditional, on all architectures, and you
probably wouldn't like the performance of that.
--
UUCP: {ames,decwrl,prls,pyramid}!mips!earl
USPS: MIPS Computer Systems, 930 Arques Ave, Sunnyvale CA, 94086

guy@auspex.auspex.com (Guy Harris) (08/24/89)

>Has the left shift operator been redefined in the MIPS systems from the typical
>shift to a modulo type shift?  By this I mean:
>   i << j
>redefined to
>   i << (j % 32)

The C language specs I've seen - both K&R I and ANSI C - indicate that
the behavior of shift operators is undefined if the shift count is
larger than the size of the object being shifted, in bits.

Therefore, there is no redefinition involved here; the definition of the
left shift operator on the MIPS systems is exactly the same as it is on
other systems.  Its behavior in a case where said behavior is left
undefined by the standard is different from its behavior in *some*
systems, but the definition allows that.  Other systems behave the way
the MIPS systems do.

The reason for this is that the specifiers wanted to allow shift
operators with a non-constant right-hand operand to be compiled into the
machine's shift instructions, and different machines do different things
with that count.  Some take it modulo the word size, some don't.

>Thus, a simple statement of the form
>   (1L << j) - 1
>or
>   ~(~0 << j)
>now has to have a conditional to handle the case when j is 32.

Said statement would, on systems using R[23]000 (and SPARC and 80386 and
some other) chips, have to have the conditional inserted into the
compiled code anyway.  The question is which end users are better off
having the language specify the behavior in the "shift count larger than
the size of the shifted object" case, and having the compiler insert the
conditional in the compiled code, or having the language not specify the
behavior and obliging the user to insert the condition *in those cases
where it matters* - which are not all cases.  (Consider, for example,
code used to maintain a "bit array"; the shift count is already going to
be less than the size of the object, in bits.)

The ANSI C standard isn't going to change at this late date, so if you
don't like the fact that it permits the type of behavior you see on the
MIPS, you'll have to lobby the vendors of all systems to which you might
want to port your code to have their compilers ensure the behavior you
want.