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; }
//TODO: need to rework //Parse whole line first //Get number of arguments //Get base op code //Get first argument register offset if exists //Get second argument register offset if exists //Calculate op_code //Get first value argument if exists (i.e. RAM address) //Get second value argument if exists (i.e. register or value) void AssemblyParser::Parse(const ASSEMBLY &assembly, Model::Memory &memory, PROGRAM_ASSEMBLY_MAP &program_map) { ADDRESS byte_address = memory.GetTopAddress(); std::map<std::string, ADDRESS> tag_map; unsigned int line_number = 0; bool found_begin = false; bool found_end = false; for (auto line : assembly) { line_number++; if (line == PROGRAM_BEGIN && !found_begin) { found_begin = true; memory.SetValue(byte_address++, Model::OpCode::GetOpCode(OP_BEGIN, 0)); } else if (line == PROGRAM_END && !found_end) { found_end = true; memory.SetValue(byte_address++, Model::OpCode::GetOpCode(OP_END, 0)); } else if (found_begin && !line.empty()) { std::istringstream strstream(line); std::string token; std::getline(strstream, token, ' '); //TODO: tags are any strings (a-z, A-Z, ending with :) //Tags must be defined before use //TODO: subroutines are blocks beginning with a tag and ending with ROUTINE_RET if (token.substr(0,1) == COMMENT_BEGIN) { continue; } else if (token.back() == TAG_END) { tag_map[token.substr(0,token.length() - 1)] = byte_address; memory.SetValue(byte_address++, OP_NOP); } else { program_map[line_number] = byte_address; auto base_op_code = ParseInstruction(token); auto num_arguments = Model::OpCode::GetNumArguments(base_op_code); if (num_arguments >= 1) { std::getline(strstream, token, ' '); int register_index = 0; auto op_code = Model::OpCode::GetOpCode(base_op_code, register_index); //TODO: get rid of comma if (base_op_code == OP_JMP) { if (tag_map.find(token) != tag_map.end()) { memory.SetValue(byte_address++, op_code); memory.SetValue(byte_address++, tag_map[token]); } } else { register_index = ParseRegister(token); op_code = Model::OpCode::GetOpCode(base_op_code, register_index); memory.SetValue(byte_address++, op_code); } if (num_arguments >= 2) { std::getline(strstream, token, ' '); auto value = ParseRegValue(token); memory.SetValue(byte_address++, value); } //TODO: what if more arguments? i.e. what about inline comments } else { memory.SetValue(byte_address++, base_op_code); } } } } }
/** * Disassembles one instruction; only fully disassembly an instruction if it matches the filter criteria * * @returns VBox error code * @param pCpu Pointer to cpu structure which have DISCPUSTATE::mode * set correctly. * @param pu8Instruction Pointer to the structure to disassemble. * @param u32EipOffset Offset to add to instruction address to get the real virtual address * @param pcbSize Where to store the size of the instruction. * NULL is allowed. * @param pszOutput Storage for disassembled instruction * @param uFilter Instruction type filter * * @todo Define output callback. */ DISDECL(int) DISInstrEx(PDISCPUSTATE pCpu, RTUINTPTR pu8Instruction, unsigned u32EipOffset, unsigned *pcbSize, char *pszOutput, unsigned uFilter) { unsigned i = 0, prefixbytes; unsigned idx, inc; const OPCODE *paOneByteMap; #ifdef __L4ENV__ jmp_buf jumpbuffer; #endif //reset instruction settings pCpu->prefix = PREFIX_NONE; pCpu->enmPrefixSeg = DIS_SELREG_DS; pCpu->ModRM.u = 0; pCpu->SIB.u = 0; pCpu->lastprefix = 0; pCpu->param1.parval = 0; pCpu->param2.parval = 0; pCpu->param3.parval = 0; pCpu->param1.szParam[0] = 0; pCpu->param2.szParam[0] = 0; pCpu->param3.szParam[0] = 0; pCpu->param1.size = 0; pCpu->param2.size = 0; pCpu->param3.size = 0; pCpu->param1.flags = 0; pCpu->param2.flags = 0; pCpu->param3.flags = 0; pCpu->uFilter = uFilter; pCpu->pfnDisasmFnTable = pfnFullDisasm; if (pszOutput) *pszOutput = '\0'; if (pCpu->mode == CPUMODE_64BIT) { paOneByteMap = g_aOneByteMapX64; pCpu->addrmode = CPUMODE_64BIT; pCpu->opmode = CPUMODE_32BIT; } else { paOneByteMap = g_aOneByteMapX86; pCpu->addrmode = pCpu->mode; pCpu->opmode = pCpu->mode; } prefixbytes = 0; #ifndef __L4ENV__ /* Unfortunately, we have no exception handling in l4env */ try #else pCpu->pJumpBuffer = &jumpbuffer; if (setjmp(jumpbuffer) == 0) #endif { while(1) { uint8_t codebyte = DISReadByte(pCpu, pu8Instruction+i); uint8_t opcode = paOneByteMap[codebyte].opcode; /* Hardcoded assumption about OP_* values!! */ if (opcode <= OP_LAST_PREFIX) { /* The REX prefix must precede the opcode byte(s). Any other placement is ignored. */ if (opcode != OP_REX) { pCpu->lastprefix = opcode; pCpu->prefix &= ~PREFIX_REX; } switch(opcode) { case OP_INVALID: #if 0 //defined (DEBUG_Sander) AssertMsgFailed(("Invalid opcode!!\n")); #endif return VERR_DIS_INVALID_OPCODE; // segment override prefix byte case OP_SEG: pCpu->enmPrefixSeg = (DIS_SELREG)(paOneByteMap[codebyte].param1 - OP_PARM_REG_SEG_START); /* Segment prefixes for CS, DS, ES and SS are ignored in long mode. */ if ( pCpu->mode != CPUMODE_64BIT || pCpu->enmPrefixSeg >= DIS_SELREG_FS) { pCpu->prefix |= PREFIX_SEG; } i += sizeof(uint8_t); prefixbytes++; continue; //fetch the next byte // lock prefix byte case OP_LOCK: pCpu->prefix |= PREFIX_LOCK; i += sizeof(uint8_t); prefixbytes++; continue; //fetch the next byte // address size override prefix byte case OP_ADDRSIZE: pCpu->prefix |= PREFIX_ADDRSIZE; if (pCpu->mode == CPUMODE_16BIT) pCpu->addrmode = CPUMODE_32BIT; else if (pCpu->mode == CPUMODE_32BIT) pCpu->addrmode = CPUMODE_16BIT; else pCpu->addrmode = CPUMODE_32BIT; /* 64 bits */ i += sizeof(uint8_t); prefixbytes++; continue; //fetch the next byte // operand size override prefix byte case OP_OPSIZE: pCpu->prefix |= PREFIX_OPSIZE; if (pCpu->mode == CPUMODE_16BIT) pCpu->opmode = CPUMODE_32BIT; else pCpu->opmode = CPUMODE_16BIT; /* for 32 and 64 bits mode (there is no 32 bits operand size override prefix) */ i += sizeof(uint8_t); prefixbytes++; continue; //fetch the next byte // rep and repne are not really prefixes, but we'll treat them as such case OP_REPE: pCpu->prefix |= PREFIX_REP; i += sizeof(uint8_t); prefixbytes += sizeof(uint8_t); continue; //fetch the next byte case OP_REPNE: pCpu->prefix |= PREFIX_REPNE; i += sizeof(uint8_t); prefixbytes += sizeof(uint8_t); continue; //fetch the next byte case OP_REX: Assert(pCpu->mode == CPUMODE_64BIT); /* REX prefix byte */ pCpu->prefix |= PREFIX_REX; pCpu->prefix_rex = PREFIX_REX_OP_2_FLAGS(paOneByteMap[codebyte].param1); i += sizeof(uint8_t); prefixbytes += sizeof(uint8_t); if (pCpu->prefix_rex & PREFIX_REX_FLAGS_W) pCpu->opmode = CPUMODE_64BIT; /* overrides size prefix byte */ continue; //fetch the next byte } } idx = i; i += sizeof(uint8_t); //first opcode byte pCpu->opcode = codebyte; /* Prefix byte(s) is/are part of the instruction. */ pCpu->opaddr = pu8Instruction + idx + u32EipOffset - prefixbytes; inc = ParseInstruction(pu8Instruction + i, &paOneByteMap[pCpu->opcode], pCpu); pCpu->opsize = prefixbytes + inc + sizeof(uint8_t); if(pszOutput) { disasmSprintf(pszOutput, pu8Instruction+i-1-prefixbytes, pCpu, &pCpu->param1, &pCpu->param2, &pCpu->param3); } i += inc; prefixbytes = 0; break; } } #ifndef __L4ENV__ catch(...) #else else /* setjmp has returned a non-zero value: an exception occurred */ #endif { if (pcbSize) *pcbSize = 0; return VERR_DIS_GEN_FAILURE; } if (pcbSize) *pcbSize = i; if (pCpu->prefix & PREFIX_LOCK) disValidateLockSequence(pCpu); return VINF_SUCCESS; }
bool Player::UpdateInstruction() { m_CurrentInstruction.ReadFromConsole("Which direction to go in?"); return ParseInstruction(); }
int CFPParser::Parse(const char *str) { int i,iline = 0; bool inProgram = false; std::stringstream input(str); while(!input.eof()) { char line[256]; 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,"!!FP2.0",7)==0) inProgram = true; else if(strncmp(line,"!!ARBfp1.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(opcode) { char *param_str = SkipSpaces(strtok(NULL,"\0")); if(strcasecmp(opcode,"OPTION")==0) { if(strncasecmp(param_str,"NV_fragment_program2",20)==0) m_nOption |= NV_OPTION_FP2; continue; } else if(strcasecmp(opcode,"PARAM")==0) continue; else if(strcasecmp(opcode,"TEMP")==0) continue; else if(strcasecmp(opcode,"OUTPUT")==0) { ParseOutput(param_str); continue; } else { struct _opcode opc = FindOpcode(opcode); insn = &m_pInstructions[m_nInstructions]; if(opc.opcode>=MAX_OPCODE) continue; InitInstruction(insn,opc.opcode); if(opc.opcode==OPCODE_END) { m_nInstructions++; break; } ParseInstruction(insn,&opc,param_str); m_nInstructions++; } } } return 0; }