diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/vm/core.js | 9 | ||||
| -rw-r--r-- | src/vm/instruction.js | 15 | ||||
| -rw-r--r-- | src/vm/instruction.test.js | 128 | 
3 files changed, 147 insertions, 5 deletions
| diff --git a/src/vm/core.js b/src/vm/core.js index 074e156..6303ee5 100644 --- a/src/vm/core.js +++ b/src/vm/core.js @@ -31,13 +31,13 @@ class Core {  				return this.normalize(pc, address.value);  			case AddrMode.Indirect: {  				let loc = this.normalize(pc, address.value); -				let b = this.data[loc]; +				let b = this.data[loc].b.value;  				return this.normalize(loc, b);  			}  			case AddrMode.Predecrement: {  				let loc = this.normalize(pc, address.value); -				this.data[loc].b -= 1; -				let b = this.data[loc].b; +				this.data[loc].b.value -= 1; +				let b = this.data[loc].b.value;  				return this.normalize(loc, b);  			}  			default: @@ -46,7 +46,8 @@ class Core {  	}  	getValue(pc, address) { -		return this.data[this.getLocation(pc, address)]; +		const index = this.getLocation(pc, address); +		return this.data[index];  	}  } diff --git a/src/vm/instruction.js b/src/vm/instruction.js index c991643..c9048e1 100644 --- a/src/vm/instruction.js +++ b/src/vm/instruction.js @@ -22,3 +22,18 @@ exports.MOV = function(core, pc, ins) {  	return [pc + 1];  } + + +exports.ADD = function(core, pc, ins) { +	if (ins.a.mode === AddrMode.Immediate) { +		const dst = core.getValue(pc, ins.b); +		dst.b.value += ins.a.value; +	} else { +		const src = core.getValue(pc, ins.a); +		const dst = core.getValue(pc, ins.b); +		dst.a.value += src.a.value; +		dst.b.value += src.b.value; +	} + +	return [pc + 1]; +} diff --git a/src/vm/instruction.test.js b/src/vm/instruction.test.js index 3535b76..fd402e4 100644 --- a/src/vm/instruction.test.js +++ b/src/vm/instruction.test.js @@ -1,7 +1,7 @@  'use strict';  const { Core } = require('./core.js'); -const { DAT, MOV } = require('./instruction.js'); +const { DAT, MOV, ADD } = require('./instruction.js');  const CORESIZE = 8000; @@ -47,5 +47,131 @@ test('MOV correctly moves a B-field', () => {  		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('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 }, +	});  }); | 
