; LIBF32.TXT

;		Bibliotheque mathematique pour les flottants sur 32 bits
;		--------------------------------------------------------
;
;						(C) E+E CHAMOUARD 2002

; La bibliotheque offre les sous-programmes mathematiques pour les nombres
;	flottants codes sur 32 bits (simple precision) selon le standard IEEE754.

; Pour les fonctions arithmetiques (addition, soustraction, multiplication et
;	division), les nombres en entree ne sont pas completement testes (flottant 
;	anormal, infini,...). C'est au programme utilisateur de faire le necessaire 
;	(lors du chargement en memoire par exemple) avec les fonctions mises a 
;	disposition (F32ValidREx, F32InfREx, F32PresREx et F32ZeroREx). En sortie 
;	la carry (C) indique au programme utilisateur si tout c'est bien passe 
;	(C=1 si probleme). Les fonctions mathematiques sont compatibles (et ont ete
;	testees sur les nombre anormaux). Consulter chaque fonction pour les details 
;	specifiques.

; Cette bibliotheque necessite l'utilisation de la bibliotheque sur entiers
;	32 bits. Par compatibilite avec les autres bibliotheques des fonctions
;	(ex. ecriture/lecture en memoire) sont aussi redefinies dans cette
;	bibliotheque.

; L'erreur de calcul ne depasse pas un LSB avec une mantisse de 24 bits soit
;	une precision meilleure que 10-7 (sauf nombres "anormaux").

; Rappel du standard IEEE754 (simple precision) :
; Les nombres (normaux) sont sous la forme s*(1.f)*2^x avec :
;	  s : le bit de signe (1=negatif)
;	  f : la mantisse sur 23 bits (24 bits de precision avec le 1 implicite)
;	  x : l'exposant sur 8 bits avec un offset de 127 (129 <=> 2^2)
; Les nombres anormaux sont sous la forme s*(0.f)*2^(x+1) (0 implicite)

; Exemples et codages speciaux :
;
;	s	 x		   f      hexas (i+3 a i)   Signification
;
;	0	127			  0		3f 80 00 00		+1
;	0	125		4194304		3e c0 00 00		+0.375
;	0	128			  0		40 00 00 00		+2
;	1	128			  0		c0 00 00 00		-2
;	0	127		1906731		3f 9d 18 2b		+1.2273
;	0	  0			  0		00 00 00 00		+0					Plus zero
;	1	  0			  0		80 00 00 00		-0					Moins zero
;	0	255			  0		7f 80 00 00		+INF				Plus l'infini
;	1	255			  0		ff 80 00 00		-INF				Moins l'infini
;	0	254		8388607		7f 7f ff ff		+3.4028233e+38		Plus grand positif
;	1	254		8388607		ff 7f ff ff		-3.4028233e+38		Plus grand negatif
;	0	  1			  0		00 80 00 00		+1.1754944e-38		Plus petit positif normal
;	1	  1			  0		00 80 00 80		-1.1754944e-38		Plus petit negatif normal
;	0	255			!=0		7f xx xx xx		+NaN (Not a Number)
;	1	255			!=0		ff xx xx xx		-NaN (Not a Number)
;	0	  0			!=0		00 xx xx xx		+Denormal number (gradual undeflow)
;	1	  0			!=0		80 xx xx xx		-Denormal number (gradual undeflow)
;	0	  0			  1		00 00 00 01		+1.4012985e-45		Plus petit positif anormal
;	0	  0			256		00 00 01 00		+3.5873241e-43
;	0	  0		  65536		00 01 00 00		+9.1835496e-41
;	0	  0		8388607		00 7f ff ff		+1.1754942e-38		Plus grand positif anormal


; La bibliotheque travaille sur 3 groupes de registres :
;	RE1x pour le premier operande ou premier resultat,
;	RE2x pour le second operande ou second resultat,
;	TMPx pour les resultats intermediaires.

; Le programme principal doit donc definir 12 registres directs :
;	direct  RE10, xxh   ; LSB du premier operande ou premier resultat
;	direct  RE11, xxh   ;
;	direct  RE12, xxh   ;
;	direct  RE13, xxh   ; MSB du premier operande ou premier resultat
;	direct  RE20, xxh   ; LSB du second operande ou second resultat
;	direct  RE21, xxh   ;
;	direct  RE22, xxh   ;
;	direct  RE23, xxh   ; MSB du second operande ou second resultat
;	direct  TMP0, xxh   ; LSB du resultat intermediaire
;	direct  TMP1, xxh   ;
;	direct  TMP2, xxh   ;
;	direct  TMP3, xxh   ; MSB du resultat intermediaire

