-- NonResident.mesa; edited by Sandman, July 1, 1980 8:23 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AltoDefs USING [BYTE], ControlDefs USING [ ControlLink, FrameHandle, GFTItem, GFT, GlobalFrameHandle, StateVector], FrameDefs USING [SwapInCode], FrameOps USING [GetReturnFrame, GetReturnLink, ReleaseCode], InlineDefs USING [ BITSHIFT, BITXOR, COPY, DIVMOD, LongCOPY, LongDiv, LongDivMod, LongMult, LongNumber], Mopcodes USING [zRBL, zWBL], NucleusOps USING [], Runtime USING [], SDDefs USING [SD, sGFTLength], SDOps USING []; NonResident: PROGRAM IMPORTS FrameDefs, FrameOps, InlineDefs EXPORTS FrameDefs, FrameOps, NucleusOps, Runtime, SDOps SHARES ControlDefs =PUBLIC BEGIN OPEN ControlDefs; -- Frame validation InvalidGlobalFrame: SIGNAL [frame: GlobalFrameHandle] = CODE; ValidateGlobalFrame: PROCEDURE [g: GlobalFrameHandle] = BEGIN IF ~ValidGlobalFrame[g] THEN SIGNAL InvalidGlobalFrame[g]; END; ValidGlobalFrame: PROCEDURE [g: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN gft: POINTER TO ARRAY [0..0) OF GFTItem ← GFT; IF LOOPHOLE[g, ControlLink].tag # frame OR g.gfi >= SDDefs.SD[ SDDefs.sGFTLength] THEN RETURN[FALSE]; RETURN[gft[g.gfi].frame = g] END; InvalidFrame: SIGNAL [frame: FrameHandle] = CODE; ValidateFrame: PROCEDURE [f: FrameHandle] = BEGIN IF ~ValidFrame[f] THEN SIGNAL InvalidFrame[f]; END; ValidFrame: PROCEDURE [f: FrameHandle] RETURNS [BOOLEAN] = BEGIN RETURN[ LOOPHOLE[f, ControlLink].tag = frame AND ValidGlobalFrame[f.accesslink]] END; -- unimplemented instructions BlockEqual: PROCEDURE [p1: POINTER, n: CARDINAL, p2: POINTER] RETURNS [BOOLEAN] = BEGIN i: CARDINAL; FOR i IN [0..n) DO IF (p1 + i)↑ # (p2 + i)↑ THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] END; PPA: TYPE = POINTER TO PACKED ARRAY [0..0) OF AltoDefs.BYTE; ByteBlockEqual: PROCEDURE [p1: PPA, n: CARDINAL, p2: PPA] RETURNS [BOOLEAN] = BEGIN RETURN[BlockEqual[p1: p1, p2: p2, n: n/2] AND p1[n - 1] = p2[n - 1]] END; BlockEqualCode: PROCEDURE [p1: POINTER, n: CARDINAL, offset: CARDINAL] RETURNS [BOOLEAN] = BEGIN result: BOOLEAN; frame: GlobalFrameHandle = FrameOps.GetReturnFrame[].accesslink; FrameDefs.SwapInCode[frame]; result ← IF frame.code.highByte = 0 THEN BlockEqualLong[ p1: p1, n: n, p2: frame.code.longbase + offset] ELSE BlockEqual[p1: p1, n: n, p2: frame.code.shortbase + offset]; FrameOps.ReleaseCode[frame]; RETURN[result] END; ByteBlockEqualCode: PROCEDURE [p1: POINTER, n: CARDINAL, offset: CARDINAL] RETURNS [BOOLEAN] = BEGIN result: BOOLEAN; frame: GlobalFrameHandle = FrameOps.GetReturnFrame[].accesslink; FrameDefs.SwapInCode[frame]; result ← IF frame.code.highByte = 0 THEN ByteBlockEqualLong[ p1: p1, n: n, p2: frame.code.longbase + offset] ELSE ByteBlockEqual[p1: p1, n: n, p2: frame.code.shortbase + offset]; FrameOps.ReleaseCode[frame]; RETURN[result] END; ReadLongWord: PROCEDURE [LONG POINTER] RETURNS [CARDINAL] = MACHINE CODE BEGIN Mopcodes.zRBL, 0 END; BlockEqualLong: PROCEDURE [p1: LONG POINTER, n: CARDINAL, p2: LONG POINTER] RETURNS [BOOLEAN] = BEGIN i: CARDINAL; FOR i IN [0..n) DO IF ReadLongWord[p1 + i] # ReadLongWord[p2 + i] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] END; ByteBlockEqualLong: PROCEDURE [p1: LONG PPA, n: CARDINAL, p2: LONG PPA] RETURNS [BOOLEAN] = BEGIN w1, w2: RECORD [odd, ignore: [0..377B]]; IF ~BlockEqualLong[p1: p1, p2: p2, n: n/2] THEN RETURN[FALSE]; w1 ← LOOPHOLE[ReadLongWord[p1 + n/2]]; w2 ← LOOPHOLE[ReadLongWord[p2 + n/2]]; RETURN[w1.odd = w2.odd]; END; -- data shuffling LongReadWord: PROCEDURE [LONG POINTER] RETURNS [UNSPECIFIED] = MACHINE CODE BEGIN Mopcodes.zRBL, 0 END; LongWriteWord: PROCEDURE [UNSPECIFIED, LONG POINTER] = MACHINE CODE BEGIN Mopcodes.zWBL, 0 END; StringInit: PROCEDURE [coffset, n: CARDINAL, reloc, dest: POINTER] = BEGIN OPEN ControlDefs; g: GlobalFrameHandle = FrameOps.GetReturnFrame[].accesslink; i, j: CARDINAL; FrameDefs.SwapInCode[g]; IF g.code.highByte = 0 THEN BEGIN InlineDefs.LongCOPY[from: g.code.longbase + coffset, to: dest, nwords: n]; FOR i IN [0..n) DO j ← LongReadWord[dest + i]; LongWriteWord[j + reloc, dest + i]; ENDLOOP; END ELSE BEGIN InlineDefs.COPY[from: g.code.shortbase + coffset, to: dest, nwords: n]; FOR i IN [0..n) DO (dest + i)↑ ← (dest + i)↑ + reloc; ENDLOOP; END; FrameOps.ReleaseCode[g]; RETURN END; -- long, signed and mixed mode arithmetic DIVMOD: PROCEDURE [n, d: CARDINAL] RETURNS [QR] = LOOPHOLE[InlineDefs.DIVMOD]; QR: TYPE = RECORD [q, r: INTEGER]; PQR: TYPE = POINTER TO QR; SignDivide: PROCEDURE = BEGIN state: ControlDefs.StateVector; p: PQR; t: CARDINAL; negnum, negden: BOOLEAN; state ← STATE; state.stkptr ← t ← state.stkptr - 1; state.dest ← FrameOps.GetReturnLink[]; p ← @state.stk[t - 1]; IF negden ← (p.r < 0) THEN p.r ← -p.r; IF negnum ← (p.q < 0) THEN p.q ← -p.q; p↑ ← DIVMOD[n: p.q, d: p.r]; -- following assumes TRUE = 1; FALSE = 0 IF InlineDefs.BITXOR[negnum, negden] # 0 THEN p.q ← -p.q; IF negnum THEN p.r ← -p.r; RETURN WITH state END; DDivMod: PROCEDURE [num, den: Number] RETURNS [quotient, remainder: Number] = BEGIN negNum, negDen: BOOLEAN ← FALSE; IF LOOPHOLE[num.highbits, INTEGER] < 0 THEN BEGIN negNum ← TRUE; num.li ← -num.li; END; IF LOOPHOLE[den.highbits, INTEGER] < 0 THEN BEGIN negDen ← TRUE; den.li ← -den.li; END; [quotient: quotient, remainder: remainder] ← DUnsignedDivMod[ num: num, den: den]; IF InlineDefs.BITXOR[negNum, negDen] # 0 THEN quotient.li ← -quotient.li; IF negNum THEN remainder.li ← -remainder.li; RETURN END; DDiv: PROCEDURE [a, b: Number] RETURNS [Number] = BEGIN RETURN[DDivMod[a, b].quotient] END; DMod: PROCEDURE [a, b: Number] RETURNS [r: Number] = BEGIN [remainder: r] ← DDivMod[a, b]; RETURN END; DMultiply: PROCEDURE [a, b: Number] RETURNS [product: Number] = BEGIN product.lc ← InlineDefs.LongMult[a.lowbits, b.lowbits]; product.highbits ← product.highbits + a.lowbits*b.highbits + a.highbits*b.lowbits; RETURN END; Number: PRIVATE TYPE = InlineDefs.LongNumber; DUnsignedDivMod: PROCEDURE [num, den: Number] RETURNS [quotient, remainder: Number] = BEGIN OPEN InlineDefs; qq: CARDINAL; count: [0..31); lTemp: Number; IF den.highbits = 0 THEN BEGIN [quotient.highbits, qq] ← LongDivMod[ LOOPHOLE[Number[num[lowbits: num.highbits, highbits: 0]]], den.lowbits]; [quotient.lowbits, remainder.lowbits] ← LongDivMod[ LOOPHOLE[Number[num[lowbits: num.lowbits, highbits: qq]]], den.lowbits]; remainder.highbits ← 0; END ELSE BEGIN count ← 0; quotient.highbits ← 0; lTemp ← den; WHILE lTemp.highbits # 0 DO -- normalize lTemp.lowbits ← BITSHIFT[lTemp.lowbits, -1] + BITSHIFT[lTemp.highbits, 15]; lTemp.highbits ← BITSHIFT[lTemp.highbits, -1]; count ← count + 1; ENDLOOP; IF num.highbits >= lTemp.lowbits THEN BEGIN -- subtract off 2↑16*divisor and fix up count div: Number ← Number[num[lowbits: 0, highbits: lTemp.lowbits]]; qq ← LongDiv[num.lc - div.lc, lTemp.lowbits]/2 + 100000B; count ← count - 1; END ELSE qq ← LongDiv[num.lc, lTemp.lowbits]; -- trial quotient qq ← BITSHIFT[qq, -count]; lTemp.lc ← LongMult[den.lowbits, qq]; -- multiply by trial quotient lTemp.highbits ← lTemp.highbits + den.highbits*qq; UNTIL lTemp.lc <= num.lc DO -- decrease quotient until product is small enough lTemp.lc ← lTemp.lc - den.lc; qq ← qq - 1; ENDLOOP; quotient.lowbits ← qq; remainder.lc ← num.lc - lTemp.lc; END; RETURN END; DUnsignedDiv: PROCEDURE [a, b: Number] RETURNS [Number] = BEGIN RETURN[DUnsignedDivMod[a, b].quotient] END; DUnsignedMod: PROCEDURE [a, b: Number] RETURNS [r: Number] = BEGIN [remainder: r] ← DUnsignedDivMod[a, b]; RETURN END; END...