Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -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.

View File

@@ -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++;
}

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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";

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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


View File

@@ -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;

View File

@@ -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};

View File

@@ -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);
}

View File

@@ -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]);
}

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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,

View File

@@ -0,0 +1,2 @@
This directory contains the source and object files for the
Z8000 CP/M assembler "asz8k" to run under CP/M.

View File

@@ -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 */
};

View File

@@ -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 */
};

View File

@@ -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

View File

@@ -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 */
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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)
/* */
/************************/

View File

@@ -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 );
}
}

View File

@@ -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 */
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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
;*****************************************************
;*****************************************************

View File

@@ -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

View File

@@ -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
;****************************************************
;****************************************************

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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 */
};

View File

@@ -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 */
};

View File

@@ -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)
/* */
/************************/

File diff suppressed because it is too large Load Diff

View File

@@ -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')

View File

@@ -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

View File

@@ -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! */
}

View File

@@ -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 */

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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 *
; * *
; *************************************************

View File

@@ -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;
}

View File

@@ -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;
};

File diff suppressed because it is too large Load Diff

View File

@@ -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 */

View File

@@ -0,0 +1,2 @@
This directory contains the source and object files for the Z8000 debugger,
ddt, for CP/M.

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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 */
};

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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 */
};

View File

@@ -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

View File

@@ -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 */
};

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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)++));
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)
/* */
/************************/

View File

@@ -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

View File

@@ -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

View File

@@ -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
;*****************************************************
;*****************************************************

View File

@@ -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
;*****************************************************
;*****************************************************

View File

@@ -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

View File

@@ -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 */

View File

@@ -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
;****************************************************
;****************************************************

View File

@@ -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

View File

@@ -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
;****************************************************
;****************************************************

View File

@@ -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

View File

@@ -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