	NAME	FPCNV
	CSEG

	PUBLIC	FFLOAT,FFIX,FINP,FOUT
	EXTRN	FSTOR,FZERO,FABS,FTEST,FLOAD,FMUL
	EXTRN	FDIV,FADD,ADD10,LSH,RSH,FCOMP
	EXTRN	OVER,ACCE,ACCS,ACC1,ACC2,ACC3,SF
	EXTRN	FTEN,RND0
	EXTRN	ADRL,ADRH,TMP1,TMP2,TMP3,VALE,VAL1,VAL2,VAL3,TMP4
 ;     8080 BINARY FLOATING POINT SYSTEM
 ;     FORMAT CONVERSION PACKAGE
 ;     PROGRAMMER  CAL OHME
 ;     DATE  26 DECEMBER 1973


 ;     SUBROUTINE TO CONVERT FROM FIXED
 ;     POINT TO FLOATING POINT FORMAT.
 FFLOAT: MOV     L,E;       INPUT EXPONENT
        MOV     E,D;       4TH INPUT FRACTION
        MOV     D,C;       3RD INPUT FRACTION
        MOV     C,B;       2ND INPUT FRACTION
        MOV     B,A;       1ST INPUT FRACTION
        MOV     A,L;       INPUT EXPONENT
        XRI     80H;  APPLY EXPONENT BIAS
        LXI     H,ACCE;  TO ADDR ACCUM EXPONENT
        MOV     M,A;       ACCUMULATOR EXPONENT
        INR     L;       TO ADDRESS ACCUM SIGN
        MVI     M,80H;  SET ACCUM SIGN POSITIVE
        INR     L;       TO ADDR ACCUM 1ST FRCTN
        MOV     A,B;       1ST INPUT FRACTION
        ANA     A       ;       SET SIGN BIT
        RAL     ;       INPUT SIGN TO CARRY
        JMP     ADD10; COMPLETE CONVERSION
 ;     SUBROUTINE TO CONVERT FROM FLOATING
 ;     POINT TO FIXED POINT FORMAT.
 FFIX:  LXI     H,ACCE;  TO ADDRESS SCRATCH BANK
        MOV     A,M;       ACCUMULATOR EXPONENT
        ANA     A       ;       SET CONTROL BITS
        JZ      FIX1;  IF ACCUMULATOR IS ZERO
        MOV     A,E;       INPUT EXPONENT
        ADI     7FH;  APPLY BIAS - 1
        SUB     M;       SHIFT COUNT - 1
        RC      ;       RETURN IF ACCUM TOO LARGE
        CPI     1FH;  COMPARE TO LARGE SHIFT
        JNC     FIX1;  IF ACCUMULATOR TOO SMALL
        ADI     1;     SHIFT COUNT
        MVI     L,LOW(ACC1);  TO ADDR ACCUM 1ST FRCTN
        MOV     B,M;       ACCUMULATOR 1ST FRACTION
        INR     L;       TO ADDR ACCUM 2ND FRCTN
        MOV     C,M;       ACCUMULATOR 2ND FRCTN
        INR     L;       TO ADDR ACCUM 3RD FRCTN
        MOV     D,M;       ACCUMULATOR 3RD FRCTN
        CALL    RSH;   POSITION THE FRACTION
        MVI     L,LOW(ACCS);  TO ADDR ACCUM SIGN
        MOV     A,M;       ACCUMULATOR SIGN
        ANA     A       ;       SET CONTROL BITS
        CP      FCOMP;  COMPLEMENT FRCTN IF NEG
        MVI     A,1;     NON-ZERO
        ORA     B;       SET CONTROL BITS FOR EXIT
        MOV     A,B;       1ST RESULT
        MOV     B,C;       2ND RESULT
        MOV     C,D;       3RD RESULT
        MOV     D,E;       4TH RESULT
        RET     ;       RETURN TO CALLER
 FIX1:  XRA     A;       ZERO
        MOV     B,A;       ZERO
        MOV     C,A;       ZERO
        MOV     D,A;       ZERO
        RET     ;       RETURN TO CALLER
        DB      0;     CHECKSUM WORD
 ;     INP SUBROUTINE ENTRY POINT.
 ;     INITIALIZE TEMPORARY STORAGE.
 FINP:  MOV     E,M;       FIRST CHARACTER OF STRING
        CALL    SVAD;  SET CHAR ADDR, PNT FLG, EXP
        INR     L;       TO ADDRESS VALUE SIGN
        MVI     M,80H;  SET VALUE SIGN POSITIVE
        LXI     H,ACCE;  TO ADDR ACCUM EXPONENT
        MOV     M,D;       SET ACCUM TO ZERO
        MOV     A,E;       FIRST CHARACTER
        CPI     0F0H;  COMPARE TO SPACE
        JZ      INP1;  IF SPACE CHARACTER
        CPI     0FBH;  COMPARE CHAR TO PLUS
        JZ      INP1;  IF PLUS SIGN
        CPI     0FDH;  COMPARE TO MINUS
        JNZ     INP2;  IF NOT MINUS SIGN
        LXI     H,TMP3;  TO ADDR VALUE SIGN
        MOV     M,D;       SET VALUE SIGN NEGATIVE
 ;     ANALYZE NEXT CHARACTER IN STRING.
 INP1:  CALL    CHAD;  CALL CHAR ADDR SBRTN
        MOV     A,M;       NEXT CHARACTER
 INP2:  MVI     B,0;     DIGIT 2ND WD OR DEC EXP
        CPI     0FEH;  COMPARE TO DECIMAL POINT
        JZ      INP3;  IF DECIMAL POINT
        CPI     15H;  COMPARE TO EXPONENT SIGN
        JZ      INP4;  IF EXPONENT SIGN
        CPI     0AH;   SET CARRY IF CHAR IS DIGIT
        JNC     INP8;  IF CHAR IS NOT A DIGIT
        LXI     H,TMP4;  TO ADDR CURRENT DIGIT
        MOV     M,A;       SAVE CURRENT DIGIT
        LXI     H,FTEN;  TO ADDR FLOATING TEN
        CALL    FMUL;   MULTIPLY BY TEN
        MVI     L,LOW(VALE);  TO ADDR VALUE
        CALL    FSTOR;   STORE OLD VALUE TIMES TEN
        INR     L;       TO ADDR CURRENT DIGIT
        MOV     A,M;       CURRENT DIGIT
        MVI     B,0;     CLEAR 2ND WORD OF DIGIT
        MOV     C,B;       CLEAR 3RD WORD OF DIGIT
        MOV     D,B;       CLEAR 4TH WORD OF DIGIT
        MVI     E,8;  INDICATE DIGIT IS IN REG A
        CALL    FFLOAT;   CONVERT DIGIT TO FLOATING PNT
        MVI     L,LOW(VALE);  TO ADDR VALUE
        CALL    FADD ;   ADD OLD VALUE TIMES TEN
        MVI     L,LOW(TMP2);  TO ADDR DEC PNT FLAG
        MOV     A,M;       DECIMAL POINT FLAG
        ANA     A       ;       SET CONTROL BITS
        JZ      INP1;  IF NO DEC PNT ENCOUNTERED
        DCR     L;       TO ADDR INPUT EXPONENT
        MOV     B,M;       INPUT EXPONENT
        DCR     B;       DECREMENT INPUT EXPONENT
        MOV     M,B;       UPDATE INPUT EXPONENT
        JMP     INP1;  TO GET NEXT CHARACTER
 INP3:  LXI     H,TMP2;  TO ADDR DEC PNT FLAG
        XRA     M;       ZERO IF FLAG SET
        MOV     M,A;       SET DEC PNT FLAG
        JNZ     INP1;  IF FLAG NOT ALREADY SET
        JMP     INP8;  IF 2ND DEC PNT
 ;     PROCESS DECIMAL EXPONENT.
 INP4:  CALL    CHAD;  CALL CHAR ADDR SBRTN
        MOV     A,M;       NEXT CHARACTER OF STRING
        MOV     B,A;       CURRENT CHARACTER
        SUI     0FDH;  COMPARE TO MINUS CHAR
        MOV     E,A;       CHAR - MINUS SIGN
        JZ      INP5;  IF MINUS SIGN
        ADI     2;     COMPARE TO PLUS CHAR
        MOV     A,B;       CURRENT CHARACTER
        JNZ     INP6;  IF NOT PLUS SIGN
 INP5:  INR     L;       TO ADDRESS NEXT CHAR
        MOV     A,M;       NEXT CHARACTER OF STRING
 INP6:  MVI     B,0;     POSSIBLE DEC EXPONENT
        CPI     0AH;   SET CARRY IF CHAR IS DIGIT
        JNC     INP8;  IF CHAR IS NOT A DIGIT
        MOV     B,A;       DEC EXP EQUAL DIGIT
        INR     L;       TO ADDRESS NEXT CHAR
        MOV     A,M;       NEXT CHARACTER OF STRING
        CPI     0AH;   SET CARRY IF CHAR IS DIGIT
        JNC     INP7;  IF CHAR IS NOT A DIGIT
 ;     FORM COMPLETE DECIMAL EXPONENT.
        MOV     C,A;       LS DIGIT OF DEC EXP
        MOV     A,B;       MS DIGIT OF DEC EXP
        ADD     A;       2 * MS DIGIT
        ADD     A;       4 * MS DIGIT
        ADD     B;       5 * MS DIGIT
        ADD     A;       10 * MS DIGIT
        ADD     C;       10 * MS + LS DIGIT
        MOV     B,A;       DECIMAL EXPONENT
 INP7:  MOV     A,E;       SIGN OF DEC EXPONENT
        ANA     A       ;       SET CONTROL BITS
        JNZ     INP8;  IF SIGN PLUS
        SUB     B;       COMPLEMENT DEC EXP
        MOV     B,A;       DECIMAL EXPONENT
 INP8:  LXI     H,TMP3;  TO ADDRESS SCRATCH BANK
        MOV     C,M;       INPUT SIGN
        LXI     H,ACCS;  TO ADDRESS ACCUM SIGN
        MOV     M,C;       ACCUMULATOR SIGN
        MOV     A,B;       DECIMAL EXPONENT
 ;     CONVERT DECIMAL EXPONENT TO BINARY.
 INP9:  LXI     H,TMP1;  TO ADDRESS DEC EXPONENT
        ADD     M;       ADJUST DECIMAL EXPONENT
        JZ      FTEST;   IN DEC EXP IS ZERO
        MOV     M,A;       CURRENT DECIMAL EXPONENT
        LXI     H,FTEN;  TO ADDR FLOATING TEN
        JP      INP10; IF MULTIPLY REQUIRED
        CALL    FDIV;   DIVIDE BY TEN
        MVI     A,1;     TO INCREMENT DEC EXP
        JMP     INP9;  TO TEST FOR COMPLETION
 INP10: CALL    FMUL;   MULTIPLY BY TEN
        RC      ;       RETURN IF OVERFLOW
        MVI     A,0FFH;  TO DECREMENT DEC EXP
        JMP     INP9;  TO TEST FOR COMPLETION
 ;     OUT SUBROUTINE ENTRY POINT.
 ;     SAVE CHARACTER ADDRESS AND ACCUMULATOR.
 FOUT:  DCR     L;       DECREMENT CHARACTER ADDRESS
        CALL    SVAD;  SET CHAR ADDR, DIG CNT, DEC EXP
        CALL    FTEST;   LOAD ACCUM TO REGISTERS
        LXI     H,VALE;  TO ADDR ACCUM SAVE AREA
        CALL    FSTOR;   CALL REG STR SUBROUTINE
 ;     OUTPUT SIGN CHARACTER.
        CALL    CHAD;  CALL CHAR ADDR SBRTN
        MVI     M,0F0H;  STORE SPACE CHARACTER
        ANA     A       ;       SET CONTROL BITS
        JZ      OUT3;  IF ACCUMULATOR IS ZERO
        MOV     E,A;       ACCUMULATOR EXPONENT
        MOV     A,B;       ACCUM SIGN AND 1ST FRCTN
        ANA     A       ;       SET CONTROL BITS
        MOV     A,E;       ACCUMULATOR EXPONENT
        JP      OUT1;  IF ACCUM IS POSITIVE
        MVI     M,0FDH;  CHANGE SIGN TO MINUS
 ;     SCALE ACCUMULATOR TO .1 - 1. RANGE.
 OUT1:  CPI     7EH;  COMPARE TO SMALL EXPONENT
 OUT2:  LXI     H,FTEN;  TO ADDR FLOATING TEN
        JC      OUT4;  IF EXPONENT TOO SMALL
        CPI     81H;  COMPARE TO LARGE EXP
        JC      OUT5;  IF EXP SMALL ENOUGH
        CALL    FDIV;   DIVIDE BY TEN
 OUT3:  LXI     H,TMP2;  TO ADDRESS SCRATCH BANK
        MOV     E,M;       DECIMAL EXPONENT
        INR     E;       INCREMENT DECIMAL EXPONENT
        MOV     M,E;       DECIMAL EXPONENT
        JMP     OUT2;  TO TEST FOR SCALING COMPLETE
 OUT4:  CALL    FMUL;   MULTIPLY BY TEN
        LXI     H,TMP2;  TO ADDR DECIMAL EXPONENT
        MOV     E,M;       DECIMAL EXPONENT
        DCR     E;       DECREMENT DECIMAL EXPONENT
        MOV     M,E;       DECIMAL EXPONENT
        JMP     OUT1;  TO TEST FOR SCALING COMPLETE
 ;     ROUND THE VALUE BY ADDING .00000005.
 OUT5:  CALL    FABS;   SET ACCUM POSITIVE
        LXI     H,RND0;  TO ADDRESS ROUNDER
        CALL    FADD;   ADD THE ROUNDER
        CPI     81H;  CHECK FOR OVERFLOW
        JNC     OUT2;  IF EXP TOO LARGE
 ;     SET DIGIT COUNTS.
        LXI     H,TMP2;  TO ADDR DECIMAL EXPONENT
        MOV     A,M;       DECIMAL EXPONENT
        MOV     E,A;       DIGITS BEFORE DEC POINT
        CPI     8;  COMPARE TO LARGE EXP
        JC      OUT6;  IF EXPONENT IN RANGE
        MVI     E,1;     DIGITS BEFORE DEC POINT
 OUT6:  SUB     E;       ADJUST DEC EXPONENT
        MOV     M,A;       DECIMAL EXPONENT
        MVI     A,7;     TOTAL NUMBER OF DIGITS
        SUB     E;       DIGITS AFTER DECIMAL PNT
        INR     L;       TO ADDR 2ND DIGIT CNT
        MOV     M,A;       DIGITS AFTER DECIMAL POINT
        DCR     E;       DECREMENT DIGIT COUNT
        MOV     A,E;       DIGITS BEFORE DEC PNT
 ;     OUTPUT SIGNIFICANT DIGITS.
 OUT7:  LXI     H,TMP1;  TO ADDR DIGIT COUNT
        ADD     M;       ADJUST DIGIT COUNT
        MOV     M,A;       NEW DIGIT COUNT
        JM      OUT8;  IF COUNT RUN OUT
        LXI     H,FTEN;  TO ADDR FLOATING TEN
        CALL    FMUL;   MULTIPLY BY TEN
        MVI     E,8;   TO PLACE DIGIT IN REG A
        CALL    FFIX;   CONVERT TO FIXED FORMAT
        CALL    CHAD;  CALL CHAR ADDR SBRTN
        MOV     M,A;       OUTPUT DECIMAL DIGIT
        XRA     A;       CLEAR CURRENT DIGIT
        MVI     E,8;  BINARY SCALING FACTOR
        CALL    FFLOAT;   RESTORE VALUE MINUS DIGIT
        MVI     A,0FFH;  TO ADJUST DIGIT CNT
        JMP     OUT7;  LOOP FOR NEXT DIGIT
 OUT8:  LXI     H,TMP3;  TO ADDR 2ND DIGIT CNT
        MOV     A,M;       DIGITS AFTER DECIMAL PNT
        MVI     M,0FFH;  SET 2ND COUNT NEG
        ANA     A       ;       SET CONTROL BITS
        JM      OUT9;  IF 2ND COUNT RAN OUT
        CALL    CHAD;  CALL CHAR ADDR SBRTN
        MVI     M,0FEH;  STORE DECIMAL POINT
        JMP     OUT7;  LOOP FOR NEXT DIGIT
 OUT9:  DCR     L;       TO ADDR DECIMAL EXP
        ANA     M       ;       DECIMAL EXPONENT
        JZ      OUT13; IF DECIMAL EXPONENT IS ZERO
 ;     OUTPUT DECIMAL EXPONENT.
        MVI     B,0FBH;  PLUS CHARACTER
        JP      OUT10; IF EXPONENT IS POSITIVE
        MVI     B,0FDH;  CHANGE SIGN TO MINUS
        MOV     C,A;       NEGATIVE EXPONENT
        XRA     A;       ZERO
        SUB     C;       COMPLEMENT EXPONENT
 OUT10: MVI     C,0FFH;  EMBRYO TENS DIGIT
 OUT11: MOV     D,A;       UNITS DIGIT
        INR     C;       INCREMENT TENS DIGIT
        SUI     0AH;  REDUCE REMAINDER
        JNC     OUT11; IF MORE TENS
        MVI     A,15H;  EXPONENT SIGN
 OUT12: CALL    CHAD;  CALL CHAR ADDR SBRTN
        CALL    FSTOR;   STORE LAST 4 CHARACTERS
        LXI     H,VALE;  TO ADDRESS ACCUM SAVE AREA
        JMP     FLOAD;   RESTORE ACCUM AND EXIT
 ;     OUTPUT 4 SPACES IF EXPONENT IS ZERO.
 OUT13: MVI     A,0F0H;  SPACE CHARACTER
        MOV     B,A;       SPACE CHARACTER
        MOV     C,A;       SPACE CHARACTER
        MOV     D,A;       SPACE CHARACTER
        JMP     OUT12; TO STORE CHARACTERS
 ;     SUBROUTINE TO SAVE CHARACTER STRING ADDR.
 SVAD:  MOV     A,L;       CHARACTER STRING WORD
        MOV     B,H;       CHARACTER STRING BANK
        MVI     C,0;     INPUT EXP OR DIGIT CNT
        MOV     D,C;       DEC PNT FLAG OR DEC EXP
        LXI     H,ADRL;  TO ADDR CHAR STRING WORD
        CALL    FSTOR;   STORE A, B, C, AND D
        RET     ;       RETURN TO CALLER
 ;     SUBROUTINE TO OBTAIN NEXT CHARACTER ADDR.
 CHAD:  LXI     H,ADRL;  TO ADDRESS SCRATCH BANK
        MOV     E,M;       CHARACTER STRING WORD
        INR     E;       TO ADDR NEXT CHARACTER
        MOV     M,E;       UPDATE CHAR STRING WORD
        INR     L;       TO ADDR CHAR STRING BANK
        MOV     H,M;       CHARACTER STRING BANK
        MOV     L,E;       CHARACTER STRING WORD
        RET     ;       RETURN TO CALLER
	END
