PageRenderTime 605ms CodeModel.GetById 131ms app.highlight 378ms RepoModel.GetById 85ms app.codeStats 1ms

/opengles/src/arm/GenLline.cpp

http://ftk.googlecode.com/
C++ | 1140 lines | 601 code | 295 blank | 244 comment | 13 complexity | f55f5c5fae19ac49ebd0a48591f3334a MD5 | raw file
   1// ==========================================================================
   2//
   3// GenLine.cpp			JIT Class for 3D Rendering Library
   4//
   5//						This file contains the rasterizer functions that
   6//						implement the runtime code generation support
   7//						for optimized scan line rasterization routines.
   8//
   9// --------------------------------------------------------------------------
  10//
  11// 12-29-2003		Hans-Martin Will	initial version
  12//
  13// --------------------------------------------------------------------------
  14//
  15// Copyright (c) 2004, Hans-Martin Will. All rights reserved.
  16// 
  17// Redistribution and use in source and binary forms, with or without 
  18// modification, are permitted provided that the following conditions are 
  19// met:
  20// 
  21//	 *  Redistributions of source code must retain the above copyright
  22// 		notice, this list of conditions and the following disclaimer. 
  23//   *	Redistributions in binary form must reproduce the above copyright
  24// 		notice, this list of conditions and the following disclaimer in the 
  25// 		documentation and/or other materials provided with the distribution. 
  26// 
  27// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  29// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  30// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
  31// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
  32// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  33// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
  35// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  36// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
  37// THE POSSIBILITY OF SUCH DAMAGE.
  38//
  39// ==========================================================================
  40
  41
  42#include "stdafx.h"
  43#include "CodeGenerator.h"
  44#include "Rasterizer.h"
  45#include "FunctionCache.h"
  46#include "Surface.h"
  47#include "Texture.h"
  48#include "codegen.h"
  49#include "instruction.h"
  50#include "emit.h"
  51#include "arm-dis.h"
  52
  53
  54using namespace EGL;
  55
  56
  57namespace {
  58
  59	inline cg_virtual_reg_t * LOAD_DATA(cg_block_t * block, cg_virtual_reg_t * base, I32 constant) {
  60		cg_virtual_reg_t * offset = cg_virtual_reg_create(block->proc, cg_reg_type_general);
  61		cg_virtual_reg_t * addr = cg_virtual_reg_create(block->proc, cg_reg_type_general);
  62		cg_virtual_reg_t * value = cg_virtual_reg_create(block->proc, cg_reg_type_general);
  63
  64		LDI(offset, constant);
  65		ADD(addr, base, offset);
  66		LDW(value, addr);
  67
  68		return value;
  69	}
  70
  71#define ALLOC_REG(reg) reg = cg_virtual_reg_create(procedure, cg_reg_type_general)
  72#define ALLOC_FLAGS(reg) reg = cg_virtual_reg_create(procedure, cg_reg_type_flags)
  73#define DECL_REG(reg) cg_virtual_reg_t * reg = cg_virtual_reg_create(procedure, cg_reg_type_general)
  74#define DECL_FLAGS(reg) cg_virtual_reg_t * reg = cg_virtual_reg_create(procedure, cg_reg_type_flags)
  75#define DECL_CONST_REG(reg, value) cg_virtual_reg_t * reg = cg_virtual_reg_create(procedure, cg_reg_type_general); LDI(reg, value)
  76
  77	U32 Log(U32 value) {
  78		U32 result = 0;
  79		U32 mask = 1;
  80
  81		while ((value & mask) != value) {
  82			++result;
  83			mask = (mask << 1) | 1;
  84		}
  85
  86		return result;
  87	}
  88}
  89
  90
  91
  92
  93void CodeGenerator :: GenerateRasterLine() {
  94
  95	cg_proc_t * procedure = cg_proc_create(m_Module);
  96
  97	// The signature of the generated function is:
  98	//	(const RasterInfo * info, const EdgePos& start, const EdgePos& end);
  99	// Do not pass in y coordinate but rather assume that raster info pointers have been
 100	// adjusted to point to current scanline in memory
 101	// In the edge buffers, z, tu and tv are actually divided by w
 102
 103	DECL_REG	(regInfo);		// virtual register containing info structure pointer
 104	DECL_REG	(regFrom);		// virtual register containing start RasterPos pointer
 105	DECL_REG	(regTo);		// virtual register containing end RasterPos pointer
 106
 107	procedure->num_args = 3;	// the previous three declarations make up the arguments
 108
 109	cg_block_t * block = cg_block_create(procedure, 1);
 110	cg_block_ref_t * blockRefEndProc = cg_block_ref_create(procedure);
 111
 112	cg_virtual_reg_t * regTexture = LOAD_DATA(block, regInfo, OFFSET_TEXTURES);
 113
 114	FragmentGenerationInfo info;
 115	size_t unit;
 116
 117	info.regInfo = regInfo;
 118
 119	info.regTexture[0] = regTexture;
 120
 121	for (unit = 1; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 122		DECL_CONST_REG	(regOffset, unit * 4);
 123		DECL_REG		(regTextureN);
 124
 125		ADD				(regTextureN, regTexture, regOffset);
 126
 127		info.regTexture[unit] = regTextureN;
 128	}
 129
 130	// EGL_Fixed deltaX = p_to.m_WindowCoords.x - p_from.m_WindowCoords.x;
 131	// EGL_Fixed deltaY = p_to.m_WindowCoords.y - p_from.m_WindowCoords.y;
 132	DECL_REG	(regDeltaX);
 133	DECL_REG	(regDeltaY);
 134
 135	cg_virtual_reg_t *	regToX		= LOAD_DATA(block, regTo, OFFSET_RASTER_POS_WINDOW_X);
 136	cg_virtual_reg_t *	regFromX	= LOAD_DATA(block, regFrom, OFFSET_RASTER_POS_WINDOW_X);
 137	cg_virtual_reg_t *	regToY		= LOAD_DATA(block, regTo, OFFSET_RASTER_POS_WINDOW_Y);
 138	cg_virtual_reg_t *	regFromY	= LOAD_DATA(block, regFrom, OFFSET_RASTER_POS_WINDOW_Y);
 139
 140	FSUB		(regDeltaX, regToX, regFromX);
 141	FSUB		(regDeltaY, regToY, regFromY);
 142
 143	DECL_REG	(regAbsDeltaX);
 144	DECL_REG	(regAbsDeltaY);
 145
 146	ABS			(regAbsDeltaX, regDeltaX);
 147	ABS			(regAbsDeltaY, regDeltaY);
 148
 149	// if (EGL_Abs(deltaX) > EGL_Abs(deltaY)) {
 150
 151	DECL_FLAGS	(regCompareXY);
 152	FCMP		(regCompareXY, regAbsDeltaY, regAbsDeltaX);
 153
 154	cg_block_ref_t * blockRefRasterY = cg_block_ref_create(procedure);
 155
 156	BGT			(regCompareXY, blockRefRasterY);
 157
 158		// Bresenham along x-axis
 159	block = cg_block_create(procedure, 1);
 160
 161	{
 162		// 	const RasterPos *start, *end;
 163
 164		// 	I32 x;
 165		// 	I32 endX;
 166		// 	EGL_Fixed roundedX;
 167
 168		// 	if (deltaX < 0) {
 169		DECL_FLAGS		(regSignX);
 170		DECL_CONST_REG	(regZero, 0);
 171		
 172		FCMP		(regSignX, regDeltaX, regZero);
 173
 174		cg_block_ref_t * blockRefPositiveDeltaX = cg_block_ref_create(procedure);
 175
 176		BGE			(regSignX, blockRefPositiveDeltaX);
 177
 178		block = cg_block_create(procedure, 1);
 179
 180		// 		deltaY = -deltaY;
 181		// 		deltaX = -deltaX;
 182		DECL_REG	(regMinusDeltaX);
 183		DECL_REG	(regMinusDeltaY);
 184
 185		FNEG		(regMinusDeltaX, regDeltaX);
 186		FNEG		(regMinusDeltaY, regDeltaY);
 187
 188		// 		start = &p_to;
 189		// 		end = &p_from;
 190		DECL_REG	(regStart0);
 191		DECL_REG	(regEnd0);
 192
 193		OR			(regStart0, regTo, regTo);
 194		OR			(regEnd0, regFrom, regFrom);
 195
 196		// 		roundedX = EGL_NearestInt(p_to.m_WindowCoords.x + 1);
 197		// 		x = EGL_IntFromFixed(roundedX);
 198		// 		endX = EGL_IntFromFixed(p_from.m_WindowCoords.x + ((EGL_ONE)/2));
 199		DECL_REG	(regX0);
 200		DECL_REG	(regEndX0);
 201		DECL_CONST_REG	(regHalf, 0x8000);
 202		DECL_REG	(regXToPlusHalf0);
 203		DECL_REG	(regXFromPlusHalf0);
 204
 205		FADD		(regXToPlusHalf0, regToX, regHalf);
 206		TRUNC		(regX0, regXToPlusHalf0);
 207		FADD		(regXFromPlusHalf0, regFromX, regHalf);
 208		TRUNC		(regEndX0, regXFromPlusHalf0);
 209
 210		cg_block_ref_t * blockRefPostDeltaX = cg_block_ref_create(procedure);
 211
 212		BRA			(blockRefPostDeltaX);
 213
 214		// 	} else {
 215		block = cg_block_create(procedure, 1);
 216		blockRefPositiveDeltaX->block = block;
 217
 218		// 		start = &p_from;
 219		// 		end = &p_to;
 220		DECL_REG	(regStart1);
 221		DECL_REG	(regEnd1);
 222
 223		OR			(regStart1, regFrom, regFrom);
 224		OR			(regEnd1, regTo, regTo);
 225
 226		// 		roundedX = EGL_NearestInt(p_from.m_WindowCoords.x);
 227		// 		x = EGL_IntFromFixed(roundedX);
 228		// 		endX = EGL_IntFromFixed(p_to.m_WindowCoords.x + ((EGL_ONE)/2-1));
 229		DECL_REG	(regX1);
 230		DECL_REG	(regEndX1);
 231		DECL_CONST_REG	(regHalf1, 0x7fff);
 232		DECL_REG	(regXToPlusHalf1);
 233		DECL_REG	(regXFromPlusHalf1);
 234
 235		FADD		(regXToPlusHalf1, regToX, regHalf1);
 236		TRUNC		(regEndX1, regXToPlusHalf1);
 237		FADD		(regXFromPlusHalf1, regFromX, regHalf1);
 238		TRUNC		(regX1, regXFromPlusHalf1);
 239
 240		// 	}
 241
 242		block = cg_block_create(procedure, 1);
 243		blockRefPostDeltaX->block = block;
 244
 245		DECL_REG	(regCommonDeltaX);
 246		DECL_REG	(regCommonDeltaY);
 247
 248		PHI			(regCommonDeltaX, cg_create_virtual_reg_list(procedure->module->heap, regDeltaX, regMinusDeltaX, NULL));
 249		PHI			(regCommonDeltaY, cg_create_virtual_reg_list(procedure->module->heap, regDeltaY, regMinusDeltaY, NULL));
 250
 251		DECL_REG	(regCommonX);
 252		DECL_REG	(regCommonEndX);
 253
 254		PHI			(regCommonX, cg_create_virtual_reg_list(procedure->module->heap, regX0, regX1, NULL));
 255		PHI			(regCommonEndX, cg_create_virtual_reg_list(procedure->module->heap, regEndX0, regEndX1, NULL));
 256
 257		// 	const RasterPos& from = *start;
 258		// 	const RasterPos& to = *end;
 259
 260		DECL_REG	(regCommonFrom);
 261		DECL_REG	(regCommonTo);
 262
 263		PHI			(regCommonFrom, cg_create_virtual_reg_list(procedure->module->heap, regStart0, regStart1, NULL));
 264		PHI			(regCommonTo, cg_create_virtual_reg_list(procedure->module->heap, regEnd0, regEnd1, NULL));
 265
 266		// 	I32 yIncrement = (deltaY > 0) ? 1 : -1;
 267		DECL_FLAGS		(regSignY);
 268		
 269		FCMP		(regSignY, regCommonDeltaY, regZero);
 270
 271		cg_block_ref_t * blockRefPositiveDeltaY = cg_block_ref_create(procedure);
 272
 273		BGT			(regSignY, blockRefPositiveDeltaY);
 274
 275		block = cg_block_create(procedure, 1);
 276
 277		DECL_CONST_REG	(regYIncrementNeg, -1);
 278
 279		cg_block_ref_t * blockRefCommonDeltaY = cg_block_ref_create(procedure);
 280
 281		BRA			(blockRefCommonDeltaY);
 282
 283		block = cg_block_create(procedure, 1);
 284		blockRefPositiveDeltaY->block = block;
 285
 286		DECL_CONST_REG	(regYIncrementPos, 1);
 287
 288		block = cg_block_create(procedure, 1);
 289		blockRefCommonDeltaY->block = block;
 290
 291		DECL_REG		(regYIncrement);
 292		PHI				(regYIncrement, cg_create_virtual_reg_list(procedure->module->heap, regYIncrementPos, regYIncrementNeg, NULL));
 293
 294			// -- initialize with starting vertex attributes
 295		// 	FractionalColor baseColor = from.m_Color;
 296		// 	EGL_Fixed OneOverZ = from.m_WindowCoords.invZ;
 297		// 	EGL_Fixed tuOverZ = EGL_Mul(from.m_TextureCoords.tu, OneOverZ);
 298		// 	EGL_Fixed tvOverZ = EGL_Mul(from.m_TextureCoords.tv, OneOverZ);
 299		// 	EGL_Fixed fogDensity = from.m_FogDensity;
 300		// 	EGL_Fixed depth = from.m_WindowCoords.depth;
 301
 302		cg_virtual_reg_t * regColorR0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_COLOR_R);
 303		cg_virtual_reg_t * regColorG0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_COLOR_G);
 304		cg_virtual_reg_t * regColorB0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_COLOR_B);
 305		cg_virtual_reg_t * regColorA0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_COLOR_A);
 306		cg_virtual_reg_t * regInvZ0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_WINDOW_INV_Z);
 307		cg_virtual_reg_t * regFog0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_FOG);
 308		cg_virtual_reg_t * regDepth0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_WINDOW_DEPTH);
 309
 310		cg_virtual_reg_t * regTu0[EGL_NUM_TEXTURE_UNITS];
 311		cg_virtual_reg_t * regTv0[EGL_NUM_TEXTURE_UNITS];
 312		cg_virtual_reg_t * regTuOverZ0[EGL_NUM_TEXTURE_UNITS];
 313		cg_virtual_reg_t * regTvOverZ0[EGL_NUM_TEXTURE_UNITS];
 314
 315		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 316			regTu0[unit] = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_TEX_TU + unit * sizeof(TexCoord));
 317			regTv0[unit] = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_TEX_TV + unit * sizeof(TexCoord));
 318
 319			ALLOC_REG(regTuOverZ0[unit]);
 320			ALLOC_REG(regTvOverZ0[unit]);
 321
 322			FMUL		(regTuOverZ0[unit], regTu0[unit], regInvZ0);
 323			FMUL		(regTvOverZ0[unit], regTv0[unit], regInvZ0);
 324		}
 325
 326
 327			// -- end initialize
 328
 329		// 	EGL_Fixed invSpan = EGL_Inverse(deltaX);
 330		// 	EGL_Fixed slope = EGL_Mul(EGL_Abs(deltaY), invSpan);
 331		// 	EGL_Fixed OneOverZTo = to.m_WindowCoords.invZ;
 332		DECL_REG	(regInvSpan);
 333		DECL_REG	(regSlope);
 334
 335		FINV		(regInvSpan, regCommonDeltaX);
 336		FMUL		(regSlope, regAbsDeltaY, regInvSpan);
 337
 338		cg_virtual_reg_t * regEndColorR0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_COLOR_R);
 339		cg_virtual_reg_t * regEndColorG0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_COLOR_G);
 340		cg_virtual_reg_t * regEndColorB0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_COLOR_B);
 341		cg_virtual_reg_t * regEndColorA0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_COLOR_A);
 342		cg_virtual_reg_t * regEndInvZ0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_WINDOW_INV_Z);
 343		cg_virtual_reg_t * regEndFog0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_FOG);
 344		cg_virtual_reg_t * regEndDepth0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_WINDOW_DEPTH);
 345
 346		cg_virtual_reg_t * regEndTu0[EGL_NUM_TEXTURE_UNITS];
 347		cg_virtual_reg_t * regEndTv0[EGL_NUM_TEXTURE_UNITS];
 348		cg_virtual_reg_t * regEndTuOverZ0[EGL_NUM_TEXTURE_UNITS];
 349		cg_virtual_reg_t * regEndTvOverZ0[EGL_NUM_TEXTURE_UNITS];
 350
 351		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 352			regEndTu0[unit] = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_TEX_TU + unit * sizeof(TexCoord));
 353			regEndTv0[unit] = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_TEX_TV + unit * sizeof(TexCoord));
 354
 355			ALLOC_REG(regEndTuOverZ0[unit]);
 356			ALLOC_REG(regEndTvOverZ0[unit]);
 357
 358			FMUL		(regEndTuOverZ0[unit], regEndTu0[unit], regEndInvZ0);
 359			FMUL		(regEndTvOverZ0[unit], regEndTv0[unit], regEndInvZ0);
 360		}
 361
 362		// -- increments(to, from, invSpan)
 363
 364		// 	FractionalColor colorIncrement = (to.m_Color - from.m_Color) * invSpan;
 365		// 	EGL_Fixed deltaFog = EGL_Mul(to.m_FogDensity - from.m_FogDensity, invSpan);
 366
 367		// 	EGL_Fixed deltaZ = EGL_Mul(OneOverZTo - OneOverZ, invSpan);
 368
 369		// 	EGL_Fixed deltaU = EGL_Mul(EGL_Mul(to.m_TextureCoords.tu, OneOverZTo) -
 370		// 							   EGL_Mul(from.m_TextureCoords.tu, OneOverZ), invSpan);
 371
 372		// 	EGL_Fixed deltaV = EGL_Mul(EGL_Mul(to.m_TextureCoords.tv, OneOverZTo) -
 373		// 							   EGL_Mul(from.m_TextureCoords.tv, OneOverZ), invSpan);
 374
 375		// 	EGL_Fixed deltaDepth = EGL_Mul(to.m_WindowCoords.depth - from.m_WindowCoords.depth, invSpan);
 376
 377		DECL_REG		(regDiffColorR);
 378		DECL_REG		(regDeltaColorR);
 379		DECL_REG		(regDiffColorG);
 380		DECL_REG		(regDeltaColorG);
 381		DECL_REG		(regDiffColorB);
 382		DECL_REG		(regDeltaColorB);
 383		DECL_REG		(regDiffColorA);
 384		DECL_REG		(regDeltaColorA);
 385		DECL_REG		(regDiffFog);
 386		DECL_REG		(regDeltaFog);
 387		DECL_REG		(regDiffDepth);
 388		DECL_REG		(regDeltaDepth);
 389
 390		FSUB			(regDiffColorR, regEndColorR0, regColorR0);
 391		FMUL			(regDeltaColorR, regDiffColorR, regInvSpan);
 392		FSUB			(regDiffColorG, regEndColorG0, regColorG0);
 393		FMUL			(regDeltaColorG, regDiffColorG, regInvSpan);
 394		FSUB			(regDiffColorB, regEndColorB0, regColorB0);
 395		FMUL			(regDeltaColorB, regDiffColorB, regInvSpan);
 396		FSUB			(regDiffColorA, regEndColorA0, regColorA0);
 397		FMUL			(regDeltaColorA, regDiffColorA, regInvSpan);
 398
 399		FSUB			(regDiffFog, regEndFog0, regFog0);
 400		FMUL			(regDeltaFog, regDiffFog, regInvSpan);
 401		FSUB			(regDiffDepth, regEndDepth0, regDepth0);
 402		FMUL			(regDeltaDepth, regDiffDepth, regInvSpan);
 403
 404		DECL_REG		(regDiffInvZ);
 405		DECL_REG		(regDeltaInvZ);
 406
 407		FSUB			(regDiffInvZ, regEndInvZ0, regInvZ0);
 408		FMUL			(regDeltaInvZ, regDiffInvZ, regInvSpan);
 409
 410		cg_virtual_reg_t * regDiffTuOverZ[EGL_NUM_TEXTURE_UNITS];
 411		cg_virtual_reg_t * regDeltaTuOverZ[EGL_NUM_TEXTURE_UNITS];
 412		cg_virtual_reg_t * regDiffTvOverZ[EGL_NUM_TEXTURE_UNITS];
 413		cg_virtual_reg_t * regDeltaTvOverZ[EGL_NUM_TEXTURE_UNITS];
 414
 415		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 416			ALLOC_REG		(regDiffTuOverZ[unit]);
 417			ALLOC_REG		(regDeltaTuOverZ[unit]);
 418			ALLOC_REG		(regDiffTvOverZ[unit]);
 419			ALLOC_REG		(regDeltaTvOverZ[unit]);
 420
 421			FSUB			(regDiffTuOverZ[unit], regEndTuOverZ0[unit], regTuOverZ0[unit]);
 422			FMUL			(regDeltaTuOverZ[unit], regDiffTuOverZ[unit], regInvSpan);
 423			FSUB			(regDiffTvOverZ[unit], regEndTvOverZ0[unit], regTvOverZ0[unit]);
 424			FMUL			(regDeltaTvOverZ[unit], regDiffTvOverZ[unit], regInvSpan);
 425		}
 426		// -- end increments
 427
 428		// 	I32 y = EGL_IntFromFixed(from.m_WindowCoords.y + ((EGL_ONE)/2-1));
 429		cg_virtual_reg_t * regFromY0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_WINDOW_Y);
 430
 431		DECL_CONST_REG	(regHalf2, 0x7fff);
 432		DECL_REG		(regFromY0PlusHalf);
 433		DECL_REG		(regY0);
 434
 435		FADD			(regFromY0PlusHalf, regFromY0, regHalf2);
 436		TRUNC			(regY0, regFromY0PlusHalf);
 437
 438		// 	EGL_Fixed error = 0;
 439		DECL_CONST_REG	(regError0, 0);
 440
 441		block = cg_block_create(procedure, 4);
 442		cg_block_ref_t * blockRefBeginLoop = cg_block_ref_create(procedure);
 443		blockRefBeginLoop->block = block;
 444
 445		// 	for (; x < endX; ++x) {
 446
 447		// --- variables for loop entry
 448		DECL_REG		(regLoopX);
 449		DECL_REG		(regLoopY);
 450		DECL_REG		(regLoopError);
 451
 452		DECL_REG		(regLoopOneOverZ);
 453
 454		DECL_REG		(regLoopColorR);
 455		DECL_REG		(regLoopColorG);
 456		DECL_REG		(regLoopColorB);
 457		DECL_REG		(regLoopColorA);
 458
 459		DECL_REG		(regLoopDepth);
 460		DECL_REG		(regLoopFog);
 461
 462		// --- variables for loop exit
 463		DECL_REG		(regEndLoopX);
 464		DECL_REG		(regEndLoopY);
 465		DECL_REG		(regEndLoopError);
 466
 467		DECL_REG		(regEndLoopOneOverZ);
 468
 469		DECL_REG		(regEndLoopColorR);
 470		DECL_REG		(regEndLoopColorG);
 471		DECL_REG		(regEndLoopColorB);
 472		DECL_REG		(regEndLoopColorA);
 473
 474		DECL_REG		(regEndLoopDepth);
 475		DECL_REG		(regEndLoopFog);
 476
 477		PHI				(regLoopX, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopX, regCommonX, NULL));
 478		PHI				(regLoopY, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopY, regY0, NULL));
 479		PHI				(regLoopError, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopError, regError0, NULL));
 480
 481		PHI				(regLoopOneOverZ, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopOneOverZ, regInvZ0, NULL));
 482
 483		PHI				(regLoopColorR, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopColorR, regColorR0, NULL));
 484		PHI				(regLoopColorG, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopColorG, regColorG0, NULL));
 485		PHI				(regLoopColorB, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopColorB, regColorB0, NULL));
 486		PHI				(regLoopColorA, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopColorA, regColorA0, NULL));
 487
 488		PHI				(regLoopDepth, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopDepth, regDepth0, NULL));
 489		PHI				(regLoopFog, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopFog, regFog0, NULL));
 490
 491		cg_virtual_reg_t * regLoopTuOverZ[EGL_NUM_TEXTURE_UNITS];
 492		cg_virtual_reg_t * regLoopTvOverZ[EGL_NUM_TEXTURE_UNITS];
 493		cg_virtual_reg_t * regEndLoopTuOverZ[EGL_NUM_TEXTURE_UNITS];
 494		cg_virtual_reg_t * regEndLoopTvOverZ[EGL_NUM_TEXTURE_UNITS];
 495
 496		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 497			ALLOC_REG		(regLoopTuOverZ[unit]);
 498			ALLOC_REG		(regLoopTvOverZ[unit]);
 499			ALLOC_REG		(regEndLoopTuOverZ[unit]);
 500			ALLOC_REG		(regEndLoopTvOverZ[unit]);
 501
 502			PHI				(regLoopTuOverZ[unit], cg_create_virtual_reg_list(procedure->module->heap, regEndLoopTuOverZ[unit], regTuOverZ0[unit], NULL));
 503			PHI				(regLoopTvOverZ[unit], cg_create_virtual_reg_list(procedure->module->heap, regEndLoopTvOverZ[unit], regTvOverZ0[unit], NULL));
 504		}
 505		
 506		// 		EGL_Fixed z = EGL_Inverse(OneOverZ);
 507		// 		OneOverZ += deltaZ;
 508
 509		DECL_REG		(regLoopZ);
 510		FINV			(regLoopZ, regLoopOneOverZ);
 511		FADD			(regEndLoopOneOverZ, regLoopOneOverZ, regDeltaInvZ);
 512
 513		cg_virtual_reg_t * regLoopTu[EGL_NUM_TEXTURE_UNITS];
 514		cg_virtual_reg_t * regLoopTv[EGL_NUM_TEXTURE_UNITS];
 515
 516		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 517			ALLOC_REG		(regLoopTu[unit]);
 518			ALLOC_REG		(regLoopTv[unit]);
 519
 520			// 		EGL_Fixed tu = EGL_Mul(tuOverZ, z);
 521			// 		EGL_Fixed tv = EGL_Mul(tvOverZ, z);
 522			// 		tuOverZ += deltaU;
 523			// 		tvOverZ += deltaV;
 524			FMUL			(regLoopTu[unit], regLoopTuOverZ[unit], regLoopZ);
 525			FADD			(regEndLoopTuOverZ[unit], regLoopTuOverZ[unit], regDeltaTuOverZ[unit]);
 526			FMUL			(regLoopTv[unit], regLoopTvOverZ[unit], regLoopZ);
 527			FADD			(regEndLoopTvOverZ[unit], regLoopTvOverZ[unit], regDeltaTvOverZ[unit]);
 528
 529			info.regU[unit] = regLoopTu[unit];
 530			info.regV[unit] = regLoopTv[unit]; 
 531		}
 532
 533
 534		// 		Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
 535		info.regX = regLoopX;
 536		info.regY = regLoopY;
 537
 538		info.regFog = regLoopFog;
 539		info.regDepth = regLoopDepth;
 540		info.regR = regLoopColorR;
 541		info.regG = regLoopColorG;
 542		info.regB = regLoopColorB;
 543		info.regA = regLoopColorA;
 544
 545		cg_block_ref_t * postFragment = cg_block_ref_create(procedure);
 546
 547		GenerateFragment(procedure, block, postFragment, info, 5, true);
 548
 549		block = cg_block_create(procedure, 5);
 550		postFragment->block = block;
 551
 552		// 		error += slope;
 553
 554		DECL_REG		(regIncError);
 555		FADD			(regIncError, regLoopError, regSlope);
 556
 557		// 		if (error > EGL_ONE) {
 558		DECL_CONST_REG	(regLoopOne, EGL_ONE);
 559		DECL_FLAGS		(regErrorOverflow);
 560		FCMP			(regErrorOverflow, regIncError, regLoopOne);
 561		cg_block_ref_t * noOverflow = cg_block_ref_create(procedure);
 562
 563		BLE				(regErrorOverflow, noOverflow);
 564
 565		block = cg_block_create(procedure, 5);
 566
 567		// 			y += yIncrement;
 568		// 			error -= EGL_ONE;
 569		DECL_REG		(regIncY);
 570		DECL_REG		(regCorrectedError);
 571
 572		FADD			(regIncY, regLoopY, regYIncrement);
 573		FSUB			(regCorrectedError, regIncError, regLoopOne);
 574		// 		}
 575
 576		block = cg_block_create(procedure, 5);
 577		noOverflow->block = block;
 578
 579		PHI				(regEndLoopY, cg_create_virtual_reg_list(procedure->module->heap, regLoopY, regIncY, NULL));
 580		PHI				(regEndLoopError, cg_create_virtual_reg_list(procedure->module->heap, regIncError, regCorrectedError, NULL));
 581
 582		// 		baseColor += colorIncrement;
 583		FADD			(regEndLoopColorR,	regLoopColorR, regDeltaColorR);
 584		FADD			(regEndLoopColorG,	regLoopColorG, regDeltaColorG);
 585		FADD			(regEndLoopColorB,	regLoopColorB, regDeltaColorB);
 586		FADD			(regEndLoopColorA,	regLoopColorA, regDeltaColorA);
 587
 588		// 		depth += deltaDepth;
 589		// 		fogDensity += deltaFog;
 590		FADD			(regEndLoopDepth,	regLoopDepth, regDeltaDepth);
 591		FADD			(regEndLoopFog,		regLoopFog, regDeltaFog);
 592
 593		DECL_CONST_REG	(regConstInt1, 1);
 594		DECL_FLAGS		(regCompareX);
 595		FADD			(regEndLoopX, regLoopX, regConstInt1);
 596		FCMP			(regCompareX, regEndLoopX, regCommonEndX);
 597		BLT				(regCompareX, blockRefBeginLoop);
 598
 599		// 	}
 600	}
 601
 602	BRA		(blockRefEndProc);
 603
 604	// } else {
 605		// Bresenham along y-axis
 606
 607	block = cg_block_create(procedure, 1);
 608	blockRefRasterY->block = block;
 609
 610	// 	const RasterPos *start, *end;
 611
 612	// 	I32 y;
 613	// 	I32 endY;
 614	// 	EGL_Fixed roundedY; //, preStepY;
 615
 616	// 	if (deltaY < 0) {
 617	// 		deltaY = -deltaY;
 618	// 		deltaX = -deltaX;
 619	// 		start = &p_to;
 620	// 		end = &p_from;
 621	// 		roundedY = EGL_NearestInt(p_to.m_WindowCoords.y + 1);
 622	// 		y = EGL_IntFromFixed(roundedY);
 623	// 		endY = EGL_IntFromFixed(p_from.m_WindowCoords.y + ((EGL_ONE)/2));
 624	// 	} else {
 625	// 		start = &p_from;
 626	// 		end = &p_to;
 627	// 		roundedY = EGL_NearestInt(p_from.m_WindowCoords.y);
 628	// 		y = EGL_IntFromFixed(roundedY);
 629	// 		endY = EGL_IntFromFixed(p_to.m_WindowCoords.y + ((EGL_ONE)/2-1));
 630	// 	}
 631
 632	// 	const RasterPos& from = *start;
 633	// 	const RasterPos& to = *end;
 634
 635		//-- initialize with from vertex attributes
 636	// 	FractionalColor baseColor = from.m_Color;
 637	// 	EGL_Fixed OneOverZ = from.m_WindowCoords.invZ;
 638	// 	EGL_Fixed tuOverZ = EGL_Mul(from.m_TextureCoords.tu, OneOverZ);
 639	// 	EGL_Fixed tvOverZ = EGL_Mul(from.m_TextureCoords.tv, OneOverZ);
 640	// 	EGL_Fixed fogDensity = from.m_FogDensity;
 641	// 	EGL_Fixed depth = from.m_WindowCoords.depth;
 642		//-- end initialize
 643
 644	// 	EGL_Fixed invSpan = EGL_Inverse(deltaY);
 645	// 	EGL_Fixed slope = EGL_Mul(EGL_Abs(deltaX), invSpan);
 646	// 	EGL_Fixed OneOverZTo = to.m_WindowCoords.invZ;
 647
 648		// -- increments(to, from, invSpan)
 649	// 	FractionalColor colorIncrement = (to.m_Color - from.m_Color) * invSpan;
 650	// 	EGL_Fixed deltaFog = EGL_Mul(to.m_FogDensity - from.m_FogDensity, invSpan);
 651
 652	// 	EGL_Fixed deltaZ = EGL_Mul(OneOverZTo - OneOverZ, invSpan);
 653
 654	// 	EGL_Fixed deltaU = EGL_Mul(EGL_Mul(to.m_TextureCoords.tu, OneOverZTo) -
 655	// 							   EGL_Mul(from.m_TextureCoords.tu, OneOverZ), invSpan);
 656
 657	// 	EGL_Fixed deltaV = EGL_Mul(EGL_Mul(to.m_TextureCoords.tv, OneOverZTo) -
 658	// 							   EGL_Mul(from.m_TextureCoords.tv, OneOverZ), invSpan);
 659
 660	// 	EGL_Fixed deltaDepth = EGL_Mul(to.m_WindowCoords.depth - from.m_WindowCoords.depth, invSpan);
 661		// -- end increments
 662
 663	// 	I32 x = EGL_IntFromFixed(from.m_WindowCoords.x + ((EGL_ONE)/2-1));
 664
 665	// 	I32 xIncrement = (deltaX > 0) ? 1 : -1;
 666	// 	EGL_Fixed error = 0;
 667
 668		// can have xIncrement; yIncrement; xBaseIncrement, yBaseIncrement
 669		// then both x/y loops become the same
 670		// question: how to add correct mipmap selection?
 671
 672	// 	for (; y < endY; ++y) {
 673
 674	// 		EGL_Fixed z = EGL_Inverse(OneOverZ);
 675	// 		EGL_Fixed tu = EGL_Mul(tuOverZ, z);
 676	// 		EGL_Fixed tv = EGL_Mul(tvOverZ, z);
 677
 678	// 		Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
 679
 680	// 		error += slope;
 681	// 		if (error > EGL_ONE) {
 682	// 			x += xIncrement;
 683	// 			error -= EGL_ONE;
 684	// 		}
 685
 686	// 		baseColor += colorIncrement;
 687	// 		depth += deltaDepth;
 688	// 		OneOverZ += deltaZ;
 689	// 		tuOverZ += deltaU;
 690	// 		tvOverZ += deltaV;
 691	// 		fogDensity += deltaFog;
 692	// 	}
 693	// }
 694
 695	{
 696		// 	const RasterPos *start, *end;
 697
 698		// 	I32 x;
 699		// 	I32 endX;
 700		// 	EGL_Fixed roundedX;
 701
 702		// 	if (deltaX < 0) {
 703		DECL_FLAGS		(regSignY);
 704		DECL_CONST_REG	(regZero, 0);
 705		
 706		FCMP		(regSignY, regDeltaY, regZero);
 707
 708		cg_block_ref_t * blockRefPositiveDeltaY = cg_block_ref_create(procedure);
 709
 710		BGE			(regSignY, blockRefPositiveDeltaY);
 711
 712		block = cg_block_create(procedure, 1);
 713
 714		// 		deltaY = -deltaY;
 715		// 		deltaX = -deltaX;
 716		DECL_REG	(regMinusDeltaX);
 717		DECL_REG	(regMinusDeltaY);
 718
 719		FNEG		(regMinusDeltaX, regDeltaX);
 720		FNEG		(regMinusDeltaY, regDeltaY);
 721
 722		// 		start = &p_to;
 723		// 		end = &p_from;
 724		DECL_REG	(regStart0);
 725		DECL_REG	(regEnd0);
 726
 727		OR			(regStart0, regTo, regTo);
 728		OR			(regEnd0, regFrom, regFrom);
 729
 730		// 		roundedX = EGL_NearestInt(p_to.m_WindowCoords.x + 1);
 731		// 		x = EGL_IntFromFixed(roundedX);
 732		// 		endX = EGL_IntFromFixed(p_from.m_WindowCoords.x + ((EGL_ONE)/2));
 733		DECL_REG	(regY0);
 734		DECL_REG	(regEndY0);
 735		DECL_CONST_REG	(regHalf, 0x8000);
 736		DECL_REG	(regYToPlusHalf0);
 737		DECL_REG	(regYFromPlusHalf0);
 738
 739		FADD		(regYToPlusHalf0, regToY, regHalf);
 740		TRUNC		(regY0, regYToPlusHalf0);
 741		FADD		(regYFromPlusHalf0, regFromY, regHalf);
 742		TRUNC		(regEndY0, regYFromPlusHalf0);
 743
 744		cg_block_ref_t * blockRefPostDeltaY = cg_block_ref_create(procedure);
 745
 746		BRA			(blockRefPostDeltaY);
 747
 748		// 	} else {
 749		block = cg_block_create(procedure, 1);
 750		blockRefPositiveDeltaY->block = block;
 751
 752		// 		start = &p_from;
 753		// 		end = &p_to;
 754		DECL_REG	(regStart1);
 755		DECL_REG	(regEnd1);
 756
 757		OR			(regStart1, regFrom, regFrom);
 758		OR			(regEnd1, regTo, regTo);
 759
 760		// 		roundedX = EGL_NearestInt(p_from.m_WindowCoords.x);
 761		// 		x = EGL_IntFromFixed(roundedX);
 762		// 		endX = EGL_IntFromFixed(p_to.m_WindowCoords.x + ((EGL_ONE)/2-1));
 763		DECL_REG	(regY1);
 764		DECL_REG	(regEndY1);
 765		DECL_CONST_REG	(regHalf1, 0x7fff);
 766		DECL_REG	(regYToPlusHalf1);
 767		DECL_REG	(regYFromPlusHalf1);
 768
 769		FADD		(regYToPlusHalf1, regToY, regHalf1);
 770		TRUNC		(regEndY1, regYToPlusHalf1);
 771		FADD		(regYFromPlusHalf1, regFromY, regHalf1);
 772		TRUNC		(regY1, regYFromPlusHalf1);
 773
 774		// 	}
 775
 776		block = cg_block_create(procedure, 1);
 777		blockRefPostDeltaY->block = block;
 778
 779		DECL_REG	(regCommonDeltaX);
 780		DECL_REG	(regCommonDeltaY);
 781
 782		PHI			(regCommonDeltaX, cg_create_virtual_reg_list(procedure->module->heap, regDeltaX, regMinusDeltaX, NULL));
 783		PHI			(regCommonDeltaY, cg_create_virtual_reg_list(procedure->module->heap, regDeltaY, regMinusDeltaY, NULL));
 784
 785		DECL_REG	(regCommonY);
 786		DECL_REG	(regCommonEndY);
 787
 788		PHI			(regCommonY, cg_create_virtual_reg_list(procedure->module->heap, regY0, regY1, NULL));
 789		PHI			(regCommonEndY, cg_create_virtual_reg_list(procedure->module->heap, regEndY0, regEndY1, NULL));
 790
 791		// 	const RasterPos& from = *start;
 792		// 	const RasterPos& to = *end;
 793
 794		DECL_REG	(regCommonFrom);
 795		DECL_REG	(regCommonTo);
 796
 797		PHI			(regCommonFrom, cg_create_virtual_reg_list(procedure->module->heap, regStart0, regStart1, NULL));
 798		PHI			(regCommonTo, cg_create_virtual_reg_list(procedure->module->heap, regEnd0, regEnd1, NULL));
 799
 800		// 	I32 yIncrement = (deltaY > 0) ? 1 : -1;
 801		DECL_FLAGS		(regSignX);
 802		
 803		FCMP		(regSignX, regCommonDeltaX, regZero);
 804
 805		cg_block_ref_t * blockRefPositiveDeltaX = cg_block_ref_create(procedure);
 806
 807		BGT			(regSignX, blockRefPositiveDeltaX);
 808
 809		block = cg_block_create(procedure, 1);
 810
 811		DECL_CONST_REG	(regXIncrementNeg, -1);
 812
 813		cg_block_ref_t * blockRefCommonDeltaX = cg_block_ref_create(procedure);
 814
 815		BRA			(blockRefCommonDeltaX);
 816
 817		block = cg_block_create(procedure, 1);
 818		blockRefPositiveDeltaX->block = block;
 819
 820		DECL_CONST_REG	(regXIncrementPos, 1);
 821
 822		block = cg_block_create(procedure, 1);
 823		blockRefCommonDeltaX->block = block;
 824
 825		DECL_REG		(regXIncrement);
 826		PHI				(regXIncrement, cg_create_virtual_reg_list(procedure->module->heap, regXIncrementPos, regXIncrementNeg, NULL));
 827
 828			// -- initialize with starting vertex attributes
 829		// 	FractionalColor baseColor = from.m_Color;
 830		// 	EGL_Fixed OneOverZ = from.m_WindowCoords.invZ;
 831		// 	EGL_Fixed tuOverZ = EGL_Mul(from.m_TextureCoords.tu, OneOverZ);
 832		// 	EGL_Fixed tvOverZ = EGL_Mul(from.m_TextureCoords.tv, OneOverZ);
 833		// 	EGL_Fixed fogDensity = from.m_FogDensity;
 834		// 	EGL_Fixed depth = from.m_WindowCoords.depth;
 835
 836		cg_virtual_reg_t * regColorR0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_COLOR_R);
 837		cg_virtual_reg_t * regColorG0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_COLOR_G);
 838		cg_virtual_reg_t * regColorB0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_COLOR_B);
 839		cg_virtual_reg_t * regColorA0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_COLOR_A);
 840		cg_virtual_reg_t * regInvZ0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_WINDOW_INV_Z);
 841		cg_virtual_reg_t * regFog0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_FOG);
 842		cg_virtual_reg_t * regDepth0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_WINDOW_DEPTH);
 843
 844		cg_virtual_reg_t * regTu0[EGL_NUM_TEXTURE_UNITS];
 845		cg_virtual_reg_t * regTv0[EGL_NUM_TEXTURE_UNITS];
 846		cg_virtual_reg_t * regTuOverZ0[EGL_NUM_TEXTURE_UNITS];
 847		cg_virtual_reg_t * regTvOverZ0[EGL_NUM_TEXTURE_UNITS];
 848
 849		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 850			regTu0[unit] = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_TEX_TU + unit * sizeof(TexCoord));
 851			regTv0[unit] = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_TEX_TV + unit * sizeof(TexCoord));
 852
 853			ALLOC_REG	(regTuOverZ0[unit]);
 854			ALLOC_REG	(regTvOverZ0[unit]);
 855
 856			FMUL		(regTuOverZ0[unit], regTu0[unit], regInvZ0);
 857			FMUL		(regTvOverZ0[unit], regTv0[unit], regInvZ0);
 858		}
 859
 860			// -- end initialize
 861
 862		// 	EGL_Fixed invSpan = EGL_Inverse(deltaX);
 863		// 	EGL_Fixed slope = EGL_Mul(EGL_Abs(deltaY), invSpan);
 864		// 	EGL_Fixed OneOverZTo = to.m_WindowCoords.invZ;
 865		DECL_REG	(regInvSpan);
 866		DECL_REG	(regSlope);
 867
 868		FINV		(regInvSpan, regCommonDeltaY);
 869		FMUL		(regSlope, regAbsDeltaX, regInvSpan);
 870
 871		cg_virtual_reg_t * regEndColorR0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_COLOR_R);
 872		cg_virtual_reg_t * regEndColorG0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_COLOR_G);
 873		cg_virtual_reg_t * regEndColorB0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_COLOR_B);
 874		cg_virtual_reg_t * regEndColorA0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_COLOR_A);
 875		cg_virtual_reg_t * regEndFog0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_FOG);
 876		cg_virtual_reg_t * regEndDepth0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_WINDOW_DEPTH);
 877		cg_virtual_reg_t * regEndInvZ0 = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_WINDOW_INV_Z);
 878
 879		cg_virtual_reg_t * regEndTu0[EGL_NUM_TEXTURE_UNITS];
 880		cg_virtual_reg_t * regEndTv0[EGL_NUM_TEXTURE_UNITS];
 881		cg_virtual_reg_t * regEndTuOverZ0[EGL_NUM_TEXTURE_UNITS];
 882		cg_virtual_reg_t * regEndTvOverZ0[EGL_NUM_TEXTURE_UNITS];
 883
 884		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 885			regEndTu0[unit] = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_TEX_TU + unit * sizeof(TexCoord));
 886			regEndTv0[unit] = LOAD_DATA(block, regCommonTo, OFFSET_RASTER_POS_TEX_TV + unit * sizeof(TexCoord));
 887
 888			ALLOC_REG	(regEndTuOverZ0[unit]);
 889			ALLOC_REG	(regEndTvOverZ0[unit]);
 890
 891			FMUL		(regEndTuOverZ0[unit], regEndTu0[unit], regEndInvZ0);
 892			FMUL		(regEndTvOverZ0[unit], regEndTv0[unit], regEndInvZ0);
 893		}
 894
 895
 896		// -- increments(to, from, invSpan)
 897
 898		// 	FractionalColor colorIncrement = (to.m_Color - from.m_Color) * invSpan;
 899		// 	EGL_Fixed deltaFog = EGL_Mul(to.m_FogDensity - from.m_FogDensity, invSpan);
 900
 901		// 	EGL_Fixed deltaZ = EGL_Mul(OneOverZTo - OneOverZ, invSpan);
 902
 903		// 	EGL_Fixed deltaU = EGL_Mul(EGL_Mul(to.m_TextureCoords.tu, OneOverZTo) -
 904		// 							   EGL_Mul(from.m_TextureCoords.tu, OneOverZ), invSpan);
 905
 906		// 	EGL_Fixed deltaV = EGL_Mul(EGL_Mul(to.m_TextureCoords.tv, OneOverZTo) -
 907		// 							   EGL_Mul(from.m_TextureCoords.tv, OneOverZ), invSpan);
 908
 909		// 	EGL_Fixed deltaDepth = EGL_Mul(to.m_WindowCoords.depth - from.m_WindowCoords.depth, invSpan);
 910
 911		DECL_REG		(regDiffColorR);
 912		DECL_REG		(regDeltaColorR);
 913		DECL_REG		(regDiffColorG);
 914		DECL_REG		(regDeltaColorG);
 915		DECL_REG		(regDiffColorB);
 916		DECL_REG		(regDeltaColorB);
 917		DECL_REG		(regDiffColorA);
 918		DECL_REG		(regDeltaColorA);
 919		DECL_REG		(regDiffFog);
 920		DECL_REG		(regDeltaFog);
 921		DECL_REG		(regDiffDepth);
 922		DECL_REG		(regDeltaDepth);
 923
 924		FSUB			(regDiffColorR, regEndColorR0, regColorR0);
 925		FMUL			(regDeltaColorR, regDiffColorR, regInvSpan);
 926		FSUB			(regDiffColorG, regEndColorG0, regColorG0);
 927		FMUL			(regDeltaColorG, regDiffColorG, regInvSpan);
 928		FSUB			(regDiffColorB, regEndColorB0, regColorB0);
 929		FMUL			(regDeltaColorB, regDiffColorB, regInvSpan);
 930		FSUB			(regDiffColorA, regEndColorA0, regColorA0);
 931		FMUL			(regDeltaColorA, regDiffColorA, regInvSpan);
 932
 933		FSUB			(regDiffFog, regEndFog0, regFog0);
 934		FMUL			(regDeltaFog, regDiffFog, regInvSpan);
 935		FSUB			(regDiffDepth, regEndDepth0, regDepth0);
 936		FMUL			(regDeltaDepth, regDiffDepth, regInvSpan);
 937
 938		DECL_REG		(regDiffInvZ);
 939		DECL_REG		(regDeltaInvZ);
 940
 941		FSUB			(regDiffInvZ, regEndInvZ0, regInvZ0);
 942		FMUL			(regDeltaInvZ, regDiffInvZ, regInvSpan);
 943
 944		cg_virtual_reg_t * regDiffTuOverZ[EGL_NUM_TEXTURE_UNITS];
 945		cg_virtual_reg_t * regDeltaTuOverZ[EGL_NUM_TEXTURE_UNITS];
 946		cg_virtual_reg_t * regDiffTvOverZ[EGL_NUM_TEXTURE_UNITS];
 947		cg_virtual_reg_t * regDeltaTvOverZ[EGL_NUM_TEXTURE_UNITS];
 948
 949		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
 950			ALLOC_REG		(regDiffTuOverZ[unit]);
 951			ALLOC_REG		(regDeltaTuOverZ[unit]);
 952			ALLOC_REG		(regDiffTvOverZ[unit]);
 953			ALLOC_REG		(regDeltaTvOverZ[unit]);
 954
 955			FSUB			(regDiffTuOverZ[unit], regEndTuOverZ0[unit], regTuOverZ0[unit]);
 956			FMUL			(regDeltaTuOverZ[unit], regDiffTuOverZ[unit], regInvSpan);
 957			FSUB			(regDiffTvOverZ[unit], regEndTvOverZ0[unit], regTvOverZ0[unit]);
 958			FMUL			(regDeltaTvOverZ[unit], regDiffTvOverZ[unit], regInvSpan);
 959		}
 960		// -- end increments
 961
 962		// 	I32 y = EGL_IntFromFixed(from.m_WindowCoords.y + ((EGL_ONE)/2-1));
 963		cg_virtual_reg_t * regFromX0 = LOAD_DATA(block, regCommonFrom, OFFSET_RASTER_POS_WINDOW_X);
 964
 965		DECL_CONST_REG	(regHalf2, 0x7fff);
 966		DECL_REG		(regFromX0PlusHalf);
 967		DECL_REG		(regX0);
 968
 969		FADD			(regFromX0PlusHalf, regFromX0, regHalf2);
 970		TRUNC			(regX0, regFromX0PlusHalf);
 971
 972		// 	EGL_Fixed error = 0;
 973		DECL_CONST_REG	(regError0, 0);
 974
 975		block = cg_block_create(procedure, 4);
 976		cg_block_ref_t * blockRefBeginLoop = cg_block_ref_create(procedure);
 977		blockRefBeginLoop->block = block;
 978
 979		// 	for (; x < endX; ++x) {
 980
 981		// --- variables for loop entry
 982		DECL_REG		(regLoopX);
 983		DECL_REG		(regLoopY);
 984		DECL_REG		(regLoopError);
 985
 986		DECL_REG		(regLoopOneOverZ);
 987
 988		DECL_REG		(regLoopColorR);
 989		DECL_REG		(regLoopColorG);
 990		DECL_REG		(regLoopColorB);
 991		DECL_REG		(regLoopColorA);
 992
 993		DECL_REG		(regLoopDepth);
 994		DECL_REG		(regLoopFog);
 995
 996		// --- variables for loop exit
 997		DECL_REG		(regEndLoopX);
 998		DECL_REG		(regEndLoopY);
 999		DECL_REG		(regEndLoopError);
