DIRECTORY Ascii, Convert, Inline, IO, Process, PupTypes, PupDefs, Rope, Runtime USING [GetBcdTime], TeleDebOps, TeleLoad, Time, Transaction, TypeScript USING [ChangeLooks], ViewerIO USING [CreateViewerStreams, GetViewerFromStream], ViewerOps USING [PaintViewer], UECP USING [Argv, Parse], UserExec; TeleDebImpl: PROGRAM IMPORTS Convert, Inline, IO, Process, PupDefs, Rope, Runtime, TeleDebOps, TeleLoad, Time, TypeScript, UECP, UserExec, ViewerIO, ViewerOps EXPORTS TeleDebOps = { OPEN TeleDebOps; hosts: PUBLIC LIST OF TeleDebOps.TeleDebugData; Junk: SIGNAL = CODE; BitOp: TYPE = PROC [a, b: UNSPECIFIED] RETURNS [UNSPECIFIED]; And: BitOp = INLINE { RETURN[Inline.BITAND[a,b]]; }; Shift: BitOp = INLINE { RETURN[Inline.BITSHIFT[a,b]]; }; IsASPorCR: IO.DeliverWhenProc = TRUSTED { RETURN [char=' OR char = '\n]; }; Main: PROC [hostName: Rope.ROPE] = { { ENABLE ABORTED => GO TO CleanUp; c: CHAR; tdd: TeleDebOps.TeleDebugData _ CreateWindow[]; eventsStream _ tdd.out; TeleLoad.StartEventServer[NoteEvents]; IF hostName # NIL THEN { tdd.out.PutF["Opening connection with %g\n", IO.rope[hostName]]; tdd _ SetupHost[tdd, hostName]; TeleDebOps.SetHostByRef[tdd]; }; WHILE tdd.h = NIL DO tdd _ OpenConnection[tdd]; ENDLOOP; DO ENABLE { IO.Error => { tdd.out.PutF[" !IO.Error!\n" ! ANY => CONTINUE]; CONTINUE; }; IO.Signal, Junk => TRUSTED { tdd.out.PutF[" !IO.Signal!\n" ! ANY => CONTINUE]; CONTINUE; }; Failed => CONTINUE; }; NoEcho[tdd]; tdd.out.PutF["%% "]; c _ tdd.in.GetChar[]; tdd.out.PutF[" "]; SELECT c FROM 'a => AlterVariable[tdd]; 'A => AlterVariablesFromFile[tdd]; 'b, 'B => Blit[tdd]; 'c, 'C => SetCurrentProgram[tdd]; 'd => Fetch[tdd, TRUE]; 'D => Fetch[tdd, FALSE]; 'g => Go[tdd, FALSE]; 'G => Go[tdd, TRUE]; 'h => GoFromBreak[tdd, FALSE]; 'H => GoFromBreak[tdd, TRUE]; 'l => Load[tdd, TRUE]; 'L => Load[tdd, FALSE]; 'm, 'M => MemoryTest[tdd]; 'n => SingleStep[tdd, FALSE]; 'N => SingleStep[tdd, TRUE]; 'o, 'O => tdd _ OpenConnection[tdd]; 'p => Parse[tdd]; 'P => Patch[tdd]; 'r, 'R => AlterRegister[tdd]; 's, 'S => Store[tdd]; 'v, 'V => Verify[tdd]; 'x => GetState[tdd, FALSE]; 'X => GetState[tdd, TRUE]; 'y, 'Y => YankVariable[tdd]; 'z, 'Z => GoToDebugger[tdd, TRUE]; '. => ResetCache[tdd]; '? => Help[tdd]; ' => InteractiveDebug[tdd]; ENDCASE => tdd.out.PutF[" type '? for Help\n"]; tdd.out.Flush[]; ENDLOOP; EXITS CleanUp => NULL; }; }; OpenConnection: PROC [old: TeleDebOps.TeleDebugData] RETURNS [new: TeleDebOps.TeleDebugData] = { newHostName: Rope.ROPE; Echo[old]; old.out.PutF["Open connection with: "]; newHostName _ old.edit.GetToken[]; TeleDebOps.MCR[old.out]; new _ SetupHost[old, newHostName]; TeleDebOps.SetHostByRef[new]; }; EnumerateHosts: PROC [ep: PROC [TeleDebOps.TeleDebugData] RETURNS [continue: BOOL]] = { FOR hl: LIST OF TeleDebOps.TeleDebugData _ hosts, hl.rest WHILE hl # NIL DO IF NOT ep[hl.first] THEN EXIT; ENDLOOP; }; FindByNameOrAddress: PUBLIC PROC [hostName: Rope.ROPE] RETURNS [htd: TeleDebOps.TeleDebugData] = { pa: PupTypes.PupAddress; ok: BOOL; NameEP: PROC [td: TeleDebOps.TeleDebugData] RETURNS [continue: BOOL] = { IF Rope.Equal[hostName, td.h.host, FALSE] OR pa = td.h.address THEN { htd _ td; RETURN [FALSE]; }; RETURN [TRUE]; }; [pa, ok] _ TeleLoad.NameToAddress[hostName]; IF ok THEN hostName _ TeleLoad.AddressToName[pa].nameRope; htd _ NIL; EnumerateHosts[NameEP]; }; FindByAddress: PROC [who: PupTypes.PupAddress] RETURNS [htd: TeleDebOps.TeleDebugData] = { AddressEP: PROC [td: TeleDebOps.TeleDebugData] RETURNS [continue: BOOL] = { IF who = td.h.address THEN { htd _ td; RETURN [FALSE]; }; RETURN [TRUE]; }; htd _ NIL; EnumerateHosts[AddressEP]; }; CreateWindow: PROC RETURNS [tdd: TeleDebOps.TeleDebugData] = { tdd _ NEW[TeleDebugDataObject]; [tdd.in, tdd.out] _ ViewerIO.CreateViewerStreams[name: "TeleDeb", editedStream: FALSE]; tdd.edit _ IO.CreateEditedStream[in: tdd.in, echoTo: tdd.out, deliverWhen: IsASPorCR]; tdd.origecho _ tdd.in.SetEcho[NIL]; TypeScript.ChangeLooks[ViewerIO.GetViewerFromStream[tdd.out], 'f]; tdd.out.PutF["TeleDeb of %t running at %t\n", IO.time[Runtime.GetBcdTime[]], IO.time[]]; }; SetupHost: PROC [old: TeleDebOps.TeleDebugData, hostName: Rope.ROPE] RETURNS [tdd: TeleDebOps.TeleDebugData] = { nameRope, addressRope: Rope.ROPE; pa: PupTypes.PupAddress; ok: BOOL; tdd _ FindByNameOrAddress[hostName]; IF tdd = NIL THEN { IF old.h # NIL THEN tdd _ NEW[TeleDebugDataObject] ELSE tdd _ old; [pa, ok] _ TeleLoad.NameToAddress[hostName]; IF ok THEN { [nameRope: nameRope, addressRope: addressRope] _ TeleLoad.AddressToName[pa]; tdd.in _ old.in; tdd.out _ old.out; tdd.edit _ old.edit; tdd.origecho _ old.origecho; tdd.h _ TeleLoad.Start[hostName]; IF tdd.h = NIL THEN { tdd.out.PutF[" . . . returns NIL.\n"]; tdd _ old; } ELSE { tdd.out.PutChar['\n]; hosts _ CONS[tdd, hosts]; }; } ELSE { old.out.PutF[" . . . returns NIL.\n"]; tdd _ old; }; }; IF tdd.h # NIL THEN { [nameRope: nameRope, addressRope: addressRope] _ TeleLoad.AddressToName[tdd.h.address]; ViewerIO.GetViewerFromStream[tdd.out].name _ Rope.Cat["TeleDeb ", nameRope, " [", addressRope, "]"]; ViewerOps.PaintViewer[ViewerIO.GetViewerFromStream[tdd.out], caption]; }; }; eventsStream: IO.STREAM; NoteEvents: PROC [who: PupTypes.PupAddress, cb: TeleLoad.EventRecordObject] = TRUSTED { hostRope: Rope.ROPE; addressRope: Rope.ROPE; longClock: LONG CARDINAL; [nameRope: hostRope, addressRope: addressRope] _ TeleLoad.AddressToName[who]; eventsStream.PutF["\nEvent from %g (%g): %04xH\n", IO.rope[hostRope], IO.rope[addressRope], IO.card[TeleDebOps.Swab[cb.reason]]]; longClock _ TeleDebOps.Swab[cb.clockHigh]; longClock _ longClock * 65536; longClock _ longClock + TeleDebOps.Swab[cb.clockLow]; eventsStream.PutF["clock %08x, switches: %04xH, advice: %04xH\n", IO.card[longClock], IO.card[TeleDebOps.Swab[cb.bootSwitches]], IO.card[TeleDebOps.Swab[cb.advice]]]; DisplayState[s: eventsStream, state: SwabState[cb.regs]]; eventsStream.PutF["%% "]; }; Echo: PROC [tdd: TeleDebOps.TeleDebugData] = { [] _ tdd.in.SetEcho[tdd.origecho]; }; NoEcho: PROC [tdd: TeleDebOps.TeleDebugData] = { [] _ tdd.in.SetEcho[NIL]; }; Help: PROC [tdd: TeleDebOps.TeleDebugData] = { tdd.out.PutRope["a(lter variable), "]; tdd.out.PutRope["A(lter variables from file) "]; tdd.out.PutRope["BLT, "]; tdd.out.PutRope["C(urrent Program) "]; tdd.out.PutRope["d(isplay words), D(isplay bytes), "]; tdd.out.PutRope["g(store state and go) "]; tdd.out.PutRope["G(fetch state then go) "]; tdd.out.PutRope["h(store state and go from break) "]; tdd.out.PutRope["H(fetch state then go from break) "]; tdd.out.PutRope["l(oad) "]; tdd.out.PutRope["L(oad without first Zap) "]; tdd.out.PutRope["M(emoryTest) "]; tdd.out.PutRope["n(store state and single step) "]; tdd.out.PutRope["N(fetch state then single step) "]; tdd.out.PutRope["O(pen Connection) "]; tdd.out.PutRope["p(arse Program) "]; tdd.out.PutRope["p(atch Program) "]; tdd.out.PutRope["Register (Change register) "]; tdd.out.PutRope["S(tore) "]; tdd.out.PutRope["Q(uit) "]; tdd.out.PutRope["V(erify) "]; tdd.out.PutRope["x(display state) "]; tdd.out.PutRope["X(fetch state and set debug pointers) "]; tdd.out.PutRope["y(ank {print variable}) "]; tdd.out.PutRope["Z(ap { go to debugger }) "]; tdd.out.PutRope[".(reset Display cache) "]; tdd.out.PutRope["SP(ace: enter Swat mode) "]; tdd.out.PutRope["\n"]; }; Blit: PROC [tdd: TeleDebOps.TeleDebugData] = { source, destination: TeleLoad.CoreAddress; count: LONG CARDINAL; tdd.out.PutF["BLT from (hex) "]; source _ GetHex[tdd.edit]; tdd.out.PutF[" to (hex) "]; destination _ GetHex[tdd.edit]; tdd.out.PutF[" count (hex) "]; count _ GetHex[tdd.edit]; BlitInternal[tdd: tdd, source: source, destination: destination, count: count]; }; BlitInternal: PROC [tdd: TeleDebOps.TeleDebugData, source, destination: TeleLoad.CoreAddress, count: LONG CARDINAL] = { cb: TeleLoad.CoreBlock; highAddr: TeleLoad.CoreAddress; cb _ NEW[TeleLoad.CoreBlockObject[locMaxByte]]; highAddr _ source+count-1; DO IF source+locMaxByte > highAddr THEN { count _ highAddr-source; cb _ NEW[TeleLoad.CoreBlockObject[count]]; } ELSE count _ locMaxByte; cb.address _ source; cb.advice _ [FALSE, FALSE, 0]; IF NOT TeleLoad.Fetch[tdd.h, cb].ok THEN { MCR[tdd.out]; tdd.out.PutF["cannot fetch %d bytes from address %04xH\r", IO.card[count], IO.card[source]]; EXIT; }; cb.address _ destination; cb.advice _ [FALSE, FALSE, 0]; IF NOT TeleLoad.Store[tdd.h, cb].ok THEN { MCR[tdd.out]; tdd.out.PutF["cannot restore %d bytes at address %04xH\r", IO.card[count], IO.card[destination]]; EXIT; }; tdd.out.PutChar['.]; destination _ destination + locMaxByte; source _ source + locMaxByte; IF source > highAddr THEN EXIT; ENDLOOP; MCR[tdd.out]; }; Fetch: PROC [tdd: TeleDebOps.TeleDebugData, words: BOOL] = { addr: TeleLoad.CoreAddress; count: CARDINAL _ 0; tdd.out.PutF["Dump "]; Echo[tdd]; tdd.out.PutF["(hex address) "]; addr _ GetHex[tdd.edit]; IF tdd.edit.GetChar[] #'\n THEN { tdd.out.PutF[" (decimal count): "]; count _ Inline.LowHalf[tdd.edit.GetInt[]]; tdd.out.PutF[" (= %xH)\n", IO.card[count]]; }; Show[tdd, addr, count, words]; }; Store: PROC [tdd: TeleDebOps.TeleDebugData] = { ENABLE TeleDebOps.Failed => GOTO Quit; addr: TeleLoad.CoreAddress; val: CARDINAL; tdd.out.PutF["Store data,"]; Echo[tdd]; tdd.out.PutF[" address (hex): "]; addr _ GetHex[tdd.edit]; tdd.out.PutF[" end with >FF"]; DO ENABLE { IO.Error => CONTINUE; }; tdd.out.PutF["\n%04xH: ", IO.card[addr]]; val _ Inline.LowHalf[GetHex[tdd.edit]]; IF val > 377B THEN EXIT; Write[tdd, addr, val]; addr _ addr + 1; ENDLOOP; FlushWrites[tdd]; MCR[tdd.out]; EXITS Quit => NULL; }; Show: PUBLIC PROC[host: TeleDebOps.TeleDebugData, addr: TeleLoad.CoreAddress, count: CARDINAL, words: BOOL _ FALSE] = { chars: STRING _ [16]; val, wval: CARDINAL; { ENABLE TeleDebOps.Failed => CONTINUE; TeleDebOps.FlushWrites[host: host]; TeleDebOps.ResetCache[host: host]; chars.length _ 16; IF count = 0 THEN count _ 64 ELSE count _ count + (addr MOD 16); addr _ addr - (addr MOD 16); -- round down to nearest multiple of 16 IF (count MOD 16) # 0 THEN count _ count + 16 - (count MOD 16); -- and round up FOR i: CARDINAL IN [0..count) DO IF (i MOD 16) = 0 THEN host.out.PutF[IF addr + i > LAST[CARDINAL] THEN " %08x" ELSE " %04xH", IO.card[addr + i]]; IF words THEN { IF (i MOD 2) = 0 THEN { val _ TeleDebOps.Read[host, addr+i]; chars[i MOD 16] _ IF val IN [40B..176B] THEN LOOPHOLE[val] ELSE '.; wval _ val; val _ TeleDebOps.Read[host, addr+i+1]; chars[(i + 1) MOD 16] _ IF val IN [40B..176B] THEN LOOPHOLE[val] ELSE '.; wval _ wval + Shift[val, 8]; host.out.PutF[" %04xH", IO.card[wval]]; }; } ELSE { val _ TeleDebOps.Read[host, addr+i]; host.out.PutF[" %02x", IO.card[val]]; chars[i MOD 16] _ IF val IN [40B..176B] THEN LOOPHOLE[val] ELSE '.; }; IF (i MOD 16) = 15 THEN { host.out.PutF[" "]; FOR j: NAT IN [0..16) DO host.out.PutChar[chars[j]]; ENDLOOP; host.out.PutChar['\n]; }; ENDLOOP; }; }; GetHex: PUBLIC PROC [h: IO.Handle] RETURNS [LONG CARDINAL] = { r: Rope.ROPE _ h.GetToken[]; v: Convert.Value _ Convert.Parse[text: [rope[r]], template: [unsigned[base: 16]]].value; RETURN[NARROW[v, Convert.Value[unsigned]! ANY => SIGNAL Junk].unsigned]; }; Parse: PROC [tdd: TeleDebOps.TeleDebugData] = { iName: Rope.ROPE; Echo[tdd]; tdd.out.PutF["Parse, Name of .obj file: "]; iName _ tdd.edit.GetToken[]; TeleDebOps.MCR[tdd.out]; tdd.program _ TeleDebOps.ReadProgramFromDisk[iName, tdd.out]; TeleDebOps.ResetPatchList[tdd.program]; TeleDebOps.MCR[tdd.out]; TeleDebOps.AddOrReplaceProgram[tdd.program]; }; Patch: PROC [tdd: TeleDebOps.TeleDebugData] = { progName: Rope.ROPE; prog: TeleDebOps.Program; pfName: Rope.ROPE; pl: LIST OF TeleDebOps.PatchItem; Echo[tdd]; tdd.out.PutF["Program Name: "]; progName _ tdd.edit.GetToken[]; TeleDebOps.MCR[tdd.out]; prog _ TeleDebOps.FetchProgram[progName]; IF prog = NIL THEN { tdd.out.PutF[" %g not found\n", IO.rope[progName]]; RETURN; }; tdd.out.PutF["Patch File Name: "]; pfName _ tdd.edit.GetToken[]; TeleDebOps.MCR[tdd.out]; pl _ TeleDebOps.PatchFromFile[host: tdd, fileName: pfName]; WHILE pl # NIL DO TeleDebOps.PatchProgramWord[program: prog, address: pl.first.address, wordValue: pl.first.wordValue]; pl _ pl.rest; ENDLOOP; }; SetCurrentProgram: PROC [tdd: TeleDebOps.TeleDebugData] = { iName: Rope.ROPE; Echo[tdd]; tdd.out.PutF["Set current .obj file: "]; iName _ tdd.edit.GetToken[]; TeleDebOps.MCR[tdd.out]; tdd.program _ TeleDebOps.FetchProgram[iName]; IF tdd.program = NIL THEN { tdd.program _ TeleDebOps.ReadProgramFromDisk[iName, tdd.out]; TeleDebOps.ResetPatchList[tdd.program]; IF tdd.program # NIL THEN TeleDebOps.AddOrReplaceProgram[tdd.program]; }; }; Load: PROC [tdd: TeleDebOps.TeleDebugData, zap: BOOL] = { TeleDebOps.MCR[tdd.out]; tdd.out.PutF["Load\n"]; IF zap THEN GoToDebugger[tdd, FALSE]; IF tdd.program = NIL THEN SetCurrentProgram[tdd]; tdd.larkState _ tdd.program.startState; TeleDebOps.LoadProgram[host: tdd, program: tdd.program, log: tdd.out]; TeleDebOps.MCR[tdd.out]; }; Verify: PROC [tdd: TeleDebOps.TeleDebugData] = { IF tdd.program = NIL THEN { tdd.out.PutF["Program not parsed.\n"]; RETURN; }; TeleDebOps.VerifyProgram[host: tdd, program: tdd.program, log: tdd.out]; }; MemoryTest: PROC [tdd: TeleDebOps.TeleDebugData] = { 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[tdd.h, cb].ok THEN { cb.advice _ [FALSE, FALSE, 0]; IF NOT TeleLoad.Fetch[tdd.h, cb].ok THEN tdd.out.PutF["contact lost\r"]; FOR i: CARDINAL IN [0..count) DO IF cb.data[i] # testValue THEN { tdd.out.PutF["loc %4x is %02x, should be %02x\r", IO.card[addr+i], IO.card[cb.data[i]], IO.card[testValue]]; EXIT; }; ENDLOOP; tdd.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]; }; tdd.out.PutF["Memory Test, "]; IF tdd.h = NIL THEN { tdd.out.PutF["Connection not open\n"]; RETURN; }; Echo[tdd]; tdd.out.PutF[" low address (hex): "]; lowAddr _ GetHex[tdd.edit]; tdd.out.PutF[" high address (hex): "]; highAddr _ GetHex[tdd.edit]; saved _ NEW[TeleLoad.CoreBlockObject[locMaxByte]]; cb _ NEW[TeleLoad.CoreBlockObject[locMaxByte]]; addr _ lowAddr; DO IF addr+locMaxByte > highAddr THEN { count _ Inline.LowHalf[highAddr-addr]; cb _ NEW[TeleLoad.CoreBlockObject[count]]; saved _ NEW[TeleLoad.CoreBlockObject[count]]; } ELSE count _ locMaxByte; saved.address _ addr; saved.advice _ [FALSE, FALSE, 0]; IF NOT TeleLoad.Fetch[tdd.h, saved].ok THEN { tdd.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; saved.advice _ [FALSE, FALSE, 0]; IF NOT TeleLoad.Store[tdd.h, saved].ok THEN { tdd.out.PutF["cannot restore %d bytes at address %04xH\r", IO.card[count], IO.card[addr]]; EXIT; }; addr _ addr + locMaxByte; IF addr > highAddr THEN EXIT; ENDLOOP; }; myFork: UserExec.CommandProc = TRUSTED { argv: UECP.Argv _ UECP.Parse[commands: event.commandLine]; hostName: Rope.ROPE _ IF argv.argc > 1 THEN argv[1] ELSE NIL; Process.Detach[FORK Main[hostName]]; }; RegNames: ARRAY TeleLoad.Registers8086 OF Rope.ROPE = [ "AX", "BX", "CX", "DX", "SP", "BP", "SI", "DI", "CS", "DS", "SS", "ES", "IP", "FL"]; GetState: PROC[tdd: TeleDebOps.TeleDebugData, forceGet: BOOLEAN _ FALSE] = { tdd.out.PutF["State "]; IF forceGet THEN FetchState[tdd, [TRUE, TRUE, 1234]]; tdd.out.PutChar['\n]; DisplayState[s: tdd.out, state: tdd.larkState]; }; DisplayState: PROC[s: IO.STREAM, state: TeleLoad.State8086Object] = { FOR i: TeleLoad.Registers8086 IN [AX..SI] DO PutReg[s, i, state.Regs[i]]; ENDLOOP; s.PutChar['\n]; FOR i: TeleLoad.Registers8086 IN [DI..FL] DO PutReg[s, i, state.Regs[i]]; ENDLOOP; s.PutChar['\n]; }; SwabState: PROC [state: TeleLoad.State8086Object] RETURNS [TeleLoad.State8086Object] = { FOR i: TeleLoad.Registers8086 IN [AX..FL] DO state.Regs[i] _ TeleDebOps.Swab[state.Regs[i]]; ENDLOOP; RETURN[state]; }; FetchState: PUBLIC PROC[host: TeleDebOps.TeleDebugData, adv: TeleLoad.Advice _ [FALSE, FALSE, 0]] = { cb: TeleLoad.CoreBlock; ok: BOOLEAN; tries: NAT; pp: TeleLoad.State8086; size: CARDINAL = SIZE[TeleLoad.State8086Object]*2; IF host.h = NIL THEN { host.out.PutF["Connection not open\n"]; RETURN; }; cb _ NEW[TeleLoad.CoreBlockObject[size]]; cb.address _ 1; cb.advice _ adv; [ok, tries] _ TeleLoad.FetchState[host.h, cb]; IF NOT ok THEN { host.out.PutF[" ... failed (%d attempts)\n", IO.int[tries]]; RETURN; }; pp _ LOOPHOLE[BASE[DESCRIPTOR[cb.data]], TeleLoad.State8086]; host.larkState _ SwabState[pp^]; pp _ NIL; }; Go: PROC [tdd: TeleDebOps.TeleDebugData, gs: BOOL _ FALSE] = { tdd.out.PutF["GO!\n"]; SetState[tdd, TeleLoad.Go, gs]; }; SingleStep: PROC [tdd: TeleDebOps.TeleDebugData, gs: BOOL _ FALSE] = { tdd.out.PutF["SingleStep!\n"]; SetState[tdd, TeleLoad.SingleStep, gs]; }; GoFromBreak: PROC [tdd: TeleDebOps.TeleDebugData, gs: BOOL _ FALSE] = { tdd.out.PutF["Break and Go!\n"]; SetState[tdd, TeleLoad.GoFromBreak, gs]; }; SetState: PROC [tdd: TeleDebOps.TeleDebugData, tp: TeleLoad.TeleLoadProc, getState: BOOL] = { cb: TeleLoad.CoreBlock; ok: BOOLEAN; pp: TeleLoad.State8086; size: CARDINAL = SIZE[TeleLoad.State8086Object]*2; IF tdd.h = NIL THEN { tdd.out.PutF["Connection not open\n"]; RETURN; }; IF getState THEN FetchState[tdd]; cb _ NEW[TeleLoad.CoreBlockObject[size]]; cb.address _ 1; cb.advice _ [FALSE, FALSE, 0]; pp _ LOOPHOLE[BASE[DESCRIPTOR[cb.data]], TeleLoad.State8086]; pp^ _ SwabState[tdd.larkState]; pp _ NIL; ok _ tp[tdd.h, cb].ok; IF NOT ok THEN tdd.out.PutF[" ... failed\n"]; }; GoToDebugger: PROC [tdd: TeleDebOps.TeleDebugData, print: BOOL] = { IF print THEN tdd.out.PutRope["Debug!\n"]; SetState[tdd, TeleLoad.GoToDebugger, FALSE]; }; PutReg: PROC [s: IO.STREAM, i: TeleLoad.Registers8086, v: CARDINAL] = { s.PutF[" %2s=%04xH", IO.rope[RegNames[i]], IO.card[v]]; }; AlterRegister: PROC [tdd: TeleDebOps.TeleDebugData] = { i: TeleLoad.Registers8086; r: Rope.ROPE; Echo[tdd]; tdd.out.PutF["Change register: "]; r _ tdd.edit.GetToken[]; SELECT TRUE FROM Rope.Equal[s1: r, s2: "0", case: FALSE] => { FOR i: TeleLoad.Registers8086 IN [AX..FL] DO tdd.larkState.Regs[i] _ 0; ENDLOOP; tdd.larkState.Regs[IP] _ 1024; -- 00400H tdd.larkState.Regs[SP] _ 54256; -- 0D3F0H RETURN; }; Rope.Equal[s1: r, s2: "r", case: FALSE] => { FetchState[tdd]; RETURN; }; Rope.Equal[s1: r, s2: "s", case: FALSE] => { IF tdd.program # NIL THEN tdd.larkState _ tdd.program.startState ELSE tdd.out.PutF[" . . .No program specified\n"]; RETURN; }; ENDCASE; FOR i IN TeleLoad.Registers8086 DO IF Rope.Equal[s1: r, s2: RegNames[i], case: FALSE] THEN EXIT; REPEAT FINISHED => { tdd.out.PutF[" ... unknown register\nRegisters are 0 (clear), r(emote), s(tartState of program), plus 8086 registers.\n"]; RETURN; }; ENDLOOP; tdd.out.PutF[" value for register %s (hex): ", IO.rope[RegNames[i]]]; tdd.larkState[i] _ Inline.LowHalf[GetHex[tdd.edit]]; tdd.out.PutF[" new value %s: %04xH\n", IO.rope[RegNames[i]], IO.card[tdd.larkState[i]]]; }; YankVariable: PROC [tdd: TeleDebOps.TeleDebugData] = { variableName: Rope.ROPE; Echo[tdd]; tdd.out.PutF["Print variable: "]; variableName _ tdd.edit.GetToken[]; TeleDebOps.PrintVariable[tdd, variableName]; TeleDebOps.MCR[tdd.out]; }; AlterVariable: PROC [tdd: TeleDebOps.TeleDebugData] = { variableName: Rope.ROPE; offset: NAT; value: CARDINAL; Echo[tdd]; tdd.out.PutF["Alter variable. Name: "]; variableName _ tdd.edit.GetToken[]; tdd.out.PutF[" Offset (decimal): "]; offset _ And[Inline.LowHalf[tdd.edit.GetInt[]], 077777B]; tdd.out.PutF[" new value (hex) "]; value _ Inline.LowHalf[GetHex[tdd.edit]]; TeleDebOps.MCR[tdd.out]; [] _ TeleDebOps.SetValue[host: tdd, name: variableName, value: value, offset: offset]; }; AlterVariablesFromFile: PROC [tdd: TeleDebOps.TeleDebugData] = { fileName: Rope.ROPE; pl: LIST OF TeleDebOps.PatchItem; Echo[tdd]; tdd.out.PutF["Alter variables from file. Filename: "]; fileName _ tdd.edit.GetToken[]; TeleDebOps.MCR[tdd.out]; pl _ TeleDebOps.PatchFromFile[host: tdd, fileName: fileName]; WHILE pl # NIL DO TeleDebOps.WriteWord[host: host, addr: pl.first.address, value: pl.first.wordValue]; tdd.out.PutChar['p]; pl _ pl.rest; ENDLOOP; TeleDebOps.FlushWrites[host]; TeleDebOps.MCR[tdd.out]; }; InteractiveDebug: PROC [tdd: TeleDebOps.TeleDebugData] = { ENABLE TeleDebOps.Failed => CONTINUE; address: INT; value: CARDINAL; variableRope: Rope.ROPE; found: BOOL; sym: TeleDebOps.STObject; c: CHAR; PrintVarAddress: PROC = { sym _ TeleDebOps.ProcedureEnclosing[tdd.program, address]; tdd.out.PutF["\n%04xH (%g", IO.card[address], IO.rope[sym.id]]; IF sym.addr # address THEN tdd.out.PutF[" + %04xH): ", IO.card[address - sym.addr]] ELSE tdd.out.PutF["): "]; }; Echo[tdd]; TeleDebOps.ResetCache[tdd]; variableRope _ tdd.edit.GetToken[]; [item: sym, found: found] _ TeleDebOps.FindVariable[tdd.program, variableRope]; IF found THEN address _ sym.addr ELSE address _ GetHex[IO.RIS[variableRope]]; PrintVarAddress[]; DO value _ TeleDebOps.ReadWord[host: tdd, addr: address]; tdd.out.PutF["%04xH (%6d) ", IO.card[value], IO.card[value]]; NoEcho[tdd]; c _ tdd.in.GetChar[]; Echo[tdd]; SELECT c FROM Ascii.LF, 'n => { address _ address + 2; PrintVarAddress[]; }; Ascii.BS, 'p => { address _ address - 2; PrintVarAddress[]; }; Ascii.CR => EXIT; '? => { tdd.out.PutF["LF, n => next word, BS, p => previous, CR => exit, Hex number => change\n"]; PrintVarAddress[]; }; '_ => { tdd.out.PutF[" _ "]; value _ Inline.LowHalf[GetHex[tdd.edit]]; TeleDebOps.WriteWord[tdd, address, value]; TeleDebOps.FlushWrites[tdd]; address _ address + 2; PrintVarAddress[]; WHILE tdd.in.CharsAvail[] DO [] _ tdd.in.GetChar[]; ENDLOOP; }; ENDCASE => { tdd.out.PutF["LF, n => next word, BS, p => previous, CR => exit, _ => new hex value\n"]; PrintVarAddress[]; WHILE tdd.in.CharsAvail[] DO [] _ tdd.in.GetChar[]; ENDLOOP; }; ENDLOOP; TeleDebOps.MCR[tdd.out]; TeleDebOps.ResetCache[tdd]; }; Init: PROC = { PupDefs.PupPackageMake[]; UserExec.RegisterCommand[name: "TeleDeb.~", proc: myFork, briefDoc: "Lark Downloading and debugging"]; }; Init[]; }. TeleDebImpl.mesa Last modified: Stewart, April 7, 1983 2:18 pm, cleanup duplicate copies check to see if there is one already Fetch old contents Store old contents always get the newest data code for Load starts here check to see if the program is correct Fetch old contents Store old contents Main program Swinehart, November 8, 1982 4:51 pm Stewart, November 19, 1982 3:53 pm Stewart, December 6, 1982 4:33 pm, Cedar 3.5 Stewart, December 22, 1982 3:31 pm, mods to TeleLoad Stewart, December 28, 1982 1:33 pm, smaller locMaxByte Ê7˜J˜Jšœ™Jšœ™Jšœ'™'J˜šÏk ˜ J˜J˜J˜Jšœ˜J˜J˜ J˜J˜Jšœœ˜J˜ J˜ J˜J˜ Jšœ œ˜Jšœ œ,˜:Jšœ œ˜Jšœœ˜J˜ J˜—Jšœ ˜JšœœKœ˜‰šœ ˜J˜—Jšœ ˜˜Jšœœœœ˜/J˜Jšœœœ˜Jšœ™Jš Ïnœœœ œœ œ˜=J˜Jšœ œœœ ˜4Jšœœœœ ˜8J˜Jš œ œœœ œ˜LJ˜šžœœœ˜$J˜Jšœœœœ ˜ Jšœœ˜J˜/J˜J˜&šœ œœ˜Jšœ-œ˜@J˜J˜J˜—šœ œ˜J˜Jšœ˜—šœœ˜ šœ ˜ Jšœœœ˜0Jšœ˜ J˜—šœœ˜Jšœ œœ˜1Jšœ˜ J˜—Jšœ œ˜—˜J˜ J˜J˜J˜šœ˜ J˜J˜"J˜J˜!Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜J˜Jšœœ˜Jšœœ˜J˜$J˜J˜J˜J˜J˜Jšœœ˜Jšœœ˜J˜Jšœœ˜"J˜J˜J˜Jšœ(˜/—J˜Jšœ˜—Jšœ œ˜J˜J˜J˜—šžœœ!œ$˜`Jšœœ˜J˜ J˜'J˜"Jšœ œ ˜J˜"J˜J˜J˜—š žœœœœ œ˜Wš œœœ+œœ˜KJšœœœœ˜Jšœ˜—J˜J˜—š žœœœœœ$˜bJ˜Jšœœ˜ šžœœ œ œ˜Hšœ!œœœ˜EJ˜ Jšœœ˜J˜—Jšœœ˜J˜—J˜,Jšœœ0˜:Jšœœ˜ J˜J˜J˜—šž œœœ$˜Zšž œœ œ œ˜Kšœœ˜J˜ Jšœœ˜J˜—Jšœœ˜J˜—Jšœœ˜ J˜J˜J˜—šž œœœ$˜>Jšœœ˜JšœPœ˜WJšœ œI˜VJšœœ˜#J˜BJšœ.œœ ˜XJ˜J˜—šž œœ0œœ$˜pJšœœ˜!J˜Jšœœ˜ Jšœ$™$J˜$šœœœ˜Jšœ œœœ˜2Jšœ ˜J˜,šœœ˜ J˜LJ˜J˜J˜J˜J˜!šœ œœ˜J˜'J˜ J˜—šœ˜J˜Jšœœ ˜J˜—J˜—šœ˜J˜'J˜ J˜—J˜—šœ œœ˜J˜WJ˜dJ˜FJ˜—J˜J˜—Jšœœœ˜J˜šž œœ>œ˜WJšœœ˜Jšœœ˜Jšœ œœ˜J˜MJšœ3œœœ#˜J˜*J˜J˜5JšœBœœ)œ#˜¦J˜9J˜J˜J˜—JšžœœJ˜TJ˜Jšžœœ9œ˜MJ˜šžœœ$˜.J˜&J˜0J˜J˜&J˜6J˜*J˜+J˜5J˜6J˜J˜-J˜!J˜3J˜4J˜&J˜$J˜$J˜/J˜J˜J˜J˜%J˜:J˜,J˜-J˜+J˜-J˜J˜J˜—šžœœ$˜.J˜*Jšœœœ˜J˜ J˜J˜J˜J˜J˜J˜OJ˜J˜—šž œœSœœ˜wJ˜J˜Jšœœ'˜/J˜š˜šœœ˜&J˜Jšœœ"˜*J˜—Jšœ˜Jšœ™J˜Jšœ œœ˜šœœœ˜*Jšœ ˜ Jšœ;œœ˜\Jšœ˜J˜—Jšœ™J˜Jšœ œœ˜šœœœ˜*Jšœ ˜ Jšœ;œœ˜aJšœ˜J˜—J˜J˜'J˜Jšœœœ˜Jšœ˜—Jšœ ˜ J˜J˜—šžœœ(œ˜Jšœœ˜J˜XJšœœœœ˜HJ˜J˜—šžœœ$˜/Jšœ œ˜——šœ™J˜ J˜+J˜Jšœ œ ˜J˜=J˜'Jšœ œ ˜J˜,J˜J˜šžœœ$˜/Jšœœ˜J˜Jšœ œ˜Jšœœœ˜!J˜ J˜J˜Jšœ œ ˜J˜)šœœœ˜Jšœ#œ˜6Jšœ˜J˜—J˜"J˜Jšœ œ ˜J˜;šœœ˜J˜eJ˜ Jšœ˜—J˜J˜—šžœœ$˜;Jšœ œ˜J˜ J˜(J˜Jšœ œ ˜J˜-šœœœ˜J˜=J˜'Jšœœœ-˜FJ˜—J˜J˜—šžœœ&œ˜9Jšœ œ ˜J˜Jšœœœ˜%Jšœœœ˜1J˜'J˜FJšœ œ ˜J˜J˜—Jšœ&™&J˜šžœœ$˜0šœœœ˜J˜&Jšœ˜J˜—J˜HJ˜J˜—šž œœ$˜4J˜J˜.Jšœœ˜š žœœ œœœ˜7J˜Jšœ œœ˜Jš œœœ œœ˜Ašœœœ˜*Jšœ œœ˜Jšœœœ ˜Hšœœœ ˜ šœœ˜ Jšœ2œœœ˜lJšœ˜J˜—Jšœ˜—JšœCœœœ ˜vJšœœ˜J˜—Jšœœ˜ J˜—J˜šœ œœ˜J˜&Jšœ˜J˜—J˜ J˜%J˜J˜&J˜Jšœœ'˜2Jšœœ'˜/J˜š˜šœœ˜$J˜&Jšœœ"˜*Jšœœ"˜-J˜—Jšœ˜Jšœ™J˜Jšœœœ˜!šœœ!œ˜-Jšœ;œœ ˜ZJšœ˜J˜—Jšœœœœ˜!Jšœœœœ˜Jšœœœœ˜!Jšœœœœ˜!Jšœ™Jšœœœ˜!šœœ!œ˜-Jšœ;œœ ˜ZJšœ˜J˜—J˜Jšœœœ˜Jšœ˜—J˜J˜—šœœ˜(Jšœœœ$˜:Jš œœœœ œœ˜=Jšœœ˜$J˜J˜—šœ œœœ˜7J˜TJ˜—šžœœ*œœ˜LJ˜Jšœ œœœ ˜5J˜J˜/J˜J˜—šž œœœœ'˜FJš œœœœœœ˜RJ˜Jš œœœœœœ˜RJ˜J˜J˜—šž œœ#œ˜Xš œœœœ˜,J˜/Jšœ˜—Jšœ˜J˜J˜—š ž œœœ9œœ ˜eJ˜Jšœœ˜ Jšœœ˜ J˜Jšœœœ˜2šœ œœ˜J˜'Jšœ˜J˜—Jšœœ!˜)J˜J˜J˜.šœœœ˜Jšœ-œ ˜J˜J˜J˜J˜—šž œœ%œœ˜FJ˜J˜'J˜J˜—šž œœ%œœ˜GJ˜ J˜(J˜J˜—šžœœFœ˜]J˜Jšœœ˜ J˜Jšœœœ˜2šœ œœ˜J˜&Jšœ˜J˜—Jšœ œ˜!Jšœœ!˜)J˜Jšœ œœ˜Jšœœœ œ ˜=J˜Jšœœ˜ J˜Jšœœœ˜-J˜J˜—šž œœ(œ˜CJšœœ˜*Jšœ%œ˜,J˜J˜—š žœœœœ œ˜GJšœœœ ˜7J˜J˜—šž œœ$˜7J˜Jšœœ˜ J˜ J˜"J˜šœœ˜šœ!œ˜,Jš œœœœœœ˜PJšœœ Ÿ ˜(Jšœœ Ÿ ˜)Jšœ˜J˜—šœ!œ˜,J˜Jšœ˜J˜—šœ!œ˜,Jšœœœ'˜@Jšœ.˜2Jšœ˜J˜—Jšœ˜—šœœ˜"Jšœ*œœœ˜=Jš˜šœ˜ J˜zJšœ˜J˜—Jšœ˜—Jšœ/œ˜EJ˜4Jšœ'œœ˜XJ˜J˜——šž œœ$˜6Jšœœ˜J˜ J˜!J˜#J˜,Jšœ œ ˜J˜J˜—šž œœ$˜7Jšœœ˜Jšœœ˜ Jšœœ˜J˜ J˜(J˜#J˜$J˜9J˜"J˜)Jšœ œ ˜J˜VJ˜J˜—šžœœ$˜@Jšœœ˜Jšœœœ˜!J˜ J˜7J˜Jšœ œ ˜J˜=šœœ˜J˜TJ˜J˜ Jšœ˜—J˜Jšœ œ ˜J˜J˜—šžœœ$˜:Jšœœ˜%Jšœ œ˜ Jšœœ˜Jšœœ˜Jšœœ˜ J˜Jšœœ˜šžœœ˜J˜:Jšœœœ˜?Jšœœœ˜SJšœ˜J˜—J˜ J˜J˜#J˜OJšœœ˜ Jšœœœ˜,J˜š˜J˜6Jšœœœ˜=J˜ J˜J˜ šœ˜ šœœ ˜J˜J˜J˜—šœœ ˜J˜J˜J˜—Jšœœœ˜˜J˜ZJ˜J˜—˜J˜J˜)J˜*J˜J˜J˜Jšœœœ˜