Add SwiftShader source to repo
Oct 6 code drop from Transgaming
Review URL: https://chromereviews.googleplex.com/3846015
diff --git a/src/Shader/SetupRoutine.cpp b/src/Shader/SetupRoutine.cpp
new file mode 100644
index 0000000..40a2a18
--- /dev/null
+++ b/src/Shader/SetupRoutine.cpp
@@ -0,0 +1,661 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2011 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+#include "SetupRoutine.hpp"
+
+#include "Constants.hpp"
+#include "Renderer/Primitive.hpp"
+#include "Renderer/Polygon.hpp"
+#include "Renderer/Renderer.hpp"
+#include "Reactor/Shell.hpp"
+
+namespace sw
+{
+ extern bool complementaryDepthBuffer;
+ extern TranscendentalPrecision logPrecision;
+
+ SetupRoutine::SetupRoutine(const SetupProcessor::State &state) : state(state)
+ {
+ routine = 0;
+ }
+
+ SetupRoutine::~SetupRoutine()
+ {
+ }
+
+ void SetupRoutine::generate()
+ {
+ Function<Bool, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>, Pointer<Byte>> function;
+ {
+ Pointer<Byte> primitive(function.arg(0));
+ Pointer<Byte> tri(function.arg(1));
+ Pointer<Byte> polygon(function.arg(2));
+ Pointer<Byte> data(function.arg(3));
+
+ Pointer<Byte> constants = *Pointer<Pointer<Byte>>(data + OFFSET(DrawData,constants));
+
+ const bool point = state.isDrawPoint;
+ const bool sprite = state.pointSprite;
+ const bool line = state.isDrawLine;
+ const bool triangle = state.isDrawSolidTriangle || sprite;
+ const bool solidTriangle = state.isDrawSolidTriangle;
+
+ const int V0 = OFFSET(Triangle,v0);
+ const int V1 = (triangle || line) ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0);
+ const int V2 = triangle ? OFFSET(Triangle,v2) : (line ? OFFSET(Triangle,v1) : OFFSET(Triangle,v0));
+
+ int pos = state.positionRegister;
+
+ Pointer<Byte> v0 = tri + V0;
+ Pointer<Byte> v1 = tri + V1;
+ Pointer<Byte> v2 = tri + V2;
+
+ Array<Int> X(16);
+ Array<Int> Y(16);
+
+ X[0] = *Pointer<Int>(v0 + OFFSET(Vertex,X));
+ X[1] = *Pointer<Int>(v1 + OFFSET(Vertex,X));
+ X[2] = *Pointer<Int>(v2 + OFFSET(Vertex,X));
+
+ Y[0] = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
+ Y[1] = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
+ Y[2] = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
+
+ Int d = 1; // Winding direction
+
+ // Culling
+ if(solidTriangle)
+ {
+ Float x0 = Float(X[0]);
+ Float x1 = Float(X[1]);
+ Float x2 = Float(X[2]);
+
+ Float y0 = Float(Y[0]);
+ Float y1 = Float(Y[1]);
+ Float y2 = Float(Y[2]);
+
+ Float A = (y2 - y0) * x1 + (y1 - y2) * x0 + (y0 - y1) * x2; // Area
+
+ If(A == Float(0.0f))
+ {
+ Return(false);
+ }
+
+ Float w0w1w2 = *Pointer<Float>(v0 + pos * 16 + 12) *
+ *Pointer<Float>(v1 + pos * 16 + 12) *
+ *Pointer<Float>(v2 + pos * 16 + 12);
+
+ A = IfThenElse(w0w1w2 < Float(0.0f), -A, A);
+
+ if(state.cullMode == Context::CULL_CLOCKWISE)
+ {
+ If(A >= Float(0.0f)) Return(false);
+ }
+ else if(state.cullMode == Context::CULL_COUNTERCLOCKWISE)
+ {
+ If(A <= Float(0.0f)) Return(false);
+ }
+
+ d = IfThenElse(A < Float(0.0f), d, Int(0));
+
+ if(state.twoSidedStencil)
+ {
+ Byte8 clockwiseMask = IfThenElse(A > Float(0.0f), Byte8(0xFFFFFFFFFFFFFFFF), Byte8(0x0000000000000000));
+
+ *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = clockwiseMask;
+ *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = ~clockwiseMask;
+ }
+
+ if(state.vFace)
+ {
+ *Pointer<Float>(primitive + OFFSET(Primitive,area)) = Float(0.5f) * A;
+ }
+ }
+ else
+ {
+ if(state.twoSidedStencil)
+ {
+ *Pointer<Byte8>(primitive + OFFSET(Primitive,clockwiseMask)) = Byte8(0xFFFFFFFFFFFFFFFF);
+ *Pointer<Byte8>(primitive + OFFSET(Primitive,invClockwiseMask)) = Byte8(0x0000000000000000);
+ }
+ }
+
+ Int n = *Pointer<Int>(polygon + OFFSET(Polygon,n));
+ Int m = *Pointer<Int>(polygon + OFFSET(Polygon,i));
+
+ If(m != 0 || Bool(!solidTriangle)) // Clipped triangle; reproject
+ {
+ Pointer<Byte> V = polygon + OFFSET(Polygon,P) + m * sizeof(void*) * 16;
+
+ Int i = 0;
+
+ Do
+ {
+ Pointer<Float4> p = *Pointer<Pointer<Float4>>(V + i * sizeof(void*));
+ Float4 v = *Pointer<Float4>(p, 16);
+
+ Float w = v.w;
+ Float rhw = IfThenElse(w != Float(0.0f), Float(1.0f) / w, Float(1.0f));
+
+ X[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,LLLLx16)) + v.x * rhw * *Pointer<Float>(data + OFFSET(DrawData,WWWWx16)));
+ Y[i] = RoundInt(*Pointer<Float>(data + OFFSET(DrawData,TTTTx16)) + v.y * rhw * *Pointer<Float>(data + OFFSET(DrawData,HHHHx16)));
+
+ i++;
+ }
+ Until(i >= n)
+ }
+
+ // Vertical range
+ Int yMin = Y[0];
+ Int yMax = Y[0];
+
+ Int i = 1;
+
+ Do
+ {
+ yMin = IfThenElse(Y[i] < yMin, Int(Y[i]), yMin); // FIXME: Min(Y[i], yMin)
+ yMax = IfThenElse(Y[i] > yMax, Int(Y[i]), yMax); // FIXME: Max(Y[i], yMax)
+
+ i++;
+ }
+ Until(i >= n)
+
+ if(state.multiSample > 1)
+ {
+ yMin = (yMin + 0x0A) >> 4;
+ yMax = (yMax + 0x14) >> 4;
+ }
+ else
+ {
+ yMin = (yMin + 0x0F) >> 4;
+ yMax = (yMax + 0x0F) >> 4;
+ }
+
+ If(yMin == yMax)
+ {
+ Return(false);
+ }
+
+ For(Int q = 0, q < state.multiSample, q++)
+ {
+ Array<Int> Xq(16);
+ Array<Int> Yq(16);
+
+ Int i = 0;
+
+ Do
+ {
+ Xq[i] = X[i];
+ Yq[i] = Y[i];
+
+ if(state.multiSample > 1)
+ {
+ Xq[i] = Xq[i] + *Pointer<Int>(constants + OFFSET(Constants,Xf) + q * sizeof(int));
+ Yq[i] = Yq[i] + *Pointer<Int>(constants + OFFSET(Constants,Yf) + q * sizeof(int));
+ }
+
+ i++;
+ }
+ Until(i >= n)
+
+ Pointer<Byte> leftEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->left)) + q * sizeof(Primitive);
+ Pointer<Byte> rightEdge = Pointer<Byte>(primitive + OFFSET(Primitive,outline->right)) + q * sizeof(Primitive);
+
+ if(state.multiSample > 1)
+ {
+ Short x = Short((X[0] + 0xF) >> 4);
+
+ For(Int y = yMin - 1, y < yMax + 1, y++)
+ {
+ *Pointer<Short>(leftEdge + y * sizeof(Primitive::Span)) = x;
+ *Pointer<Short>(rightEdge + y * sizeof(Primitive::Span)) = x;
+ }
+ }
+
+ Xq[n] = Xq[0];
+ Yq[n] = Yq[0];
+
+ // Rasterize
+ {
+ Int i = 0;
+
+ Do
+ {
+ edge(primitive, Int(Xq[i + 1 - d]), Int(Yq[i + 1 - d]), Int(Xq[i + d]), Int(Yq[i + d]), q);
+
+ i++;
+ }
+ Until(i >= n)
+ }
+
+ if(state.multiSample == 1)
+ {
+ For(yMin, yMin < yMax && *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + yMin * sizeof(Primitive::Span)), yMin++)
+ {
+ // Increments yMin
+ }
+
+ For(yMax, yMax > yMin && *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span)) == *Pointer<Short>(rightEdge + (yMax - 1) * sizeof(Primitive::Span)), yMax--)
+ {
+ // Decrements yMax
+ }
+
+ If(yMin == yMax)
+ {
+ Return(false);
+ }
+
+ *Pointer<Short>(leftEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
+ *Pointer<Short>(rightEdge + (yMin - 1) * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + yMin * sizeof(Primitive::Span));
+ *Pointer<Short>(leftEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
+ *Pointer<Short>(rightEdge + yMax * sizeof(Primitive::Span)) = *Pointer<Short>(leftEdge + (yMax - 1) * sizeof(Primitive::Span));
+ }
+ }
+
+ *Pointer<Int>(primitive + OFFSET(Primitive,yMin)) = yMin;
+ *Pointer<Int>(primitive + OFFSET(Primitive,yMax)) = yMax;
+
+ // Sort by minimum y
+ if(solidTriangle && logPrecision >= WHQL)
+ {
+ Float y0 = *Pointer<Float>(v0 + pos * 16 + 4);
+ Float y1 = *Pointer<Float>(v1 + pos * 16 + 4);
+ Float y2 = *Pointer<Float>(v2 + pos * 16 + 4);
+
+ Float yMin = Min(Min(y0, y1), y2);
+
+ conditionalRotate1(yMin == y1, v0, v1, v2);
+ conditionalRotate2(yMin == y2, v0, v1, v2);
+ }
+
+ // Sort by maximum w
+ if(solidTriangle)
+ {
+ Float w0 = *Pointer<Float>(v0 + pos * 16 + 12);
+ Float w1 = *Pointer<Float>(v1 + pos * 16 + 12);
+ Float w2 = *Pointer<Float>(v2 + pos * 16 + 12);
+
+ Float wMax = Max(Max(w0, w1), w2);
+
+ conditionalRotate1(wMax == w1, v0, v1, v2);
+ conditionalRotate2(wMax == w2, v0, v1, v2);
+ }
+
+ Float4 p0 = *Pointer<Float4>(v0 + pos * 16, 16);
+ Float4 p1 = *Pointer<Float4>(v1 + pos * 16, 16);
+ Float4 p2 = *Pointer<Float4>(v2 + pos * 16, 16);
+
+ Float w0 = p0.w;
+ Float w1 = p1.w;
+ Float w2 = p2.w;
+
+ Float4 w012;
+
+ w012.x = w0;
+ w012.y = w1;
+ w012.z = w2;
+ w012.w = 1;
+
+ Float rhw0 = *Pointer<Float>(v0 + OFFSET(Vertex,W));
+
+ Int X0 = *Pointer<Int>(v0 + OFFSET(Vertex,X));
+ Int X1 = *Pointer<Int>(v1 + OFFSET(Vertex,X));
+ Int X2 = *Pointer<Int>(v2 + OFFSET(Vertex,X));
+
+ Int Y0 = *Pointer<Int>(v0 + OFFSET(Vertex,Y));
+ Int Y1 = *Pointer<Int>(v1 + OFFSET(Vertex,Y));
+ Int Y2 = *Pointer<Int>(v2 + OFFSET(Vertex,Y));
+
+ if(line)
+ {
+ X2 = X1 + Y1 - Y0;
+ Y2 = Y1 + X0 - X1;
+ }
+
+ Float dx = Float(X0) * Float(1.0f / 16.0f);
+ Float dy = Float(Y0) * Float(1.0f / 16.0f);
+
+ X1 -= X0;
+ Y1 -= Y0;
+
+ X2 -= X0;
+ Y2 -= Y0;
+
+ Float x1 = w1 * Float(1.0f / 16.0f) * Float(X1);
+ Float y1 = w1 * Float(1.0f / 16.0f) * Float(Y1);
+
+ Float x2 = w2 * Float(1.0f / 16.0f) * Float(X2);
+ Float y2 = w2 * Float(1.0f / 16.0f) * Float(Y2);
+
+ Float a = x1 * y2 - x2 * y1;
+
+ Float4 xQuad = Float4(0, 1, 0, 1) - Float4(dx);
+ Float4 yQuad = Float4(0, 0, 1, 1) - Float4(dy);
+
+ *Pointer<Float4>(primitive + OFFSET(Primitive,xQuad), 16) = xQuad;
+ *Pointer<Float4>(primitive + OFFSET(Primitive,yQuad), 16) = yQuad;
+
+ Float4 M[3];
+
+ M[0] = Float4(0, 0, 0, 0);
+ M[1] = Float4(0, 0, 0, 0);
+ M[2] = Float4(0, 0, 0, 0);
+
+ M[0].z = rhw0;
+
+ If(a != Float(0.0f))
+ {
+ Float A = Float(1) / a;
+ Float D = A * rhw0;
+
+ M[0].x = (y1 * w2 - y2 * w1) * D;
+ M[0].y = (x2 * w1 - x1 * w2) * D;
+ // M[0].z = rhw0;
+ // M[0].w = 0;
+
+ M[1].x = y2 * A;
+ M[1].y = -x2 * A;
+ // M[1].z = 0;
+ // M[1].w = 0;
+
+ M[2].x = -y1 * A;
+ M[2].y = x1 * A;
+ // M[2].z = 0;
+ // M[2].w = 0;
+ }
+
+ if(state.perspective)
+ {
+ Float4 ABC = M[0] + M[1] + M[2];
+
+ Float4 A = ABC.x;
+ Float4 B = ABC.y;
+ Float4 C = ABC.z;
+
+ *Pointer<Float4>(primitive + OFFSET(Primitive,w.A), 16) = A;
+ *Pointer<Float4>(primitive + OFFSET(Primitive,w.B), 16) = B;
+ *Pointer<Float4>(primitive + OFFSET(Primitive,w.C), 16) = C;
+ }
+
+ if(state.interpolateDepth)
+ {
+ Float z0 = *Pointer<Float>(v0 + OFFSET(Vertex,Z));
+ Float z1 = *Pointer<Float>(v1 + OFFSET(Vertex,Z));
+ Float z2 = *Pointer<Float>(v2 + OFFSET(Vertex,Z));
+
+ z1 -= z0;
+ z2 -= z0;
+
+ Float4 A;
+ Float4 B;
+ Float4 C;
+
+ if(!point)
+ {
+ Float x1 = Float(X1) * Float(1.0f / 16.0f);
+ Float y1 = Float(Y1) * Float(1.0f / 16.0f);
+ Float x2 = Float(X2) * Float(1.0f / 16.0f);
+ Float y2 = Float(Y2) * Float(1.0f / 16.0f);
+
+ Float D = *Pointer<Float>(data + OFFSET(DrawData,depthRange)) / (x1 * y2 - x2 * y1);
+
+ Float a = (y2 * z1 - y1 * z2) * D;
+ Float b = (x1 * z2 - x2 * z1) * D;
+
+ A = Float4(a);
+ B = Float4(b);
+ }
+ else
+ {
+ A = Float4(0, 0, 0, 0);
+ B = Float4(0, 0, 0, 0);
+ }
+
+ *Pointer<Float4>(primitive + OFFSET(Primitive,z.A), 16) = A;
+ *Pointer<Float4>(primitive + OFFSET(Primitive,z.B), 16) = B;
+
+ Float c = z0;
+
+ if(state.isDrawTriangle && state.slopeDepthBias)
+ {
+ Float bias = Max(Abs(Float(A.x)), Abs(Float(B.x)));
+ bias *= *Pointer<Float>(data + OFFSET(DrawData,slopeDepthBias));
+
+ if(complementaryDepthBuffer)
+ {
+ bias = -bias;
+ }
+
+ c += bias;
+ }
+
+ C = Float4(c * *Pointer<Float>(data + OFFSET(DrawData,depthRange)) + *Pointer<Float>(data + OFFSET(DrawData,depthNear)));
+
+ *Pointer<Float4>(primitive + OFFSET(Primitive,z.C), 16) = C;
+ }
+
+ for(int interpolant = 0; interpolant < 11; interpolant++)
+ {
+ int componentCount = interpolant < 10 ? 4 : 1; // Fog only has one component
+
+ for(int component = 0; component < componentCount; component++)
+ {
+ int attribute = state.gradient[interpolant][component].attribute;
+ bool flat = state.gradient[interpolant][component].flat;
+ bool wrap = state.gradient[interpolant][component].wrap;
+
+ if(attribute < 12)
+ {
+ setupGradient(primitive, tri, w012, M, v0, v1, v2, OFFSET(Vertex,v[attribute][component]), OFFSET(Primitive,V[interpolant][component]), flat, sprite, state.perspective, wrap, component);
+ }
+ }
+ }
+
+ Return(true);
+ }
+
+ routine = function(L"SetupRoutine");
+ }
+
+ 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)
+ {
+ Float4 i;
+
+ if(!flat)
+ {
+ if(!sprite)
+ {
+ i.x = *Pointer<Float>(v0 + attribute);
+ i.y = *Pointer<Float>(v1 + attribute);
+ i.z = *Pointer<Float>(v2 + attribute);
+ i.w = 0;
+ }
+ else
+ {
+ if(component == 0) i.x = Float(0.5f);
+ if(component == 1) i.x = Float(0.5f);
+ if(component == 2) i.x = Float(0.0f);
+ if(component == 3) i.x = Float(1.0f);
+
+ if(component == 0) i.y = Float(1.0f);
+ if(component == 1) i.y = Float(0.5f);
+ if(component == 2) i.y = Float(0.0f);
+ if(component == 3) i.y = Float(1.0f);
+
+ if(component == 0) i.z = Float(0.5f);
+ if(component == 1) i.z = Float(0.0f);
+ if(component == 2) i.z = Float(0.0f);
+ if(component == 3) i.z = Float(1.0f);
+
+ i.w = 0;
+ }
+
+ if(wrap)
+ {
+ Float m;
+
+ m = *Pointer<Float>(v0 + attribute);
+ m = Max(m, *Pointer<Float>(v1 + attribute));
+ m = Max(m, *Pointer<Float>(v2 + attribute));
+ m -= Float(0.5f); // FIXME: m -= 0.5f;
+
+ // FIXME: Vectorize
+ If(Float(i.x) < m) i.x = Float(i.x) + Float(1.0f);
+ If(Float(i.y) < m) i.y = Float(i.y) + Float(1.0f);
+ If(Float(i.z) < m) i.z = Float(i.z) + Float(1.0f);
+ }
+
+ if(!perspective)
+ {
+ i *= w012;
+ }
+
+ Float4 A;
+ Float4 B;
+ Float4 C;
+
+ A = i.xxxx;
+ B = i.yyyy;
+ C = i.zzzz;
+
+ A *= m[0];
+ B *= m[1];
+ C *= m[2];
+
+ C = A + B + C;
+
+ A = C.xxxx;
+ B = C.yyyy;
+ C = C.zzzz;
+
+ *Pointer<Float4>(primitive + planeEquation + 0, 16) = A;
+ *Pointer<Float4>(primitive + planeEquation + 16, 16) = B;
+ *Pointer<Float4>(primitive + planeEquation + 32, 16) = C;
+ }
+ else
+ {
+ Float C = *Pointer<Float>(triangle + OFFSET(Triangle,v0) + attribute);
+
+ *Pointer<Float4>(primitive + planeEquation + 0, 16) = Float4(0, 0, 0, 0);
+ *Pointer<Float4>(primitive + planeEquation + 16, 16) = Float4(0, 0, 0, 0);
+ *Pointer<Float4>(primitive + planeEquation + 32, 16) = Float4(C);
+ }
+ }
+
+ void SetupRoutine::edge(Pointer<Byte> &primitive, Int &X1, Int &Y1, Int &X2, Int &Y2, Int &q)
+ {
+ If(Y1 != Y2)
+ {
+ Bool swap = Y2 < Y1;
+
+ Pointer<Byte> leftEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->left);
+ Pointer<Byte> rightEdge = primitive + q * sizeof(Primitive) + OFFSET(Primitive,outline->right);
+ Pointer<Byte> edge = IfThenElse(swap, rightEdge, leftEdge);
+
+ Int X0 = X1;
+ Int Y0 = Y1;
+ X1 = IfThenElse(swap, X2, X1);
+ X2 = IfThenElse(swap, X0, X2);
+ Y1 = IfThenElse(swap, Y2, Y1);
+ Y2 = IfThenElse(swap, Y0, Y2);
+
+ Int y1 = (Y1 + 0x0000000F) >> 4;
+ Int y2 = (Y2 + 0x0000000F) >> 4;
+
+ If(y1 != y2)
+ {
+ // Deltas
+ Int DX12 = X2 - X1;
+ Int DY12 = Y2 - Y1;
+
+ Int FDX12 = DX12 << 4;
+ Int FDY12 = DY12 << 4;
+
+ Int X = DX12 * (-Y1 & 0xF) + X1 * DY12;
+ Int x = X / FDY12; // Edge
+ Int d = X % FDY12; // Error-term
+ Int ceil = -d >> 31; // Ceiling division: remainder <= 0
+ x -= ceil;
+ d -= ceil & FDY12;
+
+ Int Q = FDX12 / FDY12; // Edge-step
+ Int R = FDX12 % FDY12; // Error-step
+ Int floor = R >> 31; // Flooring division: remainder >= 0
+ Q += floor;
+ R += floor & FDY12;
+
+ Int D = FDY12; // Error-overflow
+ Int y = y1;
+
+ Do
+ {
+ *Pointer<Short>(edge + y * sizeof(Primitive::Span)) = Short(x);
+
+ x += Q;
+ d += R;
+
+ Int overflow = -d >> 31;
+
+ d -= D & overflow;
+ x -= overflow;
+
+ y++;
+ }
+ Until(y >= y2)
+ }
+ }
+ }
+
+ void SetupRoutine::conditionalRotate1(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
+ {
+ #if 0 // Rely on LLVM optimization
+ If(condition)
+ {
+ Pointer<Byte> vX;
+
+ vX = v0;
+ v0 = v1;
+ v1 = v2;
+ v2 = vX;
+ }
+ #else
+ Pointer<Byte> vX = v0;
+ v0 = IfThenElse(condition, v1, v0);
+ v1 = IfThenElse(condition, v2, v1);
+ v2 = IfThenElse(condition, vX, v2);
+ #endif
+ }
+
+ void SetupRoutine::conditionalRotate2(Bool condition, Pointer<Byte> &v0, Pointer<Byte> &v1, Pointer<Byte> &v2)
+ {
+ #if 0 // Rely on LLVM optimization
+ If(condition)
+ {
+ Pointer<Byte> vX;
+
+ vX = v2;
+ v2 = v1;
+ v1 = v0;
+ v0 = vX;
+ }
+ #else
+ Pointer<Byte> vX = v2;
+ v2 = IfThenElse(condition, v1, v2);
+ v1 = IfThenElse(condition, v0, v1);
+ v0 = IfThenElse(condition, vX, v0);
+ #endif
+ }
+
+ Routine *SetupRoutine::getRoutine()
+ {
+ return routine;
+ }
+}