Annotation of sys/arch/m68k/fpsp/scale.sa, Revision 1.1.1.1
1.1 nbrk 1: * $OpenBSD: scale.sa,v 1.2 1996/05/29 21:05:36 niklas Exp $
2: * $NetBSD: scale.sa,v 1.3 1994/10/26 07:49:34 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: * scale.sa 3.3 7/30/91
36: *
37: * The entry point sSCALE computes the destination operand
38: * scaled by the source operand. If the absoulute value of
39: * the source operand is (>= 2^14) an overflow or underflow
40: * is returned.
41: *
42: * The entry point sscale is called from do_func to emulate
43: * the fscale unimplemented instruction.
44: *
45: * Input: Double-extended destination operand in FPTEMP,
46: * double-extended source operand in ETEMP.
47: *
48: * Output: The function returns scale(X,Y) to fp0.
49: *
50: * Modifies: fp0.
51: *
52: * Algorithm:
53: *
54:
55: SCALE IDNT 2,1 Motorola 040 Floating Point Software Package
56:
57: section 8
58:
59: include fpsp.h
60:
61: xref t_ovfl2
62: xref t_unfl
63: xref round
64: xref t_resdnrm
65:
66: SRC_BNDS dc.w $3fff,$400c
67:
68: *
69: * This entry point is used by the unimplemented instruction exception
70: * handler.
71: *
72: *
73: *
74: * FSCALE
75: *
76: xdef sscale
77: sscale:
78: fmove.l #0,fpcr ;clr user enabled exc
79: clr.l d1
80: move.w FPTEMP(a6),d1 ;get dest exponent
81: smi L_SCR1(a6) ;use L_SCR1 to hold sign
82: andi.l #$7fff,d1 ;strip sign
83: move.w ETEMP(a6),d0 ;check src bounds
84: andi.w #$7fff,d0 ;clr sign bit
85: cmp2.w SRC_BNDS,d0
86: bcc.b src_in
87: cmpi.w #$400c,d0 ;test for too large
88: bge.w src_out
89: *
90: * The source input is below 1, so we check for denormalized numbers
91: * and set unfl.
92: *
93: src_small:
94: move.b DTAG(a6),d0
95: andi.b #$e0,d0
96: tst.b d0
97: beq.b no_denorm
98: st STORE_FLG(a6) ;dest already contains result
99: or.l #unfl_mask,USER_FPSR(a6) ;set UNFL
100: den_done:
101: lea.l FPTEMP(a6),a0
102: bra t_resdnrm
103: no_denorm:
104: fmove.l USER_FPCR(a6),FPCR
105: fmove.x FPTEMP(a6),fp0 ;simply return dest
106: rts
107:
108:
109: *
110: * Source is within 2^14 range. To perform the int operation,
111: * move it to d0.
112: *
113: src_in:
114: fmove.x ETEMP(a6),fp0 ;move in src for int
115: fmove.l #rz_mode,fpcr ;force rz for src conversion
116: fmove.l fp0,d0 ;int src to d0
117: fmove.l #0,FPSR ;clr status from above
118: tst.w ETEMP(a6) ;check src sign
119: blt.w src_neg
120: *
121: * Source is positive. Add the src to the dest exponent.
122: * The result can be denormalized, if src = 0, or overflow,
123: * if the result of the add sets a bit in the upper word.
124: *
125: src_pos:
126: tst.w d1 ;check for denorm
127: beq.w dst_dnrm
128: add.l d0,d1 ;add src to dest exp
129: beq.b denorm ;if zero, result is denorm
130: cmpi.l #$7fff,d1 ;test for overflow
131: bge.b ovfl
132: tst.b L_SCR1(a6)
133: beq.b spos_pos
134: or.w #$8000,d1
135: spos_pos:
136: move.w d1,FPTEMP(a6) ;result in FPTEMP
137: fmove.l USER_FPCR(a6),FPCR
138: fmove.x FPTEMP(a6),fp0 ;write result to fp0
139: rts
140: ovfl:
141: tst.b L_SCR1(a6)
142: beq.b sovl_pos
143: or.w #$8000,d1
144: sovl_pos:
145: move.w FPTEMP(a6),ETEMP(a6) ;result in ETEMP
146: move.l FPTEMP_HI(a6),ETEMP_HI(a6)
147: move.l FPTEMP_LO(a6),ETEMP_LO(a6)
148: bra t_ovfl2
149:
150: denorm:
151: tst.b L_SCR1(a6)
152: beq.b den_pos
153: or.w #$8000,d1
154: den_pos:
155: tst.l FPTEMP_HI(a6) ;check j bit
156: blt.b nden_exit ;if set, not denorm
157: move.w d1,ETEMP(a6) ;input expected in ETEMP
158: move.l FPTEMP_HI(a6),ETEMP_HI(a6)
159: move.l FPTEMP_LO(a6),ETEMP_LO(a6)
160: or.l #unfl_bit,USER_FPSR(a6) ;set unfl
161: lea.l ETEMP(a6),a0
162: bra t_resdnrm
163: nden_exit:
164: move.w d1,FPTEMP(a6) ;result in FPTEMP
165: fmove.l USER_FPCR(a6),FPCR
166: fmove.x FPTEMP(a6),fp0 ;write result to fp0
167: rts
168:
169: *
170: * Source is negative. Add the src to the dest exponent.
171: * (The result exponent will be reduced). The result can be
172: * denormalized.
173: *
174: src_neg:
175: add.l d0,d1 ;add src to dest
176: beq.b denorm ;if zero, result is denorm
177: blt.b fix_dnrm ;if negative, result is
178: * ;needing denormalization
179: tst.b L_SCR1(a6)
180: beq.b sneg_pos
181: or.w #$8000,d1
182: sneg_pos:
183: move.w d1,FPTEMP(a6) ;result in FPTEMP
184: fmove.l USER_FPCR(a6),FPCR
185: fmove.x FPTEMP(a6),fp0 ;write result to fp0
186: rts
187:
188:
189: *
190: * The result exponent is below denorm value. Test for catastrophic
191: * underflow and force zero if true. If not, try to shift the
192: * mantissa right until a zero exponent exists.
193: *
194: fix_dnrm:
195: cmpi.w #$ffc0,d1 ;lower bound for normalization
196: blt.w fix_unfl ;if lower, catastrophic unfl
197: move.w d1,d0 ;use d0 for exp
198: move.l d2,-(a7) ;free d2 for norm
199: move.l FPTEMP_HI(a6),d1
200: move.l FPTEMP_LO(a6),d2
201: clr.l L_SCR2(a6)
202: fix_loop:
203: add.w #1,d0 ;drive d0 to 0
204: lsr.l #1,d1 ;while shifting the
205: roxr.l #1,d2 ;mantissa to the right
206: bcc.b no_carry
207: st L_SCR2(a6) ;use L_SCR2 to capture inex
208: no_carry:
209: tst.w d0 ;it is finished when
210: blt.b fix_loop ;d0 is zero or the mantissa
211: tst.b L_SCR2(a6)
212: beq.b tst_zero
213: or.l #unfl_inx_mask,USER_FPSR(a6)
214: * ;set unfl, aunfl, ainex
215: *
216: * Test for zero. If zero, simply use fmove to return +/- zero
217: * to the fpu.
218: *
219: tst_zero:
220: clr.w FPTEMP_EX(a6)
221: tst.b L_SCR1(a6) ;test for sign
222: beq.b tst_con
223: or.w #$8000,FPTEMP_EX(a6) ;set sign bit
224: tst_con:
225: move.l d1,FPTEMP_HI(a6)
226: move.l d2,FPTEMP_LO(a6)
227: move.l (a7)+,d2
228: tst.l d1
229: bne.b not_zero
230: tst.l FPTEMP_LO(a6)
231: bne.b not_zero
232: *
233: * Result is zero. Check for rounding mode to set lsb. If the
234: * mode is rp, and the zero is positive, return smallest denorm.
235: * If the mode is rm, and the zero is negative, return smallest
236: * negative denorm.
237: *
238: btst.b #5,FPCR_MODE(a6) ;test if rm or rp
239: beq.b no_dir
240: btst.b #4,FPCR_MODE(a6) ;check which one
241: beq.b zer_rm
242: zer_rp:
243: tst.b L_SCR1(a6) ;check sign
244: bne.b no_dir ;if set, neg op, no inc
245: move.l #1,FPTEMP_LO(a6) ;set lsb
246: bra.b sm_dnrm
247: zer_rm:
248: tst.b L_SCR1(a6) ;check sign
249: beq.b no_dir ;if clr, neg op, no inc
250: move.l #1,FPTEMP_LO(a6) ;set lsb
251: or.l #neg_mask,USER_FPSR(a6) ;set N
252: bra.b sm_dnrm
253: no_dir:
254: fmove.l USER_FPCR(a6),FPCR
255: fmove.x FPTEMP(a6),fp0 ;use fmove to set cc's
256: rts
257:
258: *
259: * The rounding mode changed the zero to a smallest denorm. Call
260: * t_resdnrm with exceptional operand in ETEMP.
261: *
262: sm_dnrm:
263: move.l FPTEMP_EX(a6),ETEMP_EX(a6)
264: move.l FPTEMP_HI(a6),ETEMP_HI(a6)
265: move.l FPTEMP_LO(a6),ETEMP_LO(a6)
266: lea.l ETEMP(a6),a0
267: bra t_resdnrm
268:
269: *
270: * Result is still denormalized.
271: *
272: not_zero:
273: or.l #unfl_mask,USER_FPSR(a6) ;set unfl
274: tst.b L_SCR1(a6) ;check for sign
275: beq.b fix_exit
276: or.l #neg_mask,USER_FPSR(a6) ;set N
277: fix_exit:
278: bra.b sm_dnrm
279:
280:
281: *
282: * The result has underflowed to zero. Return zero and set
283: * unfl, aunfl, and ainex.
284: *
285: fix_unfl:
286: or.l #unfl_inx_mask,USER_FPSR(a6)
287: btst.b #5,FPCR_MODE(a6) ;test if rm or rp
288: beq.b no_dir2
289: btst.b #4,FPCR_MODE(a6) ;check which one
290: beq.b zer_rm2
291: zer_rp2:
292: tst.b L_SCR1(a6) ;check sign
293: bne.b no_dir2 ;if set, neg op, no inc
294: clr.l FPTEMP_EX(a6)
295: clr.l FPTEMP_HI(a6)
296: move.l #1,FPTEMP_LO(a6) ;set lsb
297: bra.b sm_dnrm ;return smallest denorm
298: zer_rm2:
299: tst.b L_SCR1(a6) ;check sign
300: beq.b no_dir2 ;if clr, neg op, no inc
301: move.w #$8000,FPTEMP_EX(a6)
302: clr.l FPTEMP_HI(a6)
303: move.l #1,FPTEMP_LO(a6) ;set lsb
304: or.l #neg_mask,USER_FPSR(a6) ;set N
305: bra.w sm_dnrm ;return smallest denorm
306:
307: no_dir2:
308: tst.b L_SCR1(a6)
309: bge.b pos_zero
310: neg_zero:
311: clr.l FP_SCR1(a6) ;clear the exceptional operand
312: clr.l FP_SCR1+4(a6) ;for gen_except.
313: clr.l FP_SCR1+8(a6)
314: fmove.s #:80000000,fp0
315: rts
316: pos_zero:
317: clr.l FP_SCR1(a6) ;clear the exceptional operand
318: clr.l FP_SCR1+4(a6) ;for gen_except.
319: clr.l FP_SCR1+8(a6)
320: fmove.s #:00000000,fp0
321: rts
322:
323: *
324: * The destination is a denormalized number. It must be handled
325: * by first shifting the bits in the mantissa until it is normalized,
326: * then adding the remainder of the source to the exponent.
327: *
328: dst_dnrm:
329: movem.l d2/d3,-(a7)
330: move.w FPTEMP_EX(a6),d1
331: move.l FPTEMP_HI(a6),d2
332: move.l FPTEMP_LO(a6),d3
333: dst_loop:
334: tst.l d2 ;test for normalized result
335: blt.b dst_norm ;exit loop if so
336: tst.l d0 ;otherwise, test shift count
337: beq.b dst_fin ;if zero, shifting is done
338: subq.l #1,d0 ;dec src
339: add.l d3,d3
340: addx.l d2,d2
341: bra.b dst_loop
342: *
343: * Destination became normalized. Simply add the remaining
344: * portion of the src to the exponent.
345: *
346: dst_norm:
347: add.w d0,d1 ;dst is normalized; add src
348: tst.b L_SCR1(a6)
349: beq.b dnrm_pos
350: or.w #$8000,d1
351: dnrm_pos:
352: movem.w d1,FPTEMP_EX(a6)
353: movem.l d2,FPTEMP_HI(a6)
354: movem.l d3,FPTEMP_LO(a6)
355: fmove.l USER_FPCR(a6),FPCR
356: fmove.x FPTEMP(a6),fp0
357: movem.l (a7)+,d2/d3
358: rts
359:
360: *
361: * Destination remained denormalized. Call t_excdnrm with
362: * exceptional operand in ETEMP.
363: *
364: dst_fin:
365: tst.b L_SCR1(a6) ;check for sign
366: beq.b dst_exit
367: or.l #neg_mask,USER_FPSR(a6) ;set N
368: or.w #$8000,d1
369: dst_exit:
370: movem.w d1,ETEMP_EX(a6)
371: movem.l d2,ETEMP_HI(a6)
372: movem.l d3,ETEMP_LO(a6)
373: or.l #unfl_mask,USER_FPSR(a6) ;set unfl
374: movem.l (a7)+,d2/d3
375: lea.l ETEMP(a6),a0
376: bra t_resdnrm
377:
378: *
379: * Source is outside of 2^14 range. Test the sign and branch
380: * to the appropriate exception handler.
381: *
382: src_out:
383: tst.b L_SCR1(a6)
384: beq.b scro_pos
385: or.w #$8000,d1
386: scro_pos:
387: move.l FPTEMP_HI(a6),ETEMP_HI(a6)
388: move.l FPTEMP_LO(a6),ETEMP_LO(a6)
389: tst.w ETEMP(a6)
390: blt.b res_neg
391: res_pos:
392: move.w d1,ETEMP(a6) ;result in ETEMP
393: bra t_ovfl2
394: res_neg:
395: move.w d1,ETEMP(a6) ;result in ETEMP
396: lea.l ETEMP(a6),a0
397: bra t_unfl
398: end
CVSweb