
; Routinen zum Konvertieren von FFP-Fließkommazahlen in ASCII und umgekehrt.  Compress-Tab 8.









; FFP =	afp (Stringzeiger)
; Wandelt einen	ASCII-String in	eine FFP-Fließkommazahl	um.  Rückgabe in D0.

	IFD	afp_c

	XDEF	_afp

	XREF	FFPAFP

_afp_REG	REG	d1-d7/a0-a6
REGISTER	SET	14

_afp
	movem.l	_afp_REG,-(SP)
	move.l	REGISTER*4+4(SP),a0	; Stringzeiger
	jsr	FFPAFP
	move.l	d7,d0			; Rückgabewert
	movem.l	(SP)+,_afp_REG
	rts

	ENDC










; FFPAFP
; Assemblerversion von _afp.
; Eingabe:	A0 zeigt auf den umzuwandelnden	ASCII-String.
; Ausgabe:	D7 und D0 enthalten die	FFP-Fließkommazahl.
;		A0 zeigt direkt	hinter den gelesenen ASCII-String.
;		Falls ein Fehler auftrat, ist das Carry-Flag gesetzt, und A0
;		zeigt auf die Fehlerstelle.

; Der String muß die Form haben:
;	[+|-]{x}.xxxx[(e|E)[+|-]x{x}]
;	[+|-]x{x}[(e|E)[+|-]x{x}]

	IFD	afp_a

	INCLUDE	"lvo/math.i"

	XDEF	FFPAFP

	XREF	_MathBase

FFPAFP
	; Initialisiere	ein paar Werte.
	move.l	a0,a5			; benutze A5 als Quellzeiger
	moveq	#0,d7			; Zahl
	moveq	#0,d6			; Zeichen
	move.l	_MathBase,a6		; Library-Basis

	; Gibt es ein Vorzeichen ?
	move.b	(a5)+,d6		; hole Zeichen
	cmp.b	#'-',d6			; Minus	?
	seq	d5			; ja, setze Vorzeichenflag
	beq.s	1$			; ja, neues Zeichen holen
	cmp.b	#'+',d6			; Plus ?
	bne.s	2$			; nein,	dann Vorzeichen	beendet
1$	move.b	(a5)+,d6		; hole Zeichen
	bra.s	2$



	; Solange Dezimalziffern (vor dem Komma) kommen, multipliziere die
	; Zahl mit zehn	und addiere die	Ziffer.
4$	move.l	d7,d0			; FFP-Zahl
	move.l	#$A0000044,d1		; mal 10
	jsr	_LVOSPMul(a6)
	bvs	AFPOverflow		; wenn Überlauf
	move.l	d0,d7
	move.l	d6,d0
	sub.b	#'0',d0			; ergibt Integerzahl der Ziffer
	jsr	_LVOSPFlt(a6)		; wandele in FFP um
	move.l	d7,d1
	jsr	_LVOSPAdd(a6)		; addiere die Ziffer zur Zahl
	bvs	AFPOverflow		; wenn Überlauf
	move.l	d0,d7
	move.b	(a5)+,d6		; hole Zeichen
2$	cmp.b	#'0',d6
	blo.s	3$
	cmp.b	#'9',d6
	bls.s	4$			; wenn weitermachen



	; Jetzt	folgt ein Punkt	mit Nachkommastellen oder der Exponent.
3$	cmp.b	#'.',d6			; folgt	Punkt ?
	bne.s	AFPNoDot		; nein
	move.l	#$CCCCCD3D,d4		; beginne mit 0.1
	bra.s	5$

	; Addiere Nachkommastellen.
6$	move.l	d6,d0
	sub.b	#'0',d0			; ergibt Integerzahl der Ziffer
	jsr	_LVOSPFlt(a6)		; wandele in FFP um
	move.l	d4,d1
	jsr	_LVOSPMul(a6)
	move.l	d7,d1
	jsr	_LVOSPAdd(a6)		; addiere die Ziffer zur Zahl
	bvs	AFPOverflow		; wenn Überlauf
	move.l	d0,d7
	move.l	d4,d0
	move.l	#$CCCCCD3D,d1		; mal 0.1
	jsr	_LVOSPMul(a6)
	beq.s	AFPNoDot		; wenn Stellen nicht mehr signifikant
	move.l	d0,d4
