#include<cstdlib>
#include<cstdint>
#include<cstddef>
#include<cstdio>
#include<initializer_list>
namespace test{
enum class
opcode
{
nop,
psh0,
psh,
pop,
add,
lt,
brz,
ld,
st,
inc,
exi,
};
class
vm
{
uint32_t m_pc=8;
uint32_t m_bp=80;
uint32_t m_sp=80;
int32_t m_memory[256];
bool m_is_exited=false;
void push(int32_t v) noexcept
{
m_memory[m_sp--] = v;
}
int32_t pop() noexcept
{
return m_memory[++m_sp];
}
int32_t fetch() noexcept
{
return m_memory[m_pc++];
}
public:
vm(std::initializer_list<int32_t> ls) noexcept
{
int32_t* p = &m_memory[8];
for(auto v: ls)
{
*p++ = v;
}
}
bool is_exited() const noexcept{return m_is_exited;}
uint32_t get_pc() const noexcept{return m_pc;}
int32_t get_value(int32_t i) const noexcept{return m_memory[i];}
void step() noexcept
{
auto inst = fetch();
int32_t lv;
int32_t rv;
switch(static_cast<opcode>(inst))
{
case(opcode::nop):
break;
case(opcode::psh0):
push(0);
break;
case(opcode::psh):
push(fetch());
break;
case(opcode::add):
rv = pop();
lv = pop();
push(lv+rv);
break;
case(opcode::lt):
rv = pop();
lv = pop();
push((lv < rv)? 1:0);
break;
case(opcode::ld):
lv = pop();
push(get_value(lv));
break;
case(opcode::st):
rv = pop();
lv = pop();
m_memory[rv] = lv;
break;
case(opcode::inc):
lv = pop();
m_memory[lv] += 1;
break;
case(opcode::brz):
rv = pop();
lv = pop();
if(!lv)
{
m_pc += rv;
}
break;
case(opcode::exi):
m_is_exited = true;
break;
default:
printf("[%d]",inst);
}
}
};
}
int
main(int argc, char** argv)
{
using namespace test;
bool pr = (argc > 1);
test::vm vm({
static_cast<int32_t>(opcode::psh0),
static_cast<int32_t>(opcode::psh0),
static_cast<int32_t>(opcode::st),
static_cast<int32_t>(opcode::psh0),
static_cast<int32_t>(opcode::ld),
static_cast<int32_t>(opcode::psh),0xFFFFFF,
static_cast<int32_t>(opcode::lt),
static_cast<int32_t>(opcode::psh),6,
static_cast<int32_t>(opcode::brz),
static_cast<int32_t>(opcode::psh0),
static_cast<int32_t>(opcode::inc),
static_cast<int32_t>(opcode::psh0),
static_cast<int32_t>(opcode::psh),-14,
static_cast<int32_t>(opcode::brz),
static_cast<int32_t>(opcode::exi),
});
while(!vm.is_exited())
{
if(pr){printf("%8d",vm.get_pc());}
vm.step();
if(pr){printf(" %8d\n",vm.get_value(0));}
}
return 0;
}
I2luY2x1ZGU8Y3N0ZGxpYj4KI2luY2x1ZGU8Y3N0ZGludD4KI2luY2x1ZGU8Y3N0ZGRlZj4KI2luY2x1ZGU8Y3N0ZGlvPgojaW5jbHVkZTxpbml0aWFsaXplcl9saXN0PgoKCgpuYW1lc3BhY2UgdGVzdHsKCgplbnVtIGNsYXNzCm9wY29kZQp7CiAgbm9wLAogIHBzaDAsCiAgcHNoLAogIHBvcCwKICBhZGQsCiAgbHQsCiAgYnJ6LAogIGxkLAogIHN0LAogIGluYywKICBleGksCgp9OwoKCmNsYXNzCnZtCnsKICB1aW50MzJfdCAgbV9wYz04OwogIHVpbnQzMl90ICBtX2JwPTgwOwogIHVpbnQzMl90ICBtX3NwPTgwOwoKICBpbnQzMl90ICBtX21lbW9yeVsyNTZdOwoKICBib29sICBtX2lzX2V4aXRlZD1mYWxzZTsKCiAgdm9pZCAgcHVzaChpbnQzMl90ICB2KSBub2V4Y2VwdAogIHsKICAgIG1fbWVtb3J5W21fc3AtLV0gPSB2OwogIH0KCiAgaW50MzJfdCAgcG9wKCkgbm9leGNlcHQKICB7CiAgICByZXR1cm4gbV9tZW1vcnlbKyttX3NwXTsKICB9CgogIGludDMyX3QgIGZldGNoKCkgbm9leGNlcHQKICB7CiAgICByZXR1cm4gbV9tZW1vcnlbbV9wYysrXTsKICB9CgpwdWJsaWM6CiAgdm0oc3RkOjppbml0aWFsaXplcl9saXN0PGludDMyX3Q+ICBscykgbm9leGNlcHQKICB7CiAgICBpbnQzMl90KiAgcCA9ICZtX21lbW9yeVs4XTsKCiAgICAgIGZvcihhdXRvICB2OiBscykKICAgICAgewogICAgICAgICpwKysgPSB2OwogICAgICB9CiAgfQoKICBib29sICBpc19leGl0ZWQoKSBjb25zdCBub2V4Y2VwdHtyZXR1cm4gbV9pc19leGl0ZWQ7fQoKICB1aW50MzJfdCAgZ2V0X3BjKCkgY29uc3Qgbm9leGNlcHR7cmV0dXJuIG1fcGM7fQoKICBpbnQzMl90ICBnZXRfdmFsdWUoaW50MzJfdCAgaSkgY29uc3Qgbm9leGNlcHR7cmV0dXJuIG1fbWVtb3J5W2ldO30KCiAgdm9pZCAgc3RlcCgpIG5vZXhjZXB0CiAgewogICAgYXV0byAgaW5zdCA9IGZldGNoKCk7CgogICAgaW50MzJfdCAgbHY7CiAgICBpbnQzMl90ICBydjsKCiAgICAgIHN3aXRjaChzdGF0aWNfY2FzdDxvcGNvZGU+KGluc3QpKQogICAgICB7CiAgICBjYXNlKG9wY29kZTo6bm9wKToKICAgICAgICBicmVhazsKICAgIGNhc2Uob3Bjb2RlOjpwc2gwKToKICAgICAgICBwdXNoKDApOwogICAgICAgIGJyZWFrOwogICAgY2FzZShvcGNvZGU6OnBzaCk6CiAgICAgICAgcHVzaChmZXRjaCgpKTsKICAgICAgICBicmVhazsKICAgIGNhc2Uob3Bjb2RlOjphZGQpOgogICAgICAgIHJ2ID0gcG9wKCk7CiAgICAgICAgbHYgPSBwb3AoKTsKCiAgICAgICAgcHVzaChsditydik7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlKG9wY29kZTo6bHQpOgogICAgICAgIHJ2ID0gcG9wKCk7CiAgICAgICAgbHYgPSBwb3AoKTsKCiAgICAgICAgcHVzaCgobHYgPCBydik/IDE6MCk7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlKG9wY29kZTo6bGQpOgogICAgICAgIGx2ID0gcG9wKCk7CgogICAgICAgIHB1c2goZ2V0X3ZhbHVlKGx2KSk7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlKG9wY29kZTo6c3QpOgogICAgICAgIHJ2ID0gcG9wKCk7CiAgICAgICAgbHYgPSBwb3AoKTsKCiAgICAgICAgbV9tZW1vcnlbcnZdID0gbHY7CiAgICAgICAgYnJlYWs7CiAgICBjYXNlKG9wY29kZTo6aW5jKToKICAgICAgICBsdiA9IHBvcCgpOwoKICAgICAgICBtX21lbW9yeVtsdl0gKz0gMTsKICAgICAgICBicmVhazsKICAgIGNhc2Uob3Bjb2RlOjpicnopOgogICAgICAgIHJ2ID0gcG9wKCk7CiAgICAgICAgbHYgPSBwb3AoKTsKCiAgICAgICAgICBpZighbHYpCiAgICAgICAgICB7CiAgICAgICAgICAgIG1fcGMgKz0gcnY7CiAgICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICBjYXNlKG9wY29kZTo6ZXhpKToKICAgICAgICBtX2lzX2V4aXRlZCA9IHRydWU7CiAgICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICAgIHByaW50ZigiWyVkXSIsaW5zdCk7CiAgICAgIH0KICB9Cgp9OwoKCgp9CgoKaW50Cm1haW4oaW50ICBhcmdjLCBjaGFyKiogIGFyZ3YpCnsKICB1c2luZyBuYW1lc3BhY2UgdGVzdDsKCiAgYm9vbCAgcHIgPSAoYXJnYyA+IDEpOwoKICB0ZXN0Ojp2bSAgdm0oewogICAgc3RhdGljX2Nhc3Q8aW50MzJfdD4ob3Bjb2RlOjpwc2gwKSwKICAgIHN0YXRpY19jYXN0PGludDMyX3Q+KG9wY29kZTo6cHNoMCksCiAgICBzdGF0aWNfY2FzdDxpbnQzMl90PihvcGNvZGU6OnN0KSwKICAgIHN0YXRpY19jYXN0PGludDMyX3Q+KG9wY29kZTo6cHNoMCksCiAgICBzdGF0aWNfY2FzdDxpbnQzMl90PihvcGNvZGU6OmxkKSwKICAgIHN0YXRpY19jYXN0PGludDMyX3Q+KG9wY29kZTo6cHNoKSwweEZGRkZGRiwKICAgIHN0YXRpY19jYXN0PGludDMyX3Q+KG9wY29kZTo6bHQpLAogICAgc3RhdGljX2Nhc3Q8aW50MzJfdD4ob3Bjb2RlOjpwc2gpLDYsCiAgICBzdGF0aWNfY2FzdDxpbnQzMl90PihvcGNvZGU6OmJyeiksCgogICAgc3RhdGljX2Nhc3Q8aW50MzJfdD4ob3Bjb2RlOjpwc2gwKSwKICAgIHN0YXRpY19jYXN0PGludDMyX3Q+KG9wY29kZTo6aW5jKSwKCiAgICBzdGF0aWNfY2FzdDxpbnQzMl90PihvcGNvZGU6OnBzaDApLAogICAgc3RhdGljX2Nhc3Q8aW50MzJfdD4ob3Bjb2RlOjpwc2gpLC0xNCwKICAgIHN0YXRpY19jYXN0PGludDMyX3Q+KG9wY29kZTo6YnJ6KSwKICAgIHN0YXRpY19jYXN0PGludDMyX3Q+KG9wY29kZTo6ZXhpKSwKICB9KTsKCiAgICB3aGlsZSghdm0uaXNfZXhpdGVkKCkpCiAgICB7CmlmKHByKXtwcmludGYoIiU4ZCIsdm0uZ2V0X3BjKCkpO30KICAgICAgdm0uc3RlcCgpOwppZihwcil7cHJpbnRmKCIgJThkXG4iLHZtLmdldF92YWx1ZSgwKSk7fQogICAgfQoKCgogIHJldHVybiAwOwp9CgoKCg==