; Le chargement ou sauvegarde des resultats ou des operandes s'effectue
;	par chargement  :
;		dans la memoire externe   (ex : F32ReadExtREx),
;		dans la memoire programme (ex : F32ReadProgREx),
;		dans la memoire interne   (ex : F32ReadIntREx).

; La carry (C) est positionnee en cas de debordement ou d'erreur (division)
;	pour tous les sous-programmes sauf ceux de chargement ou de sauvegarde.

; Liste des sous-programmes :
;	F32ReadExtRE1				Lecture de RE1 depuis la memoire externe
;	F32ReadExtRE2				Lecture de RE2 depuis la memoire externe
;	F32ReadProgRE1				Lecture de RE1 depuis la memoire programme
;	F32ReadProgRE2				Lecture de RE2 depuis la memoire programme
;	F32ReadIntRE1				Lecture de RE1 depuis la memoire interne
;	F32ReadIntRE2				Lecture de RE2 depuis la memoire interne
;	F32WriteExtRE1				Ecriture de RE1 dans la memoire externe
;	F32WriteExtRE2				Ecriture de RE2 dans la memoire externe
;	F32WriteIntRE1				Ecriture de RE1 dans la memoire interne
;	F32WriteIntRE2				Ecriture de RE2 dans la memoire interne
;	F32ClearRE1					Mise a 0 de RE1
;	F32Add						RE1=RE1+RE2
;	F32Sub						RE1=RE1-RE2
;	F32Mul						RE1=RE1*RE2
;	F32Div						RE1=RE1/RE2
;	F32NegRE1					RE1=-RE1
;	F32SgnRE1					C=Signe de RE1
;	F32AbsRE1					RE1=Valeur absolue de RE1
;	F32ValidRE1					C=0 si RE1!=NaN (Not a Number)
;	F32ValidRE2					C=0 si RE2!=NaN (Not a Number)
;	F32InfRE1					C=0 si RE1!=INF (Infinity)
;	F32InfRE2					C=0 si RE2!=INF (Infinity)
;	F32PresRE1					C=0 si RE1!=nombre avec gradual underflow
;	F32PresRE2					C=0 si RE2!=nombre avec gradual underflow
;	F32ZeroRE1					C=0 si RE1!=0
;	F32ZeroRE2					C=0 si RE2!=0
;	F32Cvti32tof32				Conversion signee de RE1 entier -> flottant
;	F32Cvtf32toi32				Conversion signee de RE1 flottant -> entier
;	F32UCvti32tof32				Conversion non signee de RE1 entier -> flottant
;	F32UCvtf32toi32				Conversion non signee de RE1 flottant -> entier

