#
! 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