1 /* 2 Copyright (C) 1996-1997 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 // 21 // r_drawa.s 22 // x86 assembly-language edge clipping and emission code 23 // 24 25 #include "asm_i386.h" 26 #include "quakeasm.h" 27 #include "asm_draw.h" 28 #include "d_ifacea.h" 29 30 #if id386 31 32 // !!! if these are changed, they must be changed in r_draw.c too !!! 33 #define FULLY_CLIPPED_CACHED 0x80000000 34 #define FRAMECOUNT_MASK 0x7FFFFFFF 35 36 .data 37 38 Ld0: .single 0.0 39 Ld1: .single 0.0 40 Lstack: .long 0 41 Lfp_near_clip: .single NEAR_CLIP 42 Lceilv0: .long 0 43 Lv: .long 0 44 Lu0: .long 0 45 Lv0: .long 0 46 Lzi0: .long 0 47 48 .text 49 50 //---------------------------------------------------------------------- 51 // edge clipping code 52 //---------------------------------------------------------------------- 53 54 #define pv0 4+12 55 #define pv1 8+12 56 #define clip 12+12 57 58 .align 4 59 .globl C(R_ClipEdge) 60 C(R_ClipEdge): 61 pushl %esi // preserve register variables 62 pushl %edi 63 pushl %ebx 64 movl %esp,Lstack // for clearing the stack later 65 66 // float d0, d1, f; 67 // mvertex_t clipvert; 68 69 movl clip(%esp),%ebx 70 movl pv0(%esp),%esi 71 movl pv1(%esp),%edx 72 73 // if (clip) 74 // { 75 testl %ebx,%ebx 76 jz Lemit 77 78 // do 79 // { 80 81 Lcliploop: 82 83 // d0 = DotProduct (pv0->position, clip->normal) - clip->dist; 84 // d1 = DotProduct (pv1->position, clip->normal) - clip->dist; 85 flds mv_position+0(%esi) 86 fmuls cp_normal+0(%ebx) 87 flds mv_position+4(%esi) 88 fmuls cp_normal+4(%ebx) 89 flds mv_position+8(%esi) 90 fmuls cp_normal+8(%ebx) 91 fxch %st(1) 92 faddp %st(0),%st(2) // d0mul2 | d0add0 93 94 flds mv_position+0(%edx) 95 fmuls cp_normal+0(%ebx) 96 flds mv_position+4(%edx) 97 fmuls cp_normal+4(%ebx) 98 flds mv_position+8(%edx) 99 fmuls cp_normal+8(%ebx) 100 fxch %st(1) 101 faddp %st(0),%st(2) // d1mul2 | d1add0 | d0mul2 | d0add0 102 fxch %st(3) // d0add0 | d1add0 | d0mul2 | d1mul2 103 104 faddp %st(0),%st(2) // d1add0 | dot0 | d1mul2 105 faddp %st(0),%st(2) // dot0 | dot1 106 107 fsubs cp_dist(%ebx) // d0 | dot1 108 fxch %st(1) // dot1 | d0 109 fsubs cp_dist(%ebx) // d1 | d0 110 fxch %st(1) 111 fstps Ld0 112 fstps Ld1 113 114 // if (d0 >= 0) 115 // { 116 movl Ld0,%eax 117 movl Ld1,%ecx 118 orl %eax,%ecx 119 js Lp2 120 121 // both points are unclipped 122 123 Lcontinue: 124 125 // 126 // R_ClipEdge (&clipvert, pv1, clip->next); 127 // return; 128 // } 129 // } while ((clip = clip->next) != NULL); 130 movl cp_next(%ebx),%ebx 131 testl %ebx,%ebx 132 jnz Lcliploop 133 134 // } 135 136 //// add the edge 137 // R_EmitEdge (pv0, pv1); 138 Lemit: 139 140 // 141 // set integer rounding to ceil mode, set to single precision 142 // 143 // FIXME: do away with by manually extracting integers from floats? 144 // FIXME: set less often 145 fldcw ceil_cw 146 147 // edge_t *edge, *pcheck; 148 // int u_check; 149 // float u, u_step; 150 // vec3_t local, transformed; 151 // float *world; 152 // int v, v2, ceilv0; 153 // float scale, lzi0, u0, v0; 154 // int side; 155 156 // if (r_lastvertvalid) 157 // { 158 cmpl $0,C(r_lastvertvalid) 159 jz LCalcFirst 160 161 // u0 = r_u1; 162 // v0 = r_v1; 163 // lzi0 = r_lzi1; 164 // ceilv0 = r_ceilv1; 165 movl C(r_lzi1),%eax 166 movl C(r_u1),%ecx 167 movl %eax,Lzi0 168 movl %ecx,Lu0 169 movl C(r_v1),%ecx 170 movl C(r_ceilv1),%eax 171 movl %ecx,Lv0 172 movl %eax,Lceilv0 173 jmp LCalcSecond 174 175 // } 176 177 LCalcFirst: 178 179 // else 180 // { 181 // world = &pv0->position[0]; 182 183 call LTransformAndProject // v0 | lzi0 | u0 184 185 fsts Lv0 186 fxch %st(2) // u0 | lzi0 | v0 187 fstps Lu0 // lzi0 | v0 188 fstps Lzi0 // v0 189 190 // ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0); 191 fistpl Lceilv0 192 193 // } 194 195 LCalcSecond: 196 197 // world = &pv1->position[0]; 198 movl %edx,%esi 199 200 call LTransformAndProject // v1 | lzi1 | u1 201 202 flds Lu0 // u0 | v1 | lzi1 | u1 203 fxch %st(3) // u1 | v1 | lzi1 | u0 204 flds Lzi0 // lzi0 | u1 | v1 | lzi1 | u0 205 fxch %st(3) // lzi1 | u1 | v1 | lzi0 | u0 206 flds Lv0 // v0 | lzi1 | u1 | v1 | lzi0 | u0 207 fxch %st(3) // v1 | lzi1 | u1 | v0 | lzi0 | u0 208 209 // r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1); 210 fistl C(r_ceilv1) 211 212 fldcw single_cw // put back normal floating-point state 213 214 fsts C(r_v1) 215 fxch %st(4) // lzi0 | lzi1 | u1 | v0 | v1 | u0 216 217 // if (r_lzi1 > lzi0) 218 // lzi0 = r_lzi1; 219 fcom %st(1) 220 fnstsw %ax 221 testb $1,%ah 222 jz LP0 223 fstp %st(0) 224 fld %st(0) 225 LP0: 226 227 fxch %st(1) // lzi1 | lzi0 | u1 | v0 | v1 | u0 228 fstps C(r_lzi1) // lzi0 | u1 | v0 | v1 | u0 229 fxch %st(1) 230 fsts C(r_u1) 231 fxch %st(1) 232 233 // if (lzi0 > r_nearzi) // for mipmap finding 234 // r_nearzi = lzi0; 235 fcoms C(r_nearzi) 236 fnstsw %ax 237 testb $0x45,%ah 238 jnz LP1 239 fsts C(r_nearzi) 240 LP1: 241 242 // // for right edges, all we want is the effect on 1/z 243 // if (r_nearzionly) 244 // return; 245 movl C(r_nearzionly),%eax 246 testl %eax,%eax 247 jz LP2 248 LPop5AndDone: 249 movl C(cacheoffset),%eax 250 movl C(r_framecount),%edx 251 cmpl $0x7FFFFFFF,%eax 252 jz LDoPop 253 andl $(FRAMECOUNT_MASK),%edx 254 orl $(FULLY_CLIPPED_CACHED),%edx 255 movl %edx,C(cacheoffset) 256 257 LDoPop: 258 fstp %st(0) // u1 | v0 | v1 | u0 259 fstp %st(0) // v0 | v1 | u0 260 fstp %st(0) // v1 | u0 261 fstp %st(0) // u0 262 fstp %st(0) 263 jmp Ldone 264 265 LP2: 266 267 // // create the edge 268 // if (ceilv0 == r_ceilv1) 269 // return; // horizontal edge 270 movl Lceilv0,%ebx 271 movl C(edge_p),%edi 272 movl C(r_ceilv1),%ecx 273 movl %edi,%edx 274 movl C(r_pedge),%esi 275 addl $(et_size),%edx 276 cmpl %ecx,%ebx 277 jz LPop5AndDone 278 279 movl C(r_pedge),%eax 280 movl %eax,et_owner(%edi) 281 282 // side = ceilv0 > r_ceilv1; 283 // 284 // edge->nearzi = lzi0; 285 fstps et_nearzi(%edi) // u1 | v0 | v1 | u0 286 287 // if (side == 1) 288 // { 289 jc LSide0 290 291 LSide1: 292 293 // // leading edge (go from p2 to p1) 294 295 // u_step = ((u0 - r_u1) / (v0 - r_v1)); 296 fsubrp %st(0),%st(3) // v0 | v1 | u0-u1 297 fsub %st(1),%st(0) // v0-v1 | v1 | u0-u1 298 fdivrp %st(0),%st(2) // v1 | ustep 299 300 // r_emitted = 1; 301 movl $1,C(r_emitted) 302 303 // edge = edge_p++; 304 movl %edx,C(edge_p) 305 306 // pretouch next edge 307 movl (%edx),%eax 308 309 // v2 = ceilv0 - 1; 310 // v = r_ceilv1; 311 movl %ecx,%eax 312 leal -1(%ebx),%ecx 313 movl %eax,%ebx 314 315 // edge->surfs[0] = 0; 316 // edge->surfs[1] = surface_p - surfaces; 317 movl C(surface_p),%eax 318 movl C(surfaces),%esi 319 subl %edx,%edx 320 subl %esi,%eax 321 shrl $(SURF_T_SHIFT),%eax 322 movl %edx,et_surfs(%edi) 323 movl %eax,et_surfs+2(%edi) 324 325 subl %esi,%esi 326 327 // u = r_u1 + ((float)v - r_v1) * u_step; 328 movl %ebx,Lv 329 fildl Lv // v | v1 | ustep 330 fsubp %st(0),%st(1) // v-v1 | ustep 331 fmul %st(1),%st(0) // (v-v1)*ustep | ustep 332 fadds C(r_u1) // u | ustep 333 334 jmp LSideDone 335 336 // } 337 338 LSide0: 339 340 // else 341 // { 342 // // trailing edge (go from p1 to p2) 343 344 // u_step = ((r_u1 - u0) / (r_v1 - v0)); 345 fsub %st(3),%st(0) // u1-u0 | v0 | v1 | u0 346 fxch %st(2) // v1 | v0 | u1-u0 | u0 347 fsub %st(1),%st(0) // v1-v0 | v0 | u1-u0 | u0 348 fdivrp %st(0),%st(2) // v0 | ustep | u0 349 350 // r_emitted = 1; 351 movl $1,C(r_emitted) 352 353 // edge = edge_p++; 354 movl %edx,C(edge_p) 355 356 // pretouch next edge 357 movl (%edx),%eax 358 359 // v = ceilv0; 360 // v2 = r_ceilv1 - 1; 361 decl %ecx 362 363 // edge->surfs[0] = surface_p - surfaces; 364 // edge->surfs[1] = 0; 365 movl C(surface_p),%eax 366 movl C(surfaces),%esi 367 subl %edx,%edx 368 subl %esi,%eax 369 shrl $(SURF_T_SHIFT),%eax 370 movl %edx,et_surfs+2(%edi) 371 movl %eax,et_surfs(%edi) 372 373 movl $1,%esi 374 375 // u = u0 + ((float)v - v0) * u_step; 376 movl %ebx,Lv 377 fildl Lv // v | v0 | ustep | u0 378 fsubp %st(0),%st(1) // v-v0 | ustep | u0 379 fmul %st(1),%st(0) // (v-v0)*ustep | ustep | u0 380 faddp %st(0),%st(2) // ustep | u 381 fxch %st(1) // u | ustep 382 383 // } 384 385 LSideDone: 386 387 // edge->u_step = u_step*0x100000; 388 // edge->u = u*0x100000 + 0xFFFFF; 389 390 fmuls fp_1m // u*0x100000 | ustep 391 fxch %st(1) // ustep | u*0x100000 392 fmuls fp_1m // ustep*0x100000 | u*0x100000 393 fxch %st(1) // u*0x100000 | ustep*0x100000 394 fadds fp_1m_minus_1 // u*0x100000 + 0xFFFFF | ustep*0x100000 395 fxch %st(1) // ustep*0x100000 | u*0x100000 + 0xFFFFF 396 fistpl et_u_step(%edi) // u*0x100000 + 0xFFFFF 397 fistpl et_u(%edi) 398 399 // // we need to do this to avoid stepping off the edges if a very nearly 400 // // horizontal edge is less than epsilon above a scan, and numeric error 401 // // causes it to incorrectly extend to the scan, and the extension of the 402 // // line goes off the edge of the screen 403 // // FIXME: is this actually needed? 404 // if (edge->u < r_refdef.vrect_x_adj_shift20) 405 // edge->u = r_refdef.vrect_x_adj_shift20; 406 // if (edge->u > r_refdef.vrectright_adj_shift20) 407 // edge->u = r_refdef.vrectright_adj_shift20; 408 movl et_u(%edi),%eax 409 movl C(r_refdef)+rd_vrect_x_adj_shift20,%edx 410 cmpl %edx,%eax 411 jl LP4 412 movl C(r_refdef)+rd_vrectright_adj_shift20,%edx 413 cmpl %edx,%eax 414 jng LP5 415 LP4: 416 movl %edx,et_u(%edi) 417 movl %edx,%eax 418 LP5: 419 420 // // sort the edge in normally 421 // u_check = edge->u; 422 // 423 // if (edge->surfs[0]) 424 // u_check++; // sort trailers after leaders 425 addl %esi,%eax 426 427 // if (!newedges[v] || newedges[v]->u >= u_check) 428 // { 429 movl C(newedges)(,%ebx,4),%esi 430 testl %esi,%esi 431 jz LDoFirst 432 cmpl %eax,et_u(%esi) 433 jl LNotFirst 434 LDoFirst: 435 436 // edge->next = newedges[v]; 437 // newedges[v] = edge; 438 movl %esi,et_next(%edi) 439 movl %edi,C(newedges)(,%ebx,4) 440 441 jmp LSetRemove 442 443 // } 444 445 LNotFirst: 446 447 // else 448 // { 449 // pcheck = newedges[v]; 450 // 451 // while (pcheck->next && pcheck->next->u < u_check) 452 // pcheck = pcheck->next; 453 LFindInsertLoop: 454 movl %esi,%edx 455 movl et_next(%esi),%esi 456 testl %esi,%esi 457 jz LInsertFound 458 cmpl %eax,et_u(%esi) 459 jl LFindInsertLoop 460 461 LInsertFound: 462 463 // edge->next = pcheck->next; 464 // pcheck->next = edge; 465 movl %esi,et_next(%edi) 466 movl %edi,et_next(%edx) 467 468 // } 469 470 LSetRemove: 471 472 // edge->nextremove = removeedges[v2]; 473 // removeedges[v2] = edge; 474 movl C(removeedges)(,%ecx,4),%eax 475 movl %edi,C(removeedges)(,%ecx,4) 476 movl %eax,et_nextremove(%edi) 477 478 Ldone: 479 movl Lstack,%esp // clear temporary variables from stack 480 481 popl %ebx // restore register variables 482 popl %edi 483 popl %esi 484 ret 485 486 // at least one point is clipped 487 488 Lp2: 489 testl %eax,%eax 490 jns Lp1 491 492 // else 493 // { 494 // // point 0 is clipped 495 496 // if (d1 < 0) 497 // { 498 movl Ld1,%eax 499 testl %eax,%eax 500 jns Lp3 501 502 // // both points are clipped 503 // // we do cache fully clipped edges 504 // if (!leftclipped) 505 movl C(r_leftclipped),%eax 506 movl C(r_pedge),%ecx 507 testl %eax,%eax 508 jnz Ldone 509 510 // r_pedge->framecount = r_framecount; 511 movl C(r_framecount),%eax 512 andl $(FRAMECOUNT_MASK),%eax 513 orl $(FULLY_CLIPPED_CACHED),%eax 514 movl %eax,C(cacheoffset) 515 516 // return; 517 jmp Ldone 518 519 // } 520 521 Lp1: 522 523 // // point 0 is unclipped 524 // if (d1 >= 0) 525 // { 526 // // both points are unclipped 527 // continue; 528 529 // // only point 1 is clipped 530 531 // f = d0 / (d0 - d1); 532 flds Ld0 533 flds Ld1 534 fsubr %st(1),%st(0) 535 536 // // we don't cache partially clipped edges 537 movl $0x7FFFFFFF,C(cacheoffset) 538 539 fdivrp %st(0),%st(1) 540 541 subl $(mv_size),%esp // allocate space for clipvert 542 543 // clipvert.position[0] = pv0->position[0] + 544 // f * (pv1->position[0] - pv0->position[0]); 545 // clipvert.position[1] = pv0->position[1] + 546 // f * (pv1->position[1] - pv0->position[1]); 547 // clipvert.position[2] = pv0->position[2] + 548 // f * (pv1->position[2] - pv0->position[2]); 549 flds mv_position+8(%edx) 550 fsubs mv_position+8(%esi) 551 flds mv_position+4(%edx) 552 fsubs mv_position+4(%esi) 553 flds mv_position+0(%edx) 554 fsubs mv_position+0(%esi) // 0 | 1 | 2 555 556 // replace pv1 with the clip point 557 movl %esp,%edx 558 movl cp_leftedge(%ebx),%eax 559 testb %al,%al 560 561 fmul %st(3),%st(0) 562 fxch %st(1) // 1 | 0 | 2 563 fmul %st(3),%st(0) 564 fxch %st(2) // 2 | 0 | 1 565 fmulp %st(0),%st(3) // 0 | 1 | 2 566 fadds mv_position+0(%esi) 567 fxch %st(1) // 1 | 0 | 2 568 fadds mv_position+4(%esi) 569 fxch %st(2) // 2 | 0 | 1 570 fadds mv_position+8(%esi) 571 fxch %st(1) // 0 | 2 | 1 572 fstps mv_position+0(%esp) // 2 | 1 573 fstps mv_position+8(%esp) // 1 574 fstps mv_position+4(%esp) 575 576 // if (clip->leftedge) 577 // { 578 jz Ltestright 579 580 // r_leftclipped = true; 581 // r_leftexit = clipvert; 582 movl $1,C(r_leftclipped) 583 movl mv_position+0(%esp),%eax 584 movl %eax,C(r_leftexit)+mv_position+0 585 movl mv_position+4(%esp),%eax 586 movl %eax,C(r_leftexit)+mv_position+4 587 movl mv_position+8(%esp),%eax 588 movl %eax,C(r_leftexit)+mv_position+8 589 590 jmp Lcontinue 591 592 // } 593 594 Ltestright: 595 // else if (clip->rightedge) 596 // { 597 testb %ah,%ah 598 jz Lcontinue 599 600 // r_rightclipped = true; 601 // r_rightexit = clipvert; 602 movl $1,C(r_rightclipped) 603 movl mv_position+0(%esp),%eax 604 movl %eax,C(r_rightexit)+mv_position+0 605 movl mv_position+4(%esp),%eax 606 movl %eax,C(r_rightexit)+mv_position+4 607 movl mv_position+8(%esp),%eax 608 movl %eax,C(r_rightexit)+mv_position+8 609 610 // } 611 // 612 // R_ClipEdge (pv0, &clipvert, clip->next); 613 // return; 614 // } 615 jmp Lcontinue 616 617 // } 618 619 Lp3: 620 621 // // only point 0 is clipped 622 // r_lastvertvalid = false; 623 624 movl $0,C(r_lastvertvalid) 625 626 // f = d0 / (d0 - d1); 627 flds Ld0 628 flds Ld1 629 fsubr %st(1),%st(0) 630 631 // // we don't cache partially clipped edges 632 movl $0x7FFFFFFF,C(cacheoffset) 633 634 fdivrp %st(0),%st(1) 635 636 subl $(mv_size),%esp // allocate space for clipvert 637 638 // clipvert.position[0] = pv0->position[0] + 639 // f * (pv1->position[0] - pv0->position[0]); 640 // clipvert.position[1] = pv0->position[1] + 641 // f * (pv1->position[1] - pv0->position[1]); 642 // clipvert.position[2] = pv0->position[2] + 643 // f * (pv1->position[2] - pv0->position[2]); 644 flds mv_position+8(%edx) 645 fsubs mv_position+8(%esi) 646 flds mv_position+4(%edx) 647 fsubs mv_position+4(%esi) 648 flds mv_position+0(%edx) 649 fsubs mv_position+0(%esi) // 0 | 1 | 2 650 651 movl cp_leftedge(%ebx),%eax 652 testb %al,%al 653 654 fmul %st(3),%st(0) 655 fxch %st(1) // 1 | 0 | 2 656 fmul %st(3),%st(0) 657 fxch %st(2) // 2 | 0 | 1 658 fmulp %st(0),%st(3) // 0 | 1 | 2 659 fadds mv_position+0(%esi) 660 fxch %st(1) // 1 | 0 | 2 661 fadds mv_position+4(%esi) 662 fxch %st(2) // 2 | 0 | 1 663 fadds mv_position+8(%esi) 664 fxch %st(1) // 0 | 2 | 1 665 fstps mv_position+0(%esp) // 2 | 1 666 fstps mv_position+8(%esp) // 1 667 fstps mv_position+4(%esp) 668 669 // replace pv0 with the clip point 670 movl %esp,%esi 671 672 // if (clip->leftedge) 673 // { 674 jz Ltestright2 675 676 // r_leftclipped = true; 677 // r_leftenter = clipvert; 678 movl $1,C(r_leftclipped) 679 movl mv_position+0(%esp),%eax 680 movl %eax,C(r_leftenter)+mv_position+0 681 movl mv_position+4(%esp),%eax 682 movl %eax,C(r_leftenter)+mv_position+4 683 movl mv_position+8(%esp),%eax 684 movl %eax,C(r_leftenter)+mv_position+8 685 686 jmp Lcontinue 687 688 // } 689 690 Ltestright2: 691 // else if (clip->rightedge) 692 // { 693 testb %ah,%ah 694 jz Lcontinue 695 696 // r_rightclipped = true; 697 // r_rightenter = clipvert; 698 movl $1,C(r_rightclipped) 699 movl mv_position+0(%esp),%eax 700 movl %eax,C(r_rightenter)+mv_position+0 701 movl mv_position+4(%esp),%eax 702 movl %eax,C(r_rightenter)+mv_position+4 703 movl mv_position+8(%esp),%eax 704 movl %eax,C(r_rightenter)+mv_position+8 705 706 // } 707 jmp Lcontinue 708 709 // %esi = vec3_t point to transform and project 710 // %edx preserved 711 LTransformAndProject: 712 713 // // transform and project 714 // VectorSubtract (world, modelorg, local); 715 flds mv_position+0(%esi) 716 fsubs C(modelorg)+0 717 flds mv_position+4(%esi) 718 fsubs C(modelorg)+4 719 flds mv_position+8(%esi) 720 fsubs C(modelorg)+8 721 fxch %st(2) // local[0] | local[1] | local[2] 722 723 // TransformVector (local, transformed); 724 // 725 // if (transformed[2] < NEAR_CLIP) 726 // transformed[2] = NEAR_CLIP; 727 // 728 // lzi0 = 1.0 / transformed[2]; 729 fld %st(0) // local[0] | local[0] | local[1] | local[2] 730 fmuls C(vpn)+0 // zm0 | local[0] | local[1] | local[2] 731 fld %st(1) // local[0] | zm0 | local[0] | local[1] | 732 // local[2] 733 fmuls C(vright)+0 // xm0 | zm0 | local[0] | local[1] | local[2] 734 fxch %st(2) // local[0] | zm0 | xm0 | local[1] | local[2] 735 fmuls C(vup)+0 // ym0 | zm0 | xm0 | local[1] | local[2] 736 fld %st(3) // local[1] | ym0 | zm0 | xm0 | local[1] | 737 // local[2] 738 fmuls C(vpn)+4 // zm1 | ym0 | zm0 | xm0 | local[1] | 739 // local[2] 740 fld %st(4) // local[1] | zm1 | ym0 | zm0 | xm0 | 741 // local[1] | local[2] 742 fmuls C(vright)+4 // xm1 | zm1 | ym0 | zm0 | xm0 | 743 // local[1] | local[2] 744 fxch %st(5) // local[1] | zm1 | ym0 | zm0 | xm0 | 745 // xm1 | local[2] 746 fmuls C(vup)+4 // ym1 | zm1 | ym0 | zm0 | xm0 | 747 // xm1 | local[2] 748 fxch %st(1) // zm1 | ym1 | ym0 | zm0 | xm0 | 749 // xm1 | local[2] 750 faddp %st(0),%st(3) // ym1 | ym0 | zm2 | xm0 | xm1 | local[2] 751 fxch %st(3) // xm0 | ym0 | zm2 | ym1 | xm1 | local[2] 752 faddp %st(0),%st(4) // ym0 | zm2 | ym1 | xm2 | local[2] 753 faddp %st(0),%st(2) // zm2 | ym2 | xm2 | local[2] 754 fld %st(3) // local[2] | zm2 | ym2 | xm2 | local[2] 755 fmuls C(vpn)+8 // zm3 | zm2 | ym2 | xm2 | local[2] 756 fld %st(4) // local[2] | zm3 | zm2 | ym2 | xm2 | local[2] 757 fmuls C(vright)+8 // xm3 | zm3 | zm2 | ym2 | xm2 | local[2] 758 fxch %st(5) // local[2] | zm3 | zm2 | ym2 | xm2 | xm3 759 fmuls C(vup)+8 // ym3 | zm3 | zm2 | ym2 | xm2 | xm3 760 fxch %st(1) // zm3 | ym3 | zm2 | ym2 | xm2 | xm3 761 faddp %st(0),%st(2) // ym3 | zm4 | ym2 | xm2 | xm3 762 fxch %st(4) // xm3 | zm4 | ym2 | xm2 | ym3 763 faddp %st(0),%st(3) // zm4 | ym2 | xm4 | ym3 764 fxch %st(1) // ym2 | zm4 | xm4 | ym3 765 faddp %st(0),%st(3) // zm4 | xm4 | ym4 766 767 fcoms Lfp_near_clip 768 fnstsw %ax 769 testb $1,%ah 770 jz LNoClip 771 fstp %st(0) 772 flds Lfp_near_clip 773 774 LNoClip: 775 776 fdivrs float_1 // lzi0 | x | y 777 fxch %st(1) // x | lzi0 | y 778 779 // // FIXME: build x/yscale into transform? 780 // scale = xscale * lzi0; 781 // u0 = (xcenter + scale*transformed[0]); 782 flds C(xscale) // xscale | x | lzi0 | y 783 fmul %st(2),%st(0) // scale | x | lzi0 | y 784 fmulp %st(0),%st(1) // scale*x | lzi0 | y 785 fadds C(xcenter) // u0 | lzi0 | y 786 787 // if (u0 < r_refdef.fvrectx_adj) 788 // u0 = r_refdef.fvrectx_adj; 789 // if (u0 > r_refdef.fvrectright_adj) 790 // u0 = r_refdef.fvrectright_adj; 791 // FIXME: use integer compares of floats? 792 fcoms C(r_refdef)+rd_fvrectx_adj 793 fnstsw %ax 794 testb $1,%ah 795 jz LClampP0 796 fstp %st(0) 797 flds C(r_refdef)+rd_fvrectx_adj 798 LClampP0: 799 fcoms C(r_refdef)+rd_fvrectright_adj 800 fnstsw %ax 801 testb $0x45,%ah 802 jnz LClampP1 803 fstp %st(0) 804 flds C(r_refdef)+rd_fvrectright_adj 805 LClampP1: 806 807 fld %st(1) // lzi0 | u0 | lzi0 | y 808 809 // scale = yscale * lzi0; 810 // v0 = (ycenter - scale*transformed[1]); 811 fmuls C(yscale) // scale | u0 | lzi0 | y 812 fmulp %st(0),%st(3) // u0 | lzi0 | scale*y 813 fxch %st(2) // scale*y | lzi0 | u0 814 fsubrs C(ycenter) // v0 | lzi0 | u0 815 816 // if (v0 < r_refdef.fvrecty_adj) 817 // v0 = r_refdef.fvrecty_adj; 818 // if (v0 > r_refdef.fvrectbottom_adj) 819 // v0 = r_refdef.fvrectbottom_adj; 820 // FIXME: use integer compares of floats? 821 fcoms C(r_refdef)+rd_fvrecty_adj 822 fnstsw %ax 823 testb $1,%ah 824 jz LClampP2 825 fstp %st(0) 826 flds C(r_refdef)+rd_fvrecty_adj 827 LClampP2: 828 fcoms C(r_refdef)+rd_fvrectbottom_adj 829 fnstsw %ax 830 testb $0x45,%ah 831 jnz LClampP3 832 fstp %st(0) 833 flds C(r_refdef)+rd_fvrectbottom_adj 834 LClampP3: 835 ret 836 837 #endif // id386 838 839