From 25eef41c3a097ff84fbcd2e4d6d26960d76f11c9 Mon Sep 17 00:00:00 2001 From: sater Date: Mon, 25 Jun 1984 16:22:03 +0000 Subject: [PATCH] Initial revision --- mach/z80/int/Makefile | 4 + mach/z80/int/READ_ME | 23 + mach/z80/int/atof.s | 280 +++ mach/z80/int/cv.c | 34 + mach/z80/int/dl.c | 200 ++ mach/z80/int/doas | 3 + mach/z80/int/dosort | 9 + mach/z80/int/dvi4.s | 74 + mach/z80/int/dvu4.s | 137 ++ mach/z80/int/eb.s | 2 + mach/z80/int/em.s | 4932 +++++++++++++++++++++++++++++++++++++++++ mach/z80/int/fpp.s | 474 ++++ mach/z80/int/mli4.s | 75 + 13 files changed, 6247 insertions(+) create mode 100644 mach/z80/int/Makefile create mode 100644 mach/z80/int/READ_ME create mode 100644 mach/z80/int/atof.s create mode 100644 mach/z80/int/cv.c create mode 100644 mach/z80/int/dl.c create mode 100644 mach/z80/int/doas create mode 100755 mach/z80/int/dosort create mode 100644 mach/z80/int/dvi4.s create mode 100644 mach/z80/int/dvu4.s create mode 100644 mach/z80/int/eb.s create mode 100644 mach/z80/int/em.s create mode 100644 mach/z80/int/fpp.s create mode 100644 mach/z80/int/mli4.s diff --git a/mach/z80/int/Makefile b/mach/z80/int/Makefile new file mode 100644 index 000000000..139a7e296 --- /dev/null +++ b/mach/z80/int/Makefile @@ -0,0 +1,4 @@ +CFLAGS=-O + +dl: dl.o + cc -n -o dl dl.o diff --git a/mach/z80/int/READ_ME b/mach/z80/int/READ_ME new file mode 100644 index 000000000..6b2a6a431 --- /dev/null +++ b/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 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 diff --git a/mach/z80/int/atof.s b/mach/z80/int/atof.s new file mode 100644 index 000000000..26c0a2e2e --- /dev/null +++ b/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 diff --git a/mach/z80/int/cv.c b/mach/z80/int/cv.c new file mode 100644 index 000000000..03811e276 --- /dev/null +++ b/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 + +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 +#include +#include + +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); +} diff --git a/mach/z80/int/doas b/mach/z80/int/doas new file mode 100644 index 000000000..5d30eae68 --- /dev/null +++ b/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 diff --git a/mach/z80/int/dosort b/mach/z80/int/dosort new file mode 100755 index 000000000..dfcbf7fa0 --- /dev/null +++ b/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 diff --git a/mach/z80/int/dvi4.s b/mach/z80/int/dvi4.s new file mode 100644 index 000000000..cf1ccbce0 --- /dev/null +++ b/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 diff --git a/mach/z80/int/dvu4.s b/mach/z80/int/dvu4.s new file mode 100644 index 000000000..f0489664e --- /dev/null +++ b/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 diff --git a/mach/z80/int/eb.s b/mach/z80/int/eb.s new file mode 100644 index 000000000..875035ed3 --- /dev/null +++ b/mach/z80/int/eb.s @@ -0,0 +1,2 @@ + .bss +eb: diff --git a/mach/z80/int/em.s b/mach/z80/int/em.s new file mode 100644 index 000000000..4e82dd114 --- /dev/null +++ b/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 diff --git a/mach/z80/int/fpp.s b/mach/z80/int/fpp.s new file mode 100644 index 000000000..fbec1550c --- /dev/null +++ b/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 diff --git a/mach/z80/int/mli4.s b/mach/z80/int/mli4.s new file mode 100644 index 000000000..ce7927ef9 --- /dev/null +++ b/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