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