#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct instruction {
size_t offset;
unsigned int opcode;
unsigned int mode;
unsigned int rdest;
unsigned int rsrc;
uint16_t imm;
} instruction;
static instruction instructions[16384];
size_t num_instructions = 0;
static const char *op_names[] = {
"MOVE", "OR", "XOR", "AND", "NOT", "ADD", "SUB", "MUL", "SHL", "SHR",
"INC", "DEC", "PUSH", "POP", "CMP", "JNZ", "JZ",
};
static void create_instructions(const uint8_t *code, size_t length)
{
for (size_t i = 0; i < length; i += 2) {
unsigned int opt = code[i + 1];
instruction insn = {
.offset = i,
.opcode = code[i],
.mode = opt & 15,
.rdest = (opt >> 4) & 3,
.rsrc = (opt >> 6) & 3,
.imm = 0xbaadU,
};
if (insn.opcode >= sizeof(op_names) / sizeof(op_names[0])) {
fprintf(stderr
, "Wrong opcode %u at %.8zx\n", insn.
opcode, insn.
offset); }
if (insn.mode >= 4) {
fprintf(stderr
, "Wrong mode %u at %.8zx\n", insn.
mode, insn.
offset); }
if (insn.mode == 0 || insn.mode == 2) {
i += 2;
insn.imm = code[i] | code[i + 1] << 8;
}
instructions[num_instructions++] = insn;
}
}
static void read_code(const char *filename)
{
static uint8_t code[65536];
FILE
*fp
= fopen(filename
, "rb"); if (!fp) {
}
size_t length
= fread(code
, 1, sizeof(code
), fp
);
create_instructions(code, length);
}
static void write_response(const char *filename, const uint16_t *regs)
{
FILE
*fp
= fopen(filename
, "wb"); if (!fp) {
}
fprintf(fp
, "%.4x %.4x %.4x %.4x\n", regs
[0], regs
[1], regs
[2], regs
[3]); }
int main(int argc, char *argv[])
{
if (argc != 3) {
fprintf(stderr
, "usage: %s <input file> <output file>", argv
[0]); return -1;
}
read_code(argv[1]);
size_t ip = 0;
uint16_t regs[4] = { 0 };
uint16_t stack[256];
size_t stackptr = 0;
bool zf = false;
while (ip < num_instructions) {
instruction *insn = &instructions[ip];
uint16_t *dest = NULL;
uint16_t *src = NULL;
uint16_t imm = insn->imm;
printf("%.4zx: %s\t", ip
, op_names
[insn
->opcode
]);
switch (insn->mode) {
case 0: // IMM.
dest = &imm;
break;
case 1: // REG.
dest = ®s[insn->rdest];
break;
case 2: // REG, IMM.
dest = ®s[insn->rdest];
src = &imm;
printf("r%u, %.4x", insn
->rdest
, insn
->imm
); break;
case 3: // REG, REG.
dest = ®s[insn->rdest];
src = ®s[insn->rsrc];
printf("r%u, r%u ", insn
->rdest
, insn
->rsrc
); break;
}
++ip;
switch (insn->opcode) {
case 0: // MOVE.
*dest = *src;
break;
case 1: // OR.
*dest = *dest | *src;
break;
case 2: // XOR.
*dest = *dest ^ *src;
break;
case 3: // AND.
*dest = *dest & *src;
break;
case 4: // NOT.
*dest = ~*dest;
break;
case 5: // ADD.
*dest += *src;
break;
case 6: // SUB.
*dest -= *src;
break;
case 7: // MUL.
*dest = *dest * *src;
break;
case 8: // SHL.
*dest <<= *src;
break;
case 9: // SHR.
*dest >>= *src;
break;
case 10: // INC.
*dest += 1;
break;
case 11: // DEC.
*dest -= 1;
break;
case 12: // PUSH.
if (stackptr >= sizeof(stack) / sizeof(stack[0])) {
fprintf(stderr
, "Stack overflow\n"); return 2;
}
stack[stackptr++] = *dest;
break;
case 13: // POP
if (stackptr == 0) {
fprintf(stderr
, "Stack underflow\n"); return 2;
}
*dest = stack[--stackptr];
break;
case 14: // CMP.
zf = (*dest - *src) == 0;
break;
case 15: // JNZ.
if (!zf) {
ip = *dest;
}
break;
case 16: // JZ.
if (zf) {
ip = *dest;
}
break;
}
// Set ZF for arithmetical and logical instructions (except CMP).
if (insn->opcode >= 1 && insn->opcode <= 11) {
zf = *dest == 0;
}
printf(" r0 = %.4x, r1 = %.4x, r2 = %.4x, r3 = %.4x, zf = %u\n", regs[0], regs[1], regs[2], regs[3], zf);
}
write_response(argv[2], regs);
return 0;
}
I2luY2x1ZGUgPHN0ZGJvb2wuaD4KI2luY2x1ZGUgPHN0ZGludC5oPgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0ZGxpYi5oPgojaW5jbHVkZSA8c3RyaW5nLmg+Cgp0eXBlZGVmIHN0cnVjdCBpbnN0cnVjdGlvbiB7CiAgICBzaXplX3Qgb2Zmc2V0OwogICAgdW5zaWduZWQgaW50IG9wY29kZTsKICAgIHVuc2lnbmVkIGludCBtb2RlOwogICAgdW5zaWduZWQgaW50IHJkZXN0OwogICAgdW5zaWduZWQgaW50IHJzcmM7CiAgICB1aW50MTZfdCBpbW07Cn0gaW5zdHJ1Y3Rpb247CgpzdGF0aWMgaW5zdHJ1Y3Rpb24gaW5zdHJ1Y3Rpb25zWzE2Mzg0XTsKc2l6ZV90IG51bV9pbnN0cnVjdGlvbnMgPSAwOwoKc3RhdGljIGNvbnN0IGNoYXIgKm9wX25hbWVzW10gPSB7CiAgICAiTU9WRSIsICJPUiIsICJYT1IiLCAiQU5EIiwgIk5PVCIsICJBREQiLCAiU1VCIiwgIk1VTCIsICJTSEwiLCAiU0hSIiwKICAgICJJTkMiLCAiREVDIiwgIlBVU0giLCAiUE9QIiwgIkNNUCIsICJKTloiLCAiSloiLAp9OwoKc3RhdGljIHZvaWQgY3JlYXRlX2luc3RydWN0aW9ucyhjb25zdCB1aW50OF90ICpjb2RlLCBzaXplX3QgbGVuZ3RoKQp7CiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgdW5zaWduZWQgaW50IG9wdCA9IGNvZGVbaSArIDFdOwoKICAgICAgICBpbnN0cnVjdGlvbiBpbnNuID0gewogICAgICAgICAgICAub2Zmc2V0ID0gaSwKICAgICAgICAgICAgLm9wY29kZSA9IGNvZGVbaV0sCiAgICAgICAgICAgIC5tb2RlID0gb3B0ICYgMTUsCiAgICAgICAgICAgIC5yZGVzdCA9IChvcHQgPj4gNCkgJiAzLAogICAgICAgICAgICAucnNyYyA9IChvcHQgPj4gNikgJiAzLAogICAgICAgICAgICAuaW1tID0gMHhiYWFkVSwKICAgICAgICB9OwoKICAgICAgICBpZiAoaW5zbi5vcGNvZGUgPj0gc2l6ZW9mKG9wX25hbWVzKSAvIHNpemVvZihvcF9uYW1lc1swXSkpIHsKICAgICAgICAgICAgZnByaW50ZihzdGRlcnIsICJXcm9uZyBvcGNvZGUgJXUgYXQgJS44enhcbiIsIGluc24ub3Bjb2RlLCBpbnNuLm9mZnNldCk7CiAgICAgICAgICAgIGV4aXQoMSk7CiAgICAgICAgfQoKICAgICAgICBpZiAoaW5zbi5tb2RlID49IDQpIHsKICAgICAgICAgICAgZnByaW50ZihzdGRlcnIsICJXcm9uZyBtb2RlICV1IGF0ICUuOHp4XG4iLCBpbnNuLm1vZGUsIGluc24ub2Zmc2V0KTsKICAgICAgICAgICAgZXhpdCgxKTsKICAgICAgICB9CgogICAgICAgIGlmIChpbnNuLm1vZGUgPT0gMCB8fCBpbnNuLm1vZGUgPT0gMikgewogICAgICAgICAgICBpICs9IDI7CiAgICAgICAgICAgIGluc24uaW1tID0gY29kZVtpXSB8IGNvZGVbaSArIDFdIDw8IDg7CiAgICAgICAgfQogICAgICAgIGluc3RydWN0aW9uc1tudW1faW5zdHJ1Y3Rpb25zKytdID0gaW5zbjsKICAgIH0KfQoKc3RhdGljIHZvaWQgcmVhZF9jb2RlKGNvbnN0IGNoYXIgKmZpbGVuYW1lKQp7CiAgICBzdGF0aWMgdWludDhfdCBjb2RlWzY1NTM2XTsKCiAgICBGSUxFICpmcCA9IGZvcGVuKGZpbGVuYW1lLCAicmIiKTsKICAgIGlmICghZnApIHsKICAgICAgICBwZXJyb3IoZmlsZW5hbWUpOwogICAgICAgIGV4aXQoMSk7CiAgICB9CgogICAgc2l6ZV90IGxlbmd0aCA9IGZyZWFkKGNvZGUsIDEsIHNpemVvZihjb2RlKSwgZnApOwogICAgZmNsb3NlKGZwKTsKCiAgICBjcmVhdGVfaW5zdHJ1Y3Rpb25zKGNvZGUsIGxlbmd0aCk7Cn0KCnN0YXRpYyB2b2lkIHdyaXRlX3Jlc3BvbnNlKGNvbnN0IGNoYXIgKmZpbGVuYW1lLCBjb25zdCB1aW50MTZfdCAqcmVncykKewogICAgRklMRSAqZnAgPSBmb3BlbihmaWxlbmFtZSwgIndiIik7CiAgICBpZiAoIWZwKSB7CiAgICAgICAgcGVycm9yKGZpbGVuYW1lKTsKICAgICAgICBleGl0KDEpOwogICAgfQogICAgZnByaW50ZihmcCwgIiUuNHggJS40eCAlLjR4ICUuNHhcbiIsIHJlZ3NbMF0sIHJlZ3NbMV0sIHJlZ3NbMl0sIHJlZ3NbM10pOwogICAgZmNsb3NlKGZwKTsKfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkKewogICAgaWYgKGFyZ2MgIT0gMykgewogICAgICAgIGZwcmludGYoc3RkZXJyLCAidXNhZ2U6ICVzIDxpbnB1dCBmaWxlPiA8b3V0cHV0IGZpbGU+IiwgYXJndlswXSk7CiAgICAgICAgcmV0dXJuIC0xOwogICAgfQoKICAgIHJlYWRfY29kZShhcmd2WzFdKTsKCiAgICBzaXplX3QgaXAgPSAwOwogICAgdWludDE2X3QgcmVnc1s0XSA9IHsgMCB9OwogICAgdWludDE2X3Qgc3RhY2tbMjU2XTsKICAgIHNpemVfdCBzdGFja3B0ciA9IDA7CiAgICBib29sIHpmID0gZmFsc2U7CgogICAgd2hpbGUgKGlwIDwgbnVtX2luc3RydWN0aW9ucykgewogICAgICAgIGluc3RydWN0aW9uICppbnNuID0gJmluc3RydWN0aW9uc1tpcF07CiAgICAgICAgdWludDE2X3QgKmRlc3QgPSBOVUxMOwogICAgICAgIHVpbnQxNl90ICpzcmMgPSBOVUxMOwogICAgICAgIHVpbnQxNl90IGltbSA9IGluc24tPmltbTsKCiAgICAgICAgcHJpbnRmKCIlLjR6eDogJXNcdCIsIGlwLCBvcF9uYW1lc1tpbnNuLT5vcGNvZGVdKTsKCiAgICAgICAgc3dpdGNoIChpbnNuLT5tb2RlKSB7CiAgICAgICAgICAgIGNhc2UgMDogLy8gSU1NLgogICAgICAgICAgICAgICAgZGVzdCA9ICZpbW07CiAgICAgICAgICAgICAgICBwcmludGYoIiUuNHggICAgIiwgaW5zbi0+aW1tKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDE6IC8vIFJFRy4KICAgICAgICAgICAgICAgIGRlc3QgPSAmcmVnc1tpbnNuLT5yZGVzdF07CiAgICAgICAgICAgICAgICBwcmludGYoInIldSAgICAgICIsIGluc24tPnJkZXN0KTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6IC8vIFJFRywgSU1NLgogICAgICAgICAgICAgICAgZGVzdCA9ICZyZWdzW2luc24tPnJkZXN0XTsKICAgICAgICAgICAgICAgIHNyYyA9ICZpbW07CiAgICAgICAgICAgICAgICBwcmludGYoInIldSwgJS40eCIsIGluc24tPnJkZXN0LCBpbnNuLT5pbW0pOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzogLy8gUkVHLCBSRUcuCiAgICAgICAgICAgICAgICBkZXN0ID0gJnJlZ3NbaW5zbi0+cmRlc3RdOwogICAgICAgICAgICAgICAgc3JjID0gJnJlZ3NbaW5zbi0+cnNyY107CiAgICAgICAgICAgICAgICBwcmludGYoInIldSwgciV1ICAiLCBpbnNuLT5yZGVzdCwgaW5zbi0+cnNyYyk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIHByaW50ZigiIDsgIik7CiAgICAgICAgKytpcDsKCiAgICAgICAgc3dpdGNoIChpbnNuLT5vcGNvZGUpIHsKICAgICAgICAgICAgY2FzZSAwOiAvLyBNT1ZFLgogICAgICAgICAgICAgICAgKmRlc3QgPSAqc3JjOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMTogLy8gT1IuCiAgICAgICAgICAgICAgICAqZGVzdCA9ICpkZXN0IHwgKnNyYzsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6IC8vIFhPUi4KICAgICAgICAgICAgICAgICpkZXN0ID0gKmRlc3QgXiAqc3JjOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzogLy8gQU5ELgogICAgICAgICAgICAgICAgKmRlc3QgPSAqZGVzdCAmICpzcmM7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSA0OiAvLyBOT1QuCiAgICAgICAgICAgICAgICAqZGVzdCA9IH4qZGVzdDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDU6IC8vIEFERC4KICAgICAgICAgICAgICAgICpkZXN0ICs9ICpzcmM7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSA2OiAvLyBTVUIuCiAgICAgICAgICAgICAgICAqZGVzdCAtPSAqc3JjOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgNzogLy8gTVVMLgogICAgICAgICAgICAgICAgKmRlc3QgPSAqZGVzdCAqICpzcmM7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSA4OiAvLyBTSEwuCiAgICAgICAgICAgICAgICAqZGVzdCA8PD0gKnNyYzsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDk6IC8vIFNIUi4KICAgICAgICAgICAgICAgICpkZXN0ID4+PSAqc3JjOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMTA6IC8vIElOQy4KICAgICAgICAgICAgICAgICpkZXN0ICs9IDE7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAxMTogLy8gREVDLgogICAgICAgICAgICAgICAgKmRlc3QgLT0gMTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDEyOiAvLyBQVVNILgogICAgICAgICAgICAgICAgaWYgKHN0YWNrcHRyID49IHNpemVvZihzdGFjaykgLyBzaXplb2Yoc3RhY2tbMF0pKSB7CiAgICAgICAgICAgICAgICAgICAgZnByaW50ZihzdGRlcnIsICJTdGFjayBvdmVyZmxvd1xuIik7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBzdGFja1tzdGFja3B0cisrXSA9ICpkZXN0OwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMTM6IC8vIFBPUAogICAgICAgICAgICAgICAgaWYgKHN0YWNrcHRyID09IDApIHsKICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKHN0ZGVyciwgIlN0YWNrIHVuZGVyZmxvd1xuIik7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAqZGVzdCA9IHN0YWNrWy0tc3RhY2twdHJdOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMTQ6IC8vIENNUC4KICAgICAgICAgICAgICAgIHpmID0gKCpkZXN0IC0gKnNyYykgPT0gMDsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDE1OiAvLyBKTlouCiAgICAgICAgICAgICAgICBpZiAoIXpmKSB7CiAgICAgICAgICAgICAgICAgICAgaXAgPSAqZGVzdDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDE2OiAvLyBKWi4KICAgICAgICAgICAgICAgIGlmICh6ZikgewogICAgICAgICAgICAgICAgICAgIGlwID0gKmRlc3Q7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIC8vIFNldCBaRiBmb3IgYXJpdGhtZXRpY2FsIGFuZCBsb2dpY2FsIGluc3RydWN0aW9ucyAoZXhjZXB0IENNUCkuCiAgICAgICAgaWYgKGluc24tPm9wY29kZSA+PSAxICYmIGluc24tPm9wY29kZSA8PSAxMSkgewogICAgICAgICAgICB6ZiA9ICpkZXN0ID09IDA7CiAgICAgICAgfQoKICAgICAgICBwcmludGYoIiByMCA9ICUuNHgsIHIxID0gJS40eCwgcjIgPSAlLjR4LCByMyA9ICUuNHgsIHpmID0gJXVcbiIsCiAgICAgICAgICAgIHJlZ3NbMF0sIHJlZ3NbMV0sIHJlZ3NbMl0sIHJlZ3NbM10sIHpmKTsKICAgIH0KCiAgICB3cml0ZV9yZXNwb25zZShhcmd2WzJdLCByZWdzKTsKICAgIHJldHVybiAwOwp9Cg==