echo x - Makefile
sed '/^X/s///' > Makefile << '/'
XCFLAGS= -c -LIB -D_MINIX -D_POSIX_SOURCE
X
Xall:
X	@$(CC) $(CFLAGS) *.c *.s
X
Xclean:	
X	@rm -f peekpoke.s portio.s *.bak
/
echo x - __sigreturn.s
sed '/^X/s///' > __sigreturn.s << '/'
X.define ___sigreturn
X.extern __sigreturn
X___sigreturn: 
Xadd sp, #4
Xj __sigreturn
/
echo x - _sendrec.s
sed '/^X/s///' > _sendrec.s << '/'
X.define __send, __receive, __sendrec
XSEND = 1
XRECEIVE = 2
XBOTH = 3
XSYSVEC = 32
X.extern __send, __receive, __sendrec
X__send: mov cx,*SEND
Xj L0
X__receive: 
Xmov cx,*RECEIVE
Xj L0
X__sendrec: 
Xmov cx,*BOTH
Xj L0
XL0: push bp
Xmov bp,sp
Xmov ax,4(bp)
Xmov bx,6(bp)
Xint SYSVEC
Xpop bp
Xret
/
echo x - brksize.s
sed '/^X/s///' > brksize.s << '/'
X.define __brksize
X.data
X.extern endbss, __brksize
X__brksize: .word  endbss
/
echo x - crtso.s
sed '/^X/s///' > crtso.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
X.globl _main, _exit, crtso, _environ
X.globl 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	_environ,ax	| save envp in environ
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_environ:	.word 0
X.bss
Xbegbss:
/
echo x - end.s
sed '/^X/s///' > end.s << '/'
X.globl endtext, enddata, endbss, _end, _edata
X.text
Xendtext:
X.data
Xenddata:
X_edata:
X.bss
Xendbss:
X_end:
/
echo x - head.s
sed '/^X/s///' > head.s << '/'
X.globl _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.word 0xDADA			| magic number for build
X.word 8				| CLICK_SHIFT to check - must match h/const.h
X.word 0,0,0			| used by FS only for sizes of init
X				| stack for separate I&D follows
X.word 0,0,0			| for ip:ss:f pushed by debugger traps
X.word 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.word 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.define _setjmp, _longjmp, __longjmp
X.extern _setjmp, _longjmp, __longjmp
X.extern _sigprocmask
X.extern __longjerr
X.extern __sigjmp
X.extern .sti, .gto
X.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 or three arguments. If called with three
X| arguments, the second argument should be 0 or 1, and if it is 0,
X| the signal context should not be restored on the longjmp.
X| The last argument is added by the compiler, | which recognizes the
X| "setjmp" identifier and adds an extra parameter: the | return address
X| (there is no portable way to obtain this in the compiler intermediate code).
X|
X| _setjmp(jmp_buf, 0/1, retaddr)
X| or
X| _setjmp(jmp_buf, 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	2(bp)		| program counter; take it from the return
X				| area. We could also get it from either
X				| 6(bp) or 8(bp), but this is faster.
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	xor	ax, ax
X	push	ax
X	push	ax
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	mov	sp,bp
X	pop	bp
X	ret
X
X|
X| _longjmp() should be called for a setjmp() call that did not save the
X| signal context.
X|
X
X__longjmp:
X	push	bp
X	mov	bp, sp
X
X	mov	bx,4(bp)
X
X| Check that this jmp_buf has no saved registers.
X	mov 	ax, (bx)		| 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	add	bx, *6
X	jmp	.gto
X
X|
X| longjmp() should be called for a setjmp() call that DID save the
X| signal context.
X|
X
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, (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	bx
X	call	__sigjmp
X	add	sp, *4
/
