LarkWorkCommandsA.mesa
L. Stewart, December 22, 1983 2:43 pm
DIRECTORY
Ascii USING [BS, CR, LF],
Basics USING [BITAND, LowHalf],
CommandTool USING [ArgumentVector],
Convert USING [CardFromRope, Error],
IO,
LarkControl USING [BootReason, Breakpoint, BreakpointObject, DisplayEvent, DisplayState, FetchState, LarkData, LoadProgram, LocalGo, RepairBreakpoint, SetState, SetValue, VerifyInternal],
LarkPrograms USING [AddOrReplaceProgram, FetchProgram, FindVariable, Monitor, PatchFromFile, PatchItem, ProcedureEnclosing, Program, ReadProgramFromDisk, STObject],
LarkWork USING [LarkWorkProc, RegisterLarkWorkProc],
Process USING [MsecToTicks, Pause],
ProcessExtras USING [CheckForAbort],
Rope USING [Concat, Equal, ROPE],
TeleLoad USING [AddressSpace, CoreAddress, CoreBlock, CoreBlockObject, EventRecordObject, Failed, Fetch, FlushWrites, GetEventData, GoToDebugger, Handle, locMaxByte, Read, ReadWord, Registers8086, ResetCache, SetCacheSize, SingleStep, State8086Object, Store, Write, WriteWord];
LarkWorkCommandsA: CEDAR PROGRAM
IMPORTS Basics, Convert, IO, LarkControl, LarkPrograms, LarkWork, Process, ProcessExtras, Rope, TeleLoad =
BEGIN
BadCommRope: Rope.ROPE = "Communications Failure\n";
BadArgsRope: Rope.ROPE = "Bad Arguments\n";
SetCurrentProgram: LarkWork.LarkWorkProc = {
IF argv.argc < 2 THEN RETURN["Requires programName as argument\n"];
IF NOT capital THEN { -- main CPU
lark.program ← LarkPrograms.FetchProgram[argv[1]];
IF lark.program = NIL THEN RETURN[Rope.Concat[argv[1], " not found\n"]];
}
ELSE { -- slave cpu
lark.slaveProgram ← LarkPrograms.FetchProgram[argv[1]];
IF lark.slaveProgram = NIL THEN RETURN[Rope.Concat[argv[1], " not found\n"]];
};
};
Go: LarkWork.LarkWorkProc = {
LarkControl.LocalGo[lark];
};
SingleStep: LarkWork.LarkWorkProc = {
ENABLE {
TeleLoad.Failed => GOTO BadComm;
};
found: BOOLFALSE;
breakpoint: LarkControl.Breakpoint;
FOR l: LIST OF LarkControl.Breakpoint ← lark.breakList, l.rest WHILE l # NIL DO
IF l.first.address = lark.state.Regs[IP] THEN {
found ← TRUE;
breakpoint ← l.first;
EXIT;
};
ENDLOOP;
IF found THEN {
LarkControl.RepairBreakpoint[h: lark.h, breakpoint: breakpoint];
[] ← LarkControl.SetState[h: lark.h, state: lark.state, tp: TeleLoad.SingleStep, print: TRUE];
Process.Pause[Process.MsecToTicks[50]];
TeleLoad.SetCacheSize[lark.h, 1];
TeleLoad.Write[lark.h, breakpoint.address, 0CCH];
TeleLoad.FlushWrites[lark.h];
TeleLoad.SetCacheSize[lark.h, 0];
}
ELSE [] ← LarkControl.SetState[h: lark.h, state: lark.state, tp: TeleLoad.SingleStep, print: TRUE];
EXITS
BadComm => RETURN[BadCommRope];
};
GetState: LarkWork.LarkWorkProc = {
localState: TeleLoad.State8086Object;
ok: BOOL;
lark.h.log.PutRope["State\n"];
IF capital THEN {
[ok, localState] ← LarkControl.FetchState[h: lark.h];
IF ok THEN lark.state ← localState;
};
LarkControl.DisplayState[lark.h.log, lark.state];
};
AlterVariable: LarkWork.LarkWorkProc = {
ENABLE Convert.Error => GOTO BadArgs;
variableName: Rope.ROPE;
offset: NAT ← 0;
value: CARDINAL;
IF argv.argc > 1 THEN variableName ← argv[1]
ELSE RETURN;
SELECT argv.argc FROM
3 => value ← Basics.LowHalf[Convert.CardFromRope[argv[2], 16]];
ENDCASE => {
value ← Basics.LowHalf[Convert.CardFromRope[argv[3], 16]];
offset ← Basics.LowHalf[Convert.CardFromRope[argv[2], 16]];
};
[] ← LarkControl.SetValue[lark: lark, name: variableName, value: value, offset: offset];
EXITS
BadArgs => RETURN["Bad arguments\n"];
};
AlterVariablesFromFile: LarkWork.LarkWorkProc = {
ENABLE TeleLoad.Failed => GOTO BadComm;
pl: LIST OF LarkPrograms.PatchItem;
IF argv.argc # 2 THEN RETURN;
pl ← LarkPrograms.PatchFromFile[program: lark.program, fileName: argv[1], log: lark.h.log];
TeleLoad.SetCacheSize[h: lark.h, bytes: 2];
WHILE pl # NIL DO
TeleLoad.WriteWord[h: lark.h, addr: pl.first.address, value: pl.first.wordValue];
lark.h.log.PutChar['p];
pl ← pl.rest;
ENDLOOP;
TeleLoad.FlushWrites[lark.h];
TeleLoad.SetCacheSize[h: lark.h, bytes: 0];
lark.h.log.PutChar['\n];
EXITS
BadComm => RETURN[BadCommRope];
};
SetBlock: LarkWork.LarkWorkProc = {
ENABLE {
Convert.Error => GOTO BadArgs;
TeleLoad.Failed => GOTO BadComm;
};
destination: TeleLoad.CoreAddress;
addr: TeleLoad.CoreAddress;
count: LONG CARDINAL;
value: CARDINAL;
IF argv.argc NOT IN [4..5] THEN GOTO BadArgs;
destination ← Convert.CardFromRope[argv[1], 16];
count ← Convert.CardFromRope[argv[2], 16];
value ← Basics.LowHalf[Convert.CardFromRope[argv[3], 16]];
TeleLoad.FlushWrites[lark.h];
TeleLoad.ResetCache[lark.h];
TeleLoad.SetCacheSize[lark.h, 0];
addr ← destination;
WHILE addr < (destination+count) DO
TeleLoad.WriteWord[h: lark.h, addr: addr, value: value];
addr ← addr + 2;
ENDLOOP;
TeleLoad.FlushWrites[lark.h];
TeleLoad.ResetCache[lark.h];
EXITS
BadArgs => RETURN[BadArgsRope];
BadComm => RETURN[BadCommRope];
};
CheckSetBlock: LarkWork.LarkWorkProc = {
ENABLE {
Convert.Error => GOTO BadArgs;
TeleLoad.Failed => GOTO BadComm;
};
destination: TeleLoad.CoreAddress;
addr: TeleLoad.CoreAddress;
count: LONG CARDINAL;
value, found: CARDINAL;
IF argv.argc # 4 THEN GOTO BadArgs;
destination ← Convert.CardFromRope[argv[1], 16];
count ← Convert.CardFromRope[argv[2], 16];
value ← Basics.LowHalf[Convert.CardFromRope[argv[3], 16]];
TeleLoad.FlushWrites[lark.h];
TeleLoad.ResetCache[lark.h];
TeleLoad.SetCacheSize[lark.h, 0];
addr ← destination;
WHILE addr < (destination+count) DO
found ← TeleLoad.ReadWord[h: lark.h, addr: addr];
IF found # value THEN {
lark.h.log.PutF["%04x is %04x\n", IO.card[addr], IO.card[found]];
ProcessExtras.CheckForAbort[];
};
addr ← addr + 2;
ENDLOOP;
TeleLoad.FlushWrites[lark.h];
TeleLoad.ResetCache[lark.h];
EXITS
BadArgs => RETURN[BadArgsRope];
BadComm => RETURN[BadCommRope];
};
FillWithAddress: LarkWork.LarkWorkProc = {
ENABLE {
Convert.Error => GOTO BadArgs;
TeleLoad.Failed => GOTO BadComm;
};
destination: TeleLoad.CoreAddress;
addr: TeleLoad.CoreAddress;
count: LONG CARDINAL;
bytes: BOOL ← capital;
IF argv.argc # 3 THEN RETURN;
destination ← Convert.CardFromRope[argv[1], 16];
count ← Convert.CardFromRope[argv[2], 16];
TeleLoad.FlushWrites[lark.h];
TeleLoad.ResetCache[lark.h];
TeleLoad.SetCacheSize[lark.h, 0];
addr ← destination;
WHILE addr < (destination+count) DO
IF bytes THEN {
TeleLoad.Write[h: lark.h, addr: addr, value: Basics.BITAND[Basics.LowHalf[addr], 0377B]];
addr ← addr + 1;
}
ELSE {
TeleLoad.WriteWord[h: lark.h, addr: addr, value: Basics.LowHalf[addr]];
addr ← addr + 2;
};
ENDLOOP;
TeleLoad.FlushWrites[lark.h];
TeleLoad.ResetCache[lark.h];
EXITS
BadArgs => RETURN[BadArgsRope];
BadComm => RETURN[BadCommRope];
};
CheckAddressFill: LarkWork.LarkWorkProc = {
ENABLE {
Convert.Error => GOTO BadArgs;
TeleLoad.Failed => GOTO BadComm;
};
destination: TeleLoad.CoreAddress;
addr: TeleLoad.CoreAddress;
count: LONG CARDINAL;
bytes: BOOL ← capital;
found: CARDINAL;
IF argv.argc # 3 THEN RETURN;
destination ← Convert.CardFromRope[argv[1], 16];
count ← Convert.CardFromRope[argv[2], 16];
TeleLoad.FlushWrites[lark.h];
TeleLoad.ResetCache[lark.h];
TeleLoad.SetCacheSize[lark.h, 0];
addr ← destination;
WHILE addr < (destination+count) DO
IF bytes THEN {
found ← TeleLoad.Read[h: lark.h, addr: addr];
IF found # LOOPHOLE[Basics.BITAND[Basics.LowHalf[addr], 0377B], CARDINAL] THEN {
lark.h.log.PutF["%04x is %02x\n", IO.card[addr], IO.card[found]];
ProcessExtras.CheckForAbort[];
};
addr ← addr + 1;
}
ELSE {
found ← TeleLoad.ReadWord[h: lark.h, addr: addr];
IF found # LOOPHOLE[Basics.LowHalf[addr], CARDINAL] THEN {
lark.h.log.PutF["%04x is %04x\n", IO.card[addr], IO.card[found]];
ProcessExtras.CheckForAbort[];
};
addr ← addr + 2;
};
ENDLOOP;
EXITS
BadArgs => RETURN[BadArgsRope];
BadComm => RETURN[BadCommRope];
};
Blit: LarkWork.LarkWorkProc = {
ENABLE {
Convert.Error => GOTO BadArgs;
TeleLoad.Failed => GOTO BadComm;
};
source, destination: TeleLoad.CoreAddress;
count: LONG CARDINAL;
IF argv.argc # 4 THEN RETURN;
source ← Convert.CardFromRope[argv[1], 16];
destination ← Convert.CardFromRope[argv[2], 16];
count ← Convert.CardFromRope[argv[3], 10];
BlitInternal[h: lark.h, source: source, destination: destination, count: count];
EXITS
BadArgs => RETURN[BadArgsRope];
BadComm => RETURN[BadCommRope];
};
BlitInternal: PROC [h: TeleLoad.Handle, source, destination: TeleLoad.CoreAddress, count: LONG CARDINAL] = {
cb: TeleLoad.CoreBlock;
highAddr: TeleLoad.CoreAddress;
TeleLoad.FlushWrites[h];
TeleLoad.ResetCache[h];
TeleLoad.SetCacheSize[h, 0];
cb ← NEW[TeleLoad.CoreBlockObject[TeleLoad.locMaxByte]];
highAddr ← source+count-1;
DO
IF source+TeleLoad.locMaxByte > highAddr THEN {
count ← highAddr-source;
cb ← NEW[TeleLoad.CoreBlockObject[count]];
}
ELSE count ← TeleLoad.locMaxByte;
Fetch old contents
cb.address ← source;
cb.advice ← [FALSE, FALSE, 0];
IF NOT TeleLoad.Fetch[h, cb].ok THEN {
h.log.PutF["\ncannot fetch %d bytes from address %04xH\n", IO.card[count], IO.card[source]];
EXIT;
};
Store old contents
cb.address ← destination;
cb.advice ← [FALSE, FALSE, 0];
IF NOT TeleLoad.Store[h, cb].ok THEN {
h.log.PutF["\ncannot restore %d bytes at address %04xH\n", IO.card[count], IO.card[destination]];
EXIT;
};
h.log.PutChar['.];
destination ← destination + TeleLoad.locMaxByte;
source ← source + TeleLoad.locMaxByte;
IF source > highAddr THEN EXIT;
ENDLOOP;
h.log.PutChar['\n];
};
LocalLoad: LarkWork.LarkWorkProc = {
IF NOT capital AND lark.program = NIL THEN RETURN["No program selected\n"];
IF capital AND lark.slaveProgram = NIL THEN RETURN["No program selected\n"];
IF NOT capital AND lark.breakList # NIL THEN {
lark.h.log.PutRope["Clearing breakpoints\n"];
lark.breakList ← NIL;
};
LarkControl.LoadProgram[lark: lark, go: FALSE, main: NOT capital];
};
MemoryTest: LarkWork.LarkWorkProc = {
ENABLE {
Convert.Error => GOTO BadArgs;
TeleLoad.Failed => GOTO BadComm;
};
out: IO.STREAM ← lark.h.log;
h: TeleLoad.Handle ← lark.h;
saved, cb: TeleLoad.CoreBlock;
lowAddr, highAddr, addr: TeleLoad.CoreAddress;
count: CARDINAL;
TestLump: PROC [testValue: CARDINAL] RETURNS [BOOL] = {
cb.address ← addr;
cb.advice ← [FALSE, FALSE, 0];
FOR i: CARDINAL IN [0..count) DO cb.data[i] ← testValue; ENDLOOP;
IF NOT TeleLoad.Store[h, cb].ok THEN {
cb.advice ← [FALSE, FALSE, 0];
IF NOT TeleLoad.Fetch[h, cb].ok THEN out.PutRope["contact lost\n"];
FOR i: CARDINAL IN [0..count) DO
IF cb.data[i] # testValue THEN {
out.PutF["loc %4x is %02x, should be %02x\r", IO.card[addr+i], IO.card[cb.data[i]], IO.card[testValue]];
EXIT;
};
ENDLOOP;
out.PutF["test of %d bytes of %02x at address %04xH failed\r", IO.card[count], IO.card[testValue], IO.card[addr]];
RETURN [FALSE];
};
RETURN[TRUE];
};
TeleLoad.ResetCache[h];
IF argv.argc # 3 THEN RETURN;
lowAddr ← Convert.CardFromRope[argv[1], 16];
highAddr ← Convert.CardFromRope[argv[2], 16];
saved ← NEW[TeleLoad.CoreBlockObject[TeleLoad.locMaxByte]];
cb ← NEW[TeleLoad.CoreBlockObject[TeleLoad.locMaxByte]];
addr ← lowAddr;
DO
IF addr+TeleLoad.locMaxByte > highAddr THEN {
count ← Basics.LowHalf[highAddr-addr];
cb ← NEW[TeleLoad.CoreBlockObject[count]];
saved ← NEW[TeleLoad.CoreBlockObject[count]];
}
ELSE count ← TeleLoad.locMaxByte;
Fetch old contents
saved.address ← addr;
saved.advice ← [FALSE, FALSE, 0];
IF NOT TeleLoad.Fetch[h, saved].ok THEN {
out.PutF["cannot fetch %d bytes from address %04xH\r", IO.card[count], IO.card[addr]];
EXIT;
};
IF NOT TestLump[0377B] THEN EXIT;
IF NOT TestLump[0B] THEN EXIT;
IF NOT TestLump[0252B] THEN EXIT;
IF NOT TestLump[0125B] THEN EXIT;
Store old contents
saved.advice ← [FALSE, FALSE, 0];
IF NOT TeleLoad.Store[h, saved].ok THEN {
out.PutF["cannot restore %d bytes at address %04xH\r", IO.card[count], IO.card[addr]];
EXIT;
};
addr ← addr + TeleLoad.locMaxByte;
IF addr > highAddr THEN EXIT;
ENDLOOP;
EXITS
BadArgs => RETURN[BadArgsRope];
BadComm => RETURN[BadCommRope];
};
ChangeRegister: LarkWork.LarkWorkProc = {
value: CARDINAL;
IfCmd: PROC [r: Rope.ROPE] RETURNS [BOOL] = {
RETURN [Rope.Equal[argv[1], r, FALSE]];
};
IF argv.argc # 3 THEN GOTO BadArgs;
value ← Basics.LowHalf[Convert.CardFromRope[argv[2], 16 ! Convert.Error => GOTO BadArgs]];
IF IfCmd["AX"] THEN lark.state.Regs[AX] ← value;
IF IfCmd["BX"] THEN lark.state.Regs[BX] ← value;
IF IfCmd["CX"] THEN lark.state.Regs[CX] ← value;
IF IfCmd["DX"] THEN lark.state.Regs[DX] ← value;
IF IfCmd["SP"] THEN lark.state.Regs[SP] ← value;
IF IfCmd["BP"] THEN lark.state.Regs[BP] ← value;
IF IfCmd["SI"] THEN lark.state.Regs[SI] ← value;
IF IfCmd["DI"] THEN lark.state.Regs[DI] ← value;
IF IfCmd["IP"] THEN lark.state.Regs[IP] ← value;
IF IfCmd["FL"] THEN lark.state.Regs[FL] ← value;
IF IfCmd["CS"] THEN lark.state.Regs[CS] ← value;
IF IfCmd["DS"] THEN lark.state.Regs[DS] ← value;
IF IfCmd["SS"] THEN lark.state.Regs[SS] ← value;
IF IfCmd["ES"] THEN lark.state.Regs[ES] ← value;
IF IfCmd["SR"] THEN StartRegisters[lark];
IF IfCmd["ZR"] THEN ZeroRegisters[lark];
IF IfCmd["RR"] THEN RemoteRegisters[lark];
IF IfCmd["ER"] THEN EventRegisters[lark];
IF IfCmd["?"] THEN RETURN["8088 register name or: SR => program start state, ZR => zero registers, ER => last event registers, RR => remote registers\n"];
LarkControl.DisplayState[lark.h.log, lark.state];
EXITS
BadArgs => RETURN[BadArgsRope];
};
ZeroRegisters: PROC [lark: LarkControl.LarkData] = {
FOR i: TeleLoad.Registers8086 IN [AX..FL] DO lark.state.Regs[i] ← 0; ENDLOOP;
lark.state.Regs[IP] ← 1024; -- 00400H
lark.state.Regs[SP] ← 54256; -- 0D3F0H
};
StartRegisters: PROC [lark: LarkControl.LarkData] = {
IF lark.program # NIL THEN lark.state ← lark.program.startState
ELSE lark.h.log.PutRope[" . . .No program specified\n"];
};
RemoteRegisters: PROC [lark: LarkControl.LarkData] = {
localState: TeleLoad.State8086Object;
ok: BOOL;
[ok, localState] ← LarkControl.FetchState[h: lark.h];
IF ok THEN lark.state ← localState;
};
EventRegisters: PROC [lark: LarkControl.LarkData] = {
lark.state ← lark.event.regs;
};
InteractiveDebug: LarkWork.LarkWorkProc = {
ENABLE TeleLoad.Failed => GOTO BadComm;
out: IO.STREAM ← lark.h.log;
in: IO.STREAM ← lark.eval.in.backingStream; -- not edited
h: TeleLoad.Handle ← lark.h;
address: INT;
value: CARDINAL;
variableRope: Rope.ROPE;
found: BOOL;
sym: LarkPrograms.STObject;
c: CHAR;
addressSpace: TeleLoad.AddressSpace ← main;
words: BOOLTRUE;
PrintVarAddress: PROC = {
sym ← LarkPrograms.ProcedureEnclosing[lark.program, address];
out.PutF["\n%04xH (%g", IO.card[address], IO.rope[sym.id]];
IF sym.addr # address THEN out.PutF[" + %04xH): ", IO.card[address - sym.addr]]
ELSE out.PutF["): "];
};
TeleLoad.ResetCache[h];
TeleLoad.SetCacheSize[h, 2];
IF argv.argc > 1 THEN variableRope ← argv[1]
ELSE variableRope ← lark.eval.in.GetTokenRope[].token;
[item: sym, found: found] ← LarkPrograms.FindVariable[lark.program, variableRope];
IF found THEN address ← sym.addr
ELSE address ← Convert.CardFromRope[variableRope, 16 ! Convert.Error => {
out.PutRope["???\n"];
GOTO Quit;
}];
PrintVarAddress[];
DO
value ← IF words THEN TeleLoad.ReadWord[h: h, addr: address, addressSpace: addressSpace] ELSE TeleLoad.Read[h: h, addr: address, addressSpace: addressSpace];
IF words THEN out.PutF["%04xH (%6d) ", IO.card[value], IO.card[value]]
ELSE out.PutF["%02xH (%3d) ", IO.card[value], IO.card[value]];
c ← in.GetChar[];
SELECT c FROM
Ascii.LF, 'n => {
address ← IF words THEN address + 2 ELSE address + 1;
PrintVarAddress[];
};
Ascii.BS, 'p => {
address ← IF words THEN address - 2 ELSE address - 1;
PrintVarAddress[];
};
Ascii.CR => EXIT;
'w, 'W => {
words ← TRUE;
TeleLoad.SetCacheSize[h, 2];
PrintVarAddress[];
};
'b, 'B => {
words ← FALSE;
TeleLoad.SetCacheSize[h, 1];
PrintVarAddress[];
};
's, 'S => {
addressSpace ← main;
PrintVarAddress[];
};
'm, 'M => {
addressSpace ← slave;
PrintVarAddress[];
};
't, 'T => {
address ← value;
PrintVarAddress[];
};
'? => {
out.PutF["LF, n => next word, BS, p => previous, CR => exit, m => main, s=> slave, w => words, b=> bytes, ← => new hex value, t => trace\n"];
PrintVarAddress[];
};
'← => {
out.PutF[" ← "];
value ← Basics.LowHalf[Convert.CardFromRope[lark.eval.in.GetTokenRope[].token, 16 ! Convert.Error => GOTO Quit]];
IF words THEN TeleLoad.WriteWord[h, address, value, addressSpace] ELSE TeleLoad.Write[h, address, value, addressSpace];
TeleLoad.FlushWrites[h];
address ← IF words THEN address + 2 ELSE address + 1;
PrintVarAddress[];
lark.eval.in.Reset[];
};
ENDCASE => {
out.PutF["LF, n => next word, BS, p => previous, CR => exit, m => main, s=> slave, w => words, b=> bytes, ← => new hex value\n"];
PrintVarAddress[];
lark.eval.in.Reset[];
};
ENDLOOP;
out.PutChar['\n];
TeleLoad.ResetCache[h];
TeleLoad.SetCacheSize[h, 0];
EXITS
Quit => NULL;
BadComm => RETURN[BadCommRope];
};
SetBreak: LarkWork.LarkWorkProc = {
ENABLE {
Convert.Error => GOTO BadArgs;
TeleLoad.Failed => GOTO BadComm;
};
out: IO.STREAM ← lark.h.log;
sym: LarkPrograms.STObject;
address, offset: TeleLoad.CoreAddress;
breakpoint: LarkControl.Breakpoint;
found: BOOL;
set: BOOLNOT capital;
IF argv.argc # 2 AND argv.argc # 3 THEN RETURN;
[item: sym, found: found] ← LarkPrograms.FindVariable[lark.program, argv[1]];
IF found THEN address ← sym.addr
ELSE {
address ← Convert.CardFromRope[argv[1], 16 ! Convert.Error => {
out.PutF["%g not found\n", IO.rope[argv[1]]];
GOTO Quit;
}];
};
IF argv.argc = 3 THEN offset ← Convert.CardFromRope[argv[2], 16 ! Convert.Error => {
out.PutF["%g bad offset\n", IO.rope[argv[2]]];
GOTO Quit;
}]
ELSE offset ← 0;
found ← FALSE;
FOR l: LIST OF LarkControl.Breakpoint ← lark.breakList, l.rest WHILE l # NIL DO
IF offset + address = l.first.address THEN {
found ← TRUE;
EXIT;
};
ENDLOOP;
IF set THEN {
IF found THEN out.PutRope["Breakpoint already exists.\n"]
ELSE {
breakpoint ← NEW[LarkControl.BreakpointObject];
breakpoint.address ← address + offset;
TeleLoad.SetCacheSize[lark.h, 1];
breakpoint.codeByte ← TeleLoad.Read[lark.h, breakpoint.address];
lark.breakList ← CONS[breakpoint, lark.breakList];
TeleLoad.Write[lark.h, breakpoint.address, 0CCH];
TeleLoad.FlushWrites[lark.h];
TeleLoad.SetCacheSize[lark.h, 0];
};
}
ELSE {
IF found THEN {
l: LIST OF LarkControl.Breakpoint ← lark.breakList;
lark.breakList ← NIL;
WHILE l # NIL DO
IF l.first.address # offset + address THEN lark.breakList ← CONS[l.first, lark.breakList]
ELSE breakpoint ← l.first;
l ← l.rest;
ENDLOOP;
TeleLoad.SetCacheSize[lark.h, 1];
TeleLoad.Write[lark.h, breakpoint.address, breakpoint.codeByte];
TeleLoad.FlushWrites[lark.h];
TeleLoad.SetCacheSize[lark.h, 0];
}
ELSE out.PutRope["Breakpoint doesn't exist.\n"];
};
EXITS
Quit => NULL;
BadArgs => RETURN[BadArgsRope];
BadComm => RETURN[BadCommRope];
};
WorkVerify: LarkWork.LarkWorkProc = {
program: LarkPrograms.Program;
IF lark = NIL THEN RETURN["NIL Lark!"];
program ← IF capital THEN lark.slaveProgram ELSE lark.program;
IF program = NIL THEN RETURN["No program!"];
IF capital THEN lark.h.log.PutRope["Verify Slave program\n"]
ELSE lark.h.log.PutRope["Verify Main program\n"];
RETURN[VerifyCommon[lark, argv, program]]
};
MonitorVerify: LarkWork.LarkWorkProc = {
program: LarkPrograms.Program ← LarkPrograms.Monitor[log: lark.h.log, addressSpace: IF capital THEN slave ELSE main];
IF lark = NIL THEN RETURN["NIL Lark!"];
IF program = NIL THEN RETURN["No monitor!"];
IF capital THEN lark.h.log.PutRope["Verify Slave Monitor\n"]
ELSE lark.h.log.PutRope["Verify Main Monitor\n"];
RETURN[VerifyCommon[lark, argv, program]]
};
VerifyCommon: PROC [lark: LarkControl.LarkData, argv: CommandTool.ArgumentVector, program: LarkPrograms.Program] RETURNS [Rope.ROPE] = {
ENABLE {
Convert.Error => GOTO BadArgs;
TeleLoad.Failed => GOTO BadComm;
};
startAddress, stopAddress: TeleLoad.CoreAddress;
log: IO.STREAM ← lark.h.log;
IF argv.argc = 3 THEN {
startAddress ← Convert.CardFromRope[argv[1], 16];
stopAddress ← Convert.CardFromRope[argv[2], 16];
}
ELSE {
startAddress ← 0;
stopAddress ← 0;
};
LarkControl.VerifyInternal[lark: lark, program: program, startAddress: startAddress, stopAddress: stopAddress];
RETURN[NIL];
EXITS
BadArgs => RETURN[BadArgsRope];
BadComm => RETURN[BadCommRope];
};
Zap: LarkWork.LarkWorkProc = {
[] ← LarkControl.SetState[h: lark.h, state: lark.state, tp: TeleLoad.GoToDebugger, print: FALSE];
};
ParseProgram: LarkWork.LarkWorkProc = {
program: LarkPrograms.Program ← LarkPrograms.ReadProgramFromDisk[objectFileName: argv[1], log: lark.h.log, addressSpace: IF capital THEN slave ELSE main];
IF argv.argc # 2 THEN RETURN;
IF program # NIL THEN LarkPrograms.AddOrReplaceProgram[program];
};
ShowEvent: LarkWork.LarkWorkProc = {
IF NOT capital THEN {
ok: BOOL;
event: TeleLoad.EventRecordObject;
[event: event, ok: ok] ← TeleLoad.GetEventData[lark.h, FALSE];
IF ok THEN lark.event ← event
ELSE lark.h.log.PutRope["GetEventData failed\n"];
};
LarkControl.DisplayEvent[lark: lark, event: lark.event, out: lark.h.log, reasonRope: LarkControl.BootReason[lark.event.reason, lark.event.regs.Regs[BX]], preRope: "Event "];
};
Register all the commands
LarkWork.RegisterLarkWorkProc[proc: SetCurrentProgram, key: "CurrentProgram", caseMatters: FALSE, doc: "Set program which Lark should use", usage: "[c/C]urrentProgram programName, c => main, C => slave"];
LarkWork.RegisterLarkWorkProc[proc: Go, key: "Go", caseMatters: FALSE, doc: "Start full speed execution"];
LarkWork.RegisterLarkWorkProc[proc: SingleStep, key: "Next", caseMatters: FALSE, doc: "Single step"];
LarkWork.RegisterLarkWorkProc[proc: GetState, key: "X", caseMatters: FALSE, doc: "Print Lark State", usage: "x: print local state, X print remote state and copy to local state"];
LarkWork.RegisterLarkWorkProc[proc: AlterVariable, key: "AlterVariable", caseMatters: FALSE, doc: "Change a variable in Lark", usage: "AlterVariable variableName {offset} value"];
LarkWork.RegisterLarkWorkProc[proc: AlterVariablesFromFile, key: "FilePatch", caseMatters: FALSE, doc: "Patch Lark from a File", usage: "FilePatch patchFileName"];
LarkWork.RegisterLarkWorkProc[proc: SetBlock, key: "SetBlock", caseMatters: FALSE, doc: "Set a block of memory to a value", usage: "SetBlock addr count value, count and value are in words"];
LarkWork.RegisterLarkWorkProc[proc: CheckSetBlock, key: "CheckSetBlock", caseMatters: FALSE, doc: "Check that a block of memory is set to a value", usage: "CheckSetBlock addr count value, count and value are in words"];
LarkWork.RegisterLarkWorkProc[proc: FillWithAddress, key: "FillWithAddress", caseMatters: FALSE, doc: "Fill a block of memory with its address", usage: "FillWithAddress addr count {b}, b => count is in bytes"];
LarkWork.RegisterLarkWorkProc[proc: CheckAddressFill, key: "CheckFillWithAddress", caseMatters: FALSE, doc: "Check that a block of memory is filled with its address", usage: "CheckFillWithAddress addr count {b}, b => count is in bytes"];
LarkWork.RegisterLarkWorkProc[proc: Blit, key: "Move", caseMatters: FALSE, doc: "BLT in Lark", usage: "Move from to count"];
LarkWork.RegisterLarkWorkProc[proc: LocalLoad, key: "Load", caseMatters: FALSE, doc: "Load current program", usage: "[l/L]oad, l => load main, L => load slave"];
LarkWork.RegisterLarkWorkProc[proc: MemoryTest, key: "TestMemory", caseMatters: FALSE, doc: "Test Lark Memory", usage: "TestMemory lowAddress highAddress"];
LarkWork.RegisterLarkWorkProc[proc: ChangeRegister, key: "Register", caseMatters: FALSE, doc: "Change a register value", usage: "Register registerName newValue"];
LarkWork.RegisterLarkWorkProc[proc: InteractiveDebug, key: "Fiddle", caseMatters: FALSE, doc: "Enter interactive debugger", usage: "Fiddle {Variable}"];
LarkWork.RegisterLarkWorkProc[proc: SetBreak, key: "Break", caseMatters: FALSE, doc: "Set and clear breakpoints", usage: "[b/B]reak {variableOrAddress} {offset}. break => set, Beak => clear, no argument => all breaks"];
LarkWork.RegisterLarkWorkProc[proc: WorkVerify, key: "Verify", caseMatters: FALSE, doc: "Check Lark Code space", usage: "[v/V]erify {lowAddress highAddress}, v => main program, V => slave program"];
LarkWork.RegisterLarkWorkProc[proc: MonitorVerify, key: "MonVerify", caseMatters: FALSE, doc: "Check Lark monitor", usage: "[m/M]onVerify {lowAddress highAddress}, m => main monitor, M => slave monitor"];
LarkWork.RegisterLarkWorkProc[proc: Zap, key: "Zap", caseMatters: FALSE, doc: "Force Lark into debugger"];
LarkWork.RegisterLarkWorkProc[proc: ParseProgram, key: "Parse", caseMatters: FALSE, doc: "Read a program from disk", usage: "[p/P]arse programName, p => main CPU, P => slave CPU"];
LarkWork.RegisterLarkWorkProc[proc: ShowEvent, key: "Event", caseMatters: FALSE, doc: "Display last event", usage: "[e/E]vent. e => fetch event and print, E => print local event"];
END.
April 27, 1983 2:14 pm, LCS, created from LarkWorkImpl
December 22, 1983 2:43 pm, LCS, Cedar 5