; ******************************* ; * * ; * Fliesskomma-Arithmetik fuer * ; * den Z80-Mikroprozessor * ; * (C) 1988 by H. Voelzke * ; * * ; ******************************* ; ********************************************************* ; * Edition history ; * ; * # Date Comments by ; * ------------------------------------------------------- ; * 01 28-08-88 Adapted from 8086-Version HV ; * 02 30-08-88 f_mul adapted HV Version equ 2 .Z80 start: ld bc,3f80h ; Aufruf der Additionsroutine ld de,0000h ; mit verschiedenen Parametern push bc ; entspricht 1 + 2 push de ld bc,4000h ld de,0000h push bc push de call f_add call hexout ; anschliessend Ausgabe ld bc,00f0h ; eine kleine, gerade noch normali- ld de,0000h ; sierte Zahl, dazu die kleinste push bc ; normalisierte Zahl mit negativen push de ; Vorzeichen addieren ld bc,8080h ld de,0000h push bc push de call f_add call hexout ld bc,7f00h ; die Summe dieser beiden Zahlen ld de,0000h ; ergibt unendlich. Setzt man push bc ; fuer die zweite Zahl den Wert push de ; 7efffffe, so ist das Ergebnis ld bc,7effh ; gerade MAXFLOAT ld de,0ffffh push bc push de call f_add call hexout ld bc,0000h ; Multiplikation testen ld de,0003h ; MAXFLOAT * (denormalisierte Zahl) push bc push de ld bc,7f7fh ld de,0ffffh push bc push de call f_mul call hexout ld bc,0080h ; die kleinste normalisierte Zahl ld de,0000h ; mit 0.5 multiplizieren push bc ; (ergibt eine denormalisierte Zahl) push de ld bc,3f00h ld de,0000h push bc push de call f_mul call hexout ld bc,4000h ; eine sehr grosse Zahl mit zwei ld de,0000h ; multiplizieren. Das Ergebnis push bc ; ist genau MAXFLOAT push de ld bc,7effh ld de,0ffffh push bc push de call f_mul call hexout ld bc,0000h ; Test der Divisionsroutine ld de,0000h ; hier 1 / 0 (ergibt unendlich) push bc push de ld bc,3f80h ld de,0000h push bc push de call f_div call hexout ld bc,40e0h ; jetzt 26 / 7 berechnen ld de,0000h push bc push de ld bc,41d0h ld de,0000h push bc push de call f_div call hexout ld bc,1fffh ; jetzt eine sehr kleine ld de,0ffffh ; denormalisierte Zahl durch push bc ; eine kleine normalisierte push de ; Zahl dividieren ld bc,0000h ld de,0003h push bc push de call f_div call hexout jp 0 ; Ende des Testes, Warmstart ; ************************************************* ; * Zahl in BC-DE in 8 Hexadezimalziffern drucken. ; * Dazu werden nacheinander die Nibble-Paare in ; * B, C, D und E ausgedruckt. ; * hexout: ld a,b ; Nacheinander die einzelnen call dig2 ; Nibble-Paare in A laden ld a,c ; und ausdrucken call dig2 ld a,d call dig2 ld a,e call dig2 ld a,10 call outchar ld a,13 call outchar ret dig2: push af ; Nibble-Paar ausdrucken srl a ; unteres Nibble retten srl a ; oberes Nibble rechtsbuendig srl a ; positionieren srl a add a,'0' ; ASCII-Offset addieren cp '9'+1 ; Ziffer oder Buchstabe? jr c,nokor add a,7 ; ggf. ASCII-Differenz addieren nokor: call outchar ; Zeichen ausgeben pop af ; jetzt unteres Nibble verarbeiten and 01111b ; Nibble maskieren add a,'0' cp '9'+1 jr c,nokor2 add a, 7 nokor2: call outchar ret outchar:push bc ; Zeichen auf CON: ausgeben push de ; Register retten ld c,2 ; BDOS-Funktion Console-Output ld e,a ; Zeichen wird in E uebergeben call 5 ; BDOS-Einsprung pop de ; Register restaurieren pop bc ret ; ********************************** ; * Globale Konstanten-Definitionen ; * fuer das Fliesskommapaket ; * maxexpo equ 255 ; Maximal zulaessiger Exponent bias equ 127 ; Bias des Exponenten ; ************************************************ ; * Fliesskomma-Addition in Single-Precision ; * Parameter: Operand 1 und Operand 2 ueber Stack ; * Ergebnis: in BC-DE: MSB in B, LSB in E ; * ; * Es folgen Offset-Definitionen fuer Stack-relative Zugriffe fhl_alt equ 0 ; Top of Stack liegt HL fadr equ 2 ; dann die Ruecksprungadresse op1 equ 4 ; jetzt Offset-Definitionen fuer op2 equ 8 ; Parameter-Uebergabe opsize equ 4 ; Groesse eines Operanden f_add: push hl ; alten Basepointer retten ld (f_stack),sp ; aktuellen Stackpointer abspeichern ld hl,(f_stack) ; und in HL laden (= Basepointer) push af ; benoetigte Register retten push ix push iy ld bc,op1 ; jetzt die Zeiger auf die add hl,bc ; Operanden initialisieren push hl pop ix ; IX zeigt auf Operand 1 ld bc,opsize add hl,bc push hl pop iy ; IY Zeigt auf Operand 2 f_adsub:add hl,bc ; HL zeigt jstzt hinter die Operanden! ld (f_stack),hl ; diese Adresse fuer's Ende merken ld a,(ix+3) ; Vorzeichen von Operand 1 laden ld e,a ; Ergebnisvorzeichen in E, Bit 7 xor (iy+3) ; mit Vorzeichen von OP2 verknuepfen ld d,a ; Subtraktlonsflag in D, Bit 7 res 7,(ix+3) ; Vorzeichen in Mantisse 1 loeschen res 7,(iy+3) ; Vorzeichen in Hantisse 2 loeschen ; Die Operanden sind jetzt in der Form: 0eee eeee efff ... ffff ld a,(ix+0) ; Differenz OP1 - OP2 bilden sub (iy+0) ld a,(ix+1) sbc a,(iy+1) ld a,(ix+2) sbc a,(iy+2) ld a,(ix+3) sbc a,(iy+3) jr nc,fad_1 ; Sprung falls OPI groesser als OP2 push ix ; ansonsten Operanden vertauschen ex (sp),iy ; (eigentlich nur die Pointer), so pop ix ; dass IY den kleineren adressiert ld a,e ; Ergebnisvorzeichen neu berechnen xor d ld e,a fad_1: ld a,(ix+2) ld c,(ix+3) ; Exponent der groesseren Zahl laden sla a rl c jr z,ad_dn1 set 7,(ix+2) ; implizite Eins erzeugen ad_dn1: ld a,(iy+2) ld b,(iy+3) ; Exponent der kleineren Zahl laden sla a rl b jr z,ad_dn2 set 7,(iy+2) ; implizite Eins erzeugen ad_dn2: push bc ; Jetzt die Register fuer den push de ; Blocktransferbefehl retten ld bc,opsize+opsize-1 ; beide Operanden verschieben dec hl ; HL zeigt auf letztes Byte push hl ; HL nach DE kopieren pop de dec hl ; HL zeigt auf vorletztes Byte lddr ; Verschiebung beider Mantissen pop de ; um 8 Bit nach links pop bc xor a ld (ix+0),a ; Form ffff ... ffff 0000 0000 ld (iy+0),a ld a,c ; Differenz der Exponenten berechnen sub b ld b,a ; Differenz nach B fuer Loop-Befehl jr z,ad_nap ; falls Null, dann keine Anpassung cp 25 ; mehr als 24? (Abfragt mit Carry jp nc,ad_rnd ; erfordert Vergleich mit 25) ad_anp: srl (iy+3) ; Anpassung der zweiten Mantisse rr (iy+2) ; durch Verschiebung nach rechts rr (iy+1) rr (iy+0) djnz ad_anp ; Loop-Befehl bis B = 0 ad_nap: bit 7,d ; Subtraktion oder Addition? jr nz,subtr ; ggf. zur Subtraktion springen ld a,(ix+0) ; jetzt werden die beiden Mantissen add a,(iy+0) ; zueinander addiert ld (ix+0),a ld a,(ix+1) adc a,(iy+1) ld (ix+1),a ld a,(ix+2) adc a,(iy+2) ld (ix+2),a ld a,(ix+3) adc a,(iy+3) ld (ix+3),a jr nc,ad_rnd ; kein Ueberlauf --> zum Runden rr (ix+3) ; Ueberlauf einschieben rr (ix+2) ; und Exponent erhoehen rr (ix+1) ; durch die Vorgeschichte ist rr (ix+0) ; gesichert, dass B Null ist; BC inc bc ; enthaelt den 16-Bit-Exponent jr ad_rnd ; und zum Runden subtr: ld a,(ix+0) ; Die beiden Mantissen werden sub (iy+0) ; voneinander subtrahiert ld (ix+0),a ld a,(ix+1) sbc a,(iy+1) ld (ix+1),a ld a,(ix+2) sbc a,(iy+2) ld (ix+2),a ld a,(ix+3) sbc a,(iy+3) ld (ix+3),a jp m,ad_rnd ; bei fuehrender Eins zum Runden jr nz,ad_nrm ; ungleich Null: Normalisieren cp (ix+2) ; Rest der Mantisse auch Null? jr nz,ad_nrm cp (ix+1) jr nz,ad_nrm cp (ix+0) jr z,ad_zero ; alles Null --> Ergebnis ist Null ad_nrm: xor a ; A = 0 ad_nr1: cp c ; Exponent ist Null? jr nz,ad_nr2 ; nein, Normierung moeglich cp b ; oberes Byte auch Null? jr z,ad_rnd ; dann ist Ergebnis denormalisiert ad_nr2: dec bc ; Exponent erniedrigen sla (ix+0) ; Mantisse normalisieren bis rl (ix+1) ; fuehrende Eins auftaucht rl (ix+2) rl (ix+3) jp p,ad_nr1 ; weiter bis fuehrende Eins auftaucht ad_rnd: ld a,(ix+0) ; jetzt Runden auf Bit hinter add a,080h ; Mantisse jr nc,ad_nov ; kein Uebertrag? inc (ix+1) ; doch, naechstes Mantissenbyte jr nz,ad_nov ; behandeln, jetzt auf Null pruefen, inc (ix+2) ; da der INC-Befehl kein Carry liefert jr nz,ad_nov inc (ix+3) jr nz,ad_nov scf ; Eins erzeugen rr (ix+3) ; bei Ueberlauf Mantisse durch rr (ix+2) ; Rechtsschieben wieder normalisieren rr (ix+1) ; (nur noch 24 Bit noetig) inc bc ; und Exponent korrigieren ad_nov: xor a ; A = 0 cp (ix+3) ; Mantisse auf Null pruefen jr nz,ad_noz cp (ix+2) jr nz,ad_noz cp (ix+1) ; alle Mantissenbytes Null? jr nz,ad_noz ; dann ist auch das Ergebnis Null ad_zero:ld b,a ; Null-Ergebnis aufbauen ld c,a ld d,a ld e,a jr ad_exit ; dann Routine verlassen ad_noz: cp b ; A ist 0 ld a,maxexpo ; Exponent oberes Byte ungleich Null? jr nz,ad_ovr ; dann idt Ueberlauf eingetreten cp c ; oder genau maxexpo erreicht? jr nz,ad_num ; nein, --> kein Ueberlauf ad_ovr: ld c,a ; Exponent auf maxexpo setzen xor a ; und Mantisse auf Null ld (ix+3),a ; fuer unendlich ld (ix+2),a ld (ix+1),a jr ad_den ad_num: xor a ; A = 0 cp c ; Exponent Null (Zahl denotmalisiert?) jr z,ad_den ; ja, --> sla (ix+1) ; fuehrendes Bit wird nicht gespeichert rl (ix+2) ; daher Mantisse um 1 Bit nach links rl (ix+3) ad_den: ld b,c ; Ergebnisaufbauen: Exponent in B ld c,(ix+3) ; Mantisse oberstes Byte ld d,(ix+2) sla e ; Vorzeichen aus E in Carry schieben ld e,(ix+1) rr b ; Vorzeichen in Ergebnis einschieben rr c rr d rr e ad_exit:pop iy ; Register restaurieren pop ix pop af pop hl ld (f_hl),hl ; HL zwischenspeichern ex (sp),hl ; alte Ruecksprungadresse in HL ld sp,(f_stack) ; Stack zuruecksetzen push hl ; Ruecksprungadresse ablegen ld hl,(f_hl) ; HL wieder laden ret ; Ende des Unterprogrammes ; ************************************************ ; * Fliesskomma-Subtraktion in Single Precision ; * Parameter: Operand 1 und Operand 2 ueber Stack ; * Ergebnis: in BC-DE: MSB in B, LSB in E ; * f_sub: push hl ; alten Basepointer retten ld (f_stack),sp ; aktuellen Stackpointer abspeichern ld hl,(f_stack) ; und in HL laden (= Basepointer) push af ; benoetigte Register retten push ix push iy ld bc,op1 add hl,bc push hl pop ix ; IX zeigt auf Operand 1 ld bc,opsize add hl,bc push hl pop iy ; IY Zeigt auf Operand 2 ld a,080h xor (iy+3) ; Vorzeichenbit von Operand 2 umdrehen ld (iy+3),a ; wieder abspeichern jp f_adsub ; jetzt weiter bei Additionsroutine ; ************************************************ ; * Fliesskomma-Multiplikation in Single Precision ; * Parameter: Operand 1 und Operand 2 ueber Stack ; * Ergebnis: in BC-DE: MSB in B, LSB in E ; * temp equ -10 ; Offset lokale Variable (6 Byte) f_mul: push hl ; alten Basepointer retten ld (f_stack),sp ; aktuellen Stackpointer abspeichern ld hl,(f_stack) ; und in HL laden (= Basepointer) push af ; benoetigte Register retten push ix push iy ld bc,op1 add hl,bc push hl ex (sp),ix ; IX zeigt auf Operand 1 ; 2 Dummy-Byte auf Stack fuer lokale ld bc,opsize ; Variable bleiben stehen add hl,bc push hl ex (sp),iy ; IY zeigt auf Operand 2 push hl ; insgesamt 6 Byte fuer lokale Variable add hl,bc ; HL zeigt jetzt hinter die Operanden! ld (f_stack),hl ld a,(ix+3) ; Ergebnisvorzeichen bestimmen xor (iy+3) ld c,a ; Vorzeichen in C Bit 7 merken ld d,0 ; Exponent 1 laden ld e,(ix+3) ld a,(ix+2) ; Operand um 8 Bit nach links schieben ld (ix+3),a res 7,(ix+3) ; implizite Null vorbesetzen sla a ; Exponent unterstes Bit in Carry rl e ; und in E einschieben jr z,mu_dn1 ; falls Null, dann Op1 denormalisiert set 7,(ix+3) ; implizite Eins erzeugen dec de ; Bias kompensieren mu_dn1: ld a,(ix+1) ; jetzt restliche Bytes verschieben ld (ix+2),a ld a,(ix+0) ld (ix+1),a xor a ; unterste Mantissenbits loeschen ld (ix+0),a ; Form: ffff ... ffff 0000 0000 ld (ix+temp+5),a ; lokale Variable mit Null vorbesetzen ld (ix+temp+4),a ld (ix+temp+3),a ld (ix+temp+2),a ld (ix+temp+1),a ld (ix+temp+0),a ld h,a ; Exponent 2 in HL aufbauen ld l,(iy+3) ld a,(iy+2) res 7,(iy+2) ; implizite Null Vorbesetzen sla a rl l jr z,mu_dn2 ; gleich Null, dann Op2 denormalisiert set 7,(iy+2) ; implizite Eins erzeugen dec hl ; Bias kompensieren mu_dn2: add hl,de ; Exponenten aufaddieren ld de,3-bias ; Bias-3 subtrahieren add hl,de ; bzw. 3-Bias addieren jp p,mu_noz ld a,l ; Exponent kleiner als -24? cp -24 jr nc,mu_noz jp mu_zero ; ja, dann ist das Ergebnis Null mu_noz: ld b,24 ; Multiplikationsschleifenzaehler ld de,0 ; Hilfsregister fuer Multiplikand mu_mul: srl (ix+3) ; Multiplikand nach rechts schieben rr (ix+2) rr (ix+1) rr (ix+0) rr d ; DE als Verlaengerung von Operand 1 rr e sla (iy+0) ; Multiplikator nach links schieben rl (iy+1) rl (iy+2) ; falls fuehrende Bit Null ist, dann jr nc,mu_nad ; muss nicht addiert werden ld a,(ix+temp+0) ; sonst Multiplikand aufaddieren add a,e ld (ix+temp+0),a ld a,(ix+temp+1) adc a,d ld (ix+temp+1),a ld a,(ix+temp+2) adc a,(ix+0) ld (ix+temp+2),a ld a,(ix+temp+3) adc a,(ix+1) ld (ix+temp+3),a ld a,(ix+temp+4) adc a,(ix+2) ld (ix+temp+4),a ld a,(ix+temp+5) adc a,(ix+3) ld (ix+temp+5),a mu_nad: djnz mu_mul ; Schleife durchlaufen ld a,(ix+temp+5) or a ; Flags setzen jp m,mu_rnd ; bei fuehrender Eins zum Runden jr nz,mu_nor ; ungleich Null --> normalisieren cp (ix+temp+4) jr nz,mu_nor cp (ix+temp+3) jr nz,mu_nor cp (ix+temp+2) jr nz,mu_nor jp mu_zero ; Mantisse konplett Null --> Null mu_nor: xor a ; A = 0 or h ; Exponent ist negativ? jp m,mu_unt ; ggf. Unterlauf behandeln mu_nr1: xor a ; A = 0 cp l ; Exponent = Null? jr nz,mu_nr2 cp h ; bei Null zum Runden jr z,mu_rnd mu_nr2: dec hl ; Exponent erniedrigen sla (ix+temp+0) rl (ix+temp+1) rl (ix+temp+2) ; Mantisse solange nach links rl (ix+temp+3) ; verschieben bis fuehrende Eins rl (ix+temp+4) ; auftaucht rl (ix+temp+5) jp p,mu_nr1 mu_rnd: ld a,(ix+temp+2) ; jetzt Runden auf Bit hinter add a,080h ; Mantisse jr nc,mu_nov ; kein Uebertrag? inc (ix+temp+3) ; doch, naechstes Mantissenbyte jr nz,mu_nov ; behandeln, jetzt auf Null pruefen inc (ix+temp+4) ; da der INC-Befehl kein Carry liefert jr nz,mu_nov inc (ix+temp+5) jr nz,mu_nov scf ; Eins erzeugen rr (ix+temp+5) ; bei Ueberlauf Mantisse durch rr (ix+temp+4) ; Rechtsschieben wieder normalisieren rr (ix+temp+3) inc hl ; und Exponent korrigieren mu_nov: xor a ; A = 0 cp h ; Exponent pruefen ld a,maxexpo ; A vorbesetzen jr nz,mu_ovr ; groesser Null: Ueberlauf behandeln cp l ; oder genau maxexpo erreicht? jr nz,mu_nue ; nein, kein Ueberlauf mu_ovr: ld l,maxexpo ; Ueberlauf: Exponent = maxexpo xor a ; Mantisse = Null ld (ix+temp+5),a ld (ix+temp+4),a ld (ix+temp+3),a jr mu_den mu_nue: xor a ; A = 0 cp l ; Exponent ist Null? jr z,mu_den ; ja, Ergebnis ist denormalisiert sla (ix+temp+3) ; nein, fuehrendes Mantissenbit rl (ix+temp+4) ; rausschieben rl (ix+temp+5) mu_den: 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 ; Form: seee eeee efff ... ffff rr e mu_res: pop hl ; lokale Variable deallozieren pop hl pop hl pop iy ; Register restaurieren pop ix pop af pop hl ld (f_hl),hl ; Parameter vom Stack deallozieren ex (sp),hl ld sp,(f_stack) push hl ld hl,(f_hl) ret ; und return mu_zero:xor a ; Ergebnis ist Null ld b,a ld c,a ld d,a ld e,a jr mu_res mu_unt: ld a,l ; Exponent in A neg ; negieren fuer Schleifenzaehler cp 24 ; totaler Unterlauf? jr nc,mu_zero ; ja, dann ist Ergebnis Null ld b,a ; In B fuer Loop mu_shr: srl (ix+temp+5) ; Mantisse denormalisieren rr (ix+temp+4) ; bis Exponent Null ist rr (ix+temp+3) djnz mu_shr ld l,b ; Exponent in Register L = B = 0 jp mu_den ; denormalisiertes Ergebnis erzeugen ; ************************************************ ; * Fliesskomma-Division in Single-Precision ; * Parameter: Operand 1 und Operand 2 ueber Stack ; * Ergebnis: in BC-DE: MSB in B, LSB in E ; * f_div: push hl ; alten Basepointer retten ld (f_stack),sp ; aktuellen Stackpointer abspeichern ld hl,(f_stack) ; und in HL laden (= Basepointer) push af ; benoetigte Register retten push ix push iy ld bc,op1 add hl,bc push hl ex (sp),ix ; IX zeigt auf Operand 1 ; 2 Dummy-Byte auf Stack fuer lokale ld bc,opsize ; Variable bleiben stehen add hl,bc push hl ex (sp),iy ; IY zeigt auf Operand 2 push hl ; insgesamt 6 Byte fuer lokale Variable add hl,bc ; HL zeigt jetzt hinter die Operanden! ld (f_stack),hl ld a,(ix+3) ; Ergebnissvorzeichen bestimmen xor (iy+3) ld c,a ; Vorzeichen in C Bit 7 merken ld h,0 ; Exponent 1 laden ld l,(ix+3) ld a,(ix+2) res 7,(ix+2) ; implizite Null vorbesetzen sla a ; Exponent unterstes Bit in Carry rl l ; und in E einschieben jr z,dv_dn1 ; falls Null, dann Op1 denormalisiert set 7,(ix+2) ; implizite Eins erzeugen dec hl ; Bias kompensieren dv_dn1: ld d,0 ; Exponent 2 in DE aufbauen ld e,(iy+3) ld a,(iy+2) ld (iy+3),a ; Mantisse um 8 Bit verschieben res 7,(iy+3) ; implizite Null Vorbestzen sla a rl e jr z,dv_dn2 ; gleich Null, dann Op2 denormalisiert set 7,(iy+3) ; implizite Eins erzeugen dec de ; Bias kompensieren dv_dn2: ld a,(iy+1) ; jetzt restliche Bytes verschieben ld (iy+2),a ld a,(iy+0) ld (iy+1),a xor a ; A = 0 ld (iy+0),a ; Form: ffff ... ffff 0000 0000 srl (iy+3) rr (iy+2) rr (iy+1) rr (iy+0) ; Form: 0fff ... ffff f000 0000 jr nz,dv_nz1 ; Mantisse 2 auf Null pruefen cp (iy+1) jr nz,dv_nz1 cp (iy+2) jr nz,dv_nz1 cp (iy+3) jr nz,dv_nz1 jp mu_ovr ; Bei Division durch Null: Unendlich dv_nz1: xor a ; Carry-Flag loeschen sbc hl,de ; Exponenten subtrahieren ld de,bias ; Bias addieren add hl,de bit 7,h ; Exponent positiv? jr z,dv_noz ld a,l ; Exponent kleiner als -24? cp -24 jr nc,dv_noz jp mu_zero ; ja, dann ist das Ergebnis Null dv_noz: push bc ; Vorzeichen retten ld de,25 ; Exponent um 25 erhoehen add hl,de ; jetzt ist er sicher groesser als Null xor a ; A = 0 ld b,(ix+2) ; Dividend im Register kopieren ld c,(ix+1) ld d,(ix+0) ld e,a ; die untersten Bits sind Null cp d ; ist Dividend Null? jr nz,dv_nz2 cp c jr nz,dv_nz2 cp b jr nz,dv_nz2 pop bc ; Stack bereinigen (Vorzeichen laden) jp mu_zero ; und Null als Ergebnis ausgeben dv_nz2: ld (ix+temp+5),a ; Ergebnis vorbesetzen ld (ix+temp+4),a ld (ix+temp+3),a ld (ix+temp+2),a dv_nlp: bit 6,(iy+3) ; ist der Divisor normalisiert? jr nz,dv_nor ; ja,--> inc hl ; nein, Exponent erhoehen sla (iy+0) ; Divisor verschieben bis in rl (iy+1) ; Form 01ff ... rl (iy+2) rl (iy+3) jr dv_nlp dv_nor: srl b rr c rr d rr e ; Form: 0fff ... ffff f000 0000 dv_lop: ld (ix+3),b ; Dividend zwischenspeichern ld (ix+2),c ; die Speicherplaetze von Op1 ld (ix+1),d ; stehen zur Verfuegung, da wir Op1 ld (ix+0),e ; in die Register BC-DE kopiert haben ld a,e ; jetzt Divisor abziehen sub (iy+0) ld e,a ld a,d sbc a,(iy+1) ld d,a ld a,c sbc a,(iy+2) ld c,a ld a,b sbc a,(iy+3) ld b,a jr nc,dv_one ; kein Carry: Divisor passt ld e,(ix+0) ; zurueckkopieren ld d,(ix+1) ; Carry bleibt dabei erhalten! ld c,(ix+2) ld b,(ix+3) dv_one: ccf ; Carry-Flag umkehren rl (ix+temp+2) ; Ergebnis aufbauen rl (ix+temp+3) rl (ix+temp+4) rl (ix+temp+5) sla e ; Dividend verschieben rl d rl c rl b dec hl ; Exponent erniedrigen xor a ; A = 0 cp l ; Exponent = Null? jr nz,dv_div cp h jr z,dv_den ; falls Null, dann denormalisiert dv_div: bit 0,(ix+temp+5) ; fuehrende Eine in Ergebns-Mantisse? jr z,dv_lop ; nein, weiter rechnen dv_den: ld b,(ix+temp+5) ; hoechstes Bit merken ld a,(ix+temp+4) ld (ix+temp+5),a ; Mantisse in Form ld a,(ix+temp+3) ; ffff ... ffff 0000 0000 ld (ix+temp+4),a ld a,(ix+temp+2) ld (ix+temp+3),a rr b ; hoechstes Bit einschieben rr (ix+temp+5) rr (ix+temp+4) rr (ix+temp+3) ; Form ffff ... ffff f000 0000 rr (ix+temp+2) pop bc ; Vorzeichen wieder laden xor a ; A = 0 cp (ix+temp+5) ; Mantisse ist Null? jr nz,dv_nz3 cp (ix+temp+4) jr nz,dv_nz3 cp (ix+temp+3) jr nz,dv_nz3 cp (ix+temp+2) jp z,mu_zero ; dann ist Ergebnis auch Null dv_nz3: jp mu_rnd ; sonst weiter wie bei Multiplikation f_stack:ds 2 ; Hilfspeicher fuer Stackpointer f_hl: ds 2 ; Hilfspeicher fuer Basepointer HL end start