Browse Source

MOS6502 bug fixes, added compiler directive '.bytes'. All directives will now start with a period (including 'define'). Tests updated.

master
Bryan Miller 5 years ago
parent
commit
bd3c510e07
2 changed files with 74 additions and 8 deletions
  1. +36
    -6
      src/MOS6502.js
  2. +38
    -2
      test/MOS6502.spec.js

+ 36
- 6
src/MOS6502.js View File

if (line === ""){return this;} if (line === ""){return this;}
if (line[0] !== ";"){ // Skip comment lines. if (line[0] !== ";"){ // Skip comment lines.
line = line.split(";")[0].trim(); // Take out any trailing comments. line = line.split(";")[0].trim(); // Take out any trailing comments.
// Checking for any jump labels!
if (line.indexOf(":") >= 0){
let s = line.split(":");
let lbl = s[0].trim();
if (lbl.length <= 0)
throw new Error("Malformatted jump label at program address " + toHexString(this.__PC));
this.__StoreJmpLabel(lbl);
line = s[1].trim();
if (line.length <= 0){return this;} // Nothing left to process.
}
// Finally... tokenize the main command.
var tokens = tokenize(line); var tokens = tokenize(line);


if (tokens[0].toLowerCase() === 'define'){
if (tokens[0].toLowerCase() === '.define'){
// Variable label!! // Variable label!!
this.__StoreVarLabel(tokens[1], tokens[2]); 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!
this.__StoreJmpLabel(tokens[0].substr(0, tokens[0].length - 1));
this.__StoreJmpLabel(tokens[0].substr(0, tokens[0].length - 1));*/
} else if (tokens[0].toLowerCase() === '.bytes'){
// Compiler directive. Treat all proceeding tokens as values and store them raw.
for(let i=1; i < tokens.length; i++){
let v = Number.NaN;
if (tokens[i].startsWith("$")){
v = parseInt(tokens[i].substr(1), 16);
} else if (tokens[i].startsWith("b")){
v = parseInt(tokens[i].substr(1), 2);
} else {
v = parseInt(tokens[i]);
}
if (isNaN(v) || v < 0 || v >= 256)
throw new Error("Byte list value is malformed or out of bounds at program address " + toHexString(this.__PC));
op.push(v);
this.__PC += 1;
};
} else if (tokens[0].length === 3){ } else if (tokens[0].length === 3){


let StoreSingleOp = (code)=>{ let StoreSingleOp = (code)=>{
} }


if (!isNaN(v)){ 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;
if (v < (this.__PC+1) - 127 || v > (this.__PC+1) + 128)
throw new Error("Branch exceeds maximum number of bytes on program address " + toHexString(this.__PC + 1));
v = v - (this.__PC + 1);
op.push(code); op.push(code);
op.push((v >= 0) ? v : v + 255); op.push((v >= 0) ? v : v + 255);
this.__PC += 2; this.__PC += 2;
case 'tya': case 'tya':
procFailed = StoreSingleOp(0x98); break; procFailed = StoreSingleOp(0x98); break;
// --- --- // --- ---
// EOL
// --- ---
default: default:
throw new Error("Unknown op-code '" + tokens[0].toUpperCase() + "' at program address " + toHexString(this.__PC)); throw new Error("Unknown op-code '" + tokens[0].toUpperCase() + "' at program address " + toHexString(this.__PC));
} }
this.__varlabels = {}; this.__varlabels = {};
this.__jmplabels = {}; this.__jmplabels = {};
this.__result = []; this.__result = [];
return this;
} }
} }



+ 38
- 2
test/MOS6502.spec.js View File

}); });


describe(".compile()", function(){ describe(".compile()", function(){
it("Variable definition", function(){
asm.compile("define TAG $44");
it(".define directive", function(){
asm.compile(".define TAG $44");
let vars = asm.variables; let vars = asm.variables;
expect(vars).to.have.key('TAG'); expect(vars).to.have.key('TAG');
expect(vars['TAG']).to.equal(0x44); expect(vars['TAG']).to.equal(0x44);
expect(jmp['loop']).to.equal(pc); expect(jmp['loop']).to.equal(pc);
}); });


it(".bytes directive", function(){
let res = asm.reset().compile(".BYTES $44, $55, $66, $77, b10110101, 128").result();
expect(res.length).to.equal(6);
expect(res[0]).to.equal(0x44);
expect(res[1]).to.equal(0x55);
expect(res[2]).to.equal(0x66);
expect(res[3]).to.equal(0x77);
expect(res[4]).to.equal(parseInt('10110101', 2));
expect(res[5]).to.equal(128);
});

it("Jump label before and after .byte directive", function(){
asm.reset();
let pc1 = asm.PC;
asm.compile("bytes: .bytes $44, $55, $66, $77");
let pc2 = asm.PC;
asm.compile("loop: BNE loop");

let jmp = asm.jumplabels;
//expect(jmp).to.have.key('bytes');
expect(jmp['bytes']).to.equal(pc1);
//expect(jmp).to.have.key('loop');
expect(jmp['loop']).to.equal(pc2);

let res = asm.result();
expect(res.length).to.equal(6);
expect(res[0]).to.equal(0x44);
expect(res[1]).to.equal(0x55);
expect(res[2]).to.equal(0x66);
expect(res[3]).to.equal(0x77);
expect(res[4]).to.equal(0xD0);
expect(res[5]).to.equal(0xFE);
});

it("ADC Immediate", function(){ it("ADC Immediate", function(){
asm.reset(); asm.reset();
asm.compile("ADC #$44"); asm.compile("ADC #$44");
it("STY Zero Page"); it("STY Zero Page");
it("STY Zero Page, X"); it("STY Zero Page, X");
it("STY Absolute"); it("STY Absolute");

// -------------------------------------------------------------
}); });
}); });



Loading…
Cancel
Save