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],
System USING [NetworkAddress],
Rapunzel;
RapunzelServiceImpl:
PROGRAM
IMPORTS Heap, Inline, 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;
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
};
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] = {
result ← PeekOpCode[bH, address];
};
PokeShort:
PUBLIC
PROC [bH: BindHandle, address: Rapunzel.Address, value: Rapunzel.Short] = {
PokeOpCode[bH, address, value];
};
PeekLong:
PUBLIC
PROC [bH: BindHandle, address: Rapunzel.Address]
RETURNS [result: Rapunzel.Long] = {
xx: Inline.LongNumber;
xx.low ← PeekOpCode[bH, address];
xx.high ← PeekOpCode[bH, (address+1)];
result ← xx.lc;
};
PokeLong:
PUBLIC
PROC [bH: BindHandle, address: Rapunzel.Address, value: Rapunzel.Long] = {
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]];
results ← zone.NEW [Rapunzel.SeqShort ← DESCRIPTOR[chunk, count]];
FOR i:
CARDINAL
IN [0..count)
DO
results[i] ← PeekOpCode[bH, (address+i)];
ENDLOOP;
};
PokeSeqShort:
PUBLIC
PROC [bH: BindHandle, address: Rapunzel.Address, valueSeq:
LONG
POINTER
TO Rapunzel.SeqShort] = {
FOR i:
CARDINAL
IN [0..
LENGTH[valueSeq^])
DO
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]];
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 ← [PeekShort[bH, address]];
resultSeq[i] ← [peekShort[res]];
};
pokeShort => {
address: Rapunzel.Address = this.pokeShort.address;
res: pokeShort Rapunzel.Result = NULL;
PokeShort[bH, address, this.pokeShort.value];
resultSeq[i] ← res;
};
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[];
}...