'use strict'; const { Core } = require('./core.js'); const { DAT, MOV, ADD, SUB, CMP, SLT, JMP, } = 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+1]).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-2]).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[0]).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]); });