[M3commit] CVS Update: cm3

Antony Hosking hosking at elego.de
Thu Feb 18 03:33:15 CET 2010


CVSROOT:	/usr/cvs
Changes by:	hosking at birch.	10/02/18 03:33:15

Modified files:
	cm3/m3-sys/m3middle/src/: M3CG_BinRd.m3 M3CG_Rd.m3 TInt.i3 
	                          TInt.m3 TWord.i3 TWord.m3 Target.i3 
	                          Target.m3 
	cm3/m3-sys/m3back/src/: Codex86.m3 M3x86.m3 M3x86Rep.i3 
	                        Stackx86.m3 Wrx86.m3 
	cm3/m3-sys/m3front/src/builtinAtomic/: AtomicModule.mg 
	cm3/m3-sys/m3front/src/builtinInfo/: InfoThisLine.m3 
	cm3/m3-sys/m3front/src/builtinOps/: BitSize.m3 Dec.m3 Number.m3 
	cm3/m3-sys/m3front/src/builtinWord/: And.mg Divide.mg Extract.mg 
	                                     GE.mg GT.mg Insert.mg LE.mg 
	                                     LT.mg Minus.mg Mod.mg 
	                                     Module.mg Not.mg Or.mg 
	                                     Plus.mg Rotate.mg Shift.mg 
	                                     Times.mg Xor.mg 
	cm3/m3-sys/m3front/src/exprs/: AddExpr.m3 AddressExpr.m3 
	                               ArrayExpr.m3 Expr.m3 
	                               IntegerExpr.m3 ModExpr.m3 
	                               ReelExpr.m3 SetExpr.m3 
	                               SubtractExpr.m3 
	cm3/m3-sys/m3front/src/misc/: CG.m3 Scanner.m3 TipeDesc.m3 
	cm3/m3-sys/m3front/src/stmts/: CaseStmt.m3 
	cm3/m3-sys/m3front/src/types/: ArrayType.m3 EnumType.m3 
	                               OpenArrayType.m3 SubrangeType.m3 
	                               Type.m3 
	cm3/m3-sys/m3tools/src/: M3Builtin.m3 M3Const.m3 M3Lexer.m3 
	                         M3Type.m3 

