diff Bison-Flex/BasicCompiler-StackBase/vm.cpp @ 0:db40c85cad7a default tip

upload sample source
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Mon, 09 May 2011 03:11:59 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bison-Flex/BasicCompiler-StackBase/vm.cpp	Mon May 09 03:11:59 2011 +0900
@@ -0,0 +1,222 @@
+//
+// 仮想CPU
+//
+//	関数ポインタベースでの実装例
+//
+//		(c)2008 Chihiro.SAKAMOTO HyperWorks
+//
+#include <exception>
+#include "vm.h"
+
+namespace vm {
+
+	// 0除算例外
+	class devide_by_zero: public std::exception {
+	  public:
+		const char *what() const throw()
+		{
+			return "devide by zero";
+		}
+	} ;
+
+	void (vcpu::*vcpu::cmd_[])() = {
+		#define	VM_EXECTABLE
+		#include "vm_code.h"
+		#undef	VM_EXECTABLE
+	} ;
+
+	// 実行
+	int vcpu::run()
+	{
+		command_ = data_.command_;						// プログラム格納位置
+		command_size_ = data_.command_size_;			// プログラムの大きさ
+
+		global_value.resize(data_.value_size_);			// 外部変数テーブル確保
+		command_ptr_ = command_;						// プログラムカウンター初期化
+
+		active = true;									// Haltしていない
+
+		try {
+			while (active) {							// Haltするまでループ
+				int op = *command_ptr_++;
+				(this->*cmd_[op])();
+			}
+		}
+		catch (const std::exception &e) {
+			std::cerr << "例外発生(" << e.what() << ")" << std::endl;
+			return -1;
+		}
+		return 0;
+	}
+
+	// 定数Push
+	void vcpu::PushConst()
+	{
+		push(value());
+	}
+
+	// 変数Push
+	void vcpu::PushValue()
+	{
+		push(global_value[value()]);
+	}
+
+	// 変数にPop
+	void vcpu::PopValue()
+	{
+		global_value[value()] = top(); pop();
+	}
+
+	// 空Pop(スタックトップを捨てる)
+	void vcpu::OpPop()
+	{
+		pop();
+	}
+
+	// 単項マイナス
+	void vcpu::OpNeg()
+	{
+		top() = -top();
+	}
+
+	// ==
+	void vcpu::OpEq()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs == rhs);
+	}
+
+	// !=
+	void vcpu::OpNe()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs != rhs);
+	}
+
+	// >
+	void vcpu::OpGt()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs > rhs);
+	}
+
+	// >=
+	void vcpu::OpGe()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs >= rhs);
+	}
+
+	// <
+	void vcpu::OpLt()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs < rhs);
+	}
+
+	// <=
+	void vcpu::OpLe()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs <= rhs);
+	}
+
+	// +
+	void vcpu::OpAdd()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs + rhs);
+	}
+
+	// -
+	void vcpu::OpSub()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs - rhs);
+	}
+
+	// *
+	void vcpu::OpMul()
+	{
+		int rhs = top(); pop();
+		int lhs = top(); pop();
+		push(lhs * rhs);
+	}
+
+	// /
+	void vcpu::OpDiv()
+	{
+		int rhs = top(); pop();
+		if (rhs == 0)
+			throw devide_by_zero();
+		int lhs = top(); pop();
+		push(lhs / rhs);
+	}
+
+	// %
+	void vcpu::OpMod()
+	{
+		int rhs = top(); pop();
+		if (rhs == 0)
+			throw devide_by_zero();
+		int lhs = top(); pop();
+		push(lhs % rhs);
+	}
+
+	// 無条件ジャンプ
+	void vcpu::OpJmp()
+	{
+		jmp(value());
+	}
+
+	// 真の時ジャンプ
+	void vcpu::OpJmpC()
+	{
+		int addr = value();
+		int cond = top(); pop();
+		if (cond)
+			jmp(addr);
+	}
+
+	// 偽の時ジャンプ
+	void vcpu::OpJmpNC()
+	{
+		int addr = value();
+		int cond = top(); pop();
+		if (!cond)
+			jmp(addr);
+	}
+
+	// 仮想CPUプログラム停止
+	void vcpu::OpHalt()
+	{
+		active = false;
+	}
+
+	void vcpu::OpRand()
+	{
+		int range = top(); pop();
+		int value = (range <= 0)? 0: (rand() % range);
+		push(value);
+	}
+
+	void vcpu::OpPrint()
+	{
+		int count = value();
+		while (count--) {
+			std::cout << top();
+			pop();
+			if (count)
+				std::cout << ", ";
+		}
+		std::cout << std::endl;
+	}
+}