diff --git a/cpu.js b/cpu.js index c420178..6f6c7db 100644 --- a/cpu.js +++ b/cpu.js @@ -84,7 +84,7 @@ function CPU_65816() { 0x65 : ADC_direct_page, 0x72 : ADC_direct_page_indirect, 0x7d : ADC_absolute_indexed_x, 0x79 : ADC_absolute_indexed_y, - 0x75 : ADC_direct_page_indexed_x }; + 0x75 : ADC_direct_page_indexed_x, 0xe9 : SBC_const }; /** * Take a raw hex string representing the program and execute it. @@ -163,6 +163,63 @@ var MMU = { } }; +var SBC_const = { + bytes_required:function(cpu) { + if(cpu.p.m) { + return 2; + } else { + return 3; + } + }, + execute:function(cpu, bytes) { + var old_a = cpu.r.a; + if(cpu.p.m) { + cpu.r.a -= bytes[0] - cpu.p.c; + if(cpu.r.a < 0) { + cpu.p.c = 1; + cpu.r.a = 0x100 + cpu.r.a; + } else { + cpu.p.c = 0; + } + cpu.p.n = cpu.r.a >> 7; + + // Check for signed overflow. + // If they started with the same sign and then the resulting sign is + // different then we have a signed overflow. + if((!((old_a ^ bytes[0]) & 0x80)) && ((cpu.r.a ^ old_a) & 0x80)) { + cpu.p.v = 1; + } else { + cpu.p.v = 0; + } + } else { + var argument = (bytes[1]<<8)|bytes[0]; + cpu.r.a -= argument - cpu.p.c; + if(cpu.r.a < 0) { + cpu.p.c = 1; + cpu.r.a = 0x10000 + cpu.r.a; + } else { + cpu.p.c = 0; + } + cpu.p.n = cpu.r.a >> 15; + + // Check for signed overflow. + // If they started with the same sign and then the resulting sign is + // different then we have a signed overflow. + if((!((old_a ^ argument) & 0x8000)) && ((cpu.r.a ^ old_a) & 0x8000)) { + cpu.p.v = 1; + } else { + cpu.p.v = 0; + } + } + + if(cpu.r.a===0) { + cpu.p.z = 1; + } else { + cpu.p.z = 0; + } + } +}; + var ADC_const = { bytes_required:function(cpu) { if(cpu.p.m) { @@ -172,8 +229,8 @@ var ADC_const = { } }, execute:function(cpu, bytes) { + var old_a = cpu.r.a; if(cpu.p.m) { - var old_a = cpu.r.a; cpu.r.a += bytes[0] + cpu.p.c; if(cpu.r.a & 0x100) { cpu.p.c = 1; @@ -192,7 +249,6 @@ var ADC_const = { cpu.p.v = 0; } } else { - var old_a = cpu.r.a; var argument = (bytes[1]<<8)|bytes[0]; cpu.r.a += argument + cpu.p.c; if(cpu.r.a & 0x10000) { @@ -272,7 +328,7 @@ var ADC_direct_page_indirect = { } }; -ADC_absolute_indexed_x = { +var ADC_absolute_indexed_x = { bytes_required:function() { return 3; }, @@ -281,7 +337,7 @@ ADC_absolute_indexed_x = { } }; -ADC_absolute_indexed_y = { +var ADC_absolute_indexed_y = { bytes_required:function() { return 3; }, @@ -290,7 +346,7 @@ ADC_absolute_indexed_y = { } }; -ADC_direct_page_indexed_x = { +var ADC_direct_page_indexed_x = { bytes_required:function() { return 2; }, diff --git a/test/tests.js b/test/tests.js index c6e7ab6..048330b 100644 --- a/test/tests.js +++ b/test/tests.js @@ -19,6 +19,72 @@ function run_tests() { test_sep(); test_branching(); test_adc(); + test_sbc(); +} + +function test_sbc() { + module("SBC"); + test("Test normal subtraction of two 8-bit numbers that don't cause a "+ + "borrow.", function() { + var cpu = new CPU_65816(); + cpu.execute("18fbe23018a901e901"); + equals(cpu.r.a, 0, "0x01 - 0x01 should result in zero when using "+ + "SBC"); + equals(cpu.p.z, 1, "0x01 - 0x01 should set the zero(z) bit when "+ + "using SBC"); + equals(cpu.p.n, 0, "0x01 - 0x01 should not set the negative(n) bit "+ + "when using SBC"); + equals(cpu.p.v, 0, "0x01 - 0x01 should not set the overflow(v) bit "+ + "when using SBC"); + equals(cpu.p.c, 0, "0x01 - 0x01 should not set the carry(c) bit when "+ + "using SBC"); + }); + + test("Test normal subtraction of two 16-bit numbers that don't cause a "+ + "borrow.", function() { + var cpu = new CPU_65816(); + cpu.execute("18fbc23018a90100e90100"); + equals(cpu.r.a, 0, "0x0001 - 0x0001 should result in zero when using "+ + "SBC"); + equals(cpu.p.z, 1, "0x0001 - 0x0001 should set the zero(z) bit when "+ + "using SBC"); + equals(cpu.p.n, 0, "0x0001 - 0x0001 should not set the negative(n) bit "+ + "when using SBC"); + equals(cpu.p.v, 0, "0x0001 - 0x0001 should not set the overflow(v) bit "+ + "when using SBC"); + equals(cpu.p.c, 0, "0x0001 - 0x0001 should not set the carry(c) bit "+ + "when using SBC"); + }); + test("Test subtraction that triggers a borrow with 8-bit numbers", + function() { + var cpu = new CPU_65816(); + cpu.execute("18fbe23018a9d0e9ef"); + equals(cpu.r.a, 0xe1, "0xd0 - 0xef should set the accumulator to 0xe1 "+ + "when using SBC"); + equals(cpu.p.n, 1, "0xd0 - 0xef should set the negative(n) bit when "+ + "using SBC"); + equals(cpu.p.v, 0, "0xd0 - 0xef should not set the overflow(v) bit "+ + "when using SBC"); + equals(cpu.p.z, 0, "0xd0 - 0xef should not set the zero(z) bit when "+ + "using SBC"); + equals(cpu.p.c, 1, "0xd0 - 0xef should set the carry(c) bit when "+ + "using SBC"); + }); + test("Test subtraction that triggers a borrow with 16-bit numbers", + function() { + var cpu = new CPU_65816(); + cpu.execute("18fbc23018a900d0e900ef"); + equals(cpu.r.a, 0xe100, "0xd000 - 0xef00 should set the accumulator to "+ + "0xe0ff when using SBC"); + equals(cpu.p.n, 1, "0xd000 - 0xef00 should set the negative(n) bit when "+ + "using SBC"); + equals(cpu.p.v, 0, "0xd000 - 0xef00 should not set the overflow(v) bit "+ + "when using SBC"); + equals(cpu.p.z, 0, "0xd000 - 0xef00 should not set the zero(z) bit when "+ + "using SBC"); + equals(cpu.p.c, 1, "0xd000 - 0xef00 should set the carry(c) bit when "+ + "using SBC"); + }); } function test_adc() {