5$	move.b	(a5)+,d6		; hole Zeichen
	cmp.b	#'0',d6
	blo.s	AFPNoDot
	cmp.b	#'9',d6
	bls.s	6$			; wenn weitermachen



AFPNoDot
	; Jetzt	kann der Exponent folgen.
	bclr	#5,d6			; wandele in Großbuchstaben
	cmp.b	#'E',d6			; kommt	jetzt Exponent ?
	bne.s	AFPEnd			; nein,	Ende

	; Gibt es ein Exponentenvorzeichen ?
	swap	d5			; rette	Vorzeichenflag
	move.b	(a5)+,d6		; hole Zeichen
	cmp.b	#'-',d6			; Minus	?
	seq	d5			; ja, setze Flag
	beq.s	1$			; und hole neues Zeichen
	cmp.b	#'+',d6			; Plus ?
	bne.s	2$			; nein,	dann Vorzeichen	beendet
1$	move.b	(a5)+,d6		; hole Zeichen


	; Lies den Exponenten maximal vierstellig.  Bei	zu vielen Stellen
	; gibt es automatisch einen Überlauf.
2$	moveq	#4-1,d0
	moveq	#0,d3			; Exponentenzahl
	cmp.b	#'9',d6			; Dezimalziffer	?
	bhi.s	AFPOverflow		; nein,	Fehler
	cmp.b	#'0',d6
	blo.s	AFPOverflow		; nein,	Fehler

4$	mulu	#10,d3
	sub.b	#'0',d6
	add	d6,d3
	move.b	(a5)+,d6
	cmp.b	#'0',d6
	blo.s	3$			; wenn Ende
	cmp.b	#'9',d6
	bhi.s	3$			; wenn Ende
	dbra	d0,4$


	; Der Exponent ist zu Ende.  Ermittle den Exponentenfaktor.
3$	move.l	#$80000041,d0		; beginne mit 1.0
	move.l	#$A0000044,d4		; vorerst Faktor 10.0
	swap	d5
	btst	#16,d5			; negativer Exponent ?
	beq.s	5$
	move.l	#$CCCCCD3D,d4		; ja, dann Faktor 0.1
	bra.s	5$

6$	move.l	d4,d1			; Faktor
	jsr	_LVOSPMul(a6)
	bvs.s	AFPOverflow		; wenn Überlauf
5$	dbra	d3,6$


	; Multipliziere	den Exponenten hinein.
	move.l	d7,d1
	jsr	_LVOSPMul(a6)
	bvs.s	AFPOverflow		; wenn Überlauf
	move.l	d0,d7


AFPEnd
	; Soll die FFP-Zahl negativ sein ?
	move.l	d7,d0
	tst.b	d5
	beq.s	1$			; nein
	jsr	_LVOSPNeg(a6)		; ja, negiere Zahl
	move.l	d0,d7
1$	subq	#1,a5			; stelle Zeiger	zurück
	move.l	a5,a0
	andi	#~1,CCR			; lösche das Carry-Flag
	rts



AFPOverflow
	; Es kam ein Überlauf vor.
	subq	#1,a5			; zeigt	jetzt auf Fehlerstelle
	move.l	a5,a0
	ori	#1,CCR			; setze	das Carry-Flag
	rts

	ENDC










; Exponent = fpa (FFP-Zahl, Stringzeiger)
; Wandelt eine FFP-Fließkommazahl in einen ASCII-String	um.

	IFD	fpa_c

	XDEF	_fpa

	XREF	FFPFPA

_fpa_REG	REG	d1-d7/a0-a6
REGISTER	SET	14

_fpa
	movem.l	_fpa_REG,-(SP)
	movem.l	REGISTER*4+4(SP),d0/a0
	jsr	FFPFPA			; Exponent in D0 zurück
	movem.l	(SP)+,_fpa_REG
	rts

	ENDC










