diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m68k/fpsp040/util.S |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/m68k/fpsp040/util.S')
-rw-r--r-- | arch/m68k/fpsp040/util.S | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/arch/m68k/fpsp040/util.S b/arch/m68k/fpsp040/util.S new file mode 100644 index 000000000000..452f3d65857b --- /dev/null +++ b/arch/m68k/fpsp040/util.S | |||
@@ -0,0 +1,748 @@ | |||
1 | | | ||
2 | | util.sa 3.7 7/29/91 | ||
3 | | | ||
4 | | This file contains routines used by other programs. | ||
5 | | | ||
6 | | ovf_res: used by overflow to force the correct | ||
7 | | result. ovf_r_k, ovf_r_x2, ovf_r_x3 are | ||
8 | | derivatives of this routine. | ||
9 | | get_fline: get user's opcode word | ||
10 | | g_dfmtou: returns the destination format. | ||
11 | | g_opcls: returns the opclass of the float instruction. | ||
12 | | g_rndpr: returns the rounding precision. | ||
13 | | reg_dest: write byte, word, or long data to Dn | ||
14 | | | ||
15 | | | ||
16 | | Copyright (C) Motorola, Inc. 1990 | ||
17 | | All Rights Reserved | ||
18 | | | ||
19 | | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA | ||
20 | | The copyright notice above does not evidence any | ||
21 | | actual or intended publication of such source code. | ||
22 | |||
23 | |UTIL idnt 2,1 | Motorola 040 Floating Point Software Package | ||
24 | |||
25 | |section 8 | ||
26 | |||
27 | #include "fpsp.h" | ||
28 | |||
29 | |xref mem_read | ||
30 | |||
31 | .global g_dfmtou | ||
32 | .global g_opcls | ||
33 | .global g_rndpr | ||
34 | .global get_fline | ||
35 | .global reg_dest | ||
36 | |||
37 | | | ||
38 | | Final result table for ovf_res. Note that the negative counterparts | ||
39 | | are unnecessary as ovf_res always returns the sign separately from | ||
40 | | the exponent. | ||
41 | | ;+inf | ||
42 | EXT_PINF: .long 0x7fff0000,0x00000000,0x00000000,0x00000000 | ||
43 | | ;largest +ext | ||
44 | EXT_PLRG: .long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 | ||
45 | | ;largest magnitude +sgl in ext | ||
46 | SGL_PLRG: .long 0x407e0000,0xffffff00,0x00000000,0x00000000 | ||
47 | | ;largest magnitude +dbl in ext | ||
48 | DBL_PLRG: .long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 | ||
49 | | ;largest -ext | ||
50 | |||
51 | tblovfl: | ||
52 | .long EXT_RN | ||
53 | .long EXT_RZ | ||
54 | .long EXT_RM | ||
55 | .long EXT_RP | ||
56 | .long SGL_RN | ||
57 | .long SGL_RZ | ||
58 | .long SGL_RM | ||
59 | .long SGL_RP | ||
60 | .long DBL_RN | ||
61 | .long DBL_RZ | ||
62 | .long DBL_RM | ||
63 | .long DBL_RP | ||
64 | .long error | ||
65 | .long error | ||
66 | .long error | ||
67 | .long error | ||
68 | |||
69 | |||
70 | | | ||
71 | | ovf_r_k --- overflow result calculation | ||
72 | | | ||
73 | | This entry point is used by kernel_ex. | ||
74 | | | ||
75 | | This forces the destination precision to be extended | ||
76 | | | ||
77 | | Input: operand in ETEMP | ||
78 | | Output: a result is in ETEMP (internal extended format) | ||
79 | | | ||
80 | .global ovf_r_k | ||
81 | ovf_r_k: | ||
82 | lea ETEMP(%a6),%a0 |a0 points to source operand | ||
83 | bclrb #sign_bit,ETEMP_EX(%a6) | ||
84 | sne ETEMP_SGN(%a6) |convert to internal IEEE format | ||
85 | |||
86 | | | ||
87 | | ovf_r_x2 --- overflow result calculation | ||
88 | | | ||
89 | | This entry point used by x_ovfl. (opclass 0 and 2) | ||
90 | | | ||
91 | | Input a0 points to an operand in the internal extended format | ||
92 | | Output a0 points to the result in the internal extended format | ||
93 | | | ||
94 | | This sets the round precision according to the user's FPCR unless the | ||
95 | | instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul, | ||
96 | | fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg. | ||
97 | | If the instruction is fsgldiv of fsglmul, the rounding precision must be | ||
98 | | extended. If the instruction is not fsgldiv or fsglmul but a force- | ||
99 | | precision instruction, the rounding precision is then set to the force | ||
100 | | precision. | ||
101 | |||
102 | .global ovf_r_x2 | ||
103 | ovf_r_x2: | ||
104 | btstb #E3,E_BYTE(%a6) |check for nu exception | ||
105 | beql ovf_e1_exc |it is cu exception | ||
106 | ovf_e3_exc: | ||
107 | movew CMDREG3B(%a6),%d0 |get the command word | ||
108 | andiw #0x00000060,%d0 |clear all bits except 6 and 5 | ||
109 | cmpil #0x00000040,%d0 | ||
110 | beql ovff_sgl |force precision is single | ||
111 | cmpil #0x00000060,%d0 | ||
112 | beql ovff_dbl |force precision is double | ||
113 | movew CMDREG3B(%a6),%d0 |get the command word again | ||
114 | andil #0x7f,%d0 |clear all except operation | ||
115 | cmpil #0x33,%d0 | ||
116 | beql ovf_fsgl |fsglmul or fsgldiv | ||
117 | cmpil #0x30,%d0 | ||
118 | beql ovf_fsgl | ||
119 | bra ovf_fpcr |instruction is none of the above | ||
120 | | ;use FPCR | ||
121 | ovf_e1_exc: | ||
122 | movew CMDREG1B(%a6),%d0 |get command word | ||
123 | andil #0x00000044,%d0 |clear all bits except 6 and 2 | ||
124 | cmpil #0x00000040,%d0 | ||
125 | beql ovff_sgl |the instruction is force single | ||
126 | cmpil #0x00000044,%d0 | ||
127 | beql ovff_dbl |the instruction is force double | ||
128 | movew CMDREG1B(%a6),%d0 |again get the command word | ||
129 | andil #0x0000007f,%d0 |clear all except the op code | ||
130 | cmpil #0x00000027,%d0 | ||
131 | beql ovf_fsgl |fsglmul | ||
132 | cmpil #0x00000024,%d0 | ||
133 | beql ovf_fsgl |fsgldiv | ||
134 | bra ovf_fpcr |none of the above, use FPCR | ||
135 | | | ||
136 | | | ||
137 | | Inst is either fsgldiv or fsglmul. Force extended precision. | ||
138 | | | ||
139 | ovf_fsgl: | ||
140 | clrl %d0 | ||
141 | bra ovf_res | ||
142 | |||
143 | ovff_sgl: | ||
144 | movel #0x00000001,%d0 |set single | ||
145 | bra ovf_res | ||
146 | ovff_dbl: | ||
147 | movel #0x00000002,%d0 |set double | ||
148 | bra ovf_res | ||
149 | | | ||
150 | | The precision is in the fpcr. | ||
151 | | | ||
152 | ovf_fpcr: | ||
153 | bfextu FPCR_MODE(%a6){#0:#2},%d0 |set round precision | ||
154 | bra ovf_res | ||
155 | |||
156 | | | ||
157 | | | ||
158 | | ovf_r_x3 --- overflow result calculation | ||
159 | | | ||
160 | | This entry point used by x_ovfl. (opclass 3 only) | ||
161 | | | ||
162 | | Input a0 points to an operand in the internal extended format | ||
163 | | Output a0 points to the result in the internal extended format | ||
164 | | | ||
165 | | This sets the round precision according to the destination size. | ||
166 | | | ||
167 | .global ovf_r_x3 | ||
168 | ovf_r_x3: | ||
169 | bsr g_dfmtou |get dest fmt in d0{1:0} | ||
170 | | ;for fmovout, the destination format | ||
171 | | ;is the rounding precision | ||
172 | |||
173 | | | ||
174 | | ovf_res --- overflow result calculation | ||
175 | | | ||
176 | | Input: | ||
177 | | a0 points to operand in internal extended format | ||
178 | | Output: | ||
179 | | a0 points to result in internal extended format | ||
180 | | | ||
181 | .global ovf_res | ||
182 | ovf_res: | ||
183 | lsll #2,%d0 |move round precision to d0{3:2} | ||
184 | bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode | ||
185 | orl %d1,%d0 |index is fmt:mode in d0{3:0} | ||
186 | leal tblovfl,%a1 |load a1 with table address | ||
187 | movel %a1@(%d0:l:4),%a1 |use d0 as index to the table | ||
188 | jmp (%a1) |go to the correct routine | ||
189 | | | ||
190 | |case DEST_FMT = EXT | ||
191 | | | ||
192 | EXT_RN: | ||
193 | leal EXT_PINF,%a1 |answer is +/- infinity | ||
194 | bsetb #inf_bit,FPSR_CC(%a6) | ||
195 | bra set_sign |now go set the sign | ||
196 | EXT_RZ: | ||
197 | leal EXT_PLRG,%a1 |answer is +/- large number | ||
198 | bra set_sign |now go set the sign | ||
199 | EXT_RM: | ||
200 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
201 | beqs e_rm_pos | ||
202 | e_rm_neg: | ||
203 | leal EXT_PINF,%a1 |answer is negative infinity | ||
204 | orl #neginf_mask,USER_FPSR(%a6) | ||
205 | bra end_ovfr | ||
206 | e_rm_pos: | ||
207 | leal EXT_PLRG,%a1 |answer is large positive number | ||
208 | bra end_ovfr | ||
209 | EXT_RP: | ||
210 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
211 | beqs e_rp_pos | ||
212 | e_rp_neg: | ||
213 | leal EXT_PLRG,%a1 |answer is large negative number | ||
214 | bsetb #neg_bit,FPSR_CC(%a6) | ||
215 | bra end_ovfr | ||
216 | e_rp_pos: | ||
217 | leal EXT_PINF,%a1 |answer is positive infinity | ||
218 | bsetb #inf_bit,FPSR_CC(%a6) | ||
219 | bra end_ovfr | ||
220 | | | ||
221 | |case DEST_FMT = DBL | ||
222 | | | ||
223 | DBL_RN: | ||
224 | leal EXT_PINF,%a1 |answer is +/- infinity | ||
225 | bsetb #inf_bit,FPSR_CC(%a6) | ||
226 | bra set_sign | ||
227 | DBL_RZ: | ||
228 | leal DBL_PLRG,%a1 |answer is +/- large number | ||
229 | bra set_sign |now go set the sign | ||
230 | DBL_RM: | ||
231 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
232 | beqs d_rm_pos | ||
233 | d_rm_neg: | ||
234 | leal EXT_PINF,%a1 |answer is negative infinity | ||
235 | orl #neginf_mask,USER_FPSR(%a6) | ||
236 | bra end_ovfr |inf is same for all precisions (ext,dbl,sgl) | ||
237 | d_rm_pos: | ||
238 | leal DBL_PLRG,%a1 |answer is large positive number | ||
239 | bra end_ovfr | ||
240 | DBL_RP: | ||
241 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
242 | beqs d_rp_pos | ||
243 | d_rp_neg: | ||
244 | leal DBL_PLRG,%a1 |answer is large negative number | ||
245 | bsetb #neg_bit,FPSR_CC(%a6) | ||
246 | bra end_ovfr | ||
247 | d_rp_pos: | ||
248 | leal EXT_PINF,%a1 |answer is positive infinity | ||
249 | bsetb #inf_bit,FPSR_CC(%a6) | ||
250 | bra end_ovfr | ||
251 | | | ||
252 | |case DEST_FMT = SGL | ||
253 | | | ||
254 | SGL_RN: | ||
255 | leal EXT_PINF,%a1 |answer is +/- infinity | ||
256 | bsetb #inf_bit,FPSR_CC(%a6) | ||
257 | bras set_sign | ||
258 | SGL_RZ: | ||
259 | leal SGL_PLRG,%a1 |answer is +/- large number | ||
260 | bras set_sign | ||
261 | SGL_RM: | ||
262 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
263 | beqs s_rm_pos | ||
264 | s_rm_neg: | ||
265 | leal EXT_PINF,%a1 |answer is negative infinity | ||
266 | orl #neginf_mask,USER_FPSR(%a6) | ||
267 | bras end_ovfr | ||
268 | s_rm_pos: | ||
269 | leal SGL_PLRG,%a1 |answer is large positive number | ||
270 | bras end_ovfr | ||
271 | SGL_RP: | ||
272 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
273 | beqs s_rp_pos | ||
274 | s_rp_neg: | ||
275 | leal SGL_PLRG,%a1 |answer is large negative number | ||
276 | bsetb #neg_bit,FPSR_CC(%a6) | ||
277 | bras end_ovfr | ||
278 | s_rp_pos: | ||
279 | leal EXT_PINF,%a1 |answer is positive infinity | ||
280 | bsetb #inf_bit,FPSR_CC(%a6) | ||
281 | bras end_ovfr | ||
282 | |||
283 | set_sign: | ||
284 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
285 | beqs end_ovfr | ||
286 | neg_sign: | ||
287 | bsetb #neg_bit,FPSR_CC(%a6) | ||
288 | |||
289 | end_ovfr: | ||
290 | movew LOCAL_EX(%a1),LOCAL_EX(%a0) |do not overwrite sign | ||
291 | movel LOCAL_HI(%a1),LOCAL_HI(%a0) | ||
292 | movel LOCAL_LO(%a1),LOCAL_LO(%a0) | ||
293 | rts | ||
294 | |||
295 | |||
296 | | | ||
297 | | ERROR | ||
298 | | | ||
299 | error: | ||
300 | rts | ||
301 | | | ||
302 | | get_fline --- get f-line opcode of interrupted instruction | ||
303 | | | ||
304 | | Returns opcode in the low word of d0. | ||
305 | | | ||
306 | get_fline: | ||
307 | movel USER_FPIAR(%a6),%a0 |opcode address | ||
308 | movel #0,-(%a7) |reserve a word on the stack | ||
309 | leal 2(%a7),%a1 |point to low word of temporary | ||
310 | movel #2,%d0 |count | ||
311 | bsrl mem_read | ||
312 | movel (%a7)+,%d0 | ||
313 | rts | ||
314 | | | ||
315 | | g_rndpr --- put rounding precision in d0{1:0} | ||
316 | | | ||
317 | | valid return codes are: | ||
318 | | 00 - extended | ||
319 | | 01 - single | ||
320 | | 10 - double | ||
321 | | | ||
322 | | begin | ||
323 | | get rounding precision (cmdreg3b{6:5}) | ||
324 | | begin | ||
325 | | case opclass = 011 (move out) | ||
326 | | get destination format - this is the also the rounding precision | ||
327 | | | ||
328 | | case opclass = 0x0 | ||
329 | | if E3 | ||
330 | | *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL | ||
331 | | *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL | ||
332 | | case RndPr(from cmdreg3b{6:5} = 00 | 01 | ||
333 | | use precision from FPCR{7:6} | ||
334 | | case 00 then RND_PREC = EXT | ||
335 | | case 01 then RND_PREC = SGL | ||
336 | | case 10 then RND_PREC = DBL | ||
337 | | else E1 | ||
338 | | use precision in FPCR{7:6} | ||
339 | | case 00 then RND_PREC = EXT | ||
340 | | case 01 then RND_PREC = SGL | ||
341 | | case 10 then RND_PREC = DBL | ||
342 | | end | ||
343 | | | ||
344 | g_rndpr: | ||
345 | bsr g_opcls |get opclass in d0{2:0} | ||
346 | cmpw #0x0003,%d0 |check for opclass 011 | ||
347 | bnes op_0x0 | ||
348 | |||
349 | | | ||
350 | | For move out instructions (opclass 011) the destination format | ||
351 | | is the same as the rounding precision. Pass results from g_dfmtou. | ||
352 | | | ||
353 | bsr g_dfmtou | ||
354 | rts | ||
355 | op_0x0: | ||
356 | btstb #E3,E_BYTE(%a6) | ||
357 | beql unf_e1_exc |branch to e1 underflow | ||
358 | unf_e3_exc: | ||
359 | movel CMDREG3B(%a6),%d0 |rounding precision in d0{10:9} | ||
360 | bfextu %d0{#9:#2},%d0 |move the rounding prec bits to d0{1:0} | ||
361 | cmpil #0x2,%d0 | ||
362 | beql unff_sgl |force precision is single | ||
363 | cmpil #0x3,%d0 |force precision is double | ||
364 | beql unff_dbl | ||
365 | movew CMDREG3B(%a6),%d0 |get the command word again | ||
366 | andil #0x7f,%d0 |clear all except operation | ||
367 | cmpil #0x33,%d0 | ||
368 | beql unf_fsgl |fsglmul or fsgldiv | ||
369 | cmpil #0x30,%d0 | ||
370 | beql unf_fsgl |fsgldiv or fsglmul | ||
371 | bra unf_fpcr | ||
372 | unf_e1_exc: | ||
373 | movel CMDREG1B(%a6),%d0 |get 32 bits off the stack, 1st 16 bits | ||
374 | | ;are the command word | ||
375 | andil #0x00440000,%d0 |clear all bits except bits 6 and 2 | ||
376 | cmpil #0x00400000,%d0 | ||
377 | beql unff_sgl |force single | ||
378 | cmpil #0x00440000,%d0 |force double | ||
379 | beql unff_dbl | ||
380 | movel CMDREG1B(%a6),%d0 |get the command word again | ||
381 | andil #0x007f0000,%d0 |clear all bits except the operation | ||
382 | cmpil #0x00270000,%d0 | ||
383 | beql unf_fsgl |fsglmul | ||
384 | cmpil #0x00240000,%d0 | ||
385 | beql unf_fsgl |fsgldiv | ||
386 | bra unf_fpcr | ||
387 | |||
388 | | | ||
389 | | Convert to return format. The values from cmdreg3b and the return | ||
390 | | values are: | ||
391 | | cmdreg3b return precision | ||
392 | | -------- ------ --------- | ||
393 | | 00,01 0 ext | ||
394 | | 10 1 sgl | ||
395 | | 11 2 dbl | ||
396 | | Force single | ||
397 | | | ||
398 | unff_sgl: | ||
399 | movel #1,%d0 |return 1 | ||
400 | rts | ||
401 | | | ||
402 | | Force double | ||
403 | | | ||
404 | unff_dbl: | ||
405 | movel #2,%d0 |return 2 | ||
406 | rts | ||
407 | | | ||
408 | | Force extended | ||
409 | | | ||
410 | unf_fsgl: | ||
411 | movel #0,%d0 | ||
412 | rts | ||
413 | | | ||
414 | | Get rounding precision set in FPCR{7:6}. | ||
415 | | | ||
416 | unf_fpcr: | ||
417 | movel USER_FPCR(%a6),%d0 |rounding precision bits in d0{7:6} | ||
418 | bfextu %d0{#24:#2},%d0 |move the rounding prec bits to d0{1:0} | ||
419 | rts | ||
420 | | | ||
421 | | g_opcls --- put opclass in d0{2:0} | ||
422 | | | ||
423 | g_opcls: | ||
424 | btstb #E3,E_BYTE(%a6) | ||
425 | beqs opc_1b |if set, go to cmdreg1b | ||
426 | opc_3b: | ||
427 | clrl %d0 |if E3, only opclass 0x0 is possible | ||
428 | rts | ||
429 | opc_1b: | ||
430 | movel CMDREG1B(%a6),%d0 | ||
431 | bfextu %d0{#0:#3},%d0 |shift opclass bits d0{31:29} to d0{2:0} | ||
432 | rts | ||
433 | | | ||
434 | | g_dfmtou --- put destination format in d0{1:0} | ||
435 | | | ||
436 | | If E1, the format is from cmdreg1b{12:10} | ||
437 | | If E3, the format is extended. | ||
438 | | | ||
439 | | Dest. Fmt. | ||
440 | | extended 010 -> 00 | ||
441 | | single 001 -> 01 | ||
442 | | double 101 -> 10 | ||
443 | | | ||
444 | g_dfmtou: | ||
445 | btstb #E3,E_BYTE(%a6) | ||
446 | beqs op011 | ||
447 | clrl %d0 |if E1, size is always ext | ||
448 | rts | ||
449 | op011: | ||
450 | movel CMDREG1B(%a6),%d0 | ||
451 | bfextu %d0{#3:#3},%d0 |dest fmt from cmdreg1b{12:10} | ||
452 | cmpb #1,%d0 |check for single | ||
453 | bnes not_sgl | ||
454 | movel #1,%d0 | ||
455 | rts | ||
456 | not_sgl: | ||
457 | cmpb #5,%d0 |check for double | ||
458 | bnes not_dbl | ||
459 | movel #2,%d0 | ||
460 | rts | ||
461 | not_dbl: | ||
462 | clrl %d0 |must be extended | ||
463 | rts | ||
464 | |||
465 | | | ||
466 | | | ||
467 | | Final result table for unf_sub. Note that the negative counterparts | ||
468 | | are unnecessary as unf_sub always returns the sign separately from | ||
469 | | the exponent. | ||
470 | | ;+zero | ||
471 | EXT_PZRO: .long 0x00000000,0x00000000,0x00000000,0x00000000 | ||
472 | | ;+zero | ||
473 | SGL_PZRO: .long 0x3f810000,0x00000000,0x00000000,0x00000000 | ||
474 | | ;+zero | ||
475 | DBL_PZRO: .long 0x3c010000,0x00000000,0x00000000,0x00000000 | ||
476 | | ;smallest +ext denorm | ||
477 | EXT_PSML: .long 0x00000000,0x00000000,0x00000001,0x00000000 | ||
478 | | ;smallest +sgl denorm | ||
479 | SGL_PSML: .long 0x3f810000,0x00000100,0x00000000,0x00000000 | ||
480 | | ;smallest +dbl denorm | ||
481 | DBL_PSML: .long 0x3c010000,0x00000000,0x00000800,0x00000000 | ||
482 | | | ||
483 | | UNF_SUB --- underflow result calculation | ||
484 | | | ||
485 | | Input: | ||
486 | | d0 contains round precision | ||
487 | | a0 points to input operand in the internal extended format | ||
488 | | | ||
489 | | Output: | ||
490 | | a0 points to correct internal extended precision result. | ||
491 | | | ||
492 | |||
493 | tblunf: | ||
494 | .long uEXT_RN | ||
495 | .long uEXT_RZ | ||
496 | .long uEXT_RM | ||
497 | .long uEXT_RP | ||
498 | .long uSGL_RN | ||
499 | .long uSGL_RZ | ||
500 | .long uSGL_RM | ||
501 | .long uSGL_RP | ||
502 | .long uDBL_RN | ||
503 | .long uDBL_RZ | ||
504 | .long uDBL_RM | ||
505 | .long uDBL_RP | ||
506 | .long uDBL_RN | ||
507 | .long uDBL_RZ | ||
508 | .long uDBL_RM | ||
509 | .long uDBL_RP | ||
510 | |||
511 | .global unf_sub | ||
512 | unf_sub: | ||
513 | lsll #2,%d0 |move round precision to d0{3:2} | ||
514 | bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode | ||
515 | orl %d1,%d0 |index is fmt:mode in d0{3:0} | ||
516 | leal tblunf,%a1 |load a1 with table address | ||
517 | movel %a1@(%d0:l:4),%a1 |use d0 as index to the table | ||
518 | jmp (%a1) |go to the correct routine | ||
519 | | | ||
520 | |case DEST_FMT = EXT | ||
521 | | | ||
522 | uEXT_RN: | ||
523 | leal EXT_PZRO,%a1 |answer is +/- zero | ||
524 | bsetb #z_bit,FPSR_CC(%a6) | ||
525 | bra uset_sign |now go set the sign | ||
526 | uEXT_RZ: | ||
527 | leal EXT_PZRO,%a1 |answer is +/- zero | ||
528 | bsetb #z_bit,FPSR_CC(%a6) | ||
529 | bra uset_sign |now go set the sign | ||
530 | uEXT_RM: | ||
531 | tstb LOCAL_SGN(%a0) |if negative underflow | ||
532 | beqs ue_rm_pos | ||
533 | ue_rm_neg: | ||
534 | leal EXT_PSML,%a1 |answer is negative smallest denorm | ||
535 | bsetb #neg_bit,FPSR_CC(%a6) | ||
536 | bra end_unfr | ||
537 | ue_rm_pos: | ||
538 | leal EXT_PZRO,%a1 |answer is positive zero | ||
539 | bsetb #z_bit,FPSR_CC(%a6) | ||
540 | bra end_unfr | ||
541 | uEXT_RP: | ||
542 | tstb LOCAL_SGN(%a0) |if negative underflow | ||
543 | beqs ue_rp_pos | ||
544 | ue_rp_neg: | ||
545 | leal EXT_PZRO,%a1 |answer is negative zero | ||
546 | oril #negz_mask,USER_FPSR(%a6) | ||
547 | bra end_unfr | ||
548 | ue_rp_pos: | ||
549 | leal EXT_PSML,%a1 |answer is positive smallest denorm | ||
550 | bra end_unfr | ||
551 | | | ||
552 | |case DEST_FMT = DBL | ||
553 | | | ||
554 | uDBL_RN: | ||
555 | leal DBL_PZRO,%a1 |answer is +/- zero | ||
556 | bsetb #z_bit,FPSR_CC(%a6) | ||
557 | bra uset_sign | ||
558 | uDBL_RZ: | ||
559 | leal DBL_PZRO,%a1 |answer is +/- zero | ||
560 | bsetb #z_bit,FPSR_CC(%a6) | ||
561 | bra uset_sign |now go set the sign | ||
562 | uDBL_RM: | ||
563 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
564 | beqs ud_rm_pos | ||
565 | ud_rm_neg: | ||
566 | leal DBL_PSML,%a1 |answer is smallest denormalized negative | ||
567 | bsetb #neg_bit,FPSR_CC(%a6) | ||
568 | bra end_unfr | ||
569 | ud_rm_pos: | ||
570 | leal DBL_PZRO,%a1 |answer is positive zero | ||
571 | bsetb #z_bit,FPSR_CC(%a6) | ||
572 | bra end_unfr | ||
573 | uDBL_RP: | ||
574 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
575 | beqs ud_rp_pos | ||
576 | ud_rp_neg: | ||
577 | leal DBL_PZRO,%a1 |answer is negative zero | ||
578 | oril #negz_mask,USER_FPSR(%a6) | ||
579 | bra end_unfr | ||
580 | ud_rp_pos: | ||
581 | leal DBL_PSML,%a1 |answer is smallest denormalized negative | ||
582 | bra end_unfr | ||
583 | | | ||
584 | |case DEST_FMT = SGL | ||
585 | | | ||
586 | uSGL_RN: | ||
587 | leal SGL_PZRO,%a1 |answer is +/- zero | ||
588 | bsetb #z_bit,FPSR_CC(%a6) | ||
589 | bras uset_sign | ||
590 | uSGL_RZ: | ||
591 | leal SGL_PZRO,%a1 |answer is +/- zero | ||
592 | bsetb #z_bit,FPSR_CC(%a6) | ||
593 | bras uset_sign | ||
594 | uSGL_RM: | ||
595 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
596 | beqs us_rm_pos | ||
597 | us_rm_neg: | ||
598 | leal SGL_PSML,%a1 |answer is smallest denormalized negative | ||
599 | bsetb #neg_bit,FPSR_CC(%a6) | ||
600 | bras end_unfr | ||
601 | us_rm_pos: | ||
602 | leal SGL_PZRO,%a1 |answer is positive zero | ||
603 | bsetb #z_bit,FPSR_CC(%a6) | ||
604 | bras end_unfr | ||
605 | uSGL_RP: | ||
606 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
607 | beqs us_rp_pos | ||
608 | us_rp_neg: | ||
609 | leal SGL_PZRO,%a1 |answer is negative zero | ||
610 | oril #negz_mask,USER_FPSR(%a6) | ||
611 | bras end_unfr | ||
612 | us_rp_pos: | ||
613 | leal SGL_PSML,%a1 |answer is smallest denormalized positive | ||
614 | bras end_unfr | ||
615 | |||
616 | uset_sign: | ||
617 | tstb LOCAL_SGN(%a0) |if negative overflow | ||
618 | beqs end_unfr | ||
619 | uneg_sign: | ||
620 | bsetb #neg_bit,FPSR_CC(%a6) | ||
621 | |||
622 | end_unfr: | ||
623 | movew LOCAL_EX(%a1),LOCAL_EX(%a0) |be careful not to overwrite sign | ||
624 | movel LOCAL_HI(%a1),LOCAL_HI(%a0) | ||
625 | movel LOCAL_LO(%a1),LOCAL_LO(%a0) | ||
626 | rts | ||
627 | | | ||
628 | | reg_dest --- write byte, word, or long data to Dn | ||
629 | | | ||
630 | | | ||
631 | | Input: | ||
632 | | L_SCR1: Data | ||
633 | | d1: data size and dest register number formatted as: | ||
634 | | | ||
635 | | 32 5 4 3 2 1 0 | ||
636 | | ----------------------------------------------- | ||
637 | | | 0 | Size | Dest Reg # | | ||
638 | | ----------------------------------------------- | ||
639 | | | ||
640 | | Size is: | ||
641 | | 0 - Byte | ||
642 | | 1 - Word | ||
643 | | 2 - Long/Single | ||
644 | | | ||
645 | pregdst: | ||
646 | .long byte_d0 | ||
647 | .long byte_d1 | ||
648 | .long byte_d2 | ||
649 | .long byte_d3 | ||
650 | .long byte_d4 | ||
651 | .long byte_d5 | ||
652 | .long byte_d6 | ||
653 | .long byte_d7 | ||
654 | .long word_d0 | ||
655 | .long word_d1 | ||
656 | .long word_d2 | ||
657 | .long word_d3 | ||
658 | .long word_d4 | ||
659 | .long word_d5 | ||
660 | .long word_d6 | ||
661 | .long word_d7 | ||
662 | .long long_d0 | ||
663 | .long long_d1 | ||
664 | .long long_d2 | ||
665 | .long long_d3 | ||
666 | .long long_d4 | ||
667 | .long long_d5 | ||
668 | .long long_d6 | ||
669 | .long long_d7 | ||
670 | |||
671 | reg_dest: | ||
672 | leal pregdst,%a0 | ||
673 | movel %a0@(%d1:l:4),%a0 | ||
674 | jmp (%a0) | ||
675 | |||
676 | byte_d0: | ||
677 | moveb L_SCR1(%a6),USER_D0+3(%a6) | ||
678 | rts | ||
679 | byte_d1: | ||
680 | moveb L_SCR1(%a6),USER_D1+3(%a6) | ||
681 | rts | ||
682 | byte_d2: | ||
683 | moveb L_SCR1(%a6),%d2 | ||
684 | rts | ||
685 | byte_d3: | ||
686 | moveb L_SCR1(%a6),%d3 | ||
687 | rts | ||
688 | byte_d4: | ||
689 | moveb L_SCR1(%a6),%d4 | ||
690 | rts | ||
691 | byte_d5: | ||
692 | moveb L_SCR1(%a6),%d5 | ||
693 | rts | ||
694 | byte_d6: | ||
695 | moveb L_SCR1(%a6),%d6 | ||
696 | rts | ||
697 | byte_d7: | ||
698 | moveb L_SCR1(%a6),%d7 | ||
699 | rts | ||
700 | word_d0: | ||
701 | movew L_SCR1(%a6),USER_D0+2(%a6) | ||
702 | rts | ||
703 | word_d1: | ||
704 | movew L_SCR1(%a6),USER_D1+2(%a6) | ||
705 | rts | ||
706 | word_d2: | ||
707 | movew L_SCR1(%a6),%d2 | ||
708 | rts | ||
709 | word_d3: | ||
710 | movew L_SCR1(%a6),%d3 | ||
711 | rts | ||
712 | word_d4: | ||
713 | movew L_SCR1(%a6),%d4 | ||
714 | rts | ||
715 | word_d5: | ||
716 | movew L_SCR1(%a6),%d5 | ||
717 | rts | ||
718 | word_d6: | ||
719 | movew L_SCR1(%a6),%d6 | ||
720 | rts | ||
721 | word_d7: | ||
722 | movew L_SCR1(%a6),%d7 | ||
723 | rts | ||
724 | long_d0: | ||
725 | movel L_SCR1(%a6),USER_D0(%a6) | ||
726 | rts | ||
727 | long_d1: | ||
728 | movel L_SCR1(%a6),USER_D1(%a6) | ||
729 | rts | ||
730 | long_d2: | ||
731 | movel L_SCR1(%a6),%d2 | ||
732 | rts | ||
733 | long_d3: | ||
734 | movel L_SCR1(%a6),%d3 | ||
735 | rts | ||
736 | long_d4: | ||
737 | movel L_SCR1(%a6),%d4 | ||
738 | rts | ||
739 | long_d5: | ||
740 | movel L_SCR1(%a6),%d5 | ||
741 | rts | ||
742 | long_d6: | ||
743 | movel L_SCR1(%a6),%d6 | ||
744 | rts | ||
745 | long_d7: | ||
746 | movel L_SCR1(%a6),%d7 | ||
747 | rts | ||
748 | |end | ||