'use strict'; const { AddrMode } = require('./enum.js'); function getOp(core, pc, op) { switch(op.mode) { case AddrMode.Immediate: return { mode: AddrMode.Immediate, value: op.value }; default: return { mode: 'precomp', value: core.getLocation(pc, op) }; } } function Instruction(f) { return function(core, pc, ins) { const a = getOp(core, pc, ins.a); const b = getOp(core, pc, ins.b); return f(core, pc, a, b); } } exports.DAT = Instruction((core, pc, a, b) => { // do nothing and die return []; }); exports.MOV = Instruction((core, pc, a, b) => { if (a.mode === AddrMode.Immediate) { const dst = core.data[b.value]; dst.b.value = a.value; } else { const src = core.data[a.value]; // hacky deep copy core.data[b.value] = JSON.parse(JSON.stringify(src)); } return [core.normalize(pc, 1)]; }); exports.ADD = Instruction((core, pc, a, b) => { if (a.mode === AddrMode.Immediate) { const dst = core.data[b.value]; dst.b.value += a.value; } else { const src = core.data[a.value]; const dst = core.data[b.value]; dst.a.value += src.a.value; dst.b.value += src.b.value; } return [core.normalize(pc, 1)]; }); exports.SUB = Instruction((core, pc, a, b) => { if (a.mode === AddrMode.Immediate) { const dst = core.data[b.value]; dst.b.value -= a.value; } else { const src = core.data[a.value]; const dst = core.data[b.value]; dst.a.value -= src.a.value; dst.b.value -= src.b.value; } return [core.normalize(pc, 1)]; }); exports.CMP = Instruction((core, pc, a, b) => { if (a.mode === AddrMode.Immediate) { const test = core.data[b.value]; if (test.b.value === a.value) { return [core.normalize(pc, 2)]; } else { return [core.normalize(pc, 1)]; } } else { const left = core.data[a.value]; const right = core.data[b.value]; if ( // compare opcode left.opcode === right.opcode && // compare a-field left.a.mode === right.a.mode && left.a.value === right.a.value && // compare b-field left.b.mode === right.b.mode && left.b.value === right.b.value ) { return [core.normalize(pc, 2)]; } else { return [core.normalize(pc, 1)]; } } }); exports.SLT = Instruction((core, pc, a, b) => { if (a.mode === AddrMode.Immediate) { const test = core.data[b.value]; if (a.value < test.b.value) { return [core.normalize(pc, 2)]; } else { return [core.normalize(pc, 1)]; } } else { const left = core.data[a.value]; const right = core.data[b.value]; if (left.b.value < right.b.value) { return [core.normalize(pc, 2)]; } else { return [core.normalize(pc, 1)]; } } }); exports.JMP = Instruction((core, pc, a, b) => { return [a.value]; }); exports.JMZ = Instruction((core, pc, a, b) => { let test if (b.mode === AddrMode.Immediate) { test = (b.value === 0); } else { const src = core.data[b.value]; test = (src.b.value === 0); } if (test) { return [a.value]; } else { return [core.normalize(pc, 1)]; } }); exports.JMN = Instruction((core, pc, a, b) => { let test; if (b.mode === AddrMode.Immediate) { test = (b.value !== 0); } else { const src = core.data[b.value]; test = (src.b.value !== 0); } if (test) { return [a.value]; } else { return [core.normalize(pc, 1)]; } }); exports.DJN = Instruction((core, pc, a, b) => { let test; if (b.mode === AddrMode.Immediate) { core.data[pc].b.value -= 1; b.value -= 1; test = (b.value !== 0); } else { const src = core.data[b.value]; src.b.value -= 1; test = (src.b.value !== 0); } if (test) { return [a.value]; } else { return [core.normalize(pc, 1)]; } }); exports.SPL = Instruction((core, pc, a, b) => { return [ core.normalize(pc, 1), a.value, ]; });