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/* 30 * Usage of %ncc 31 * 32 * When the branch instructions were modified from Bicc to BPcc format, 33 * the pseudo-op %ncc was used. This will be converted by the assembler 34 * to %icc or %xcc depending on whether the compilation is being done 35 * for 32-bit or 64-bit platforms. 36 */ 37 38 39#include<sys/asm_linkage.h> 40 41/* 42 * ------------------------------------------------------------------------ 43 * Name: datap_add() 44 * Function: This routine test the data path of the adder for single 45 * precision. 46 * Calling: i0 = value 47 * Returns: 48 * Convention: 49 * -------------------------------------------------------------------------- 50 * 51 * f0 = value 52 * f1 = 0 53 * add = f2 = value 54 */ 55 56#ifdef __lint 57 58/*ARGSUSED*/ 59unsigned long 60datap_add(unsigned long arg1) 61{ 62 return (0); 63} 64 65#else 66 67.section ".data" 68.align 4 69 70.Ldadd: 71 .skip 4 72.Ldadd1: 73 .skip 4 74 75ENTRY_NP(datap_add) 76 save %sp, -SA(MINFRAME), %sp ! save the stack frame 77 setn .Ldadd,%l6,%l0 ! get a memory address 78 setn .Ldadd1,%l6,%l1 ! .. one for the result 79 mov %g0,%l3 ! .. get a zero 80 st %l3, [%l1] ! .... and store it in memory 81 st %i0, [%l0] ! .... store the value passed 82 ld [%l0], %f0 ! .... put the passed value into f0 83 ld [%l1], %f1 ! .... put value 0 into reg f1 84 fadds %f0, %f1, %f2 ! ...... add zero and value into f2 85 fcmps %fcc0, %f0, %f2 ! .... check the value passed and added value 86 fbe,a %fcc0, datap_ok ! .. if they are equal 87 nop ! .... delay 88 89 st %f2, [%l1] ! return the result on error 90 91datap_ok: 92 ld [%l1], %i0 ! then return a zero 93 ret ! .... delay 94 restore 95SET_SIZE(datap_add) 96 97#endif 98 99/* 100 * ------------------------------------------------------------------------ 101 * Name: 102 * Function: 103 * Calling: 104 * Returns: 105 * Convention: 106 * -------------------------------------------------------------------------- 107 * 108 * This routine test the data path of multiplier for single precision 109 * f0 = value 110 * f1 = 1 111 * mult = f2 = f0 * f1 112 */ 113 114#ifdef __lint 115 116/*ARGSUSED*/ 117unsigned long 118datap_mult(unsigned long arg1) 119{ 120 return (0); 121} 122 123#else 124 125.section ".data" 126.align 4 127 128.Ldtmlt: 129 .skip 4 130.Ldtmlt1: 131 .skip 4 132 133ENTRY_NP(datap_mult) 134 save %sp, -SA(MINFRAME), %sp 135 setn .Ldtmlt,%l6,%l0 136 setn .Ldtmlt1,%l6,%l1 137 setn 0x3F800000,%l6,%l3 ! put value 1 into memory 138 st %l3, [%l1] 139 st %i0, [%l0] ! store the value passed into memory location 140 ld [%l0], %f0 ! put the passed value into f0 141 ld [%l1], %f1 ! put value 1 into reg f1 142 fmuls %f0, %f1, %f2 ! multiply value with 1 , it has to be same 143 fcmps %fcc0, %f0, %f2 144 145 fbne,a %fcc0, datap_mult_done 146 st %f2, [%l1] ! executed only when the conditional 147 ! branch is taken as annul bit is set. 148 ! This branch will be taken under 149 ! an error condition (%f0 != %f2). 150 ! Then we need to return the result. 151 152 mov %g0,%l3 153 st %l3, [%l1] 154 155datap_mult_done : 156 ld [%l1], %i0 157 ret 158 restore 159SET_SIZE(datap_mult) 160 161#endif 162 163/* 164 * ------------------------------------------------------------------------ 165 * Name: 166 * Function: 167 * Calling: 168 * Returns: 169 * Convention: 170 * -------------------------------------------------------------------------- 171 * 172 * This routine tests the data path of the weitek multiplier for 173 * double precision. Single-precision load and store are being 174 * used as the input double-precision value is taken as two SP 175 * arguments 176 * 177 * f0 = msw value 178 * f1 = lsw value 179 * 180 * f2 = 0 181 * f3 = 0 182 * add = f4 = f0 + f2 183 */ 184 185#ifdef __lint 186 187/*ARGSUSED*/ 188unsigned long 189datap_add_dp(unsigned long arg1, unsigned long arg2) 190{ 191 return (0); 192} 193 194#else 195 196.section ".data" 197.align 8 198 199.Ldtadddp: 200 .skip 8 201.Ldtadddp1: 202 .skip 8 203.Ldtadddp2: 204 .skip 8 205.Lamsw: 206 .skip 8 207.Lalsw: 208 .skip 8 209 210ENTRY_NP(datap_add_dp) 211 save %sp, -SA(MINFRAME), %sp 212 setn .Ldtadddp,%l6,%l0 213 setn .Ldtadddp1,%l6,%l1 214 setn .Ldtadddp2,%l6,%l2 215 setn .Lamsw,%l6,%l4 216 setn .Lalsw,%l6,%l5 217 mov %g0,%l3 ! put value 0 into memory 218 st %l3, [%l1] 219 st %i0, [%l0] ! msw of value 220 st %i1, [%l2] ! lsw of value 221 ld [%l0], %f0 ! put the msw into f0 222 ld [%l2], %f1 ! put the lsw into f1 223 ld [%l1], %f2 ! put 0 into f2 224 ld [%l1], %f3 ! put 0 into f3 225 faddd %f0, %f2, %f4 ! add value + 0 into f4 226 fcmpd %fcc0, %f0, %f4 ! now compare the result 227 228 fbe,a %fcc0, datap_add_dp_ok ! good 229 nop 230 231 mov 0x1,%l3 232 st %l3, [%l1] 233 234datap_add_dp_ok : 235 ld [%l1], %i0 236 ret 237 restore 238 239SET_SIZE(datap_add_dp) 240 241#endif 242 243/* 244 * ------------------------------------------------------------------------ 245 * Name: 246 * Function: 247 * Calling: 248 * Returns: 249 * Convention: 250 * 251 * This routine tests the data path of the weitek multiplier for 252 * double precision. Single-precision load and store are being 253 * used as the input double-precision value is taken as two SP 254 * arguments. 255 * 256 * f0 = msw value 257 * f1 = lsw value 258 * f2 = 0 259 * f3 = 0 260 * mult = f4 = f0 * f2 261 * ------------------------------------------------------------------------ 262 */ 263 264#ifdef __lint 265 266/*ARGSUSED*/ 267unsigned long 268datap_mult_dp(unsigned long arg1, unsigned long arg2) 269{ 270 return (0); 271} 272 273#else 274 275.section ".data" 276.align 8 277 278.Ldtmdp: 279 .skip 8 280.Ldtmdp1: 281 .skip 8 282.Ldtmdp2: 283 .skip 8 284.Lmmsw: 285 .skip 8 286.Lmlsw: 287 .skip 8 288 289ENTRY_NP(datap_mult_dp) 290 save %sp, -SA(MINFRAME), %sp 291 setn .Ldtmdp,%l6,%l0 292 setn .Ldtmdp1,%l6,%l1 293 setn .Ldtmdp2,%l6,%l2 294 setn .Lmmsw,%l6,%l4 295 setn .Lmlsw,%l6,%l5 296 setn 0x3FF00000,%l6,%l3 ! put msw value of DP 1 into memory 297 st %l3, [%l1] 298 st %i0, [%l0] ! msw of value 299 st %i1, [%l2] ! lsw of value 300 ld [%l0], %f0 ! put the msw into f0 301 ld [%l2], %f1 ! put the lsw into f1 302 ld [%l1], %f2 ! put msw of DP 1 into f2 303 mov %g0,%l3 304 st %l3, [%l1] 305 ld [%l1], %f3 ! put 0 into f3, i.e f2|f3 = 0x3ff0000000000000 (dp 1) 306 fmuld %f0, %f2, %f4 ! mult value * 1 into f4 307 fcmpd %fcc0, %f0, %f4 ! now compare the result 308 309 fbe,a %fcc0, datap_mult_dp_ok ! good 310 nop 311 312 mov 0x1,%l3 313 st %l3, [%l1] 314 315datap_mult_dp_ok : 316 ld [%l1], %i0 317 ret 318 restore 319 320SET_SIZE(datap_mult_dp) 321 322#endif 323 324/* 325 * ------------------------------------------------------------------------- 326 * for add routine all the f registers from 0 - 19 will be filled with numbers 327 * and the result should be 10. 328 * ------------------------------------------------------------------------- 329 */ 330 331#ifdef __lint 332 333unsigned long 334timing_add_sp() 335{ 336 return (0); 337} 338 339#else 340 341.section ".data" 342.align 4 343 344.Ltmasp: 345 .skip 4 346.Ltmasp1: 347 .skip 4 348.Ltmasp2: 349 .skip 4 350 351ENTRY_NP(timing_add_sp) 352 save %sp, -SA(MINFRAME), %sp ! save the registers, stacck 353 setn .Ltmasp,%l6,%l0 354 setn .Ltmasp1,%l6,%l1 355 setn .Ltmasp2,%l6,%l2 356 mov %g0,%l3 357 setn 0x3f800000,%l6,%l4 ! put value 1 358 setn 0x41200000,%l6,%l5 ! put value 10 into local 5 359 st %l5, [%l0] 360 st %l4, [%l1] 361 st %l3, [%l2] 362 ld [%l0], %f31 ! register 31 has 10 363 ld [%l1], %f30 ! register 30 has 1 364 365 ld [%l2], %f0 ! reg 0 has 0 366 fmovs %f31, %f1 ! reg1 has 10 367 fsubs %f31, %f30, %f18 ! reg 18 has 9 368 fmovs %f18, %f3 ! reg 3 has 9 369 fmovs %f30, %f2 ! reg 2 has 1 370 fmovs %f30, %f19 ! reg 19 has 1 371 fsubs %f18, %f19, %f16 ! reg 16 has 8 372 fmovs %f16, %f5 ! reg 5 has 8 373 fsubs %f31, %f16, %f17 ! reg 17 has 2 374 fmovs %f17, %f4 ! reg 4 has 2 375 fsubs %f16, %f30, %f14 ! reg 14 has 7 376 fmovs %f14, %f7 ! reg 7 has 7 377 fsubs %f31, %f14, %f15 ! reg 15 has 3 378 fmovs %f15, %f6 ! reg 6 has 3 379 fsubs %f14, %f30, %f12 ! reg 12 has 6 380 fmovs %f12, %f9 ! reg 9 has 6 381 fsubs %f31, %f12, %f13 ! reg 13 has 4 382 fmovs %f13, %f8 ! reg 8 has 4 383 fsubs %f12, %f30, %f10 ! reg 10 has 5 384 fmovs %f10, %f11 ! reg 11 has 5 385 386 fadds %f0, %f1, %f20 ! reg 0 + reg 1 = reg 20 = 10 387 fadds %f2, %f3, %f21 ! reg 2 + reg 3 = reg 21 = 10 388 fadds %f4, %f5, %f22 ! reg 4 + reg 5 = reg 22 = 10 389 fadds %f6, %f7, %f23 ! reg 6 + reg 7 = reg 23 = 10 390 fadds %f8, %f9, %f24 ! reg 8 + reg 9 = reg 24 = 10 391 fadds %f10, %f11, %f25 ! reg 10 + reg 11 = reg 25 = 10 392 fadds %f12, %f13, %f26 ! reg 12 + reg 13 = reg 26 = 10 393 fadds %f14, %f15, %f27 ! reg 14 + reg 15 = reg 27 = 10 394 fadds %f16, %f17, %f28 ! reg 16 + reg 17 = reg 28 = 10 395 fadds %f18, %f19, %f29 ! reg 18 + reg 19 = reg 29 = 10 396 397 ! Now additions are done check it out 398 fcmps %fcc0, %f31, %f20 399 fbne,a,pn %fcc0, done_t_add_sp ! If not equal, go to the end. 400 st %f20, [%l2] ! Executed only when the conditional 401 ! branch is taken as annul bit is set. 402 ! This branch will be taken under 403 ! an error condition. 404 405 ! No errors. Move on to the next register 406 407 fcmps %fcc0, %f31, %f21 408 fbne,a,pn %fcc0, done_t_add_sp 409 st %f21, [%l2] 410 411 412 fcmps %fcc0, %f31, %f22 413 fbne,a,pn %fcc0, done_t_add_sp 414 st %f22, [%l2] 415 416 417 fcmps %fcc0, %f31, %f23 418 fbne,a,pn %fcc0, done_t_add_sp 419 st %f23, [%l2] 420 421 422 fcmps %fcc0, %f31, %f24 423 fbne,a,pn %fcc0, done_t_add_sp 424 st %f24, [%l2] 425 426 427 fcmps %fcc0, %f31, %f25 428 fbne,a,pn %fcc0, done_t_add_sp 429 st %f25, [%l2] 430 431 432 fcmps %fcc0, %f31, %f26 433 fbne,a,pn %fcc0, done_t_add_sp 434 st %f26, [%l2] 435 436 437 fcmps %fcc0, %f31, %f27 438 fbne,a,pn %fcc0, done_t_add_sp 439 st %f27, [%l2] 440 441 442 fcmps %fcc0, %f31, %f28 443 fbne,a,pn %fcc0, done_t_add_sp 444 st %f28, [%l2] 445 446 447 ! Though this is the last set of compare instructions 448 ! we cannot fall through as the store needs to be done 449 ! only when the registers are not equal. That is why 450 ! we need the unconditional branch with the annul bit set. 451 fcmps %fcc0, %f31, %f29 452 fbne,a,pn %fcc0, done_t_add_sp 453 st %f29, [%l2] 454 455done_t_add_sp: 456 ld [%l2], %i0 457 ret 458 restore 459SET_SIZE(timing_add_sp) 460 461#endif 462 463/* 464 * ---------------------------------------------------------------------- 465 * for mult routine all the f registers from 0 - 19 will be filled 466 * with numbers and the result should be the number. 467 * ---------------------------------------------------------------------- 468 */ 469 470 471#ifdef __lint 472 473unsigned long 474timing_mult_sp() 475{ 476 return (0); 477} 478 479#else 480 481.section ".data" 482.align 4 483 484.Ltmmsp: 485 .skip 4 486.Ltmmsp1: 487 .skip 4 488.Ltmmsp2: 489 .skip 4 490 491ENTRY_NP(timing_mult_sp) 492 save %sp, -SA(MINFRAME), %sp ! save the registers, stacck 493 setn .Ltmmsp,%l6, %l0 494 setn .Ltmmsp1,%l6, %l1 495 setn .Ltmmsp2,%l6, %l2 496 mov %g0, %l3 497 setn 0x3f800000,%l6, %l4 ! put value 1 498 setn 0x41200000,%l6, %l5 ! put value 10 into local 5 499 st %l5, [%l0] 500 st %l4, [%l1] 501 st %l3, [%l2] 502 ld [%l0], %f31 ! register 31 has 10 503 ld [%l1], %f1 ! register 1 has 1 504 fmovs %f1, %f3 505 fmovs %f1, %f5 506 fmovs %f1, %f7 507 fmovs %f1, %f9 508 fmovs %f1, %f11 ! register 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 509 fmovs %f1, %f13 ! has a value of 1 510 fmovs %f1, %f15 511 fmovs %f1, %f17 512 fmovs %f1, %f19 ! 513 fmovs %f1, %f0 514 fmovs %f31, %f18 ! reg 18 has 10 515 fsubs %f31, %f0, %f16 ! reg 16 has 9 516 fsubs %f16, %f0, %f14 ! reg 14 has 8 517 fsubs %f14, %f0, %f12 ! reg 12 has 7 518 fsubs %f12, %f0, %f10 ! reg 10 has 6 519 fsubs %f10, %f0, %f8 ! reg 8 has 5 520 fsubs %f8, %f0, %f6 ! reg 6 has 4 521 fsubs %f6, %f0, %f4 ! reg 4 has 3 522 fsubs %f4, %f0, %f2 ! reg 2 has 2 523 524 fmuls %f0, %f1, %f20 ! reg 0 * reg 1 = reg 20 = 1 525 fmuls %f2, %f3, %f21 ! reg 2 * reg 3 = reg 21 = 2 526 fmuls %f4, %f5, %f22 ! reg 4 * reg 5 = reg 22 = 3 527 fmuls %f6, %f7, %f23 ! reg 6 * reg 7 = reg 23 = 4 528 fmuls %f8, %f9, %f24 ! reg 8 * reg 9 = reg 24 = 5 529 fmuls %f10, %f11, %f25 ! reg 10 * reg 11 = reg 25 = 6 530 fmuls %f12, %f13, %f26 ! reg 12 * reg 13 = reg 26 = 7 531 fmuls %f14, %f15, %f27 ! reg 14 * reg 15 = reg 27 = 8 532 fmuls %f16, %f17, %f28 ! reg 16 * reg 17 = reg 28 = 9 533 fmuls %f18, %f19, %f29 ! reg 18 * reg 19 = reg 29 = 10 534 535 fcmps %fcc0, %f0, %f20 536 fbne,a,pn %fcc0, done_t_mult_sp 537 st %f20, [%l2] ! Executed only when the conditional 538 ! branch is taken as annul bit is set. 539 ! This branch will be taken under 540 ! an error condition. 541 542 ! No errors. Move on to the next register 543 544 fcmps %fcc0, %f2, %f21 545 fbne,a,pn %fcc0, done_t_mult_sp 546 st %f21, [%l2] 547 548 549 fcmps %fcc0, %f4, %f22 550 fbne,a,pn %fcc0, done_t_mult_sp 551 st %f22, [%l2] 552 553 554 fcmps %fcc0, %f6, %f23 555 fbne,a,pn %fcc0, done_t_mult_sp 556 st %f23, [%l2] 557 558 559 fcmps %fcc0, %f8, %f24 560 fbne,a,pn %fcc0, done_t_mult_sp 561 st %f24, [%l2] 562 563 564 fcmps %fcc0, %f10, %f25 565 fbne,a,pn %fcc0, done_t_mult_sp 566 st %f25, [%l2] 567 568 569 fcmps %fcc0, %f12, %f26 570 fbne,a,pn %fcc0, done_t_mult_sp 571 st %f26, [%l2] 572 573 574 fcmps %fcc0, %f14, %f27 575 fbne,a,pn %fcc0, done_t_mult_sp 576 st %f27, [%l2] 577 578 579 fcmps %fcc0, %f16, %f28 580 fbne,a,pn %fcc0, done_t_mult_sp 581 st %f28, [%l2] 582 583 584 ! Though this is the last set of compare instructions 585 ! we cannot fall through as the store needs to be done 586 ! only when the registers are not equal. That is why 587 ! we need the unconditional branch with the annul bit set. 588 fcmps %fcc0, %f18, %f29 589 fbne,a,pn %fcc0, done_t_mult_sp 590 st %f29, [%l2] 591 592 593done_t_mult_sp: 594 ld [%l2], %i0 595 ret 596 restore 597SET_SIZE(timing_mult_sp) 598 599#endif 600 601/* 602 * ---------------------------------------------------------------- 603 * same thing for double precision 604 * ---------------------------------------------------------------- 605 */ 606 607#ifdef __lint 608 609uint64_t 610timing_add_dp() 611{ 612 return (0); 613} 614 615#else 616 617.section ".data" 618.align 8 619 620.Ltmadp: 621 .skip 8 622.Ltmadp1: 623 .skip 8 624.Ltmadp2: 625 .skip 8 626 627ENTRY_NP(timing_add_dp) 628 save %sp, -SA(MINFRAME), %sp ! save the registers, stacck 629 setn .Ltmadp,%l6, %l0 630 setn .Ltmadp1,%l6, %l1 631 setn .Ltmadp2,%l6, %l2 632 mov %g0, %l3 633 setn 0x3ff0000000000000,%l6, %l4 ! put value 1 634 setn 0x4024000000000000,%l6, %l5 ! put value 10 into local 5 635 stx %l5, [%l0] 636 stx %l4, [%l1] 637 stx %l3, [%l2] 638 ldd [%l0], %f30 ! register 30 has 10 639 fmovd %f30, %f2 ! reg 2 has 10 640 ldd [%l2], %f0 ! reg 0 has 0 641 ldd [%l1], %f4 ! reg 4 has 1 642 fsubd %f30, %f4, %f6 ! reg 6 has 9 643 fsubd %f6, %f4, %f10 ! reg 10 has 8 644 fsubd %f30, %f10, %f8 ! reg 8 has 2 645 fsubd %f10, %f4, %f14 ! reg 14 has 7 646 fsubd %f30, %f14, %f12 ! reg 12 has 3 647 fsubd %f14, %f4, %f18 ! reg 18 has 6 648 fsubd %f30, %f18, %f16 ! reg 16 has 4 649! 650 faddd %f0, %f2, %f20 ! reg 20 has 10 651 faddd %f4, %f6, %f22 ! reg 22 has 10 652 faddd %f8, %f10, %f24 ! reg 24 has 10 653 faddd %f12, %f14, %f26 ! reg 26 has 10 654 faddd %f16, %f18, %f28 ! reg 28 has 10 655! 656 fcmpd %fcc0, %f30, %f20 657 fbne,a,pn %fcc0, done_t_add_dp 658 std %f20, [%l2] 659 660 fcmpd %fcc0, %f30, %f22 661 fbne,a,pn %fcc0, done_t_add_dp 662 std %f22, [%l2] 663 664 fcmpd %fcc0, %f30, %f24 665 fbne,a,pn %fcc0, done_t_add_dp 666 std %f24, [%l2] 667 668 fcmpd %fcc0, %f30, %f26 669 fbne,a,pn %fcc0, done_t_add_dp 670 std %f26, [%l2] 671 672 ! Though this is the last set of compare instructions 673 ! we cannot fall through as the store needs to be done 674 ! only when the registers are not equal. That is why 675 ! we need the unconditional branch with the annul bit set. 676 fcmpd %fcc0, %f30, %f28 677 fbne,a %fcc0, done_t_add_dp 678 std %f28, [%l2] 679 680done_t_add_dp: 681 ldx [%l2], %i0 682 683 ret 684 restore 685SET_SIZE(timing_add_dp) 686 687#endif 688 689/* 690 * ------------------------------------------------------------------- 691 * Now for mult 692 * ------------------------------------------------------------------- 693 */ 694 695#ifdef __lint 696 697uint64_t 698timing_mult_dp() 699{ 700 return (0); 701} 702 703#else 704 705.section ".data" 706.align 8 707 708.Ltmmdp: 709 .skip 8 710.Ltmmdp1: 711 .skip 8 712.Ltmmdp2: 713 .skip 8 714 715ENTRY_NP(timing_mult_dp) 716 save %sp, -SA(MINFRAME), %sp ! save the registers, stacck 717 setn .Ltmmdp,%l6, %l0 718 setn .Ltmmdp1,%l6, %l1 719 setn .Ltmmdp2,%l6, %l2 720 mov %g0, %l3 721 setn 0x3ff0000000000000,%l6, %l4 ! put value 1 722 setn 0x4034000000000000,%l6, %l5 ! put value 20 into local 5 723 stx %l5, [%l0] 724 stx %l4, [%l1] 725 stx %l3, [%l2] 726 ldd [%l0], %f30 ! register 30 has 20 727 ldd [%l1], %f2 ! register 2 has 1 728 fmovd %f30, %f0 ! register 0 has 20 729 faddd %f2, %f2, %f10 ! register 10 has 2 730 fmovd %f10, %f16 ! register 16 has 2 731 faddd %f10, %f16, %f4 ! register 4 has 4 732 faddd %f4, %f2, %f6 ! register 6 has 5 733 fmovd %f6, %f12 ! reg. 12 has 5 734 fmovd %f4, %f14 ! reg 14 has 4 735 faddd %f12, %f6, %f18 ! reg 18 has 10 736 fmovd %f18, %f8 ! reg 8 has 10 737! 738! now everything is set 739! 740 fmuld %f0, %f2, %f20 ! reg 20 has 20 741 fmuld %f4, %f6, %f22 ! reg 22 has 20 742 fmuld %f8, %f10, %f24 ! reg 24 has 20 743 fmuld %f12, %f14, %f26 ! reg 26 has 20 744 fmuld %f16, %f18, %f28 ! reg 28 has 20 745! 746 fcmpd %fcc0, %f30, %f20 747 fbne,a,pn %fcc0, done_t_mult_dp 748 std %f20, [%l2] 749 750 fcmpd %fcc0, %f30, %f22 751 fbne,a,pn %fcc0, done_t_mult_dp 752 std %f22, [%l2] 753 754 fcmpd %fcc0, %f30, %f24 755 fbne,a,pn %fcc0, done_t_mult_dp 756 std %f24, [%l2] 757 758 fcmpd %fcc0, %f30, %f26 759 fbne,a,pn %fcc0, done_t_mult_dp 760 std %f26, [%l2] 761 762 ! Though this is the last set of compare instructions 763 ! we cannot fall through as the store needs to be done 764 ! only when the registers are not equal. That is why 765 ! we need the unconditional branch with the annul bit set. 766 fcmpd %fcc0, %f30, %f28 767 fbne,a %fcc0, done_t_mult_dp 768 std %f28, [%l2] 769 770done_t_mult_dp: 771 ldx [%l2], %i0 772 773 ret 774 restore 775SET_SIZE(timing_mult_dp) 776 777#endif 778 779/* 780 * -------------------------------------------------------------------------- 781 * The following routines are for testing the IEEE754 exception fields 782 * of the FSR (cexc, aexc) 783 * The input is : i0 = amsw 784 * i1 = bmsw or alsw (for double precision) 785 * i2 = bmsw (for dp) 786 * i3 = blsw (for dp) 787 * 788 * The output is i0 = value of FSR register 789 * ------------------------------------------------------------------------- 790 */ 791 792#ifdef __lint 793 794/*ARGSUSED*/ 795uint64_t 796wadd_sp(unsigned long arg1, unsigned long arg2) 797{ 798 return (0); 799} 800 801#else 802 803.section ".data" 804.align 8 805 806.Lwadds: 807 .word 0 808.Lwadds1: 809 .word 0 810.Lwadds2: 811 .xword 0 ! For the FSR contents 812 813ENTRY_NP(wadd_sp) 814 save %sp, -SA(MINFRAME), %sp 815 setn .Lwadds,%l6, %l0 816 setn .Lwadds1,%l6, %l1 817 setn .Lwadds2,%l6, %l2 818 819 st %i0, [%l0] ! get the first value 820 st %i1, [%l1] ! get the second value 821 ld [%l0], %f0 ! f0 has the first value 822 ld [%l1], %f2 ! f2 has the second value 823 824 fadds %f0, %f2, %f3 ! now do the instruction 825 stx %fsr, [%l2] ! get the fsr value 826 827 ldx [%l2], %i0 828 ret 829 restore 830SET_SIZE(wadd_sp) 831 832#endif 833 834/* 835 * ------------------------------------------------------------- 836 * same thing for add double precision 837 * ------------------------------------------------------------- 838 */ 839 840#ifdef __lint 841 842/*ARGSUSED*/ 843uint64_t 844wadd_dp(unsigned long arg1, unsigned long arg2, 845 unsigned long arg3, unsigned long arg4) 846{ 847 return (0); 848} 849 850#else 851 852.section ".data" 853.align 8 854 855.Ladddp: 856 .word 0 857.Ladddp1: 858 .word 0 859.Ladddp2: 860 .xword 0 ! For the FSR contents 861 862ENTRY_NP(wadd_dp) 863 save %sp, -SA(MINFRAME), %sp 864 setn .Ladddp,%l6, %l0 865 setn .Ladddp1,%l6, %l1 866 setn .Ladddp2,%l6, %l2 867 868 st %i0, [%l0] ! get the first value 869 st %i1, [%l1] ! get the lsw of first value 870 ld [%l0], %f0 871 ld [%l1], %f1 872 st %i2, [%l0] ! get the second value 873 st %i3, [%l1] ! get the lsw of second value 874 ld [%l0], %f2 875 ld [%l1], %f3 876 877 faddd %f0, %f2, %f4 ! now do the instruction 878 stx %fsr, [%l2] ! get the fsr value 879 880 ldx [%l2], %i0 881 ret 882 restore 883 884SET_SIZE(wadd_dp) 885 886#endif 887 888/* 889 * -------------------------------------------------------------- 890 * for divide single precision 891 * -------------------------------------------------------------- 892 */ 893 894#ifdef __lint 895 896/*ARGSUSED*/ 897uint64_t wdiv_sp(unsigned long arg1, unsigned long arg2) 898{ 899 return (0); 900} 901 902#else 903 904.section ".data" 905.align 8 906 907.Ldvsp: 908 .word 0 909.Ldvsp1: 910 .word 0 911.Ldvsp2: 912 .xword 0 ! For the FSR contents 913 914ENTRY_NP(wdiv_sp) 915 save %sp, -SA(MINFRAME), %sp 916 setn .Ldvsp,%l6, %l0 917 setn .Ldvsp1,%l6, %l1 918 setn .Ldvsp2,%l6, %l2 919 920 st %i0, [%l0] ! get the first value 921 st %i1, [%l1] ! get the second value 922 ld [%l0], %f0 ! f0 has the first value 923 ld [%l1], %f2 ! f2 has the second value 924 925 fdivs %f0, %f2, %f3 ! now do the instruction 926 stx %fsr, [%l2] ! get the fsr value 927 928 ldx [%l2], %i0 929 ret 930 restore 931 932SET_SIZE(wdiv_sp) 933 934#endif 935 936/* 937 * ---------------------------------------------------------------- 938 * for divide double precision 939 * ---------------------------------------------------------------- 940 */ 941 942#ifdef __lint 943 944/*ARGSUSED*/ 945uint64_t 946wdiv_dp(unsigned long arg1, unsigned long arg2, 947 unsigned long arg3, unsigned long arg4) 948{ 949 return (0); 950} 951 952#else 953 954 .section ".data" 955 .align 8 956 957.Ldvdp: 958 .word 0 959.Ldvdp1: 960 .word 0 961.Ldvdp2: 962 .xword 0 ! For the FSR contents 963 964ENTRY_NP(wdiv_dp) 965 save %sp, -SA(MINFRAME), %sp 966 setn .Ldvdp,%l6, %l0 967 setn .Ldvdp1,%l6, %l1 968 setn .Ldvdp2,%l6, %l2 969 970 st %i0, [%l0] ! get the first value 971 st %i1, [%l1] ! get the lsw of first value 972 ld [%l0], %f0 973 ld [%l1], %f1 974 st %i2, [%l0] ! get the second value 975 st %i3, [%l1] ! get the lsw of second value 976 ld [%l0], %f2 977 ld [%l1], %f3 978 979 fdivd %f0, %f2, %f4 ! now do the instruction 980 stx %fsr, [%l2] ! get the fsr value 981 982 ldx [%l2], %i0 983 ret 984 restore 985 986SET_SIZE(wdiv_dp) 987 988#endif 989 990/* 991 * ------------------------------------------------------------------------ 992 * for multiply single precision 993 * ------------------------------------------------------------------------ 994 */ 995 996#ifdef __lint 997 998/*ARGSUSED*/ 999uint64_t 1000wmult_sp(unsigned long arg1, unsigned long arg2) 1001{ 1002 return (0); 1003} 1004 1005#else 1006 1007.section ".data" 1008.align 8 1009 1010.Lmltsp: 1011 .word 0 1012.Lmltsp1: 1013 .word 0 1014.Lmltsp2: 1015 .xword 0 ! For the FSR contents 1016 1017ENTRY_NP(wmult_sp) 1018 save %sp, -SA(MINFRAME), %sp 1019 setn .Lmltsp,%l6, %l0 1020 setn .Lmltsp1,%l6, %l1 1021 setn .Lmltsp2,%l6, %l2 1022 1023 st %i0, [%l0] ! get the first value 1024 st %i1, [%l1] ! get the second value 1025 ld [%l0], %f0 ! f0 has the first value 1026 ld [%l1], %f2 ! f2 has the second value 1027 1028 fmuls %f0, %f2, %f3 ! now do the instruction 1029 stx %fsr, [%l2] ! get the fsr value 1030 1031 ldx [%l2], %i0 1032 ret 1033 restore 1034 1035SET_SIZE(wmult_sp) 1036 1037#endif 1038 1039/* 1040 * --------------------------------------------------------------------- 1041 * for multiply double precision 1042 * --------------------------------------------------------------------- 1043 */ 1044 1045#ifdef __lint 1046 1047/*ARGSUSED*/ 1048uint64_t 1049wmult_dp(unsigned long arg1, unsigned long arg2, 1050 unsigned long arg3, unsigned long arg4) 1051{ 1052 return (0); 1053} 1054 1055#else 1056 1057.section ".data" 1058.align 8 1059 1060.Lmltdp: 1061 .word 0 1062.Lmltdp1: 1063 .word 0 1064.Lmltdp2: 1065 .xword 0 ! For the FSR contents 1066 1067ENTRY_NP(wmult_dp) 1068 save %sp, -SA(MINFRAME), %sp 1069 setn .Lmltdp,%l6, %l0 1070 setn .Lmltdp1,%l6, %l1 1071 setn .Lmltdp2,%l6, %l2 1072 1073 st %i0, [%l0] ! get the first value 1074 st %i1, [%l1] ! get the lsw of first value 1075 ld [%l0], %f0 1076 ld [%l1], %f1 1077 st %i2, [%l0] ! get the second value 1078 st %i3, [%l1] ! get the lsw of second value 1079 ld [%l0], %f2 1080 ld [%l1], %f3 1081 1082 fmuld %f0, %f2, %f4 ! now do the instruction 1083 stx %fsr, [%l2] ! get the fsr value 1084 1085 ldx [%l2], %i0 1086 ret 1087 restore 1088 1089SET_SIZE(wmult_dp) 1090 1091#endif 1092 1093/* 1094 * ----------------------------------------------------------------- 1095 * for square-root single precision 1096 * ----------------------------------------------------------------- 1097 */ 1098 1099#ifdef __lint 1100 1101/*ARGSUSED*/ 1102uint64_t 1103wsqrt_sp(unsigned long arg1) 1104{ 1105 return (0); 1106} 1107 1108#else 1109 1110.section ".data" 1111.align 4 1112.Lsqsp_opr: 1113 .word 0 1114 1115 .align 8 1116.Lsqsp_fsr: 1117 .xword 0 ! For the FSR contents 1118 1119ENTRY_NP(wsqrt_sp) 1120 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1121 setn .Lsqsp_opr,%l6,%l0 ! .. get the address of temp2 1122 setn .Lsqsp_fsr,%l6,%l2 ! .. and temp 1123 1124 st %i0, [%l0] ! .. get the callers value 1125 ld [%l0], %f0 ! .. into the float register 1126 1127 fsqrts %f0, %f2 ! .... have the fpu perform the operation 1128 stx %fsr, [%l2] ! get the fsr value 1129 1130 ldx [%l2], %i0 1131 ret 1132 restore 1133 1134SET_SIZE(wsqrt_sp) 1135 1136#endif 1137 1138/* 1139 * --------------------------------------------------------------------- 1140 * for square-root double precision 1141 * --------------------------------------------------------------------- 1142 */ 1143 1144#ifdef __lint 1145 1146/*ARGSUSED*/ 1147uint64_t 1148wsqrt_dp(uint64_t arg1) 1149{ 1150 return (0); 1151} 1152 1153#else 1154 1155.section ".data" 1156.align 8 1157.Lsqdp_opr: 1158 .xword 0 1159.Lsqdp_fsr: 1160 .xword 0 ! For the FSR contents 1161 1162ENTRY_NP(wsqrt_dp) 1163 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1164 setn .Lsqdp_opr,%l6,%l0 ! .. get the address of temp2 1165 setn .Lsqdp_fsr,%l6,%l2 ! .. and temp 1166 1167 stx %i0, [%l0] ! .. get the callers value 1168 ldd [%l0], %f0 ! .. into a float register 1169 1170 fsqrtd %f0, %f2 ! .... have the fpu perform the operation 1171 stx %fsr, [%l2] ! get the fsr value 1172 1173 ldx [%l2], %i0 1174 ret 1175 restore 1176 1177SET_SIZE(wsqrt_dp) 1178 1179#endif 1180 1181/* 1182 * --------------------------------------------------------------------- 1183 * Chaining test. 1184 * --------------------------------------------------------------------- 1185 */ 1186 1187#ifdef __lint 1188 1189/*ARGSUSED*/ 1190unsigned long 1191chain_sp(int arg1) 1192{ 1193 return (0); 1194} 1195 1196#else 1197 1198.section ".data" 1199.align 8 1200 1201.Lchsp: 1202 .word 0 1203.Lchsp1: 1204 .word 0 1205 1206ENTRY_NP(chain_sp) 1207 save %sp, -SA(MINFRAME), %sp 1208 setn .Lchsp,%l6, %l0 1209 setn .Lchsp1,%l6, %l1 1210 st %i0, [%l0] ! store the value 1211 ld [%l0], %f0 1212 fitos %f0, %f2 ! convert integer into single 1213 fmovs %f2, %f0 ! f0 has the same value x 1214 fadds %f0, %f2, %f4 ! f4 will have 2x 1215 fsubs %f4, %f0, %f6 ! f6 will have x 1216 fmuls %f6, %f4, %f8 ! f8 will have (2x * x) 1217 fdivs %f8, %f4, %f10 ! f10 will have (2x * x) / 2x = x 1218 fstoi %f10, %f12 1219 1220 st %f12, [%l1] 1221 ld [%l1], %i0 1222 1223 ret 1224 restore 1225SET_SIZE(chain_sp) 1226 1227#endif 1228 1229#ifdef __lint 1230 1231/*ARGSUSED*/ 1232unsigned long 1233chain_dp(int arg1) 1234{ 1235 return (0); 1236} 1237 1238#else 1239 1240.section ".data" 1241.align 8 1242 1243.Lchdp: 1244 .word 0 1245.Lchdp1: 1246 .word 0 1247 1248ENTRY_NP(chain_dp) 1249 save %sp, -SA(MINFRAME), %sp 1250 setn .Lchdp,%l6, %l0 1251 setn .Lchdp1,%l6, %l1 1252 st %i0, [%l0] ! store the value 1253 ld [%l0], %f0 1254 fitod %f0, %f2 ! convert integer into double 1255 fmovs %f2, %f0 ! f0 has the same value x 1256 faddd %f0, %f2, %f4 ! f4 will have 2x 1257 fsubd %f4, %f0, %f6 ! f6 will have x 1258 fmuld %f6, %f4, %f8 ! f8 will have (2x * x) 1259 fdivd %f8, %f4, %f10 ! f10 will have (2x * x) / 2x = x 1260 fdtoi %f10, %f12 1261 1262 st %f12, [%l1] 1263 ld [%l1], %i0 1264 1265 ret 1266 restore 1267SET_SIZE(chain_dp) 1268 1269#endif 1270 1271/* 1272 * -------------------------------------------------------------------------- 1273 * Name: Initialize all SP Registers 1274 * Function: Loads the callers value into all SP floating point registers. 1275 * Calling: in0 = Value 1276 * Returns: All float register = Value 1277 * Convention: init_regs(val); 1278 * Method: Copys the user value into each fp reg in sequence. 1279 * -------------------------------------------------------------------------- 1280 */ 1281 1282#ifdef __lint 1283 1284/*ARGSUSED*/ 1285void 1286init_regs(uint32_t arg1) 1287{ 1288} 1289 1290#else 1291 1292.section ".data" 1293.align 8 1294 1295.Lclrg: 1296 .skip 8 1297 1298ENTRY_NP(init_regs) 1299 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1300 setn .Lclrg,%l6,%l0 ! load the address of temp2 in local0 1301 st %i0, [%l0] ! load the value in temp2 via local0 1302 ld [%l0], %f0 ! .. load the value 1303 ld [%l0], %f1 ! .. load the value 1304 ld [%l0], %f2 ! .. load the value 1305 ld [%l0], %f3 ! .. load the value 1306 ld [%l0], %f4 ! .. load the value 1307 ld [%l0], %f5 ! .. load the value 1308 ld [%l0], %f6 ! .. load the value 1309 ld [%l0], %f7 ! .. load the value 1310 ld [%l0], %f8 ! .. load the value 1311 ld [%l0], %f9 ! .. load the value 1312 ld [%l0], %f10 ! .. load the value 1313 ld [%l0], %f11 ! .. load the value 1314 ld [%l0], %f12 ! .. load the value 1315 ld [%l0], %f13 ! .. load the value 1316 ld [%l0], %f14 ! .. load the value 1317 ld [%l0], %f15 ! .. load the value 1318 ld [%l0], %f16 ! .. load the value 1319 ld [%l0], %f17 ! .. load the value 1320 ld [%l0], %f18 ! .. load the value 1321 ld [%l0], %f19 ! .. load the value 1322 ld [%l0], %f20 ! .. load the value 1323 ld [%l0], %f21 ! .. load the value 1324 ld [%l0], %f22 ! .. load the value 1325 ld [%l0], %f23 ! .. load the value 1326 ld [%l0], %f24 ! .. load the value 1327 ld [%l0], %f25 ! .. load the value 1328 ld [%l0], %f26 ! .. load the value 1329 ld [%l0], %f27 ! .. load the value 1330 ld [%l0], %f28 ! .. load the value 1331 ld [%l0], %f29 ! .. load the value 1332 ld [%l0], %f30 ! .. load the value 1333 ld [%l0], %f31 ! .. load the value 1334 ret 1335 restore 1336SET_SIZE(init_regs) 1337 1338#endif 1339 1340/* 1341 * Name: Initialize all double precision Registers 1342 * Function: Loads the callers value into all floating point registers. 1343 * Calling: in0 = Value 1344 * Returns: All float register = Value 1345 * Convention: init_regs_dp(val); 1346 * Method: Copys the user value into each fp reg in sequence. 1347 * -------------------------------------------------------------------------- 1348 */ 1349 1350#ifdef __lint 1351 1352/*ARGSUSED*/ 1353void 1354init_regs_dp(uint64_t arg1) 1355{ 1356} 1357 1358#else 1359 1360.section ".data" 1361.align 8 1362 1363.Lclrg_dp: 1364 .skip 16 1365 1366ENTRY_NP(init_regs_dp) 1367 save %sp, -SA(MINFRAME), %sp 1368 ! save the registers, stack 1369 setx .Lclrg_dp,%l6,%l0 ! load the address of temp2 in local0 1370 stx %i0, [%l0] ! load the value in temp2 via local0 1371 ldd [%l0], %f0 ! .. load the value 1372 ldd [%l0], %f2 ! .. load the value 1373 ldd [%l0], %f4 ! .. load the value 1374 ldd [%l0], %f6 ! .. load the value 1375 ldd [%l0], %f8 ! .. load the value 1376 ldd [%l0], %f10 ! .. load the value 1377 ldd [%l0], %f12 ! .. load the value 1378 ldd [%l0], %f14 ! .. load the value 1379 ldd [%l0], %f16 ! .. load the value 1380 ldd [%l0], %f18 ! .. load the value 1381 ldd [%l0], %f20 ! .. load the value 1382 ldd [%l0], %f22 ! .. load the value 1383 ldd [%l0], %f24 ! .. load the value 1384 ldd [%l0], %f26 ! .. load the value 1385 ldd [%l0], %f28 ! .. load the value 1386 ldd [%l0], %f30 ! .. load the value 1387 ldd [%l0], %f32 ! .. load the value 1388 ldd [%l0], %f34 ! .. load the value 1389 ldd [%l0], %f36 ! .. load the value 1390 ldd [%l0], %f38 ! .. load the value 1391 ldd [%l0], %f40 ! .. load the value 1392 ldd [%l0], %f42 ! .. load the value 1393 ldd [%l0], %f44 ! .. load the value 1394 ldd [%l0], %f46 ! .. load the value 1395 ldd [%l0], %f48 ! .. load the value 1396 ldd [%l0], %f50 ! .. load the value 1397 ldd [%l0], %f52 ! .. load the value 1398 ldd [%l0], %f54 ! .. load the value 1399 ldd [%l0], %f56 ! .. load the value 1400 ldd [%l0], %f58 ! .. load the value 1401 ldd [%l0], %f60 ! .. load the value 1402 ldd [%l0], %f62 ! .. load the value 1403 ret 1404 restore 1405SET_SIZE(init_regs_dp) 1406 1407#endif 1408 1409/* 1410 * Name: 1411 * Function: 1412 * Calling: 1413 * Returns: 1414 * Convention: 1415 * -------------------------------------------------------------------------- 1416 */ 1417 1418#ifdef __lint 1419 1420/*ARGSUSED*/ 1421uint32_t 1422register_test(int arg1, uint32_t arg2) 1423{ 1424 return (0); 1425} 1426 1427#else 1428 1429.section ".data" 1430.align 4 1431 1432.Lrgtst1: 1433 .skip 4 1434.Lrgtst2: 1435 .skip 4 1436 1437ENTRY_NP(register_test) 1438 save %sp, -SA(MINFRAME), %sp 1439 1440 setn .Lrgtst1,%l6,%l1 1441 setn .Lrgtst2,%l6,%l2 1442 1443 1444 setn regTable, %l6, %o0 1445 mulx %i0, 12, %o1 ! Table entries are 12 bytes each. 1446 1447 ! Jump to the appropriate set of instructions 1448 jmp %o0+%o1 1449 st %i1, [%l1] ! save the pattern to be written 1450 1451 1452! If the number of instructions in this macro are changed, 1453! please ensure that the second operand for the mulx above 1454! is also updated. We can calculate this during run-time but 1455! that will mean extra instructions and time. 1456#define TEST_REG(reg_num) \ 1457 ld [%l1], %f/**/reg_num; \ 1458 ba %ncc, reg_done; \ 1459 st %f/**/reg_num, [%l2] 1460 1461regTable : 1462 1463 TEST_REG(0) 1464 TEST_REG(1) 1465 TEST_REG(2) 1466 TEST_REG(3) 1467 TEST_REG(4) 1468 TEST_REG(5) 1469 TEST_REG(6) 1470 TEST_REG(7) 1471 TEST_REG(8) 1472 TEST_REG(9) 1473 TEST_REG(10) 1474 TEST_REG(11) 1475 TEST_REG(12) 1476 TEST_REG(13) 1477 TEST_REG(14) 1478 TEST_REG(15) 1479 TEST_REG(16) 1480 TEST_REG(17) 1481 TEST_REG(18) 1482 TEST_REG(19) 1483 TEST_REG(20) 1484 TEST_REG(21) 1485 TEST_REG(22) 1486 TEST_REG(23) 1487 TEST_REG(24) 1488 TEST_REG(25) 1489 TEST_REG(26) 1490 TEST_REG(27) 1491 TEST_REG(28) 1492 TEST_REG(29) 1493 TEST_REG(30) 1494 1495 ! No need for a branch here as this the last entry in 1496 ! the table and the label is will be reached by falling 1497 ! through. 1498 ld [%l1], %f31 1499 st %f31, [%l2] 1500 1501reg_done: 1502 ld [%l2], %i0 1503 1504 ret 1505 restore 1506SET_SIZE(register_test) 1507 1508#endif 1509 1510/* 1511 * Name: 1512 * Function: 1513 * Calling: 1514 * Returns: 1515 * Convention: 1516 * -------------------------------------------------------------------------- 1517 */ 1518 1519#ifdef __lint 1520 1521/*ARGSUSED*/ 1522uint64_t 1523register_test_dp(int arg1, uint64_t arg2) 1524{ 1525 return (0); 1526} 1527 1528#else 1529 1530.section ".data" 1531.align 8 1532 1533.Lrgtst1_dp: 1534 .skip 8 1535.Lrgtst2_dp: 1536 .skip 8 1537 1538ENTRY_NP(register_test_dp) 1539 save %sp, -SA(MINFRAME), %sp 1540 1541 setx .Lrgtst1_dp,%l6,%l1 1542 setx .Lrgtst2_dp,%l6,%l2 1543 1544 setn regTable_dp, %l6, %o0 1545 mulx %i0, 6, %o1 ! Registers are 64-bit and hence the 1546 ! register numbers given will be even. 1547 ! Each table entry is 12 bytes. 1548 ! Multiplying the even register number 1549 ! by 6 will give the correct offset. 1550 1551 1552 ! Jump to the appropriate set of instructions 1553 jmp %o0+%o1 1554 stx %i1, [%l1] !save the pattern to be written 1555 1556! If the number of instructions in this macro are changed, 1557! please ensure that the second operand for the mulx above 1558! is also updated. We can calculate this during run-time but 1559! that will mean extra instructions and time. 1560#define TEST_REG_DP(reg_num) \ 1561 ldd [%l1], %f/**/reg_num; \ 1562 ba %ncc, reg_done_dp; \ 1563 std %f/**/reg_num, [%l2] 1564 1565regTable_dp : 1566 1567 TEST_REG_DP(0) 1568 TEST_REG_DP(2) 1569 TEST_REG_DP(4) 1570 TEST_REG_DP(6) 1571 TEST_REG_DP(8) 1572 TEST_REG_DP(10) 1573 TEST_REG_DP(12) 1574 TEST_REG_DP(14) 1575 TEST_REG_DP(16) 1576 TEST_REG_DP(18) 1577 TEST_REG_DP(20) 1578 TEST_REG_DP(22) 1579 TEST_REG_DP(24) 1580 TEST_REG_DP(26) 1581 TEST_REG_DP(28) 1582 TEST_REG_DP(30) 1583 TEST_REG_DP(32) 1584 TEST_REG_DP(34) 1585 TEST_REG_DP(36) 1586 TEST_REG_DP(38) 1587 TEST_REG_DP(40) 1588 TEST_REG_DP(42) 1589 TEST_REG_DP(44) 1590 TEST_REG_DP(46) 1591 TEST_REG_DP(48) 1592 TEST_REG_DP(50) 1593 TEST_REG_DP(52) 1594 TEST_REG_DP(54) 1595 TEST_REG_DP(56) 1596 TEST_REG_DP(58) 1597 TEST_REG_DP(60) 1598 1599 ! No need for a branch here as this the last entry in 1600 ! the table and the label is will be reached by falling 1601 ! through. 1602 ldd [%l1], %f62 1603 std %f62, [%l2] 1604 1605reg_done_dp: 1606 ldx [%l2], %i0 1607 1608 ret 1609 restore 1610SET_SIZE(register_test_dp) 1611 1612#endif 1613 1614/* 1615 * ------------------------------------------------------------------------ 1616 * Name: Move Registers 1617 * Function: Move a value thru the float registers 1618 * Calling: in0 = value 1619 * Returns: in0 = result 1620 * Convention: if (result != move_regs(value)) 1621 * error(result-value); 1622 * -------------------------------------------------------------------------- 1623 */ 1624 1625#ifdef __lint 1626 1627/*ARGSUSED*/ 1628unsigned long 1629move_regs(unsigned long arg1) 1630{ 1631 return (0); 1632} 1633 1634#else 1635 1636.section ".data" 1637.align 4 1638 1639.Lmvrg: 1640 .skip 4 1641.Lmvrg1: 1642 .skip 4 1643 1644ENTRY_NP(move_regs) 1645 save %sp, -SA(MINFRAME), %sp ! save the registers, stack 1646 setn .Lmvrg1,%l6,%l0 ! get the address to temp2 1647 setn .Lmvrg,%l6,%l1 ! .. and temp 1648 st %i0, [%l0] ! get the callers value 1649 ld [%l0], %f0 ! .. into a float register 1650 fmovs %f0, %f1 ! copy from 1 register to the next 1651 fmovs %f1, %f2 ! .. to the next 1652 fmovs %f2, %f3 ! .. to the next 1653 fmovs %f3, %f4 ! .. to the next 1654 fmovs %f4, %f5 ! .. to the next 1655 fmovs %f5, %f6 ! .. to the next 1656 fmovs %f6, %f7 ! .. to the next 1657 fmovs %f7, %f8 ! .. to the next 1658 fmovs %f8, %f9 ! .. to the next 1659 fmovs %f9, %f10 ! .. to the next 1660 fmovs %f10, %f11 ! .. to the next 1661 fmovs %f11, %f12 ! .. to the next 1662 fmovs %f12, %f13 ! .. to the next 1663 fmovs %f13, %f14 ! .. to the next 1664 fmovs %f14, %f15 ! .. to the next 1665 fmovs %f15, %f16 ! .. to the next 1666 fmovs %f16, %f17 ! .. to the next 1667 fmovs %f17, %f18 ! .. to the next 1668 fmovs %f18, %f19 ! .. to the next 1669 fmovs %f19, %f20 ! .. to the next 1670 fmovs %f20, %f21 ! .. to the next 1671 fmovs %f21, %f22 ! .. to the next 1672 fmovs %f22, %f23 ! .. to the next 1673 fmovs %f23, %f24 ! .. to the next 1674 fmovs %f24, %f25 ! .. to the next 1675 fmovs %f25, %f26 ! .. to the next 1676 fmovs %f26, %f27 ! .. to the next 1677 fmovs %f27, %f28 ! .. to the next 1678 fmovs %f28, %f29 ! .. to the next 1679 fmovs %f29, %f30 ! .. to the next 1680 fmovs %f30, %f31 ! .. to the next 1681 st %f31, [%l1] ! .... save the result 1682 ld [%l1], %i0 ! .. and return it to the caller 1683 ret 1684 restore 1685SET_SIZE(move_regs) 1686 1687#endif 1688 1689/* 1690 * ------------------------------------------------------------------------ 1691 * Name: 1692 * Function: 1693 * Calling: 1694 * Returns: 1695 * Convention: 1696 * -------------------------------------------------------------------------- 1697 * 1698 * The following routine checks the branching is done accordingly 1699 * to the ficc bits. 1700 * input %i0 = 0 = branch unordered 1701 * 1 = branch greater 1702 * 2 = branch unordered or greater 1703 * 3 = branch less 1704 * 4 = branch unordered or less 1705 * 5 = branch less or greater 1706 * 6 = branch not equal 1707 * 7 = branch equal 1708 * 8 = branch unordered or equal 1709 * . 9 = branch greater or equal 1710 * 10 = branch branch unordered or greater or equal 1711 * 11 = branch less or equal 1712 * 12 = branch unordered or or less or equal 1713 * 13 = branch ordered 1714 * 14 = branch always 1715 * 15 = branch never 1716 * 1717 * ouput : %i0 = 0 = good 1718 * = 1 = error 1719 */ 1720 1721#ifdef __lint 1722 1723/*ARGSUSED*/ 1724unsigned long 1725branches(unsigned long arg1, unsigned long arg2, unsigned long arg3) 1726{ 1727 return (0); 1728} 1729 1730#else 1731 1732.section ".data" 1733.align 8 1734 1735.Lbr: 1736 .skip 8 1737.Lbr1: 1738 .skip 8 1739 1740ENTRY_NP(branches) 1741 save %sp, -SA(MINFRAME), %sp ! save the registers, stacck 1742 setn .Lbr1,%l6,%l1 1743 setn .Lbr,%l6,%l2 1744 st %i1, [%l1] 1745 st %i2, [%l2] 1746 ld [%l1], %f0 1747 ld [%l2], %f2 1748 1749 setn brn_0, %l6, %o0 1750 mulx %i0, 12, %o1 1751 1752 1753 jmp %o0+%o1 1754 fcmps %fcc0, %f0, %f2 ! compare the values to get ficc 1755! 1756! branch unordered 1757brn_0: 1758 fbu,a %fcc0, br_good 1759 nop 1760 ba,a %ncc, br_error 1761 1762! branch greater 1763brn_1: 1764 fbg,a %fcc0, br_good 1765 nop 1766 ba,a %ncc, br_error 1767 1768! branch unordered or greater 1769brn_2: 1770 fbug,a %fcc0, br_good 1771 nop 1772 ba,a %ncc, br_error 1773 1774! branch less 1775brn_3: 1776 fbl,a %fcc0, br_good 1777 nop 1778 ba,a %ncc, br_error 1779 1780! branch unorderd or less 1781brn_4: 1782 fbul,a %fcc0, br_good 1783 nop 1784 ba,a %ncc, br_error 1785 1786! branch less or greater 1787brn_5: 1788 fblg,a %fcc0, br_good 1789 nop 1790 ba,a %ncc, br_error 1791 1792! branch not equal 1793brn_6: 1794 fbne,a %fcc0, br_good 1795 nop 1796 ba,a %ncc, br_error 1797 1798! branch equal 1799brn_7: 1800 fbe,a %fcc0, br_good 1801 nop 1802 ba,a %ncc, br_error 1803 1804! branch unordered or equal 1805brn_8: 1806 fbue,a %fcc0, br_good 1807 nop 1808 ba,a %ncc, br_error 1809 1810! branch greater or equal 1811brn_9: 1812 fbge,a %fcc0, br_good 1813 nop 1814 ba,a %ncc, br_error 1815 1816! branch unordered or greater or equal 1817brn_10: 1818 fbuge,a %fcc0, br_good 1819 nop 1820 ba,a %ncc, br_error 1821 1822! branch less or equal 1823brn_11: 1824 fble,a %fcc0, br_good 1825 nop 1826 ba,a %ncc, br_error 1827 1828! branch unordered or less or equal 1829brn_12: 1830 fbule,a %fcc0, br_good 1831 nop 1832 ba,a %ncc, br_error 1833 1834! branch ordered 1835brn_13: 1836 fbo,a %fcc0, br_good 1837 nop 1838 ba,a %ncc, br_error 1839 1840! branch always 1841brn_14: 1842 fba,a %fcc0, br_good 1843 nop 1844 ba,a %ncc, br_error 1845 1846! branch never 1847brn_15: 1848 fbn,a %fcc0, br_error 1849 nop 1850 1851br_good: 1852 mov %g0, %i0 ! Branch worked as expected 1853 1854 ret 1855 restore 1856 1857br_error: 1858 mov 0xff, %i0 ! set the flag that it is error 1859 1860 ret 1861 restore 1862SET_SIZE(branches) 1863 1864#endif 1865 1866/* 1867 * void read_fpreg(pf, n) 1868 * FPU_REGS_TYPE *pf; Old freg value. 1869 * unsigned n; Want to read register n. 1870 * 1871 * { 1872 * *pf = %f[n]; 1873 * } 1874 */ 1875 1876 1877#ifdef __lint 1878 1879/*ARGSUSED*/ 1880void 1881read_fpreg(unsigned int *arg1, int arg2) 1882{ 1883} 1884 1885#else 1886 1887ENTRY_NP(read_fpreg) 1888 save %sp, -SA(MINFRAME), %sp 1889 mulx %i1, 12, %i1 ! Table entries are 12 bytes each. 1890 setn stable, %l1, %g1 ! g1 gets base of table. 1891 jmp %g1 + %i1 ! Jump into table 1892 nop ! Can't follow CTI by CTI. 1893 1894#define STOREFP(n) st %f/**/n, [%i0]; ret; restore 1895 1896stable: 1897 STOREFP(0) 1898 STOREFP(1) 1899 STOREFP(2) 1900 STOREFP(3) 1901 STOREFP(4) 1902 STOREFP(5) 1903 STOREFP(6) 1904 STOREFP(7) 1905 STOREFP(8) 1906 STOREFP(9) 1907 STOREFP(10) 1908 STOREFP(11) 1909 STOREFP(12) 1910 STOREFP(13) 1911 STOREFP(14) 1912 STOREFP(15) 1913 STOREFP(16) 1914 STOREFP(17) 1915 STOREFP(18) 1916 STOREFP(19) 1917 STOREFP(20) 1918 STOREFP(21) 1919 STOREFP(22) 1920 STOREFP(23) 1921 STOREFP(24) 1922 STOREFP(25) 1923 STOREFP(26) 1924 STOREFP(27) 1925 STOREFP(28) 1926 STOREFP(29) 1927 STOREFP(30) 1928 STOREFP(31) 1929SET_SIZE(read_fpreg) 1930 1931#endif 1932 1933#ifdef __lint 1934 1935/*ARGSUSED*/ 1936void 1937read_fpreg_dp(unsigned long *arg1, int arg2) 1938{ 1939 return; 1940} 1941 1942#else 1943 1944ENTRY_NP(read_fpreg_dp) 1945 save %sp, -SA(MINFRAME), %sp 1946 mulx %i1, 6, %i1 ! Table entries are 12 bytes each. 1947 ! But o1 will have even numbered 1948 ! index 1949 setn stable_dp, %l0, %g1 ! g1 gets base of table. 1950 jmp %g1 + %i1 ! Jump into table 1951 nop ! Can't follow CTI by CTI. 1952 1953#define STOREFP_DP(n) std %f/**/n, [%i0]; ret; restore 1954 1955stable_dp: 1956 STOREFP_DP(0) 1957 STOREFP_DP(2) 1958 STOREFP_DP(4) 1959 STOREFP_DP(6) 1960 STOREFP_DP(8) 1961 STOREFP_DP(10) 1962 STOREFP_DP(12) 1963 STOREFP_DP(14) 1964 STOREFP_DP(16) 1965 STOREFP_DP(18) 1966 STOREFP_DP(20) 1967 STOREFP_DP(22) 1968 STOREFP_DP(24) 1969 STOREFP_DP(26) 1970 STOREFP_DP(28) 1971 STOREFP_DP(30) 1972 STOREFP_DP(32) 1973 STOREFP_DP(34) 1974 STOREFP_DP(36) 1975 STOREFP_DP(38) 1976 STOREFP_DP(40) 1977 STOREFP_DP(42) 1978 STOREFP_DP(44) 1979 STOREFP_DP(46) 1980 STOREFP_DP(48) 1981 STOREFP_DP(50) 1982 STOREFP_DP(52) 1983 STOREFP_DP(54) 1984 STOREFP_DP(56) 1985 STOREFP_DP(58) 1986 STOREFP_DP(60) 1987 STOREFP_DP(62) 1988 1989SET_SIZE(read_fpreg_dp) 1990 1991#endif 1992 1993/* 1994 * void 1995 * write_fpreg(pf, n) 1996 * FPU_REGS_TYPE *pf; New freg value. 1997 * unsigned n; Want to read register n. 1998 * 1999 * { 2000 * %f[n] = *pf; 2001 * } 2002 */ 2003 2004#ifdef __lint 2005 2006#else 2007 2008ENTRY_NP(write_fpreg) 2009 sll %o1, 3, %o1 ! Table entries are 8 bytes each. 2010 setn ltable, %l0, %g1 ! g1 gets base of table. 2011 jmp %g1 + %o1 ! Jump into table 2012 nop ! Can't follow CTI by CTI. 2013 2014 2015#define LOADFP(n) jmp %o7+8 ; ld [%o0],%f/**/n 2016 2017ltable: 2018 LOADFP(0) 2019 LOADFP(1) 2020 LOADFP(2) 2021 LOADFP(3) 2022 LOADFP(4) 2023 LOADFP(5) 2024 LOADFP(6) 2025 LOADFP(7) 2026 LOADFP(8) 2027 LOADFP(9) 2028 LOADFP(10) 2029 LOADFP(11) 2030 LOADFP(12) 2031 LOADFP(13) 2032 LOADFP(14) 2033 LOADFP(15) 2034 LOADFP(16) 2035 LOADFP(17) 2036 LOADFP(18) 2037 LOADFP(19) 2038 LOADFP(20) 2039 LOADFP(21) 2040 LOADFP(22) 2041 LOADFP(23) 2042 LOADFP(24) 2043 LOADFP(25) 2044 LOADFP(26) 2045 LOADFP(27) 2046 LOADFP(28) 2047 LOADFP(29) 2048 LOADFP(30) 2049 LOADFP(31) 2050SET_SIZE(write_fpreg) 2051 2052#endif 2053