From 333b605b2afd472b823aeda0adf0e8b1ea9843c0 Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Mon, 27 May 2019 02:41:51 +0100 Subject: initial commit from asl-1.41r8.tar.gz --- tests/t_fl900/float.inc | 973 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 973 insertions(+) create mode 100644 tests/t_fl900/float.inc (limited to 'tests/t_fl900/float.inc') diff --git a/tests/t_fl900/float.inc b/tests/t_fl900/float.inc new file mode 100644 index 0000000..dd4796c --- /dev/null +++ b/tests/t_fl900/float.inc @@ -0,0 +1,973 @@ +; FLOAT.INC +;****************************************************************************** +;* Gleitkommabibliothek fr TLCS 900 * +;* * +;* Originale fr den 68000 aus mc, bis auf die Quadratwurzel aus c't * +;* Portierung auf TLCS 900 von Alfred Arnold, Oktober 1993 * +;* * +;* Routine Funktion Eingabe Ausgabe Stack L„nge Zeit/14MHz * +;* * +;* fadd Addition XWA+XHL XWA 12 Byte 194 Byte 60 us * +;* fsub Subtraktion XWA-XHL XWA 12 Byte 7 Byte 65 us * +;* fmul Multiplikation XWA*XHL XWA 20 Byte 218 Byte 70 us * +;* fdiv Division XWA/XHL XWA 20 Byte 147 Byte 300 us * +;* fmul2 Mult. mit 2er-Potenz XWA*(2^BC) XWA 6 Byte 99 Byte 20 us * +;* fitof Int-->Float XWA XWA 4 Byte 41 Byte 90 us * +;* fftoi Float-->Int XWA XWA 2 Byte 72 Byte 20 us * +;* fsqrt Quadratwurzel XWA XWA 16 Byte 192 Byte 220 us * +;* fftoa Float-->ASCII XWA (XHL),BC ~38 Byte 228 Byte ~4500 us * +;* fatof ASCII-->Float (XHL),BC XWA,[BC] ~40 Byte 260 Byte ~2300 us * +;* * +;* - Wollen Sie einzelne Routinen entfernen, so beachten Sie, daá fsub Teile * +;* aus fadd und fdiv Teile aus fmul verwendet ! * +;* - Gleitkommaformat ist IEEE Single (32 Bit) * +;* - Integerwerte bei fmul2, fitof und fftoi sind vorzeichenbehaftet * +;* - Der Prozessor muá sich im Maximum-Modus befinden * +;* - Da die Routinen lokale Labels verwenden, ist mindestens AS 1.39 erfor- * +;* derlich * +;* - Die Ausfhrungszeiten k”nnen je nach Operand streuen, insbesondere bei * +;* den Konvertierungsfunktionen * +;* - MACROS.INC muá vorher eingebunden werden * +;****************************************************************************** + +;------------------------------------------------------------------------------ +; gemeinsamer Anfang, Makros + +shifta macro op,dest ; Schieben, falls evtl. A>=16 + push a ; A wird zerschossen + bit 4,a ; Akku im Bereich 16..31 ? + jr z,smaller + op 16,dest ; dann einmal groá schieben +smaller: push f ; Carry erhalten + and a,15 ; obere Bits pl„tten + jr z,fertig + pop f ; evtl. Rest verarbeiten + op a,dest + jr ende ; Carry schon gut +fertig: pop f +ende: pop a ; A zurck + endm + + section FloatLib + +;------------------------------------------------------------------------------ +; Konstanten + +Ld10: dd ld(10) ; Konversionskonstanten +One: dd 1.0 +Half: dd 0.5 +Ten: dd 10.0 +Tenth: dd 3dcccccdh ; =0.1, aber die Rundung auf manchen + ; Systemen variiert (damit Test nicht + ; scheitert) + +Bias equ 127 +MaxExpo equ 255 +Comma equ '.' + +;------------------------------------------------------------------------------ +; Addition: XWA=XWA+XHL + + proc fadd + + push xbc ; andere Register retten + push xde + push xhl + + ld xde,xwa ; Operand 1 nach XDE verschieben + rlc 1,xde ; Vorzeichen der Operanden nach Bit 0 + rlc 1,xhl + ld xbc,xde ; Differenz bilden + sub xbc,xhl + jr nc,NoSwap ; evtl. vertauschen, so daá + ld xwa,xhl ; gr”áere in XDE + ld xhl,xde + ld xde,xwa +NoSwap: ld qa,e ; Vorzeichen 1 ausmaskieren + and qa,1 ; (=Ergebnis Vorzeichen) + bit 0,c ; gleiches Vorzeichen ? + jr z,NoSub + set 1,qa ; dann Subtraktion vormerken + +NoSub: sub xbc,xbc ; XBC initialisieren + rlc 8,xde ; Exponent 1 rausholen + ld c,e + or e,e ; falls <>0, implizite 1 einbauen + scc nz,e + rrc 1,xde + ld e,0 ; Bit 0..7 wieder pl„tten + + rlc 8,xhl ; dito Exponent 2 extrahieren + ld qc,l + or l,l + scc nz,l + rrc 1,xhl + ld l,0 + +; Zwischenstand: +; - Mantissen linksbndig inkl. impliziter Eins in XDE und XHL +; - Exponent 1 in BC, Exponent 2 in QBC +; - Ergebnisvorzeichen in QA, Bit 0 +; - Subtraktionsflag in QA, Bit 1 + + ld wa,bc ; Exponentendifferenz berechnen + sub wa,qbc + cp wa,24 ; >24, d.h. Zahl 2 vernachl„ssigbar gegen Zahl 1 + jr gt,Round ; ja, Ergebnis ist gr”áere Zahl + shifta srl,xhl ; ansonsten Mantisse 2 entspr. anpassen + +Add: bit 1,qa ; subtrahieren ? + jr nz,Subtract ; ja--> + add xde,xhl ; nein, Mantissen addieren + jr nc,Round ; kein šberlauf, runden + rr 1,xde ; ansonsten šberlauf einschieben... + inc bc ; ...und Exponent korrigieren + jr Round ; normal weiter runden + +Subtract: sub xde,xhl ; Mantissen subtrahieren + jr z,Zero ; falls Null, Gesamtergebnis 0 + jr m,Round ; fhrende 1 noch da: zum Runden +Normalize: or bc,bc ; Exponent bereits Null ? + jr z,Round ; dann denormales Ergebnis + dec bc ; ansonsten Mantisse eins rauf, Exponent + sll 1,xde ; eins runter + jr p,Normalize ; solange, bis Eins auftaucht + +Round: add xde,80h ; Rundung auf Bit hinter Mantisse + jr nc,NoOver + rr 1,xde ; Bei šberlauf korrigieren + inc bc +NoOver: ld e,0 ; Mantissenrest pl„tten + or xde,xde ; insgesamt 0 ? + jr z,Zero ; dann Ergebnis 0 + cp bc,MaxExpo ; Exponentenberlauf ? + jr lt,NoEOver + ld bc,MaxExpo ; ja: Unendlich: Exponent=Maximum + sub xde,xde ; Mantisse=0 + jr Denormal + +NoEOver: or bc,bc ; Exponent 0 ? + jr z,Denormal ; ja, denormal + sll 1,xde ; fhrende Eins nicht speichern +Denormal: ld e,c ; Exponenten einbauen + rrc 8,xde ; nach oben schieben + rr 1,qa ; Vorzeichen einbauen + rr 1,xde + +Zero: ld xwa,xde ; Ergebnis in Akku + + pop xhl ; Register zurck + pop xde + pop xbc + + ret + + endp + +;------------------------------------------------------------------------------ +; Subtraktion: XWA=XWA-XHL + + proc fsub + + xor qh,80h ; Vorzeichen 2 drehen + jp fadd ; ansonsten wie Addition + + endp + +;------------------------------------------------------------------------------ +; Multiplikation: XWA=XWA*XHL + + proc fmul + + public MulRound:Parent,MulZero:Parent,MulResult:Parent + public DivError:Parent + + push xbc ; Register retten + push xde + push xhl + push xix + push xiy + + ld xiy,xwa ; Op1 kopieren + xor xiy,xhl ; Ergebnisvorzeichen bestimmen + + ex wa,qwa ; Registerh„lften Op1 vertauschen + ld xde,xwa ; Op1 ab sofort in XDE + and de,7fh ; Exponent und Vz. behandeln + and wa,7f80h ; Exponent maskieren + jr z,Denorm1 ; gleich Null-->Op1 denormal + set 7,de ; ansonsten implizite Eins einbauen + sub wa,80h ; Bias kompensieren +Denorm1: + ex hl,qhl ; Op2 genauso behandeln + ld xbc,xhl + and hl,7fh + and bc,7f80h + jr z,Denorm2 + set 7,hl + sub bc,80h +Denorm2: + add bc,wa ; Exponenten addieren + srl 7,bc ; richtig positionieren + sub bc,Bias-3 ; Bias-3 abziehen + cp bc,-24 ; totaler Unterlauf ? + jr lt,MulZero ; dann Ergebnis 0 + + ld wa,de ; beide oberen H„lften multiplizieren + mul xwa,hl + ex wa,qwa ; Ergebnis in oberer H„lfte lagern + ld wa,de ; obere H„lfte Op1 retten + ex de,qde ; untere H„lfte Op1 holen + ld ix,hl ; untere H„lfte Op1 * obere Op2 + mul xix,de + ex hl,qhl ; untere Op1 * untere Op2 + mul xde,hl + ex de,qde ; obere Op1 * untere Op2 + mul xhl,wa + + ld wa,de ; Teile aufaddieren + add xwa,xix + add xwa,xhl + jr z,MulResult ; Mantisse Null, Ergebnis Null + jr m,MulRound + + or bc,bc ; Exponent negativ ? + jr m,Unterlauf ; ggfs. Unterlauf behandeln + +Nor: or bc,bc ; Exponent Null ? + jr z,MulRound ; ja-->zum Runden + rl 1,xde ; nein, Mantisse eins nachschieben + rl 1,xwa + dec bc ; und Exponent runter + or xwa,xwa ; fhrende Eins da ? + jr p,Nor ; nein, weiterschieben + +MulRound: add xwa,80h ; Rundung + jr nc,NoROver ; dabei šberlauf ? + rr 1,xwa ; ja: Mantisse & Exponent korrigieren + inc bc +NoROver: cp bc,MaxExpo ; Exponentenberlauf ? + jr lt,NoEOver +DivError: ld bc,MaxExpo ; dann unendlich einstellen + sub xwa,xwa + jr Denormal + +NoEOver: or bc,bc ; Exponent 0 ? + jr z,Denormal + sll 1,xwa ; fhrende 1 l”schen + +Denormal: ld a,c ; Exponent einbauen + rrc 8,xwa ; hochschieben + rl 1,xiy ; Vorzeichen einbauen + rr 1,xwa + +MulResult: pop xiy + pop xix + pop xhl + pop xde + pop xbc + + ret + +MulZero: sub xwa,xwa ; Null erzeugen + jr MulResult + +Unterlauf: cp bc,-24 ; totaler Unterlauf ? + jr le,MulZero ; dann Null + neg bc ; sonst umbauen + ld xde,xwa ; dazu Akku freimachen + sub wa,wa ; Endexponent + ex wa,bc ; ist 0 + shifta srl,xde ; Mantisse herunterschieben + ld xwa,xde ; Ergebnis zurck nach XWA + jr MulRound ; zurck mit Exponent 0 + + endp + +;------------------------------------------------------------------------------ +; Division: XWA=XWA/XHL + + proc fdiv + + push xbc ; Register retten (muá gleich zu fmul sein) + push xde + push xhl + push xix + push xiy + + ld xiy,xwa ; Op1 kopieren + xor xiy,xhl ; Ergebnisvorzeichen bestimmen + + ex wa,qwa ; Vorbehandlung wie bei fmul + ld xde,xwa + and de,7fh + and wa,7f80h + jr z,Denorm1 + set 7,de + sub wa,80h +Denorm1: + ex hl,qhl + ld xbc,xhl + and hl,7fh + and bc,7f80h + jr z,Denorm2 + set 7,hl + sub bc,80h +Denorm2: + sub wa,bc ; Exponentendifferenz bilden + ld bc,wa ; muá in BC liegen + sra 7,bc ; richtig positionieren + add bc,Bias ; Bias addieren + cp bc,-24 ; totaler Unterlauf ? + jr lt,MulZero ; ja, Ergebnis Null + + ex hl,qhl ; Format 0fff ... ffff 0000 0000 + or xhl,xhl ; Ergebnis unendlich ? + jrl z,DivError + sll 7,xhl + ex de,qde ; dito Divident + or xde,xde ; falls Null, Ergebnis Null + jrl z,MulZero + sll 7,xde + +NormLoop: bit 14,qhl ; Divisor normalisiert ? + jr nz,Normal + inc bc ; nein, Exponent RAUF (ist Ergebnisexponent) + sll 1,xhl + jr NormLoop + +Normal: sub xwa,xwa ; Ergebnisquotient vorbesetzen + add bc,25 ; Exponent nicht gr”áer als 0 + +Loop: ld xix,xde ; Divident zwischenspeichern + sub xde,xhl ; probeweise abziehen + ccf ; Carry drehen + jr c,IsOne ; ungedrehter Carry=1: Divisor paát + ld xde,xix ; ansonsten zurckkopieren +IsOne: rl 1,xwa ; Ergebnisbit einschieben + sll 1,xde ; Divident verschieben + dec bc ; Exponent runter + or bc,bc + jr z,Denorm ; falls Null, denormalisieren + bit 8,qwa ; fhrende Eins da ? + jr z,Loop ; nein, weiterrechnen + +Denorm: sll 7,xwa ; Mantisse positionieren + jrl z,MulResult ; Ergebnis 0 ? + jrl MulRound ; ansonsten zum Runden + + endp + +;----------------------------------------------------------------------------- +; Multiplikation mit Zweierpotenz: XWA=XWA*2^BC + + proc fmul2 + + push bc ; Register retten + push xde + + ld xde,xwa ; Vorzeichen merken + sll 1,xwa ; Vorzeichen rausschieben + jr z,Zero ; falls Null, Ergebnis Null + rlc 8,xwa ; Exponent nach unten... + sub de,de ; und in DE packen + add e,a + jr z,Denorm ; falls denormalisiert.. + or bc,bc ; Multiplikation oder Division ? + jr m,Divide ; (neg. Exponent=Division) + + add de,bc ; Exponent addieren + cp de,MaxExpo ; šberlauf ? + jr ge,Over ; ja, Ergebnis unendlich +Result: ld a,e ; Ergebnisexponent einbauen + rrc 8,xwa ; Exponent nach oben + rl 1,xde ; Vorzeichen einschieben + rr 1,xwa + +Zero: pop xde ; Register zurck + pop bc + ret + +Over: ld de,MaxExpo ; Ergebnis unendlich + sub xwa,xwa + jr Result + +Divide: add de,bc ; Exponentensumme bilden + jr gt,Result ; >0, keine Sonderbehandlung + scf ; ansonsten 1 explizit fr + rr 1,xwa ; denormale Zahl machen +DDenorm: or de,de ; Exponent=0 ? + jr z,Result ; ja, Ergebnis einfach denormal + srl 1,xwa ; ansonsten weiter denormalisieren + jr z,Zero ; dabei totaler Unterlauf->Null + inc de ; Exponent korrigieren + jr DDenorm +DDDenorm: add de,bc ; Exponentensumme bilden + jr DDenorm + +Denorm: or bc,bc ; Multiplikation oder Division ? + jr m,DDDenorm + sub a,a ; alten Exponenten l”schen +Norm: sll 1,xwa ; normalisieren... + jr c,Stop ; bis fhrende Eins da + dec bc ; oder 2. Exponent 0 + or bc,bc + jr nz,Norm + jr Result ; Multiplikator kompl. fr Normalisierung draufgegangen +Stop: add de,bc ; Rest addieren + jr Result ; alles andere schon o.k. + + endp + +;------------------------------------------------------------------------------ +; LongInt-->Float : XWA-->XWA + + proc fitof + + push xbc ; Register retten + + or xwa,xwa ; Null ? + jr z,Result ; dann Ergebnis Null + scc m,qc ; Vorzeichen nach QC, Bit 0 + jr p,Positive + cpl wa ; falls negativ,drehen + cpl qwa + inc xwa +Positive: ld bc,Bias+32 ; Exponent vorbesetzen +Shift: dec bc ; Mantisse verschieben + sll 1,xwa + jr nc,Shift + ld a,c ; Exponent einbauen + rrc 8,xwa ; Exponent nach oben + rr 1,qc ; Vorzeichen einbauen + rr 1,xwa + +Result: pop xbc ; Register zurck + ret + + endp + +;------------------------------------------------------------------------------ +; Float-->LongInt : XWA-->XWA + + proc fftoi + + push bc ; Register retten + + rl 1,xwa ; Vorzeichen in Carry + scc c,b ; in B merken + + rlc 8,xwa ; Exponent nach unten + ld c,a ; in C legen + sub c,Bias ; Bias abziehen + + jr m,Zero ; neg. Exponent -> Zahl<0 -> Ergebnis 0 + cp c,31 ; šberlauf ? + jr ge,Over + + scf ; fhrende Eins einschieben + rr 1,xwa + sub a,a ; Exponent l”schen + +Shift: srl 1,xwa ; jetzt schieben, bis Ergebnis stimmt + inc c + cp c,31 + jr ne,Shift + + srl 1,b ; negieren ? + jr nc,Positive + cpl wa ; ggfs. negieren + cpl qwa + inc xwa + +Positive: pop bc ; Register zurck + ret + +Zero: sub xwa,xwa ; Ergebnis 0 + jr Positive + +Over: ld xwa,7fffffffh ; šberlauf: Maxint zurckgeben + srl 1,b ; negativ ? + jr nc,Positive + cpl wa ; ja, neg. Maximum zurckgeben + cpl qwa + jr Positive + + endp + +;------------------------------------------------------------------------------ +; Quadratwurzel: XWA=SQRT(XWA) + + proc fsqrt + + push xbc ; Register retten + push xde + push xhl + push xix + + ld xix,xwa ; Argument retten + or xix,xix ; Zahl negativ ? + jrl m,DomainError ; dann geht es nicht + + ex ix,qix ; MSW holen + and xix,7f80h ; Exponent isolieren + jrl z,Zero ; keine Behandlung denormaler Zahlen + + and xwa,7fffffh ; Mantisse isolieren + sub ix,7fh*80h ; Bias vom Exponenten entfernen + bit 7,ix ; Exponent ungerade ? + res 7,ix + jr z,EvenExp + add xwa,xwa ; ja: Mantisse verdoppeln + add xwa,1000000h-800000h ; impl. Eins dazu +EvenExp: ; erste Iteration ohne impl. Eins + sra 1,ix ; Exponent/2 mit Vorzeichen + add ix,7fh*80h ; Bias wieder dazu + ex ix,qix ; neuen Exponenten in QIX aufheben + sll 7,xwa ; x ausrichten + ld xde,40000000h ; xroot nach erster Iteration + ld xhl,10000000h ; m2=2 << (MaxBit-1) +Loop10: ld xbc,xwa ; xx2 = x +Loop11: sub xbc,xde ; xx2 -= xroot + srl 1,xde ; xroot = xroot/2 + sub xbc,xhl ; x2 -= m2 + jr m,DontSet1 + ld xwa,xbc ; x = xx2 + or xde,xhl ; xroot += m2 + srl 2,xhl ; m2 = m2/4 + jr nz,Loop11 + jr WABCSame +DontSet1: srl 2,xhl ; m2 = m2/4 + jr nz,Loop10 ; 15* abarbeiten + ; Bit 22..8 + ld xbc,xwa ; 17. Iteration separat +WABCSame: sub xbc,xde + rrc 1,xde ; mitsamt Carry... + ex de,qde ; auf neues Alignment umstellen + sub xbc,1 ; Carry von 0-$4000: x2 -= m2 + jr m,DontSet7 + or xbc,-40000000h ; 0-$4000: x2 -= m2, Teil 2 + ld xwa,xbc + or de,4000h ; xroot += m2 +DontSet7: ex wa,qwa ; x auf neues Alignment umstellen + ld hl,1000h ; m2 - obere H„lfte schon 0 +Loop20: ld xbc,xwa ; xx2 = x +Loop21: sub xbc,xde ; xx2 -= xroot + srl 1,xde ; xroot = xroot/2 + sub xbc,xhl ; x2 -= m2 + jr m,DontSet2 + ld xwa,xbc ; x = xx2 + or xde,xhl ; xroot += m2 + srl 2,xhl ; m2 = m2/4 + jr nz,Loop21 + jr Finish +DontSet2: srl 2,xhl ; m2 = m2/4 + jr nz,Loop20 ; 7* abarbeiten + +Finish: sub xwa,xde ; Aufrunden notwendig ? + jr ule,NoInc + inc xde ; wenn ja, durchfhren +NoInc: res 7,qde ; impl. Eins l”schen + or xde,xix + ld xwa,xde ; Ergebnis in XWA + jr End + +DomainError: ld xwa,0ffc00000h ; -NAN zurckgeben + jr End + +Zero: sub xwa,xwa ; Ergebnis 0 + +End: pop xix ; Register zurck + pop xhl + pop xde + pop xbc + ret + + endp + +;------------------------------------------------------------------------------ +; Unterroutine Zehnerpotenz bilden: XWA=10.0^BC + + section fPot10 ; nicht mit proc, da private Funktion + public fPot10:Parent +fPot10: + + push xbc ; Register retten + push xhl + + ld xwa,(One) ; Ausgangspunkt frs Multiplizieren + ld xhl,(Ten) ; zu benutzende Potenz + or bc,bc ; negative Potenz ? + jr p,IsPos + ld xhl,(Tenth) ; dann eben Zehntel multiplizieren + neg bc ; fr Schleife immer positiv +IsPos: + or bc,bc ; Noch weiter multiplizieren ? + jr z,End + bit 0,bc ; Restpotenz ungerade ? + jr z,IsEven + call fmul ; ja: einzeln multiplizieren +IsEven: srl 1,bc ; n„chste Stelle + push xwa ; neue Potenz berechnen + ld xwa,xhl + call fmul ; durch quadrieren + ld xhl,xwa + pop xwa + jr IsPos ; weiter nach Einsen suchen + +End: pop xhl ; Register zurck + pop xbc + ret + + endsection + +;------------------------------------------------------------------------------ +; Unterroutine Zahl dezimal wandeln + + section fOutDec + public fOutDec:Parent +fOutDec: + + push xwa ; Register retten + push xbc + push de + push xhl + + bit 15,qwa ; negativ ? + jr z,IsPos + ld (xix+),'-' ; ja: vermerken... + cpl wa ; ...und Zweierkomplement + cpl qwa + inc xwa + jr GoOn +IsPos: bit 7,c ; Pluszeichen ausgeben ? + jr nz,GoOn + ld (xix+),'+' +GoOn: res 7,c ; Plusflag l”schen + ld qbc,0 ; Nullflag und Z„hler l”schen + +InLoop: ld xhl,0 ; Division vorbereiten + ld e,32 ; 32 Bit-Division +DivLoop: sll 1,xwa ; eins weiterschieben + rl 1,xhl + srl 1,xwa ; fr nachher + sub xhl,10 ; paát Divisor hinein ? + jr nc,DivOK + add xhl,10 ; nein, zurcknehmen... + scf ; im Ergebnis 0 einschieben +DivOK: ccf ; neues Ergebnisbit + rl 1,xwa ; Ergebnis in XWA einschieben... + djnz e,DivLoop + + add l,'0' ; ASCII-Offset addieren + bit 1,qb ; schon im Nullbereich ? + jr z,NormVal + ld l,b ; ja, dann gewnschtes Leerzeichen +NormVal: push l ; auf LIFO legen + inc qc ; ein Zeichen mehr + or xwa,xwa ; Quotient Null ? + scc z,qb + jr nz,InLoop ; wenn nicht Null, auf jeden Fall weiter + cp c,qc ; ansonsten nur, falls min. Stellenzahl + jr ugt,InLoop ; noch nicht erreicht + +OutLoop: pop a ; jetzt Zeichen umgekehrt ablegen + ld (xix+),a + djnz qc,OutLoop + + pop xhl ; Register zurck + pop de + pop xbc + pop xwa + + ret + + endsection + +;------------------------------------------------------------------------------ +; Gleitkomma nach ASCII wandeln: +; In: Zahl in XWA +; Zeiger auf Speicher in XHL +; max. Anzahl Nachkommastellen in C +; B/Bit 0 setzen, falls Mantissen-Pluszeichen unerwnscht +; B/Bit 1 setzen, falls Exponenten-Pluszeichen unerwnscht +; B/Bit 2..4 = Stellenzahl Exponent +; B/Bit 5 setzen, falls Nullen am Ende der Mantisse unerwnscht +; Out: Zahl abgelegter Zeichen (exkl. NUL am Ende) in BC +; (XHL) = gebildeter String + + proc fftoa + + push xix ; Register retten + push xhl + push de + push xbc + push xwa + + ld xix,xhl ; Zeiger auf Speicher kopieren + ld de,bc ; Parameter sichern + + ld xhl,xwa ; Zahl auf die Zerlegebank bringen + res 15,qwa ; Vorzeichen hier nicht mehr gebraucht + + ld c,'+' ; Annahme positiv + sll 1,xhl ; Vorzeichen in Carry bringen + jr c,IsNeg ; Minuszeichen immer erforderlich... + bit 0,d ; ...Pluszeichen optional + jr nz,NoMantSgn + jr WrMantSgn +IsNeg: ld c,'-' ; ja +WrMantSgn: ld (xix+),c ; Mantissenvorzeichen ablegen +NoMantSgn: + ld c,qh ; Exponenten herausholen... + extz bc ; ...auf 16 Bit erweitern... + sll 8,xhl ; ...und in Quelle l”schen + + cp bc,MaxExpo ; Sonderwert (INF/NAN) ? + jrl z,SpecialVals ; ja--> + + or bc,bc ; Zahl denormal ? + jr nz,IsNormal ; nein, normal weiter + or xhl,xhl ; bei kompl. Null auch berspringen + jr z,IsNull +Normalize: sll 1,xhl ; ja: solange z„hlen, bis 1 erscheint + jr c,IsNormal + dec bc + jr Normalize +IsNormal: sub bc,Bias ; Bias abziehen +IsNull: + push xwa ; fr folgendes Zahl retten + ld wa,bc ; Zweierexponenten in Float wandeln + exts xwa + call fitof + ld xhl,(Ld10) ; in Dezimalexponenten wandeln + call fdiv + or xwa,xwa ; Zahl negativ ? + jr p,NoCorr + ld xhl,(One) ; dann nocheinmal korrigieren wg. + call fsub ; unterer Gauáklammer +NoCorr: call fftoi ; Den Ausflug in Float beenden + ld qbc,wa ; den Zehnerexponenten retten + ld bc,wa + call fPot10 ; von diesem Exponenten Zehnerpotenz + ld xhl,xwa ; bilden + pop xwa ; alte Zahl zurck + call fdiv ; Teilen: Ergebnis ist Zahl zwischen +Again: ld xhl,xwa ; 1.0 und 9.9999..., diese retten + call fftoi ; Vorkommastelle berechnen + cp a,10 ; doch etwas drber ? + jr ult,NoRoundErr + ld xwa,xhl ; ja, dann noch einmal zehnteln + ld xhl,(Tenth) + call fmul + inc qbc + jr Again +NoRoundErr: add a,'0' ; diese nach ASCII wandeln... + ld (xix+),a ; ...und ablegen + sub a,'0' ; wieder rckg„ngig machen + cp e,0 ; gar keine Nachkommastellen ? + jr eq,NoComma + ld (xix+),Comma ; Dezimalpunkt ausgeben + call fitof ; in ganze Gleitkommazahl wandeln + call fsub ; Differenz bilden + chg 15,qwa ; war verkehrtherum... + ld xhl,xwa ; nach XHL verschieben, weil XWA gebraucht + ld c,e ; Zehnerpotenz fr Skalierung ausrechnen + extz bc ; auf 16 Bit aufblasen + call fPot10 ; Skalierungswert berechnen + call fmul ; hochmultiplizieren + ld xhl,(Half) ; Rundung + call fadd + call fftoi ; diese herausziehen + ld b,'0' ; n-stellig mit Vornullen ausgeben + ld c,e + set 7,c ; kein Pluszeichen! + call fOutDec + bit 5,d ; Nullen am Ende abr„umen ? + jr nz,CleanZeros +NoComma: + ld a,d ; falls Minimalstellenzahl Exponent=0 + and a,00011100b ; und Exponent=0, vergessen + or a,qb + or a,qc + jr z,End + + ld (xix+),'E' ; Exponenten ausgeben + ld wa,qbc + exts xwa + ld b,'0' ; evtl. vornullen... + ld c,d ; Bit 1-->Bit 7 + rrc 2,c + and c,87h ; Bits ausmaskieren + call fOutDec + +End: pop xwa ; Register zurck + pop xbc + pop de + pop xhl + ld (xix),0 ; NUL-Zeichen im String nicht vergessen + sub xix,xhl ; Stringl„nge berechnen + ld bc,ix + pop xix + + ret + +SpecialVals: or xde,xde ; Ist die Mantisse Null ? + jr nz,IsNAN + ldw (xix+),'NI' ; ja: INF einschreiben + ld (xix+),'F' + jr End +IsNAN: ldw (xix+),'AN' ; nein: NAN einschreiben + ld (xix+),'N' + jr End + +CleanZeros: cp (xix-1),'0' ; steht da eine Null am Ende ? + jr nz,CleanNoZero ; nein, Ende + dec xix ; ja: Z„hler runter, so daá ber- + jr CleanZeros ; schrieben wird und neuer Versuch +CleanNoZero: cp (xix-1),Comma ; evtl. Komma entfernbar ? + jr nz,NoComma ; nein--> + dec xix ; ja: noch ein Zeichen weniger + jr NoComma + + endp + +;------------------------------------------------------------------------------ +; ASCII nach Gleitkomma wandeln: +; In: Zeiger auf String (ASCIIZ) in XHL +; Out: XWA = Ergebnis bzw. fehlerhafte Stelle +; CY = 0, falls fehlerfrei + + proc fatof + + push xbc ; Register retten + push xde + push xhl + push xix + + ld xix,xhl ; Zeiger nach XIX + ld qbc,01 ; Phase 1 (Mantisse), noch kein Vorzeichen + ld xde,(Ten) ; in der Mantisse mit 10 hochmultiplizieren + ld xhl,0 ; Mantisse vorbelegen + ld bc,0 ; Exponent vorbelegen + +ReadLoop: ld a,(xix+) ; ein neues Zeichen holen + extz wa ; auf 32 Bit aufblasen + extz xwa + + cp a,0 ; Endezeichen ? + jrl eq,Combine ; ja, alles zusammen + + cp a,' ' ; Leerzeichen ignorieren + jr eq,ReadLoop + + cp a,'+' ; Pluszeichen gnadenhalber zugelassen + jr ne,NoPlus ; ist aber nur ein Dummy + bit 0,qb ; schon ein Vorzeichen dagewesen ? + jrl nz,Error ; dann Fehler + set 0,qb ; ansonsten einfach setzen + jr ReadLoop +NoPlus: + cp a,'-' ; Minuszeichen bewirkt schon eher etwas + jr ne,NoMinus + bit 0,qb ; darf auch nur einmal auftreten + jrl nz,Error + set 0,qb + cp qc,1 ; je nach Phase anderes Flag setzen + jr ne,MinPhase3 + set 1,qb ; bei Mantisse Bit 1... + jr ReadLoop +MinPhase3: set 2,qb ; bei Exponent Bit 2 + jr ReadLoop +NoMinus: + cp a,'.' ; Umschaltung zu Phase 2 (Nachkomma) ? + jr ne,NoPoint + cp qc,1 ; bish. Phase muá eins sein + jrl ne,Error + ld qc,2 ; neue Phase eintragen + set 0,qb ; Nachkomma darf kein Vorzeichen haben + ld xde,(Tenth) ; im Nachkomma durch 10 teilen + jr ReadLoop +NoPoint: + cp a,'e' ; kleines und groáes E zulassen + jr eq,IsE + cp a,'E' + jr ne,NoE +IsE: cp qc,3 ; vorherige Phase muá 1 oder 2 sein + jr eq,Error + ld qc,3 ; vermerken + res 0,qb ; Vorzeichen wieder zugelassen + jr ReadLoop +NoE: + sub a,'0' ; jetzt nur noch 0..9 zugelassen + jr c,Error + cp a,9 + jr ugt,Error + set 0,qb ; nach Ziffern kein Vorzeichen mehr zulassen + + cp qc,1 ; Phase 1 (Mantisse) : + jr ne,NoPhase1 + push xwa ; Zeichen retten + ld xwa,xde ; bish. Mantisse * 10 + call fmul + ld xhl,xwa + pop xwa ; Zahl nach Float wandeln + call fitof + call fadd ; dazuaddieren + ld xhl,xwa ; Mantisse zurcklegen + jrl ReadLoop +NoPhase1: + cp qc,2 ; Phase 2 (Nachkomma) : + jr ne,NoPhase2 + call fitof ; Stelle nach Float wandeln + push xhl ; Mantisse retten + ld xhl,xde ; Stelle mit Zehnerpotenz skalieren + call fmul + pop xhl ; zur Mantisse addieren + call fadd + push xwa ; Zwischenergebnis retten + ld xwa,xde ; n„chste Skalierungspotenz ausrechnen + ld xhl,(Tenth) + call fmul + ld xde,xwa ; alles wieder zurck + pop xhl + jrl ReadLoop +NoPhase2: + mul bc,10 ; Exponent heraufmultiplizieren + add bc,wa + cp bc,45 ; Minimum ist 1e-45 + jr ugt,Error + jrl ReadLoop + +Combine: bit 2,qb ; Exponent negativ ? + jr z,ExpPos + neg bc +ExpPos: call fPot10 ; Zehnerpotenz des Exponenten bilden + call fmul ; mit Mantisse kombinieren + bit 1,qb ; Mantisse negativ ? + jr z,ManPos + set 15,qwa +ManPos: rcf ; Ende ohne Fehler + + pop xix ; Register zurck + pop xhl + pop xde + pop xbc + ret + +Error: ld xwa,xix ; Endzeiger laden + pop xix + pop xhl + sub xwa,xhl ; rel. Position des fehlerhaften Zeichens berechnen + pop xde + pop xbc + scf ; Ende mit Fehler + ret + + endp + +;------------------------------------------------------------------------------ +; gemeinsames Ende + + endsection + -- cgit v1.2.3