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_fl90/asflags | 0 tests/t_fl90/cpu_time.inc | 170 +++++ tests/t_fl90/float.inc | 1601 +++++++++++++++++++++++++++++++++++++++++++++ tests/t_fl90/macros.inc | 57 ++ tests/t_fl90/mon.inc | 11 + tests/t_fl90/t_fl90.asm | 179 +++++ tests/t_fl90/t_fl90.doc | 6 + tests/t_fl90/t_fl90.ori | Bin 0 -> 5466 bytes 8 files changed, 2024 insertions(+) create mode 100644 tests/t_fl90/asflags create mode 100644 tests/t_fl90/cpu_time.inc create mode 100644 tests/t_fl90/float.inc create mode 100644 tests/t_fl90/macros.inc create mode 100644 tests/t_fl90/mon.inc create mode 100644 tests/t_fl90/t_fl90.asm create mode 100644 tests/t_fl90/t_fl90.doc create mode 100644 tests/t_fl90/t_fl90.ori (limited to 'tests/t_fl90') diff --git a/tests/t_fl90/asflags b/tests/t_fl90/asflags new file mode 100644 index 0000000..e69de29 diff --git a/tests/t_fl90/cpu_time.inc b/tests/t_fl90/cpu_time.inc new file mode 100644 index 0000000..bb23594 --- /dev/null +++ b/tests/t_fl90/cpu_time.inc @@ -0,0 +1,170 @@ +; CPU_TIME.INC +;****************************************************************************** +;* Zeitmessmodul fr TLCS 90 * +;* * +;* Originale fr den TLCS 900 von Oli(ver Sellke) * +;* Implementierung TLCS 90 von Alfred Arnold, Dezember 1993 * +;* * +;* Routine Funktion Eingabe Ausgabe Stack L„nge * +;* * +;* InitTimer Timer initialisieren ---- ---- 0 Byte 6 Byte * +;* StartTimer Timer starten ---- ---- 0 Byte 7 Byte * +;* StopTime Timer stoppen & Ausgabe ---- ---- 6 Byte 117 Byte *) * +;* * +;* *) bei hoher Aufl”sung * +;* * +;* - Die Routinen benutzen Timer 4, dieser darf nicht von der Anwendung * +;* benutzt werden!! * +;* - Die Aufl”sung kann ber das Symbol BigTime umgeschaltet werden: * +;* * +;* BigTime Aufl”sung Maximalzeit * +;* definiert 0,8 us 52,428 ms * +;* undefiniert 12,8 us 838,848 ms * +;* * +;* - Die Datei MON.INC wird fr die Einsprnge des TDBTMP90-Monitors ben”tigt.* +;* - MACROS.INC muá vorher eingebunden werden * +;* * +;****************************************************************************** + + section CPU_Time + +;------------------------------------------------------------------------------ +; Monitoreinsprungadressen laden + + include "mon.inc" + +;------------------------------------------------------------------------------ +; Timer vorinitialisieren + + proc InitTimer + ifdef BigTime + ld (T4MOD),00100010b ; nur Software-Capture, Phi16 + elseif + ld (T4MOD),00100001b ; nur Software-Capture, Phi1 + endif + set 5,(TRUN) ; Vorteiler starten + res 4,(TRUN) ; Timer steht noch + ret + endp + +;------------------------------------------------------------------------------ +; Timer starten + + proc StartTimer + set 2,(T4MOD) ; Timer l”schen + res 2,(T4MOD) + set 4,(TRUN) ; Timer starten + ret + endp + +;------------------------------------------------------------------------------ +; Timer stoppen & Wert auf Konsole ausgeben + + subproc Div24 + + ld b,16 ; A-HL : B = HL und A +DivLoop: sll l ; Divident hochschieben + rl h + rla + srl h ; fr nachher + rr l + sub a,c ; paát Divisor hinein ? + jr nc,DivOK + add a,c ; nein, zurcknehmen + scf ; ins Ergebnis 0 einschieben +DivOK: ccf ; neues Ergebnisbit + rl l ; Ergebnis in HL einschieben + rl h + djnz DivLoop + ret + + endp + + + proc StopTimer + + push af ; Register retten + push hl + push de + push bc + + res 5,(T4MOD) ; Wert im CAP1 latchen + res 4,(TRUN) ; Timer wieder anhalten + ld hl,(CAP1L) ; Wert auslesen + + ifdef BigTime + ld a,h ; groáe Periode: x128... + ld h,l + ld l,0 + srla + rr h + rr l + ld c,100 ; ...Teilen durch 100 + elseif + ld a,0 ; kleine Periode: x8... + rept 3 + sll l + rl h + rla + endm + ld c,10 ; ...Teilen durch 10 + endif + call Div24 ; Division durchfhren + ifdef BigTime ; Kommatrennung fr groáe Periode + ld a,0 + call Div24 + ld d,a ; Rest merken + endif + ld e,0 ; Zeichenz„hler nullen + ld c,10 ; Teilerfaktor konstant +InLoop: ld a,0 ; Erweiterung auf 24 Bit + call Div24 ; einmal teilen + push af ; Zeichen auf LIFO merken + inc e ; ein Zeichen mehr + or hl,hl ; noch etwas brig ? + jr nz,InLoop + ld a,5 ; Leerzeichen fr Ausrichtung + sub a,e ; Zahl berechnen + jr z,OutErg ; Nullschleife abfangen + ld b,a ; ansonsten passende Zahl Leerzeichen +BlankLoop: call BLAUS ; voranstellen + djnz BlankLoop +OutErg: ld b,e ; jetzt die Zeichen ausgeben +OutLoop: pop af + add a,'0' + call CONOUT + djnz OutLoop + ifdef BigTime ; bei groáer Aufl”sung Nachkommastellen + ld a,'.' + call CONOUT + ld l,d ; Zehner/Einerzerlegung + ld h,0 + div hl,c + add hl,'00' + ld a,l + call CONOUT + ld a,h + call CONOUT + call BLAUS + ld a,'m' + elseif + ld a,' ' + call CONOUT + ld a,'u' + endif + call CONOUT ; Ausgabe Einheit + ld a,'s' + call CONOUT + + pop bc ; Register zurck + pop de + pop hl + pop af + + ret + endp + +;------------------------------------------------------------------------------ +; gemeinsames Ende + + endsection 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 + diff --git a/tests/t_fl90/macros.inc b/tests/t_fl90/macros.inc new file mode 100644 index 0000000..d949ddc --- /dev/null +++ b/tests/t_fl90/macros.inc @@ -0,0 +1,57 @@ +; MACROS.INC +;****************************************************************************** +;* überall gebrauchte Makros * +;* * +;* Alfred Arnold, Oktober 1993 * +;****************************************************************************** + +proc macro name,{NoExpand} ; Prozedureintritt + section name + forward LocalSize ; lokal reservierter Speicher auf Stack +LocalSize eval 0 + public name +name label $ + endm + +subproc macro name,{NoExpand} ; Prozedureintritt für private Routine + section name + forward LocalSize ; lokal reservierter Speicher auf Stack +LocalSize eval 0 + public name:Parent +name label $ + endm + +endp macro name,{NoExpand} ; Prozeduraustritt +LocalSize eval 0-LocalSize ; damit man's im Listing lesen kann + endsection name + endm + +link macro reg,count,{NoExpand} ; Stack-Rahmen einrichten + push reg ; alten Basepointer retten + ld reg,sp ; neuen aufbauen + if count<>0 + add sp,count ; Platz auf Stack reservieren + endif + endm + +unlk macro reg,{NoExpand} ; Stack-Rahmen abbauen + ld sp,reg ; Speicherreservierung zurücknehmen + pop reg ; alten Basepointer zurück + endm + +retd macro dist,{NoExpand} ; Return and Deallocate + if dist<>0 + push hl ; Arbeitsregister retten + ld hl,(sp+2) ; Rücksprungadresse umkopieren + ld (sp+2+dist),hl + ld hl,(sp) ; Arbeitsregister zurück + add sp,2+dist ; Stack aufräumen + endif + ret + endm + +DefLocal macro Name,Size,{NoExpand} ; eine lokale Variable definieren +LocalSize eval LocalSize-Size ; zählt lok. reservierten Speicher +Name equ LocalSize ; liegt an neuem unteren Ende des Stackrahmens + endm + diff --git a/tests/t_fl90/mon.inc b/tests/t_fl90/mon.inc new file mode 100644 index 0000000..46e08d3 --- /dev/null +++ b/tests/t_fl90/mon.inc @@ -0,0 +1,11 @@ +MRET EQU 0080H ; RETURN TO MONITOR +CONIN EQU 0083H ; CONSOLE INPUT +COSTAT EQU 0086H ; CONSOLE STATUS +CONOUT EQU 0089H ; CONSOLE OUTPUT +TXTAUS EQU 008CH ; TEXT-OUTPUT +PSTR EQU 008FH ; STRING OUTPUT +A_ASC EQU 0092H ; CONVERT CONTENT OF A TO ASCII +HL_ASC EQU 0095H ; CONVERT CONTENT OF HL TO ASCII +BLAUS EQU 0098H ; BLANK OUTPUT +GETZEIL EQU 009BH ; READ LINE + diff --git a/tests/t_fl90/t_fl90.asm b/tests/t_fl90/t_fl90.asm new file mode 100644 index 0000000..3e53195 --- /dev/null +++ b/tests/t_fl90/t_fl90.asm @@ -0,0 +1,179 @@ +; FTEST.ASM +;****************************************************************************** +;* Testet Gleitkommabibliothek für TLCS90 * +;* * +;* Hardware: TDB-TMP90 * +;* Software: AS 1.39p5 oder höher * +;* Includes MACROS.INC, FLOAT.INC, CPU_TIME.INC * +;* * +;* Übersetzen mit AS ftest oder beiliegendem Makefile * +;* * +;****************************************************************************** + + cpu 90c141 + + org 8500h ; Startadresse User-RAM + +;------------------------------------------------------------------------------ + +CR equ 13 +LF equ 10 +Format_Tab equ 0000100000000110b ; fftoa-Format für tab. Ausgabe +Format_Min equ 0010001100000101b ; fftoa-Format für minimale Länge +; ^<+>^^<--+---> +; | | || | +; | | || +------ Maximalzahl Nachkommastellen +; | | |+---------- Mantissenpluszeichen unterdrücken +; | | +----------- Exponentenpluszeichen unterdrücken +; | +------------- Minimalstellenzahl Exponent +; +--------------- anhängende Nullen in Mantisse löschen +Format equ Format_Tab ; gewähltes fftoa-Format + +;------------------------------------------------------------------------------ +; Vorgaben + + include stddef90.inc ; Registeradressen + include macros.inc ; für Unterroutinen benötigte Makros + include mon.inc ; Einsprungadressen TDBTMP90-Monitor + + section MainProg + +;------------------------------------------------------------------------------ +; Makros zur Schreiberleichterung + +pushop macro adr,{NoExpand} ; einen Operanden auf den Stack legen + ld hl,(adr+2) + push hl + ld hl,(adr) + push hl + endm + +storeop macro {NoExpand} ; Ergebnis in Array ablegen + ld (iy),de + ld (iy+2),bc + add iy,4 + endm + +OneOp macro Msg,Operation,Op1,Op2,{Expand} ; Aufruf, Ausgabe und + call PSTR ; Zeitmessung + db Msg,0 + call StartTimer + if "OP1"<>"" + pushop Op1 + endif + if "OP2"<>"" + pushop Op2 + endif + call Operation + storeop + call StopTimer + if (("OPERATION"<>"FNOP") && ("OPERATION"<>"FFTOI")) + call PSTR + db ", Ergebnis ",0 + push bc + push de + ld hl,Format + push hl + ld hl,CharBuffer + push hl + call fftoa + call TXTAUS + endif + call PSTR + db CR,LF,0 + endm + +;------------------------------------------------------------------------------ +; Hauptroutine + + proc Main + + ld sp,Stack ; Stack reservieren + ld iy,Erg ; Zeiger auf Ergebnisfeld + call InitTimer ; Zeitmessung vorinitialisieren + + OneOp "Ladeoverhead : ",fnop,Eins,Eins + OneOp "Addition 2+Pi : ",fadd,Zwei,Pi + OneOp "Addition 100000+2 : ",fadd,Thou,Zwei + OneOp "Addition 0+1 : ",fadd,Null,Eins + OneOp "Subtraktion Pi-2 : ",fsub,Pi,Zwei + OneOp "Subtraktion 100000-1 : ",fsub,Thou,Eins + OneOp "Multiplikation 2*Pi : ",fmul,Zwei,Pi + OneOp "Division 1/Pi : ",fdiv,Eins,Pi + OneOp "Wurzel aus 2 : ",fsqrt,Zwei, + OneOp "Wurzel aus 10000 : ",fsqrt,Thou, + OneOp "Wurzel aus -1 : ",fsqrt,MinEins, + OneOp "Wandlung 1-->Float : ",fitof,IntEins, + OneOp "Wandlung 1E5-->Float : ",fitof,IntThou, + OneOp "Wandlung 1-->Int : ",fftoi,Eins, + OneOp "Wandlung 1E5-->Int : ",fftoi,Thou, + ld a,10 + OneOp "Pi*2^10 : ",fmul2,Pi, + ld a,-10 + OneOp "Pi*2^(-10) : ",fmul2,Pi, + + call PSTR + db "Eingabe: ",0 + ld hl,InpBuffer + call TXTAUS + ld hl,InpBuffer + push hl + call fatof + storeop + call PSTR + db ", Ergebnis: ",0 + push bc + push de + ld hl,Format + push hl + ld hl,CharBuffer + push hl + call fftoa + call TXTAUS + call PSTR + db 13,10,0 + + jp MRET + + endp + + proc fnop ; Dummyroutine fr Overheadmessung + + link ix,0 + unlk ix + + retd 8 + + endp + +CharBuffer: db 30 dup (?) ; Puffer fr fftoa +InpBuffer: db "-123.456E-7",0 ; Puffer fr fatof + + align 4 +Eins: dd 1.0 ; ben”tigte Konstanten +MinEins: dd -1.0 +Zwei: dd 2.0 +Pi: dd 40490fdbh ; um Vergleichsfehler durch Rundung zu + ; vermeiden +Zehn: dd 10.0 +Null: dd 0.0 +Thou: dd 100000.0 +IntEins: dd 1 +IntThou: dd 100000 +Erg: dd 40 dup (?) ; Ergebnisfeld + + align 2 ; Platz fr Stack + db 300 dup (?) +Stack: + endsection + +;------------------------------------------------------------------------------ +; ben”tigte Module + + include cpu_time.inc ; Zeitmessung + include float.inc ; Gleitkommabibliothek + +;------------------------------------------------------------------------------ + + end Main + diff --git a/tests/t_fl90/t_fl90.doc b/tests/t_fl90/t_fl90.doc new file mode 100644 index 0000000..668986f --- /dev/null +++ b/tests/t_fl90/t_fl90.doc @@ -0,0 +1,6 @@ ++------------------------ Test Application FL90 -----------------------------+ +| | +| This is an IEEE single precision floating point library for the Toshiba | +| TLCS-90 microcontroller, embedded into a small test program. | +| | ++-----------------------------------------------------------------------------+ diff --git a/tests/t_fl90/t_fl90.ori b/tests/t_fl90/t_fl90.ori new file mode 100644 index 0000000..4aff532 Binary files /dev/null and b/tests/t_fl90/t_fl90.ori differ -- cgit v1.2.3