static struct nvfx_reg constant(struct nvfx_vpc *vpc, int pipe, float x, float y, float z, float w) { struct nv30_vertprog *vp = vpc->vp; struct nv30_vertprog_data *vpd; int idx; if (pipe >= 0) { for (idx = 0; idx < vp->nr_consts; idx++) { if (vp->consts[idx].index == pipe) return nvfx_reg(NVFXSR_CONST, idx); } } idx = vp->nr_consts++; vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); vpd = &vp->consts[idx]; vpd->index = pipe; vpd->value[0] = x; vpd->value[1] = y; vpd->value[2] = z; vpd->value[3] = w; return nvfx_reg(NVFXSR_CONST, idx); }
struct nvfx_reg CCompilerFP::temp() { s32 idx = ffs(~m_rTemps) - 1; if(idx<0) return nvfx_reg(NVFXSR_TEMP,0); m_rTemps |= (1<<idx); m_rTempsDiscard |= (1<<idx); return nvfx_reg(NVFXSR_TEMP,idx); }
struct nvfx_reg CCompiler::temp() { s32 idx = ffs(~m_rTemps) - 1; if(idx<0) return nvfx_reg(NVFXSR_NONE,0); m_rTemps |= (1<<idx); m_rTempsDiscard |= (1<<idx); if((s32)m_nNumRegs<idx) m_nNumRegs = idx; return nvfx_reg(NVFXSR_TEMP,idx); }
static struct nvfx_reg temp(struct nvfx_vpc *vpc) { int idx = ffs(~vpc->r_temps) - 1; if (idx < 0 || (!vpc->is_nv4x && idx >= 16)) { NOUVEAU_ERR("out of temps!!\n"); return nvfx_reg(NVFXSR_TEMP, 0); } vpc->r_temps |= (1 << idx); vpc->r_temps_discard |= (1 << idx); return nvfx_reg(NVFXSR_TEMP, idx); }
void CVPParser::ParseInstruction(struct nvfx_insn *insn,opcode *opc,const char *param_str) { u32 i; char *token = SkipSpaces(strtok((char*)param_str,",")); if(opc->is_imm) ParseMaskedDstAddr(token,insn); else ParseMaskedDstReg(token,insn); for(i=0;i<opc->nr_src;i++) { token = SkipSpaces(strtok(NULL,",")); ParseSwizzledSrcReg(token,&insn->src[opc->src_slots[i]]); } if(opc->opcode == OPCODE_TEX) { uint8_t unit = ~0, target = ~0; token = SkipSpaces(strtok(NULL,",")); ParseTextureUnit(token,&unit); token = SkipSpaces(strtok(NULL,",")); ParseTextureTarget(token,&target); insn->src[1] = nvfx_src(nvfx_reg(NVFXSR_VPTEXINPUT,unit)); } }
void CParser::InitInstruction(struct nvfx_insn *insn,u8 op) { insn->op = op; insn->scale = 0; insn->unit = -1; insn->precision = FLOAT32; insn->mask = NVFX_VP_MASK_ALL; insn->cc_swz[0] = 0; insn->cc_swz[1] = 1; insn->cc_swz[2] = 2; insn->cc_swz[3] = 3; insn->sat = FALSE; insn->cc_update = FALSE; insn->cc_update_reg = 0; insn->cc_cond = NVFX_COND_TR; insn->cc_test = 0; insn->cc_test_reg = 0; insn->dst = nvfx_reg(NVFXSR_NONE,0); insn->src[0] = nvfx_src(nvfx_reg(NVFXSR_NONE,0)); insn->src[1] = nvfx_src(nvfx_reg(NVFXSR_NONE,0)); insn->src[2] = nvfx_src(nvfx_reg(NVFXSR_NONE,0)); }
struct nvfx_reg CCompiler::constant(s32 pipe, f32 x, f32 y, f32 z, f32 w) { int idx; struct vertex_program_data *vpd; if(pipe>=0) { for(idx=0;idx<m_nConsts;idx++) { if(m_pConstData[idx].index==pipe) return nvfx_reg(NVFXSR_CONST,idx); } } idx = m_nConsts++; m_pConstData = (struct vertex_program_data*)realloc(m_pConstData,sizeof(struct vertex_program_data)*m_nConsts); vpd = &m_pConstData[idx]; vpd->index = pipe; vpd->value[0] = x; vpd->value[1] = y; vpd->value[2] = z; vpd->value[3] = w; return nvfx_reg(NVFXSR_CONST,idx); }
void CCompiler::Compile(CParser *pParser) { struct nvfx_src tmp; struct nvfx_relocation reloc; std::vector<u32> insns_pos; std::list<struct nvfx_relocation> label_reloc; int i,nICount = pParser->GetInstructionCount(); struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE,0)); struct nvfx_insn tmp_insn,*insns = pParser->GetInstructions(); Prepare(pParser); for(i=0;i<nICount;i++) { /* u32 idx = (u32)insns_pos.size(); */ struct nvfx_insn *insn = &insns[i]; insns_pos.push_back(m_nInstructions); switch(insn->op) { case OPCODE_NOP: tmp_insn = arith(0,none.reg,0,none,none,none); emit_insn(gen_op(NOP,VEC),&tmp_insn); break; case OPCODE_ABS: tmp_insn = arith_ctor(insn,insn->dst,abs(insn->src[0]),none,none); emit_insn(gen_op(MOV,VEC),&tmp_insn); break; case OPCODE_ADD: emit_insn(gen_op(ADD,VEC),insn); break; case OPCODE_ARA: break; case OPCODE_ARL: break; case OPCODE_ARR: break; case OPCODE_BRA: reloc.location = m_nInstructions; reloc.target = insn->dst.index; label_reloc.push_back(reloc); tmp_insn = arith(0,none.reg,0,none,none,none); emit_insn(gen_op(BRA,SCA),&tmp_insn); break; case OPCODE_CAL: reloc.location = m_nInstructions; reloc.target = insn->dst.index; label_reloc.push_back(reloc); tmp_insn = arith(0,none.reg,0,none,none,none); emit_insn(gen_op(CAL,SCA),&tmp_insn); break; case OPCODE_COS: emit_insn(gen_op(COS,SCA),insn); break; case OPCODE_DP3: emit_insn(gen_op(DP3,VEC),insn); break; case OPCODE_DP4: emit_insn(gen_op(DP4,VEC),insn); break; case OPCODE_DPH: emit_insn(gen_op(DPH,VEC),insn); break; case OPCODE_DST: emit_insn(gen_op(DST,VEC),insn); break; case OPCODE_EX2: emit_insn(gen_op(EX2,SCA),insn); break; case OPCODE_EXP: emit_insn(gen_op(EXP,SCA),insn); break; case OPCODE_FLR: emit_insn(gen_op(FLR,VEC),insn); break; case OPCODE_FRC: emit_insn(gen_op(FRC,VEC),insn); break; case OPCODE_LG2: emit_insn(gen_op(LG2,SCA),insn); break; case OPCODE_LIT: emit_insn(gen_op(LIT,SCA),insn); break; case OPCODE_LOG: emit_insn(gen_op(LOG,SCA),insn); break; case OPCODE_MAD: emit_insn(gen_op(MAD,VEC),insn); break; case OPCODE_MAX: emit_insn(gen_op(MAX,VEC),insn); break; case OPCODE_MIN: emit_insn(gen_op(MIN,VEC),insn); break; case OPCODE_MOV: emit_insn(gen_op(MOV,VEC),insn); break; case OPCODE_MUL: emit_insn(gen_op(MUL,VEC),insn); break; case OPCODE_POW: tmp = nvfx_src(temp()); tmp_insn = arith(0, tmp.reg, NVFX_VP_MASK_X, none, none, insn->src[0]); emit_insn(gen_op(LG2,SCA),&tmp_insn); tmp_insn = arith(0, tmp.reg, NVFX_VP_MASK_X, swz(tmp, X, X, X, X), insn->src[1], none); emit_insn(gen_op(MUL,VEC),&tmp_insn); tmp_insn = arith_ctor(insn, insn->dst, none, none, swz(tmp, X, X, X, X)); emit_insn(gen_op(EX2,SCA),&tmp_insn); break; case OPCODE_RCC: emit_insn(gen_op(RCC,SCA),insn); break; case OPCODE_RCP: emit_insn(gen_op(RCP,SCA),insn); break; case OPCODE_RSQ: emit_insn(gen_op(RSQ,SCA),insn); break; case OPCODE_SEQ: emit_insn(gen_op(SEQ,VEC),insn); break; case OPCODE_SFL: emit_insn(gen_op(SFL,VEC),insn); break; case OPCODE_SGE: emit_insn(gen_op(SGE,VEC),insn); break; case OPCODE_SGT: emit_insn(gen_op(SGT,VEC),insn); break; case OPCODE_SIN: emit_insn(gen_op(SIN,SCA),insn); break; case OPCODE_SLE: emit_insn(gen_op(SLE,VEC),insn); break; case OPCODE_SLT: emit_insn(gen_op(SLT,VEC),insn); break; case OPCODE_SNE: emit_insn(gen_op(SNE,VEC),insn); break; case OPCODE_SSG: emit_insn(gen_op(SSG,VEC),insn); break; case OPCODE_STR: emit_insn(gen_op(STR,VEC),insn); break; case OPCODE_SUB: tmp_insn = arith_ctor(insn,insn->dst,insn->src[0],none,neg(insn->src[2])); emit_insn(gen_op(ADD,VEC),&tmp_insn); break; case OPCODE_END: if(m_nInstructions) m_pInstructions[m_nCurInstruction].data[3] |= NVFX_VP_INST_LAST; else { tmp_insn = arith(0,none.reg,0,none,none,none); emit_insn(gen_op(NOP,VEC),&tmp_insn); m_pInstructions[m_nCurInstruction].data[3] |= NVFX_VP_INST_LAST; } break; } release_temps(); } for(std::list<struct nvfx_relocation>::iterator it = label_reloc.begin();it!=label_reloc.end();it++) { struct nvfx_relocation hw_reloc; hw_reloc.location = it->location; hw_reloc.target = insns_pos[it->target]; m_lBranchRelocation.push_back(hw_reloc); } }
int CVPParser::Parse(const char *str) { int i,iline = 0; bool inProgram = false; std::stringstream input(str); struct nvfx_src none = nvfx_src(nvfx_reg(NVFXSR_NONE,0)); while(!input.eof()) { char line[256]; opcode *opc = NULL; struct nvfx_insn *insn = NULL; input.getline(line,255); iline++; for(i=0; i<256; i++) { char c = line[i]; if(c=='\n' || c=='\r' || c==';') c = 0; if(c=='\t') c = ' '; line[i] = c; if(c==0) break; } if(line[0]=='#') { ParseComment(line); continue; } if(!inProgram) { if(strncmp(line,"!!VP2.0",7)==0) inProgram = true; else if(strncmp(line,"!!ARBvp1.0",10)==0) inProgram = true; continue; } char *label = NULL; char *col_ptr = NULL; char *opcode = NULL; char *ptr = line; if((col_ptr = strstr((char*)ptr,":"))!=NULL) { int j = 0; bool valid = true; while((ptr+j)<col_ptr) { if(j==0 && !(isLetter(ptr[j]) || ptr[j]=='_')) valid = false; if(!(isLetter(ptr[j]) || isDigit(ptr[j]) || ptr[j]=='_')) valid = false; j++; } if(valid) { label = strtok(ptr,":\x20"); ptr = col_ptr + 1; } } opcode = strtok(ptr," "); if(label) { jmpdst d; strcpy(d.ident,label); d.location = m_nInstructions; m_lIdent.push_back(d); } if(opcode) { char *param_str = SkipSpaces(strtok(NULL,"\0")); if(strcasecmp(opcode,"OPTION")==0) { if(strncasecmp(param_str,"NV_vertex_program3",18)==0) m_nOption |= NV_OPTION_VP3; continue; } else if(strcasecmp(opcode,"PARAM")==0) continue; else if(strcasecmp(opcode,"TEMP")==0) continue; else { opc = FindOpcode(opcode); insn = &m_pInstructions[m_nInstructions]; if(!opc) continue; InitInstruction(insn,opc->opcode); if(opc->opcode==OPCODE_END) { m_nInstructions++; break; } char *opc_ext = opcode + strlen(opc->mnemonic); if(m_nOption&(NV_OPTION_VP2|NV_OPTION_VP3)) { if(opc_ext[0]=='C') { insn->cc_update = TRUE; if(m_nOption&NV_OPTION_VP3 && (opc_ext[1]=='0' || opc_ext[1]=='1')) { switch(opc_ext[1]) { case '0': insn->cc_update_reg = 0; break; case '1': insn->cc_update_reg = 1; break; } opc_ext++; } opc_ext++; } } if(opc_ext[0]=='_') { if(strncasecmp(opc_ext,"_sat",4)==0) insn->sat = TRUE; } ParseInstruction(insn,opc,param_str); m_nInstructions++; } } } for(std::list<jmpdst>::iterator r=m_lJmpDst.begin(); r!=m_lJmpDst.end(); r++) { bool found = false; for(std::list<jmpdst>::iterator i=m_lIdent.begin(); i!=m_lIdent.end(); i++) { if(strcmp(r->ident,i->ident)==0) { found = true; m_pInstructions[r->location].dst = nvfx_reg(NVFXSR_RELOCATED,i->location); break; } } if(found==false) { fprintf(stderr,"Identifier \'%s\' not found.\n",r->ident); exit(EXIT_FAILURE); } } return 0; }
void CCompilerFP::Compile(CParser *pParser) { int i,nCount = pParser->GetInstructionCount(); struct nvfx_insn tmp_insn,*insns = pParser->GetInstructions(); struct nvfx_src tmp,none = nvfx_src(nvfx_reg(NVFXSR_NONE,0)); Prepare(pParser); for(i=0;i<nCount;i++) { struct nvfx_insn *insn = &insns[i]; switch(insn->op) { case OPCODE_ADD: emit_insn(NVFX_FP_OP_OPCODE_ADD,insn); break; case OPCODE_BRK: emit_brk(insn); break; case OPCODE_COS: emit_insn(NVFX_FP_OP_OPCODE_COS,insn); break; case OPCODE_DP3: emit_insn(NVFX_FP_OP_OPCODE_DP3,insn); break; case OPCODE_DP4: emit_insn(NVFX_FP_OP_OPCODE_DP4,insn); break; case OPCODE_EX2: emit_insn(NVFX_FP_OP_OPCODE_EX2,insn); break; case OPCODE_LG2: emit_insn(NVFX_FP_OP_OPCODE_LG2,insn); break; case OPCODE_LRP: tmp = nvfx_src(temp()); tmp_insn = arith(0,tmp.reg,insn->mask,neg(insn->src[0]),insn->src[2],insn->src[2]); emit_insn(NVFX_FP_OP_OPCODE_MAD,&tmp_insn); tmp_insn = arith(insn->sat,insn->dst,insn->mask,insn->src[0],insn->src[1],tmp); emit_insn(NVFX_FP_OP_OPCODE_MAD,&tmp_insn); break; case OPCODE_MAX: emit_insn(NVFX_FP_OP_OPCODE_MAX,insn); break; case OPCODE_MIN: emit_insn(NVFX_FP_OP_OPCODE_MIN,insn); break; case OPCODE_MAD: emit_insn(NVFX_FP_OP_OPCODE_MAD,insn); break; case OPCODE_MOV: emit_insn(NVFX_FP_OP_OPCODE_MOV,insn); break; case OPCODE_MUL: emit_insn(NVFX_FP_OP_OPCODE_MUL,insn); break; case OPCODE_POW: tmp = nvfx_src(temp()); tmp_insn = arith(0,tmp.reg, NVFX_FP_MASK_X, insn->src[0], none, none); emit_insn(NVFX_FP_OP_OPCODE_LG2,&tmp_insn); tmp_insn = arith(0,tmp.reg, NVFX_FP_MASK_X, swz(tmp, X, X, X, X),insn->src[1], none); emit_insn(NVFX_FP_OP_OPCODE_MUL,&tmp_insn); tmp_insn = arith_ctor(insn,insn->dst,swz(tmp, X, X, X, X), none, none); emit_insn(NVFX_FP_OP_OPCODE_EX2,&tmp_insn); break; case OPCODE_RCP: emit_insn(NVFX_FP_OP_OPCODE_RCP,insn); break; case OPCODE_RSQ: tmp = nvfx_src(temp()); tmp_insn = arith(0,tmp.reg,NVFX_FP_MASK_X,abs(insn->src[0]),none,none); tmp_insn.scale = NVFX_FP_OP_DST_SCALE_INV_2X; emit_insn(NVFX_FP_OP_OPCODE_LG2,&tmp_insn); tmp_insn = arith_ctor(insn,insn->dst,neg(swz(tmp,X,X,X,X)),none,none); emit_insn(NVFX_FP_OP_OPCODE_EX2,&tmp_insn); break; case OPCODE_SEQ: emit_insn(NVFX_FP_OP_OPCODE_SEQ,insn); break; case OPCODE_SFL: emit_insn(NVFX_FP_OP_OPCODE_SFL,insn); break; case OPCODE_SGE: emit_insn(NVFX_FP_OP_OPCODE_SGE,insn); break; case OPCODE_SGT: emit_insn(NVFX_FP_OP_OPCODE_SGT,insn); break; case OPCODE_SIN: emit_insn(NVFX_FP_OP_OPCODE_SIN,insn); break; case OPCODE_SLE: emit_insn(NVFX_FP_OP_OPCODE_SLE,insn); break; case OPCODE_SLT: emit_insn(NVFX_FP_OP_OPCODE_SLT,insn); break; case OPCODE_SNE: emit_insn(NVFX_FP_OP_OPCODE_SNE,insn); break; case OPCODE_TEX: emit_insn(NVFX_FP_OP_OPCODE_TEX,insn); break; case OPCODE_TXB: emit_insn(NVFX_FP_OP_OPCODE_TXB,insn); break; case OPCODE_TXL: emit_insn(NVFX_FP_OP_OPCODE_TXL_NV40,insn); break; case OPCODE_TXP: emit_insn(NVFX_FP_OP_OPCODE_TXP,insn); break; case OPCODE_BGNREP: emit_rep(insn); break; case OPCODE_ENDREP: fixup_rep(); break; case OPCODE_END: if(m_nInstructions) m_pInstructions[m_nCurInstruction].data[0] |= NVFX_FP_OP_PROGRAM_END; else { m_nCurInstruction = m_nInstructions; grow_insns(1); m_pInstructions[m_nCurInstruction].data[0] = 0x00000001; m_pInstructions[m_nCurInstruction].data[1] = 0x00000000; m_pInstructions[m_nCurInstruction].data[2] = 0x00000000; m_pInstructions[m_nCurInstruction].data[3] = 0x00000000; } } release_temps(); } }