Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | | |
| 2 | | x_snan.sa 3.3 7/1/91 |
| 3 | | |
| 4 | | fpsp_snan --- FPSP handler for signalling NAN exception |
| 5 | | |
| 6 | | SNAN for float -> integer conversions (integer conversion of |
| 7 | | an SNAN) is a non-maskable run-time exception. |
| 8 | | |
| 9 | | For trap disabled the 040 does the following: |
| 10 | | If the dest data format is s, d, or x, then the SNAN bit in the NAN |
| 11 | | is set to one and the resulting non-signaling NAN (truncated if |
| 12 | | necessary) is transferred to the dest. If the dest format is b, w, |
| 13 | | or l, then garbage is written to the dest (actually the upper 32 bits |
| 14 | | of the mantissa are sent to the integer unit). |
| 15 | | |
| 16 | | For trap enabled the 040 does the following: |
| 17 | | If the inst is move_out, then the results are the same as for trap |
| 18 | | disabled with the exception posted. If the instruction is not move_ |
| 19 | | out, the dest. is not modified, and the exception is posted. |
| 20 | | |
| 21 | |
| 22 | | Copyright (C) Motorola, Inc. 1990 |
| 23 | | All Rights Reserved |
| 24 | | |
Matt Waddel | e00d82d | 2006-02-11 17:55:48 -0800 | [diff] [blame] | 25 | | For details on the license for this file, please see the |
| 26 | | file, README, in this same directory. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 27 | |
| 28 | X_SNAN: |idnt 2,1 | Motorola 040 Floating Point Software Package |
| 29 | |
| 30 | |section 8 |
| 31 | |
| 32 | #include "fpsp.h" |
| 33 | |
| 34 | |xref get_fline |
| 35 | |xref mem_write |
| 36 | |xref real_snan |
| 37 | |xref real_inex |
| 38 | |xref fpsp_done |
| 39 | |xref reg_dest |
| 40 | |
| 41 | .global fpsp_snan |
| 42 | fpsp_snan: |
| 43 | link %a6,#-LOCAL_SIZE |
| 44 | fsave -(%a7) |
| 45 | moveml %d0-%d1/%a0-%a1,USER_DA(%a6) |
| 46 | fmovemx %fp0-%fp3,USER_FP0(%a6) |
| 47 | fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6) |
| 48 | |
| 49 | | |
| 50 | | Check if trap enabled |
| 51 | | |
| 52 | btstb #snan_bit,FPCR_ENABLE(%a6) |
| 53 | bnes ena |If enabled, then branch |
| 54 | |
| 55 | bsrl move_out |else SNAN disabled |
| 56 | | |
| 57 | | It is possible to have an inex1 exception with the |
| 58 | | snan. If the inex enable bit is set in the FPCR, and either |
| 59 | | inex2 or inex1 occurred, we must clean up and branch to the |
| 60 | | real inex handler. |
| 61 | | |
| 62 | ck_inex: |
| 63 | moveb FPCR_ENABLE(%a6),%d0 |
| 64 | andb FPSR_EXCEPT(%a6),%d0 |
| 65 | andib #0x3,%d0 |
| 66 | beq end_snan |
| 67 | | |
| 68 | | Inexact enabled and reported, and we must take an inexact exception. |
| 69 | | |
| 70 | take_inex: |
| 71 | moveb #INEX_VEC,EXC_VEC+1(%a6) |
| 72 | moveml USER_DA(%a6),%d0-%d1/%a0-%a1 |
| 73 | fmovemx USER_FP0(%a6),%fp0-%fp3 |
| 74 | fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar |
| 75 | frestore (%a7)+ |
| 76 | unlk %a6 |
| 77 | bral real_inex |
| 78 | | |
| 79 | | SNAN is enabled. Check if inst is move_out. |
| 80 | | Make any corrections to the 040 output as necessary. |
| 81 | | |
| 82 | ena: |
| 83 | btstb #5,CMDREG1B(%a6) |if set, inst is move out |
| 84 | beq not_out |
| 85 | |
| 86 | bsrl move_out |
| 87 | |
| 88 | report_snan: |
| 89 | moveb (%a7),VER_TMP(%a6) |
| 90 | cmpib #VER_40,(%a7) |test for orig unimp frame |
| 91 | bnes ck_rev |
| 92 | moveql #13,%d0 |need to zero 14 lwords |
| 93 | bras rep_con |
| 94 | ck_rev: |
| 95 | moveql #11,%d0 |need to zero 12 lwords |
| 96 | rep_con: |
| 97 | clrl (%a7) |
| 98 | loop1: |
| 99 | clrl -(%a7) |clear and dec a7 |
| 100 | dbra %d0,loop1 |
| 101 | moveb VER_TMP(%a6),(%a7) |format a busy frame |
| 102 | moveb #BUSY_SIZE-4,1(%a7) |
| 103 | movel USER_FPSR(%a6),FPSR_SHADOW(%a6) |
| 104 | orl #sx_mask,E_BYTE(%a6) |
| 105 | moveml USER_DA(%a6),%d0-%d1/%a0-%a1 |
| 106 | fmovemx USER_FP0(%a6),%fp0-%fp3 |
| 107 | fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar |
| 108 | frestore (%a7)+ |
| 109 | unlk %a6 |
| 110 | bral real_snan |
| 111 | | |
| 112 | | Exit snan handler by expanding the unimp frame into a busy frame |
| 113 | | |
| 114 | end_snan: |
| 115 | bclrb #E1,E_BYTE(%a6) |
| 116 | |
| 117 | moveb (%a7),VER_TMP(%a6) |
| 118 | cmpib #VER_40,(%a7) |test for orig unimp frame |
| 119 | bnes ck_rev2 |
| 120 | moveql #13,%d0 |need to zero 14 lwords |
| 121 | bras rep_con2 |
| 122 | ck_rev2: |
| 123 | moveql #11,%d0 |need to zero 12 lwords |
| 124 | rep_con2: |
| 125 | clrl (%a7) |
| 126 | loop2: |
| 127 | clrl -(%a7) |clear and dec a7 |
| 128 | dbra %d0,loop2 |
| 129 | moveb VER_TMP(%a6),(%a7) |format a busy frame |
| 130 | moveb #BUSY_SIZE-4,1(%a7) |write busy size |
| 131 | movel USER_FPSR(%a6),FPSR_SHADOW(%a6) |
| 132 | orl #sx_mask,E_BYTE(%a6) |
| 133 | moveml USER_DA(%a6),%d0-%d1/%a0-%a1 |
| 134 | fmovemx USER_FP0(%a6),%fp0-%fp3 |
| 135 | fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar |
| 136 | frestore (%a7)+ |
| 137 | unlk %a6 |
| 138 | bral fpsp_done |
| 139 | |
| 140 | | |
| 141 | | Move_out |
| 142 | | |
| 143 | move_out: |
| 144 | movel EXC_EA(%a6),%a0 |get <ea> from exc frame |
| 145 | |
| 146 | bfextu CMDREG1B(%a6){#3:#3},%d0 |move rx field to d0{2:0} |
| 147 | cmpil #0,%d0 |check for long |
| 148 | beqs sto_long |branch if move_out long |
| 149 | |
| 150 | cmpil #4,%d0 |check for word |
| 151 | beqs sto_word |branch if move_out word |
| 152 | |
| 153 | cmpil #6,%d0 |check for byte |
| 154 | beqs sto_byte |branch if move_out byte |
| 155 | |
| 156 | | |
| 157 | | Not byte, word or long |
| 158 | | |
| 159 | rts |
| 160 | | |
| 161 | | Get the 32 most significant bits of etemp mantissa |
| 162 | | |
| 163 | sto_long: |
| 164 | movel ETEMP_HI(%a6),%d1 |
| 165 | movel #4,%d0 |load byte count |
| 166 | | |
| 167 | | Set signalling nan bit |
| 168 | | |
| 169 | bsetl #30,%d1 |
| 170 | | |
| 171 | | Store to the users destination address |
| 172 | | |
| 173 | tstl %a0 |check if <ea> is 0 |
| 174 | beqs wrt_dn |destination is a data register |
| 175 | |
| 176 | movel %d1,-(%a7) |move the snan onto the stack |
| 177 | movel %a0,%a1 |load dest addr into a1 |
| 178 | movel %a7,%a0 |load src addr of snan into a0 |
| 179 | bsrl mem_write |write snan to user memory |
| 180 | movel (%a7)+,%d1 |clear off stack |
| 181 | rts |
| 182 | | |
| 183 | | Get the 16 most significant bits of etemp mantissa |
| 184 | | |
| 185 | sto_word: |
| 186 | movel ETEMP_HI(%a6),%d1 |
| 187 | movel #2,%d0 |load byte count |
| 188 | | |
| 189 | | Set signalling nan bit |
| 190 | | |
| 191 | bsetl #30,%d1 |
| 192 | | |
| 193 | | Store to the users destination address |
| 194 | | |
| 195 | tstl %a0 |check if <ea> is 0 |
| 196 | beqs wrt_dn |destination is a data register |
| 197 | |
| 198 | movel %d1,-(%a7) |move the snan onto the stack |
| 199 | movel %a0,%a1 |load dest addr into a1 |
| 200 | movel %a7,%a0 |point to low word |
| 201 | bsrl mem_write |write snan to user memory |
| 202 | movel (%a7)+,%d1 |clear off stack |
| 203 | rts |
| 204 | | |
| 205 | | Get the 8 most significant bits of etemp mantissa |
| 206 | | |
| 207 | sto_byte: |
| 208 | movel ETEMP_HI(%a6),%d1 |
| 209 | movel #1,%d0 |load byte count |
| 210 | | |
| 211 | | Set signalling nan bit |
| 212 | | |
| 213 | bsetl #30,%d1 |
| 214 | | |
| 215 | | Store to the users destination address |
| 216 | | |
| 217 | tstl %a0 |check if <ea> is 0 |
| 218 | beqs wrt_dn |destination is a data register |
| 219 | movel %d1,-(%a7) |move the snan onto the stack |
| 220 | movel %a0,%a1 |load dest addr into a1 |
| 221 | movel %a7,%a0 |point to source byte |
| 222 | bsrl mem_write |write snan to user memory |
| 223 | movel (%a7)+,%d1 |clear off stack |
| 224 | rts |
| 225 | |
| 226 | | |
| 227 | | wrt_dn --- write to a data register |
| 228 | | |
| 229 | | We get here with D1 containing the data to write and D0 the |
| 230 | | number of bytes to write: 1=byte,2=word,4=long. |
| 231 | | |
| 232 | wrt_dn: |
| 233 | movel %d1,L_SCR1(%a6) |data |
| 234 | movel %d0,-(%a7) |size |
| 235 | bsrl get_fline |returns fline word in d0 |
| 236 | movel %d0,%d1 |
| 237 | andil #0x7,%d1 |d1 now holds register number |
| 238 | movel (%sp)+,%d0 |get original size |
| 239 | cmpil #4,%d0 |
| 240 | beqs wrt_long |
| 241 | cmpil #2,%d0 |
| 242 | bnes wrt_byte |
| 243 | wrt_word: |
| 244 | orl #0x8,%d1 |
| 245 | bral reg_dest |
| 246 | wrt_long: |
| 247 | orl #0x10,%d1 |
| 248 | bral reg_dest |
| 249 | wrt_byte: |
| 250 | bral reg_dest |
| 251 | | |
| 252 | | Check if it is a src nan or dst nan |
| 253 | | |
| 254 | not_out: |
| 255 | movel DTAG(%a6),%d0 |
| 256 | bfextu %d0{#0:#3},%d0 |isolate dtag in lsbs |
| 257 | |
| 258 | cmpib #3,%d0 |check for nan in destination |
| 259 | bnes issrc |destination nan has priority |
| 260 | dst_nan: |
| 261 | btstb #6,FPTEMP_HI(%a6) |check if dest nan is an snan |
| 262 | bnes issrc |no, so check source for snan |
| 263 | movew FPTEMP_EX(%a6),%d0 |
| 264 | bras cont |
| 265 | issrc: |
| 266 | movew ETEMP_EX(%a6),%d0 |
| 267 | cont: |
| 268 | btstl #15,%d0 |test for sign of snan |
| 269 | beqs clr_neg |
| 270 | bsetb #neg_bit,FPSR_CC(%a6) |
| 271 | bra report_snan |
| 272 | clr_neg: |
| 273 | bclrb #neg_bit,FPSR_CC(%a6) |
| 274 | bra report_snan |
| 275 | |
| 276 | |end |