Back to home page

LXR

 
 

    


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

0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 //  x_store.sa 3.2 1/24/91
0005 //
0006 //  store --- store operand to memory or register
0007 //
0008 //  Used by underflow and overflow handlers.
0009 //
0010 //  a6 = points to fp value to be stored.
0011 //
0012 
0013 //      Copyright (C) Motorola, Inc. 1990
0014 //          All Rights Reserved
0015 //
0016 //  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0017 //  The copyright notice above does not evidence any
0018 //  actual or intended publication of such source code.
0019 
0020 X_STORE:    //idnt    2,1 | Motorola 040 Floating Point Software Package
0021 
0022     |section    8
0023 
0024 fpreg_mask:
0025     .byte   0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
0026 
0027 #include "fpsp.defs"
0028 
0029     |xref   mem_write
0030     |xref   get_fline
0031     |xref   g_opcls
0032     |xref   g_dfmtou
0033     |xref   reg_dest
0034 
0035     .global dest_ext
0036     .global dest_dbl
0037     .global dest_sgl
0038 
0039     .global store
0040 store:
0041     btstb   #E3,E_BYTE(%a6)
0042     beqs    E1_sto
0043 E3_sto:
0044     movel   CMDREG3B(%a6),%d0
0045     bfextu  %d0{#6:#3},%d0      //isolate dest. reg from cmdreg3b
0046 sto_fp:
0047     lea fpreg_mask,%a1
0048     moveb   (%a1,%d0.w),%d0     //convert reg# to dynamic register mask
0049     tstb    LOCAL_SGN(%a0)
0050     beqs    is_pos
0051     bsetb   #sign_bit,LOCAL_EX(%a0)
0052 is_pos:
0053     fmovemx (%a0),%d0       //move to correct register
0054 //
0055 //  if fp0-fp3 is being modified, we must put a copy
0056 //  in the USER_FPn variable on the stack because all exception
0057 //  handlers restore fp0-fp3 from there.
0058 //
0059     cmpb    #0x80,%d0
0060     bnes    not_fp0
0061     fmovemx %fp0-%fp0,USER_FP0(%a6)
0062     rts
0063 not_fp0:
0064     cmpb    #0x40,%d0
0065     bnes    not_fp1
0066     fmovemx %fp1-%fp1,USER_FP1(%a6)
0067     rts
0068 not_fp1:
0069     cmpb    #0x20,%d0
0070     bnes    not_fp2
0071     fmovemx %fp2-%fp2,USER_FP2(%a6)
0072     rts
0073 not_fp2:
0074     cmpb    #0x10,%d0
0075     bnes    not_fp3
0076     fmovemx %fp3-%fp3,USER_FP3(%a6)
0077     rts
0078 not_fp3:
0079     rts
0080 
0081 E1_sto:
0082     bsrl    g_opcls     //returns opclass in d0
0083     cmpib   #3,%d0
0084     beq opc011      //branch if opclass 3
0085     movel   CMDREG1B(%a6),%d0
0086     bfextu  %d0{#6:#3},%d0  //extract destination register
0087     bras    sto_fp
0088 
0089 opc011:
0090     bsrl    g_dfmtou    //returns dest format in d0
0091 //              ;ext=00, sgl=01, dbl=10
0092     movel   %a0,%a1     //save source addr in a1
0093     movel   EXC_EA(%a6),%a0 //get the address
0094     cmpil   #0,%d0      //if dest format is extended
0095     beq dest_ext    //then branch
0096     cmpil   #1,%d0      //if dest format is single
0097     beq dest_sgl    //then branch
0098 //
0099 //  fall through to dest_dbl
0100 //
0101 
0102 //
0103 //  dest_dbl --- write double precision value to user space
0104 //
0105 //Input
0106 //  a0 -> destination address
0107 //  a1 -> source in extended precision
0108 //Output
0109 //  a0 -> destroyed
0110 //  a1 -> destroyed
0111 //  d0 -> 0
0112 //
0113 //Changes extended precision to double precision.
0114 // Note: no attempt is made to round the extended value to double.
0115 //  dbl_sign = ext_sign
0116 //  dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias)
0117 //  get rid of ext integer bit
0118 //  dbl_mant = ext_mant{62:12}
0119 //
0120 //          ---------------   ---------------    ---------------
0121 //  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
0122 //          ---------------   ---------------    ---------------
0123 //       95     64    63 62       32      31     11   0
0124 //                   |               |
0125 //                   |               |
0126 //                   |               |
0127 //                       v               v
0128 //                    ---------------   ---------------
0129 //  double   ->           |s|exp| mant  |   |  mant       |
0130 //                    ---------------   ---------------
0131 //                63     51   32   31          0
0132 //
0133 dest_dbl:
0134     clrl    %d0     //clear d0
0135     movew   LOCAL_EX(%a1),%d0   //get exponent
0136     subw    #0x3fff,%d0 //subtract extended precision bias
0137     cmpw    #0x4000,%d0 //check if inf
0138     beqs    inf     //if so, special case
0139     addw    #0x3ff,%d0  //add double precision bias
0140     swap    %d0     //d0 now in upper word
0141     lsll    #4,%d0      //d0 now in proper place for dbl prec exp
0142     tstb    LOCAL_SGN(%a1)
0143     beqs    get_mant    //if positive, go process mantissa
0144     bsetl   #31,%d0     //if negative, put in sign information
0145 //              ; before continuing
0146     bras    get_mant    //go process mantissa
0147 inf:
0148     movel   #0x7ff00000,%d0 //load dbl inf exponent
0149     clrl    LOCAL_HI(%a1)   //clear msb
0150     tstb    LOCAL_SGN(%a1)
0151     beqs    dbl_inf     //if positive, go ahead and write it
0152     bsetl   #31,%d0     //if negative put in sign information
0153 dbl_inf:
0154     movel   %d0,LOCAL_EX(%a1)   //put the new exp back on the stack
0155     bras    dbl_wrt
0156 get_mant:
0157     movel   LOCAL_HI(%a1),%d1   //get ms mantissa
0158     bfextu  %d1{#1:#20},%d1 //get upper 20 bits of ms
0159     orl %d1,%d0     //put these bits in ms word of double
0160     movel   %d0,LOCAL_EX(%a1)   //put the new exp back on the stack
0161     movel   LOCAL_HI(%a1),%d1   //get ms mantissa
0162     movel   #21,%d0     //load shift count
0163     lsll    %d0,%d1     //put lower 11 bits in upper bits
0164     movel   %d1,LOCAL_HI(%a1)   //build lower lword in memory
0165     movel   LOCAL_LO(%a1),%d1   //get ls mantissa
0166     bfextu  %d1{#0:#21},%d0 //get ls 21 bits of double
0167     orl %d0,LOCAL_HI(%a1)   //put them in double result
0168 dbl_wrt:
0169     movel   #0x8,%d0        //byte count for double precision number
0170     exg %a0,%a1     //a0=supervisor source, a1=user dest
0171     bsrl    mem_write   //move the number to the user's memory
0172     rts
0173 //
0174 //  dest_sgl --- write single precision value to user space
0175 //
0176 //Input
0177 //  a0 -> destination address
0178 //  a1 -> source in extended precision
0179 //
0180 //Output
0181 //  a0 -> destroyed
0182 //  a1 -> destroyed
0183 //  d0 -> 0
0184 //
0185 //Changes extended precision to single precision.
0186 //  sgl_sign = ext_sign
0187 //  sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias)
0188 //  get rid of ext integer bit
0189 //  sgl_mant = ext_mant{62:12}
0190 //
0191 //          ---------------   ---------------    ---------------
0192 //  extended ->  |s|    exp    |   |1| ms mant   |    | ls mant     |
0193 //          ---------------   ---------------    ---------------
0194 //       95     64    63 62    40 32      31     12   0
0195 //                   |     |
0196 //                   |     |
0197 //                   |     |
0198 //                       v     v
0199 //                    ---------------
0200 //  single   ->           |s|exp| mant  |
0201 //                    ---------------
0202 //                31     22     0
0203 //
0204 dest_sgl:
0205     clrl    %d0
0206     movew   LOCAL_EX(%a1),%d0   //get exponent
0207     subw    #0x3fff,%d0 //subtract extended precision bias
0208     cmpw    #0x4000,%d0 //check if inf
0209     beqs    sinf        //if so, special case
0210     addw    #0x7f,%d0       //add single precision bias
0211     swap    %d0     //put exp in upper word of d0
0212     lsll    #7,%d0      //shift it into single exp bits
0213     tstb    LOCAL_SGN(%a1)
0214     beqs    get_sman    //if positive, continue
0215     bsetl   #31,%d0     //if negative, put in sign first
0216     bras    get_sman    //get mantissa
0217 sinf:
0218     movel   #0x7f800000,%d0 //load single inf exp to d0
0219     tstb    LOCAL_SGN(%a1)
0220     beqs    sgl_wrt     //if positive, continue
0221     bsetl   #31,%d0     //if negative, put in sign info
0222     bras    sgl_wrt
0223 
0224 get_sman:
0225     movel   LOCAL_HI(%a1),%d1   //get ms mantissa
0226     bfextu  %d1{#1:#23},%d1 //get upper 23 bits of ms
0227     orl %d1,%d0     //put these bits in ms word of single
0228 
0229 sgl_wrt:
0230     movel   %d0,L_SCR1(%a6) //put the new exp back on the stack
0231     movel   #0x4,%d0        //byte count for single precision number
0232     tstl    %a0     //users destination address
0233     beqs    sgl_Dn      //destination is a data register
0234     exg %a0,%a1     //a0=supervisor source, a1=user dest
0235     leal    L_SCR1(%a6),%a0 //point a0 to data
0236     bsrl    mem_write   //move the number to the user's memory
0237     rts
0238 sgl_Dn:
0239     bsrl    get_fline   //returns fline word in d0
0240     andw    #0x7,%d0        //isolate register number
0241     movel   %d0,%d1     //d1 has size:reg formatted for reg_dest
0242     orl #0x10,%d1       //reg_dest wants size added to reg#
0243     bral    reg_dest    //size is X, rts in reg_dest will
0244 //              ;return to caller of dest_sgl
0245 
0246 dest_ext:
0247     tstb    LOCAL_SGN(%a1)  //put back sign into exponent word
0248     beqs    dstx_cont
0249     bsetb   #sign_bit,LOCAL_EX(%a1)
0250 dstx_cont:
0251     clrb    LOCAL_SGN(%a1)  //clear out the sign byte
0252 
0253     movel   #0x0c,%d0       //byte count for extended number
0254     exg %a0,%a1     //a0=supervisor source, a1=user dest
0255     bsrl    mem_write   //move the number to the user's memory
0256     rts
0257 
0258     |end