|
|
1.1 root 1: .data
2: .asciz "@(#)Ffloat.s 1.1 86/02/03 Copyr 1985 Sun Micro"
3: .even
4: .text
5:
6: | Copyright (c) 1985 by Sun Microsystems, Inc.
7:
8: #include "fpcrtdefs.h"
9:
10: /*
11: * single-precision utility operations
12: *
13: * copyright 1981, 1982 Richard E. James III
14: * translated to SUN idiom 11 March 1983 rt
15: */
16:
17: NSAVED = 3*4 | save registers d2-d4
18: SAVEMASK = 0x3c00
19: RESTMASK = 0x003c
20:
21: /*
22: * unpack a single-precision number into the unpacked record format:
23: * d0/d1 mantissa
24: * d2.w exponent
25: * d3.w sign in upper bit
26: * d3.b type ( zero, gu, plain, inf, nan )
27: */
28:
29: ENTER(f_unpk)
30: movl d1,d3
31: swap d3 | sign in bit 15
32: lsll #1,d1 | toss sign
33: roll #8,d1
34: clrw d2
35: movb d1,d2 | exponent
36: bnes 1$ | not gu or zero
37: movb #1,d3
38: tstl d1
39: beqs 3$
40: movb #2,d3 | gu -- gradual underflow unnormalized
41: bras 3$
42: 1$: cmpb #255,d2 | inf or nan
43: bnes 2$ | nope, plain number
44: movw #0x6000,d2
45: clrb d1 | erase exponent
46: movb #4,d3 | infinity
47: tstl d1
48: beqs 4$
49: movb #5,d3 | nan
50: bras 4$
51: 2$: movb #1,d1 | hidden bit
52: subqw #1,d2
53: movb #3,d3
54: 3$: subw #(126+23),d2
55: 4$: rorl #1,d1
56: lsrl #8,d1
57: clrl d0
58: rts
59:
60: /*
61: * reconstruct a single precision number from its pieces
62: * returns packed value in d0
63: */
64:
65: ENTER(f_pack)
66: movw d2,d4 | exponent
67: cmpb #4,d3 | is type inf or nan ?
68: blts 1$ | no, then branch
69: orl d0,d1
70: orl #0x7f800000,d1 | exponent for inf/nan
71: lsll #1,d1
72: bras 6$
73: 1$:
74: clrb d2 | for sticky
75: tstl d0
76: beqs 3$
77: | shift from upper into lower
78: 2$:
79: orb d1,d2 | sticky
80: movb d0,d1
81: addqw #8,d4 | adjust exponent
82: rorl #8,d1
83: lsrl #8,d0
84: bnes 2$ | loop until top == 0
85: 3$: movl d1,d0
86: beqs 6$
87: | find top bit
88: bmis 5$
89: 4$: subqw #1,d4 | adjust exponent
90: lsll #1,d0 | normalize
91: bpls 4$
92: 5$: addw #(126+23+9),d4
93: tstb d2
94: beqs 7$ | Branch if no sticky.
95: bset #0,d0 | Turn on sticky bit.
96: 7$:
97: bsrs f_rcp
98: rorl #8,d0
99: movl d0,d1
100: 6$: lslw #1,d3
101: roxrl #1,d1 | append sign
102: rts
103:
104:
105: /*
106: * round, check for over/underflow, and pack in the exponent.
107: */
108:
109: ENTER(f_rcp)
110: tstl d0
111: bmis f_rcfast
112: | do extra normalize ( for mul/div)
113: subqw #1,d4
114: lsll #1,d0 | do one normalize
115: f_rcfast:
116: tstw d4
117: bgts 2$
118: | underflow
119: cmpw #-24,d4
120: blts rcpzero
121: negb d4
122: addqb #1,d4
123: movl d1,sp@- | Save d1 on stack.
124: clrl d1 | d1 gets 0.
125: bset d4,d1 | For n bit shift, d1 gets 2**n.
126: subql #1,d1 | d1 gets 2**n -1, an n bit field.
127: andl d0,d1 | d1 gets bits to be shifted away.
128: beqs 1f | Branch if all zero.
129: bset d4,d0 | Sticky lsb for bits to be lost.
130: 1:
131: movl sp@+,d1 | Restore d1.
132: lsrl d4,d0 | denormalize
133: clrw d4 | exp == 0
134: 2$: addl #0x80,d0 | crude round
135: bccs stesteven
136: | round overflowed
137: roxrl #1,d0
138: addqw #1,d4
139: bras scheckbig
140: stesteven:
141: tstb d0 | Check extra bits after round.
142: bnes scheckbig | Branch if round was not ambiguous.
143: bclr #8,d0 | Force round to even.
144: scheckbig:
145: cmpw #0xff,d4 | adjust exponent
146: bges rcpinf
147: lsll #1,d0 | toss hidden
148: |scs d0 | no hidden implies zero or denormalized
149: |andb d4,d0
150: |rts
151: bccs rcpsubnorm | Branch if no i bit found, implying zero or subnorm.
152: movb d4,d0 | d0 gets exponent.
153: bnes rcprts | Branch if exp was not zero, implying normal result.
154: movb #1,d0 | Result was subnormal before round, normal after,
155: | so adjust exponent accordingly.
156: rcprts:
157: rts
158: rcpsubnorm: | No carry out from shift implies zero or subnormal
159: | result after rounding.
160: clrb d0 | Set minimum exponent.
161: rts
162:
163: rcpzero:
164: clrl d0
165: rts
166: rcpinf:
167: movl #0xff,d0 | infinity
168: rts
169:
170: NSAVED = 3*4 | save registers d2-d4
171: SAVEMASK = 0x3c00
172: RESTMASK = 0x003c
173: ARG2PTR = a0
174:
175: /*
176: * split a double floating number into its pieces
177: * input:
178: * d0/d1 double number
179: * output: (format of an unpacked record)
180: * d0/d1 mantissa: array[1..2] of integer;
181: * d2.w exponent: -32768..32767;
182: * d3.w sign: (bit 15) 0..1;
183: * d3.b type: 1..5; (zero, gu, plain, inf, nan )
184: */
185:
186: ENTER(d_unpk)
187: movl #0xfff00000,d2 | mask for sign and exponent
188: movl d0,d3
189: swap d3 | sign
190: andl d0,d2 | extract exponent
191: eorl d2,d0 | top of mantissa cleared out
192: movl d1,d4
193: orl d0,d4 | non-zero iff mantissa non-zero
194: lsll #1,d2 | toss sign
195: bnes 1$ | not 0 or gu
196: movb #1,d3
197: tstl d4
198: beqs 3$ | zero
199: movb #2,d3
200: bras 3$ | gu
201: 1$: swap d2
202: lsrw #(16-11),d2 | exp to bottom of register
203: cmpw #0x7ff,d2 | inf or nan
204: bnes 2$ | plain
205: movw #0x6000,d2
206: movb #4,d3
207: tstl d4
208: beqs 4$ | inf
209: movb #5,d3 | nan
210: bras 4$
211: 2$: bset #20,d0 | hidden bit
212: subqw #1,d2
213: movb #3,d3
214: 3$: subw #(1022+52), d2
215: 4$: rts
216:
217: /*
218: * reconstruct a double precision number from a record containing its pieces.
219: *
220: * input:
221: * d2 upper
222: * d3 lower
223: * d6 exponent
224: * output:
225: * d0/d1 result
226: */
227:
228: ENTER(d_pack)
229: cmpb #4,d3 | type
230: blts 1$
231: orl d1,d0
232: lsll #1,d0
233: orl #0xffe00000,d0
234: bras 2$ | nan or inf
235: 1$: addw #(1022+52+12),d2
236: exg d0,d2
237: exg d0,d6
238: exg d1,d3
239: bsrs d_norm
240: bsr d_rcp
241: movl d0,d6
242: movl d2,d0
243: exg d3,d1
244: 2$: lslw #1,d3
245: roxrl #1,d0
246: rts
247:
248: /*
249: * normalize a double-precision number
250: *
251: * input:
252: * d2/d3 mantissa
253: * d6 exponent
254: */
255:
256: ENTER(d_norm)
257: tstl d2 | upper is non-zero
258: bnes 1$
259: cmpw #32,d6
260: blts 2$ | about to be denormalized
261: subw #32,d6
262: exg d3,d2 | shift 32
263: tstl d2
264: beqs 4$ | if result == 0
265: 1$: bmis 3$ | if already normalized
266: 2$: lsll #1,d3 | normalize
267: roxll #1,d2
268: dbmi d6,2$ | loop until normalized
269: dbpl d6,3$ | make sure d6 decremented
270: 3$: rts
271: 4$: movw #-2222,d6 | exp == 0 for zero
272: rts
273:
274:
275: /*
276: * round, check for over/underflow, and pack in the exponent.
277: * d_rcp rounds the double value and packs the exponent in,
278: * catching infinity, zero, and denormalized numbers.
279: * d_usel puts together the larger argument.
280: *
281: * input:
282: * d2/d3 mantissa (- if norm)
283: * d6 biased exponent
284: * (need sign, sticky)
285: * output:
286: * d2/d3 most of number, no sign or hidden bit,
287: * waiting to shift sign in.
288: * other:
289: * d4 lost
290: * d5 unchanged
291: */
292:
293: ENTER(d_rcp)
294: tstw d6
295: bgts 2$
296: | exponent is negative; denormalize before rounding
297: cmpw #-53,d6
298: blts dsigned0| go all the way with zero
299: negw d6
300: 1$: lsrl #1,d2 | denormalize
301: roxrl #1,d3
302: bccs 1f | Check for bit passing out forever.
303: bset #0,d3 | Stick it back on the end.
304: 1: dbra d6,1$
305: clrw d6
306: | round
307: 2$: addl #0x400,d3
308: bccs testeven | Branch if round did not overflow lower part.
309: addql #1,d2 | carry
310: bccs testeven | Branch if round did not overflow significand.
311: roxrl #1,d2
312: roxrl #1,d3
313: addqw #1,d6
314: bras checkbig
315:
316: testeven: | Test for ambiguous case to force round to even.
317: movw #0x7ff,d4 | d4 gets rounding mask.
318: andw d3,d4 | d4 gets extra bits left after rounding.
319: bnes checkbig | Branch if it wasn't ambiguous case.
320: bclr #11,d3 | Ambiguous case: force round to even.
321:
322: checkbig:
323: cmpw #0x7ff,d6
324: bges drcpbig
325: ENTER(d_usel)
326: | rebuild answer
327: movl #0xfffff800,d4
328: andl d4,d3
329: andl d2,d4
330: eorl d4,d2
331: orl d2,d3
332: movl d4,d2
333: lsll #1,d2
334: |bcss 4$
335: bcss cout | Branch if carry out occurred.
336: cmpw #0x7ff,d6
337: beqs 4$
338: clrw d6
339: 4$:
340: dshiftright: | Double shift right to pack.
341: moveq #11,d4
342: rorl d4,d3
343: orw d6,d2
344: rorl d4,d2
345: rts
346: dsigned0: clrl d2
347: clrl d3
348: rts
349: drcpbig:movl #0xffe00000,d2 | infinity
350: clrl d3
351: rts
352:
353: cout:
354: tstw d6
355: bnes dshiftright | Branch if number was not subnormal.
356: movw #1,d6 | Subnormal rounded to normal so fix exp.
357: bras dshiftright
358:
359: | utilities used for floating point routines
360:
361: ENTER(f_snan)
362: movl #0x7fffffff,d0 | Standard 68881 error nan.
363: rts
364:
365: SAVED0D1 = 0x0003
366: RESTD0D1 = 0x0003
367: SAVEALL = 0x3F00 | registers d2-d4
368: RESTALL = 0x00fc
369:
370: | decode type of arg in d1 and return 1-5 n d0 for zero gu plain inf and nan
371:
372: ENTER(f_tst)
373: lsll #1,d1 | toss sign
374: roll #8,d1 | exp in low byte
375: tstb d1
376: bnes 1$ | branch if not gu or zero
377: movl #1,d0 | assume zero
378: tstl d1
379: beqs 3$ | it is
380: movl #2,d0 | else it's a gu
381: bras 3$
382: 1$: cmpb #255,d1 | inf or nan ?
383: bnes 2$ | nope - plain
384: movl #4,d0 | assume inf
385: andl #0xFFFFFF00,d1 | Clear exponent field.
386: beqs 3$ | it is
387: movl #5,d0 | else it'a a nan
388: rts
389: 2$: movl #3,d0
390: 3$: rts
391:
392: | Single and double unbiased exponent, d0 to d0.
393:
394: | Fexpos(1.0) = 0 = Fexpod(1.0)
395:
396: RTENTRY(Fexpos)
397: andl #0x7f800000,d0 | Clear out extra bits.
398: roll #1,d0
399: roll #8,d0
400: subl #0x7f,d0
401: RET
402:
403: RTENTRY(Fexpod)
404: andl #0x7ff00000,d0 | Clear out extra bits.
405: roll #4,d0
406: roll #8,d0
407: subl #0x3ff,d0
408: RET
409:
410: | Switch mode and status.
411:
412: RTENTRY(Fmode)
413: movel d0,sp@-
414: movel _Fmode,d0
415: movel sp@+,_Fmode
416: RET
417: RTENTRY(Fstatus)
418: movel d0,sp@-
419: movel _Fstatus,d0
420: movel sp@+,_Fstatus
421: RET
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.