DIRECTORY Alloc USING [Base, Notifier], Code USING [codeptr], CodeDefs USING [Base, CCIndex, CCNull, codeType, JumpCCIndex, JumpType, RelativePC], OpCodeParams USING [MaxBBJumps, MaxFBJumps, MaxFIAJumps, MaxFICJumps], P5F USING [CodeJumpDist, StartIndex]; DJumps: PROGRAM IMPORTS CPtr: Code, P5F EXPORTS CodeDefs, P5F = BEGIN OPEN OpCodeParams, CodeDefs; cb: CodeDefs.Base; -- code base (local copy) DJumpsNotify: PUBLIC Alloc.Notifier = BEGIN -- called by allocator whenever table area is repacked cb _ base[codeType]; END; BindJump: PUBLIC PROC [min, max: INTEGER, c: JumpCCIndex] RETURNS [bindable: BOOL _ TRUE] = BEGIN -- compute size of jump instruction(s) t: JumpType = cb[c].jtype; js: [0..7]; 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 NOT 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 NOT IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 4 ELSE bindable _ FALSE; JumpCA => IF max IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 2 ELSE IF min NOT IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 3 ELSE bindable _ FALSE; ENDCASE => IF max IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 2 ELSE IF min NOT IN [-MaxBBJumps..MaxFBJumps-2] THEN js _ 5 ELSE bindable _ FALSE; IF bindable THEN {cb[c].fixedup _ TRUE; cb[c].jsize _ js}; RETURN END; CodeJump: PUBLIC PROC [nbytes: INTEGER, c: JumpCCIndex] = BEGIN -- code all jump instruction(s) l: [0..7] = cb[c].jsize; forward: BOOL = cb[c].forward; dist: INTEGER _ IF ~forward THEN -nbytes ELSE nbytes+l; IF l > 3 THEN dist _ dist + 3 - l; CPtr.codeptr _ c; P5F.CodeJumpDist[dist, l, c]; END; dMinMax: ARRAY {unconditional, equal, relational} OF PACKED ARRAY BOOL 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) FillInPCEstimates: PUBLIC PROC = BEGIN min, max: RelativePC _ 0; FOR k: CCIndex _ P5F.StartIndex, cb[k].flink UNTIL k = CCNull DO WITH cc:cb[k] SELECT FROM code => BEGIN t: CARDINAL = cc.isize; min _ min + t; max _ max + t; END; jump => IF cc.jtype # JumpC THEN BEGIN IF ~cc.fixedup THEN BEGIN dMin, dMax: [0..15]; [dMin,dMax] _ dMinMax[(SELECT cc.jtype FROM Jump, JumpA, JumpCA => unconditional, JumpE, JumpN => equal, ENDCASE => relational)][cc.forward]; IF ~cc.forward THEN {cc.minPC _ min; cc.maxPC _ max}; min _ min+dMin; max _ max+dMax; IF cc.forward THEN {cc.minPC _ min; cc.maxPC _ max}; END ELSE IF ~cc.completed THEN BEGIN t: CARDINAL = cc.jsize; IF ~cc.forward THEN {cc.minPC _ min; cc.maxPC _ max}; min _ min + t; max _ max + t; IF cc.forward THEN {cc.minPC _ min; cc.maxPC _ max}; END; END; label => {cc.minPC _ min; cc.maxPC _ max}; other => WITH cc SELECT FROM table => BEGIN min _ min + tablecodebytes; max _ max + tablecodebytes; END; ENDCASE; ENDCASE; ENDLOOP; END; END. άDJumps.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Sweet, March 20, 1979 4:53 PM Satterthwaite, November 2, 1982 3:52 pm Russ Atkinson (RRA) March 6, 1985 11:15:13 pm PST max and min are counts of the number of bytes between the jump and the label. Computing dist 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 Κ?˜codešœ ™ Kšœ Οmœ1™