MAKE SUB SEND SUBMAKE SUB STDIO H 123PORTAB H CPU68000H CPU68010H DDT10LODS &8.rel e:sendc68.68k $2reloc 10:size68.rel e:size68.68k $2reloc 10:find.rel e:find.68k $2reloc 11:cp68.rel $2cp68.68k SID05 C dSID03 C efghijklmnopqrstSID03 C uSIDDEF H vwxg8 $2pip $2=reloc.rel[g10 $2reloc.rel $2reloc.rel $2reloc.68k era $2reloc.rel $2reloc 15:pip.rel $2pip.68k $2reloc 15:BDOSDEF H / BDOSIF S BDOSMAINC BDOSREADC .MAKE SUBCPUTYPE H LDRLIB SRCKIT DOC$2reloc 12:c068.rel $2c068.68k $2reloc 13:c168.rel $2c168.68k user 14!make $1 $2 LGCDEF H yzSID04 C i{|}~SIDLOAD S %BDOSFUNCH stat.rel $2stat.68k $2reloc 15:ed.rel e:ed.68k $2reloc 3:link68.rel e:link68.68k $2reloc 9:as68.rel $2as68.68k BIOSDEF H CPMLDR C " !DSKUTIL C "#$FILEIO C %&'2reloc 12:c068.rel $2c068.68k $2reloc 13:c168.rel $2c168.68k user 14!make $1 $2 SIDFUN C DISAS H SID68K C tSID68K DOK$2as68 -f $1 -s 0$1 -i 9:as68init $2pip $2=$1as68symb.dat $2reloc 10:lo68.rel $2lo68.68k $2reloc 10:ar68.rel $2ar68.6IOSYS C ()LDRIF S *+PKTIO H ,-STDIO H ./0$2pip e:=*.h[g6 $2pip $1=*.h[g6 $2pip e:=clib[g6 $2pip $2=clib[g6 $2pip $1=s.o[g6 $2pip e:=s.o[g6 $2pip e:=klib[g4 $2pip 2reloc 12:c068.rel $2c068.68k $2reloc 13:c168.rel $2c168.68k user 14!make $1 $2 DDTINC H !DDTLOAD S %BDOS00 S HBDOS10 S Q8k $2reloc 10:dump.rel e:dump.68k $2reloc 10:nm68.rel e:nm68.68k $2reloc 10:prtobj.rel e:prtobj.68k $2reloc 10:sendc6OPTAB H S456789:;<=>BDOS S "?@ABCSID05 C DEFGHIJKLMNOPQRSSID05 C TUVWXYZ[\]^_`abc$2=klib[g4 $2pip e:=klib.h[g4 $2pip $1=klib.h[g4 $2pip e:=libf.a[g7 $2pip $2=libf.a[g7 $2pip e:=libe.a[g8 $2pip $2=libe.a[l 60(sp),a0 * get pointer to LPB clr.l d0 * start with return parm cleared bsr gethd $1vsend ddt10lod.s $1vsend make.sub $1vsend send.sub $1vsend ddt.rel $1vsend ddt68000.68k $1vsend ddt10.rel $1vsend ddt6osys.s $2as68 -f $1 -s 0$1 -l -u bdosif.s $2as68 -f $1 -s 0$1 -l -u ldrif.s era ldrlib $2ar68 rf $1 ldrlib ldrif.o cpmldcpmldr.s $2cp68 dskutil.c $1x.i $2c068 $1x.i $1x.1 $1x.2 $1x.3 era $1x.i $2c168 $1x.1 $1x.2 dskutil.s era $1x.1 era $1x$2cp68 bdosmain.c $1x.i $2c068 $1x.i $1x.1 $1x.2 $1x.3 era $1x.i $2c168 $1x.1 $1x.2 bdosmain.s era $1x.1 era $1x.2 $2as68 8010.68k $1vsend cputype.h $1vsend done r.o bdosif.o dskutil.o fileio.o bdosread.o $2ar68 rf $1 ldrlib bdosmain.o iosys.o era *.o user 2!make $1 $2 $1vsend sid68k.c $1vsend sidfun.c $1vsend sid03.c $1vsend sid04.c $1vsend sid05.c $1vsend ddtload.s $1vsend bdos00.s $1vs.2 $2as68 -l -u -s 0$1 -f $1 dskutil.s era dskutil.s $2cp68 fileio.c $1x.i $2c068 $1x.i $1x.1 $1x.2 $1x.3 era $1x.i $2c1-l -u -s 0$1 -f $1 bdosmain.s era bdosmain.s $2cp68 bdosread.c $1x.i $2c068 $1x.i $1x.1 $1x.2 $1x.3 era $1x.i $2c168 $1x.010.68k $1vsend cputype.h $1vsend done .o bdosif.o dskutil.o fileio.o bdosread.o $2ar68 rf $1 ldrlib bdosmain.o iosys.o era *.o user 2!make $1 $2 end bdos10.s $1vsend optab.h $1vsend lgcdef.h $1vsend siddef.h $1vsend ddtinc.h $1vsend bdosfunc.h $1vsend portab.h $1vse68 $1x.1 $1x.2 fileio.s era $1x.1 era $1x.2 $2as68 -l -u -s 0$1 -f $1 fileio.s era fileio.s $2cp68 iosys.c $1x.i $2c0681 $1x.2 bdosread.s era $1x.1 era $1x.2 $2as68 -l -u -s 0$1 -f $1 bdosread.s era bdosread.s $2cp68 cpmldr.c $1x.i $2c068 ry point for Program Load routine _pgmld: movem.l d1-d7/a0-a6, -(sp) * save everything, just to be safe move..o bdosif.o dskutil.o fileio.o bdosread.o $2ar68 rf $1 ldrlib bdosmain.o iosys.o era *.o user 2!make $1 $2 nd stdio.h $1vsend disas.h $1vsend cpu68000.h $1vsend cpu68010.h $1vsend make00.sub $1vsend make10.sub $1vsend sendddt.sub $1x.i $1x.1 $1x.2 $1x.3 era $1x.i $2c168 $1x.1 $1x.2 iosys.s era $1x.1 era $1x.2 $2as68 -l -u -s 0$1 -f $1 iosys.s era i$1x.i $1x.1 $1x.2 $1x.3 era $1x.i $2c168 $1x.1 $1x.2 cpmldr.s era $1x.1 era $1x.2 $2as68 -l -u -s 0$1 -f $1 cpmldr.s era Digital Research, Inc. * * Structure definitions for BDOS globals * * and BDOS data structures * * * ****************************************************/ /****************************************************************************/rations take this philosophy into account, and define a simple structure for the single thread environment while leaving the p */ /* File I/O Definitions */ /* are simply declared as global variables in bdosmain.c. Only a few "globals" are really global in this sense. The majority o*********************************************/ /************************************************************************** T /* Miscellaneous Definitions: */ /*********************************************ossibilities open for the multi-thread environment. *************************************************************************** */ /* The definitions in this section are used by the run-time */ /* f the "global" variables are actually state variables that relate to the state of the task using the file system. In CP/M-68K,he BDOS data structures, especially those relating to global variables, are structured in a way that hopefully will enable thi*******************************/ #define FAILURE (-1) /* Function failure return val */ #define SUC*/ #define snglthrd TRUE /* TRUE for single-thread environment FALSE to create based structure for re-entrant model * package to provide an interface between CP/M-68K I/O and */ /* standard C I/O. these are "global", since there's only one task, but in a multi-thread model they're not. These type of variables are put ins BDOS, in the future, to easily become a re-entrant multi-tasking file system. Consequently, the BDOS global variables are /******************************************************** * * * CP/M-68K header file * * Copyright (c) 1982 by / #if snglthrd #define GBL gbls /* In single thread case, GBL just names the structure */ #define BSETUP EXTERN */ /* */ /*******************************to a data structure, with the intention that in the multi-task environment this structure will be based. The following decla/************************************************************************/ /* divided into two classes. Those that are truly global, even in the case of multiple tasks using the file system concurrently,struct stvars gbls; /* and BSETUP defines the extern structure */ #endif #if ! snglthrd #define GBL (*statep) /* cnt; /* Nmbr rcrds in last block, 0..128 */ union { UBYTE small[16]; /* 16 block numbers of 1 byte */ WORD big[8];Version number for CP/M-68K */ #define robit 0 /* read-only bit in file type field of fcb */ #define SECLEN 128 /* length y byte for fill */ UWORD dsm; /* max disk size in blocks */ UWORD drm; /* max directory entries */ UWORD dir_al; /* in Consequently, the primitives LOCK and UNLOCK are defined and used where necessary in the file system. For the singleE s2; /* Module field (bits 0..5), write flag (7) */ UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */ union { UBIf multi-task, state vars are based */ #define BSETUP REG struct stvars *statep; \ statep = &gbls; /* set up pointer /* or 8 block numbers of 1 word */ } dskmap; UBYTE cur_rec; /* current record field */ UBYTE ran0; /* random record of a CP/M sector */ /* File Control Block definition */ struct fcb { UBYTE drvcode; /* 0 = default drive, 1..16 are driitial allocation for dir */ UWORD cks; /* number dir sectors to checksum */ UWORD trk_off; /* track offset */ }; stru thread model, they are null routines */ #define LOCK /**/ #define UNLOCK /**/ /* Be sure LOCK and UNLOCK are imYTE small[16]; /* 16 block numbers of 1 byte */ WORD big[8]; /* or 8 block numbers of 1 word */ } dskmap; }; /* Dto state variables */ /* This is intended as an example to show the intent */ #endif /* Note that there are a few critfield (3 bytes) */ UBYTE ran1; UBYTE ran2; }; /* Declaration of directory entry */ struct dirent { UBYTE entry; /ves A..P */ UBYTE fname[8]; /* File name (ASCII) */ UBYTE ftype[3]; /* File type (ASCII) */ UBYTE extent; /* Extent nct dph /* disk parameter header */ { UBYTE *xlt; /* pointer to sector translate table */ UWORD hiwater; /* high water maplemented to allow recursive calls to LOCK. That is, if a process that calls LOCK already owns the lock, let it proceed, eclaration of disk parameter tables */ struct dpb /* disk parameter table */ { UWORD spt; /* sectors per track */ Uical regions in the file system that must execute without interruption. They pertain mostly to the manipulation of the* 0 - 15 for user numbers, E5 for empty */ /* the rest are reserved */ UBYTE fname[8]; /* File name (ASCII) */ UBYTEumber (bits 0..4 used) */ UBYTE s1; /* Reserved */ UBYTE s2; /* Module field (bits 0..5), write flag (7) */ UBYTE rcdrk for this disk */ UWORD dum1; /* dummy (unused) */ UWORD dum2; UBYTE *dbufp; /* pointer to 128 byte directory buffer but remember that only the outer-most call to UNLOCK really releases the file system. */ #define VERSION 0x2022 /* BYTE bsh; /* block shift factor */ UBYTE blm; /* block mask */ UBYTE exm; /* extent mask */ UBYTE dpbdum; /* dumm allocation vector. This isn't a problem in a single-thread model, but must be provided for in a multi-tasking file system. ftype[3]; /* File type (ASCII) */ UBYTE extent; /* Extent number (bits 0..4 used) */ UBYTE s1; /* Reserved */ UBYT */ struct dpb *dpbp; /* pointer to disk parameter block */ UBYTE *csv; /* pointer to check vector */ UBYTE *alv; /* poface Routines * * * Note - there are 5 BIOS entry points from the BDOS, labelled BIOS1 - * BIOS5, depending on the param * * For "C" version of CP/M-68K * * * * Copyright (c) 1982 Digital Research, Inc. * * * * Version 0.bytes of a word, return swapped value in d0 move.b 5(sp),d0 lsl #8,d0 move.b 4(sp),d0 rts _udiv: * Unsigned divid/ }; 6(sp),d1 * get long word parameter bra _bios1 * join common routine _bios2: * For all BIOS functions with a word parameteinter to allocation vector */ }; /* Declaration of structure containing "global" state variables */ struct stvars { seters passed. _bios5: * For BIOS functions sectran and set exception vector * Has function number and 2 parameters, a word 1 -- September 22, 1982 * * * ***************************************************************** * Declare Publice. * Inputs: Long dividend, unsigned word divisor, address of return structure * Return: In structure passed, unsigned word qu }; r * Word parameter follows function number move.w 6(sp),d1 * get 1st parameter (word) _bios1: * For all BIOS functions thtruct dph *dphp; /* pointer to disk parm hdr for cur disk */ struct dirent *dirbufp; /* pointer for directory buff for procefollowed by a long word move.l 8(sp),d2 * get 2nd parameter (long word) bra _bios2 * join common routine _bios4: * For Routines .globl _bios1 * 5 BIOS entry points from BDOS .globl _bios2 .globl _bios3 .globl _bios4 .globl _bios5 .otient, unsigned word remainder move.l a0, -(sp) * save a0 move.l 14(sp), a0 * get address of return structure move.l 8(spat have no parameter other than function number move.w 4(sp),d0 * get function number movem.l d3-d7/a3-a6,-(sp) jsr _bios ss */ /* stored here so that each process can */ /* have a separate dirbuf. */ struct dpb *parmp; /* pointerBIOS function seldsk * Has function number followed by 2 word parameters move.w 8(sp),d2 * get 2nd parameter (word) bra _biglobl _swap * byte swapper .globl _udiv * unsigned divide routine * External Routine .globl _bios * * BIOS Inter), d0 * get dividend divu 12(sp), d0 * do the divide move.w d0, (a0)+ * store quotient swap d0 move.w d0, (a0) * store r ***************************************************************** * * * CP/M-68K Interface Module for the Loader BDOS * do BIOS call movem.l (sp)+,d3-d7/a3-a6 * * returns value in d0 rts * * Utility Subroutines * _swap: * Swap to disk parameter block for cur */ /* disk. Stored here to save ref calc */ UBYTE *dmaadr; /* Disk dma address *os2 * join common routine _bios3: * For BIOS function set dma * Has function number followed by 1 long parameter move.l emainder move.l (sp)+, a0 * restore a0 rts .end .1, Copyright (c) 1983, Digital Research"; char *serial = "XXXX-0000-654321"; /* Declare EXTERN functions */ EXTERN WO, potentially a long word * * The BDOS can potentially return a pointer, long word, * * or word * * * * Configu */ REG UBYTE *infop; /* d1.l pointer parameter */ { switch (func) /* switch on function number */ { case 2: bco****** * * * _bdos MAIN ROUTINE * * * * Called with _bdos(func, info, infop) * * * * Where: mainder move.l (sp)+, a0 * restore a0 rts .end RD seldisk(); /* Select disk */ EXTERN BOOLEAN openfile(); /* Open File */ EXTERN UWORD dirscan(); /* General directory scred for Alcyon C on the VAX * * * ****************************************************************/ #include "stdinout((UBYTE)info); /* console output */ break; case 14: return(seldisk(info)); /* select disk */ case 15: i /**************************************************************** * * * CP/M-68K Loader BDOS Main Routine * * * * func is the BDOS function number (d0.w) * * info is the word parameter (d1.w) * * infop is the pointer parameteranning routine */ EXTERN UWORD seqread(); /* Sequential disk read */ /* Declare the "state variables". These are globalo.h" /* Standard I/O declarations */ #include "bdosdef.h" /* Type and structure declarations for BDOS */ #include "biosdnfop->drvcode = 0; /* open file */ infop->extent = 0; infop->s2 = 0; return(dirscan(openfile, infop)); * * This is the main routine for the Loader BDOS for * * CP/M-68K. It has one entry point, _bdos. * * the assembly langu (d1.l) * * note that info is the word form of infop* * * *********************************************************s for the single-thread version of the file system, but are put in a structure so they can be based, with a pointer coef.h" /* Declarations of BIOS functions */ /* Serial Number and Copyright Notice */ char *copyrt="CP/M-68K(tm), Version 1 case 20: infop->drvcode = 0; /* read sequential */ return(seqread(infop)); case 26: GBL.dmaadr = infop; /* sage trap handler found in bdosif.s. * * There are two parameters: a function number (integer) * * and an information parameter*******/ UWORD _bdos(func,info,infop) REG WORD func; /* BDOS function number */ REG UWORD info; /* d1.w word parameter ming from the calling process */ GLOBAL struct stvars gbls; /**********************************************************et dma address */ break; default: return(0xffff); /* bad function number */ /* break; */ }; /* end FCB block number routines * ******************************/ WORD blkindx(fcbp) /* return index into fcb disk map */ RBDOS */ /* External function definitions */ EXTERN UWORD rdsec(); /* disk read routine */ EXTERN WORD swap(); /* assembl) + (LONG)(rcrd & (dparmp->blm)); return( rdsec(lsec, GBL.dmaadr) ); } /****************************************** * * This module contains functions to perform sequential * * or random access read or write to the disk for CP/M-68K *of fcb */ WORD wrdfcb; /* boolean, fcb disk map of words? */ { if (wrdfcb) return( swap(fcbp->dskmap.big[index]) ); of switch statement */ return(0); /* return the BDOS return value */ } /* end _bdos */ EG struct fcb *fcbp; /* pointer to fcb */ { REG struct dpb *dparmp; /* pointer to disk parameter block */ REG WORD iy language byte swapper */ EXTERN UWORD dirscan(); /* directory scanning routine */ EXTERN BOOLEAN openfile(); /* open file fu* * routine for crossing extent boundaries * *******************************************/ WORD new_ext(fcbp) /* If sequ * * * It includes the following external functions: * * * * seqread() - sequential disk read * * else return( UBWORD(fcbp->dskmap.small[index]) ); } /********************* * disk read routine * ******************of switch statement */ return(0); /* return the BDOS return value */ } /* end _bdos */ ; REG WORD blkshf; BSETUP dparmp = GBL.parmp; blkshf = dparmp->bsh; i = ((fcbp->extent) & dparmp->exmnction passed to dirscan */ /**********************************************************/ /* First, some utility functionsential I/O, open the next extent */ REG struct fcb *fcbp; /* pointer to fcb */ { REG UBYTE mod; /* module number */ * * * * Compiled with Alcyon C on the VAX * * * ************************************************************/ UWORD do_io(block, rcrd) UWORD block; /* block number */ UBYTE rcrd; /* record number */ { LONG lsec; ) << (7 - blkshf); return (i + (UBWORD(fcbp->cur_rec) >> blkshf) ); } UWORD blknum(fcbp, index, wrdfcb) /* return bl used by seqio and ranio */ /**********************************************************/ /****************************** * REG UBYTE ext; /* extent number */ BSETUP mod = (fcbp->s2) & 0x3f; ext = (fcbp->extent) + 1; /* for sequ*******/ #include "stdio.h" /* Standard I/O declarations */ #include "bdosdef.h" /* Type and structure declarations for REG struct dpb *dparmp; BSETUP dparmp = GBL.parmp; /* init dpb pointer */ lsec = ((LONG)block << (dparmp->bsh) /**************************************************************** * * * CP/M-68K BDOS Disk Read/Write Module * * ock number in fcb indicated by index */ REG struct fcb *fcbp; /* pointer to fcb */ REG WORD index; /* index into disk map ential, incr extent */ if (ext >= 32) { ext = 0; mod += 1; } if (mod >= 64) return(6); /* past maximum f else if (ext > fcbp->extent) return(128); /* if the fcb has more extents past this one, then */ /* the current onep)->bsh); return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i ); } /********************************* * Routine /* reading unwritten data */ return( do_io(block, (fcbp->cur_rec)++) ); } ********* * Routine to calculate the maximum * * extent number of an FCB in a * * extent-folded environment * *****e = ((GBL.parmp)->dsm) & ~0xff; if (fcbp->cur_rec == 128) { /* time to try next extent */ if ( new_ext(fcbp) ) ile size */ if ( mod == ((fcbp->s2) & 0x3f) ) if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) ) { /* we' is logically full */ else return (0); /* if we seeked past the last active extent, rc = 0 */ } /**************** to get the actual * * record count of the currently * * active logical extent of a FCB * ********************************* /* reading unwritten data */ return( do_io(block, (fcbp->cur_rec)++) ); } *******************************/ UWORD calcext(fcbp) REG struct fcb *fcbp; { REG UWORD i; REG BYTE *p; B return(1); /* if can't open new extent, error */ fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */ } if ( UBre in same logical extent */ fcbp->extent = ext; return(0); } /* Extent or Module numbers don't match */ ******** * seqread entry point * ************************/ UWORD seqread(fcbp) REG struct fcb *fcbp; /* fcbp is a poin/ UWORD get_rc(fcbp) REG struct fcb *fcbp; { REG UWORD ext; ext = calcext(fcbp); /* find last active extentSETUP i = 15; p = &(fcbp->dskmap.small[16]); do { if (*--p) break; i -= 1; } while (i); /* Now iWORD(fcbp->cur_rec) >= get_rc(fcbp) ) return(1); /* this is end of file */ index = blkindx(fcbp); /* get index into fcb /* Close the old extent and open a new one */ fcbp->s2 = mod; fcbp->extent = ext; if ( dirscan(openfile, fcbp) >ter to a fcb */ { REG UWORD block; /* block number from fcb */ REG WORD index; /* index into disk map of fcb */ in fcb */ if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt)); /* if this is the last active fcb, return fcb's rc */ contains the index of the last non-zero block in the FCB */ if ((GBL.parmp)->dsm > 255) i >>= 1; i >>= 7 - ((GBL.parmdisk map */ block = blknum(fcbp, index, bigfile); if ( ! block) /* no data allocated at that position */ return(1);= 255 ) /* open new extent */ return(4); /* reading unwritten extent */ return(0); } /*************************** REG WORD parm; /* parameter to do-io */ REG WORD bigfile; /* file system is in word mode */ BSETUP bigfil /******************************************************** * * * BIOS definitions for CP/M-68K * * * * Copyrig() bios1(18) /* get memory segment tbl */ #define bgetiob() bios1(19) /* get I/O byte */ #define bsetiob(parm) bios2(20,parm)arm1,parm2) /* select disk and return info */ #define bsettrk(parm) bios2(10,parm) /* set track on disk */ #define bsetss5(); /* for sectran and set exception */ #define bwboot() bios1(1) /* warm boot */ #define bconstat() bios1(2) /* cht (c) 1982 Digital Research, Inc. * * * * This include file simply defines the BIOS calls * * * *************** /* set I/O byte */ #define bflush() bios1(21) /* flush buffers */ #define bsetvec(parm1,parm2) bios5(22,parm1,parm2) /ec(parm) bios2(11,parm) /* set sector for disk */ #define bsetdma(parm) bios3(12,parm) /* set dma address */ #define bread(onsole status */ #define bconin() bios1(3) /* console input */ #define bconout(parm) bios2(4,parm) /* console output parm */ *****************************************/ EXTERN UBYTE bios1(); /* used for character I/O functions */ EXTERN bios2(); /** set exception vector */ ) bios1(13) /* read sector from disk */ #define bwrite(parm) bios2(14,parm) /* write sector to disk */ #define blistst() bios/**************************************************************** * * * CP/M-68K Loader * * * * This is t #define blstout(parm) bios2(5,parm) /* list device output */ #define bpun(parm) bios2(6,parm) /* punch char output */ #define parm1 is word, no return value */ EXTERN bios3(); /* used for set dma only */ /* parm1 is a pointer, no return  set exception vector */ 1(15) /* list device status */ #define bsectrn(parm1,parm2) bios5(16,parm1,parm2) /* sector translate */ #define bgetseghe main routine for the CP/M-68K Loader. * * It has one entry point, ldcpm, which is called from * * the assembly language brdr() bios1(7) /* reader input */ #define bhome() bios1(8) /* recalibrate drive */ #define bseldsk(parm1,parm2) bios4(9,p*/ EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */ /* words, returns a pointer to dph */ EXTERN UWORD bioroutine called startld found in * * ldrif.s. startld just sets up the stack. * * * * Configured for Alcyon C on the TE *start; /* low memory address */ LONG length; /* length of segment */ }; /**********************/ /* Globaares */ UBYTE dskmap[16]; /* disk map, also a don't care */ UBYTE cur_rec; /* current record field */ }; stru**************/ BYTE *load(fcbp) /* load the file pointed to by fcbp and return pointer to load point */ REG struct fcb *fc* general purpose byte mover */ #define conout(ch) _bdos(2,ch) #define seldsk(dsk) _bdos(14,dsk) #define open(fcbp) _bdos************/ pstring(p) /* print string */ REG BYTE *p; { while (*p) conout(*p++); } badload(errtype) /* VAX * * * ****************************************************************/ #include "stdio.h" /* Standard I/O del Variables */ /**********************/ BYTE buffer[SECLEN]; /* 128 byte dma buffer to read program headers */ /* We nect hdr { WORD magic; /* magic number. We only recognize 0x601a */ LONG size[5]; /* sizes of code, data, bss, sym bp; { REG BYTE *p; REG struct hdr *hp; REG LONG length; setdma( buffer ); if ( open(fcbp) >= 255 ) b(15,0,fcbp) #define read(fcbp) _bdos(20,0,fcbp) #define setdma(p) _bdos(26,0,p) /* Define the data structures used in ldcLoad failed. Print message and try again */ REG WORD errtype; { REG WORD i; switch (errtype) { case 0: pstclarations */ #define ALCYON TRUE /* TRUE if compiling with the ALCYON 68K C compiler */ #define SECLEN 128 /* CP/M sector ed 1 FCB to read CPM.SYS. */ /* Unfortunately, due to a bug in the Alcyon compiler, we can't initialize */ /* them in a stbl, stack */ BYTE *tstart; /* start address of text segment */ WORD rlbflg; /* relocation bits suppressed flag */ adload(1); fcbp->cur_rec = 0; if ( read(fcbp) ) badload(1); hp = buffer; if ( (hp->magic != 0x601a) || ! (hppm */ struct fcb { UBYTE drvcode; /* drive code, must be 0 for loader BDOS */ /* (auto disk select not supported) *ring("\r\nBoot error."); startld(); case 1: pstring("\n\rOpen or Read error on "); break; case 2: pstring("\n\rBadlength */ /* Declare EXTERN functions */ EXTERN WORD _bdos(); /* Loader BDOS entry point */ EXTERN startld(); /* Asstraightforward way. So: */ /*sw No longer true. Deleted klutz. */ struct fcb cpmfcb = { 0, /* drive code */ }; struct segtbl { /* memory segment table from LDRBIOS */ WORD entrys; /* number of segments, must be 1 */ BY->rlbflg) ) badload(2); p = hp->tstart; length = hp->size[0] + hp->size[1]; move(&buffer[sizeof *hp], p, SECLEN/ UBYTE fname[11]; /* includes file name and type fields */ UBYTE sys_info[4]; /* ex, s1, s2, rc. These are don't c file format on "); } pstring("CPM.SYS"); startld(); } /******************** * load subroutine * ******embly routine to set up stack & retry */ EXTERN BYTE *bios1(); /* bios entry point for get segment table */ EXTERN move(); / 'C','P','M',' ',' ',' ',' ',' ','S','Y','S' }; /**************************/ /* Utility Routines */ /************** - (sizeof *hp)); /* move the first record minus header to load point */ p += SECLEN - (sizeof *hp); length -= SEC * * * * This module contains the miscellaneous utilities * * for manipulating the disk in CP/M-68K. Included are:cnum; /* sector number */ rwpkt.xferadr = dma; /* dma address */ /* parameters that are currently not used by do_pn"); (*gocpm)(); /* jump to the CCP */ } d variables */ EXTERN UWORD do_phio(); /* external physical disk I/O routine */ /********************** * read/write routLEN - (sizeof *hp); while (length > 0L) { setdma(p); if ( read(fcbp) ) badload(1); p += SECLEN; length -= SECL * * * * dirscan() - general purpose dir scanning * * dir_rd() - read directory sector * * rdsec() - reahio rwpkt.devnum = GBL.curdsk; rwpkt.devtype = disk; rwpkt.xferlen = 1; */ rwpkt.infop = GBL.dphp; /*ine * **********************/ UWORD rdsec(secnum, dma) /* General disk sector read routine */ /* It simply sets up a I/O EN; } return(hp->tstart); } /*************************** * ldcpm main routine * ************************d/write disk sector * * * * * * Configured for Alcyon C on the VAX * * * ************************** pass ptr to dph */ return(do_phio(&rwpkt)); } /*************************** * directory read routine * **********packet and sends it to do_phio */ LONG secnum; /* logical sector number to read/write */ UBYTE *dma; /* dma address ****/ ldcpm() { WORD (*gocpm)(); if (seldsk(0)) badload(0); gocpm = load(&cpmfcb); /* load the CP/M syste**************************************/ #include "stdio.h" /* Standard I/O declarations */ #include "bdosdef.h" /* Type /**************************************************************** * * * CP/M-68K Loader BDOS Disk Utilities Module*****************/ UWORD dir_rd(secnum) WORD secnum; { BSETUP return( rdsec((LONG)secnum, GBL.dirbufp) ); } / { struct iopb rwpkt; BSETUP rwpkt.iofcn = (BYTE)read; rwpkt.ioflags = (BYTE)0; rwpkt.devadr = sem */ pstring("\r\n\nCP/M-68K(tm) Version 1.2 03/20/84 "); pstring("\n\rCopyright (c) 1984 Digital Research, Inc.\r\n\and structure declarations for BDOS */ #include "pktio.h" /* Packet I/O definitions */ /* declare external functions an /************************ * dirscan entry point * ************************/ UWORD dirscan(funcp, fcbp) BOOLEAN (*f* * * * Compiled with Alcyon C on the VAX * * * ************************************************************rn(255); }  byte mover * *******************************/ move(p1, p2, i) REG BYTE *p1; REG BYTE *p2; REG WORD i; { while read another directory sector */ dirsec = i >> 2; if (dir_rd(dirsec)) /* read the directory sector */ return(0xopb selpkt; REG UWORD *p; /* scratch pointer */ REG WORD i; BSETUP if (UBWORD(dsknum) > 15) return(0xffff); uncp)(); /* funcp is a pointer to a Boolean function */ REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */ { REG ****/ #include "stdio.h" /* Standard I/O declarations */ #include "bdosdef.h" /* Type and structure declarations for BDO /**************************************************************** * * * CP/M-68K BDOS File I/O Module * * *(i--) *p2++ = *p1++; } /************************************* * General purpose filename matcher * *****************ffff); } if ( (*funcp)(fcbp, (GBL.dirbufp) + (i&3), i) ) /* call function with parms of (1) fcb ptr, (2) pointe selpkt.iofcn = sel_info; selpkt.devnum = dsknum; selpkt.ioflags = 0; do_phio(&selpkt); /* actually do the disk select */UWORD i; /* loop counter */ REG struct dpb *dparmp; /* pointer to disk parm block */ REG UWORD dirsec; /* sector S */ #include "pktio.h" /* Packet I/O definitions */ /* declare external fucntions */ EXTERN UWORD do_phio(); /* packet * This module contains all file handling BDOS functions * * except for read and write for CP/M-68K. Included are: * * ********************/ BOOLEAN match(p1, p2, chk_ext) REG UBYTE *p1; REG UBYTE *p2; BOOLEAN chk_ext; { REG WORD i;r to directory entry, and (3) directory index */ return(i & 3); /* return directory code */ } ret if ((GBL.dphp = selpkt.infop) == NULL) return(0xffff); GBL.dirbufp = (GBL.dphp)->dbufp; /* set up GBL copies of dnumber we're working on */ BSETUP dparmp = GBL.parmp; /* init ptr to dpb */ for ( i = 0 ; i <= dparmp->ddisk i/o handler */ EXTERN UWORD swap(); /* assembly language byte swapper */ /************************ * seldisk entry * * seldisk() - select disk * * openfile() - open file * * move() - general purpose byte mover * * REG UBYTE temp; BSETUP i = 12; do { temp = (*p1 ^ '?'); if ( ((*p1++ ^ *p2++) & 0x7f) && temp ) urn(255); } ir_buf and dpb ptrs */ GBL.parmp = (GBL.dphp)->dpbp; return(0); } /******************************* * General purposerm ; i++ ) { /* main directory scanning loop */ if ( ! (i & 3) ) { /* inside loop happens when we need to point * ************************/ WORD seldisk(dsknum) REG UBYTE dsknum; /* disk number to select */ { struct i return(FALSE); i -= 1; } while (i); if (chk_ext) { if ( (*p1 != '?') && ((*p1 ^ *p2) & ~((GBL.parmp)->e/* Packet I/O definitions */ #include "biosdef.h" /* Declarations for BIOS entry points */ EXTERN udiv(); /* Assembly l * * This module translates from the packet oriented I/O * * passed from the other BDOS modules into BIOS calls. * * return(0); }  fcb_ext = fcbp->extent; /* save extent number from user's fcb */ move(dirp, fcbp, sizeof *dirp); /* copy dir entry inl divide */ UWORD iotrk; UWORD iosect; } iopdiv; LOCK /* lock the disk system while doing physical i/o */ xm)) ) return(FALSE); p1 += 2; p2 += 2; if ((*p1 ^ *p2) & 0x3f) return(FALSE); } return(TRUE); } /**anguage unsigned divide routine */ /* in bdosif.s. It's used because Alcyon C */ /* can't do / or % without an exter * * It includes only one external entry point: * do_phio() - do physical i/o * * * * * * Configured f return(0); } to user's fcb */ fcbp->extent = fcb_ext; } return(rtn); }  switch (iop->iofcn) { case sel_info: iop->infop = bseldsk(iop->devnum, iop->ioflags); break; case read: h********************** * openfile entry point * ************************/ BOOLEAN openfile(fcbp, dirp, dirindx) REG strnal */ /************************ * do_phio entry point * ************************/ UWORD do_phio(iop) REG struct iopor Alcyon C on the VAX * * * ****************************************************************/ #include "stdio.h" ***************************************** * Assembly Language Interface Routine * * for the CP/M-68K loader, cpmldr * *o user's fcb */ fcbp->extent = fcb_ext; } return(rtn); } drp = iop->infop; dparmp = hdrp->dpbp; udiv( iop->devadr, dparmp->spt, &iopdiv ); bsettrk( iopdiv.iotrk + dparmp->trk_ouct fcb *fcbp; /* pointer to fcb for file to open */ struct dirent *dirp; /* pointer to directory entry */ WORD dirindx; b *iop; /* iop is a pointer to a i/o parameter block */ { REG struct dph *hdrp; /* pointer to disk parameter header * /* Standard I/O declarations */ #include "bdosdef.h" /* Type and structure declarations for BDOS */ #include "pktio.h" * * It has one entry point: _startld * * It sets up the stack and jumps to * * _ldcpm * ************************* /**************************************************************** * * * CP/M-68K BDOS Disk I/O System Module * * ff ); bsetsec( bsectrn( iopdiv.iosect, hdrp->xlt ) ); bsetdma(iop->xferadr); return(bread()); } UNLOCK { REG UBYTE fcb_ext; /* extent field from fcb */ REG BOOLEAN rtn; if ( rtn = match(fcbp, dirp, TRUE) ) {/ REG struct dpb *dparmp; /* pointer to disk parameter block */ struct { /* structure for results of externa**************** .globl _startld * public entry point .globl ldr * label for library search .globl _bios * external / UWORD xferlen; /* number items to transfer */ UBYTE *xferadr; /* memory address to xfer to/from */ struct dph *infop; .end  UWORD dskmax; UWORD dirmax; UWORD chksize; }; */ struct iopb { UBYTE iofcn; /* function number, see defines references .globl _ldcpm .globl _bios1 * library search .globl _dirscan * " " .globl _seqread * " " ./******************************************************** * * * CP/M-68K header file * * Copyright (c) 1982 by D /* pointer to disk parameter header */ /* return parm for fcn 0, input for rest */ }; /* Definitions for iofcn, t .end below */ UBYTE ioflags; /* used for login flag and write flag */ UBYTE devtype; /* device type, see defines below */ text ldr: _startld: lea stack,sp clr.l d0 jsr _bios * init the BIOS move #22,d0 move #8,d1 move.l #privexc,d2 igital Research, Inc. * * Structure definitions for doing I/O in packets * * * *************************************he function number */ #define sel_info 0 /* select and return info on device */ #define read 1 #define write 2 #define /* currently unused */ UBYTE devnum; /* device number, or, devtype and devnum taken together form int device nu jsr _bios * set exception for privilege violation ori #$2000,sr * set supervisor state * if in user mode, will generat*******************/ /* May use this information structure instead of disk parameter header and disk parameter block in f flush 3 #define status 4 /* not currently used */ /* Definitions for devtype, the device type */ /* This field nmber */ LONG devadr; /* item nmbr on device to start xfer at */ /* note -- item is sector for disks, byte for char devs *e priv violation lea stack,sp bra _ldcpm privexc: ori.w #$2000,(sp) rte .bss .ds.l 256 stack: .ds.w 1 uture, but for now it's unused struct dskinfo { UBYTE *dbuffp; UBYTE *csv; UBYTE *alv; UBYTE blksize; UBYTE didummy;ot currently used */ #define console 0 #define printer 1 #define disk 2 #define memory 3 /* gets TPA boundaries */ /***************************/ #ifdef ALCYON #define UBYTE char #define UBWORD(a) ((UWORD)a & 0xff) /* Unsigned byne WORD short /* Signed word (16 bits) */ #define UWORD unsigned int /* unsigned word */ #define LONG long /* sig**********************************************************************/ #define abs(x) ((x) < 0 ? -(x) : (x)) /* Absolute val ----------------------------------- * Copyright 1982 by Digital Research Inc. All rights reserved. * * This is an incl#define FOREVER for(;;) /* Infinite loop declaration */ #define NULL (BYTE *)0 /* Null pointer value */ #define EOF ( #define redir 4 /* read/write IOByte */ #define exc_vec 5 /* set exception vector */ te to word cast */ #else #define UBYTE unsigned char /* Unsigned byte */ #define UBWORD(a) (UWORD)a #endif /****ned long (32 bits) */ #define ULONG unsigned long /* Unsigned long */ #define REG register /* register variable */ue function */ #define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */ #define min(x,y) (((x) < (y)) ? (ude file for assisting the user to write portable * programs for C. * *******************************************************-1) /* EOF Value */ #define TRUE (1) /* Function TRUE value */ #define FALSE (0) /* Function FALSE value *#define redir 4 /* read/write IOByte */ #define exc_vec 5 /* set exception vector */ ************************************************************************/ /* Miscellaneous Definitions: */ /********** #define LOCAL auto /* Local var on 68000 */ #define EXTERN extern /* External variable */ #define MLOCAL static x) : (y)) /* Min function */ /*************************** end of stdio.h *********************************/ **********************/ #define ALCYON 1 /* using Alcyon compiler */ /* * Standard type definitions */ /******/ /****************************************************************************/ /* */ /* M A C R O S ******************************************************************/ #define FAILURE (-1) /* Function failure return val */ # /* Local to module */ #define GLOBAL /**/ /* Global variable */ #define VOID /**/ /* Void function return */) : (y)) /* Min function */ /*************************** end of stdio.h *********************************/ *********************/ #define BYTE char /* Signed byte */ #define BOOLEAN char /* 2 valued (true/false) */ #defi */ /* ----------- */ /* */ /* Define some stuff as macros .... */ /* */ /******/***************************************************************************** * * C P / M C H E A D E R F I L E *define SUCCESS (0) /* Function success return val */ #define YES 1 /* "TRUE" */ #define NO 0 /* "FALSE" */ ) : (y)) /* Min function */ /*************************** end of stdio.h *********************************/ DOS(CONIN, 0)) /* Get character from console */ /**/ #define isalpha(c) (islower(c)||isupper(c)) /* true if "c" a M A C R O S */ /* ----------- ation */ /* */ /**** */ #define EOF (-1) /* EOF Value */ #define TRUE (1) /* toupper(c) (islower(c) ? ((c)-040):(c)) /* translate to upper case */ /**/ #define abs(x) ((x) < 0 ? -(x) : (x)) /) : (y)) /* Min function */ /*************************** end of stdio.h *********************************/ letter */ #define isdigit(c) ('0' <= (c) && (c) <= '9') /* Ascii only!! */ #define iswhite(c) ((c) <= 040 || */ /* */ /* Define some********************************************************************/ long BDOS(); /***/  */ /**** Function TRUE value */ #define FALSE (0) /* Function FALSE value */ #define BUF* Absolute value function */ #define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */ #define min(x,y) CESS (0) /* Function success return val */ #define YES 1 /* "TRUE" 0177<= (c)) /* Is control / funny char */ #define iswild(c) ((c) == '*' || (c) == '?') /* true if a wildcard char */ /** stuff as macros .... */ /* *******************************************************************/ long BDOS(); /***/  */ /****SIZE 128 /* # bytes in a buffer */ /**/ /********************************** (((x) < (y)) ? (x) : (y)) /* Min function */ /**/ /**************************************************** */ #define NO 0 /* "FALSE" */ #define FOREVER for(;;) / #define islower(c) ('a' <= (c) && (c) <= 'z') /* Ascii only!! */ #define isupper(c) ('A' <= (c) && (c) <= 'Z') */ /****************************************************************************/ #define getchar() ((char) Bf M68010 bsr.w except * 2 Buserr excrtn0: bsr.w except * 3 Addressing error bsr.w except * 4 Illegal Instruction #******************************************/ /* */ /* ********************/ /* */ /* BDOS Procedure Declar /* Infinite loop declaration */ #define NULL 0 /* Null pointer value /* Ascii only!! */ /**/ #define tolower(c) (isupper(c) ? ((c)+040):(c)) /* translate to lower case */ #define/* struct for optab */ struct optbl { WORD inmsk; WORD invalu; WORD infmt; BYTE *innam; }; #define MAXff8, 0x4e68, 17, "move.l", 0xfff8, 0x4840, 22, "swap", 0xfff8, 0x4e58, 22, "unlk", 0xfff0, 0x4e40, 23e", 0xfff8, 0x57c8, 12, "dbeq", 0xfff8, 0x58c8, 12, "dbvc", 0xfff8, 0x59c8, 12, "dbvs", 0xfff8, "move.w", 0xffc0, 0x46c0, 5, "move.w", 0xffc0, 0x40c0, 5, "move.w", 0xffc0, 0x4c80, 18, "movem., 0xffff, 0x4e74, 21, "rtd", 0xffff, 0x4e73, 0, "rte", 0xffff, 0x4e77, 0, "rtr", 0xffff, 0x4e7xffc0, 0x4240, 7, "clr.w", 0xffc0, 0x4280, 7, "clr.l", 0xffc0, 0x0c00, 3, "cmpi.b", 0xffc0, 0x0c40FMT 28 #define OPENT 4 /* # words per line in optab */ struct optbl optab[] = { 0xffff, 0x023c, 3, "andi.b", , "trap", 0xffc0, 0x0600, 3, "addi.b", 0xffc0, 0x0640, 3, "addi.w", 0xffc0, 0x0680, 3, "addi.l0x5ac8, 12, "dbpl", 0xfff8, 0x5bc8, 12, "dbmi", 0xfff8, 0x5cc8, 12, "dbge", 0xfff8, 0x5dc8, 12, "w", 0xffc0, 0x4cc0, 18, "movem.l", 0xffc0, 0x4880, 18, "movem.w", 0xffc0, 0x48c0, 18, "movem.l", 5, 0, "rts", 0xffff, 0x4e72, 21, "stop", 0xffff, 0x4e76, 0, "trapv", 0xfffe, 0x4e7a, 24, "movec, 3, "cmpi.w", 0xffc0, 0x0c80, 3, "cmpi.l", 0xffc0, 0x0a00, 3, "eori.b", 0xffc0, 0x0a40, 3, " 0xffff, 0x027c, 3, "andi.w", 0xffff, 0x0a3c, 3, "eori.b", 0xffff, 0x0a7c, 3, "eori.w", 0xffff,", 0xffc0, 0x0200, 3, "andi.b", 0xffc0, 0x0240, 3, "andi.w", 0xffc0, 0x0280, 3, "andi.l", 0xfdblt", 0xfff8, 0x5ec8, 12, "dbgt", 0xfff8, 0x5fc8, 12, "dble", 0xfff8, 0x4880, 14, "ext.w", 0xff 0xffc0, 0x0e00, 25, "moves.b", 0xffc0, 0x0e40, 25, "moves.w", 0xffc0, 0x0e80, 25, "moves.l", 0xffc0,", 0xfff8, 0x50c8, 12, "dbt", 0xfff8, 0x51c8, 12, "dbf", 0xfff8, 0x52c8, 12, "dbhi", 0xfff8, 0x5eori.w", 0xffc0, 0x0a80, 3, "eori.l", 0xffc0, 0x4ec0, 7, "jmp", 0xffc0, 0x4e80, 7, "jsr", 0xf 0x4afa, 0, "illegal", 0xffff, 0x4afb, 0, "illegal", 0xffff, 0x4afc, 0, "illegal", 0xffff, 0x4e71,fc0, 0xe1c0, 7, "asl", 0xffc0, 0xe0c0, 7, "asr", 0xffc0, 0x0840, 10, "bchg", 0xffc0, 0x0880, 10, f8, 0x48c0, 14, "ext.l", 0xfff8, 0x4e50, 15, "link", 0xfff8, 0x4e60, 17, "move.l", /* move usp */ 0xf 0x4800, 7, "nbcd", 0xffc0, 0x4400, 7, "neg.b", 0xffc0, 0x4440, 7, "neg.w", 0xffc0, 0x4480, 7, 3c8, 12, "dbls", 0xfff8, 0x54c8, 12, "dbcc", 0xfff8, 0x55c8, 12, "dbcs", 0xfff8, 0x56c8, 12, "dbnfc0, 0xe3c0, 7, "lsl", 0xffc0, 0xe2c0, 7, "lsr", 0xffc0, 0x42c0, 5, "move.w", 0xffc0, 0x44c0, 5, 0, "nop", 0xffff, 0x003c, 3, "ori.b", 0xffff, 0x007c, 3, "ori.w", 0xffff, 0x4e70, 0, "reset" "bclr", 0xffc0, 0x08c0, 10, "bset", 0xffc0, 0x0800, 10, "btst", 0xffc0, 0x4200, 7, "clr.b", 0 "neg.l", 0xffc0, 0x4000, 7, "negx.b", 0xffc0, 0x4040, 7, "negx.w", 0xffc0, 0x4080, 7, "negx.l", f00, 0x6900, 8, "bvs", 0xff00, 0x6a00, 8, "bpl", 0xff00, 0x6b00, 8, "bmi", 0xff00, 0x6c00, 8, 00, 3, "subi.b", 0xffc0, 0x0440, 3, "subi.w", 0xffc0, 0x0480, 3, "subi.l", 0xffc0, 0x4ac0, 7, 0xf1f8, 0xe0a0, 6, "asr.l", 0xf1f8, 0xb108, 11, "cmpm.b", 0xf1f8, 0xb148, 11, "cmpm.w", 0xf1f8, 0c0, 0x52c0, 7, "shi", 0xffc0, 0x53c0, 7, "sls", 0xffc0, 0x54c0, 7, "scc", 0xffc0, 0x55c0, 7, 140, 13, "exg", 0xf1f8, 0xc148, 13, "exg", 0xf1f8, 0xc188, 13, "exg", 0xf1f8, 0xe100, 6, "asl.b" 0xffc0, 0x4600, 7, "not.b", 0xffc0, 0x4640, 7, "not.w", 0xffc0, 0x4680, 7, "not.l", 0xffc0, 0 "bge", 0xff00, 0x6d00, 8, "blt", 0xff00, 0x6e00, 8, "bgt", 0xff00, 0x6f00, 8, "ble", 0xff00, "tas.b", 0xffc0, 0x4a00, 7, "tst.b", 0xffc0, 0x4a40, 7, "tst.w", 0xffc0, 0x4a80, 7, "tst.l", xb188, 11, "cmpm.l", 0xf1f8, 0xe108, 6, "lsl.b", 0xf1f8, 0xe148, 6, "lsl.w", 0xf1f8, 0xe188, 6, "scs", 0xffc0, 0x56c0, 7, "sne", 0xffc0, 0x57c0, 7, "seq", 0xffc0, 0x58c0, 7, "svc", 0xffc0, , 0xf1f8, 0xe140, 6, "asl.w", 0xf1f8, 0xe180, 6, "asl.l", 0xf1f8, 0xe120, 6, "asl.b", 0xf1f8,x0000, 3, "ori.b", 0xffc0, 0x0040, 3, "ori.w", 0xffc0, 0x0080, 3, "ori.l", 0xffc0, 0x4840, 7, 0x6000, 8, "bra", 0xff00, 0x6100, 8, "bsr", 0xf1f8, 0xc100, 1, "abcd", 0xf1f8, 0xc108, 1, "a 0xff00, 0x6200, 8, "bhi", 0xff00, 0x6300, 8, "bls", 0xff00, 0x6400, 8, "bcc", 0xff00, 0x6500, 8, "lsl.l", 0xf1f8, 0xe128, 6, "lsl.b", 0xf1f8, 0xe168, 6, "lsl.w", 0xf1f8, 0xe1a8, 6, "lsl.l", 0x59c0, 7, "svs", 0xffc0, 0x5ac0, 7, "spl", 0xffc0, 0x5bc0, 7, "smi", 0xffc0, 0x5cc0, 7, "sge 0xe160, 6, "asl.w", 0xf1f8, 0xe1a0, 6, "asl.l", 0xf1f8, 0xe000, 6, "asr.b", 0xf1f8, 0xe040, 6, "pea", 0xffc0, 0xe7c0, 7, "rol", 0xffc0, 0xe6c0, 7, "ror", /* rotate memory */ 0xffc0, 0xe5c0, 7, bcd", 0xf1f8, 0xd100, 1, "addx.b", 0xf1f8, 0xd140, 1, "addx.w", 0xf1f8, 0xd180, 1, "addx.l", "bcs", 0xff00, 0x6600, 8, "bne", 0xff00, 0x6700, 8, "beq", 0xff00, 0x6800, 8, "bvc", 0xf 0xf1f8, 0xe008, 6, "lsr.b", 0xf1f8, 0xe048, 6, "lsr.w", 0xf1f8, 0xe088, 6, "lsr.l", 0xf1f8, 0xe0", 0xffc0, 0x5dc0, 7, "slt", 0xffc0, 0x5ec0, 7, "sgt", 0xffc0, 0x5fc0, 7, "sle", 0xffc0, 0x04 "asr.w", 0xf1f8, 0xe080, 6, "asr.l", 0xf1f8, 0xe020, 6, "asr.b", 0xf1f8, 0xe060, 6, "asr.w", "roxl", 0xffc0, 0xe4c0, 7, "roxr", 0xffc0, 0x50c0, 7, "st", 0xffc0, 0x51c0, 7, "sf", 0xff0xf1f8, 0xd108, 1, "addx.b", 0xf1f8, 0xd148, 1, "addx.w", 0xf1f8, 0xd188, 1, "addx.l", 0xf1f8, 0xc28, 6, "lsr.b", 0xf1f8, 0xe068, 6, "lsr.w", 0xf1f8, 0xe0a8, 6, "lsr.l", 0xf1f8, 0x0108, 19, "m, 0xf1c0, 0xd140, 2, "add.w", 0xf1c0, 0xd180, 2, "add.l", 0xf1c0, 0xd0c0, 2, "adda.w", 0xf1c0 "roxr.w", 0xf1f8, 0xe0b0, 6, "roxr.l", 0xf1f8, 0x8100, 1, "sbcd", 0xf1f8, 0x8108, 1, "sbcd", "movea.w", 0xf1c0, 0x2040, 16, "movea.l", 0xf1c0, 0xc1c0, 9, "muls", 0xf1c0, 0xc0c0, 9, "mulu"038, 6, "ror.b", 0xf1f8, 0xe078, 6, "ror.w", 0xf1f8, 0xe0b8, 6, "ror.l", 0xf1f8, 0xe110, 6, " "btst", /* fix to Belton's code */ 0xf1c0, 0x4180, 9, "chk", 0xf1c0, 0xb000, 2, "cmp.b", 0xf1c0, 0xb04ovep.w", 0xf1f8, 0x0148, 19, "movep.l", 0xf1f8, 0x0188, 19, "movep.w", 0xf1f8, 0x01c8, 19, "movep.l",, 0xd1c0, 2, "adda.l", 0xf1c0, 0x5000, 4, "addq.b", 0xf1c0, 0x5040, 4, "addq.w", 0xf1c0, 0x5080, 4 0xf1f8, 0x9100, 1, "subx.b", 0xf1f8, 0x9140, 1, "subx.w", 0xf1f8, 0x9180, 1, "subx.l", 0xf1f8, 0xf1c0, 0x8000, 2, "or.b", 0xf1c0, 0x8040, 2, "or.w", 0xf1c0, 0x8080, 2, "or.l", 0xf1c0, 0xroxl.b", 0xf1f8, 0xe150, 6, "roxl.w", 0xf1f8, 0xe190, 6, "roxl.l", 0xf1f8, 0xe130, 6, "roxl.b", 0, 2, "cmp.w", 0xf1c0, 0xb080, 2, "cmp.l", 0xf1c0, 0xb0c0, 2, "cmpa.w", 0xf1c0, 0xb1c0, 2, "c 0xf1f8, 0xe118, 6, "rol.b", /* rotate register */ 0xf1f8, 0xe158, 6, "rol.w", 0xf1f8, 0xe198, 6, , "addq.l", 0xf1c0, 0xc000, 2, "and.b", 0xf1c0, 0xc040, 2, "and.w", 0xf1c0, 0xc080, 2, "and.l, 0x9108, 1, "subx.b", 0xf1f8, 0x9148, 1, "subx.w", 0xf1f8, 0x9188, 1, "subx.l", 0xf1c0, 0xd000, 28100, 2, "or.b", 0xf1c0, 0x8140, 2, "or.w", 0xf1c0, 0x8180, 2, "or.l", 0xf1c0, 0x9000, 2, "su 0xf1f8, 0xe170, 6, "roxl.w", 0xf1f8, 0xe1b0, 6, "roxl.l", 0xf1f8, 0xe010, 6, "roxr.b", 0xf1f8, mpa.l", 0xf1c0, 0x81c0, 9, "divs", 0xf1c0, 0x80c0, 9, "divu", 0xf1c0, 0xb100, 2, "eor.b", 0xf "rol.l", 0xf1f8, 0xe138, 6, "rol.b", 0xf1f8, 0xe178, 6, "rol.w", 0xf1f8, 0xe1b8, 6, "rol.l", ", 0xf1c0, 0xc100, 2, "and.b", 0xf1c0, 0xc140, 2, "and.w", 0xf1c0, 0xc180, 2, "and.l", 0xf1c0, "add.b", 0xf1c0, 0xd040, 2, "add.w", 0xf1c0, 0xd080, 2, "add.l", 0xf1c0, 0xd100, 2, "add.b"b.b", 0xf1c0, 0x9040, 2, "sub.w", 0xf1c0, 0x9080, 2, "sub.l", 0xf1c0, 0x9100, 2, "sub.b", 0xf0xe050, 6, "roxr.w", 0xf1f8, 0xe090, 6, "roxr.l", 0xf1f8, 0xe030, 6, "roxr.b", 0xf1f8, 0xe070, 6, 1c0, 0xb140, 2, "eor.w", 0xf1c0, 0xb180, 2, "eor.l", 0xf1c0, 0x41c0, 2, "lea", 0xf1c0, 0x3040, 16, 0xf1f8, 0xe018, 6, "ror.b", 0xf1f8, 0xe058, 6, "ror.w", 0xf1f8, 0xe098, 6, "ror.l", 0xf1f8, 0xe, 0x0140, 10, "bchg", 0xf1c0, 0x0180, 10, "bclr", 0xf1c0, 0x01c0, 10, "bset", 0xf1c0, 0x0100, 10, 1c0, 0x9140, 2, "sub.w", 0xf1c0, 0x9180, 2, "sub.l", 0xf1c0, 0x90c0, 2, "suba.w", 0xf1c0, 0x91c0, * ***************************************************************** * .globl _GO .globl _STEP .globl _BDOS .gin a multi-tasking file system. Consequently, the primitives LOCK and UNLOCK are defined and used where necessary in the ve.l a0,savea0 move.l usp,a0 move.l a0,saveusp move.l savea0,a0 andi $5fff,sr movem.l a6/a7,bsave are based */ #define BSETUP REG struct stvars *statep; \ statep = &gbls; /* set u0),a1 set up stack pointers move a1,usp user stack pointer move.l 8(a0),a7 supervisor stack pointer movem.l 14(2, "suba.l", 0xf1c0, 0x5100, 4, "subq.b", 0xf1c0, 0x5140, 4, "subq.w", 0xf1c0, 0x5180, 4, "sulobl _GETSSP .text * * _GO: movem.l d0-d7/a0-a5,regsave save register variables movem.l a6/a7,asave move.w ***************************************************************** * * * Usual filename: BDOS.S * * Adapted by: save regs move.l asave+4,a7 get old regs move.l 4(a7),a6 move.l pctr,(a6) move.l savp pointer to state variables */ /* This is intended as an example to show the intent */ #endif /*a0),d0-d7/a0-a6 set up other registers move.l pctr,-(a7) set up for rte and.w #$7FFF,status bq.l", 0xf100, 0x7000, 20, "moveq.l", 0xf000, 0x1000, 16, "move.b", 0xf000, 0x3000, 16, "move.w", #22,d0 set up illegal trap vector move.w #iltv,d1 move.w d1,thvnum move.l #th,d2 trap #3 move.l d0,savev * Timothy M. Benson * * Control: 5 May 83 15:25 (TMB) * * eusp,4(a6) move.l savessp,8(a6) move.w status,12(a6) and.w #$7FFF,12(a6) movem.l d0-d7/a0-a5,14(a6) mov Note that there are a few critical regions in the file system that must execute without interruption. They pertain mostly move.w status,-(a7) rte begin executing * * trap handling for _GO and _STEP * th: m 0xf000, 0x2000, 16, "move.l", 0x0000, 0x0000, 0, "*unknown instruction*" }; , 0x3000, 16, "move.w", move.l 4(a7),a0 addr of state save area * move.w #62,d0 get supervisor mode trap #2 move.l a7,realssp * * initiate program execution * * e.w #22,d0 move.w thvnum,d1 move.l savev,d2 trap #3 move.l bsave,70(a6) move.l bsave+4,74(a6) btst # to the manipulation of the allocation vector. This isn't a problem in a single-thread model, but must be provided for ove.w (a7)+,status grab info from sys stack move.l (a7)+,pctr move.l a7,savessp move.l realssp,a7 mo 0xf000, 0x2000, 16, "move.l", 0x0000, 0x0000, 0, "*unknown instruction*" }; , 0x3000, 16, "move.w", * move.l (a0),pctr pc to start at move.w 12(a0),status starting status move.l 4(a5,status beq wasusr move.l savessp,74(a6) wasusr: move.l asave,a6 movem.l regsave,d0-d7/a0-a5 rts BDOS: move.w 4(a7),d0 move.l d1,saved1 move.l 6(a7),d1 trap #2 move.l saved1,d1 rts * .bss * saved1: .ds.l 1 * .ds.l 14 realssp: .ds.l 1 savessp: .ds.l 1 saveusp: .ds.l 1 savea0: .ds.l 1 iltv = $4 illegal instruction vectordphp; /* pointer to disk parm hdr for cur disk */ struct dirent *dirbufp; /* pointer for directory buff for proSave previous trace exception pointer. * move.l asave+4,a0 caller's stack ptr move.l 4(a0),a0 address of cpu state save are */ BOOLEAN lstecho; /* True if echoing console output to lst: */ BOOLEAN echodel; back to SID proper * * ***************************************************************** * * * execut .text * ***************************************************************** * * * GETSSP -- supplies system stack poin number trv = $9 trace exception vector number * savev: .ds.l 1 thvnum: .ds.w 1 * setexp = 61 setsup = 62 * pctr: cess */ /* stored here so that each process can */ /* havea move.l (a0),pctr starting pc move.w 12(a0),d0 status ori.w #$8000,d0 set trace bit move.w d0,status starting status /* Echo char when getting ? */ UWORD column; /* CRT column number for expanding tabs */ e one user instruction (trace or notrace) * * * ***************************************************************** * ter to C * * * ***************************************************************** * _GETSSP: move.w #62,d0 trap #2 .ds.l 1 status: .ds.w 1 * * .text * ***************************************************************** * /************************************************************************/ /* */ /* Usual filename: SID05.C */ move.l 4(a0),a1 user stack pointer move.l a1,usp move.l 8(a0),a7 system stack pointer movem.l 14(a0),d0-d7/a0-a6 registers UBYTE curdsk; /* Currently selected disk */ UBYTE dfltdsk; /* Default disk (l_STEP: movem.l d0-d7/a0-a5,regsave save registers movem.l a6/a7,asave save registers * move.w #62,d0 get supervisor mode move.l a7,d0 andi #$5fff,sr rts * .end * * BDOS Call Subroutine -- C Callable * * * ***************************************************************** * _ /* Remarks: Fourth C module for SID68K */ /* Adapted by: Timothy M. Benson */ /* Control: 11 MAY 83 11:31 (TMB move.l pctr,-(a7) set up for rte move.w status,-(a7) rte * .bss * asave: .ds.l 2 bsave: .ds.l 2 regsave:ast selected by fcn 14) */ UBYTE user; /* Current user number */ struct dph * trap #2 move.l a7,realssp * move.w #22,d0 move.w #trv,d1 move.w d1,thvnum move.l #th,d2 trap #3 move.l d0,savev  move.l a7,d0 andi #$5fff,sr rts * .end ) */ /* */ /************************************************************************/ #include #ibreak; case 7 : inf7(); break; case 8 : inf8(); break; case 9 : inf9(); break; case 10 : inf10(); breamatches anything */ if( (instr & (p->inmsk)) == p->invalu) break; /* found it */ p++; } stout(p->innam---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* ABCD, ADDX EXTERN WORD scope; EXTERN BYTE ref; EXTERN LONG inhalt; /**temp** End of added stuff */ REG struct optbl recently */ if ( ref ) { putchar(' '); spell((U32)inhalt,caput->sump,scope,ref,'H'); } } else punclude "lgcdef.h" #include "cputype.h" #include "siddef.h" #include "ddtinc.h" #include "optab.h" #include "stdio.h" #inclk; case 11 : inf11(); break; case 12 : inf12(); break; case 13 : inf13(); break; case 14 : inf14(); break; ); /* print mnemonic */ stout(" "); if( (p->infmt >= 0) && (p->infmt <= MAXFMT) ) { if(p->infmt) { s, SBCD, SUBX */ /* */ /************************************************************************/ { REG WORD *p; REG WORD reg; /**temp** Next several lines added recently */ ref = '\0'; /* Mark "not in use" */ tchar('?'); } VOID noin() { stout("illegal instruction format #\n"); return; } VOID inf1() /********ude "bdosfunc.h" #include "disas.h" VOID pinstr() /******************************************************************* case 15 : inf15(); break; case 16 : inf16(); break; case 17 : inf17(); break; case 18 : inf18(); break; cwitch ( p->infmt) { /* call proper funct */ case 0 : noin(); break; case 1 : inf1(); break; case 2 : inf2(i; i = (instr & 0x0E00) >> 9; if (instr & 8) { /* R/M field == 1 so... */ paripd(instr & 7); /* this is m /**temp** End of added stuff */ sdot = dot + 2; /* next word address */ dotinc = 2; instr = dot->memw;****************************************************************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+*****/ /* */ /* print an instruction in assembler format */ /* */ /***************************************ase 19 : inf19(); break; case 20 : inf20(); break; case 21 : inf21(); break; case 22 : inf22(); break; case ); break; case 3 : inf3(); break; case 4 : inf4(); break; case 5 : inf5(); break; case 6 : inf6(); emory to memory op */ putchar(','); /* use Address registers with */ paripd(i); /* predecrement. */ } else { /* instruction in binary */ p = &optab; /* sequential search = (n+1)/2 */ while(TRUE) { /* last table entry ---+---+---+---+---+---+ */ /* | x | x | x | x | REG Rx | x | SIZE | x | x |R/M| REG Ry | */ /* +---+---+---+---+*********************************/ { /**temp** Next several lines added recently */ EXTERN struct lmhedr *caput; 23 : inf23(); break; case 24 : inf24(); break; case 25 : inf25(); break; } } /**temp** Next line added pdr(instr & 7); /* R/M field == 0 so.... */ putchar(','); /* this is data reg to data reg */ pdr(i); /* operands in/* | x | x | x | x | x | x | x | x | SIZE | MODE | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+--tr & 0x00C0) >> 6; } if( (reg > 7) || ( (instr & 0x0100) == 0) ) { prtop(instr & 077,mode); putchar(','); /**/ case 0x0A3C: /* and ORI to CCR. */ case 0x003C: stout("CCR"); break; default : prtop( (instr & 077), SUB, SUBA */ /* */ /************************************************************************/ { REG WORD reg; { REG WORD size; size = (instr & 0x00C0) >> 6; /* Print out the size of the */ /* operation. Then s data register. */ } } VOID inf2() /************************************************************************/ /* -+---+---+---+---+ */ /* | WORD DATA (16 bits) | BYTE DATA (8 bits) | */ /* +---+---+---+---+---+-- Operation ,(Dn or An) */ prtreg(reg); } else { prtreg(reg); putchar(','); /* Operation Dn, */ prto,size); } } VOID inf4() /************************************************************************/ /* */ REG WORD mode; reg = ( (instr & 0x0E00) >> 9); /* Special case the ADDA/SUBA */ /* instructions. Theperate */ /* with blank. Display the */ primm(size); /* immediate size of the value. */ putchar(','); */ /* | EFFECTIVE ADDRESS | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ -+---+---+---+---+---+---+---+---+---+---+ */ /* | LONG DATA (32 bits, including previous word) | */ /* +---+---p(instr & 077,mode); } } VOID inf3() /************************************************************************/ /*/* | EFFECTIVE ADDRESS | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x ese have */ /* OP-MODEs = 3,7. Then add 8 */ /* to denote address register */ if( (instr & 0x00C0) == 0x00C0) switch (instr) { /* Then print the effective */ case 0x027C: /* address. Special case ANDI, */ case 0x0A7C: /* | x | x | x | x | REGISTER | OP-MODE | MODE | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+-+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* A */ /* EFFECTIVE ADDRESS */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ | x | x | x | DATA | x | SIZE | MODE | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---{ mode = WORDSZ; if((instr & 0x01C0) == 0x01C0) { mode = LONGSZ; } reg += AREG0; } else { mode = (ins /* EORI, and ORI to SR. */ case 0x007C: stout("SR"); break; case 0x023C: /* Also special case ANDI, EORI --+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* ADD, ADDA, AND, CMP, CMPA, EOR, LEA, ORDDI, ANDI, CMPI, EORI, ORI, SUBI */ /* */ /************************************************************************/+---+---+ */ /* */ /* Covers the following instructions: */ /* ADDQ, SUBQ */ /****************************/* */ /************************************************************************/ { REG WORD i; i = (ins stout(",CCR"); else if (i == 0x0600) stout(",SR"); } VOID inf6() /******************************************** */ /* */ /************************************************************************/ { prtop( (instr & 077),WOE | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Covers the fo***************************************************/ /* */ /* | EFFECTIVE ADDRESS | */ /* +---+---+--********************************************/ { REG WORD i; i = (instr & 0x0E00) >> 9; if(i == 0) i = 8; tr & 0x0E00) >> 9; /* get register number and find */ if(instr & 0x0020) { /* if bit # is in a register. */ pdr(i); ****************************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* |RDSZ); /* print the Effective Address */ /* size is a nop for imm */ } VOID inf8() /****************************llowing instructions: */ /* MOVE to CCR, MOVE from CCR, MOVE to SR, MOVE from SR */ /* */ /**********************-+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | x | x | x | x | x | x | MODE | REGISTER stout("#$"); hexbzs( (BYTE)i); putchar(','); prtop((instr & 077),WORDSZ); } VOID inf5() /***** /* If so print the reg # */ } else { /* Otherwise.... */ if(i == 0) /* A zero denotes 8 bits all */ i x | x | x | x | COUNT/REG | DR| SIZE |I/R| x | x | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+********************************************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+**************************************************/ { REG WORD i; i = instr & 0x0600; if(i == 0) { stout( | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Covers The following instr*******************************************************************/ /* */ /* | EFFECTIVE ADDRESS | */ /= 8; /* others the same */ putchar('#'); /* print the immediate value */ hexbzs((BYTE)i); } putchar(','); ---+---+---+ */ /* */ /* Covers the following instructions: */ /* ASL, ASR, LSL, LSR, ROL, ROR, ROXL, ROXR */ ---+ */ /* | x | x | x | x | CONDITION | 8-BIT DISPLACEMENT | */ /* +---+---+---+---+---+---+---+---+---+---+"SR,"); } else if (i == 0x0200) { stout("CCR,"); } prtop( (instr &077),WORDSZ); if(i == 0x0400) uctions: */ /* ASL, ASR, CLR, JMP, JSR, LSL, LSR, NBCD, NEG, NEGX, */ /* NOT, PEA, ROL, ROR, ROXL, ROXR, Scc, TAS, TST, * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | x | x | x | x | x | x | MOD /* Then.... */ prtreg(instr & 07); /* display the reg to be shifted*/ } VOID inf7() /*********************---+---+---+---+---+---+ */ /* | 16-BIT DISPLACEMENT if 8-BIT == 0 | */ /* +---+---+---+---+---+---+---+---+---+-10() /************************************************************************/ /* */ /* | EFFECTIVE ADDRE | x | MODE | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /---+---+---+---+---+---+ */ /* | x | x | x | x |REGISTER Rx| x | SIZE | x | x | x |REGISTER Ry| */ /* +---+---+---+---+t->memw; /* displacement = current local */ sdot += 2; /* + the next word. Bump the */ dotinc += 2; /* counters accord**********************************/ { if(instr & 0x0100) { /* if bit #dynamic, then print */ pdr( (instr & 0x0E00) >--+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* Bcc, BRA, BSR */ /* SS | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | REGISTER | x | x * Covers the following Instructions: */ /* CHK, DIVS, DIVU, MULS, MULU */ /* */ /*****************************---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* CMPM ingly */ } stout("$"); /* Print the hex value of the */ hexlzs(p); /* displacement. */ } VOID in> 9); /* Data reg number. */ } else { /* Otherwise... */ primm(WORDSZ); /* print the immediate value */ */ /************************************************************************/ { REG WORD i; /* temp for 8-bit displ| x | MODE | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | BIT NUMB*******************************************/ { REG WORD i; prtop( (instr & 077),WORDSZ); /* print the Effective */ /* */ /************************************************************************/ { REG WORD i; parf9() /************************************************************************/ /* */ /* | EFFECTIVE ADDR } putchar(','); prtop( (instr & 077),WORDSZ); /* then the Effective Address */ } VOID inf11() /********acement */ REG BYTE *p; i = instr.lobyte; /* Determine if 8-bit displace- */ if(i) { /* ment is presentER (for static only) | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Cov Address */ putchar(','); i = (instr & 0x0E00) >> 9; /* Then the register and type */ pdr(i); } VOID infipi(instr & 7); /* Prints source address then */ putchar(','); /* the destination address in */ i = (instr & 0x0E0ESS | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | REGISTER | x | x****************************************************************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+. If so get */ p = sdot + i; /* current location and add disp*/ } else { /* Otherwise... */ p = sdot + sdoers the following instructions: */ /* BCHG, BCLR, BSET, BTST */ /* */ /**************************************0) >> 9; /* Address register post inc */ paripi(i); } VOID inf12() /********************************************tr & 7; opmde = instr & 0x00F8; if(opmde == 0x0048) { /* Specifies both as Address */ rx += AREG0; /* registers */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x |REGISTER Rx| x | OP******************************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* ******************************************/ { REG BYTE *p; /* Get and print out the Data */ pdr(instr -+---+---+---+---+---+---+---+ */ /* | x | x | x | x | x | x | x | OP-MODE | x | x | x | REGISTER | */ /* +---+---+--****************************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* |. Bump by 8 to let */ ry += AREG0; /* routine know. */ } else if(opmde == 0x0088) { /* if true echange is betwe-MODE |REGISTER Ry| */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Cover | x | x | x | x | x | x | x | x | x | x | x | x | x | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+--& 07); /* Register that contains the */ /* count. */ putchar(','); p = sdot + sdot->memw; /* Then get c-+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* EXT x | x | x | x | CONDITION | x | x | x | x | x | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+en a */ ry += AREG0; /* data and address reg. Ry is */ } /* always an Address register. */ prtreg(rx); /s the following instructions: */ /* EXG */ /* */ /*********************************************************-+---+---+---+ */ /* | DISPLACEMENT | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ urrent loc and add */ sdot += 2; /* the diaplacement. Bump all */ dotinc += 2; /* pointers then print disp. */ */ /* */ /************************************************************************/ { REG WORD i; ---+---+---+ */ /* | DISPLACEMENT | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ ** prints source register */ putchar(','); prtreg(ry); /* print destination register */ } VOID inf14() /*****************/ { REG WORD rx; REG WORD ry; REG WORD opmde; rx = (instr & 0x0E00) >> 9; ry = ins */ /* */ /* Covers the following instructions: */ /* LINK */ /* */ /**************************** hexlzs(p); } VOID inf13() /************************************************************************/ /* i = instr & 07; /* Print out Data Register */ pdr(i); } VOID inf15() /******************************************/ /* */ /* Covers the following instructions: */ /* DBcc */ /* */ /****************************************************************************************************/ /* */ /* +---+---+---+---+---+---+---+---+--********************************************/ { par(instr & 7); stout(",#$"); hexwzs(sdot->memw); sdot ***********************************/ { REG WORD i; i = instr & 7; if(instr & 8) { /* USP to An */ stoutective Address */ } VOID inf17() /************************************************************************/ /* ot += 2; dotinc += 2; if (instr & 0x0400) { /* test for mem->reg xfer */ prtop( (instr & 077), WORDSZ); putchar */ /************************************************************************/ { REG WORD size; REG WORD i; ---+ */ /* | x | x | x | x | x | x | x | x | x | x | MODE | REGISTER | */ /* +---+---+---+---+---+---+---+---+---++= 2; dotinc += 2; } VOID inf16() /************************************************************************/ /* ("USP,"); par(i); } else { par(i); stout(",USP"); } } WORD regmsk0[] = {0100000,040000,020000,01000 */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | x | x | x | x | x | x |(','); putrlist(regmsk1,rlm); } else { /* must be reg->mem */ if ( (instr & 070) == 040 ) putrlist(regmsk i = instr & 0x3000; /* determine the size */ if(i == 0x1000) size = BYTESZ; else if (i == 0x3000) size = W---+---+---+---+---+---+---+ */ /* | REGISTER LIST MASK | */ /* +---+---+---+---+---+---+---+---+---+---+- */ /* | DESTINATION | SOURCE | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+--0,04000,02000,01000,0400,0200, 0100,040,020,010,4,2,1}; WORD regmsk1[] = {1,2,4,010,020,040,0100,0200,0400,01000,02000,040 x | x | DR| REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Cove0,rlm); /* predec */ else putrlist(regmsk1,rlm); putchar(','); prtop( (instr & 077), WORDSZ); } } VOID ORDSZ; else if(i == 0x2000) size = LONGSZ; else badsize(); prtop( (instr & 077),size); /* Source Effective--+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* MOVEM */ /* */ /***-+---+ */ /* | x | x | SIZE | REGISTER | MODE | MODE | REGISTER | */ /* +---+---+---+---+---+---+---+---+--00,010000, 020000,040000,0100000}; VOID inf18() /***********************************************************************rs the following instructions: */ /* MOVE USP,An, MOVE An,USP */ /* */ /************************************* inf19() /************************************************************************/ /* */ /* +---+---+---+---+---+- Address */ putchar(','); i = ( (instr & 07000) >> 9) | ( (instr & 0700) >> 3); prtop(i,size); /* Dest. Eff*********************************************************************/ { REG WORD rlm; rlm = sdot->memw; sd-+---+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions. */ /* MOVE, MOVEA */ /* */ /* */ /* | EFFECTIVE ADDRESS | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | DATA REG | OP-MODE | x | x | x | ADDR REG | */ /* ********************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x |+---+---+ */ /* | x | x | x | x | REGISTER | x | DATA | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+-23() /************************************************************************/ /* */ /* +---+---+---+---+---+---+-/ prtreg((instr & 0x0E00) >> 9); putchar(','); } j = sdot->memw; hexwzs(j); /* print the displacement */*****************************************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--- +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | DISPLACEMENT | */ /* +---+---+---+ x | x | x | x | x | x | x | x | x | x | x | x | x | x | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--+---+---+---+ */ /* */ /* Covers the following instructions: */ /* MOVEQ */ /* */ /***********--+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | x | x | x | x | x | x | x | x | VECTOR | */ /* +--- pari(instr & 7); /* and the Address register */ if(i == 0x0100) { /* This is memory to register */ putchar(',+ */ /* | x | x | x | x | x | x | x | x | x | x | x | x | x | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+------+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* MOVEP ---+ */ /* | IMMEDIATE DATA | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* *************************************************************/ { stout("#$"); hexbzs((BYTE)(instr & 0x00FF)); +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /*'); prtreg( (instr & 0x0E00) >> 9); } sdot += 2; dotinc += 2; } VOID inf20() /***********************+---+---+---+---+---+---+ */ /* */ /* Covers the following instructions: */ /* SWAP, UNLK */ /* */ */ /* */ /************************************************************************/ { REG WORD i; REG */ /* Covers the following instructions: */ /* STOP, RTD(68010) */ /* */ /**************************putchar(','); prtreg((instr & 0x0E00) >> 9); } VOID inf21() /**************************************************** TRAP */ /* */ /************************************************************************/ { stout("#$"); *************************************************/ /* */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+--- /************************************************************************/ { prtreg(instr & 0x000F); } VOID inf WORD j; i = instr & 0x0180; /* Get transfer direction */ if(i == 0x0180) { /* This is register to memory ***********************************************/ { primm(WORDSZ); } VOID inf22() /******************************* hexbzs((BYTE)(instr & 0x000F)); } VOID inf24() /******************************************************************* | x | x | x | SIZE | MODE | REGISTER | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /*eak; case 0x0800: stout("USP"); break; case 0x0801: stout("VBR"); break; default: stout("illegal Contro */ /************************************************************************/ { REG WORD i; REG WORD *p; *****************************************/ { REG WORD creg; REG WORD rreg; REG WORD i; i = sdot->memw; & 0xF000) >> 12) & 0x000F; /* get the general register */ if (i & 0x0800) { /* This is register to */ prtreg(rr*****/ /* */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | x | x |A/D| REGISTER | x | x | x | x | x | x | x | x | x | x | x | x | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+-l Register"); break; } if ( !(instr & 1)) { /* this is Creg to register */ putchar(','); prtreg(rreg); }REG WORD lmsk; REG WORD j; lmsk = mask; p = ap; j = -1; for(i = 0; i < 16; i++) { if(lmsk & sdot += 2; dotinc += 2; creg = i & 0x0FFF; /* get Control Register then */ rreg = ( (i & 0xF000) >> 12) eg); putchar(','); } prtop( (instr & 077),size); /* print the effecive address */ if ( !(instr & 0x800)) {| x | x | x | x | x | x | x | x | x | DR| */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* |A--+---+---+---+ */ /* */ /* Covers the following instructions: */ /* MOVES(68010) */ /* */ /****** } VOID inf25() /************************************************************************/ /* */ /* |*p++) { if(j == 0) putchar('/'); if(j != 1) { prtreg(i); putchar('-'); } j = 1; } el& 0x000F; /* the A/D register */ if (instr & 1) { /* This is register to Creg */ prtreg(rreg); putchar(','); } /* this is to register */ putchar(','); prtreg(rreg); } } VOID putrlist(ap,mask) WORD *ap; WORD mask;/D| REGISTER | Control Register | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* ******************************************************************/ { REG WORD rreg; REG WORD size; REG WORD i; EFFECTIVE ADDRESS | */ /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ /* | x | x | x | x | xse if(j == 1) { prtreg(i - 1); j = 0; } } if(j == 1) stout("A7"); } VOID pdr(r) WORD r; / switch (creg) { /* display Control Register */ case 0: stout("SFC"); break; case 1: stout("DFC"); br /************************************************************************/ /* */ /* PUT Register LIST */ /* */ /* Covers the following instructions: */ /* MOVEC (68010) */ /* */ /******************************* size = instr & 0x00C0; /* get the size */ i = sdot->memw; sdot += 2; dotinc += 2; rreg = ((i************************************************************************/ /* */ /* Print Data Register */ /* */ /* */ /************************************************************************/ { pari(r); putchar('+' par(r); putchar(')'); } VOID paripd(r) WORD r; /*********************************************************************************************************************/ /* */ /* The SIZE field is wrong */ /* */ /********************************/ /* */ /* Print Data Register Inderect */ /* */ /**************************** /* */ /* write an integer in hex */ /* */ /*********************************************************** */ /************************************************************************/ { putchar('D'); putchar(hexchar); } VOID hexlzs(n) LONG n; /************************************************************************/ /* */ *******/ /* */ /* Print Address Register Indirect PreDecrement */ /* */ /**************************************************************************************************/ { stout("\n** illegal size field **\n"); } VOI********************************************/ { putchar('('); pdr(r); putchar(')'); } VOID pari(r) WORD *************/ { puthex((LONG)n, 16, 1); } VOID hexbzs(n) BYTE n; /******************************************(r)); } VOID par(r) WORD r; /************************************************************************/ /* */ /* write a long integer in hex */ /* */ /****************************************************************************************************************/ { putchar('-'); pari(r); } VOID paripi(r) WORD r; /*************D prtreg(areg) WORD areg; /************************************************************************/ /* */ /* Printr; /************************************************************************/ /* */ /* Print Address Register Indirec******************************/ /* */ /* write a byte as a hex integer */ /* */ /*********************** /* Print Address Register */ /* */ /************************************************************************/ / { EXTERN LONG inhalt; EXTERN BYTE ref; inhalt = n; ref = 'm'; /* Let ref => possible symbol */ ***********************************************************/ /* */ /* Print Address Register Indirect Post Increment the register specified in AREG */ /* */ /************************************************************************/t */ /* */ /************************************************************************/ { putchar('('); *************************************************/ { puthex((LONG)n, 8, 1); } VOID badsize() /********************{ putchar('A'); putchar(hexchar(r)); } VOID pdri(r) WORD r; /********************************************** puthex(n,32,1); } VOID hexwzs(n) WORD n; /************************************************************************/ { REG WORD reg; reg = areg; if(reg > 7) { par(reg - 8); } else { pdr(reg); } } / sdot += 2; /* default to WORD or BYTE */ dotinc += 2; stout("#$"); /* print out immediate value in */ ***************************************/ /* */ /* Print out Immediate value */ /* */ /*****************xFFFF0000; /* sign extend like hard */ sdot += 2; dotinc += 2; hexlzs(p); break; case 1: /ex */ /* */ /************************************************************************/ { REG WORD i; 0: /* D reg direct */ pdr(reg); break; case 1: /* A reg direct */ par(reg); break; case 2: /* A VOID prdisp() /************************************************************************/ /* */ /* PRint DISPlaceme hexlzs(l1); /* hex notation. */ } VOID prtop(adrtype,asize) WORD adrtype; WORD asize; /*******************************************************************************/ { LONG l1; l1 = 0; /* initialize for safety */ * xxx.L */ la.hiword = sdot->memw; sdot += 2; dotinc += 2; la.loword = sdot->memw; sdot += 2; i = sdot->memw; sdot += 2; dotinc += 2; putchar('$'); hexbzs((BYTE)(i & 0x00FF)); putchar('('); indirect */ pari(reg); break; case 3: /* A+ */ paripi(reg); break; case 4: /* -(An) */ paripd(reg)nt */ /* */ /************************************************************************/ { REG WORD i; ************************************************/ /* */ /* Print the Effective Address */ /* */ /******* if (asize == LONGSZ) { /* Determine whether it is a */ l1.hiword = sdot->memw; /* LONG immediate value. Get */ sdot += dotinc += 2; putchar('$'); hexlzs(la); break; case 2: /* d(PC) */ prdisp(); stout(" if(areg == PC) stout("PC,"); else { par(areg); putchar(','); } prtreg( (i >> 12) & 0x000F); i; break; case 5: /* d(an) */ prdisp(); pari(reg); break; case 6: /* d(An,Ri) */ prindex(reg); b i = sdot->memw; sdot += 2; dotinc += 2; putchar('$'); hexwzs(i); } VOID prindex(areg) WORD areg; /*****************************************************************/ { REG WORD reg; REG WORD mode; REG WORD defer 2; /* value and bump pointers if so*/ dotinc += 2; } l1.loword = sdot->memw; /* get loword value if LONG else*(PC)"); break; case 3: /* d(PC,Ri) */ prindex(PC); break; case 4: primm(asize); break; f( i & 0x0800) stout(".l"); putchar(')'); } VOID primm(asize) WORD asize; /*********************************reak; case 7: la = 0; switch(reg) { case 0: /* xxx.W */ p = sdot->memw; if(p & 0x8000) p |= 0************************************************************************/ /* */ /* Address Register Indirect With Ind; LONG la; REG LONG p; mode = (adrtype & 070) >> 3; reg = adrtype & 7; switch (mode) { case } break; } } } } if ( ! nomore(cx) ) {bad(); return(0);} statep->pc = newpc; /* Execute one instruction */ if (ST */ short mor; /* 1 => nonzero pass count, so GO again */ union asis BEGIN long i32; char *p8; int *p16; and.p16 EQ ILLEGAL then BLOCK showstate(statep); stout("\nEncountered the ILLEGAL instruction\n"); goto trotz; UNo.h" #include "bdosfunc.h" #include "disas.h" gocmd(cx,statep,nulist) /* begin executing (optional breakpoints) */ char ->memw = ILLEGAL; } GO(statep); /* Restore previous contents at break points. */ for (i=0; imemw = brkwd[i]; yank(); /* Restore original contents at pass points. */ newpc = statep AT pc; /* Det/************************************************/ /* */ /* Usual filename: SID03.C */ /* Remarks: Second C module fostore after pass, process pass point if */ /* applicable, continuing until pass point with count of one */ /* is encount newpc = statep->pc; if (gethex(&cx, &x)) newpc = x; nbp = 0; while ( GETSEP ) { if (nbp >= MAXB end If ancien[i] NE BDOSCALL and ancien[i] NE BIOSCALL then STEP(statep); else begin /* Execute system call normHMPPTS]; extern int minus; /* 1 => no intermediate display */ int nbp; long brkpt[MAXBP]; short ermine if pass point */ for(i=0,itsapp=0; i LT HMPPTS and NOT itsapp; i++) BLOCK strand.p16 = plocus[i]; If pkawnt[ir SID68K */ /* Author: Timothy M. Benson */ /* Control: 19 MAY 83 16:52 (TMB) */ /* */ /*************************ered or until break point is encountered. */ for (mor = 1; mor and NOT keyhit();) BEGIN stick(); /* Set up pass pointsP) {bad(); return;} else { if (gethex(&cx,&x)) brkpt[nbp++]=x; else {bad(); return;} ally */ strand.i32 = newpc + 2; jetsam = *strand.p16; *strand.p16 = ILLEGAL; GO(statep); *stbrkwd[MAXBP]; long newpc; long x; int i; short itsapp; /* 1 => ILLEGAL identified as pass point] and strand.i32 EQ newpc then begin itsapp = 1; i--; end UNBLOCK strand.i32 = newpc; If *str***********************/ #include "lgcdef.h" #include "cputype.h" #include "siddef.h" #include "ddtinc.h" #include "stdi */ for (i=0; imemw; brkpt[i]rand.p16 = jetsam; end newpc = statep AT pc; If pkawnt[i] GT (U16) 1 then --pkawnt[i]; otherwise begin mor = ] = nc; if ( parse(&cx, &(bpp->fcb1), " ") && GETSEP ) parse(&cx, &(bpp->fcb2), " "); } disasm(cx,dap) char putchar(' '); puthexl(a-b); putchar('\n'); UNBLOCK else bad(); END } yhit() ) return; If caput then nl INCBY spell((U32) s,caput AT sump,scope,'m','v'); putchar(' '); putchar(' '); long a, b; deblank(&cx); If nomore(cx) then BEGIN If omega GE 0 then deluge(caput AT sump,omega); e } if ( s & 1) { bad(); return(0);} /* must use even address */ if ( GETSEP ) { /* get end ad0; showstate(statep); end UNBLOCK otherwise BLOCK mor = 0; showstate(statep); UNBLOCK END t*cx; char **dap; { /* display memory in assembly format */ extern struct lmhedr *caput; extern int scope; char *s; incomtl(cx, valuep) char *cx; struct value *valuep; { /* process command tail */ register char *p; register char *q; r puthexl(s); putchar('\t'); dot = s; pinstr(); putchar('\n'lse stout("\nNo symbols\n"); END otherwise BEGIN If gethex(&cx,&a) and nomore(cx) then BLOCK putchar('\n'); puthdress */ if ( gethex(&cx, &f) ) deflt=0; /* got it */ else { bad(); return(0); } } else { f = s; deflt = 1; }rotz: *nulist = statep AT pc; } /* end of go command */ /************************************************/ /* H alone: S /* start address */ char *f; /* end address */ register short int deflt; register short int nl; egister char nc; register struct basepage *bpp; if ( (valuep->kind) != 1 ) {bad(); return;} /* no pgm loaded */ bpp = ); s += dotinc; nl++; *dap = s; } /* end of loop through instructionexl(a); putchar(' '); If qotbyt(a) then putchar(' '); spell(a,caput AT sump,scope,'b','h'); putchar('\n'); UNB /* not there, use def */ if((!nomore(cx)) || (s>f)) {bad(); return(0);} /* junk or nonsense */ pill symbol table */ /* Ha format: Print hex, ASCII, symbols */ /* Ha,b format: Do arithmetic */ /********************* /* parse command and extract parameters */ deblank(&cx); if ( ! gethex(&cx, &s) ) { /* get start address */ valuep->bpa; p = cx + 1; q = &(bpp->comtail[1]); nc = 0; while (*p) { *q++ = *p++; nc += 1;} *q = *p; bpp->comtail[0s */ } /* end disassembly */ movemem(cx) char *cx; { /* move memory block */ char *s; /* start address LOCK else If GETSEP && gethex(&cx,&b) && nomore(cx) then BLOCK putchar('\n'); puthexl(a+b); /* now do the display */ nl = 0; while ( (s<=f) || (deflt && (nl<12)) ) { if ( ke***************************/ hexmath(cx) char *cx; { extern struct lmhedr *caput; extern int omega; extern int scope; if (nomore(cx)) s = *dap; /* or use default */ else {bad(); return(0);} /* junk on the line */ */ char *f; /* end address */ char *d; /* destination address */ /* parse co} else bad(); /* parsing error */ } setmem(cx) char *cx; { /* set memory */ register short int format; nnot open file\n"); return; } fcb1.cr = 0; lotpa = basep->lowtpa; hitpa = basep; curdma = lotpa; endofile mw); break; case 4: puthexl(s->meml); break; { bad(); return(0); } /* now do the moving */ for ( ; s <= f; s++, d++ ) d->memb = s->memb; } /* end of m0);} /* not there, error */ if ( (format != 1) && (s & 1) ) /* must be even address, error */ mmand and extract parameters */ deblank(&cx); if ( gethex(&cx, &s) ); /* get start address */ else { /* 1=byte, 2=word, 4=long word */ char *s; /* start address */ long v; /* valu= 0; while ( (! endofile) && (curdma+128 <= hitpa) ) { /* read a sector */ BDOS(SETDMA, curdma); endofile = } /* end of switch */ putchar(' '); *buf = BUFLEN - 2; BDOovemem */ readfl(cx, basep, valuep, dap) char *cx; struct basepage *basep; struct value *valuep; char **dap; { /* read {bad(); return(0);} if (!nomore(cx)) { bad(); return(0); } /* test for junk */ /* now do the stuffbad(); return(0);} /* not there, error */ if ( GETSEP && gethex(&cx, &f) ); /* get end address */ e to stuff into memory */ char buf[BUFLEN]; /* input buffer */ char *bx; /* points i(BDOS(READSEQ, &fcb1) & 0xffL); curdma += 128; } if ( ! endofile ) stout("\nFile too big -- read truncated.\n"); vaS ( READBUF, buf ); putchar('\n'); buf[2+(nc=buf[1])] = 0; if ( nc > 0 ) { a file into memory */ struct fcb fcb1; long lotpa; long hitpa; long curdma; int endofile; deblank(&cx); if ing */ for ( ; ; s += format ) { puthexl(s); putchar(' '); switch ( format ) { else { bad(); return(0); } /* not there, error */ if ( GETSEP && gethex(&cx, &d) ); /* get dest addrento buf */ short int nc; /* num of hex digits input */ /* parse command and extract parametersluep->kind = 2; valuep->textbase = lotpa; valuep->textlen = curdma - lotpa - 128; showvals(valuep); *dap = lotpa; if ( buf[2] == '.' ) {return(0);} for ( bx = &buf[1] ; *++bx ; ) *bx = ( parse(&cx, &fcb1, " ") && nomore(cx)) { if ( (BDOS(OPEN, &fcb1) & 0xffL) == 0xffL) /* open failed */ { stout("Ca case 1: puthexb(s->memb); break; case 2: puthexw(s->mess */ else { bad(); return(0); } if ((!nomore(cx)) || (s>f) ) /* test for junk or nonsense */ */ format = getform(&cx); if ( gethex(&cx, &s) ); /* get start address */ else {bad(); return(toupper(*bx) ; bx = &buf[1]; if ( gethex( &bx, &v ) ); app; /* 1 => ILLEGAL identified as pass point */ union asis32 BEGIN long i32; char *p8; U16 *p16; END strac > 0 */ } /* end of for */ } /* end of setmem */ trace(cx, statep, dap, tr) char *cx; struct cpustate * ILLEGAL then BEGIN showstate(statep); stout("\nEncountered the ILLEGAL instruction\n"); goto reject; END / case 1 : s->memb = (char)v ; if ( (s->memb ^ v) & 0x0ffL ) badram(s); break; */ int kt; /* Loop index for GO */ int steperr; /* set if an error exception occurs during step */ iota = omega; /* Save else { bad(); return(0); } while ( (*++bx) == 0x20 ) ; /* skip blanks */ nd; /* General purpose pointer */ /**temp** Watch this: "strand" declared "*strand" elsewhere and */ /**temp** seems to work.statep; char **dap; int tr; { /* trace program execution for n steps */ extern U16 pkawnt[HMPPTS]; extern U16 *plocus[HM* GO thru traps, ignoring pass points */ If (inst & 0xFFF0) EQ 0x4E40 then BEGIN inst = (addr INCBY 2) AT memw; addr case 2 : s->memw = (short int)v ; if ( (s->memw ^ v) & 0x0ffffL ) badram(s); true value of "omega" */ deblank(&cx); underw = vecina(&cx,'W'); if ( ! gethex(&cx, &nsteps)) nsteps = 1; if ( ! nomore if ( (*bx != 0) || /* test for bad input */ ( (format == 1) && ((v>255L) || (v<0)) ) Not sure why it works there, so it may */ /**temp** not work here. */ int jetsam; /* Place to save word after system cPPTS]; extern U16 ancien[HMPPTS]; extern int minus; /* 1 => no intermediate display */ extern int omega; /* If negative, S AT memw = ILLEGAL; GO(statep); addr AT memw = inst; goto refuse; END If underw and ((inst & 0xFF00) EQ 0x6 break; case 4 : s->meml = (long)v ; if ( s->meml ^ v ) badram(s);(cx) ) {bad(); return;} /* Warning: Let there be no explicit returns here to end */ /* of function, lest symbols be accidenta|| ( (format == 2) && ((v>65535L) || (v<0)) ) ) { bad(); return(0); }all */ long nsteps; register int underw; /* 1 => trace without call */ int oxbow; /* 0 => trace; otherwise it = length */ ID thinks no symbols */ int iota; /* Place to keep true value of "omega" */ /* while kidding oneself */ short its100 or (inst & 0xFFC0) EQ 0x4E80) then BEGIN If NOT (inst & 0x00FF) then oxbow = 4; /* Long BSR */ else If (inst & 0 break; } /* end of switch */ } /* end of nlly zapped. */ If tr and minus then omega = -1; while(nsteps--) { inst = (addr = (statep->pc))->memw; If inst EQ /* stuff the value */ switch ( format ) { register int inst; register long addr; int jt; /* General purpose loop index */ short mor; /* 1 => not finished with GO xFF00) EQ 0x6100 then oxbow = 2; /* Short BSR */ else BLOCK /* JSR */ inst ANDWITH 0x003F; If inst Gnd UNBLOCK addr AT memw = inst; END otherwise steperr = STEP(statep); refuse: if (tr) showstate(statep)plocus[kt] then { itsapp = 1; kt--; } If itsapp and pkawnt[kt] GT (U16) 1 then --pkawnt[kt]; else } fcb1.cr = 0; while ( s <= f ) { BDOS(SETDMA, s); if ( BDOS(WRITSEQ, &fcb1) & 0xffL ) { stout("File wri; otherwise nsteps = 0; If NOT nsteps or NOT tr and NOT minus then BLOCK shopas(jt); showstate(statep); Ub1, " ") ) {bad(); return;} if ( nomore(cx) ) /* use default start and end */ { if ( (valuep->kind) != 2 ) {bad(); reE 0x0038 then begin If inst EQ 0x0039 then oxbow = 6; otherwise oxbow = 4; end else begin inst ANDWITH; if ( keyhit() || steperr ) nsteps = 0; } if ( ! tr ) showstate(statep); reject: *dap = statep->pc; omega = iota {mor = 0; nsteps = 0;} If *strand.p16 EQ ILLEGAL then { showstate(statep); stout("\nEncountered the ILLEGAL instte error.\n"); s = f + 1; } s += 128; } BDOS(CLOSE, &fcb1); } int dummy(s) char *s; { stout("\n\nUNBLOCK END If oxbow then BEGIN inst = (addr INCBY oxbow) AT memw; addr AT memw = ILLEGAL; steperr = STEP(stturn;} s = valuep->textbase; f = s + valuep->textlen - 1; } else /* try to parse s & f values */ { if ( ( ! GETS 0x0038; If inst EQ 0x0010 then oxbow = 2; otherwise oxbow = 4; end UNBLOCK END otherwise oxbow = ; /* Reenable symbols. */ } vcmd(cx, valuep) char *cx; struct value *valuep; {/* display start and end of stuff loaded wiruction\n"); addr AT memw = inst; goto reject; } If NOT nsteps or NOT tr and NOT minus then { shopas(knimplemented Function: "); stout(s); stout("\n\n"); } shopas(jsh) /* Display pass-point data */ int jsh; atep); for (mor=1;mor;) BLOCK stick(); GO(statep); yank(); If (strand.i32 = statep AT pc) EQ addr then moEP ) || ( ! gethex(&cx, &s) ) || ( ! GETSEP ) || ( ! gethex(&cx, &f) ) || ( ! nomore(cx) ) ) {bad(); return;} 0; strand.i32 = addr; for(jt=0,itsapp=0;jt LT HMPPTS and NOT itsapp;jt++) If pkawnt[jt] and strand.p16 EQ plth R or E commands */ if (nomore(cx)) showvals(valuep); otherwise bad(); } wrtfile(cx, valuep) char *cx; struct value t); showstate(statep); } steperr = STEP(statep); If keyhit() then {mor = 0; nsteps = 0; tr = 0;} e { extern U16 pkawnt[HMPPTS]; extern U16 *plocus[HMPPTS]; putchar('\n'); puthexw(pkawnt[jsh]); stout(" PASS "); r = 0; otherwise begin for(kt=0,itsapp=0;kt LT HMPPTS and NOT itsapp;kt++) If pkawnt[kt] and strand.p16 EQ } BDOS(DELETE, &fcb1); if ( (BDOS(MAKEFILE, &fcb1) & 0xffL) == 0xffL ) { stout("Cannot create file.\n"); return; ocus[jt] then BEGIN itsapp = 1; jt--; END If itsapp then BEGIN If pkawnt[jt] GT (U16) 1 then --pkawnt[jt]*valuep; { /* write memory contents to disk */ struct fcb fcb1; long s; long f; deblank(&cx); if ( ! parse(&cx, &fcputhexl(plocus[jsh]); putchar('\n'); } stick() /* Set pass points, saving original contents. */ { extern U16 pkawnt[HMP (Must agree with preceding line */ #define CONTIG 0x601A /* First word of contiguous load modules */ #define DISCON 0x601B /*iddef.h" ' at head of each */ /* separately compiled module containing */ /* code added to DDT68K to give SID68K. */ /if allowed, alignment on even address, no gaps. */ struct lmhedr BEGIN U16 lmkind; /* 0x601A => contiguous; 0x601B => nonco(kya=0; kya LT HMPPTS; kya++) If pkawnt[kya] then *plocus[kya] = ancien[kya]; }****************/ /* */ /* Structure of symbol table entry */ /* */ /********************************************PTS]; extern U16 *plocus[HMPPTS]; extern U16 ancien[HMPPTS]; int kst; for (kst=0; kst LT HMPPTS; kst++) If pkawnt[k First word of noncontiguous load modules */ #define TLONG 0x0080 /* Flag for entry in long-names string table */ #define GONE* Remarks: Definitions and declarations */ /* specific to SID68K. */ /* Author: Timothy M. Benson */ /* Control: ntiguous */ U32 lmtlen; /* Number of bytes in text segment */ U32 lmdlen; /* Number of bytes in data segment */ U32 padlen /* break; */ case 13: log_dsk = 0; /* reset disk system */ ro_dsk****/ struct asymbl BEGIN char namae[8]; U16 symtyp; U32 symval; END; #define sizasym 14 /**********************st] then BLOCK ancien[kst] = *plocus[kst]; *plocus[kst] = ILLEGAL; UNBLOCK } yank() /* Restore original contents 0x0040 /* Flag indicating hidden symbol */ #define SEGREF 0x0700 /* Text, data, or bss relative */ #define IS & /* (Sometimes12 MAY 83 15:36 (TMB) */ /* */ /********************************************************/ typedef long U32; type; /* Number of bytes in bss segment */ U32 symlen; /* Number of bytes in symbol table */ U32 nought; /* Filler: Should be z = 0; crit_dsk= 0; GBL.curdsk = 0xff; GBL.dfltdsk = 0; **************************/ /* */ /* Structure of load module header */ /* followed by symbol table */ /* */ /*at pass points. */ { extern U16 pkawnt[HMPPTS]; extern U16 *plocus[HMPPTS]; extern U16 ancien[HMPPTS]; int kya; for reads well) */ #define TREL 0x0200 /* (sic) Text relative */ #define DREL 0x0400 /* (sic) Data relative */ #define BREL 0x01def unsigned int U16; extern long HMSYMS; #define HMPPTS 32 /* # pass points allowed */ #define SAYMAX stout("32\n"); /*ero */ U32 tceps; /* Start of text */ U16 rflagb; /* 0 => relocation; nonzero => no relocation */ U32 dceps; /* Start of d/********************************************************/ /* */ /* Usual filename: SIDDEF.H */ /* Put ' #include "s***********************************************/ /* Using type definitions to ensure lengths of 16 and 32 bits, unsigned (kya=0; kya LT HMPPTS; kya++) If pkawnt[kya] then *plocus[kya] = ancien[kya]; }00 /* Bss relative */ #define XTRASYM 32 /* Number of symbols to pre-allocate space for */ /********************************ata */ U32 bceps; /* Start of bss */ struct asymbl sump[1]; /* Symbol table per se */ char filler[128]; END; #define sefine DECBY -= #define DEFAULT default #define DO do #define DOFALSE : #define DOTRUE ? #define ELSE else #define ENn */ /* Last modified: 27 January 1983 */ /* */ /********************************************************/ /* /************************************************/ /* */ /* Usual filename: SID04.C */ /* Remarks: Third C module for GBL.user = (UBYTE)info; return(UBWORD(GBL.user)); /* break; */ TRUE 1 #define UNBLOCK } #define VAL * #define WHILE while #define XOR ^ #define XORWITH ^= izlmhdr 178 D } #define EQ == #define FALSE 0 #define GE >= #define GT > #define IF if #define IGNORE continue #define INC +=Lower-case and mixed-case */ #define begin { #define end } #define otherwise else #define and && #define or || #defi SID68k */ /* Author: Timothy M. Benson */ /* Control: 9 MAY 83 13:59 (TMB) */ /* */ /***************************/********************************************************/ /* */ /* Usual filename: LGCDEF.H */ /* Put ' #include "l break; default: return(-1); /* bad function number */ /* brzlmhdr 178  #define INCBY += #define LE <= #define LT < #define NE != #define NOT ! #define OR | #define OREQ |= #define ORWne If if( /* Note mixed case */ #define then ) /* Upper-case */ #define ADDR & #define AND & #define ANDEQ &= #*********************/ #include "lgcdef.h" #include "cputype.h" #include "siddef.h" #include "ddtinc.h" #include "stdio.gcdef.h" ' at head of each */ /* separately compiled module containing */ /* code added to DDT68K to give SID68K. */ /eak; */ }; /* end of switch statement */ if (temp.reselect) infop->drvc!= GBL.dfltdsk) seldsk(GBL.dfltdsk); move( (GBL.parmp), infop, sizeof *(GBL.parmp) ); ITH |= #define SHL << #define SHLBY <<= #define SHLR <<= #define SHR >> #define SHRBY >>= #define SHRR >>= #definedefine ANDWITH &= #define AT -> #define BEGIN { #define BLOCK { #define CASE case #define COMP ~ #define DCR -= #dh" #include "bdosfunc.h" #include "disas.h" /******************************************************************** * ISSPAC* Remarks: General purpose symbol definitions */ /* for use by C-programmers in Languages. */ /* Author: Timothy M. Bensoode = temp.tempdisk; /* if reselected disk, restore it now */ return(rtnval); break; /* return disk parameters */ case 32: if ( (info & 0xff) <= 15 ) /* get/set user number */ TRUE 1 #define UNBLOCK } #define VAL * #define WHILE while #define XOR ^ #define XORWITH ^= E character * * Return TRUE if the character is a whitespace character ******************************************************and qu NE ',' and qu NE '+' and qu NE '-' and qu NE '/' and qu NE '*') ; /* Find char after supposed name */ If nchine dependent */ long all32; int last16[2]; char last8[4]; UNBLOCK triad; register char *cp; U1 return ( n<10 ? '0'+n : 'A'+n-10 ); } int puthex(n, i, zs) register long n; register int i; register int z* possible hex number from string or evaluate */ /* longest possible symbol. */ /* Fill in *np with value found. Return # o UNBLOCK END otherwise for (n=0, nd=0, cp = *cpp; ishex(*++cp); nd++, n=(n<<4)+he**************/ isspace(ch) int ch; { return(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); } putchar(x) rd = 8 * (omega GE 0 and (1 EQ indica((int)(cp - *cpp),*cpp ,caput AT sump,'B',&n,&nomo))) then If px NE '=' an6 *d16; /* For '@' values */ U32 *d32; /* For '!' values */ char *deixis; /* For '=' values */ long n; regs; { register char d; while ( i >= 4 ) { i -= 4; d = hexchar( (char)((n>>i) & 0xf) ); if ( d != '0' ) zs = 0; f */ /* digits if hex, 8 if symbol, or 0 if invalid. */ /* Leave **cpp pointing to next position after */ /* chars processed.xval(*cp)); *cpp = --cp; *np = n; return(nd); } int ishex ( c ) register char c; { returegister char x; { BDOS(CONOUT, (long)x); if (x == '\n') BDOS(CONOUT, (long)'\r'); } int stout(s) /* write ad px NE '.' and n AND 1L then nd = 0; otherwise BLOCK triad.all32 = 0; switch (px) begin case '.': triad.ister int nd; char px; /* . = @ ! */ register char qu; px = *(*cpp + 1); If px EQ '.' or px EQ '=' or px EQ '@' or px if ( (! zs) || (! i) ) putchar(d); } } int puthexl(n) /* write a long integer in hex */ long n; { puthex(n, 32, */ /************************************************/ gethex(cpp,np) char **cpp; long *np; { /**temp** This functionn ( ( ('0'<=c) && (c<='9') ) || ( ('A'<=c) && (c<='F') ) ); } int hexval ( c ) register char c; { if ( ('0 string */ register char *s; { register int nc; nc = 0; while ( *s ) { putchar( *s++ ); nc++; } all32 = n; break; case '=': deixis = n; triad.last8[3] = *deixis; break; case '@': d16 = n; EQ '!' then BEGIN cp = ++*cpp; /* Locate prefix */ ++*cpp; /* Skip prefix */ while((qu = *++cp) and qu NE ' ' 0); } int puthexw(n) /* write an integer in hex */ short int n; { puthex((long)n, 16, 0); } puthexb(n) extensively modified for SID */ extern struct lmhedr *caput; extern int omega; extern int nomo; union ambig BLOCK /* Ma'<=c) && (c<='9') ) return ( c-'0'); else return ( 10 + c - 'A' ); } char hexchar(n) register char n; { return(nc); } /************************************************/ /* Starting at byte after **cpp get longest */ / triad.last16[1] = *d16; break; case '!': d32 = n; triad.all32 = *d32; break; end n = triad.all32; /* write a byte in hex */ char n; { puthex((long)n, 8, 0); } int putbyte(c) /* write an ascii byte. if not prinif ( *(cx+1) == ':' ) {fcbp->dr = c - 'A' + 1; cx += 2; } else fcbp->dr = 0; n = 0; c = *cx; while (isalpha(c) || isdiegister short int format; cx = *cxp; if ( *++cx == 'W' ) format = 2; else if ( *cx == 'L' ) format = 4; else { forma case 1: /* do program vals */ for ( i = 0; i < 2; ++i ) { lp = &(vp->textbase); lp += i; for (j register char *cx; cx = (*cxp) + 1; if ((*cx != ' ') && (*cx != ',')) return(0); while ( *cx == fcbp->t[n++] = '?'; c = *++cx; break; } fcbp->t[n] = c; ++n; c = *++cx; } while ( n < 3 ) fcbp->t[ntable, write '.' */ register char c; { char d[2]; d[1] = 0; d[0] = ( ( (c < 0x20) || (c > 0x7E) git(c) || iswild(c)) { if ( n >= 8 ) return(0); if(c == '*') { while(n < 8) fcbp->fn[n++] = '?'; c = *++cxt = 1; cx--; } *cxp = cx; deblank(cxp); return(format); } parse(cxp, fcbp, dtp) register char **cxp; struc= 0; j < 3; ++j) { switch ( j ) { case 0: stout("text "); break; case 1: stout("data "); break; ' ' ) ++cx; if ( ! *cx ) return(0); if ( *cx != ',' ) {*cxp = --cx; return(1);} ++cx; while ( *cx ++] = ' '; *cxp = --cx; return(1); } /* end of parse fcb */ int keyhit() { if ( BDOS(CONSTAT, 0L) & 0xFFFFL )) ? '.' : c ); stout(d); } bad() { stout("?\n"); } badram(a) long a; { sto; break; } fcbp->fn[n++] = c; c = *++cx; } while ( n < 8 ) fcbp->fn[n++] = ' '; for (n = 0; n < 3; ++n) {t fcb *fcbp; char *dtp; { /* parse a filename into an fcb */ register char *cx; register char c; register int n; case 2: stout("bss "); break; } switch ( i ) { case 0: stout(" base "); break; case 1: stout("== ' ' ) ++cx; *cxp = --cx; return(1); } deblank(cxp) register char **cxp; { ++*cxp; { BDOS(CONIN, 0L); return(1); } else return(0); } showvals(vp) register struct value *vp; { register int i,ut("Bad or non-existent RAM at "); puthexl(a); putchar('\n'); } nomore(cx) char *cx; { ++cx; while if (*dtp) fcbp->t[n] = *dtp++; else fcbp->t[n] = ' '; } if (*cx != '.') {*cxp = --cx; return(1);} n = 0; c fcbp->ex = 0; fcbp->cr = 0; cx = *cxp; c = *++cx; if ( ! (isalpha(c) || isdigit(c) || iswild(c))) return(0); length"); break; } stout(" = "); puthexl(*lp); lp += 2; stout(" "); } putchar(' while ( isspace(**cxp) ) ++*cxp; --*cxp; } short int getform(cxp) register char **cxp; { register char *cx; r j; register long * lp; switch ( vp->kind ) { case 0: stout("\nERROR, no program or file loaded.\n"); break; (*cx) { if (!isspace(*cx)) return(0); else ++cx; } return(1); } getsep(cxp) register char **cxp; { = *++cx; while ( isalpha(c) || isdigit(c) || iswild(c)) { if ( n >= 3 ) return(0); if(c == '*') { while(n < 3) \n'); } stout("base page address = "); puthexl(vp->bpa); stout(" initial stack pointer = "); &(statep->vbr)); else if (cmp("SFC",cx)) pregn("SFC", &(statep->sfc)); else if (cmp("DFC",cx)) pregn("DFC", &(statep->df->areg[7] = statep->usp; } else if (cmp("SSP",cx)) { if (pregl("SSP",&(statep->ssp)) && & ZERO) stout(" ZER"); if (status & OFLOW) stout(" OFL"); if (status & CARRY) stout(" CRY"); put* */ /************************************************************ stout("PC="); puthexl(statep->pc); putchar(' '); stout("USP="); puthexl(statep->usp); putchar(' '); stout( puthexl(vp->initstk); break; /* end of program values */ case 2: /* do file values */ stout("Start = "); c)); #endif else if (*++cx == 'D') pdareg('D', cx, statep->dreg); else if (*cx == 'A') pdareg('A', cx (statep->status & SUPER) ) statep->areg[7] = statep->ssp; char('\n'); #ifdef MC68010 stout("VBR="); puthexl(statep->vbr); putchar(' '); stout("SFC="); puthex(statep->sfc, 4, 0); put****/ examine(cx, statep) char *cx; struct cpustate *statep; { if (nomore(cx)) showstate(statep); "SSP="); puthexl(statep->ssp); putchar(' '); stout("ST="); puthexw(status = statep->status); stout("=>"); puthexl(vp->textbase); stout(" End = "); puthexl((vp->textbase)+(vp->textlen)-1L); break; } putch, statep->areg); else bad(); if ( statep->status & SUPER) statep->ssp = statep->areg[7]; else statep->usp = statep->a } else if (cmp("ST", cx)) { pregw("ST",&(statep->status) ); if ( statep->status & SUPER) statep->areg[char(' '); stout("DFC="); puthex(statep->dfc, 4, 0); putchar('\n'); #endif preglrow('D', statep->dreg); /* D reg else if (cmp("PC",cx)) pregl("PC", &(statep->pc)); else if (cmp("USP",cx)) { if (pregl("USP",&(statep->usp if (status & TRACE) stout("TR "); if (status & SUPER) stout("SUP "); stout("IM="); putchar(((status &ar('\n'); } /* end of showvals */ /**/ /****************************************************************/ /* reg[7]; } showstate(statep) register struct cpustate *statep; { /**temp** Next several lines added recently */ 7] = statep->ssp; else statep->areg[7] = statep->usp; } #ifdef MC68010 else if (cmp("VBR",cx)) pregl("VBR", isters */ preglrow('A', statep->areg); /* A registers */ dot = statep -> pc; spell(statep AT pc,caput AT)) && ((statep->status & SUPER) == 0 )) statep INTMSK)>>8)+'0'); if (status & EXTEND) stout(" EXT"); if (status & NEG) stout(" NEG"); if (status */ /* Examine/Alter CPU Registers */ /extern int scope; extern struct lmhedr *caput; /**temp** End of added stuff */ register short int status; sump,scope,'m','h'); /* Label, if any */ pinstr(); /* disassembled instruction */ bp = buf + 1; if (gethex(&bp, &newval) && nomore(bp)) { switch(size) { modify = 0; stout(rname); putchar('='); switch(size) { case 0 : puthex(regp->meml, 4, 0); break( ( ! *str) && nomore(ctl) ) return(1); else return(0); } p, 4)); } pregn(rname, regp) char *rname; long *regp; { return(preg(rname, regp, 0)); } pregw(rname, regp) for (n=0; n<8; n++) { putchar(' '); puthexl(*rowp++); if (n==3) putchar(' ' putchar('\n'); } pdareg(da, cx, rp) /* print data or address register contents */ char da; register char *cx; lon case 0 : regp->meml = newval & 0xffL; break; case 1 : regp->memb = (char)(newval & 0xffL); break; case 2 : ; case 1 : puthexb(regp->memb); break; case 2 : puthexw(regp->memw); break; case 4 : puthexl(regp->meml); IOS definitions for CP/M-68K * * * * Copyright (/* print register contents as word */ char *rname; long *regp; { return( preg(rname, regp, 2) ); } preg(rname, regp, s); } putchar('\n'); } tryflags(cx, statep) register char *cx; register struct cpustate *statep; { bag *rp; { char str[3]; if ( ('0' <= *++cx) && (*cx <= '7') && nomore(cx) ) { str[0] = dregp->memw = (int)(newval & 0xffffL); break; case 4 : regp->meml = newval; break; } mo break; } putchar(' '); *buf = BUFLEN-2; BDOS(READBUF, buf); putchar('\n'); if ((nc=bufc) 1982 Digital Research, Inc. * * * * This include file simize) /* print register contents */ register char *rname; register long *regp; register int size; { char bufd(); } cmp(str, ctl) register char *str; register char *ctl; { while (*str && (*str++ == *++ctl)) ; ifa; str[1] = *cx; str[2] = 0; pregl(str, rp + *cx - '0'); } else badify = 1; } else if ( ! nomore(buf+1) ) bad(); } return(modify); } preg[1])>0) { buf[nc+2]=0; bp = buf + 1; while (*++bp) *bp = toupper(*bp); ply defines the BIOS calls * * * ***************************************[BUFLEN]; register short int nc; long int newval; char *bp; register int modify; ( ( ! *str) && nomore(ctl) ) return(1); else return(0); } d(); } pregl(rname, regp) /* print register contents as long */ char *rname; long *regp; { return(preg(rname, reglrow(ch, rowp) char ch; long *rowp; { register int n; putchar(ch); putchar(' '); *****************/ EXTERN UBYTE bios1(); /* used for character I/O functions */ EXTERN bios2(); /*ure bne openok * if not then go ahead * tst d3 * check if we are on user 0 beq loadfail * if so then we have failed age to local area lea localbp,a1 move.l #$100,d0 * count of bytes to move bsr copy * branch to subroutine * move.w #* set up lpb and load pgm move.l d1,lpbhitpa(a1) sub.l d0,d1 bclr.l #0,d1 move.l d1,lpblotpa(a1) clr.w lpbcf(a1) clr- This program loads SID68K at the top of * * the TPA, hands it its command tail, and passes control * * to it. * * Lahe bdos cmpi.w #0,d0 * check for errors bne loadfail * error, load failed * lea dskbuf,a0 move.l tsize(a0),d0 * com parm1 is word, no return value */ EXTERN bios3(); /* used for set dma only */ * move.w #32,d0 * if not then switch to user 0 clr.l d1 * d1 = 0 trap #2 * call the bdos * move.w #openf,d0 * t32,d0 * get the current user # and save it move.l #$ff,d1 * d1 = 255 trap #2 * call the bdos move.l d0,d3 * d3 hol.b ddt1fcb+fcbcr move.w #pgmldf,d0 * now do load move.l a1,d1 trap #2 tst.w d0 bne loadfail * load has failed * mst modified 28 January 1983 * * * **temp** Later revise symbol and comment usage to reflect * **temp** SID rather pute size of DDT1.68K add.l dsize(a0),d0 * by adding component sizes add.l bsize(a0),d0 add.l #$1000,d0 * fake stack siz /* parm1 is a pointer, no return */ EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */ ry the open again move.l #ddt1fcb,d1 * address of fcb trap #2 * call the bdos cmpi.b #$ff,d0 * check for errors beqds current user # * move.l bpaddr,a0 * get drive for DDT1 move.b $24(a0),ddt1fcb * and stuff into FCB move.w #openf,d0 ove.l d3,d1 * restore the old user 0 move.w #32,d0 * get bdos function # trap #2 * call the bdos * * set up for ddt than DDT * * ***************************************************************** * .text * start: move.l (a7)+,ccprtn *e since Belton doesnt add.l #bplen+fudge,d0 * cmpi.w #goodmgc,magic(a0) * must be $601A bne loadfail * tst.w rlbflg(a0 /* words, returns a pointer to dph */ EXTERN UWORD bios5(); /* for sectran and set ex loadfail * error, load failed * openok: move.w #setdma,d0 * set up to read pgm header move.l #dskbuf,d1 * dma address * open file DDT1.68K move.l #ddt1fcb,d1 * get address of fcb trap #2 * call the bdos cmpi.b #$ff,d0 * check for failexecution * move.l lpbbpa(a1),a2 * addr of new bp move.l bplotpa(a0),bplotpa(a2) * copy tpa lower bound move.l lpbdusp save stacked info move.l (a7)+,bpaddr * lea mystack+$80,a7 * switch to local stack * move.l bpaddr,a0 * copy base p) * must be 0 bne loadfail * lea localbp,a0 lea lpb,a1 lea ddt1fcb,a2 move.l a2,lpbfcb(a1) move.l bphitpa(a0),d1 ***************************************************************** * * * Usual filename: SIDLOAD.S * * SID Loader -trap #2 * call the bdos * move.w #readseq,d0 * read the header move.l #ddt1fcb,d1 * address of fcb trap #2 * call t(a1),a7 * default user stack ptr move.l a2,-(a7) * stack new bp address move.l ccprtn,-(a7) * stack ccp rtn address d1 trap #2 move.l ccprtn,-(a7) rts loaderr: .dc.b 13,10,'Cannot load DDT1.68K.',13,10,'$' * * .end  offsets in pgm header tsize = 2 dsize = 6 bsize = 10 stksize = 18 rlbflg = 26 * goodmgc = $601A * legal value for mag 8 #define PRNTSTR 9 #define READBUF 10 #define CONSTAT 11 #define GETVER 12 #define RESETDSK 13 #define SELDSK 14 #defpcsstrt= 8 bpcslen = $C bpdsstrt= $10 bpdslen = $14 bpbsstrt= $18 bpbslen = $1C bpfcb2 = $38 bpfcb1 = $5C * ccprtn: .ds /****************************************************************/ /* move.l bpcsstrt(a2),-(a7) * stack entry to ddt1 lea bpfcb2(a0),a0 * copy parsed fcb's & lea bpfcb2(a2),a1 * command ta1 trap #2 move.l ccprtn,-(a7) rts loaderr: .dc.b 13,10,'Cannot load DDT1.68K.',13,10,'$' * * .end ic number * * * lpb: .ds.w 11 * loader parameter block lpbfcb = 0 lpblotpa= 4 lpbhitpa= 8 lpbbpa = 12 lpbdusp = 16ine OPEN 15 #define CLOSE 16 #define SRCHFST 17 #define SRCHNXT 18 #define DELETE 19 #define READSEQ 20 #defin.l 1 * return addr in CCP bpaddr: .ds.l 1 * base page address * ddt1fcb: .dc.b 0 * FCB for DDT1.68K .dc.b 'SID68K 68 */ /* Define BDOS Function Codes */ /* il to new bp move.l #bplen-bpfcb2,d0 bsr copy rts * exit to ddt1 * * BDOS Function Code Equates * prstrng = 9 op--------------------------------------------------------*/ struct _cmd_tbl { BYTE *ident; /* command identifer field */ U lpbcf = 20 * * * Copy Bytes from (a0)+ to (a1)+ for d0 * copy: subi.l #1,d0 bmi copyxit copylp: move.b (a0)+,(a1)+ de WRITSEQ 21 #define MAKEFILE 22 #define RENAME 23 #define GTLOGIN 24 #define CURDSK 25 #define SETDMA 26 #define K' File name and type. .dc.b 0 * extent .dc.b 0,0 * s1, s2 .dc.b 0 * rc .ds.b 16 * d0 ... dn .dc.b 0 * cr */ /****************************************************************/ #define SYSRESET 0 #define CONIN 1 #enf = 15 closef = 16 readseq = 20 setdma = 26 bioscall= 50 pgmldf = 59 * * * Local Variables etc. * mystack: .ds.l $20WORD cmd_code; /* command code field */ } cmd_tbl[8] = /* declare CP/M built-in table */ { "DIR",DIRCMD, "DIRS"bf d0,copylp copyxit: rts * * * Can't Load DDT1.68K, Print Error Message * loadfail: move.w #prstrng,d0 move.w #loaderr,WRTPROT 28 #define GETROV 29 #define SETATTR 30 #define GETDPB 31 #define USERCD 32 #define READRND 33 #define WRITRND .ds.b 0,0,0 * random record number * .even * fcbcr = 32 * dskbuf: .ds.w 64 * used to hold pgm header magic = 0 *define CONOUT 2 #define READIN 3 #define PUNOUT 4 #define LISTOUT 5 #define DCONIO 6 #define GETIOB 7 #define SETIOB * local stack * fudge = $10 * bplen = $100 localbp: .ds.l bplen * local copy of base page bplotpa = 0 bphitpa = 4 b,DIRSCMD, "TYPE",TYPECMD, "REN",RENCMD, "ERA",ERACMD, "USER",UCMD, "SUBMIT",SUBCMD, NULL,-1 }; 34 #define FILESIZ 35 #define SETRND 36 #define RESTDRV 37 #define WRANDZF 40 #define GETFREE 46 #define DBIOSCL 50 #def*/ /************************************************/ simz(fcbp,hwer) struct fcb *fcbp; long hwer; { extern struct lmhens specific to DDT68K */ /* Author: Timothy M. Benson */ /* Control: 19 MAY 83 17:36 (TMB) */ /* */ /*******us header */ if(relocate = !*((unsigned *)((long)caput+0x1A))) stout("File is relocatable\n"); If NOT(caput AT symlen) th; /* used by fill_fcb(? or blanks)*/ BYTE subprompt; /* submit file was prompted for */ extern BYTE morecmds; /* command al -- whether or not file is relocatable */ randy = 0; BDOS(SETDMA,caput); rano(fcbp,&randy); irate = BDOS(OPEN,fcbp) ine PGMLOAD 59 dr *caput; extern int nomo; U32 rano(); /* Returns second argument incremented by one */ struct asymbl *icon; int goods;*************************************************/ #include "lgcdef.h" #include "cputype.h" #include "siddef.h" #include "en BEGIN stout("No symbols\n"); /**temp** Need to allot space for added symbols */ /**temp** Need to deallocate extra spaceafter warmboot flag */ UWORD sub_index; /* index for subdma buffer */ UWORD index; /* index into cmd argument array*/ UWAND 0xFFFFFFFCL; irate ORWITH (int) BDOS(READRND,fcbp); caput AT tceps = hwer; If caput AT lmkind EQ CONTIG then BEGIN ne PGMLOAD 59  /* # symbol bytes in first symbol record */ int i; int irate; /* Zero iff no input errors */ int junk; /* # bytes precediddtinc.h" #include "stdio.h" #include "bdosfunc.h" #include "disas.h" /************************************************/ */ nomo = -1; return(-1); END randy INCBY caput AT lmtlen + caput AT lmdlen; /* I.e., compute # bytes preceding syORD sub_user; /* submit file user number */ UWORD user; /* current default user number */ UWORD cur_disk; /* currecaput AT dceps = caput AT tceps; caput AT dceps INCBY caput AT lmtlen; caput AT bceps = caput AT dceps; caput AT bceps YTE load_try; /* flag to mark a load try */ BYTE first_sub; /* flag to save current cmd ptr */ BYTE chain_sub; /* submitng symbols in first symbol record */ register long kount; /* Scratch loop counter */ char *oint; /* Scratch byte pointer */ /* Load and initialize symbol table, returning */ /* int sized index to last valid symbol aut */ /* negative error code. mbols */ junk = randy % 128; goods = 128 - junk; randy /= 128; oint = caput AT sump; icon = oint; /* Save addr of symb/********************************************************/ /* */ /* Usual filename: SIDFUN.C */ /* Remarks: FunctioINCBY caput AT lmdlen; randy = 28; /* # bytes in contiguous header */ END otherwise randy = 36; /* # bytes in noncontiguo chaining flag */ extern BYTE submit; /* submit file flag */ BYTE end_of_file; /* submit end of file flag */ BYTE dirflag U32 randy; /* Current random record number */ int zulu; /* Index to last symbol in current table */ int relocate; /* Logicol table. */ BDOS(SETDMA,icon); randy = rano(fcbp,&randy); irate ORWITH (int) BDOS(READRND,fcbp); /* Move wanted info to***************************/ U32 rano(fcbp,rand) struct fcb *fcbp; union slimy BLOCK U32 recno; char tail[4]; UNBLOCK point in program */ If caput AT lmkind EQ CONTIG then for(i = 0; i LE zulu; i++) If (icon+i) AT symtyp IS SEGREF ahen reply = pause(); END putchar('\n'); } kobold() { /* Will handle printing long symbols here; for now print message of symbol table here */ /**temp** and/or deallocate unused storage */ while (kount-- GT 0) BEGIN BDOS(SETDMA,oint); r If simbl IS BREL then putchar('B'); else putchar('A'); stout(")("); If simbl IS GONE then putchar('H'); head of array. */ for (i = 0; i LT goods; i++) *oint++ = *(oint + junk); /* Now oint points to icon + goods. */ zulu = HM*rand; { int i; for (i = 0; i LE 2; i++) fcbp AT r[i] = rand AT tail[i+1]; return(rand AT recno + 1); } deluge(tnd relocate then (icon+i) AT symval INCBY caput AT tceps; /**temp** May later need different test for full symbol table */ stout("** Long COBOL-style symbol **"); } pause() { register char mor; stout("\n Continue listing? (y/n)"); andy = rano(fcbp,&randy); If (i = BDOS(READRND,fcbp)) then If i EQ 1 or i EQ 4 then kount = 0; else irate ORWIT otherwise putchar('V'); stout("): "); puthexl(tabula[i].symval); stout(" = "); /**temp** Call to kobold inSYMS * sizeof(struct asymbl); If caput AT symlen GT zulu then BEGIN kount = (zulu - goods) / 128; If (zulu - goods) % 12abula,zulu) struct asymbl tabula[]; register int zulu; { register int i; register int j; register char litt; register*/ If zulu GE HMSYMS - 1 then stout("Symbol table full\n"); return(zulu); } /***************************************** mor = getchar(); mor = toupper(mor); putchar('\n'); return(mor NE 'N'); } /******************************************H i; oint INCBY 128; END If irate then BEGIN stout("Symbol table disaster\n"); return(-1); END /**temp** Whe next line may need parameters */ If simbl IS TLONG then kobold(); otherwise for(j = 0; j LT 8; j++) If litt = ta8 then ++kount; zulu = HMSYMS - 1; END otherwise BEGIN kount = (caput AT symlen - goods) / 128; If (caput AT symlen int reply; U16 simbl; for(i = 0, reply = 2; i LE zulu and reply; i++) BEGIN putchar('\n'); puthexw(i); *******/ /* Install random record number in fcb and */ /* return next higher random record number */ /*******************************************/ /* For a given numerical value, find and print corresponding */ /* symbols in indicated table, with cen symbol table allocated dynamically, make */ /**temp** sure zulu still reflects subscript of */ /**temp** last symbol at thisbula[i].namae[j] then putchar(litt); else putchar(' '); If reply EQ 2 then reply = 1; otherwise If NOT (i % 10) t - goods) % 128 then ++kount; zulu = caput AT symlen / sizeof(struct asymbl) - 1; END /**temp** May want to compute end putchar('('); If (simbl = tabula[i].symtyp) IS TREL then putchar('T'); else If simbl IS DREL then putchar('D'); elsertain options. Return */ /* int number of symbols found. */ /************************************************************s */ } /************************************************/ /* For given string of given length find first */ /* correspontine to handle long symbols */ If simbol IS TLONG then roam(); If orient EQ 'H' then putchar('.'); for(j = 0; If NOT (symbol IS SEGREF) then IGNORE; break; case 'A': /* Nonaddress numerical value wanted */ If symbol IS Ster U16 simbol; /* Hold symtyp here for inspection. */ hmany = 0; /* Alcyon compiler does not allow this */ /* to be ini *value; /* Place to stick value if and when found */ int *whence; /* Place to stick subscript to symbol table */ { extern i****/ spell(value,table,scope,class,orient) U32 value; struct asymbl table[]; int scope; /* If zero, then find all; otherwding symbol table entry, updating */ /* value and putting subscript at *whence. */ /* Return int 1 if found, 0 if not found,j LT 8 and (it = table[i].namae[j]); j++) putchar(it); If orient NE 'H' then putchar(':'); If orient EQ 'H' or orEGREF then IGNORE; break; case 'B': break; /* Accept any kind of symbol */ default: return(-1); /* This stialized in declaration: */ /* I protest! */ for(i = 0; i LE omega; i++) BEGIN If table[i].symval NE value then IGnt omega; register int i; /* To sweep symbol table */ register int j; /* To sweep string */ register short match; /* 1 iffise find first. */ char class; /* 'm' implies only want segment references. */ char orient; /* 'h' or 'H' horizontal, anything */ /* -1 if the bizarre happens, and -2 if an */ /* attempt is made to utilize a feature not */ /* yet implemented. */ient EQ 'h' then putchar(' '); otherwise putchar('\n'); hmany++; If scope then break; END If hmany and orihouldn't happen */ UNBLOCK If symbol IS GONE then IGNORE; /**temp** Call in next statement will require parameters. */ /**NORE; simbol = table[i].symtyp; If class EQ 'm' and NOT (simbol IS SEGREF) then IGNORE; /* I.e. ignore e.g strings equivalent */ register char nxch; /* Next char in logos */ U16 symbol; /* Type of last symbol considered */ else vertical: */ /* If 'H' then prefix '.'; if 'h' then append ':'.*/ { extern int omega; int hmany; /* Counter for # /************************************************/ indica(leqth,logos,tesoro,phylum,value,whence) int leqth; char logos[]ent EQ 'h' then putchar('\n'); return(hmany); } roam() { /* dummy routine: will later handle symbols longer than 8 chartemp** For now just returns (int) -2. */ If symbol IS TLONG then return(trek()); for(j = 0, match = 1; j LT 8 and match; j. stack references */ If simbol IS GONE then IGNORE; /* I.e. ignore hidden symbol */ /* Next line is dummy call to rou for(i = 0; i LE omega; i++) BEGIN symbol = tesoro[i].symtyp; switch(phylum) BLOCK case 'M': /* Address value wanted */ of symbols with given value */ register int i; char it; /* Hold char while deciding what to do. */ register int j; regis; /* String containing name */ struct asymbl tesoro[]; /* Short symbol table */ char phylum; /* Type of symbol wanted */ U32++) BLOCK If j LT leqth then nxch = logos[j]; otherwise nxch = '\0'; If nxch NE toupper(tesoro[i].namae[j]) then for(seqno = 0; seqno LT 8; seqno++) begin (galaxy+omega) AT namae[seqno] = uppr; If *++cx NE ',' and uppr then uppNBLOCK return; END deblank(&cx); task = *++cx; switch(task) BEGIN case 'A': /* Add a symbol; e.g. KAname,value number */ /* equal to given value, if in range */ If nomore(cx) then for(seqno = 0; seqno LE omega; seqno++) t seqno; /* Subscript to symbol table */ long spot; /* Symbol value input */ char task; char uppr; /* For entering new nambol most recently sought by name*/ /* KHvalue hide first symbol with given value */ /* KH*value hide symbol with sequence numatch = 0; UNBLOCK If match then BLOCK *whence = i; *value = tesoro[i].symval; return(1); UNBLOCK Er = *cx; else uppr = '\0'; end cx--; If NOT (getsep(&cx) and gethex(&cx,&spot)) then begin omega--; e,type */ /* where name is converted to upper case and */ /* comma after it is obligatory, as is value. */ If nomo (galaxy+seqno) AT symtyp ANDWITH ~GONE; otherwise BLOCK seqno = findsn(cx,omega,galaxy); If seqno LT 0 then begin e */ galaxy = caput AT sump; If nomore(cx) then BEGIN stout("DDT begins at: "); puthexl(main); putchar(mber equal */ /* to given value, if in range */ seqno = findsn(cx,omega,galaxy); If seqno LT 0 then begin bad();ND return(0); } trek() { /* dummy routine: will later handle symbols longer than 8 chars */ return(-2); } / bad(); return; end (galaxy+omega) AT symval = spot; If getsep(&cx) and gethex(&cx,&spot) then seqno = (re(cx) then BLOCK bad(); return; UNBLOCK otherwise BLOCK If omega GE HMSYMS then begin stout("\nSymbol table fulbad(); return; end else (galaxy+seqno) AT symtyp ANDWITH ~GONE; UNBLOCK break; default: bad(); retu'\n'); stout("Symbol table at: "); puthexl(galaxy); putchar('\n'); If omega LT 0 then BLOCK stout("N return; end otherwise (galaxy+seqno) AT symtyp ORWITH GONE; break; case 'R': /* Recover hidden symbols */ /* KR****************************************/ /* K command: Play with symbol table */ /****************************************/int)spot; else seqno = 0xA700; /* Default symbol type */ If NOT nomore(cx) then begin omega--; bad(); l\n"); return; end deblank(&cx); uppr = *++cx; If uppr EQ ',' then begin bad(); return; end ++omega; rn; break; END putchar('\n'); } /************************************************/ /* Find serial number of symboo symbols"); If caput then begin stout("; file header at: "); puthexl(caput); end putchar('\n'); U recover all hidden symbols */ /* KRvalue recover first symbol with given value */ /* KR*value recover symbol with sequenc koax(cx) char *cx; { extern struct lmhedr *caput; extern int omega; extern int main(); struct asymbl *galaxy; in return; end (galaxy+omega) AT symtyp = seqno; UNBLOCK break; case 'H': /* Hide symbols */ /* KH hide syml entry, parsing */ /* rest of command line */ /************************************************/ findsn(spear,zedd,arcadlared "char" pointer.*/ If nupt & 1 then BLOCK stout("\nNo change--Address must be even!\n"); return; UNBLOCK struct lmhedr *caput; int jp; int reply; /* Operator's response */ int plain; /* plain iff no tail */ char *nupt; /* Vaand plocus[jp] EQ nupt then begin If pkawnt[jp] EQ cntdn then stout("\nAlready set\n"); otherwise pkawnt[jp] = cn If gethex(&spear,&werth) and nomore(spear) then script = (int) werth; end else If gethex(&spear,&werth) a) begin If pkawnt[jp] then { If ++minus GT 16 and jp LT HMPPTS then BEGIN reply = pause(); minus = 0;e) char *spear; /* Scanner for command line */ int zedd; /* Highest symbol table subscript */ struct asymbl *arcade; /* Addr If getsep(&pcx) then If NOT gethex(&pcx,&cntdn) or minus then goto chide; If NOT nomore(pcx) then goto chide; lue of new pass point */ /* N.b.: "char" required so bitwise "&" */ /* will work properly. */ long cntdn; /* Newtdn; return; end minus = 1; for (jp = 0; jp LT HMPPTS; jp++) If NOT pkawnt[jp] then begin pkawntnd nomore(spear) then for(ix = 0; ix LE zedd and script LT 0; ix++) If (arcade+ix) AT symval EQ werth then script = ix; END If reply then BEGIN putchar('\n'); puthexw(pkawnt[jp]); stout(" "); puthexl(plocus of symbol table */ { extern int nomo; /* Last entry sought by name */ int ix; /* To sweep symbol table */ int script; /END If NOT cntdn then goto chide; If minus then BEGIN If plain then zappas(); else BLOCK for (jp = 0; jp LT H pass count (initially long) */ cntdn = 1; /* Set to default pass count */ If NOT (plain = nomore(pcx)) then BEGIN I[jp] = (U16) cntdn; plocus[jp] = nupt; jp = HMPPTS; minus = 0; end If minus then begin UNBLOCK If script GT zedd then script = -1; return(script); } passpt(pcx) char *pcx; { extern U16 pkawnt[HMPPTS];[jp]); stout(" "); If omega GE 0 then spell((U32) plocus[jp],caput AT sump ,scope,'m','H'); * Int subscript to be returned */ long werth; /* Numerical value of symbol */ script = -1; /* Preset to illegal value */ MPPTS; jp++) If pkawnt[jp] and plocus[jp] EQ nupt then begin pkawnt[jp] = 0; minus = 0; end If minus f NOT gethex(&pcx,&nupt) then goto chide; /* Warning: The following bitwise "&" statement */ /* requires nupt to be dec stout("\nToo many pass points--limit is: "); SAYMAX end UNBLOCK END return; chide: bad(); } qotbyt extern U16 *plocus[HMPPTS]; extern U16 ancien[HMPPTS]; extern int minus; extern int omega; extern int scope; extern END } end putchar('\n'); UNBLOCK else BLOCK for (jp = 0; jp LT HMPPTS; jp++) If pkawnt[jp] If nomore(spear) then script = nomo; otherwise BLOCK deblank(&spear); If *(spear+1) EQ '*' then begin ++spear;then goto chide; UNBLOCK END otherwise BEGIN If plain then BLOCK for(jp=0,reply=1;jp LT HMPPTS and reply;jp++(nnnn) long nnnn; { If nnnn LT 0x20 or nnnn GT 0x7E then return(0); putchar('\''); BDOS(CONOUT,nnnn); putchar('\''); define ABSS 03400 char tsym[10]; char fsymbol[10]; int seffadr, sefaflg; /* effective address search variables */ }; char *symbuf; /*start of symbol table*/ char *esymbuf; /*end of symbol table*/ int *symptr; int errflg; /* th/********************************************************/ /* */ /* Usual filename: SID68K.C */ /* Remarks: Main C i+1] && parm[2][0] == NULL)) bad_cmd = TRUE; } else if(!(parm[2][0] == '=' && parm[2][1] == NU /* DATA based relocatable */ # define SYTX 0001000 /* TEXT based relocatable */ # define SYBS 0000400 /* return(1); } vecina(cxp,sought) char **cxp; char sought; { /* Check if next char in command is a specified char, advanc int ssval[NUMSS]; /* special symbol values */ int instr; /* holds instruction first word */ #de following definitions must not be changed -- esp. the order */ int symlen; int symct; char ssymbol[8]; int module for SID68K */ /* Author: Timothy M. Benson */ /* Control: 19 MAY 83 18:01 (TMB) */ /* */ /*************/* Copyright 1981 Alcyon Corporation 8474 Commerce Av. San Diego, Ca. 92121 */ #define NU BSS based relocatable */ struct { /* NOT PORTABLE !!!!!! */ char hibyte; char lobyte; }; ing */ /* pointer if it is. */ ++*cxp; If **cxp EQ sought then return(1); --*cxp; return(0); } zappas() { exefine BYTESZ 0 #define WORDSZ 1 #define LONGSZ 2 /* flags for symbols */ # define SYDF 0100000 /* defined */ #ssymflg; char *ssymval; /* end of order dependant declarations */ char *dot; char *tdot; int dotinc; char *sdot; *******************************************/ #include "lgcdef.h" #include "cputype.h" #include "siddef.h" #include "ddtiMSS 1 /*number of special symbols*/ #define SSRG 0 /*max symbol offset to display symbolically*/ #define LSTENT 12 #define AREG0 8 #define PC 16 char lbuf[40]; tern U16 pkawnt[HMPPTS]; int jz; for (jz = 0; jz LT HMPPTS; jz++) pkawnt[jz] = 0; }  define SYEQ 0040000 /* equated */ # define SYGL 0020000 /* global - entry or external */ # define SYER /* symbolic operand temporary dot */ int textsym; #define TEXTS 01000 #define DATAS 02000 #define BSSS 0400 #nc.h" #include "stdio.h" #include "bdosfunc.h" #include "disas.h" typedef long (*PFL)(); struct lmhedr *caput = NULL; / struct symtab { char syname[8]; char *syval; }; struct { int hiword; int loword;  #define AREG0 8 #define PC 16 char lbuf[40]; ern U16 pkawnt[HMPPTS]; int jz; for (jz = 0; jz LT HMPPTS; jz++) pkawnt[jz] = 0; } 0010000 /* equated register */ # define SYXR 0004000 /* external reference */ # define SYDA 0002000 * Symbol table--known globally */ long HMSYMS; long inhalt; /* Possible symbol value discovered during dissasembly */ int nr, &bpptr); while ( 1 ) { while ( ! (cx = readcom(combuf)) ); If *cx EQ '-' then BEGIN minus = 1; ++cxe initialization */ for (i=0; i<8; i++) {state.dreg[i]=0L; state.areg[i]=0L;} state.pc = 0x0; state.u case 'P' : passpt(cx); break; case 'R' : readfl(cx, bpptr, &curvals, &dispaddr); plocus[HMPPTS]; /* Values of pass points */ U16 ancien[HMPPTS]; /* Previous contents at pass point */ struct cpustate state; case 'G' : gocmd(cx,&state,&listaddr); break; case 'H' : omo = -1; /* Index to last symbol found by name */ int omega = -1; /* Index to last symbol in symbol table:*/ /* Negative v; END otherwise minus = 0; switch ( *cx ) { /* one case for each possible command */ csp = 0x00001000L; state.areg[7]=state.usp; state.ssp = GETSSP(); state.status = 0x0000; #ifdef MC68010 st break; case 'S' : setmem(cx); break; /* state of user program regs */ main(bpptr) struct basepage *bpptr; { char combuf[BUFLEN]; char *cx hexmath(cx); break; case 'I' : incomtl(cx, &curvals); alue => no symbols */ char ref; /* Symbols for disassembly: */ /* '\0' => none */ /* 'm' => text, data, or bss */ /**ase 'C': callrt(cx); break; case 'D' : display(cx, &dispaddr); ate.vbr = GETVBR(); state.sfc = GETSFC(); state.dfc = GETDFC(); #endif dispaddr = 0; listaddr = 0; curvals.ki case 'T' : trace(cx, &state, &listaddr, (int)1); break; case 'U' ; char *dispaddr; /* current display address */ char *listaddr; /* current disassembly addr*/ struct value curvals; break; case 'K' : koax(cx); break; case 'L' : disasm(cx, &listaddr); temp** Setting of 'a' not currently in use */ /* 'a' => other */ int scope = 0; /* If zero, find all; otherwise find first break; case 'E' : ecmd(cx, bpptr, &state, &curvals, &dispaddr, &listaddr, &bpptr); nd = 0; /* no current file or program */ zappas(); /* Purge pass points */ init(bpptr, &state, &curvals, &dispaddr, &listadd: trace(cx, &state, &listaddr, (int)0); break; case 'V' : vcmd(cx /* values relating to current file or pgm */ register int i; /* workhorse integer */ /* phony machine stat break; case 'M' : movemem(cx); break; */ int minus; /* 1 => "-" in effect; 0 => "-" not in effect */ U16 pkawnt[HMPPTS]; /* Pass counts (0 => not in use) */ U16 * break; case 'F' : fillmem(cx); break; , &curvals); break; case 'W' : wrtfile(cx, &curvals); -"); /* prompt */ *buf = BUFLEN-3; BDOS(READBUF, buf); /* get command line */ stout("**************************************************\n\n"); caput = (long)basep - (long)(XTRASYM*sizeof(struct lmhed); stout("Return value --> "); hexlzs(ret); stout("h\n"); for (i = 0; i < 8; i++) { state.areg[i] = ppa; { /* if program file argument, then load it */ /* set up trap vectors */ ( ! gethex(&s,&n) ) { bad(); return(0); } for (i = 0; i < 10; i ++) p[i] = i; i = 0; while ( (i < break; case 'X' : examine(cx, &state); break; putchar('\n'); } while ( ( nc=buf[1]) == 0 ); buf[2+nc] = 0; forr)); if ((long)caput < basep->lowtpa) caput = NULL; HMSYMS = 0; if (basep->fcb1.fn[0] != ' ') loadpgm(&(basep->fcb1tstate.areg[i]; state.dreg[i] = tstate.dreg[i]; } state.pc = tstate.pc; state.usp = tstate.usp; state.ssp /* initialize tables */ EXINIT(); /* Initialize Exception handlers */ stout("\n10) && ( (getsep(&s)) && (gethex(&s,&p[i])) ) ) { i++; } for (i = 0; i < 8; i++) { tstate.areg[i] = state.areg[i default : stout("Unknown Command\n\n"); break; }; /* end of s ( cx = &buf[2]; *cx; *cx=toupper(*cx), cx++); for ( cx = &buf[2], i=0 ; iswhite(*cx) && (imeml); ; s <= f ; s += 16 ) { /* one line per pass */ if ( keyhit() ) return; puthexl(s); putchte *statep; struct value *valuep; char **dap; char **lap; long *bppa; { /* load a program for execution */ extern i default */ else { bad(); return(0); } /* junk on the line */ } if ( (format != 1) && ( statep, valuep, dap, lap, bppa) char *cx; struct basepage *basep; struct cpustate *statep; struct value *valuep; char char *j; /* ditto */ short int c; /* column number */ /* p break; } /* end of switch */ putchar(' '); ar(' '); putchar(' '); c = 10; for ( i=s, j=min(s+15,f); i <= j; nt omega; struct lpb pgmlpb; int loaderr; struct basepage *newbp; long *stkptr; int i; char sector[128]; longs & 1) ) s += 1; /* force even */ if ( GETSEP ) {if ( ! gethex(&cx, &f) ) {bad(); return;} } else f = s +**dap; char **lap; long *bppa; { /* Load the program named in the command */ struct fcb pgmfcb; deblank(&cx); arse command and extract parameters */ format = getform(&cx); if (*++cx == '@') { if ((*++cx >= '0') && (*cx <= ' c += (2*format+1); } /* end of loop across line */ while ( c++ i += format ) { switch ( format ) { case 1 : puthexb(i->memb) stlen; /* open program file */ while(1) { if ( (BDOS(OPEN, fcbp) & 0xffL) == 0x0FFL ) { if(fcbp->t[0] != ' (11*16-1); /* not there, use def */ if ( ! nomore(cx) ) {bad(); return;} /* rest of line must be empty */ } if (parse(&cx, &pgmfcb, "68K") && nomore(cx)) loadpgm ( &pgmfcb, basep, statep, valuep, dap, lap, bppa); else bad(); 7')) { s = state.areg[*cx - '0']; f = s + ((11*16) - 1); } else { bad(); return(0); } } else { < 60 ) putchar(' '); for ( i=s, j=min(s+15,f); i<=j ; i++ ) putbyte(*i); putchar('\n');; break; case 2 : puthexw(i->memw); ') { /* open failed */ stout("Cannot open program file\n"); return; } else { fcbp->t[0] = '6'; /* now do the display */ f = f - format + 1; /* first byte of last chunk to print */ for ( } loadpgm(fcbp, basep, statep, valuep, dap, lap, bppa) struct fcb *fcbp; struct basepage *basep; struct cpusta cx--; if ( ! gethex(&cx, &s) ) { /* get start address */ if ( nomore(cx) ) s = *dap; /* or use } /* end of loop through lines */ *dap = f + format; } /* end display */ ecmd(cx, basep, fcbp->t[1] = '8'; fcbp->t[2] = 'K'; } } else break; } /* Set up space for symbol table in top of newbp->fcb1.ex = 0; newbp->fcb2.ex = 0; } break; /* end case 0 -- success */ case 1: { stout("Insufficienbpa = newbp; valuep->initstk = pgmlpb.stkinit; statep->pc = newbp->csstart; stkptr = pgmlpb.stkinit; (*--sn(0);} /* not there, error */ if ( (format != 1) && (s & 1) ) /* must be even address, error */ pb.tpatop = basep; */ pgmlpb.tpatop = caput; pgmlpb.flags = 0; /* now do program load */ loaderr = (int)(BDOS(PG /* end loadpgm */ fillmem(cx) char *cx; { /* fill memory with constant */ register short int format; TPA */ fcbp->cr = 0; BDOS(SETDMA, sector); if ( BDOS(READSEQ, fcbp) & 0xffL ) { stout("Can not read program file.\t memory or bad file header\n"); return; } break; case 2: { stout("Read error\n"); return; } brtkptr) = newbp; (*--stkptr) = *--bppa; statep->usp = stkptr; statep->areg[7]= stkptr; statep->status = 0; {bad(); return(0);} if ( GETSEP && gethex(&cx, &f) ); /* get end address */ else { bad(); return(0); MLOAD, &pgmlpb) & 0x0FFFFL); switch ( loaderr ) { case 0: { /* successful */ newbp = pgmlpb.bpaddr; valuep->k /* 1=byte, 2=word, 4=long word */ char *s; /* start address */ char *f; /* end n"); return; } fcbp->cr = 0; stlen = (§or[14])->meml; HMSYMS = stlen / sizasym + (long)XTRASYM + 1L; if(stleneak; case 3: { stout("Bad relocation bits\n"); return; } break; default: { stout("Unknown program load e *dap = newbp->csstart; *lap = newbp->csstart; newbp->fcb1.dr = 0; newbp->fcb2.dr = 0; for ( i = 0; i < 11} /* not there, error */ if ( GETSEP && gethex(&cx, &v) ); /* get value to stuff */ else { bind = 1; valuep->textbase = newbp->csstart; valuep->textlen = newbp->cslen; valuep->database = newbp->dsstart; address */ long v; /* value to stuff into memory */ /* parse command and extract paramete) caput = (long)caput - (long)(stlen-128L-sizlmhdr); if((long)caput < basep->lowtpa) {caput = NULL; HMSYMS = 0;} /* set uprror\n"); return; } break; } /* end switch */ zappas(); /* Delete all pass points */ if(stlen) omega; ++i) { newbp->fcb1.fn[i] = ' '; newbp->fcb2.fn[i] = ' '; } newbp->fcb1.cr = 0; newbp->fcb2.cr = 0; ad(); return(0); } if ( ! nomore(cx) ) {bad(); return;} /* rest of line must be empty */ if ((s>f) || valuep->datalen = newbp->dslen; valuep->bssbase = newbp->bsstart; valuep->bsslen = newbp->bslen; valuep->rs */ format = getform(&cx); if ( gethex(&cx, &s) ); /* get start address */ else {bad(); retur lpb */ pgmlpb.fcbaddr = fcbp; pgmlpb.tpabase = basep->lowtpa; /* if ( stlen ) pgmlpb.tpatop = caput; else pgml = simz(fcbp,valuep AT textbase); /*load symbol table*/ else {omega = -1; stout("No Symbols\n");} showvals(valuep); } /* test for junk or nonsense */ ( (format == 1) && ((v > 255L) || (v < 0)) ) || ( (format == 2) &on at ext. 6092. 1. Much like DDT-68K (see CP/M-68K Programmer's Guide) with the following enhancements: a. Symbols b.egments, but any symbol is recognized when you are typing in SID commands. 4. The P-command works just as in SID-86 (see ma break; case 4 : s->meml = (long)v ; if ( s->meml != v ) badramat symbol table, type K (the K-command "edit symbol table", which otherwise doesn't work yet). You may use a symbol referen& ((v > 65535L) || (v < 0)) ) ) { bad(); return(0); } /* now do the stuffing */ for ( ; (s+ W-option on T- and U-commands c. Pass points (P-command) These operate much as in SID-86 and CP/M SID (see manuals). 2.nual). 5. The G-, T-, and U-commands work much as in SID-86 (see manual). However, a TRAP instruction will not be traced th(s); break; } /* end of switch */ } /* end of for */ } /* end of fillmem */ ce wherever a Hex specification could be used. For example, if _main is a symbol, then H._main prints value of symbol H=_format) <= (f+1); s += format ) { switch ( format ) { case 1 : s->memb = (char)v; For now, to run SID-68K you need SID.68K and SID68K.68K, the latter on default drive. Just say SID [file-spec]. 3. Symboru, even if the W-option is not specified. Note that the "-" prefix works with these commands (see manual). For now, a hyphes); break; } /* end of switch */ } /* end of for */ } /* end of fillmem */ main prints byte at addr given by value of symbol H@_main prints word at addr given by value of symbol H!_main prints lon if ((s->memb ^ (char)v) & 0xFF) badram(s); break; ls are loaded automatically if present in a load module that is loaded at start-up or with the E-command. For now, symbol tabl SID-68K 20 MAY 1983 (For internal DRI use) Please refer bugs, complaints, questions, and suggestions to Tim Bensn preceding any other SID command is ignored. 6. Pass points behave much as in SID-86. The following exceptions are notewg at addr given by value of symbol. The disassembler only prints such symbols as refer to addrs in the text, data, and bss scase 2 : s->memw = (short int)v ; if ((s->memw ^ (short int)v) & 0xFFFF) badram(s); e is an array of fixed size with room for up to 2000 symbol entries. For a listing of symbols, type H. If you need to look orthy: a. When a pass-point is encountered, you get a message, and both "before" and "after" state displays. b. If y large, attempting to load it can wipe out SID altogether. 3 JUN 83 17:21 (TMB) to be the register mask--it should take the SECOND word, which may or may not be last.) 2. In D- and L-commands, if you givn */ #define BUFLEN 85 /* command buffer length */ #define GETSEP getsep(&cx) struct bytestr { char memb; }; same as a pass point is treated as a pass point; in effect, it is ignored. MAJOR KNOWN BUGS Please report any b /********************************************************/ /* */ /* our program contains the ILLEGAL instruction, and if SID encounters it under Go, Trace, and Untrace, you get an erro #define SMALL_WIDTH 40 /*-------------------------------------------*\ | BDOS Function Calls | e addr via a symbol reference and symbol does not exist, then you should get "?", but you don't. 3. G-command, inter al., i struct wordstr { int memw; }; struct longstr { long meml; }; /************************************************************ugs OTHER THAN the following: 1. Some machine instructions are disassembled incorrectly. Examples: IN HEX GIVEN AS Stuff to INCLUDE in DDT-68K */ /* */ /**************r message, and the command is aborted. c. SID will not "see" any pass points between the time an attempt is made to Tra\*-------------------------------------------*/ #define WARMBOOT 0 #define CONIN 1 #define CONSOLE_OUTPUT 2 #define Rs not protected in any way against odd-numbered addresses in the command line. 4. If the bss segment in a load module is to****/ /* */ /* Define the CPU Status Structure and Related T SHOULD BE 4AFC xxxx tas #xxxx illegal ... 000A 3202 ori.b #$3202,A2 *unknown instruction* 4CF9 0018 0000 06C0 ******************************************/ #define MAXBP 10 /* max breakpoints allowed */ #define ILLEGAL 0x4AFC /* ce or Untrace thru a TRAP and the time when control returns to the instruction following the TRAP (if it ever does).EADER_INPUT 3 #define PUNCH_OUTPUT 4 #define LIST_OUTPUT 5 #define DIR_CONS_I/O 6 #define GET_I/O_BYTE 7 #define SET_Io large, attempting to load it can wipe out SID altogether. 3 JUN 83 17:21 (TMB) ables */ /* */ /******************************************** movem.L $180000,D3-D3/D6-D7/A1-A2 movem.L $6C0,D3-D4 (In the MOVEM instruction, the disassembler takes the LAST word ILLEGAL instruction */ #define BDOSCALL 0x4E42 /* TRAP #2 instruction */ #define BIOSCALL 0x4E43 /* TRAP #3 instructio d. DO NOT set a pass point in the middle of an instruction-- result is undefined. e. A break point that is set the /O_BYTE 8 #define PRINT_STRING 9 #define READ_CONS_BUF 10 #define GET_CONS_STAT 11 #define RET_VERSION_NO 12 #define R********************/ struct cpustate { long pc; long usp; long ssp; ; char comtail[0x80]; }; /************************************************************************/ /* */ *********************************************************/ struct basepage { long lowtpa; /* low address of tpa */ lon char *readcom(); char hexchar(); short int getform(); long int GETSSP(); #ifdef MC68010 long int GE****************************************************/ struct fcb { char dr; /* drive code */ char fn[8]; /* file name ******************/ /* */ /* Define the Load Program Parameter Block */ /* */ /*************************** int status; long dreg[8]; long areg[8]; #ifdef MC68010 long vbr; l /* Define a structure for holding information about the most */ /* recently loaded program or file */ /* */ /***g hightpa; /* high address of tpa */ long csstart; /* start of code seg */ long cslen; /* length of code seg */ long dTVBR(); long int GETSFC(); long int GETDFC(); #endif /**/ / char t[3]; /* file type */ char ex; /* extent */ char s1; /* used by sys */ char s2; /* used by sys */ char rc;*********************************************/ struct lpb { struct fcb *fcbaddr; long tpabase; long tpatop; long ong sfc; long dfc; #endif }; #define TRACE 0x8000 #define SUPER 0x2000 #define INTMSK 0x0700 #define E*********************************************************************/ struct value { int kind; /* 0 => none, 1 => pgm, 2sstart; /* start of data seg */ long dslen; /* length of data seg */ long bsstart; /* start of bss seg */ long bslenVBR(); long int GETSFC(); long int GETDFC(); #endif /**/  /* rec count */ char d[16]; /* used by sys */ char cr; /* curr rec no */ char r[3]; /* rand rec no */ }; /****** *bpaddr; long stkinit; int flags; }; /****************************************************************/ /* XTEND 0x0010 #define NEG 0x0008 #define ZERO 0x0004 #define OFLOW 0x0002 #define CARRY 0x0001 /************ => file */ long textbase; /* if kind==2 then use textseg for file */ long textlen; long database; long datalen; ; /* length of bss seg */ long freelen; /* free mem after bss */ long reserved[5]; struct fcb fcb2; struct fcb fcb1user: .ds.w 1 .even _submit: .ds.b 1 .even _morecmds: .ds.b 1 .even _patch .ds.l 25 .end **********************************************************/ /* */ /* Base Page Structure */ /* */ /******* */ /* Some Forward Function Definitions */ /* */ /****************************************************************/****************************************************/ /* */ /* Define FCB Structure */ /* */ /************long bssbase; long bsslen; long bpa; long initstk; }; /*******************************************************user: .ds.w 1 .even _submit: .ds.b 1 .even _morecmds: .ds.b 1 .even _patch .ds.l 25 .end  drive for DDT68000.68K move.b $24(a0),sidfcb * and stuff into FCB move.w #openf,d0 * open file DDT68000.68K move.l #sid************************************* * .text * start: move.l (a7)+,ccprtn * save stacked info move.l (a7)+,bpaddr * en+fudge,d0 * cmpi.w #goodmgc,magic(a0) * must be $601A bne loadfail * tst.w rlbflg(a0) * must be 0 bne loadfail * penok: move.w #setdma,d0 * set up to read pgm header move.l #dskbuf,d1 * dma address trap #2 * call the bdos * move.wfcb,d1 * get address of fcb trap #2 * call the bdos cmpi.b #$ff,d0 * check for failure bne openok * if not then go lea mystack+$80,a7 * switch to local stack * move.l bpaddr,a0 * copy base page to local area lea localbp,a1 move.l #$ lea localbp,a0 lea lpb,a1 lea sidfcb,a2 move.l a2,lpbfcb(a1) move.l bphitpa(a0),d1 * set up lpb and load pgm move.l ***************************************************************** * * * Usual filename: SIDLOAD.S * * Adapted by: #readseq,d0 * read the header move.l #sidfcb,d1 * address of fcb trap #2 * call the bdos cmpi.w #0,d0 * check for eahead * tst d3 * check if we are on user 0 beq loadfail * if so then we have failed * move.w #32,d0 * if not then s100,d0 * count of bytes to move bsr copy * branch to subroutine * move.w #32,d0 * get the current user # and save it d1,lpbhitpa(a1) sub.l d0,d1 bclr.l #0,d1 move.l d1,lpblotpa(a1) clr.w lpbcf(a1) clr.b sidfcb+fcbcr move.w #pgmldf,d0 Timothy M. Benson * * Control: 4 MAY 83 15:21 (TMB) * * * * SID Loader -- This program loads DDT68000 at the rrors bne loadfail * error, load failed * lea dskbuf,a0 move.l tsize(a0),d0 * compute size of DDT68000.68K add.l dsizwitch to user 0 clr.l d1 * d1 = 0 trap #2 * call the bdos * move.w #openf,d0 * try the open again move.l #sidfcb,d move.l #$ff,d1 * d1 = 255 trap #2 * call the bdos move.l d0,d3 * d3 holds current user # * move.l bpaddr,a0 * get * now do load move.l a1,d1 trap #2 tst.w d0 bne loadfail * load has failed * move.l d3,d1 * restore the old usertop of * * the TPA, hands it its command tail, and passes control * * to it. * * * ****************************e(a0),d0 * by adding component sizes add.l bsize(a0),d0 add.l #$1000,d0 * fake stack size since Belton doesnt add.l #bpl1 * address of fcb trap #2 * call the bdos cmpi.b #$ff,d0 * check for errors beq loadfail * error, load failed * o 0 move.w #32,d0 * get bdos function # trap #2 * call the bdos * * set up for SID execution * move.l lpbbpa(a1),a2 * * Copy Bytes from (a0)+ to (a1)+ for d0 * copy: subi.l #1,d0 bmi copyxit copylp: move.b (a0)+,(a1)+ dbf d0,copylp cnd type. .dc.b 0 * extent .dc.b 0,0 * s1, s2 .dc.b 0 * rc .ds.b 16 * d0 ... dn .dc.b 0 * cr .ds.b 0,0,0 d 18 March 1984 for extended exception handling WBT. * * This version works with the 68000, not the 68010. * * 6 readseq = 20 setdma = 26 bioscall= 50 pgmldf = 59 * * * Local Variables etc. * mystack: .ds.l $20 * local stack * cnum; { REG UWORD rtn; BSETUP rtn = rdwrt( (LONG)secnum, GBL.dirbufp, 2); if ( secnum < (GBL.parmp)->cks * addr of new bp move.l bplotpa(a0),bplotpa(a2) * copy tpa lower bound move.l lpbdusp(a1),a7 * default user stack ptr opyxit: rts * * * Can't Load DDT68000.68K, Print Error Message * loadfail: move.w #prstrng,d0 move.l #loaderr,d1 trap #* random record number * .even * fcbcr = 32 * dskbuf: .ds.w 64 * used to hold pgm header magic = 0 * offsets in pgm * * initiate program execution * * fudge = $10 * bplen = $100 localbp: .ds.l bplen * local copy of base page bplotpa = 0 bphitpa = 4 bpcsstrt= 8 bpcslen ) *((GBL.dphp)->csv + secnum) = dchksum(); return(rtn); } /******************************* * directory checksum r move.l a2,-(a7) * stack new bp address move.l ccprtn,-(a7) * stack ccp rtn address move.l bpcsstrt(a2),-(a7) * stack e2 move.l ccprtn,-(a7) rts loaderr: .dc.b 13,10,'Cannot load DDT68000.68K.',13,10,'$' * * .end  header tsize = 2 dsize = 6 bsize = 10 stksize = 18 rlbflg = 26 * goodmgc = $601A * legal value for magic number * * * ***************************************************************** * = $C bpdsstrt= $10 bpdslen = $14 bpbsstrt= $18 bpbslen = $1C bpfcb2 = $38 bpfcb1 = $5C * ccprtn: .ds.l 1 * return addr***************************************************************** * * * Usual filename: BDOS00.S * * Originallyntry to DDT68000.68K lea bpfcb2(a0),a0 * copy parsed fcb's & lea bpfcb2(a2),a1 * command tail to new bp move.l #bplen move.l ccprtn,-(a7) rts loaderr: .dc.b 13,10,'Cannot load DDT68000.68K.',13,10,'$' * * .end  * lpb: .ds.w 11 * loader parameter block lpbfcb = 0 lpblotpa= 4 lpbhitpa= 8 lpbbpa = 12 lpbdusp = 16 lpbcf = 20 * .globl _GO .globl _STEP .globl _BDOS .globl _GETSSP .globl _EXINIT .text * * _GO: clr.l errflag movem.l in CCP bpaddr: .ds.l 1 * base page address * sidfcb: .dc.b 0 * FCB for DDT68000.68K .dc.b 'DDT6800068K' * File name a Written by W. B. Tyler, 1982. * * Adapted by: Timothy M. Benson * * Control: 5 May 83 15:25 (TMB) * * Modifie-bpfcb2,d0 bsr copy rts * exit to DDT68000.68K * * BDOS Function Code Equates * prstrng = 9 openf = 15 closef = 1*************************** * directory write routine * ****************************/ UWORD dir_wr(secnum) REG WORD se d0-d7/a0-a5,regsave save register variables movem.l a6/a7,asave move.w #22,d0 set up illegal trap vector move.w #iltv,d move.l asave+4,a7 get old regs move.l 4(a7),a6 move.l pctr,(a6) move.l saveusp,4(a6) bsave Save some stuff Move.L #OLDVEC,A0 Get address of exception storage Move.W #9,D0 Load exception vector count (-1) 2 trap #3 move.l d0,savev Save previous trace exception pointer. * move.l asave+4,a0 caller's stack ptr move.l 4(a0),a0 set up for rte and.w #$7FFF,status move.w status,-(a7) rte begin etatus register again THRTE: Rte Continue processing as in GO. * * *****************************************************1 move.w d1,thvnum move.l #th,d2 trap #3 move.l d0,savev * move.l 4(a7),a0 addr of state save move.l savessp,8(a6) move.w status,12(a6) and.w #$7FFF,12(a6) movem.l d0-d7/a0-a5,14(a6) move.w #22,d0 Move.L (A7),D1 Get return address from stack th3: Cmp.L (A0)+,D1 Is this the one we have? Beq th4 Yep. Dbf D0,th3 A address of cpu state save area move.l (a0),pctr starting pc move.w 12(a0),d0 status ori.w #$8000,d0 set trace bit move.xecuting * * trap handling for _GO and _STEP * th1: move.w (a7)+,status grab info from sys stack move.l************ * * * execute one user instruction (trace or notrace) * * * ************************************area * move.w #62,d0 get supervisor mode trap #2 * move.l (a0),pctr pc to start at movemove.w thvnum,d1 move.l savev,d2 trap #3 move.l bsave,70(a6) move.l bsave+4,74(a6) btst #5,status bere we done yet? Movem.L bsave,D0-D1/A0 User exception vector move.l (a7)+,pctr th2: move.l a7,savessp move.l aw d0,status starting status move.l 4(a0),a1 user stack pointer move.l a1,usp move.l 8(a0),a7 system stack pointer movem. (a7)+,pctr (this one for exceptions) movem.l d0-d1,bsave Move.W #62,D0 Back into supervisor mode Trap #2 By using t***************************** * _STEP: clr.l errflag movem.l d0-d7/a0-a5,regsave save registers movem.l a6/a7,asave save r.w 12(a0),status starting status move.l 4(a0),a1 set up stack pointers move a1,usp user stack pointer move.lq wasusr move.l savessp,74(a6) wasusr: move.l asave,a6 movem.l regsave,d0-d7/a0-a5 move.l errflag,d0 rts 0,savea0 move.l usp,a0 move.l a0,saveusp move.l savea0,a0 andi $5fff,sr movem.l a6/a7,bsave save regs l 14(a0),d0-d7/a0-a6 registers move.l pctr,-(a7) set up for rte move.w status,-(a7) rte * * ***************************he BDOS call movem.l bsave,d0-d1 jmp th2 th: move.w (a7)+,status grab info from sys stack Movem.L D0-D1/A0,egisters * move.w #62,d0 get supervisor mode trap #2 * move.w #22,d0 move.w #trv,d1 move.w d1,thvnum move.l #th,d 8(a0),a7 supervisor stack pointer movem.l 14(a0),d0-d7/a0-a6 set up other registers move.l pctr,-(a7) back to SID proper th4: Movem.L bsave,D0-D1/A0 Restore registers (again) Move.W status,-(SP) Save s************************************** * * * BDOS Call Subroutine -- C Callable * * * **********************re the old vector in the BIOS Move.W #22,D0 * The call (see above) Move.W (A0),D1 * Das Vectornummer Movem.L A0-A1,-(S.L #OLDVEC,A1 * Make pointer to old vectors EXINI1: Move.W #$3D,D0 * Func $3D == Set Exc. Vector Move.L A0,D1 * Get addr* Good enough for printing Trap #2 Move.L #ATMES,D1 * Print " at " Move.W #9,D0 Trap #2 Move.L ESTKSV,A0 * Get excep******************************* * * * Exception Vector Setting * * * * This routine sets all the exception big enough to save regs Move.L STKVAL,D1 * Get the IBRVEC RA again Sub.L #IBRVEC+6,D1 * Make it an offset into IBRVEC D******************************************* * _BDOS: move.w 4(a7),d0 move.l d1,saved1 move.l 6(a7),d1 trap #2 move.l sP) * Take a guess Trap #3 Movem.L (SP)+,A0-A1 Add.W #1,(A0) * Increase vector num. to change Add.L #6,2(A0) * And ess of block Trap #2 Move.W #22,D0 * get BIOS exception vector call Move.W (A0),D1 * Get the vector number Move.L tion RA Move.L 2(A0),-(SP) * Throw it on the stack Jsr _puthexl * And print it out Move.L (SP)+,A0 * Clean up the stackvectors handled by * * DDT on behalf of the program being debugged. * * * *******************************************ivu.W #3,D1 * Get (EXV-2) * 2 And.L #$FFFF,D1 * Clear out the remainder Lsl.L #1,D1 * Make it an offset into messages aved1,d1 rts * .bss * saved1: .ds.l 1 * .text * ***************************************************************** *set new exception handler Cmp.W #12,(A0) * Done yet? Bne EXINI1 * Nope, do it again Movem.L (SP)+,D0-D7/A0-A5 * Restore#THRTE,D2 * Temporary exception vector handler Movem.L A0-A1,-(SP) * Save the address registers Trap #3 * Call up the BI Move.L #ENDMES,D1 * Print out the Move.W #9,D0 Trap #2 Movem.L (SP)+,D0-D7/A0-A6 * Get old register values ********************** * * _EXINIT: Movem.L D0-D7/A0-A5,-(SP) * Save all them registers Move.L #EPB,A0 * Initialize Exc Cmp.W #8,D1 * If Bus Error or Address Error Bge EXHAN1 Add.L #8,ESTKSV * .. Then get rid of garbage EXHAN1: Add.L # * * GETSSP -- supplies system stack pointer to C * * * ****************************************************** all those registers Rts EXHANDL: move.l #$FF,errflag * indicate error to caller Move.L (SP)+,STKVAL * Save RA to IBROS Movem.L (SP)+,A0-A1 * Restore the address registers Move.L D0,(A1)+ * Save the old BIOS vector Move.L D0,D2 * restoMove.L ESTKSV,SP * And the old stack pointer Jmp th1 * And return to DDT * * .data * * Message Table contains all theeption Parameter Move.W #2,(A0) * .. Block. 1st vector is #2, Move.L #IBRVEC,2(A0) * Place to come to on interrupt MoveEXMSLT,D1 * Now a pointer to message pointer Move.L D1,A0 Move.L (A0),D1 * Now a pointer to the message Move.W #9,D0 *********** * _GETSSP: move.w #62,d0 trap #2 move.l a7,d0 andi #$5fff,sr rts * * **********************************VEC Move.L SP,ESTKSV * Save old user stack Move.L #EXCSTK,SP * And get one of our own Movem.L D0-D7/A0-A6,-(SP) * Plenty exception handler messages * BUSERR: Dc.B "Bus Error$" ADRERR: Dc.B "Address Error$" ILLINS: Dc.B "Illegal Instruction$" Z .end 3 regsave: .ds.l 14 savessp: .ds.l 1 saveusp: .ds.l 1 savea0: .ds.l 1 iltv = $4 illegal instruction vector numbermove.l 4(a7),a0 addr of state save area * move.w #62,d0 get supervisor mode trap #2 * move.l ( is where exceptions point Jsr EXHANDL * Sole purpose: Put their return Jsr EXHANDL * .. address on the stack so that * ***************************************************************** * ERDIV: Dc.B "Divide by Zero$" CHKINS: Dc.B "'CHK' Exception$" TPVINS: Dc.B "'TRAPV' Exception$" PRVERR: Dc.B "Privilege Viola***************************************************************** * * * Usual filename: BDOS10.S * * Originally trv = $9 trace exception vector number * savev: .ds.l 1 thvnum: .ds.w 1 * setexp = 61 setsup = 62 * pctr: .ds.la0),pctr pc to start at move.w 12(a0),status starting status move.l 4(a0),a1 set up stack pJsr EXHANDL * .. the exception number can be Jsr EXHANDL * .. calculated Jsr EXHANDL Jsr EXHANDL Jsr EXHANDL Jsr E .globl _GO .globl _STEP .globl _BDOS .globl _GETSSP .globl _EXINIT .globl _GETVBR .globl _GETSFC .globl _GETDFC tion$" XTRACE: Dc.B "Trace Exception$" LN10EM: Dc.B "Line 1010 Emulator$" LN15EM: Dc.B "Line 1111 Emulator$" ATMES: Dc.B " Written by W. B. Tyler, 1982. * * Adapted by: Timothy M. Benson * * Control: 5 May 83 15:25 (TMB) * * Modifie 1 status: .ds.w 1 * * EPB: vnum: .ds.w 1 newv: .ds.l 1 oldv: .ds.l 1 * setexv=61 linef=11 buserr=2 * * ointers move a1,usp user stack pointer move.l 8(a0),a7 supervisor stack pointer move.l 78(a0),d0 set up control registXHANDL Jsr EXHANDL .bss * ESTKSV: .Ds.L 1 * One LONG for the old user stack STKVAL: .Ds.L 1 * Value of pointer from .text * * _GO: clr.l errflag movem.l d0-d7/a0-a5,regsave save register variables movem.l a6/a7,asave move.w # at $" ENDMES: Dc.B $0D,$0A,"$" .even OLDVEC: .Ds.L 10 * Old vector addresses EXMSLT: .Dc.L BUSERR,ADRERR,ILLINS * Med 18 March 1984 for extended exception handling WBT. * * This version works with the 68010, not the 68000. * * .end ers... movec d0,vbr move.l 82(a0),d0 movec d0,sfc move.l 86(a0),d0 movec d0,dfc movem.l 14(a0),d0-d7/a0-a6 IBRVEC .Ds.B 256 * Plenty of room for Exception Stack EXCSTK: errflag: .ds.l 1 asave: .ds.l 2 bsave: .ds.l 22,d0 set up illegal trap vector move.w #iltv,d1 move.w d1,thvnum move.l #th,d2 trap #3 move.l d0,savev * ssage addresses .Dc.L ZERDIV,CHKINS,TPVINS .Dc.L PRVERR,XTRACE,LN10EM .Dc.L LN15EM .data IBRVEC: Jsr EXHANDL * This * * initiate program execution * * set up other registers clr.w -(a7) format word move.l pctr,-(a7) set up for rte and.w #$7FFF,sta86(a6) move.w #22,d0 move.w thvnum,d1 move.l savev,d2 trap #3 move.l bsave,70(a6) move.l bsave+4,74(,savevbr move.l d1,savesfc move.l d2,savedfc movem.l (a7)+,d0-d2 move.l a0,savea0 move.l usp,a0 move.l a0,saveusp atus ori.w #$8000,d0 set trace bit move.w d0,status starting status move.l 4(a0),a1 user stack pointer move.l a1,usp m some stuff Move.L #OLDVEC,A0 Get address of exception storage Move.W #9,D0 Load exception vector count (-1) Move.L (A7 * ***************************************************************** * _STEP: clr.l errflag movem.l d0-d7/a0-a5,regsavetus move.w status,-(a7) rte begin executing * * trap handling for _GO and _STEPa6) btst #5,status beq wasusr move.l savessp,74(a6) wasusr: move.l asave,a6 movem.l regsave,d0-d7/a0-a5 move.move.l savea0,a0 andi $5fff,sr movem.l a6/a7,bsave save regs move.l asave+4,a7 get old reove.l 8(a0),a7 system stack pointer move.l 78(a0),d0 movec d0,vbr move.l 82(a0),d0 movec d0,sfc move.l 86(a0),d0 mov),D1 Get return address from stack th3: Cmp.L (A0)+,D1 Is this the one we have? Beq th4 Yep. Dbf D0,th3 Are we done save registers movem.l a6/a7,asave save registers * move.w #62,d0 get supervisor mode trap #2 * move.w #22,d0 move * th1: move.w (a7)+,status grab info from sys stack move.l (a7)+,pctr (this one for exceptions) movel errflag,d0 return error flag rts back to SID proper th4: Movem.L bsave,D0-D1/A0 Restore reggs move.l 4(a7),a6 move.l pctr,(a6) move.l saveusp,4(a6) move.l savessp,8(a6) move.w status,12ec d0,dfc movem.l 14(a0),d0-d7/a0-a6 registers clr.w -(a7) format word move.l pctr,-(a7) set up for rte move.w status,-yet? Movem.L bsave,D0-D1/A0 User exception vector move.l (a7)+,pctr unstack PC add.l #2,a7 unstack format word.w #trv,d1 move.w d1,thvnum move.l #th,d2 trap #3 move.l d0,savev Save previous trace exception pointer. * move.l asam.l d0-d1,bsave save registers Move.W #62,D0 Back into supervisor mode Trap #2 By using the BDOS call movem.l bsave,disters (again) Move.W status,-(SP) Save status register again THRTE: Rte Continue processing as in GO. * * *********(a6) and.w #$7FFF,12(a6) movem.l d0-d7/a0-a5,14(a6) move.l savevbr,78(a6) move.l savesfc,82(a6) move.l savedfc,(a7) rte * * ***************************************************************** * * * BDOS Call Subroutine -- C Cal th2: move.l a7,savessp movem.l d0-d2,-(a7) movec vbr,d0 save control registers movec sfc,d1 movec dfc,d2 move.l d0ve+4,a0 caller's stack ptr move.l 4(a0),a0 address of cpu state save area move.l (a0),pctr starting pc move.w 12(a0),d0 st0-d1 restore registers jmp th2 th: move.w (a7)+,status grab info from sys stack Movem.L D0-D1/A0,bsave Save******************************************************** * * * execute one user instruction (trace or notrace) * * lable * * * ***************************************************************** * _BDOS: move.w 4(a7),d0 move.l d1, Move.W #22,D0 * get BIOS exception vector call Move.W (A0),D1 * Get the vector number Move.L #THRTE,D2 * Temporary DDT on behalf of the program being debugged. * * * ***************************************************************** V-2) * 2 And.L #$FFFF,D1 * Clear out the remainder Lsl.L #1,D1 * Make it an offset into messages Cmp.W #8,D1 * If Br values from C * * * ***************************************************************** * * _GETVBR: move.w #62,d0 er Cmp.W #12,(A0) * Done yet? Bne EXINI1 * Nope, do it again Movem.L (SP)+,D0-D7/A0-A5 * Restore all those registers saved1 move.l 6(a7),d1 trap #2 move.l saved1,d1 rts * .bss * saved1: .ds.l 1 * .text * ***********************exception vector handler Movem.L A0-A1,-(SP) * Save the address registers Trap #3 * Call up the BIOS Movem.L (SP)+,A0-A * * _EXINIT: Movem.L D0-D7/A0-A5,-(SP) * Save all them registers Move.L #EPB,A0 * Initialize Exception Parameter Moveus Error or Address Error Bge EXHAN1 Add.L #8,ESTKSV * .. Then get rid of garbage EXHAN1: Add.L #EXMSLT,D1 * Now a poin trap #2 movec vbr,d0 andi #$5fff,sr rts _GETSFC: move.w #62,d0 trap #2 movec sfc,d0 andi #$5fff,sr rts _GETDFCRts EXHANDL: move.l #$ff,errflag * indicate error to caller Move.L (SP)+,STKVAL * Save RA to IBRVEC Move.L SP,ESTKSV ****************************************** * * * GETSSP -- supplies system stack pointer to C * * * *********1 * Restore the address registers Move.L D0,(A1)+ * Save the old BIOS vector Move.L D0,D2 * restore the old vector in th.W #2,(A0) * .. Block. 1st vector is #2, Move.L #IBRVEC,2(A0) * Place to come to on interrupt Move.L #OLDVEC,A1 * Make pter to message pointer Move.L D1,A0 Move.L (A0),D1 * Now a pointer to the message Move.W #9,D0 * Good enough for print: move.w #62,d0 trap #2 movec dfc,d0 andi #$5fff,sr rts * * ********************************************************* * Save old user stack Move.L #EXCSTK,SP * And get one of our own Movem.L D0-D7/A0-A6,-(SP) * Plenty big enough to save reg******************************************************** * _GETSSP: move.w #62,d0 trap #2 move.l a7,d0 andi #$5fff,sr e BIOS Move.W #22,D0 * The call (see above) Move.W (A0),D1 * Das Vectornummer Movem.L A0-A1,-(SP) * Take a guess Trointer to old vectors EXINI1: Move.W #$3D,D0 * Func $3D == Set Exc. Vector Move.L A0,D1 * Get address of block Trap #2 ing Trap #2 Move.L #ATMES,D1 * Print " at " Move.W #9,D0 Trap #2 Move.L ESTKSV,A0 * Get exception RA Move.L 2(A0),******** * * * Exception Vector Setting * * * * This routine sets all the exception vectors handled by * *s Move.L STKVAL,D1 * Get the IBRVEC RA again Sub.L #IBRVEC+6,D1 * Make it an offset into IBRVEC Divu.W #3,D1 * Get (EXrts * * ***************************************************************** * * * Routines for getting control registeap #3 Movem.L (SP)+,A0-A1 Add.W #1,(A0) * Increase vector num. to change Add.L #6,2(A0) * And set new exception handl-(SP) * Throw it on the stack Jsr _puthexl * And print it out Move.L (SP)+,A0 * Clean up the stack Move.L #ENDMES,D1 *legal instruction vector number trv = $9 trace exception vector number * savev: .ds.l 1 thvnum: .ds.w 1 * setexp = 61 exception number can be Jsr EXHANDL * .. calculated Jsr EXHANDL Jsr EXHANDL Jsr EXHANDL Jsr EXHANDL Jsr EXHANDL dirscan with close function */ } /************************ * search entry point * ************************/ /* Firace Exception$" LN10EM: Dc.B "Line 1010 Emulator$" LN15EM: Dc.B "Line 1111 Emulator$" ATMES: Dc.B " at $" ENDMES: Dc.B $0 return(FALSE); } else return(FALSE); } /************************ * close_fi entry point * ***************** Print out the Move.W #9,D0 Trap #2 Movem.L (SP)+,D0-D7/A0-A6 * Get old register values Move.L ESTKSV,SP * And setsup = 62 * pctr: .ds.l 1 status: .ds.w 1 * * EPB: vnum: .ds.w 1 newv: .ds.l 1 oldv: .ds.l 1 * setexv= .bss * ESTKSV: .Ds.L 1 * One LONG for the old user stack STKVAL: .Ds.L 1 * Value of pointer from IBRVEC .Ds.B 256 *rst two functions for dirscan */ BOOLEAN alltrue(p1, p2, i) UBYTE *p1; UBYTE *p2; WORD i; { return(TRUE); } D,$0A,"$" .even OLDVEC: .Ds.L 10 * Old vector addresses EXMSLT: .Dc.L BUSERR,ADRERR,ILLINS * Message addresses .Dc.L*******/ UWORD close_fi(fcbp) struct fcb *fcbp; /* pointer to fcb for file to close */ { flushit(); the old stack pointer Jmp th1 * And return to DDT * * .data * * Message Table contains all the exception handler mess61 linef=11 buserr=2 * * .end  Plenty of room for Exception Stack EXCSTK: errflag: .ds.l 1 asave: .ds.l 2 bsave: .ds.l 3 regsave: .ds.l 14 s/***************************************************************************** * * C P / M C R U N T I M E L I B ZERDIV,CHKINS,TPVINS .Dc.L PRVERR,XTRACE,LN10EM .Dc.L LN15EM .data IBRVEC: Jsr EXHANDL * This is where exceptions po /* first, flush the buffers */ if ((fcbp->s2) & 0x80) return(0); /* if file write flag not on,ages * BUSERR: Dc.B "Bus Error$" ADRERR: Dc.B "Address Error$" ILLINS: Dc.B "Illegal Instruction$" ZERDIV: Dc.B "Divide by 1 linef=11 buserr=2 * * .end avessp: .ds.l 1 saveusp: .ds.l 1 savea0: .ds.l 1 savevbr: .ds.l 1 savesfc: .ds.l 1 savedfc: .ds.l 1 iltv = $4 il H E A D E R F I L E * ------------------------------------------------------------- * Copyright 1982 by Digital Researcint Jsr EXHANDL * Sole purpose: Put their return Jsr EXHANDL * .. address on the stack so that Jsr EXHANDL * .. the don't need to do physical close */ return( dirscan(close, fcbp, 0)); /* callZero$" CHKINS: Dc.B "'CHK' Exception$" TPVINS: Dc.B "'TRAPV' Exception$" PRVERR: Dc.B "Privilege Violation$" XTRACE: Dc.B "Tdirindx >> 2); UNLOCK return(TRUE); badmerge: UNLOCK ro_dsk |= (1 << GBL.curdsk); h Inc. All rights reserved. * * This is an include file for assisting the user to write portable * programs for C. * *****value */ #define EOF (-1) /* EOF Value */ #define TRUE (1) /* Function TRUE value */ #define FALSE (0) /*******************************************************************/ /* Miscellaneous Definitions: */ /***************/********************************************************/ /* */ /* Include file for SID-68K -- MC68000 Version */ /* #define REG register /* register variable */ #define LOCAL auto /* Local var on 68000 */ #define EXTERN extern rmp)->dsm < 256) { i = 16; do clraloc(UBWORD(dirp->dskmap.small[--i])); whil************************************************************************/ #define ALCYON 1 /* using Alcyon compiler */ /** Function FALSE value */ /*************************** end of portab.h ********************************/  FALSE (0) /*************************************************************/ #define FAILURE (-1) /* Function failure return val */ #defin */ /********************************************************/ #define MC68000 1 /* External variable */ #define MLOCAL static /* Local to module */ #define GLOBAL /**/ /* Global variable */ e (i); } else { i = 8; do clraloc(swap(dirp->dskmap.big[--i])); * Standard type definitions */ /***************************/ #define BYTE char /* Signed byte */ #define BO Function FALSE value */ /*************************** end of portab.h ********************************/  FALSE (0) /e SUCCESS (0) /* Function success return val */ #define YES 1 /* "TRUE" */ #define NO 0 /* "FALSE" */ #defi */ /********************************************************/ #define MC68000 1 #define VOID /**/ /* Void function return */ #define DEFAULT int /* Default size */ /********************** while (i); } UNLOCK } return(rtn); } /************************ * rename entry point OLEAN char /* 2 valued (true/false) */ #define WORD short /* Signed word (16 bits) */ #define UWORD unsigned int /it]) & 0x80 ) ro_err(fcbp,dirindx); /* check for read-only file */ dirp->entry = 0xe5;ne FOREVER for(;;) /* Infinite loop declaration */ #define NULL 0 /* Null pointer value */ #define ZERO 0 /* Zero ) ro_err(fcbp,dirindx); /* check for read-only file */ p = &(fcbp->dskmap.small[1]); *****/ #ifdef ALCYON #define UBYTE char #else #define UBYTE unsigned char /* Unsigned byte */ #endif /********** ************************/ BOOLEAN rename(fcbp, dirp, dirindx) REG struct fcb *fcbp; /* pointer to fcb for fil* unsigned word */ #define LONG long /* signed long (32 bits) */ #define ULONG unsigned long /* Unsigned long */ LOCK dir_wr(dirindx >> 2); /* Now free up the space in the allocation vector */ if ((GBL.pa q = &(dirp->fname[0]); i = 11; do { *q++ = *p++ & 0x7f; i -= 1; Timothy M. Benson * * Control: 4 MAY 83 15:21 (TMB) * * * * SID Loader -- This program loads DDT68010 at the *********/ setran(fcbp) REG struct fcb *fcbp; /* pointer to fcb for file to set ran rec */ { struct witch to user 0 clr.l d1 * d1 = 0 trap #2 * call the bdos * move.w #openf,d0 * try the open again move.l #sidfcb,d */ /********************************************************/ #define MC68010 1  move.l #$ff,d1 * d1 = 255 trap #2 * call the bdos move.l d0,d3 * d3 holds current user # * move.l bpaddr,a0 * get } while (i); dir_wr(dirindx >> 2); } return(rtn); } /************************ * set_attr entrytop of * * the TPA, hands it its command tail, and passes control * * to it. * * * **************************** { BYTE b3; BYTE b2; BYTE b1; BYTE b0; }; LONG random; random = (LONG)UBWOR1 * address of fcb trap #2 * call the bdos cmpi.b #$ff,d0 * check for errors beq loadfail * error, load failed * o */ /********************************************************/ #define MC68010 1  drive for DDT68010.68K move.b $24(a0),sidfcb * and stuff into FCB move.w #openf,d0 * open file DDT68010.68K move.l #sid point * ************************/ BOOLEAN set_attr(fcbp, dirp, dirindx) REG struct fcb *fcbp; /* pointer to fc************************************* * .text * start: move.l (a7)+,ccprtn * save stacked info move.l (a7)+,bpaddr * D(fcbp->cur_rec) + extsize(fcbp); /* compute random record field */ fcbp->ran0 = random.bpenok: move.w #setdma,d0 * set up to read pgm header move.l #dskbuf,d1 * dma address trap #2 * call the bdos * move.w /* Return size of extent pointed to by fcbp */ REG struct fcb *fcbp; { return( ((LONG)(fcbp->extent & 0x1f) << 7) fcb,d1 * get address of fcb trap #2 * call the bdos cmpi.b #$ff,d0 * check for failure bne openok * if not then go b for file to delete */ REG struct dirent *dirp; /* pointer to directory entry */ REG WORD dirindx; /* lea mystack+$80,a7 * switch to local stack * move.l bpaddr,a0 * copy base page to local area lea localbp,a1 move.l #$***************************************************************** * * * Usual filename: DDTLOAD.S * * Adapted by: #readseq,d0 * read the header move.l #sidfcb,d1 * address of fcb trap #2 * call the bdos cmpi.w #0,d0 * check for e | ((LONG)(fcbp->s2 & 0x3f) << 12) ); } /************************ * setran entry point * ***************ahead * tst d3 * check if we are on user 0 beq loadfail * if so then we have failed * move.w #32,d0 * if not then s/********************************************************/ /* */ /* Include file for SID-68K -- MC68010 Version */ /* 100,d0 * count of bytes to move bsr copy * branch to subroutine * move.w #32,d0 * get the current user # and save it rrors bne loadfail * error, load failed * lea dskbuf,a0 move.l tsize(a0),d0 * compute size of DDT68010.68K add.l dsizlocal copy of base page bplotpa = 0 bphitpa = 4 bpcsstrt= 8 bpcslen = $C bpdsstrt= $10 bpdslen = $14 bpbsstrt= $18 bpbsln,-(a7) * stack ccp rtn address move.l bpcsstrt(a2),-(a7) * stack entry to DDT68010.68K lea bpfcb2(a0),a0 * copy parsednot load DDT68010.68K.',13,10,'$' * .bss .even lastload: .ds.l 1 * .end ,lpblotpa(a1) clr.w lpbcf(a1) clr.b sidfcb+fcbcr move.w #pgmldf,d0 * now do load move.l a1,d1 trap #2 tst.w d0 bn rlbflg = 26 * goodmgc = $601A * legal value for magic number * * * lpb: .ds.w 11 * loader parameter block lpbfcb = e(a0),d0 * by adding component sizes add.l bsize(a0),d0 add.l #$1000,d0 * fake stack size since Belton doesnt add.l #bplen = $1C bpfcb2 = $38 bpfcb1 = $5C * ccprtn: .ds.l 1 * return addr in CCP bpaddr: .ds.l 1 * base page address * sidfc fcb's & lea bpfcb2(a2),a1 * command tail to new bp move.l #bplen-bpfcb2,d0 bsr copy rts * exit to DDT68010.68K ot load DDT68010.68K.',13,10,'$' * .bss .even lastload: .ds.l 1 * .end e loadfail * load has failed * move.l d3,d1 * restore the old user 0 move.w #32,d0 * get bdos function # trap #2 * 0 lpblotpa= 4 lpbhitpa= 8 lpbbpa = 12 lpbdusp = 16 lpbcf = 20 * * * Copy Bytes from (a0)+ to (a1)+ for d0 * copy: sen+fudge,d0 * cmpi.w #goodmgc,magic(a0) * must be $601A bne loadfail * tst.w rlbflg(a0) * must be 0 bne loadfail * b: .dc.b 0 * FCB for DDT68010.68K .dc.b 'DDT6801068K' * File name and type. .dc.b 0 * extent .dc.b 0,0 * s1, s2 .* * BDOS Function Code Equates * prstrng = 9 openf = 15 closef = 16 readseq = 20 setdma = 26 bioscall= 50 pgmldf = 59 ===================== * * call the bdos * * set up for SID execution * move.l lpbbpa(a1),a2 * addr of new bp move.l bplotpa(a0),bplotpa(a2) * cubi.l #1,d0 bmi copyxit copylp: move.b (a0)+,(a1)+ dbf d0,copylp copyxit: rts * * * Can't Load DDT68010.68K, Print Erro lea localbp,a0 lea lpb,a1 lea sidfcb,a2 move.l a2,lpbfcb(a1) move.l bphitpa(a0),d1 * set up lpb and load pgm move.l dc.b 0 * rc .ds.b 16 * d0 ... dn .dc.b 0 * cr .ds.b 0,0,0 * random record number * .even * fcbcr = 32 * dsk * * * Local Variables etc. * mystack: .ds.l $20 * local stack * fudge = $10 * bplen = $100 localbp: .ds.l bplen * * *-----------------------------------------------------------------------* * opy tpa lower bound move.l lpbdusp(a1),a7 * default user stack ptr move.l a2,-(a7) * stack new bp address move.l ccprtr Message * loadfail: move.w #prstrng,d0 move.l #loaderr,d1 trap #2 move.l ccprtn,-(a7) rts loaderr: .dc.b 13,10,'Cand1,lpbhitpa(a1) sub.l d0,d1 bclr.l #0,d1 cmp.l #lastload,d1 * test for overlap with this code! ble loadfail move.l d1buf: .ds.w 64 * used to hold pgm header magic = 0 * offsets in pgm header tsize = 2 dsize = 6 bsize = 10 stksize = 18 $2pip cputype.h=cpu68000.h $2cp68 -i 0$1 sid68k.c $1sid68k.i $2c068 $1sid68k.i $1sid68k.1 $1sid68k.2 $1sid68k.3 -f era $1sisidfun.i $1sidfun.1 $1sidfun.2 $1sidfun.3 -f -T era $1sidfun.i $2c168 $1sidfun.1 $1sidfun.2 sidfun.s -T era $1sidfun.1 era $-f $1 -l -u bdos00.s $2as68 -s 0$1 -f $1 -l -u ddtload.s lo68 -s -f $1 -r -o ddt68000.68k sid68k.o sidfun.o sid03.o sid05.o bdos10.o 0$2clib lo68 -r -f $1 -s -o ddt10.68k ddt10lod.o era *.o era $1sid03.2 $2as68 -s 0$1 -f $1 -l -u sid03.s era sid03.s $2cp68 -i 0$1 sid04.c $1sid04.i $2c068 $1sid04.i $1sid04.1 $1s $2cp68 -i 0$1 sid05.c $1sid05.i $2c068 $1sid05.i $1sid05.1 $1sid05.2 $1sid05.3 -f -T era $1sid05.i $2c168 $1sid05.1 $1sid68k.i $2c168 $1sid68k.1 $1sid68k.2 sid68k.s era $1sid68k.1 era $1sid68k.2 $2as68 -s 0$1 -f $1 -l -u sid68k.s era sid68k.s1sidfun.2 $2as68 -s 0$1 -f $1 -t -l -u sidfun.s era sidfun.s $2cp68 -i 0$1 sid03.c $1sid03.i $2c068 $1sid03.i $1sid03.1 $d04.o sid05.o bdos00.o 0$2clib lo68 -r -f $1 -s -o ddt.68k ddtload.o pip cputype.h=cpu68010.h $2cp68 -i 0$1 sid68k.c $1si************************/ #include "bdosinc.h" /* Standard I/O declarations */ #include "bdosdef.h" sid04.2 $1sid04.3 -f era $1sid04.i $2c168 $1sid04.1 $1sid04.2 sid04.s era $1sid04.1 era $1sid04.2 $2as68 -s 0$1 -f $1 -l -d05.2 sid05.s -T era $1sid05.1 era $1sid05.2 $2as68 -s 0$1 -f $1 -t -l -u sid05.s era sid05.s $2as68 -s 0$1 -f $1 -t -l $2cp68 -i 0$1 sidfun.c $1sidfun.i $2c068 $1sidfun.i $1sidfun.1 $1sidfun.2 $1sidfun.3 -f era $1sidfun.i $2c168 $1sidfun.1 1sid03.2 $1sid03.3 -f -T era $1sid03.i $2c168 $1sid03.1 $1sid03.2 sid03.s -T era $1sid03.1 era $1sid03.2 $2as68 -s 0$1 -f $d68k.i $2c068 $1sid68k.i $1sid68k.1 $1sid68k.2 $1sid68k.3 -f -T era $1sid68k.i $2c168 $1sid68k.1 $1sid68k.2 sid68k.s -T era /********************************************************/ /* */ /* Include file for SID-68K -- MC68010 Version */ /* u sid04.s era sid04.s $2cp68 -i 0$1 sid05.c $1sid05.i $2c068 $1sid05.i $1sid05.1 $1sid05.2 $1sid05.3 -f era $1sid05.i $2c -u bdos10.s $2as68 -s 0$1 -f $1 -t -l -u ddt10lod.s lo68 -r -f $1 -s -o ddt68010.68k sid68k.o sidfun.o sid03.o sid04.o s$1sidfun.2 sidfun.s era $1sidfun.1 era $1sidfun.2 $2as68 -s 0$1 -f $1 -l -u sidfun.s era sidfun.s $2cp68 -i 0$1 sid03.c 1 -t -l -u sid03.s era sid03.s $2cp68 -i 0$1 sid04.c $1sid04.i $2c068 $1sid04.i $1sid04.1 $1sid04.2 $1sid04.3 -f -T era $$1sid68k.1 era $1sid68k.2 $2as68 -s 0$1 -f $1 -t -l -u sid68k.s era sid68k.s $2cp68 -i 0$1 sidfun.c $1sidfun.i $2c068 $1 */ /********************************************************/ #define MC68010 1 168 $1sid05.1 $1sid05.2 sid05.s era $1sid05.1 era $1sid05.2 $2as68 -s 0$1 -f $1 -l -u sid05.s era sid05.s $2as68 -s 0$1 id05.o bdos10.o 0$2clib lo68 -r -f $1 -s -o ddt10.68k ddt10lod.o era *.o $1sid03.i $2c068 $1sid03.i $1sid03.1 $1sid03.2 $1sid03.3 -f era $1sid03.i $2c168 $1sid03.1 $1sid03.2 sid03.s era $1sid03.1 1sid04.i $2c168 $1sid04.1 $1sid04.2 sid04.s -T era $1sid04.1 era $1sid04.2 $2as68 -s 0$1 -f $1 -t -l -u sid04.s era sid04. */ /********************************************************/ #define MC68010 1  11* CP68 Source 12* C068 Source 13* C168 Source 14 Test Suite Source 15 reas. After copying all diskettes to the hard disk, you should have the following: User Contents building the O/S, utilities, and compiler. Each successive iteration uses the tools built on the previousk parameter block */ REG UWORD rtn; /* return parameter */ UWORD iosect; ecifications. The first drive is for temporary files, and the second specifies the drive on which the compiler/* can't do / or % without an external */ /************************ * do_phio entry point * ************************/ Distribution Kit .SUB files Items marked with an asterisk ("*") are not complete. Sources for ---- -------- 0 Binaries, RELOC files 1 Bootstrap (LDRLIB) source 2 O/S (C iteration. The test suite is run just after installation of the new tools. The MAKE.SUB files distribu CP/M-68K Version 1.2 Source Kit ------------------------------- , assembler, linker, and C runtime library are located. If you have a RAMdisk with 512K, use it for the firUWORD do_phio(iop) REG struct iopb *iop; /* iop is a pointer to a i/o parameter block */ { MLOCAL UBYTE lasthe C compiler, assembler, linker, etc. are copyright by Alcyon Corp., and require a separate source license. PMLIB) source 3* LINK68 Source 4 KLIB Source 5 DDT Source 6 CLIB Source ted will not work due to the missing sources for the compiler, assembler, and linkers. You can rebuild This source distribution for CP/M-68K is designed for use on a machine with a large capacity (7Mb) hast drive. If you have a 1Mb RAMdisk, use it for both. (See the MAKE.SUB file for user 0 to get a list t_dsk; /* static variable to tell which disk was last used, to avoid disk selects */ Each user number contains a file "MAKE.SUB". This command file re-creates from source all 7 LIBF.A Source 8 LIBE.A Source 9* AS68 Source 10* LO68 / Utility Sources the binaries for the sources which are present by editing these MAKE.SUB files, however. rd disk. All 15 user numbers are utilized. The files on the diskettes are already in their proper user aof the files to put on the disk). The entire process is designed to repeat over and over, REG struct dph *hdrp; /* pointer to disk parameter header */ REG struct dpb *dparmp; /* pointer to disbinary files within the user area. There are two parameters to these files. Both parameters are drive spUser 15 contains files MAKE.SUB, which makes a VME-10 distribution, and MAKE8.SUB, which makes an eg,d7 add.l csize,d7 addq.l #1,d7 bclr #0,d7 move.l d7,dseg add.l dsize,d7e,d7 sub.l dsize,d7 sub.l bsize,d7 subq.l #4,d7 bclr #0,d7 * put cseg at nase cmp.l LoAdr(a0),d7 * above bottom of memory? blt badadr add.l 0(a6,d2),d7 * find tPL/H compiler, which we also can't distribute. The port to the Z-8000 involved re-coding these in C. We wi trymemtp * try to fit stack at top of memory tst.l d1 beq set6 * if ok, skip eight-inch distribution. The files V1.SUB->V3.SUB contain PIP commands for copying files from the hard d addq.l #1,d7 bclr #0,d7 move.l d7,bseg set4: * cseg, dseg, bseg set up * now find a place foext even address below move.l d7,cseg * high memory - (sum of sizes) set2: * Cseg has been set up. Now do op of segment cmp.l HiAdr(a0),d7 * below top of memory? bgt badadr addq.l #4,d2 *ll try to incorporate the C versions into the next release.  moveq.l #4,d2 bsr fndseg * else, try to fit below other segs tst.l d1 bne badisk to floppies to create a 5.25 CP/M-68K Version 1.2 Source Kit Page 1 r the base page and stack moveq.l #3,d2 bsr fndseg * try to fit base page below cseg, dseg, bseg dseg, bseg cmpi.w #$601b,magic bne set3 * if magic # = 601b, take addr from hdr move.l dstart, point to next segment dbf d3,set7 rts badadr: moveq.l #1,d0 rts movebuf: * move (d3) bytel try to incorporate the C versions into the next release. adr set6: * now check all segments for conflicts with low and high memory boundaries movea.l #cseg,a5 movea. inch distribution kit. The files 1.SUB->8.SUB do the same for the eight-inch distribution. tst.l d1 beq set5 * if found, skip moveq.l #3,d2 bsr trymemtp * dseg move.l bstart,bseg bra set4 set3: * if short header, dseg and bseg follow cseg move.l css from the base page buffer to (a2) * uses d6 movea.l basepg,a1 move.l #secsize,d6 sub.w bufbyts,$100 (even boundary) bra set2 sldhi: * relocatable, load high move.l HiAdr(a0),d7 sub.l csizl #csize,a6 clr.l d2 moveq #4,d3 * loop counter set7: move.l 0(a5,d2),d7 * get segment b Also in user 15 are the sources for ED, PIP, and STAT. These require the Hitachi Super else, try top of memory tst.l d1 bne badadr * if fail, exit set5: moveq.l #4,d2 bsrd6 * address to move from = adda.w d6,a1 * (basepg) + secsize - (bufbyts) sub.w d3,bufead next sector tst.w d1 bne rdbad * if no good, exit sub.l d3,d2 * decre bsr movebuf * if yes, move # bytes to load bra finrd rdtxt4: sub.l d3,d2 move.w (a3)+,d7 * get relocation info andi.w #7,d7 * strip off symbol table bits lsl -28,d7 cmpi.w #$601a,magic * short header? beq rdtxt2 subq.w #8,d7 rdtxt2: move.w d7,bufbyd: move.l dseg,a2 * set up to load data segment move.l dsize,d2 sub.w #1,loop bnbyts * update # bytes buffered bra moveb2 moveb1: move.b (a1)+,(a2)+ * do the move moveb2: dbf d3,mment # bytes to load adda.l #secsize,a2 * increment dma address bra rdtxt5 rdtxt6: tst.l * if no, update # bytes to load bsr movebuf * move remainder of buffer move.l #secsize,d3 * #1,d7 * multiply by 2 jmp 2(pc,d7) bra relabs bra reldata bra ts * indicate # bytes of text in buffer move.w #2,loop * do for code, data segments move.l csege rdtxt3 move.l bseg,a2 * clear the bss segment move.l bsize,d2 beq rdtxt8 rdtxt7:oveb1 rts rdtxt: * Read code and data text into memory * during this routine, a2 is always the load address, * d2 * any more bytes to read? beq finrd move.l basepg,d1 bsr setdma bsrd3 = secsize fo following loop rdtxt5: cmp.l d3,d2 * have at least one more full sector? blt relcode bra relbss bra relbad bra rellong bra relbad bra relo,a2 * start at cseg move.l csize,d2 * for csize bytes rdtxt3: clr.l d3 move.w buf clr.b (a2)+ subq.l #1,d2 bne rdtxt7 rdtxt8: rts rdbad: moveq.l #2,d0 rts relocword: d2 is number of bytes left to load moveq #63,d7 movea.l LoAdr(a0),a5 movea.l b readseq * if yes, read into base page tst.w d1 bne rdbad move.w d3,bufbyts *rdtxt6 move.l a2,d1 bsr setdma * if yes, set up dma address bsr readseq * rp relbad: move.l (sp)+,d0 * pop return address moveq #3,d0 * return bad relocation to main routibyts,d3 cmp.l d2,d3 * # bytes in buffer >= # bytes to load? blt rdtxt4 move.l d2,d3 * relocate word at (a2) based on reloc bits at (a3) * lsb of d2 indicates whether previous word was 1st half of long-word asepg,a6 rdtxt1: move.w (a5)+,(a6)+ * move header sector to base page dbf d7,rdtxt1 move.w #secsize indicate that we've buffered a sector move.l d2,d3 bsr movebuf * move remainder of segment finrne rts relabs: relop: bclr #0,d2 * reset long word flag tst.w (a2)+ * point to n *if amt in buffer < # bytes to skip, addq #1,d6 * read in 1 extra sector skip1: move.l basepg,a3 * we will always read into base page * skip past the symbol table move.l symsize,d7 divu #secsize,d move.w #(secsize/2)-1,d3 reloc3: bsr relocword * relocate one word subq.l #1,d4 reloc4: move.l d6,(a2)+ * note that a2 points past long word rts reloc: * Modify address references of coset move.l csize,d4 * nmbr of bytes to relocate move.w #2,loop * we're going to relocate 2 seext word of segment rts rellong: bset #0,d2 * set long word flag tst.w (a2)+ adda #secsize,a3 suba.w d3,a3 * set up a3 to point to buffer lsr #1,d3 * d37 * calculate how many sectors to skip * note that max # symbols is 8k, which is 896 sectors of 128 bytes move.w tst.l d4 * any more to relocate in this segment? bne reloc2 * if yes, do it mde and data segments based on relocation bits * During this routine, * a2 points to text file to relocate * a3 points to relogments reloc1: * relocate one segment clr.l d2 * clear long word flag lsr.l #1,d4 * point to next word of segment rts reldata: relbss: relcode: bclr #0,d2 * long word fla is nmbr words in buffer bra skip3 skip2: bsr readseq * read next symbol table sector d7,d6 * d6 is nmbr sectors to skip swap d7 * d7 is nmbr bytes to skip move.w bufbytove.l dseg,a2 * else, set up for dseg move.l dsize,d4 sub.w #1,loop bne reloc1 cation word in basepg * lsb of d2 is long word flag (set on reloc type 5, reset on next word) * d3 is # words in relocation bu * make d4 indicate # words bra reloc4 reloc2: subq.w #1,d3 bpl reloc3 bsr reag set? bne relc1 * if yes, skip move.w (a2),d6 add.w d5,d6 move.w d6,(a2)+ tst.w d1 bne rdbad skip3: dbf d6,skip2 * we got past symbol table * a3, d3 are set up move.l s,d3 sub.w d7,d3 * subtract bytes to skip from buffer bge skip1 addi #secsize,d3 rts setrtn: * Set up the return parameters in Ld Parm Blk and Base Page move.l basepg,BasPage(a0) moffer * d4 is nmbr of words left to relocate * d5 is relocation offset move.l basepg,d1 bsr setdma dseq * if no more words in buffer, refill it tst.w d1 bne rdbad move.l basepg,a3 rts relc1: tst.w -(a2) * point to first word of long move.l (a2),d6 add.l d5,d6 cseg,d5 move.l d5,a2 * relocate cseg first sub.l tstart,d5 * d5 contains the relocation offve.l stk,d7 add.l stksize,d7 bclr #0,d7 move.l d7,Stack(a0) move.l basepg,a1 * offsets from start of parameter block FCBPtr = 0 LoAdr = 4 HiAdr = 8 BasPage = 12 * return parameters S* now put disk number that we loaded from into base page movea.l FCBPtr(a0),a2 move.b (w 1 bufbyts: .ds.w 1 .end  moveq #4,d5 * try for all segments clr.l bseg * but force bss not to appear setb1:asepg: .ds.l 1 stk: .ds.l 1 symsize: .ds.l 1 temp: .ds.l 1 loop: .ds move.l LoAdr(a0),(a1)+ move.l HiAdr(a0),(a1)+ move.l cseg,(a1)+ move.l csize,(a1)+ movtack = 16 Flags = 21 hdr: * load file header is read into here magic: .ds.w a2),d0 * get disk select byte bne setb3 * if not auto-select, skip move #25,d0 * we will always read into base page * skip past the symbol table move.l symsize,d7 divu #secsize,d cmp.l (a6),d6 * segment above bss? bhi setb2 cmp.l (a6),d7 * segment is above bss. I.w 1 bufbyts: .ds.w 1 .end e.l dseg,(a1)+ move.l dsize,(a1)+ move.l bseg,(a1)+ move.l bsize,(a1) * find size of free memory 1 csize: .ds.l 1 dsize: .ds.l 1 bsize: .ds.l 1 bpsize: .ds.l 1 * symb tbl trap #2 * get default disk addq #1,d0 * we want it in range of 1..16 setb3: move.b d7 * calculate how many sectors to skip * note that max # symbols is 8k, which is 896 sectors of 128 bytes move.w s it below previous? bls setb2 move.l (a6),d7 setb2: tst.l (a6)+ * point to next segment w 1 bufbyts: .ds.w 1 .end  after bss segment move.l HiAdr(a0),d7 * d7 contains next segment above bss move.l -4(a1),d6 addsize is swapped with base page size stksize: .ds.l 1 tstart: .ds.l 1 rlbflg: .ds.w 1 dstart: 0,(a1)+ * move disk number into base page clr.l d0 * function OK rts .bss d7,d6 * d6 is nmbr sectors to skip swap d7 * d7 is nmbr bytes to skip move.w bufbyt dbf d5,setb1 sub.l d6,d7 * diff between bss top and next segment abv move.l d7,(a1)+ w 1 bufbyts: .ds.w 1 .end .l (a1)+,d6 * d6 points to start of free mem after bss movea.l #cseg,a6 * a6 points to segment to try .ds.l 1 bstart: .ds.l 1 cseg: .ds.l 1 dseg: .ds.l 1 bseg: .ds.l 1 bs,d3 sub.w d7,d3 * subtract bytes to skip from buffer bge skip1 addi #secsize,d3 /* pointer to disk parameter header */ /* return parm for fcn 0, input for rest */ }; /* Definitions for iofcn, tbelow */ UBYTE ioflags; /* used for login flag and write flag */ UBYTE devtype; /* device type, see defines below */ igital Research, Inc. * * Structure definitions for doing I/O in packets * * * *************************************#define redir 4 /* read/write IOByte */ #define exc_vec 5 /* set exception vector */  *if amt in buffer < # bytes to skip, addq #1,d6 * read in 1 extra sector skip1: move.l basepg,a3 he function number */ #define sel_info 0 /* select and return info on device */ #define read 1 #define write 2 #define /* currently unused */ UBYTE devnum; /* device number, or, devtype and devnum taken together form int device nu*******************/ /* May use this information structure instead of disk parameter header and disk parameter block in f#define redir 4 /* read/write IOByte */ #define exc_vec 5 /* set exception vector */  adda #secsize,a3 suba.w d3,a3 * set up a3 to point to buffer lsr #1,d3 * d3 flush 3 #define status 4 /* not currently used */ /* Definitions for devtype, the device type */ /* This field nmber */ LONG devadr; /* item nmbr on device to start xfer at */ /* note -- item is sector for disks, byte for char devs *uture, but for now it's unused struct dskinfo { UBYTE *dbuffp; UBYTE *csv; UBYTE *alv; UBYTE blksize; UBYTE didummy; is nmbr words in buffer bra skip3 skip2: bsr readseq * read next symbol table sector ot currently used */ #define console 0 #define printer 1 #define disk 2 #define memory 3 /* gets TPA boundaries */ / UWORD xferlen; /* number items to transfer */ UBYTE *xferadr; /* memory address to xfer to/from */ struct dph *infop; UWORD dskmax; UWORD dirmax; UWORD chksize; }; */ struct iopb { UBYTE iofcn; /* function number, see defines /******************************************************** * * * CP/M-68K header file * * Copyright (c) 1982 by D #define redir 4 /* read/write IOByte */ #define exc_vec 5 /* set exception vector */