mirror of
https://github.com/sethm/symon.git
synced 2024-06-29 00:29:44 +00:00
Bug Fixes and Copyright Date Change
The simulator now passes Klaus Dormann's 6502 Functional Test suite for the first time. Bug Fixes: - PHP was not correctly setting the Break bit on the stack copy of the processor status, so subsequent PLA's would not set the Break status flag. - The CPU had swapped NMI and IRQ reset vectors, so RTI was failing. - BRK was pushing PC + 2 onto the stack, instead of PC + 1 - (Zero Page,X) addressing mode did not correctly wrap on zero page boundaries. - The instruction table used for disassembly had addressing modes of LDA $B9 and $BD reversed. This did not affect behavior, only disassembly of these instructions. Other: - Updated copyright date for 2013. - Started migrating old JUnit 3 style tests to JUnit 4 annotations.
This commit is contained in:
parent
92b61e4839
commit
da8250778e
28
README.md
28
README.md
|
@ -4,11 +4,11 @@ SYMON - A 6502 System Simulator
|
||||||
**NOTE: THIS IS BETA QUALITY SOFTWARE UNDER ACTIVE DEVELOPMENT. Feedback is
|
**NOTE: THIS IS BETA QUALITY SOFTWARE UNDER ACTIVE DEVELOPMENT. Feedback is
|
||||||
welcome!**
|
welcome!**
|
||||||
|
|
||||||
**Version:** 0.8.1
|
**Version:** 0.8.2
|
||||||
|
|
||||||
**Last Updated:** 30 December, 2012
|
**Last Updated:** 01 January, 2013
|
||||||
|
|
||||||
Copyright (c) 2008-2012 Seth J. Morabito <web@loomcom.com>
|
Copyright (c) 2008-2013 Seth J. Morabito <web@loomcom.com>
|
||||||
|
|
||||||
See the file COPYING for license.
|
See the file COPYING for license.
|
||||||
|
|
||||||
|
@ -25,6 +25,11 @@ documentation, and extensive test suites for validating correctness.
|
||||||
Symon simulates a complete system with a 1 MHz NMOS 6502, 32KB of RAM,
|
Symon simulates a complete system with a 1 MHz NMOS 6502, 32KB of RAM,
|
||||||
16KB of ROM, a 6551 ACIA, and a 6522 VIA.
|
16KB of ROM, a 6551 ACIA, and a 6522 VIA.
|
||||||
|
|
||||||
|
Symon has extensive unit tests to verify correctness, and fully passes
|
||||||
|
Klaus Dormann's 6502 Functional Test Suite as of version 0.8.2
|
||||||
|
(See [this thread on the 6502.org Forums] (http://forum.6502.org/viewtopic.php?f=2&t=2241)
|
||||||
|
for more information about this functional test suite).
|
||||||
|
|
||||||
## 2.0 Requirements
|
## 2.0 Requirements
|
||||||
|
|
||||||
- Java 1.5 or higher
|
- Java 1.5 or higher
|
||||||
|
@ -135,14 +140,15 @@ running.
|
||||||
|
|
||||||
## 5.0 Revision History
|
## 5.0 Revision History
|
||||||
|
|
||||||
- 0.8.1: 30 December, 2012
|
- **0.8.2:** 01 January, 2013 - Fully passes Klaus Dormann's 6502 Functional Test suite!
|
||||||
- 0.8.0: 29 December, 2012
|
- **0.8.1:** 30 December, 2012
|
||||||
- 0.7.0: 9 December, 2012
|
- **0.8.0:** 29 December, 2012
|
||||||
- 0.6: 5 November, 2012
|
- **0.7.0:** 9 December, 2012
|
||||||
- 0.5: 21 October, 2012
|
- **0.6:** 5 November, 2012
|
||||||
- 0.3: 14 October, 2012
|
- **0.5:** 21 October, 2012 - Able to run Enhanced BASIC for the first time.
|
||||||
- 0.2: 22 April, 2012
|
- **0.3:** 14 October, 2012
|
||||||
- 0.1: 20 January, 2010
|
- **0.2:** 22 April, 2012
|
||||||
|
- **0.1:** 20 January, 2010
|
||||||
|
|
||||||
## 6.0 To Do
|
## 6.0 To Do
|
||||||
|
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -4,7 +4,7 @@
|
||||||
<groupId>com.loomcom.symon</groupId>
|
<groupId>com.loomcom.symon</groupId>
|
||||||
<artifactId>symon</artifactId>
|
<artifactId>symon</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>0.8.1</version>
|
<version>0.8.2</version>
|
||||||
<name>symon</name>
|
<name>symon</name>
|
||||||
<url>http://www.loomcom.com/symon</url>
|
<url>http://www.loomcom.com/symon</url>
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -44,14 +44,14 @@ public class Cpu implements InstructionTable {
|
||||||
public static final int P_NEGATIVE = 0x80;
|
public static final int P_NEGATIVE = 0x80;
|
||||||
|
|
||||||
// NMI vector
|
// NMI vector
|
||||||
public static final int IRQ_VECTOR_L = 0xfffa;
|
public static final int NMI_VECTOR_L = 0xfffa;
|
||||||
public static final int IRQ_VECTOR_H = 0xfffb;
|
public static final int NMI_VECTOR_H = 0xfffb;
|
||||||
// Reset vector
|
// Reset vector
|
||||||
public static final int RST_VECTOR_L = 0xfffc;
|
public static final int RST_VECTOR_L = 0xfffc;
|
||||||
public static final int RST_VECTOR_H = 0xfffd;
|
public static final int RST_VECTOR_H = 0xfffd;
|
||||||
// IRQ vector
|
// IRQ vector
|
||||||
public static final int NMI_VECTOR_L = 0xfffe;
|
public static final int IRQ_VECTOR_L = 0xfffe;
|
||||||
public static final int NMI_VECTOR_H = 0xffff;
|
public static final int IRQ_VECTOR_H = 0xffff;
|
||||||
|
|
||||||
// The delay in microseconds between steps.
|
// The delay in microseconds between steps.
|
||||||
// TODO: Make configurable
|
// TODO: Make configurable
|
||||||
|
@ -214,7 +214,7 @@ public class Cpu implements InstructionTable {
|
||||||
case 1:
|
case 1:
|
||||||
switch (irAddressMode) {
|
switch (irAddressMode) {
|
||||||
case 0: // (Zero Page,X)
|
case 0: // (Zero Page,X)
|
||||||
tmp = state.args[0] + state.x;
|
tmp = (state.args[0] + state.x) & 0xff;
|
||||||
effectiveAddress = address(bus.read(tmp), bus.read(tmp + 1));
|
effectiveAddress = address(bus.read(tmp), bus.read(tmp + 1));
|
||||||
break;
|
break;
|
||||||
case 1: // Zero Page
|
case 1: // Zero Page
|
||||||
|
@ -252,9 +252,9 @@ public class Cpu implements InstructionTable {
|
||||||
if (!getIrqDisableFlag()) {
|
if (!getIrqDisableFlag()) {
|
||||||
// Set the break flag before pushing.
|
// Set the break flag before pushing.
|
||||||
setBreakFlag();
|
setBreakFlag();
|
||||||
// Push program counter + 2 onto the stack
|
// Push program counter + 1 onto the stack
|
||||||
stackPush((state.pc + 2 >> 8) & 0xff); // PC high byte
|
stackPush((state.pc + 1 >> 8) & 0xff); // PC high byte
|
||||||
stackPush(state.pc + 2 & 0xff); // PC low byte
|
stackPush(state.pc + 1 & 0xff); // PC low byte
|
||||||
stackPush(state.getStatusFlag());
|
stackPush(state.getStatusFlag());
|
||||||
// Set the Interrupt Disabled flag. RTI will clear it.
|
// Set the Interrupt Disabled flag. RTI will clear it.
|
||||||
setIrqDisableFlag();
|
setIrqDisableFlag();
|
||||||
|
@ -263,7 +263,8 @@ public class Cpu implements InstructionTable {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x08: // PHP - Push Processor Status - Implied
|
case 0x08: // PHP - Push Processor Status - Implied
|
||||||
stackPush(state.getStatusFlag());
|
// Break flag is always set in the stack value.
|
||||||
|
stackPush(state.getStatusFlag() | 0x10);
|
||||||
break;
|
break;
|
||||||
case 0x10: // BPL - Branch if Positive - Relative
|
case 0x10: // BPL - Branch if Positive - Relative
|
||||||
if (!getNegativeFlag()) {
|
if (!getNegativeFlag()) {
|
||||||
|
@ -1094,6 +1095,11 @@ public class Cpu implements InstructionTable {
|
||||||
public void setStackPointer(int offset) {
|
public void setStackPointer(int offset) {
|
||||||
state.sp = offset;
|
state.sp = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getInstruction() {
|
||||||
|
return state.ir;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @value The value of the Process Status Register bits to be set.
|
* @value The value of the Process Status Register bits to be set.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -241,8 +241,8 @@ public interface InstructionTable {
|
||||||
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xac-0xaf
|
Mode.ABS, Mode.ABS, Mode.ABS, Mode.NUL, // 0xac-0xaf
|
||||||
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xb0-0xb3
|
Mode.REL, Mode.INY, Mode.NUL, Mode.NUL, // 0xb0-0xb3
|
||||||
Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0xb4-0xb7
|
Mode.ZPX, Mode.ZPX, Mode.ZPY, Mode.NUL, // 0xb4-0xb7
|
||||||
Mode.IMP, Mode.ABX, Mode.IMP, Mode.NUL, // 0xb8-0xbb
|
Mode.IMP, Mode.ABY, Mode.IMP, Mode.NUL, // 0xb8-0xbb
|
||||||
Mode.ABX, Mode.ABY, Mode.ABY, Mode.NUL, // 0xbc-0xbf
|
Mode.ABX, Mode.ABX, Mode.ABY, Mode.NUL, // 0xbc-0xbf
|
||||||
Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xc0-0xc3
|
Mode.IMM, Mode.XIN, Mode.NUL, Mode.NUL, // 0xc0-0xc3
|
||||||
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xc4-0xc7
|
Mode.ZPG, Mode.ZPG, Mode.ZPG, Mode.NUL, // 0xc4-0xc7
|
||||||
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xc8-0xcb
|
Mode.IMP, Mode.IMM, Mode.IMP, Mode.NUL, // 0xc8-0xcb
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
@ -451,9 +451,9 @@ public class Simulator implements Observer {
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (isRunning && !(preferences.getHaltOnBreak() && cpu.getBreakFlag())) {
|
do {
|
||||||
step();
|
step();
|
||||||
}
|
} while (shouldContinue());
|
||||||
} catch (SymonException ex) {
|
} catch (SymonException ex) {
|
||||||
logger.log(Level.SEVERE, "Exception in main simulator run thread. Exiting run.");
|
logger.log(Level.SEVERE, "Exception in main simulator run thread. Exiting run.");
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
|
@ -475,6 +475,15 @@ public class Simulator implements Observer {
|
||||||
|
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the run loop should proceed to the next step.
|
||||||
|
*
|
||||||
|
* @return True if the run loop should proceed to the next step.
|
||||||
|
*/
|
||||||
|
private boolean shouldContinue() {
|
||||||
|
return isRunning && !(preferences.getHaltOnBreak() && cpu.getInstruction() == 0x00);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadProgramAction extends AbstractAction {
|
class LoadProgramAction extends AbstractAction {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.loomcom.symon.exceptions;
|
package com.loomcom.symon.exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.loomcom.symon.exceptions;
|
package com.loomcom.symon.exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.loomcom.symon.exceptions;
|
package com.loomcom.symon.exceptions;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008-2012 Seth J. Morabito <sethm@loomcom.com>
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.loomcom.symon.util;
|
package com.loomcom.symon.util;
|
||||||
|
|
||||||
import com.loomcom.symon.exceptions.*;
|
import com.loomcom.symon.exceptions.*;
|
||||||
|
|
|
@ -1,3 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2008-2013 Seth J. Morabito <sethm@loomcom.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
package com.loomcom.symon.util;
|
package com.loomcom.symon.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,14 +3,17 @@ package com.loomcom.symon;
|
||||||
import com.loomcom.symon.devices.Memory;
|
import com.loomcom.symon.devices.Memory;
|
||||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||||
import com.loomcom.symon.exceptions.MemoryRangeException;
|
import com.loomcom.symon.exceptions.MemoryRangeException;
|
||||||
import junit.framework.*;
|
import org.junit.*;
|
||||||
|
|
||||||
public class CpuImpliedModeTest extends TestCase {
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class CpuImpliedModeTest {
|
||||||
|
|
||||||
protected Cpu cpu;
|
protected Cpu cpu;
|
||||||
protected Bus bus;
|
protected Bus bus;
|
||||||
protected Memory mem;
|
protected Memory mem;
|
||||||
|
|
||||||
|
@Before
|
||||||
public void setUp() throws MemoryRangeException, MemoryAccessException {
|
public void setUp() throws MemoryRangeException, MemoryAccessException {
|
||||||
this.cpu = new Cpu();
|
this.cpu = new Cpu();
|
||||||
this.bus = new Bus(0x0000, 0xffff);
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
@ -69,6 +72,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
|
|
||||||
/* BRK Tests - 0x00 */
|
/* BRK Tests - 0x00 */
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_BRK() throws MemoryAccessException {
|
public void test_BRK() throws MemoryAccessException {
|
||||||
cpu.setCarryFlag();
|
cpu.setCarryFlag();
|
||||||
cpu.setOverflowFlag();
|
cpu.setOverflowFlag();
|
||||||
|
@ -80,15 +84,15 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertEquals(0xff, cpu.getStackPointer());
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
|
|
||||||
// Set the IRQ vector
|
// Set the IRQ vector
|
||||||
bus.write(Cpu.IRQ_VECTOR_H, 0x12);
|
bus.write(0xffff, 0x12);
|
||||||
bus.write(Cpu.IRQ_VECTOR_L, 0x34);
|
bus.write(0xfffe, 0x34);
|
||||||
|
|
||||||
bus.loadProgram(0xea,
|
bus.loadProgram(0xea, // NOP
|
||||||
0xea,
|
0xea, // NOP
|
||||||
0xea,
|
0xea, // NOP
|
||||||
0x00,
|
0x00, // BRK
|
||||||
0xea,
|
0xea, // NOP
|
||||||
0xea);
|
0xea); // NOP
|
||||||
|
|
||||||
cpu.step(3); // Three NOP instructions
|
cpu.step(3); // Three NOP instructions
|
||||||
|
|
||||||
|
@ -96,9 +100,9 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
|
|
||||||
cpu.step(); // Triggers the BRK
|
cpu.step(); // Triggers the BRK
|
||||||
|
|
||||||
// Was at PC = 0x204. PC+2 should now be on the stack
|
// Was at PC = 0x204. PC+1 should now be on the stack
|
||||||
assertEquals(0x02, bus.read(0x1ff)); // PC high byte
|
assertEquals(0x02, bus.read(0x1ff)); // PC high byte
|
||||||
assertEquals(0x06, bus.read(0x1fe)); // PC low byte
|
assertEquals(0x05, bus.read(0x1fe)); // PC low byte
|
||||||
assertEquals(0x20 | Cpu.P_CARRY | Cpu.P_OVERFLOW | Cpu.P_BREAK,
|
assertEquals(0x20 | Cpu.P_CARRY | Cpu.P_OVERFLOW | Cpu.P_BREAK,
|
||||||
bus.read(0x1fd)); // Processor Status, with B set
|
bus.read(0x1fd)); // Processor Status, with B set
|
||||||
|
|
||||||
|
@ -112,6 +116,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
cpu.getProcessorStatus());
|
cpu.getProcessorStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_BRK_HonorsIrqDisableFlag() throws MemoryAccessException {
|
public void test_BRK_HonorsIrqDisableFlag() throws MemoryAccessException {
|
||||||
cpu.setIrqDisableFlag();
|
cpu.setIrqDisableFlag();
|
||||||
|
|
||||||
|
@ -144,6 +149,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CLC - Clear Carry Flag - $18 */
|
/* CLC - Clear Carry Flag - $18 */
|
||||||
|
@Test
|
||||||
public void test_CLC() throws MemoryAccessException {
|
public void test_CLC() throws MemoryAccessException {
|
||||||
cpu.setCarryFlag();
|
cpu.setCarryFlag();
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
@ -155,6 +161,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CLD - Clear Decimal Mode Flag - $d8 */
|
/* CLD - Clear Decimal Mode Flag - $d8 */
|
||||||
|
@Test
|
||||||
public void test_CLD() throws MemoryAccessException {
|
public void test_CLD() throws MemoryAccessException {
|
||||||
cpu.setDecimalModeFlag();
|
cpu.setDecimalModeFlag();
|
||||||
assertTrue(cpu.getDecimalModeFlag());
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
@ -166,6 +173,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CLI - Clear Interrupt Disabled Flag - $58 */
|
/* CLI - Clear Interrupt Disabled Flag - $58 */
|
||||||
|
@Test
|
||||||
public void test_CLI() throws MemoryAccessException {
|
public void test_CLI() throws MemoryAccessException {
|
||||||
cpu.setIrqDisableFlag();
|
cpu.setIrqDisableFlag();
|
||||||
assertTrue(cpu.getIrqDisableFlag());
|
assertTrue(cpu.getIrqDisableFlag());
|
||||||
|
@ -177,6 +185,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CLV - Clear Overflow Flag - $b8 */
|
/* CLV - Clear Overflow Flag - $b8 */
|
||||||
|
@Test
|
||||||
public void test_CLV() throws MemoryAccessException {
|
public void test_CLV() throws MemoryAccessException {
|
||||||
cpu.setOverflowFlag();
|
cpu.setOverflowFlag();
|
||||||
assertTrue(cpu.getOverflowFlag());
|
assertTrue(cpu.getOverflowFlag());
|
||||||
|
@ -188,7 +197,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DEX - Decrement the X register - $ca */
|
/* DEX - Decrement the X register - $ca */
|
||||||
|
@Test
|
||||||
public void test_DEX() throws MemoryAccessException {
|
public void test_DEX() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xca);
|
bus.loadProgram(0xca);
|
||||||
cpu.setXRegister(0x02);
|
cpu.setXRegister(0x02);
|
||||||
|
@ -198,6 +207,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_DEX_SetsZeroFlagWhenZero() throws MemoryAccessException {
|
public void test_DEX_SetsZeroFlagWhenZero() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xca);
|
bus.loadProgram(0xca);
|
||||||
cpu.setXRegister(0x01);
|
cpu.setXRegister(0x01);
|
||||||
|
@ -207,6 +217,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_DEX_SetsNegativeFlagWhen() throws MemoryAccessException {
|
public void test_DEX_SetsNegativeFlagWhen() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xca);
|
bus.loadProgram(0xca);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
|
@ -216,7 +227,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DEY - Decrement the Y register - $88 */
|
/* DEY - Decrement the Y register - $88 */
|
||||||
|
@Test
|
||||||
public void test_DEY() throws MemoryAccessException {
|
public void test_DEY() throws MemoryAccessException {
|
||||||
bus.loadProgram(0x88);
|
bus.loadProgram(0x88);
|
||||||
cpu.setYRegister(0x02);
|
cpu.setYRegister(0x02);
|
||||||
|
@ -226,6 +237,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_DEY_SetsZeroFlagWhenZero() throws MemoryAccessException {
|
public void test_DEY_SetsZeroFlagWhenZero() throws MemoryAccessException {
|
||||||
bus.loadProgram(0x88);
|
bus.loadProgram(0x88);
|
||||||
cpu.setYRegister(0x01);
|
cpu.setYRegister(0x01);
|
||||||
|
@ -235,6 +247,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_DEY_SetsNegativeFlagWhen() throws MemoryAccessException {
|
public void test_DEY_SetsNegativeFlagWhen() throws MemoryAccessException {
|
||||||
bus.loadProgram(0x88);
|
bus.loadProgram(0x88);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
|
@ -244,7 +257,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* INX - Increment the X register - $e8 */
|
/* INX - Increment the X register - $e8 */
|
||||||
|
@Test
|
||||||
public void test_INX() throws MemoryAccessException {
|
public void test_INX() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xe8);
|
bus.loadProgram(0xe8);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
|
@ -253,6 +266,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_INX_SetsNegativeFlagWhenNegative() throws MemoryAccessException {
|
public void test_INX_SetsNegativeFlagWhenNegative() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xe8);
|
bus.loadProgram(0xe8);
|
||||||
cpu.setXRegister(0x7f);
|
cpu.setXRegister(0x7f);
|
||||||
|
@ -262,6 +276,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_INX_SetsZeroFlagWhenZero() throws MemoryAccessException {
|
public void test_INX_SetsZeroFlagWhenZero() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xe8);
|
bus.loadProgram(0xe8);
|
||||||
cpu.setXRegister(0xff);
|
cpu.setXRegister(0xff);
|
||||||
|
@ -272,7 +287,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* INY - Increment the Y register - $c8 */
|
/* INY - Increment the Y register - $c8 */
|
||||||
|
@Test
|
||||||
public void test_INY() throws MemoryAccessException {
|
public void test_INY() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xc8);
|
bus.loadProgram(0xc8);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
|
@ -281,6 +296,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_INY_SetsNegativeFlagWhenNegative() throws MemoryAccessException {
|
public void test_INY_SetsNegativeFlagWhenNegative() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xc8);
|
bus.loadProgram(0xc8);
|
||||||
cpu.setYRegister(0x7f);
|
cpu.setYRegister(0x7f);
|
||||||
|
@ -290,6 +306,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_INY_SetsZeroFlagWhenZero() throws MemoryAccessException {
|
public void test_INY_SetsZeroFlagWhenZero() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xc8);
|
bus.loadProgram(0xc8);
|
||||||
cpu.setYRegister(0xff);
|
cpu.setYRegister(0xff);
|
||||||
|
@ -300,7 +317,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOP - No Operation - $ea */
|
/* NOP - No Operation - $ea */
|
||||||
|
@Test
|
||||||
public void test_NOP() throws MemoryAccessException {
|
public void test_NOP() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xea);
|
bus.loadProgram(0xea);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
|
@ -314,7 +331,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PHA - Push Accumulator - $48 */
|
/* PHA - Push Accumulator - $48 */
|
||||||
|
@Test
|
||||||
public void test_PHA() throws MemoryAccessException {
|
public void test_PHA() throws MemoryAccessException {
|
||||||
bus.loadProgram(0x48);
|
bus.loadProgram(0x48);
|
||||||
cpu.setAccumulator(0x3a);
|
cpu.setAccumulator(0x3a);
|
||||||
|
@ -324,17 +341,19 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PHP - Push Processor Status - $08 */
|
/* PHP - Push Processor Status - $08 */
|
||||||
|
@Test
|
||||||
public void test_PHP() throws MemoryAccessException {
|
public void test_PHP() throws MemoryAccessException {
|
||||||
bus.loadProgram(0x08);
|
bus.loadProgram(0x08);
|
||||||
cpu.setProcessorStatus(0x27);
|
cpu.setProcessorStatus(0x27);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
assertEquals(0xfe, cpu.getStackPointer());
|
assertEquals(0xfe, cpu.getStackPointer());
|
||||||
assertEquals(0x27, cpu.stackPeek());
|
// PHP should have set the BREAK flag _on the stack_ (but not in the CPU)
|
||||||
|
assertEquals(0x37, cpu.stackPeek());
|
||||||
|
assertEquals(0x27, cpu.getProcessorStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PLA - Pul Accumulator - $68 */
|
/* PLA - Pul Accumulator - $68 */
|
||||||
|
@Test
|
||||||
public void test_PLA() throws MemoryAccessException {
|
public void test_PLA() throws MemoryAccessException {
|
||||||
cpu.stackPush(0x32);
|
cpu.stackPush(0x32);
|
||||||
bus.loadProgram(0x68);
|
bus.loadProgram(0x68);
|
||||||
|
@ -344,6 +363,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_PLA_SetsZeroIfAccumulatorIsZero() throws MemoryAccessException {
|
public void test_PLA_SetsZeroIfAccumulatorIsZero() throws MemoryAccessException {
|
||||||
cpu.stackPush(0x00);
|
cpu.stackPush(0x00);
|
||||||
bus.loadProgram(0x68);
|
bus.loadProgram(0x68);
|
||||||
|
@ -353,6 +373,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_PLA_SetsNegativeIfAccumulatorIsNegative() throws MemoryAccessException {
|
public void test_PLA_SetsNegativeIfAccumulatorIsNegative() throws MemoryAccessException {
|
||||||
cpu.stackPush(0xff);
|
cpu.stackPush(0xff);
|
||||||
bus.loadProgram(0x68);
|
bus.loadProgram(0x68);
|
||||||
|
@ -363,7 +384,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PLP - Pull Processor Status - $28 */
|
/* PLP - Pull Processor Status - $28 */
|
||||||
|
@Test
|
||||||
public void test_PLP() throws MemoryAccessException {
|
public void test_PLP() throws MemoryAccessException {
|
||||||
cpu.stackPush(0x2f);
|
cpu.stackPush(0x2f);
|
||||||
bus.loadProgram(0x28);
|
bus.loadProgram(0x28);
|
||||||
|
@ -372,7 +393,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RTI - Return from Interrupt - $40 */
|
/* RTI - Return from Interrupt - $40 */
|
||||||
|
@Test
|
||||||
public void test_RTI() throws MemoryAccessException {
|
public void test_RTI() throws MemoryAccessException {
|
||||||
cpu.stackPush(0x0f); // PC hi
|
cpu.stackPush(0x0f); // PC hi
|
||||||
cpu.stackPush(0x11); // PC lo
|
cpu.stackPush(0x11); // PC lo
|
||||||
|
@ -386,7 +407,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RTS - Return from Subroutine - $60 */
|
/* RTS - Return from Subroutine - $60 */
|
||||||
|
@Test
|
||||||
public void test_RTS() throws MemoryAccessException {
|
public void test_RTS() throws MemoryAccessException {
|
||||||
cpu.stackPush(0x0f); // PC hi
|
cpu.stackPush(0x0f); // PC hi
|
||||||
cpu.stackPush(0x11); // PC lo
|
cpu.stackPush(0x11); // PC lo
|
||||||
|
@ -399,7 +420,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SEC - Set Carry Flag - $38 */
|
/* SEC - Set Carry Flag - $38 */
|
||||||
|
@Test
|
||||||
public void test_SEC() throws MemoryAccessException {
|
public void test_SEC() throws MemoryAccessException {
|
||||||
bus.loadProgram(0x38);
|
bus.loadProgram(0x38);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
|
@ -407,7 +428,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SED - Set Decimal Mode Flag - $f8 */
|
/* SED - Set Decimal Mode Flag - $f8 */
|
||||||
|
@Test
|
||||||
public void test_SED() throws MemoryAccessException {
|
public void test_SED() throws MemoryAccessException {
|
||||||
bus.loadProgram(0xf8);
|
bus.loadProgram(0xf8);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
|
@ -415,7 +436,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SEI - Set Interrupt Disable Flag - $78 */
|
/* SEI - Set Interrupt Disable Flag - $78 */
|
||||||
|
@Test
|
||||||
public void test_SEI() throws MemoryAccessException {
|
public void test_SEI() throws MemoryAccessException {
|
||||||
bus.loadProgram(0x78);
|
bus.loadProgram(0x78);
|
||||||
cpu.step();
|
cpu.step();
|
||||||
|
@ -423,7 +444,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TAX - Transfer Accumulator to X Register - $aa */
|
/* TAX - Transfer Accumulator to X Register - $aa */
|
||||||
|
@Test
|
||||||
public void test_TAX() throws MemoryAccessException {
|
public void test_TAX() throws MemoryAccessException {
|
||||||
cpu.setAccumulator(0x32);
|
cpu.setAccumulator(0x32);
|
||||||
bus.loadProgram(0xaa);
|
bus.loadProgram(0xaa);
|
||||||
|
@ -433,6 +454,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TAX_SetsZeroFlagIfXIsZero() throws MemoryAccessException {
|
public void test_TAX_SetsZeroFlagIfXIsZero() throws MemoryAccessException {
|
||||||
cpu.setAccumulator(0x00);
|
cpu.setAccumulator(0x00);
|
||||||
bus.loadProgram(0xaa);
|
bus.loadProgram(0xaa);
|
||||||
|
@ -442,6 +464,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TAX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException {
|
public void test_TAX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException {
|
||||||
cpu.setAccumulator(0xff);
|
cpu.setAccumulator(0xff);
|
||||||
bus.loadProgram(0xaa);
|
bus.loadProgram(0xaa);
|
||||||
|
@ -452,7 +475,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TAY - Transfer Accumulator to Y Register - $a8 */
|
/* TAY - Transfer Accumulator to Y Register - $a8 */
|
||||||
|
@Test
|
||||||
public void test_TAY() throws MemoryAccessException {
|
public void test_TAY() throws MemoryAccessException {
|
||||||
cpu.setAccumulator(0x32);
|
cpu.setAccumulator(0x32);
|
||||||
bus.loadProgram(0xa8);
|
bus.loadProgram(0xa8);
|
||||||
|
@ -462,6 +485,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TAY_SetsZeroFlagIfYIsZero() throws MemoryAccessException {
|
public void test_TAY_SetsZeroFlagIfYIsZero() throws MemoryAccessException {
|
||||||
cpu.setAccumulator(0x00);
|
cpu.setAccumulator(0x00);
|
||||||
bus.loadProgram(0xa8);
|
bus.loadProgram(0xa8);
|
||||||
|
@ -471,6 +495,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TAY_SetsNegativeFlagIfYIsNegative() throws MemoryAccessException {
|
public void test_TAY_SetsNegativeFlagIfYIsNegative() throws MemoryAccessException {
|
||||||
cpu.setAccumulator(0xff);
|
cpu.setAccumulator(0xff);
|
||||||
bus.loadProgram(0xa8);
|
bus.loadProgram(0xa8);
|
||||||
|
@ -481,7 +506,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TSX - Transfer Stack Pointer to X Register - $ba */
|
/* TSX - Transfer Stack Pointer to X Register - $ba */
|
||||||
|
@Test
|
||||||
public void test_TSX() throws MemoryAccessException {
|
public void test_TSX() throws MemoryAccessException {
|
||||||
cpu.setStackPointer(0x32);
|
cpu.setStackPointer(0x32);
|
||||||
bus.loadProgram(0xba);
|
bus.loadProgram(0xba);
|
||||||
|
@ -491,6 +516,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TSX_SetsZeroFlagIfXIsZero() throws MemoryAccessException {
|
public void test_TSX_SetsZeroFlagIfXIsZero() throws MemoryAccessException {
|
||||||
cpu.setStackPointer(0x00);
|
cpu.setStackPointer(0x00);
|
||||||
bus.loadProgram(0xba);
|
bus.loadProgram(0xba);
|
||||||
|
@ -500,6 +526,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TSX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException {
|
public void test_TSX_SetsNegativeFlagIfXIsNegative() throws MemoryAccessException {
|
||||||
cpu.setStackPointer(0xff);
|
cpu.setStackPointer(0xff);
|
||||||
bus.loadProgram(0xba);
|
bus.loadProgram(0xba);
|
||||||
|
@ -510,7 +537,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TXA - Transfer X Register to Accumulator - $8a */
|
/* TXA - Transfer X Register to Accumulator - $8a */
|
||||||
|
@Test
|
||||||
public void test_TXA() throws MemoryAccessException {
|
public void test_TXA() throws MemoryAccessException {
|
||||||
cpu.setXRegister(0x32);
|
cpu.setXRegister(0x32);
|
||||||
bus.loadProgram(0x8a);
|
bus.loadProgram(0x8a);
|
||||||
|
@ -520,6 +547,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TXA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException {
|
public void test_TXA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException {
|
||||||
cpu.setXRegister(0x00);
|
cpu.setXRegister(0x00);
|
||||||
bus.loadProgram(0x8a);
|
bus.loadProgram(0x8a);
|
||||||
|
@ -529,6 +557,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TXA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException {
|
public void test_TXA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException {
|
||||||
cpu.setXRegister(0xff);
|
cpu.setXRegister(0xff);
|
||||||
bus.loadProgram(0x8a);
|
bus.loadProgram(0x8a);
|
||||||
|
@ -539,7 +568,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TXS - Transfer X Register to Stack Pointer - $9a */
|
/* TXS - Transfer X Register to Stack Pointer - $9a */
|
||||||
|
@Test
|
||||||
public void test_TXS() throws MemoryAccessException {
|
public void test_TXS() throws MemoryAccessException {
|
||||||
cpu.setXRegister(0x32);
|
cpu.setXRegister(0x32);
|
||||||
bus.loadProgram(0x9a);
|
bus.loadProgram(0x9a);
|
||||||
|
@ -549,6 +578,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TXS_DoesNotAffectProcessorStatus() throws MemoryAccessException {
|
public void test_TXS_DoesNotAffectProcessorStatus() throws MemoryAccessException {
|
||||||
cpu.setXRegister(0x00);
|
cpu.setXRegister(0x00);
|
||||||
bus.loadProgram(0x9a);
|
bus.loadProgram(0x9a);
|
||||||
|
@ -566,7 +596,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TYA - Transfer Y Register to Accumulator - $98 */
|
/* TYA - Transfer Y Register to Accumulator - $98 */
|
||||||
|
@Test
|
||||||
public void test_TYA() throws MemoryAccessException {
|
public void test_TYA() throws MemoryAccessException {
|
||||||
cpu.setYRegister(0x32);
|
cpu.setYRegister(0x32);
|
||||||
bus.loadProgram(0x98);
|
bus.loadProgram(0x98);
|
||||||
|
@ -576,6 +606,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TYA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException {
|
public void test_TYA_SetsZeroFlagIfAccumulatorIsZero() throws MemoryAccessException {
|
||||||
cpu.setYRegister(0x00);
|
cpu.setYRegister(0x00);
|
||||||
bus.loadProgram(0x98);
|
bus.loadProgram(0x98);
|
||||||
|
@ -585,6 +616,7 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test_TYA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException {
|
public void test_TYA_SetsNegativeFlagIfAccumulatorIsNegative() throws MemoryAccessException {
|
||||||
cpu.setYRegister(0xff);
|
cpu.setYRegister(0xff);
|
||||||
bus.loadProgram(0x98);
|
bus.loadProgram(0x98);
|
||||||
|
@ -593,5 +625,4 @@ public class CpuImpliedModeTest extends TestCase {
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getNegativeFlag());
|
assertTrue(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -48,6 +48,32 @@ public class CpuIndexedIndirectModeTest {
|
||||||
assertEquals(0x45, cpu.getAccumulator());
|
assertEquals(0x45, cpu.getAccumulator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testZeroPageWrap() throws Exception {
|
||||||
|
bus.write(0x0020, 0x01);
|
||||||
|
bus.write(0x0021, 0x07); // ($0701)
|
||||||
|
bus.write(0x0701, 0xaa);
|
||||||
|
|
||||||
|
bus.write(0x000f, 0x02);
|
||||||
|
bus.write(0x0010, 0x08); // ($0802)
|
||||||
|
bus.write(0x0802, 0xbb);
|
||||||
|
|
||||||
|
bus.write(0x010f, 0x03);
|
||||||
|
bus.write(0x0110, 0x09); // ($0903)
|
||||||
|
bus.write(0x0903, 0xcc);
|
||||||
|
|
||||||
|
cpu.setXRegister(0x10);
|
||||||
|
|
||||||
|
// No wrap needed
|
||||||
|
bus.loadProgram(0xa1, 0x10, // LDA ($10,X) = ($10 + $10) & $ff = $20
|
||||||
|
0xa1, 0xff); // LDA ($ff,X) = ($ff + $10) & $ff = $0f, NOT $10f!
|
||||||
|
cpu.step(1);
|
||||||
|
assertEquals(0xaa, cpu.getAccumulator());
|
||||||
|
|
||||||
|
cpu.step(1);
|
||||||
|
assertEquals(0xbb, cpu.getAccumulator());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_ORA() throws Exception {
|
public void test_ORA() throws Exception {
|
||||||
bus.write(0x0012, 0x1f);
|
bus.write(0x0012, 0x1f);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user