-- RapunzelServiceImpl.mesa -- Copyright (C) 1986 by Xerox Corporation. All rights reserved. -- Bill Jackson (bj) September 22, 1986 6:31:14 pm PDT -- Willie-Sue, September 23, 1986 11:03:56 am PDT DIRECTORY ESCAlpha USING [alpha], Heap USING [systemZone], Inline USING [HighHalf, LowHalf, LongNumber], Mopcodes USING [zESC], Put USING [LongNumber, Text], System USING [NetworkAddress], Rapunzel; RapunzelServiceImpl: PROGRAM IMPORTS Heap, Inline, Put, Rapunzel EXPORTS Rapunzel = { OPEN Rapunzel; -- Types & Magic #'s pMemFetch: ESCAlpha.alpha = 3EH; pMemSmash: ESCAlpha.alpha = 3FH; firstPhysical: Rapunzel.Address = 0; lowestGuarded: Rapunzel.Address = (LONG[12]*256*256); -- 1.5MB lastPhysical: Rapunzel.Address = ((LONG[32]*256*256)-1); -- 2↑(5+8+8) words = 4MB lowerBound: CARDINAL = 0; upperBound: CARDINAL = 1023; Mem: TYPE = ARRAY [lowerBound..upperBound] OF WORD; -- Global State mem: Mem; nilHandle: BindHandle; simulation: BOOLEAN ← TRUE; debugging: BOOLEAN ← TRUE; Fault: PUBLIC ERROR [bH: BindHandle, code: Rapunzel.FaultCode, address: Rapunzel.Address] = CODE; MemFetch: PROC [LONG CARDINAL] RETURNS [WORD] = MACHINE CODE { Mopcodes.zESC, pMemFetch }; MemSmash: PROC [LONG CARDINAL, WORD] = MACHINE CODE { Mopcodes.zESC, pMemSmash }; Display: PROC [lead: LONG STRING, value: LONG CARDINAL] = { IF (NOT debugging) THEN RETURN; Put.Text[NIL, lead]; Put.LongNumber[NIL, value, [base: 8]]; Put.Text[NIL, "B\n"]; }; PeekOpCode: PROC [bH: BindHandle, addr: LONG CARDINAL] RETURNS [word: WORD] = INLINE { phys: CARDINAL = Inline.LowHalf[addr]; IF (simulation) THEN { IF NOT (phys IN [lowerBound..upperBound]) THEN ERROR Fault[bH, nonexistent, addr]; word ← mem[phys]; } ELSE { IF NOT (addr IN [lowestGuarded..lastPhysical]) THEN ERROR Fault[bH, IF (addr < lowestGuarded) THEN protection ELSE nonexistent, addr]; word ← MemFetch[addr]; }; }; PokeOpCode: PROC [bH: BindHandle, addr: LONG CARDINAL, word: WORD] = INLINE { phys: CARDINAL = Inline.LowHalf[addr]; IF (simulation) THEN { IF NOT (phys IN [lowerBound..upperBound]) THEN ERROR Fault[bH, nonexistent, addr]; mem[phys] ← word; } ELSE { IF NOT (addr IN [lowestGuarded..lastPhysical]) THEN ERROR Fault[bH, IF (addr < lowestGuarded) THEN protection ELSE nonexistent, addr]; MemSmash[addr, word]; }; }; PeekShort: PUBLIC PROC [bH: BindHandle, address: Rapunzel.Address] RETURNS [result: Rapunzel.Short] = { Display["PeekShort - address: ", address]; result ← PeekOpCode[bH, address]; Display[" result: ", result]; }; PokeShort: PUBLIC PROC [bH: BindHandle, address: Rapunzel.Address, value: Rapunzel.Short] = { Display["PokeShort - address: ", address]; Display[" value: ", value]; PokeOpCode[bH, address, value]; }; PeekLong: PUBLIC PROC [bH: BindHandle, address: Rapunzel.Address] RETURNS [result: Rapunzel.Long] = { xx: Inline.LongNumber; Display["PeekLong - address: ", address]; xx.low ← PeekOpCode[bH, address]; xx.high ← PeekOpCode[bH, (address+1)]; result ← xx.lc; Display[" result: ", result]; }; PokeLong: PUBLIC PROC [bH: BindHandle, address: Rapunzel.Address, value: Rapunzel.Long] = { Display["PokeLong - address: ", address]; Display[" value: ", value]; PokeOpCode[bH, address, Inline.LowHalf[value]]; PokeOpCode[bH, (address+1), Inline.HighHalf[value]]; }; PeekSeqShort: PUBLIC PROC [bH: BindHandle, address: Rapunzel.Address, count: CARDINAL] RETURNS [results: LONG POINTER TO Rapunzel.SeqShort] = { Chunk: TYPE = RECORD [SEQUENCE COMPUTED Rapunzel.SeqShortIndex OF Rapunzel.Short]; zone: UNCOUNTED ZONE = Heap.systemZone; chunk: LONG POINTER = zone.NEW [Chunk[count]]; Display["PeekSeqShort - address: ", address]; Display[" count: ", count]; results ← zone.NEW [Rapunzel.SeqShort ← DESCRIPTOR[chunk, count]]; FOR i: CARDINAL IN [0..count) DO results[i] ← PeekOpCode[bH, (address+i)]; Display[" ", results[i]]; ENDLOOP; }; PokeSeqShort: PUBLIC PROC [bH: BindHandle, address: Rapunzel.Address, valueSeq: LONG POINTER TO Rapunzel.SeqShort] = { Display["PokeSeqShort - address: ", address]; Display[" count: ", LENGTH[valueSeq↑]]; FOR i: CARDINAL IN [0..LENGTH[valueSeq↑]) DO Display[" ", valueSeq[i]]; PokeOpCode[bH, (address+i), valueSeq[i]]; ENDLOOP; }; DoCmds: PUBLIC PROC [bH: BindHandle, cmdSeq: LONG POINTER TO Rapunzel.SeqCmd] RETURNS [resultSeq: LONG POINTER TO Rapunzel.SeqResult] = { Chunk: TYPE = RECORD [SEQUENCE COMPUTED Rapunzel.SeqResultIndex OF Rapunzel.Result]; zone: UNCOUNTED ZONE = Heap.systemZone; chunk: LONG POINTER = zone.NEW [Chunk[cmdSeq↑.LENGTH]]; resultSeq ← zone.NEW [Rapunzel.SeqResult ← DESCRIPTOR[chunk, cmdSeq↑.LENGTH]]; Display["DoCmds -- count: ", cmdSeq↑.LENGTH]; FOR i: CARDINAL IN [0..cmdSeq↑.LENGTH) DO this: Rapunzel.Cmd = cmdSeq[i]; WITH this: this SELECT FROM peekShort => { address: Rapunzel.Address = this.peekShort.address; res: Rapunzel.PeekShortResult ← NULL; Display[" address: ", address]; res ← [PeekOpCode[bH, address]]; Display[" peekShort: ", res]; resultSeq[i] ← [peekShort[res]]; }; pokeShort => { address: Rapunzel.Address = this.pokeShort.address; -- res: Rapunzel.PokeShortResult ← NULL; Display[" address: ", address]; Display[" pokeShort: ", this.pokeShort.value]; PokeOpCode[bH, address, this.pokeShort.value]; resultSeq[i] ← [pokeShort[NULL]]; }; ENDCASE => ERROR Fault[bH, nonexistent, 0]; ENDLOOP; }; FreePeekSeqShortResults: PUBLIC PROC [bH: BindHandle, resultSeq: LONG POINTER TO SeqShort] = { zone: UNCOUNTED ZONE = Heap.systemZone; zone.FREE [@(resultSeq↑.BASE)]; zone.FREE [@(resultSeq)]; }; FreeDoCmdsResults: PUBLIC PROC [bH: BindHandle, resultSeq: LONG POINTER TO SeqResult] = { zone: UNCOUNTED ZONE = Heap.systemZone; zone.FREE [@(resultSeq↑.BASE)]; zone.FREE [@(resultSeq)]; }; Init: PROC = { trash: System.NetworkAddress ← TRASH; mem ← ALL[0]; nilHandle ← Rapunzel.RemoteBind[trash, NIL]; IF (nilHandle # NIL) THEN ERROR; }; Shutdown: PROC = { nilHandle ← Rapunzel.RemoteUnbind[nilHandle]; IF (nilHandle # NIL) THEN ERROR; }; Init[]; }...