summaryrefslogtreecommitdiff
path: root/src/vm/instruction.test.js.n
diff options
context:
space:
mode:
authorsanine-a <sanine.not@pm.me>2023-05-24 13:06:45 -0500
committersanine-a <sanine.not@pm.me>2023-05-24 13:06:45 -0500
commit9f478261bc8fd1502090c701c998e48a4018e7ee (patch)
treec1758c322450af1eead232cb42491e558b5aba12 /src/vm/instruction.test.js.n
parent15323007750e0f0f7c36a6a6fa01ad1d303a4a16 (diff)
fix operand resolution to match specmain
Diffstat (limited to 'src/vm/instruction.test.js.n')
-rw-r--r--src/vm/instruction.test.js.n508
1 files changed, 508 insertions, 0 deletions
diff --git a/src/vm/instruction.test.js.n b/src/vm/instruction.test.js.n
new file mode 100644
index 0000000..cf23404
--- /dev/null
+++ b/src/vm/instruction.test.js.n
@@ -0,0 +1,508 @@
+'use strict';
+
+const { Core } = require('./core.js');
+const {
+ DAT,
+ MOV, ADD, SUB, CMP, SLT,
+ JMP, JMZ, JMN, DJN, SPL,
+} = require('./instruction.js');
+
+
+const CORESIZE = 8000;
+
+
+test('DAT does nothing and kills the program', () => {
+ const core = new Core(CORESIZE);
+ const pc = 0;
+ const ins = core.data[pc];
+ expect(DAT(core, pc, ins)).toEqual([]);
+});
+
+
+test('MOV correctly moves a full instruction', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'MOV',
+ a: { mode: 'direct', value: 0 },
+ b: { mode: 'direct', value: 1 },
+ };
+ const ins = core.data[pc];
+ expect(core.data[pc+1].opcode).toBe('DAT');
+ expect(MOV(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc]).toEqual(core.data[pc+1]);
+ expect(core.data[pc+1].opcode).toBe('MOV');
+});
+
+
+test('MOV correctly moves a B-field', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'MOV',
+ a: { mode: 'immediate', value: 100 },
+ b: { mode: 'direct', value: 1 },
+ };
+ const ins = core.data[pc];
+ expect(core.data[pc+1].opcode).toBe('DAT');
+ expect(MOV(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc+1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 0 },
+ b: { mode: 'immediate', value: 100 },
+ });
+});
+
+
+test('MOV correctly handles indirection', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc-1] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 0 },
+ b: { mode: 'immediate', value: 2 },
+ };
+ core.data[pc] = {
+ opcode: 'MOV',
+ a: { mode: 'immediate', value: 100 },
+ b: { mode: 'indirect', value: -1 },
+ };
+ const ins = core.data[pc];
+ expect(core.data[pc+1].opcode).toBe('DAT');
+ expect(MOV(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc-1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 0 },
+ b: { mode: 'immediate', value: 2 },
+ });
+
+ expect(core.data[pc+2]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 0 },
+ b: { mode: 'immediate', value: 100 },
+ });
+
+});
+
+
+
+
+test('MOV correctly handles predecrement indirection', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'MOV',
+ a: { mode: 'immediate', value: 100 },
+ b: { mode: 'predecrement', value: 1 },
+ };
+ const ins = core.data[pc];
+ expect(core.data[pc+1].opcode).toBe('DAT');
+ expect(MOV(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc+1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 0 },
+ b: { mode: 'immediate', value: -1 },
+ });
+
+ expect(core.data[pc-1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 0 },
+ b: { mode: 'immediate', value: 100 },
+ });
+
+});
+
+
+test('MOV correctly handles core boundaries', () => {
+ const core = new Core(CORESIZE);
+ const pc = CORESIZE-1;
+ core.data[pc] = {
+ opcode: 'MOV',
+ a: { mode: 'immediate', value: 100 },
+ b: { mode: 'predecrement', value: 2 },
+ };
+ const ins = core.data[pc];
+ expect(core.data[0].opcode).toBe('DAT');
+ expect(MOV(core, pc, ins)).toEqual([0]);
+ expect(core.data[1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 0 },
+ b: { mode: 'immediate', value: -1 },
+ });
+
+ expect(core.data[CORESIZE-2]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 0 },
+ b: { mode: 'immediate', value: 100 },
+ });
+
+});
+
+
+
+test('ADD correctly adds two full instructions', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'ADD',
+ a: { mode: 'direct', value: 1 },
+ b: { mode: 'direct', value: 2 },
+ };
+ core.data[pc+1] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ };
+ core.data[pc+2] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ const ins = core.data[pc];
+
+ expect(ADD(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc+1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ });
+ expect(core.data[pc+2]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 13 },
+ b: { mode: 'immediate', value: 24 },
+ });
+});
+
+
+test('ADD correctly adds B-field', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'ADD',
+ a: { mode: 'immediate', value: 1 },
+ b: { mode: 'direct', value: 2 },
+ };
+ core.data[pc+1] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ };
+ core.data[pc+2] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ const ins = core.data[pc];
+
+ expect(ADD(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc+1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ });
+ expect(core.data[pc+2]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 5 },
+ });
+});
+
+
+test('SUB correctly subtracts two full instructions', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'SUB',
+ a: { mode: 'direct', value: 1 },
+ b: { mode: 'direct', value: 2 },
+ };
+ core.data[pc+1] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ };
+ core.data[pc+2] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ const ins = core.data[pc];
+
+ expect(SUB(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc+1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ });
+ expect(core.data[pc+2]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: -7 },
+ b: { mode: 'immediate', value: -16 },
+ });
+});
+
+
+test('SUB correctly subtracts B-field', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'SUB',
+ a: { mode: 'immediate', value: 1 },
+ b: { mode: 'direct', value: 2 },
+ };
+ core.data[pc+1] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ };
+ core.data[pc+2] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ const ins = core.data[pc];
+
+ expect(SUB(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc+1]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ });
+ expect(core.data[pc+2]).toEqual({
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 3 },
+ });
+});
+
+
+test('CMP properly compares full instructions', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'CMP',
+ a: { mode: 'direct', value: 1 },
+ b: { mode: 'direct', value: 2 },
+ };
+ core.data[pc+1] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 10 },
+ b: { mode: 'immediate', value: 20 },
+ };
+ core.data[pc+2] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ const ins = core.data[pc];
+
+ expect(CMP(core, pc, ins)).toEqual([pc+1]);
+
+ core.data[pc+2] = JSON.parse(JSON.stringify(core.data[pc+1]));
+
+ expect(CMP(core, pc, ins)).toEqual([pc+2]);
+});
+
+
+test('CMP properly compares B-field', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'CMP',
+ a: { mode: 'immediate', value: 1 },
+ b: { mode: 'direct', value: 2 },
+ };
+ core.data[pc+2] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ const ins = core.data[pc];
+
+ expect(CMP(core, pc, ins)).toEqual([pc+1]);
+
+ core.data[pc+2].b.value = 1;
+
+ expect(CMP(core, pc, ins)).toEqual([pc+2]);
+});
+
+
+test('SLT properly compares full instructions', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'SLT',
+ a: { mode: 'direct', value: 1 },
+ b: { mode: 'direct', value: 2 },
+ };
+ core.data[pc+1] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ core.data[pc+2] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ const ins = core.data[pc];
+
+ expect(SLT(core, pc, ins)).toEqual([pc+1]);
+
+ core.data[pc+2].b.value = 5;
+
+ expect(SLT(core, pc, ins)).toEqual([pc+2]);
+});
+
+
+
+test('SLT properly compares B-fields', () => {
+ const core = new Core(CORESIZE);
+ const pc = 20;
+ core.data[pc] = {
+ opcode: 'SLT',
+ a: { mode: 'immediate', value: 7 },
+ b: { mode: 'direct', value: 2 },
+ };
+ core.data[pc+2] = {
+ opcode: 'DAT',
+ a: { mode: 'immediate', value: 3 },
+ b: { mode: 'immediate', value: 4 },
+ };
+ const ins = core.data[pc];
+
+ expect(SLT(core, pc, ins)).toEqual([pc+1]);
+
+ core.data[pc+2].b.value = 8;
+
+ expect(SLT(core, pc, ins)).toEqual([pc+2]);
+});
+
+
+test('JMP correctly jumps', () => {
+ const core = new Core(CORESIZE);
+ const pc = 2;
+ core.data[pc] = {
+ opcode: 'JMP',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'direct', value: 0 },
+ };
+ const ins = core.data[pc];
+
+ expect(JMP(core, pc, ins)).toEqual([CORESIZE-1]);
+});
+
+
+test('JMZ correctly jumps in non-immediate mode', () => {
+ const core = new Core(CORESIZE);
+ const pc = 2;
+ core.data[pc] = {
+ opcode: 'JMZ',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'direct', value: 1 },
+ };
+ core.data[pc+1] = {
+ opcode: 'JMZ',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'direct', value: 1 },
+ };
+ const ins = core.data[pc];
+
+ expect(JMZ(core, pc, ins)).toEqual([pc+1]);
+ core.data[pc+1].b.value = 0;
+ expect(JMZ(core, pc, ins)).toEqual([CORESIZE-1]);
+});
+
+
+test('JMZ correctly jumps in immediate mode', () => {
+ const core = new Core(CORESIZE);
+ const pc = 2;
+ core.data[pc] = {
+ opcode: 'JMZ',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'immediate', value: 1 },
+ };
+ const ins = core.data[pc];
+
+ expect(JMZ(core, pc, ins)).toEqual([pc+1]);
+ core.data[pc].b.value = 0;
+ expect(JMZ(core, pc, ins)).toEqual([CORESIZE-1]);
+});
+
+
+test('JMN correctly jumps in non-immediate mode', () => {
+ const core = new Core(CORESIZE);
+ const pc = 2;
+ core.data[pc] = {
+ opcode: 'JMN',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'direct', value: 1 },
+ };
+ core.data[pc+1] = {
+ opcode: 'JMN',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'direct', value: 0 },
+ };
+ const ins = core.data[pc];
+
+ expect(JMN(core, pc, ins)).toEqual([pc+1]);
+ core.data[pc+1].b.value = 1;
+ expect(JMN(core, pc, ins)).toEqual([CORESIZE-1]);
+});
+
+
+test('JMN correctly jumps in immediate mode', () => {
+ const core = new Core(CORESIZE);
+ const pc = 2;
+ core.data[pc] = {
+ opcode: 'JMN',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'immediate', value: 0 },
+ };
+ const ins = core.data[pc];
+
+ expect(JMN(core, pc, ins)).toEqual([pc+1]);
+ core.data[pc].b.value = 1;
+ expect(JMN(core, pc, ins)).toEqual([CORESIZE-1]);
+});
+
+
+test('DJN correctly jumps in non-immediate mode', () => {
+ const core = new Core(CORESIZE);
+ const pc = 2;
+ core.data[pc] = {
+ opcode: 'DJN',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'direct', value: 1 },
+ };
+ core.data[pc+1] = {
+ opcode: 'DJN',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'direct', value: 1 },
+ };
+ const ins = core.data[pc];
+
+ expect(DJN(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc+1].b.value).toBe(0);
+ expect(DJN(core, pc, ins)).toEqual([CORESIZE-1]);
+ expect(core.data[pc+1].b.value).toBe(-1);
+});
+
+
+test('DJN correctly jumps in immediate mode', () => {
+ const core = new Core(CORESIZE);
+ const pc = 2;
+ core.data[pc] = {
+ opcode: 'DJN',
+ a: { mode: 'direct', value: -3 },
+ b: { mode: 'immediate', value: 1 },
+ };
+ const ins = core.data[pc];
+
+ expect(DJN(core, pc, ins)).toEqual([pc+1]);
+ expect(core.data[pc].b.value).toBe(0);
+ expect(DJN(core, pc, ins)).toEqual([CORESIZE-1]);
+ expect(core.data[pc].b.value).toBe(-1);
+});
+
+