F32ReadExtRE1:
    Fonction  :   Lecture de 32 bits de la memoire externe vers l'operande/resultat RE1
    Entree(s) :   Dans {DPH,DPL} l'adresse de la donnee (LSB en tete)
    Sortie(s) :   RE1={@DPTR+3,@DPTR+2,@DPTR+1,@DPTR} (DPTR incremente de 4 cases)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ReadExtRE2:
    Fonction  :   Lecture de 32 bits de la memoire externe vers l'operande/resultat RE2
    Entree(s) :   Dans {DPH,DPL} l'adresse de la donnee (LSB en tete)
    Sortie(s) :   RE2={@DPTR+3,@DPTR+2,@DPTR+1,@DPTR} (DPTR incremente de 4 cases)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ReadProgRE1:
    Fonction  :   Lecture de 32 bits de la memoire programme vers l'operande/resultat RE1
    Entree(s) :   Dans {DPH,DPL} l'adresse de la donnee (LSB en tete)
    Sortie(s) :   RE1={@DPTR+3,@DPTR+2,@DPTR+1,@DPTR} (DPTR incremente de 4 cases)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ReadProgRE2:
    Fonction  :   Lecture de 32 bits de la memoire programme vers l'operande/resultat RE2
    Entree(s) :   Dans {DPH,DPL} l'adresse de la donnee (LSB en tete)
    Sortie(s) :   RE2={@DPTR+3,@DPTR+2,@DPTR+1,@DPTR} (DPTR incremente de 4 cases)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ReadIntRE1:
    Fonction  :   Lecture de 32 bits de la memoire interne vers l'operande/resultat RE1
    Entree(s) :   Dans R0 l'adresse de la donnee (LSB en tete)
    Sortie(s) :   RE1={@R0+3,@R0+2,@R0+1,@R0} (R0 incremente de 4 cases)
    Utilise   :   Rien
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ReadIntRE2:
    Fonction  :   Lecture de 32 bits de la memoire interne vers l'operande/resultat RE2
    Entree(s) :   Dans R0 l'adresse de la donnee (LSB en tete)
    Sortie(s) :   RE2={@R0+3,@R0+2,@R0+1,@R0} (R0 incremente de 4 cases)
    Utilise   :   Rien
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32WriteExtRE1:
    Fonction  :   Ecriture de 32 bits de l'operande/resultat RE1 vers la memoire externe
    Entree(s) :   Dans {DPH,DPL} l'adresse de la donnee (LSB en tete)
    Sortie(s) :   {@DPTR+3,@DPTR+2,@DPTR+1,@DPTR}=RE1 (DPTR incremente de 4 cases)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32WriteExtRE2:
    Fonction  :   Ecriture de 32 bits de l'operande/resultat RE2 vers la memoire externe
    Entree(s) :   Dans {DPH,DPL} l'adresse de la donnee (LSB en tete)
    Sortie(s) :   {@DPTR+3,@DPTR+2,@DPTR+1,@DPTR}=RE2 (DPTR incremente de 4 cases)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32WriteIntRE1:
    Fonction  :   Ecriture de 32 bits de l'operande/resultat RE1 vers la memoire interne
    Entree(s) :   Dans R0 l'adresse de la donnee (LSB en tete)
    Sortie(s) :   {@R0+3,@R0+2,@R0+1,@R0}=RE1 (R0 incremente de 4 cases)
    Utilise   :   Rien
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32WriteIntRE2:
    Fonction  :   Ecriture de 32 bits de l'operande/resultat RE2 vers la memoire interne
    Entree(s) :   Dans R0 l'adresse de la donnee (LSB en tete)
    Sortie(s) :   {@R0+3,@R0+2,@R0+1,@R0}=RE2 (R0 incremente de 4 cases)
    Utilise   :   Rien
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ClearRE1:
    Fonction  :   RAZ de l'operande/resultat RE1
    Entree(s) :   Rien
    Sortie(s) :   RE1={0,0,0,0}=+0 (C=0)
    Utilise   :   Rien
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32Add:
    Fonction  :   Addition de deux nombres flottants de 32 bits
    Entree(s) :   Donnees dans RE1 et RE2
    Sortie(s) :   RE1=RE1+RE2 (RE2 perdu)
  				  Si RE2=0 sortie de RE1 avec C=0
 				  Sinon
				    Si RE1=0 sortie de RE2 avec C=0
					  Sinon
					    Si RE1=INF ou NaN sortie de RE1 avec C=1
					    Sinon
						  Si RE2=INF ou NaN sortie de RE2 avec C=1
						  Sinon
						    Si pas debordement sortie de RE1+RE2 avec C=0
						    Sinon sortie de + ou - INF avec C=1 
    Utilise   :   Registres TMP0 a TMP3, A, B, F0 et PSW non sauvegardes
    Pile      :   4 avec l'appel
    Cycles    :   ?

F32Sub:
    Fonction  :   Soustraction de deux nombres flottants de 32 bits
    Entree(s) :   Donnees dans RE1 et RE2
    Sortie(s) :   RE1=RE1-RE2 (RE2 perdu)
				  Si RE2=0 sortie de RE1 avec C=0
				  Sinon
				    Si RE1=0 sortie de -RE2 avec C=0
					  Sinon
					    Si RE1=INF ou NaN sortie de RE1 avec C=1
					    Sinon
						  Si RE2=INF ou NaN sortie de -RE2 avec C=1
						  Sinon
						    Si pas debordement sortie de RE1-RE2 avec C=0
						    Sinon sortie de + ou - INF avec C=1 
    Utilise   :   Registres TMP0 a TMP3, A, B, F0 et PSW non sauvegardes
    Pile      :   4 avec l'appel
    Cycles    :   ?

