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