Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | | | x_store.sa 3.2 1/24/91 | | store --- store operand to memory or register | | Used by underflow and overflow handlers. | | a6 = points to fp value to be stored. | | Copyright (C) Motorola, Inc. 1990 | All Rights Reserved | | For details on the license for this file, please see the | file, README, in this same directory. X_STORE: |idnt 2,1 | Motorola 040 Floating Point Software Package |section 8 fpreg_mask: .byte 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 #include "fpsp.h" |xref mem_write |xref get_fline |xref g_opcls |xref g_dfmtou |xref reg_dest .global dest_ext .global dest_dbl .global dest_sgl .global store store: btstb #E3,E_BYTE(%a6) beqs E1_sto E3_sto: movel CMDREG3B(%a6),%d0 bfextu %d0{#6:#3},%d0 |isolate dest. reg from cmdreg3b sto_fp: lea fpreg_mask,%a1 moveb (%a1,%d0.w),%d0 |convert reg# to dynamic register mask tstb LOCAL_SGN(%a0) beqs is_pos bsetb #sign_bit,LOCAL_EX(%a0) is_pos: fmovemx (%a0),%d0 |move to correct register | | if fp0-fp3 is being modified, we must put a copy | in the USER_FPn variable on the stack because all exception | handlers restore fp0-fp3 from there. | cmpb #0x80,%d0 bnes not_fp0 fmovemx %fp0-%fp0,USER_FP0(%a6) rts not_fp0: cmpb #0x40,%d0 bnes not_fp1 fmovemx %fp1-%fp1,USER_FP1(%a6) rts not_fp1: cmpb #0x20,%d0 bnes not_fp2 fmovemx %fp2-%fp2,USER_FP2(%a6) rts not_fp2: cmpb #0x10,%d0 bnes not_fp3 fmovemx %fp3-%fp3,USER_FP3(%a6) rts not_fp3: rts E1_sto: bsrl g_opcls |returns opclass in d0 cmpib #3,%d0 beq opc011 |branch if opclass 3 movel CMDREG1B(%a6),%d0 bfextu %d0{#6:#3},%d0 |extract destination register bras sto_fp opc011: bsrl g_dfmtou |returns dest format in d0 | ;ext=00, sgl=01, dbl=10 movel %a0,%a1 |save source addr in a1 movel EXC_EA(%a6),%a0 |get the address cmpil #0,%d0 |if dest format is extended beq dest_ext |then branch cmpil #1,%d0 |if dest format is single beq dest_sgl |then branch | | fall through to dest_dbl | | | dest_dbl --- write double precision value to user space | |Input | a0 -> destination address | a1 -> source in extended precision |Output | a0 -> destroyed | a1 -> destroyed | d0 -> 0 | |Changes extended precision to double precision. | Note: no attempt is made to round the extended value to double. | dbl_sign = ext_sign | dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias) | get rid of ext integer bit | dbl_mant = ext_mant{62:12} | | --------------- --------------- --------------- | extended -> |s| exp | |1| ms mant | | ls mant | | --------------- --------------- --------------- | 95 64 63 62 32 31 11 0 | | | | | | | | | | v v | --------------- --------------- | double -> |s|exp| mant | | mant | | --------------- --------------- | 63 51 32 31 0 | dest_dbl: clrl %d0 |clear d0 movew LOCAL_EX(%a1),%d0 |get exponent subw #0x3fff,%d0 |subtract extended precision bias cmpw #0x4000,%d0 |check if inf beqs inf |if so, special case addw #0x3ff,%d0 |add double precision bias swap %d0 |d0 now in upper word lsll #4,%d0 |d0 now in proper place for dbl prec exp tstb LOCAL_SGN(%a1) beqs get_mant |if positive, go process mantissa bsetl #31,%d0 |if negative, put in sign information | ; before continuing bras get_mant |go process mantissa inf: movel #0x7ff00000,%d0 |load dbl inf exponent clrl LOCAL_HI(%a1) |clear msb tstb LOCAL_SGN(%a1) beqs dbl_inf |if positive, go ahead and write it bsetl #31,%d0 |if negative put in sign information dbl_inf: movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack bras dbl_wrt get_mant: movel LOCAL_HI(%a1),%d1 |get ms mantissa bfextu %d1{#1:#20},%d1 |get upper 20 bits of ms orl %d1,%d0 |put these bits in ms word of double movel %d0,LOCAL_EX(%a1) |put the new exp back on the stack movel LOCAL_HI(%a1),%d1 |get ms mantissa movel #21,%d0 |load shift count lsll %d0,%d1 |put lower 11 bits in upper bits movel %d1,LOCAL_HI(%a1) |build lower lword in memory movel LOCAL_LO(%a1),%d1 |get ls mantissa bfextu %d1{#0:#21},%d0 |get ls 21 bits of double orl %d0,LOCAL_HI(%a1) |put them in double result dbl_wrt: movel #0x8,%d0 |byte count for double precision number exg %a0,%a1 |a0=supervisor source, a1=user dest bsrl mem_write |move the number to the user's memory rts | | dest_sgl --- write single precision value to user space | |Input | a0 -> destination address | a1 -> source in extended precision | |Output | a0 -> destroyed | a1 -> destroyed | d0 -> 0 | |Changes extended precision to single precision. | sgl_sign = ext_sign | sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias) | get rid of ext integer bit | sgl_mant = ext_mant{62:12} | | --------------- --------------- --------------- | extended -> |s| exp | |1| ms mant | | ls mant | | --------------- --------------- --------------- | 95 64 63 62 40 32 31 12 0 | | | | | | | | | | v v | --------------- | single -> |s|exp| mant | | --------------- | 31 22 0 | dest_sgl: clrl %d0 movew LOCAL_EX(%a1),%d0 |get exponent subw #0x3fff,%d0 |subtract extended precision bias cmpw #0x4000,%d0 |check if inf beqs sinf |if so, special case addw #0x7f,%d0 |add single precision bias swap %d0 |put exp in upper word of d0 lsll #7,%d0 |shift it into single exp bits tstb LOCAL_SGN(%a1) beqs get_sman |if positive, continue bsetl #31,%d0 |if negative, put in sign first bras get_sman |get mantissa sinf: movel #0x7f800000,%d0 |load single inf exp to d0 tstb LOCAL_SGN(%a1) beqs sgl_wrt |if positive, continue bsetl #31,%d0 |if negative, put in sign info bras sgl_wrt get_sman: movel LOCAL_HI(%a1),%d1 |get ms mantissa bfextu %d1{#1:#23},%d1 |get upper 23 bits of ms orl %d1,%d0 |put these bits in ms word of single sgl_wrt: movel %d0,L_SCR1(%a6) |put the new exp back on the stack movel #0x4,%d0 |byte count for single precision number tstl %a0 |users destination address beqs sgl_Dn |destination is a data register exg %a0,%a1 |a0=supervisor source, a1=user dest leal L_SCR1(%a6),%a0 |point a0 to data bsrl mem_write |move the number to the user's memory rts sgl_Dn: bsrl get_fline |returns fline word in d0 andw #0x7,%d0 |isolate register number movel %d0,%d1 |d1 has size:reg formatted for reg_dest orl #0x10,%d1 |reg_dest wants size added to reg# bral reg_dest |size is X, rts in reg_dest will | ;return to caller of dest_sgl dest_ext: tstb LOCAL_SGN(%a1) |put back sign into exponent word beqs dstx_cont bsetb #sign_bit,LOCAL_EX(%a1) dstx_cont: clrb LOCAL_SGN(%a1) |clear out the sign byte movel #0x0c,%d0 |byte count for extended number exg %a0,%a1 |a0=supervisor source, a1=user dest bsrl mem_write |move the number to the user's memory rts |end |