0
|
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 }
|