7. Core commands

7.1. The Main Enum

This enum gets dynamically populated with commands via worgle.

<<enums>>=
enum {
<<commands>>
   SEQVM_NONE
};

7.2. HALT

HALT. halts computation. Must be called in order to continue.

<<commands>>=
SEQVM_HALT,
<<compute>>=
case SEQVM_HALT:
    svm->halt = 1;
    pos++;
    break;
<<dump>>=
DUMP0(SEQVM_HALT, "HALT")
<<seqvm_cmd>>=
ISCMD("halt") {
    *pos = seqvm_insert0(svm, *pos, SEQVM_HALT);
}

7.3. END

Ends the program. This will prevent the program from moving.

<<compute>>=
case SEQVM_NONE:
case SEQVM_END:
    svm->halt = 1;
    break;
<<commands>>=
SEQVM_END,

7.4. VAL/VALR

VAL. Sets the value flag. This should correspond to a position in a table.

<<commands>>=
SEQVM_VAL,
<<compute>>=
case SEQVM_VAL: {
    int chn;
    int val;

    chn = c->p[0];
    val = c->p[1];

    if (chn >= 0 && chn < 4) {
        svm->next.chan[chn].val = val;
    }

    pos++;
    break;
}
<<dump>>=
DUMP2(SEQVM_VAL, "VAL")
<<seqvm_cmd>>=
ISCMD("val") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_VAL, a, b);
}

VALR. like VAL, but using a value from a register.

<<commands>>=
SEQVM_VALR,
<<compute>>=
case SEQVM_VALR: {
    int chn;
    int val;
    int r;

    chn = c->p[0];
    r = c->p[1];
    val = 0;

    pos++;

    if (r >= 0 && r < 16) {
        val = svm->r[r];
    } else break;

    if (chn >= 0 && chn < 4) {
        svm->next.chan[chn].val = val;
    }

    break;
}
<<dump>>=
DUMP2(SEQVM_VALR, "VALR")
<<seqvm_cmd>>=
ISCMD("valr") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_VALR, a, b);
}

7.5. SET

SET. Sets register to value.

<<commands>>=
SEQVM_SET,
<<compute>>=
case SEQVM_SET: {
    int r, val;

    r = c->p[0];
    val = c->p[1];

    if (r >= 0 && r < 16) {
        svm->r[r] = val;
    }

    pos++;
    break;
}
<<dump>>=
DUMP2(SEQVM_SET, "SET")
<<seqvm_cmd>>=
ISCMD("set") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_SET, a, b);
}

7.6. ADD/SUB

SUB. Subtracts from value in register.

<<commands>>=
SEQVM_SUB,
<<compute>>=
case SEQVM_SUB: {
    int r;
    int amt;

    r = c->p[0];
    amt = c->p[1];

    if (r >= 0 || r < 16) {
        svm->r[r] -= amt;
    }

    pos++;
    break;
}
<<dump>>=
DUMP2(SEQVM_SUB, "SUB")
<<seqvm_cmd>>=
ISCMD("sub") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_SET, a, b);
}

ADD. Adds to value in register.

7.7. RAND

Usage: RAND reg N

Creates random number between 0 and N - 1, and stores it in a register reg.

<<commands>>=
SEQVM_RAND,
<<compute>>=
case SEQVM_RAND: {
    int r;
    int n;

    pos++;

    r = c->p[0];
    n = c->p[1];

    if (r >= 0 && r < 16) {
        if (n == 0) {
            svm->r[r] = 0;
        } else {
            int div;
            div = SEQVM_RANDMAX / n;
            svm->r[r] = seqvm_rand(svm) / div;
        }
    }
    break;
}
<<dump>>=
DUMP2(SEQVM_RAND, "RAND")
<<seqvm_cmd>>=
ISCMD("rand") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_RAND, a, b);
}

7.8. JUMP/JUMPR

JUMP. Jumps to address unconditionally.

<<commands>>=
SEQVM_JUMP,
<<compute>>=
case SEQVM_JUMP: {
    pos = c->p[0];
    break;
}
<<dump>>=
DUMP1(SEQVM_JUMP, "JUMP")
<<seqvm_cmd>>=
ISCMD("jump") {
    *pos = seqvm_insert1(svm, *pos, SEQVM_JUMP, a);
}

JUMPR. Same as JUMP, but reads from value in register. If out of range, defaults to next value.

<<commands>>=
SEQVM_JUMPR,
<<compute>>=
case SEQVM_JUMPR: {
    if (c->p[0] < 0 || c->p[0] >= 8) pos++;
    else pos = svm->r[c->p[0]];
    break;
}
<<dump>>=
DUMP1(SEQVM_JUMPR, "JUMPR")
<<seqvm_cmd>>=
ISCMD("jumpr") {
    *pos = seqvm_insert1(svm, *pos, SEQVM_JUMPR, a);
}

7.9. CJUMP/CRJUMP

CJUMP reg addr CRJUMP reg off

CJUMP jumps to address if value in register is nonzero.

CJUMPR jumps to a relative address.

<<commands>>=
SEQVM_CJUMP,
<<compute>>=
case SEQVM_CJUMP: {
    int r;
    int addr;

    r = c->p[0];
    addr = c->p[1];

    pos++;

    if (r >= 0 && r < 16) {
        int val;
        val = svm->r[r];
        if (val) pos = addr;
    }
    break;
}
<<dump>>=
DUMP2(SEQVM_CJUMP, "CJUMP")
<<seqvm_cmd>>=
ISCMD("cjump") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_CJUMP, a, b);
}
<<commands>>=
SEQVM_CRJUMP,
<<compute>>=
case SEQVM_CRJUMP: {
    int r;

    r = c->p[0];

    if (r >= 0 && r < 16) {
        int val;
        val = svm->r[r];
        if (val) pos += (val + 1);
        else pos++;
    } else {
        pos++;
    }
    break;
}
<<dump>>=
DUMP2(SEQVM_CRJUMP, "CRJUMP")
<<seqvm_cmd>>=
ISCMD("crjump") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_CRJUMP, a, b);
}

