| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496 |
- /**************************************************************************
- *
- * Copyright 2009 VMware, Inc.
- * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
- #include "pipe/p_config.h"
- #include "pipe/p_shader_tokens.h"
- #include "util/u_debug.h"
- #include "util/u_math.h"
- #include "util/u_memory.h"
- #include "tgsi/tgsi_info.h"
- #include "tgsi/tgsi_parse.h"
- #include "tgsi/tgsi_util.h"
- #include "tgsi/tgsi_exec.h"
- #include "lp_bld_type.h"
- #include "lp_bld_const.h"
- #include "lp_bld_intr.h"
- #include "lp_bld_arit.h"
- #include "lp_bld_logic.h"
- #include "lp_bld_swizzle.h"
- #include "lp_bld_tgsi.h"
- #include "lp_bld_debug.h"
-
-
- #define LP_MAX_TEMPS 256
- #define LP_MAX_IMMEDIATES 256
-
-
- #define FOR_EACH_CHANNEL( CHAN )\
- for (CHAN = 0; CHAN < NUM_CHANNELS; CHAN++)
-
- #define IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
- ((INST)->FullDstRegisters[0].DstRegister.WriteMask & (1 << (CHAN)))
-
- #define IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
- if (IS_DST0_CHANNEL_ENABLED( INST, CHAN ))
-
- #define FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\
- FOR_EACH_CHANNEL( CHAN )\
- IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )
-
- #define CHAN_X 0
- #define CHAN_Y 1
- #define CHAN_Z 2
- #define CHAN_W 3
-
-
- struct lp_build_tgsi_soa_context
- {
- struct lp_build_context base;
-
- LLVMValueRef x, y, w;
- LLVMValueRef a0_ptr;
- LLVMValueRef dadx_ptr;
- LLVMValueRef dady_ptr;
-
- LLVMValueRef consts_ptr;
- LLVMValueRef (*outputs)[NUM_CHANNELS];
- LLVMValueRef samplers_ptr;
-
- LLVMValueRef oow;
-
- LLVMValueRef inputs[PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS];
-
- LLVMValueRef immediates[LP_MAX_IMMEDIATES][NUM_CHANNELS];
- LLVMValueRef temps[LP_MAX_TEMPS][NUM_CHANNELS];
-
- LLVMValueRef mask;
-
- /** Coords/texels store */
- LLVMValueRef store_ptr;
- };
-
-
- /**
- * Register fetch.
- */
- static LLVMValueRef
- emit_fetch(
- struct lp_build_tgsi_soa_context *bld,
- const struct tgsi_full_instruction *inst,
- unsigned index,
- const unsigned chan_index )
- {
- const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[index];
- unsigned swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index );
- LLVMValueRef res;
-
- switch (swizzle) {
- case TGSI_EXTSWIZZLE_X:
- case TGSI_EXTSWIZZLE_Y:
- case TGSI_EXTSWIZZLE_Z:
- case TGSI_EXTSWIZZLE_W:
-
- switch (reg->SrcRegister.File) {
- case TGSI_FILE_CONSTANT: {
- LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), reg->SrcRegister.Index*4 + swizzle, 0);
- LLVMValueRef scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr, &index, 1, "");
- LLVMValueRef scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
- res = lp_build_broadcast_scalar(&bld->base, scalar);
- break;
- }
-
- case TGSI_FILE_IMMEDIATE:
- res = bld->immediates[reg->SrcRegister.Index][swizzle];
- assert(res);
- break;
-
- case TGSI_FILE_INPUT:
- res = bld->inputs[reg->SrcRegister.Index][swizzle];
- assert(res);
- break;
-
- case TGSI_FILE_TEMPORARY:
- res = bld->temps[reg->SrcRegister.Index][swizzle];
- if(!res)
- return bld->base.undef;
- break;
-
- default:
- assert( 0 );
- return bld->base.undef;
- }
- break;
-
- case TGSI_EXTSWIZZLE_ZERO:
- res = bld->base.zero;
- break;
-
- case TGSI_EXTSWIZZLE_ONE:
- res = bld->base.one;
- break;
-
- default:
- assert( 0 );
- return bld->base.undef;
- }
-
- switch( tgsi_util_get_full_src_register_sign_mode( reg, chan_index ) ) {
- case TGSI_UTIL_SIGN_CLEAR:
- res = lp_build_abs( &bld->base, res );
- break;
-
- case TGSI_UTIL_SIGN_SET:
- res = lp_build_abs( &bld->base, res );
- res = LLVMBuildNeg( bld->base.builder, res, "" );
- break;
-
- case TGSI_UTIL_SIGN_TOGGLE:
- res = LLVMBuildNeg( bld->base.builder, res, "" );
- break;
-
- case TGSI_UTIL_SIGN_KEEP:
- break;
- }
-
- return res;
- }
-
-
- /**
- * Register store.
- */
- static void
- emit_store(
- struct lp_build_tgsi_soa_context *bld,
- const struct tgsi_full_instruction *inst,
- unsigned index,
- unsigned chan_index,
- LLVMValueRef value)
- {
- const struct tgsi_full_dst_register *reg = &inst->FullDstRegisters[index];
-
- switch( inst->Instruction.Saturate ) {
- case TGSI_SAT_NONE:
- break;
-
- case TGSI_SAT_ZERO_ONE:
- value = lp_build_max(&bld->base, value, bld->base.zero);
- value = lp_build_min(&bld->base, value, bld->base.one);
- break;
-
- case TGSI_SAT_MINUS_PLUS_ONE:
- value = lp_build_max(&bld->base, value, lp_build_const_uni(bld->base.type, -1.0));
- value = lp_build_min(&bld->base, value, bld->base.one);
- break;
-
- default:
- assert(0);
- }
-
- switch( reg->DstRegister.File ) {
- case TGSI_FILE_OUTPUT:
- bld->outputs[reg->DstRegister.Index][chan_index] = value;
- break;
-
- case TGSI_FILE_TEMPORARY:
- bld->temps[reg->DstRegister.Index][chan_index] = value;
- break;
-
- case TGSI_FILE_ADDRESS:
- /* FIXME */
- assert(0);
- break;
-
- default:
- assert( 0 );
- }
- }
-
-
- void PIPE_CDECL
- lp_build_tgsi_fetch_texel_soa( struct tgsi_sampler **samplers,
- uint32_t unit,
- float *store )
- {
- struct tgsi_sampler *sampler = samplers[unit];
-
- #if 0
- uint j;
-
- debug_printf("%s sampler: %p (%p) store: %p\n",
- __FUNCTION__,
- sampler, *sampler,
- store );
-
- debug_printf("lodbias %f\n", store[12]);
-
- for (j = 0; j < 4; j++)
- debug_printf("sample %d texcoord %f %f\n",
- j,
- store[0+j],
- store[4+j]);
- #endif
-
- {
- float rgba[NUM_CHANNELS][QUAD_SIZE];
- sampler->get_samples(sampler,
- &store[0],
- &store[4],
- &store[8],
- 0.0f, /*store[12], lodbias */
- rgba);
- memcpy(store, rgba, sizeof rgba);
- }
-
- #if 0
- for (j = 0; j < 4; j++)
- debug_printf("sample %d result %f %f %f %f\n",
- j,
- store[0+j],
- store[4+j],
- store[8+j],
- store[12+j]);
- #endif
- }
-
- /**
- * High-level instruction translators.
- */
-
- static void
- emit_tex( struct lp_build_tgsi_soa_context *bld,
- const struct tgsi_full_instruction *inst,
- boolean apply_lodbias,
- boolean projected)
- {
- LLVMTypeRef vec_type = lp_build_vec_type(bld->base.type);
- const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
- LLVMValueRef lodbias;
- LLVMValueRef oow;
- LLVMValueRef args[3];
- unsigned count;
- unsigned i;
-
- switch (inst->InstructionExtTexture.Texture) {
- case TGSI_TEXTURE_1D:
- case TGSI_TEXTURE_SHADOW1D:
- count = 1;
- break;
- case TGSI_TEXTURE_2D:
- case TGSI_TEXTURE_RECT:
- case TGSI_TEXTURE_SHADOW2D:
- case TGSI_TEXTURE_SHADOWRECT:
- count = 2;
- break;
- case TGSI_TEXTURE_3D:
- case TGSI_TEXTURE_CUBE:
- count = 3;
- break;
- default:
- assert(0);
- return;
- }
-
- if(apply_lodbias)
- lodbias = emit_fetch( bld, inst, 0, 3 );
- else
- lodbias = bld->base.zero;
-
- if(!bld->store_ptr)
- bld->store_ptr = LLVMBuildArrayAlloca(bld->base.builder,
- vec_type,
- LLVMConstInt(LLVMInt32Type(), 4, 0),
- "store");
-
- if (projected) {
- oow = emit_fetch( bld, inst, 0, 3 );
- oow = lp_build_rcp(&bld->base, oow);
- }
-
- for (i = 0; i < count; i++) {
- LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
- LLVMValueRef coord_ptr = LLVMBuildGEP(bld->base.builder, bld->store_ptr, &index, 1, "");
- LLVMValueRef coord;
-
- coord = emit_fetch( bld, inst, 0, i );
-
- if (projected)
- coord = lp_build_mul(&bld->base, coord, oow);
-
- LLVMBuildStore(bld->base.builder, coord, coord_ptr);
- }
-
- args[0] = bld->samplers_ptr;
- args[1] = LLVMConstInt(LLVMInt32Type(), unit, 0);
- args[2] = bld->store_ptr;
-
- lp_build_intrinsic(bld->base.builder, "fetch_texel", LLVMVoidType(), args, 3);
-
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, i ) {
- LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
- LLVMValueRef res_ptr = LLVMBuildGEP(bld->base.builder, bld->store_ptr, &index, 1, "");
- LLVMValueRef res = LLVMBuildLoad(bld->base.builder, res_ptr, "");
- emit_store( bld, inst, 0, i, res );
- }
- }
-
-
- static void
- emit_kil(
- struct lp_build_tgsi_soa_context *bld,
- const struct tgsi_full_instruction *inst )
- {
- const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[0];
- LLVMValueRef terms[NUM_CHANNELS];
- unsigned chan_index;
-
- memset(&terms, 0, sizeof terms);
-
- FOR_EACH_CHANNEL( chan_index ) {
- unsigned swizzle;
-
- /* Unswizzle channel */
- swizzle = tgsi_util_get_full_src_register_extswizzle( reg, chan_index );
-
- /* Note that we test if the value is less than zero, so 1.0 and 0.0 need
- * not to be tested. */
- if(swizzle == TGSI_EXTSWIZZLE_ZERO || swizzle == TGSI_EXTSWIZZLE_ONE)
- continue;
-
- /* Check if the component has not been already tested. */
- assert(swizzle < NUM_CHANNELS);
- if( !terms[swizzle] )
- /* TODO: change the comparison operator instead of setting the sign */
- terms[swizzle] = emit_fetch(bld, inst, 0, chan_index );
- }
-
- FOR_EACH_CHANNEL( chan_index ) {
- if(terms[chan_index]) {
- LLVMValueRef mask;
-
- mask = lp_build_cmp(&bld->base, PIPE_FUNC_GEQUAL, terms[chan_index], bld->base.zero);
-
- if(bld->mask)
- bld->mask = LLVMBuildAnd(bld->base.builder, bld->mask, mask, "");
- else
- bld->mask = mask;
- }
- }
- }
-
-
- static void
- emit_kilp(
- struct lp_build_tgsi_soa_context *bld )
- {
- /* XXX todo / fix me */
- }
-
-
- /**
- * Check if inst src/dest regs use indirect addressing into temporary
- * register file.
- */
- static boolean
- indirect_temp_reference(const struct tgsi_full_instruction *inst)
- {
- uint i;
- for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
- const struct tgsi_full_src_register *reg = &inst->FullSrcRegisters[i];
- if (reg->SrcRegister.File == TGSI_FILE_TEMPORARY &&
- reg->SrcRegister.Indirect)
- return TRUE;
- }
- for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
- const struct tgsi_full_dst_register *reg = &inst->FullDstRegisters[i];
- if (reg->DstRegister.File == TGSI_FILE_TEMPORARY &&
- reg->DstRegister.Indirect)
- return TRUE;
- }
- return FALSE;
- }
-
-
- static int
- emit_instruction(
- struct lp_build_tgsi_soa_context *bld,
- struct tgsi_full_instruction *inst )
- {
- unsigned chan_index;
- LLVMValueRef src0, src1, src2;
- LLVMValueRef tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
- LLVMValueRef dst0;
-
- /* we can't handle indirect addressing into temp register file yet */
- if (indirect_temp_reference(inst))
- return FALSE;
-
- switch (inst->Instruction.Opcode) {
- #if 0
- case TGSI_OPCODE_ARL:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- emit_flr(bld, 0, 0);
- emit_f2it( bld, 0 );
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
- #endif
-
- case TGSI_OPCODE_MOV:
- case TGSI_OPCODE_SWZ:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_LIT:
- if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ) {
- emit_store( bld, inst, 0, CHAN_X, bld->base.one);
- }
- if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ) {
- src0 = emit_fetch( bld, inst, 0, CHAN_X );
- dst0 = lp_build_max( &bld->base, src0, bld->base.zero);
- emit_store( bld, inst, 0, CHAN_Y, dst0);
- }
- if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) {
- /* XMM[1] = SrcReg[0].yyyy */
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
- /* XMM[1] = max(XMM[1], 0) */
- tmp1 = lp_build_max( &bld->base, tmp1, bld->base.zero);
- /* XMM[2] = SrcReg[0].wwww */
- tmp2 = emit_fetch( bld, inst, 0, CHAN_W );
- tmp1 = lp_build_pow( &bld->base, tmp1, tmp2);
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp2 = lp_build_cmp(&bld->base, PIPE_FUNC_GREATER, tmp0, bld->base.zero);
- dst0 = lp_build_select(&bld->base, tmp2, tmp1, bld->base.zero);
- emit_store( bld, inst, 0, CHAN_Z, dst0);
- }
- if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) ) {
- emit_store( bld, inst, 0, CHAN_W, bld->base.one);
- }
- break;
-
- case TGSI_OPCODE_RCP:
- /* TGSI_OPCODE_RECIP */
- src0 = emit_fetch( bld, inst, 0, CHAN_X );
- dst0 = lp_build_rcp(&bld->base, src0);
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, dst0 );
- }
- break;
-
- case TGSI_OPCODE_RSQ:
- /* TGSI_OPCODE_RECIPSQRT */
- src0 = emit_fetch( bld, inst, 0, CHAN_X );
- src0 = lp_build_abs(&bld->base, src0);
- dst0 = lp_build_rsqrt(&bld->base, src0);
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, dst0 );
- }
- break;
-
- case TGSI_OPCODE_EXP:
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ||
- IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ||
- IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) {
- LLVMValueRef *p_exp2_int_part = NULL;
- LLVMValueRef *p_frac_part = NULL;
- LLVMValueRef *p_exp2 = NULL;
-
- src0 = emit_fetch( bld, inst, 0, CHAN_X );
-
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ))
- p_exp2_int_part = &tmp0;
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ))
- p_frac_part = &tmp1;
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ))
- p_exp2 = &tmp2;
-
- lp_build_exp2_approx(&bld->base, src0, p_exp2_int_part, p_frac_part, p_exp2);
-
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ))
- emit_store( bld, inst, 0, CHAN_X, tmp0);
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ))
- emit_store( bld, inst, 0, CHAN_Y, tmp1);
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ))
- emit_store( bld, inst, 0, CHAN_Z, tmp2);
- }
- /* dst.w = 1.0 */
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_W )) {
- tmp0 = bld->base.one;
- emit_store( bld, inst, 0, CHAN_W, tmp0);
- }
- break;
-
- case TGSI_OPCODE_LOG:
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ||
- IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ||
- IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) {
- LLVMValueRef *p_floor_log2;
- LLVMValueRef *p_exp;
- LLVMValueRef *p_log2;
-
- src0 = emit_fetch( bld, inst, 0, CHAN_X );
- src0 = lp_build_abs( &bld->base, src0 );
-
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ))
- p_floor_log2 = &tmp0;
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ))
- p_exp = &tmp1;
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ))
- p_log2 = &tmp2;
-
- lp_build_log2_approx(&bld->base, src0, p_exp, p_floor_log2, p_log2);
-
- /* dst.x = floor(lg2(abs(src.x))) */
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ))
- emit_store( bld, inst, 0, CHAN_X, tmp0);
- /* dst.y = abs(src)/ex2(floor(lg2(abs(src.x)))) */
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y )) {
- tmp1 = lp_build_div( &bld->base, src0, tmp1);
- emit_store( bld, inst, 0, CHAN_Y, tmp1);
- }
- /* dst.z = lg2(abs(src.x)) */
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ))
- emit_store( bld, inst, 0, CHAN_Z, tmp2);
- }
- /* dst.w = 1.0 */
- if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_W )) {
- tmp0 = bld->base.one;
- emit_store( bld, inst, 0, CHAN_W, tmp0);
- }
- break;
-
- case TGSI_OPCODE_MUL:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- dst0 = lp_build_mul(&bld->base, src0, src1);
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_ADD:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- dst0 = lp_build_add(&bld->base, src0, src1);
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_DP3:
- /* TGSI_OPCODE_DOT3 */
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp1 = emit_fetch( bld, inst, 1, CHAN_X );
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
- tmp2 = emit_fetch( bld, inst, 1, CHAN_Y );
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Z );
- tmp2 = emit_fetch( bld, inst, 1, CHAN_Z );
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_DP4:
- /* TGSI_OPCODE_DOT4 */
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp1 = emit_fetch( bld, inst, 1, CHAN_X );
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
- tmp2 = emit_fetch( bld, inst, 1, CHAN_Y );
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Z );
- tmp2 = emit_fetch( bld, inst, 1, CHAN_Z );
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- tmp1 = emit_fetch( bld, inst, 0, CHAN_W );
- tmp2 = emit_fetch( bld, inst, 1, CHAN_W );
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_DST:
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) {
- tmp0 = bld->base.one;
- emit_store( bld, inst, 0, CHAN_X, tmp0);
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) {
- tmp0 = emit_fetch( bld, inst, 0, CHAN_Y );
- tmp1 = emit_fetch( bld, inst, 1, CHAN_Y );
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
- emit_store( bld, inst, 0, CHAN_Y, tmp0);
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) {
- tmp0 = emit_fetch( bld, inst, 0, CHAN_Z );
- emit_store( bld, inst, 0, CHAN_Z, tmp0);
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) {
- tmp0 = emit_fetch( bld, inst, 1, CHAN_W );
- emit_store( bld, inst, 0, CHAN_W, tmp0);
- }
- break;
-
- case TGSI_OPCODE_MIN:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- dst0 = lp_build_min( &bld->base, src0, src1 );
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_MAX:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- dst0 = lp_build_max( &bld->base, src0, src1 );
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_SLT:
- /* TGSI_OPCODE_SETLT */
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LESS, src0, src1 );
- dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_SGE:
- /* TGSI_OPCODE_SETGE */
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GEQUAL, src0, src1 );
- dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_MAD:
- /* TGSI_OPCODE_MADD */
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- tmp1 = emit_fetch( bld, inst, 1, chan_index );
- tmp2 = emit_fetch( bld, inst, 2, chan_index );
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp2);
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_SUB:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- tmp1 = emit_fetch( bld, inst, 1, chan_index );
- tmp0 = lp_build_sub( &bld->base, tmp0, tmp1);
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_LRP:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- src2 = emit_fetch( bld, inst, 2, chan_index );
- tmp0 = lp_build_sub( &bld->base, src1, src2 );
- tmp0 = lp_build_mul( &bld->base, src0, tmp0 );
- dst0 = lp_build_add( &bld->base, tmp0, src2 );
- emit_store( bld, inst, 0, chan_index, dst0 );
- }
- break;
-
- case TGSI_OPCODE_CND:
- return 0;
- break;
-
- case TGSI_OPCODE_CND0:
- return 0;
- break;
-
- case TGSI_OPCODE_DP2A:
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); /* xmm0 = src[0].x */
- tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); /* xmm1 = src[1].x */
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 * xmm1 */
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); /* xmm1 = src[0].y */
- tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); /* xmm2 = src[1].y */
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); /* xmm1 = xmm1 * xmm2 */
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */
- tmp1 = emit_fetch( bld, inst, 2, CHAN_X ); /* xmm1 = src[2].x */
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0); /* dest[ch] = xmm0 */
- }
- break;
-
- #if 0
- case TGSI_OPCODE_FRC:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- emit_frc( bld, 0, 0 );
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_CLAMP:
- return 0;
- break;
-
- case TGSI_OPCODE_FLR:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- emit_flr( bld, 0, 0 );
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_ROUND:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- emit_rnd( bld, 0, 0 );
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
- #endif
-
- case TGSI_OPCODE_EX2: {
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp0 = lp_build_exp2( &bld->base, tmp0);
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
- }
-
- case TGSI_OPCODE_LG2:
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp0 = lp_build_log2( &bld->base, tmp0);
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_POW:
- src0 = emit_fetch( bld, inst, 0, CHAN_X );
- src1 = emit_fetch( bld, inst, 1, CHAN_X );
- dst0 = lp_build_pow( &bld->base, src0, src1 );
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, dst0 );
- }
- break;
-
- case TGSI_OPCODE_XPD:
- if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ||
- IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ) {
- tmp1 = emit_fetch( bld, inst, 1, CHAN_Z );
- tmp3 = emit_fetch( bld, inst, 0, CHAN_Z );
- }
- if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ||
- IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) {
- tmp0 = emit_fetch( bld, inst, 0, CHAN_Y );
- tmp4 = emit_fetch( bld, inst, 1, CHAN_Y );
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) {
- tmp2 = tmp0;
- tmp2 = lp_build_mul( &bld->base, tmp2, tmp1);
- tmp5 = tmp3;
- tmp5 = lp_build_mul( &bld->base, tmp5, tmp4);
- tmp2 = lp_build_sub( &bld->base, tmp2, tmp5);
- emit_store( bld, inst, 0, CHAN_X, tmp2);
- }
- if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ||
- IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) {
- tmp2 = emit_fetch( bld, inst, 1, CHAN_X );
- tmp5 = emit_fetch( bld, inst, 0, CHAN_X );
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) {
- tmp3 = lp_build_mul( &bld->base, tmp3, tmp2);
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp5);
- tmp3 = lp_build_sub( &bld->base, tmp3, tmp1);
- emit_store( bld, inst, 0, CHAN_Y, tmp3);
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) {
- tmp5 = lp_build_mul( &bld->base, tmp5, tmp4);
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp2);
- tmp5 = lp_build_sub( &bld->base, tmp5, tmp0);
- emit_store( bld, inst, 0, CHAN_Z, tmp5);
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) {
- tmp0 = bld->base.one;
- emit_store( bld, inst, 0, CHAN_W, tmp0);
- }
- break;
-
- case TGSI_OPCODE_ABS:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- tmp0 = lp_build_abs( &bld->base, tmp0 ) ;
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_RCC:
- return 0;
- break;
-
- case TGSI_OPCODE_DPH:
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp1 = emit_fetch( bld, inst, 1, CHAN_X );
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp1);
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Y );
- tmp2 = emit_fetch( bld, inst, 1, CHAN_Y );
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Z );
- tmp2 = emit_fetch( bld, inst, 1, CHAN_Z );
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- tmp1 = emit_fetch( bld, inst, 1, CHAN_W );
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_COS:
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp0 = lp_build_cos( &bld->base, tmp0 );
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_DDX:
- return 0;
- break;
-
- case TGSI_OPCODE_DDY:
- return 0;
- break;
-
- #if 0
- case TGSI_OPCODE_KILP:
- /* predicated kill */
- emit_kilp( bld );
- return 0; /* XXX fix me */
- break;
- #endif
-
- case TGSI_OPCODE_KIL:
- /* conditional kill */
- emit_kil( bld, inst );
- break;
-
- case TGSI_OPCODE_PK2H:
- return 0;
- break;
-
- case TGSI_OPCODE_PK2US:
- return 0;
- break;
-
- case TGSI_OPCODE_PK4B:
- return 0;
- break;
-
- case TGSI_OPCODE_PK4UB:
- return 0;
- break;
-
- case TGSI_OPCODE_RFL:
- return 0;
- break;
-
- case TGSI_OPCODE_SEQ:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_EQUAL, src0, src1 );
- dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_SFL:
- return 0;
- break;
-
- case TGSI_OPCODE_SGT:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GREATER, src0, src1 );
- dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_SIN:
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp0 = lp_build_sin( &bld->base, tmp0 );
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
-
- case TGSI_OPCODE_SLE:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LEQUAL, src0, src1 );
- dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_SNE:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_NOTEQUAL, src0, src1 );
- dst0 = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero );
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_STR:
- return 0;
- break;
-
- case TGSI_OPCODE_TEX:
- emit_tex( bld, inst, FALSE, FALSE );
- break;
-
- case TGSI_OPCODE_TXD:
- return 0;
- break;
-
- case TGSI_OPCODE_UP2H:
- return 0;
- break;
-
- case TGSI_OPCODE_UP2US:
- return 0;
- break;
-
- case TGSI_OPCODE_UP4B:
- return 0;
- break;
-
- case TGSI_OPCODE_UP4UB:
- return 0;
- break;
-
- case TGSI_OPCODE_X2D:
- return 0;
- break;
-
- case TGSI_OPCODE_ARA:
- return 0;
- break;
-
- #if 0
- case TGSI_OPCODE_ARR:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- emit_rnd( bld, 0, 0 );
- emit_f2it( bld, 0 );
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
- #endif
-
- case TGSI_OPCODE_BRA:
- return 0;
- break;
-
- case TGSI_OPCODE_CAL:
- return 0;
- break;
-
- #if 0
- case TGSI_OPCODE_RET:
- emit_ret( bld );
- break;
- #endif
-
- case TGSI_OPCODE_END:
- break;
-
- #if 0
- case TGSI_OPCODE_SSG:
- /* TGSI_OPCODE_SGN */
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- emit_sgn( bld, 0, 0 );
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
- #endif
-
- case TGSI_OPCODE_CMP:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- src0 = emit_fetch( bld, inst, 0, chan_index );
- src1 = emit_fetch( bld, inst, 1, chan_index );
- src2 = emit_fetch( bld, inst, 2, chan_index );
- tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LESS, src0, bld->base.zero );
- dst0 = lp_build_select( &bld->base, tmp0, src1, src2);
- emit_store( bld, inst, 0, chan_index, dst0);
- }
- break;
-
- case TGSI_OPCODE_SCS:
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) {
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp0 = lp_build_cos( &bld->base, tmp0 );
- emit_store( bld, inst, 0, CHAN_X, tmp0);
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) {
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X );
- tmp0 = lp_build_sin( &bld->base, tmp0 );
- emit_store( bld, inst, 0, CHAN_Y, tmp0);
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) {
- tmp0 = bld->base.zero;
- emit_store( bld, inst, 0, CHAN_Z, tmp0);
- }
- IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) {
- tmp0 = bld->base.one;
- emit_store( bld, inst, 0, CHAN_W, tmp0);
- }
- break;
-
- case TGSI_OPCODE_TXB:
- emit_tex( bld, inst, TRUE, FALSE );
- break;
-
- case TGSI_OPCODE_NRM:
- /* fall-through */
- case TGSI_OPCODE_NRM4:
- /* 3 or 4-component normalization */
- {
- uint dims = (inst->Instruction.Opcode == TGSI_OPCODE_NRM) ? 3 : 4;
-
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X) ||
- IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y) ||
- IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z) ||
- (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W) && dims == 4)) {
-
- /* NOTE: Cannot use xmm regs 2/3 here (see emit_rsqrt() above). */
-
- /* xmm4 = src.x */
- /* xmm0 = src.x * src.x */
- tmp0 = emit_fetch(bld, inst, 0, CHAN_X);
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X)) {
- tmp4 = tmp0;
- }
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp0);
-
- /* xmm5 = src.y */
- /* xmm0 = xmm0 + src.y * src.y */
- tmp1 = emit_fetch(bld, inst, 0, CHAN_Y);
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y)) {
- tmp5 = tmp1;
- }
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp1);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
-
- /* xmm6 = src.z */
- /* xmm0 = xmm0 + src.z * src.z */
- tmp1 = emit_fetch(bld, inst, 0, CHAN_Z);
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z)) {
- tmp6 = tmp1;
- }
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp1);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
-
- if (dims == 4) {
- /* xmm7 = src.w */
- /* xmm0 = xmm0 + src.w * src.w */
- tmp1 = emit_fetch(bld, inst, 0, CHAN_W);
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W)) {
- tmp7 = tmp1;
- }
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp1);
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1);
- }
-
- /* xmm1 = 1 / sqrt(xmm0) */
- tmp1 = lp_build_rsqrt( &bld->base, tmp0);
-
- /* dst.x = xmm1 * src.x */
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X)) {
- tmp4 = lp_build_mul( &bld->base, tmp4, tmp1);
- emit_store(bld, inst, 0, CHAN_X, tmp4);
- }
-
- /* dst.y = xmm1 * src.y */
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y)) {
- tmp5 = lp_build_mul( &bld->base, tmp5, tmp1);
- emit_store(bld, inst, 0, CHAN_Y, tmp5);
- }
-
- /* dst.z = xmm1 * src.z */
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z)) {
- tmp6 = lp_build_mul( &bld->base, tmp6, tmp1);
- emit_store(bld, inst, 0, CHAN_Z, tmp6);
- }
-
- /* dst.w = xmm1 * src.w */
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X) && dims == 4) {
- tmp7 = lp_build_mul( &bld->base, tmp7, tmp1);
- emit_store(bld, inst, 0, CHAN_W, tmp7);
- }
- }
-
- /* dst0.w = 1.0 */
- if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W) && dims == 3) {
- tmp0 = bld->base.one;
- emit_store(bld, inst, 0, CHAN_W, tmp0);
- }
- }
- break;
-
- case TGSI_OPCODE_DIV:
- return 0;
- break;
-
- case TGSI_OPCODE_DP2:
- tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); /* xmm0 = src[0].x */
- tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); /* xmm1 = src[1].x */
- tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 * xmm1 */
- tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); /* xmm1 = src[0].y */
- tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); /* xmm2 = src[1].y */
- tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); /* xmm1 = xmm1 * xmm2 */
- tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- emit_store( bld, inst, 0, chan_index, tmp0); /* dest[ch] = xmm0 */
- }
- break;
-
- case TGSI_OPCODE_TXL:
- emit_tex( bld, inst, TRUE, FALSE );
- break;
-
- case TGSI_OPCODE_TXP:
- emit_tex( bld, inst, FALSE, TRUE );
- break;
-
- case TGSI_OPCODE_BRK:
- return 0;
- break;
-
- case TGSI_OPCODE_IF:
- return 0;
- break;
-
- case TGSI_OPCODE_LOOP:
- return 0;
- break;
-
- case TGSI_OPCODE_REP:
- return 0;
- break;
-
- case TGSI_OPCODE_ELSE:
- return 0;
- break;
-
- case TGSI_OPCODE_ENDIF:
- return 0;
- break;
-
- case TGSI_OPCODE_ENDLOOP:
- return 0;
- break;
-
- case TGSI_OPCODE_ENDREP:
- return 0;
- break;
-
- case TGSI_OPCODE_PUSHA:
- return 0;
- break;
-
- case TGSI_OPCODE_POPA:
- return 0;
- break;
-
- case TGSI_OPCODE_CEIL:
- return 0;
- break;
-
- case TGSI_OPCODE_I2F:
- return 0;
- break;
-
- case TGSI_OPCODE_NOT:
- return 0;
- break;
-
- #if 0
- case TGSI_OPCODE_TRUNC:
- FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) {
- tmp0 = emit_fetch( bld, inst, 0, chan_index );
- emit_f2it( bld, 0 );
- emit_i2f( bld, 0 );
- emit_store( bld, inst, 0, chan_index, tmp0);
- }
- break;
- #endif
-
- case TGSI_OPCODE_SHL:
- return 0;
- break;
-
- case TGSI_OPCODE_SHR:
- return 0;
- break;
-
- case TGSI_OPCODE_AND:
- return 0;
- break;
-
- case TGSI_OPCODE_OR:
- return 0;
- break;
-
- case TGSI_OPCODE_MOD:
- return 0;
- break;
-
- case TGSI_OPCODE_XOR:
- return 0;
- break;
-
- case TGSI_OPCODE_SAD:
- return 0;
- break;
-
- case TGSI_OPCODE_TXF:
- return 0;
- break;
-
- case TGSI_OPCODE_TXQ:
- return 0;
- break;
-
- case TGSI_OPCODE_CONT:
- return 0;
- break;
-
- case TGSI_OPCODE_EMIT:
- return 0;
- break;
-
- case TGSI_OPCODE_ENDPRIM:
- return 0;
- break;
-
- default:
- return 0;
- }
-
- return 1;
- }
-
- static void
- emit_declaration(
- struct lp_build_tgsi_soa_context *bld,
- struct tgsi_full_declaration *decl )
- {
- if( decl->Declaration.File == TGSI_FILE_INPUT ) {
- LLVMBuilderRef builder = bld->base.builder;
- unsigned first, last, mask;
- unsigned attrib, chan;
-
- first = decl->DeclarationRange.First;
- last = decl->DeclarationRange.Last;
- mask = decl->Declaration.UsageMask;
-
- for( attrib = first; attrib <= last; attrib++ ) {
- for( chan = 0; chan < NUM_CHANNELS; chan++ ) {
- LLVMValueRef input = bld->base.undef;
-
- if( mask & (1 << chan) ) {
- LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), (1 + attrib)*NUM_CHANNELS + chan, 0);
- LLVMValueRef a0;
- LLVMValueRef dadx;
- LLVMValueRef dady;
-
- switch( decl->Declaration.Interpolate ) {
- case TGSI_INTERPOLATE_PERSPECTIVE:
- /* fall-through */
-
- case TGSI_INTERPOLATE_LINEAR: {
- LLVMValueRef dadx_ptr = LLVMBuildGEP(builder, bld->dadx_ptr, &index, 1, "");
- LLVMValueRef dady_ptr = LLVMBuildGEP(builder, bld->dady_ptr, &index, 1, "");
- dadx = LLVMBuildLoad(builder, dadx_ptr, "");
- dady = LLVMBuildLoad(builder, dady_ptr, "");
- dadx = lp_build_broadcast_scalar(&bld->base, dadx);
- dady = lp_build_broadcast_scalar(&bld->base, dady);
- lp_build_name(dadx, "dadx_%u.%c", attrib, "xyzw"[chan]);
- lp_build_name(dady, "dady_%u.%c", attrib, "xyzw"[chan]);
- /* fall-through */
- }
-
- case TGSI_INTERPOLATE_CONSTANT: {
- LLVMValueRef a0_ptr = LLVMBuildGEP(builder, bld->a0_ptr, &index, 1, "");
- a0 = LLVMBuildLoad(builder, a0_ptr, "");
- a0 = lp_build_broadcast_scalar(&bld->base, a0);
- lp_build_name(a0, "a0_%u.%c", attrib, "xyzw"[chan]);
- break;
- }
-
- default:
- assert(0);
- break;
- }
-
- input = a0;
-
- if (decl->Declaration.Interpolate != TGSI_INTERPOLATE_CONSTANT) {
- input = lp_build_add(&bld->base, input, lp_build_mul(&bld->base, bld->x, dadx));
- input = lp_build_add(&bld->base, input, lp_build_mul(&bld->base, bld->y, dady));
- }
-
- if (decl->Declaration.Interpolate == TGSI_INTERPOLATE_PERSPECTIVE) {
- if(!bld->oow)
- bld->oow = lp_build_rcp(&bld->base, bld->w);
- input = lp_build_mul(&bld->base, input, bld->oow);
- }
-
- lp_build_name(input, "input%u.%c", attrib, "xyzw"[chan]);
- }
-
- bld->inputs[attrib][chan] = input;
- }
- }
- }
- }
-
- /**
- * Translate a TGSI vertex/fragment shader to SSE2 code.
- * Slightly different things are done for vertex vs. fragment shaders.
- *
- * \param tokens the TGSI input shader
- * \param bld the output SSE code/function
- * \param immediates buffer to place immediates, later passed to SSE bld
- * \param return 1 for success, 0 if translation failed
- */
- LLVMValueRef
- lp_build_tgsi_soa(LLVMBuilderRef builder,
- const struct tgsi_token *tokens,
- union lp_type type,
- LLVMValueRef *pos,
- LLVMValueRef a0_ptr,
- LLVMValueRef dadx_ptr,
- LLVMValueRef dady_ptr,
- LLVMValueRef consts_ptr,
- LLVMValueRef (*outputs)[4],
- LLVMValueRef samplers_ptr)
- {
- struct lp_build_tgsi_soa_context bld;
- struct tgsi_parse_context parse;
- uint num_immediates = 0;
- unsigned i;
-
- /* Setup build context */
- memset(&bld, 0, sizeof bld);
- lp_build_context_init(&bld.base, builder, type);
- bld.x = pos[0];
- bld.y = pos[1];
- bld.w = pos[3];
- bld.a0_ptr = a0_ptr;
- bld.dadx_ptr = dadx_ptr;
- bld.dady_ptr = dady_ptr;
- bld.outputs = outputs;
- bld.consts_ptr = consts_ptr;
- bld.samplers_ptr = samplers_ptr;
-
- tgsi_parse_init( &parse, tokens );
-
- while( !tgsi_parse_end_of_tokens( &parse ) ) {
- tgsi_parse_token( &parse );
-
- switch( parse.FullToken.Token.Type ) {
- case TGSI_TOKEN_TYPE_DECLARATION:
- if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
- emit_declaration( &bld, &parse.FullToken.FullDeclaration );
- }
- break;
-
- case TGSI_TOKEN_TYPE_INSTRUCTION:
- if (!emit_instruction( &bld, &parse.FullToken.FullInstruction )) {
- unsigned opcode = parse.FullToken.FullInstruction.Instruction.Opcode;
- const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode);
- _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
- info ? info->mnemonic : "<invalid>");
- }
- break;
-
- case TGSI_TOKEN_TYPE_IMMEDIATE:
- /* simply copy the immediate values into the next immediates[] slot */
- {
- const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
- assert(size <= 4);
- assert(num_immediates < LP_MAX_IMMEDIATES);
- for( i = 0; i < size; ++i )
- bld.immediates[num_immediates][i] =
- lp_build_const_uni(type, parse.FullToken.FullImmediate.u[i].Float);
- for( i = size; i < 4; ++i )
- bld.immediates[num_immediates][i] = bld.base.undef;
- num_immediates++;
- }
- break;
-
- default:
- assert( 0 );
- }
- }
-
- tgsi_parse_free( &parse );
-
- return bld.mask;
- }
|