DragomanUtil.mesa
Copyright © 1984 by Xerox Corporation. All rights reversed.
Stolen from RESIUtil.mesa, by Sweet.
Bertrand Serlet, July 27, 1985 9:43:15 pm PDT
DIRECTORY
DragomanPrivate,
Basics,
CacheModels,
Convert,
DragOpsCross, DragOpsCrossUtils,
IO,
PrincOps,
Rope;
DragomanUtil: CEDAR PROGRAM
IMPORTS CacheModels, Convert, DragOpsCrossUtils, RI: DragomanPrivate, Rope
EXPORTS DragomanPrivate =
BEGIN
OPEN PrincOps;
Types and Global Data
Value: TYPE = RI.Value;
DValue: TYPE = RI.DValue;
Ptr1: TYPE = RI.Ptr1;
Ptr2: TYPE = RI.Ptr2;
LPtr1: TYPE = RI.LPtr1;
LPtr2: TYPE = RI.LPtr2;
ROPE: TYPE = Rope.ROPE;
Machine: TYPE = RI.Machine;
Byte: TYPE = RI.Byte;
Bytes: TYPE = RI.Bytes;
Pair: TYPE = RI.Pair;
FieldDescriptor: TYPE = PrincOps.FieldDescriptor;
LCB: TYPE = RI.LCB;
wordsPerPage: CARDINAL = CacheModels.wordsPerPage;
bytesPerWord: NAT = DragOpsCross.bytesPerWord;
LocalsInRing: NAT = 16;
Word: TYPE = DragOpsCross.Word;
FinishedExecution: PUBLIC SIGNAL = CODE; -- This should not be there!!!!
Cache Model stuff
CacheInfo: TYPE = DragomanPrivate.CacheInfo;
FlushAllCaches, FlushCaches: PUBLIC PROC [m: Machine] = {
cache: CacheInfo ← NARROW[m.cacheData];
IF cache = NIL THEN RETURN;
FOR i: NAT IN [0..cache.iCaches) DO CacheModels.Flush[cache.iCache[i]]; ENDLOOP;
FOR i: NAT IN [0..cache.dCaches) DO CacheModels.Flush[cache.dCache[i]]; ENDLOOP;
};
EnableCaches: PUBLIC PROC [m: Machine, state: BOOL] = {
cache: CacheInfo ← NARROW[m.cacheData];
cache.active ← state};
PrintCacheStats: PUBLIC PROC [os: IO.STREAM, m: Machine] = {
cache: CacheInfo ← NARROW[m.cacheData];
IF cache # NIL THEN {
FOR i: NAT IN [0..cache.iCaches) DO
CacheModels.Print[cache.iCache[i], os, Rope.Cat["Instruction cache ", Convert.RopeFromInt[i]]];
ENDLOOP;
FOR i: NAT IN [0..cache.dCaches) DO
CacheModels.Print[cache.dCache[i], os, Rope.Cat["Data cache ", Convert.RopeFromInt[i]]];
ENDLOOP;
};
};
Statistics recording
ReadAtAddress: PUBLIC PROC [m: Machine, addr: LONG POINTER] = TRUSTED {
cache: CacheInfo = NARROW[m.cacheData];
IF cache # NIL AND cache.active AND cache.dCaches # 0 THEN {
byteAddress: LONG CARDINALLOOPHOLE[addr, LONG CARDINAL]*2;
wordAddr: Word;
cacheIndex: NAT;
[wordAddr,] ← DragOpsCrossUtils.BytePCToWordAddress[
[DragOpsCrossUtils.CardToWord[byteAddress]]];
cacheIndex ← (DragOpsCrossUtils.WordToCard[wordAddr] / wordsPerPage) MOD cache.dCaches;
CacheModels.Fetch[cache.dCache[cacheIndex], wordAddr]};
};
DoubleReadAtAddress: PUBLIC PROC [m: Machine, addr: LONG POINTER] = TRUSTED {
tAddr: Basics.LongNumber = LOOPHOLE[addr];
ReadAtAddress[m, addr];
IF tAddr.lowbits MOD 2 # 0 THEN ReadAtAddress[m, addr+1];
};
ReadLocal: PUBLIC PROC [m: Machine, offset: CARDINAL] = TRUSTED {
IF offset >= PrincOps.localbase + LocalsInRing THEN
ReadAtAddress[m, m.l + offset]};
DoubleReadLocal: PUBLIC PROC [m: Machine, offset: CARDINAL] = TRUSTED {
IF offset >= PrincOps.localbase + LocalsInRing THEN
ReadAtAddress[m, m.l + offset];
IF offset MOD 2 # 0 THEN ReadAtAddress[m, m.l + offset + 1];
};
WriteAtAddress: PUBLIC PROC [m: Machine, addr: LONG POINTER] = TRUSTED {
cache: CacheInfo = NARROW[m.cacheData];
IF cache # NIL AND cache.active AND cache.dCaches # 0 THEN {
byteAddress: LONG CARDINALLOOPHOLE[addr, LONG CARDINAL]*2;
wordAddr: Word;
cacheIndex: NAT;
[wordAddr,] ← DragOpsCrossUtils.BytePCToWordAddress[
[DragOpsCrossUtils.CardToWord[byteAddress]]];
cacheIndex ← (DragOpsCrossUtils.WordToCard[wordAddr] / wordsPerPage) MOD cache.dCaches;
CacheModels.Store[cache.dCache[cacheIndex], wordAddr]};
};
DoubleWriteAtAddress: PUBLIC PROC [m: Machine, addr: LONG POINTER] = TRUSTED {
tAddr: Basics.LongNumber = LOOPHOLE[addr];
WriteAtAddress[m, addr+1];
IF tAddr.lowbits MOD 2 # 0 THEN WriteAtAddress[m, addr];
};
StoreLocal: PUBLIC PROC [m: Machine, offset: CARDINAL] = TRUSTED {
IF offset >= PrincOps.localbase + LocalsInRing THEN
WriteAtAddress[m, m.l + offset]};
DoubleStoreLocal: PUBLIC PROC [m: Machine, offset: CARDINAL] = TRUSTED {
IF offset >= PrincOps.localbase + LocalsInRing THEN
WriteAtAddress[m, m.l + offset+1];
IF offset MOD 2 # 0 THEN WriteAtAddress[m, m.l + offset];
};
Utilities
NextOpByte: PUBLIC PROC [m: Machine, opcode: BOOL] RETURNS [b: Byte] = {
note instruction fetch
cache: CacheInfo = NARROW[m.cacheData];
IF cache # NIL AND cache.active AND cache.iCaches # 0 THEN {
IF cache.iBufferBytes = 0 OR (opcode AND cache.iBufferBytes <= cache.iBufferSize - bytesPerWord) THEN TRUSTED {
cacheIndex: NAT;
wordAddrInCache: Word;
byteInWord: [0..bytesPerWord);
byteAddress: LONG CARDINALLOOPHOLE[m.cb, LONG CARDINAL]*2 + m.pc;
This is a PrincOps byte address!
[wordAddrInCache, byteInWord] ←
DragOpsCrossUtils.BytePCToWordAddress[
[DragOpsCrossUtils.CardToWord[byteAddress]]];
cacheIndex ← (DragOpsCrossUtils.WordToCard[wordAddrInCache] / wordsPerPage) MOD cache.iCaches;
CacheModels.Fetch[cache.iCache[cacheIndex], wordAddrInCache, cache.afterJump];
cache.iBufferBytes ←
IF cache.iBufferBytes = 0 THEN bytesPerWord - byteInWord
ELSE cache.iBufferBytes + bytesPerWord;
};
cache.iBufferBytes ← cache.iBufferBytes - 1;
cache.afterJump ← FALSE};
b ← LOOPHOLE[m.cb, LONG POINTER TO PACKED ARRAY [0..0) OF Byte][m.pc];
m.pc ← m.pc + 1;
};
SetPc: PUBLIC PROC [m: Machine, pc: CARDINAL] = {
note new pc value
WITH m.cacheData SELECT FROM
cache: CacheInfo => {cache.iBufferBytes ← 0; cache.afterJump ← TRUE};
ENDCASE;
m.pc ← pc};
UnboundProcTrap: PUBLIC PROC [m: Machine, link: ControlLink] = {ERROR Problem[m, unboundProc]};
ControlTrap: PUBLIC PROC [m: Machine, link: ControlLink] = {ERROR Problem[m, controlFault]};
Problem: PUBLIC ERROR [m: Machine, reason: RI.InterpreterProblem] = CODE;
Confusion: PUBLIC PROC [m: Machine] = {ERROR Problem[m, confused]};
NilFault: PUBLIC PROC [m: Machine] = {ERROR Problem[m, nilcheck]};
BoundsFault: PUBLIC PROC [m: Machine] = {ERROR Problem[m, boundscheck]};
Push: PUBLIC PROC [m: Machine, v: Value] = {m.stack[m.sd] ← v; m.sd ← m.sd + 1};
Pop: PUBLIC PROC [m: Machine] RETURNS [v: Value] = {m.sd ← m.sd - 1; RETURN [m.stack[m.sd]]};
Top: PUBLIC PROC [m: Machine] RETURNS [v: Value] = {RETURN [m.stack[m.sd-1]]};
Push2: PUBLIC PROC [m: Machine, v: DValue] = {
m.stack[m.sd] ← RI.VCard[v.lo];
m.stack[m.sd+1] ← RI.VCard[v.hi];
m.sd ← m.sd + 2};
Pop2: PUBLIC PROC [m: Machine] RETURNS [v: DValue] = {
m.sd ← m.sd - 2;
RETURN [[lo: RI.CardV[m.stack[m.sd]], hi: RI.CardV[m.stack[m.sd+1]]]]};
Read: PUBLIC PROC [m: Machine, p: LPtr1] RETURNS [Value] = TRUSTED {
ReadAtAddress[m, p];
RETURN [p^]};
ReadDouble: PUBLIC PROC [m: Machine, p: LPtr2] RETURNS [DValue] = TRUSTED {
DoubleReadAtAddress[m, p];
RETURN [p^]};
ReadField: PUBLIC PROC [m: Machine, p: LPtr1, fd: FieldDescriptor] RETURNS [Value] = TRUSTED {
ReadAtAddress[m, p];
RETURN [RI.RFSLOp[p, fd]]};
Write: PUBLIC PROC [m: Machine, p: LPtr1, v: Value] = TRUSTED {
WriteAtAddress[m, p];
p^ ← v};
WriteDouble: PUBLIC PROC [m: Machine, p: LPtr2, v: DValue] = TRUSTED {
DoubleWriteAtAddress[m, p];
p^ ← v};
WriteField: PUBLIC PROC [m: Machine, p: LPtr1, fd: FieldDescriptor, v: Value] = TRUSTED {
ReadAtAddress[m, p];
WriteAtAddress[m, p];
RI.WFSLOp[v: v, p: p, fd: fd]};
END.