echo x - Makefile
sed '/^X/s///' > Makefile << '/'
XCFLAGS= -c -O -D_MINIX -D_POSIX_SOURCE
X
Xall:
X	@$(CC) $(CFLAGS) *.c *.s
X
Xclean:	
X	@rm -f *.o *.bak
/
echo x - __sigreturn.s
sed '/^X/s///' > __sigreturn.s << '/'
X! This routine is the low-level code for returning from signals.  
X! It calls __sigreturn, which is the normal "system call" routine.
X! Both ___sigreturn and __sigreturn are needed.
X.sect .text; .sect .rom; .sect .data; .sect .bss
X.sect .text
X.define ___sigreturn
X.extern __sigreturn
X___sigreturn:
X	add sp, #4
X	jmp __sigreturn
/
echo x - _sendrec.s
sed '/^X/s///' > _sendrec.s << '/'
X.define __send, __receive, __sendrec
X
X! See ../h/com.h for C definitions
XSEND = 1
XRECEIVE = 2
XBOTH = 3
XSYSVEC = 32
X
X!*========================================================================*
X!                           _send and _receive                            *
X!*========================================================================*
X! _send(), _receive(), _sendrec() all save bp, but destroy ax, bx, and cx.
X.extern __send, __receive, __sendrec
X__send:	mov cx,*SEND		! _send(dest, ptr)
X	jmp L0
X
X__receive:
X	mov cx,*RECEIVE		! _receive(src, ptr)
X	jmp L0
X
X__sendrec:
X	mov cx,*BOTH		! _sendrec(srcdest, ptr)
X	jmp L0
X
X  L0:	push bp			! save bp
X	mov bp,sp		! can't index off sp
X	mov ax,4(bp)		! ax = dest-src
X	mov bx,6(bp)		! bx = message pointer
X	int SYSVEC		! trap to the kernel
X	pop bp			! restore bp
X	ret			! return
X
/
echo x - brksize.s
sed '/^X/s///' > brksize.s << '/'
X.define __brksize
X.data
X.extern endbss, __brksize
X__brksize: .data2 endbss
/
echo x - ncrtso.s
sed '/^X/s///' > ncrtso.s << '/'
X! This is the C run-time start-off routine.  It's job is to take the
X! arguments as put on the stack by EXEC, and to parse them and set them up the
X! way _main expects them.
X! It also initializes _environ when this variable isn't defined by the
X! programmer.  The detection of whether _environ belong to us is rather
X! simplistic.  We simply check for some magic value, but there is no other
X! way.
X
X.extern _main, _exit, crtso, __penvp
X.extern begtext, begdata, begbss, endtext, enddata, endbss
X.text
Xbegtext:
Xcrtso:		mov	bx,sp
X		mov	cx,(bx)
X		add	bx,*2
X		mov	ax,cx
X		inc	ax
X		shl	ax,#1
X		add	ax,bx
X		mov	__penvp,ax	! save envp in __envp
X
X		! Test whether address of environ < address of end.
X		! This is done for separate I&D systems.
X		mov	dx,#_environ
X		cmp	dx,#__end
X		jae	1f
X		cmp	_environ,#21331		! is it our _environ?
X		jne	1f
X		mov	_environ,ax
X1:
X		push	ax	! push environ
X		push	bx	! push argv
X		push	cx	! push argc
X		xor	bp,bp	! clear bp for traceback of core files
X		call	_main
X		add	sp,*6
X		push	ax	! push exit status
X		call	_exit
X
X.data
Xbegdata:
X__penvp:	.data2 0
X.bss
Xbegbss:
/
echo x - nhead.s
sed '/^X/s///' > nhead.s << '/'
X.extern _main, _stackpt, begtext, begdata, begbss, _data_org, _exit, .fat, .trp
X.text
Xbegtext:
X	jmp L0
X	.zerow 13		! stack for inital IRET when common I&D
X				! also padding to make INIT_SP same as
X				! for separate I&D
XL0:	mov sp,_stackpt
X	call _main
X_exit:				! dummy for library functions - never executed
X.fat:				! dummy
X.trp:				! dummy
XL1:	jmp L1			! this should never be executed either
X.data
Xbegdata:
X_data_org:			! fs needs to know where build stuffed table
X.data2 0xDADA			! magic number for build
X.data2 8			! CLICK_SHIFT to check - must match h/const.h
X.data2 0,0,0			! used by FS only for sizes of init
X				! stack for separate I&D follows
X.data2 0,0,0			! for ip:ss:f pushed by debugger traps
X.data2 0,0,0			! for cs:ds:ret adr in save()
X				! this was missing - a bug as late as V1.3c
X				! for ds for new restart() as well
X.data2 0,0,0			! for ip:ss:f built by restart()
X				! so INIT_SP in const.h must be 0x1C
X.bss
Xbegbss:
/
echo x - peekpoke.c
sed '/^X/s///' > peekpoke.c << '/'
X/* Peek and poke using /dev/mem.
X *
X * Callers now ought to check the return values.
X *
X * Calling peek() requires read permission on /dev/mem, and consumes
X * a file descriptor.  Calling poke() requires write permission, and
X * consumes another file descriptor.
X */
X
X#include <sys/types.h>
X#include <fcntl.h>
X#include <unistd.h>
X
X_PROTOTYPE( int peek, (unsigned segment, unsigned offset));
X_PROTOTYPE( int poke, (unsigned segment, unsigned offset, unsigned value));
X
X#define SEGSIZE 0x10
X
Xint peek(segment, offset)
Xunsigned segment;
Xunsigned offset;
X{
X  unsigned char chvalue;
X  static int infd = -1;
X
X  if (infd < 0) infd = open("/dev/mem", O_RDONLY);
X  if (infd < 0 ||
X      lseek(infd, (unsigned long) segment * SEGSIZE + offset, SEEK_SET) < 0 ||
X      read(infd, (char *) &chvalue, (unsigned) 1) != 1)
X	return(-1);
X  return(chvalue);
X}
X
Xint poke(segment, offset, value)
Xunsigned segment;
Xunsigned offset;
Xunsigned value;
X{
X  unsigned char chvalue;
X  static int outfd = -1;
X
X  chvalue = value;
X  if (outfd < 0) outfd = open("/dev/mem", O_WRONLY);
X  if (outfd < 0 ||
X      lseek(outfd, (unsigned long) segment * SEGSIZE + offset, SEEK_SET) < 0 ||
X      write(outfd, (char *) &chvalue, (unsigned) 1) != 1)
X	return(-1);
X  return(chvalue);
X}
/
echo x - portio.c
sed '/^X/s///' > portio.c << '/'
X/* Port i/o functions using /dev/port.
X * Callers now ought to check the return values.
X * Calling either of these functions consumes a file descriptor.
X */
X
X#include <lib.h>
X#include <sys/types.h>
X#include <fcntl.h>
X#include <unistd.h>
X
X_PROTOTYPE( int port_in, (unsigned port, unsigned *valuep));
X_PROTOTYPE( int port_out, (unsigned port, unsigned value));
X
X#define P_READ 1
X#define P_WRITE 2
X
XPRIVATE int portfd = -1;
XPRIVATE int mode_opened = 0;
X
Xint port_in(port, valuep)
Xunsigned port;
Xunsigned *valuep;
X{
X  unsigned char chvalue;
X
X  if ( !( mode_opened & P_READ )) {
X     if ( mode_opened & P_WRITE ) {
X        close(portfd);
X        portfd = open("/dev/port", O_RDWR);
X      }
X      else {
X        portfd = open("/dev/port", O_RDONLY);
X      }
X      mode_opened |= P_READ ;
X    }
X
X  if (portfd < 0 ||
X      lseek(portfd, (long) port, 0) < 0 ||
X      read(portfd, (char *) &chvalue, (size_t) 1) != 1)
X	return(*valuep = -1);
X  return(*valuep = chvalue);
X}
X
Xint port_out(port, value)
Xunsigned port;
Xunsigned value;
X{
X  unsigned char chvalue;
X
X  chvalue = value;
X  if ( !( mode_opened & P_WRITE )) {
X     if ( mode_opened & P_READ ) {
X        close(portfd);
X        portfd = open("/dev/port", O_RDWR);
X      }
X      else {
X        portfd = open("/dev/port", O_WRONLY);
X      }
X      mode_opened |= P_WRITE ;
X    }
X
X  if (portfd < 0 || lseek(portfd, (long) port, 0) < 0 ||
X      write(portfd, (char *) &chvalue, (size_t) 1) != 1)
X	return(-1);
X  return(chvalue);
X}
/
echo x - setjmp.s
sed '/^X/s///' > setjmp.s << '/'
X.sect .text; .sect .data; .sect .bss
X.sect .bss
X.comm _gtobuf, 12
X.extern ___setjmp
X.extern _sigprocmask
X.extern __longjerr
X.extern __sigjmp
X.extern _printf, _exit
X.extern .blm, .sti, .cret
X.sect .text
X!
X! Warning:  this code depends on the C language declaration of
X! jmp_buf in <setjmp.h>, and on the definitions of the flags
X! SC_ONSTACK, SC_SIGCONTEXT, and SC_NOREGLOCALS in <sys/sigcontext.h>.
XSC_SIGCONTEXT=2
XSC_NOREGLOCALS=4
X!
X! ___setjmp is called with two arguments.  The third argument is pushed
X! by compiler generated code transparently to the caller.
X!
X! ___setjmp(jmp_buf, savemask, retaddr)
X!
X___setjmp:
X	push	bp
X	mov	bp,sp
X
X	push	0(bp)		! frame pointer
X	lea	ax, 4(bp)
X	push	ax		! stack pointer
X	push	8(bp)		! program counter
X	
X	xor	ax, ax
X	push	ax		! signal mask high
X	push	ax		! signal mask low
X	mov	ax,#SC_NOREGLOCALS	! flags (4 is SC_NOREGLOCALS)
X	push	ax
X
X	mov	ax, 6(bp)	! get the savemask arg
X	cmp	ax, #0
X	je	nosigstate	! don't save signal state
X
X	or	-12(bp), #SC_SIGCONTEXT		! flags |= SC_SIGCONTEXT
X
X	lea	ax, -10(bp)
X	push	ax
X	push	#0
X	push	#0
X	call	_sigprocmask	! fill in signal mask
X	add	sp, #6
X
Xnosigstate:
X	mov	bx, 4(bp)	! jmp_buf
X	mov	cx, #12		! sizeof(jmp_buf)
X	call	.sti		! sp = src addr, bx = dest addr, cx = count
X	xor	ax, ax
X	jmp	.cret
X
X.extern __longjmp
X__longjmp:
X	push	bp
X	mov	bp, sp
X
X! Copy the jmp_buf to the gtobuf.
X	push	4(bp)			! src address
X	mov	ax, #_gtobuf
X	push	ax			! dst address
X	mov	cx, #6			! word count
X	call	.blm			! block move			
X
X! Check that this jmp_buf has no saved registers.
X	mov 	ax, _gtobuf		! get flags
X	test 	ax, #4
X	je	__longjerr
X
X! Set up the value to return in ax.
X	mov	ax, 6(bp)		! value to return
X	or	ax, ax
X	jne	nonzero
X	mov	ax, #1
Xnonzero:
X	mov	bx, #_gtobuf
X	mov	bp, 10(bx)
X	mov	sp, 8(bx)
X	jmp	@6(bx)
X
X.extern _longjmp
X_longjmp:
X	push	bp
X	mov	bp, sp
X
X! Check that this is a jmp_buf with no saved regs and with signal context info.
X	mov	bx, 4(bp)		! pointer to jmp_buf
X	mov	ax, 0(bx)		! get the flags
X	test 	ax, #4			! check for no saved registers
X	je	__longjerr
X	test	ax, #2			! check for signal context
X	je	__longjerr
X	
X! Compute the value to return
X	mov	ax, 6(bp)		! proposed value to return
X	or	ax, ax
X	jne	nonzero1
X	mov	ax, #1
Xnonzero1:
X
X! Call _sigjmp to restore the old signal context.
X	push	ax
X	push	4(bp)
X	call	__sigjmp
X	add	sp, #4
/
