| this.__PC = (initpc >= 0) ? initpc : 0; | this.__PC = (initpc >= 0) ? initpc : 0; | ||||
| } | } | ||||
| function __AddrModeVal(tA, tB){ | |||||
| __StoreVarLabel(lbl, val){ | |||||
| if (lbl in this.__varlabels) | |||||
| throw new Error("Variable label '" + lbl + "' defined more than once."); | |||||
| if (lbl in this.__jmplabels) | |||||
| throw new Error("Variable label '" + lbl + "' matches already existing jump label."); | |||||
| let v = Number.NaN; | |||||
| if (val[0] === "$"){ | |||||
| if (val.length >= 2 && val.length <= 5) | |||||
| v = parseInt(val.substr(1), 16); | |||||
| } else if (val[0] === "#"){ | |||||
| if (val.startsWith("#b")){ | |||||
| v = parseInt(val.substr(2), 2); | |||||
| } else { | |||||
| v = parseInt(val); | |||||
| } | |||||
| } | |||||
| if (!isNaN(v)){ | |||||
| if (v < 0 || v > 65535) | |||||
| throw new Error("Variable '" + lbl + "' value is out of bounds for this processor."); | |||||
| this.__varlabels[lbl] = v; | |||||
| } else { | |||||
| throw new Error("Variable '" + lbl + "' value malformed."); | |||||
| } | |||||
| } | |||||
| __StoreJmpLabel(lbl){ | |||||
| if (lbl in this.__jmplabels) | |||||
| throw new Error("Jump label '" + lbl + "' defined more than once at program address " + toHexString(this.__PC)); | |||||
| if (lbl in this.__varlabels) | |||||
| throw new Error("Jump label '" + lbl + "' matches already existing variable name at program address " + toHexString(this.__PC)); | |||||
| this.__jmplabels[lbl] = this.__PC; | |||||
| } | |||||
| __AddrModeVal(tA, tB){ | |||||
| var mode = ""; | var mode = ""; | ||||
| var v = Number.NaN; | var v = Number.NaN; | ||||
| if (tA[0] === '#'){ | if (tA[0] === '#'){ | ||||
| if (tokens[0] === 'define'){ | if (tokens[0] === 'define'){ | ||||
| // Variable label!! | // Variable label!! | ||||
| this.__StoreVarLabel(tokens[1], tokens[2]); | |||||
| } else if (tokens[0][tokens[0].length - 1] === ':'){ | } else if (tokens[0][tokens[0].length - 1] === ':'){ | ||||
| // Jump labels! | // Jump labels! | ||||
| // TODO: Finish me!! | |||||
| let lbl = tokens[0].substr(0, tokens[0].length - 1); | |||||
| if (lbl in this.__jmplabels) | |||||
| throw new Error("Jump label '" + lbl + "' defined more than once at program address " + toHexString(this.__PC)); | |||||
| if (lbl in this.__varlabels) | |||||
| throw new Error("Jump label '" + lbl + "' matches already existing variable name at program address " + toHexString(this.__PC)); | |||||
| this.__jmplabels[lbl] = this.__PC; | |||||
| this.__StoreJmpLabel(tokens[0].substr(0, tokens[0].length - 1);); | |||||
| } else if (tokens[0].length === 3){ | } else if (tokens[0].length === 3){ | ||||
| let StoreSingleOp = (code)=>{ | let StoreSingleOp = (code)=>{ | ||||
| }; | }; | ||||
| let StoreBranchOp = (code) => { | let StoreBranchOp = (code) => { | ||||
| // TODO: If value is not valid, test to see if it's a jump or variable value. | |||||
| if (tokens.length === 2){ | if (tokens.length === 2){ | ||||
| if (token[1][0] === '$' && (tokens[1].length === 3 || tokens[1].length === 5)){ | |||||
| let v = parseInt(token[1].substr(1), 16); | |||||
| if (isNaN(v)) | |||||
| return false; | |||||
| let v = Number.NaN; | |||||
| if (token[1][0] === '$'){ | |||||
| if (tokens[1].length === 3 || tokens[1].length === 5){ | |||||
| v = parseInt(token[1].substr(1), 16); | |||||
| } | |||||
| } else { | |||||
| if (tokens[1] in this.__jmplabels){ | |||||
| v = this.__jmplabels[tokens[1]]; | |||||
| } | |||||
| } | |||||
| if (!isNaN(v)){ | |||||
| if (v < this.__PC - 127 || v > this.__PC + 128) | if (v < this.__PC - 127 || v > this.__PC + 128) | ||||
| throw new Error("Branch exceeds maximum number of bytes on program address " + toHexString(this.__PC)); | throw new Error("Branch exceeds maximum number of bytes on program address " + toHexString(this.__PC)); | ||||
| v = v - this.__PC; | v = v - this.__PC; | ||||
| procFailed = StoreSingleOp(0xC8); break; | procFailed = StoreSingleOp(0xC8); break; | ||||
| // --- JMP | // --- JMP | ||||
| case 'jmp': | case 'jmp': | ||||
| // TODO: Update value results to test for jump names if value not a number. | |||||
| if (tokens.length === 2){ | if (tokens.length === 2){ | ||||
| if (tokens[1].startsWith("$") && tokens[1].length === 5){ | |||||
| let v = parseInt(tokens[1].substr(1), 16); | |||||
| if (!isNaN(v)){ | |||||
| op.push(0x4C); | |||||
| op.push(v & 0x000000FF); | |||||
| op.push((v & 0x0000FF00) >> 8); | |||||
| this.__PC += 3; | |||||
| } else { | |||||
| throw new Error("Malformed op-code or value on program address " + toHexString(this.__PC)); | |||||
| } | |||||
| } else if (tokens[1].startsWith("+$") && tokens[1].length === 6){ | |||||
| let v = parseInt(tokens[1].substr(2), 16); | |||||
| if (!isNaN(v)){ | |||||
| op.push(0x6C); | |||||
| op.push(v & 0x000000FF); | |||||
| op.push((v & 0x0000FF00) >> 8); | |||||
| this.__PC += 3; | |||||
| } else { | |||||
| throw new Error("Malformed op-code or value on program address " + toHexString(this.__PC)); | |||||
| } | |||||
| } else { procFailed = true; } | |||||
| let v = Number.NaN; | |||||
| let code = (tokens[1].startsWith("+")) ? 0x6C : 0x4C; | |||||
| if (tokens[1].startsWith("$")){ | |||||
| if (tokens[1].length === 5) | |||||
| v = parseInt(tokens[1].substr(1), 16); | |||||
| } else if (tokens[1].startsWith("+$")){ | |||||
| if (tokens[1].length === 6) | |||||
| v = parseInt(tokens[1].substr(2), 16); | |||||
| } else { | |||||
| let lbl = (tokens[1].startsWith("+")) ? tokens[1].substr(1) : tokens[1]; | |||||
| if (lbl in this.__jmplabels) | |||||
| v = this.__jmplabels[lbl]; | |||||
| } | |||||
| if (!isNaN(v)){ | |||||
| op.push(code); | |||||
| op.push(v & 0x000000FF); | |||||
| op.push((v & 0x0000FF00) >> 8); | |||||
| this.__PC += 3; | |||||
| } else { | |||||
| throw new Error("Malformed op-code or value on program address " + toHexString(this.__PC)); | |||||
| } | |||||
| } else { procFailed = true; } | } else { procFailed = true; } | ||||
| break; | break; | ||||
| // --- JSR | // --- JSR | ||||
| case 'jsr': | case 'jsr': | ||||
| // TODO: Update value results to test for jump names if value not a number. | |||||
| if (tokens.length === 2){ | if (tokens.length === 2){ | ||||
| if (tokens[1].startsWith("$") && tokens[1].length === 5){ | |||||
| let v = parseInt(tokens[1].substr(1), 16); | |||||
| if (!isNaN(v)){ | |||||
| op.push(0x20); | |||||
| op.push(v & 0x000000FF); | |||||
| op.push((v & 0x0000FF00) >> 8); | |||||
| this.__PC += 3; | |||||
| } else { | |||||
| throw new Error("Malformed op-code or value on program address " + toHexString(this.__PC)); | |||||
| } | |||||
| } else { procFailed = true; } | |||||
| let v = Number.NaN; | |||||
| if (tokens[1].startsWith("$")){ | |||||
| if (tokens[1].length === 5) | |||||
| v = parseInt(tokens[1].substr(1), 16); | |||||
| } else { | |||||
| if (tokens[1] in this.__jmplabels) | |||||
| v = this.__jmplabels[tokens[1]]; | |||||
| } | |||||
| if (!isNaN(v)){ | |||||
| op.push(0x20); | |||||
| op.push(v & 0x000000FF); | |||||
| op.push((v & 0x0000FF00) >> 8); | |||||
| this.__PC += 3; | |||||
| } else { | |||||
| throw new Error("Malformed op-code or value on program address " + toHexString(this.__PC)); | |||||
| } | |||||
| } else { | } else { | ||||
| procFailed = true; | procFailed = true; | ||||
| } | } |