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 49unsigned long 50get_fsr() 51{ 52 return (0); 53} 54 55#else 56 57.section ".data" 58.align 8 59.Lgfsr: 60 .skip 8 61 62ENTRY_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 69SET_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*/ 89void 90set_fsr(unsigned long arg1) 91{ 92} 93 94#else 95 96.section ".data" 97.align 8 98.Lsfsr: 99 .skip 8 100 101ENTRY_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 108SET_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 124uint64_t 125get_gsr() 126{ 127 return (0); 128} 129 130#else 131 132ENTRY_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 137SET_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*/ 157void 158set_gsr(uint64_t arg1) 159{ 160} 161 162#else 163 164ENTRY_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 169SET_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*/ 193unsigned long 194int_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 208ENTRY_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 219SET_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*/ 237unsigned long 238int_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 255ENTRY_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 266SET_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*/ 283unsigned long 284float_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 298ENTRY_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 309SET_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*/ 326unsigned long 327float_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 341ENTRY_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 352SET_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*/ 369uint64_t 370convert_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 384ENTRY_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 395SET_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*/ 412unsigned long 413convert_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 430ENTRY_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 441SET_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*/ 458unsigned long 459negate_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 473ENTRY_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 484SET_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*/ 501uint64_t 502negate_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 516ENTRY_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 527SET_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*/ 544unsigned long 545absolute_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 559ENTRY_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 570SET_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*/ 587uint64_t 588absolute_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 602ENTRY_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 613SET_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*/ 636uint64_t 637sqrt_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 651ENTRY_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 662SET_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*/ 679uint64_t 680sqrt_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 694ENTRY_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 705SET_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*/ 722unsigned long 723add_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 739ENTRY_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 753SET_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*/ 770uint64_t 771add_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 787ENTRY_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 801SET_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*/ 818unsigned long 819sub_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 835ENTRY_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 849SET_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*/ 866uint64_t 867sub_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 883ENTRY_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 897SET_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*/ 914unsigned 915long 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 931ENTRY_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 945SET_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*/ 962uint64_t 963mult_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 979ENTRY_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 993SET_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*/ 1010unsigned long 1011div_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 1027ENTRY_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 1043SET_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*/ 1060uint64_t 1061div_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 1077ENTRY_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 1091SET_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*/ 1115unsigned long 1116cmp_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 1132ENTRY_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 1147SET_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*/ 1165unsigned long 1166cmp_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 1182ENTRY_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 1197SET_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*/ 1213uint64_t 1214float_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 1232ENTRY_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 1245SET_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*/ 1262uint64_t 1263float_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 1278ENTRY_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 1291SET_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*/ 1309unsigned long 1310long_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 1325ENTRY_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 1336SET_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*/ 1354uint64_t 1355long_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 1368ENTRY_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 1379SET_SIZE(long_float_d) 1380 1381#endif 1382