-- file DJumps.mesa -- last modified by Sweet, March 20, 1979 4:53 PM DIRECTORY AltoDefs: FROM "altodefs" USING [BYTE], Code: FROM "code" USING [codeptr], CodeDefs: FROM "codedefs" USING [CCIndex, CCNull, JumpCCIndex, JumpType, RelativePC], OpCodeParams: FROM "opcodeparams" USING [MaxBBJumps, MaxFBJumps, MaxFIAJumps, MaxFICJumps], P5F: FROM "p5f" USING [CodeJumpDist, StartIndex], Table: FROM "table" USING [Base, Notifier], Tree: FROM "tree" USING [treeType]; DJumps: PROGRAM IMPORTS CPtr: Code, P5F EXPORTS CodeDefs, P5F = BEGIN OPEN OpCodeParams, CodeDefs; -- imported definitions BYTE: TYPE = AltoDefs.BYTE; cb: Table.Base; -- code base (local copy) DJumpsNotify: PUBLIC Table.Notifier = BEGIN -- called by allocator whenever table area is repacked cb _ base[Tree.treeType]; RETURN END; BindJumpDStar: PUBLIC PROCEDURE [min, max: INTEGER, c: JumpCCIndex] RETURNS [bindable: BOOLEAN] = BEGIN -- compute size of jump instruction(s) -- max and min are counts of the number of bytes between the -- jump and the label. t: JumpType; js: [0..7]; bindable _ TRUE; t _ cb[c].jtype; IF t = JumpC THEN BEGIN -- "bound" by OutBinary cb[c].fixedup _ TRUE; cb[c].completed _ TRUE; RETURN END; IF ~cb[c].forward THEN BEGIN max _ -max; min _ -min END; SELECT t FROM Jump, JumpA => IF max IN [1..MaxFIAJumps] THEN js _ 1 ELSE IF max IN (MaxFIAJumps..MaxFBJumps-2] AND min > MaxFIAJumps THEN js _ 2 ELSE IF max IN [-MaxBBJumps..0] THEN js _ 2 ELSE IF min ~IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 3 ELSE bindable _ FALSE; JumpE, JumpN => IF max IN [1..MaxFICJumps] THEN js _ 1 ELSE IF max IN (MaxFICJumps..MaxFBJumps-2] AND min > MaxFICJumps THEN js _ 2 ELSE IF max IN [-MaxBBJumps..0] THEN js _ 2 ELSE IF min ~IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 4 ELSE bindable _ FALSE; JumpCA => IF max IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 2 ELSE IF min ~IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 3 ELSE bindable _ FALSE; ENDCASE => IF max IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 2 ELSE IF min ~IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 5 ELSE bindable _ FALSE; IF bindable THEN BEGIN cb[c].fixedup _ TRUE; cb[c].jsize _ js END; RETURN END; CodeJumpDStar: PUBLIC PROCEDURE [nbytes: INTEGER, c: JumpCCIndex] = BEGIN -- code all jump instruction(s) forward: BOOLEAN; dist: INTEGER; l: [0..7]; CPtr.codeptr _ c; l _ cb[c].jsize; forward _ cb[c].forward; -- The next statement copes with the fact that the parameter to a jump -- instruction is added to the byte pc of the first byte of the instruction -- nbytes is the number of bytes between the jump and its label dist _ IF ~forward THEN -nbytes ELSE nbytes+l; IF l > 3 THEN dist _ dist + 3 - l; P5F.CodeJumpDist[dist, l, 0, c, TRUE]; END; dMinMaxDStar: ARRAY {unconditional, equal, relational} OF PACKED ARRAY BOOLEAN OF RECORD [min,max: [0..15]] _ [ [[2,3],[1,3]], -- unconditional, (backward, forward) [[2,4],[1,4]], -- equal, (backward, forward) [[2,5],[2,5]]]; -- relational, (backward, forward) FillInPCEstimatesDStar: PUBLIC PROCEDURE = BEGIN k: CCIndex; t: CARDINAL; min, max: RelativePC; dMin, dMax: [0..15]; min _ max _ 0; FOR k _ P5F.StartIndex, cb[k].flink UNTIL k = CCNull DO WITH cc:cb[k] SELECT FROM code => BEGIN t _ cc.isize; min _ min + t; max _ max + t; END; jump => IF cc.jtype # JumpC THEN BEGIN IF ~cc.fixedup THEN BEGIN [dMin,dMax] _ dMinMaxDStar[(SELECT cc.jtype FROM Jump,JumpA,JumpCA => unconditional, JumpE,JumpN => equal, ENDCASE => relational)][cc.forward]; IF ~cc.forward THEN BEGIN cc.minPC _ min; cc.maxPC _ max; END; min _ min+dMin; max _ max+dMax; IF cc.forward THEN BEGIN cc.minPC _ min; cc.maxPC _ max; END; END ELSE IF ~cc.completed THEN BEGIN t _ cc.jsize; IF ~cc.forward THEN BEGIN cc.minPC _ min; cc.maxPC _ max; END; min _ min + t; max _ max + t; IF cc.forward THEN BEGIN cc.minPC _ min; cc.maxPC _ max; END; END; END; label => BEGIN cc.minPC _ min; cc.maxPC _ max; END; other => WITH cc SELECT FROM table => BEGIN t _ tablecodebytes; min _ min + t; max _ max + t; END; ENDCASE; ENDCASE; ENDLOOP; RETURN END; END..