; --------------------------------------------------------------------------- ; Deze file bevat de afhandeling van floating point functies. Deze functies ; testen niet of de 80x87 processor aanwezig is. Ze mogen pas aangeroepen ; worden als getest is of de coprocessor aanwezig is. Dit kan met subfunctie ; #00. ; Met subfunctie #00 kan eveneens ingesteld worden met welke floating point ; notatie gewerkt dient te worden. Ondersteund worden Atom notatie en Intel8 ; --------------------------------------------------------------------------- ; Auteur: Roland Leurs ; december 1995 ; --------------------------------------------------------------------------- ATOM DQ 0 ; ATOM FP GETAL INTEL DQ 0 ; INTEL FP GETAL COPROC DB 0 ; COPROCESSOR TYPE FPMODE DB 0 ; FLOATING POINT MODE CONST180 DQ 180.0 ; CONSTANTE WAARDE 180 HALF DQ 0.5 ; CONSTANTE WAARDE 0.5000 ; --------------------------------------------------------------------------- ; Algemene floating point subroutines ; --------------------------------------------------------------------------- ATEL PROC NEAR ; CONVERSIE VAN ATOM->INTEL8 XOR AX,AX ; CLEAR INTEL WAARDE MOV WORD PTR INTEL[0],AX MOV WORD PTR INTEL[2],AX MOV WORD PTR INTEL[4],AX MOV WORD PTR INTEL[6],AX MOV AH,BYTE PTR ATOM[1] ; ATOM MANTISSA NAAR AX:BX MOV AL,BYTE PTR ATOM[2] MOV BH,BYTE PTR ATOM[3] MOV BL,BYTE PTR ATOM[4] XOR DX,DX ; DX OOK BIJ INTEL MANTISSA MOV CX,0BH ; LAADT TELLER ATEL1: SHR AX,1 ; SCHUIF MANTISSA DRIE BITS RCR BX,1 RCR DX,1 LOOP ATEL1 MOV CL,BYTE PTR ATOM[1] ; LAADT SIGN BIT IN CL7 SHL AX,1 ; MAAK PLAATS VOOR SIGN BIT SHL CL,1 ; ZET SIGN BIT IN CARRY RCR AX,1 ; SCHUIF SIGN BIT IN AX AND AX,1000000000001111B ; EXPONENT NOG BEREKENEN MOV CL,BYTE PTR ATOM[0] ; LAADT EXPONENT IN CL XOR CL,80H ; INVERTEER BIAS BIT XCHG AX,CX ; WISSEL AX EN CX TIJDELIJK CBW XCHG AX,CX ; WISSEL AX EN CX WEER ADD CX,1022 ; BEREKEN INTEL'S EXPONENT SHL CX,1 ; RESULTAAT OPSCHUIVEN SHL CX,1 SHL CX,1 SHL CX,1 XOR AX,CX ; EXPONENT TOEVOEGEN MOV WORD PTR INTEL[6],AX ; RESULTAAT OPSLAAN MOV WORD PTR INTEL[4],BX MOV WORD PTR INTEL[2],DX RET ; EINDE ROUTINE ATEL ENDP INTOM PROC NEAR ; CONVERSIE VAN INTEL8->ATOM MOV AH,BYTE PTR INTEL[7] ; LAADT MANTISSA IN AX:BX:BX MOV AL,BYTE PTR INTEL[6] MOV BH,BYTE PTR INTEL[5] MOV BL,BYTE PTR INTEL[4] MOV DH,BYTE PTR INTEL[3] MOV DL,BYTE PTR INTEL[2] MOV CX,11 ; LAADT TELLER INTOM1: SHL DX,1 ; SCHUIF LINKS RCL BX,1 RCL AX,1 LOOP INTOM1 ; ELF MAAL DOEN SHL AX,1 ; EVEN OPSCHUIVEN MOV CL,BYTE PTR INTEL[7] ; LEES TEKEN VAN INTEL SHL CL,1 ; SCHUIF TEKEN IN CARRY RCR AX,1 ; SCHUIF TEKEN IN MANTISSA MOV BYTE PTR ATOM[1],AH ; ATOM MANTISSA WEGSCHRIJVEN MOV BYTE PTR ATOM[2],AL MOV BYTE PTR ATOM[3],BH MOV BYTE PTR ATOM[4],BL MOV AH,BYTE PTR INTEL[7] ; LAADT INTEL EXPONENT MOV AL,BYTE PTR INTEL[6] MOV CL,4 ; LAADT TELLER SHR AX,CL ; BEPAAL EXPONENT AND AX,7FFH ; ALLEEN ONDERSTE 11 BITS SUB AX,1022 ; ATOM EXPONENT BEREKENEN PUSHF ; SAVE CARRY SHL AL,1 ; EVEN PLAATSMAKEN VOOR BIAS POPF ; HAAL CARRY TERUG RCR AL,1 ; ZET CARRY ALS BIAS XOR AL,80h ; INVERT OM KLOPPEND TE MAKEN MOV BYTE PTR ATOM[0],AL ; BERG ATOM EXPONENT OP RET ; EINDE ROUTINE INTOM ENDP ZENDREAL PROC NEAR ; STUUR FP GETAL NAAR ATOM CMP FPMODE,0 ; TEST OP ATOM MODE JNE ZENDREAL1 ; SPRING INDIEN INTEL MODE CALL INTOM ; CONVERTEER WAARDE NAAR ATOM MOV SI,OFFSET ATOM ; LAADT ADRES ATOM MODE MOV CX,5 ; LEES AANTAL TE ZENDEN BYTES JMP SHORT ZENDREAL2 ; GEDWONGEN SPRONG ZENDREAL1: MOV SI,OFFSET INTEL ; LAADT ADRES INTEL MODE MOV CX,8 ; LAADT AANTAL TE ZENDEN BYTES ZENDREAL2: MOV AL,BYTE PTR [SI] ; LEES BYTE CALL ZENDBYTE ; STUUR NAAR ATOM INC SI ; VERHOOG POINTER LOOP ZENDREAL2 ; DOE VOOR ALLE BYTES RET ; EINDE ROUTINE ZENDREAL ENDP LEESREAL PROC NEAR ; LEES FP GETAL VAN ATOM CMP FPMODE,0 ; TEST OP ATOM MODE JNE LEESREAL1 ; SPRING INDIEN INTEL MODE MOV DI,OFFSET ATOM ; LAADT ADRES ATOM MODE MOV CX,5 ; LEES AANTAL TE ZENDEN BYTES JMP SHORT LEESREAL2 ; GEDWONGEN SPRONG LEESREAL1: MOV DI,OFFSET INTEL ; LAADT ADRES INTEL MODE MOV CX,8 ; LAADT AANTAL TE ZENDEN BYTES LEESREAL2: CALL LEESBYTE ; LEES BYTE VAN ATOM MOV BYTE PTR [DI],AL ; BERG OP IN VARIABELE INC DI ; VERHOOG POINTER LOOP LEESREAL2 ; DOE VOOR ALLE BYTES CMP FPMODE,0 ; TEST NOGMAALS OP ATOM MODE JNE LEESREAL3 ; SPRING INDIEN NIET ATOM CALL ATEL ; ZET OM NAAR INTEL NOTATIE LEESREAL3: RET ; EINDE ROUTINE LEESREAL ENDP ; --------------------------------------------------------------------------- ; Subcommando interpreter ; --------------------------------------------------------------------------- FPFUN: CALL LEESBYTE ; LEES SUBFUNCTIE NUMMER CMP AL,20H ; TEST OP GELDIGE FUNCTIE JLE FPFUN1 ; SPRING INDIEN GELDIG MOV FUN_CODE,AL ; ZET AL IN WERKRUIMTE JMP ERROR ; GEEF FOUTMELDING EN BEEINDIG ROUTINE FPFUN1: MOV AH,0 ; MAAK HOGE BYTE AX 0 SHL AX,1 ; MAAK ER EEN WORD POINTER VAN MOV BX,AX ; ZET TABEL OFFSET IN BASE REGISTER JMP WORD PTR FPTAB[BX] ; SPRING NAAR SUBFUNCTIE FPTAB: DW FPROC, FPADD, FPSUB, FPMUL, FPDIV, FPABS DW FPRNDINT, FPSQRT, FTANG, FPSIN, FPCOS DW FPDEG, FPRAD, FPOWER ; --------------------------------------------------------------------------- ; Commando's ; --------------------------------------------------------------------------- FPROC: CALL LEESBYTE ; LEES FP-MODE (0=ATOM, 1=INTEL) MOV FPMODE,AL ; BERG OP FNINIT ; INIT COPROCESSOR XOR DX,DX ; CLEAR PROCESSORTYPE MOV WORD PTR INTEL,5A5AH FNSTSW WORD PTR INTEL CMP BYTE PTR INTEL,DL JNE SET_FLAGS ; GEEN COPROCESSOR AANWEZIG FNSTCW WORD PTR INTEL MOV AX,WORD PTR INTEL AND AX,103FH CMP AX,3FH JNE SET_FLAGS ; GEEN COPROCESSOR AANWEZIG INC DX ; VERHOOG PROCESSORTYPE 8087/80287 FLD1 FLDZ FDIV FLD ST FCHS FCOMPP FSTSW WORD PTR INTEL MOV AX,WORD PTR INTEL SAHF JE SET_FLAGS ; SPRING ALS 8087 OF 80287 INC DX ; HET IS EEN 80387 OF HOGER SET_FLAGS: MOV COPROC,DL ; SCHRIJF PROCESSORTYPE WEG MOV AL,DL ; STUUR TEVENS NAAR ATOM CALL ZENDBYTE JMP LEESCOM ; EINDE COMMANDO FPADD: CALL LEESREAL ; LEES EERSTE GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; LEES TWEEDE GETAL FADD INTEL ; TEL DE GETALLEN OP FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPSUB: CALL LEESREAL ; LEES EERSTE GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; LEES TWEEDE GETAL FSUB INTEL ; TREK GETALLEN VAN ELKAAR AF FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPMUL: CALL LEESREAL ; LEES EERSTE GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; LEES TWEEDE GETAL FMUL INTEL ; VERMENIGVULDIG DE GETALLEN FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPDIV: CALL LEESREAL ; LEES EERSTE GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; LEES TWEEDE GETAL FDIV INTEL ; DEEL DE GETALLEN FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPABS: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FABS ; BEREKEN ABSOLUTE WAARDE FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPRNDINT: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FRNDINT ; ROND AF NAAR INTEGER WAARDE FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPSQRT: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FSQRT ; BEREKEN VIERKANTSWORTEL FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FTANG: CALL LEESREAL ; LEES GETAL CMP COPROC,2 ; TEST OP 80387 JE FTAN387 ; JA, VERVOLG ROUTINE JMP FTAN287 ; VOOR 287 ANDERE ROUTINE FTAN387: FLD INTEL ; LEES WAARDE IN PROCESSOR FPTAN ; BEREKEN VERHOUDING Y/X FDIV ; BEREKEN TANGENS FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FTAN287: CALL _FTAN287 ; LAAT TANGENS BEREKENEN DOOR PROC CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO _FTAN287 PROC NEAR ; BEREKEN TANGENS VAN GETAL IN ST FINIT FLD INTEL ; LEES WAARDE IN PROCESSOR FLD HALF ; LAAD 0.5 FLDPI ; LAAD PI FMUL ; BEREKEN 0.5*PI FLDPI ; LAAD PI NOGMAALS FXCH ST(2) ; ST=x, ST(1)=0.5*PI, ST(2)=PI FTST ; BEPAAL TEKEN VAN ST FSTSW TEMP ; ZET STATUSREGISTER IN TEMP FWAIT MOV AX,WORD PTR TEMP; KOPIEER STATUS NAAR FLAGS SAHF JC FTAN_NEG ; SPRING ALS ST < 0 FTAN_POS: FCOM ST(1) ; KIJK OF ST > 0.5*PI FSTSW TEMP FWAIT MOV AX,WORD PTR TEMP AND AH,01000001B ; FILTER BENODIGDE STATUSBITS JNZ FTAN287A ; EXIT ALS ST <= 0.5*PI FSUB ST,ST(2) ; ST:=ST-PI JMP SHORT FTAN_POS FTAN_NEG: FXCH ST(1) ; ZET -0.5*PI IN ST(1) FCHS FXCH ST(1) ; ST=x, ST(1)=-0.5*PI, ST(2)=PI FTAN_NEG1: FCOM ST(1) ; KIJK OF ST < -0.5*PI FSTSW TEMP FWAIT MOV AX,WORD PTR TEMP SAHF JNC FTAN287A ; EXIT ALS ST >= -0.5*PI FADD ST,ST(2) ; ST:=ST+PI JMP SHORT FTAN_NEG1 FTAN287A: FTST ; BEPAAL TEKEN VAN NIEUWE ST FSTSW TEMP ; BERG OP IN WERKRUIMTE FABS ; BEPAAL |ST| FLD HALF ; LAAD 0.5 FMUL ST,ST(3) ; VERMENIGVULDIG MET 0.5*PI FABS ; HET RESULTAAT KAN NEGATIEF ZIJN FCOM ; TEST OF ST(1) < OF > 0.25*PI FSTSW TEMP[2] FWAIT MOV AX,WORD PTR TEMP[2] SAHF JC FTANREV ; SPRING ALS ST(1) > 0.25*PI FLD ST(1) ; LAAD ARGUMENT IN ST FPTAN ; BEREKEN TANGENS VAN ST FDIV JMP SHORT FTAN287B ; GA TEKEN NOG GOED ZETTEN FTANREV: FLD HALF ; LAAD 0.5 FLDPI ; LAAD PI FMUL ; BEREKEN 0.5*PI FSUB ST,ST(1) ; BEREKEN 0.5*PI-ST(1) FPTAN ; BEREKEN DAAR DE TANGENS VAN FDIV FLD1 ; LAAD WAARDE 1 FDIV ; BEREKEN 1/TAN(0.5*PI-x) FTAN287B: MOV AX,WORD PTR TEMP; HAAL TEKEN INFO TERUG SAHF ; ZET IN FLAGS JNC FTAN287C ; SPRING INDIEN POSITIEF FCHS ; MAAK NEGATIEF FTAN287C: FSTP INTEL ; ZET EINDRESULTAAT IN WERKRUIMTE FWAIT RET ; EINDE TAN287 ROUTINE _FTAN287 ENDP P386 ; DEZE FUNCTIES ALLEEN VOOR 80386 P387 FPSIN: CALL LEESREAL ; LEES GETAL CMP COPROC,2 ; TEST OP 387 JE FPSIN387 JMP FPSIN287 ; VOOR 287 ANDERE ROUTINE FPSIN387: FLD INTEL ; LEES IN PROCESSOR FSIN ; BEREKEN SINUS FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO P286 P287 FPSIN287: CALL FPCOSIN287 ; BEREKEN SINUS FLD QWORD PTR TEMP ; LAAD SINUS FSTP INTEL ; ZET IN GEHEUGEN FWAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO P386 P387 FPCOS: CALL LEESREAL ; LEES GETAL CMP COPROC,2 ; TEST OP 387 JE FPCOS387 JMP FPCOS287 ; VOOR 287 ANDERE ROUTINE FPCOS387: FLD INTEL ; LEES IN PROCESSOR FCOS ; BEREKEN COSINUS FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO P286 ; EN WEER TERUG NAAR 286 INSTRUKTIES P287 FPCOS287: CALL FPCOSIN287 ; BEREKEN COSINUS CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE ROUTINE FPCOSIN287 PROC NEAR ; BEREKEN COS EN SIN VAN ST FLDPI ; LAAD PI FLD INTEL ; LAAD x FPREM FST QWORD PTR TEMP[24] ; BEWAAR IN WERKRUIMTE FSTP INTEL ; PLAATS IN WERKRUIMTE FWAIT CALL _FTAN287 ; BEREKEN TAN FLD INTEL ; HAAL TAN OP FST QWORD PTR TEMP[16] ; BERG OP VOOR LATER GEBRUIK FLD INTEL ; HAAL NOGMAALS TAN OP FMUL ; BEREKEN TAN-KWADRAAT FLD1 ; TEL ER 1 BIJ OP FADD FLD1 ; LAAD 1 FDIVR ; BEREKEN 1/(1+TAN-KWADRAAT) FSQRT ; BEREKEN SQRT (1/(1+TAN-KWADRAAT)) FSTP INTEL ; ZET IN GEHEUGEN FWAIT FLD QWORD PTR TEMP[24] ; TEKEN NOG AANPASSEN FABS ; BEPAAL |ST| (ST= x) FLDPI ; LAAD PI FLD HALF ; LAAD 0.5 FMULP ; ST = 0.5*PI FCOM ST(1) ; TEST OF |x| < 0.5*PI FSTSW TEMP MOV AX,WORD PTR TEMP SAHF JNC FPCOSIN287A FLD INTEL ; WIJZIG HET TEKEN FCHS FST INTEL ; BERG COS x WEER OP FPCOSIN287A: FLD INTEL ; LAAD COS IN ST FLD QWORD PTR TEMP[16] ; LAAD TAN IN ST FMUL ; COS * TAN = SIN FSTP QWORD PTR TEMP ; BERG SIN x OP IN TEMP FWAIT FINIT ; RESET 287 RET ; INTEL=COS, ST=SIN FPCOSIN287 ENDP FPDEG: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FMUL CONST180 ; VERMENIGVULDIG MET 180 FLDPI ; DEEL DOOR PI FDIV FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPRAD: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FDIV CONST180 ; DEEL DOOR 180 FLDPI ; DEEL DOOR PI FMUL FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPOWER: CALL LEESREAL ; LEES GETAL FLD INTEL ; put power on top of stack CALL LEESREAL ; put number on top of stack FLD INTEL fabs ; make sure it's not negative ftst ; is it's zero .... fstsw AX sahf jne not_zero jmp get_out ; ...yes, so get out with 0.0 on TOS not_zero: ; now st(1) = power, st = number fyl2x ; st = number * log power base 2 fstcw TEMP+2 ; save the control word to restore later fstcw WORD PTR temp ; to change rounding control to round-down and WORD PTR temp,0F33FH ; clear out RoundingControl bits or WORD PTR temp,0400H ; set for Round-down fldcw WORD PTR temp ; put it in control word fld st(0) ; push copy of number frndint ; st = z1, st(1) = z fldcw TEMP+2 ; restore initial control word fsub st(1), st ; st(1) = z2 = (z-z1) fxch ; st = z2, st(1) = z1 fld half ; 1/2 -> top of stack fxch ; st = z2, st(1) = 1/2 fprem ; st is z2 or z2=1/2; if z2=1/2, c1=1 fstsw TEMP+2 fstp st(1) ; now flags are set, so get rid of the half f2xm1 ; st is now ((2 to the st) - 1) fld1 faddp st(1), st test TEMP+3,00000010B; st has z2 if bit 1 on jz was_z2 ; else it had z2 - 1/2 fld1 fadd st, st(0) fsqrt ; so multiply it by the square root of 2 fmulp st(1), st was_z2: fscale ; just need to scale by 2**st(1) get_out: fstp st(1) fstp INTEL ; BERG RESULTAAT OP WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE ROUTINE