7.10. RJUMP/RJUMPR

Relative jump. Jumps N + 1 place relative to the current instruction. Done to work well with the RAND command. A value of 0 is a regular jump to the next instruction.

Usage: RJUMPR reg Usage: RJUMP jump

<<commands>>=
SEQVM_RJUMP,
<<compute>>=
case SEQVM_RJUMP: {
    int val;
    val = c->p[0];
    pos += (val + 1);
    break;
}
<<dump>>=
DUMP1(SEQVM_RJUMP, "RJUMP")
<<seqvm_cmd>>=
ISCMD("rjump") {
    *pos = seqvm_insert1(svm, *pos, SEQVM_RJUMP, a);
}

And now RJUMPR:

<<commands>>=
SEQVM_RJUMPR,
<<compute>>=
case SEQVM_RJUMPR: {
    int r;
    r = c->p[0];

    if (r >= 0 && r < 16) {
        int val;
        val = svm->r[r];
        pos += (val + 1);
    } else {
        pos++; /* ignore */
    }
    break;
}
<<dump>>=
DUMP1(SEQVM_RJUMPR, "RJUMPR")
<<seqvm_cmd>>=
ISCMD("rjumpr") {
    *pos = seqvm_insert1(svm, *pos, SEQVM_RJUMPR, a);
}

7.11. WAIT

Usage: WAIT reg

WAIT will act as a HALT while the value in reg is non-zero. Every time it executed, it subtracts 1 from the value stored in reg.

Equivalent to the following pseudo-code

WAIT:
  SUB REG 1
  HALT
  CJUMP REG $WAIT

So it saves 3 instructions.

<<commands>>=
SEQVM_WAIT,
<<compute>>=
case SEQVM_WAIT: {
    int r;
    r = c->p[0];

    if (r >= 0 || r <= 16) {
        int *val;
        val = &svm->r[r];
        (*val)--;
        if (*val <= 0) pos++;
        svm->halt = 1;
    } else {
        pos++; /* invalid range, skip */
    }
    break;
}
<<dump>>=
DUMP1(SEQVM_WAIT, "WAIT")
<<seqvm_cmd>>=
ISCMD("wait") {
    *pos = seqvm_insert1(svm, *pos, SEQVM_WAIT, a);
}

7.12. TICK

Usage: TICK chan

Sets tick flag. This gets reset at the beginning of every compute cycle.

<<commands>>=
SEQVM_TICK,
<<compute>>=
case SEQVM_TICK: {
    int chan;

    chan = c->p[0];

    if (chan >= 0 && chan < 4) {
        svm->next.chan[chan].tick = 1;
    }

    pos++;
    break;
}
<<dump>>=
DUMP1(SEQVM_TICK, "TICK")
<<seqvm_cmd>>=
ISCMD("tick") {
    *pos = seqvm_insert1(svm, *pos, SEQVM_TICK, a);
}

7.13. GATE

Usage: GATE chan state

Sets the gate flag to be ON or OFF.

<<commands>>=
SEQVM_GATE,
<<compute>>=
case SEQVM_GATE: {
    int state;
    int chan;

    chan = c->p[0];
    state = c->p[1];


    if (chan >= 0 && chan <= 4) {
        svm->next.chan[chan].gate = state;
    }

    pos++;
    break;
}
<<dump>>=
DUMP2(SEQVM_GATE, "GATE")
<<seqvm_cmd>>=
ISCMD("gate") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_GATE, a, b);
}

7.14. RANDQ

Usage: RANDQ reg N

Creates random number between 0 and N - 1, and stores it in a register reg. This is different than RAND in that it produces a value that is different from the value in the register. If N is zero, zero is returned.

<<commands>>=
SEQVM_RANDQ,
<<compute>>=
case SEQVM_RANDQ: {
    int r;
    int n;

    pos++;

    r = c->p[0];
    n = c->p[1];

    if (r >= 0 && r < 16) {
        if (n <= 1) {
            svm->r[r] = 0;
        } else if (n == 2) {
            if (svm->r[r] == 0) svm->r[r] = 1;
            else svm->r[r] = 0;
        } else {
            int div;
            int prev;
            int next;
            prev = svm->r[r];
            next = prev;
            div = SEQVM_RANDMAX / n;

            while (prev == next) {
                next = seqvm_rand(svm) / div;
            }

            svm->r[r] = next;
        }
    }
    break;
}
<<dump>>=
DUMP2(SEQVM_RANDQ, "RANDQ")
<<seqvm_cmd>>=
ISCMD("randq") {
    *pos = seqvm_insert2(svm, *pos, SEQVM_RANDQ, a, b);
}

7.15. LT

LT r val out

Checks if value in register is less than value, then writes boolean to another register.

<<commands>>=
SEQVM_LT,
<<compute>>=
case SEQVM_LT: {
    int r;
    int val;
    int out;

    r = c->p[0];
    val = c->p[1];
    out = c->p[2];

    if (r >= 0 && r < 16 && out >= 0 && out < 16) {
        int x;

        x = svm->r[r];
        svm->r[out] = x < val;
    }

    pos++;

    break;
}
<<dump>>=
DUMP3(SEQVM_LT, "LT")
<<seqvm_cmd>>=
ISCMD("lt") {
    *pos = seqvm_insert3(svm, *pos, SEQVM_LT, a, b, c);
}



prev | home | next