F32Mul:
    Fonction  :   Multiplication de deux nombres flottants de 32 bits
    Entree(s) :   Donnees dans RE1 et RE2
    Sortie(s) :   RE1=RE1*RE2 (RE2 perdu)
				  Si RE1=0 sortie de 0 avec C=0
				  Sinon
				    Si RE2=0 sortie de 0 avec C=0
					  Sinon
					    Si RE1=INF ou NaN sortie de RE1 avec C=1
					    Sinon
						  Si RE2=INF ou NaN sortie de RE2 avec C=1
						  Sinon
						    Si pas debordement sortie de RE1*RE2 avec C=0
						    Sinon sortie de + ou - INF avec C=1 
    Utilise   :   Registres TMP0 a TMP3, A, B, F0 et PSW non sauvegardes
    Pile      :   4 avec l'appel
    Cycles    :   ?

F32Div:
    Fonction  :   Division de deux nombres flottants de 32 bits
    Entree(s) :   Donnees dans RE1 (numerateur) et RE2 (denominateur)
    Sortie(s) :   RE1=RE1/RE2 (RE2 perdu)
				  Si RE2=0 sortie de + ou - INF avec C=1
			 	  Sinon
				    Si RE2=INF ou NAN sortie de + ou - 0 avec C=1
					  Sinon
					    Si RE1=+ ou - 0 sortie de + ou - 0 avec C=0
					    Sinon
						  Si RE1=INF ou NaN sortie de + ou - INF avec C=1
						  Sinon
						    Si pas debordement sortie de RE1/RE2 avec C=0
						    Sinon sortie de + ou - INF avec C=1 
    Utilise   :   Registres TMP0 a TMP3, A, B, F0 et PSW non sauvegardes
    Pile      :   4 avec l'appel
    Cycles    :   ?

