Annotation of sys/arch/m68k/fpsp/round.sa, Revision 1.1.1.1
1.1 nbrk 1: * $OpenBSD: round.sa,v 1.3 2005/11/15 21:09:45 miod Exp $
2: * $NetBSD: round.sa,v 1.3 1994/10/26 07:49:24 cgd Exp $
3:
4: * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
5: * M68000 Hi-Performance Microprocessor Division
6: * M68040 Software Package
7: *
8: * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
9: * All rights reserved.
10: *
11: * THE SOFTWARE is provided on an "AS IS" basis and without warranty.
12: * To the maximum extent permitted by applicable law,
13: * MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
14: * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
15: * PARTICULAR PURPOSE and any warranty against infringement with
16: * regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
17: * and any accompanying written materials.
18: *
19: * To the maximum extent permitted by applicable law,
20: * IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
21: * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
22: * PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
23: * OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
24: * SOFTWARE. Motorola assumes no responsibility for the maintenance
25: * and support of the SOFTWARE.
26: *
27: * You are hereby granted a copyright license to use, modify, and
28: * distribute the SOFTWARE so long as this entire notice is retained
29: * without alteration in any modified and/or redistributed versions,
30: * and that such modified versions are clearly identified as such.
31: * No licenses are granted by implication, estoppel or otherwise
32: * under any patents or trademarks of Motorola, Inc.
33:
34: *
35: * round.sa 3.4 7/29/91
36: *
37: * handle rounding and normalization tasks
38: *
39:
40: ROUND IDNT 2,1 Motorola 040 Floating Point Software Package
41:
42: section 8
43:
44: include fpsp.h
45:
46: *
47: * round --- round result according to precision/mode
48: *
49: * a0 points to the input operand in the internal extended format
50: * d1(high word) contains rounding precision:
51: * ext = $0000xxxx
52: * sgl = $0001xxxx
53: * dbl = $0002xxxx
54: * d1(low word) contains rounding mode:
55: * RN = $xxxx0000
56: * RZ = $xxxx0001
57: * RM = $xxxx0010
58: * RP = $xxxx0011
59: * d0{31:29} contains the g,r,s bits (extended)
60: *
61: * On return the value pointed to by a0 is correctly rounded,
62: * a0 is preserved and the g-r-s bits in d0 are cleared.
63: * The result is not typed - the tag field is invalid. The
64: * result is still in the internal extended format.
65: *
66: * The INEX bit of USER_FPSR will be set if the rounded result was
67: * inexact (i.e. if any of the g-r-s bits were set).
68: *
69:
70: xdef round
71: round:
72: * If g=r=s=0 then result is exact and round is done, else set
73: * the inex flag in status reg and continue.
74: *
75: bsr.b ext_grs ;this subroutine looks at the
76: * :rounding precision and sets
77: * ;the appropriate g-r-s bits.
78: tst.l d0 ;if grs are zero, go force
79: bne.w rnd_cont ;lower bits to zero for size
80:
81: swap d1 ;set up d1.w for round prec.
82: bra.w truncate
83:
84: rnd_cont:
85: *
86: * Use rounding mode as an index into a jump table for these modes.
87: *
88: or.l #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex
89: lea mode_tab,a1
90: move.l (a1,d1.w*4),a1
91: jmp (a1)
92: *
93: * Jump table indexed by rounding mode in d1.w. All following assumes
94: * grs != 0.
95: *
96: mode_tab:
97: dc.l rnd_near
98: dc.l rnd_zero
99: dc.l rnd_mnus
100: dc.l rnd_plus
101: *
102: * ROUND PLUS INFINITY
103: *
104: * If sign of fp number = 0 (positive), then add 1 to l.
105: *
106: rnd_plus:
107: swap d1 ;set up d1 for round prec.
108: tst.b LOCAL_SGN(a0) ;check for sign
109: bmi.w truncate ;if positive then truncate
110: move.l #$ffffffff,d0 ;force g,r,s to be all f's
111: lea add_to_l,a1
112: move.l (a1,d1.w*4),a1
113: jmp (a1)
114: *
115: * ROUND MINUS INFINITY
116: *
117: * If sign of fp number = 1 (negative), then add 1 to l.
118: *
119: rnd_mnus:
120: swap d1 ;set up d1 for round prec.
121: tst.b LOCAL_SGN(a0) ;check for sign
122: bpl.w truncate ;if negative then truncate
123: move.l #$ffffffff,d0 ;force g,r,s to be all f's
124: lea add_to_l,a1
125: move.l (a1,d1.w*4),a1
126: jmp (a1)
127: *
128: * ROUND ZERO
129: *
130: * Always truncate.
131: rnd_zero:
132: swap d1 ;set up d1 for round prec.
133: bra.w truncate
134: *
135: *
136: * ROUND NEAREST
137: *
138: * If (g=1), then add 1 to l and if (r=s=0), then clear l
139: * Note that this will round to even in case of a tie.
140: *
141: rnd_near:
142: swap d1 ;set up d1 for round prec.
143: add.l d0,d0 ;shift g-bit to c-bit
144: bcc.w truncate ;if (g=1) then
145: lea add_to_l,a1
146: move.l (a1,d1.w*4),a1
147: jmp (a1)
148:
149: *
150: * ext_grs --- extract guard, round and sticky bits
151: *
152: * Input: d1 = PREC:ROUND
153: * Output: d0{31:29}= guard, round, sticky
154: *
155: * The ext_grs extract the guard/round/sticky bits according to the
156: * selected rounding precision. It is called by the round subroutine
157: * only. All registers except d0 are kept intact. d0 becomes an
158: * updated guard,round,sticky in d0{31:29}
159: *
160: * Notes: the ext_grs uses the round PREC, and therefore has to swap d1
161: * prior to usage, and needs to restore d1 to original.
162: *
163: ext_grs:
164: swap d1 ;have d1.w point to round precision
165: tst.w d1
166: bne.b sgl_or_dbl
167: bra.b end_ext_grs
168:
169: sgl_or_dbl:
170: movem.l d2/d3,-(a7) ;make some temp registers
171: cmpi.w #1,d1
172: bne.b grs_dbl
173: grs_sgl:
174: bfextu LOCAL_HI(a0){24:2},d3 ;sgl prec. g-r are 2 bits right
175: move.l #30,d2 ;of the sgl prec. limits
176: lsl.l d2,d3 ;shift g-r bits to MSB of d3
177: move.l LOCAL_HI(a0),d2 ;get word 2 for s-bit test
178: andi.l #$0000003f,d2 ;s bit is the or of all other
179: bne.b st_stky ;bits to the right of g-r
180: tst.l LOCAL_LO(a0) ;test lower mantissa
181: bne.b st_stky ;if any are set, set sticky
182: tst.l d0 ;test original g,r,s
183: bne.b st_stky ;if any are set, set sticky
184: bra.b end_sd ;if words 3 and 4 are clr, exit
185: grs_dbl:
186: bfextu LOCAL_LO(a0){21:2},d3 ;dbl-prec. g-r are 2 bits right
187: move.l #30,d2 ;of the dbl prec. limits
188: lsl.l d2,d3 ;shift g-r bits to the MSB of d3
189: move.l LOCAL_LO(a0),d2 ;get lower mantissa for s-bit test
190: andi.l #$000001ff,d2 ;s bit is the or-ing of all
191: bne.b st_stky ;other bits to the right of g-r
192: tst.l d0 ;test word original g,r,s
193: bne.b st_stky ;if any are set, set sticky
194: bra.b end_sd ;if clear, exit
195: st_stky:
196: bset #rnd_stky_bit,d3
197: end_sd:
198: move.l d3,d0 ;return grs to d0
199: movem.l (a7)+,d2/d3 ;restore scratch registers
200: end_ext_grs:
201: swap d1 ;restore d1 to original
202: rts
203:
204: ******************** Local Equates
205: ad_1_sgl equ $00000100 constant to add 1 to l-bit in sgl prec
206: ad_1_dbl equ $00000800 constant to add 1 to l-bit in dbl prec
207:
208:
209: *Jump table for adding 1 to the l-bit indexed by rnd prec
210:
211: add_to_l:
212: dc.l add_ext
213: dc.l add_sgl
214: dc.l add_dbl
215: dc.l add_dbl
216: *
217: * ADD SINGLE
218: *
219: add_sgl:
220: add.l #ad_1_sgl,LOCAL_HI(a0)
221: bcc.b scc_clr ;no mantissa overflow
222: roxr.w LOCAL_HI(a0) ;shift v-bit back in
223: roxr.w LOCAL_HI+2(a0) ;shift v-bit back in
224: add.w #$1,LOCAL_EX(a0) ;and incr exponent
225: scc_clr:
226: tst.l d0 ;test for rs = 0
227: bne.b sgl_done
228: andi.w #$fe00,LOCAL_HI+2(a0) ;clear the l-bit
229: sgl_done:
230: andi.l #$ffffff00,LOCAL_HI(a0) ;truncate bits beyond sgl limit
231: clr.l LOCAL_LO(a0) ;clear d2
232: rts
233:
234: *
235: * ADD EXTENDED
236: *
237: add_ext:
238: addq.l #1,LOCAL_LO(a0) ;add 1 to l-bit
239: bcc.b xcc_clr ;test for carry out
240: addq.l #1,LOCAL_HI(a0) ;propogate carry
241: bcc.b xcc_clr
242: roxr.w LOCAL_HI(a0) ;mant is 0 so restore v-bit
243: roxr.w LOCAL_HI+2(a0) ;mant is 0 so restore v-bit
244: roxr.w LOCAL_LO(a0)
245: roxr.w LOCAL_LO+2(a0)
246: add.w #$1,LOCAL_EX(a0) ;and inc exp
247: xcc_clr:
248: tst.l d0 ;test rs = 0
249: bne.b add_ext_done
250: andi.b #$fe,LOCAL_LO+3(a0) ;clear the l bit
251: add_ext_done:
252: rts
253: *
254: * ADD DOUBLE
255: *
256: add_dbl:
257: add.l #ad_1_dbl,LOCAL_LO(a0)
258: bcc.b dcc_clr
259: addq.l #1,LOCAL_HI(a0) ;propogate carry
260: bcc.b dcc_clr
261: roxr.w LOCAL_HI(a0) ;mant is 0 so restore v-bit
262: roxr.w LOCAL_HI+2(a0) ;mant is 0 so restore v-bit
263: roxr.w LOCAL_LO(a0)
264: roxr.w LOCAL_LO+2(a0)
265: add.w #$1,LOCAL_EX(a0) ;incr exponent
266: dcc_clr:
267: tst.l d0 ;test for rs = 0
268: bne.b dbl_done
269: andi.w #$f000,LOCAL_LO+2(a0) ;clear the l-bit
270:
271: dbl_done:
272: andi.l #$fffff800,LOCAL_LO(a0) ;truncate bits beyond dbl limit
273: rts
274:
275: error:
276: rts
277: *
278: * Truncate all other bits
279: *
280: trunct:
281: dc.l end_rnd
282: dc.l sgl_done
283: dc.l dbl_done
284: dc.l dbl_done
285:
286: truncate:
287: lea trunct,a1
288: move.l (a1,d1.w*4),a1
289: jmp (a1)
290:
291: end_rnd:
292: rts
293:
294: *
295: * NORMALIZE
296: *
297: * These routines (nrm_zero & nrm_set) normalize the unnorm. This
298: * is done by shifting the mantissa left while decrementing the
299: * exponent.
300: *
301: * NRM_SET shifts and decrements until there is a 1 set in the integer
302: * bit of the mantissa (msb in d1).
303: *
304: * NRM_ZERO shifts and decrements until there is a 1 set in the integer
305: * bit of the mantissa (msb in d1) unless this would mean the exponent
306: * would go less than 0. In that case the number becomes a denorm - the
307: * exponent (d0) is set to 0 and the mantissa (d1 & d2) is not
308: * normalized.
309: *
310: * Note that both routines have been optimized (for the worst case) and
311: * therefore do not have the easy to follow decrement/shift loop.
312: *
313: * NRM_ZERO
314: *
315: * Distance to first 1 bit in mantissa = X
316: * Distance to 0 from exponent = Y
317: * If X < Y
318: * Then
319: * nrm_set
320: * Else
321: * shift mantissa by Y
322: * set exponent = 0
323: *
324: *input:
325: * FP_SCR1 = exponent, ms mantissa part, ls mantissa part
326: *output:
327: * L_SCR1{4} = fpte15 or ete15 bit
328: *
329: xdef nrm_zero
330: nrm_zero:
331: move.w LOCAL_EX(a0),d0
332: cmp.w #64,d0 ;see if exp > 64
333: bmi.b d0_less
334: bsr nrm_set ;exp > 64 so exp won't exceed 0
335: rts
336: d0_less:
337: movem.l d2/d3/d5/d6,-(a7)
338: move.l LOCAL_HI(a0),d1
339: move.l LOCAL_LO(a0),d2
340:
341: bfffo d1{0:32},d3 ;get the distance to the first 1
342: * ;in ms mant
343: beq.b ms_clr ;branch if no bits were set
344: cmp.w d3,d0 ;of X>Y
345: bmi.b greater ;then exp will go past 0 (neg) if
346: * ;it is just shifted
347: bsr nrm_set ;else exp won't go past 0
348: movem.l (a7)+,d2/d3/d5/d6
349: rts
350: greater:
351: move.l d2,d6 ;save ls mant in d6
352: lsl.l d0,d2 ;shift ls mant by count
353: lsl.l d0,d1 ;shift ms mant by count
354: move.l #32,d5
355: sub.l d0,d5 ;make op a denorm by shifting bits
356: lsr.l d5,d6 ;by the number in the exp, then
357: * ;set exp = 0.
358: or.l d6,d1 ;shift the ls mant bits into the ms mant
359: clr.l d0 ;same as if decremented exp to 0
360: * ;while shifting
361: move.w d0,LOCAL_EX(a0)
362: move.l d1,LOCAL_HI(a0)
363: move.l d2,LOCAL_LO(a0)
364: movem.l (a7)+,d2/d3/d5/d6
365: rts
366: ms_clr:
367: bfffo d2{0:32},d3 ;check if any bits set in ls mant
368: beq.b all_clr ;branch if none set
369: add.w #32,d3
370: cmp.w d3,d0 ;if X>Y
371: bmi.b greater ;then branch
372: bsr nrm_set ;else exp won't go past 0
373: movem.l (a7)+,d2/d3/d5/d6
374: rts
375: all_clr:
376: clr.w LOCAL_EX(a0) ;no mantissa bits set. Set exp = 0.
377: movem.l (a7)+,d2/d3/d5/d6
378: rts
379: *
380: * NRM_SET
381: *
382: xdef nrm_set
383: nrm_set:
384: move.l d7,-(a7)
385: bfffo LOCAL_HI(a0){0:32},d7 ;find first 1 in ms mant to d7)
386: beq.b lower ;branch if ms mant is all 0's
387:
388: move.l d6,-(a7)
389:
390: sub.w d7,LOCAL_EX(a0) ;sub exponent by count
391: move.l LOCAL_HI(a0),d0 ;d0 has ms mant
392: move.l LOCAL_LO(a0),d1 ;d1 has ls mant
393:
394: lsl.l d7,d0 ;shift first 1 to j bit position
395: move.l d1,d6 ;copy ls mant into d6
396: lsl.l d7,d6 ;shift ls mant by count
397: move.l d6,LOCAL_LO(a0) ;store ls mant into memory
398: moveq.l #32,d6
399: sub.l d7,d6 ;continue shift
400: lsr.l d6,d1 ;shift off all bits but those that will
401: * ;be shifted into ms mant
402: or.l d1,d0 ;shift the ls mant bits into the ms mant
403: move.l d0,LOCAL_HI(a0) ;store ms mant into memory
404: movem.l (a7)+,d7/d6 ;restore registers
405: rts
406:
407: *
408: * We get here if ms mant was = 0, and we assume ls mant has bits
409: * set (otherwise this would have been tagged a zero not a denorm).
410: *
411: lower:
412: move.w LOCAL_EX(a0),d0 ;d0 has exponent
413: move.l LOCAL_LO(a0),d1 ;d1 has ls mant
414: sub.w #32,d0 ;account for ms mant being all zeros
415: bfffo d1{0:32},d7 ;find first 1 in ls mant to d7)
416: sub.w d7,d0 ;subtract shift count from exp
417: lsl.l d7,d1 ;shift first 1 to integer bit in ms mant
418: move.w d0,LOCAL_EX(a0) ;store ms mant
419: move.l d1,LOCAL_HI(a0) ;store exp
420: clr.l LOCAL_LO(a0) ;clear ls mant
421: move.l (a7)+,d7
422: rts
423: *
424: * denorm --- denormalize an intermediate result
425: *
426: * Used by underflow.
427: *
428: * Input:
429: * a0 points to the operand to be denormalized
430: * (in the internal extended format)
431: *
432: * d0: rounding precision
433: * Output:
434: * a0 points to the denormalized result
435: * (in the internal extended format)
436: *
437: * d0 is guard,round,sticky
438: *
439: * d0 comes into this routine with the rounding precision. It
440: * is then loaded with the denormalized exponent threshold for the
441: * rounding precision.
442: *
443:
444: xdef denorm
445: denorm:
446: btst.b #6,LOCAL_EX(a0) ;check for exponents between $7fff-$4000
447: beq.b no_sgn_ext
448: bset.b #7,LOCAL_EX(a0) ;sign extend if it is so
449: no_sgn_ext:
450:
451: tst.b d0 ;if 0 then extended precision
452: bne.b not_ext ;else branch
453:
454: clr.l d1 ;load d1 with ext threshold
455: clr.l d0 ;clear the sticky flag
456: bsr dnrm_lp ;denormalize the number
457: tst.b d1 ;check for inex
458: beq.w no_inex ;if clr, no inex
459: bra.b dnrm_inex ;if set, set inex
460:
461: not_ext:
462: cmpi.l #1,d0 ;if 1 then single precision
463: beq.b load_sgl ;else must be 2, double prec
464:
465: load_dbl:
466: move.w #dbl_thresh,d1 ;put copy of threshold in d1
467: move.l d1,d0 ;copy d1 into d0
468: sub.w LOCAL_EX(a0),d0 ;diff = threshold - exp
469: cmp.w #67,d0 ;if diff > 67 (mant + grs bits)
470: bpl.b chk_stky ;then branch (all bits would be
471: * ; shifted off in denorm routine)
472: clr.l d0 ;else clear the sticky flag
473: bsr dnrm_lp ;denormalize the number
474: tst.b d1 ;check flag
475: beq.b no_inex ;if clr, no inex
476: bra.b dnrm_inex ;if set, set inex
477:
478: load_sgl:
479: move.w #sgl_thresh,d1 ;put copy of threshold in d1
480: move.l d1,d0 ;copy d1 into d0
481: sub.w LOCAL_EX(a0),d0 ;diff = threshold - exp
482: cmp.w #67,d0 ;if diff > 67 (mant + grs bits)
483: bpl.b chk_stky ;then branch (all bits would be
484: * ; shifted off in denorm routine)
485: clr.l d0 ;else clear the sticky flag
486: bsr dnrm_lp ;denormalize the number
487: tst.b d1 ;check flag
488: beq.b no_inex ;if clr, no inex
489: bra.b dnrm_inex ;if set, set inex
490:
491: chk_stky:
492: tst.l LOCAL_HI(a0) ;check for any bits set
493: bne.b set_stky
494: tst.l LOCAL_LO(a0) ;check for any bits set
495: bne.b set_stky
496: bra.b clr_mant
497: set_stky:
498: or.l #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex
499: move.l #$20000000,d0 ;set sticky bit in return value
500: clr_mant:
501: move.w d1,LOCAL_EX(a0) ;load exp with threshold
502: clr.l LOCAL_HI(a0) ;set d1 = 0 (ms mantissa)
503: clr.l LOCAL_LO(a0) ;set d2 = 0 (ms mantissa)
504: rts
505: dnrm_inex:
506: or.l #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex
507: no_inex:
508: rts
509:
510: *
511: * dnrm_lp --- normalize exponent/mantissa to specified threshold
512: *
513: * Input:
514: * a0 points to the operand to be denormalized
515: * d0{31:29} initial guard,round,sticky
516: * d1{15:0} denormalization threshold
517: * Output:
518: * a0 points to the denormalized operand
519: * d0{31:29} final guard,round,sticky
520: * d1.b inexact flag: all ones means inexact result
521: *
522: * The LOCAL_LO and LOCAL_GRS parts of the value are copied to FP_SCR2
523: * so that bfext can be used to extract the new low part of the mantissa.
524: * Dnrm_lp can be called with a0 pointing to ETEMP or WBTEMP and there
525: * is no LOCAL_GRS scratch word following it on the fsave frame.
526: *
527: xdef dnrm_lp
528: dnrm_lp:
529: move.l d2,-(sp) ;save d2 for temp use
530: btst.b #E3,E_BYTE(a6) ;test for type E3 exception
531: beq.b not_E3 ;not type E3 exception
532: bfextu WBTEMP_GRS(a6){6:3},d2 ;extract guard,round, sticky bit
533: move.l #29,d0
534: lsl.l d0,d2 ;shift g,r,s to their postions
535: move.l d2,d0
536: not_E3:
537: move.l (sp)+,d2 ;restore d2
538: move.l LOCAL_LO(a0),FP_SCR2+LOCAL_LO(a6)
539: move.l d0,FP_SCR2+LOCAL_GRS(a6)
540: move.l d1,d0 ;copy the denorm threshold
541: sub.w LOCAL_EX(a0),d1 ;d1 = threshold - uns exponent
542: ble.b no_lp ;d1 <= 0
543: cmp.w #32,d1
544: blt.b case_1 ;0 = d1 < 32
545: cmp.w #64,d1
546: blt.b case_2 ;32 <= d1 < 64
547: bra.w case_3 ;d1 >= 64
548: *
549: * No normalization necessary
550: *
551: no_lp:
552: clr.b d1 ;set no inex2 reported
553: move.l FP_SCR2+LOCAL_GRS(a6),d0 ;restore original g,r,s
554: rts
555: *
556: * case (0<d1<32)
557: *
558: case_1:
559: move.l d2,-(sp)
560: move.w d0,LOCAL_EX(a0) ;exponent = denorm threshold
561: move.l #32,d0
562: sub.w d1,d0 ;d0 = 32 - d1
563: bfextu LOCAL_EX(a0){d0:32},d2
564: bfextu d2{d1:d0},d2 ;d2 = new LOCAL_HI
565: bfextu LOCAL_HI(a0){d0:32},d1 ;d1 = new LOCAL_LO
566: bfextu FP_SCR2+LOCAL_LO(a6){d0:32},d0 ;d0 = new G,R,S
567: move.l d2,LOCAL_HI(a0) ;store new LOCAL_HI
568: move.l d1,LOCAL_LO(a0) ;store new LOCAL_LO
569: clr.b d1
570: bftst d0{2:30}
571: beq.b c1nstky
572: bset.l #rnd_stky_bit,d0
573: st.b d1
574: c1nstky:
575: move.l FP_SCR2+LOCAL_GRS(a6),d2 ;restore original g,r,s
576: andi.l #$e0000000,d2 ;clear all but G,R,S
577: tst.l d2 ;test if original G,R,S are clear
578: beq.b grs_clear
579: or.l #$20000000,d0 ;set sticky bit in d0
580: grs_clear:
581: andi.l #$e0000000,d0 ;clear all but G,R,S
582: move.l (sp)+,d2
583: rts
584: *
585: * case (32<=d1<64)
586: *
587: case_2:
588: move.l d2,-(sp)
589: move.w d0,LOCAL_EX(a0) ;unsigned exponent = threshold
590: sub.w #32,d1 ;d1 now between 0 and 32
591: move.l #32,d0
592: sub.w d1,d0 ;d0 = 32 - d1
593: bfextu LOCAL_EX(a0){d0:32},d2
594: bfextu d2{d1:d0},d2 ;d2 = new LOCAL_LO
595: bfextu LOCAL_HI(a0){d0:32},d1 ;d1 = new G,R,S
596: bftst d1{2:30}
597: bne.b c2_sstky ;bra if sticky bit to be set
598: bftst FP_SCR2+LOCAL_LO(a6){d0:32}
599: bne.b c2_sstky ;bra if sticky bit to be set
600: move.l d1,d0
601: clr.b d1
602: bra.b end_c2
603: c2_sstky:
604: move.l d1,d0
605: bset.l #rnd_stky_bit,d0
606: st.b d1
607: end_c2:
608: clr.l LOCAL_HI(a0) ;store LOCAL_HI = 0
609: move.l d2,LOCAL_LO(a0) ;store LOCAL_LO
610: move.l FP_SCR2+LOCAL_GRS(a6),d2 ;restore original g,r,s
611: andi.l #$e0000000,d2 ;clear all but G,R,S
612: tst.l d2 ;test if original G,R,S are clear
613: beq.b clear_grs
614: or.l #$20000000,d0 ;set sticky bit in d0
615: clear_grs:
616: andi.l #$e0000000,d0 ;get rid of all but G,R,S
617: move.l (sp)+,d2
618: rts
619: *
620: * d1 >= 64 Force the exponent to be the denorm threshold with the
621: * correct sign.
622: *
623: case_3:
624: move.w d0,LOCAL_EX(a0)
625: tst.w LOCAL_SGN(a0)
626: bge.b c3con
627: c3neg:
628: or.l #$80000000,LOCAL_EX(a0)
629: c3con:
630: cmp.w #64,d1
631: beq.b sixty_four
632: cmp.w #65,d1
633: beq.b sixty_five
634: *
635: * Shift value is out of range. Set d1 for inex2 flag and
636: * return a zero with the given threshold.
637: *
638: clr.l LOCAL_HI(a0)
639: clr.l LOCAL_LO(a0)
640: move.l #$20000000,d0
641: st.b d1
642: rts
643:
644: sixty_four:
645: move.l LOCAL_HI(a0),d0
646: bfextu d0{2:30},d1
647: andi.l #$c0000000,d0
648: bra.b c3com
649:
650: sixty_five:
651: move.l LOCAL_HI(a0),d0
652: bfextu d0{1:31},d1
653: andi.l #$80000000,d0
654: lsr.l #1,d0 ;shift high bit into R bit
655:
656: c3com:
657: tst.l d1
658: bne.b c3ssticky
659: tst.l LOCAL_LO(a0)
660: bne.b c3ssticky
661: tst.b FP_SCR2+LOCAL_GRS(a6)
662: bne.b c3ssticky
663: clr.b d1
664: bra.b c3end
665:
666: c3ssticky:
667: bset.l #rnd_stky_bit,d0
668: st.b d1
669: c3end:
670: clr.l LOCAL_HI(a0)
671: clr.l LOCAL_LO(a0)
672: rts
673:
674: end
CVSweb