Skip to content
Snippets Groups Projects
vm_regs.c 2.38 KiB
Newer Older
Michal Privoznik's avatar
Michal Privoznik committed
#include <stdio.h>
#include <inttypes.h>
Michal Privoznik's avatar
Michal Privoznik committed

typedef enum {
    A = 0,
    B,
Michal Privoznik's avatar
Michal Privoznik committed
} Registers;

typedef enum {
    FLAG_ZERO       = 1,
    FLAG_NEGATIVE   = 1 << 1,
} Flags;

typedef enum {
    OP_ADD,
    OP_ADD_VALUE,
    OP_HALT,
    OP_JMP_REL,
    OP_JMP_REL_NEGATIVE,
    OP_JMP_REL_NOT_EQUAL,
    OP_JMP_REL_EQUAL,
Michal Privoznik's avatar
Michal Privoznik committed
    OP_LOAD,
    OP_MOV,
    OP_XCHG,
Michal Privoznik's avatar
Michal Privoznik committed
    OP_NOP,
    OP_PRINT,
Michal Privoznik's avatar
Michal Privoznik committed
} OpCode;

static void
set_flags(int16_t value, uint8_t *flags_register)
    int new_flags = 0;

Michal Privoznik's avatar
Michal Privoznik committed
    if (value == 0)
        new_flags |= FLAG_ZERO;
Michal Privoznik's avatar
Michal Privoznik committed
    if (value < 0)
        new_flags |= FLAG_NEGATIVE;

    *flags_register = new_flags;
Michal Privoznik's avatar
Michal Privoznik committed
}

int main() {
    int16_t program[] = {
        OP_LOAD, A, 255,
        OP_LOAD, B, 0,
        OP_ADD, B, A,
        OP_ADD_VALUE, A, -1,
        OP_TEST, A, 0,
        OP_JMP_REL_NOT_EQUAL, -11,
        OP_PRINT, B,
Michal Privoznik's avatar
Michal Privoznik committed
        OP_HALT
    };

    int16_t registers[4] = { 0 };
    uint8_t flags_register = 0;
    uint16_t *ip = (uint16_t *) program;
Michal Privoznik's avatar
Michal Privoznik committed

    while (1) {
        OpCode op = *ip++;
        switch (op) {
        case OP_LOAD: {
            int16_t idx = *ip++;
Michal Privoznik's avatar
Michal Privoznik committed
            registers[idx] = *ip++;
            set_flags(registers[idx], &flags_register);
            break;
        }
        case OP_ADD: {
            int16_t idx = *ip++;
            int16_t val = registers[*ip++];
            registers[idx] += val;
            set_flags(registers[idx], &flags_register);
Michal Privoznik's avatar
Michal Privoznik committed
            break;
        }
        case OP_ADD_VALUE: {
Michal Privoznik's avatar
Michal Privoznik committed
            break;
        }
        case OP_JMP_REL: {
Michal Privoznik's avatar
Michal Privoznik committed
            break;
        }
        case OP_NOP: {
            break;
        }
        case OP_TEST: {
            break;
        }
        case OP_JMP_REL_NOT_EQUAL: {
            break;
        }
        case OP_JMP_REL_NEGATIVE: {
            /* TODO */
            break;
        }
        case OP_JMP_REL_EQUAL: {
            /* TODO */
            break;
        }
        case OP_MOV: {
            break;
        }
        case OP_XCHG: {
Michal Privoznik's avatar
Michal Privoznik committed
            break;
        }
        case OP_PRINT:
            printf("%d\n", registers[*ip++]);
            break;
        case OP_HALT:
            return 0;
        default:
            fprintf(stderr, "Unknown instruction %" PRId16 "\n", *ip);
Michal Privoznik's avatar
Michal Privoznik committed
            return -1;
        }
    }

    return 0;
}