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 17Ld0: .single 0.0 18Ld1: .single 0.0 19Lstack: .long 0 20Lfp_near_clip: .single NEAR_CLIP 21Lceilv0: .long 0 22Lv: .long 0 23Lu0: .long 0 24Lv0: .long 0 25Lzi0: .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) 39C(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 60Lcliploop: 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 102Lcontinue: 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); 117Lemit: 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 156LCalcFirst: 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 174LCalcSecond: 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) 204LP0: 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) 219LP1: 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 227LPop5AndDone: 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 236LDoPop: 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 244LP2: 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 270LSide1: 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 317LSide0: 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 364LSideDone: 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 394LP4: 395 movl %edx,et_u(%edi) 396 movl %edx,%eax 397LP5: 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 413LDoFirst: 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 424LNotFirst: 425 426// else 427// { 428// pcheck = newedges[v]; 429// 430// while (pcheck->next && pcheck->next->u < u_check) 431// pcheck = pcheck->next; 432LFindInsertLoop: 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 440LInsertFound: 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 449LSetRemove: 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 457Ldone: 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 467Lp2: 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 500Lp1: 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 573Ltestright: 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 598Lp3: 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 669Ltestright2: 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 690LTransformAndProject: 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 753LNoClip: 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 777LClampP0: 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 784LClampP1: 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 806LClampP2: 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 813LClampP3: 814 ret 815 816#endif // id386 817 818