Bell 32V development
authorTom London <tbl@research.uucp>
Thu, 22 Mar 1979 02:43:23 +0000 (21:43 -0500)
committerTom London <tbl@research.uucp>
Thu, 22 Mar 1979 02:43:23 +0000 (21:43 -0500)
Work on file usr/src/standalone/fboot.c

Co-Authored-By: John Reiser <jfr@research.uucp>
Synthesized-from: 32v

usr/src/standalone/fboot.c [new file with mode: 0644]

diff --git a/usr/src/standalone/fboot.c b/usr/src/standalone/fboot.c
new file mode 100644 (file)
index 0000000..aa15934
--- /dev/null
@@ -0,0 +1,878 @@
+# include "rel.h"
+# define RP6CYL  815  /*  no. RP06 cylinders/pack */
+# define RP6TRK  19  /*  no. tracks/cyl  */
+# define RP6SEC  22  /*  no. sectors/track  */
+# define RM3CYL 823  /*  RM03  */
+#define RM3TRK 5
+#define RM3SEC 32
+# define RP6ST  (rptrk*rpsec)
+# define MAXSEC  (rpcyl*rptrk*rpsec)  /*  sectors/pack  */
+# define M0  0x20010000  /* phys addr MBA 0  */
+# define M1  0x20012000  /*  phys addr MBA 1  */
+# define M_cr  1  /*  MBA 0 control reg addr , longword offset */
+# define M_sr 2  /* MBA 0 status reg offset */
+# define M_map  0x200  /* start MBA 0 map reg's longword offset */
+# define M_var  3  /* MBA 0 virt addr reg offset */
+# define M_bc  4  /*  MBA 0 byte count reg offset */
+# define MBAinit 01  /*  MBA init bit */
+/*             */
+# define EXTREG  0x400  /*  base for external reg's on MBA  */
+/*             */
+# define RP_cr  0  /* RP06 control reg offset, longword */
+# define RP_sr  1  /*  RP06 status reg offset */
+# define RP_stk  5  /*  RP06 sector/track reg offset */
+# define RP_typ 06  /* drive type reg */
+# define RP_off  011  /*  RP offset reg */
+# define RP_cyl  10  /*  RP06 cylinder reg offset */
+/*             */
+# define RP_GO  1  /*  go bit */
+# define RP_RED  070  /*  RP06 read function code */
+# define RP_DC  010  /*  drive clear function code */
+# define RP_DRY  0200  /*  drive ready, status reg */
+# define RP_ERR 040000  /* composite error, status reg */
+# define RP_RIP 020  /* RP readin preset function code */
+# define RP_FMT  0x1000  /* format bit in RP offset reg */
+# define RP_MOL  0x1000  /* medium on-line bit in RP status reg */
+/*             */
+# define RXCS  32  /*  receiver control/staus */
+# define RXDB  33  /*  receiver data */
+# define TXCS  34  /*  transmitter control/status */
+# define TXDB  35  /*  transmitter data */
+# define RXCS_DONE  0x80  /*  receiver done */
+# define TXCS_RDY  0x80  /*  transmitter ready */
+/*             */
+# define MAG410 0410
+# define MAG411 0411
+# define MAXUNI  1
+# define NL  012
+# define CR 015
+# define CDEL 0x23
+# define LDEL 0x40
+# define BLKSIZ 512
+# define HDRSIZ 040  /*  task header size  */
+# define INOSIZ  64  /*  no. bytes per inode entry */
+# define INOBLK  (BLKSIZ/INOSIZ)  /*  no. inodes/disk block */
+# define NAMSIZ 14  /*  no. char's in dir name field */
+# define DIRSIZ  16  /*  no. bytes/directory entry */
+# define SLASH  057  /* '/'  */
+# define NADDR  13  /* no. addr blocks in inode entry */
+# define KSP 0
+/*             */
+# define IFMT 0170000
+# define IFDIR 040000
+# define IFREG 0100000
+# define ROOTINO  2  /*  root dir inode no. */
+
+/*             */
+#define RP6typ  022  /*  RP06 */
+#define RM3typ  024  /*  RM03 type */
+struct dirent { short ino ; char dname[NAMSIZ] ; } ;
+struct inod {
+       short i_mode ;
+       short fill1[3] ;
+       int i_size ;
+       char i_addr[40] ;
+       int fill2[3] ;
+       } ;
+struct thdr {
+       int hmagic ;
+       int htsiz ;
+       int hdsiz ;
+       int hbsiz ;
+       int hsmsiz ;
+       int hentry ;
+       int hrelb ;
+       int hrflg ;
+       } ;
+int filsiz ;
+char *entry ;
+char buf[BLKSIZ] , *namep ;
+char dbuf[BLKSIZ] ;
+short mode ;
+int addr[NADDR] ;
+int *mbap ; /* MBA ptr */
+int *RPptr ; /* RP06 ptr */
+int rpsec,rpcyl,rptrk; /* get set up in 'init' for RP06 or RM03 */
+char *bufloc;
+int dtmp1[128] , dtmp2[128] , dtmp3[128] ;
+/*
+*  This program, '/fboot', is always read in by code in the RP
+*  boot block (block 0). It boots in the file specified by the
+*  user.
+*/
+main()
+{
+/* set stack ptr and move code up to high end of core */
+reloc() ;
+/* jump to re-located code */
+asm("  .text") ;
+asm("  .globl  _main1") ;
+asm("  jmp     *$(_main1+2)") ;
+asm("  .align  2") ;
+}
+/*             */
+main1()
+{
+char ntmp[10*NAMSIZ] ;
+register int inum ;
+register struct inod *inp ;
+struct inod *getiblk() ;
+struct dirent *dsearch() , *pde ;
+int j ;
+floop :
+putnl() ;
+putstr("file : ") ;
+getcon(ntmp) ; /* null-terminated filename */
+putnl() ;
+namep = ntmp ;
+inum = ROOTINO ; /* root dir inode no. */
+while ((*namep) == SLASH) namep++ ;
+if ((*namep) == '\0') goto floop ;
+mbap = M0 ;
+RPptr = M0 + EXTREG ;
+if (init()) {
+       putlin("init error") ;
+       return(-1) ;
+       }
+giblk :
+/* get disk block that has inode entry for inode no. 'inum' */
+inp = getiblk(inum) ; /* 'cp' = ptr. to inode entry in 'buf[]' */
+if (inp == (-1)) {
+       ioerr :
+               putlin("disk i/o error") ;
+               goto floop ;
+       }
+/* Get 'mode' and 'addr[]' entries for selected inode & save off */
+iexpand(inp) ;
+/*  inode mode is in 'mode'.
+*   block no.'s are in 'addr[]'.
+*   If inode is a directory, search all its blocks for pathname
+*    component pointed to by 'namep'.
+*   If inode is regular file, load blocks of file into core
+*    for execution.
+*/
+if ((j = mode&IFMT) == IFDIR) { /* Directory */
+       if (*namep == '\0') goto floop ; /* no more pathname */
+       pde = dsearch() ; /* search all directory blocks */
+       if (pde == (-1)) goto ioerr ; /* i/o error */
+       if (pde == 0) goto floop ; /* pathname component not found */
+       /* Found pathname component (directory or file) - go get
+         its inode and continue search.
+       */
+       inum = pde->ino ;
+       goto giblk ;
+       }
+else {
+       if (j == IFREG) { /* regular file */
+               if (*namep != '\0') goto floop ; /* should have been
+                       last component in pathname */
+               if (lodfil()) goto floop ; /* load file whose
+                 inode 'addr' blocks are in 'addr[]' */
+/*
+*  Code to check for task header, move code down to 0,
+*  get task entry address, clear core, etc.
+*/
+               fexec() ;
+               goto floop ; /* returned from execution - go to loop */
+               }
+       }
+goto floop ; /* wasn't directory or file */
+}
+/*             */
+struct inod *getiblk(in)
+register int in ;
+{
+/*
+*  Read in disk inode block which contains inode
+*  no. 'in' - return ptr. to start of inode entry.
+*/
+register i ;
+i = (in + (INOBLK*2) - 1)/INOBLK ;
+if (dread(i,buf)) /*  read block 'i' into 'buf[]' */
+       return(-1) ; /* i/o error */
+return((int)buf + (((in-1) & (INOBLK-1))*INOSIZ)) ;
+}
+/*             */
+iexpand(ip)
+register struct inod *ip ;
+{
+/*
+*  Get mode, file size and block no.'s from disk inode and store
+*  away.
+*  'ip' = ptr. to inode entry.
+*/
+register int i ;
+register char *f , *t ;
+mode = ip->i_mode ;
+filsiz = ip->i_size ;
+f = (&ip->i_addr[0]) ;
+t = (&addr[0]) ;
+for (i = NADDR ; i ; i--) {
+       (*t++) = (*f++) ;
+       (*t++) = (*f++) ;
+       (*t++) = (*f++) ;
+       (*t++) = '\0' ;
+       }
+return(0) ;
+}
+/*             */
+struct dirent *dsearch()
+{
+/*
+*  Search blocks of directory inode 'inum', whose block
+*  no.'s are in 'addr[]', for pathname component pointed
+*  to by 'namep'.
+*  Return (-1) for error.
+*  Return (0)  for no match.
+*  Return ptr. to directory entry for match.
+*/
+register char c ;
+register struct dirent *cp ;
+register int i , j ;
+struct dirent *pfind() ;
+/*  direct  */
+cp = pfind(addr,NADDR-3) ; /* search 'NADDR-3' blocks(in 'naddr[]') */
+if (cp == (-1)) return(-1) ; /* i/o error */
+if (cp == 0) return(0) ;  /* zero block encountered - no more blocks */
+if (cp == 1) goto level1 ; /* more blocks to search */
+/* 'cp' must be ptr. to matched directory */
+found :
+       /*  point to next pathname component */
+while (((c = (*namep)) != '/') && (c !='\0')) namep++ ;
+if (c == '/') while (*namep == '/') namep++ ;
+return(cp) ;
+/*
+*/
+level1 : /*  1st level indirection */
+if ((j = addr[NADDR-3]) == 0) return(0) ;
+if (dread(j,dtmp1)) return(-1) ; /* i/o error */
+cp = pfind(dtmp1,128) ;
+if (cp == (-1)) return(-1) ;
+if (cp == 0) return(0) ;
+if (cp == 1) goto level2 ;
+goto found ;
+level2 :
+if ((j = addr[NADDR-2]) == 0) return(0) ;
+if (dread(j,dtmp1)) return(-1) ;
+for (i = 0 ; i < 128 ; i++) {
+       if (dtmp1[i] == 0) return(0) ;
+       if (dread(dtmp1[i],dtmp2)) return(-1) ;
+       cp = pfind(dtmp2,128) ;
+       if (cp == (-1)) return(-1) ;
+       if (cp == 0) return(0) ;
+       if (cp == 1) continue ;
+       goto found ;
+       }
+level3 :
+if ((j = addr[NADDR-1]) == 0) return(0) ;
+if (dread(j,dtmp1)) return(-1) ;
+for (i = 0 ; i < 128 ; i++) {
+       if (dread(dtmp1[i],dtmp2)) return(-1) ;
+       for (j = 0 ; j < 128 ; j++) {
+               if (dread(dtmp2[i],dtmp3)) return(-1) ;
+               cp = pfind(dtmp3,128) ;
+               if (cp == (-1)) return(-1) ;
+               if (cp == 0) return(0) ;
+               if (cp == 1) continue ;
+               goto found ;
+               }
+       }
+return(0) ;
+}
+/*             */
+struct dirent *pfind(ia,knt)
+int ia[] ;
+register int knt ;
+{
+/*
+*  'ia' :  array of integer block no.'s.
+*  'knt' :  no. entries in 'ia'
+*  A zero block in 'ia[]' -> no match -> return(0) .
+*  Return (-1) on i/o error.
+*  Return (1) if no zero blocks and all blocks searched but
+*    no match.
+*  Return ptr. to directory entry for match.
+*/
+register int *bp , bn ;
+register struct dirent *ix ;
+bp = ia ;
+while (knt--) {
+       if ((bn = (*bp++)) == 0) return(0) ;
+       if (dread(bn,dbuf)) return(-1) ;
+       for (ix = dbuf ; ix < &dbuf[BLKSIZ] ; ix++) {
+               if (dnmatch(ix->dname,namep)) return(ix) ;
+               }
+       }
+return(1) ;
+}
+/*             */
+dnmatch(p1,p2)
+register char *p1 , *p2 ;
+{
+/*
+*  'p1' : ptr. to directory filename field
+*  'p2' : ptr. to null-terminated file pathname
+*  Return(1) if match,
+*   else, return(0).
+*/
+register int i ;
+register char c1 , c2 ;
+for (i = NAMSIZ ; i ; i--) {
+       c1 = (*p1++) ;
+       c2 = (*p2++) ;
+       if (((c1 == '\0') && (c2 == '\0')) || (c2 == SLASH)) return(1) ;
+       if (c1 != c2) return(0) ;
+       }
+if ((c2 == '\0') || (c2 == SLASH)) return(1) ;
+return(0) ;
+}
+/*             */
+dread(dbn,cbuf)
+char *cbuf ;
+{
+/*
+*  Read physical block no. 'dbn' from disk and
+*    load into array 'cbuf[]'.
+*  Return (-1) for i/o error.
+*  Else return (0).
+*/
+register int i , j ;
+*(RPptr+RP_cr) = RP_DC | RP_GO ; /*  RP06 drive clear function code */
+*(RPptr+RP_cyl) = dbn/RP6ST ; /* cylinder no. */
+i = dbn%RP6ST ;
+j = (i/rpsec)<<8 ; /* track */
+*(RPptr+RP_stk) = j | (i%rpsec) ; /* sector : track */
+*(mbap+M_bc) = (-BLKSIZ) ;
+i = (int)cbuf&0777;
+*(mbap+M_var) = i ;
+*(mbap+M_map) = (i = 0x80000000 | ((int)((int)cbuf>>9)&07777777)) ;
+*(mbap+M_map+1) = (++i) ;
+*(RPptr+RP_cr) = RP_RED | RP_GO ; /* read */
+dwait() ; /* wait for i/o to finish */
+if (derror()) { /* error */
+       putlin("fboot : disk read error");
+       return(-1);
+       }
+return(0) ; /* normal return */
+}
+/*             */
+dwait() {
+/*
+* Function to wait MBA 0 RP06 disc unit to be ready.
+*/
+while ((*(RPptr+RP_sr)&RP_DRY) == 0) ;
+}
+/*             */
+derror()
+{
+/*
+*  Function to check for MBA 0 RP06 error.
+*/
+if (*(RPptr+RP_sr) & RP_ERR) return(-1) ;
+return(0) ;
+}
+/*             */
+init()
+{
+/*
+*  Initialization.
+*/
+register int i;
+*(mbap+M_cr) = MBAinit ; /* MBA initialize */
+if ((*(RPptr+RP_sr) & RP_MOL) == 0 ){
+       putlin("unit not online") ;
+       return(-1) ;
+       }
+*(RPptr+RP_cr) = RP_RIP | RP_GO ; /* readin preset */
+*(RPptr+RP_off) = RP_FMT ; /* format bit in offset reg */
+bufloc = 0 ;
+i = *(RPptr+RP_typ)&0777 ;  /* get disk type */
+if (i==RP6typ) { /* RP06 */
+       rpsec=RP6SEC; rpcyl=RP6CYL; rptrk=RP6TRK;
+       }
+else {
+       if (i==RM3typ) {
+               rpsec=RM3SEC; rpcyl=RM3CYL; rptrk=RM3TRK;
+               }
+       else return(-1);
+       }
+return(0) ;
+}
+/*             */
+lodfil()
+{
+/*
+*  Function to load a file into low core - disk blocks no.'s
+*  which comprise file are in 'addr[]'.
+*  Return (-1) if i/o error,
+*  else return (0).
+*/
+register int i , j , k , n ;
+int dtmp1[128] , dtmp2[128] ;
+/*  direct  */
+for (i = 0 ; i < NADDR-3 ; i++) {
+       if ((j = addr[i]) == 0) return(0) ;
+       if (dread(j,bufloc)) return(-1) ;
+       bufloc += BLKSIZ ;
+       }
+level1 : /*  1st level indirection */
+if ((j = addr[NADDR-3]) == 0) return(0) ;
+/*  read in <=128 blocks into low core */
+if ((k = r128(j)) < 0) return(-1) ; /* i/o error */
+if (k > 0) return(0) ; /* no more blocks */
+level2 :
+if ((j = addr[NADDR-2]) == 0) return(0) ;
+if (dread(j,dtmp1)) return(-1) ;
+for (i = 0 ; i < 128 ; i++) {
+       if ((j = dtmp1[i]) == 0) return(0) ;
+       if ((k = r128(j)) < 0) return(-1) ;
+       if (k > 0) return(0) ;
+       }
+level3 :
+if ((j = addr[NADDR-1]) == 0) return(0) ;
+if (dread(j,dtmp1)) return(-1) ;
+for (i = 0 ; i < 128 ; i++) {
+       if ((k = dtmp1[i]) == 0) return(0) ;
+       if (dread(k,dtmp2)) return(-1) ;
+       for (j = 0 ; j < 128 ; j++) {
+               if ((k = dtmp2[j]) == 0) return(0) ;
+               if ((n = r128(k)) < 0) return(-1) ;
+               if (n > 0) return(0) ;
+               }
+       }
+return(0) ;
+}
+/*             */
+r128(blk)
+int blk ;
+{
+/*
+*  Read in disk block no. 'blk' into buffer.
+*  Then read in the 128 disk blocks whose block no.'s are
+*  in the buffer into low core.
+*  Stop on a zero block no. - return(1).
+*  Return(-1) on i/o error.
+*  Return(0) if all 128 blocks read.
+*/
+int btmp[128] ;
+register int i , j ;
+if (dread(blk,btmp)) return(-1) ;
+for (i = 0 ; i < 128 ; i++) {
+       if ((j = btmp[i]) == 0) return(1) ; /* no more blocks */
+       if (dread(j,bufloc)) return(-1) ; /* i/o error */
+       bufloc += BLKSIZ ; /* next core block loc */
+       }
+return(0) ;
+}
+/*             */
+halt() {
+       asm("   halt") ;
+}
+/*             */
+putstr(csp)
+register char *csp ;
+{
+if (putcon(csp)) return(-1) ;
+return(0) ;
+}
+/*             */
+putlin(sptr)
+register char *sptr ;
+{
+if (putcon(sptr)) return(-1) ;
+if (putnl()) return(-1) ;
+return(0) ;
+}
+/*             */
+nullcon(nn)
+register nn ;
+{
+/*
+*  Output 'nn' nulls to console terminal -
+*  used for delay.
+*/
+while (nn--) putc(0) ;
+}
+/*             */
+putnl()
+{
+if (putcon("\r\n")) return(-1) ;
+return(0) ;
+}
+/*             */
+putcon(csp)
+register char *csp ;
+{
+/*
+*  Function to output null-terminated string pointed to 
+*  by 'csp' to the VAX LSI terminal.
+*/
+register c ;
+c = 0 ;
+while (c = (*csp++)) putc(c) ;
+return(0) ;
+}
+/*             */
+putc(c)
+{
+/*  wait for LSI printer to be ready */
+while ((mfpr(TXCS) & TXCS_RDY) == 0) ;
+/*  output character */
+mtpr(TXDB,c&0177) ;
+}
+/*             */
+getcon(cs)
+register char *cs ;
+{
+/*
+*  Function to return char's from VAX LSI keyboard to
+*  char array 'cs' - input stops when CR or LF received -
+*  null char appended to end of input
+*/
+register int c , c2 ;
+int getc() ;
+char *ocs;
+       ocs=cs;
+inloop :
+       c = getc() ; /* get 1 char from terminal */
+       putc(c) ;  /*  echo char */
+       if (c==CDEL) {cs--; goto inloop;}
+       if (c==LDEL) {putc(CR);putc(0);putc(NL);cs=ocs; goto inloop;}
+       if ((c == NL) || (c == CR)) {
+               putc(CR) ;
+               putc(0);
+               putc(NL) ;
+               (*cs++) = '\0' ;
+               return(0) ;
+               }
+       else {
+               (*cs++) = c ;
+               goto inloop ;
+               }
+}
+/*             */
+getc()
+{
+/*
+*  Return char from VAX LSI terminal char buffer
+*/
+int mfpr() ;
+/*  Wait for receiver done (user entered char)
+*/
+while ((mfpr(RXCS) & RXCS_DONE) == 0) ;
+return (mfpr(RXDB) & 0177) ;  /* return char from receiver buffer */
+}
+/*             */
+mtpr(regno,value)
+{
+       asm("   mtpr    8(ap),4(ap)") ;
+}
+/*             */
+mfpr(regno)
+{
+       asm("   mfpr    4(ap),r0") ;
+}
+/*             */
+a2l(as)
+register char *as ;
+{
+/*
+*  Convert null-terminated ascii string to binary
+*  and return value.
+*  1st char in string :
+*      0 -> octal
+*      x -> hex
+*      else decimal
+*/
+register value , base , sign , digit ;
+digit = value = sign = 0 ;
+base = 10 ;  /* default base */
+aloop :
+if ((digit = (*as++)) == 0) return(value) ; /* null */
+if (digit == '-') {
+       sign++ ;
+       goto aloop ;
+       }
+if (digit == '0') base = 8 ;  /* octal base  */
+else { if (digit == 'x') base = 16 ;  /* hex base */
+       else value = (digit-060) ; /* 060 = '0' */
+       }
+while (digit = (*as++)) {
+       if (digit < '0') return(0) ;
+       switch (base) {
+               case 8 : {
+                       if (digit > '7') return(0) ;
+                       digit -= 060 ;
+                       break ;
+                       }
+               case 10 : {
+                       if (digit > '9') return(0) ;
+                       digit -= 060 ;
+                       break ;
+                       }
+               case 16 : {
+                       if (digit <= '9') {
+                               digit -= 060 ;
+                               break ;
+                               }
+                       if ((digit >= 'A') && (digit <= 'F')) {
+                               digit = (digit - 0101 + 10) ;
+                                       break ;
+                               }
+                       if ((digit >= 'a') && (digit <= 'f')) {
+                               digit = digit - 0141 + 10 ;
+                               break ;
+                               }
+                       return(0) ;
+                       break ;
+                       }
+               }
+       value = (value * base) + digit ;
+       }
+return (sign ? -value : value) ;
+}
+/*             */
+l2a(val,rptr)
+register int val ;
+register char *rptr ;
+{
+register int i ;
+register char *tp ;
+int knt ;
+char tmp[20] , sign ;
+knt = sign = 0 ;
+if (val < 0) {
+       sign++ ;
+       val = (-val) ;
+       }
+tp = tmp ;
+loop :
+       knt++ ;
+       i = val/10  ;  /*  quotient & base 10 */
+       (*tp++) = val%10 + '0' ; /*  ascii remainder  */
+       val = i ;
+       if (val == 0) {
+               /*  done  dividing  */
+               if (sign) { knt++ ; (*tp++) = '-' ; }
+               for (i = knt ; i ; i--)
+                       (*rptr++) = tmp[i-1] ;
+               (*rptr++) = '\0' ;
+               return(knt) ;
+               }
+       else goto loop ;
+}
+/*             */
+fexec()
+{
+/*
+*  Part of stand-alone programs that load programs into low core
+*  and execute them.
+*  This function :
+*      1) Checks if user specified file has a header - if so,
+*         move start of exec. file down to 0. If file is 0410,
+*         move data up to page boundary.
+*      2) Clear core.
+*      3) Jump to user task (calls).
+*/
+register struct thdr *hdp ;
+register char *corep1 , * corep2 ;
+register int k ;
+int i , stxt , sdat , sbss , clrmin ;
+register char *clrmax ;
+hdp = 0 ;
+clrmax = RELOC - 0x400 ; /* last addr+1 to clear */
+i = hdp->hmagic ; /* task type code from task header */
+entry = 0 ; /* default entry addr if no header */
+clrmin = filsiz ;
+if ((i != MAG410) && (i != MAG411)) goto clrcor ; /* NO HEADER */
+/* file has task header */
+entry = hdp->hentry & 017777777777 ;
+stxt = hdp->htsiz ; /* no. of text bytes in file */
+sdat = hdp->hdsiz ; /* no. data bytes */
+sbss = hdp->hbsiz ; /* no. bytes in bss area */
+filsiz = stxt + sdat ; /* file size = text + data */
+clrmax = filsiz + sbss ; /* new upper limit to clear */
+/*  move file down to loc 0 */
+corep1 = 0 ;
+corep2 = sizeof(struct thdr) ;
+for (k = filsiz ; k ; k--)
+       (*corep1++) = (*corep2++) ;
+clrmin = stxt ;
+/* If 0410 file , move data up to page boundary */
+if ((i == MAG410) && sdat ) { /*  0410  */
+       i = corep2 = ((stxt + 511) & 017777777000) ; /* page boundary */
+       corep2 += sdat ; /* end+1 of new data area */
+       corep1 = filsiz ; /* end+1 of current data area */
+       for (k = sdat ; k ; k--) /* move data up */
+               *(--corep2) = *(--corep1) ;
+       clrmax += (i-stxt) ; /* adjust upper limit for moved data */
+       clrmin = i + sdat ;
+       }
+/*  clear  core  */
+clrcor :
+for (corep1 = clrmin ; corep1 < clrmax ; corep1++)
+       *corep1 = 0 ;
+/*  execute  user  task  */
+asm("  .globl  _entry") ;
+asm("  calls   $0,*_entry") ;
+/*             */
+return(0) ;
+}
+/*             */
+reloc()
+{
+extern edata ;
+register int *to , *from , i ;
+mtpr(KSP,RELOC) ; /* set stack */
+from = 0 ;
+to = RELOC ;
+for (i = (int)&edata-RELOC ; i > 0 ; i -= (sizeof *from))
+       (*to++) = (*from++) ;
+}
+/*             */
+l2x(val,rptr)
+register int val ;
+register char *rptr ;
+{
+register int i , j ;
+register char *tp ;
+int knt ;
+char tmp[20] , sign ;
+knt = sign = 0 ;
+if (val < 0) {
+       sign++ ;
+       val = (-val) ;
+       }
+tp = tmp ;
+loop :
+       knt++ ;
+       i = val/16  ;  /*  quotient & base 16 */
+       j = val%16 ;
+       (*tp++) = j + (j<10?0x30:0x57) ;
+       val = i ;
+       if (val == 0) {
+               /*  done  dividing  */
+               if (sign) { knt++ ; (*tp++) = '-' ; }
+               for (i = knt ; i ; i--)
+                       (*rptr++) = tmp[i-1] ;
+               (*rptr++) = '\0' ;
+               return(knt) ;
+               }
+       else goto loop ;
+}