aboutsummaryrefslogtreecommitdiffstats
path: root/tests/t_fl900/float.inc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/t_fl900/float.inc')
-rw-r--r--tests/t_fl900/float.inc973
1 files changed, 973 insertions, 0 deletions
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
+