Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | | |
| 2 | | util.sa 3.7 7/29/91 |
| 3 | | |
| 4 | | This file contains routines used by other programs. |
| 5 | | |
| 6 | | ovf_res: used by overflow to force the correct |
| 7 | | result. ovf_r_k, ovf_r_x2, ovf_r_x3 are |
| 8 | | derivatives of this routine. |
| 9 | | get_fline: get user's opcode word |
| 10 | | g_dfmtou: returns the destination format. |
| 11 | | g_opcls: returns the opclass of the float instruction. |
| 12 | | g_rndpr: returns the rounding precision. |
| 13 | | reg_dest: write byte, word, or long data to Dn |
| 14 | | |
| 15 | | |
| 16 | | Copyright (C) Motorola, Inc. 1990 |
| 17 | | All Rights Reserved |
| 18 | | |
| 19 | | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA |
| 20 | | The copyright notice above does not evidence any |
| 21 | | actual or intended publication of such source code. |
| 22 | |
| 23 | |UTIL idnt 2,1 | Motorola 040 Floating Point Software Package |
| 24 | |
| 25 | |section 8 |
| 26 | |
| 27 | #include "fpsp.h" |
| 28 | |
| 29 | |xref mem_read |
| 30 | |
| 31 | .global g_dfmtou |
| 32 | .global g_opcls |
| 33 | .global g_rndpr |
| 34 | .global get_fline |
| 35 | .global reg_dest |
| 36 | |
| 37 | | |
| 38 | | Final result table for ovf_res. Note that the negative counterparts |
| 39 | | are unnecessary as ovf_res always returns the sign separately from |
| 40 | | the exponent. |
| 41 | | ;+inf |
| 42 | EXT_PINF: .long 0x7fff0000,0x00000000,0x00000000,0x00000000 |
| 43 | | ;largest +ext |
| 44 | EXT_PLRG: .long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 |
| 45 | | ;largest magnitude +sgl in ext |
| 46 | SGL_PLRG: .long 0x407e0000,0xffffff00,0x00000000,0x00000000 |
| 47 | | ;largest magnitude +dbl in ext |
| 48 | DBL_PLRG: .long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 |
| 49 | | ;largest -ext |
| 50 | |
| 51 | tblovfl: |
| 52 | .long EXT_RN |
| 53 | .long EXT_RZ |
| 54 | .long EXT_RM |
| 55 | .long EXT_RP |
| 56 | .long SGL_RN |
| 57 | .long SGL_RZ |
| 58 | .long SGL_RM |
| 59 | .long SGL_RP |
| 60 | .long DBL_RN |
| 61 | .long DBL_RZ |
| 62 | .long DBL_RM |
| 63 | .long DBL_RP |
| 64 | .long error |
| 65 | .long error |
| 66 | .long error |
| 67 | .long error |
| 68 | |
| 69 | |
| 70 | | |
| 71 | | ovf_r_k --- overflow result calculation |
| 72 | | |
| 73 | | This entry point is used by kernel_ex. |
| 74 | | |
| 75 | | This forces the destination precision to be extended |
| 76 | | |
| 77 | | Input: operand in ETEMP |
| 78 | | Output: a result is in ETEMP (internal extended format) |
| 79 | | |
| 80 | .global ovf_r_k |
| 81 | ovf_r_k: |
| 82 | lea ETEMP(%a6),%a0 |a0 points to source operand |
| 83 | bclrb #sign_bit,ETEMP_EX(%a6) |
| 84 | sne ETEMP_SGN(%a6) |convert to internal IEEE format |
| 85 | |
| 86 | | |
| 87 | | ovf_r_x2 --- overflow result calculation |
| 88 | | |
| 89 | | This entry point used by x_ovfl. (opclass 0 and 2) |
| 90 | | |
| 91 | | Input a0 points to an operand in the internal extended format |
| 92 | | Output a0 points to the result in the internal extended format |
| 93 | | |
| 94 | | This sets the round precision according to the user's FPCR unless the |
| 95 | | instruction is fsgldiv or fsglmul or fsadd, fdadd, fsub, fdsub, fsmul, |
| 96 | | fdmul, fsdiv, fddiv, fssqrt, fsmove, fdmove, fsabs, fdabs, fsneg, fdneg. |
| 97 | | If the instruction is fsgldiv of fsglmul, the rounding precision must be |
| 98 | | extended. If the instruction is not fsgldiv or fsglmul but a force- |
| 99 | | precision instruction, the rounding precision is then set to the force |
| 100 | | precision. |
| 101 | |
| 102 | .global ovf_r_x2 |
| 103 | ovf_r_x2: |
| 104 | btstb #E3,E_BYTE(%a6) |check for nu exception |
| 105 | beql ovf_e1_exc |it is cu exception |
| 106 | ovf_e3_exc: |
| 107 | movew CMDREG3B(%a6),%d0 |get the command word |
| 108 | andiw #0x00000060,%d0 |clear all bits except 6 and 5 |
| 109 | cmpil #0x00000040,%d0 |
| 110 | beql ovff_sgl |force precision is single |
| 111 | cmpil #0x00000060,%d0 |
| 112 | beql ovff_dbl |force precision is double |
| 113 | movew CMDREG3B(%a6),%d0 |get the command word again |
| 114 | andil #0x7f,%d0 |clear all except operation |
| 115 | cmpil #0x33,%d0 |
| 116 | beql ovf_fsgl |fsglmul or fsgldiv |
| 117 | cmpil #0x30,%d0 |
| 118 | beql ovf_fsgl |
| 119 | bra ovf_fpcr |instruction is none of the above |
| 120 | | ;use FPCR |
| 121 | ovf_e1_exc: |
| 122 | movew CMDREG1B(%a6),%d0 |get command word |
| 123 | andil #0x00000044,%d0 |clear all bits except 6 and 2 |
| 124 | cmpil #0x00000040,%d0 |
| 125 | beql ovff_sgl |the instruction is force single |
| 126 | cmpil #0x00000044,%d0 |
| 127 | beql ovff_dbl |the instruction is force double |
| 128 | movew CMDREG1B(%a6),%d0 |again get the command word |
| 129 | andil #0x0000007f,%d0 |clear all except the op code |
| 130 | cmpil #0x00000027,%d0 |
| 131 | beql ovf_fsgl |fsglmul |
| 132 | cmpil #0x00000024,%d0 |
| 133 | beql ovf_fsgl |fsgldiv |
| 134 | bra ovf_fpcr |none of the above, use FPCR |
| 135 | | |
| 136 | | |
| 137 | | Inst is either fsgldiv or fsglmul. Force extended precision. |
| 138 | | |
| 139 | ovf_fsgl: |
| 140 | clrl %d0 |
| 141 | bra ovf_res |
| 142 | |
| 143 | ovff_sgl: |
| 144 | movel #0x00000001,%d0 |set single |
| 145 | bra ovf_res |
| 146 | ovff_dbl: |
| 147 | movel #0x00000002,%d0 |set double |
| 148 | bra ovf_res |
| 149 | | |
| 150 | | The precision is in the fpcr. |
| 151 | | |
| 152 | ovf_fpcr: |
| 153 | bfextu FPCR_MODE(%a6){#0:#2},%d0 |set round precision |
| 154 | bra ovf_res |
| 155 | |
| 156 | | |
| 157 | | |
| 158 | | ovf_r_x3 --- overflow result calculation |
| 159 | | |
| 160 | | This entry point used by x_ovfl. (opclass 3 only) |
| 161 | | |
| 162 | | Input a0 points to an operand in the internal extended format |
| 163 | | Output a0 points to the result in the internal extended format |
| 164 | | |
| 165 | | This sets the round precision according to the destination size. |
| 166 | | |
| 167 | .global ovf_r_x3 |
| 168 | ovf_r_x3: |
| 169 | bsr g_dfmtou |get dest fmt in d0{1:0} |
| 170 | | ;for fmovout, the destination format |
| 171 | | ;is the rounding precision |
| 172 | |
| 173 | | |
| 174 | | ovf_res --- overflow result calculation |
| 175 | | |
| 176 | | Input: |
| 177 | | a0 points to operand in internal extended format |
| 178 | | Output: |
| 179 | | a0 points to result in internal extended format |
| 180 | | |
| 181 | .global ovf_res |
| 182 | ovf_res: |
| 183 | lsll #2,%d0 |move round precision to d0{3:2} |
| 184 | bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode |
| 185 | orl %d1,%d0 |index is fmt:mode in d0{3:0} |
| 186 | leal tblovfl,%a1 |load a1 with table address |
| 187 | movel %a1@(%d0:l:4),%a1 |use d0 as index to the table |
| 188 | jmp (%a1) |go to the correct routine |
| 189 | | |
| 190 | |case DEST_FMT = EXT |
| 191 | | |
| 192 | EXT_RN: |
| 193 | leal EXT_PINF,%a1 |answer is +/- infinity |
| 194 | bsetb #inf_bit,FPSR_CC(%a6) |
| 195 | bra set_sign |now go set the sign |
| 196 | EXT_RZ: |
| 197 | leal EXT_PLRG,%a1 |answer is +/- large number |
| 198 | bra set_sign |now go set the sign |
| 199 | EXT_RM: |
| 200 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 201 | beqs e_rm_pos |
| 202 | e_rm_neg: |
| 203 | leal EXT_PINF,%a1 |answer is negative infinity |
| 204 | orl #neginf_mask,USER_FPSR(%a6) |
| 205 | bra end_ovfr |
| 206 | e_rm_pos: |
| 207 | leal EXT_PLRG,%a1 |answer is large positive number |
| 208 | bra end_ovfr |
| 209 | EXT_RP: |
| 210 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 211 | beqs e_rp_pos |
| 212 | e_rp_neg: |
| 213 | leal EXT_PLRG,%a1 |answer is large negative number |
| 214 | bsetb #neg_bit,FPSR_CC(%a6) |
| 215 | bra end_ovfr |
| 216 | e_rp_pos: |
| 217 | leal EXT_PINF,%a1 |answer is positive infinity |
| 218 | bsetb #inf_bit,FPSR_CC(%a6) |
| 219 | bra end_ovfr |
| 220 | | |
| 221 | |case DEST_FMT = DBL |
| 222 | | |
| 223 | DBL_RN: |
| 224 | leal EXT_PINF,%a1 |answer is +/- infinity |
| 225 | bsetb #inf_bit,FPSR_CC(%a6) |
| 226 | bra set_sign |
| 227 | DBL_RZ: |
| 228 | leal DBL_PLRG,%a1 |answer is +/- large number |
| 229 | bra set_sign |now go set the sign |
| 230 | DBL_RM: |
| 231 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 232 | beqs d_rm_pos |
| 233 | d_rm_neg: |
| 234 | leal EXT_PINF,%a1 |answer is negative infinity |
| 235 | orl #neginf_mask,USER_FPSR(%a6) |
| 236 | bra end_ovfr |inf is same for all precisions (ext,dbl,sgl) |
| 237 | d_rm_pos: |
| 238 | leal DBL_PLRG,%a1 |answer is large positive number |
| 239 | bra end_ovfr |
| 240 | DBL_RP: |
| 241 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 242 | beqs d_rp_pos |
| 243 | d_rp_neg: |
| 244 | leal DBL_PLRG,%a1 |answer is large negative number |
| 245 | bsetb #neg_bit,FPSR_CC(%a6) |
| 246 | bra end_ovfr |
| 247 | d_rp_pos: |
| 248 | leal EXT_PINF,%a1 |answer is positive infinity |
| 249 | bsetb #inf_bit,FPSR_CC(%a6) |
| 250 | bra end_ovfr |
| 251 | | |
| 252 | |case DEST_FMT = SGL |
| 253 | | |
| 254 | SGL_RN: |
| 255 | leal EXT_PINF,%a1 |answer is +/- infinity |
| 256 | bsetb #inf_bit,FPSR_CC(%a6) |
| 257 | bras set_sign |
| 258 | SGL_RZ: |
| 259 | leal SGL_PLRG,%a1 |answer is +/- large number |
| 260 | bras set_sign |
| 261 | SGL_RM: |
| 262 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 263 | beqs s_rm_pos |
| 264 | s_rm_neg: |
| 265 | leal EXT_PINF,%a1 |answer is negative infinity |
| 266 | orl #neginf_mask,USER_FPSR(%a6) |
| 267 | bras end_ovfr |
| 268 | s_rm_pos: |
| 269 | leal SGL_PLRG,%a1 |answer is large positive number |
| 270 | bras end_ovfr |
| 271 | SGL_RP: |
| 272 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 273 | beqs s_rp_pos |
| 274 | s_rp_neg: |
| 275 | leal SGL_PLRG,%a1 |answer is large negative number |
| 276 | bsetb #neg_bit,FPSR_CC(%a6) |
| 277 | bras end_ovfr |
| 278 | s_rp_pos: |
| 279 | leal EXT_PINF,%a1 |answer is positive infinity |
| 280 | bsetb #inf_bit,FPSR_CC(%a6) |
| 281 | bras end_ovfr |
| 282 | |
| 283 | set_sign: |
| 284 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 285 | beqs end_ovfr |
| 286 | neg_sign: |
| 287 | bsetb #neg_bit,FPSR_CC(%a6) |
| 288 | |
| 289 | end_ovfr: |
| 290 | movew LOCAL_EX(%a1),LOCAL_EX(%a0) |do not overwrite sign |
| 291 | movel LOCAL_HI(%a1),LOCAL_HI(%a0) |
| 292 | movel LOCAL_LO(%a1),LOCAL_LO(%a0) |
| 293 | rts |
| 294 | |
| 295 | |
| 296 | | |
| 297 | | ERROR |
| 298 | | |
| 299 | error: |
| 300 | rts |
| 301 | | |
| 302 | | get_fline --- get f-line opcode of interrupted instruction |
| 303 | | |
| 304 | | Returns opcode in the low word of d0. |
| 305 | | |
| 306 | get_fline: |
| 307 | movel USER_FPIAR(%a6),%a0 |opcode address |
| 308 | movel #0,-(%a7) |reserve a word on the stack |
| 309 | leal 2(%a7),%a1 |point to low word of temporary |
| 310 | movel #2,%d0 |count |
| 311 | bsrl mem_read |
| 312 | movel (%a7)+,%d0 |
| 313 | rts |
| 314 | | |
| 315 | | g_rndpr --- put rounding precision in d0{1:0} |
| 316 | | |
| 317 | | valid return codes are: |
| 318 | | 00 - extended |
| 319 | | 01 - single |
| 320 | | 10 - double |
| 321 | | |
| 322 | | begin |
| 323 | | get rounding precision (cmdreg3b{6:5}) |
| 324 | | begin |
| 325 | | case opclass = 011 (move out) |
| 326 | | get destination format - this is the also the rounding precision |
| 327 | | |
| 328 | | case opclass = 0x0 |
| 329 | | if E3 |
| 330 | | *case RndPr(from cmdreg3b{6:5} = 11 then RND_PREC = DBL |
| 331 | | *case RndPr(from cmdreg3b{6:5} = 10 then RND_PREC = SGL |
| 332 | | case RndPr(from cmdreg3b{6:5} = 00 | 01 |
| 333 | | use precision from FPCR{7:6} |
| 334 | | case 00 then RND_PREC = EXT |
| 335 | | case 01 then RND_PREC = SGL |
| 336 | | case 10 then RND_PREC = DBL |
| 337 | | else E1 |
| 338 | | use precision in FPCR{7:6} |
| 339 | | case 00 then RND_PREC = EXT |
| 340 | | case 01 then RND_PREC = SGL |
| 341 | | case 10 then RND_PREC = DBL |
| 342 | | end |
| 343 | | |
| 344 | g_rndpr: |
| 345 | bsr g_opcls |get opclass in d0{2:0} |
| 346 | cmpw #0x0003,%d0 |check for opclass 011 |
| 347 | bnes op_0x0 |
| 348 | |
| 349 | | |
| 350 | | For move out instructions (opclass 011) the destination format |
| 351 | | is the same as the rounding precision. Pass results from g_dfmtou. |
| 352 | | |
| 353 | bsr g_dfmtou |
| 354 | rts |
| 355 | op_0x0: |
| 356 | btstb #E3,E_BYTE(%a6) |
| 357 | beql unf_e1_exc |branch to e1 underflow |
| 358 | unf_e3_exc: |
| 359 | movel CMDREG3B(%a6),%d0 |rounding precision in d0{10:9} |
| 360 | bfextu %d0{#9:#2},%d0 |move the rounding prec bits to d0{1:0} |
| 361 | cmpil #0x2,%d0 |
| 362 | beql unff_sgl |force precision is single |
| 363 | cmpil #0x3,%d0 |force precision is double |
| 364 | beql unff_dbl |
| 365 | movew CMDREG3B(%a6),%d0 |get the command word again |
| 366 | andil #0x7f,%d0 |clear all except operation |
| 367 | cmpil #0x33,%d0 |
| 368 | beql unf_fsgl |fsglmul or fsgldiv |
| 369 | cmpil #0x30,%d0 |
| 370 | beql unf_fsgl |fsgldiv or fsglmul |
| 371 | bra unf_fpcr |
| 372 | unf_e1_exc: |
| 373 | movel CMDREG1B(%a6),%d0 |get 32 bits off the stack, 1st 16 bits |
| 374 | | ;are the command word |
| 375 | andil #0x00440000,%d0 |clear all bits except bits 6 and 2 |
| 376 | cmpil #0x00400000,%d0 |
| 377 | beql unff_sgl |force single |
| 378 | cmpil #0x00440000,%d0 |force double |
| 379 | beql unff_dbl |
| 380 | movel CMDREG1B(%a6),%d0 |get the command word again |
| 381 | andil #0x007f0000,%d0 |clear all bits except the operation |
| 382 | cmpil #0x00270000,%d0 |
| 383 | beql unf_fsgl |fsglmul |
| 384 | cmpil #0x00240000,%d0 |
| 385 | beql unf_fsgl |fsgldiv |
| 386 | bra unf_fpcr |
| 387 | |
| 388 | | |
| 389 | | Convert to return format. The values from cmdreg3b and the return |
| 390 | | values are: |
| 391 | | cmdreg3b return precision |
| 392 | | -------- ------ --------- |
| 393 | | 00,01 0 ext |
| 394 | | 10 1 sgl |
| 395 | | 11 2 dbl |
| 396 | | Force single |
| 397 | | |
| 398 | unff_sgl: |
| 399 | movel #1,%d0 |return 1 |
| 400 | rts |
| 401 | | |
| 402 | | Force double |
| 403 | | |
| 404 | unff_dbl: |
| 405 | movel #2,%d0 |return 2 |
| 406 | rts |
| 407 | | |
| 408 | | Force extended |
| 409 | | |
| 410 | unf_fsgl: |
| 411 | movel #0,%d0 |
| 412 | rts |
| 413 | | |
| 414 | | Get rounding precision set in FPCR{7:6}. |
| 415 | | |
| 416 | unf_fpcr: |
| 417 | movel USER_FPCR(%a6),%d0 |rounding precision bits in d0{7:6} |
| 418 | bfextu %d0{#24:#2},%d0 |move the rounding prec bits to d0{1:0} |
| 419 | rts |
| 420 | | |
| 421 | | g_opcls --- put opclass in d0{2:0} |
| 422 | | |
| 423 | g_opcls: |
| 424 | btstb #E3,E_BYTE(%a6) |
| 425 | beqs opc_1b |if set, go to cmdreg1b |
| 426 | opc_3b: |
| 427 | clrl %d0 |if E3, only opclass 0x0 is possible |
| 428 | rts |
| 429 | opc_1b: |
| 430 | movel CMDREG1B(%a6),%d0 |
| 431 | bfextu %d0{#0:#3},%d0 |shift opclass bits d0{31:29} to d0{2:0} |
| 432 | rts |
| 433 | | |
| 434 | | g_dfmtou --- put destination format in d0{1:0} |
| 435 | | |
| 436 | | If E1, the format is from cmdreg1b{12:10} |
| 437 | | If E3, the format is extended. |
| 438 | | |
| 439 | | Dest. Fmt. |
| 440 | | extended 010 -> 00 |
| 441 | | single 001 -> 01 |
| 442 | | double 101 -> 10 |
| 443 | | |
| 444 | g_dfmtou: |
| 445 | btstb #E3,E_BYTE(%a6) |
| 446 | beqs op011 |
| 447 | clrl %d0 |if E1, size is always ext |
| 448 | rts |
| 449 | op011: |
| 450 | movel CMDREG1B(%a6),%d0 |
| 451 | bfextu %d0{#3:#3},%d0 |dest fmt from cmdreg1b{12:10} |
| 452 | cmpb #1,%d0 |check for single |
| 453 | bnes not_sgl |
| 454 | movel #1,%d0 |
| 455 | rts |
| 456 | not_sgl: |
| 457 | cmpb #5,%d0 |check for double |
| 458 | bnes not_dbl |
| 459 | movel #2,%d0 |
| 460 | rts |
| 461 | not_dbl: |
| 462 | clrl %d0 |must be extended |
| 463 | rts |
| 464 | |
| 465 | | |
| 466 | | |
| 467 | | Final result table for unf_sub. Note that the negative counterparts |
| 468 | | are unnecessary as unf_sub always returns the sign separately from |
| 469 | | the exponent. |
| 470 | | ;+zero |
| 471 | EXT_PZRO: .long 0x00000000,0x00000000,0x00000000,0x00000000 |
| 472 | | ;+zero |
| 473 | SGL_PZRO: .long 0x3f810000,0x00000000,0x00000000,0x00000000 |
| 474 | | ;+zero |
| 475 | DBL_PZRO: .long 0x3c010000,0x00000000,0x00000000,0x00000000 |
| 476 | | ;smallest +ext denorm |
| 477 | EXT_PSML: .long 0x00000000,0x00000000,0x00000001,0x00000000 |
| 478 | | ;smallest +sgl denorm |
| 479 | SGL_PSML: .long 0x3f810000,0x00000100,0x00000000,0x00000000 |
| 480 | | ;smallest +dbl denorm |
| 481 | DBL_PSML: .long 0x3c010000,0x00000000,0x00000800,0x00000000 |
| 482 | | |
| 483 | | UNF_SUB --- underflow result calculation |
| 484 | | |
| 485 | | Input: |
| 486 | | d0 contains round precision |
| 487 | | a0 points to input operand in the internal extended format |
| 488 | | |
| 489 | | Output: |
| 490 | | a0 points to correct internal extended precision result. |
| 491 | | |
| 492 | |
| 493 | tblunf: |
| 494 | .long uEXT_RN |
| 495 | .long uEXT_RZ |
| 496 | .long uEXT_RM |
| 497 | .long uEXT_RP |
| 498 | .long uSGL_RN |
| 499 | .long uSGL_RZ |
| 500 | .long uSGL_RM |
| 501 | .long uSGL_RP |
| 502 | .long uDBL_RN |
| 503 | .long uDBL_RZ |
| 504 | .long uDBL_RM |
| 505 | .long uDBL_RP |
| 506 | .long uDBL_RN |
| 507 | .long uDBL_RZ |
| 508 | .long uDBL_RM |
| 509 | .long uDBL_RP |
| 510 | |
| 511 | .global unf_sub |
| 512 | unf_sub: |
| 513 | lsll #2,%d0 |move round precision to d0{3:2} |
| 514 | bfextu FPCR_MODE(%a6){#2:#2},%d1 |set round mode |
| 515 | orl %d1,%d0 |index is fmt:mode in d0{3:0} |
| 516 | leal tblunf,%a1 |load a1 with table address |
| 517 | movel %a1@(%d0:l:4),%a1 |use d0 as index to the table |
| 518 | jmp (%a1) |go to the correct routine |
| 519 | | |
| 520 | |case DEST_FMT = EXT |
| 521 | | |
| 522 | uEXT_RN: |
| 523 | leal EXT_PZRO,%a1 |answer is +/- zero |
| 524 | bsetb #z_bit,FPSR_CC(%a6) |
| 525 | bra uset_sign |now go set the sign |
| 526 | uEXT_RZ: |
| 527 | leal EXT_PZRO,%a1 |answer is +/- zero |
| 528 | bsetb #z_bit,FPSR_CC(%a6) |
| 529 | bra uset_sign |now go set the sign |
| 530 | uEXT_RM: |
| 531 | tstb LOCAL_SGN(%a0) |if negative underflow |
| 532 | beqs ue_rm_pos |
| 533 | ue_rm_neg: |
| 534 | leal EXT_PSML,%a1 |answer is negative smallest denorm |
| 535 | bsetb #neg_bit,FPSR_CC(%a6) |
| 536 | bra end_unfr |
| 537 | ue_rm_pos: |
| 538 | leal EXT_PZRO,%a1 |answer is positive zero |
| 539 | bsetb #z_bit,FPSR_CC(%a6) |
| 540 | bra end_unfr |
| 541 | uEXT_RP: |
| 542 | tstb LOCAL_SGN(%a0) |if negative underflow |
| 543 | beqs ue_rp_pos |
| 544 | ue_rp_neg: |
| 545 | leal EXT_PZRO,%a1 |answer is negative zero |
| 546 | oril #negz_mask,USER_FPSR(%a6) |
| 547 | bra end_unfr |
| 548 | ue_rp_pos: |
| 549 | leal EXT_PSML,%a1 |answer is positive smallest denorm |
| 550 | bra end_unfr |
| 551 | | |
| 552 | |case DEST_FMT = DBL |
| 553 | | |
| 554 | uDBL_RN: |
| 555 | leal DBL_PZRO,%a1 |answer is +/- zero |
| 556 | bsetb #z_bit,FPSR_CC(%a6) |
| 557 | bra uset_sign |
| 558 | uDBL_RZ: |
| 559 | leal DBL_PZRO,%a1 |answer is +/- zero |
| 560 | bsetb #z_bit,FPSR_CC(%a6) |
| 561 | bra uset_sign |now go set the sign |
| 562 | uDBL_RM: |
| 563 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 564 | beqs ud_rm_pos |
| 565 | ud_rm_neg: |
| 566 | leal DBL_PSML,%a1 |answer is smallest denormalized negative |
| 567 | bsetb #neg_bit,FPSR_CC(%a6) |
| 568 | bra end_unfr |
| 569 | ud_rm_pos: |
| 570 | leal DBL_PZRO,%a1 |answer is positive zero |
| 571 | bsetb #z_bit,FPSR_CC(%a6) |
| 572 | bra end_unfr |
| 573 | uDBL_RP: |
| 574 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 575 | beqs ud_rp_pos |
| 576 | ud_rp_neg: |
| 577 | leal DBL_PZRO,%a1 |answer is negative zero |
| 578 | oril #negz_mask,USER_FPSR(%a6) |
| 579 | bra end_unfr |
| 580 | ud_rp_pos: |
| 581 | leal DBL_PSML,%a1 |answer is smallest denormalized negative |
| 582 | bra end_unfr |
| 583 | | |
| 584 | |case DEST_FMT = SGL |
| 585 | | |
| 586 | uSGL_RN: |
| 587 | leal SGL_PZRO,%a1 |answer is +/- zero |
| 588 | bsetb #z_bit,FPSR_CC(%a6) |
| 589 | bras uset_sign |
| 590 | uSGL_RZ: |
| 591 | leal SGL_PZRO,%a1 |answer is +/- zero |
| 592 | bsetb #z_bit,FPSR_CC(%a6) |
| 593 | bras uset_sign |
| 594 | uSGL_RM: |
| 595 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 596 | beqs us_rm_pos |
| 597 | us_rm_neg: |
| 598 | leal SGL_PSML,%a1 |answer is smallest denormalized negative |
| 599 | bsetb #neg_bit,FPSR_CC(%a6) |
| 600 | bras end_unfr |
| 601 | us_rm_pos: |
| 602 | leal SGL_PZRO,%a1 |answer is positive zero |
| 603 | bsetb #z_bit,FPSR_CC(%a6) |
| 604 | bras end_unfr |
| 605 | uSGL_RP: |
| 606 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 607 | beqs us_rp_pos |
| 608 | us_rp_neg: |
| 609 | leal SGL_PZRO,%a1 |answer is negative zero |
| 610 | oril #negz_mask,USER_FPSR(%a6) |
| 611 | bras end_unfr |
| 612 | us_rp_pos: |
| 613 | leal SGL_PSML,%a1 |answer is smallest denormalized positive |
| 614 | bras end_unfr |
| 615 | |
| 616 | uset_sign: |
| 617 | tstb LOCAL_SGN(%a0) |if negative overflow |
| 618 | beqs end_unfr |
| 619 | uneg_sign: |
| 620 | bsetb #neg_bit,FPSR_CC(%a6) |
| 621 | |
| 622 | end_unfr: |
| 623 | movew LOCAL_EX(%a1),LOCAL_EX(%a0) |be careful not to overwrite sign |
| 624 | movel LOCAL_HI(%a1),LOCAL_HI(%a0) |
| 625 | movel LOCAL_LO(%a1),LOCAL_LO(%a0) |
| 626 | rts |
| 627 | | |
| 628 | | reg_dest --- write byte, word, or long data to Dn |
| 629 | | |
| 630 | | |
| 631 | | Input: |
| 632 | | L_SCR1: Data |
| 633 | | d1: data size and dest register number formatted as: |
| 634 | | |
| 635 | | 32 5 4 3 2 1 0 |
| 636 | | ----------------------------------------------- |
| 637 | | | 0 | Size | Dest Reg # | |
| 638 | | ----------------------------------------------- |
| 639 | | |
| 640 | | Size is: |
| 641 | | 0 - Byte |
| 642 | | 1 - Word |
| 643 | | 2 - Long/Single |
| 644 | | |
| 645 | pregdst: |
| 646 | .long byte_d0 |
| 647 | .long byte_d1 |
| 648 | .long byte_d2 |
| 649 | .long byte_d3 |
| 650 | .long byte_d4 |
| 651 | .long byte_d5 |
| 652 | .long byte_d6 |
| 653 | .long byte_d7 |
| 654 | .long word_d0 |
| 655 | .long word_d1 |
| 656 | .long word_d2 |
| 657 | .long word_d3 |
| 658 | .long word_d4 |
| 659 | .long word_d5 |
| 660 | .long word_d6 |
| 661 | .long word_d7 |
| 662 | .long long_d0 |
| 663 | .long long_d1 |
| 664 | .long long_d2 |
| 665 | .long long_d3 |
| 666 | .long long_d4 |
| 667 | .long long_d5 |
| 668 | .long long_d6 |
| 669 | .long long_d7 |
| 670 | |
| 671 | reg_dest: |
| 672 | leal pregdst,%a0 |
| 673 | movel %a0@(%d1:l:4),%a0 |
| 674 | jmp (%a0) |
| 675 | |
| 676 | byte_d0: |
| 677 | moveb L_SCR1(%a6),USER_D0+3(%a6) |
| 678 | rts |
| 679 | byte_d1: |
| 680 | moveb L_SCR1(%a6),USER_D1+3(%a6) |
| 681 | rts |
| 682 | byte_d2: |
| 683 | moveb L_SCR1(%a6),%d2 |
| 684 | rts |
| 685 | byte_d3: |
| 686 | moveb L_SCR1(%a6),%d3 |
| 687 | rts |
| 688 | byte_d4: |
| 689 | moveb L_SCR1(%a6),%d4 |
| 690 | rts |
| 691 | byte_d5: |
| 692 | moveb L_SCR1(%a6),%d5 |
| 693 | rts |
| 694 | byte_d6: |
| 695 | moveb L_SCR1(%a6),%d6 |
| 696 | rts |
| 697 | byte_d7: |
| 698 | moveb L_SCR1(%a6),%d7 |
| 699 | rts |
| 700 | word_d0: |
| 701 | movew L_SCR1(%a6),USER_D0+2(%a6) |
| 702 | rts |
| 703 | word_d1: |
| 704 | movew L_SCR1(%a6),USER_D1+2(%a6) |
| 705 | rts |
| 706 | word_d2: |
| 707 | movew L_SCR1(%a6),%d2 |
| 708 | rts |
| 709 | word_d3: |
| 710 | movew L_SCR1(%a6),%d3 |
| 711 | rts |
| 712 | word_d4: |
| 713 | movew L_SCR1(%a6),%d4 |
| 714 | rts |
| 715 | word_d5: |
| 716 | movew L_SCR1(%a6),%d5 |
| 717 | rts |
| 718 | word_d6: |
| 719 | movew L_SCR1(%a6),%d6 |
| 720 | rts |
| 721 | word_d7: |
| 722 | movew L_SCR1(%a6),%d7 |
| 723 | rts |
| 724 | long_d0: |
| 725 | movel L_SCR1(%a6),USER_D0(%a6) |
| 726 | rts |
| 727 | long_d1: |
| 728 | movel L_SCR1(%a6),USER_D1(%a6) |
| 729 | rts |
| 730 | long_d2: |
| 731 | movel L_SCR1(%a6),%d2 |
| 732 | rts |
| 733 | long_d3: |
| 734 | movel L_SCR1(%a6),%d3 |
| 735 | rts |
| 736 | long_d4: |
| 737 | movel L_SCR1(%a6),%d4 |
| 738 | rts |
| 739 | long_d5: |
| 740 | movel L_SCR1(%a6),%d5 |
| 741 | rts |
| 742 | long_d6: |
| 743 | movel L_SCR1(%a6),%d6 |
| 744 | rts |
| 745 | long_d7: |
| 746 | movel L_SCR1(%a6),%d7 |
| 747 | rts |
| 748 | |end |