-- 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..