mirror of
https://github.com/sethm/symon.git
synced 2024-06-21 17:29:46 +00:00
Add interrupt flag to CPU
This commit is contained in:
parent
3d36cd5460
commit
0c5035fc56
|
@ -151,6 +151,18 @@ public class Bus {
|
||||||
throw new MemoryAccessException("Bus write failed. No device at address " + String.format("$%04X", address));
|
throw new MemoryAccessException("Bus write failed. No device at address " + String.format("$%04X", address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assertInterrupt() {
|
||||||
|
if (cpu != null) {
|
||||||
|
cpu.assertInterrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearInterrupt() {
|
||||||
|
if (cpu != null) {
|
||||||
|
cpu.clearInterrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public SortedSet<Device> getDevices() {
|
public SortedSet<Device> getDevices() {
|
||||||
// Expose a copy of the device list, not the original
|
// Expose a copy of the device list, not the original
|
||||||
return new TreeSet<Device>(devices);
|
return new TreeSet<Device>(devices);
|
||||||
|
|
|
@ -113,7 +113,9 @@ public class Cpu implements InstructionTable {
|
||||||
* Reset the CPU to known initial values.
|
* Reset the CPU to known initial values.
|
||||||
*/
|
*/
|
||||||
public void reset() throws MemoryAccessException {
|
public void reset() throws MemoryAccessException {
|
||||||
// Registers
|
/* TODO: In reality, the stack pointer could be anywhere
|
||||||
|
on the stack after reset. This non-deterministic behavior might be
|
||||||
|
worth while to simulate. */
|
||||||
state.sp = 0xff;
|
state.sp = 0xff;
|
||||||
|
|
||||||
// Set the PC to the address stored in the reset vector
|
// Set the PC to the address stored in the reset vector
|
||||||
|
@ -131,6 +133,8 @@ public class Cpu implements InstructionTable {
|
||||||
state.overflowFlag = false;
|
state.overflowFlag = false;
|
||||||
state.negativeFlag = false;
|
state.negativeFlag = false;
|
||||||
|
|
||||||
|
state.interruptAsserted = false;
|
||||||
|
|
||||||
// Clear illegal opcode trap.
|
// Clear illegal opcode trap.
|
||||||
state.opTrap = false;
|
state.opTrap = false;
|
||||||
|
|
||||||
|
@ -1161,6 +1165,20 @@ public class Cpu implements InstructionTable {
|
||||||
return state.getStatusFlag();
|
return state.getStatusFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulate transition from logic-high to logic-low on the INT line.
|
||||||
|
*/
|
||||||
|
public void assertInterrupt() {
|
||||||
|
state.interruptAsserted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulate transition from logic-low to logic-high of the INT line.
|
||||||
|
*/
|
||||||
|
public void clearInterrupt() {
|
||||||
|
state.interruptAsserted = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push an item onto the stack, and decrement the stack counter.
|
* Push an item onto the stack, and decrement the stack counter.
|
||||||
* Will wrap-around if already at the bottom of the stack (This
|
* Will wrap-around if already at the bottom of the stack (This
|
||||||
|
@ -1305,6 +1323,8 @@ public class Cpu implements InstructionTable {
|
||||||
public int[] args = new int[2];
|
public int[] args = new int[2];
|
||||||
public int instSize;
|
public int instSize;
|
||||||
public boolean opTrap;
|
public boolean opTrap;
|
||||||
|
/* True if the INT line was held low */
|
||||||
|
public boolean interruptAsserted;
|
||||||
|
|
||||||
/* Status Flag Register bits */
|
/* Status Flag Register bits */
|
||||||
public boolean carryFlag;
|
public boolean carryFlag;
|
||||||
|
@ -1341,6 +1361,7 @@ public class Cpu implements InstructionTable {
|
||||||
this.args[1] = s.args[1];
|
this.args[1] = s.args[1];
|
||||||
this.instSize = s.instSize;
|
this.instSize = s.instSize;
|
||||||
this.opTrap = s.opTrap;
|
this.opTrap = s.opTrap;
|
||||||
|
this.interruptAsserted = s.interruptAsserted;
|
||||||
this.carryFlag = s.carryFlag;
|
this.carryFlag = s.carryFlag;
|
||||||
this.negativeFlag = s.negativeFlag;
|
this.negativeFlag = s.negativeFlag;
|
||||||
this.zeroFlag = s.zeroFlag;
|
this.zeroFlag = s.zeroFlag;
|
||||||
|
@ -1349,7 +1370,7 @@ public class Cpu implements InstructionTable {
|
||||||
this.breakFlag = s.breakFlag;
|
this.breakFlag = s.breakFlag;
|
||||||
this.overflowFlag = s.overflowFlag;
|
this.overflowFlag = s.overflowFlag;
|
||||||
this.stepCounter = s.stepCounter;
|
this.stepCounter = s.stepCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string formatted for the trace log.
|
* Returns a string formatted for the trace log.
|
||||||
|
|
|
@ -10,113 +10,129 @@ import com.loomcom.symon.exceptions.*;
|
||||||
*/
|
*/
|
||||||
public class BusTest extends TestCase {
|
public class BusTest extends TestCase {
|
||||||
|
|
||||||
public BusTest(String testName) {
|
public BusTest(String testName) {
|
||||||
super(testName);
|
super(testName);
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return new TestSuite(BusTest.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCreatingWithStartAndEndAddresses() {
|
|
||||||
Bus b = null;
|
|
||||||
|
|
||||||
b = new Bus(0x00, 0xff);
|
|
||||||
assertEquals(0x00, b.startAddress());
|
|
||||||
assertEquals(0xff, b.endAddress());
|
|
||||||
|
|
||||||
b = new Bus(0x20, 0xea);
|
|
||||||
assertEquals(0x20, b.startAddress());
|
|
||||||
assertEquals(0xea, b.endAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCreatingWithSize() {
|
|
||||||
Bus b = null;
|
|
||||||
|
|
||||||
b = new Bus(256);
|
|
||||||
assertEquals(0x00, b.startAddress());
|
|
||||||
assertEquals(0xff, b.endAddress());
|
|
||||||
|
|
||||||
b = new Bus(4096);
|
|
||||||
assertEquals(0x000, b.startAddress());
|
|
||||||
assertEquals(0xfff, b.endAddress());
|
|
||||||
|
|
||||||
b = new Bus(65536);
|
|
||||||
assertEquals(0x0000, b.startAddress());
|
|
||||||
assertEquals(0xffff, b.endAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAddDevice() throws MemoryRangeException {
|
|
||||||
Device memory = new Memory(0x0000, 0x00ff, true);
|
|
||||||
Device rom = new Memory(0x0100, 0x02ff, false);
|
|
||||||
|
|
||||||
Bus b = new Bus(0x0000, 0xffff);
|
|
||||||
|
|
||||||
assertEquals(0, b.getDevices().size());
|
|
||||||
b.addDevice(memory);
|
|
||||||
assertEquals(1, b.getDevices().size());
|
|
||||||
b.addDevice(rom);
|
|
||||||
assertEquals(2, b.getDevices().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testOverlappingDevicesShouldFail() throws MemoryRangeException {
|
|
||||||
Device memory = new Memory(0x0000, 0x0100, true);
|
|
||||||
Device rom = new Memory(0x00ff, 0x0200, false);
|
|
||||||
|
|
||||||
Bus b = new Bus(0x0000, 0xffff);
|
|
||||||
|
|
||||||
b.addDevice(memory);
|
|
||||||
|
|
||||||
try {
|
|
||||||
b.addDevice(rom);
|
|
||||||
fail("Should have thrown a MemoryRangeException.");
|
|
||||||
} catch (MemoryRangeException ex) {
|
|
||||||
// expected
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void testIsCompleteWithFirstDeviceNotStartingAtStartAddress() throws MemoryRangeException {
|
public static Test suite() {
|
||||||
Device memory = new Memory(0x00ff, 0xff00, true);
|
return new TestSuite(BusTest.class);
|
||||||
|
}
|
||||||
|
|
||||||
Bus b = new Bus(0x0000, 0xffff);
|
public void testCreatingWithStartAndEndAddresses() {
|
||||||
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
Bus b = null;
|
||||||
b.addDevice(memory);
|
|
||||||
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIsCompleteWithOneDevice() throws MemoryRangeException {
|
b = new Bus(0x00, 0xff);
|
||||||
Device memory = new Memory(0x0000, 0xffff, true);
|
assertEquals(0x00, b.startAddress());
|
||||||
Bus b = new Bus(0x0000, 0xffff);
|
assertEquals(0xff, b.endAddress());
|
||||||
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
|
||||||
b.addDevice(memory);
|
|
||||||
assertTrue("Address space should have been complete!", b.isComplete());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIsCompleteWithTwoDevices() throws MemoryRangeException {
|
b = new Bus(0x20, 0xea);
|
||||||
Device memory = new Memory(0x0000, 0x7fff, true);
|
assertEquals(0x20, b.startAddress());
|
||||||
Device rom = new Memory(0x8000, 0xffff, false);
|
assertEquals(0xea, b.endAddress());
|
||||||
|
}
|
||||||
|
|
||||||
Bus b = new Bus(0x0000, 0xffff);
|
public void testCreatingWithSize() {
|
||||||
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
Bus b = null;
|
||||||
b.addDevice(memory);
|
|
||||||
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
|
||||||
b.addDevice(rom);
|
|
||||||
assertTrue("Address space should have been complete!", b.isComplete());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIsCompleteWithThreeDevices() throws MemoryRangeException {
|
b = new Bus(256);
|
||||||
Device memory = new Memory(0x0000, 0x7fff, true);
|
assertEquals(0x00, b.startAddress());
|
||||||
Device rom1 = new Memory(0x8000, 0xBfff, false);
|
assertEquals(0xff, b.endAddress());
|
||||||
Device rom2 = new Memory(0xC000, 0xffff, false);
|
|
||||||
|
|
||||||
Bus b = new Bus(0x0000, 0xffff);
|
b = new Bus(4096);
|
||||||
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
assertEquals(0x000, b.startAddress());
|
||||||
b.addDevice(memory);
|
assertEquals(0xfff, b.endAddress());
|
||||||
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
|
||||||
b.addDevice(rom1);
|
b = new Bus(65536);
|
||||||
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
assertEquals(0x0000, b.startAddress());
|
||||||
b.addDevice(rom2);
|
assertEquals(0xffff, b.endAddress());
|
||||||
assertTrue("Address space should have been complete!", b.isComplete());
|
}
|
||||||
}
|
|
||||||
|
public void testAddDevice() throws MemoryRangeException {
|
||||||
|
Device memory = new Memory(0x0000, 0x00ff, true);
|
||||||
|
Device rom = new Memory(0x0100, 0x02ff, false);
|
||||||
|
|
||||||
|
Bus b = new Bus(0x0000, 0xffff);
|
||||||
|
|
||||||
|
assertEquals(0, b.getDevices().size());
|
||||||
|
b.addDevice(memory);
|
||||||
|
assertEquals(1, b.getDevices().size());
|
||||||
|
b.addDevice(rom);
|
||||||
|
assertEquals(2, b.getDevices().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOverlappingDevicesShouldFail() throws MemoryRangeException {
|
||||||
|
Device memory = new Memory(0x0000, 0x0100, true);
|
||||||
|
Device rom = new Memory(0x00ff, 0x0200, false);
|
||||||
|
|
||||||
|
Bus b = new Bus(0x0000, 0xffff);
|
||||||
|
|
||||||
|
b.addDevice(memory);
|
||||||
|
|
||||||
|
try {
|
||||||
|
b.addDevice(rom);
|
||||||
|
fail("Should have thrown a MemoryRangeException.");
|
||||||
|
} catch (MemoryRangeException ex) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsCompleteWithFirstDeviceNotStartingAtStartAddress() throws MemoryRangeException {
|
||||||
|
Device memory = new Memory(0x00ff, 0xff00, true);
|
||||||
|
|
||||||
|
Bus b = new Bus(0x0000, 0xffff);
|
||||||
|
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
||||||
|
b.addDevice(memory);
|
||||||
|
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsCompleteWithOneDevice() throws MemoryRangeException {
|
||||||
|
Device memory = new Memory(0x0000, 0xffff, true);
|
||||||
|
Bus b = new Bus(0x0000, 0xffff);
|
||||||
|
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
||||||
|
b.addDevice(memory);
|
||||||
|
assertTrue("Address space should have been complete!", b.isComplete());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsCompleteWithTwoDevices() throws MemoryRangeException {
|
||||||
|
Device memory = new Memory(0x0000, 0x7fff, true);
|
||||||
|
Device rom = new Memory(0x8000, 0xffff, false);
|
||||||
|
|
||||||
|
Bus b = new Bus(0x0000, 0xffff);
|
||||||
|
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
||||||
|
b.addDevice(memory);
|
||||||
|
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
||||||
|
b.addDevice(rom);
|
||||||
|
assertTrue("Address space should have been complete!", b.isComplete());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsCompleteWithThreeDevices() throws MemoryRangeException {
|
||||||
|
Device memory = new Memory(0x0000, 0x7fff, true);
|
||||||
|
Device rom1 = new Memory(0x8000, 0xBfff, false);
|
||||||
|
Device rom2 = new Memory(0xC000, 0xffff, false);
|
||||||
|
|
||||||
|
Bus b = new Bus(0x0000, 0xffff);
|
||||||
|
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
||||||
|
b.addDevice(memory);
|
||||||
|
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
||||||
|
b.addDevice(rom1);
|
||||||
|
assertFalse("Address space was unexpectedly complete!", b.isComplete());
|
||||||
|
b.addDevice(rom2);
|
||||||
|
assertTrue("Address space should have been complete!", b.isComplete());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSetAndClearInterrupt() throws Exception {
|
||||||
|
Bus b = new Bus(0x0000, 0xffff);
|
||||||
|
Cpu c = new Cpu();
|
||||||
|
b.addCpu(c);
|
||||||
|
|
||||||
|
assertFalse(c.getCpuState().interruptAsserted);
|
||||||
|
|
||||||
|
b.assertInterrupt();
|
||||||
|
|
||||||
|
assertTrue(c.getCpuState().interruptAsserted);
|
||||||
|
|
||||||
|
b.clearInterrupt();
|
||||||
|
|
||||||
|
assertFalse(c.getCpuState().interruptAsserted);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user