1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include<sys/asm_linkage.h> 30 31 /* 32 * ----------------------------------------------------------------------- 33 * File: fpu-if64.s 34 * ----------------------------------------------------------------------- 35 */ 36 37 /* 38 * -------------------------------------------------------------------------- 39 * Name: Get the Floating point Status Register 40 * Function: return a copy of the FSR to caller 41 * Calling: none 42 * Returns: i0 = fsr contents 43 * Convention: fsr_value = get_fsr() ** 44 * -------------------------------------------------------------------------- 45 */ 46 47 #ifdef __lint 48 49 unsigned long 50 get_fsr() 51 { 52 return (0); 53 } 54 55 #else 56 57 .section ".data" 58 .align 8 59 .Lgfsr: 60 .skip 8 61 62 ENTRY_NP(get_fsr) 63 save %sp, -SA(MINFRAME), %sp ! save the registers & stack frame 64 setn .Lgfsr,%l6,%l0 ! .. set the address of the result holder 65 stx %fsr, [%l0] ! .. set the contents of the FSR register 66 ldx [%l0], %i0 ! .. return the fsr to caller 67 ret ! Delayed return (get user ret addr) 68 restore ! .. restore the frame window 69 SET_SIZE(get_fsr) 70 71 #endif 72 73 /* 74 * -------------------------------------------------------------------------- 75 * Name: Set Floating point Status Register 76 * Function: Set the FSR 77 * Calling: i0 = value to write to fsr 78 * Returns: none 79 * Convention: set_fsr(get_fsr() ** || <userVal>) ** 80 * Please note that the user is expected to OR the new value 81 * with the current FSR content and pass the result to 82 * set_fsr(). 83 * -------------------------------------------------------------------------- 84 */ 85 86 #ifdef __lint 87 88 /*ARGSUSED*/ 89 void 90 set_fsr(unsigned long arg1) 91 { 92 } 93 94 #else 95 96 .section ".data" 97 .align 8 98 .Lsfsr: 99 .skip 8 100 101 ENTRY_NP(set_fsr) 102 save %sp, -SA(MINFRAME), %sp ! save the registers & stack frame 103 setn .Lsfsr,%l6,%l0 ! .. set the address of the result holder 104 stx %i0, [%l0] ! .. save the value in memory 105 ldx [%l0], %fsr ! .. get the contents of the FSR register 106 ret ! Delayed return (get user ret addr) 107 restore ! .. restore the frame window 108 SET_SIZE(set_fsr) 109 110 #endif 111 112 /* 113 * -------------------------------------------------------------------------- 114 * Name: Get the Graphics Status Register 115 * Function: return a copy of the GSR to caller 116 * Calling: none 117 * Returns: i0 = gsr contents 118 * Convention: gsr_value = get_gsr() ** 119 * -------------------------------------------------------------------------- 120 */ 121 122 #ifdef __lint 123 124 uint64_t 125 get_gsr() 126 { 127 return (0); 128 } 129 130 #else 131 132 ENTRY_NP(get_gsr) 133 save %sp, -SA(MINFRAME), %sp ! save the registers & stack frame 134 rd %gsr, %i0 135 ret ! Delayed return (get user ret addr) 136 restore ! .. restore the frame window 137 SET_SIZE(get_gsr) 138 139 #endif 140 141 /* 142 * ------------------------------------------------------------------------- 143 * Name: Set Graphics Status Register 144 * Function: Set the GSR 145 * Calling: i0 = value to write to gsr 146 * Returns: none 147 * Convention: set_gsr(get_gsr() || <userVal>) 148 * Please note that the user is expected to OR the new value 149 * with the current GSR content and pass the result to 150 * set_gsr(). 151 * -------------------------------------------------------------------------- 152 */ 153 154 #ifdef __lint 155 156 /*ARGSUSED*/ 157 void 158 set_gsr(uint64_t arg1) 159 { 160 } 161 162 #else 163 164 ENTRY_NP(set_gsr) 165 save %sp, -SA(MINFRAME), %sp ! save the registers & stack frame 166 wr %i0, %g0, %gsr 167 ret ! Delayed return (get user ret addr) 168 restore ! .. restore the frame window 169 SET_SIZE(set_gsr) 170 171 #endif 172 173 /* 174 * ----------------------------------------------------------------------- 175 * Data Conversion Functions * 176 * ----------------------------------------------------------------------- 177 */ 178 179 /* 180 * -------------------------------------------------------------------------- 181 * Name: Integer to Float (Single) 182 * Function: Convert an integer value to a single precision floating point 183 * value 184 * Calling: in0 = value to convert 185 * Returns: in0 = converted value 186 * Convention: Real = int_float_s(Int) ** 187 * -------------------------------------------------------------------------- 188 */ 189 190 #ifdef __lint 191 192 /*ARGSUSED*/ 193 unsigned long 194 int_float_s(int arg1) 195 { 196 return (0); 197 } 198 199 #else 200 201 .section ".data" 202 .align 4 203 .Lfls: 204 .word 0 205 .Lfls1: 206 .word 0 207 208 ENTRY_NP(int_float_s) 209 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 210 setn .Lfls1,%l6,%o5 ! .. set the address of the result holder 211 setn .Lfls,%l6,%o4 ! .. set address of temp. mem reg 212 st %i0, [%o4] ! .. put the passed value into memory 213 ld [%o4], %f0 ! .. get the value from memory into FPU register 214 fitos %f0, %f2 ! .. get the integer into float into fpu r1 215 st %f2, [%o5] ! .. store into the location 216 ld [%o5], %i0 ! .. put the value for return 217 ret ! Delayed return (get user ret addr) 218 restore ! .. restore the frame window 219 SET_SIZE(int_float_s) 220 221 #endif 222 223 /* 224 * -------------------------------------------------------------------------- 225 * Name: Integer to Float (double) 226 * Function: Convert an integer value to a double precision floating point 227 * value 228 * Calling: in0 = value to convert 229 * Returns: in0 = converted value 230 * Convention: Real = int_float_d(Int) ** 231 * -------------------------------------------------------------------------- 232 */ 233 234 #ifdef __lint 235 236 /*ARGSUSED*/ 237 unsigned long 238 int_float_d(int arg1) 239 { 240 return (0); 241 } 242 243 #else 244 245 .section ".data" 246 .align 4 247 .Lfld: 248 .word 0 249 250 .align 8 251 252 .Lfld1: 253 .skip 8 254 255 ENTRY_NP(int_float_d) 256 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 257 setn .Lfld1,%l6,%o5 ! .. get the address of temp2 258 setn .Lfld,%l6,%o4 ! .. get the address of temp 259 st %i0, [%o4] ! .. get the user value 260 ld [%o4], %f0 ! .. into the float register 261 fitod %f0, %f2 ! .... have the fpu perform the operation 262 std %f2, [%o5] ! .. save the result 263 ldx [%o5], %i0 ! .. and return it to caller 264 ret ! Delayed return (get user ret addr) 265 restore ! .. restore the frame window 266 SET_SIZE(int_float_d) 267 268 #endif 269 270 /* 271 * -------------------------------------------------------------------------- 272 * Name: float to integer (single) 273 * Function: Convert a real value to an integer 274 * Calling: in0 = Value 275 * Returns: in0 = Value 276 * Convention: Int = float_int_s(real) ** 277 * -------------------------------------------------------------------------- 278 */ 279 280 #ifdef __lint 281 282 /*ARGSUSED*/ 283 unsigned long 284 float_int_s(unsigned long arg1) 285 { 286 return (0); 287 } 288 289 #else 290 291 .section ".data" 292 .align 4 293 .Lflnts: 294 .word 0 295 .Lflnts1: 296 .word 0 297 298 ENTRY_NP(float_int_s) 299 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 300 setn .Lflnts1,%l6,%o5 ! .. get the address of temp2 301 setn .Lflnts,%l6,%o4 ! .... and temp 302 st %i0, [%o4] ! .. get the users value 303 ld [%o4], %f0 ! .. into the float register 304 fstoi %f0, %f2 ! .... have the fpu perform the operation 305 st %f2, [%o5] ! .. save the result 306 ld [%o5], %i0 ! .. and return it to the user 307 ret ! Delayed return (get user ret addr) 308 restore ! .. restore the frame window 309 SET_SIZE(float_int_s) 310 311 #endif 312 313 /* 314 * -------------------------------------------------------------------------- 315 * Name: Float to Integer conversion (double) 316 * Function: Convert a real value to an integer 317 * Calling: in0 = value 318 * Returns: in0 = value 319 * Convention: Int = float_int_d(real) ** 320 * -------------------------------------------------------------------------- 321 */ 322 323 #ifdef __lint 324 325 /*ARGSUSED*/ 326 unsigned long 327 float_int_d(uint64_t arg1) 328 { 329 return (0); 330 } 331 332 #else 333 334 .section ".data" 335 .align 8 336 .Lflntd: 337 .skip 8 338 .Lflntd1: 339 .skip 4 340 341 ENTRY_NP(float_int_d) 342 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 343 setn .Lflntd1,%l6,%o5 ! .. get the address of temp2 344 setn .Lflntd,%l6,%o4 ! .. and temp 345 stx %i0, [%o4] ! .. get the callers value 346 ldd [%o4], %f0 ! .. into the float register 347 fdtoi %f0, %f2 ! .... have the fpu perform the operation 348 st %f2, [%o5] ! .. save the result 349 ld [%o5], %i0 ! .... and return it to caller 350 ret ! Delayed return (get user ret addr) 351 restore ! .. restore the frame window 352 SET_SIZE(float_int_d) 353 354 #endif 355 356 /* 357 * -------------------------------------------------------------------------- 358 * Name: Convert Single to double precision 359 * Function: <as the name says> 360 * Calling: in0 = value 361 * Returns: in0 = result 362 * Convention: result = convert_sp_dp(value) ** 363 * -------------------------------------------------------------------------- 364 */ 365 366 #ifdef __lint 367 368 /*ARGSUSED*/ 369 uint64_t 370 convert_sp_dp(unsigned long arg1) 371 { 372 return (0); 373 } 374 375 #else 376 377 .section ".data" 378 .align 8 379 .Lspdp: 380 .skip 8 381 .Lspdp1: 382 .skip 4 383 384 ENTRY_NP(convert_sp_dp) 385 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 386 setn .Lspdp1,%l6,%l0 ! .. get the address of temp2 387 setn .Lspdp,%l6,%l1 ! .. get the address of temp 388 st %i0, [%l0] ! .. get the callers value 389 ld [%l0], %f0 ! .. into the float register 390 fstod %f0, %f2 ! .... have the fpu perform the operation 391 std %f2, [%l1] ! .. save the result 392 ldx [%l1], %i0 ! .... and return it to the caller 393 ret ! Delayed return (get user ret addr) 394 restore ! .. restore the frame window 395 SET_SIZE(convert_sp_dp) 396 397 #endif 398 399 /* 400 * -------------------------------------------------------------------------- 401 * Name: Convert Double to Single precision 402 * Function: .. 403 * Calling: in0 = double precision value 404 * Returns: in0 = result 405 * Convention: result = convert_dp_sp(value) ** 406 * -------------------------------------------------------------------------- 407 */ 408 409 #ifdef __lint 410 411 /*ARGSUSED*/ 412 unsigned long 413 convert_dp_sp(uint64_t arg1) 414 { 415 return (0); 416 } 417 418 #else 419 420 .section ".data" 421 .align 4 422 .Ldpsp: 423 .skip 4 424 425 .align 8 426 427 .Ldpsp1: 428 .skip 8 429 430 ENTRY_NP(convert_dp_sp) 431 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 432 setn .Ldpsp1,%l6,%l0 ! .. get the address of temp2 433 setn .Ldpsp,%l6,%l1 ! .. and temp 434 stx %i0, [%l0] ! .. get the users value 435 ldd [%l0], %f0 ! .. move it to a float register 436 fdtos %f0, %f2 ! .... have the fpu perform the operation 437 st %f2, [%l1] ! .. save the result 438 ld [%l1], %i0 ! .... and return it to the caller 439 ret ! Delayed return (get user ret addr) 440 restore ! .. restore the frame window 441 SET_SIZE(convert_dp_sp) 442 443 #endif 444 445 /* 446 * -------------------------------------------------------------------------- 447 * Name: Negate a value (Single-precision) 448 * Function: Compliments the Sign bit 449 * Calling: in0 = number to cross her 450 * Returns: in0 = result 451 * Convention: result = negate_value_sp(value) ** 452 * -------------------------------------------------------------------------- 453 */ 454 455 #ifdef __lint 456 457 /*ARGSUSED*/ 458 unsigned long 459 negate_value_sp(unsigned long arg1) 460 { 461 return (0); 462 } 463 464 #else 465 466 .section ".data" 467 .align 8 468 .Lneg: 469 .skip 8 470 .Lneg1: 471 .skip 8 472 473 ENTRY_NP(negate_value_sp) 474 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 475 setn .Lneg1,%l6,%l0 ! .. get the address of .Lneg 476 setn .Lneg,%l6,%l1 ! .. and of .Lneg1 477 st %i0, [%l0] ! .. get the callers value 478 ld [%l0], %f0 ! .. into the float register 479 fnegs %f0, %f2 ! .... have the fpu perform the operation 480 st %f2, [%l1] ! .. save the result 481 ld [%l1], %i0 ! .... and return it to the caller 482 ret ! Delayed return (get user ret addr) 483 restore ! .. restore the frame window 484 SET_SIZE(negate_value_sp) 485 486 #endif 487 488 /* 489 * -------------------------------------------------------------------------- 490 * Name: Negate a value (Double-precision) 491 * Function: Compliments the Sign bit 492 * Calling: in0 = number to cross her 493 * Returns: in0 = result 494 * Convention: result = negate_value_dp(value) ** 495 * -------------------------------------------------------------------------- 496 */ 497 498 #ifdef __lint 499 500 /*ARGSUSED*/ 501 uint64_t 502 negate_value_dp(uint64_t arg1) 503 { 504 return (0); 505 } 506 507 #else 508 509 .section ".data" 510 .align 8 511 .Lneg2: 512 .skip 8 513 .Lneg3: 514 .skip 8 515 516 ENTRY_NP(negate_value_dp) 517 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 518 setn .Lneg3,%l6,%l0 ! .. get the address of .Lneg 519 setn .Lneg1,%l6,%l1 ! .. and of .Lneg1 520 stx %i0, [%l0] ! .. get the callers value 521 ldd [%l0], %f0 ! .. into the float register 522 fnegd %f0, %f2 ! .... have the fpu perform the operation 523 std %f2, [%l1] ! .. save the result 524 ldx [%l1], %i0 ! .... and return it to the caller 525 ret ! Delayed return (get user ret addr) 526 restore ! .. restore the frame window 527 SET_SIZE(negate_value_dp) 528 529 #endif 530 531 /* 532 * -------------------------------------------------------------------------- 533 * Name: Absolute Value (Single-precision) 534 * Function: Convert a SP value to its absolute value (clears sign bit) 535 * Calling: in0 = value 536 * Returns: in0 = result 537 * Convention: result = absolute_value_sp(value) ** 538 * -------------------------------------------------------------------------- 539 */ 540 541 #ifdef __lint 542 543 /*ARGSUSED*/ 544 unsigned long 545 absolute_value_sp(unsigned long arg1) 546 { 547 return (0); 548 } 549 550 #else 551 552 .section ".data" 553 .align 8 554 .Labs: 555 .skip 8 556 .Labs1: 557 .skip 8 558 559 ENTRY_NP(absolute_value_sp) 560 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 561 setn .Labs1,%l6,%l0 ! .. get the address of temp2 562 setn .Labs,%l6,%l1 ! .. and temp 563 st %i0, [%l0] ! .. get the users value 564 ld [%l0], %f0 ! .. into a float register 565 fabss %f0, %f2 ! .... have the fpu perform the operation 566 st %f2, [%l1] ! .. save the result 567 ld [%l1], %i0 ! .... and return it to caller 568 ret ! Delayed return (get user ret addr) 569 restore ! .. restore the frame window 570 SET_SIZE(absolute_value_sp) 571 572 #endif 573 574 /* 575 * -------------------------------------------------------------------------- 576 * Name: Absolute Value (Double-precision) 577 * Function: Convert a DP value to its absolute value (clears sign bit) 578 * Calling: in0 = value 579 * Returns: in0 = result 580 * Convention: result = absolute_value_dp(value) ** 581 * -------------------------------------------------------------------------- 582 */ 583 584 #ifdef __lint 585 586 /*ARGSUSED*/ 587 uint64_t 588 absolute_value_dp(uint64_t arg1) 589 { 590 return (0); 591 } 592 593 #else 594 595 .section ".data" 596 .align 8 597 .Labs2: 598 .skip 8 599 .Labs3: 600 .skip 8 601 602 ENTRY_NP(absolute_value_dp) 603 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 604 setn .Labs3,%l6,%l0 ! .. get the address of temp2 605 setn .Labs2,%l6,%l1 ! .. and temp 606 stx %i0, [%l0] ! .. get the users value 607 ldd [%l0], %f0 ! .. into a float register 608 fabsd %f0, %f2 ! .... have the fpu perform the operation 609 std %f2, [%l1] ! .. save the result 610 ldx [%l1], %i0 ! .... and return it to caller 611 ret ! Delayed return (get user ret addr) 612 restore ! .. restore the frame window 613 SET_SIZE(absolute_value_dp) 614 615 #endif 616 617 /* 618 * ----------------------------------------------------------------------- 619 * Arithmetic Functions * 620 * ----------------------------------------------------------------------- 621 */ 622 623 /* 624 * -------------------------------------------------------------------------- 625 * Name: Single-precision square-root 626 * Function: Calculate the square-root of a Single precision value 627 * Calling: in0 = value 628 * Returns: in0 = result 629 * Convention: result = sqrt_sp(value) ** 630 * -------------------------------------------------------------------------- 631 */ 632 633 #ifdef __lint 634 635 /*ARGSUSED*/ 636 uint64_t 637 sqrt_sp(unsigned long arg1) 638 { 639 return (0); 640 } 641 642 #else 643 644 .section ".data" 645 .align 4 646 .Lsqsp: 647 .skip 4 648 .Lsqsp1: 649 .skip 4 650 651 ENTRY_NP(sqrt_sp) 652 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 653 setn .Lsqsp1,%l6,%l0 ! .. get the address of temp2 654 setn .Lsqsp,%l6,%l1 ! .. and temp 655 st %i0, [%l0] ! .. get the callers value 656 ld [%l0], %f0 ! .. into the float register 657 fsqrts %f0, %f2 ! .... have the fpu perform the operation 658 st %f2, [%l1] ! .. save the result 659 ld [%l1], %i0 ! .... and return it to caller 660 ret ! Delayed return (get user ret addr) 661 restore ! .. restore the frame window 662 SET_SIZE(sqrt_sp) 663 664 #endif 665 666 /* 667 * -------------------------------------------------------------------------- 668 * Name: Double-precision square-root 669 * Function: Calculate the square-root of a double precision value 670 * Calling: in0 = value 671 * Returns: in0 = result 672 * Convention: result = sqrt_dp(value) ** 673 * -------------------------------------------------------------------------- 674 */ 675 676 #ifdef __lint 677 678 /*ARGSUSED*/ 679 uint64_t 680 sqrt_dp(uint64_t arg1) 681 { 682 return (0); 683 } 684 685 #else 686 687 .section ".data" 688 .align 8 689 .Lsqdp: 690 .skip 8 691 .Lsqdp1: 692 .skip 8 693 694 ENTRY_NP(sqrt_dp) 695 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 696 setn .Lsqdp1,%l6,%l0 ! .. get the address of temp2 697 setn .Lsqdp,%l6,%l1 ! .. and temp 698 stx %i0, [%l0] ! .. get the callers value 699 ldd [%l0], %f0 ! .. into a float register 700 fsqrtd %f0, %f2 ! .... have the fpu perform the operation 701 std %f2, [%l1] ! .. save the result 702 ldx [%l1], %i0 ! .... and return it to the caller 703 ret ! Delayed return (get user ret addr) 704 restore ! .. restore the frame window 705 SET_SIZE(sqrt_dp) 706 707 #endif 708 709 /* 710 * -------------------------------------------------------------------------- 711 * Name: Add single precision 712 * Function: Add two values 713 * Calling: in0 = value1, in1 = value2 714 * Returns: in0 = result 715 * Convention: result = add_sp(value1,value2); 716 * -------------------------------------------------------------------------- 717 */ 718 719 #ifdef __lint 720 721 /*ARGSUSED*/ 722 unsigned long 723 add_sp(unsigned long arg1, unsigned long arg2) 724 { 725 return (0); 726 } 727 728 #else 729 730 .section ".data" 731 .align 4 732 .Laddsp: 733 .skip 4 734 .Laddsp1: 735 .skip 4 736 .Laddsp2: 737 .skip 4 738 739 ENTRY_NP(add_sp) 740 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 741 setn .Laddsp2,%l6,%l0 ! .. get the address of temp2 742 setn .Laddsp1,%l6,%l1 ! .. and temp1 743 setn .Laddsp,%l6,%l2 ! .. and temp 744 st %i0, [%l0] ! .. get the users value1 745 st %i1, [%l1] ! .. and value2 746 ld [%l0], %f0 ! .. into the float registers 747 ld [%l1], %f2 ! ...... 748 fadds %f0, %f2, %f4 ! .... have the fpu perform the operation 749 st %f4, [%l2] ! .. save the result 750 ld [%l2], %i0 ! .... and return it to caller 751 ret ! Delayed return (get user ret addr) 752 restore ! .. restore the frame window 753 SET_SIZE(add_sp) 754 755 #endif 756 757 /* 758 * -------------------------------------------------------------------------- 759 * Name: Add double precision 760 * Function: Add two 64 bit values 761 * Calling: in0 = value1, in1 = value2 762 * Returns: in0.1 = result 763 * Convention: result = add_dp(value1,value2); 764 * -------------------------------------------------------------------------- 765 */ 766 767 #ifdef __lint 768 769 /*ARGSUSED*/ 770 uint64_t 771 add_dp(uint64_t arg1, uint64_t arg2) 772 { 773 return (0); 774 } 775 776 #else 777 778 .section ".data" 779 .align 8 780 .Ladddp: 781 .skip 8 782 .Ladddp1: 783 .skip 8 784 .Ladddp2: 785 .skip 8 786 787 ENTRY_NP(add_dp) 788 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 789 setn .Ladddp2,%l6,%l0 ! .. get the address of temp2 790 setn .Ladddp1,%l6,%l1 ! .. and temp1 791 setn .Ladddp,%l6,%l2 ! .. and temp 792 stx %i0, [%l0] ! .. get the user value1 793 stx %i1, [%l1] ! .. get the user value2 794 ldd [%l0], %f0 ! .. set them in float registers 795 ldd [%l1], %f2 ! .... both values 796 faddd %f0, %f2, %f4 ! .... have the fpu perform the operation 797 std %f4, [%l2] ! .. save the result 798 ldx [%l2], %i0 ! .... and return it to the caller 799 ret ! Delayed return (get user ret addr) 800 restore ! .. restore the frame window 801 SET_SIZE(add_dp) 802 803 #endif 804 805 /* 806 * -------------------------------------------------------------------------- 807 * Name: Subtract Single Precision 808 * Function: Subtract two single precision values from each other 809 * Calling: in0 = Value1, in1 = value2 810 * Returns: in0 = result 811 * Convention: result = sub_sp(value1, value2); 812 * -------------------------------------------------------------------------- 813 */ 814 815 #ifdef __lint 816 817 /*ARGSUSED*/ 818 unsigned long 819 sub_sp(unsigned long arg1, unsigned long arg2) 820 { 821 return (0); 822 } 823 824 #else 825 826 .section ".data" 827 .align 4 828 .Lsbsp: 829 .skip 4 830 .Lsbsp1: 831 .skip 4 832 .Lsbsp2: 833 .skip 4 834 835 ENTRY_NP(sub_sp) 836 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 837 setn .Lsbsp2,%l6,%l0 ! set the address of the result holder 838 setn .Lsbsp1,%l6,%l1 ! .. get the address of temp1 (holder) 839 setn .Lsbsp,%l6,%l2 ! .. get the address of temp 840 st %i0, [%l0] ! .. save the value in memory 841 st %i1, [%l1] ! .. save the value in memory 842 ld [%l0], %f0 ! .. load the fpu register 843 ld [%l1], %f2 ! .. load the fpu register 844 fsubs %f0, %f2, %f4 ! .... have the fpu perform the operation 845 st %f4, [%l2] ! .. save the result 846 ld [%l2], %i0 ! .. return the result to the caller 847 ret ! Delayed return (get user ret addr) 848 restore ! .. restore the frame window 849 SET_SIZE(sub_sp) 850 851 #endif 852 853 /* 854 * -------------------------------------------------------------------------- 855 * Name: Subtract Double Precision 856 * Function: Subtract two double precision values 857 * Calling: in0 = Value1, in1 = Value2 858 * Returns: in0 = Result 859 * Convention: Result = sub_dp(Value1,Value2); 860 * -------------------------------------------------------------------------- 861 */ 862 863 #ifdef __lint 864 865 /*ARGSUSED*/ 866 uint64_t 867 sub_dp(uint64_t arg1, uint64_t arg2) 868 { 869 return (0); 870 } 871 872 #else 873 874 .section ".data" 875 .align 8 876 .Lsbdp: 877 .skip 8 878 .Lsbdp1: 879 .skip 8 880 .Lsbdp2: 881 .skip 8 882 883 ENTRY_NP(sub_dp) 884 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 885 setn .Lsbdp2,%l6,%l0 ! set the address of the result holder 886 setn .Lsbdp1,%l6,%l1 ! .. get the address of temp1 (holder) 887 setn .Lsbdp,%l6,%l2 ! .. get the address of temp 888 stx %i0, [%l0] ! .. save the value in memory 889 stx %i1, [%l1] ! .. save the value in memory 890 ldd [%l0], %f0 ! .. load the fpu register 891 ldd [%l1], %f2 ! .. load the fpu register 892 fsubd %f0, %f2, %f4 ! .... have the fpu perform the operation 893 std %f4, [%l2] ! .. save the result 894 ldx [%l2], %i0 ! .. return the result to the caller 895 ret ! Delayed return (get user ret addr) 896 restore ! .. restore the frame window 897 SET_SIZE(sub_dp) 898 899 #endif 900 901 /* 902 * -------------------------------------------------------------------------- 903 * Name: Multiply Single Precision 904 * Function: Multiply two single precision values 905 * Calling: in0 = Value1, in1 = value2 906 * Returns: in0 = Result 907 * Convention: Result = mult_sp(Value1,Value2); 908 * -------------------------------------------------------------------------- 909 */ 910 911 #ifdef __lint 912 913 /*ARGSUSED*/ 914 unsigned 915 long mult_sp(unsigned long arg1, unsigned long arg2) 916 { 917 return (0); 918 } 919 920 #else 921 922 .section ".data" 923 .align 4 924 .Lmlsp: 925 .skip 4 926 .Lmlsp1: 927 .skip 4 928 .Lmlsp2: 929 .skip 4 930 931 ENTRY_NP(mult_sp) 932 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 933 setn .Lmlsp2,%l6,%l0 ! .. get the address of temp2 934 setn .Lmlsp1,%l6,%l1 ! .. and temp1 935 setn .Lmlsp,%l6,%l2 ! .. and temp 936 st %i0, [%l0] ! .. Get the callers value1 into temp2 937 st %i1, [%l1] ! .. Get the callers value2 into temp1 938 ld [%l0], %f0 ! .. then load Value1 939 ld [%l1], %f2 ! .. and Value2 940 fmuls %f0, %f2, %f4 ! .... have the fpu perform the operation 941 st %f4, [%l2] ! .. save the result 942 ld [%l2], %i0 ! .... and return it to the caller 943 ret ! Delayed return (get user ret addr) 944 restore ! .. restore the frame window 945 SET_SIZE(mult_sp) 946 947 #endif 948 949 /* 950 * -------------------------------------------------------------------------- 951 * Name: Multiply Double Precision 952 * Function: Multiply two values and return the result 953 * Calling: i0 = value1, i1 = value2 954 * Returns: i0 = result 955 * Convention: result = mul_dp(value1, value2); 956 * -------------------------------------------------------------------------- 957 */ 958 959 #ifdef __lint 960 961 /*ARGSUSED*/ 962 uint64_t 963 mult_dp(uint64_t arg1, uint64_t arg2) 964 { 965 return (0); 966 } 967 968 #else 969 970 .section ".data" 971 .align 8 972 .Lmldp: 973 .skip 8 974 .Lmldp1: 975 .skip 8 976 .Lmldp2: 977 .skip 8 978 979 ENTRY_NP(mult_dp) 980 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 981 setn .Lmldp2,%l6,%l0 ! set the address of the result holder 982 setn .Lmldp1,%l6,%l1 ! .. get the address of temp1 (holder) 983 setn .Lmldp,%l6,%l2 ! .. get the address of temp 984 stx %i0, [%l0] ! .. save the value in memory 985 stx %i1, [%l1] ! .. save the value in memory 986 ldd [%l0], %f0 ! .. load the fpu register 987 ldd [%l1], %f2 ! .. load the fpu register 988 fmuld %f0, %f2, %f4 ! .... have the fpu perform the operation 989 std %f4, [%l2] ! .. save the result 990 ldx [%l2], %i0 ! .. return the result to the caller 991 ret ! Delayed return (get user ret addr) 992 restore ! .. restore the frame window 993 SET_SIZE(mult_dp) 994 995 #endif 996 997 /* 998 * -------------------------------------------------------------------------- 999 * Name: Divide Single Precision 1000 * Function: Divide two value and return the result 1001 * Calling: i0 = value1, i1 = value2 1002 * Returns: i0 = result 1003 * Convention: result = div_sp(value1, value2); 1004 * -------------------------------------------------------------------------- 1005 */ 1006 1007 #ifdef __lint 1008 1009 /*ARGSUSED*/ 1010 unsigned long 1011 div_sp(unsigned long arg1, unsigned long arg2) 1012 { 1013 return (0); 1014 } 1015 1016 #else 1017 1018 .section ".data" 1019 .align 4 1020 .Ldvsp: 1021 .word 0 1022 .Ldvsp1: 1023 .word 0 1024 .Ldvsp2: 1025 .word 0 1026 1027 ENTRY_NP(div_sp) 1028 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1029 setn .Ldvsp2,%l6,%l0 ! .. get the address of temp2 1030 setn .Ldvsp1,%l6,%l1 ! .. get the address of temp1 (holder) 1031 setn .Ldvsp,%l6,%l2 ! .. get the address of temp 1032 st %i0, [%l0] ! .. save the value in memory 1033 st %i1, [%l1] ! .. save the value in memory 1034 ld [%l0], %f0 ! .. load the fpu register 1035 ld [%l1], %f2 ! .. load the fpu register 1036 1037 fdivs %f0, %f2, %f4 ! .... have the fpu perform the operation 1038 st %f4, [%l2] ! .. save the result 1039 ld [%l2], %i0 ! .. return the result to the caller 1040 1041 ret ! Delayed return (get user ret addr) 1042 restore ! .. restore the frame window 1043 SET_SIZE(div_sp) 1044 1045 #endif 1046 1047 /* 1048 * -------------------------------------------------------------------------- 1049 * Name: Divide Double Precision 1050 * Function: Divide two value and return the result 1051 * Calling: i0 = value1, i1 = value2 1052 * Returns: i0 = result 1053 * Convention: result = div_dp(value1, value2); 1054 * -------------------------------------------------------------------------- 1055 */ 1056 1057 #ifdef __lint 1058 1059 /*ARGSUSED*/ 1060 uint64_t 1061 div_dp(uint64_t arg1, uint64_t arg2) 1062 { 1063 return (0); 1064 } 1065 1066 #else 1067 1068 .section ".data" 1069 .align 8 1070 .Ldvdp: 1071 .skip 8 1072 .Ldvdp1: 1073 .skip 8 1074 .Ldvdp2: 1075 .skip 8 1076 1077 ENTRY_NP(div_dp) 1078 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1079 setn .Ldvdp2,%l6,%l0 ! .. get the address of temp2 1080 setn .Ldvdp1,%l6,%l1 ! .. get the address of temp1 (holder) 1081 setn .Ldvdp,%l6,%l2 ! .. get the address of temp 1082 stx %i0, [%l0] ! .. save the value in memory 1083 stx %i1, [%l1] ! .. save the value in memory 1084 ldd [%l0], %f0 ! .. load the fpu register 1085 ldd [%l1], %f2 ! .. load the fpu register 1086 fdivd %f0, %f2, %f4 ! .... have the fpu perform the operation 1087 std %f4, [%l2] ! .. save the result 1088 ldx [%l2], %i0 ! .. return the result to the caller 1089 ret ! Delayed return (get user ret addr) 1090 restore ! .. restore the frame window 1091 SET_SIZE(div_dp) 1092 1093 #endif 1094 1095 /* 1096 * ----------------------------------------------------------------------- 1097 * Data Comparison Functions 1098 * ----------------------------------------------------------------------- 1099 */ 1100 1101 /* 1102 * -------------------------------------------------------------------------- 1103 * Name: Compare Single and Exception if Unordered 1104 * Function: Compare two values and return the FSR flags 1105 * Warning: 1106 * Calling: i0 = value1, i2 = value2 1107 * Returns: i0 = flags 1108 * Convention: flagsresult = cmp_s_ex(value1, value2); 1109 * -------------------------------------------------------------------------- 1110 */ 1111 1112 #ifdef __lint 1113 1114 /*ARGSUSED*/ 1115 unsigned long 1116 cmp_s_ex(unsigned long arg1, unsigned long arg2) 1117 { 1118 return (0); 1119 } 1120 1121 #else 1122 1123 .section ".data" 1124 .align 8 1125 .Lcpsx: 1126 .skip 8 1127 .Lcpsx1: 1128 .skip 4 1129 .Lcpsx2: 1130 .skip 4 1131 1132 ENTRY_NP(cmp_s_ex) 1133 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1134 setn .Lcpsx2,%l6,%l0 ! .. get the address of temp2 1135 setn .Lcpsx1,%l6,%l1 ! .. get the address of temp 1136 setn .Lcpsx,%l6,%l2 ! .. get the address of temp 1137 st %i0, [%l0] ! .. save the value in memory 1138 st %i1, [%l1] ! .. save the value in memory 1139 ld [%l0], %f0 ! .. load the fpu register 1140 ld [%l1], %f2 ! .. load the fpu register 1141 fcmpes %f0, %f2 ! .... have the fpu perform the operation 1142 nop ! .. delay 1143 stx %fsr, [%l2] ! .. get the contents of the FSR register 1144 ldx [%l2], %i0 ! .. return the result to the caller 1145 ret ! Delayed return (get user ret addr) 1146 restore ! .. restore the frame window 1147 SET_SIZE(cmp_s_ex) 1148 1149 #endif 1150 1151 /* 1152 * -------------------------------------------------------------------------- 1153 * Name: Compare Double and Exception if Unordered 1154 * Function: Compare two values and return the FSR flags 1155 * Warning: 1156 * Calling: i0 = value1, i2 = value2 1157 * Returns: i0 = flags 1158 * Convention: flagsresult = cmp_d_ex(value1, value2); 1159 * -------------------------------------------------------------------------- 1160 */ 1161 1162 #ifdef __lint 1163 1164 /*ARGSUSED*/ 1165 unsigned long 1166 cmp_d_ex(unsigned long arg1, unsigned long arg2) 1167 { 1168 return (0); 1169 } 1170 1171 #else 1172 1173 .section ".data" 1174 .align 8 1175 .Lcpdx: 1176 .skip 8 1177 .Lcpdx1: 1178 .skip 8 1179 .Lcpdx2: 1180 .skip 8 1181 1182 ENTRY_NP(cmp_d_ex) 1183 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1184 setn .Lcpdx2,%l6,%l0 ! .. get the address of temp2 1185 setn .Lcpdx1,%l6,%l1 ! .. get the address of temp1 (holder) 1186 setn .Lcpdx,%l6,%l2 ! .. get the address of temp 1187 stx %i0, [%l0] ! .. save the value in memory 1188 stx %i1, [%l1] ! .. save the value in memory 1189 ldd [%l0], %f0 ! .. load the fpu register 1190 ldd [%l1], %f2 ! .. load the fpu register 1191 fcmped %f0, %f2 ! .... have the FPU do it 1192 nop ! .. delay 1193 stx %fsr, [%l2] ! .. get the contents of the FSR register 1194 ldx [%l2], %i0 ! .. return the result to the caller 1195 ret ! Delayed return (get user ret addr) 1196 restore ! .. restore the frame window 1197 SET_SIZE(cmp_d_ex) 1198 1199 #endif 1200 1201 /* 1202 * -------------------------------------------------------------------------- 1203 * Name: Float to long conversion (single) 1204 * Function: Convert a real single-precision value to a long 1205 * Calling: in0 = value 1206 * Returns: in0 = value 1207 * Convention: long = float_long_s(real) ** 1208 * -------------------------------------------------------------------------- 1209 */ 1210 #ifdef __lint 1211 1212 /*ARGSUSED*/ 1213 uint64_t 1214 float_long_s(unsigned long arg1) 1215 { 1216 return (0); 1217 } 1218 1219 #else 1220 1221 .data 1222 .align 4 1223 1224 .Lfllngs: 1225 .skip 4 1226 1227 .align 8 1228 1229 .Lfllngs1: 1230 .skip 8 1231 1232 ENTRY_NP(float_long_s) 1233 save %sp, -SA(MINFRAME), %sp 1234 setn .Lfllngs1,%l6,%o5 ! .. get the address of temp2 1235 setn .Lfllngs,%l6,%o4 ! .. and temp 1236 1237 st %i0, [%o4] ! .. get the callers value 1238 ld [%o4], %f0 ! .. into the float register 1239 fstox %f0, %f2 ! .... have the fpu perform the operation 1240 std %f2, [%o5] ! .. save the result 1241 ldx [%o5], %i0 ! .... and return it to caller 1242 1243 ret 1244 restore 1245 SET_SIZE(float_long_s) 1246 1247 #endif 1248 1249 /* 1250 * -------------------------------------------------------------------------- 1251 * Name: Float to long conversion (double) 1252 * Function: Convert a real value to a long 1253 * Calling: in0 = value 1254 * Returns: in0 = value 1255 * Convention: long = float_long_d(real) ** 1256 * -------------------------------------------------------------------------- 1257 */ 1258 1259 #ifdef __lint 1260 1261 /*ARGSUSED*/ 1262 uint64_t 1263 float_long_d(uint64_t arg1) 1264 { 1265 return (0); 1266 } 1267 1268 #else 1269 1270 .data 1271 .align 8 1272 1273 .Lfllngd: 1274 .skip 8 1275 .Lfllngd1: 1276 .skip 8 1277 1278 ENTRY_NP(float_long_d) 1279 save %sp, -SA(MINFRAME), %sp 1280 setn .Lfllngd1,%l6,%o5 ! .. get the address of temp2 1281 setn .Lfllngd,%l6,%o4 ! .. and temp 1282 1283 stx %i0, [%o4] ! .. get the callers value 1284 ldd [%o4], %f0 ! .. into the float register 1285 fdtox %f0, %f2 ! .... have the fpu perform the operation 1286 std %f2, [%o5] ! .. save the result 1287 ldx [%o5], %i0 ! .... and return it to caller 1288 1289 ret 1290 restore 1291 SET_SIZE(float_long_d) 1292 1293 #endif 1294 1295 /* 1296 * -------------------------------------------------------------------------- 1297 * Name: Long to Float (Single) 1298 * Function: Convert an integer value to a single precision floating point 1299 * value 1300 * Calling: in0 = value to convert 1301 * Returns: in0 = converted value 1302 * Convention: Real = long_float_s(Int) ** 1303 * -------------------------------------------------------------------------- 1304 */ 1305 1306 #ifdef __lint 1307 1308 /*ARGSUSED*/ 1309 unsigned long 1310 long_float_s(uint64_t arg1) 1311 { 1312 return (0); 1313 } 1314 1315 #else 1316 1317 .data 1318 .align 8 1319 1320 .Llngfls: 1321 .skip 8 1322 .Llngfls1: 1323 .skip 4 1324 1325 ENTRY_NP(long_float_s) 1326 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1327 setn .Llngfls1,%l6,%o5 ! .. set the address of the result holder 1328 setn .Llngfls,%l6,%o4 ! .. set address of temp. mem reg 1329 stx %i0, [%o4] ! .. put the passed value into memory 1330 ldd [%o4], %f0 ! .. get the value from memory into FPU register 1331 fxtos %f0, %f2 ! .. get the integer into float into fpu r1 1332 st %f2, [%o5] ! .. store into the location 1333 ld [%o5], %i0 ! .. put the value for return 1334 ret ! Delayed return (get user ret addr) 1335 restore ! .. restore the frame window 1336 SET_SIZE(long_float_s) 1337 1338 #endif 1339 1340 /* 1341 * -------------------------------------------------------------------------- 1342 * Name: Long to Float (double) 1343 * Function: Convert an integer value to a double precision floating point 1344 * value 1345 * Calling: in0 = value to convert 1346 * Returns: in0 = converted value 1347 * Convention: Real = long_float_d(Int) ** 1348 * --------------------------------------------------------------------------- 1349 */ 1350 1351 #ifdef __lint 1352 1353 /*ARGSUSED*/ 1354 uint64_t 1355 long_float_d(uint64_t arg1) 1356 { 1357 return (0); 1358 } 1359 1360 #else 1361 .data 1362 .align 8 1363 .Llngfld: 1364 .skip 8 1365 .Llngfld1: 1366 .skip 8 1367 1368 ENTRY_NP(long_float_d) 1369 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1370 setn .Llngfld1,%l6,%o5 ! .. get the address of temp2 1371 setn .Llngfld,%l6,%o4 ! .. get the address of temp 1372 stx %i0, [%o4] ! .. get the user value 1373 ldd [%o4], %f0 ! .. into the float register 1374 fxtod %f0, %f2 ! .... have the fpu perform the operation 1375 std %f2, [%o5] ! .. save the result 1376 ldx [%o5], %i0 ! .. and return it to caller 1377 ret ! Delayed return (get user ret addr) 1378 restore ! .. restore the frame window 1379 SET_SIZE(long_float_d) 1380 1381 #endif 1382