Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:49

0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 //  util.sa 3.7 7/29/91
0005 //
0006 //  This file contains routines used by other programs.
0007 //
0008 //  ovf_res: used by overflow to force the correct
0009 //       result. ovf_r_k, ovf_r_x2, ovf_r_x3 are
0010 //       derivatives of this routine.
0011 //  get_fline: get user's opcode word
0012 //  g_dfmtou: returns the destination format.
0013 //  g_opcls: returns the opclass of the float instruction.
0014 //  g_rndpr: returns the rounding precision.
0015 //  reg_dest: write byte, word, or long data to Dn
0016 //
0017 //
0018 //      Copyright (C) Motorola, Inc. 1990
0019 //          All Rights Reserved
0020 //
0021 //  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0022 //  The copyright notice above does not evidence any
0023 //  actual or intended publication of such source code.
0024 
0025 //UTIL  idnt    2,1 | Motorola 040 Floating Point Software Package
0026 
0027     |section    8
0028 
0029 #include "fpsp.defs"
0030 
0031     |xref   mem_read
0032 
0033     .global g_dfmtou
0034     .global g_opcls
0035     .global g_rndpr
0036     .global get_fline
0037     .global reg_dest
0038 
0039 //
0040 // Final result table for ovf_res. Note that the negative counterparts
0041 // are unnecessary as ovf_res always returns the sign separately from
0042 // the exponent.
0043 //                  ;+inf
0044 EXT_PINF:   .long   0x7fff0000,0x00000000,0x00000000,0x00000000
0045 //                  ;largest +ext
0046 EXT_PLRG:   .long   0x7ffe0000,0xffffffff,0xffffffff,0x00000000
0047 //                  ;largest magnitude +sgl in ext
0048 SGL_PLRG:   .long   0x407e0000,0xffffff00,0x00000000,0x00000000
0049 //                  ;largest magnitude +dbl in ext
0050 DBL_PLRG:   .long   0x43fe0000,0xffffffff,0xfffff800,0x00000000
0051 //                  ;largest -ext
0052 
0053 tblovfl:
0054     .long   EXT_RN
0055     .long   EXT_RZ
0056     .long   EXT_RM
0057     .long   EXT_RP
0058     .long   SGL_RN
0059     .long   SGL_RZ
0060     .long   SGL_RM
0061     .long   SGL_RP
0062     .long   DBL_RN
0063     .long   DBL_RZ
0064     .long   DBL_RM
0065     .long   DBL_RP
0066     .long   error
0067     .long   error
0068     .long   error
0069     .long   error
0070 
0071 
0072 //
0073 //  ovf_r_k --- overflow result calculation
0074 //
0075 // This entry point is used by kernel_ex.
0076 //
0077 // This forces the destination precision to be extended
0078 //
0079 // Input:   operand in ETEMP
0080 // Output:  a result is in ETEMP (internal extended format)
0081 //
0082     .global ovf_r_k
0083 ovf_r_k:
0084     lea ETEMP(%a6),%a0  //a0 points to source operand
0085     bclrb   #sign_bit,ETEMP_EX(%a6)
0086     sne ETEMP_SGN(%a6)  //convert to internal IEEE format
0087 
0088 //
0089 //  ovf_r_x2 --- overflow result calculation
0090 //
0091 // This entry point used by x_ovfl.  (opclass 0 and 2)
0092 //
0093 // Input        a0  points to an operand in the internal extended format
0094 // Output   a0  points to the result in the internal extended format
0095 //
0096 // This sets the round precision according to the user's FPCR unless the
0097 // instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul,
0098 // fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg.
0099 // If the instruction is fsgldiv of fsglmul, the rounding precision must be
0100 // extended.  If the instruction is not fsgldiv or fsglmul but a force-
0101 // precision instruction, the rounding precision is then set to the force
0102 // precision.
0103 
0104     .global ovf_r_x2
0105 ovf_r_x2:
0106     btstb   #E3,E_BYTE(%a6)     //check for nu exception
0107     beql    ovf_e1_exc      //it is cu exception
0108 ovf_e3_exc:
0109     movew   CMDREG3B(%a6),%d0       //get the command word
0110     andiw   #0x00000060,%d0     //clear all bits except 6 and 5
0111     cmpil   #0x00000040,%d0
0112     beql    ovff_sgl        //force precision is single
0113     cmpil   #0x00000060,%d0
0114     beql    ovff_dbl        //force precision is double
0115     movew   CMDREG3B(%a6),%d0       //get the command word again
0116     andil   #0x7f,%d0           //clear all except operation
0117     cmpil   #0x33,%d0
0118     beql    ovf_fsgl        //fsglmul or fsgldiv
0119     cmpil   #0x30,%d0
0120     beql    ovf_fsgl
0121     bra ovf_fpcr        //instruction is none of the above
0122 //                  ;use FPCR
0123 ovf_e1_exc:
0124     movew   CMDREG1B(%a6),%d0       //get command word
0125     andil   #0x00000044,%d0     //clear all bits except 6 and 2
0126     cmpil   #0x00000040,%d0
0127     beql    ovff_sgl        //the instruction is force single
0128     cmpil   #0x00000044,%d0
0129     beql    ovff_dbl        //the instruction is force double
0130     movew   CMDREG1B(%a6),%d0       //again get the command word
0131     andil   #0x0000007f,%d0     //clear all except the op code
0132     cmpil   #0x00000027,%d0
0133     beql    ovf_fsgl        //fsglmul
0134     cmpil   #0x00000024,%d0
0135     beql    ovf_fsgl        //fsgldiv
0136     bra ovf_fpcr        //none of the above, use FPCR
0137 //
0138 //
0139 // Inst is either fsgldiv or fsglmul.  Force extended precision.
0140 //
0141 ovf_fsgl:
0142     clrl    %d0
0143     bra ovf_res
0144 
0145 ovff_sgl:
0146     movel   #0x00000001,%d0     //set single
0147     bra ovf_res
0148 ovff_dbl:
0149     movel   #0x00000002,%d0     //set double
0150     bra ovf_res
0151 //
0152 // The precision is in the fpcr.
0153 //
0154 ovf_fpcr:
0155     bfextu  FPCR_MODE(%a6){#0:#2},%d0 //set round precision
0156     bra ovf_res
0157 
0158 //
0159 //
0160 //  ovf_r_x3 --- overflow result calculation
0161 //
0162 // This entry point used by x_ovfl. (opclass 3 only)
0163 //
0164 // Input        a0  points to an operand in the internal extended format
0165 // Output   a0  points to the result in the internal extended format
0166 //
0167 // This sets the round precision according to the destination size.
0168 //
0169     .global ovf_r_x3
0170 ovf_r_x3:
0171     bsr g_dfmtou    //get dest fmt in d0{1:0}
0172 //              ;for fmovout, the destination format
0173 //              ;is the rounding precision
0174 
0175 //
0176 //  ovf_res --- overflow result calculation
0177 //
0178 // Input:
0179 //  a0  points to operand in internal extended format
0180 // Output:
0181 //  a0  points to result in internal extended format
0182 //
0183     .global ovf_res
0184 ovf_res:
0185     lsll    #2,%d0      //move round precision to d0{3:2}
0186     bfextu  FPCR_MODE(%a6){#2:#2},%d1 //set round mode
0187     orl %d1,%d0     //index is fmt:mode in d0{3:0}
0188     leal    tblovfl,%a1 //load a1 with table address
0189     movel   %a1@(%d0:l:4),%a1   //use d0 as index to the table
0190     jmp (%a1)       //go to the correct routine
0191 //
0192 //case DEST_FMT = EXT
0193 //
0194 EXT_RN:
0195     leal    EXT_PINF,%a1    //answer is +/- infinity
0196     bsetb   #inf_bit,FPSR_CC(%a6)
0197     bra set_sign    //now go set the sign
0198 EXT_RZ:
0199     leal    EXT_PLRG,%a1    //answer is +/- large number
0200     bra set_sign    //now go set the sign
0201 EXT_RM:
0202     tstb    LOCAL_SGN(%a0)  //if negative overflow
0203     beqs    e_rm_pos
0204 e_rm_neg:
0205     leal    EXT_PINF,%a1    //answer is negative infinity
0206     orl #neginf_mask,USER_FPSR(%a6)
0207     bra end_ovfr
0208 e_rm_pos:
0209     leal    EXT_PLRG,%a1    //answer is large positive number
0210     bra end_ovfr
0211 EXT_RP:
0212     tstb    LOCAL_SGN(%a0)  //if negative overflow
0213     beqs    e_rp_pos
0214 e_rp_neg:
0215     leal    EXT_PLRG,%a1    //answer is large negative number
0216     bsetb   #neg_bit,FPSR_CC(%a6)
0217     bra end_ovfr
0218 e_rp_pos:
0219     leal    EXT_PINF,%a1    //answer is positive infinity
0220     bsetb   #inf_bit,FPSR_CC(%a6)
0221     bra end_ovfr
0222 //
0223 //case DEST_FMT = DBL
0224 //
0225 DBL_RN:
0226     leal    EXT_PINF,%a1    //answer is +/- infinity
0227     bsetb   #inf_bit,FPSR_CC(%a6)
0228     bra set_sign
0229 DBL_RZ:
0230     leal    DBL_PLRG,%a1    //answer is +/- large number
0231     bra set_sign    //now go set the sign
0232 DBL_RM:
0233     tstb    LOCAL_SGN(%a0)  //if negative overflow
0234     beqs    d_rm_pos
0235 d_rm_neg:
0236     leal    EXT_PINF,%a1    //answer is negative infinity
0237     orl #neginf_mask,USER_FPSR(%a6)
0238     bra end_ovfr    //inf is same for all precisions (ext,dbl,sgl)
0239 d_rm_pos:
0240     leal    DBL_PLRG,%a1    //answer is large positive number
0241     bra end_ovfr
0242 DBL_RP:
0243     tstb    LOCAL_SGN(%a0)  //if negative overflow
0244     beqs    d_rp_pos
0245 d_rp_neg:
0246     leal    DBL_PLRG,%a1    //answer is large negative number
0247     bsetb   #neg_bit,FPSR_CC(%a6)
0248     bra end_ovfr
0249 d_rp_pos:
0250     leal    EXT_PINF,%a1    //answer is positive infinity
0251     bsetb   #inf_bit,FPSR_CC(%a6)
0252     bra end_ovfr
0253 //
0254 //case DEST_FMT = SGL
0255 //
0256 SGL_RN:
0257     leal    EXT_PINF,%a1    //answer is +/-  infinity
0258     bsetb   #inf_bit,FPSR_CC(%a6)
0259     bras    set_sign
0260 SGL_RZ:
0261     leal    SGL_PLRG,%a1    //answer is +/- large number
0262     bras    set_sign
0263 SGL_RM:
0264     tstb    LOCAL_SGN(%a0)  //if negative overflow
0265     beqs    s_rm_pos
0266 s_rm_neg:
0267     leal    EXT_PINF,%a1    //answer is negative infinity
0268     orl #neginf_mask,USER_FPSR(%a6)
0269     bras    end_ovfr
0270 s_rm_pos:
0271     leal    SGL_PLRG,%a1    //answer is large positive number
0272     bras    end_ovfr
0273 SGL_RP:
0274     tstb    LOCAL_SGN(%a0)  //if negative overflow
0275     beqs    s_rp_pos
0276 s_rp_neg:
0277     leal    SGL_PLRG,%a1    //answer is large negative number
0278     bsetb   #neg_bit,FPSR_CC(%a6)
0279     bras    end_ovfr
0280 s_rp_pos:
0281     leal    EXT_PINF,%a1    //answer is positive infinity
0282     bsetb   #inf_bit,FPSR_CC(%a6)
0283     bras    end_ovfr
0284 
0285 set_sign:
0286     tstb    LOCAL_SGN(%a0)  //if negative overflow
0287     beqs    end_ovfr
0288 neg_sign:
0289     bsetb   #neg_bit,FPSR_CC(%a6)
0290 
0291 end_ovfr:
0292     movew   LOCAL_EX(%a1),LOCAL_EX(%a0) //do not overwrite sign
0293     movel   LOCAL_HI(%a1),LOCAL_HI(%a0)
0294     movel   LOCAL_LO(%a1),LOCAL_LO(%a0)
0295     rts
0296 
0297 
0298 //
0299 //  ERROR
0300 //
0301 error:
0302     rts
0303 //
0304 //  get_fline --- get f-line opcode of interrupted instruction
0305 //
0306 //  Returns opcode in the low word of d0.
0307 //
0308 get_fline:
0309     movel   USER_FPIAR(%a6),%a0 //opcode address
0310     movel   #0,-(%a7)   //reserve a word on the stack
0311     leal    2(%a7),%a1  //point to low word of temporary
0312     movel   #2,%d0      //count
0313     bsrl    mem_read
0314     movel   (%a7)+,%d0
0315     rts
0316 //
0317 //  g_rndpr --- put rounding precision in d0{1:0}
0318 //
0319 //  valid return codes are:
0320 //      00 - extended
0321 //      01 - single
0322 //      10 - double
0323 //
0324 // begin
0325 // get rounding precision (cmdreg3b{6:5})
0326 // begin
0327 //  case    opclass = 011 (move out)
0328 //  get destination format - this is the also the rounding precision
0329 //
0330 //  case    opclass = 0x0
0331 //  if E3
0332 //      *case RndPr(from cmdreg3b{6:5} = 11  then RND_PREC = DBL
0333 //      *case RndPr(from cmdreg3b{6:5} = 10  then RND_PREC = SGL
0334 //       case RndPr(from cmdreg3b{6:5} = 00 | 01
0335 //      use precision from FPCR{7:6}
0336 //          case 00 then RND_PREC = EXT
0337 //          case 01 then RND_PREC = SGL
0338 //          case 10 then RND_PREC = DBL
0339 //  else E1
0340 //       use precision in FPCR{7:6}
0341 //       case 00 then RND_PREC = EXT
0342 //       case 01 then RND_PREC = SGL
0343 //       case 10 then RND_PREC = DBL
0344 // end
0345 //
0346 g_rndpr:
0347     bsr g_opcls     //get opclass in d0{2:0}
0348     cmpw    #0x0003,%d0 //check for opclass 011
0349     bnes    op_0x0
0350 
0351 //
0352 // For move out instructions (opclass 011) the destination format
0353 // is the same as the rounding precision.  Pass results from g_dfmtou.
0354 //
0355     bsr     g_dfmtou
0356     rts
0357 op_0x0:
0358     btstb   #E3,E_BYTE(%a6)
0359     beql    unf_e1_exc  //branch to e1 underflow
0360 unf_e3_exc:
0361     movel   CMDREG3B(%a6),%d0   //rounding precision in d0{10:9}
0362     bfextu  %d0{#9:#2},%d0  //move the rounding prec bits to d0{1:0}
0363     cmpil   #0x2,%d0
0364     beql    unff_sgl    //force precision is single
0365     cmpil   #0x3,%d0        //force precision is double
0366     beql    unff_dbl
0367     movew   CMDREG3B(%a6),%d0   //get the command word again
0368     andil   #0x7f,%d0       //clear all except operation
0369     cmpil   #0x33,%d0
0370     beql    unf_fsgl    //fsglmul or fsgldiv
0371     cmpil   #0x30,%d0
0372     beql    unf_fsgl    //fsgldiv or fsglmul
0373     bra unf_fpcr
0374 unf_e1_exc:
0375     movel   CMDREG1B(%a6),%d0   //get 32 bits off the stack, 1st 16 bits
0376 //              ;are the command word
0377     andil   #0x00440000,%d0 //clear all bits except bits 6 and 2
0378     cmpil   #0x00400000,%d0
0379     beql    unff_sgl    //force single
0380     cmpil   #0x00440000,%d0 //force double
0381     beql    unff_dbl
0382     movel   CMDREG1B(%a6),%d0   //get the command word again
0383     andil   #0x007f0000,%d0 //clear all bits except the operation
0384     cmpil   #0x00270000,%d0
0385     beql    unf_fsgl    //fsglmul
0386     cmpil   #0x00240000,%d0
0387     beql    unf_fsgl    //fsgldiv
0388     bra unf_fpcr
0389 
0390 //
0391 // Convert to return format.  The values from cmdreg3b and the return
0392 // values are:
0393 //  cmdreg3b    return       precision
0394 //  --------    ------       ---------
0395 //    00,01       0     ext
0396 //     10         1     sgl
0397 //     11         2     dbl
0398 // Force single
0399 //
0400 unff_sgl:
0401     movel   #1,%d0      //return 1
0402     rts
0403 //
0404 // Force double
0405 //
0406 unff_dbl:
0407     movel   #2,%d0      //return 2
0408     rts
0409 //
0410 // Force extended
0411 //
0412 unf_fsgl:
0413     movel   #0,%d0
0414     rts
0415 //
0416 // Get rounding precision set in FPCR{7:6}.
0417 //
0418 unf_fpcr:
0419     movel   USER_FPCR(%a6),%d0 //rounding precision bits in d0{7:6}
0420     bfextu  %d0{#24:#2},%d0 //move the rounding prec bits to d0{1:0}
0421     rts
0422 //
0423 //  g_opcls --- put opclass in d0{2:0}
0424 //
0425 g_opcls:
0426     btstb   #E3,E_BYTE(%a6)
0427     beqs    opc_1b      //if set, go to cmdreg1b
0428 opc_3b:
0429     clrl    %d0     //if E3, only opclass 0x0 is possible
0430     rts
0431 opc_1b:
0432     movel   CMDREG1B(%a6),%d0
0433     bfextu  %d0{#0:#3},%d0  //shift opclass bits d0{31:29} to d0{2:0}
0434     rts
0435 //
0436 //  g_dfmtou --- put destination format in d0{1:0}
0437 //
0438 //  If E1, the format is from cmdreg1b{12:10}
0439 //  If E3, the format is extended.
0440 //
0441 //  Dest. Fmt.
0442 //      extended  010 -> 00
0443 //      single    001 -> 01
0444 //      double    101 -> 10
0445 //
0446 g_dfmtou:
0447     btstb   #E3,E_BYTE(%a6)
0448     beqs    op011
0449     clrl    %d0     //if E1, size is always ext
0450     rts
0451 op011:
0452     movel   CMDREG1B(%a6),%d0
0453     bfextu  %d0{#3:#3},%d0  //dest fmt from cmdreg1b{12:10}
0454     cmpb    #1,%d0      //check for single
0455     bnes    not_sgl
0456     movel   #1,%d0
0457     rts
0458 not_sgl:
0459     cmpb    #5,%d0      //check for double
0460     bnes    not_dbl
0461     movel   #2,%d0
0462     rts
0463 not_dbl:
0464     clrl    %d0     //must be extended
0465     rts
0466 
0467 //
0468 //
0469 // Final result table for unf_sub. Note that the negative counterparts
0470 // are unnecessary as unf_sub always returns the sign separately from
0471 // the exponent.
0472 //                  ;+zero
0473 EXT_PZRO:   .long   0x00000000,0x00000000,0x00000000,0x00000000
0474 //                  ;+zero
0475 SGL_PZRO:   .long   0x3f810000,0x00000000,0x00000000,0x00000000
0476 //                  ;+zero
0477 DBL_PZRO:   .long   0x3c010000,0x00000000,0x00000000,0x00000000
0478 //                  ;smallest +ext denorm
0479 EXT_PSML:   .long   0x00000000,0x00000000,0x00000001,0x00000000
0480 //                  ;smallest +sgl denorm
0481 SGL_PSML:   .long   0x3f810000,0x00000100,0x00000000,0x00000000
0482 //                  ;smallest +dbl denorm
0483 DBL_PSML:   .long   0x3c010000,0x00000000,0x00000800,0x00000000
0484 //
0485 //  UNF_SUB --- underflow result calculation
0486 //
0487 // Input:
0488 //  d0  contains round precision
0489 //  a0  points to input operand in the internal extended format
0490 //
0491 // Output:
0492 //  a0  points to correct internal extended precision result.
0493 //
0494 
0495 tblunf:
0496     .long   uEXT_RN
0497     .long   uEXT_RZ
0498     .long   uEXT_RM
0499     .long   uEXT_RP
0500     .long   uSGL_RN
0501     .long   uSGL_RZ
0502     .long   uSGL_RM
0503     .long   uSGL_RP
0504     .long   uDBL_RN
0505     .long   uDBL_RZ
0506     .long   uDBL_RM
0507     .long   uDBL_RP
0508     .long   uDBL_RN
0509     .long   uDBL_RZ
0510     .long   uDBL_RM
0511     .long   uDBL_RP
0512 
0513     .global unf_sub
0514 unf_sub:
0515     lsll    #2,%d0      //move round precision to d0{3:2}
0516     bfextu  FPCR_MODE(%a6){#2:#2},%d1 //set round mode
0517     orl %d1,%d0     //index is fmt:mode in d0{3:0}
0518     leal    tblunf,%a1  //load a1 with table address
0519     movel   %a1@(%d0:l:4),%a1   //use d0 as index to the table
0520     jmp (%a1)       //go to the correct routine
0521 //
0522 //case DEST_FMT = EXT
0523 //
0524 uEXT_RN:
0525     leal    EXT_PZRO,%a1    //answer is +/- zero
0526     bsetb   #z_bit,FPSR_CC(%a6)
0527     bra uset_sign   //now go set the sign
0528 uEXT_RZ:
0529     leal    EXT_PZRO,%a1    //answer is +/- zero
0530     bsetb   #z_bit,FPSR_CC(%a6)
0531     bra uset_sign   //now go set the sign
0532 uEXT_RM:
0533     tstb    LOCAL_SGN(%a0)  //if negative underflow
0534     beqs    ue_rm_pos
0535 ue_rm_neg:
0536     leal    EXT_PSML,%a1    //answer is negative smallest denorm
0537     bsetb   #neg_bit,FPSR_CC(%a6)
0538     bra end_unfr
0539 ue_rm_pos:
0540     leal    EXT_PZRO,%a1    //answer is positive zero
0541     bsetb   #z_bit,FPSR_CC(%a6)
0542     bra end_unfr
0543 uEXT_RP:
0544     tstb    LOCAL_SGN(%a0)  //if negative underflow
0545     beqs    ue_rp_pos
0546 ue_rp_neg:
0547     leal    EXT_PZRO,%a1    //answer is negative zero
0548     oril    #negz_mask,USER_FPSR(%a6)
0549     bra end_unfr
0550 ue_rp_pos:
0551     leal    EXT_PSML,%a1    //answer is positive smallest denorm
0552     bra end_unfr
0553 //
0554 //case DEST_FMT = DBL
0555 //
0556 uDBL_RN:
0557     leal    DBL_PZRO,%a1    //answer is +/- zero
0558     bsetb   #z_bit,FPSR_CC(%a6)
0559     bra uset_sign
0560 uDBL_RZ:
0561     leal    DBL_PZRO,%a1    //answer is +/- zero
0562     bsetb   #z_bit,FPSR_CC(%a6)
0563     bra uset_sign   //now go set the sign
0564 uDBL_RM:
0565     tstb    LOCAL_SGN(%a0)  //if negative overflow
0566     beqs    ud_rm_pos
0567 ud_rm_neg:
0568     leal    DBL_PSML,%a1    //answer is smallest denormalized negative
0569     bsetb   #neg_bit,FPSR_CC(%a6)
0570     bra end_unfr
0571 ud_rm_pos:
0572     leal    DBL_PZRO,%a1    //answer is positive zero
0573     bsetb   #z_bit,FPSR_CC(%a6)
0574     bra end_unfr
0575 uDBL_RP:
0576     tstb    LOCAL_SGN(%a0)  //if negative overflow
0577     beqs    ud_rp_pos
0578 ud_rp_neg:
0579     leal    DBL_PZRO,%a1    //answer is negative zero
0580     oril    #negz_mask,USER_FPSR(%a6)
0581     bra end_unfr
0582 ud_rp_pos:
0583     leal    DBL_PSML,%a1    //answer is smallest denormalized negative
0584     bra end_unfr
0585 //
0586 //case DEST_FMT = SGL
0587 //
0588 uSGL_RN:
0589     leal    SGL_PZRO,%a1    //answer is +/- zero
0590     bsetb   #z_bit,FPSR_CC(%a6)
0591     bras    uset_sign
0592 uSGL_RZ:
0593     leal    SGL_PZRO,%a1    //answer is +/- zero
0594     bsetb   #z_bit,FPSR_CC(%a6)
0595     bras    uset_sign
0596 uSGL_RM:
0597     tstb    LOCAL_SGN(%a0)  //if negative overflow
0598     beqs    us_rm_pos
0599 us_rm_neg:
0600     leal    SGL_PSML,%a1    //answer is smallest denormalized negative
0601     bsetb   #neg_bit,FPSR_CC(%a6)
0602     bras    end_unfr
0603 us_rm_pos:
0604     leal    SGL_PZRO,%a1    //answer is positive zero
0605     bsetb   #z_bit,FPSR_CC(%a6)
0606     bras    end_unfr
0607 uSGL_RP:
0608     tstb    LOCAL_SGN(%a0)  //if negative overflow
0609     beqs    us_rp_pos
0610 us_rp_neg:
0611     leal    SGL_PZRO,%a1    //answer is negative zero
0612     oril    #negz_mask,USER_FPSR(%a6)
0613     bras    end_unfr
0614 us_rp_pos:
0615     leal    SGL_PSML,%a1    //answer is smallest denormalized positive
0616     bras    end_unfr
0617 
0618 uset_sign:
0619     tstb    LOCAL_SGN(%a0)  //if negative overflow
0620     beqs    end_unfr
0621 uneg_sign:
0622     bsetb   #neg_bit,FPSR_CC(%a6)
0623 
0624 end_unfr:
0625     movew   LOCAL_EX(%a1),LOCAL_EX(%a0) //be careful not to overwrite sign
0626     movel   LOCAL_HI(%a1),LOCAL_HI(%a0)
0627     movel   LOCAL_LO(%a1),LOCAL_LO(%a0)
0628     rts
0629 //
0630 //  reg_dest --- write byte, word, or long data to Dn
0631 //
0632 //
0633 // Input:
0634 //  L_SCR1: Data
0635 //  d1:     data size and dest register number formatted as:
0636 //
0637 //  32      5    4     3     2     1     0
0638 //       -----------------------------------------------
0639 //       |        0        |    Size   |  Dest Reg #   |
0640 //       -----------------------------------------------
0641 //
0642 //  Size is:
0643 //      0 - Byte
0644 //      1 - Word
0645 //      2 - Long/Single
0646 //
0647 pregdst:
0648     .long   byte_d0
0649     .long   byte_d1
0650     .long   byte_d2
0651     .long   byte_d3
0652     .long   byte_d4
0653     .long   byte_d5
0654     .long   byte_d6
0655     .long   byte_d7
0656     .long   word_d0
0657     .long   word_d1
0658     .long   word_d2
0659     .long   word_d3
0660     .long   word_d4
0661     .long   word_d5
0662     .long   word_d6
0663     .long   word_d7
0664     .long   long_d0
0665     .long   long_d1
0666     .long   long_d2
0667     .long   long_d3
0668     .long   long_d4
0669     .long   long_d5
0670     .long   long_d6
0671     .long   long_d7
0672 
0673 reg_dest:
0674     leal    pregdst,%a0
0675     movel   %a0@(%d1:l:4),%a0
0676     jmp (%a0)
0677 
0678 byte_d0:
0679     moveb   L_SCR1(%a6),USER_D0+3(%a6)
0680     rts
0681 byte_d1:
0682     moveb   L_SCR1(%a6),USER_D1+3(%a6)
0683     rts
0684 byte_d2:
0685     moveb   L_SCR1(%a6),%d2
0686     rts
0687 byte_d3:
0688     moveb   L_SCR1(%a6),%d3
0689     rts
0690 byte_d4:
0691     moveb   L_SCR1(%a6),%d4
0692     rts
0693 byte_d5:
0694     moveb   L_SCR1(%a6),%d5
0695     rts
0696 byte_d6:
0697     moveb   L_SCR1(%a6),%d6
0698     rts
0699 byte_d7:
0700     moveb   L_SCR1(%a6),%d7
0701     rts
0702 word_d0:
0703     movew   L_SCR1(%a6),USER_D0+2(%a6)
0704     rts
0705 word_d1:
0706     movew   L_SCR1(%a6),USER_D1+2(%a6)
0707     rts
0708 word_d2:
0709     movew   L_SCR1(%a6),%d2
0710     rts
0711 word_d3:
0712     movew   L_SCR1(%a6),%d3
0713     rts
0714 word_d4:
0715     movew   L_SCR1(%a6),%d4
0716     rts
0717 word_d5:
0718     movew   L_SCR1(%a6),%d5
0719     rts
0720 word_d6:
0721     movew   L_SCR1(%a6),%d6
0722     rts
0723 word_d7:
0724     movew   L_SCR1(%a6),%d7
0725     rts
0726 long_d0:
0727     movel   L_SCR1(%a6),USER_D0(%a6)
0728     rts
0729 long_d1:
0730     movel   L_SCR1(%a6),USER_D1(%a6)
0731     rts
0732 long_d2:
0733     movel   L_SCR1(%a6),%d2
0734     rts
0735 long_d3:
0736     movel   L_SCR1(%a6),%d3
0737     rts
0738 long_d4:
0739     movel   L_SCR1(%a6),%d4
0740     rts
0741 long_d5:
0742     movel   L_SCR1(%a6),%d5
0743     rts
0744 long_d6:
0745     movel   L_SCR1(%a6),%d6
0746     rts
0747 long_d7:
0748     movel   L_SCR1(%a6),%d7
0749     rts
0750     |end