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 &params value. Get it from op._params_parsedstring demunge_ocstring(UCFunc &ucf, const FuncMap &funcmap, const string &asmstr, const vector<unsigned int> &params, 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 + -
显示快捷键?