Log message:
	Drastic simplification of TInt/TWord.  These no longer simulate INTEGER
	arithmetic directly, but simply provide support for arithmetic up to the
	precision of any target.  As a result, users of these interfaces must
	explicitly ensure that their results do not exceed the bounds of their target
	integer precision.  One side-effect has been fixes to some remaining bugs in
	range-checking for CARDINAL/LONGCARD.
	
	Index: m3middle/src/M3CG_BinRd.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_BinRd.m3,v
	retrieving revision 1.9
	diff -c -r1.9 M3CG_BinRd.m3
	*** m3middle/src/M3CG_BinRd.m3	11 Jan 2010 22:04:48 -0000	1.9
	--- m3middle/src/M3CG_BinRd.m3	18 Feb 2010 02:30:47 -0000
	***************
	*** 407,426 ****
	| M3CG_Binary.Int8  =>  n_bytes := 8;  sign := +1;
	| M3CG_Binary.NInt8 =>  n_bytes := 8;  sign := -1;
	ELSE
	!       ok := TInt.FromInt (i, NUMBER (val.x), val);  <*ASSERT ok*>
	RETURN val;
	END;
	
	val := TInt.Zero;  shift := 0;
	FOR i := 0 TO n_bytes-1 DO
	!       ok := TInt.FromInt (GetByte (s), NUMBER (byte.x), byte);  <*ASSERT ok*>
	TWord.Shift (byte, shift, byte);
	TWord.Or (val, byte, val);
	INC (shift, 8);
	END;
	!     IF (sign < 0) THEN
	!       TWord.Subtract (TInt.Zero, val, val);
	!     END;
	
	RETURN val;
	END Scan_Tint;
	--- 407,424 ----
	| M3CG_Binary.Int8  =>  n_bytes := 8;  sign := +1;
	| M3CG_Binary.NInt8 =>  n_bytes := 8;  sign := -1;
	ELSE
	!       ok := TInt.FromInt (i, val);  <*ASSERT ok*>
	RETURN val;
	END;
	
	val := TInt.Zero;  shift := 0;
	FOR i := 0 TO n_bytes-1 DO
	!       ok := TInt.FromInt (GetByte (s), byte);  <*ASSERT ok*>
	TWord.Shift (byte, shift, byte);
	TWord.Or (val, byte, val);
	INC (shift, 8);
	END;
	!     IF (sign < 0) THEN TWord.Subtract (TInt.Zero, val, val); END;
	
	RETURN val;
	END Scan_Tint;
	Index: m3middle/src/M3CG_Rd.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/M3CG_Rd.m3,v
	retrieving revision 1.7
	diff -c -r1.7 M3CG_Rd.m3
	*** m3middle/src/M3CG_Rd.m3	30 Jan 2010 21:28:34 -0000	1.7
	--- m3middle/src/M3CG_Rd.m3	18 Feb 2010 02:30:48 -0000
	***************
	*** 364,377 ****
	result, tmp: Target.Int;   value, used: INTEGER;
	BEGIN
	value := Convert.ToInt (SUBARRAY (buf, 0, len), used);
	!     IF (used = len) AND TInt.FromInt (value, NUMBER (result.x), result) THEN
	RETURN result;
	ELSIF (buf[0] # '-') THEN
	!       IF TInt.New (SUBARRAY (buf, 0, len), NUMBER (result.x), result) THEN
	!         RETURN result;
	!       END;
	ELSE (* Target doesn't handle negative values *)
	!       IF TInt.New (SUBARRAY (buf, 1, len-1), NUMBER (tmp.x), tmp)
	AND TInt.Subtract (TInt.Zero, tmp, result) THEN
	RETURN result;
	END;
	--- 364,375 ----
	result, tmp: Target.Int;   value, used: INTEGER;
	BEGIN
	value := Convert.ToInt (SUBARRAY (buf, 0, len), used);
	!     IF (used = len) AND TInt.FromInt (value, result) THEN
	RETURN result;
	ELSIF (buf[0] # '-') THEN
	!       IF TInt.New (SUBARRAY (buf, 0, len), result) THEN RETURN result END;
	ELSE (* Target doesn't handle negative values *)
	!       IF TInt.New (SUBARRAY (buf, 1, len-1), tmp)
	AND TInt.Subtract (TInt.Zero, tmp, result) THEN
	RETURN result;
	END;
	Index: m3middle/src/TInt.i3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/TInt.i3,v
	retrieving revision 1.25
	diff -c -r1.25 TInt.i3
	*** m3middle/src/TInt.i3	8 Feb 2010 16:42:41 -0000	1.25
	--- m3middle/src/TInt.i3	18 Feb 2010 02:30:49 -0000
	***************
	*** 10,74 ****
	
	(*  Modula-3 target description
	
	!     This interface provides simulations of the target machine's
	!     signed integer operations.
	
	Unless otherwise specified, the arithmetic operations defined
	!     below return TRUE if they succeed in producing a new target value,
	otherwise they return FALSE.
	*)
	
	! FROM Target IMPORT Int, IBytes;
	
	CONST
	!   Zero      = Int{NUMBER (IBytes), IBytes{ 0,0,..}};
	!   One       = Int{NUMBER (IBytes), IBytes{ 1,0,..}};
	!   Two       = Int{NUMBER (IBytes), IBytes{ 2,0,..}};
	!   Three     = Int{NUMBER (IBytes), IBytes{ 3,0,..}};
	!   Four      = Int{NUMBER (IBytes), IBytes{ 4,0,..}};
	!   Eight     = Int{NUMBER (IBytes), IBytes{ 8,0,..}};
	!   Ten       = Int{NUMBER (IBytes), IBytes{10,0,..}};
	!   ThirtyOne = Int{NUMBER (IBytes), IBytes{31,0,..}};
	!   ThirtyTwo = Int{NUMBER (IBytes), IBytes{32,0,..}};
	!   SixtyThree= Int{NUMBER (IBytes), IBytes{63,0,..}};
	!   SixtyFour = Int{NUMBER (IBytes), IBytes{64,0,..}};
	!   F3FF      = Int{NUMBER (IBytes), IBytes{16_FF,16_F3,0,..}};
	!   x0400     = Int{NUMBER (IBytes), IBytes{0,4,0,..}};
	!   x0800     = Int{NUMBER (IBytes), IBytes{0,8,0,..}};
	!   x0F00     = Int{NUMBER (IBytes), IBytes{0,16_F,0,..}};
	!
	!   (* 'M' for Minus (negative) *)
	!
	!   MOne  = Int{NUMBER (IBytes), IBytes{16_FF,..}};
	!   MThirtyOne = Int{NUMBER (IBytes), IBytes{16_E1,16_FF,..}};
	!   MSixtyThree= Int{NUMBER (IBytes), IBytes{16_C1,16_FF,..}};
	
	! PROCEDURE FromInt (x: INTEGER;  n: CARDINAL;  VAR i: Int): BOOLEAN;
	(* converts a host integer 'x' to a target integer 'i' *)
	
	- PROCEDURE IntI (READONLY x: Int;  n: CARDINAL;  VAR i: Int): BOOLEAN;
	- (* converts a target integer 'x' to a target integer 'i' *)
	-
	PROCEDURE ToInt (READONLY i: Int;  VAR x: INTEGER): BOOLEAN;
	(* converts a target integer 'i' to a host integer 'x' *)
	
	! PROCEDURE New (READONLY chars: ARRAY OF CHAR;  n: CARDINAL;
	!                VAR i: Int): BOOLEAN;
	(* converts the string of decimal characters in 'chars' to an integer
	value in 'i' *)
	
	- PROCEDURE Abs (READONLY a: Int;  VAR r: Int): BOOLEAN;
	- (* returns a if a >= 0, -a if a < 0, or overflow *)
	-
	PROCEDURE Add (READONLY a, b: Int;  VAR i: Int): BOOLEAN;
	(* returns 'a + b' unless there's an overflow *)
	
	PROCEDURE Subtract (READONLY a, b: Int;  VAR i: Int): BOOLEAN;
	(* returns 'a - b' unless there's an overflow *)
	
	- PROCEDURE Negate (READONLY a: Int;  VAR r: Int): BOOLEAN;
	- (* returns '-a' unless there's an overflow *)
	-
	PROCEDURE Multiply (READONLY a, b: Int;  VAR i: Int): BOOLEAN;
	(* returns 'a * b' unless there's an overflow *)
	
	--- 10,48 ----
	
	(*  Modula-3 target description
	
	!     This interface provides simulations of signed integer operations,
	!     at the maximum precision supported by any target.
	
	Unless otherwise specified, the arithmetic operations defined
	!     below return TRUE if they succeed in producing a new value,
	otherwise they return FALSE.
	*)
	
	! FROM Target IMPORT Int;
	!
	! CONST Size = BITSIZE(Int);
	
	CONST
	!   Zero   = Int{ 0, 0,..};
	!   One    = Int{ 1, 0,..};
	!   MOne   = Int{16_FF,..};
	
	! PROCEDURE FromInt (x: INTEGER;  VAR i: Int): BOOLEAN;
	(* converts a host integer 'x' to a target integer 'i' *)
	
	PROCEDURE ToInt (READONLY i: Int;  VAR x: INTEGER): BOOLEAN;
	(* converts a target integer 'i' to a host integer 'x' *)
	
	! PROCEDURE New (READONLY chars: ARRAY OF CHAR;  VAR i: Int): BOOLEAN;
	(* converts the string of decimal characters in 'chars' to an integer
	value in 'i' *)
	
	PROCEDURE Add (READONLY a, b: Int;  VAR i: Int): BOOLEAN;
	(* returns 'a + b' unless there's an overflow *)
	
	PROCEDURE Subtract (READONLY a, b: Int;  VAR i: Int): BOOLEAN;
	(* returns 'a - b' unless there's an overflow *)
	
	PROCEDURE Multiply (READONLY a, b: Int;  VAR i: Int): BOOLEAN;
	(* returns 'a * b' unless there's an overflow *)
	
	***************
	*** 81,101 ****
	PROCEDURE EQ (READONLY a, b: Int): BOOLEAN;
	(* returns 'a = b' *)
	
	- PROCEDURE NE (READONLY a, b: Int): BOOLEAN;
	- (* returns 'a # b' *)
	-
	PROCEDURE LT (READONLY a, b: Int): BOOLEAN;
	(* returns 'a < b' *)
	
	- PROCEDURE GT (READONLY a, b: Int): BOOLEAN;
	- (* returns 'a > b' *)
	-
	PROCEDURE LE (READONLY a, b: Int): BOOLEAN;
	(* returns 'a <= b' *)
	
	- PROCEDURE GE (READONLY a, b: Int): BOOLEAN;
	- (* returns 'a >= b' *)
	-
	PROCEDURE ToText (READONLY i: Int): TEXT;
	(* converts 'i' to a printable string. *)
	
	--- 55,66 ----
	***************
	*** 103,111 ****
	(* converts 'i' to a printable string in 'buf'.  Returns the
	number of characters in the string.  Returns -1 if 'buf' is too short. *)
	
	! PROCEDURE ToBytes (READONLY i: Int;  VAR buf: ARRAY OF [0..255]): INTEGER;
	(* converts 'i' to the shortest sequence of bytes in little-endian order
	which when sign-extended equal 'i'.  Returns the number of
	!    significant bytes in the result.  Returns -1 if 'buf' is too short. *)
	
	END TInt.
	--- 68,79 ----
	(* converts 'i' to a printable string in 'buf'.  Returns the
	number of characters in the string.  Returns -1 if 'buf' is too short. *)
	
	! PROCEDURE ToBytes (READONLY i: Int;  VAR buf: ARRAY OF [0..255]): CARDINAL;
	(* converts 'i' to the shortest sequence of bytes in little-endian order
	which when sign-extended equal 'i'.  Returns the number of
	!    significant bytes in the result.  Returns 0 if 'buf' is too short. *)
	!
	! PROCEDURE Chop (VAR i: Int;  n: CARDINAL);
	! (* Extract the low-order 'n' bytes of 'i', sign extended. *)
	
	END TInt.
	Index: m3middle/src/TInt.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/TInt.m3,v
	retrieving revision 1.22
	diff -c -r1.22 TInt.m3
	*** m3middle/src/TInt.m3	10 Feb 2010 13:09:59 -0000	1.22
	--- m3middle/src/TInt.m3	18 Feb 2010 02:30:49 -0000
	***************
	*** 9,15 ****
	MODULE TInt;
	
	IMPORT Word, TWord, Text;
	! FROM Target IMPORT Int, IByte, IBytes;
	
	CONST (* IMPORTS *)
	RShift = Word.RightShift;
	--- 9,15 ----
	MODULE TInt;
	
	IMPORT Word, TWord, Text;
	! FROM Target IMPORT Int, IByte;
	
	CONST (* IMPORTS *)
	RShift = Word.RightShift;
	***************
	*** 17,109 ****
	And    = Word.And;
	
	CONST
	!   Mask     = 16_FF;
	!   SignMask = 16_80;
	!   Base     = 16_100;
	Digits   = ARRAY [0..9] OF CHAR { '0','1','2','3','4','5','6','7','8','9'};
	
	! PROCEDURE FromInt (x: INTEGER;  n: CARDINAL;  VAR r: Int): BOOLEAN =
	BEGIN
	!     <*ASSERT n # 0*>
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       r.x[i] := And (x, Mask);
	x := x DIV Base;
	END;
	!     RETURN (n > 0) AND (x = 0 OR x = -1);
	END FromInt;
	
	! TYPE Sign = {Bad, Neg, Pos};
	!
	! PROCEDURE CheckSign (READONLY r: Int;  n: CARDINAL): Sign =
	BEGIN
	!     <*ASSERT n # 0*>
	!     IF And (r.x[r.n-1], SignMask) = 0 THEN
	!       IF n < r.n THEN
	!         IF And (r.x[n-1], SignMask) # 0 THEN RETURN Sign.Bad END;
	!         FOR i := n TO r.n-1 DO
	!           IF r.x[i] # 0 THEN RETURN Sign.Bad END;
	!         END;
	!       END;
	!       RETURN Sign.Pos;
	!     ELSE
	!       IF n < r.n THEN
	!         IF And (r.x[n-1], SignMask) = 0 THEN RETURN Sign.Bad END;
	!         FOR i := n TO r.n-1 DO
	!           IF r.x[i] # Mask THEN RETURN Sign.Bad END;
	!         END;
	!       END;
	!       RETURN Sign.Neg;
	END;
	-   END CheckSign;
	
	- PROCEDURE IntI (READONLY r: Int;  n: CARDINAL;  VAR x: Int): BOOLEAN =
	-   VAR sign := CheckSign (r, n);  j := 0;  result := TRUE;
	-   BEGIN
	-     CASE sign OF
	-     | Sign.Bad => result := FALSE;
	-     | Sign.Pos => j := 0;
	-     | Sign.Neg => j := Mask;
	-     END;
	-     x.n := n;
	-     FOR i := 0 TO r.n-1 DO x.x[i] := r.x[i] END;
	-     FOR i := r.n TO n-1 DO x.x[i] := j END;
	-     RETURN result;
	-   END IntI;
	-
	- PROCEDURE ToInt (READONLY r: Int;  VAR x: INTEGER): BOOLEAN =
	-   VAR sign := CheckSign (r, BITSIZE (INTEGER) DIV BITSIZE (IByte));
	-       result := TRUE;
	-   BEGIN
	(* ensure the result has the right sign extension *)
	!     CASE sign OF
	!     | Sign.Bad => result := FALSE;
	!     | Sign.Pos => x := 0;
	!     | Sign.Neg => x := Word.Not (0);
	END;
	
	(* finally, pack the bits *)
	!     FOR i := r.n-1 TO 0 BY -1  DO
	!       x := Word.Or (LShift (x, BITSIZE (IByte)), r.x[i]);
	END;
	
	!     RETURN result;
	END ToInt;
	
	! PROCEDURE New (READONLY x: ARRAY OF CHAR;  n: CARDINAL;  VAR r: Int): BOOLEAN =
	CONST ZERO = ORD ('0');   ZEROZERO = 10 * ZERO + ZERO;
	VAR tmp, digit: Int;
	BEGIN
	!     <*ASSERT n # 0*>
	!     r := Int{n};
	IF (NUMBER (x) = 1) THEN
	!       r.x[0] := ORD (x[0]) - ZERO;
	ELSIF (NUMBER (x) = 2) THEN
	!       r.x[0] := 10 * ORD (x[0]) + ORD (x[1]) - ZEROZERO;
	ELSE
	!       digit := Int{n};
	FOR i := FIRST (x) TO LAST (x) DO
	!         digit.x[0] := ORD (x[i]) - ZERO;
	IF NOT Multiply (r, Ten, tmp) THEN RETURN FALSE; END;
	IF NOT Add (tmp, digit, r)    THEN RETURN FALSE; END;
	END;
	--- 17,74 ----
	And    = Word.And;
	
	CONST
	!   Mask     = RShift (Word.Not (0), Word.Size - BITSIZE (IByte));
	!   SignMask = LShift (1, BITSIZE (IByte) - 1);
	!   Base     = Mask + 1;
	Digits   = ARRAY [0..9] OF CHAR { '0','1','2','3','4','5','6','7','8','9'};
	+   Ten      = Int{10,0,..};
	
	! PROCEDURE FromInt (x: INTEGER;  VAR r: Int): BOOLEAN =
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       r [i] := And (x, Mask);
	x := x DIV Base;
	END;
	!     RETURN (x = 0 OR x = -1);
	END FromInt;
	
	! PROCEDURE ToInt (READONLY r: Int;  VAR x: INTEGER): BOOLEAN =
	!   CONST Extras = BITSIZE (INTEGER) DIV BITSIZE (IByte);
	!   VAR j := 0;  sign_chunk := MIN (Extras - 1, LAST(Int));
	BEGIN
	!     (* check that any extra bits are the same as the sign bit *)
	!     IF And (r [sign_chunk], SignMask) # 0 THEN j := Mask; END;
	!     FOR i := Extras TO LAST(Int) DO
	!       IF r [i] # j THEN RETURN FALSE; END;
	END;
	
	(* ensure the result has the right sign extension *)
	!     IF j = 0
	!       THEN x := 0;
	!       ELSE x := Word.Not (0);
	END;
	
	(* finally, pack the bits *)
	!     FOR i := LAST(Int) TO 0 BY -1  DO
	!       x := Word.Or (LShift (x, BITSIZE (IByte)), r[i]);
	END;
	
	!     RETURN TRUE;
	END ToInt;
	
	! PROCEDURE New (READONLY x: ARRAY OF CHAR;  VAR r: Int): BOOLEAN =
	CONST ZERO = ORD ('0');   ZEROZERO = 10 * ZERO + ZERO;
	VAR tmp, digit: Int;
	BEGIN
	!     r := Zero;
	IF (NUMBER (x) = 1) THEN
	!       r[0] := ORD (x[0]) - ZERO;
	ELSIF (NUMBER (x) = 2) THEN
	!       r[0] := 10 * ORD (x[0]) + ORD (x[1]) - ZEROZERO;
	ELSE
	!       digit := Zero;
	FOR i := FIRST (x) TO LAST (x) DO
	!         digit [0] := ORD (x[i]) - ZERO;
	IF NOT Multiply (r, Ten, tmp) THEN RETURN FALSE; END;
	IF NOT Add (tmp, digit, r)    THEN RETURN FALSE; END;
	END;
	***************
	*** 113,206 ****
	
	PROCEDURE Add (READONLY a, b: Int;  VAR r: Int): BOOLEAN =
	(* It is safe for r to alias a or b *)
	!   VAR n := MIN (a.n, b.n);  carry := 0;  r_sign := Sign.Bad;
	!       a_sign := CheckSign (a, n);  b_sign := CheckSign (b, n);
	!   BEGIN
	!     IF (a_sign = Sign.Bad) OR (b_sign = Sign.Bad) THEN
	!       RETURN FALSE
	!     END;
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       carry := a.x[i] + b.x[i] + carry;
	!       r.x[i] := And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	!     r_sign := CheckSign (r, n);  <*ASSERT r_sign # Sign.Bad*>
	RETURN (a_sign # b_sign) OR (a_sign = r_sign);
	END Add;
	
	PROCEDURE Subtract (READONLY a, b: Int;  VAR r: Int): BOOLEAN =
	(* It is safe for r to alias a or b *)
	!   VAR n := MIN (a.n, b.n);  borrow := 0; r_sign := Sign.Bad;
	!       a_sign := CheckSign (a, n);  b_sign := CheckSign (b, n);
	!   BEGIN
	!     IF (a_sign = Sign.Bad) OR (b_sign = Sign.Bad) THEN
	!       RETURN FALSE
	!     END;
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       borrow := a.x[i] - b.x[i] - borrow;
	!       r.x[i] := And (borrow, Mask);
	borrow := And (RShift (borrow, BITSIZE (IByte)), 1);
	END;
	!     r_sign := CheckSign (r, n);  <*ASSERT r_sign # Sign.Bad*>
	RETURN (a_sign = b_sign) OR (a_sign = r_sign);
	END Subtract;
	
	- PROCEDURE Negate (READONLY a: Int;  VAR r: Int): BOOLEAN =
	-   (* It is safe for r to alias a *)
	-   BEGIN
	-     RETURN Subtract(Zero, a, r);
	-   END Negate;
	-
	- PROCEDURE Abs (READONLY a: Int;  VAR r: Int): BOOLEAN =
	-   (* It is safe for r to alias a *)
	-   BEGIN
	-     IF GE(a, Zero) THEN
	-       r := a;
	-       RETURN TRUE;
	-     END;
	-     RETURN Negate(a, r);
	-   END Abs;
	-
	PROCEDURE Multiply (READONLY a, b: Int;  VAR r: Int): BOOLEAN =
	VAR
	!     n := MIN (a.n, b.n);  k, carry: INTEGER;  q: Int;
	!     p := ARRAY [0.. 2 * NUMBER (IBytes) - 1] OF IByte {0, ..};
	!     a_sign := CheckSign (a, n);  b_sign := CheckSign (b, n);
	BEGIN
	!     IF (a_sign = Sign.Bad) OR (b_sign = Sign.Bad) THEN
	!       RETURN FALSE
	!     END;
	!     FOR i := 0 TO n-1 DO
	!       FOR j := 0 TO n-1 DO
	k := i + j;
	!         carry := Word.Times (a.x[i], b.x[j]);
	WHILE carry # 0 DO
	!           carry := carry + p[k];
	!           p[k] := And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	INC (k);
	END;
	END;
	END;
	
	!     r.n := n; FOR i := 0 TO n-1 DO r.x[i] := p[i]; END;
	!     q.n := n; FOR i := 0 TO n-1 DO q.x[i] := p[i+n]; END;
	
	(* compute the top half *)
	!     IF And (a.x[n-1], SignMask) # 0 THEN EVAL Subtract (q, b, q); END;
	!     IF And (b.x[n-1], SignMask) # 0 THEN EVAL Subtract (q, a, q); END;
	
	(* there is overflow if the top half is not equal to
	to the sign bit of the low half *)
	!     CASE CheckSign (r, n) OF
	!     | Sign.Bad => <*ASSERT FALSE*>
	!     | Sign.Pos => carry := 0;
	!     | Sign.Neg => carry := Mask;
	!     END;
	!     FOR i := 0 TO n-1 DO
	!       IF q.x[i] # carry THEN RETURN FALSE; END;
	END;
	
	RETURN TRUE;
	--- 78,145 ----
	
	PROCEDURE Add (READONLY a, b: Int;  VAR r: Int): BOOLEAN =
	(* It is safe for r to alias a or b *)
	!   VAR carry := 0;
	!       a_sign := And (a [LAST(Int)], SignMask);
	!       b_sign := And (b [LAST(Int)], SignMask);
	!       r_sign : Word.T;
	!   BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       carry := a [i] + b [i] + carry;
	!       r [i] := And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	!     r_sign := And (r [LAST(Int)], SignMask);
	RETURN (a_sign # b_sign) OR (a_sign = r_sign);
	END Add;
	
	PROCEDURE Subtract (READONLY a, b: Int;  VAR r: Int): BOOLEAN =
	(* It is safe for r to alias a or b *)
	!   VAR borrow := 0;
	!       a_sign := And (a [LAST(Int)], SignMask);
	!       b_sign := And (b [LAST(Int)], SignMask);
	!       r_sign : Word.T;
	!   BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       borrow := a [i] - b [i] - borrow;
	!       r [i] := And (borrow, Mask);
	borrow := And (RShift (borrow, BITSIZE (IByte)), 1);
	END;
	!     r_sign := And (r [LAST(Int)], SignMask);
	RETURN (a_sign = b_sign) OR (a_sign = r_sign);
	END Subtract;
	
	PROCEDURE Multiply (READONLY a, b: Int;  VAR r: Int): BOOLEAN =
	VAR
	!     k, carry: INTEGER;
	!     q: Int;
	!     p := ARRAY [0.. 2 * NUMBER(Int) - 1] OF IByte {0, ..};
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       FOR j := 0 TO LAST(Int) DO
	k := i + j;
	!         carry := Word.Times (a [i], b [j]);
	WHILE carry # 0 DO
	!           carry := carry + p [k];
	!           p [k] := And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	INC (k);
	END;
	END;
	END;
	
	!     FOR i := 0 TO LAST(Int) DO r[i] := p[i]; END;
	!     FOR i := 0 TO LAST(Int) DO q[i] := p[i+NUMBER(Int)]; END;
	
	(* compute the top half *)
	!     IF And (a [LAST(Int)], SignMask) # 0 THEN EVAL Subtract (q, b, q); END;
	!     IF And (b [LAST(Int)], SignMask) # 0 THEN EVAL Subtract (q, a, q); END;
	
	(* there is overflow if the top half is not equal to
	to the sign bit of the low half *)
	!     carry := 0;
	!     IF And (r [LAST(Int)], SignMask) # 0 THEN carry := Mask;  END;
	!     FOR i := 0 TO LAST(Int) DO
	!       IF q[i] # carry THEN RETURN FALSE; END;
	END;
	
	RETURN TRUE;
	***************
	*** 224,250 ****
	VAR
	num     := a;
	den     := b;
	!     num_neg: BOOLEAN;
	!     den_neg: BOOLEAN;
	!     n := MIN (a.n, b.n);
	!     a_sign := CheckSign (a, n);
	!     b_sign := CheckSign (b, n);
	!     min: Int;
	BEGIN
	-     IF (a_sign = Sign.Bad) OR (b_sign = Sign.Bad) THEN
	-       RETURN FALSE
	-     END;
	-
	IF EQ (b, Zero) THEN  RETURN FALSE;  END;
	IF EQ (a, Zero) THEN  q := Zero;  r := Zero;  RETURN TRUE;  END;
	
	(* grab the signs *)
	!     num_neg := a_sign = Sign.Neg;
	!     den_neg := b_sign = Sign.Neg;
	
	!     (* check for the only possible overflow:  FIRST DIV -1 *)
	IF num_neg AND den_neg THEN
	!       TWord.Shift (MOne, n * BITSIZE (IByte) - 1, min);
	IF EQ (a, min) AND EQ (b, MOne) THEN
	RETURN FALSE;
	END;
	--- 163,182 ----
	VAR
	num     := a;
	den     := b;
	!     num_neg : BOOLEAN;
	!     den_neg : BOOLEAN;
	!     min     : Int;
	BEGIN
	IF EQ (b, Zero) THEN  RETURN FALSE;  END;
	IF EQ (a, Zero) THEN  q := Zero;  r := Zero;  RETURN TRUE;  END;
	
	(* grab the signs *)
	!     num_neg := And (a [LAST(Int)], SignMask) # 0;
	!     den_neg := And (b [LAST(Int)], SignMask) # 0;
	
	!     (* check for the only possible overflow:  FIRST(Int) DIV -1 *)
	IF num_neg AND den_neg THEN
	!       TWord.Shift (MOne, Size - 1, min);
	IF EQ (a, min) AND EQ (b, MOne) THEN
	RETURN FALSE;
	END;
	***************
	*** 296,327 ****
	*)
	
	PROCEDURE EQ (READONLY a, b: Int): BOOLEAN =
	-   VAR n := MIN (a.n, b.n);
	BEGIN
	!     IF (CheckSign (a, n) = Sign.Bad) OR (CheckSign (b, n) = Sign.Bad) THEN
	!       RETURN FALSE;
	!     END;
	!     FOR i := 0 TO n-1 DO
	!       IF a.x[i] # b.x[i] THEN RETURN FALSE; END;
	END;
	RETURN TRUE;
	END EQ;
	
	PROCEDURE LT (READONLY a, b: Int): BOOLEAN =
	!   VAR a_sign := CheckSign (a, a.n);
	!       b_sign := CheckSign (b, b.n);
	!       n := MIN (a.n, b.n);
	!   BEGIN
	!     <*ASSERT a_sign # Sign.Bad*>
	!     <*ASSERT b_sign # Sign.Bad*>
	!     IF (a_sign # b_sign) THEN RETURN (a_sign = Sign.Neg); END;
	!
	!     IF CheckSign (a, n) = Sign.Bad THEN RETURN a_sign = Sign.Neg END;
	!     IF CheckSign (b, n) = Sign.Bad THEN RETURN b_sign = Sign.Pos END;
	!
	!     FOR i := n-1 TO 0 BY -1 DO
	!       IF    a.x[i] < b.x[i] THEN  RETURN TRUE;
	!       ELSIF a.x[i] > b.x[i] THEN  RETURN FALSE;
	END;
	END;
	
	--- 228,249 ----
	*)
	
	PROCEDURE EQ (READONLY a, b: Int): BOOLEAN =
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       IF a[i] # b[i] THEN RETURN FALSE; END;
	END;
	RETURN TRUE;
	END EQ;
	
	PROCEDURE LT (READONLY a, b: Int): BOOLEAN =
	!   VAR a_sign := And (a [LAST(Int)], SignMask);
	!       b_sign := And (b [LAST(Int)], SignMask);
	!   BEGIN
	!     IF (a_sign # b_sign) THEN RETURN (a_sign # 0); END;
	!
	!     FOR i := LAST(Int) TO 0 BY -1 DO
	!       IF    a [i] < b [i] THEN  RETURN TRUE;
	!       ELSIF a [i] > b [i] THEN  RETURN FALSE;
	END;
	END;
	
	***************
	*** 333,355 ****
	RETURN EQ (a, b) OR LT (a, b);
	END LE;
	
	- PROCEDURE NE (READONLY a, b: Int): BOOLEAN =
	-   BEGIN
	-     RETURN NOT EQ (a, b);
	-   END NE;
	-
	- PROCEDURE GT (READONLY a, b: Int): BOOLEAN =
	-   BEGIN
	-     RETURN LT (b, a);
	-   END GT;
	-
	- PROCEDURE GE (READONLY a, b: Int): BOOLEAN =
	-   BEGIN
	-     RETURN LE(b, a);
	-   END GE;
	-
	PROCEDURE ToText (READONLY r: Int): TEXT =
	!   VAR result  : ARRAY [0..BITSIZE (IByte) * NUMBER (IBytes)] OF CHAR;
	BEGIN
	RETURN Text.FromChars(SUBARRAY(result, 0, ToChars(r, result)));
	END ToText;
	--- 255,262 ----
	RETURN EQ (a, b) OR LT (a, b);
	END LE;
	
	PROCEDURE ToText (READONLY r: Int): TEXT =
	!   VAR result: ARRAY [0..BITSIZE (Int)] OF CHAR;
	BEGIN
	RETURN Text.FromChars(SUBARRAY(result, 0, ToChars(r, result)));
	END ToText;
	***************
	*** 360,369 ****
	minus   : BOOLEAN := FALSE;
	bump    : BOOLEAN := FALSE;
	i, j    : INTEGER;
	!     result  : ARRAY [0..BITSIZE (IByte) * NUMBER (IBytes)] OF CHAR;
	rr      := r;
	!     quo, rem, min: Int;
	!     n := r.n;
	BEGIN
	IF EQ (r, Zero) THEN
	result [0] := '0';
	--- 267,276 ----
	minus   : BOOLEAN := FALSE;
	bump    : BOOLEAN := FALSE;
	i, j    : INTEGER;
	!     result  : ARRAY [0..Size] OF CHAR;
	rr      := r;
	!     quo, rem: Int;
	!     min     : Int;
	BEGIN
	IF EQ (r, Zero) THEN
	result [0] := '0';
	***************
	*** 372,381 ****
	ELSE (* handle a non-zero number *)
	
	(* get rid of negative numbers *)
	!       IF And (r.x[n-1], SignMask) # 0 THEN
	!         TWord.Shift (MOne, n * BITSIZE (IByte) - 1, min);
	IF EQ (r, min) THEN
	!           (* 2's complement makes FIRST a special case *)
	bump := TRUE;
	EVAL Add (rr, One, rr);
	END;
	--- 279,288 ----
	ELSE (* handle a non-zero number *)
	
	(* get rid of negative numbers *)
	!       IF And (r [LAST(Int)], SignMask) # 0 THEN
	!         TWord.Shift (MOne, Size - 1, min);
	IF EQ (r, min) THEN
	!           (* 2's complement makes FIRST(Int) a special case *)
	bump := TRUE;
	EVAL Add (rr, One, rr);
	END;
	***************
	*** 386,397 ****
	(* convert the bulk of the digits *)
	WHILE LT (Zero, rr) DO
	TWord.DivMod (rr, Ten, quo, rem);
	!         result [nDigits] := Digits [rem.x [0]];
	rr := quo;
	INC (nDigits);
	END;
	
	!       (* fixup FIRST *)
	IF (bump) THEN
	result [nDigits] := '0';
	j := 0;
	--- 293,304 ----
	(* convert the bulk of the digits *)
	WHILE LT (Zero, rr) DO
	TWord.DivMod (rr, Ten, quo, rem);
	!         result [nDigits] := Digits [rem [0]];
	rr := quo;
	INC (nDigits);
	END;
	
	!       (* fixup FIRST (Int) *)
	IF (bump) THEN
	result [nDigits] := '0';
	j := 0;
	***************
	*** 399,405 ****
	i := ORD (result [j]) - ORD ('0');
	INC (i);
	IF (i < 10) THEN
	!             result [j] := Digits [i];
	EXIT;
	END;
	result [j] := '0';
	--- 306,312 ----
	i := ORD (result [j]) - ORD ('0');
	INC (i);
	IF (i < 10) THEN
	!             result [j] := Digits [i];
	EXIT;
	END;
	result [j] := '0';
	***************
	*** 416,422 ****
	
	(* build the result buffer *)
	j := 0;
	!     IF (minus)  THEN
	buf [0] := '-';
	j := 1; END;
	FOR k := nDigits-1 TO 0 BY -1 DO
	--- 323,329 ----
	
	(* build the result buffer *)
	j := 0;
	!     IF (minus) THEN
	buf [0] := '-';
	j := 1; END;
	FOR k := nDigits-1 TO 0 BY -1 DO
	***************
	*** 426,447 ****
	RETURN j;
	END ToChars;
	
	! PROCEDURE ToBytes (READONLY r: Int;  VAR buf: ARRAY OF [0..255]): INTEGER =
	!   VAR n := r.n;  j := 0;  k := n;
	BEGIN
	(* strip the sign extension *)
	!     IF And (r.x[n-1], SignMask) # 0 THEN j := Mask END;
	!     FOR i := n-1 TO 0 BY -1 DO
	!       IF r.x[i] # j THEN EXIT END;
	!       DEC (k);
	!     END;
	!     <* ASSERT (k = 0) = (EQ(r, Zero) OR EQ(r, MOne)) *>
	!     INC(k, ORD(k = 0)); (* increment if 0 *)
	!     IF k > NUMBER (buf) THEN RETURN -1 END;
	(* unpack the bytes *)
	!     FOR i := 0 TO k-1 DO buf[i] := r.x[i] END;
	!     RETURN k;
	END ToBytes;
	
	BEGIN
	END TInt.
	--- 333,365 ----
	RETURN j;
	END ToChars;
	
	! PROCEDURE ToBytes (READONLY r: Int;  VAR buf: ARRAY OF [0..255]): CARDINAL =
	!   VAR j := NUMBER(Int);
	BEGIN
	(* strip the sign extension *)
	!     DEC (j);
	!     IF (r[j] = 0) THEN
	!       WHILE (j > 0) AND (r[j] = 0) AND (r[j-1] < 16_80) DO DEC (j); END;
	!     ELSIF (r[j] = 16_ff) THEN
	!       WHILE (j > 0) AND (r[j] = 16_ff) AND (r[j-1] >= 16_80) DO DEC (j); END;
	!     END;
	!     INC (j);
	!
	!     IF j > NUMBER (buf) THEN RETURN 0 END;
	!
	(* unpack the bytes *)
	!     FOR i := 0 TO j-1 DO buf[i] := r[i] END;
	!
	!     RETURN j;
	END ToBytes;
	
	+ PROCEDURE Chop (VAR r: Int;  n: CARDINAL) =
	+   BEGIN
	+     IF And (r [n-1], SignMask) = 0
	+       THEN FOR i := n TO LAST(Int) DO r [i] := 0    END;
	+       ELSE FOR i := n TO LAST(Int) DO r [i] := Mask END;
	+     END;
	+   END Chop;
	+
	BEGIN
	END TInt.
	Index: m3middle/src/TWord.i3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/TWord.i3,v
	retrieving revision 1.8
	diff -c -r1.8 TWord.i3
	*** m3middle/src/TWord.i3	24 Jan 2010 12:29:14 -0000	1.8
	--- m3middle/src/TWord.i3	18 Feb 2010 02:30:49 -0000
	***************
	*** 10,17 ****
	
	(*  Modula-3 target description
	
	!     This interface provides simulations of the target machine's
	!     unsigned integer operations.
	
	Unless otherwise specified, the arithmetic operations defined
	below return TRUE if they succeed in producing a new target value,
	--- 10,17 ----
	
	(*  Modula-3 target description
	
	!     This interface provides simulations of unsigned integer operations, at the
	!     maximum precision supported by any target.
	
	Unless otherwise specified, the arithmetic operations defined
	below return TRUE if they succeed in producing a new target value,
	***************
	*** 20,26 ****
	
	FROM Target IMPORT Int;
	
	! PROCEDURE New (READONLY chars: ARRAY OF CHAR;  base: [2..16];  n: CARDINAL;
	VAR i: Int): BOOLEAN;
	(* converts the string of characters in 'chars' representing a base 'base'
	number to an integer value in 'i' *)
	--- 20,28 ----
	
	FROM Target IMPORT Int;
	
	! CONST Size = BITSIZE(Int);
	!
	! PROCEDURE New (READONLY chars: ARRAY OF CHAR;  base: [2..16];
	VAR i: Int): BOOLEAN;
	(* converts the string of characters in 'chars' representing a base 'base'
	number to an integer value in 'i' *)
	***************
	*** 43,54 ****
	PROCEDURE DivMod (READONLY x, y: Int;  VAR q, r: Int);
	(* returns 'q = x DIV y', and 'r = x MOD y', but assumes that 'y # 0' *)
	
	! PROCEDURE LT (READONLY a, b: Int): BOOLEAN; (* a < b *)
	! PROCEDURE LE (READONLY a, b: Int): BOOLEAN; (* a <= b *)
	! PROCEDURE EQ (READONLY a, b: Int): BOOLEAN; (* a = b *)
	! PROCEDURE NE (READONLY a, b: Int): BOOLEAN; (* a # b *)
	! PROCEDURE GE (READONLY a, b: Int): BOOLEAN; (* a >= b *)
	! PROCEDURE GT (READONLY a, b: Int): BOOLEAN; (* a > b *)
	
	PROCEDURE And (READONLY a, b: Int;  VAR i: Int);
	(* returns 'Word.And (a, b)' *)
	--- 45,55 ----
	PROCEDURE DivMod (READONLY x, y: Int;  VAR q, r: Int);
	(* returns 'q = x DIV y', and 'r = x MOD y', but assumes that 'y # 0' *)
	
	! PROCEDURE LT (READONLY a, b: Int): BOOLEAN;
	! (* returns 'Word.LT (a, b)' *)
	!
	! PROCEDURE LE (READONLY a, b: Int): BOOLEAN;
	! (* returns 'Word.LE (a, b)' *)
	
	PROCEDURE And (READONLY a, b: Int;  VAR i: Int);
	(* returns 'Word.And (a, b)' *)
	***************
	*** 62,83 ****
	PROCEDURE Not (READONLY a: Int;  VAR i: Int);
	(* returns 'Word.Not (a)' *)
	
	! PROCEDURE Shift (READONLY x: Int;  n: INTEGER;  VAR r: Int);
	! (* returns 'Word.Shift (x, n)' *)
	
	! PROCEDURE LeftShift (READONLY x: Int;  n: CARDINAL;  VAR r: Int);
	! (* returns 'Word.LeftShift (x, n)' *)
	
	! PROCEDURE RightShift (READONLY x: Int;  n: CARDINAL;  VAR r: Int);
	! (* returns 'Word.RightShift (x, n)' *)
	
	! PROCEDURE Rotate (READONLY x: Int;  n: INTEGER;  VAR r: Int);
	! (* returns 'Word.Rotate (x, n)' *)
	
	! PROCEDURE Extract (READONLY x: Int;  i, n: CARDINAL;  VAR r: Int): BOOLEAN;
	! (* returns 'Word.Extract (x, i, n)' *)
	
	! PROCEDURE Insert (READONLY x, y: Int;  i, n: CARDINAL;  VAR r: Int): BOOLEAN;
	! (* returns 'Word.Insert (x, y, i, n)' *)
	
	END TWord.
	--- 63,84 ----
	PROCEDURE Not (READONLY a: Int;  VAR i: Int);
	(* returns 'Word.Not (a)' *)
	
	! PROCEDURE Shift (READONLY a: Int;  b: INTEGER;  VAR r: Int);
	! (* returns 'Word.Shift (a, b)' *)
	
	! PROCEDURE LeftShift (READONLY a: Int;  b: [0..Size-1];  VAR r: Int);
	! (* returns 'Word.LeftShift (a, b)' *)
	
	! PROCEDURE RightShift (READONLY a: Int;  b: [0..Size-1];  VAR r: Int);
	! (* returns 'Word.RightShift (a, b)' *)
	
	! PROCEDURE Rotate (READONLY a: Int;  b: INTEGER;  n: CARDINAL;  VAR r: Int);
	! (* returns 'Word.Rotate (a, b)' *)
	
	! PROCEDURE Extract (READONLY a: Int;  b, c: CARDINAL;  VAR r: Int): BOOLEAN;
	! (* returns 'Word.Extract (a, b, c)' *)
	
	! PROCEDURE Insert (READONLY a, b: Int;  c, d: CARDINAL;  VAR r: Int): BOOLEAN;
	! (* returns 'Word.Insert (a, b, c, d)' *)
	
	END TWord.
	Index: m3middle/src/TWord.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/TWord.m3,v
	retrieving revision 1.15
	diff -c -r1.15 TWord.m3
	*** m3middle/src/TWord.m3	10 Feb 2010 16:33:10 -0000	1.15
	--- m3middle/src/TWord.m3	18 Feb 2010 02:30:49 -0000
	***************
	*** 9,32 ****
	MODULE TWord;
	
	IMPORT Word, TInt;
	! FROM Target IMPORT Int, IByte, IBytes;
	
	CONST (* IMPORTS *)
	RShift = Word.RightShift;
	LShift = Word.LeftShift;
	
	CONST
	!   Mask = 16_FF;
	!   Base = 16_100;
	
	(*------------------------------------------- unsigned integer operations ---*)
	
	! PROCEDURE New (READONLY x: ARRAY OF CHAR; base: [2..16];  n: CARDINAL;
	!                VAR r: Int): BOOLEAN =
	!   VAR rr: IBytes;  digit: INTEGER;  ch: CHAR;
	BEGIN
	!     <*ASSERT n # 0*>
	!     r := Int{n};
	FOR i := FIRST (x) TO LAST (x) DO
	ch := x [i];
	IF    ('0' <= ch) AND (ch <= '9') THEN  digit := ORD (ch) - ORD ('0');
	--- 9,30 ----
	MODULE TWord;
	
	IMPORT Word, TInt;
	! FROM Target IMPORT Int, IByte;
	
	CONST (* IMPORTS *)
	RShift = Word.RightShift;
	LShift = Word.LeftShift;
	
	CONST
	!   Mask = RShift (Word.Not (0), Word.Size - BITSIZE (IByte));
	!   Base = Mask + 1;
	
	(*------------------------------------------- unsigned integer operations ---*)
	
	! PROCEDURE New (READONLY x: ARRAY OF CHAR; base: [2..16];  VAR r: Int): BOOLEAN =
	!   VAR rr: Int;  digit: INTEGER;  ch: CHAR;
	BEGIN
	!     r := TInt.Zero;
	FOR i := FIRST (x) TO LAST (x) DO
	ch := x [i];
	IF    ('0' <= ch) AND (ch <= '9') THEN  digit := ORD (ch) - ORD ('0');
	***************
	*** 36,49 ****
	END;
	
	(* rr := r * base *)
	!       rr := IBytes {0,..};
	!       FOR i := 0 TO n-1 DO
	!         VAR carry := Word.Times (r.x[i], base);
	BEGIN
	!           FOR j := i TO n-1 DO
	IF carry = 0 THEN EXIT END;
	!             INC (carry, rr[j]);
	!             rr[j] := Word.And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	IF carry # 0 THEN RETURN FALSE END;
	--- 34,47 ----
	END;
	
	(* rr := r * base *)
	!       rr := TInt.Zero;
	!       FOR i := 0 TO LAST(Int) DO
	!         VAR carry := Word.Times (r[i], base);
	BEGIN
	!           FOR j := i TO LAST(Int) DO
	IF carry = 0 THEN EXIT END;
	!             INC (carry, rr [j]);
	!             rr [j] := Word.And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	IF carry # 0 THEN RETURN FALSE END;
	***************
	*** 53,61 ****
	(* r := rr + digit *)
	VAR carry := digit;
	BEGIN
	!         FOR i := 0 TO n-1 DO
	!           INC (carry, rr[i]);
	!           r.x[i] := Word.And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	IF carry # 0 THEN RETURN FALSE END;
	--- 51,59 ----
	(* r := rr + digit *)
	VAR carry := digit;
	BEGIN
	!         FOR i := 0 TO LAST(Int) DO
	!           INC (carry, rr [i]);
	!           r[i] := Word.And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	IF carry # 0 THEN RETURN FALSE END;
	***************
	*** 66,106 ****
	END New;
	
	PROCEDURE Add (READONLY a, b: Int;  VAR r: Int) =
	!   VAR carry := 0;  n := MIN (a.n, b.n);
	BEGIN
	!     <*ASSERT n # 0*>
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       carry := a.x[i] + b.x[i] + carry;
	!       r.x[i] := Word.And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	END Add;
	
	PROCEDURE Subtract (READONLY a, b: Int;  VAR r: Int) =
	!   VAR borrow := 0;  n := MIN (a.n, b.n);
	BEGIN
	!     <*ASSERT n # 0*>
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       borrow := a.x[i] - b.x[i] - borrow;
	!       r.x[i] := Word.And (borrow, Mask);
	borrow := Word.And (RShift (borrow, BITSIZE (IByte)), 1);
	END;
	END Subtract;
	
	PROCEDURE Multiply (READONLY a, b: Int;  VAR r: Int) =
	!   VAR carry: INTEGER;  n := MIN (a.n, b.n);
	BEGIN
	!     <*ASSERT n # 0*>
	!     r := Int{n};
	!     FOR i := 0 TO n-1 DO
	!       FOR j := 0 TO n-1 DO
	!         carry := Word.Times (a.x[i], b.x[j]);
	!         FOR k := i + j TO n-1 DO
	IF carry = 0 THEN EXIT END;
	!           carry := carry + r.x[k];
	!           r.x[k] := Word.And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	END;
	--- 64,99 ----
	END New;
	
	PROCEDURE Add (READONLY a, b: Int;  VAR r: Int) =
	!   VAR carry := 0;
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       carry := a[i] + b[i] + carry;
	!       r[i] := Word.And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	END Add;
	
	PROCEDURE Subtract (READONLY a, b: Int;  VAR r: Int) =
	!   VAR borrow := 0;
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       borrow := a [i] - b [i] - borrow;
	!       r [i] := Word.And (borrow, Mask);
	borrow := Word.And (RShift (borrow, BITSIZE (IByte)), 1);
	END;
	END Subtract;
	
	PROCEDURE Multiply (READONLY a, b: Int;  VAR r: Int) =
	!   VAR carry: INTEGER;
	BEGIN
	!     r := TInt.Zero;
	!     FOR i := 0 TO LAST(Int) DO
	!       FOR j := 0 TO LAST(Int) DO
	!         carry := Word.Times (a[i], b[j]);
	!         FOR k := i + j TO LAST(Int) DO
	IF carry = 0 THEN EXIT END;
	!           carry := carry + r[k];
	!           r[k] := Word.And (carry, Mask);
	carry := RShift (carry, BITSIZE (IByte));
	END;
	END;
	***************
	*** 136,168 ****
	quo_est : INTEGER;
	num_hi  : INTEGER;
	x1,x2,x3: INTEGER;
	!     num, den: ARRAY [0..NUMBER (IBytes)+1] OF INTEGER;
	!     n := MIN (x.n, y.n);
	BEGIN
	-     <*ASSERT n # 0*>
	(* initialize the numerator and denominator,
	and find the highest non-zero digits *)
	!     FOR i := 0 TO n-1 DO
	!       num[i] := x.x[i];  IF num[i] # 0 THEN max_num := i END;
	!       den[i] := y.x[i];  IF den[i] # 0 THEN max_den := i END;
	!     END;
	!     FOR i := n TO LAST (num) DO
	!       num[i] := 0;
	!       den[i] := 0;
	END;
	
	!     q := Int{n};
	!     r := Int{n};
	
	IF max_den = 0 THEN
	(* single digit denominator case *)
	carry := 0;
	FOR j := max_num TO 0 BY -1 DO
	tmp := carry * Base + num [j];
	!         q.x [j] := tmp DIV den[0];
	carry := tmp MOD den[0];
	END;
	!       r.x[0] := carry;
	RETURN;
	END;
	
	--- 129,155 ----
	quo_est : INTEGER;
	num_hi  : INTEGER;
	x1,x2,x3: INTEGER;
	!     num, den := ARRAY [0..NUMBER (Int)+1] OF INTEGER {0,..};
	BEGIN
	(* initialize the numerator and denominator,
	and find the highest non-zero digits *)
	!     FOR i := 0 TO LAST(Int) DO
	!       num[i] := x[i];  IF num[i] # 0 THEN max_num := i; END;
	!       den[i] := y[i];  IF den[i] # 0 THEN max_den := i; END;
	END;
	
	!     q := TInt.Zero;
	!     r := TInt.Zero;
	
	IF max_den = 0 THEN
	(* single digit denominator case *)
	carry := 0;
	FOR j := max_num TO 0 BY -1 DO
	tmp := carry * Base + num [j];
	!         q [j] := tmp DIV den[0];
	carry := tmp MOD den[0];
	END;
	!       r[0] := carry;
	RETURN;
	END;
	
	***************
	*** 237,243 ****
	END;
	
	(* store the quotient digit.  *)
	!       q.x [i - 1] := quo_est;
	END;
	
	(* finally, compute the remainder *)
	--- 224,230 ----
	END;
	
	(* store the quotient digit.  *)
	!       q [i - 1] := quo_est;
	END;
	
	(* finally, compute the remainder *)
	***************
	*** 246,420 ****
	END DivMod;
	
	PROCEDURE LT (READONLY a, b: Int): BOOLEAN =
	-   VAR n := MIN (a.n, b.n);
	BEGIN
	!     <*ASSERT n # 0*>
	!     FOR i := n TO a.n-1 DO IF a.x[i] # 0 THEN RETURN FALSE END END;
	!     FOR i := n TO b.n-1 DO IF b.x[i] # 0 THEN RETURN TRUE  END END;
	!     FOR i := n-1 TO 0 BY -1 DO
	!       IF    a.x[i] < b.x[i] THEN RETURN TRUE;
	!       ELSIF a.x[i] > b.x[i] THEN RETURN FALSE;
	END;
	END;
	RETURN FALSE;
	END LT;
	
	PROCEDURE LE (READONLY a, b: Int): BOOLEAN =
	-   VAR n := MIN (a.n, b.n);
	BEGIN
	!     <*ASSERT n # 0*>
	!     FOR i := n TO a.n-1 DO IF a.x[i] # 0 THEN RETURN FALSE END END;
	!     FOR i := n TO b.n-1 DO IF b.x[i] # 0 THEN RETURN TRUE  END END;
	!     FOR i := n-1 TO 0 BY -1 DO
	!       IF    a.x[i] < b.x[i] THEN RETURN TRUE;
	!       ELSIF a.x[i] > b.x[i] THEN RETURN FALSE;
	END;
	END;
	RETURN TRUE;
	END LE;
	
	- PROCEDURE xEQ (READONLY a, b: Int): BOOLEAN =
	-   VAR n := MIN (a.n, b.n);
	-   BEGIN
	-     <*ASSERT n # 0*>
	-     FOR i := n-1 TO 0 BY -1 DO
	-       IF a.x[i] # b.x[i] THEN
	-         RETURN FALSE;
	-       END;
	-     END;
	-     FOR i := n TO a.n-1 DO IF a.x[i] # 0 THEN RETURN FALSE END END;
	-     FOR i := n TO b.n-1 DO IF b.x[i] # 0 THEN RETURN FALSE END END;
	-     RETURN TRUE;
	-   END xEQ;
	-
	- PROCEDURE EQ (READONLY a, b: Int): BOOLEAN =
	-   VAR x := xEQ(a, b);
	-   BEGIN
	-     <* ASSERT x = xEQ(b, a) *>
	-     <* ASSERT x = (LE(a, b) AND LE(b, a)) *>
	-     RETURN x;
	-   END EQ;
	-
	- PROCEDURE NE (READONLY a, b: Int): BOOLEAN =
	-   VAR x := NOT xEQ(a, b);
	-   BEGIN
	-     <* ASSERT x = (NOT xEQ(b, a)) *>
	-     <* ASSERT x = (LT(a, b) OR LT(b, a)) *>
	-     RETURN x;
	-   END NE;
	-
	- PROCEDURE GE (READONLY a, b: Int): BOOLEAN =
	-   BEGIN
	-     RETURN LE(b, a);
	-   END GE;
	-
	- PROCEDURE GT (READONLY a, b: Int): BOOLEAN =
	-   BEGIN
	-     RETURN LT(b, a);
	-   END GT;
	-
	PROCEDURE And (READONLY a, b: Int;  VAR r: Int) =
	-   VAR n := MIN (a.n, b.n);
	BEGIN
	!     <*ASSERT n # 0*>
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       r.x[i] := Word.And (a.x[i], b.x[i]);
	END;
	END And;
	
	PROCEDURE Or (READONLY a, b: Int;  VAR r: Int) =
	-   VAR n := MIN (a.n, b.n);
	BEGIN
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       r.x[i] := Word.Or (a.x[i], b.x[i]);
	END;
	END Or;
	
	PROCEDURE Xor (READONLY a, b: Int;  VAR r: Int) =
	-   VAR n := MIN (a.n, b.n);
	BEGIN
	!     <*ASSERT n # 0*>
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       r.x[i] := Word.Xor (a.x[i], b.x[i]);
	END;
	END Xor;
	
	PROCEDURE Not (READONLY a: Int;  VAR r: Int) =
	-   VAR n := a.n;
	BEGIN
	!     <*ASSERT n # 0*>
	!     r.n := n;
	!     FOR i := 0 TO n-1 DO
	!       r.x[i] := Word.And (Word.Not (a.x[i]), Mask);
	END;
	END Not;
	
	! PROCEDURE LeftShift (READONLY a: Int;  b: CARDINAL;  VAR r: Int) =
	VAR w, i, j, z, x1, x2: INTEGER;
	-       n := a.n;  size := n * BITSIZE (IByte);
	BEGIN
	!     <*ASSERT n # 0*>
	!     IF b >= size THEN
	!       r := Int{n};
	!     ELSIF b = 0 THEN (* no shift *)
	r := a;
	ELSE
	w := b DIV BITSIZE (IByte);
	i := b MOD BITSIZE (IByte);
	j := BITSIZE (IByte) - i;
	!       FOR k := n-1 TO 0 BY -1 DO
	z := k - w;  x1 := 0;  x2 := 0;
	!         IF z   >= 0 THEN  x1 := LShift (a.x[z], i);   END;
	!         IF z-1 >= 0 THEN  x2 := RShift (a.x[z-1], j); END;
	!         r.x[k] := Word.And (Word.Or (x1, x2), Mask);
	END;
	-       r.n := a.n;
	END;
	END LeftShift;
	
	! PROCEDURE RightShift (READONLY a: Int;  b: CARDINAL;  VAR r: Int) =
	VAR w, i, j, z, x1, x2: INTEGER;
	-       n := a.n;  size := n * BITSIZE (IByte);
	BEGIN
	!     <*ASSERT n # 0*>
	!     IF b >= size THEN
	!       r := Int{n};
	!     ELSIF b = 0 THEN (* no shift *)
	r := a;
	ELSE
	w := b DIV BITSIZE (IByte);
	i := b MOD BITSIZE (IByte);
	j := BITSIZE (IByte) - i;
	!       FOR k := 0 TO n-1 DO
	z := k + w;  x1 := 0;  x2 := 0;
	!         IF z   <= n-1 THEN x1 := RShift (a.x[z], i);   END;
	!         IF z+1 <= n-1 THEN x2 := LShift (a.x[z+1], j); END;
	!         r.x[k] := Word.And (Word.Or (x1, x2), Mask);
	END;
	-       r.n := a.n;
	
	END;
	END RightShift;
	
	! PROCEDURE Shift (READONLY a: Int;  b: INTEGER;  VAR r: Int) =
	!   BEGIN
	!     IF b > 0 THEN (* left shift *)
	!       LeftShift(a, b, r);
	!     ELSE (* right shift *)
	!       RightShift(a, -b, r);
	!     END;
	!   END Shift;
	!
	! PROCEDURE Rotate (READONLY a: Int;  b: INTEGER;  VAR r: Int) =
	VAR
	w, i, j, z, x1, x2: INTEGER;
	!     tmp: IBytes;
	!     n := a.n;  size := n * BITSIZE (IByte);
	BEGIN
	-     <*ASSERT n # 0*>
	b := b MOD size;
	
	IF b = 0 THEN
	--- 233,338 ----
	END DivMod;
	
	PROCEDURE LT (READONLY a, b: Int): BOOLEAN =
	BEGIN
	!     FOR i := LAST(Int) TO 0 BY -1 DO
	!       IF    a [i] < b [i] THEN RETURN TRUE;
	!       ELSIF a [i] > b [i] THEN RETURN FALSE;
	END;
	END;
	RETURN FALSE;
	END LT;
	
	PROCEDURE LE (READONLY a, b: Int): BOOLEAN =
	BEGIN
	!     FOR i := LAST(Int) TO 0 BY -1 DO
	!       IF    a [i] < b [i] THEN RETURN TRUE;
	!       ELSIF a [i] > b [i] THEN RETURN FALSE;
	END;
	END;
	RETURN TRUE;
	END LE;
	
	PROCEDURE And (READONLY a, b: Int;  VAR r: Int) =
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       r [i] := Word.And (a [i], b[i]);
	END;
	END And;
	
	PROCEDURE Or (READONLY a, b: Int;  VAR r: Int) =
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       r [i] := Word.Or (a [i], b[i]);
	END;
	END Or;
	
	PROCEDURE Xor (READONLY a, b: Int;  VAR r: Int) =
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       r [i] := Word.Xor (a [i], b[i]);
	END;
	END Xor;
	
	PROCEDURE Not (READONLY a: Int;  VAR r: Int) =
	BEGIN
	!     FOR i := 0 TO LAST(Int) DO
	!       r [i] := Word.And (Word.Not (a [i]), Mask);
	END;
	END Not;
	
	! PROCEDURE Shift (READONLY a: Int;  b: INTEGER;  VAR r: Int) =
	!   BEGIN
	!     IF ABS (b) >= Size THEN
	!       r := TInt.Zero;
	!     ELSIF b > 0
	!       THEN LeftShift(a, b, r);
	!       ELSE RightShift(a, -b, r);
	!     END;
	!   END Shift;
	!
	! PROCEDURE LeftShift (READONLY a: Int;  b: [0..Size-1];  VAR r: Int) =
	VAR w, i, j, z, x1, x2: INTEGER;
	BEGIN
	!     IF b = 0 THEN (* no shift *)
	r := a;
	ELSE
	w := b DIV BITSIZE (IByte);
	i := b MOD BITSIZE (IByte);
	j := BITSIZE (IByte) - i;
	!       FOR k := LAST(Int) TO 0 BY -1 DO
	z := k - w;  x1 := 0;  x2 := 0;
	!         IF z   >= 0 THEN  x1 := LShift (a[z], i);   END;
	!         IF z-1 >= 0 THEN  x2 := RShift (a[z-1], j); END;
	!         r[k] := Word.And (Word.Or (x1, x2), Mask);
	END;
	END;
	END LeftShift;
	
	! PROCEDURE RightShift (READONLY a: Int;  b: [0..Size-1];  VAR r: Int) =
	VAR w, i, j, z, x1, x2: INTEGER;
	BEGIN
	!     IF b = 0 THEN (* no shift *)
	r := a;
	ELSE
	w := b DIV BITSIZE (IByte);
	i := b MOD BITSIZE (IByte);
	j := BITSIZE (IByte) - i;
	!       FOR k := 0 TO LAST(Int) DO
	z := k + w;  x1 := 0;  x2 := 0;
	!         IF z   <= LAST(Int) THEN x1 := RShift (a[z], i);   END;
	!         IF z+1 <= LAST(Int) THEN x2 := LShift (a[z+1], j); END;
	!         r[k] := Word.And (Word.Or (x1, x2), Mask);
	END;
	
	END;
	END RightShift;
	
	! PROCEDURE Rotate (READONLY a: Int;  b: INTEGER;  n: CARDINAL;  VAR r: Int) =
	VAR
	w, i, j, z, x1, x2: INTEGER;
	!     tmp: Int;
	!     size := n * BITSIZE (IByte);
	BEGIN
	b := b MOD size;
	
	IF b = 0 THEN
	***************
	*** 426,436 ****
	j := BITSIZE (IByte) - i;
	FOR k := 0 TO n-1 DO
	z := k - w;  x1 := 0;  x2 := 0;
	!         x1 := LShift (a.x[z MOD n], i);
	!         x2 := RShift (a.x[(z-1) MOD n], j);
	tmp[k] := Word.And (Word.Or (x1, x2), Mask);
	END;
	!       r := Int {a.n, tmp};
	
	ELSE (* right rotate *)
	w := (-b) DIV BITSIZE (IByte);
	--- 344,354 ----
	j := BITSIZE (IByte) - i;
	FOR k := 0 TO n-1 DO
	z := k - w;  x1 := 0;  x2 := 0;
	!         x1 := LShift (a[z MOD n], i);
	!         x2 := RShift (a[(z-1) MOD n], j);
	tmp[k] := Word.And (Word.Or (x1, x2), Mask);
	END;
	!       r := tmp;
	
	ELSE (* right rotate *)
	w := (-b) DIV BITSIZE (IByte);
	***************
	*** 438,485 ****
	j := BITSIZE (IByte) - i;
	FOR k := 0 TO n-1 DO
	z := k + w;  x1 := 0;  x2 := 0;
	!         x1 := RShift (a.x[z MOD n], i);
	!         x2 := LShift (a.x[(z+1) MOD n], j);
	tmp[k] := Word.And (Word.Or (x1, x2), Mask);
	END;
	!       r := Int {a.n, tmp};
	
	END;
	END Rotate;
	
	PROCEDURE Extract (READONLY x: Int;  i, n: CARDINAL;  VAR r: Int): BOOLEAN =
	VAR w, b: INTEGER;
	-       size := x.n * BITSIZE (IByte);
	BEGIN
	!     IF i + n > size THEN RETURN FALSE; END;
	
	!     RightShift (x, i, r);
	
	w := n DIV BITSIZE (IByte);
	b := n MOD BITSIZE (IByte);
	!     r.x[w] := Word.And (r.x[w], RShift (Mask, BITSIZE (IByte) - b));
	!     FOR k := w + 1 TO LAST (IBytes) DO r.x[k] := 0; END;
	
	RETURN TRUE;
	END Extract;
	
	PROCEDURE Insert (READONLY x, y: Int;  i, n: CARDINAL;  VAR r: Int): BOOLEAN =
	VAR yy, yyy, yyyy: Int;
	-       size := x.n * BITSIZE (IByte);
	BEGIN
	!     IF i + n > size THEN RETURN FALSE; END;
	
	!     RightShift (x, i + n, yy);
	!     LeftShift (yy, n, r);
	
	!     LeftShift (y, size - n, yy);
	!     RightShift (yy, size - n, yyy);
	Or (r, yyy, r);
	!     LeftShift (r, i, yyyy);
	r := yyyy;
	
	!     LeftShift (x, size - i, yy);
	!     RightShift (yy, size - i, yyy);
	Or (r, yyy, r);
	
	RETURN TRUE;
	--- 356,401 ----
	j := BITSIZE (IByte) - i;
	FOR k := 0 TO n-1 DO
	z := k + w;  x1 := 0;  x2 := 0;
	!         x1 := RShift (a[z MOD n], i);
	!         x2 := LShift (a[(z+1) MOD n], j);
	tmp[k] := Word.And (Word.Or (x1, x2), Mask);
	END;
	!       r := tmp;
	
	END;
	END Rotate;
	
	PROCEDURE Extract (READONLY x: Int;  i, n: CARDINAL;  VAR r: Int): BOOLEAN =
	VAR w, b: INTEGER;
	BEGIN
	!     IF i + n > Size THEN RETURN FALSE; END;
	
	!     Shift (x, -i, r);
	
	w := n DIV BITSIZE (IByte);
	b := n MOD BITSIZE (IByte);
	!     r[w] := Word.And (r[w], RShift (Mask, BITSIZE (IByte) - b));
	!     FOR k := w + 1 TO LAST(Int) DO r[k] := 0; END;
	
	RETURN TRUE;
	END Extract;
	
	PROCEDURE Insert (READONLY x, y: Int;  i, n: CARDINAL;  VAR r: Int): BOOLEAN =
	VAR yy, yyy, yyyy: Int;
	BEGIN
	!     IF i + n > Size THEN RETURN FALSE; END;
	
	!     Shift (x, -(i + n), yy);
	!     Shift (yy, n, r);
	
	!     Shift (y, Size - n, yy);
	!     Shift (yy, -(Size - n), yyy);
	Or (r, yyy, r);
	!     Shift (r, i, yyyy);
	r := yyyy;
	
	!     Shift (x, Size - i, yy);
	!     Shift (yy, -(Size - i), yyy);
	Or (r, yyy, r);
	
	RETURN TRUE;
	Index: m3middle/src/Target.i3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/Target.i3,v
	retrieving revision 1.49
	diff -c -r1.49 Target.i3
	*** m3middle/src/Target.i3	8 Feb 2010 16:00:54 -0000	1.49
	--- m3middle/src/Target.i3	18 Feb 2010 02:30:49 -0000
	***************
	*** 191,210 ****
	
	(*-------------------------------------------------------- integer values ---*)
	
	! (* The bits of a target INTEGER (in 2's complement) are stored in
	an array of small host values, with the low order bits in the first
	element of the array. *)
	
	TYPE
	!   Int = (* OPAQUE *) RECORD
	!     n: CARDINAL;          (* only bytes [0..n-1] contain valid bits *)
	!     x := IBytes{0,..};    (* default is Zero *)
	!   END;
	!   IBytes = ARRAY [0..7] OF IByte;
	IByte = BITS 8 FOR [0..16_ff];
	
	- PROCEDURE TargetIntToDiagnosticText(a: Int): TEXT;
	-
	TYPE
	Int_type = RECORD
	cg_type : CGType;    (* representation *)
	--- 191,204 ----
	
	(*-------------------------------------------------------- integer values ---*)
	
	! (* The bits of a target integer (in 2's complement) are stored in
	an array of small host values, with the low order bits in the first
	element of the array. *)
	
	TYPE
	!   Int = (* OPAQUE *) ARRAY [0..7] OF IByte;
	IByte = BITS 8 FOR [0..16_ff];
	
	TYPE
	Int_type = RECORD
	cg_type : CGType;    (* representation *)
	Index: m3middle/src/Target.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3middle/src/Target.m3,v
	retrieving revision 1.85
	diff -c -r1.85 Target.m3
	*** m3middle/src/Target.m3	8 Feb 2010 07:17:14 -0000	1.85
	--- m3middle/src/Target.m3	18 Feb 2010 02:30:49 -0000
	***************
	*** 8,33 ****
	
	MODULE Target;
	
	! IMPORT Text, TargetMap, M3RT, TextUtils, Fmt;
	
	VAR (*CONST*)
	CCs : REF ARRAY OF CallingConvention;
	
	- PROCEDURE TargetIntToDiagnosticText(a: Int): TEXT =
	-   VAR t: TEXT;
	-   BEGIN
	-     t := "n:";
	-     t := t & Fmt.Unsigned(a.n);
	-     t := t & ",x:";
	-     FOR i := 0 TO 7 DO
	-       t := t & Fmt.Unsigned(a.x[i]);
	-       IF i # 7 THEN
	-         t := t & ",";
	-       END;
	-     END;
	-     RETURN t;
	-   END TargetIntToDiagnosticText;
	-
	PROCEDURE Init64 () =
	BEGIN
	Integer := Int64;
	--- 8,18 ----
	
	MODULE Target;
	
	! IMPORT Text, TargetMap, M3RT, TextUtils;
	
	VAR (*CONST*)
	CCs : REF ARRAY OF CallingConvention;
	
	PROCEDURE Init64 () =
	BEGIN
	Integer := Int64;
	***************
	*** 82,131 ****
	Int8.cg_type     := CGType.Int8;
	Int8.size        := 8;
	Int8.align       := 8;
	!     Int8.min         := Int{NUMBER(IBytes), IBytes{16_80,FF,..}};
	!     Int8.max         := Int{NUMBER(IBytes), IBytes{16_7f,00,..}};
	
	Int16.cg_type    := CGType.Int16;
	Int16.size       := 16;
	Int16.align      := 16;
	!     Int16.min        := Int{NUMBER(IBytes), IBytes{00,16_80,FF,..}};
	!     Int16.max        := Int{NUMBER(IBytes), IBytes{FF,16_7f,00,..}};
	
	Int32.cg_type    := CGType.Int32;
	Int32.size       := 32;
	Int32.align      := 32;
	!     Int32.min        := Int{NUMBER(IBytes), IBytes{00,00,00,16_80,FF,..}};
	!     Int32.max        := Int{NUMBER(IBytes), IBytes{FF,FF,FF,16_7f,00,..}};
	
	Int64.cg_type    := CGType.Int64;
	Int64.size       := 64;
	Int64.align      := 64;
	!     Int64.min        := Int{NUMBER(IBytes), IBytes{00,00,00,00,00,00,00,16_80}};
	!     Int64.max        := Int{NUMBER(IBytes), IBytes{FF,FF,FF,FF,FF,FF,FF,16_7f}};
	
	Word8.cg_type    := CGType.Word8;
	Word8.size       := 8;
	Word8.align      := 8;
	!     Word8.min        := Int{NUMBER(IBytes), IBytes{00,00,..}};
	!     Word8.max        := Int{NUMBER(IBytes), IBytes{FF,00,..}};
	
	Word16.cg_type   := CGType.Word16;
	Word16.size      := 16;
	Word16.align     := 16;
	!     Word16.min       := Int{NUMBER(IBytes), IBytes{00,00,00,..}};
	!     Word16.max       := Int{NUMBER(IBytes), IBytes{FF,FF,00,..}};
	
	Word32.cg_type   := CGType.Word32;
	Word32.size      := 32;
	Word32.align     := 32;
	!     Word32.min       := Int{NUMBER(IBytes), IBytes{00,00,00,00,00,..}};
	!     Word32.max       := Int{NUMBER(IBytes), IBytes{FF,FF,FF,FF,00,..}};
	
	Word64.cg_type   := CGType.Word64;
	Word64.size      := 64;
	Word64.align     := 64;
	!     Word64.min       := Int{NUMBER(IBytes), IBytes{00,00,00,00,00,00,00,00}};
	!     Word64.max       := Int{NUMBER(IBytes), IBytes{FF,FF,FF,FF,FF,FF,FF,FF}};
	
	Integer          := Int32;  (* default for the 32-bit platforms *)
	Longint          := Int64;
	--- 67,116 ----
	Int8.cg_type     := CGType.Int8;
	Int8.size        := 8;
	Int8.align       := 8;
	!     Int8.min         := Int{16_80,FF,..};
	!     Int8.max         := Int{16_7f,00,..};
	
	Int16.cg_type    := CGType.Int16;
	Int16.size       := 16;
	Int16.align      := 16;
	!     Int16.min        := Int{00,16_80,FF,..};
	!     Int16.max        := Int{FF,16_7f,00,..};
	
	Int32.cg_type    := CGType.Int32;
	Int32.size       := 32;
	Int32.align      := 32;
	!     Int32.min        := Int{00,00,00,16_80,FF,..};
	!     Int32.max        := Int{FF,FF,FF,16_7f,00,..};
	
	Int64.cg_type    := CGType.Int64;
	Int64.size       := 64;
	Int64.align      := 64;
	!     Int64.min        := Int{00,00,00,00,00,00,00,16_80};
	!     Int64.max        := Int{FF,FF,FF,FF,FF,FF,FF,16_7f};
	
	Word8.cg_type    := CGType.Word8;
	Word8.size       := 8;
	Word8.align      := 8;
	!     Word8.min        := Int{00,00,..};
	!     Word8.max        := Int{FF,00,..};
	
	Word16.cg_type   := CGType.Word16;
	Word16.size      := 16;
	Word16.align     := 16;
	!     Word16.min       := Int{00,00,00,..};
	!     Word16.max       := Int{FF,FF,00,..};
	
	Word32.cg_type   := CGType.Word32;
	Word32.size      := 32;
	Word32.align     := 32;
	!     Word32.min       := Int{00,00,00,00,00,..};
	!     Word32.max       := Int{FF,FF,FF,FF,00,..};
	
	Word64.cg_type   := CGType.Word64;
	Word64.size      := 64;
	Word64.align     := 64;
	!     Word64.min       := Int{00,00,00,00,00,00,00,00};
	!     Word64.max       := Int{FF,FF,FF,FF,FF,FF,FF,FF};
	
	Integer          := Int32;  (* default for the 32-bit platforms *)
	Longint          := Int64;
	***************
	*** 137,144 ****
	Void.cg_type     := CGType.Void;
	Void.size        := 0;
	Void.align       := Byte;
	!     Void.min         := Int{0};
	!     Void.max         := Int{0};
	
	Real.cg_type     := CGType.Reel;
	Real.pre         := Precision.Short;
	--- 122,129 ----
	Void.cg_type     := CGType.Void;
	Void.size        := 0;
	Void.align       := Byte;
	!     Void.min         := Int{0,..};
	!     Void.max         := Int{0,..};
	
	Real.cg_type     := CGType.Reel;
	Real.pre         := Precision.Short;
	Index: m3back/src/Codex86.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3back/src/Codex86.m3,v
	retrieving revision 1.79
	diff -c -r1.79 Codex86.m3
	*** m3back/src/Codex86.m3	15 Feb 2010 17:48:57 -0000	1.79
	--- m3back/src/Codex86.m3	18 Feb 2010 02:30:50 -0000
	***************
	*** 9,15 ****
	MODULE Codex86;
	
	IMPORT Fmt, TargetMap, M3x86Rep, M3ID, M3CG_Ops, Word, M3ObjFile, Wrx86, Target;
	! IMPORT TInt, TWord;
	
	FROM TargetMap IMPORT CG_Bytes;
	
	--- 9,15 ----
	MODULE Codex86;
	
	IMPORT Fmt, TargetMap, M3x86Rep, M3ID, M3CG_Ops, Word, M3ObjFile, Wrx86, Target;
	! IMPORT TInt, TWord, Text;
	
	FROM TargetMap IMPORT CG_Bytes;
	
	***************
	*** 18,24 ****
	FROM M3CG_Ops IMPORT ErrorHandler;
	
	FROM M3x86Rep IMPORT Operand, MVar, Regno, OLoc, VLoc, x86Var, x86Proc, NRegs, OperandSize, GetOperandSize;
	! FROM M3x86Rep IMPORT RegistersForByteOperations, RegName, SplitOperand, Is64, SplitImm, OperandPart, GetTypeSize, TZero;
	FROM M3x86Rep IMPORT EAX, EDX, ESP, EBP, ECX;
	
	FROM M3ObjFile IMPORT Seg;
	--- 18,24 ----
	FROM M3CG_Ops IMPORT ErrorHandler;
	
	FROM M3x86Rep IMPORT Operand, MVar, Regno, OLoc, VLoc, x86Var, x86Proc, NRegs, OperandSize, GetOperandSize;
	! FROM M3x86Rep IMPORT RegistersForByteOperations, RegName, SplitOperand, Is64, SplitImm, OperandPart, GetTypeSize;
	FROM M3x86Rep IMPORT EAX, EDX, ESP, EBP, ECX;
	
	FROM M3ObjFile IMPORT Seg;
	***************
	*** 252,258 ****
	op.reg[0] IN RegistersForByteOperations ) OR
	(op.loc = OLoc.mem AND CG_Bytes[op.mvar.mvar_type] = 1) *>
	IF op.loc = OLoc.register THEN
	!       movImmT(t, op, TZero);
	END;
	build_modrm(t, op, t.opcode[0], ins);
	ins.escape := TRUE;
	--- 252,258 ----
	op.reg[0] IN RegistersForByteOperations ) OR
	(op.loc = OLoc.mem AND CG_Bytes[op.mvar.mvar_type] = 1) *>
	IF op.loc = OLoc.register THEN
	!       movImmT(t, op, TInt.Zero);
	END;
	build_modrm(t, op, t.opcode[0], ins);
	ins.escape := TRUE;
	***************
	*** 379,392 ****
	
	PROCEDURE immOp1 (t: T; op: Op; READONLY dest: Operand; READONLY imm: Target.Int) =
	VAR ins: Instruction;
	BEGIN
	<* ASSERT dest.loc = OLoc.register OR dest.loc = OLoc.mem *>
	
	!     IF (NOT TInt.ToInt(imm, ins.imm)) AND (NOT TWord.LE(imm, Target.Word32.max)) THEN
	!       t.Err("immOp1: unable to convert immediate to INTEGER:" & Target.TargetIntToDiagnosticText(imm));
	END;
	
	!     IF TInt.GE(imm, Target.Int8.min) AND TInt.LE(imm, Target.Int8.max) THEN
	ins.imsize := 1;
	ELSE
	ins.imsize := 4;
	--- 379,395 ----
	
	PROCEDURE immOp1 (t: T; op: Op; READONLY dest: Operand; READONLY imm: Target.Int) =
	VAR ins: Instruction;
	+       buf: ARRAY [0..BITSIZE(Target.Int)] OF CHAR;
	BEGIN
	<* ASSERT dest.loc = OLoc.register OR dest.loc = OLoc.mem *>
	
	!     IF (NOT TInt.ToInt(imm, ins.imm))
	!       AND (NOT TWord.LE(imm, Target.Word32.max)) THEN
	!       t.Err("immOp1: unable to convert immediate to INTEGER: " &
	!         Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(imm, buf))));
	END;
	
	!     IF TInt.LE(Target.Int8.min, imm) AND TInt.LE(imm, Target.Int8.max) THEN
	ins.imsize := 1;
	ELSE
	ins.imsize := 4;
	***************
	*** 465,473 ****
	t.set_label(compare_label);
	
	| Op.oSHL =>
	!             IF TInt.GE(imm, TInt.ThirtyTwo) THEN
	!               IF TInt.NE(imm, TInt.ThirtyTwo) THEN
	!                 EVAL TInt.Subtract(imm, TInt.ThirtyTwo, immMinus32);
	(* Ideally we'd do a virtual move in the register alloator. *)
	movOp1(t, destA[1], destA[0]);
	immOp1(t, op, destA[1], immMinus32);
	--- 468,476 ----
	t.set_label(compare_label);
	
	| Op.oSHL =>
	!             IF TInt.LE(Target.Int{32,0,..}, imm) THEN
	!               IF NOT TInt.EQ(imm, Target.Int{32,0,..}) THEN
	!                 EVAL TInt.Subtract(imm, Target.Int{32,0,..}, immMinus32);
	(* Ideally we'd do a virtual move in the register alloator. *)
	movOp1(t, destA[1], destA[0]);
	immOp1(t, op, destA[1], immMinus32);
	***************
	*** 482,490 ****
	END
	
	| Op.oSHR =>
	!             IF TInt.GE(imm, TInt.ThirtyTwo) THEN
	!               IF TInt.NE(imm, TInt.ThirtyTwo) THEN
	!                 EVAL TInt.Subtract(imm, TInt.ThirtyTwo, immMinus32);
	(* Ideally we'd do a virtual move in the register alloator. *)
	movOp1(t, destA[0], destA[1]);
	immOp1(t, op, destA[0], immMinus32);
	--- 485,493 ----
	END
	
	| Op.oSHR =>
	!             IF TInt.LE(Target.Int{32,0,..}, imm) THEN
	!               IF NOT TInt.EQ(imm, Target.Int{32,0,..}) THEN
	!                 EVAL TInt.Subtract(imm, Target.Int{32,0,..}, immMinus32);
	(* Ideally we'd do a virtual move in the register alloator. *)
	movOp1(t, destA[0], destA[1]);
	immOp1(t, op, destA[0], immMinus32);
	***************
	*** 513,518 ****
	--- 516,522 ----
	
	PROCEDURE binOp1WithShiftCount (t: T; op: Op; READONLY dest, src: Operand; READONLY shiftCount: Operand) =
	VAR ins: Instruction;
	+       buf: ARRAY [0..BITSIZE(Target.Int)] OF CHAR;
	BEGIN
	
	<* ASSERT NOT Is64(src.optype) *>
	***************
	*** 549,559 ****
	<* ASSERT src.loc = OLoc.register *>
	<* ASSERT shiftCount.loc = OLoc.register OR shiftCount.loc = OLoc.imm *>
	<* ASSERT shiftCount.loc # OLoc.register OR shiftCount.reg[0] = ECX *>
	!       <* ASSERT shiftCount.loc # OLoc.imm OR (TInt.GE(shiftCount.imm, Target.Int8.min) AND TInt.LE(shiftCount.imm, Target.Int8.max)) *>
	
	IF shiftCount.loc = OLoc.imm THEN
	IF NOT TInt.ToInt(shiftCount.imm, ins.imm) THEN
	!           t.Err("binOp: unable to convert immediate to INTEGER:" & Target.TargetIntToDiagnosticText(shiftCount.imm));
	END;
	ins.imsize := 1;
	ELSE
	--- 553,564 ----
	<* ASSERT src.loc = OLoc.register *>
	<* ASSERT shiftCount.loc = OLoc.register OR shiftCount.loc = OLoc.imm *>
	<* ASSERT shiftCount.loc # OLoc.register OR shiftCount.reg[0] = ECX *>
	!       <* ASSERT shiftCount.loc # OLoc.imm OR (TInt.LE(Target.Int8.min, shiftCount.imm) AND TInt.LE(shiftCount.imm, Target.Int8.max)) *>
	
	IF shiftCount.loc = OLoc.imm THEN
	IF NOT TInt.ToInt(shiftCount.imm, ins.imm) THEN
	!           t.Err("binOp: unable to convert immediate to INTEGER:" &
	!             Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(shiftCount.imm, buf))));
	END;
	ins.imsize := 1;
	ELSE
	***************
	*** 908,916 ****
	
	PROCEDURE movImmT (t: T; READONLY dest: Operand; imm: Target.Int) =
	VAR ins: Instruction;
	BEGIN
	!     IF (NOT TInt.ToInt(imm, ins.imm)) AND (NOT TWord.LE(imm, Target.Word32.max)) THEN
	!       t.Err("movImmT: unable to convert immediate to INTEGER:" & Target.TargetIntToDiagnosticText(imm));
	END;
	IF dest.loc # OLoc.register THEN
	<* ASSERT dest.loc = OLoc.mem *>
	--- 913,924 ----
	
	PROCEDURE movImmT (t: T; READONLY dest: Operand; imm: Target.Int) =
	VAR ins: Instruction;
	+       buf: ARRAY [0..BITSIZE(Target.Int)] OF CHAR;
	BEGIN
	!     IF (NOT TInt.ToInt(imm, ins.imm))
	!       AND (NOT TWord.LE(imm, Target.Word32.max)) THEN
	!       t.Err("movImmT: unable to convert immediate to INTEGER: " &
	!         Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(imm, buf))));
	END;
	IF dest.loc # OLoc.register THEN
	<* ASSERT dest.loc = OLoc.mem *>
	***************
	*** 921,927 ****
	ins.imsize := CG_Bytes[dest.mvar.mvar_type];
	writecode(t, ins);
	log_global_var(t, dest.mvar, -4 - CG_Bytes[dest.mvar.mvar_type]);
	!     ELSIF TInt.EQ(imm, TZero) THEN
	binOp(t, Op.oXOR, dest, dest);
	ELSE
	ins.opcode := 16_B8 + dest.reg[0];
	--- 929,935 ----
	ins.imsize := CG_Bytes[dest.mvar.mvar_type];
	writecode(t, ins);
	log_global_var(t, dest.mvar, -4 - CG_Bytes[dest.mvar.mvar_type]);
	!     ELSIF TInt.EQ(imm, TInt.Zero) THEN
	binOp(t, Op.oXOR, dest, dest);
	ELSE
	ins.opcode := 16_B8 + dest.reg[0];
	***************
	*** 934,940 ****
	PROCEDURE movImmI (t: T; READONLY dest: Operand; imm: INTEGER) =
	VAR immT: Target.Int;
	BEGIN
	!     IF NOT TInt.FromInt(imm, BYTESIZE(imm), immT) THEN
	t.Err("movImmI: unable to convert INTEGER to Target.Int");
	END;
	t.movImmT(dest, immT);
	--- 942,948 ----
	PROCEDURE movImmI (t: T; READONLY dest: Operand; imm: INTEGER) =
	VAR immT: Target.Int;
	BEGIN
	!     IF NOT TInt.FromInt(imm, immT) THEN
	t.Err("movImmI: unable to convert INTEGER to Target.Int");
	END;
	t.movImmT(dest, immT);
	***************
	*** 942,954 ****
	
	PROCEDURE pushOp1 (t: T; READONLY src: Operand) =
	VAR ins: Instruction;
	BEGIN
	Mn(t, "PUSH");  MnOp(t, src);
	CASE src.loc OF
	| OLoc.imm =>
	ins.opcode := 16_68;
	!         IF (NOT TInt.ToInt(src.imm, ins.imm)) AND (NOT TWord.LE(src.imm, Target.Word32.max)) THEN
	!           t.Err("pushOp: unable to convert immediate to INTEGER:" & Target.TargetIntToDiagnosticText(src.imm));
	END;
	ins.imsize := 4;
	writecode(t, ins);
	--- 950,966 ----
	
	PROCEDURE pushOp1 (t: T; READONLY src: Operand) =
	VAR ins: Instruction;
	+       buf: ARRAY [0..BITSIZE(Target.Int)] OF CHAR;
	BEGIN
	Mn(t, "PUSH");  MnOp(t, src);
	CASE src.loc OF
	| OLoc.imm =>
	ins.opcode := 16_68;
	!         IF (NOT TInt.ToInt(src.imm, ins.imm))
	!           AND (NOT TWord.LE(src.imm, Target.Word32.max))
	!         THEN
	!           t.Err("pushOp: unable to convert immediate to INTEGER: " &
	!             Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(src.imm, buf))));
	END;
	ins.imsize := 4;
	writecode(t, ins);
	***************
	*** 1073,1079 ****
	unOp1(t, op, destA[1]);
	| Op.oNEG =>
	unOp1(t, op, destA[0]);
	!             t.binOp(Op.oADC, destA[1], Operand {loc := OLoc.imm, imm := TZero, optype := Type.Word32});
	unOp1(t, op, destA[1]);
	ELSE
	<* ASSERT FALSE *>
	--- 1085,1091 ----
	unOp1(t, op, destA[1]);
	| Op.oNEG =>
	unOp1(t, op, destA[0]);
	!             t.binOp(Op.oADC, destA[1], Operand {loc := OLoc.imm, imm := TInt.Zero, optype := Type.Word32});
	unOp1(t, op, destA[1]);
	ELSE
	<* ASSERT FALSE *>
	***************
	*** 1104,1109 ****
	--- 1116,1122 ----
	
	PROCEDURE imulOp (t: T; READONLY dest, src: Operand) =
	VAR ins: Instruction;
	+       buf: ARRAY [0..BITSIZE(Target.Int)] OF CHAR;
	BEGIN
	<* ASSERT dest.loc = OLoc.register *>
	<* ASSERT src.loc # OLoc.mem OR CG_Bytes[src.mvar.mvar_type] = 4 *>
	***************
	*** 1111,1118 ****
	IF src.loc = OLoc.imm THEN
	build_modrm(t, t.reg[dest.reg[0]], dest, ins);
	ins.opcode := 16_69;
	!       IF (NOT TInt.ToInt(src.imm, ins.imm)) AND (NOT TWord.LE(src.imm, Target.Word32.max)) THEN
	!         t.Err("imulOp: unable to convert immediate to INTEGER:" & Target.TargetIntToDiagnosticText(src.imm));
	END;
	ins.imsize := 4;
	writecode(t, ins);
	--- 1124,1134 ----
	IF src.loc = OLoc.imm THEN
	build_modrm(t, t.reg[dest.reg[0]], dest, ins);
	ins.opcode := 16_69;
	!       IF (NOT TInt.ToInt(src.imm, ins.imm))
	!         AND (NOT TWord.LE(src.imm, Target.Word32.max))
	!       THEN
	!         t.Err("imulOp: unable to convert immediate to INTEGER: " &
	!           Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(src.imm, buf))));
	END;
	ins.imsize := 4;
	writecode(t, ins);
	***************
	*** 1195,1201 ****
	set_label(t, diffsignlab);                        (* .diffsignlab        *)
	noargOp(t, Op.oCDQ);                              (*   CDQ               *)
	idivOp(t, divisor);                               (*   IDIV EAX, divisor *)
	!     immOp(t, Op.oCMP, t.reg[EDX], TZero);             (*   CMP EDX, #0       *)
	brOp(t, Cond.E, endlab);                          (*   JE  endlab        *)
	decOp(t, t.reg[EAX]);                             (*   DEC EAX           *)
	set_label(t, endlab);                             (* .endlab             *)
	--- 1211,1217 ----
	set_label(t, diffsignlab);                        (* .diffsignlab        *)
	noargOp(t, Op.oCDQ);                              (*   CDQ               *)
	idivOp(t, divisor);                               (*   IDIV EAX, divisor *)
	!     immOp(t, Op.oCMP, t.reg[EDX], TInt.Zero);         (*   CMP EDX, #0       *)
	brOp(t, Cond.E, endlab);                          (*   JE  endlab        *)
	decOp(t, t.reg[EAX]);                             (*   DEC EAX           *)
	set_label(t, endlab);                             (* .endlab             *)
	***************
	*** 1221,1227 ****
	set_label(t, diffsignlab);                        (* .diffsignlab         *)
	noargOp(t, Op.oCDQ);                              (*    CDQ               *)
	idivOp(t, divisor);                               (*    IDIV EAX, divisor *)
	!     immOp(t, Op.oCMP, t.reg[EDX], TZero);             (*    CMP EDX, #0       *)
	brOp(t, Cond.E, endlab);                          (*    JE  endlab        *)
	binOp(t, Op.oADD, t.reg[EDX], divisor);           (*    ADD EDX, divisor  *)
	set_label(t, endlab);                             (* .endlab              *)
	--- 1237,1243 ----
	set_label(t, diffsignlab);                        (* .diffsignlab         *)
	noargOp(t, Op.oCDQ);                              (*    CDQ               *)
	idivOp(t, divisor);                               (*    IDIV EAX, divisor *)
	!     immOp(t, Op.oCMP, t.reg[EDX], TInt.Zero);         (*    CMP EDX, #0       *)
	brOp(t, Cond.E, endlab);                          (*    JE  endlab        *)
	binOp(t, Op.oADD, t.reg[EDX], divisor);           (*    ADD EDX, divisor  *)
	set_label(t, endlab);                             (* .endlab              *)
	***************
	*** 1479,1492 ****
	
	PROCEDURE store_ind1 (t: T; READONLY val, ind: Operand; offset: ByteOffset; type: MType) =
	VAR ins: Instruction;
	BEGIN
	<* ASSERT ind.loc = OLoc.register AND val.loc # OLoc.mem *>
	
	ins.opcode := 16_88;
	IF val.loc = OLoc.imm THEN
	ins.opcode := 16_C6;
	!       IF (NOT TInt.ToInt(val.imm, ins.imm)) AND (NOT TWord.LE(val.imm, Target.Word32.max)) THEN
	!         t.Err("store_ind1: unable to convert immediate to INTEGER:" & Target.TargetIntToDiagnosticText(val.imm));
	END;
	ins.imsize := CG_Bytes[type];
	END;
	--- 1495,1512 ----
	
	PROCEDURE store_ind1 (t: T; READONLY val, ind: Operand; offset: ByteOffset; type: MType) =
	VAR ins: Instruction;
	+       buf: ARRAY [0..BITSIZE(Target.Int)] OF CHAR;
	BEGIN
	<* ASSERT ind.loc = OLoc.register AND val.loc # OLoc.mem *>
	
	ins.opcode := 16_88;
	IF val.loc = OLoc.imm THEN
	ins.opcode := 16_C6;
	!       IF (NOT TInt.ToInt(val.imm, ins.imm))
	!         AND (NOT TWord.LE(val.imm, Target.Word32.max))
	!       THEN
	!         t.Err("store_ind1: unable to convert immediate to INTEGER: " &
	!           Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(val.imm, buf))));
	END;
	ins.imsize := CG_Bytes[type];
	END;
	***************
	*** 2324,2330 ****
	
	WHILE f_lit # NIL DO
	FOR i := 0 TO f_lit.flit_size - 1 DO
	!         EVAL TInt.FromInt(f_lit.arr[i], Target.Integer.bytes, tint);
	t.parent.init_int(f_lit.loc + i, tint, Type.Word8);
	END;
	
	--- 2344,2350 ----
	
	WHILE f_lit # NIL DO
	FOR i := 0 TO f_lit.flit_size - 1 DO
	!         EVAL TInt.FromInt(f_lit.arr[i], tint);
	t.parent.init_int(f_lit.loc + i, tint, Type.Word8);
	END;
	
	***************
	*** 2332,2338 ****
	END;
	
	WHILE abscall # NIL DO
	!       t.parent.init_int(abscall.loc, TZero, Type.Int32);
	t.obj.relocate(intvar.symbol, abscall.loc, abscall.sym);
	abscall := abscall.link;
	END;
	--- 2352,2358 ----
	END;
	
	WHILE abscall # NIL DO
	!       t.parent.init_int(abscall.loc, TInt.Zero, Type.Int32);
	t.obj.relocate(intvar.symbol, abscall.loc, abscall.sym);
	abscall := abscall.link;
	END;
	Index: m3back/src/M3x86.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3back/src/M3x86.m3,v
	retrieving revision 1.126
	diff -c -r1.126 M3x86.m3
	*** m3back/src/M3x86.m3	15 Feb 2010 17:58:21 -0000	1.126
	--- m3back/src/M3x86.m3	18 Feb 2010 02:30:50 -0000
	***************
	*** 1105,1117 ****
	pad_init(u, o);
	
	len := TInt.ToBytes(value, bytes);
	-     IF NOT (len <= NUMBER(bytes) AND len <= CG_Bytes[t] AND len > 0) THEN
	-       u.Err("init_int: len:" & Fmt.Int(len) & " type:" & Target.TypeNames[t] & " value:" & Target.TargetIntToDiagnosticText(value));
	-     END;
	<* ASSERT len > 0 *>
	<* ASSERT len <= NUMBER(bytes) *>
	<* ASSERT len <= CG_Bytes[t] *>
	!     IF TInt.LT(value, TZero) THEN
	FOR i := len TO CG_Bytes[t] - 1 DO
	bytes[i] := 16_FF;
	END;
	--- 1105,1114 ----
	pad_init(u, o);
	
	len := TInt.ToBytes(value, bytes);
	<* ASSERT len > 0 *>
	<* ASSERT len <= NUMBER(bytes) *>
	<* ASSERT len <= CG_Bytes[t] *>
	!     IF TInt.LT(value, TInt.Zero) THEN
	FOR i := len TO CG_Bytes[t] - 1 DO
	bytes[i] := 16_FF;
	END;
	***************
	*** 1506,1512 ****
	u.wr.NL    ();
	END;
	
	!     u.vstack.doimm (Op.oCMP, TZero, FALSE);
	u.cg.brOp (Cond.NZ, label);
	END if_true;
	
	--- 1503,1509 ----
	u.wr.NL    ();
	END;
	
	!     u.vstack.doimm (Op.oCMP, TInt.Zero, FALSE);
	u.cg.brOp (Cond.NZ, label);
	END if_true;
	
	***************
	*** 1520,1526 ****
	u.wr.NL    ();
	END;
	
	!     u.vstack.doimm (Op.oCMP, TZero, FALSE);
	u.cg.brOp (Cond.Z, label);
	END if_false;
	
	--- 1517,1523 ----
	u.wr.NL    ();
	END;
	
	!     u.vstack.doimm (Op.oCMP, TInt.Zero, FALSE);
	u.cg.brOp (Cond.Z, label);
	END if_false;
	
	***************
	*** 1802,1808 ****
	END;
	
	u.vstack.unlock();
	!     u.vstack.pushimmT(TZero, Type.Addr);
	END load_nil;
	
	PROCEDURE load_integer  (u: U;  t: IType;  READONLY i: Target.Int) =
	--- 1799,1805 ----
	END;
	
	u.vstack.unlock();
	!     u.vstack.pushimmT(TInt.Zero, Type.Addr);
	END load_nil;
	
	PROCEDURE load_integer  (u: U;  t: IType;  READONLY i: Target.Int) =
	***************
	*** 2166,2172 ****
	pop_param(u, Type.Addr);
	pop_param(u, Type.Addr);
	call_int_proc (u, proc);
	!       u.vstack.pushimmT(TZero, Type.Word32);
	condset(u, CompareOpCond [op], t);
	ELSE
	proc := CompareOpProc [op];
	--- 2163,2169 ----
	pop_param(u, Type.Addr);
	pop_param(u, Type.Addr);
	call_int_proc (u, proc);
	!       u.vstack.pushimmT(TInt.Zero, Type.Word32);
	condset(u, CompareOpCond [op], t);
	ELSE
	proc := CompareOpProc [op];
	***************
	*** 2323,2336 ****
	
	TWord.And(u.vstack.op(stack0).imm, MaximumShift[t], and);
	u.vstack.set_imm(stack0, and);
	!           IF TInt.NE(u.vstack.op(stack0).imm, TZero) THEN
	u.vstack.find(stack1, Force.anytemp);
	u.cg.immOp(Op.oSHL, u.vstack.op(stack1), u.vstack.op(stack0).imm);
	u.vstack.newdest(u.vstack.op(stack1));
	END
	END
	ELSE
	!         IF (u.vstack.loc(stack1) # OLoc.imm) OR TInt.NE(u.vstack.op(stack1).imm, TZero) THEN
	
	(* shift non-constant *)
	
	--- 2320,2333 ----
	
	TWord.And(u.vstack.op(stack0).imm, MaximumShift[t], and);
	u.vstack.set_imm(stack0, and);
	!           IF NOT TInt.EQ(u.vstack.op(stack0).imm, TInt.Zero) THEN
	u.vstack.find(stack1, Force.anytemp);
	u.cg.immOp(Op.oSHL, u.vstack.op(stack1), u.vstack.op(stack0).imm);
	u.vstack.newdest(u.vstack.op(stack1));
	END
	END
	ELSE
	!         IF (u.vstack.loc(stack1) # OLoc.imm) OR NOT TInt.EQ(u.vstack.op(stack1).imm, TInt.Zero) THEN
	
	(* shift non-constant *)
	
	***************
	*** 2385,2391 ****
	
	TWord.And(u.vstack.op(stack0).imm, MaximumShift[t], and);
	u.vstack.set_imm(stack0, and);
	!           IF TInt.NE(u.vstack.op(stack0).imm, TZero) THEN
	u.vstack.find(stack1, Force.anytemp);
	u.cg.immOp(Op.oSHR, u.vstack.op(stack1), u.vstack.op(stack0).imm);
	u.vstack.newdest(u.vstack.op(stack1));
	--- 2382,2388 ----
	
	TWord.And(u.vstack.op(stack0).imm, MaximumShift[t], and);
	u.vstack.set_imm(stack0, and);
	!           IF NOT TInt.EQ(u.vstack.op(stack0).imm, TInt.Zero) THEN
	u.vstack.find(stack1, Force.anytemp);
	u.cg.immOp(Op.oSHR, u.vstack.op(stack1), u.vstack.op(stack0).imm);
	u.vstack.newdest(u.vstack.op(stack1));
	***************
	*** 2395,2401 ****
	
	(* shift a non-constant or non-zero *)
	
	!         IF ((u.vstack.loc(stack1) # OLoc.imm) OR (TInt.NE(u.vstack.op(stack1).imm, TZero))) THEN
	IF Is64(t) THEN
	do_custom_calling_convention_shift_64 (u, Builtin.shift_right_64);
	RETURN;
	--- 2392,2398 ----
	
	(* shift a non-constant or non-zero *)
	
	!         IF ((u.vstack.loc(stack1) # OLoc.imm) OR (NOT TInt.EQ(u.vstack.op(stack1).imm, TInt.Zero))) THEN
	IF Is64(t) THEN
	do_custom_calling_convention_shift_64 (u, Builtin.shift_right_64);
	RETURN;
	***************
	*** 2452,2458 ****
	IF NOT TInt.ToInt(u.vstack.op(stack0).imm, rotateCount) THEN
	u.Err("unable to convert rotate count to host integer");
	END;
	!           TWord.Rotate(u.vstack.op(stack1).imm, rotateCount, rotate);
	u.vstack.set_imm(stack1, rotate);
	ELSE
	TWord.And(u.vstack.op(stack0).imm, MaximumShift[t], and);
	--- 2449,2456 ----
	IF NOT TInt.ToInt(u.vstack.op(stack0).imm, rotateCount) THEN
	u.Err("unable to convert rotate count to host integer");
	END;
	!           TWord.Rotate(u.vstack.op(stack1).imm, rotateCount,
	!                        Target.Integer.bytes, rotate);
	u.vstack.set_imm(stack1, rotate);
	ELSE
	TWord.And(u.vstack.op(stack0).imm, MaximumShift[t], and);
	***************
	*** 2505,2511 ****
	IF NOT TInt.ToInt(u.vstack.op(stack0).imm, rotateCount) THEN
	u.Err("unable to convert rotate count to host integer");
	END;
	!           TWord.Rotate(u.vstack.op(stack1).imm, -rotateCount, rotate);
	u.vstack.set_imm(stack1, rotate);
	ELSE
	TWord.And(u.vstack.op(stack0).imm, MaximumShift[t], and);
	--- 2503,2510 ----
	IF NOT TInt.ToInt(u.vstack.op(stack0).imm, rotateCount) THEN
	u.Err("unable to convert rotate count to host integer");
	END;
	!           TWord.Rotate(u.vstack.op(stack1).imm, -rotateCount,
	!                        Target.Integer.bytes, rotate);
	u.vstack.set_imm(stack1, rotate);
	ELSE
	TWord.And(u.vstack.op(stack0).imm, MaximumShift[t], and);
	***************
	*** 2749,2757 ****
	u.vstack.unlock();
	
	CASE CG_Bytes[t] OF
	!           2 => shift := TInt.One;
	!         | 4 => shift := TInt.Two;
	!         | 8 => shift := TInt.Three;
	ELSE
	u.Err("Unknown MType size in copy_n");
	END;
	--- 2748,2756 ----
	u.vstack.unlock();
	
	CASE CG_Bytes[t] OF
	!           2 => shift := Target.Int{1,0,..};
	!         | 4 => shift := Target.Int{2,0,..};
	!         | 8 => shift := Target.Int{3,0,..};
	ELSE
	u.Err("Unknown MType size in copy_n");
	END;
	***************
	*** 2806,2815 ****
	IF forward THEN
	u.cg.noargOp(Op.oCLD);
	ELSE
	!       IF NOT TInt.FromInt(n, Target.Integer.bytes, tn) THEN
	u.Err("string_copy: unable to convert n to target int");
	END;
	!       IF NOT TInt.FromInt(size, Target.Integer.bytes, tsize) THEN
	u.Err("string_copy: unable to convert size to target int");
	END;
	IF NOT TInt.Subtract(tn, TInt.One, tNMinus1) THEN
	--- 2805,2814 ----
	IF forward THEN
	u.cg.noargOp(Op.oCLD);
	ELSE
	!       IF NOT TInt.FromInt(n, tn) THEN
	u.Err("string_copy: unable to convert n to target int");
	END;
	!       IF NOT TInt.FromInt(size, tsize) THEN
	u.Err("string_copy: unable to convert size to target int");
	END;
	IF NOT TInt.Subtract(tn, TInt.One, tNMinus1) THEN
	***************
	*** 2940,2948 ****
	u.vstack.find(stack0, Force.anyreg);
	
	CASE CG_Bytes[t] OF
	!           2 => shift := TInt.One;
	!         | 4 => shift := TInt.Two;
	!         | 8 => shift := TInt.Three;
	ELSE
	u.Err("Unknown MType size in zero_n");
	END;
	--- 2939,2947 ----
	u.vstack.find(stack0, Force.anyreg);
	
	CASE CG_Bytes[t] OF
	!           2 => shift := Target.Int{1,0,..};
	!         | 4 => shift := Target.Int{2,0,..};
	!         | 8 => shift := Target.Int{3,0,..};
	ELSE
	u.Err("Unknown MType size in zero_n");
	END;
	***************
	*** 2953,2959 ****
	
	start_int_proc (u, Builtin.memset);
	pop_param (u, z);
	!     u.vstack.pushimmT (TZero, Type.Word32);
	pop_param (u, Type.Word32);
	pop_param (u, Type.Addr);
	call_int_proc (u, Builtin.memset);
	--- 2952,2958 ----
	
	start_int_proc (u, Builtin.memset);
	pop_param (u, z);
	!     u.vstack.pushimmT (TInt.Zero, Type.Word32);
	pop_param (u, Type.Word32);
	pop_param (u, Type.Addr);
	call_int_proc (u, Builtin.memset);
	***************
	*** 3013,3019 ****
	stop0 = u.vstack.op(stack0) DO
	u.vstack.find(stack0, Force.anyreg, RegSet {}, TRUE);
	FOR i := 0 TO n - 1 DO
	!           u.cg.store_ind(Operand { loc := OLoc.imm, imm := TZero, optype := t },
	stop0, i * size, faketype[size]);
	END
	END
	--- 3012,3018 ----
	stop0 = u.vstack.op(stack0) DO
	u.vstack.find(stack0, Force.anyreg, RegSet {}, TRUE);
	FOR i := 0 TO n - 1 DO
	!           u.cg.store_ind(Operand { loc := OLoc.imm, imm := TInt.Zero, optype := t },
	stop0, i * size, faketype[size]);
	END
	END
	***************
	*** 3155,3168 ****
	u.vstack.unlock();
	WITH stack0 = u.vstack.pos(0, "check_nil") DO
	IF u.vstack.loc(stack0) = OLoc.imm THEN
	!         IF TInt.EQ(u.vstack.op(stack0).imm, TZero) THEN
	reportfault(u, code);
	END
	ELSE
	u.vstack.find(stack0, Force.anyreg, RegSet {}, TRUE);
	
	IF NOT u.vstack.non_nil(u.vstack.reg(stack0)) THEN
	!           u.cg.immOp(Op.oCMP, u.vstack.op(stack0), TZero);
	safelab := u.cg.reserve_labels(1, TRUE);
	u.cg.brOp(Cond.NE, safelab);
	reportfault(u, code);
	--- 3154,3167 ----
	u.vstack.unlock();
	WITH stack0 = u.vstack.pos(0, "check_nil") DO
	IF u.vstack.loc(stack0) = OLoc.imm THEN
	!         IF TInt.EQ(u.vstack.op(stack0).imm, TInt.Zero) THEN
	reportfault(u, code);
	END
	ELSE
	u.vstack.find(stack0, Force.anyreg, RegSet {}, TRUE);
	
	IF NOT u.vstack.non_nil(u.vstack.reg(stack0)) THEN
	!           u.cg.immOp(Op.oCMP, u.vstack.op(stack0), TInt.Zero);
	safelab := u.cg.reserve_labels(1, TRUE);
	u.cg.brOp(Cond.NE, safelab);
	reportfault(u, code);
	***************
	*** 3194,3200 ****
	END
	ELSE
	u.vstack.find(stack0, Force.anyreg);
	!         IF TInt.GE(u.vstack.lower(u.vstack.reg(stack0)), i) THEN
	(* ok *)
	ELSIF TInt.LT(u.vstack.upper(u.vstack.reg(stack0)), i) THEN
	reportfault(u, code);
	--- 3193,3199 ----
	END
	ELSE
	u.vstack.find(stack0, Force.anyreg);
	!         IF TInt.LE(i, u.vstack.lower(u.vstack.reg(stack0))) THEN
	(* ok *)
	ELSIF TInt.LT(u.vstack.upper(u.vstack.reg(stack0)), i) THEN
	reportfault(u, code);
	***************
	*** 3232,3238 ****
	u.vstack.find(stack0, Force.anyreg);
	IF TInt.LE(u.vstack.upper(u.vstack.reg(stack0)), i) THEN
	(* ok *)
	!         ELSIF TInt.GT(u.vstack.lower(u.vstack.reg(stack0)), i) THEN
	reportfault(u, code);
	ELSE
	u.cg.immOp(Op.oCMP, u.vstack.op(stack0), i);
	--- 3231,3237 ----
	u.vstack.find(stack0, Force.anyreg);
	IF TInt.LE(u.vstack.upper(u.vstack.reg(stack0)), i) THEN
	(* ok *)
	!         ELSIF TInt.LT(i, u.vstack.lower(u.vstack.reg(stack0))) THEN
	reportfault(u, code);
	ELSE
	u.cg.immOp(Op.oCMP, u.vstack.op(stack0), i);
	***************
	*** 3279,3287 ****
	reportfault(u, code);
	ELSIF TInt.LE(hi, b) THEN
	check_lo(u, t, a, code);
	!         ELSIF TInt.GE(lo, a) THEN
	check_hi(u, t, b, code);
	!         ELSIF TInt.EQ(a, TZero) THEN
	(* 0 <= x <= b  ==>   UNSIGNED(x) <= b *)
	safelab := u.cg.reserve_labels(1, TRUE);
	u.cg.immOp(Op.oCMP, u.vstack.op(stack0), b);
	--- 3278,3286 ----
	reportfault(u, code);
	ELSIF TInt.LE(hi, b) THEN
	check_lo(u, t, a, code);
	!         ELSIF TInt.LE(a, lo) THEN
	check_hi(u, t, b, code);
	!         ELSIF TInt.EQ(a, TInt.Zero) THEN
	(* 0 <= x <= b  ==>   UNSIGNED(x) <= b *)
	safelab := u.cg.reserve_labels(1, TRUE);
	u.cg.immOp(Op.oCMP, u.vstack.op(stack0), b);
	***************
	*** 3457,3463 ****
	u.wr.NL    ();
	END;
	
	!     IF NOT TInt.FromInt(i, Target.Integer.bytes, ti) THEN
	u.Err("add_offset: failed to convert i to target integer");
	END;
	
	--- 3456,3462 ----
	u.wr.NL    ();
	END;
	
	!     IF NOT TInt.FromInt(i, ti) THEN
	u.Err("add_offset: failed to convert i to target integer");
	END;
	
	***************
	*** 3642,3650 ****
	IF Target.FloatType [t] THEN
	<* ASSERT depth = 0 *>
	IF t = Type.Reel THEN
	!           u.cg.immOp(Op.oSUB, u.cg.reg[ESP], TInt.Four);
	ELSE
	!           u.cg.immOp(Op.oSUB, u.cg.reg[ESP], TInt.Eight);
	END;
	u.cg.f_storeind(u.cg.reg[ESP], 0, t);
	ELSE
	--- 3641,3649 ----
	IF Target.FloatType [t] THEN
	<* ASSERT depth = 0 *>
	IF t = Type.Reel THEN
	!           u.cg.immOp(Op.oSUB, u.cg.reg[ESP], Target.Int{4,0,..});
	ELSE
	!           u.cg.immOp(Op.oSUB, u.cg.reg[ESP], Target.Int{8,0,..});
	END;
	u.cg.f_storeind(u.cg.reg[ESP], 0, t);
	ELSE
	***************
	*** 3694,3706 ****
	
	WITH stack0 = u.vstack.pos(0, "pop_struct") DO
	
	!       IF NOT TInt.FromInt(s, Target.Integer.bytes, ts) THEN
	u.Err("pop_struct: unable to convert s to target int");
	END;
	
	(* if the struct is "large", use rep mov to copy it to the machine stack *)
	
	!       IF TInt.GT(ts, TInt.ThirtyTwo) THEN
	u.cg.immOp(Op.oSUB, u.cg.reg[ESP], ts);
	
	u.vstack.find(stack0, Force.regset, RegSet { ESI });
	--- 3693,3705 ----
	
	WITH stack0 = u.vstack.pos(0, "pop_struct") DO
	
	!       IF NOT TInt.FromInt(s, ts) THEN
	u.Err("pop_struct: unable to convert s to target int");
	END;
	
	(* if the struct is "large", use rep mov to copy it to the machine stack *)
	
	!       IF TInt.LT(Target.Int{32,0,..}, ts) THEN
	u.cg.immOp(Op.oSUB, u.cg.reg[ESP], ts);
	
	u.vstack.find(stack0, Force.regset, RegSet { ESI });
	***************
	*** 3880,3886 ****
	IF (NOT realproc.stdcall) (* => caller cleans *)
	AND u.call_param_size[u.in_proc_call - 1] > 0 THEN
	
	!         IF NOT TInt.FromInt(u.call_param_size[u.in_proc_call - 1], Target.Integer.bytes, call_param_size) THEN
	u.Err("call_direct: unable to convert param_size to target integer");
	END;
	u.cg.immOp(Op.oADD, u.cg.reg[ESP], call_param_size);
	--- 3879,3885 ----
	IF (NOT realproc.stdcall) (* => caller cleans *)
	AND u.call_param_size[u.in_proc_call - 1] > 0 THEN
	
	!         IF NOT TInt.FromInt(u.call_param_size[u.in_proc_call - 1], call_param_size) THEN
	u.Err("call_direct: unable to convert param_size to target integer");
	END;
	u.cg.immOp(Op.oADD, u.cg.reg[ESP], call_param_size);
	***************
	*** 3939,3945 ****
	
	(* caller-cleans calling convention *)
	
	!       IF NOT TInt.FromInt(u.call_param_size[u.in_proc_call - 1], Target.Integer.bytes, call_param_size) THEN
	u.Err("call_indirect: unable to convert param_size to target integer");
	END;
	
	--- 3938,3944 ----
	
	(* caller-cleans calling convention *)
	
	!       IF NOT TInt.FromInt(u.call_param_size[u.in_proc_call - 1], call_param_size) THEN
	u.Err("call_indirect: unable to convert param_size to target integer");
	END;
	
	***************
	*** 4027,4033 ****
	u.vstack.unlock();
	
	IF realproc.lev = 0 THEN
	!       u.vstack.pushimmT(TZero, Type.Word32);
	ELSE
	u.vstack.pushnew(Type.Addr, Force.anyreg);
	u.cg.get_frame(u.vstack.op(u.vstack.pos(0, "load_static_link")).reg[0],
	--- 4026,4032 ----
	u.vstack.unlock();
	
	IF realproc.lev = 0 THEN
	!       u.vstack.pushimmT(TInt.Zero, Type.Word32);
	ELSE
	u.vstack.pushnew(Type.Addr, Force.anyreg);
	u.cg.get_frame(u.vstack.op(u.vstack.pos(0, "load_static_link")).reg[0],
	***************
	*** 4047,4053 ****
	
	IF realproc.lev = 0 THEN
	u.vstack.corrupt(ECX, operandPart := 0);
	!       u.cg.movImmT(u.cg.reg[ECX], TZero);
	ELSE
	u.vstack.unlock();
	u.vstack.corrupt(ECX, operandPart := 0);
	--- 4046,4052 ----
	
	IF realproc.lev = 0 THEN
	u.vstack.corrupt(ECX, operandPart := 0);
	!       u.cg.movImmT(u.cg.reg[ECX], TInt.Zero);
	ELSE
	u.vstack.unlock();
	u.vstack.corrupt(ECX, operandPart := 0);
	***************
	*** 4060,4066 ****
	PROCEDURE intregcmp (u: U; tozero: BOOLEAN; type: Type): BOOLEAN =
	BEGIN
	IF tozero THEN
	!       u.vstack.doimm(Op.oCMP, TZero, FALSE);
	RETURN FALSE;
	ELSE
	RETURN u.vstack.dobin(Op.oCMP, TRUE, FALSE, type);
	--- 4059,4065 ----
	PROCEDURE intregcmp (u: U; tozero: BOOLEAN; type: Type): BOOLEAN =
	BEGIN
	IF tozero THEN
	!       u.vstack.doimm(Op.oCMP, TInt.Zero, FALSE);
	RETURN FALSE;
	ELSE
	RETURN u.vstack.dobin(Op.oCMP, TRUE, FALSE, type);
	Index: m3back/src/M3x86Rep.i3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3back/src/M3x86Rep.i3,v
	retrieving revision 1.28
	diff -c -r1.28 M3x86Rep.i3
	*** m3back/src/M3x86Rep.i3	14 Feb 2010 08:35:08 -0000	1.28
	--- m3back/src/M3x86Rep.i3	18 Feb 2010 02:30:50 -0000
	***************
	*** 146,161 ****
	PROCEDURE GetOperandSize(READONLY op: Operand): OperandSize;
	PROCEDURE GetTypeSize(type: Type): OperandSize;
	
	! CONST TZero = TInt.Zero;
	
	! CONST UnsignedType = ARRAY IType OF IType { Type.Word32, Type.Word32,
	!                                             Type.Word64, Type.Word64 };
	
	! CONST MaximumShift = ARRAY IType OF Target.Int { TInt.ThirtyOne, TInt.ThirtyOne,
	!                                                  TInt.SixtyThree, TInt.SixtyThree };
	!
	! CONST MinimumShift = ARRAY IType OF Target.Int { TInt.MThirtyOne, TInt.MThirtyOne,
	!                                                  TInt.MSixtyThree, TInt.MSixtyThree };
	
	CONST BitCountMask = MaximumShift;
	
	--- 146,162 ----
	PROCEDURE GetOperandSize(READONLY op: Operand): OperandSize;
	PROCEDURE GetTypeSize(type: Type): OperandSize;
	
	! CONST UnsignedType = ARRAY IType OF IType {
	!   Type.Word32, Type.Word32,
	!   Type.Word64, Type.Word64 };
	
	! CONST MaximumShift = ARRAY IType OF Target.Int {
	!   Target.Int{31,0,..}, Target.Int{31,0,..},
	!   Target.Int{63,0,..}, Target.Int{63,0,..}};
	
	! CONST MinimumShift = ARRAY IType OF Target.Int {
	!   Target.Int{31,0,..}, Target.Int{31,0,..},
	!   Target.Int{63,0,..}, Target.Int{63,0,..}};
	
	CONST BitCountMask = MaximumShift;
	
	Index: m3back/src/Stackx86.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3back/src/Stackx86.m3,v
	retrieving revision 1.93
	diff -c -r1.93 Stackx86.m3
	*** m3back/src/Stackx86.m3	14 Feb 2010 13:23:42 -0000	1.93
	--- m3back/src/Stackx86.m3	18 Feb 2010 02:30:51 -0000
	***************
	*** 16,22 ****
	FROM M3CG IMPORT Type, MType, ZType, IType, Sign, Label, ByteOffset;
	FROM M3CG_Ops IMPORT ErrorHandler;
	
	! FROM M3x86Rep IMPORT Operand, MVar, Regno, OLoc, VLoc, NRegs, Force, Is64, OperandPart, RegName, OperandSize, TZero;
	FROM M3x86Rep IMPORT RegistersForByteOperations, RegSet, FlToInt, x86Var, x86Proc, NoStore, SplitOperand, SplitMVar, GetTypeSize, GetOperandSize;
	FROM M3x86Rep IMPORT IsInt, IsWord, EAX, ECX, EDX, EBX, ESI, EDI, UnsignedType, MaximumShift, MinimumShift, BitCountMask, IntType;
	
	--- 16,22 ----
	FROM M3CG IMPORT Type, MType, ZType, IType, Sign, Label, ByteOffset;
	FROM M3CG_Ops IMPORT ErrorHandler;
	
	! FROM M3x86Rep IMPORT Operand, MVar, Regno, OLoc, VLoc, NRegs, Force, Is64, OperandPart, RegName, OperandSize;
	FROM M3x86Rep IMPORT RegistersForByteOperations, RegSet, FlToInt, x86Var, x86Proc, NoStore, SplitOperand, SplitMVar, GetTypeSize, GetOperandSize;
	FROM M3x86Rep IMPORT IsInt, IsWord, EAX, ECX, EDX, EBX, ESI, EDI, UnsignedType, MaximumShift, MinimumShift, BitCountMask, IntType;
	
	***************
	*** 101,107 ****
	Register = RECORD
	stackp     : INTEGER := -1;
	last_store : MVar    := NoStore;
	!     last_imm   : Target.Int := TZero;
	lowbound   : Target.Int;
	upbound    : Target.Int;
	imm        : BOOLEAN := FALSE;
	--- 101,107 ----
	Register = RECORD
	stackp     : INTEGER := -1;
	last_store : MVar    := NoStore;
	!     last_imm   : Target.Int := TInt.Zero;
	lowbound   : Target.Int;
	upbound    : Target.Int;
	imm        : BOOLEAN := FALSE;
	***************
	*** 780,786 ****
	PROCEDURE pushimmI (t: T; immI: INTEGER; type: Type) =
	VAR immT: Target.Int;
	BEGIN
	!     IF NOT TInt.FromInt(immI, Target.Integer.bytes, immT) THEN
	t.Err("pushimmI: unable to convert to target integer");
	END;
	t.pushimmT(immT, type);
	--- 780,786 ----
	PROCEDURE pushimmI (t: T; immI: INTEGER; type: Type) =
	VAR immT: Target.Int;
	BEGIN
	!     IF NOT TInt.FromInt(immI, immT) THEN
	t.Err("pushimmI: unable to convert to target integer");
	END;
	t.pushimmT(immT, type);
	***************
	*** 974,983 ****
	WITH stop0 = t.vstack[pos(t, 0, "doloadaddress")] DO
	IF v.loc = VLoc.temp AND v.parent # t.current_proc THEN
	t.cg.get_frame(stop0.reg[0], v.parent, t.current_proc);
	!         IF NOT TInt.FromInt(o, Target.Integer.bytes, to) THEN
	t.Err("doloadaddress: unable to convert o");
	END;
	!         IF NOT TInt.FromInt(v.offset, Target.Integer.bytes, tvoffset) THEN
	t.Err("doloadaddress: unable to convert v.offset");
	END;
	IF NOT TInt.Add(to, tvoffset, ti) THEN
	--- 974,983 ----
	WITH stop0 = t.vstack[pos(t, 0, "doloadaddress")] DO
	IF v.loc = VLoc.temp AND v.parent # t.current_proc THEN
	t.cg.get_frame(stop0.reg[0], v.parent, t.current_proc);
	!         IF NOT TInt.FromInt(o, to) THEN
	t.Err("doloadaddress: unable to convert o");
	END;
	!         IF NOT TInt.FromInt(v.offset, tvoffset) THEN
	t.Err("doloadaddress: unable to convert v.offset");
	END;
	IF NOT TInt.Add(to, tvoffset, ti) THEN
	***************
	*** 1234,1240 ****
	
	IF (a = Sign.Positive AND b = Sign.Negative) OR
	(a = Sign.Negative AND b = Sign.Positive) THEN
	!           t.cg.immOp(Op.oCMP, t.cg.reg[EDX], TZero);
	
	neglabel := t.cg.reserve_labels(1, TRUE);
	
	--- 1234,1240 ----
	
	IF (a = Sign.Positive AND b = Sign.Negative) OR
	(a = Sign.Negative AND b = Sign.Positive) THEN
	!           t.cg.immOp(Op.oCMP, t.cg.reg[EDX], TInt.Zero);
	
	neglabel := t.cg.reserve_labels(1, TRUE);
	
	***************
	*** 1294,1300 ****
	
	IF (a = Sign.Positive AND b = Sign.Negative) OR
	(a = Sign.Negative AND b = Sign.Positive) THEN
	!           t.cg.immOp(Op.oCMP, t.cg.reg[EDX], TZero);
	
	neglabel := t.cg.reserve_labels(1, TRUE);
	
	--- 1294,1300 ----
	
	IF (a = Sign.Positive AND b = Sign.Negative) OR
	(a = Sign.Negative AND b = Sign.Positive) THEN
	!           t.cg.immOp(Op.oCMP, t.cg.reg[EDX], TInt.Zero);
	
	neglabel := t.cg.reserve_labels(1, TRUE);
	
	***************
	*** 1323,1329 ****
	IF (stop0.loc = OLoc.mem AND
	((overwritesdest AND NOT stop0.mvar.var.stack_temp) OR
	CG_Bytes[stop0.mvar.mvar_type] = 2 OR
	!           (CG_Bytes[stop0.mvar.mvar_type] = 1 AND (TInt.GT(imm, Target.Int8.max) OR TInt.LT(imm, Target.Int8.min)))))
	OR stop0.loc = OLoc.imm THEN
	find(t, stack0, Force.anyreg);
	ELSE
	--- 1323,1329 ----
	IF (stop0.loc = OLoc.mem AND
	((overwritesdest AND NOT stop0.mvar.var.stack_temp) OR
	CG_Bytes[stop0.mvar.mvar_type] = 2 OR
	!           (CG_Bytes[stop0.mvar.mvar_type] = 1 AND (TInt.LT(Target.Int8.max, imm) OR TInt.LT(imm, Target.Int8.min)))))
	OR stop0.loc = OLoc.imm THEN
	find(t, stack0, Force.anyreg);
	ELSE
	***************
	*** 1347,1353 ****
	WITH stack0 = pos(t, 0, "doneg"),
	stop0 = t.vstack[stack0] DO
	IF stop0.loc = OLoc.imm THEN
	!         IF NOT TInt.Negate(stop0.imm, neg) THEN
	t.Err("doneg: Negate overflowed");
	END;
	stop0.imm := neg;
	--- 1347,1353 ----
	WITH stack0 = pos(t, 0, "doneg"),
	stop0 = t.vstack[stack0] DO
	IF stop0.loc = OLoc.imm THEN
	!         IF NOT TInt.Subtract(TInt.Zero, stop0.imm, neg) THEN
	t.Err("doneg: Negate overflowed");
	END;
	stop0.imm := neg;
	***************
	*** 1367,1380 ****
	WITH stack0 = pos(t, 0, "doabs"),
	stop0 = t.vstack[stack0] DO
	IF stop0.loc = OLoc.imm THEN
	!         IF NOT TInt.Abs(stop0.imm, stop0.imm) THEN
	!           t.Err("doabs: Abs overflowed");
	END;
	ELSE
	find(t, stack0, Force.anytemp);
	
	IF (stop0.loc = OLoc.mem) OR (GetOperandSize(stop0) > 1) THEN
	!           t.cg.immOp(Op.oCMP, stop0, TZero);
	
	lab := t.cg.reserve_labels(1, TRUE);
	
	--- 1367,1382 ----
	WITH stack0 = pos(t, 0, "doabs"),
	stop0 = t.vstack[stack0] DO
	IF stop0.loc = OLoc.imm THEN
	!         IF TInt.LT (stop0.imm, TInt.Zero) THEN
	!           IF NOT TInt.Subtract (TInt.Zero, stop0.imm, stop0.imm) THEN
	!             t.Err("doabs: Abs overflowed");
	!           END;
	END;
	ELSE
	find(t, stack0, Force.anytemp);
	
	IF (stop0.loc = OLoc.mem) OR (GetOperandSize(stop0) > 1) THEN
	!           t.cg.immOp(Op.oCMP, stop0, TInt.Zero);
	
	lab := t.cg.reserve_labels(1, TRUE);
	
	***************
	*** 1426,1452 ****
	
	(* shift non-constant by a constant *)
	
	!           IF TInt.NE(stop0.imm, TZero) THEN
	
	(* shift non-constant by a non-zero constant *)
	
	find(t, stack1, Force.anytemp);
	
	!             IF     TInt.GT(stop0.imm, MaximumShift[type])
	OR TInt.LT(stop0.imm, MinimumShift[type]) THEN
	
	(* shifting "too far" just yields zero *)
	
	t.cg.binOp(Op.oXOR, stop1, stop1);
	
	!             ELSIF TInt.GT(stop0.imm, TZero) THEN
	
	(* positive shift is left shift *)
	
	t.cg.immOp(Op.oSHL, stop1, stop0.imm);
	
	ELSE
	!               IF NOT TInt.Negate(stop0.imm, tShiftCount) THEN
	t.Err("doshift: Negate overflowed");
	END;
	
	--- 1428,1454 ----
	
	(* shift non-constant by a constant *)
	
	!           IF NOT TInt.EQ(stop0.imm, TInt.Zero) THEN
	
	(* shift non-constant by a non-zero constant *)
	
	find(t, stack1, Force.anytemp);
	
	!             IF     TInt.LT(MaximumShift[type], stop0.imm)
	OR TInt.LT(stop0.imm, MinimumShift[type]) THEN
	
	(* shifting "too far" just yields zero *)
	
	t.cg.binOp(Op.oXOR, stop1, stop1);
	
	!             ELSIF TInt.LT(TInt.Zero, stop0.imm) THEN
	
	(* positive shift is left shift *)
	
	t.cg.immOp(Op.oSHL, stop1, stop0.imm);
	
	ELSE
	!               IF NOT TInt.Subtract(TInt.Zero, stop0.imm, tShiftCount) THEN
	t.Err("doshift: Negate overflowed");
	END;
	
	***************
	*** 1461,1467 ****
	END
	ELSE
	
	!         IF ((stop1.loc # OLoc.imm) OR (TInt.NE(stop1.imm, TZero))) THEN
	
	(* shift by a non-constant *)
	
	--- 1463,1469 ----
	END
	ELSE
	
	!         IF ((stop1.loc # OLoc.imm) OR (NOT TInt.EQ(stop1.imm, TInt.Zero))) THEN
	
	(* shift by a non-constant *)
	
	***************
	*** 1476,1482 ****
	find(t, stack1, Force.anyreg);
	END;
	
	!           t.cg.immOp(Op.oCMP, stop0, TZero);
	
	leftlab := t.cg.reserve_labels(1, TRUE);
	ovflshift := t.cg.reserve_labels(1, TRUE);
	--- 1478,1484 ----
	find(t, stack1, Force.anyreg);
	END;
	
	!           t.cg.immOp(Op.oCMP, stop0, TInt.Zero);
	
	leftlab := t.cg.reserve_labels(1, TRUE);
	ovflshift := t.cg.reserve_labels(1, TRUE);
	***************
	*** 1484,1490 ****
	
	t.cg.brOp(Cond.GE, leftlab);
	t.cg.unOp(Op.oNEG, stop0);
	!           t.cg.immOp(Op.oCMP, stop0, TInt.ThirtyTwo);
	t.cg.brOp(Cond.GE, ovflshift);
	t.cg.unOp(Op.oSHR, stop1);
	t.cg.brOp(Cond.Always, endlab);
	--- 1486,1492 ----
	
	t.cg.brOp(Cond.GE, leftlab);
	t.cg.unOp(Op.oNEG, stop0);
	!           t.cg.immOp(Op.oCMP, stop0, Target.Int{32,0,..});
	t.cg.brOp(Cond.GE, ovflshift);
	t.cg.unOp(Op.oSHR, stop1);
	t.cg.brOp(Cond.Always, endlab);
	***************
	*** 1494,1500 ****
	t.cg.brOp(Cond.Always, endlab);
	t.cg.set_label(leftlab);
	(* .leftlab *)
	!           t.cg.immOp(Op.oCMP, stop0, TInt.ThirtyTwo);
	t.cg.brOp(Cond.GE, ovflshift);
	t.cg.unOp(Op.oSHL, stop1);
	t.cg.set_label(endlab);
	--- 1496,1502 ----
	t.cg.brOp(Cond.Always, endlab);
	t.cg.set_label(leftlab);
	(* .leftlab *)
	!           t.cg.immOp(Op.oCMP, stop0, Target.Int{32,0,..});
	t.cg.brOp(Cond.GE, ovflshift);
	t.cg.unOp(Op.oSHL, stop1);
	t.cg.set_label(endlab);
	***************
	*** 1528,1536 ****
	IF NOT TInt.ToInt(stop0.imm, rotateCount) THEN
	t.Err("dorotate: failed to convert rotateCount to host integer");
	END;
	!           TWord.Rotate(stop1.imm, rotateCount, stop1.imm);
	ELSE
	!           IF TInt.NE(stop0.imm, TZero) THEN
	
	IF is64 THEN (* needs work *)
	RETURN FALSE;
	--- 1530,1539 ----
	IF NOT TInt.ToInt(stop0.imm, rotateCount) THEN
	t.Err("dorotate: failed to convert rotateCount to host integer");
	END;
	!           TWord.Rotate(stop1.imm, rotateCount,
	!                        Target.Integer.bytes, stop1.imm);
	ELSE
	!           IF NOT TInt.EQ(stop0.imm, TInt.Zero) THEN
	
	IF is64 THEN (* needs work *)
	RETURN FALSE;
	***************
	*** 1538,1548 ****
	
	find(t, stack1, Force.anytemp);
	
	!             IF TInt.GT(stop0.imm, TZero) THEN
	TWord.And(stop0.imm, BitCountMask[type], stop0.imm);
	t.cg.immOp(Op.oROL, stop1, stop0.imm);
	ELSE
	!               IF NOT TInt.Negate(stop0.imm, stop0.imm) THEN
	t.Err("dorotate: negate overflowed");
	END;
	TWord.And(stop0.imm, BitCountMask[type], stop0.imm);
	--- 1541,1551 ----
	
	find(t, stack1, Force.anytemp);
	
	!             IF TInt.LT(TInt.Zero, stop0.imm) THEN
	TWord.And(stop0.imm, BitCountMask[type], stop0.imm);
	t.cg.immOp(Op.oROL, stop1, stop0.imm);
	ELSE
	!               IF NOT TInt.Subtract(TInt.Zero, stop0.imm, stop0.imm) THEN
	t.Err("dorotate: negate overflowed");
	END;
	TWord.And(stop0.imm, BitCountMask[type], stop0.imm);
	***************
	*** 1554,1560 ****
	END
	ELSE
	
	!         IF ((stop0.loc # OLoc.imm) OR (TInt.NE(stop0.imm, TZero))) THEN
	
	IF is64 THEN (* needs work *)
	RETURN FALSE;
	--- 1557,1563 ----
	END
	ELSE
	
	!         IF ((stop0.loc # OLoc.imm) OR (NOT TInt.EQ(stop0.imm, TInt.Zero))) THEN
	
	IF is64 THEN (* needs work *)
	RETURN FALSE;
	***************
	*** 1567,1573 ****
	find(t, stack1, Force.anyreg);
	END;
	
	!           t.cg.immOp(Op.oCMP, stop0, TZero);
	
	leftlab := t.cg.reserve_labels(1, TRUE);
	endlab := t.cg.reserve_labels(1, TRUE);
	--- 1570,1576 ----
	find(t, stack1, Force.anyreg);
	END;
	
	!           t.cg.immOp(Op.oCMP, stop0, TInt.Zero);
	
	leftlab := t.cg.reserve_labels(1, TRUE);
	endlab := t.cg.reserve_labels(1, TRUE);
	***************
	*** 1705,1715 ****
	find(t, stack0, Force.anyreg);
	END;
	
	!         IF NOT TInt.FromInt(n, Target.Integer.bytes, tn) THEN
	t.Err("doextract_n: failed to convert n to target integer");
	END;
	
	!         IF NOT TInt.Subtract(TInt.ThirtyTwo, tn, t32MinusN) THEN
	t.Err("doextract_n: Subtract overflowed");
	END;
	
	--- 1708,1718 ----
	find(t, stack0, Force.anyreg);
	END;
	
	!         IF NOT TInt.FromInt(n, tn) THEN
	t.Err("doextract_n: failed to convert n to target integer");
	END;
	
	!         IF NOT TInt.Subtract(Target.Int{32,0,..}, tn, t32MinusN) THEN
	t.Err("doextract_n: Subtract overflowed");
	END;
	
	***************
	*** 1759,1765 ****
	IF sign THEN
	TWord.Shift(TInt.One, n - 1, tint);
	TWord.And(stop0.imm, tint, tint);
	!           IF TInt.NE(tint, TZero) THEN
	TWord.Shift(Target.Word32.max, n, tint);
	TWord.Or(stop0.imm, tint, stop0.imm);
	END;
	--- 1762,1768 ----
	IF sign THEN
	TWord.Shift(TInt.One, n - 1, tint);
	TWord.And(stop0.imm, tint, tint);
	!           IF NOT TInt.EQ(tint, TInt.Zero) THEN
	TWord.Shift(Target.Word32.max, n, tint);
	TWord.Or(stop0.imm, tint, stop0.imm);
	END;
	***************
	*** 1770,1783 ****
	IF sign THEN
	find(t, stack0, Force.anyreg);
	IF (m + n) < 32 THEN
	!           IF NOT TInt.FromInt(32 - (m + n), Target.Integer.bytes, tint) THEN
	t.Err("doextract_mn: failed to convert 32 - (m + n) to target integer");
	END;
	t.cg.immOp(Op.oSHL, stop0, tint);
	END;
	
	IF n < 32 THEN
	!           IF NOT TInt.FromInt(32 - n, Target.Integer.bytes, tint) THEN
	t.Err("doextract_mn: failed to convert 32 - n to target integer");
	END;
	t.cg.immOp(Op.oSAR, stop0, tint);
	--- 1773,1786 ----
	IF sign THEN
	find(t, stack0, Force.anyreg);
	IF (m + n) < 32 THEN
	!           IF NOT TInt.FromInt(32 - (m + n), tint) THEN
	t.Err("doextract_mn: failed to convert 32 - (m + n) to target integer");
	END;
	t.cg.immOp(Op.oSHL, stop0, tint);
	END;
	
	IF n < 32 THEN
	!           IF NOT TInt.FromInt(32 - n, tint) THEN
	t.Err("doextract_mn: failed to convert 32 - n to target integer");
	END;
	t.cg.immOp(Op.oSAR, stop0, tint);
	***************
	*** 1790,1796 ****
	END;
	
	IF m > 0 THEN
	!           IF NOT TInt.FromInt(m, Target.Integer.bytes, tint) THEN
	t.Err("doextract_mn: failed to m to target integer");
	END;
	t.cg.immOp(Op.oSHR, stop0, tint);
	--- 1793,1799 ----
	END;
	
	IF m > 0 THEN
	!           IF NOT TInt.FromInt(m, tint) THEN
	t.Err("doextract_mn: failed to m to target integer");
	END;
	t.cg.immOp(Op.oSHR, stop0, tint);
	***************
	*** 1858,1864 ****
	t.cg.binOp(Op.oAND, stop2, t.cg.reg[maskreg]);
	
	IF stop1.loc = OLoc.imm THEN
	!         IF TInt.NE(stop1.imm, TZero) THEN
	t.cg.immOp(Op.oSHL, stop2, stop1.imm);
	t.cg.immOp(Op.oADD, stop0, stop1.imm);
	END
	--- 1861,1867 ----
	t.cg.binOp(Op.oAND, stop2, t.cg.reg[maskreg]);
	
	IF stop1.loc = OLoc.imm THEN
	!         IF NOT TInt.EQ(stop1.imm, TInt.Zero) THEN
	t.cg.immOp(Op.oSHL, stop2, stop1.imm);
	t.cg.immOp(Op.oADD, stop0, stop1.imm);
	END
	***************
	*** 1997,2003 ****
	END;
	
	IF m # 0 THEN
	!           IF NOT TInt.FromInt(m, Target.Integer.bytes, tint_m) THEN
	t.Err("doinsert_mn: unable to convert m to target integer");
	END;
	t.cg.immOp(Op.oSHL, stop0, tint_m);
	--- 2000,2006 ----
	END;
	
	IF m # 0 THEN
	!           IF NOT TInt.FromInt(m, tint_m) THEN
	t.Err("doinsert_mn: unable to convert m to target integer");
	END;
	t.cg.immOp(Op.oSHL, stop0, tint_m);
	***************
	*** 2008,2014 ****
	TWord.Shift(uint_type.max, m + n - uint_type.size, mask_m_n);
	TWord.Xor(mask_m, mask_m_n, mask);
	
	!       IF TWord.NE(mask, uint_type.max) THEN
	IF stop1.loc = OLoc.imm THEN
	TWord.And(stop1.imm, mask, stop1.imm);
	ELSE
	--- 2011,2017 ----
	TWord.Shift(uint_type.max, m + n - uint_type.size, mask_m_n);
	TWord.Xor(mask_m, mask_m_n, mask);
	
	!       IF NOT TInt.EQ(mask, uint_type.max) THEN
	IF stop1.loc = OLoc.imm THEN
	TWord.And(stop1.imm, mask, stop1.imm);
	ELSE
	***************
	*** 2021,2032 ****
	TWord.Or(stop1.imm, stop0.imm, stop1.imm);
	ELSE
	swap(t);
	!           IF stop0.loc # OLoc.imm OR TInt.NE(stop0.imm, TZero) THEN
	t.cg.binOp(Op.oOR, stop1, stop0);
	END
	END
	ELSE
	!         IF stop0.loc # OLoc.imm OR TInt.NE(stop0.imm, TZero) THEN
	t.cg.binOp(Op.oOR, stop1, stop0);
	END
	END;
	--- 2024,2035 ----
	TWord.Or(stop1.imm, stop0.imm, stop1.imm);
	ELSE
	swap(t);
	!           IF stop0.loc # OLoc.imm OR NOT TInt.EQ(stop0.imm, TInt.Zero) THEN
	t.cg.binOp(Op.oOR, stop1, stop0);
	END
	END
	ELSE
	!         IF stop0.loc # OLoc.imm OR NOT TInt.EQ(stop0.imm, TInt.Zero) THEN
	t.cg.binOp(Op.oOR, stop1, stop0);
	END
	END;
	***************
	*** 2209,2215 ****
	find(t, stack1, Force.anyreg, RegSet {}, TRUE);
	
	IF stop0.loc = OLoc.imm THEN
	!         IF NOT TInt.FromInt(size, Target.Integer.bytes, tsize) THEN
	t.Err("doindex_address: failed to convert size to target integer");
	END;
	IF NOT TInt.Multiply(stop0.imm, tsize, tint) THEN
	--- 2212,2218 ----
	find(t, stack1, Force.anyreg, RegSet {}, TRUE);
	
	IF stop0.loc = OLoc.imm THEN
	!         IF NOT TInt.FromInt(size, tsize) THEN
	t.Err("doindex_address: failed to convert size to target integer");
	END;
	IF NOT TInt.Multiply(stop0.imm, tsize, tint) THEN
	***************
	*** 2244,2250 ****
	END
	
	ELSIF shift > 0 THEN
	!           IF NOT TInt.FromInt(shift, Target.Integer.bytes, tshift) THEN
	t.Err("doindex_address: failed to convert size to target integer");
	END;
	t.cg.immOp(Op.oSHL, stop0, tshift);
	--- 2247,2253 ----
	END
	
	ELSIF shift > 0 THEN
	!           IF NOT TInt.FromInt(shift, tshift) THEN
	t.Err("doindex_address: failed to convert size to target integer");
	END;
	t.cg.immOp(Op.oSHL, stop0, tshift);
	***************
	*** 2383,2391 ****
	t.cg.memFOp(FOp.fSTCW, statusop.mvar);
	
	t.cg.movOp(t.cg.reg[statreg], statusop);
	!     t.cg.immOp(Op.oAND, t.cg.reg[statreg], TInt.F3FF);
	
	!     IF TInt.NE(t.rmode[mode], TZero) THEN
	t.cg.immOp(Op.oOR, t.cg.reg[statreg], t.rmode[mode]);
	END;
	
	--- 2386,2394 ----
	t.cg.memFOp(FOp.fSTCW, statusop.mvar);
	
	t.cg.movOp(t.cg.reg[statreg], statusop);
	!     t.cg.immOp(Op.oAND, t.cg.reg[statreg], Target.Int{16_FF,16_F3,0,..});
	
	!     IF NOT TInt.EQ(t.rmode[mode], TInt.Zero) THEN
	t.cg.immOp(Op.oOR, t.cg.reg[statreg], t.rmode[mode]);
	END;
	
	***************
	*** 2540,2546 ****
	END;
	
	t.rmode := ARRAY FlToInt OF Target.Int
	!       { TZero, TInt.x0400, TInt.x0800, TInt.x0F00 };
	t.lowset_table := NIL;
	t.highset_table := NIL;
	END init;
	--- 2543,2552 ----
	END;
	
	t.rmode := ARRAY FlToInt OF Target.Int
	!       { Target.Int{0,0,0,..},
	!         Target.Int{0,4,0,..},
	!         Target.Int{0,8,0,..},
	!         Target.Int{0,16_F,0,..}};
	t.lowset_table := NIL;
	t.highset_table := NIL;
	END init;
	***************
	*** 2633,2639 ****
	IF r.last_store # NoStore THEN
	wr.OutT ("  mvar: ");  DebugMVar (r.last_store, wr);
	END;
	!     IF (NOT TInt.EQ(r.last_imm, TZero)) THEN
	wr.OutT ("  imm: ");  wr.OutT (TInt.ToText (r.last_imm));
	END;
	IF (NOT TInt.EQ(r.lowbound, Target.Integer.min)) THEN
	--- 2639,2645 ----
	IF r.last_store # NoStore THEN
	wr.OutT ("  mvar: ");  DebugMVar (r.last_store, wr);
	END;
	!     IF (NOT TInt.EQ(r.last_imm, TInt.Zero)) THEN
	wr.OutT ("  imm: ");  wr.OutT (TInt.ToText (r.last_imm));
	END;
	IF (NOT TInt.EQ(r.lowbound, Target.Integer.min)) THEN
	Index: m3back/src/Wrx86.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3back/src/Wrx86.m3,v
	retrieving revision 1.6
	diff -c -r1.6 Wrx86.m3
	*** m3back/src/Wrx86.m3	15 Feb 2010 17:45:22 -0000	1.6
	--- m3back/src/Wrx86.m3	18 Feb 2010 02:30:51 -0000
	***************
	*** 153,164 ****
	PROCEDURE TInt (t: T;  READONLY i: Target.Int) =
	VAR
	buf : ARRAY [0..BITSIZE (Target.Integer)] OF CHAR;
	-     len := TargetInt.ToChars (i, buf);
	BEGIN
	OutC (t, ' ');
	!     OutS (t, SUBARRAY (buf, 0, len));
	!     OutC (t, ' ');
	!     OutT (t, Target.TargetIntToDiagnosticText(i));
	END TInt;
	
	PROCEDURE BInt (t: T;  i: INTEGER) =
	--- 153,161 ----
	PROCEDURE TInt (t: T;  READONLY i: Target.Int) =
	VAR
	buf : ARRAY [0..BITSIZE (Target.Integer)] OF CHAR;
	BEGIN
	OutC (t, ' ');
	!     OutS (t, SUBARRAY (buf, 0, TargetInt.ToChars (i, buf)));
	END TInt;
	
	PROCEDURE BInt (t: T;  i: INTEGER) =
	Index: m3front/src/builtinAtomic/AtomicModule.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinAtomic/AtomicModule.mg,v
	retrieving revision 1.2
	diff -c -r1.2 AtomicModule.mg
	*** m3front/src/builtinAtomic/AtomicModule.mg	4 Feb 2010 02:11:30 -0000	1.2
	--- m3front/src/builtinAtomic/AtomicModule.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 10,20 ****
	Fence,
	FetchInc, FetchDec, FetchOr, FetchXor, FetchAnd);
	
	! IMPORT Scope, Tipe, Module, TInt;
	IMPORT Field, M3ID, Value, RecordType;
	IMPORT EnumType, EnumExpr, EnumElt;
	
	PROCEDURE Initialize (name: TEXT) =
	VAR zz, elts: Scope.T;  rep: Field.Info;  cs: Value.CheckState;
	BEGIN
	M := Module.NewDefn (name, TRUE, NIL);
	--- 10,26 ----
	Fence,
	FetchInc, FetchDec, FetchOr, FetchXor, FetchAnd);
	
	! IMPORT Scope, Tipe, Module, Target;
	IMPORT Field, M3ID, Value, RecordType;
	IMPORT EnumType, EnumExpr, EnumElt;
	
	PROCEDURE Initialize (name: TEXT) =
	+   CONST
	+     Zero  = Target.Int{0,0,..};
	+     One   = Target.Int{1,0,..};
	+     Two   = Target.Int{2,0,..};
	+     Three = Target.Int{3,0,..};
	+     Four  = Target.Int{4,0,..};
	VAR zz, elts: Scope.T;  rep: Field.Info;  cs: Value.CheckState;
	BEGIN
	M := Module.NewDefn (name, TRUE, NIL);
	***************
	*** 40,55 ****
	
	elts := Scope.PushNew (FALSE, M3ID.NoID);
	Order := EnumType.New (5, elts);
	!     Scope.Insert (EnumElt.New (M3ID.Add ("Relaxed"),        TInt.Zero,  Order));
	!     Scope.Insert (EnumElt.New (M3ID.Add ("Release"),        TInt.One,   Order));
	!     Scope.Insert (EnumElt.New (M3ID.Add ("Acquire"),        TInt.Two,   Order));
	!     Scope.Insert (EnumElt.New (M3ID.Add ("AcquireRelease"), TInt.Three, Order));
	!     Scope.Insert (EnumElt.New (M3ID.Add ("Sequential"),     TInt.Four,  Order));
	Scope.PopNew ();
	Scope.TypeCheck (elts, cs);
	Tipe.Define ("Order", Order, FALSE);
	
	!     Sequential := EnumExpr.New (Order, TInt.Four);
	
	IsLockFree.Initialize ();
	Store.Initialize ();
	--- 46,61 ----
	
	elts := Scope.PushNew (FALSE, M3ID.NoID);
	Order := EnumType.New (5, elts);
	!     Scope.Insert (EnumElt.New (M3ID.Add ("Relaxed"),        Zero,  Order));
	!     Scope.Insert (EnumElt.New (M3ID.Add ("Release"),        One,   Order));
	!     Scope.Insert (EnumElt.New (M3ID.Add ("Acquire"),        Two,   Order));
	!     Scope.Insert (EnumElt.New (M3ID.Add ("AcquireRelease"), Three, Order));
	!     Scope.Insert (EnumElt.New (M3ID.Add ("Sequential"),     Four,  Order));
	Scope.PopNew ();
	Scope.TypeCheck (elts, cs);
	Tipe.Define ("Order", Order, FALSE);
	
	!     Sequential := EnumExpr.New (Order, Four);
	
	IsLockFree.Initialize ();
	Store.Initialize ();
	Index: m3front/src/builtinInfo/InfoThisLine.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinInfo/InfoThisLine.m3,v
	retrieving revision 1.4
	diff -c -r1.4 InfoThisLine.m3
	*** m3front/src/builtinInfo/InfoThisLine.m3	18 Sep 2007 20:25:21 -0000	1.4
	--- m3front/src/builtinInfo/InfoThisLine.m3	18 Feb 2010 02:30:51 -0000
	***************
	*** 28,34 ****
	BEGIN
	Scanner.Here (file, line);
	line := MAX (0,  line);
	!     b := TInt.FromInt (line, Target.Integer.bytes, val);  <*ASSERT b*>
	RETURN IntegerExpr.New (Int.T, val);
	END Fold;
	
	--- 28,34 ----
	BEGIN
	Scanner.Here (file, line);
	line := MAX (0,  line);
	!     b := TInt.FromInt (line, val);  <*ASSERT b*>
	RETURN IntegerExpr.New (Int.T, val);
	END Fold;
	
	Index: m3front/src/builtinOps/BitSize.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinOps/BitSize.m3,v
	retrieving revision 1.3
	diff -c -r1.3 BitSize.m3
	*** m3front/src/builtinOps/BitSize.m3	18 Sep 2007 20:25:35 -0000	1.3
	--- m3front/src/builtinOps/BitSize.m3	18 Feb 2010 02:30:51 -0000
	***************
	*** 111,121 ****
	IF (info.class = Type.Class.OpenArray) THEN RETURN NIL END;
	END;
	t := Type.CheckInfo (t, info);
	!     IF    TInt.FromInt (info.size, Target.Integer.bytes, size)
	!       AND TInt.FromInt (unit, Target.Integer.bytes, a)
	!       AND TInt.FromInt (unit - 1, Target.Integer.bytes, b)
	AND TInt.Add (size, b, c)
	AND TInt.Div (c, a, d)
	THEN RETURN IntegerExpr.New (Int.T, d);
	ELSE RETURN NIL;
	END;
	--- 111,123 ----
	IF (info.class = Type.Class.OpenArray) THEN RETURN NIL END;
	END;
	t := Type.CheckInfo (t, info);
	!     IF    TInt.FromInt (info.size, size)
	!       AND TInt.FromInt (unit, a)
	!       AND TInt.FromInt (unit - 1, b)
	AND TInt.Add (size, b, c)
	AND TInt.Div (c, a, d)
	+       AND NOT TInt.LT (d, Target.Integer.min)
	+       AND NOT TInt.LT (Target.Integer.max, d)
	THEN RETURN IntegerExpr.New (Int.T, d);
	ELSE RETURN NIL;
	END;
	Index: m3front/src/builtinOps/Dec.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinOps/Dec.m3,v
	retrieving revision 1.12
	diff -c -r1.12 Dec.m3
	*** m3front/src/builtinOps/Dec.m3	10 Jan 2010 10:46:35 -0000	1.12
	--- m3front/src/builtinOps/Dec.m3	18 Feb 2010 02:30:51 -0000
	***************
	*** 71,77 ****
	dec    : Expr.T;
	check  : [0..3] := 0;
	lvalue : CG.Val;
	!     bmin, bmax: Target.Int;
	cg_type: CG.Type;
	BEGIN
	tlhs := Type.CheckInfo (tlhs, info);
	--- 71,77 ----
	dec    : Expr.T;
	check  : [0..3] := 0;
	lvalue : CG.Val;
	!     tmin, tmax, bmin, bmax: Target.Int;
	cg_type: CG.Type;
	BEGIN
	tlhs := Type.CheckInfo (tlhs, info);
	***************
	*** 79,100 ****
	THEN tlhs := LInt.T; cg_type := Target.Longint.cg_type;
	ELSE tlhs := Int.T;  cg_type := Target.Integer.cg_type;
	END;
	IF (NUMBER (ce.args^) > 1)
	THEN dec := ce.args[1];
	!     ELSIF tlhs = LInt.T
	!       THEN dec := IntegerExpr.New (LInt.T, TInt.One);  Expr.Prep (dec);
	!       ELSE dec := IntegerExpr.New (Int.T,  TInt.One);  Expr.Prep (dec);
	END;
	Expr.GetBounds (lhs, bmin, bmax);
	
	IF Host.doRangeChk THEN
	!       IF tlhs = LInt.T THEN
	!         IF TInt.LT (Target.Longint.min, bmin) THEN INC (check) END;
	!         IF TInt.LT (bmax, Target.Longint.max) THEN INC (check, 2) END;
	!       ELSE
	!         IF TInt.LT (Target.Integer.min, bmin) THEN INC (check) END;
	!         IF TInt.LT (bmax, Target.Integer.max) THEN INC (check, 2) END;
	!       END;
	END;
	
	Expr.CompileLValue (lhs, traced := FALSE);
	--- 79,94 ----
	THEN tlhs := LInt.T; cg_type := Target.Longint.cg_type;
	ELSE tlhs := Int.T;  cg_type := Target.Integer.cg_type;
	END;
	+     EVAL Type.GetBounds (tlhs, tmin, tmax);
	IF (NUMBER (ce.args^) > 1)
	THEN dec := ce.args[1];
	!       ELSE dec := IntegerExpr.New (tlhs, TInt.One);  Expr.Prep (dec);
	END;
	Expr.GetBounds (lhs, bmin, bmax);
	
	IF Host.doRangeChk THEN
	!       IF TInt.LT (tmin, bmin) THEN INC (check) END;
	!       IF TInt.LT (bmax, tmax) THEN INC (check, 2) END;
	END;
	
	Expr.CompileLValue (lhs, traced := FALSE);
	Index: m3front/src/builtinOps/Number.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinOps/Number.m3,v
	retrieving revision 1.4
	diff -c -r1.4 Number.m3
	*** m3front/src/builtinOps/Number.m3	18 Sep 2007 20:25:36 -0000	1.4
	--- m3front/src/builtinOps/Number.m3	18 Feb 2010 02:30:51 -0000
	***************
	*** 64,70 ****
	e := ce.args[0];
	t, index, element: Type.T;
	min, max, tmp, num: Target.Int;
	-     One := Target.Int{Target.Integer.bytes, Target.IBytes{1,0,..}};
	BEGIN
	IF NOT TypeExpr.Split (e, t) THEN t := Expr.TypeOf (e) END;
	IF ArrayType.Split (t, index, element) THEN t := index END;
	--- 64,69 ----
	***************
	*** 77,83 ****
	IF TInt.LT (max, min) THEN
	CG.Load_integer (Target.Integer.cg_type, TInt.Zero);
	ELSIF TInt.Subtract (max, min, tmp)
	!         AND TInt.Add (tmp, One, num) THEN
	CG.Load_integer (Target.Integer.cg_type, num);
	ELSE
	Error.Warn (2, "result of NUMBER too large");
	--- 76,83 ----
	IF TInt.LT (max, min) THEN
	CG.Load_integer (Target.Integer.cg_type, TInt.Zero);
	ELSIF TInt.Subtract (max, min, tmp)
	!         AND TInt.Add (tmp, TInt.One, num)
	!         AND NOT TInt.LT (Target.Integer.max, num) THEN
	CG.Load_integer (Target.Integer.cg_type, num);
	ELSE
	Error.Warn (2, "result of NUMBER too large");
	***************
	*** 90,96 ****
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	VAR min, max, tmp, num: Target.Int;  t, index, elem: Type.T;  e: Expr.T;
	-       One := Target.Int{Target.Integer.bytes, Target.IBytes{1,0,..}};
	BEGIN
	e := ce.args[0];
	IF NOT TypeExpr.Split (e, t) THEN
	--- 90,95 ----
	***************
	*** 102,108 ****
	IF (e = NIL) THEN RETURN NIL END;
	IF ArrayExpr.GetBounds (e, min, max)
	AND TInt.Subtract (max, min, tmp)
	!           AND TInt.Add (tmp, One, num)
	THEN RETURN IntegerExpr.New (Int.T, num);
	ELSE RETURN NIL;
	END;
	--- 101,109 ----
	IF (e = NIL) THEN RETURN NIL END;
	IF ArrayExpr.GetBounds (e, min, max)
	AND TInt.Subtract (max, min, tmp)
	!           AND TInt.Add (tmp, TInt.One, num)
	!           AND NOT TInt.LT (num, Target.Integer.max)
	!           AND NOT TInt.LT (Target.Integer.max, num)
	THEN RETURN IntegerExpr.New (Int.T, num);
	ELSE RETURN NIL;
	END;
	***************
	*** 114,120 ****
	IF TInt.LT (max, min) THEN
	RETURN IntegerExpr.New (Int.T, TInt.Zero);
	ELSIF TInt.Subtract (max, min, tmp)
	!       AND TInt.Add (tmp, One, num) THEN
	RETURN IntegerExpr.New (Int.T, num);
	ELSE
	RETURN NIL;
	--- 115,122 ----
	IF TInt.LT (max, min) THEN
	RETURN IntegerExpr.New (Int.T, TInt.Zero);
	ELSIF TInt.Subtract (max, min, tmp)
	!       AND TInt.Add (tmp, TInt.One, num)
	!       AND NOT TInt.LT (Target.Integer.max, num) THEN
	RETURN IntegerExpr.New (Int.T, num);
	ELSE
	RETURN NIL;
	Index: m3front/src/builtinWord/And.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/And.mg,v
	retrieving revision 1.1
	diff -c -r1.1 And.mg
	*** m3front/src/builtinWord/And.mg	4 Feb 2010 20:00:45 -0000	1.1
	--- m3front/src/builtinWord/And.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 7,17 ****
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	IMPORT IntegerExpr, Formal, Value, Target, TWord, TInt;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Integer_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Integer_types) .. LAST (Integer_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	--- 7,17 ----
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	IMPORT IntegerExpr, Formal, Value, Target, TWord, TInt;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Word_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Word_types) .. LAST (Word_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	***************
	*** 23,29 ****
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.And (Integer_types[rep].cg_type);
	END Compile;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	--- 23,29 ----
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.And (Word_types[rep].cg_type);
	END Compile;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	***************
	*** 31,36 ****
	--- 31,37 ----
	BEGIN
	IF GetArgs (ce.args, w0, w1) THEN
	TWord.And (w0, w1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	Index: m3front/src/builtinWord/Divide.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Divide.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Divide.mg
	*** m3front/src/builtinWord/Divide.mg	4 Feb 2010 20:00:45 -0000	1.1
	--- m3front/src/builtinWord/Divide.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 42,49 ****
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     RETURN (e0 # NIL) AND IntegerExpr.Split (e0, w0, t) AND
	!            (e1 # NIL) AND IntegerExpr.Split (e1, w1, t);
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	--- 42,56 ----
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     IF    (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	!       AND (e1 # NIL) AND IntegerExpr.Split (e1, w1, t)
	!     THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.And (w1, Word_types[rep].max, w1);
	!       RETURN TRUE;
	!     ELSE
	!       RETURN FALSE;
	!     END;
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	Index: m3front/src/builtinWord/Extract.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Extract.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Extract.mg
	*** m3front/src/builtinWord/Extract.mg	4 Feb 2010 20:00:45 -0000	1.1
	--- m3front/src/builtinWord/Extract.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 8,18 ****
	IMPORT IntegerExpr, Type, ProcType, Host, Card;
	IMPORT Target, TInt, TWord, Value, Formal, CheckExpr, Error;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Integer_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Integer_types) .. LAST (Integer_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	--- 8,18 ----
	IMPORT IntegerExpr, Type, ProcType, Host, Card;
	IMPORT Target, TInt, TWord, Value, Formal, CheckExpr, Error;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Word_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Word_types) .. LAST (Word_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	***************
	*** 32,67 ****
	
	IF x1 AND x2 THEN
	(* we can use the extract_mn operator *)
	!       IF (i1 + i2 > Integer_types[rep].size) THEN
	Error.Warn (2, "Word.Extract: i+n value out of range");
	CG.Load_integer (Target.Integer.cg_type, TInt.One);
	CG.Check_hi (Target.Integer.cg_type, TInt.Zero,
	CG.RuntimeError.ValueOutOfRange);
	ELSE
	Expr.Compile (ce.args[0]);
	!         CG.Extract_mn (Integer_types[rep].cg_type, FALSE, i1, i2);
	END;
	
	ELSIF x2 THEN
	(* we can use the extract_n operator *)
	!       b := TInt.FromInt (Integer_types[rep].size - i2, Target.Integer.bytes, max);
	!       <*ASSERT b*>
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!       CG.Extract_n (Integer_types[rep].cg_type, FALSE, i2);
	
	ELSIF x1 THEN
	(* we need the general purpose extract operator, but can simplify
	the range checking code *)
	!       b := TInt.FromInt (Integer_types[rep].size - i1, Target.Integer.bytes, max);
	!       <*ASSERT b*>
	Expr.Compile (ce.args[0]);
	CG.Force ();
	CG.Load_intt (i1);
	CheckExpr.EmitChecks (ce.args[2], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!       CG.Extract (Integer_types[rep].cg_type, sign := FALSE);
	
	ELSE
	(* we need the general purpose extract operator *)
	--- 32,65 ----
	
	IF x1 AND x2 THEN
	(* we can use the extract_mn operator *)
	!       IF (i1 + i2 > Word_types[rep].size) THEN
	Error.Warn (2, "Word.Extract: i+n value out of range");
	CG.Load_integer (Target.Integer.cg_type, TInt.One);
	CG.Check_hi (Target.Integer.cg_type, TInt.Zero,
	CG.RuntimeError.ValueOutOfRange);
	ELSE
	Expr.Compile (ce.args[0]);
	!         CG.Extract_mn (Word_types[rep].cg_type, FALSE, i1, i2);
	END;
	
	ELSIF x2 THEN
	(* we can use the extract_n operator *)
	!       b := TInt.FromInt (Word_types[rep].size - i2, max);  <*ASSERT b*>
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!       CG.Extract_n (Word_types[rep].cg_type, FALSE, i2);
	
	ELSIF x1 THEN
	(* we need the general purpose extract operator, but can simplify
	the range checking code *)
	!       b := TInt.FromInt (Word_types[rep].size - i1, max);  <*ASSERT b*>
	Expr.Compile (ce.args[0]);
	CG.Force ();
	CG.Load_intt (i1);
	CheckExpr.EmitChecks (ce.args[2], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!       CG.Extract (Word_types[rep].cg_type, sign := FALSE);
	
	ELSE
	(* we need the general purpose extract operator *)
	***************
	*** 72,79 ****
	CG.RuntimeError.ValueOutOfRange);
	t2 := CG.Pop ();
	IF Host.doRangeChk THEN
	!         b := TInt.FromInt (Integer_types[rep].size, Target.Integer.bytes, max);
	!         <*ASSERT b*>
	CG.Push (t1);
	CG.Push (t2);
	CG.Add (Target.Integer.cg_type);
	--- 70,76 ----
	CG.RuntimeError.ValueOutOfRange);
	t2 := CG.Pop ();
	IF Host.doRangeChk THEN
	!         b := TInt.FromInt (Word_types[rep].size, max);  <*ASSERT b*>
	CG.Push (t1);
	CG.Push (t2);
	CG.Add (Target.Integer.cg_type);
	***************
	*** 85,91 ****
	CG.Force ();
	CG.Push (t1);
	CG.Push (t2);
	!       CG.Extract (Integer_types[rep].cg_type, sign := FALSE);
	CG.Free (t1);
	CG.Free (t2);
	END;
	--- 82,88 ----
	CG.Force ();
	CG.Push (t1);
	CG.Push (t2);
	!       CG.Extract (Word_types[rep].cg_type, sign := FALSE);
	CG.Free (t1);
	CG.Free (t2);
	END;
	***************
	*** 95,115 ****
	BEGIN
	e := Expr.ConstValue (e);
	IF (e = NIL) THEN RETURN FALSE END;
	!     RETURN IntegerExpr.ToInt (e, i) AND (0 <= i) AND (i <= Integer_types[rep].size);
	END GetBitIndex;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	!   VAR e0, e1, e2: Expr.T;  w0, result: Target.Int;  i1, i2: INTEGER;  t: Type.T;
	BEGIN
	e0 := Expr.ConstValue (ce.args[0]);
	!     e1 := Expr.ConstValue (ce.args[1]);
	!     e2 := Expr.ConstValue (ce.args[2]);
	!     IF (e0 = NIL) OR (NOT IntegerExpr.Split (e0, w0, t)) OR
	!        (e1 = NIL) OR (NOT IntegerExpr.ToInt (e1, i1)) OR
	!        (e2 = NIL) OR (NOT IntegerExpr.ToInt (e2, i2)) OR
	!        NOT TWord.Extract (w0, i1, i2, result) THEN
	RETURN NIL;
	END;
	RETURN IntegerExpr.New (T, result);
	END Fold;
	
	--- 92,114 ----
	BEGIN
	e := Expr.ConstValue (e);
	IF (e = NIL) THEN RETURN FALSE END;
	!     RETURN IntegerExpr.ToInt (e, i)
	!        AND (0 <= i) AND (i <= Word_types[rep].size);
	END GetBitIndex;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	!   VAR e0: Expr.T;  w0, result: Target.Int;  i1, i2: INTEGER;  t: Type.T;
	BEGIN
	e0 := Expr.ConstValue (ce.args[0]);
	!     IF   (e0 = NIL)
	!       OR NOT IntegerExpr.Split (e0, w0, t)
	!       OR NOT GetBitIndex (ce.args[1], i1)
	!       OR NOT GetBitIndex (ce.args[2], i2)
	!       OR i1 + i2 > Word_types[rep].size
	!       OR NOT TWord.Extract (w0, i1, i2, result) THEN
	RETURN NIL;
	END;
	+     TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END Fold;
	
	***************
	*** 117,123 ****
	VAR min_bits, max_bits: Target.Int;  i: INTEGER;
	BEGIN
	Expr.GetBounds (ce.args[2], min_bits, max_bits);
	!     IF TInt.ToInt (max_bits, i) AND i < Integer_types[rep].size THEN
	IF NOT TWord.Extract (TInt.MOne, 0, i, max) THEN
	EVAL Type.GetBounds (T, min, max);
	END;
	--- 116,122 ----
	VAR min_bits, max_bits: Target.Int;  i: INTEGER;
	BEGIN
	Expr.GetBounds (ce.args[2], min_bits, max_bits);
	!     IF TInt.ToInt (max_bits, i) AND i < Word_types[rep].size THEN
	IF NOT TWord.Extract (TInt.MOne, 0, i, max) THEN
	EVAL Type.GetBounds (T, min, max);
	END;
	Index: m3front/src/builtinWord/GE.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/GE.mg,v
	retrieving revision 1.1
	diff -c -r1.1 GE.mg
	*** m3front/src/builtinWord/GE.mg	4 Feb 2010 20:00:45 -0000	1.1
	--- m3front/src/builtinWord/GE.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 49,56 ****
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     RETURN (e0 # NIL) AND IntegerExpr.Split (e0, w0, t) AND
	!            (e1 # NIL) AND IntegerExpr.Split (e1, w1, t);
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	--- 49,63 ----
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     IF    (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	!       AND (e1 # NIL) AND IntegerExpr.Split (e1, w1, t)
	!     THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.And (w1, Word_types[rep].max, w1);
	!       RETURN TRUE;
	!     ELSE
	!       RETURN FALSE;
	!     END;
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	Index: m3front/src/builtinWord/GT.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/GT.mg,v
	retrieving revision 1.1
	diff -c -r1.1 GT.mg
	*** m3front/src/builtinWord/GT.mg	4 Feb 2010 20:00:45 -0000	1.1
	--- m3front/src/builtinWord/GT.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 49,56 ****
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     RETURN (e0 # NIL) AND IntegerExpr.Split (e0, w0, t) AND
	!            (e1 # NIL) AND IntegerExpr.Split (e1, w1, t);
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	--- 49,63 ----
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     IF    (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	!       AND (e1 # NIL) AND IntegerExpr.Split (e1, w1, t)
	!     THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.And (w1, Word_types[rep].max, w1);
	!       RETURN TRUE;
	!     ELSE
	!       RETURN FALSE;
	!     END;
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	Index: m3front/src/builtinWord/Insert.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Insert.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Insert.mg
	*** m3front/src/builtinWord/Insert.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Insert.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 8,18 ****
	IMPORT IntegerExpr, Type, ProcType, CheckExpr, Card;
	IMPORT Target, TInt, TWord, Value, Formal, Host;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Integer_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Integer_types) .. LAST (Integer_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	--- 8,18 ----
	IMPORT IntegerExpr, Type, ProcType, CheckExpr, Card;
	IMPORT Target, TInt, TWord, Value, Formal, Host;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Word_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Word_types) .. LAST (Word_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	***************
	*** 30,37 ****
	CG.RuntimeError.ValueOutOfRange);
	t3 := CG.Pop ();
	IF Host.doRangeChk THEN
	!       b := TInt.FromInt (Integer_types[rep].size, Target.Integer.bytes, max);
	!       <*ASSERT b*>
	CG.Push (t2);
	CG.Push (t3);
	CG.Add (Target.Integer.cg_type);
	--- 30,36 ----
	CG.RuntimeError.ValueOutOfRange);
	t3 := CG.Pop ();
	IF Host.doRangeChk THEN
	!       b := TInt.FromInt (Word_types[rep].size, max);  <*ASSERT b*>
	CG.Push (t2);
	CG.Push (t3);
	CG.Add (Target.Integer.cg_type);
	***************
	*** 45,70 ****
	CG.Force ();
	CG.Push (t2);
	CG.Push (t3);
	!     CG.Insert (Integer_types[rep].cg_type);
	CG.Free (t2);
	CG.Free (t3);
	END Compile;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	!   VAR e0, e1, e2, e3: Expr.T;  w0, w1, result: Target.Int; i2, i3: INTEGER;
	!       t: Type.T;
	BEGIN
	e0 := Expr.ConstValue (ce.args[0]);
	e1 := Expr.ConstValue (ce.args[1]);
	!     e2 := Expr.ConstValue (ce.args[2]);
	!     e3 := Expr.ConstValue (ce.args[3]);
	!     IF (e0 = NIL) OR (NOT IntegerExpr.Split (e0, w0, t)) OR
	!        (e1 = NIL) OR (NOT IntegerExpr.Split (e1, w1, t)) OR
	!        (e2 = NIL) OR (NOT IntegerExpr.ToInt (e2, i2)) OR
	!        (e3 = NIL) OR (NOT IntegerExpr.ToInt (e3, i3)) OR
	!        NOT TWord.Insert (w0, w1, i2, i3, result) THEN
	RETURN NIL;
	END;
	RETURN IntegerExpr.New (T, result);
	END Fold;
	
	--- 44,77 ----
	CG.Force ();
	CG.Push (t2);
	CG.Push (t3);
	!     CG.Insert (Word_types[rep].cg_type);
	CG.Free (t2);
	CG.Free (t3);
	END Compile;
	
	+ PROCEDURE GetBitIndex (e: Expr.T;  VAR i: INTEGER): BOOLEAN =
	+   BEGIN
	+     e := Expr.ConstValue (e);
	+     IF (e = NIL) THEN RETURN FALSE END;
	+     RETURN IntegerExpr.ToInt (e, i)
	+        AND (0 <= i) AND (i <= Word_types[rep].size);
	+   END GetBitIndex;
	+
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	!   VAR e0, e1: Expr.T;  w0, w1, result: Target.Int; i2, i3: INTEGER;  t: Type.T;
	BEGIN
	e0 := Expr.ConstValue (ce.args[0]);
	e1 := Expr.ConstValue (ce.args[1]);
	!     IF   (e0 = NIL) OR (e1 = NIL)
	!       OR NOT IntegerExpr.Split (e0, w0, t)
	!       OR NOT IntegerExpr.Split (e1, w1, t)
	!       OR NOT GetBitIndex (ce.args[2], i2)
	!       OR NOT GetBitIndex (ce.args[3], i3)
	!       OR i2 + i3 > Word_types[rep].size
	!       OR NOT TWord.Insert (w0, w1, i2, i3, result) THEN
	RETURN NIL;
	END;
	+     TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END Fold;
	
	Index: m3front/src/builtinWord/LE.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/LE.mg,v
	retrieving revision 1.1
	diff -c -r1.1 LE.mg
	*** m3front/src/builtinWord/LE.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/LE.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 49,56 ****
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     RETURN (e0 # NIL) AND IntegerExpr.Split (e0, w0, t) AND
	!            (e1 # NIL) AND IntegerExpr.Split (e1, w1, t);
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	--- 49,63 ----
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     IF    (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	!       AND (e1 # NIL) AND IntegerExpr.Split (e1, w1, t)
	!     THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.And (w1, Word_types[rep].max, w1);
	!       RETURN TRUE;
	!     ELSE
	!       RETURN FALSE;
	!     END;
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	Index: m3front/src/builtinWord/LT.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/LT.mg,v
	retrieving revision 1.1
	diff -c -r1.1 LT.mg
	*** m3front/src/builtinWord/LT.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/LT.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 49,56 ****
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     RETURN (e0 # NIL) AND IntegerExpr.Split (e0, w0, t) AND
	!            (e1 # NIL) AND IntegerExpr.Split (e1, w1, t);
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	--- 49,63 ----
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     IF    (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	!       AND (e1 # NIL) AND IntegerExpr.Split (e1, w1, t)
	!     THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.And (w1, Word_types[rep].max, w1);
	!       RETURN TRUE;
	!     ELSE
	!       RETURN FALSE;
	!     END;
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	Index: m3front/src/builtinWord/Minus.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Minus.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Minus.mg
	*** m3front/src/builtinWord/Minus.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Minus.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 5,11 ****
	GENERIC MODULE Minus (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	! IMPORT IntegerExpr, Value, Formal, Target, TWord;
	FROM Rep IMPORT T;
	FROM TargetMap IMPORT Word_types;
	
	--- 5,11 ----
	GENERIC MODULE Minus (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	! IMPORT IntegerExpr, Value, Formal, Target, TWord, TInt;
	FROM Rep IMPORT T;
	FROM TargetMap IMPORT Word_types;
	
	***************
	*** 31,36 ****
	--- 31,37 ----
	BEGIN
	IF GetArgs (ce.args, w0, w1) THEN
	TWord.Subtract (w0, w1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	Index: m3front/src/builtinWord/Mod.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Mod.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Mod.mg
	*** m3front/src/builtinWord/Mod.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Mod.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 32,37 ****
	--- 32,38 ----
	VAR w0, w1, result: Target.Int;
	BEGIN
	IF GetArgs (ce.args, w0, w1) AND TWord.Mod (w0, w1, result) THEN
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	***************
	*** 42,49 ****
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     RETURN (e0 # NIL) AND IntegerExpr.Split (e0, w0, t) AND
	!            (e1 # NIL) AND IntegerExpr.Split (e1, w1, t);
	END GetArgs;
	
	PROCEDURE GetBounds (ce: CallExpr.T;  VAR min, max: Target.Int) =
	--- 43,57 ----
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     IF    (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	!       AND (e1 # NIL) AND IntegerExpr.Split (e1, w1, t)
	!     THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.And (w1, Word_types[rep].max, w1);
	!       RETURN TRUE;
	!     ELSE
	!       RETURN FALSE;
	!     END;
	END GetArgs;
	
	PROCEDURE GetBounds (ce: CallExpr.T;  VAR min, max: Target.Int) =
	***************
	*** 56,61 ****
	--- 64,70 ----
	ELSE
	min := TInt.Zero;
	TWord.Subtract (max_b, TInt.One, max);
	+       TInt.Chop (max, Word_types[rep].bytes);
	END;
	END GetBounds;
	
	Index: m3front/src/builtinWord/Module.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Module.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Module.mg
	*** m3front/src/builtinWord/Module.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Module.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 15,22 ****
	PROCEDURE SetRep (): INTEGER =
	VAR min, max: Target.Int;  b: BOOLEAN;
	BEGIN
	!     b := Type.GetBounds (T, min, max);
	!     <*ASSERT b*>
	FOR i := FIRST (Word_types) TO LAST (Word_types) DO
	WITH t = Word_types[i] DO
	IF TWord.LE (max, t.max) THEN
	--- 15,21 ----
	PROCEDURE SetRep (): INTEGER =
	VAR min, max: Target.Int;  b: BOOLEAN;
	BEGIN
	!     b := Type.GetBounds (T, min, max);  <*ASSERT b*>
	FOR i := FIRST (Word_types) TO LAST (Word_types) DO
	WITH t = Word_types[i] DO
	IF TWord.LE (max, t.max) THEN
	***************
	*** 30,37 ****
	PROCEDURE Initialize (name: TEXT) =
	VAR zz: Scope.T;  size: Target.Int;  b: BOOLEAN;  rep := SetRep ();
	BEGIN
	!     b := TInt.FromInt (Word_types[rep].size, Target.Integer.bytes, size);
	!     <*ASSERT b*>
	M := Module.NewDefn (name, TRUE, NIL);
	
	(* WARNING: The following list must be in the same order
	--- 29,35 ----
	PROCEDURE Initialize (name: TEXT) =
	VAR zz: Scope.T;  size: Target.Int;  b: BOOLEAN;  rep := SetRep ();
	BEGIN
	!     b := TInt.FromInt (Word_types[rep].size, size);  <*ASSERT b*>
	M := Module.NewDefn (name, TRUE, NIL);
	
	(* WARNING: The following list must be in the same order
	Index: m3front/src/builtinWord/Not.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Not.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Not.mg
	*** m3front/src/builtinWord/Not.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Not.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 5,11 ****
	GENERIC MODULE Not (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Target, TWord;
	! IMPORT IntegerExpr, Value, Formal, Type, ProcType;
	FROM Rep IMPORT T;
	FROM TargetMap IMPORT Integer_types;
	
	--- 5,11 ----
	GENERIC MODULE Not (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Target, TWord;
	! IMPORT IntegerExpr, Value, Formal, Type, ProcType, TInt;
	FROM Rep IMPORT T;
	FROM TargetMap IMPORT Integer_types;
	
	***************
	*** 31,36 ****
	--- 31,37 ----
	e := Expr.ConstValue (ce.args[0]);
	IF (e # NIL) AND IntegerExpr.Split (e, w, t) THEN
	TWord.Not (w, result);
	+       TInt.Chop (result, Integer_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	Index: m3front/src/builtinWord/Or.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Or.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Or.mg
	*** m3front/src/builtinWord/Or.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Or.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 5,17 ****
	GENERIC MODULE Or (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	! IMPORT IntegerExpr, Value, Formal, Target, TWord;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Integer_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Integer_types) .. LAST (Integer_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	--- 5,17 ----
	GENERIC MODULE Or (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	! IMPORT IntegerExpr, Value, Formal, Target, TWord, TInt;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Word_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Word_types) .. LAST (Word_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	***************
	*** 23,29 ****
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.Or (Integer_types[rep].cg_type);
	END Compile;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	--- 23,29 ----
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.Or (Word_types[rep].cg_type);
	END Compile;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	***************
	*** 31,36 ****
	--- 31,37 ----
	BEGIN
	IF GetArgs (ce.args, w0, w1) THEN
	TWord.Or (w0, w1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	Index: m3front/src/builtinWord/Plus.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Plus.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Plus.mg
	*** m3front/src/builtinWord/Plus.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Plus.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 4,10 ****
	
	GENERIC MODULE Plus (Rep);
	
	! IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Target, TWord;
	IMPORT IntegerExpr, Value, Formal, Type, ProcType;
	FROM Rep IMPORT T;
	FROM TargetMap IMPORT Word_types;
	--- 4,10 ----
	
	GENERIC MODULE Plus (Rep);
	
	! IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Target, TWord, TInt;
	IMPORT IntegerExpr, Value, Formal, Type, ProcType;
	FROM Rep IMPORT T;
	FROM TargetMap IMPORT Word_types;
	***************
	*** 31,36 ****
	--- 31,37 ----
	BEGIN
	IF GetArgs (ce.args, w0, w1) THEN
	TWord.Add (w0, w1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	Index: m3front/src/builtinWord/Rotate.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Rotate.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Rotate.mg
	*** m3front/src/builtinWord/Rotate.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Rotate.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 7,17 ****
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Formal, Type, SubrangeType;
	IMPORT Int, IntegerExpr, Value, ProcType, CheckExpr, Target, TInt, TWord;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Integer_types;
	
	VAR Z, ZL, ZR: CallExpr.MethodList;
	VAR formals, formalsL, formalsR: Value.T;
	! VAR rep: [FIRST (Integer_types) .. LAST (Integer_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	--- 7,18 ----
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Formal, Type, SubrangeType;
	IMPORT Int, IntegerExpr, Value, ProcType, CheckExpr, Target, TInt, TWord;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Word_types;
	
	VAR Z, ZL, ZR: CallExpr.MethodList;
	VAR formals, formalsL, formalsR: Value.T;
	! VAR rep: [FIRST (Word_types) .. LAST (Word_types)];
	! VAR max : Target.Int;
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	***************
	*** 35,63 ****
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.Rotate (Integer_types[rep].cg_type);
	END Compile;
	
	PROCEDURE CompileL (ce: CallExpr.T) =
	-   VAR max: Target.Int;
	-       b := TInt.FromInt (Integer_types[rep].size-1, Target.Integer.bytes, max);
	BEGIN
	-     <* ASSERT b *>
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!     CG.Rotate_left (Integer_types[rep].cg_type);
	END CompileL;
	
	PROCEDURE CompileR (ce: CallExpr.T) =
	-   VAR max: Target.Int;
	-       b := TInt.FromInt (Integer_types[rep].size-1, Target.Integer.bytes, max);
	BEGIN
	-     <* ASSERT b *>
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!     CG.Rotate_right (Integer_types[rep].cg_type);
	END CompileR;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	--- 36,58 ----
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.Rotate (Word_types[rep].cg_type);
	END Compile;
	
	PROCEDURE CompileL (ce: CallExpr.T) =
	BEGIN
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!     CG.Rotate_left (Word_types[rep].cg_type);
	END CompileL;
	
	PROCEDURE CompileR (ce: CallExpr.T) =
	BEGIN
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!     CG.Rotate_right (Word_types[rep].cg_type);
	END CompileR;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	***************
	*** 68,74 ****
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	THEN
	!       TWord.Rotate (w0, i1, result);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	--- 63,71 ----
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.Rotate (w0, i1, Word_types[rep].bytes, result);
	!       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	***************
	*** 81,89 ****
	e1 := Expr.ConstValue (ce.args[1]);
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	!       AND 0 <= i1 AND i1 < Integer_types[rep].size
	THEN
	!       TWord.Rotate (w0, i1, result);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	--- 78,88 ----
	e1 := Expr.ConstValue (ce.args[1]);
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	!       AND 0 <= i1 AND i1 < Word_types[rep].size
	THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.Rotate (w0, i1, Word_types[rep].bytes, result);
	!       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	***************
	*** 96,104 ****
	e1 := Expr.ConstValue (ce.args[1]);
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	!       AND 0 <= i1 AND i1 < Integer_types[rep].size
	THEN
	!       TWord.Rotate (w0, -i1, result);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	--- 95,105 ----
	e1 := Expr.ConstValue (ce.args[1]);
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	!       AND 0 <= i1 AND i1 < Word_types[rep].size
	THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.Rotate (w0, -i1, Word_types[rep].bytes, result);
	!       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	***************
	*** 106,113 ****
	
	PROCEDURE Initialize (r: INTEGER) =
	VAR
	!     max : Target.Int;
	!     b   := TInt.FromInt (Integer_types[r].size-1, Target.Integer.bytes, max);
	sub := SubrangeType.New (TInt.Zero, max, Int.T, FALSE);
	
	f0  := Formal.NewBuiltin ("x", 0, T);
	--- 107,113 ----
	
	PROCEDURE Initialize (r: INTEGER) =
	VAR
	!     b   := TInt.FromInt (Word_types[r].size-1, max);
	sub := SubrangeType.New (TInt.Zero, max, Int.T, FALSE);
	
	f0  := Formal.NewBuiltin ("x", 0, T);
	Index: m3front/src/builtinWord/Shift.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Shift.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Shift.mg
	*** m3front/src/builtinWord/Shift.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Shift.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 7,17 ****
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, SubrangeType, Formal;
	IMPORT Int, IntegerExpr, Value, ProcType, CheckExpr, Target, TInt, TWord;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Integer_types;
	
	VAR Z, ZL, ZR: CallExpr.MethodList;
	VAR formals, formalsL, formalsR: Value.T;
	! VAR rep: [FIRST (Integer_types) .. LAST (Integer_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	--- 7,18 ----
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, SubrangeType, Formal;
	IMPORT Int, IntegerExpr, Value, ProcType, CheckExpr, Target, TInt, TWord;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Word_types;
	
	VAR Z, ZL, ZR: CallExpr.MethodList;
	VAR formals, formalsL, formalsR: Value.T;
	! VAR rep: [FIRST (Word_types) .. LAST (Word_types)];
	! VAR max: Target.Int;
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	***************
	*** 35,63 ****
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.Shift (Integer_types[rep].cg_type);
	END Compile;
	
	PROCEDURE CompileL (ce: CallExpr.T) =
	-   VAR max: Target.Int;
	-       b := TInt.FromInt (Integer_types[rep].size-1, Target.Integer.bytes, max);
	BEGIN
	-     <* ASSERT b *>
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!     CG.Shift_left (Integer_types[rep].cg_type);
	END CompileL;
	
	PROCEDURE CompileR (ce: CallExpr.T) =
	-   VAR max: Target.Int;
	-       b := TInt.FromInt (Integer_types[rep].size-1, Target.Integer.bytes, max);
	BEGIN
	-     <* ASSERT b *>
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!     CG.Shift_right (Integer_types[rep].cg_type);
	END CompileR;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	--- 36,58 ----
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.Shift (Word_types[rep].cg_type);
	END Compile;
	
	PROCEDURE CompileL (ce: CallExpr.T) =
	BEGIN
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!     CG.Shift_left (Word_types[rep].cg_type);
	END CompileL;
	
	PROCEDURE CompileR (ce: CallExpr.T) =
	BEGIN
	Expr.Compile (ce.args[0]);
	CheckExpr.EmitChecks (ce.args[1], TInt.Zero, max,
	CG.RuntimeError.ValueOutOfRange);
	!     CG.Shift_right (Word_types[rep].cg_type);
	END CompileR;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	***************
	*** 68,74 ****
	--- 63,71 ----
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	THEN
	+       TWord.And (w0, Word_types[rep].max, w0);
	TWord.Shift (w0, i1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	***************
	*** 81,89 ****
	e1 := Expr.ConstValue (ce.args[1]);
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	!       AND 0 <= i1 AND i1 < Integer_types[rep].size
	THEN
	TWord.Shift (w0, i1, result);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	--- 78,88 ----
	e1 := Expr.ConstValue (ce.args[1]);
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	!       AND 0 <= i1 AND i1 < Word_types[rep].size
	THEN
	+       TWord.And (w0, Word_types[rep].max, w0);
	TWord.Shift (w0, i1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	***************
	*** 96,104 ****
	e1 := Expr.ConstValue (ce.args[1]);
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	!       AND 0 <= i1 AND i1 < Integer_types[rep].size
	THEN
	TWord.Shift (w0, -i1, result);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	--- 95,105 ----
	e1 := Expr.ConstValue (ce.args[1]);
	IF (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	AND (e1 # NIL) AND IntegerExpr.ToInt (e1, i1)
	!       AND 0 <= i1 AND i1 < Word_types[rep].size
	THEN
	+       TWord.And (w0, Word_types[rep].max, w0);
	TWord.Shift (w0, -i1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	***************
	*** 106,113 ****
	
	PROCEDURE Initialize (r: INTEGER) =
	VAR
	!     max : Target.Int;
	!     b   := TInt.FromInt (Integer_types[r].size-1, Target.Integer.bytes, max);
	sub := SubrangeType.New (TInt.Zero, max, Int.T, FALSE);
	
	f0  := Formal.NewBuiltin ("x", 0, T);
	--- 107,113 ----
	
	PROCEDURE Initialize (r: INTEGER) =
	VAR
	!     b   := TInt.FromInt (Word_types[r].size-1, max);
	sub := SubrangeType.New (TInt.Zero, max, Int.T, FALSE);
	
	f0  := Formal.NewBuiltin ("x", 0, T);
	Index: m3front/src/builtinWord/Times.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Times.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Times.mg
	*** m3front/src/builtinWord/Times.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Times.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 5,11 ****
	GENERIC MODULE Times (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	! IMPORT IntegerExpr, Value, Formal, Target, TWord;
	FROM Rep IMPORT T;
	FROM TargetMap IMPORT Word_types;
	
	--- 5,11 ----
	GENERIC MODULE Times (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	! IMPORT IntegerExpr, Value, Formal, Target, TWord, TInt;
	FROM Rep IMPORT T;
	FROM TargetMap IMPORT Word_types;
	
	***************
	*** 31,36 ****
	--- 31,37 ----
	BEGIN
	IF GetArgs (ce.args, w0, w1) THEN
	TWord.Multiply (w0, w1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	***************
	*** 41,48 ****
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     RETURN (e0 # NIL) AND IntegerExpr.Split (e0, w0, t) AND
	!            (e1 # NIL) AND IntegerExpr.Split (e1, w1, t);
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	--- 42,56 ----
	BEGIN
	e0 := Expr.ConstValue (args[0]);
	e1 := Expr.ConstValue (args[1]);
	!     IF    (e0 # NIL) AND IntegerExpr.Split (e0, w0, t)
	!       AND (e1 # NIL) AND IntegerExpr.Split (e1, w1, t)
	!     THEN
	!       TWord.And (w0, Word_types[rep].max, w0);
	!       TWord.And (w1, Word_types[rep].max, w1);
	!       RETURN TRUE;
	!     ELSE
	!       RETURN FALSE;
	!     END;
	END GetArgs;
	
	PROCEDURE Initialize (r: INTEGER) =
	Index: m3front/src/builtinWord/Xor.mg
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/builtinWord/Xor.mg,v
	retrieving revision 1.1
	diff -c -r1.1 Xor.mg
	*** m3front/src/builtinWord/Xor.mg	4 Feb 2010 20:00:46 -0000	1.1
	--- m3front/src/builtinWord/Xor.mg	18 Feb 2010 02:30:51 -0000
	***************
	*** 5,17 ****
	GENERIC MODULE Xor (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	! IMPORT IntegerExpr, Value, Formal, Target, TWord;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Integer_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Integer_types) .. LAST (Integer_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	--- 5,17 ----
	GENERIC MODULE Xor (Rep);
	
	IMPORT CG, CallExpr, Expr, ExprRep, Procedure, Type, ProcType;
	! IMPORT IntegerExpr, Value, Formal, Target, TWord, TInt;
	FROM Rep IMPORT T;
	! FROM TargetMap IMPORT Word_types;
	
	VAR Z: CallExpr.MethodList;
	VAR formals: Value.T;
	! VAR rep: [FIRST (Word_types) .. LAST (Word_types)];
	
	PROCEDURE Check (ce: CallExpr.T;  VAR cs: Expr.CheckState) =
	BEGIN
	***************
	*** 23,29 ****
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.Xor (Integer_types[rep].cg_type);
	END Compile;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	--- 23,29 ----
	BEGIN
	Expr.Compile (ce.args[0]);
	Expr.Compile (ce.args[1]);
	!     CG.Xor (Word_types[rep].cg_type);
	END Compile;
	
	PROCEDURE Fold (ce: CallExpr.T): Expr.T =
	***************
	*** 31,36 ****
	--- 31,37 ----
	BEGIN
	IF GetArgs (ce.args, w0, w1) THEN
	TWord.Xor (w0, w1, result);
	+       TInt.Chop (result, Word_types[rep].bytes);
	RETURN IntegerExpr.New (T, result);
	END;
	RETURN NIL;
	Index: m3front/src/exprs/AddExpr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/AddExpr.m3,v
	retrieving revision 1.4
	diff -c -r1.4 AddExpr.m3
	*** m3front/src/exprs/AddExpr.m3	10 Jan 2010 05:12:05 -0000	1.4
	--- m3front/src/exprs/AddExpr.m3	18 Feb 2010 02:30:51 -0000
	***************
	*** 172,178 ****
	EVAL Type.GetBounds (p.type, min, max);
	Expr.GetBounds (p.a, min_a, max_a);
	Expr.GetBounds (p.b, min_b, max_b);
	!     IF TInt.Add (min_a, min_b, smin) AND TInt.Add (max_a, max_b, smax) THEN
	IF TInt.LT (min, smin) THEN min := smin END;
	IF TInt.LT (smax, max) THEN max := smax END;
	END;
	--- 172,181 ----
	EVAL Type.GetBounds (p.type, min, max);
	Expr.GetBounds (p.a, min_a, max_a);
	Expr.GetBounds (p.b, min_b, max_b);
	!     IF TInt.Add (min_a, min_b, smin)
	!       AND NOT TInt.LT (smin, min) AND NOT TInt.LT (max, smin)
	!       AND TInt.Add (max_a, max_b, smax)
	!       AND NOT TInt.LT (smax, min) AND NOT TInt.LT (max, smax) THEN
	IF TInt.LT (min, smin) THEN min := smin END;
	IF TInt.LT (smax, max) THEN max := smax END;
	END;
	Index: m3front/src/exprs/AddressExpr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/AddressExpr.m3,v
	retrieving revision 1.8
	diff -c -r1.8 AddressExpr.m3
	*** m3front/src/exprs/AddressExpr.m3	8 Feb 2010 12:03:30 -0000	1.8
	--- m3front/src/exprs/AddressExpr.m3	18 Feb 2010 02:30:52 -0000
	***************
	*** 39,45 ****
	PROCEDURE New (READONLY value: Target.Int): Expr.T =
	VAR p: P;
	BEGIN
	-     IF TWord.LT (Target.Address.max, value) THEN RETURN NIL END;
	p := NEW (P);
	ExprRep.Init (p);
	p.value   := value;
	--- 39,44 ----
	***************
	*** 66,72 ****
	IF NOT IntegerExpr.Split (b, i, t) THEN RETURN FALSE END;
	TYPECASE a OF
	| NULL => RETURN FALSE;
	!     | P(p) => TWord.Add (p.value, i, j);  c := New (j);  RETURN c # NIL;
	ELSE      RETURN FALSE;
	END;
	END Add;
	--- 65,75 ----
	IF NOT IntegerExpr.Split (b, i, t) THEN RETURN FALSE END;
	TYPECASE a OF
	| NULL => RETURN FALSE;
	!     | P(p) =>
	!       TWord.Add (p.value, i, j);
	!       TInt.Chop (j, Target.Address.bytes);
	!       c := New (j);
	!       RETURN TRUE;
	ELSE      RETURN FALSE;
	END;
	END Add;
	***************
	*** 82,102 ****
	
	IF IntegerExpr.Split (b, j, t) THEN
	TWord.Subtract (i, j, k);
	c := New (k);
	ELSE (* address - address *)
	TYPECASE b OF
	| NULL => RETURN FALSE;
	!       | P(p) => TWord.Subtract (i, p.value, k);  c := IntegerExpr.New (t, k);
	ELSE      RETURN FALSE;
	END;
	END;
	!     RETURN c # NIL;
	END Subtract;
	
	PROCEDURE Compare (a, b: Expr.T;  VAR sign: INTEGER): BOOLEAN =
	VAR x, y: Target.Int;
	BEGIN
	IF  NOT SplitPair (a, b, x, y) THEN RETURN FALSE END;
	IF TWord.LT (x, y) THEN
	sign := -1
	ELSIF TWord.LT (y, x) THEN
	--- 85,111 ----
	
	IF IntegerExpr.Split (b, j, t) THEN
	TWord.Subtract (i, j, k);
	+       TInt.Chop (k, Target.Address.bytes);
	c := New (k);
	ELSE (* address - address *)
	TYPECASE b OF
	| NULL => RETURN FALSE;
	!       | P(p) =>
	!         TWord.Subtract (i, p.value, k);
	!         TInt.Chop (k, Target.Address.bytes);
	!         c := IntegerExpr.New (t, k);
	ELSE      RETURN FALSE;
	END;
	END;
	!     RETURN TRUE;
	END Subtract;
	
	PROCEDURE Compare (a, b: Expr.T;  VAR sign: INTEGER): BOOLEAN =
	VAR x, y: Target.Int;
	BEGIN
	IF  NOT SplitPair (a, b, x, y) THEN RETURN FALSE END;
	+     TWord.And (x, Target.Address.max, x);
	+     TWord.And (y, Target.Address.max, y);
	IF TWord.LT (x, y) THEN
	sign := -1
	ELSIF TWord.LT (y, x) THEN
	Index: m3front/src/exprs/ArrayExpr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/ArrayExpr.m3,v
	retrieving revision 1.6
	diff -c -r1.6 ArrayExpr.m3
	*** m3front/src/exprs/ArrayExpr.m3	18 Sep 2007 20:25:54 -0000	1.6
	--- m3front/src/exprs/ArrayExpr.m3	18 Feb 2010 02:30:52 -0000
	***************
	*** 103,117 ****
	END;
	IF p.index = NIL THEN
	min := TInt.Zero (* FIRST (p.args^) *);
	!       b := TInt.FromInt (LAST (p.args^), Target.Integer.bytes, max);
	!       <* ASSERT b *>
	ELSE
	EVAL Type.GetBounds (p.index, min, max);
	END;
	
	(* correct for the base index of the array *)
	IF NOT TInt.Subtract (int, min, offs) THEN RETURN FALSE END;
	!     IF TInt.LT (offs, TInt.Zero)  THEN RETURN FALSE END;
	b := TInt.ToInt (offs, i); <* ASSERT b *>
	
	n := LAST (p.args^);
	--- 103,116 ----
	END;
	IF p.index = NIL THEN
	min := TInt.Zero (* FIRST (p.args^) *);
	!       b := TInt.FromInt (LAST (p.args^), max);  <* ASSERT b *>
	ELSE
	EVAL Type.GetBounds (p.index, min, max);
	END;
	
	(* correct for the base index of the array *)
	IF NOT TInt.Subtract (int, min, offs) THEN RETURN FALSE END;
	!     IF TInt.LT (offs, TInt.Zero) THEN RETURN FALSE END;
	b := TInt.ToInt (offs, i); <* ASSERT b *>
	
	n := LAST (p.args^);
	***************
	*** 125,140 ****
	BEGIN
	TYPECASE array OF
	| NULL => RETURN FALSE;
	!     | P(p) => IF p.index = NIL THEN
	!                 (* open array type *)
	!                 min := TInt.Zero (* FIRST (p.args^) *);
	!                 b := TInt.FromInt (LAST (p.args^), Target.Integer.bytes, max);
	!                 <*ASSERT b*>
	!                 RETURN TRUE;
	!               ELSE
	!                 RETURN Type.GetBounds (p.index, min, max);
	!               END;
	!     ELSE     RETURN FALSE;
	END;
	END GetBounds;
	
	--- 124,140 ----
	BEGIN
	TYPECASE array OF
	| NULL => RETURN FALSE;
	!     | P(p) =>
	!       IF p.index = NIL THEN
	!         (* open array type *)
	!         min := TInt.Zero (* FIRST (p.args^) *);
	!         b := TInt.FromInt (LAST (p.args^), max);  <*ASSERT b*>
	!         RETURN TRUE;
	!       ELSE
	!         RETURN Type.GetBounds (p.index, min, max);
	!       END;
	!     ELSE
	!       RETURN FALSE;
	END;
	END GetBounds;
	
	***************
	*** 214,220 ****
	END;
	
	IF (solidElt # NIL)
	!         AND TInt.FromInt (LAST (p.args^), Target.Integer.bytes, nn) THEN
	p.kind := Kind.FixedOpen;
	index := SubrangeType.New (TInt.Zero, nn, Int.T, FALSE);
	p.solidType := ArrayType.New (index, solidElt);
	--- 214,222 ----
	END;
	
	IF (solidElt # NIL)
	!         AND TInt.FromInt (LAST (p.args^), nn)
	!         AND NOT TInt.LT (nn, Target.Integer.min)
	!         AND NOT TInt.LT (Target.Integer.max, nn) THEN
	p.kind := Kind.FixedOpen;
	index := SubrangeType.New (TInt.Zero, nn, Int.T, FALSE);
	p.solidType := ArrayType.New (index, solidElt);
	***************
	*** 335,341 ****
	EVAL Type.CheckInfo (p.tipe, info);
	align := info.alignment;
	b := TInt.ToInt (nn_elts, n_elts);    <*ASSERT b*>
	!     b := TInt.FromInt (n_args, Target.Integer.bytes, nn_args);  <*ASSERT b*>
	
	(* If this is a direct structure assignment, the LHS has already
	* been prepped and compiled -- save it.
	--- 337,343 ----
	EVAL Type.CheckInfo (p.tipe, info);
	align := info.alignment;
	b := TInt.ToInt (nn_elts, n_elts);    <*ASSERT b*>
	!     b := TInt.FromInt (n_args, nn_args);  <*ASSERT b*>
	
	(* If this is a direct structure assignment, the LHS has already
	* been prepped and compiled -- save it.
	Index: m3front/src/exprs/Expr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/Expr.m3,v
	retrieving revision 1.8
	diff -c -r1.8 Expr.m3
	*** m3front/src/exprs/Expr.m3	25 Sep 2009 02:42:12 -0000	1.8
	--- m3front/src/exprs/Expr.m3	18 Feb 2010 02:30:52 -0000
	***************
	*** 98,104 ****
	GetBounds (t, min, max);
	IF    TInt.LE (TInt.Zero, min) THEN  RETURN CG.Sign.Positive;
	ELSIF TInt.LE (max, TInt.Zero) THEN  RETURN CG.Sign.Negative;
	!     ELSE                                        RETURN CG.Sign.Unknown;
	END;
	END GetSign;
	
	--- 98,104 ----
	GetBounds (t, min, max);
	IF    TInt.LE (TInt.Zero, min) THEN  RETURN CG.Sign.Positive;
	ELSIF TInt.LE (max, TInt.Zero) THEN  RETURN CG.Sign.Negative;
	!     ELSE                                 RETURN CG.Sign.Unknown;
	END;
	END GetSign;
	
	Index: m3front/src/exprs/IntegerExpr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/IntegerExpr.m3,v
	retrieving revision 1.9
	diff -c -r1.9 IntegerExpr.m3
	*** m3front/src/exprs/IntegerExpr.m3	8 Feb 2010 13:02:20 -0000	1.9
	--- m3front/src/exprs/IntegerExpr.m3	18 Feb 2010 02:30:52 -0000
	***************
	*** 38,58 ****
	VAR cache := ARRAY BOOLEAN, [-7 .. 64] OF P {ARRAY [-7 .. 64] OF P{NIL, ..},..};
	
	PROCEDURE New (type: Type.T;  READONLY value: Target.Int): Expr.T =
	!   VAR p: P;  n: INTEGER;  v: Target.Int;  t := type = LInt.T;
	BEGIN
	IF TInt.ToInt (value, n)
	AND (FIRST (cache[t]) <= n) AND (n <= LAST (cache[t])) THEN
	p := cache[t][n];
	IF (p # NIL) THEN RETURN p; END;
	END;
	!     IF type = Int.T THEN
	!       IF NOT TInt.IntI (value, Target.Integer.bytes, v) THEN RETURN NIL END;
	!     ELSIF type = LInt.T THEN
	!       IF NOT TInt.IntI (value, Target.Longint.bytes, v) THEN RETURN NIL END;
	!     ELSE RETURN NIL END;
	p := NEW (P);
	ExprRep.Init (p);
	!     p.value   := v;
	p.type    := type;
	p.checked := TRUE;
	IF TInt.ToInt (value, n)
	--- 38,59 ----
	VAR cache := ARRAY BOOLEAN, [-7 .. 64] OF P {ARRAY [-7 .. 64] OF P{NIL, ..},..};
	
	PROCEDURE New (type: Type.T;  READONLY value: Target.Int): Expr.T =
	!   VAR p: P;  n: INTEGER;  t := Type.IsSubtype (type, LInt.T);
	!       min, max: Target.Int;
	BEGIN
	IF TInt.ToInt (value, n)
	AND (FIRST (cache[t]) <= n) AND (n <= LAST (cache[t])) THEN
	p := cache[t][n];
	IF (p # NIL) THEN RETURN p; END;
	END;
	!     IF NOT Type.GetBounds (type, min, max)
	!       OR TInt.LT (value, min)
	!       OR TInt.LT (max, value) THEN
	!       <*ASSERT FALSE*>
	!     END;
	p := NEW (P);
	ExprRep.Init (p);
	!     p.value   := value;
	p.type    := type;
	p.checked := TRUE;
	IF TInt.ToInt (value, n)
	***************
	*** 94,127 ****
	END Compare;
	
	PROCEDURE Add (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF NOT TInt.Add (x, y, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN c # NIL;
	END Add;
	
	PROCEDURE Subtract (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF NOT TInt.Subtract (x, y, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN c # NIL;
	END Subtract;
	
	PROCEDURE Multiply (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF NOT TInt.Multiply (x, y, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN c # NIL;
	END Multiply;
	
	PROCEDURE Div (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF TInt.EQ (y, TInt.Zero) THEN
	--- 95,134 ----
	END Compare;
	
	PROCEDURE Add (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, min, max, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF NOT TInt.Add (x, y, res) THEN RETURN FALSE END;
	+     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	+     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN TRUE;
	END Add;
	
	PROCEDURE Subtract (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, min, max, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF NOT TInt.Subtract (x, y, res) THEN RETURN FALSE END;
	+     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	+     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN TRUE;
	END Subtract;
	
	PROCEDURE Multiply (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, min, max, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF NOT TInt.Multiply (x, y, res) THEN RETURN FALSE END;
	+     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	+     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN TRUE;
	END Multiply;
	
	PROCEDURE Div (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, min, max, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF TInt.EQ (y, TInt.Zero) THEN
	***************
	*** 129,140 ****
	RETURN FALSE;
	END;
	IF NOT TInt.Div (x, y, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN c # NIL;
	END Div;
	
	PROCEDURE Mod (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF TInt.EQ (y, TInt.Zero) THEN
	--- 136,149 ----
	RETURN FALSE;
	END;
	IF NOT TInt.Div (x, y, res) THEN RETURN FALSE END;
	+     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	+     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN TRUE;
	END Div;
	
	PROCEDURE Mod (a, b: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, y, min, max, res: Target.Int;  t: Type.T;
	BEGIN
	IF NOT SplitPair (a, b, x, y, t) THEN RETURN FALSE END;
	IF TInt.EQ (y, TInt.Zero) THEN
	***************
	*** 142,190 ****
	RETURN FALSE;
	END;
	IF NOT TInt.Mod (x, y, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN c # NIL;
	END Mod;
	
	PROCEDURE Negate (a: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR res: Target.Int;
	BEGIN
	!     TYPECASE a OF
	!     | NULL => RETURN FALSE;
	!     | P(p) => IF NOT TInt.Subtract (TInt.Zero, p.value, res) THEN
	!                 RETURN FALSE;
	!               END;
	!               c := New (p.type, res);  RETURN c # NIL;
	!     ELSE      RETURN FALSE;
	!     END;
	END Negate;
	
	PROCEDURE Abs (a: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR res: Target.Int;
	BEGIN
	!     TYPECASE a OF
	!     | NULL => RETURN FALSE;
	!     | P(p) => IF TInt.LE (TInt.Zero, p.value) THEN
	!                 c := a;  RETURN TRUE;
	!               END;
	!               IF NOT TInt.Subtract (TInt.Zero, p.value, res) THEN
	!                 RETURN FALSE;
	!               END;
	!               c := New (p.type, res);  RETURN c # NIL;
	!     ELSE      RETURN FALSE;
	END;
	END Abs;
	
	PROCEDURE ToInt (a: Expr.T;  VAR i: INTEGER): BOOLEAN =
	BEGIN
	!     TYPECASE a OF
	!     | NULL => RETURN FALSE;
	!     | P(p) => IF NOT TInt.ToInt (p.value, i) THEN
	!                 RETURN FALSE;
	!               END;
	!               RETURN TRUE;
	!     ELSE      RETURN FALSE;
	!     END;
	END ToInt;
	
	PROCEDURE SplitPair (a, b: Expr.T;  VAR x, y: Target.Int;  VAR t: Type.T):
	--- 151,194 ----
	RETURN FALSE;
	END;
	IF NOT TInt.Mod (x, y, res) THEN RETURN FALSE END;
	+     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	+     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := New (t, res);
	!     RETURN TRUE;
	END Mod;
	
	PROCEDURE Negate (a: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, min, max, res: Target.Int;  t: Type.T;
	BEGIN
	!     IF NOT Split (a, x, t) THEN RETURN FALSE END;
	!     IF NOT TInt.Subtract (TInt.Zero, x, res) THEN RETURN FALSE END;
	!     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	!     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	!     c := New (t, res);
	!     RETURN TRUE;
	END Negate;
	
	PROCEDURE Abs (a: Expr.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x, min, max, res: Target.Int;  t: Type.T;
	BEGIN
	!     IF NOT Split (a, x, t) THEN RETURN FALSE END;
	!     IF TInt.LT (x, TInt.Zero) THEN
	!       IF NOT TInt.Subtract (TInt.Zero, x, res) THEN RETURN FALSE END;
	!       IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	!       IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	!       c := New (t, res);
	!     ELSE
	!       c := a;
	END;
	+     RETURN TRUE;
	END Abs;
	
	PROCEDURE ToInt (a: Expr.T;  VAR i: INTEGER): BOOLEAN =
	+   VAR x: Target.Int;  t: Type.T;
	BEGIN
	!     IF NOT Split (a, x, t) THEN RETURN FALSE END;
	!     IF NOT TInt.ToInt (x, i) THEN RETURN FALSE END;
	!     RETURN TRUE;
	END ToInt;
	
	PROCEDURE SplitPair (a, b: Expr.T;  VAR x, y: Target.Int;  VAR t: Type.T):
	Index: m3front/src/exprs/ModExpr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/ModExpr.m3,v
	retrieving revision 1.5
	diff -c -r1.5 ModExpr.m3
	*** m3front/src/exprs/ModExpr.m3	4 May 2008 11:03:46 -0000	1.5
	--- m3front/src/exprs/ModExpr.m3	18 Feb 2010 02:30:52 -0000
	***************
	*** 181,202 ****
	END Fold;
	
	PROCEDURE GetBounds (p: P;  VAR min, max: Target.Int) =
	!   VAR min_b, max_b: Target.Int;
	!       OneI := Target.Int{Target.Integer.bytes, Target.IBytes{1,0,..}};
	!       OneL := Target.Int{Target.Longint.bytes, Target.IBytes{1,0,..}};
	!       One := ARRAY[Class.cINT..Class.cLINT] OF Target.Int { OneI, OneL };
	!       MaxI := Target.Integer.max;
	!       MaxL := Target.Longint.max;
	!       Max := ARRAY [Class.cINT..Class.cLINT] OF Target.Int { MaxI, MaxL };
	BEGIN
	IF (p.class = Class.cINT) OR (p.class = Class.cLINT) THEN
	Expr.GetBounds (p.b, min_b, max_b);
	IF TInt.LT (min_b, TInt.Zero) OR TInt.LT (max_b, TInt.Zero) THEN
	ExprRep.NoBounds (p, min, max);
	ELSE
	min := TInt.Zero;
	!         IF NOT TInt.Subtract (max_b, One[p.class], max) THEN
	!           max := Max[p.class];
	END;
	END;
	ELSE
	--- 181,198 ----
	END Fold;
	
	PROCEDURE GetBounds (p: P;  VAR min, max: Target.Int) =
	!   VAR tmin, tmax, min_b, max_b: Target.Int;
	BEGIN
	IF (p.class = Class.cINT) OR (p.class = Class.cLINT) THEN
	+       EVAL Type.GetBounds (p.type, tmin, tmax);
	Expr.GetBounds (p.b, min_b, max_b);
	IF TInt.LT (min_b, TInt.Zero) OR TInt.LT (max_b, TInt.Zero) THEN
	ExprRep.NoBounds (p, min, max);
	ELSE
	min := TInt.Zero;
	!         IF NOT TInt.Subtract (max_b, TInt.One, max)
	!           OR TInt.LT (max, tmin) OR TInt.LT (tmax, max) THEN
	!           max := tmax;
	END;
	END;
	ELSE
	Index: m3front/src/exprs/ReelExpr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/ReelExpr.m3,v
	retrieving revision 1.6
	diff -c -r1.6 ReelExpr.m3
	*** m3front/src/exprs/ReelExpr.m3	8 Feb 2010 12:03:31 -0000	1.6
	--- m3front/src/exprs/ReelExpr.m3	18 Feb 2010 02:30:52 -0000
	***************
	*** 9,15 ****
	MODULE ReelExpr;
	
	IMPORT M3, CG, Expr, ExprRep, Type, Target, TInt, TFloat;
	! IMPORT M3Buf, Int, LInt, Reel, LReel, EReel, IntegerExpr;
	
	TYPE
	P = Expr.T OBJECT
	--- 9,15 ----
	MODULE ReelExpr;
	
	IMPORT M3, CG, Expr, ExprRep, Type, Target, TInt, TFloat;
	! IMPORT M3Buf, Reel, LReel, EReel, IntegerExpr;
	
	TYPE
	P = Expr.T OBJECT
	***************
	*** 172,222 ****
	END Abs;
	
	PROCEDURE Floor (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x: Target.Float;  res: Target.Int;  n: CARDINAL;
	BEGIN
	-     IF    t = Int.T  THEN n := Target.Integer.bytes;
	-     ELSIF t = LInt.T THEN n := Target.Longint.bytes;
	-     ELSE RETURN FALSE END;
	IF NOT Split (a, x) THEN RETURN FALSE END;
	!     IF NOT TInt.FromInt (TFloat.Floor (x), n, res) THEN RETURN FALSE END;
	c := IntegerExpr.New (t, res);
	!     RETURN c # NIL;
	END Floor;
	
	PROCEDURE Ceiling (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x: Target.Float;  res: Target.Int;  n: CARDINAL;
	BEGIN
	-     IF    t = Int.T  THEN n := Target.Integer.bytes;
	-     ELSIF t = LInt.T THEN n := Target.Longint.bytes;
	-     ELSE RETURN FALSE END;
	IF NOT Split (a, x) THEN RETURN FALSE END;
	!     IF NOT TInt.FromInt (TFloat.Ceiling (x), n, res) THEN RETURN FALSE END;
	c := IntegerExpr.New (t, res);
	!     RETURN c # NIL;
	END Ceiling;
	
	PROCEDURE Trunc (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x: Target.Float;  res: Target.Int;  n: CARDINAL;
	BEGIN
	-     IF    t = Int.T  THEN n := Target.Integer.bytes;
	-     ELSIF t = LInt.T THEN n := Target.Longint.bytes;
	-     ELSE RETURN FALSE END;
	IF NOT Split (a, x) THEN RETURN FALSE END;
	!     IF NOT TInt.FromInt (TFloat.Trunc (x), n, res) THEN RETURN FALSE END;
	c := IntegerExpr.New (t, res);
	!     RETURN c # NIL;
	END Trunc;
	
	PROCEDURE Round (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x: Target.Float;  res: Target.Int;  n: CARDINAL;
	BEGIN
	-     IF    t = Int.T  THEN n := Target.Integer.bytes;
	-     ELSIF t = LInt.T THEN n := Target.Longint.bytes;
	-     ELSE RETURN FALSE END;
	IF NOT Split (a, x) THEN RETURN FALSE END;
	!     IF NOT TInt.FromInt (TFloat.Round (x), n, res) THEN RETURN FALSE END;
	c := IntegerExpr.New (t, res);
	!     RETURN c # NIL;
	END Round;
	
	PROCEDURE Float (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	--- 172,218 ----
	END Abs;
	
	PROCEDURE Floor (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x: Target.Float;  min, max, res: Target.Int;
	BEGIN
	IF NOT Split (a, x) THEN RETURN FALSE END;
	!     IF NOT TInt.FromInt (TFloat.Floor (x), res) THEN RETURN FALSE END;
	!     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	!     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := IntegerExpr.New (t, res);
	!     RETURN TRUE;
	END Floor;
	
	PROCEDURE Ceiling (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x: Target.Float;  min, max, res: Target.Int;
	BEGIN
	IF NOT Split (a, x) THEN RETURN FALSE END;
	!     IF NOT TInt.FromInt (TFloat.Ceiling (x), res) THEN RETURN FALSE END;
	!     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	!     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := IntegerExpr.New (t, res);
	!     RETURN TRUE;
	END Ceiling;
	
	PROCEDURE Trunc (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x: Target.Float;  min, max, res: Target.Int;
	BEGIN
	IF NOT Split (a, x) THEN RETURN FALSE END;
	!     IF NOT TInt.FromInt (TFloat.Trunc (x), res) THEN RETURN FALSE END;
	!     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	!     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := IntegerExpr.New (t, res);
	!     RETURN TRUE;
	END Trunc;
	
	PROCEDURE Round (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	!   VAR x: Target.Float;  min, max, res: Target.Int;
	BEGIN
	IF NOT Split (a, x) THEN RETURN FALSE END;
	!     IF NOT TInt.FromInt (TFloat.Round (x), res) THEN RETURN FALSE END;
	!     IF NOT Type.GetBounds (t, min, max) THEN RETURN FALSE END;
	!     IF TInt.LT (res, min) OR TInt.LT (max, res) THEN RETURN FALSE END;
	c := IntegerExpr.New (t, res);
	!     RETURN TRUE;
	END Round;
	
	PROCEDURE Float (a: Expr.T;  t: Type.T;  VAR c: Expr.T): BOOLEAN =
	Index: m3front/src/exprs/SetExpr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/SetExpr.m3,v
	retrieving revision 1.6
	diff -c -r1.6 SetExpr.m3
	*** m3front/src/exprs/SetExpr.m3	2 Jan 2010 21:31:48 -0000	1.6
	--- m3front/src/exprs/SetExpr.m3	18 Feb 2010 02:30:52 -0000
	***************
	*** 10,16 ****
	
	IMPORT M3, CG, Expr, ExprRep, Type, Error, IntegerExpr, EnumExpr;
	IMPORT RangeExpr, KeywordExpr, SetType, AssignStmt, CheckExpr;
	! IMPORT M3ID, Target, TInt, TWord, Bool, M3Buf, Module;
	
	TYPE
	Node = REF RECORD
	--- 10,16 ----
	
	IMPORT M3, CG, Expr, ExprRep, Type, Error, IntegerExpr, EnumExpr;
	IMPORT RangeExpr, KeywordExpr, SetType, AssignStmt, CheckExpr;
	! IMPORT M3ID, Target, TInt, TWord, Bool, M3Buf, Module, Text;
	
	TYPE
	Node = REF RECORD
	***************
	*** 564,579 ****
	END;
	END Compile;
	
	- PROCEDURE TargetIntToDiagnosticText(name: TEXT; a: Target.Int): TEXT =
	-   VAR t := "";
	-       b: INTEGER;
	-   BEGIN
	-     IF NOT TInt.ToInt(a, b) THEN
	-       t := "**";
	-     END;
	-     RETURN t & name & ":" & Target.TargetIntToDiagnosticText(a);
	-   END TargetIntToDiagnosticText;
	-
	PROCEDURE CompileBig (p: P;  VAR info: Type.Info): CG.Var =
	VAR
	range        : Type.T;
	--- 564,569 ----
	***************
	*** 590,603 ****
	n            : Node;
	b            : BOOLEAN;
	tmp          : Target.Int;
	BEGIN
	b := SetType.Split (p.tipe, range); <* ASSERT b *>
	EVAL Type.GetBounds (range, min_T, max_T);
	IF NOT TInt.ToInt (min_T, minT)
	OR NOT TInt.ToInt (max_T, maxT) THEN
	!       Error.Msg ("set domain too large ("
	!             & TargetIntToDiagnosticText("min", min_T)
	!             & "," & TargetIntToDiagnosticText("max", max_T) & ")");
	minT := FIRST (INTEGER);
	maxT := LAST (INTEGER);
	END;
	--- 580,594 ----
	n            : Node;
	b            : BOOLEAN;
	tmp          : Target.Int;
	+     buf: ARRAY [0..TInt.Size] OF CHAR;
	BEGIN
	b := SetType.Split (p.tipe, range); <* ASSERT b *>
	EVAL Type.GetBounds (range, min_T, max_T);
	IF NOT TInt.ToInt (min_T, minT)
	OR NOT TInt.ToInt (max_T, maxT) THEN
	!       Error.Msg ("set domain too large (" &
	!         Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(min_T, buf))) & ".." &
	!         Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(max_T, buf))) & ")");
	minT := FIRST (INTEGER);
	maxT := LAST (INTEGER);
	END;
	***************
	*** 659,666 ****
	
	PROCEDURE EmitAssign (set: CG.Var;  index: INTEGER;
	READONLY value: Target.Int) =
	BEGIN
	!     CG.Load_integer (Target.Integer.cg_type, value);
	CG.Store_int (Target.Integer.cg_type, set, index * Grain);
	<* ASSERT Grain = Target.Integer.size *>
	END EmitAssign;
	--- 650,659 ----
	
	PROCEDURE EmitAssign (set: CG.Var;  index: INTEGER;
	READONLY value: Target.Int) =
	+   VAR tmp := value;
	BEGIN
	!     TInt.Chop (tmp, Target.Integer.bytes);
	!     CG.Load_integer (Target.Integer.cg_type, tmp);
	CG.Store_int (Target.Integer.cg_type, set, index * Grain);
	<* ASSERT Grain = Target.Integer.size *>
	END EmitAssign;
	***************
	*** 689,694 ****
	--- 682,688 ----
	n            : Node;
	b            : BOOLEAN;
	tmp          : Target.Int;
	+     buf: ARRAY [0..TInt.Size] OF CHAR;
	BEGIN
	Type.Compile (p.tipe);
	nWords  := info.size DIV Grain;
	***************
	*** 699,707 ****
	EVAL Type.GetBounds (range, min_T, max_T);
	IF NOT TInt.ToInt (min_T, minT)
	OR NOT TInt.ToInt (max_T, maxT) THEN
	!       Error.Msg ("set domain too large ("
	!             & TargetIntToDiagnosticText("min", min_T)
	!             & "," & TargetIntToDiagnosticText("max", max_T) & ")");
	minT := FIRST (INTEGER);
	maxT := LAST (INTEGER);
	END;
	--- 693,701 ----
	EVAL Type.GetBounds (range, min_T, max_T);
	IF NOT TInt.ToInt (min_T, minT)
	OR NOT TInt.ToInt (max_T, maxT) THEN
	!       Error.Msg ("set domain too large (" &
	!         Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(min_T, buf))) & ".." &
	!         Text.FromChars (SUBARRAY(buf, 0, TInt.ToChars(max_T, buf))) & ")");
	minT := FIRST (INTEGER);
	maxT := LAST (INTEGER);
	END;
	***************
	*** 793,800 ****
	IF (w1 # curWord) THEN
	(* write the mask we've accumulated *)
	IF NOT TInt.EQ (curMask, TInt.Zero) THEN
	CG.Init_int (offset + curWord*Target.Integer.pack,
	!                         Target.Integer.size, curMask, is_const);
	END;
	curWord := w1;
	curMask := TInt.Zero;
	--- 787,796 ----
	IF (w1 # curWord) THEN
	(* write the mask we've accumulated *)
	IF NOT TInt.EQ (curMask, TInt.Zero) THEN
	+           tmp := curMask;
	+           TInt.Chop (tmp, Target.Integer.bytes);
	CG.Init_int (offset + curWord*Target.Integer.pack,
	!                         Target.Integer.size, tmp, is_const);
	END;
	curWord := w1;
	curMask := TInt.Zero;
	***************
	*** 802,812 ****
	IF (w1 # w2) THEN
	(* write the full words [w1..w2-1] *)
	TWord.Or (curMask, left [b1], tmp);
	CG.Init_int (offset + w1 * Target.Integer.pack, Target.Integer.size,
	tmp, is_const);
	FOR i := w1 + 1 TO w2 - 1 DO
	CG.Init_int (offset + i * Target.Integer.pack, Target.Integer.size,
	!                        full, is_const);
	END;
	curWord := w2;
	curMask := right [b2];
	--- 798,811 ----
	IF (w1 # w2) THEN
	(* write the full words [w1..w2-1] *)
	TWord.Or (curMask, left [b1], tmp);
	+         TInt.Chop (tmp, Target.Integer.bytes);
	CG.Init_int (offset + w1 * Target.Integer.pack, Target.Integer.size,
	tmp, is_const);
	FOR i := w1 + 1 TO w2 - 1 DO
	+           tmp := full;
	+           TInt.Chop (tmp, Target.Integer.bytes);
	CG.Init_int (offset + i * Target.Integer.pack, Target.Integer.size,
	!                        tmp, is_const);
	END;
	curWord := w2;
	curMask := right [b2];
	***************
	*** 819,837 ****
	
	(* write the last mask *)
	IF NOT TInt.EQ (curMask, TInt.Zero) THEN
	CG.Init_int (offset + curWord * Target.Integer.pack,
	!                    Target.Integer.size, curMask, is_const);
	END;
	END GenLiteral;
	
	PROCEDURE Init () =
	-   VAR Zero := Target.Int{Target.Integer.bytes, Target.IBytes{0,..}};
	BEGIN
	Grain := MAX (Target.Integer.size, Target.Set_grain);
	!     TWord.Not (Zero, full);
	FOR i := 0 TO Grain - 1 DO
	TWord.Shift (full, i + 1 - Grain, right [i]);
	TWord.Shift (full, i, left [i]);
	END;
	END Init;
	
	--- 818,840 ----
	
	(* write the last mask *)
	IF NOT TInt.EQ (curMask, TInt.Zero) THEN
	+       tmp := curMask;
	+       TInt.Chop (tmp, Target.Integer.bytes);
	CG.Init_int (offset + curWord * Target.Integer.pack,
	!                    Target.Integer.size, tmp, is_const);
	END;
	END GenLiteral;
	
	PROCEDURE Init () =
	BEGIN
	Grain := MAX (Target.Integer.size, Target.Set_grain);
	!     TWord.Not (TInt.Zero, full);
	!     TWord.And (full, Target.Word.max, full);
	FOR i := 0 TO Grain - 1 DO
	TWord.Shift (full, i + 1 - Grain, right [i]);
	+       TWord.And (right[i], Target.Word.max, right[i]);
	TWord.Shift (full, i, left [i]);
	+       TWord.And (left[i], Target.Word.max, left[i]);
	END;
	END Init;
	
	Index: m3front/src/exprs/SubtractExpr.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/exprs/SubtractExpr.m3,v
	retrieving revision 1.5
	diff -c -r1.5 SubtractExpr.m3
	*** m3front/src/exprs/SubtractExpr.m3	10 Jan 2010 05:12:18 -0000	1.5
	--- m3front/src/exprs/SubtractExpr.m3	18 Feb 2010 02:30:52 -0000
	***************
	*** 62,68 ****
	VAR ta: Type.T;
	BEGIN
	ta := Type.Base (Expr.TypeOf (p.a));
	!     IF (p.extended) THEN
	ta := Int.T;
	ELSIF Type.IsSubtype (ta, Addr.T) AND
	Type.IsSubtype (Type.Base (Expr.TypeOf (p.b)), Addr.T) THEN
	--- 62,68 ----
	VAR ta: Type.T;
	BEGIN
	ta := Type.Base (Expr.TypeOf (p.a));
	!     IF (p.extended) AND EnumType.Is (ta) THEN
	ta := Int.T;
	ELSIF Type.IsSubtype (ta, Addr.T) AND
	Type.IsSubtype (Type.Base (Expr.TypeOf (p.b)), Addr.T) THEN
	***************
	*** 189,195 ****
	ELSIF (p.extended)
	AND EnumExpr.Split (e1, x1, t1)
	AND IntegerExpr.Split (e2, x2, t1)
	!       AND TInt.Subtract (x1, x2, x3) THEN
	e3 := IntegerExpr.New (t1, x3);
	ELSIF ReelExpr.Subtract    (e1, e2, e3) THEN
	ELSIF AddressExpr.Subtract (e1, e2, e3) THEN
	--- 189,197 ----
	ELSIF (p.extended)
	AND EnumExpr.Split (e1, x1, t1)
	AND IntegerExpr.Split (e2, x2, t1)
	!       AND TInt.Subtract (x1, x2, x3)
	!       AND NOT TInt.LT (x3, Target.Integer.min)
	!       AND NOT TInt.LT (Target.Integer.max, x3) THEN
	e3 := IntegerExpr.New (t1, x3);
	ELSIF ReelExpr.Subtract    (e1, e2, e3) THEN
	ELSIF AddressExpr.Subtract (e1, e2, e3) THEN
	***************
	*** 205,211 ****
	Expr.GetBounds (p.a, min_a, max_a);
	Expr.GetBounds (p.b, min_b, max_b);
	IF TInt.Subtract (min_a, max_b, smin)
	!       AND TInt.Subtract (max_a, min_b, smax) THEN
	IF TInt.LT (min, smin) THEN min := smin END;
	IF TInt.LT (smax, max) THEN max := smax END;
	END;
	--- 207,215 ----
	Expr.GetBounds (p.a, min_a, max_a);
	Expr.GetBounds (p.b, min_b, max_b);
	IF TInt.Subtract (min_a, max_b, smin)
	!       AND NOT TInt.LT (smin, min) AND NOT TInt.LT (max, smin)
	!       AND TInt.Subtract (max_a, min_b, smax)
	!       AND NOT TInt.LT (smax, min) AND NOT TInt.LT (max, smax) THEN
	IF TInt.LT (min, smin) THEN min := smin END;
	IF TInt.LT (smax, max) THEN max := smax END;
	END;
	Index: m3front/src/misc/CG.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/CG.m3,v
	retrieving revision 1.35
	diff -c -r1.35 CG.m3
	*** m3front/src/misc/CG.m3	15 Feb 2010 05:07:07 -0000	1.35
	--- m3front/src/misc/CG.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 940,946 ****
	(* send out some number of bytes *)
	EVAL FindInitType (n_bytes, init_pc, t);
	size := TargetMap.CG_Size[t];
	!         excess := Target.Longint.size - size;
	IF (excess = 0) THEN
	cg.init_int (init_pc DIV Target.Byte, init_bits, t);
	init_bits := TInt.Zero;
	--- 940,946 ----
	(* send out some number of bytes *)
	EVAL FindInitType (n_bytes, init_pc, t);
	size := TargetMap.CG_Size[t];
	!         excess := TWord.Size - size;
	IF (excess = 0) THEN
	cg.init_int (init_pc DIV Target.Byte, init_bits, t);
	init_bits := TInt.Zero;
	***************
	*** 984,1001 ****
	
	PROCEDURE Init_int (o: Offset;  s: Size;  READONLY value: Target.Int;
	is_const: BOOLEAN) =
	!   VAR bit_offset: CARDINAL;  itype: Type;  v, tmp: Target.Int;
	BEGIN
	IF (NOT in_init) THEN
	PushPending (NEW (IntNode, o := o, s := s, v := value), is_const);
	RETURN;
	END;
	-     EVAL TInt.IntI (value, Target.Longint.bytes, v);
	
	AdvanceInit (o);
	IF Target.Little_endian
	THEN bit_offset := o - init_pc;
	!       ELSE bit_offset := Target.Longint.size - (o - init_pc) - s;
	END;
	
	IF (o = init_pc)
	--- 984,1000 ----
	
	PROCEDURE Init_int (o: Offset;  s: Size;  READONLY value: Target.Int;
	is_const: BOOLEAN) =
	!   VAR bit_offset: CARDINAL;  itype: Type;  tmp: Target.Int;
	BEGIN
	IF (NOT in_init) THEN
	PushPending (NEW (IntNode, o := o, s := s, v := value), is_const);
	RETURN;
	END;
	
	AdvanceInit (o);
	IF Target.Little_endian
	THEN bit_offset := o - init_pc;
	!       ELSE bit_offset := TWord.Size - (o - init_pc) - s;
	END;
	
	IF (o = init_pc)
	***************
	*** 1003,1010 ****
	AND (FindInitType (s DIV Target.Byte, init_pc, itype))
	AND (TargetMap.CG_Size[itype] = s) THEN
	(* simple, aligned integer initialization *)
	!       cg.init_int (o DIV Target.Byte, v, itype);
	!     ELSIF TWord.Insert (init_bits, v, bit_offset, s, tmp) THEN
	init_bits := tmp;
	ELSE
	Err ("unable to stuff bit field value??");
	--- 1002,1009 ----
	AND (FindInitType (s DIV Target.Byte, init_pc, itype))
	AND (TargetMap.CG_Size[itype] = s) THEN
	(* simple, aligned integer initialization *)
	!       cg.init_int (o DIV Target.Byte, value, itype);
	!     ELSIF TWord.Insert (init_bits, value, bit_offset, s, tmp) THEN
	init_bits := tmp;
	ELSE
	Err ("unable to stuff bit field value??");
	***************
	*** 1013,1021 ****
	END Init_int;
	
	PROCEDURE Init_intt (o: Offset;  s: Size;  value: INTEGER;  is_const: BOOLEAN) =
	!   VAR val: Target.Int;  b := TInt.FromInt (value, Target.Integer.bytes, val);
	BEGIN
	!     IF NOT b THEN ErrI (value, "integer const not representable") END;
	Init_int (o, s, val, is_const);
	END Init_intt;
	
	--- 1012,1023 ----
	END Init_int;
	
	PROCEDURE Init_intt (o: Offset;  s: Size;  value: INTEGER;  is_const: BOOLEAN) =
	!   VAR val: Target.Int;  b := TInt.FromInt (value, val);
	BEGIN
	!     IF NOT b
	!       OR TInt.LT (val, Target.Integer.min)
	!       OR TInt.LT (Target.Integer.max, val)
	!     THEN ErrI (value, "integer const not representable") END;
	Init_int (o, s, val, is_const);
	END Init_intt;
	
	***************
	*** 1807,1815 ****
	END Load_byte_address;
	
	PROCEDURE Load_intt (i: INTEGER) =
	!   VAR val: Target.Int;  b := TInt.FromInt (i, Target.Integer.bytes, val);
	BEGIN
	!     IF NOT b THEN ErrI (i, "integer not representable") END;
	Load_integer (Target.Integer.cg_type, val);
	END Load_intt;
	
	--- 1809,1820 ----
	END Load_byte_address;
	
	PROCEDURE Load_intt (i: INTEGER) =
	!   VAR val: Target.Int;  b := TInt.FromInt (i, val);
	BEGIN
	!     IF NOT b
	!       OR TInt.LT (val, Target.Integer.min)
	!       OR TInt.LT (Target.Integer.max, val)
	!     THEN ErrI (i, "integer not representable") END;
	Load_integer (Target.Integer.cg_type, val);
	END Load_intt;
	
	***************
	*** 2760,2768 ****
	END AsBytes;
	
	PROCEDURE Push_int (i: INTEGER) =
	!   VAR val: Target.Int;  b := TInt.FromInt (i, Target.Integer.bytes, val);
	BEGIN
	!     IF NOT b THEN ErrI (i, "integer not representable") END;
	cg.load_integer (Target.Integer.cg_type, val);
	END Push_int;
	
	--- 2765,2776 ----
	END AsBytes;
	
	PROCEDURE Push_int (i: INTEGER) =
	!   VAR val: Target.Int;  b := TInt.FromInt (i, val);
	BEGIN
	!     IF NOT b
	!       OR TInt.LT (val, Target.Integer.min)
	!       OR TInt.LT (Target.Integer.max, val)
	!     THEN ErrI (i, "integer not representable") END;
	cg.load_integer (Target.Integer.cg_type, val);
	END Push_int;
	
	Index: m3front/src/misc/Scanner.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/Scanner.m3,v
	retrieving revision 1.7
	diff -c -r1.7 Scanner.m3
	*** m3front/src/misc/Scanner.m3	4 May 2008 11:03:47 -0000	1.7
	--- m3front/src/misc/Scanner.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 509,515 ****
	
	IF (ch = '_') THEN
	(* scan a based integer *)
	!       IF    NOT TInt.New (SUBARRAY (buf, 0, len), Target.Integer.bytes, val)
	OR NOT TInt.ToInt (val, base)
	OR (base < 2)
	OR (16 < base) THEN
	--- 509,515 ----
	
	IF (ch = '_') THEN
	(* scan a based integer *)
	!       IF    NOT TInt.New (SUBARRAY (buf, 0, len), val)
	OR NOT TInt.ToInt (val, base)
	OR (base < 2)
	OR (16 < base) THEN
	***************
	*** 524,542 ****
	END;
	IF (ch = 'l') OR (ch = 'L') THEN
	GetCh (); (* eat the precision character *)
	!         IF (len = 0) OR NOT (TWord.New (SUBARRAY (buf, 0, len), base,
	!                                         Target.Long.bytes, val)) THEN
	Error.Msg ("illegal based LONGINT literal, zero used");
	val := TInt.Zero;
	END;
	cur.token := TK.tLONGINTCONST;
	cur.int   := val;
	ELSE
	!         IF (len = 0) OR NOT (TWord.New (SUBARRAY (buf, 0, len), base,
	!                                         Target.Word.bytes, val)) THEN
	Error.Msg ("illegal based INTEGER literal, zero used");
	val := TInt.Zero;
	END;
	cur.token := TK.tINTEGERCONST;
	cur.int   := val;
	END;
	--- 524,546 ----
	END;
	IF (ch = 'l') OR (ch = 'L') THEN
	GetCh (); (* eat the precision character *)
	!         IF (len = 0)
	!           OR NOT (TWord.New (SUBARRAY (buf, 0, len), base, val))
	!           OR TWord.LT (Target.Long.max, val) THEN
	Error.Msg ("illegal based LONGINT literal, zero used");
	val := TInt.Zero;
	END;
	+         TInt.Chop (val, Target.Longint.bytes);
	cur.token := TK.tLONGINTCONST;
	cur.int   := val;
	ELSE
	!         IF (len = 0)
	!           OR NOT TWord.New (SUBARRAY (buf, 0, len), base, val)
	!           OR TWord.LT (Target.Word.max, val) THEN
	Error.Msg ("illegal based INTEGER literal, zero used");
	val := TInt.Zero;
	END;
	+         TInt.Chop (val, Target.Integer.bytes);
	cur.token := TK.tINTEGERCONST;
	cur.int   := val;
	END;
	***************
	*** 551,558 ****
	(*****  Rd.UnGetChar (input);  *****)
	DEC (input_ptr);  input_buf[input_ptr] := ORD ('.');
	
	!         IF NOT TInt.New (SUBARRAY (buf, 0, len-1),
	!                          Target.Integer.bytes, val) THEN
	Error.Msg ("illegal INTEGER literal, zero used");
	val := TInt.Zero;
	END;
	--- 555,563 ----
	(*****  Rd.UnGetChar (input);  *****)
	DEC (input_ptr);  input_buf[input_ptr] := ORD ('.');
	
	!         IF NOT TInt.New (SUBARRAY (buf, 0, len-1), val)
	!           OR TInt.LT (val, Target.Integer.min)
	!           OR TInt.LT (Target.Integer.max, val) THEN
	Error.Msg ("illegal INTEGER literal, zero used");
	val := TInt.Zero;
	END;
	***************
	*** 617,632 ****
	(* already scanned a decimal integer *)
	IF (ch = 'l') OR (ch = 'L') THEN
	GetCh (); (* eat the precision character *)
	!         IF NOT TInt.New (SUBARRAY (buf, 0, len),
	!                          Target.Longint.bytes, val) THEN
	Error.Msg ("illegal LONGINT literal, zero used");
	val := TInt.Zero;
	END;
	cur.token := TK.tLONGINTCONST;
	cur.int   := val;
	ELSE
	!         IF NOT TInt.New (SUBARRAY (buf, 0, len),
	!                          Target.Integer.bytes, val) THEN
	Error.Msg ("illegal INTEGER literal, zero used");
	val := TInt.Zero;
	END;
	--- 622,639 ----
	(* already scanned a decimal integer *)
	IF (ch = 'l') OR (ch = 'L') THEN
	GetCh (); (* eat the precision character *)
	!         IF NOT TInt.New (SUBARRAY (buf, 0, len), val)
	!           OR TInt.LT (val, Target.Longint.min)
	!           OR TInt.LT (Target.Longint.max, val) THEN
	Error.Msg ("illegal LONGINT literal, zero used");
	val := TInt.Zero;
	END;
	cur.token := TK.tLONGINTCONST;
	cur.int   := val;
	ELSE
	!         IF NOT TInt.New (SUBARRAY (buf, 0, len), val)
	!           OR TInt.LT (val, Target.Integer.min)
	!           OR TInt.LT (Target.Integer.max, val) THEN
	Error.Msg ("illegal INTEGER literal, zero used");
	val := TInt.Zero;
	END;
	***************
	*** 675,681 ****
	THEN Error.Msg ("missing closing quote on character literal");
	ELSE GetCh ();
	END;
	!     IF NOT TInt.FromInt (val, Target.Integer.bytes, cur.int) THEN
	Error.Msg ("illegal character literal");
	END;
	END ScanChar;
	--- 682,688 ----
	THEN Error.Msg ("missing closing quote on character literal");
	ELSE GetCh ();
	END;
	!     IF NOT TInt.FromInt (val, cur.int) THEN
	Error.Msg ("illegal character literal");
	END;
	END ScanChar;
	Index: m3front/src/misc/TipeDesc.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/misc/TipeDesc.m3,v
	retrieving revision 1.5
	diff -c -r1.5 TipeDesc.m3
	*** m3front/src/misc/TipeDesc.m3	1 Apr 2008 00:02:58 -0000	1.5
	--- m3front/src/misc/TipeDesc.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 145,155 ****
	
	PROCEDURE AddBigX (READONLY ii: Target.Int) =
	CONST Sign = ARRAY BOOLEAN OF INTEGER { 16_40, 16_c0 };
	!   VAR x: ARRAY [0..LAST (Target.IBytes)] OF [0..255];
	key, n_bytes: INTEGER;  i := ii;
	BEGIN
	key := Sign [TInt.LT (i, TInt.Zero)];
	!     IF (key # 16_40) THEN TWord.Subtract (TInt.Zero, ii, i); END;
	
	(* extract the bytes *)
	n_bytes := TInt.ToBytes (i, x);
	--- 145,158 ----
	
	PROCEDURE AddBigX (READONLY ii: Target.Int) =
	CONST Sign = ARRAY BOOLEAN OF INTEGER { 16_40, 16_c0 };
	!   VAR x: ARRAY [0..LAST (Target.Int)] OF [0..255];
	key, n_bytes: INTEGER;  i := ii;
	BEGIN
	key := Sign [TInt.LT (i, TInt.Zero)];
	!     IF (key # 16_40) THEN
	!       TWord.Subtract (TInt.Zero, ii, i);
	!       TInt.Chop (i, Target.Integer.bytes);
	!     END;
	
	(* extract the bytes *)
	n_bytes := TInt.ToBytes (i, x);
	Index: m3front/src/stmts/CaseStmt.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/stmts/CaseStmt.m3,v
	retrieving revision 1.4
	diff -c -r1.4 CaseStmt.m3
	*** m3front/src/stmts/CaseStmt.m3	4 May 2008 11:03:48 -0000	1.4
	--- m3front/src/stmts/CaseStmt.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 247,253 ****
	
	PROCEDURE CompleteTree (t: Tree;  min, max: Target.Int): BOOLEAN =
	VAR x, y: Target.Int;
	-       One := Target.Int{Target.Integer.bytes, Target.IBytes{1,0,..}};
	BEGIN
	WHILE (t # NIL) DO
	IF TInt.LT (t.max, min) OR TInt.LT (max, t.min) THEN
	--- 247,252 ----
	***************
	*** 256,273 ****
	IF    TInt.Subtract (t.min, min, x)
	AND TInt.Subtract (max, t.max, y)
	AND TInt.LT (y, x) THEN
	!         IF TInt.Add (t.max, One, x) THEN
	IF NOT CompleteTree (t.greater, x, max) THEN RETURN FALSE END;
	END;
	!         IF NOT TInt.Subtract (t.min, One, max) THEN
	RETURN TRUE;
	END;
	t := t.less;
	ELSE
	!         IF TInt.Subtract (t.min, One, x) THEN
	IF NOT CompleteTree (t.less, min, x) THEN RETURN FALSE END;
	END;
	!         IF NOT TInt.Add (t.max, One, min) THEN
	RETURN TRUE;
	END;
	t := t.greater;
	--- 255,280 ----
	IF    TInt.Subtract (t.min, min, x)
	AND TInt.Subtract (max, t.max, y)
	AND TInt.LT (y, x) THEN
	!         IF TInt.Add (t.max, TInt.One, x)
	!           AND NOT TInt.LT (x, Target.Integer.min)
	!           AND NOT TInt.LT (Target.Integer.max, x) THEN
	IF NOT CompleteTree (t.greater, x, max) THEN RETURN FALSE END;
	END;
	!         IF NOT TInt.Subtract (t.min, TInt.One, max)
	!           OR TInt.LT (x, Target.Integer.min)
	!           OR TInt.LT (Target.Integer.max, x) THEN
	RETURN TRUE;
	END;
	t := t.less;
	ELSE
	!         IF TInt.Subtract (t.min, TInt.One, x)
	!           AND NOT TInt.LT (x, Target.Integer.min)
	!           AND NOT TInt.LT (Target.Integer.max, x) THEN
	IF NOT CompleteTree (t.less, min, x) THEN RETURN FALSE END;
	END;
	!         IF NOT TInt.Add (t.max, TInt.One, min)
	!           OR TInt.LT (x, Target.Integer.min)
	!           OR TInt.LT (Target.Integer.max, x) THEN
	RETURN TRUE;
	END;
	t := t.greater;
	***************
	*** 458,464 ****
	next: Target.Int;
	oc, xc: Stmt.Outcomes;
	l_bodies, l_else, l_end: INTEGER;
	-     One := Target.Int{Target.Integer.bytes, Target.IBytes{1,0,..}};
	BEGIN
	p.tree := CollapseTree (p.tree);
	l_bodies := CG.Next_label (p.nCases);
	--- 465,470 ----
	***************
	*** 485,491 ****
	CG.Push (x);
	CG.Load_integer (Target.Integer.cg_type, t.max);
	CG.If_compare (Target.Integer.cg_type, CG.Cmp.LE, l_bodies+t.body, CG.Maybe);
	!       IF NOT TInt.Add (t.max, One, next) THEN
	IF (t.greater # NIL) THEN Error.Msg ("case label too large") END;
	next := t.max;
	END;
	--- 491,499 ----
	CG.Push (x);
	CG.Load_integer (Target.Integer.cg_type, t.max);
	CG.If_compare (Target.Integer.cg_type, CG.Cmp.LE, l_bodies+t.body, CG.Maybe);
	!       IF NOT TInt.Add (t.max, TInt.One, next)
	!         OR TInt.LT (next, Target.Integer.min)
	!         OR TInt.LT (Target.Integer.max, next) THEN
	IF (t.greater # NIL) THEN Error.Msg ("case label too large") END;
	next := t.max;
	END;
	Index: m3front/src/types/ArrayType.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/types/ArrayType.m3,v
	retrieving revision 1.5
	diff -c -r1.5 ArrayType.m3
	*** m3front/src/types/ArrayType.m3	4 May 2008 11:03:48 -0000	1.5
	--- m3front/src/types/ArrayType.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 309,315 ****
	VAR n, m, res: Target.Int;  x: INTEGER;
	BEGIN
	x := Type.InitCost (p.element, zeroed);
	!     IF NOT TInt.FromInt (x, Target.Integer.bytes, m) THEN
	RETURN LAST (INTEGER);
	END;
	n := Type.Number (p.index);
	--- 309,315 ----
	VAR n, m, res: Target.Int;  x: INTEGER;
	BEGIN
	x := Type.InitCost (p.element, zeroed);
	!     IF NOT TInt.FromInt (x, m) THEN
	RETURN LAST (INTEGER);
	END;
	n := Type.Number (p.index);
	Index: m3front/src/types/EnumType.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/types/EnumType.m3,v
	retrieving revision 1.7
	diff -c -r1.7 EnumType.m3
	*** m3front/src/types/EnumType.m3	4 May 2008 11:03:49 -0000	1.7
	--- m3front/src/types/EnumType.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 44,50 ****
	n := Ident.ParseList ();
	j := Ident.top - n;
	FOR i := 0 TO n - 1 DO
	!         b := TInt.FromInt (i, Target.Integer.bytes, val); <*ASSERT b*>
	Scope.Insert (EnumElt.New (Ident.stack[j + i], val, p));
	END;
	DEC (Ident.top, n);
	--- 44,50 ----
	n := Ident.ParseList ();
	j := Ident.top - n;
	FOR i := 0 TO n - 1 DO
	!         b := TInt.FromInt (i, val); <*ASSERT b*>
	Scope.Insert (EnumElt.New (Ident.stack[j + i], val, p));
	END;
	DEC (Ident.top, n);
	***************
	*** 70,76 ****
	BEGIN
	p := Create (Scope.PushNew (FALSE, M3ID.NoID));
	FOR i := 0 TO LAST (elt_nms) DO
	!       b := TInt.FromInt (i, Target.Integer.bytes, val);  <*ASSERT b*>
	Scope.Insert (EnumElt.New (M3ID.Add (elt_nms[i]), val, p));
	END;
	Scope.PopNew ();
	--- 70,76 ----
	BEGIN
	p := Create (Scope.PushNew (FALSE, M3ID.NoID));
	FOR i := 0 TO LAST (elt_nms) DO
	!       b := TInt.FromInt (i, val);  <*ASSERT b*>
	Scope.Insert (EnumElt.New (M3ID.Add (elt_nms[i]), val, p));
	END;
	Scope.PopNew ();
	***************
	*** 121,127 ****
	PROCEDURE SetRep (p: P) =
	VAR max: Target.Int;
	BEGIN
	!     IF NOT TInt.FromInt (p.n_elts-1, Target.Integer.bytes, max) THEN
	Error.Msg ("enumeration type too large");
	END;
	FOR i := FIRST (Rep) TO LAST (Rep) DO
	--- 121,129 ----
	PROCEDURE SetRep (p: P) =
	VAR max: Target.Int;
	BEGIN
	!     IF NOT TInt.FromInt (p.n_elts-1, max)
	!       OR TInt.LT (max, Target.Integer.min)
	!       OR TInt.LT (Target.Integer.max, max) THEN
	Error.Msg ("enumeration type too large");
	END;
	FOR i := FIRST (Rep) TO LAST (Rep) DO
	***************
	*** 158,164 ****
	p.info.hash      := hash;
	END Check;
	
	-
	PROCEDURE CheckAlign (p: P;  offset: INTEGER): BOOLEAN =
	VAR
	sz := TargetMap.Word_types [p.rep].size;
	--- 160,165 ----
	***************
	*** 172,178 ****
	RETURN (offset + sz) <= (z0 + Target.Integer.size);
	END CheckAlign;
	
	-
	PROCEDURE Compiler (p: P) =
	VAR v := Scope.ToList (p.scope);
	BEGIN
	--- 173,178 ----
	***************
	*** 222,230 ****
	VAR max: Target.Int;
	BEGIN
	IF (p.n_elts <= 0) OR (zeroed) THEN RETURN 0; END;
	!     IF NOT TInt.FromInt (p.n_elts-1, Target.Integer.bytes, max) THEN
	!       RETURN 1;
	!     END;
	IF TInt.EQ (TargetMap.Word_types[p.rep].max, max)
	THEN RETURN 0;
	ELSE RETURN 1;
	--- 222,228 ----
	VAR max: Target.Int;
	BEGIN
	IF (p.n_elts <= 0) OR (zeroed) THEN RETURN 0; END;
	!     IF NOT TInt.FromInt (p.n_elts-1, max) THEN RETURN 1 END;
	IF TInt.EQ (TargetMap.Word_types[p.rep].max, max)
	THEN RETURN 0;
	ELSE RETURN 1;
	Index: m3front/src/types/OpenArrayType.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/types/OpenArrayType.m3,v
	retrieving revision 1.4
	diff -c -r1.4 OpenArrayType.m3
	*** m3front/src/types/OpenArrayType.m3	18 Sep 2007 20:26:11 -0000	1.4
	--- m3front/src/types/OpenArrayType.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 209,217 ****
	PROCEDURE InitCoster (p: P; zeroed: BOOLEAN): INTEGER =
	VAR n, m, res: Target.Int;  x: INTEGER;
	BEGIN
	!     IF    TInt.FromInt (Type.InitCost (p.element, zeroed),
	!                         Target.Integer.bytes, m)
	!       AND TInt.FromInt (20, Target.Integer.bytes, n) (* guess 20 elements *)
	AND TInt.Multiply (m, n, res)
	AND TInt.ToInt (res, x)
	THEN RETURN x;
	--- 209,216 ----
	PROCEDURE InitCoster (p: P; zeroed: BOOLEAN): INTEGER =
	VAR n, m, res: Target.Int;  x: INTEGER;
	BEGIN
	!     IF    TInt.FromInt (Type.InitCost (p.element, zeroed), m)
	!       AND TInt.FromInt (20, n) (* guess that there are 20 elements *)
	AND TInt.Multiply (m, n, res)
	AND TInt.ToInt (res, x)
	THEN RETURN x;
	Index: m3front/src/types/SubrangeType.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/types/SubrangeType.m3,v
	retrieving revision 1.7
	diff -c -r1.7 SubrangeType.m3
	*** m3front/src/types/SubrangeType.m3	15 Jan 2010 21:50:12 -0000	1.7
	--- m3front/src/types/SubrangeType.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 78,91 ****
	
	PROCEDURE SetRep (p: P) =
	BEGIN
	-     IF Type.IsSubtype (p.baseType, LInt.T)
	-       THEN p.rep := Target.Longint.cg_type;
	-       ELSE p.rep := Target.Integer.cg_type;
	-     END;
	-
	IF TInt.LT (p.max, p.min) THEN
	p.min := TInt.Zero;
	p.max := TInt.MOne;
	RETURN;
	END;
	
	--- 78,90 ----
	
	PROCEDURE SetRep (p: P) =
	BEGIN
	IF TInt.LT (p.max, p.min) THEN
	p.min := TInt.Zero;
	p.max := TInt.MOne;
	+       IF Type.IsSubtype (p.baseType, LInt.T)
	+         THEN p.rep := Target.Longint.cg_type;
	+         ELSE p.rep := Target.Integer.cg_type;
	+       END;
	RETURN;
	END;
	
	***************
	*** 102,109 ****
	(* look for a signed type *)
	FOR i := FIRST (TargetMap.Integer_types) TO LAST (TargetMap.Integer_types) DO
	WITH z = TargetMap.Integer_types[i] DO
	!           IF TInt.LE (z.min, p.min)
	!             AND TInt.LE (p.max, z.max) THEN
	p.rep := z.cg_type; RETURN;
	END;
	END;
	--- 101,107 ----
	(* look for a signed type *)
	FOR i := FIRST (TargetMap.Integer_types) TO LAST (TargetMap.Integer_types) DO
	WITH z = TargetMap.Integer_types[i] DO
	!           IF TInt.LE (z.min, p.min) AND TInt.LE (p.max, z.max) THEN
	p.rep := z.cg_type; RETURN;
	END;
	END;
	***************
	*** 277,283 ****
	END BitWidth;
	
	VAR (*CONST*)
	!   power : ARRAY [0..BITSIZE (Target.Int)] OF Target.Int;
	powers_done := FALSE;
	
	PROCEDURE BuildPowerTables () =
	--- 275,281 ----
	END BitWidth;
	
	VAR (*CONST*)
	!   power : ARRAY [0..TInt.Size] OF Target.Int;
	powers_done := FALSE;
	
	PROCEDURE BuildPowerTables () =
	***************
	*** 306,312 ****
	rep_max := Target.Integer.max;
	END;
	
	!     IF zeroed AND TInt.LE (p.min, TInt.Zero)
	AND TInt.LE (TInt.Zero, p.max) THEN
	RETURN 0;
	END;
	--- 304,311 ----
	rep_max := Target.Integer.max;
	END;
	
	!     IF zeroed
	!       AND TInt.LE (p.min, TInt.Zero)
	AND TInt.LE (TInt.Zero, p.max) THEN
	RETURN 0;
	END;
	***************
	*** 340,347 ****
	VAR info: Type.Info;
	BEGIN
	EVAL Type.CheckInfo (p, info);
	!     IF TInt.LT (TInt.Zero, p.min)
	!       OR TInt.LT (p.max, TInt.Zero) THEN
	CG.Load_integer (info.stk_type, p.min);
	CG.Store_indirect (info.stk_type, 0, info.size);
	ELSIF zeroed THEN
	--- 339,345 ----
	VAR info: Type.Info;
	BEGIN
	EVAL Type.CheckInfo (p, info);
	!     IF TInt.LT (TInt.Zero, p.min) OR TInt.LT (p.max, TInt.Zero) THEN
	CG.Load_integer (info.stk_type, p.min);
	CG.Store_indirect (info.stk_type, 0, info.size);
	ELSIF zeroed THEN
	Index: m3front/src/types/Type.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3front/src/types/Type.m3,v
	retrieving revision 1.8
	diff -c -r1.8 Type.m3
	*** m3front/src/types/Type.m3	4 May 2008 11:03:49 -0000	1.8
	--- m3front/src/types/Type.m3	18 Feb 2010 02:30:53 -0000
	***************
	*** 392,399 ****
	IF (c = Class.Subrange) THEN
	b := SubrangeType.Split (u, min, max);  <*ASSERT b*>
	ELSIF (c = Class.Enum) THEN
	!       b := TInt.FromInt (EnumType.NumElts (u), Target.Integer.bytes, max);
	!       <*ASSERT b*>
	RETURN max;
	ELSIF (c = Class.Integer) THEN
	min := Target.Integer.min;
	--- 392,398 ----
	IF (c = Class.Subrange) THEN
	b := SubrangeType.Split (u, min, max);  <*ASSERT b*>
	ELSIF (c = Class.Enum) THEN
	!       b := TInt.FromInt (EnumType.NumElts (u), max);  <*ASSERT b*>
	RETURN max;
	ELSIF (c = Class.Integer) THEN
	min := Target.Integer.min;
	***************
	*** 411,417 ****
	END;
	IF TInt.Subtract (max, min, tmp)
	AND TInt.Add (tmp, TInt.One, max)
	!       AND TInt.LE (max, Target.Integer.max) THEN
	RETURN max;
	END;
	Error.Msg ("type has too many elements");
	--- 410,417 ----
	END;
	IF TInt.Subtract (max, min, tmp)
	AND TInt.Add (tmp, TInt.One, max)
	!       AND NOT TInt.LT (max, Target.Integer.min)
	!       AND NOT TInt.LT (Target.Integer.max, max) THEN
	RETURN max;
	END;
	Error.Msg ("type has too many elements");
	***************
	*** 425,432 ****
	b := SubrangeType.Split (u, min, max);  <*ASSERT b*>
	RETURN TRUE;
	ELSIF (c = Class.Enum) THEN
	!       b := TInt.FromInt (EnumType.NumElts (u), Target.Integer.bytes, min);
	!       <*ASSERT b*>
	b := TInt.Subtract (min, TInt.One, max);   <*ASSERT b*>
	min := TInt.Zero;
	RETURN TRUE;
	--- 425,431 ----
	b := SubrangeType.Split (u, min, max);  <*ASSERT b*>
	RETURN TRUE;
	ELSIF (c = Class.Enum) THEN
	!       b := TInt.FromInt (EnumType.NumElts (u), min);  <*ASSERT b*>
	b := TInt.Subtract (min, TInt.One, max);   <*ASSERT b*>
	min := TInt.Zero;
	RETURN TRUE;
	Index: m3tools/src/M3Builtin.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3tools/src/M3Builtin.m3,v
	retrieving revision 1.5
	diff -c -r1.5 M3Builtin.m3
	*** m3tools/src/M3Builtin.m3	18 Sep 2007 20:26:30 -0000	1.5
	--- m3tools/src/M3Builtin.m3	18 Feb 2010 02:30:54 -0000
	***************
	*** 111,117 ****
	val.type  := M3Type.Integer;
	val.class := M3Const.Class.Integer;
	MustBe (info.size >= 0);
	!               MustBe (TInt.FromInt (info.size, Target.Integer.bytes, val.int));
	END;
	ELSE
	NotImpl ("BYTESIZE(expr)");
	--- 111,117 ----
	val.type  := M3Type.Integer;
	val.class := M3Const.Class.Integer;
	MustBe (info.size >= 0);
	!               MustBe (TInt.FromInt (info.size, val.int));
	END;
	ELSE
	NotImpl ("BYTESIZE(expr)");
	Index: m3tools/src/M3Const.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3tools/src/M3Const.m3,v
	retrieving revision 1.6
	diff -c -r1.6 M3Const.m3
	*** m3tools/src/M3Const.m3	16 Jan 2010 02:29:10 -0000	1.6
	--- m3tools/src/M3Const.m3	18 Feb 2010 02:30:54 -0000
	***************
	*** 861,868 ****
	Err ("bad operand for subscript operation");
	ELSIF (b.class = Class.Integer) THEN
	(* ok *)
	!     ELSIF (b.class = Class.Enum)
	!       AND TInt.FromInt (b.info, Target.Integer.bytes, b.int) THEN
	(* ok *)
	ELSE
	Err ("bad operand for subscript operation");
	--- 861,867 ----
	Err ("bad operand for subscript operation");
	ELSIF (b.class = Class.Integer) THEN
	(* ok *)
	!     ELSIF (b.class = Class.Enum) AND TInt.FromInt (b.info, b.int) THEN
	(* ok *)
	ELSE
	Err ("bad operand for subscript operation");
	***************
	*** 1161,1167 ****
	BEGIN
	val.class := Class.Integer;
	val.type  := M3Type.Integer;
	!     IF NOT TInt.FromInt (s.info, Target.Integer.bytes, val.int) THEN
	Err ("illegal integer value");
	END;
	END EvalInt;
	--- 1160,1166 ----
	BEGIN
	val.class := Class.Integer;
	val.type  := M3Type.Integer;
	!     IF NOT TInt.FromInt (s.info, val.int) THEN
	Err ("illegal integer value");
	END;
	END EvalInt;
	***************
	*** 1171,1177 ****
	BEGIN
	val.class := Class.Integer;
	val.type  := M3Type.Longint;
	!     IF NOT TInt.FromInt (s.info, Target.Longint.bytes, val.int) THEN
	Err ("illegal integer value");
	END;
	END EvalLInt;
	--- 1170,1176 ----
	BEGIN
	val.class := Class.Integer;
	val.type  := M3Type.Longint;
	!     IF NOT TInt.FromInt (s.info, val.int) THEN
	Err ("illegal integer value");
	END;
	END EvalLInt;
	Index: m3tools/src/M3Lexer.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3tools/src/M3Lexer.m3,v
	retrieving revision 1.4
	diff -c -r1.4 M3Lexer.m3
	*** m3tools/src/M3Lexer.m3	18 Sep 2007 20:26:30 -0000	1.4
	--- m3tools/src/M3Lexer.m3	18 Feb 2010 02:30:54 -0000
	***************
	*** 89,96 ****
	SUPER.next (t);
	CASE t.token OF
	| TK_Ident          => FixID (t);
	!         | TK_Card_const     => FixInt (t, Target.Integer.bytes);
	!         | TK_Long_const     => FixInt (t, Target.Longint.bytes);
	| TK_Real_const     => FixFloat (t, Target.Precision.Short);
	| TK_Longreal_const => FixFloat (t, Target.Precision.Long);
	| TK_Extended_const => FixFloat (t, Target.Precision.Extended);
	--- 89,96 ----
	SUPER.next (t);
	CASE t.token OF
	| TK_Ident          => FixID (t);
	!         | TK_Card_const     => FixInt (t);
	!         | TK_Long_const     => FixInt (t);
	| TK_Real_const     => FixFloat (t, Target.Precision.Short);
	| TK_Longreal_const => FixFloat (t, Target.Precision.Long);
	| TK_Extended_const => FixFloat (t, Target.Precision.Extended);
	***************
	*** 108,114 ****
	t.id := M3ID.FromStr (SUBARRAY (t.buffer^, t.offset, t.length));
	END FixID;
	
	! PROCEDURE FixInt (t: T;  bytes: CARDINAL) =
	VAR break := -1;  base: INTEGER;
	BEGIN
	FOR i := t.offset TO t.offset + t.length - 1 DO
	--- 108,114 ----
	t.id := M3ID.FromStr (SUBARRAY (t.buffer^, t.offset, t.length));
	END FixID;
	
	! PROCEDURE FixInt (t: T) =
	VAR break := -1;  base: INTEGER;
	BEGIN
	FOR i := t.offset TO t.offset + t.length - 1 DO
	***************
	*** 120,135 ****
	END;
	
	IF (break < 0) THEN (* scan a simple integer *)
	!       IF NOT TInt.New (SUBARRAY (t.buffer^, t.offset, t.length), bytes, t.int) THEN
	Err (t, "illegal integer literal");
	END;
	!     ELSIF NOT TInt.New (SUBARRAY (t.buffer^, t.offset, break - t.offset), bytes, t.int)
	OR NOT TInt.ToInt (t.int, base)
	OR (base < 2) OR (16 < base) THEN
	Err (t, "illegal base for integer literal");
	ELSIF NOT TWord.New (SUBARRAY (t.buffer^, break+1,
	t.offset + t.length - break - 1),
	!                          base, bytes, t.int) THEN
	Err (t, "illegal based integer literal");
	END;
	END FixInt;
	--- 120,135 ----
	END;
	
	IF (break < 0) THEN (* scan a simple integer *)
	!       IF NOT TInt.New (SUBARRAY (t.buffer^, t.offset, t.length), t.int) THEN
	Err (t, "illegal integer literal");
	END;
	!     ELSIF NOT TInt.New (SUBARRAY (t.buffer^, t.offset, break - t.offset), t.int)
	OR NOT TInt.ToInt (t.int, base)
	OR (base < 2) OR (16 < base) THEN
	Err (t, "illegal base for integer literal");
	ELSIF NOT TWord.New (SUBARRAY (t.buffer^, break+1,
	t.offset + t.length - break - 1),
	!                          base, t.int) THEN
	Err (t, "illegal based integer literal");
	END;
	END FixInt;
	Index: m3tools/src/M3Type.m3
	===================================================================
	RCS file: /usr/cvs/cm3/m3-sys/m3tools/src/M3Type.m3,v
	retrieving revision 1.6
	diff -c -r1.6 M3Type.m3
	*** m3tools/src/M3Type.m3	16 Jan 2010 02:29:11 -0000	1.6
	--- m3tools/src/M3Type.m3	18 Feb 2010 02:30:54 -0000
	***************
	*** 45,55 ****
	
	PROCEDURE Number (t: T): Target.Int =
	VAR min, max, tmp: Target.Int;
	-       One := Target.Int{Target.Integer.bytes, TInt.One.x};
	BEGIN
	IF t.get_bounds (min, max)
	AND TInt.Subtract (max, min, tmp)
	!       AND TInt.Add (tmp, One, max) THEN
	RETURN max;
	END;
	RETURN Target.Integer.max;
	--- 45,54 ----
	
	PROCEDURE Number (t: T): Target.Int =
	VAR min, max, tmp: Target.Int;
	BEGIN
	IF t.get_bounds (min, max)
	AND TInt.Subtract (max, min, tmp)
	!       AND TInt.Add (tmp, TInt.One, max) THEN
	RETURN max;
	END;
	RETURN Target.Integer.max;
	***************
	*** 248,254 ****
	PROCEDURE GetEnumInfo (self: Enum;  VAR x: Info) RAISES {Error} =
	VAR n_elts := NUMBER (self.elements^);   max: Target.Int;  rep: EnumRep;
	BEGIN
	!     IF NOT TInt.FromInt (n_elts-1, Target.Integer.bytes, max) THEN
	Err ("enumeration type too large");
	END;
	rep := FindEnumRep (max);
	--- 247,253 ----
	PROCEDURE GetEnumInfo (self: Enum;  VAR x: Info) RAISES {Error} =
	VAR n_elts := NUMBER (self.elements^);   max: Target.Int;  rep: EnumRep;
	BEGIN
	!     IF NOT TInt.FromInt (n_elts-1, max) THEN
	Err ("enumeration type too large");
	END;
	rep := FindEnumRep (max);
	***************
	*** 289,296 ****
	VAR b: BOOLEAN;
	BEGIN
	min := TInt.Zero;
	!     b := TInt.FromInt (NUMBER (self.elements^) - 1, Target.Integer.size, max);
	!     <*ASSERT b*>
	RETURN TRUE;
	END EnumBounds;
	
	--- 288,294 ----
	VAR b: BOOLEAN;
	BEGIN
	min := TInt.Zero;
	!     b := TInt.FromInt (NUMBER (self.elements^) - 1, max);  <*ASSERT b*>
	RETURN TRUE;
	END EnumBounds;




More information about the M3commit mailing list