7. Core commands
7.1. The Main Enum
This enum gets dynamically populated with commands via worgle.
enum {
<<commands>>
SEQVM_NONE
};
7.2. HALT
HALT. halts computation. Must be called in order to continue.
SEQVM_HALT,
case SEQVM_HALT:
svm->halt = 1;
pos++;
break;
DUMP0(SEQVM_HALT, "HALT")
ISCMD("halt") {
*pos = seqvm_insert0(svm, *pos, SEQVM_HALT);
}
7.3. END
Ends the program. This will prevent the program from moving.
case SEQVM_NONE:
case SEQVM_END:
svm->halt = 1;
break;
SEQVM_END,
7.4. VAL/VALR
VAL. Sets the value flag. This should correspond to a position in a table.
SEQVM_VAL,
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;
}
DUMP2(SEQVM_VAL, "VAL")
ISCMD("val") {
*pos = seqvm_insert2(svm, *pos, SEQVM_VAL, a, b);
}
VALR. like VAL, but using a value from a register.
SEQVM_VALR,
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;
}
DUMP2(SEQVM_VALR, "VALR")
ISCMD("valr") {
*pos = seqvm_insert2(svm, *pos, SEQVM_VALR, a, b);
}
7.5. SET
SEQVM_SET,
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;
}
DUMP2(SEQVM_SET, "SET")
ISCMD("set") {
*pos = seqvm_insert2(svm, *pos, SEQVM_SET, a, b);
}
7.6. ADD/SUB
SUB. Subtracts from value in register.
SEQVM_SUB,
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;
}
DUMP2(SEQVM_SUB, "SUB")
ISCMD("sub") {
*pos = seqvm_insert2(svm, *pos, SEQVM_SET, a, b);
}
ADD. Adds to value in register.
7.7. RAND
Creates random number between 0 and N - 1
, and stores
it in a register reg
.
SEQVM_RAND,
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;
}
DUMP2(SEQVM_RAND, "RAND")
ISCMD("rand") {
*pos = seqvm_insert2(svm, *pos, SEQVM_RAND, a, b);
}
7.8. JUMP/JUMPR
JUMP. Jumps to address unconditionally.
SEQVM_JUMP,
case SEQVM_JUMP: {
pos = c->p[0];
break;
}
DUMP1(SEQVM_JUMP, "JUMP")
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.
SEQVM_JUMPR,
case SEQVM_JUMPR: {
if (c->p[0] < 0 || c->p[0] >= 8) pos++;
else pos = svm->r[c->p[0]];
break;
}
DUMP1(SEQVM_JUMPR, "JUMPR")
ISCMD("jumpr") {
*pos = seqvm_insert1(svm, *pos, SEQVM_JUMPR, a);
}
7.9. CJUMP/CRJUMP
CJUMP
jumps to address if value in register is nonzero.
CJUMPR
jumps to a relative address.
SEQVM_CJUMP,
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;
}
DUMP2(SEQVM_CJUMP, "CJUMP")
ISCMD("cjump") {
*pos = seqvm_insert2(svm, *pos, SEQVM_CJUMP, a, b);
}
SEQVM_CRJUMP,
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;
}
DUMP2(SEQVM_CRJUMP, "CRJUMP")
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
SEQVM_RJUMP,
case SEQVM_RJUMP: {
int val;
val = c->p[0];
pos += (val + 1);
break;
}
DUMP1(SEQVM_RJUMP, "RJUMP")
ISCMD("rjump") {
*pos = seqvm_insert1(svm, *pos, SEQVM_RJUMP, a);
}
And now RJUMPR:
SEQVM_RJUMPR,
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;
}
DUMP1(SEQVM_RJUMPR, "RJUMPR")
ISCMD("rjumpr") {
*pos = seqvm_insert1(svm, *pos, SEQVM_RJUMPR, a);
}
7.11. WAIT
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.
SEQVM_WAIT,
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;
}
DUMP1(SEQVM_WAIT, "WAIT")
ISCMD("wait") {
*pos = seqvm_insert1(svm, *pos, SEQVM_WAIT, a);
}
7.12. TICK
Sets tick flag. This gets reset at the beginning of every compute cycle.
SEQVM_TICK,
case SEQVM_TICK: {
int chan;
chan = c->p[0];
if (chan >= 0 && chan < 4) {
svm->next.chan[chan].tick = 1;
}
pos++;
break;
}
DUMP1(SEQVM_TICK, "TICK")
ISCMD("tick") {
*pos = seqvm_insert1(svm, *pos, SEQVM_TICK, a);
}
7.13. GATE
Sets the gate flag to be ON or OFF.
SEQVM_GATE,
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;
}
DUMP2(SEQVM_GATE, "GATE")
ISCMD("gate") {
*pos = seqvm_insert2(svm, *pos, SEQVM_GATE, a, b);
}
7.14. RANDQ
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.
SEQVM_RANDQ,
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;
}
DUMP2(SEQVM_RANDQ, "RANDQ")
ISCMD("randq") {
*pos = seqvm_insert2(svm, *pos, SEQVM_RANDQ, a, b);
}
7.15. LT
Checks if value in register is less than value, then writes boolean to another register.
SEQVM_LT,
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;
}
DUMP3(SEQVM_LT, "LT")
ISCMD("lt") {
*pos = seqvm_insert3(svm, *pos, SEQVM_LT, a, b, c);
}
prev | home | next