Rework the way the cpu object loads and executes code

This commit is contained in:
Preston Skupinski 2011-11-05 21:45:36 -04:00
parent 798dd18835
commit a9b70c8ad0
3 changed files with 173 additions and 114 deletions

6
README
View File

@ -2,4 +2,8 @@ This project's goal is to fully emulate the 65816 microprocessor in JavaScript.
After achieving that goal the next step will be to create a new branch that will focus on emulating the SNES. Any CPU related improvements that aren't specific to the SNES will be merged back. After achieving that goal the next step will be to create a new branch that will focus on emulating the SNES. Any CPU related improvements that aren't specific to the SNES will be merged back.
You call the execute function of the cpu object with a raw hex string representing the program you wish to emulate and it will execute those instructions as close to the 65816 as possible. Here is a short example of how to use the emulator:
var cpu = new CPU_65816();
cpu.load_binary("18fba9ff", 0x8000); // Load the program at 0x8000 in memory
cpu.execute(0x8000); // Execute starting at 0x8000

58
cpu.js
View File

@ -255,28 +255,23 @@ function CPU_65816() {
/** /**
* Load given program into memory and prepare for execution. * Load given program into memory and prepare for execution.
*/ */
this.load_program = function(raw_hex, has_header) { this.load_binary = function(raw_hex, memory_location_start) {
this.mmu.load_rom(raw_hex); var loc = memory_location_start;
this.r.pc = 0x8000; var byte_buffer = [];
for(var i = 0; i < raw_hex.length; i++) {
// Skip the header(the first 512 bytes) if there is one present for now. byte_buffer.push(raw_hex[i]);
if(has_header) { if(byte_buffer.length===2) {
this.r.pc += 4096; this.mmu.store_byte(loc, parseInt(byte_buffer[0]+byte_buffer[1],
} "16"));
loc++;
byte_buffer = [];
}
}
}; };
/** /**
* Take a raw hex string representing the program and execute it. * Step through the processing of a single instruction from the current
*/ * location of the program counter.
this.execute = function(raw_hex, has_header) {
this.load_program(raw_hex, has_header);
this.start();
};
/**
* Step through the processing of a single byte from the current location of
* the program counter.
* TODO: Refactor the code to only process a single byte per step call
*/ */
this.step = function() { this.step = function() {
if(this.interrupt&&(!this.p.i|(this.interrupt===this.INTERRUPT.NMI))) { if(this.interrupt&&(!this.p.i|(this.interrupt===this.INTERRUPT.NMI))) {
@ -364,11 +359,6 @@ function CPU_65816() {
return; return;
} }
var operation = this.opcode_map[b]; var operation = this.opcode_map[b];
// Check if unsupported opcode.
if(operation==null) {
this.executing = false;
return;
}
var bytes_required = operation.bytes_required(this); var bytes_required = operation.bytes_required(this);
if(bytes_required===1) { if(bytes_required===1) {
operation.execute(this); operation.execute(this);
@ -385,7 +375,12 @@ function CPU_65816() {
this.executing = false; this.executing = false;
}; };
this.start = function() { /**
* TODO: Add ability for this function to limit number of cpu cycles per
* second.
*/
this.execute = function(start_address) {
this.r.pc = start_address;
this.executing = true; this.executing = true;
while(this.executing) { while(this.executing) {
this.step(); this.step();
@ -493,19 +488,6 @@ function MMU() {
} }
this.memory[bank][location] = b; this.memory[bank][location] = b;
}; };
this.load_rom = function(raw_hex) {
var loc = 0x8000;
var byte_buffer = [];
for(var i = 0; i < raw_hex.length; i++) {
byte_buffer.push(raw_hex[i]);
if(byte_buffer.length===2) {
this.store_byte(loc, parseInt(byte_buffer[0]+byte_buffer[1], "16"));
loc++;
byte_buffer = [];
}
}
};
} }
var STP = { var STP = {

View File

@ -33,7 +33,8 @@ function test_lda() {
test("Make sure LDA with a constant properly loads an 8-bit value in "+ test("Make sure LDA with a constant properly loads an 8-bit value in "+
"8-bit memory/accumulator mode.", function() { "8-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9ff"); cpu.load_binary("18fba9ff", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xff, "The accumulator should be 0xff when 0xff is "+ equals(cpu.r.a, 0xff, "The accumulator should be 0xff when 0xff is "+
"given as its argument in 8-bit "+ "given as its argument in 8-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -45,7 +46,8 @@ function test_lda() {
test("Make sure LDA with a constant properly loads a 16-bit value in "+ test("Make sure LDA with a constant properly loads a 16-bit value in "+
"16-bit memory/accumulator mode.", function() { "16-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9ffff"); cpu.load_binary("18fbc220a9ffff", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xffff, "The accumulator should be 0xffff when 0xffff is "+ equals(cpu.r.a, 0xffff, "The accumulator should be 0xffff when 0xffff is "+
"given as its argument in 16-bit "+ "given as its argument in 16-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -58,7 +60,8 @@ function test_lda() {
test("Make sure LDA with a direct page address loads an 8-bit value in "+ test("Make sure LDA with a direct page address loads an 8-bit value in "+
"8-bit memory/accumulator mode.", function() { "8-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba90185fea5fe"); cpu.load_binary("18fba90185fea5fe", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 1, "The accumulator should be 1 when 1 is "+ equals(cpu.r.a, 1, "The accumulator should be 1 when 1 is "+
"loaded from $fe(direct page) in 8-bit "+ "loaded from $fe(direct page) in 8-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -70,7 +73,8 @@ function test_lda() {
test("Make sure LDA with a direct page address loads a 16-bit value in "+ test("Make sure LDA with a direct page address loads a 16-bit value in "+
"16-bit memory/accumulator mode.", function() { "16-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a901ff85fea5fe"); cpu.load_binary("18fbc220a901ff85fea5fe", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xff01, "The accumulator should be 0xff01 when 0xff01 "+ equals(cpu.r.a, 0xff01, "The accumulator should be 0xff01 when 0xff01 "+
"is loaded from $fe(direct page) in 16-bit "+ "is loaded from $fe(direct page) in 16-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -82,7 +86,8 @@ function test_lda() {
test("Make sure LDA with an absolute address loads an 8-bit value in "+ test("Make sure LDA with an absolute address loads an 8-bit value in "+
"8-bit memory/accumulator mode.", function() { "8-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9fe8dff0aa900adff0a"); cpu.load_binary("18fba9fe8dff0aa900adff0a", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe when 0xfe is "+ equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe when 0xfe is "+
"loaded from $0aff(absolute) in 8-bit "+ "loaded from $0aff(absolute) in 8-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -94,7 +99,8 @@ function test_lda() {
test("Make sure LDA with an absolute address loads a 16-bit value in "+ test("Make sure LDA with an absolute address loads a 16-bit value in "+
"16-bit memory/accumulator mode.", function() { "16-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9ffff8dff0aa90000adff0a"); cpu.load_binary("18fbc220a9ffff8dff0aa90000adff0a", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xffff, "The accumulator should be 0xffff when 0xffff "+ equals(cpu.r.a, 0xffff, "The accumulator should be 0xffff when 0xffff "+
"is loaded from $0aff and $0b00(absolute) in 16-bit "+ "is loaded from $0aff and $0b00(absolute) in 16-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -107,7 +113,8 @@ function test_lda() {
"register loads an 8-bit value in 8-bit memory/accumulator mode.", "register loads an 8-bit value in 8-bit memory/accumulator mode.",
function() { function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba201a9ff85ffa900b5fe"); cpu.load_binary("18fba201a9ff85ffa900b5fe", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xff, "The accumulator should be 0xff when 0xff "+ equals(cpu.r.a, 0xff, "The accumulator should be 0xff when 0xff "+
"is loaded from direct page address $fe indexed "+ "is loaded from direct page address $fe indexed "+
"with x(which is 1) and thus loaded from $ff in "+ "with x(which is 1) and thus loaded from $ff in "+
@ -124,7 +131,8 @@ function test_lda() {
"register loads a 16-bit value in 16-bit memory/accumulator mode.", "register loads a 16-bit value in 16-bit memory/accumulator mode.",
function() { function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a201a9ffff85fea90000bdfd"); cpu.load_binary("18fbc220a201a9ffff85fea90000bdfd", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xffff, "The accumulator should be 0xffff when 0xffff "+ equals(cpu.r.a, 0xffff, "The accumulator should be 0xffff when 0xffff "+
"is loaded from direct page addresses $fe and "+ "is loaded from direct page addresses $fe and "+
"$ff after $fd is indexed with the x register("+ "$ff after $fd is indexed with the x register("+
@ -140,7 +148,8 @@ function test_lda() {
test("Make sure LDA indirect given a direct page address loads an 8-bit "+ test("Make sure LDA indirect given a direct page address loads an 8-bit "+
"value in 8-bit memory/accumulator mode.", function() { "value in 8-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9ff85fea90a85ffa9068dff0aa900b2fe"); cpu.load_binary("18fba9ff85fea90a85ffa9068dff0aa900b2fe", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 6, "The accumulator should be 6 when LDA loads an 8-bit "+ equals(cpu.r.a, 6, "The accumulator should be 6 when LDA loads an 8-bit "+
"value using an indirect address in 8-bit mode "+ "value using an indirect address in 8-bit mode "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -152,7 +161,8 @@ function test_lda() {
test("Make sure LDA indirect given a direct page address loads a 16-bit "+ test("Make sure LDA indirect given a direct page address loads a 16-bit "+
"value in 16-bit memory/accumulator mode.", function() { "value in 16-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9ff0a85fea9ffff8dff0aa90000b2fe"); cpu.load_binary("18fbc220a9ff0a85fea9ffff8dff0aa90000b2fe", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xffff, "The accumulator should be 0xffff when LDA loads "+ equals(cpu.r.a, 0xffff, "The accumulator should be 0xffff when LDA loads "+
"a 16-bit value using an indirect address "+ "a 16-bit value using an indirect address "+
"loaded from a direct page address."); "loaded from a direct page address.");
@ -164,7 +174,8 @@ function test_lda() {
test("Ensure that LDA absolute indexed by the x register works for 8-bit "+ test("Ensure that LDA absolute indexed by the x register works for 8-bit "+
"memory/accumulator mode.", function() { "memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9fa8dff0aa201a900bdfe0a"); cpu.load_binary("18fba9fa8dff0aa201a900bdfe0a", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfa, "The accumulator should be 0xfa when LDA loads "+ equals(cpu.r.a, 0xfa, "The accumulator should be 0xfa when LDA loads "+
"an 8-bit value using absolute indexed x mode "+ "an 8-bit value using absolute indexed x mode "+
"from $0aff"); "from $0aff");
@ -178,7 +189,8 @@ function test_lda() {
test("Ensure that LDA absolute indexed by the x register works for 16-bit "+ test("Ensure that LDA absolute indexed by the x register works for 16-bit "+
"memory/accumulator mode.", function() { "memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9fefa8dff0aa203bdfc0a"); cpu.load_binary("18fbc220a9fefa8dff0aa203bdfc0a", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA "+ equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA "+
"loads a 16-bit value from $0aff using "+ "loads a 16-bit value from $0aff using "+
"absolute indexed x addressing mode."); "absolute indexed x addressing mode.");
@ -192,7 +204,8 @@ function test_lda() {
test("Ensure that LDA absolute indexed by the y register works for 8-bit "+ test("Ensure that LDA absolute indexed by the y register works for 8-bit "+
"memory/acccumulator mode.", function() { "memory/acccumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9fe8dff0aa002a900b9fd0a"); cpu.load_binary("18fba9fe8dff0aa002a900b9fd0a", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe when LDA loads an "+ equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe when LDA loads an "+
"8-bit value from $0aff using absolute indexed y "+ "8-bit value from $0aff using absolute indexed y "+
"addressing mode."); "addressing mode.");
@ -206,7 +219,8 @@ function test_lda() {
test("Ensure that LDA absolute indexed by the y register works for 16-bit "+ test("Ensure that LDA absolute indexed by the y register works for 16-bit "+
"memory/accumulator mode.", function() { "memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9fefa8dff0aa003a90000b9fc0a"); cpu.load_binary("18fbc220a9fefa8dff0aa003a90000b9fc0a", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA loads "+ equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA loads "+
"a 16-bit value from $0aff using absolute "+ "a 16-bit value from $0aff using absolute "+
"indexed y addressing mode."); "indexed y addressing mode.");
@ -220,7 +234,8 @@ function test_lda() {
test("Ensure that LDA stack relative works for 8-bit memory/accumulator "+ test("Ensure that LDA stack relative works for 8-bit memory/accumulator "+
"mode.", function() { "mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9fe48a90148a900a302"); cpu.load_binary("18fba9fe48a90148a900a302", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe when LDA loads "+ equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe when LDA loads "+
"an 8-bit value from the stack using LDA stack "+ "an 8-bit value from the stack using LDA stack "+
"relative addressing mode."); "relative addressing mode.");
@ -232,7 +247,8 @@ function test_lda() {
test("Ensure that LDA stack relative works for 16-bit memory/accumulator "+ test("Ensure that LDA stack relative works for 16-bit memory/accumulator "+
"mode.", function() { "mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9fefa48a9010048a90000a303"); cpu.load_binary("18fbc220a9fefa48a9010048a90000a303", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA "+ equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA "+
"loads a 16-bit value from the stack using LDA "+ "loads a 16-bit value from the stack using LDA "+
"stack relative addressing mode."); "stack relative addressing mode.");
@ -244,7 +260,8 @@ function test_lda() {
test("Ensure that LDA absolute long works for 8-bit memory/accumulator "+ test("Ensure that LDA absolute long works for 8-bit memory/accumulator "+
"mode.", function() { "mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9fa8fffeeaaa900afffeeaa"); cpu.load_binary("18fba9fa8fffeeaaa900afffeeaa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfa, "The accumulator should be 0xfa when LDA "+ equals(cpu.r.a, 0xfa, "The accumulator should be 0xfa when LDA "+
"loads an 8-bit value from $aaeeff using "+ "loads an 8-bit value from $aaeeff using "+
"absolute long addressing mode."); "absolute long addressing mode.");
@ -256,7 +273,8 @@ function test_lda() {
test("Ensure that LDA absolute long works for 16-bit memory/accumulator "+ test("Ensure that LDA absolute long works for 16-bit memory/accumulator "+
"mode.", function() { "mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9fefa8fffeeaaa90000afffeeaa"); cpu.load_binary("18fbc220a9fefa8fffeeaaa90000afffeeaa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA "+ equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA "+
"loads a 16-bit value from $aaeeff using "+ "loads a 16-bit value from $aaeeff using "+
"absolute long addressing mode."); "absolute long addressing mode.");
@ -268,7 +286,8 @@ function test_lda() {
test("Ensure that LDA absolute long indexed by the x register works for "+ test("Ensure that LDA absolute long indexed by the x register works for "+
"8-bit memory/accumulator mode.", function() { "8-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9fe8fffeeaaa202a900bffdeeaa"); cpu.load_binary("18fba9fe8fffeeaaa202a900bffdeeaa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe when LDA "+ equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe when LDA "+
"loads an 8-bit value from $aaeeff using "+ "loads an 8-bit value from $aaeeff using "+
"absolute long indexed x addressing mode."); "absolute long indexed x addressing mode.");
@ -282,7 +301,8 @@ function test_lda() {
test("Ensure that LDA absolute long indexed by the x register works for "+ test("Ensure that LDA absolute long indexed by the x register works for "+
"16-bit memory/accumulator mode.", function() { "16-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9fefa8fffeeaaa203a90000bffceeaa"); cpu.load_binary("18fbc220a9fefa8fffeeaaa203a90000bffceeaa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA "+ equals(cpu.r.a, 0xfafe, "The accumulator should be 0xfafe when LDA "+
"loads a 16-bit value from $aaeeff using "+ "loads a 16-bit value from $aaeeff using "+
"absolute long indexed x addressing mode."); "absolute long indexed x addressing mode.");
@ -299,7 +319,8 @@ function test_stz() {
module("STZ"); module("STZ");
test("Test STZ direct page for 8-bit memory/accumulator mode.", function() { test("Test STZ direct page for 8-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9ff85fa64faa5fa"); cpu.load_binary("18fba9ff85fa64faa5fa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "The accumulator should be zero after loading from a "+ equals(cpu.r.a, 0, "The accumulator should be zero after loading from a "+
"direct page addresss that has had zero stored to it."); "direct page addresss that has had zero stored to it.");
equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode."); equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode.");
@ -308,7 +329,8 @@ function test_stz() {
}); });
test("Test STZ direct page for 16-bit memory/accumulator mode.", function() { test("Test STZ direct page for 16-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9ffff85fa64faa5fa"); cpu.load_binary("18fbc220a9ffff85fa64faa5fa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "The accumulator should be zero after loading from a "+ equals(cpu.r.a, 0, "The accumulator should be zero after loading from a "+
"direct page address that had zero stored to it."); "direct page address that had zero stored to it.");
equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode."); equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode.");
@ -317,7 +339,8 @@ function test_stz() {
}); });
test("Test STZ absolute for 8-bit memory/accumulator mode.", function() { test("Test STZ absolute for 8-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9ff8d34129c3412ad3412"); cpu.load_binary("18fba9ff8d34129c3412ad3412", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "The accumulator should be zero after loading from an "+ equals(cpu.r.a, 0, "The accumulator should be zero after loading from an "+
"absolute address that had zero stored to it."); "absolute address that had zero stored to it.");
equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode."); equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode.");
@ -326,7 +349,8 @@ function test_stz() {
}); });
test("Test STZ absolute for 16-bit memory/accumulator mode.", function() { test("Test STZ absolute for 16-bit memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9ffff8d34129c3412ad3412"); cpu.load_binary("18fbc220a9ffff8d34129c3412ad3412", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "The accumulator should be zero after loading from an "+ equals(cpu.r.a, 0, "The accumulator should be zero after loading from an "+
"absolute page address that had zero stored to it."); "absolute page address that had zero stored to it.");
equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode."); equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode.");
@ -336,7 +360,8 @@ function test_stz() {
test("Test STZ direct page indexed by the x register for 8-bit "+ test("Test STZ direct page indexed by the x register for 8-bit "+
"memory/accumulator mode.", function() { "memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9ff85fb85faa20174faa5fb"); cpu.load_binary("18fba9ff85fb85faa20174faa5fb", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "The accumulator should be zero after loading from a "+ equals(cpu.r.a, 0, "The accumulator should be zero after loading from a "+
"direct page addresss that has had zero stored to it."); "direct page addresss that has had zero stored to it.");
equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode."); equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode.");
@ -346,7 +371,8 @@ function test_stz() {
test("Test STZ direct page indexed by the x register for 16-bit "+ test("Test STZ direct page indexed by the x register for 16-bit "+
"memory/accumulator mode.", function() { "memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9ffff85faa20274f8a5fa"); cpu.load_binary("18fbc220a9ffff85faa20274f8a5fa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "The accumulator should be zero after loading from a "+ equals(cpu.r.a, 0, "The accumulator should be zero after loading from a "+
"direct page address that had zero stored to it."); "direct page address that had zero stored to it.");
equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode."); equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode.");
@ -356,7 +382,8 @@ function test_stz() {
test("Test STZ absolute indexed by the x register for 8-bit "+ test("Test STZ absolute indexed by the x register for 8-bit "+
"memory/accumulator mode.", function() { "memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fba9ff8dbbaa8dbaaaa2019ebaaaadbbaa"); cpu.load_binary("18fba9ff8dbbaa8dbaaaa2019ebaaaadbbaa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "The accumulator should be zero after loading from an "+ equals(cpu.r.a, 0, "The accumulator should be zero after loading from an "+
"absolute address that had zero stored to it."); "absolute address that had zero stored to it.");
equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode."); equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode.");
@ -366,7 +393,8 @@ function test_stz() {
test("Test STZ absolute indexed by the x register for 16-bit "+ test("Test STZ absolute indexed by the x register for 16-bit "+
"memory/accumulator mode.", function() { "memory/accumulator mode.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220a9ffff8dbbaaa2029eb9aaadbbaa"); cpu.load_binary("18fbc220a9ffff8dbbaaa2029eb9aaadbbaa", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "The accumulator should be zero after loading from an "+ equals(cpu.r.a, 0, "The accumulator should be zero after loading from an "+
"absolute page address that had zero stored to it."); "absolute page address that had zero stored to it.");
equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode."); equals(cpu.p.e, 0, "The hidden e flag should be zero for native mode.");
@ -380,7 +408,8 @@ function test_emulation_mode() {
test("Make sure pulling from the stack when the stack register is at 0x1ff"+ test("Make sure pulling from the stack when the stack register is at 0x1ff"+
"causes the stack register to pull from 0x100.", function() { "causes the stack register to pull from 0x100.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("a9fe8d0001a90068"); cpu.load_binary("a9fe8d0001a90068", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.s, 0, "The stack register should be 0 after the pull "+ equals(cpu.r.s, 0, "The stack register should be 0 after the pull "+
"operation."); "operation.");
equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe after the pull "+ equals(cpu.r.a, 0xfe, "The accumulator should be 0xfe after the pull "+
@ -392,7 +421,9 @@ function test_mvn_and_mvp() {
module("MVN and MVP"); module("MVN and MVP");
test("Test a short example program for MVP", function() { test("Test a short example program for MVP", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbe230a9ab8dff0fa9cd8d0010c230a90100a20010a00020440000"); cpu.load_binary("18fbe230a9ab8dff0fa9cd8d0010c230a90100a20010a00020440000",
0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xffff, "After executing the example program the "+ equals(cpu.r.a, 0xffff, "After executing the example program the "+
"accumulator should've underflowed and "+ "accumulator should've underflowed and "+
"resulted in 0xffff."); "resulted in 0xffff.");
@ -415,7 +446,8 @@ function test_subroutines() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
// It jumps to 0xffff so it doesn't execute the subroutine again and // It jumps to 0xffff so it doesn't execute the subroutine again and
// effectively halts the program. // effectively halts the program.
cpu.execute("18fbc23018a9ffff200e804cffff3a60"); cpu.load_binary("18fbc23018a9ffff200e804cffff3a60", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xfffe, "The subroutine should execute exactly once, "+ equals(cpu.r.a, 0xfffe, "The subroutine should execute exactly once, "+
"decrementing 0xffff to 0xfffe."); "decrementing 0xffff to 0xfffe.");
}); });
@ -425,7 +457,8 @@ function test_cmp() {
module("CMP"); module("CMP");
test("Compare two 8-bit numbers, 0x01 and 0xff", function() { test("Compare two 8-bit numbers, 0x01 and 0xff", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbe23018a901c9ff"); cpu.load_binary("18fbe23018a901c9ff", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x01, "CMP should not change the value of the "+ equals(cpu.r.a, 0x01, "CMP should not change the value of the "+
"accumulator"); "accumulator");
equals(cpu.p.z, 0, "When comparing 0x01 and 0xff the zero(z) bit "+ equals(cpu.p.z, 0, "When comparing 0x01 and 0xff the zero(z) bit "+
@ -437,7 +470,8 @@ function test_cmp() {
}); });
test("Compare two 16-bit numbers, 0xff01 and 0xfeff", function() { test("Compare two 16-bit numbers, 0xff01 and 0xfeff", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc23018a901ffc9fffe"); cpu.load_binary("18fbc23018a901ffc9fffe", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xff01, "CMP should not change the value of the "+ equals(cpu.r.a, 0xff01, "CMP should not change the value of the "+
"accumulator"); "accumulator");
equals(cpu.p.n, 0, "When comparing 0xff01 and 0xfeff the negative(n) "+ equals(cpu.p.n, 0, "When comparing 0xff01 and 0xfeff the negative(n) "+
@ -454,7 +488,8 @@ function test_sbc() {
test("Test normal subtraction of two 8-bit numbers that don't cause a "+ test("Test normal subtraction of two 8-bit numbers that don't cause a "+
"borrow.", function() { "borrow.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbe230a90138e901"); cpu.load_binary("18fbe230a90138e901", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "0x01 - 0x01 should result in zero when using "+ equals(cpu.r.a, 0, "0x01 - 0x01 should result in zero when using "+
"SBC"); "SBC");
equals(cpu.p.z, 1, "0x01 - 0x01 should set the zero(z) bit when "+ equals(cpu.p.z, 1, "0x01 - 0x01 should set the zero(z) bit when "+
@ -470,7 +505,8 @@ function test_sbc() {
test("Test normal subtraction of two 16-bit numbers that don't cause a "+ test("Test normal subtraction of two 16-bit numbers that don't cause a "+
"borrow.", function() { "borrow.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc230a9010038e90100"); cpu.load_binary("18fbc230a9010038e90100", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0, "0x0001 - 0x0001 should result in zero when using "+ equals(cpu.r.a, 0, "0x0001 - 0x0001 should result in zero when using "+
"SBC"); "SBC");
equals(cpu.p.z, 1, "0x0001 - 0x0001 should set the zero(z) bit when "+ equals(cpu.p.z, 1, "0x0001 - 0x0001 should set the zero(z) bit when "+
@ -485,7 +521,8 @@ function test_sbc() {
test("Test subtraction that triggers a borrow with 8-bit numbers", test("Test subtraction that triggers a borrow with 8-bit numbers",
function() { function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbe230a9d038e9ef"); cpu.load_binary("18fbe230a9d038e9ef", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xe1, "0xd0 - 0xef should set the accumulator to 0xe1 "+ equals(cpu.r.a, 0xe1, "0xd0 - 0xef should set the accumulator to 0xe1 "+
"when using SBC"); "when using SBC");
equals(cpu.p.n, 1, "0xd0 - 0xef should set the negative(n) bit when "+ equals(cpu.p.n, 1, "0xd0 - 0xef should set the negative(n) bit when "+
@ -500,7 +537,8 @@ function test_sbc() {
test("Test subtraction that triggers a borrow with 16-bit numbers", test("Test subtraction that triggers a borrow with 16-bit numbers",
function() { function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc230a900d038e900ef"); cpu.load_binary("18fbc230a900d038e900ef", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0xe100, "0xd000 - 0xef00 should set the accumulator to "+ equals(cpu.r.a, 0xe100, "0xd000 - 0xef00 should set the accumulator to "+
"0xe0ff when using SBC"); "0xe0ff when using SBC");
equals(cpu.p.n, 1, "0xd000 - 0xef00 should set the negative(n) bit when "+ equals(cpu.p.n, 1, "0xd000 - 0xef00 should set the negative(n) bit when "+
@ -515,7 +553,8 @@ function test_sbc() {
test("Test subtraction with decimal mode on with two single digit 8-bit "+ test("Test subtraction with decimal mode on with two single digit 8-bit "+
"numbers.", function() { "numbers.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbf8a90938e905"); cpu.load_binary("18fbf8a90938e905", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 4, "The accumulator should be 4 after subtracting 0x5 "+ equals(cpu.r.a, 4, "The accumulator should be 4 after subtracting 0x5 "+
"0x9 with decimal mode on with 8-bit "+ "0x9 with decimal mode on with 8-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -529,7 +568,8 @@ function test_sbc() {
test("Test subtraction with decimal mode on with two double digit 8-bit "+ test("Test subtraction with decimal mode on with two double digit 8-bit "+
"numbers.", function() { "numbers.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbf8a99038e949"); cpu.load_binary("18fbf8a99038e949", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x41, "The accumulator should be 41 after subtracting 0x49 "+ equals(cpu.r.a, 0x41, "The accumulator should be 41 after subtracting 0x49 "+
"from 0x90 with decimal mode on with 8-bit "+ "from 0x90 with decimal mode on with 8-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -543,7 +583,8 @@ function test_sbc() {
test("Test subtraction with decimal mode on with 8-bit numbers that causes "+ test("Test subtraction with decimal mode on with 8-bit numbers that causes "+
"a borrow.", function() { "a borrow.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbf8a91038e920"); cpu.load_binary("18fbf8a91038e920", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x90, "The accumulator should be 0x90 after subtracting "+ equals(cpu.r.a, 0x90, "The accumulator should be 0x90 after subtracting "+
"0x20 from 0x10 with decimal and 8-bit "+ "0x20 from 0x10 with decimal and 8-bit "+
"memory/accumulator modes."); "memory/accumulator modes.");
@ -557,7 +598,8 @@ function test_sbc() {
test("Test subtraction of two single digit 16-bit numbers with decimal "+ test("Test subtraction of two single digit 16-bit numbers with decimal "+
"mode set.", function() { "mode set.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220f8a9050038e90200"); cpu.load_binary("18fbc220f8a9050038e90200", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x03, "The accumulator should be 0x03 after subtracting "+ equals(cpu.r.a, 0x03, "The accumulator should be 0x03 after subtracting "+
"0x02 from 0x05 with decimal and 16-bit "+ "0x02 from 0x05 with decimal and 16-bit "+
"memory/accumulator modes."); "memory/accumulator modes.");
@ -571,7 +613,8 @@ function test_sbc() {
test("Test subtraction of two four digit 16-bit numbers with decimal "+ test("Test subtraction of two four digit 16-bit numbers with decimal "+
"mode set.", function() { "mode set.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220f8a9999938e91111"); cpu.load_binary("18fbc220f8a9999938e91111", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x8888, "The accumulator should be 0x8888 after "+ equals(cpu.r.a, 0x8888, "The accumulator should be 0x8888 after "+
"subtracting 0x1111 from 0x9999 with decimal "+ "subtracting 0x1111 from 0x9999 with decimal "+
"and 16-bit memory/accumulator modes."); "and 16-bit memory/accumulator modes.");
@ -585,7 +628,8 @@ function test_sbc() {
test("Test subtraction of two four digit 16-bit numbers with decimal "+ test("Test subtraction of two four digit 16-bit numbers with decimal "+
"mode set that causes a borrow.", function() { "mode set that causes a borrow.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc220f8a9111138e99999"); cpu.load_binary("18fbc220f8a9111138e99999", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x1112, "The accumulator should be 0x1112 after "+ equals(cpu.r.a, 0x1112, "The accumulator should be 0x1112 after "+
"subtracting 0x9999 from 0x1111 with decimal "+ "subtracting 0x9999 from 0x1111 with decimal "+
"and 16-bit memory/accumulator modes."); "and 16-bit memory/accumulator modes.");
@ -603,7 +647,8 @@ function test_adc() {
test("Test normal addition of two 16-bit numbers that don't cause an "+ test("Test normal addition of two 16-bit numbers that don't cause an "+
"overflow (m bit is 0)", function() { "overflow (m bit is 0)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18c230a90100690100"); cpu.load_binary("18fb18c230a90100690100", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 2, "0x0001 + 0x0001 should result in 0x0002 when using "+ equals(cpu.r.a, 2, "0x0001 + 0x0001 should result in 0x0002 when using "+
"ADC"); "ADC");
equals(cpu.p.n, 0, "0x0001 + 0x0001 does not result in a negative "+ equals(cpu.p.n, 0, "0x0001 + 0x0001 does not result in a negative "+
@ -618,7 +663,8 @@ function test_adc() {
test("Test normal addition of two 8-bit numbers that don't cause an "+ test("Test normal addition of two 8-bit numbers that don't cause an "+
"overflow (m bit is 1)", function() { "overflow (m bit is 1)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18e230a9016901"); cpu.load_binary("18fb18e230a9016901", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 2, "0x01 + 0x01 should result in 0x02 when using "+ equals(cpu.r.a, 2, "0x01 + 0x01 should result in 0x02 when using "+
"ADC"); "ADC");
equals(cpu.p.n, 0, "0x01 + 0x01 does not result in a negative "+ equals(cpu.p.n, 0, "0x01 + 0x01 does not result in a negative "+
@ -634,7 +680,8 @@ function test_adc() {
test("Test that overflow sets the carry flag and works in general with two"+ test("Test that overflow sets the carry flag and works in general with two"+
"16-bit numbers (m bit is 0)", function() { "16-bit numbers (m bit is 0)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18c230a9ffff690100"); cpu.load_binary("18fb18c230a9ffff690100", 0x8000);
cpu.execute(0x8000);
equals(cpu.p.c, 1, "0xffff + 0x0001 should set the carry bit when using "+ equals(cpu.p.c, 1, "0xffff + 0x0001 should set the carry bit when using "+
"ADC"); "ADC");
equals(cpu.r.a, 0, "0xffff + 0x0001 should result in the accumulator "+ equals(cpu.r.a, 0, "0xffff + 0x0001 should result in the accumulator "+
@ -650,7 +697,8 @@ function test_adc() {
test("Test that overflow sets the carry flag and works in general with two"+ test("Test that overflow sets the carry flag and works in general with two"+
"8-bit numbers (m bit is 1)", function() { "8-bit numbers (m bit is 1)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18e230a9ff6901"); cpu.load_binary("18fb18e230a9ff6901", 0x8000);
cpu.execute(0x8000);
equals(cpu.p.c, 1, "0xff + 0x01 should set the carry bit when using "+ equals(cpu.p.c, 1, "0xff + 0x01 should set the carry bit when using "+
"ADC"); "ADC");
equals(cpu.r.a, 0, "0xff + 0x01 should result in the accumulator "+ equals(cpu.r.a, 0, "0xff + 0x01 should result in the accumulator "+
@ -665,7 +713,8 @@ function test_adc() {
test("Test signed overflow with two 8-bit numbers (m bit is 1)", function() { test("Test signed overflow with two 8-bit numbers (m bit is 1)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18e230a97f6901"); cpu.load_binary("18fb18e230a97f6901", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x80, "0x7f + 0x01 should result in 0x80 when "+ equals(cpu.r.a, 0x80, "0x7f + 0x01 should result in 0x80 when "+
"using ADC"); "using ADC");
equals(cpu.p.v, 1, "0x7f + 0x01 should set the overflow(v) bit when "+ equals(cpu.p.v, 1, "0x7f + 0x01 should set the overflow(v) bit when "+
@ -679,7 +728,8 @@ function test_adc() {
}); });
test("Test signed overflow with two 16-bit numbers (m bit is 0)", function() { test("Test signed overflow with two 16-bit numbers (m bit is 0)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18c230a9ff7f690100"); cpu.load_binary("18fb18c230a9ff7f690100", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x8000, "0x7fff + 0x0001 should result in 0x8000 when "+ equals(cpu.r.a, 0x8000, "0x7fff + 0x0001 should result in 0x8000 when "+
"using ADC"); "using ADC");
equals(cpu.p.v, 1, "0x7fff + 0x0001 should set the overflow(v) bit when "+ equals(cpu.p.v, 1, "0x7fff + 0x0001 should set the overflow(v) bit when "+
@ -694,7 +744,8 @@ function test_adc() {
test("Test ADC direct page with 8-bit numbers (m bit is 1)", function() { test("Test ADC direct page with 8-bit numbers (m bit is 1)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18e230a90185ffa97f65ff"); cpu.load_binary("18fb18e230a90185ffa97f65ff", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x80, "0x7f + 0x01 should result in 0x80 when "+ equals(cpu.r.a, 0x80, "0x7f + 0x01 should result in 0x80 when "+
"using ADC"); "using ADC");
equals(cpu.p.v, 1, "0x7f + 0x01 should set the overflow(v) bit when "+ equals(cpu.p.v, 1, "0x7f + 0x01 should set the overflow(v) bit when "+
@ -709,7 +760,8 @@ function test_adc() {
test("Test ADC direct page with 16-bit numbers (m bit is 0)", function() { test("Test ADC direct page with 16-bit numbers (m bit is 0)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18c230a9010085fea9ff7f65fe"); cpu.load_binary("18fb18c230a9010085fea9ff7f65fe", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x8000, "0x7fff + 0x0001 should result in 0x8000 when "+ equals(cpu.r.a, 0x8000, "0x7fff + 0x0001 should result in 0x8000 when "+
"using ADC"); "using ADC");
equals(cpu.p.v, 1, "0x7fff + 0x0001 should set the overflow(v) bit when "+ equals(cpu.p.v, 1, "0x7fff + 0x0001 should set the overflow(v) bit when "+
@ -724,7 +776,8 @@ function test_adc() {
test("Test ADC absolute with 8-bit numbers (m bit is 1)", function() { test("Test ADC absolute with 8-bit numbers (m bit is 1)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18e230a9018dffffa97f6dffff"); cpu.load_binary("18fb18e230a9018dffffa97f6dffff", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x80, "0x7f + 0x01 should result in 0x80 when "+ equals(cpu.r.a, 0x80, "0x7f + 0x01 should result in 0x80 when "+
"using ADC"); "using ADC");
equals(cpu.p.v, 1, "0x7f + 0x01 should set the overflow(v) bit when "+ equals(cpu.p.v, 1, "0x7f + 0x01 should set the overflow(v) bit when "+
@ -739,7 +792,8 @@ function test_adc() {
test("Test ADC absolute with 16-bit numbers (m bit is 0)", function() { test("Test ADC absolute with 16-bit numbers (m bit is 0)", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18c230a901008dffffa9ff7f6dffff"); cpu.load_binary("18fb18c230a901008dffffa9ff7f6dffff", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x8000, "0x7fff + 0x0001 should result in 0x8000 when "+ equals(cpu.r.a, 0x8000, "0x7fff + 0x0001 should result in 0x8000 when "+
"using ADC"); "using ADC");
equals(cpu.p.v, 1, "0x7fff + 0x0001 should set the overflow(v) bit when "+ equals(cpu.p.v, 1, "0x7fff + 0x0001 should set the overflow(v) bit when "+
@ -755,7 +809,8 @@ function test_adc() {
test("Test ADC direct page indirect with 8-bit numbers (m bit is 1)", test("Test ADC direct page indirect with 8-bit numbers (m bit is 1)",
function() { function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18e230a90185ffa9ff85fd64fea97f72fd"); cpu.load_binary("18fb18e230a90185ffa9ff85fd64fea97f72fd", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x80, "0x7f + 0x01 should result in 0x80 when "+ equals(cpu.r.a, 0x80, "0x7f + 0x01 should result in 0x80 when "+
"using ADC"); "using ADC");
equals(cpu.p.v, 1, "0x7f + 0x01 should set the overflow(v) bit when "+ equals(cpu.p.v, 1, "0x7f + 0x01 should set the overflow(v) bit when "+
@ -770,7 +825,8 @@ function test_adc() {
test("Test ADC direct page indirect with 16-bit numbers (m bit is 0)", test("Test ADC direct page indirect with 16-bit numbers (m bit is 0)",
function() { function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18c230a901008500a9000085bba9ff7f72bb"); cpu.load_binary("18fb18c230a901008500a9000085bba9ff7f72bb", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x8000, "0x7fff + 0x0001 should result in 0x8000 when "+ equals(cpu.r.a, 0x8000, "0x7fff + 0x0001 should result in 0x8000 when "+
"using ADC"); "using ADC");
equals(cpu.p.v, 1, "0x7fff + 0x0001 should set the overflow(v) bit when "+ equals(cpu.p.v, 1, "0x7fff + 0x0001 should set the overflow(v) bit when "+
@ -786,7 +842,8 @@ function test_adc() {
test("Test that ADC handles decimal mode with legal BCD numbers in 8-bit "+ test("Test that ADC handles decimal mode with legal BCD numbers in 8-bit "+
"memory/accumulator mode with single digit numbers.", function() { "memory/accumulator mode with single digit numbers.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18f8a9056905"); cpu.load_binary("18fb18f8a9056905", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x10, "0x05 + 0x05 should result in 0x10 with decimal "+ equals(cpu.r.a, 0x10, "0x05 + 0x05 should result in 0x10 with decimal "+
"mode on and with 8-bit memory/accumulator mode."); "mode on and with 8-bit memory/accumulator mode.");
equals(cpu.p.c, 0, "The carry flag of the p status register should be "+ equals(cpu.p.c, 0, "The carry flag of the p status register should be "+
@ -801,7 +858,8 @@ function test_adc() {
test("Test that ADC handles decimal mode with legal BCD numbers in 8-bit "+ test("Test that ADC handles decimal mode with legal BCD numbers in 8-bit "+
"memory/accumulator mode with double digit numbers.", function() { "memory/accumulator mode with double digit numbers.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18f8a9156926"); cpu.load_binary("18fb18f8a9156926", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x41, "0x15 + 0x26 should result in 0x41 with decimal "+ equals(cpu.r.a, 0x41, "0x15 + 0x26 should result in 0x41 with decimal "+
"mode on and with 8-bit memory/accumulator mode."); "mode on and with 8-bit memory/accumulator mode.");
equals(cpu.p.c, 0, "The carry flag of the p status register should be "+ equals(cpu.p.c, 0, "The carry flag of the p status register should be "+
@ -817,7 +875,8 @@ function test_adc() {
"memory/accumulator mode with double digit numbers with the carry "+ "memory/accumulator mode with double digit numbers with the carry "+
"bit set", function() { "bit set", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb38f8a9156926"); cpu.load_binary("18fb38f8a9156926", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x42, "0x15 + 0x26 should result in 0x42 with decimal "+ equals(cpu.r.a, 0x42, "0x15 + 0x26 should result in 0x42 with decimal "+
"mode on and with 8-bit memory/accumulator mode "+ "mode on and with 8-bit memory/accumulator mode "+
"and the carry bit set."); "and the carry bit set.");
@ -834,7 +893,8 @@ function test_adc() {
"memory/accumulator mode when adding two numbers that cause an "+ "memory/accumulator mode when adding two numbers that cause an "+
"overflow.", function() { "overflow.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18f8a9556960"); cpu.load_binary("18fb18f8a9556960", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x16, "0x55 + 0x60 should result in 0x16 with decimal "+ equals(cpu.r.a, 0x16, "0x55 + 0x60 should result in 0x16 with decimal "+
"mode on and with 8-bit memory/accumulator mode."); "mode on and with 8-bit memory/accumulator mode.");
equals(cpu.p.c, 1, "The carry flag of the p status register should be "+ equals(cpu.p.c, 1, "The carry flag of the p status register should be "+
@ -850,7 +910,8 @@ function test_adc() {
"memory/accumulator mode when adding two single digit numbers.", "memory/accumulator mode when adding two single digit numbers.",
function() { function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18f8c220a90100690900"); cpu.load_binary("18fb18f8c220a90100690900", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x10, "0x0001 + 0x0009 should result in 0x0010 with "+ equals(cpu.r.a, 0x10, "0x0001 + 0x0009 should result in 0x0010 with "+
"decimal mode on and with 16-bit "+ "decimal mode on and with 16-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -867,7 +928,8 @@ function test_adc() {
"memory/accumulator mode when adding two four digit numbers.", "memory/accumulator mode when adding two four digit numbers.",
function() { function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18f8c220a90110699939"); cpu.load_binary("18fb18f8c220a90110699939", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x5000, "0x1001 + 0x3999 should result in 0x5000 with "+ equals(cpu.r.a, 0x5000, "0x1001 + 0x3999 should result in 0x5000 with "+
"decimal mode on and with 16-bit "+ "decimal mode on and with 16-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -884,7 +946,8 @@ function test_adc() {
"memory/accumulator mode when adding two numbers that cause an "+ "memory/accumulator mode when adding two numbers that cause an "+
"overflow.", function() { "overflow.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb18f8c220a99756699999"); cpu.load_binary("18fb18f8c220a99756699999", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x5697, "0x5697 + 0x9999 should result in 0x5697 with "+ equals(cpu.r.a, 0x5697, "0x5697 + 0x9999 should result in 0x5697 with "+
"decimal mode on and with 16-bit "+ "decimal mode on and with 16-bit "+
"memory/accumulator mode."); "memory/accumulator mode.");
@ -901,7 +964,8 @@ function test_adc() {
"memory/accumulator mode when adding two four digit numbers with the "+ "memory/accumulator mode when adding two four digit numbers with the "+
"carry bit set.", function() { "carry bit set.", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fb38f8c220a90110699939"); cpu.load_binary("18fb38f8c220a90110699939", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x5001, "0x1001 + 0x3999 should result in 0x5001 with "+ equals(cpu.r.a, 0x5001, "0x1001 + 0x3999 should result in 0x5001 with "+
"decimal mode on and with 16-bit "+ "decimal mode on and with 16-bit "+
"memory/accumulator mode and the carry flag set."); "memory/accumulator mode and the carry flag set.");
@ -921,9 +985,8 @@ function test_branching() {
test("Test that BRA with 0x00 as its argument doesn't increment or "+ test("Test that BRA with 0x00 as its argument doesn't increment or "+
"decrement the program counter", function() { "decrement the program counter", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("8000"); cpu.load_binary("8000", 0x8000);
// NOTE: 0x8003 is subject to change however I decide to lay out memory cpu.execute(0x8000);
// eventually.
equals(cpu.r.pc, 0x8003, "Make sure that the program counter isn't "+ equals(cpu.r.pc, 0x8003, "Make sure that the program counter isn't "+
"incremented or decremented if BRA is given "+ "incremented or decremented if BRA is given "+
"0x00 as its argument."); "0x00 as its argument.");
@ -932,12 +995,16 @@ function test_branching() {
test("Check that the branching operations properly treat the argument as "+ test("Check that the branching operations properly treat the argument as "+
"a two's complement number", function() { "a two's complement number", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("80f0"); // negative two's complement number 0xf0 = -16 // negative two's complement number 0xf0 = -16
cpu.load_binary("80f0", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.pc, (0x8003-16), "A branching operation when given a "+ equals(cpu.r.pc, (0x8003-16), "A branching operation when given a "+
"negative two's complement number should "+ "negative two's complement number should "+
"decrement the program counter by the "+ "decrement the program counter by the "+
"proper amount."); "proper amount.");
cpu.execute("8020"); // positive two's complement number. cpu.reset();
cpu.load_binary("8020", 0x8000); // positive two's complement number.
cpu.execute(0x8000);
equals(cpu.r.pc, (0x8003+0x20), "A branching operation when given a "+ equals(cpu.r.pc, (0x8003+0x20), "A branching operation when given a "+
"positive two's complement number should "+ "positive two's complement number should "+
"increment the program counter by the "+ "increment the program counter by the "+
@ -946,14 +1013,16 @@ function test_branching() {
test("Check that BPL works as expected", function() { test("Check that BPL works as expected", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc230a9fe7f1a10fd"); cpu.load_binary("18fbc230a9fe7f1a10fd", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x8000, "Check that branching only occurs while the "+ equals(cpu.r.a, 0x8000, "Check that branching only occurs while the "+
"number is a two's complement positive number."); "number is a two's complement positive number.");
}); });
test("Check that BMI works as expected", function() { test("Check that BMI works as expected", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.execute("18fbc230a901803a30fd"); cpu.load_binary("18fbc230a901803a30fd", 0x8000);
cpu.execute(0x8000);
equals(cpu.r.a, 0x7fff, "Check that branching only occurs while the "+ equals(cpu.r.a, 0x7fff, "Check that branching only occurs while the "+
"number is a two's complement negative number."); "number is a two's complement negative number.");
}); });
@ -964,7 +1033,8 @@ function test_sep() {
test("Test 'SEP #$30' not in emulation mode", function() { test("Test 'SEP #$30' not in emulation mode", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.p.e = 0; cpu.p.e = 0;
cpu.execute("e230"); cpu.load_binary("e230", 0x8000);
cpu.execute(0x8000);
equals(cpu.p.m, 1, "'SEP #$30' should set the m status bit of the p "+ equals(cpu.p.m, 1, "'SEP #$30' should set the m status bit of the p "+
"register to 1"); "register to 1");
equals(cpu.p.x, 1, "'SEP #$30' should set the x status bit of the p "+ equals(cpu.p.x, 1, "'SEP #$30' should set the x status bit of the p "+
@ -985,7 +1055,8 @@ function test_sep() {
test("Test 'SEP #$cf' not in emulation mode", function() { test("Test 'SEP #$cf' not in emulation mode", function() {
var cpu = new CPU_65816(); var cpu = new CPU_65816();
cpu.p.e = 0; cpu.p.e = 0;
cpu.execute("e2cf"); cpu.load_binary("e2cf", 0x8000);
cpu.execute(0x8000);
equals(cpu.p.m, 0, "'SEP #$cf' should not set the m status bit of the p "+ equals(cpu.p.m, 0, "'SEP #$cf' should not set the m status bit of the p "+
"register to 1"); "register to 1");
equals(cpu.p.x, 0, "'SEP #$cf' should not set the x status bit of the p "+ equals(cpu.p.x, 0, "'SEP #$cf' should not set the x status bit of the p "+
@ -1019,7 +1090,8 @@ function test_rep() {
cpu.p.x = 1; cpu.p.x = 1;
cpu.p.m = 1; cpu.p.m = 1;
cpu.p.z = 1; cpu.p.z = 1;
cpu.execute("c230"); cpu.load_binary("c230", 0x8000);
cpu.execute(0x8000);
equals(cpu.p.m, 0, "'REP #$30' should clear the m bit of the p status "+ equals(cpu.p.m, 0, "'REP #$30' should clear the m bit of the p status "+
"register"); "register");
equals(cpu.p.x, 0, "'REP #$30' should clear the x bit of the p status "+ equals(cpu.p.x, 0, "'REP #$30' should clear the x bit of the p status "+
@ -1050,7 +1122,8 @@ function test_rep() {
cpu.p.x = 1; cpu.p.x = 1;
cpu.p.m = 1; cpu.p.m = 1;
cpu.p.z = 1; cpu.p.z = 1;
cpu.execute("c2cf"); cpu.load_binary("c2cf", 0x8000);
cpu.execute(0x8000);
equals(cpu.p.m, 1, "'REP #$cf' should not clear the m bit of the p "+ equals(cpu.p.m, 1, "'REP #$cf' should not clear the m bit of the p "+
"status register"); "status register");
equals(cpu.p.x, 1, "'REP #$cf' should not clear the x bit of the p "+ equals(cpu.p.x, 1, "'REP #$cf' should not clear the x bit of the p "+