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