mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-12-10 07:13:02 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
These are the C sources for a CP/M-8000 version from May 5, 1983 and October 20, 1983. Version number unknown, possibly 1.0. Some sources contain the string "P-CP/M for the Olivetti M20 (Z8001)". Included is the BIOS for the Olivetti M20 Z8001 and adaptions for the Kontron Z8002. Also included is a set of manuals in TEX format.
|
||||
Here are some comments I recently received regarding this and the two following archives:
|
||||
|
||||
Reading 'bdos/bdosmisc.c' reveals: "CPM-Z8000 Version 1.2 03/14/83". This file seems to be the usual place for version and copyright strings in CP/M's written in C.
|
||||
In the same archive, 'newos/bdosmisc.c' says "CPM-Z8000 Version 1.3 06/14/83". Sad, really, that 'newos/bdosmain.c' is the cut-down 'loader' version of the BDOS. Sadder still that BDOSMA.C in cpm8k13.zip is also the loader BDOS.
|
||||
Might as well dip into cpm8k11, then...
|
||||
|
||||
1. The BIOS (source) is for the Olivetti M20.
|
||||
2. There's no source for BDOS and utils.
|
||||
3. There is a C compiler: "Zilog CP/M-Z8000 C Compiler v1.01e 12/26/84". In the readme on disk 4 it is claimed that the -D option is broken on this version. Clearly not good.
|
||||
|
||||
@@ -0,0 +1,724 @@
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "stdio.h"
|
||||
#include "acom.h"
|
||||
#include "obj.h"
|
||||
|
||||
/*
|
||||
* Version Z.3, 4/7/83. Added explicit fclose of LIST and OBJECT files,
|
||||
* in case of error exit.
|
||||
*
|
||||
* Version Z.2, 4/5/83. Added external declarations of the variables
|
||||
* segflg and oflag, which are used in chaining to xcon.
|
||||
*
|
||||
* Version Z.1, 10/14/82. killed profiling and made cpm changes.
|
||||
*
|
||||
* Version 3.7, 10/13/82. Changed dopass() so that the default section
|
||||
* at the beginning of each pass is "__text" rather than the absolute
|
||||
* section. This is a FUNCTIONAL CHANGE.
|
||||
*
|
||||
* Version 3.6, 8/20/82. Changed laboc() to accomodate the colon
|
||||
* as a legitimate token rather than as a part of a label, for the
|
||||
* 8086 assembler.
|
||||
*
|
||||
* Version 3.5, 8/19/82. Fixed two minor bugs: 1. Location counter
|
||||
* field sometimes came out too long on 32-bit machines. 2. Undefined
|
||||
* symbols sometimes went into the object file with non-zero values.
|
||||
*
|
||||
* Version 3.4, 7/5/82. Added hooks for profiling.
|
||||
*
|
||||
* Version 3.3, 5/27/82. Added uext (-u) switch.
|
||||
*
|
||||
* Version 3.2, 5/22/82. Moved closing of files into special exit()
|
||||
* routine in a.misc.c.
|
||||
*/
|
||||
static char ident[] = "@(#)a.ascom.c 3.6";
|
||||
|
||||
extern char segflg;
|
||||
extern char oflag;
|
||||
|
||||
char putfile[15];
|
||||
char optfile[15];
|
||||
|
||||
main(argc,argv) int argc; char *argv[]; {
|
||||
|
||||
static char errfmt[] = "%u errors, %u warnings\n";
|
||||
struct octab *ocp;
|
||||
int index;
|
||||
|
||||
init(argc,argv);
|
||||
dopass();
|
||||
interlude();
|
||||
pass2 = 1;
|
||||
dopass();
|
||||
oflush(); objtyp = OBOND; oflush();
|
||||
if(lflag) {
|
||||
pgcheck(); fputc('\n',LIST);
|
||||
pgcheck(); fprintf(LIST,errfmt,errct,warnct);
|
||||
if(xflag) putxref();
|
||||
}
|
||||
unlink("VM.TMP");
|
||||
if(errct) {
|
||||
fprintf(ERROR,errfmt,errct,warnct);
|
||||
fclose(LIST);
|
||||
fclose(OBJECT);
|
||||
exit(1);
|
||||
}
|
||||
argv[index = 0] = "xcon";
|
||||
index++;
|
||||
if (segflg)
|
||||
argv[index++] = "-s";
|
||||
if (oflag) {
|
||||
argv[index++] = "-o";
|
||||
argv[index++] = optfile;
|
||||
}
|
||||
argv[index++] = putfile;
|
||||
argv[index] = NULL;
|
||||
chain(argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* assem1 - Assembles a single statement.
|
||||
*/
|
||||
assem1() {
|
||||
|
||||
laboc();
|
||||
if(*opcstr) { /* we have an opcode field */
|
||||
opcode = oclook(opcstr);
|
||||
switch(opcode->oc_typ) {
|
||||
|
||||
case OTUND: /* undefined mnemonic */
|
||||
err('O'); skipeol();
|
||||
break;
|
||||
|
||||
case OTINS: /* machine instruction */
|
||||
instr(opcode->oc_val);
|
||||
break;
|
||||
|
||||
case OTDIR: /* assembler directive */
|
||||
direc(opcode->oc_val);
|
||||
break;
|
||||
|
||||
case OTMAC: /* macro call */
|
||||
macro(opcode->oc_val);
|
||||
break;
|
||||
|
||||
}
|
||||
} else if(*labstr) { /* we have a label field standing alone */
|
||||
label = sylook(labstr);
|
||||
assign(STLAB,curloc,cursec);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* assign - If a label is present, this routine gives it the specified type,
|
||||
* value, and relocation, checking for multiple definition and phase errors.
|
||||
* It also records a cross reference entry. The returned value is a pointer
|
||||
* to the label's sytab entry (in physical memory), or 0 if there was no
|
||||
* label or there was an error.
|
||||
*/
|
||||
struct sytab *
|
||||
assign(typ,val,rel) uns typ; exprval val; uns rel; {
|
||||
|
||||
struct sytab *syp;
|
||||
|
||||
sprintf(llloc,"%04x",(uns)(val&0xffff));
|
||||
if(label == 0) return(0); /* no label */
|
||||
xref(label,XRDEF);
|
||||
syp = wfetch(label);
|
||||
if(syp->sy_typ!=STVAR&&(pass2?syp->sy_atr&SADP2:syp->sy_typ!=STUND)) {
|
||||
err('M'); syp->sy_atr |= SAMUD;
|
||||
return(0);
|
||||
}
|
||||
if(syp->sy_typ == STUND) { /* assign a type */
|
||||
syp->sy_typ = typ; syp->sy_rel = RBUND;
|
||||
} else if(syp->sy_typ != typ) goto phaser;
|
||||
if(syp->sy_rel==RBUND || syp->sy_typ==STVAR) { /* assign a value */
|
||||
syp->sy_val = val; syp->sy_rel = rel;
|
||||
} else if(syp->sy_val!=val || syp->sy_rel!=rel) goto phaser;
|
||||
if(pass2) syp->sy_atr |= SADP2;
|
||||
return(syp);
|
||||
phaser:
|
||||
err('P');
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* def1 - Copies one statement into a macro definition.
|
||||
*/
|
||||
def1() {
|
||||
|
||||
int argno;
|
||||
|
||||
/*
|
||||
* Check for an ADMAC or ADENDM directive.
|
||||
*/
|
||||
laboc();
|
||||
if(*opcstr) { /* opcode field */
|
||||
opcode = oclook(opcstr);
|
||||
if(opcode->oc_typ == OTDIR) { /* directive */
|
||||
if(opcode->oc_val == ADMAC) { /* nested macro def */
|
||||
deflev++;
|
||||
} else if(opcode->oc_val == ADENDM) { /* end def */
|
||||
deflev--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(deflev > 0) { /* copy a line of the definition */
|
||||
scanpt = sline; /* reset scan to beginning of line */
|
||||
do {
|
||||
scanc();
|
||||
if(ch == escchr) { /* escaped character */
|
||||
scanc();
|
||||
*wfetch(valloc(1)) = ch;
|
||||
} else if(ch == argchr) { /* macro parameter */
|
||||
scanc();
|
||||
if(ch == mctchr) /* macro expansion ct */
|
||||
*wfetch(valloc(1)) = 0200;
|
||||
else if(ch == argchr) /* extra args */
|
||||
*wfetch(valloc(1)) = 0201;
|
||||
else if('0'<=ch && ch<='9') {
|
||||
argno = ch-'0';
|
||||
if(argno > curdef->oc_arg)
|
||||
curdef->oc_arg = argno;
|
||||
*wfetch(valloc(1)) = argno+0202;
|
||||
} else err('A');
|
||||
} else { /* normal character */
|
||||
*wfetch(valloc(1)) = ch;
|
||||
}
|
||||
} while(ch != '\n');
|
||||
unscanc(); token();
|
||||
} else { /* finish off the definition */
|
||||
*wfetch(valloc(1)) = '\0';
|
||||
}
|
||||
skipeol();
|
||||
}
|
||||
|
||||
/*
|
||||
* delim - Skips over a delimiter string if one is present.
|
||||
*/
|
||||
delim() {
|
||||
|
||||
if(toktyp == TKSPC) iilex();
|
||||
if(toktyp == TKCOM) iilex();
|
||||
if(toktyp == TKSPC) iilex();
|
||||
}
|
||||
|
||||
/*
|
||||
* dopass - Performs one pass of the source input.
|
||||
*/
|
||||
dopass() {
|
||||
|
||||
if(include(srcfile) != 0) {
|
||||
fprintf(ERROR,"Cannot open %s\n",srcfile);
|
||||
exit(1);
|
||||
}
|
||||
condlev = curatr = curloc = cursec = deflev = mexct =
|
||||
rptlev = sectab[0].se_loc = truelev = 0;
|
||||
curaln = minaln;
|
||||
curext = 32;
|
||||
reading = secct = 1;
|
||||
label = sylook("__text"); newsec(); /* set the default section */
|
||||
while(reading) { /* process statements one at a time */
|
||||
if(deflev > 0) { /* defining a macro */
|
||||
def1();
|
||||
} else if(rptlev > 0) { /* defining a repeat */
|
||||
rpt1();
|
||||
} else if(condlev > truelev) { /* skipping conditional code */
|
||||
skip1();
|
||||
} else { /* assembling statements normally */
|
||||
assem1();
|
||||
}
|
||||
if(toktyp == TKEOF) break;
|
||||
if(toktyp != TKEOL) {
|
||||
err('S'); skipeol();
|
||||
}
|
||||
putline();
|
||||
}
|
||||
setsec(0); /* update sectab info for last section */
|
||||
while(toktyp != TKEOF) token();
|
||||
}
|
||||
|
||||
/*
|
||||
* emitb - Emits a byte of object code.
|
||||
*/
|
||||
emitb(value,reloc) uns value, reloc; {
|
||||
|
||||
if(pass2) {
|
||||
/*
|
||||
* Check whether relocation is needed.
|
||||
*/
|
||||
if((reloc&RAMSK)==RANOP || (reloc&RBMSK)==RBABS) reloc = 0;
|
||||
/*
|
||||
* Output to the object file without breaking up a relocatable
|
||||
* item.
|
||||
*/
|
||||
if(relbot-objtop<(reloc?7:1)) oflush();
|
||||
setorg();
|
||||
if(reloc) {
|
||||
*--relbot = reloc>>8;
|
||||
*--relbot = reloc;
|
||||
*--relbot = objtop-objbuf;
|
||||
}
|
||||
oputb(value); objbuf[5]++;
|
||||
/*
|
||||
* Output to the listing.
|
||||
*/
|
||||
if(llobt >= llobj+LLOBJ) {
|
||||
putline();
|
||||
sprintf(llloc,"%04x",(uns)curloc);
|
||||
}
|
||||
sprintf(llobt,"%02x",value&0377);
|
||||
llobt = llobt + 2;
|
||||
}
|
||||
nxtloc = ++curloc;
|
||||
}
|
||||
|
||||
/*
|
||||
* emitl - Emits a long to the object file.
|
||||
*/
|
||||
emitl(value,reloc) long value; uns reloc; {
|
||||
|
||||
emitw((uns)value,reloc);
|
||||
emitw((uns)(value>>16),0);
|
||||
}
|
||||
|
||||
/*
|
||||
* emitw - Emits a word to the object file.
|
||||
*/
|
||||
emitw(value,reloc) uns value, reloc; {
|
||||
|
||||
emitb(value,reloc);
|
||||
emitb(value>>8,0);
|
||||
}
|
||||
|
||||
/*
|
||||
* err - Puts the specified error flag into the listing.
|
||||
*/
|
||||
err(c) int c; {
|
||||
|
||||
if(!pass2 || llert>=llerr+LLERR) return;
|
||||
if(c<=' ' || c>='\177') c = '?';
|
||||
*llert++ = c;
|
||||
*llert = '\0';
|
||||
errct++;
|
||||
}
|
||||
|
||||
/*
|
||||
* expression - Parses an expression and checks for various error conditions.
|
||||
* the expression's value and relocation are left in curop. At call time,
|
||||
* iilexeme should contain the first token of the expression.
|
||||
*/
|
||||
expression() {
|
||||
|
||||
if(iiparse() != 0) { /* error */
|
||||
curop.op_cls = 0L;
|
||||
while(toktyp!=TKCOM && toktyp!=TKEOL) token();
|
||||
}
|
||||
if(!(curop.op_cls&1L<<OCEXP)) { /* not expression */
|
||||
err('S'); curop.op_val = 0; curop.op_rel = RBUND;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* interlude - Performs processing between pass 1 and pass 2.
|
||||
*/
|
||||
interlude() {
|
||||
|
||||
struct sytab *syp;
|
||||
vmadr p;
|
||||
uns h;
|
||||
uns rel;
|
||||
char type;
|
||||
|
||||
objtyp = OBOST; oflush();
|
||||
for(rel=RBSEC ; rel<secct ; rel++) { /* output sections blocks */
|
||||
if(objtyp!=OBSEC || relbot-objtop<SYMSIZ+7) {
|
||||
oflush(); objtyp = OBSEC;
|
||||
}
|
||||
syp = (struct sytab *)rfetch(sectab[rel].se_sym);
|
||||
oputb(sectab[rel].se_aln);
|
||||
oputb(sectab[rel].se_ext);
|
||||
oputb(sectab[rel].se_atr);
|
||||
oputs(syp->sy_str);
|
||||
}
|
||||
rel = RBEXT;
|
||||
for(h=0 ; h<1<<SHSHLOG ; h++) {
|
||||
for(p=syhtab[h] ; p ; p=syp->sy_lnk) {
|
||||
syp = (struct sytab *)rfetch(p);
|
||||
if(syp->sy_typ==STKEY || syp->sy_typ==STSEC) continue;
|
||||
if(syp->sy_atr&SAGLO || uext&&syp->sy_typ==STUND)
|
||||
type = OBGLO;
|
||||
else
|
||||
type = OBLOC;
|
||||
if(objtyp!=type || relbot-objtop<SYMSIZ+7) {
|
||||
oflush(); objtyp = type;
|
||||
}
|
||||
if(syp->sy_typ == STUND) {
|
||||
oputl(0L);
|
||||
oputb(RBUND);
|
||||
if(syp->sy_atr&SAGLO || uext) {
|
||||
if(rel >= RBMSK) {
|
||||
fprintf(ERROR,"Too many externals\n");
|
||||
exit(1);
|
||||
}
|
||||
syp = (struct sytab *)wfetch(p);
|
||||
syp->sy_typ = STLAB;
|
||||
syp->sy_atr |= SAGLO;
|
||||
syp->sy_val = 0;
|
||||
syp->sy_rel = rel++;
|
||||
}
|
||||
} else {
|
||||
oputl((long)syp->sy_val);
|
||||
oputb(syp->sy_rel);
|
||||
}
|
||||
oputs(syp->sy_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* laboc - Scans the label and opcode fields from the next assembler
|
||||
* statement, and leaves their strings in global arrays labstr and
|
||||
* opcstr. Each string is set to null if its field is missing. Toktyp
|
||||
* is left on the token after the opcode (if it is present).
|
||||
*/
|
||||
laboc() {
|
||||
|
||||
labstr[0] = opcstr[0] = 0;
|
||||
if(token() == TKSYM) { /* label in column 1, possibly with colon */
|
||||
symcpy(labstr,tokstr); labstr[SYMSIZ] = '\0';
|
||||
if(token() == TKCOLON) /* colon label */
|
||||
token();
|
||||
if(toktyp == TKSPC) token();
|
||||
if(toktyp == TKSYM) { /* opcode */
|
||||
symcpy(opcstr,tokstr); opcstr[SYMSIZ] = '\0';
|
||||
token();
|
||||
}
|
||||
} else if(toktyp==TKSPC && token()==TKSYM) { /* colon label or opcode */
|
||||
symcpy(labstr,tokstr); labstr[SYMSIZ] = '\0';
|
||||
if(token() == TKCOLON) { /* was a label, check for opcode */
|
||||
if(token() == TKSPC) token();
|
||||
if(toktyp == TKSYM) { /* opcode */
|
||||
symcpy(opcstr,tokstr); opcstr[SYMSIZ] = '\0';
|
||||
token();
|
||||
}
|
||||
} else { /* oops, was opcode, not label */
|
||||
symcpy(opcstr,labstr);
|
||||
opcstr[SYMSIZ] = labstr[0] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* macro - Processes a macro call.
|
||||
*/
|
||||
macro(vp) vmadr vp; {
|
||||
|
||||
struct input *newfp;
|
||||
int brlev;
|
||||
int i;
|
||||
char **avp;
|
||||
char *sp;
|
||||
char mch;
|
||||
char nbuf[6];
|
||||
|
||||
/*
|
||||
* Create an input stack frame with room for argument pointers
|
||||
* at the beginning of the variable area.
|
||||
*/
|
||||
newfp = pushin(); avp = insp;
|
||||
insp += (opcode->oc_arg+3)*sizeof(char *); iovck();
|
||||
newfp->in_typ = INMAC;
|
||||
/*
|
||||
* Push the macro expansion count (?#) string, and initialize the
|
||||
* extra arguments (??) string to null.
|
||||
*/
|
||||
avp[0] = insp;
|
||||
sprintf(nbuf,"%u",++mexct);
|
||||
sp = nbuf;
|
||||
while(*sp != '\0') pushc(*sp++);
|
||||
avp[1] = insp;
|
||||
pushc('\0');
|
||||
/*
|
||||
* Push the label (?0) string.
|
||||
*/
|
||||
avp[2] = insp;
|
||||
sp = labstr;
|
||||
i = SYMSIZ;
|
||||
while(--i>=0 && *sp!='\0') pushc(*sp++);
|
||||
pushc('\0');
|
||||
/*
|
||||
* Push the operand field arguments.
|
||||
*/
|
||||
if(toktyp == TKSPC) scanc();
|
||||
for(i=1 ; i<=opcode->oc_arg||ch!='\n'&&ch!=';' ; i++) {
|
||||
if(i <= opcode->oc_arg) { /* an expected argument */
|
||||
avp[i+2] = insp;
|
||||
} else { /* an extra argument */
|
||||
if(i == opcode->oc_arg+1) { /* first extra arg */
|
||||
avp[1] = insp;
|
||||
} else { /* additional extra arg */
|
||||
insp[-1] = ',';
|
||||
}
|
||||
pushc(lbrchr);
|
||||
}
|
||||
if(ch == lbrchr) { /* argument enclosed in braces */
|
||||
brlev = 1;
|
||||
for(;;) {
|
||||
scanc();
|
||||
if(ch == lbrchr) brlev++;
|
||||
else if(ch == rbrchr) brlev--;
|
||||
if(brlev<=0 || ch=='\n') break;
|
||||
if(ch == escchr) scanc();
|
||||
pushc(ch);
|
||||
}
|
||||
if(ch == rbrchr) scanc();
|
||||
} else { /* normal argument (not in braces) */
|
||||
while(ch!=',' && !white(ch) && ch!='\n' && ch!=';') {
|
||||
pushc(ch); scanc();
|
||||
}
|
||||
}
|
||||
if(i > opcode->oc_arg) pushc(rbrchr);
|
||||
pushc('\0');
|
||||
while(white(ch)) scanc();
|
||||
if(ch == ',') scanc();
|
||||
while(white(ch)) scanc();
|
||||
}
|
||||
while(ch != '\n') scanc();
|
||||
toktyp = TKEOL;
|
||||
/*
|
||||
* Copy the macro body onto the input stack.
|
||||
*/
|
||||
newfp->in_ptr = insp;
|
||||
while(mch = *rfetch(vp++)) {
|
||||
pushc(mch); newfp->in_cnt++;
|
||||
}
|
||||
/*
|
||||
* Switch input source to macro stack frame.
|
||||
*/
|
||||
infp = newfp;
|
||||
if((curlst = infp->in_lst&0377) != 0) curlst--;
|
||||
}
|
||||
|
||||
/*
|
||||
* newsec - Creates a new section and makes it the current section.
|
||||
*/
|
||||
newsec() {
|
||||
|
||||
if(secct >= SECSIZ) {
|
||||
fprintf(ERROR,"Too many sections\n");
|
||||
exit(1);
|
||||
}
|
||||
assign(STSEC,(exprval)0,secct);
|
||||
sectab[secct].se_sym = label;
|
||||
setsec(secct++);
|
||||
curatr = curloc = 0;
|
||||
curaln = minaln;
|
||||
curext = 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* oflush - Outputs an object block to the object file.
|
||||
*/
|
||||
oflush() {
|
||||
|
||||
char *op;
|
||||
|
||||
if(objtyp) {
|
||||
fputc(objtyp,OBJECT);
|
||||
fputc(OBJSIZ-(relbot-objtop),OBJECT);
|
||||
for(op=objbuf ; op<objtop ; op++) fputc(*op,OBJECT);
|
||||
for(op=relbot ; op<&objbuf[OBJSIZ] ; op++) fputc(*op,OBJECT);
|
||||
}
|
||||
objtop = objbuf; relbot = &objbuf[OBJSIZ]; objtyp = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* oputb - Puts a byte into the object buffer.
|
||||
*/
|
||||
oputb(c) char c; {
|
||||
|
||||
if(objtop >= relbot) {
|
||||
fprintf(ERROR,"Object buffer overflow\n");
|
||||
exit(1);
|
||||
}
|
||||
*objtop++ = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* oputl - Puts a long word into the object buffer.
|
||||
*/
|
||||
oputl(l) long l; {
|
||||
|
||||
oputw((uns)l);
|
||||
oputw((uns)(l>>16));
|
||||
}
|
||||
|
||||
/*
|
||||
* oputs - Puts a symbol into the object buffer.
|
||||
*/
|
||||
oputs(s) char *s; {
|
||||
|
||||
char i;
|
||||
|
||||
i = SYMSIZ;
|
||||
do {
|
||||
if(*s == '\0') break;
|
||||
oputb(*s++);
|
||||
} while(--i > 0);
|
||||
oputb('\0');
|
||||
}
|
||||
|
||||
/*
|
||||
* oputw - Puts a word into the object buffer.
|
||||
*/
|
||||
oputw(w) uns w; {
|
||||
|
||||
oputb(w);
|
||||
oputb(w>>8);
|
||||
}
|
||||
|
||||
/*
|
||||
* rpt1 - Copies one statement into a repeat definition.
|
||||
*/
|
||||
rpt1() {
|
||||
|
||||
struct input *newfp;
|
||||
vmadr vp;
|
||||
char rch;
|
||||
|
||||
laboc();
|
||||
if(*opcstr) { /* check opcode field for special cases */
|
||||
opcode = oclook(opcstr);
|
||||
if(opcode->oc_typ == OTDIR) { /* directive */
|
||||
if(opcode->oc_val == ADREPT) { /* nested repeat */
|
||||
rptlev++;
|
||||
} else if(opcode->oc_val == ADENDR) { /* end rpt */
|
||||
rptlev--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(rptlev > 0) { /* copy a line of the repeat definition */
|
||||
scanpt = sline; /* reset scan to beginning of line */
|
||||
do { /* copy the line */
|
||||
scanc();
|
||||
*wfetch(valloc(1)) = ch;
|
||||
} while(ch != '\n');
|
||||
unscanc(); token();
|
||||
} else { /* finish off the repeat definition and start the repeat */
|
||||
*wfetch(valloc(1)) = '\0';
|
||||
newfp = pushin();
|
||||
newfp->in_typ = INRPT;
|
||||
newfp->in_rpt = rptct;
|
||||
vp = rptstr;
|
||||
while(rch = *rfetch(vp++)) { /* copy definition to stack */
|
||||
pushc(rch);
|
||||
}
|
||||
newfp->in_ptr = insp; /* set up as though at end of frame */
|
||||
virtop = rptstr; /* free up the virtual space */
|
||||
infp = newfp; /* switch to new input stack frame */
|
||||
if((curlst = infp->in_lst&0377) != 0) curlst--;
|
||||
}
|
||||
skipeol();
|
||||
}
|
||||
|
||||
/*
|
||||
* setorg - Sets up the next address for text output.
|
||||
*/
|
||||
setorg() {
|
||||
|
||||
if(objtyp!=OBTXT || nxtloc!=curloc || nxtsec!=cursec) {
|
||||
oflush(); objtyp = OBTXT;
|
||||
oputl((long)curloc); oputb(cursec); oputb(0);
|
||||
nxtloc = curloc; nxtsec = cursec;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* setsec - Changes to the specified section for code generation.
|
||||
*/
|
||||
setsec(sec) uns sec; {
|
||||
|
||||
sectab[cursec].se_aln = curaln;
|
||||
sectab[cursec].se_ext = curext;
|
||||
sectab[cursec].se_atr = curatr;
|
||||
sectab[cursec].se_loc = curloc;
|
||||
cursec = sec;
|
||||
curaln = sectab[cursec].se_aln;
|
||||
curext = sectab[cursec].se_ext;
|
||||
curatr = sectab[cursec].se_atr;
|
||||
curloc = sectab[cursec].se_loc;
|
||||
}
|
||||
|
||||
/*
|
||||
* skip1 - Skips one statement due to an unsatisfied conditional assembly.
|
||||
*/
|
||||
skip1() {
|
||||
|
||||
laboc();
|
||||
opcode = *opcstr?oclook(opcstr):0;
|
||||
if(opcode && opcode->oc_typ==OTDIR) {
|
||||
switch(opcode->oc_val) {
|
||||
|
||||
case ADIF: /* .if */
|
||||
condlev++;
|
||||
break;
|
||||
|
||||
case ADELSE: /* .else */
|
||||
if(truelev == condlev-1) truelev++;
|
||||
break;
|
||||
|
||||
case ADENDIF: /* .endif */
|
||||
condlev--;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if(condlev > truelev) { /* mark listing line as skipped */
|
||||
sprintf(llobj,"%8s","-"); /* 8 should be LLOBJ */
|
||||
llobt = llobj + LLOBJ;
|
||||
} else
|
||||
/*
|
||||
* End of the skip. List the directive regardless of
|
||||
* the condlst value.
|
||||
*/
|
||||
llfull = curlst;
|
||||
skipeol();
|
||||
}
|
||||
|
||||
/*
|
||||
* skipeol - Skips to the next end of line or end of file.
|
||||
*/
|
||||
skipeol() {
|
||||
|
||||
while(toktyp!=TKEOL && toktyp!=TKEOF) token();
|
||||
}
|
||||
|
||||
/*
|
||||
* title - Puts a title into the specified string, and fixes up the listing.
|
||||
*/
|
||||
title(s) char *s; {
|
||||
|
||||
if(!pass2) return;
|
||||
if(toktyp==TKSPC && token()==TKSTR) {
|
||||
tokstr[TITSIZ] = '\0';
|
||||
strcpy(s,tokstr);
|
||||
token();
|
||||
llfull = linect = 0;
|
||||
} else err('S');
|
||||
}
|
||||
|
||||
/*
|
||||
* warn - Puts the specified warning flag into the listing.
|
||||
*/
|
||||
warn(c) int c; {
|
||||
|
||||
if(!pass2 || llert>=llerr+LLERR) return;
|
||||
if(c<=' ' || c>='\177') c = '?';
|
||||
*llert++ = c;
|
||||
*llert = '\0';
|
||||
warnct++;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* @(#)a.com.h 3.5
|
||||
*
|
||||
* Declarations common to all of the cross assemblers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Version 3.5, 8/20/82. Added extensions for the 8086.
|
||||
*
|
||||
* Version 3.4, 7/5/82. Added scanc() and white() macros.
|
||||
*
|
||||
* Version 3.3, 5/27/82. Added uext switch.
|
||||
*
|
||||
* Version 3.2, 5/22/82. Added define for PDDIR.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parameters.
|
||||
*/
|
||||
#define BLKLOG 9 /* log base 2 of disk block size */
|
||||
#define IISIZ 30 /* size of parse stack in frames */
|
||||
#define INSIZ 4096 /* size of input stack in bytes */
|
||||
#define LLERR 3 /* length of error field in listing line */
|
||||
#define LLLOC 4 /* length of location field in listing line */
|
||||
#define LLOBJ 8 /* length of object field in listing line */
|
||||
#define LLPP 58 /* listing lines/page (must be less than 64) */
|
||||
#define LLSEQ 5 /* length of sequence field in listing line */
|
||||
#define OBJSIZ 255 /* maximum object block length */
|
||||
#define OHSHLOG 6 /* log base 2 of opcode hash table size */
|
||||
|
||||
#ifndef PDDIR /* following define overridable in cc line */
|
||||
#define PDDIR "/usr/lib" /* directory containing the predef file */
|
||||
#endif PDDIR
|
||||
|
||||
#define SECSIZ 255 /* maximum number of sections including abs */
|
||||
#define SHSHLOG 9 /* log base 2 of symbol hash table size */
|
||||
#define SLINSIZ 128 /* maximum source line length */
|
||||
#define STRSIZ 128 /* maximum string length */
|
||||
#define SYMSIZ 8 /* maximum symbol length */
|
||||
#define TITSIZ 47 /* maximum title string length */
|
||||
/*
|
||||
* Assembler directive numbers.
|
||||
*/
|
||||
#define ADABS 19 /* .abs */
|
||||
#define ADALIGN 20 /* .align */
|
||||
#define ADBLOCK 7 /* .block */
|
||||
#define ADBYTE 4 /* .byte */
|
||||
#define ADCLIST 9 /* .clist */
|
||||
#define ADCOM 26 /* .common */
|
||||
#define ADEJECT 25 /* .eject */
|
||||
#define ADELSE 15 /* .else */
|
||||
#define ADEND 1 /* .end */
|
||||
#define ADENDIF 16 /* .endif */
|
||||
#define ADENDM 23 /* .endm */
|
||||
#define ADENDR 28 /* .endr */
|
||||
#define ADEQU 2 /* .equ */
|
||||
#define ADERROR 30 /* .error */
|
||||
#define ADEXIT 31 /* .exit */
|
||||
#define ADGLOB 18 /* .global */
|
||||
#define ADIF 17 /* .if */
|
||||
#define ADINPUT 3 /* .input */
|
||||
#define ADLIST 14 /* .list */
|
||||
#define ADLONG 24 /* .long */
|
||||
#define ADMAC 22 /* .macro */
|
||||
#define ADORG 8 /* .org */
|
||||
#define ADREPT 29 /* .repeat */
|
||||
#define ADSECT 10 /* .sect */
|
||||
#define ADSET 6 /* .set */
|
||||
#define ADSPACE 11 /* .space */
|
||||
#define ADSTITL 12 /* .stitle */
|
||||
#define ADTITLE 13 /* .title */
|
||||
#define ADWARN 33 /* .warn */
|
||||
#define ADWITHN 21 /* .within */
|
||||
#define ADWORD 5 /* .word */
|
||||
/*
|
||||
* Parsing constants and flags.
|
||||
*/
|
||||
#define IIAFLG 020000 /* alternate left parts flag */
|
||||
#define IIDSYM 0377 /* default symbol in scntab */
|
||||
#define IIESYM 0376 /* error symbol in scntab */
|
||||
#define IILMSK 0007 /* production length mask */
|
||||
#define IINFLG 0400 /* nonterminal symbol flag */
|
||||
#define IIRFLG 040000 /* read and reduce flag */
|
||||
#define IIXFLG 0100000 /* transition flag */
|
||||
/*
|
||||
* Input stack frame types (in in_typ).
|
||||
*/
|
||||
#define INFILE 1 /* file */
|
||||
#define INMAC 2 /* macro expansion */
|
||||
#define INRPT 3 /* repeat */
|
||||
#define INARG 4 /* macro argument */
|
||||
/*
|
||||
* Operand classes.
|
||||
*/
|
||||
#define OCNULL 0x00 /* no operand */
|
||||
#define OCNEX 0x01 /* nn */
|
||||
#define OCPEX 0x02 /* (nn) */
|
||||
#define OCEXP 0x03 /* {nn,(nn)} */
|
||||
/*
|
||||
* Operand flags (in op_flg and ps_flg).
|
||||
*/
|
||||
#define OFFOR 0x8000 /* operand contains a forward reference */
|
||||
/*
|
||||
* Opcode types (in oc_typ).
|
||||
*/
|
||||
#define OTUND 0 /* undefined */
|
||||
#define OTINS 1 /* instruction */
|
||||
#define OTDIR 2 /* directive */
|
||||
#define OTMAC 3 /* macro */
|
||||
/*
|
||||
* Symbol attribute flags (in sy_atr).
|
||||
*/
|
||||
#define SADP2 0001 /* defined in pass 2 */
|
||||
#define SAMUD 0002 /* multiply defined */
|
||||
#define SAGLO 0004 /* global */
|
||||
/*
|
||||
* Symbol types (in sy_typ).
|
||||
*/
|
||||
#define STUND 0 /* undefined */
|
||||
#define STKEY 1 /* keyword */
|
||||
#define STSEC 2 /* section */
|
||||
#define STLAB 3 /* label or equ */
|
||||
#define STVAR 4 /* variable (redefinable) */
|
||||
/*
|
||||
* Token types and values returned from the lexical scanner.
|
||||
*/
|
||||
#define TKEOF 0 /* end of file -- must be 0 */
|
||||
#define TKDOL 1 /* dollar sign */
|
||||
#define TKSYM 2 /* symbol */
|
||||
#define TKCON 3 /* constant */
|
||||
#define TKSTR 4 /* quoted string */
|
||||
#define TKUNOP 5 /* unary operator */
|
||||
#define TKMULOP 6 /* multiplicative operator */
|
||||
#define TVMUL 1 /* multiplication */
|
||||
#define TVDIV 2 /* division */
|
||||
#define TVMOD 3 /* modulo */
|
||||
#define TVSHL 4 /* shift left */
|
||||
#define TVSHR 5 /* shift right */
|
||||
#define TKADDOP 7 /* additive operator */
|
||||
#define TVADD 1 /* addition */
|
||||
#define TVSUB 2 /* subtraction */
|
||||
#define TKRELOP 8 /* relational operator */
|
||||
#define TVEQ 1 /* equal */
|
||||
#define TVNE 2 /* not equal */
|
||||
#define TVLT 3 /* less than */
|
||||
#define TVGT 4 /* greater than */
|
||||
#define TVLE 5 /* less than or equal */
|
||||
#define TVGE 6 /* greater than or equal */
|
||||
#define TKANDOP 9 /* logical and operator */
|
||||
#define TKXOROP 10 /* exclusive or operator */
|
||||
#define TKOROP 11 /* inclusive or operator */
|
||||
#define TKLPAR 12 /* left parenthesis */
|
||||
#define TKRPAR 13 /* right parenthesis */
|
||||
#define TKCOM 100 /* comma */
|
||||
#define TKCOLON 101 /* colon */
|
||||
#define TKEOL 102 /* end of line */
|
||||
#define TKSPC 103 /* white space */
|
||||
#define TKERR 127 /* erroneous token */
|
||||
/*
|
||||
* Virtual memory buffer flags (in vm_flg).
|
||||
*/
|
||||
#define VMDIR 01 /* dirty bit */
|
||||
/*
|
||||
* Cross reference masks (in xr_pl).
|
||||
*/
|
||||
#define XRDEF 0100000 /* Symbol defined at this reference */
|
||||
/*
|
||||
* Type definitions.
|
||||
*/
|
||||
#define exprval long /* expression value */
|
||||
#define reg register /* abbreviation for good tabbing */
|
||||
#define uns unsigned /* abbreviation for good tabbing */
|
||||
#define vmadr unsigned /* virtual memory address */
|
||||
/*
|
||||
* Pseudo-variables.
|
||||
*/
|
||||
#define ERROR stdout /* ERRORs go to standard output */
|
||||
FILE *LIST; /* pointer to listing FILE structure */
|
||||
FILE *OBJECT; /* pointer to object FILE structure */
|
||||
/*
|
||||
* Pseudo-functions.
|
||||
*/
|
||||
#define scanc() ((ch = *scanpt++)!='\0'&&ch!=escchr ? ch : xscanc())
|
||||
#define unscanc() (ch = *--scanpt)
|
||||
#define white(c) (c==' ' || c=='\t')
|
||||
/*
|
||||
* Structure declarations.
|
||||
*/
|
||||
struct aside { /* symbol lookaside table entry */
|
||||
struct aside *as_lnk; /* lru chain link */
|
||||
vmadr as_sym; /* symbol table entry pointer */
|
||||
char as_str[SYMSIZ]; /* symbol */
|
||||
};
|
||||
struct chent { /* single-character token table entry */
|
||||
char ch_chr; /* character */
|
||||
char ch_typ; /* token type */
|
||||
char ch_val; /* token value */
|
||||
};
|
||||
struct input { /* input stack frame */
|
||||
struct input *in_ofp; /* pointer to previous frame */
|
||||
char in_typ; /* frame type */
|
||||
char in_rpt; /* repeat count */
|
||||
char in_lst; /* listing level */
|
||||
char *in_ptr; /* pointer to next character */
|
||||
int in_cnt; /* number of characters left */
|
||||
int in_fd; /* file descriptor */
|
||||
uns in_seq; /* line number */
|
||||
char in_buf[1<<BLKLOG]; /* buffer area (variable size & use */
|
||||
};
|
||||
struct octab { /* opcode table entry */
|
||||
struct octab *oc_lnk; /* link to next entry in hash chain */
|
||||
uns oc_val; /* value of opcode */
|
||||
char oc_typ; /* type of opcode */
|
||||
char oc_arg; /* highest formal number for macro */
|
||||
char oc_str[SYMSIZ]; /* opcode mnemonic string */
|
||||
};
|
||||
struct operand { /* operand descriptor */
|
||||
long op_cls; /* set of classes (bit vector) */
|
||||
exprval op_val; /* value of operand */
|
||||
uns op_rel; /* relocation of operand */
|
||||
int op_flg; /* flags */
|
||||
};
|
||||
struct output { /* output buffering structure */
|
||||
char *ou_ptr; /* pointer to next character */
|
||||
int ou_cnt; /* number of characters left */
|
||||
int ou_fd; /* file descriptor */
|
||||
char ou_buf[1<<BLKLOG]; /* buffer */
|
||||
};
|
||||
struct psframe { /* parse stack frame */
|
||||
int *ps_state; /* parse state */
|
||||
int ps_sym; /* lookahead symbol */
|
||||
exprval ps_val0; /* usually subexpression value */
|
||||
uns ps_val1; /* usually subexpression relocation */
|
||||
int ps_flg; /* flags */
|
||||
};
|
||||
struct section { /* section table entry */
|
||||
vmadr se_sym; /* symbol table pointer */
|
||||
uns se_loc; /* location counter */
|
||||
char se_aln; /* alignment */
|
||||
char se_ext; /* extent */
|
||||
char se_atr; /* attributes */
|
||||
};
|
||||
struct sytab { /* symbol table entry */
|
||||
vmadr sy_lnk; /* link to next entry in hash chain */
|
||||
vmadr sy_xlk; /* link to rear of xref chain */
|
||||
exprval sy_val; /* value of symbol */
|
||||
uns sy_rel; /* relocation of symbol */
|
||||
char sy_typ; /* type of symbol */
|
||||
char sy_atr; /* attributes of symbol */
|
||||
char sy_str[SYMSIZ]; /* symbol mnemonic string */
|
||||
};
|
||||
struct vmbuf { /* virtual memory buffer */
|
||||
struct vmbuf *vm_lnk; /* lru link to next buffer */
|
||||
short vm_blk; /* disk block number */
|
||||
short vm_flg; /* flags */
|
||||
char vm_mem[1<<BLKLOG]; /* disk block data storage */
|
||||
};
|
||||
struct xref { /* cross reference entry */
|
||||
vmadr xr_lnk; /* circular link to next entry */
|
||||
int xr_pl; /* page and line number */
|
||||
};
|
||||
/*
|
||||
* Global variable declarations.
|
||||
*/
|
||||
char argchr; /* macro argument designator character */
|
||||
struct aside *ashead; /* symbol lookaside lru chain head */
|
||||
struct aside aspool[]; /* pool of symbol lookaside entries */
|
||||
int ch; /* current character from scanc */
|
||||
struct chent chtab[]; /* single-character token table */
|
||||
uns condlev; /* nesting level of conditionals */
|
||||
char condlst; /* flag enabling listing of skipped code */
|
||||
uns curaln; /* alignment for current section */
|
||||
uns curatr; /* attributes for current section */
|
||||
struct octab *curdef; /* current macro being defined */
|
||||
uns curext; /* extent for current section */
|
||||
exprval curloc; /* current location counter value */
|
||||
uns curlst; /* current listing level */
|
||||
struct operand curop; /* current operand information */
|
||||
uns cursec; /* current section number */
|
||||
int curxpl; /* current xref page and line */
|
||||
char datstr[]; /* string containing date and time */
|
||||
uns deflev; /* macro definition nesting level */
|
||||
char eflg; /* expression error flag */
|
||||
extern char oflag; /* Flag to Make Labled output file */
|
||||
extern char segflg; /* Flag to Make Segmented output file */
|
||||
uns errct; /* error count */
|
||||
char escchr; /* escape character */
|
||||
int extoff; /* offset of source extension in program name */
|
||||
struct psframe iilexeme; /* info returned from lexical scanner */
|
||||
int iilset; /* alternate left parts set */
|
||||
int iilsym; /* new left part symbol */
|
||||
struct psframe iips[]; /* parsing stack */
|
||||
struct psframe *iipsp; /* parsing stack pointer */
|
||||
struct psframe *iipspl; /* parsing left end pointer */
|
||||
struct input *infp; /* input frame pointer */
|
||||
char *insp; /* input stack pointer */
|
||||
int instk[]; /* input stack */
|
||||
vmadr label; /* sytab pointer for statement label */
|
||||
char labstr[]; /* label string */
|
||||
char lbrchr; /* left brace character for macro args */
|
||||
char lflag; /* flag set if listing being generated */
|
||||
uns linect; /* number of lines left on listing page */
|
||||
char llerr[]; /* error field of listing line */
|
||||
char *llert; /* top of error field */
|
||||
char llfull; /* flag indicating something to list */
|
||||
char llloc[]; /* location field in listing line */
|
||||
char llobj[]; /* object field in listing line */
|
||||
char *llobt; /* top of object field */
|
||||
char llseq[]; /* sequence field in listing line */
|
||||
char llsrc[]; /* source field in listing line */
|
||||
char mctchr; /* macro expansion count character */
|
||||
uns mexct; /* count of macro expansions */
|
||||
uns minaln; /* minimum section alignment value */
|
||||
int ntdflt[]; /* nonterminal default action table */
|
||||
exprval nxtloc; /* next location for text output */
|
||||
uns nxtsec; /* next section for text output */
|
||||
char objbuf[]; /* object block construction area */
|
||||
char *objtop; /* top of text info in objbuf */
|
||||
char objtyp; /* object block type being built */
|
||||
struct octab *ochtab[]; /* opcode hash table */
|
||||
struct octab *opcode; /* octab pointer for statement opcode */
|
||||
char opcstr[]; /* opcode string */
|
||||
struct operand optab[]; /* instruction operands description */
|
||||
uns pagect; /* listing page number */
|
||||
char parsing; /* flag indicating we are parsing */
|
||||
char pass2; /* flag indicating we are in pass 2 */
|
||||
char pflag; /* flag indicating local predef file */
|
||||
char *phylim; /* first unallocated memory location */
|
||||
char *phytop; /* first unused memory location */
|
||||
int prevsem; /* most recent semantic routine number */
|
||||
char *prname; /* name of this assembler */
|
||||
int ptab[]; /* parsing action table */
|
||||
char rbrchr; /* right brace character for macro args */
|
||||
char reading; /* flag indicating we are reading input */
|
||||
char *relbot; /* bottom of relocation info in objbuf */
|
||||
uns rmarg; /* listing right margin column */
|
||||
char rptct; /* repeat count for current repeat def */
|
||||
uns rptlev; /* repeat definition nesting level */
|
||||
vmadr rptstr; /* start of repeat definition in vm */
|
||||
int savlen; /* length of string in savstr */
|
||||
char savstr[]; /* first string of string comparison */
|
||||
char *scanpt; /* pointer to next character in sline */
|
||||
char scntab[]; /* symbol scanning table */
|
||||
uns secct; /* number of sections defined */
|
||||
struct section sectab[]; /* section table */
|
||||
int semtab[]; /* semantic action table */
|
||||
char sline[]; /* buffer holding current source line */
|
||||
char *srcfile; /* source file name pointer */
|
||||
vmadr syhtab[]; /* symbol hash table */
|
||||
char titl1[]; /* first title line */
|
||||
char titl2[]; /* second title line */
|
||||
char tokstr[]; /* string from token scanner */
|
||||
int toktyp; /* token type from token scanner */
|
||||
exprval tokval; /* value from token scanner */
|
||||
uns truelev; /* true conditional nesting level */
|
||||
char uext; /* flag turning undef. syms into externals */
|
||||
char uflg; /* undefined symbol in expression flag */
|
||||
vmadr virtop; /* first unused vm location */
|
||||
int vmfd; /* virtual memory file descriptor */
|
||||
struct vmbuf *vmhead; /* head of vm lru chain */
|
||||
struct vmbuf vmpool[]; /* pool of virtual memory buffers */
|
||||
uns warnct; /* warning count */
|
||||
char xflag; /* flag enabling cross referencing */
|
||||
|
||||
#ifdef STATS
|
||||
uns ashct; /* number of symbol lookaside hits */
|
||||
uns chnct; /* total sytab links followed */
|
||||
char stats; /* flag enabling statistics */
|
||||
uns sylct; /* number of calls to sylook */
|
||||
uns symct; /* number of symbols */
|
||||
uns vmgct; /* number of vm accesses */
|
||||
uns vmrct; /* number of vm disk reads */
|
||||
uns vmwct; /* number of vm disk writes */
|
||||
#endif
|
||||
/*
|
||||
* Function declarations.
|
||||
*/
|
||||
struct sytab *assign();
|
||||
uns hash();
|
||||
struct octab *oclook();
|
||||
struct input *pushin();
|
||||
char *rfetch();
|
||||
char *rindex();
|
||||
vmadr sylook();
|
||||
vmadr symerge();
|
||||
vmadr valloc();
|
||||
char *wfetch();
|
||||
@@ -0,0 +1,327 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
#include "obj.h"
|
||||
|
||||
/*
|
||||
* Version 3.4, 8/27/82. Changed this routine to dircom, and moved
|
||||
* direc to the as*.c files.
|
||||
*
|
||||
* Version 3.3, 6/9/82. Fixed .REPEAT bug.
|
||||
*
|
||||
* Version 3.2, 5/22/82. Fixed listing control.
|
||||
*/
|
||||
static char ident[] = "@(#)a.direc.c 3.4";
|
||||
|
||||
/*
|
||||
* dircom - Performs the assembler directives common to all versions.
|
||||
*/
|
||||
dircom(dirnum) int dirnum; {
|
||||
|
||||
reg struct sytab *syp;
|
||||
vmadr sym;
|
||||
exprval l;
|
||||
int i;
|
||||
char cond;
|
||||
char *sp;
|
||||
char llsave;
|
||||
|
||||
switch(dirnum) {
|
||||
|
||||
case ADABS: /* .abs */
|
||||
setsec(0);
|
||||
assign(STLAB,curloc,cursec);
|
||||
break;
|
||||
|
||||
case ADALIGN: /* .align */
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
expression();
|
||||
if(curop.op_rel==RBABS && 0L<=curop.op_val &&
|
||||
curop.op_val<=32L) {
|
||||
i = (int)curop.op_val;
|
||||
if(i > curaln) curaln = i;
|
||||
l = -1L<<i;
|
||||
curloc = curloc-l-1&l;
|
||||
if(pass2) setorg();
|
||||
} else err('E');
|
||||
assign(STLAB,curloc,cursec);
|
||||
break;
|
||||
|
||||
case ADBLOCK: /* .block */
|
||||
assign(STLAB,curloc,cursec);
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
expression();
|
||||
if(curop.op_rel == RBABS) {
|
||||
curloc += curop.op_val;
|
||||
if(pass2) setorg();
|
||||
} else err('E');
|
||||
break;
|
||||
|
||||
case ADBYTE: /* .byte */
|
||||
assign(STLAB,curloc,cursec);
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
while(toktyp != TKEOL) {
|
||||
if(toktyp == TKSTR) {
|
||||
sp = tokstr; i = tokval;
|
||||
while(i-- > 0) emitb(*sp++,0);
|
||||
iilex();
|
||||
} else {
|
||||
expression();
|
||||
emitb((uns)curop.op_val,RAA8|curop.op_rel);
|
||||
}
|
||||
delim();
|
||||
}
|
||||
break;
|
||||
|
||||
case ADCLIST: /* .clist */
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
expression();
|
||||
if(curop.op_rel) err('E');
|
||||
else condlst = curop.op_val!=0;
|
||||
break;
|
||||
|
||||
case ADCOM: /* .common */
|
||||
if(label) {
|
||||
syp = (struct sytab *)rfetch(label);
|
||||
if(syp->sy_typ==STSEC &&
|
||||
(!pass2||syp->sy_atr&SADP2)) { /* old section */
|
||||
setsec(syp->sy_rel);
|
||||
} else { /* start a new common section */
|
||||
newsec();
|
||||
}
|
||||
curatr |= SECOM;
|
||||
} else err('L');
|
||||
break;
|
||||
|
||||
case ADEJECT: /* .eject */
|
||||
llfull = linect = 0;
|
||||
break;
|
||||
|
||||
case ADELSE: /* .else */
|
||||
if(truelev) truelev--;
|
||||
else err('C');
|
||||
break;
|
||||
|
||||
case ADEND: /* .end */
|
||||
if(toktyp == TKSPC) { /* read transfer address */
|
||||
iilex();
|
||||
expression();
|
||||
if(pass2) { /* output transfer address */
|
||||
oflush(); objtyp = OBTRA;
|
||||
oputl((long)curop.op_val);
|
||||
oputw(curop.op_rel);
|
||||
}
|
||||
}
|
||||
reading = 0;
|
||||
break;
|
||||
|
||||
case ADENDIF: /* .endif */
|
||||
if(condlev) {
|
||||
condlev--; truelev--;
|
||||
} else err('C');
|
||||
break;
|
||||
|
||||
case ADEQU: /* .equ */
|
||||
equ(STLAB);
|
||||
break;
|
||||
|
||||
case ADERROR: /* .error */
|
||||
if(toktyp!=TKSPC || token()!=TKSTR) goto synerr;
|
||||
sp = tokstr;
|
||||
while(*sp != '\0') err(*sp++);
|
||||
token();
|
||||
break;
|
||||
|
||||
case ADEXIT: /* .exit */
|
||||
if(infp && (infp->in_typ==INMAC||infp->in_typ==INRPT)) popin();
|
||||
else err('O');
|
||||
break;
|
||||
|
||||
case ADGLOB: /* .global */
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
token();
|
||||
while(toktyp == TKSYM) {
|
||||
syp = (struct sytab *)wfetch(sym = sylook(tokstr));
|
||||
syp->sy_atr |= SAGLO;
|
||||
xref(sym,0);
|
||||
token();
|
||||
delim();
|
||||
}
|
||||
break;
|
||||
|
||||
case ADIF: /* .if */
|
||||
condlev++;
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
expression();
|
||||
if(curop.op_rel) {
|
||||
cond = 0; err('E');
|
||||
} else cond = curop.op_val!=0;
|
||||
if(cond) truelev++;
|
||||
break;
|
||||
|
||||
case ADINPUT: /* .input */
|
||||
if(toktyp!=TKSPC || token()!=TKSTR) goto synerr;
|
||||
if(include(tokstr) == -1) err('E');
|
||||
token();
|
||||
break;
|
||||
|
||||
case ADLIST: /* .list */
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
expression();
|
||||
if(curop.op_rel) err('E');
|
||||
else {
|
||||
if(0<=curop.op_val&&curop.op_val<=255) i = curop.op_val;
|
||||
else i = 255;
|
||||
if((curlst = infp->in_lst&0377) != 0) curlst--;
|
||||
if(i < curlst) curlst = i;
|
||||
}
|
||||
/*
|
||||
* We list the .list directive itself only if listing was
|
||||
* on before and is still on now.
|
||||
*/
|
||||
if(!curlst)
|
||||
llfull = 0;
|
||||
break;
|
||||
|
||||
case ADLONG: /* .long */
|
||||
assign(STLAB,curloc,cursec);
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
while(toktyp != TKEOL) {
|
||||
expression();
|
||||
emitl((long)curop.op_val,RAA32|curop.op_rel);
|
||||
delim();
|
||||
}
|
||||
break;
|
||||
|
||||
case ADMAC: /* .macro */
|
||||
if(*labstr) {
|
||||
curdef = oclook(labstr);
|
||||
curdef->oc_typ = OTMAC;
|
||||
curdef->oc_arg = 0;
|
||||
curdef->oc_val = virtop;
|
||||
deflev++;
|
||||
} else err('L');
|
||||
break;
|
||||
|
||||
case ADORG: /* .org */
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
expression();
|
||||
if(curop.op_rel == cursec) {
|
||||
curloc = curop.op_val;
|
||||
assign(STLAB,curop.op_val,curop.op_rel);
|
||||
if(pass2) setorg();
|
||||
} else err('E');
|
||||
break;
|
||||
|
||||
case ADREPT: /* .repeat */
|
||||
rptlev++;
|
||||
rptstr = virtop; /* Set now in case of syntax error */
|
||||
rptct = 1;
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
expression();
|
||||
/*
|
||||
* The expression may have generated some new xref entries,
|
||||
* changing virtop. So we set rptstr again to be sure it is
|
||||
* correct.
|
||||
*/
|
||||
rptstr = virtop;
|
||||
if(curop.op_rel!=RBABS || curop.op_val>255L) err('E');
|
||||
else rptct = curop.op_val>=0?curop.op_val:0;
|
||||
break;
|
||||
|
||||
case ADSECT: /* .sect */
|
||||
if(label) {
|
||||
syp = (struct sytab *)rfetch(label);
|
||||
if(syp->sy_typ==STSEC &&
|
||||
(!pass2||syp->sy_atr&SADP2)) { /* old section */
|
||||
setsec(syp->sy_rel);
|
||||
} else { /* start a new section */
|
||||
newsec();
|
||||
}
|
||||
} else err('L');
|
||||
break;
|
||||
|
||||
case ADSET: /* .set */
|
||||
equ(STVAR);
|
||||
break;
|
||||
|
||||
case ADSPACE: /* .space */
|
||||
llsave = llfull; /* save list/nolist flag */
|
||||
llfull = 0; /* suppress listing of source line */
|
||||
if(toktyp != TKSPC) i = 1;
|
||||
else {
|
||||
iilex();
|
||||
expression();
|
||||
if(curop.op_rel != RBABS) err('E');
|
||||
i = (int) curop.op_val;
|
||||
}
|
||||
if(i >= linect) linect = 0; /* eject page */
|
||||
else if(i > 0) { /* space down specified number of lines */
|
||||
putline(); /* get rid of source line */
|
||||
llfull = llsave; /* reset list/nolist flag */
|
||||
while(--i > 0) /* note last line put automatically */
|
||||
putline();
|
||||
}
|
||||
break;
|
||||
|
||||
case ADSTITL: /* .stitle */
|
||||
title(titl2);
|
||||
break;
|
||||
|
||||
case ADTITLE: /* .title */
|
||||
title(titl1);
|
||||
break;
|
||||
|
||||
case ADWARN: /* .warn */
|
||||
if(toktyp!=TKSPC || token()!=TKSTR) goto synerr;
|
||||
sp = tokstr;
|
||||
while(*sp != '\0') warn(*sp++);
|
||||
token();
|
||||
break;
|
||||
|
||||
case ADWITHN: /* .within */
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
expression();
|
||||
if(curop.op_rel==RBABS && 0L<=curop.op_val &&
|
||||
curop.op_val<=32L) {
|
||||
i = (int)curop.op_val;
|
||||
if(i < curext) curext = i;
|
||||
} else err('E');
|
||||
assign(STLAB,curloc,cursec);
|
||||
break;
|
||||
|
||||
case ADWORD: /* .word */
|
||||
assign(STLAB,curloc,cursec);
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
while(toktyp != TKEOL) {
|
||||
expression();
|
||||
emitw((uns)curop.op_val,RAA16|curop.op_rel);
|
||||
delim();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
err('O'); skipeol();
|
||||
break;
|
||||
|
||||
}
|
||||
return;
|
||||
|
||||
synerr:
|
||||
err('S'); skipeol();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
|
||||
#define NOBSS
|
||||
|
||||
/*
|
||||
* Version 3.3, 9/19/82. Added conditional compilation on NOBSS to
|
||||
* avoid explicit initialization (and bulky load modules) where possible.
|
||||
*
|
||||
* Version 3.2, 5/27/82. Added uext switch.
|
||||
*/
|
||||
static char ident[] = "@(#)a.glocom.c 3.3";
|
||||
|
||||
/*
|
||||
* Global variable definitions and initializations common to all of the
|
||||
* cross assemblers.
|
||||
*/
|
||||
char argchr = '?';
|
||||
struct aside *ashead = &aspool[0];
|
||||
struct aside aspool[] = {
|
||||
{ &aspool[1] },
|
||||
{ &aspool[2] },
|
||||
{ &aspool[3] },
|
||||
{ &aspool[4] },
|
||||
{ &aspool[5] },
|
||||
{ &aspool[6] },
|
||||
{ &aspool[7] },
|
||||
{ &aspool[8] },
|
||||
{ &aspool[9] },
|
||||
{ &aspool[10] },
|
||||
{ &aspool[11] },
|
||||
{ &aspool[12] },
|
||||
{ &aspool[13] },
|
||||
{ &aspool[14] },
|
||||
{ &aspool[15] },
|
||||
{ &aspool[16] },
|
||||
{ &aspool[17] },
|
||||
{ &aspool[18] },
|
||||
{ &aspool[19] },
|
||||
{ &aspool[20] },
|
||||
{ &aspool[21] },
|
||||
{ &aspool[22] },
|
||||
{ &aspool[23] },
|
||||
{ &aspool[24] },
|
||||
{ &aspool[25] },
|
||||
{ &aspool[26] },
|
||||
{ &aspool[27] },
|
||||
{ &aspool[28] },
|
||||
{ &aspool[29] },
|
||||
{ 0 }
|
||||
};
|
||||
char condlst = 1;
|
||||
uns curext = 32;
|
||||
uns curlst = 255;
|
||||
struct output errout = { &errout.ou_buf[0], 0, 1 };
|
||||
char escchr = '\\';
|
||||
struct psframe *iipsp = &iips[0];
|
||||
struct psframe *iipspl = &iips[0];
|
||||
char *insp = instk;
|
||||
char lbrchr = '{';
|
||||
char *llert = &llerr[0];
|
||||
char *llobt = &llobj[0];
|
||||
struct output lstout = { &lstout.ou_buf[0], 0, -1 };
|
||||
char mctchr = '#';
|
||||
/* ntdflt is initialized in as*gram.c */
|
||||
struct output objout = { &objout.ou_buf[0], 0, -1 };
|
||||
char *objtop = &objbuf[0];
|
||||
char *phylim;
|
||||
char *phytop;
|
||||
/* ptab is initialized in as*gram.c */
|
||||
char rbrchr = '}';
|
||||
char reading = 1;
|
||||
char *relbot = &objbuf[OBJSIZ];
|
||||
uns rmarg = 80;
|
||||
char *scanpt = &sline[0];
|
||||
/* scntab is initialized in as*gram.c */
|
||||
uns secct = 1;
|
||||
/* semtab is initialized in as*gram.c */
|
||||
vmadr virtop = 2;
|
||||
struct vmbuf *vmhead = &vmpool[0];
|
||||
struct vmbuf vmpool[] = {
|
||||
{ &vmpool[1], -1 },
|
||||
{ &vmpool[2], -1 },
|
||||
{ &vmpool[3], -1 },
|
||||
{ &vmpool[4], -1 },
|
||||
{ &vmpool[5], -1 },
|
||||
{ &vmpool[6], -1 },
|
||||
{ &vmpool[7], -1 },
|
||||
{ &vmpool[8], -1 },
|
||||
{ &vmpool[9], -1 },
|
||||
{ &vmpool[10], -1 },
|
||||
{ &vmpool[11], -1 },
|
||||
{ 0, -1}
|
||||
};
|
||||
|
||||
/*
|
||||
* The following variables all have initial values of zero. We need
|
||||
* not explicitly initialize them if the loader we use has a BSS segment.
|
||||
*/
|
||||
#ifdef NOBSS
|
||||
|
||||
int ch = 0;
|
||||
uns condlev = 0;
|
||||
uns curaln = 0;
|
||||
uns curatr = 0;
|
||||
struct octab *curdef = 0;
|
||||
exprval curloc = 0;
|
||||
struct operand curop = { 0 };
|
||||
uns cursec = 0;
|
||||
int curxpl = 0;
|
||||
char datstr[26] = 0;
|
||||
uns deflev = 0;
|
||||
char eflg = 0;
|
||||
uns errct = 0;
|
||||
struct psframe iilexeme = { 0 };
|
||||
int iilset = 0;
|
||||
int iilsym = 0;
|
||||
struct psframe iips[IISIZ] = 0;
|
||||
struct input *infp = 0;
|
||||
int instk[INSIZ] = 0;
|
||||
vmadr label = 0;
|
||||
char labstr[SYMSIZ+1] = 0;
|
||||
char lflag = 0;
|
||||
uns linect = 0;
|
||||
char llerr[LLERR+1] = 0;
|
||||
char llfull = 0;
|
||||
char llloc[LLLOC+1] = 0;
|
||||
char llobj[LLOBJ+1] = 0;
|
||||
char llseq[LLSEQ+1] = 0;
|
||||
char llsrc[SLINSIZ+2] = 0;
|
||||
uns mexct = 0;
|
||||
exprval nxtloc = 0;
|
||||
uns nxtsec = 0;
|
||||
char objbuf[OBJSIZ] = 0;
|
||||
char objtyp = 0;
|
||||
struct octab *ochtab[1<<OHSHLOG] = 0;
|
||||
struct octab *opcode = 0;
|
||||
char opcstr[SYMSIZ+1] = 0;
|
||||
uns pagect = 0;
|
||||
char parsing = 0;
|
||||
char pass2 = 0;
|
||||
char pflag = 0;
|
||||
int prevsem = 0;
|
||||
char *prname = 0;
|
||||
char rptct = 0;
|
||||
uns rptlev = 0;
|
||||
vmadr rptstr = 0;
|
||||
int savlen = 0;
|
||||
char savstr[STRSIZ+1] = 0;
|
||||
struct section sectab[SECSIZ] = 0;
|
||||
char sline[SLINSIZ+2] = 0;
|
||||
char *srcfile = 0;
|
||||
vmadr syhtab[1<<SHSHLOG] = 0;
|
||||
char titl1[TITSIZ+1] = 0;
|
||||
char titl2[TITSIZ+1] = 0;
|
||||
char tokstr[STRSIZ+1] = 0;
|
||||
int toktyp = 0;
|
||||
exprval tokval = 0;
|
||||
uns truelev = 0;
|
||||
char uext = 0;
|
||||
char uflg = 0;
|
||||
int vmfd = 0;
|
||||
uns warnct = 0;
|
||||
char xflag = 0;
|
||||
|
||||
#ifdef STATS
|
||||
uns ashct = 0;
|
||||
uns chnct = 0;
|
||||
char stats = 0;
|
||||
uns sylct = 0;
|
||||
uns symct = 0;
|
||||
uns vmgct = 0;
|
||||
uns vmrct = 0;
|
||||
uns vmwct = 0;
|
||||
#endif STATS
|
||||
|
||||
#endif NOBSS
|
||||
@@ -0,0 +1,164 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
|
||||
/*
|
||||
* Version Z.1, 4/5/83. Added external declarations of segflg and oflag.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Version 3.2, 5/27/82. Added uext (-u) switch.
|
||||
*/
|
||||
static char ident[] = "@(#)a.init.c 3.2";
|
||||
|
||||
extern char segflg;
|
||||
extern char oflag;
|
||||
|
||||
/*
|
||||
* badpre - Issues a fatal error for a bad PREDEF file.
|
||||
*/
|
||||
badpre() {
|
||||
|
||||
fprintf(ERROR,"PREDEF file error at line %u\n",infp->in_seq);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* getdat - Gets the date and time and puts them into datstr.
|
||||
* Disabled in CP/M version.
|
||||
*/
|
||||
getdat() {
|
||||
}
|
||||
#define BinFile 1
|
||||
#define AscFile 0
|
||||
|
||||
extern char putfile[];
|
||||
extern char optfile[];
|
||||
/*
|
||||
* init - Performs assembler initialization.
|
||||
*/
|
||||
init(argc,argv) int argc; char *argv[]; {
|
||||
|
||||
char **av;
|
||||
char *ap;
|
||||
char *ep;
|
||||
char *sp;
|
||||
char fname[15];
|
||||
int fd;
|
||||
FILE *newfile();
|
||||
|
||||
phytop = phylim = sbrk(0); /* needed only for monitoring */
|
||||
getdat();
|
||||
prname = "asz8k";
|
||||
while((ap = *++argv) && ap!=-1) { /* read command line arguments */
|
||||
if(*ap == '-') { /* switches */
|
||||
while(*++ap) switch(*ap) {
|
||||
|
||||
case 'l':
|
||||
lflag = 1;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
oflag = 1;
|
||||
if ((**argv == '\0') || (*argv == NULL))
|
||||
{printf("called from case 'o'\n");
|
||||
usage();}
|
||||
strcpy(optfile,*++argv);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
segflg = 1;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
uext = 1;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
xflag = lflag = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("error case\n");
|
||||
usage();
|
||||
|
||||
}
|
||||
} else { /* file name */
|
||||
if(srcfile) {printf("srcfile != 0\n"); usage();}
|
||||
srcfile = ap;
|
||||
}
|
||||
}
|
||||
if(!srcfile) {printf("no srcfile\n"); usage();}
|
||||
if((sp = rindex(srcfile,'/')) == 0) sp = srcfile; else sp++;
|
||||
if(strlen(sp) > 14) sp[14] = '\0';
|
||||
strcpy(titl1,srcfile);
|
||||
strcpy(fname,sp);
|
||||
if((ep = rindex(fname,'.')) == 0)
|
||||
usage();
|
||||
else
|
||||
ep++;
|
||||
if( segflg ) { /* Prog name must end with "8ks". */
|
||||
if( strcmp (ep,"8ks") != 0) {
|
||||
printf("Segmented source file must end with '.8ks'\n");
|
||||
usage();
|
||||
}
|
||||
}
|
||||
else /* Prog name must end in "8kn". */
|
||||
if( strcmp (ep,"8kn") != 0) {
|
||||
printf("Nonsegmented source file must end with '.8kn'\n");
|
||||
usage();
|
||||
}
|
||||
if((fd = opena(srcfile,0)) == -1) {
|
||||
fprintf(ERROR,"Cannot open %s\n",srcfile);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(ep,"obj"); OBJECT = newfile(fname,BinFile);
|
||||
strcpy(putfile,fname);
|
||||
if(lflag) {
|
||||
strcpy(ep,"lst"); LIST = newfile(fname,AscFile);
|
||||
}
|
||||
vinit();
|
||||
predef();
|
||||
}
|
||||
|
||||
/*
|
||||
* newfile - Creates a new file of the specified name,
|
||||
* and returns the file descriptor.
|
||||
*/
|
||||
FILE *
|
||||
newfile(s,asci) char *s; char asci; {
|
||||
|
||||
FILE *fd;
|
||||
|
||||
if((fd = _fopen(s,"w",asci)) == NULL) {
|
||||
fprintf(ERROR,"Cannot create %s\n",s);
|
||||
exit(1);
|
||||
}
|
||||
return(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* preget - Gets a token, issues a fatal error if it is not the specified
|
||||
* type, and returns the token's value.
|
||||
*/
|
||||
preget(typ) int typ; {
|
||||
|
||||
if(token() != typ) badpre();
|
||||
return(tokval);
|
||||
}
|
||||
|
||||
/*
|
||||
* usage - Issues a fatal error for an illegal command line.
|
||||
*/
|
||||
usage() {
|
||||
|
||||
fprintf(ERROR,"Usage: asz8k [-o outfile] [-luxs] file.8k{n|s}\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
|
||||
/*
|
||||
* Version 3.2, 7/5/82. Performance enhancements.
|
||||
*/
|
||||
|
||||
static char ident[] = "@(#)a.input.c 3.2";
|
||||
|
||||
/*
|
||||
* fillin - Processes the end of an input stack frame.
|
||||
*/
|
||||
fillin() {
|
||||
|
||||
reg struct input *rinfp;
|
||||
|
||||
switch((rinfp = infp)->in_typ) {
|
||||
|
||||
case INFILE:
|
||||
rinfp->in_ptr = rinfp->in_buf;
|
||||
rinfp->in_cnt = read(rinfp->in_fd,rinfp->in_buf,
|
||||
1<<BLKLOG);
|
||||
if(rinfp->in_cnt == 0) {
|
||||
close(rinfp->in_fd);
|
||||
popin();
|
||||
}
|
||||
return;
|
||||
|
||||
case INARG:
|
||||
case INMAC:
|
||||
popin();
|
||||
return;
|
||||
|
||||
case INRPT:
|
||||
if(rinfp->in_rpt-- != 0) {
|
||||
rinfp->in_cnt = rinfp->in_ptr-rinfp->in_buf;
|
||||
rinfp->in_ptr = rinfp->in_buf;
|
||||
rinfp->in_seq = 0;
|
||||
} else popin();
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* include - Pushes the specified file into the input stream. Returns -1
|
||||
* if the file cannot be opened, 0 otherwise.
|
||||
*/
|
||||
include(file) char *file; {
|
||||
|
||||
int fd;
|
||||
|
||||
if((fd = opena(file,0)) == -1) return(-1);
|
||||
infp = pushin();
|
||||
insp += 1<<BLKLOG; iovck();
|
||||
infp->in_typ = INFILE;
|
||||
infp->in_fd = fd;
|
||||
if((curlst = infp->in_lst&0377) != 0) curlst--;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* iovck - Checks to make sure the input stack pointer is not beyond the
|
||||
* end of the input stack area.
|
||||
*/
|
||||
iovck() {
|
||||
|
||||
if(insp > instk+INSIZ) {
|
||||
fprintf(ERROR,"Input stack overflow\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* macarg - Pushes a macro argument frame on the input stack. The parameter
|
||||
* is the argument designator.
|
||||
*/
|
||||
macarg(argno) int argno; {
|
||||
|
||||
reg struct input *rinfp;
|
||||
char *ap;
|
||||
char **avp;
|
||||
|
||||
avp = infp->in_buf;
|
||||
ap = avp[argno&0177];
|
||||
rinfp = infp = pushin();
|
||||
rinfp->in_typ = INARG;
|
||||
rinfp->in_ptr = ap;
|
||||
rinfp->in_cnt = strlen(ap);
|
||||
if((curlst = rinfp->in_lst&0377) != 0) curlst--;
|
||||
}
|
||||
|
||||
/*
|
||||
* popin - Pops the top frame off the input stack.
|
||||
*/
|
||||
popin() {
|
||||
|
||||
curlst = infp->in_lst&0377; insp = infp; infp = infp->in_ofp;
|
||||
}
|
||||
|
||||
/*
|
||||
* pushc - Pushes the specified character onto the input stack.
|
||||
*/
|
||||
pushc(c) char c; {
|
||||
|
||||
char *oldsp;
|
||||
|
||||
oldsp = insp++; iovck();
|
||||
*oldsp = c;
|
||||
}
|
||||
|
||||
/*
|
||||
* pushin - Pushes a new frame onto the input stack. The buffer area in_buf
|
||||
* is not allocated, since it is of variable size. The value returned is
|
||||
* the new frame pointer. Note that the global frame pointer infp is
|
||||
* not automatically adjusted.
|
||||
*/
|
||||
struct input *
|
||||
pushin() {
|
||||
|
||||
struct input *newfp;
|
||||
|
||||
if((int)insp&01) insp++; /* force integer alignment */
|
||||
newfp = insp;
|
||||
insp = &newfp->in_buf[0]; iovck();
|
||||
newfp->in_ofp = infp;
|
||||
newfp->in_seq = newfp->in_cnt = 0;
|
||||
newfp->in_lst = curlst;
|
||||
return(newfp);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
|
||||
/*
|
||||
* Version 3.2, 8/19/82. Added initialization of the sy_val field
|
||||
* when adding a new symbol to the symbol table. It sometimes
|
||||
* came up nonzero, giving undefined externals nonzero values in
|
||||
* the object output.
|
||||
*/
|
||||
static char ident[] = "@(#)a.look.c 3.2";
|
||||
|
||||
/*
|
||||
* oclook - Returns a pointer to the operation table entry for the
|
||||
* specified opcode symbol. Creates a new entry in the operation
|
||||
* table if necessary.
|
||||
*/
|
||||
struct octab *
|
||||
oclook(s) char *s; {
|
||||
|
||||
struct octab *p, *q, *r;
|
||||
uns h;
|
||||
int cmp;
|
||||
|
||||
h = hash(s)>>(16-OHSHLOG)&(1<<OHSHLOG)-1;
|
||||
p = 0;
|
||||
q = ochtab[h];
|
||||
while(q && (cmp=symcmp(s,q->oc_str))>0) { /* follow hash chain */
|
||||
p = q;
|
||||
q = q->oc_lnk;
|
||||
}
|
||||
if(q && cmp==0) return(q); /* found */
|
||||
/*
|
||||
* Add a new entry to the table.
|
||||
*/
|
||||
if((uns)phytop&01) phytop++; /* force integer alignment */
|
||||
r = (struct octab *)palloc(sizeof(struct octab));
|
||||
symcpy(r->oc_str,s);
|
||||
r->oc_typ = 0;
|
||||
r->oc_lnk = q;
|
||||
if(p) p->oc_lnk = r; else ochtab[h] = r;
|
||||
return(r);
|
||||
}
|
||||
|
||||
/*
|
||||
* hash - Given a string, computes a partial hashing function of the string,
|
||||
* and returns its value.
|
||||
*/
|
||||
uns
|
||||
hash(s) char *s; {
|
||||
|
||||
uns h;
|
||||
|
||||
h = 0;
|
||||
while(*s) h = (h<<1)+*s++;
|
||||
return(h*40143);
|
||||
}
|
||||
|
||||
/*
|
||||
* sylook - Returns a virtual memory pointer to the symbol table entry
|
||||
* for the specified symbol. Creates a new entry in the symbol table
|
||||
* if necessary.
|
||||
*/
|
||||
vmadr
|
||||
sylook(s) char *s; {
|
||||
|
||||
struct aside *apt, **lpt;
|
||||
vmadr p, q, r;
|
||||
struct sytab *qp, *rp;
|
||||
uns h;
|
||||
int cmp;
|
||||
|
||||
#ifdef STATS
|
||||
sylct++;
|
||||
#endif
|
||||
/*
|
||||
* Check the lookaside table to see if the symbol is in it.
|
||||
*/
|
||||
lpt = &ashead; apt = ashead;
|
||||
while((cmp = symcmp(apt->as_str,s)) && apt->as_lnk) {
|
||||
apt = *(lpt = &apt->as_lnk);
|
||||
}
|
||||
/*
|
||||
* Whether we found a hit or not, move the entry to the front of the
|
||||
* lru chain.
|
||||
*/
|
||||
*lpt = apt->as_lnk; apt->as_lnk = ashead; ashead = apt;
|
||||
if(cmp == 0) { /* hit */
|
||||
#ifdef STATS
|
||||
ashct++;
|
||||
#endif
|
||||
return(apt->as_sym);
|
||||
}
|
||||
/*
|
||||
* No luck in the lookaside table, so search the hash chains in
|
||||
* the customary manner.
|
||||
*/
|
||||
symcpy(ashead->as_str,s); /* update lookaside table */
|
||||
h = hash(s)>>(16-SHSHLOG)&(1<<SHSHLOG)-1;
|
||||
p = 0;
|
||||
q = syhtab[h];
|
||||
while(q && (cmp=symcmp(s,(qp=(struct sytab *)rfetch(q))->sy_str))>0) {
|
||||
p = q;
|
||||
q = qp->sy_lnk;
|
||||
#ifdef STATS
|
||||
chnct++;
|
||||
#endif
|
||||
}
|
||||
if(q && cmp==0) return(ashead->as_sym = q); /* found */
|
||||
/*
|
||||
* Add a new entry to the table.
|
||||
*/
|
||||
#ifdef STATS
|
||||
symct++;
|
||||
#endif
|
||||
if((uns)virtop&01) virtop++; /* force integer alignment */
|
||||
rp = (struct sytab *)wfetch(r=valloc(sizeof(struct sytab)));
|
||||
symcpy(rp->sy_str,s);
|
||||
rp->sy_typ = rp->sy_atr = rp->sy_xlk = rp->sy_val = 0;
|
||||
rp->sy_lnk = q;
|
||||
if(p) ((struct sytab *)wfetch(p))->sy_lnk = r; else syhtab[h] = r;
|
||||
return(ashead->as_sym = r);
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
|
||||
/*
|
||||
* Version 3.3, 7/5/82. Added hooks for profiling and performance
|
||||
* enhancements.
|
||||
*
|
||||
* Version 3.2, 5/22/82. Added exit routine to replace the standard one
|
||||
* in libc.a.
|
||||
*/
|
||||
static char ident[] = "@(#)a.misc.c 3.3";
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* ferr - Issues a fatal error message and terminates.
|
||||
* Used a variable number of parameters - replaced by in-line
|
||||
* calls to fprintf, followed everywhere by exit(1).
|
||||
* FZ 9/14/82
|
||||
*/
|
||||
/*
|
||||
*ferr(arglist) char *arglist; {
|
||||
*
|
||||
* fprintf(ERROR,"%r",&arglist);
|
||||
* exit(1);
|
||||
*}
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* getline - Reads the next line of source, and puts it into the global
|
||||
* array sline and into the listing buffer lline.
|
||||
*/
|
||||
getline() {
|
||||
|
||||
reg struct input *rinfp;
|
||||
reg int ch;
|
||||
reg char *slp;
|
||||
reg char *llp;
|
||||
|
||||
scanpt = slp = sline; llp = llsrc;
|
||||
for( ; ; ) {
|
||||
if((rinfp = infp) == 0) { /* end of file */
|
||||
sline[0] = -1;
|
||||
sline[1] = '\0';
|
||||
return;
|
||||
}
|
||||
if(rinfp->in_cnt-- <= 0) { /* end of input stack frame */
|
||||
fillin();
|
||||
continue;
|
||||
}
|
||||
if((ch = *rinfp->in_ptr++ & 0377) >= 0200 &&
|
||||
rinfp->in_typ == INMAC) { /* push macro argument frame */
|
||||
macarg(ch);
|
||||
continue;
|
||||
}
|
||||
ch &= 0177;
|
||||
if(ch == '\n') /* we have a line */
|
||||
break;
|
||||
if(ch == '\f') linect = 0; /* page eject */
|
||||
else if(slp < &sline[SLINSIZ]) *slp++ = *llp++ = ch;
|
||||
}
|
||||
*slp++ = *llp++ = '\n'; *slp = *llp = '\0';
|
||||
rinfp->in_seq++;
|
||||
if(rinfp == (struct input *)instk)
|
||||
sprintf(llseq," %4d",rinfp->in_seq);
|
||||
else sprintf(llseq,"+%4d",rinfp->in_seq);
|
||||
/*
|
||||
* Decide now whether listing of this line is enabled.
|
||||
*/
|
||||
llfull = curlst && (condlev<=truelev || condlst);
|
||||
curxpl = pagect<<6|LLPP-linect+1;
|
||||
if(linect == 0) curxpl += 64-LLPP; /* anticipate form feed */
|
||||
}
|
||||
|
||||
/*
|
||||
* palloc - Allocates a block of physical memory of the specified size,
|
||||
* and returns a pointer to the block.
|
||||
*/
|
||||
char *
|
||||
palloc(size) uns size; {
|
||||
|
||||
static char *oldtop;
|
||||
|
||||
oldtop = phytop; phytop += size;
|
||||
while(phytop > phylim) {
|
||||
if(sbrk(1024) == -1) {
|
||||
fprintf(ERROR,"Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
phylim += 1024;
|
||||
}
|
||||
return(oldtop);
|
||||
}
|
||||
|
||||
/*
|
||||
* pgcheck - Checks to see if a new listing page is needed, and starts one
|
||||
* if necessary. Then updates the line counter in anticipation of a line
|
||||
* of output.
|
||||
*/
|
||||
pgcheck() {
|
||||
|
||||
int i;
|
||||
|
||||
if(linect <= 0) { /* time for a new page */
|
||||
pagect++;
|
||||
fprintf(LIST,"\f\n\n%-8s%-48s%s\
|
||||
%-48s Page%4d\n\n",
|
||||
prname,titl1,datstr,titl2,pagect);
|
||||
linect = LLPP;
|
||||
}
|
||||
linect--;
|
||||
}
|
||||
|
||||
/*
|
||||
* putline - Outputs the next line of the assembly listing, provided
|
||||
* it is pass 2 and there is something to output.
|
||||
*/
|
||||
putline() {
|
||||
|
||||
static char lstfmt[] = "%-3s %-4s %-8s %-5s %s";
|
||||
|
||||
if(pass2) {
|
||||
if(*llerr) { /* put out an error listing line */
|
||||
fprintf(ERROR,lstfmt,llerr,llloc, llobj,llseq,llsrc);
|
||||
}
|
||||
if(lflag && (llfull||*llerr)) { /* put out assembly listing */
|
||||
pgcheck(); /* start a new page if necessary */
|
||||
if(*llerr == '\0') { /* put listing line number */
|
||||
sprintf(llerr," %2d",LLPP-linect);
|
||||
}
|
||||
fprintf(LIST,lstfmt,llerr,llloc,llobj,llseq,llsrc);
|
||||
}
|
||||
}
|
||||
llsrc[0] = '\n';
|
||||
*llerr = *llloc = *llobj = *llseq = llsrc[1] = '\0';
|
||||
llert = llerr; llobt = llobj;
|
||||
}
|
||||
|
||||
/*
|
||||
* symcmp - Compares two symbols, and returns a number which is:
|
||||
*
|
||||
* > 0, if a > b,
|
||||
* == 0, if a == b,
|
||||
* < 0, if a < b.
|
||||
*/
|
||||
symcmp(a,b) reg char *a, *b; {
|
||||
|
||||
reg int i;
|
||||
|
||||
i = SYMSIZ;
|
||||
while(--i>=0 && *a==*b++) {
|
||||
if(*a++ == '\0') return(0);
|
||||
}
|
||||
return(i<0 ? 0 : *a-*--b);
|
||||
}
|
||||
|
||||
/*
|
||||
* symcpy - Copies one symbol from source to destination.
|
||||
*/
|
||||
symcpy(d,s) reg char *d, *s; {
|
||||
|
||||
reg char i;
|
||||
|
||||
i = SYMSIZ;
|
||||
do {
|
||||
if((*d++ = *s++) == '\0') return;
|
||||
} while(--i > 0);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
|
||||
static char ident[] = "@(#)a.output.c 3.1";
|
||||
@@ -0,0 +1,310 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
#include "obj.h"
|
||||
|
||||
/*
|
||||
* Version 3.2, 8/20/82. Added the forward reference flag (OFFOR).
|
||||
*/
|
||||
static char ident[] = "@(#)a.parse.c 3.2";
|
||||
|
||||
/*
|
||||
* iiaction - Given the state and symbol on the top of the stack, returns the
|
||||
* next action, or -1 if a syntax error was detected.
|
||||
*/
|
||||
iiaction() {
|
||||
|
||||
reg int *pp; /* ptab pointer */
|
||||
reg char *scp; /* scntab pointer */
|
||||
reg int sym; /* lookahead symbol */
|
||||
|
||||
scp = scntab; pp = iipsp->ps_state; sym = iipsp->ps_sym&0377;
|
||||
if(iipsp->ps_sym&IINFLG) { /* scan for a nonterminal symbol */
|
||||
scp += *--pp-1;
|
||||
do {
|
||||
pp--; scp++;
|
||||
} while((*scp&0377)!=sym && (*scp&0377)!=IIDSYM);
|
||||
if((*scp&0377) == IIDSYM) pp = ntdflt+(unsigned)sym;
|
||||
} else { /* scan for a terminal symbol */
|
||||
scp += *pp++;
|
||||
while((*scp&0377)!=sym && (*scp&0377)!=IIDSYM) {
|
||||
if((*scp&0377) == IIESYM) return(-1);
|
||||
pp++; scp++;
|
||||
}
|
||||
}
|
||||
return(*pp);
|
||||
}
|
||||
|
||||
/*
|
||||
* iiparse - Attempts to parse the input stream, and returns 0 if successful.
|
||||
* Expects iilexeme to contain the first symbol of the input at call time.
|
||||
* Returns -1 on failure to recover from a syntax error, -2 on parse stack
|
||||
* overflow.
|
||||
*/
|
||||
iiparse() {
|
||||
|
||||
reg int act; /* next action to take */
|
||||
reg int *smp; /* pointer into semtab */
|
||||
int semnum; /* semantic number */
|
||||
|
||||
eflg = prevsem = uflg = 0;
|
||||
iipsp = &iips[IISIZ];
|
||||
act = ptab[0];
|
||||
parsing = 1;
|
||||
do {
|
||||
/*
|
||||
* Push the current state and lookahead symbol on the stack.
|
||||
*/
|
||||
if(--iipsp < iips) return(-2);
|
||||
iipsp->ps_state = ptab+(act&~IIXFLG);
|
||||
iipsp->ps_sym = iilexeme.ps_sym;
|
||||
iipsp->ps_val0 = iilexeme.ps_val0;
|
||||
iipsp->ps_val1 = iilexeme.ps_val1;
|
||||
/*
|
||||
* Scan the tables to determine the next action.
|
||||
*/
|
||||
if((act = iiaction()) == -1) return(-1);
|
||||
/*
|
||||
* Perform a transition or start a reduction loop, depending
|
||||
* upon the action just found.
|
||||
*/
|
||||
if(act&IIXFLG) { /* transition */
|
||||
iilex();
|
||||
} else { /* reduction */
|
||||
if(act&IIRFLG) { /* combined read and reduce */
|
||||
iilex();
|
||||
} else { /* simple reduction */
|
||||
iipsp++;
|
||||
}
|
||||
do { /* reduce loop */
|
||||
smp = semtab+(act&0377);
|
||||
iipspl = iipsp+(act>>8&IILMSK)-1;
|
||||
iilsym = *smp>>8&0377;
|
||||
iilset = (act&IIAFLG) ? *(smp+1) : 0100000;
|
||||
if((semnum = *smp&0377) != 0) {
|
||||
if(semnum >= 51) sem51(semnum);
|
||||
else sem01(semnum);
|
||||
prevsem = semnum;
|
||||
}
|
||||
iipsp = iipspl;
|
||||
iipsp->ps_sym = iilsym|IINFLG;
|
||||
act = iiaction();
|
||||
} while(!(act&IIXFLG));
|
||||
}
|
||||
} while(parsing);
|
||||
return(iilexeme.ps_sym==TKEOF?0:-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* sem01 - Common semantic routines.
|
||||
*/
|
||||
sem01(sem) int sem; {
|
||||
|
||||
reg struct psframe *p, *pl;
|
||||
struct sytab *syp;
|
||||
char *dp, *sp;
|
||||
int c, i, j;
|
||||
|
||||
p = iipsp; pl = iipspl;
|
||||
switch(sem) {
|
||||
|
||||
case 1: /* <s> ::= <operand> */
|
||||
parsing = 0;
|
||||
break;
|
||||
|
||||
case 2: /* <expr1> ::= addop <expr1> */
|
||||
if(pl->ps_val1 == TVADD) { /* unary plus */
|
||||
pl->ps_val0 = p->ps_val0;
|
||||
pl->ps_val1 = p->ps_val1;
|
||||
} else { /* unary minus */
|
||||
if(p->ps_val1) goto experr;
|
||||
pl->ps_val0 = -p->ps_val0;
|
||||
pl->ps_val1 = 0;
|
||||
}
|
||||
pl->ps_flg = p->ps_flg&OFFOR;
|
||||
break;
|
||||
|
||||
case 3: /* <expr1> ::= unop <expr1> */
|
||||
if(p->ps_val1) goto experr;
|
||||
pl->ps_val0 = ~p->ps_val0;
|
||||
pl->ps_val1 = 0;
|
||||
pl->ps_flg = p->ps_flg&OFFOR;
|
||||
break;
|
||||
|
||||
case 4: /* <expr6> ::= <expr6> xorop <expr5> */
|
||||
if(pl->ps_val1 || p->ps_val1) goto experr;
|
||||
pl->ps_val0 ^= p->ps_val0;
|
||||
pl->ps_flg |= p->ps_flg&OFFOR;
|
||||
break;
|
||||
|
||||
case 5: /* <expr2> ::= <expr2> mulop <expr1> */
|
||||
if(pl->ps_val1 || p->ps_val1) goto experr;
|
||||
switch(p[1].ps_val1) {
|
||||
case TVMUL:
|
||||
pl->ps_val0 *= p->ps_val0;
|
||||
break;
|
||||
case TVDIV:
|
||||
pl->ps_val0 /= p->ps_val0;
|
||||
break;
|
||||
case TVMOD:
|
||||
pl->ps_val0 %= p->ps_val0;
|
||||
break;
|
||||
case TVSHL:
|
||||
pl->ps_val0 <<= p->ps_val0;
|
||||
break;
|
||||
case TVSHR:
|
||||
pl->ps_val0 >>= p->ps_val0;
|
||||
break;
|
||||
}
|
||||
pl->ps_flg |= p->ps_flg&OFFOR;
|
||||
break;
|
||||
|
||||
case 6: /* <expr3> ::= <expr3> addop <expr2> */
|
||||
if(p[1].ps_val1 == TVADD) { /* addition */
|
||||
pl->ps_val0 += p->ps_val0;
|
||||
if(pl->ps_val1) {
|
||||
if(p->ps_val1) goto experr;
|
||||
} else pl->ps_val1 = p->ps_val1;
|
||||
} else { /* subtraction */
|
||||
pl->ps_val0 -= p->ps_val0;
|
||||
if(pl->ps_val1 == p->ps_val1)
|
||||
pl->ps_val1 = 0;
|
||||
else if(p->ps_val1) goto experr;
|
||||
}
|
||||
pl->ps_flg |= p->ps_flg&OFFOR;
|
||||
break;
|
||||
|
||||
case 7: /* <expr5> ::= <expr5> andop <expr4> */
|
||||
if(pl->ps_val1 || p->ps_val1) goto experr;
|
||||
pl->ps_val0 &= p->ps_val0;
|
||||
pl->ps_flg |= p->ps_flg&OFFOR;
|
||||
break;
|
||||
|
||||
case 8: /* <expr> ::= <expr> orop <expr6> */
|
||||
if(pl->ps_val1 || p->ps_val1) goto experr;
|
||||
pl->ps_val0 |= p->ps_val0;
|
||||
pl->ps_flg |= p->ps_flg&OFFOR;
|
||||
break;
|
||||
|
||||
case 9: /* <expr4> ::= <expr3> relop <expr3> */
|
||||
switch(p[1].ps_val1) {
|
||||
case TVEQ:
|
||||
pl->ps_val0 = pl->ps_val1==p->ps_val1 &&
|
||||
pl->ps_val0==p->ps_val0;
|
||||
break;
|
||||
case TVNE:
|
||||
pl->ps_val0 = pl->ps_val1!=p->ps_val1 ||
|
||||
pl->ps_val0!=p->ps_val0;
|
||||
break;
|
||||
case TVLT:
|
||||
if(pl->ps_val1 != p->ps_val1) goto experr;
|
||||
pl->ps_val0 = pl->ps_val0<p->ps_val0;
|
||||
break;
|
||||
case TVGT:
|
||||
if(pl->ps_val1 != p->ps_val1) goto experr;
|
||||
pl->ps_val0 = pl->ps_val0>p->ps_val0;
|
||||
break;
|
||||
case TVLE:
|
||||
if(pl->ps_val1 != p->ps_val1) goto experr;
|
||||
pl->ps_val0 = pl->ps_val0<=p->ps_val0;
|
||||
break;
|
||||
case TVGE:
|
||||
if(pl->ps_val1 != p->ps_val1) goto experr;
|
||||
pl->ps_val0 = pl->ps_val0>=p->ps_val0;
|
||||
break;
|
||||
}
|
||||
if(pl->ps_val0) pl->ps_val0 = -1;
|
||||
pl->ps_val1 = 0;
|
||||
pl->ps_flg |= p->ps_flg&OFFOR;
|
||||
break;
|
||||
|
||||
case 10: /* <primary> ::= ( <expr7> ) */
|
||||
pl->ps_val0 = p[1].ps_val0;
|
||||
pl->ps_val1 = p[1].ps_val1;
|
||||
pl->ps_flg = p[1].ps_flg;
|
||||
break;
|
||||
|
||||
case 11: /* <primary> ::= constant */
|
||||
pl->ps_val1 = pl->ps_flg = 0;
|
||||
break;
|
||||
|
||||
case 12: /* <primary> ::= symbol */
|
||||
xref((vmadr)p->ps_val1,0);
|
||||
syp = rfetch((vmadr)p->ps_val1);
|
||||
if(syp->sy_typ == STSEC) goto experr;
|
||||
if(syp->sy_typ==STUND || syp->sy_rel==RBUND ||
|
||||
syp->sy_typ==STVAR&&pass2&&!(syp->sy_atr&SADP2)) {
|
||||
err('U'); uflg = 1;
|
||||
pl->ps_val0 = pl->ps_val1 = 0;
|
||||
pl->ps_flg = OFFOR;
|
||||
} else {
|
||||
pl->ps_val0 = syp->sy_val;
|
||||
pl->ps_val1 = syp->sy_rel;
|
||||
pl->ps_flg = pass2&&!(syp->sy_atr&SADP2) ? OFFOR : 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 13: /* <primary> ::= $ */
|
||||
pl->ps_val0 = curloc;
|
||||
pl->ps_val1 = cursec;
|
||||
pl->ps_flg = 0;
|
||||
break;
|
||||
|
||||
case 14: /* <string1> ::= string */
|
||||
i = savlen = p->ps_val0; sp = tokstr; dp = savstr;
|
||||
while(i-- > 0) *dp++ = *sp++;
|
||||
*dp = '\0';
|
||||
break;
|
||||
|
||||
case 15: /* <operand> ::= <expr> */
|
||||
curop.op_cls = (1L<<OCEXP)|(1L<<(prevsem==10?OCPEX:OCNEX));
|
||||
if(eflg) {
|
||||
curop.op_val = curop.op_rel = curop.op_flg = 0;
|
||||
} else {
|
||||
curop.op_val = p->ps_val0;
|
||||
curop.op_rel = p->ps_val1;
|
||||
curop.op_flg = p->ps_flg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 16: /* <expr4> ::= <string1> relop string */
|
||||
sp = savstr; i = savlen;
|
||||
dp = tokstr; j = p->ps_val0;
|
||||
while(i>0 && j>0 && (c = *sp++ - *dp++)==0) {
|
||||
i--; j--;
|
||||
}
|
||||
if(c == 0) c = i-j; /* c reflects the comparison outcome */
|
||||
switch(p[1].ps_val1) {
|
||||
case TVEQ:
|
||||
pl->ps_val0 = c==0;
|
||||
break;
|
||||
case TVNE:
|
||||
pl->ps_val0 = c!=0;
|
||||
break;
|
||||
case TVLT:
|
||||
pl->ps_val0 = c<0;
|
||||
break;
|
||||
case TVGT:
|
||||
pl->ps_val0 = c>0;
|
||||
break;
|
||||
case TVLE:
|
||||
pl->ps_val0 = c<=0;
|
||||
break;
|
||||
case TVGE:
|
||||
pl->ps_val0 = c>=0;
|
||||
break;
|
||||
}
|
||||
if(pl->ps_val0) pl->ps_val0 = -1;
|
||||
pl->ps_val1 = pl->ps_flg = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
return;
|
||||
|
||||
experr:
|
||||
err('E'); eflg = 1;
|
||||
pl->ps_val0 = pl->ps_val1 = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,695 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
#include "asz8k.h"
|
||||
#include "obj.h"
|
||||
|
||||
/*
|
||||
* Version 3.4, 8/27/82. Changes to accomodate 8086 version.
|
||||
*
|
||||
* Version 3.3, 5/22/82. Added PDDIR define for predef directory.
|
||||
*/
|
||||
static char ident[] = "@(#)asz8k.c 3.4";
|
||||
|
||||
/*
|
||||
* direc - Processes assembler directives which are special to this
|
||||
* assembler. Calls dircom to process other directives.
|
||||
*/
|
||||
direc(dirnum) int dirnum; {
|
||||
|
||||
if(dirnum != ADMAC) { /* look up the label */
|
||||
label = *labstr?sylook(labstr):0;
|
||||
}
|
||||
switch(dirnum) {
|
||||
|
||||
case ADLONG: /* .long */
|
||||
if(curloc & 01) /* Force word alignment */
|
||||
curloc++;
|
||||
assign(STLAB,curloc,cursec);
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
while(toktyp != TKEOL) {
|
||||
expression();
|
||||
/*
|
||||
* If we are assembling for the segmented version, and
|
||||
* if the expression is relocatable, we generate a long
|
||||
* segmented address. Otherwise, we generate a normal
|
||||
* 32-bit value.
|
||||
*/
|
||||
if(segflg && curop.op_rel!=0)
|
||||
emitls((long)curop.op_val, curop.op_rel);
|
||||
else
|
||||
emitlm((long)curop.op_val, RAA32M|curop.op_rel);
|
||||
delim();
|
||||
}
|
||||
return;
|
||||
|
||||
case ADWORD: /* .word */
|
||||
if(curloc & 01) /* Force word alignment */
|
||||
curloc++;
|
||||
assign(STLAB,curloc,cursec);
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
while(toktyp != TKEOL) {
|
||||
expression();
|
||||
/*
|
||||
* For the segmented version, we generate the
|
||||
* offset portion of the expression. (Note that
|
||||
* if the expression is non-relocatable, its offset
|
||||
* is the same as its value.) For the non-segmented
|
||||
* version, we simply generate a normal 16-bit value.
|
||||
*/
|
||||
emitwm((uns)curop.op_val,
|
||||
(segflg?RAZOF:RAA16M)|curop.op_rel);
|
||||
delim();
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
dircom(dirnum);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
synerr:
|
||||
err('S'); skipeol();
|
||||
}
|
||||
|
||||
/*
|
||||
* emitlm - Emits a long to the object file, MSW first.
|
||||
*/
|
||||
emitlm(value, reloc) long value; uns reloc; {
|
||||
|
||||
emitwm((uns)(value>>16), reloc);
|
||||
emitwm((uns)value, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* emitls - Emits a long segmented address to the object file.
|
||||
*/
|
||||
emitls(value, reloc) long value; uns reloc; {
|
||||
|
||||
uns seg;
|
||||
|
||||
reloc &= RBMSK;
|
||||
seg = reloc<=0x7f ? reloc : 0x7f;
|
||||
value &= 0xffffL;
|
||||
emitlm(((long)(0x80|seg)<<24)|value, RAZLS|reloc);
|
||||
}
|
||||
|
||||
/*
|
||||
* emitss - Emits a short segmented address to the object file.
|
||||
*/
|
||||
emitss(value, reloc) uns value, reloc; {
|
||||
|
||||
uns seg;
|
||||
|
||||
reloc &= RBMSK;
|
||||
seg = reloc<=0x7f ? reloc : 0x7f;
|
||||
value &= 0xff;
|
||||
emitwm((seg<<8)|value, RAZSS|reloc);
|
||||
}
|
||||
|
||||
/*
|
||||
* emitwm - Emits a word to the object file, MSB first.
|
||||
*/
|
||||
emitwm(value, reloc) uns value, reloc; {
|
||||
|
||||
emitb(value>>8, reloc);
|
||||
emitb(value, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* equ - Handles the .equ and .set directives. The argument is the type
|
||||
* of symbol to define (label or variable). Some assemblers have special
|
||||
* interest code here to allow assigning symbols to registers or other
|
||||
* keywords.
|
||||
*/
|
||||
equ(symtype) int symtype; {
|
||||
|
||||
if(!label) err('L');
|
||||
if(toktyp != TKSPC) goto synerr;
|
||||
iilex();
|
||||
if(iiparse()!=0 || !(curop.op_cls&1L<<OCEXP)) goto synerr;
|
||||
if(!(eflg||uflg) || pass2)
|
||||
assign(symtype,curop.op_val,curop.op_rel);
|
||||
return;
|
||||
synerr:
|
||||
err('S'); skipeol();
|
||||
}
|
||||
|
||||
/*
|
||||
* iilex - Lexical scanner for expression parsing. Calls token and does
|
||||
* further processing as required by the isp parser.
|
||||
*/
|
||||
iilex() {
|
||||
|
||||
struct sytab *syp;
|
||||
|
||||
iilexeme.ps_sym = token();
|
||||
iilexeme.ps_val0 = tokval;
|
||||
if(iilexeme.ps_sym == TKSYM) { /* symbol */
|
||||
iilexeme.ps_val0 = (exprval)sylook(tokstr);
|
||||
syp = rfetch((vmadr)iilexeme.ps_val0);
|
||||
if(syp->sy_typ == STKEY) { /* keyword */
|
||||
iilexeme.ps_val0 = syp->sy_val&0377;
|
||||
iilexeme.ps_sym = syp->sy_val>>8&0377;
|
||||
}
|
||||
} else if(iilexeme.ps_sym==TKCOM || iilexeme.ps_sym==TKSPC ||
|
||||
iilexeme.ps_sym==TKEOL) iilexeme.ps_sym = TKEOF;
|
||||
iilexeme.ps_val1 = (uns)iilexeme.ps_val0;
|
||||
return(iilexeme.ps_sym);
|
||||
}
|
||||
|
||||
/*
|
||||
* inops - Reads the operands for a machine instruction and leaves their
|
||||
* descriptions in optab.
|
||||
*/
|
||||
inops() {
|
||||
|
||||
struct operand *opp;
|
||||
|
||||
if(toktyp == TKSPC) iilex();
|
||||
for(opp=optab ; opp<optab+OPMAX ; opp++) {
|
||||
opp->op_cls = 1L<<OCNULL;
|
||||
if(toktyp == TKEOL) continue;
|
||||
if(iiparse() != 0) {
|
||||
err('S');
|
||||
skipeol();
|
||||
continue;
|
||||
}
|
||||
if(curop.op_cls & (1L<<OCEXP))
|
||||
curop.op_cls |= (1L<<OCX);
|
||||
*opp = curop;
|
||||
delim();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* instr - Generates the specified machine instruction.
|
||||
*/
|
||||
instr(fmp) struct format *fmp; {
|
||||
|
||||
long v,
|
||||
dispval,
|
||||
immval;
|
||||
int displen,
|
||||
disprel,
|
||||
f,
|
||||
i,
|
||||
immlen,
|
||||
immrel,
|
||||
r,
|
||||
skel0,
|
||||
skel1,
|
||||
skel2,
|
||||
skel3,
|
||||
srel1;
|
||||
|
||||
if(curloc & 01) /* Force word alignment */
|
||||
curloc++;
|
||||
label = *labstr?sylook(labstr):0;
|
||||
assign(STLAB,curloc,cursec);
|
||||
inops(); /* read the instruction operands */
|
||||
while(!opmatch(fmp)) { /* scan for matching format entry */
|
||||
if(fmp->fm_flg&FMLAST) goto nomatch;
|
||||
fmp++;
|
||||
}
|
||||
displen = immlen = 0;
|
||||
/*
|
||||
* Build up the instruction's fields.
|
||||
*/
|
||||
skel0 = fmp->fm_skel>>8 & 0xff;
|
||||
skel1 = fmp->fm_skel & 0xff;
|
||||
skel2 = 0;
|
||||
skel3 = fmp->fm_flg & FMNIB7;
|
||||
srel1 = 0;
|
||||
for(i=0 ; i<OPMAX ; i++) {
|
||||
f = optab[i].op_flg;
|
||||
r = optab[i].op_rel;
|
||||
v = optab[i].op_val;
|
||||
switch(fmp->fm_op[i] & OAMSK) {
|
||||
|
||||
case OANIB1: /* Pack value into nibble 1 */
|
||||
if(r!=0 || v<0 || v>15)
|
||||
err('E');
|
||||
skel0 |= v & 0x0f;
|
||||
break;
|
||||
|
||||
case OANIB2: /* Pack value into nibble 2 */
|
||||
if(r!=0 || v<0 || v>15)
|
||||
err('E');
|
||||
skel1 |= v<<4 & 0xf0;
|
||||
break;
|
||||
|
||||
case OANIB3: /* Pack value into nibble 3 */
|
||||
if(r!=0 || v<0 || v>15)
|
||||
err('E');
|
||||
skel1 |= v & 0x0f;
|
||||
break;
|
||||
|
||||
case OANIB5: /* Pack value into nibble 5 */
|
||||
if(r!=0 || v<0 || v>15)
|
||||
err('E');
|
||||
skel2 |= v & 0x0f;
|
||||
break;
|
||||
|
||||
case OANIB6: /* Pack value into nibble 6 */
|
||||
if(r!=0 || v<0 || v>15)
|
||||
err('E');
|
||||
skel3 |= v<<4 & 0xf0;
|
||||
break;
|
||||
|
||||
case OANIB7: /* Pack value into nibble 7 */
|
||||
if(r!=0 || v<0 || v>15)
|
||||
err('E');
|
||||
skel3 |= v & 0x0f;
|
||||
break;
|
||||
|
||||
case OABYT1: /* Pack value into byte 1 */
|
||||
skel1 = v;
|
||||
srel1 = r;
|
||||
break;
|
||||
|
||||
case OAX2: /* Generate indexed addr using nibble 2 */
|
||||
skel1 |= (f & OFXMSK) << 4;
|
||||
dispval = v;
|
||||
disprel = r;
|
||||
if(segflg)
|
||||
displen = f&OFSHORT ? 2 : 4;
|
||||
else
|
||||
displen = 2;
|
||||
break;
|
||||
|
||||
case OAX3: /* Generate indexed addr using nibble 3 */
|
||||
skel1 |= f & OFXMSK;
|
||||
dispval = v;
|
||||
disprel = r;
|
||||
if(segflg)
|
||||
displen = f&OFSHORT ? 2 : 4;
|
||||
else
|
||||
displen = 2;
|
||||
break;
|
||||
|
||||
case OABA2: /* Generate based addr using nibble 2 */
|
||||
skel1 |= (f & OFXMSK) << 4;
|
||||
dispval = v;
|
||||
disprel = r;
|
||||
displen = 2;
|
||||
break;
|
||||
|
||||
case OABA3: /* Generate based addr using nibble 3 */
|
||||
skel1 |= f & OFXMSK;
|
||||
dispval = v;
|
||||
disprel = r;
|
||||
displen = 2;
|
||||
break;
|
||||
|
||||
case OABX2: /* Generate based-indexed addr using nibble 2 */
|
||||
skel1 |= (f & OFXMSK) << 4;
|
||||
skel2 |= v;
|
||||
break;
|
||||
|
||||
case OABX3: /* Generate based-indexed addr using nibble 3 */
|
||||
skel1 |= f & OFXMSK;
|
||||
skel2 |= v;
|
||||
break;
|
||||
|
||||
case OACFLAG: /* OR condition flag into nibble 2 */
|
||||
skel1 |= 1<<v;
|
||||
break;
|
||||
|
||||
case OANIB3S: /* Pack into low 3 bits of nibble 3 */
|
||||
if(r!=0 || v<0 || v>7)
|
||||
err('E');
|
||||
skel1 |= v & 0x07;
|
||||
break;
|
||||
|
||||
case OANIB3A: /* AND into nibble 3 */
|
||||
skel1 &= 0xf0 | v;
|
||||
break;
|
||||
|
||||
case OANIB3D: /* Decrement and pack into nibble 3 */
|
||||
v--;
|
||||
if(r!=0 || v<0 || v>15)
|
||||
err('E');
|
||||
skel1 |= v & 0x0f;
|
||||
break;
|
||||
|
||||
case OANIB7D: /* Decrement and pack into nibble 7 */
|
||||
v--;
|
||||
if(r!=0 || v<0 || v>15)
|
||||
err('E');
|
||||
skel3 |= v & 0x0f;
|
||||
break;
|
||||
|
||||
case OARA7: /* Generate 7-bit relative address */
|
||||
v = curloc+2 - v;
|
||||
if(r!=cursec || v&01 || v<0 || v>=(2*128))
|
||||
err('E');
|
||||
skel1 |= v >> 1;
|
||||
break;
|
||||
|
||||
case OARA8: /* Generate 8-bit relative address */
|
||||
v -= curloc+2;
|
||||
if(r!=cursec || v&01 || v<(2*-128) || v>=(2*128))
|
||||
err('E');
|
||||
skel1 |= v >> 1;
|
||||
break;
|
||||
|
||||
case OARA12: /* Generate 12-bit relative address */
|
||||
v = curloc+2 - v;
|
||||
if(r!=cursec || v&01 || v<(2*-2048) || v>=(2*2048))
|
||||
err('E');
|
||||
skel0 |= (v>>9) & 0x0f;
|
||||
skel1 = (v>>1) & 0xff;
|
||||
break;
|
||||
|
||||
case OARA16: /* Generate 16-bit relative address */
|
||||
v -= curloc+4;
|
||||
if(r!=cursec || v&01)
|
||||
err('E');
|
||||
/*
|
||||
* We treat this as an immediate because we don't
|
||||
* want a segmented form of address for the segmented
|
||||
* version.
|
||||
*/
|
||||
immlen = 2;
|
||||
immrel = 0;
|
||||
immval = v & 0xffff;
|
||||
break;
|
||||
|
||||
case OAIMM8: /* Generate 8-bit immediate */
|
||||
immlen = 1;
|
||||
immrel = r;
|
||||
immval = v & 0xff;
|
||||
break;
|
||||
|
||||
case OAIMM16: /* Generate 16-bit immediate */
|
||||
immlen = 2;
|
||||
immrel = r;
|
||||
immval = v & 0xffff;
|
||||
break;
|
||||
|
||||
case OAIMM32: /* Generate 32-bit immediate */
|
||||
immlen = 4;
|
||||
immrel = r;
|
||||
immval = v;
|
||||
break;
|
||||
|
||||
case OASHFT: /* Generate shift count of 1 or 2 */
|
||||
if(r!=0 || v<1 || v>2)
|
||||
err('E');
|
||||
if(v == 2)
|
||||
skel1 |= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
emitb(skel0, 0);
|
||||
emitb(skel1, RAA8|srel1);
|
||||
if(fmp->fm_flg & FMSKEL2) {
|
||||
if(fmp->fm_flg & FMNEGI) /* Fake -1 immed. for R shift */
|
||||
skel2 = skel3 = 0xff;
|
||||
emitb(skel2, 0);
|
||||
emitb(skel3, 0);
|
||||
}
|
||||
if(displen == 2) {
|
||||
if(segflg)
|
||||
emitss((uns)dispval, disprel);
|
||||
else
|
||||
emitwm((uns)dispval, RAA16M|disprel);
|
||||
} else if(displen == 4)
|
||||
emitls((long)dispval, disprel);
|
||||
if(immlen == 1) {
|
||||
emitb((uns)immval, RAA8|immrel);
|
||||
emitb((uns)immval, RAA8|immrel);
|
||||
} else if(immlen == 2) {
|
||||
if(fmp->fm_flg & FMNEGI) {
|
||||
/*
|
||||
* Negate immediate value for right shift instrucions.
|
||||
*/
|
||||
if(immrel != 0)
|
||||
err('E');
|
||||
immval = -immval;
|
||||
}
|
||||
/*
|
||||
* For the segmented version, we generate the
|
||||
* offset portion of the expression. (Note that
|
||||
* if the expression is non-relocatable, its offset
|
||||
* is the same as its value.) For the non-segmented
|
||||
* version, we simply generate a normal 16-bit value.
|
||||
*/
|
||||
emitwm((uns)immval, (segflg?RAZOF:RAA16M)|immrel);
|
||||
} else if(immlen == 4) {
|
||||
/*
|
||||
* If we are assembling for the segmented version, and if
|
||||
* the expression is relocatable, we generate a long
|
||||
* segmented address. Otherwise, we generate a normal
|
||||
* 32-bit value.
|
||||
*/
|
||||
if(segflg && immrel!=0)
|
||||
emitls((long)immval, immrel);
|
||||
else
|
||||
emitlm(immval, RAA32M|immrel);
|
||||
}
|
||||
return;
|
||||
|
||||
nomatch:
|
||||
err('O');
|
||||
}
|
||||
|
||||
/*
|
||||
* opmatch - Returns 1 if the specified format entry matches the operands
|
||||
* in optab, 0 otherwise.
|
||||
*/
|
||||
opmatch(fmp) struct format *fmp; {
|
||||
|
||||
int i;
|
||||
|
||||
for(i=0 ; i<OPMAX ; i++) {
|
||||
if(!(1L<<(fmp->fm_op[i]&OCMSK)&optab[i].op_cls)) return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* predef - Reads the predefined symbols into the symbol table.
|
||||
*/
|
||||
predef() {
|
||||
|
||||
struct format *fmp;
|
||||
struct octab *ocp;
|
||||
struct sytab *syp;
|
||||
int i, val;
|
||||
char predef[30];
|
||||
|
||||
/*
|
||||
* Open the predef file and read in the definitions.
|
||||
*/
|
||||
sprintf(predef,"%s.pd",prname); /* use local predef file */
|
||||
if(include(predef) == -1) {
|
||||
fprintf(ERROR,"No PREDEF file (%s)\n",predef);
|
||||
exit(1);
|
||||
}
|
||||
while(token() == TKCON) { /* read machine instructions */
|
||||
if((uns)phytop&01) phytop++; /* force alignment */
|
||||
val = phytop;
|
||||
for(;;) { /* read format table entries */
|
||||
fmp = palloc(sizeof(struct format));
|
||||
for(i=0 ; i<OPMAX ; i++) { /* operand descriptors */
|
||||
fmp->fm_op[i] = tokval;
|
||||
preget(TKSPC); preget(TKCON);
|
||||
}
|
||||
fmp->fm_skel = tokval;
|
||||
preget(TKSPC);
|
||||
fmp->fm_flg = preget(TKCON);
|
||||
if(token() != TKEOL) break;
|
||||
preget(TKCON);
|
||||
}
|
||||
fmp->fm_flg |= FMLAST;
|
||||
while(toktyp == TKSPC) { /* read instruction mnemonics */
|
||||
preget(TKSYM); ocp = oclook(tokstr);
|
||||
ocp->oc_typ = OTINS; ocp->oc_val = val;
|
||||
token();
|
||||
}
|
||||
if(toktyp != TKEOL) badpre();
|
||||
}
|
||||
if(toktyp != TKEOL) badpre();
|
||||
while(token() == TKCON) { /* read assembler directives */
|
||||
val = tokval;
|
||||
while(token() == TKSPC) { /* read directive mnemonics */
|
||||
preget(TKSYM); ocp = oclook(tokstr);
|
||||
ocp->oc_typ = OTDIR; ocp->oc_val = val;
|
||||
}
|
||||
if(toktyp != TKEOL) badpre();
|
||||
}
|
||||
if(toktyp != TKEOL) badpre();
|
||||
while(token() == TKCON) { /* read predefined symbols */
|
||||
val = tokval;
|
||||
while(token() == TKSPC) { /* read symbol mnemonics */
|
||||
preget(TKSYM); syp = wfetch(sylook(tokstr));
|
||||
syp->sy_typ = STKEY;
|
||||
syp->sy_val = val;
|
||||
syp->sy_atr = SADP2;
|
||||
}
|
||||
if(toktyp != TKEOL) badpre();
|
||||
}
|
||||
preget(TKEOF);
|
||||
}
|
||||
|
||||
/*
|
||||
* sem51 - Parser semantic routines specific to asz8k.
|
||||
*/
|
||||
sem51(sem) int sem; {
|
||||
|
||||
reg struct psframe *p, *pl;
|
||||
|
||||
p = iipsp; pl = iipspl;
|
||||
switch(sem) {
|
||||
|
||||
case 51: /* <operand> ::= reg8 */
|
||||
curop.op_cls = (1L<<OCREG8);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 52: /* <operand> ::= reg16 */
|
||||
curop.op_cls = (1L<<OCREG16);
|
||||
if(!segflg)
|
||||
curop.op_cls |= (1L<<OCREGA);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 53: /* <operand> ::= reg32 */
|
||||
curop.op_cls = (1L<<OCREG32);
|
||||
if(segflg)
|
||||
curop.op_cls |= (1L<<OCREGA);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 54: /* <operand> ::= reg64 */
|
||||
curop.op_cls = (1L<<OCREG64);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 55: /* <operand> ::= pound <expr> */
|
||||
curop.op_cls = (1L<<OCIMM);
|
||||
if(eflg)
|
||||
curop.op_val = curop.op_rel = curop.op_flg = 0;
|
||||
else {
|
||||
curop.op_val = p->ps_val0;
|
||||
curop.op_rel = p->ps_val1;
|
||||
curop.op_flg = p->ps_flg;
|
||||
}
|
||||
return;
|
||||
|
||||
case 56: /* <operand> ::= <indexed> */
|
||||
curop.op_cls = (1L<<OCX);
|
||||
if(eflg)
|
||||
curop.op_val = curop.op_rel = curop.op_flg = 0;
|
||||
else {
|
||||
curop.op_val = pl->ps_val0;
|
||||
curop.op_rel = pl->ps_val1;
|
||||
curop.op_flg = pl->ps_flg;
|
||||
}
|
||||
return;
|
||||
|
||||
case 57: /* <operand> ::= @ reg16 */
|
||||
curop.op_cls = (1L<<OCIRIO);
|
||||
if(!segflg)
|
||||
curop.op_cls |= (1L<<OCIR);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 58: /* <operand> ::= @ reg32 */
|
||||
if(segflg)
|
||||
curop.op_cls = (1L<<OCIR);
|
||||
else
|
||||
curop.op_cls = 0;
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 59: /* <operand> ::= <basereg> ( pound <expr> ) */
|
||||
curop.op_cls = (1L<<OCBA);
|
||||
if(eflg)
|
||||
curop.op_val = curop.op_rel = curop.op_flg = 0;
|
||||
else {
|
||||
curop.op_val = p[1].ps_val0;
|
||||
curop.op_rel = p[1].ps_val1;
|
||||
curop.op_flg = p[1].ps_flg | pl->ps_val1;
|
||||
}
|
||||
return;
|
||||
|
||||
case 60: /* <operand> ::= <basereg> ( reg16 ) */
|
||||
curop.op_cls = (1L<<OCBX);
|
||||
if(p[1].ps_val1 == 0)
|
||||
err('E');
|
||||
curop.op_val = p[1].ps_val1;
|
||||
curop.op_rel = 0;
|
||||
curop.op_flg = pl->ps_val1;
|
||||
return;
|
||||
|
||||
case 61: /* <operand> ::= ccode */
|
||||
curop.op_cls = (1L<<OCCCODE);
|
||||
if(4 <= p->ps_val1 && p->ps_val1 < 8)
|
||||
curop.op_cls |= (1L<<OCCFLAG);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 62: /* <operand> ::= int */
|
||||
curop.op_cls = (1L<<OCINT);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 63: /* <operand> ::= ctl */
|
||||
curop.op_cls = (1L<<OCCTL);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 64: /* <operand> ::= FLAGS */
|
||||
curop.op_cls = (1L<<OCFLAGS);
|
||||
curop.op_val = p->ps_val1;
|
||||
curop.op_rel = curop.op_flg = 0;
|
||||
return;
|
||||
|
||||
case 65: /* <basereg> ::= reg16 */
|
||||
if(segflg || p->ps_val1==0)
|
||||
err('E');
|
||||
return;
|
||||
|
||||
case 66: /* <basereg> ::= reg32 */
|
||||
if(!segflg || p->ps_val1==0)
|
||||
err('E');
|
||||
return;
|
||||
|
||||
case 67: /* <indexed> ::= <expr> ( reg16 ) */
|
||||
if(p[1].ps_val1 == 0)
|
||||
err('E');
|
||||
pl->ps_flg |= p[1].ps_val1;
|
||||
return;
|
||||
|
||||
case 68: /* <operand> ::= orop <expr> */
|
||||
case 69: /* <operand> ::= orop <indexed> */
|
||||
curop.op_cls = (1L<<OCX);
|
||||
if(eflg) {
|
||||
curop.op_val = curop.op_rel = 0;
|
||||
curop.op_flg = OFSHORT;
|
||||
} else {
|
||||
curop.op_val = p->ps_val0;
|
||||
curop.op_rel = p->ps_val1;
|
||||
curop.op_flg = p->ps_flg | OFSHORT;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* @(#)asz8k.h 3.1
|
||||
*
|
||||
* Declarations specific to asz8k.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Parameters.
|
||||
*/
|
||||
#define OPMAX 4 /* maximum number of instruction operands */
|
||||
/*
|
||||
* Instruction format table flags (in fm_flg).
|
||||
*/
|
||||
#define FMNIB7 0x000f /* value to OR into nibble 7 */
|
||||
#define FMSKEL2 0x0010 /* generate 2nd skeleton word */
|
||||
#define FMNEGI 0x0020 /* negate immediate value for right shift */
|
||||
#define FMLAST 0x8000 /* final entry for this instruction */
|
||||
/*
|
||||
* Operand actions (in fm_op[]).
|
||||
*/
|
||||
#define OANULL 0x0000 /* operand not used */
|
||||
#define OANIB1 0x0100 /* pack into nibble 1 */
|
||||
#define OANIB2 0x0200 /* pack into nibble 2 */
|
||||
#define OANIB3 0x0300 /* pack into nibble 3 */
|
||||
#define OANIB5 0x0500 /* pack into nibble 5 */
|
||||
#define OANIB6 0x0600 /* pack into nibble 6 */
|
||||
#define OANIB7 0x0700 /* pack into nibble 7 */
|
||||
#define OABYT1 0x0800 /* pack into byte 1 */
|
||||
#define OAX2 0x0900 /* generate indexed addr using nibble 2 */
|
||||
#define OAX3 0x0a00 /* generate indexed addr using nibble 3 */
|
||||
#define OABA2 0x0b00 /* generate based address using nibble 2 */
|
||||
#define OABA3 0x0c00 /* generate based address using nibble 3 */
|
||||
#define OABX2 0x0d00 /* generate based-indexed addr using nibble 2 */
|
||||
#define OABX3 0x0e00 /* generate based-indexed addr using nibble 3 */
|
||||
#define OACFLAG 0x0f00 /* OR condition flag bit into nibble 2 */
|
||||
#define OANIB3S 0x1100 /* pack into low 3 bits of nibble 3 */
|
||||
#define OANIB3A 0x1200 /* AND into nibble 3 */
|
||||
#define OANIB3D 0x1300 /* decrement and pack into nibble 3 */
|
||||
#define OANIB7D 0x1700 /* decrement and pack into nibble 7 */
|
||||
#define OARA7 0x1800 /* generate 7-bit relative address */
|
||||
#define OARA8 0x1900 /* generate 8-bit relative address */
|
||||
#define OARA12 0x1a00 /* generate 12-bit relative address */
|
||||
#define OARA16 0x1b00 /* generate 16-bit relative address */
|
||||
#define OAIMM8 0x1c00 /* generate 8-bit immediate */
|
||||
#define OAIMM16 0x1d00 /* generate 16-bit immediate */
|
||||
#define OAIMM32 0x1e00 /* generate 32-bit immediate */
|
||||
#define OASHFT 0x1f00 /* generate shift count of 1 or 2 */
|
||||
#define OAMSK 0x1f00 /* mask for operand action field */
|
||||
/*
|
||||
* Operand classes.
|
||||
*/
|
||||
#define OCREG8 0x0004 /* {rh0,rh1,rh2,rh3,...,rl4,rl5,rl6,rl7} */
|
||||
#define OCREG16 0x0005 /* {r0,r1,r2,r3,...,r14,r15} */
|
||||
#define OCREG32 0x0006 /* {rr0,rr2,rr4,rr6,rr8,rr10,rr12,rr14} */
|
||||
#define OCREG64 0x0007 /* {rq0,rq4,rq8,rq12} */
|
||||
#define OCIMM 0x0008 /* immediate value */
|
||||
#define OCIR 0x0009 /* indirect register */
|
||||
#define OCX 0x000a /* indexed address */
|
||||
#define OCBA 0x000b /* based address */
|
||||
#define OCBX 0x000c /* based-indexed address */
|
||||
#define OCCCODE 0x000d /* condition code */
|
||||
#define OCCFLAG 0x000e /* condition code flag bit */
|
||||
#define OCINT 0x000f /* {nvi,vi} */
|
||||
#define OCCTL 0x0010 /* control register for LDCTL */
|
||||
#define OCFLAGS 0x0011 /* FLAGS for LDCTLB */
|
||||
#define OCIRIO 0x0012 /* indirect register for I/O instruction */
|
||||
#define OCREGA 0x0013 /* address register (depends on seg mode) */
|
||||
#define OCMSK 0x001f /* mask for operand class field in fm_op */
|
||||
/*
|
||||
* Operand flags (in op_flg and ps_flg).
|
||||
*/
|
||||
#define OFXMSK 0x0f /* mask for index register code */
|
||||
#define OFSHORT 0x80 /* force short offset */
|
||||
/*
|
||||
* Token types.
|
||||
*/
|
||||
#define TKPOUND 14 /* '#' */
|
||||
#define TKAT 15 /* '@' */
|
||||
#define TKREG8 16 /* {rh0,rh1,rh2,rh3,...rl4,rl5,rl6,rl7} */
|
||||
#define TKREG16 17 /* {r0,r1,r2,r3,...,r12,r13,r14,r15} */
|
||||
#define TKREG32 18 /* {rr0,rr2,rr4,rr6,rr8,rr10,rr12,rr14} */
|
||||
#define TKREG64 19 /* {rq0,rq4,rq8,rq12} */
|
||||
#define TKCCODE 20 /* condition codes and flags */
|
||||
#define TKINT 21 /* {nvi,vi} */
|
||||
#define TKCTL 22 /* control registers for LDCTL */
|
||||
#define TKFLAGS 23 /* FLAGS for LDCTLB */
|
||||
/*
|
||||
* Structure declarations.
|
||||
*/
|
||||
struct format { /* instruction format table entry */
|
||||
int fm_op[OPMAX]; /* operand descriptions */
|
||||
int fm_skel; /* opcode skeleton word */
|
||||
int fm_flg; /* flags */
|
||||
};
|
||||
/*
|
||||
* Global variable declarations.
|
||||
*/
|
||||
char segflg; /* Generate code for segmented processor */
|
||||
@@ -0,0 +1,509 @@
|
||||
305h 205h 0 0 0b500h 0 adc ADC
|
||||
304h 204h 0 0 0b400h 0 adcb ADCB
|
||||
305h 205h 0 0 8100h 0
|
||||
305h 1d08h 0 0 100h 0
|
||||
305h 209h 0 0 100h 0
|
||||
305h 90ah 0 0 4100h 0 add ADD
|
||||
304h 204h 0 0 8000h 0
|
||||
304h 1c08h 0 0 0 0
|
||||
304h 209h 0 0 0 0
|
||||
304h 90ah 0 0 4000h 0 addb ADDB
|
||||
306h 206h 0 0 9600h 0
|
||||
306h 1e08h 0 0 1600h 0
|
||||
306h 209h 0 0 1600h 0
|
||||
306h 90ah 0 0 5600h 0 addl ADDL
|
||||
305h 205h 0 0 8700h 0
|
||||
305h 1d08h 0 0 700h 0
|
||||
305h 209h 0 0 700h 0
|
||||
305h 90ah 0 0 4700h 0 and AND
|
||||
304h 204h 0 0 8600h 0
|
||||
304h 1c08h 0 0 600h 0
|
||||
304h 209h 0 0 600h 0
|
||||
304h 90ah 0 0 4600h 0 andb ANDB
|
||||
205h 308h 0 0 0a700h 0
|
||||
209h 308h 0 0 2700h 0
|
||||
90ah 308h 0 0 6700h 0
|
||||
505h 305h 0 0 2700h 10h bit BIT
|
||||
204h 1108h 0 0 0a600h 0
|
||||
209h 1108h 0 0 2600h 0
|
||||
90ah 1108h 0 0 6600h 0
|
||||
504h 1105h 0 0 2600h 10h bitb BITB
|
||||
209h 0 0 0 1f00h 0
|
||||
90ah 0 0 0 5f00h 0 call CALL
|
||||
1a03h 0 0 0 0d000h 0 calr CALR
|
||||
205h 0 0 0 8d08h 0
|
||||
209h 0 0 0 0d08h 0
|
||||
90ah 0 0 0 4d08h 0 clr CLR
|
||||
204h 0 0 0 8c08h 0
|
||||
209h 0 0 0 0c08h 0
|
||||
90ah 0 0 0 4c08h 0 clrb CLRB
|
||||
205h 0 0 0 8d00h 0
|
||||
209h 0 0 0 0d00h 0
|
||||
90ah 0 0 0 4d00h 0 com COM
|
||||
204h 0 0 0 8c00h 0
|
||||
209h 0 0 0 0c00h 0
|
||||
90ah 0 0 0 4c00h 0 comb COMB
|
||||
0f0eh 0 0 0 8d05h 0
|
||||
0f0eh 0f0eh 0 0 8d05h 0
|
||||
0f0eh 0f0eh 0f0eh 0 8d05h 0
|
||||
0f0eh 0f0eh 0f0eh 0f0eh 8d05h 0 comflg COMFLG
|
||||
305h 205h 0 0 8b00h 0
|
||||
305h 1d08h 0 0 0b00h 0
|
||||
305h 209h 0 0 0b00h 0
|
||||
305h 90ah 0 0 4b00h 0
|
||||
209h 1d08h 0 0 0d01h 0
|
||||
90ah 1d08h 0 0 4d01h 0 cp CP
|
||||
304h 204h 0 0 8a00h 0
|
||||
304h 1c08h 0 0 0a00h 0
|
||||
304h 209h 0 0 0a00h 0
|
||||
304h 90ah 0 0 4a00h 0
|
||||
209h 1c08h 0 0 0c01h 0
|
||||
90ah 1c08h 0 0 4c01h 0 cpb CPB
|
||||
306h 206h 0 0 9000h 0
|
||||
306h 1e08h 0 0 1000h 0
|
||||
306h 209h 0 0 1000h 0
|
||||
306h 90ah 0 0 5000h 0 cpl CPL
|
||||
605h 209h 505h 70dh 0bb08h 10h cpd CPD
|
||||
604h 209h 505h 70dh 0ba08h 10h cpdb CPDB
|
||||
605h 209h 505h 70dh 0bb0ch 10h cpdr CPDR
|
||||
604h 209h 505h 70dh 0ba0ch 10h cpdrb CPDRB
|
||||
605h 209h 505h 70dh 0bb00h 10h cpi CPI
|
||||
604h 209h 505h 70dh 0ba00h 10h cpib CPIB
|
||||
605h 209h 505h 70dh 0bb04h 10h cpir CPIR
|
||||
604h 209h 505h 70dh 0ba04h 10h cpirb CPIRB
|
||||
609h 209h 505h 70dh 0bb0ah 10h cpsd CPSD
|
||||
609h 209h 505h 70dh 0ba0ah 10h cpsdb CPSDB
|
||||
609h 209h 505h 70dh 0bb0eh 10h cpsdr CPSDR
|
||||
609h 209h 505h 70dh 0ba0eh 10h cpsdrb CPSDRB
|
||||
609h 209h 505h 70dh 0bb02h 10h cpsi CPSI
|
||||
609h 209h 505h 70dh 0ba02h 10h cpsib CPSIB
|
||||
609h 209h 505h 70dh 0bb06h 10h cpsir CPSIR
|
||||
609h 209h 505h 70dh 0ba06h 10h cpsirb CPSIRB
|
||||
204h 0 0 0 0b000h 0 dab DAB
|
||||
205h 0 0 0 0ab00h 0
|
||||
209h 0 0 0 2b00h 0
|
||||
90ah 0 0 0 6b00h 0
|
||||
205h 1308h 0 0 0ab00h 0
|
||||
209h 1308h 0 0 2b00h 0
|
||||
90ah 1308h 0 0 6b00h 0 dec DEC
|
||||
204h 0 0 0 0aa00h 0
|
||||
209h 0 0 0 2a00h 0
|
||||
90ah 0 0 0 6a00h 0
|
||||
204h 1308h 0 0 0aa00h 0
|
||||
209h 1308h 0 0 2a00h 0
|
||||
90ah 1308h 0 0 6a00h 0 decb DECB
|
||||
120fh 0 0 0 7c03h 0
|
||||
120fh 120fh 0 0 7c03h 0 di DI
|
||||
306h 205h 0 0 9b00h 0
|
||||
306h 1d08h 0 0 1b00h 0
|
||||
306h 209h 0 0 1b00h 0
|
||||
306h 90ah 0 0 5b00h 0 div DIV
|
||||
307h 206h 0 0 9a00h 0
|
||||
307h 1e08h 0 0 1a00h 0
|
||||
307h 209h 0 0 1a00h 0
|
||||
307h 90ah 0 0 5a00h 0 divl DIVL
|
||||
105h 1803h 0 0 0f080h 0 djnz DJNZ
|
||||
104h 1803h 0 0 0f000h 0 dbjnz DBJNZ
|
||||
120fh 0 0 0 7c07h 0
|
||||
120fh 120fh 0 0 7c07h 0 ei EI
|
||||
305h 205h 0 0 0ad00h 0
|
||||
305h 209h 0 0 2d00h 0
|
||||
305h 90ah 0 0 6d00h 0 ex EX
|
||||
304h 204h 0 0 0ac00h 0
|
||||
304h 209h 0 0 2c00h 0
|
||||
304h 90ah 0 0 6c00h 0 exb EXB
|
||||
206h 0 0 0 0b10ah 0 exts EXTS
|
||||
205h 0 0 0 0b100h 0 extsb EXTSB
|
||||
207h 0 0 0 0b107h 0 extsl EXTSL
|
||||
0 0 0 0 7a00h 0 halt HALT
|
||||
305h 212h 0 0 3d00h 0
|
||||
205h 1d03h 0 0 3b04h 0 in IN
|
||||
304h 212h 0 0 3c00h 0
|
||||
204h 1d03h 0 0 3a04h 0 inb INB
|
||||
205h 0 0 0 0a900h 0
|
||||
209h 0 0 0 2900h 0
|
||||
90ah 0 0 0 6900h 0
|
||||
205h 1308h 0 0 0a900h 0
|
||||
209h 1308h 0 0 2900h 0
|
||||
90ah 1308h 0 0 6900h 0 inc INC
|
||||
204h 0 0 0 0a800h 0
|
||||
209h 0 0 0 2800h 0
|
||||
90ah 0 0 0 6800h 0
|
||||
204h 1308h 0 0 0a800h 0
|
||||
209h 1308h 0 0 2800h 0
|
||||
90ah 1308h 0 0 6800h 0 incb INCB
|
||||
609h 212h 505h 0 3b08h 18h ind IND
|
||||
609h 212h 505h 0 3a08h 18h indb INDB
|
||||
609h 212h 505h 0 3b08h 10h indr INDR
|
||||
609h 212h 505h 0 3a08h 10h indrb INDRB
|
||||
609h 212h 505h 0 3b00h 18h ini INI
|
||||
609h 212h 505h 0 3a00h 18h inib INIB
|
||||
609h 212h 505h 0 3b00h 10h inir INIR
|
||||
609h 212h 505h 0 3a00h 10h inirb INIRB
|
||||
0 0 0 0 7b00h 0 iret IRET
|
||||
209h 0 0 0 1e08h 0
|
||||
90ah 0 0 0 5e08h 0
|
||||
30dh 209h 0 0 1e00h 0
|
||||
30dh 90ah 0 0 5e00h 0 jp JP
|
||||
1903h 0 0 0 0e800h 0
|
||||
10dh 1903h 0 0 0e000h 0 jr JR
|
||||
305h 205h 0 0 0a100h 0
|
||||
305h 1d08h 0 0 2100h 0
|
||||
305h 209h 0 0 2100h 0
|
||||
305h 90ah 0 0 6100h 0
|
||||
305h 0b0bh 0 0 3100h 0
|
||||
305h 0d0ch 0 0 7100h 10h
|
||||
209h 305h 0 0 2f00h 0
|
||||
90ah 305h 0 0 6f00h 0
|
||||
209h 1d08h 0 0 0d05h 0
|
||||
90ah 1d08h 0 0 4d05h 0
|
||||
0b0bh 305h 0 0 3300h 0
|
||||
0d0ch 305h 0 0 7300h 10h ld LD
|
||||
304h 204h 0 0 0a000h 0
|
||||
104h 808h 0 0 0c000h 0
|
||||
304h 209h 0 0 2000h 0
|
||||
304h 90ah 0 0 6000h 0
|
||||
304h 0b0bh 0 0 3000h 0
|
||||
304h 0d0ch 0 0 7000h 10h
|
||||
209h 304h 0 0 2e00h 0
|
||||
90ah 304h 0 0 6e00h 0
|
||||
209h 1c08h 0 0 0c05h 0
|
||||
90ah 1c08h 0 0 4c05h 0
|
||||
0b0bh 304h 0 0 3200h 0
|
||||
0d0ch 304h 0 0 7200h 10h ldb LDB
|
||||
306h 206h 0 0 9400h 0
|
||||
306h 1e08h 0 0 1400h 0
|
||||
306h 209h 0 0 1400h 0
|
||||
306h 90ah 0 0 5400h 0
|
||||
306h 0b0bh 0 0 3500h 0
|
||||
306h 0d0ch 0 0 7500h 10h
|
||||
209h 306h 0 0 1d00h 0
|
||||
90ah 306h 0 0 5d00h 0
|
||||
0b0bh 306h 0 0 3700h 0
|
||||
0d0ch 306h 0 0 7700h 10h ldl LDL
|
||||
313h 90ah 0 0 7600h 0
|
||||
313h 0b0bh 0 0 3400h 0
|
||||
313h 0d0ch 0 0 7400h 10h lda LDA
|
||||
313h 1b03h 0 0 3400h 0 ldar LDAR
|
||||
11h 204h 0 0 8c09h 0
|
||||
204h 11h 0 0 8c01h 0 ldctlb LDCTLB
|
||||
310h 205h 0 0 7d08h 0
|
||||
205h 310h 0 0 7d00h 0 ldctl LDCTL
|
||||
609h 209h 505h 0 0bb09h 18h ldd LDD
|
||||
609h 209h 505h 0 0ba09h 18h lddb LDDB
|
||||
609h 209h 505h 0 0bb09h 10h lddr LDDR
|
||||
609h 209h 505h 0 0ba09h 10h lddrb LDDRB
|
||||
609h 209h 505h 0 0bb01h 18h ldi LDI
|
||||
609h 209h 505h 0 0ba01h 18h ldib LDIB
|
||||
609h 209h 505h 0 0bb01h 10h ldir LDIR
|
||||
609h 209h 505h 0 0ba01h 10h ldirb LDIRB
|
||||
205h 308h 0 0 0bd00h 0 ldk LDK
|
||||
505h 209h 1708h 0 1c01h 10h
|
||||
505h 90ah 1708h 0 5c01h 10h
|
||||
209h 505h 1708h 0 1c09h 10h
|
||||
90ah 505h 1708h 0 5c09h 10h ldm LDM
|
||||
209h 0 0 0 3900h 0
|
||||
90ah 0 0 0 7900h 0 ldps LDPS
|
||||
305h 1b03h 0 0 3100h 0
|
||||
1b03h 305h 0 0 3300h 0 ldr LDR
|
||||
304h 1b03h 0 0 3000h 0
|
||||
1b03h 304h 0 0 3200h 0 ldrb LDRB
|
||||
306h 1b03h 0 0 3500h 0
|
||||
1b03h 306h 0 0 3700h 0 ldrl LDRL
|
||||
0 0 0 0 7b0ah 0 mbit MBIT
|
||||
205h 0 0 0 7b0dh 0 mreq MREQ
|
||||
0 0 0 0 7b09h 0 mres MRES
|
||||
0 0 0 0 7b08h 0 mset MSET
|
||||
306h 205h 0 0 9900h 0
|
||||
306h 1d08h 0 0 1900h 0
|
||||
306h 209h 0 0 1900h 0
|
||||
306h 90ah 0 0 5900h 0 mult MULT
|
||||
307h 206h 0 0 9800h 0
|
||||
307h 1e08h 0 0 1800h 0
|
||||
307h 209h 0 0 1800h 0
|
||||
307h 90ah 0 0 5800h 0 multl MULTL
|
||||
205h 0 0 0 8d02h 0
|
||||
209h 0 0 0 0d02h 0
|
||||
90ah 0 0 0 4d02h 0 neg NEG
|
||||
204h 0 0 0 8c02h 0
|
||||
209h 0 0 0 0c02h 0
|
||||
90ah 0 0 0 4c02h 0 negb NEGB
|
||||
0 0 0 0 8d07h 0 nop NOP
|
||||
305h 205h 0 0 8500h 0
|
||||
305h 1d08h 0 0 500h 0
|
||||
305h 209h 0 0 500h 0
|
||||
305h 90ah 0 0 4500h 0 or OR
|
||||
304h 204h 0 0 8400h 0
|
||||
304h 1c08h 0 0 400h 0
|
||||
304h 209h 0 0 400h 0
|
||||
304h 90ah 0 0 4400h 0 orb ORB
|
||||
612h 209h 505h 0 3b0ah 10h otdr OTDR
|
||||
612h 209h 505h 0 3a0ah 10h otdrb OTDRB
|
||||
612h 209h 505h 0 3b02h 10h otir OTIR
|
||||
612h 209h 505h 0 3a02h 10h otirb OTIRB
|
||||
212h 305h 0 0 3f00h 0
|
||||
1d03h 205h 0 0 3b06h 0 out OUT
|
||||
212h 304h 0 0 3e00h 0
|
||||
1d03h 204h 0 0 3a06h 0 outb OUTB
|
||||
612h 209h 505h 0 3b0ah 18h outd OUTD
|
||||
612h 209h 505h 0 3a0ah 18h outdb OUTDB
|
||||
612h 209h 505h 0 3b02h 18h outi OUTI
|
||||
612h 209h 505h 0 3a02h 18h outib OUTIB
|
||||
305h 209h 0 0 9700h 0
|
||||
309h 209h 0 0 1700h 0
|
||||
0a0ah 209h 0 0 5700h 0 pop POP
|
||||
306h 209h 0 0 9500h 0
|
||||
309h 209h 0 0 1500h 0
|
||||
0a0ah 209h 0 0 5500h 0 popl POPL
|
||||
209h 305h 0 0 9300h 0
|
||||
209h 309h 0 0 1300h 0
|
||||
209h 0a0ah 0 0 5300h 0
|
||||
209h 1d08h 0 0 0d09h 0 push PUSH
|
||||
209h 306h 0 0 9100h 0
|
||||
209h 309h 0 0 1100h 0
|
||||
209h 0a0ah 0 0 5100h 0 pushl PUSHL
|
||||
205h 308h 0 0 0a300h 0
|
||||
209h 308h 0 0 2300h 0
|
||||
90ah 308h 0 0 6300h 0
|
||||
505h 305h 0 0 2300h 10h res RES
|
||||
204h 1108h 0 0 0a200h 0
|
||||
209h 1108h 0 0 2200h 0
|
||||
90ah 1108h 0 0 6200h 0
|
||||
504h 1105h 0 0 2200h 10h resb RESB
|
||||
0f0eh 0 0 0 8d03h 0
|
||||
0f0eh 0f0eh 0 0 8d03h 0
|
||||
0f0eh 0f0eh 0f0eh 0 8d03h 0
|
||||
0f0eh 0f0eh 0f0eh 0f0eh 8d03h 0 resflg RESFLG
|
||||
0 0 0 0 9e08h 0
|
||||
30dh 0 0 0 9e00h 0 ret RET
|
||||
205h 0 0 0 0b300h 0
|
||||
205h 1f08h 0 0 0b300h 0 rl RL
|
||||
204h 0 0 0 0b200h 0
|
||||
204h 1f08h 0 0 0b200h 0 rlb RLB
|
||||
205h 0 0 0 0b308h 0
|
||||
205h 1f08h 0 0 0b308h 0 rlc RLC
|
||||
204h 0 0 0 0b208h 0
|
||||
204h 1f08h 0 0 0b208h 0 rlcb RLCB
|
||||
304h 204h 0 0 0be00h 0 rldb RLDB
|
||||
205h 0 0 0 0b304h 0
|
||||
205h 1f08h 0 0 0b304h 0 rr RR
|
||||
204h 0 0 0 0b204h 0
|
||||
204h 1f08h 0 0 0b204h 0 rrb RRB
|
||||
205h 0 0 0 0b30ch 0
|
||||
205h 1f08h 0 0 0b30ch 0 rrc RRC
|
||||
204h 0 0 0 0b20ch 0
|
||||
204h 1f08h 0 0 0b20ch 0 rrcb RRCB
|
||||
304h 204h 0 0 0bc00h 0 rrdb RRDB
|
||||
305h 205h 0 0 0b700h 0 sbc SBC
|
||||
304h 204h 0 0 0b600h 0 sbcb SBCB
|
||||
808h 0 0 0 7f00h 0 sc SC
|
||||
205h 505h 0 0 0b30bh 10h sda SDA
|
||||
204h 505h 0 0 0b20bh 10h sdab SDAB
|
||||
206h 505h 0 0 0b30fh 10h sdal SDAL
|
||||
205h 505h 0 0 0b303h 10h sdl SDL
|
||||
204h 505h 0 0 0b203h 10h sdlb SDLB
|
||||
206h 505h 0 0 0b307h 10h sdll SDLL
|
||||
205h 308h 0 0 0a500h 0
|
||||
209h 308h 0 0 2500h 0
|
||||
90ah 308h 0 0 6500h 0
|
||||
505h 305h 0 0 2500h 10h set SET
|
||||
204h 1108h 0 0 0a400h 0
|
||||
209h 1108h 0 0 2400h 0
|
||||
90ah 1108h 0 0 6400h 0
|
||||
504h 1105h 0 0 2400h 10h setb SETB
|
||||
0f0eh 0 0 0 8d01h 0
|
||||
0f0eh 0f0eh 0 0 8d01h 0
|
||||
0f0eh 0f0eh 0f0eh 0 8d01h 0
|
||||
0f0eh 0f0eh 0f0eh 0f0eh 8d01h 0 setflg SETFLG
|
||||
205h 1d03h 0 0 3b05h 0 sin SIN
|
||||
204h 1d03h 0 0 3a05h 0 sinb SINB
|
||||
609h 212h 505h 0 3b09h 18h sind SIND
|
||||
609h 212h 505h 0 3a09h 18h sindb SINDB
|
||||
609h 212h 505h 0 3b09h 10h sindr SINDR
|
||||
609h 212h 505h 0 3a09h 10h sindrb SINDRB
|
||||
609h 212h 505h 0 3b01h 18h sini SINI
|
||||
609h 212h 505h 0 3a01h 18h sinib SINIB
|
||||
609h 212h 505h 0 3b01h 10h sinir SINIR
|
||||
609h 212h 505h 0 3a01h 10h sinirb SINIRB
|
||||
205h 0 0 0 0b309h 11h
|
||||
205h 1d08h 0 0 0b309h 0 sla SLA
|
||||
204h 0 0 0 0b209h 11h
|
||||
204h 1d08h 0 0 0b209h 0 slab SLAB
|
||||
206h 0 0 0 0b30dh 11h
|
||||
206h 1d08h 0 0 0b30dh 0 slal SLAL
|
||||
205h 0 0 0 0b301h 11h
|
||||
205h 1d08h 0 0 0b301h 0 sll SLL
|
||||
204h 0 0 0 0b201h 11h
|
||||
204h 1d08h 0 0 0b201h 0 sllb SLLB
|
||||
206h 0 0 0 0b305h 11h
|
||||
206h 1d08h 0 0 0b305h 0 slll SLLL
|
||||
612h 209h 505h 0 3b0bh 10h sotdr SOTDR
|
||||
612h 209h 505h 0 3a0bh 10h sotdrb SOTDRB
|
||||
612h 209h 505h 0 3b03h 10h sotir SOTIR
|
||||
612h 209h 505h 0 3a03h 10h sotirb SOTIRB
|
||||
1d03h 205h 0 0 3b07h 0 sout SOUT
|
||||
1d03h 204h 0 0 3a07h 0 soutb SOUTB
|
||||
612h 209h 505h 0 3b0bh 18h soutd SOUTD
|
||||
612h 209h 505h 0 3a0bh 18h soutdb SOUTDB
|
||||
612h 209h 505h 0 3b03h 18h souti SOUTI
|
||||
612h 209h 505h 0 3a03h 18h soutib SOUTIB
|
||||
205h 0 0 0 0b309h 31h
|
||||
205h 1d08h 0 0 0b309h 20h sra SRA
|
||||
204h 0 0 0 0b209h 31h
|
||||
204h 1d08h 0 0 0b209h 20h srab SRAB
|
||||
206h 0 0 0 0b30dh 31h
|
||||
206h 1d08h 0 0 0b30dh 20h sral SRAL
|
||||
205h 0 0 0 0b301h 31h
|
||||
205h 1d08h 0 0 0b301h 20h srl SRL
|
||||
204h 0 0 0 0b201h 31h
|
||||
204h 1d08h 0 0 0b201h 20h srlb SRLB
|
||||
206h 0 0 0 0b305h 31h
|
||||
206h 1d08h 0 0 0b305h 20h srll SRLL
|
||||
305h 205h 0 0 8300h 0
|
||||
305h 1d08h 0 0 300h 0
|
||||
305h 209h 0 0 300h 0
|
||||
305h 90ah 0 0 4300h 0 sub SUB
|
||||
304h 204h 0 0 8200h 0
|
||||
304h 1c08h 0 0 200h 0
|
||||
304h 209h 0 0 200h 0
|
||||
304h 90ah 0 0 4200h 0 subb SUBB
|
||||
306h 206h 0 0 9200h 0
|
||||
306h 1e08h 0 0 1200h 0
|
||||
306h 209h 0 0 1200h 0
|
||||
306h 90ah 0 0 5200h 0 subl SUBL
|
||||
30dh 205h 0 0 0af00h 0 tcc TCC
|
||||
30dh 204h 0 0 0ae00h 0 tccb TCCB
|
||||
205h 0 0 0 8d04h 0
|
||||
209h 0 0 0 0d04h 0
|
||||
90ah 0 0 0 4d04h 0 test TEST
|
||||
204h 0 0 0 8c04h 0
|
||||
209h 0 0 0 0c04h 0
|
||||
90ah 0 0 0 4c04h 0 testb TESTB
|
||||
206h 0 0 0 9c08h 0
|
||||
209h 0 0 0 1c08h 0
|
||||
90ah 0 0 0 5c08h 0 testl TESTL
|
||||
209h 609h 505h 0 0b808h 10h trdb TRDB
|
||||
209h 609h 505h 0 0b80ch 10h trdrb TRDRB
|
||||
209h 609h 505h 0 0b800h 10h trib TRIB
|
||||
209h 609h 505h 0 0b804h 10h trirb TRIRB
|
||||
209h 609h 505h 0 0b80ah 10h trtdb TRTDB
|
||||
209h 609h 505h 0 0b80eh 1eh trtdrb TRTDRB
|
||||
209h 609h 505h 0 0b802h 10h trtib TRTIB
|
||||
209h 609h 505h 0 0b806h 1eh trtirb TRTIRB
|
||||
205h 0 0 0 8d06h 0
|
||||
209h 0 0 0 0d06h 0
|
||||
90ah 0 0 0 4d06h 0 tset TSET
|
||||
204h 0 0 0 8c06h 0
|
||||
209h 0 0 0 0c06h 0
|
||||
90ah 0 0 0 4c06h 0 tsetb TSETB
|
||||
305h 205h 0 0 8900h 0
|
||||
305h 1d08h 0 0 900h 0
|
||||
305h 209h 0 0 900h 0
|
||||
305h 90ah 0 0 4900h 0 xor XOR
|
||||
304h 204h 0 0 8800h 0
|
||||
304h 1c08h 0 0 800h 0
|
||||
304h 209h 0 0 800h 0
|
||||
304h 90ah 0 0 4800h 0 xorb XORB
|
||||
|
||||
1 .end .END
|
||||
2 .equ .EQU
|
||||
3 .input .INPUT
|
||||
4 .byte .BYTE
|
||||
5 .word .WORD
|
||||
6 .set .SET
|
||||
7 .block .BLOCK
|
||||
8 .org .ORG
|
||||
9 .clist .CLIST
|
||||
10 .sect .SECT
|
||||
11 .space .SPACE
|
||||
12 .stitle .STITLE
|
||||
13 .title .TITLE
|
||||
14 .list .LIST
|
||||
15 .else .ELSE
|
||||
16 .endif .ENDIF
|
||||
17 .if .IF
|
||||
18 .global .GLOBAL
|
||||
19 .abs .ABS
|
||||
20 .align .ALIGN
|
||||
21 .within .WITHIN
|
||||
22 .macro .MACRO
|
||||
23 .endm .ENDM
|
||||
24 .long .LONG
|
||||
25 .eject .EJECT
|
||||
26 .common .COMMON
|
||||
28 .endr .ENDR
|
||||
29 .repeat .REPEAT
|
||||
30 .error .ERROR
|
||||
31 .exit .EXIT
|
||||
33 .warn .WARN
|
||||
|
||||
100h $
|
||||
1000h rh0 RH0
|
||||
1001h rh1 RH1
|
||||
1002h rh2 RH2
|
||||
1003h rh3 RH3
|
||||
1004h rh4 RH4
|
||||
1005h rh5 RH5
|
||||
1006h rh6 RH6
|
||||
1007h rh7 RH7
|
||||
1008h rl0 RL0
|
||||
1009h rl1 RL1
|
||||
100ah rl2 RL2
|
||||
100bh rl3 RL3
|
||||
100ch rl4 RL4
|
||||
100dh rl5 RL5
|
||||
100eh rl6 RL6
|
||||
100fh rl7 RL7
|
||||
1100h r0 R0
|
||||
1101h r1 R1
|
||||
1102h r2 R2
|
||||
1103h r3 R3
|
||||
1104h r4 R4
|
||||
1105h r5 R5
|
||||
1106h r6 R6
|
||||
1107h r7 R7
|
||||
1108h r8 R8
|
||||
1109h r9 R9
|
||||
110ah r10 R10
|
||||
110bh r11 R11
|
||||
110ch r12 R12
|
||||
110dh r13 R13
|
||||
110eh r14 R14
|
||||
110fh r15 R15
|
||||
1200h rr0 RR0
|
||||
1202h rr2 RR2
|
||||
1204h rr4 RR4
|
||||
1206h rr6 RR6
|
||||
1208h rr8 RR8
|
||||
120ah rr10 RR10
|
||||
120ch rr12 RR12
|
||||
120eh rr14 RR14
|
||||
1300h rq0 RQ0
|
||||
1304h rq4 RQ4
|
||||
1308h rq8 RQ8
|
||||
130ch rq12 RQ12
|
||||
1401h lt LT
|
||||
1402h le LE
|
||||
1403h ule ULE
|
||||
1404h ov OV pe PE p P v V
|
||||
1405h mi MI s S
|
||||
1406h z Z eq EQ
|
||||
1407h c C ult ULT
|
||||
1409h ge GE
|
||||
140ah gt GT
|
||||
140bh ugt UGT
|
||||
140ch nov NOV po PO
|
||||
140dh pl PL
|
||||
140eh nz NZ ne NE
|
||||
140fh nc NC uge UGE
|
||||
150eh nvi NVI
|
||||
150dh vi VI
|
||||
1602h fcw FCW
|
||||
1603h refresh REFRESH
|
||||
1604h psapseg PSAPSEG
|
||||
1605h psapoff PSAPOFF psap PSAP
|
||||
1606h nspseg NSPSEG
|
||||
1607h nspoff NSPOFF nsp NSP
|
||||
1701h flags FLAGS
|
||||
; @(#)asz8k.pdc 3.1
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
#include "asz8k.h"
|
||||
|
||||
/*
|
||||
* Version 3.3, 8/27/82. Changes to accomodate 8086 version.
|
||||
*/
|
||||
static char ident[] = "@(#)asz8kglo.c 3.3";
|
||||
|
||||
/*
|
||||
* Global variable definitions and initializations specific to asz8k.
|
||||
*/
|
||||
struct chent chtab[] = { /* table of single-character tokens */
|
||||
{'~',TKUNOP},
|
||||
{'*',TKMULOP,TVMUL},
|
||||
{'/',TKMULOP,TVDIV},
|
||||
{'%',TKMULOP,TVMOD},
|
||||
{'+',TKADDOP,TVADD},
|
||||
{'-',TKADDOP,TVSUB},
|
||||
{'=',TKRELOP,TVEQ},
|
||||
{'&',TKANDOP},
|
||||
{'^',TKXOROP},
|
||||
{'|',TKOROP},
|
||||
{'(',TKLPAR},
|
||||
{')',TKRPAR},
|
||||
{'#',TKPOUND},
|
||||
{'@',TKAT},
|
||||
{',',TKCOM},
|
||||
{':',TKCOLON},
|
||||
{'\n',TKEOL},
|
||||
{-1,TKEOF},
|
||||
{0,TKERR}
|
||||
};
|
||||
int extoff = 2;
|
||||
uns minaln = 1;
|
||||
struct operand optab[OPMAX] = 0;
|
||||
char segflg = 0;
|
||||
char oflag = 0;
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
int ptab[] {02,0,01,040400,040401,040402,040403,0100030,0100042,
|
||||
0100054,0100066,0100100,0100110,040404,0100113,0100116,040405,
|
||||
040406,040407,040410,040411,041012,041012,024,026,040400,
|
||||
040401,040402,0100030,0100042,0100066,041013,041013,024,
|
||||
026,040400,040401,040402,0100030,0100042,0100066,041014,
|
||||
0100150,035,040,040400,040401,040402,040403,0100030,0100042,
|
||||
0100066,0100153,050,040,040400,040401,040402,040403,0100030,
|
||||
0100042,0100066,041015,052,040,040400,040401,040402,040403,
|
||||
0100030,0100042,0100066,054,041016,041017,057,0420,0421,
|
||||
057,0422,0423,052,0100160,0424,062,0100173,0425,064,0100205,
|
||||
0426,066,0100221,0100232,0427,071,0100241,073,0100246,0430,
|
||||
057,0431,0100255,033,0100257,057,01032,0100255,075,0100160,
|
||||
041433,0100262,0100,040,040400,040401,040402,040403,0100030,
|
||||
0100042,0100066,0100265,0100265,0102,040,040400,040401,040402,
|
||||
040403,0100030,0100042,0100066,041434,0103,040,040400,040401,
|
||||
040402,040403,0100030,0100042,0100066,0100270,0100270,0100270,
|
||||
0105,026,040400,040401,040402,0100030,0100042,0100066,0100273,
|
||||
073,026,040400,040401,040402,0100030,0100042,0100066,0110,
|
||||
041435,041436,041436,024,026,040400,040401,040402,0100030,
|
||||
0100042,0100066,0112,0100276,0114,0100302,0100312,062,0100173,
|
||||
01437,064,0100205,01440,073,0100246,01441,0117,0100221,01442,
|
||||
076,042043,0100314,052,040,040400,040401,040402,040403,0100030,
|
||||
0100042,0100066,076,042044,076,042445};
|
||||
|
||||
int ntdflt[] {0100002,040446,0100121,0100124,0100127,0100127,0100132,
|
||||
0100136,0100140,0100140,0100140,0100143,040447,0100146};
|
||||
|
||||
int semtab[] {05015,05014,05013,03416,0463,0466,0475,0476,0477,0500,
|
||||
04403,04402,0505,0467,0471,0472,0464,06501,0465,06502,05400,
|
||||
01000,01400,02400,03000,0417,0504,05012,02007,02420,04005,
|
||||
01010,01404,03006,02411,06103,0474,0473,01,0470};
|
||||
|
||||
char scntab[] {0377,01,02,03,04,05,07,013,014,016,017,020,021,022,023,
|
||||
024,025,026,027,0376,011,012,01,02,03,05,07,014,0376,013,014,
|
||||
0377,01,02,03,04,05,07,014,0376,02,0377,013,0377,021,022,0376,
|
||||
0,014,0376,012,0377,011,0377,07,010,0377,010,0376,06,0377,013,
|
||||
015,0376,03,0377,04,05,0377,010,011,012,04,0376,021,0376,016,
|
||||
021,0376,07,0377};
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
|
||||
/*
|
||||
* Version 3.3, 8/20/82. Made colon a real token and got rid of the TKLAB
|
||||
* token type, to accomodate 8086 version.
|
||||
*
|
||||
* Version 3.2, 7/5/82. Performance enhancements.
|
||||
*/
|
||||
|
||||
static char ident[] = "@(#)a.token.c 3.3";
|
||||
|
||||
/*
|
||||
* stresc - Processes a string escape. This routine is called after the
|
||||
* escape character (normally '\') has been seen. It scans off the remainder
|
||||
* of the escape and returns its value.
|
||||
*/
|
||||
stresc() {
|
||||
|
||||
int ct,
|
||||
val;
|
||||
|
||||
scanc();
|
||||
if('0'<=ch && ch<='7') { /* an octal escape */
|
||||
val = 0; ct = 3;
|
||||
do {
|
||||
val = (val<<3)+ch-'0';
|
||||
scanc();
|
||||
} while(--ct>0 && '0'<=ch && ch<='7');
|
||||
unscanc();
|
||||
return(val);
|
||||
}
|
||||
switch(ch) { /* a single-character escape */
|
||||
|
||||
case 'b':
|
||||
case 'B':
|
||||
return('\b');
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
return('\f');
|
||||
|
||||
case 'n':
|
||||
case 'N':
|
||||
return('\n');
|
||||
|
||||
case 'r':
|
||||
case 'R':
|
||||
return('\r');
|
||||
|
||||
case 't':
|
||||
case 'T':
|
||||
return('\t');
|
||||
|
||||
default:
|
||||
return(ch);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* token - Scans the next token and returns its type. Also sets up the
|
||||
* token's type and value information in the global cells toktyp, tokval,
|
||||
* and tokstr.
|
||||
*/
|
||||
token() {
|
||||
|
||||
int c;
|
||||
struct chent *chp;
|
||||
char radix;
|
||||
char *strp;
|
||||
|
||||
strp = tokstr;
|
||||
scanc();
|
||||
#ifdef DEBUG
|
||||
printf("%c(%o)",ch,ch);
|
||||
#endif
|
||||
if(white(ch)) { /* white space */
|
||||
do {
|
||||
scanc();
|
||||
} while(white(ch));
|
||||
if(ch!=';' && ch!='\n') {
|
||||
unscanc();
|
||||
return(toktyp = TKSPC);
|
||||
}
|
||||
}
|
||||
if(ch == ';') { /* comment */
|
||||
do {
|
||||
scanc();
|
||||
} while(ch != '\n');
|
||||
return(toktyp = TKEOL);
|
||||
}
|
||||
if('a'<=ch&&ch<='z' || 'A'<=ch&&ch<='Z' || ch=='$' || ch=='_'
|
||||
|| ch=='.') { /* symbol */
|
||||
do {
|
||||
if(strp < tokstr+SYMSIZ) *strp++ = ch;
|
||||
scanc();
|
||||
} while('a'<=ch&&ch<='z' || 'A'<=ch&&ch<='Z' ||
|
||||
'0'<=ch&&ch<='9' || ch=='$' || ch=='_' || ch=='.');
|
||||
*strp = '\0';
|
||||
unscanc();
|
||||
return(toktyp = TKSYM);
|
||||
}
|
||||
if('0'<=ch && ch<='9') { /* constant */
|
||||
do {
|
||||
*strp++ = ch;
|
||||
scanc();
|
||||
if('A'<=ch && ch<='Z') ch += 'a'-'A';
|
||||
} while('0'<=ch&&ch<='9' || 'a'<=ch&&ch<='z');
|
||||
unscanc();
|
||||
*strp = '\0';
|
||||
c = *--strp;
|
||||
if('0'<=c && c<='9') radix = 10;
|
||||
else {
|
||||
switch(c) {
|
||||
|
||||
case 'b':
|
||||
radix = 2;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
radix = 10;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
radix = 16;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'q':
|
||||
radix = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
return(toktyp = TKERR);
|
||||
}
|
||||
*strp = '\0';
|
||||
}
|
||||
tokval = 0; strp = tokstr;
|
||||
while(c = *strp++) {
|
||||
if('0'<=c && c<='9') c -= '0';
|
||||
else c += 10-'a';
|
||||
if(c >= radix) return(toktyp = TKERR);
|
||||
tokval = tokval*radix+c;
|
||||
}
|
||||
return(toktyp = TKCON);
|
||||
}
|
||||
if(ch == '\'') { /* character constant */
|
||||
scanc();
|
||||
if(ch == '\n') {
|
||||
unscanc();
|
||||
return(toktyp = TKERR);
|
||||
}
|
||||
tokval = (ch==escchr)?stresc():ch;
|
||||
scanc();
|
||||
if(ch != '\'') {
|
||||
unscanc();
|
||||
return(toktyp = TKERR);
|
||||
}
|
||||
return(toktyp = TKCON);
|
||||
}
|
||||
if(ch == '"') { /* quoted string */
|
||||
scanc();
|
||||
while(ch != '"') {
|
||||
if(ch == '\n') {
|
||||
unscanc();
|
||||
return(toktyp = TKERR);
|
||||
}
|
||||
if(strp < tokstr+STRSIZ) {
|
||||
*strp++ = (ch==escchr)?stresc():ch;
|
||||
}
|
||||
scanc();
|
||||
}
|
||||
*strp = '\0';
|
||||
tokval = strp-tokstr;
|
||||
return(toktyp = TKSTR);
|
||||
}
|
||||
if(ch == '<') {
|
||||
scanc();
|
||||
if(ch == '<') {
|
||||
tokval = TVSHL;
|
||||
return(toktyp = TKMULOP);
|
||||
}
|
||||
if(ch == '=') {
|
||||
tokval = TVLE;
|
||||
return(toktyp = TKRELOP);
|
||||
}
|
||||
unscanc();
|
||||
tokval = TVLT;
|
||||
return(toktyp = TKRELOP);
|
||||
}
|
||||
if(ch == '>') {
|
||||
scanc();
|
||||
if(ch == '>') {
|
||||
tokval = TVSHR;
|
||||
return(toktyp = TKMULOP);
|
||||
}
|
||||
if(ch == '=') {
|
||||
tokval = TVGE;
|
||||
return(toktyp = TKRELOP);
|
||||
}
|
||||
unscanc();
|
||||
tokval = TVGT;
|
||||
return(toktyp = TKRELOP);
|
||||
}
|
||||
if(ch == '!') {
|
||||
scanc();
|
||||
if(ch == '=') {
|
||||
tokval = TVNE;
|
||||
return(toktyp = TKRELOP);
|
||||
}
|
||||
unscanc();
|
||||
return(toktyp = TKERR);
|
||||
}
|
||||
/* single character token */
|
||||
for(chp=chtab ; chp->ch_chr ; chp++) {
|
||||
if(ch == chp->ch_chr) break;
|
||||
}
|
||||
tokval = chp->ch_val;
|
||||
return(toktyp = chp->ch_typ);
|
||||
}
|
||||
|
||||
/*
|
||||
* xscanc - Takes care of the cases of character scanning which would be
|
||||
* difficult for the macro scanc() to handle. Namely, these are end of line
|
||||
* processing and continuation processing.
|
||||
*/
|
||||
xscanc() {
|
||||
|
||||
top:
|
||||
if(ch == '\0') {
|
||||
getline();
|
||||
ch = *scanpt++;
|
||||
goto top;
|
||||
}
|
||||
if(ch==escchr && *scanpt=='\n') { /* continuation */
|
||||
scanpt++;
|
||||
putline();
|
||||
ch = *scanpt++;
|
||||
goto top;
|
||||
}
|
||||
return(ch);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
|
||||
static char ident[] = "@(#)a.vm.c 3.1";
|
||||
|
||||
/*
|
||||
* getbuf - Returns a pointer to a buffer which contains the specified
|
||||
* virtual address. Pages the buffers on a LRU basis.
|
||||
*/
|
||||
struct vmbuf *
|
||||
getbuf(adr) vmadr adr; {
|
||||
|
||||
static int limblk = 0; /* file high water mark */
|
||||
reg struct vmbuf *cb, *pb;
|
||||
reg uns vbn;
|
||||
|
||||
#ifdef STATS
|
||||
vmgct++;
|
||||
#endif
|
||||
vbn = adr>>BLKLOG;
|
||||
pb = &vmhead; cb = vmhead;
|
||||
while(cb->vm_blk!=vbn && cb->vm_lnk) {
|
||||
pb = cb; cb = cb->vm_lnk;
|
||||
}
|
||||
if(cb->vm_blk!=vbn) { /* must commandeer a buffer */
|
||||
if(cb->vm_flg&VMDIR) { /* write out old contents */
|
||||
lseek(vmfd,(long)cb->vm_blk<<BLKLOG,0);
|
||||
write(vmfd,cb->vm_mem,1<<BLKLOG);
|
||||
if(cb->vm_blk >= limblk) limblk = cb->vm_blk+1;
|
||||
cb->vm_flg &= ~VMDIR;
|
||||
#ifdef STATS
|
||||
vmwct++;
|
||||
#endif
|
||||
}
|
||||
if(vbn < limblk) { /* read from disk */
|
||||
lseek(vmfd,(long)vbn<<BLKLOG,0);
|
||||
read(vmfd,cb->vm_mem,1<<BLKLOG);
|
||||
#ifdef STATS
|
||||
vmrct++;
|
||||
#endif
|
||||
}
|
||||
cb->vm_blk = vbn;
|
||||
}
|
||||
pb->vm_lnk = cb->vm_lnk; cb->vm_lnk = vmhead; vmhead = cb;
|
||||
return(cb);
|
||||
}
|
||||
|
||||
/*
|
||||
* rfetch - Fetches a specified virtual address for reading, and returns
|
||||
* a pointer to the in-core copy of the address.
|
||||
*/
|
||||
char *
|
||||
rfetch(adr) vmadr adr; {
|
||||
|
||||
return(&getbuf(adr)->vm_mem[adr&(1<<BLKLOG)-1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* valloc - Allocates a region of virtual memory of the specified size,
|
||||
* and returns the vm address of it. The region is guaranteed to reside
|
||||
* entirely within a single block.
|
||||
*/
|
||||
vmadr
|
||||
valloc(size) uns size; {
|
||||
|
||||
vmadr base, blklim;
|
||||
|
||||
blklim = (virtop|(1<<BLKLOG)-1)+1;
|
||||
if(virtop+size > blklim) virtop = blklim;
|
||||
base = virtop; virtop += size;
|
||||
return(base);
|
||||
}
|
||||
|
||||
/*
|
||||
* vinit - Opens the virtual memory file.
|
||||
*/
|
||||
vinit() {
|
||||
|
||||
close(creatb("VM.TMP",0666));
|
||||
if((vmfd=openb("VM.TMP",2)) == -1) {
|
||||
fprintf(ERROR,"Cannot reopen vm file\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* wfetch - Fetches a specified virtual address for writing, and returns
|
||||
* a pointer to the in-core copy of the address.
|
||||
*/
|
||||
char *
|
||||
wfetch(adr) vmadr adr; {
|
||||
|
||||
reg struct vmbuf *bp;
|
||||
|
||||
(bp=getbuf(adr))->vm_flg |= VMDIR;
|
||||
return(&bp->vm_mem[adr&(1<<BLKLOG)-1]);
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
#include "stdio.h"
|
||||
/*
|
||||
* Changed to use the Standard I/O library 9/13/82 FZ
|
||||
*/
|
||||
#include "acom.h"
|
||||
#include "obj.h"
|
||||
|
||||
static char ident[] = "@(#)a.xref.c 3.1";
|
||||
|
||||
/*
|
||||
* putxref - Prints out the cross reference listing.
|
||||
*/
|
||||
putxref() {
|
||||
|
||||
struct sytab *syp;
|
||||
struct xref *xrp;
|
||||
vmadr sym, xr, xrtail;
|
||||
uns llcol;
|
||||
char undef;
|
||||
|
||||
strcpy(titl2,"Cross Reference Listing"); linect = 0;
|
||||
sysort();
|
||||
for(sym=syhtab[0] ; sym!=0 ; sym=syp->sy_lnk) {
|
||||
syp = (struct sytab *)rfetch(sym);
|
||||
xrtail = syp->sy_xlk;
|
||||
undef = syp->sy_typ==STUND || syp->sy_rel==RBUND;
|
||||
if(syp->sy_typ==STKEY || syp->sy_typ==STSEC ||
|
||||
undef&&xrtail==0) continue;
|
||||
pgcheck();
|
||||
fprintf(LIST,"%-8.8s ",syp->sy_str);
|
||||
if(undef) fprintf(LIST," U");
|
||||
else if(syp->sy_atr&SAMUD) fprintf(LIST," M");
|
||||
else {
|
||||
fprintf(LIST,"%8X",(long)syp->sy_val);
|
||||
if(syp->sy_rel == RBABS) fputc(' ',LIST);
|
||||
else if(syp->sy_rel >= RBEXT) fputc('X',LIST);
|
||||
else fputc('\'',LIST);
|
||||
}
|
||||
if(xrtail != 0) { /* we have some xref entries */
|
||||
xrp = (struct xref *)rfetch(xrtail);
|
||||
llcol = 18;
|
||||
do {
|
||||
xr = xrp->xr_lnk;
|
||||
xrp = (struct xref *)rfetch(xr);
|
||||
if(llcol > rmarg-8) { /* start new line */
|
||||
fputc('\n',LIST);
|
||||
pgcheck();
|
||||
fprintf(LIST," ");
|
||||
llcol = 18;
|
||||
}
|
||||
fprintf(LIST," %3d-%2d%c",xrp->xr_pl>>6&0777,
|
||||
xrp->xr_pl&077,xrp->xr_pl&XRDEF?'*':' ');
|
||||
llcol += 8;
|
||||
} while(xr != xrtail);
|
||||
syp = (struct sytab *)rfetch(sym);
|
||||
}
|
||||
fputc('\n',LIST);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* symerge - Merges the two specified symbol table hash chains, and
|
||||
* returns a pointer to the resulting chain.
|
||||
*/
|
||||
vmadr
|
||||
symerge(a,b) vmadr a, b; {
|
||||
|
||||
struct sytab *ap, *bp;
|
||||
vmadr pa, r, t;
|
||||
|
||||
if(a == 0) return(b);
|
||||
if(b == 0) return(a);
|
||||
/*
|
||||
* Initialize so that the first element of chain a is less than the
|
||||
* first element of chain b.
|
||||
*
|
||||
* CAUTION -- This code requires an lru virtual memory buffer pool
|
||||
* of at least 3 blocks.
|
||||
*/
|
||||
if(symcmp((ap=(struct sytab *)rfetch(a))->sy_str,
|
||||
(bp=(struct sytab *)rfetch(b))->sy_str) > 0) { /* exchange a and b */
|
||||
t = a; a = b; b = t; ap = bp;
|
||||
}
|
||||
r = a; /* initialize result with smallest element */
|
||||
/*
|
||||
* Attach successive smallest portions of the chains onto the result
|
||||
* until there is nothing left.
|
||||
*/
|
||||
do {
|
||||
/*
|
||||
* Walk along chain a until its end is reached or it is
|
||||
* no longer the smaller of the two.
|
||||
*/
|
||||
do {
|
||||
pa = a;
|
||||
} while((a=ap->sy_lnk)!=0 &&
|
||||
symcmp((ap=(struct sytab *)rfetch(a))->sy_str,
|
||||
(bp=(struct sytab *)rfetch(b))->sy_str)<=0);
|
||||
/*
|
||||
* Link b to the end of the result, then exchange the chains
|
||||
* so that a again points to the smaller of the two.
|
||||
*/
|
||||
((struct sytab *)wfetch(pa))->sy_lnk = b;
|
||||
t = a; a = b; b = t; ap = bp;
|
||||
} while(b != 0);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/*
|
||||
* sysort - Sorts the symbol table into a single alphabetical chain whose
|
||||
* head is syhtab[0].
|
||||
*/
|
||||
sysort() {
|
||||
|
||||
uns halfi, i, j;
|
||||
|
||||
for(i=1<<SHSHLOG ; i>1 ; i=halfi) {
|
||||
halfi = i>>1;
|
||||
for(j=0 ; j<halfi ; j++) {
|
||||
syhtab[j] = symerge(syhtab[j],syhtab[j+halfi]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* xref - Adds a cross reference entry of the specified type for the
|
||||
* specified symbol.
|
||||
*/
|
||||
xref(sym,type) vmadr sym; int type; {
|
||||
|
||||
struct sytab *syp;
|
||||
struct xref *oxp, *nxp;
|
||||
vmadr nxr;
|
||||
int pl;
|
||||
|
||||
if(!(xflag&&pass2)) return;
|
||||
pl = curxpl|type;
|
||||
/*
|
||||
* CAUTION -- This code requires an lru virtual memory buffer pool
|
||||
* of at least 3 blocks.
|
||||
*/
|
||||
syp = (struct sytab *)wfetch(sym);
|
||||
if(syp->sy_xlk == 0) { /* first xref entry for this symbol */
|
||||
if((uns)virtop&01) virtop++; /* force alignment */
|
||||
nxp = (struct xref *)wfetch(nxr=valloc(sizeof(struct xref)));
|
||||
nxp->xr_lnk = nxr;
|
||||
} else { /* add to existing circular list of xref entries */
|
||||
oxp = (struct xref *)wfetch(syp->sy_xlk);
|
||||
if(oxp->xr_pl == pl) return; /* no duplicate xrefs */
|
||||
if((uns)virtop&01) virtop++; /* force alignment */
|
||||
nxp = (struct xref *)wfetch(nxr=valloc(sizeof(struct xref)));
|
||||
nxp->xr_lnk = oxp->xr_lnk; oxp->xr_lnk = nxr;
|
||||
}
|
||||
nxp->xr_pl = pl;
|
||||
syp->sy_xlk = nxr;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* @(#)obj.h 3.3
|
||||
*
|
||||
* Unidot Object Format.
|
||||
*
|
||||
* Copyright 1981 by John D. Polstra and Robert M. McClure.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Object file block types.
|
||||
*/
|
||||
#define OBOST 1 /* object start block */
|
||||
#define OBLST 2 /* library start block */
|
||||
#define OBSEC 3 /* sections block */
|
||||
#define OBGLO 4 /* global symbols block */
|
||||
#define OBLOC 5 /* local symbols block */
|
||||
#define OBTXT 6 /* text block */
|
||||
#define OBBSZ 7 /* bssz block */
|
||||
#define OBTRA 8 /* transfer address block */
|
||||
#define OBLIX 9 /* library index block */
|
||||
#define OBLND 10 /* library end block */
|
||||
#define OBOND 11 /* object end block */
|
||||
#define OBMOD 12 /* module name block */
|
||||
/*
|
||||
* Object file relocation actions.
|
||||
*/
|
||||
#define RANOP 0 /* no relocation operation */
|
||||
#define RAA16 0x8000 /* add base to word field */
|
||||
#define RAA8 0x4000 /* add base to byte field */
|
||||
#define RAA32 0xc000 /* add base to long field */
|
||||
#define RAA16M 0x2000 /* add base to word field (MSB first) */
|
||||
#define RAA32M 0xa000 /* add base to long field (MSB first) */
|
||||
#define RAZSS 0x6000 /* relocate Z8001 short seg address */
|
||||
#define RAZLS 0xe000 /* relocate Z8001 long seg address */
|
||||
#define RASEG 0x1000 /* 8086 segment relocation */
|
||||
#define RAOFF 0x9000 /* 8086 offset relocation */
|
||||
#define RAJ11 0x5000 /* 8051 11-bit jump target relocation */
|
||||
#define RASOFF 0xd000 /* 8086 short offset relocation */
|
||||
#define RAZOF 0x3000 /* relocate Z8001 16-bit offset */
|
||||
#define RAMSK 0xf000 /* mask for relocation action field */
|
||||
/*
|
||||
* Object file relocation bases.
|
||||
*/
|
||||
#define RBABS 0 /* absolute */
|
||||
#define RBSEC 1 /* section */
|
||||
#define RBUND 255 /* undefined */
|
||||
#define RBEXT 256 /* external */
|
||||
#define RBMSK 0x0fff /* mask for relocation base field */
|
||||
/*
|
||||
* Section attributes.
|
||||
*/
|
||||
#define SENOX 0001 /* not executable */
|
||||
#define SENOW 0002 /* not writeable */
|
||||
#define SENOR 0004 /* not readable */
|
||||
#define SECOM 0010 /* common */
|
||||
#define SEFIX 0020 /* base address fixed */
|
||||
@@ -0,0 +1,489 @@
|
||||
.title "Asz8k Assembler Test Program"
|
||||
.stitle "Opcodes in Alphabetical Order"
|
||||
__text .sect
|
||||
|
||||
adc r3,r5
|
||||
adcb rh3,rh5
|
||||
add r3,#1234h
|
||||
add r3,@r5
|
||||
add r3,foo
|
||||
add r3,foo(r5)
|
||||
add r3,r5
|
||||
addb rh3,#12h
|
||||
addb rh3,@r5
|
||||
addb rh3,foo
|
||||
addb rh3,foo(r5)
|
||||
addb rh3,rh5
|
||||
addl rr2,#12345678h
|
||||
addl rr2,@r5
|
||||
addl rr2,foo
|
||||
addl rr2,foo(r5)
|
||||
addl rr2,rr6
|
||||
and r3,#12h
|
||||
and r3,@r5
|
||||
and r3,foo
|
||||
and r3,foo(r5)
|
||||
and r3,r5
|
||||
andb rh3,#12h
|
||||
andb rh3,@r5
|
||||
andb rh3,foo
|
||||
andb rh3,foo(r5)
|
||||
andb rh3,rh5
|
||||
bit @r3,#5
|
||||
bit foo(r3),#5
|
||||
bit foo,#5
|
||||
bit r3,#5
|
||||
bit r3,r5
|
||||
bitb @r3,#5
|
||||
bitb foo(r3),#5
|
||||
bitb foo,#5
|
||||
bitb rh3,#5
|
||||
bitb rh3,r5
|
||||
call @r3
|
||||
call foo
|
||||
call foo(r3)
|
||||
calr $
|
||||
clr @r3
|
||||
clr foo
|
||||
clr foo(r3)
|
||||
clr r3
|
||||
clrb @r3
|
||||
clrb foo
|
||||
clrb foo(r3)
|
||||
clrb rh3
|
||||
com @r3
|
||||
com foo
|
||||
com foo(r3)
|
||||
com r3
|
||||
comb @r3
|
||||
comb foo
|
||||
comb foo(r3)
|
||||
comb rh3
|
||||
comflg v
|
||||
comflg v,s
|
||||
comflg v,s,z
|
||||
comflg v,s,z,c
|
||||
cp @r3,#12
|
||||
cp foo(r3),#12
|
||||
cp foo,#12
|
||||
cp r3,#12
|
||||
cp r3,@r5
|
||||
cp r3,foo
|
||||
cp r3,foo(r5)
|
||||
cp r3,r5
|
||||
cpb @r3,#12
|
||||
cpb foo(r3),#12
|
||||
cpb foo,#12
|
||||
cpb rh3,#12
|
||||
cpb rh3,@r5
|
||||
cpb rh3,foo
|
||||
cpb rh3,foo(r5)
|
||||
cpb rh3,rh5
|
||||
cpd r3,@r5,r7,gt
|
||||
cpdb rh3,@r5,r7,gt
|
||||
cpdr r3,@r5,r7,gt
|
||||
cpdrb rh3,@r5,r7,gt
|
||||
cpi r3,@r5,r7,gt
|
||||
cpib rh3,@r5,r7,gt
|
||||
cpir r3,@r5,r7,gt
|
||||
cpirb rh3,@r5,r7,gt
|
||||
cpl rr4,#12
|
||||
cpl rr4,@r5
|
||||
cpl rr4,foo
|
||||
cpl rr4,foo(r5)
|
||||
cpl rr4,rr6
|
||||
cpsd @r3,@r5,r7,gt
|
||||
cpsdb @r3,@r5,r7,gt
|
||||
cpsdr @r3,@r5,r7,gt
|
||||
cpsdrb @r3,@r5,r7,gt
|
||||
cpsi @r3,@r5,r7,gt
|
||||
cpsib @r3,@r5,r7,gt
|
||||
cpsir @r3,@r5,r7,gt
|
||||
cpsirb @r3,@r5,r7,gt
|
||||
dab rh3
|
||||
dbjnz rh3,$
|
||||
dec @r3
|
||||
dec @r3,#16
|
||||
dec foo
|
||||
dec foo(r3)
|
||||
dec foo(r3),#16
|
||||
dec foo,#16
|
||||
dec r3
|
||||
dec r3,#16
|
||||
decb @r3
|
||||
decb @r3,#16
|
||||
decb foo
|
||||
decb foo(r3)
|
||||
decb foo(r3),#16
|
||||
decb foo,#16
|
||||
decb rh3
|
||||
decb rh3,#16
|
||||
di nvi
|
||||
di nvi,vi
|
||||
di vi
|
||||
div rr2,#1234h
|
||||
div rr2,@r5
|
||||
div rr2,foo
|
||||
div rr2,foo(r5)
|
||||
div rr2,r4
|
||||
divl rq4,#12345678h
|
||||
divl rq4,@r5
|
||||
divl rq4,foo
|
||||
divl rq4,foo(r5)
|
||||
divl rq4,rr8
|
||||
djnz r3,$
|
||||
ei nvi
|
||||
ei nvi,vi
|
||||
ei vi
|
||||
ex r3,@r5
|
||||
ex r3,foo
|
||||
ex r3,foo(r5)
|
||||
ex r3,r5
|
||||
exb rh3,@r5
|
||||
exb rh3,foo
|
||||
exb rh3,foo(r5)
|
||||
exb rh3,rh5
|
||||
exts rr2
|
||||
extsb r3
|
||||
extsl rq4
|
||||
halt
|
||||
in r3,1234h
|
||||
in r3,@r5
|
||||
inb rh3,1234h
|
||||
inb rh3,@r5
|
||||
inc @r3
|
||||
inc @r3,#16
|
||||
inc foo
|
||||
inc foo(r3)
|
||||
inc foo(r3),#16
|
||||
inc foo,#16
|
||||
inc r3
|
||||
inc r3,#16
|
||||
incb @r3
|
||||
incb @r3,#16
|
||||
incb foo
|
||||
incb foo(r3)
|
||||
incb foo(r3),#16
|
||||
incb foo,#16
|
||||
incb rh3
|
||||
incb rh3,#16
|
||||
ind @r3,@r5,r7
|
||||
indb @r3,@r5,r7
|
||||
indr @r3,@r5,r7
|
||||
indrb @r3,@r5,r7
|
||||
ini @r3,@r5,r7
|
||||
inib @r3,@r5,r7
|
||||
inir @r3,@r5,r7
|
||||
inirb @r3,@r5,r7
|
||||
iret
|
||||
jp @r3
|
||||
jp foo
|
||||
jp foo(r5)
|
||||
jr $
|
||||
jr gt,$
|
||||
ld @r3,#1234h
|
||||
ld @r3,r5
|
||||
ld foo(r3),#1234h
|
||||
ld foo(r3),r5
|
||||
ld foo,#1234h
|
||||
ld foo,r5
|
||||
ld r3(#1234h),r5
|
||||
ld r3(r7),r5
|
||||
ld r3,#1234h
|
||||
ld r3,@r5
|
||||
ld r3,foo
|
||||
ld r3,foo(r5)
|
||||
ld r3,r5
|
||||
ld r3,r5(#1234h)
|
||||
ld r3,r5(r7)
|
||||
lda r3,foo
|
||||
lda r3,foo(r5)
|
||||
lda r3,r5(#1234h)
|
||||
lda r3,r5(r7)
|
||||
ldar r3,$
|
||||
ldb @r3,#12h
|
||||
ldb @r3,rh5
|
||||
ldb foo(r3),#12h
|
||||
ldb foo(r3),rh5
|
||||
ldb foo,#12h
|
||||
ldb foo,rh5
|
||||
ldb r3(#1234h),rh5
|
||||
ldb r3(r7),rh5
|
||||
ldb rh3,#12h
|
||||
ldb rh3,@r5
|
||||
ldb rh3,foo
|
||||
ldb rh3,foo(r5)
|
||||
ldb rh3,r5(#1234h)
|
||||
ldb rh3,r5(r7)
|
||||
ldb rh3,rh5
|
||||
ldctl fcw,r5
|
||||
ldctl nsp,r5
|
||||
ldctl psap,r5
|
||||
ldctl r5,fcw
|
||||
ldctl r5,nsp
|
||||
ldctl r5,psap
|
||||
ldctl r5,refresh
|
||||
ldctl refresh,r5
|
||||
ldctlb flags,rh5
|
||||
ldctlb rh3,flags
|
||||
ldd @r3,@r5,r7
|
||||
lddb @r3,@r5,r7
|
||||
lddr @r3,@r5,r7
|
||||
lddrb @r3,@r5,r7
|
||||
ldi @r3,@r5,r7
|
||||
ldib @r3,@r5,r7
|
||||
ldir @r3,@r5,r7
|
||||
ldirb @r3,@r5,r7
|
||||
ldk r3,#15
|
||||
ldl @r3,rr6
|
||||
ldl foo(r3),rr6
|
||||
ldl foo,rr6
|
||||
ldl r3(#1234h),rr6
|
||||
ldl r3(r7),rr6
|
||||
ldl rr2,#12345678h
|
||||
ldl rr2,@r5
|
||||
ldl rr2,foo
|
||||
ldl rr2,foo(r5)
|
||||
ldl rr2,r5(#1234h)
|
||||
ldl rr2,r5(r7)
|
||||
ldl rr2,rr6
|
||||
ldm @r3,r10,#5
|
||||
ldm foo(r3),r10,#5
|
||||
ldm foo,r10,#5
|
||||
ldm r3,@r10,#5
|
||||
ldm r3,foo(r10),#5
|
||||
ldm r3,foo,#5
|
||||
ldps @r3
|
||||
ldps foo
|
||||
ldps foo(r5)
|
||||
ldr $,r7
|
||||
ldr r7,$
|
||||
mbit
|
||||
mreq r7
|
||||
mres
|
||||
mset
|
||||
mult rr2,#1234h
|
||||
mult rr2,@r5
|
||||
mult rr2,foo
|
||||
mult rr2,foo(r5)
|
||||
mult rr2,r4
|
||||
multl rq4,#12345678h
|
||||
multl rq4,@r5
|
||||
multl rq4,foo
|
||||
multl rq4,foo(r5)
|
||||
multl rq4,rr8
|
||||
neg @r3
|
||||
neg foo
|
||||
neg foo(r3)
|
||||
neg r3
|
||||
negb @r3
|
||||
negb foo
|
||||
negb foo(r3)
|
||||
negb rh3
|
||||
nop
|
||||
or r3,#12h
|
||||
or r3,@r5
|
||||
or r3,foo
|
||||
or r3,foo(r5)
|
||||
or r3,r5
|
||||
orb rh3,#12h
|
||||
orb rh3,@r5
|
||||
orb rh3,foo
|
||||
orb rh3,foo(r5)
|
||||
orb rh3,rh5
|
||||
otdr @r3,@r5,r7
|
||||
otdrb @r3,@r5,r7
|
||||
otir @r3,@r5,r7
|
||||
otirb @r3,@r5,r7
|
||||
out 1234h,r6
|
||||
out @r3,r9
|
||||
outb 1234h,rl4
|
||||
outb @r3,rl4
|
||||
outd @r3,@r5,r7
|
||||
outdb @r3,@r5,r7
|
||||
outi @r3,@r5,r7
|
||||
outib @r3,@r5,r7
|
||||
pop @r3,@r11
|
||||
pop foo(r5),@r11
|
||||
pop foo,@r11
|
||||
pop r3,@r11
|
||||
popl @r3,@r11
|
||||
popl foo(r5),@r11
|
||||
popl foo,@r11
|
||||
popl rr10,@r11
|
||||
push @r3,#1234h
|
||||
push @r3,@r5
|
||||
push @r3,foo
|
||||
push @r3,foo(r5)
|
||||
push @r3,r5
|
||||
pushl @r3,@r5
|
||||
pushl @r3,foo
|
||||
pushl @r3,foo(r5)
|
||||
pushl @r3,rr12
|
||||
res @r3,#5
|
||||
res foo(r3),#5
|
||||
res foo,#5
|
||||
res r3,#5
|
||||
res r3,r5
|
||||
resb @r3,#5
|
||||
resb foo(r3),#5
|
||||
resb foo,#5
|
||||
resb rh3,#5
|
||||
resb rh3,r5
|
||||
resflg v
|
||||
resflg v,s
|
||||
resflg v,s,z
|
||||
resflg v,s,z,c
|
||||
ret
|
||||
ret gt
|
||||
rl r3
|
||||
rl r3,#1
|
||||
rl r3,#2
|
||||
rlb rh3
|
||||
rlb rh3,#1
|
||||
rlb rh3,#2
|
||||
rlc r3
|
||||
rlc r3,#1
|
||||
rlc r3,#2
|
||||
rlcb rh3
|
||||
rlcb rh3,#1
|
||||
rlcb rh3,#2
|
||||
rldb rh3,rl5
|
||||
rr r3
|
||||
rr r3,#1
|
||||
rr r3,#2
|
||||
rrb rh3
|
||||
rrb rh3,#1
|
||||
rrb rh3,#2
|
||||
rrc r3
|
||||
rrc r3,#1
|
||||
rrc r3,#2
|
||||
rrcb rh3
|
||||
rrcb rh3,#1
|
||||
rrcb rh3,#2
|
||||
rrdb rh7,rl7
|
||||
sbc r14,r15
|
||||
sbcb rh1,rl2
|
||||
sc #12h
|
||||
sda r3,r5
|
||||
sdab rh3,r5
|
||||
sdal rr6,r7
|
||||
sdl r3,r5
|
||||
sdlb rh3,r5
|
||||
sdll rr6,r7
|
||||
set @r3,#5
|
||||
set foo(r3),#5
|
||||
set foo,#5
|
||||
set r3,#5
|
||||
set r3,r5
|
||||
setb @r3,#5
|
||||
setb foo(r3),#5
|
||||
setb foo,#5
|
||||
setb rh3,#5
|
||||
setb rh3,r5
|
||||
setflg v
|
||||
setflg v,s
|
||||
setflg v,s,z
|
||||
setflg v,s,z,c
|
||||
sin r3,1234h
|
||||
sinb rh3,1234h
|
||||
sind @r3,@r8,r12
|
||||
sindb @r3,@r8,r12
|
||||
sindr @r3,@r8,r12
|
||||
sindrb @r3,@r8,r12
|
||||
sini @r3,@r8,r12
|
||||
sinib @r3,@r8,r12
|
||||
sinir @r3,@r8,r12
|
||||
sinirb @r3,@r8,r12
|
||||
sla r2
|
||||
sla r2,#5
|
||||
slab rl2
|
||||
slab rl2,#5
|
||||
slal rr2
|
||||
slal rr2,#5
|
||||
sll r2
|
||||
sll r2,#5
|
||||
sllb rl2
|
||||
sllb rl2,#5
|
||||
slll rr2
|
||||
slll rr2,#5
|
||||
sotdr @r3,@r5,r7
|
||||
sotdrb @r3,@r5,r7
|
||||
sotir @r3,@r5,r7
|
||||
sotirb @r3,@r5,r7
|
||||
sout 1234h,r4
|
||||
soutb 1234h,rl4
|
||||
soutd @r4,@r6,r8
|
||||
soutdb @r4,@r6,r8
|
||||
souti @r4,@r6,r8
|
||||
soutib @r4,@r6,r8
|
||||
sra r2
|
||||
sra r2,#5
|
||||
srab rl2
|
||||
srab rl2,#5
|
||||
sral rr2
|
||||
sral rr2,#5
|
||||
srl r2
|
||||
srl r2,#5
|
||||
srlb rl2
|
||||
srlb rl2,#5
|
||||
srll rr2
|
||||
srll rr2,#5
|
||||
sub r3,#1234h
|
||||
sub r3,@r5
|
||||
sub r3,foo
|
||||
sub r3,foo(r5)
|
||||
sub r3,r5
|
||||
subb rh3,#12h
|
||||
subb rh3,@r5
|
||||
subb rh3,foo
|
||||
subb rh3,foo(r5)
|
||||
subb rh3,rh5
|
||||
subl rr2,#12345678h
|
||||
subl rr2,@r5
|
||||
subl rr2,foo
|
||||
subl rr2,foo(r5)
|
||||
subl rr2,rr6
|
||||
tcc ult,r1
|
||||
tccb uge,rl3
|
||||
test @r2
|
||||
test foo
|
||||
test foo(r5)
|
||||
test r2
|
||||
testb @r2
|
||||
testb foo
|
||||
testb foo(r5)
|
||||
testb rh2
|
||||
testl @r2
|
||||
testl foo
|
||||
testl foo(r5)
|
||||
testl rr2
|
||||
trdb @r5,@r7,r9
|
||||
trdrb @r5,@r7,r9
|
||||
trib @r5,@r7,r9
|
||||
trirb @r5,@r7,r9
|
||||
trtdb @r5,@r7,r9
|
||||
trtdrb @r5,@r7,r9
|
||||
trtib @r5,@r7,r9
|
||||
trtirb @r5,@r7,r9
|
||||
tset @r6
|
||||
tset foo
|
||||
tset foo(r6)
|
||||
tset r6
|
||||
tsetb @r6
|
||||
tsetb foo
|
||||
tsetb foo(r6)
|
||||
tsetb rl6
|
||||
xor r3,#12h
|
||||
xor r3,@r5
|
||||
xor r3,foo
|
||||
xor r3,foo(r5)
|
||||
xor r3,r5
|
||||
xorb rh3,#12h
|
||||
xorb rh3,@r5
|
||||
xorb rh3,foo
|
||||
xorb rh3,foo(r5)
|
||||
xorb rh3,rh5
|
||||
|
||||
__data .Iq
|
||||
This directory contains the source and object files for the Z8000 CP/M Bdos,
|
||||
@@ -0,0 +1,2 @@
|
||||
This directory contains the source and object files for the
|
||||
Z8000 CP/M assembler "asz8k" to run under CP/M.
|
||||
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* B A S E P A G E . H */
|
||||
/* ------------------- */
|
||||
/* */
|
||||
/* This file contains a definition of the CP/M basepage structure, */
|
||||
/* b_page. */
|
||||
/* */
|
||||
/* NOTE: In the portable CP/M environment, it is NOT guaranteed */
|
||||
/* that the location of the base page is known at link-edit time */
|
||||
/* (as it is, for example, in CP/M-80 and CP/M-86.) Instead, a */
|
||||
/* pointer to the current basepage is delivered by the BDOS */
|
||||
/* to each new program which is run. This pointer, _base, is */
|
||||
/* initialized by the C startup function (startup.s) and is */
|
||||
/* available to C programs as an external. */
|
||||
/* */
|
||||
/* This file has been modified to live with the BDOS definitions. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct b_page
|
||||
{
|
||||
XADDR ltpa; /* Low TPA address */
|
||||
XADDR htpa; /* High TPA address */
|
||||
XADDR lcode; /* Start address of code seg*/
|
||||
long codelen; /* Code segment length */
|
||||
XADDR ldata; /* Start address of data seg*/
|
||||
long datalen; /* Data segment length */
|
||||
XADDR lbss; /* Start address of bss seg */
|
||||
long bsslen; /* Bss segment length */
|
||||
long freelen; /* Free segment length */
|
||||
char resvd1[20]; /* Reserved area */
|
||||
struct fcb fcb2; /* Second basepage FCB */
|
||||
struct fcb fcb1; /* First basepage FCB */
|
||||
char buff[128]; /* Default DMA buffer, */
|
||||
/* command line tail */
|
||||
};
|
||||
@@ -0,0 +1,171 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* P-CP/M header file *
|
||||
* Copyright (c) 1982 by Digital Research, Inc. *
|
||||
* Structure definitions for BDOS globals *
|
||||
* and BDOS data structures *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
The BDOS data structures, especially those relating to global variables,
|
||||
are structured in a way that hopefully will enable this BDOS, in the future,
|
||||
to easily become a re-entrant multi-tasking file system. Consequently,
|
||||
the BDOS global variables are divided into two classes. Those that are
|
||||
truly global, even in the case of multiple tasks using the file system
|
||||
concurrently, are simply declared as global variables in bdosmain.c.
|
||||
Only a few "globals" are really global in this sense.
|
||||
|
||||
The majority of the "global" variables are actually state variables that
|
||||
relate to the state of the task using the file system. In CP/M-68K, these
|
||||
are "global", since there's only one task, but in a multi-thread model they're
|
||||
not. These type of variables are put into a data structure, with the
|
||||
intention that in the multi-task environment this structure will be based.
|
||||
|
||||
The following declarations take this philosophy into account, and define
|
||||
a simple structure for the single thread environment while leaving the
|
||||
possibilities open for the multi-thread environment.
|
||||
****************************************************************************/
|
||||
|
||||
#define snglthrd TRUE
|
||||
/* TRUE for single-thread environment
|
||||
undefined to create based structure for re-entrant model */
|
||||
#ifdef snglthrd
|
||||
#define GBL gbls
|
||||
/* In single thread case, GBL just names
|
||||
the structure */
|
||||
#define BSETUP EXTERN struct stvars gbls;
|
||||
/* and BSETUP defines the extern structure */
|
||||
#else
|
||||
|
||||
#define GBL (*statep)
|
||||
/* If multi-task, state vars are based */
|
||||
#define BSETUP REG struct stvars *statep; \
|
||||
statep = &gbls;
|
||||
/* set up pointer to state variables */
|
||||
/* This is intended as an example to show the intent */
|
||||
#endif
|
||||
|
||||
|
||||
/* Note that there are a few critical regions in the file system that must
|
||||
execute without interruption. They pertain mostly to the manipulation of
|
||||
the allocation vector. This isn't a problem in a single-thread model, but
|
||||
must be provided for in a multi-tasking file system. Consequently, the
|
||||
primitives LOCK and UNLOCK are defined and used where necessary in the
|
||||
file system. For the single thread model, they are null routines */
|
||||
|
||||
#define LOCK /**/
|
||||
#define UNLOCK /**/
|
||||
/* Be sure LOCK and UNLOCK are implemented to allow recursive calls to LOCK.
|
||||
That is, if a process that calls LOCK already owns the lock, let it proceed,
|
||||
but remember that only the outer-most call to UNLOCK really releases the
|
||||
file system. */
|
||||
|
||||
|
||||
#define VERSION 0x2022 /* Version number for CP/M-68K */
|
||||
#define robit 0 /* read-only bit in file type field of fcb */
|
||||
#define arbit 2 /* archive bit in file type field of fcb */
|
||||
#define SECLEN 128 /* length of a CP/M sector */
|
||||
|
||||
|
||||
union smallbig
|
||||
{
|
||||
UBYTE small[16]; /* 16 block numbers of 1 byte */
|
||||
WORD big[8]; /* or 8 block numbers of 1 word */
|
||||
};
|
||||
|
||||
/* File Control Block definition */
|
||||
struct fcb
|
||||
{
|
||||
UBYTE drvcode; /* 0 = default drive, 1..16 are drives A..P */
|
||||
UBYTE fname[8]; /* File name (ASCII) */
|
||||
UBYTE ftype[3]; /* File type (ASCII) */
|
||||
UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
UBYTE s1; /* Reserved */
|
||||
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
union smallbig dskmap;
|
||||
UBYTE cur_rec; /* current record field */
|
||||
UBYTE ran0; /* random record field (3 bytes) */
|
||||
UBYTE ran1;
|
||||
UBYTE ran2;
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of directory entry */
|
||||
struct dirent
|
||||
{
|
||||
UBYTE entry; /* 0 - 15 for user numbers, E5 for empty */
|
||||
/* the rest are reserved */
|
||||
UBYTE fname[8]; /* File name (ASCII) */
|
||||
UBYTE ftype[3]; /* File type (ASCII) */
|
||||
UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
UBYTE s1; /* Reserved */
|
||||
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
union smallbig dskmap;
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of disk parameter tables */
|
||||
struct dpb /* disk parameter table */
|
||||
{
|
||||
UWORD spt; /* sectors per track */
|
||||
UBYTE bsh; /* block shift factor */
|
||||
UBYTE blm; /* block mask */
|
||||
UBYTE exm; /* extent mask */
|
||||
UBYTE dpbdum; /* dummy byte for fill */
|
||||
UWORD dsm; /* max disk size in blocks */
|
||||
UWORD drm; /* max directory entries */
|
||||
UWORD dir_al; /* initial allocation for dir */
|
||||
UWORD cks; /* number dir sectors to checksum */
|
||||
UWORD trk_off; /* track offset */
|
||||
};
|
||||
|
||||
struct dph /* disk parameter header */
|
||||
{
|
||||
UBYTE *xlt; /* pointer to sector translate table */
|
||||
UWORD hiwater; /* high water mark for this disk */
|
||||
UWORD dum1; /* dummy (unused) */
|
||||
UWORD dum2;
|
||||
UBYTE *dbufp; /* pointer to 128 byte directory buffer */
|
||||
struct dpb *dpbp; /* pointer to disk parameter block */
|
||||
UBYTE *csv; /* pointer to check vector */
|
||||
UBYTE *alv; /* pointer to allocation vector */
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of structure containing "global" state variables */
|
||||
struct stvars
|
||||
{
|
||||
UBYTE kbchar; /* One byte keyboard type-ahead buffer */
|
||||
UBYTE delim; /* Delimiter for function 9 */
|
||||
BOOLEAN lstecho; /* True if echoing console output to lst: */
|
||||
BOOLEAN echodel; /* Echo char when getting <del> ? */
|
||||
UWORD column; /* CRT column number for expanding tabs */
|
||||
XADDR chainp; /* Used for chain to program call */
|
||||
UBYTE curdsk; /* Currently selected disk */
|
||||
UBYTE dfltdsk; /* Default disk (last selected by fcn 14) */
|
||||
UBYTE user; /* Current user number */
|
||||
struct dph *dphp; /* pointer to disk parm hdr for cur disk */
|
||||
struct dirent *dirbufp; /* pointer for directory buff for process */
|
||||
/* stored here so that each process can */
|
||||
/* have a separate dirbuf. */
|
||||
struct dpb *parmp; /* pointer to disk parameter block for cur */
|
||||
/* disk. Stored here to save ref calc */
|
||||
UWORD srchpos; /* position in directory for search next */
|
||||
XADDR dmaadr; /* Disk dma address */
|
||||
XADDR srchp; /* Pointer to search FCB for function 17 */
|
||||
UBYTE *excvec[18]; /* Array of exception vectors */
|
||||
};
|
||||
|
||||
|
||||
/* Console buffer structure declaration */
|
||||
struct conbuf
|
||||
{
|
||||
UBYTE maxlen; /* Maximum length from calling routine */
|
||||
UBYTE retlen; /* Length actually found by BDOS */
|
||||
UBYTE cbuf[1]; /* Console data */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
|
||||
;****************************************************************
|
||||
;* *
|
||||
;* CP/M-Z8K Basic Disk Operating System interface module *
|
||||
;* For "C" version of CP/M-Z8K *
|
||||
;* *
|
||||
;* Copyright (c) 1982 Digital Research, Inc. *
|
||||
;* *
|
||||
;* Version 0.2 -- September 22, 1982 *
|
||||
;* Z8000 version -- 821014 *
|
||||
;* *
|
||||
;****************************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Globals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
.global _bios1 ; 6 BIOS entry points from BDOS
|
||||
.global _bios2
|
||||
.global _bios3
|
||||
.global _bios4
|
||||
.global _bios5
|
||||
.global _bios6
|
||||
.global _traphnd ; trap #2 handler
|
||||
.global _swap ; byte swapper
|
||||
.global _udiv ; unsigned divide routine
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals and Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global __bdos ; BDOS entry point in bdosmain
|
||||
|
||||
;* The following were put in so that all BDOS modules were
|
||||
;* referenced, so they could be put in a library
|
||||
|
||||
.global _constat ; references conbdos.o
|
||||
.global _dirscan ; references dskutil.o
|
||||
.global _create ; references fileio.o
|
||||
.global _bdosrw ; references bdosrw.o
|
||||
|
||||
biosf .equ 50
|
||||
setsupf .equ 62
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap Handler
|
||||
;*
|
||||
;* rcode = bdos(command, (long)parameter)
|
||||
;*
|
||||
;* rr6: parameter
|
||||
;* r5: command
|
||||
;* returns
|
||||
;* r7: result
|
||||
;*
|
||||
;* called SEGMENTED with caller's registers
|
||||
;* saved on stack, and all but rr0 intact in
|
||||
;* registers.
|
||||
;*
|
||||
;* Calls __bdos(cmd, (word)param, (addr)param)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_traphnd:
|
||||
ldctl r0,FCW ;go non-segmented
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
;
|
||||
; check for functions handled by assembly
|
||||
; language routines
|
||||
;
|
||||
cp r5,#setsupf ; set system mode
|
||||
jr eq setsup
|
||||
cp r5,#biosf ; call bios direct
|
||||
jr eq bioscall
|
||||
;
|
||||
; If caller was non-segmented user program,
|
||||
; get segment number from his program counter
|
||||
;
|
||||
ldl rr2,rr6
|
||||
ld r0,34+4(r15) ;caller's fcw
|
||||
bit r0,#15
|
||||
jr nz callC ; segmented
|
||||
bit r0,#14
|
||||
jr nz callC ; system
|
||||
ld r2,36+4(r15) ; user nonseg.
|
||||
; set seg from PC
|
||||
;
|
||||
; Call C main routine
|
||||
;
|
||||
callC:
|
||||
pushl @r15,rr2 ; xaddr param.
|
||||
push @r15,r7 ; word param
|
||||
push @r15,r5 ; command
|
||||
call __bdos
|
||||
add r15,#8
|
||||
;
|
||||
; Return result in caller's r7.
|
||||
; Restore segmented mode and return
|
||||
;
|
||||
ld 14+4(r15),r7
|
||||
|
||||
ldctl r0,FCW ;go segmented
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
ret
|
||||
|
||||
;
|
||||
; direct BIOS call function
|
||||
;
|
||||
bioscall:
|
||||
;
|
||||
; If caller was non-segmented user program,
|
||||
; get segment number from his program counter
|
||||
;
|
||||
ld r0,34+4(r15) ;caller's fcw
|
||||
bit r0,#15
|
||||
jr nz callBios ; segmented
|
||||
bit r0,#14
|
||||
jr nz callBios ; system
|
||||
ld r6,36+4(r15) ; user nonseg.
|
||||
ld r2,r6 ; set seg from PC
|
||||
; save in r2, also
|
||||
ldctl r0,FCW ;go segmented
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
ldm r3,@r6,#5 ;get parameters
|
||||
ld r4,r2 ;set segments
|
||||
ld r6,r2
|
||||
|
||||
sc #3 ;call BIOS
|
||||
ret ;done
|
||||
|
||||
callBios:
|
||||
ldctl r0,FCW ;go segmented
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
ldm r3,@r6,#5 ;get parameters
|
||||
|
||||
sc #3 ;call BIOS
|
||||
ret ;done
|
||||
;
|
||||
; Set supervisor mode procedure -- VERY DANGEROUS
|
||||
;
|
||||
; Status is set to SYSTEM, SEGMENTED.
|
||||
; Interrupt status will be that at the time
|
||||
; of the call.
|
||||
;
|
||||
setsup:
|
||||
ld r0,34+4(r15)
|
||||
set r0,#14 ;set system
|
||||
set r0,#15 ; and segmented
|
||||
ld 34+4(r15),r0 ; in user FCW
|
||||
|
||||
ldctl r0,FCW ;go segmented
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
ret ;return
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* BIOS Interface Routines
|
||||
;*
|
||||
;* Note - there are 6 BIOS entry points from the BDOS,
|
||||
;* labelled BIOS1 - BIOS6, depending on the
|
||||
;* parameters passed.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_bios5:
|
||||
; For BIOS functions sectran and set exception vector
|
||||
; (funct, word, long) offsets 2, 4, 6
|
||||
|
||||
ldl rr6,6(r15) ; get 2nd param (long)
|
||||
jp _bios2 ; join common routine
|
||||
|
||||
_bios4:
|
||||
; For BIOS function seldsk
|
||||
; (func, word, word) offsets 2, 4, 6
|
||||
ld r7,6(r15) ; get 2nd param (word)
|
||||
clr r6 ; extend to ulong
|
||||
jp _bios2 ; join common routine
|
||||
|
||||
_bios3:
|
||||
; For BIOS function set dma
|
||||
; (func, long) offsets 2, 4
|
||||
ldl rr4,4(r15) ; get 1st param (long)
|
||||
subl rr6,rr6 ; clear second
|
||||
jp _bios1 ; join common routine
|
||||
|
||||
_bios2:
|
||||
; For all BIOS functions with a word parameter
|
||||
; (func, word) offsets 2, 4
|
||||
ld r5,4(r15) ; get 1st param (word)
|
||||
clr r4 ; extend to ulong
|
||||
|
||||
_bios6:
|
||||
_bios1:
|
||||
; For all BIOS functions that have no parameter
|
||||
; other than function number
|
||||
ld r3,2(r15) ; get function number
|
||||
sc #3 ; do BIOS call
|
||||
ret ; returns value in rr7
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Utility Subroutines
|
||||
;*
|
||||
;* swap(word) swap bytes of a word
|
||||
;*
|
||||
;* uword udiv((long) dividend,
|
||||
;* (uword) divisor,
|
||||
;* (uword *)rem )
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_swap:
|
||||
ld r7,2(r15)
|
||||
exb rh7,rl7
|
||||
ret
|
||||
|
||||
_udiv:
|
||||
ldl rr2,2(r15) ;long dividend
|
||||
subl rr0,rr0 ; as unsigned quad
|
||||
ld r5,6(r15) ;word divisor
|
||||
clr r4 ; as unsigned long
|
||||
ldl rr6,8(r15) ;->result
|
||||
|
||||
divl rq0,rr4
|
||||
|
||||
ld @r7,r1 ; store remainder
|
||||
ld r7,r3 ; return quotient
|
||||
clr r6
|
||||
|
||||
|
||||
ret
|
||||
|
||||
|
||||
@@ -0,0 +1,379 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Main Routine *
|
||||
* *
|
||||
* This is the main routine for the BDOS for P-CP/M. *
|
||||
* It has one entry point, _bdos, which is called from *
|
||||
* the assembly language trap handler found in bdosif.s. *
|
||||
* The parameters are a function number (integer) and an *
|
||||
* information parameter, (passed as both an integer and *
|
||||
* a pointer) *
|
||||
* The BDOS can potentially return a pointer, long word, *
|
||||
* or word *
|
||||
* *
|
||||
* Memory management for Z8000, etc. added 821018 by SS. *
|
||||
* One non-obvious change is using tmp_sel to copy in the *
|
||||
* user's FCB, and copying it out again if changed. *
|
||||
* Tmp_sel now handles '?' in the drive field, so it need *
|
||||
* not be called from search (the only place outside of *
|
||||
* this module where it is called) *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* Declarations of BIOS functions */
|
||||
|
||||
/* Declare EXTERN functions */
|
||||
|
||||
EXTERN warmboot(); /* Warm Boot function */
|
||||
EXTERN BOOLEAN constat(); /* Console status */
|
||||
EXTERN UBYTE conin(); /* Console Input function */
|
||||
EXTERN cookdout(); /* Cooked console output routine */
|
||||
EXTERN UBYTE rawconio(); /* Raw console I/O */
|
||||
EXTERN prt_line(); /* Print line until delimiter */
|
||||
EXTERN readline(); /* Buffered console read */
|
||||
EXTERN seldsk(); /* Select disk */
|
||||
EXTERN BOOLEAN openfile(); /* Open File */
|
||||
EXTERN UWORD close_fi(); /* Close File */
|
||||
EXTERN UWORD search(); /* Search first and next fcns */
|
||||
EXTERN UWORD dirscan(); /* General directory scanning routine */
|
||||
EXTERN UWORD bdosrw(); /* Sequential and Random disk read/write */
|
||||
EXTERN BOOLEAN create(); /* Create file */
|
||||
EXTERN BOOLEAN delete(); /* Delete file */
|
||||
EXTERN BOOLEAN rename(); /* Rename file */
|
||||
EXTERN BOOLEAN set_attr(); /* Set file attributes */
|
||||
EXTERN getsize(); /* Get File Size */
|
||||
EXTERN setran(); /* Set Random Record */
|
||||
EXTERN free_sp(); /* Get Disk Free Space */
|
||||
EXTERN UWORD flushit(); /* Flush Buffers */
|
||||
EXTERN UWORD pgmld(); /* Program Load */
|
||||
EXTERN UWORD setexc(); /* Set Exception Vector */
|
||||
EXTERN set_tpa(); /* Get/Set TPA Limits */
|
||||
EXTERN move(); /* general purpose byte mover */
|
||||
|
||||
|
||||
/* Declare "true" global variables; i.e., those which will pertain to the
|
||||
entire file system and thus will remain global even when this becomes
|
||||
a multi-tasking file system */
|
||||
|
||||
GLOBAL UWORD log_dsk = 0; /* 16-bit vector of logged in drives */
|
||||
GLOBAL UWORD ro_dsk = 0; /* 16-bit vector of read-only drives */
|
||||
GLOBAL UWORD crit_dsk = 0; /* 16-bit vector of drives in "critical"
|
||||
state. Used to control dir checksums */
|
||||
GLOBAL XADDR tpa_lp; /* TPA lower boundary (permanent) */
|
||||
GLOBAL XADDR tpa_lt; /* TPA lower boundary (temporary) */
|
||||
GLOBAL XADDR tpa_hp; /* TPA upper boundary (permanent) */
|
||||
GLOBAL XADDR tpa_ht; /* TPA upper boundary (temporary) */
|
||||
|
||||
/* Declare the "state variables". These are globals for the single-thread
|
||||
version of the file system, but are put in a structure so they can be
|
||||
based, with a pointer coming from the calling process */
|
||||
|
||||
GLOBAL struct stvars gbls;
|
||||
|
||||
struct tempstr
|
||||
{
|
||||
UBYTE tempdisk;
|
||||
BOOLEAN reselect;
|
||||
struct fcb *fptr;
|
||||
XADDR fxptr; /* xaddr of caller's FCB */
|
||||
struct fcb tempfcb; /* added for memory management */
|
||||
/* because caller's fcb may not */
|
||||
/* be directly accessible */
|
||||
};
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* _bdos MAIN ROUTINE *
|
||||
* *
|
||||
* Called with _bdos(func, info, infop) *
|
||||
* *
|
||||
* Where: *
|
||||
* func is the BDOS function number (d0.w) *
|
||||
* info is the parameter as a word *
|
||||
* infop is the parameter as a segmented pointer *
|
||||
* note that info is the word form of infop*
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
|
||||
UWORD _bdos(func,info,infop)
|
||||
REG WORD func; /* BDOS function number */
|
||||
REG UWORD info; /* parameter as word */
|
||||
REG XADDR infop; /* parameter as (segmented) pointer */
|
||||
{
|
||||
REG UWORD rtnval;
|
||||
LOCAL struct tempstr temp;
|
||||
BSETUP
|
||||
|
||||
temp.reselect = FALSE;
|
||||
temp.fxptr = infop;
|
||||
rtnval = 0;
|
||||
|
||||
switch (func) /* switch on function number */
|
||||
{
|
||||
case 0: warmboot(0); /* warm boot function */
|
||||
/* break; */
|
||||
|
||||
case 1: return((UWORD)conin()); /* console input function */
|
||||
/* break; */
|
||||
|
||||
case 2: cookdout((UBYTE)info,FALSE);/* "cooked" console output */
|
||||
break;
|
||||
|
||||
case 3: return((UWORD)brdr()); /* get reader from bios */
|
||||
/* break; */
|
||||
|
||||
case 4: bpun((UBYTE)info); /* punch output to bios */
|
||||
break;
|
||||
|
||||
case 5: blstout((UBYTE)info); /* list output from bios */
|
||||
break;
|
||||
|
||||
case 6: return((UWORD)rawconio(info)); /* raw console I/O */
|
||||
/* break; */
|
||||
|
||||
case 7: return(bgetiob()); /* get i/o byte */
|
||||
/* break; */
|
||||
|
||||
case 8: bsetiob(info); /* set i/o byte function */
|
||||
break;
|
||||
|
||||
case 9: uprt_line(infop); /* print line function */
|
||||
break;
|
||||
|
||||
case 10: ureadline(infop); /* read buffered con input */
|
||||
break;
|
||||
|
||||
case 11: return((UWORD)constat()); /* console status */
|
||||
/* break; */
|
||||
|
||||
case 12: return(VERSION); /* return version number */
|
||||
/* break; */
|
||||
|
||||
case 13: log_dsk = 0; /* reset disk system */
|
||||
ro_dsk = 0;
|
||||
crit_dsk= 0;
|
||||
GBL.curdsk = 0xff;
|
||||
GBL.dfltdsk = 0;
|
||||
break;
|
||||
|
||||
case 14: seldsk((UBYTE)info); /* select disk */
|
||||
GBL.dfltdsk = (UBYTE)info;
|
||||
break;
|
||||
|
||||
case 15: tmp_sel(&temp); /* open file */
|
||||
temp.fptr->extent = 0;
|
||||
temp.fptr->s2 = 0;
|
||||
rtnval = dirscan(openfile, temp.fptr, 0);
|
||||
break;
|
||||
|
||||
case 16: tmp_sel(&temp); /* close file */
|
||||
rtnval = close_fi(temp.fptr);
|
||||
break;
|
||||
|
||||
case 17: GBL.srchp = infop; /* search first */
|
||||
tmp_sel(&temp);
|
||||
rtnval = search(temp.fptr, 0, &temp);
|
||||
break;
|
||||
|
||||
case 18: infop = GBL.srchp; /* search next */
|
||||
temp.fxptr = infop;
|
||||
tmp_sel(&temp);
|
||||
rtnval = search(temp.fptr, 1, &temp);
|
||||
break;
|
||||
|
||||
case 19: tmp_sel(&temp); /* delete file */
|
||||
rtnval = dirscan(delete, temp.fptr, 2);
|
||||
break;
|
||||
|
||||
case 20: tmp_sel(&temp); /* read sequential */
|
||||
rtnval = bdosrw(temp.fptr, TRUE, 0);
|
||||
break;
|
||||
|
||||
case 21: tmp_sel(&temp); /* write sequential */
|
||||
rtnval = bdosrw(temp.fptr, FALSE, 0);
|
||||
break;
|
||||
|
||||
case 22: tmp_sel(&temp); /* create file */
|
||||
temp.fptr->extent = 0;
|
||||
temp.fptr->s1 = 0;
|
||||
temp.fptr->s2 = 0;
|
||||
temp.fptr->rcdcnt = 0;
|
||||
/* Zero extent, S1, S2, rcrdcnt. create zeros rest */
|
||||
rtnval = dirscan(create, temp.fptr, 8);
|
||||
break;
|
||||
|
||||
case 23: tmp_sel(&temp); /* rename file */
|
||||
rtnval = dirscan(rename, temp.fptr, 2);
|
||||
break;
|
||||
|
||||
case 24: return(log_dsk); /* return login vector */
|
||||
/* break; */
|
||||
|
||||
case 25: return(UBWORD(GBL.dfltdsk)); /* return current disk */
|
||||
/* break; */
|
||||
|
||||
case 26: GBL.dmaadr = infop; /* set dma address */
|
||||
break;
|
||||
|
||||
/* No function 27 -- Get Allocation Vector */
|
||||
|
||||
case 28: ro_dsk |= 1<<GBL.dfltdsk; /* set disk read-only */
|
||||
break;
|
||||
|
||||
case 29: return(ro_dsk); /* get read-only vector */
|
||||
/* break; */
|
||||
|
||||
case 30: tmp_sel(&temp); /* set file attributes */
|
||||
rtnval = dirscan(set_attr, temp.fptr, 2);
|
||||
break;
|
||||
|
||||
case 31: if (GBL.curdsk != GBL.dfltdsk) seldsk(GBL.dfltdsk);
|
||||
cpy_out( (GBL.parmp), infop, sizeof *(GBL.parmp) );
|
||||
break; /* return disk parameters */
|
||||
|
||||
case 32: if ( (info & 0xff) <= 15 ) /* get/set user number */
|
||||
GBL.user = (UBYTE)info;
|
||||
return(UBWORD(GBL.user));
|
||||
/* break; */
|
||||
|
||||
case 33: tmp_sel(&temp); /* random read */
|
||||
rtnval = bdosrw(temp.fptr, TRUE, 1);
|
||||
break;
|
||||
|
||||
case 34: tmp_sel(&temp); /* random write */
|
||||
rtnval = bdosrw(temp.fptr, FALSE, 1);
|
||||
break;
|
||||
|
||||
case 35: tmp_sel(&temp); /* get file size */
|
||||
getsize(temp.fptr);
|
||||
break;
|
||||
|
||||
case 36: tmp_sel(&temp); /* set random record */
|
||||
setran(temp.fptr);
|
||||
break;
|
||||
|
||||
case 37: info = ~info; /* reset drive */
|
||||
log_dsk &= info;
|
||||
ro_dsk &= info;
|
||||
crit_dsk&= info;
|
||||
break;
|
||||
|
||||
case 40: tmp_sel(&temp); /* write random with 0 fill */
|
||||
rtnval = bdosrw(temp.fptr, FALSE, 2);
|
||||
break;
|
||||
|
||||
case 46: free_sp(info); /* get disk free space */
|
||||
break;
|
||||
|
||||
case 47: GBL.chainp = GBL.dmaadr; /* chain to program */
|
||||
warmboot(0); /* terminate calling program */
|
||||
/* break; */
|
||||
|
||||
case 48: return( flushit() ); /* flush buffers */
|
||||
/* break; */
|
||||
|
||||
case 59: return(pgmld(infop)); /* program load */
|
||||
/* break; */
|
||||
|
||||
case 61: return(setexc(infop)); /* set exception vector */
|
||||
/* break; */
|
||||
|
||||
case 63: set_tpa(infop); /* get/set TPA limits */
|
||||
break;
|
||||
|
||||
default: return(-1); /* bad function number */
|
||||
/* break; */
|
||||
|
||||
}; /* end of switch statement */
|
||||
|
||||
if (temp.reselect){ /* if reselected disk, restore it now */
|
||||
temp.fptr->drvcode = temp.tempdisk;
|
||||
cpy_out(temp.fptr, infop, sizeof *temp.fptr);
|
||||
}
|
||||
|
||||
return(rtnval); /* return the BDOS return value */
|
||||
} /* end _bdos */
|
||||
|
||||
|
||||
/*****************************************************
|
||||
**
|
||||
** tmp_sel(temptr) -- temporarily select disk
|
||||
** pointed to by temptr->fptr.
|
||||
**
|
||||
** make local copy of FCB in caller's space.
|
||||
**
|
||||
*****************************************************/
|
||||
|
||||
tmp_sel(temptr) /* temporarily select disk pointed to by fcb */
|
||||
/* also copy fcb into temp structure */
|
||||
REG struct tempstr *temptr;
|
||||
{
|
||||
REG struct fcb *fcbp;
|
||||
REG UBYTE tmp_dsk;
|
||||
BSETUP
|
||||
|
||||
/* get local copy of caller's FCB, */
|
||||
/* and point temptr->fptr at it */
|
||||
|
||||
cpy_in(temptr->fxptr, &temptr->tempfcb, sizeof(struct fcb));
|
||||
temptr->fptr = &temptr->tempfcb;
|
||||
|
||||
/* get local copy of fcb pointer */
|
||||
fcbp = temptr->fptr;
|
||||
|
||||
/* select disk if necessary */
|
||||
tmp_dsk = fcbp->drvcode;
|
||||
if (tmp_dsk == '?') { /* -- drive '?' for search */
|
||||
seldsk( GBL.dfltdsk);
|
||||
} else { /* -- drive 0 or disk+1 */
|
||||
temptr->tempdisk = tmp_dsk;
|
||||
seldsk( tmp_dsk ? tmp_dsk - 1 : GBL.dfltdsk );
|
||||
|
||||
fcbp->drvcode = GBL.user;
|
||||
temptr->reselect = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
**
|
||||
** uprt_line(ptr) -- print line in user space
|
||||
** ureadline(ptr) -- read line into user space
|
||||
**
|
||||
** The pointer parameter is passed as a long,
|
||||
** since it may be in the user's memory space.
|
||||
**
|
||||
*****************************************************/
|
||||
|
||||
uprt_line(ptr)
|
||||
XADDR ptr;
|
||||
{
|
||||
UBYTE c;
|
||||
XADDR caddr;
|
||||
|
||||
/* At one system-call per byte, this is VERY inefficient. */
|
||||
|
||||
caddr = map_adr((XADDR)&c, 0);
|
||||
while (mem_cpy(ptr++, caddr, 1L), c != GBL.delim)
|
||||
cookdout( c, FALSE);
|
||||
}
|
||||
|
||||
|
||||
ureadline(ptr)
|
||||
XADDR ptr;
|
||||
{
|
||||
char buf[258];
|
||||
|
||||
cpy_in(ptr, buf, 1); /* copy in user's buffer */
|
||||
|
||||
readline(buf); /* read line */
|
||||
|
||||
cpy_out(buf, ptr, 2+(255&(int)buf[1])); /* copy out result */
|
||||
}
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Miscellaneous Module *
|
||||
* *
|
||||
* This module contains miscellaneous loose ends for *
|
||||
* P-CP/M. Included are: *
|
||||
* *
|
||||
* bdosinit() - BDOS initialization routine *
|
||||
* called from CCP for system init *
|
||||
* warmboot() - BDOS warm boot exit routine *
|
||||
* error() - BDOS error printing routine *
|
||||
* setexc() - BDOS set exception vector *
|
||||
* set_tpa() - BDOS get/set TPA limits *
|
||||
* cpy_bi() - copy byte in *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on the Z8000 *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* BIOS definitions, needed for bios wboot */
|
||||
|
||||
|
||||
/* Declare external functions */
|
||||
EXTERN conout(); /* Console Output function */
|
||||
EXTERN UBYTE conin(); /* Console Input function */
|
||||
EXTERN prt_line(); /* Print String function */
|
||||
EXTERN UWORD _bdos(); /* BDOS main routine */
|
||||
EXTERN UBYTE *traphnd(); /* assembly language trap handler */
|
||||
EXTERN initexc(); /* init the exception handler in */
|
||||
/* exceptn.s */
|
||||
EXTERN UWORD dirscan(); /* Directory scanning routine */
|
||||
EXTERN BOOLEAN set_attr(); /* Set File attributes function */
|
||||
|
||||
/* Declare external variables */
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* vector of critical disks */
|
||||
EXTERN XADDR tpa_lt; /* TPA lower limit (temporary) */
|
||||
EXTERN XADDR tpa_lp; /* TPA lower limit (permanent) */
|
||||
EXTERN XADDR tpa_ht; /* TPA upper limit (temporary) */
|
||||
EXTERN XADDR tpa_hp; /* TPA upper limit (permanent) */
|
||||
EXTERN BOOLEAN submit; /* external variables from CCP */
|
||||
EXTERN BOOLEAN morecmds;
|
||||
|
||||
|
||||
#define trap2v 34 /* trap 2 vector number */
|
||||
#define ctrlc 3 /* control-c */
|
||||
|
||||
|
||||
/********************************
|
||||
* bdos initialization routine *
|
||||
********************************/
|
||||
|
||||
bdosinit()
|
||||
/* Initialize the File System */
|
||||
{
|
||||
REG struct
|
||||
{
|
||||
WORD nmbr;
|
||||
XADDR low;
|
||||
LONG length;
|
||||
} *segp;
|
||||
BSETUP
|
||||
|
||||
bsetvec(trap2v, map_adr((long)traphnd, 257)); /* set up trap vector */
|
||||
/* (inst. space addr) */
|
||||
GBL.kbchar = 0; /* initialize the "global" variables */
|
||||
GBL.delim = '$';
|
||||
GBL.lstecho = FALSE;
|
||||
GBL.echodel = TRUE;
|
||||
GBL.chainp = XNULL;
|
||||
GBL.user = 0;
|
||||
_bdos(13,0, XNULL); /* reset disk system function */
|
||||
prt_line("
|
||||
\r\nCPM-Z8000 Version 1.2 03/14/83$");
|
||||
prt_line("\r\nCopyright 1982 Digital Research Inc., Zilog Inc.$");
|
||||
segp = bgetseg(); /* get pointer to memory segment table */
|
||||
tpa_lt = tpa_lp = segp->low;
|
||||
tpa_ht = tpa_hp = tpa_lp + segp->length;
|
||||
initexc( &(GBL.excvec[0]) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* warmboot entry point *
|
||||
************************/
|
||||
|
||||
warmboot(parm)
|
||||
/* Warm Boot the system */
|
||||
WORD parm; /* 1 to reset submit flag */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
log_dsk &= ~ro_dsk; /* log off any disk marked read-only */
|
||||
/* note that this code is specifically for a single-
|
||||
thread system. It won't work in a multi-task sys */
|
||||
ro_dsk = 0;
|
||||
crit_dsk = 0;
|
||||
if (parm)
|
||||
submit = morecmds = FALSE;
|
||||
tpa_lt = tpa_lp;
|
||||
tpa_ht = tpa_hp;
|
||||
initexc( &(GBL.excvec[0]) );
|
||||
bwboot();
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* disk error handlers */
|
||||
/*************************/
|
||||
|
||||
prt_err(p)
|
||||
/* print the error message */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
prt_line(p);
|
||||
prt_line(" error on drive $");
|
||||
conout(GBL.curdsk + 'A');
|
||||
}
|
||||
|
||||
|
||||
abrt_err(p)
|
||||
/* print the error message and always abort */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
prt_err(p);
|
||||
warmboot(1);
|
||||
}
|
||||
|
||||
|
||||
ext_err(p)
|
||||
/* print the error message, and allow for retry, abort, or ignore */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
REG UBYTE ch;
|
||||
|
||||
prt_err(p);
|
||||
do
|
||||
{
|
||||
prt_line("\n\rDo you want to: Abort (A), Retry (R),$");
|
||||
prt_line(" or Continue with bad data (C)? $");
|
||||
ch = conin() & 0x5f;
|
||||
prt_line("\r\n$");
|
||||
|
||||
switch ( ch )
|
||||
{
|
||||
case ctrlc: warmboot(1);
|
||||
case 'A': warmboot(1);
|
||||
case 'C': return(1);
|
||||
case 'R': return(0);
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
|
||||
filero(fcbp)
|
||||
/* File R/O error */
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
{
|
||||
REG BYTE *p;
|
||||
REG UWORD i;
|
||||
REG UBYTE ch;
|
||||
|
||||
p = (BYTE *)fcbp;
|
||||
prt_line("file error: $");
|
||||
i = 8;
|
||||
do conout(*++p); while (--i);
|
||||
conout('.');
|
||||
i = 3;
|
||||
do conout(*++p); while (--i);
|
||||
prt_line(" is read-only.$");
|
||||
do
|
||||
{
|
||||
prt_line("\r\nDo you want to: Change it to read/write (C), or Abort (A)? $");
|
||||
ch = conin() & 0x5f;
|
||||
prt_line("\r\n$");
|
||||
|
||||
switch ( ch )
|
||||
{
|
||||
case ctrlc: warmboot(1);
|
||||
case 'A': warmboot(1);
|
||||
case 'C': fcbp->ftype[robit] &= 0x7f;
|
||||
return( dirscan(set_attr, fcbp, 2) );
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* error entry point *
|
||||
************************/
|
||||
|
||||
error(errnum, fcbp) /* VARARGS */
|
||||
/* Print error message, do appropriate response */
|
||||
|
||||
UWORD errnum; /* error number */
|
||||
struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
prt_line("\r\nCP/M Disk $");
|
||||
switch (errnum)
|
||||
{
|
||||
case 0: return( ext_err("read$") );
|
||||
/* break; */
|
||||
|
||||
case 1: return( ext_err("write$") );
|
||||
/* break; */
|
||||
|
||||
case 2: abrt_err("select$");
|
||||
/* break; */
|
||||
|
||||
case 3: return( ext_err("select$") );
|
||||
/* break; */
|
||||
|
||||
case 4: abrt_err("change$");
|
||||
/* break; */
|
||||
|
||||
case 5: return filero(fcbp);
|
||||
/* break; */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* set exception entry point *
|
||||
*****************************/
|
||||
|
||||
setexc(xepbp)
|
||||
/* Set Exception Vector */
|
||||
REG XADDR xepbp;
|
||||
{
|
||||
REG WORD i;
|
||||
REG struct
|
||||
{
|
||||
WORD vecnum;
|
||||
UBYTE *newvec;
|
||||
UBYTE *oldvec;
|
||||
} epb;
|
||||
|
||||
BSETUP
|
||||
|
||||
cpy_in(xepbp, &epb, sizeof epb); /* copy in param block */
|
||||
|
||||
i = epb.vecnum-2;
|
||||
if ( i==32 || i==33) return(-1);
|
||||
if ( (30 <= i) && (i <= 37) ) i -= 20;
|
||||
else if ( (i < 0) || (i > 9) ) return(-1);
|
||||
epb.oldvec = GBL.excvec[i];
|
||||
GBL.excvec[i] = epb.newvec;
|
||||
|
||||
cpy_out(&epb, xepbp, sizeof epb); /* copy out param block */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* get/set TPA entry point *
|
||||
*****************************/
|
||||
|
||||
set_tpa(xp)
|
||||
/* Get/Set TPA Limits */
|
||||
REG XADDR xp;
|
||||
|
||||
#define set 1
|
||||
#define sticky 2
|
||||
|
||||
{
|
||||
struct
|
||||
{
|
||||
UWORD parms;
|
||||
XADDR low;
|
||||
XADDR high;
|
||||
} p;
|
||||
|
||||
cpy_in(xp, &p, sizeof p); /* copy in param block */
|
||||
|
||||
if (p.parms & set)
|
||||
{
|
||||
tpa_lt = p.low;
|
||||
tpa_ht = p.high;
|
||||
if (p.parms & sticky)
|
||||
{
|
||||
tpa_lp = tpa_lt;
|
||||
tpa_hp = tpa_ht;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p.low = tpa_lt;
|
||||
p.high = tpa_ht;
|
||||
}
|
||||
|
||||
cpy_out(&p, xp, sizeof p); /* copy out param block */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
**
|
||||
** ubyte = cpy_bi(xaddr)-- copy byte in
|
||||
**
|
||||
*****************************************************/
|
||||
|
||||
UBYTE cpy_bi(addr)
|
||||
XADDR addr;
|
||||
{
|
||||
UBYTE b;
|
||||
|
||||
cpy_in(addr, &b, 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Disk Read/Write Module *
|
||||
* *
|
||||
* This module contains functions to perform sequential *
|
||||
* or random access read or write to the disk for P-CP/M *
|
||||
* *
|
||||
* It includes the following external functions: *
|
||||
* *
|
||||
* bdosrw() - sequential and random disk I/O *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on the Z8000 *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
|
||||
/* External function definitions */
|
||||
EXTERN UWORD rdwrt(); /* disk read/write routine */
|
||||
EXTERN WORD getaloc(); /* allocate a block of disk space */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
|
||||
EXTERN UWORD close_fi(); /* close file function */
|
||||
EXTERN BOOLEAN create(); /* create file function passed to dirscan */
|
||||
EXTERN UWORD error(); /* error handler */
|
||||
|
||||
/* External variable definitions */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
/* First, some utility functions used by seqio and ranio */
|
||||
/**********************************************************/
|
||||
|
||||
/******************************
|
||||
* FCB block number routines *
|
||||
******************************/
|
||||
|
||||
WORD blkindx(fcbp)
|
||||
/* return index into fcb disk map */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
REG WORD i;
|
||||
REG WORD blkshf;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp;
|
||||
blkshf = dparmp->bsh;
|
||||
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
|
||||
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
|
||||
}
|
||||
|
||||
|
||||
UWORD blknum(fcbp, index, wrdfcb)
|
||||
/* return block number in fcb indicated by index */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
WORD wrdfcb; /* boolean, fcb disk map of words? */
|
||||
{
|
||||
if (wrdfcb)
|
||||
return( swap(fcbp->dskmap.big[index]) );
|
||||
else return( UBWORD(fcbp->dskmap.small[index]) );
|
||||
}
|
||||
|
||||
|
||||
setblk(fcbp, index, wrdfcb, block)
|
||||
/* put block number into fcb */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
WORD wrdfcb; /* boolean, fcb disk map of words? */
|
||||
REG UWORD block; /* block number */
|
||||
{
|
||||
fcbp->s2 &= 0x7f; /* set file write flag */
|
||||
if (wrdfcb)
|
||||
fcbp->dskmap.big[index] = swap(block);
|
||||
else fcbp->dskmap.small[index] = (UBYTE)block;
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
* disk read/write routine *
|
||||
***************************/
|
||||
|
||||
UWORD do_io(block, rcrd, parm)
|
||||
|
||||
UWORD block; /* block number */
|
||||
UBYTE rcrd; /* record number */
|
||||
REG WORD parm; /* write parameter */
|
||||
{
|
||||
REG LONG lsec;
|
||||
REG struct dpb *dparmp;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp; /* init dpb pointer */
|
||||
lsec = ((LONG)block << (dparmp->bsh)) +
|
||||
(LONG)(rcrd & (dparmp->blm));
|
||||
return( rdwrt(lsec, GBL.dmaadr, parm) );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************
|
||||
* routine for crossing extent boundaries *
|
||||
*******************************************/
|
||||
|
||||
WORD new_ext(fcbp, reading, ran)
|
||||
/* If sequential I/O, open the next extent */
|
||||
/* If random I/O, compute new extent from random record field */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
BOOLEAN reading; /* read/write flag */
|
||||
WORD ran; /* random I/O flag */
|
||||
{
|
||||
REG UBYTE mod; /* module number */
|
||||
REG UBYTE ext; /* extent number */
|
||||
BSETUP
|
||||
|
||||
if (ran)
|
||||
{
|
||||
mod = ( (fcbp->ran0) << 4) | ( (fcbp->ran1) >> 4);
|
||||
ext = ( ((fcbp->ran1) & 0x0f) << 1);
|
||||
if ((fcbp->ran2) & 0x80) ext |= 1;
|
||||
/* the calculation of ext was coded this way because of a */
|
||||
/* compiler bug from Alcyon */
|
||||
}
|
||||
else
|
||||
{
|
||||
mod = (fcbp->s2) & 0x3f;
|
||||
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
|
||||
}
|
||||
if (ext >= 32)
|
||||
{
|
||||
ext = 0;
|
||||
mod += 1;
|
||||
}
|
||||
if (mod >= 64) return(6); /* past maximum file size */
|
||||
if ( mod == ((fcbp->s2) & 0x3f) )
|
||||
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
|
||||
{ /* we're in same logical extent */
|
||||
fcbp->extent = ext;
|
||||
return(0);
|
||||
}
|
||||
/* Extent or Module numbers don't match */
|
||||
/* Close the old extent and open a new one */
|
||||
if ( close_fi(fcbp) >= 255 ) return(3);
|
||||
/* can't close old extent */
|
||||
fcbp->s2 = mod;
|
||||
fcbp->extent = ext;
|
||||
if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open new extent */
|
||||
{
|
||||
if (reading) return(4); /* reading unwritten extent */
|
||||
if ( dirscan(create, fcbp, 8) >= 255 )
|
||||
return(5); /* can't create new extent */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/************************************
|
||||
* Routine to calculate the maximum *
|
||||
* extent number of an FCB in a *
|
||||
* extent-folded environment *
|
||||
************************************/
|
||||
|
||||
UWORD calcext(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p;
|
||||
BSETUP
|
||||
|
||||
i = 15;
|
||||
p = &(fcbp->dskmap.small[16]);
|
||||
do
|
||||
{
|
||||
if (*--p) break;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
/* Now i contains the index of the last non-zero block in the FCB */
|
||||
if ((GBL.parmp)->dsm > 255) i >>= 1;
|
||||
i >>= 7 - ((GBL.parmp)->bsh);
|
||||
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* Routine to get the actual *
|
||||
* record count of the currently *
|
||||
* active logical extent of a FCB *
|
||||
*********************************/
|
||||
|
||||
UWORD get_rc(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD ext;
|
||||
|
||||
ext = calcext(fcbp); /* find last active extent in fcb */
|
||||
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
|
||||
/* if this is the last active fcb, return fcb's rc */
|
||||
else if (ext > fcbp->extent) return(128);
|
||||
/* if the fcb has more extents past this one, then */
|
||||
/* the current one is logically full */
|
||||
else return (0);
|
||||
/* if we seeked past the last active extent, rc = 0 */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* bdosrw entry point *
|
||||
************************/
|
||||
|
||||
UWORD bdosrw(fcbp, reading, random)
|
||||
|
||||
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
REG BOOLEAN reading; /* boolean to tell whether to read or write */
|
||||
WORD random; /* 0 = sequential, 1 = random (normal), */
|
||||
/* 2 = random with zero fill */
|
||||
{
|
||||
REG UWORD block; /* block number from fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
REG XADDR old_dma; /* temp holding spot for dmaadr */
|
||||
REG UBYTE *buf; /* type compatibility kludge */
|
||||
REG WORD parm; /* parameter to do-io */
|
||||
REG WORD bigfile; /* file system is in word mode */
|
||||
REG UWORD rtn; /* return parameter */
|
||||
REG UBYTE rc; /* temp storage for rcdcnt */
|
||||
BSETUP
|
||||
|
||||
bigfile = ((GBL.parmp)->dsm) & ~0xff;
|
||||
if ( ( ! reading) && (fcbp->ftype[robit] & 0x80) ) error(5,fcbp);
|
||||
/* check for read-only file */
|
||||
if (random)
|
||||
{
|
||||
if ( rtn = new_ext(fcbp, reading, TRUE) ) return(rtn);
|
||||
/* open new extent if necessary, return if error */
|
||||
fcbp->cur_rec = (fcbp->ran2) & 0x7f;
|
||||
}
|
||||
else /* sequential */
|
||||
if (fcbp->cur_rec == 128)
|
||||
{ /* time to try next extent */
|
||||
if ( new_ext(fcbp, reading, FALSE) )
|
||||
return(1); /* if can't open new extent, error */
|
||||
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
|
||||
}
|
||||
|
||||
/* record is now in active fcb */
|
||||
rc = fcbp->rcdcnt;
|
||||
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
|
||||
{
|
||||
if (reading) return(1); /* reading unwritten data */
|
||||
fcbp->s2 &= 0x7f; /* set file write flag */
|
||||
rc = fcbp->cur_rec + 1;
|
||||
}
|
||||
index = blkindx(fcbp); /* get index into fcb disk map */
|
||||
block = blknum(fcbp, index, bigfile);
|
||||
if (block) parm = (reading ? 0 : 1);
|
||||
else /* if allocated block, parm is just read or write */
|
||||
{ /* unallocated block */
|
||||
if (reading) return(1); /* reading unwritten data */
|
||||
/* Writing to new block */
|
||||
block = getaloc();
|
||||
if (block == (UWORD *)~0) return(2); /* out of space */
|
||||
setblk(fcbp, index, bigfile, block);
|
||||
parm = 3;
|
||||
if (random == 2)
|
||||
{ /* Write random with zero fill */
|
||||
old_dma = GBL.dmaadr;
|
||||
GBL.dmaadr = map_adr((XADDR)GBL.dirbufp,0);/* Do DMA from dir_buf */
|
||||
index = SECLEN;
|
||||
buf = (UBYTE *)GBL.dirbufp; /* fix type incompatibility */
|
||||
do buf[--index] = 0;
|
||||
while (index); /* zero the dma buffer */
|
||||
for (index = 0; index <= ((GBL.parmp)->blm); index++)
|
||||
{
|
||||
do_io(block, (UBYTE)index, parm);
|
||||
/* write zeros to the block */
|
||||
parm = 1; /* next write is not to new block */
|
||||
}
|
||||
GBL.dmaadr = old_dma; /* restore dma address */
|
||||
}
|
||||
}
|
||||
rtn = do_io(block, fcbp->cur_rec, parm);
|
||||
if ( rtn == 0 )
|
||||
{
|
||||
fcbp->rcdcnt = rc;
|
||||
if ( ! random ) fcbp->cur_rec += 1;
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* BIOS definitions for P-CP/M *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
* This include file simply defines the BIOS calls *
|
||||
* *
|
||||
* Memory management added 821018 by SS at Zilog *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
EXTERN long bios(); /* main BIOS entry point */
|
||||
EXTERN UBYTE bios1(); /* used for character I/O functions */
|
||||
EXTERN bios2(); /* parm1 is word, no return value */
|
||||
EXTERN bios3(); /* used for set dma only */
|
||||
/* parm1 is a pointer, no return */
|
||||
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
|
||||
/* words, returns a pointer to dph */
|
||||
EXTERN UWORD bios5(); /* for sectran and set exception */
|
||||
EXTERN BYTE *bios6(); /* for get memory segment table */
|
||||
|
||||
|
||||
#define bwboot() bios1(1) /* warm boot */
|
||||
#define bconstat() bios1(2) /* console status */
|
||||
#define bconin() bios1(3) /* console input */
|
||||
#define bconout(parm) bios2(4,parm) /* console output parm */
|
||||
#define blstout(parm) bios2(5,parm) /* list device output */
|
||||
#define bpun(parm) bios2(6,parm) /* punch char output */
|
||||
#define brdr() bios1(7) /* reader input */
|
||||
#define bhome() bios1(8) /* recalibrate drive */
|
||||
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
|
||||
/* select disk and return info */
|
||||
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
|
||||
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
|
||||
#define bsetdma(parm) bios3(12,parm) /* set dma address */
|
||||
#define bread() bios1(13) /* read sector from disk */
|
||||
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
|
||||
#define blistst() bios1(15) /* list device status */
|
||||
#define bsectrn(parm1,parm2) bios5(16,parm1,(XADDR)parm2)
|
||||
/* sector translate */
|
||||
#define bgetseg() bios6(18) /* get memory segment tbl */
|
||||
#define bgetiob() bios1(19) /* get I/O byte */
|
||||
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
|
||||
#define bflush() bios1(21) /* flush buffers */
|
||||
#define bsetvec(parm1,parm2) bios5(22,parm1,(XADDR)parm2)
|
||||
/* set exception vector */
|
||||
|
||||
|
||||
/************************/
|
||||
/* MEMORY MANAGEMENT */
|
||||
/*----------------------*/
|
||||
EXTERN XADDR map_adr(); /*(laddr, space)->paddr */
|
||||
EXTERN VOID mem_cpy(); /*(src, dst, len) */
|
||||
/*----------------------*/
|
||||
/* copy in, out (s,d,l) */
|
||||
/* */
|
||||
#define cpy_in(s,d,l) mem_cpy((XADDR)s, map_adr((XADDR)d, 0), (long)l)
|
||||
#define cpy_out(s,d,l) mem_cpy(map_adr((XADDR)s, 0), (XADDR)d, (long)l)
|
||||
/* */
|
||||
/************************/
|
||||
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Character I/O Routines *
|
||||
* *
|
||||
* This module does BDOS functions 1 thru 11 *
|
||||
* *
|
||||
* It contains the following functions which *
|
||||
* are called from the BDOS main routine: *
|
||||
* constat(); *
|
||||
* conin(); *
|
||||
* cookdout(); *
|
||||
* rawconio(); *
|
||||
* prt_line(); *
|
||||
* readline(); *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
#include "bdosdef.h"
|
||||
|
||||
#include "biosdef.h"
|
||||
|
||||
|
||||
#define ctrlc 0x03
|
||||
#define ctrle 0x05
|
||||
#define ctrlp 0x10
|
||||
#define ctrlq 0x11
|
||||
#define ctrlr 0x12
|
||||
#define ctrls 0x13
|
||||
#define ctrlu 0x15
|
||||
#define ctrlx 0x18
|
||||
|
||||
#define cr 0x0d
|
||||
#define lf 0x0a
|
||||
#define tab 0x09
|
||||
#define rub 0x7f
|
||||
#define bs 0x08
|
||||
#define space 0x20
|
||||
|
||||
|
||||
EXTERN warmboot(); /* External function definition */
|
||||
EXTERN UBYTE cpy_bi(); /* copy byte in from user space */
|
||||
|
||||
|
||||
/******************/
|
||||
/* console status */
|
||||
/******************/
|
||||
|
||||
BOOLEAN constat()
|
||||
{
|
||||
BSETUP
|
||||
|
||||
return( GBL.kbchar ? TRUE : bconstat() );
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* check for ctrl/s */
|
||||
/* used internally */
|
||||
/********************/
|
||||
conbrk()
|
||||
{
|
||||
REG UBYTE ch;
|
||||
REG BOOLEAN stop;
|
||||
BSETUP
|
||||
|
||||
stop = FALSE;
|
||||
if ( bconstat() ) do
|
||||
{
|
||||
if ( (ch = bconin()) == ctrlc ) warmboot(1);
|
||||
if ( ch == ctrls ) stop = TRUE;
|
||||
else if (ch == ctrlq) stop = FALSE;
|
||||
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
else GBL.kbchar = ch;
|
||||
} while (stop);
|
||||
}
|
||||
|
||||
|
||||
/******************/
|
||||
/* console output */
|
||||
/* used internally*/
|
||||
/******************/
|
||||
|
||||
conout(ch)
|
||||
REG UBYTE ch;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
conbrk(); /* check for control-s break */
|
||||
bconout(ch); /* output character to console */
|
||||
if (GBL.lstecho) blstout(ch); /* if ctrl-p on, echo to list dev */
|
||||
if (ch >= ' ') GBL.column++; /* keep track of screen column */
|
||||
else if (ch == cr) GBL.column = 0;
|
||||
else if (ch == bs) GBL.column--;
|
||||
}
|
||||
|
||||
|
||||
/*************************************/
|
||||
/* console output with tab expansion */
|
||||
/*************************************/
|
||||
|
||||
cookdout(ch, ctlout)
|
||||
REG UBYTE ch; /* character to output */
|
||||
BOOLEAN ctlout; /* output ^<char> for control chars? */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (ch == tab) do /* expand tabs */
|
||||
conout( ' ' );
|
||||
while (GBL.column & 7);
|
||||
|
||||
else
|
||||
{
|
||||
if ( ctlout && (ch < ' ') )
|
||||
{
|
||||
conout( '^' );
|
||||
ch |= 0x40;
|
||||
}
|
||||
conout(ch); /* output the character */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/* console input */
|
||||
/*****************/
|
||||
|
||||
UBYTE getch() /* Get char from buffer or bios */
|
||||
/* For internal use only */
|
||||
{
|
||||
REG UBYTE temp;
|
||||
BSETUP
|
||||
|
||||
temp = GBL.kbchar; /* get buffered char */
|
||||
GBL.kbchar = 0; /* clear it */
|
||||
return( temp ? temp : bconin() ); /* if non-zero, return it */
|
||||
/* else get char from bios */
|
||||
}
|
||||
|
||||
UBYTE conin() /* BDOS console input function */
|
||||
{
|
||||
REG UBYTE ch;
|
||||
BSETUP
|
||||
|
||||
conout( ch = getch() );
|
||||
if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/******************
|
||||
* raw console i/o *
|
||||
******************/
|
||||
|
||||
UBYTE rawconio(parm) /* BDOS raw console I/O function */
|
||||
|
||||
REG UWORD parm;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (parm == 0xff) return(getch());
|
||||
else if (parm == 0xfe) return(constat());
|
||||
else return(bconout(parm & 0xff)); /* add return to make lint happy */
|
||||
}
|
||||
|
||||
|
||||
/****************************************************/
|
||||
/* print line up to delimiter($) with tab expansion */
|
||||
/****************************************************/
|
||||
|
||||
prt_line(p)
|
||||
REG UBYTE *p;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
while( *p != GBL.delim ) cookdout( *(p++), FALSE);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************/
|
||||
/* read line with editing and bounds checking */
|
||||
/**********************************************/
|
||||
|
||||
/* Two subroutines first */
|
||||
|
||||
newline(startcol)
|
||||
REG UWORD startcol;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
conout(cr); /* go to new line */
|
||||
conout(lf);
|
||||
while(startcol)
|
||||
{
|
||||
conout(' ');
|
||||
startcol -= 1; /* start output at starting column */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
backsp(p, stcol) /* backspace one character position */
|
||||
REG struct conbuf *p; /* pointer to console buffer */
|
||||
UWORD stcol;
|
||||
{
|
||||
REG WORD i;
|
||||
REG WORD length;
|
||||
REG UBYTE ch;
|
||||
BSETUP
|
||||
|
||||
if (p->retlen) length = UBWORD(--(p->retlen));
|
||||
/* if buffer non-empty, decrease it by 1 */
|
||||
else length = 0;
|
||||
i = stcol;
|
||||
while (length--)
|
||||
{
|
||||
ch = p->cbuf[length]; /* get character from buffer */
|
||||
if ( ch == tab )
|
||||
{
|
||||
i += 8; /* i is our column counter */
|
||||
i &= ~7; /* for tab, go to multiple of 8 */
|
||||
}
|
||||
else if ( ch < ' ' ) i += 2;
|
||||
/* control chars put out 2 printable chars */
|
||||
else i += 1;
|
||||
}
|
||||
while (GBL.column > i)
|
||||
{
|
||||
conout(bs); /* backspace until we get to proper column */
|
||||
conout(' ');
|
||||
conout(bs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
readline(p) /* BDOS function 10 */
|
||||
REG struct conbuf *p;
|
||||
|
||||
{
|
||||
REG UBYTE ch;
|
||||
REG UWORD i;
|
||||
REG UWORD j;
|
||||
REG UBYTE *q;
|
||||
UWORD stcol;
|
||||
|
||||
BSETUP
|
||||
|
||||
stcol = GBL.column; /* set up starting column */
|
||||
if (GBL.chainp != XNULL) /* chain to program code */
|
||||
{
|
||||
i = UBWORD(cpy_bi(GBL.chainp++)); /* cpy in from user space */
|
||||
j = UBWORD(p->maxlen);
|
||||
if (j < i) i = j; /* don't overflow console buffer! */
|
||||
p->retlen = (UBYTE)i;
|
||||
q = p->cbuf;
|
||||
while (i)
|
||||
{
|
||||
cookdout( *q++ = cpy_bi(GBL.chainp++), TRUE);
|
||||
i -= 1;
|
||||
}
|
||||
GBL.chainp = XNULL;
|
||||
return;
|
||||
}
|
||||
|
||||
p->retlen = 0; /* start out with empty buffer */
|
||||
while ( UBWORD(p->retlen) < UBWORD(p->maxlen) )
|
||||
{ /* main loop for read console buffer */
|
||||
|
||||
if ( ((ch=getch()) == ctrlc) && !(p->retlen) )
|
||||
{
|
||||
cookdout(ctrlc, TRUE);
|
||||
warmboot(1);
|
||||
}
|
||||
|
||||
else if ( (ch == cr) || (ch == lf) )
|
||||
{ /* if cr or lf, exit */
|
||||
conout(cr);
|
||||
break;
|
||||
}
|
||||
|
||||
else if (ch == bs) backsp(p, stcol); /* backspace */
|
||||
|
||||
else if (ch == rub) /* delete character */
|
||||
{
|
||||
if (GBL.echodel)
|
||||
{
|
||||
if (p->retlen)
|
||||
{
|
||||
i = UBWORD(--(p->retlen));
|
||||
conout( p->cbuf[i] );
|
||||
}
|
||||
}
|
||||
else backsp(p, stcol);
|
||||
}
|
||||
|
||||
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
/* control-p */
|
||||
else if (ch == ctrlx) /* control-x */
|
||||
do backsp(p,stcol); while (p->retlen);
|
||||
|
||||
else if (ch == ctrle) newline(stcol); /* control-e */
|
||||
|
||||
else if (ch == ctrlu) /* control-u */
|
||||
{
|
||||
conout('#');
|
||||
newline(stcol);
|
||||
p->retlen = 0;
|
||||
}
|
||||
|
||||
else if (ch == ctrlr) /* control-r */
|
||||
{
|
||||
conout('#');
|
||||
newline(stcol);
|
||||
for (i=0; i < UBWORD(p->retlen); i++)
|
||||
cookdout( p->cbuf[i], TRUE);
|
||||
}
|
||||
|
||||
else /* normal character */
|
||||
cookdout( (p->cbuf[UBWORD((p->retlen)++)] = ch), TRUE );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Disk Utilities Module *
|
||||
* *
|
||||
* This module contains the miscellaneous utilities *
|
||||
* for manipulating the disk in P-CP/M. Included are: *
|
||||
* *
|
||||
* dirscan() - general purpose dir scanning *
|
||||
* setaloc() - set bit in allocation vector *
|
||||
* clraloc() - clear bit in allocation vector *
|
||||
* getaloc() - get free allocation block *
|
||||
* dchksum() - directory checksum calculator *
|
||||
* dir_rd() - read directory sector *
|
||||
* dir_wr() - write directory sector *
|
||||
* rdwrt() - read/write disk sector *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on Z8000 *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
#include "biosdef.h" /* Bios & mem mapperinterface */
|
||||
|
||||
|
||||
/* declare external functions and variables */
|
||||
EXTERN UWORD do_phio(); /* external physical disk I/O routine */
|
||||
EXTERN UWORD error(); /* external error routine */
|
||||
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* critical disk vector */
|
||||
|
||||
|
||||
/**********************
|
||||
* read/write routine *
|
||||
**********************/
|
||||
|
||||
UWORD rdwrt(secnum, dma, parm)
|
||||
/* General disk sector read/write routine */
|
||||
/* It simply sets up a I/O packet and sends it to do_phio */
|
||||
|
||||
LONG secnum; /* logical sector number to read/write */
|
||||
XADDR dma; /* dma address */
|
||||
REG WORD parm; /* 0 for read, write parm + 1 for write */
|
||||
|
||||
{
|
||||
struct iopb rwpkt;
|
||||
BSETUP
|
||||
|
||||
rwpkt.devnum = GBL.curdsk; /* disk to read/write */
|
||||
if (parm)
|
||||
{
|
||||
rwpkt.iofcn = (BYTE)write; /* if parm non-zero, we're doing a write */
|
||||
rwpkt.ioflags = (BYTE)(parm-1); /* pass write parm */
|
||||
if ( ro_dsk & (1 << (rwpkt.devnum)) ) error(4);
|
||||
/* don't write on read-only disk */
|
||||
}
|
||||
else
|
||||
{
|
||||
rwpkt.iofcn = (BYTE)read;
|
||||
rwpkt.ioflags = (BYTE)0;
|
||||
}
|
||||
rwpkt.devadr = secnum; /* sector number */
|
||||
rwpkt.xferadr = dma; /* dma address */
|
||||
|
||||
/* parameters that are currently not used by do_phio
|
||||
rwpkt.devtype = disk;
|
||||
rwpkt.xferlen = 1;
|
||||
*/
|
||||
rwpkt.infop = GBL.dphp; /* pass ptr to dph */
|
||||
while ( do_phio(&rwpkt) )
|
||||
if ( error( parm ? 1 : 0 ) ) break;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
* directory read routine *
|
||||
***************************/
|
||||
|
||||
UWORD dir_rd(secnum)
|
||||
|
||||
UWORD secnum;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
return( rdwrt((LONG)secnum, map_adr((XADDR)GBL.dirbufp, 0), 0) );
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* directory write routine *
|
||||
****************************/
|
||||
|
||||
UWORD dir_wr(secnum)
|
||||
|
||||
REG WORD secnum;
|
||||
{
|
||||
REG UWORD rtn;
|
||||
UBYTE dchksum();
|
||||
BSETUP
|
||||
|
||||
rtn = rdwrt( (LONG)secnum, map_adr((XADDR)GBL.dirbufp, 0), 2);
|
||||
if ( secnum < (GBL.parmp)->cks )
|
||||
*((GBL.dphp)->csv + secnum) = dchksum();
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
* directory checksum routine *
|
||||
*******************************/
|
||||
|
||||
UBYTE dchksum()
|
||||
/* Compute checksum over one directory sector */
|
||||
/* Note that this implementation is dependant on the representation */
|
||||
/* of a LONG and is therefore not very portable. But it's fast */
|
||||
{
|
||||
REG LONG *p; /* local temp variables */
|
||||
REG LONG lsum;
|
||||
REG WORD i;
|
||||
|
||||
BSETUP
|
||||
|
||||
p = (LONG *)GBL.dirbufp; /* point to directory buffer */
|
||||
lsum = 0;
|
||||
i = SECLEN / (sizeof lsum);
|
||||
do
|
||||
{
|
||||
lsum += *p++; /* add next 4 bytes of directory */
|
||||
i -= 1;
|
||||
} while (i);
|
||||
lsum += (lsum >> 16);
|
||||
lsum += (lsum >> 8);
|
||||
return( (UBYTE)(lsum & 0xff) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* dirscan entry point *
|
||||
************************/
|
||||
|
||||
UWORD dirscan(funcp, fcbp, parms)
|
||||
|
||||
BOOLEAN (*funcp)(); /* funcp is a pointer to a Boolean function */
|
||||
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
REG UWORD parms; /* parms is 16 bit set of bit parameters */
|
||||
|
||||
/* Parms & 1 = 0 to start at beginning of dir, 1 to continue from last */
|
||||
/* Parms & 2 = 0 to stop when *funcp is true, 1 to go until end */
|
||||
/* Parms & 4 = 0 to check the dir checksum, 1 to store new checksum */
|
||||
/* Parms & 8 = 0 to stop at hiwater, 1 to go until end of directory */
|
||||
|
||||
#define continu 1
|
||||
#define full 2
|
||||
#define initckv 4
|
||||
#define pasthw 8
|
||||
|
||||
{
|
||||
REG UWORD i; /* loop counter */
|
||||
REG struct dpb *dparmp; /* pointer to disk parm block */
|
||||
REG UWORD dirsec; /* sector number we're working on */
|
||||
REG UWORD rtn; /* return value */
|
||||
REG UBYTE *p; /* scratch pointer */
|
||||
REG UWORD bitvec; /* disk nmbr represented as a vector */
|
||||
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp; /* init ptr to dpb */
|
||||
rtn = 255; /* assume it doesn't work */
|
||||
|
||||
/* Sorry about this FOR loop, but the initialization terms and end test
|
||||
really do depend on the input parameters, so...... */
|
||||
for ( i = ( (parms & continu) ? GBL.srchpos + 1 : 0);
|
||||
i <= ( (parms & pasthw) ? (dparmp->drm) : (GBL.dphp)->hiwater );
|
||||
i++ )
|
||||
{ /* main directory scanning loop */
|
||||
if ( ! (i & 3) )
|
||||
{ /* inside loop happens when we need to
|
||||
read another directory sector */
|
||||
retry: dirsec = i >> 2;
|
||||
dir_rd(dirsec); /* read the directory sector */
|
||||
if ( dirsec < (dparmp->cks) ) /* checksumming on this sector? */
|
||||
{
|
||||
p = ((GBL.dphp)->csv) + dirsec;
|
||||
/* point to checksum vector byte */
|
||||
if (parms & initckv) *p = dchksum();
|
||||
else if (*p != dchksum())
|
||||
{ /* checksum error! */
|
||||
(GBL.dphp)->hiwater = dparmp->drm; /* reset hi water */
|
||||
bitvec = 1 << (GBL.curdsk);
|
||||
if (crit_dsk & bitvec) /* if disk in critical mode */
|
||||
ro_dsk |= bitvec; /* then set it to r/o */
|
||||
else
|
||||
{
|
||||
log_dsk &= ~bitvec; /* else log it off */
|
||||
seldsk(GBL.curdsk); /* and re-select it */
|
||||
goto retry; /* and re-do current op */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GBL.srchpos = i;
|
||||
if ( (*funcp)(fcbp, (GBL.dirbufp) + (i&3), i) )
|
||||
/* call function with parms of (1) fcb ptr,
|
||||
(2) pointer to directory entry, and
|
||||
(3) directory index */
|
||||
{
|
||||
if (parms & full) rtn = 0; /* found a match, but keep going */
|
||||
else return(i & 3); /* return directory code */
|
||||
}
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/****************************************
|
||||
* Routines to manage allocation vector *
|
||||
* setaloc() *
|
||||
* clraloc() *
|
||||
* getaloc() *
|
||||
****************************************/
|
||||
|
||||
setaloc(bitnum)
|
||||
/* Set bit in allocation vector */
|
||||
REG UWORD bitnum;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
*((GBL.dphp)->alv + (bitnum>>3)) |= 0x80 >> (bitnum & 7);
|
||||
}
|
||||
|
||||
|
||||
clraloc(bitnum)
|
||||
/* Clear bit in allocation vector */
|
||||
REG UWORD bitnum;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (bitnum)
|
||||
*((GBL.dphp)->alv + (bitnum>>3)) &= ~(0x80 >> (bitnum & 7));
|
||||
}
|
||||
|
||||
|
||||
UWORD getaloc()
|
||||
/* Get a free block in the file system and set the bit in allocation vector */
|
||||
{
|
||||
REG UWORD i; /* loop counter */
|
||||
REG WORD diskmax; /* # bits in alv - 1 */
|
||||
REG UBYTE *p; /* ptr to byte */
|
||||
|
||||
BSETUP
|
||||
LOCK /* need to lock the file system while messing
|
||||
with the allocation vector */
|
||||
|
||||
diskmax = (GBL.parmp)->dsm;
|
||||
/* get disk max field from dpb */
|
||||
p = (GBL.dphp)->alv;
|
||||
for (i = 0; i <= diskmax; i++)
|
||||
{
|
||||
if ( ~(*(p + (i >> 3))) & (0x80 >> (i&7)) )
|
||||
{ /* found a zero in allocation vector */
|
||||
setaloc(i);
|
||||
UNLOCK /* can unlock file system now */
|
||||
return(i); /* return block number */
|
||||
}
|
||||
}
|
||||
return(~0); /* if no free block found, return -1 */
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
;************************************************
|
||||
;* *
|
||||
;* P-CP/M Basic Disk Operating System *
|
||||
;* Exception Handling Module *
|
||||
;* *
|
||||
;* Version 0.0 -- July 21, 1982 *
|
||||
;* Version 0.1 -- July 25, 1982 *
|
||||
;* Version 0.2 -- 821014 (Zilog) *
|
||||
;* Version 0.3 -- 821222 (Zilog) *
|
||||
;* *
|
||||
;************************************************
|
||||
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _sysseg
|
||||
.global _tpa_lp
|
||||
.global _tpa_hp
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Globals and Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _initexc
|
||||
|
||||
BGETSEG .equ 18 ;Bios call to get mem seg tbl
|
||||
BSETEXC .equ 22 ;Bios call to set xvec
|
||||
|
||||
BIOS_SC .equ 3 ;Bios system call
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* initexc(vecarray) -- initialize exception vector
|
||||
;*
|
||||
;* The BDOS maintains its OWN exception vector.
|
||||
;* This routine sets up the BIOS exception
|
||||
;* vectors to point to handlers in this module,
|
||||
;* that vector again using the BDOS vectors.
|
||||
;*
|
||||
;* Only vectors 2-23 and 36-38 are handled by
|
||||
;* the BDOS, leaving 0-1 and 24-35 for the BIOS
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_initexc:
|
||||
;* sp -> return addr
|
||||
;* +2 table addr
|
||||
|
||||
ld r3,#BSETEXC ; r3 = BDOS command
|
||||
ldl rr4,#2 ;rr4 = exception #
|
||||
ld r6,_sysseg ;rr6 -> handler
|
||||
lda r7,exchndl ; (segmented)
|
||||
|
||||
dec r15,#10 ;space to save regs
|
||||
; on stack over SC
|
||||
initloop:
|
||||
ldm @r15,r3,#5
|
||||
sc #BIOS_SC
|
||||
ldm r3,@r15,#5
|
||||
inc r5,#1 ;step exception #
|
||||
inc r7,#2 ;and handler addr.
|
||||
cp r5,#24 ;done 23 yet?
|
||||
jr ne init1 ; no
|
||||
ld r5,#36 ; yes--skip to 36
|
||||
inc r7,#8 ; we have entries in
|
||||
; table for 32-36
|
||||
; but system uses
|
||||
; them. Skip.
|
||||
init1: cp r5,#48 ;done all 48?
|
||||
jr ne initloop ; no--loop
|
||||
|
||||
inc r15,#10 ;clean stack
|
||||
|
||||
ld r2,2(r15) ;save vector address
|
||||
ld evec_adr,r2
|
||||
|
||||
ld r0,#18 ; 18 long entries
|
||||
subl rr4,rr4
|
||||
init2: ;clear vector array
|
||||
|
||||
; should check current entry, and keep it if
|
||||
; between old TPA and current TPA limits.
|
||||
|
||||
; The TPA limits are flaky because we have two TPA's,
|
||||
; for split and merged spaces, not to mention
|
||||
; segmented programs.
|
||||
|
||||
; What we are going to do is clear the lot.
|
||||
; Programs that want permanent traps can use the
|
||||
; Bios to set the trap vector.
|
||||
|
||||
ldl rr6,@r2 ; rr6 = exception addr
|
||||
|
||||
ldl @r2,rr4
|
||||
init3:
|
||||
inc r2,#4
|
||||
djnz r0,init2
|
||||
|
||||
ret ;return
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Exception Handler Routine
|
||||
;*
|
||||
;* An exception handler is called as a subroutine
|
||||
;* in segmented mode, with all registers saved
|
||||
;* on the stack.
|
||||
;*
|
||||
;* Returning (ret) from the handler (in segmented
|
||||
;* mode) will return to the state-restorer.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
exchndl:
|
||||
calr except
|
||||
excrtn0:
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
calr except
|
||||
|
||||
|
||||
except: ; general exception handler
|
||||
|
||||
ldctl r0,FCW ; NONSEGMENTED
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
popl rr0,@r15 ; get return address
|
||||
; from above array
|
||||
sub r1,#excrtn0 ; r1 now = 4*encoded
|
||||
srl r2,#2 ; exception number
|
||||
|
||||
; r1/4 = [0..21, 22..37] represents exceptions
|
||||
; [2..23, 32..47].
|
||||
;
|
||||
; If r1/4 is in the range [0..9, 22..29] then the
|
||||
; exception may be redirected by the BDOS.
|
||||
|
||||
cp r1,#36
|
||||
jr le chkredir
|
||||
cp r1,#88
|
||||
jr lt dfltexc
|
||||
cp r1,#116
|
||||
jr gt dfltexc
|
||||
; in range of redirected exceptions
|
||||
sub r1,#48 ; subtract 4*12 to normalize [0..9,22..29]
|
||||
; into [0..9,10..17]
|
||||
chkredir:
|
||||
ld r2,evec_adr ; index into exception
|
||||
; vector array
|
||||
ldl rr4,r2(r1) ; rr4 -> handler
|
||||
testl rr4 ; if non-zero
|
||||
jr nz usrexc ; go do it
|
||||
|
||||
;not redirected,
|
||||
; do default handler
|
||||
cp r1,#40
|
||||
jr lt dfltexc
|
||||
add r1,#48 ; add 4*12 sub'd above
|
||||
dfltexc:
|
||||
srl r1,#2 ; divide r1 by 4
|
||||
; r1 = [0..21,22..37]
|
||||
; meaning [2..23,32..47]
|
||||
add r1,#2 ;get back real except#
|
||||
cp r1,#23
|
||||
jr le lowexc
|
||||
add r2,#12
|
||||
lowexc:
|
||||
push @r15,r1 ; save exception #
|
||||
; print default msg
|
||||
clr r6
|
||||
ld r7,#excmsg1
|
||||
calr print
|
||||
calr prtdollar
|
||||
pop r1,@r15
|
||||
calr prtbyte
|
||||
clr r6
|
||||
ld r7,#excmsg2
|
||||
calr print
|
||||
calr prtdollar
|
||||
popl rr0,@r15
|
||||
calr prtlong
|
||||
clr r6
|
||||
ld r7,#excmsg3
|
||||
calr print
|
||||
|
||||
clr r5 ; warm boot
|
||||
sc #2
|
||||
ret
|
||||
|
||||
usrexc: ; call user exception handler
|
||||
; rr4 -> handler
|
||||
|
||||
; user exception handler called in with FCW restored
|
||||
; to that at the time of the exception, with the
|
||||
; stack containing a copy of the context block.
|
||||
; On top of the context block will be a GARBAGE
|
||||
; return address of the appropriate mode.
|
||||
|
||||
; Handler must exit with XFER system call.
|
||||
|
||||
; stack now contains:
|
||||
; return address (long) to trap_ret
|
||||
; normal r0..r15
|
||||
; reason, fcw, PC (long)
|
||||
|
||||
ld r1,38(r15) ;34+4 r1 = user FCW
|
||||
bit r1,#14 ;system mode?
|
||||
jr nz sysexc ; yes
|
||||
; no
|
||||
ldl rr2,32(r15) ;28+4 rr2 = user stack
|
||||
bit r1,#15 ;segmented?
|
||||
jr nz segusrx ; yes
|
||||
; no -- get seg
|
||||
ld r2,42(r15) ;38+4
|
||||
segusrx:
|
||||
ldctl r0,FCW ;go segmented
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
sub r3,#44 ;copy frame to usr
|
||||
; (with junk PC)
|
||||
ld r0,#22
|
||||
ldir @r2,@r14,r0
|
||||
|
||||
pushl @r14,rr4 ;go
|
||||
pushl @r14,rr0
|
||||
iret
|
||||
|
||||
sysexc: ;system mode exc.
|
||||
set r1,#15 ; go segmented
|
||||
ldctl FCW,r1
|
||||
jp @r4 ;go
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Subroutines
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
print:
|
||||
ld r5,#9 ;PRINTMSG
|
||||
sc #2 ;BDOS
|
||||
ret
|
||||
|
||||
prtdollar:
|
||||
ld r5,#2 ;PRINTCHAR
|
||||
ldl rr6,#24h ; dollarsign
|
||||
sc #2
|
||||
ret
|
||||
|
||||
prtlong: ; print rr0 as hex long
|
||||
push @r15,r1
|
||||
ex r0,r1
|
||||
calr prtword
|
||||
pop r1,@r15
|
||||
|
||||
prtword: ; print r1 as hex word
|
||||
push @r15,r1
|
||||
ldb rl1,rh1
|
||||
calr prtbyte
|
||||
pop r1,@r15
|
||||
|
||||
prtbyte: ; Print rl1 as hex byte
|
||||
push @r15,r1
|
||||
srl r1,#4
|
||||
calr prtnib
|
||||
pop r1,@r15
|
||||
|
||||
prtnib:
|
||||
and r1,#15
|
||||
cp r1,#10
|
||||
jr lt lt10
|
||||
add r1,#7
|
||||
lt10:
|
||||
add r1,#30h
|
||||
ld r7,r1
|
||||
ld r5,#2 ;PRINTBYTE
|
||||
sc #2 ;BDOS
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* data
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__data: .sect
|
||||
|
||||
excmsg1:
|
||||
.byte 13,10,10,"Exception $"
|
||||
|
||||
excmsg2:
|
||||
.byte " at user address $"
|
||||
|
||||
excmsg3:
|
||||
.byte ". Aborted.$"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* bss
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
evec_adr:
|
||||
.block 2
|
||||
|
||||
.end
|
||||
@@ -0,0 +1,662 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS File I/O Module *
|
||||
* *
|
||||
* This module contains all file handling BDOS functions *
|
||||
* except for read and write for P-CP/M. Included are: *
|
||||
* *
|
||||
* seldsk() - select disk *
|
||||
* openfile() - open file *
|
||||
* close_fi() - close file *
|
||||
* search() - search for first/next file match *
|
||||
* create() - create file *
|
||||
* delete() - delete file *
|
||||
* rename() - rename file *
|
||||
* set_attr() - set file attributes *
|
||||
* getsize() - get file size *
|
||||
* setran() - set random record field *
|
||||
* free_sp() - get disk free space *
|
||||
* move() - general purpose byte mover *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on Z8000 *
|
||||
* The main change is that search no longer calls tmp_sel *
|
||||
* tmp_sel in bdosmain.c now handles drive number = '?' *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* and BIOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
/* declare external fucntions */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN UWORD error(); /* disk error routine */
|
||||
EXTERN UWORD do_phio(); /* packet disk i/o handler */
|
||||
EXTERN clraloc(); /* clear bit in allocation vector */
|
||||
EXTERN setaloc(); /* set bit in allocation vector */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dir_wr(); /* directory write routine */
|
||||
EXTERN tmp_sel(); /* temporary select disk routine */
|
||||
EXTERN UWORD calcext(); /* calc max extent allocated for fcb */
|
||||
EXTERN UWORD udiv(); /* unsigned divide routine */
|
||||
|
||||
|
||||
/* declare external variables */
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* vector of disks in critical state */
|
||||
|
||||
|
||||
/************************************
|
||||
* This function passed to dirscan *
|
||||
* from seldsk (below) *
|
||||
************************************/
|
||||
|
||||
BOOLEAN alloc(fcbp, dirp, dirindx) /* ARGSUSED */
|
||||
/* Set up allocation vector for directory entry pointed to by dirp */
|
||||
|
||||
struct fcb *fcbp; /* not used in this function */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory for *dirp */
|
||||
{
|
||||
REG WORD i; /* loop counter */
|
||||
BSETUP
|
||||
|
||||
if ( UBWORD(dirp->entry) < 0x10 ) /* skip MP/M 2.x and CP/M 3.x XFCBs */
|
||||
{
|
||||
(GBL.dphp)->hiwater = dirindx; /* set up high water mark for disk */
|
||||
i = 0;
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{
|
||||
do setaloc( UBWORD(dirp->dskmap.small[i++]) );
|
||||
while (i <= 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
do setaloc(swap(dirp->dskmap.big[i++]));
|
||||
while (i <= 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* seldsk entry point *
|
||||
************************/
|
||||
|
||||
seldsk(dsknum)
|
||||
|
||||
REG UBYTE dsknum; /* disk number to select */
|
||||
|
||||
{
|
||||
struct iopb selpkt;
|
||||
REG WORD i;
|
||||
UWORD j;
|
||||
REG UBYTE logflag;
|
||||
BSETUP
|
||||
|
||||
logflag = ~(log_dsk >> dsknum) & 1;
|
||||
if ((GBL.curdsk != dsknum) || logflag)
|
||||
{ /* if not last used disk or not logged on */
|
||||
selpkt.iofcn = sel_info;
|
||||
GBL.curdsk = (selpkt.devnum = dsknum);
|
||||
if (UBWORD(dsknum) > 15) error(2);
|
||||
selpkt.ioflags = logflag ^ 1;
|
||||
do
|
||||
{
|
||||
do_phio(&selpkt); /* actually do the disk select */
|
||||
if ( (GBL.dphp = (struct dph *)selpkt.infop) != NULL ) break;
|
||||
} while ( ! error(3) );
|
||||
|
||||
GBL.dirbufp = (GBL.dphp)->dbufp;
|
||||
/* set up GBL copies of dir_buf and dpb ptrs */
|
||||
GBL.parmp = (GBL.dphp)->dpbp;
|
||||
}
|
||||
if (logflag)
|
||||
{ /* if disk not previously logged on, do it now */
|
||||
LOCK /* must lock the file system while messing with alloc vec */
|
||||
i = (GBL.parmp)->dsm;
|
||||
do clraloc(i); while (i--); /* clear the allocation vector */
|
||||
i = udiv( (LONG)(((GBL.parmp)->drm) + 1),
|
||||
4 * (((GBL.parmp)->blm) + 1), &j);
|
||||
/* calculate nmbr of directory blks */
|
||||
if (j) i++; /* round up */
|
||||
do setaloc(--i); while (i); /* alloc directory blocks */
|
||||
dirscan(alloc, NULL, 0x0e); /* do directory scan & alloc blocks */
|
||||
log_dsk |= 1 << dsknum; /* mark disk as logged in */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
* General purpose byte mover *
|
||||
*******************************/
|
||||
|
||||
move(p1, p2, i)
|
||||
|
||||
REG BYTE *p1;
|
||||
REG BYTE *p2;
|
||||
REG WORD i;
|
||||
{
|
||||
while (i--)
|
||||
*p2++ = *p1++;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* General purpose filename matcher *
|
||||
*************************************/
|
||||
|
||||
BOOLEAN match(p1, p2, chk_ext)
|
||||
|
||||
REG UBYTE *p1;
|
||||
REG UBYTE *p2;
|
||||
BOOLEAN chk_ext;
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE temp;
|
||||
BSETUP
|
||||
|
||||
i = 12;
|
||||
do
|
||||
{
|
||||
temp = (*p1 ^ '?');
|
||||
if ( ((*p1++ ^ *p2++) & 0x7f) && temp )
|
||||
return(FALSE);
|
||||
i -= 1;
|
||||
} while (i);
|
||||
if (chk_ext)
|
||||
{
|
||||
if ( (*p1 != '?') && ((*p1 ^ *p2) & ~((GBL.parmp)->exm)) )
|
||||
return(FALSE);
|
||||
p1 += 2;
|
||||
p2 += 2;
|
||||
if ((*p1 ^ *p2) & 0x3f) return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* openfile entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN openfile(fcbp, dirp, dirindx) /* ARGSUSED */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to open */
|
||||
struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx;
|
||||
|
||||
{
|
||||
REG UBYTE fcb_ext; /* extent field from fcb */
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, TRUE) )
|
||||
{
|
||||
fcb_ext = fcbp->extent; /* save extent number from user's fcb */
|
||||
move(dirp, fcbp, sizeof *dirp);
|
||||
/* copy dir entry into user's fcb */
|
||||
fcbp->extent = fcb_ext;
|
||||
fcbp->s2 |= 0x80; /* set hi bit of S2 (write flag) */
|
||||
crit_dsk |= 1 << (GBL.curdsk);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* flush buffers routine */
|
||||
/*************************/
|
||||
|
||||
UWORD flushit()
|
||||
{
|
||||
REG UWORD rtn; /* return code from flush buffers call */
|
||||
struct iopb flushpkt; /* I/O packet for flush buffers call */
|
||||
|
||||
flushpkt.iofcn = flush;
|
||||
while ( rtn = do_phio(&flushpkt) )
|
||||
if ( error(1) ) break;
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* file close routine for dirscan *
|
||||
*********************************/
|
||||
|
||||
BOOLEAN close(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE *fp;
|
||||
REG UBYTE *dp;
|
||||
REG UWORD fcb_ext;
|
||||
REG UWORD dir_ext;
|
||||
BSETUP
|
||||
|
||||
if ( match(fcbp, dirp, TRUE) )
|
||||
{ /* Note that FCB merging is done here as a final
|
||||
confirmation that disks haven't been swapped */
|
||||
LOCK
|
||||
fp = &(fcbp->dskmap.small[0]);
|
||||
dp = &(dirp->dskmap.small[0]);
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{ /* Small disk map merge routine */
|
||||
i = 16;
|
||||
do
|
||||
{
|
||||
if (*dp)
|
||||
{
|
||||
if (*fp)
|
||||
{
|
||||
if (*dp != *fp) goto badmerge;
|
||||
}
|
||||
else *fp = *dp;
|
||||
}
|
||||
else *dp = *fp;
|
||||
fp += 1;
|
||||
dp += 1;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
}
|
||||
else
|
||||
{ /* Large disk map merge routine */
|
||||
i = 8;
|
||||
do
|
||||
{
|
||||
if (*(UWORD *)dp)
|
||||
{
|
||||
if (*(UWORD *)fp)
|
||||
{
|
||||
if (*(UWORD *)dp != *(UWORD *)fp) goto badmerge;
|
||||
}
|
||||
else *(UWORD *)fp = *(UWORD *)dp;
|
||||
}
|
||||
else *(UWORD *)dp = *(UWORD *)fp;
|
||||
fp += sizeof (UWORD);
|
||||
dp += sizeof (UWORD);
|
||||
i -= 1;
|
||||
} while (i);
|
||||
}
|
||||
/* Disk map merging complete */
|
||||
fcb_ext = calcext(fcbp); /* calc max extent for fcb */
|
||||
dir_ext = (UWORD)(dirp->extent) & 0x1f;
|
||||
if ( (fcb_ext > dir_ext) ||
|
||||
((fcb_ext == dir_ext) &&
|
||||
(UBWORD(fcbp->rcdcnt) > UBWORD(dirp->rcdcnt))) )
|
||||
/* if fcb points to larger file than dirp */
|
||||
{
|
||||
dirp->rcdcnt = fcbp->rcdcnt; /* set up rc, ext from fcb */
|
||||
dirp->extent = (BYTE)fcb_ext;
|
||||
}
|
||||
dirp->s1 = fcbp->s1;
|
||||
if ( (fcbp->ftype[robit]) & 0x80) error(5,fcbp);
|
||||
/* read-only file error */
|
||||
dirp->ftype[arbit] &= 0x7f; /* clear archive bit */
|
||||
dir_wr(dirindx >> 2);
|
||||
UNLOCK
|
||||
return(TRUE);
|
||||
|
||||
badmerge:
|
||||
UNLOCK
|
||||
ro_dsk |= (1 << GBL.curdsk);
|
||||
return(FALSE);
|
||||
}
|
||||
else return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* close_fi entry point *
|
||||
************************/
|
||||
|
||||
UWORD close_fi(fcbp)
|
||||
|
||||
struct fcb *fcbp; /* pointer to fcb for file to close */
|
||||
{
|
||||
flushit(); /* first, flush the buffers */
|
||||
if ((fcbp->s2) & 0x80) return(0); /* if file write flag not on,
|
||||
don't need to do physical close */
|
||||
return( dirscan(close, fcbp, 0)); /* call dirscan with close function */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* search entry point *
|
||||
************************/
|
||||
|
||||
/* First two functions for dirscan */
|
||||
|
||||
BOOLEAN alltrue(p1, p2, i) /* ARGSUSED */
|
||||
UBYTE *p1;
|
||||
UBYTE *p2;
|
||||
WORD i;
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
BOOLEAN matchit(p1, p2, i) /* ARGSUSED */
|
||||
UBYTE *p1;
|
||||
UBYTE *p2;
|
||||
WORD i;
|
||||
{
|
||||
return(match(p1, p2, TRUE));
|
||||
}
|
||||
|
||||
|
||||
/* search entry point */
|
||||
UWORD search(fcbp, dsparm, p) /* ARGSUSED */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to search */
|
||||
REG UWORD dsparm; /* parameter to pass through to dirscan */
|
||||
UBYTE *p; /* pointer to pass through to tmp_sel */
|
||||
/* -- now unused -- */
|
||||
|
||||
{
|
||||
REG UWORD rtn; /* return value */
|
||||
BSETUP
|
||||
|
||||
if (fcbp->drvcode == '?')
|
||||
{
|
||||
rtn = dirscan(alltrue, fcbp, dsparm);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fcbp->extent != '?') fcbp->extent = 0;
|
||||
fcbp->s2 = 0;
|
||||
rtn = dirscan(matchit, fcbp, dsparm);
|
||||
}
|
||||
cpy_out( GBL.dirbufp, GBL.dmaadr, SECLEN);
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* create entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN create(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to create */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BYTE *p;
|
||||
REG WORD i;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = ((dirp->entry) == 0xe5) )
|
||||
{
|
||||
p = &(fcbp->rcdcnt);
|
||||
i = 17;
|
||||
do
|
||||
{ /* clear fcb rcdcnt and disk map */
|
||||
*p++ = 0;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
move(fcbp, dirp, sizeof *dirp); /* move the fcb to the directory */
|
||||
dir_wr(dirindx >> 2); /* write the directory sector */
|
||||
if ( dirindx > (GBL.dphp)->hiwater )
|
||||
(GBL.dphp)->hiwater = dirindx;
|
||||
crit_dsk |= 1 << (GBL.curdsk);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* delete entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN delete(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
if ( (dirp->ftype[robit]) & 0x80 ) error(5,fcbp);
|
||||
/* check for read-only file */
|
||||
dirp->entry = 0xe5;
|
||||
LOCK
|
||||
dir_wr(dirindx >> 2);
|
||||
/* Now free up the space in the allocation vector */
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{
|
||||
i = 16;
|
||||
do clraloc(UBWORD(dirp->dskmap.small[--i]));
|
||||
while (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 8;
|
||||
do clraloc(swap(dirp->dskmap.big[--i]));
|
||||
while (i);
|
||||
}
|
||||
UNLOCK
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* rename entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN rename(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p; /* general purpose pointers */
|
||||
REG BYTE *q;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
if ( (dirp->ftype[robit]) & 0x80 ) error(5,fcbp);
|
||||
/* check for read-only file */
|
||||
p = &(fcbp->dskmap.small[1]);
|
||||
q = &(dirp->fname[0]);
|
||||
i = 11;
|
||||
do
|
||||
{
|
||||
*q++ = *p++ & 0x7f;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
dir_wr(dirindx >> 2);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* set_attr entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN set_attr(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
move(&fcbp->fname[0], &dirp->fname[0], 11);
|
||||
dir_wr(dirindx >> 2);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* utility routine used by *
|
||||
* setran and getsize *
|
||||
****************************/
|
||||
|
||||
LONG extsize(fcbp)
|
||||
/* Return size of extent pointed to by fcbp */
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
return( ((LONG)(fcbp->extent & 0x1f) << 7)
|
||||
| ((LONG)(fcbp->s2 & 0x3f) << 12) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* setran entry point *
|
||||
************************/
|
||||
|
||||
setran(fcbp)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to set ran rec */
|
||||
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
LONG random;
|
||||
|
||||
random = (LONG)UBWORD(fcbp->cur_rec) + extsize(fcbp);
|
||||
/* compute random record field */
|
||||
fcbp->ran0 = random.b2;
|
||||
fcbp->ran1 = random.b1;
|
||||
fcbp->ran2 = random.b0;
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/* fsize is a funtion for dirscan */
|
||||
/* passed from getsize */
|
||||
/**********************************/
|
||||
|
||||
BOOLEAN fsize(fcbp, dirp, dirindx) /* ARGSUSED */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BOOLEAN rtn;
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
LONG temp;
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
temp = (LONG)UBWORD(dirp->rcdcnt) + extsize(dirp);
|
||||
/* compute file size */
|
||||
fcbp->ran0 = temp.b2;
|
||||
fcbp->ran1 = temp.b1;
|
||||
fcbp->ran2 = temp.b0;
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
/************************
|
||||
* getsize entry point *
|
||||
************************/
|
||||
|
||||
getsize(fcbp)
|
||||
/* get file size */
|
||||
REG struct fcb *fcbp; /* pointer to fcb to get file size for */
|
||||
|
||||
{
|
||||
LONG maxrcd;
|
||||
LONG temp;
|
||||
REG WORD dsparm;
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
|
||||
maxrcd = 0;
|
||||
dsparm = 0;
|
||||
temp = 0;
|
||||
while ( dirscan(fsize, fcbp, dsparm) < 255 )
|
||||
{ /* loop until no more matches */
|
||||
temp.b2 = fcbp->ran0;
|
||||
temp.b1 = fcbp->ran1;
|
||||
temp.b0 = fcbp->ran2;
|
||||
if (temp > maxrcd) maxrcd = temp;
|
||||
dsparm = 1;
|
||||
}
|
||||
fcbp->ran0 = maxrcd.b2;
|
||||
fcbp->ran1 = maxrcd.b1;
|
||||
fcbp->ran2 = maxrcd.b0;
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* free_sp entry point *
|
||||
************************/
|
||||
|
||||
free_sp(dsknum)
|
||||
|
||||
UBYTE dsknum; /* disk number to get free space of */
|
||||
{
|
||||
LONG records;
|
||||
REG UWORD *alvec;
|
||||
REG UWORD bitmask;
|
||||
REG UWORD alvword;
|
||||
REG WORD i;
|
||||
BSETUP
|
||||
|
||||
seldsk(dsknum); /* select the disk */
|
||||
records = (LONG)0; /* initialize the variables */
|
||||
alvec = (GBL.dphp)->alv;
|
||||
bitmask = 0;
|
||||
for (i = 0; i <= (GBL.parmp)->dsm; i++) /* for loop to compute */
|
||||
{
|
||||
if ( ! bitmask)
|
||||
{
|
||||
bitmask = 0x8000;
|
||||
alvword = ~(*alvec++);
|
||||
}
|
||||
if ( alvword & bitmask)
|
||||
records += (LONG)( ((GBL.parmp)->blm) + 1 );
|
||||
bitmask >>= 1;
|
||||
}
|
||||
/* move # records to DMA address */
|
||||
cpy_out(&records, GBL.dmaadr, sizeof records);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Disk I/O System Module *
|
||||
* *
|
||||
* This module translates from the packet oriented I/O *
|
||||
* passed from the other BDOS modules into BIOS calls. *
|
||||
* *
|
||||
* It includes only one external entry point: *
|
||||
* do_phio() - do physical i/o *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on Z8000 *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
#include "biosdef.h" /* Declarations for BIOS entry points */
|
||||
|
||||
EXTERN udiv(); /* Assembly language unsigned divide routine */
|
||||
/* in bdosif.s. It's used because Alcyon C */
|
||||
/* can't do / or % without an external */
|
||||
|
||||
/************************
|
||||
* do_phio entry point *
|
||||
************************/
|
||||
|
||||
UWORD do_phio(iop)
|
||||
|
||||
REG struct iopb *iop; /* iop is a pointer to a i/o parameter block */
|
||||
|
||||
{
|
||||
MLOCAL UBYTE last_dsk; /* static variable to tell which disk
|
||||
was last used, to avoid disk selects */
|
||||
REG struct dph *hdrp; /* pointer to disk parameter header */
|
||||
REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
REG UWORD rtn; /* return parameter */
|
||||
UWORD iosect; /* sector number returned from divide rtn */
|
||||
|
||||
LOCK /* lock the disk system while doing physical i/o */
|
||||
|
||||
rtn = 0;
|
||||
switch (iop->iofcn)
|
||||
{
|
||||
case sel_info:
|
||||
last_dsk = iop->devnum;
|
||||
iop->infop = bseldsk(last_dsk, iop->ioflags);
|
||||
break;
|
||||
|
||||
case read:
|
||||
case write:
|
||||
if (last_dsk != iop->devnum)
|
||||
bseldsk((last_dsk = iop->devnum), 0);
|
||||
/* guaranteed disk is logged on, because temp_sel in
|
||||
BDOSMAIN does it */
|
||||
hdrp = iop->infop;
|
||||
dparmp = hdrp->dpbp;
|
||||
|
||||
bsettrk( udiv( iop->devadr, dparmp->spt, (long)&iosect )
|
||||
+ dparmp->trk_off );
|
||||
bsetsec( bsectrn( iosect, hdrp->xlt ) );
|
||||
bsetdma(iop->xferadr);
|
||||
if ((iop->iofcn) == read) rtn = bread();
|
||||
else rtn = bwrite(iop->ioflags);
|
||||
break;
|
||||
|
||||
case flush:
|
||||
rtn = bflush();
|
||||
}
|
||||
|
||||
UNLOCK
|
||||
return(rtn);
|
||||
}
|
||||
@@ -0,0 +1,482 @@
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-8000 BDOS Program Loader *
|
||||
* *
|
||||
* Copyright (c) 1982 Zilog Incorporated *
|
||||
* *
|
||||
* This function implements BDOS call 59: Program Load. *
|
||||
* The single parameter passed is a pointer to a space *
|
||||
* where a partially filled LPB (Load Parameter Block) *
|
||||
* can be found. pgmld must fill in the base page *
|
||||
* address and the starting user stack pointer. In *
|
||||
* addition, the Z8000 implementation will set a loader *
|
||||
* flag if the program being loaded uses separate I/D *
|
||||
* space or segmentation. *
|
||||
* *
|
||||
* NOTE! unlike the usual CP/M loader, the Z8000 loader *
|
||||
* returns the actual starting address of the code segment *
|
||||
* (starting PC) in the LPB, clobbering the program load *
|
||||
* address. This is because the segment containing the *
|
||||
* code may not be known until load time. *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard declarations for BDOS, BIOS */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* Declarations of BIOS functions */
|
||||
|
||||
#include "basepage.h" /* Base page structure */
|
||||
|
||||
#include "x.out.h" /* structure of x.out (".Z8[KS] file") */
|
||||
|
||||
#define SPLIT 0x4000 /* Separate I/D flag for LPB */
|
||||
#define SEG 0x2000 /* Segmented code flag for TPA */
|
||||
#define NSEG 16 /* Maximum number of x.out segments */
|
||||
#define SEGLEN 0x10000 /* Length of a Z8000 segment */
|
||||
/* Address of basepage (near top of TPA)*/
|
||||
#define BPLEN (sizeof (struct b_page))
|
||||
#define DEFSTACK 0x100 /* Default stack length */
|
||||
#define NREGIONS 2 /* Number of regions in the MRT */
|
||||
|
||||
/* return values */
|
||||
|
||||
#define GOOD 0 /* good return value */
|
||||
#define BADHDR 1 /* bad header */
|
||||
#define NOMEM 2 /* not enough memory */
|
||||
#define READERR 3 /* read error */
|
||||
|
||||
#define MYDATA 0 /* Argument for map_adr */
|
||||
#define TPAPROG 5 /* Argument for map_adr */
|
||||
#define TPADATA 4 /* Argument for map_adr */
|
||||
/* Get actual code segment (as opposed */
|
||||
/* to segment where it can be accessed*/
|
||||
/* as data) */
|
||||
#define TRUE_TPAPROG (TPAPROG | 0x100)
|
||||
|
||||
struct lpb /* Load Parameter Block */
|
||||
{
|
||||
XADDR fcbaddr;/* Address of fcb of opened file */
|
||||
XADDR pgldaddr;/* Low address of prog load area */
|
||||
XADDR pgtop; /* High address of prog load area, +1 */
|
||||
XADDR bpaddr; /* Address of basepage; return value */
|
||||
XADDR stackptr;/* Stack ptr of user; return value */
|
||||
short flags; /* Loader control flags; return value */
|
||||
} mylpb;
|
||||
|
||||
struct ustack /* User's initial stack - nonsegmented */
|
||||
{
|
||||
short two; /* "Return address" (actually address */
|
||||
/* of warm boot call in user's startup)*/
|
||||
short bpoffset;/* Pointer to basepage */
|
||||
};
|
||||
|
||||
struct sstack /* User's initial stack - segmented */
|
||||
{
|
||||
XADDR stwo; /* "Return address" (actually address */
|
||||
/* of warm boot call in user's startup)*/
|
||||
XADDR sbpadr; /* Pointer to basepage */
|
||||
};
|
||||
|
||||
|
||||
struct m_rt { /* The Memory Region Table */
|
||||
int count;
|
||||
struct {
|
||||
XADDR tpalow;
|
||||
XADDR tpalen;
|
||||
} m_reg[NREGIONS];
|
||||
};
|
||||
|
||||
#define SPREG 1 /* The MRT region for split I/D programs */
|
||||
#define NSPREG 0 /* The MRT region for non-split programs */
|
||||
#define SDREG 2 /* The MRT region for split I/D data */
|
||||
#define NSDREG 0 /* The MRT region for non-split data */
|
||||
|
||||
#define READ 20 /* Read Sequential BDOS call */
|
||||
#define SETDMA 26 /* Set DMA Address BDOS call */
|
||||
extern UWORD bdos(); /* To do I/O into myself (note this */
|
||||
/* function does not map 2nd param - */
|
||||
/* see mbdos macro below) */
|
||||
|
||||
static XADDR textloc, /* Physical locations of pgm sections. */
|
||||
dataloc,
|
||||
bssloc,
|
||||
stkloc;
|
||||
|
||||
static XADDR textsiz, /* Sizes of the various sections. */
|
||||
datasiz,
|
||||
bsssiz,
|
||||
stksiz;
|
||||
|
||||
static UWORD split, /* Tells if split I/D or not */
|
||||
seg; /* Tells if segmented or not */
|
||||
|
||||
static char *gp; /* Buffer pointer for char input */
|
||||
static char *mydma; /* Local address of read buffer */
|
||||
|
||||
struct x_hdr x_hdr; /* Object File Header structure */
|
||||
struct x_sg x_sg[NSEG]; /* Segment Header structure */
|
||||
|
||||
static XADDR segsiz[NSEG]; /* Segment lengths */
|
||||
static XADDR seglim[NSEG]; /* Segment length limits */
|
||||
static XADDR segloc[NSEG]; /* Segment base physical addresses */
|
||||
|
||||
static short textseg, /* Logical seg # of various segments */
|
||||
dataseg,
|
||||
bssseg,
|
||||
stkseg;
|
||||
|
||||
|
||||
/********************************/
|
||||
/* */
|
||||
/* Start of pgmld function */
|
||||
/* */
|
||||
/********************************/
|
||||
|
||||
UWORD pgmld(xlpbp) /* Load a program from LPB info */
|
||||
XADDR xlpbp;
|
||||
{ register int i,j; /* Temporary counters etc. */
|
||||
struct m_rt *mrp; /* Pointer to a MRT structure */
|
||||
char mybuf[SECLEN]; /* Local buffer for file reading*/
|
||||
|
||||
/* get local LPB copy */
|
||||
cpy_in(xlpbp, &mylpb, (long) sizeof mylpb);
|
||||
|
||||
mydma = mybuf; /* Initialize addr for local DMA*/
|
||||
gp = &mybuf[SECLEN]; /* Point beyond end of buffer */
|
||||
|
||||
mrp = (struct m_rt *) bgetseg();/* Get address of memory region */
|
||||
/* table (note segment # lost)*/
|
||||
if (readhdr() == EOF) /* Get x.out file header */
|
||||
return (READERR); /* Read error on header */
|
||||
|
||||
switch (x_hdr.x_magic) /* Is this acceptable x.out file*/
|
||||
{
|
||||
case X_NXN_MAGIC: /* Non-seg, combined I & D */
|
||||
split = FALSE;
|
||||
seg = FALSE;
|
||||
break;
|
||||
|
||||
case X_NXI_MAGIC: /* Non-seg, separate I & D */
|
||||
split = SPLIT;
|
||||
seg = FALSE;
|
||||
break;
|
||||
|
||||
case X_SX_MAGIC: /* Segmented - must be combined */
|
||||
split = FALSE;
|
||||
seg = SEG;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (BADHDR); /* Sorry, can't load it! */
|
||||
}
|
||||
|
||||
/* Set the user space segment number, from the low address in the */
|
||||
/* appropriate entry of the MRT. */
|
||||
/* m_reg[SPREG] is the region used for split I/D programs in the MRT */
|
||||
/* m_reg[NSPREG] is used for non-split. */
|
||||
/* -1 is used for segmented */
|
||||
|
||||
/* NOTE -- the tpa limits passed in the LPB are ignored. This is */
|
||||
/* incorrect, but saves the caller from having to look at the */
|
||||
/* load module to determine the magic number. */
|
||||
|
||||
map_adr(seg ? -1L
|
||||
: (mrp->m_reg[split ? SPREG : NSPREG].tpalow),
|
||||
0xffff);
|
||||
|
||||
for (i = 0; i < x_hdr.x_nseg; i++) { /* For each segment... */
|
||||
if( readxsg(i) == EOF) /* ...get segment hdr */
|
||||
return(READERR);
|
||||
seglim[i] = SEGLEN; /* ...set max length */
|
||||
segsiz[i] = 0L; /* ...and current size */
|
||||
}
|
||||
|
||||
/* Set section base addresses */
|
||||
|
||||
textloc = dataloc = bssloc = stkloc = 0L;
|
||||
|
||||
/* Zero section sizes */
|
||||
textsiz = datasiz = bsssiz = 0L;
|
||||
stksiz = DEFSTACK;
|
||||
|
||||
|
||||
if (seg) { /* Locate text & data segments */
|
||||
/* if segmented we know nothing */
|
||||
textseg = dataseg = bssseg = stkseg = 0;
|
||||
} else { /* if nonsegmented ... */
|
||||
/* assign segment numbers */
|
||||
textseg = 0;
|
||||
dataseg = (split) ? 1 : 0;
|
||||
stkseg = bssseg = dataseg;
|
||||
|
||||
/* assign locations */
|
||||
segloc[textseg] = map_adr(0L, TPAPROG);
|
||||
if (split)
|
||||
segloc[dataseg] = map_adr(0L, TPADATA);
|
||||
|
||||
/* Assign limits */
|
||||
seglim[textseg] = SEGLEN;
|
||||
seglim[dataseg] = mrp->m_reg[split ? SDREG : NSDREG].tpalen
|
||||
- BPLEN - stksiz;
|
||||
|
||||
/* Assign stack location */
|
||||
stkloc = segloc[dataseg] + seglim[dataseg] + stksiz;
|
||||
}
|
||||
|
||||
for (i = 0; i < x_hdr.x_nseg; i++) /* For each segment... */
|
||||
if( (j = loadseg(i)) != GOOD) /* ...load memory. If */
|
||||
return (j); /* error return, pass */
|
||||
/* it back. */
|
||||
setbase(setaddr(&mylpb)); /* Set addresses in LPB,*/
|
||||
/* Set up base page */
|
||||
cpy_out((XADDR) &mylpb, xlpbp, sizeof mylpb);
|
||||
return (GOOD);
|
||||
}
|
||||
|
||||
|
||||
/* Macro to call BDOS. First parameter is passed unchanged, second */
|
||||
/* is cast into an XADR, then mapped to caller data space. */
|
||||
|
||||
#define mbdos(func, param) (bdos((func), map_adr((XADDR) (param), MYDATA)))
|
||||
|
||||
|
||||
/* Macro to read the next character from the input file (much faster */
|
||||
/* than having to make a function call for each byte) */
|
||||
|
||||
#define fgetch() ((gp<mydma+SECLEN) ? (int)*gp++&0xff : fillbuff())
|
||||
|
||||
|
||||
/* Routine to fill input buffer when fgetch macro detects it is empty */
|
||||
|
||||
|
||||
int fillbuf() /* Returns first char in buffer */
|
||||
{ /* or EOF if read fails */
|
||||
/* Set up address to read into */
|
||||
mbdos(SETDMA, mydma);
|
||||
if (bdos(READ, mylpb.fcbaddr) != 0) /* Have BDOS do the read*/
|
||||
return (EOF);
|
||||
gp = mydma; /* Initialize buffer pointer */
|
||||
return ((int)*gp++ & 0xff); /* Return first character */
|
||||
}
|
||||
|
||||
/* Routine to read the file header */
|
||||
|
||||
int readhdr()
|
||||
{
|
||||
register int n, k;
|
||||
register char *p;
|
||||
|
||||
p = (char *) &x_hdr;
|
||||
for (n = 0; n < sizeof (struct x_hdr); n++) {
|
||||
if( (k = fgetch()) == EOF)
|
||||
return (k);
|
||||
*p++ = (char) k;
|
||||
}
|
||||
return (GOOD);
|
||||
}
|
||||
|
||||
/* Routine to read the header for segment i */
|
||||
|
||||
int readxsg(i)
|
||||
int i;
|
||||
{
|
||||
register int n, k;
|
||||
register char *p;
|
||||
|
||||
p = (char *) &x_sg[i];
|
||||
for(n = 0; n < sizeof (struct x_sg); n++) {
|
||||
if ( (k = fgetch()) == EOF)
|
||||
return (READERR);
|
||||
*p++ = (char) k;
|
||||
}
|
||||
return (GOOD);
|
||||
}
|
||||
|
||||
/* Routine to load segment number i */
|
||||
/* This assumes that the segments occur in load order in the file, and */
|
||||
/* that all initialized data and, in the case of combined I/D programs, */
|
||||
/* text segments, precede all bss segments. */
|
||||
|
||||
/* In the case of segmented programs, the stack segment must exist, */
|
||||
/* and all segments are presumed to be of maximum length. */
|
||||
/* Text, data, bss, and stack lengths are sum of lengths of all such */
|
||||
/* segments, and so may be bigger than maximum segment length. */
|
||||
|
||||
int loadseg(i)
|
||||
int i;
|
||||
{
|
||||
register UWORD l, length; /* Total, incremental length */
|
||||
register int type; /* Type of segment loaded */
|
||||
register short lseg; /* logical segment index */
|
||||
register XADDR phystarg; /* physical target load address */
|
||||
|
||||
l = x_sg[i].x_sg_len; /* number of bytes to load */
|
||||
type = x_sg[i].x_sg_typ; /* Type of segment */
|
||||
|
||||
lseg = textseg; /* try putting in text space */
|
||||
|
||||
if (split) { /* If separate I/D, this may */
|
||||
switch (type) /* be a bad guess */
|
||||
{
|
||||
case X_SG_CON: /* Separate I/D: all data goes */
|
||||
case X_SG_DATA: /* in data space */
|
||||
case X_SG_BSS:
|
||||
case X_SG_STK:
|
||||
lseg = dataseg;
|
||||
}
|
||||
}
|
||||
|
||||
if (seg) { /* If segmented, compute phys. */
|
||||
/* address of segment */
|
||||
|
||||
/* search to see if seg was used already */
|
||||
/* if so, use the same logical segment index. */
|
||||
/* (if not, loop ends with lseg == i) */
|
||||
|
||||
for (lseg = 0;
|
||||
x_sg[lseg].x_sg_no != x_sg[i].x_sg_no;
|
||||
lseg++) ;
|
||||
|
||||
segloc[lseg] = ((long)x_sg[i].x_sg_no) << 24;
|
||||
}
|
||||
|
||||
phystarg = segloc[lseg] + segsiz[lseg]; /* physical target addr */
|
||||
|
||||
switch (type) /* Now load data, if necessary */
|
||||
/* save physical address & size */
|
||||
{
|
||||
case X_SG_BSS: /* BSS gets cleared by runtime */
|
||||
/* startup. */
|
||||
stkloc = (phystarg & 0xffff0000L) + SEGLEN - BPLEN - stksiz;
|
||||
/* ...in case no stack segment */
|
||||
if (bssloc == 0L) bssloc = phystarg;
|
||||
bsssiz += l;
|
||||
if ((segsiz[lseg] += l) >= seglim[lseg])
|
||||
return (NOMEM);
|
||||
return (GOOD); /* Transfer no data */
|
||||
|
||||
case X_SG_STK: /* Stack segment: */
|
||||
if (stkloc == 0L) { /* if segmented, we now */
|
||||
/* know where to put */
|
||||
seglim[lseg] -= BPLEN; /* the base page */
|
||||
stkloc = segloc[lseg] + seglim[lseg];
|
||||
}
|
||||
|
||||
stkseg = lseg;
|
||||
stksiz += l; /* adjust size and */
|
||||
seglim[lseg] -= l; /* memory limit */
|
||||
if (segsiz[lseg] >= seglim[lseg])
|
||||
return (NOMEM);
|
||||
return (GOOD); /* Transfer no data */
|
||||
|
||||
case X_SG_COD: /* Pure text segment */
|
||||
case X_SG_MXU: /* Dirty code/data (better not)*/
|
||||
case X_SG_MXP: /* Clean code/data (be sep I/D)*/
|
||||
if (textloc == 0L) textloc = phystarg;
|
||||
textsiz += l;
|
||||
break;
|
||||
|
||||
case X_SG_CON: /* Constant (clean) data */
|
||||
case X_SG_DAT: /* Dirty data */
|
||||
stkloc = (phystarg & 0xffff0000L) + SEGLEN - BPLEN - stksiz;
|
||||
/* ...in case no stack or */
|
||||
/* bss segments */
|
||||
if (dataloc == 0L) dataloc = segloc[i];
|
||||
datasiz += l;
|
||||
break;
|
||||
}
|
||||
/* Check seg overflow */
|
||||
if ((segsiz[lseg] += l) >= seglim[lseg])
|
||||
return (NOMEM);
|
||||
/* load data from file */
|
||||
|
||||
/* Following loop is optimized for load speed. It knows*/
|
||||
/* about three conditions for data transfer: */
|
||||
/* 1. Data in read buffer: */
|
||||
/* Transfer data from read buffer to target */
|
||||
/* 2. Read buffer empty and more than 1 sector of data */
|
||||
/* remaining to load: */
|
||||
/* Read data direct to target */
|
||||
/* 3. Read buffer empty and less than 1 sector of data */
|
||||
/* remaining to load: */
|
||||
/* Fill read buffer, then proceed as in 1 above */
|
||||
|
||||
while (l) /* Until all loaded */
|
||||
{ /* Data in disk buffer? */
|
||||
if (gp < mydma + SECLEN)
|
||||
{
|
||||
length = min(l, mydma + SECLEN - gp);
|
||||
cpy_out(gp, phystarg, length);
|
||||
gp += length;
|
||||
}
|
||||
else if (l < SECLEN) /* Less than 1 sector */
|
||||
{ /* remains to transfer*/
|
||||
length = 0;
|
||||
mbdos(SETDMA, mydma);
|
||||
fillbuf();
|
||||
gp = mydma;
|
||||
}
|
||||
else /* Read full sector */
|
||||
{ /* into target space */
|
||||
length = SECLEN;
|
||||
bdos(SETDMA, phystarg);
|
||||
bdos(READ, mylpb.fcbaddr);
|
||||
}
|
||||
|
||||
phystarg += length;
|
||||
l -= length;
|
||||
}
|
||||
|
||||
return (GOOD);
|
||||
}
|
||||
|
||||
/* Routine to set the addresses in the Load Parameter Block */
|
||||
/* Unlike normal CP/M, the original load address is replaced on return */
|
||||
/* by the actual starting address of the program (true Code-space addr) */
|
||||
|
||||
int setaddr(lpbp)
|
||||
struct lpb *lpbp;
|
||||
{
|
||||
register int space;
|
||||
|
||||
space = (split) ? TPADATA : TPAPROG;
|
||||
lpbp->pgldaddr = (seg) ? textloc : map_adr(textloc, TRUE_TPAPROG);
|
||||
lpbp->bpaddr = stkloc;
|
||||
lpbp->stackptr = stkloc - (seg? sizeof (struct sstack)
|
||||
: sizeof (struct ustack));
|
||||
lpbp->flags = split | seg;
|
||||
return (space);
|
||||
}
|
||||
|
||||
/* Routine to set up the base page. The parameter indicates whether
|
||||
* the data and bss should be mapped in code space or in data space.
|
||||
*/
|
||||
|
||||
VOID setbase(space)
|
||||
int space;
|
||||
{
|
||||
struct b_page bp;
|
||||
|
||||
if (seg) {
|
||||
bp.lcode = textloc;
|
||||
bp.ltpa = 0L;
|
||||
} else {
|
||||
bp.lcode = bp.ltpa = map_adr(textloc, TRUE_TPAPROG);
|
||||
}
|
||||
|
||||
bp.htpa = mylpb.stackptr; /* htpa is where the stack is */
|
||||
bp.codelen = textsiz;
|
||||
|
||||
bp.ldata = dataloc;
|
||||
bp.datalen = datasiz;
|
||||
|
||||
if (bssloc == 0L) bssloc = dataloc + datasiz;
|
||||
bp.lbss = bssloc;
|
||||
bp.bsslen = bsssiz;
|
||||
|
||||
bp.freelen = seglim[bssseg] - segsiz[bssseg];
|
||||
|
||||
cpy_out(&bp, map_adr((long) stkloc, space), sizeof bp);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/********************************************************
|
||||
* *
|
||||
* P-CP/M header file *
|
||||
* Copyright (c) 1982 by Digital Research, Inc. *
|
||||
* Structure definitions for doing I/O in packets *
|
||||
* *
|
||||
* Modified for data in other address space *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
/* May use this information structure instead of disk parameter header and
|
||||
disk parameter block in future, but for now it's unused
|
||||
struct dskinfo
|
||||
{
|
||||
UBYTE *dbuffp;
|
||||
UBYTE *csv;
|
||||
UBYTE *alv;
|
||||
UBYTE blksize;
|
||||
UBYTE didummy;
|
||||
UWORD dskmax;
|
||||
UWORD dirmax;
|
||||
UWORD chksize;
|
||||
};
|
||||
*/
|
||||
|
||||
struct iopb
|
||||
{
|
||||
UBYTE iofcn; /* function number, see defines below */
|
||||
UBYTE ioflags; /* used for login flag and write flag */
|
||||
UBYTE devtype; /* device type, see defines below */
|
||||
/* currently unused */
|
||||
UBYTE devnum; /* device number, or, devtype and devnum
|
||||
taken together form int device number */
|
||||
LONG devadr; /* item nmbr on device to start xfer at */
|
||||
/* note -- item is sector for disks, byte for char devs */
|
||||
UWORD xferlen; /* number items to transfer */
|
||||
XADDR xferadr; /* memory address to xfer to/from */
|
||||
struct dph *infop; /* pointer to disk parameter header */
|
||||
/* return parm for fcn 0, input for rest */
|
||||
};
|
||||
|
||||
|
||||
/* Definitions for iofcn, the function number */
|
||||
#define sel_info 0 /* select and return info on device */
|
||||
#define read 1
|
||||
#define write 2
|
||||
#define flush 3
|
||||
#define status 4 /* not currently used */
|
||||
|
||||
|
||||
/* Definitions for devtype, the device type */
|
||||
/* This field not currently used */
|
||||
#define console 0
|
||||
#define printer 1
|
||||
#define disk 2
|
||||
#define memory 3 /* gets TPA boundaries */
|
||||
#define redir 4 /* read/write IOByte */
|
||||
#define exc_vec 5 /* set exception vector */
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* C P / M C H E A D E R F I L E
|
||||
* -----------------------------------
|
||||
* Copyright 1982 by Digital Research Inc. All rights reserved.
|
||||
*
|
||||
* This is an include file for assisting the user to write portable
|
||||
* programs for C.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define ALCYON 1 /* NOT using Alcyon compiler*/
|
||||
/* but Zilog has similar bug*/
|
||||
|
||||
/*
|
||||
* Standard type definitions
|
||||
*/
|
||||
/***************************/
|
||||
#define BYTE char /* Signed byte */
|
||||
#define BOOLEAN char /* 2 valued (true/false) */
|
||||
#define WORD short /* Signed word (16 bits) */
|
||||
#define UWORD unsigned int /* unsigned word */
|
||||
#define LONG long /* signed long (32 bits) */
|
||||
#define ULONG unsigned long /* Unsigned long */
|
||||
#define REG register /* register variable */
|
||||
#define LOCAL auto /* Local var on 68000 */
|
||||
#define EXTERN extern /* External variable */
|
||||
#define MLOCAL static /* Local to module */
|
||||
#define GLOBAL /**/ /* Global variable */
|
||||
#define VOID /**/ /* Void function return */
|
||||
#define XADDR long /* Extended (SEG) address */
|
||||
/***************************/
|
||||
#ifdef ALCYON
|
||||
#define UBYTE char
|
||||
#define UBWORD(a) ((UWORD)a & 0xff)
|
||||
/* Unsigned byte to word cast */
|
||||
#else
|
||||
#define UBYTE unsigned char /* Unsigned byte */
|
||||
#define UBWORD(a) (UWORD)a
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Miscellaneous Definitions: */
|
||||
/****************************************************************************/
|
||||
|
||||
#define FAILURE (-1) /* Function failure return val */
|
||||
#define SUCCESS (0) /* Function success return val */
|
||||
#define YES 1 /* "TRUE" */
|
||||
#define NO 0 /* "FALSE" */
|
||||
#define FOREVER for(;;) /* Infinite loop declaration */
|
||||
#define NULL (BYTE *)0 /* Null pointer value */
|
||||
#define XNULL 0L /* Null XADDR */
|
||||
#define EOF (-1) /* EOF Value */
|
||||
#define TRUE (1)
|
||||
/* Function TRUE value */
|
||||
#define FALSE (0)
|
||||
/* Function FALSE value */
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* M A C R O S */
|
||||
/* ----------- */
|
||||
/* */
|
||||
/* Define some stuff as macros .... */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#define abs(x) ((x) < 0 ? -(xIq
|
||||
This directory contains the source and object files for the Z8000 CP/M Bios,
|
||||
and the necessary include files. This includes the floating point emulator
|
||||
@@ -0,0 +1,958 @@
|
||||
/*=======================================================================*/
|
||||
/*+---------------------------------------------------------------------+*/
|
||||
/*| |*/
|
||||
/*| P-CP/M(tm) BIOS for the OLIVETTI M20 (Z8000) |*/
|
||||
/*| |*/
|
||||
/*| Copyright 1982, Zilog Incorporated. |*/
|
||||
/*| |*/
|
||||
/*+---------------------------------------------------------------------+*/
|
||||
/*=======================================================================*/
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
|
||||
char copyright[] = "Copyright 1982, Zilog Incorporated";
|
||||
|
||||
|
||||
/* HISTORY
|
||||
**
|
||||
** 820803 S. Savitzky (Zilog) -- derived from 68000 EXORMACS bios
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* I/O Device Definitions */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define Interrupt Controller constants */
|
||||
/************************************************************************/
|
||||
|
||||
/* The interrupt controller is an Intel 8259 left-shifted one bit */
|
||||
/* to allow for the word-alligned interrupt vectors of the Z8000. */
|
||||
|
||||
/* === I am going to assume that this is set up in the PROM === */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define the two USART ports */
|
||||
/************************************************************************/
|
||||
|
||||
/* The USARTs are Intel 8251's */
|
||||
|
||||
#define KBD 0xA1 /* Keyboard USART base */
|
||||
#define RS232 0xC1 /* RS-232 terminal */
|
||||
|
||||
#define SERDATA 0 /* data port offset */
|
||||
#define SERCTRL 2 /* control port offset */
|
||||
#define SERSTAT 2 /* status port offset */
|
||||
|
||||
#define SERINIT 0x37 /* init (3 times) */
|
||||
#define SERRES 0x40 /* reset */
|
||||
#define SERMODE 0xEE /* mode (2 stop, even parity */
|
||||
/* parity disable, 8 bits */
|
||||
/* divide by 16 */
|
||||
/* DUBIOUS. 15?? */
|
||||
#define SERCMD 0x37 /* cmd (no hunt, no reset, */
|
||||
/* RTS=0, error reset, */
|
||||
/* no break, rcv enable, */
|
||||
/* DTR=0, xmt enable */
|
||||
|
||||
#define SERRRDY 0x02 /* RCV ready bit mask */
|
||||
#define SERXRDY 0x01 /* XMT ready bit mask */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define the counter/timer ports */
|
||||
/************************************************************************/
|
||||
|
||||
/* The counter-timer is an Intel 8253 */
|
||||
|
||||
#define CT_232 0x121 /* counter/timer 0 -- RS232 baud rate */
|
||||
#define CT_KBD 0x123 /* counter/timer 1 -- kbd baud rate */
|
||||
#define CT_RTC 0x125 /* counter/timer 2 -- NVI (rt clock) */
|
||||
#define CT_CTRL 0x127 /* counter/timer control port */
|
||||
|
||||
#define CT0CTL 0x36 /* c/t 0 control byte */
|
||||
#define CT1CTL 0x76 /* c/t 1 control byte */
|
||||
#define CT2CTL 0xB4 /* c/t 2 control byte */
|
||||
|
||||
/* control byte is followed by LSB, then MSB of count to data register */
|
||||
/* baud rate table follows: */
|
||||
|
||||
int baudRates[10] = {
|
||||
1538, /* 50 */
|
||||
699, /* 110 */
|
||||
256, /* 300 */
|
||||
128, /* 600 */
|
||||
64, /* 1200 */
|
||||
32, /* 2400 */
|
||||
16, /* 4800 */
|
||||
8, /* 9600 */
|
||||
4, /* 19200 */
|
||||
2 /* 38400 */
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define Parallel Port constants */
|
||||
/************************************************************************/
|
||||
|
||||
/* The parallel (printer) port is an Intel 8255 */
|
||||
|
||||
#define PAR_A 0x81 /* port A data */
|
||||
#define PAR_B 0x83 /* port B data */
|
||||
#define PAR_C 0x85 /* port C data */
|
||||
#define PARCTRL 0x87 /* control port */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* PROM AND HARDWARE INTERFACE */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/************************************************************************/
|
||||
/* Define PROM I/O Addresses and Related Constants */
|
||||
/************************************************************************/
|
||||
|
||||
extern int disk_io(); /* (char drive, cmd -- disk I/O */
|
||||
/* int blk_count, */
|
||||
/* int blk_num, */
|
||||
/* char *dest) -> int error? */
|
||||
|
||||
extern crt_put(); /* (char character) -- put byte to CRT */
|
||||
|
||||
extern cold_boot(); /* boot operating system */
|
||||
|
||||
#define DSKREAD 0 /* disk read command */
|
||||
#define DSKWRITE 1 /* disk write command */
|
||||
#define DSKFMT 2 /* disk format command */
|
||||
#define DSKVFY 3 /* disk verify command */
|
||||
#define DSKINIT 4 /* disk init. command */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define external I/O routines and addresses */
|
||||
/************************************************************************/
|
||||
|
||||
extern output(); /* (port, data: int) -- output */
|
||||
extern int input(); /* (port: int) -- input */
|
||||
|
||||
/************************************************************************/
|
||||
/* Define external memory management routines */
|
||||
/************************************************************************/
|
||||
|
||||
extern mem_cpy(); /* (src, dest, len: long)-- copy data */
|
||||
extern long map_adr(); /* paddr = (laddr: long; space: int) */
|
||||
|
||||
#define CDATA 0 /* caller data space */
|
||||
#define CCODE 1 /* caller code space */
|
||||
#define SDATA 2 /* system data space */
|
||||
#define SCODE 3 /* system code space */
|
||||
#define NDATA 4 /* normal data space */
|
||||
#define NCODE 5 /* normal code space */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Memory Region Table */
|
||||
/************************************************************************/
|
||||
|
||||
struct mrt { int count;
|
||||
struct {long tpalow;
|
||||
long tpalen;
|
||||
} regions[4];
|
||||
}
|
||||
memtab = {4,
|
||||
0x0A000000L, 0x10000L, /* merged I and D */
|
||||
0x08000000L, 0x10000L, /* separated I */
|
||||
0x08000000L, 0x10000L, /* and D */
|
||||
0x0B000000L, 0x10000L /* accessing I as D */
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* Set Exception Vector entry */
|
||||
/************************************************************************/
|
||||
|
||||
extern long trapvec[]; /* trap vector */
|
||||
|
||||
long setxvect(vnum, vval)
|
||||
int vnum;
|
||||
long vval;
|
||||
{
|
||||
register long oldval;
|
||||
|
||||
oldval = trapvec[vnum];
|
||||
trapvec[vnum] = vval;
|
||||
|
||||
return(oldval);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* CHARACTER I/O */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/************************************************************************/
|
||||
/* Generic Serial Port I/O Procedures */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
/* define as extern the dirty flag, which is actually defined later */
|
||||
/* on in this file. Used to flush the buffer at an opportune moment. */
|
||||
|
||||
extern int tbdirty;
|
||||
|
||||
serinit(port)
|
||||
int port;
|
||||
{
|
||||
output(port+SERCTRL, SERINIT);
|
||||
output(port+SERCTRL, SERINIT);
|
||||
output(port+SERCTRL, SERINIT);
|
||||
|
||||
output(port+SERCTRL, SERRES);
|
||||
output(port+SERCTRL, SERMODE);
|
||||
output(port+SERCTRL, SERCMD);
|
||||
|
||||
/* === worry about baud rate. assume the PROM sets it up. === */
|
||||
}
|
||||
|
||||
int serirdy(port)
|
||||
int port;
|
||||
{
|
||||
return(((input(port+SERSTAT) & SERRRDY) == SERRRDY) ? 0xFF : 0);
|
||||
}
|
||||
|
||||
|
||||
char serin(port)
|
||||
int port;
|
||||
{
|
||||
while (serirdy(port) == 0) ;
|
||||
return input(port+SERDATA);
|
||||
}
|
||||
|
||||
|
||||
int serordy(port)
|
||||
int port;
|
||||
{
|
||||
return(((input(port+SERSTAT) & SERXRDY) == SERXRDY) ? 0xFF : 0);
|
||||
}
|
||||
|
||||
|
||||
serout(port, ch)
|
||||
int port;
|
||||
char ch;
|
||||
{
|
||||
while ( (input(port + SERSTAT) & SERXRDY) != SERXRDY) ;
|
||||
output(port+SERDATA, ch);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Olivetti keyboard translation table. */
|
||||
/************************************************************************/
|
||||
|
||||
char kbtran[256] = {
|
||||
|
||||
/* Raw key codes for main keypad:
|
||||
|
||||
RE \ A B C D E F G H I J K L M N
|
||||
O P Q R S T U V W X Y Z 0 1 2 3
|
||||
4 5 6 7 8 9 - ^ @ [ ; : ] , . /
|
||||
*/
|
||||
|
||||
/* main keyboard UNSHIFTED. */
|
||||
|
||||
0xDD,'\\', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '-', '^', '@', '[', ';', ':', ']', ',', '.', '/',
|
||||
|
||||
/* main keyboard SHIFTED */
|
||||
|
||||
0xDE, '|', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '!', '"', '#',
|
||||
'$', '%', '&','\'', '(', ')', '=', '~', '`', '{', '+', '*', '}', '<', '>', '?',
|
||||
|
||||
/* main keyboard CONTROL -- CTL B and C differ from Olivetti. */
|
||||
|
||||
0xA0,0x7F,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
|
||||
0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0xE0,0xE1,0xE2,0xE3,
|
||||
0xE4,0xE5,0xD6,0xE7,0xE8,0xE9,0xEA,0xEB,0x00,0xFB,0x1E,0x1F,0x1D,0xFE,0xFF,0xA4,
|
||||
|
||||
/* main keyboard COMMAND */
|
||||
|
||||
0xDF,0xF8,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,
|
||||
0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xEC,0xED,0xEE,0xEF,
|
||||
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0x13,0x1C,0xFC,0xFD,0x9F,0xF9,0xFA,0xA5,
|
||||
|
||||
/* other keys
|
||||
|
||||
SP CR S1 S2
|
||||
KEYPAD . 0 00 1
|
||||
2 3 4 5
|
||||
6 7 8 9
|
||||
+ - * /
|
||||
*/
|
||||
|
||||
/* other keys UNSHIFTED -- CR differs from Olivetti */
|
||||
|
||||
' ','\r',0x7f,0x08,
|
||||
'.', '0',0xA6, '1',
|
||||
'2', '3', '4', '5',
|
||||
'6', '7', '8', '9',
|
||||
'+', '-', '*', '/',
|
||||
|
||||
/* other keys SHIFTED -- CR differs from Olivetti */
|
||||
|
||||
' ','\r',0xA8,0xA9,
|
||||
'.', '0',0xA6,0x1C,
|
||||
0x9A,0x1D,0x9B,0x9C,
|
||||
0x9D,0x1E,0x9E,0x1F,
|
||||
0x2B,0x2D,0x2A,0x2F,
|
||||
|
||||
/* other keys CONTROL */
|
||||
|
||||
' ','\r',0xA8,0xA9,
|
||||
0xB0,0xB1,0xB2,0xB3,
|
||||
0xB4,0xB5,0xB6,0x1B,
|
||||
0xB8,0xB9,0xBA,0xBB,
|
||||
0xBC,0xBD,0xBE,0xBF,
|
||||
|
||||
|
||||
/* special -- substitute \r for Olivetti's 0xAF. */
|
||||
|
||||
'\r','\r','\r','\r'
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* specific I/O procedures for use with iobyte */
|
||||
/************************************************************************/
|
||||
|
||||
/* CRT status, read, write routines */
|
||||
|
||||
int crtrs()
|
||||
{
|
||||
return( serirdy(KBD));
|
||||
}
|
||||
|
||||
char crtrd()
|
||||
{
|
||||
return( kbtran[serin(KBD) & 0xff]);
|
||||
}
|
||||
|
||||
int crtws()
|
||||
{
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
#define crtwr crt_put /* output routine in PROM */
|
||||
|
||||
|
||||
/* TTY status, read, write routines */
|
||||
|
||||
int ttyrs()
|
||||
{
|
||||
return(serirdy(RS232));
|
||||
}
|
||||
|
||||
char ttyrd()
|
||||
{
|
||||
return(serin(RS232));
|
||||
}
|
||||
|
||||
int ttyws()
|
||||
{
|
||||
return(serordy(RS232));
|
||||
}
|
||||
|
||||
ttywr(ch)
|
||||
char ch;
|
||||
{
|
||||
serout(RS232, ch);
|
||||
}
|
||||
|
||||
/* LPT status, output routines */
|
||||
|
||||
int lptws()
|
||||
{
|
||||
}
|
||||
|
||||
lptwr(ch) /* ARGSUSED */
|
||||
char ch;
|
||||
{
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* generic device names, batch, and null devices */
|
||||
/************************************************************************/
|
||||
|
||||
/* the device names are the offset of the proper field in iobyte */
|
||||
|
||||
#define CON 0
|
||||
#define READER 2
|
||||
#define PUNCH 4
|
||||
#define LIST 6
|
||||
|
||||
|
||||
/* BATCH status, read, write routines */
|
||||
|
||||
int batrs()
|
||||
{
|
||||
int genstat();
|
||||
|
||||
return genstat(READER);
|
||||
}
|
||||
|
||||
char batrd()
|
||||
{
|
||||
int genread();
|
||||
|
||||
return genread(READER);
|
||||
}
|
||||
|
||||
batwr(ch)
|
||||
char ch;
|
||||
{
|
||||
genwrite(LIST, ch);
|
||||
}
|
||||
|
||||
|
||||
/* NULL status, read, write routines */
|
||||
|
||||
int nulst()
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
char nulrd()
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
nulwr(ch) /* ARGSUSED */
|
||||
char ch;
|
||||
{
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Generic I/O routines using iobyte */
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
** IObyte itself.
|
||||
*/
|
||||
|
||||
char iobyte;
|
||||
|
||||
/*
|
||||
** A dummy aligner for the linker bug.
|
||||
*/
|
||||
|
||||
char alignxx;
|
||||
|
||||
|
||||
/*
|
||||
** Device operation tables. DEVINDEX is the index into the
|
||||
** table appropriate to a device (row) and its iobyte index (column)
|
||||
**
|
||||
** nonexistent devices are mapped into NUL.
|
||||
*/
|
||||
|
||||
#define DEVINDEX (((iobyte>>dev) & 3) + (dev * 2) )
|
||||
|
||||
|
||||
int (*sttbl[16])() = {
|
||||
ttyrs, crtrs, batrs, nulst, /* con */
|
||||
ttyrs, nulst, nulst, nulst, /* reader */
|
||||
ttyws, nulst, nulst, nulst, /* punch */
|
||||
ttyws, crtws, lptws, nulst /* list */
|
||||
};
|
||||
|
||||
char (*rdtbl[16])() = {
|
||||
ttyrd, crtrd, batrd, nulrd,
|
||||
ttyrd, nulrd, nulrd, nulrd,
|
||||
nulrd, nulrd, nulrd, nulrd,
|
||||
nulrd, nulrd, nulrd, nulrd
|
||||
};
|
||||
|
||||
int (*wrtbl[16])() = {
|
||||
ttywr, crtwr, batwr, nulwr,
|
||||
nulwr, nulwr, nulwr, nulwr,
|
||||
ttywr, nulwr, nulwr, nulwr,
|
||||
ttywr, crtwr, lptwr, nulwr
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** the generic service routines themselves
|
||||
*/
|
||||
|
||||
int genstat(dev)
|
||||
int dev;
|
||||
{
|
||||
return( (*sttbl[DEVINDEX])() );
|
||||
}
|
||||
|
||||
int genread(dev)
|
||||
int dev;
|
||||
{
|
||||
return( (*rdtbl[DEVINDEX])() );
|
||||
}
|
||||
|
||||
genwrite(dev, ch)
|
||||
int dev;
|
||||
char ch;
|
||||
{
|
||||
(*wrtbl[DEVINDEX])(ch);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Error procedure for BIOS */
|
||||
/************************************************************************/
|
||||
|
||||
bioserr(errmsg)
|
||||
register char *errmsg;
|
||||
{
|
||||
printstr("\n\rBIOS ERROR -- ");
|
||||
printstr(errmsg);
|
||||
printstr(".\n\r");
|
||||
while(1);
|
||||
}
|
||||
|
||||
printstr(s) /* used by bioserr */
|
||||
register char *s;
|
||||
{
|
||||
while (*s) {crtwr(*s); s += 1; };
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* DISK I/O */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* BIOS Table Definitions */
|
||||
/************************************************************************/
|
||||
|
||||
struct dpb
|
||||
{
|
||||
int spt; /* sectors per track */
|
||||
char bsh; /* block shift = log2(blocksize/128) */
|
||||
char blm; /* block mask = 2**bsh - 1 */
|
||||
char exm; /* extent mask */
|
||||
char dpbjunk; /* dummy field to allign words */
|
||||
int dsm; /* size of disk less offset, in blocks */
|
||||
int drm; /* size of directory - 1 */
|
||||
char al0; /* reservation bits for directory */
|
||||
char al1; /* ... */
|
||||
int cks; /* size of checksum vector = (drm+1)/4 */
|
||||
int off; /* track offset for OS boot */
|
||||
char psh; /* log2(sectorsize/128) */
|
||||
char psm; /* physical size mask = 2**psh - 1 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct dph
|
||||
{
|
||||
char *xltp; /* -> sector translation table */
|
||||
int dphscr[3]; /* scratchpad for BDOS */
|
||||
char *dirbufp; /* -> directory buffer (128 bytes) */
|
||||
struct dpb *dpbp; /* -> disk parameter block */
|
||||
char *csvp; /* -> software check vector (cks bytes) */
|
||||
char *alvp; /* -> alloc vector ((dsm/8)+1 bytes) */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Disk Parameter Blocks */
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
** CP/M assumes that disks are made of 128-byte logical sectors.
|
||||
**
|
||||
** The Olivetti uses 256-byte sectors on its disks. This BIOS buffers
|
||||
** a track at a time, so sector address translation is not needed.
|
||||
**
|
||||
** Sample tables are included for several different disk sizes.
|
||||
*/
|
||||
|
||||
/* === Olivetti has 3 floppy formats & a hard disk === */
|
||||
|
||||
#define SECSZ 128 /* CP/M logical sector size */
|
||||
#define TRKSZ 32 /* track size for floppies, 1/2 track sz for hd */
|
||||
#define PSECSZ 256 /* Olivetti physical sector size */
|
||||
#define PTRKSZ 16 /* physical track size */
|
||||
#define MAXDSK 3 /* max. number of disks */
|
||||
|
||||
|
||||
/***** spt, bsh, blm, exm, jnk, dsm, drm, al0, al1, cks, off, psh, psm */
|
||||
|
||||
struct dpb dpb0= /* --- 1 side, 16*256 sector, 35 track. 140kb --- */
|
||||
{ 32, 4, 15, 1, 0, 50, 63, 0xC0, 0, 16, 10};
|
||||
struct dpb dpb1= /* --- 2 side, 16*256 sector, 35 track. 280kb --- */
|
||||
{ 32, 4, 15, 1, 0, 120, 63, 0xC0, 0, 16, 10};
|
||||
struct dpb dpb2= /* --- 2 side, 16*256 sector, 80 track. 640kb --- */
|
||||
{ 32, 4, 15, 0, 0, 300, 63, 0xC0, 0, 16, 10};
|
||||
struct dpb dpb3= /* --- 6 side, 32*256 sector, 180 trk. 8640kb --- */
|
||||
{ 64, 4, 15, 0, 0, 4296, 63, 0xC0, 0, 16, 10};
|
||||
|
||||
/* bls = 2K dsm = (disk size - 8 reserved tracks) / bls */
|
||||
|
||||
#ifdef SECT26
|
||||
|
||||
/* === The Olivetti does not have 26-sector disks, but many people do.
|
||||
** The following parameter blocks are provided for their use.
|
||||
*/
|
||||
|
||||
struct dpb dpbS= /* --- 1 side, 26*128 sector, 72 trk --- */
|
||||
{ 26, 3, 7, 0, 0, 242, 63, 0xC0, 0, 16, 2};
|
||||
struct dpb dpbD= /* --- 1 side, 26*256 sector, 72 trk --- */
|
||||
{ 52, 4, 15, 0, 0, 242, 63, 0xC0, 0, 16, 2};
|
||||
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* BDOS Scratchpad Areas */
|
||||
/************************************************************************/
|
||||
|
||||
char dirbuf[SECSZ];
|
||||
|
||||
|
||||
char csv0[16];
|
||||
char csv1[16];
|
||||
char csv2[16];
|
||||
|
||||
|
||||
|
||||
char alv0[32]; /* (dsm0 / 8) + 1 */
|
||||
char alv1[32]; /* (dsm1 / 8) + 1 */
|
||||
char alv2[2002]; /* (dsm2 / 8) + 1 */
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Sector Translate Table */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifdef SECT26
|
||||
|
||||
/* === The Olivetti does not have 26-sector disks, but many people do.
|
||||
** The following translate table is provided for their use.
|
||||
*/
|
||||
|
||||
char xlt26[26] = { 1, 7, 13, 19, 25, 5, 11, 17, 23, 3, 9, 15, 21,
|
||||
2, 8, 14, 20, 26, 6, 12, 18, 24, 4, 10, 16, 22 };
|
||||
|
||||
#endif
|
||||
|
||||
char xlt16[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
|
||||
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Disk Parameter Headers */
|
||||
/* */
|
||||
/* Three disks are defined: dsk a: diskno=0, drive 0 */
|
||||
/* dsk b: diskno=1, drive 1 */
|
||||
/* dsk c: diskno=2, drive 10 */
|
||||
/************************************************************************/
|
||||
|
||||
struct dph dphtab[3] =
|
||||
{ {xlt16, {0, 0, 0}, dirbuf, &dpb1, csv0, alv0}, /*dsk a*/
|
||||
{xlt16, {0, 0, 0}, dirbuf, &dpb1, csv1, alv1}, /*dsk b*/
|
||||
{(char *) 0L, {0, 0, 0}, dirbuf, &dpb2, csv2, alv2}, /*dsk c*/
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Currently Selected Disk Stuff */
|
||||
/************************************************************************/
|
||||
|
||||
int settrk, setsec, setdsk; /* track, sector, disk # */
|
||||
long setdma; /* dma address with segment info: long */
|
||||
|
||||
|
||||
char trkbuf[TRKSZ * SECSZ]; /* track buffer */
|
||||
int tbvalid = 0; /* track buffer valid */
|
||||
int tbdirty = 0; /* track buffer dirty */
|
||||
int tbtrk; /* track buffer track # */
|
||||
int tbdsk; /* track buffer disk # */
|
||||
int dskerr; /* disk error */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Disk I/O Procedures */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
|
||||
dskxfer(dsk, trk, bufp, cmd) /* transfer a disk track */
|
||||
register int dsk, trk, cmd;
|
||||
register char *bufp;
|
||||
{
|
||||
if (dsk==3) dsk = 10; /* convert hard disk drive # */
|
||||
dskerr=0; /* assume no error */
|
||||
/* do transfer */
|
||||
if (0 != disk_io(dsk, cmd, PTRKSZ, trk*PTRKSZ, map_adr((long)bufp,0)))
|
||||
dskerr=1;
|
||||
}
|
||||
|
||||
|
||||
#define wrongtk ((! tbvalid) || (tbtrk != settrk) || (tbdsk != setdsk))
|
||||
#define gettrk if (wrongtk) filltb()
|
||||
|
||||
|
||||
flush()
|
||||
{
|
||||
|
||||
if ( tbdirty && tbvalid ) dskxfer(tbdsk, tbtrk, trkbuf, DSKWRITE);
|
||||
|
||||
tbdirty = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
filltb()
|
||||
{
|
||||
|
||||
if ( tbvalid && tbdirty ) flush();
|
||||
|
||||
dskxfer(setdsk, settrk, trkbuf, DSKREAD);
|
||||
|
||||
tbvalid = 1;
|
||||
tbdirty = 0;
|
||||
tbtrk = settrk;
|
||||
tbdsk = setdsk;
|
||||
|
||||
}
|
||||
|
||||
|
||||
dskread()
|
||||
{
|
||||
register char *p;
|
||||
|
||||
gettrk;
|
||||
p = &trkbuf[SECSZ * (setsec-1)];
|
||||
|
||||
/* transfer between memory spaces. setdma is physical address */
|
||||
|
||||
mem_cpy(map_adr((long)p, CDATA), setdma, (long)SECSZ);
|
||||
|
||||
return(dskerr);
|
||||
}
|
||||
|
||||
|
||||
dskwrite(mode)
|
||||
char mode;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
gettrk;
|
||||
p = &trkbuf[SECSZ * (setsec-1)];
|
||||
|
||||
/* transfer between memory spaces. setdma is physical address */
|
||||
|
||||
mem_cpy(setdma, map_adr((long) p, CDATA), (long)SECSZ);
|
||||
tbdirty = 1;
|
||||
if ( mode == 1 ) flush();
|
||||
return(dskerr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char sectran(s, xp)
|
||||
int s;
|
||||
char *xp;
|
||||
{
|
||||
if (xp != 0) return xp[s]; else return s;
|
||||
}
|
||||
|
||||
|
||||
struct dph *seldisk(dsk, logged)
|
||||
register char dsk;
|
||||
char logged;
|
||||
{
|
||||
register struct dph *dphp;
|
||||
|
||||
if (dsk > MAXDSK) return(0L);
|
||||
setdsk = dsk;
|
||||
dphp = &dphtab[dsk];
|
||||
if ( ! logged )
|
||||
{
|
||||
|
||||
/* === disk not logged in. select density, etc. === */
|
||||
|
||||
}
|
||||
return(dphp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* BIOS PROPER */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
biosinit()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printstr("\r\nP-CP/M: Olivetti M20 BIOS.");
|
||||
#endif
|
||||
/* serinit(KBD);*/ /* DON'T init keyboard serial port */
|
||||
serinit(RS232); /* init rs232 serial port */
|
||||
|
||||
tbvalid = 0; /* init disk flags */
|
||||
tbdirty = 0;
|
||||
|
||||
iobyte = 0x41; /* con, list = CRT; rdr, punch = TTY */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
long _bios(d0, d1, d2)
|
||||
int d0;
|
||||
long d1, d2;
|
||||
{
|
||||
|
||||
switch(d0)
|
||||
{
|
||||
case 0: /* INIT */
|
||||
biosinit();
|
||||
break;
|
||||
|
||||
case 1: /* WBOOT */
|
||||
wboot();
|
||||
break;
|
||||
|
||||
case 2: /* CONST */
|
||||
return(genstat(CON));
|
||||
break;
|
||||
|
||||
case 3: /* CONIN */
|
||||
return(genread(CON));
|
||||
break;
|
||||
|
||||
case 4: /* CONOUT */
|
||||
genwrite(CON, (char)d1);
|
||||
break;
|
||||
|
||||
case 5: /* LIST */
|
||||
genwrite(LIST, (char)d1);
|
||||
break;
|
||||
|
||||
case 6: /* PUNCH */
|
||||
genwrite(PUNCH, (char)d1);
|
||||
break;
|
||||
|
||||
case 7: /* READER */
|
||||
return(genread(READER));
|
||||
break;
|
||||
|
||||
case 8: /* HOME */
|
||||
settrk = 0;
|
||||
break;
|
||||
|
||||
case 9: /* SELDSK */
|
||||
return((long)seldisk((char)d1, (char)d2));
|
||||
break;
|
||||
|
||||
case 10: /* SETTRK */
|
||||
settrk = (int)d1;
|
||||
break;
|
||||
|
||||
case 11: /* SETSEC */
|
||||
setsec = (int)d1;
|
||||
break;
|
||||
|
||||
case 12: /* SETDMA */
|
||||
setdma = d1;
|
||||
break;
|
||||
|
||||
case 13: /* READ */
|
||||
return(dskread());
|
||||
break;
|
||||
|
||||
case 14: /* WRITE */
|
||||
return(dskwrite((char)d1));
|
||||
break;
|
||||
|
||||
case 15: /* LISTST */
|
||||
return(genstat(LIST));
|
||||
break;
|
||||
|
||||
case 16: /* SECTRAN */
|
||||
return(sectran((int)d1, (char*)d2));
|
||||
break;
|
||||
|
||||
case 18: /* GMRTA */
|
||||
return((long)&memtab);
|
||||
break;
|
||||
|
||||
case 19: /* GETIOB */
|
||||
return((long)iobyte);
|
||||
break;
|
||||
|
||||
case 20: /* SETIOB */
|
||||
iobyte = (char)d1;
|
||||
break;
|
||||
|
||||
case 21: /* FLUSH */
|
||||
flush();
|
||||
return((long)dskerr);
|
||||
break;
|
||||
|
||||
case 22: /* SETXVECT */
|
||||
return(setxvect((int)d1, d2));
|
||||
break;
|
||||
|
||||
|
||||
|
||||
} /* end switch */
|
||||
|
||||
return(0);
|
||||
|
||||
|
||||
} /* end bios procedure */
|
||||
|
||||
|
||||
|
||||
/* End of C Bios */
|
||||
@@ -0,0 +1,390 @@
|
||||
;********** wboot.s -- Olivetti bootstrap writer*****
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- adapt for nonseg.
|
||||
;* 820930 S. Savitzky (Zilog) -- created
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE -- THIS CODE IS HIGHLY SYSTEM-DEPENDENT
|
||||
;*
|
||||
;* This module contains both the bootstrap
|
||||
;* writer, and the code that receives control
|
||||
;* after being booted.
|
||||
;*
|
||||
;* The main function of the latter is to make
|
||||
;* sure that the system, whose entry point is
|
||||
;* called "bios", is passed a valid stack
|
||||
;* and PSA pointer.
|
||||
;*
|
||||
;* Although this code runs segmented, it must
|
||||
;* be linked with non-segmented code, so it
|
||||
;* looks rather odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bootstrap Writer for P-CP/M on the Olivetti M20.
|
||||
;*
|
||||
;* This program puts out a bootstrap file in the
|
||||
;* Olivetti's peculiar format, which has a lot of
|
||||
;* Olivetti's file system in it.
|
||||
;*
|
||||
;* Track 0 is unused except for sector 0, since
|
||||
;* it is single density and thus has smaller
|
||||
;* sectors.
|
||||
;*
|
||||
;* A total of 10 tracks are reserved from CP/M,
|
||||
;* leaving 9 tracks for the system proper.
|
||||
;*
|
||||
;* The first sector on track 1 is the PCOS file
|
||||
;* descriptor block; the second is the boot file
|
||||
;* header and the start of the system code.
|
||||
;*
|
||||
;* This leaves something under 28K for the
|
||||
;* system (BIOS+BDOS+CCP). It is assumed that
|
||||
;* the system starts at its lowest address,
|
||||
;* and that data follows immediately after code.
|
||||
;*
|
||||
;* For now, we assume that the system starts at
|
||||
;* <<11>>0000 (hex)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios
|
||||
.global _wboot
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
SYSTEM .equ 0B000000h ; system address
|
||||
SYSSTK .equ SYSTEM+0BFFEh ; system stack top
|
||||
rtc_ext .equ 02000022h ; real-time clock
|
||||
; ext. call addr
|
||||
|
||||
BPT .equ 16 ; #blocks in a track
|
||||
BPS .equ 256 ; #bytes in a sector
|
||||
NBLKS .equ 9*16 ; #blocks in boot
|
||||
HDRSIZE .equ 24 ; #bytes in header
|
||||
FILSIZE .equ 256*(NBLKS-1) ; file data size
|
||||
SYSSIZE .equ FILSIZE-HDRSIZE ; total system size
|
||||
S1SIZE .equ BPS-HDRSIZE ; data in sector 1
|
||||
|
||||
SEG4 .equ 04000000h
|
||||
SEG2 .equ 02000000h
|
||||
|
||||
SYSPSA .equ SEG2+100h ; system PSA
|
||||
BOOTPSA .equ SEG4+100h ; PSA in PROM for boot
|
||||
|
||||
sscall .macro ;short segmented call
|
||||
.word 05f00h
|
||||
.word ?1
|
||||
.endm
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Entry Points and post-boot Initialization
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;* transfer vector
|
||||
|
||||
jr wboot
|
||||
jr wrboot
|
||||
jr entry
|
||||
|
||||
;* post-boot init.
|
||||
|
||||
entry: ;SEGMENTED
|
||||
|
||||
DI VI,NVI
|
||||
|
||||
ldl rr14, #SYSSTK ; init stack pointer
|
||||
|
||||
ldl rr2, #SYSPSA ; copy PROM's PSA
|
||||
ldctl r4, psapseg
|
||||
ldctl r5, psapoff
|
||||
ld r0, #570/2
|
||||
ldir @r2, @r4, r0
|
||||
|
||||
ldl rr2, #SYSPSA ; shift PSA pointer
|
||||
ldctl psapseg, r2
|
||||
ldctl psapoff, r3
|
||||
|
||||
ld r2,#142h ;CROCK-- turn off
|
||||
ld r3,#1feh ; usart interrupts
|
||||
out @r2,r3
|
||||
|
||||
ldar r2, $ ; go
|
||||
ld r3,#bios
|
||||
jp @r2
|
||||
|
||||
|
||||
wboot: ldar r2, $
|
||||
ld r3,#_wboot
|
||||
jp @r2
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bootstrap Writer
|
||||
;* Although written as if non-segmented,
|
||||
;* this code actually has to run segmented.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
wrboot:
|
||||
|
||||
;* Init
|
||||
|
||||
ldl rr2,#BOOTPSA ; psa
|
||||
ldctl psapseg, r2
|
||||
ldctl psapoff, r3
|
||||
|
||||
ldl rr14,#SYSSTK ; stack ptr
|
||||
ldl rr2,#rtc_ext ; disable real-time
|
||||
ld @r2,#0ffffh ; clock ext call
|
||||
|
||||
EI VI,NVI ; interrupts
|
||||
|
||||
ld r2,#0202h ; type 2 drives & disks
|
||||
ldl rr4,#SEG2+0030h ; (kludge for Olivetti)
|
||||
ld @r4,r2
|
||||
inc r5,#2
|
||||
ld @r4,r2
|
||||
|
||||
sscall 047Ah ; screen init
|
||||
sscall 046Eh ; clock init
|
||||
sscall 0462h ; disk init
|
||||
|
||||
ldar r12, msg2 ; "writing ..."
|
||||
sscall 0486h ; put message
|
||||
|
||||
;* Write track 0 sector 0
|
||||
|
||||
ld r8,#1
|
||||
ld r9,#0
|
||||
ldar r10,T0S0
|
||||
calr Write
|
||||
|
||||
;* copy data into first sector
|
||||
|
||||
ldl rr2,#SYSTEM
|
||||
ldar r4,s1data
|
||||
ld r0, #S1SIZE/2
|
||||
ldir @r4,@r2,r0
|
||||
|
||||
;* write FDB and first data sector
|
||||
|
||||
ld r8,#2
|
||||
ld r9,#BPT
|
||||
ldar r10,T1S0
|
||||
calr Write
|
||||
|
||||
;* write rest of system.
|
||||
|
||||
ld r8,#NBLKS-2
|
||||
ld r9,#BPT+2
|
||||
ldl rr10,#SYSTEM+S1SIZE
|
||||
calr Write
|
||||
|
||||
;* hang up.
|
||||
|
||||
ldar r12, msg1 ; "done ..."
|
||||
sscall 0486h ; put message
|
||||
|
||||
hang:
|
||||
jr hang
|
||||
|
||||
|
||||
;*------------- W R I T E D I S K ------------------
|
||||
|
||||
Write: ; write sectors to disk.
|
||||
; r8 = block count
|
||||
; r9 = block number
|
||||
; rr10= data address
|
||||
|
||||
; add parameters for PROM routine
|
||||
|
||||
ldb rh7,#0 ; rh7 = drive #
|
||||
ldb rl7,#1 ; rl7 = command
|
||||
|
||||
sscall 0468h ; do it
|
||||
ret
|
||||
|
||||
|
||||
;*--------------- messages -----------------------
|
||||
;* Note: must be in same program section as code
|
||||
|
||||
msg1: .byte " Done "
|
||||
msg2: .byte "Writing Bootstrap..."
|
||||
.byte 0 0
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Track 0 Sector 0
|
||||
;*
|
||||
;* This sector contains the pointer to the
|
||||
;* bootstrap file's FDB.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
T0S0:
|
||||
|
||||
.byte 0 ; major version
|
||||
.byte 0 ; minor version
|
||||
.word 40 ; #tracks/surface ?? 35 ??
|
||||
.byte 2 ; #surfaces
|
||||
.byte 16 ; #sectors/track
|
||||
.word 256 ; #bytes/sector
|
||||
.word 40 ; ??? track # of control blk
|
||||
.word 38h ; ??? vdb size
|
||||
.word 136 ; ??? block bitmap size
|
||||
.byte 30 ; ??? directory bitmap size
|
||||
.byte 0 ; ??? track count direction ???
|
||||
.byte 0 ; number of uses (if 0, no boot)
|
||||
.byte 0 ; copy protection (OFF)
|
||||
.byte 0 ; boot block read protect (OFF)
|
||||
.byte 0 ; boot block write protect (OFF)
|
||||
.word 0 ; soft error count
|
||||
.word 0 ; hard error count
|
||||
.word 0 ; lowest useable track side 0 ?1?
|
||||
.word 39 ; highest
|
||||
.word 0 ; side 1
|
||||
.word 39 ;
|
||||
.word 0 ; side 2
|
||||
.word 0 ;
|
||||
.word 0 ; side 3
|
||||
.word 0 ;
|
||||
.long BPT ; BOOT FILE FDB BLOCK NUMBER
|
||||
.byte "PCOS" ; system name??
|
||||
.long 2 ; ??? directory start addr
|
||||
.long 0 ; ??? drive data ???
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.word 1 ; disk valid (VALID)
|
||||
.byte 0 ; drive number required ???
|
||||
.byte 0 ; disk open
|
||||
.byte 0 ; format major version #
|
||||
.byte 0 ; minor
|
||||
.byte 2 ; disk type = 320Kb
|
||||
.byte 0 ; 27 bytes of nothing
|
||||
.byte 0 ; 26
|
||||
.byte 0 ; 25
|
||||
.byte 0 ; 24
|
||||
.byte 0 ; 23
|
||||
.byte 0 ; 22
|
||||
.byte 0 ; 21
|
||||
.byte 0 ; 20
|
||||
.byte 0 ; 19
|
||||
.byte 0 ; 18
|
||||
.byte 0 ; 17
|
||||
.byte 0 ; 16
|
||||
.byte 0 ; 15
|
||||
.byte 0 ; 14
|
||||
.byte 0 ; 13
|
||||
.byte 0 ; 12
|
||||
.byte 0 ; 11
|
||||
.byte 0 ; 10
|
||||
.byte 0 ; 9
|
||||
.byte 0 ; 8
|
||||
.byte 0 ; 7
|
||||
.byte 0 ; 6
|
||||
.byte 0 ; 5
|
||||
.byte 0 ; 4
|
||||
.byte 0 ; 3
|
||||
.byte 0 ; 2
|
||||
.byte 0 ; 1
|
||||
.block 22 ; forgotten, aparently
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Track 1 Sector 0
|
||||
;*
|
||||
;* This sector is the FDB for the bootstrap
|
||||
;* file. It has a single extent.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
T1S0:
|
||||
.long FILSIZE ; file length in bytes
|
||||
.word 1 ; #extents
|
||||
.byte 0 ; 14 password (14 bytes)
|
||||
.byte 0 ; 13
|
||||
.byte 0 ; 12
|
||||
.byte 0 ; 11
|
||||
.byte 0 ; 10
|
||||
.byte 0 ; 9
|
||||
.byte 0 ; 8
|
||||
.byte 0 ; 7
|
||||
.byte 0 ; 6
|
||||
.byte 0 ; 5
|
||||
.byte 0 ; 4
|
||||
.byte 0 ; 3
|
||||
.byte 0 ; 2
|
||||
.byte 0 ; 1
|
||||
.word 0 ; ??? verify location ???
|
||||
.byte 0 ; write protect
|
||||
.byte 0 ; future
|
||||
.long BPT+1 ; STARTING BLOCK OF EXTENT
|
||||
.word NBLKS-1 ; NUMBER OF BLOCKS IN EXTENT
|
||||
.block 222 ; other extents
|
||||
.long 0 ; next fdb
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Track 1 Sector 1
|
||||
;*
|
||||
;* This sector is the header for the bootstrap
|
||||
;* file, followed by the first S1SIZE bytes of
|
||||
;* data, which are copied in.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
T1S1:
|
||||
|
||||
.word 0101h ; magic number
|
||||
.byte "PCPM" ; identifier
|
||||
.byte "x01."
|
||||
.byte "01"
|
||||
|
||||
.long SYSTEM+6 ; starting addr.
|
||||
.word 1 ; #code blocks
|
||||
|
||||
.long SYSTEM ; load address
|
||||
.word SYSSIZE/2 ; #words
|
||||
|
||||
s1data .block S1SIZE ; data area
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
;************ biosdefs.z8k **************************
|
||||
;*
|
||||
;* Assembly language definitions for
|
||||
;* P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Calls and Trap Indexes
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
XFER_SC .equ 1
|
||||
BIOS_SC .equ 3
|
||||
BDOS_SC .equ 2
|
||||
MEM_SC .equ 1
|
||||
DEBUG_SC .equ 0
|
||||
|
||||
;* the traps use numbers similar to those in the
|
||||
;* 68K version of P-CP/M
|
||||
|
||||
NTRAPS .equ 48 ;total number of traps
|
||||
SC0TRAP .equ 32 ;trap # of system call 0
|
||||
|
||||
;Z8000 traps
|
||||
EPUTRAP .equ 1 ;EPU (floating pt. emulator)
|
||||
SEGTRAP .equ 2 ;segmentation (68K bus err)
|
||||
NMITRAP .equ 0 ;non-maskable int.
|
||||
PITRAP .equ 8 ;priviledge violation
|
||||
;Interrupts, etc.
|
||||
TRACETR .equ 9 ; trace
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* C Stack frame equates
|
||||
;*
|
||||
;* A C stack frame consists of the PC on top,
|
||||
;* followed by the arguments, leftmost argument first.
|
||||
;*
|
||||
;* The caller adjusts the stack on return.
|
||||
;* Returned value is in r7 (int) or rr6 (long)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
PCSIZE .equ 2 ;PC size non-segmented
|
||||
INTSIZE .equ 2 ;INT data type size
|
||||
LONGSIZE .equ 4 ;LONG data type size
|
||||
|
||||
ARG1 .equ PCSIZE ;integer arguments
|
||||
ARG2 .equ ARG1+INTSIZE
|
||||
ARG3 .equ ARG2+INTSIZE
|
||||
ARG4 .equ ARG3+INTSIZE
|
||||
ARG5 .equ ARG4+INTSIZE
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Segmented Mode Operations
|
||||
;*
|
||||
;* NOTE: segmented indirect-register operations
|
||||
;* can be done by addressing the low half
|
||||
;* of the register pair.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
SEG .MACRO ; START segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
NONSEG .MACRO ; END segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
scall .MACRO ;(segaddr) segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.long ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
sscall .MACRO ;(|segaddr|) short segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.word ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call Trap Handler Stack Frame
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
cr0 .equ 0 ;WORD caller r0
|
||||
cr1 .equ cr0+2 ;WORD caller r1
|
||||
cr2 .equ cr1+2 ;WORD caller r2
|
||||
cr3 .equ cr2+2 ;WORD caller r3
|
||||
cr4 .equ cr3+2 ;WORD caller r4
|
||||
cr5 .equ cr4+2 ;WORD caller r5
|
||||
cr6 .equ cr5+2 ;WORD caller r6
|
||||
cr7 .equ cr6+2 ;WORD caller r7
|
||||
cr8 .equ cr7+2 ;WORD caller r8
|
||||
cr9 .equ cr8+2 ;WORD caller r9
|
||||
cr10 .equ cr9+2 ;WORD caller r10
|
||||
cr11 .equ cr10+2 ;WORD caller r11
|
||||
cr12 .equ cr11+2 ;WORD caller r12
|
||||
cr13 .equ cr12+2 ;WORD caller r13
|
||||
nr14 .equ cr13+2 ;WORD normal r14
|
||||
nr15 .equ nr14+2 ;WORD normal r15
|
||||
scinst .equ nr15+2 ;WORD SC instruction
|
||||
scfcw .equ scinst+2 ;WORD caller FCW
|
||||
scseg .equ scfcw+2 ;WORD caller PC SEG
|
||||
scpc .equ scseg+2 ;WORD caller PC OFFSET
|
||||
FRAMESZ .equ scpc+2
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
;************ biosif.z8k **************************
|
||||
;*
|
||||
;* Assembly language interface for P-CP/M (tm) BIOS
|
||||
;* ----- System-Independent -----
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split into modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;* The resulting code looks a little odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _biosinit ;C portion init
|
||||
.global _flush ;Flush buffers
|
||||
|
||||
.global ccp ;Command Processor
|
||||
|
||||
.global _trapinit ;trap startup
|
||||
|
||||
.global _psap, _sysseg, _sysstk
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios ; initialization
|
||||
.global _wboot ; warm boot
|
||||
.global _input ; input a byte
|
||||
.global _output ; output a byte
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios Initialization and Entry Point
|
||||
;*
|
||||
;* This is where control comes after boot.
|
||||
;* Control is transferred to the CCP.
|
||||
;*
|
||||
;* We get here from bootstrap with:
|
||||
;* segmented mode
|
||||
;* valid stack pointer
|
||||
;* valid PSA in RAM
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
bios:
|
||||
|
||||
; enter in segmented mode.
|
||||
; Get system (PC) segment into r4
|
||||
|
||||
DI VI,NVI
|
||||
calr kludge ; get PC segment on stack
|
||||
kludge: popl rr4, @r14
|
||||
|
||||
; get PSAP into rr2.
|
||||
|
||||
ldctl r2, PSAPSEG
|
||||
ldctl r3, PSAPOFF
|
||||
|
||||
; go non-segmented. save PSAP, system segment,
|
||||
; system stack pointer (in system segment, please)
|
||||
|
||||
NONSEG
|
||||
|
||||
ldl _psap, rr2
|
||||
ld _sysseg, r4
|
||||
ld r14,_sysseg
|
||||
ldl _sysstk, rr14
|
||||
|
||||
; set up system stack so that a return will warm boot
|
||||
|
||||
push @r15,#_wboot
|
||||
|
||||
; set up traps, then enable interrupts
|
||||
|
||||
call _trapinit
|
||||
EI VI,NVI
|
||||
|
||||
; set up C part of Bios
|
||||
|
||||
call _biosinit
|
||||
|
||||
; Turn control over to command processor
|
||||
|
||||
jp ccp
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Warm Boot
|
||||
;*
|
||||
;* flush buffers and initialize Bios
|
||||
;* then transfer to CCP
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
_wboot:
|
||||
call _flush
|
||||
call _biosinit
|
||||
ldl rr14,_sysstk
|
||||
jp ccp
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* I/O port operations
|
||||
;*
|
||||
;* int = input(port: int)
|
||||
;* output (port, data: int)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_input:
|
||||
ld r2,ARG1(r15)
|
||||
subl rr6,rr6
|
||||
inb rl7,@r2
|
||||
ldb rl6,rl7
|
||||
ret
|
||||
|
||||
|
||||
_output:
|
||||
ld r2,ARG1(r15)
|
||||
ld r3,ARG2(r15)
|
||||
outb @r2,rl3
|
||||
ret
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*****************************************************
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
;************ biosio.z8k **************************
|
||||
;*
|
||||
;* I/O routines for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE The Olivetti PROM routines are segmented.
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
.global _disk_io
|
||||
.global _crt_put
|
||||
.global _cold_boot
|
||||
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Prom Subroutine Access
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_disk_io: ;err=disk_io(drv, cmd, count, blk, addr)
|
||||
|
||||
dec r15,#14 ;save registers
|
||||
ldm @r15,r8,#7
|
||||
|
||||
ldb rh7,14+ARG1+1(r15) ;get args
|
||||
ldb rl7,14+ARG2+1(r15)
|
||||
ld r8, 14+ARG3(r15)
|
||||
ld r9, 14+ARG4(r15)
|
||||
ldl rr10,14+ARG5(r15)
|
||||
|
||||
;rh7 = drive #
|
||||
;rl7 = command
|
||||
;r8 = block count
|
||||
;r9 = block number
|
||||
;rr10 = segmented address
|
||||
|
||||
SEG
|
||||
scall 84000068h
|
||||
NONSEG
|
||||
;r8 = block count not transferred
|
||||
;rh7 = #retries
|
||||
;rl7 = final error code (RETURNED)
|
||||
;rh6 = error retried
|
||||
|
||||
and r7,#0FFh ;value returned in r7
|
||||
|
||||
ldm r8,@r15,#7 ;restore regs
|
||||
inc r15,#14
|
||||
ret
|
||||
|
||||
|
||||
_crt_put: ;crt_put(char)
|
||||
|
||||
dec r15,#14 ;save registers
|
||||
ldm @r15,r8,#7
|
||||
|
||||
ld r1,14+ARG1(r15) ;get arg in r1
|
||||
|
||||
SEG ; SEG clobbers r0
|
||||
ld r0,r1 ;rl0 = char
|
||||
scall 84000080h
|
||||
NONSEG
|
||||
|
||||
ldm r8,@r15,#7 ;restore regs
|
||||
inc r15,#14
|
||||
ret
|
||||
|
||||
|
||||
|
||||
_cold_boot:
|
||||
|
||||
SEG
|
||||
scall 8400008Ch
|
||||
NONSEG
|
||||
ret
|
||||
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
;************ biosmem.z8k **************************
|
||||
;*
|
||||
;* Memory Management for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* This module copies data from one memory space
|
||||
;* to another. The machine-dependent parts of
|
||||
;* the mapping are well isolated.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
|
||||
.global memsc
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global xfersc
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1) -> addr
|
||||
;* sets user seg# from addr
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* control transfer to context at addr.
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* x+256 x=1, 3, 5 : segmented I-space addr.
|
||||
;* instead of data access
|
||||
;*
|
||||
;* FFFF: set user segment
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
memsc: ;memory manager system call
|
||||
; CALLED FROM SC
|
||||
; IN SEGMENTED MODE
|
||||
; rr6: source
|
||||
; rr4: dest / space
|
||||
; rr2: length / 0
|
||||
testl rr2
|
||||
jr z mem_map
|
||||
|
||||
mem_copy: ; copy data.
|
||||
; rr6: source
|
||||
; rr4: dest
|
||||
; rr2: length
|
||||
ldirb @r4,@r6,r3
|
||||
ldl rr6,rr4 ; rr6 = dest + length
|
||||
ret
|
||||
|
||||
mem_map: ; map address
|
||||
; rr6: source
|
||||
; r4: caller's seg.
|
||||
; r5: space
|
||||
; r2: caller's FCW
|
||||
NONSEG
|
||||
|
||||
cp r5,#-2 ; space=-2: xfer
|
||||
jp eq xfersc
|
||||
|
||||
ld r4,scseg+4(r15)
|
||||
ld r2,scfcw+4(r15)
|
||||
calr map_1
|
||||
ldl cr6+4(r15),rr6 ; return rr6
|
||||
SEG
|
||||
ret
|
||||
|
||||
map_1: ; dispatch
|
||||
|
||||
cp r5,#0FFFFh
|
||||
jr eq set_usr ; space=-1: user seg
|
||||
|
||||
cpb rl5,#0
|
||||
jr eq call_data
|
||||
cpb rl5,#1
|
||||
jr eq call_prog
|
||||
cpb rl5,#2
|
||||
jr eq sys_data
|
||||
cpb rl5,#3
|
||||
jr eq sys_prog
|
||||
cpb rl5,#4
|
||||
jr eq usr_data
|
||||
cpb rl5,#5
|
||||
jr eq usr_prog
|
||||
|
||||
ret ;default: no mapping
|
||||
|
||||
set_usr: ;-1: set user seg.
|
||||
ld _usrseg,r6
|
||||
ret
|
||||
|
||||
;*
|
||||
;*** THE FOLLOWING CODE IS SYSTEM-DEPENDENT ***
|
||||
;*
|
||||
;* rr6= logical address
|
||||
;* r4 = caller's PC segment
|
||||
;* r2 = caller's FCW
|
||||
;* returns
|
||||
;* rr6= mapped address
|
||||
;*
|
||||
;* Most of the system dependencies are in map_prog,
|
||||
;* which maps a program segment into a data segment
|
||||
;* for access as data.
|
||||
;*
|
||||
|
||||
call_data:
|
||||
bit r2,#15 ; segmented caller?
|
||||
ret nz ; yes-- use passed seg
|
||||
ld r6,r4 ; no -- use pc segment
|
||||
ret ; already mapped
|
||||
|
||||
call_prog:
|
||||
bit r2,#15 ; segmented caller?
|
||||
jr nz map_prog ; yes-- use passed seg
|
||||
ld r6,r4 ; no -- use pc segment
|
||||
jr map_prog ; map prog as data
|
||||
|
||||
sys_data:
|
||||
ld r6, _sysseg
|
||||
ret
|
||||
|
||||
sys_prog:
|
||||
ld r6, _sysseg
|
||||
ret ; assume sys does not
|
||||
; separate code, data
|
||||
|
||||
usr_data:
|
||||
ld r0, #-1
|
||||
cp r0, _usrseg
|
||||
ret eq
|
||||
ld r6, _usrseg
|
||||
ret
|
||||
|
||||
usr_prog:
|
||||
ld r0, #-1
|
||||
cp r0, _usrseg
|
||||
jr eq map_prog
|
||||
ld r6, _usrseg
|
||||
jr map_prog
|
||||
|
||||
|
||||
map_prog: ;map program addr into data
|
||||
; rr6 = address
|
||||
|
||||
testb rh5 ; data access?
|
||||
ret nz ; no: done
|
||||
|
||||
and r6,#7F00h ; extract seg bits
|
||||
|
||||
; olivetti: segment 8 is the only one with
|
||||
; separate I and D spaces, and
|
||||
; the program space is accessed
|
||||
; as segment 10's data.
|
||||
|
||||
cpb rh6,#8
|
||||
ret ne
|
||||
ldb rh6,#10
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Data
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_sysseg: .block 2 ;system segment
|
||||
_usrseg: .block 2 ;user segment
|
||||
_sysstk: .block 4 ;system stack pointer
|
||||
_psap: .block 4 ;program status area ptr
|
||||
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
@@ -0,0 +1,370 @@
|
||||
;************ biostrap.z8k **************************
|
||||
;*
|
||||
;* Trap handlers for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created
|
||||
;* 821123 D. Dunlop (Zilog) -- added Olivetti M20-
|
||||
;* specific code to invalidate track buffer
|
||||
;* contents when disk drive motor stops
|
||||
;* (fixes directory-overwrite on disk change)
|
||||
;* 830305 D. Sallume (Zilog) -- added FPE trap
|
||||
;* code.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* Trap and interrupt handlers are started up
|
||||
;* in segmented mode.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global __bios ;C portion of BIOS
|
||||
.global memsc ;memory-management SC
|
||||
.global _tbvalid ;disk track buff valid
|
||||
.global _tbdirty ;disk track buff is dirty
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap, fp_epu
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* M-20 ROM scratchpad RAM addresses
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
rtc_ext: .equ 82000022h ;Place to put address
|
||||
; of list of functions
|
||||
; for each clock tick
|
||||
motor_on: .equ 82000020h ;Disk motor timeout
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _trapinit
|
||||
.global _trapvec
|
||||
.global _trap
|
||||
|
||||
.global xfersc
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap vector table
|
||||
;*
|
||||
;* entries 0..31 are misc. system traps
|
||||
;* entries 32..47 are system calls 0..15
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_trapvec:
|
||||
.block NTRAPS*4
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call and General Trap Handler And Dispatch
|
||||
;*
|
||||
;* It is assumed that the system runs
|
||||
;* non-segmented on a segmented CPU.
|
||||
;*
|
||||
;* _trap is jumped to segmented, with the
|
||||
;* following information on the stack:
|
||||
;*
|
||||
;* trap type: WORD
|
||||
;* reason: WORD
|
||||
;* fcw: WORD
|
||||
;* pc: LONG
|
||||
;*
|
||||
;* The trap handler is called as a subroutine,
|
||||
;* with all registers saved on the stack,
|
||||
;* IN SEGMENTED MODE. This allows the trap
|
||||
;* handler to be in another segment (with some
|
||||
;* care). This is useful mainly to the debugger.
|
||||
;*
|
||||
;* All registers except rr0 are also passed
|
||||
;* intact to the handler.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
sc_trap: ;system call trap server
|
||||
|
||||
push @r14,@r14
|
||||
|
||||
|
||||
_trap:
|
||||
|
||||
sub r15,#30 ; push caller state
|
||||
ldm @r14,r0,#14
|
||||
NONSEG ; go nonsegmented
|
||||
ldctl r1,NSP
|
||||
ld nr14(r15),r14
|
||||
ex r1,nr15(r15)
|
||||
|
||||
; trap# now in r1
|
||||
cpb rh1,#7Fh ; system call?
|
||||
jr ne trap_disp ; no
|
||||
; yes: map it
|
||||
clrb rh1
|
||||
add r1,#SC0TRAP
|
||||
|
||||
;=== need range check ===
|
||||
|
||||
trap_disp: ; dispatch
|
||||
sll r1,#2
|
||||
ldl rr0,_trapvec(r1)
|
||||
testl rr0
|
||||
jr z _trap_ret ; zero -- no action
|
||||
; else call seg @rr0
|
||||
pushl @r15,rr0 ; (done via kludge)
|
||||
SEG
|
||||
popl rr0,@r14
|
||||
calr trap_1
|
||||
jr _trap_ret
|
||||
|
||||
trap_1: ; jp @rr0
|
||||
pushl @r14,rr0
|
||||
ret
|
||||
|
||||
|
||||
_trap_ret: ;return from trap or interrupt
|
||||
|
||||
NONSEG
|
||||
ld r1,nr15(r15) ; pop state
|
||||
ld r14,nr14(r15)
|
||||
ldctl NSP,r1
|
||||
SEG ; go segmented for the iret.
|
||||
ldm r0,@r14,#14
|
||||
add r15,#32
|
||||
|
||||
iret ; return from interrupt
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Assorted Trap Handlers
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
epu_trap:
|
||||
push @r14,#EPUTRAP
|
||||
jr _trap
|
||||
|
||||
pi_trap:
|
||||
push @r14,#PITRAP
|
||||
jr _trap
|
||||
|
||||
seg_trap:
|
||||
push @r14,#SEGTRAP
|
||||
jr _trap
|
||||
|
||||
nmi_trap:
|
||||
push @r14,#NMITRAP
|
||||
jr _trap
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios system call handler
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
biossc: ;call bios
|
||||
NONSEG
|
||||
; r3 = operation code
|
||||
; rr4= P1
|
||||
; rr6= P2
|
||||
|
||||
ld r0,scfcw+4(r15) ; if caller nonseg, normal
|
||||
and r0,#0C000h
|
||||
jr nz seg_ok
|
||||
|
||||
ld r4,scseg+4(r15) ; then add seg to P1, P2
|
||||
ld r6,r4
|
||||
seg_ok:
|
||||
; set up C stack frame
|
||||
;===
|
||||
pushl @r15,rr6
|
||||
pushl @r15,rr4
|
||||
push @r15,r3
|
||||
|
||||
; call C program
|
||||
call __bios
|
||||
|
||||
; clean stack & return
|
||||
add r15,#10
|
||||
ldl cr6+4(r15),rr6 ; with long in rr6
|
||||
|
||||
SEG
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch System Call
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC segment
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
xfersc: ;enter here from system call
|
||||
SEG
|
||||
|
||||
; build frame on system stack
|
||||
|
||||
; when called from system call, the frame replaces
|
||||
; the caller's context, which will never be resumed.
|
||||
|
||||
inc r15,#4 ;discard return addr
|
||||
ldl rr4,rr14 ;move context
|
||||
ld r2,#FRAMESZ/2
|
||||
ldir @r4,@r6,r2
|
||||
jr _trap_ret ;restore context
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _motor_c -- check if disk motor still running.
|
||||
;* Entered each clock tick. Invalidates
|
||||
;* track buffer when motor stops
|
||||
;* (Note: runs segmented)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_motor_c:
|
||||
ldl rr4,#motor_on ;Motor running?
|
||||
test @r4
|
||||
ret nz ;Yes: do nothing
|
||||
ldar r4,$
|
||||
ld r5,#_tbdirty ; Is track buff dirty?
|
||||
test @r4 ; Yes...
|
||||
ret nz ; ...return without invalidating
|
||||
ld r5,#_tbvalid
|
||||
clr @r4 ;No: mark track buffer
|
||||
ret ; invalid
|
||||
|
||||
; Table of functions run each real time clock tick
|
||||
|
||||
_ticktab:
|
||||
.long -1 ;Will contain _motor_c
|
||||
.word 0ffffh ;Terminator
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _trapinit -- initialize trap system
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;*
|
||||
;* PSA (Program Status Area) structure
|
||||
;*
|
||||
ps .equ 8 ; size of a program status entry
|
||||
; --- segmented ---
|
||||
|
||||
psa_epu .equ 1*ps ; EPU trap offset
|
||||
psa_prv .equ 2*ps ; priviledged instruction trap
|
||||
psa_sc .equ 3*ps ; system call trap
|
||||
psa_seg .equ 4*ps ; segmentation trap
|
||||
psa_nmi .equ 5*ps ; non-maskable interrupt
|
||||
psa_nvi .equ 6*ps ; non-vectored interrupt
|
||||
psa_vi .equ 7*ps ; vectored interrupt
|
||||
psa_vec .equ psa_vi+(ps/2) ; vectors
|
||||
|
||||
|
||||
_trapinit:
|
||||
|
||||
; initialize trap table
|
||||
|
||||
lda r2,_trapvec
|
||||
ld r0,#NTRAPS
|
||||
subl rr4,rr4
|
||||
clrtraps:
|
||||
ldl @r2,rr4
|
||||
inc r2,#4
|
||||
djnz r0,clrtraps
|
||||
|
||||
ld r2,_sysseg
|
||||
lda r3,biossc
|
||||
ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2
|
||||
lda r3,memsc
|
||||
ldl _trapvec+(MEM_SC+SC0TRAP)*4,rr2
|
||||
lda r3,fp_epu
|
||||
ldl _trapvec+EPUTRAP*4,rr2
|
||||
|
||||
|
||||
; initialize some PSA entries.
|
||||
; rr0 PSA entry: FCW (ints ENABLED)
|
||||
; rr2 PSA entry: PC
|
||||
; rr4 -> PSA slot
|
||||
|
||||
ldl rr4,_psap
|
||||
SEG
|
||||
ldl rr0,#0000D800h
|
||||
|
||||
add r5,#ps ; EPU trap
|
||||
ldar r2,epu_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; Priviledged Inst
|
||||
ldar r2,pi_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; System Call
|
||||
ldar r2,sc_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; segmentation
|
||||
ldar r2,seg_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; Non-Maskable Int.
|
||||
ldar r2,nmi_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
; Set up Real-Time Clock external call loc
|
||||
|
||||
ldar r2,_motor_c
|
||||
ldar r4,_ticktab
|
||||
ldl @r4,rr2
|
||||
ldl rr2,#rtc_ext
|
||||
ldl @r2,rr4
|
||||
NONSEG
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,131 @@
|
||||
;*************************************************
|
||||
;** Change history --
|
||||
;** 30mar81: Broken off from general interface.
|
||||
;** 30mar81: Set up for Zilog ZLAB 8000
|
||||
;** 09may81: Tell cpu when state is free.
|
||||
;** 19jan82: Allow segmented users.
|
||||
;** 21jan82: Took out references to freecpu and needcpu
|
||||
;** 15feb82: Dummy out need/free cpu.
|
||||
;** 13may82: Comment out references to setfp and resfp
|
||||
;*************************************************
|
||||
|
||||
.title "sysdep MODULE"
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
;*************************************************
|
||||
;** SAVED CPU STATE --
|
||||
;** is specified by the following "constants."
|
||||
;** Offset stapcsg must point to the word preceding
|
||||
;** the saved PC offset, EVEN FOR NONSEGMENTED
|
||||
;** OPERATION.
|
||||
;*************************************************
|
||||
__data .sect
|
||||
.GLOBAL stareg,staevnt,stafcw,stapcsg
|
||||
stareg .WORD 4 ;offset of r0
|
||||
staevnt .WORD 36 ;saved 1st word
|
||||
stafcw .WORD 38 ;saved fcw
|
||||
stapcsg .WORD 40 ;seg word of PC
|
||||
|
||||
;*************************************************
|
||||
;** ADDRESSES --
|
||||
;** as input parameters to the routines below are
|
||||
;** delivered in register pairs (i.e. as though
|
||||
;** segmented). The high-order word of such an
|
||||
;** address is undefined when the process running
|
||||
;** in that address space runs in nonsegmented
|
||||
;** mode.
|
||||
;*************************************************
|
||||
.eject
|
||||
;*************************************************
|
||||
;** GET NEXT INSTRUCTION WORD --
|
||||
;** Input:
|
||||
;** rr6 = saved PC -- seg # must be fixed for
|
||||
;** nonseg users
|
||||
;** Output:
|
||||
;** r3 = next instruction word
|
||||
;*************************************************
|
||||
__data .sect
|
||||
gttxt: .WORD 0
|
||||
__text .sect
|
||||
.GLOBAL gettext
|
||||
gettext: ; PROCEDURE ENTRY
|
||||
; ld r5,#2 ; it is system data
|
||||
; ldl rr2,#0 ; required parameter
|
||||
; sc #MEM_SC ; MAP source
|
||||
|
||||
pushl @r15,rr6
|
||||
ld r7,#gttxt ; address of temp
|
||||
ld r5,#0 ; it is caller Instruction
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP destination
|
||||
|
||||
ldl rr4,rr6
|
||||
popl rr6,@r15 ; restore source
|
||||
ldl rr2,#2 ; byte count to move
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ld r3,gttxt ; load return values
|
||||
ldb rl2,#0
|
||||
ret
|
||||
|
||||
.eject
|
||||
;*************************************************
|
||||
;** GET MEMORY BYTES --
|
||||
;** Segmented emulator input --
|
||||
;** rr6 - src address (trapee space)
|
||||
;** rr4 - dst address (emulator space)
|
||||
;** r3 - byte count
|
||||
;*************************************************
|
||||
.GLOBAL getmem
|
||||
getmem:
|
||||
push @r15,r3
|
||||
; pushl @r15,rr4
|
||||
; ld r5,#4 ; it is user data
|
||||
; ldl rr2,#0 ; required parameter
|
||||
; sc #MEM_SC ; MAP source
|
||||
;
|
||||
; popl rr4,@r15
|
||||
pushl @r15,rr6 ; save source
|
||||
ldl rr6,rr4 ; position dest
|
||||
ld r5,#0 ; it is caller data
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP destination
|
||||
|
||||
ldl rr4,rr6
|
||||
popl rr6,@r15 ; restore source
|
||||
pop r3,@r15 ; restore byte count
|
||||
ld r2,#0 ; requrired parameter
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ret
|
||||
|
||||
.eject
|
||||
;*************************************************
|
||||
;** PUT MEMORY BYTES --
|
||||
;** Emulator input --
|
||||
;** rr6 - src address (emulator space)
|
||||
;** rr4 - dst address (trapee space)
|
||||
;** r3 - byte count
|
||||
;*************************************************
|
||||
.GLOBAL putmem
|
||||
putmem: ; PROCEDURE ENTRY
|
||||
push @r15,r3
|
||||
pushl @r15,rr4
|
||||
ld r5,#0 ; it is caller data
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP source
|
||||
|
||||
popl rr4,@r15
|
||||
; pushl @r15,rr6 ; save source
|
||||
; ldl rr6,rr4 ; position destination
|
||||
; ld r5,#2 ; it is system data
|
||||
; ldl rr2,#0 ; required parameter
|
||||
; sc #MEM_SC ; MAP destination
|
||||
;
|
||||
; ldl rr4,rr6
|
||||
; popl rr6,@r15 ; restore source
|
||||
pop r3,@r15 ; restore byte count
|
||||
ld r2,#0 ; required parameter
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ret
|
||||
@@ -0,0 +1,155 @@
|
||||
;************ syscall.z8s **************************
|
||||
;*
|
||||
;* System Call interface for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 820927 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* The following system call interface routines
|
||||
;* are designed to be called from non-segmented
|
||||
;* C programs.
|
||||
;*
|
||||
;* Addresses are passed as LONGs.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
.global _xfer
|
||||
.global _mem_cpy
|
||||
.global _map_adr
|
||||
.global _bios
|
||||
.global _bdos
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch Routine
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC segment
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_xfer:
|
||||
|
||||
ldl rr6,ARG1(r15)
|
||||
ldl rr4,#-2
|
||||
subl rr2,rr2
|
||||
sc #XFER_SC
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1)
|
||||
;* sets user segment # from addr.
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* transfer to context block at addr
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* x+256 return segmented instruction address,
|
||||
;* not data access address
|
||||
;*
|
||||
;* FFFF set user-space segment from address
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
_mem_cpy: ;copy memory C subroutine
|
||||
|
||||
;===
|
||||
ldl rr6,ARG1(r15)
|
||||
ldl rr4,ARG3(r15)
|
||||
ldl rr2,ARG5(r15)
|
||||
sc #MEM_SC
|
||||
ret
|
||||
|
||||
|
||||
_map_adr: ;map address C subroutine
|
||||
|
||||
;===
|
||||
ldl rr6,ARG1(r15)
|
||||
ld r5, ARG3(r15)
|
||||
subl rr2,rr2 ; 0 length says map
|
||||
sc #MEM_SC
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* long _bios(code, p1, p2)
|
||||
;* long _bdos(code, p1)
|
||||
;* int code;
|
||||
;* long p1, p2;
|
||||
;*
|
||||
;* BIOS, BDOS access
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
_bios:
|
||||
ld r3,ARG1(r15)
|
||||
ldl rr4,ARG2(r15)
|
||||
ldl rr6,ARG4(r15)
|
||||
sc #BIOS_SC
|
||||
ret
|
||||
|
||||
_bdos:
|
||||
ld r5,ARG1(r15)
|
||||
ldl rr6,ARG2(r15)
|
||||
sc #BDOS_SC
|
||||
ret
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/* 07/20/82 Added new types WORD and BYTE (DMH) */
|
||||
/* 10/15/82 Added some new defines (DMH) */
|
||||
/* 11/13/82 This is the version for Unidot comp- */
|
||||
/* iler which doesn't support unsigned. */
|
||||
|
||||
/* the pseudo storage classes */
|
||||
|
||||
#define AFAST register
|
||||
#define FAST register
|
||||
#define GLOBAL extern
|
||||
#define IMPORT extern
|
||||
#define INTERN static
|
||||
#define LOCAL static
|
||||
|
||||
/* the pseudo types */
|
||||
|
||||
typedef char TEXT, TINY;
|
||||
typedef double DOUBLE;
|
||||
typedef int ARGINT, BOOL, VOID;
|
||||
typedef long LONG;
|
||||
typedef short BITS, COUNT, FILE;
|
||||
typedef /* unsigned */ BYTES, WORD;
|
||||
typedef /* unsigned */ char BYTE, UTINY;
|
||||
typedef /* unsigned */ long ULONG;
|
||||
typedef /* unsigned */ short UCOUNT;
|
||||
|
||||
/* system parameters */
|
||||
|
||||
#define STDIN 0
|
||||
#define STDOUT 1
|
||||
#define STDERR 2
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NULL 0
|
||||
#define FOREVER for (;;)
|
||||
#define BUFSIZE 512
|
||||
#define BWRITE -1
|
||||
#define READ 0
|
||||
#define WRITE 1
|
||||
#define UPDATE 2
|
||||
#define EOF -1
|
||||
#define BYTMASK 0377
|
||||
|
||||
/* macros */
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||
#define gtc(pf) (0 < (pf)->_nleft ? (--(pf)->_nleft, *(pf)->_pnext++ & BYTMASK) \
|
||||
: getc(pf))
|
||||
#define isalpha(c) (islower(c) || isupper(c))
|
||||
#define isdigit(c) ('0' <= (c) && (c) <= '9')
|
||||
#define islower(c) ('a' <= (c) && (c) <= 'z')
|
||||
#define isupper(c) ('A' <= (c) && (c) <= 'Z')
|
||||
#define iswhite(c) ((c) <= ' ' || 0177 <= (c)) /* ASCII ONLY */
|
||||
#define max(x, y) (((x) < (y)) ? (y) : (x))
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define ptc(pf, c) if ((pf)->_nleft < 512) (pf)->_buf[(pf)->_nleft++] = (c); \
|
||||
else putc(pf, (c))
|
||||
#define tolower(c) (isupper(c) ? ((c) + ('a' - 'A')) : (c))
|
||||
#define toupper(c) (islower(c) ? ((c) - ('a' - 'A')) : (c))
|
||||
|
||||
/* the file IO structure */
|
||||
|
||||
typedef struct fio
|
||||
{
|
||||
FILE _fd;
|
||||
COUNT _nleft;
|
||||
COUNT _fmode;
|
||||
TEXT *_pnext;
|
||||
TEXT _buf[BUFSIZE];
|
||||
} FIO;
|
||||
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* B A S E P A G E . H */
|
||||
/* ------------------- */
|
||||
/* */
|
||||
/* This file contains a definition of the CP/M basepage structure, */
|
||||
/* b_page. */
|
||||
/* */
|
||||
/* NOTE: In the portable CP/M environment, it is NOT guaranteed */
|
||||
/* that the location of the base page is known at link-edit time */
|
||||
/* (as it is, for example, in CP/M-80 and CP/M-86.) Instead, a */
|
||||
/* pointer to the current basepage is delivered by the BDOS */
|
||||
/* to each new program which is run. This pointer, _base, is */
|
||||
/* initialized by the C startup function (startup.s) and is */
|
||||
/* available to C programs as an external. */
|
||||
/* */
|
||||
/* This file has been modified to live with the BDOS definitions. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct b_page
|
||||
{
|
||||
XADDR ltpa; /* Low TPA address */
|
||||
XADDR htpa; /* High TPA address */
|
||||
XADDR lcode; /* Start address of code seg*/
|
||||
long codelen; /* Code segment length */
|
||||
XADDR ldata; /* Start address of data seg*/
|
||||
long datalen; /* Data segment length */
|
||||
XADDR lbss; /* Start address of bss seg */
|
||||
long bsslen; /* Bss segment length */
|
||||
long freelen; /* Free segment length */
|
||||
char resvd1[20]; /* Reserved area */
|
||||
struct fcb fcb2; /* Second basepage FCB */
|
||||
struct fcb fcb1; /* First basepage FCB */
|
||||
char buff[128]; /* Default DMA buffer, */
|
||||
/* command line tail */
|
||||
};
|
||||
@@ -0,0 +1,170 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* P-CP/M header file *
|
||||
* Copyright (c) 1982 by Digital Research, Inc. *
|
||||
* Structure definitions for BDOS globals *
|
||||
* and BDOS data structures *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
The BDOS data structures, especially those relating to global variables,
|
||||
are structured in a way that hopefully will enable this BDOS, in the future,
|
||||
to easily become a re-entrant multi-tasking file system. Consequently,
|
||||
the BDOS global variables are divided into two classes. Those that are
|
||||
truly global, even in the case of multiple tasks using the file system
|
||||
concurrently, are simply declared as global variables in bdosmain.c.
|
||||
Only a few "globals" are really global in this sense.
|
||||
|
||||
The majority of the "global" variables are actually state variables that
|
||||
relate to the state of the task using the file system. In CP/M-68K, these
|
||||
are "global", since there's only one task, but in a multi-thread model they're
|
||||
not. These type of variables are put into a data structure, with the
|
||||
intention that in the multi-task environment this structure will be based.
|
||||
|
||||
The following declarations take this philosophy into account, and define
|
||||
a simple structure for the single thread environment while leaving the
|
||||
possibilities open for the multi-thread environment.
|
||||
****************************************************************************/
|
||||
|
||||
#define snglthrd TRUE
|
||||
/* TRUE for single-thread environment
|
||||
undefined to create based structure for re-entrant model */
|
||||
#ifdef snglthrd
|
||||
#define GBL gbls
|
||||
/* In single thread case, GBL just names
|
||||
the structure */
|
||||
#define BSETUP EXTERN struct stvars gbls;
|
||||
/* and BSETUP defines the extern structure */
|
||||
#else
|
||||
|
||||
#define GBL (*statep)
|
||||
/* If multi-task, state vars are based */
|
||||
#define BSETUP REG struct stvars *statep; \
|
||||
statep = &gbls;
|
||||
/* set up pointer to state variables */
|
||||
/* This is intended as an example to show the intent */
|
||||
#endif
|
||||
|
||||
|
||||
/* Note that there are a few critical regions in the file system that must
|
||||
execute without interruption. They pertain mostly to the manipulation of
|
||||
the allocation vector. This isn't a problem in a single-thread model, but
|
||||
must be provided for in a multi-tasking file system. Consequently, the
|
||||
primitives LOCK and UNLOCK are defined and used where necessary in the
|
||||
file system. For the single thread model, they are null routines */
|
||||
|
||||
#define LOCK /**/
|
||||
#define UNLOCK /**/
|
||||
/* Be sure LOCK and UNLOCK are implemented to allow recursive calls to LOCK.
|
||||
That is, if a process that calls LOCK already owns the lock, let it proceed,
|
||||
but remember that only the outer-most call to UNLOCK really releases the
|
||||
file system. */
|
||||
|
||||
|
||||
#define VERSION 0x2022 /* Version number for CP/M-68K */
|
||||
#define robit 0 /* read-only bit in file type field of fcb */
|
||||
#define SECLEN 128 /* length of a CP/M sector */
|
||||
|
||||
|
||||
union smallbig
|
||||
{
|
||||
UBYTE small[16]; /* 16 block numbers of 1 byte */
|
||||
WORD big[8]; /* or 8 block numbers of 1 word */
|
||||
};
|
||||
|
||||
/* File Control Block definition */
|
||||
struct fcb
|
||||
{
|
||||
UBYTE drvcode; /* 0 = default drive, 1..16 are drives A..P */
|
||||
UBYTE fname[8]; /* File name (ASCII) */
|
||||
UBYTE ftype[3]; /* File type (ASCII) */
|
||||
UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
UBYTE s1; /* Reserved */
|
||||
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
union smallbig dskmap;
|
||||
UBYTE cur_rec; /* current record field */
|
||||
UBYTE ran0; /* random record field (3 bytes) */
|
||||
UBYTE ran1;
|
||||
UBYTE ran2;
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of directory entry */
|
||||
struct dirent
|
||||
{
|
||||
UBYTE entry; /* 0 - 15 for user numbers, E5 for empty */
|
||||
/* the rest are reserved */
|
||||
UBYTE fname[8]; /* File name (ASCII) */
|
||||
UBYTE ftype[3]; /* File type (ASCII) */
|
||||
UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
UBYTE s1; /* Reserved */
|
||||
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
union smallbig dskmap;
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of disk parameter tables */
|
||||
struct dpb /* disk parameter table */
|
||||
{
|
||||
UWORD spt; /* sectors per track */
|
||||
UBYTE bsh; /* block shift factor */
|
||||
UBYTE blm; /* block mask */
|
||||
UBYTE exm; /* extent mask */
|
||||
UBYTE dpbdum; /* dummy byte for fill */
|
||||
UWORD dsm; /* max disk size in blocks */
|
||||
UWORD drm; /* max directory entries */
|
||||
UWORD dir_al; /* initial allocation for dir */
|
||||
UWORD cks; /* number dir sectors to checksum */
|
||||
UWORD trk_off; /* track offset */
|
||||
};
|
||||
|
||||
struct dph /* disk parameter header */
|
||||
{
|
||||
UBYTE *xlt; /* pointer to sector translate table */
|
||||
UWORD hiwater; /* high water mark for this disk */
|
||||
UWORD dum1; /* dummy (unused) */
|
||||
UWORD dum2;
|
||||
UBYTE *dbufp; /* pointer to 128 byte directory buffer */
|
||||
struct dpb *dpbp; /* pointer to disk parameter block */
|
||||
UBYTE *csv; /* pointer to check vector */
|
||||
UBYTE *alv; /* pointer to allocation vector */
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of structure containing "global" state variables */
|
||||
struct stvars
|
||||
{
|
||||
UBYTE kbchar; /* One byte keyboard type-ahead buffer */
|
||||
UBYTE delim; /* Delimiter for function 9 */
|
||||
BOOLEAN lstecho; /* True if echoing console output to lst: */
|
||||
BOOLEAN echodel; /* Echo char when getting <del> ? */
|
||||
UWORD column; /* CRT column number for expanding tabs */
|
||||
XADDR chainp; /* Used for chain to program call */
|
||||
UBYTE curdsk; /* Currently selected disk */
|
||||
UBYTE dfltdsk; /* Default disk (last selected by fcn 14) */
|
||||
UBYTE user; /* Current user number */
|
||||
struct dph *dphp; /* pointer to disk parm hdr for cur disk */
|
||||
struct dirent *dirbufp; /* pointer for directory buff for process */
|
||||
/* stored here so that each process can */
|
||||
/* have a separate dirbuf. */
|
||||
struct dpb *parmp; /* pointer to disk parameter block for cur */
|
||||
/* disk. Stored here to save ref calc */
|
||||
UWORD srchpos; /* position in directory for search next */
|
||||
XADDR dmaadr; /* Disk dma address */
|
||||
XADDR srchp; /* Pointer to search FCB for function 17 */
|
||||
UBYTE *excvec[14]; /* Array of exception vectors */
|
||||
};
|
||||
|
||||
|
||||
/* Console buffer structure declaration */
|
||||
struct conbuf
|
||||
{
|
||||
UBYTE maxlen; /* Maximum length from calling routine */
|
||||
UBYTE retlen; /* Length actually found by BDOS */
|
||||
UBYTE cbuf[1]; /* Console data */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* BIOS definitions for P-CP/M *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
* This include file simply defines the BIOS calls *
|
||||
* *
|
||||
* Memory management added 821018 by SS at Zilog *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
EXTERN UBYTE bios1(); /* used for character I/O functions */
|
||||
EXTERN bios2(); /* parm1 is word, no return value */
|
||||
EXTERN bios3(); /* used for set dma only */
|
||||
/* parm1 is a pointer, no return */
|
||||
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
|
||||
/* words, returns a pointer to dph */
|
||||
EXTERN UWORD bios5(); /* for sectran and set exception */
|
||||
|
||||
|
||||
#define bwboot() bios1(1) /* warm boot */
|
||||
#define bconstat() bios1(2) /* console status */
|
||||
#define bconin() bios1(3) /* console input */
|
||||
#define bconout(parm) bios2(4,parm) /* console output parm */
|
||||
#define blstout(parm) bios2(5,parm) /* list device output */
|
||||
#define bpun(parm) bios2(6,parm) /* punch char output */
|
||||
#define brdr() bios1(7) /* reader input */
|
||||
#define bhome() bios1(8) /* recalibrate drive */
|
||||
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
|
||||
/* select disk and return info */
|
||||
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
|
||||
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
|
||||
#define bsetdma(parm) bios3(12,parm) /* set dma address */
|
||||
#define bread() bios1(13) /* read sector from disk */
|
||||
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
|
||||
#define blistst() bios1(15) /* list device status */
|
||||
#define bsectrn(parm1,parm2) bios5(16,parm1,(XADDR)parm2)
|
||||
/* sector translate */
|
||||
#define bgetseg() bios1(18) /* get memory segment tbl */
|
||||
#define bgetiob() bios1(19) /* get I/O byte */
|
||||
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
|
||||
#define bflush() bios1(21) /* flush buffers */
|
||||
#define bsetvec(parm1,parm2) bios5(22,parm1,(XADDR)parm2)
|
||||
/* set exception vector */
|
||||
|
||||
|
||||
/************************/
|
||||
/* MEMORY MANAGEMENT */
|
||||
/*----------------------*/
|
||||
EXTERN XADDR map_adr(); /*(laddr, space)->paddr */
|
||||
EXTERN VOID mem_cpy(); /*(src, dst, len) */
|
||||
/*----------------------*/
|
||||
/* copy in, out (s,d,l) */
|
||||
/* */
|
||||
#define cpy_in(s,d,l) mem_cpy((XADDR)s, map_adr((XADDR)d, 0), (long)l)
|
||||
#define cpy_out(s,d,l) mem_cpy(map_adr((XADDR)s, 0), (XADDR)d, (long)l)
|
||||
/* */
|
||||
/************************/
|
||||
|
||||
|
||||
1505
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/ccp/ccp.c
Normal file
1505
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/ccp/ccp.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,158 @@
|
||||
/*--------------------------------------------------------------*\
|
||||
| ccp_def.c DEFINES v1.0 |
|
||||
| ======= |
|
||||
| |
|
||||
| P-CP/M: A CP/M derived operating system |
|
||||
| |
|
||||
| File contents: |
|
||||
| ------------- |
|
||||
| This file contains all of the #defines |
|
||||
| used by the console command processor. |
|
||||
| |
|
||||
| created by : Tom Saulpaugh Date: 7/13/82 |
|
||||
| ---------- |
|
||||
| last modified: 12/20/82 |
|
||||
| ------------- |
|
||||
| |
|
||||
| (c) COPYRIGHT Digital Research 1982 |
|
||||
| all rights reserved |
|
||||
| |
|
||||
\*--------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| CP/M Transient Commands |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define DIRCMD 0
|
||||
#define TYPECMD 1
|
||||
#define RENCMD 2
|
||||
#define ERACMD 3
|
||||
#define UCMD 4
|
||||
#define CH_DISK 5
|
||||
#define SUBCMD 6
|
||||
#define SUB_FILE 7
|
||||
#define FILE 8
|
||||
#define DIRSCMD 9
|
||||
#define SEARCH 10
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| Modes and Flags |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define ON 1
|
||||
#define OFF 0
|
||||
#define MATCH 0
|
||||
#define GOOD 1
|
||||
#define BAD 0
|
||||
#define FILL 1
|
||||
#define NOFILL 0
|
||||
#define VOID /*no return value*/
|
||||
#define NO_FILE 98
|
||||
#define STOP 99
|
||||
#define USER_ZERO 0
|
||||
#define DISK_A 1
|
||||
#define SOURCEDRIVE 88
|
||||
#define DESTDRIVE 99
|
||||
#define BYTE char
|
||||
#define REG register
|
||||
#define WORD short
|
||||
#define UWORD unsigned int
|
||||
#define LONG long
|
||||
#define ULONG unsigned long
|
||||
#define GET_MEM_REG 18
|
||||
#define ZERO 0
|
||||
#define NULL '\0'
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NO_READ 255
|
||||
#define BLANK ' '
|
||||
#define BACKSLH '\\'
|
||||
#define EXLIMPT '!'
|
||||
#define CMASK 0177
|
||||
#define ONE (long)49
|
||||
#define TAB 9
|
||||
#define Cr 13
|
||||
#define Lf 10
|
||||
#define CR (long)13
|
||||
#define LF (long)10
|
||||
#define EOF 26
|
||||
#define BLANKS (long)32
|
||||
#define PERIOD (long)46
|
||||
#define COLON (long)58
|
||||
#define ARROW (long)62
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| Data Structure Size Constants |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define CMD_LEN 128
|
||||
#define BIG_CMD_LEN 255
|
||||
#define MAX_ARGS 4
|
||||
#define ARG_LEN 26
|
||||
#define NO_OF_DRIVES 16
|
||||
#define NUMDELS 16
|
||||
#define FCB_LEN 36
|
||||
#define DMA_LEN 128
|
||||
#define FILES_PER_LINE 4 /* Zilog */
|
||||
#define SCR_HEIGHT 23
|
||||
#define BIG_WIDTH 80
|
||||
#define SMALL_WIDTH 40
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| BDOS Function Calls |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define WARMBOOT 0
|
||||
#define CONIN 1
|
||||
#define CONSOLE_OUTPUT 2
|
||||
#define READER_INPUT 3
|
||||
#define PUNCH_OUTPUT 4
|
||||
#define LIST_OUTPUT 5
|
||||
#define DIR_CONS_I/O 6
|
||||
#define GET_I/O_BYTE 7
|
||||
#define SET_I/O_BYTE 8
|
||||
#define PRINT_STRING 9
|
||||
#define READ_CONS_BUF 10
|
||||
#define GET_CONS_STAT 11
|
||||
#define RET_VERSION_NO 12
|
||||
#define RESET_DISK_SYS 13
|
||||
#define SELECT_DISK 14
|
||||
#define OPEN_FILE 15
|
||||
#define CLOSE_FILE 16
|
||||
#define SEARCH_FIRST 17
|
||||
#define SEARCH_NEXT 18
|
||||
#define DELETE_FILE 19
|
||||
#define READ_SEQ 20
|
||||
#define WRITE_SEQ 21
|
||||
#define MAKE_FILE 22
|
||||
#define RENAME_FILE 23
|
||||
#define RET_LOGIN_VEC 24
|
||||
#define RET_CUR_DISK 25
|
||||
#define SET_DMA_ADDR 26
|
||||
/* #define GET_ADDR(ALLOC) 27 */
|
||||
#define WRITE_PROT_DISK 28
|
||||
#define GET_READ/O_VEC 29
|
||||
#define SET_FILE_ATTRIB 30
|
||||
#define GET_ADDR_D_PARM 31
|
||||
#define GET_USER_NO 32
|
||||
#define READ_RANDOM 33
|
||||
#define WRITE_RANDOM 34
|
||||
#define COMP_FILE-SIZE 35
|
||||
#define SET_RANDOM_REC 36
|
||||
#define RESET_DRIVE 37
|
||||
/* #define WRITE_RAN_ZERO 40 */
|
||||
#define BIOS_CALL 50
|
||||
#define LOAD_PROGRAM 59
|
||||
|
||||
/*----------------------------------------------*\
|
||||
| MACROS |
|
||||
\*----------------------------------------------*/
|
||||
|
||||
#define isalpha(c) (islower(c) || isupper(c))
|
||||
#define islower(c) ('a' <= (c) && (c) <= 'z')
|
||||
#define isupper(c) ('A' <= (c) && (c) <= 'Z')
|
||||
#define tolower(c) (isupper(c) ? ((c)+040):(c))
|
||||
#define toupper(c) (islower(c) ? ((c)-040):(c))
|
||||
#define isdigit(c) ('0' <= (c) && (c) <= '9')
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
;******* ccpif.z8k -- CCP interface *****************
|
||||
;*
|
||||
;* 821015 S. Savitzky (Zilog) derived from 68K version
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* EXTERNALS
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _bdosinit
|
||||
.global _main
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* GLOBALS
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global ccp ; main entry point
|
||||
.global _autost
|
||||
.global _usercmd
|
||||
.global _submit
|
||||
.global _morecmds
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* JUMP VECTOR
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
ccp: jr ccpstart ; start ccp with possible
|
||||
; initial command
|
||||
jp ccpclear ; clear autostart flag
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* DATA
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__data: .sect
|
||||
|
||||
copy: .byte " COPYRIGHT (C) 1982, Digital Research "
|
||||
|
||||
_autost: ; autostart command flag
|
||||
.byte 0
|
||||
sysinit: ; set if system initialized
|
||||
.byte 0
|
||||
_submit:
|
||||
.byte 0
|
||||
_morecmds:
|
||||
.byte 0
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_usercmd: ; user command buffer
|
||||
.block 130
|
||||
stackp: ; saved stack pointer
|
||||
.block 2
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* PROGRAM INTERFACE
|
||||
;*
|
||||
;* ccpclear -- clear autostart flag
|
||||
;* ccpstart -- normal entry from boot
|
||||
;* jumped to with valid stack ptr.
|
||||
;* ccploop -- main loop (internal)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
ccpclear:
|
||||
clrb _autost ; clear the autostart flag
|
||||
|
||||
ccpstart:
|
||||
ld stackp,r15 ; save stack pointer
|
||||
tsetb sysinit ; system initialized?
|
||||
jr mi ccploop ; yes
|
||||
; no: init flag now set
|
||||
call _bdosinit ; init bdos
|
||||
|
||||
ccploop:
|
||||
ld r15,stackp ; reset stack pointer
|
||||
call _main ; call the CCP
|
||||
jr ccploop ; loop forever
|
||||
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/************************************************************************
|
||||
* *
|
||||
* CP/M-8000 CCP Program Loader (__LOAD) *
|
||||
* *
|
||||
* Copyright (c) 1982 Zilog Incorporated *
|
||||
* *
|
||||
* This function arranges for the BDOS program loader to be *
|
||||
* invoked in a suitable environment. Suitable means that it *
|
||||
* fills in whatever is expected in the LPB, gets the rest back *
|
||||
* from the BDOS, and then completes the basepage and resets the *
|
||||
* dma buffer. *
|
||||
* *
|
||||
* The loading of segmented programs is not currently supported *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard declarations for BDOS, BIOS */
|
||||
|
||||
#include "bdosdef.h" /* BDOS type and structure declarations */
|
||||
|
||||
#include "biosdef.h" /* Declarations of BIOS functions */
|
||||
|
||||
#include "basepage.h" /* Base page structure */
|
||||
|
||||
#define SEP_ID 0x4000 /* Separate I/D flag */
|
||||
#define SEG 0x2000 /* Segmented load module */
|
||||
|
||||
#define NREGIONS 2 /* Number of MRT regions */
|
||||
|
||||
/* Return values: indexes into msgs (included here for documentation */
|
||||
/* purposes - only GOOD is used in this module */
|
||||
|
||||
#define GOOD 0 /* good return value */
|
||||
#define BADHDR 1 /* bad header */
|
||||
#define NOMEM 2 /* not enough memory */
|
||||
#define READERR 3 /* read error */
|
||||
|
||||
#define WARMBOOT 0 /* Warm reboot BDOS call */
|
||||
#define PRNTSTR 9 /* Print String BDOS call */
|
||||
#define SETDMA 26 /* Set DMA Address BDOS call */
|
||||
#define PGLOAD 59 /* Program Load BDOS call */
|
||||
|
||||
#define MYDATA 0 /* Argument for map_adr */
|
||||
#define TPADATA 4 /* Argument for map_adr */
|
||||
#define TPAPROG 5 /* Argument for map_adr */
|
||||
/* Get actual code segment (as opposed */
|
||||
/* to segment where it can be accessed*/
|
||||
/* as data) */
|
||||
#define TRUE_TPAPROG (TPAPROG | 0x100)
|
||||
|
||||
#define BGETMRT 18 /* Number of the BIOS call */
|
||||
|
||||
extern char cmdfcb[]; /* the FCB for everything */
|
||||
extern char *tail; /* where the command tail is */
|
||||
|
||||
extern UWORD bdos(); /* To do I/O into myself */
|
||||
extern XADDR bios(); /* To get MRT pointer */
|
||||
extern VOID fill_fcb(); /* Parse filename into fcb */
|
||||
extern VOID xfer(); /* Transfer control to user program */
|
||||
|
||||
struct lpb {
|
||||
XADDR fcbaddr; /* Address of fcb of opened file */
|
||||
XADDR pgldaddr; /* Low address of prog load area */
|
||||
XADDR pgtop; /* High address of prog load area, +1 */
|
||||
XADDR bpaddr; /* Address of basepage; return value */
|
||||
XADDR stackptr; /* Stack ptr of user; return value */
|
||||
short flags; /* Loader control flags; return value */
|
||||
} LPB;
|
||||
|
||||
struct m_rt { /* The Memory Region Table */
|
||||
int entries;
|
||||
struct {
|
||||
XADDR m_low;
|
||||
XADDR m_len;
|
||||
} m_reg[NREGIONS];
|
||||
};
|
||||
|
||||
struct ustack /* User's initial stack (nonsegmented) */
|
||||
{
|
||||
short two; /* "Return address" (actually a call to */
|
||||
/* BDOS warm boot in runtime startup) */
|
||||
short bpgaddr;/* Input parameter: pointer to basepage */
|
||||
} stack =
|
||||
{
|
||||
0x0002 /* bpgaddr initialized at runtime */
|
||||
};
|
||||
|
||||
struct sstack /* User's initial stack (segmented) */
|
||||
{
|
||||
XADDR stwo; /* "Return address" (actually a call to */
|
||||
/* BDOS warm boot in runtime startup) */
|
||||
XADDR sbpgadr;/* Input parameter: pointer to basepage */
|
||||
} sstack;
|
||||
|
||||
|
||||
/* Error messages for bad loads */
|
||||
|
||||
static char *msgs[] =
|
||||
{
|
||||
"",
|
||||
"File is not executable$",
|
||||
"Insufficient memory$",
|
||||
"Read error on program load$",
|
||||
"Program Load Error$"
|
||||
};
|
||||
|
||||
struct context /* Startup context for user's program */
|
||||
{
|
||||
short regs[16];
|
||||
short ignore;
|
||||
short FCW;
|
||||
XADDR PC;
|
||||
} context =
|
||||
|
||||
{ /* Regs 0-14 cleared, 15 set up below */
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
0, /* Ignore: value is zero */
|
||||
0x1800 /* FCW: nonsegmented normal, VI, NVI set*/
|
||||
}; /* PC initialized below */
|
||||
|
||||
|
||||
/********************************/
|
||||
/* */
|
||||
/* _ _ L O A D */
|
||||
/* */
|
||||
/********************************/
|
||||
|
||||
|
||||
VOID /* Load a program from */
|
||||
__LOAD() /* info in cmdfcb */
|
||||
{
|
||||
register short k;
|
||||
struct m_rt *mpr;
|
||||
register XADDR physaddr;
|
||||
BYTE tlen; /* length of cmd tail */
|
||||
register char *tp;
|
||||
|
||||
mpr = (struct m_rt *) bios(BGETMRT);
|
||||
|
||||
/* Set up the Load Parameter Block */
|
||||
/* Strictly speaking we should look at magic number to find out */
|
||||
/* which segment(s) the program needs. */
|
||||
|
||||
LPB.pgldaddr = mpr->m_reg[0].m_low;
|
||||
LPB.pgtop = mpr->m_reg[0].m_len;
|
||||
LPB.fcbaddr = map_adr((XADDR) cmdfcb, MYDATA);
|
||||
|
||||
/* Try loading the program. Print message and reboot if load fails */
|
||||
|
||||
if ((k = bdos(PGLOAD, map_adr((XADDR) &LPB, MYDATA))) != GOOD)
|
||||
{
|
||||
bdos(PRNTSTR, map_adr((XADDR) msgs[min(4, k)], MYDATA));
|
||||
bdos(WARMBOOT, 0L);
|
||||
}
|
||||
|
||||
/* Move command tail to basepage buffer; reset DMA address to that buffer. */
|
||||
/* Due to difficulty of adding structure member offset to something */
|
||||
/* which is not a structure pointer, we use a kludge to get physical */
|
||||
/* DMA buffer address: buffer is at last thing on basepage and has a */
|
||||
/* length of one sector. */
|
||||
|
||||
/* Compute length of tail, since CCP does not supply it */
|
||||
|
||||
for (tlen=0, tp=tail; *tp++ != NULL; tlen++) ;
|
||||
|
||||
/* Next expression written in strange way to overcome compiler bug */
|
||||
|
||||
physaddr = LPB.bpaddr - (SECLEN - sizeof (struct b_page));
|
||||
bdos(SETDMA, physaddr);
|
||||
cpy_out(&tlen, physaddr, 1L); /* tail length */
|
||||
cpy_out(tail, physaddr+1, (long) SECLEN-1); /* and cmd tail */
|
||||
|
||||
/* Fill base page fcb's */
|
||||
|
||||
fill_fcb(1, cmdfcb);
|
||||
physaddr -= sizeof (struct fcb); /* Another kludge */
|
||||
cpy_out(cmdfcb, physaddr, sizeof (struct fcb));
|
||||
|
||||
fill_fcb(2, cmdfcb);
|
||||
physaddr -= sizeof (struct fcb); /* Yet a third kludge */
|
||||
cpy_out(cmdfcb, physaddr, sizeof(struct fcb));
|
||||
|
||||
/* Now build a user stack which looks like:
|
||||
* ----------------- ^ ^
|
||||
* word/long | Base page addr| ^ High address ^
|
||||
* ----------------- ^ ^
|
||||
* word/long | 2 | <-- Stack pointer points here
|
||||
* -----------------
|
||||
*/
|
||||
if (LPB.flags & SEG) { /* Segmented */
|
||||
sstack.sbpgadr = LPB.bpaddr;
|
||||
sstack.stwo = LPB.pgldaddr + 2;
|
||||
cpy_out(&sstack, LPB.bpaddr - sizeof sstack, sizeof sstack);
|
||||
} else { /* Nonsegmented */
|
||||
stack.bpgaddr = (short) LPB.bpaddr;
|
||||
cpy_out(&stack, LPB.bpaddr - sizeof stack, sizeof stack);
|
||||
}
|
||||
|
||||
/* Finally, ready to transfer control. Must complete context first. */
|
||||
|
||||
if (LPB.flags & SEG) { /* Segmented */
|
||||
context.regs[14] = (short)(LPB.stackptr >> 16);
|
||||
context.regs[15] = (short)LPB.stackptr;
|
||||
context.PC = LPB.pgldaddr;
|
||||
context.FCW= 0x9800;
|
||||
} else { /* Nonsegmented!*/
|
||||
context.regs[15] = (short) LPB.stackptr;
|
||||
context.PC = map_adr(LPB.pgldaddr, TRUE_TPAPROG);
|
||||
context.FCW= 0x1800;
|
||||
}
|
||||
xfer(map_adr((XADDR) &context, MYDATA)); /* Go for it! */
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/********************************************************
|
||||
* *
|
||||
* P-CP/M header file *
|
||||
* Copyright (c) 1982 by Digital Research, Inc. *
|
||||
* Structure definitions for doing I/O in packets *
|
||||
* *
|
||||
* Modified for data in other address space *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
/* May use this information structure instead of disk parameter header and
|
||||
disk parameter block in future, but for now it's unused
|
||||
struct dskinfo
|
||||
{
|
||||
UBYTE *dbuffp;
|
||||
UBYTE *csv;
|
||||
UBYTE *alv;
|
||||
UBYTE blksize;
|
||||
UBYTE didummy;
|
||||
UWORD dskmax;
|
||||
UWORD dirmax;
|
||||
UWORD chksize;
|
||||
};
|
||||
*/
|
||||
|
||||
struct iopb
|
||||
{
|
||||
UBYTE iofcn; /* function number, see defines below */
|
||||
UBYTE ioflags; /* used for login flag and write flag */
|
||||
UBYTE devtype; /* device type, see defines below */
|
||||
/* currently unused */
|
||||
UBYTE devnum; /* device number, or, devtype and devnum
|
||||
taken together form int device number */
|
||||
LONG devadr; /* item nmbr on device to start xfer at */
|
||||
/* note -- item is sector for disks, byte for char devs */
|
||||
UWORD xferlen; /* number items to transfer */
|
||||
XADDR xferadr; /* memory address to xfer to/from */
|
||||
struct dph *infop; /* pointer to disk parameter header */
|
||||
/* return parm for fcn 0, input for rest */
|
||||
};
|
||||
|
||||
|
||||
/* Definitions for iofcn, the function number */
|
||||
#define sel_info 0 /* select and return info on device */
|
||||
#define read 1
|
||||
#define write 2
|
||||
#define flush 3
|
||||
#define status 4 /* not currently used */
|
||||
|
||||
|
||||
/* Definitions for devtype, the device type */
|
||||
/* This field not currently used */
|
||||
#define console 0
|
||||
#define printer 1
|
||||
#define disk 2
|
||||
#define memory 3 /* gets TPA boundaries */
|
||||
#define redir 4 /* read/write IOByte */
|
||||
#define exc_vec 5 /* set exception vector */
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* C P / M C H E A D E R F I L E
|
||||
* -----------------------------------
|
||||
* Copyright 1982 by Digital Research Inc. All rights reserved.
|
||||
*
|
||||
* This is an include file for assisting the user to write portable
|
||||
* programs for C.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define ALCYON 1 /* NOT using Alcyon compiler*/
|
||||
/* but Zilog has similar bug*/
|
||||
|
||||
/*
|
||||
* Standard type definitions
|
||||
*/
|
||||
/***************************/
|
||||
#define BYTE char /* Signed byte */
|
||||
#define BOOLEAN char /* 2 valued (true/false) */
|
||||
#define WORD short /* Signed word (16 bits) */
|
||||
#define UWORD unsigned int /* unsigned word */
|
||||
#define LONG long /* signed long (32 bits) */
|
||||
#define ULONG unsigned long /* Unsigned long */
|
||||
#define REG register /* register variable */
|
||||
#define LOCAL auto /* Local var on 68000 */
|
||||
#define EXTERN extern /* External variable */
|
||||
#define MLOCAL static /* Local to module */
|
||||
#define GLOBAL /**/ /* Global variable */
|
||||
#define VOID /**/ /* Void function return */
|
||||
#define XADDR long /* Extended (SEG) address */
|
||||
/***************************/
|
||||
#ifdef ALCYON
|
||||
#define UBYTE char
|
||||
#define UBWORD(a) ((UWORD)a & 0xff)
|
||||
/* Unsigned byte to word cast */
|
||||
#else
|
||||
#define UBYTE unsigned char /* Unsigned byte */
|
||||
#define UBWORD(a) (UWORD)a
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Miscellaneous Definitions: */
|
||||
/****************************************************************************/
|
||||
|
||||
#define FAILURE (-1) /* Function failure return val */
|
||||
#define SUCCESS (0) /* Function success return val */
|
||||
#define YES 1 /* "TRUE" */
|
||||
#define NO 0 /* "FALSE" */
|
||||
#define FOREVER for(;;) /* Infinite loop declaration */
|
||||
#define NULL (BYTE *)0 /* Null pointer value */
|
||||
#define XNULL 0L /* Null XADDR */
|
||||
#define EOF (-1) /* EOF Value */
|
||||
#define TRUE (1)
|
||||
/* Function TRUE value */
|
||||
#define FALSE (0)
|
||||
/* Function FALSE value */
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* M A C R O S */
|
||||
/* ----------- */
|
||||
/* */
|
||||
/* Define some stuff as macros .... */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#define abs(x) ((x) < 0 ? -(xIq
|
||||
This directory contains the source, object, and archived object ("libcpm.a")
|
||||
of the Non-segmented version of the Z8000 C runtime library. The segmented
|
||||
1075
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/ddt/dbg.c
Normal file
1075
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/ddt/dbg.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,114 @@
|
||||
;
|
||||
; Z8000 CPM kernal to DDT debugger interface
|
||||
;
|
||||
;
|
||||
; Oct. 20, 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 Avenue, Campbell, Ca. 95008
|
||||
; tel: (408) 370-8000 twx: 910-338-7621
|
||||
;
|
||||
; Copyright 1982 Zilog Corporation, all rights reserved.
|
||||
;
|
||||
; date listed: ______ ____/____/____ ____:____ ____
|
||||
;
|
||||
; project name: #916ss - Zilog cross software development
|
||||
;
|
||||
; program name: Breakpoint to debugger interface.
|
||||
;
|
||||
; programmer: Thorn Smith x 8317
|
||||
;
|
||||
; environment: Zilog S8000 1 v1.7
|
||||
;
|
||||
; language: Zilog PLZ-ASM, Zeus C
|
||||
;
|
||||
; approvals-mgr: ________________________________________, Zilog
|
||||
;
|
||||
; approvals-q.a: ________________________________________, Zilog
|
||||
;
|
||||
; approvals-d.v: ________________________________________, Zilog
|
||||
;
|
||||
|
||||
SUPV .equ 62 ; supervisor state BDOS call
|
||||
MEM_SC .equ 1 ; memory call
|
||||
BDOS_SC .equ 2 ; system call number 2
|
||||
|
||||
.global _frame
|
||||
.global _dbg
|
||||
|
||||
.global _getsp
|
||||
.global _bkptrap
|
||||
|
||||
; *************************************************
|
||||
; * *
|
||||
; * S T A R T O F C O D E *
|
||||
; * *
|
||||
; *************************************************
|
||||
|
||||
__text .sect
|
||||
|
||||
;
|
||||
;******** get the sp (rr14)
|
||||
;
|
||||
|
||||
_getsp:
|
||||
ldl rr6,rr14
|
||||
ret
|
||||
|
||||
;
|
||||
;******** unimplemented instruction trap interface to debugger
|
||||
;
|
||||
; upon entry, rr14 points to a frame structure as follows:
|
||||
; trap return address, r0-r15, 0x7f00, FCW, pcseg, pcoff
|
||||
;
|
||||
|
||||
_bkptrap:
|
||||
ldl rr8,rr14 ; rr8= frame pointer
|
||||
inc r9,#4 ; bump the long return address to this rtn
|
||||
|
||||
ldctl r0,FCW
|
||||
and r0,#03FFFh ; unset nonseg and system mode
|
||||
or r0,#01800h ; enable vi, nvi
|
||||
ldctl FCW,r0 ; BOOM! NOW IN NORMAL NONSEG MODE W/NORMAL SP !
|
||||
|
||||
; rr6= source (adjusted stack)
|
||||
ldl rr6,#_frame ; rr4= dest. temporary address in this segment
|
||||
ld r5,#0 ; 0= caller data space
|
||||
ldl rr2,#0 ;
|
||||
sc #MEM_SC ; map adr, rr6= physical address
|
||||
|
||||
ldl rr2,#040 ; rr2= length
|
||||
ldl rr4,rr6 ; rr4= dest= physical address of #_frame
|
||||
ldl rr6,rr8 ; rr6= source= frame on stack
|
||||
pushl @r15,rr4 ; preserve physical address of #_frame
|
||||
sc #MEM_SC ; copy memory
|
||||
|
||||
push @r15,#_frame ; state
|
||||
call _dbg ; call the debugger with the frame as an arg.
|
||||
inc r15,#2 ;
|
||||
|
||||
popl rr6,@r15 ; rr6= source= physical address of #_frame
|
||||
ldl rr4,rr8 ; rr4= dest= top of stack on frame
|
||||
ldl rr2,#040 ; rr2= length
|
||||
sc #MEM_SC ; copy memory
|
||||
|
||||
ld r5,#SUPV ; SUPV= request to switch to system mode.
|
||||
sc #BDOS_SC ; BOOM! NOW IN SYSTEM SEG MODE W/SYSTEM SP !
|
||||
|
||||
ret ; presumably, this does the xfer.
|
||||
|
||||
; *************************************************
|
||||
; * *
|
||||
; * S T A R T O F R A M *
|
||||
; * *
|
||||
; *************************************************
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "env.h"
|
||||
#include "u.h"
|
||||
|
||||
int memode;
|
||||
int mfile; /* memory file */
|
||||
BYTE memory[MEMSIZE];
|
||||
|
||||
struct symbol regtbl[] ={
|
||||
0, 0, "?",
|
||||
RINT, 0x00, "r0",
|
||||
RINT, 0x02, "r1",
|
||||
RINT, 0x04, "r2",
|
||||
RINT, 0x06, "r3",
|
||||
RINT, 0x08, "r4",
|
||||
RINT, 0x0A, "r5",
|
||||
RINT, 0x0C, "r6",
|
||||
RINT+RCR, 0x0E, "r7",
|
||||
|
||||
RINT, 0x10, "r8",
|
||||
RINT, 0x12, "r9",
|
||||
RINT, 0x14, "ra",
|
||||
RINT, 0x16, "rb",
|
||||
RINT, 0x18, "rc",
|
||||
RINT, 0x1A, "rd",
|
||||
RINT, 0x1C, "re",
|
||||
RINT+RCR, 0x1E, "rf",
|
||||
|
||||
RCHR, 0x00, "rh0", RCHR, 0x01, "rl0",
|
||||
RCHR, 0x02, "rh1", RCHR, 0x03, "rl1",
|
||||
RCHR, 0x04, "rh2", RCHR, 0x05, "rl2",
|
||||
RCHR, 0x06, "rh3", RCHR, 0x07, "rl3",
|
||||
RCHR, 0x08, "rh4", RCHR, 0x09, "rl4",
|
||||
RCHR, 0x0a, "rh5", RCHR, 0x0b, "rl5",
|
||||
RCHR, 0x0c, "rh6", RCHR, 0x0d, "rl6",
|
||||
RCHR, 0x0e, "rh7", RCHR, 0x0f, "rl7",
|
||||
|
||||
RCHR, 0x10, "rh8", RCHR, 0x11, "rl8",
|
||||
RCHR, 0x12, "rh9", RCHR, 0x13, "rl9",
|
||||
RCHR, 0x14, "rha", RCHR, 0x15, "rla",
|
||||
RCHR, 0x16, "rhb", RCHR, 0x17, "rlb",
|
||||
RCHR, 0x18, "rhc", RCHR, 0x19, "rlc",
|
||||
RCHR, 0x1a, "rhd", RCHR, 0x1b, "rld",
|
||||
RCHR, 0x1c, "rhe", RCHR, 0x1d, "rle",
|
||||
RCHR, 0x1e, "rhf", RCHR, 0x1f, "rlf",
|
||||
|
||||
RINT, 0x20, "id",
|
||||
RINT, 0x22, "$$",
|
||||
#ifdef Z8001
|
||||
RINT, 0x24, "pcs",
|
||||
RINT, 0x26, "pc",
|
||||
#else
|
||||
RINT, 0x24, "pc",
|
||||
#endif
|
||||
0, 0, "",
|
||||
};
|
||||
|
||||
/*
|
||||
******** the FCW bits
|
||||
*/
|
||||
|
||||
struct bitable pflags[] ={
|
||||
'f', 0x8000,
|
||||
'x', 0x4000,
|
||||
'e', 0x2000,
|
||||
'v', 0x1000,
|
||||
'n', 0x0800,
|
||||
'a', 0x0400,
|
||||
'9', 0x0200,
|
||||
'8', 0x0100,
|
||||
'c', 0x0080,
|
||||
'z', 0x0040,
|
||||
's', 0x0020,
|
||||
'p', 0x0010,
|
||||
'd', 0x0008,
|
||||
'h', 0x0004,
|
||||
'1', 0x0002,
|
||||
'0', 0x0001,
|
||||
'\0', 0x0000,
|
||||
};
|
||||
|
||||
/*
|
||||
**
|
||||
|
||||
** *************************************************
|
||||
** * *
|
||||
** * S U B R O U T I N E S F O R Z 8 K *
|
||||
** * *
|
||||
** *************************************************
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
******** initializer
|
||||
*/
|
||||
|
||||
dbginit (state)
|
||||
union pstate *state;
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
******** Single stepper
|
||||
*/
|
||||
|
||||
sstep (state)
|
||||
union pstate *state;
|
||||
{
|
||||
int diopn;
|
||||
diopn= deasm((POINTER)state->lregs.pc,oline);
|
||||
printf ("%s\n",oline);
|
||||
state->lregs.pc += getnext(diopn);
|
||||
return(diopn);
|
||||
}
|
||||
|
||||
/*
|
||||
******** breakpoint routines
|
||||
*/
|
||||
|
||||
tstrap (addr)
|
||||
POINTER addr;
|
||||
{
|
||||
if (ldint(addr) == BKPT) return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
setrap (addr,bkpt)
|
||||
POINTER addr;
|
||||
WORD bkpt;
|
||||
{
|
||||
WORD oldop;
|
||||
oldop= ldint(addr);
|
||||
stint (addr,bkpt);
|
||||
return (oldop & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
******** Memory access routines
|
||||
*/
|
||||
|
||||
WORD ldint (addr)
|
||||
POINTER addr;
|
||||
{
|
||||
return (((ldchr(addr) << 8) & 0xFF00) | (ldchr(addr+1) & 0xFF));
|
||||
}
|
||||
|
||||
stint (addr,data)
|
||||
POINTER addr;
|
||||
WORD data;
|
||||
{
|
||||
stchr (addr,(data >> 8) & 0xFF);
|
||||
stchr (addr+1,data & 0xFF);
|
||||
}
|
||||
|
||||
BYTE ldstemp; /* load & store temporary varible */
|
||||
|
||||
#ifdef CPM
|
||||
|
||||
BYTE ldchr (addr)
|
||||
POINTER addr;
|
||||
{
|
||||
mem_cpy (addr,map_adr((LONG)&ldstemp & 0xFFFFL,0),1L);
|
||||
return (ldstemp & 0xFF);
|
||||
}
|
||||
|
||||
stchr (addr,data)
|
||||
POINTER addr;
|
||||
BYTE data;
|
||||
{
|
||||
ldstemp= data;
|
||||
mem_cpy (map_adr((LONG)&ldstemp & 0xFFFFL,0),addr,1L);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BYTE ldchr (addr)
|
||||
POINTER addr;
|
||||
{
|
||||
return (*(BYTE *)addr);
|
||||
}
|
||||
|
||||
stchr (addr,data)
|
||||
POINTER addr;
|
||||
BYTE data;
|
||||
{
|
||||
*(BYTE *)addr= data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
******** IO access routines
|
||||
*/
|
||||
|
||||
pichr (addr)
|
||||
POINTER addr;
|
||||
{
|
||||
return (*(BYTE *)addr);
|
||||
}
|
||||
|
||||
pochr (addr,data)
|
||||
POINTER addr;
|
||||
int data;
|
||||
{
|
||||
*(BYTE *)addr= data;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
******** Environmental varibles for z8000dm
|
||||
*/
|
||||
|
||||
#define Z8001 1
|
||||
|
||||
#ifdef CPM
|
||||
|
||||
#include "portab.h"
|
||||
#include "cpm.h"
|
||||
#include "stdio.h"
|
||||
#include "bdos.h"
|
||||
|
||||
#define NREGIONS 2 /* number of regions in the MRT */
|
||||
#define BGETMRT 18 /* SC to get MRT */
|
||||
#define PGLOAD 59 /* BDOS call to load program */
|
||||
#define SECLEN 128 /* size of a sector */
|
||||
|
||||
struct b_page
|
||||
{
|
||||
XADDR ltpa; /* Low TPA address */
|
||||
XADDR htpa; /* High TPA address */
|
||||
XADDR lcode; /* Start address of code seg*/
|
||||
long codelen; /* Code segment length */
|
||||
XADDR ldata; /* Start address of data seg*/
|
||||
long datalen; /* Data segment length */
|
||||
XADDR lbss; /* Start address of bss seg */
|
||||
long bsslen; /* Bss segment length */
|
||||
long freelen; /* Free segment length */
|
||||
char resvd1[20]; /* Reserved area */
|
||||
struct fcbtab fcb2; /* Second basepage FCB */
|
||||
struct fcbtab fcb1; /* First basepage FCB */
|
||||
char buff[128]; /* Default DMA buffer, */
|
||||
/* command line tail */
|
||||
};
|
||||
|
||||
|
||||
struct lpb {
|
||||
XADDR fcbaddr; /* Address of fcb of opened file */
|
||||
XADDR pgldaddr; /* Low address of prog load area */
|
||||
XADDR pgtop; /* High address of prog load area, +1 */
|
||||
XADDR bpaddr; /* Address of basepage; return value */
|
||||
XADDR stackptr; /* Stack ptr of user; return value */
|
||||
short lcflags; /* Loader control flags; return value */
|
||||
} LPB;
|
||||
|
||||
struct m_rt { /* The Memory Region Table */
|
||||
int entries;
|
||||
struct {
|
||||
XADDR m_low;
|
||||
XADDR m_len;
|
||||
} m_reg[NREGIONS];
|
||||
};
|
||||
|
||||
struct ustack { /* User's initial stack (nonsegmented) */
|
||||
short two; /* "Return address" (actually a call to */
|
||||
/* BDOS warm boot in runtime startup) */
|
||||
short bpgaddr; /* Input parameter: pointer to basepage */
|
||||
};
|
||||
|
||||
extern long map_adr();
|
||||
|
||||
#else
|
||||
|
||||
#define BYTE char
|
||||
#define WORD short
|
||||
#define LONG long
|
||||
|
||||
#endif
|
||||
|
||||
#define POINTER long
|
||||
#define OPCODE short
|
||||
#define BKPT 0x7F00
|
||||
|
||||
#define COLS 256
|
||||
#define SWIDTH 64
|
||||
|
||||
/* swap macros */
|
||||
#define MSWP(a) (a)
|
||||
#define PSWP(a) (a)
|
||||
|
||||
/* globals from env.c */
|
||||
#define MEMSIZE 0x100
|
||||
extern BYTE memory[];
|
||||
extern BYTE ldchr();
|
||||
extern WORD ldint();
|
||||
extern int memode;
|
||||
|
||||
/* globals from dbg.c */
|
||||
extern int tractr;
|
||||
extern POINTER temppc;
|
||||
|
||||
/*
|
||||
******** Z8000 Processor state frame
|
||||
*/
|
||||
|
||||
union pstate {
|
||||
struct {
|
||||
WORD r0; /* 00 */
|
||||
WORD r1; /* 02 */
|
||||
WORD r2; /* 04 */
|
||||
WORD r3; /* 06 */
|
||||
WORD r4; /* 08 */
|
||||
WORD r5; /* 0a */
|
||||
WORD r6; /* 0c */
|
||||
WORD r7; /* 0e */
|
||||
WORD r8; /* 10 */
|
||||
WORD r9; /* 12 */
|
||||
WORD ra; /* 14 */
|
||||
WORD rb; /* 16 */
|
||||
WORD rc; /* 18 */
|
||||
WORD rd; /* 1a */
|
||||
WORD re; /* 1c */
|
||||
WORD rf; /* 1e */
|
||||
WORD id; /* 20 */
|
||||
WORD fcw; /* 22 */
|
||||
#ifdef Z8001
|
||||
WORD pcs; /* 24 */
|
||||
#endif
|
||||
WORD pc; /* 24-26 */
|
||||
} lregs;
|
||||
struct {
|
||||
BYTE rh0; BYTE rl0;
|
||||
BYTE rh1; BYTE rl1;
|
||||
BYTE rh2; BYTE rl2;
|
||||
BYTE rh3; BYTE rl3;
|
||||
BYTE rh4; BYTE rl4;
|
||||
BYTE rh5; BYTE rl5;
|
||||
BYTE rh6; BYTE rl6;
|
||||
BYTE rh7; BYTE rl7;
|
||||
BYTE rh8; BYTE rl8;
|
||||
BYTE rh9; BYTE rl9;
|
||||
BYTE rha; BYTE rla;
|
||||
BYTE rhb; BYTE rlb;
|
||||
BYTE rhc; BYTE rlc;
|
||||
BYTE rhd; BYTE rld;
|
||||
BYTE rhe; BYTE rle;
|
||||
BYTE rhf; BYTE rlf;
|
||||
BYTE id1; BYTE id2;
|
||||
BYTE f; BYTE f1;
|
||||
} sregs;
|
||||
};
|
||||
1006
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/ddt/mad.c
Normal file
1006
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/ddt/mad.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,145 @@
|
||||
|
||||
/*
|
||||
******** Z800 opcode table (from z800.c)
|
||||
*/
|
||||
|
||||
#define OFFSET 0x000F
|
||||
|
||||
/* standard data types */
|
||||
#define B1 0x0100 /* bit */
|
||||
#define B2 0x0200 /* nib */
|
||||
#define B3 0x0300 /* oct */
|
||||
#define B4 0x0400 /* nibble */
|
||||
#define B5 0x0500 /* 5-bit (used for bitL) */
|
||||
|
||||
#define X1 0x1100 /* byte */
|
||||
#define X2 0x1200 /* word */
|
||||
#define X3 0x1300 /* triple-byte? */
|
||||
#define X4 0x1400 /* long */
|
||||
#define X5 0x1500 /* quad */
|
||||
#define X6 0x1600 /* float */
|
||||
#define X7 0x1700 /* double */
|
||||
|
||||
#define AA 0x2100 /* address */
|
||||
#define AL 0x2200 /* long address */
|
||||
|
||||
#define RB 0x3100 /* byte register */
|
||||
#define RR 0x3200 /* register */
|
||||
#define RL 0x3300 /* long register */
|
||||
#define RQ 0x3400 /* quad register */
|
||||
|
||||
#define II 0x4100 /* indirect register either long or short, but not 0 */
|
||||
#define I0 0x4200 /* indirect register either long or short, incl 0 */
|
||||
#define IR 0x4300 /* indirect register, but not r0 */
|
||||
#define IS 0x4400 /* indirect register including r0 */
|
||||
#define IL 0x4500 /* indirect long register, but not rr0 */
|
||||
#define L0 0x4600 /* indirect long register including rr0 */
|
||||
#define PP 0x4800 /* parenthesized register, either long or short, not 0*/
|
||||
#define PR 0x4900 /* parenthesized register, but not (R0) */
|
||||
#define P0 0x4A00 /* parenthesized register, but not rr0 */
|
||||
#define PL 0x4B00 /* parenthesized long register */
|
||||
#define BB 0x4C00 /* base register (an RR or RL but not R0 or RR0) */
|
||||
#define BR 0x4D00 /* base register (an RR but not RR), not R0 */
|
||||
#define BL 0x4E00 /* long base register (an RL but not RR), not RR0 */
|
||||
|
||||
#define CC 0x5100 /* condition code */
|
||||
#define CF 0x5200 /* conditional flag for comflg,resflg,setflg */
|
||||
|
||||
#define D1 0x6100 /* 7-bit displacement (for djnz,dbjnz) */
|
||||
#define D2 0x6200 /* 8-bit displacement (for jr) */
|
||||
#define D3 0x6300 /* 12-bit displacement (for calr) */
|
||||
#define D4 0x6400 /* 16-bit displacement (for ld BA) */
|
||||
#define D5 0x6500 /* 16-bit displacement (for ldr) */
|
||||
|
||||
#define SR 0x7100 /* special (control) register */
|
||||
#define UR 0x7200 /* user special (control) register */
|
||||
#define VI 0x7400 /* interrupts (vi,nvi) */
|
||||
#define NI 0x7500 /* interrupts (vi,nvi) */
|
||||
#define BN 0x7600 /* 1,2 bit field for rl,rlc,rr,rrc */
|
||||
#define ID 0x7700 /* increment and decrement fields (to be bumped) */
|
||||
#define P1 0x7800 /* +b field for sla,sll */
|
||||
#define P2 0x7900 /* +b field for slab,sllb */
|
||||
#define P3 0x7A00 /* +b field for slal,slll */
|
||||
#define N1 0x7B00 /* -b field for sra,srl */
|
||||
#define N2 0x7C00 /* -b field for srab,srlb */
|
||||
#define N3 0x7D00 /* -b field for sral,srll */
|
||||
#define SL 0x7E00 /* long special (control) register */
|
||||
|
||||
/* bizarre data types */
|
||||
#define XRST 0x8100
|
||||
#define XBOF 0x8200
|
||||
#define XBWD 0x8300
|
||||
|
||||
/* register data types */
|
||||
#define RNS1 0x8400 /* normal single reg(b, c, d, e, h, l, m ) */
|
||||
#define RNS2 0x8500 /* normal single reg(b, c, d, e, h, l, m ) */
|
||||
#define XPSR 0x8600 /* prime single reg(b',c',d',e',h',l',m') */
|
||||
#define XIXY 0x8700 /* XY single reg(ixh, ixl, iyh, iyl) */
|
||||
#define XISR 0x8800 /* indexed single reg(@(c)) */
|
||||
#define XNDR 0x8900 /* normal double reg(bc, de, hl, pc, sp) */
|
||||
#define XPDR 0x8a00 /* prime double reg(bc',de',hl') */
|
||||
#define XIDR 0x8b00 /* indexed double reg(@(bc,de,hl,sp,ix,iy)) */
|
||||
#define XIRR 0x8c00 /* indexed registr reg(@(hl+ix,hl+iy,ix+iy))*/
|
||||
#define XIII 0x8d00 /* i register */
|
||||
#define XRRR 0x8e00 /* r register */
|
||||
#define XTXR 0x8f00 /* TX register */
|
||||
#define DREG 0xA000
|
||||
#define PSRG 0xA100
|
||||
#define PDRG 0xA200
|
||||
|
||||
#define XOPC 0xA300
|
||||
|
||||
#define EM 0xB000
|
||||
#define BP 0xB100
|
||||
#define BS 0xB200
|
||||
|
||||
struct op {
|
||||
BYTE opc;
|
||||
BYTE opb[4];
|
||||
WORD opa[4];
|
||||
};
|
||||
extern struct op ops[];
|
||||
|
||||
/*
|
||||
******** reserved symbol table (from z800.c)
|
||||
*/
|
||||
|
||||
extern char *opcodes[];
|
||||
extern struct symbol oprands[];
|
||||
/*
|
||||
** struct rsym {
|
||||
** int ltype;
|
||||
** int lvalu;
|
||||
** char *label;
|
||||
** };
|
||||
**
|
||||
** extern struct rsym oprands[];
|
||||
*/
|
||||
|
||||
/*
|
||||
******** globals for assembler / disassembler
|
||||
**
|
||||
** int types[MAXARGS] - array for all of the fields
|
||||
** int fields[MAXARGS] - pointers to start of fields in formatted str2.
|
||||
** long values[MAXARGS] - array of numeric decode
|
||||
**
|
||||
*/
|
||||
|
||||
/* maxargs (including comment field) */
|
||||
#define MAXA 4
|
||||
#define MAXB 4
|
||||
#define MAXF 10
|
||||
|
||||
extern int args,opcode;
|
||||
extern int types[];
|
||||
extern long values[];
|
||||
extern char *fields[];
|
||||
extern char tline[];
|
||||
|
||||
|
||||
extern int opsa,opsb;
|
||||
extern int ttype,fldtype,bitoff,offset,bitnum;
|
||||
extern int ivalue;
|
||||
extern long tvalue;
|
||||
extern int z12,segmode;
|
||||
extern POINTER slide; /* relative pc offset for assembler */
|
||||
@@ -0,0 +1,2 @@
|
||||
This directory contains the source and object files for the Z8000 debugger,
|
||||
ddt, for CP/M.
|
||||
1021
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/ddt/u.c
Normal file
1021
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/ddt/u.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
#define SYMLEN 10
|
||||
#define LASTSYM -1
|
||||
|
||||
#define MDASIZE long
|
||||
#define RQUAD 0x80
|
||||
#define RLONG 0x40
|
||||
#define RINT 0x20
|
||||
#define RCHR 0x10
|
||||
#define RCR 0x08
|
||||
|
||||
#define CODE 1
|
||||
#define DATA 0
|
||||
|
||||
#define CHR(bits8) (bits8 & 0xFF)
|
||||
#define SHT(bitsf) (bitsf & 0xFFFF)
|
||||
|
||||
/*
|
||||
******** IO
|
||||
*/
|
||||
|
||||
char fgetc(), *gets(), *fgets();
|
||||
|
||||
/*
|
||||
******** symbol stuff
|
||||
*/
|
||||
|
||||
#define SYMDEF 0x80
|
||||
#define SYMUDEF 0x40
|
||||
|
||||
struct symbol {
|
||||
int utype;
|
||||
MDASIZE uvalue;
|
||||
char uname[SYMLEN+1];
|
||||
};
|
||||
|
||||
extern struct symbol regtbl[];
|
||||
extern struct symbol symtbl[];
|
||||
|
||||
/*
|
||||
******** bit tables
|
||||
*/
|
||||
|
||||
struct bitable {
|
||||
char bitlabel;
|
||||
WORD bitmask;
|
||||
};
|
||||
extern struct bitable pflags[];
|
||||
|
||||
/*
|
||||
******** debugger flags
|
||||
*/
|
||||
|
||||
#define TTRACE 0x0001
|
||||
#define XTRACE 0x0002
|
||||
#define INDBG 0x0010
|
||||
#define LSTEP 0x0020
|
||||
#define TEMPPC 0x0040
|
||||
#define MUFOM 0x0100
|
||||
|
||||
/*
|
||||
******** misc
|
||||
*/
|
||||
|
||||
extern BYTE tbyte;
|
||||
extern WORD tword;
|
||||
extern LONG tlong;
|
||||
extern POINTER tptr;
|
||||
|
||||
extern int error,errctr;
|
||||
extern int infixflg;
|
||||
extern char *errors[];
|
||||
|
||||
extern char *iscan,*oscan,*tscan;
|
||||
extern char ichksum,ochksum;
|
||||
extern char iline[COLS],oline[COLS]; /* the IO buffers */
|
||||
|
||||
extern WORD bswap();
|
||||
extern MDASIZE infix(),infixer(),numin(),fltin(),adrin(),hexin(),getsym();
|
||||
|
||||
extern char symbuf[SYMLEN+1];
|
||||
|
||||
extern char aflag,bflag,cflag,dflag,eflag,hflag,iflag,jflag,kflag;
|
||||
extern char lflag,mflag,nflag,oflag,pflag,qflag,rflag,sflag,tflag;
|
||||
extern char uflag,vflag,wflag,xflag,yflag,zflag;
|
||||
|
||||
@@ -0,0 +1,812 @@
|
||||
/*
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#include "env.h"
|
||||
#include "u.h"
|
||||
#include "mad.h"
|
||||
|
||||
struct op ops[] ={
|
||||
0002, 0x00,0x00,0x00,0x00, X2+00, 0, 0, 0, /* 0 .word #00123 */
|
||||
0222, 0xb5,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /* 1 adc r3,r2 */
|
||||
0222, 0xb4,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /* 2 adcb rh3,rh2 */
|
||||
0222, 0x81,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /* 3 add r3,r2 */
|
||||
0022, 0x01,0x00,0x00,0x00, RR+14,II+10, 0, 0, /* 3 add r3,@r2 */
|
||||
0024, 0x01,0x00,0x00,0x00, RR+14,X2+20, 0, 0, /* 3 add r3,#04567 */
|
||||
0024, 0x41,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /* 3 add r3,4567(r2) */
|
||||
0024, 0x41,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /* 3 add r3,4567 */
|
||||
0222, 0x80,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /* 4 addb rh3,rh2 */
|
||||
0022, 0x00,0x00,0x00,0x00, RB+14,II+10, 0, 0, /* 4 addb rh3,@r2 */
|
||||
0024, 0x00,0x00,0x00,0x00, RB+14,X1+20, 0, 0, /* 4 addb rh3,#045 */
|
||||
0024, 0x40,0x00,0x00,0x00, RB+14,AA+20,PR+10, 0, /* 4 addb rh3,4567(r2) */
|
||||
0024, 0x40,0x00,0x00,0x00, RB+14,AA+20, 0, 0, /* 4 addb rh3,4567 */
|
||||
0222, 0x96,0x00,0x00,0x00, RL+14,RL+10, 0, 0, /* 5 addl rr2,rr2 */
|
||||
0022, 0x16,0x00,0x00,0x00, RL+14,II+10, 0, 0, /* 5 addl rr2,@r2 */
|
||||
0026, 0x16,0x00,0x00,0x00, RL+14,X4+20, 0, 0, /* 5 addl rr2, #0022b */
|
||||
0024, 0x56,0x00,0x00,0x00, RL+14,AA+20,PR+10, 0, /* 5 addl rr2,4567(r2) */
|
||||
0024, 0x56,0x00,0x00,0x00, RL+14,AA+20, 0, 0, /* 5 addl rr2,4567 */
|
||||
0222, 0x87,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /* 6 and r3,r2 */
|
||||
0022, 0x07,0x00,0x00,0x00, RR+14,II+10, 0, 0, /* 6 and r3,@r2 */
|
||||
0024, 0x07,0x00,0x00,0x00, RR+14,X2+20, 0, 0, /* 6 and r3,#04567 */
|
||||
0024, 0x47,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /* 6 and r3,4567(r2) */
|
||||
0024, 0x47,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /* 6 and r3,4567 */
|
||||
0222, 0x86,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /* 7 andb rh3,rh2 */
|
||||
0022, 0x06,0x00,0x00,0x00, RB+14,II+10, 0, 0, /* 7 andb rh3,@r2 */
|
||||
0024, 0x06,0x00,0x00,0x00, RB+14,X1+20, 0, 0, /* 7 andb rh3,#045 */
|
||||
0024, 0x46,0x00,0x00,0x00, RB+14,AA+20,PR+10, 0, /* 7 andb rh3,4567(r2) */
|
||||
0024, 0x46,0x00,0x00,0x00, RB+14,AA+20, 0, 0, /* 7 andb rh3,4567 */
|
||||
0222, 0xa7,0x00,0x00,0x00, RR+10,B4+14, 0, 0, /* 8 bit r2,#3 */
|
||||
0022, 0x27,0x00,0x00,0x00, II+10,B4+14, 0, 0, /* 8 bit @r2,#3 */
|
||||
0044, 0x27,0x00,0x00,0x00, RR+24,RR+14, 0, 0, /* 8 bit r5,r3 */
|
||||
0024, 0x67,0x00,0x00,0x00, AA+20,PR+10,B4+14, 0, /* 8 bit 4567(r2),#3 */
|
||||
0024, 0x67,0x00,0x00,0x00, AA+20,B4+14, 0, 0, /* 8 bit 4567,#3 */
|
||||
0222, 0xa6,0x00,0x00,0x00, RB+10,B4+14, 0, 0, /* 9 bitb rh2,#3 */
|
||||
0022, 0x26,0x00,0x00,0x00, II+10,B4+14, 0, 0, /* 9 bitb @r2,#3 */
|
||||
0044, 0x26,0x00,0x00,0x00, RB+24,RR+14, 0, 0, /* 9 bitb rh5,r3 */
|
||||
0024, 0x66,0x00,0x00,0x00, AA+20,PR+10,B4+14, 0, /* 9 bitb 4567(r2),#3 */
|
||||
0024, 0x66,0x00,0x00,0x00, AA+20,B4+14, 0, 0, /* 9 bitb 4567,#3 */
|
||||
0222, 0x1f,0x00,0x00,0x00, II+10, 0, 0, 0, /* 10 call @r2 */
|
||||
0024, 0x5f,0x00,0x00,0x00, AA+20,PR+10, 0, 0, /* 10 call 4567(r2) */
|
||||
0024, 0x5f,0x00,0x00,0x00, AA+20, 0, 0, 0, /* 10 call 4567 */
|
||||
0222, 0xd0,0x00,0x00,0x00, D3+04, 0, 0, 0, /* 11 calr 0a0c */
|
||||
0222, 0x8d,0x08,0x00,0x00, RR+10, 0, 0, 0, /* 12 clr r2 */
|
||||
0022, 0x0d,0x08,0x00,0x00, II+10, 0, 0, 0, /* 12 clr @r2 */
|
||||
0024, 0x4d,0x08,0x00,0x00, AA+20,PR+10, 0, 0, /* 12 clr 4567(r2) */
|
||||
0024, 0x4d,0x08,0x00,0x00, AA+20, 0, 0, 0, /* 12 clr 4567 */
|
||||
0222, 0x8c,0x08,0x00,0x00, RB+10, 0, 0, 0, /* 13 clrb rh2 */
|
||||
0022, 0x0c,0x08,0x00,0x00, II+10, 0, 0, 0, /* 13 clrb @r2 */
|
||||
0024, 0x4c,0x08,0x00,0x00, AA+20,PR+10, 0, 0, /* 13 clrb 4567(r2) */
|
||||
0024, 0x4c,0x08,0x00,0x00, AA+20, 0, 0, 0, /* 13 clrb 4567 */
|
||||
0222, 0x8d,0x00,0x00,0x00, RR+10, 0, 0, 0, /* 14 com r2 */
|
||||
0022, 0x0d,0x00,0x00,0x00, II+10, 0, 0, 0, /* 14 com @r2 */
|
||||
0024, 0x4d,0x00,0x00,0x00, AA+20,PR+10, 0, 0, /* 14 com 4567(r2) */
|
||||
0024, 0x4d,0x00,0x00,0x00, AA+20, 0, 0, 0, /* 14 com 4567 */
|
||||
0222, 0x8c,0x00,0x00,0x00, RB+10, 0, 0, 0, /* 15 comb rh2 */
|
||||
0022, 0x0c,0x00,0x00,0x00, II+10, 0, 0, 0, /* 15 comb @r2 */
|
||||
0024, 0x4c,0x00,0x00,0x00, AA+20,PR+10, 0, 0, /* 15 comb 4567(r2) */
|
||||
0024, 0x4c,0x00,0x00,0x00, AA+20, 0, 0, 0, /* 15 comb 4567 */
|
||||
0222, 0x8d,0x05,0x00,0x00, CF+10,CF+10,CF+10,CF+10, /* 16 comflg le */
|
||||
0222, 0x8b,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /* 17 cp r3,r2 */
|
||||
0022, 0x0b,0x00,0x00,0x00, RR+14,II+10, 0, 0, /* 17 cp r3,@r2 */
|
||||
0024, 0x0b,0x00,0x00,0x00, RR+14,X2+20, 0, 0, /* 17 cp r3,#04567 */
|
||||
0024, 0x4b,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /* 17 cp r3,4567(r2) */
|
||||
0024, 0x4b,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /* 17 cp r3,4567 */
|
||||
0024, 0x0d,0x01,0x00,0x00, IR+10,X2+20, 0, 0, /* 17 cp @r2,#04567 */
|
||||
0026, 0x4d,0x01,0x00,0x00, AA+20,PR+10,X2+40, 0, /* 17 cp 4567(r2),#089ab */
|
||||
0026, 0x4d,0x01,0x00,0x00, AA+20,X2+40, 0, 0, /* 17 cp 4567,#089ab */
|
||||
0222, 0x8a,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /* 18 cpb rh3,rh2 */
|
||||
0022, 0x0a,0x00,0x00,0x00, RB+14,II+10, 0, 0, /* 18 cpb rh3,@r2 */
|
||||
0024, 0x0a,0x00,0x00,0x00, RB+14,X1+20, 0, 0, /* 18 cpb rh3,#045 */
|
||||
0024, 0x4a,0x00,0x00,0x00, RB+14,AA+20,PR+10, 0, /* 18 cpb rh3,4567(r2) */
|
||||
0024, 0x4a,0x00,0x00,0x00, RB+14,AA+20, 0, 0, /* 18 cpb rh3,4567 */
|
||||
0024, 0x0c,0x01,0x00,0x00, IR+10,X1+20, 0, 0, /* 18 cpb @r2,#045 */
|
||||
0026, 0x4c,0x01,0x00,0x00, AA+20,PR+10,X1+40, 0, /* 18 cpb 4567(r2),#089 */
|
||||
0026, 0x4c,0x01,0x00,0x00, AA+20,X2+40, 0, 0, /* 18 cpb 4567,#089ab */
|
||||
0222, 0x90,0x00,0x00,0x00, RL+14,RL+10, 0, 0, /* 19 cpl rr2,rr2 */
|
||||
0022, 0x10,0x00,0x00,0x00, RL+14,II+10, 0, 0, /* 19 cpl rr2,@r2 */
|
||||
0026, 0x10,0x00,0x00,0x00, RL+14,X4+20, 0, 0, /* 19 cpl rr2, #0022b */
|
||||
0024, 0x50,0x00,0x00,0x00, RL+14,AA+20,PR+10, 0, /* 19 cpl rr2,4567(r2) */
|
||||
0024, 0x50,0x00,0x00,0x00, RL+14,AA+20, 0, 0, /* 19 cpl rr2,4567 */
|
||||
0244, 0xbb,0x08,0x00,0x00, RR+30,II+10,RR+24,CC+34, /* 20 cpd r6,@r2,r5,cy */
|
||||
0244, 0xba,0x08,0x00,0x00, RB+30,II+10,RR+24,CC+34, /* 21 cpdb r6,@r2,r5,cy */
|
||||
0244, 0xbb,0x0c,0x00,0x00, RR+30,II+10,RR+24,CC+34, /* 22 cpdr r6,@r2,r5,cy */
|
||||
0244, 0xba,0x0c,0x00,0x00, RB+30,II+10,RR+24,CC+34, /* 23 cpdrb r6,@r2,r5,cy */
|
||||
0244, 0xbb,0x00,0x00,0x00, RR+30,II+10,RR+24,CC+34, /* 24 cpi r6,@r2,r5,cy */
|
||||
0244, 0xba,0x00,0x00,0x00, RB+30,II+10,RR+24,CC+34, /* 25 cpib r6,@r2,r5,cy */
|
||||
0244, 0xbb,0x04,0x00,0x00, RR+30,II+10,RR+24,CC+34, /* 26 cpir r6,@r2,r5,cy */
|
||||
0244, 0xba,0x04,0x00,0x00, RB+30,II+10,RR+24,CC+34, /* 27 cpirb r6,@r2,r5,cy */
|
||||
0244, 0xbb,0x0a,0x00,0x00, II+30,II+10,RR+24,CC+34, /* 28 cpsd @r6,@r2,r5,cy */
|
||||
0244, 0xba,0x0a,0x00,0x00, II+30,II+10,RR+24,CC+34, /* 29 cpsdb @r6,@r2,r5,cy */
|
||||
0244, 0xbb,0x0e,0x00,0x00, II+30,II+10,RR+24,CC+34, /* 30 cpsdr @r6,@r2,r5,cy */
|
||||
0244, 0xba,0x0e,0x00,0x00, II+30,II+10,RR+24,CC+34, /* 31 cpsdrb @r6,@r2,r5,cy */
|
||||
0244, 0xbb,0x02,0x00,0x00, II+30,II+10,RR+24,CC+34, /* 32 cpsi @r6,@r2,r5,cy */
|
||||
0244, 0xba,0x02,0x00,0x00, II+30,II+10,RR+24,CC+34, /* 33 cpsib @r6,@r2,r5,cy */
|
||||
0244, 0xbb,0x06,0x00,0x00, II+30,II+10,RR+24,CC+34, /* 34 cpsir @r6,@r2,r5,cy */
|
||||
0244, 0xba,0x06,0x00,0x00, II+30,II+10,RR+24,CC+34, /* 35 cpsirb @r6,@r2,r5,cy */
|
||||
0222, 0xb0,0x00,0x00,0x00, RB+10, 0, 0, 0, /* 36 dab rh2 */
|
||||
0222, 0xab,0x00,0x00,0x00, RR+10,ID+14, 0, 0, /* 37 dec r2,#4 */
|
||||
0022, 0x2b,0x00,0x00,0x00, II+10,ID+14, 0, 0, /* 37 dec @r2,#4 */
|
||||
0024, 0x6b,0x00,0x00,0x00, AA+20,PR+10,ID+14, 0, /* 37 dec 4567(r2),#4 */
|
||||
0024, 0x6b,0x00,0x00,0x00, AA+20,ID+14, 0, 0, /* 37 dec 4567,#4 */
|
||||
0222, 0xaa,0x00,0x00,0x00, RB+10,ID+14, 0, 0, /* 38 decb rh2,#4 */
|
||||
0022, 0x2a,0x00,0x00,0x00, II+10,ID+14, 0, 0, /* 38 decb @r2,#4 */
|
||||
0024, 0x6a,0x00,0x00,0x00, AA+20,PR+10,ID+14, 0, /* 38 decb 4567(r2),#4 */
|
||||
0024, 0x6a,0x00,0x00,0x00, AA+20,ID+14, 0, 0, /* 38 decb 4567,#4 */
|
||||
0222, 0x7c,0x00,0x00,0x00, VI+16,VI+17, 0, 0, /* 39 di vi,nvi, */
|
||||
0222, 0x9b,0x00,0x00,0x00, RL+14,RR+10, 0, 0, /* 40 div rr4,r2 */
|
||||
0022, 0x1b,0x00,0x00,0x00, RL+14,II+10, 0, 0, /* 40 div rr4,@r2 */
|
||||
0024, 0x1b,0x00,0x00,0x00, RL+14,X2+20, 0, 0, /* 40 div rr4,#4 */
|
||||
0024, 0x5b,0x00,0x00,0x00, RL+14,AA+20,PR+10, 0, /* 40 div rr4,4567(r2) */
|
||||
0024, 0x5b,0x00,0x00,0x00, RL+14,AA+20, 0, 0, /* 40 div rr4,4567 */
|
||||
0222, 0x9a,0x00,0x00,0x00, RQ+14,RL+10, 0, 0, /* 41 divl rq4,rr2 */
|
||||
0022, 0x1a,0x00,0x00,0x00, RQ+14,II+10, 0, 0, /* 41 divl rq4,@r2 */
|
||||
0026, 0x1a,0x00,0x00,0x00, RQ+14,X4+20, 0, 0, /* 41 divl rq4,#4 */
|
||||
0024, 0x5a,0x00,0x00,0x00, RQ+14,AA+20,PR+10, 0, /* 41 divl rq4,4567(r2) */
|
||||
0024, 0x5a,0x00,0x00,0x00, RQ+14,AA+20, 0, 0, /* 41 divl rq4,4567 */
|
||||
0222, 0xf0,0x80,0x00,0x00, RR+04,D1+11, 0, 0, /* 42 djnz r1,2c0c */
|
||||
0222, 0xf0,0x00,0x00,0x00, RB+04,D1+11, 0, 0, /* 43 dbjnz rh1,2c0c */
|
||||
0222, 0x7c,0x04,0x00,0x00, VI+16,VI+17, 0, 0, /* 44 ei vi,nvi, */
|
||||
0222, 0xad,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /* 45 ex r3,r2 */
|
||||
0022, 0x2d,0x00,0x00,0x00, RR+14,II+10, 0, 0, /* 45 ex r3,@r2 */
|
||||
0024, 0x6d,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /* 45 ex r3,4567(r2) */
|
||||
0024, 0x6d,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /* 45 ex r3,4567 */
|
||||
0222, 0xac,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /* 46 exb rh3,rh2 */
|
||||
0022, 0x2c,0x00,0x00,0x00, RB+14,II+10, 0, 0, /* 46 exb rh3,@r2 */
|
||||
0024, 0x6c,0x00,0x00,0x00, RB+14,AA+20,PR+10, 0, /* 46 exb rh3,4567(r2) */
|
||||
0024, 0x6c,0x00,0x00,0x00, RB+14,AA+20, 0, 0, /* 46 exb rh3,4567 */
|
||||
0222, 0xb1,0x0a,0x00,0x00, RL+10, 0, 0, 0, /* 47 exts rr2 */
|
||||
0222, 0xb1,0x00,0x00,0x00, RR+10, 0, 0, 0, /* 48 extsb r2 */
|
||||
0222, 0xb1,0x07,0x00,0x00, RQ+10, 0, 0, 0, /* 49 extsl rq0 */
|
||||
0222, 0x7a,0x00,0x00,0x00, 0, 0, 0, 0, /* 50 halt */
|
||||
0222, 0x3d,0x00,0x00,0x00, RR+14,IR+10, 0, 0, /* 51 in r3,@r2 */
|
||||
0024, 0x3b,0x04,0x00,0x00, RR+10,D4+20, 0, 0, /* 51 in r2(#4567) */
|
||||
0222, 0x3c,0x00,0x00,0x00, RB+14,IR+10, 0, 0, /* 52 inb rh3,@r2 */
|
||||
0024, 0x3a,0x04,0x00,0x00, RB+10,D4+20, 0, 0, /* 52 inb rh2(#4567) */
|
||||
0222, 0xa9,0x00,0x00,0x00, RR+10,ID+14, 0, 0, /* 53 inc r2,#4 */
|
||||
0022, 0x29,0x00,0x00,0x00, II+10,ID+14, 0, 0, /* 53 inc @r2,#4 */
|
||||
0024, 0x69,0x00,0x00,0x00, AA+20,PR+10,ID+14, 0, /* 53 inc 4567(r2),#4 */
|
||||
0024, 0x69,0x00,0x00,0x00, AA+20,ID+14, 0, 0, /* 53 inc 4567,#4 */
|
||||
0222, 0xa8,0x00,0x00,0x00, RB+10,ID+14, 0, 0, /* 54 incb rh2,#4 */
|
||||
0022, 0x28,0x00,0x00,0x00, II+10,ID+14, 0, 0, /* 54 incb @r2,#4 */
|
||||
0024, 0x68,0x00,0x00,0x00, AA+20,PR+10,ID+14, 0, /* 54 incb 4567(r2),#4 */
|
||||
0024, 0x68,0x00,0x00,0x00, AA+20,ID+14, 0, 0, /* 54 incb 4567,#4 */
|
||||
0244, 0x3b,0x08,0x00,0x08, II+30,IR+10,RR+24, 0, /* 55 ind @r6,@r2,r5 */
|
||||
0244, 0x3a,0x08,0x00,0x08, II+30,IR+10,RR+24, 0, /* 56 indb @r6,@r2,r5 */
|
||||
0244, 0x3b,0x08,0x00,0x00, II+30,IR+10,RR+24, 0, /* 57 indr @r6,@r2,r5 */
|
||||
0244, 0x3a,0x08,0x00,0x00, II+30,IR+10,RR+24, 0, /* 58 indrb @r6,@r2,r5 */
|
||||
0244, 0x3b,0x00,0x00,0x08, II+30,IR+10,RR+24, 0, /* 59 ini @r6,@r2,r5 */
|
||||
0244, 0x3a,0x00,0x00,0x08, II+30,IR+10,RR+24, 0, /* 60 inib @r6,@r2,r5 */
|
||||
0244, 0x3b,0x00,0x00,0x00, II+30,IR+10,RR+24, 0, /* 61 inir @r6,@r2,r5 */
|
||||
0244, 0x3a,0x00,0x00,0x00, II+30,IR+10,RR+24, 0, /* 62 inirb @r6,@r2,r5 */
|
||||
0222, 0x7b,0x00,0x00,0x00, 0, 0, 0, 0, /* 63 iret */
|
||||
0222, 0x1e,0x08,0x00,0x00, II+10, 0, 0, 0, /* 64 jp @r2 */
|
||||
0024, 0x5e,0x08,0x00,0x00, AA+20,PR+10, 0, 0, /* 64 jp 4567(r2) */
|
||||
0024, 0x5e,0x08,0x00,0x00, AA+20, 0, 0, 0, /* 64 jp 4567 */
|
||||
0022, 0x1e,0x00,0x00,0x00, CC+14,II+10, 0, 0, /* 64 jp ule,@r2 */
|
||||
0024, 0x5e,0x00,0x00,0x00, CC+14,AA+20,PR+10, 0, /* 64 jp ule,4567(r2) */
|
||||
0024, 0x5e,0x00,0x00,0x00, CC+14,AA+20, 0, 0, /* 64 jp ule,4567 */
|
||||
0222, 0xe8,0x00,0x00,0x00, D2+10, 0, 0, 0, /* 65 jr 2c98 */
|
||||
0022, 0xe0,0x00,0x00,0x00, CC+04,D2+10, 0, 0, /* 65 jr lt,2c98 */
|
||||
0222, 0xa1,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /* 66 ld r3,r2 */
|
||||
0022, 0x21,0x00,0x00,0x00, RR+14,II+10, 0, 0, /* 66 ld r3,@r2 */
|
||||
0024, 0x21,0x00,0x00,0x00, RR+14,X2+20, 0, 0, /* 66 ld r3,#04567 */
|
||||
0024, 0x61,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /* 66 ld r3,4567(r2) */
|
||||
0024, 0x61,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /* 66 ld r3,4567 */
|
||||
0024, 0x31,0x00,0x00,0x00, RR+14,BB+10,D4+20, 0, /* 66 ld r3,r2(#4567) */
|
||||
0044, 0x71,0x00,0x00,0x00, RR+14,BB+10,PR+24, 0, /* 66 ld r3,r2(r5) */
|
||||
0022, 0x2f,0x00,0x00,0x00, II+10,RR+14, 0, 0, /* 66 ld @r2,r3 */
|
||||
0024, 0x6f,0x00,0x00,0x00, AA+20,PR+10,RR+14, 0, /* 66 ld 4567(r2),r3 */
|
||||
0024, 0x6f,0x00,0x00,0x00, AA+20,RR+14, 0, 0, /* 66 ld 4567,r3 */
|
||||
0024, 0x33,0x00,0x00,0x00, BB+10,D4+20,RR+14, 0, /* 66 ld r2(#4567),r3 */
|
||||
0044, 0x73,0x00,0x00,0x00, BB+10,PR+24,RR+14, 0, /* 66 ld r2(r5),r3 */
|
||||
0026, 0x0d,0x05,0x00,0x00, II+10,X2+20, 0, 0, /* 66 ld @r2,#04567 */
|
||||
0026, 0x4d,0x05,0x00,0x00, AA+20,PR+10,X2+40, 0, /* 66 ld 4567(r2),#089ab */
|
||||
0026, 0x4d,0x05,0x00,0x00, AA+20,X2+40, 0, 0, /* 66 ld 4567,#089ab */
|
||||
0222, 0xa0,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /* 67 ldb rh3,rh2 */
|
||||
0022, 0x20,0x00,0x00,0x00, RB+14,II+10, 0, 0, /* 67 ldb rh3,@r2 */
|
||||
0024, 0x20,0x00,0x00,0x00, RB+14,X1+20, 0, 0, /* 67 ldb rh3,#045 */
|
||||
0024, 0x60,0x00,0x00,0x00, RB+14,AA+20,PR+10, 0, /* 67 ldb rh3,4567(r2) */
|
||||
0024, 0x60,0x00,0x00,0x00, RB+14,AA+20, 0, 0, /* 67 ldb rh3,4567 */
|
||||
0024, 0x30,0x00,0x00,0x00, RB+14,BB+10,D4+20, 0, /* 67 ldb rh3,r2(#4567) */
|
||||
0044, 0x70,0x00,0x00,0x00, RB+14,BB+10,PR+24, 0, /* 67 ldb rh3,r2(r5) */
|
||||
0022, 0x2e,0x00,0x00,0x00, II+10,RB+14, 0, 0, /* 67 ldb @r2,rh3 */
|
||||
0024, 0x6e,0x00,0x00,0x00, AA+20,PR+10,RB+14, 0, /* 67 ldb 4567(r2),rh3 */
|
||||
0024, 0x6e,0x00,0x00,0x00, AA+20,RB+14, 0, 0, /* 67 ldb 4567,rh3 */
|
||||
0024, 0x32,0x00,0x00,0x00, BB+10,D4+20,RB+14, 0, /* 67 ldb r2(#4567),rh3 */
|
||||
0044, 0x72,0x00,0x00,0x00, BB+10,PR+24,RB+14, 0, /* 67 ldb r2(r5),rh3 */
|
||||
0022, 0xc0,0x00,0x00,0x00, RB+04,B4+10,B4+14, 0, /* 67 ldb rh1,#2,#3 */
|
||||
0026, 0x0c,0x05,0x00,0x00, II+10,X1+20, 0, 0, /* 67 ldb @r2,#045 */
|
||||
0026, 0x4c,0x05,0x00,0x00, AA+20,PR+10,X1+40, 0, /* 67 ldb 4567(r2),#089 */
|
||||
0026, 0x4c,0x05,0x00,0x00, AA+20,X1+40, 0, 0, /* 67 ldb 4567,#089 */
|
||||
0222, 0x94,0x00,0x00,0x00, RL+14,RL+10, 0, 0, /* 68 ldl rr2,rr2 */
|
||||
0022, 0x14,0x00,0x00,0x00, RL+14,II+10, 0, 0, /* 68 ldl rr2,@r2 */
|
||||
0026, 0x14,0x00,0x00,0x00, RL+14,X4+20, 0, 0, /* 68 ldl rr2, #0022b */
|
||||
0024, 0x54,0x00,0x00,0x00, RL+14,AA+20,PR+10, 0, /* 68 ldl rr2,4567(r2) */
|
||||
0024, 0x54,0x00,0x00,0x00, RL+14,AA+20, 0, 0, /* 68 ldl rr2,4567 */
|
||||
0024, 0x35,0x00,0x00,0x00, RL+14,BB+10,D4+20, 0, /* 68 ldl rr2,r2(#4567) */
|
||||
0044, 0x75,0x00,0x00,0x00, RL+14,BB+10,PR+24, 0, /* 68 ldl rr2,r2(r5) */
|
||||
0022, 0x1d,0x00,0x00,0x00, II+10,RL+14, 0, 0, /* 68 ldl @r2,rr2 */
|
||||
0024, 0x5d,0x00,0x00,0x00, AA+20,PR+10,RL+14, 0, /* 68 ldl 4567(r2),rr2 */
|
||||
0024, 0x5d,0x00,0x00,0x00, AA+20,RL+14, 0, 0, /* 68 ldl 4567,rr2 */
|
||||
0024, 0x37,0x00,0x00,0x00, BB+10,D4+20,RL+14, 0, /* 68 ldl r2(#4567),rr2 */
|
||||
0044, 0x77,0x00,0x00,0x00, BB+10,PR+24,RL+14, 0, /* 68 ldl r2(r5),rr2 */
|
||||
0224, 0x76,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /* 69 lda r3,4567 */
|
||||
0024, 0x76,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /* 69 lda r3,4567(r2) */
|
||||
0024, 0x34,0x00,0x00,0x00, RR+14,BB+10,D4+20, 0, /* 69 lda r3,r2(#4567) */
|
||||
0044, 0x74,0x00,0x00,0x00, RR+14,BB+10,PR+24, 0, /* 69 lda r3,r2(r5) */
|
||||
0224, 0x34,0x00,0x00,0x00, RR+14,D4+20, 0, 0, /* 70 ldar r3(#4567) */
|
||||
0222, 0x7d,0x08,0x00,0x00, SR+14,RR+10, 0, 0, /* 71 ldctl refresh,r2 */
|
||||
0022, 0x7d,0x00,0x00,0x00, RR+10,SR+14, 0, 0, /* 71 ldctl r2,refresh */
|
||||
0222, 0x8c,0x09,0x00,0x00, UR+14,RB+10, 0, 0, /* 72 ldctlb flags,rh2 */
|
||||
0022, 0x8c,0x01,0x00,0x00, RB+10,UR+14, 0, 0, /* 72 ldctlb rh2,flags */
|
||||
0244, 0xbb,0x09,0x00,0x08, II+30,II+10,RR+24, 0, /* 73 ldd @r6,@r2,r5 */
|
||||
0244, 0xba,0x09,0x00,0x08, II+30,II+10,RR+24, 0, /* 74 lddb @r6,@r2,r5 */
|
||||
0244, 0xbb,0x09,0x00,0x00, II+30,II+10,RR+24, 0, /* 75 lddr @r6,@r2,r5 */
|
||||
0244, 0xba,0x09,0x00,0x00, II+30,II+10,RR+24, 0, /* 76 lddrb @r6,@r2,r5 */
|
||||
0244, 0xbb,0x01,0x00,0x08, II+30,II+10,RR+24, 0, /* 77 ldi @r6,@r2,r5 */
|
||||
0244, 0xba,0x01,0x00,0x08, II+30,II+10,RR+24, 0, /* 78 ldib @r6,@r2,r5 */
|
||||
0244, 0xbb,0x01,0x00,0x00, II+30,II+10,RR+24, 0, /* 79 ldir @r6,@r2,r5 */
|
||||
0244, 0xba,0x01,0x00,0x00, II+30,II+10,RR+24, 0, /* 80 ldirb @r6,@r2,r5 */
|
||||
0222, 0xbd,0x00,0x00,0x00, RR+10,B4+14, 0, 0, /* 81 ldk r2,#3 */
|
||||
0224, 0x1c,0x01,0x00,0x00, RR+24,II+10,ID+34, 0, /* 82 ldm r5,@r2,#2 */
|
||||
0026, 0x5c,0x01,0x00,0x00, RR+24,AA+40,PR+10,ID+34, /* 82 ldm r5,4567(r2),#2 */
|
||||
0026, 0x5c,0x01,0x00,0x00, RR+24,AA+40,ID+34, 0, /* 82 ldm r5,4567, #0022b */
|
||||
0024, 0x1c,0x09,0x00,0x00, II+10,RR+24,ID+34, 0, /* 82 ldm @r2,r5,#2 */
|
||||
0026, 0x5c,0x09,0x00,0x00, AA+40,PR+10,RR+24,ID+34, /* 82 ldm 4567(r2),r5,#2 */
|
||||
0026, 0x5c,0x09,0x00,0x00, AA+40,RR+24,ID+34, 0, /* 82 ldm 4567,r5,#2 */
|
||||
0222, 0x39,0x00,0x00,0x00, II+10, 0, 0, 0, /* 83 ldps @r2 */
|
||||
0024, 0x79,0x00,0x00,0x00, AA+20,PR+10, 0, 0, /* 83 ldps 4567(r2) */
|
||||
0024, 0x79,0x00,0x00,0x00, AA+20, 0, 0, 0, /* 83 ldps 4567 */
|
||||
0224, 0x31,0x00,0x00,0x00, RR+14,D4+20, 0, 0, /* 84 ldr r3(#4567) */
|
||||
0024, 0x33,0x00,0x00,0x00, D4+20,RR+14, 0, 0, /* 84 ldr (#4567),r3 */
|
||||
0224, 0x30,0x00,0x00,0x00, RR+14,D4+20, 0, 0, /* 85 ldrb r3(#4567) */
|
||||
0024, 0x32,0x00,0x00,0x00, D4+20,RR+14, 0, 0, /* 85 ldrb (#4567),r3 */
|
||||
0224, 0x35,0x00,0x00,0x00, RR+14,D4+20, 0, 0, /* 86 ldrl r3(#4567) */
|
||||
0024, 0x37,0x00,0x00,0x00, D4+20,RR+14, 0, 0, /* 86 ldrl (#4567),r3 */
|
||||
0222, 0x7b,0x0a,0x00,0x00, 0, 0, 0, 0, /* 87 mbit */
|
||||
0222, 0x7b,0x0d,0x00,0x00, RR+10, 0, 0, 0, /* 88 mreq r2 */
|
||||
0222, 0x7b,0x09,0x00,0x00, 0, 0, 0, 0, /* 89 mres */
|
||||
0222, 0x7b,0x08,0x00,0x00, 0, 0, 0, 0, /* 90 mset */
|
||||
0222, 0x99,0x00,0x00,0x00, RL+14,RR+10, 0, 0, /* 91 mult rr4,r2 */
|
||||
0022, 0x19,0x00,0x00,0x00, RL+14,II+10, 0, 0, /* 91 mult rr4,@r2 */
|
||||
0024, 0x19,0x00,0x00,0x00, RL+14,X2+20, 0, 0, /* 91 mult rr4,#4 */
|
||||
0024, 0x59,0x00,0x00,0x00, RL+14,AA+20,PR+10, 0, /* 91 mult rr4,4567(r2) */
|
||||
0024, 0x59,0x00,0x00,0x00, RL+14,AA+20, 0, 0, /* 91 mult rr4,4567 */
|
||||
0222, 0x98,0x00,0x00,0x00, RQ+14,RL+10, 0, 0, /* 92 multl rq4,rr2 */
|
||||
0022, 0x18,0x00,0x00,0x00, RQ+14,II+10, 0, 0, /* 92 multl rq4,@r2 */
|
||||
0026, 0x18,0x00,0x00,0x00, RQ+14,X4+20, 0, 0, /* 92 multl rq4,#4 */
|
||||
0024, 0x58,0x00,0x00,0x00, RQ+14,AA+20,PR+10, 0, /* 92 multl rq4,4567(r2) */
|
||||
0024, 0x58,0x00,0x00,0x00, RQ+14,AA+20, 0, 0, /* 92 multl rq4,4567 */
|
||||
0222, 0x8d,0x02,0x00,0x00, RR+10, 0, 0, 0, /* 93 neg r2 */
|
||||
0022, 0x0d,0x02,0x00,0x00, II+10, 0, 0, 0, /* 93 neg @r2 */
|
||||
0024, 0x4d,0x02,0x00,0x00, AA+20,PR+10, 0, 0, /* 93 neg 4567(r2) */
|
||||
0024, 0x4d,0x02,0x00,0x00, AA+20, 0, 0, 0, /* 93 neg 4567 */
|
||||
0222, 0x8c,0x02,0x00,0x00, RB+10, 0, 0, 0, /* 94 negb rh2 */
|
||||
0022, 0x0c,0x02,0x00,0x00, II+10, 0, 0, 0, /* 94 negb @r2 */
|
||||
0024, 0x4c,0x02,0x00,0x00, AA+20,PR+10, 0, 0, /* 94 negb 4567(r2) */
|
||||
0024, 0x4c,0x02,0x00,0x00, AA+20, 0, 0, 0, /* 94 negb 4567 */
|
||||
0222, 0x8d,0x07,0x00,0x00, 0, 0, 0, 0, /* 95 nop */
|
||||
0222, 0x85,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /* 96 or r3,r2 */
|
||||
0022, 0x05,0x00,0x00,0x00, RR+14,II+10, 0, 0, /* 96 or r3,@r2 */
|
||||
0024, 0x05,0x00,0x00,0x00, RR+14,X2+20, 0, 0, /* 96 or r3,#04567 */
|
||||
0024, 0x45,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /* 96 or r3,4567(r2) */
|
||||
0024, 0x45,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /* 96 or r3,4567 */
|
||||
0222, 0x84,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /* 97 orb rh3,rh2 */
|
||||
0022, 0x04,0x00,0x00,0x00, RB+14,II+10, 0, 0, /* 97 orb rh3,@r2 */
|
||||
0024, 0x04,0x00,0x00,0x00, RB+14,X1+20, 0, 0, /* 97 orb rh3,#045 */
|
||||
0024, 0x44,0x00,0x00,0x00, RB+14,AA+20,PR+10, 0, /* 97 orb rh3,4567(r2) */
|
||||
0024, 0x44,0x00,0x00,0x00, RB+14,AA+20, 0, 0, /* 97 orb rh3,4567 */
|
||||
0244, 0x3b,0x0a,0x00,0x00, IR+30,II+10,RR+24, 0, /* 98 otdr @r6,@r2,r5 */
|
||||
0244, 0x3a,0x0a,0x00,0x00, IR+30,II+10,RR+24, 0, /* 99 otdrb @r6,@r2,r5 */
|
||||
0244, 0x3b,0x02,0x00,0x00, IR+30,II+10,RR+24, 0, /*100 otir @r6,@r2,r5 */
|
||||
0244, 0x3a,0x02,0x00,0x00, IR+30,II+10,RR+24, 0, /*101 otirb @r6,@r2,r5 */
|
||||
0222, 0x3f,0x00,0x00,0x00, II+10,RR+14, 0, 0, /*102 out @r2,r3 */
|
||||
0024, 0x3b,0x06,0x00,0x00, D4+20,RR+10, 0, 0, /*102 out (#4567),r2 */
|
||||
0222, 0x3e,0x00,0x00,0x00, II+10,RB+14, 0, 0, /*103 outb @r2,rh3 */
|
||||
0024, 0x3a,0x06,0x00,0x00, D4+20,RB+10, 0, 0, /*103 outb (#4567),rh2 */
|
||||
0244, 0x3b,0x0a,0x00,0x08, IR+30,II+10,RR+24, 0, /*104 outd @r6,@r2,r5 */
|
||||
0244, 0x3a,0x0a,0x00,0x08, IR+30,II+10,RR+24, 0, /*105 outdb @r6,@r2,r5 */
|
||||
0244, 0x3b,0x02,0x00,0x08, IR+30,II+10,RR+24, 0, /*106 outi @r6,@r2,r5 */
|
||||
0244, 0x3a,0x02,0x00,0x08, IR+30,II+10,RR+24, 0, /*107 outib @r6,@r2,r5 */
|
||||
0222, 0x97,0x00,0x00,0x00, RR+14,II+10, 0, 0, /*108 pop r3,@r2 */
|
||||
0022, 0x17,0x00,0x00,0x00, II+14,II+10, 0, 0, /*108 pop @r3,@r2 */
|
||||
0024, 0x57,0x00,0x00,0x00, AA+20,PR+14,II+10, 0, /*108 pop 4567(r3),@r2 */
|
||||
0024, 0x57,0x00,0x00,0x00, AA+20,II+10, 0, 0, /*108 pop 4567,@r2 */
|
||||
0222, 0x95,0x00,0x00,0x00, RL+14,II+10, 0, 0, /*109 popl rr2,@r2 */
|
||||
0022, 0x15,0x00,0x00,0x00, II+14,II+10, 0, 0, /*109 popl @r3,@r2 */
|
||||
0024, 0x55,0x00,0x00,0x00, AA+20,PR+14,II+10, 0, /*109 popl 4567(r3),@r2 */
|
||||
0024, 0x55,0x00,0x00,0x00, AA+20,II+10, 0, 0, /*109 popl 4567,@r2 */
|
||||
0222, 0x93,0x00,0x00,0x00, II+10,RR+14, 0, 0, /*110 push @r2,r3 */
|
||||
0022, 0x13,0x00,0x00,0x00, II+10,II+14, 0, 0, /*110 push @r2,@r3 */
|
||||
0024, 0x53,0x00,0x00,0x00, II+10,AA+20,PR+14, 0, /*110 push @r2,4567(r3) */
|
||||
0024, 0x53,0x00,0x00,0x00, II+10,AA+20, 0, 0, /*110 push @r2,4567 */
|
||||
0024, 0x0d,0x09,0x00,0x00, II+10,X2+20, 0, 0, /*111 push @r2,#04567 */
|
||||
0222, 0x91,0x00,0x00,0x00, II+10,RL+14, 0, 0, /*111 pushl @r2,rr2 */
|
||||
0022, 0x11,0x00,0x00,0x00, II+10,II+14, 0, 0, /*111 pushl @r2,@r3 */
|
||||
0024, 0x51,0x00,0x00,0x00, II+10,AA+20,PR+14, 0, /*111 pushl @r2,4567(r3) */
|
||||
0024, 0x51,0x00,0x00,0x00, II+10,AA+20, 0, 0, /*111 pushl @r2,4567 */
|
||||
0222, 0xa3,0x00,0x00,0x00, RR+10,B4+14, 0, 0, /*112 res r2,#3 */
|
||||
0022, 0x23,0x00,0x00,0x00, II+10,B4+14, 0, 0, /*112 res @r2,#3 */
|
||||
0044, 0x23,0x00,0x00,0x00, RR+24,RR+14, 0, 0, /*112 res r5,r3 */
|
||||
0024, 0x63,0x00,0x00,0x00, AA+20,PR+10,B4+14, 0, /*112 res 4567(r2),#3 */
|
||||
0024, 0x63,0x00,0x00,0x00, AA+20,B4+14, 0, 0, /*112 res 4567,#3 */
|
||||
0222, 0xa2,0x00,0x00,0x00, RB+10,B4+14, 0, 0, /*113 resb rh2,#3 */
|
||||
0022, 0x22,0x00,0x00,0x00, II+10,B4+14, 0, 0, /*113 resb @r2,#3 */
|
||||
0044, 0x22,0x00,0x00,0x00, RB+24,RR+14, 0, 0, /*113 resb rh5,r3 */
|
||||
0024, 0x62,0x00,0x00,0x00, AA+20,PR+10,B4+14, 0, /*113 resb 4567(r2),#3 */
|
||||
0024, 0x62,0x00,0x00,0x00, AA+20,B4+14, 0, 0, /*113 resb 4567,#3 */
|
||||
0222, 0x8d,0x03,0x00,0x00, CF+10,CF+10,CF+10,CF+10, /*114 resflg le */
|
||||
0222, 0x9e,0x08,0x00,0x00, 0, 0, 0, 0, /*115 ret */
|
||||
0022, 0x9e,0x00,0x00,0x00, CC+14, 0, 0, 0, /*115 ret ule */
|
||||
0222, 0xb3,0x00,0x00,0x00, RR+10,BN+16, 0, 0, /*116 rl r2,#9 */
|
||||
0222, 0xb2,0x00,0x00,0x00, RB+10,BN+16, 0, 0, /*117 rlb rh2,#9 */
|
||||
0222, 0xb3,0x08,0x00,0x00, RR+10,BN+16, 0, 0, /*118 rlc r2,#9 */
|
||||
0222, 0xb2,0x08,0x00,0x00, RB+10,BN+16, 0, 0, /*119 rlcb rh2,#9 */
|
||||
0222, 0xbe,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /*120 rldb rh3,rh2 */
|
||||
0222, 0xb3,0x04,0x00,0x00, RR+10,BN+16, 0, 0, /*121 rr r2,#9 */
|
||||
0222, 0xb2,0x04,0x00,0x00, RB+10,BN+16, 0, 0, /*122 rrb rh2,#9 */
|
||||
0222, 0xb3,0x0c,0x00,0x00, RR+10,BN+16, 0, 0, /*123 rrc r2,#9 */
|
||||
0222, 0xb2,0x0c,0x00,0x00, RB+10,BN+16, 0, 0, /*124 rrcb rh2,#9 */
|
||||
0222, 0xbc,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /*125 rrdb rh3,rh2 */
|
||||
0222, 0xb7,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /*126 sbc r3,r2 */
|
||||
0222, 0xb6,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /*127 sbcb rh3,rh2 */
|
||||
0222, 0x7f,0x00,0x00,0x00, X1+10, 0, 0, 0, /*128 sc #023 */
|
||||
0244, 0xb3,0x0b,0x00,0x00, RR+10,RR+24, 0, 0, /*129 sda r2,r5 */
|
||||
0244, 0xb2,0x0b,0x00,0x00, RB+10,RR+24, 0, 0, /*130 sdab rh2,r5 */
|
||||
0244, 0xb3,0x0f,0x00,0x00, RL+10,RR+24, 0, 0, /*131 sdal rr2,r5 */
|
||||
0244, 0xb3,0x03,0x00,0x00, RR+10,RR+24, 0, 0, /*132 sdl r2,r5 */
|
||||
0244, 0xb2,0x03,0x00,0x00, RB+10,RR+24, 0, 0, /*133 sdlb rh2,r5 */
|
||||
0244, 0xb3,0x07,0x00,0x00, RL+10,RR+24, 0, 0, /*134 sdll rr2,r5 */
|
||||
0222, 0xa5,0x00,0x00,0x00, RR+10,B4+14, 0, 0, /*135 set r2,#3 */
|
||||
0022, 0x25,0x00,0x00,0x00, II+10,B4+14, 0, 0, /*135 set @r2,#3 */
|
||||
0044, 0x25,0x00,0x00,0x00, RR+24,RR+14, 0, 0, /*135 set r5,r3 */
|
||||
0024, 0x65,0x00,0x00,0x00, AA+20,PR+10,B4+14, 0, /*135 set 4567(r2),#3 */
|
||||
0024, 0x65,0x00,0x00,0x00, AA+20,B4+14, 0, 0, /*135 set 4567,#3 */
|
||||
0222, 0xa4,0x00,0x00,0x00, RB+10,B4+14, 0, 0, /*136 setb rh2,#3 */
|
||||
0022, 0x24,0x00,0x00,0x00, II+10,B4+14, 0, 0, /*136 setb @r2,#3 */
|
||||
0044, 0x24,0x00,0x00,0x00, RB+24,RR+14, 0, 0, /*136 setb rh5,r3 */
|
||||
0024, 0x64,0x00,0x00,0x00, AA+20,PR+10,B4+14, 0, /*136 setb 4567(r2),#3 */
|
||||
0024, 0x64,0x00,0x00,0x00, AA+20,B4+14, 0, 0, /*136 setb 4567,#3 */
|
||||
0222, 0x8d,0x01,0x00,0x00, CF+10,CF+10,CF+10,CF+10, /*137 setflg le */
|
||||
0224, 0x3b,0x05,0x00,0x00, RR+10,D4+20, 0, 0, /*138 sin r2(#4567) */
|
||||
0224, 0x3a,0x05,0x00,0x00, RB+10,D4+20, 0, 0, /*139 sinb rh2(#4567) */
|
||||
0244, 0x3b,0x09,0x00,0x08, II+30,II+10,RR+24, 0, /*140 sind @r6,@r2,r5 */
|
||||
0244, 0x3a,0x09,0x00,0x08, II+30,II+10,RR+24, 0, /*141 sindb @r6,@r2,r5 */
|
||||
0244, 0x3b,0x09,0x00,0x00, II+30,II+10,RR+24, 0, /*142 sindr @r6,@r2,r5 */
|
||||
0244, 0x3a,0x09,0x00,0x00, II+30,II+10,RR+24, 0, /*143 sindrb @r6,@r2,r5 */
|
||||
0244, 0x3b,0x01,0x00,0x08, II+30,II+10,RR+24, 0, /*144 sini @r6,@r2,r5 */
|
||||
0244, 0x3a,0x01,0x00,0x08, II+30,II+10,RR+24, 0, /*145 sinib @r6,@r2,r5 */
|
||||
0244, 0x3b,0x01,0x00,0x00, II+30,II+10,RR+24, 0, /*146 sinir @r6,@r2,r5 */
|
||||
0244, 0x3a,0x01,0x00,0x00, II+30,II+10,RR+24, 0, /*147 sinirb @r6,@r2,r5 */
|
||||
0244, 0xb3,0x09,0x00,0x00, RR+10,P1+20, 0, 0, /*148 sla r2,#7 */
|
||||
0244, 0xb2,0x09,0x00,0x00, RB+10,P2+30, 0, 0, /*149 slab rh2,#7 */
|
||||
0244, 0xb3,0x0d,0x00,0x00, RL+10,P3+20, 0, 0, /*150 slal rr2,#7 */
|
||||
0244, 0xb3,0x01,0x00,0x00, RR+10,P1+20, 0, 0, /*151 sll r2,#7 */
|
||||
0244, 0xb2,0x01,0x00,0x00, RB+10,P2+30, 0, 0, /*152 sllb rh2,#7 */
|
||||
0244, 0xb3,0x05,0x00,0x00, RL+10,P3+20, 0, 0, /*153 slll rr2,#7 */
|
||||
0244, 0x3b,0x0b,0x00,0x00, II+30,II+10,RR+24, 0, /*154 sotdr @r6,@r2,r5 */
|
||||
0244, 0x3a,0x0b,0x00,0x00, II+30,II+10,RR+24, 0, /*155 sotdrb @r6,@r2,r5 */
|
||||
0244, 0x3b,0x03,0x00,0x00, II+30,II+10,RR+24, 0, /*156 sotir @r6,@r2,r5 */
|
||||
0244, 0x3a,0x03,0x00,0x00, II+30,II+10,RR+24, 0, /*157 sotirb @r6,@r2,r5 */
|
||||
0224, 0x3b,0x07,0x00,0x00, D4+20,RR+10, 0, 0, /*158 sout (#4567),r2 */
|
||||
0224, 0x3a,0x07,0x00,0x00, D4+20,RB+10, 0, 0, /*159 soutb (#4567),rh2 */
|
||||
0244, 0x3b,0x0b,0x00,0x08, II+30,II+10,RR+24, 0, /*160 soutd @r6,@r2,r5 */
|
||||
0244, 0x3a,0x0b,0x00,0x08, II+30,II+10,RR+24, 0, /*161 soutdb @r6,@r2,r5 */
|
||||
0244, 0x3b,0x03,0x00,0x08, II+30,II+10,RR+24, 0, /*162 souti @r6,@r2,r5 */
|
||||
0244, 0x3a,0x03,0x00,0x08, II+30,II+10,RR+24, 0, /*163 soutib @r6,@r2,r5 */
|
||||
0244, 0xb3,0x09,0x00,0x00, RR+10,N1+20, 0, 0, /*164 sra r2,#25 */
|
||||
0244, 0xb2,0x09,0x00,0x00, RB+10,N2+30, 0, 0, /*165 srab rh2,#25 */
|
||||
0244, 0xb3,0x0d,0x00,0x00, RL+10,N3+20, 0, 0, /*166 sral rr2,#25 */
|
||||
0244, 0xb3,0x01,0x00,0x00, RR+10,N1+20, 0, 0, /*167 srl r2,#25 */
|
||||
0244, 0xb2,0x01,0x00,0x00, RB+10,N2+30, 0, 0, /*168 srlb rh2,#25 */
|
||||
0244, 0xb3,0x05,0x00,0x00, RL+10,N3+20, 0, 0, /*169 srll rr2,#25 */
|
||||
0222, 0x83,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /*170 sub r3,r2 */
|
||||
0022, 0x03,0x00,0x00,0x00, RR+14,II+10, 0, 0, /*170 sub r3,@r2 */
|
||||
0024, 0x03,0x00,0x00,0x00, RR+14,X2+20, 0, 0, /*170 sub r3,#04567 */
|
||||
0024, 0x43,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /*170 sub r3,4567(r2) */
|
||||
0024, 0x43,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /*170 sub r3,4567 */
|
||||
0222, 0x82,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /*171 subb rh3,rh2 */
|
||||
0022, 0x02,0x00,0x00,0x00, RB+14,II+10, 0, 0, /*171 subb rh3,@r2 */
|
||||
0024, 0x02,0x00,0x00,0x00, RB+14,X1+20, 0, 0, /*171 subb rh3,#045 */
|
||||
0024, 0x42,0x00,0x00,0x00, RB+14,AA+20,PR+10, 0, /*171 subb rh3,4567(r2) */
|
||||
0024, 0x42,0x00,0x00,0x00, RB+14,AA+20, 0, 0, /*171 subb rh3,4567 */
|
||||
0222, 0x92,0x00,0x00,0x00, RL+14,RL+10, 0, 0, /*172 subl rr2,rr2 */
|
||||
0022, 0x12,0x00,0x00,0x00, RL+14,II+10, 0, 0, /*172 subl rr2,@r2 */
|
||||
0026, 0x12,0x00,0x00,0x00, RL+14,X4+20, 0, 0, /*172 subl rr2, #0022b */
|
||||
0024, 0x52,0x00,0x00,0x00, RL+14,AA+20,PR+10, 0, /*172 subl rr2,4567(r2) */
|
||||
0024, 0x52,0x00,0x00,0x00, RL+14,AA+20, 0, 0, /*172 subl rr2,4567 */
|
||||
0222, 0xaf,0x00,0x00,0x00, CC+14,RR+10, 0, 0, /*173 tcc ule,r2 */
|
||||
0222, 0xae,0x00,0x00,0x00, CC+14,RB+10, 0, 0, /*174 tccb ule,rh2 */
|
||||
0222, 0x8d,0x04,0x00,0x00, RR+10, 0, 0, 0, /*175 test r2 */
|
||||
0022, 0x0d,0x04,0x00,0x00, II+10, 0, 0, 0, /*175 test @r2 */
|
||||
0024, 0x4d,0x04,0x00,0x00, AA+20,PR+10, 0, 0, /*175 test 4567(r2) */
|
||||
0024, 0x4d,0x04,0x00,0x00, AA+20, 0, 0, 0, /*175 test 4567 */
|
||||
0222, 0x8c,0x04,0x00,0x00, RB+10, 0, 0, 0, /*176 testb rh2 */
|
||||
0022, 0x0c,0x04,0x00,0x00, II+10, 0, 0, 0, /*176 testb @r2 */
|
||||
0024, 0x4c,0x04,0x00,0x00, AA+20,PR+10, 0, 0, /*176 testb 4567(r2) */
|
||||
0024, 0x4c,0x04,0x00,0x00, AA+20, 0, 0, 0, /*176 testb 4567 */
|
||||
0222, 0x9c,0x08,0x00,0x00, RL+10, 0, 0, 0, /*177 testl rr2 */
|
||||
0022, 0x1c,0x08,0x00,0x00, II+10, 0, 0, 0, /*177 testl @r2 */
|
||||
0024, 0x5c,0x08,0x00,0x00, AA+20,PR+10, 0, 0, /*177 testl 4567(r2) */
|
||||
0024, 0x5c,0x08,0x00,0x00, AA+20, 0, 0, 0, /*177 testl 4567 */
|
||||
0244, 0xb8,0x08,0x00,0x00, II+10,II+30,RR+24, 0, /*178 trdb @r2,@r6,r5 */
|
||||
0244, 0xb8,0x0c,0x00,0x00, II+10,II+30,RR+24, 0, /*179 trdrb @r2,@r6,r5 */
|
||||
0244, 0xb8,0x00,0x00,0x00, II+10,II+30,RR+24, 0, /*180 trib @r2,@r6,r5 */
|
||||
0244, 0xb8,0x04,0x00,0x00, II+10,II+30,RR+24, 0, /*181 trirb @r2,@r6,r5 */
|
||||
0244, 0xb8,0x0a,0x00,0x00, II+10,II+30,RR+24, 0, /*182 trtdb @r2,@r6,r5 */
|
||||
0244, 0xb8,0x0e,0x00,0x0e, II+10,II+30,RR+24, 0, /*183 trtdrb @r2,@r6,r5 */
|
||||
0244, 0xb8,0x02,0x00,0x00, II+10,II+30,RR+24, 0, /*184 trtib @r2,@r6,r5 */
|
||||
0244, 0xb8,0x06,0x00,0x0e, II+10,II+30,RR+24, 0, /*185 trtirb @r2,@r6,r5 */
|
||||
0222, 0x8d,0x06,0x00,0x00, RR+10, 0, 0, 0, /*186 tset r2 */
|
||||
0022, 0x0d,0x06,0x00,0x00, II+10, 0, 0, 0, /*186 tset @r2 */
|
||||
0024, 0x4d,0x06,0x00,0x00, AA+20,PR+10, 0, 0, /*186 tset 4567(r2) */
|
||||
0024, 0x4d,0x06,0x00,0x00, AA+20, 0, 0, 0, /*186 tset 4567 */
|
||||
0222, 0x8c,0x06,0x00,0x00, RB+10, 0, 0, 0, /*187 tsetb rh2 */
|
||||
0022, 0x0c,0x06,0x00,0x00, II+10, 0, 0, 0, /*187 tsetb @r2 */
|
||||
0024, 0x4c,0x06,0x00,0x00, AA+20,PR+10, 0, 0, /*187 tsetb 4567(r2) */
|
||||
0024, 0x4c,0x06,0x00,0x00, AA+20, 0, 0, 0, /*187 tsetb 4567 */
|
||||
0222, 0x89,0x00,0x00,0x00, RR+14,RR+10, 0, 0, /*188 xor r3,r2 */
|
||||
0022, 0x09,0x00,0x00,0x00, RR+14,II+10, 0, 0, /*188 xor r3,@r2 */
|
||||
0024, 0x09,0x00,0x00,0x00, RR+14,X2+20, 0, 0, /*188 xor r3,#04567 */
|
||||
0024, 0x49,0x00,0x00,0x00, RR+14,AA+20,PR+10, 0, /*188 xor r3,4567(r2) */
|
||||
0024, 0x49,0x00,0x00,0x00, RR+14,AA+20, 0, 0, /*188 xor r3,4567 */
|
||||
0222, 0x88,0x00,0x00,0x00, RB+14,RB+10, 0, 0, /*189 xorb rh3,rh2 */
|
||||
0022, 0x08,0x00,0x00,0x00, RB+14,II+10, 0, 0, /*189 xorb rh3,@r2 */
|
||||
0024, 0x08,0x00,0x00,0x00, RB+14,X1+20, 0, 0, /*189 xorb rh3,#045 */
|
||||
0024, 0x48,0x00,0x00,0x00, RB+14,AA+20,PR+10, 0, /*189 xorb rh3,4567(r2) */
|
||||
0024, 0x48,0x00,0x00,0x00, RB+14,AA+20, 0, 0, /*189 xorb rh3,4567 */
|
||||
0000, 0x00,0x00,0x00,0x00, 0, 0, 0, 0, /* PHEW! */
|
||||
};
|
||||
|
||||
/*
|
||||
******** The reserved opcodes table
|
||||
*/
|
||||
|
||||
char *opcodes[] ={
|
||||
".word", /* 01: 1, 0, 0 */
|
||||
"adc", /* 02: */
|
||||
"adcb", /* 03: 32, 0, 0 */
|
||||
"add", /* 04: 12, 0, 0 */
|
||||
"addb", /* 05: 17, 0, 0 */
|
||||
"addl", /* 06: 3, 0, 0 */
|
||||
"and", /* 07: 20, 0, 0 */
|
||||
"andb", /* 08: 9, 0, 0 */
|
||||
"bit", /* 09: 1, 0, 0 */
|
||||
"bitb", /* 0a: 29, 0, 0 */
|
||||
"call", /* 0b: 1, 0, 0 */
|
||||
"calr", /* 0c: 1, 0, 0 */
|
||||
"clr", /* 0d: 1, 0, 0 */
|
||||
"clrb", /* 0e: 1, 0, 0 */
|
||||
"com", /* 0f: 1, 0, 0 */
|
||||
"comb", /* 10: 1, 0, 0 */
|
||||
"comflg", /* 11: 1, 0, 0 */
|
||||
"cp", /* 12: 29, 0, 0 */
|
||||
"cpb", /* 13: 3, 0, 0 */
|
||||
"cpl", /* 14: 2, 0, 0 */
|
||||
"cpd", /* 15: 28, 0, 0 */
|
||||
"cpdb", /* 16: 28, 0, 0 */
|
||||
"cpdr", /* 17: 6, 0, 0 */
|
||||
"cpdrb", /* 18: 6, 0, 0 */
|
||||
"cpi", /* 19: 1, 0, 0 */
|
||||
"cpib", /* 1a: 2, 0, 0 */
|
||||
"cpir", /* 1b: 1, 0, 0 */
|
||||
"cpirb", /* 1c: 1, 0, 0 */
|
||||
"cpsd", /* 1d: 10, 0, 0 */
|
||||
"cpsdb", /* 1e: 7, 0, 0 */
|
||||
"cpsdr", /* 1f: 2, 0, 0 */
|
||||
"cpsdrb", /* 20: 1, 0, 0 */
|
||||
"cpsi", /* 21: 1, 0, 0 */
|
||||
"cpsib", /* 22: 1, 0, 0 */
|
||||
"cpsir", /* 23: 1, 0, 0 */
|
||||
"cpsirb", /* 24: 1, 0, 0 */
|
||||
"dab", /* 25: 1, 0, 0 */
|
||||
"dec", /* 26: 22, 0, 0 */
|
||||
"decb", /* 27: 29, 0, 0 */
|
||||
"di", /* 28: 3, 0, 0 */
|
||||
"div", /* 29: 1, 0, 0 */
|
||||
"divl", /* 2a: 1, 0, 0 */
|
||||
"djnz", /* 2b: 1, 0, 0 */
|
||||
"dbjnz", /* 2c: 1, 0, 0 */
|
||||
"ei", /* 2d: 1, 0, 0 */
|
||||
"ex", /* 2e: 1, 0, 0 */
|
||||
"exb", /* 2f: 1, 0, 0 */
|
||||
"exts", /* 30: 1, 0, 0 */
|
||||
"extsb", /* 31: 1, 0, 0 */
|
||||
"extsl", /* 32: 1, 0, 0 */
|
||||
"halt", /* 33: 20, 0, 0 */
|
||||
"in", /* 34: 14, 0, 0 */
|
||||
"inb", /* 35: 311, 0, 0 */
|
||||
"inc", /* 36: 24, 0, 0 */
|
||||
"incb", /* 37: 6, 0, 0 */
|
||||
"ind", /* 38: 1, 0, 0 */
|
||||
"indb", /* 39: 1, 0, 0 */
|
||||
"indr", /* 3a: 1, 0, 0 */
|
||||
"indrb", /* 3b: 1, 0, 0 */
|
||||
"ini", /* 3c: 6, 0, 0 */
|
||||
"inib", /* 3d: 6, 0, 0 */
|
||||
"inir", /* 3e: 6, 0, 0 */
|
||||
"inirb", /* 3f: 10, 0, 0 */
|
||||
"iret", /* 40: 28, 0, 0 */
|
||||
"jp", /* 41: 28, 0, 0 */
|
||||
"jr", /* 42: 6, 0, 0 */
|
||||
"ld", /* 43: 6, 0, 0 */
|
||||
"ldb", /* 44: 2, 0, 0 */
|
||||
"ldl", /* 45: 1, 0, 0 */
|
||||
"lda", /* 46: 17, 0, 0 */
|
||||
"ldar", /* ?? */
|
||||
"ldctl", /* 47: 22, 0, 0 */
|
||||
"ldctlb", /* 48: 1, 0, 0 */
|
||||
"ldd", /* 49: 1, 0, 0 */
|
||||
"lddb", /* 4a: 1, 0, 0 */
|
||||
"lddr", /* 4b: 1, 0, 0 */
|
||||
"lddrb", /* 4c: 1, 0, 0 */
|
||||
"ldi", /* 4d: 1, 0, 0 */
|
||||
"ldib", /* 4e: 1, 0, 0 */
|
||||
"ldir", /* 4f: 1, 0, 0 */
|
||||
"ldirb", /* 50: 1, 0, 0 */
|
||||
"ldk", /* 51: 8, 0, 0 */
|
||||
"ldm", /* 52: 1, 0, 0 */
|
||||
"ldps", /* 53: 9, 0, 0 */
|
||||
"ldr", /* 54: 1, 0, 0 */
|
||||
"ldrb", /* 55: 3, 0, 0 */
|
||||
"ldrl", /* 56: 9, 0, 0 */
|
||||
"mbit", /* 57: 1, 0, 0 */
|
||||
"mreq", /* 58: 1, 0, 0 */
|
||||
"mres", /* 59: 1, 0, 0 */
|
||||
"mset", /* 5a: 1, 0, 0 */
|
||||
"mult", /* 5b: 3, 0, 0 */
|
||||
"multl", /* 5c: 1, 0, 0 */
|
||||
"neg", /* 5d: 3, 0, 0 */
|
||||
"negb", /* 5e: 1, 0, 0 */
|
||||
"nop", /* 5f: 1, 0, 0 */
|
||||
"or", /* 60: 3, 0, 0 */
|
||||
"orb", /* 61: 1, 0, 0 */
|
||||
"otdr", /* 62: 3, 0, 0 */
|
||||
"otdrb", /* 63: 1, 0, 0 */
|
||||
"otir", /* 64: 1, 0, 0 */
|
||||
"otirb", /* 65: 1, 0, 0 */
|
||||
"out", /* 66: 29, 0, 0 */
|
||||
"outb", /* 67: 1, 0, 0 */
|
||||
"outd", /* 68: 1, 0, 0 */
|
||||
"outdb", /* 69: 3, 0, 0 */
|
||||
"outi", /* 6a: 3, 0, 0 */
|
||||
"outib", /* 6b: 3, 0, 0 */
|
||||
"pop", /* 6c: 3, 0, 0 */
|
||||
"popl", /* 6d: 17, 0, 0 */
|
||||
"push", /* 6e: 12, 0, 0 */
|
||||
"pushl", /* 6f: 3, 0, 0 */
|
||||
"res", /* 70: 1, 0, 0 */
|
||||
"resb", /* 71: 17, 0, 0 */
|
||||
"resflg", /* 72: 0, 0, 0 */
|
||||
"ret", /* 73: 0, 0, 0 */
|
||||
"rl", /* 74: 0, 0, 0 */
|
||||
"rlb", /* 75: 0, 0, 0 */
|
||||
"rlc", /* 76: 0, 0, 0 */
|
||||
"rlcb", /* 77: 0, 0, 0 */
|
||||
"rldb", /* 78: 0, 0, 0 */
|
||||
"rr", /* 79: 0, 0, 0 */
|
||||
"rrb", /* 7a: 0, 0, 0 */
|
||||
"rrc", /* 7b: 0, 0, 0 */
|
||||
"rrcb", /* 7c: 0, 0, 0 */
|
||||
"rrdb", /* 7d: 0, 0, 0 */
|
||||
"sbc", /* 7e: 0, 0, 0 */
|
||||
"sbcb", /* 7f: 0, 0, 0 */
|
||||
"sc", /* 80: 0, 0, 0 */
|
||||
"sda", /* 81: 0, 0, 0 */
|
||||
"sdab", /* 82: 0, 0, 0 */
|
||||
"sdal", /* 83: 0, 0, 0 */
|
||||
"sdl", /* 84: 0, 0, 0 */
|
||||
"sdlb", /* 85: 0, 0, 0 */
|
||||
"sdll", /* 86: 0, 0, 0 */
|
||||
"set", /* 87: 0, 0, 0 */
|
||||
"setb", /* 88: 0, 0, 0 */
|
||||
"setflg", /* 89: 0, 0, 0 */
|
||||
"sin", /* 8a: 0, 0, 0 */
|
||||
"sinb", /* 8b: 0, 0, 0 */
|
||||
"sind", /* 8c: 0, 0, 0 */
|
||||
"sindb", /* 8d: 0, 0, 0 */
|
||||
"sindr", /* 8e: 0, 0, 0 */
|
||||
"sindrb", /* 8f: 0, 0, 0 */
|
||||
"sini", /* 90: 0, 0, 0 */
|
||||
"sinib", /* 91: 0, 0, 0 */
|
||||
"sinir", /* 92: 0, 0, 0 */
|
||||
"sinirb", /* 93: 0, 0, 0 */
|
||||
"sla", /* 94: 0, 0, 0 */
|
||||
"slab", /* 95: 0, 0, 0 */
|
||||
"slal", /* 96: 0, 0, 0 */
|
||||
"sll", /* 97: 0, 0, 0 */
|
||||
"sllb", /* 98: 0, 0, 0 */
|
||||
"slll", /* 99: 0, 0, 0 */
|
||||
"sotdr", /* 9a: 0, 0, 0 */
|
||||
"sotdrb", /* 9b: 0, 0, 0 */
|
||||
"sotir", /* 9c: 0, 0, 0 */
|
||||
"sotirb", /* 9d: 0, 0, 0 */
|
||||
"sout", /* 9e: 0, 0, 0 */
|
||||
"soutb", /* 9f: 0, 0, 0 */
|
||||
"soutd", /* a0: 0, 0, 0 */
|
||||
"soutdb", /* a1: 0, 0, 0 */
|
||||
"souti", /* a2: 0, 0, 0 */
|
||||
"soutib", /* a3: 0, 0, 0 */
|
||||
"sra", /* a4: 0, 0, 0 */
|
||||
"srab", /* a5: 0, 0, 0 */
|
||||
"sral", /* a6: 0, 0, 0 */
|
||||
"srl", /* a7: 0, 0, 0 */
|
||||
"srlb", /* a8: 0, 0, 0 */
|
||||
"srll", /* a9: 0, 0, 0 */
|
||||
"sub", /* aa: 0, 0, 0 */
|
||||
"subb", /* ab: 0, 0, 0 */
|
||||
"subl", /* ac: 0, 0, 0 */
|
||||
"tcc", /* ad: 0, 0, 0 */
|
||||
"tccb", /* ae: 0, 0, 0 */
|
||||
"test", /* af: 0, 0, 0 */
|
||||
"testb", /* b0: 0, 0, 0 */
|
||||
"testl", /* b1: 0, 0, 0 */
|
||||
"trdb", /* b2: 0, 0, 0 */
|
||||
"trdrb", /* b3: 0, 0, 0 */
|
||||
"trib", /* b4: 0, 0, 0 */
|
||||
"trirb", /* b5: 0, 0, 0 */
|
||||
"trtdb", /* b6: 0, 0, 0 */
|
||||
"trtdrb", /* b7: 0, 0, 0 */
|
||||
"trtib", /* b8: 0, 0, 0 */
|
||||
"trtirb", /* b9: 0, 0, 0 */
|
||||
"tset", /* ba: 0, 0, 0 */
|
||||
"tsetb", /* bb: 0, 0, 0 */
|
||||
"xor", /* bc: 0, 0, 0 */
|
||||
"xorb", /* bd: 0, 0, 0 */
|
||||
"", /* be: 0, 0, 0 */
|
||||
};
|
||||
|
||||
/*
|
||||
******** The reserved operands
|
||||
*/
|
||||
|
||||
struct symbol oprands[] ={
|
||||
0, 0, "", /* 0 */
|
||||
RR, 0, "r0", /* 1 */
|
||||
RR, 1, "r1", /* 2 */
|
||||
RR, 2, "r2", /* 3 */
|
||||
RR, 3, "r3", /* 4 */
|
||||
RR, 4, "r4", /* 5 */
|
||||
RR, 5, "r5", /* 6 */
|
||||
RR, 6, "r6", /* 7 */
|
||||
RR, 7, "r7", /* 8 */
|
||||
RR, 8, "r8", /* 9 */
|
||||
RR, 9, "r9", /* 10 */
|
||||
RR, 10, "r10", /* 11 */
|
||||
RR, 11, "r11", /* 12 */
|
||||
RR, 12, "r12", /* 13 */
|
||||
RR, 13, "r13", /* 14 */
|
||||
RR, 14, "r14", /* 15 */
|
||||
RR, 15, "r15", /* 16 */
|
||||
RB, 0, "rh0", /* 17 */
|
||||
RB, 1, "rh1", /* 18 */
|
||||
RB, 2, "rh2", /* 19 */
|
||||
RB, 3, "rh3", /* 20 */
|
||||
RB, 4, "rh4", /* 21 */
|
||||
RB, 5, "rh5", /* 22 */
|
||||
RB, 6, "rh6", /* 23 */
|
||||
RB, 7, "rh7", /* 24 */
|
||||
RB, 8, "rl0", /* 25 */
|
||||
RB, 9, "rl1", /* 26 */
|
||||
RB, 10, "rl2", /* 27 */
|
||||
RB, 11, "rl3", /* 28 */
|
||||
RB, 12, "rl4", /* 29 */
|
||||
RB, 13, "rl5", /* 30 */
|
||||
RB, 14, "rl6", /* 31 */
|
||||
RB, 15, "rl7", /* 32 */
|
||||
RL, 0, "rr0", /* 33 */
|
||||
RL, 1, "rr1?", /* 34 */
|
||||
RL, 2, "rr2", /* 35 */
|
||||
RL, 3, "rr3?", /* 36 */
|
||||
RL, 4, "rr4", /* 37 */
|
||||
RL, 5, "rr5?", /* 38 */
|
||||
RL, 6, "rr6", /* 39 */
|
||||
RL, 7, "rr7?", /* 40 */
|
||||
RL, 8, "rr8", /* 41 */
|
||||
RL, 9, "rr9?", /* 42 */
|
||||
RL, 10, "rr10", /* 43 */
|
||||
RL, 11, "rr11?", /* 44 */
|
||||
RL, 12, "rr12", /* 45 */
|
||||
RL, 13, "rr13?", /* 46 */
|
||||
RL, 14, "rr14", /* 47 */
|
||||
RL, 15, "rr15?", /* 48 */
|
||||
RQ, 0, "rq0", /* 49 */
|
||||
RQ, 4, "rq4", /* 50 */
|
||||
RQ, 8, "rq8", /* 51 */
|
||||
RQ, 12, "rq12", /* 52 */
|
||||
0, 0, "X", /* 53 */
|
||||
0, 0, "X", /* 54 */
|
||||
0, 0, "X", /* 55 */
|
||||
0, 0, "X", /* 56 */
|
||||
0, 0, "Y", /* 57 */
|
||||
II, 1, "@r1", /* 58 */
|
||||
II, 2, "@r2", /* 59 */
|
||||
II, 3, "@r3", /* 60 */
|
||||
II, 4, "@r4", /* 61 */
|
||||
II, 5, "@r5", /* 62 */
|
||||
II, 6, "@r6", /* 63 */
|
||||
II, 7, "@r7", /* 64 */
|
||||
II, 8, "@r8", /* 65 */
|
||||
II, 9, "@r9", /* 66 */
|
||||
II, 10, "@r10", /* 67 */
|
||||
II, 11, "@r11", /* 68 */
|
||||
II, 12, "@r12", /* 69 */
|
||||
II, 13, "@r13", /* 70 */
|
||||
II, 14, "@r14", /* 71 */
|
||||
II, 15, "@r15", /* 72 */
|
||||
0, 0, "Y", /* 73 */
|
||||
IL, 2, "@rr2", /* 74 */
|
||||
IL, 4, "@rr4", /* 75 */
|
||||
IL, 6, "@rr6", /* 76 */
|
||||
IL, 8, "@rr8", /* 77 */
|
||||
IL, 10, "@rr10", /* 78 */
|
||||
IL, 12, "@rr12", /* 79 */
|
||||
IL, 14, "@rr14", /* 80 */
|
||||
0, 0, "Y", /* 81 */
|
||||
0, 0, "Y", /* 82 */
|
||||
0, 0, "Y", /* 83 */
|
||||
0, 0, "Y", /* 84 */
|
||||
0, 0, "Y", /* 85 */
|
||||
0, 0, "Y", /* 86 */
|
||||
0, 0, "Y", /* 87 */
|
||||
0, 0, "Y", /* 88 */
|
||||
0, 0, "Y", /* 89 */
|
||||
PR, 1, "(r1)", /* 90 */
|
||||
PR, 2, "(r2)", /* 91 */
|
||||
PR, 3, "(r3)", /* 92 */
|
||||
PR, 4, "(r4)", /* 93 */
|
||||
PR, 5, "(r5)", /* 94 */
|
||||
PR, 6, "(r6)", /* 95 */
|
||||
PR, 7, "(r7)", /* 96 */
|
||||
PR, 8, "(r8)", /* 97 */
|
||||
PR, 9, "(r9)", /* 98 */
|
||||
PR, 10, "(r10)", /* 99 */
|
||||
PR, 11, "(r11)", /* 100 */
|
||||
PR, 12, "(r12)", /* 101 */
|
||||
PR, 13, "(r13)", /* 102 */
|
||||
PR, 14, "(r14)", /* 103 */
|
||||
PR, 15, "(r15)", /* 104 */
|
||||
0, 0, "Y", /* 105 */
|
||||
PL, 2, "(rr2)", /* 106 */
|
||||
PL, 4, "(rr4)", /* 107 */
|
||||
PL, 6, "(rr6)", /* 108 */
|
||||
PL, 8, "(rr8)", /* 109 */
|
||||
PL, 10, "(rr10)", /* 110 */
|
||||
PL, 12, "(rr12)", /* 111 */
|
||||
PL, 14, "(rr14)", /* 112 */
|
||||
SR, 0, "cr0?", /* 113 */
|
||||
SR, 1, "cr1?", /* 114 */
|
||||
SR, 2, "fcw", /* 115 */
|
||||
SR, 3, "refresh", /* 116 */
|
||||
SR, 4, "psapseg", /* 117 */
|
||||
SR, 5, "psapoff", /* 118 */
|
||||
SR, 6, "nspseg", /* 119 */
|
||||
SR, 7, "nspoff", /* 120 */
|
||||
CC, 0, "Y", /* 121 */
|
||||
CC, 1, "lt", /* 122 */
|
||||
CC, 2, "le", /* 123 */
|
||||
CC, 3, "ule", /* 124 */
|
||||
CC, 4, "ov", /* 125 */
|
||||
CC, 5, "mi", /* 126 */
|
||||
CC, 6, "z", /* 127 */
|
||||
CC, 7, "cy", /* 128 */
|
||||
CC, 8, " ", /* 129 */
|
||||
CC, 9, "ge", /* 130 */
|
||||
CC, 10, "gt", /* 131 */
|
||||
CC, 11, "ugt", /* 132 */
|
||||
CC, 12, "nov", /* 133 */
|
||||
CC, 13, "pl", /* 134 */
|
||||
CC, 14, "nz", /* 135 */
|
||||
CC, 15, "nc", /* 136 */
|
||||
CC, 4, "pe", /* 137 */
|
||||
CC, 6, "eq", /* 138 */
|
||||
CC, 7, "ult", /* 139 */
|
||||
CC, 12, "po", /* 140 */
|
||||
CC, 14, "ne", /* 141 */
|
||||
CC, 15, "uge", /* 142 */
|
||||
0, 0, "NOTHING?", /* 143 */
|
||||
VI, 1, "nvi", /* 144 */
|
||||
VI, 2, "vi", /* 145 */
|
||||
VI, 3, "vi,nvi", /* 146 */
|
||||
UR, 1, "flags", /* 147 */
|
||||
0, 0, "" /* 148 */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* 3D Tic Tac Toe.
|
||||
*/
|
||||
#include "stdio.h"
|
||||
#define EMPTY 0
|
||||
#define PLAYER 1
|
||||
#define BEAST 5
|
||||
|
||||
/*
|
||||
* This is a table of all winning
|
||||
* combinations.
|
||||
* I stole it out of Kilobaud, April
|
||||
* 78.
|
||||
* You can look there to see how it
|
||||
* is ordered.
|
||||
*/
|
||||
char w[] = {
|
||||
0, 1, 2, 3,
|
||||
4, 5, 6, 7,
|
||||
8, 9, 10, 11,
|
||||
12, 13, 14, 15,
|
||||
0, 4, 8, 12,
|
||||
1, 5, 9, 13,
|
||||
2, 6, 10, 14,
|
||||
3, 7, 11, 15,
|
||||
0, 5, 10, 15,
|
||||
3, 6, 9, 12,
|
||||
16, 17, 18, 19,
|
||||
20, 21, 22, 23,
|
||||
24, 25, 26, 27,
|
||||
28, 29, 30, 31,
|
||||
16, 20, 24, 28,
|
||||
17, 21, 25, 29,
|
||||
18, 22, 26, 30,
|
||||
19, 23, 27, 31,
|
||||
16, 21, 26, 31,
|
||||
19, 22, 25, 28,
|
||||
32, 33, 34, 35,
|
||||
36, 37, 38, 39,
|
||||
40, 41, 42, 43,
|
||||
44, 45, 46, 47,
|
||||
32, 36, 40, 44,
|
||||
33, 37, 41, 45,
|
||||
34, 38, 42, 46,
|
||||
35, 39, 43, 47,
|
||||
32, 37, 42, 47,
|
||||
35, 38, 41, 44,
|
||||
48, 49, 50, 51,
|
||||
52, 53, 54, 55,
|
||||
56, 57, 58, 59,
|
||||
60, 61, 62, 63,
|
||||
48, 52, 56, 60,
|
||||
49, 53, 57, 61,
|
||||
50, 54, 58, 62,
|
||||
51, 55, 59, 63,
|
||||
48, 53, 58, 63,
|
||||
51, 54, 57, 60,
|
||||
0, 16, 32, 48,
|
||||
1, 17, 33, 49,
|
||||
2, 18, 34, 50,
|
||||
3, 19, 35, 51,
|
||||
4, 20, 36, 52,
|
||||
5, 21, 37, 53,
|
||||
6, 22, 38, 54,
|
||||
7, 23, 39, 55,
|
||||
8, 24, 40, 56,
|
||||
9, 25, 41, 57,
|
||||
10, 26, 42, 58,
|
||||
11, 27, 43, 59,
|
||||
13, 29, 45, 61,
|
||||
12, 28, 44, 60,
|
||||
14, 30, 46, 62,
|
||||
15, 31, 47, 63,
|
||||
0, 21, 42, 63,
|
||||
4, 21, 38, 55,
|
||||
8, 25, 42, 59,
|
||||
12, 25, 38, 51,
|
||||
1, 21, 41, 61,
|
||||
13, 25, 37, 49,
|
||||
2, 22, 42, 62,
|
||||
14, 26, 38, 50,
|
||||
3, 22, 41, 60,
|
||||
7, 22, 37, 52,
|
||||
11, 26, 41, 56,
|
||||
15, 26, 37, 48,
|
||||
0, 20, 40, 60,
|
||||
0, 17, 34, 51,
|
||||
3, 18, 33, 48,
|
||||
3, 23, 43, 63,
|
||||
12, 24, 36, 48,
|
||||
12, 29, 46, 63,
|
||||
15, 30, 45, 60,
|
||||
15, 27, 39, 51
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the board.
|
||||
* Starts off all empty.
|
||||
*/
|
||||
char b[64];
|
||||
|
||||
char *sep = "----------- ----------- ----------- -----------";
|
||||
|
||||
/*
|
||||
* The mainline is just
|
||||
* a driver.
|
||||
*/
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
printf("Do you want the rules? ");
|
||||
gets(buf);
|
||||
if(buf[0]=='Y' || buf[0]=='y')
|
||||
rules();
|
||||
printf("Do you want to go first? ");
|
||||
gets(buf);
|
||||
if(buf[0]=='Y' || buf[0]=='y')
|
||||
user();
|
||||
for(;;) {
|
||||
beast();
|
||||
user();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the rules of the
|
||||
* game.
|
||||
*/
|
||||
rules()
|
||||
{
|
||||
printf("Three dimensional tic-tac-toe is played on a 4x4x4\n");
|
||||
printf("board. To win you must get 4 in a row. Your moves\n");
|
||||
printf("are specified as a 3 digit number; the first digit\n");
|
||||
printf("is the level, the second the row and the third the\n");
|
||||
printf("column. Levels and columns go from left to right\n");
|
||||
printf("from 0 to 3. Rows go from top to bottom with 0 on\n");
|
||||
printf("the top.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept a user move.
|
||||
* Exit if he wins.
|
||||
*/
|
||||
user()
|
||||
{
|
||||
register int i, j, t;
|
||||
char buf[20];
|
||||
|
||||
board();
|
||||
for(;;) {
|
||||
printf("Your move? ");
|
||||
if(gets(buf) == NULL) {
|
||||
printf("Chicken.\n");
|
||||
exit(0);
|
||||
}
|
||||
i = 16*(buf[0]-'0') + (buf[1]-'0') + 4*(buf[2]-'0');
|
||||
if(i>=0 && i<=63 && b[i]==EMPTY)
|
||||
break;
|
||||
printf("Eh?\n");
|
||||
}
|
||||
b[i] = PLAYER;
|
||||
for(i=0; i<4*76; i+=4) {
|
||||
t = 0;
|
||||
for(j=0; j<4; ++j)
|
||||
t += b[w[i+j]];
|
||||
if(t == 4*PLAYER) {
|
||||
printf("You win.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the board.
|
||||
* Not as easy as it sounds.
|
||||
*/
|
||||
board()
|
||||
{
|
||||
register int i, j;
|
||||
|
||||
for(i=0; i<4; ++i) {
|
||||
if(i != 0)
|
||||
puts(sep);
|
||||
for(j=0; j<64; j+=4) {
|
||||
psq(i+j);
|
||||
if(j==12 || j==28 || j==44)
|
||||
putchar(' ');
|
||||
else if(j >= 60)
|
||||
putchar('\n');
|
||||
else
|
||||
putchar('!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Format and put out square
|
||||
* `s' of the board.
|
||||
*/
|
||||
psq(s)
|
||||
{
|
||||
register int v;
|
||||
|
||||
v = b[s];
|
||||
if(v == PLAYER)
|
||||
printf("UU");
|
||||
else if(v == BEAST)
|
||||
printf("CC");
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Move for the machine.
|
||||
* Just exit on machine wins
|
||||
* and draws.
|
||||
*/
|
||||
beast()
|
||||
{
|
||||
register int i, j, t;
|
||||
int s, bs, bt, v[76];
|
||||
|
||||
for(i=0; i<4*76; i+=4) {
|
||||
t = 0;
|
||||
for(j=0; j<4; ++j)
|
||||
t += b[w[i+j]];
|
||||
v[i>>2] = t;
|
||||
if(t == 3*BEAST)
|
||||
break;
|
||||
}
|
||||
if(i < 4*76) {
|
||||
for(j=0; j<4; ++j)
|
||||
if(b[w[i+j]] == EMPTY) {
|
||||
b[w[i+j]] = BEAST;
|
||||
break;
|
||||
}
|
||||
board();
|
||||
printf("I win.\n");
|
||||
exit(0);
|
||||
}
|
||||
bt = 0;
|
||||
for(s=0; s<64; ++s) {
|
||||
if(b[s] != EMPTY)
|
||||
continue;
|
||||
t = 0;
|
||||
for(i=0; i<4*76; i+=4) {
|
||||
for(j=0; j<4; ++j)
|
||||
if(w[i+j] == s)
|
||||
break;
|
||||
if(j != 4) {
|
||||
if(v[i>>2] == 3*PLAYER) {
|
||||
b[s] = BEAST;
|
||||
return;
|
||||
}
|
||||
t += weight(v[i>>2]);
|
||||
}
|
||||
}
|
||||
if(t > bt) {
|
||||
bt = t;
|
||||
bs = s;
|
||||
}
|
||||
}
|
||||
if(bt != 0)
|
||||
b[bs] = BEAST;
|
||||
else {
|
||||
for(s=0; s<64; ++s)
|
||||
if(b[s] == EMPTY)
|
||||
break;
|
||||
if(s == 64) {
|
||||
printf("Draw.\n");
|
||||
exit(0);
|
||||
}
|
||||
b[s] = BEAST;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a total along a winning
|
||||
* combination, return the weight
|
||||
* value.
|
||||
*/
|
||||
weight(at)
|
||||
{
|
||||
register int t;
|
||||
|
||||
t = at;
|
||||
if(t == PLAYER)
|
||||
return(1);
|
||||
if(t == 2*PLAYER)
|
||||
return(4);
|
||||
if(t == BEAST)
|
||||
return(1);
|
||||
if(t == 2*BEAST)
|
||||
return(2);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
#include "stdio.h"
|
||||
#include "cpm.h"
|
||||
/*
|
||||
* wumpus
|
||||
* stolen from PCC Vol 2 No 1
|
||||
*/
|
||||
|
||||
#define NBAT 3
|
||||
#define NROOM 20
|
||||
#define NTUNN 3
|
||||
#define NPIT 3
|
||||
/* #define BIGINT 2147483648.0 */
|
||||
|
||||
struct room
|
||||
{
|
||||
int tunn[NTUNN];
|
||||
int flag;
|
||||
} room[NROOM] = 0;
|
||||
|
||||
char *intro[] =
|
||||
{
|
||||
"\n",
|
||||
"Welcome to 'Hunt the Wumpus.'\n",
|
||||
"\n",
|
||||
"The Wumpus lives in a cave of %d rooms.\n",
|
||||
"Each room has %d tunnels leading to other rooms.\n",
|
||||
"\n",
|
||||
"Hazards:\n",
|
||||
"\n",
|
||||
"Bottomless Pits - Some rooms have Bottomless Pits in them.\n",
|
||||
" If you go there, you fall into the pit and lose!\n",
|
||||
"Super Bats - Some other rooms have super bats.\n",
|
||||
" If you go there, a bat will grab you and take you to\n",
|
||||
" somewhere else in the cave where you could\n",
|
||||
" fall into a pit or run into the . . .\n",
|
||||
"\n",
|
||||
"Wumpus:\n",
|
||||
"\n",
|
||||
"The Wumpus is not bothered by the hazards since\n",
|
||||
"he has sucker feet and is too big for a bat to lift.\n",
|
||||
"\n",
|
||||
"Usually he is asleep.\n",
|
||||
"Two things wake him up:\n",
|
||||
" your entering his room\n",
|
||||
" your shooting an arrow anywhere in the cave.\n",
|
||||
"If the wumpus wakes, he either decides to move one room or\n",
|
||||
"stay where he was. But if he ends up where you are,\n",
|
||||
"he eats you up and you lose!\n",
|
||||
"\n",
|
||||
"You:\n",
|
||||
"\n",
|
||||
"Each turn you may either move or shoot a crooked arrow.\n",
|
||||
"\n",
|
||||
"Moving - You can move to one of the adjoining rooms;\n",
|
||||
" that is, to one that has a tunnel connecting it with\n",
|
||||
" the room you are in.\n",
|
||||
"\n",
|
||||
"Shooting - You have 5 arrows. You lose when you run out.\n",
|
||||
" Each arrow can go from 1 to 5 rooms.\n",
|
||||
" You aim by telling the computer\n",
|
||||
" The arrow's path is a list of room numbers\n",
|
||||
" telling the arrow which room to go to next.\n",
|
||||
" The list is terminated with a 0.\n",
|
||||
" The first room in the path must be connected to the\n",
|
||||
" room you are in. Each succeeding room must be\n",
|
||||
" connected to the previous room.\n",
|
||||
" If there is no tunnel between two of the rooms\n",
|
||||
" in the arrow's path, the arrow chooses one of the\n",
|
||||
" three tunnels from the room it's in and goes its\n",
|
||||
" own way.\n",
|
||||
"\n",
|
||||
" If the arrow hits the wumpus, you win!\n",
|
||||
" If the arrow hits you, you lose!\n",
|
||||
"\n",
|
||||
"Warnings:\n",
|
||||
"\n",
|
||||
"When you are one or two rooms away from the wumpus,\n",
|
||||
"the computer says:\n",
|
||||
" 'I smell a Wumpus'\n",
|
||||
"When you are one room away from some other hazard, it says:\n",
|
||||
" Bat - 'Bats nearby'\n",
|
||||
" Pit - 'I feel a draft'\n",
|
||||
"\n",
|
||||
0,
|
||||
};
|
||||
|
||||
#define BAT 01
|
||||
#define PIT 02
|
||||
#define WUMP 04
|
||||
|
||||
int arrow = 0;
|
||||
int loc = 0;
|
||||
int wloc = 0;
|
||||
int tchar = 0;
|
||||
|
||||
main()
|
||||
{
|
||||
register i, j;
|
||||
register struct room *p;
|
||||
int k, icomp();
|
||||
|
||||
printf("Instructions? (y-n) ");
|
||||
if(rline() == 'y')
|
||||
for(i=0; intro[i]; i++)
|
||||
printf(intro[i], i&1? NROOM: NTUNN);
|
||||
|
||||
|
||||
/*
|
||||
* initialize the room connections
|
||||
*/
|
||||
|
||||
init:
|
||||
p = &room[0];
|
||||
for(i=0; i<NROOM; i++) {
|
||||
for(j=0; j<NTUNN; j++)
|
||||
p->tunn[j] = -1;
|
||||
p++;
|
||||
}
|
||||
k = 0;
|
||||
for(i=1; i<NROOM; ) {
|
||||
j = rnum(NROOM);
|
||||
p = &room[j];
|
||||
if(j == k || p->tunn[0] >= 0 || p->tunn[1] >= 0)
|
||||
continue;
|
||||
p->tunn[1] = k;
|
||||
room[k].tunn[0] = j;
|
||||
k = j;
|
||||
i++;
|
||||
}
|
||||
p = &room[0];
|
||||
for(i=0; i<NROOM; i++) {
|
||||
for(j=0; j<NTUNN; j++) {
|
||||
if(p->tunn[j] < 0)
|
||||
p->tunn[j] = tunnel(i);
|
||||
if(p->tunn[j] == i)
|
||||
goto init;
|
||||
for(k=0; k<j; k++)
|
||||
if(p->tunn[j] == p->tunn[k])
|
||||
goto init;
|
||||
}
|
||||
qsort(&p->tunn[0], NTUNN, sizeof(p->tunn[0]), icomp);
|
||||
p++;
|
||||
}
|
||||
|
||||
/*
|
||||
* put in player, wumpus,
|
||||
* pits and bats
|
||||
*/
|
||||
|
||||
setup:
|
||||
arrow = 5;
|
||||
p = &room[0];
|
||||
for(i=0; i<NROOM; i++) {
|
||||
p->flag = 0;
|
||||
p++;
|
||||
}
|
||||
for(i=0; i<NPIT; ) {
|
||||
p = &room[rnum(NROOM)];
|
||||
if((p->flag&PIT) == 0) {
|
||||
p->flag |= PIT;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
for(i=0; i<NBAT; ) {
|
||||
p = &room[rnum(NROOM)];
|
||||
if((p->flag&(PIT|BAT)) == 0) {
|
||||
p->flag |= BAT;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
i = rnum(NROOM);
|
||||
wloc = i;
|
||||
room[i].flag |= WUMP;
|
||||
for(;;) {
|
||||
i = rnum(NROOM);
|
||||
if((room[i].flag&(PIT|BAT|WUMP)) == 0) {
|
||||
loc = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* main loop of the game
|
||||
*/
|
||||
|
||||
loop:
|
||||
printf("You are in room %d\n", loc+1);
|
||||
p = &room[loc];
|
||||
if(p->flag&PIT) {
|
||||
printf("You fell into a pit\n");
|
||||
goto done;
|
||||
}
|
||||
if(p->flag&WUMP) {
|
||||
printf("You were eaten by the wumpus\n");
|
||||
goto done;
|
||||
}
|
||||
if(p->flag&BAT) {
|
||||
printf("Theres a bat in your room\n");
|
||||
loc = rnum(NROOM);
|
||||
goto loop;
|
||||
}
|
||||
for(i=0; i<NTUNN; i++)
|
||||
if(near(&room[p->tunn[i]], WUMP))
|
||||
goto nearwump;
|
||||
if (near(p, WUMP)) {
|
||||
nearwump:
|
||||
printf("I smell a wumpus\n");
|
||||
}
|
||||
if (near(p, BAT))
|
||||
printf("Bats nearby\n");
|
||||
if (near(p, PIT))
|
||||
printf("I feel a draft\n");
|
||||
printf("There are tunnels to");
|
||||
for(i=0; i<NTUNN; i++)
|
||||
printf(" %d", p->tunn[i]+1);
|
||||
printf("\n");
|
||||
|
||||
again:
|
||||
printf("Move or shoot (m-s) ");
|
||||
switch(rline()) {
|
||||
case 'm':
|
||||
if(tchar == '\n')
|
||||
printf("which room? ");
|
||||
i = rin()-1;
|
||||
for(j=0; j<NTUNN; j++)
|
||||
if(i == p->tunn[j])
|
||||
goto groom;
|
||||
printf("You hit the wall\n");
|
||||
goto again;
|
||||
groom:
|
||||
loc = i;
|
||||
if(i == wloc)
|
||||
goto mwump;
|
||||
goto loop;
|
||||
|
||||
case 's':
|
||||
if(tchar == '\n')
|
||||
printf("Give list of rooms terminated by 0\n");
|
||||
for(i=0; i<5; i++) {
|
||||
j = rin()-1;
|
||||
if(j == -1)
|
||||
break;
|
||||
ranarw:
|
||||
for(k=0; k<NTUNN; k++)
|
||||
if(j == p->tunn[k])
|
||||
goto garow;
|
||||
j = rnum(NROOM);
|
||||
goto ranarw;
|
||||
garow:
|
||||
p = &room[j];
|
||||
if(j == loc) {
|
||||
printf("You shot yourself\n");
|
||||
goto done;
|
||||
}
|
||||
if(p->flag&WUMP) {
|
||||
printf("You slew the wumpus\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if(--arrow == 0) {
|
||||
printf("That was your last shot\n");
|
||||
goto done;
|
||||
}
|
||||
goto mwump;
|
||||
}
|
||||
|
||||
goto again;
|
||||
|
||||
mwump:
|
||||
p = &room[wloc];
|
||||
p->flag &= ~WUMP;
|
||||
i = rnum(NTUNN+1);
|
||||
if(i != NTUNN)
|
||||
wloc = p->tunn[i];
|
||||
room[wloc].flag |= WUMP;
|
||||
goto loop;
|
||||
|
||||
done:
|
||||
drain();
|
||||
printf("Another game? (y-n) ");
|
||||
if(rline() != 'n') {
|
||||
drain();
|
||||
printf("Same room setup? (y-n) ");
|
||||
if(rline() != 'n')
|
||||
goto setup;
|
||||
goto init;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
tunnel(i)
|
||||
{
|
||||
register struct room *p;
|
||||
register n, j;
|
||||
int c;
|
||||
|
||||
c = 20;
|
||||
|
||||
loop:
|
||||
n = rnum(NROOM);
|
||||
if(n == i)
|
||||
if(--c > 0)
|
||||
goto loop;
|
||||
p = &room[n];
|
||||
for(j=0; j<NTUNN; j++)
|
||||
if(p->tunn[j] == -1) {
|
||||
p->tunn[j] = i;
|
||||
return(n);
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
|
||||
rline()
|
||||
{
|
||||
register char c, r;
|
||||
|
||||
while((c=getchar()) == ' ');
|
||||
r = c;
|
||||
while(c != '\n' && c != ' ') {
|
||||
if(c == EOF)
|
||||
exit(0);
|
||||
c = getchar();
|
||||
}
|
||||
tchar = c;
|
||||
return(r);
|
||||
}
|
||||
|
||||
rnum(n)
|
||||
{
|
||||
static short first[2];
|
||||
long temp;
|
||||
|
||||
if(first[1] == 0) {
|
||||
/* time(first); */
|
||||
if(first[1]==0) first[1] = 1;
|
||||
srand((first[1]*first[0])^first[1]);
|
||||
}
|
||||
temp = ((unsigned) rand()) * n;
|
||||
temp = temp/16384; temp = temp/2;
|
||||
return(temp);
|
||||
}
|
||||
|
||||
rin()
|
||||
{
|
||||
register n, c;
|
||||
|
||||
n = 0;
|
||||
c = getchar();
|
||||
while(c != '\n' && c != ' ') {
|
||||
if(c<'0' || c>'9') {
|
||||
while(c != '\n') {
|
||||
if(c == EOF)
|
||||
exit(0);
|
||||
c = getchar();
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
n = n*10 + c-'0';
|
||||
c = getchar();
|
||||
}
|
||||
return(n);
|
||||
}
|
||||
|
||||
near(ap, ahaz)
|
||||
struct room *ap;
|
||||
{
|
||||
register struct room *p;
|
||||
register haz, i;
|
||||
|
||||
p = apIq
|
||||
This directory contains the source, object and linked versions of utilities
|
||||
useful in the Olivetti implementation of CP/M-8000:
|
||||
cpmcopy Copies the 10 boot tracks from one disk
|
||||
to another.
|
||||
ddcopy "fast" disk-to-disk copy.
|
||||
@@ -0,0 +1,413 @@
|
||||
/* this is the archiver for the Zilog edition of the C compiler */
|
||||
|
||||
typedef long time_t; /* a time */
|
||||
typedef int dev_t; /* device code */
|
||||
typedef long off_t; /* offset in file */
|
||||
|
||||
struct stat
|
||||
{
|
||||
dev_t st_dev;
|
||||
unsigned int st_ino;
|
||||
unsigned short st_mode;
|
||||
short st_nlink;
|
||||
short st_uid;
|
||||
short st_gid;
|
||||
dev_t st_rdev;
|
||||
off_t st_size;
|
||||
time_t st_atime;
|
||||
time_t st_mtime;
|
||||
time_t st_ctime;
|
||||
};
|
||||
|
||||
#define S_IFMT 0170000 /* type of file */
|
||||
#define S_IFDIR 0040000 /* directory */
|
||||
#define S_IFCHR 0020000 /* character special */
|
||||
#define S_IFBLK 0060000 /* block special */
|
||||
#define S_IFREG 0100000 /* regular */
|
||||
#define S_IFMPC 0030000 /* multiplexed char special */
|
||||
#define S_IFMPB 0070000 /* multiplexed block special */
|
||||
#define S_ISUID 0004000 /* set user id on execution */
|
||||
#define S_ISGID 0002000 /* set group id on execution */
|
||||
#define S_ISVTX 0001000 /* save swapped text even after use */
|
||||
#define S_IREAD 0000400 /* read permission, owner */
|
||||
#define S_IWRITE 0000200 /* write permission, owner */
|
||||
#define S_IEXEC 0000100 /* execute/search permission, owner */
|
||||
|
||||
#define AR8KMAGIC 0177545
|
||||
#define EVEN 0
|
||||
#define ODD 1
|
||||
|
||||
|
||||
struct ar8k_hd {
|
||||
char ar8k_name[14];
|
||||
long ar8k_date;
|
||||
char ar8k_uid, /* not used except for compatibility */
|
||||
ar8k_gid; /* only for compatibility */
|
||||
int ar8k_mode; /* compatibility */
|
||||
long ar8k_size;
|
||||
}
|
||||
head; /* header from the old archive */
|
||||
|
||||
struct stat statbuf;
|
||||
|
||||
char **filvec, /* pointer to start of vertor of files */
|
||||
*filename, /* current file being processed */
|
||||
*archive, /* the name of the archive file */
|
||||
*tail(), /* find the real name of the file */
|
||||
filmrk[256], /* marks for up to 256 files */
|
||||
buffer[512]; /* the copying buffer */
|
||||
|
||||
char *tmpname = "ar8kxxxx.tmp";
|
||||
|
||||
int key = 0, /* one of d r q t x */
|
||||
verbose, /* set if the 'v' key is used */
|
||||
arfile, /* file number of the archive file */
|
||||
tpfile, /* file number of the temporary file */
|
||||
tmpflag = 0, /* flag set if a tempfile created */
|
||||
file, /* file number of the input or output file */
|
||||
magic = {AR8KMAGIC}, /* the output magic word */
|
||||
inmagic, /* the file magic word is read here */
|
||||
filyet, /* count of files not yet processed */
|
||||
filcnt; /* count of files in filvec to process */
|
||||
|
||||
main(argc,argv) char **argv;{
|
||||
|
||||
register i;
|
||||
register char *cp;
|
||||
|
||||
if( argc < 3 ){
|
||||
printf("usage: ar8k key archfile [files ...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cp = argv[1];
|
||||
while( i = *cp++ ) switch( i ){
|
||||
|
||||
case 'd':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 't':
|
||||
case 'x':
|
||||
if( key ) errex("only one of d q r t x allowed");
|
||||
key = i;
|
||||
continue;
|
||||
|
||||
case 'v': verbose++;
|
||||
continue;
|
||||
|
||||
default: errex("illegal key");
|
||||
}
|
||||
if( key == 0 ) errex("no key specified");
|
||||
|
||||
archive = argv[2];
|
||||
filvec = &argv[3];
|
||||
filyet = filcnt = argc-3;
|
||||
if( filcnt > 256 ) errex( "too many file names" );
|
||||
|
||||
/* now create a temporary file for the functions needing it */
|
||||
|
||||
switch( key ){
|
||||
|
||||
case 'd':
|
||||
case 'r':
|
||||
tmpflag = settmp();
|
||||
}
|
||||
|
||||
/* now open the archive for the functions needing to read it */
|
||||
|
||||
switch( key ){
|
||||
|
||||
case 'd':
|
||||
case 'r':
|
||||
case 't':
|
||||
case 'x':
|
||||
arfile = openb( archive , 0 );
|
||||
if( arfile < 0 ){ /* can't read */
|
||||
if( key != 'r' ) errex("can't read %s\n",archive );
|
||||
key = 'q';
|
||||
} else {
|
||||
chmagic( arfile );
|
||||
}
|
||||
}
|
||||
|
||||
if( key == 'q' ){ /* quick append to end */
|
||||
arfile = openb( archive , 2 );
|
||||
if( arfile < 0 ){
|
||||
arfile = creatb( archive , 0666 );
|
||||
if( arfile >= 0 ) wrmagic( arfile );
|
||||
else errex("can't append to %s",archive);
|
||||
} else {
|
||||
chmagic( arfile );
|
||||
lseek( arfile , 0L , 2 ); /* seek to end */
|
||||
}
|
||||
append( arfile );
|
||||
close(arfile);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* now do the main body of processing */
|
||||
|
||||
while( read( arfile, (char *) &head, sizeof head ) == sizeof head ){
|
||||
|
||||
switch( key ){
|
||||
|
||||
case 'd': /* deletion */
|
||||
if( inlist() ){
|
||||
comment("deleting");
|
||||
skip();
|
||||
} else {
|
||||
puthead( tpfile );
|
||||
copy( tpfile , EVEN , arfile , EVEN );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r': /* replacement */
|
||||
if( inlist() && (file = openb(filename,0)) >= 0 ){
|
||||
skip();
|
||||
getfile( tpfile , "replacing");
|
||||
} else {
|
||||
puthead( tpfile );
|
||||
copy( tpfile , EVEN , arfile , EVEN );
|
||||
}
|
||||
break;
|
||||
|
||||
case 't': /* listing */
|
||||
if( filcnt == 0 || inlist() ){
|
||||
if( verbose ){
|
||||
printf(" %7D ", head.ar8k_size );
|
||||
}
|
||||
printf("%-14.14s\n",head.ar8k_name);
|
||||
}
|
||||
skip();
|
||||
break;
|
||||
|
||||
case 'x': /* extracting */
|
||||
if( (filcnt == 0 || inlist()) &&
|
||||
(file=creatb(head.ar8k_name,0666)) >=0 ){
|
||||
comment("extracting");
|
||||
copy( file , ODD , arfile , EVEN );
|
||||
close( file );
|
||||
} else {
|
||||
skip();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* the main body of the work is done, copy the archive file back */
|
||||
|
||||
switch( key ){
|
||||
|
||||
case 'r':
|
||||
if( filyet )append( tpfile );
|
||||
|
||||
case 'd':
|
||||
close( arfile );
|
||||
arfile = creatb( archive , 0666 );
|
||||
if( arfile < 0 ){
|
||||
printf("cannot create %s\n",archive );
|
||||
} else {
|
||||
lseek( tpfile , 0L , 0 );
|
||||
while( (i = read( tpfile , buffer , 512)) > 0 )
|
||||
if( write( arfile , buffer , i ) != i )
|
||||
errex("botch in recopying the archive");
|
||||
}
|
||||
}
|
||||
if( filyet != 0 ){
|
||||
printf("\nfiles not processed:\n\n");
|
||||
for( i=0; i<filcnt; i++ )
|
||||
if( !filmrk[i] )
|
||||
printf("\t%s\n",filvec[i] );
|
||||
}
|
||||
if (tmpflag) {
|
||||
close(tpfile);
|
||||
unlink(tmpname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
settmp(){ /* create a temporary archive file */
|
||||
|
||||
close( creatb( tmpname ) , 0600 );
|
||||
tpfile = openb( tmpname , 2 );
|
||||
/* unlink( "/tmp/ar8kxxxxxxx" ); */
|
||||
if( tpfile < 0 ){
|
||||
printf("cannot create tempfile\n" );
|
||||
exit(1);
|
||||
}
|
||||
wrmagic( tpfile );
|
||||
return(1);
|
||||
}
|
||||
|
||||
wrmagic( f ){ /* write the magic word */
|
||||
|
||||
if( write( f , (char *) &magic , sizeof(int) ) != sizeof(int) )
|
||||
errex("can't write magic word\n");
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
tail( s ) char *s; {
|
||||
|
||||
register i;
|
||||
register char *t,*u;
|
||||
|
||||
for(;;){
|
||||
u = t = s;
|
||||
while( i = *u++ )
|
||||
if( i == '/' ) t = u;
|
||||
if( *t ) return( t );
|
||||
if( t == s )errex("bad file name");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
comment(s) register char *s; {
|
||||
|
||||
if( verbose ) printf("%s:\t%-14.14s\n",s,head.ar8k_name);
|
||||
}
|
||||
|
||||
|
||||
errex(s,a,b,c) char *s; {
|
||||
|
||||
printf("fatal:\t");
|
||||
printf(s,a,b,c);
|
||||
printf("\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
getfile( f , s ) char *s;{ /* make a header and copy a file to f */
|
||||
|
||||
register char *cp;
|
||||
register i;
|
||||
|
||||
|
||||
cp = tail( filename );
|
||||
fstat( file , &statbuf );
|
||||
lseek(file, 0L, 0); /* reposition at head; "fstat" */
|
||||
/* corrupts the file position. */
|
||||
head.ar8k_size = statbuf.st_size;
|
||||
head.ar8k_uid = statbuf.st_uid;
|
||||
head.ar8k_gid = statbuf.st_gid;
|
||||
head.ar8k_date = statbuf.st_mtime;
|
||||
head.ar8k_mode = statbuf.st_mode;
|
||||
for( i=0; i<14; i++ )
|
||||
if( head.ar8k_name[i] = *cp )
|
||||
cp++;
|
||||
comment( s );
|
||||
puthead( f );
|
||||
copy( f , EVEN , file , ODD );
|
||||
close( file );
|
||||
}
|
||||
|
||||
|
||||
inlist(){ /* check to see if the current header name is in the list */
|
||||
|
||||
register char *cp,*bp;
|
||||
register j;
|
||||
int i;
|
||||
|
||||
for( i=0; i<filcnt; i++ ){
|
||||
if( !filmrk[i] ){
|
||||
cp = tail( filvec[i] );
|
||||
bp = head.ar8k_name;
|
||||
for( j=0; j<14; j++ ){
|
||||
if( *cp != *bp++ ) break;
|
||||
if( *cp ) cp++;
|
||||
}
|
||||
if( j == 14 ){
|
||||
filmrk[i]++;
|
||||
filyet--;
|
||||
filename = filvec[i];
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
copy( outf, outflag , inf, inflag ){
|
||||
|
||||
|
||||
register i,j;
|
||||
|
||||
i = head.ar8k_size >> 9;
|
||||
while( --i >= 0 ){
|
||||
if( read( inf , buffer , 512 ) != 512 ) errex("bad read");
|
||||
if( write( outf , buffer , 512) != 512 ) errex("bad write");
|
||||
}
|
||||
i = head.ar8k_size;
|
||||
j = i = i & 0777;
|
||||
if( i & 1 ){ /* odd length */
|
||||
if( inflag == EVEN ) i++;
|
||||
if( outflag == EVEN ) j++;
|
||||
}
|
||||
if( i ){
|
||||
if( read( inf , buffer , i ) != i ) errex("bad read.");
|
||||
buffer[i] = 0;
|
||||
if( write( outf , buffer , j ) != j ) errex("bad write.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
skip(){ /* skip over a file */
|
||||
|
||||
long size;
|
||||
|
||||
size = head.ar8k_size;
|
||||
if( size & 1 ) size++;
|
||||
lseek( arfile , size , 1 );
|
||||
}
|
||||
|
||||
|
||||
puthead( f ){ /* write the header */
|
||||
|
||||
if( write( f , (char *) &head , sizeof head ) != sizeof head )
|
||||
errex( "header write error" );
|
||||
}
|
||||
|
||||
|
||||
append( f ){
|
||||
|
||||
register i;
|
||||
|
||||
|
||||
for( i=0; i<filcnt; i++ ){
|
||||
if( !filmrk[i] ){
|
||||
filename = filvec[i];
|
||||
if( (file = openb(filename,0)) >= 0 ){
|
||||
filmrk[i]++;
|
||||
filyet--;
|
||||
getfile( f ,"appending");
|
||||
} else {
|
||||
printf("cannot read %s\n",filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chmagic( f ){ /* check the file for the magic code */
|
||||
|
||||
read( f , (char *) &inmagic , sizeof(int) );
|
||||
if( inmagic != AR8KMAGIC ) errex("%s is not an archive",archive);
|
||||
}
|
||||
|
||||
/* Dummy fstat since we're not in UNIX anymore. The call to _filesz */
|
||||
/* has the side effect of positioning the file at the end. */
|
||||
|
||||
fstat(fd,stp)
|
||||
int fd;
|
||||
struct stat *stp;
|
||||
{
|
||||
register long fsize;
|
||||
|
||||
fsize = _filesz(fd);
|
||||
stp->st_size = fsize;
|
||||
stp->st_uid = 0;
|
||||
stp->st_gid = 0;
|
||||
stp->st_mtime = 0;
|
||||
stp->st_mode = 0666;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,598 @@
|
||||
/******************************************************************************
|
||||
*******************************************************************************
|
||||
**
|
||||
** Unidot object format to x.out convertor.
|
||||
**
|
||||
** Usage is:
|
||||
**
|
||||
** xcon [-o outfile] [-s] file.obj
|
||||
**
|
||||
** The input file (file.obj) must be in the standard Unidot object file format,
|
||||
** and its name must end with ".obj". The input file is converted into the
|
||||
** x.out format, and the result is put in the output file specified by the
|
||||
** "-o" switch. If no "-o" switch is given, the file "x.out" is created as
|
||||
** a default.
|
||||
**
|
||||
** The "-s" switch will force the output to be marked as segmented, for
|
||||
** those rare cases where xcon cannot determine that from the input file.
|
||||
**
|
||||
** Care has been taken to ensure machine independence. The output file
|
||||
** generated by this program will be correct for a Z8000 regardless of
|
||||
** the processor on which this program is run. In particular, this program
|
||||
** may be run on a PDP-11 or on a VAX without any byte swap problems in the
|
||||
** output file. One consequence of this policy is that routines are used
|
||||
** to output the various structures defined in "xout.h". If the x.out
|
||||
** file format is changed, or if "xout.h" is changed, the corresponding
|
||||
** routines will probably need changing too. The routines to check are
|
||||
** outhdr(), outrel(), outseg(), outsym(), and outtxt().
|
||||
**
|
||||
** John D. Polstra
|
||||
** September 13, 1982
|
||||
**
|
||||
*******************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#include "stdio.h"
|
||||
#include "xout.h"
|
||||
#include "obj.h"
|
||||
|
||||
/*
|
||||
* Constants.
|
||||
*/
|
||||
#define EXTMAX (RBMSK+1-RBEXT) /* Maximum number of external symbols allowed */
|
||||
#define SEGMAX 128 /* Maximum number of segments allowed */
|
||||
|
||||
/*
|
||||
* Type definitions.
|
||||
*/
|
||||
typedef unsigned short uns;
|
||||
|
||||
/*
|
||||
* Global variables.
|
||||
*/
|
||||
uns exttab[EXTMAX]; /* Mapping from external # to symbol # */
|
||||
uns *exttop = exttab; /* Pointer to top of exttab */
|
||||
|
||||
struct x_sg segtab[SEGMAX]; /* Table of information about segments */
|
||||
|
||||
struct x_hdr header; /* Header for x.out file */
|
||||
|
||||
long curoff; /* Current x.out file offset */
|
||||
long reloff; /* X.out file offset for next reloc. entry */
|
||||
long segoff[SEGMAX]; /* X.out file offsets for segments */
|
||||
long symoff; /* X.out file offset for next symbol */
|
||||
|
||||
uns symct; /* Number of symbols for the x.out file */
|
||||
|
||||
char dbgflg = 0; /* Debug output flag on =1 off =0 */
|
||||
char objbuf[255]; /* Buffer holding body of current .obj block */
|
||||
FILE *objiop; /* Standard I/O pointer for .obj file */
|
||||
char *objname; /* Name of .obj file */
|
||||
char *objpt, *objtop; /* Pointers into objbuf */
|
||||
int objtyp; /* Type of current .obj block */
|
||||
|
||||
int outfd; /* File descriptor for x.out file */
|
||||
char *outname = "x.out"; /* Name of x.out file */
|
||||
|
||||
int firstseg; /* First segment (0 or 1) actually output */
|
||||
char pass2; /* Flag set for second pass over .obj file */
|
||||
|
||||
char *prname; /* Name of this program */
|
||||
|
||||
/*
|
||||
* Here is a brief description of our section / segment numbering
|
||||
* scheme. The tables segtab[] and segoff[] are indexed by the Unidot
|
||||
* section number; thus they always have a slot for the absolute section
|
||||
* (number 0) whether it is used or not. However, we do not want to
|
||||
* output a segment descriptor for the absolute section unless it is
|
||||
* really used. So in the interlude we set the variable firstseg to
|
||||
* one iff the absolute section is used. Within the various x.out
|
||||
* outputting routines (outrel, outsym, etc.) we adjust the section numbers
|
||||
* according to the value of firstseg. The general philosophy is that
|
||||
* the outputting routines are called with Unidot section numbers; they
|
||||
* perform the necessary adjustments to produce the required x.out
|
||||
* segment numbers in the output file.
|
||||
*
|
||||
* Got it?
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function declarations.
|
||||
*/
|
||||
long lseek(); /* Move I/O pointer to new file position */
|
||||
uns ogetb(); /* Get next byte from object block */
|
||||
long ogetl(); /* Get next long from object block */
|
||||
char *ogets(); /* Get next string from object block */
|
||||
uns ogetw(); /* Get next word from object block */
|
||||
|
||||
/*
|
||||
* main - The main program consists simply of some initialization followed
|
||||
* by two processing passes, with some interlude processing in between
|
||||
* the two passes.
|
||||
*/
|
||||
main(argc, argv)
|
||||
|
||||
int argc;
|
||||
char *argv[];
|
||||
|
||||
{
|
||||
init(argc, argv);
|
||||
dopass();
|
||||
interlude();
|
||||
pass2 = 1;
|
||||
rewind(objiop);
|
||||
dopass();
|
||||
close(outfd);
|
||||
fclose(objiop);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* dopass - Performs a scan of the .obj file.
|
||||
*/
|
||||
dopass() {
|
||||
|
||||
uns action;
|
||||
uns adr;
|
||||
uns base;
|
||||
uns len;
|
||||
uns relent;
|
||||
uns relpos;
|
||||
uns sec;
|
||||
char *sym;
|
||||
int type;
|
||||
uns val;
|
||||
|
||||
header.x_nseg = 1; /* We always leave room for an absolute segment */
|
||||
if(ofill() != OBOST)
|
||||
ferr("Bad .obj file format\n");
|
||||
while(ofill() != OBOND) {
|
||||
switch(objtyp) {
|
||||
|
||||
case OBSEC: /* Sections block */
|
||||
while(objpt < objtop) {
|
||||
ogetb(); /* Discard alignment */
|
||||
ogetb(); /* Discard extent */
|
||||
ogetb(); /* Discard attributes */
|
||||
sym = ogets(); /* Get section name */
|
||||
if(pass2 && dbgflg) printf("sections %s\n",sym);
|
||||
if(!pass2) {
|
||||
/*
|
||||
* Enter a new segment into segtab.
|
||||
* Increment the number of segments
|
||||
* in the header. Also increase
|
||||
* the symbol table size to account
|
||||
* for the segment name symbol.
|
||||
*/
|
||||
segtab[header.x_nseg].x_sg_no = 255;
|
||||
if (strcmp(sym,"__text")== 0)
|
||||
segtab[header.x_nseg].x_sg_typ = X_SG_COD;
|
||||
if (strcmp(sym,"__con")== 0)
|
||||
segtab[header.x_nseg].x_sg_typ = X_SG_CON;
|
||||
if (strcmp(sym,"__data")== 0)
|
||||
segtab[header.x_nseg].x_sg_typ = X_SG_DAT;
|
||||
if (strcmp(sym,"__bss")== 0)
|
||||
segtab[header.x_nseg].x_sg_typ = X_SG_BSS;
|
||||
header.x_symb += sizeof(struct x_sym);
|
||||
symct++;
|
||||
} else
|
||||
outsym(sym, X_SY_SEG, 0, header.x_nseg);
|
||||
header.x_nseg++;
|
||||
}
|
||||
break;
|
||||
|
||||
case OBGLO: /* Global symbols block */
|
||||
if(pass2 && dbgflg) printf("global ");
|
||||
case OBLOC: /* Local symbols block */
|
||||
if(pass2 && dbgflg) printf("symbols block\n");
|
||||
while(objpt < objtop) {
|
||||
val = (uns)ogetl();
|
||||
sec = ogetb();
|
||||
sym = ogets();
|
||||
if(!pass2) {
|
||||
if(sec == RBUND) /* Enter symbol # of new external */
|
||||
*exttop++ = symct;
|
||||
header.x_symb += sizeof(struct x_sym);
|
||||
symct++;
|
||||
} else {
|
||||
type = objtyp==OBGLO ? X_SY_GLB : X_SY_LOC;
|
||||
if(sec == RBUND)
|
||||
type = X_SY_UNX;
|
||||
outsym(sym, type, val, sec);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OBTXT: /* Text block */
|
||||
adr = (uns)ogetl();
|
||||
sec = ogetb();
|
||||
len = ogetb();
|
||||
if(pass2 && dbgflg)
|
||||
printf("text section[%x] at %x for %x bytes\n",sec,adr,len);
|
||||
if(!pass2) {
|
||||
if(adr+len > segtab[sec].x_sg_len)
|
||||
segtab[sec].x_sg_len = adr+len;
|
||||
objpt += len;
|
||||
while(objpt < objtop) {
|
||||
ogetb(); /* Relocation byte number */
|
||||
relent = ogetw(); /* Relocation entry */
|
||||
header.x_reloc += sizeof(struct x_rel);
|
||||
relent &= RAMSK;
|
||||
if(relent==RAZLS || relent==RAZSS || relent==RAZOF)
|
||||
header.x_magic = X_SU_MAGIC;
|
||||
}
|
||||
} else {
|
||||
outtxt(adr, sec, objpt, len);
|
||||
objpt += len;
|
||||
while(objpt < objtop) {
|
||||
relpos = adr + ogetb() - 6;
|
||||
relent = ogetw();
|
||||
action = relent & RAMSK;
|
||||
base = relent & RBMSK;
|
||||
switch(action) {
|
||||
|
||||
case RAA32M: /* absolute 32-bit address */
|
||||
/*
|
||||
* The loader can only relocate the least
|
||||
* significant half of a 32-bit item.
|
||||
*/
|
||||
relpos += 2;
|
||||
/* Fall through to next case */
|
||||
|
||||
case RAA16M: /* absolute 16-bit address */
|
||||
case RAZOF: /* segmented offset */
|
||||
type = base<RBEXT ? X_RL_OFF : X_RL_XOF;
|
||||
break;
|
||||
|
||||
case RAZSS: /* short segmented address */
|
||||
type = base<RBEXT ? X_RL_SSG : X_RL_XSSG;
|
||||
break;
|
||||
|
||||
case RAZLS: /* long segmented address */
|
||||
type = base<RBEXT ? X_RL_LSG : X_RL_XLSG;
|
||||
break;
|
||||
|
||||
default:
|
||||
ferr("Illegal reloc. 0x%x at loc. 0x%x of sec. 0x%x\n",
|
||||
relent, relpos, sec);
|
||||
}
|
||||
outrel(type, relpos, sec, base);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ferr - Issues a fatal error message and terminates.
|
||||
*/
|
||||
ferr(a, b, c, d, e)
|
||||
|
||||
char *a;
|
||||
int b, c, d, e;
|
||||
|
||||
{
|
||||
fprintf(stderr, a, b, c, d, e);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* init - Initialization.
|
||||
*/
|
||||
init(argc, argv)
|
||||
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
char *ap;
|
||||
|
||||
prname = argv[0];
|
||||
argv[argc] = (char *)0; /* For the benefit of UNIX Version 6 */
|
||||
header.x_magic = X_NU_MAGIC;
|
||||
while(*++argv != (char *)0) {
|
||||
ap = *argv;
|
||||
if(*ap == '-') /* options */
|
||||
while(*++ap != '\0')
|
||||
switch(*ap) {
|
||||
|
||||
case 'd': /* debug flag on */
|
||||
dbgflg = 1;
|
||||
break;
|
||||
case 'o': /* Next argument is output file */
|
||||
if((outname = *++argv) == (char *)0)
|
||||
usage();
|
||||
break;
|
||||
|
||||
case 's': /* Force segmented magic number */
|
||||
header.x_magic = X_SU_MAGIC;
|
||||
break;
|
||||
|
||||
default: /* Illegal switch */
|
||||
usage();
|
||||
}
|
||||
else { /* object file name */
|
||||
if(objname != (char *)0)
|
||||
usage();
|
||||
objname = ap;
|
||||
}
|
||||
}
|
||||
|
||||
if(objname==(char *)0 || strcmp(&objname[strlen(objname)-4], ".obj")!=0)
|
||||
usage();
|
||||
if((objiop = fopenb(objname, "r")) == NULL)
|
||||
ferr("Cannot open %s\n", objname);
|
||||
if(strcmp(objname, outname) == 0)
|
||||
ferr("Would destroy %s\n", objname);
|
||||
|
||||
/*
|
||||
* The 0th entry in the segment table is the absolute segment.
|
||||
* We will output it only if some code is generated into it. If we
|
||||
* do end up outputting it, we will hard assign it to segment number 0.
|
||||
*/
|
||||
segtab[0].x_sg_typ = X_SG_BSS;
|
||||
}
|
||||
|
||||
/*
|
||||
* interlude - Performs interpass processing.
|
||||
*/
|
||||
interlude() {
|
||||
|
||||
long off;
|
||||
uns *extptr;
|
||||
int segno;
|
||||
|
||||
if(exttop == exttab) { /* No undefined externals, make executable */
|
||||
header.x_magic = header.x_magic==X_SU_MAGIC ? X_SX_MAGIC : X_NXN_MAGIC;
|
||||
outfd = creatb(outname, 0777);
|
||||
} else
|
||||
outfd = creatb(outname, 0666);
|
||||
if(outfd == -1)
|
||||
ferr("Cannot create %s\n", outname);
|
||||
|
||||
if(segtab[0].x_sg_typ==X_SG_BSS || segtab[0].x_sg_typ==X_SG_STK)
|
||||
/*
|
||||
* There is no code going into the absolute segment, so we skip it.
|
||||
*/
|
||||
firstseg = 1;
|
||||
|
||||
off = (sizeof header) + (header.x_nseg - firstseg) * sizeof(struct x_sg);
|
||||
for(segno=0 ; segno<header.x_nseg ; segno++) {
|
||||
segoff[segno] = off;
|
||||
if(segtab[segno].x_sg_typ!=X_SG_BSS &&
|
||||
segtab[segno].x_sg_typ!=X_SG_STK) {
|
||||
off += segtab[segno].x_sg_len;
|
||||
header.x_init += segtab[segno].x_sg_len;
|
||||
}
|
||||
}
|
||||
reloff = off;
|
||||
symoff = reloff + header.x_reloc;
|
||||
|
||||
curoff = 0L;
|
||||
outhdr();
|
||||
outseg();
|
||||
}
|
||||
|
||||
/*
|
||||
* ofill - Reads the next object block into objbuf, and returns the block type.
|
||||
*/
|
||||
ofill() {
|
||||
|
||||
int ch;
|
||||
|
||||
if((objtyp = getc(objiop)) == EOF) return(0);
|
||||
if((ch = getc(objiop)) == EOF) ferr("Premature EOF\n");
|
||||
objtop = &objbuf[ch];
|
||||
for(objpt=objbuf ; objpt<objtop ; objpt++) {
|
||||
if((ch = getc(objiop)) == EOF) ferr("Premature EOF\n");
|
||||
*objpt = ch;
|
||||
}
|
||||
objpt = objbuf;
|
||||
return(objtyp);
|
||||
}
|
||||
|
||||
/*
|
||||
* ogetb - Returns the next byte from the object buffer.
|
||||
*/
|
||||
uns
|
||||
ogetb() {
|
||||
|
||||
if(objpt >= objtop) {
|
||||
ferr("Off the end of objbuf\n");
|
||||
}
|
||||
return(*objpt++&0377);
|
||||
}
|
||||
|
||||
/*
|
||||
* ogetl - Returns the next long word from the object buffer.
|
||||
*/
|
||||
long
|
||||
ogetl() {
|
||||
|
||||
long l;
|
||||
|
||||
l = ogetw();
|
||||
return((long)ogetw()<<16|l);
|
||||
}
|
||||
|
||||
/*
|
||||
* ogets - Returns a pointer to the next string in the object buffer.
|
||||
*/
|
||||
char *
|
||||
ogets() {
|
||||
|
||||
char *s;
|
||||
|
||||
s = objpt; while(ogetb());
|
||||
return(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* ogetw - Returns the next word from the object buffer.
|
||||
*/
|
||||
uns
|
||||
ogetw() {
|
||||
|
||||
uns w;
|
||||
|
||||
w = ogetb();
|
||||
return(ogetb()<<8|w);
|
||||
}
|
||||
|
||||
/*
|
||||
* outb - Outputs a single byte to the .out file.
|
||||
*/
|
||||
outb(val)
|
||||
|
||||
char val;
|
||||
{
|
||||
write(outfd, &val, 1);
|
||||
curoff++;
|
||||
}
|
||||
|
||||
/*
|
||||
* outhdr - Outputs the header section of the .out file.
|
||||
*/
|
||||
outhdr()
|
||||
{
|
||||
outw(header.x_magic);
|
||||
outw(header.x_nseg - firstseg);
|
||||
outl(header.x_init);
|
||||
outl(header.x_reloc);
|
||||
outl(header.x_symb);
|
||||
}
|
||||
|
||||
/*
|
||||
* outl - Outputs a single long word to the .out file. The long word is
|
||||
* written in Z8000 (MSB first) format, regardless of the host processor.
|
||||
*/
|
||||
outl(val)
|
||||
|
||||
long val;
|
||||
{
|
||||
char buf[4];
|
||||
|
||||
buf[3] = val;
|
||||
val >>= 8;
|
||||
buf[2] = val;
|
||||
val >>= 8;
|
||||
buf[1] = val;
|
||||
val >>= 8;
|
||||
buf[0] = val;
|
||||
write(outfd, buf, 4);
|
||||
curoff += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* outrel - Outputs a relocation entry with the specified type, offset,
|
||||
* segment, and relocation base.
|
||||
*/
|
||||
outrel(type, offset, segment, base)
|
||||
|
||||
int type;
|
||||
uns offset;
|
||||
int segment;
|
||||
uns base;
|
||||
{
|
||||
if(curoff != reloff)
|
||||
lseek(outfd, curoff = reloff, 0);
|
||||
if(base >= RBEXT)
|
||||
base = exttab[base-RBEXT];
|
||||
else
|
||||
base -= firstseg;
|
||||
outb(segment - firstseg);
|
||||
outb(type);
|
||||
outw(offset);
|
||||
outw(base);
|
||||
reloff = curoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* outseg - Outputs the segments section of the .out file.
|
||||
*/
|
||||
outseg()
|
||||
{
|
||||
struct x_sg *p;
|
||||
|
||||
for(p = &segtab[firstseg] ; p < &segtab[header.x_nseg] ; p++) {
|
||||
outb(p->x_sg_no);
|
||||
outb(p->x_sg_typ);
|
||||
outw(p->x_sg_len);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* outsym - Outputs a symbol table entry with the specified name,
|
||||
* type, value, and segment.
|
||||
*/
|
||||
outsym(name, type, value, segment)
|
||||
|
||||
register char *name;
|
||||
int type;
|
||||
unsigned short value;
|
||||
int segment;
|
||||
{
|
||||
register int i;
|
||||
|
||||
if(curoff != symoff)
|
||||
lseek(outfd, curoff = symoff, 0);
|
||||
if(segment==RBABS || segment==RBUND)
|
||||
segment = 255;
|
||||
else
|
||||
segment -= firstseg;
|
||||
outb(segment);
|
||||
outb(type);
|
||||
outw(value);
|
||||
for(i=0 ; i<XNAMELN ; i++) {
|
||||
outb(*name);
|
||||
if(*name != '\0')
|
||||
name++;
|
||||
}
|
||||
symoff = curoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* outtxt - Outputs a block of text for the specified offset in the specified
|
||||
* segment. The text comes from txtptr and has txtct bytes.
|
||||
*/
|
||||
outtxt(offset, segment, txtptr, txtct)
|
||||
|
||||
uns offset;
|
||||
int segment;
|
||||
char *txtptr;
|
||||
int txtct;
|
||||
{
|
||||
long txtoff;
|
||||
|
||||
txtoff = segoff[segment] + (long)offset;
|
||||
if(curoff != txtoff)
|
||||
lseek(outfd, curoff = txtoff, 0);
|
||||
write(outfd, txtptr, txtct);
|
||||
curoff += txtct;
|
||||
}
|
||||
|
||||
/*
|
||||
* outw - Outputs a single word to the .out file. The word is written in
|
||||
* Z8000 (MSB first) format, regardless of the host processor.
|
||||
*/
|
||||
outw(val)
|
||||
|
||||
uns val;
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
buf[1] = val;
|
||||
val >>= 8;
|
||||
buf[0] = val;
|
||||
write(outfd, buf, 2);
|
||||
curoff += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* usage - Issues a fatal error message for incorrect usage.
|
||||
*/
|
||||
usage() {
|
||||
|
||||
ferr("Usage: %s [-o x.out] [-s] file.obj\n", prname);
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
|
||||
/* quickie program to dump x.out files */
|
||||
|
||||
#include "stdio.h"
|
||||
#include "x.out.h"
|
||||
|
||||
struct x_hdr x_hdr;
|
||||
struct x_sg x_sg[10];
|
||||
struct x_rel x_rel;
|
||||
struct x_sym x_sym;
|
||||
short sbuf[2048];
|
||||
|
||||
char *segtypes[] {
|
||||
"unknown",
|
||||
"bss",
|
||||
"stack",
|
||||
"code",
|
||||
"constant pool",
|
||||
"initialized data",
|
||||
"mixed code/data, not protectable",
|
||||
"mixed code/data, protectable"
|
||||
};
|
||||
|
||||
int floc,
|
||||
bigs,
|
||||
dflag = {1}, /* dump init data */
|
||||
rflag = {1}, /* dump relocation data */
|
||||
sflag = {1}; /* dump symbol table data */
|
||||
|
||||
main( argc, argv ) char **argv; {
|
||||
|
||||
register i,
|
||||
j,
|
||||
k,
|
||||
l;
|
||||
unsigned len,
|
||||
offset;
|
||||
|
||||
i = 1;
|
||||
if( i < argc && argv[i][0] == '-' ) doargs( argv[i++] );
|
||||
if( i < argc ){
|
||||
close( 0 );
|
||||
if( openb( argv[i] , 0 ) != 0 ){
|
||||
printf(stderr,"cannot open '%s'\n",argv[i] );
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
read( 0 , &x_hdr , sizeof( x_hdr ) );
|
||||
if( !bigs )fprintf( stdout,
|
||||
"magic = %x nseg = %d init = %ld reloc = %ld symb = %ld\n",
|
||||
x_hdr.x_magic,
|
||||
x_hdr.x_nseg,
|
||||
x_hdr.x_init,
|
||||
x_hdr.x_reloc,
|
||||
x_hdr.x_symb );
|
||||
floc = sizeof( x_hdr );
|
||||
for( i=0; i<x_hdr.x_nseg; i++ ){
|
||||
read( 0 , &x_sg[i] , sizeof( x_sg[0] ) );
|
||||
if( !bigs )fprintf( stdout,
|
||||
"%4x sg[%d]: sgno = %d typ = %d len = %u\n",
|
||||
floc,
|
||||
i,
|
||||
x_sg[i].x_sg_no & 0377,
|
||||
x_sg[i].x_sg_typ & 0377,
|
||||
x_sg[i].x_sg_len );
|
||||
floc += sizeof( x_sg[0] );
|
||||
}
|
||||
for( i=0; i<x_hdr.x_nseg; i++ ){ /* dump the segments */
|
||||
k = x_sg[i].x_sg_typ;
|
||||
if( !bigs )
|
||||
fprintf( stdout, "segment %d\ttype is %s\n",
|
||||
i, segtypes[k]);
|
||||
if( k == X_SG_BSS || k == X_SG_STK ){
|
||||
if( !bigs )fprintf(stdout,"\nNo initialization");
|
||||
} else {
|
||||
len = x_sg[i].x_sg_len;
|
||||
offset = 0;
|
||||
while(len>0) {
|
||||
l = (len>4096)?4096:len;
|
||||
j = read( 0, sbuf, l );
|
||||
if( j != l ){
|
||||
fprintf(stdout,
|
||||
"unexpected eof: length is %u\n",
|
||||
offset + j);
|
||||
j = 0;
|
||||
}
|
||||
for( k = 0; k<j; offset += 2, k += 2 ){
|
||||
if( dflag ){
|
||||
if( (k & 017) == 0 )
|
||||
fprintf(stdout,"\n%4x %5d %4x ",
|
||||
floc,offset,offset);
|
||||
puth( sbuf[ k>>1 ] );
|
||||
}
|
||||
floc += 2;
|
||||
}
|
||||
len -= l;
|
||||
}
|
||||
}
|
||||
if( dflag ) fprintf(stdout,"\n\n" );
|
||||
}
|
||||
if(x_hdr.x_reloc && rflag && !bigs)
|
||||
fprintf(stdout,"floc sgn flg loc bas\n");
|
||||
for( i=0; i<x_hdr.x_reloc; i += sizeof( x_rel ) ){
|
||||
if( read( 0 , &x_rel, sizeof( x_rel ) ) != sizeof(x_rel)) eof();
|
||||
if( rflag ) fprintf(stdout,
|
||||
"%4x %4d%4d%6d%6d\n",
|
||||
floc,
|
||||
x_rel.x_rl_sgn & 0377,
|
||||
x_rel.x_rl_flg & 0377,
|
||||
x_rel.x_rl_loc,
|
||||
x_rel.x_rl_bas );
|
||||
floc += sizeof( x_rel );
|
||||
}
|
||||
if( sflag || bigs ){
|
||||
if( !bigs )fprintf(stdout,"\nsymbols: \n\n");
|
||||
for( i=0; i<x_hdr.x_symb; i+= sizeof( x_sym ) ){
|
||||
if(read(0, &x_sym, sizeof(x_sym)) != sizeof( x_sym ))
|
||||
eof();
|
||||
if( !bigs )fprintf(stdout,
|
||||
"%4x %4d%4d",
|
||||
floc,
|
||||
x_sym.x_sy_sg & 0377,
|
||||
x_sym.x_sy_fl & 0377);
|
||||
fprintf(stdout,"%6x %.8s\n",
|
||||
x_sym.x_sy_val,
|
||||
x_sym.x_sy_name );
|
||||
floc += sizeof( x_sym );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
doargs( s ) register char *s; {
|
||||
|
||||
sflag = dflag = rflag = 0;
|
||||
for(;;) switch( *s++ ){
|
||||
|
||||
case 0: return;
|
||||
case 'd': dflag++; continue;
|
||||
case 'r': rflag++; continue;
|
||||
case 'S': bigs++;
|
||||
case 's': sflag++; continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char hextab[] {"0123456789abcdef"};
|
||||
puth( n ){ /* put out a word in hex */
|
||||
|
||||
register i;
|
||||
|
||||
putchar( ' ' );
|
||||
for( i=12; i>= 0; i -= 4 ) putchar( hextab[ (n>>i) & 017 ] );
|
||||
}
|
||||
|
||||
|
||||
eof(){
|
||||
|
||||
fprintf(stdout,"\n\n*****unexpected eof*****\n");
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
struct x_hdr {
|
||||
short x_magic; /* magic number */
|
||||
short x_nseg; /* number of segments in file */
|
||||
long x_init; /* length of initialized part of file */
|
||||
long x_reloc; /* length of relocation part of file */
|
||||
long x_symb; /* length of symbol table part of file */
|
||||
};
|
||||
|
||||
|
||||
struct x_sg {
|
||||
char x_sg_no; /* assigned number of segment */
|
||||
char x_sg_typ; /* type of segment */
|
||||
unsigned x_sg_len; /* length of segment */
|
||||
}; /* x_sg[] is an array of size x_nseg */
|
||||
|
||||
|
||||
#define X_SU_MAGIC 0xEE00 /* segmented, non executable */
|
||||
#define X_SX_MAGIC 0xEE01 /* segmented, executable */
|
||||
#define X_NU_MAGIC 0xEE02 /* non-segmented, non executable */
|
||||
#define X_NXN_MAGIC 0xEE03 /* non-segmented, executable, non-shared */
|
||||
#define X_NUS_MAGIC 0xEE06 /* non-segmented, non executable, shared */
|
||||
#define X_NXS_MAGIC 0xEE07 /* non-segmented, executable, shared */
|
||||
#define X_NUI_MAGIC 0xEE0A /* non-segmented, non executable, split ID */
|
||||
#define X_NXI_MAGIC 0xEE0B /* non-segmented, executable, split ID */
|
||||
|
||||
#define X_SG_BSS 1 /* non-initialized data segment */
|
||||
#define X_SG_STK 2 /* stack segment, no data in file */
|
||||
#define X_SG_COD 3 /* code segment */
|
||||
#define X_SG_CON 4 /* constant pool */
|
||||
#define X_SG_DAT 5 /* initialized data */
|
||||
#define X_SG_MXU 6 /* mixed code and data, not protectable */
|
||||
#define X_SG_MXP 7 /* mixed code and data, protectable */
|
||||
|
||||
struct x_rel { /* relocation item */
|
||||
char x_rl_sgn; /* segment containing item to be relocated */
|
||||
char x_rl_flg; /* relocation type (see below) */
|
||||
unsigned x_rl_loc; /* location of item to be relocated */
|
||||
unsigned x_rl_bas; /* number of (external) element in symbol table
|
||||
or (internal) segment by which to relocate */
|
||||
};
|
||||
|
||||
|
||||
#define X_RL_OFF 1 /* adjust a 16 bit offset value only */
|
||||
#define X_RL_SSG 2 /* adjust a short form segment plus offset */
|
||||
#define X_RL_LSG 3 /* adjust a long form (32 bit) seg plus off */
|
||||
#define X_RL_XOF 5 /* adjust a 16 bit offset by an external */
|
||||
#define X_RL_XSSG 6 /* adjust a short seg ref by an external */
|
||||
#define X_RL_XLSG 7 /* adjust a long seg ref by an external */
|
||||
|
||||
#define XNAMELN 8 /* length of a symbol */
|
||||
|
||||
struct x_sym {
|
||||
char x_sy_sg; /* the segment number */
|
||||
char x_sy_fl; /* the type of entry */
|
||||
unsigned x_sy_val; /* the value of this entry */
|
||||
char x_sy_name[XNAMELN]; /* the symbol name, padded with 0's */
|
||||
};
|
||||
|
||||
#define X_SY_LOC 1 /* local symbol (for debug only) */
|
||||
#define X_SY_UNX 2 /* undefined external entry */
|
||||
#define X_SY_GLB 3 /* global definition */
|
||||
#define X_SY_SEG 4 /* segmenIq
|
||||
|
||||
|
||||
This directory contains the source and object files for the Z8000 CP/M Ccp,
|
||||
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* B A S E P A G E . H */
|
||||
/* ------------------- */
|
||||
/* */
|
||||
/* This file contains a definition of the CP/M basepage structure, */
|
||||
/* b_page. */
|
||||
/* */
|
||||
/* NOTE: In the portable CP/M environment, it is NOT guaranteed */
|
||||
/* that the location of the base page is known at link-edit time */
|
||||
/* (as it is, for example, in CP/M-80 and CP/M-86.) Instead, a */
|
||||
/* pointer to the current basepage is delivered by the BDOS */
|
||||
/* to each new program which is run. This pointer, _base, is */
|
||||
/* initialized by the C startup function (startup.s) and is */
|
||||
/* available to C programs as an external. */
|
||||
/* */
|
||||
/* This file has been modified to live with the BDOS definitions. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct b_page
|
||||
{
|
||||
XADDR ltpa; /* Low TPA address */
|
||||
XADDR htpa; /* High TPA address */
|
||||
XADDR lcode; /* Start address of code seg*/
|
||||
long codelen; /* Code segment length */
|
||||
XADDR ldata; /* Start address of data seg*/
|
||||
long datalen; /* Data segment length */
|
||||
XADDR lbss; /* Start address of bss seg */
|
||||
long bsslen; /* Bss segment length */
|
||||
long freelen; /* Free segment length */
|
||||
char resvd1[20]; /* Reserved area */
|
||||
struct fcb fcb2; /* Second basepage FCB */
|
||||
struct fcb fcb1; /* First basepage FCB */
|
||||
char buff[128]; /* Default DMA buffer, */
|
||||
/* command line tail */
|
||||
};
|
||||
@@ -0,0 +1,367 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* B D O S . H */
|
||||
/* ----------- */
|
||||
/* */
|
||||
/* Copyright (c) 1982, Zilog Incorporated */
|
||||
/* */
|
||||
/* Macros defining the direct BDOS calls used by the standard CP/M */
|
||||
/* utilities (ED, PIP, STAT, SET, SHOW.) Some necessary data */
|
||||
/* data structures are also defined. */
|
||||
/* */
|
||||
/* All macros return a long value, even when the BDOS function they */
|
||||
/* call does produce a return parameter. */
|
||||
/* */
|
||||
/* This header file can be used applications which do not require */
|
||||
/* to use the C standard I/O library functions. For applications */
|
||||
/* which require the library, but which wish to make use of the */
|
||||
/* additional information in this file, cpm.h should be included in */
|
||||
/* the source ahead of this file. The compiler flags multiple */
|
||||
/* definition errors if this ordering is not observed. */
|
||||
/* */
|
||||
/* portab.h must always be included ahead of this file. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
extern long __BDOS(); /* BDOS entry point */
|
||||
|
||||
#define XADDR long /* 32-bit address data type */
|
||||
|
||||
/****************************************************************************/
|
||||
/* The following BDOS calls are defined in cpm.h. Define them only if they */
|
||||
/* are not defined already. */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef EXIT /* Find out where we stand */
|
||||
/* Define if necessary */
|
||||
#define EXIT 0 /* Exit to BDOS */
|
||||
#define CONOUT 2 /* Direct console output */
|
||||
#define LSTOUT 5 /* Direct list device output*/
|
||||
#define CONIO 6 /* Direct console I/O */
|
||||
#define CONBUF 10 /* Read console buffer */
|
||||
#define OPEN 15 /* OPEN a disk file */
|
||||
#define CLOSE 16 /* Close a disk file */
|
||||
#define DELETE 19 /* Delete a disk file */
|
||||
#define CREATE 22 /* Create a disk file */
|
||||
#define SETDMA 26 /* Set DMA address */
|
||||
#define B_READ 33 /* Read Random record */
|
||||
#define B_WRITE 34 /* Write Random record */
|
||||
#define FILSIZ 35 /* Compute File Size */
|
||||
#define SETMSC 44 /* Set Multi-Sector Count */
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* The following BDOS calls are not defined in cpm.h */
|
||||
/****************************************************************************/
|
||||
|
||||
#define CONIN 1 /* Single char I/P with echo*/
|
||||
#define READER 3 /* Paper tape input */
|
||||
#define PUNCH 4 /* Paper tape output */
|
||||
#define GET_IOB 7 /* Get I/O byte */
|
||||
#define SET_IOB 8 /* Set I/O byte */
|
||||
#define PRINT 9 /* Print $-terminated line */
|
||||
#define CONSTAT 11 /* Check if I/P char waiting*/
|
||||
#define VERSION 12 /* Return version number */
|
||||
#define RS_DISK 13 /* Reset disk system */
|
||||
#define SEL_DISK 14 /* Select disk */
|
||||
#define SRCH_1ST 17 /* Search 1st filename match*/
|
||||
#define SRCH_NEXT 18 /* Search next match */
|
||||
#define S_READ 20 /* Sequential read from file*/
|
||||
#define S_WRITE 21 /* Sequential write to file */
|
||||
#define RENAME 23 /* Rename a file */
|
||||
#define RET_LOGIN 24 /* Return login vector */
|
||||
#define RET_CDISK 25 /* Return current disk */
|
||||
#define GET_ALLOC 27 /* Get allocation vector */
|
||||
#define WR_PROTD 28 /* Write protect disk */
|
||||
#define GET_RO 29 /* Get read-only vector */
|
||||
#define SET_ATT 30 /* Set file attributes */
|
||||
#define GET_DPB 31 /* Get disk parameters */
|
||||
#define GSET_UCODE 32 /* Get/set user code */
|
||||
#define SET_RAND 36 /* Set random record */
|
||||
#define RS_DRIVE 37 /* Reset disk specified drv */
|
||||
/* 38, 39 not used */
|
||||
#define B_WRZF 40 /* Write random, zero fill */
|
||||
/* 41 - 43 not used */
|
||||
#define RET_ERRORS 45 /* Set error return mode */
|
||||
#define GET_DFS 46 /* Get free disk space */
|
||||
#define CHAIN 47 /* Chain to program via CCP */
|
||||
#define FLUSH 48 /* Flush buffers to disk */
|
||||
#define GSET_SCB 49 /* Get/set system control bk*/
|
||||
#define BIOS_CALL 50 /* Direct call to BIOS */
|
||||
/* 51 - 58 not used */
|
||||
#define PROG_LOAD 59 /* Program load */
|
||||
/* 60 unused */
|
||||
#define SET_EXV 61 /* Set exception vector */
|
||||
#define SET_SUP 62 /* Set supervisor state */
|
||||
#define SET_LABEL 100 /* Set directory label */
|
||||
#define GET_LABEL 101 /* Get directory label */
|
||||
#define GET_XFCB 102 /* Get extended FCB */
|
||||
#define SET_XFCB 103 /* Set extended FCB */
|
||||
#define COND_LST 161 /* Conditionally attach LST:*/
|
||||
|
||||
/****************************************************************************/
|
||||
/* The macros themselves... */
|
||||
/****************************************************************************/
|
||||
|
||||
#define _conin() (__BDOS(CONIN, (long) 0))
|
||||
|
||||
#define _conout(a) (__BDOS(CONOUT, (long) (a)))
|
||||
|
||||
#define _reader() (__BDOS(READER, (long) 0))
|
||||
|
||||
#define _punch(a) (__BDOS(PUNCH, (long) (a)))
|
||||
|
||||
#define _lstout(a) (__BDOS(LSTOUT, (long) (a)))
|
||||
|
||||
#define _conio(a) (__BDOS(CONIO, (long) (a)))
|
||||
|
||||
#define _get_iob() (__BDOS(GET_IOB, (long) 0))
|
||||
|
||||
#define _set_iob(a) (__BDOS(SET_IOB, (long) (a)))
|
||||
|
||||
#define _print(a) (__BDOS(PRINT, (long) (a)))
|
||||
|
||||
#define _conbuf(a) (__BDOS(CONBUF, (long) (a)))
|
||||
|
||||
#define _constat() (__BDOS(CONSTAT, (long) 0))
|
||||
|
||||
#define _version() (__BDOS(VERSION, (long) 0))
|
||||
|
||||
#define _rs_disk(a) (__BDOS(RS_DISK, (long) (a)))
|
||||
|
||||
#define _sel_disk(a) (__BDOS(SEL_DISK, (long) (a)))
|
||||
|
||||
#define _open(a) (__BDOS(OPEN, (long) (a)))
|
||||
|
||||
#define _close(a) (__BDOS(CLOSE, (long) (a)))
|
||||
|
||||
#define _srch_1st(a) (__BDOS(SRCH_1ST, (long) (a)))
|
||||
|
||||
#define _srch_next() (__BDOS(SRCH_NEXT, (long) 0))
|
||||
|
||||
#define _delete(a) (__BDOS(DELETE, (long) (a)))
|
||||
|
||||
#define _s_read(a) (__BDOS(S_READ, (long) (a)))
|
||||
|
||||
#define _s_write(a) (__BDOS(S_WRITE, (long) (a)))
|
||||
|
||||
#define _create(a) (__BDOS(CREATE, (long) (a)))
|
||||
|
||||
#define _rename(a) (__BDOS(RENAME, (long) (a)))
|
||||
|
||||
#define _ret_login() (__BDOS(RET_LOGIN, (long) 0))
|
||||
|
||||
#define _ret_cdisk() (__BDOS(RET_CDISK, (long) 0))
|
||||
|
||||
#define _setdma(a) (__BDOS(SETDMA, (long) (a)))
|
||||
|
||||
#define _get_alloc() (__BDOS(GET_ALLOC, (long) 0))
|
||||
|
||||
#define _wr_protd() (__BDOS(WR_PROTD, (long) 0))
|
||||
|
||||
#define _get_ro() (__BDOS(GET_RO, (long) 0))
|
||||
|
||||
#define _set_att(a) (__BDOS(SET_ATT, (long) (a)))
|
||||
|
||||
/* _get_dpb has parameter in*/
|
||||
/* some implementations */
|
||||
/* of CP/M but not others */
|
||||
/* This macro suitable only */
|
||||
/* for former */
|
||||
#define _get_dpb(a) (__BDOS(GET_DPB, (long) (a)))
|
||||
/* This one handles latter */
|
||||
#define _get_dpa() (__BDOS(GET_DPB, (long) 0))
|
||||
|
||||
#define _gset_ucode(a) (__BDOS(GSET_UCODE, (long) (a)))
|
||||
|
||||
#define _b_read(a) (__BDOS(B_READ, (long) (a)))
|
||||
|
||||
#define _b_write(a) (__BDOS(B_WRITE, (long) (a)))
|
||||
|
||||
#define _filsiz(a) (__BDOS(FILSIZ, (long) (a)))
|
||||
|
||||
#define _set_rand(a) (__BDOS(SET_RAND, (long) (a)))
|
||||
|
||||
#define _rs_drive(a) (__BDOS(RS_DRIVE, (long) (a)))
|
||||
|
||||
#define _b_wrzf(a) (__BDOS(B_WRZF, (long) (a)))
|
||||
|
||||
#define _setmsc(a) (__BDOS(SETMSC, (long) (a)))
|
||||
|
||||
#define _ret_errors(a) (__BDOS(RET_ERRORS, (long) (a)))
|
||||
|
||||
#define _get_dfs(a) (__BDOS(GET_DFS, (long) (a)))
|
||||
|
||||
#define _chain() (__BDOS(CHAIN, (long) 0))
|
||||
|
||||
#define _flush() (__BDOS(FLUSH, (long) 0))
|
||||
|
||||
#define _gset_scb(a) (__BDOS(GSET_SCB, (long) (a)))
|
||||
|
||||
#define _bios_call(a) (__BDOS(BIOS_CALL, (long) (a)))
|
||||
|
||||
#define _prog_load(a) (__BDOS(PROG_LOAD, (long) (a)))
|
||||
|
||||
#define _set_exv(a) (__BDOS(SET_EXV, (long) (a)))
|
||||
|
||||
#define _set_sup(a) (__BDOS(SET_SUP, (long) 0))
|
||||
|
||||
#define _get_label(a) (__BDOS(GET_LABEL, (long) (a)))
|
||||
|
||||
#define _set_label(a) (__BDOS(SET_LABEL, (long) (a)))
|
||||
|
||||
#define _get_xfcb(a) (__BDOS(GET_XFCB, (long) (a)))
|
||||
|
||||
#define _set_xfcb(a) (__BDOS(SET_XFCB, (long) (a)))
|
||||
|
||||
#define _cond_lst() (__BDOS(COND_LST, (long) 0))
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* BIOS calls, for use in conjunction with BDOS call 50 & struct bios_parms */
|
||||
/****************************************************************************/
|
||||
|
||||
#define _INIT 0 /* Cold start */
|
||||
#define _WARM 1 /* Warm start */
|
||||
#define _CONST 2 /* Console status */
|
||||
#define _CONIN 3 /* Read console character */
|
||||
#define _CONOUT 4 /* Write console character */
|
||||
#define _LIST 5 /* Write listing character */
|
||||
#define _PUNCH 6 /* Write punch character */
|
||||
#define _READER 7 /* Read tape character */
|
||||
#define _HOME 8 /* Move to track 0 */
|
||||
#define _SELDSK 9 /* Select disk drive */
|
||||
#define _SETTRK 10 /* Set track number */
|
||||
#define _SETSEC 11 /* Set sector number */
|
||||
#define _SETDMA 12 /* Set DMA address */
|
||||
#define _READ 13 /* Read selected sector */
|
||||
#define _WRITE 14 /* Write selected sector */
|
||||
#define _LISTST 15 /* Return list status */
|
||||
#define _GETMRT 16 /* Get memory region table */
|
||||
/* address */
|
||||
#define _GETIOB 17 /* Get IOBYTE value */
|
||||
#define _SETIOB 18 /* Set IOBYTE value */
|
||||
#define _FLUSH 19 /* Flush buffers */
|
||||
#define _SETEXC 20 /* Set exception vector */
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* FCB structure is defined in cpm.h. Define it here only if it is not */
|
||||
/* defined already. Declare some useful values at the same time. */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef SECSIZ /* Not already declared? */
|
||||
|
||||
struct fcbtab /* File control block */
|
||||
{ /* */
|
||||
BYTE drive; /* Disk drive field */
|
||||
BYTE fname[8]; /* File name */
|
||||
BYTE ftype[3]; /* File type */
|
||||
BYTE extent; /* Current extent number */
|
||||
BYTE s1,s2; /* "system reserved" */
|
||||
BYTE reccnt; /* Record counter */
|
||||
BYTE resvd[16]; /* More "system reserved" */
|
||||
LONG record; /* Note -- we overlap the */
|
||||
/* current record field to */
|
||||
/* make this useful. */
|
||||
};
|
||||
|
||||
#define fcb fcbtab /* A useful synonym */
|
||||
#define SECSIZ 128 /* size of CP/M sector */
|
||||
#define _MAXSXFR 1 /* max # sectors xferrable */
|
||||
#define _MAXSHFT 12 /* shift right BDOS rtn val */
|
||||
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* Data structures not defined in cpm.h */
|
||||
/****************************************************************************/
|
||||
|
||||
struct dpbs /* Disk parameter block */
|
||||
{
|
||||
UWORD spt; /* Sectors per track */
|
||||
BYTE bls; /* Block shift factor */
|
||||
BYTE bms; /* Block mask */
|
||||
BYTE exm; /* Extent mark */
|
||||
/* BYTE filler; *** Pad to align words ***/
|
||||
UWORD mxa; /* Maximum allocation (blks)*/
|
||||
UWORD dmx; /* Max directory entries */
|
||||
UWORD dbl; /* Directory alloc. map */
|
||||
UWORD cks; /* Directory checksum */
|
||||
UWORD ofs; /* Track offset from track 0*/
|
||||
};
|
||||
|
||||
struct bios_parm /* BIOS parameters for BDOS */
|
||||
{ /* call 50 */
|
||||
UWORD req; /* BIOS request code */
|
||||
LONG p1; /* First parameter */
|
||||
LONG p2; /* Second parameter */
|
||||
};
|
||||
|
||||
struct scbs /* System control block */
|
||||
{
|
||||
BYTE resvd_1[6]; /* Reserved for system use */
|
||||
BYTE u_flags[4]; /* Utility flags */
|
||||
BYTE d_flags[4]; /* Display flags */
|
||||
BYTE clp_flags[2]; /* Command Line Proc flags */
|
||||
UWORD p_error; /* Program error return code*/
|
||||
BYTE resvd_2[8]; /* Reserved for system use */
|
||||
BYTE con_w; /* Console width */
|
||||
BYTE con_c; /* Console column */
|
||||
BYTE con_l; /* Console page length */
|
||||
BYTE resvd_3[5]; /* Reserved for system use */
|
||||
UWORD conin_r; /* CONIN redirection flag */
|
||||
UWORD conout_r; /* CONOUT redirection flag */
|
||||
UWORD auxin_r; /* AUXIN redirection flag */
|
||||
UWORD auxout_r; /* AUXOUT redirection flag */
|
||||
UWORD lstout_r; /* LSTOUT redirection flag */
|
||||
BYTE resvd_4[2]; /* Reserved for system use */
|
||||
BOOLEAN ctl_h_a; /* Backspace active */
|
||||
BOOLEAN rubout_a; /* Rubout active */
|
||||
BYTE resvd_5[2]; /* Reserved for system use */
|
||||
UWORD c_xlate; /* Console translate func. */
|
||||
UWORD con_m; /* Console mode (raw/cooked)*/
|
||||
UWORD buff_a; /* 128 byte buffer available*/
|
||||
BYTE o_delim; /* Output delimiter */
|
||||
BOOLEAN lo_flag; /* List output flag */
|
||||
BYTE resvd_6[2]; /* Reserved for system use */
|
||||
UWORD d_m_a; /* Current DMA address */
|
||||
BYTE disk_no; /* Current disk */
|
||||
BYTE bdos_info[2]; /* BDOS variable info */
|
||||
BYTE resvd_7[3]; /* Reserved for system use */
|
||||
BYTE user_no; /* Current user number */
|
||||
BYTE resvd_8[6]; /* Reserved for system use */
|
||||
BYTE bdos_mode; /* BDOS error mode */
|
||||
BYTE c_chain[4]; /* Current search chain */
|
||||
BYTE tmp_drv; /* Drive for temporary files*/
|
||||
BYTE resvd_9[7]; /* Reserved for system use */
|
||||
BYTE date_s[5]; /* Date stamp */
|
||||
BYTE error_jmp[3]; /* Error jump */
|
||||
UWORD cmb_a; /* Common memory base addr */
|
||||
UWORD bdos_ent; /* BDOS entry point */
|
||||
};
|
||||
|
||||
struct scbpb /* SCB parameter block */
|
||||
{
|
||||
BYTE off; /* Index to data in SCB */
|
||||
BYTE op; /* Operation: 0xff Set byte */
|
||||
/* 0xfe Set word */
|
||||
/* else Get word */
|
||||
UWORD val; /* Byte/word value to be set*/
|
||||
};
|
||||
|
||||
#define SET_BYTE 0xff
|
||||
#define SET_WORD 0xfe
|
||||
#define GET 0
|
||||
|
||||
/****************************************************************************/
|
||||
/* HILO must be defined for the Z8000. Undefine it first, in case cpm.h */
|
||||
/* has already defined it. The tagless structures defining byte ordering */
|
||||
/* which are declared in cpm.h are not redeclared here (the use of members */
|
||||
/* of tagless structures to define offsets is an obsolete feature of the C */
|
||||
/* language.) */
|
||||
/****************************************************************************/
|
||||
|
||||
#undef HILO
|
||||
#define HILO
|
||||
@@ -0,0 +1,171 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* P-CP/M header file *
|
||||
* Copyright (c) 1982 by Digital Research, Inc. *
|
||||
* Structure definitions for BDOS globals *
|
||||
* and BDOS data structures *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
The BDOS data structures, especially those relating to global variables,
|
||||
are structured in a way that hopefully will enable this BDOS, in the future,
|
||||
to easily become a re-entrant multi-tasking file system. Consequently,
|
||||
the BDOS global variables are divided into two classes. Those that are
|
||||
truly global, even in the case of multiple tasks using the file system
|
||||
concurrently, are simply declared as global variables in bdosmain.c.
|
||||
Only a few "globals" are really global in this sense.
|
||||
|
||||
The majority of the "global" variables are actually state variables that
|
||||
relate to the state of the task using the file system. In CP/M-68K, these
|
||||
are "global", since there's only one task, but in a multi-thread model they're
|
||||
not. These type of variables are put into a data structure, with the
|
||||
intention that in the multi-task environment this structure will be based.
|
||||
|
||||
The following declarations take this philosophy into account, and define
|
||||
a simple structure for the single thread environment while leaving the
|
||||
possibilities open for the multi-thread environment.
|
||||
****************************************************************************/
|
||||
|
||||
#define snglthrd TRUE
|
||||
/* TRUE for single-thread environment
|
||||
undefined to create based structure for re-entrant model */
|
||||
#ifdef snglthrd
|
||||
#define GBL gbls
|
||||
/* In single thread case, GBL just names
|
||||
the structure */
|
||||
#define BSETUP EXTERN struct stvars gbls;
|
||||
/* and BSETUP defines the extern structure */
|
||||
#else
|
||||
|
||||
#define GBL (*statep)
|
||||
/* If multi-task, state vars are based */
|
||||
#define BSETUP REG struct stvars *statep; \
|
||||
statep = &gbls;
|
||||
/* set up pointer to state variables */
|
||||
/* This is intended as an example to show the intent */
|
||||
#endif
|
||||
|
||||
|
||||
/* Note that there are a few critical regions in the file system that must
|
||||
execute without interruption. They pertain mostly to the manipulation of
|
||||
the allocation vector. This isn't a problem in a single-thread model, but
|
||||
must be provided for in a multi-tasking file system. Consequently, the
|
||||
primitives LOCK and UNLOCK are defined and used where necessary in the
|
||||
file system. For the single thread model, they are null routines */
|
||||
|
||||
#define LOCK /**/
|
||||
#define UNLOCK /**/
|
||||
/* Be sure LOCK and UNLOCK are implemented to allow recursive calls to LOCK.
|
||||
That is, if a process that calls LOCK already owns the lock, let it proceed,
|
||||
but remember that only the outer-most call to UNLOCK really releases the
|
||||
file system. */
|
||||
|
||||
|
||||
#define VERSION 0x2022 /* Version number for CP/M-68K */
|
||||
#define robit 0 /* read-only bit in file type field of fcb */
|
||||
#define arbit 2 /* archive bit in file type field of fcb */
|
||||
#define SECLEN 128 /* length of a CP/M sector */
|
||||
|
||||
|
||||
union smallbig
|
||||
{
|
||||
UBYTE small[16]; /* 16 block numbers of 1 byte */
|
||||
WORD big[8]; /* or 8 block numbers of 1 word */
|
||||
};
|
||||
|
||||
/* File Control Block definition */
|
||||
struct fcb
|
||||
{
|
||||
UBYTE drvcode; /* 0 = default drive, 1..16 are drives A..P */
|
||||
UBYTE fname[8]; /* File name (ASCII) */
|
||||
UBYTE ftype[3]; /* File type (ASCII) */
|
||||
UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
UBYTE s1; /* Reserved */
|
||||
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
union smallbig dskmap;
|
||||
UBYTE cur_rec; /* current record field */
|
||||
UBYTE ran0; /* random record field (3 bytes) */
|
||||
UBYTE ran1;
|
||||
UBYTE ran2;
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of directory entry */
|
||||
struct dirent
|
||||
{
|
||||
UBYTE entry; /* 0 - 15 for user numbers, E5 for empty */
|
||||
/* the rest are reserved */
|
||||
UBYTE fname[8]; /* File name (ASCII) */
|
||||
UBYTE ftype[3]; /* File type (ASCII) */
|
||||
UBYTE extent; /* Extent number (bits 0..4 used) */
|
||||
UBYTE s1; /* Reserved */
|
||||
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
|
||||
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
|
||||
union smallbig dskmap;
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of disk parameter tables */
|
||||
struct dpb /* disk parameter table */
|
||||
{
|
||||
UWORD spt; /* sectors per track */
|
||||
UBYTE bsh; /* block shift factor */
|
||||
UBYTE blm; /* block mask */
|
||||
UBYTE exm; /* extent mask */
|
||||
UBYTE dpbdum; /* dummy byte for fill */
|
||||
UWORD dsm; /* max disk size in blocks */
|
||||
UWORD drm; /* max directory entries */
|
||||
UWORD dir_al; /* initial allocation for dir */
|
||||
UWORD cks; /* number dir sectors to checksum */
|
||||
UWORD trk_off; /* track offset */
|
||||
};
|
||||
|
||||
struct dph /* disk parameter header */
|
||||
{
|
||||
UBYTE *xlt; /* pointer to sector translate table */
|
||||
UWORD hiwater; /* high water mark for this disk */
|
||||
UWORD dum1; /* dummy (unused) */
|
||||
UWORD dum2;
|
||||
UBYTE *dbufp; /* pointer to 128 byte directory buffer */
|
||||
struct dpb *dpbp; /* pointer to disk parameter block */
|
||||
UBYTE *csv; /* pointer to check vector */
|
||||
UBYTE *alv; /* pointer to allocation vector */
|
||||
};
|
||||
|
||||
|
||||
/* Declaration of structure containing "global" state variables */
|
||||
struct stvars
|
||||
{
|
||||
UBYTE kbchar; /* One byte keyboard type-ahead buffer */
|
||||
UBYTE delim; /* Delimiter for function 9 */
|
||||
BOOLEAN lstecho; /* True if echoing console output to lst: */
|
||||
BOOLEAN echodel; /* Echo char when getting <del> ? */
|
||||
UWORD column; /* CRT column number for expanding tabs */
|
||||
XADDR chainp; /* Used for chain to program call */
|
||||
UBYTE curdsk; /* Currently selected disk */
|
||||
UBYTE dfltdsk; /* Default disk (last selected by fcn 14) */
|
||||
UBYTE user; /* Current user number */
|
||||
struct dph *dphp; /* pointer to disk parm hdr for cur disk */
|
||||
struct dirent *dirbufp; /* pointer for directory buff for process */
|
||||
/* stored here so that each process can */
|
||||
/* have a separate dirbuf. */
|
||||
struct dpb *parmp; /* pointer to disk parameter block for cur */
|
||||
/* disk. Stored here to save ref calc */
|
||||
UWORD srchpos; /* position in directory for search next */
|
||||
XADDR dmaadr; /* Disk dma address */
|
||||
XADDR srchp; /* Pointer to search FCB for function 17 */
|
||||
UBYTE *excvec[18]; /* Array of exception vectors */
|
||||
};
|
||||
|
||||
|
||||
/* Console buffer structure declaration */
|
||||
struct conbuf
|
||||
{
|
||||
UBYTE maxlen; /* Maximum length from calling routine */
|
||||
UBYTE retlen; /* Length actually found by BDOS */
|
||||
UBYTE cbuf[1]; /* Console data */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
|
||||
;****************************************************************
|
||||
;* *
|
||||
;* CP/M-Z8K Interface module for the Loader BDOS *
|
||||
;* For "C" version of CP/M-Z8K *
|
||||
;* *
|
||||
;* Copyright (c) 1982 Digital Research, Inc. *
|
||||
;* *
|
||||
;* Version 0.2 -- September 22, 1982 *
|
||||
;* Z8000 version -- 830728 *
|
||||
;* *
|
||||
;****************************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Globals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
.global _bios1 ; 6 BIOS entry points from BDOS
|
||||
.global _bios2
|
||||
.global _bios3
|
||||
.global _bios4
|
||||
.global _bios5
|
||||
.global _swap ; byte swapper
|
||||
.global _udiv ; unsigned divide routine
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals and Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _bios ; The Loader BDOS calls the BIOS direct
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* BIOS Interface Routines
|
||||
;*
|
||||
;* Note - there are 5 BIOS entry points from the BDOS,
|
||||
;* labelled BIOS1 - BIOS5, depending on the
|
||||
;* parameters passed.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_bios5:
|
||||
; For BIOS functions sectran and set exception vector
|
||||
; (funct, word, long) offsets 2, 4, 6
|
||||
|
||||
ldl rr6,6(r15) ; get 2nd param (long)
|
||||
jp _bios2 ; join common routine
|
||||
|
||||
_bios4:
|
||||
; For BIOS function seldsk
|
||||
; (func, word, word) offsets 2, 4, 6
|
||||
ld r7,6(r15) ; get 2nd param (word)
|
||||
clr r6 ; extend to ulong
|
||||
jp _bios2 ; join common routine
|
||||
|
||||
_bios3:
|
||||
; For BIOS function set dma
|
||||
; (func, long) offsets 2, 4
|
||||
ldl rr4,4(r15) ; get 1st param (long)
|
||||
subl rr6,rr6 ; clear second
|
||||
jp _bios1 ; join common routine
|
||||
|
||||
_bios2:
|
||||
; For all BIOS functions with a word parameter
|
||||
; (func, word) offsets 2, 4
|
||||
ld r5,4(r15) ; get 1st param (word)
|
||||
clr r4 ; extend to ulong
|
||||
|
||||
_bios1:
|
||||
; For all BIOS functions that have no parameter
|
||||
; other than function number
|
||||
ld r3,2(r15) ; get function number
|
||||
sub r15, #10 ; adjust sp...
|
||||
ldm @r15, r3, #5 ; ... and push args on stack
|
||||
call _bios ; do BIOS call as a call...
|
||||
add r15, #10 ; ...and readjust sp
|
||||
ret ; returns value in rr7
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Utility Subroutines
|
||||
;*
|
||||
;* swap(word) swap bytes of a word
|
||||
;*
|
||||
;* uword udiv((long) dividend,
|
||||
;* (uword) divisor,
|
||||
;* (uword *)rem )
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_swap:
|
||||
ld r7,2(r15)
|
||||
exb rh7,rl7
|
||||
ret
|
||||
|
||||
_udiv:
|
||||
ldl rr2,2(r15) ;long dividend
|
||||
subl rr0,rr0 ; as unsigned quad
|
||||
ld r5,6(r15) ;word divisor
|
||||
clr r4 ; as unsigned long
|
||||
ldl rr6,8(r15) ;->result
|
||||
|
||||
divl rq0,rr4
|
||||
|
||||
ld @r7,r1 ; store remainder
|
||||
ld r7,r3 ; return quotient
|
||||
clr r6
|
||||
|
||||
|
||||
ret
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
|
||||
;****************************************************************
|
||||
;* *
|
||||
;* CP/M-Z8K Basic Disk Operating System interface module *
|
||||
;* For "C" version of CP/M-Z8K *
|
||||
;* *
|
||||
;* Copyright (c) 1982 Digital Research, Inc. *
|
||||
;* *
|
||||
;* Version 0.2 -- September 22, 1982 *
|
||||
;* Z8000 version -- 821014 *
|
||||
;* *
|
||||
;****************************************************************
|
||||
|
||||
; 01/10/83 Modified for use with Z8002 (DMH)
|
||||
; 01/21/83 Fixed TPA caller Pseudo-segment prooblem
|
||||
|
||||
__text: .sect
|
||||
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Globals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
.global _bios1 ; 6 BIOS entry points from BDOS
|
||||
.global _bios2
|
||||
.global _bios3
|
||||
.global _bios4
|
||||
.global _bios5
|
||||
.global _bios6
|
||||
.global _traphnd ; trap #2 handler
|
||||
.global _swap ; byte swapper
|
||||
.global _udiv ; unsigned divide routine
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals and Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global __bdos ; BDOS entry point in bdosmain
|
||||
.global _usrseg ; This is user pseudo-segment
|
||||
.global _sysseg ; This is system pseudo_segment
|
||||
|
||||
;* The following were put in so that all BDOS modules were
|
||||
;* referenced, so they could be put in a library
|
||||
|
||||
.global _constat ; references conbdos.o
|
||||
.global _dirscan ; references dskutil.o
|
||||
.global _create ; references fileio.o
|
||||
.global _bdosrw ; references bdosrw.o
|
||||
|
||||
biosf .equ 50
|
||||
setsupf .equ 62
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap Handler
|
||||
;*
|
||||
;* rcode = bdos(command, (long)parameter)
|
||||
;*
|
||||
;* rr6: parameter
|
||||
;* r5: command
|
||||
;* returns
|
||||
;* r7: result
|
||||
;*
|
||||
;* called non-SEGMENTED with caller's registers
|
||||
;* saved on stack, and all but rr0 intact in
|
||||
;* registers.
|
||||
;*
|
||||
;* Calls __bdos(cmd, (word)param, (addr)param)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_traphnd:
|
||||
|
||||
; check for functions handled by assembly
|
||||
; language routines
|
||||
|
||||
cp r5,#setsupf ; set system mode
|
||||
jr eq setsup
|
||||
cp r5,#biosf ; call bios direct
|
||||
jr eq bioscall
|
||||
|
||||
;
|
||||
; if caller was non-segmented (always case for Z8002)
|
||||
; get (pseudo) segment number from _userseg
|
||||
|
||||
ldl rr2,rr6
|
||||
; ld r2,_sysseg ; assume system mode
|
||||
; ld r0,scfcw+co(r15)
|
||||
; bit r0,#14 ; Was user system?
|
||||
; jr nz,callC ; Yes.
|
||||
; ld r2,_usrseg ; user pseudo segment
|
||||
|
||||
;
|
||||
; Call C main routine
|
||||
;
|
||||
|
||||
callC:
|
||||
pushl @r15,rr2 ; xaddr param.
|
||||
push @r15,r7 ; word param
|
||||
push @r15,r5 ; command
|
||||
call __bdos
|
||||
add r15,#8
|
||||
;
|
||||
; Return result in caller's r7.
|
||||
; Restore segmented mode and return
|
||||
;
|
||||
ld cr7+co(r15),r7
|
||||
ret
|
||||
|
||||
;
|
||||
; direct BIOS call function
|
||||
;
|
||||
bioscall:
|
||||
ldm r3,@r7,#5 ;get parameters
|
||||
sc #3 ;call BIOS
|
||||
ret ;done
|
||||
|
||||
callBios:
|
||||
|
||||
;
|
||||
; Set supervisor mode procedure -- VERY DANGEROUS
|
||||
;
|
||||
; Status is set to SYSTEM, SEGMENTED.
|
||||
; Interrupt status will be that at the time
|
||||
; of the call.
|
||||
;
|
||||
setsup:
|
||||
ld r0,scfcw+co(r15)
|
||||
set r0,#14 ;set system
|
||||
ld scfcw+co(r15),r0;in user FCW
|
||||
ret ;return
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* BIOS Interface Routines
|
||||
;*
|
||||
;* Note - there are 6 BIOS entry points from the BDOS,
|
||||
;* labelled BIOS1 - BIOS6, depending on the
|
||||
;* parameters passed.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_bios5:
|
||||
; For BIOS functions sectran and set exception vector
|
||||
; (funct, word, long) offsets 2, 4, 6
|
||||
|
||||
ldl rr6,6(r15) ; get 2nd param (long)
|
||||
jr _bios2 ; join common routine
|
||||
|
||||
_bios4:
|
||||
; For BIOS function seldsk
|
||||
; (func, word, word) offsets 2, 4, 6
|
||||
ld r7,6(r15) ; get 2nd param (word)
|
||||
clr r6 ; extend to ulong
|
||||
jr _bios2 ; join common routine
|
||||
|
||||
_bios3:
|
||||
; For BIOS function set dma
|
||||
; (func, long) offsets 2, 4
|
||||
ldl rr4,4(r15) ; get 1st param (long)
|
||||
subl rr6,rr6 ; clear second
|
||||
jr _bios1 ; join common routine
|
||||
|
||||
_bios2:
|
||||
; For all BIOS functions with a word parameter
|
||||
; (func, word) offsets 2, 4
|
||||
ld r5,4(r15) ; get 1st param (word)
|
||||
clr r4 ; extend to ulong
|
||||
|
||||
_bios6:
|
||||
_bios1:
|
||||
; For all BIOS functions that have no parameter
|
||||
; other than function number
|
||||
ld r3,2(r15) ; get function number
|
||||
sc #3 ; do BIOS call
|
||||
ret ; returns value in rr7
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Utility Subroutines
|
||||
;*
|
||||
;* swap(word) swap bytes of a word
|
||||
;*
|
||||
;* uword udiv((long) dividend,
|
||||
;* (uword) divisor,
|
||||
;* (uword *)rem )
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_swap:
|
||||
ld r7,2(r15)
|
||||
exb rh7,rl7
|
||||
ret
|
||||
|
||||
_udiv:
|
||||
ldl rr2,2(r15) ;long dividend
|
||||
subl rr0,rr0 ; as unsigned quad
|
||||
ld r5,6(r15) ;word divisor
|
||||
clr r4 ; as unsigned long
|
||||
ldl rr6,8(r15) ;->result
|
||||
|
||||
divl rq0,rr4
|
||||
|
||||
ld @r7,r1 ; store remainder
|
||||
ld r7,r3 ; return quotient
|
||||
clr r6
|
||||
|
||||
ret
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-Z8K Loader BDOS Main Routine *
|
||||
* *
|
||||
* This is the main routine for the loader BDOS for P-CP/M.*
|
||||
* It has one entry point, _bdos, which is called from *
|
||||
* the assembly language trap handler found in bdosif.z8k. *
|
||||
* The parameters are a function number (integer) and an *
|
||||
* information parameter, (passed as both an integer and *
|
||||
* a pointer) *
|
||||
* The BDOS can potentially return a pointer, long word, *
|
||||
* or word *
|
||||
* *
|
||||
* Memory management for Z8000, etc. added 821018 by SS. *
|
||||
* One non-obvious change is using tmp_sel to copy in the *
|
||||
* user's FCB, and copying it out again if changed. *
|
||||
* Tmp_sel now handles '?' in the drive field, so it need *
|
||||
* not be called from search (the only place outside of *
|
||||
* this module where it is called) *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* Declarations of BIOS functions */
|
||||
|
||||
/* Declare EXTERN functions */
|
||||
|
||||
EXTERN seldsk(); /* Select disk */
|
||||
EXTERN BOOLEAN openfile(); /* Open File */
|
||||
EXTERN UWORD dirscan(); /* General directory scanning routine */
|
||||
EXTERN UWORD seqread(); /* Sequential disk read */
|
||||
|
||||
|
||||
/* Declare the "state variables". These are globals for the single-thread
|
||||
version of the file system, but are put in a structure so they can be
|
||||
based, with a pointer coming from the calling process */
|
||||
|
||||
GLOBAL struct stvars gbls;
|
||||
|
||||
struct tempstr
|
||||
{
|
||||
UBYTE tempdisk;
|
||||
BOOLEAN reselect;
|
||||
struct fcb *fptr;
|
||||
XADDR fxptr; /* xaddr of caller's FCB */
|
||||
struct fcb tempfcb; /* added for memory management */
|
||||
/* because caller's fcb may not */
|
||||
/* be directly accessible */
|
||||
};
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* _bdos MAIN ROUTINE *
|
||||
* *
|
||||
* Called with _bdos(func, info, infop) *
|
||||
* *
|
||||
* Where: *
|
||||
* func is the BDOS function number (d0.w) *
|
||||
* info is the parameter as a word *
|
||||
* infop is the parameter as a segmented pointer *
|
||||
* note that info is the word form of infop*
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
|
||||
UWORD _bdos(func,info,infop)
|
||||
REG WORD func; /* BDOS function number */
|
||||
REG UWORD info; /* parameter as word */
|
||||
REG XADDR infop; /* parameter as (segmented) pointer */
|
||||
{
|
||||
REG UWORD rtnval;
|
||||
LOCAL struct tempstr temp;
|
||||
BSETUP
|
||||
|
||||
temp.reselect = FALSE;
|
||||
temp.fxptr = infop;
|
||||
rtnval = 0;
|
||||
|
||||
switch (func) /* switch on function number */
|
||||
{
|
||||
|
||||
case 2: bconout((UBYTE)info); /* console output */
|
||||
break;
|
||||
|
||||
|
||||
case 14: seldsk((UBYTE)info); /* select disk */
|
||||
GBL.dfltdsk = (UBYTE)info;
|
||||
break;
|
||||
|
||||
case 15: tmp_sel(&temp); /* open file */
|
||||
temp.fptr->extent = 0;
|
||||
temp.fptr->s2 = 0;
|
||||
rtnval = dirscan(openfile, temp.fptr);
|
||||
break;
|
||||
|
||||
case 20: tmp_sel(&temp); /* read sequential */
|
||||
rtnval = seqread(temp.fptr);
|
||||
break;
|
||||
|
||||
case 26: GBL.dmaadr = infop; /* set dma address */
|
||||
break;
|
||||
|
||||
default: return(-1); /* bad function number */
|
||||
/* break; */
|
||||
|
||||
}; /* end of switch statement */
|
||||
|
||||
if (temp.reselect){ /* if reselected disk, restore it now */
|
||||
temp.fptr->drvcode = temp.tempdisk;
|
||||
cpy_out(temp.fptr, infop, sizeof *temp.fptr);
|
||||
}
|
||||
|
||||
return(rtnval); /* return the BDOS return value */
|
||||
|
||||
} /* end _bdos */
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* bdos call - replaces system call in real CP/M-Z8K *
|
||||
* Function is to arrange for parameters to _bdos to be *
|
||||
* in the right place. *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
bdos(func, longaddr)
|
||||
int func;
|
||||
XADDR longaddr;
|
||||
{
|
||||
return(_bdos(func, (int) longaddr, longaddr));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
**
|
||||
** tmp_sel(temptr) -- temporarily select disk
|
||||
** pointed to by temptr->fptr.
|
||||
**
|
||||
** make local copy of FCB in caller's space.
|
||||
**
|
||||
*****************************************************/
|
||||
|
||||
tmp_sel(temptr) /* temporarily select disk pointed to by fcb */
|
||||
/* also copy fcb into temp structure */
|
||||
REG struct tempstr *temptr;
|
||||
{
|
||||
REG struct fcb *fcbp;
|
||||
REG UBYTE tmp_dsk;
|
||||
BSETUP
|
||||
|
||||
/* get local copy of caller's FCB, */
|
||||
/* and point temptr->fptr at it */
|
||||
|
||||
cpy_in(temptr->fxptr, &temptr->tempfcb, sizeof(struct fcb));
|
||||
temptr->fptr = &temptr->tempfcb;
|
||||
|
||||
/* get local copy of fcb pointer */
|
||||
fcbp = temptr->fptr;
|
||||
|
||||
/* select disk if necessary */
|
||||
tmp_dsk = fcbp->drvcode;
|
||||
if (tmp_dsk == '?') { /* -- drive '?' for search */
|
||||
seldsk( GBL.dfltdsk);
|
||||
} else { /* -- drive 0 or disk+1 */
|
||||
temptr->tempdisk = tmp_dsk;
|
||||
seldsk( tmp_dsk ? tmp_dsk - 1 : GBL.dfltdsk );
|
||||
|
||||
fcbp->drvcode = GBL.user;
|
||||
temptr->reselect = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Miscellaneous Module *
|
||||
* *
|
||||
* This module contains miscellaneous loose ends for *
|
||||
* P-CP/M. Included are: *
|
||||
* *
|
||||
* bdosinit() - BDOS initialization routine *
|
||||
* called from CCP for system init *
|
||||
* warmboot() - BDOS warm boot exit routine *
|
||||
* error() - BDOS error printing routine *
|
||||
* setexc() - BDOS set exception vector *
|
||||
* set_tpa() - BDOS get/set TPA limits *
|
||||
* cpy_bi() - copy byte in *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on the Z8000 *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* BIOS definitions, needed for bios wboot */
|
||||
|
||||
|
||||
/* Declare external functions */
|
||||
EXTERN conout(); /* Console Output function */
|
||||
EXTERN UBYTE conin(); /* Console Input function */
|
||||
EXTERN prt_line(); /* Print String function */
|
||||
EXTERN UWORD _bdos(); /* BDOS main routine */
|
||||
EXTERN UBYTE *traphnd(); /* assembly language trap handler */
|
||||
EXTERN initexc(); /* init the exception handler in */
|
||||
/* exceptn.s */
|
||||
EXTERN UWORD dirscan(); /* Directory scanning routine */
|
||||
EXTERN BOOLEAN set_attr(); /* Set File attributes function */
|
||||
|
||||
/* Declare external variables */
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* vector of critical disks */
|
||||
EXTERN XADDR tpa_lt; /* TPA lower limit (temporary) */
|
||||
EXTERN XADDR tpa_lp; /* TPA lower limit (permanent) */
|
||||
EXTERN XADDR tpa_ht; /* TPA upper limit (temporary) */
|
||||
EXTERN XADDR tpa_hp; /* TPA upper limit (permanent) */
|
||||
EXTERN BOOLEAN submit; /* external variables from CCP */
|
||||
EXTERN BOOLEAN morecmds;
|
||||
|
||||
|
||||
#define trap2v 34 /* trap 2 vector number */
|
||||
#define ctrlc 3 /* control-c */
|
||||
|
||||
|
||||
/********************************
|
||||
* bdos initialization routine *
|
||||
********************************/
|
||||
|
||||
bdosinit()
|
||||
/* Initialize the File System */
|
||||
{
|
||||
REG struct
|
||||
{
|
||||
WORD nmbr;
|
||||
XADDR low;
|
||||
LONG length;
|
||||
} *segp;
|
||||
BSETUP
|
||||
|
||||
bsetvec(trap2v, map_adr((long)traphnd, 257)); /* set up trap vector */
|
||||
/* (inst. space addr) */
|
||||
GBL.kbchar = 0; /* initialize the "global" variables */
|
||||
GBL.delim = '$';
|
||||
GBL.lstecho = FALSE;
|
||||
GBL.echodel = TRUE;
|
||||
GBL.chainp = XNULL;
|
||||
GBL.user = 0;
|
||||
_bdos(13,0, XNULL); /* reset disk system function */
|
||||
prt_line("
|
||||
\r\nCPM-Z8000 Version 1.3 06/14/83$");
|
||||
prt_line("\r\nCopyright 1982 Digital Research Inc., Zilog Inc.$");
|
||||
segp = bgetseg(); /* get pointer to memory segment table */
|
||||
tpa_lt = tpa_lp = segp->low;
|
||||
tpa_ht = tpa_hp = tpa_lp + segp->length;
|
||||
initexc( &(GBL.excvec[0]) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* warmboot entry point *
|
||||
************************/
|
||||
|
||||
warmboot(parm)
|
||||
/* Warm Boot the system */
|
||||
WORD parm; /* 1 to reset submit flag */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
log_dsk &= ~ro_dsk; /* log off any disk marked read-only */
|
||||
/* note that this code is specifically for a single-
|
||||
thread system. It won't work in a multi-task sys */
|
||||
ro_dsk = 0;
|
||||
crit_dsk = 0;
|
||||
if (parm)
|
||||
submit = morecmds = FALSE;
|
||||
tpa_lt = tpa_lp;
|
||||
tpa_ht = tpa_hp;
|
||||
initexc( &(GBL.excvec[0]) );
|
||||
bwboot();
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* disk error handlers */
|
||||
/*************************/
|
||||
|
||||
prt_err(p)
|
||||
/* print the error message */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
prt_line(p);
|
||||
prt_line(" error on drive $");
|
||||
conout(GBL.curdsk + 'A');
|
||||
}
|
||||
|
||||
|
||||
abrt_err(p)
|
||||
/* print the error message and always abort */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
prt_err(p);
|
||||
warmboot(1);
|
||||
}
|
||||
|
||||
|
||||
ext_err(p)
|
||||
/* print the error message, and allow for retry, abort, or ignore */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
REG UBYTE ch;
|
||||
|
||||
prt_err(p);
|
||||
do
|
||||
{
|
||||
prt_line("\n\rDo you want to: Abort (A), Retry (R),$");
|
||||
prt_line(" or Continue with bad data (C)? $");
|
||||
ch = conin() & 0x5f;
|
||||
prt_line("\r\n$");
|
||||
|
||||
switch ( ch )
|
||||
{
|
||||
case ctrlc: warmboot(1);
|
||||
case 'A': warmboot(1);
|
||||
case 'C': return(1);
|
||||
case 'R': return(0);
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
|
||||
filero(fcbp)
|
||||
/* File R/O error */
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
{
|
||||
REG BYTE *p;
|
||||
REG UWORD i;
|
||||
REG UBYTE ch;
|
||||
|
||||
p = (BYTE *)fcbp;
|
||||
prt_line("file error: $");
|
||||
i = 8;
|
||||
do conout(*++p); while (--i);
|
||||
conout('.');
|
||||
i = 3;
|
||||
do conout(*++p); while (--i);
|
||||
prt_line(" is read-only.$");
|
||||
do
|
||||
{
|
||||
prt_line("\r\nDo you want to: Change it to read/write (C), or Abort (A)? $");
|
||||
ch = conin() & 0x5f;
|
||||
prt_line("\r\n$");
|
||||
|
||||
switch ( ch )
|
||||
{
|
||||
case ctrlc: warmboot(1);
|
||||
case 'A': warmboot(1);
|
||||
case 'C': fcbp->ftype[robit] &= 0x7f;
|
||||
return( dirscan(set_attr, fcbp, 2) );
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* error entry point *
|
||||
************************/
|
||||
|
||||
error(errnum, fcbp) /* VARARGS */
|
||||
/* Print error message, do appropriate response */
|
||||
|
||||
UWORD errnum; /* error number */
|
||||
struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
prt_line("\r\nCP/M Disk $");
|
||||
switch (errnum)
|
||||
{
|
||||
case 0: return( ext_err("read$") );
|
||||
/* break; */
|
||||
|
||||
case 1: return( ext_err("write$") );
|
||||
/* break; */
|
||||
|
||||
case 2: abrt_err("select$");
|
||||
/* break; */
|
||||
|
||||
case 3: return( ext_err("select$") );
|
||||
/* break; */
|
||||
|
||||
case 4: abrt_err("change$");
|
||||
/* break; */
|
||||
|
||||
case 5: return filero(fcbp);
|
||||
/* break; */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* set exception entry point *
|
||||
*****************************/
|
||||
|
||||
setexc(xepbp)
|
||||
/* Set Exception Vector */
|
||||
REG XADDR xepbp;
|
||||
{
|
||||
REG WORD i;
|
||||
REG struct
|
||||
{
|
||||
WORD vecnum;
|
||||
UBYTE *newvec;
|
||||
UBYTE *oldvec;
|
||||
} epb;
|
||||
|
||||
BSETUP
|
||||
|
||||
cpy_in(xepbp, &epb, sizeof epb); /* copy in param block */
|
||||
|
||||
i = epb.vecnum-2;
|
||||
if ( i==32 || i==33) return(-1);
|
||||
if ( (30 <= i) && (i <= 37) ) i -= 20;
|
||||
else if ( (i < 0) || (i > 9) ) return(-1);
|
||||
epb.oldvec = GBL.excvec[i];
|
||||
GBL.excvec[i] = epb.newvec;
|
||||
|
||||
cpy_out(&epb, xepbp, sizeof epb); /* copy out param block */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* get/set TPA entry point *
|
||||
*****************************/
|
||||
|
||||
set_tpa(xp)
|
||||
/* Get/Set TPA Limits */
|
||||
REG XADDR xp;
|
||||
|
||||
#define set 1
|
||||
#define sticky 2
|
||||
|
||||
{
|
||||
struct
|
||||
{
|
||||
UWORD parms;
|
||||
XADDR low;
|
||||
XADDR high;
|
||||
} p;
|
||||
|
||||
cpy_in(xp, &p, sizeof p); /* copy in param block */
|
||||
|
||||
if (p.parms & set)
|
||||
{
|
||||
tpa_lt = p.low;
|
||||
tpa_ht = p.high;
|
||||
if (p.parms & sticky)
|
||||
{
|
||||
tpa_lp = tpa_lt;
|
||||
tpa_hp = tpa_ht;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p.low = tpa_lt;
|
||||
p.high = tpa_ht;
|
||||
}
|
||||
|
||||
cpy_out(&p, xp, sizeof p); /* copy out param block */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
**
|
||||
** ubyte = cpy_bi(xaddr)-- copy byte in
|
||||
**
|
||||
*****************************************************/
|
||||
|
||||
UBYTE cpy_bi(addr)
|
||||
XADDR addr;
|
||||
{
|
||||
UBYTE b;
|
||||
|
||||
cpy_in(addr, &b, 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-Z8K Loader BDOS Disk Read Module *
|
||||
* *
|
||||
* This module contains functions to perform sequential *
|
||||
* or random access read or write to the disk for P-CP/M *
|
||||
* *
|
||||
* It includes the following external functions: *
|
||||
* *
|
||||
* seqread() - sequential and random disk I/O *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on the Z8000 *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
|
||||
/* External function definitions */
|
||||
EXTERN UWORD rdsec(); /* disk read/write routine */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
|
||||
|
||||
/**********************************************************/
|
||||
/* First, some utility functions used by seqio and ranio */
|
||||
/**********************************************************/
|
||||
|
||||
/******************************
|
||||
* FCB block number routines *
|
||||
******************************/
|
||||
|
||||
WORD blkindx(fcbp)
|
||||
/* return index into fcb disk map */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
REG WORD i;
|
||||
REG WORD blkshf;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp;
|
||||
blkshf = dparmp->bsh;
|
||||
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
|
||||
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
|
||||
}
|
||||
|
||||
|
||||
UWORD blknum(fcbp, index, wrdfcb)
|
||||
/* return block number in fcb indicated by index */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
WORD wrdfcb; /* boolean, fcb disk map of words? */
|
||||
{
|
||||
if (wrdfcb)
|
||||
return( swap(fcbp->dskmap.big[index]) );
|
||||
else return( UBWORD(fcbp->dskmap.small[index]) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********************
|
||||
* disk read routine *
|
||||
*********************/
|
||||
|
||||
UWORD do_io(block, rcrd)
|
||||
|
||||
UWORD block; /* block number */
|
||||
UBYTE rcrd; /* record number */
|
||||
{
|
||||
REG LONG lsec;
|
||||
REG struct dpb *dparmp;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp; /* init dpb pointer */
|
||||
lsec = ((LONG)block << (dparmp->bsh)) +
|
||||
(LONG)(rcrd & (dparmp->blm));
|
||||
return( rdsec(lsec, GBL.dmaadr) );
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* routine for crossing extent boundaries *
|
||||
*******************************************/
|
||||
|
||||
WORD new_ext(fcbp)
|
||||
/* If sequential I/O, open the next extent */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
REG UBYTE mod; /* module number */
|
||||
REG UBYTE ext; /* extent number */
|
||||
BSETUP
|
||||
|
||||
mod = (fcbp->s2) & 0x3f;
|
||||
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
|
||||
if (ext >= 32)
|
||||
{
|
||||
ext = 0;
|
||||
mod += 1;
|
||||
}
|
||||
if (mod >= 64) return(6); /* past maximum file size */
|
||||
if ( mod == ((fcbp->s2) & 0x3f) )
|
||||
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
|
||||
{ /* we're in same logical extent */
|
||||
fcbp->extent = ext;
|
||||
return(0);
|
||||
}
|
||||
/* Extent or Module numbers don't match */
|
||||
/* Close the old extent and open a new one */
|
||||
fcbp->s2 = mod;
|
||||
fcbp->extent = ext;
|
||||
if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open new extent */
|
||||
return(4); /* reading unwritten extent */
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/************************************
|
||||
* Routine to calculate the maximum *
|
||||
* extent number of an FCB in a *
|
||||
* extent-folded environment *
|
||||
************************************/
|
||||
|
||||
UWORD calcext(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p;
|
||||
BSETUP
|
||||
|
||||
i = 15;
|
||||
p = &(fcbp->dskmap.small[16]);
|
||||
do
|
||||
{
|
||||
if (*--p) break;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
/* Now i contains the index of the last non-zero block in the FCB */
|
||||
if ((GBL.parmp)->dsm > 255) i >>= 1;
|
||||
i >>= 7 - ((GBL.parmp)->bsh);
|
||||
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* Routine to get the actual *
|
||||
* record count of the currently *
|
||||
* active logical extent of a FCB *
|
||||
*********************************/
|
||||
|
||||
UWORD get_rc(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD ext;
|
||||
|
||||
ext = calcext(fcbp); /* find last active extent in fcb */
|
||||
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
|
||||
/* if this is the last active fcb, return fcb's rc */
|
||||
else if (ext > fcbp->extent) return(128);
|
||||
/* if the fcb has more extents past this one, then */
|
||||
/* the current one is logically full */
|
||||
else return (0);
|
||||
/* if we seeked past the last active extent, rc = 0 */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* bdosrw entry point *
|
||||
************************/
|
||||
|
||||
UWORD seqread(fcbp)
|
||||
|
||||
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
/* 2 = random with zero fill */
|
||||
{
|
||||
REG UWORD block; /* block number from fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
REG UBYTE *buf; /* type compatibility kludge */
|
||||
REG WORD parm; /* parameter to do-io */
|
||||
REG WORD bigfile; /* file system is in word mode */
|
||||
BSETUP
|
||||
|
||||
bigfile = ((GBL.parmp)->dsm) & ~0xff;
|
||||
if (fcbp->cur_rec == 128)
|
||||
{ /* time to try next extent */
|
||||
if ( new_ext(fcbp) )
|
||||
return(1); /* if can't open new extent, error */
|
||||
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
|
||||
}
|
||||
|
||||
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
|
||||
return(1); /* this is end of file */
|
||||
index = blkindx(fcbp); /* get index into fcb disk map */
|
||||
block = blknum(fcbp, index, bigfile);
|
||||
if ( ! block) return(1);
|
||||
return( do_io(block, (fcbp->cur_rec)++));
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Disk Read/Write Module *
|
||||
* *
|
||||
* This module contains functions to perform sequential *
|
||||
* or random access read or write to the disk for P-CP/M *
|
||||
* *
|
||||
* It includes the following external functions: *
|
||||
* *
|
||||
* bdosrw() - sequential and random disk I/O *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on the Z8000 *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
|
||||
/* External function definitions */
|
||||
EXTERN UWORD rdwrt(); /* disk read/write routine */
|
||||
EXTERN WORD getaloc(); /* allocate a block of disk space */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
|
||||
EXTERN UWORD close_fi(); /* close file function */
|
||||
EXTERN BOOLEAN create(); /* create file function passed to dirscan */
|
||||
EXTERN UWORD error(); /* error handler */
|
||||
|
||||
/* External variable definitions */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
/* First, some utility functions used by seqio and ranio */
|
||||
/**********************************************************/
|
||||
|
||||
/******************************
|
||||
* FCB block number routines *
|
||||
******************************/
|
||||
|
||||
WORD blkindx(fcbp)
|
||||
/* return index into fcb disk map */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
REG WORD i;
|
||||
REG WORD blkshf;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp;
|
||||
blkshf = dparmp->bsh;
|
||||
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
|
||||
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
|
||||
}
|
||||
|
||||
|
||||
UWORD blknum(fcbp, index, wrdfcb)
|
||||
/* return block number in fcb indicated by index */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
WORD wrdfcb; /* boolean, fcb disk map of words? */
|
||||
{
|
||||
if (wrdfcb)
|
||||
return( swap(fcbp->dskmap.big[index]) );
|
||||
else return( UBWORD(fcbp->dskmap.small[index]) );
|
||||
}
|
||||
|
||||
|
||||
setblk(fcbp, index, wrdfcb, block)
|
||||
/* put block number into fcb */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
WORD wrdfcb; /* boolean, fcb disk map of words? */
|
||||
REG UWORD block; /* block number */
|
||||
{
|
||||
fcbp->s2 &= 0x7f; /* set file write flag */
|
||||
if (wrdfcb)
|
||||
fcbp->dskmap.big[index] = swap(block);
|
||||
else fcbp->dskmap.small[index] = (UBYTE)block;
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
* disk read/write routine *
|
||||
***************************/
|
||||
|
||||
UWORD do_io(block, rcrd, parm)
|
||||
|
||||
UWORD block; /* block number */
|
||||
UBYTE rcrd; /* record number */
|
||||
REG WORD parm; /* write parameter */
|
||||
{
|
||||
REG LONG lsec;
|
||||
REG struct dpb *dparmp;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp; /* init dpb pointer */
|
||||
lsec = ((LONG)block << (dparmp->bsh)) +
|
||||
(LONG)(rcrd & (dparmp->blm));
|
||||
return( rdwrt(lsec, GBL.dmaadr, parm) );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************
|
||||
* routine for crossing extent boundaries *
|
||||
*******************************************/
|
||||
|
||||
WORD new_ext(fcbp, reading, ran)
|
||||
/* If sequential I/O, open the next extent */
|
||||
/* If random I/O, compute new extent from random record field */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
BOOLEAN reading; /* read/write flag */
|
||||
WORD ran; /* random I/O flag */
|
||||
{
|
||||
REG UBYTE mod; /* module number */
|
||||
REG UBYTE ext; /* extent number */
|
||||
BSETUP
|
||||
|
||||
if (ran)
|
||||
{
|
||||
mod = ( (fcbp->ran0) << 4) | ( (fcbp->ran1) >> 4);
|
||||
ext = ( ((fcbp->ran1) & 0x0f) << 1);
|
||||
if ((fcbp->ran2) & 0x80) ext |= 1;
|
||||
/* the calculation of ext was coded this way because of a */
|
||||
/* compiler bug from Alcyon */
|
||||
}
|
||||
else
|
||||
{
|
||||
mod = (fcbp->s2) & 0x3f;
|
||||
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
|
||||
}
|
||||
if (ext >= 32)
|
||||
{
|
||||
ext = 0;
|
||||
mod += 1;
|
||||
}
|
||||
if (mod >= 64) return(6); /* past maximum file size */
|
||||
if ( mod == ((fcbp->s2) & 0x3f) )
|
||||
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
|
||||
{ /* we're in same logical extent */
|
||||
fcbp->extent = ext;
|
||||
return(0);
|
||||
}
|
||||
/* Extent or Module numbers don't match */
|
||||
/* Close the old extent and open a new one */
|
||||
if ( close_fi(fcbp) >= 255 ) return(3);
|
||||
/* can't close old extent */
|
||||
fcbp->s2 = mod;
|
||||
fcbp->extent = ext;
|
||||
if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open new extent */
|
||||
{
|
||||
if (reading) return(4); /* reading unwritten extent */
|
||||
if ( dirscan(create, fcbp, 8) >= 255 )
|
||||
return(5); /* can't create new extent */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/************************************
|
||||
* Routine to calculate the maximum *
|
||||
* extent number of an FCB in a *
|
||||
* extent-folded environment *
|
||||
************************************/
|
||||
|
||||
UWORD calcext(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p;
|
||||
BSETUP
|
||||
|
||||
i = 15;
|
||||
p = &(fcbp->dskmap.small[16]);
|
||||
do
|
||||
{
|
||||
if (*--p) break;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
/* Now i contains the index of the last non-zero block in the FCB */
|
||||
if ((GBL.parmp)->dsm > 255) i >>= 1;
|
||||
i >>= 7 - ((GBL.parmp)->bsh);
|
||||
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* Routine to get the actual *
|
||||
* record count of the currently *
|
||||
* active logical extent of a FCB *
|
||||
*********************************/
|
||||
|
||||
UWORD get_rc(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD ext;
|
||||
|
||||
ext = calcext(fcbp); /* find last active extent in fcb */
|
||||
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
|
||||
/* if this is the last active fcb, return fcb's rc */
|
||||
else if (ext > fcbp->extent) return(128);
|
||||
/* if the fcb has more extents past this one, then */
|
||||
/* the current one is logically full */
|
||||
else return (0);
|
||||
/* if we seeked past the last active extent, rc = 0 */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* bdosrw entry point *
|
||||
************************/
|
||||
|
||||
UWORD bdosrw(fcbp, reading, random)
|
||||
|
||||
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
REG BOOLEAN reading; /* boolean to tell whether to read or write */
|
||||
WORD random; /* 0 = sequential, 1 = random (normal), */
|
||||
/* 2 = random with zero fill */
|
||||
{
|
||||
REG UWORD block; /* block number from fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
REG XADDR old_dma; /* temp holding spot for dmaadr */
|
||||
REG UBYTE *buf; /* type compatibility kludge */
|
||||
REG WORD parm; /* parameter to do-io */
|
||||
REG WORD bigfile; /* file system is in word mode */
|
||||
REG UWORD rtn; /* return parameter */
|
||||
REG UBYTE rc; /* temp storage for rcdcnt */
|
||||
BSETUP
|
||||
|
||||
bigfile = ((GBL.parmp)->dsm) & ~0xff;
|
||||
if ( ( ! reading) && (fcbp->ftype[robit] & 0x80) ) error(5,fcbp);
|
||||
/* check for read-only file */
|
||||
if (random)
|
||||
{
|
||||
if ( rtn = new_ext(fcbp, reading, TRUE) ) return(rtn);
|
||||
/* open new extent if necessary, return if error */
|
||||
fcbp->cur_rec = (fcbp->ran2) & 0x7f;
|
||||
}
|
||||
else /* sequential */
|
||||
if (fcbp->cur_rec == 128)
|
||||
{ /* time to try next extent */
|
||||
if ( new_ext(fcbp, reading, FALSE) )
|
||||
return(1); /* if can't open new extent, error */
|
||||
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
|
||||
}
|
||||
|
||||
/* record is now in active fcb */
|
||||
rc = fcbp->rcdcnt;
|
||||
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
|
||||
{
|
||||
if (reading) return(1); /* reading unwritten data */
|
||||
fcbp->s2 &= 0x7f; /* set file write flag */
|
||||
rc = fcbp->cur_rec + 1;
|
||||
}
|
||||
index = blkindx(fcbp); /* get index into fcb disk map */
|
||||
block = blknum(fcbp, index, bigfile);
|
||||
if (block) parm = (reading ? 0 : 1);
|
||||
else /* if allocated block, parm is just read or write */
|
||||
{ /* unallocated block */
|
||||
if (reading) return(1); /* reading unwritten data */
|
||||
/* Writing to new block */
|
||||
block = getaloc();
|
||||
if (block == (UWORD *)~0) return(2); /* out of space */
|
||||
setblk(fcbp, index, bigfile, block);
|
||||
parm = 3;
|
||||
if (random == 2)
|
||||
{ /* Write random with zero fill */
|
||||
old_dma = GBL.dmaadr;
|
||||
GBL.dmaadr = map_adr((XADDR)GBL.dirbufp,0);/* Do DMA from dir_buf */
|
||||
index = SECLEN;
|
||||
buf = (UBYTE *)GBL.dirbufp; /* fix type incompatibility */
|
||||
do buf[--index] = 0;
|
||||
while (index); /* zero the dma buffer */
|
||||
for (index = 0; index <= ((GBL.parmp)->blm); index++)
|
||||
{
|
||||
do_io(block, (UBYTE)index, parm);
|
||||
/* write zeros to the block */
|
||||
parm = 1; /* next write is not to new block */
|
||||
}
|
||||
GBL.dmaadr = old_dma; /* restore dma address */
|
||||
}
|
||||
}
|
||||
rtn = do_io(block, fcbp->cur_rec, parm);
|
||||
if ( rtn == 0 )
|
||||
{
|
||||
fcbp->rcdcnt = rc;
|
||||
if ( ! random ) fcbp->cur_rec += 1;
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
||||
;********** wboot.s -- Olivetti bootstrap writer*****
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- adapt for nonseg.
|
||||
;* 820930 S. Savitzky (Zilog) -- created
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE -- THIS CODE IS HIGHLY SYSTEM-DEPENDENT
|
||||
;*
|
||||
;* This module contains both the bootstrap
|
||||
;* writer, and the code that receives control
|
||||
;* after being booted.
|
||||
;*
|
||||
;* The main function of the latter is to make
|
||||
;* sure that the system, whose entry point is
|
||||
;* called "bios", is passed a valid stack
|
||||
;* and PSA pointer.
|
||||
;*
|
||||
;* Although this code runs segmented, it must
|
||||
;* be linked with non-segmented code, so it
|
||||
;* looks rather odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;* The first sector on track 1 is the PCOS file
|
||||
;* descriptor block; the second is the boot file
|
||||
;* header and the start of the system code.
|
||||
;*
|
||||
;* For now, we assume that the system starts at
|
||||
;* <<11>>0000 (hex)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Globals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _startld
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
BOOTSYS .equ 0A000000h ; system address
|
||||
BOOTSTK .equ BOOTSYS+0BFFEh ; system stack top
|
||||
rtc_ext .equ 02000022h ; real-time clock
|
||||
; ext. call addr
|
||||
|
||||
BPT .equ 16 ; #blocks in a track
|
||||
BPS .equ 256 ; #bytes in a sector
|
||||
NBLKS .equ 9*16 ; #blocks in boot
|
||||
HDRSIZE .equ 24 ; #bytes in header
|
||||
FILSIZE .equ 256*(NBLKS-1) ; file data size
|
||||
SYSSIZE .equ FILSIZE-HDRSIZE ; total system size
|
||||
S1SIZE .equ BPS-HDRSIZE ; data in sector 1
|
||||
|
||||
SEG4 .equ 04000000h
|
||||
SEG2 .equ 02000000h
|
||||
|
||||
SYSPSA .equ SEG2+100h ; system PSA
|
||||
BOOTPSA .equ SEG4+100h ; PSA in PROM for boot
|
||||
|
||||
sscall .macro ;short segmented call
|
||||
.word 05f00h
|
||||
.word ?1
|
||||
.endm
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Entry Points and post-boot Initialization
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;* transfer vector
|
||||
|
||||
; jr wboot
|
||||
; jr wrboot * Commented out - this has implications for booter
|
||||
jr entry
|
||||
|
||||
;* post-boot init.
|
||||
|
||||
entry: ;SEGMENTED
|
||||
_startld:
|
||||
|
||||
DI VI,NVI
|
||||
|
||||
ldl rr14, #BOOTSTK ; init stack pointer
|
||||
|
||||
ldl rr2, #SYSPSA ; copy PROM's PSA
|
||||
ldctl r4, psapseg
|
||||
ldctl r5, psapoff
|
||||
ld r0, #570/2
|
||||
ldir @r2, @r4, r0
|
||||
|
||||
ldl rr2, #SYSPSA ; shift PSA pointer
|
||||
ldctl psapseg, r2
|
||||
ldctl psapoff, r3
|
||||
|
||||
ld r2,#142h ;CROCK-- turn off
|
||||
ld r3,#1feh ; usart interrupts
|
||||
out @r2,r3
|
||||
|
||||
ldar r2, $ ; go
|
||||
ld r3,#bios
|
||||
jp @r2
|
||||
@@ -0,0 +1,80 @@
|
||||
;********** wboot.s -- Olivetti bootstrap writer*****
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- adapt for nonseg.
|
||||
;* 820930 S. Savitzky (Zilog) -- created
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
; 01/12/83 Adapted for the Kontron ECB/16 Z8002 (DMH)
|
||||
; 01/16/83 Added relocation code to relocate the
|
||||
; Z8002 CP/M from 8000h to 0000h (DMH).
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE -- THIS CODE IS HIGHLY SYSTEM-DEPENDENT
|
||||
;*
|
||||
;* This module contains the code that receives
|
||||
;* control after being booted.
|
||||
;*
|
||||
;* The main function is to make sure that the
|
||||
;* system, whose entry point is called "bios",
|
||||
;* is passed a valid stack and PSA pointer.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios
|
||||
.global _wboot
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
SYSTEM .equ 00000000h ; system address
|
||||
SYSSTK .equ 08000h-200h ; system stack top, leave room for PSA
|
||||
SYSPSA .equ SYSSTK ; system PSA
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Entry Points and post-boot Initialization
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;* transfer vector
|
||||
|
||||
jr wboot
|
||||
jr entry ; there is no write boot entry
|
||||
jr entry
|
||||
|
||||
;* post-boot init
|
||||
;* (note that this code
|
||||
;* is position indepent).
|
||||
|
||||
entry: DI VI,NVI
|
||||
ld r15, #SYSSTK ; init stack pointer
|
||||
ld r3, #SYSPSA ; initialize PSA
|
||||
ldctl psap, r3
|
||||
ld r7,#0 ; destination of system copy
|
||||
ld r5,#8000h ; source of system copy
|
||||
ld r0,#4000h ; copy 16k words
|
||||
ldir @r7,@r5,r0 ; Zip it!
|
||||
ld r3,#bios
|
||||
jp @r3 ; Actually jumping to low address
|
||||
|
||||
wboot: ld r3,#_wboot
|
||||
jp @r3
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/********************************************************
|
||||
* *
|
||||
* BIOS definitions for P-CP/M *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
* This include file simply defines the BIOS calls *
|
||||
* *
|
||||
* Memory management added 821018 by SS at Zilog *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
EXTERN long bios(); /* main BIOS entry point */
|
||||
EXTERN UBYTE bios1(); /* used for character I/O functions */
|
||||
EXTERN bios2(); /* parm1 is word, no return value */
|
||||
EXTERN bios3(); /* used for set dma only */
|
||||
/* parm1 is a pointer, no return */
|
||||
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
|
||||
/* words, returns a pointer to dph */
|
||||
EXTERN UWORD bios5(); /* for sectran and set exception */
|
||||
|
||||
|
||||
#define bwboot() bios1(1) /* warm boot */
|
||||
#define bconstat() bios1(2) /* console status */
|
||||
#define bconin() bios1(3) /* console input */
|
||||
#define bconout(parm) bios2(4,parm) /* console output parm */
|
||||
#define blstout(parm) bios2(5,parm) /* list device output */
|
||||
#define bpun(parm) bios2(6,parm) /* punch char output */
|
||||
#define brdr() bios1(7) /* reader input */
|
||||
#define bhome() bios1(8) /* recalibrate drive */
|
||||
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
|
||||
/* select disk and return info */
|
||||
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
|
||||
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
|
||||
#define bsetdma(parm) bios3(12,parm) /* set dma address */
|
||||
#define bread() bios1(13) /* read sector from disk */
|
||||
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
|
||||
#define blistst() bios1(15) /* list device status */
|
||||
#define bsectrn(parm1,parm2) bios5(16,parm1,(XADDR)parm2)
|
||||
/* sector translate */
|
||||
#define bgetseg() bios1(18) /* get memory segment tbl */
|
||||
#define bgetiob() bios1(19) /* get I/O byte */
|
||||
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
|
||||
#define bflush() bios1(21) /* flush buffers */
|
||||
#define bsetvec(parm1,parm2) bios5(22,parm1,(XADDR)parm2)
|
||||
/* set exception vector */
|
||||
|
||||
|
||||
/************************/
|
||||
/* MEMORY MANAGEMENT */
|
||||
/*----------------------*/
|
||||
EXTERN XADDR map_adr(); /*(laddr, space)->paddr */
|
||||
EXTERN VOID mem_cpy(); /*(src, dst, len) */
|
||||
/*----------------------*/
|
||||
/* copy in, out (s,d,l) */
|
||||
/* */
|
||||
#define cpy_in(s,d,l) mem_cpy((XADDR)s, map_adr((XADDR)d, 0), (long)l)
|
||||
#define cpy_out(s,d,l) mem_cpy(map_adr((XADDR)s, 0), (XADDR)d, (long)l)
|
||||
/* */
|
||||
/************************/
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
;************ biosdefs.z8k **************************
|
||||
;*
|
||||
;* Assembly language definitions for
|
||||
;* P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Calls and Trap Indexes
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
XFER_SC .equ 1
|
||||
BIOS_SC .equ 3
|
||||
BDOS_SC .equ 2
|
||||
MEM_SC .equ 1
|
||||
DEBUG_SC .equ 0
|
||||
|
||||
;* the traps use numbers similar to those in the
|
||||
;* 68K version of P-CP/M
|
||||
|
||||
NTRAPS .equ 48 ;total number of traps
|
||||
SC0TRAP .equ 32 ;trap # of system call 0
|
||||
|
||||
;Z8000 traps
|
||||
EPUTRAP .equ 1 ;EPU (floating pt. emulator)
|
||||
SEGTRAP .equ 2 ;segmentation (68K bus err)
|
||||
NMITRAP .equ 0 ;non-maskable int.
|
||||
PITRAP .equ 8 ;priviledge violation
|
||||
;Interrupts, etc.
|
||||
TRACETR .equ 9 ; trace
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* C Stack frame equates
|
||||
;*
|
||||
;* A C stack frame consists of the PC on top,
|
||||
;* followed by the arguments, leftmost argument first.
|
||||
;*
|
||||
;* The caller adjusts the stack on return.
|
||||
;* Returned value is in r7 (int) or rr6 (long)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
PCSIZE .equ 2 ;PC size non-segmented
|
||||
INTSIZE .equ 2 ;INT data type size
|
||||
LONGSIZE .equ 4 ;LONG data type size
|
||||
|
||||
ARG1 .equ PCSIZE ;integer arguments
|
||||
ARG2 .equ ARG1+INTSIZE
|
||||
ARG3 .equ ARG2+INTSIZE
|
||||
ARG4 .equ ARG3+INTSIZE
|
||||
ARG5 .equ ARG4+INTSIZE
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Segmented Mode Operations
|
||||
;*
|
||||
;* NOTE: segmented indirect-register operations
|
||||
;* can be done by addressing the low half
|
||||
;* of the register pair.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
SEG .MACRO ; START segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
NONSEG .MACRO ; END segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
scall .MACRO ;(segaddr) segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.long ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
sscall .MACRO ;(|segaddr|) short segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.word ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call Trap Handler Stack Frame
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
cr0 .equ 0 ;WORD caller r0
|
||||
cr1 .equ cr0+2 ;WORD caller r1
|
||||
cr2 .equ cr1+2 ;WORD caller r2
|
||||
cr3 .equ cr2+2 ;WORD caller r3
|
||||
cr4 .equ cr3+2 ;WORD caller r4
|
||||
cr5 .equ cr4+2 ;WORD caller r5
|
||||
cr6 .equ cr5+2 ;WORD caller r6
|
||||
cr7 .equ cr6+2 ;WORD caller r7
|
||||
cr8 .equ cr7+2 ;WORD caller r8
|
||||
cr9 .equ cr8+2 ;WORD caller r9
|
||||
cr10 .equ cr9+2 ;WORD caller r10
|
||||
cr11 .equ cr10+2 ;WORD caller r11
|
||||
cr12 .equ cr11+2 ;WORD caller r12
|
||||
cr13 .equ cr12+2 ;WORD caller r13
|
||||
nr14 .equ cr13+2 ;WORD normal r14
|
||||
nr15 .equ nr14+2 ;WORD normal r15
|
||||
scinst .equ nr15+2 ;WORD SC instruction
|
||||
scfcw .equ scinst+2 ;WORD caller FCW
|
||||
scseg .equ scfcw+2 ;WORD caller PC SEG
|
||||
scpc .equ scseg+2 ;WORD caller PC OFFSET
|
||||
FRAMESZ .equ scpc+2
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
;************ biosdefs2.z8k **************************
|
||||
;*
|
||||
;* Assembly language definitions for
|
||||
;* P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
; 01/11/83 Modified for use with Z8002 (DMH)
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Calls and Trap Indexes
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
XFER_SC .equ 1
|
||||
BIOS_SC .equ 3
|
||||
BDOS_SC .equ 2
|
||||
MEM_SC .equ 1
|
||||
DEBUG_SC .equ 0
|
||||
|
||||
;* the traps use numbers similar to those in the
|
||||
;* 68K version of P-CP/M
|
||||
|
||||
NTRAPS .equ 48 ;total number of traps
|
||||
SC0TRAP .equ 32 ;trap # of system call 0
|
||||
|
||||
;Z8000 traps
|
||||
EPUTRAP .equ 1 ;EPU (floating pt. emulator)
|
||||
SEGTRAP .equ 2 ;segmentation (68K bus err)
|
||||
NMITRAP .equ 0 ;non-maskable int.
|
||||
PITRAP .equ 8 ;priviledge violation
|
||||
;Interrupts, etc.
|
||||
TRACETR .equ 9 ; trace
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* C Stack frame equates
|
||||
;*
|
||||
;* A C stack frame consists of the PC on top,
|
||||
;* followed by the arguments, leftmost argument first.
|
||||
;*
|
||||
;* The caller adjusts the stack on return.
|
||||
;* Returned value is in r7 (int) or rr6 (long)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
co .equ 2 ;call offset, for 8002
|
||||
PCSIZE .equ 2 ;PC size non-segmented
|
||||
INTSIZE .equ 2 ;INT data type size
|
||||
LONGSIZE .equ 4 ;LONG data type size
|
||||
|
||||
ARG1 .equ PCSIZE ;integer arguments
|
||||
ARG2 .equ ARG1+INTSIZE
|
||||
ARG3 .equ ARG2+INTSIZE
|
||||
ARG4 .equ ARG3+INTSIZE
|
||||
ARG5 .equ ARG4+INTSIZE
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Segmented Mode Operations
|
||||
;*
|
||||
;* NOTE: segmented indirect-register operations
|
||||
;* can be done by addressing the low half
|
||||
;* of the register pair.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
SEG .MACRO ; START segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
NONSEG .MACRO ; END segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
scall .MACRO ;(segaddr) segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.long ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
sscall .MACRO ;(|segaddr|) short segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.word ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call Trap Handler Stack Frame
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
cr0 .equ 0 ;WORD caller r0
|
||||
cr1 .equ cr0+2 ;WORD caller r1
|
||||
cr2 .equ cr1+2 ;WORD caller r2
|
||||
cr3 .equ cr2+2 ;WORD caller r3
|
||||
cr4 .equ cr3+2 ;WORD caller r4
|
||||
cr5 .equ cr4+2 ;WORD caller r5
|
||||
cr6 .equ cr5+2 ;WORD caller r6
|
||||
cr7 .equ cr6+2 ;WORD caller r7
|
||||
cr8 .equ cr7+2 ;WORD caller r8
|
||||
cr9 .equ cr8+2 ;WORD caller r9
|
||||
cr10 .equ cr9+2 ;WORD caller r10
|
||||
cr11 .equ cr10+2 ;WORD caller r11
|
||||
cr12 .equ cr11+2 ;WORD caller r12
|
||||
cr13 .equ cr12+2 ;WORD caller r13
|
||||
cr14 .equ cr13+2 ;WORD caller r14
|
||||
nr15 .equ cr14+2 ;WORD normal r15
|
||||
scinst .equ nr15+2 ;WORD SC instruction
|
||||
scfcw .equ scinst+2 ;WORD caller FCW
|
||||
scpc .equ scfcw+2 ;WORD caller PC OFFSET
|
||||
FRAMESZ .equ scpc+2
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
;************ biosif.z8k **************************
|
||||
;*
|
||||
;* Assembly language interface for P-CP/M (tm) BIOS
|
||||
;* ----- System-Independent -----
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split into modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;* The resulting code looks a little odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _biosinit ;C portion init
|
||||
.global _ldcpm ;Load the system into memory
|
||||
|
||||
.global _trapinit ;trap startup
|
||||
|
||||
.global _psap, _sysseg, _sysstk
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios ; initialization
|
||||
.global _input ; input a byte
|
||||
.global _output ; output a byte
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Loader Bios Initialization and Entry Point
|
||||
;*
|
||||
;* This is where control comes after boot.
|
||||
;*
|
||||
;* We get here from bootstrap with:
|
||||
;* segmented mode
|
||||
;* valid stack pointer
|
||||
;* valid PSA in RAM
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
bios:
|
||||
|
||||
; enter in segmented mode.
|
||||
; Get system (PC) segment into r4
|
||||
|
||||
DI VI,NVI
|
||||
calr kludge ; get PC segment on stack
|
||||
kludge: popl rr4, @r14
|
||||
|
||||
; get PSAP into rr2.
|
||||
|
||||
ldctl r2, PSAPSEG
|
||||
ldctl r3, PSAPOFF
|
||||
|
||||
; go non-segmented. save PSAP, system segment,
|
||||
; system stack pointer (in system segment, please)
|
||||
|
||||
NONSEG
|
||||
|
||||
ldl _psap, rr2
|
||||
ld _sysseg, r4
|
||||
ld r14,_sysseg
|
||||
ldl _sysstk, rr14
|
||||
|
||||
; set up traps, then enable interrupts
|
||||
|
||||
call _trapinit
|
||||
EI VI,NVI
|
||||
|
||||
; set up C part of Bios
|
||||
|
||||
call _biosinit
|
||||
|
||||
; Turn control over to command processor
|
||||
|
||||
jp _ldcpm
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* I/O port operations
|
||||
;*
|
||||
;* int = input(port: int)
|
||||
;* output (port, data: int)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_input:
|
||||
ld r2,ARG1(r15)
|
||||
subl rr6,rr6
|
||||
inb rl7,@r2
|
||||
ldb rl6,rl7
|
||||
ret
|
||||
|
||||
|
||||
_output:
|
||||
ld r2,ARG1(r15)
|
||||
ld r3,ARG2(r15)
|
||||
outb @r2,rl3
|
||||
ret
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*****************************************************
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
;************ biosif.z8k **************************
|
||||
;*
|
||||
;* Assembly language interface for P-CP/M (tm) BIOS
|
||||
;* ----- System-Independent -----
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split into modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
; 01/12/83 Adapted for a Z8002 (DMH)
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;* The resulting code looks a little odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _biosinit ;C portion init
|
||||
.global _flush ;Flush buffers
|
||||
|
||||
.global ccp ;Command Processor
|
||||
|
||||
.global _trapinit ;trap startup
|
||||
|
||||
.global _psap, _sysseg, _sysstk
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios ; initialization
|
||||
.global _wboot ; warm boot
|
||||
.global _input ; input a byte
|
||||
.global _output ; output a byte
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios Initialization and Entry Point
|
||||
;*
|
||||
;* This is where control comes after boot.
|
||||
;* Control is transferred to the CCP.
|
||||
;*
|
||||
;* We get here from bootstrap with:
|
||||
;* valid stack pointer
|
||||
;* valid PSA in RAM
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
bios:
|
||||
|
||||
; Get system (PC) segment into r4
|
||||
|
||||
DI VI,NVI
|
||||
|
||||
; get PSAP into r3.
|
||||
|
||||
ldctl r3, PSAPOFF
|
||||
sub r4,r4 ; this will be _sysseg, for consistency
|
||||
ld _psap, r3
|
||||
ld _sysseg, r4
|
||||
ld r14,_sysseg
|
||||
ld _sysstk, r15
|
||||
|
||||
; set up system stack so that a return will warm boot
|
||||
|
||||
push @r15,#_wboot
|
||||
|
||||
|
||||
; set up traps, then enable interrupts
|
||||
|
||||
call _trapinit
|
||||
EI VI,NVI
|
||||
|
||||
; set up C part of Bios
|
||||
|
||||
call _biosinit
|
||||
|
||||
; Turn control over to command processor
|
||||
|
||||
jp ccp
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Warm Boot
|
||||
;*
|
||||
;* flush buffers and initialize Bios
|
||||
;* then transfer to CCP
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
_wboot:
|
||||
call _flush
|
||||
call _biosinit
|
||||
ld r15,_sysstk
|
||||
jp ccp
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* I/O port operations
|
||||
;*
|
||||
;* int = input(port: int)
|
||||
;* output (port, data: int)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_input:
|
||||
ld r2,ARG1(r15)
|
||||
subl rr6,rr6
|
||||
inb rl7,@r2
|
||||
ldb rl6,rl7
|
||||
ret
|
||||
|
||||
|
||||
_output:
|
||||
ld r2,ARG1(r15)
|
||||
ld r3,ARG2(r15)
|
||||
outb @r2,rl3
|
||||
ret
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*****************************************************
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
;************ biosio.z8k **************************
|
||||
;*
|
||||
;* I/O routines for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE The Olivetti PROM routines are segmented.
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
.global _disk_io
|
||||
.global _crt_put
|
||||
.global _cold_boot
|
||||
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Prom Subroutine Access
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_disk_io: ;err=disk_io(drv, cmd, count, blk, addr)
|
||||
|
||||
dec r15,#14 ;save registers
|
||||
ldm @r15,r8,#7
|
||||
|
||||
ldb rh7,14+ARG1+1(r15) ;get args
|
||||
ldb rl7,14+ARG2+1(r15)
|
||||
ld r8, 14+ARG3(r15)
|
||||
ld r9, 14+ARG4(r15)
|
||||
ldl rr10,14+ARG5(r15)
|
||||
|
||||
;rh7 = drive #
|
||||
;rl7 = command
|
||||
;r8 = block count
|
||||
;r9 = block number
|
||||
;rr10 = segmented address
|
||||
|
||||
SEG
|
||||
scall 84000068h
|
||||
NONSEG
|
||||
;r8 = block count not transferred
|
||||
;rh7 = #retries
|
||||
;rl7 = final error code (RETURNED)
|
||||
;rh6 = error retried
|
||||
|
||||
and r7,#0FFh ;value returned in r7
|
||||
|
||||
ldm r8,@r15,#7 ;restore regs
|
||||
inc r15,#14
|
||||
ret
|
||||
|
||||
|
||||
_crt_put: ;crt_put(char)
|
||||
|
||||
dec r15,#14 ;save registers
|
||||
ldm @r15,r8,#7
|
||||
|
||||
ld r1,14+ARG1(r15) ;get arg in r1
|
||||
|
||||
SEG ; SEG clobbers r0
|
||||
ld r0,r1 ;rl0 = char
|
||||
scall 84000080h
|
||||
NONSEG
|
||||
|
||||
ldm r8,@r15,#7 ;restore regs
|
||||
inc r15,#14
|
||||
ret
|
||||
|
||||
|
||||
|
||||
_cold_boot:
|
||||
|
||||
SEG
|
||||
scall 8400008Ch
|
||||
NONSEG
|
||||
ret
|
||||
@@ -0,0 +1,818 @@
|
||||
|
||||
/*
|
||||
***************************************************************************
|
||||
|
||||
This is the Master/requestor portion of a Dual processor P-CP/M BIOS. It
|
||||
should be designed such that only the low level inter-processor transfer
|
||||
protocols and BIOS primitives should have to be modified to accomplish
|
||||
porting to different hardware configurations. Error checking and report-
|
||||
ing is necessary because I/O channel may be unplugged or unreliable.
|
||||
|
||||
***************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Author: David Heintz *
|
||||
* Module: Biosmasc.c *
|
||||
* Creation Date: 10/20/82 *
|
||||
* Language: Standard C *
|
||||
* Version: 1.0 *
|
||||
* Last Mod: 01/20/83 *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* STANDARD HEADERS *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
#include "unstdsys.h"
|
||||
#include "stdcpm.h"
|
||||
#include "stdbios.h"
|
||||
#include "chnequ.h"
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* EXTERNAL DECLARATIONS *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
extern wboot();
|
||||
*************************************************
|
||||
* *
|
||||
* BIOS Entry Point declaration *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
extern LONG _bios();
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Other Globals *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
extern biosinit(); /* Initialize system */
|
||||
extern flush(); /* Flush buffer */
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* I/O Channel Related Externals *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
extern BYTE rcv_cmd();
|
||||
extern BYTE rcv_byte();
|
||||
extern BYTE rcv_word();
|
||||
extern BYTE rcv_long();
|
||||
extern BYTE rcv_data();
|
||||
|
||||
extern BYTE snd_cmd();
|
||||
extern BYTE snd_byte();
|
||||
extern BYTE snd_word();
|
||||
extern BYTE snd_long();
|
||||
extern BYTE snd_data();
|
||||
extern chn_err();
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Machine and Processor Dependent *
|
||||
* Externals *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
extern *memtab;
|
||||
extern LONG trapvec[];
|
||||
extern mem_cpy();
|
||||
extern LONG map_adr();
|
||||
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* LOCAL DEFINITIONS *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
static char signon[] = "\n\rKontron Z8000 BIOS v. 1.0 11/23/82\n\r";
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Check Vectors *
|
||||
* 512 Directory Entries Maximum *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
BYTE csvtab[8][128] = {{0}};
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Allocation Vectors *
|
||||
* 2048 Allocation Blocks Maximum *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
BYTE alvtab[8][256] = {{0}};
|
||||
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Data Parameter Blocks *
|
||||
* Unitialized *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
DPB dpbtab[8] = {0};
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Directory Buffer *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
BYTE dirbuf[128] = {0};
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Disk Parameter Headers *
|
||||
* Maximum of 8 defined *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
DPH dphtab[8] =
|
||||
/*
|
||||
{ *xltp, dphscr[3], *dirbufp, *dpbp, *csvp, *alvp}
|
||||
*/
|
||||
{
|
||||
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[0], csvtab[0], alvtab[0]},
|
||||
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[1], csvtab[1], alvtab[1]},
|
||||
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[2], csvtab[2], alvtab[2]},
|
||||
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[3], csvtab[3], alvtab[3]},
|
||||
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[4], csvtab[4], alvtab[4]},
|
||||
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[5], csvtab[5], alvtab[5]},
|
||||
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[6], csvtab[6], alvtab[6]},
|
||||
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[7], csvtab[7], alvtab[7]},
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Time-Honored BIOS Variables *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
static LONG dmaadr = 0; /* Caller's data transfer address */
|
||||
static WORD sector = 0; /* Current sector (Unused) */
|
||||
static WORD track = 0; /* Current track (Unused) */
|
||||
static BYTE disk = 0; /* Current drive number (Unused) */
|
||||
static BYTE IOBYTE = 0; /* Logical to physical mapping (Unused) */
|
||||
static BYTE retry = 0xff; /* I/O channel retry boolean */
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Sector Buffer *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
static BYTE secbuf[seclen] = {0};
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* MISCELLANEOUS FUNCTIONS *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Print a Message |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: Pointer to message
|
||||
/ terminated by '\0'
|
||||
/ Outputs: None
|
||||
/ Actions: Send message to slave
|
||||
/ console output.
|
||||
/
|
||||
*/
|
||||
|
||||
prtmsg(pbyte)
|
||||
BYTE *pbyte;
|
||||
{
|
||||
char c;
|
||||
while(c = *(pbyte++))
|
||||
_bios((WORD)coreq, (LONG)c, 0L);
|
||||
}
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Illegal Command |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Currently unused
|
||||
/
|
||||
*/
|
||||
|
||||
ill_cmd()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ biosinit(); |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Initialize hardware
|
||||
/
|
||||
*/
|
||||
|
||||
biosinit()
|
||||
{
|
||||
prtmsg(signon);
|
||||
_bios((WORD)inreq, 0L, 0L); /* Make BIOS request */
|
||||
}
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Flush Disk Buffer |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Flush Disk Buffer on Slave
|
||||
/
|
||||
*/
|
||||
|
||||
flush()
|
||||
{
|
||||
_bios((WORD)fbreq, 0L, 0L); /* Ignore return code? */
|
||||
}
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ snd_rcv(): |
|
||||
/ send a command and |
|
||||
/ receive a parameter |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: BIOS parameters d0, d1, d2
|
||||
/ Outputs: LONG return parameter
|
||||
/ Actions: Send command through fifo and
|
||||
/ receive return parameter
|
||||
/
|
||||
*/
|
||||
|
||||
LONG snd_rcv(d0, d1, d2)
|
||||
WORD d0;
|
||||
LONG d1, d2;
|
||||
{
|
||||
BYTE code;
|
||||
LONG temp;
|
||||
do
|
||||
{
|
||||
code = snd_cmd(d0, d1, d2);
|
||||
if (code == chsuc)
|
||||
code = rcv_long(&temp);
|
||||
if (code != chsuc)
|
||||
{
|
||||
chn_err(d0, code);
|
||||
temp = cherr;
|
||||
}
|
||||
}
|
||||
while (retry && (code != chsuc));
|
||||
return(temp);
|
||||
}
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* P-CP/M BIOS ENTRY POINT *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
LONG _bios(d0, d1, d2)
|
||||
WORD d0;
|
||||
LONG d1, d2;
|
||||
|
||||
{
|
||||
char zzz = {"kludge "};
|
||||
switch(d0)
|
||||
{
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 4: |
|
||||
/ Console Output |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: (BYTE) d1 contains character
|
||||
/ to output to slave console
|
||||
/ Outputs: None
|
||||
/ Actions: Output character from master
|
||||
/ to slave console I/O.
|
||||
*/
|
||||
case coreq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 5: |
|
||||
/ List Output |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: (BYTE) d1 contains character
|
||||
/ to output to slave list device.
|
||||
/ Outpus: None
|
||||
/ Actions: Output character from master
|
||||
/ to slave list I/O.
|
||||
*/
|
||||
case loreq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 6: |
|
||||
/ Auxilliary Output |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: (BYTE) d1 contains character
|
||||
/ to output to slave aux. device.
|
||||
/ Outputs: None
|
||||
/ Actions: Output character from master
|
||||
/ to slave auxilliary (punch) I/O.
|
||||
*/
|
||||
case aoreq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 8: |
|
||||
/ Home disk |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Perform slave home disk function.
|
||||
*/
|
||||
case hdreq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 10: |
|
||||
/ Set Track |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: (WORD) d1 contains track number.
|
||||
/ Outputs: None
|
||||
/ Actions: Set track number from master on slave.
|
||||
*/
|
||||
case streq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 11: |
|
||||
/ Set Sector |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: (WORD) d1 contains sector number
|
||||
/ Outputs: None
|
||||
/ Actions: Set sector number from master on slave.
|
||||
*/
|
||||
case ssreq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 20: |
|
||||
/ Set I/O byte |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: BYTE d1 contains IOBYTE value
|
||||
/ Outputs: None
|
||||
/ Actions: Send contents of slave
|
||||
/ location IOBYTE to master.
|
||||
*/
|
||||
case sireq: /* Fall through to next case */
|
||||
|
||||
|
||||
/* All degenerate cases of BIOS functions */
|
||||
/* end up falling through to here. Request */
|
||||
/* is forwarded to the slave BIOS and no */
|
||||
/* parameters are returned to the master. */
|
||||
|
||||
{
|
||||
BYTE code;
|
||||
code = snd_cmd(d0, d1, d2);
|
||||
if (code != chsuc)
|
||||
chn_err(d0, code);
|
||||
}
|
||||
break; /* Request completed. */
|
||||
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 2: |
|
||||
/ Console Status |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: returns console status.
|
||||
/ Actions: receive 1-byte slave con-
|
||||
/ sole status.
|
||||
*/
|
||||
case csreq: /* Fall through to next case */
|
||||
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 7: |
|
||||
/ Auxilliary Input |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: Return character from aux device
|
||||
/ Actions: Input a character from slave
|
||||
/ auxilliary (reader) I/O to master.
|
||||
*/
|
||||
|
||||
case aireq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 15: |
|
||||
/ List Status |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: Return status of slave list device.
|
||||
/ Actions: Send 1-byte slave list
|
||||
/ status to master.
|
||||
*/
|
||||
case lsreq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 16: |
|
||||
/ Translate Sector |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: (LONG) d1 is sector translation table address
|
||||
/ (WORD) d2 is sector number to be translated
|
||||
/ Outputs: Return translated sector.
|
||||
/ Actions: Perform slave BIOS sector
|
||||
/ translation call
|
||||
*/
|
||||
case tsreq: /* Fall through to next case */
|
||||
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 19: |
|
||||
/ Get I/O byte |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: Returns IOBYTE value from slave.
|
||||
/ Actions: Receive byte from master and
|
||||
/ store in slave location IOBYTE.
|
||||
*/
|
||||
case gireq: /* Fall through to next case */
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 21: |
|
||||
/ Flush disk buffer |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Send request to slave
|
||||
/
|
||||
*/
|
||||
case fbreq: /* Fall through to next case */
|
||||
|
||||
/* All cases which return status or data */
|
||||
/* end up falling through to here. Request */
|
||||
/* passed on to the slave BIOS and a long */
|
||||
/* parameter is returned to the master. */
|
||||
|
||||
return(snd_rcv(d0, d1, d2));
|
||||
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 0: |
|
||||
/ System Init |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Initialize Master.
|
||||
/ Just print message, so far.
|
||||
*/
|
||||
case inreq:
|
||||
break;
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 1: |
|
||||
/ Warm Boot |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Warm boot master.
|
||||
*/
|
||||
case wbreq:
|
||||
wboot();
|
||||
break;
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 3: |
|
||||
/ Console Input |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: returns console character.
|
||||
/ Actions: Input character from
|
||||
/ slave console to master.
|
||||
*/
|
||||
case cireq:
|
||||
while(!_bios(csreq, 0L, 0L));
|
||||
return(snd_rcv(d0, d1, d2));
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 9: |
|
||||
/ Select Disk |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: Pointer to DPH for selected drive.
|
||||
/ Null if illegal drive.
|
||||
/ Actions: Select drive number from master on slave.
|
||||
/ Return condition code from slave to master.
|
||||
/ Pass selected drive's DPB from slave to master,
|
||||
/ if drive selected.
|
||||
*/
|
||||
case sdreq:
|
||||
|
||||
{
|
||||
BYTE code;
|
||||
LONG temp;
|
||||
DPH *dphptr;
|
||||
DPB *dpbptr;
|
||||
do
|
||||
{
|
||||
code = snd_cmd(d0, d1, d2);
|
||||
if (code == chsuc)
|
||||
code = rcv_long(&temp);
|
||||
if (code == chsuc)
|
||||
if ((DPH *)temp != NULL)
|
||||
{
|
||||
dphptr = &dphtab[d1];
|
||||
dpbptr = dphptr -> dpbp;
|
||||
if (!((BYTE)d2 & 0x1))
|
||||
{
|
||||
code = rcv_long(&temp);
|
||||
if (code == chsuc)
|
||||
(dphptr -> xltp) = (BYTE *)temp;
|
||||
if (code == chsuc)
|
||||
code = rcv_word(&(dpbptr -> spt));
|
||||
if (code == chsuc)
|
||||
code = rcv_byte(&(dpbptr -> bsh));
|
||||
if (code == chsuc)
|
||||
code = rcv_byte(&(dpbptr -> blm));
|
||||
if (code == chsuc)
|
||||
code = rcv_byte(&(dpbptr -> exm));
|
||||
if (code == chsuc)
|
||||
code = rcv_word(&(dpbptr -> dsm));
|
||||
if (code == chsuc)
|
||||
code = rcv_word(&(dpbptr -> drm));
|
||||
if (code == chsuc)
|
||||
code = rcv_byte(&(dpbptr -> al0));
|
||||
if (code == chsuc)
|
||||
code = rcv_byte(&(dpbptr -> al1));
|
||||
if (code == chsuc)
|
||||
code = rcv_word(&(dpbptr -> cks));
|
||||
if (code == chsuc)
|
||||
code = rcv_word(&(dpbptr -> off));
|
||||
}
|
||||
temp = (LONG)dphptr;
|
||||
}
|
||||
else temp = (LONG)NULL;
|
||||
if (code != chsuc)
|
||||
{
|
||||
chn_err(sdreq, code);
|
||||
temp = (LONG)cherr;
|
||||
}
|
||||
}
|
||||
while (retry && (code != chsuc));
|
||||
return(temp);
|
||||
}
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 13: |
|
||||
/ Read Sector |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: Read completion status
|
||||
/ Actions: Receive a 128 byte sector specified by
|
||||
/ current drive, sector, track from slave
|
||||
/ and place it at the current DMA add-
|
||||
/ ress.
|
||||
*/
|
||||
case rsreq:
|
||||
|
||||
{
|
||||
BYTE stat, code;
|
||||
LONG temp;
|
||||
do
|
||||
{
|
||||
code = snd_cmd(d0, d1, d2);
|
||||
if (code == chsuc)
|
||||
code = rcv_byte(&stat);
|
||||
if ((stat == rssuc) && (code == chsuc))
|
||||
code = rcv_data(&secbuf[0], seclen);
|
||||
if (code == chsuc)
|
||||
temp = (LONG)stat;
|
||||
else
|
||||
{
|
||||
chn_err(d0, code);
|
||||
temp = cherr;
|
||||
}
|
||||
}
|
||||
while (retry && (code != chsuc));
|
||||
if (temp == rssuc)
|
||||
mem_cpy(map_adr((LONG)secbuf, 0),(LONG)dmaadr,(LONG)seclen);
|
||||
return(temp);
|
||||
}
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 14: |
|
||||
/ Write Sector |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: Write type.
|
||||
/ Outputs: Write sector completion status.
|
||||
/ Actions: Send a 128 byte sector from current DMA
|
||||
/ address to slave.
|
||||
/ Receive a 1-byte completion code, in-
|
||||
/ dicating if write successful or not.
|
||||
*/
|
||||
case wsreq:
|
||||
|
||||
{
|
||||
BYTE stat, code;
|
||||
LONG temp;
|
||||
do
|
||||
{
|
||||
mem_cpy((LONG)dmaadr,map_adr((LONG)secbuf,0),(LONG)seclen);
|
||||
code = snd_cmd(d0, d1, d2);
|
||||
if (code == chsuc)
|
||||
code = snd_data(&secbuf[0], seclen);
|
||||
if (code == chsuc)
|
||||
code = rcv_byte(&stat);
|
||||
if (code == chsuc)
|
||||
temp = (LONG)stat;
|
||||
else
|
||||
{
|
||||
chn_err(d0, code);
|
||||
temp = cherr;
|
||||
}
|
||||
}
|
||||
while (retry && (code != chsuc));
|
||||
return(temp);
|
||||
}
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 12: |
|
||||
/ Set DMA Address |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: (LONG) d1 contains DMA address.
|
||||
/ Outputs: None
|
||||
/ Actions: Set DMA address from master.
|
||||
*/
|
||||
case sareq:
|
||||
|
||||
dmaadr = d1;
|
||||
break;
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 17: |
|
||||
/ Get Memory Table |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: Return pointer to memory region table
|
||||
/ Actions: None
|
||||
*/
|
||||
case gmreq:
|
||||
return((long)&memtab);
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Function 22: |
|
||||
/ Set Exception Vector |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Currently unused
|
||||
/
|
||||
*/
|
||||
case svreq:
|
||||
{
|
||||
LONG oldval;
|
||||
oldval = trapvec[(int)d1];
|
||||
trapvec[(int)d1] = d2;
|
||||
return(oldval);
|
||||
}
|
||||
|
||||
/*
|
||||
/--------------------------------
|
||||
/ |
|
||||
/ Illegal Request |
|
||||
/ |
|
||||
/--------------------------------
|
||||
/ Inputs: None
|
||||
/ Outputs: None
|
||||
/ Actions: Currently unused
|
||||
/
|
||||
*/
|
||||
|
||||
default:
|
||||
ill_cmd(); /* Illegal command */
|
||||
break;
|
||||
|
||||
} /* End of Switch */
|
||||
} /* End of BIOS */
|
||||
@@ -0,0 +1,234 @@
|
||||
;************ biosmem.z8k **************************
|
||||
;*
|
||||
;* Memory Management for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* This module copies data from one memory space
|
||||
;* to another. The machine-dependent parts of
|
||||
;* the mapping are well isolated.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
|
||||
.global memsc
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global xfersc
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1) -> addr
|
||||
;* sets user seg# from addr
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* control transfer to context at addr.
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* x+256 x=1, 3, 5 : segmented I-space addr.
|
||||
;* instead of data access
|
||||
;*
|
||||
;* FFFF: set user segment
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
memsc: ;memory manager system call
|
||||
; CALLED FROM SC
|
||||
; IN SEGMENTED MODE
|
||||
; rr6: source
|
||||
; rr4: dest / space
|
||||
; rr2: length / 0
|
||||
testl rr2
|
||||
jr z mem_map
|
||||
|
||||
mem_copy: ; copy data.
|
||||
; rr6: source
|
||||
; rr4: dest
|
||||
; rr2: length
|
||||
ldirb @r4,@r6,r3
|
||||
ldl rr6,rr4 ; rr6 = dest + length
|
||||
ret
|
||||
|
||||
mem_map: ; map address
|
||||
; rr6: source
|
||||
; r4: caller's seg.
|
||||
; r5: space
|
||||
; r2: caller's FCW
|
||||
NONSEG
|
||||
|
||||
cp r5,#-2 ; space=-2: xfer
|
||||
jp eq xfersc
|
||||
|
||||
ld r4,scseg+4(r15)
|
||||
ld r2,scfcw+4(r15)
|
||||
calr map_1
|
||||
ldl cr6+4(r15),rr6 ; return rr6
|
||||
SEG
|
||||
ret
|
||||
|
||||
map_1: ; dispatch
|
||||
|
||||
cp r5,#0FFFFh
|
||||
jr eq set_usr ; space=-1: user seg
|
||||
|
||||
cpb rl5,#0
|
||||
jr eq call_data
|
||||
cpb rl5,#1
|
||||
jr eq call_prog
|
||||
cpb rl5,#2
|
||||
jr eq sys_data
|
||||
cpb rl5,#3
|
||||
jr eq sys_prog
|
||||
cpb rl5,#4
|
||||
jr eq usr_data
|
||||
cpb rl5,#5
|
||||
jr eq usr_prog
|
||||
|
||||
ret ;default: no mapping
|
||||
|
||||
set_usr: ;-1: set user seg.
|
||||
ld _usrseg,r6
|
||||
ret
|
||||
|
||||
;*
|
||||
;*** THE FOLLOWING CODE IS SYSTEM-DEPENDENT ***
|
||||
;*
|
||||
;* rr6= logical address
|
||||
;* r4 = caller's PC segment
|
||||
;* r2 = caller's FCW
|
||||
;* returns
|
||||
;* rr6= mapped address
|
||||
;*
|
||||
;* Most of the system dependencies are in map_prog,
|
||||
;* which maps a program segment into a data segment
|
||||
;* for access as data.
|
||||
;*
|
||||
|
||||
call_data:
|
||||
bit r2,#15 ; segmented caller?
|
||||
ret nz ; yes-- use passed seg
|
||||
ld r6,r4 ; no -- use pc segment
|
||||
ret ; already mapped
|
||||
|
||||
call_prog:
|
||||
bit r2,#15 ; segmented caller?
|
||||
jr nz map_prog ; yes-- use passed seg
|
||||
ld r6,r4 ; no -- use pc segment
|
||||
jr map_prog ; map prog as data
|
||||
|
||||
sys_data:
|
||||
ld r6, _sysseg
|
||||
ret
|
||||
|
||||
sys_prog:
|
||||
ld r6, _sysseg
|
||||
ret ; assume sys does not
|
||||
; separate code, data
|
||||
|
||||
usr_data:
|
||||
ld r0, #-1
|
||||
cp r0, _usrseg
|
||||
ret eq
|
||||
ld r6, _usrseg
|
||||
ret
|
||||
|
||||
usr_prog:
|
||||
ld r0, #-1
|
||||
cp r0, _usrseg
|
||||
jr eq map_prog
|
||||
ld r6, _usrseg
|
||||
jr map_prog
|
||||
|
||||
|
||||
map_prog: ;map program addr into data
|
||||
; rr6 = address
|
||||
|
||||
testb rh5 ; data access?
|
||||
ret nz ; no: done
|
||||
|
||||
and r6,#7F00h ; extract seg bits
|
||||
|
||||
; olivetti: segment 8 is the only one with
|
||||
; separate I and D spaces, and
|
||||
; the program space is accessed
|
||||
; as segment 10's data.
|
||||
|
||||
cpb rh6,#8
|
||||
ret ne
|
||||
ldb rh6,#10
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Data
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_sysseg: .block 2 ;system segment
|
||||
_usrseg: .block 2 ;user segment
|
||||
_sysstk: .block 4 ;system stack pointer
|
||||
_psap: .block 4 ;program status area ptr
|
||||
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
@@ -0,0 +1,303 @@
|
||||
;************ biosmem2.z8k **************************
|
||||
;*
|
||||
;* Memory Management for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
; 01/12/83 Adapted for Z8002 (DMH, FMZ)
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* This module copies data from one memory space
|
||||
;* to another. The machine-dependent parts of
|
||||
;* the mapping are well isolated.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
.global _mem_mov, _map_wdw
|
||||
.global memsc
|
||||
|
||||
.global _blkmov
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global xfersc
|
||||
.global _mem_bcp
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1) -> addr
|
||||
;* sets user seg# from addr
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* control transfer to context at addr.
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* The following does not apply in Z8002 case
|
||||
;*
|
||||
;* x+256 x=1, 3, 5 : segmented I-space addr.
|
||||
;* instead of data access
|
||||
;*
|
||||
;* FFFF: set user segment
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
memsc: ;memory manager system call
|
||||
; CALLED FROM SC
|
||||
; IN SEGMENTED MODE
|
||||
; rr6: source
|
||||
; rr4: dest / space
|
||||
; rr2: length / 0
|
||||
testl rr2
|
||||
jr z mem_map
|
||||
|
||||
|
||||
mem_copy: ; copy data.
|
||||
; rr6: source
|
||||
; rr4: dest
|
||||
; rr2: length
|
||||
push @r15,r3 ; push length as a short!
|
||||
pushl @r15,rr4 ; push dest
|
||||
pushl @r15, rr6 ; push source
|
||||
call _mem_bcp ; call C copy routine
|
||||
ldl rr6,4(r15) ; get dest into rr6
|
||||
add r7,8(r15) ; return dest plus length
|
||||
inc r15,#10 ; restore stack
|
||||
ret
|
||||
|
||||
mem_map: ; map address
|
||||
; rr6: source
|
||||
; r4: caller's seg.
|
||||
; r5: space
|
||||
; r2: caller's FCW
|
||||
|
||||
cp r5,#-2 ; space=-2: xfer
|
||||
jp eq xfersc
|
||||
|
||||
;* ld r4,scseg+co(r15) Not done in Z8002 implementation
|
||||
ld r2,scfcw+co(r15)
|
||||
calr map_1
|
||||
ldl cr6+co(r15),rr6 ; return rr6
|
||||
ret
|
||||
|
||||
map_1: ; dispatch
|
||||
|
||||
cp r5,#0FFFFh
|
||||
jr eq set_usr ; space=-1: user seg
|
||||
|
||||
cpb rl5,#0
|
||||
jr eq call_data
|
||||
cpb rl5,#1
|
||||
jr eq call_prog
|
||||
cpb rl5,#2
|
||||
jr eq sys_data
|
||||
cpb rl5,#3
|
||||
jr eq sys_prog
|
||||
cpb rl5,#4
|
||||
jr eq usr_data
|
||||
cpb rl5,#5
|
||||
jr eq usr_prog
|
||||
|
||||
ret ;default: no mapping
|
||||
|
||||
set_usr: ;-1: set user seg.
|
||||
ld _usrseg,r6
|
||||
ret
|
||||
|
||||
;*
|
||||
;*** THE FOLLOWING CODE IS SYSTEM-DEPENDENT ***
|
||||
;*
|
||||
;* rr6= logical address
|
||||
;* r4 = caller's PC segment - but NOT in the Z8002 implementation!
|
||||
;* r2 = caller's FCW
|
||||
;* returns
|
||||
;* rr6= mapped address
|
||||
;*
|
||||
;* This code is much simpler than the corresponding
|
||||
;* Z8001 code. If the caller's FCW indicates that he
|
||||
;* was in Normal mode, then _usrseg is returned.
|
||||
;* Otherwise, pseudo-segment 0 is returned.
|
||||
;*
|
||||
|
||||
call_data:
|
||||
bit r2,#14 ; System caller?
|
||||
jr nz sys_data ; yes-- use system seg
|
||||
ld r6,_usrseg ; no -- use pc segment
|
||||
ret
|
||||
|
||||
call_prog:
|
||||
bit r2,#14 ; System caller?
|
||||
jr nz sys_prog ; yes-- use system seg
|
||||
ld r6,_usrseg ; no 00 use pc segment
|
||||
jr map_prog ; map prog as data
|
||||
|
||||
sys_data:
|
||||
sys_prog:
|
||||
ld r6, _sysseg
|
||||
ret ; assume sys does not
|
||||
; separate code, data
|
||||
|
||||
usr_data:
|
||||
ld r6, _usrseg
|
||||
ret
|
||||
|
||||
usr_prog:
|
||||
ld r6, _usrseg
|
||||
jr map_prog
|
||||
|
||||
|
||||
map_prog: ; map program addr into data
|
||||
; rr6 = address
|
||||
|
||||
and r6,#7F00h ; extract seg bits
|
||||
|
||||
; kontron: pseudo-segment 2 is the only one with
|
||||
; separate I and D spaces, and
|
||||
; the program space is accessed
|
||||
; as pseudo-segment 1, data space as pseudo-segment 2
|
||||
|
||||
cpb rh6,#2
|
||||
ret ne
|
||||
ldb rh6,#1
|
||||
ret
|
||||
|
||||
;*
|
||||
;* The following routine copies a block of data from one part
|
||||
;* of the system address space to another. In practice, part
|
||||
;* of the address space may be windowed, but that is transparent
|
||||
;* here.
|
||||
;*
|
||||
;* The interface is:
|
||||
;* blkmov(source,dest,length)
|
||||
;* short source,dest,length;
|
||||
;*
|
||||
|
||||
_blkmov:
|
||||
ld r5,ARG1(r15) ; r5: source
|
||||
ld r4,ARG2(r15) ; r4: dest
|
||||
ld r2,ARG3(r15) ; r2: length (just a word!)
|
||||
ld r7,r2 ; return value = bytes copied
|
||||
ldirb @r4,@r5,r2 ; copy!
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;* mem_mov -- C callable block move routine
|
||||
;* input stack:
|
||||
;* ret. addr (word)
|
||||
;* source (word)
|
||||
;* destination (word)
|
||||
;* length, bytes (word)
|
||||
|
||||
_mem_mov:
|
||||
ld r5,2(r15) ; pull off source
|
||||
ld r7,4(r15) ; pull off destination
|
||||
ld r0,6(r15) ; pull off length
|
||||
ldirb @r7,@r5,r0 ; block move
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;* map_wdw -- C callable map window routine,
|
||||
; system dependent.
|
||||
;* input stack:
|
||||
;* ret. addr (word)
|
||||
;* window code (word)
|
||||
;* 2 means physical block 2
|
||||
;* 3 means physical block 3
|
||||
;* x means physical block 1
|
||||
;*
|
||||
;* Note: the manual is unclear, but implies that
|
||||
;* history must be kept concerning the window
|
||||
;* mapping, if the window was last block 3.
|
||||
;* That is why I map block one before others.
|
||||
;* See ECB/C16 Hardware description for details.
|
||||
|
||||
_map_wdw:
|
||||
ld r0,2(r15) ; pull off window code
|
||||
out 0c000h,r0 ; map physical block 1
|
||||
cp r0,#2 ; map physical block 2?
|
||||
jr nz,map_wdw_3 ; No, go for physical block 3.
|
||||
out 8001h,r0 ; Funny port address, huh?
|
||||
ret
|
||||
|
||||
map_wdw_3:
|
||||
cp r0,#3 ; map pysical block 3?
|
||||
ret nz ; no, already mapped to 1.
|
||||
|
||||
out 0c001h,r0 ; yes.
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Data
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_sysseg: .block 2 ;system segment
|
||||
_usrseg: .block 2 ;user segment
|
||||
_sysstk: .block 2 ;system stack pointer
|
||||
_psap: .block 2 ;program status area ptr
|
||||
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,370 @@
|
||||
;************ biostrap.z8k **************************
|
||||
;*
|
||||
;* Trap handlers for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created
|
||||
;* 821123 D. Dunlop (Zilog) -- added Olivetti M20-
|
||||
;* specific code to invalidate track buffer
|
||||
;* contents when disk drive motor stops
|
||||
;* (fixes directory-overwrite on disk change)
|
||||
;* 830305 D. Sallume (Zilog) -- added FPE trap
|
||||
;* code.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* Trap and interrupt handlers are started up
|
||||
;* in segmented mode.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _bios ;C portion of BIOS
|
||||
.global memsc ;memory-management SC
|
||||
.global _tbvalid ;disk track buff valid
|
||||
.global _tbdirty ;disk track buff is dirty
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* M-20 ROM scratchpad RAM addresses
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
rtc_ext: .equ 82000022h ;Place to put address
|
||||
; of list of functions
|
||||
; for each clock tick
|
||||
motor_on: .equ 82000020h ;Disk motor timeout
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _trapinit
|
||||
.global _trapvec
|
||||
.global _trap
|
||||
|
||||
.global xfersc
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap vector table
|
||||
;*
|
||||
;* entries 0..31 are misc. system traps
|
||||
;* entries 32..47 are system calls 0..15
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_trapvec:
|
||||
.block NTRAPS*4
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call and General Trap Handler And Dispatch
|
||||
;*
|
||||
;* It is assumed that the system runs
|
||||
;* non-segmented on a segmented CPU.
|
||||
;*
|
||||
;* _trap is jumped to segmented, with the
|
||||
;* following information on the stack:
|
||||
;*
|
||||
;* trap type: WORD
|
||||
;* reason: WORD
|
||||
;* fcw: WORD
|
||||
;* pc: LONG
|
||||
;*
|
||||
;* The trap handler is called as a subroutine,
|
||||
;* with all registers saved on the stack,
|
||||
;* IN SEGMENTED MODE. This allows the trap
|
||||
;* handler to be in another segment (with some
|
||||
;* care). This is useful mainly to the debugger.
|
||||
;*
|
||||
;* All registers except rr0 are also passed
|
||||
;* intact to the handler.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
sc_trap: ;system call trap server
|
||||
|
||||
push @r14,@r14
|
||||
|
||||
|
||||
_trap:
|
||||
|
||||
sub r15,#30 ; push caller state
|
||||
ldm @r14,r0,#14
|
||||
NONSEG ; go nonsegmented
|
||||
ldctl r1,NSP
|
||||
ld nr14(r15),r14
|
||||
ex r1,nr15(r15)
|
||||
|
||||
; trap# now in r1
|
||||
cpb rh1,#7Fh ; system call?
|
||||
jr ne trap_disp ; no
|
||||
; yes: map it
|
||||
clrb rh1
|
||||
add r1,#SC0TRAP
|
||||
|
||||
;=== need range check ===
|
||||
|
||||
trap_disp: ; dispatch
|
||||
sll r1,#2
|
||||
ldl rr0,_trapvec(r1)
|
||||
testl rr0
|
||||
jr z _trap_ret ; zero -- no action
|
||||
; else call seg @rr0
|
||||
pushl @r15,rr0 ; (done via kludge)
|
||||
SEG
|
||||
popl rr0,@r14
|
||||
calr trap_1
|
||||
jr _trap_ret
|
||||
|
||||
trap_1: ; jp @rr0
|
||||
pushl @r14,rr0
|
||||
ret
|
||||
|
||||
|
||||
_trap_ret: ;return from trap or interrupt
|
||||
|
||||
NONSEG
|
||||
ld r1,nr15(r15) ; pop state
|
||||
ld r14,nr14(r15)
|
||||
ldctl NSP,r1
|
||||
SEG ; go segmented for the iret.
|
||||
ldm r0,@r14,#14
|
||||
add r15,#32
|
||||
|
||||
iret ; return from interrupt
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Assorted Trap Handlers
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
epu_trap:
|
||||
push @r14,#EPUTRAP
|
||||
jr _trap
|
||||
|
||||
pi_trap:
|
||||
push @r14,#PITRAP
|
||||
jr _trap
|
||||
|
||||
seg_trap:
|
||||
push @r14,#SEGTRAP
|
||||
jr _trap
|
||||
|
||||
nmi_trap:
|
||||
push @r14,#NMITRAP
|
||||
jr _trap
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios system call handler
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;biossc: ;call bios
|
||||
; NONSEG
|
||||
; ; r3 = operation code
|
||||
; ; rr4= P1
|
||||
; ; rr6= P2
|
||||
;
|
||||
; ld r0,scfcw+4(r15) ; if caller nonseg, normal
|
||||
; and r0,#0C000h
|
||||
; jr nz seg_ok
|
||||
;
|
||||
; ld r4,scseg+4(r15) ; then add seg to P1, P2
|
||||
; ld r6,r4
|
||||
;seg_ok:
|
||||
; ; set up C stack frame
|
||||
;;===
|
||||
; pushl @r15,rr6
|
||||
; pushl @r15,rr4
|
||||
; push @r15,r3
|
||||
;
|
||||
; ; call C program
|
||||
; call _bios
|
||||
;
|
||||
; ; clean stack & return
|
||||
; add r15,#10
|
||||
; ldl cr6+4(r15),rr6 ; with long in rr6
|
||||
;
|
||||
; SEG
|
||||
; ret
|
||||
;
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch System Call
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC segment
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
xfersc: ;enter here from system call
|
||||
SEG
|
||||
|
||||
; build frame on system stack
|
||||
|
||||
; when called from system call, the frame replaces
|
||||
; the caller's context, which will never be resumed.
|
||||
|
||||
inc r15,#4 ;discard return addr
|
||||
ldl rr4,rr14 ;move context
|
||||
ld r2,#FRAMESZ/2
|
||||
ldir @r4,@r6,r2
|
||||
jr _trap_ret ;restore context
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _motor_c -- check if disk motor still running.
|
||||
;* Entered each clock tick. Invalidates
|
||||
;* track buffer when motor stops
|
||||
;* (Note: runs segmented)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_motor_c:
|
||||
ldl rr4,#motor_on ;Motor running?
|
||||
test @r4
|
||||
ret nz ;Yes: do nothing
|
||||
ldar r4,$
|
||||
ld r5,#_tbdirty ; Is track buff dirty?
|
||||
test @r4 ; Yes...
|
||||
ret nz ; ...return without invalidating
|
||||
ld r5,#_tbvalid
|
||||
clr @r4 ;No: mark track buffer
|
||||
ret ; invalid
|
||||
|
||||
; Table of functions run each real time clock tick
|
||||
|
||||
_ticktab:
|
||||
.long -1 ;Will contain _motor_c
|
||||
.word 0ffffh ;Terminator
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _trapinit -- initialize trap system
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;*
|
||||
;* PSA (Program Status Area) structure
|
||||
;*
|
||||
ps .equ 8 ; size of a program status entry
|
||||
; --- segmented ---
|
||||
|
||||
psa_epu .equ 1*ps ; EPU trap offset
|
||||
psa_prv .equ 2*ps ; priviledged instruction trap
|
||||
psa_sc .equ 3*ps ; system call trap
|
||||
psa_seg .equ 4*ps ; segmentation trap
|
||||
psa_nmi .equ 5*ps ; non-maskable interrupt
|
||||
psa_nvi .equ 6*ps ; non-vectored interrupt
|
||||
psa_vi .equ 7*ps ; vectored interrupt
|
||||
psa_vec .equ psa_vi+(ps/2) ; vectors
|
||||
|
||||
|
||||
_trapinit:
|
||||
|
||||
; initialize trap table
|
||||
|
||||
lda r2,_trapvec
|
||||
ld r0,#NTRAPS
|
||||
subl rr4,rr4
|
||||
clrtraps:
|
||||
ldl @r2,rr4
|
||||
inc r2,#4
|
||||
djnz r0,clrtraps
|
||||
|
||||
ld r2,_sysseg
|
||||
; lda r3,biossc
|
||||
; ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2
|
||||
lda r3,memsc
|
||||
ldl _trapvec+(MEM_SC+SC0TRAP)*4,rr2
|
||||
; lda r3,fp_epu
|
||||
; ldl _trapvec+EPUTRAP*4,rr2
|
||||
|
||||
|
||||
; initialize some PSA entries.
|
||||
; rr0 PSA entry: FCW (ints ENABLED)
|
||||
; rr2 PSA entry: PC
|
||||
; rr4 -> PSA slot
|
||||
|
||||
ldl rr4,_psap
|
||||
SEG
|
||||
ldl rr0,#0000D800h
|
||||
|
||||
add r5,#ps ; EPU trap
|
||||
ldar r2,epu_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; Priviledged Inst
|
||||
ldar r2,pi_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; System Call
|
||||
ldar r2,sc_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; segmentation
|
||||
ldar r2,seg_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; Non-Maskable Int.
|
||||
ldar r2,nmi_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
; Set up Real-Time Clock external call loc
|
||||
|
||||
ldar r2,_motor_c
|
||||
ldar r4,_ticktab
|
||||
ldl @r4,rr2
|
||||
ldl rr2,#rtc_ext
|
||||
ldl @r2,rr4
|
||||
NONSEG
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
@@ -0,0 +1,294 @@
|
||||
;************ biostrap.z8k **************************
|
||||
;*
|
||||
;* Trap handlers for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created
|
||||
;* 821123 D. Dunlop (Zilog) -- added Olivetti M20-
|
||||
;* specific code to invalidate track buffer
|
||||
;* contents when disk drive motor stops
|
||||
;* (fixes directory-overwrite on disk change)
|
||||
;*
|
||||
|
||||
; 01/12/83 Adapted for Z8002 (DMH)
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* Trap and interrupt handlers are started up
|
||||
;* in segmented mode on the Z8001.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global __bios ;C portion of BIOS
|
||||
.global memsc ;memory-management SC
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _trapinit
|
||||
.global _trapvec
|
||||
.global _trap
|
||||
|
||||
.global xfersc
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap vector table
|
||||
;*
|
||||
;* entries 0..31 are misc. system traps
|
||||
;* entries 32..47 are system calls 0..15
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_trapvec:
|
||||
.block NTRAPS*4 ; leave trap space same as for Z8001,
|
||||
; for compatibility
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call and General Trap Handler And Dispatch
|
||||
;*
|
||||
;* It is assumed that the system runs
|
||||
;* non-segmented on a segmented CPU.
|
||||
;*
|
||||
;* _trap is jumped to with the
|
||||
;* following information on the stack:
|
||||
;*
|
||||
;* trap type: WORD
|
||||
;* reason: WORD
|
||||
;* fcw: WORD
|
||||
;* pc: WORD
|
||||
;*
|
||||
;* The trap handler is called as a subroutine,
|
||||
;* with all registers saved on the stack. This
|
||||
;* allows the trap handler to be in another
|
||||
;* segment (with some care). This is useful
|
||||
;* mainly to the debugger.
|
||||
;*
|
||||
;* All registers except rr0 are also passed
|
||||
;* intact to the handler.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
sc_trap: ; system call trap server
|
||||
|
||||
push @r15,@r15 ; duplicate type as reason
|
||||
|
||||
|
||||
_trap: ; general trap server
|
||||
|
||||
sub r15,#FRAMESZ-8 ; push caller state
|
||||
ldm @r15,r0,#15
|
||||
ldctl r1,NSP
|
||||
ex r1,nr15(r15)
|
||||
|
||||
; trap# now in r1
|
||||
cpb rh1,#7Fh ; system call?
|
||||
jr ne trap_disp ; no
|
||||
; yes: map it
|
||||
clrb rh1
|
||||
add r1,#SC0TRAP
|
||||
|
||||
;=== need range check ===
|
||||
|
||||
trap_disp: ; dispatch
|
||||
sll r1,#2
|
||||
ldl rr0,_trapvec(r1)
|
||||
testl rr0
|
||||
jr z _trap_ret ; zero -- no action
|
||||
call @r1 ; go execute the trap
|
||||
|
||||
_trap_ret: ;return from trap or interrupt
|
||||
|
||||
ld r1,nr15(r15) ; pop state
|
||||
ldctl NSP,r1
|
||||
ldm r0,@r15,#15
|
||||
add r15,#FRAMESZ-6 ; re-adjust stack
|
||||
iret ; return from interrupt
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Assorted Trap Handlers
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
epu_trap:
|
||||
push @r15,#EPUTRAP
|
||||
jr _trap
|
||||
|
||||
pi_trap:
|
||||
push @r15,#PITRAP
|
||||
jr _trap
|
||||
|
||||
seg_trap:
|
||||
push @r15,#SEGTRAP
|
||||
jr _trap
|
||||
|
||||
nmi_trap:
|
||||
push @r15,#NMITRAP
|
||||
jr _trap
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios system call handler
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
biossc: ; call bios
|
||||
; r3 = operation code
|
||||
; rr4= P1
|
||||
; rr6= P2
|
||||
|
||||
; set up C stack frame
|
||||
;===
|
||||
pushl @r15,rr6
|
||||
pushl @r15,rr4
|
||||
push @r15,r3
|
||||
|
||||
; call C program
|
||||
call __bios
|
||||
|
||||
; clean stack & return
|
||||
add r15,#10
|
||||
ldl cr6+co(r15),rr6 ; with long in rr6
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch System Call
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word (trap reason)
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
xfersc: ;enter here from system call
|
||||
|
||||
; build frame on system stack
|
||||
|
||||
; when called from system call, the frame replaces
|
||||
; the caller's context, which will never be resumed.
|
||||
|
||||
inc r15,#co ; discard return addr
|
||||
ld r5,r15 ; move context
|
||||
ld r2,#FRAMESZ/2
|
||||
ldir @r5,@r7,r2
|
||||
dec r5,#2 ;point back to PC
|
||||
ldi @r5,@r7,r2 ;transfer PC
|
||||
jr _trap_ret ;restore context
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _trapinit -- initialize trap system
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;*
|
||||
;* PSA (Program Status Area) structure
|
||||
;*
|
||||
ps .equ 4 ; size of a program status entry
|
||||
; --- non-segmented ---
|
||||
|
||||
psa_epu .equ 1*ps ; EPU trap offset
|
||||
psa_prv .equ 2*ps ; priviledged instruction trap
|
||||
psa_sc .equ 3*ps ; system call trap
|
||||
psa_seg .equ 4*ps ; segmentation trap
|
||||
psa_nmi .equ 5*ps ; non-maskable interrupt
|
||||
psa_nvi .equ 6*ps ; non-vectored interrupt
|
||||
psa_vi .equ 7*ps ; vectored interrupt
|
||||
psa_vec .equ psa_vi+(ps/2) ; vectors
|
||||
|
||||
|
||||
_trapinit:
|
||||
|
||||
; initialize trap table
|
||||
|
||||
lda r2,_trapvec
|
||||
ld r0,#NTRAPS
|
||||
subl rr4,rr4
|
||||
clrtraps:
|
||||
ldl @r2,rr4
|
||||
inc r2,#4
|
||||
djnz r0,clrtraps
|
||||
|
||||
ld r2,_sysseg
|
||||
lda r3,biossc
|
||||
ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2
|
||||
lda r3,memsc
|
||||
ldl _trapvec+(MEM_SC+SC0TRAP)*4,rr2
|
||||
|
||||
|
||||
; initialize some PSA entries.
|
||||
; r0 PSA entry: FCW (ints ENABLED)
|
||||
; r1 PSA entry: PC
|
||||
; r5 -> PSA slot
|
||||
|
||||
ld r5,_psap
|
||||
ld r0,#0D800h
|
||||
|
||||
add r5,#ps ; skip reserved to EPU trap
|
||||
ld r1,#epu_trap
|
||||
ldm @r5,r0,#2
|
||||
|
||||
add r5,#ps ; Priviledged Inst
|
||||
ld r1,#pi_trap
|
||||
ldm @r5,r0,#2
|
||||
|
||||
add r5,#ps ; System Call
|
||||
ld r1,#sc_trap
|
||||
ldm @r5,r0,#2
|
||||
|
||||
add r5,#ps ; segmentation
|
||||
ld r1,#seg_trap
|
||||
ldm @r5,r0,#2
|
||||
|
||||
add r5,#ps ; Non-Maskable Int.
|
||||
ld r1,#nmi_trap
|
||||
ldm @r5,r0,#2
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,158 @@
|
||||
/*--------------------------------------------------------------*\
|
||||
| ccp_def.c DEFINES v1.0 |
|
||||
| ======= |
|
||||
| |
|
||||
| P-CP/M: A CP/M derived operating system |
|
||||
| |
|
||||
| File contents: |
|
||||
| ------------- |
|
||||
| This file contains all of the #defines |
|
||||
| used by the console command processor. |
|
||||
| |
|
||||
| created by : Tom Saulpaugh Date: 7/13/82 |
|
||||
| ---------- |
|
||||
| last modified: 12/20/82 |
|
||||
| ------------- |
|
||||
| |
|
||||
| (c) COPYRIGHT Digital Research 1982 |
|
||||
| all rights reserved |
|
||||
| |
|
||||
\*--------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| CP/M Transient Commands |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define DIRCMD 0
|
||||
#define TYPECMD 1
|
||||
#define RENCMD 2
|
||||
#define ERACMD 3
|
||||
#define UCMD 4
|
||||
#define CH_DISK 5
|
||||
#define SUBCMD 6
|
||||
#define SUB_FILE 7
|
||||
#define FILE 8
|
||||
#define DIRSCMD 9
|
||||
#define SEARCH 10
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| Modes and Flags |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define ON 1
|
||||
#define OFF 0
|
||||
#define MATCH 0
|
||||
#define GOOD 1
|
||||
#define BAD 0
|
||||
#define FILL 1
|
||||
#define NOFILL 0
|
||||
#define VOID /*no return value*/
|
||||
#define NO_FILE 98
|
||||
#define STOP 99
|
||||
#define USER_ZERO 0
|
||||
#define DISK_A 1
|
||||
#define SOURCEDRIVE 88
|
||||
#define DESTDRIVE 99
|
||||
#define BYTE char
|
||||
#define REG register
|
||||
#define WORD short
|
||||
#define UWORD unsigned int
|
||||
#define LONG long
|
||||
#define ULONG unsigned long
|
||||
#define GET_MEM_REG 18
|
||||
#define ZERO 0
|
||||
#define NULL '\0'
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NO_READ 255
|
||||
#define BLANK ' '
|
||||
#define BACKSLH '\\'
|
||||
#define EXLIMPT '!'
|
||||
#define CMASK 0177
|
||||
#define ONE (long)49
|
||||
#define TAB 9
|
||||
#define Cr 13
|
||||
#define Lf 10
|
||||
#define CR (long)13
|
||||
#define LF (long)10
|
||||
#define EOF 26
|
||||
#define BLANKS (long)32
|
||||
#define PERIOD (long)46
|
||||
#define COLON (long)58
|
||||
#define ARROW (long)62
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| Data Structure Size Constants |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define CMD_LEN 128
|
||||
#define BIG_CMD_LEN 255
|
||||
#define MAX_ARGS 4
|
||||
#define ARG_LEN 26
|
||||
#define NO_OF_DRIVES 16
|
||||
#define NUMDELS 16
|
||||
#define FCB_LEN 36
|
||||
#define DMA_LEN 128
|
||||
#define FILES_PER_LINE 4 /* Zilog */
|
||||
#define SCR_HEIGHT 23
|
||||
#define BIG_WIDTH 80
|
||||
#define SMALL_WIDTH 40
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| BDOS Function Calls |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define WARMBOOT 0
|
||||
#define CONIN 1
|
||||
#define CONSOLE_OUTPUT 2
|
||||
#define READER_INPUT 3
|
||||
#define PUNCH_OUTPUT 4
|
||||
#define LIST_OUTPUT 5
|
||||
#define DIR_CONS_I/O 6
|
||||
#define GET_I/O_BYTE 7
|
||||
#define SET_I/O_BYTE 8
|
||||
#define PRINT_STRING 9
|
||||
#define READ_CONS_BUF 10
|
||||
#define GET_CONS_STAT 11
|
||||
#define RET_VERSION_NO 12
|
||||
#define RESET_DISK_SYS 13
|
||||
#define SELECT_DISK 14
|
||||
#define OPEN_FILE 15
|
||||
#define CLOSE_FILE 16
|
||||
#define SEARCH_FIRST 17
|
||||
#define SEARCH_NEXT 18
|
||||
#define DELETE_FILE 19
|
||||
#define READ_SEQ 20
|
||||
#define WRITE_SEQ 21
|
||||
#define MAKE_FILE 22
|
||||
#define RENAME_FILE 23
|
||||
#define RET_LOGIN_VEC 24
|
||||
#define RET_CUR_DISK 25
|
||||
#define SET_DMA_ADDR 26
|
||||
/* #define GET_ADDR(ALLOC) 27 */
|
||||
#define WRITE_PROT_DISK 28
|
||||
#define GET_READ/O_VEC 29
|
||||
#define SET_FILE_ATTRIB 30
|
||||
#define GET_ADDR_D_PARM 31
|
||||
#define GET_USER_NO 32
|
||||
#define READ_RANDOM 33
|
||||
#define WRITE_RANDOM 34
|
||||
#define COMP_FILE-SIZE 35
|
||||
#define SET_RANDOM_REC 36
|
||||
#define RESET_DRIVE 37
|
||||
/* #define WRITE_RAN_ZERO 40 */
|
||||
#define BIOS_CALL 50
|
||||
#define LOAD_PROGRAM 59
|
||||
|
||||
/*----------------------------------------------*\
|
||||
| MACROS |
|
||||
\*----------------------------------------------*/
|
||||
|
||||
#define isalpha(c) (islower(c) || isupper(c))
|
||||
#define islower(c) ('a' <= (c) && (c) <= 'z')
|
||||
#define isupper(c) ('A' <= (c) && (c) <= 'Z')
|
||||
#define tolower(c) (isupper(c) ? ((c)+040):(c))
|
||||
#define toupper(c) (islower(c) ? ((c)-040):(c))
|
||||
#define isdigit(c) ('0' <= (c) && (c) <= '9')
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user