added decimal mode support for SBC, wrote unit tests to verify that support and updated the TODO

This commit is contained in:
Preston Skupinski 2011-09-04 11:34:09 -04:00
parent b505f7a50d
commit d902611e9c
3 changed files with 187 additions and 40 deletions

8
TODO
View File

@ -3,14 +3,14 @@ Testing:
- More tests for CMP/CPY/CPX operations
- Tests needed for JMP operations
- Tests needed for LD* and ST* operations
- Tests needed for bank/page wrapping
- Tests needed for IN* and DE* operations
- Tests needed for T** transfer operations
- Tests needed for interrupt support
- Tests needed for the numerous other operations added
CPU:
- More work on interrupts
- Decimal mode support(figure out details as to how it handles illegal BCD
numbers)
- Figure out the exact details of how the 65816 handles illegal BCD numbers
when decimal mode is set
- Have each operation return the number of cycles used by the execute function.
- Optimization
Memory:
@ -18,8 +18,6 @@ Memory:
settings
- Page wrapping or not wrapping for certain addressing modes and with certain
settings
- ROM protection
- Improve the memory mapped I/O interface and handling
Display:
- Add the ability to step, pause and stop execution
- Ability to view the path of operation execution as it executes, like have

127
cpu.js
View File

@ -3227,44 +3227,109 @@ var SBC_const = {
},
execute:function(cpu, bytes) {
var old_a = cpu.r.a;
if(cpu.p.e|cpu.p.m) {
cpu.r.a -= bytes[0] - cpu.p.c;
if(cpu.r.a < 0) {
cpu.p.c = 0;
cpu.r.a = 0x100 + cpu.r.a;
} else {
cpu.p.c = 1;
}
cpu.p.n = cpu.r.a >> 7;
var temp = 0;
if(cpu.p.c===0)
temp = 1;
// 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;
if(cpu.p.e|cpu.p.m) {
if(cpu.p.d) {
// Form a decimal number out of a.
var ones = cpu.r.a & 0x0f;
var tens = cpu.r.a >> 4;
var dec_a = (tens*10)+ones;
// Form a decimal number out of the argument.
ones = bytes[0] & 0x0f;
tens = bytes[0] >> 4;
var dec_arg = (tens*10)+ones;
var result = dec_a - dec_arg - temp;
// Check for decimal overflow.
if(result<0) {
result += 100;
cpu.p.c = 0;
} else {
cpu.p.c = 1;
}
var digits = result.toString(10).split("");
var i = 0;
cpu.r.a = 0;
for(i=0;i<digits.length;i++) {
cpu.r.a += (digits[i]-0)*Math.pow(16,digits.length-i-1);
}
} else {
cpu.p.v = 0;
cpu.r.a -= bytes[0] - temp;
if(cpu.r.a < 0) {
cpu.p.c = 0;
cpu.r.a = 0x100 + cpu.r.a;
} else {
cpu.p.c = 1;
}
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 = 0;
cpu.r.a = 0x10000 + cpu.r.a;
} else {
cpu.p.c = 1;
}
cpu.p.n = cpu.r.a >> 15;
var temp = 0;
if(cpu.p.c===0)
temp = 1;
// 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;
if(cpu.p.d) {
// Form a decimal number out of a.
var ones = cpu.r.a & 0xf;
var tens = (cpu.r.a >>4) & 0xf;
var hundreds = (cpu.r.a >> 8) & 0xf;
var thousands = (cpu.r.a >> 12) & 0xf;
var dec_a = (thousands*1000)+(hundreds*100)+(tens*10)+ones;
// Form a decimal number out of the argument.
ones = argument & 0xf;
tens = (argument >> 4) & 0xf;
hundreds = (argument >> 8) & 0xf;
thousands = (argument >> 12) & 0xf;
var dec_arg = (thousands*1000)+(hundreds*100)+(tens*10)+ones;
var result = dec_a - dec_arg - temp;
// Check for decimal overflow.
if(result<0) {
result += 10000;
cpu.p.c = 0;
} else {
cpu.p.c = 1;
}
var digits = result.toString(10).split("");
var i = 0;
cpu.r.a = 0;
for(i=0;i<digits.length;i++) {
cpu.r.a += (digits[i]-0)*Math.pow(16,digits.length-i-1);
}
} else {
cpu.p.v = 0;
}
}
cpu.r.a -= argument - temp;
if(cpu.r.a < 0) {
cpu.p.c = 0;
cpu.r.a = 0x10000 + cpu.r.a;
} else {
cpu.p.c = 1;
}
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;

View File

@ -373,7 +373,7 @@ function test_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");
cpu.execute("18fbe230a90138e901");
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 "+
@ -389,7 +389,7 @@ function test_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");
cpu.execute("18fbc230a9010038e90100");
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 "+
@ -404,7 +404,7 @@ function test_sbc() {
test("Test subtraction that triggers a borrow with 8-bit numbers",
function() {
var cpu = new CPU_65816();
cpu.execute("18fbe23018a9d0e9ef");
cpu.execute("18fbe230a9d038e9ef");
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 "+
@ -419,7 +419,7 @@ function test_sbc() {
test("Test subtraction that triggers a borrow with 16-bit numbers",
function() {
var cpu = new CPU_65816();
cpu.execute("18fbc23018a900d0e900ef");
cpu.execute("18fbc230a900d038e900ef");
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 "+
@ -431,6 +431,90 @@ function test_sbc() {
equals(cpu.p.c, 0, "0xd000 - 0xef00 should not set the carry(c) bit when "+
"using SBC");
});
test("Test subtraction with decimal mode on with two single digit 8-bit "+
"numbers.", function() {
var cpu = new CPU_65816();
cpu.execute("18fbf8a90938e905");
equals(cpu.r.a, 4, "The accumulator should be 4 after subtracting 0x5 "+
"0x9 with decimal mode on with 8-bit "+
"memory/accumulator mode.");
equals(cpu.p.c, 1, "The carry bit should be set after no borrow is "+
"triggered.");
equals(cpu.p.m, 1, "The m flag of the p status register should be one "+
"for 8-bit memory/accumulator mode.");
equals(cpu.p.e, 0, "The hidden e flag of the p status register should "+
"be zero for native mode.");
});
test("Test subtraction with decimal mode on with two double digit 8-bit "+
"numbers.", function() {
var cpu = new CPU_65816();
cpu.execute("18fbf8a99038e949");
equals(cpu.r.a, 0x41, "The accumulator should be 41 after subtracting 0x49 "+
"from 0x90 with decimal mode on with 8-bit "+
"memory/accumulator mode.");
equals(cpu.p.c, 1, "The carry bit should be set after no borrow is "+
"triggered.");
equals(cpu.p.m, 1, "The m flag of the p status register should be one "+
"for 8-bit memory/accumulator mode.");
equals(cpu.p.e, 0, "The hidden e flag of the p status register should "+
"be zero for native mode.");
});
test("Test subtraction with decimal mode on with 8-bit numbers that causes "+
"a borrow.", function() {
var cpu = new CPU_65816();
cpu.execute("18fbf8a91038e920");
equals(cpu.r.a, 0x90, "The accumulator should be 0x90 after subtracting "+
"0x20 from 0x10 with decimal and 8-bit "+
"memory/accumulator modes.");
equals(cpu.p.c, 0, "The carry bit should be clear after a borrow is "+
"triggered.");
equals(cpu.p.m, 1, "The m flag of the p status register should be one "+
"for 8-bit memory/accumulator mode.");
equals(cpu.p.e, 0, "The hidden e flag of the p status register should "+
"be zero for native mode.");
});
test("Test subtraction of two single digit 16-bit numbers with decimal "+
"mode set.", function() {
var cpu = new CPU_65816();
cpu.execute("18fbc220f8a9050038e90200");
equals(cpu.r.a, 0x03, "The accumulator should be 0x03 after subtracting "+
"0x02 from 0x05 with decimal and 16-bit "+
"memory/accumulator modes.");
equals(cpu.p.c, 1, "The carry bit should be set after no borrow is "+
"triggered.");
equals(cpu.p.m, 0, "The m flag of the p status register should be zero "+
"for 16-bit memory/accumulator mode.");
equals(cpu.p.e, 0, "The hidden e flag of the p status register should "+
"be zero for native mode.");
});
test("Test subtraction of two four digit 16-bit numbers with decimal "+
"mode set.", function() {
var cpu = new CPU_65816();
cpu.execute("18fbc220f8a9999938e91111");
equals(cpu.r.a, 0x8888, "The accumulator should be 0x8888 after "+
"subtracting 0x1111 from 0x9999 with decimal "+
"and 16-bit memory/accumulator modes.");
equals(cpu.p.c, 1, "The carry bit should be set after no borrow is "+
"triggered.");
equals(cpu.p.m, 0, "The m flag of the p status register should be zero "+
"for 16-bit memory/accumulator mode.");
equals(cpu.p.e, 0, "The hidden e flag of the p status register should "+
"be zero for native mode.");
});
test("Test subtraction of two four digit 16-bit numbers with decimal "+
"mode set that causes a borrow.", function() {
var cpu = new CPU_65816();
cpu.execute("18fbc220f8a9111138e99999");
equals(cpu.r.a, 0x1112, "The accumulator should be 0x1112 after "+
"subtracting 0x9999 from 0x1111 with decimal "+
"and 16-bit memory/accumulator modes.");
equals(cpu.p.c, 0, "The carry bit should be clear after a borrow is "+
"triggered.");
equals(cpu.p.m, 0, "The m flag of the p status register should be zero "+
"for 16-bit memory/accumulator mode.");
equals(cpu.p.e, 0, "The hidden e flag of the p status register should "+
"be zero for native mode.");
});
}
function test_adc() {