~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/m68k/fpsp040/scale.S

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
|
 
2
|       scale.sa 3.3 7/30/91
 
3
|
 
4
|       The entry point sSCALE computes the destination operand
 
5
|       scaled by the source operand.  If the absolute value of
 
6
|       the source operand is (>= 2^14) an overflow or underflow
 
7
|       is returned.
 
8
|
 
9
|       The entry point sscale is called from do_func to emulate
 
10
|       the fscale unimplemented instruction.
 
11
|
 
12
|       Input: Double-extended destination operand in FPTEMP,
 
13
|               double-extended source operand in ETEMP.
 
14
|
 
15
|       Output: The function returns scale(X,Y) to fp0.
 
16
|
 
17
|       Modifies: fp0.
 
18
|
 
19
|       Algorithm:
 
20
|
 
21
|               Copyright (C) Motorola, Inc. 1990
 
22
|                       All Rights Reserved
 
23
|
 
24
|       For details on the license for this file, please see the
 
25
|       file, README, in this same directory.
 
26
 
 
27
|SCALE    idnt    2,1 | Motorola 040 Floating Point Software Package
 
28
 
 
29
        |section        8
 
30
 
 
31
#include "fpsp.h"
 
32
 
 
33
        |xref   t_ovfl2
 
34
        |xref   t_unfl
 
35
        |xref   round
 
36
        |xref   t_resdnrm
 
37
 
 
38
SRC_BNDS: .short        0x3fff,0x400c
 
39
 
 
40
|
 
41
| This entry point is used by the unimplemented instruction exception
 
42
| handler.
 
43
|
 
44
|
 
45
|
 
46
|       FSCALE
 
47
|
 
48
        .global sscale
 
49
sscale:
 
50
        fmovel          #0,%fpcr                |clr user enabled exc
 
51
        clrl            %d1
 
52
        movew           FPTEMP(%a6),%d1 |get dest exponent
 
53
        smi             L_SCR1(%a6)     |use L_SCR1 to hold sign
 
54
        andil           #0x7fff,%d1     |strip sign
 
55
        movew           ETEMP(%a6),%d0  |check src bounds
 
56
        andiw           #0x7fff,%d0     |clr sign bit
 
57
        cmp2w           SRC_BNDS,%d0
 
58
        bccs            src_in
 
59
        cmpiw           #0x400c,%d0     |test for too large
 
60
        bge             src_out
 
61
|
 
62
| The source input is below 1, so we check for denormalized numbers
 
63
| and set unfl.
 
64
|
 
65
src_small:
 
66
        moveb           DTAG(%a6),%d0
 
67
        andib           #0xe0,%d0
 
68
        tstb            %d0
 
69
        beqs            no_denorm
 
70
        st              STORE_FLG(%a6)  |dest already contains result
 
71
        orl             #unfl_mask,USER_FPSR(%a6) |set UNFL
 
72
den_done:
 
73
        leal            FPTEMP(%a6),%a0
 
74
        bra             t_resdnrm
 
75
no_denorm:
 
76
        fmovel          USER_FPCR(%a6),%FPCR
 
77
        fmovex          FPTEMP(%a6),%fp0        |simply return dest
 
78
        rts
 
79
 
 
80
 
 
81
|
 
82
| Source is within 2^14 range.  To perform the int operation,
 
83
| move it to d0.
 
84
|
 
85
src_in:
 
86
        fmovex          ETEMP(%a6),%fp0 |move in src for int
 
87
        fmovel          #rz_mode,%fpcr  |force rz for src conversion
 
88
        fmovel          %fp0,%d0                |int src to d0
 
89
        fmovel          #0,%FPSR                |clr status from above
 
90
        tstw            ETEMP(%a6)      |check src sign
 
91
        blt             src_neg
 
92
|
 
93
| Source is positive.  Add the src to the dest exponent.
 
94
| The result can be denormalized, if src = 0, or overflow,
 
95
| if the result of the add sets a bit in the upper word.
 
96
|
 
97
src_pos:
 
98
        tstw            %d1             |check for denorm
 
99
        beq             dst_dnrm
 
100
        addl            %d0,%d1         |add src to dest exp
 
101
        beqs            denorm          |if zero, result is denorm
 
102
        cmpil           #0x7fff,%d1     |test for overflow
 
103
        bges            ovfl
 
104
        tstb            L_SCR1(%a6)
 
105
        beqs            spos_pos
 
