(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: WordShift.m3 *) (* Last Modified On Tue Jun 30 09:36:52 PDT 1992 By kalsow *) (* Modified On Fri May 18 08:15:52 1990 By muller *) MODULE WordShift; IMPORT Word, CallExpr, Expr, Type, Procedure, Emit, BuiltinArgs, Target; IMPORT Int, IntegerExpr, Value, Formal, Temp, ProcType; VAR Z, ZL, ZR: CallExpr.MethodList; VAR formals, formalsLR: ARRAY [0..1] OF Value.T; PROCEDURE Check (<*UNUSED*> proc: Expr.T; VAR args: Expr.List; VAR cs: Expr.CheckState): Type.T = BEGIN EVAL Formal.CheckArgs (cs, args, formals); RETURN Int.T; END Check; PROCEDURE CheckLR (<*UNUSED*> proc: Expr.T; VAR args: Expr.List; VAR cs: Expr.CheckState): Type.T = BEGIN EVAL Formal.CheckArgs (cs, args, formalsLR); RETURN Int.T; END CheckLR; PROCEDURE Compile (<*UNUSED*> proc: Expr.T; args: Expr.List): Temp.T = VAR t1, t11, t2, t12, t3: Temp.T; e2: Expr.T; i2: INTEGER; BEGIN t1 := Expr.Compile (args[0]); e2 := Expr.ConstValue (args^[1]); IF (e2 # NIL) AND IntegerExpr.Split (e2, i2) THEN IF i2 = 0 THEN RETURN t1; END; t3 := Temp.AllocEmpty (Int.T); Emit.OpT ("@ = ", t3); IF (ABS (i2) >= Target.INTSIZE) THEN Emit.Op ("0;\n"); ELSIF (i2 < 0) THEN Emit.OpTI ("((unsigned)@) >> @;\n", t1, -i2); ELSE Emit.OpTI ("((unsigned)@) << @;\n", t1, i2); END; Temp.Free (t1); RETURN t3; END; t2 := Expr.Compile (args[1]); t3 := Temp.AllocEmpty (Int.T); t11 := Temp.AllocEmpty (Int.T); t12 := Temp.AllocEmpty (Int.T); Emit.OpTT ("@ = @;\n", t11, t1); Emit.OpTT ("@ = @;\n", t12, t2); Emit.OpT ("@ = (", t3); Emit.OpTI ("((@ <= @) || ", t12, -Target.INTSIZE); Emit.OpTI ("(@ >= @)) ? 0 : \n", t12, Target.INTSIZE); Emit.OpTTT ("((@ < 0) ? (((unsigned)@) >> -(@)) : ", t12, t11, t12); Emit.OpTT ("(((unsigned) @) << @)));\n", t11, t12); Temp.Free (t1); Temp.Free (t2); Temp.Free (t11); Temp.Free (t12); RETURN t3; END Compile; PROCEDURE CompileL (<*UNUSED*> proc: Expr.T; args: Expr.List): Temp.T = VAR t1, t2, t3: Temp.T; BEGIN t1 := Expr.Compile (args[0]); t2 := Expr.Compile (args[1]); t3 := Temp.AllocEmpty (Int.T); Emit.OpTTT ("@ = ((unsigned)@) << @;\n", t3, t1, t2); Temp.Free (t1); Temp.Free (t2); RETURN t3; END CompileL; PROCEDURE CompileR (<*UNUSED*> proc: Expr.T; args: Expr.List): Temp.T = VAR t1, t2, t3: Temp.T; BEGIN t1 := Expr.Compile (args[0]); t2 := Expr.Compile (args[1]); t3 := Temp.AllocEmpty (Int.T); Emit.OpTTT ("@ = ((unsigned)@) >> @;\n", t3, t1, t2); Temp.Free (t1); Temp.Free (t2); RETURN t3; END CompileR; PROCEDURE Fold (<*UNUSED*> proc: Expr.T; args: Expr.List): Expr.T = VAR e0, e1: Expr.T; w0: Word.T; i1: INTEGER; BEGIN e0 := Expr.ConstValue (args[0]); e1 := Expr.ConstValue (args[1]); IF (e0 # NIL) AND IntegerExpr.Split (e0, w0) AND (e1 # NIL) AND IntegerExpr.Split (e1, i1) THEN RETURN IntegerExpr.New (Word.Shift (w0, i1)); ELSE RETURN NIL; END; END Fold; PROCEDURE FoldL (<*UNUSED*> proc: Expr.T; args: Expr.List): Expr.T = VAR e0, e1: Expr.T; w0: Word.T; i1: INTEGER; BEGIN e0 := Expr.ConstValue (args[0]); e1 := Expr.ConstValue (args[1]); IF (e0 # NIL) AND IntegerExpr.Split (e0, w0) AND (e1 # NIL) AND IntegerExpr.Split (e1, i1) THEN RETURN IntegerExpr.New (Word.LeftShift (w0, i1)); ELSE RETURN NIL; END; END FoldL; PROCEDURE FoldR (<*UNUSED*> proc: Expr.T; args: Expr.List): Expr.T = VAR e0, e1: Expr.T; w0: Word.T; i1: INTEGER; BEGIN e0 := Expr.ConstValue (args[0]); e1 := Expr.ConstValue (args[1]); IF (e0 # NIL) AND IntegerExpr.Split (e0, w0) AND (e1 # NIL) AND IntegerExpr.Split (e1, i1) THEN RETURN IntegerExpr.New (Word.RightShift (w0, i1)); ELSE RETURN NIL; END; END FoldR; PROCEDURE Initialize () = BEGIN formals[0] := BuiltinArgs.f1; formals[1] := BuiltinArgs.f13; Z := CallExpr.NewMethodList (2, 2, TRUE, TRUE, Int.T, NIL, Check, Compile, Fold, CallExpr.IsNever, (* writable *) CallExpr.IsNever, (* designator *) CallExpr.NotWritable (* noteWriter *)); Procedure.Define ("Shift", Z, FALSE, ProcType.New (formals, Int.T)); formalsLR[0] := BuiltinArgs.f1; formalsLR[1] := BuiltinArgs.f14; ZL := CallExpr.NewMethodList (2, 2, TRUE, TRUE, Int.T, NIL, CheckLR, CompileL, FoldL, CallExpr.IsNever, (* writable *) CallExpr.IsNever, (* designator *) CallExpr.NotWritable (* noteWriter *)); Procedure.Define ("LeftShift", ZL, FALSE, ProcType.New (formalsLR, Int.T)); ZR := CallExpr.NewMethodList (2, 2, TRUE, TRUE, Int.T, NIL, CheckLR, CompileR, FoldR, CallExpr.IsNever, (* writable *) CallExpr.IsNever, (* designator *) CallExpr.NotWritable (* noteWriter *)); Procedure.Define ("RightShift", ZR, FALSE, ProcType.New (formalsLR, Int.T)); END Initialize; BEGIN END WordShift.