ユーザー定義命令の追加 - onikiri/onikiri2 GitHub Wiki

dst/仕様/拡張/ユーザー定義命令の追加.md

この機能は現在公開されているバージョンには,まだ実装されていません

はじめに

  • 鬼斬では,ユーザー定義の新しい命令をエミュレータに追加する機構を備えてる
  • 具体的な手順は以下の通り 1. 1.

手順

  1. デコードのフック・ポイントに対し,ユーザー定義のデコード・メソッドを登録
    • ExtraOpDecoder::s_extraOpDecodeHook に以下のプロトタイプのメソッドを登録
void Decode( HookParameter<ExtraOpDecoder, ExtraOpDecodeArgs>* param );
  1. デコードに必要な情報の取得
    • param->GetParameter() により,ExtraOpDecodeArgs 構造体へのポインタを取得.
  2. Opコードのチェック
    • ExtraOpDecodeArgs ::codeWord を見て判断
    • ユーザー定義命令として扱う必要がなければ,そのままリターン
  3. 命令の生成
    • ExtraOpDecodeArgs ::decoded をtrueに
    • ExtraOpDecodeArgs ::decodedOps に,マイクロ命令列へのポインタと命令数を格納

備考

  • 簡単なテストの際は,gcc のインライン・アセンブラに直接数値を埋め込むと良い
__asm__ ( 
	".int 1<<26 \n\t"
);

サンプル

  • 以下は ソースを1つ取り,インクリメントして返す命令の例
  • 命令のOpコードは1<<26.
class TestOp : public ExtraOpInfoIF
{
	OpClass m_opClass;
public:
	TestOp() : m_opClass(OpClassCode::syscall)
	{
	}

	void Execute( OpStateIF* opState ) 
	{
		opState->SetDst( 0, opState->GetSrc(0) + 1 );
	}

	// 命令の種類
	const OpClass& GetOpClass() const
	{
		return m_opClass;
	}

	// オペランド
	int GetSrcOperand(const int index) const
	{
		return 1;	// レジスタ番号1
	}

	int GetDstOperand(const int index) const
	{
		return 1;	// レジスタ番号1
	}

	// オペランドの数
	int GetSrcNum() const
	{
		return 1;
	}

	int GetDstNum() const
	{
		return 1;
	}

	// ニーモニック (dump等のため)
	const char* GetMnemonic() const
	{
		return "TestOp";
	}

};

class TestDecoder
{
	struct MicroOps
	{
		ExtraOpInfoIF* ops[SimISAInfo::MAX_OP_INFO_COUNT_PER_PC];
		int count;
	};
	vector<MicroOps> m_mops;
public:
	TestDecoder()
	{
		ExtraOpDecoder::s_extraOpDecodeHook.Register( this, &TestDecoder::Decode, 0 ); 
	};

	~TestDecoder()
	{
		// Release ops
		for( size_t i = 0; i < m_mops.size(); i++ ){
			for( int j = 0; j < m_mops[i].count; j++ ){
				delete m_mops[i].ops[j];
			}
		}
	}

	void Decode( HookParameter<ExtraOpDecoder, ExtraOpDecodeArgs>* param )
	{
		ExtraOpDecodeArgs* args = param->GetParameter();
		args->decoded = false;

		int opCode = (args->codeWord >> 26) & 63;
		if( opCode == 1 ){
			args->decoded = true;

			MicroOps mops;
			mops.count = 1;
			mops.ops[0] = new TestOp;
			m_mops.push_back( mops );

			args->decodedOps->first  = &mops.ops[0];
			args->decodedOps->second = mops.count;
		}
	};
};
⚠️ **GitHub.com Fallback** ⚠️