106
        orw             #0x8000,%d1
 
107
spos_pos:
 
108
        movew           %d1,FPTEMP(%a6) |result in FPTEMP
 
109
        fmovel          USER_FPCR(%a6),%FPCR
 
110
        fmovex          FPTEMP(%a6),%fp0        |write result to fp0
 
111
        rts
 
112
ovfl:
 
113
        tstb            L_SCR1(%a6)
 
114
        beqs            sovl_pos
 
115
        orw             #0x8000,%d1
 
116
sovl_pos:
 
117
        movew           FPTEMP(%a6),ETEMP(%a6)  |result in ETEMP
 
118
        movel           FPTEMP_HI(%a6),ETEMP_HI(%a6)
 
119
        movel           FPTEMP_LO(%a6),ETEMP_LO(%a6)
 
120
        bra             t_ovfl2
 
121
 
 
122
denorm:
 
123
        tstb            L_SCR1(%a6)
 
124
        beqs            den_pos
 
125
        orw             #0x8000,%d1
 
126
den_pos:
 
127
        tstl            FPTEMP_HI(%a6)  |check j bit
 
128
        blts            nden_exit       |if set, not denorm
 
129
        movew           %d1,ETEMP(%a6)  |input expected in ETEMP
 
130
        movel           FPTEMP_HI(%a6),ETEMP_HI(%a6)
 
131
        movel           FPTEMP_LO(%a6),ETEMP_LO(%a6)
 
132
        orl             #unfl_bit,USER_FPSR(%a6)        |set unfl
 
133
        leal            ETEMP(%a6),%a0
 
134
        bra             t_resdnrm
 
135
nden_exit:
 
136
        movew           %d1,FPTEMP(%a6) |result in FPTEMP
 
137
        fmovel          USER_FPCR(%a6),%FPCR
 
138
        fmovex          FPTEMP(%a6),%fp0        |write result to fp0
 
139
        rts
 
140
 
 
141
|
 
142
| Source is negative.  Add the src to the dest exponent.
 
143
| (The result exponent will be reduced).  The result can be
 
144
| denormalized.
 
145
|
 
146
src_neg:
 
147
        addl            %d0,%d1         |add src to dest
 
148
        beqs            denorm          |if zero, result is denorm
 
149
        blts            fix_dnrm        |if negative, result is
 
150
|                                       ;needing denormalization
 
151
        tstb            L_SCR1(%a6)
 
152
        beqs            sneg_pos
 
153
        orw             #0x8000,%d1
 
154
sneg_pos:
 
155
        movew           %d1,FPTEMP(%a6) |result in FPTEMP
 
156
        fmovel          USER_FPCR(%a6),%FPCR
 
157
        fmovex          FPTEMP(%a6),%fp0        |write result to fp0
 
158
        rts
 
159
 
 
160
 
 
161
|
 
162
| The result exponent is below denorm value.  Test for catastrophic
 
163
| underflow and force zero if true.  If not, try to shift the
 
164
| mantissa right until a zero exponent exists.
 
165
|
 
166
fix_dnrm:
 
167
        cmpiw           #0xffc0,%d1     |lower bound for normalization
 
168
        blt             fix_unfl        |if lower, catastrophic unfl
 
169
        movew           %d1,%d0         |use d0 for exp
 
170
        movel           %d2,-(%a7)      |free d2 for norm
 
171
        movel           FPTEMP_HI(%a6),%d1
 
172
        movel           FPTEMP_LO(%a6),%d2
 
173
        clrl            L_SCR2(%a6)
 
174
fix_loop:
 
175
        addw            #1,%d0          |drive d0 to 0
 
176
        lsrl            #1,%d1          |while shifting the
 
177
        roxrl           #1,%d2          |mantissa to the right
 
178
        bccs            no_carry
 
179
        st              L_SCR2(%a6)     |use L_SCR2 to capture inex
 
180
no_carry:
 
181
        tstw            %d0             |it is finished when
 
182
        blts            fix_loop        |d0 is zero or the mantissa
 
183
        tstb            L_SCR2(%a6)
 
184
        beqs            tst_zero
 
185
        orl             #unfl_inx_mask,USER_FPSR(%a6)
 
186
|                                       ;set unfl, aunfl, ainex
 
187
|
 
188
| Test for zero. If zero, simply use fmove to return +/- zero
 
189
| to the fpu.
 
190
|
 
191
tst_zero:
 
