DIRECTORY Basics, CirioMemory, CirioNubAccess, IntHashTable, IO, LoadStateAccess, Rope, SymTab; CirioMemoryImpl: CEDAR PROGRAM IMPORTS Basics, CirioMemory, CirioNubAccess, IntHashTable, IO, Rope, SymTab EXPORTS CirioMemory = BEGIN OPEN CirioMemory, LSA:LoadStateAccess; Error: PUBLIC ERROR [msg: ROPE] ~ CODE; PtrRegName: ARRAY PtrReg OF ROPE ~ [fp: "fp", sp: "sp", fe: "fe"]; BaAsAbs: PUBLIC PROC [ba: BitAddr] RETURNS [BitAddr] ~ { IF ba.bits<0 THEN { ba.bits ¬ ba.bits + bitsPerAu; ba.aus ¬ ba.aus - 1; IF ba.bits<0 THEN Error["asked to absify a broken BitAddr"]; }; RETURN[ba]}; BaCompare: PUBLIC PROC [a, b: BitAddr] RETURNS [Basics.Comparison] ~ { a ¬ BaAsAbs[a]; b ¬ BaAsAbs[b]; SELECT TRUE FROM a.aus < b.aus => RETURN [less]; a.aus > b.aus => RETURN [greater]; a.bits < b.bits => RETURN [less]; a.bits > b.bits => RETURN [greater]; ENDCASE => RETURN [equal]}; BsCompose: PUBLIC PROC [main, inner: BitStretch] RETURNS [within: BOOL, compd: BitStretch] ~ { compd ¬ [main.start.BaAdd[inner.start], IF inner.size=unspecdBA AND main.size#unspecdBA THEN main.size.BaSub[inner.start] ELSE inner.size]; SELECT TRUE FROM BaCompare[inner.size, zeroBA] within ¬ FALSE; main.size=unspecdBA => within ¬ TRUE; BaCompare[inner.start, zeroBA] within ¬ FALSE; inner.size=unspecdBA => within ¬ TRUE; ENDCASE => within ¬ BaCompare[inner.start.BaAdd[inner.size], main.size]<=equal; RETURN}; MemIndirect: PUBLIC PROC [mem: Mem, size: BitAddr ¬ unspecdBA, offset: BitAddr ¬ zeroBA] RETURNS [Mem] ~ { base: CARD ~ mem.MemRead[bitsPerPtr, zeroBA]; RETURN mem.class.CreateSimple[mem.data, [start: PtrToBa[base].BaAdd[offset], size: size], FALSE]}; MemPtrRegIndirect: PUBLIC PROC [mem: Mem, ptrReg: PtrReg, size, offset: BitAddr, keepFrame: BOOL] RETURNS [Mem] ~ { ptrVal: BitStretch ~ mem.MemReadPtrReg[ptrReg]; sub: BitStretch; within: BOOL; [within, sub] ¬ BsCompose[ptrVal, [start: offset, size: size]]; IF NOT within THEN Error["MemPtrRegIndirecting out of bounds"]; RETURN mem.class.CreateSimple[mem.data, sub, keepFrame]}; MemSelectSegment: PUBLIC PROC [mem: Mem, segName: ROPE, segNum: INT, keepFrame: BOOL] RETURNS [Mem] ~ { seg: BitStretch ~ mem.MemReadSegReg[segName, segNum]; RETURN mem.class.CreateSimple[mem.data, seg, keepFrame]}; UMem: TYPE = REF UMemPrivate; UMemPrivate: TYPE ~ RECORD [ nub: CirioNubAccess.Handle, ptrs: ARRAY PtrReg OF BitStretch, segTables: SymTab.Ref--segName -> IntHashTable.Table(segNum -> REF BitStretch)--, rawStart, rawSize: BitAddr]; AintSimple: PROC [um: UMem] RETURNS [BOOL] ~ INLINE {RETURN[um.rawStart=unspecdBA]}; CreateSimpleMem: PUBLIC PROC[addr: CirioNubAccess.RemoteAddress, size: BitAddr ¬ unspecdBA] RETURNS[Mem] = { um: UMem; rawStart: BitAddr ¬ BaCons[addr.byteAddress, addr.bitOffset].BaAsAbs; IF rawStart=unspecdBA OR addr.nil OR NOT addr.valid THEN Error["trying to construct bogus Simple Mem in RMTWFrames"]; um ¬ NEW [UMemPrivate ¬ [ nub: addr.h, ptrs: ALL[[unspecdBA, unspecdBA]], segTables: SymTab.Create[--case?--], rawStart: rawStart, rawSize: size.BaAsAbs]]; RETURN[[uMemClass, um]]}; MakeDualMem: PUBLIC PROC [nub: CirioNubAccess.Handle, fp, sp: CARD, text, data, bss, fep, simple: BitStretch] RETURNS [mem: Mem] ~ { um: UMem ¬ NEW [UMemPrivate ¬ [ nub: nub, ptrs: [ fp: [IF fp=invalidPtr THEN unspecdBA ELSE PtrToBa[fp], unspecdBA], sp: [IF sp=invalidPtr THEN unspecdBA ELSE PtrToBa[sp], unspecdBA], fe: fep], segTables: SymTab.Create[--case?--], rawStart: simple.start, rawSize: simple.size ]]; mem ¬ [uMemClass, um]; IF text#unspecdBS THEN mem ¬ UAddSegReg[mem, "text", 0, text]; IF data#unspecdBS THEN mem ¬ UAddSegReg[mem, "data", 0, data]; IF bss#unspecdBS THEN mem ¬ UAddSegReg[mem, "bss", 0, bss]; RETURN}; UAddSegReg: PROC [mem: Mem, segName: ROPE, segNum: INT, val: BitStretch] RETURNS [--same--Mem] ~ { um: UMem ~ NARROW[mem.data]; segTable: IntHashTable.Table ¬ NARROW[um.segTables.Fetch[segName].val]; IF segTable=NIL THEN IF NOT um.segTables.Insert[segName, segTable ¬ IntHashTable.Create[]] THEN ERROR; IF NOT segTable.Insert[segNum, NEW[BitStretch ¬ val]] THEN Error["redefining segment register"]; RETURN[mem]}; uMemClass: MemClass ¬ NEW[MemClassPrivate ¬ [UCreateSimple, USubfield, UShift, UGetStretch, URead, UWrite, UReadPtrReg, UReadSegmentReg, USetPtrReg]]; UCreateSimple: PROC [data: REF ANY, stretch: BitStretch, keepFrame: BOOL] RETURNS [Mem] ~ { oldUm: UMem ~ NARROW[data]; new: Mem ¬ CreateSimpleMem[[h: oldUm.nub, byteAddress: stretch.start.aus, bitOffset: stretch.start.bits, nil: FALSE, valid: TRUE], stretch.size]; newUm: UMem ¬ NARROW[new.data]; CopySegReg: PROC [segName: ROPE, segNum: INT, val: BitStretch] RETURNS [BOOL] ~ {[] ¬ UAddSegReg[new, segName, segNum, val]; RETURN[FALSE]}; IF keepFrame THEN { newUm.ptrs ¬ oldUm.ptrs; IF UScanSegmentRegs[oldUm, CopySegReg].found THEN ERROR}; RETURN[new]}; USubfield: PROC [data: REF ANY, rel: BitStretch] RETURNS [Mem] ~ { oldUm: UMem ~ NARROW[data]; newUm: UMem ~ NEW [UMemPrivate ¬ oldUm­]; within: BOOL; IF AintSimple[oldUm] THEN Error["subfield of non-Simple Mem"]; [within, [newUm.rawStart, newUm.rawSize]] ¬ BsCompose[[oldUm.rawStart, oldUm.rawSize], rel]; IF NOT within THEN Error["taking subfield that extends outside main"]; RETURN[[uMemClass, newUm]]}; UShift: PROC [data: REF ANY, offset: BitAddr] RETURNS [Mem] ~ { oldUm: UMem ~ NARROW[data]; newUm: UMem ~ NEW [UMemPrivate ¬ oldUm­]; IF AintSimple[oldUm] THEN Error["shift of non-Simple Mem"]; newUm.rawStart ¬ newUm.rawStart.BaAdd[offset]; RETURN[[uMemClass, newUm]]}; UGetStretch: PROC [data: REF ANY] RETURNS [BitStretch] ~ { um: UMem ~ NARROW[data]; IF AintSimple[um] THEN Error["GetStretch of non-Simple Mem"]; RETURN[[um.rawStart, um.rawSize]]}; URead: PROC [data: REF ANY, bitSize: CARD, offset: BitAddr] RETURNS [CARD] ~ { um: UMem ~ NARROW[data]; readStart, readSize: BitAddr; lmask, ans: CARD; within: BOOL; afterLastBit: CARD; IF AintSimple[um] THEN Error["Read of non-Simple Mem"]; IF bitSize=0 THEN RETURN [0]; IF bitSize > 32 THEN Error["trying to read more than 32 bits at once"]; IF um.rawStart=zeroBA THEN Error["trying to read from NIL address"]; [within, [readStart, readSize]] ¬ BsCompose[[um.rawStart, um.rawSize], [offset, BitsToBa[bitSize]]]; readStart ¬ WordAlign[readStart]; IF NOT within THEN Error["trying to read outside of bounds"]; lmask ¬ Basics.BITRSHIFT[CARD.LAST, readStart.bits]; afterLastBit ¬ readStart.bits+bitSize; ans ¬ CirioNubAccess.Read32BitsAsCard[[um.nub, readStart.aus, 0, readStart.aus=0, TRUE]]; --doesn't work right with non-0 bitOffset ans ¬ Basics.BITAND[ans, lmask]; IF afterLastBit>32 THEN { ans2: CARD ~ CirioNubAccess.Read32BitsAsCard[[um.nub, readStart.aus+4, 0, readStart.aus+4=0, TRUE]]; ans ¬ Basics.BITOR[ Basics.BITLSHIFT[ans, afterLastBit-32], Basics.BITRSHIFT[ans2, 64-afterLastBit] ]; RETURN[ans]}; IF afterLastBit<32 THEN ans ¬ Basics.BITRSHIFT[ans, 32-afterLastBit]; RETURN[ans]}; UWrite: PROC [data: REF ANY, bits: CARD, bitSize: CARD, offset: BitAddr] ~ { um: UMem ~ NARROW[data]; writeStart, writeSize: BitAddr; afterLastBit: CARD; within: BOOL; IF AintSimple[um] THEN Error["Write of non-Simple Mem"]; IF bitSize=0 THEN RETURN; IF bitSize > 32 THEN Error["trying to write more than 32 bits at once"]; IF um.rawStart=zeroBA THEN Error["trying to write to NIL address"]; [within, [writeStart, writeSize]] ¬ BsCompose[[um.rawStart, um.rawSize], [offset, BitsToBa[bitSize]]]; IF NOT within THEN Error["trying to write outside of bounds"]; writeStart ¬ WordAlign[writeStart]; IF (afterLastBit ¬ writeStart.bits+bitSize) > 32 THEN {--split across two words lMaskNew: CARD ~ Basics.BITRSHIFT[CARD.LAST, writeStart.bits]; rMaskNew: CARD ~ Basics.BITLSHIFT[CARD.LAST, 64-afterLastBit]; lInsNew: CARD ~ Basics.BITRSHIFT[bits, afterLastBit-32]; rInsNew: CARD ~ Basics.BITLSHIFT[bits, 64-afterLastBit]; lOld: CARD ~ CirioNubAccess.Read32BitsAsCard[[um.nub, writeStart.aus, 0, writeStart.aus=0, TRUE]]; rOld: CARD ~ CirioNubAccess.Read32BitsAsCard[[um.nub, writeStart.aus+4, 0, writeStart.aus+4=0, TRUE]]; lNew: CARD ~ Basics.BITOR[Basics.BITAND[lInsNew, lMaskNew], Basics.BITAND[lOld, Basics.BITNOT[lMaskNew]]]; rNew: CARD ~ Basics.BITOR[Basics.BITAND[rInsNew, rMaskNew], Basics.BITAND[rOld, Basics.BITNOT[rMaskNew]]]; CirioNubAccess.WriteCardAs32Bits[[um.nub, writeStart.aus, 0, FALSE, TRUE], lNew]; CirioNubAccess.WriteCardAs32Bits[[um.nub, writeStart.aus+4, 0, FALSE, TRUE], rNew]; RETURN} ELSE { hmn: CARD ~ 2**(bitSize-1); maskNew: CARD ~ Basics.BITLSHIFT[hmn+(hmn-1), 32-afterLastBit]; insNew: CARD ~ Basics.BITLSHIFT[bits, 32-afterLastBit]; old: CARD ~ CirioNubAccess.Read32BitsAsCard[[um.nub, writeStart.aus, 0, writeStart.aus=0, TRUE]]; new: CARD ~ Basics.BITOR[Basics.BITAND[insNew, maskNew], Basics.BITAND[old, Basics.BITNOT[maskNew]]]; CirioNubAccess.WriteCardAs32Bits[[um.nub, writeStart.aus, 0, FALSE, TRUE], new]; RETURN}; }; WordAlign: PROC [ba: BitAddr] RETURNS [BitAddr] ~ { rem: CARD; ba ¬ ba.BaAsAbs[]; rem ¬ ba.aus MOD 4; ba.aus ¬ ba.aus - rem; ba.bits ¬ ba.bits + rem*8; RETURN[ba]}; UReadPtrReg: PROC [data: REF ANY, ptrReg: PtrReg] RETURNS [BitStretch] ~ { um: UMem ~ NARROW[data]; bs: BitStretch ~ um.ptrs[ptrReg]; IF bs.start=unspecdBA THEN Error[Rope.Cat["reading undefined pointer register (", PtrRegName[ptrReg], ")"]]; IF bs.start.bits#0 THEN Error[Rope.Cat["found non-AU-aligned pointer! (", PtrRegName[ptrReg], ")"]]; RETURN[bs]}; UReadSegmentReg: PROC [data: REF ANY, segName: ROPE, segNum: INT] RETURNS [BitStretch] ~ { um: UMem ~ NARROW[data]; segTable: IntHashTable.Table ~ NARROW[um.segTables.Fetch[segName].val]; rbs: REF BitStretch; IF segTable=NIL THEN Error[IO.PutFR["trying to read non-existing segment register (for \"%q\" (#%g))", [rope[segName]], [integer[segNum]] ]]; rbs ¬ NARROW[segTable.Fetch[segNum].value]; IF rbs=NIL THEN Error[IO.PutFR["trying to read non-existing segment register (for #%g of \"%q\")", [integer[segNum]], [rope[segName]] ]]; RETURN[rbs­]}; USetPtrReg: PROC [data: REF ANY, ptrReg: PtrReg, val: BitStretch] ~ { um: UMem ~ NARROW[data]; um.ptrs[ptrReg] ¬ val; RETURN}; UScanSegmentRegs: PROC [data: REF ANY, Consume: PROC [segName: ROPE, segNum: INT, val: BitStretch] RETURNS [BOOL]] RETURNS [found: BOOL ¬ FALSE, itsName: ROPE ¬ NIL, itsNum: INT ¬ 0] ~ { um: UMem ~ NARROW[data]; PerSegTable: PROC [key: ROPE, val: REF ANY] RETURNS [quit: BOOL ¬ FALSE] ~ { segName: ROPE ~ key; segTable: IntHashTable.Table ~ NARROW[val]; PerSeg: PROC [key: INT, value: REF ANY] RETURNS [quit: BOOL] ~ { rbs: REF BitStretch ~ NARROW[value]; IF Consume[segName, key, rbs­] THEN { found ¬ TRUE; itsName ¬ segName; itsNum ¬ key}; RETURN[found]}; [] ¬ segTable.Pairs[PerSeg]; RETURN[found]}; IF um.segTables#NIL THEN [] ¬ um.segTables.Pairs[PerSegTable]; RETURN}; END. š CirioMemoryImpl.mesa Copyright Σ 1991, 1992 by Xerox Corporation. All rights reserved. Laurie Horton, September 20, 1991 8:36 am PDT Last tweaked by Mike Spreitzer April 24, 1992 12:27 pm PDT Philip James, February 24, 1992 9:59 am PST Willie-s, May 14, 1992 2:22 pm PDT Note: ABS[bits] < bitsPerAu. Note: 0 <= bits < bitsPerAu. MJS, May 23, 1991: As I write this for the first time, I am aware of no constraints on how I treat negatively-sized stretches, as I don't expect them to appear. MJS, May 25, 1991: when main.size=unspecdBA, this is a base address from which negative offsets are valid (ie, may be within). These cover both Simple and Frame Mems. Κ –(cedarcode) style•NewlineDelimiter ™code™Kšœ Οeœ7™BK™-K™:K™+K™"—K˜KšΟk œ4žœ ˜_K˜šΟnœžœž˜Kšžœ4žœ˜KKšžœ ˜—K˜Kšœžœžœžœ˜.K˜Kš Ÿœžœžœžœžœ˜'K˜šŸ œžœžœž˜ K˜!—K˜šŸœžœžœžœ˜8šžœ žœ˜K˜K˜Kšžœ žœ+˜žœžœ ˜sKšœ/˜/K˜Kšœžœ˜ K˜?Kšžœžœžœ-˜?Kšžœ3˜9—K˜šŸœžœžœžœ žœ žœžœ ˜gKšœ5˜5Kšžœ3˜9—K˜Kšœžœžœ ˜šœ žœžœ˜K˜Kšœžœžœ ˜!KšœΟc;œ˜QKšœ˜K™'—K˜šŸ œžœ žœžœ˜*Kšœžœžœ˜)—K˜šŸœžœžœ@žœ ˜lKšœ ˜ K˜EKš žœžœ žœžœ žœ=˜ušœžœ˜K˜ Kšœžœ˜"Kšœ  œ˜$Kšœ˜Kšœ˜—Kšžœ˜—K˜š Ÿ œžœžœ&žœ,žœ˜„šœ žœ˜K˜ ˜Kšœžœžœ žœ˜BKšœžœžœ žœ˜BKšœ ˜ —Kšœ  œ˜$K˜K˜—K˜Kšžœžœ(˜>Kšžœžœ(˜>Kšžœžœ&˜;Kšžœ˜—K˜š Ÿ œžœžœ žœžœ œ˜bKšœ žœ ˜Kšœžœ"˜GKšžœ žœžœžœžœ@žœžœ˜fKšžœžœžœžœ&˜`Kšžœ˜ —K˜Kšœžœ}˜–K˜š Ÿ œžœžœžœ"žœžœ ˜[Kšœžœ˜Kšœnžœ žœ˜‘Kšœžœ ˜š Ÿ œžœ žœ žœžœžœ˜MKšœ/žœžœ˜>—šžœ žœ˜K˜Kšžœ+žœžœ˜9—Kšžœ˜ —K˜š Ÿ œžœžœžœžœ ˜BKšœžœ˜Kšœžœ˜)Kšœžœ˜ Kšžœžœ%˜>K˜\Kšžœžœžœ4˜FKšžœ˜—K˜š Ÿœžœžœžœžœ ˜?Kšœžœ˜Kšœžœ˜)Kšžœžœ"˜;K˜.Kšžœ˜—K˜š Ÿ œžœžœžœžœ˜:Kšœ žœ˜Kšžœžœ'˜=Kšžœ˜#—K˜šŸœžœžœžœ žœžœžœ˜NKšœ žœ˜K˜Kšœ žœ˜Kšœžœ˜ Kšœžœ˜Kšžœžœ!˜7Kšžœ žœžœ˜Kšžœžœ3˜GKšžœžœ*˜DK˜dK˜!Kšžœžœžœ+˜=Kšœž œžœžœ˜4K˜&KšœRžœ )˜ƒKšœ žœ ˜ šžœžœ˜KšœžœSžœ˜dšœ žœ˜Kšœž œ˜'Kšœž œ˜*—Kšžœ˜ —Kšžœžœž œ˜EKšžœ˜ —K˜š Ÿœžœžœžœžœ žœ˜LKšœ žœ˜K˜Kšœžœ˜Kšœžœ˜ Kšžœžœ"˜8Kšžœ žœžœ˜Kšžœžœ4˜HKšžœžœ)˜CK˜fKšžœžœžœ,˜>K˜#šžœ/žœ ˜OKš œ žœ ž œžœžœ˜>Kš œ žœ ž œžœžœ˜>Kšœ žœ ž œ˜8Kšœ žœ ž œ˜8KšœžœQžœ˜bKšœžœUžœ˜fKš œžœ žœžœžœžœ ˜jKš œžœ žœžœžœžœ ˜jKšœ=žœžœ ˜QKšœ?žœžœ ˜SKšžœ˜—šžœ˜Kšœžœ˜Kšœ žœ ž œ˜?Kšœžœ ž œ˜7KšœžœQžœ˜aKš œžœ žœžœžœ žœ ˜eKšœ=žœžœ˜PKšžœ˜—Kšœ˜—K˜šŸ œžœžœ˜3Kšœžœ˜ K˜Kšœ žœ˜K˜K˜Kšžœ˜ —K˜š Ÿ œžœžœžœžœ˜JKšœ žœ˜K˜!KšžœžœR˜lKšžœžœM˜dKšžœ˜ —K˜šŸœžœžœžœ žœ žœžœ˜ZKšœ žœ˜Kšœžœ"˜GKšœžœ ˜Kšžœ žœžœžœp˜Kšœžœ˜+Kšžœžœžœžœq˜‰Kšžœ˜—K˜šŸ œžœžœžœ&˜EKšœ žœ˜K˜Kšžœ˜—K˜š ŸœžœžœžœŸœžœ žœ žœžœžœžœ žœžœ žœžœ žœ ˜ΊKšœ žœ˜šŸ œžœžœžœžœžœžœžœ˜LKšœ žœ˜Kšœžœ˜+šŸœžœžœ žœžœžœžœ˜@Kšœžœžœ˜$šžœžœ˜%Kšœžœ˜ K˜K˜—Kšžœ ˜—K˜Kšžœ ˜—Kšžœžœžœ&˜>Kšžœ˜—K˜Kšžœ˜—…—)ή8~