F32NegRE1:
    Fonction  :   Changement de signe de l'operande/resultat RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   RE1=-RE1
                  C=0 (pas d'erreur possible)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32SgnRE1:
    Fonction  :   Recuperation du signe de l'operande/resultat RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   C=0 si le nombre est positif
                  C=1 si le nombre est negatif
                  RE1 reste inchange
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32AbsRE1:
    Fonction  :   Valeur absolue de l'operande/resultat RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   RE1=ABS(RE1)
                  C=0 (pas d'erreur possible)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ValidRE1:
    Fonction  :   Verification de la validite de l'operande/resultat RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   C=0 si RE1 ne contient pas NAN et uniquement ce cas,
                  sinon C=1 (RE1 reste inchange dans tous les cas)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ValidRE2:
    Fonction  :   Verification de la validite de l'operande/resultat RE2
    Entree(s) :   Donnee dans RE2
    Sortie(s) :   C=0 si RE2 ne contient pas NAN et uniquement ce cas,
                  sinon C=1 (RE2 reste inchange dans tous les cas)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32InfRE1:
    Fonction  :   Verification de la non infinite de l'operande/resultat RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   C=0 si RE1 ne contient pas +INF ni -INF et uniquement ces cas,
                  sinon C=1 (RE1 reste inchange dans tous les cas)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32InfRE2:
    Fonction  :   Verification de la non infinite de l'operande/resultat RE2
    Entree(s) :   Donnee dans RE2
    Sortie(s) :   C=0 si RE2 ne contient pas +INF ni -INF et uniquement ces cas,
                  sinon C=1 (RE2 reste inchange dans tous les cas)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32PresRE1:
    Fonction  :   Verification de la precision de l'operande/resultat RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   C=0 si RE1 ne contient pas un flottant avec gradual underflow
                  et uniquement ce cas,
                  sinon C=1 (RE1 reste inchange dans tous les cas)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32PresRE2:
    Fonction  :   Verification de la precision de l'operande/resultat RE2
    Entree(s) :   Donnee dans RE2
    Sortie(s) :   C=0 si RE2 ne contient pas un flottant avec gradual underflow
                  et uniquement ce cas,
                  sinon C=1 (RE2 reste inchange dans tous les cas)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ZeroRE1:
    Fonction  :   Verification de la non nullite de l'operande/resultat RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   C=0 si RE1 ne contient pas +0 ni -0 et uniquement ces cas,
                  sinon C=1 (RE1 reste inchange dans tous les cas)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32ZeroRE2:
    Fonction  :   Verification de la non nullite de l'operande/resultat RE2
    Entree(s) :   Donnee dans RE2
    Sortie(s) :   C=0 si RE2 ne contient pas +0 ni -0 et uniquement ces cas,
                  sinon C=1 (RE2 reste inchange dans tous les cas)
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32Cvti32tof32RE1:
    Fonction  :   Conversion d'un entier signe de 32 bits vers un flottant de 32 bits dans RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   Donnee convertie en flottant dans RE1 avec C=0
    Utilise   :   Registres A, PSW, B, TMP0 et TMP1 non sauvegardes
    Pile      :   4 avec l'appel
    Cycles    :   ?

F32Cvtf32toi32RE1:
    Fonction  :   Conversion d'un flottant de 32 bits vers un entier signe de 32 bits dans RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   Donnee convertie sur 32 bits dans RE1 avec C=0 sauf
				    si RE1<-2^31 sortie de -2^31 avec C=1
				    si RE1>2^31-1 sortie de 2^31-1 avec C=1
				  Le nombre est arrondi  l'entier inferieur :
				  -1.    -> -1
				  -0.999 -> 0
				  +0.999 -> 0
				  +1.    -> +1
    Utilise   :   Registres A, PSW, B, TMP0 et TMP1 non sauvegardes
    Pile      :   6 avec l'appel
    Cycles    :   ?

F32UCvti32tof32RE1:
    Fonction  :   Conversion d'un entier non signe de 32 bits vers un flottant de 32 bits dans RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   Donnee convertie en flottant dans RE1 avec C=0
    Utilise   :   Registres A, PSW, B, TMP0 et TMP1 non sauvegardes
    Pile      :   4 avec l'appel
    Cycles    :   ?

F32UCvtf32toi32RE1:
    Fonction  :   Conversion d'un flottant de 32 bits vers un entier non signe de 32 bits dans RE1
    Entree(s) :   Donnee dans RE10
    Sortie(s) :   Donnee convertie sur 32 bits dans RE1 avec C=0 sauf
				    si RE1<=-0.5   sortie de 0 avec C=1
				    si RE1>+2^32-1 sortie de 2^32-1 avec C=1
				  Le nombre est arrondi  l'entier inferieur :
				  -0.499 -> 0
				  +0.999 -> 0
	 			  +1.    -> +1
    Utilise   :   Registres A, PSW, B, TMP0 et TMP1 non sauvegardes
    Pile      :   4 avec l'appel
    Cycles    :   ?

;
;   Sous-programmes internes
;

F32GetexpRE1:
    Fonction  :   Decomposition de l'argument RE1
    Entree(s) :   Donnee dans RE1
    Sortie(s) :   Exposant dans A
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32GetexpRE2:
    Fonction  :   Decomposition de l'argument RE2
    Entree(s) :   Donnee dans RE2
    Sortie(s) :   Exposant dans A
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32RE22RE1:
    Fonction  :   Copie de l'argument RE2 vers l'argument RE1
    Entree(s) :   Donnee dans RE2
    Sortie(s) :   RE1 contenant la valeur de RE2
    Utilise   :   Rien
    Pile      :   2 avec l'appel
    Cycles    :   ?

F32NormRE1:
    Fonction  :   Normalisation d'un nombre dans RE1 et sortie
    Entree(s) :   RE1 la mantisse (non signee) sur un nombre de bits variable
				  F0 signe du nombre a sortir
				  TMP1,TMP0 l'exposant sur 16 bits correspondant a une
				  mantisse sur 30 bits (codage IEEE754) donc si elle est de
				  la forme : 001xxxxx xxxxxxxx xxxxxxxx xxxxxxxx
				  (mantisse IEEE754 multipliee par 64)
  				  Exemple : TMP1,TMP0=127 mantisse=00100000 00000000 0000000 00000000
  				  En sortie on aura 3f 80 00 00 soit 1.
    Sortie(s) :   RE1 normalis (dnormalis, infini ou nul) selon IEEE754
    Utilise   :   Registres A, PSW, B, TMP0 et TMP1 non sauvegardes
    Pile      :   4 avec l'appel
    Cycles    :   ?

F32OutInf:
    Fonction  :   Sortie de + ou moins l'infini
    Entree(s) :   Signe de l'infini a sortir dans F0
    Sortie(s) :   RE1 contenant + ou - l'infini
    Utilise   :   Registres A et PSW non sauvegardes
    Pile      :   2 avec l'appel
    Cycles    :   ?
