view Bison-Flex/BasicCompiler-MemoryBase/EUC/vm.h @ 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 source

#ifndef	__VM_H__
#define	__VM_H__

#include <vector>
#include "vm_value.h"

#define	VM_ENUMDEF
enum	{
#include "vm_code.h"
	VM_MAXCOMMAND,
} ;
#undef	VM_ENUMDEF

namespace vm {

	class data {
	  public:
		data(): command_(0)
		{
		}
		~data()
		{
			delete[] command_;
		}

	  public:
		unsigned char *command_;	// コマンドテーブル
		int command_size_;			// コマンドサイズ
		int value_size_;			// グローバル変数サイズ
	} ;

	// 0除算例外
	class devide_by_zero: public std::exception {
	  public:
		const char *what() const throw()
		{
			return "devide by zero";
		}
	} ;

	// 仮想マシン
	class vcpu {
	  public:
		const static int STACK_SIZE = 1000;

	  public:
		vcpu(data &mem)
			: data_(mem)
		{
		}
		~vcpu()
		{
		}

		int run();

	  private:
		// 定数Push
		void PushConst(int value)
		{
			push(value);
		}

		// 変数Push
		void PushValue(int value)
		{
			push(global_value[value]);
		}

		// 変数にPop
		void PopValue(int value)
		{
			global_value[value] = top(); pop();
		}

		// 空Pop(スタックトップを捨てる)
		void OpPop()
		{
			pop();
		}

		// 代入
		void OpMovC(int result, int arg)
		{
			global_value[result] = arg;
		}

		void OpMovV(int result, int arg)
		{
			global_value[result] = global_value[arg];
		}

		// 単項マイナス
		void OpNegC(int result, int arg)
		{
			global_value[result] = -arg;
		}

		void OpNegV(int result, int arg)
		{
			global_value[result] = -global_value[arg];
		}

		// ==
		void OpEqCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 == arg2;
		}

		void OpEqVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] == arg2;
		}

		void OpEqCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 == global_value[arg2];
		}

		void OpEqVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] == global_value[arg2];
		}

		// !=
		void OpNeCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 != arg2;
		}

		void OpNeVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] != arg2;
		}

		void OpNeCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 != global_value[arg2];
		}

		void OpNeVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] != global_value[arg2];
		}

		// >
		void OpGtCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 > arg2;
		}

		void OpGtVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] > arg2;
		}

		void OpGtCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 > global_value[arg2];
		}

		void OpGtVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] > global_value[arg2];
		}

		// >=
		void OpGeCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 >= arg2;
		}

		void OpGeVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] >= arg2;
		}

		void OpGeCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 >= global_value[arg2];
		}

		void OpGeVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] >= global_value[arg2];
		}

		// <
		void OpLtCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 < arg2;
		}

		void OpLtVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] < arg2;
		}

		void OpLtCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 < global_value[arg2];
		}

		void OpLtVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] < global_value[arg2];
		}

		// <=
		void OpLeCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 <= arg2;
		}

		void OpLeVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] <= arg2;
		}

		void OpLeCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 <= global_value[arg2];
		}

		void OpLeVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] <= global_value[arg2];
		}

		// +
		void OpAddCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 + arg2;
		}

		void OpAddVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] + arg2;
		}

		void OpAddCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 + global_value[arg2];
		}

		void OpAddVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] + global_value[arg2];
		}

		// -
		void OpSubCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 - arg2;
		}

		void OpSubVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] - arg2;
		}

		void OpSubCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 - global_value[arg2];
		}

		void OpSubVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] - global_value[arg2];
		}

		// *
		void OpMulCC(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 * arg2;
		}

		void OpMulVC(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] * arg2;
		}

		void OpMulCV(int result, int arg1, int arg2)
		{
			global_value[result] = arg1 * global_value[arg2];
		}

		void OpMulVV(int result, int arg1, int arg2)
		{
			global_value[result] = global_value[arg1] * global_value[arg2];
		}

		// /
		void OpDivCC(int result, int arg1, int arg2)
		{
			if (arg2 == 0)
				throw devide_by_zero();
			global_value[result] = arg1 / arg2;
		}

		void OpDivVC(int result, int arg1, int arg2)
		{
			if (arg2 == 0)
				throw devide_by_zero();
			global_value[result] = global_value[arg1] / arg2;
		}

		void OpDivCV(int result, int arg1, int arg2)
		{
			arg2 = global_value[arg2];
			if (arg2 == 0)
				throw devide_by_zero();
			global_value[result] = arg1 / arg2;
		}

		void OpDivVV(int result, int arg1, int arg2)
		{
			arg2 = global_value[arg2];
			if (arg2 == 0)
				throw devide_by_zero();
			global_value[result] = global_value[arg1] / arg2;
		}

		// %
		void OpModCC(int result, int arg1, int arg2)
		{
			if (arg2 == 0)
				throw devide_by_zero();
			global_value[result] = arg1 % arg2;
		}

		void OpModVC(int result, int arg1, int arg2)
		{
			if (arg2 == 0)
				throw devide_by_zero();
			global_value[result] = global_value[arg1] % arg2;
		}

		void OpModCV(int result, int arg1, int arg2)
		{
			arg2 = global_value[arg2];
			if (arg2 == 0)
				throw devide_by_zero();
			global_value[result] = arg1 % arg2;
		}

		void OpModVV(int result, int arg1, int arg2)
		{
			arg2 = global_value[arg2];
			if (arg2 == 0)
				throw devide_by_zero();
			global_value[result] = global_value[arg1] % arg2;
		}

		// 無条件ジャンプ
		void OpJmp(int addr)
		{
			jmp(addr);
		}

		// 真の時ジャンプ
		void OpJmpC(int addr, int arg)
		{
			if (global_value[arg])
				jmp(addr);
		}

		// 偽の時ジャンプ
		void OpJmpNC(int addr, int arg)
		{
			if (!global_value[arg])
				jmp(addr);
		}

		// 仮想CPUプログラム停止
		void OpHalt()
		{
		}

		// 乱数
		void OpRandC(int result, int arg)
		{
			global_value[result] = (arg <= 0)? 0: (rand() % arg);
		}

		void OpRandV(int result, int arg)
		{
			arg = global_value[arg];
			global_value[result] = (arg <= 0)? 0: (rand() % arg);
		}

		void OpPrint(int count)
		{
			while (count--) {
				std::cout << top();
				pop();
				if (count)
					std::cout << ", ";
			}
			std::cout << std::endl;
		}

	  private:
		const int *value(int n) { const int *v = (const int *)command_ptr_; command_ptr_ += 4 * n; return v; }
		int addr() const { return (int)(command_ptr_ - command_); }
		void jmp(int addr) { command_ptr_ = command_ + addr; }
		void push(int v) { stack.push(v); }
		void pop() { stack.pop(); }
		const int top() const { return stack.top(); }
		int &top() { return stack.top(); }

	  private:
		data &data_;
		unsigned char *command_;
		unsigned char *command_ptr_;
		int command_size_;

		vm::stack<int, STACK_SIZE> stack;
		std::vector<int> global_value;
	} ;

}

#endif