⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 issgen.cpp

📁 arm的模拟器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************    Copyright (C) 2002 - 2007 Wei Qin    See file COPYING for more information.    This program is free software; you can redistribute it and/or modify        it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.*************************************************************************/#include "issgen.hpp"#include <fstream>#include <list>#include <vector>#include <cassert>#include <iomanip>#include <cstring>using namespace issgen;using std::string;using std::ifstream;using std::ofstream;using std::vector;using std::pair;using std::map;using std::list;// global constant symbolsSymbol sym_condition;Symbol sym_vtarget;Symbol sym_ctarget;Symbol sym_execute;Symbol sym_iswrite;Symbol sym_pc;Symbol sym_inst;Symbol sym_root;extern isa_prog *isa_parse_wrapper(ifstream *infile, const char *fname);/* bincode related methods */bool bin_ident::type_check(const FIELD_ENV *fenv, const VAR_ENV *venv,	OP_ENV *oenv, Symbol opname, unsigned off){	offset = off;	if (fenv->find(data)!=fenv->end()) {		type  = BIN_FIELD;		width = (*fenv->find(data)).second;		return true;	}	else if (oenv->find(data)!=oenv->end()) {		type  = BIN_OPER;		oper = (*oenv->find(data)).second;		if (oper->type_check(fenv, venv, oenv)) {			width = oper->get_width();			count *= oper->get_count();			return true;		}		return false;	}	fprintf(stderr, "Unknown field %s in operation %s\n",		symbol_get_string(data).c_str(),		symbol_get_string(opname).c_str());	return false;}string bin_ident::get_opcode(unsigned index) const{	assert(index<count);	if (type==BIN_FIELD) return std::string(width, '-');	return oper->get_opcode(index);		}string bin_ident::get_qualified_name(unsigned index) const{	assert(index<count);	if (type==BIN_FIELD) return std::string();	return oper->get_qualified_name(index);}void bin_ident::get_used_vars(unsigned index, VAR_ENV *vtab) const{	assert(index<count);	if (type==BIN_OPER)		oper->get_used_vars(index, vtab);}bin_literal::bin_literal(const char *str) {	unsigned ii, len;	len = strlen(str);	for (ii=0; ii<len; ii++) {		if (str[ii]=='0' || str[ii]=='1' || str[ii]=='-') {			data.push_back(str[ii]);		}	}	width = data.length();	count = 1;}/* oper methods */bool oper::type_check(const FIELD_ENV *fenv, const VAR_ENV *venv, OP_ENV *oenv){	if (checked) 		return true;	if (incheck) {		fprintf(stderr, "Cyclic reference detected involving op %s.\n",			symbol_get_string(name).c_str());		return false;	}	incheck = true;	// check the opcode patterns first	unsigned offset = 0;	count = 1;	// check the opcode	vector<class bin_code *>::reverse_iterator rbit;	for (rbit=pat->rbegin(); rbit!=pat->rend(); rbit++) {		if (!(*rbit)->type_check(fenv, venv, oenv, name, offset))			return false;		/* if this is not literal, enter into table */		if ((*rbit)->is_identifier())			field_table[(*rbit)->get_name()] = 				dynamic_cast<class bin_ident *>(*rbit);		offset += (*rbit)->get_width();		count *= (*rbit)->get_count();	}	width = offset;	/* enter PC into the table */	field_table[sym_pc] = NULL;	field_table[sym_inst] = NULL;	// then need to check the contents	OP_CON_ENV::iterator cit;	for (cit=contents->begin(); cit!=contents->end(); cit++) {		// check if the name of the content is recognized		if ((*cit).first==sym_condition || (*cit).first==sym_vtarget ||			(*cit).first==sym_ctarget || (*cit).first==sym_execute ||			(*cit).first==sym_iswrite) {			if (!check_content((*cit).first, venv, oenv))				return false;		}		else {			fprintf(stderr, "Unknown attribute %s in operation %s\n",				symbol_get_string((*cit).first).c_str(),				symbol_get_string(name).c_str());		}	}	checked = true;	incheck = false;	return true;}static bool str_contain_word(const char *str, const char *needle){	const char *ptr = str;	int len = strlen(needle);	while (*ptr) {		char *match = strstr(ptr, needle);		if (match==NULL) break;		/* we check what is before the bword */		if (ptr<match) {			/* alphabet, number, _ means this is a subword, no good */			if (isalnum(*(match-1)) || *(match-1)=='_') {				ptr = match+len;				continue;			}		}		/* we then check what is after the word */		/* alphabet, number, _ means this is a subword, no good */		if (isalnum(match[len]) || match[len]=='_')			ptr = match+len;		else			/* good, find one */			return true;	}	return false;}bool oper::check_content(Symbol nam, const VAR_ENV *venv, OP_ENV *oenv){	assert(contents->find(nam)!=contents->end());	char *str = (*(contents->find(nam))).second;	/* we first check which variables are used in this content */	VAR_ENV::const_iterator vit;	for (vit=venv->begin(); vit!=venv->end(); vit++) {		string vname = symbol_get_string((*vit).first);		if (str_contain_word(str, vname.c_str())) {			var_table.insert(*vit);		}	}	int  left = 0, right = 0;	//index for scanning	bool in_escape = false;		//escape mode starts with '\' 	bool in_field = false;		//field is surrounded by '$'	vector<class token> *tokens = new vector<class token>;	// we parse into the string	while (str[right]) {		if (in_escape) {			in_escape = false;		}		else if (str[right]=='\\') {			in_escape = true;		}		else if (str[right]=='$') {			if (in_field) {				in_field = false;				str[right] = 0;				// from left to right, we have a field				tokens->push_back(token(str+left, token::FIELD));				left = right+1;			}			else {				in_field = true;				str[right] = 0;				// encounter a new field				tokens->push_back(token(str+left, token::CHARS));				left = right+1;			}		}		right++;	}	if (in_field) {		fprintf(stderr, "Unterminated field reference in oper %s\n",			symbol_get_string(name).c_str());			delete tokens;		return false;	}	if (left<right)		tokens->push_back(token(str+left, token::CHARS));	// now we check all the fields	vector<class token>::iterator tit;	for (tit=tokens->begin(); tit!=tokens->end(); tit++) {		if ((*tit).get_type()==token::FIELD) {			Symbol fname = symbol_find_or_insert((*tit).get_data());			if (field_table.find(fname)==field_table.end()) {				fprintf(stderr, "Undefined field %s in oper %s\n",					(*tit).get_data(),					symbol_get_string(name).c_str());					delete tokens;				return false;			}		}	}	cont_table[nam] = tokens;	return true;}oper::~oper(){	map<Symbol, char *>::iterator ait;	for(ait=contents->begin(); ait!=contents->end(); ait++) {		free((*ait).second);	}	delete contents;		vector<class bin_code *>::iterator bit;	for (bit=pat->begin(); bit!=pat->end(); bit++) {		delete *bit;	}	map<Symbol, vector<class token> *>::iterator cit;	for (cit=cont_table.begin(); cit!=cont_table.end(); cit++) {		delete (*cit).second;	}	delete pat;}string oper::get_opcode(unsigned index) const{	/* safety checking */	assert(index<count);	string ret;	vector<class bin_code *>::reverse_iterator rbit;	for (rbit=pat->rbegin(); rbit!=pat->rend(); rbit++) {		ret = (*rbit)->get_opcode(index % (*rbit)->get_count()) + ret;		index = index/(*rbit)->get_count();	}	return ret;}string oper::get_qualified_name(unsigned index) const{	/* safety checking */	assert(index<count);	string ret(symbol_get_string(name)+'_');	vector<class bin_code *>::reverse_iterator rbit;	for (rbit=pat->rbegin(); rbit!=pat->rend(); rbit++) {		if ((*rbit)->is_identifier()) {			class bin_ident *bident = dynamic_cast<class bin_ident *>(*rbit);			ret += bident->get_qualified_name(index % bident->get_count());			index = index/bident->get_count();		}	}	return ret;	}void oper::get_used_vars(unsigned index, VAR_ENV *vtab) const{	/* safety checking */	assert(index<count);	vector<class bin_code *>::reverse_iterator rbit;	for (rbit=pat->rbegin(); rbit!=pat->rend(); rbit++) {		if ((*rbit)->is_identifier()) {			class bin_ident *bident = dynamic_cast<class bin_ident *>(*rbit);			bident->get_used_vars(index % bident->get_count(), vtab);			index = index/bident->get_count();		}	}	vtab->insert(var_table.begin(), var_table.end());}/* group methods */group::~group(){	vector<class oper_base *>::iterator oit;	for (oit=opers->begin(); oit!=opers->end(); oit++) {		delete *oit;	}	delete opers;}bool group::type_check(const FIELD_ENV *fenv, const VAR_ENV *venv, OP_ENV *oenv){	if (incheck) {		fprintf(stderr, "Cyclic reference detected involving group %s.\n",			symbol_get_string(name).c_str());		return false;	}	incheck = true;	count = 0;	/* first do recursive checking */	vector<class oper_base *>::iterator op_it;	for (op_it=opers->begin(); op_it!=opers->end(); op_it++) {		if (!(*op_it)->type_check(fenv, venv, oenv)) return false;		count += (*op_it)->get_count();	}	/* second check width */	if (opers->size()) {		width = opers->front()->get_width();		for (op_it=opers->begin(); op_it!=opers->end(); op_it++) {			if ((*op_it)->get_width()!=width) {				fprintf(stderr, "%d %d Width mismatch for %s in group %s.\n",					(*op_it)->get_width(), width,					symbol_get_string((*op_it)->get_name()).c_str(), 					symbol_get_string(name).c_str());				return false;			}		}	}	else width = 0;	checked = true;	incheck = false;	return true;}string group::get_opcode(unsigned index) const{	assert(index<count);	vector<class oper_base *>::const_iterator op_it;	for (op_it=opers->begin(); op_it!=opers->end(); op_it++) {		if (index<(*op_it)->get_count())			return (*op_it)->get_opcode(index);		index -= (*op_it)->get_count();	}	assert(0); 			// should not reach here	return string();	// shut up gcc}string group::get_qualified_name(unsigned index) const{	assert(index<count);	vector<class oper_base *>::const_iterator op_it;	for (op_it=opers->begin(); op_it!=opers->end(); op_it++) {		if (index<(*op_it)->get_count())			return (*op_it)->get_qualified_name(index);		index -= (*op_it)->get_count();	}	assert(0); 			// should not reach here	return string();	// shut up gcc}void group::get_used_vars(unsigned index, VAR_ENV *vtab) const{	assert(index<count);	vector<class oper_base *>::const_iterator op_it;	for (op_it=opers->begin(); op_it!=opers->end(); op_it++) {		if (index<(*op_it)->get_count())			return (*op_it)->get_used_vars(index, vtab);		index -= (*op_it)->get_count();	}	assert(0); 			// should not reach here}/* isa_prog methods */bool isa_prog::type_check(){	/* Maintaining a list for recursion */	list<class oper_base *> op_list;	/* Push every toplevel opers into the list */	op_list.insert(op_list.end(), ops->begin(), ops->end());	/* need to build up oenv */	while (!op_list.empty()) {		class oper_base *op_tmp = op_list.front();		op_list.pop_front();		if (oenv->find(op_tmp->get_name())!=oenv->end()) {			fprintf(stderr, "Redefinition of op/group %s\n",				symbol_get_string(op_tmp->get_name()).c_str());			return false;		}		oenv->insert(OP_T(op_tmp->get_name(), op_tmp));		if (op_tmp->is_group()) {			class group *grp_tmp = dynamic_cast<class group *>(op_tmp);			vector<class oper_base *> *nlist = grp_tmp->get_opers();			op_list.insert(op_list.end(), nlist->begin(), nlist->end());		}	}	/* now with oenv, we can type check */	OP_ENV::iterator op_it;	for (op_it = oenv->begin(); op_it!=oenv->end(); op_it++) {		if (!(*op_it).second->type_check(fenv, venv, oenv)) return false;	}	/* now find the group named root */	if (oenv->find(sym_root)!=oenv->end()) {		grp_root = (*oenv->find(sym_root)).second;		if (grp_root->get_width()!=32) {			fprintf(stderr, "Root's encoding width is not 32\n");			return false;		}		fprintf(stderr, "Total instruction count = %d\n",			grp_root->get_count());	}	else {		fprintf(stderr, "Cannot find root\n");		return false;	}	return true;}isa_prog::~isa_prog() {	delete fenv;	delete venv;	delete oenv;	vector<class oper_base *>::iterator oit;	for (oit=ops->begin(); oit!=ops->end(); oit++) {		delete *oit;	}	delete ops;}static unsigned get_sign(string& code){	unsigned ind, val;	for (ind=0,val=0; ind<code.length(); ind++) {		val = val<<1;			if (code[ind]=='1') val = val|1;	}	return val;}static unsigned get_mask(string& code){	unsigned ind, val;	for (ind=0,val=0; ind<code.length(); ind++) {		val = val<<1;			if (code[ind]!='-') val = val|1;	}	return val;}void isa_prog::emit_decoder(ofstream& ofile){	ofile << std::hex;	ofile << std::setfill('0');	ofile << std::uppercase;	unsigned count = grp_root->get_count();	for (unsigned ii=0; ii<count; ii++) {		string opcode = grp_root->get_opcode(ii);		ofile << "IDEF(" << grp_root->get_qualified_name(ii)			<< ", 0x" << std::setw(8) << get_mask(opcode)			<< ", 0x" << std::setw(8) << get_sign(opcode) << ", 1)\n";	}}void bin_ident::emit_declaration(unsigned index,	unsigned rmb, ofstream& ofile){	if (type==BIN_FIELD) {		ofile << "\tunsigned " << symbol_get_string(data)			<< " = " << "(inst>>" << offset+rmb			<< ")&" << (1<<width)-1 << ";\n";	}	else {		oper->emit_field_declarations(index, offset+rmb, ofile);	}}void bin_ident::emit_interpreter_content(unsigned index,	Symbol attr, ofstream& ofile){	assert(index<count);	if (type==BIN_FIELD) {		ofile << symbol_get_string(data);	}	else {		oper->emit_interpreter_content(index, attr, ofile);	}}void bin_ident::emit_codegenerator_content1(unsigned index,	Symbol attr, ofstream& ofile){	assert(index<count);	if (type==BIN_FIELD) {		ofile << "%u";	}	else {		oper->emit_codegenerator_content1(index, attr, ofile);	}}void bin_ident::emit_codegenerator_content2(unsigned index, unsigned rmb,	Symbol attr, ofstream& ofile){	assert(index<count);	if (type==BIN_FIELD) {		ofile << ", (inst>>" << offset+rmb			<< ")&" << (1<<width)-1;	}	else {		oper->emit_codegenerator_content2(index, offset+rmb, attr, ofile);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -