0
|
1 #ifndef __VM_H__
|
|
2 #define __VM_H__
|
|
3
|
|
4 #include <vector>
|
|
5 #include "vm_value.h"
|
|
6
|
|
7 #ifdef _MSC_VER
|
|
8 //
|
|
9 // VS2008�ł́A�Z�L���A���C�u�������i*_s�j���g���悤�x�����o�܂��B
|
|
10 // �����ł́A��ʉ��igcc���̑Ή��j�̂��߁A�����C�u�������g�p���Ă���̂ŁA
|
|
11 // �x����}�~���Ă��܂��B
|
|
12 //
|
|
13 #pragma warning(disable: 4996)
|
|
14 #endif
|
|
15
|
|
16 #define VM_ENUMDEF
|
|
17 enum {
|
|
18 #include "vm_code.h"
|
|
19 VM_MAXCOMMAND,
|
|
20 } ;
|
|
21 #undef VM_ENUMDEF
|
|
22
|
|
23 namespace vm {
|
|
24
|
|
25 enum {
|
|
26 SYS_PRINT,
|
|
27 SYS_TOSTR,
|
|
28 } ;
|
|
29
|
|
30 class data {
|
|
31 public:
|
|
32 data(): command_(0), text_buffer_(0)
|
|
33 {
|
|
34 }
|
|
35 ~data()
|
|
36 {
|
|
37 delete[] command_;
|
|
38 delete[] text_buffer_;
|
|
39 }
|
|
40
|
|
41 public:
|
|
42 unsigned char *command_; // �R�}���h�e�[�u��
|
|
43 char *text_buffer_; // �e�L�X�g�f�[�^
|
|
44 int command_size_; // �R�}���h�T�C�Y
|
|
45 int text_size_; // �e�L�X�g�T�C�Y
|
|
46 int value_size_; // �O���[�o���ϐ��T�C�Y
|
|
47 int entry_point_; // �J�n�ʒu
|
|
48 } ;
|
|
49
|
|
50
|
|
51 // 0���Z��O
|
|
52 class devide_by_zero: public std::exception {
|
|
53 public:
|
|
54 const char *what() const throw()
|
|
55 {
|
|
56 return "devide by zero";
|
|
57 }
|
|
58 } ;
|
|
59
|
|
60 // ���z�}�V��
|
|
61 class vcpu {
|
|
62 public:
|
|
63 const static int STACK_SIZE = 1000;
|
|
64 const static int global_flag = 0x4000000;
|
|
65 const static int global_mask = 0x3ffffff;
|
|
66
|
|
67
|
|
68 public:
|
|
69 vcpu(data &mem)
|
|
70 : data_(mem)
|
|
71 {
|
|
72 }
|
|
73 ~vcpu()
|
|
74 {
|
|
75 }
|
|
76
|
|
77 int run();
|
|
78
|
|
79 private:
|
|
80 // �萔Push
|
|
81 void PushConst(int val)
|
|
82 {
|
|
83 push(val);
|
|
84 }
|
|
85
|
|
86 // �����萔Push
|
|
87 void PushString(int val)
|
|
88 {
|
|
89 push(std::string(text_buffer_ + val));
|
|
90 }
|
|
91
|
|
92 // �ϐ�Push
|
|
93 void PushValue(int val)
|
|
94 {
|
|
95 push(global_value[val]);
|
|
96 }
|
|
97
|
|
98 // ���[�J���ϐ�Push
|
|
99 void PushLocal(int val)
|
|
100 {
|
|
101 push(stack[val + stack_base]);
|
|
102 }
|
|
103
|
|
104 // �z��Push
|
|
105 void PushArray(int val)
|
|
106 {
|
|
107 int index = top().i_; pop();
|
|
108 push(global_value[val + index]);
|
|
109 }
|
|
110
|
|
111 // ���[�J���̔z��Push
|
|
112 void PushLocalArray(int val)
|
|
113 {
|
|
114 int index = top().i_; pop();
|
|
115 push(stack[val + stack_base + index]);
|
|
116 }
|
|
117
|
|
118 // ���[�J���ϐ�(�Q��)Push
|
|
119 void PushLocalRef(int val)
|
|
120 {
|
|
121 int addr = stack[val + stack_base].i_;
|
|
122 push(ref_to_value(addr));
|
|
123 }
|
|
124
|
|
125 // ���[�J���̔z��(�Q��)����Push
|
|
126 void PushLocalArrayRef(int val)
|
|
127 {
|
|
128 int addr = stack[val + stack_base].i_;
|
|
129 int index = top().i_; pop();
|
|
130 push(ref_to_value(addr + index));
|
|
131 }
|
|
132
|
|
133 // �A�h���X��Push
|
|
134 void PushAddr(int val)
|
|
135 {
|
|
136 if ((val & global_flag) == 0) // local
|
|
137 val += + stack_base;
|
|
138 push(val);
|
|
139 }
|
|
140
|
|
141 // �z��̃A�h���X��Push
|
|
142 void PushArrayAddr(int val)
|
|
143 {
|
|
144 if ((val & global_flag) == 0) // local
|
|
145 val += + stack_base;
|
|
146 int index = top().i_; pop();
|
|
147 push(val + index);
|
|
148 }
|
|
149
|
|
150 // �ϐ���Pop
|
|
151 void PopValue(int val)
|
|
152 {
|
|
153 global_value[val] = top(); pop();
|
|
154 }
|
|
155
|
|
156 // ���[�J���ϐ���Pop
|
|
157 void PopLocal(int val)
|
|
158 {
|
|
159 stack[val + stack_base] = top(); pop();
|
|
160 }
|
|
161
|
|
162 // �z��ϐ���Pop
|
|
163 void PopArray(int val)
|
|
164 {
|
|
165 int index = top().i_; pop();
|
|
166 global_value[val + index] = top(); pop();
|
|
167 }
|
|
168
|
|
169 // ���[�J���̔z��ϐ���Pop
|
|
170 void PopLocalArray(int val)
|
|
171 {
|
|
172 int index = top().i_; pop();
|
|
173 stack[val + stack_base + index] = top(); pop();
|
|
174 }
|
|
175
|
|
176 // ���[�J���ϐ�(�Q��)��Pop
|
|
177 void PopLocalRef(int val)
|
|
178 {
|
|
179 int addr = stack[val + stack_base].i_;
|
|
180 set_ref(addr, top()); pop();
|
|
181 }
|
|
182
|
|
183 // ���[�J���̔z��ϐ�(�Q��)��Pop
|
|
184 void PopLocalArrayRef(int val)
|
|
185 {
|
|
186 int addr = stack[val + stack_base].i_;
|
|
187 int index = top().i_; pop();
|
|
188 set_ref(addr + index, top()); pop();
|
|
189 }
|
|
190
|
|
191 // ���[�J���ϐ����m��
|
|
192 void OpAllocStack(int val)
|
|
193 {
|
|
194 stack.resize(stack_base + val);
|
|
195 }
|
|
196
|
|
197 // ��Pop�i�X�^�b�N�g�b�v���̂Ă�j
|
|
198 void OpPop()
|
|
199 {
|
|
200 pop();
|
|
201 }
|
|
202
|
|
203 // �P���}�C�i�X
|
|
204 void OpNeg()
|
|
205 {
|
|
206 top().i_ = -top().i_;
|
|
207 }
|
|
208
|
|
209 // ==
|
|
210 void OpEq()
|
|
211 {
|
|
212 int rhs = top().i_; pop();
|
|
213 int lhs = top().i_; pop();
|
|
214 push(lhs == rhs);
|
|
215 }
|
|
216
|
|
217 // !=
|
|
218 void OpNe()
|
|
219 {
|
|
220 int rhs = top().i_; pop();
|
|
221 int lhs = top().i_; pop();
|
|
222 push(lhs != rhs);
|
|
223 }
|
|
224
|
|
225 // >
|
|
226 void OpGt()
|
|
227 {
|
|
228 int rhs = top().i_; pop();
|
|
229 int lhs = top().i_; pop();
|
|
230 push(lhs > rhs);
|
|
231 }
|
|
232
|
|
233 // >=
|
|
234 void OpGe()
|
|
235 {
|
|
236 int rhs = top().i_; pop();
|
|
237 int lhs = top().i_; pop();
|
|
238 push(lhs >= rhs);
|
|
239 }
|
|
240
|
|
241 // <
|
|
242 void OpLt()
|
|
243 {
|
|
244 int rhs = top().i_; pop();
|
|
245 int lhs = top().i_; pop();
|
|
246 push(lhs < rhs);
|
|
247 }
|
|
248
|
|
249 // <=
|
|
250 void OpLe()
|
|
251 {
|
|
252 int rhs = top().i_; pop();
|
|
253 int lhs = top().i_; pop();
|
|
254 push(lhs <= rhs);
|
|
255 }
|
|
256
|
|
257 // &&
|
|
258 void OpLogAnd()
|
|
259 {
|
|
260 int rhs = top().i_; pop();
|
|
261 int lhs = top().i_; pop();
|
|
262 push(lhs && rhs);
|
|
263 }
|
|
264
|
|
265 // ||
|
|
266 void OpLogOr()
|
|
267 {
|
|
268 int rhs = top().i_; pop();
|
|
269 int lhs = top().i_; pop();
|
|
270 push(lhs || rhs);
|
|
271 }
|
|
272
|
|
273 // &
|
|
274 void OpAnd()
|
|
275 {
|
|
276 int rhs = top().i_; pop();
|
|
277 int lhs = top().i_; pop();
|
|
278 push(lhs & rhs);
|
|
279 }
|
|
280
|
|
281 // |
|
|
282 void OpOr()
|
|
283 {
|
|
284 int rhs = top().i_; pop();
|
|
285 int lhs = top().i_; pop();
|
|
286 push(lhs | rhs);
|
|
287 }
|
|
288
|
|
289 // <<
|
|
290 void OpLeftShift()
|
|
291 {
|
|
292 int rhs = top().i_; pop();
|
|
293 int lhs = top().i_; pop();
|
|
294 push(lhs << rhs);
|
|
295 }
|
|
296
|
|
297 // >>
|
|
298 void OpRightShift()
|
|
299 {
|
|
300 int rhs = top().i_; pop();
|
|
301 int lhs = top().i_; pop();
|
|
302 push(lhs >> rhs);
|
|
303 }
|
|
304
|
|
305 // +
|
|
306 void OpAdd()
|
|
307 {
|
|
308 int rhs = top().i_; pop();
|
|
309 int lhs = top().i_; pop();
|
|
310 push(lhs + rhs);
|
|
311 }
|
|
312
|
|
313 // -
|
|
314 void OpSub()
|
|
315 {
|
|
316 int rhs = top().i_; pop();
|
|
317 int lhs = top().i_; pop();
|
|
318 push(lhs - rhs);
|
|
319 }
|
|
320
|
|
321 // *
|
|
322 void OpMul()
|
|
323 {
|
|
324 int rhs = top().i_; pop();
|
|
325 int lhs = top().i_; pop();
|
|
326 push(lhs * rhs);
|
|
327 }
|
|
328
|
|
329 // /
|
|
330 void OpDiv()
|
|
331 {
|
|
332 int rhs = top().i_; pop();
|
|
333 if (rhs == 0)
|
|
334 throw devide_by_zero();
|
|
335 int lhs = top().i_; pop();
|
|
336 push(lhs / rhs);
|
|
337 }
|
|
338
|
|
339 // %
|
|
340 void OpMod()
|
|
341 {
|
|
342 int rhs = top().i_; pop();
|
|
343 if (rhs == 0)
|
|
344 throw devide_by_zero();
|
|
345 int lhs = top().i_; pop();
|
|
346 push(lhs % rhs);
|
|
347 }
|
|
348
|
|
349 // �������==
|
|
350 void OpStrEq()
|
|
351 {
|
|
352 const std::string &rhs = text(top()); pop();
|
|
353 const std::string &lhs = text(top()); pop();
|
|
354
|
|
355 push(lhs == rhs);
|
|
356 }
|
|
357
|
|
358 // �������!=
|
|
359 void OpStrNe()
|
|
360 {
|
|
361 const std::string &rhs = text(top()); pop();
|
|
362 const std::string &lhs = text(top()); pop();
|
|
363
|
|
364 push(lhs != rhs);
|
|
365 }
|
|
366
|
|
367 // �������>
|
|
368 void OpStrGt()
|
|
369 {
|
|
370 const std::string &rhs = text(top()); pop();
|
|
371 const std::string &lhs = text(top()); pop();
|
|
372
|
|
373 push(lhs > rhs);
|
|
374 }
|
|
375
|
|
376 // �������>=
|
|
377 void OpStrGe()
|
|
378 {
|
|
379 const std::string &rhs = text(top()); pop();
|
|
380 const std::string &lhs = text(top()); pop();
|
|
381
|
|
382 push(lhs >= rhs);
|
|
383 }
|
|
384
|
|
385 // �������<
|
|
386 void OpStrLt()
|
|
387 {
|
|
388 const std::string &rhs = text(top()); pop();
|
|
389 const std::string &lhs = text(top()); pop();
|
|
390
|
|
391 push(lhs < rhs);
|
|
392 }
|
|
393
|
|
394 // �������<=
|
|
395 void OpStrLe()
|
|
396 {
|
|
397 const std::string &rhs = text(top()); pop();
|
|
398 const std::string &lhs = text(top()); pop();
|
|
399
|
|
400 push(lhs <= rhs);
|
|
401 }
|
|
402
|
|
403 // �������+
|
|
404 void OpStrAdd()
|
|
405 {
|
|
406 const std::string &rhs = text(top()); pop();
|
|
407 const std::string &lhs = text(top()); pop();
|
|
408
|
|
409 push(lhs + rhs);
|
|
410 }
|
|
411
|
|
412 // �������W�����v
|
|
413 void OpJmp(int val)
|
|
414 {
|
|
415 jmp(val);
|
|
416 }
|
|
417
|
|
418 // �^�̎��W�����v
|
|
419 void OpJmpC(int val)
|
|
420 {
|
|
421 int cond = top().i_; pop();
|
|
422 if (cond)
|
|
423 jmp(val);
|
|
424 }
|
|
425
|
|
426 // �U�̎��W�����v
|
|
427 void OpJmpNC(int val)
|
|
428 {
|
|
429 int cond = top().i_; pop();
|
|
430 if (!cond)
|
|
431 jmp(val);
|
|
432 }
|
|
433
|
|
434 // switch���p���ꔻ��
|
|
435 void OpTest(int val)
|
|
436 {
|
|
437 int value = top().i_; pop();
|
|
438 if (value == top().i_) {
|
|
439 pop();
|
|
440 jmp(val);
|
|
441 }
|
|
442 }
|
|
443
|
|
444 // ���R�[��
|
|
445 void OpCall(int val)
|
|
446 {
|
|
447 push(stack_base);
|
|
448 push(addr()); // ���^�[���A�h���X��Push
|
|
449 stack_base = stack.size(); // �X�^�b�N�x�[�X�X�V
|
|
450 jmp(val);
|
|
451 }
|
|
452
|
|
453 // �����Ȃ����^�[��
|
|
454 void OpReturn()
|
|
455 {
|
|
456 stack.resize(stack_base); // ���[�J���ϐ��r��
|
|
457 int addr = top().i_; pop();
|
|
458 stack_base = top().i_; pop();
|
|
459 int arg_count = top().i_; pop();
|
|
460 stack.pop(arg_count);
|
|
461 jmp(addr);
|
|
462 }
|
|
463
|
|
464 // �����t�����^�[��
|
|
465 void OpReturnV()
|
|
466 {
|
|
467 vm::value result = top(); pop();
|
|
468 stack.resize(stack_base); // ���[�J���ϐ��r��
|
|
469 int addr = top().i_; pop();
|
|
470 stack_base = top().i_; pop();
|
|
471 int arg_count = top().i_; pop();
|
|
472 stack.pop(arg_count);
|
|
473 push(result);
|
|
474 jmp(addr);
|
|
475 }
|
|
476
|
|
477 // ���zCPU�v���O������~
|
|
478 void OpHalt()
|
|
479 {
|
|
480 }
|
|
481
|
|
482 // �V�X�e���R�[���i�g�ݍ��݊��j
|
|
483 void OpSysCall(int val)
|
|
484 {
|
|
485 pop(); // arg_count
|
|
486 switch (val) {
|
|
487 case SYS_PRINT:
|
|
488 sys_print();
|
|
489 break;
|
|
490
|
|
491 case SYS_TOSTR:
|
|
492 sys_tostr();
|
|
493 break;
|
|
494 }
|
|
495 }
|
|
496
|
|
497 // �V�X�e���R�[���iprint�j
|
|
498 void sys_print()
|
|
499 {
|
|
500 std::cout << text(top());
|
|
501 pop();
|
|
502 }
|
|
503
|
|
504 // �V�X�e���R�[��(���l����ɕϊ�)
|
|
505 void sys_tostr()
|
|
506 {
|
|
507 int v = top().i_; pop();
|
|
508 char str[16];
|
|
509 sprintf(str, "%d", v);
|
|
510 push(std::string(str)); // �߂�l�̓X�^�b�N�ɓ����
|
|
511 }
|
|
512
|
|
513 private:
|
|
514 int value() { int v = *(int *)command_ptr_; command_ptr_ += 4; return v; }
|
|
515 int addr() const { return (int)(command_ptr_ - command_); }
|
|
516 void jmp(int addr) { command_ptr_ = command_ + addr; }
|
|
517 void push(int v) { stack.push(vm::value(v)); }
|
|
518 void push(const std::string &v) { stack.push(vm::value(v)); }
|
|
519 void push(const vm::value &v) { stack.push(v); }
|
|
520 void pop() { stack.pop(); }
|
|
521 const vm::value &top() const { return stack.top(); }
|
|
522 vm::value &top() { return stack.top(); }
|
|
523 std::string text(const vm::value &v) { return v.s_->str_; }
|
|
524 const vm::value &ref_to_value(int addr) const
|
|
525 {
|
|
526 if (addr & global_flag)
|
|
527 return global_value[addr & global_mask];
|
|
528 return stack[addr];
|
|
529 }
|
|
530 void set_ref(int addr, const vm::value &v)
|
|
531 {
|
|
532 if (addr & global_flag)
|
|
533 global_value[addr & global_mask] = v;
|
|
534 else
|
|
535 stack[addr] = v;
|
|
536 }
|
|
537
|
|
538 private:
|
|
539 data &data_;
|
|
540 unsigned char *command_;
|
|
541 unsigned char *command_ptr_;
|
|
542 int command_size_;
|
|
543 char *text_buffer_;
|
|
544 int text_size_;
|
|
545
|
|
546 vm::stack<vm::value, STACK_SIZE> stack;
|
|
547 std::vector<vm::value> global_value;
|
|
548 int stack_base;
|
|
549 } ;
|
|
550
|
|
551 }
|
|
552
|
|
553 #endif
|