1000
1001		DECL_REG		(regEndLoopOneOverZ);
1002
1003		DECL_REG		(regEndLoopColorR);
1004		DECL_REG		(regEndLoopColorG);
1005		DECL_REG		(regEndLoopColorB);
1006		DECL_REG		(regEndLoopColorA);
1007
1008		DECL_REG		(regEndLoopDepth);
1009		DECL_REG		(regEndLoopFog);
1010
1011		PHI				(regLoopX, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopX, regX0, NULL));
1012		PHI				(regLoopY, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopY, regCommonY, NULL));
1013		PHI				(regLoopError, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopError, regError0, NULL));
1014
1015		PHI				(regLoopOneOverZ, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopOneOverZ, regInvZ0, NULL));
1016
1017		PHI				(regLoopColorR, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopColorR, regColorR0, NULL));
1018		PHI				(regLoopColorG, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopColorG, regColorG0, NULL));
1019		PHI				(regLoopColorB, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopColorB, regColorB0, NULL));
1020		PHI				(regLoopColorA, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopColorA, regColorA0, NULL));
1021
1022		PHI				(regLoopDepth, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopDepth, regDepth0, NULL));
1023		PHI				(regLoopFog, cg_create_virtual_reg_list(procedure->module->heap, regEndLoopFog, regFog0, NULL));
1024		
1025		cg_virtual_reg_t * regLoopTuOverZ[EGL_NUM_TEXTURE_UNITS];
1026		cg_virtual_reg_t * regLoopTvOverZ[EGL_NUM_TEXTURE_UNITS];
1027		cg_virtual_reg_t * regEndLoopTuOverZ[EGL_NUM_TEXTURE_UNITS];
1028		cg_virtual_reg_t * regEndLoopTvOverZ[EGL_NUM_TEXTURE_UNITS];
1029
1030		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1031			ALLOC_REG		(regLoopTuOverZ[unit]);
1032			ALLOC_REG		(regLoopTvOverZ[unit]);
1033			ALLOC_REG		(regEndLoopTuOverZ[unit]);
1034			ALLOC_REG		(regEndLoopTvOverZ[unit]);
1035
1036			PHI				(regLoopTuOverZ[unit], cg_create_virtual_reg_list(procedure->module->heap, regEndLoopTuOverZ[unit], regTuOverZ0[unit], NULL));
1037			PHI				(regLoopTvOverZ[unit], cg_create_virtual_reg_list(procedure->module->heap, regEndLoopTvOverZ[unit], regTvOverZ0[unit], NULL));
1038		}
1039		
1040		// 		EGL_Fixed z = EGL_Inverse(OneOverZ);
1041		// 		OneOverZ += deltaZ;
1042
1043		DECL_REG		(regLoopZ);
1044		FINV			(regLoopZ, regLoopOneOverZ);
1045		FADD			(regEndLoopOneOverZ, regLoopOneOverZ, regDeltaInvZ);
1046
1047		cg_virtual_reg_t * regLoopTu[EGL_NUM_TEXTURE_UNITS];
1048		cg_virtual_reg_t * regLoopTv[EGL_NUM_TEXTURE_UNITS];
1049
1050		for (unit = 0; unit < EGL_NUM_TEXTURE_UNITS; ++unit) {
1051			ALLOC_REG		(regLoopTu[unit]);
1052			ALLOC_REG		(regLoopTv[unit]);
1053
1054			// 		EGL_Fixed tu = EGL_Mul(tuOverZ, z);
1055			// 		EGL_Fixed tv = EGL_Mul(tvOverZ, z);
1056			// 		tuOverZ += deltaU;
1057			// 		tvOverZ += deltaV;
1058			FMUL			(regLoopTu[unit], regLoopTuOverZ[unit], regLoopZ);
1059			FADD			(regEndLoopTuOverZ[unit], regLoopTuOverZ[unit], regDeltaTuOverZ[unit]);
1060			FMUL			(regLoopTv[unit], regLoopTvOverZ[unit], regLoopZ);
1061			FADD			(regEndLoopTvOverZ[unit], regLoopTvOverZ[unit], regDeltaTvOverZ[unit]);
1062
1063			info.regU[unit] = regLoopTu[unit];
1064			info.regV[unit] = regLoopTv[unit]; 
1065		}
1066
1067		// 		Fragment(x, y, depth, tu, tv, fogDensity, baseColor);
1068		info.regX = regLoopX;
1069		info.regY = regLoopY;
1070
1071		info.regFog = regLoopFog;
1072		info.regDepth = regLoopDepth;
1073		info.regR = regLoopColorR;
1074		info.regG = regLoopColorG;
1075		info.regB = regLoopColorB;
1076		info.regA = regLoopColorA;
1077
1078		cg_block_ref_t * postFragment = cg_block_ref_create(procedure);
1079
1080		GenerateFragment(procedure, block, postFragment, info, 5, true);
1081
1082		block = cg_block_create(procedure, 5);
1083		postFragment->block = block;
1084
1085		// 		error += slope;
1086
1087		DECL_REG		(regIncError);
1088		FADD			(regIncError, regLoopError, regSlope);
1089
1090		// 		if (error > EGL_ONE) {
1091		DECL_CONST_REG	(regLoopOne, EGL_ONE);
1092		DECL_FLAGS		(regErrorOverflow);
1093		FCMP			(regErrorOverflow, regIncError, regLoopOne);
1094		cg_block_ref_t * noOverflow = cg_block_ref_create(procedure);
1095
1096		BLE				(regErrorOverflow, noOverflow);
1097
1098		block = cg_block_create(procedure, 5);
1099
1100		// 			y += yIncrement;
1101		// 			error -= EGL_ONE;
1102		DECL_REG		(regIncX);
1103		DECL_REG		(regCorrectedError);
1104
1105		FADD			(regIncX, regLoopX, regXIncrement);
1106		FSUB			(regCorrectedError, regIncError, regLoopOne);
1107		// 		}
1108
1109		block = cg_block_create(procedure, 5);
1110		noOverflow->block = block;
1111
1112		PHI				(regEndLoopX, cg_create_virtual_reg_list(procedure->module->heap, regLoopX, regIncX, NULL));
1113		PHI				(regEndLoopError, cg_create_virtual_reg_list(procedure->module->heap, regIncError, regCorrectedError, NULL));
1114
1115		// 		baseColor += colorIncrement;
1116		FADD			(regEndLoopColorR,	regLoopColorR, regDeltaColorR);
1117		FADD			(regEndLoopColorG,	regLoopColorG, regDeltaColorG);
1118		FADD			(regEndLoopColorB,	regLoopColorB, regDeltaColorB);
1119		FADD			(regEndLoopColorA,	regLoopColorA, regDeltaColorA);
1120
1121		// 		depth += deltaDepth;
1122		// 		fogDensity += deltaFog;
1123		FADD			(regEndLoopDepth,	regLoopDepth, regDeltaDepth);
1124		FADD			(regEndLoopFog,		regLoopFog, regDeltaFog);
1125
1126		DECL_CONST_REG	(regConstInt1, 1);
1127		DECL_FLAGS		(regCompareY);
1128		FADD			(regEndLoopY, regLoopY, regConstInt1);
1129		FCMP			(regCompareY, regEndLoopY, regCommonEndY);
1130		BLT				(regCompareY, blockRefBeginLoop);
1131
1132		// 	}
1133	}
1134
1135	block = cg_block_create(procedure, 1);
1136	blockRefEndProc->block = block;
1137
1138	RET();
1139}
1140