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