ucfunc.cc
来自「一个制作3d游戏的源程序」· CC 代码 · 共 1,080 行 · 第 1/3 页
CC
1,080 行
output_asm_opcode(tab_indent(3, cout), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); #endif if(current->second==false) { if((opcode_table_data[current->first->_id].num_pop!=0) || (opcode_table_data[current->first->_id].call_effect!=0)) { //if(opcode_table_data[current->first->_id].num_pop<0x7F) { #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(3, cout << "0x" << std::setw(2) << current->first->_id << "-"), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); tab_indent(3, cout << "0x" << std::setw(2) << current->first->_id << "-") << opcode_table_data[current->first->_id].num_pop << endl; #endif unsigned int num_args=0; if(opcode_table_data[current->first->_id].num_pop>0x7F) { #ifdef DEBUG_PARSE2a cout << "CALL EFFECT: " << opcode_table_data[current->first->_id].num_pop << '\t'; #endif unsigned int offset = 0x100 - opcode_table_data[current->first->_id].num_pop - 1; num_args = current->first->_params_parsed[offset]; #ifdef DEBUG_PARSE2a cout << num_args << endl; #endif } else if(opcode_table_data[current->first->_id].call_effect!=0) { assert(current->first->_params_parsed.size()>=1); assert(_externs.size()>=current->first->_params_parsed[0]); FuncMap::const_iterator fmp = funcmap.find(_externs[current->first->_params_parsed[0]]); assert(fmp!=funcmap.end()); #ifdef DEBUG_PARSE2 cout << "CALL: " << fmp->second.funcid << '\t' << fmp->second.num_args << endl; #endif num_args = fmp->second.num_args; } else { #ifdef DEBUG_PARSE2 cout << "Non-CALL: \t" << opcode_table_data[current->first->_id].num_pop << endl; #endif num_args = opcode_table_data[current->first->_id].num_pop; } if(num_args>0) { /* save the 'current' value as the return value and increment it so it's pointing at the 'next' current value */ vector<pair<UCc *, bool> >::reverse_iterator ret(current); ret->first->_popped = parse_ucs_pass2a(++current, vec, num_args, funcmap, intrinsics); assert(current!=ret); --current; assert(current==ret); #ifdef DEBUG_PARSE2a output_asm_opcode(tab_indent(1, cout), *this, funcmap, opcode_table_data, intrinsics, *(ret->first)); for(vector<UCc *>::iterator i=ret->first->_popped.begin(); i!=ret->first->_popped.end(); i++) output_asm_opcode(tab_indent(2, cout), *this, funcmap, opcode_table_data, intrinsics, **i); #endif } } } if((opsneeded!=0) && (current->second==false)) { // if it's a 'push' opcode and we need items to return that we've popped off the stack... if(opcode_table_data[current->first->_id].num_push!=0) { #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(4, cout << "P-"), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); #endif opsfound+=opcode_table_data[current->first->_id].num_push; vucc.push_back(current->first); current->second=true; } // if it's a call to a function that returns a variable... else if(opcode_table_data[current->first->_id].call_effect!=0) { FuncMap::const_iterator fmp = funcmap.find(_externs[current->first->_params_parsed[0]]); assert(fmp!=funcmap.end()); if(fmp->second.return_var) { #ifdef DEBUG_PARSE2 output_asm_opcode(tab_indent(4, cout << "C-"), *this, funcmap, opcode_table_data, intrinsics, *(current->first)); #endif opsfound+=1; vucc.push_back(current->first); current->second=true; } } else current->second=true; // if we've found all the ops we were searching for, return them if(opsfound>=opsneeded) { return vucc; } } } } if(vucc.size()>0) cout << "DID NOT FIND ALL OPCODE PARAMETERS." << endl; return vucc;}/* The 'optimisation' phase. Attempting to remove as many goto...labels as possible. */void UCFunc::parse_ucs_pass3(vector<GotoSet> &gotoset, const map<unsigned int, string> &intrinsics){}bool UCFunc::output_tt(std::ostream &o){ o << "\t<0x" << setw(4) << _funcid << ">" << endl; for(map<unsigned int, string, less<unsigned int> >::iterator i=_data.begin(); i!=_data.end(); i++) { o << "\t\t<0x" << setw(4) << i->first << ">" << endl << "\t\t`" << i->second << "`" << endl << "\t\t</>" << endl; } o << "\t</>" << endl; return true;}/* calculates the relative offset jump location, used in opcodes jmp && jne */inline int calc16reloffset(const UCc &op, unsigned int param){ /* forumla: real offset = offset of start of current opcode + int of parameter (since you can jump backwards) + 1 (size of "opcode") + size of "opcode" parameter data NOTE: since param is unsigned, a twos-complimant is required: formula: 0xFFFF - (unsigned short)param + 1 ^^^^^^ max of unsighed short */ return op._offset + ((param>>15) ? (-1 * (0xFFFF - static_cast<unsigned short>(param) + 1)) : static_cast<int>(param)) + 1 + op._params.size();}/* calculates the relative offset jump location, used in opcodes jmp && jne */inline int calc32reloffset(const UCc &op, unsigned int param) //FIXME: Test this!{ /* forumla: real offset = offset of start of current opcode + int of parameter (since you can jump backwards) + 1 (size of "opcode") + size of "opcode" parameter data NOTE: since param is unsigned, a twos-complimant is required: formula: 0xFFFFFFFF - (unsigned int)param + 1 ^^^^^^ max of unsighed int */ return op._offset + ((param>>31) ? (-1 * (0xFFFFFFFF - static_cast<unsigned int>(param) + 1)) : static_cast<int>(param)) + 1 + op._params.size();}void ucc_parse_parambytes(UCc &ucop, const UCOpcodeData &otd){ unsigned int first=0; for(vector<pair<unsigned int, bool> >::const_iterator s=otd.param_sizes.begin(); s!=otd.param_sizes.end(); ++s) { //cout << ucop._id << '\t' << ucop._params.size() << endl; assert(first<ucop._params.size()); unsigned int ssize=s->first; bool offset_munge=s->second; assert(ssize!=0); if(ssize==1) ucop._params_parsed.push_back(static_cast<unsigned int>(ucop._params[first++])); else if(ssize==2) if(offset_munge) { unsigned int calcvar = static_cast<unsigned int>(ucop._params[first++]); calcvar += ((static_cast<unsigned int>(ucop._params[first++])) << 8); unsigned int reloffset = calc16reloffset(ucop, calcvar); ucop._params_parsed.push_back(reloffset); ucop._jump_offsets.push_back(reloffset); } else { unsigned int calcvar = static_cast<unsigned int>(ucop._params[first++]); calcvar += ((static_cast<unsigned int>(ucop._params[first++])) << 8); ucop._params_parsed.push_back(calcvar); } else if(ssize==4) if(offset_munge) { unsigned int calcvar = static_cast<unsigned int>(ucop._params[first++]); calcvar += ((static_cast<unsigned int>(ucop._params[first++])) << 8); calcvar += ((static_cast<unsigned int>(ucop._params[first++])) << 16); calcvar += ((static_cast<unsigned int>(ucop._params[first++])) << 24); unsigned int reloffset = calc32reloffset(ucop, calcvar); ucop._params_parsed.push_back(reloffset); ucop._jump_offsets.push_back(reloffset); } else { unsigned int calcvar = static_cast<unsigned int>(ucop._params[first++]); calcvar += ((static_cast<unsigned int>(ucop._params[first++])) << 8); calcvar += ((static_cast<unsigned int>(ucop._params[first++])) << 16); calcvar += ((static_cast<unsigned int>(ucop._params[first++])) << 24); ucop._params_parsed.push_back(calcvar); } else assert(false); // just paranoia. }}/* prints the "assembler" output of the usecode, currently trying to duplicate the output of the original ucdump... returns true if successful*/bool UCFunc::output_asm(ostream &o, const FuncMap &funcmap, const map<unsigned int, string> &intrinsics, const UCOptions &options){ if(options.verbose) cout << "Printing function..." << endl; o << "Function at file offset " << std::setw(8) << _offset << "H" << endl; o << "\t.funcnumber " << std::setw(4) << _funcid << "H" << endl; if(ext32) o << "\t.ext32" << endl; o << "\t.msize " << ((ext32) ? setw(8) : setw(4)) << _funcsize << "H" << endl; o << "\t.dsize " << ((ext32) ? setw(8) : setw(4)) << _datasize << "H" << endl; if(debugging_info) o << "\t .dbgoffset " << std::setw(4) << debugging_offset << "H" << endl; if(_data.size()) output_asm_data(o); o << "Code segment at file offset " << std::setw(8) << _codeoffset << "H" << endl; o << "\t.argc " << std::setw(4) << _num_args << "H" << endl; o << "\t.localc " << std::setw(4) << _num_locals << "H" << endl; o << "\t.externsize " << std::setw(4) << _externs.size() << "H" << endl; for(typeof(_externs.begin()) i=_externs.begin(); i!=_externs.end(); i++) o << '\t' << " .extern " << std::setw(4) << *i << "H" << endl;/* for(unsigned int i=0; i<_externs.size(); i++) //FIXME: ::iterators o << '\t' << " .extern " << std::setw(4) << _externs[i] << "H" << endl;*/ for(vector<UCc>::iterator op=_opcodes.begin(); op!=_opcodes.end(); op++) output_asm_opcode(o, funcmap, opcode_table_data, intrinsics, *op, options); return true;}void UCFunc::output_asm_data(ostream &o){ static const unsigned int nochars=60; // limit of about 60 chars to a line, wrap to the next line if longer then this... for(map<unsigned int, string, less<unsigned int> >::iterator i=_data.begin(); i!=_data.end(); i++) { for(unsigned int j=0; j<i->second.size(); j++) { if(j==0) o << setw(4) << i->first; if((j!=0) && !(j%nochars)) o << "'" << endl; if(!(j%nochars)) o << "\tdb\t'"; o << i->second[j]; } o << "'" << endl; o << "\tdb\t00" << endl; }}void UCFunc::output_raw_opcodes(ostream &o, const UCc &op){ // chars in opcode o << ' ' << std::setw(2) << static_cast<unsigned int>(op._id); if(op._params.size()) cout << ' '; for(unsigned int i=0; i<op._params.size(); i++) { o << std::setw(2) << static_cast<unsigned int>(op._params[i]); if(i!=op._params.size()) o << ' '; } // seperator unsigned int numsep = op._params.size(); //cout << endl << numsep << endl; if(numsep>6) o << endl << "\t\t\t"; else if (numsep>5) o << " "; else if (numsep>2) o << "\t"; else o << "\t\t";}void UCFunc::output_asm_opcode(ostream &o, const FuncMap &funcmap, const vector<UCOpcodeData> &optab, const map<unsigned int, string> &intrinsics, const UCc &op, const UCOptions &options){ // offset o << std::setw(4) << op._offset << ':'; if(options.rawops) output_raw_opcodes(o, op); else o << '\t'; o << demunge_ocstring(*this, funcmap, optab[op._id].asm_nmo, op._params_parsed, intrinsics, op, false); if(options.autocomment) o << demunge_ocstring(*this, funcmap, optab[op._id].asm_comment, op._params_parsed, intrinsics, op, false); o << endl;}inline unsigned int charnum2uint(const char c){ switch(c) { case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; default: return 0; } return 0; // can't happen}// FIXME: Remove the passed ¶ms value. Get it from op._params_parsedstring demunge_ocstring(UCFunc &ucf, const FuncMap &funcmap, const string &asmstr, const vector<unsigned int> ¶ms, const map<unsigned int, string> &intrinsics, const UCc &op, bool ucs_output){#ifdef HAVE_SSTREAM std::stringstream str;#else std::strstream str;#endif str << std::setfill('0') << std::setbase(16); str.setf(ios::uppercase); size_t len=asmstr.length(); if(len==0) return string(); // for the degenerate case bool finished=false; // terminating details are at end-of-while unsigned int i=0; // istr index unsigned int width=0; // width value for setw() if(ucs_output && opcode_table_data[op._id].flag_paren) str << '(';
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?