1 * $NetBSD: util.sa,v 1.3 1994/10/26 07:50:20 cgd Exp $
3 * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
4 * M68000 Hi-Performance Microprocessor Division
5 * M68040 Software Package
7 * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
10 * THE SOFTWARE is provided on an "AS IS" basis and without warranty.
11 * To the maximum extent permitted by applicable law,
12 * MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
13 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
14 * PARTICULAR PURPOSE and any warranty against infringement with
15 * regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
16 * and any accompanying written materials.
18 * To the maximum extent permitted by applicable law,
19 * IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
20 * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
21 * PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
22 * OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
23 * SOFTWARE. Motorola assumes no responsibility for the maintenance
24 * and support of the SOFTWARE.
26 * You are hereby granted a copyright license to use, modify, and
27 * distribute the SOFTWARE so long as this entire notice is retained
28 * without alteration in any modified and/or redistributed versions,
29 * and that such modified versions are clearly identified as such.
30 * No licenses are granted by implication, estoppel or otherwise
31 * under any patents or trademarks of Motorola, Inc.
36 * This file contains routines used by other programs.
38 * ovf_res: used by overflow to force the correct
39 * result. ovf_r_k, ovf_r_x2, ovf_r_x3 are
40 * derivatives of this routine.
41 * get_fline: get user's opcode word
42 * g_dfmtou: returns the destination format.
43 * g_opcls: returns the opclass of the float instruction.
44 * g_rndpr: returns the rounding precision.
45 * reg_dest: write byte, word, or long data to Dn
48 UTIL IDNT 2,1 Motorola 040 Floating Point Software Package
63 * Final result table for ovf_res. Note that the negative counterparts
64 * are unnecessary as ovf_res always returns the sign separately from
67 EXT_PINF dc.l $7fff0000,$00000000,$00000000,$00000000
69 EXT_PLRG dc.l $7ffe0000,$ffffffff,$ffffffff,$00000000
70 * ;largest magnitude +sgl in ext
71 SGL_PLRG dc.l $407e0000,$ffffff00,$00000000,$00000000
72 * ;largest magnitude +dbl in ext
73 DBL_PLRG dc.l $43fe0000,$ffffffff,$fffff800,$00000000
96 * ovf_r_k --- overflow result calculation
98 * This entry point is used by kernel_ex.
100 * This forces the destination precision to be extended
102 * Input: operand in ETEMP
103 * Output: a result is in ETEMP (internal extended format)
107 lea ETEMP(a6),a0 ;a0 points to source operand
108 bclr.b #sign_bit,ETEMP_EX(a6)
109 sne ETEMP_SGN(a6) ;convert to internal IEEE format
112 * ovf_r_x2 --- overflow result calculation
114 * This entry point used by x_ovfl. (opclass 0 and 2)
116 * Input a0 points to an operand in the internal extended format
117 * Output a0 points to the result in the internal extended format
119 * This sets the round precision according to the user's FPCR unless the
120 * instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul,
121 * fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg.
122 * If the instruction is fsgldiv of fsglmul, the rounding precision must be
123 * extended. If the instruction is not fsgldiv or fsglmul but a force-
124 * precision instruction, the rounding precision is then set to the force
129 btst.b #E3,E_BYTE(a6) ;check for nu exception
130 beq.l ovf_e1_exc ;it is cu exception
132 move.w CMDREG3B(a6),d0 ;get the command word
133 andi.w #$00000060,d0 ;clear all bits except 6 and 5
135 beq.l ovff_sgl ;force precision is single
137 beq.l ovff_dbl ;force precision is double
138 move.w CMDREG3B(a6),d0 ;get the command word again
139 andi.l #$7f,d0 ;clear all except operation
141 beq.l ovf_fsgl ;fsglmul or fsgldiv
144 bra ovf_fpcr ;instruction is none of the above
147 move.w CMDREG1B(a6),d0 ;get command word
148 andi.l #$00000044,d0 ;clear all bits except 6 and 2
150 beq.l ovff_sgl ;the instruction is force single
152 beq.l ovff_dbl ;the instruction is force double
153 move.w CMDREG1B(a6),d0 ;again get the command word
154 andi.l #$0000007f,d0 ;clear all except the op code
156 beq.l ovf_fsgl ;fsglmul
158 beq.l ovf_fsgl ;fsgldiv
159 bra ovf_fpcr ;none of the above, use FPCR
162 * Inst is either fsgldiv or fsglmul. Force extended precision.
169 move.l #$00000001,d0 ;set single
172 move.l #$00000002,d0 ;set double
175 * The precision is in the fpcr.
178 bfextu FPCR_MODE(a6){0:2},d0 ;set round precision
183 * ovf_r_x3 --- overflow result calculation
185 * This entry point used by x_ovfl. (opclass 3 only)
187 * Input a0 points to an operand in the internal extended format
188 * Output a0 points to the result in the internal extended format
190 * This sets the round precision according to the destination size.
194 bsr g_dfmtou ;get dest fmt in d0{1:0}
195 * ;for fmovout, the destination format
196 * ;is the rounding precision
199 * ovf_res --- overflow result calculation
202 * a0 points to operand in internal extended format
204 * a0 points to result in internal extended format
209 lsl.l #2,d0 ;move round precision to d0{3:2}
210 bfextu FPCR_MODE(a6){2:2},d1 ;set round mode
211 or.l d1,d0 ;index is fmt:mode in d0{3:0}
212 lea.l tblovfl,a1 ;load a1 with table address
213 move.l (a1,d0*4),a1 ;use d0 as index to the table
214 jmp (a1) ;go to the correct routine
219 lea.l EXT_PINF,a1 ;answer is +/- infinity
220 bset.b #inf_bit,FPSR_CC(a6)
221 bra set_sign ;now go set the sign
223 lea.l EXT_PLRG,a1 ;answer is +/- large number
224 bra set_sign ;now go set the sign
226 tst.b LOCAL_SGN(a0) ;if negative overflow
229 lea.l EXT_PINF,a1 ;answer is negative infinity
230 or.l #neginf_mask,USER_FPSR(a6)
233 lea.l EXT_PLRG,a1 ;answer is large positive number
236 tst.b LOCAL_SGN(a0) ;if negative overflow
239 lea.l EXT_PLRG,a1 ;answer is large negative number
240 bset.b #neg_bit,FPSR_CC(a6)
243 lea.l EXT_PINF,a1 ;answer is positive infinity
244 bset.b #inf_bit,FPSR_CC(a6)
250 lea.l EXT_PINF,a1 ;answer is +/- infinity
251 bset.b #inf_bit,FPSR_CC(a6)
254 lea.l DBL_PLRG,a1 ;answer is +/- large number
255 bra set_sign ;now go set the sign
257 tst.b LOCAL_SGN(a0) ;if negative overflow
260 lea.l EXT_PINF,a1 ;answer is negative infinity
261 or.l #neginf_mask,USER_FPSR(a6)
262 bra end_ovfr ;inf is same for all precisions (ext,dbl,sgl)
264 lea.l DBL_PLRG,a1 ;answer is large positive number
267 tst.b LOCAL_SGN(a0) ;if negative overflow
270 lea.l DBL_PLRG,a1 ;answer is large negative number
271 bset.b #neg_bit,FPSR_CC(a6)
274 lea.l EXT_PINF,a1 ;answer is positive infinity
275 bset.b #inf_bit,FPSR_CC(a6)
281 lea.l EXT_PINF,a1 ;answer is +/- infinity
282 bset.b #inf_bit,FPSR_CC(a6)
285 lea.l SGL_PLRG,a1 ;anwer is +/- large number
288 tst.b LOCAL_SGN(a0) ;if negative overflow
291 lea.l EXT_PINF,a1 ;answer is negative infinity
292 or.l #neginf_mask,USER_FPSR(a6)
295 lea.l SGL_PLRG,a1 ;answer is large positive number
298 tst.b LOCAL_SGN(a0) ;if negative overflow
301 lea.l SGL_PLRG,a1 ;answer is large negative number
302 bset.b #neg_bit,FPSR_CC(a6)
305 lea.l EXT_PINF,a1 ;answer is postive infinity
306 bset.b #inf_bit,FPSR_CC(a6)
310 tst.b LOCAL_SGN(a0) ;if negative overflow
313 bset.b #neg_bit,FPSR_CC(a6)
316 move.w LOCAL_EX(a1),LOCAL_EX(a0) ;do not overwrite sign
317 move.l LOCAL_HI(a1),LOCAL_HI(a0)
318 move.l LOCAL_LO(a1),LOCAL_LO(a0)
328 * get_fline --- get f-line opcode of interrupted instruction
330 * Returns opcode in the low word of d0.
333 move.l USER_FPIAR(a6),a0 ;opcode address
334 clr.l -(a7) ;reserve a word on the stack
335 lea.l 2(a7),a1 ;point to low word of temporary
341 * g_rndpr --- put rounding precision in d0{1:0}
343 * valid return codes are:
349 * get rounding precision (cmdreg3b{6:5})
351 * case opclass = 011 (move out)
352 * get destination format - this is the also the rounding precision
356 * *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL
357 * *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL
358 * case RndPr(from cmdreg3b{6:5} = 00 | 01
359 * use precision from FPCR{7:6}
360 * case 00 then RND_PREC = EXT
361 * case 01 then RND_PREC = SGL
362 * case 10 then RND_PREC = DBL
364 * use precision in FPCR{7:6}
365 * case 00 then RND_PREC = EXT
366 * case 01 then RND_PREC = SGL
367 * case 10 then RND_PREC = DBL
371 bsr.w g_opcls ;get opclass in d0{2:0}
372 cmp.w #$0003,d0 ;check for opclass 011
376 * For move out instructions (opclass 011) the destination format
377 * is the same as the rounding precision. Pass results from g_dfmtou.
382 btst.b #E3,E_BYTE(a6)
383 beq.l unf_e1_exc ;branch to e1 underflow
385 move.l CMDREG3B(a6),d0 ;rounding precision in d0{10:9}
386 bfextu d0{9:2},d0 ;move the rounding prec bits to d0{1:0}
388 beq.l unff_sgl ;force precision is single
389 cmpi.l #$3,d0 ;force precision is double
391 move.w CMDREG3B(a6),d0 ;get the command word again
392 andi.l #$7f,d0 ;clear all except operation
394 beq.l unf_fsgl ;fsglmul or fsgldiv
396 beq.l unf_fsgl ;fsgldiv or fsglmul
399 move.l CMDREG1B(a6),d0 ;get 32 bits off the stack, 1st 16 bits
400 * ;are the command word
401 andi.l #$00440000,d0 ;clear all bits except bits 6 and 2
403 beq.l unff_sgl ;force single
404 cmpi.l #$00440000,d0 ;force double
406 move.l CMDREG1B(a6),d0 ;get the command word again
407 andi.l #$007f0000,d0 ;clear all bits except the operation
409 beq.l unf_fsgl ;fsglmul
411 beq.l unf_fsgl ;fsgldiv
415 * Convert to return format. The values from cmdreg3b and the return
417 * cmdreg3b return precision
418 * -------- ------ ---------
425 move.l #1,d0 ;return 1
431 move.l #2,d0 ;return 2
440 * Get rounding precision set in FPCR{7:6}.
443 move.l USER_FPCR(a6),d0 ;rounding precision bits in d0{7:6}
444 bfextu d0{24:2},d0 ;move the rounding prec bits to d0{1:0}
447 * g_opcls --- put opclass in d0{2:0}
450 btst.b #E3,E_BYTE(a6)
451 beq.b opc_1b ;if set, go to cmdreg1b
453 clr.l d0 ;if E3, only opclass 0x0 is possible
456 move.l CMDREG1B(a6),d0
457 bfextu d0{0:3},d0 ;shift opclass bits d0{31:29} to d0{2:0}
460 * g_dfmtou --- put destination format in d0{1:0}
462 * If E1, the format is from cmdreg1b{12:10}
463 * If E3, the format is extended.
471 btst.b #E3,E_BYTE(a6)
473 clr.l d0 ;if E1, size is always ext
476 move.l CMDREG1B(a6),d0
477 bfextu d0{3:3},d0 ;dest fmt from cmdreg1b{12:10}
478 cmp.b #1,d0 ;check for single
483 cmp.b #5,d0 ;check for double
488 clr.l d0 ;must be extended
493 * Final result table for unf_sub. Note that the negative counterparts
494 * are unnecessary as unf_sub always returns the sign separately from
497 EXT_PZRO dc.l $00000000,$00000000,$00000000,$00000000
499 SGL_PZRO dc.l $3f810000,$00000000,$00000000,$00000000
501 DBL_PZRO dc.l $3c010000,$00000000,$00000000,$00000000
502 * ;smallest +ext denorm
503 EXT_PSML dc.l $00000000,$00000000,$00000001,$00000000
504 * ;smallest +sgl denorm
505 SGL_PSML dc.l $3f810000,$00000100,$00000000,$00000000
506 * ;smallest +dbl denorm
507 DBL_PSML dc.l $3c010000,$00000000,$00000800,$00000000
509 * UNF_SUB --- underflow result calculation
512 * d0 contains round precision
513 * a0 points to input operand in the internal extended format
516 * a0 points to correct internal extended precision result.
539 lsl.l #2,d0 ;move round precision to d0{3:2}
540 bfextu FPCR_MODE(a6){2:2},d1 ;set round mode
541 or.l d1,d0 ;index is fmt:mode in d0{3:0}
542 lea.l tblunf,a1 ;load a1 with table address
543 move.l (a1,d0*4),a1 ;use d0 as index to the table
544 jmp (a1) ;go to the correct routine
549 lea.l EXT_PZRO,a1 ;answer is +/- zero
550 bset.b #z_bit,FPSR_CC(a6)
551 bra uset_sign ;now go set the sign
553 lea.l EXT_PZRO,a1 ;answer is +/- zero
554 bset.b #z_bit,FPSR_CC(a6)
555 bra uset_sign ;now go set the sign
557 tst.b LOCAL_SGN(a0) ;if negative underflow
560 lea.l EXT_PSML,a1 ;answer is negative smallest denorm
561 bset.b #neg_bit,FPSR_CC(a6)
564 lea.l EXT_PZRO,a1 ;answer is positive zero
565 bset.b #z_bit,FPSR_CC(a6)
568 tst.b LOCAL_SGN(a0) ;if negative underflow
571 lea.l EXT_PZRO,a1 ;answer is negative zero
572 ori.l #negz_mask,USER_FPSR(a6)
575 lea.l EXT_PSML,a1 ;answer is positive smallest denorm
581 lea.l DBL_PZRO,a1 ;answer is +/- zero
582 bset.b #z_bit,FPSR_CC(a6)
585 lea.l DBL_PZRO,a1 ;answer is +/- zero
586 bset.b #z_bit,FPSR_CC(a6)
587 bra uset_sign ;now go set the sign
589 tst.b LOCAL_SGN(a0) ;if negative overflow
592 lea.l DBL_PSML,a1 ;answer is smallest denormalized negative
593 bset.b #neg_bit,FPSR_CC(a6)
596 lea.l DBL_PZRO,a1 ;answer is positive zero
597 bset.b #z_bit,FPSR_CC(a6)
600 tst.b LOCAL_SGN(a0) ;if negative overflow
603 lea.l DBL_PZRO,a1 ;answer is negative zero
604 ori.l #negz_mask,USER_FPSR(a6)
607 lea.l DBL_PSML,a1 ;answer is smallest denormalized negative
613 lea.l SGL_PZRO,a1 ;answer is +/- zero
614 bset.b #z_bit,FPSR_CC(a6)
617 lea.l SGL_PZRO,a1 ;answer is +/- zero
618 bset.b #z_bit,FPSR_CC(a6)
621 tst.b LOCAL_SGN(a0) ;if negative overflow
624 lea.l SGL_PSML,a1 ;answer is smallest denormalized negative
625 bset.b #neg_bit,FPSR_CC(a6)
628 lea.l SGL_PZRO,a1 ;answer is positive zero
629 bset.b #z_bit,FPSR_CC(a6)
632 tst.b LOCAL_SGN(a0) ;if negative overflow
635 lea.l SGL_PZRO,a1 ;answer is negative zero
636 ori.l #negz_mask,USER_FPSR(a6)
639 lea.l SGL_PSML,a1 ;answer is smallest denormalized positive
643 tst.b LOCAL_SGN(a0) ;if negative overflow
646 bset.b #neg_bit,FPSR_CC(a6)
649 move.w LOCAL_EX(a1),LOCAL_EX(a0) ;be careful not to overwrite sign
650 move.l LOCAL_HI(a1),LOCAL_HI(a0)
651 move.l LOCAL_LO(a1),LOCAL_LO(a0)
654 * reg_dest --- write byte, word, or long data to Dn
659 * d1: data size and dest register number formatted as:
662 * -----------------------------------------------
663 * | 0 | Size | Dest Reg # |
664 * -----------------------------------------------
703 move.b L_SCR1(a6),USER_D0+3(a6)
706 move.b L_SCR1(a6),USER_D1+3(a6)
727 move.w L_SCR1(a6),USER_D0+2(a6)
730 move.w L_SCR1(a6),USER_D1+2(a6)
751 move.l L_SCR1(a6),USER_D0(a6)
754 move.l L_SCR1(a6),USER_D1(a6)