TeleLoad:
CEDAR
DEFINITIONS =
{
note: a LONG CARDINAL has the more significant
word at the higher memory address.
MaxByte: NAT = 200;
BlockIndex: TYPE = [0..MaxByte);
CoreAddress: TYPE = LONG CARDINAL;
BootTypeNumber: TYPE = LONG CARDINAL;
MachineTypeNumber: TYPE = LONG CARDINAL;
Byte: TYPE = [0..400B);
DataBlock: TYPE = PACKED ARRAY [0..0) OF Byte;
TLObject:
TYPE =
MONITORED
RECORD [
host: Rope.ROPE ← NIL,
address: Pup.Address,
cacheCB: CoreBlock ← NIL,
cacheSize: NAT ← 0,
addressSpace: AddressSpace ← main,
dirty: BOOLEAN ← FALSE,
log: IO.STREAM
];
Handle: TYPE = REF TLObject;
teleSwatSocket: Pup.Socket = [0, 0, 0, 60B];
locMaxByte is a public global variable which says how large a coreblock Larks are willing to handle.
locMaxByte: PUBLIC NAT;
Core fetch and store requests are identical except that the store request includes data. Both reply with the new contents of memory. The pupType of the reply is that of the request plus one.
coreStoreRequest: PupType.Type = LOOPHOLE[300B];
coreFetchRequest: PupType.Type = LOOPHOLE[302B];
The state fetch and store requests fetch and return the remote processor "state" whatever that may be. The count field must be the right value and the address field is a small integer indicating which block of state is involved, if there is more than one.
goRequest causes normal execution to resume using the given state.
singleStepRequest executes one instruction using the given state then returns to the debugger.
goFromBreakRequest single steps once, installs a breakpoint, then continues
For the 8088, the size of the state block is 28, it consists solely of the registers per State8086Object.
goRequest: PupType.Type = LOOPHOLE[304B];
stateFetchRequest: PupType.Type = LOOPHOLE[306B];
singleStepRequest: PupType.Type = LOOPHOLE[312B];
goFromBreakRequest: PupType.Type = LOOPHOLE[314B];
The running program is requested to go to the debugger. Whenever the debugger is entered, a packet of type eventBooted is transmitted. The eventBooted packet carries the machine state plus the boot reason.
debugRequest: PupType.Type = LOOPHOLE[310B];
eventBooted: PupType.Type = LOOPHOLE[311B];
Read and write in slave processor's address space.
slaveStoreRequest: PupType.Type = LOOPHOLE[316B];
slaveFetchRequest: PupType.Type = LOOPHOLE[320B];
Call a procedure with given arguments.
callRequest: PupType.Type = LOOPHOLE[322B];
The following records are contained in the data part of a Pup
Advice:
TYPE =
MACHINE
DEPENDENT
RECORD [
setHost: BOOLEAN,
setAdvice: BOOLEAN,
data: [0..37777B]
];
The fetch and store requests use this record.
CorePktObject:
TYPE =
MACHINE
DEPENDENT
RECORD [
advice: Advice,
address: CoreAddress,
count: CARDINAL,
data: DataBlock
];
CorePkt: TYPE = LONG POINTER TO CorePktObject;
This is the structure found in the data part of a CorePktObject for a procedure call.
CallPktObject:
TYPE =
MACHINE
DEPENDENT
RECORD [
proc: CARDINAL,
nargs: CARDINAL,
returnArg: CARDINAL,
args: ARRAY [0..5) OF CARDINAL
];
CallPkt: TYPE = LONG POINTER TO CallPktObject;
8086 state
Registers8086:
TYPE =
MACHINE
DEPENDENT {
AX(0), BX(1), CX(2), DX(3), SP(4), BP(5), SI(6),
DI(7), CS(8), DS(9), SS(10), ES(11), IP(12), FL(13)
};
State8086Object:
TYPE =
MACHINE
DEPENDENT
RECORD [
Regs: ARRAY Registers8086 OF CARDINAL
];
State8086: TYPE = LONG POINTER TO State8086Object;
The store requests and acknowledges use this record.
CoreBlockObject:
TYPE =
RECORD [
advice: Advice,
address: CoreAddress,
data: PACKED SEQUENCE count: NAT OF Byte
];
CoreBlock: TYPE = REF CoreBlockObject;
count may be odd, but the data array is padded to an even number of bytes.
Procedures
NameToAddress: PROC [name: Rope.ROPE] RETURNS [address: Pup.Address, ok: BOOL];
AddressToName: PROC [address: Pup.Address] RETURNS [nameRope, addressRope: Rope.ROPE];
Start: PROC [host: Rope.ROPE, log: IO.STREAM] RETURNS [h: Handle];
Stop: PROC [h: Handle];
TeleLoadProc:
TYPE =
PROC [h: Handle, cb: CoreBlock, tries:
NAT ← 5]
RETURNS [ok: BOOL, attempts: NAT];
Store: TeleLoadProc;
Fetch: TeleLoadProc;
Go: TeleLoadProc;
FetchState: TeleLoadProc;
SingleStep: TeleLoadProc;
GoFromBreak: TeleLoadProc;
GoToDebugger: TeleLoadProc;
SlaveStore: TeleLoadProc;
SlaveFetch: TeleLoadProc;
Call: TeleLoadProc;
eventBooted packets . . .
EventRecordObject:
TYPE =
MACHINE
DEPENDENT
RECORD [
regs: State8086Object,
reason: CARDINAL,
clockLow: CARDINAL,
clockHigh: CARDINAL,
bootSwitches: CARDINAL,
advice: CARDINAL,
monRelays: CARDINAL,
tlNet: CARDINAL,
tlHost: CARDINAL,
tlImHost: CARDINAL,
localNet: CARDINAL
];
EventRecord: TYPE = LONG POINTER TO EventRecordObject;
proc will be called with a CoreBlock containing an EventRecordObject. This part of the package uses TeleSwatSocket on the local machine.
EventProc: TYPE = PROC[who: Pup.Address, cb: EventRecordObject, clientData: REF ANY];
StartEventServer: PROC [proc: EventProc, clientData: REF ANY ← NIL];
StopEventServer: PROC;
Communications Procedures
This signal is raised on communiction failure from the routines below.
Failed: ERROR;
AddressSpace: TYPE = {main, slave};
GetCoreBlock:
PROC[h: Handle, addr: CoreAddress, count:
CARDINAL, addressSpace: AddressSpace ← main]
RETURNS [CoreBlock];
The following procedures deal with the handle.cacheCB
Read: PROC [h: Handle, addr: CoreAddress, addressSpace: AddressSpace ← main] RETURNS [CARDINAL];
ReadWord: PROC [h: Handle, addr: CoreAddress, addressSpace: AddressSpace ← main] RETURNS [CARDINAL];
Write: PROC [h: Handle, addr: CoreAddress, value: CARDINAL, addressSpace: AddressSpace ← main];
WriteWord: PROC [h: Handle, addr: CoreAddress, value: CARDINAL, addressSpace: AddressSpace ← main];
FlushWrites: PROC [h: Handle];
Invalidate the cache, so that new data will be fetched.
ResetCache: PROC [h: Handle];
If you are altering the memory image of a running program, it is wise to use a very small cache size. This procedure also does a FlushWrites before setting the size. A zero cache size sets the size to locMaxByte.
SetCacheSize: PROC [h: Handle, bytes: NAT];
utilities
Swab: PROC [a: CARDINAL] RETURNS [b: CARDINAL];
SwabState: PROC [state: State8086Object] RETURNS [State8086Object];
SwabEvent: PROC [state: EventRecordObject] RETURNS [EventRecordObject];
Send a single packet to stop the given machine from probing. IF grab, then set his debugging pointers to us.
StopHimProbing: PROC [h: Handle, setPointers: BOOL ← FALSE];
Read the event region of the remote machine.
GetEventData: PROC [h: Handle, setPointers: BOOL] RETURNS [event: EventRecordObject, ok: BOOL];
Worldwide failility, needed for anything to work
StartKing: PROC;
StopKing: PROC;
}.