Mercurial > hg > Members > nobuyasu > SampleSource
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:db40c85cad7a |
---|---|
1 // | |
2 // 仮想CPU | |
3 // | |
4 // 関数ポインタベースでの実装例 | |
5 // | |
6 // (c)2008 Chihiro.SAKAMOTO HyperWorks | |
7 // | |
8 #include <exception> | |
9 #include "vm.h" | |
10 | |
11 namespace vm { | |
12 | |
13 // 0除算例外 | |
14 class devide_by_zero: public std::exception { | |
15 public: | |
16 const char *what() const throw() | |
17 { | |
18 return "devide by zero"; | |
19 } | |
20 } ; | |
21 | |
22 void (vcpu::*vcpu::cmd_[])() = { | |
23 #define VM_EXECTABLE | |
24 #include "vm_code.h" | |
25 #undef VM_EXECTABLE | |
26 } ; | |
27 | |
28 // 実行 | |
29 int vcpu::run() | |
30 { | |
31 command_ = data_.command_; // プログラム格納位置 | |
32 command_size_ = data_.command_size_; // プログラムの大きさ | |
33 | |
34 global_value.resize(data_.value_size_); // 外部変数テーブル確保 | |
35 command_ptr_ = command_; // プログラムカウンター初期化 | |
36 | |
37 active = true; // Haltしていない | |
38 | |
39 try { | |
40 while (active) { // Haltするまでループ | |
41 int op = *command_ptr_++; | |
42 (this->*cmd_[op])(); | |
43 } | |
44 } | |
45 catch (const std::exception &e) { | |
46 std::cerr << "例外発生(" << e.what() << ")" << std::endl; | |
47 return -1; | |
48 } | |
49 return 0; | |
50 } | |
51 | |
52 // 定数Push | |
53 void vcpu::PushConst() | |
54 { | |
55 push(value()); | |
56 } | |
57 | |
58 // 変数Push | |
59 void vcpu::PushValue() | |
60 { | |
61 push(global_value[value()]); | |
62 } | |
63 | |
64 // 変数にPop | |
65 void vcpu::PopValue() | |
66 { | |
67 global_value[value()] = top(); pop(); | |
68 } | |
69 | |
70 // 空Pop(スタックトップを捨てる) | |
71 void vcpu::OpPop() | |
72 { | |
73 pop(); | |
74 } | |
75 | |
76 // 単項マイナス | |
77 void vcpu::OpNeg() | |
78 { | |
79 top() = -top(); | |
80 } | |
81 | |
82 // == | |
83 void vcpu::OpEq() | |
84 { | |
85 int rhs = top(); pop(); | |
86 int lhs = top(); pop(); | |
87 push(lhs == rhs); | |
88 } | |
89 | |
90 // != | |
91 void vcpu::OpNe() | |
92 { | |
93 int rhs = top(); pop(); | |
94 int lhs = top(); pop(); | |
95 push(lhs != rhs); | |
96 } | |
97 | |
98 // > | |
99 void vcpu::OpGt() | |
100 { | |
101 int rhs = top(); pop(); | |
102 int lhs = top(); pop(); | |
103 push(lhs > rhs); | |
104 } | |
105 | |
106 // >= | |
107 void vcpu::OpGe() | |
108 { | |
109 int rhs = top(); pop(); | |
110 int lhs = top(); pop(); | |
111 push(lhs >= rhs); | |
112 } | |
113 | |
114 // < | |
115 void vcpu::OpLt() | |
116 { | |
117 int rhs = top(); pop(); | |
118 int lhs = top(); pop(); | |
119 push(lhs < rhs); | |
120 } | |
121 | |
122 // <= | |
123 void vcpu::OpLe() | |
124 { | |
125 int rhs = top(); pop(); | |
126 int lhs = top(); pop(); | |
127 push(lhs <= rhs); | |
128 } | |
129 | |
130 // + | |
131 void vcpu::OpAdd() | |
132 { | |
133 int rhs = top(); pop(); | |
134 int lhs = top(); pop(); | |
135 push(lhs + rhs); | |
136 } | |
137 | |
138 // - | |
139 void vcpu::OpSub() | |
140 { | |
141 int rhs = top(); pop(); | |
142 int lhs = top(); pop(); | |
143 push(lhs - rhs); | |
144 } | |
145 | |
146 // * | |
147 void vcpu::OpMul() | |
148 { | |
149 int rhs = top(); pop(); | |
150 int lhs = top(); pop(); | |
151 push(lhs * rhs); | |
152 } | |
153 | |
154 // / | |
155 void vcpu::OpDiv() | |
156 { | |
157 int rhs = top(); pop(); | |
158 if (rhs == 0) | |
159 throw devide_by_zero(); | |
160 int lhs = top(); pop(); | |
161 push(lhs / rhs); | |
162 } | |
163 | |
164 // % | |
165 void vcpu::OpMod() | |
166 { | |
167 int rhs = top(); pop(); | |
168 if (rhs == 0) | |
169 throw devide_by_zero(); | |
170 int lhs = top(); pop(); | |
171 push(lhs % rhs); | |
172 } | |
173 | |
174 // 無条件ジャンプ | |
175 void vcpu::OpJmp() | |
176 { | |
177 jmp(value()); | |
178 } | |
179 | |
180 // 真の時ジャンプ | |
181 void vcpu::OpJmpC() | |
182 { | |
183 int addr = value(); | |
184 int cond = top(); pop(); | |
185 if (cond) | |
186 jmp(addr); | |
187 } | |
188 | |
189 // 偽の時ジャンプ | |
190 void vcpu::OpJmpNC() | |
191 { | |
192 int addr = value(); | |
193 int cond = top(); pop(); | |
194 if (!cond) | |
195 jmp(addr); | |
196 } | |
197 | |
198 // 仮想CPUプログラム停止 | |
199 void vcpu::OpHalt() | |
200 { | |
201 active = false; | |
202 } | |
203 | |
204 void vcpu::OpRand() | |
205 { | |
206 int range = top(); pop(); | |
207 int value = (range <= 0)? 0: (rand() % range); | |
208 push(value); | |
209 } | |
210 | |
211 void vcpu::OpPrint() | |
212 { | |
213 int count = value(); | |
214 while (count--) { | |
215 std::cout << top(); | |
216 pop(); | |
217 if (count) | |
218 std::cout << ", "; | |
219 } | |
220 std::cout << std::endl; | |
221 } | |
222 } |