; FFPFPA
; Assemblerversion von _fpa.
; Eingabe:	D0 enthält die FFP-Fließkommazahl.
;		A0 zeigt auf den Zielstring.
; Ausgabe:	D0 enthält den Exponenten als vorzeichenbehafteten 32-Bit-Integer.

	IFD	fpa_a

	INCLUDE	"lvo/math.i"

	XDEF	FFPFPA

	XREF	_MathBase

FFPFPA
	; Initialisiere.
	move.l	a0,a5			; Zielzeiger
	move.l	d0,d7			; FFP-Zahl
	move.l	_MathBase,a6		; Library-Basis

	; Ist die Zahl negativ ?
	moveq	#0,d6			; Exponent
	bclr	#7,d7
	beq.s	1$
	move.b	#'-',(a5)+		; ja, stelle Minus davor
	bra.s	1$

	; Ziehe	den negativen Exponenten.
3$	move.l	d7,d0
	move.l	#$A0000044,d1
	jsr	_LVOSPMul(a6)
	move.l	d0,d7			; Zahl mal 10.0
	subq.l	#1,d6			; dekrementiere	Exponent
1$	move.l	d7,d0
	move.l	#$80000041,d1		; vergleiche mit 1.0
	jsr	_LVOSPCmp(a6)
	bge.s	2$			; wenn größer gleich 1.0
	move.l	d7,d1
	jsr	_LVOSPTst(a6)
	bne.s	3$			; wenn ungleich	Null
	bra.s	2$

	; Ziehe	den positiven Exponenten.
4$	move.l	d7,d0
	move.l	#$CCCCCD3D,d1
	jsr	_LVOSPMul(a6)
	move.l	d0,d7			; Zahl mal 0.1
	addq.l	#1,d6			; inkrementiere	Exponent
2$	move.l	d7,d0
	move.l	#$A0000044,d1		; vergleiche mit 10.0
	jsr	_LVOSPCmp(a6)
	bge.s	4$			; solange größer gleich	10.0

	; Was steht vor	dem Komma ?
	move.l	d7,d0
	jsr	_LVOSPFix(a6)
	move	d0,d1
	add.b	#'0',d1			; ergibt ASCII-Ziffer
	move.b	d1,(a5)+
	jsr	_LVOSPFlt(a6)
	move.l	d0,d1
	move.l	d7,d0
	jsr	_LVOSPSub(a6)
	beq.s	FPAExp			; wenn nichts mehr nach	dem Komma kommt
	move.b	#'.',(a5)+
	moveq	#6-1,d5			; maximale Nachkommastellen


	; Gib die Nachkommastellen aus.
5$	move.l	d0,d7
	move.l	#$A0000044,d1
	jsr	_LVOSPMul(a6)		; Zahl mal 10.0
	move.l	d0,d7
	jsr	_LVOSPFix(a6)
	move	d0,d1
	add.b	#'0',d1			; ergibt ASCII-Ziffer
	move.b	d1,(a5)+
	jsr	_LVOSPFlt(a6)
	move.l	d0,d1
	move.l	d7,d0
	jsr	_LVOSPSub(a6)
	dbeq	d5,5$			; wenn noch Nachkommastellen


FPAExp
	; Ist der Exponent Null	?
	move.l	d6,d0			; Rückgabewert
	beq.s	0$			; ja, dann nicht ausgeben und Ende

	; Ist der Exponenten negativ ?
	move.b	#'e',(a5)+
	move.b	#'+',(a5)+
	tst.l	d6
	bpl.s	1$
	neg.l	d6			; ja
	move.b	#'-',-1(a5)		; gib Minus aus

	; Der Exponent ist zweistellig.
1$	divu	#10,d6
	add.b	#'0',d6
	move.b	d6,(a5)+		; 10er-Stelle
	swap	d6
	add.b	#'0',d6
	move.b	d6,(a5)+		; 1er-Stelle

	; Fertig !
0$	clr.b	(a5)			; Stringende
	rts

	ENDC










	END

