mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 00:44:23 +00:00
1076 lines
22 KiB
C
1076 lines
22 KiB
C
/*
|
||
**
|
||
**
|
||
**
|
||
**
|
||
**
|
||
**
|
||
**
|
||
**
|
||
** Zilog Portable Debugger
|
||
**
|
||
** October 1, 1982 Thorn Smith
|
||
**
|
||
**
|
||
**
|
||
**
|
||
** ***** PROPRIETARY ******
|
||
**
|
||
**
|
||
** This document is the property of Zilog corporation,
|
||
** and is protected from unauthorized duplication under
|
||
** applicable federal, state, and civil copyright laws.
|
||
** No part of this document may be reproduced, stored,
|
||
** or transmitted, in any form or by any means, such as
|
||
** electronic, mechanical, photocopying, recording, or
|
||
** otherwise, without the prior written permission of
|
||
** Zilog, inc. 1315 Dell Ave., Campbell, Calif. 95008
|
||
** tel: (408) 370-8000 twx: 910-338-7621
|
||
**
|
||
**
|
||
**
|
||
**
|
||
**
|
||
**
|
||
**
|
||
**
|
||
** Copyright 1982 Zilog Corporation, all rights reserved.
|
||
**
|
||
** date listed: ______ ____/____/____ ____:____ ____
|
||
**
|
||
** project name: 619ss - ZRTS software enhancement development
|
||
**
|
||
** program name: Zilog portable debugger
|
||
**
|
||
** specifications: Thorn Smith x 370-8317
|
||
**
|
||
** implementation: Thorn Smith x 370-8317
|
||
**
|
||
** documentation: Thorn Smith x 370-8317
|
||
**
|
||
** environment: Zilog S8000 v2.1
|
||
**
|
||
** language: Unix- C
|
||
**
|
||
** approvals-mgr: ________________________________________, Zilog
|
||
**
|
||
** approvals-q.a: ________________________________________, Zilog
|
||
**
|
||
** approvals-d.v: ________________________________________, Zilog
|
||
**
|
||
** program description:
|
||
**
|
||
** *************************************************
|
||
** * *
|
||
** * I N C L U D E F I L E S *
|
||
** * *
|
||
** *************************************************
|
||
**
|
||
*/
|
||
|
||
#ifndef CPM
|
||
#include <stdio.h>
|
||
#endif
|
||
|
||
#include "env.h"
|
||
#include "u.h"
|
||
|
||
/*
|
||
** *************************************************
|
||
** * *
|
||
** * P R E P R O C E S S C O N S T A N T S *
|
||
** * *
|
||
** *************************************************
|
||
**
|
||
*/
|
||
|
||
#define SYMMAX 300
|
||
#define ARGMAX 5
|
||
#define MAXBP 20
|
||
#define DSEG 0x9000000L
|
||
#define SSEG 0xA000000L
|
||
|
||
#define LADDR (MEMSIZE-0x10)
|
||
|
||
/*
|
||
** *************************************************
|
||
** * *
|
||
** * G L O B A L S / E X T E R N A L S *
|
||
** * *
|
||
** *************************************************
|
||
**
|
||
*/
|
||
|
||
/* globals to other modules */
|
||
extern int tractr;
|
||
extern POINTER temppc;
|
||
extern union pstate frame;
|
||
|
||
int tractr;
|
||
int sstctr;
|
||
POINTER temppc;
|
||
union pstate frame;
|
||
|
||
/* common symbols */
|
||
POINTER aptr,dptr,iptr,lptr,sptr;
|
||
POINTER arg[ARGMAX+1];
|
||
int dargs;
|
||
WORD fbits;
|
||
POINTER setmem();
|
||
|
||
struct symbol symtbl[SYMMAX];
|
||
|
||
int targc;
|
||
char **targv;
|
||
|
||
/*
|
||
******** debugger flags
|
||
*/
|
||
|
||
struct bitable dbgbits[] ={
|
||
'l', LSTEP,
|
||
'm', MUFOM,
|
||
't', TTRACE,
|
||
'\0', 0x0000,
|
||
};
|
||
|
||
/*
|
||
**
|
||
|
||
** *************************************************
|
||
** * *
|
||
** * S T A R T O F C O D E *
|
||
** * *
|
||
** *************************************************
|
||
**
|
||
*/
|
||
|
||
/*
|
||
******** main
|
||
*/
|
||
|
||
main (argc,argv)
|
||
int argc;
|
||
char **argv;
|
||
{
|
||
POINTER addr;
|
||
int diopn;
|
||
|
||
#ifdef CPM
|
||
extern long getsp();
|
||
extern int bkptrap();
|
||
struct bios_parm sclink;
|
||
|
||
if (cflag++) goto noreloc;
|
||
|
||
targc= argc;
|
||
targv= argv;
|
||
|
||
mem_cpy (map_adr(0L,1),DSEG,0xFFFFL); /* copy to segment 9 */
|
||
|
||
frame.lregs.fcw= 0x1800; /* ei VI,NVI */
|
||
frame.lregs.pcs= (WORD)(DSEG >> 16); /* new pc= current pc in seg9 */
|
||
frame.lregs.pc= (WORD)main;
|
||
frame.lregs.re= (WORD)(getsp() >> 16); /* new sp= current sp */
|
||
frame.lregs.rf= (WORD)(getsp() + 2);
|
||
xfer (map_adr((LONG) &frame & 0xFFFFL,257)); /* ZAP! relocate */
|
||
|
||
noreloc:
|
||
argc= targc;
|
||
argv= targv;
|
||
|
||
#endif
|
||
|
||
printf ("Zilog Portable debugger, @1982 Zilog, TRS\n");
|
||
symtbl[SYMMAX-1].utype= LASTSYM;
|
||
addsym ("$",1,(MDASIZE)0);
|
||
|
||
while (--argc && (*++argv)[0] == '-')
|
||
for (iscan= argv[0]+1; *iscan != '\0'; iscan++)
|
||
switch (*iscan) {
|
||
case 'j':
|
||
jflag++;
|
||
if (ishex(*(iscan+1)) < 0) break;
|
||
iscan++;
|
||
tlong= hexin(8);
|
||
frame.lregs.pc= (WORD)PSWP((WORD)(tlong));
|
||
#ifdef Z8001
|
||
frame.lregs.pcs= (WORD)(tlong >> 16);
|
||
#endif
|
||
iscan--;
|
||
break;
|
||
case 'm':
|
||
yflag^= MUFOM;
|
||
break;
|
||
case 'x':
|
||
if (ishex(*(iscan+1)) < 0) break;
|
||
iscan++;
|
||
xflag= (int)hexin(4);
|
||
iscan--;
|
||
break;
|
||
case 'y':
|
||
if (ishex(*(iscan+1)) < 0) break;
|
||
iscan++;
|
||
yflag= (int)hexin(4);
|
||
iscan--;
|
||
break;
|
||
default:
|
||
error=03;
|
||
}
|
||
err();
|
||
while (argc-- && ((*argv)[0] != '-')) { inload(&frame,*argv++); err(); }
|
||
|
||
dbginit (&frame);
|
||
err();
|
||
|
||
#ifdef CPM
|
||
sclink.req= 22;
|
||
sclink.p1= 32L;
|
||
sclink.p2= map_adr((LONG)bkptrap & 0xFFFFL,257);
|
||
_bios_call (&sclink); /* link sc 0 to bkpt to _bkpt */
|
||
|
||
frame.lregs.fcw= 0x1800; /* ei VI,NVI */
|
||
frame.lregs.pcs= (WORD)(SSEG >> 16); /* init user pc= 0A00 0000 */
|
||
/*
|
||
** frame.lregs.pc= (WORD)PSWP(0x0000);
|
||
*/
|
||
|
||
frame.lregs.re= (WORD)(SSEG >> 16); /* init user sp= 0A00 FDFC */
|
||
frame.lregs.rf= (WORD)PSWP(0xFDFC);
|
||
|
||
if (!jflag) setbkpt ((POINTER)0x0A000000,(WORD)1);
|
||
|
||
xfer (map_adr((LONG) &frame & 0xFFFF,257));
|
||
|
||
#else /* assumed ILS */
|
||
dbgloop:
|
||
if (!jflag) tractr= dbg(&frame);
|
||
while (!tractr) { /* run until trap */
|
||
addr= PSWP((WORD)frame.lregs.pc) & 0xFFFFL;
|
||
if (tstrap(addr)) break;
|
||
diopn= sstep(&frame);
|
||
sstctr++;
|
||
if (error) break;
|
||
if (!diopn) break;
|
||
if (yflag & TTRACE) diopn= sstate(&frame);
|
||
}
|
||
while (tractr--) sstep(&frame);
|
||
goto dbgloop;
|
||
#endif
|
||
}
|
||
|
||
/*
|
||
******** Breakpoint Entry
|
||
*/
|
||
|
||
dbg (state)
|
||
union pstate *state;
|
||
{
|
||
MDASIZE accu;
|
||
POINTER addr;
|
||
POINTER bkptadr;
|
||
WORD bkptctr;
|
||
char cmd,cmd1;
|
||
int diopn,mmode;
|
||
|
||
addr= PSWP((WORD)state->lregs.pc) & 0xFFFFL;
|
||
#ifdef Z8001
|
||
addr|= ((LONG)state->lregs.pcs << 16);
|
||
if (state->lregs.id == BKPT) {
|
||
addr-= 2;
|
||
state->lregs.pc= (WORD)addr;
|
||
clrbkpt(addr);
|
||
}
|
||
#else
|
||
if (tstrap(addr)) clrbkpt(addr);
|
||
#endif
|
||
error= 0;
|
||
|
||
if (yflag & LSTEP) {
|
||
state->lregs.pc= PSWP((WORD)temppc);
|
||
#ifdef Z8001
|
||
state->lregs.pcs= (WORD)(temppc >> 16);
|
||
#endif
|
||
yflag&= ~(LSTEP);
|
||
}
|
||
|
||
diopn= sstate (state);
|
||
|
||
cmdline:
|
||
error=0;
|
||
printf("> ");
|
||
iscan= gets(iline);
|
||
if (iscan == NULL) exit(0);
|
||
/*
|
||
** uctolc (iscan);
|
||
*/
|
||
tscan= iscan;
|
||
cmdloop:
|
||
cmd= tolower(*iscan++);
|
||
cmd1= tolower(*iscan);
|
||
|
||
mmode= 8; /* default memory mode (8-bits wide) */
|
||
if (cmd == 'd' || cmd == 'f' || cmd == 's') {
|
||
if (cmd1 == 's') { mmode= 8; iscan++; }
|
||
if (cmd1 == 'w') { mmode= 16; iscan++; }
|
||
/*
|
||
** if (cmd1 == 'l') { mmode= 32; iscan++; }
|
||
** if (cmd1 == 'q') { mmode= 64; iscan++; }
|
||
*/
|
||
}
|
||
if (cmd == 'p' && cmd1 == 'w') { mmode= 16; iscan++; }
|
||
|
||
itrim(); /* set *iscan to first arg field */
|
||
switch(cmd) {
|
||
case '\0': /* null line (currently does nothing) */
|
||
case '\n':
|
||
break;
|
||
case '?': /* help facility */
|
||
printf ("?\t\t\t\tHelp\n");
|
||
printf ("*\t\t\t\tRemark\n");
|
||
printf ("$ [symbol=] expr\t\tSymbolic Assignment\n");
|
||
printf ("@ address, instr\t\tSingle patch\n");
|
||
printf ("^ instr\t\t\t\tExecute in local mode\n");
|
||
printf ("a from\t\t\t\tAssemble source code\n");
|
||
printf ("b [addr][,addr]...\t\tSet/Display Breakpoint(s)\n");
|
||
printf ("c [addr][,addr]...\t\tClear (All) Breakpoint(s)\n");
|
||
printf ("dx [from [,to] || [,,count]]\tDump memory\n");
|
||
printf ("fx from,to,word\t\t\tFill memory\n");
|
||
printf ("i filename\t\t\tInload (overlay) a file\n");
|
||
printf ("j [expr]\t\t\tJump to user code (execute)\n");
|
||
printf ("l [from [,to] || [,,count]]\tList (disam) \n");
|
||
printf ("m from,to,bytes\t\t\tMove Memory\n");
|
||
printf ("n [count]\t\t\tSingle Step (next)\n");
|
||
printf ("p port [,data]\t\t\tPort read [write] data\n");
|
||
printf ("r [x=expr] [x=expr]...\t\tSet/Disp regs(s)\n");
|
||
printf ("sx [addr]\t\t\tSet memory\n");
|
||
printf ("x [flags]\t\t\tflip FCW status bits\n");
|
||
break;
|
||
|
||
case '*': /* remark */
|
||
break;
|
||
|
||
/*
|
||
** case ':':
|
||
** iscan--;
|
||
** inline();
|
||
** break;
|
||
*/
|
||
|
||
case '$': /* symbol = expr Set/display a symbol */
|
||
if (eolchr(*iscan)) { dspsyms(); break; }
|
||
if (*iscan == '=') { error=22; break; }
|
||
if (symchr(*iscan) && !(*iscan >= '0' && *iscan <= '9'))
|
||
skipsym();
|
||
if (error) break;
|
||
if (*iscan == '=') {
|
||
iscan++;
|
||
accu= infixer();
|
||
if (error) break;
|
||
iscan= &iline[1];
|
||
itrim();
|
||
setsym (1,accu);
|
||
break;
|
||
}
|
||
iscan= &iline[1];
|
||
itrim();
|
||
accu= infixer();
|
||
if (error) break;
|
||
symtbl[1].uvalue= accu;
|
||
printf ("%ld\t",accu);
|
||
printf ("0%lx\t",accu);
|
||
printf (":%lo\n",accu);
|
||
break;
|
||
|
||
case '@': /* @addr instr assemble instr into address (in user space) */
|
||
tptr= infixer();
|
||
if (error) break;
|
||
if (eolchr(*iscan)) error= 79;
|
||
if (error) break;
|
||
diopn= asdis(tptr,iscan);
|
||
break;
|
||
|
||
case ' ':
|
||
case '^': /* ^ instr assemble instr into local space and Sstep */
|
||
diopn= asdis((POINTER)LADDR,iscan);
|
||
if (error) break;
|
||
temppc= PSWP(state->lregs.pc) & 0xFFFFL;
|
||
state->lregs.pc= PSWP((WORD)LADDR);
|
||
#ifdef Z8001
|
||
temppc|= ((LONG)state->lregs.pcs << 16);
|
||
state->lregs.pcs= (WORD)(LADDR >> 16);
|
||
#endif
|
||
yflag|= LSTEP;
|
||
return (1);
|
||
|
||
case 'a': /* A [from] assemble multiple instructions into "from"++ */
|
||
getargs();
|
||
if (error) break;
|
||
if (dargs) aptr= arg[1];
|
||
while (1) {
|
||
error=0;
|
||
adrout(aptr);
|
||
iscan= gets(iline);
|
||
if (eolchr(*iscan)) break;
|
||
diopn= asdis(aptr,iscan);
|
||
if (error) { err(); continue; }
|
||
aptr += getnext(diopn);
|
||
}
|
||
break;
|
||
|
||
case 'b': /* B [addr][,addr] ... breakpoint set/display */
|
||
while (!eolchr(*iscan)) {
|
||
bkptctr= 1;
|
||
bkptadr= infixer();
|
||
if (*iscan == ':') {
|
||
iscan++;
|
||
error=0;
|
||
bkptctr= (WORD)infixer();
|
||
}
|
||
if (error) break;
|
||
if (!delchr(*iscan)) error=70;
|
||
if (error) break;
|
||
setbkpt ((POINTER)bkptadr,(WORD)bkptctr);
|
||
if (error) break;
|
||
if (*iscan != ',') break;
|
||
iscan++;
|
||
}
|
||
dispbkpt();
|
||
break;
|
||
|
||
case 'c': /* C [addr][,addr] ... breakpoint clear/clear all */
|
||
if (eolchr(*iscan)) nobkpts();
|
||
while (!eolchr(*iscan)) {
|
||
bkptadr= infixer();
|
||
if (error) break;
|
||
if (!delchr(*iscan)) error=70;
|
||
if (error) break;
|
||
clrbkpt ((POINTER)bkptadr);
|
||
if (error) break;
|
||
if (*iscan != ',') break;
|
||
iscan++;
|
||
}
|
||
dispbkpt();
|
||
break;
|
||
|
||
case 'd': /* D [from][to][count] dump memory in hexadecimal and ascii */
|
||
getargs();
|
||
if (error) break;
|
||
if (dargs == 0) arg[1]= dptr;
|
||
if (arg[3] == 0) arg[3]= 0x100;
|
||
if (arg[2] == 0) arg[2]= arg[1]+arg[3];
|
||
if (arg[4] == 0) arg[4]= 16;
|
||
if (arg[1] > arg[2]) { error=65; break; }
|
||
dmpmem (arg[1],arg[2],mmode,(WORD)arg[4]);
|
||
dptr= arg[2];
|
||
break;
|
||
|
||
case 'f': /* F from,to,byte fill memory with constant data */
|
||
getargs();
|
||
if (error) break;
|
||
if (dargs != 3) {
|
||
error=63;
|
||
break;
|
||
}
|
||
if (arg[1] >= arg[2]) {
|
||
error=66;
|
||
break;
|
||
}
|
||
while (arg[1] < arg[2]) {
|
||
if (mmode == 8) {
|
||
stchr(arg[1],(BYTE)arg[3]);
|
||
arg[1]+= 1;
|
||
}
|
||
if (mmode == 16) {
|
||
stint(arg[1],(WORD)arg[3]);
|
||
arg[1]+= 2;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'g': /* G addr [bkpts] begin execution (load PC & jump) */
|
||
case 'j': /* J addr [bkpts] begin execution (load PC & jump) */
|
||
getargs();
|
||
if (error) break;
|
||
if (!arg[1]) return (0);
|
||
state->lregs.pc= (WORD)(arg[1]);
|
||
#ifdef z8001
|
||
state->lregs.pcs= (WORD)(arg[1] >> 16);
|
||
#endif
|
||
return (0);
|
||
|
||
case 'i': /* I filename build a file control block for IO */
|
||
inload (state,iscan);
|
||
break;
|
||
|
||
case 'l': /* L [from][to][count] list memory using disassembler */
|
||
getargs();
|
||
if (error) break;
|
||
if (dargs == 0) arg[1]= lptr;
|
||
if (arg[3] == 0) arg[3]= 0x10;
|
||
if (arg[2] == 0) arg[2]= arg[1]+arg[3];
|
||
if (arg[1] > arg[2]) {
|
||
error=65;
|
||
break;
|
||
}
|
||
for (lptr= arg[1]; lptr <= arg[2];) {
|
||
memode= CODE;
|
||
diopn= deasm(lptr,oline);
|
||
memode= DATA;
|
||
printf ("%s\n",oline);
|
||
lptr += getnext(diopn);
|
||
}
|
||
break;
|
||
|
||
case 'm': /* Mx From,to,count Move memory */
|
||
getargs();
|
||
if (error) break;
|
||
if (dargs != 3) {
|
||
error=63;
|
||
break;
|
||
}
|
||
if (arg[1] == arg[2]) {
|
||
error=67;
|
||
break;
|
||
}
|
||
movmem(arg[1],arg[2],arg[3]);
|
||
break;
|
||
case 'n': /* N count single step n times */
|
||
getargs();
|
||
if (error) break;
|
||
if (!dargs) arg[1]= 1;
|
||
return (arg[1]);
|
||
|
||
case 'p': /* P port,address read/write io port */
|
||
getargs();
|
||
if (error) break;
|
||
if (dargs == 1) {
|
||
adrout (sptr);
|
||
printf ("%02x\n",CHR(pichr(arg[1])));
|
||
}
|
||
if (dargs == 2) {
|
||
pochr(arg[1],(BYTE)arg[2]);
|
||
}
|
||
break;
|
||
|
||
case 'r': /* R [reg=value] register set/display */
|
||
if (!eolchr(*iscan)) setregs(state);
|
||
if (error) break;
|
||
diopn= sstate(state);
|
||
break;
|
||
|
||
case 's': /* S [addr] set memory */
|
||
if (eolchr(*iscan)) goto nextsl;
|
||
if (delchr(*iscan)) goto nextsf;
|
||
arg[1]= infixer();
|
||
if (error) break;
|
||
sptr= arg[1];
|
||
if (eolchr(*iscan)) goto nextsl;
|
||
if (delchr(*iscan)) goto nextsf;
|
||
nextsl: /* process next line */
|
||
adrout (sptr);
|
||
if (mmode == 8) { printf ("%02x ",CHR(ldchr(sptr))); }
|
||
if (mmode == 16) { printf ("%04x ",SHT(ldint(sptr))); }
|
||
iscan= gets(iline);
|
||
if (eolchr(*iscan)) break;
|
||
if (spcchr(*iscan) || *iscan == '.') {
|
||
if (mmode == 8) sptr+= 1;
|
||
if (mmode == 16) sptr+= 2;
|
||
goto nextsl;
|
||
}
|
||
sptr= setmem(sptr,mmode); /* set memory from the line */
|
||
if (error) break;
|
||
goto nextsl;
|
||
|
||
nextsf: /* process next field */
|
||
if (eolchr(*iscan)) break;
|
||
if (delchr(*iscan)) iscan++;
|
||
sptr= setmem(sptr,mmode);
|
||
if (error) break;
|
||
goto nextsf;
|
||
|
||
case 'x': /* X [bit] set fcw bits nmemonicaly */
|
||
fbits= (state->sregs.f1 << 8) & 0xFF00;
|
||
fbits|= (state->sregs.f & 0xFF);
|
||
fbits= sflags(fbits,pflags);
|
||
state->sregs.f1= (fbits >> 8) & 0xFF;
|
||
state->sregs.f= (fbits) & 0xFF;
|
||
printf("%04x: ",SHT(fbits));
|
||
dflags(fbits,pflags);
|
||
printf ("\n");
|
||
break;
|
||
|
||
case 'y': /* Y [bit] set dbgbits nmemonically */
|
||
yflag= sflags((WORD)yflag,dbgbits);
|
||
printf("%04x: ",SHT(yflag));
|
||
dflags((WORD)yflag,dbgbits);
|
||
printf ("\n");
|
||
break;
|
||
|
||
case 'z':
|
||
printf ("ssteps= %d\n",sstctr);
|
||
sstctr= 0;
|
||
break;
|
||
|
||
default:
|
||
error=50;
|
||
}
|
||
err();
|
||
while (!eolchr(*tscan)) tscan++;
|
||
if (*tscan == ';') { tscan++; iscan= tscan; goto cmdloop; }
|
||
|
||
goto cmdline;
|
||
}
|
||
|
||
/*
|
||
******** get arguments utility
|
||
*/
|
||
|
||
getargs()
|
||
{
|
||
for (dargs=0; dargs < ARGMAX; dargs++) arg[dargs]= 0;
|
||
dargs=0;
|
||
if (eolchr(*iscan)) return;
|
||
for (dargs=1; (dargs < ARGMAX); dargs++) {
|
||
arg[dargs]= infixer();
|
||
if (error) break;
|
||
if (eolchr(*iscan)) break;
|
||
if (delchr(*iscan)) { iscan++; continue; }
|
||
error=50+dargs;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
******** dump memory utility
|
||
*/
|
||
|
||
dmpmem (from,to,mmode,width)
|
||
POINTER from,to;
|
||
int mmode;
|
||
WORD width;
|
||
{
|
||
char c;
|
||
|
||
tptr= from; /* tptr= base address for current line */
|
||
while (from < to) {
|
||
if (tptr == from) adrout (from);
|
||
if (mmode == 8) {
|
||
printf ("%02x ",CHR(ldchr(from))); from+= 1;
|
||
}
|
||
if (mmode == 16) {
|
||
printf ("%04x ",SHT(ldint(from))); from+= 2;
|
||
}
|
||
if ((from-tptr < width) && (from < to)) continue;
|
||
printf (" ");
|
||
while (tptr < from) {
|
||
c= ldchr(tptr++);
|
||
if (c < ' ') c='.';
|
||
printf ("%c",c);
|
||
}
|
||
printf ("\n");
|
||
}
|
||
}
|
||
|
||
POINTER setmem (from,mmode)
|
||
POINTER from;
|
||
{
|
||
MDASIZE accu;
|
||
while (!eolchr(*iscan)) {
|
||
while (spcchr(*iscan) || *iscan == ',') iscan++;
|
||
if (*iscan == '"') {
|
||
iscan++;
|
||
while (!eolchr(*iscan)) {
|
||
if (*iscan == '\"') break;
|
||
stchr(from++,(BYTE)*iscan++);
|
||
}
|
||
if (*iscan == '"') iscan++;
|
||
continue;
|
||
}
|
||
accu= infixer();
|
||
if (error) break;
|
||
if (mmode == 8) { stchr (from,(BYTE)accu); from+= 1; }
|
||
if (mmode == 16) { stint (from,(WORD)accu); from+= 2; }
|
||
}
|
||
return (from);
|
||
}
|
||
|
||
/*
|
||
******** move memory utility
|
||
*/
|
||
|
||
movmem (from,to,count)
|
||
POINTER from,to,count;
|
||
{
|
||
if (from > to) {
|
||
while (count--) stchr(to++,ldchr(from++));
|
||
return;
|
||
}
|
||
if (from < to) {
|
||
from+= count;
|
||
to+= count;
|
||
while (count--) stchr(--to,ldchr(--from));
|
||
}
|
||
}
|
||
|
||
/*
|
||
********* breakpoint display / set / clear and find routines
|
||
*/
|
||
|
||
struct {
|
||
POINTER bkptadr;
|
||
WORD bkptdat;
|
||
WORD bkptctr;
|
||
} bkpts[MAXBP];
|
||
|
||
dispbkpt()
|
||
{
|
||
int bkptc;
|
||
for (bkptc=1; (bkptc < MAXBP); bkptc++)
|
||
if (bkpts[bkptc].bkptctr) {
|
||
adrout (bkpts[bkptc].bkptadr);
|
||
printf ("%6d\t",bkpts[bkptc].bkptctr);
|
||
printf ("%05x\n",bkpts[bkptc].bkptdat);
|
||
}
|
||
}
|
||
|
||
setbkpt(bkpt,bcount)
|
||
POINTER bkpt;
|
||
WORD bcount;
|
||
{
|
||
int bkptc;
|
||
bkptc= findbkpt(bkpt);
|
||
if (bkptc) error=71; /* already set */
|
||
if (error) return;
|
||
if (!bcount) error=78; /* zero bkpt count */
|
||
if (error) return;
|
||
for (bkptc=1; bkptc < MAXBP; bkptc++) {
|
||
if (bkpts[bkptc].bkptctr) continue;
|
||
bkpts[bkptc].bkptadr= bkpt;
|
||
bkpts[bkptc].bkptdat= (WORD)setrap(bkpt,(WORD)BKPT);
|
||
bkpts[bkptc].bkptctr= (WORD)bcount;
|
||
return;
|
||
}
|
||
error=72; /* no more space */
|
||
}
|
||
|
||
nobkpts()
|
||
{
|
||
int bkptc;
|
||
for (bkptc=1; bkptc < MAXBP; bkptc++)
|
||
if (bkpts[bkptc].bkptctr)
|
||
clrbkpt(bkpts[bkptc].bkptadr);
|
||
}
|
||
|
||
clrbkpt(bkpt)
|
||
POINTER bkpt;
|
||
{
|
||
int bkptc;
|
||
bkptc= findbkpt(bkpt);
|
||
if (!bkptc) error=73; /* no bkpt to clear */
|
||
if (error) return;
|
||
if ((WORD)setrap(bkpt,bkpts[bkptc].bkptdat) != BKPT) error=74;
|
||
if (error) return;
|
||
bkpts[bkptc].bkptctr= (POINTER)0;
|
||
}
|
||
|
||
findbkpt(bkpt)
|
||
POINTER bkpt;
|
||
{
|
||
int bkptc;
|
||
for (bkptc=1; bkptc < MAXBP; bkptc++) {
|
||
if (bkpts[bkptc].bkptctr == 0) continue; /* invalid */
|
||
if (bkpts[bkptc].bkptadr == bkpt)
|
||
return (bkptc);
|
||
}
|
||
return (0);
|
||
}
|
||
|
||
/*
|
||
******** set processor state register
|
||
*/
|
||
|
||
setregs(state)
|
||
union pstate *state;
|
||
{
|
||
POINTER addr;
|
||
char *tp,*rp;
|
||
long rvalue;
|
||
int i;
|
||
while (!eolchr(*iscan)) {
|
||
for (i=1; ; i++) {
|
||
rp= regtbl[i].uname;
|
||
tp= iscan;
|
||
if (*rp == '\0') { error=75; return; }
|
||
while (tolower(*rp) == tolower(*tp)) {
|
||
rp++; tp++;
|
||
}
|
||
if ((*rp=='\0' || *rp==' ') && *tp=='=') break;
|
||
}
|
||
iscan= ++tp;
|
||
rvalue= infixer();
|
||
if (error) return;
|
||
addr= ((POINTER)state & 0xFFFFL) + (POINTER)regtbl[i].uvalue;
|
||
if (regtbl[i].utype & (MDASIZE)RCHR)
|
||
*(BYTE *)addr= (BYTE)rvalue;
|
||
if (regtbl[i].utype & (MDASIZE)RINT)
|
||
*(WORD *)addr= (WORD)PSWP((WORD)rvalue);
|
||
if (regtbl[i].utype & (MDASIZE)RLONG)
|
||
*(LONG *)addr= (LONG)(rvalue);
|
||
if (eolchr(*iscan)) return;
|
||
if (delchr(*iscan)) { iscan++; continue; }
|
||
error=76;
|
||
return;
|
||
}
|
||
}
|
||
|
||
/*
|
||
******** display processor state
|
||
*/
|
||
|
||
sstate(state)
|
||
union pstate *state;
|
||
{
|
||
POINTER addr;
|
||
int i,diopn;
|
||
|
||
for (i=1; *regtbl[i].uname; i++) {
|
||
if (regtbl[i].utype & (MDASIZE)RCHR) continue;
|
||
addr= ((POINTER)state & 0xFFFFL) + (POINTER)regtbl[i].uvalue;
|
||
printf ("%s=",regtbl[i].uname);
|
||
if (regtbl[i].utype & (MDASIZE)RLONG)
|
||
printf ("%08lx",*(POINTER *)addr);
|
||
if (regtbl[i].utype & (MDASIZE)RINT)
|
||
printf ("%04x",PSWP(*(WORD *)addr));
|
||
if (regtbl[i].utype & (MDASIZE)RCR) printf ("\n");
|
||
else printf (" ");
|
||
}
|
||
fbits= ((state->sregs.f1 << 8) & 0xFF00) | (state->sregs.f & 0x00FF);
|
||
dflags(fbits,pflags);
|
||
addr= PSWP(state->lregs.pc) & 0xFFFFL;
|
||
#ifdef Z8001
|
||
addr|= ((LONG)state->lregs.pcs << 16);
|
||
#endif
|
||
memode= CODE;
|
||
diopn= deasm (addr,oline);
|
||
memode= DATA;
|
||
printf ("\n%s\n",oline);
|
||
/*
|
||
** printf ("\t%s\n",&oline[24]);
|
||
*/
|
||
return (diopn);
|
||
}
|
||
|
||
/*
|
||
******** set mask ^= fcw bits nmemonically with string at *iscan
|
||
*/
|
||
|
||
sflags (mask,table)
|
||
WORD mask;
|
||
struct bitable table[];
|
||
{
|
||
int loop;
|
||
while (!eolchr(*iscan)) {
|
||
for (loop= 0; table[loop].bitmask; loop++) {
|
||
if (*iscan != table[loop].bitlabel) continue;
|
||
mask^= table[loop].bitmask;
|
||
break;
|
||
}
|
||
if (!table[loop].bitmask) error=77; /* bad flag */
|
||
iscan++;
|
||
}
|
||
return (mask);
|
||
}
|
||
|
||
/*
|
||
******** display fcw bits nmemonically using bitable[]
|
||
*/
|
||
|
||
dflags(mask,table)
|
||
WORD mask;
|
||
struct bitable table[];
|
||
{
|
||
int loop;
|
||
printf ("\"");
|
||
for (loop= 0; table[loop].bitmask; loop++) {
|
||
if (mask & table[loop].bitmask)
|
||
{ printf ("%c",table[loop].bitlabel); }
|
||
else
|
||
{ printf ("."); }
|
||
}
|
||
printf ("\"");
|
||
}
|
||
|
||
/*
|
||
******** down load a file into user memory
|
||
*/
|
||
|
||
#ifdef CPM
|
||
|
||
inload(state,fname)
|
||
union pstate *state;
|
||
char *fname;
|
||
{
|
||
int findex;
|
||
struct m_rt mrt;
|
||
struct ustack stack;
|
||
long addr,from,to;
|
||
char *arglist;
|
||
struct ccb *ccbptr;
|
||
|
||
printf ("loading '%s':\n",fname);
|
||
findex= openb(fname,0);
|
||
if (findex < 0) error=80;
|
||
if (error) return;
|
||
|
||
from= map_adr((long)bios(BGETMRT),2); /* phys addr MRT in sys data */
|
||
to= map_adr((long)&mrt,0); /* phys addr of my MRT struct */
|
||
mem_cpy (from,to,(long)sizeof(mrt));
|
||
|
||
LPB.pgldaddr= mrt.m_reg[0].m_low;
|
||
LPB.pgtop = mrt.m_reg[0].m_len;
|
||
ccbptr = &_fds[findex];
|
||
LPB.fcbaddr= map_adr((long)&(ccbptr->fcb), 0);
|
||
|
||
tlong= _prog_load(map_adr((long)&LPB,0));
|
||
if (error) return;
|
||
|
||
arglist= fname;
|
||
while (!delchr(*arglist)) arglist++;
|
||
|
||
addr= LPB.bpaddr - (SECLEN - sizeof (struct b_page));
|
||
tlong= _setdma(addr);
|
||
mem_cpy (map_adr((long)arglist,0), (long)addr, (long)SECLEN);
|
||
|
||
stack.two= (short) 2;
|
||
stack.bpgaddr= (short)LPB.bpaddr;
|
||
addr= LPB.bpaddr - sizeof (stack);
|
||
mem_cpy (map_adr((long)&stack,0), (long)addr, (long)sizeof(stack));
|
||
}
|
||
|
||
#else
|
||
|
||
inload(state,fname)
|
||
union pstate *state;
|
||
char *fname;
|
||
{
|
||
FILE *ifile;
|
||
|
||
printf ("loading '%s':\n",fname);
|
||
ifile= fopen(fname,"r");
|
||
if (ifile == NULL) error=80;
|
||
if (error) return;
|
||
while (fgets(iline,COLS,ifile) != NULL) {
|
||
iscan=iline;
|
||
printf (".");
|
||
inline(); /* process and load the line at iscan */
|
||
if (error) break;
|
||
}
|
||
state->lregs.pc= 0x0000;
|
||
printf ("\n");
|
||
}
|
||
|
||
/*
|
||
******** download a single line into user memory
|
||
*/
|
||
|
||
inline()
|
||
{
|
||
int lcode,ectr,ldat;
|
||
|
||
if (yflag & MUFOM) {
|
||
if (*iscan == 'A') {
|
||
iscan += 5;
|
||
iptr= hexin(9);
|
||
if (*iscan != '.') error=83;
|
||
return;
|
||
}
|
||
if (*iscan == 'L') {
|
||
iscan += 3;
|
||
while (*iscan != '.') {
|
||
ldat= hexin(2);
|
||
if (ishex(*iscan) < 0) break;
|
||
stchr (iptr++,(BYTE)ldat);
|
||
}
|
||
if (*iscan != '.') error=85;
|
||
return;
|
||
}
|
||
error=81;
|
||
return;
|
||
}
|
||
|
||
if (*iscan != ':') { error=81; return; }
|
||
iscan++;
|
||
ectr= hexin(2); /* get the record length */
|
||
if (ishex(*iscan) < 0) { error=82; return; }
|
||
|
||
iptr= hexin(8); /* get the load addr */
|
||
if (ishex(*iscan) < 0) { error=83; return; }
|
||
|
||
lcode= hexin(2); /* get the control code */
|
||
if (ishex(*iscan) < 0) { error=84; return; }
|
||
|
||
switch (lcode) {
|
||
case 0: /* data */
|
||
while (ectr--) {
|
||
ldat= hexin(2);
|
||
if (ishex(*iscan)<0 && ectr) error=85;
|
||
if (error) return;
|
||
stchr (iptr++,(BYTE)ldat);
|
||
}
|
||
break;
|
||
case 1: /* EOF */
|
||
case 2: /* extended address mark */
|
||
case 3: /* start address */
|
||
default:
|
||
error=86; return;
|
||
}
|
||
if (ishex(*iscan) < 0) { error=87; return; }
|
||
ichksum= hexin(2); /* get the checksum */
|
||
|
||
if (*iscan == '\n') iscan++;
|
||
if (*iscan != '\0') error=88;
|
||
}
|
||
|
||
#endif
|
||
|
||
/*
|
||
******** assemble into user memory (with deassembly verification)
|
||
*/
|
||
|
||
asdis(adptr,adbuf)
|
||
POINTER adptr;
|
||
char *adbuf;
|
||
{
|
||
int asopn,diopn;
|
||
if (eolchr(*iscan)) return (0);
|
||
memode= CODE;
|
||
asopn= asmbl(adptr,adbuf);
|
||
memode= DATA;
|
||
if (error) return (asopn);
|
||
if (infixflg) error= 10;
|
||
if (error) return (asopn);
|
||
memode= CODE;
|
||
diopn= deasm(adptr,oline);
|
||
memode= DATA;
|
||
if (error) return (diopn);
|
||
printf ("%s\n",oline);
|
||
/*
|
||
** if (asopn != diopn) error=46;
|
||
*/
|
||
if (error) return (asopn);
|
||
if (getnext(asopn) != getnext(diopn)) error=47;
|
||
return (diopn);
|
||
}
|
||
|
||
/*
|
||
******** encode and output a user memory address
|
||
*/
|
||
|
||
adrout (ptr)
|
||
POINTER ptr;
|
||
{
|
||
printf ("%08lx: ",ptr);
|
||
}
|
||
|