1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, 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 38Ld0: .single 0.0 39Ld1: .single 0.0 40Lstack: .long 0 41Lfp_near_clip: .single NEAR_CLIP 42Lceilv0: .long 0 43Lv: .long 0 44Lu0: .long 0 45Lv0: .long 0 46Lzi0: .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) 60C(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 81Lcliploop: 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 123Lcontinue: 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); 138Lemit: 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 177LCalcFirst: 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 195LCalcSecond: 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) 225LP0: 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) 240LP1: 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 248LPop5AndDone: 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 257LDoPop: 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 265LP2: 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 291LSide1: 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 338LSide0: 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 385LSideDone: 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 415LP4: 416 movl %edx,et_u(%edi) 417 movl %edx,%eax 418LP5: 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 434LDoFirst: 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 445LNotFirst: 446 447// else 448// { 449// pcheck = newedges[v]; 450// 451// while (pcheck->next && pcheck->next->u < u_check) 452// pcheck = pcheck->next; 453LFindInsertLoop: 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 461LInsertFound: 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 470LSetRemove: 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 478Ldone: 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 488Lp2: 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 521Lp1: 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 594Ltestright: 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 619Lp3: 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 690Ltestright2: 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 711LTransformAndProject: 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 774LNoClip: 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 798LClampP0: 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 805LClampP1: 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 827LClampP2: 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 834LClampP3: 835 ret 836 837#endif // id386 838 839