DIRECTORY Basics USING [ BITSHIFT, bitsPerByte, bitsPerWord, Byte,bytesPerWord, DIVMOD, LDIVMOD, LongDiv, LongDivMod, LongMult, LongNumber], MesaRuntimeInit USING [], PrincOps USING [ BBptr, BBTableSpace, ByteBltBlock, GlobalFrameHandle, NullLink, sBLTE, sBLTEC, sBLTECL, sBLTEL, sBoundsFault, sBYTBLTE, sBYTBLTEC, sBYTBLTECL, sBYTBLTEL, SD, sLongDiv, sLongDivMod, sLongMod, sLongMul, sLongStringCheck, sPointerFault, sSignedDiv, sStringInit, StateVector, sULongDiv, sULongDivMod, sULongMod, zKFCB], PrincOpsUtils USING [ AlignedBBTable, Codebase, BITBLT, GetReturnFrame, GetReturnLink, LongCOPY]; InstructionsImpl: PROGRAM IMPORTS Basics, PrincOpsUtils EXPORTS MesaRuntimeInit, PrincOpsUtils = BEGIN BlockEqual: PROC [p1: POINTER, n: CARDINAL, p2: POINTER] RETURNS [BOOL] = {-- BLTE FOR i: CARDINAL IN [0 .. n) DO IF (p1+i)^ ~= (p2+i)^ THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] }; BlockEqualCodeLong: PROC [p1: LONG POINTER, n, offset: CARDINAL] RETURNS [BOOL] = {-- BLTECL p2: LONG POINTER = PrincOpsUtils.Codebase[PrincOpsUtils.GetReturnFrame[].accesslink]+offset; FOR i: CARDINAL IN [0 .. n) DO IF (p1+i)^ ~= (p2+i)^ THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] }; BlockEqualCode: PROC [p1: POINTER, n, offset: CARDINAL] RETURNS [BOOL] = {-- BLTEC p2: LONG POINTER = PrincOpsUtils.Codebase[PrincOpsUtils.GetReturnFrame[].accesslink]+offset; FOR i: CARDINAL IN [0 .. n) DO IF (p1+i)^ ~= (p2+i)^ THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] }; BlockEqualLong: PROC [p1: LONG POINTER, n: CARDINAL, p2: LONG POINTER] RETURNS [BOOL] = {-- BLTEL FOR i: CARDINAL IN [0 .. n) DO IF (p1+i)^ ~= (p2+i)^ THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] }; ByteBlockEqual: PROC [p1: PPA, n: CARDINAL, p2: PPA] RETURNS [BOOL] = -- BYTBLTE {RETURN[BlockEqual[p1: p1, p2: p2, n: n/2] AND p1[n-1] = p2[n-1]]}; ByteBlockEqualCode: PROC [p1: POINTER, n, offset: CARDINAL] RETURNS [BOOL] = {-- BYTBLTEC codebase: LONG POINTER = PrincOpsUtils.Codebase[PrincOpsUtils.GetReturnFrame[].accesslink]; RETURN[ByteBlockEqualLong[p2: codebase+offset, p1: p1, n: n]] }; ByteBlockEqualCodeLong: PROC [p1: LONG POINTER, n, offset: CARDINAL] RETURNS [result: BOOL] = {-- BYTBLTECL codebase: LONG POINTER = PrincOpsUtils.Codebase[PrincOpsUtils.GetReturnFrame[].accesslink]; RETURN[ByteBlockEqualLong[p2: codebase+offset, p1: p1, n: n]] }; PPA: TYPE = POINTER TO PACKED ARRAY [0..0) OF Basics.Byte; ByteBlockEqualLong: PROC [p1: LONG PPA, n: CARDINAL, p2: LONG PPA] RETURNS [BOOL] = -- BYTBLTEL {RETURN[BlockEqualLong[p1: p1, p2: p2, n: n/2] AND p1[n-1]=p2[n-1]]}; ByteBlt: PUBLIC PROC [to, from: PrincOps.ByteBltBlock] RETURNS [nBytes: CARDINAL] = { toBytes, fromBytes: LONG POINTER TO PACKED ARRAY [0..0) OF [0..377B); moved: CARDINAL _ 0; IF to.startIndex>to.stopIndexPlusOne OR from.startIndex>from.stopIndexPlusOne THEN ERROR; IF (nBytes _ MIN[to.stopIndexPlusOne-to.startIndex,from.stopIndexPlusOne-from.startIndex]) = 0 THEN RETURN; toBytes _ to.blockPointer; fromBytes _ from.blockPointer; IF to.startIndex MOD 2 ~= 0 THEN { toBytes[to.startIndex] _ fromBytes[from.startIndex]; moved _ 1; to.startIndex _ to.startIndex+1; from.startIndex _ from.startIndex+1; }; IF from.startIndex MOD 2 = 0 THEN { words: CARDINAL = (nBytes-moved)/2; PrincOpsUtils.LongCOPY[ to: toBytes+to.startIndex/2, from: fromBytes+from.startIndex/2, nwords: words]; IF moved+2*words ~= nBytes THEN toBytes[to.startIndex+2*words] _ fromBytes[from.startIndex+2*words]; } ELSE { bba: PrincOps.BBTableSpace; bbt: PrincOps.BBptr = PrincOpsUtils.AlignedBBTable[@bba]; lineWidth: CARDINAL = 16; -- words per scan line: controls interrupt latency bitsPerLine: CARDINAL = lineWidth*Basics.bitsPerWord; bytesPerLine: CARDINAL =lineWidth*Basics.bytesPerWord; lines: CARDINAL = (nBytes-moved)/bytesPerLine; -- bytes left to move with first BitBlt tail: CARDINAL = (nBytes-moved) MOD bytesPerLine; -- bytes left to move with second BitBlt bbt^ _ [ dst: [word: toBytes+to.startIndex/2, bit: 0], dstBpl: bitsPerLine, src: [word: fromBytes+from.startIndex/2, bit: 8], srcDesc: [srcBpl[bitsPerLine]], width: bitsPerLine, height: lines, flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: null, dstFunc: null]]; IF lines ~= 0 THEN PrincOpsUtils.BITBLT[bbt]; bbt.dst.word _ bbt.dst.word + lines*lineWidth; bbt.src.word _ bbt.src.word + lines*lineWidth; bbt.width _ Basics.bitsPerByte*tail; bbt.height _ 1; IF tail ~= 0 THEN PrincOpsUtils.BITBLT[bbt]; }; }; StringInit: PROC [coffset, n: CARDINAL, reloc, dest: POINTER] = { g: PrincOps.GlobalFrameHandle = PrincOpsUtils.GetReturnFrame[].accesslink; codebase: LONG POINTER = PrincOpsUtils.Codebase[g] + coffset; FOR i: CARDINAL IN [0..n) DO (dest+i)^ _ (codebase+i)^ + reloc; ENDLOOP; }; Number: TYPE = Basics.LongNumber; DIVMOD: PROC [n, d: CARDINAL] RETURNS [QR] = LOOPHOLE[Basics.DIVMOD]; LDIVMOD: PROC [nlow, nhigh, d: CARDINAL] RETURNS [QR] = LOOPHOLE[Basics.LDIVMOD]; QR: TYPE = RECORD [q, r: INTEGER]; PQR: TYPE = POINTER TO QR; SignDivide: PROC = { state: PrincOps.StateVector; p: PQR; t: CARDINAL; negnum, negden: BOOL; state _ STATE; state.stkptr _ t _ state.stkptr-1; state.dest _ PrincOpsUtils.GetReturnLink[]; state.source _ PrincOps.NullLink; 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]; IF negnum ~= negden THEN p.q _ -p.q; IF negnum THEN p.r _ -p.r; RETURN WITH state; }; DDivMod: PROC [num, den: Number] RETURNS [quotient, remainder: Number] = { negNum, negDen: BOOL _ FALSE; IF LOOPHOLE[num.highbits, INTEGER] < 0 THEN {negNum _ TRUE; num.li _ -num.li}; IF LOOPHOLE[den.highbits, INTEGER] < 0 THEN {negDen _ TRUE; den.li _ -den.li}; [quotient: quotient, remainder: remainder] _ DUnsignedDivMod[num: num, den: den]; IF negNum ~= negDen THEN quotient.li _ -quotient.li; IF negNum THEN remainder.li _ -remainder.li; }; DDiv: PROC [a, b: Number] RETURNS [Number] = {RETURN[DDivMod[a, b].quotient]}; DMod: PROC [a, b: Number] RETURNS [Number] = {RETURN[DDivMod[a, b].remainder]}; DMultiply: PROC [a, b: Number] RETURNS [product: Number] = { product.lc _ Basics.LongMult[a.lowbits, b.lowbits]; product.highbits _ product.highbits + a.lowbits*b.highbits + a.highbits*b.lowbits; }; DUnsignedDivMod: PROC [num, den: Number] RETURNS [quotient, remainder: Number] = { OPEN Basics; qq: CARDINAL; count: [0..31); lTemp: Number; IF den.highbits = 0 THEN { [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; } ELSE { 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 { div: Number _ Number[num[lowbits: 0, highbits: lTemp.lowbits]]; qq _ LongDiv[num.lc-div.lc, lTemp.lowbits]/2 + 100000B; count _ count - 1; } 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 lTemp.lc _ lTemp.lc - den.lc; qq _ qq - 1; ENDLOOP; quotient.lowbits _ qq; remainder.lc _ num.lc - lTemp.lc; }; }; DUnsignedDiv: PROC [a, b: Number] RETURNS [Number] = {RETURN[DUnsignedDivMod[a, b].quotient]}; DUnsignedMod: PROC [a, b: Number] RETURNS [Number] = {RETURN[DUnsignedDivMod[a, b].remainder]}; LongStringCheck: PROC = { state: PrincOps.StateVector; tos, index: CARDINAL; p: POINTER TO LONG STRING; BoundsFault: PROC = MACHINE CODE {PrincOps.zKFCB, PrincOps.sBoundsFault}; PointerFault: PROC = MACHINE CODE {PrincOps.zKFCB, PrincOps.sPointerFault}; state _ STATE; tos _ state.stkptr; index _ state.stk[tos]; p _ @state.stk[tos-2]; IF p^ = NIL THEN PointerFault[]; IF index >= p^.maxlength THEN BoundsFault[]; state.dest _ PrincOpsUtils.GetReturnLink[]; state.source _ PrincOps.NullLink; RETURN WITH state; }; Initialize: PROC = { OPEN PrincOps; pSD: POINTER TO ARRAY [0..0) OF UNSPECIFIED _ SD; pSD[sBLTE] _ BlockEqual; pSD[sBYTBLTE] _ ByteBlockEqual; pSD[sBLTEC] _ BlockEqualCode; pSD[sBYTBLTEC] _ ByteBlockEqualCode; pSD[sBLTECL] _ BlockEqualCodeLong; pSD[sBYTBLTECL] _ ByteBlockEqualCodeLong; pSD[sBLTEL] _ BlockEqualLong; pSD[sBYTBLTEL] _ ByteBlockEqualLong; pSD[sLongDiv] _ DDiv; pSD[sLongDivMod] _ DDivMod; pSD[sLongMod] _ DMod; pSD[sLongMul] _ DMultiply; pSD[sLongStringCheck] _ LongStringCheck; pSD[sULongDivMod] _ DUnsignedDivMod; pSD[sULongMod] _ DUnsignedMod; pSD[sULongDiv] _ DUnsignedDiv; pSD[sSignedDiv] _ SignDivide; pSD[sStringInit] _ StringInit; }; Initialize[]; END. InstructionsImpl.mesa last modified by Levin on August 8, 1983 10:47 am Unimplemented instructions. This stuff will be moved to the processor head as part of the architectural bootstrap. ByteBlt NB: to&from are RECORDs, not POINTERs to RECORDs, so we can update them This check is necessary since subtracting CARDINALs gives big numbers Move the first odd byte (if any) to be sure that "to" is word aligned Fast case: both are word aligned Move the one and only remaining byte Slow case: have to ripple things BitBlt is not interruptable except at the end of each scan line, so we break things up into chunks in order to maintain reasonable interrupt latency for the IO devices. It takes about 200microsec to move 50 bytes with the display off. This BitBlt moves a rectangle that is lineWidth words wide by as many lines high as will fit. NB: It cheats and actually reads a byte from beyond the edge of the rectangle. This is not really legal, but works out OK for any reasonable inplementation of BitBlt. update the pointers to reflect the work done, and then move one line that is less than lineWidth words wide. Data shuffling Long, signed and mixed mode arithmetic: subtract off 2^16*divisor and fix up count decrease quotient until product is small enough Other Initialization Κ Ύ– "Cedar" style˜Jšœ™J™1J˜šΟk ˜ šœœ˜Jšœ.œœ-˜s—Jšœœ˜šœ œ˜JšœšœŸ˜»—šœœ˜Jšœœ+˜KJ˜——šœ˜Jšœ˜Jšœ!˜(—J˜Jš˜J˜Jšœs™sJ˜šΟn œœœœœœœΟc˜Ršœœœ ˜Jšœœœœ˜)Jšœ˜—Jšœœ˜ Jšœ˜J˜—šžœœœœ œœœŸ ˜\JšœœœL˜\šœœœ ˜Jšœœœœ˜)Jšœ˜—Jšœœ˜ Jšœ˜J˜—š žœœœ œœœŸ˜RJšœœœL˜\šœœœ ˜Jš œœœœœ˜2—Jšœœ˜ Jšœ˜J˜—šžœœœœœœœœœŸ˜ašœœœ ˜Jšœœœœ˜)Jšœ˜—Jšœœ˜ Jšœ˜J˜—šžœœœœœœœŸ ˜PJšœœ$œ˜CJ˜—š žœœœ œœœŸ ˜YJšœ œœE˜[Jšœ7˜=Jšœ˜J˜—š žœœœœ œ˜DJšœ œŸ ˜&Jšœ œœE˜[Jšœ7˜=Jšœ˜J˜—Jšœœœœœœœ ˜:J˜šžœœœœœœœœœŸ ˜_Jšœœ(œ˜EJ˜J˜—J™J˜š žœœœ#œ œ˜UJšœG™GJš œœœœœœœ ˜EJšœœ˜J˜JšœE™EJšœ#œ'œœ˜YJšœ œOœœ˜kJ˜9JšœE™Ešœœœ˜"J˜4J˜ J˜ J˜$Jšœ˜—šœœœ˜#Jšœ ™ Jšœœ˜#˜J˜O—šœ˜Jšœ$™$J˜D—Jšœ˜—Jšœ ™ šœ˜Jšœλ™λJ˜J˜9Jšœ œŸ2˜LJšœ œ ˜5Jšœœ ˜6Jšœœ Ÿ'˜VJšœœœŸ(˜ZJ˜˜J˜BJ˜QJ˜"Jšœ&œœœ˜MJ˜J˜—Jšœ†™†Jšœ œœ˜-J˜Jšœl™lJ˜.J˜.J˜4Jšœ œœ˜,Jšœ˜—Jšœ˜J˜—Jšœ™J˜šž œœœœ˜AJšœK˜KJšœ œœ'˜=Jš œœœœ$œ˜HJšœ˜J˜—Jšœ'™'J˜Jšœœ˜!Jšœœœœœ œœ˜EJšœœœœœ œœ˜QJšœœœœ˜"Jš œœœœœ˜J˜šž œœ˜J˜Jšœœ˜Jšœœ˜ Jšœœ˜Jšœœ˜J˜"Jšœ+˜+J˜!J˜Jšœœ ˜&Jšœœ ˜&Jšœœ˜Jšœœ ˜$Jšœœ ˜Jšœœ˜Jšœ˜J˜—šžœœœ"˜JJšœœœ˜Jš œœœœ œœ˜NJš œœœœ œ˜NJ˜QJšœœ˜4Jšœœ˜,J˜J˜—šžœœœ ˜,Jšœœ˜!J˜—šžœœœ ˜,Jšœœ˜"J˜—šž œœœ˜