summaryrefslogtreecommitdiff
path: root/src/vm
diff options
context:
space:
mode:
authorsanine-a <sanine.not@pm.me>2023-05-23 14:53:53 -0500
committersanine-a <sanine.not@pm.me>2023-05-23 14:53:53 -0500
commit15323007750e0f0f7c36a6a6fa01ad1d303a4a16 (patch)
tree70835b4364299274dc0145af5cd41c5af05ae53b /src/vm
parent29ed5eacb80cdfe49bff0d9335241dc3e2188981 (diff)
implement basic vm runner
Diffstat (limited to 'src/vm')
-rw-r--r--src/vm/core.js15
-rw-r--r--src/vm/vm.js34
2 files changed, 38 insertions, 11 deletions
diff --git a/src/vm/core.js b/src/vm/core.js
index a8fbce7..6363a60 100644
--- a/src/vm/core.js
+++ b/src/vm/core.js
@@ -133,6 +133,21 @@ class Core {
const index = this.getLocation(pc, address);
return this.data[index];
}
+
+
+ pretty(ins) {
+ const prettyMode = {
+ 'immediate': '#',
+ 'direct': ' ',
+ 'indirect': '@',
+ 'predecrement': '<',
+ };
+
+ return `\
+${ins.opcode} \
+${prettyMode[ins.a.mode]}${ins.a.value}, \
+${prettyMode[ins.b.mode]}${ins.b.value}`;
+ }
}
diff --git a/src/vm/vm.js b/src/vm/vm.js
index 6add546..eea949a 100644
--- a/src/vm/vm.js
+++ b/src/vm/vm.js
@@ -23,7 +23,12 @@ class Warrior {
next() {
const pc = this.queue[0];
this.queue = this.queue.slice(1);
- return next;
+ return pc;
+ }
+
+ peek() {
+ const pc = this.queue[0];
+ return pc;
}
};
@@ -38,7 +43,8 @@ class RedcodeVm {
step() {
let running = 0;
- for (let warrior of this.warriors) {
+ for (let i=0; i<this.warriors.length; i++) {
+ const warrior = this.warriors[i];
if (warrior.isDead()) {
continue;
} else {
@@ -48,6 +54,7 @@ class RedcodeVm {
const pc = warrior.next();
const ins = this.core.data[pc];
let next;
+ console.log(i, this.core.pretty(ins));
switch(ins.opcode) {
case 'DAT':
next = DAT(this.core, pc, ins);
@@ -85,25 +92,30 @@ class RedcodeVm {
default:
throw `core corruption: bad instruction ${ins}`
}
+
+ warrior.append(next);
}
return running;
}
+ warriorsAlive() {
+ return this.warriors.reduce(
+ (count, warrior) => warrior.isDead() ? count : count+1,
+ 0
+ );
+ }
+
run(maxSteps) {
let steps = 0;
- let running = this.warriors.length;
- while(running > 0 && steps < maxSteps) {
- running = this.step();
+ while(this.warriorsAlive() > 1 && steps < maxSteps) {
+ this.step();
steps += 1;
}
- if (running !== 0) {
- console.log("draw, maximum steps exceeded");
- }
- for (let i=0; i<this.warriors.length; i++) {
- console.log(`${i} running: ${!this.warriors[i].isDead()}`);
- }
+ return this.warriors.map(
+ (w, i) => ({ warrior: i, alive: !w.isDead() })
+ );
}
};