Selaa lähdekoodia

Initial revision

sater 40 vuotta sitten
vanhempi
commit
2af94af5c6

+ 4 - 0
mach/z80/int/Makefile

@@ -0,0 +1,4 @@
+CFLAGS=-O
+
+dl:	dl.o
+	cc -n -o dl dl.o

+ 23 - 0
mach/z80/int/READ_ME

@@ -0,0 +1,23 @@
+The interpreter contained here is tested under CP/M on a RC702 Z80
+microcomputer. Make it by typing `doas'.
+E.out files to interpret must be made with a special Pascal library
+using whatever means available, because the UNIX and CP/M conventions
+about end of file and end of line differ.
+Then the following sequence can be used to transmit it to CP/M.
+cv <e.out >file.cv
+dl file.cv file.hex
+< Transmission to file.hex under CP/M using pip >
+LOAD FILE
+
+The resulting file.com can be used as an argument to the interpreter.
+This implementation has been tested but is not guaranteed to be complete.
+Simple UNIX-system calls have been implemented but anything except
+terminal I/O has not been thoroughly tested.
+Please send any errors in the implementation to
+Hans van Staveren
+Vrije Universiteit
+Wiskundig Seminarium
+De Boelelaan 1081
+1081 HV  Amsterdam
+Holland
+..!decvax!mcvax!vu44!sater

+ 280 - 0
mach/z80/int/atof.s

@@ -0,0 +1,280 @@
+	.data
+! Set of variables
+
+big:	.byte 0
+	.byte 0
+	.byte 0x40
+	.byte 24	! 2^23
+negfrac:.space 1
+negexp:	.space 1
+begzero:
+nd:	.space 2
+fl:	.space 6
+	exp=fl+4
+eexp:	.space 2
+flexp:	.space 4
+exp5:	.space 4
+endzero:
+ten:	.byte 0
+	.byte 0
+	.byte 0x50
+	.byte 4		! 10
+dig:	.byte 0
+	.byte 0
+fildig:	.byte 0		! here a number from 0 to 31 will be converted flt.
+	.byte 7
+bexp:	.space 2
+
+	.text
+atof:			! entry with stringpointer in hl
+			! exit with pointer to float in hl
+	push ix
+	push iy
+	push bc
+	push de
+	push af
+	ld b,1
+1:
+	ld a,(hl)
+	inc hl
+	cp ' '
+	jr z,1b
+	cp '-'
+	jr nz,1f
+	ld b,-1
+	jr 2f
+1:	cp '+'
+	jr z,2f
+	dec hl
+2:	ld a,b
+	ld (negfrac),a
+	xor a
+	ld de,begzero
+	ld b,endzero-begzero
+1:	ld (de),a
+	inc de
+	djnz 1b
+1:	ld a,(hl)
+	inc hl
+	sub '0'
+	jr c,1f
+	cp 10
+	jr nc,1f
+	ld (fildig),a
+	call cmpbigfl
+	jr z,2f
+	call mulandadd
+	jr 3f
+2:	ld de,(exp)
+	inc de
+	ld (exp),de
+3:	ld de,(nd)
+	inc de
+	ld (nd),de
+	jr 1b
+1:	cp '.'-'0'
+	jr nz,4f
+1:	ld a,(hl)
+	inc hl
+	sub '0'
+	jr c,4f
+	cp 10
+	jr nc,4f
+	ld (fildig),a
+	call cmpbigfl
+	jr z,2f
+	call mulandadd
+	ld de,(exp)
+	dec de
+	ld (exp),de
+2:	ld de,(nd)
+	inc de
+	ld (nd),de
+	jr 1b
+4:
+	ld b,1
+	cp 'E'-'0'
+	jr z,1f
+	cp 'e'-'0'
+	jr nz,5f
+1:	ld a,(hl)
+	inc hl
+	cp '+'
+	jr z,1f
+	cp '-'
+	jr nz,2f
+	ld b,-1
+	jr 1f
+2:	dec hl
+1:	ld a,b
+	ld (negexp),a
+	exx
+	xor a
+	ld h,a
+	ld l,a
+	ld b,a
+	ld d,a
+	ld e,a
+	exx
+1:	ld a,(hl)
+	inc hl
+	sub '0'
+	jr c,1f
+	cp 10
+	jr nc,1f
+	exx
+	ld c,a
+	add hl,hl
+	add hl,hl
+	add hl,de
+	add hl,hl
+	add hl,bc
+	ld d,h
+	ld e,l
+	exx
+	jr 1b
+1:	exx
+	ld hl,negexp
+	or a
+	bit 7,(hl)
+	ld hl,(exp)
+	jr z,1f
+	sbc hl,de
+	jr 2f
+1:	add hl,de
+2:	ld (exp),hl
+	exx
+5:	ld a,1
+	ld de,(exp)
+	push de
+	bit 7,d
+	jr z,1f
+	neg
+	ld hl,0
+	or a
+	sbc hl,de
+	ex de,hl
+1:	ld (negexp),a
+	ld (exp),de
+	pop de
+	ld hl,(nd)
+	add hl,de
+	ld de,-33		! -LOGHUGE ?
+	xor a
+	sbc hl,de
+	jp p,1f
+	ld hl,fl
+	ld b,6
+2:	ld (hl),a
+	inc hl
+	djnz 2b
+1:	ld hl,0x0140	! 1.0
+	ld (flexp+2),hl
+	ld hl,0x0350	! 5.0
+	ld (exp5+2),hl
+	ld hl,(exp)
+	ld (bexp),hl
+1:	bit 0,l
+	jr z,2f
+	call xflt
+	.word flexp,exp5,fpmult,4,flexp
+2:	sra h
+	rr l
+	ld a,h
+	or l
+	jr z,3f
+	call xflt
+	.word exp5,exp5,fpmult,4,exp5
+	jr 1b
+3:	ld hl,negexp
+	ld a,(bexp)
+	bit 7,(hl)
+	jr z,1f
+	call xflt
+	.word flexp,fl,fpdiv,4,fl
+	neg
+	jr 2f
+1:	call xflt
+	.word flexp,fl,fpmult,4,fl
+2:	ld b,a
+	ld a,(fl+3)
+	add a,b
+	ld (fl+3),a
+	ld a,(negfrac)
+	bit 7,a
+	jr z,1f
+	call xflt
+	.word fl,fl,fpcomp,4,fl
+1:	call xflt
+	.word fl,fl,fpnorm,4,fl
+	ld hl,fl
+	pop af
+	pop de
+	pop bc
+	pop iy
+	pop ix
+	ret
+
+cmpbigfl:
+	call xflt
+	.word big,fl,fpcmf,0
+	ld a,(fpac+1)
+	bit 7,a
+	ret
+mulandadd:
+	call xflt
+	.word fl,ten,fpmult,4,fl
+	ld a,7
+	ld (fildig+1),a
+	call xflt
+	.word dig,dig,fpnorm,4,dig
+	call xflt
+	.word fl,dig,fpadd,4,fl
+	ret
+
+xflt:
+	ex (sp),iy
+	push af
+	push bc
+	push de
+	push hl
+	ld h,(iy+1)
+	ld l,(iy+0)
+	ld de,fpac
+	ld bc,4
+	ldir
+	ld h,(iy+3)
+	ld l,(iy+2)
+	ld de,fpop
+	ld bc,4
+	ldir
+	push iy
+	ld hl,1f
+	push hl
+	ld h,(iy+5)
+	ld l,(iy+4)
+	jp (hl)
+1:	pop iy
+	ld b,(iy+7)
+	ld c,(iy+6)
+	ld a,b
+	or c
+	jr z,1f
+	inc iy
+	inc iy
+	ld hl,fpac
+	ld d,(iy+7)
+	ld e,(iy+6)
+	ldir
+1:	push iy
+	pop hl
+	ld de,8
+	add hl,de
+	push hl
+	pop iy
+	pop hl
+	pop de
+	pop bc
+	pop af
+	ex (sp),iy
+	ret

+ 34 - 0
mach/z80/int/cv.c

@@ -0,0 +1,34 @@
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include <stdio.h>
+
+unsigned memaddr = 0x100;
+
+main() {
+	char buf[256];
+	register i,len;
+
+	while((len=read(0,buf,sizeof(buf))) > 0) {
+		putw(memaddr,stdout);
+		putw(0,stdout);
+		putw(len,stdout);
+		memaddr += len;
+		for(i=0;i<len;i++)
+			putc(buf[i],stdout);
+	}
+}

+ 200 - 0
mach/z80/int/dl.c

@@ -0,0 +1,200 @@
+/*
+ * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ *
+ *          This product is part of the Amsterdam Compiler Kit.
+ *
+ * Permission to use, sell, duplicate or disclose this software must be
+ * obtained in writing. Requests for such permissions may be sent to
+ *
+ *      Dr. Andrew S. Tanenbaum
+ *      Wiskundig Seminarium
+ *      Vrije Universiteit
+ *      Postbox 7161
+ *      1007 MC Amsterdam
+ *      The Netherlands
+ *
+ */
+
+#include	<sgtty.h>
+#include	<stdio.h>
+#include	<assert.h>
+
+struct sgttyb	tty;
+
+#define	DATTYPE		0
+#define	EOFTYPE		1
+#define	SEGTYPE		2
+#define	PCTYPE		3
+
+#define	MAXBYTE		32
+
+int	check;
+int	echo;
+int	istty;
+int	bytecount;
+int	ttyfd;
+
+char	*progname;
+
+char	hex[] = "0123456789ABCDEF";
+
+main(argc,argv) char **argv; {
+	register nd,pc,sg,osg,first;
+	register char *s;
+	int uid;
+
+	progname = argv[0];
+	if (argc > 3)
+		fatal("usage: %s [object [tty]]\n",argv[0]);
+	s = "a.out";
+	if (argc >= 2)
+		s = argv[1];
+	if (freopen(s,"r",stdin) == NULL)
+		fatal("can't open %s",s);
+	s = "/dev/tty05";
+	if (argc >= 3)
+		s = argv[2];
+	if ((ttyfd = open(s,2)) < 0)
+		if ((ttyfd = creat(s,0666)) < 0)
+			fatal("can't open %s",s);
+	if (gtty(ttyfd,&tty) == 0) {
+		echo++;
+		istty++;
+		tty.sg_ispeed = tty.sg_ospeed = B2400;
+		tty.sg_flags = RAW;
+		stty(ttyfd,&tty);
+	} else {
+		freopen(s,"w",stdout);
+	}
+	first = 1; osg = 0;
+	uid = getuid();
+	lock(1);
+	for (;;) {
+		pc = get2c(stdin);
+		if (feof(stdin))
+			break;
+		sg = get2c(stdin);
+		nd = get2c(stdin);
+		if (first) {
+			put('L'); reply();
+			put('S'); reply();
+			first = 0;
+		}
+		if (sg != osg) {
+			segment(sg);
+			osg = sg;
+		}
+		while (nd > MAXBYTE) {
+			data(MAXBYTE,pc);
+			nd -= MAXBYTE;
+			pc += MAXBYTE;
+		}
+		if (nd > 0)
+			data(nd,pc);
+		assert(feof(stdin) == 0);
+	}
+	if (first == 0)
+		eof();
+/* 	lock(0); */
+/* 	setuid(uid); */
+/* 	if (echo) */
+/* 		for (;;) */
+/* 			reply(); */
+}
+
+segment(sg) {
+
+	newline(2,0,SEGTYPE);
+	word(sg);
+	endline();
+}
+
+startad(pc) {
+
+	newline(4,0,PCTYPE);
+	word(0);
+	word(pc);
+	endline();
+}
+
+data(nd,pc) {
+
+	newline(nd,pc,DATTYPE);
+	do
+		byte(getc(stdin));
+	while (--nd);
+	endline();
+}
+
+eof() {
+
+	newline(0,0,EOFTYPE);
+	byte(0xFF);
+	put('\n');
+}
+
+newline(n,pc,typ) {
+
+	check = 0;
+	bytecount = n+5;
+	put('\n');	/* added instruction */
+	put(':');
+	byte(n);
+	word(pc);
+	byte(typ);
+}
+
+endline() {
+
+	byte(-check);
+	assert(bytecount == 0);
+	assert(check == 0);
+}
+
+word(w) {
+
+	byte(w>>8);
+	byte(w);
+}
+
+byte(b) {
+
+	check += b;
+	--bytecount;
+	put(hex[(b>>4) & 017]);
+	put(hex[b & 017]);
+}
+
+put(c) {
+
+	if (istty)
+		write(ttyfd,&c,1);
+	else
+		putchar(c);
+}
+
+reply() {
+	register i;
+	int c;
+
+	if (echo == 0)
+		return;
+	i = read(ttyfd,&c,1);
+	assert(i > 0);
+	write(1,&c,1);
+}
+
+get2c(f) FILE *f; {
+	register c;
+
+	c = getc(f);
+	return((getc(f) << 8) | c);
+}
+
+fatal(s,a) {
+
+	fprintf(stderr,"%s: ",progname);
+	fprintf(stderr,s,a);
+	fprintf(stderr,"\n");
+	exit(-1);
+}

+ 3 - 0
mach/z80/int/doas

@@ -0,0 +1,3 @@
+/usr/em/mach/z80/as/as -d em.s atof.s fpp.s mli4.s dvu4.s dvi4.s eb.s >em.list
+dl a.out int.hex
+dosort int.hex

+ 9 - 0
mach/z80/int/dosort

@@ -0,0 +1,9 @@
+case $# in
+1) ;;
+*) echo "usage $0 file";exit ;;
+esac
+head -1 $1>$$.head
+tail -1 $1>$$.tail
+tail +2 $1|sort +0.3|tail +2>$$.middle
+cat $$.head $$.middle $$.tail >$1
+rm $$.head $$.middle $$.tail

+ 74 - 0
mach/z80/int/dvi4.s

@@ -0,0 +1,74 @@
+.dvi4:
+	pop hl
+	ld (retaddr),hl
+	xor a
+	ld (.flag1),a
+	ld (.flag2),a
+	ld ix,0
+	add ix,sp
+	ld b,(ix+7)		! dividend
+	bit 7,b
+	jr z,1f
+	ld c,(ix+6)
+	ld d,(ix+5)
+	ld e,(ix+4)
+	call .negbd
+	ld (ix+7),b
+	ld (ix+6),c
+	ld (ix+5),d
+	ld (ix+4),e
+	ld a,1
+	ld (.flag1),a
+1:
+	ld b,(ix+3)
+	bit 7,b
+	jr z,2f
+	call .negst
+	ld a,1
+	ld (.flag2),a
+2:
+	call .dvu4
+	ld a,(.flag1)
+	or a
+	jr z,3f
+	call .negbd
+3:
+	ld (.savebc),bc
+	ld (.savede),de
+	ld a,(.flag2)
+	ld b,a
+	ld a,(.flag1)
+	xor b
+	jr z,4f
+	call .negst
+4:
+	ld bc,(.savebc)
+	ld de,(.savede)
+	ld hl,(retaddr)
+	jp (hl)
+.negbd:
+	xor a
+	ld h,a
+	ld l,a
+	sbc hl,de
+	ex de,hl
+	ld h,a
+	ld l,a
+	sbc hl,bc
+	ld b,h
+	ld c,l
+	ret
+.negst:
+	pop iy
+	pop de
+	pop bc
+	call .negbd
+	push bc
+	push de
+	jp (iy)
+.data
+	.flag1: .byte 0
+	.flag2: .byte 0
+	retaddr:.word 0
+	.savebc: .word 0
+	.savede: .word 0

+ 137 - 0
mach/z80/int/dvu4.s

@@ -0,0 +1,137 @@
+.define .dvu4
+
+! 4-byte divide routine for z80
+! parameters:
+!    stack: divisor
+!	    dividend
+!    stack: quotient (out)
+!    bc de: remainder (out)  (high part in bc)
+
+
+
+! a n-byte divide may be implemented
+! using 2 (virtual) registers:
+!  - a n-byte register containing
+!    the divisor
+!  - a 2n-byte shiftregister (VSR)
+!
+! Initially, the VSR contains the dividend
+! in its low (right) n bytes and zeroes in its
+! high n bytes. The dividend is shifted
+! left into a "window" bit by bit. After
+! each shift, the contents of the window
+! is compared with the divisor. If it is
+! higher or equal, the divisor is subtracted from
+! it and a "1" bit is inserted in the
+! VSR from the right side; else a "0" bit
+! is inserted. These bits are shifted left
+! too during subsequent iterations.
+! At the end, the rightmost part of VSR
+! contains the quotient.
+! For n=4, we need 2*4+4 = 12 bytes of
+! registers. Unfortunately we only have
+! 5 2-byte registers on the z80
+! (bc,de,hl,ix and iy). Therefore we use
+! an overlay technique for the rightmost
+! 4 bytes of the VSR. The 32 iterations
+! are split up into two groups: during
+! the first 16 iterations we use the high
+! order 16 bits of the dividend; during
+! the last 16 iterations we use the
+! low order 16 bits.
+! register allocation:
+!   VSR        iy hl ix
+!   divisor   -de bc
+.dvu4:
+	! initialization
+	pop hl		! save return address
+	ld (.retaddr),hl
+	pop bc		! low part (2 bytes)
+			! of divisor in bc
+	xor a		! clear carry, a := 0
+	ld h,a		! hl := 0
+	ld l,a
+	ld (.flag),a	! first pass main loop
+	pop de		! high part divisor
+	sbc hl,de	! inverse of high part
+	ex de,hl	! of divisor in de
+	pop hl		! save low part of
+			! dividend in memory
+	ld (.low),hl	! used during second
+			! iteration over main loop
+	pop ix		! high part of dividend
+	push iy		! save LB
+	ld h,a		! hl := 0
+	ld l,a
+	ld iy,0		! now the VSR is initialized
+
+	! main loop, done twice
+1:
+	ld a,16
+	! sub-loop, done 16 times
+2:
+	add iy,iy	! shift VSR left
+	add ix,ix
+	adc hl,hl
+	jp nc,3f
+	inc iy
+3:
+	or a		! subtract divisor from
+			! window (iy hl)
+	ld (.iysave),iy
+	sbc hl,bc
+	jr nc,4f	! decrement iy if there
+			! was no borrow
+	dec iy
+4:
+	add iy,de	! there is no "sbc iy,ss"
+			! on the z80, so de was
+			! inverted during init.
+	inc ix
+	! see if the result is non-negative,
+	! otherwise undo the subtract.
+	! note that this uncooperating machine
+	! does not set its S -or Z flag after
+	! a 16-bit add.
+	ex (sp),iy	! does anyone see a better
+	ex (sp),hl	! solution ???
+	bit 7,h
+	ex (sp),hl
+	ex (sp),iy
+	jp z,5f
+	! undo the subtract
+	add hl,bc
+	ld iy,(.iysave)
+	dec ix
+5:
+	dec a
+	jr nz,2b
+	ld a,(.flag)	! see if this was first or
+			! second iteration of main loop
+	or a		! 0=first, 1=second
+	jr nz,6f
+	inc a		! a := 1
+	ld (.flag),a	! flag := 1
+	ld (.result),ix ! save high part of result
+	ld ix,(.low)	! initialize second
+			! iteration, ix := low
+			! part of dividend
+	jr 1b
+6:
+	! clean up
+	push iy		! transfer remainder
+	pop bc		! from iy-hl to bc-de
+	ex de,hl
+	pop iy		! restore LB
+	ld hl,(.result) ! high part of result
+	push hl
+	push ix		! low part of result
+	ld hl,(.retaddr)
+	jp (hl)		! return
+
+.data
+.flag:		.byte 0
+.low:		.word 0
+.iysave:	.word 0
+.retaddr:	.word 0
+.result:	.word 0

+ 2 - 0
mach/z80/int/eb.s

@@ -0,0 +1,2 @@
+	.bss
+eb:

+ 4932 - 0
mach/z80/int/em.s

@@ -0,0 +1,4932 @@
+#
+! This program is an EM interpreter for the Z80.
+! Register pair bc is used to hold lb.
+! Register ix is used to hold the EM program counter.
+! The interpreter assumes 16-bit words and 16-bit pointers.
+
+! #define	CPM1	1
+
+! Definitions:
+   zone = 8	! size of subroutine call block (address + old lb)
+   bdos = 5	! standard entry into I/O-routines
+   boot = 0
+   fcb = 0x5c	! file descriptor of EM-1 file (5C hex)
+
+   reset=0
+   delete=19
+   makefile=22
+   close=16
+   readconsole = 10
+   writeconsole = 2
+   open = 15
+   read = 20
+   write = 21
+   setdma = 26
+   printstring = 9
+   seqread = 20
+   randomread = 33
+   seqwrite = 21
+   randomwrite = 34
+   consolein = 1
+   diconio = 6
+   RAW=0			!0 for cooked,1 for raw io
+
+   timebuf=0xFFDE
+
+   b_lolp = 176
+   b_loln = 179
+   b_lof = 161
+   b_loi = 168
+   b_lal = 130
+   b_lil = 146
+   b_stlm = 227
+   b_stf = 214
+   b_sti = 218
+   b_inl = 112
+   b_cal = 63
+   b_asp = 44
+   b_zrl = 249
+
+   EARRAY = 0
+   ERANGE = 1
+   EILLINS=18
+   EILLSIZE=19
+   ECASE=20
+   EMON=25
+
+!--------------------------- Initialization ---------------------------
+
+	.base 0x100
+
+	jp init		! 3 byte instruction.
+
+!------------------------- MAIN DISPATCH ------------------------------
+!
+! must be put in a suitable place in memory to reduce memory usage
+! must be put on a page boundary
+
+
+dispat = . - 3	! base of dispatch table
+!	.byte	loc.0	/256
+!	.byte	loc.1	/256
+!	.byte	loc.2	/256
+	.byte	loc.3	/256
+	.byte	loc.4	/256
+	.byte	loc.5	/256
+	.byte	loc.6	/256
+	.byte	loc.7	/256
+	.byte	loc.8	/256
+	.byte	loc.9	/256
+	.byte	loc.10	/256
+	.byte	loc.11	/256
+	.byte	loc.12	/256
+	.byte	loc.13	/256
+	.byte	loc.14	/256
+	.byte	loc.15	/256
+	.byte	loc.16	/256
+	.byte	loc.17	/256
+	.byte	loc.18	/256
+	.byte	loc.19	/256
+	.byte	loc.20	/256
+	.byte	loc.21	/256
+	.byte	loc.22	/256
+	.byte	loc.23	/256
+	.byte	loc.24	/256
+	.byte	loc.25	/256
+	.byte	loc.26	/256
+	.byte	loc.27	/256
+	.byte	loc.28	/256
+	.byte	loc.29	/256
+	.byte	loc.30	/256
+	.byte	loc.31	/256
+	.byte	loc.32	/256
+	.byte	loc.33	/256
+	.byte	aar.2	/256
+	.byte	adf.s0	/256
+	.byte	adi.2	/256
+	.byte	adi.4	/256
+	.byte	adp.l	/256
+	.byte	adp.1	/256
+	.byte	adp.2	/256
+	.byte	adp.s0	/256
+	.byte	adp.sm1	/256
+	.byte	ads.2	/256
+	.byte	and.2	/256
+	.byte	asp.2	/256
+	.byte	asp.4	/256
+	.byte	asp.6	/256
+	.byte	asp.8	/256
+	.byte	asp.10	/256
+	.byte	asp.w0	/256
+	.byte	beq.l	/256
+	.byte	beq.s0	/256
+	.byte	bge.s0	/256
+	.byte	bgt.s0	/256
+	.byte	ble.s0	/256
+	.byte	blm.s0	/256
+	.byte	blt.s0	/256
+	.byte	bne.s0	/256
+	.byte	bra.l	/256
+	.byte	bra.sm1	/256
+	.byte	bra.sm2	/256
+	.byte	bra.s0	/256
+	.byte	bra.s1	/256
+	.byte	cal.1	/256
+	.byte	cal.2	/256
+	.byte	cal.3	/256
+	.byte	cal.4	/256
+	.byte	cal.5	/256
+	.byte	cal.6	/256
+	.byte	cal.7	/256
+	.byte	cal.8	/256
+	.byte	cal.9	/256
+	.byte	cal.10	/256
+	.byte	cal.11	/256
+	.byte	cal.12	/256
+	.byte	cal.13	/256
+	.byte	cal.14	/256
+	.byte	cal.15	/256
+	.byte	cal.16	/256
+	.byte	cal.17	/256
+	.byte	cal.18	/256
+	.byte	cal.19	/256
+	.byte	cal.20	/256
+	.byte	cal.21	/256
+	.byte	cal.22	/256
+	.byte	cal.23	/256
+	.byte	cal.24	/256
+	.byte	cal.25	/256
+	.byte	cal.26	/256
+	.byte	cal.27	/256
+	.byte	cal.28	/256
+	.byte	cal.s0	/256
+	.byte	cff.z	/256
+	.byte	cif.z	/256
+	.byte	cii.z	/256
+	.byte	cmf.s0	/256
+	.byte	cmi.2	/256
+	.byte	cmi.4	/256
+	.byte	cmp.z	/256
+	.byte	cms.s0	/256
+	.byte	csa.2	/256
+	.byte	csb.2	/256
+	.byte	dec.z	/256
+	.byte	dee.w0	/256
+	.byte	del.wm1	/256
+	.byte	dup.2	/256
+	.byte	dvf.s0	/256
+	.byte	dvi.2	/256
+	.byte	fil.l	/256
+	.byte	inc.z	/256
+	.byte	ine.l	/256
+	.byte	ine.w0	/256
+	.byte	inl.m2	/256
+	.byte	inl.m4	/256
+	.byte	inl.m6	/256
+	.byte	inl.wm1	/256
+	.byte	inn.s0	/256
+	.byte	ior.2	/256
+	.byte	ior.s0	/256
+	.byte	lae.l	/256
+	.byte	lae.w0	/256
+	.byte	lae.w1	/256
+	.byte	lae.w2	/256
+	.byte	lae.w3	/256
+	.byte	lae.w4	/256
+	.byte	lae.w5	/256
+	.byte	lae.w6	/256
+	.byte	lal.p	/256
+	.byte	lal.n	/256
+	.byte	lal.0	/256
+	.byte	lal.m1	/256
+	.byte	lal.w0	/256
+	.byte	lal.wm1	/256
+	.byte	lal.wm2	/256
+	.byte	lar.2	/256
+	.byte	ldc.0	/256
+	.byte	lde.l	/256
+	.byte	lde.w0	/256
+	.byte	ldl.0	/256
+	.byte	ldl.wm1	/256
+	.byte	lfr.2	/256
+	.byte	lfr.4	/256
+	.byte	lfr.s0	/256
+	.byte	lil.wm1	/256
+	.byte	lil.w0	/256
+	.byte	lil.0	/256
+	.byte	lil.2	/256
+	.byte	lin.l	/256
+	.byte	lin.s0	/256
+	.byte	lni.z	/256
+	.byte	loc.l	/256
+	.byte	loc.m1	/256
+	.byte	loc.s0	/256
+	.byte	loc.sm1	/256
+	.byte	loe.l	/256
+	.byte	loe.w0	/256
+	.byte	loe.w1	/256
+	.byte	loe.w2	/256
+	.byte	loe.w3	/256
+	.byte	loe.w4	/256
+	.byte	lof.l	/256
+	.byte	lof.2	/256
+	.byte	lof.4	/256
+	.byte	lof.6	/256
+	.byte	lof.8	/256
+	.byte	lof.s0	/256
+	.byte	loi.l	/256
+	.byte	loi.1	/256
+	.byte	loi.2	/256
+	.byte	loi.4	/256
+	.byte	loi.6	/256
+	.byte	loi.8	/256
+	.byte	loi.s0	/256
+	.byte	lol.p	/256
+	.byte	lol.n	/256
+	.byte	lol.0	/256
+	.byte	lol.2	/256
+	.byte	lol.4	/256
+	.byte	lol.6	/256
+	.byte	lol.m2	/256
+	.byte	lol.m4	/256
+	.byte	lol.m6	/256
+	.byte	lol.m8	/256
+	.byte	lol.m10	/256
+	.byte	lol.m12	/256
+	.byte	lol.m14	/256
+	.byte	lol.m16	/256
+	.byte	lol.w0	/256
+	.byte	lol.wm1	/256
+	.byte	lxa.1	/256
+	.byte	lxl.1	/256
+	.byte	lxl.2	/256
+	.byte	mlf.s0	/256
+	.byte	mli.2	/256
+	.byte	mli.4	/256
+	.byte	rck.2	/256
+	.byte	ret.0	/256
+	.byte	ret.2	/256
+	.byte	ret.s0	/256
+	.byte	rmi.2	/256
+	.byte	sar.2	/256
+	.byte	sbf.s0	/256
+	.byte	sbi.2	/256
+	.byte	sbi.4	/256
+	.byte	sdl.wm1	/256
+	.byte	set.s0	/256
+	.byte	sil.wm1	/256
+	.byte	sil.w0	/256
+	.byte	sli.2	/256
+	.byte	ste.l	/256
+	.byte	ste.w0	/256
+	.byte	ste.w1	/256
+	.byte	ste.w2	/256
+	.byte	stf.l	/256
+	.byte	stf.2	/256
+	.byte	stf.4	/256
+	.byte	stf.s0	/256
+	.byte	sti.1	/256
+	.byte	sti.2	/256
+	.byte	sti.4	/256
+	.byte	sti.6	/256
+	.byte	sti.8	/256
+	.byte	sti.s0	/256
+	.byte	stl.p	/256
+	.byte	stl.n	/256
+	.byte	stl.p0	/256
+	.byte	stl.p2	/256
+	.byte	stl.m2	/256
+	.byte	stl.m4	/256
+	.byte	stl.m6	/256
+	.byte	stl.m8	/256
+	.byte	stl.m10	/256
+	.byte	stl.wm1	/256
+	.byte	teq.z	/256
+	.byte	tgt.z	/256
+	.byte	tlt.z	/256
+	.byte	tne.z	/256
+	.byte	zeq.l	/256
+	.byte	zeq.s0	/256
+	.byte	zeq.s1	/256
+	.byte	zer.s0	/256
+	.byte	zge.s0	/256
+	.byte	zgt.s0	/256
+	.byte	zle.s0	/256
+	.byte	zlt.s0	/256
+	.byte	zne.s0	/256
+	.byte	zne.sm1	/256
+	.byte	zre.l	/256
+	.byte	zre.w0	/256
+	.byte	zrl.m2	/256
+	.byte	zrl.m4	/256
+	.byte	zrl.wm1	/256
+	.byte	zrl.n	/256
+	.byte	loop1	/256
+	.byte	loop2	/256
+
+	.errnz .-dispat-256
+
+	.byte	loc.0	%256
+	.byte	loc.1	%256
+	.byte	loc.2	%256
+	.byte	loc.3	%256
+	.byte	loc.4	%256
+	.byte	loc.5	%256
+	.byte	loc.6	%256
+	.byte	loc.7	%256
+	.byte	loc.8	%256
+	.byte	loc.9	%256
+	.byte	loc.10	%256
+	.byte	loc.11	%256
+	.byte	loc.12	%256
+	.byte	loc.13	%256
+	.byte	loc.14	%256
+	.byte	loc.15	%256
+	.byte	loc.16	%256
+	.byte	loc.17	%256
+	.byte	loc.18	%256
+	.byte	loc.19	%256
+	.byte	loc.20	%256
+	.byte	loc.21	%256
+	.byte	loc.22	%256
+	.byte	loc.23	%256
+	.byte	loc.24	%256
+	.byte	loc.25	%256
+	.byte	loc.26	%256
+	.byte	loc.27	%256
+	.byte	loc.28	%256
+	.byte	loc.29	%256
+	.byte	loc.30	%256
+	.byte	loc.31	%256
+	.byte	loc.32	%256
+	.byte	loc.33	%256
+	.byte	aar.2	%256
+	.byte	adf.s0	%256
+	.byte	adi.2	%256
+	.byte	adi.4	%256
+	.byte	adp.l	%256
+	.byte	adp.1	%256
+	.byte	adp.2	%256
+	.byte	adp.s0	%256
+	.byte	adp.sm1	%256
+	.byte	ads.2	%256
+	.byte	and.2	%256
+	.byte	asp.2	%256
+	.byte	asp.4	%256
+	.byte	asp.6	%256
+	.byte	asp.8	%256
+	.byte	asp.10	%256
+	.byte	asp.w0	%256
+	.byte	beq.l	%256
+	.byte	beq.s0	%256
+	.byte	bge.s0	%256
+	.byte	bgt.s0	%256
+	.byte	ble.s0	%256
+	.byte	blm.s0	%256
+	.byte	blt.s0	%256
+	.byte	bne.s0	%256
+	.byte	bra.l	%256
+	.byte	bra.sm1	%256
+	.byte	bra.sm2	%256
+	.byte	bra.s0	%256
+	.byte	bra.s1	%256
+	.byte	cal.1	%256
+	.byte	cal.2	%256
+	.byte	cal.3	%256
+	.byte	cal.4	%256
+	.byte	cal.5	%256
+	.byte	cal.6	%256
+	.byte	cal.7	%256
+	.byte	cal.8	%256
+	.byte	cal.9	%256
+	.byte	cal.10	%256
+	.byte	cal.11	%256
+	.byte	cal.12	%256
+	.byte	cal.13	%256
+	.byte	cal.14	%256
+	.byte	cal.15	%256
+	.byte	cal.16	%256
+	.byte	cal.17	%256
+	.byte	cal.18	%256
+	.byte	cal.19	%256
+	.byte	cal.20	%256
+	.byte	cal.21	%256
+	.byte	cal.22	%256
+	.byte	cal.23	%256
+	.byte	cal.24	%256
+	.byte	cal.25	%256
+	.byte	cal.26	%256
+	.byte	cal.27	%256
+	.byte	cal.28	%256
+	.byte	cal.s0	%256
+	.byte	cff.z	%256
+	.byte	cif.z	%256
+	.byte	cii.z	%256
+	.byte	cmf.s0	%256
+	.byte	cmi.2	%256
+	.byte	cmi.4	%256
+	.byte	cmp.z	%256
+	.byte	cms.s0	%256
+	.byte	csa.2	%256
+	.byte	csb.2	%256
+	.byte	dec.z	%256
+	.byte	dee.w0	%256
+	.byte	del.wm1	%256
+	.byte	dup.2	%256
+	.byte	dvf.s0	%256
+	.byte	dvi.2	%256
+	.byte	fil.l	%256
+	.byte	inc.z	%256
+	.byte	ine.l	%256
+	.byte	ine.w0	%256
+	.byte	inl.m2	%256
+	.byte	inl.m4	%256
+	.byte	inl.m6	%256
+	.byte	inl.wm1	%256
+	.byte	inn.s0	%256
+	.byte	ior.2	%256
+	.byte	ior.s0	%256
+	.byte	lae.l	%256
+	.byte	lae.w0	%256
+	.byte	lae.w1	%256
+	.byte	lae.w2	%256
+	.byte	lae.w3	%256
+	.byte	lae.w4	%256
+	.byte	lae.w5	%256
+	.byte	lae.w6	%256
+	.byte	lal.p	%256
+	.byte	lal.n	%256
+	.byte	lal.0	%256
+	.byte	lal.m1	%256
+	.byte	lal.w0	%256
+	.byte	lal.wm1	%256
+	.byte	lal.wm2	%256
+	.byte	lar.2	%256
+	.byte	ldc.0	%256
+	.byte	lde.l	%256
+	.byte	lde.w0	%256
+	.byte	ldl.0	%256
+	.byte	ldl.wm1	%256
+	.byte	lfr.2	%256
+	.byte	lfr.4	%256
+	.byte	lfr.s0	%256
+	.byte	lil.wm1	%256
+	.byte	lil.w0	%256
+	.byte	lil.0	%256
+	.byte	lil.2	%256
+	.byte	lin.l	%256
+	.byte	lin.s0	%256
+	.byte	lni.z	%256
+	.byte	loc.l	%256
+	.byte	loc.m1	%256
+	.byte	loc.s0	%256
+	.byte	loc.sm1	%256
+	.byte	loe.l	%256
+	.byte	loe.w0	%256
+	.byte	loe.w1	%256
+	.byte	loe.w2	%256
+	.byte	loe.w3	%256
+	.byte	loe.w4	%256
+	.byte	lof.l	%256
+	.byte	lof.2	%256
+	.byte	lof.4	%256
+	.byte	lof.6	%256
+	.byte	lof.8	%256
+	.byte	lof.s0	%256
+	.byte	loi.l	%256
+	.byte	loi.1	%256
+	.byte	loi.2	%256
+	.byte	loi.4	%256
+	.byte	loi.6	%256
+	.byte	loi.8	%256
+	.byte	loi.s0	%256
+	.byte	lol.p	%256
+	.byte	lol.n	%256
+	.byte	lol.0	%256
+	.byte	lol.2	%256
+	.byte	lol.4	%256
+	.byte	lol.6	%256
+	.byte	lol.m2	%256
+	.byte	lol.m4	%256
+	.byte	lol.m6	%256
+	.byte	lol.m8	%256
+	.byte	lol.m10	%256
+	.byte	lol.m12	%256
+	.byte	lol.m14	%256
+	.byte	lol.m16	%256
+	.byte	lol.w0	%256
+	.byte	lol.wm1	%256
+	.byte	lxa.1	%256
+	.byte	lxl.1	%256
+	.byte	lxl.2	%256
+	.byte	mlf.s0	%256
+	.byte	mli.2	%256
+	.byte	mli.4	%256
+	.byte	rck.2	%256
+	.byte	ret.0	%256
+	.byte	ret.2	%256
+	.byte	ret.s0	%256
+	.byte	rmi.2	%256
+	.byte	sar.2	%256
+	.byte	sbf.s0	%256
+	.byte	sbi.2	%256
+	.byte	sbi.4	%256
+	.byte	sdl.wm1	%256
+	.byte	set.s0	%256
+	.byte	sil.wm1	%256
+	.byte	sil.w0	%256
+	.byte	sli.2	%256
+	.byte	ste.l	%256
+	.byte	ste.w0	%256
+	.byte	ste.w1	%256
+	.byte	ste.w2	%256
+	.byte	stf.l	%256
+	.byte	stf.2	%256
+	.byte	stf.4	%256
+	.byte	stf.s0	%256
+	.byte	sti.1	%256
+	.byte	sti.2	%256
+	.byte	sti.4	%256
+	.byte	sti.6	%256
+	.byte	sti.8	%256
+	.byte	sti.s0	%256
+	.byte	stl.p	%256
+	.byte	stl.n	%256
+	.byte	stl.p0	%256
+	.byte	stl.p2	%256
+	.byte	stl.m2	%256
+	.byte	stl.m4	%256
+	.byte	stl.m6	%256
+	.byte	stl.m8	%256
+	.byte	stl.m10	%256
+	.byte	stl.wm1	%256
+	.byte	teq.z	%256
+	.byte	tgt.z	%256
+	.byte	tlt.z	%256
+	.byte	tne.z	%256
+	.byte	zeq.l	%256
+	.byte	zeq.s0	%256
+	.byte	zeq.s1	%256
+	.byte	zer.s0	%256
+	.byte	zge.s0	%256
+	.byte	zgt.s0	%256
+	.byte	zle.s0	%256
+	.byte	zlt.s0	%256
+	.byte	zne.s0	%256
+	.byte	zne.sm1	%256
+	.byte	zre.l	%256
+	.byte	zre.w0	%256
+	.byte	zrl.m2	%256
+	.byte	zrl.m4	%256
+	.byte	zrl.wm1	%256
+	.byte	zrl.n	%256
+	.byte	loop1	%256
+	.byte	loop2	%256
+
+	.errnz .-dispat-512
+
+!----------------- END OF MAIN DISPATCH -------------------------------
+
+init:
+	ld sp,(bdos+1)	! address of fbase
+	ld hl,dispat
+	ld (hl),loc.0/256
+	inc hl
+	ld (hl),loc.1/256
+	inc hl
+	ld (hl),loc.2/256
+	call uxinit
+warmstart:
+	ld sp,(bdos+1)	! address of fbase
+	call makeargv
+	ld de,0x80
+	ld c,setdma
+	call bdos
+	ld c,open
+	ld de,fcb
+	call bdos
+	inc a
+	jr z,bademfile
+	ld c,read
+	ld de,fcb
+	call bdos
+	or a
+	jr nz,bademfile	! no file
+	ld de,header
+	ld hl,0x90	! start of 2nd half of header
+	ld bc,10	! we copy only first 5 words
+	ldir
+	ld de,(ntext)	! size of program text in bytes
+	ld hl,0
+	sbc hl,de
+	add hl,sp
+	ld sp,hl	! save space for program
+	ld (pb),hl	! set procedure base
+	ld a,0xa0
+	ld (nextp),a
+	ld de,(ntext)
+	xor a
+	ld h,a
+	ld l,a
+	sbc hl,de
+	ex de,hl
+	ld h,a
+	ld l,a
+	add hl,sp
+1:	call getb
+	ld (hl),c
+	inc hl
+	inc e
+	jr nz,1b
+	inc d
+	jr nz,1b
+			! now program text has been read,so start read-
+	ld iy,0		! ing data descriptors, (nextp) (was hl) is
+	ld ix,eb+eb%2	! pointer into DMA,ix is pointer into global
+	! data area,iy is #bytes pushed in last instr (used for repeat)
+rddata:	ld hl,(ndata)
+	ld a,h
+	or l
+	jr z,prdes	! no data left
+	dec hl
+	ld (ndata),hl
+	call getb	! read 1 byte (here:init type) into register c
+	dec c
+	jp p,2f
+	call getw
+	push iy
+	pop hl
+	ld a,h
+	or l
+	jr z,5f		! size of block is zero, so no work
+	push hl
+	push bc
+3:	pop hl		! #repeats
+	pop bc		! block size
+	push bc
+	ld a,h
+	or l
+	jr z,4f		! ready
+	dec hl
+	push hl
+	push ix
+	pop hl
+	add ix,bc
+	dec hl
+	ld d,h
+	ld e,l
+	add hl,bc
+	ex de,hl
+	lddr
+	jr 3b
+4:	pop bc
+5:	ld iy,0		! now last instruction = repeat = type 0
+	jr rddata
+2:	ld b,c		! here other types come
+	jr nz,2f	! Z-flag was (re-)set when decrementing c
+	call getb	! uninitialized words, fetch #words
+	sla c
+	rl b
+	ld iy,0
+	add iy,bc
+	add ix,bc
+4:	jr rddata
+2:	call getb	! remaining types, first fetch #bytes/words
+	ld a,b
+	cp 7
+	jr z,rdflt
+	jp p,bademfile	! floats are not accepted,nor are illegal types
+	ld b,0
+	cp 1
+	jr z,2f
+	cp 5
+	jp m,1f
+2:	ld iy,0		! initialized bytes, simply copy from EM-1 file
+	add iy,bc
+	ld b,c		! #bytes
+3:
+	call getb
+	ld (ix),c
+	inc ix
+	djnz 3b
+	jr 4b
+1:	cp 2
+	jr z,2f
+	cp 3
+	jr z,3f
+	ld hl,(pb)
+	jr 4f
+3:	ld hl,eb+eb%2
+	jr 4f
+2:	ld hl,0
+4:	ld (ntext),hl	! ntext is used here to hold base address of
+	ld iy,0		! correct type: data,instr or 0 (plain numbers)
+	add iy,bc
+	add iy,bc
+	ld b,c
+1:
+	push bc
+	ex de,hl	! save e into l
+	call getw
+	ex de,hl
+	ld hl,(ntext)
+	add hl,bc
+	ld (ix),l
+	inc ix
+	ld (ix),h
+	inc ix
+	pop bc
+	djnz 1b
+2:	jr rddata
+rdflt:
+	ld a,c
+	cp 4
+	jr nz,bademfile
+	push ix
+	pop hl
+1:	call getb
+	ld a,c
+	ld (hl),a
+	inc hl
+	or a
+	jr nz,1b
+	push ix
+	pop hl
+	call atof
+	ld b,4
+1:	ld a,(hl)
+	ld (ix),a
+	inc ix
+	inc hl
+	djnz 1b
+	jr rddata
+
+bademfile:
+	ld c,printstring
+	ld de,1f
+	call bdos
+	jp 0
+1:	.ascii 'load file error\r\n$'
+
+! now all data has been read,so on with the procedure descriptors
+prdes:
+	ld (hp),ix	! initialize heap pointer
+	ld de,(nproc)
+	ld hl,0
+	xor a
+	sbc hl,de
+	add hl,hl
+	add hl,hl	! 4 bytes per proc-descriptor
+	add hl,sp
+	ld sp,hl	! save space for procedure descriptors
+	push hl
+	pop ix
+	ld (pd),hl	! initialize base
+	ld hl,(nproc)
+1:	ld a,h
+	or l
+	jr z,2f
+	dec hl
+	call getb
+	ld (ix),c
+	inc ix
+	call getb
+	ld (ix),c
+	inc ix
+	call getw
+	ex de,hl
+	ld hl,(pb)
+	add hl,bc
+	ld (ix),l
+	inc ix
+	ld (ix),h
+	inc ix
+	ex de,hl
+	jr 1b
+2:
+	ld de,(entry)	! get ready for start of program
+	ld ix,0		! reta, jumping here will stop execution
+	push ix
+	ld hl,argv
+	push hl
+	ld hl,(argc)
+	push hl
+	jr cal		! call EM-1 main program
+
+getw:	call getb
+	ld b,c
+	call getb
+	ld a,b
+	ld b,c
+	ld c,a
+	ret
+getb:	push hl		! getb reads 1 byte in register c from standard
+	push de
+	ld a,(nextp)	! DMA buffer and refills if necessary
+	or a
+	jr nz,1f
+	push bc
+	ld c,read
+	ld de,fcb
+	call bdos
+	or a
+	jr nz,bademfile
+	pop bc
+	ld a,0x80
+1:	ld l,a
+	ld h,0
+	ld c,(hl)
+	inc a
+	ld (nextp),a
+	pop de
+	pop hl
+	ret
+
+!------------------------- Main loop of the interpreter ---------------
+
+phl:	push hl
+loop:
+	.errnz dispat%256
+	ld l,(ix)	! l = opcode byte
+	inc ix		! advance program counter
+	ld h,dispat/256	! hl=address of high byte of jumpaddress
+	ld d,(hl)	! d=high byte of jump address
+	inc h		! hl=address of low byte of jumpaddress
+	ld e,(hl)	! de=jumpaddress
+	xor a		! clear a and carry
+	ld h,a		! and clear h
+	ex de,hl	! d:=0; hl:=jumpaddress
+	jp (hl)		! go execute the routine
+
+loop1:	ld e,(ix)	! e = opcode byte
+	inc ix		! advance EM program counter to next byte
+	ld hl,dispat1	! hl = address of dispatching table
+	xor a
+	ld d,a
+	add hl,de	! compute address of routine for this opcode
+	add hl,de	! hl = address of routine to dispatch to
+	ld d,(hl)	! e = low byte of routine address
+	inc hl		! hl now points to 2nd byte of routine address
+	ld h,(hl)	! h = high byte of routine address
+	ld l,d		! hl = address of routine
+	ld d,a
+	jp (hl)		! go execute the routine
+
+loop2:	ld e,(ix)	! e = opcode byte
+	inc ix		! advance EM program counter to next byte
+	ld hl,dispat2	! hl = address of dispatching table
+	xor a
+	ld d,a
+	add hl,de	! compute address of routine for this opcode
+	add hl,de	! hl = address of routine to dispatch to
+	ld d,(hl)	! e = low byte of routine address
+	inc hl		! hl now points to 2nd byte of routine address
+	ld h,(hl)	! h = high byte of routine address
+	ld l,d		! hl = address of routine
+	ld d,a
+	jp (hl)		! go execute the routine
+
+! Note that d and a are both still 0, and the carry bit is cleared.
+! The execution routines make heavy use of these properties.
+! The reason that the carry bit is cleared is a little subtle, since the
+! two instructions add hl,de affect it.  However, since dispat is being
+! added twice a number < 256, no carry can occur.
+
+
+
+!---------------------- Routines to compute addresses of locals -------
+
+! There are four addressing routines, corresponding to four ways the
+! offset can be represented:
+! loml: 16-bit offset.  Codes 1-32767 mean offsets -2 to -65534 bytes
+! loms:  8-bit offset.  Codes 1-255   mean offsets -2 to   -510 bytes
+! lopl: 16-bit offset.  Codes 0-32767 mean offsets  0 to +65534 bytes
+! lops:  8-bit offset.  Codes 0-255   mean offsets  0 to   +510 bytes
+
+loml:	ld d,(ix)	! loml is for 16-bit offsets with implied minus
+	inc ix
+	jr 1f
+loms:
+	dec d
+1:	ld e,(ix)	! loms is for 8-bit offsets with implied minus
+	inc ix
+	ld h,b
+	ld l,c		! hl = bc
+	add hl,de
+	add hl,de	! hl now equals lb - byte offset
+	jp (iy)
+
+lopl:	ld d,(ix)	! lopl is for 16-bit offsets >= 0
+	inc ix
+lops:	ld h,d
+	ld l,(ix)	! fetch low order byte of offset
+	inc ix
+	add hl,hl	! convert offset to bytes
+	ld de,zone	! to account of return address zone
+	add hl,de
+	add hl,bc	! hl now equals lb - byte offset
+	jp (iy)
+
+
+
+!---------------------------- LOADS -----------------------------------
+
+! LOC, LPI
+loc.l: lpi.l:
+	ld d,(ix)	! loc with 16-bit offset
+	inc ix
+loc.s0:	ld e,(ix)	! loc with 8-bit offset
+	inc ix
+loc.0:  loc.1:  loc.2:  loc.3:  loc.4:  loc.5:  loc.6:  loc.7: 
+loc.8:  loc.9:  loc.10: loc.11: loc.12: loc.13: loc.14: loc.15:
+loc.16: loc.17: loc.18: loc.19: loc.20: loc.21: loc.22: loc.23:
+loc.24: loc.25: loc.26: loc.27: loc.28: loc.29: loc.30: loc.31:
+loc.32: loc.33:
+	push de
+	jr loop
+
+loc.m1:	ld hl,-1
+	jr phl
+
+
+loc.sm1:dec d		! for constants -256...-1
+	jr loc.s0
+
+
+! LDC
+ldc.f:	ld h,(ix)
+	inc ix
+	ld l,(ix)
+	inc ix
+	push hl
+	ld h,(ix)
+	inc ix
+	ld l,(ix)
+	inc ix
+	jr phl
+ldc.l:	ld h,(ix)
+	inc ix
+	ld l,(ix)
+	inc ix
+	ld e,d
+	bit 7,h
+	jr z,1f
+	dec de
+1:
+	push de
+	jr phl
+
+ldc.0:	ld e,d
+	push de
+	push de
+	jr loop
+
+
+! LOL
+
+lol.0: lol.1: lol.2: lol.3: lol.4: lol.5: lol.6:
+	ld hl,-b_lolp-b_lolp+zone
+	add hl,de
+	add hl,de
+	add hl,bc
+	jr ipsh
+
+lol.m2: lol.m4: lol.m6: lol.m8: lol.m10: lol.m12: lol.m14: lol.m16:
+	ld hl,b_loln+b_loln
+	sbc hl,de
+	xor a		! clear carry bit
+	sbc hl,de
+	add hl,bc	! hl = lb - byte offset
+
+ipsh:	ld e,(hl)
+	inc hl
+	ld d,(hl)
+	push de
+	jr loop
+
+lol.wm1:ld iy,ipsh
+	jr loms
+lol.n:	ld iy,ipsh
+	jr loml
+lol.w0:	ld iy,ipsh
+	jr lops
+lol.p:	ld iy,ipsh
+	jr lopl
+
+
+! LOE
+
+loe.w4:	inc d
+loe.w3:	inc d
+loe.w2:	inc d
+loe.w1:	inc d
+loe.w0:	ld e,(ix)
+	inc ix
+	ld hl,eb+eb%2
+	add hl,de
+	add hl,de
+	jr ipsh
+
+loe.l:	ld d,(ix)
+	inc ix
+	jr loe.w0
+
+
+
+! LOF
+lof.2: lof.4: lof.6: lof.8:
+	ld hl,-b_lof-b_lof	! assume lof 1 means stack +2, not -2
+	add hl,de
+	add hl,de
+ 1:	pop de
+	add hl,de
+	jr ipsh
+
+lof.s0:	ld h,d
+ 2:	ld l,(ix)
+	inc ix
+	jr 1b
+
+lof.l:	ld h,(ix)
+	inc ix
+	jr 2b
+
+
+
+! LAL
+lal.m1:	ld h,b
+	ld l,c
+	dec hl
+	jr phl
+lal.0:	ld h,b
+	ld l,c
+	ld de,zone
+	add hl,de
+	jr phl
+
+lal.wm2:dec d
+lal.wm1:ld iy,phl
+	jr loms
+lal.w0:	ld iy,phl
+	jr lops
+lal.n:	ld h,(ix)
+	inc ix
+	ld l,(ix)
+	inc ix
+	add hl,bc
+	jr phl
+
+lal.p:	ld h,(ix)
+	inc ix
+	ld l,(ix)
+	inc ix
+	add hl,bc
+	ld de,zone
+	add hl,de
+	jr phl
+
+
+
+! LAE
+
+lae.w8:	inc d
+lae.w7: inc d
+lae.w6: inc d
+lae.w5: inc d
+lae.w4: inc d
+lae.w3: inc d
+lae.w2: inc d
+lae.w1: inc d
+lae.w0: ld e,(ix)
+	inc ix
+	ld hl,eb+eb%2
+	add hl,de
+	add hl,de
+	jr phl
+
+lae.l:	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	ld hl,eb+eb%2
+	add hl,de
+	jr phl
+
+
+
+! LIL
+lil.0: lil.2:
+	ld hl,-b_lil-b_lil+zone
+	add hl,de
+	add hl,de
+	add hl,bc
+ 1:	ld e,(hl)
+	inc hl
+	ld h,(hl)
+	ld l,e
+	jr ipsh
+
+lil.wm1:ld iy,1b
+	jr loms
+lil.n:	ld iy,1b
+	jr loml
+lil.w0:	ld iy,1b
+	jr lops
+lil.p:	ld iy,1b
+	jr lopl
+
+
+
+! LXL, LXA
+lxl.1:
+	ld a,1
+	jr 7f
+
+lxl.2:
+	ld a,2
+	jr 7f
+
+lxl.l:	ld d,(ix)
+	inc ix
+lxl.s:	ld a,(ix)
+	inc ix
+7:	ld iy,phl
+5:	ld h,b
+	ld l,c
+	or a
+	jr z,3f
+2:	inc hl
+	inc hl
+	inc hl
+	inc hl
+	inc hl
+	inc hl
+	inc hl
+	inc hl
+	.errnz .-2b-zone
+	ld e,(hl)
+	inc hl
+	ld h,(hl)
+	ld l,e
+	dec a
+	jr nz,2b
+3:	cp d
+	jr z,4f
+	dec d
+	jr 2b
+4:	jp (iy)
+
+lxa.1:
+	ld a,1
+	jr 7f
+
+lxa.l:	ld d,(ix)
+	inc ix
+lxa.s:	ld a,(ix)
+	inc ix
+7:	ld iy,1f
+	jr 5b
+1:	ld de,zone
+	add hl,de
+	jr phl
+
+lpb.z:
+	pop hl
+	.errnz zone/256
+	ld e,zone
+	add hl,de
+	jr phl
+
+dch.z:
+	ld e,2
+	jr loi
+
+exg.z:
+	pop de
+	jr exg
+exg.l:
+	ld d,(ix)
+	inc ix
+exg.s0:
+	ld e,(ix)
+	inc ix
+exg:
+	push bc
+	pop iy
+	ld hl,0
+	add hl,sp
+	ld b,h
+	ld c,l
+	add hl,de
+1:
+	ld a,(bc)
+	ex af,af2
+	ld a,(hl)
+	ld (bc),a
+	ex af,af2
+	ld (hl),a
+	inc bc
+	inc hl
+	dec de
+	ld a,d
+	or e
+	jr nz,1b
+	push iy
+	pop bc
+	jr loop
+
+
+! LDL
+ldl.0:	ld de,zone
+	ld h,b
+	ld l,c
+	add hl,de
+dipsh:	inc hl
+	inc hl
+	inc hl
+	ld d,(hl)
+	dec hl
+	ld e,(hl)
+	dec hl
+	push de
+	ld d,(hl)
+	dec hl
+	ld e,(hl)
+	push de
+	jr loop
+
+ldl.wm1:ld iy,dipsh
+	jr loms
+ldl.n:	ld iy,dipsh
+	jr loml
+ldl.w0:	ld iy,dipsh
+	jr lops
+ldl.p:	ld iy,dipsh
+	jr lopl
+
+
+! LDE
+lde.l:	ld d,(ix)
+	inc ix
+	jr lde.w0
+
+lde.w3:	inc d
+lde.w2:	inc d
+lde.w1:	inc d
+lde.w0:	ld e,(ix)
+	inc ix
+	ld hl,eb+eb%2
+	add hl,de
+	add hl,de
+	jr dipsh
+
+
+! LDF
+ldf.l:	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	pop hl
+	add hl,de
+	jr dipsh
+
+
+! LOI,LOS
+los.z:
+	ld iy,los.2
+	jr pop2
+los.l:	call long2
+los.2:	pop de
+loi:	pop hl
+	add hl,de
+	dec hl
+	srl d
+	rr e
+	jr nc,1f
+	ld a,e
+	or d
+	jr nz,eilsize
+	ld e,(hl)	! here the 1-byte case is caught
+	push de
+	jr loop
+1:	push bc
+	pop iy
+2:	ld b,(hl)
+	dec hl
+	ld c,(hl)
+	dec hl
+	push bc
+	dec de
+	ld a,d
+	or e
+	jr nz,2b
+loiend:	push iy
+	pop bc
+	jr loop
+
+loi.1: loi.2: loi.4: loi.6: loi.8:
+	ld hl,-b_loi-b_loi
+	add hl,de
+	adc hl,de	! again we use that the carry is cleared
+	jr nz,1f
+	inc hl		! in case loi.0 object size is 1 byte!
+1:	ex de,hl
+	jr loi
+
+loi.l:	ld d,(ix)
+	inc ix
+loi.s0:	ld e,(ix)
+	inc ix
+	jr loi
+
+
+! ------------------------------ STORES --------------------------------
+
+! STL
+stl.p2:	ld hl,2
+	jr 4f
+stl.p0:	ld hl,0
+4:	ld de,zone
+	add hl,de
+	add hl,bc
+	jr ipop
+
+stl.m2: stl.m4: stl.m6: stl.m8: stl.m10:
+	ld hl,b_stlm+b_stlm
+stl.zrl:sbc hl,de
+	xor a
+	sbc hl,de
+	add hl,bc
+ipop:	pop de
+	ld (hl),e
+	inc hl
+	ld (hl),d
+	jr loop
+
+stl.wm1:ld iy,ipop
+	jr loms
+stl.n:	ld iy,ipop
+	jr loml
+stl.w0:	ld iy,ipop
+	jr lops
+stl.p:	ld iy,ipop
+	jr lopl
+
+
+
+
+! STE
+
+ste.w3:	inc d
+ste.w2:	inc d
+ste.w1:	inc d
+ste.w0:	ld e,(ix)
+	inc ix
+	ld hl,eb+eb%2
+	add hl,de
+	add hl,de
+	jr ipop
+
+ste.l:	ld d,(ix)
+	inc ix
+	jr ste.w0
+
+
+
+! STF
+stf.2: stf.4: stf.6: 
+	ld hl,-b_stf-b_stf
+	add hl,de
+	add hl,de
+ 1:	pop de
+	add hl,de
+	jr ipop
+
+stf.s0:	ld h,d
+ 2:	ld l,(ix)
+	inc ix
+	jr 1b
+
+stf.l:	ld h,(ix)
+	inc ix
+	jr 2b
+
+
+
+! SIL
+1:	ld e,(hl)
+	inc hl
+	ld h,(hl)
+	ld l,e
+	jr ipop
+
+sil.wm1:ld iy,1b
+	jr loms
+sil.n:	ld iy,1b
+	jr loml
+sil.w0:	ld iy,1b
+	jr lops
+sil.p:	ld iy,1b
+	jr lopl
+
+
+! STI, STS
+sts.z:
+	ld iy,sts.2
+	jr pop2
+sts.l:	call long2
+sts.2:	pop de
+sti:	pop hl
+	srl d
+	rr e
+	jr nc,1f
+	ld a,e
+	or d
+	jr nz,eilsize
+	pop de		! here the 1-byte case is caught
+	ld (hl),e
+	jr loop
+1:	push bc
+	pop iy
+2:	pop bc
+	ld (hl),c
+	inc hl
+	ld (hl),b
+	inc hl
+	dec de
+	ld a,e
+	or d
+	jr nz,2b
+	jr loiend
+
+sti.1: sti.2: sti.4: sti.6: sti.8:
+	ld hl,-b_sti-b_sti
+	add hl,de
+	adc hl,de	! again we use that the carry is cleared
+	jr nz,1f
+	inc hl		! in case sti.0 object size is 1 byte!
+1:	ex de,hl
+	jr sti
+
+sti.l:	ld d,(ix)
+	inc ix
+sti.s0:	ld e,(ix)
+	inc ix
+	jr  sti
+
+
+! SDL
+sdl.wm1:ld iy,1f
+	jr loms
+sdl.n:	ld iy,1f
+	jr loml
+sdl.w0:	ld iy,1f
+	jr lops
+sdl.p:	ld iy,1f
+	jr lopl
+
+
+! SDE
+sde.l:	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	ld hl,eb+eb%2
+2:	add hl,de
+1:	pop de
+	ld (hl),e
+	inc hl
+	ld (hl),d
+	inc hl
+	jr ipop
+
+
+! SDF
+sdf.l:	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	pop hl
+	jr 2b
+
+
+!------------------------- SINGLE PRECISION ARITHMETIC ---------------
+
+! ADI, ADP, ADS, ADU
+
+adi.z: adu.z:
+	pop de
+9:
+	call chk24
+	.word adi.2,adi.4
+adi.l: adu.l:
+	ld d,(ix)	! I guess a routine chk24.l could do this job
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+ads.z:
+	ld iy,adi.2
+	jr pop2
+ads.l:
+	call long2
+ads.2: adi.2: adu.2:
+	pop de
+1:	pop hl
+	add hl,de
+	jr phl
+
+adp.l:	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 1b
+
+adp.sm1:dec d
+adp.s0:	ld e,(ix)
+	inc ix
+	jr 1b
+
+adp.2:	pop hl
+	inc hl
+	jr 1f
+inc.z:
+adp.1:	pop hl
+1:	inc hl
+	jr phl
+
+
+! SBI, SBP, SBS, SBU	(but what is SBP?)
+
+sbi.z: sbu.z:
+	pop de
+9:
+	call chk24
+	.word sbi.2,sbi.4
+sbi.l: sbu.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+sbs.z:
+	ld iy,sbi.2
+	jr pop2
+sbs.l:
+	call long2
+sbi.2:
+	pop de
+	pop hl
+	sbc hl,de
+	jr phl
+
+
+! NGI
+ngi.z:
+	pop de
+9:
+	call chk24
+	.word ngi.2,ngi.4
+ngi.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+ngi.2:	ld hl,0
+	pop de
+	sbc hl,de
+	jr phl
+
+
+! MLI, MLU	Johan version
+mli.z: mlu.z:
+	pop de
+9:
+	call chk24
+	.word mli.2,mli.4
+mli.l: mlu.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+mli.2: mlu.2:
+	ld iy,loop
+mliint:	pop de
+	pop hl
+	push bc
+	ld b,h
+	ld c,l
+	ld hl,0
+	ld a,16
+0:
+	bit 7,d
+	jr z,1f
+	add hl,bc
+1:
+	dec a
+	jr z,2f
+	ex de,hl
+	add hl,hl
+	ex de,hl
+	add hl,hl
+	jr 0b
+2:
+	pop bc
+	push hl
+	jp (iy)
+
+
+! DVI, DVU
+dvi.z:	
+	pop de
+9:
+	call chk24
+	.word dvi.2,dvi.4
+dvi.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+dvi.2:
+	pop	hl
+	pop	de
+	push	bc
+	ld	b,h
+	ld	c,l
+	xor	a
+	ld	h,a
+	ld	l,a
+	sbc	hl,bc
+	jp	m,1f
+	ld	b,h
+	ld	c,l
+	cpl
+1:
+	or	a
+	ld	hl,0
+	sbc	hl,de
+	jp	m,1f
+	ex	de,hl
+	cpl
+1:
+	push	af
+	ld	hl,0
+	ld	a,16
+0:
+	add	hl,hl
+	ex	de,hl
+	add	hl,hl
+	ex	de,hl
+	jr	nc,1f
+	inc	hl
+	or	a
+1:
+	sbc	hl,bc
+	inc	de
+	jp	p,2f
+	add	hl,bc
+	dec	de
+2:
+	dec	a
+	jr	nz,0b
+	pop	af
+	or	a
+	jr	z,1f
+	ld	hl,0
+	sbc	hl,de
+	ex	de,hl
+1:
+	pop	bc
+	push	de
+	jr	loop
+
+
+dvu.z:	
+	pop de
+9:
+	call chk24
+	.word dvu.2,dvu.4
+dvu.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+dvu.2:
+	pop	hl
+	pop	de
+	push	bc
+	ld	b,h
+	ld	c,l
+	ld	hl,0
+	ld	a,16
+0:
+	add	hl,hl
+	ex	de,hl
+	add	hl,hl
+	ex	de,hl
+	jr	nc,1f
+	inc	hl
+	or	a
+1:
+	sbc	hl,bc
+	inc	de
+	jp	p,2f
+	add	hl,bc
+	dec	de
+2:
+	dec	a
+	jr	nz,0b
+	pop	bc
+	push	de
+	jr loop
+
+
+! RMI, RMU
+rmi.z:
+	pop de
+9:
+	call chk24
+	.word rmi.2,rmi.4
+rmi.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+rmi.2:
+	pop	hl
+	pop	de
+	push	bc
+	ld	b,h
+	ld	c,l
+	xor	a
+	ld	h,a
+	ld	l,a
+	sbc	hl,bc
+	jp	m,1f
+	ld	b,h
+	ld	c,l
+1:
+	or	a
+	ld	hl,0
+	sbc	hl,de
+	jp	m,1f
+	ex	de,hl
+	cpl
+1:
+	push	af
+	ld	hl,0
+	ld	a,16
+0:
+	add	hl,hl
+	ex	de,hl
+	add	hl,hl
+	ex	de,hl
+	jr	nc,1f
+	inc	hl
+	or	a
+1:
+	sbc	hl,bc
+	inc	de
+	jp	p,2f
+	add	hl,bc
+	dec	de
+2:
+	dec	a
+	jr	nz,0b
+	ex	de,hl
+	pop	af
+	or	a
+	jr	z,1f
+	ld	hl,0
+	sbc	hl,de
+	ex	de,hl
+1:
+	pop	bc
+	push	de
+	jr	loop
+
+
+rmu.4:
+	ld iy,.dvu4
+	jr 1f
+rmi.4:
+	ld iy,.dvi4
+1:
+	ld (retarea),bc
+	ld (retarea+2),ix
+	ld hl,1f
+	push hl
+	push iy
+	ret
+1:
+	pop hl
+	pop hl
+	push bc
+	push de
+	ld bc,(retarea)
+	ld ix,(retarea+2)
+	jr loop
+rmu.z:
+	pop de
+9:
+	call chk24
+	.word rmu.2,rmu.4
+rmu.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+rmu.2:
+	pop	hl
+	pop	de
+	push	bc
+	ld	b,h
+	ld	c,l
+	ld	hl,0
+	ld	a,16
+0:
+	add	hl,hl
+	ex	de,hl
+	add	hl,hl
+	ex	de,hl
+	jr	nc,1f
+	inc	hl
+	or	a
+1:
+	sbc	hl,bc
+	inc	de
+	jp	p,2f
+	add	hl,bc
+	dec	de
+2:
+	dec	a
+	jr	nz,0b
+	pop	bc
+	jr	phl
+
+! SLI, SLU
+
+slu.z: sli.z:
+	pop de
+9:
+	call chk24
+	.word sli.2,sli.4
+slu.l:
+sli.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+sli.2:
+	pop de
+	pop hl
+	ld a,d
+	or a
+	jr z,1f
+	ld e,15
+2:	add hl,hl
+1:	dec e
+	jp m,phl
+	jr 2b
+
+sli.4:
+slu.4:
+	pop de
+	pop iy
+	pop hl
+	inc d
+	dec d
+	jr z,1f
+	ld e,31
+1:
+	dec e
+	jp m,2f
+	add iy,iy
+	adc hl,hl
+	jr 1b
+2:
+	push hl
+	push iy
+	jr loop
+
+! SRI, SRU
+
+sri.z:
+	pop de
+9:
+	call chk24
+	.word sri.2,sri.4
+sri.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+sri.2:	pop de
+	pop hl
+	ld a,d
+	or a
+	jr z,1f
+	ld e,15
+2:	sra h
+	rr l
+1:	dec e
+	jp m,phl
+	jr 2b
+
+
+sri.4:
+	pop de
+	ld a,e
+	inc d
+	dec d
+	pop de
+	pop hl
+	jr z,1f
+	ld a,31
+1:
+	dec a
+	jp m,2f
+	sra h
+	rr l
+	rr d
+	rr e
+	jr 1b
+2:
+	push hl
+	push de
+	jr loop
+
+sru.z:
+	pop de
+9:
+	call chk24
+	.word sru.2,sru.4
+sru.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+sru.2:	pop de
+	pop hl
+	ld a,d
+	or a
+	jr z,1f
+	ld e,15
+2:	srl h
+	rr l
+1:	dec e
+	jp m,phl
+	jr 2b
+
+sru.4:
+	pop de
+	ld a,e
+	inc d
+	dec d
+	pop de
+	pop hl
+	jr z,1f
+	ld a,31
+1:
+	dec a
+	jp m,2f
+	srl h
+	rr l
+	rr d
+	rr e
+	jr 1b
+2:
+	push hl
+	push de
+	jr loop
+
+! ROL, ROR
+rol.z:
+	pop de
+9:
+	call chk24
+	.word rol.2,rol.4
+rol.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+rol.2:	pop de
+	pop hl
+	ld a,e
+	and 15
+	jr z,phl
+	ld de,0
+1:	add hl,hl
+	adc hl,de
+	dec a
+	jr nz,1b
+	jr phl
+
+
+rol.4:
+	pop de
+	pop iy
+	pop hl
+	ld a,e
+	and 31
+	jr z,3f
+1:
+	add iy,iy
+	adc hl,hl
+	jr nc,2f
+	inc iy
+2:
+	dec a
+	jr nz,1b
+3:
+	push hl
+	push iy
+
+ror.z:
+	pop de
+9:
+	call chk24
+	.word ror.2,ror.4
+ror.l:
+	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr 9b
+ror.2:	pop de
+	pop hl
+	ld a,e
+	and 15
+	jr z,phl
+1:	srl h
+	rr l
+	jr nc,2f
+	set 7,h
+2:	dec a
+	jr nz,1b
+	jr phl
+
+
+ror.4:
+	pop de
+	ld a,e
+	pop de
+	pop hl
+	and 31
+	jr z,0f
+1:
+	srl h
+	rr l
+	rr d
+	rr e
+	jr nc,2f
+	set 7,h
+2:
+	dec a
+	jr nz,1b
+0:
+	push hl
+	push de
+	jr loop
+pop2:	ld de,2
+	pop hl
+	sbc hl,de
+	jr nz,eilsize
+	xor a
+	ld d,a
+	jp (iy)
+
+
+chk24:
+	! this routine is used to call indirectly
+	! a routine for either 2 or 4 byte operation
+	! ( e.g. mli.2 or mli.4)
+	! de contains 2 or 4
+	! iy points to a descriptor containing
+	! the addresses of both routines
+	pop iy		! address of descriptor
+	ld a,d		! high byte must be 0
+	or a
+	jr nz,unimpld
+	ld a,e
+	cp 2
+	jr z,1f
+	inc iy
+	inc iy		! points to word containing
+			! address of 4 byte routine
+	cp 4
+	jr nz,unimpld
+1:
+	ld h,(iy+1)
+	ld l,(iy)
+	xor a
+	jp (hl)
+!--------------------- INCREMENT, DECREMENT, ZERO ----------------------
+
+! INC
+inl.m2: inl.m4: inl.m6:
+	ld hl, b_inl+b_inl
+	sbc hl,de
+	xor a
+	sbc hl,de
+	add hl,bc
+1:	inc (hl)
+	jr nz,loop
+	inc hl
+	inc (hl)
+	jr loop
+
+inl.wm1:ld iy,1b
+	jr loms
+inl.n:	ld iy,1b
+	jr loml
+inl.p:	ld iy,1b
+	jr lopl
+
+
+! INE
+
+ine.w3:	inc d
+ine.w2:	inc d
+ine.w1:	inc d
+ine.w0:	ld e,(ix)
+	inc ix
+	ld hl,eb+eb%2
+	add hl,de
+	add hl,de
+	jr 1b
+
+ine.l:	ld d,(ix)
+	inc ix
+	jr ine.w0
+
+
+! DEC
+dec.z:	pop hl
+	dec hl
+	push hl
+	jr loop
+
+1:	ld e,(hl)
+	inc hl
+	ld d,(hl)
+	dec de
+	ld (hl),d
+	dec hl
+	ld (hl),e
+	jr loop
+
+del.wm1:ld iy,1b
+	jr loms
+del.n:	ld iy,1b
+	jr loml
+del.p:	ld iy,1b
+	jr lopl
+
+
+! DEE
+
+dee.w3:	inc d
+dee.w2:	inc d
+dee.w1:	inc d
+dee.w0:	ld e,(ix)
+	inc ix
+	ld hl,eb+eb%2
+	add hl,de
+	add hl,de
+	jr 1b
+
+dee.l:	ld d,(ix)
+	inc ix
+	jr dee.w0
+
+
+! ZERO
+zri2: zru2:
+	ld h,d
+	ld l,d
+	jr phl
+
+
+zrf.z:
+zer.z:	pop de
+2:	ld hl,0
+	sra d
+	rr e
+1:	push hl
+	dec de
+	ld a,e
+	or d
+	jr nz,1b
+	jr loop
+
+zrf.l:
+zer.l:	ld d,(ix)
+	inc ix
+zer.s0:	ld e,(ix)
+	inc ix
+	jr 2b
+
+
+zrl.m2: zrl.m4:
+	ld h,d
+	ld l,d
+	push hl
+	ld hl,b_zrl+b_zrl
+	jr stl.zrl
+
+zrl.wm1:
+	ld h,d
+	ld l,d
+	push hl
+	jr stl.wm1
+
+zrl.n:
+	ld h,d
+	ld l,d
+	push hl
+	jr stl.n
+
+zrl.w0:
+	ld h,d
+	ld l,d
+	push hl
+	jr stl.w0
+
+zrl.p:
+	ld h,d
+	ld l,d
+	push hl
+	jr stl.p
+
+
+
+zre.w0:
+	ld h,d
+	ld l,d
+	push hl
+	jr ste.w0
+
+zre.l:
+	ld h,d
+	ld l,d
+	push hl
+	jr ste.l
+
+
+! ------------------------- CONVERT GROUP ------------------------------
+
+! CII, CIU
+cii.z: ciu.z:
+	pop hl
+	pop de
+	sbc hl,de	! hl and de can only have values 2 or 4, that's
+			! why a single subtract can split the 3 cases
+	jr z,loop	! equal, so do nothing
+	jp p,2f
+3:	pop hl		! smaller, so shrink size from double to single
+	pop de
+	jr phl
+2:	pop hl		! larger, so expand (for cii with sign extend)
+	res 1,e
+	bit 7,h
+	jr z,1f
+	dec de
+1:	push de
+	jr phl
+
+! CUI, CUU
+cui.z: cuu.z:
+	pop hl
+	pop de
+	sbc hl,de
+	jr z,loop
+	jp m,3b
+	res 1,e
+	pop hl
+	jr 1b
+
+
+! ------------------------------ SETS ---------------------------------
+
+! SET
+set.z:	pop hl
+doset:	pop de
+	push bc
+	pop iy
+	ld b,h
+	ld c,l
+	xor a
+0:	push af
+	inc sp
+	dec c
+	jr nz,0b
+	dec b
+	jp p,0b
+	push iy
+	pop bc
+	ex de,hl
+	ld a,l
+	sra h
+	jp m,unimpld
+	rr l
+	sra h
+	rr l
+	sra h
+	rr l
+	push hl
+	or a
+	sbc hl,de
+	pop hl
+	jp p,unimpld
+	add hl,sp
+	ld (hl),1
+	and 7
+	jr 1f
+0:	sla (hl)
+	dec a
+1:	jr nz,0b
+	jr loop
+
+set.l:	ld d,(ix)
+	inc ix
+set.s0: ld e,(ix)
+	inc ix
+	ex de,hl
+	jr doset
+
+
+! INN
+inn.z:	pop hl
+	jr 1f
+inn.l:	ld d,(ix)
+	inc ix
+inn.s0: ld e,(ix)
+	inc ix
+	ex de,hl
+1:
+	pop de
+	add hl,sp
+	push hl
+	pop iy
+	ex de,hl
+	ld a,l
+	sra h
+	jp m,0f
+	rr l
+	sra h
+	rr l
+	sra h
+	rr l
+	add hl,sp
+	push hl
+	or a		! clear carry
+	sbc hl,de
+	pop hl
+	jp m,1f
+0:	xor a
+	jr 4f
+1:	ld e,(hl)
+	and 7
+	jr 2f
+3:	rrc e
+	dec a
+2:	jr nz,3b
+	ld a,e
+	and 1
+4:	ld l,a
+	ld h,0
+	ld sp,iy
+	jr phl
+
+
+
+! ------------------------- LOGICAL GROUP -----------------------------
+
+! AND
+and.z:	pop de
+doand:	ld h,d
+	ld l,e
+	add hl,sp
+	push bc
+	ld b,h
+	ld c,l
+	ex de,hl
+	add hl,de
+1:	dec hl
+	dec de
+	ld a,(de)
+	and (hl)
+	ld (hl),a
+	xor a
+	sbc hl,bc
+	jr z,2f
+	add hl,bc
+	jr 1b
+2:	ld h,b
+	ld l,c
+	pop bc
+	ld sp,hl
+	jr loop
+
+and.l:	ld d,(ix)
+	inc ix
+and.s0:	ld e,(ix)
+	inc ix
+	jr doand
+
+and.2:	ld e,2
+	jr doand
+
+! IOR
+ior.z:	pop de
+ior:	ld h,d
+	ld l,e
+	add hl,sp
+	push bc
+	ld b,h
+	ld c,l
+	ex de,hl
+	add hl,de
+1:	dec hl
+	dec de
+	ld a,(de)
+	or (hl)
+	ld (hl),a
+	xor a
+	sbc hl,bc
+	jr z,2f
+	add hl,bc
+	jr 1b
+2:	ld h,b
+	ld l,c
+	pop bc
+	ld sp,hl
+	jr loop
+
+ior.l:	ld d,(ix)
+	inc ix
+ior.s0:	ld e,(ix)
+	inc ix
+	jr ior
+
+ior.2:	ld e,2
+	jr ior
+
+! XOR
+xor.z:	pop de
+exor:	ld h,d
+	ld l,e
+	add hl,sp
+	push bc
+	ld b,h
+	ld c,l
+	ex de,hl
+	add hl,de
+1:	dec hl
+	dec de
+	ld a,(de)
+	xor (hl)
+	ld (hl),a
+	xor a
+	sbc hl,bc
+	jr z,2f
+	add hl,bc
+	jr 1b
+2:	ld h,b
+	ld l,c
+	pop bc
+	ld sp,hl
+	jr loop
+
+xor.l:	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	jr exor
+
+! COM
+com.z:	pop hl
+com:	add hl,sp
+1:	dec hl
+	ld a,(hl)
+	cpl
+	ld (hl),a
+	xor a
+	sbc hl,sp
+	jr z,loop
+	add hl,sp
+	jr 1b
+
+com.l:	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+	ex de,hl
+	jr com
+
+
+! ------------------------- COMPARE GROUP ------------------------------
+
+! CMI
+
+
+cmi.2:	pop de
+	pop hl
+	ld a,h
+	xor d		! check sign bit to catch overflow with subtract
+	jp m,1f
+	sbc hl,de
+	jr phl
+1:	xor d		! now a equals (original) h again
+	jp m,phl
+	set 0,l		! to catch case hl=0>de bit 0 is set explicitly
+	jr phl
+
+
+
+! CMU, CMP
+
+cmi.4:	inc a
+	ld de,4
+	jr docmu
+cmp.z:	ld de,2
+	jr docmu
+cmi.z:	inc a
+cmu.z:
+	pop de
+	jr docmu
+
+cmi.l:	inc a
+cmu.l:	ld d,(ix)
+	inc ix
+	ld e,(ix)
+	inc ix
+docmu:	push bc
+	pop iy
+	ld b,d
+	ld c,e
+	ld hl,0
+	add hl,sp
+	add hl,bc
+	dec hl
+	ld d,h
+	ld e,l
+	add hl,bc
+	ld (retarea),hl		! save new sp-1
+	or a
+	jr z,1f
+	ld a,(de)
+	cp (hl)
+	dec hl
+	dec de
+	dec bc
+	jr z,1f
+	jp p,4f
+	jp pe,5f
+	jr 6f
+1:
+	ld a,(de)
+	cp (hl)
+	dec de
+	dec hl
+	dec bc
+	jr nz,2f
+	ld a,b
+	or c
+	jr nz,1b
+	ld d,a
+	ld e,a
+	jr 3f
+2:
+	jr nc,5f
+6:
+	ld de,1
+	jr 3f
+4:
+	jp pe,6b
+5:
+	ld de,-1
+3:
+	ld hl,(retarea)
+	inc hl
+	ld sp,hl
+	push de
+	push iy
+	pop bc
+	jr loop
+
+
+
+! CMS
+
+cms.z:	pop hl
+	jr 1f
+cms.l:	ld d,(ix)
+	inc ix
+cms.s0:	ld e,(ix)
+	inc ix
+	ex de,hl
+1:	push bc
+	pop iy
+	ld b,h
+	ld c,l
+	add hl,sp
+0:
+	dec sp
+	pop af
+	cpi
+	jr nz,1f
+	ld a,b
+	or c
+	jr nz,0b
+	ld de,0
+	jr 2f
+1:
+	add hl,bc
+	ld de,1
+2:
+	ld sp,hl
+	push de
+	push iy
+	pop bc
+	jr loop
+
+
+! TLT, TLE, TEQ, TNE, TGE, TGT
+tlt.z:
+	ld h,d
+	ld l,d
+	pop de
+	bit 7,d
+	jr z,1f
+	inc l
+1:
+	jr phl
+
+tle.z:	ld hl,1
+	pop de
+	xor a
+	add a,d
+	jp m,phl
+	jr nz,1f
+	xor a
+	add a,e
+	jr z,2f
+1:	dec l
+2:
+	jr phl
+
+teq.z:
+	ld h,d
+	ld l,d
+	pop de
+	ld a,d
+	or e
+	jr nz,1f
+	inc l
+1:
+	jr phl
+
+tne.z:
+	ld h,d
+	ld l,d
+	pop de
+	ld a,d
+	or e
+	jr z,1f
+	inc l
+1:
+	jr phl
+
+tge.z:
+	ld h,d
+	ld l,d
+	pop de
+	bit 7,d
+	jr nz,1f
+	inc l
+1:
+	jr phl
+
+tgt.z:
+	ld h,d
+	ld l,d
+	pop de
+	xor a
+	add a,d
+	jp m,phl
+	jr nz,1f
+	xor a
+	add a,e
+	jr z,2f
+1:	inc l
+2:
+	jr phl
+
+
+! ------------------------- BRANCH GROUP -------------------------------
+
+! BLT, BLE, BEQ, BNE, BGE, BGT, BRA
+
+b.pl:	ld d,(ix)
+	inc ix
+b.ps:	ld e,(ix)
+	inc ix
+	push ix
+	pop hl
+	add hl,de
+	pop de
+	ex (sp),hl
+	xor a
+	jp (iy)
+
+
+bra.l:	ld d,(ix)
+	inc ix
+	jr bra.s0
+
+bra.sm2:dec d
+bra.sm1:dec d
+	dec d
+bra.s1:	inc d
+bra.s0:	ld e,(ix)
+	inc ix
+	add ix,de
+	jr loop
+
+
+bgo:	pop ix		! take branch
+	jr loop
+
+
+blt.s0:	ld iy,blt
+	jr b.ps
+blt.l:	ld iy,blt
+	jr b.pl
+blt:	ld a,h
+	xor d
+	jp m,1f
+	sbc hl,de
+	jr 2f
+1:	xor d
+2:	jp m,bgo
+	pop de
+	jr loop
+
+
+ble.s0:	ld iy,ble
+	jr b.ps
+ble.l:	ld iy,ble
+	jr b.pl
+ble:	ex de,hl
+	jr bge
+
+
+beq.s0:	ld iy,beq
+	jr b.ps
+beq.l:	ld iy,beq
+	jr b.pl
+beq:	sbc hl,de
+	jr z,bgo
+	pop de		! keep stack clean, so dump unused jump address
+	jr loop
+
+
+bne.s0:	ld iy,bne
+	jr b.ps
+bne.l:	ld iy,bne
+	jr b.pl
+bne:	sbc hl,de
+	jr nz,bgo
+	pop de		! keep stack clean, so dump unused jump address
+	jr loop
+
+
+bge.s0:	ld iy,bge
+	jr b.ps
+bge.l:	ld iy,bge
+	jr b.pl
+bge:	ld a,h
+	xor d		! check sign bit to catch overflow with subtract
+	jp m,1f
+	sbc hl,de
+	jr 2f
+1:	xor d		! now a equals (original) h again
+2:	jp p,bgo
+	pop de		! keep stack clean, so dump unused jump address
+	jr loop
+
+
+bgt.s0:	ld iy,bgt
+	jr b.ps
+bgt.l:	ld iy,bgt
+	jr b.pl
+bgt:	ex de,hl
+	jr blt
+
+
+
+! ZLT, ZLE, ZEQ, ZNE, ZGE, ZGT
+
+
+z.pl:	ld d,(ix)
+	inc ix
+z.ps:	ld e,(ix)
+	inc ix
+	push ix
+	pop hl
+	add hl,de
+	ex de,hl
+	pop hl
+	xor a
+	add a,h
+	jp (iy)
+
+
+
+zlt.l:	ld iy,zlt
+	jr z.pl
+zlt.s0:	ld iy,zlt
+	jr z.ps
+zlt:	jp m,zgo
+	jr loop
+
+
+zle.l:	ld iy,zle
+	jr z.pl
+zle.s0:	ld iy,zle
+	jr z.ps
+zle:	jp m,zgo
+	jr nz,loop
+	xor a
+	add a,l
+	jr z,zgo
+	jr loop
+
+
+zeq.l:	ld iy,zeq
+	jr z.pl
+zeq.s1: inc d
+zeq.s0:	ld iy,zeq
+	jr z.ps
+zeq:	ld a,l
+	or h
+	jr nz,loop
+zgo:	push de
+	pop ix
+	jr loop
+
+
+zne.sm1:dec d
+	jr zne.s0
+zne.l:	ld iy,zne
+	jr z.pl
+zne.s0:	ld iy,zne
+	jr z.ps
+zne:	ld a,l
+	or h
+	jr nz,zgo
+	jr loop
+
+
+zge.l:	ld iy,zge
+	jr z.pl
+zge.s0:	ld iy,zge
+	jr z.ps
+zge:	jp m,loop
+	jr zgo
+
+
+zgt.l:	ld iy,zgt
+	jr z.pl
+zgt.s0:	ld iy,zgt
+	jr z.ps
+zgt:	jp m,loop
+	jr nz,zgo
+	xor a
+	add a,l
+	jr z,loop
+	jr zgo
+
+
+! ------------------- ARRAY REFERENCE GROUP ---------------------------
+
+! AAR
+aar.z:
+	ld iy,aar.2
+	jr pop2
+aar.l:	call long2
+aar.2:	ld hl,loop
+aarint:	pop iy		! descriptor
+	ex (sp),hl	! save return address and hl:=index
+	ld e,(iy+0)
+	ld d,(iy+1)	! de := lwb
+	ld a,h
+	xor d
+	jp m,1f
+	sbc hl,de
+	jr 2f
+1:	sbc hl,de
+	xor d
+2:	call m,e.array
+	ld e,(iy+2)
+	ld d,(iy+3)	! de := upb - lwb
+	push hl
+	ex de,hl
+	ld a,h
+	xor d
+	jp m,1f
+	sbc hl,de
+	jr 2f
+1:	xor d
+2:	ex de,hl
+	pop hl
+	call m,e.array
+1:	ld e,(iy+4)
+	ld d,(iy+5)
+	pop iy
+	ex (sp),iy
+	push iy		! exchange base address and return address
+	push de
+	push de
+	push hl
+	ld iy,1f
+	jr mliint
+1:	pop de
+	pop iy
+	pop hl
+	push iy
+	add hl,de
+	pop de
+	ex (sp),hl
+	jp (hl)
+
+lar.l:	call long2
+lar.2:	ld hl,loi
+	jr aarint
+lar.z:
+	ld iy,lar.2
+	jr pop2
+
+
+sar.l:	call long2
+sar.2:	ld hl,sti
+	jr aarint
+sar.z:
+	ld iy,sar.2
+	jr pop2
+
+
+! --------------------- PROCEDURE CALL/RETURN --------------------------
+
+! CAL
+
+cal.1: cal.2: cal.3: cal.4: cal.5: cal.6: cal.7: cal.8:
+cal.9: cal.10: cal.11: cal.12: cal.13: cal.14: cal.15: cal.16:
+cal.17: cal.18: cal.19: cal.20: cal.21: cal.22: cal.23: cal.24:
+cal.25: cal.26: cal.27: cal.28:
+	ld hl,-b_cal
+	add hl,de
+	ex de,hl
+	jr cal
+
+cal.l:	ld d,(ix)
+	inc ix
+cal.s0:	ld e,(ix)
+	inc ix
+cal:	push ix		! entry point for main program of interpreter
+	push bc
+	ld hl,(eb+eb%2)
+	push hl
+	ld hl,(eb+eb%2+4)
+	push hl
+! temporary tracing facility
+! NOP it if you don't want it
+	push de
+	ld de,(eb+eb%2+4)
+	ld hl,(eb+eb%2)
+	call prline
+	pop de
+! end of temporary tracing
+	ld hl,0
+	add hl,sp
+	ld b,h
+	ld c,l
+	ld hl,(pd)
+	ex de,hl
+	add hl,hl
+	add hl,hl
+	add hl,de
+	push hl
+	pop iy
+	ld e,(iy+0)
+	ld d,(iy+1)
+	ld l,c
+	ld h,b
+	xor a
+	sbc hl,de
+	ld sp,hl
+	ld e,(iy+2)
+	ld d,(iy+3)
+	ld ix,0
+	add ix,de
+	jr loop
+
+
+! CAI
+
+cai.z:	pop de
+	jr cal
+
+
+! LFR
+lfr.z:	pop de
+2:	ld a,e
+	rr a
+	cp 5
+	jp p,eilsize	! only result sizes <= 8 are allowed
+	ld hl,retarea
+	add hl,de
+1:	dec hl
+	ld d,(hl)
+	dec hl
+	ld e,(hl)
+	push de
+	dec a
+	jr nz,1b
+	jr loop
+
+lfr.l:	ld d,(ix)
+	inc ix
+lfr.s0:	ld e,(ix)
+	inc ix
+	jr 2b
+
+lfr.2:	ld hl,(retarea)
+	jr phl
+
+lfr.4:	ld de,4
+	jr 2b
+
+
+! RET
+ret.2:	ld a,1
+	jr 3f
+
+ret.z:	pop de
+2:	ld a,d
+	or e
+	jr z,ret.0
+	rr a
+	cp 5
+	jp p,eilsize	! only result sizes <= 8 bytes are allowed
+3:	ld hl,retarea
+1:	pop de
+	ld (hl),e
+	inc hl
+	ld (hl),d
+	inc hl
+	dec a
+	jr nz,1b
+ret.0:
+	ld h,b
+	ld l,c
+	ld sp,hl
+	pop hl
+	ld (eb+eb%2+4),hl
+	pop hl
+	ld (eb+eb%2),hl
+	pop bc		! old LB
+	pop ix		! reta
+	push ix		! check to see if reta = boot (= 0)
+	pop hl
+	ld a,l
+	or h
+	jr nz,loop	! not done yet
+	call uxfinish
+	jr boot
+
+ret.l:	ld d,(ix)
+	inc ix
+ret.s0:	ld e,(ix)
+	inc ix
+	jr 2b
+
+
+! ------------------------- MISCELLANEOUS -----------------------------
+
+! SIG, TRP, RTT
+
+sig.z:
+	ld hl,(trapproc)
+	ex (sp),hl
+	ld (trapproc),hl
+	jr loop
+
+trp.z:
+	ex (sp),hl
+	push de
+	push af
+	push ix
+	push iy
+	push bc
+!	ld iy,trapproc
+!	ld a,(iy)
+!	or (iy+1)
+!	jr nz,1f
+	ld iy,2f+13
+	call octnr
+	ld c,printstring
+	ld de,2f
+	call bdos
+	ld de,(eb+eb%2+4)
+	ld hl,(eb+eb%2)
+	call prline
+0:
+	pop iy		! LB
+	ld a,(iy+6)
+	or (iy+7)	! reta
+	jr nz,3f
+	call uxfinish
+	jp boot
+3:
+	ld c,(iy+4)
+	ld b,(iy+5)
+	push bc		! next LB
+	ld e,(iy)
+	ld d,(iy+1)	! file name
+	ld l,(iy+2)
+	ld h,(iy+3)	! lineno
+	call prline
+	jr 0b
+!1:
+!	ld ix,0
+!	push hl
+!	ld hl,(trapproc)
+!	push hl
+!	ld hl,0
+!	ld (trapproc),hl
+!	jr cai.z
+2:	.ascii 'error 0xxxxxx\r\n$'
+
+prline:
+! prints lineno (hl) and filename (de)
+	push de
+	ld iy,2f+12
+	call octnr
+	ld c,printstring
+	ld de,2f
+	call bdos
+	pop de
+	ld hl,4f
+0:
+	ld a,(de)
+	or a
+	jr z,1f
+	ld (hl),a
+	inc de
+	inc hl
+	jr 0b
+1:
+	ld (hl),36	! '$'
+	ld de,4f
+	ld c,printstring
+	call bdos
+	ld de,3f
+	ld c,printstring
+	call bdos
+	ret
+2:	.ascii 'line 0xxxxxx in $'
+3:	.ascii '\r\n$'
+4:	.space 12
+
+rtt.z=ret.0
+
+
+
+! NOP
+! changed into output routine to print linenumber
+! in octal (6 digits)
+
+nop.z:	push bc
+	ld iy,1f+12
+	ld hl,(eb+eb%2)
+	call octnr
+	ld iy,1f+20
+	ld hl,0
+	add hl,sp
+	call octnr
+	ld c,printstring
+	ld de,1f
+	call bdos
+	pop bc
+	jr loop
+1:	.ascii 'test 0xxxxxx 0xxxxxx\r\n$'
+
+octnr:
+	ld b,6
+1:	ld a,7
+	and l
+	add a,'0'
+	dec iy
+	ld (iy+0),a
+	srl h
+	rr l
+	srl h
+	rr l
+	srl h
+	rr l
+	djnz 1b
+	ret
+
+
+! DUP
+
+dup.2:	pop hl
+	push hl
+	jr phl
+
+dus.z:
+	ld iy,1f
+	jr pop2
+dus.l:	call long2
+1:	push bc
+	pop iy
+	pop bc
+	jr dodup
+dup.l:
+	push bc
+	pop iy
+	ld b,(ix)
+	inc ix
+	ld c,(ix)
+	inc ix
+dodup:	ld h,d
+	ld l,d		! ld hl,0
+	add hl,sp
+	ld d,h
+	ld e,l
+	xor a
+	sbc hl,bc
+	ld sp,hl
+	ex de,hl
+	ldir
+	push iy
+	pop bc
+	jr loop
+
+
+! BLM, BLS
+bls.z:
+	ld iy,blm
+	jr pop2
+bls.l:	call long2
+blm:
+	push bc
+	pop iy
+	pop bc
+	pop de
+	pop hl
+	ldir
+	push iy
+	pop bc
+	jr loop
+
+blm.l:
+	ld d,(ix)
+	inc ix
+blm.s0:	ld e,(ix)
+	inc ix
+	push de
+	jr blm
+
+
+! ASP, ASS
+ass.z:
+	ld iy,1f
+	jr pop2
+ass.l:	call long2
+1:	pop hl
+	jr 1f
+asp.l:
+	ld h,(ix)
+	inc ix
+	ld l,(ix)
+	inc ix
+asp:	add hl,hl
+1:	add hl,sp
+	ld sp,hl
+	jr loop
+
+
+asp.2: asp.4: asp.6: asp.8: asp.10:
+	ld hl,-b_asp
+	add hl,de
+	jr asp
+
+asp.w0:	ld e,(ix)
+	inc ix
+	ex de,hl
+	jr asp
+
+
+! CSA
+
+csa.z:
+	ld iy,csa.2
+	jr pop2
+csa.l:	call long2
+csa.2:
+!! temporary version while bug in cem remains
+!	pop iy
+!	pop de
+!	push bc
+!	ld c,(iy)
+!	ld b,(iy+1)
+!	ld l,(iy+4)
+!	ld h,(iy+5)
+!	xor a
+!	sbc hl,de
+!	jp m,1f
+!	ex de,hl
+!	ld e,(iy+2)
+!	ld d,(iy+3)
+!	xor a
+!	sbc hl,de
+!	jp m,1f
+! end of temporary piece
+	pop iy
+	pop hl
+	push bc
+	ld c,(iy)
+	ld b,(iy+1)
+	ld e,(iy+2)
+	ld d,(iy+3)
+	xor a
+	sbc hl,de
+	jp m,1f
+	ex de,hl
+	ld l,(iy+4)
+	ld h,(iy+5)
+	xor a
+	sbc hl,de
+	jp m,1f
+	ex de,hl
+	add hl,hl
+	ld de,6
+	add hl,de
+	ex de,hl
+	add iy,de
+	ld l,(iy)
+	ld h,(iy+1)
+	ld a,h
+	or l
+	jr nz,2f
+1:	ld a,b
+	or c
+	jr z,e.case
+	ld l,c
+	ld h,b
+2:	pop bc
+	push hl
+	pop ix
+	jr loop
+! CSB
+
+csb.z:
+	ld iy,csb.2
+	jr pop2
+csb.l:	call long2
+csb.2:
+	pop ix
+	pop iy
+	ld e,(ix)
+	inc ix
+	ld d,(ix)
+	inc ix
+	push de
+	ex (sp),iy
+	pop de
+	push bc
+	ld c,(ix)
+	inc ix
+	ld b,(ix)
+	inc ix
+1:
+	ld a,b
+	or c
+	jr z,noteq
+	ld a,(ix+0)
+	cp e
+	jr nz,2f
+	ld a,(ix+1)
+	cp d
+	jr nz,2f
+	ld l,(ix+2)
+	ld h,(ix+3)
+	jr 3f
+2:	inc ix
+	inc ix
+	inc ix
+	inc ix
+	dec bc
+	jr 1b
+noteq:	push iy
+	pop hl
+3:	ld a,l
+	or h
+	jr z,e.case
+2:
+	pop bc
+	push hl
+	pop ix
+	jr loop
+
+
+! LIN
+lin.l:	ld d,(ix)
+	inc ix
+lin.s0:	ld e,(ix)
+	inc ix
+	ld (eb+eb%2),de
+	jr loop
+
+
+! FIL
+fil.z:	pop hl
+1:
+	ld (eb+eb%2+4),hl
+	jr loop
+
+fil.l:	ld h,(ix)
+	inc ix
+	ld l,(ix)
+	inc ix
+	ld de,eb+eb%2
+	add hl,de
+	jr 1b
+
+
+! LNI
+lni.z:	ld hl,(eb+eb%2)
+	inc hl
+	ld (eb+eb%2),hl
+	jr loop
+
+
+! RCK
+rck.z:
+	ld iy,rck.2
+	jr pop2
+rck.l:	call long2
+rck.2:
+	pop iy
+3:	pop hl
+	push hl
+	ld e,(iy)
+	ld d,(iy+1)
+	ld a,h
+	xor d		! check sign bit to catch overflow with subtract
+	jp m,1f
+	sbc hl,de
+	jr 2f
+1:	xor d		! now a equals (original) h again
+2:	call m,e.rck
+	pop de
+	push de
+	ld l,(iy+2)
+	ld h,(iy+3)
+	ld a,h
+	xor d		! check sign bit to catch overflow with subtract
+	jp m,1f
+	sbc hl,de
+	jr 2f
+1:	xor d		! now a equals (original) h again
+2:	call m,e.rck
+	jr loop
+
+
+! LIM
+lim.z:	ld hl,(ignmask)
+	jr phl
+
+
+! SIM
+sim.z:	pop de
+	ld (ignmask),de
+	jr loop
+
+
+! LOR
+
+lor.s0:	ld e,(ix)
+	inc ix
+	ld a,d
+	or e
+	jr nz,1f
+	push bc
+	jr loop
+1:	ld hl,-1
+	adc hl,de
+	jr nz,1f
+	add hl,sp
+	jr phl
+1:	ld hl,(hp)
+	jr phl
+
+
+! STR
+
+str.s0:	ld e,(ix)
+	inc ix
+	ld a,d
+	or e
+	jr nz,1f
+	pop bc
+	jr loop
+1:	pop hl
+	dec de
+	ld a,d
+	or e
+	jr nz,1f
+	ld sp,hl
+	jr loop
+1:	ld (hp),hl
+	jr loop
+
+! Floating point calling routines
+
+loadfregs:
+	pop hl
+	pop de
+	ld (fpac),de
+	pop de
+	ld (fpac+2),de
+	pop de
+	ld (fpop),de
+	pop de
+	ld (fpop+2),de
+	jp (hl)
+
+dofltop:
+	call loadfregs
+	push bc
+	push ix
+	ld hl,1f
+	push hl
+	push iy
+	ret		! really a call
+1:
+	pop ix
+	pop bc
+	ld hl,(fpac+2)
+	push hl
+	ld hl,(fpac)
+	jr phl
+
+pop4:
+	pop hl
+	or h
+	jr nz,9f
+	ld a,l
+	cp 4
+	jr nz,9f
+	jp (iy)
+arg4:
+	or d
+	jr nz,9f
+	ld a,(ix)
+	inc ix
+	cp 4
+	jr nz,9f
+	jp (iy)
+9:	jr unimpld
+
+adf.z:	ld iy,doadf
+	jr pop4
+adf.l:	ld d,(ix)
+	inc ix
+adf.s0:	ld iy,doadf
+	jr arg4
+doadf:
+	ld iy,fpadd	! routine to call
+	jr dofltop
+
+sbf.z:	ld iy,dosbf
+	jr pop4
+sbf.l:	ld d,(ix)
+	inc ix
+sbf.s0:	ld iy,dosbf
+	jr arg4
+dosbf:
+	ld iy,fpsub	! routine to call
+	jr dofltop
+
+mlf.z:	ld iy,domlf
+	jr pop4
+mlf.l:	ld d,(ix)
+	inc ix
+mlf.s0:	ld iy,domlf
+	jr arg4
+domlf:
+	ld iy,fpmult	! routine to call
+	jr dofltop
+
+dvf.z:	ld iy,dodvf
+	jr pop4
+dvf.l:	ld d,(ix)
+	inc ix
+dvf.s0:	ld iy,dodvf
+	jr arg4
+dodvf:
+	ld iy,fpdiv	! routine to call
+	jr dofltop
+
+cmf.z:	ld iy,docmf
+	jr pop4
+cmf.l:	ld d,(ix)
+	inc ix
+cmf.s0:	ld iy,docmf
+	jr arg4
+docmf:
+	call loadfregs
+	push bc
+	push ix
+	call fpcmf
+	pop ix
+	pop bc
+	ld hl,(fpac)
+	jr phl
+cfi.z:
+	pop de
+	call chk24
+	.word 1f,0f
+1:	ld iy,1f
+	jr pop4
+1:	pop hl
+	ld (fpac),hl
+	pop hl
+	ld (fpac+2),hl
+	push bc
+	push ix
+	call fpcfi
+	pop ix
+	pop bc
+	ld hl,(fpac)
+	jr phl
+0:	ld iy,1f
+	jr pop4
+1:	pop hl
+	ld (fpac),hl
+	pop hl
+ld (fpac+2),hl!
+	push bc
+	push ix
+	call fpcfd
+	jr 8f
+cif.z:
+	ld iy,1f
+	jr pop4
+1:
+	pop de
+	call chk24
+	.word 1f,0f
+1:	pop hl
+	ld (fpac),hl
+	push bc
+	push ix
+	call fpcif
+8:	pop ix
+	pop bc
+	ld hl,(fpac+2)
+	push hl
+	ld hl,(fpac)
+	jr phl
+0:	pop hl
+	ld (fpac),hl
+	pop hl
+	ld (fpac+2),hl
+	push bc
+	push ix
+	call fpcdf
+	jr 8b
+
+ngf.l:	ld d,(ix)
+	inc ix
+	ld iy,1f
+	jr arg4
+ngf.z:
+	ld iy,1f
+	jr pop4
+1:	pop hl
+	ld (fpac),hl
+	pop hl
+	ld (fpac+2),hl
+	push bc
+	push ix
+	call fpcomp
+	jr 8b
+
+fif.z:
+	ld iy,1f
+	jr pop4
+fif.l:
+	ld d,(ix)
+	inc ix
+	ld iy,1f
+	jr arg4
+1:	call loadfregs
+	push bc
+	push ix
+	call fpfif
+	pop ix
+	pop bc
+	ld hl,(fpac+2)
+	push hl
+	ld hl,(fpac)
+	push hl
+	ld hl,(fpop+2)
+	push hl
+	ld hl,(fpop)
+	jr phl
+
+fef.z:
+	ld iy,1f
+	jr pop4
+fef.l:
+	ld d,(ix)
+	inc ix
+	ld iy,1f
+	jr arg4
+1:	pop hl
+	ld (fpop),hl
+	pop hl
+	ld (fpop+2),hl
+	push bc
+	push ix
+	call fpfef
+	pop ix
+	pop bc
+	ld hl,(fpop+2)
+	push hl
+	ld hl,(fpop)
+	push hl
+	ld hl,(fpac)
+	jr phl
+
+! double aritmetic
+
+adi.4:
+	push bc
+	pop iy
+	pop hl
+	pop de
+	pop bc
+	add hl,bc
+	ex de,hl
+	pop bc
+	adc hl,bc
+	push hl
+	push de
+	push iy
+	pop bc
+	jr loop
+sbi.4:
+	push bc
+	pop iy
+	pop bc
+	pop de
+	pop hl
+	sbc hl,bc
+	ex de,hl
+	ld b,h
+	ld c,l
+	pop hl
+9:
+	sbc hl,bc
+	push hl
+	push de
+	push iy
+	pop bc
+	jr loop
+ngi.4:
+	push bc
+	pop iy
+	ld hl,0
+	pop de
+	sbc hl,de
+	ex de,hl
+	ld hl,0
+	pop bc
+	jr 9b
+mli.4:
+	ld iy,.mli4
+0:
+	ld (retarea),bc
+	ld (retarea+2),ix
+	ld hl,1f
+	push hl
+	push iy
+	ret
+1:
+	ld bc,(retarea)
+	ld ix,(retarea+2)
+	jr loop
+dvu.4:
+	ld iy,.dvu4
+	jr 0b
+	
+dvi.4:
+	ld iy,.dvi4
+	jr 0b
+	
+! list of not yet implemented instructions
+cuf.z:
+cff.z:
+cfu.z:
+unimpld:		! used in dispatch table to
+			! catch unimplemented instructions
+	ld hl,EILLINS
+9:	push hl
+	jr trp.z
+
+eilsize:
+	ld hl,EILLSIZE
+	jr 9b
+
+e.case:
+	ld hl,ECASE
+	jr 9b
+e.mon:
+	ld hl,EMON
+	jr 9b
+e.array:
+	push af
+	ld a,(ignmask)
+	bit 0,a
+	jr nz,8f
+	ld hl,EARRAY
+	jr 9b
+e.rck:
+	push af
+	ld a,(ignmask)
+	bit 1,a
+	jr nz,8f
+	ld hl,ERANGE
+	jr 9b
+8:
+	pop af
+	ret
+
+long2:	ld a,(ix)
+	inc ix
+	or a
+	jr nz,unimpld
+	ld a,(ix)
+	inc ix
+	cp 2
+	jr nz,unimpld
+	xor a		! clear carry
+	ret
+
+! monitor instruction
+! a small collection of UNIX system calls implemented under CP/M
+
+	ux_indir=e.mon
+	ux_fork=e.mon
+	ux_wait=e.mon
+	ux_link=e.mon
+	ux_exec=e.mon
+	ux_chdir=e.mon
+	ux_mknod=e.mon
+	ux_chmod=e.mon
+	ux_chown=e.mon
+	ux_break=e.mon
+	ux_stat=e.mon
+	ux_seek=e.mon
+	ux_mount=e.mon
+	ux_umount=e.mon
+	ux_setuid=e.mon
+	ux_getuid=e.mon
+	ux_stime=e.mon
+	ux_ptrace=e.mon
+	ux_alarm=e.mon
+	ux_fstat=e.mon
+	ux_pause=e.mon
+	ux_utime=e.mon
+	ux_stty=e.mon
+	ux_gtty=e.mon
+	ux_access=e.mon
+	ux_nice=e.mon
+	ux_sync=e.mon
+	ux_kill=e.mon
+	ux_dup=e.mon
+	ux_pipe=e.mon
+	ux_times=e.mon
+	ux_prof=e.mon
+	ux_unused=e.mon
+	ux_setgid=e.mon
+	ux_getgid=e.mon
+	ux_sig=e.mon
+	ux_umask=e.mon
+	ux_chroot=e.mon
+
+	EPERM	= 1
+	ENOENT	= 2
+	ESRCH	= 3
+	EINTR	= 4
+	EIO	= 5
+	ENXIO	= 6
+	E2BIG	= 7
+	ENOEXEC	= 8
+	EBADF	= 9
+	ECHILD	= 10
+	EAGAIN	= 11
+	ENOMEM	= 12
+	EACCES	= 13
+	EFAULT	= 14
+	ENOTBLK	= 15
+	EBUSY	= 16
+	EEXIST	= 17
+	EXDEV	= 18
+	ENODEV	= 19
+	ENOTDIR	= 20
+	EISDIR	= 21
+	EINVAL	= 22
+	ENFILE	= 23
+	EMFILE	= 24
+	ENOTTY	= 25
+	ETXTBSY	= 26
+	EFBIG	= 27
+	ENOSPC	= 28
+	ESPIPE	= 29
+	EROFS	= 30
+	EMLINK	= 31
+	EPIPE	= 32
+	EDOM	= 33
+! Structure of filearea maintained by this implementation
+! First iobuffer of 128 bytes
+! Then the fcb area of 36 bytes
+! The number of bytes left in the buffer, 1 byte
+! The iopointer into the buffer, 2 bytes
+! The openflag 0 unused, 1 reading, 2 writing, 1 byte
+! The filedescriptor starting at 3, 1 byte
+! The number of CTRL-Zs that have been absorbed, 1 byte
+! The byte read after a sequence of CTRL-Zs, 1 byte
+
+	maxfiles=8
+	filesize=128+36+1+2+1+1+1+1
+
+	filefcb=0	! pointers point to fcb
+	position=33
+	nleft=36
+	iopointer=37
+	openflag=39
+	fildes=40
+	zcount=41
+	zsave=42
+
+	.errnz filefcb
+
+0:	.space maxfiles*filesize
+	filearea = 0b+128
+sibuf:
+	.word 0
+	.space 82
+siptr:	.space 2
+saveargs:
+	.space 128
+argv:	.space 40		! not more than 20 args
+argc:	.space 2
+ttymode:.byte 9,9,8,21;.short 06310+RAW*040	! raw = 040
+
+uxinit:
+	xor a
+	ld c,maxfiles
+	ld hl,0b
+1:	ld b,filesize
+2:	ld (hl),a
+	inc hl
+	djnz 2b
+	dec c
+	jr nz,1b
+	ret
+
+uxfinish:
+	ld a,maxfiles-1
+1:	push af
+	call closefil
+	pop af
+	dec a
+	cp 0377
+	jr nz,1b
+	ret
+
+makeargv:
+	ld hl,0x80
+	ld de,saveargs
+	ld bc,128
+	ldir
+	ld hl,saveargs
+	ld e,(hl)
+	inc hl
+	ld d,0
+	add hl,de
+	ld (hl),0
+	ld hl,saveargs+1
+	ld ix,argv
+1:	ld a,(hl)
+	or a
+	jr z,9f
+	cp ' '
+	jr nz,2f
+4:	ld (hl),0
+	inc hl
+	jr 1b
+2:	ld (ix),l
+	inc ix
+	ld (ix),h
+	inc ix
+3:	inc hl
+	ld a,(hl)
+	or a
+	jr z,9f
+	cp ' '
+	jr nz,3b
+	jr 4b
+9:	push ix
+	pop hl
+	ld de,-argv
+	add hl,de
+	srl h;rr l
+	ld (argc),hl
+	ld (ix+0),0
+	ld (ix+1),0
+	ret
+
+mon.z:
+	pop de		! system call number
+	xor a
+	or d
+	jr nz,unimpld	! too big
+	ld a,e
+	and 0300	! only 64 system calls
+	jr nz,unimpld
+	sla e
+	ld hl,systab
+	add hl,de
+	ld e,(hl)
+	inc hl
+	ld d,(hl)
+	ex de,hl
+	jp (hl)
+
+systab:	
+	.word ux_indir
+	.word ux_exit
+	.word ux_fork
+	.word ux_read
+	.word ux_write
+	.word ux_open
+	.word ux_close
+	.word ux_wait
+	.word ux_creat
+	.word ux_link
+	.word ux_unlink
+	.word ux_exec
+	.word ux_chdir
+	.word ux_time
+	.word ux_mknod
+	.word ux_chmod
+	.word ux_chown
+	.word ux_break
+	.word ux_stat
+	.word ux_seek
+	.word ux_getpid
+	.word ux_mount
+	.word ux_umount
+	.word ux_setuid
+	.word ux_getuid
+	.word ux_stime
+	.word ux_ptrace
+	.word ux_alarm
+	.word ux_fstat
+	.word ux_pause
+	.word ux_utime
+	.word ux_stty
+	.word ux_gtty
+	.word ux_access
+	.word ux_nice
+	.word ux_ftime
+	.word ux_sync
+	.word ux_kill
+	.word unimpld
+	.word unimpld
+	.word unimpld
+	.word ux_dup
+	.word ux_pipe
+	.word ux_times
+	.word ux_prof
+	.word ux_unused
+	.word ux_setgid
+	.word ux_getgid
+	.word ux_sig
+	.word unimpld
+	.word unimpld
+	.word unimpld
+	.word unimpld
+	.word unimpld
+	.word ux_ioctl
+	.word unimpld
+	.word unimpld
+	.word unimpld
+	.word unimpld
+	.word ux_exece
+	.word ux_umask
+	.word ux_chroot
+	.word unimpld
+	.word unimpld
+
+emptyfile:
+	! searches for a free filestructure
+	! returns pointer in iy, 0 if not found
+	ld iy,filearea
+	ld l,maxfiles
+1:
+	xor a
+	or (iy+openflag)
+	jr nz,3f
+	ld a,maxfiles+3
+	sub l
+	ld (iy+fildes),a
+#ifdef	CPM1
+	push bc
+	push iy
+	ld de,-128
+	add iy,de
+	push iy
+	pop de
+	ld c,setdma
+	call bdos
+	pop iy
+	pop bc
+	or a		! to clear C
+#endif
+	ret
+3:
+	ld de,filesize
+	add iy,de
+	dec l
+	jr nz,1b
+	scf
+	ret
+
+findfile:
+	ld iy,filearea
+	ld de,filesize
+0:
+	dec a
+	ret m
+	add iy,de
+	jr 0b
+
+getchar:
+	push bc
+	push de
+	push hl
+	dec (iy+nleft)
+	jp p,0f
+	push iy
+	pop hl
+	ld de,-128
+	add hl,de
+	ld (iy+iopointer),l
+	ld (iy+iopointer+1),h
+	ex de,hl
+	push iy
+	ld c,setdma
+	call bdos
+#ifdef	CPM1
+	ld c,seqread
+#else
+	ld c,randomread
+#endif
+	pop de
+	call bdos
+	or a
+	jr z,1f
+	ld (iy+zcount),0
+	pop hl
+	pop de
+	pop bc
+	scf
+	ret
+1:
+	inc (iy+position)
+	jr nz,2f
+	inc (iy+position+1)
+2:
+	ld a,127
+	ld (iy+nleft),a
+0:
+	ld h,(iy+iopointer+1)
+	ld l,(iy+iopointer)
+	ld a,(hl)
+	inc hl
+	ld (iy+iopointer),l
+	ld (iy+iopointer+1),h
+	pop hl
+	pop de
+	pop bc
+	ret
+	or a
+
+putchar:
+	push hl
+	ld h,(iy+iopointer+1)
+	ld l,(iy+iopointer)
+	ld (hl),a
+	dec (iy+nleft)
+	jr z,0f
+	inc hl
+	ld (iy+iopointer+1),h
+	ld (iy+iopointer),l
+	pop hl
+	ret
+0:
+	pop hl
+flsbuf:
+	push hl
+	push de
+	push bc
+	push iy
+	pop hl
+	ld de,-128
+	add hl,de
+	ld (iy+iopointer+1),h
+	ld (iy+iopointer),l
+	ex de,hl
+	push iy
+	ld c,setdma
+	call bdos
+	pop de
+#ifdef	CPM1
+	ld c,seqwrite
+#else
+	ld c,randomwrite
+#endif
+	call bdos
+	or a
+	jr z,1f
+	pop bc
+	pop de
+	pop hl
+	scf
+	ret
+1:
+	inc (iy+position)
+	jr nz,2f
+	inc (iy+position+1)
+2:
+	ld a,128
+	ld (iy+nleft),a
+	ld b,a
+	push iy
+	pop hl
+	ld de,-128
+	add hl,de
+	ld a,26			! ctrl z
+1:	ld (hl),a
+	inc hl
+	djnz 1b
+	pop bc
+	pop de
+	pop hl
+	or a
+	ret
+
+parsename:
+	! parses file name pointed to by hl and fills in fcb
+	! of the file pointed to by iy.
+	! recognizes filenames as complicated as 'b:file.zot'
+	! and as simple as 'x'
+
+	push bc
+	push iy
+	pop de
+	xor a
+	push de
+	ld b,36		! sizeof fcb
+0:	ld (de),a
+	inc de
+	djnz 0b
+	pop de
+	inc hl
+	ld a,(hl)
+	dec hl
+	cp ':'		! drive specified ?
+	jr nz,1f
+	ld a,(hl)
+	inc hl
+	inc hl
+	dec a
+	and 15
+	inc a		! now 1<= a <= 16
+	ld (de),a
+1:	inc de
+	ld b,8		! filename maximum of 8 characters
+1:	ld a,(hl)
+	or a
+	jr nz,8f
+	dec hl
+	ld a,'.'
+8:
+	inc hl
+	cp '.'
+	jr z,2f
+	and 0177	! no parity
+	bit 6,a
+	jr z,9f
+	and 0337	! UPPER case
+9:
+	ld (de),a
+	inc de
+	djnz 1b
+	ld a,(hl)
+	inc hl
+	cp '.'
+	jr z,3f
+	ld a,' '
+	ld (de),a
+	inc de
+	ld (de),a
+	inc de
+	ld (de),a
+	pop bc
+	ret		! filenames longer than 8 are truncated
+2:	ld a,' '	! fill with spaces
+0:	ld (de),a
+	inc de
+	djnz 0b
+3:	ld b,3		! length of extension
+1:	ld a,(hl)
+	inc hl
+	or a
+	jr z,4f
+	cp 0100
+	jp m,2f
+	and 0137
+2:	ld (de),a
+	inc de
+	djnz 1b
+	pop bc
+	ret
+4:	ld a,' '
+0:	ld (de),a
+	inc de
+	djnz 0b
+	pop bc
+	ret
+
+! various routines
+ux_close:
+	pop hl
+	ld a,l
+	sub 3
+	jp m,1f
+	cp maxfiles
+	call m,closefil
+1:	ld hl,0
+	jr phl
+
+closefil:
+	call findfile
+	ld a,(iy+openflag)
+	or a
+	jr z,3f
+	ld (iy+openflag),0
+	cp 1
+	jr z,2f
+	ld a,(iy+nleft)
+	cp 128
+	jr z,2f
+	call flsbuf
+2:
+	push bc
+	push iy
+	pop de
+	ld c,close
+	call bdos
+	pop bc
+3:	ret
+
+ux_ioctl:
+	pop hl
+	ld a,l
+	sub 3
+	jp p,1f
+	pop hl
+	ld a,h
+	cp 't'
+	jr nz,e.mon
+	ld a,l
+	cp 8
+	jr z,tiocgetp
+	cp 9
+	jr z,tiocsetp
+	jr e.mon
+1:	pop hl
+	pop hl
+	ld hl,-1
+	jr phl
+tiocgetp:
+	pop de
+	ld hl,ttymode
+2:	push bc
+	ld bc,6
+	ldir
+	ld h,b
+	ld l,c
+	pop bc
+	jr phl
+tiocsetp:
+	pop hl
+	ld de,ttymode
+	jr 2b
+
+ux_time:
+	call time4
+	jr loop
+
+ux_ftime:
+	pop hl
+	ld (retarea+6),hl
+	call time4
+	ld hl,(retarea+6)
+	pop de
+	ld (hl),e
+	inc hl
+	ld (hl),d
+	inc hl
+	pop de
+	ld (hl),e
+	inc hl
+	ld (hl),d
+	inc hl
+	xor a
+	ld (hl),a
+	inc hl
+	ld (hl),a
+	inc hl
+	ld (hl),a
+	inc hl
+	ld (hl),a
+	inc hl
+	ld (hl),a
+	inc hl
+	ld (hl),a
+	jr loop
+
+time4:
+	pop hl
+	ld (retarea),bc
+	ld (retarea+2),ix
+	ld (retarea+4),hl
+	ld hl,(timebuf+2)
+	push hl
+	ld hl,(timebuf)
+	push hl
+	ld hl,0
+	push hl
+	ld hl,50
+	push hl
+	call .dvu4
+	ld bc,(retarea)
+	ld ix,(retarea+2)
+	ld hl,(retarea+4)
+	jp (hl)
+ux_exit:
+	call uxfinish
+	ld c,reset
+	call bdos
+	! no return
+
+ux_creat:
+	call emptyfile
+	jr c,openfailed
+	pop hl
+	call parsename
+	pop hl			! file mode, not used under CP/M
+	push bc
+	push iy
+	push iy
+	pop de
+	ld c,delete
+	call bdos
+	pop de
+	ld c,makefile
+	call bdos
+	pop bc
+	ld l,1
+	jr afteropen
+ux_open:
+	call emptyfile
+	jr nc,1f
+openfailed:
+	pop hl
+	pop hl		! remove params
+	ld hl,EMFILE
+	push hl
+	jr phl
+1:
+	pop hl		! filename
+	call parsename
+	push bc
+	ld c,open
+	push iy
+	pop de
+	call bdos
+	pop bc
+	pop hl
+afteropen:
+	inc a
+	jr nz,1f
+	ld hl,ENOENT
+	push hl
+	jr phl
+1:
+	inc l
+	ld (iy+openflag),l
+	xor a
+	ld (iy+nleft),a
+	ld (iy+zcount),a
+	ld (iy+zsave),26
+	bit 1,l
+	jr z,2f
+	ld (iy+nleft),128
+2:
+	ld (iy+position),a
+	ld (iy+position+1),a
+	push iy
+	pop hl
+	push bc
+	ld b,128
+3:	dec hl
+	ld (hl),26
+	djnz 3b
+	pop bc
+	ld (iy+iopointer+1),h
+	ld (iy+iopointer),l
+	ld h,a
+	ld l,(iy+fildes)
+	push hl
+	ld l,a
+	jr phl
+
+ux_read:
+	pop hl
+	ld a,l
+	sub 3
+	jp p,readfile
+	ld a,(ttymode+4)
+	bit 5,a
+	jr z,1f			! not raw
+	push bc
+#ifdef	CPM1
+!raw echo interface
+	ld c,consolein
+	call bdos
+#else
+!no echo interface
+4:
+	ld c,diconio
+	ld e,0xff
+	call bdos
+	or a
+	jr z,4b
+!end of no echo interface
+#endif
+	pop bc
+	pop hl
+	ld (hl),a
+	pop hl
+	ld hl,1
+	push hl
+	ld hl,0
+	jr phl
+1:
+	ld hl,sibuf+1		! read from console assumed
+	dec (hl)
+	jp p,2f
+	dec hl			! go read console line
+	ld (hl),80		! max line length
+	push bc
+	push hl
+	ld c,readconsole
+	ex de,hl
+	call bdos
+	ld c,writeconsole
+	ld e,'\n'
+	call bdos
+	pop hl
+	pop bc
+	inc hl
+	inc (hl)
+	ld (siptr),hl		! ready for transfer
+	push hl
+	ld e,(hl)
+	ld d,0
+	add hl,de
+	ld (hl),'\r'
+	inc hl
+	ld (hl),'\n'
+	pop hl
+2:
+	push bc
+	pop iy
+	ld b,(hl)
+	inc b			! bytes remaining
+	pop hl			! copy to
+	pop de			! bytes wanted (probably 512)
+	push iy
+	ld iy,(siptr)		! copy from
+	xor a			! find out minimum of ramaining and wanted
+	or d
+	jr nz,3f		! more than 255 wanted (forget that)
+	ld a,b
+	cp e
+	jp m,3f			! not enough remaining
+	ld b,e
+3:
+	ld c,b			! keep copy
+0:
+	inc iy
+	ld a,(iy)
+	ld (hl),a
+	inc hl
+	djnz 0b
+	ld a,(sibuf+1)
+	sub c
+	inc a
+	ld (sibuf+1),a
+	ld (siptr),iy
+	pop hl
+	push bc
+	ld c,b
+	push bc			! load 0
+	ld b,h
+	ld c,l
+	jr loop
+readfile:
+	call findfile
+	pop de
+	pop hl			! count
+	push bc
+	ld bc,0
+0:
+	xor a
+	or l
+	jr z,1f
+	dec l
+3:
+! warning: this may not work if zcount overflows
+	ld a,(iy+zcount)
+	or a
+	jr nz,5f
+	ld a,(iy+zsave)
+	cp 26
+	jr z,4f
+	ld (iy+zsave),26
+	jr 8f
+4:
+	call getchar
+	jr c,2f
+	ld (de),a
+	sub 26		! CTRL-Z
+	jr z,7f
+	ld a,(iy+zcount)
+	or a
+	jr z,6f
+	ld a,(de)
+	ld (iy+zsave),a
+5:
+	ld a,26
+	dec (iy+zcount)
+8:
+	ld (de),a
+6:
+	inc de
+	inc bc
+	jr 0b
+1:
+	dec l
+	dec h
+	jp p,3b
+2:
+	pop hl
+	push bc
+	ld b,h
+	ld c,l
+	ld hl,0
+	jr phl
+7:
+	inc (iy+zcount)
+	jr 4b
+
+ux_write:
+	pop hl
+	ld a,l
+	sub 3
+	jp p,writefile
+	pop hl			! buffer address
+	pop de			! count
+	push de
+	ld iy,0
+	push iy
+	push bc
+	ld b,e			! count now in 'db'
+0:
+	ld a,b
+	or a
+	jr nz,1f
+	ld a,d
+	or a
+	jr nz,2f
+	pop bc
+	jr loop
+2:
+	dec d
+1:
+	dec b
+	ld e,(hl)
+	inc hl
+	push bc
+	push de
+	push hl
+	ld c,writeconsole
+	call bdos
+	pop hl
+	pop de
+	pop bc
+	jr 0b
+writefile:
+	call findfile
+	pop de
+	pop hl			! count
+	push bc
+	ld bc,0
+0:
+	xor a
+	or l
+	jr z,1f
+	dec l
+3:
+	ld a,(de)
+	inc de
+	call putchar
+	jr c,4f
+	inc bc
+	jr 0b
+1:
+	dec l
+	dec h
+	jp p,3b
+	ld iy,0
+2:
+	pop hl
+	push bc
+	ld b,h
+	ld c,l
+	push iy
+	jr loop
+4:
+	ld iy,ENOSPC
+	jr 2b
+
+ux_unlink:
+	pop hl
+	ld iy,fcb
+	call parsename
+	push bc
+	ld c,delete
+	ld de,fcb
+	call bdos
+	pop bc
+	inc a
+	jr nz,1f
+	ld hl,ENOENT
+	jr phl
+1:
+	ld hl,0
+	jr phl
+
+ux_getpid:
+	ld hl,12345		! nice number
+	jr phl
+
+ux_exece:
+	ld iy,fcb
+	pop hl
+	call parsename
+	pop hl
+	ld b,h;ld c,l
+	pop iy
+	ld ix,0x82
+	ld (ix-1),' '
+4:	ld h,b;ld l,c
+3:	ld e,(hl)
+	inc hl
+	ld d,(hl)
+	inc hl
+	ld b,h;ld c,l
+	ex de,hl
+	ld a,h
+	or l
+	jr z,1f
+2:
+	ld a,(hl)
+	inc hl
+	ld (ix),a
+	inc ix
+	or a
+	jr nz,2b
+	ld (ix-1),' '
+	jr 4b
+1:
+	ld (ix),'X'
+	ld (ix+1),'\r'
+	ld (ix+2),'\n'
+	ld (ix+3),'$'
+	ld de,0x81
+	push ix
+	ld c,printstring
+	call bdos
+	pop hl
+	ld de,-129
+	add hl,de
+	ld a,l
+	ld (0x80),a
+	jr warmstart
+
+
+
+
+dispat1:	! base for escaped opcodes
+.word	aar.l,	aar.z,	adf.l,	adf.z,	adi.l,	adi.z,	ads.l,	ads.z
+.word	adu.l,	adu.z,	and.l,	and.z,	asp.l,	ass.l,	ass.z,	bge.l
+.word	bgt.l,	ble.l,	blm.l,	bls.l,	bls.z,	blt.l,	bne.l,	cai.z
+.word	cal.l,	cfi.z,	cfu.z,	ciu.z,	cmf.l,	cmf.z,	cmi.l,	cmi.z
+.word	cms.l,	cms.z,	cmu.l,	cmu.z,	com.l,	com.z,	csa.l,	csa.z
+.word	csb.l,	csb.z,	cuf.z,	cui.z,	cuu.z,	dee.l,	del.p,	del.n
+.word	dup.l,	dus.l,	dus.z,	dvf.l,	dvf.z,	dvi.l,	dvi.z,	dvu.l
+.word	dvu.z,	fef.l,	fef.z,	fif.l,	fif.z,	inl.p,	inl.n,	inn.l
+.word	inn.z,	ior.l,	ior.z,	lar.l,	lar.z,	ldc.l,	ldf.l,	ldl.p
+.word	ldl.n,	lfr.l,	lil.p,	lil.n,	lim.z,	los.l,	los.z,	lor.s0
+.word	lpi.l,	lxa.l,	lxl.l,	mlf.l,	mlf.z,	mli.l,	mli.z,	mlu.l
+.word	mlu.z,	mon.z,	ngf.l,	ngf.z,	ngi.l,	ngi.z,	nop.z,	rck.l
+.word	rck.z,	ret.l,	rmi.l,	rmi.z,	rmu.l,	rmu.z,	rol.l,	rol.z
+.word	ror.l,	ror.z,	rtt.z,	sar.l,	sar.z,	sbf.l,	sbf.z,	sbi.l
+.word	sbi.z,	sbs.l,	sbs.z,	sbu.l,	sbu.z,	sde.l,	sdf.l,	sdl.p
+.word	sdl.n,	set.l,	set.z,	sig.z,	sil.p,	sil.n,	sim.z,	sli.l
+.word	sli.z,	slu.l,	slu.z,	sri.l,	sri.z,	sru.l,	sru.z,	sti.l
+.word	sts.l,	sts.z,	str.s0,	tge.z,	tle.z,	trp.z,	xor.l,	xor.z
+.word	zer.l,	zer.z,	zge.l,	zgt.l,	zle.l,	zlt.l,	zne.l,	zrf.l
+.word	zrf.z,	zrl.p,	dch.z,	exg.s0,	exg.l,	exg.z,	lpb.z
+
+dispat2:	! base for 4 byte offsets
+.word	ldc.f
+
+
+ignmask: .word 0	! ignore mask (variable)
+retarea: .word 0	! base of buffer for result values (max 8 bytes)
+	 .word 0
+	 .word 0
+	 .word 0
+
+trapproc:
+	.word 0
+
+nextp:	.byte 0
+
+header:
+ntext:	.word 0
+ndata:	.word 0
+nproc:	.word 0
+entry:	.word 0
+nline:	.word 0
+
+hp:	.word 0
+pb:	.word 0
+pd:	.word 0

+ 474 - 0
mach/z80/int/fpp.s

@@ -0,0 +1,474 @@
+! floating point pakket voor Z80
+! geimplementeerd zoals beschreven in 
+! Electronica top internationaal.
+! September 1979
+! Auteur: Hr. R. Beverdam, Zuidbroekweg 9,7642 NW  Wierden
+
+xa:	.space 1
+fpac:
+fal:	.space 1
+fan:	.space 1
+fam:	.space 1
+fax:	.space 1
+xo:	.space 1
+fpop:
+fol:	.space 1
+fon:	.space 1
+fom:	.space 1
+fox:	.space 1
+	.errnz xa/256-fox/256
+
+fpsub:
+	call fpcomp		! inverteer fpacc
+fpadd:
+	ld de,(fam)		! d fax,e fam
+	ld bc,(fom)		! b fox,c fom
+	ld a,e			! test fpacc
+	or a			! 0?
+	jr z,movop		! ja: som=fpop dus verplaats
+	xor a
+	add a,c
+	ret z			! som is dus fpacc, klaar
+	ld a,b
+	sub d			! a:=fox-fax
+	ld l,a			! bewaar verschil exponenten
+	jp p,skpneg		! maak positief
+	neg
+skpneg:
+	cp 0x18			! verschil meer dan 23?
+	ld a,l
+	jp m,lineup		! spring indien binnen bereik
+	and a			! getallen te groot tov elkaar
+	ret m			! klaar als fpacc het grootst
+movop:
+	ld hl,fol		! verplaats fpop naar fpacc
+	ld de,fal		! want fpop is het antwoord
+	ld bc,4
+	ldir
+	ret
+lineup:
+	and a			! kijk welke groter is
+	jp m,shifto		! spring als fpop>fpac
+	inc a			! bereken sa
+	ld b,a			! save sa in b register
+	ld a,1			! so 1
+	push af			! bewaar so op stapel
+	jr shacop		! gr schuiven
+shifto:
+	neg			! bereken fox-fax
+eqexp:
+	inc a			! so 1+(fox-fax)
+	push af			! bewaar so op stapel
+	ld b,1			! sa 1
+shacop:
+	ld hl,(fal)		! l fal,h fan
+	xor a			! xa 0
+moracc:
+	sra e			! schuif fam
+	rr h			! fan
+	rr l			! fal
+	rra			! xa
+	inc d			! update voor fax
+	djnz moracc		! herhaal sa keer
+	ld (xa),a		! berg alles
+	ld (fal),hl		! weg in
+	ld (fam),de		! fpacc en xa
+	pop af			! haal so terug van stapel
+	ld b,a			! en zet in b register
+	xor a			! xo 0
+	ld hl,(fol)		! l fol,h fon
+morop:
+	sra c			! schuif: fom
+	rr h			!         fon
+	rr l			!         
+	rra			!         xo
+	djnz morop		! herhaal so keer
+	ld (xo),a
+	ld (fol),hl
+	ld (fom),bc		! berg alles weg in fpop en xo
+	ld de,xa
+	ld hl,xo
+	ld b,4
+	or a			! reset carry
+addmor:
+	ld a,(de)		! haal een byte
+	adc a,(hl)		! tel er een bij op
+	ld (de),a		! en berg de som weer op
+	inc e
+	inc l
+	djnz addmor		! herhaal dit 4 keer
+	jr fpnorm
+
+fpmult:
+	call setsgn
+	add a,(hl)		! bereken exponent produkt
+	ld (hl),a		! fax exponent produkt
+	ld l,fom%256
+	ex de,hl		! gebruik de als wijzer
+	xor a
+	ld h,a
+	ld l,a			! hoogste 16 bits van pp worden nul
+	exx
+	ld bc,(fal)
+	ld de,(fam)		! haal mc in registers
+	ld d,a			! d:=0 tbv 16-bit add
+	ld h,a
+	ld l,a			! middelste 16 bits van pp worden nul
+	ld ix,0			! laagste 16 bits ook
+	exx
+	ld c,3
+mult:
+	ld a,(de)		! haal een byte van mr
+	dec e
+	ld b,8			! bits in a byte
+shift:
+	rla			! schuif vooste bit in carry
+	exx
+	jr nc,noadd		! vooste bit is 0, dan niet optellen
+	add ix,bc		! pp:=pp+mc
+	adc hl,de		! continued
+noadd:
+	add ix,ix
+	adc hl,hl
+	exx
+	adc hl,hl		! dit schoof het hele partiele produkt <
+	djnz shift		! herhaal voor alle 8 bits
+	dec c
+	jr nz,mult		! herhaal voor 3 bytes
+	exx
+	rl l
+	rla
+	add a,h
+	ld (fal),a
+	ld a,d
+	exx
+	adc a,l
+	ld (fan),a		! rond getal in pp af en berg resultaat op
+	ld a,c
+	adc a,h
+	ld (fam),a
+	call fpnorm
+exmldv:
+	ld hl,xa
+	ld c,(hl)
+	jp resign		! fix sign
+
+fpdiv:
+	call setsgn
+	sub (hl)
+	ld (hl),a		! berg exponent quotient op
+	ld hl,(fol)
+	push hl
+	pop ix
+	ld de,(fal)
+	ld a,(fam)
+	or a			! fpacc = 0 ?
+	jr z,fperr		! fout, deling door nul
+	ld b,a			! b:=fam
+	ld a,(fom)
+	ld c,a
+	exx
+	ld hl,fam
+	ld e,3
+divide:
+	ld b,8
+mordiv:
+	exx
+	and a
+	sbc hl,de
+	sbc a,b			! probeer de aftrekking
+	jp m,nogo		! gaat niet
+	push hl
+	pop ix
+	ld c,a
+	ex af,af2		! quotient in tweede accumulator
+	scf
+	jr quorot
+nogo:
+	ex af,af2
+	or a
+quorot:
+	rla			! volgende bit in quotient
+	ex af,af2
+	add ix,ix		! schuif eventueel vernieuwde
+	rl c			! dd naar links
+	push ix
+	pop hl
+	ld a,c			! zet nieuwe dd in rekenregisters
+	exx
+	djnz mordiv		! herhaal 8 keer
+	ex af,af2
+	ld (hl),a		! zet een byte van het quotient in het geheugen
+	dec l
+	ex af,af2
+	dec e
+	jr nz,divide		! herhaal 3 keer
+	ld bc,(fal)
+	ld hl,(fam)		! haal quotient terug in cpu
+	bit 7,l
+	jp z,exmldv		! als niet te groot tekenherstellen
+	ld a,1			! wel te groot
+	add a,c			! eerst getal afronden
+	ld c,a
+	ld a,e
+	adc a,b
+	ld b,a
+	ld a,e
+	adc a,l
+	ld l,a
+shft:
+	inc h			! nu getal naar rechts schuiven
+	rr l
+	rr b
+	rr c
+	or a
+	bit 7,l
+	jr nz,shft		! door afronding weer te groot
+	ld (fal),bc
+	ld (fam),hl
+	jr exmldv		! inspecteer teken
+setsgn:
+	ld a,(fom)		! ******** setsgn ************
+	ld c,1			! teken -1
+	rlca			! fpop 0 ?
+	jr nc,tstacc		! nee
+	rrc c			! ja, dus teken:=teken*(-1)
+	ld hl,fol		! en inverteer fpop
+	call complm
+tstacc:
+	ld a,(fam)
+	rlca			! fpacc 0?
+	jr nc,init		! nee
+	rrc c			! ja dus teken:=teken*(-1)
+	call fpcomp
+init:
+	ld hl,xa		! initialiseer nog een paar registers
+	ld (hl),c
+	ld a,(fox)
+	ld l,fax%256
+	ret
+
+fpcif:
+	ld de,(fpac)		! integer to convert
+	xor a
+	sra d
+	rr e
+	rr a
+	ld (fan),de
+	ld (fal),a
+	ld a,16
+	ld (fax),a
+	jr fpnorm
+
+fpcfi:
+	ld a,(fax)
+	dec a
+	jp m,fpzero		! really integer zero here
+	sub 15
+	jp p,fperr		! overflow
+	ld de,(fan)
+	inc a
+	neg
+	jr z,2f
+	ld b,a
+	ld a,(fal)
+1:
+	sra d
+	rr e
+	rr a
+	djnz 1b
+2:
+	bit 7,d
+	jr z,0f
+	inc de
+0:
+	ld (fpac),de
+	ret
+
+fpcdf:
+	ld de,(fpac)
+	ld bc,(fpac+2)
+	ld h,31
+3:
+	ld a,b
+	and 0300
+	jr z,1f
+	cp 0300
+	jr z,1f
+	or a
+	jp p,2f
+	sra b
+	rr c
+	rr d
+	inc h
+2:
+	ld a,h
+	ld (fax),a
+	ld (fan),bc
+	ld a,d
+	ld (fal),a
+	ret
+1:
+	sla e
+	rl d
+	rl c
+	rl b
+	dec h
+	jr 3b
+
+fpcfd:
+	ld a,(fax)
+	dec a
+	jp m,fpzero
+	cp 32
+	jp p,fperr
+	sub 31
+	cpl
+	ld bc,(fan)
+	ld de,(fal)
+	ld d,e
+	ld e,0
+1:
+	dec a
+	jp m,2f
+	sra b
+	rr c
+	rr d
+	rr e
+	jr 1b
+2:
+	bit 7,b
+	jr z,3f
+	sla e
+	rl d
+	rl c
+	rl b
+3:
+	ld (fpac+2),bc
+	ld (fpac),de
+	ret
+fpfef:
+	ld a,(fox)
+	ld (fpac),a
+9:
+	bit 7,a
+	jr z,1f
+	ld a,0xFF
+	jr 2f
+1:
+	xor a
+2:
+	ld (fpac+1),a
+	xor a
+	ld (fox),a
+	ret
+fpcmf:
+	call fpsub
+	ld a,(fam)
+	ld (fpac),a
+	jr 9b
+fpfif:
+	call fpmult
+	ld a,(fax)
+	dec a
+	jp m,intzero
+	inc a
+	ld b,a
+	xor a
+	ld c,0200
+	ld d,a
+	ld e,a
+1:
+	sra c
+	rr d
+	rr e
+	djnz 1b
+	ld hl,fam
+	ld b,(hl)
+	ld a,c
+	and b
+	ld (fom),a
+	ld a,c
+	xor 0177
+	and b
+	ld (hl),a
+	dec l
+	ld b,(hl)
+	ld a,d
+	and b
+	ld (fon),a
+	ld a,d
+	cpl
+	and b
+	ld (hl),a
+	dec l
+	ld b,(hl)
+	ld a,e
+	and b
+	ld (fol),a
+	ld a,e
+	cpl
+	and b
+	ld (hl),a
+	ld a,(fax)
+	ld (fox),a
+	jr fpnorm
+intzero:
+	xor a
+	ld hl,fol
+	ld b,4
+1:	ld (hl),a
+	inc hl
+	djnz 1b
+	ret
+
+fpzero:
+	xor a
+	ld h,a
+	ld l,a
+	ld (fal),hl
+	ld (fam),hl
+	ret
+
+fpnorm:
+	ld a,(fam)
+	ld c,a
+	or a			! fpacc < 0 ?
+	call m,fpcomp		! ja -- inverteer
+	ld hl,(fal)
+	ld de,(fam)
+	ld a,l
+	or h
+	or e
+	jr z,fpzero		! als hele facc 0 is
+	ld a,e
+mortst:
+	bit 6,a			! test meest significante bit
+	jr nz,catch		! stop als bit is 1
+	add hl,hl		! schuif links zolang bit = 0
+	adc a,a
+	dec d			! pas fax ook aan
+	jr mortst
+catch:
+	ld e,a			! herstel nu fpacc in geheugen
+	ld (fal),hl
+	ld (fam),de
+resign:
+	bit 7,c			! test op teken
+	ret z			! positief, geen actie
+fpcomp:
+	ld hl,fal
+complm:
+	ld b,3			! inverteer alleen mantisse
+	xor a
+morcom:
+	sbc a,(hl)
+	ld (hl),a
+	inc hl
+	ld a,0
+	djnz morcom
+	or a
+	ret
+fperr:
+	scf
+	ret

+ 75 - 0
mach/z80/int/mli4.s

@@ -0,0 +1,75 @@
+.define .mli4
+
+! 32-bit multiply routine for z80
+! parameters:
+!   on stack
+
+
+
+! register utilization:
+!   ix: least significant 2 bytes of result
+!   hl: most  significant 2 bytes of result
+!   bc: least significant 2 bytes of multiplicand
+!   de: most  significant 2 bytes of multiplicand
+!   iy: 2 bytes of multiplier (first most significant,
+!	later least significant)
+!   a:  bit count
+.mli4:
+	!initialization
+	pop hl		! return address
+	pop de
+	ld (.mplier+2),de! least significant bytes of
+			! multiplier
+	pop de
+	ld (.mplier),de	! most sign. bytes
+	pop de		! least significant bytes of
+			! multiplicand
+	pop bc		! most sign. bytes
+	push hl		! return address
+	push iy		! LB
+	ld ix,0
+	xor a
+	ld h,a		! clear result
+	ld l,a
+	ld (.flag),a	! indicate that this is
+			! first pass of main loop
+	ld iy,(.mplier)
+	! main loop, done twice, once for each part (2 bytes)
+	! of multiplier
+1:
+	ld a,16
+	! sub-loop, done 16 times
+2:
+	add iy,iy	! shift left multiplier
+	jr nc,3f	! skip if most sign. bit is 0
+	add ix,de	! 32-bit add
+	adc hl,bc
+3:
+	dec a
+	jr z,4f		! done with this part of multiplier
+	add ix,ix	! 32-bit shift left
+	adc hl,hl
+	jr 2b
+4:
+	! see if we have just processed the first part
+	! of the multiplier (flag = 0) or the second
+	! part (flag = 1)
+	ld a,(.flag)
+	or a
+	jr nz,5f
+	inc a		! a := 1
+	ld (.flag),a	! set flag
+	ld iy,(.mplier+2)! least significant 2 bytes now in iy
+	add ix,ix	! 32-bit shift left
+	adc hl,hl
+	jr 1b
+5:
+	! clean up
+	pop iy		! restore LB
+	ex (sp),hl	! put most sign. 2 bytes of result
+			! on stack;  put return address in hl
+	push ix		! least sign. 2 bytes of result
+	jp (hl)		! return
+.data
+.flag:  .byte 0
+.mplier: .space 4