* Correct implementation of Indirect Indexed and Indexed Indirect addressing modes.

* Unit tests for Indirect Indexed and Indexed Indirect.
* Updated copyright dates.
* Started moving to JUnit 4.
This commit is contained in:
Seth Morabito committed 2010-01-15 08:20:03 +00:00
1 parent d858a50f1b
commit f174f0312f
6 files changed
+244 -68

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License The MIT License
Copyright (c) 2008,2009 Seth J. Morabito <sethm@loomcom.com> Copyright (c) 2008-2010 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
+5 -22
View File
@@ -11,8 +11,8 @@ deemed ready for testing, it will be given a version number of "0.1".
==================================================================== ====================================================================
Version: PRERELEASE Version: PRERELEASE
Last Updated: 07 January, 2009 Last Updated: 10 January, 2010
Copyright (c) 2008,2009 Seth J. Morabito <sethm@loomcom.com> Copyright (c) 2008-2010 Seth J. Morabito <sethm@loomcom.com>
See the file COPYING for license. See the file COPYING for license.
@@ -36,7 +36,7 @@ ACIAs. More functionality may be considered as time goes on.
- Java 1.5 or higher - Java 1.5 or higher
- Maven 2.0.x or higher (for building from source) - Maven 2.0.x or higher (for building from source)
- JUnit 3.0 or higher (for testing) - JUnit 4 or higher (for testing)
(More to come!) (More to come!)
@@ -44,25 +44,8 @@ ACIAs. More functionality may be considered as time goes on.
--------- ---------
- Finish core functionality. - Finish core functionality.
- Implement remaining addressing modes. - Finish command monitor.
- Refactor address decoding (second refactor to DRY up more).
COMPLETED ADDRESSING MODES:
o Implied
o Immediate
o Zero Page
o Accumulator
o Absolute
o Indirect [used only by JMP]
o Zero Page, X-indexed
o Zero Page, Y-indexed
o Absolute, X-indexed
o Absolute, Y-indexed
o Relative
INCOMPLETE ADDRESSING MODES:
o Indexed Indirect [ (Indirect ,X) ]
o Indirect Indexed [ (Indirect),Y ]
- Clean up JavaDoc. - Clean up JavaDoc.
- Implement CMOS 65C02 instructions and NMOS / CMOS mode flag. - Implement CMOS 65C02 instructions and NMOS / CMOS mode flag.
+4 -4
View File
@@ -11,21 +11,21 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>3.8.1</version> <version>4.7</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<!-- Set Java version to 6 --> <!-- Set Java version to Java 1.5 -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<!-- best lock down version of the plugin too --> <!-- best lock down version of the plugin too -->
<configuration> <configuration>
<source>5</source> <source>1.5</source>
<target>5</target> <target>1.5</target>
</configuration> </configuration>
</plugin> </plugin>
+68 -41
View File
@@ -192,8 +192,8 @@ public class Cpu implements InstructionTable {
case 1: case 1:
switch(irAddressMode) { switch(irAddressMode) {
case 0: // (Zero Page,X) case 0: // (Zero Page,X)
// TODO: UNIT TESTS tmp = args[0] + getXRegister();
effectiveAddress = bus.read(zpxAddress(args[0])); effectiveAddress = address(bus.read(tmp), bus.read(tmp + 1));
effectiveData = bus.read(effectiveAddress); effectiveData = bus.read(effectiveAddress);
break; break;
case 1: // Zero Page case 1: // Zero Page
@@ -209,11 +209,12 @@ public class Cpu implements InstructionTable {
effectiveData = bus.read(effectiveAddress); effectiveData = bus.read(effectiveAddress);
break; break;
case 4: // (Zero Page),Y case 4: // (Zero Page),Y
// TODO: UNIT TESTS tmp = address(bus.read(args[0]),
effectiveAddress = yAddress(bus.read(args[0]), getYRegister()); bus.read((args[0]+1)&0xff));
effectiveAddress = (tmp + getYRegister())&0xffff;
effectiveData = bus.read(effectiveAddress); effectiveData = bus.read(effectiveAddress);
break; break;
case 5: // Zero Page, X case 5: // Zero Page,X
effectiveAddress = zpxAddress(args[0]); effectiveAddress = zpxAddress(args[0]);
effectiveData = bus.read(effectiveAddress); effectiveData = bus.read(effectiveAddress);
break; break;
@@ -418,14 +419,14 @@ public class Cpu implements InstructionTable {
/** ASL - Arithmetic Shift Left *****************************************/ /** ASL - Arithmetic Shift Left *****************************************/
case 0x0a: // ASL - Accumulator case 0x0a: // Accumulator
a = asl(a); a = asl(a);
setArithmeticFlags(a); setArithmeticFlags(a);
break; break;
case 0x06: // ASL - Zero Page case 0x06: // Zero Page
case 0x0e: // ASL - Absolute case 0x0e: // Absolute
case 0x16: // ASL - Zero Page,X case 0x16: // Zero Page,X
case 0x1e: // ASL - Absolute,X case 0x1e: // Absolute,X
tmp = asl(effectiveData); tmp = asl(effectiveData);
bus.write(effectiveAddress, tmp); bus.write(effectiveAddress, tmp);
setArithmeticFlags(tmp); setArithmeticFlags(tmp);
@@ -457,14 +458,14 @@ public class Cpu implements InstructionTable {
/** ROL - Rotate Left ***************************************************/ /** ROL - Rotate Left ***************************************************/
case 0x2a: // ROL - Accumulator case 0x2a: // Accumulator
a = rol(a); a = rol(a);
setArithmeticFlags(a); setArithmeticFlags(a);
break; break;
case 0x26: // ROL - Zero Page case 0x26: // Zero Page
case 0x2e: // ROL - Absolute case 0x2e: // Absolute
case 0x36: // ROL - Zero Page,X case 0x36: // Zero Page,X
case 0x3e: // ROL - Absolute,X case 0x3e: // Absolute,X
tmp = rol(effectiveData); tmp = rol(effectiveData);
bus.write(effectiveAddress, tmp); bus.write(effectiveAddress, tmp);
setArithmeticFlags(tmp); setArithmeticFlags(tmp);
@@ -472,28 +473,28 @@ public class Cpu implements InstructionTable {
/** EOR - Exclusive OR **************************************************/ /** EOR - Exclusive OR **************************************************/
case 0x41: // EOR - (Zero Page, X) case 0x41: // (Zero Page,X)
case 0x45: // EOR - Zero Page case 0x45: // Zero Page
case 0x49: // EOR - Immediate case 0x49: // Immediate
case 0x4d: // EOR - Absolute case 0x4d: // Absolute
case 0x51: // EOR - (Zero Page,Y) case 0x51: // (Zero Page,Y)
case 0x55: // EOR - Zero Page,X case 0x55: // Zero Page,X
case 0x59: // EOR - Absolute,Y case 0x59: // Absolute,Y
case 0x5d: // EOR - Absolute,X case 0x5d: // Absolute,X
a ^= effectiveData; a ^= effectiveData;
setArithmeticFlags(a); setArithmeticFlags(a);
break; break;
/** LSR - Logical Shift Right *******************************************/ /** LSR - Logical Shift Right *******************************************/
case 0x4a: // LSR - Accumulator case 0x4a: // Accumulator
a = lsr(a); a = lsr(a);
setArithmeticFlags(a); setArithmeticFlags(a);
break; break;
case 0x46: // LSR - Zero Page case 0x46: // Zero Page
case 0x4e: // LSR - Absolute case 0x4e: // Absolute
case 0x56: // LSR - Zero Page,X case 0x56: // Zero Page,X
case 0x5e: // LSR - Absolute,X case 0x5e: // Absolute,X
tmp = lsr(effectiveData); tmp = lsr(effectiveData);
bus.write(effectiveAddress, tmp); bus.write(effectiveAddress, tmp);
setArithmeticFlags(tmp); setArithmeticFlags(tmp);
@@ -533,7 +534,7 @@ public class Cpu implements InstructionTable {
/** STA - Store Accumulator *********************************************/ /** STA - Store Accumulator *********************************************/
case 0x81: // (Zero Page, X) case 0x81: // (Zero Page,X)
case 0x85: // Zero Page case 0x85: // Zero Page
case 0x8d: // Absolute case 0x8d: // Absolute
case 0x91: // (Zero Page),Y case 0x91: // (Zero Page),Y
@@ -564,11 +565,11 @@ public class Cpu implements InstructionTable {
/** LDY - Load Y Register ***********************************************/ /** LDY - Load Y Register ***********************************************/
case 0xa0: // LDY - Immediate case 0xa0: // Immediate
case 0xa4: // LDY - Zero Page case 0xa4: // Zero Page
case 0xac: // LDY - Absolute case 0xac: // Absolute
case 0xb4: // LDY - Zero Page,X case 0xb4: // Zero Page,X
case 0xbc: // LDY - Absolute,X case 0xbc: // Absolute,X
y = effectiveData; y = effectiveData;
setArithmeticFlags(y); setArithmeticFlags(y);
break; break;
@@ -586,7 +587,7 @@ public class Cpu implements InstructionTable {
/** LDA - Load Accumulator **********************************************/ /** LDA - Load Accumulator **********************************************/
case 0xa1: // Zero Page, X) case 0xa1: // (Zero Page,X)
case 0xa5: // Zero Page case 0xa5: // Zero Page
case 0xa9: // Immediate case 0xa9: // Immediate
case 0xad: // Absolute case 0xad: // Absolute
@@ -608,11 +609,11 @@ public class Cpu implements InstructionTable {
/** CMP - Compare Accumulator *******************************************/ /** CMP - Compare Accumulator *******************************************/
case 0xc1: // (Zero Page, X) case 0xc1: // (Zero Page,X)
case 0xc5: // Zero Page case 0xc5: // Zero Page
case 0xc9: // #Immediate case 0xc9: // #Immediate
case 0xcd: // Absolute case 0xcd: // Absolute
case 0xd1: // (Zero Page), Y case 0xd1: // (Zero Page),Y
case 0xd5: // Zero Page,X case 0xd5: // Zero Page,X
case 0xd9: // Absolute,Y case 0xd9: // Absolute,Y
case 0xdd: // Absolute,X case 0xdd: // Absolute,X
@@ -623,7 +624,7 @@ public class Cpu implements InstructionTable {
/** DEC - Decrement Memory **********************************************/ /** DEC - Decrement Memory **********************************************/
case 0xc6: // Zero Page case 0xc6: // Zero Page
case 0xce: // Absolute case 0xce: // Absolute
case 0xd6: // Zero Page, X case 0xd6: // Zero Page,X
case 0xde: // Absolute,X case 0xde: // Absolute,X
tmp = --effectiveData & 0xff; tmp = --effectiveData & 0xff;
bus.write(effectiveAddress, tmp); bus.write(effectiveAddress, tmp);
@@ -640,11 +641,11 @@ public class Cpu implements InstructionTable {
/** SBC - Subtract with Carry (Borrow) **********************************/ /** SBC - Subtract with Carry (Borrow) **********************************/
case 0xe1: // (Zero Page, X) case 0xe1: // (Zero Page,X)
case 0xe5: // Zero Page case 0xe5: // Zero Page
case 0xe9: // Immediate case 0xe9: // Immediate
case 0xed: // Absolute case 0xed: // Absolute
case 0xf1: // (Zero Page), Y case 0xf1: // (Zero Page),Y
case 0xf5: // Zero Page,X case 0xf5: // Zero Page,X
case 0xf9: // Absolute,Y case 0xf9: // Absolute,Y
case 0xfd: // Absolute,X case 0xfd: // Absolute,X
@@ -1255,7 +1256,7 @@ public class Cpu implements InstructionTable {
* Given two bytes, return an address. * Given two bytes, return an address.
*/ */
int address(int lowByte, int hiByte) { int address(int lowByte, int hiByte) {
return ((hiByte<<8)|lowByte); return ((hiByte<<8)|lowByte) & 0xffff;
} }
/** /**
@@ -1313,8 +1314,34 @@ public class Cpu implements InstructionTable {
case ABS: case ABS:
sb.append(String.format(" $%04X", address(op1, op2))); sb.append(String.format(" $%04X", address(op1, op2)));
break; break;
case ABX:
sb.append(String.format(" $%04X,X", address(op1, op2)));
break;
case ABY:
sb.append(String.format(" $%04X,Y", address(op1, op2)));
break;
case IMM: case IMM:
sb.append(String.format(" #$%02X", op1)); sb.append(String.format(" #$%02X", op1));
break;
case IND:
sb.append(String.format(" ($%04X)", address(op1, op2)));
break;
case XIN:
sb.append(String.format(" ($%02X),X", op1));
break;
case INY:
sb.append(String.format(" ($%02X,Y)", op1));
break;
case REL:
case ZPG:
sb.append(String.format(" $%02X", op1));
break;
case ZPX:
sb.append(String.format(" $%02X,X", op1));
break;
case ZPY:
sb.append(String.format(" $%02X,Y", op1));
break;
} }
return sb.toString(); return sb.toString();
@@ -0,0 +1,82 @@
package com.loomcom.symon;
import com.loomcom.symon.devices.Memory;
import com.loomcom.symon.exceptions.MemoryAccessException;
import org.junit.*;
import static org.junit.Assert.*;
public class CpuIndexedIndirectModeTest {
protected Cpu cpu;
protected Bus bus;
protected Memory mem;
@Before
public void runBeforeEveryTest() throws Exception {
this.cpu = new Cpu();
this.bus = new Bus(0x0000, 0xffff);
this.mem = new Memory(0x0000, 0x10000);
bus.addCpu(cpu);
bus.addDevice(mem);
// Load the reset vector.
bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff);
bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8);
cpu.reset();
// Assert initial state
assertEquals(0, cpu.getAccumulator());
assertEquals(0, cpu.getXRegister());
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
}
@Test
public void test_LDA() throws Exception {
bus.write(0x008c, 0x3f);
bus.write(0x008d, 0xc4);
bus.write(0xc43f, 0x45);
cpu.setXRegister(0x0c);
bus.loadProgram(0xa1, 0x80); // LDA ($80,X)
cpu.step(1);
assertEquals(0x45, cpu.getAccumulator());
}
@Test
public void test_ORA() throws Exception {
bus.write(0x0012, 0x1f);
bus.write(0x0013, 0xc5);
bus.write(0xc51f, 0x31);
cpu.setXRegister(0x02);
cpu.setAccumulator(0x15);
bus.loadProgram(0x01, 0x10); // ORA ($10,X)
cpu.step(1);
assertEquals(0x35, cpu.getAccumulator());
assertEquals(0x31, bus.read(0xc51f));
}
@Test
public void test_AND() throws Exception {
bus.write(0x0012, 0x1f);
bus.write(0x0013, 0xc5);
bus.write(0xc51f, 0x31);
cpu.setXRegister(0x02);
cpu.setAccumulator(0x15);
bus.loadProgram(0x21, 0x10); // AND ($10,X)
cpu.step(1);
assertEquals(0x11, cpu.getAccumulator());
assertEquals(0x31, bus.read(0xc51f));
}
}
@@ -0,0 +1,84 @@
package com.loomcom.symon;
import com.loomcom.symon.devices.Memory;
import com.loomcom.symon.exceptions.MemoryAccessException;
import org.junit.*;
import static org.junit.Assert.*;
public class CpuIndirectIndexedModeTest {
protected Cpu cpu;
protected Bus bus;
protected Memory mem;
@Before
public void runBeforeEveryTest() throws Exception {
this.cpu = new Cpu();
this.bus = new Bus(0x0000, 0xffff);
this.mem = new Memory(0x0000, 0x10000);
bus.addCpu(cpu);
bus.addDevice(mem);
// Load the reset vector.
bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff);
bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8);
cpu.reset();
// Assert initial state
assertEquals(0, cpu.getAccumulator());
assertEquals(0, cpu.getXRegister());
assertEquals(0, cpu.getYRegister());
assertEquals(0x200, cpu.getProgramCounter());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x20, cpu.getProcessorStatus());
}
@Test
public void test_LDA() throws Exception {
assertEquals(cpu.toString(), 0x00, cpu.getAccumulator());
bus.write(0x0014, 0x00);
bus.write(0x0015, 0xd8);
bus.write(0xd828, 0x03);
cpu.setYRegister(0x28);
bus.loadProgram(0xb1, 0x14); // LDA ($14),Y
cpu.step(1);
assertEquals(0x03, cpu.getAccumulator());
}
@Test
public void test_ORA() throws Exception {
bus.write(0x0014, 0x00);
bus.write(0x0015, 0xd8);
bus.write(0xd828, 0xe3);
cpu.setYRegister(0x28);
cpu.setAccumulator(0x32);
bus.loadProgram(0x11, 0x14); // ORA ($14),Y
cpu.step(1);
assertEquals(0xf3, cpu.getAccumulator());
assertEquals(0xe3, bus.read(0xd828));
}
@Test
public void test_AND() throws Exception {
bus.write(0x0014, 0x00);
bus.write(0x0015, 0xd8);
bus.write(0xd828, 0xe3);
cpu.setYRegister(0x28);
cpu.setAccumulator(0x32);
bus.loadProgram(0x31, 0x14); // AND ($14),Y
cpu.step(1);
assertEquals(0x22, cpu.getAccumulator());
assertEquals(0xe3, bus.read(0xd828));
}
}