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