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