192
        clrw            FPTEMP_EX(%a6)
 
193
        tstb            L_SCR1(%a6)     |test for sign
 
194
        beqs            tst_con
 
195
        orw             #0x8000,FPTEMP_EX(%a6) |set sign bit
 
196
tst_con:
 
197
        movel           %d1,FPTEMP_HI(%a6)
 
198
        movel           %d2,FPTEMP_LO(%a6)
 
199
        movel           (%a7)+,%d2
 
200
        tstl            %d1
 
201
        bnes            not_zero
 
202
        tstl            FPTEMP_LO(%a6)
 
203
        bnes            not_zero
 
204
|
 
205
| Result is zero.  Check for rounding mode to set lsb.  If the
 
206
| mode is rp, and the zero is positive, return smallest denorm.
 
207
| If the mode is rm, and the zero is negative, return smallest
 
208
| negative denorm.
 
209
|
 
210
        btstb           #5,FPCR_MODE(%a6) |test if rm or rp
 
211
        beqs            no_dir
 
212
        btstb           #4,FPCR_MODE(%a6) |check which one
 
213
        beqs            zer_rm
 
214
zer_rp:
 
215
        tstb            L_SCR1(%a6)     |check sign
 
216
        bnes            no_dir          |if set, neg op, no inc
 
217
        movel           #1,FPTEMP_LO(%a6) |set lsb
 
218
        bras            sm_dnrm
 
219
zer_rm:
 
220
        tstb            L_SCR1(%a6)     |check sign
 
221
        beqs            no_dir          |if clr, neg op, no inc
 
222
        movel           #1,FPTEMP_LO(%a6) |set lsb
 
223
        orl             #neg_mask,USER_FPSR(%a6) |set N
 
224
        bras            sm_dnrm
 
225
no_dir:
 
226
        fmovel          USER_FPCR(%a6),%FPCR
 
227
        fmovex          FPTEMP(%a6),%fp0        |use fmove to set cc's
 
228
        rts
 
229
 
 
230
|
 
231
| The rounding mode changed the zero to a smallest denorm. Call
 
232
| t_resdnrm with exceptional operand in ETEMP.
 
233
|
 
234
sm_dnrm:
 
235
        movel           FPTEMP_EX(%a6),ETEMP_EX(%a6)
 
236
        movel           FPTEMP_HI(%a6),ETEMP_HI(%a6)
 
237
        movel           FPTEMP_LO(%a6),ETEMP_LO(%a6)
 
238
        leal            ETEMP(%a6),%a0
 
239
        bra             t_resdnrm
 
240
 
 
241
|
 
242
| Result is still denormalized.
 
243
|
 
244
not_zero:
 
245
        orl             #unfl_mask,USER_FPSR(%a6) |set unfl
 
246
        tstb            L_SCR1(%a6)     |check for sign
 
247
        beqs            fix_exit
 
248
        orl             #neg_mask,USER_FPSR(%a6) |set N
 
249
fix_exit:
 
250
        bras            sm_dnrm
 
251
 
 
252
 
 
253
|
 
254
| The result has underflowed to zero. Return zero and set
 
255
| unfl, aunfl, and ainex.
 
256
|
 
257
fix_unfl:
 
258
        orl             #unfl_inx_mask,USER_FPSR(%a6)
 
259
        btstb           #5,FPCR_MODE(%a6) |test if rm or rp
 
260
        beqs            no_dir2
 
261
        btstb           #4,FPCR_MODE(%a6) |check which one
 
262
        beqs            zer_rm2
 
263
zer_rp2:
 
264
        tstb            L_SCR1(%a6)     |check sign
 
265
        bnes            no_dir2         |if set, neg op, no inc
 
266
        clrl            FPTEMP_EX(%a6)
 
267
        clrl            FPTEMP_HI(%a6)
 
268
        movel           #1,FPTEMP_LO(%a6) |set lsb
 
269
        bras            sm_dnrm         |return smallest denorm
 
270
zer_rm2:
 
271
        tstb            L_SCR1(%a6)     |check sign
 
272
        beqs            no_dir2         |if clr, neg op, no inc
 
273
        movew           #0x8000,FPTEMP_EX(%a6)
 
274
        clrl            FPTEMP_HI(%a6)
 
275
        movel           #1,FPTEMP_LO(%a6) |set lsb
 
276
        orl             #neg_mask,USER_FPSR(%a6) |set N
 
277
        bra             sm_dnrm         |return smallest denorm
 
