xref: /plan9/sys/src/9/port/fpimem.c (revision 426f2a32150b219ea919a1d76cbd0c50d6d55686)
1d11907f1SDavid du Colombier #include "fpi.h"
2d11907f1SDavid du Colombier 
3d11907f1SDavid du Colombier /*
4d11907f1SDavid du Colombier  * the following routines depend on memory format, not the machine
5d11907f1SDavid du Colombier  */
6d11907f1SDavid du Colombier 
7*426f2a32SDavid du Colombier enum {
8*426f2a32SDavid du Colombier 	Sign	= 1u << 31,
9*426f2a32SDavid du Colombier };
10*426f2a32SDavid du Colombier 
11d11907f1SDavid du Colombier void
fpis2i(Internal * i,void * v)12d11907f1SDavid du Colombier fpis2i(Internal *i, void *v)
13d11907f1SDavid du Colombier {
14d11907f1SDavid du Colombier 	Single *s = v;
15d11907f1SDavid du Colombier 
16*426f2a32SDavid du Colombier 	i->s = (*s & Sign) ? 1: 0;
17*426f2a32SDavid du Colombier 	if((*s & ~Sign) == 0){
18d11907f1SDavid du Colombier 		SetZero(i);
19d11907f1SDavid du Colombier 		return;
20d11907f1SDavid du Colombier 	}
21d11907f1SDavid du Colombier 	i->e = ((*s>>23) & 0x00FF) - SingleExpBias + ExpBias;
22d11907f1SDavid du Colombier 	i->h = (*s & 0x007FFFFF)<<(1+NGuardBits);
23d11907f1SDavid du Colombier 	i->l = 0;
24d11907f1SDavid du Colombier 	if(i->e)
25d11907f1SDavid du Colombier 		i->h |= HiddenBit;
26d11907f1SDavid du Colombier 	else
27d11907f1SDavid du Colombier 		i->e++;
28d11907f1SDavid du Colombier }
29d11907f1SDavid du Colombier 
30d11907f1SDavid du Colombier void
fpid2i(Internal * i,void * v)31d11907f1SDavid du Colombier fpid2i(Internal *i, void *v)
32d11907f1SDavid du Colombier {
33d11907f1SDavid du Colombier 	Double *d = v;
34d11907f1SDavid du Colombier 
35*426f2a32SDavid du Colombier 	i->s = (d->h & Sign) ? 1: 0;
36d11907f1SDavid du Colombier 	i->e = (d->h>>20) & 0x07FF;
37d11907f1SDavid du Colombier 	i->h = ((d->h & 0x000FFFFF)<<(4+NGuardBits))|((d->l>>25) & 0x7F);
38d11907f1SDavid du Colombier 	i->l = (d->l & 0x01FFFFFF)<<NGuardBits;
39d11907f1SDavid du Colombier 	if(i->e)
40d11907f1SDavid du Colombier 		i->h |= HiddenBit;
41d11907f1SDavid du Colombier 	else
42d11907f1SDavid du Colombier 		i->e++;
43d11907f1SDavid du Colombier }
44d11907f1SDavid du Colombier 
45d11907f1SDavid du Colombier void
fpiw2i(Internal * i,void * v)46d11907f1SDavid du Colombier fpiw2i(Internal *i, void *v)
47d11907f1SDavid du Colombier {
48d11907f1SDavid du Colombier 	Word w, word = *(Word*)v;
49d11907f1SDavid du Colombier 	short e;
50d11907f1SDavid du Colombier 
51d11907f1SDavid du Colombier 	if(word < 0){
52d11907f1SDavid du Colombier 		i->s = 1;
53d11907f1SDavid du Colombier 		word = -word;
54d11907f1SDavid du Colombier 	}
55d11907f1SDavid du Colombier 	else
56d11907f1SDavid du Colombier 		i->s = 0;
57d11907f1SDavid du Colombier 	if(word == 0){
58d11907f1SDavid du Colombier 		SetZero(i);
59d11907f1SDavid du Colombier 		return;
60d11907f1SDavid du Colombier 	}
61d11907f1SDavid du Colombier 	if(word > 0){
62d11907f1SDavid du Colombier 		for (e = 0, w = word; w; w >>= 1, e++)
63d11907f1SDavid du Colombier 			;
64d11907f1SDavid du Colombier 	} else
65d11907f1SDavid du Colombier 		e = 32;
66d11907f1SDavid du Colombier 	if(e > FractBits){
67d11907f1SDavid du Colombier 		i->h = word>>(e - FractBits);
68d11907f1SDavid du Colombier 		i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
69d11907f1SDavid du Colombier 	}
70d11907f1SDavid du Colombier 	else {
71d11907f1SDavid du Colombier 		i->h = word<<(FractBits - e);
72d11907f1SDavid du Colombier 		i->l = 0;
73d11907f1SDavid du Colombier 	}
74d11907f1SDavid du Colombier 	i->e = (e - 1) + ExpBias;
75d11907f1SDavid du Colombier }
76d11907f1SDavid du Colombier 
77d11907f1SDavid du Colombier void
fpiv2i(Internal * i,void * v)784e3613abSDavid du Colombier fpiv2i(Internal *i, void *v)
794e3613abSDavid du Colombier {
804e3613abSDavid du Colombier 	Vlong w, word = *(Vlong*)v;
814e3613abSDavid du Colombier 	short e;
824e3613abSDavid du Colombier 
834e3613abSDavid du Colombier 	if(word < 0){
844e3613abSDavid du Colombier 		i->s = 1;
854e3613abSDavid du Colombier 		word = -word;
864e3613abSDavid du Colombier 	}
874e3613abSDavid du Colombier 	else
884e3613abSDavid du Colombier 		i->s = 0;
894e3613abSDavid du Colombier 	if(word == 0){
904e3613abSDavid du Colombier 		SetZero(i);
914e3613abSDavid du Colombier 		return;
924e3613abSDavid du Colombier 	}
934e3613abSDavid du Colombier 	if(word > 0){
944e3613abSDavid du Colombier 		for (e = 0, w = word; w; w >>= 1, e++)
954e3613abSDavid du Colombier 			;
964e3613abSDavid du Colombier 	} else
97*426f2a32SDavid du Colombier 		e = 64;
984e3613abSDavid du Colombier 	if(e > FractBits){
994e3613abSDavid du Colombier 		i->h = word>>(e - FractBits);
1004e3613abSDavid du Colombier 		i->l = (word & ((1<<(e - FractBits)) - 1))<<(2*FractBits - e);
1014e3613abSDavid du Colombier 	}
1024e3613abSDavid du Colombier 	else {
1034e3613abSDavid du Colombier 		i->h = word<<(FractBits - e);
1044e3613abSDavid du Colombier 		i->l = 0;
1054e3613abSDavid du Colombier 	}
1064e3613abSDavid du Colombier 	i->e = (e - 1) + ExpBias;
1074e3613abSDavid du Colombier }
1084e3613abSDavid du Colombier 
109*426f2a32SDavid du Colombier /*
110*426f2a32SDavid du Colombier  * Note that all of these conversions from Internal format
111*426f2a32SDavid du Colombier  * potentially alter *i, so it should be a disposable copy
112*426f2a32SDavid du Colombier  * of the value to be converted.
113*426f2a32SDavid du Colombier  */
114*426f2a32SDavid du Colombier 
1154e3613abSDavid du Colombier void
fpii2s(void * v,Internal * i)116d11907f1SDavid du Colombier fpii2s(void *v, Internal *i)
117d11907f1SDavid du Colombier {
118d11907f1SDavid du Colombier 	short e;
119d11907f1SDavid du Colombier 	Single *s = (Single*)v;
120d11907f1SDavid du Colombier 
121d11907f1SDavid du Colombier 	fpiround(i);
122d11907f1SDavid du Colombier 	if(i->h & HiddenBit)
123d11907f1SDavid du Colombier 		i->h &= ~HiddenBit;
124d11907f1SDavid du Colombier 	else
125d11907f1SDavid du Colombier 		i->e--;
126*426f2a32SDavid du Colombier 	*s = i->s ? Sign: 0;
127d11907f1SDavid du Colombier 	e = i->e;
128d11907f1SDavid du Colombier 	if(e < ExpBias){
129d11907f1SDavid du Colombier 		if(e <= (ExpBias - SingleExpBias))
130d11907f1SDavid du Colombier 			return;
131d11907f1SDavid du Colombier 		e = SingleExpBias - (ExpBias - e);
132d11907f1SDavid du Colombier 	}
133d11907f1SDavid du Colombier 	else  if(e >= (ExpBias + (SingleExpMax-SingleExpBias))){
134d11907f1SDavid du Colombier 		*s |= SingleExpMax<<23;
135d11907f1SDavid du Colombier 		return;
136d11907f1SDavid du Colombier 	}
137d11907f1SDavid du Colombier 	else
138d11907f1SDavid du Colombier 		e = SingleExpBias + (e - ExpBias);
139d11907f1SDavid du Colombier 	*s |= (e<<23)|(i->h>>(1+NGuardBits));
140d11907f1SDavid du Colombier }
141d11907f1SDavid du Colombier 
142d11907f1SDavid du Colombier void
fpii2d(void * v,Internal * i)143d11907f1SDavid du Colombier fpii2d(void *v, Internal *i)
144d11907f1SDavid du Colombier {
145d11907f1SDavid du Colombier 	Double *d = (Double*)v;
146d11907f1SDavid du Colombier 
147d11907f1SDavid du Colombier 	fpiround(i);
148d11907f1SDavid du Colombier 	if(i->h & HiddenBit)
149d11907f1SDavid du Colombier 		i->h &= ~HiddenBit;
150d11907f1SDavid du Colombier 	else
151d11907f1SDavid du Colombier 		i->e--;
152d11907f1SDavid du Colombier 	i->l = ((i->h & GuardMask)<<25)|(i->l>>NGuardBits);
153d11907f1SDavid du Colombier 	i->h >>= NGuardBits;
154*426f2a32SDavid du Colombier 	d->h = i->s ? Sign: 0;
155d11907f1SDavid du Colombier 	d->h |= (i->e<<20)|((i->h & 0x00FFFFFF)>>4);
156d11907f1SDavid du Colombier 	d->l = (i->h<<28)|i->l;
157d11907f1SDavid du Colombier }
158d11907f1SDavid du Colombier 
159d11907f1SDavid du Colombier void
fpii2w(Word * word,Internal * i)160d11907f1SDavid du Colombier fpii2w(Word *word, Internal *i)
161d11907f1SDavid du Colombier {
162d11907f1SDavid du Colombier 	Word w;
163d11907f1SDavid du Colombier 	short e;
164d11907f1SDavid du Colombier 
165d11907f1SDavid du Colombier 	fpiround(i);
166d11907f1SDavid du Colombier 	e = (i->e - ExpBias) + 1;
167d11907f1SDavid du Colombier 	if(e <= 0)
168d11907f1SDavid du Colombier 		w = 0;
169d11907f1SDavid du Colombier 	else if(e > 31)
170d11907f1SDavid du Colombier 		w = 0x7FFFFFFF;
171d11907f1SDavid du Colombier 	else if(e > FractBits)
172d11907f1SDavid du Colombier 		w = (i->h<<(e - FractBits))|(i->l>>(2*FractBits - e));
173d11907f1SDavid du Colombier 	else
174d11907f1SDavid du Colombier 		w = i->h>>(FractBits-e);
175d11907f1SDavid du Colombier 	if(i->s)
176d11907f1SDavid du Colombier 		w = -w;
177d11907f1SDavid du Colombier 	*word = w;
178d11907f1SDavid du Colombier }
1794e3613abSDavid du Colombier 
1804e3613abSDavid du Colombier void
fpii2v(Vlong * word,Internal * i)1814e3613abSDavid du Colombier fpii2v(Vlong *word, Internal *i)
1824e3613abSDavid du Colombier {
1834e3613abSDavid du Colombier 	Vlong w;
1844e3613abSDavid du Colombier 	short e;
1854e3613abSDavid du Colombier 
1864e3613abSDavid du Colombier 	fpiround(i);
1874e3613abSDavid du Colombier 	e = (i->e - ExpBias) + 1;
1884e3613abSDavid du Colombier 	if(e <= 0)
1894e3613abSDavid du Colombier 		w = 0;
1904e3613abSDavid du Colombier 	else if(e > 63)
1914e3613abSDavid du Colombier 		w = (1ull<<63) - 1;		/* maxlong */
1924e3613abSDavid du Colombier 	else if(e > FractBits)
1934e3613abSDavid du Colombier 		w = (Vlong)i->h<<(e - FractBits) | i->l>>(2*FractBits - e);
1944e3613abSDavid du Colombier 	else
1954e3613abSDavid du Colombier 		w = i->h>>(FractBits-e);
1964e3613abSDavid du Colombier 	if(i->s)
1974e3613abSDavid du Colombier 		w = -w;
1984e3613abSDavid du Colombier 	*word = w;
1994e3613abSDavid du Colombier }
200