aboutsummaryrefslogtreecommitdiffstats
path: root/tests/t_fl90/float.inc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/t_fl90/float.inc')
-rw-r--r--tests/t_fl90/float.inc1601
1 files changed, 1601 insertions, 0 deletions
diff --git a/tests/t_fl90/float.inc b/tests/t_fl90/float.inc
new file mode 100644
index 0000000..7355130
--- /dev/null
+++ b/tests/t_fl90/float.inc
@@ -0,0 +1,1601 @@
+; FLOAT.INC
+;******************************************************************************
+;* Gleitkommabibliothek fr TLCS 90 *
+;* *
+;* Originale fr den Z80 aus mc 12/88,1/89 *
+;* Portierung auf TLCS 90 von Alfred Arnold, Dezember 1993 *
+;* *
+;* Routine Funktion Eingabe Ausgabe Stack L„nge Zeit/10MHz *
+;* *
+;* fadd Addition 2*Stack BC-DE 14 Byte 347 Byte 248 us *
+;* fsub Subtraktion 2*Stack BC-DE 14 Byte 12 Byte 255 us *
+;* fmul Multiplikation 2*Stack BC-DE 20 Byte 356 Byte 936 us *
+;* fdiv Division 2*Stack BC-DE 22 Byte 303 Byte 1081 us *
+;* fmul2 Mult. mit 2er-Potenz Stack,A BC-DE 10 Byte 162 Byte 28 us *
+;* fsqrt Quadratwurzel Stack BC-DE 22 Byte 621 Byte 1900 us *
+;* fitof Int-->Float Stack BC-DE 10 Byte 84 Byte 160 us *) *
+;* fftoi Float-->Int Stack BC-DE 10 Byte 104 Byte 170 us *) *
+;* fftoa Float-->ASCII 3*Stack ----- 40 Byte 451 Byte *) *
+;* fatof ASCII-->Float Stack C,BC-DE 42 Byte 396 Byte *) *
+;* *
+;* *) Die Ausfhrungszeiten streuen je nach Operand sehr stark und k”nnen *
+;* bei den ASCII-Funktionen bei vielen Millisekunden liegen. *
+;* *
+;* - Parametereingabe ber den Stack bedeutet, daá die Parameter mittels *
+;* PUSH vor dem Aufruf auf den Stack gelegt werden mssen. Diese Werte *
+;* werden von den Unterroutinen am Ende automatisch vom Stack entfernt. *
+;* Der zur šbergabe ben”tigte Platz ist bei den Angaben zur Stackbelastung *
+;* eingerechnet! *
+;* - Wollen Sie einzelne Routinen entfernen, so beachten Sie, daá fsub Teile *
+;* aus fadd, fdiv Teile aus fmul sowie fftoi Teile aus fitof verwendet ! *
+;* - Gleitkommaformat ist IEEE Single (32 Bit) *
+;* - Integerwerte bei fmul2, fitof und fftoi sind vorzeichenbehaftet *
+;* - Da die Routinen lokale Labels verwenden, ist mindestens AS 1.39 erfor- *
+;* derlich *
+;* - MACROS.INC muá vorher eingebunden werden *
+;******************************************************************************
+
+ section float
+
+;------------------------------------------------------------------------------
+; modulglobale Konstanten
+
+MaxExpo equ 255
+Bias equ 127
+
+OpSize equ 4 ; GrӇe eines Operanden
+
+fIX_alt equ 0 ; Top of Stack liegt IX
+FAdr equ 2 ; Rcksprungadresse
+Op2 equ 4 ; Adresse Operand 2
+Op1 equ Op2+OpSize ; Adresse Operand 1
+
+Ld10: dd ld(10)
+One: dd 1.0
+Ten: dd 10.0
+Tenth: dd 3dcccccdh ; =0.1, aber die Rundung auf manchen
+ ; Systemen variiert (damit Test nicht
+ ; scheitert)
+Half: dd 0.5
+
+cpsh macro reg,op,{NoExpand}
+ ld reg,(op+2)
+ push reg
+ ld reg,(op)
+ push reg
+ endm
+
+;------------------------------------------------------------------------------
+; Addition
+
+ proc fadd
+ link ix,0 ; Eintritt
+
+ push af ; Register retten
+ push hl
+
+ public AddSub:Parent ; Einsprung fr fsub
+
+AddSub: ld a,(ix+Op1+3) ; Vorzeichen Operand 1 laden
+ ld e,a ; Ergebnisvorzeichen in E, Bit 7
+ xor a,(ix+Op2+3) ; mit Vorzeichen von Op2 verknpfen
+ ld d,a ; Subtraktionsflag in D, Bit 7
+ res 7,(ix+Op1+3) ; Vorzeichen in Mantisse 1 l”schen
+ res 7,(ix+Op2+3) ; Vorzeichen in Mantisse 2 l”schen
+
+; Die Operanden sind jetzt in der Form 0eee eeee efff ... ffff
+
+ ld hl,(ix+Op1) ; Differenz Op1-Op2 bilden
+ sub hl,(ix+Op2)
+ ld hl,(ix+Op1+2)
+ sbc hl,(ix+Op2+2)
+ jr nc,Ad_1 ; Sprung falls Op1>Op2
+ ld bc,(ix+Op1) ; ansonsten Operanden vertauschen
+ ex bc,(ix+Op2)
+ ld (ix+Op1),bc
+ ld bc,(ix+Op1+2)
+ ex bc,(ix+Op2+2)
+ ld (ix+Op1+2),bc
+ ld a,e ; Ergebnisvorzeichen neu berechnen
+ xor a,d
+ ld e,a
+
+Ad_1: ld a,(ix+Op1+2) ; Exponent der grӇeren Zahl laden
+ ld c,(ix+Op1+3)
+ slaa
+ rl c
+ jr z,Den1
+ set 7,(ix+Op1+2) ; implizite Eins erzeugen
+Den1: ld a,(ix+Op2+2) ; dito Zahl 2
+ ld b,(ix+Op2+3)
+ slaa
+ rl b
+ jr z,Den2
+ set 7,(ix+Op2+2)
+
+Den2: push bc ; jetzt die Register fr den
+ push de ; Blocktransferbefehl retten
+ ld bc,2*OpSize-1 ; beide Operanden verschieben
+ ld hl,ix ; HL zeigt auf letztes Byte
+ add hl,Op2+2*OpSize-1
+ ld de,hl ; HL nach DE kopieren
+ dec hl ; HL zeigt auf vorletztes Byte
+ lddr ; Verschiebung beider Mantissen
+ pop de ; um 8 Bit nach links
+ pop bc
+
+ xor a,a
+ ld (ix+Op1),a ; Form: ffff ... ffff 0000 0000
+ ld (ix+Op2),a
+ ld a,c ; Differenz der Exponenten berechnen
+ sub a,b
+ ld b,a ; Differenz nach B fr LOOP-Befehl
+ jr z,N_Anp ; falls Null, keine Anpassung
+ cp a,25 ; mehr als 24? (Abfrage mit Carry
+ jp c,Anp ; erfordert Vergleich mit 25)
+ ld b,0 ; !!!!
+ jp Round
+
+Anp: srl (ix+Op2+3) ; Anpassung der zweiten Mantisse
+ rr (ix+Op2+2) ; durch Verschiebung nach rechts
+ rr (ix+Op2+1)
+ rr (ix+Op2)
+ djnz Anp ; bis B=0
+
+N_Anp: bit 7,d ; Addition oder Subtraktion ?
+ jr nz,Subtract ; ggfs. zur Subtraktion springen
+ ld hl,(ix+Op1) ; jetzt werden die beiden Mantissen
+ add hl,(ix+Op2) ; zueinander addiert
+ ld (ix+Op1),hl
+ ld hl,(ix+Op1+2)
+ adc hl,(ix+Op2+2)
+ ld (ix+Op1+2),hl
+ jr nc,Round ; kein šberlauf-->zum Runden
+ rr (ix+Op1+3) ; šberlauf einschieben
+ rr (ix+Op1+2)
+ rr (ix+Op1+1)
+ rr (ix+Op1)
+ inc bc ; Exponent erh”hen (B ist 0 durch
+ jr Round ; Schleife), zum Runden
+
+Subtract: ld hl,(ix+Op1) ; beide Mantissen werden voneinander
+ sub hl,(ix+Op2) ; subtrahiert
+ ld (ix+Op1),hl
+ ld hl,(ix+Op1+2)
+ sbc hl,(ix+Op2+2)
+ ld (ix+Op1+2),hl
+ jr m,Round ; bei fhrender Eins zum Runden
+ jr nz,Norm ; ungleich 0 ? Dann zum Normalisieren
+ cp hl,(ix+Op1) ; Rest der Mantisse auch Null ?
+ jr eq,Zero ; alles Null --> Ergebnis ist Null
+
+Norm: ld a,b ; Exponent noch nicht Null ?
+ or a,c
+ jr z,Round
+ dec bc ; Exponent erniedrigen
+ sla (ix+Op1) ; Mantisse normalisieren, bis
+ rl (ix+Op1+1) ; fhrende Eins auftaucht
+ rl (ix+Op1+2)
+ rl (ix+Op1+3)
+ jr p,Norm ; noch keine Eins-->weitermachen
+
+Round: add (ix+Op1),80h ; jetzt Runden auf Bit hinter Mantisse
+ jr nc,NoOver ; kein šbertrag ?
+ inc (ix+Op1+1) ; doch, n„chstes Mantissenbyte
+ jr nz,NoOver ; behandeln, jetzt auf Null prfen,
+ inc (ix+Op1+2) ; da der INC-Befehl kein Carry liefert
+ jr nz,NoOver
+ inc (ix+Op1+3)
+ jr nz,NoOver
+ scf ; fhrende Eins erzeugen
+ rr (ix+Op1+3) ; bei šberlauf Mantisse durch
+ rr (ix+Op1+2) ; Rechtsschieben wieder normalisieren
+ rr (ix+Op1+1) ; (nur fr 24 Bit notwendig)
+ inc bc ; und Exponent korrigieren
+
+NoOver: xor a,a ; A = 0
+ cp a,(ix+Op1+3) ; Mantisse auf Null prfen
+ jr nz,NoZero
+ cp a,(ix+Op1+2)
+ jr nz,NoZero
+ cp a,(ix+Op1+1) ; alle Mantissenbytes Null ?
+ jr nz,NoZero ; dann ist auch das Ergebnis Null
+
+Zero: ld b,a ; Null-Ergebnis aufbauen
+ ld c,a
+ ld de,bc
+ jr Exit ; dann Routine verlassen
+
+NoZero: cp a,b ; A ist Null
+ ld a,MaxExpo ; Exponent oberes Byte ungleich Null ?
+ jr nz,Over ; dann ist šberlauf eingetreten
+ cp a,c ; oder genau MaxExpo erreicht ?
+ jr nz,NoUe
+Over: ld c,a ; Exponent auf MaxExpo setzen
+ xor a,a ; und Mantisse auf Null
+ ld (ix+Op1+3),a
+ ld (ix+Op1+2),a
+ ld (ix+Op1+1),a
+ jr DeNorm
+
+NoUe: xor a,a ; A = 0
+ cp a,c ; Exponent Null (Zahl denormalisiert ?
+ jr z,DeNorm ; ja -->
+ sla (ix+Op1+1) ; fhrendes Bit wird nicht gespeichert
+ rl (ix+Op1+2) ; daher Mantisse um 1 Bit nach links
+ rl (ix+Op1+3)
+
+DeNorm: ld b,c ; Ergebnis aufbauen: Exponent in B
+ ld c,(ix+Op1+3) ; Mantisse oberstes Byte
+ ld d,(ix+Op1+2)
+ sla e ; Vorzeichen aus E in Carry schieben
+ ld e,(ix+Op1+1)
+ rr b ; Vorzeichen in Ergebnis einschieben
+ rr c
+ rr d
+ rr e
+
+Exit: pop hl ; Register restaurieren
+ pop af
+
+ unlk ix ; Austritt
+ retd 2*OpSize ; Parameter abr„umen
+ endp
+
+;------------------------------------------------------------------------------
+; Subtraktion
+
+ proc fsub
+
+ link ix,0 ; Eintritt
+
+ push af ; Register retten
+ push hl
+
+ xor (ix+Op2+3),80h ; Vorzeichen Operand 2 kippen
+
+ jrl AddSub ; weiter wie Addition
+
+ endp
+
+;------------------------------------------------------------------------------
+; Multiplikation
+
+ proc fmul
+
+ DefLocal temp,6 ; Platz Tempor„rvariable
+
+ link ix,LocalSize ; Platz auf Stack reservieren
+
+ push af ; Register retten
+ push hl
+
+ ld a,(ix+Op1+3) ; Ergebnisvorzeichen bestimmen
+ xor a,(ix+Op2+3)
+ ld c,a ; in C merken
+
+ ld d,0 ; Exponent 1 laden
+ ld e,(ix+Op1+3)
+ ld a,(ix+Op1+2)
+ slaa ; Exponent unterstes Bit in Carry
+ rl e ; und in E einschieben
+ srla ; ergibt Bit 7=0
+ ld (ix+Op1+3),a ; impl. Null vorbesetzen+um 8 Bit schieben
+ cp e,0
+ jr z,Den1 ; falls Null, dann denormalisiert
+ set 7,(ix+Op1+3) ; ansonsten impl. Eins erzeugen
+ dec de ; Bias kompensieren
+Den1: ld hl,(ix+Op1) ; jetzt restliche Bytes verschieben
+ ld (ix+Op1+1),hl
+ xor hl,hl ; unterste Mantissenbits l”schen
+ ld (ix+Op1),h ; Form: ffff ... ffff 0000 0000
+
+ ld (ix+temp+4),hl ; lokale Variable mit Null vorbesetzen
+ ld (ix+temp+2),hl
+ ld (ix+temp),hl
+
+ ld l,(ix+Op2+3) ; Exponent 2 in HL aufbauen
+ ld a,(ix+Op2+2)
+ res 7,(ix+Op2+2) ; gleiches Verfahren wie Op1
+ slaa
+ rl l
+ jr z,Den2
+ set 7,(ix+Op2+2)
+ dec hl
+Den2:
+ add hl,de ; Exponenten aufaddieren
+ sub hl,Bias-3 ; Bias-3 subtrahieren
+ jp p,NoZero ; positiv-->kein Unterlauf
+ ld a,l ; Exponent <-24 ?
+ cp a,-24
+ jr nc,NoZero
+ jp MulZero ; ja, dann ist Ergebnis Null
+
+NoZero: ld b,24 ; Schleifenz„hler Multiplikation
+ ld de,0 ; Hilfsregister Multiplikand
+ push hl ; HL zum Addieren benutzen
+Multiply: srl (ix+Op1+3) ; Multiplikand nach rechts schieben
+ rr (ix+Op1+2)
+ rr (ix+Op1+1)
+ rr (ix+Op1)
+ rr d ; DE als Verl„ngerung von Operand 1
+ rr e
+ sla (ix+Op2) ; Multiplikator nach links schieben
+ rl (ix+Op2+1)
+ rl (ix+Op2+2) ; falls fhrendes Bit 0, nicht addieren
+ jr nc,NoAdd
+ ld hl,(ix+temp) ; sonst aufaddieren
+ add hl,de
+ ld (ix+temp),hl
+ ld hl,(ix+temp+2)
+ adc hl,(ix+Op1)
+ ld (ix+temp+2),hl
+ ld hl,(ix+temp+4)
+ adc hl,(ix+Op1+2)
+ ld (ix+temp+4),hl
+NoAdd: djnz Multiply ; Schleife durchlaufen
+ pop hl
+ ld a,(ix+temp+5)
+ or a,a ; Flags setzen
+ jp m,MulRound ; bei fhrender Eins zum Runden
+ jr nz,Normalize ; ansonsten normalisieren
+ cp a,(ix+temp+4)
+ jr nz,Normalize
+ cp a,(ix+temp+3)
+ jr nz,Normalize
+ cp a,(ix+temp+2)
+ jr Normalize
+ jp MulZero ; komplett Null-->Ergebnis Null
+
+Normalize: bit 7,h ; Exponent negativ ?
+ jp nz,Underrun ; ggf. Unterlauf behandlen
+
+Norm1: cp hl,0 ; Exponent=0 ?
+ jr z,MulRound
+ dec hl ; Exponent erniedrigen,
+ sla (ix+temp) ; Mantisse verschieben...
+ rl (ix+temp+1)
+ rl (ix+temp+2)
+ rl (ix+temp+3)
+ rl (ix+temp+4)
+ rl (ix+temp+5)
+ jp p,Norm1 ; ...bis fhrende Eins auftaucht
+
+ public MulRound:Parent ; Einsprung fr Division
+MulRound: ld a,(ix+temp+2) ; jetzt Runden auf Bit hinter Mantisse
+ add a,80h
+ jr nc,NoOver ; kein šbertrag
+ inc (ix+temp+3) ; doch, n„chstes Mantissenbyte
+ jr nz,NoOver ; behandeln, jetzt auf Null prfen
+ inc (ix+temp+4) ; da INC kein Carry liefert
+ jr nz,NoOver
+ inc (ix+temp+5)
+ jr nz,NoOver
+ scf ; Eins erzeugen
+ rr (ix+temp+5) ; bei šberlauf Mantisse durch
+ rr (ix+temp+4) ; Rechtsschieben wieder normalisieren
+ rr (ix+temp+3)
+ inc hl ; und Exponent korrigieren
+
+NoOver: cp hl,MaxExpo ; Exponent prfen
+ jr ult,NoUeber ; kein šberlauf
+
+ public MulOver:Parent ; Einsprung fr fdiv
+MulOver: ld hl,MaxExpo ; šberlauf: Exponent=MaxExpo
+ ld (ix+temp+5),h
+ ld (ix+temp+4),h
+ ld (ix+temp+3),h
+ jr DeNorm
+
+NoUeber: xor a,a ; A=0
+ cp a,l ; Exponent ist Null ?
+ jr z,DeNorm ; ja, Ergebnis ist denormalisiert
+ sla (ix+temp+3) ; nein, fhrende=implizite Eins
+ rl (ix+temp+4) ; rausschieben
+ rl (ix+temp+5)
+
+DeNorm: sla c ; Vorzeichen in Carry schieben
+ ld b,l ; Exponent einsetzen
+ ld c,(ix+temp+5)
+ ld d,(ix+temp+4)
+ ld e,(ix+temp+3)
+ rr b ; und Vorzeichen einschieben
+ rr c
+ rr d
+ rr e ; Form: seee eeee efff ffff ... ffff
+
+Result: pop hl ; Register zurck
+ pop af
+
+ unlk ix ; Stackrahmen abbauen
+ retd 2*OpSize ; Operanden abr„umen
+
+ public MulZero:Parent ; Einsprung fr fdiv
+MulZero: xor a,a ; Ergebnis ist Null
+ ld b,a
+ ld c,a
+ ld d,a
+ ld e,a
+ jr Result
+
+Underrun: ld a,l ; Exponent in A
+ neg a ; negieren fr Schleifenz„hler
+ cp a,24 ; totaler Unterlauf ?
+ jr nc,MulZero ; ja, dann ist Ergebnis Null
+ ld b,a ; Mantisse denormalisieren
+Shr: srl (ix+temp+5) ; bis Exponent Null ist
+ rr (ix+temp+4)
+ rr (ix+temp+3)
+ djnz Shr
+ ld l,b ; Exponent in Register L=B=0
+ jp Denorm ; denormalisiertes Ergebnis erzeugen
+
+ endp
+
+;------------------------------------------------------------------------------
+; Division
+
+ proc fdiv
+
+ DefLocal temp,6 ; Platz Tempor„rvariable
+
+ link ix,LocalSize ; 6 Byte Platz auf Stack reservieren
+
+ push af ; Register retten
+ push hl
+
+ ld a,(ix+Op1+3) ; Ergebnisvorzeichen bestimmen
+ xor a,(ix+Op2+3)
+ ld c,a ; Vorzeichen in C Bit 7 merken
+ push bc ; Vorzeichen retten
+
+ ld h,0 ; Exponent 1 laden
+ ld l,(ix+Op1+3)
+ ld a,(ix+Op1+2)
+ res 7,(ix+Op1+2) ; impl. Null vorbesetzen
+ slaa ; Exponent unterstes Bit in Carry
+ rl l ; und in L einschieben
+ jr z,Den1 ; falls Null, dann Op1 denormalisiert
+ set 7,(ix+Op1+2) ; implizite Eins erzeugen
+ dec hl ; Bias kompensieren
+Den1:
+ ld d,0 ; Exponent 2 in DE aufbauen
+ ld e,(ix+Op2+3)
+ ld a,(ix+Op2+2)
+ ld (ix+Op2+3),a ; Verfahren wie oben
+ res 7,(ix+Op2+3)
+ slaa
+ rl e
+ jr z,Den2
+ set 7,(ix+Op2+3)
+ dec de
+Den2:
+ ld bc,(ix+Op2) ; jetzt restliche Bytes kopieren
+ ld (ix+Op2+1),bc
+ xor a,a ; A=0
+ ld (ix+Op2),a ; Form: ffff ... ffff 0000 0000
+ srl (ix+Op2+3)
+ rr (ix+Op2+2)
+ rr (ix+Op2+1)
+ rr (ix+Op2) ; Form: 0fff ... ffff f000 0000
+ jr nz,NoZero1 ; Mantisse 2 auf Null prfen
+ cp a,(ix+Op2+1)
+ jr nz,NoZero1
+ cp a,(ix+Op2+2)
+ jr nz,NoZero1
+ cp a,(ix+Op2+3)
+ jr nz,NoZero1
+ jp MulOver
+
+NoZero1: xor a,a ; Carry-Flag l”schen
+ sbc hl,de ; Exponenten subtrahieren
+ add hl,Bias ; Bias addieren
+ jr p,NoZero ; Exponent negativ ?
+ cp l,-24 ; Exponent kleiner als -24 ?
+ jr nc,NoZero
+ jp MulZero ; ja, dann ist das Ergebnis Null
+NoZero:
+ add hl,25 ; Exponent um 25 erh”hen; jetzt ist er sicher gr”áer als Null
+ xor a,a ; A=0
+ ld bc,(ix+Op1+1) ; Divident in Register kopieren
+ ld d,(ix+Op1)
+ ld e,a ; die untersten Bits sind Null
+ cp a,d ; ist Divident Null ?
+ jr nz,NoZero2
+ cp a,c
+ jr nz,NoZero2
+ cp a,b
+ jr nz,NoZero2
+ pop bc ; Stack bereinigen (Vorzeichen laden)
+ jp MulZero ; und Null als Ergebnis ausgeben
+NoZero2:
+ ld (ix+temp+5),a ; Ergebnis vorbesetzen
+ ld (ix+temp+4),a
+ ld (ix+temp+3),a
+ ld (ix+temp+2),a
+
+NormLoop: bit 6,(ix+Op2+3) ; ist der Divisor normalisiert ?
+ jr nz,Norm ; ja-->
+ inc hl ; nein, Exponent erh”hen
+ sla (ix+Op2) ; Divisor verschieben bis in
+ rl (ix+Op2+1) ; Form 01ff ...
+ rl (ix+Op2+2)
+ rl (ix+Op2+3)
+ jr NormLoop
+Norm: srl b
+ rr c
+ rr d
+ rr e ; Form: 0fff ... ffff f000 0000
+
+ push iy ; Exponent nach IY
+ ld iy,hl
+Loop: ld (ix+Op1+2),bc ; Divident zwischenspeichern
+ ; die Speicherpl„tze von Op1
+ ld (ix+Op1),de ; stehen zur Verfgung, da wir Op1
+ ; in die Register BC-DE kopiert haben
+ ld hl,de ; jetzt Divisor abziehen
+ sub hl,(ix+Op2)
+ ld de,hl
+ ld hl,bc
+ sbc hl,(ix+Op2+2)
+ ld bc,hl
+ jr nc,IsOne ; kein Carry: Divisor paát
+ ld de,(ix+Op1) ; ansonsten zurckkopieren
+ ld bc,(ix+Op1+2) ; Carry bleibt erhalten!
+IsOne: ccf ; Carry-Flag umdrehen
+ rl (ix+temp+2) ; Ergebnis aufbauen
+ rl (ix+temp+3)
+ rl (ix+temp+4)
+ rl (ix+temp+5)
+ sla e ; Divident verschieben
+ rl d
+ rl c
+ rl b
+
+ add iy,-1 ; Exponent erniedrigen
+ jr z,DeNorm ; falls Null, dann denormalisiert
+ bit 0,(ix+temp+5) ; fhrende Eins in Ergebnis-Mantisse ?
+ jr z,Loop ; nein, weiter rechnen
+
+DeNorm: ld hl,iy ; Exponent zurck
+ ld b,(ix+temp+5) ; h”chstes Bit merken
+ ld a,(ix+temp+4)
+ ld (ix+temp+5),a ; Mantisse in Form
+ ld iy,(ix+temp+2) ; ffff ... ffff 0000 0000
+ ld (ix+temp+3),iy
+ pop iy ; IY erst jetzt freigeben
+ rr b ; h”chstes Bit einschieben
+ rr (ix+temp+5)
+ rr (ix+temp+4)
+ rr (ix+temp+3)
+ rr (ix+temp+2)
+
+ pop bc ; Vorzeichen wieder laden
+ xor a,a ; A=0
+ cp a,(ix+temp+5) ; Mantisse ist Null ?
+ jr nz,NoZero3
+ cp a,(ix+temp+4)
+ jr nz,NoZero3
+ cp a,(ix+temp+3)
+ jr nz,NoZero3
+ cp a,(ix+temp+2)
+ jp z,MulZero
+NoZero3:
+ jp MulRound
+
+ endp
+
+;------------------------------------------------------------------------------
+; Wandlung Integer-->Gleitkomma
+
+ proc fitof
+
+ link ix,0 ; Stackrahmen aufbauen
+ push af ; Register retten
+ push hl
+
+ ld bc,(ix+Op2+2) ; Operanden hereinholen
+ ld de,(ix+Op2) ; Reihenfolge: BCDE
+
+ ld hl,bc ; Operand = 0 ?
+ or hl,de
+ jr z,ItofResult ; dann Ergebnis Null
+
+ bit 7,b ; Zahl positiv ?
+ jr z,Positive
+ ld hl,bc ; dann Zahl negieren
+ xor hl,-1
+ ld bc,hl
+ ld hl,de
+ xor hl,-1
+ inc hl
+ or hl,hl
+ ld de,hl
+ jr nz,Positive
+ inc bc
+
+Positive: ld l,Bias+32 ; Exponent vorbesetzen
+Shift: dec l
+ sla e ; Mantisse verschieben, bis fhrende
+ rl d ; Eins auftaucht
+ rl c
+ rl b
+ jr nc,Shift
+ ld e,d ; Exponent einsetzen
+ ld d,c
+ ld c,b
+ ld b,l
+ sla (ix+Op2+3) ; Vorzeichen in Carry
+ rr b ; ins Ergebnis einschieben
+ rr c
+ rr d
+ rr e
+
+ public ItofResult:Parent
+ItofResult: pop hl ; Register zurck
+ pop af
+ unlk ix ; abbauen
+ retd 4 ; Ende
+
+ endp
+
+;------------------------------------------------------------------------------
+; Wandlung Gleitkomma-->Integer
+
+ proc fftoi
+
+ link ix,0 ; Stackrahmen aufbauen
+
+ push af ; Register retten
+ push hl
+
+ ld d,(ix+Op2) ; Operand in Register laden
+ ld bc,(ix+Op2+1) ; Reihenfolge: EBCD
+ ld e,(ix+Op2+3) ; erspart sp„ter Vertauschungen
+
+ ld h,e ; Vorzeichen in H, Bit 7
+ ld a,e ; Exponent in A aufbauen
+ sla b ; LSB aus B holen
+ rla
+ scf ; impl. Eins einschieben
+ rr b
+ sub a,Bias
+ ld l,a ; Exponent nach L kopieren
+ jp m,Zero ; falls keiner Null, Ergebnis Null
+ ld a,30
+ cp a,l ; grӇer 30 ?
+ jr c,Over ; dann šberlauf
+ ld e,0 ; Zahl jetzt in BCDE in der Form
+ inc a ; 1fff ... ffff 0000 0000
+
+Shift: srl b ; jetzt Mantisse verschieben
+ rr c
+ rr d
+ rr e
+ inc l
+ cp a,l ; bis Exponent stimmt
+ jr nz,Shift
+ bit 7,h ; Zahl negativ ?
+ jr z,ItofResult ; nein, fertig
+
+ ld hl,de ; Zahl negieren
+ xor hl,-1
+ ld de,hl
+ ld hl,bc
+ xor hl,-1
+ ld bc,hl
+ inc de
+ jr nz,ItofResult
+ inc bc
+ jr nz,ItofResult
+
+Zero: ld bc,0
+ ld de,bc
+ jp ItofResult ; Ergebnis Null
+
+Over: bit 7,h ; Ergebnis positiv ?
+ jr z,OpPos
+ ld b,80h ; MININT laden
+ xor a,a ; A=0
+ ld c,a
+ ld d,a
+ ld e,a
+ jp ItofResult
+OpPos: ld b,7fh ; MAXINT laden
+ ld a,0ffh
+ ld c,a
+ ld d,a
+ ld e,a
+ jp ItofResult
+
+ endp
+
+;------------------------------------------------------------------------------
+; Multiplikation mit Zweierpotenz (in A)
+
+ proc fmul2
+
+ link ix,0 ; Stackrahmen aufbauen
+
+ push af ; Register retten
+ push hl
+
+ ld de,(ix+Op2) ; Operand 1 in Register laden
+ ld bc,(ix+Op2+2)
+
+ ld h,a ; Operand 2 nach H kopieren
+ ld l,b ; Vorzeichen nach L, Bit 7
+ xor a,a ; A=0
+ cp a,b ; Operand 1 = Null ?
+ jr nz,NoZero
+ cp a,c
+ jr nz,NoZero
+ cp a,d
+ jr nz,NoZero
+ cp a,e
+ jr z,Zero
+
+NoZero: sla e ; Operand 1 verschieben
+ rl d
+ rl c
+ rl b ; Form: eeee eeee ffff ... fff0
+ jr z,Den ; Falls Exponent Null -->denormal
+
+ add a,h ; A=0+H
+ jr m,Div ; Falls Op2<0-->Division
+ add a,b ; A=Summe der Exponenten
+ ld b,a ; zurck nach B
+ jr c,Over ; bei šberlauf-->
+ cp a,MaxExpo ; oder genau MaxExpo
+ jr z,Over
+
+Result: sla l ; Vorzeichen in Carry schieben
+ rr b
+ rr c
+ rr d
+ rr e ; Ergebnis zusammensetzen
+
+Zero: pop hl ; Register zurck
+ pop af
+
+ unlk ix ; Stackrahmen abbauen
+ retd 4 ; Ende
+
+Over: ld b,MaxExpo ; šberlauf: Exponent=MaxExpo
+ xor a,a ; Mantisse=0
+ ld c,a
+ ld d,a
+ ld e,a
+ jr Result
+
+Div: add a,b ; A = Summe der Exponenten
+ ld b,a ; zurck nach B
+ jr z,Div2
+ jr p,Result ; falls >0, Ergebnis abliefern
+Div2: scf ; implizite Eins real machen
+ rr c
+ rr d
+ rr e ; Form: eeee eeee 1fff ... ffff
+
+Denorm: xor a,a ; A = 0
+ cp a,b ; Exponent Null ?
+ jr z,Result ; ja, ergebnis abliefern
+ srl c
+ rr d
+ rr e ; Mantisse denormalisieren
+ jr nz,NoZero2
+ cp a,d
+ jr nz,NoZero2
+ cp a,c
+ jr nz,NoZero2
+ ld b,a ; totaler Unterlauf, Ergebnis = Null
+ jr Zero
+
+NoZero2: inc b ; Exponent erh”hen
+ jr Denorm ; weiter denormalisieren
+
+DDD: add a,b ; Summe der Exponenten bilden
+ ld b,a ; zurck nach B
+ jr Denorm
+
+Den: add a,h ; A=0+H
+ jr m,DDD ; bei Division verzweigen
+NoOver: sla e ; Multiplikation: Eine
+ rl d ; denormalisierte Mantisse
+ rl c ; wird wieder normalisiert
+ jr c,Stop ; bis fhrende Eins rausfliegt
+ dec h ; oder Operand 2 = Null
+ jr nz,NoOver
+ jr Result
+
+Stop: ld a,h ; Summe der Exponenten bilden
+ add a,b
+ ld b,a ; zurck nach B
+ jr Result
+
+ endp
+
+;------------------------------------------------------------------------------
+; Quadratwurzel ziehen
+
+ proc fsqrt
+
+Op equ 4 ; Lage Parameter
+ DefLocal XRoot,4 ; Iterationsvariablen
+ DefLocal m2,4
+ DefLocal xx2,4
+
+ link ix,LocalSize ; Stackrahmen aufbauen
+
+ push af ; Register retten
+ push hl
+ push iy
+
+ bit 7,(ix+Op+3) ; negatives Argument ?
+ jp nz,DomainError ; dann Fehler
+
+ ld hl,(ix+Op+2) ; Exponent isolieren
+ and hl,07f80h
+ jp z,Zero ; keine Behandlung denormaler Zahlen
+
+ ld (ix+Op+3),0 ; Mantisse isolieren
+ and (ix+Op+2),7fh
+ sub hl,7fh*80h ; Bias vom Exponenten entfernen
+ ld bc,hl
+ bit 7,c ; Exponent ungerade ?
+ res 7,c
+ jr z,EvenExp
+ ld hl,(ix+Op) ; ja: Mantisse verdoppeln
+ add hl,hl
+ ld (ix+Op),hl
+ ld hl,(ix+Op+2)
+ adc hl,hl
+ add hl,100h-80h ; impl. Eins dazu
+ ld (ix+Op+2),hl
+EvenExp:
+ sra b ; Exponent/2 mit Vorzeichen
+ rr c
+ ld hl,7fh*80h ; Bias wieder dazu
+ add hl,bc
+ ld iy,hl ; Exponent in IY aufheben
+ ld de,(ix+Op+1) ; x ausrichten (um 7 nach links)
+ ld a,(ix+Op+3) ; oberstes Byte merken
+ ld (ix+Op+2),de ; da wir hier eins zuviel schieben
+ ld d,(ix+Op)
+ ld e,0
+ ld (ix+Op),de
+ srla ; dieses Bit einschieben
+ rr (ix+Op+3)
+ rr (ix+Op+2)
+ rr (ix+Op+1)
+ rr (ix+Op)
+ ld de,0 ; vorbelegen
+ ld (ix+XRoot),de
+ ld (ix+m2),de
+ ld d,40h
+ ld (ix+XRoot+2),de
+ ld d,10h
+ ld (ix+m2+2),de
+Loop10: ld de,(ix+Op) ; xx2 = x
+ ld (ix+xx2),de
+ ld de,(ix+Op+2)
+ ld (ix+xx2+2),de
+Loop11: ld hl,(ix+xx2) ; xx2 -= xroot
+ sub hl,(ix+XRoot)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+XRoot+2)
+ ld (ix+xx2+2),hl
+ srl (ix+XRoot+3) ; xroot /= 2
+ rr (ix+XRoot+2)
+ rr (ix+XRoot+1)
+ rr (ix+XRoot)
+ ld hl,(ix+xx2) ; xx2 -= m2
+ sub hl,(ix+m2)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+m2+2)
+ ld (ix+xx2+2),hl
+ jr m,DontSet1
+ ld hl,(ix+xx2) ; x = xx2
+ ld (ix+Op),hl
+ ld hl,(ix+xx2+2)
+ ld (ix+Op+2),hl
+ ld hl,(ix+XRoot) ; xroot += m2
+ or hl,(ix+m2)
+ ld (ix+XRoot),hl
+ ld hl,(ix+XRoot+2)
+ or hl,(ix+m2+2)
+ ld (ix+XRoot+2),hl
+ ld hl,(ix+m2) ; m2 /= 4
+ ld de,(ix+m2+2)
+ rept 2
+ srl d
+ rr e
+ rr h
+ rr l
+ endm
+ ld (ix+m2),hl
+ ld (ix+m2+2),de
+ or hl,de
+ jr nz,Loop11
+ jr IsSame
+DontSet1: ld hl,(ix+m2) ; m2 /= 4
+ ld de,(ix+m2+2)
+ rept 2
+ srl d
+ rr e
+ rr h
+ rr l
+ endm
+ ld (ix+m2),hl
+ ld (ix+m2+2),de
+ or hl,de
+ jp nz,Loop10 ; 15* abarbeiten
+ ; Bit 22..8
+ ld hl,(ix+Op) ; 17. Iteration separat
+ ld (ix+xx2),hl
+ ld hl,(ix+Op+2)
+ ld (ix+xx2+2),hl
+IsSame: ld hl,(ix+xx2)
+ sub hl,(ix+XRoot)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+XRoot+2)
+ ld (ix+xx2+2),hl
+ ld de,(ix+XRoot+2) ; mitsamt Carry...
+ ld hl,(ix+XRoot)
+ srl d
+ rr e
+ rr h
+ rr l
+ jr nc,NoC1
+ set 7,d
+NoC1: ld (ix+XRoot+2),hl ; auf neues Alignment umstellen
+ ld (ix+XRoot),de
+ decw (ix+xx2) ; Carry von 0-$4000: xx2 -= m2
+ jr nz,NoC2
+ decw (ix+xx2+2)
+NoC2: bit 7,(ix+xx2+3)
+ jr nz,DontSet7
+ or (ix+xx2+3),0c0h ; 0-$4000: x2 -= m2, Teil 2
+ ld hl,(ix+xx2)
+ ld (ix+Op),hl
+ ld hl,(ix+xx2+2)
+ ld (ix+Op+2),hl
+ or (ix+XRoot+1),40h; xroot += m2
+DontSet7: ld hl,(ix+Op) ; x auf neues Alignment umstellen
+ ld de,(ix+Op+2)
+ ld (ix+Op),de
+ ld (ix+Op+2),hl
+ ld hl,1000h ; m2 - obere H„lfte schon 0
+ ld (ix+m2),hl
+Loop20: ld hl,(ix+Op) ; xx2 = x
+ ld (ix+xx2),hl
+ ld hl,(ix+Op+2)
+ ld (ix+xx2+2),hl
+Loop21: ld hl,(ix+xx2) ; xx2 -= xroot
+ sub hl,(ix+XRoot)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+XRoot+2)
+ ld (ix+xx2+2),hl
+ srl (ix+XRoot+3) ; XRoot = XRoot/2
+ rr (ix+XRoot+2)
+ rr (ix+XRoot+1)
+ rr (ix+XRoot)
+ ld hl,(ix+xx2) ; x2 -= m2
+ sub hl,(ix+m2)
+ ld (ix+xx2),hl
+ ld hl,(ix+xx2+2)
+ sbc hl,(ix+m2+2)
+ ld (ix+xx2+2),hl
+ jr m,DontSet2
+ ld hl,(ix+xx2) ; x = xx2
+ ld (ix+Op),hl
+ ld hl,(ix+xx2+2)
+ ld (ix+Op+2),hl
+ ld hl,(ix+XRoot) ; xroot += m2
+ or hl,(ix+m2)
+ ld (ix+XRoot),hl
+ ld hl,(ix+XRoot+2)
+ or hl,(ix+m2+2)
+ ld (ix+XRoot+2),hl
+ ld hl,(ix+m2) ; m2 /= 4
+ ld de,(ix+m2+2)
+ rept 2
+ srl d
+ rr e
+ rr h
+ rr l
+ endm
+ ld (ix+m2),hl
+ ld (ix+m2+2),de
+ or hl,de
+ jr nz,Loop21
+ jr Finish
+DontSet2: ld hl,(ix+m2) ; m2 /= 4
+ ld de,(ix+m2+2)
+ rept 2
+ srl d
+ rr e
+ rr h
+ rr l
+ endm
+ ld (ix+m2),hl
+ ld (ix+m2+2),de
+ or hl,de
+ jp nz,Loop20 ; 7* abarbeiten
+
+Finish: ld hl,(ix+Op) ; Aufrunden notwendig ?
+ sub hl,(ix+XRoot)
+ ld (ix+Op),hl
+ ld hl,(ix+Op+2)
+ sub hl,(ix+XRoot+2)
+ ld (ix+Op+2),hl
+ jr ule,NoInc
+ incw (ix+XRoot) ; wenn ja, durchfhren
+ jr nz,NoInc
+ incw (ix+XRoot)
+NoInc: res 7,(ix+XRoot+2) ; impl. Eins l”schen
+ ld hl,(ix+XRoot+2) ; Exponent einbauen
+ or hl,iy
+ ld bc,hl ; Ergebnis in BC-DE
+ ld de,(ix+XRoot)
+ jr End
+
+DomainError: ld bc,0ffc0h ; - NAN zuckgeben
+ ld de,0
+ jr End
+
+Zero: ld bc,0 ; Ergebnis 0
+ ld de,bc
+
+End: pop iy ; Register zurck
+ pop hl
+ pop af
+
+ unlk ix ; Stackrahmen abbauen
+ retd 4 ; Ende
+
+ endp
+
+;------------------------------------------------------------------------------
+; Zehnerpotenz bilden
+
+ subproc fPot10
+
+ push ix ; Register retten
+ push iy
+ push hl
+
+ ld bc,(One+2) ; Ausgangspunkt frs Multiplizieren
+ ld de,(One)
+ ld ix,(Ten+2) ; zu benutzende Potenz
+ ld iy,(Ten)
+ or hl,hl ; negative Potenz?
+ jr p,IsPos
+ ld ix,(Tenth+2) ; dann eben mit Zehntel
+ ld iy,(Tenth)
+ xor hl,-1 ; Zweierkomplement
+ inc hl
+IsPos:
+ or hl,hl ; weiter multiplizieren ?
+ jr z,End ; nein, Ende
+ bit 0,l ; Restpotenz ungerade ?
+ jr z,IsEven
+ push bc ; ja: einzeln multiplizieren
+ push de
+ push ix
+ push iy
+ call fmul
+IsEven: srl h
+ rr l
+ push bc ; n„chste Potenz berechnen
+ push de
+ push ix ; durch quadrieren
+ push iy
+ push ix
+ push iy
+ call fmul
+ ld ix,bc
+ ld iy,de
+ pop de
+ pop bc
+ jr IsPos ; weitersuchen
+End:
+ pop hl ; Register zurck
+ pop iy
+ pop ix
+
+ ret ; Ende
+
+ endp
+
+;------------------------------------------------------------------------------
+
+ subproc fOutDec
+
+Op equ 6 ; Adresse Operand
+Format equ 4 ; Formatdeskriptor
+ DefLocal Temp,4 ; 64-Bit-Erweiterung Divident
+
+ link ix,LocalSize
+
+ push af ; Register retten
+ push bc
+ push de
+ push hl
+
+ bit 7,(ix+Op+3) ; negativ ?
+ jr z,IsPos
+ ld (iy),'-' ; ja: vermerken...
+ inc iy
+ ld hl,(ix+Op) ; ...und Zweierkomplement
+ xor hl,-1
+ ld (ix+Op),hl
+ ld hl,(ix+Op+2)
+ xor hl,-1
+ ld (ix+Op+2),hl
+ incw (ix+Op)
+ jr nz,GoOn
+ incw (ix+Op+2)
+ jr GoOn
+IsPos: bit 7,(ix+Format+1) ; Pluszeichen ausgeben ?
+ jr nz,GoOn
+ ld (iy),'+'
+ inc iy
+GoOn: res 7,(ix+Format+1) ; Plusflag l”schen
+ ld de,0 ; Nullflag & Z„hler l”schen
+
+InLoop: ld hl,0 ; Division vorbereiten
+ ld (ix+Temp),hl ; dazu auf 64 Bit erweitern
+ ld (ix+Temp+2),hl
+ ld b,32 ; 32-Bit-Division
+DivLoop: sll (ix+Op) ; eins weiterschieben
+ rl (ix+Op+1)
+ rl (ix+Op+2)
+ rl (ix+Op+3)
+ rl (ix+Temp)
+ rl (ix+Temp+1)
+ rl (ix+Temp+2)
+ rl (ix+Temp+3)
+ srl (ix+Op) ; fr nachher
+ ld hl,(ix+Temp) ; probeweise abziehen
+ sub hl,10
+ ld (ix+Temp),hl
+ ld hl,(ix+Temp+2)
+ sbc hl,0
+ ld (ix+Temp+2),hl
+ jr nc,DivOK ; paát es ?
+ ld hl,(ix+Temp) ; nein, zurcknehmen
+ add hl,10
+ ld (ix+Temp),hl
+ ld hl,(ix+Temp+2)
+ adc hl,0
+ ld (ix+Temp+2),hl
+ scf ; ins Ergebnis 0 einschieben
+DivOK: ccf ; neues Ergebnisbit
+ rl (ix+Op) ; von unten einschieben
+ djnz DivLoop
+
+ ld a,(ix+Temp) ; ASCII-Offset addieren
+ add a,'0'
+ bit 0,d ; schon im Nullbereich ?
+ jr z,NormVal
+ ld a,(ix+Format) ; ja, dann gewnschtes Leerzeichen
+NormVal: push af ; auf LIFO legen
+ inc e ; ein Zeichen mehr
+ ld a,(ix+Op) ; Quotient Null ?
+ or a,(ix+Op+1)
+ or a,(ix+Op+2)
+ or a,(ix+Op+3)
+ ld d,0 ; Annahme: nicht Null
+ jr nz,InLoop ; falls <>0, auf jeden Fall weiter
+ ld d,0ffh ; Flag auf True setzen
+ ld a,e ; ansonsten nur weiter, falls minimale
+ cp a,(ix+Format+1) ; Zahl noch nicht erreicht
+ jr ult,InLoop
+
+ ld b,e ; jetzt Zeichen ausgeben
+OutLoop: pop af
+ ld (iy),a
+ inc iy
+ djnz OutLoop
+
+ pop hl ; Register zurck
+ pop de
+ pop bc
+ pop af
+
+ unlk ix
+ retd 6
+
+ endp
+
+;------------------------------------------------------------------------------
+; Wandlung Float-->ASCII
+
+ proc fftoa
+
+Op equ 8 ; Lage Eingabe auf Stack
+Format equ 6 ; Lage Formatdeskriptor auf Stack
+Buffer equ 4 ; Pufferadresse
+ DefLocal Copy,4 ; Tempor„rkopie der Zahl
+ DefLocal ExpSave,2 ; berechneter Exponent
+
+ link ix,LocalSize ; Platz fr Exponenten/Kopie der Zahl
+
+ push af ; Register retten
+ push de
+ push iy
+ push hl
+
+ ld iy,(ix+Buffer) ; Pufferadresse holen
+
+ ld hl,(ix+Op) ; Zahl kopieren
+ ld (ix+Copy),hl
+ ld hl,(ix+Op+2)
+ res 7,h ; dabei Vorzeichen l”schen
+ ld (ix+Copy+2),hl
+
+ ld a,'+' ; Annahme positiv
+ sll (ix+Op) ; Vorzeichen herausschieben
+ rl (ix+Op+1) ; und in Carry bringen
+ rl (ix+Op+2)
+ rl (ix+Op+3)
+ jr c,IsNeg ; Minuszeichen immer erforderlich
+ bit 0,(ix+Format+1) ; Pluszeichen dagegen optional
+ jr nz,NoMantSgn
+ jr WrMantSgn
+IsNeg: ld a,'-' ; negative Zahl
+WrMantSgn: ld (iy),a ; Vorzeichen ablegen
+ inc iy
+NoMantSgn:
+ ld l,(ix+Op+3) ; Exponent herausholen...
+ ld h,0 ; ...auf 16 Bit erweitern...
+ ld bc,(ix+Op+1) ; ...und in Quelle l”schen
+ ld (ix+Op+2),bc
+ ld b,(ix+Op)
+ ld c,0
+ ld (ix+Op),bc
+
+ cp hl,MaxExpo ; Sonderwerte ?
+ jp z,SpecialVals ; ja-->
+
+ or hl,hl ; Zahl denormal ?
+ jr nz,IsNormal ; nein, normal weiter
+ ld a,(ix+Op+3) ; falls Mantisse Null,
+ or a,(ix+Op+2) ; nicht normalisieren
+ or a,(ix+Op+1)
+ jr z,IsNull
+Normalize: sll (ix+Op+1) ; ansonsten schieben, bis fhrende
+ rl (ix+Op+2) ; Eins da
+ rl (ix+Op+3)
+ jr c,IsNormal
+ dec hl
+ jr Normalize
+IsNormal: sub hl,Bias ; Bias abziehen
+IsNull:
+ ld b,h ; Zweierexponenten in Float wandeln
+ ld c,h
+ push bc
+ push hl
+ call fitof
+ push bc ; in Dezimalexponenten wandeln
+ push de
+ cpsh bc,Ld10
+ call fdiv
+ bit 7,b ; Zahl negativ ?
+ jr z,NoCorr
+ push bc ; dann noch eins abziehen wegen
+ push de ; unterer Gauáklammer
+ cpsh bc,One
+ call fsub
+NoCorr: push bc ; den Ausflug in Float beenden
+ push de
+ call fftoi
+ ld (ix+ExpSave),de ; Exponenten retten
+
+ ld bc,(ix+Copy+2) ; Originalzahl
+ push bc
+ ld bc,(ix+Copy)
+ push bc
+ ld hl,de ; durch die Zehnerpotenz
+ call fPot10 ; des Exponenten
+ push bc
+ push de
+ call fdiv ; teilen
+Again: ld (ix+Copy),de ; Ergebnis zwischen 1...9,999 retten
+ ld (ix+Copy+2),bc
+ push bc ; Vorkommastelle berechnen
+ push de
+ call fftoi
+ cp e,10 ; doch etwas drber ?
+ jr ult,NoRoundErr
+ ld bc,(ix+Copy+2) ; dann nocheinmal zehnteln
+ push bc
+ ld bc,(ix+Copy)
+ push bc
+ cpsh bc,Tenth
+ call fmul
+ incw (ix+ExpSave)
+ jr Again
+NoRoundErr: add e,'0' ; Vorkommastelle nach ASCII
+ ld (iy),e ; ablegen
+ inc iy
+ sub e,'0' ; wieder rckg„ngig machen
+ cp (ix+Format),0 ; gar keine Nachkommastellen ?
+ jr eq,NoComma
+ ld (iy),'.' ; Dezimalpunkt ausgeben
+ inc iy
+ push bc ; Vorkomma nach Float wandeln
+ push de
+ call fitof
+ push bc
+ push de
+ cpsh bc,ix+Copy ; von alter Zahl abziehen
+ call fsub
+ xor b,80h ; war verkehrtherum
+ push bc ; zum Skalieren auf Stack
+ push de
+ ld l,(ix+Format) ; passende Skalierungskonstante ausrechnen
+ ld h,0
+ call fPot10
+ push bc
+ push de
+ call fmul ; hochskalieren
+ push bc ; Rundung
+ push de
+ cpsh bc,Half
+ call fadd
+ push bc ; Stellen nach Integer
+ push de
+ call fftoi
+ push bc ; entspr. ausgeben
+ push de
+ ld b,(ix+Format) ; Format fr fOutDec aufbauen
+ set 7,b ; kein Pluszeichen
+ ld c,'0' ; Fllzeichen Nullen
+ push bc
+ call fOutDec
+ bit 5,(ix+Format+1) ; Nullen am Ende abr„umen ?
+ jr nz,CleanZeros
+NoComma:
+ ld a,(ix+Format+1) ; falls Minimalstellenzahl Exponent=0
+ and a,00011100b ; und Exponent=0, vergessen
+ or a,(ix+ExpSave)
+ or a,(ix+ExpSave+1)
+ jr z,End
+
+ ld (iy),'E' ; Exponenten ausgeben
+ inc iy
+ ld hl,(ix+ExpSave)
+ ld b,h
+ ld c,h
+ push bc
+ push hl
+ ld c,'0' ; evtl. vornullen
+ ld b,(ix+Format+1)
+ rrc b ; Bit 1-->Bit 7
+ rrc b
+ and b,87h
+ push bc
+ call fOutDec
+
+End: ld (iy),0 ; NUL-Zeichen als Terminierer
+ ld de,iy ; Endezeiger nach DE
+ pop hl ; Register zurck
+ pop iy
+ ex de,hl ; zur Subtraktion tauschen
+ sub hl,de ; = Zahl geschriebener Zeichen
+ ex de,hl ; HL wieder original
+ ld bc,de ; Ergebnis nach BC
+ pop de
+ pop af
+
+ unlk ix ; Stackrahmen abbauen
+ retd 8 ; Ende
+
+SpecialVals: ld a,(ix+Op+3) ; Mantisse Null ?
+ or a,(ix+Op+2)
+ or a,(ix+Op+1)
+ jr nz,IsNAN
+ ld (iy),'I' ; ja: Unendlichkeit
+ ld (iy+1),'N'
+ ld (iy+2),'F'
+ add iy,3
+ jr End
+IsNAN: ld (iy),'N' ; nein: NAN
+ ld (iy+1),'A'
+ ld (iy+2),'N'
+ add iy,3
+ jr End
+
+CleanZeros: cp (iy-1),'0' ; Null am Ende ?
+ jr nz,CleanNoZero ; nein, Ende
+ dec iy ; ja: Z„hler runter, so daá ber-
+ jr CleanZeros ; schrieben wird und neuer Versuch
+CleanNoZero: cp (iy-1),'.' ; evtl. Komma entfernbar ?
+ jr nz,Ready ; nein-->
+ dec iy ; ja: noch ein Zeichen weniger
+Ready: jrl NoComma
+
+ endp
+
+;------------------------------------------------------------------------------
+; Wandlung ASCII-->Float
+
+ proc fatof
+
+SrcAddr equ 4 ; Lage Parameter auf Stack
+ DefLocal Flags,2 ; Steuerflags
+ DefLocal Exp,2 ; Speicher Exponent
+ DefLocal Mant,4 ; Speicher fr Mantissenzwischenwert
+ DefLocal Factor,4 ; Speicher fr Zehnerpotenz
+
+ link ix,LocalSize ; Stackrahmen aufbauen
+
+ push af ; Register retten
+ push hl
+ push iy
+
+ ld iy,(ix+SrcAddr) ; Zeigeradresse laden
+ ld (ix+Flags),01h ; Phase 1 (Mantisse), noch kein Vorzeichen
+ ld (ix+Flags+1),0
+ ld bc,(Ten) ; in der Mantisse mit 10 hochmultiplizieren
+ ld (ix+Factor),bc
+ ld bc,(Ten+2)
+ ld (ix+Factor+2),bc
+ ld bc,0 ; Exponent mit 0 vorbelegen
+ ld (ix+Exp),bc
+ ld (ix+Mant),bc ; Mantisse auch
+ ld (ix+Mant+2),bc
+
+ReadLoop: ld a,(iy) ; ein neues Zeichen holen
+ inc iy
+
+ cp a,0 ; Endezeichen ?
+ jp eq,Combine ; ja, zusammenbauen
+
+ cp a,' ' ; Leerzeichen ignorieren
+ jr eq,ReadLoop
+
+ cp a,'+' ; Pluszeichen gnadenhalber zulassen
+ jr ne,NoPlus ; ist aber nur ein Dummy
+ bit 0,(ix+Flags+1) ; schon ein Vorzeichen dagewesen ?
+ jp nz,Error ; dann Fehler
+ set 0,(ix+Flags+1) ; ansonsten einfach setzen
+ jr ReadLoop
+NoPlus:
+ cp a,'-' ; Minuszeichen bewirkt schon eher etwas
+ jr ne,NoMinus
+ bit 0,(ix+Flags+1) ; darf auch nur einmal auftreten
+ jp nz,Error
+ set 0,(ix+Flags+1)
+ cp (ix+Flags),1 ; je nach Phase anderes Flag setzen
+ jr ne,MinPhase3
+ set 1,(ix+Flags+1) ; bei Mantisse Bit 1...
+ jr ReadLoop
+MinPhase3: set 2,(ix+Flags+1) ; ...bei Exponent Bit 2
+ jr ReadLoop
+NoMinus:
+ cp a,'.' ; Umschaltung Phase 2 (Nachkomma) ?
+ jr ne,NoPoint
+ cp (ix+Flags),1 ; bish. Phase muá Eins sein
+ jp ne,Error
+ ld (ix+Flags),2 ; neue Phase eintragen
+ set 0,(ix+Flags+1) ; Nachkomma darf kein Vorzeichen haben
+ ld bc,(Tenth) ; im Nachkomma durch 10 teilen
+ ld (ix+Factor),bc
+ ld bc,(Tenth+2)
+ ld (ix+Factor+2),bc
+ jr ReadLoop
+NoPoint:
+ cp a,'e' ; kleines & groáes E zulassen
+ jr eq,IsE
+ cp a,'E'
+ jr ne,NoE
+IsE: cp (ix+Flags),3 ; vorh. Phase muá 1 oder 2 sein
+ jp eq,Error
+ ld (ix+Flags),3 ; vermerken
+ res 0,(ix+Flags+1) ; Vorzeichen wieder zulassen
+ jr ReadLoop
+NoE:
+ sub a,'0' ; jetzt nur noch 0..9 zugelassen
+ jp c,Error
+ cp a,9
+ jp ugt,Error
+ set 0,(ix+Flags+1) ; nach Ziffern keine Vorzeichen mehr zulassen
+
+ cp (ix+Flags),1 ; Phase 1 (Mantisse) :
+ jr ne,NoPhase1
+ cpsh bc,ix+Mant ; bish. Mantisse * 10
+ cpsh bc,ix+Factor
+ call fmul
+ push bc ; Ziffer dazuaddieren
+ push de
+ ld e,a
+ ld d,0
+ ld bc,0
+ push bc
+ push de
+ call fitof
+ push bc
+ push de
+ call fadd
+ ld (ix+Mant),de ; Mantisse zurcklegen
+ ld (ix+Mant+2),bc
+ jrl ReadLoop
+NoPhase1:
+ cp (ix+Flags),2 ; Phase 2 (Nachkomma) :
+ jr nz,NoPhase2
+ ld e,a ; Stelle nach Float
+ ld d,0
+ ld bc,0
+ push bc
+ push de
+ call fitof
+ push bc ; mit Zehnerpotenz skalieren
+ push de
+ cpsh bc,ix+Factor
+ call fmul
+ push bc ; zur Mantisse addieren
+ push de
+ cpsh bc,ix+Mant
+ call fadd
+ ld (ix+Mant),de ; Mantisse zurcklegen
+ ld (ix+Mant+2),bc
+ cpsh bc,ix+Factor ; Faktor * 1/10
+ cpsh bc,Tenth
+ call fmul
+ ld (ix+Factor),de
+ ld (ix+Factor+2),bc
+ jrl ReadLoop
+NoPhase2:
+ ld hl,(ix+Exp)
+ mul hl,10 ; Exponent heraufmultiplizieren
+ add a,l
+ ld l,a
+ ld a,0
+ adc h,0
+ cp hl,45 ; Minimum ist 1E-45
+ jr ugt,Error
+ ld (ix+Exp),hl
+ jrl ReadLoop
+
+Combine: ld hl,(ix+Exp)
+ bit 2,(ix+Flags+1) ; Exponent negativ ?
+ jr z,ExpPos
+ xor hl,-1
+ inc hl
+ExpPos: call fPot10 ; Zehnerpotenz des Exponenten bilden
+ push bc
+ push de
+ cpsh bc,ix+Mant ; mit Mantisse kombinieren
+ call fmul
+ bit 1,(ix+Flags+1) ; Mantisse negativ ?
+ jr z,ManPos
+ set 7,b
+ManPos: rcf ; Ende ohne Fehler
+
+End: pop iy ; Register zurck
+ pop hl
+ pop af
+
+ unlk ix ; Rahmen abbauen
+ retd 2 ; Ende
+
+Error: ld hl,iy ; rel. Zeichenposition ermitteln
+ sub hl,(ix+SrcAddr)
+ ld bc,hl
+ scf ; Ende mit Fehler
+ jr End
+
+ endp
+
+;------------------------------------------------------------------------------
+; gemeinsames Ende
+
+ endsection
+