<> <> <> 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[]; }. <> <> <> <> <>