bindec.sa revision 1.2 1 1.1 mycroft * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
2 1.1 mycroft * M68000 Hi-Performance Microprocessor Division
3 1.1 mycroft * M68040 Software Package
4 1.1 mycroft *
5 1.1 mycroft * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
6 1.1 mycroft * All rights reserved.
7 1.1 mycroft *
8 1.1 mycroft * THE SOFTWARE is provided on an "AS IS" basis and without warranty.
9 1.1 mycroft * To the maximum extent permitted by applicable law,
10 1.1 mycroft * MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
11 1.1 mycroft * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
12 1.1 mycroft * PARTICULAR PURPOSE and any warranty against infringement with
13 1.1 mycroft * regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
14 1.1 mycroft * and any accompanying written materials.
15 1.1 mycroft *
16 1.1 mycroft * To the maximum extent permitted by applicable law,
17 1.1 mycroft * IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
18 1.1 mycroft * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
19 1.1 mycroft * PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
20 1.1 mycroft * OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
21 1.1 mycroft * SOFTWARE. Motorola assumes no responsibility for the maintenance
22 1.1 mycroft * and support of the SOFTWARE.
23 1.1 mycroft *
24 1.1 mycroft * You are hereby granted a copyright license to use, modify, and
25 1.1 mycroft * distribute the SOFTWARE so long as this entire notice is retained
26 1.1 mycroft * without alteration in any modified and/or redistributed versions,
27 1.1 mycroft * and that such modified versions are clearly identified as such.
28 1.1 mycroft * No licenses are granted by implication, estoppel or otherwise
29 1.1 mycroft * under any patents or trademarks of Motorola, Inc.
30 1.1 mycroft
31 1.1 mycroft *
32 1.1 mycroft * bindec.sa 3.4 1/3/91
33 1.1 mycroft *
34 1.1 mycroft * bindec
35 1.1 mycroft *
36 1.1 mycroft * Description:
37 1.1 mycroft * Converts an input in extended precision format
38 1.1 mycroft * to bcd format.
39 1.1 mycroft *
40 1.1 mycroft * Input:
41 1.1 mycroft * a0 points to the input extended precision value
42 1.1 mycroft * value in memory; d0 contains the k-factor sign-extended
43 1.1 mycroft * to 32-bits. The input may be either normalized,
44 1.1 mycroft * unnormalized, or denormalized.
45 1.1 mycroft *
46 1.1 mycroft * Output: result in the FP_SCR1 space on the stack.
47 1.1 mycroft *
48 1.1 mycroft * Saves and Modifies: D2-D7,A2,FP2
49 1.1 mycroft *
50 1.1 mycroft * Algorithm:
51 1.1 mycroft *
52 1.1 mycroft * A1. Set RM and size ext; Set SIGMA = sign of input.
53 1.1 mycroft * The k-factor is saved for use in d7. Clear the
54 1.1 mycroft * BINDEC_FLG for separating normalized/denormalized
55 1.1 mycroft * input. If input is unnormalized or denormalized,
56 1.1 mycroft * normalize it.
57 1.1 mycroft *
58 1.1 mycroft * A2. Set X = abs(input).
59 1.1 mycroft *
60 1.1 mycroft * A3. Compute ILOG.
61 1.1 mycroft * ILOG is the log base 10 of the input value. It is
62 1.1 mycroft * approximated by adding e + 0.f when the original
63 1.1 mycroft * value is viewed as 2^^e * 1.f in extended precision.
64 1.1 mycroft * This value is stored in d6.
65 1.1 mycroft *
66 1.1 mycroft * A4. Clr INEX bit.
67 1.1 mycroft * The operation in A3 above may have set INEX2.
68 1.1 mycroft *
69 1.1 mycroft * A5. Set ICTR = 0;
70 1.1 mycroft * ICTR is a flag used in A13. It must be set before the
71 1.1 mycroft * loop entry A6.
72 1.1 mycroft *
73 1.1 mycroft * A6. Calculate LEN.
74 1.1 mycroft * LEN is the number of digits to be displayed. The
75 1.1 mycroft * k-factor can dictate either the total number of digits,
76 1.1 mycroft * if it is a positive number, or the number of digits
77 1.1 mycroft * after the decimal point which are to be included as
78 1.1 mycroft * significant. See the 68882 manual for examples.
79 1.1 mycroft * If LEN is computed to be greater than 17, set OPERR in
80 1.1 mycroft * USER_FPSR. LEN is stored in d4.
81 1.1 mycroft *
82 1.1 mycroft * A7. Calculate SCALE.
83 1.1 mycroft * SCALE is equal to 10^ISCALE, where ISCALE is the number
84 1.1 mycroft * of decimal places needed to insure LEN integer digits
85 1.1 mycroft * in the output before conversion to bcd. LAMBDA is the
86 1.1 mycroft * sign of ISCALE, used in A9. Fp1 contains
87 1.1 mycroft * 10^^(abs(ISCALE)) using a rounding mode which is a
88 1.1 mycroft * function of the original rounding mode and the signs
89 1.1 mycroft * of ISCALE and X. A table is given in the code.
90 1.1 mycroft *
91 1.1 mycroft * A8. Clr INEX; Force RZ.
92 1.1 mycroft * The operation in A3 above may have set INEX2.
93 1.1 mycroft * RZ mode is forced for the scaling operation to insure
94 1.1 mycroft * only one rounding error. The grs bits are collected in
95 1.1 mycroft * the INEX flag for use in A10.
96 1.1 mycroft *
97 1.1 mycroft * A9. Scale X -> Y.
98 1.1 mycroft * The mantissa is scaled to the desired number of
99 1.1 mycroft * significant digits. The excess digits are collected
100 1.1 mycroft * in INEX2.
101 1.1 mycroft *
102 1.1 mycroft * A10. Or in INEX.
103 1.1 mycroft * If INEX is set, round error occured. This is
104 1.1 mycroft * compensated for by 'or-ing' in the INEX2 flag to
105 1.1 mycroft * the lsb of Y.
106 1.1 mycroft *
107 1.1 mycroft * A11. Restore original FPCR; set size ext.
108 1.1 mycroft * Perform FINT operation in the user's rounding mode.
109 1.1 mycroft * Keep the size to extended.
110 1.1 mycroft *
111 1.1 mycroft * A12. Calculate YINT = FINT(Y) according to user's rounding
112 1.1 mycroft * mode. The FPSP routine sintd0 is used. The output
113 1.1 mycroft * is in fp0.
114 1.1 mycroft *
115 1.1 mycroft * A13. Check for LEN digits.
116 1.1 mycroft * If the int operation results in more than LEN digits,
117 1.1 mycroft * or less than LEN -1 digits, adjust ILOG and repeat from
118 1.1 mycroft * A6. This test occurs only on the first pass. If the
119 1.1 mycroft * result is exactly 10^LEN, decrement ILOG and divide
120 1.1 mycroft * the mantissa by 10.
121 1.1 mycroft *
122 1.1 mycroft * A14. Convert the mantissa to bcd.
123 1.1 mycroft * The binstr routine is used to convert the LEN digit
124 1.1 mycroft * mantissa to bcd in memory. The input to binstr is
125 1.1 mycroft * to be a fraction; i.e. (mantissa)/10^LEN and adjusted
126 1.1 mycroft * such that the decimal point is to the left of bit 63.
127 1.1 mycroft * The bcd digits are stored in the correct position in
128 1.1 mycroft * the final string area in memory.
129 1.1 mycroft *
130 1.1 mycroft * A15. Convert the exponent to bcd.
131 1.1 mycroft * As in A14 above, the exp is converted to bcd and the
132 1.1 mycroft * digits are stored in the final string.
133 1.1 mycroft * Test the length of the final exponent string. If the
134 1.1 mycroft * length is 4, set operr.
135 1.1 mycroft *
136 1.1 mycroft * A16. Write sign bits to final string.
137 1.1 mycroft *
138 1.1 mycroft * Implementation Notes:
139 1.1 mycroft *
140 1.1 mycroft * The registers are used as follows:
141 1.1 mycroft *
142 1.1 mycroft * d0: scratch; LEN input to binstr
143 1.1 mycroft * d1: scratch
144 1.1 mycroft * d2: upper 32-bits of mantissa for binstr
145 1.1 mycroft * d3: scratch;lower 32-bits of mantissa for binstr
146 1.1 mycroft * d4: LEN
147 1.1 mycroft * d5: LAMBDA/ICTR
148 1.1 mycroft * d6: ILOG
149 1.1 mycroft * d7: k-factor
150 1.1 mycroft * a0: ptr for original operand/final result
151 1.1 mycroft * a1: scratch pointer
152 1.1 mycroft * a2: pointer to FP_X; abs(original value) in ext
153 1.1 mycroft * fp0: scratch
154 1.1 mycroft * fp1: scratch
155 1.1 mycroft * fp2: scratch
156 1.1 mycroft * F_SCR1:
157 1.1 mycroft * F_SCR2:
158 1.1 mycroft * L_SCR1:
159 1.1 mycroft * L_SCR2:
160 1.1 mycroft *
161 1.1 mycroft
162 1.1 mycroft BINDEC IDNT 2,1 Motorola 040 Floating Point Software Package
163 1.1 mycroft
164 1.1 mycroft include fpsp.h
165 1.1 mycroft
166 1.1 mycroft section 8
167 1.1 mycroft
168 1.1 mycroft * Constants in extended precision
169 1.1 mycroft LOG2 dc.l $3FFD0000,$9A209A84,$FBCFF798,$00000000
170 1.1 mycroft LOG2UP1 dc.l $3FFD0000,$9A209A84,$FBCFF799,$00000000
171 1.1 mycroft
172 1.1 mycroft * Constants in single precision
173 1.1 mycroft FONE dc.l $3F800000,$00000000,$00000000,$00000000
174 1.1 mycroft FTWO dc.l $40000000,$00000000,$00000000,$00000000
175 1.1 mycroft FTEN dc.l $41200000,$00000000,$00000000,$00000000
176 1.1 mycroft F4933 dc.l $459A2800,$00000000,$00000000,$00000000
177 1.1 mycroft
178 1.1 mycroft RBDTBL dc.b 0,0,0,0
179 1.1 mycroft dc.b 3,3,2,2
180 1.1 mycroft dc.b 3,2,2,3
181 1.1 mycroft dc.b 2,3,3,2
182 1.1 mycroft
183 1.1 mycroft xref binstr
184 1.1 mycroft xref sintdo
185 1.1 mycroft xref ptenrn,ptenrm,ptenrp
186 1.1 mycroft
187 1.1 mycroft xdef bindec
188 1.1 mycroft xdef sc_mul
189 1.1 mycroft bindec:
190 1.1 mycroft movem.l d2-d7/a2,-(a7)
191 1.1 mycroft fmovem.x fp0-fp2,-(a7)
192 1.1 mycroft
193 1.1 mycroft * A1. Set RM and size ext. Set SIGMA = sign input;
194 1.1 mycroft * The k-factor is saved for use in d7. Clear BINDEC_FLG for
195 1.1 mycroft * separating normalized/denormalized input. If the input
196 1.1 mycroft * is a denormalized number, set the BINDEC_FLG memory word
197 1.1 mycroft * to signal denorm. If the input is unnormalized, normalize
198 1.1 mycroft * the input and test for denormalized result.
199 1.1 mycroft *
200 1.1 mycroft fmove.l #rm_mode,FPCR ;set RM and ext
201 1.1 mycroft move.l (a0),L_SCR2(a6) ;save exponent for sign check
202 1.1 mycroft move.l d0,d7 ;move k-factor to d7
203 1.1 mycroft clr.b BINDEC_FLG(a6) ;clr norm/denorm flag
204 1.1 mycroft move.w STAG(a6),d0 ;get stag
205 1.1 mycroft andi.w #$e000,d0 ;isolate stag bits
206 1.1 mycroft beq A2_str ;if zero, input is norm
207 1.1 mycroft *
208 1.1 mycroft * Normalize the denorm
209 1.1 mycroft *
210 1.1 mycroft un_de_norm:
211 1.1 mycroft move.w (a0),d0
212 1.1 mycroft andi.w #$7fff,d0 ;strip sign of normalized exp
213 1.1 mycroft move.l 4(a0),d1
214 1.1 mycroft move.l 8(a0),d2
215 1.1 mycroft norm_loop:
216 1.1 mycroft sub.w #1,d0
217 1.2 mycroft add.l d2,d2
218 1.2 mycroft addx.l d1,d1
219 1.1 mycroft tst.l d1
220 1.1 mycroft bge.b norm_loop
221 1.1 mycroft *
222 1.1 mycroft * Test if the normalized input is denormalized
223 1.1 mycroft *
224 1.1 mycroft tst.w d0
225 1.1 mycroft bgt.b pos_exp ;if greater than zero, it is a norm
226 1.1 mycroft st BINDEC_FLG(a6) ;set flag for denorm
227 1.1 mycroft pos_exp:
228 1.1 mycroft andi.w #$7fff,d0 ;strip sign of normalized exp
229 1.1 mycroft move.w d0,(a0)
230 1.1 mycroft move.l d1,4(a0)
231 1.1 mycroft move.l d2,8(a0)
232 1.1 mycroft
233 1.1 mycroft * A2. Set X = abs(input).
234 1.1 mycroft *
235 1.1 mycroft A2_str:
236 1.1 mycroft move.l (a0),FP_SCR2(a6) ; move input to work space
237 1.1 mycroft move.l 4(a0),FP_SCR2+4(a6) ; move input to work space
238 1.1 mycroft move.l 8(a0),FP_SCR2+8(a6) ; move input to work space
239 1.1 mycroft andi.l #$7fffffff,FP_SCR2(a6) ;create abs(X)
240 1.1 mycroft
241 1.1 mycroft * A3. Compute ILOG.
242 1.1 mycroft * ILOG is the log base 10 of the input value. It is approx-
243 1.1 mycroft * imated by adding e + 0.f when the original value is viewed
244 1.1 mycroft * as 2^^e * 1.f in extended precision. This value is stored
245 1.1 mycroft * in d6.
246 1.1 mycroft *
247 1.1 mycroft * Register usage:
248 1.1 mycroft * Input/Output
249 1.1 mycroft * d0: k-factor/exponent
250 1.1 mycroft * d2: x/x
251 1.1 mycroft * d3: x/x
252 1.1 mycroft * d4: x/x
253 1.1 mycroft * d5: x/x
254 1.1 mycroft * d6: x/ILOG
255 1.1 mycroft * d7: k-factor/Unchanged
256 1.1 mycroft * a0: ptr for original operand/final result
257 1.1 mycroft * a1: x/x
258 1.1 mycroft * a2: x/x
259 1.1 mycroft * fp0: x/float(ILOG)
260 1.1 mycroft * fp1: x/x
261 1.1 mycroft * fp2: x/x
262 1.1 mycroft * F_SCR1:x/x
263 1.1 mycroft * F_SCR2:Abs(X)/Abs(X) with $3fff exponent
264 1.1 mycroft * L_SCR1:x/x
265 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
266 1.1 mycroft
267 1.1 mycroft tst.b BINDEC_FLG(a6) ;check for denorm
268 1.1 mycroft beq.b A3_cont ;if clr, continue with norm
269 1.1 mycroft move.l #-4933,d6 ;force ILOG = -4933
270 1.1 mycroft bra.b A4_str
271 1.1 mycroft A3_cont:
272 1.1 mycroft move.w FP_SCR2(a6),d0 ;move exp to d0
273 1.1 mycroft move.w #$3fff,FP_SCR2(a6) ;replace exponent with 0x3fff
274 1.1 mycroft fmove.x FP_SCR2(a6),fp0 ;now fp0 has 1.f
275 1.1 mycroft sub.w #$3fff,d0 ;strip off bias
276 1.1 mycroft fadd.w d0,fp0 ;add in exp
277 1.1 mycroft fsub.s FONE,fp0 ;subtract off 1.0
278 1.1 mycroft fbge.w pos_res ;if pos, branch
279 1.1 mycroft fmul.x LOG2UP1,fp0 ;if neg, mul by LOG2UP1
280 1.1 mycroft fmove.l fp0,d6 ;put ILOG in d6 as a lword
281 1.1 mycroft bra.b A4_str ;go move out ILOG
282 1.1 mycroft pos_res:
283 1.1 mycroft fmul.x LOG2,fp0 ;if pos, mul by LOG2
284 1.1 mycroft fmove.l fp0,d6 ;put ILOG in d6 as a lword
285 1.1 mycroft
286 1.1 mycroft
287 1.1 mycroft * A4. Clr INEX bit.
288 1.1 mycroft * The operation in A3 above may have set INEX2.
289 1.1 mycroft
290 1.1 mycroft A4_str:
291 1.1 mycroft fmove.l #0,FPSR ;zero all of fpsr - nothing needed
292 1.1 mycroft
293 1.1 mycroft
294 1.1 mycroft * A5. Set ICTR = 0;
295 1.1 mycroft * ICTR is a flag used in A13. It must be set before the
296 1.1 mycroft * loop entry A6. The lower word of d5 is used for ICTR.
297 1.1 mycroft
298 1.1 mycroft clr.w d5 ;clear ICTR
299 1.1 mycroft
300 1.1 mycroft
301 1.1 mycroft * A6. Calculate LEN.
302 1.1 mycroft * LEN is the number of digits to be displayed. The k-factor
303 1.1 mycroft * can dictate either the total number of digits, if it is
304 1.1 mycroft * a positive number, or the number of digits after the
305 1.1 mycroft * original decimal point which are to be included as
306 1.1 mycroft * significant. See the 68882 manual for examples.
307 1.1 mycroft * If LEN is computed to be greater than 17, set OPERR in
308 1.1 mycroft * USER_FPSR. LEN is stored in d4.
309 1.1 mycroft *
310 1.1 mycroft * Register usage:
311 1.1 mycroft * Input/Output
312 1.1 mycroft * d0: exponent/Unchanged
313 1.1 mycroft * d2: x/x/scratch
314 1.1 mycroft * d3: x/x
315 1.1 mycroft * d4: exc picture/LEN
316 1.1 mycroft * d5: ICTR/Unchanged
317 1.1 mycroft * d6: ILOG/Unchanged
318 1.1 mycroft * d7: k-factor/Unchanged
319 1.1 mycroft * a0: ptr for original operand/final result
320 1.1 mycroft * a1: x/x
321 1.1 mycroft * a2: x/x
322 1.1 mycroft * fp0: float(ILOG)/Unchanged
323 1.1 mycroft * fp1: x/x
324 1.1 mycroft * fp2: x/x
325 1.1 mycroft * F_SCR1:x/x
326 1.1 mycroft * F_SCR2:Abs(X) with $3fff exponent/Unchanged
327 1.1 mycroft * L_SCR1:x/x
328 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
329 1.1 mycroft
330 1.1 mycroft A6_str:
331 1.1 mycroft tst.l d7 ;branch on sign of k
332 1.1 mycroft ble.b k_neg ;if k <= 0, LEN = ILOG + 1 - k
333 1.1 mycroft move.l d7,d4 ;if k > 0, LEN = k
334 1.1 mycroft bra.b len_ck ;skip to LEN check
335 1.1 mycroft k_neg:
336 1.1 mycroft move.l d6,d4 ;first load ILOG to d4
337 1.1 mycroft sub.l d7,d4 ;subtract off k
338 1.1 mycroft addq.l #1,d4 ;add in the 1
339 1.1 mycroft len_ck:
340 1.1 mycroft tst.l d4 ;LEN check: branch on sign of LEN
341 1.1 mycroft ble.b LEN_ng ;if neg, set LEN = 1
342 1.1 mycroft cmp.l #17,d4 ;test if LEN > 17
343 1.1 mycroft ble.b A7_str ;if not, forget it
344 1.1 mycroft move.l #17,d4 ;set max LEN = 17
345 1.1 mycroft tst.l d7 ;if negative, never set OPERR
346 1.1 mycroft ble.b A7_str ;if positive, continue
347 1.1 mycroft or.l #opaop_mask,USER_FPSR(a6) ;set OPERR & AIOP in USER_FPSR
348 1.1 mycroft bra.b A7_str ;finished here
349 1.1 mycroft LEN_ng:
350 1.1 mycroft moveq.l #1,d4 ;min LEN is 1
351 1.1 mycroft
352 1.1 mycroft
353 1.1 mycroft * A7. Calculate SCALE.
354 1.1 mycroft * SCALE is equal to 10^ISCALE, where ISCALE is the number
355 1.1 mycroft * of decimal places needed to insure LEN integer digits
356 1.1 mycroft * in the output before conversion to bcd. LAMBDA is the sign
357 1.1 mycroft * of ISCALE, used in A9. Fp1 contains 10^^(abs(ISCALE)) using
358 1.1 mycroft * the rounding mode as given in the following table (see
359 1.1 mycroft * Coonen, p. 7.23 as ref.; however, the SCALE variable is
360 1.1 mycroft * of opposite sign in bindec.sa from Coonen).
361 1.1 mycroft *
362 1.1 mycroft * Initial USE
363 1.1 mycroft * FPCR[6:5] LAMBDA SIGN(X) FPCR[6:5]
364 1.1 mycroft * ----------------------------------------------
365 1.1 mycroft * RN 00 0 0 00/0 RN
366 1.1 mycroft * RN 00 0 1 00/0 RN
367 1.1 mycroft * RN 00 1 0 00/0 RN
368 1.1 mycroft * RN 00 1 1 00/0 RN
369 1.1 mycroft * RZ 01 0 0 11/3 RP
370 1.1 mycroft * RZ 01 0 1 11/3 RP
371 1.1 mycroft * RZ 01 1 0 10/2 RM
372 1.1 mycroft * RZ 01 1 1 10/2 RM
373 1.1 mycroft * RM 10 0 0 11/3 RP
374 1.1 mycroft * RM 10 0 1 10/2 RM
375 1.1 mycroft * RM 10 1 0 10/2 RM
376 1.1 mycroft * RM 10 1 1 11/3 RP
377 1.1 mycroft * RP 11 0 0 10/2 RM
378 1.1 mycroft * RP 11 0 1 11/3 RP
379 1.1 mycroft * RP 11 1 0 11/3 RP
380 1.1 mycroft * RP 11 1 1 10/2 RM
381 1.1 mycroft *
382 1.1 mycroft * Register usage:
383 1.1 mycroft * Input/Output
384 1.1 mycroft * d0: exponent/scratch - final is 0
385 1.1 mycroft * d2: x/0 or 24 for A9
386 1.1 mycroft * d3: x/scratch - offset ptr into PTENRM array
387 1.1 mycroft * d4: LEN/Unchanged
388 1.1 mycroft * d5: 0/ICTR:LAMBDA
389 1.1 mycroft * d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
390 1.1 mycroft * d7: k-factor/Unchanged
391 1.1 mycroft * a0: ptr for original operand/final result
392 1.1 mycroft * a1: x/ptr to PTENRM array
393 1.1 mycroft * a2: x/x
394 1.1 mycroft * fp0: float(ILOG)/Unchanged
395 1.1 mycroft * fp1: x/10^ISCALE
396 1.1 mycroft * fp2: x/x
397 1.1 mycroft * F_SCR1:x/x
398 1.1 mycroft * F_SCR2:Abs(X) with $3fff exponent/Unchanged
399 1.1 mycroft * L_SCR1:x/x
400 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
401 1.1 mycroft
402 1.1 mycroft A7_str:
403 1.1 mycroft tst.l d7 ;test sign of k
404 1.1 mycroft bgt.b k_pos ;if pos and > 0, skip this
405 1.1 mycroft cmp.l d6,d7 ;test k - ILOG
406 1.1 mycroft blt.b k_pos ;if ILOG >= k, skip this
407 1.1 mycroft move.l d7,d6 ;if ((k<0) & (ILOG < k)) ILOG = k
408 1.1 mycroft k_pos:
409 1.1 mycroft move.l d6,d0 ;calc ILOG + 1 - LEN in d0
410 1.1 mycroft addq.l #1,d0 ;add the 1
411 1.1 mycroft sub.l d4,d0 ;sub off LEN
412 1.1 mycroft swap d5 ;use upper word of d5 for LAMBDA
413 1.1 mycroft clr.w d5 ;set it zero initially
414 1.1 mycroft clr.w d2 ;set up d2 for very small case
415 1.1 mycroft tst.l d0 ;test sign of ISCALE
416 1.1 mycroft bge.b iscale ;if pos, skip next inst
417 1.1 mycroft addq.w #1,d5 ;if neg, set LAMBDA true
418 1.1 mycroft cmp.l #$ffffecd4,d0 ;test iscale <= -4908
419 1.1 mycroft bgt.b no_inf ;if false, skip rest
420 1.1 mycroft addi.l #24,d0 ;add in 24 to iscale
421 1.1 mycroft move.l #24,d2 ;put 24 in d2 for A9
422 1.1 mycroft no_inf:
423 1.1 mycroft neg.l d0 ;and take abs of ISCALE
424 1.1 mycroft iscale:
425 1.1 mycroft fmove.s FONE,fp1 ;init fp1 to 1
426 1.1 mycroft bfextu USER_FPCR(a6){26:2},d1 ;get initial rmode bits
427 1.2 mycroft add.w d1,d1 ;put them in bits 2:1
428 1.1 mycroft add.w d5,d1 ;add in LAMBDA
429 1.2 mycroft add.w d1,d1 ;put them in bits 3:1
430 1.1 mycroft tst.l L_SCR2(a6) ;test sign of original x
431 1.1 mycroft bge.b x_pos ;if pos, don't set bit 0
432 1.1 mycroft addq.l #1,d1 ;if neg, set bit 0
433 1.1 mycroft x_pos:
434 1.1 mycroft lea.l RBDTBL,a2 ;load rbdtbl base
435 1.1 mycroft move.b (a2,d1),d3 ;load d3 with new rmode
436 1.1 mycroft lsl.l #4,d3 ;put bits in proper position
437 1.1 mycroft fmove.l d3,fpcr ;load bits into fpu
438 1.1 mycroft lsr.l #4,d3 ;put bits in proper position
439 1.1 mycroft tst.b d3 ;decode new rmode for pten table
440 1.1 mycroft bne.b not_rn ;if zero, it is RN
441 1.1 mycroft lea.l PTENRN,a1 ;load a1 with RN table base
442 1.1 mycroft bra.b rmode ;exit decode
443 1.1 mycroft not_rn:
444 1.1 mycroft lsr.b #1,d3 ;get lsb in carry
445 1.1 mycroft bcc.b not_rp ;if carry clear, it is RM
446 1.1 mycroft lea.l PTENRP,a1 ;load a1 with RP table base
447 1.1 mycroft bra.b rmode ;exit decode
448 1.1 mycroft not_rp:
449 1.1 mycroft lea.l PTENRM,a1 ;load a1 with RM table base
450 1.1 mycroft rmode:
451 1.1 mycroft clr.l d3 ;clr table index
452 1.1 mycroft e_loop:
453 1.1 mycroft lsr.l #1,d0 ;shift next bit into carry
454 1.1 mycroft bcc.b e_next ;if zero, skip the mul
455 1.1 mycroft fmul.x (a1,d3),fp1 ;mul by 10**(d3_bit_no)
456 1.1 mycroft e_next:
457 1.1 mycroft add.l #12,d3 ;inc d3 to next pwrten table entry
458 1.1 mycroft tst.l d0 ;test if ISCALE is zero
459 1.1 mycroft bne.b e_loop ;if not, loop
460 1.1 mycroft
461 1.1 mycroft
462 1.1 mycroft * A8. Clr INEX; Force RZ.
463 1.1 mycroft * The operation in A3 above may have set INEX2.
464 1.1 mycroft * RZ mode is forced for the scaling operation to insure
465 1.1 mycroft * only one rounding error. The grs bits are collected in
466 1.1 mycroft * the INEX flag for use in A10.
467 1.1 mycroft *
468 1.1 mycroft * Register usage:
469 1.1 mycroft * Input/Output
470 1.1 mycroft
471 1.1 mycroft fmove.l #0,FPSR ;clr INEX
472 1.1 mycroft fmove.l #rz_mode,FPCR ;set RZ rounding mode
473 1.1 mycroft
474 1.1 mycroft
475 1.1 mycroft * A9. Scale X -> Y.
476 1.1 mycroft * The mantissa is scaled to the desired number of significant
477 1.1 mycroft * digits. The excess digits are collected in INEX2. If mul,
478 1.1 mycroft * Check d2 for excess 10 exponential value. If not zero,
479 1.1 mycroft * the iscale value would have caused the pwrten calculation
480 1.1 mycroft * to overflow. Only a negative iscale can cause this, so
481 1.1 mycroft * multiply by 10^(d2), which is now only allowed to be 24,
482 1.1 mycroft * with a multiply by 10^8 and 10^16, which is exact since
483 1.1 mycroft * 10^24 is exact. If the input was denormalized, we must
484 1.1 mycroft * create a busy stack frame with the mul command and the
485 1.1 mycroft * two operands, and allow the fpu to complete the multiply.
486 1.1 mycroft *
487 1.1 mycroft * Register usage:
488 1.1 mycroft * Input/Output
489 1.1 mycroft * d0: FPCR with RZ mode/Unchanged
490 1.1 mycroft * d2: 0 or 24/unchanged
491 1.1 mycroft * d3: x/x
492 1.1 mycroft * d4: LEN/Unchanged
493 1.1 mycroft * d5: ICTR:LAMBDA
494 1.1 mycroft * d6: ILOG/Unchanged
495 1.1 mycroft * d7: k-factor/Unchanged
496 1.1 mycroft * a0: ptr for original operand/final result
497 1.1 mycroft * a1: ptr to PTENRM array/Unchanged
498 1.1 mycroft * a2: x/x
499 1.1 mycroft * fp0: float(ILOG)/X adjusted for SCALE (Y)
500 1.1 mycroft * fp1: 10^ISCALE/Unchanged
501 1.1 mycroft * fp2: x/x
502 1.1 mycroft * F_SCR1:x/x
503 1.1 mycroft * F_SCR2:Abs(X) with $3fff exponent/Unchanged
504 1.1 mycroft * L_SCR1:x/x
505 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
506 1.1 mycroft
507 1.1 mycroft A9_str:
508 1.1 mycroft fmove.x (a0),fp0 ;load X from memory
509 1.1 mycroft fabs.x fp0 ;use abs(X)
510 1.1 mycroft tst.w d5 ;LAMBDA is in lower word of d5
511 1.1 mycroft bne.b sc_mul ;if neg (LAMBDA = 1), scale by mul
512 1.1 mycroft fdiv.x fp1,fp0 ;calculate X / SCALE -> Y to fp0
513 1.1 mycroft bra.b A10_st ;branch to A10
514 1.1 mycroft
515 1.1 mycroft sc_mul:
516 1.1 mycroft tst.b BINDEC_FLG(a6) ;check for denorm
517 1.1 mycroft beq.b A9_norm ;if norm, continue with mul
518 1.1 mycroft fmovem.x fp1,-(a7) ;load ETEMP with 10^ISCALE
519 1.1 mycroft move.l 8(a0),-(a7) ;load FPTEMP with input arg
520 1.1 mycroft move.l 4(a0),-(a7)
521 1.1 mycroft move.l (a0),-(a7)
522 1.1 mycroft move.l #18,d3 ;load count for busy stack
523 1.1 mycroft A9_loop:
524 1.1 mycroft clr.l -(a7) ;clear lword on stack
525 1.1 mycroft dbf.w d3,A9_loop
526 1.1 mycroft move.b VER_TMP(a6),(a7) ;write current version number
527 1.1 mycroft move.b #BUSY_SIZE-4,1(a7) ;write current busy size
528 1.1 mycroft move.b #$10,$44(a7) ;set fcefpte[15] bit
529 1.1 mycroft move.w #$0023,$40(a7) ;load cmdreg1b with mul command
530 1.1 mycroft move.b #$fe,$8(a7) ;load all 1s to cu savepc
531 1.1 mycroft frestore (a7)+ ;restore frame to fpu for completion
532 1.1 mycroft fmul.x 36(a1),fp0 ;multiply fp0 by 10^8
533 1.1 mycroft fmul.x 48(a1),fp0 ;multiply fp0 by 10^16
534 1.1 mycroft bra.b A10_st
535 1.1 mycroft A9_norm:
536 1.1 mycroft tst.w d2 ;test for small exp case
537 1.1 mycroft beq.b A9_con ;if zero, continue as normal
538 1.1 mycroft fmul.x 36(a1),fp0 ;multiply fp0 by 10^8
539 1.1 mycroft fmul.x 48(a1),fp0 ;multiply fp0 by 10^16
540 1.1 mycroft A9_con:
541 1.1 mycroft fmul.x fp1,fp0 ;calculate X * SCALE -> Y to fp0
542 1.1 mycroft
543 1.1 mycroft
544 1.1 mycroft * A10. Or in INEX.
545 1.1 mycroft * If INEX is set, round error occured. This is compensated
546 1.1 mycroft * for by 'or-ing' in the INEX2 flag to the lsb of Y.
547 1.1 mycroft *
548 1.1 mycroft * Register usage:
549 1.1 mycroft * Input/Output
550 1.1 mycroft * d0: FPCR with RZ mode/FPSR with INEX2 isolated
551 1.1 mycroft * d2: x/x
552 1.1 mycroft * d3: x/x
553 1.1 mycroft * d4: LEN/Unchanged
554 1.1 mycroft * d5: ICTR:LAMBDA
555 1.1 mycroft * d6: ILOG/Unchanged
556 1.1 mycroft * d7: k-factor/Unchanged
557 1.1 mycroft * a0: ptr for original operand/final result
558 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
559 1.1 mycroft * a2: x/ptr to FP_SCR2(a6)
560 1.1 mycroft * fp0: Y/Y with lsb adjusted
561 1.1 mycroft * fp1: 10^ISCALE/Unchanged
562 1.1 mycroft * fp2: x/x
563 1.1 mycroft
564 1.1 mycroft A10_st:
565 1.1 mycroft fmove.l FPSR,d0 ;get FPSR
566 1.1 mycroft fmove.x fp0,FP_SCR2(a6) ;move Y to memory
567 1.1 mycroft lea.l FP_SCR2(a6),a2 ;load a2 with ptr to FP_SCR2
568 1.1 mycroft btst.l #9,d0 ;check if INEX2 set
569 1.1 mycroft beq.b A11_st ;if clear, skip rest
570 1.1 mycroft ori.l #1,8(a2) ;or in 1 to lsb of mantissa
571 1.1 mycroft fmove.x FP_SCR2(a6),fp0 ;write adjusted Y back to fpu
572 1.1 mycroft
573 1.1 mycroft
574 1.1 mycroft * A11. Restore original FPCR; set size ext.
575 1.1 mycroft * Perform FINT operation in the user's rounding mode. Keep
576 1.1 mycroft * the size to extended. The sintdo entry point in the sint
577 1.1 mycroft * routine expects the FPCR value to be in USER_FPCR for
578 1.1 mycroft * mode and precision. The original FPCR is saved in L_SCR1.
579 1.1 mycroft
580 1.1 mycroft A11_st:
581 1.1 mycroft move.l USER_FPCR(a6),L_SCR1(a6) ;save it for later
582 1.1 mycroft andi.l #$00000030,USER_FPCR(a6) ;set size to ext,
583 1.1 mycroft * ;block exceptions
584 1.1 mycroft
585 1.1 mycroft
586 1.1 mycroft * A12. Calculate YINT = FINT(Y) according to user's rounding mode.
587 1.1 mycroft * The FPSP routine sintd0 is used. The output is in fp0.
588 1.1 mycroft *
589 1.1 mycroft * Register usage:
590 1.1 mycroft * Input/Output
591 1.1 mycroft * d0: FPSR with AINEX cleared/FPCR with size set to ext
592 1.1 mycroft * d2: x/x/scratch
593 1.1 mycroft * d3: x/x
594 1.1 mycroft * d4: LEN/Unchanged
595 1.1 mycroft * d5: ICTR:LAMBDA/Unchanged
596 1.1 mycroft * d6: ILOG/Unchanged
597 1.1 mycroft * d7: k-factor/Unchanged
598 1.1 mycroft * a0: ptr for original operand/src ptr for sintdo
599 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
600 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
601 1.1 mycroft * a6: temp pointer to FP_SCR2(a6) - orig value saved and restored
602 1.1 mycroft * fp0: Y/YINT
603 1.1 mycroft * fp1: 10^ISCALE/Unchanged
604 1.1 mycroft * fp2: x/x
605 1.1 mycroft * F_SCR1:x/x
606 1.1 mycroft * F_SCR2:Y adjusted for inex/Y with original exponent
607 1.1 mycroft * L_SCR1:x/original USER_FPCR
608 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
609 1.1 mycroft
610 1.1 mycroft A12_st:
611 1.1 mycroft movem.l d0-d1/a0-a1,-(a7) ;save regs used by sintd0
612 1.1 mycroft move.l L_SCR1(a6),-(a7)
613 1.1 mycroft move.l L_SCR2(a6),-(a7)
614 1.1 mycroft lea.l FP_SCR2(a6),a0 ;a0 is ptr to F_SCR2(a6)
615 1.1 mycroft fmove.x fp0,(a0) ;move Y to memory at FP_SCR2(a6)
616 1.1 mycroft tst.l L_SCR2(a6) ;test sign of original operand
617 1.1 mycroft bge.b do_fint ;if pos, use Y
618 1.1 mycroft or.l #$80000000,(a0) ;if neg, use -Y
619 1.1 mycroft do_fint:
620 1.1 mycroft move.l USER_FPSR(a6),-(a7)
621 1.1 mycroft bsr sintdo ;sint routine returns int in fp0
622 1.1 mycroft move.b (a7),USER_FPSR(a6)
623 1.1 mycroft add.l #4,a7
624 1.1 mycroft move.l (a7)+,L_SCR2(a6)
625 1.1 mycroft move.l (a7)+,L_SCR1(a6)
626 1.1 mycroft movem.l (a7)+,d0-d1/a0-a1 ;restore regs used by sint
627 1.1 mycroft move.l L_SCR2(a6),FP_SCR2(a6) ;restore original exponent
628 1.1 mycroft move.l L_SCR1(a6),USER_FPCR(a6) ;restore user's FPCR
629 1.1 mycroft
630 1.1 mycroft
631 1.1 mycroft * A13. Check for LEN digits.
632 1.1 mycroft * If the int operation results in more than LEN digits,
633 1.1 mycroft * or less than LEN -1 digits, adjust ILOG and repeat from
634 1.1 mycroft * A6. This test occurs only on the first pass. If the
635 1.1 mycroft * result is exactly 10^LEN, decrement ILOG and divide
636 1.1 mycroft * the mantissa by 10. The calculation of 10^LEN cannot
637 1.1 mycroft * be inexact, since all powers of ten upto 10^27 are exact
638 1.1 mycroft * in extended precision, so the use of a previous power-of-ten
639 1.1 mycroft * table will introduce no error.
640 1.1 mycroft *
641 1.1 mycroft *
642 1.1 mycroft * Register usage:
643 1.1 mycroft * Input/Output
644 1.1 mycroft * d0: FPCR with size set to ext/scratch final = 0
645 1.1 mycroft * d2: x/x
646 1.1 mycroft * d3: x/scratch final = x
647 1.1 mycroft * d4: LEN/LEN adjusted
648 1.1 mycroft * d5: ICTR:LAMBDA/LAMBDA:ICTR
649 1.1 mycroft * d6: ILOG/ILOG adjusted
650 1.1 mycroft * d7: k-factor/Unchanged
651 1.1 mycroft * a0: pointer into memory for packed bcd string formation
652 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
653 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
654 1.1 mycroft * fp0: int portion of Y/abs(YINT) adjusted
655 1.1 mycroft * fp1: 10^ISCALE/Unchanged
656 1.1 mycroft * fp2: x/10^LEN
657 1.1 mycroft * F_SCR1:x/x
658 1.1 mycroft * F_SCR2:Y with original exponent/Unchanged
659 1.1 mycroft * L_SCR1:original USER_FPCR/Unchanged
660 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
661 1.1 mycroft
662 1.1 mycroft A13_st:
663 1.1 mycroft swap d5 ;put ICTR in lower word of d5
664 1.1 mycroft tst.w d5 ;check if ICTR = 0
665 1.1 mycroft bne not_zr ;if non-zero, go to second test
666 1.1 mycroft *
667 1.1 mycroft * Compute 10^(LEN-1)
668 1.1 mycroft *
669 1.1 mycroft fmove.s FONE,fp2 ;init fp2 to 1.0
670 1.1 mycroft move.l d4,d0 ;put LEN in d0
671 1.1 mycroft subq.l #1,d0 ;d0 = LEN -1
672 1.1 mycroft clr.l d3 ;clr table index
673 1.1 mycroft l_loop:
674 1.1 mycroft lsr.l #1,d0 ;shift next bit into carry
675 1.1 mycroft bcc.b l_next ;if zero, skip the mul
676 1.1 mycroft fmul.x (a1,d3),fp2 ;mul by 10**(d3_bit_no)
677 1.1 mycroft l_next:
678 1.1 mycroft add.l #12,d3 ;inc d3 to next pwrten table entry
679 1.1 mycroft tst.l d0 ;test if LEN is zero
680 1.1 mycroft bne.b l_loop ;if not, loop
681 1.1 mycroft *
682 1.1 mycroft * 10^LEN-1 is computed for this test and A14. If the input was
683 1.1 mycroft * denormalized, check only the case in which YINT > 10^LEN.
684 1.1 mycroft *
685 1.1 mycroft tst.b BINDEC_FLG(a6) ;check if input was norm
686 1.1 mycroft beq.b A13_con ;if norm, continue with checking
687 1.1 mycroft fabs.x fp0 ;take abs of YINT
688 1.1 mycroft bra test_2
689 1.1 mycroft *
690 1.1 mycroft * Compare abs(YINT) to 10^(LEN-1) and 10^LEN
691 1.1 mycroft *
692 1.1 mycroft A13_con:
693 1.1 mycroft fabs.x fp0 ;take abs of YINT
694 1.1 mycroft fcmp.x fp2,fp0 ;compare abs(YINT) with 10^(LEN-1)
695 1.1 mycroft fbge.w test_2 ;if greater, do next test
696 1.1 mycroft subq.l #1,d6 ;subtract 1 from ILOG
697 1.1 mycroft move.w #1,d5 ;set ICTR
698 1.1 mycroft fmove.l #rm_mode,FPCR ;set rmode to RM
699 1.1 mycroft fmul.s FTEN,fp2 ;compute 10^LEN
700 1.1 mycroft bra.w A6_str ;return to A6 and recompute YINT
701 1.1 mycroft test_2:
702 1.1 mycroft fmul.s FTEN,fp2 ;compute 10^LEN
703 1.1 mycroft fcmp.x fp2,fp0 ;compare abs(YINT) with 10^LEN
704 1.1 mycroft fblt.w A14_st ;if less, all is ok, go to A14
705 1.1 mycroft fbgt.w fix_ex ;if greater, fix and redo
706 1.1 mycroft fdiv.s FTEN,fp0 ;if equal, divide by 10
707 1.1 mycroft addq.l #1,d6 ; and inc ILOG
708 1.1 mycroft bra.b A14_st ; and continue elsewhere
709 1.1 mycroft fix_ex:
710 1.1 mycroft addq.l #1,d6 ;increment ILOG by 1
711 1.1 mycroft move.w #1,d5 ;set ICTR
712 1.1 mycroft fmove.l #rm_mode,FPCR ;set rmode to RM
713 1.1 mycroft bra.w A6_str ;return to A6 and recompute YINT
714 1.1 mycroft *
715 1.1 mycroft * Since ICTR <> 0, we have already been through one adjustment,
716 1.1 mycroft * and shouldn't have another; this is to check if abs(YINT) = 10^LEN
717 1.1 mycroft * 10^LEN is again computed using whatever table is in a1 since the
718 1.1 mycroft * value calculated cannot be inexact.
719 1.1 mycroft *
720 1.1 mycroft not_zr:
721 1.1 mycroft fmove.s FONE,fp2 ;init fp2 to 1.0
722 1.1 mycroft move.l d4,d0 ;put LEN in d0
723 1.1 mycroft clr.l d3 ;clr table index
724 1.1 mycroft z_loop:
725 1.1 mycroft lsr.l #1,d0 ;shift next bit into carry
726 1.1 mycroft bcc.b z_next ;if zero, skip the mul
727 1.1 mycroft fmul.x (a1,d3),fp2 ;mul by 10**(d3_bit_no)
728 1.1 mycroft z_next:
729 1.1 mycroft add.l #12,d3 ;inc d3 to next pwrten table entry
730 1.1 mycroft tst.l d0 ;test if LEN is zero
731 1.1 mycroft bne.b z_loop ;if not, loop
732 1.1 mycroft fabs.x fp0 ;get abs(YINT)
733 1.1 mycroft fcmp.x fp2,fp0 ;check if abs(YINT) = 10^LEN
734 1.1 mycroft fbne.w A14_st ;if not, skip this
735 1.1 mycroft fdiv.s FTEN,fp0 ;divide abs(YINT) by 10
736 1.1 mycroft addq.l #1,d6 ;and inc ILOG by 1
737 1.1 mycroft addq.l #1,d4 ; and inc LEN
738 1.1 mycroft fmul.s FTEN,fp2 ; if LEN++, the get 10^^LEN
739 1.1 mycroft
740 1.1 mycroft
741 1.1 mycroft * A14. Convert the mantissa to bcd.
742 1.1 mycroft * The binstr routine is used to convert the LEN digit
743 1.1 mycroft * mantissa to bcd in memory. The input to binstr is
744 1.1 mycroft * to be a fraction; i.e. (mantissa)/10^LEN and adjusted
745 1.1 mycroft * such that the decimal point is to the left of bit 63.
746 1.1 mycroft * The bcd digits are stored in the correct position in
747 1.1 mycroft * the final string area in memory.
748 1.1 mycroft *
749 1.1 mycroft *
750 1.1 mycroft * Register usage:
751 1.1 mycroft * Input/Output
752 1.1 mycroft * d0: x/LEN call to binstr - final is 0
753 1.1 mycroft * d1: x/0
754 1.1 mycroft * d2: x/ms 32-bits of mant of abs(YINT)
755 1.1 mycroft * d3: x/ls 32-bits of mant of abs(YINT)
756 1.1 mycroft * d4: LEN/Unchanged
757 1.1 mycroft * d5: ICTR:LAMBDA/LAMBDA:ICTR
758 1.1 mycroft * d6: ILOG
759 1.1 mycroft * d7: k-factor/Unchanged
760 1.1 mycroft * a0: pointer into memory for packed bcd string formation
761 1.1 mycroft * /ptr to first mantissa byte in result string
762 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
763 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
764 1.1 mycroft * fp0: int portion of Y/abs(YINT) adjusted
765 1.1 mycroft * fp1: 10^ISCALE/Unchanged
766 1.1 mycroft * fp2: 10^LEN/Unchanged
767 1.1 mycroft * F_SCR1:x/Work area for final result
768 1.1 mycroft * F_SCR2:Y with original exponent/Unchanged
769 1.1 mycroft * L_SCR1:original USER_FPCR/Unchanged
770 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
771 1.1 mycroft
772 1.1 mycroft A14_st:
773 1.1 mycroft fmove.l #rz_mode,FPCR ;force rz for conversion
774 1.1 mycroft fdiv.x fp2,fp0 ;divide abs(YINT) by 10^LEN
775 1.1 mycroft lea.l FP_SCR1(a6),a0
776 1.1 mycroft fmove.x fp0,(a0) ;move abs(YINT)/10^LEN to memory
777 1.1 mycroft move.l 4(a0),d2 ;move 2nd word of FP_RES to d2
778 1.1 mycroft move.l 8(a0),d3 ;move 3rd word of FP_RES to d3
779 1.1 mycroft clr.l 4(a0) ;zero word 2 of FP_RES
780 1.1 mycroft clr.l 8(a0) ;zero word 3 of FP_RES
781 1.1 mycroft move.l (a0),d0 ;move exponent to d0
782 1.1 mycroft swap d0 ;put exponent in lower word
783 1.1 mycroft beq.b no_sft ;if zero, don't shift
784 1.1 mycroft subi.l #$3ffd,d0 ;sub bias less 2 to make fract
785 1.1 mycroft tst.l d0 ;check if > 1
786 1.1 mycroft bgt.b no_sft ;if so, don't shift
787 1.1 mycroft neg.l d0 ;make exp positive
788 1.1 mycroft m_loop:
789 1.1 mycroft lsr.l #1,d2 ;shift d2:d3 right, add 0s
790 1.1 mycroft roxr.l #1,d3 ;the number of places
791 1.1 mycroft dbf.w d0,m_loop ;given in d0
792 1.1 mycroft no_sft:
793 1.1 mycroft tst.l d2 ;check for mantissa of zero
794 1.1 mycroft bne.b no_zr ;if not, go on
795 1.1 mycroft tst.l d3 ;continue zero check
796 1.1 mycroft beq.b zer_m ;if zero, go directly to binstr
797 1.1 mycroft no_zr:
798 1.1 mycroft clr.l d1 ;put zero in d1 for addx
799 1.1 mycroft addi.l #$00000080,d3 ;inc at bit 7
800 1.1 mycroft addx.l d1,d2 ;continue inc
801 1.1 mycroft andi.l #$ffffff80,d3 ;strip off lsb not used by 882
802 1.1 mycroft zer_m:
803 1.1 mycroft move.l d4,d0 ;put LEN in d0 for binstr call
804 1.1 mycroft addq.l #3,a0 ;a0 points to M16 byte in result
805 1.1 mycroft bsr binstr ;call binstr to convert mant
806 1.1 mycroft
807 1.1 mycroft
808 1.1 mycroft * A15. Convert the exponent to bcd.
809 1.1 mycroft * As in A14 above, the exp is converted to bcd and the
810 1.1 mycroft * digits are stored in the final string.
811 1.1 mycroft *
812 1.1 mycroft * Digits are stored in L_SCR1(a6) on return from BINDEC as:
813 1.1 mycroft *
814 1.1 mycroft * 32 16 15 0
815 1.1 mycroft * -----------------------------------------
816 1.1 mycroft * | 0 | e3 | e2 | e1 | e4 | X | X | X |
817 1.1 mycroft * -----------------------------------------
818 1.1 mycroft *
819 1.1 mycroft * And are moved into their proper places in FP_SCR1. If digit e4
820 1.1 mycroft * is non-zero, OPERR is signaled. In all cases, all 4 digits are
821 1.1 mycroft * written as specified in the 881/882 manual for packed decimal.
822 1.1 mycroft *
823 1.1 mycroft * Register usage:
824 1.1 mycroft * Input/Output
825 1.1 mycroft * d0: x/LEN call to binstr - final is 0
826 1.1 mycroft * d1: x/scratch (0);shift count for final exponent packing
827 1.1 mycroft * d2: x/ms 32-bits of exp fraction/scratch
828 1.1 mycroft * d3: x/ls 32-bits of exp fraction
829 1.1 mycroft * d4: LEN/Unchanged
830 1.1 mycroft * d5: ICTR:LAMBDA/LAMBDA:ICTR
831 1.1 mycroft * d6: ILOG
832 1.1 mycroft * d7: k-factor/Unchanged
833 1.1 mycroft * a0: ptr to result string/ptr to L_SCR1(a6)
834 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
835 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
836 1.1 mycroft * fp0: abs(YINT) adjusted/float(ILOG)
837 1.1 mycroft * fp1: 10^ISCALE/Unchanged
838 1.1 mycroft * fp2: 10^LEN/Unchanged
839 1.1 mycroft * F_SCR1:Work area for final result/BCD result
840 1.1 mycroft * F_SCR2:Y with original exponent/ILOG/10^4
841 1.1 mycroft * L_SCR1:original USER_FPCR/Exponent digits on return from binstr
842 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
843 1.1 mycroft
844 1.1 mycroft A15_st:
845 1.1 mycroft tst.b BINDEC_FLG(a6) ;check for denorm
846 1.1 mycroft beq.b not_denorm
847 1.1 mycroft ftst.x fp0 ;test for zero
848 1.1 mycroft fbeq.w den_zero ;if zero, use k-factor or 4933
849 1.1 mycroft fmove.l d6,fp0 ;float ILOG
850 1.1 mycroft fabs.x fp0 ;get abs of ILOG
851 1.1 mycroft bra.b convrt
852 1.1 mycroft den_zero:
853 1.1 mycroft tst.l d7 ;check sign of the k-factor
854 1.1 mycroft blt.b use_ilog ;if negative, use ILOG
855 1.1 mycroft fmove.s F4933,fp0 ;force exponent to 4933
856 1.1 mycroft bra.b convrt ;do it
857 1.1 mycroft use_ilog:
858 1.1 mycroft fmove.l d6,fp0 ;float ILOG
859 1.1 mycroft fabs.x fp0 ;get abs of ILOG
860 1.1 mycroft bra.b convrt
861 1.1 mycroft not_denorm:
862 1.1 mycroft ftst.x fp0 ;test for zero
863 1.1 mycroft fbne.w not_zero ;if zero, force exponent
864 1.1 mycroft fmove.s FONE,fp0 ;force exponent to 1
865 1.1 mycroft bra.b convrt ;do it
866 1.1 mycroft not_zero:
867 1.1 mycroft fmove.l d6,fp0 ;float ILOG
868 1.1 mycroft fabs.x fp0 ;get abs of ILOG
869 1.1 mycroft convrt:
870 1.1 mycroft fdiv.x 24(a1),fp0 ;compute ILOG/10^4
871 1.1 mycroft fmove.x fp0,FP_SCR2(a6) ;store fp0 in memory
872 1.1 mycroft move.l 4(a2),d2 ;move word 2 to d2
873 1.1 mycroft move.l 8(a2),d3 ;move word 3 to d3
874 1.1 mycroft move.w (a2),d0 ;move exp to d0
875 1.1 mycroft beq.b x_loop_fin ;if zero, skip the shift
876 1.1 mycroft subi.w #$3ffd,d0 ;subtract off bias
877 1.1 mycroft neg.w d0 ;make exp positive
878 1.1 mycroft x_loop:
879 1.1 mycroft lsr.l #1,d2 ;shift d2:d3 right
880 1.1 mycroft roxr.l #1,d3 ;the number of places
881 1.1 mycroft dbf.w d0,x_loop ;given in d0
882 1.1 mycroft x_loop_fin:
883 1.1 mycroft clr.l d1 ;put zero in d1 for addx
884 1.1 mycroft addi.l #$00000080,d3 ;inc at bit 6
885 1.1 mycroft addx.l d1,d2 ;continue inc
886 1.1 mycroft andi.l #$ffffff80,d3 ;strip off lsb not used by 882
887 1.1 mycroft move.l #4,d0 ;put 4 in d0 for binstr call
888 1.1 mycroft lea.l L_SCR1(a6),a0 ;a0 is ptr to L_SCR1 for exp digits
889 1.1 mycroft bsr binstr ;call binstr to convert exp
890 1.1 mycroft move.l L_SCR1(a6),d0 ;load L_SCR1 lword to d0
891 1.1 mycroft move.l #12,d1 ;use d1 for shift count
892 1.1 mycroft lsr.l d1,d0 ;shift d0 right by 12
893 1.1 mycroft bfins d0,FP_SCR1(a6){4:12} ;put e3:e2:e1 in FP_SCR1
894 1.1 mycroft lsr.l d1,d0 ;shift d0 right by 12
895 1.1 mycroft bfins d0,FP_SCR1(a6){16:4} ;put e4 in FP_SCR1
896 1.1 mycroft tst.b d0 ;check if e4 is zero
897 1.1 mycroft beq.b A16_st ;if zero, skip rest
898 1.1 mycroft or.l #opaop_mask,USER_FPSR(a6) ;set OPERR & AIOP in USER_FPSR
899 1.1 mycroft
900 1.1 mycroft
901 1.1 mycroft * A16. Write sign bits to final string.
902 1.1 mycroft * Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
903 1.1 mycroft *
904 1.1 mycroft * Register usage:
905 1.1 mycroft * Input/Output
906 1.1 mycroft * d0: x/scratch - final is x
907 1.1 mycroft * d2: x/x
908 1.1 mycroft * d3: x/x
909 1.1 mycroft * d4: LEN/Unchanged
910 1.1 mycroft * d5: ICTR:LAMBDA/LAMBDA:ICTR
911 1.1 mycroft * d6: ILOG/ILOG adjusted
912 1.1 mycroft * d7: k-factor/Unchanged
913 1.1 mycroft * a0: ptr to L_SCR1(a6)/Unchanged
914 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
915 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
916 1.1 mycroft * fp0: float(ILOG)/Unchanged
917 1.1 mycroft * fp1: 10^ISCALE/Unchanged
918 1.1 mycroft * fp2: 10^LEN/Unchanged
919 1.1 mycroft * F_SCR1:BCD result with correct signs
920 1.1 mycroft * F_SCR2:ILOG/10^4
921 1.1 mycroft * L_SCR1:Exponent digits on return from binstr
922 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
923 1.1 mycroft
924 1.1 mycroft A16_st:
925 1.1 mycroft clr.l d0 ;clr d0 for collection of signs
926 1.1 mycroft andi.b #$0f,FP_SCR1(a6) ;clear first nibble of FP_SCR1
927 1.1 mycroft tst.l L_SCR2(a6) ;check sign of original mantissa
928 1.1 mycroft bge.b mant_p ;if pos, don't set SM
929 1.1 mycroft moveq.l #2,d0 ;move 2 in to d0 for SM
930 1.1 mycroft mant_p:
931 1.1 mycroft tst.l d6 ;check sign of ILOG
932 1.1 mycroft bge.b wr_sgn ;if pos, don't set SE
933 1.1 mycroft addq.l #1,d0 ;set bit 0 in d0 for SE
934 1.1 mycroft wr_sgn:
935 1.1 mycroft bfins d0,FP_SCR1(a6){0:2} ;insert SM and SE into FP_SCR1
936 1.1 mycroft
937 1.1 mycroft * Clean up and restore all registers used.
938 1.1 mycroft
939 1.1 mycroft fmove.l #0,FPSR ;clear possible inex2/ainex bits
940 1.1 mycroft fmovem.x (a7)+,fp0-fp2
941 1.1 mycroft movem.l (a7)+,d2-d7/a2
942 1.1 mycroft rts
943 1.1 mycroft
944 1.1 mycroft end
945