1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "SetupRoutine.hpp" 16 17 #include "Constants.hpp" 18 #include "Device/Primitive.hpp" 19 #include "Device/Polygon.hpp" 20 #include "Device/Renderer.hpp" 21 #include "Reactor/Reactor.hpp" 22 23 namespace sw 24 { 25 extern bool complementaryDepthBuffer; 26 extern TranscendentalPrecision logPrecision; 27 extern bool leadingVertexFirst; 28 29 SetupRoutine::SetupRoutine(const SetupProcessor::State &state) : state(state) 30 { 31 routine = 0; 32 } 33 34 SetupRoutine::~SetupRoutine() 35 { 36 } 37 38 void SetupRoutine::generate() 39 { 40 Function<Bool(Pointer<Byte>, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>)> function; 41 { 42 Pointer<Byte> primitive(function.Arg<0>()); 43 Pointer<Byte> tri(function.Arg<1>()); 44 Pointer<Byte> polygon(function.Arg<2>()); 45 Pointer<Byte> data(function.Arg<3>()); 46 47 Pointer<Byte> constants = *Pointer<Pointer<Byte> >(data + OFFSET(DrawData,constants)); 48 49 const bool point = state.isDrawPoint; 50 const bool line = state.isDrawLine; 51 const bool triangle = state.isDrawTriangle; 52 53 const int V0 = OFFSET(Triangle,v0); 54 const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0); 55 const int V2 = triangle ? OFFSET(Triangle,v2) : (line ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0)); 56 57 int pos = state.positionRegister; 58 59 Pointer<Byte> v0 = tri + V0; 60 Pointer<Byte> v1 = tri + V1; 61 Pointer<Byte> v2 = tri + V2; 62 63 Array<Int> X(16); 64 Array<Int> Y(16); 65 66 X[0] = *Pointer<Int>(v0 + OFFSET(Vertex,X)); 67 X[1] = *Pointer<Int>(v1 + OFFSET(Vertex,X)); 68 X[2] = *Pointer<Int>(v2 + OFFSET(Vertex,X)); 69 70 Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex,Y)); 71 Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex,Y)); 72 Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex,Y)); 73 74 Int d = 1; // Winding direction 75 76 // Culling 77 if(triangle) 78 { 79 Float x0 = Float(X[0]); 80 Float x1 = Float(X[1]); 81 Float x2 = Float(X[2]); 82 83 Float y0 = Float(Y[0]); 84 Float y1 = Float(Y[1]); 85 Float y2 = Float(Y[2]); 86 87 Float A = (y2 - y0) * x1 + (y1 - y2) * x0 + (y0 - y1) * x2; // Area 88 89 If(A == 0.0f) 90 { 91 Return(false); 92 } 93 94 Int w0w1w2 = *Pointer<Int>(v0 + pos * 16 + 12) ^ 95 *Pointer<Int>(v1 + pos * 16 + 12) ^ 96 *Pointer<Int>(v2 + pos * 16 + 12); 97 98 A = IfThenElse(w0w1w2 < 0, -A, A); 99 100 if(state.cullMode == CULL_CLOCKWISE) 101 { 102 If(A >= 0.0f) Return(false); 103 } 104 else if(state.cullMode == CULL_COUNTERCLOCKWISE) 105 { 106 If(A <= 0.0f) Return(false); 107 } 108 109 d = IfThenElse(A < 0.0f, d, Int(0)); 110 111 if(state.twoSidedStencil) 112 { 113 If(A > 0.0f) 114 { 115 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); 116 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 117 } 118 Else 119 { 120 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 121 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); 122 } 123 } 124 125 if(state.vFace) 126 { 127 *Pointer<Float>(primitive + OFFSET(Primitive,area)) = 0.5f * A; 128 } 129 } 130 else 131 { 132 if(state.twoSidedStencil) 133 { 134 *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); 135 *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); 136 } 137 } 138 139 Int n = *Pointer<Int>(polygon + OFFSET(Polygon,n)); 140 Int m = *Pointer<Int>(polygon + OFFSET(Polygon,i)); 141 142 If(m != 0 || Bool(!triangle)) // Clipped triangle; reproject 143 { 144 Pointer<Byte> V = polygon + OFFSET(Polygon,P) + m * sizeof(void*) * 16; 145 146 Int i = 0; 147 148 Do 149 { 150 Pointer<Float4> p = *Pointer<Pointer<Float4> >(V + i * sizeof(void*)); 151 Float4 v = *Pointer<Float4>(p, 16); 152 153 Float w = v.w; 154 Float rhw = IfThenElse(w != 0.0f, 1.0f / w, Float(1.0f)); 155 156 X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,X0x16)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData,Wx16))); 157 Y[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,Y0x16)) + v.y * rhw * *Pointer<Float>(data + OFFSET(DrawData,Hx16))); 158 159 i++; 160 } 161 Until(i >= n) 162 } 163 164 // Vertical range 165 Int yMin = Y[0]; 166 Int yMax = Y[0]; 167 168 Int i = 1; 169 170 Do 171 { 172 yMin = Min(Y[i], yMin); 173 yMax = Max(Y[i], yMax); 174 175 i++; 176 } 177 Until(i >= n) 178 179 if(state.multiSample > 1) 180 { 181 yMin = (yMin + 0x0A) >> 4; 182 yMax = (yMax + 0x14) >> 4; 183 } 184 else 185 { 186 yMin = (yMin + 0x0F) >> 4; 187 yMax = (yMax + 0x0F) >> 4; 188 } 189 190 If(yMin == yMax) 191 { 192 Return(false); 193 } 194 195 yMin = Max(yMin, *Pointer<Int>(data + OFFSET(DrawData,scissorY0))); 196 yMax = Min(yMax, *Pointer<Int>(data + OFFSET(DrawData,scissorY1))); 197 198 For(Int q = 0, q < state.multiSample, q++) 199 { 200 Array<Int> Xq(16); 201 Array<Int> Yq(16); 202 203 Int i = 0; 204 205 Do 206 { 207 Xq[i] = X[i]; 208 Yq[i] = Y[i]; 209 210 if(state.multiSample > 1) 211 { 212 Xq[i] = Xq[i] + *Pointer<Int>(constants + OFFSET(Constants,Xf) + q * sizeof(int)); 213 Yq[i] = Yq[i] + *Pointer<Int>(constants + OFFSET(Constants,Yf) + q * sizeof(int)); 214 } 215 216 i++; 217 } 218 Until(i >= n) 219 220 Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->left)) + q * sizeof(Primitive); 221 Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->right)) + q * sizeof(Primitive); 222 223 if(state.multiSample > 1) 224 { 225 Int xMin = *Pointer<Int>(data + OFFSET(DrawData, scissorX0)); 226 Int xMax = *Pointer<Int>(data + OFFSET(DrawData, scissorX1)); 227 Short x = Short(Clamp((X[0] + 0xF) >> 4, xMin, xMax)); 228 229 For(Int y = yMin - 1, y < yMax + 1, y++) 230 { 231 *Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x; 232 *Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x; 233 } 234 } 235 236 Xq[n] = Xq[0]; 237 Yq[n] = Yq[0]; 238 239 // Rasterize 240 { 241 Int i = 0; 242 243 Do 244 { 245 edge(primitive, data, Xq[i + 1 - d], Yq[i + 1 - d], Xq[i + d], Yq[i + d], q); 246 247 i++; 248 } 249 Until(i >= n) 250 } 251 252 if(state.multiSample == 1) 253 { 254 For(, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++) 255 { 256 // Increments yMin 257 } 258 259 For(, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--) 260 { 261 // Decrements yMax 262 } 263 264 If(yMin == yMax) 265 { 266 Return(false); 267 } 268 269 *Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)); 270 *Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)); 271 *Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)); 272 *Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)); 273 } 274 } 275 276 *Pointer<Int>(primitive + OFFSET(Primitive,yMin)) = yMin; 277 *Pointer<Int>(primitive + OFFSET(Primitive,yMax)) = yMax; 278 279 // Sort by minimum y 280 if(triangle) 281 { 282 Float y0 = *Pointer<Float>(v0 + pos * 16 + 4); 283 Float y1 = *Pointer<Float>(v1 + pos * 16 + 4); 284 Float y2 = *Pointer<Float>(v2 + pos * 16 + 4); 285 286 Float yMin = Min(Min(y0, y1), y2); 287 288 conditionalRotate1(yMin == y1, v0, v1, v2); 289 conditionalRotate2(yMin == y2, v0, v1, v2); 290 } 291 292 // Sort by maximum w 293 if(triangle) 294 { 295 Float w0 = *Pointer<Float>(v0 + pos * 16 + 12); 296 Float w1 = *Pointer<Float>(v1 + pos * 16 + 12); 297 Float w2 = *Pointer<Float>(v2 + pos * 16 + 12); 298 299 Float wMax = Max(Max(w0, w1), w2); 300 301 conditionalRotate1(wMax == w1, v0, v1, v2); 302 conditionalRotate2(wMax == w2, v0, v1, v2); 303 } 304 305 Float w0 = *Pointer<Float>(v0 + pos * 16 + 12); 306 Float w1 = *Pointer<Float>(v1 + pos * 16 + 12); 307 Float w2 = *Pointer<Float>(v2 + pos * 16 + 12); 308 309 Float4 w012; 310 311 w012.x = w0; 312 w012.y = w1; 313 w012.z = w2; 314 w012.w = 1; 315 316 Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex,W)); 317 318 Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex,X)); 319 Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex,X)); 320 Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex,X)); 321 322 Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex,Y)); 323 Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex,Y)); 324 Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex,Y)); 325 326 if(line) 327 { 328 X2 = X1 + Y1 - Y0; 329 Y2 = Y1 + X0 - X1; 330 } 331 332 Float dx = Float(X0) * (1.0f / 16.0f); 333 Float dy = Float(Y0) * (1.0f / 16.0f); 334 335 X1 -= X0; 336 Y1 -= Y0; 337 338 X2 -= X0; 339 Y2 -= Y0; 340 341 Float x1 = w1 * (1.0f / 16.0f) * Float(X1); 342 Float y1 = w1 * (1.0f / 16.0f) * Float(Y1); 343 344 Float x2 = w2 * (1.0f / 16.0f) * Float(X2); 345 Float y2 = w2 * (1.0f / 16.0f) * Float(Y2); 346 347 Float a = x1 * y2 - x2 * y1; 348 349 Float4 xQuad = Float4(0, 1, 0, 1) - Float4(dx); 350 Float4 yQuad = Float4(0, 0, 1, 1) - Float4(dy); 351 352 *Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16) = xQuad; 353 *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16) = yQuad; 354 355 Float4 M[3]; 356 357 M[0] = Float4(0, 0, 0, 0); 358 M[1] = Float4(0, 0, 0, 0); 359 M[2] = Float4(0, 0, 0, 0); 360 361 M[0].z = rhw0; 362 363 If(a != 0.0f) 364 { 365 Float A = 1.0f / a; 366 Float D = A * rhw0; 367 368 M[0].x = (y1 * w2 - y2 * w1) * D; 369 M[0].y = (x2 * w1 - x1 * w2) * D; 370 // M[0].z = rhw0; 371 // M[0].w = 0; 372 373 M[1].x = y2 * A; 374 M[1].y = -x2 * A; 375 // M[1].z = 0; 376 // M[1].w = 0; 377 378 M[2].x = -y1 * A; 379 M[2].y = x1 * A; 380 // M[2].z = 0; 381 // M[2].w = 0; 382 } 383 384 if(state.interpolateW) 385 { 386 Float4 ABC = M[0] + M[1] + M[2]; 387 388 Float4 A = ABC.x; 389 Float4 B = ABC.y; 390 Float4 C = ABC.z; 391 392 *Pointer<Float4>(primitive + OFFSET(Primitive,w.A), 16) = A; 393 *Pointer<Float4>(primitive + OFFSET(Primitive,w.B), 16) = B; 394 *Pointer<Float4>(primitive + OFFSET(Primitive,w.C), 16) = C; 395 } 396 397 if(state.interpolateZ) 398 { 399 Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex,Z)); 400 Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex,Z)); 401 Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex,Z)); 402 403 z1 -= z0; 404 z2 -= z0; 405 406 Float4 A; 407 Float4 B; 408 Float4 C; 409 410 if(!point) 411 { 412 Float x1 = Float(X1) * (1.0f / 16.0f); 413 Float y1 = Float(Y1) * (1.0f / 16.0f); 414 Float x2 = Float(X2) * (1.0f / 16.0f); 415 Float y2 = Float(Y2) * (1.0f / 16.0f); 416 417 Float D = *Pointer<Float>(data + OFFSET(DrawData,depthRange)) / (x1 * y2 - x2 * y1); 418 419 Float a = (y2 * z1 - y1 * z2) * D; 420 Float b = (x1 * z2 - x2 * z1) * D; 421 422 A = Float4(a); 423 B = Float4(b); 424 } 425 else 426 { 427 A = Float4(0, 0, 0, 0); 428 B = Float4(0, 0, 0, 0); 429 } 430 431 *Pointer<Float4>(primitive + OFFSET(Primitive,z.A), 16) = A; 432 *Pointer<Float4>(primitive + OFFSET(Primitive,z.B), 16) = B; 433 434 Float c = z0; 435 436 if(state.isDrawTriangle && state.slopeDepthBias) 437 { 438 Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x))); 439 bias *= *Pointer<Float>(data + OFFSET(DrawData,slopeDepthBias)); 440 441 if(complementaryDepthBuffer) 442 { 443 bias = -bias; 444 } 445 446 c += bias; 447 } 448 449 C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData,depthRange)) + *Pointer<Float>(data + OFFSET(DrawData,depthNear))); 450 451 *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) = C; 452 } 453 454 for(int interpolant = 0; interpolant < MAX_FRAGMENT_INPUTS; interpolant++) 455 { 456 for(int component = 0; component < 4; component++) 457 { 458 int attribute = state.gradient[interpolant][component].attribute; 459 bool flat = state.gradient[interpolant][component].flat; 460 bool wrap = state.gradient[interpolant][component].wrap; 461 462 if(attribute != Unused) 463 { 464 setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,v[attribute][component]), OFFSET(Primitive,V[interpolant][component]), flat, point, state.perspective, wrap, component); 465 } 466 } 467 } 468 469 Return(true); 470 } 471 472 routine = function("SetupRoutine"); 473 } 474 475 void SetupRoutine::setupGradient(Pointer<Byte> &primitive, Pointer<Byte> &triangle, Float4 &w012, Float4 (&m)[3], Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2, int attribute, int planeEquation, bool flat, bool sprite, bool perspective, bool wrap, int component) 476 { 477 Float4 i; 478 479 if(!flat) 480 { 481 if(!sprite) 482 { 483 i.x = *Pointer<Float>(v0 + attribute); 484 i.y = *Pointer<Float>(v1 + attribute); 485 i.z = *Pointer<Float>(v2 + attribute); 486 i.w = 0; 487 } 488 else 489 { 490 if(component == 0) i.x = 0.5f; 491 if(component == 1) i.x = 0.5f; 492 if(component == 2) i.x = 0.0f; 493 if(component == 3) i.x = 1.0f; 494 495 if(component == 0) i.y = 1.0f; 496 if(component == 1) i.y = 0.5f; 497 if(component == 2) i.y = 0.0f; 498 if(component == 3) i.y = 1.0f; 499 500 if(component == 0) i.z = 0.5f; 501 if(component == 1) i.z = 1.0f; 502 if(component == 2) i.z = 0.0f; 503 if(component == 3) i.z = 1.0f; 504 505 i.w = 0; 506 } 507 508 if(wrap) 509 { 510 Float m; 511 512 m = *Pointer<Float>(v0 + attribute); 513 m = Max(m, *Pointer<Float>(v1 + attribute)); 514 m = Max(m, *Pointer<Float>(v2 + attribute)); 515 m -= 0.5f; 516 517 // TODO: Vectorize 518 If(Float(i.x) < m) i.x = i.x + 1.0f; 519 If(Float(i.y) < m) i.y = i.y + 1.0f; 520 If(Float(i.z) < m) i.z = i.z + 1.0f; 521 } 522 523 if(!perspective) 524 { 525 i *= w012; 526 } 527 528 Float4 A = i.xxxx * m[0]; 529 Float4 B = i.yyyy * m[1]; 530 Float4 C = i.zzzz * m[2]; 531 532 C = A + B + C; 533 534 A = C.xxxx; 535 B = C.yyyy; 536 C = C.zzzz; 537 538 *Pointer<Float4>(primitive + planeEquation + 0, 16) = A; 539 *Pointer<Float4>(primitive + planeEquation + 16, 16) = B; 540 *Pointer<Float4>(primitive + planeEquation + 32, 16) = C; 541 } 542 else 543 { 544 int leadingVertex = leadingVertexFirst ? OFFSET(Triangle,v0) : OFFSET(Triangle,v2); 545 Float C = *Pointer<Float>(triangle + leadingVertex + attribute); 546 547 *Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0); 548 *Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0); 549 *Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C); 550 } 551 } 552 553 void SetupRoutine::edge(Pointer<Byte> &primitive, Pointer<Byte> &data, const Int &Xa, const Int &Ya, const Int &Xb, const Int &Yb, Int &q) 554 { 555 If(Ya != Yb) 556 { 557 Bool swap = Yb < Ya; 558 559 Int X1 = IfThenElse(swap, Xb, Xa); 560 Int X2 = IfThenElse(swap, Xa, Xb); 561 Int Y1 = IfThenElse(swap, Yb, Ya); 562 Int Y2 = IfThenElse(swap, Ya, Yb); 563 564 Int y1 = Max((Y1 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY0))); 565 Int y2 = Min((Y2 + 0x0000000F) >> 4, *Pointer<Int>(data + OFFSET(DrawData,scissorY1))); 566 567 If(y1 < y2) 568 { 569 Int xMin = *Pointer<Int>(data + OFFSET(DrawData,scissorX0)); 570 Int xMax = *Pointer<Int>(data + OFFSET(DrawData,scissorX1)); 571 572 Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left); 573 Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right); 574 Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge); 575 576 // Deltas 577 Int DX12 = X2 - X1; 578 Int DY12 = Y2 - Y1; 579 580 Int FDX12 = DX12 << 4; 581 Int FDY12 = DY12 << 4; 582 583 Int X = DX12 * ((y1 << 4) - Y1) + (X1 & 0x0000000F) * DY12; 584 Int x = (X1 >> 4) + X / FDY12; // Edge 585 Int d = X % FDY12; // Error-term 586 Int ceil = -d >> 31; // Ceiling division: remainder <= 0 587 x -= ceil; 588 d -= ceil & FDY12; 589 590 Int Q = FDX12 / FDY12; // Edge-step 591 Int R = FDX12 % FDY12; // Error-step 592 Int floor = R >> 31; // Flooring division: remainder >= 0 593 Q += floor; 594 R += floor & FDY12; 595 596 Int D = FDY12; // Error-overflow 597 Int y = y1; 598 599 Do 600 { 601 *Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(Clamp(x, xMin, xMax)); 602 603 x += Q; 604 d += R; 605 606 Int overflow = -d >> 31; 607 608 d -= D & overflow; 609 x -= overflow; 610 611 y++; 612 } 613 Until(y >= y2) 614 } 615 } 616 } 617 618 void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2) 619 { 620 #if 0 // Rely on LLVM optimization 621 If(condition) 622 { 623 Pointer<Byte> vX; 624 625 vX = v0; 626 v0 = v1; 627 v1 = v2; 628 v2 = vX; 629 } 630 #else 631 Pointer<Byte> vX = v0; 632 v0 = IfThenElse(condition, v1, v0); 633 v1 = IfThenElse(condition, v2, v1); 634 v2 = IfThenElse(condition, vX, v2); 635 #endif 636 } 637 638 void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2) 639 { 640 #if 0 // Rely on LLVM optimization 641 If(condition) 642 { 643 Pointer<Byte> vX; 644 645 vX = v2; 646 v2 = v1; 647 v1 = v0; 648 v0 = vX; 649 } 650 #else 651 Pointer<Byte> vX = v2; 652 v2 = IfThenElse(condition, v1, v2); 653 v1 = IfThenElse(condition, v0, v1); 654 v0 = IfThenElse(condition, vX, v0); 655 #endif 656 } 657 658 Routine *SetupRoutine::getRoutine() 659 { 660 return routine; 661 } 662 } 663