278
 
 
279
no_dir2:
 
280
        tstb            L_SCR1(%a6)
 
281
        bges            pos_zero
 
282
neg_zero:
 
283
        clrl            FP_SCR1(%a6)    |clear the exceptional operand
 
284
        clrl            FP_SCR1+4(%a6)  |for gen_except.
 
285
        clrl            FP_SCR1+8(%a6)
 
286
        fmoves          #0x80000000,%fp0
 
287
        rts
 
288
pos_zero:
 
289
        clrl            FP_SCR1(%a6)    |clear the exceptional operand
 
290
        clrl            FP_SCR1+4(%a6)  |for gen_except.
 
291
        clrl            FP_SCR1+8(%a6)
 
292
        fmoves          #0x00000000,%fp0
 
293
        rts
 
294
 
 
295
|
 
296
| The destination is a denormalized number.  It must be handled
 
297
| by first shifting the bits in the mantissa until it is normalized,
 
298
| then adding the remainder of the source to the exponent.
 
299
|
 
300
dst_dnrm:
 
301
        moveml          %d2/%d3,-(%a7)
 
302
        movew           FPTEMP_EX(%a6),%d1
 
303
        movel           FPTEMP_HI(%a6),%d2
 
304
        movel           FPTEMP_LO(%a6),%d3
 
305
dst_loop:
 
306
        tstl            %d2             |test for normalized result
 
307
        blts            dst_norm        |exit loop if so
 
308
        tstl            %d0             |otherwise, test shift count
 
309
        beqs            dst_fin         |if zero, shifting is done
 
310
        subil           #1,%d0          |dec src
 
311
        lsll            #1,%d3
 
312
        roxll           #1,%d2
 
313
        bras            dst_loop
 
314
|
 
315
| Destination became normalized.  Simply add the remaining
 
316
| portion of the src to the exponent.
 
317
|
 
318
dst_norm:
 
319
        addw            %d0,%d1         |dst is normalized; add src
 
320
        tstb            L_SCR1(%a6)
 
321
        beqs            dnrm_pos
 
322
        orl             #0x8000,%d1
 
323
dnrm_pos:
 
324
        movemw          %d1,FPTEMP_EX(%a6)
 
325
        moveml          %d2,FPTEMP_HI(%a6)
 
326
        moveml          %d3,FPTEMP_LO(%a6)
 
327
        fmovel          USER_FPCR(%a6),%FPCR
 
328
        fmovex          FPTEMP(%a6),%fp0
 
329
        moveml          (%a7)+,%d2/%d3
 
330
        rts
 
331
 
 
332
|
 
333
| Destination remained denormalized.  Call t_excdnrm with
 
334
| exceptional operand in ETEMP.
 
335
|
 
336
dst_fin:
 
337
        tstb            L_SCR1(%a6)     |check for sign
 
338
        beqs            dst_exit
 
339
        orl             #neg_mask,USER_FPSR(%a6) |set N
 
340
        orl             #0x8000,%d1
 
341
dst_exit:
 
342
        movemw          %d1,ETEMP_EX(%a6)
 
343
        moveml          %d2,ETEMP_HI(%a6)
 
344
        moveml          %d3,ETEMP_LO(%a6)
 
345
        orl             #unfl_mask,USER_FPSR(%a6) |set unfl
 
346
        moveml          (%a7)+,%d2/%d3
 
347
        leal            ETEMP(%a6),%a0
 
348
        bra             t_resdnrm
 
349
 
 
350
|
 
351
| Source is outside of 2^14 range.  Test the sign and branch
 
352
| to the appropriate exception handler.
 
353
|
 
354
src_out:
 
355
        tstb            L_SCR1(%a6)
 
356
        beqs            scro_pos
 
357
        orl             #0x8000,%d1
 
358
scro_pos:
 
359
        movel           FPTEMP_HI(%a6),ETEMP_HI(%a6)
 
360
        movel           FPTEMP_LO(%a6),ETEMP_LO(%a6)
 
361
        tstw            ETEMP(%a6)
 
362
        blts            res_neg
 
363
res_pos:
 
364
        movew           %d1,ETEMP(%a6)  |result in ETEMP
 
365
        bra             t_ovfl2
 
366
res_neg:
 
367
        movew           %d1,ETEMP(%a6)  |result in ETEMP
 
368
        leal            ETEMP(%a6),%a0
 
369
        bra             t_unfl
 
370
        |end