-- file AJumps.mesa -- last modified by Sweet, March 20, 1979 4:52 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]; AJumps: 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) AJumpsNotify: PUBLIC Table.Notifier = BEGIN -- called by allocator whenever table area is repacked cb _ base[Tree.treeType]; RETURN END; BindJump: 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. in particular max does not allow for -- a possible pad on this jump (if backward). 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) AND min > MaxFIAJumps THEN js _ 2 ELSE IF max IN (-(MaxBBJumps-1)..0] THEN js _ 2 ELSE IF min ~IN (-(MaxBBJumps-1)..MaxFBJumps) THEN js _ 3 ELSE bindable _ FALSE; JumpE, JumpN => IF max IN [1..MaxFICJumps] THEN js _ 1 ELSE IF max IN (MaxFICJumps..MaxFBJumps) AND min > MaxFICJumps THEN js _ 2 ELSE IF max IN (-(MaxBBJumps-1)..0] THEN js _ 2 ELSE IF min ~IN (-(MaxBBJumps-1)..MaxFBJumps) THEN js _ 4 ELSE bindable _ FALSE; JumpCA => IF max IN (-(MaxBBJumps-1)..MaxFBJumps) THEN js _ 2 ELSE IF min ~IN (-(MaxBBJumps-1)..MaxFBJumps) THEN js _ 3 ELSE bindable _ FALSE; ENDCASE => IF max IN (-(MaxBBJumps-1)..MaxFBJumps) THEN js _ 2 ELSE IF min ~IN (-(MaxBBJumps-1)..MaxFBJumps) THEN js _ 6 ELSE bindable _ FALSE; IF bindable THEN BEGIN cb[c].fixedup _ TRUE; cb[c].jsize _ js END; RETURN END; CodeJump: PUBLIC PROCEDURE [nbytes: INTEGER, c: JumpCCIndex] = BEGIN -- code all jump instruction(s) forward: BOOLEAN; dist: INTEGER; pad: [0..1]; l: [0..7]; CPtr.codeptr _ c; l _ cb[c].jsize; forward _ cb[c].forward; pad _ cb[c].pad; -- The next statement copes with the fact that the parameter to a jump -- instruction is added to the byte pc of the last byte of the instruction -- nbytes is the number of bytes between the jump and its label dist _ IF ~forward THEN 1-nbytes-l-pad ELSE nbytes+1; P5F.CodeJumpDist[dist, l, pad, c, FALSE]; END; dMinMax: ARRAY {unconditional, equal, relational} OF ARRAY [0..2] OF PACKED ARRAY BOOLEAN OF RECORD [min,max: [0..15]] _ [ [[[2,4],[1,4]], -- unconditional, parity 0 (backward, forward) [[3,3],[1,3]], -- unconditional, parity 1 (backward, forward) [[2,4],[1,4]]], -- unconditional, parity 2 (backward, forward) [[[2,4],[1,4]], -- equal, parity 0 (backward, forward) [[3,5],[1,5]], -- equal, parity 1 (backward, forward) [[2,5],[1,5]]], -- equal, parity 2 (backward, forward) [[[2,6],[2,6]], -- relational, parity 0 (backward, forward) [[3,7],[3,7]], -- relational, parity 1 (backward, forward) [[2,7],[2,7]]]]; -- relational, parity 2 (backward, forward) FillInPCEstimates: PUBLIC PROCEDURE = BEGIN k: CCIndex; t: CARDINAL; min, max: RelativePC; parity: [0..2] _ 0; 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; IF cc.aligned THEN BEGIN IF parity = 2 THEN max _ max + 1 ELSE IF (parity+t) MOD 2 # 0 THEN t _ t + 1; parity _ 0; END ELSE IF parity # 2 THEN parity _ (parity+t) MOD 2; min _ min + t; max _ max + t; END; jump => IF cc.jtype # JumpC THEN BEGIN IF ~cc.fixedup THEN BEGIN [dMin,dMax] _ dMinMax[(SELECT cc.jtype FROM Jump,JumpA,JumpCA => unconditional, JumpE,JumpN => equal, ENDCASE => relational)][parity][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; parity _ (SELECT cc.jtype FROM Jump,JumpA,JumpCA => 2, JumpE,JumpN => IF cc.forward AND parity # 1 THEN 2 ELSE 0, ENDCASE => 0); END ELSE IF ~cc.completed THEN BEGIN deltamax: CARDINAL _ 0; t _ cc.jsize; IF t = 1 THEN BEGIN IF parity # 2 THEN parity _ (parity+1) MOD 2 END ELSE BEGIN IF parity = 2 THEN deltamax _ 1 ELSE IF (parity+t) MOD 2 # 0 THEN t _ t + 1; parity _ 0; END; IF ~cc.forward THEN BEGIN cc.minPC _ min; cc.maxPC _ max; END; min _ min + t; max _ max + deltamax + 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 deltamax: CARDINAL _ 0; t _ tablecodebytes; IF parity = 2 THEN deltamax _ 1 ELSE IF (parity+t) MOD 2 # 0 THEN t _ t + 1; parity _ 0; min _ min + t; max _ max + deltamax + t; END; ENDCASE; ENDCASE; ENDLOOP; RETURN END; END..