/*
TestInsts9900.java
(c) 2013 Ed Swartz
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
*/
package v9t9.machine.common.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Before;
import org.junit.Test;
import v9t9.common.client.ISettingsHandler;
import v9t9.common.machine.IMachine;
import v9t9.common.machine.IMachineModel;
import v9t9.common.memory.IMemoryDomain;
import v9t9.common.settings.BasicSettingsHandler;
import v9t9.machine.ti99.cpu.CpuState9900;
import v9t9.machine.ti99.machine.StandardTI994AMachineModel;
import v9t9.machine.ti99.memory.ExpRamArea;
public class TestCycles9900 {
private IMachine machine;
private ISettingsHandler settings;
private CpuState9900 cpuState;
private IMemoryDomain console;
@Before
public void setup() throws Exception {
IMachineModel model = new StandardTI994AMachineModel();
assertNotNull(model);
settings = new BasicSettingsHandler();
machine = model.createMachine(settings);
settings.get(ExpRamArea.settingExpRam).setBoolean(true);
cpuState = (CpuState9900) machine.getCpu().getState();
console = machine.getConsole();
}
@Test
public void testLimi() throws Exception {
console.writeWord(0x8300, (short) 0x0300); // LIMI >0
console.writeWord(0x8302, (short) 0x0000);
console.writeWord(0xa000, (short) 0x0300); // LIMI >0
console.writeWord(0xa002, (short) 0x0000);
// minimal
int min = 16;
assertCycles(0x83e0, 0x8300, min);
// fetch instr from slow
assertCycles(0x83e0, 0xA000, min + 8);
// fetch ops from slow
assertCycles(0xA020, 0x8300, min);
// fetch instr & ops from slow
assertCycles(0xA020, 0xA000, min + 8);
}
@Test
public void testClr() throws Exception {
console.writeWord(0x8300, (short) 0x4c2); // CLR R2
console.writeWord(0xa000, (short) 0x4c2); // CLR R2
// minimal
int min = 10;
assertCycles(0x83e0, 0x8300, min);
// fetch instr from slow
assertCycles(0x83e0, 0xA000, min + 4);
// fetch ops from slow
assertCycles(0xA020, 0x8300, min + 8);
// fetch instr & ops from slow
assertCycles(0xA020, 0xA000, min + 4 + 8);
}
@Test
public void testClrMem() throws Exception {
console.writeWord(0x8300, (short) 0x4e0); // CLR @>83e0
console.writeWord(0x8302, (short) 0x83e0);
console.writeWord(0x8310, (short) 0x4e0); // CLR @>f000
console.writeWord(0x8312, (short) 0xf000); //
console.writeWord(0xA000, (short) 0x4e0); // CLR @>83e0
console.writeWord(0xA002, (short) 0x83e0);
console.writeWord(0xa010, (short) 0x4e0); // CLR @>f000
console.writeWord(0xa012, (short) 0xf000); //
int min = 10 + 8 /* @>xxxx */;
// minimal
assertCycles(0x83e0, 0x8300, min);
// fetch instr + op immed from slow
assertCycles(0x83e0, 0xA000, min + 8);
// fetch ops from slow
assertCycles(0x83e0, 0x8310, min + 8);
// fetch instr & ops from slow
assertCycles(0x83e0, 0xA010, min + 8 + 8);
}
@Test
public void testClrInd() throws Exception {
console.writeWord(0x8300, (short) 0x4D0); // CLR *R0
console.writeWord(0x8310, (short) 0x4D1); // CLR *R1
console.writeWord(0xA000, (short) 0x4D0); // CLR *R0
console.writeWord(0xA010, (short) 0x4D1); // CLR *R1
// R0 and R1
console.writeWord(0x83e0, (short) 0x83c0);
console.writeWord(0x83e2, (short) 0xF000);
console.writeWord(0xA020, (short) 0x83c0);
console.writeWord(0xA022, (short) 0xF000);
int min = 10 + 4 /* *Rx */;
// minimal: R2 and *R2 in fast
assertCycles(0x83e0, 0x8300, min);
// *R2 in slow
assertCycles(0x83e0, 0x8310, min + 8);
// fetch instr from slow
assertCycles(0x83e0, 0xA000, min + 4);
// *R2 in slow
assertCycles(0x83e0, 0xA010, min + 4 + 8);
// fetch ops from slow
assertCycles(0xa020, 0x8300, min + 4);
// *R2 in slow
assertCycles(0xa020, 0x8310, min + 4 + 8);
// fetch instr & ops from slow
assertCycles(0xa020, 0xA000, min + 4 + 4);
// *R2 in slow
assertCycles(0xa020, 0xA010, min + 4 + 4 + 8);
}
@Test
public void testSrl() throws Exception {
console.writeWord(0x8300, (short) 0x942); // SRL R2, 4
console.writeWord(0xa000, (short) 0x942); // SRL R2, 4
// minimal
int min = 12 + 2 * 4 /* per shift */;
assertCycles(0x83e0, 0x8300, min);
// fetch instr from slow
assertCycles(0x83e0, 0xA000, min + 4);
// fetch ops from slow
assertCycles(0xA020, 0x8300, min + 8);
// fetch instr & ops from slow
assertCycles(0xA020, 0xA000, min + 4 + 8);
}
@Test
public void testSrlVar() throws Exception {
console.writeWord(0x8300, (short) 0x902); // SRL R2, 0
console.writeWord(0xa000, (short) 0x902); // SRL R2, 0
console.writeWord(0x83e0, (short) 5);
console.writeWord(0xA020, (short) 5);
// minimal
int min = 20 + 2 * 5 /* per shift */;
assertCycles(0x83e0, 0x8300, min);
// fetch instr from slow
assertCycles(0x83e0, 0xA000, min + 4);
// fetch ops from slow
assertCycles(0xA020, 0x8300, min + 8 + 4);
// fetch instr & ops from slow
assertCycles(0xA020, 0xA000, min + 4 + 8 + 4);
}
@Test
public void testMovVdp() throws Exception {
console.writeWord(0x8300, (short) 0xD804); // MOVB R4, @>837C
console.writeWord(0x8302, (short) 0x837C);
console.writeWord(0xA000, (short) 0xD804); // MOVB R4, @>837C
console.writeWord(0xA002, (short) 0x837C);
int min = 14 + 8 /* @>... */;
// minimal: opc and dest in fast
assertCycles(0x83e0, 0x8300, min);
// opc in slow
assertCycles(0x83e0, 0xA000, min + 8);
// wp in slow
assertCycles(0xa020, 0x8300, min + 4);
// wp + opc in slow
assertCycles(0xa020, 0xA000, min + 8 + 4);
}
@Test
public void testLdcr() throws Exception {
console.writeWord(0x8300, (short) 0x31C1); // LDCR R1,7
console.writeWord(0xa000, (short) 0x31C1); // LDCR R1,7
// minimal
int min = 20 + 2 * 7 /* per bit */;
assertCycles(0x83e0, 0x8300, min);
// fetch instr from slow
assertCycles(0x83e0, 0xA000, min + 4);
// fetch ops from slow (read R1, R12)
assertCycles(0xA020, 0x8300, min + 4 + 4);
// fetch instr & ops from slow (read R1, R12)
assertCycles(0xA020, 0xA000, min + 4 + 4 + 4);
}
@Test
public void testStcr() throws Exception {
console.writeWord(0x8300, (short) 0x35C1); // STCR R1,7
console.writeWord(0xa000, (short) 0x35C1); // STCR R1,7
// minimal
int min = 42;
assertCycles(0x83e0, 0x8300, min);
// fetch instr from slow
assertCycles(0x83e0, 0xA000, min + 4);
// fetch ops from slow (read R1, R12, write R1)
assertCycles(0xA020, 0x8300, min + 4 + 4 + 4);
// fetch instr & ops from slow (read R1, R12, write R1)
assertCycles(0xA020, 0xA000, min + 4 + 4 + 4 + 4);
}
@Test
public void testStcrAutoInc() throws Exception {
console.writeWord(0x8300, (short) 0x3531); // STCR *R1+,4
console.writeWord(0x8302, (short) 0x3532); // STCR *R2+,4
console.writeWord(0x8310, (short) 0x3431); // STCR *R1+,0 // 16
console.writeWord(0x8312, (short) 0x3432); // STCR *R2+,0 // 16
console.writeWord(0xa000, (short) 0x3531); // STCR *R1+,4
console.writeWord(0xa002, (short) 0x3532); // STCR *R2+,4
console.writeWord(0xa010, (short) 0x3431); // STCR *R1+,0 // 16
console.writeWord(0xa012, (short) 0x3432); // STCR *R2+,0 // 16
// minimal
int min4 = 42 /* 1-7 */ + 6 /* *R1+ @ byte */;
int min16 = 60 /* 16 */ + 8 /* *R1+ @ word */;
console.writeWord(0x83E2, (short) 0x83A0);
console.writeWord(0x83E4, (short) 0xF000);
console.writeWord(0xA022, (short) 0x83A0);
console.writeWord(0xA024, (short) 0xF000);
// all regs fast
assertCycles(0x83e0, 0x8300, min4);
assertCycles(0x83e0, 0x8310, min16);
// store partial to slow (4 + 4)
assertCycles(0x83e0, 0x8302, min4 + 8);
assertCycles(0x83e0, 0x8312, min16 + 8);
// fetch instr from slow, *R1 fast
assertCycles(0x83e0, 0xA000, min4 + 4);
assertCycles(0x83e0, 0xA010, min16 + 4);
// *R1 slow
assertCycles(0x83e0, 0xA002, min4 + 4 + 8);
assertCycles(0x83e0, 0xA012, min16 + 4 + 8);
// fetch ops from slow, read R12, r/w slow R1
assertCycles(0xA020, 0x8300, min4 + 4 + 8);
assertCycles(0xA020, 0x8310, min16 + 4 + 8);
// *R1 slow
assertCycles(0xA020, 0x8302, min4 + 4 + 8 + 8);
assertCycles(0xA020, 0x8312, min16 + 4 + 8 + 8);
// fetch instr & ops from slow
assertCycles(0xA020, 0xA000, min4 + 4 + 4 + 8);
assertCycles(0xA020, 0xA010, min16 + 4 + 4 + 8);
// *R1 slow
assertCycles(0xA020, 0xA002, min4 + 4 + 4 + 8 + 8);
assertCycles(0xA020, 0xA012, min16 + 4 + 4 + 8 + 8);
}
private void assertCycles(int wp, int pc, int expCycles) {
cpuState.getStatus().expand((short) 0);
cpuState.setWP((short) wp);
cpuState.setPC((short) pc);
//CycleCounts counts = machine.getCpu().getCycleCounts();
//counts.getAndResetTotal();
machine.getCpu().resetCycleCounts();
machine.getExecutor().getInterpreter().executeChunk(1, machine.getExecutor());
assertEquals(expCycles, machine.getCpu().getCurrentCycleCount());
}
}