fork download
  1. #include<cstdlib>
  2. #include<cstdint>
  3. #include<cstddef>
  4. #include<cstdio>
  5. #include<initializer_list>
  6.  
  7.  
  8.  
  9. namespace test{
  10.  
  11.  
  12. enum class
  13. opcode
  14. {
  15. nop,
  16. psh0,
  17. psh,
  18. pop,
  19. add,
  20. lt,
  21. brz,
  22. ld,
  23. st,
  24. inc,
  25. exi,
  26.  
  27. };
  28.  
  29.  
  30. class
  31. vm
  32. {
  33. uint32_t m_pc=8;
  34. uint32_t m_bp=80;
  35. uint32_t m_sp=80;
  36.  
  37. int32_t m_memory[256];
  38.  
  39. bool m_is_exited=false;
  40.  
  41. void push(int32_t v) noexcept
  42. {
  43. m_memory[m_sp--] = v;
  44. }
  45.  
  46. int32_t pop() noexcept
  47. {
  48. return m_memory[++m_sp];
  49. }
  50.  
  51. int32_t fetch() noexcept
  52. {
  53. return m_memory[m_pc++];
  54. }
  55.  
  56. public:
  57. vm(std::initializer_list<int32_t> ls) noexcept
  58. {
  59. int32_t* p = &m_memory[8];
  60.  
  61. for(auto v: ls)
  62. {
  63. *p++ = v;
  64. }
  65. }
  66.  
  67. bool is_exited() const noexcept{return m_is_exited;}
  68.  
  69. uint32_t get_pc() const noexcept{return m_pc;}
  70.  
  71. int32_t get_value(int32_t i) const noexcept{return m_memory[i];}
  72.  
  73. void step() noexcept
  74. {
  75. auto inst = fetch();
  76.  
  77. int32_t lv;
  78. int32_t rv;
  79.  
  80. switch(static_cast<opcode>(inst))
  81. {
  82. case(opcode::nop):
  83. break;
  84. case(opcode::psh0):
  85. push(0);
  86. break;
  87. case(opcode::psh):
  88. push(fetch());
  89. break;
  90. case(opcode::add):
  91. rv = pop();
  92. lv = pop();
  93.  
  94. push(lv+rv);
  95. break;
  96. case(opcode::lt):
  97. rv = pop();
  98. lv = pop();
  99.  
  100. push((lv < rv)? 1:0);
  101. break;
  102. case(opcode::ld):
  103. lv = pop();
  104.  
  105. push(get_value(lv));
  106. break;
  107. case(opcode::st):
  108. rv = pop();
  109. lv = pop();
  110.  
  111. m_memory[rv] = lv;
  112. break;
  113. case(opcode::inc):
  114. lv = pop();
  115.  
  116. m_memory[lv] += 1;
  117. break;
  118. case(opcode::brz):
  119. rv = pop();
  120. lv = pop();
  121.  
  122. if(!lv)
  123. {
  124. m_pc += rv;
  125. }
  126. break;
  127. case(opcode::exi):
  128. m_is_exited = true;
  129. break;
  130. default:
  131. printf("[%d]",inst);
  132. }
  133. }
  134.  
  135. };
  136.  
  137.  
  138.  
  139. }
  140.  
  141.  
  142. int
  143. main(int argc, char** argv)
  144. {
  145. using namespace test;
  146.  
  147. bool pr = (argc > 1);
  148.  
  149. test::vm vm({
  150. static_cast<int32_t>(opcode::psh0),
  151. static_cast<int32_t>(opcode::psh0),
  152. static_cast<int32_t>(opcode::st),
  153. static_cast<int32_t>(opcode::psh0),
  154. static_cast<int32_t>(opcode::ld),
  155. static_cast<int32_t>(opcode::psh),0xFFFFFF,
  156. static_cast<int32_t>(opcode::lt),
  157. static_cast<int32_t>(opcode::psh),6,
  158. static_cast<int32_t>(opcode::brz),
  159.  
  160. static_cast<int32_t>(opcode::psh0),
  161. static_cast<int32_t>(opcode::inc),
  162.  
  163. static_cast<int32_t>(opcode::psh0),
  164. static_cast<int32_t>(opcode::psh),-14,
  165. static_cast<int32_t>(opcode::brz),
  166. static_cast<int32_t>(opcode::exi),
  167. });
  168.  
  169. while(!vm.is_exited())
  170. {
  171. if(pr){printf("%8d",vm.get_pc());}
  172. vm.step();
  173. if(pr){printf(" %8d\n",vm.get_value(0));}
  174. }
  175.  
  176.  
  177.  
  178. return 0;
  179. }
  180.  
  181.  
  182.  
  183.  
Success #stdin #stdout 1.31s 4348KB
stdin
Standard input is empty
stdout
Standard output is empty