1 * $NetBSD: do_func.sa,v 1.3 2001/12/09 01:43:13 briggs Exp $ 2 3 * MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 4 * M68000 Hi-Performance Microprocessor Division 5 * M68040 Software Package 6 * 7 * M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 8 * All rights reserved. 9 * 10 * THE SOFTWARE is provided on an "AS IS" basis and without warranty. 11 * To the maximum extent permitted by applicable law, 12 * MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 13 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 14 * PARTICULAR PURPOSE and any warranty against infringement with 15 * regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 16 * and any accompanying written materials. 17 * 18 * To the maximum extent permitted by applicable law, 19 * IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 20 * (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 21 * PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 22 * OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 23 * SOFTWARE. Motorola assumes no responsibility for the maintenance 24 * and support of the SOFTWARE. 25 * 26 * You are hereby granted a copyright license to use, modify, and 27 * distribute the SOFTWARE so long as this entire notice is retained 28 * without alteration in any modified and/or redistributed versions, 29 * and that such modified versions are clearly identified as such. 30 * No licenses are granted by implication, estoppel or otherwise 31 * under any patents or trademarks of Motorola, Inc. 32 33 * 34 * do_func.sa 3.4 2/18/91 35 * 36 * Do_func performs the unimplemented operation. The operation 37 * to be performed is determined from the lower 7 bits of the 38 * extension word (except in the case of fmovecr and fsincos). 39 * The opcode and tag bits form an index into a jump table in 40 * tbldo.sa. Cases of zero, infinity and NaN are handled in 41 * do_func by forcing the default result. Normalized and 42 * denormalized (there are no unnormalized numbers at this 43 * point) are passed onto the emulation code. 44 * 45 * CMDREG1B and STAG are extracted from the fsave frame 46 * and combined to form the table index. The function called 47 * will start with a0 pointing to the ETEMP operand. Dyadic 48 * functions can find FPTEMP at -12(a0). 49 * 50 * Called functions return their result in fp0. Sincos returns 51 * sin(x) in fp0 and cos(x) in fp1. 52 * 53 54 DO_FUNC IDNT 2,1 Motorola 040 Floating Point Software Package 55 56 section 8 57 58 include fpsp.h 59 60 xref t_dz2 61 xref t_operr 62 xref t_inx2 63 xref t_resdnrm 64 xref dst_nan 65 xref src_nan 66 xref nrm_set 67 xref sto_cos 68 69 xref tblpre 70 xref slognp1,slogn,slog10,slog2 71 xref slognd,slog10d,slog2d 72 xref smod,srem 73 xref sscale 74 xref smovcr 75 76 PONE dc.l $3fff0000,$80000000,$00000000 ;+1 77 MONE dc.l $bfff0000,$80000000,$00000000 ;-1 78 PZERO dc.l $00000000,$00000000,$00000000 ;+0 79 MZERO dc.l $80000000,$00000000,$00000000 ;-0 80 PINF dc.l $7fff0000,$00000000,$00000000 ;+inf 81 MINF dc.l $ffff0000,$00000000,$00000000 ;-inf 82 QNAN dc.l $7fff0000,$ffffffff,$ffffffff ;non-signaling nan 83 PPIBY2 dc.l $3FFF0000,$C90FDAA2,$2168C235 ;+PI/2 84 MPIBY2 dc.l $bFFF0000,$C90FDAA2,$2168C235 ;-PI/2 85 86 xdef do_func 87 do_func: 88 clr.b CU_ONLY(a6) 89 * 90 * Check for fmovecr. It does not follow the format of fp gen 91 * unimplemented instructions. The test is on the upper 6 bits; 92 * if they are $17, the inst is fmovecr. Call entry smovcr 93 * directly. 94 * 95 bfextu CMDREG1B(a6){0:6},d0 ;get opclass and src fields 96 cmpi.l #$17,d0 ;if op class and size fields are $17, 97 * ;it is FMOVECR; if not, continue 98 bne.b not_fmovecr 99 jmp smovcr ;fmovecr; jmp directly to emulation 100 101 not_fmovecr: 102 move.w CMDREG1B(a6),d0 103 and.l #$7F,d0 104 cmpi.l #$38,d0 ;if the extension is >= $38, 105 bge.b short_serror ;it is illegal 106 bfextu STAG(a6){0:3},d1 107 lsl.l #3,d0 ;make room for STAG 108 add.l d1,d0 ;combine for final index into table 109 lea.l tblpre,a1 ;start of monster jump table 110 move.l (a1,d0.w*4),a1 ;real target address 111 lea.l ETEMP(a6),a0 ;a0 is pointer to src op 112 move.l USER_FPCR(a6),d1 113 and.l #$FF,d1 ; discard all but rounding mode/prec 114 fmove.l #0,fpcr 115 jmp (a1) 116 * 117 * ERROR 118 * 119 xdef serror 120 serror: 121 short_serror: 122 st.b STORE_FLG(a6) 123 rts 124 * 125 * These routines load forced values into fp0. They are called 126 * by index into tbldo. 127 * 128 * Load a signed zero to fp0 and set inex2/ainex 129 * 130 xdef snzrinx 131 snzrinx: 132 btst.b #sign_bit,LOCAL_EX(a0) ;get sign of source operand 133 bne.b ld_mzinx ;if negative, branch 134 bsr ld_pzero ;bsr so we can return and set inx 135 bra t_inx2 ;now, set the inx for the next inst 136 ld_mzinx: 137 bsr ld_mzero ;if neg, load neg zero, return here 138 bra t_inx2 ;now, set the inx for the next inst 139 * 140 * Load a signed zero to fp0; do not set inex2/ainex 141 * 142 xdef szero 143 szero: 144 btst.b #sign_bit,LOCAL_EX(a0) ;get sign of source operand 145 bne ld_mzero ;if neg, load neg zero 146 bra ld_pzero ;load positive zero 147 * 148 * Load a signed infinity to fp0; do not set inex2/ainex 149 * 150 xdef sinf 151 sinf: 152 btst.b #sign_bit,LOCAL_EX(a0) ;get sign of source operand 153 bne ld_minf ;if negative branch 154 bra ld_pinf 155 * 156 * Load a signed one to fp0; do not set inex2/ainex 157 * 158 xdef sone 159 sone: 160 btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source 161 bne ld_mone 162 bra ld_pone 163 * 164 * Load a signed pi/2 to fp0; do not set inex2/ainex 165 * 166 xdef spi_2 167 spi_2: 168 btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source 169 bne ld_mpi2 170 bra ld_ppi2 171 * 172 * Load either a +0 or +inf for plus/minus operand 173 * 174 xdef szr_inf 175 szr_inf: 176 btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source 177 bne ld_pzero 178 bra ld_pinf 179 * 180 * Result is either an operr or +inf for plus/minus operand 181 * [Used by slogn, slognp1, slog10, and slog2] 182 * 183 xdef sopr_inf 184 sopr_inf: 185 btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source 186 bne t_operr 187 bra ld_pinf 188 * 189 * FLOGNP1 190 * 191 xdef sslognp1 192 sslognp1: 193 fmovem.x (a0),fp0 194 fcmp.b #-1,fp0 195 fbgt slognp1 196 fbeq t_dz2 ;if = -1, divide by zero exception 197 fmove.l #0,FPSR ;clr N flag 198 bra t_operr ;take care of operands < -1 199 * 200 * FETOXM1 201 * 202 xdef setoxm1i 203 setoxm1i: 204 btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source 205 bne ld_mone 206 bra ld_pinf 207 * 208 * FLOGN 209 * 210 * Test for 1.0 as an input argument, returning +zero. Also check 211 * the sign and return operr if negative. 212 * 213 xdef sslogn 214 sslogn: 215 btst.b #sign_bit,LOCAL_EX(a0) 216 bne t_operr ;take care of operands < 0 217 cmpi.w #$3fff,LOCAL_EX(a0) ;test for 1.0 input 218 bne slogn 219 cmpi.l #$80000000,LOCAL_HI(a0) 220 bne slogn 221 tst.l LOCAL_LO(a0) 222 bne slogn 223 fmove.x PZERO,fp0 224 rts 225 226 xdef sslognd 227 sslognd: 228 btst.b #sign_bit,LOCAL_EX(a0) 229 beq slognd 230 bra t_operr ;take care of operands < 0 231 232 * 233 * FLOG10 234 * 235 xdef sslog10 236 sslog10: 237 btst.b #sign_bit,LOCAL_EX(a0) 238 bne t_operr ;take care of operands < 0 239 cmpi.w #$3fff,LOCAL_EX(a0) ;test for 1.0 input 240 bne slog10 241 cmpi.l #$80000000,LOCAL_HI(a0) 242 bne slog10 243 tst.l LOCAL_LO(a0) 244 bne slog10 245 fmove.x PZERO,fp0 246 rts 247 248 xdef sslog10d 249 sslog10d: 250 btst.b #sign_bit,LOCAL_EX(a0) 251 beq slog10d 252 bra t_operr ;take care of operands < 0 253 254 * 255 * FLOG2 256 * 257 xdef sslog2 258 sslog2: 259 btst.b #sign_bit,LOCAL_EX(a0) 260 bne t_operr ;take care of operands < 0 261 cmpi.w #$3fff,LOCAL_EX(a0) ;test for 1.0 input 262 bne slog2 263 cmpi.l #$80000000,LOCAL_HI(a0) 264 bne slog2 265 tst.l LOCAL_LO(a0) 266 bne slog2 267 fmove.x PZERO,fp0 268 rts 269 270 xdef sslog2d 271 sslog2d: 272 btst.b #sign_bit,LOCAL_EX(a0) 273 beq slog2d 274 bra t_operr ;take care of operands < 0 275 276 * 277 * FMOD 278 * 279 pmodt: 280 * ;$21 fmod 281 * ;dtag,stag 282 dc.l smod ; 00,00 norm,norm = normal 283 dc.l smod_oper ; 00,01 norm,zero = nan with operr 284 dc.l smod_fpn ; 00,10 norm,inf = fpn 285 dc.l smod_snan ; 00,11 norm,nan = nan 286 dc.l smod_zro ; 01,00 zero,norm = +-zero 287 dc.l smod_oper ; 01,01 zero,zero = nan with operr 288 dc.l smod_zro ; 01,10 zero,inf = +-zero 289 dc.l smod_snan ; 01,11 zero,nan = nan 290 dc.l smod_oper ; 10,00 inf,norm = nan with operr 291 dc.l smod_oper ; 10,01 inf,zero = nan with operr 292 dc.l smod_oper ; 10,10 inf,inf = nan with operr 293 dc.l smod_snan ; 10,11 inf,nan = nan 294 dc.l smod_dnan ; 11,00 nan,norm = nan 295 dc.l smod_dnan ; 11,01 nan,zero = nan 296 dc.l smod_dnan ; 11,10 nan,inf = nan 297 dc.l smod_dnan ; 11,11 nan,nan = nan 298 299 xdef pmod 300 pmod: 301 clr.b FPSR_QBYTE(a6) ; clear quotient field 302 bfextu STAG(a6){0:3},d0 ;stag = d0 303 bfextu DTAG(a6){0:3},d1 ;dtag = d1 304 305 * 306 * Alias extended denorms to norms for the jump table. 307 * 308 bclr.l #2,d0 309 bclr.l #2,d1 310 311 lsl.b #2,d1 312 or.b d0,d1 ;d1{3:2} = dtag, d1{1:0} = stag 313 * ;Tag values: 314 * ;00 = norm or denorm 315 * ;01 = zero 316 * ;10 = inf 317 * ;11 = nan 318 lea pmodt,a1 319 move.l (a1,d1.w*4),a1 320 jmp (a1) 321 322 smod_snan: 323 bra src_nan 324 smod_dnan: 325 bra dst_nan 326 smod_oper: 327 bra t_operr 328 smod_zro: 329 move.b ETEMP(a6),d1 ;get sign of src op 330 move.b FPTEMP(a6),d0 ;get sign of dst op 331 eor.b d0,d1 ;get exor of sign bits 332 btst.l #7,d1 ;test for sign 333 beq.b smod_zsn ;if clr, do not set sign big 334 bset.b #q_sn_bit,FPSR_QBYTE(a6) ;set q-byte sign bit 335 smod_zsn: 336 btst.l #7,d0 ;test if + or - 337 beq ld_pzero ;if pos then load +0 338 bra ld_mzero ;else neg load -0 339 340 smod_fpn: 341 move.b ETEMP(a6),d1 ;get sign of src op 342 move.b FPTEMP(a6),d0 ;get sign of dst op 343 eor.b d0,d1 ;get exor of sign bits 344 btst.l #7,d1 ;test for sign 345 beq.b smod_fsn ;if clr, do not set sign big 346 bset.b #q_sn_bit,FPSR_QBYTE(a6) ;set q-byte sign bit 347 smod_fsn: 348 tst.b DTAG(a6) ;filter out denormal destination case 349 bpl.b smod_nrm ; 350 lea.l FPTEMP(a6),a0 ;a0<- addr(FPTEMP) 351 bra t_resdnrm ;force UNFL(but exact) result 352 smod_nrm: 353 fmove.l USER_FPCR(a6),fpcr ;use user's rmode and precision 354 fmove.x FPTEMP(a6),fp0 ;return dest to fp0 355 rts 356 357 * 358 * FREM 359 * 360 premt: 361 * ;$25 frem 362 * ;dtag,stag 363 dc.l srem ; 00,00 norm,norm = normal 364 dc.l srem_oper ; 00,01 norm,zero = nan with operr 365 dc.l srem_fpn ; 00,10 norm,inf = fpn 366 dc.l srem_snan ; 00,11 norm,nan = nan 367 dc.l srem_zro ; 01,00 zero,norm = +-zero 368 dc.l srem_oper ; 01,01 zero,zero = nan with operr 369 dc.l srem_zro ; 01,10 zero,inf = +-zero 370 dc.l srem_snan ; 01,11 zero,nan = nan 371 dc.l srem_oper ; 10,00 inf,norm = nan with operr 372 dc.l srem_oper ; 10,01 inf,zero = nan with operr 373 dc.l srem_oper ; 10,10 inf,inf = nan with operr 374 dc.l srem_snan ; 10,11 inf,nan = nan 375 dc.l srem_dnan ; 11,00 nan,norm = nan 376 dc.l srem_dnan ; 11,01 nan,zero = nan 377 dc.l srem_dnan ; 11,10 nan,inf = nan 378 dc.l srem_dnan ; 11,11 nan,nan = nan 379 380 xdef prem 381 prem: 382 clr.b FPSR_QBYTE(a6) ;clear quotient field 383 bfextu STAG(a6){0:3},d0 ;stag = d0 384 bfextu DTAG(a6){0:3},d1 ;dtag = d1 385 * 386 * Alias extended denorms to norms for the jump table. 387 * 388 bclr #2,d0 389 bclr #2,d1 390 391 lsl.b #2,d1 392 or.b d0,d1 ;d1{3:2} = dtag, d1{1:0} = stag 393 * ;Tag values: 394 * ;00 = norm or denorm 395 * ;01 = zero 396 * ;10 = inf 397 * ;11 = nan 398 lea premt,a1 399 move.l (a1,d1.w*4),a1 400 jmp (a1) 401 402 srem_snan: 403 bra src_nan 404 srem_dnan: 405 bra dst_nan 406 srem_oper: 407 bra t_operr 408 srem_zro: 409 move.b ETEMP(a6),d1 ;get sign of src op 410 move.b FPTEMP(a6),d0 ;get sign of dst op 411 eor.b d0,d1 ;get exor of sign bits 412 btst.l #7,d1 ;test for sign 413 beq.b srem_zsn ;if clr, do not set sign big 414 bset.b #q_sn_bit,FPSR_QBYTE(a6) ;set q-byte sign bit 415 srem_zsn: 416 btst.l #7,d0 ;test if + or - 417 beq ld_pzero ;if pos then load +0 418 bra ld_mzero ;else neg load -0 419 420 srem_fpn: 421 move.b ETEMP(a6),d1 ;get sign of src op 422 move.b FPTEMP(a6),d0 ;get sign of dst op 423 eor.b d0,d1 ;get exor of sign bits 424 btst.l #7,d1 ;test for sign 425 beq.b srem_fsn ;if clr, do not set sign big 426 bset.b #q_sn_bit,FPSR_QBYTE(a6) ;set q-byte sign bit 427 srem_fsn: 428 tst.b DTAG(a6) ;filter out denormal destination case 429 bpl.b srem_nrm ; 430 lea.l FPTEMP(a6),a0 ;a0<- addr(FPTEMP) 431 bra t_resdnrm ;force UNFL(but exact) result 432 srem_nrm: 433 fmove.l USER_FPCR(a6),fpcr ;use user's rmode and precision 434 fmove.x FPTEMP(a6),fp0 ;return dest to fp0 435 rts 436 * 437 * FSCALE 438 * 439 pscalet: 440 * ;$26 fscale 441 * ;dtag,stag 442 dc.l sscale ; 00,00 norm,norm = result 443 dc.l sscale ; 00,01 norm,zero = fpn 444 dc.l scl_opr ; 00,10 norm,inf = nan with operr 445 dc.l scl_snan ; 00,11 norm,nan = nan 446 dc.l scl_zro ; 01,00 zero,norm = +-zero 447 dc.l scl_zro ; 01,01 zero,zero = +-zero 448 dc.l scl_opr ; 01,10 zero,inf = nan with operr 449 dc.l scl_snan ; 01,11 zero,nan = nan 450 dc.l scl_inf ; 10,00 inf,norm = +-inf 451 dc.l scl_inf ; 10,01 inf,zero = +-inf 452 dc.l scl_opr ; 10,10 inf,inf = nan with operr 453 dc.l scl_snan ; 10,11 inf,nan = nan 454 dc.l scl_dnan ; 11,00 nan,norm = nan 455 dc.l scl_dnan ; 11,01 nan,zero = nan 456 dc.l scl_dnan ; 11,10 nan,inf = nan 457 dc.l scl_dnan ; 11,11 nan,nan = nan 458 459 xdef pscale 460 pscale: 461 bfextu STAG(a6){0:3},d0 ;stag in d0 462 bfextu DTAG(a6){0:3},d1 ;dtag in d1 463 bclr.l #2,d0 ;alias denorm into norm 464 bclr.l #2,d1 ;alias denorm into norm 465 lsl.b #2,d1 466 or.b d0,d1 ;d1{4:2} = dtag, d1{1:0} = stag 467 * ;dtag values stag values: 468 * ;000 = norm 00 = norm 469 * ;001 = zero 01 = zero 470 * ;010 = inf 10 = inf 471 * ;011 = nan 11 = nan 472 * ;100 = dnrm 473 * 474 * 475 lea.l pscalet,a1 ;load start of jump table 476 move.l (a1,d1.w*4),a1 ;load a1 with label depending on tag 477 jmp (a1) ;go to the routine 478 479 scl_opr: 480 bra t_operr 481 482 scl_dnan: 483 bra dst_nan 484 485 scl_zro: 486 btst.b #sign_bit,FPTEMP_EX(a6) ;test if + or - 487 beq ld_pzero ;if pos then load +0 488 bra ld_mzero ;if neg then load -0 489 scl_inf: 490 btst.b #sign_bit,FPTEMP_EX(a6) ;test if + or - 491 beq ld_pinf ;if pos then load +inf 492 bra ld_minf ;else neg load -inf 493 scl_snan: 494 bra src_nan 495 * 496 * FSINCOS 497 * 498 xdef ssincosz 499 ssincosz: 500 btst.b #sign_bit,ETEMP(a6) ;get sign 501 beq.b sincosp 502 fmove.x MZERO,fp0 503 bra.b sincoscom 504 sincosp: 505 fmove.x PZERO,fp0 506 sincoscom: 507 fmovem.x PONE,fp1 ;do not allow FPSR to be affected 508 bra sto_cos ;store cosine result 509 510 xdef ssincosi 511 ssincosi: 512 fmove.x QNAN,fp1 ;load NAN 513 bsr sto_cos ;store cosine result 514 fmove.x QNAN,fp0 ;load NAN 515 bra t_operr 516 517 xdef ssincosnan 518 ssincosnan: 519 move.l ETEMP_EX(a6),FP_SCR1(a6) 520 move.l ETEMP_HI(a6),FP_SCR1+4(a6) 521 move.l ETEMP_LO(a6),FP_SCR1+8(a6) 522 bset.b #signan_bit,FP_SCR1+4(a6) 523 fmovem.x FP_SCR1(a6),fp1 524 bsr sto_cos 525 bra src_nan 526 * 527 * This code forces default values for the zero, inf, and nan cases 528 * in the transcendentals code. The CC bits must be set in the 529 * stacked FPSR to be correctly reported. 530 * 531 ***Returns +PI/2 532 xdef ld_ppi2 533 ld_ppi2: 534 fmove.x PPIBY2,fp0 ;load +pi/2 535 bra t_inx2 ;set inex2 exc 536 537 ***Returns -PI/2 538 xdef ld_mpi2 539 ld_mpi2: 540 fmove.x MPIBY2,fp0 ;load -pi/2 541 or.l #neg_mask,USER_FPSR(a6) ;set N bit 542 bra t_inx2 ;set inex2 exc 543 544 ***Returns +inf 545 xdef ld_pinf 546 ld_pinf: 547 fmove.x PINF,fp0 ;load +inf 548 or.l #inf_mask,USER_FPSR(a6) ;set I bit 549 rts 550 551 ***Returns -inf 552 xdef ld_minf 553 ld_minf: 554 fmove.x MINF,fp0 ;load -inf 555 or.l #neg_mask+inf_mask,USER_FPSR(a6) ;set N and I bits 556 rts 557 558 ***Returns +1 559 xdef ld_pone 560 ld_pone: 561 fmove.x PONE,fp0 ;load +1 562 rts 563 564 ***Returns -1 565 xdef ld_mone 566 ld_mone: 567 fmove.x MONE,fp0 ;load -1 568 or.l #neg_mask,USER_FPSR(a6) ;set N bit 569 rts 570 571 ***Returns +0 572 xdef ld_pzero 573 ld_pzero: 574 fmove.x PZERO,fp0 ;load +0 575 or.l #z_mask,USER_FPSR(a6) ;set Z bit 576 rts 577 578 ***Returns -0 579 xdef ld_mzero 580 ld_mzero: 581 fmove.x MZERO,fp0 ;load -0 582 or.l #neg_mask+z_mask,USER_FPSR(a6) ;set N and Z bits 583 rts 584 585 end 586