|
|
@@ -105,7 +105,40 @@ class Assembler{ |
|
|
|
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 v = Number.NaN; |
|
|
|
if (tA[0] === '#'){ |
|
|
@@ -207,15 +240,10 @@ class Assembler{ |
|
|
|
|
|
|
|
if (tokens[0] === 'define'){ |
|
|
|
// Variable label!! |
|
|
|
this.__StoreVarLabel(tokens[1], tokens[2]); |
|
|
|
} else if (tokens[0][tokens[0].length - 1] === ':'){ |
|
|
|
// 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){ |
|
|
|
|
|
|
|
let StoreSingleOp = (code)=>{ |
|
|
@@ -228,12 +256,19 @@ class Assembler{ |
|
|
|
}; |
|
|
|
|
|
|
|
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 (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) |
|
|
|
throw new Error("Branch exceeds maximum number of bytes on program address " + toHexString(this.__PC)); |
|
|
|
v = v - this.__PC; |
|
|
@@ -444,46 +479,49 @@ class Assembler{ |
|
|
|
procFailed = StoreSingleOp(0xC8); break; |
|
|
|
// --- JMP |
|
|
|
case 'jmp': |
|
|
|
// TODO: Update value results to test for jump names if value not a number. |
|
|
|
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; } |
|
|
|
break; |
|
|
|
// --- JSR |
|
|
|
case 'jsr': |
|
|
|
// TODO: Update value results to test for jump names if value not a number. |
|
|
|
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 { |
|
|
|
procFailed = true; |
|
|
|
} |