Mercurial > hg > Members > nobuyasu > SampleSource
view boost-spirit/Compiler-boost-spirit/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" #ifdef _MSC_VER // // VS2008では、セキュアライブラリ関数(*_s)を使うよう警告が出ます。 // ここでは、一般化(gcc等の対応)のため、旧ライブラリを使用しているので、 // 警告を抑止しています。 // #pragma warning(disable: 4996) #endif #define VM_ENUMDEF enum { #include "vm_code.h" VM_MAXCOMMAND, } ; #undef VM_ENUMDEF namespace vm { enum { SYS_PRINT, SYS_TOSTR, } ; class data { public: data(): command_(0), text_buffer_(0) { } ~data() { delete[] command_; delete[] text_buffer_; } public: unsigned char *command_; // コマンドテーブル char *text_buffer_; // テキストデータ int command_size_; // コマンドサイズ int text_size_; // テキストサイズ int value_size_; // グローバル変数サイズ int entry_point_; // 開始位置 } ; // 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; const static int global_flag = 0x4000000; const static int global_mask = 0x3ffffff; public: vcpu(data &mem) : data_(mem) { } ~vcpu() { } int run(); private: // 定数Push void PushConst(int val) { push(val); } // 文字定数Push void PushString(int val) { push(std::string(text_buffer_ + val)); } // 変数Push void PushValue(int val) { push(global_value[val]); } // ローカル変数Push void PushLocal(int val) { push(stack[val + stack_base]); } // 配列からPush void PushArray(int val) { int index = top().i_; pop(); push(global_value[val + index]); } // ローカルの配列からPush void PushLocalArray(int val) { int index = top().i_; pop(); push(stack[val + stack_base + index]); } // ローカル変数(参照)Push void PushLocalRef(int val) { int addr = stack[val + stack_base].i_; push(ref_to_value(addr)); } // ローカルの配列(参照)からPush void PushLocalArrayRef(int val) { int addr = stack[val + stack_base].i_; int index = top().i_; pop(); push(ref_to_value(addr + index)); } // アドレスをPush void PushAddr(int val) { if ((val & global_flag) == 0) // local val += + stack_base; push(val); } // 配列のアドレスをPush void PushArrayAddr(int val) { if ((val & global_flag) == 0) // local val += + stack_base; int index = top().i_; pop(); push(val + index); } // 変数にPop void PopValue(int val) { global_value[val] = top(); pop(); } // ローカル変数にPop void PopLocal(int val) { stack[val + stack_base] = top(); pop(); } // 配列変数にPop void PopArray(int val) { int index = top().i_; pop(); global_value[val + index] = top(); pop(); } // ローカルの配列変数にPop void PopLocalArray(int val) { int index = top().i_; pop(); stack[val + stack_base + index] = top(); pop(); } // ローカル変数(参照)にPop void PopLocalRef(int val) { int addr = stack[val + stack_base].i_; set_ref(addr, top()); pop(); } // ローカルの配列変数(参照)にPop void PopLocalArrayRef(int val) { int addr = stack[val + stack_base].i_; int index = top().i_; pop(); set_ref(addr + index, top()); pop(); } // ローカル変数を確保 void OpAllocStack(int val) { stack.resize(stack_base + val); } // 空Pop(スタックトップを捨てる) void OpPop() { pop(); } // 単項マイナス void OpNeg() { top().i_ = -top().i_; } // == void OpEq() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs == rhs); } // != void OpNe() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs != rhs); } // > void OpGt() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs > rhs); } // >= void OpGe() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs >= rhs); } // < void OpLt() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs < rhs); } // <= void OpLe() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs <= rhs); } // && void OpLogAnd() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs && rhs); } // || void OpLogOr() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs || rhs); } // & void OpAnd() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs & rhs); } // | void OpOr() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs | rhs); } // << void OpLeftShift() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs << rhs); } // >> void OpRightShift() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs >> rhs); } // + void OpAdd() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs + rhs); } // - void OpSub() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs - rhs); } // * void OpMul() { int rhs = top().i_; pop(); int lhs = top().i_; pop(); push(lhs * rhs); } // / void OpDiv() { int rhs = top().i_; pop(); if (rhs == 0) throw devide_by_zero(); int lhs = top().i_; pop(); push(lhs / rhs); } // % void OpMod() { int rhs = top().i_; pop(); if (rhs == 0) throw devide_by_zero(); int lhs = top().i_; pop(); push(lhs % rhs); } // 文字列の== void OpStrEq() { const std::string &rhs = text(top()); pop(); const std::string &lhs = text(top()); pop(); push(lhs == rhs); } // 文字列の!= void OpStrNe() { const std::string &rhs = text(top()); pop(); const std::string &lhs = text(top()); pop(); push(lhs != rhs); } // 文字列の> void OpStrGt() { const std::string &rhs = text(top()); pop(); const std::string &lhs = text(top()); pop(); push(lhs > rhs); } // 文字列の>= void OpStrGe() { const std::string &rhs = text(top()); pop(); const std::string &lhs = text(top()); pop(); push(lhs >= rhs); } // 文字列の< void OpStrLt() { const std::string &rhs = text(top()); pop(); const std::string &lhs = text(top()); pop(); push(lhs < rhs); } // 文字列の<= void OpStrLe() { const std::string &rhs = text(top()); pop(); const std::string &lhs = text(top()); pop(); push(lhs <= rhs); } // 文字列の+ void OpStrAdd() { const std::string &rhs = text(top()); pop(); const std::string &lhs = text(top()); pop(); push(lhs + rhs); } // 無条件ジャンプ void OpJmp(int val) { jmp(val); } // 真の時ジャンプ void OpJmpC(int val) { int cond = top().i_; pop(); if (cond) jmp(val); } // 偽の時ジャンプ void OpJmpNC(int val) { int cond = top().i_; pop(); if (!cond) jmp(val); } // switch文用特殊判定 void OpTest(int val) { int value = top().i_; pop(); if (value == top().i_) { pop(); jmp(val); } } // 関数コール void OpCall(int val) { push(stack_base); push(addr()); // リターンアドレスをPush stack_base = stack.size(); // スタックベース更新 jmp(val); } // 引数なしリターン void OpReturn() { stack.resize(stack_base); // ローカル変数排除 int addr = top().i_; pop(); stack_base = top().i_; pop(); int arg_count = top().i_; pop(); stack.pop(arg_count); jmp(addr); } // 引数付きリターン void OpReturnV() { vm::value result = top(); pop(); stack.resize(stack_base); // ローカル変数排除 int addr = top().i_; pop(); stack_base = top().i_; pop(); int arg_count = top().i_; pop(); stack.pop(arg_count); push(result); jmp(addr); } // 仮想CPUプログラム停止 void OpHalt() { } // システムコール(組み込み関数) void OpSysCall(int val) { pop(); // arg_count switch (val) { case SYS_PRINT: sys_print(); break; case SYS_TOSTR: sys_tostr(); break; } } // システムコール(print) void sys_print() { std::cout << text(top()); pop(); } // システムコール(数値を文字列に変換) void sys_tostr() { int v = top().i_; pop(); char str[16]; sprintf(str, "%d", v); push(std::string(str)); // 戻り値はスタックに入れる } private: int value() { int v = *(int *)command_ptr_; command_ptr_ += 4; return v; } int addr() const { return (int)(command_ptr_ - command_); } void jmp(int addr) { command_ptr_ = command_ + addr; } void push(int v) { stack.push(vm::value(v)); } void push(const std::string &v) { stack.push(vm::value(v)); } void push(const vm::value &v) { stack.push(v); } void pop() { stack.pop(); } const vm::value &top() const { return stack.top(); } vm::value &top() { return stack.top(); } std::string text(const vm::value &v) { return v.s_->str_; } const vm::value &ref_to_value(int addr) const { if (addr & global_flag) return global_value[addr & global_mask]; return stack[addr]; } void set_ref(int addr, const vm::value &v) { if (addr & global_flag) global_value[addr & global_mask] = v; else stack[addr] = v; } private: data &data_; unsigned char *command_; unsigned char *command_ptr_; int command_size_; char *text_buffer_; int text_size_; vm::stack<vm::value, STACK_SIZE> stack; std::vector<vm::value> global_value; int stack_base; } ; } #endif