Mercurial > hg > Members > nobuyasu > myCompiler
diff Bison-Flex/BasicCompiler-StackBase/UTF8/vm.cpp @ 2:fbe42292d479
upload test
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 10 May 2011 06:43:55 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Bison-Flex/BasicCompiler-StackBase/UTF8/vm.cpp Tue May 10 06:43:55 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; + } +}