; ; FP and LONG functions for floating point and long packages ; INCLUDE "bds.lib" FUNCTION fp CALL arghak PUSH B ; save BC LXI H,COMMON$EXIT PUSH H ; save the common exit addr in the stack LDA arg1 ;Get code ptr RAL ;Multiply code by 2 MOV E,A MVI D,0 ;Move result to DE LXI H,JMPTAB ;Get JMPTAB addr DAD D ;Add offset to it XCHG ;Store result in DE LDAX D MOV L,A INX D LDAX D MOV H,A ;Move table addr to HL PCHL ;Jump to selected routine JMPTAB: DW XNORM DW XADD DW XSUB DW XMULT DW XDIV DW XFTOA COMMON$EXIT: POP B ; restore BC RET ; return to BDS C XNORM: CALL LD$OP1 CALL FPNORM EXIT0: CALL ST$ACC RET XADD: CALL LD$OP2 CALL FPADD JMP EXIT0 XSUB: CALL LD$OP2 CALL FPSUB JMP EXIT0 XMULT: CALL LD$OP2 CALL FPMULT JMP EXIT0 XDIV: CALL LD$OP2 CALL FPDIV JMP EXIT0 XFTOA: CALL LD$OP1 CALL FTOA RET LD$OP1: LHLD arg3 XCHG LXI H,FPACC-1 MVI M,0 INX H MVI C,5 CALL MOVE RET LD$OP2: CALL LD$OP1 LHLD arg4 XCHG LXI H,FPOP-1 MVI M,0 INX H MVI C,5 CALL MOVE RET ST$ACC: LHLD arg2 LXI D,FPACC MVI C,5 CALL MOVE RET FPNORM: LDA FPACC+3 ;Get MS byte of FPACC STA SIGN ;Save SIGN byte of FPACC ANA A ;If number is positive JP NZERO$TEST ;.. go test for zero LXI H,FPACC-1 ;Load addr of FPACC (+ xtra byte) MVI C,5 ;Load precision register CALL NEGATE ;Negate FPACC NZERO$TEST: LXI H,FPACC-1 MVI C,5 CALL ZERO$TEST ;If FPACC not zero JNZ NOTZERO ;.. go normalize STA FPACCX ;make sure exponent is zero RET NOTZERO: LXI H,FPACC-1 MVI C,5 CALL SHIFTL ;shift FPACC left LXI H,FPACCX DCR M ;subtract 1 from FPACC exponent LDA FPACC+3 ;get MS byte of FPACC ANA A ;if high order bit not no JP NOTZERO ;.. go do again ;compensate for last shift LXI H,FPACCX INR M DCX H MVI C,5 CALL SHIFTR LDA SIGN ;fetch original sign RAL ;shift sign bit into carry RNC ;exit if orig # was positive LXI H,FPACC-1 MVI C,5 CALL NEGATE ;2's complement FPACC RET ;Exit FPNORM FPADD: LXI H,FPACC MVI C,4 CALL ZERO$TEST ;if FPACC not = zero JNZ TEST$FPOP ;.. go test FPOP for zero LXI H,FPACC LXI D,FPOP MVI C,5 CALL MOVE ;Move FPOP to FPACC RET ;Exit FPADD TEST$FPOP: LXI H,FPOP MVI C,4 CALL ZERO$TEST ;if FPOP = 0 RZ ;.. exit FPADD LDA FPACCX LXI H,FPOPX SUB M ;if exponents are equal JZ ADD$SETUP ;.. go to add setup JP RANGE$TEST ;if diff of exp >=0,goto range test CMA INR A ;ABS of difference RANGE$TEST: CPI 32 ;if diff < 32 JM ALGN$OPRNDS ;.. we can go align the operands LXI H,FPACCX LDA FPOPX SUB M ;if exp of FPACC > exp of FPOP RM ;.. exit FPADD LXI D,FPOP LXI H,FPACC MVI C,5 CALL MOVE ;move FPOP to FPACC RET ;Exit FPADD ALGN$OPRNDS: LDA FPACCX LXI H,FPOPX SUB M ;subt exponents MOV B,A ;save difference of exponents JM SHFT$FPACC ;if diff neg, go shift FPACC ALGN$FPOP: LXI H,FPOPX CALL SHFT$LOOP ;shift FPOP & increment exponent DCR B ;Decrement diff register JNZ ALGN$FPOP ;loop until exponents are equal JMP ADD$SETUP ;go to add setup SHFT$FPACC: LXI H,FPACCX CALL SHFT$LOOP ;shift FPACC & increment exponent INR B ;increment difference register JNZ SHFT$FPACC ;loop until exponents are equal ADD$SETUP: XRA A STA FPACC-1 STA FPOP-1 LXI H,FPACCX CALL SHFT$LOOP ;shift FPACC right LXI H,FPOPX CALL SHFT$LOOP ;shift FPOP right LXI H,FPACC-1 LXI D,FPOP-1 MVI C,5 CALL ADDER ;add FPOP to FPACC CALL FPNORM ;normalize result RET ;exit FPADD SHFT$LOOP: INR M ;increment exponent DCX H ;decrement ptr MVI C,4 MOV A,M ;get MS byte ANA A ;if negative number JM SHFT$MINUS ;.. goto negative shift CALL SHIFTR ;shift mantissa RET SHFT$MINUS: STC ;set carry CALL SHFTR ;shift mantissa progatating sign RET ;exit FPSUB: LXI H,FPACC MVI C,4 CALL NEGATE JMP FPADD FPMULT: CALL SIGNJOB ;process the signs LXI H,WORK MVI C,8 CALL ZERO$MEMORY ;WORK := 0 (partial product) LXI H,FPACCX LDA FPOPX ADD M INR A ;compensate for algolrithm MOV M,A ;add FPOP exp to FPACC exponent LXI H,FPACC-4 MVI C,4 CALL ZERO$MEMORY ;clear multiplicand extra bytes LXI H,BITS MVI M,31 MULT$LOOP: LXI H,FPOP+3 MVI C,4 CALL SHIFTR ;shift multiplier right CC ADD$MULTIPLICAND ;add multiplicand if carry LXI H,WORK+7 MVI C,8 CALL SHIFTR ;shift partial product right LXI H,BITS DCR M ;decrement BITS counter JNZ MULT$LOOP ;if not zero, do again LXI H,WORK+7 MVI C,8 CALL SHIFTR ;shift once more for rounding LXI H,WORK+3 MOV A,M RAL ;fetch 32th bit ANA A ;if it is a 1 CM ROUND$IT ;.. round the result LXI D,WORK+3 LXI H,FPACC-1 MVI C,5 EXMLDV: CALL MOVE LDA SIGN ;fetch SIGN and save it on the stack PUSH PSW CALL FPNORM POP PSW ANA A RP LXI H,FPACC MVI C,4 CALL NEGATE RET ADD$MULTIPLICAND: LXI H,WORK LXI D,FPACC-4 MVI C,8 CALL ADDER RET ROUND$IT: MVI A,40H ADD M MVI C,4 RND$LOOP: MOV M,A INX H MVI A,0 ADC M DCR C JNZ RND$LOOP MOV M,A RET FPDIV: LXI H,FPOP MVI C,4 CALL ZERO$TEST JNZ DIV$SIGN LXI H,FPACC MVI C,5 CALL ZERO$MEMORY RET DIV$SIGN: CALL SIGNJOB LXI H,WORK MVI C,12 CALL ZERO$MEMORY MVI A,31 STA BITS LXI H,FPACCX LDA FPOPX MOV B,A MOV A,M SUB B INR A MOV M,A DIVIDE: CALL SETSUB ;WORK2 := dividend - divisor JM NOGO ;if minus, go put 0 in quotient LXI H,FPACC LXI D,WORK2 MVI C,4 CALL MOVE ;move subt results to dividend STC JMP QUOROT NOGO: ANA A QUOROT: LXI H,WORK+4 MVI C,4 CALL SHFTL ;Insert carry flag into quotient LXI H,FPACC MVI C,4 CALL SHFTL ;shift dividend left LXI H,BITS DCR M ;decrement BITS counter JNZ DIVIDE ;loop until BITS = zero CALL SETSUB ;1 more time for rounding JM DVEXIT ;if 24th bit = 0, goto exit LXI H,WORK+4 LXI D,ONE MVI C,4 CALL ADDER LXI H,WORK+7 MOV A,M ANA A JP DVEXIT MVI C,4 CALL SHIFTR LXI H,FPACCX INR M DVEXIT: LXI H,FPACC LXI D,WORK+4 MVI C,4 JMP EXMLDV SETSUB: LXI D,FPACC LXI H,WORK2 MVI C,4 CALL MOVE ;move dividend to work2 LXI H,WORK2 LXI D,FPOP MVI C,4 CALL SUBBER ;subtract divisor from work2 LDA WORK2+3 ANA A RET FTOA: LHLD arg2 SHLD ASCII$PTR MVI M,' ' LDA FPACC+3 ANA A JP BYSIGN MVI M,'-' LXI H,FPACC MVI C,4 CALL NEGATE BYSIGN: LHLD ASCII$PTR INX H MVI M,'0' INX H MVI M,'.' INX H SHLD ASCII$PTR XRA A STA EXP LXI H,FPACC MVI C,4 CALL ZERO$TEST JNZ SU$FTOA MVI C,7 LHLD ASCII$PTR ZERO$LOOP: MVI M,'0' INX H DCR C JNZ ZERO$LOOP SHLD ASCII$PTR JMP EXPOUT SU$FTOA: LXI H,FPACCX DCR M DECEXT: JP DECEXD MVI A,4 ADD M JP DECOUT CALL FPX10 DECREP: LXI H,FPACCX MOV A,M ANA A JMP DECEXT DECEXD: CALL FPD10 JMP DECREP DECOUT: LXI H,FPACC LXI D,ADJ MVI C,4 CALL ADDER LXI H,OUTAREA LXI D,FPACC MVI C,4 CALL MOVE LXI H,OUTAREA+4 MVI M,0 LXI H,OUTAREA MVI C,4 CALL SHIFTL CALL OUTX10 COMPEN: LXI H,FPACCX INR M JZ OUTDIG LXI H,OUTAREA+4 MVI C,5 CALL SHIFTR JMP COMPEN OUTDIG: MVI A,7 STA DIGCNT LXI H,OUTAREA+4 MOV A,M ANA A JZ ZERODG OUTDGS: LXI H,OUTAREA+4 MVI A,'0' ADD M LHLD ASCII$PTR MOV M,A INX H SHLD ASCII$PTR DECRDG: LXI H,DIGCNT DCR M JZ EXPOUT CALL OUTX10 JMP OUTDGS ZERODG: LXI H,EXP DCR M LXI H,OUTAREA MVI C,5 CALL ZERO$TEST JNZ DECRDG XRA A STA DIGCNT JMP DECRDG OUTX10: XRA A STA OUTAREA+4 LXI H,WORK LXI D,OUTAREA MVI C,5 CALL MOVE LXI H,OUTAREA MVI C,5 CALL SHIFTL LXI H,OUTAREA MVI C,5 CALL SHIFTL LXI D,WORK LXI H,OUTAREA MVI C,5 CALL ADDER LXI H,OUTAREA MVI C,5 CALL SHIFTL RET EXPOUT: LHLD ASCII$PTR MVI M,'E' INX H LDA EXP ANA A JP EXPOT CMA INR A STA EXP MVI M,'-' INX H LDA EXP EXPOT: MVI C,0 EXPLOOP: SUI 10 JM TOMUCH STA EXP INR C JMP EXPLOOP TOMUCH: MVI A,'0' ADD C MOV M,A INX H LDA EXP ADI '0' MOV M,A INX H MVI M,0 RET FPX10: LXI H,FPOP LXI D,TEN MVI C,5 CALL MOVE CALL FPMULT LXI H,EXP DCR M RET FPD10: LXI H,FPOP LXI D,ONE$TENTH MVI C,5 CALL MOVE CALL FPMULT LXI H,EXP INR M RET NEGATE: STC ;CARRY forces an add of 1 NEGAT$LOOP: MOV A,M ;fetch byte CMA ;complement it ACI 0 ;make it two's complement MOV M,A ;store the result INX H ;bump ptr DCR C ;decrement precision register JNZ NEGAT$LOOP ;if not done, go do it again RET ;Return to caller ZERO$TEST: XRA A ;clear A ORA M ;'OR' A with next byte INX H ;bump ptr DCR C ;decrement precision register JNZ ZERO$TEST+1 ;loop until done ANA A ;set flags RET SHIFTL: ANA A ;clear CARRY SHFTL: MOV A,M ;get next byte RAL ;shift it left MOV M,A ;store result INX H ;bump ptr DCR C ;decrement precision register JNZ SHFTL ;loop until done RET SHIFTR: ANA A SHFTR: MOV A,M RAR MOV M,A DCX H DCR C JNZ SHFTR RET ADDER: ANA A ADD$LOOP: LDAX D ADC M MOV M,A INX D INX H DCR C JNZ ADD$LOOP RET SUBBER: ANA A XCHG SUB$LOOP: LDAX D SBB M STAX D INX D INX H DCR C JNZ SUB$LOOP XCHG RET ZERO$MEMORY: MVI M,0 INX H DCR C JNZ ZERO$MEMORY RET MOVE: LDAX D MOV M,A INX D INX H DCR C JNZ MOVE RET SIGNJOB: LDA FPACC+3 STA SIGN ANA A JP CKFPOP LXI H,FPACC MVI C,4 CALL NEGATE CKFPOP: LXI H,SIGN LDA FPOP+3 XRA M MOV M,A LDA FPOP+3 ANA A RP LXI H,FPOP MVI C,4 CALL NEGATE RET DS 4 FPACC: DS 4 FPACCX: DS 1 DS 4 FPOP: DS 4 FPOPX: DS 1 SIGN: DS 1 WORK: DS 8 WORK2: DS 4 BITS: DS 1 ASCII$PTR: DS 2 EXP: DS 1 OUTAREA: DS 5 DIGCNT: DS 1 ONE$TENTH: DB 66H,66H,66H,66H,0FDH TEN: DB 0,0,0,50H,4 ADJ: DB 5,0,0,0 ONE: DB 80H,0,0,0 ENDFUNC  .