Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/m68k/fpsp040/scale.S
10817 views
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
371
372