diff --git a/8080EX1.nas b/8080EX1.nas new file mode 100644 index 0000000..3740382 Binary files /dev/null and b/8080EX1.nas differ diff --git a/README.md b/README.md index 27d421d..ec53ffa 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.codingrodent.microprocessor/Z80Processor/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.codingrodent.microprocessor/Z80Processor) [![Maven Central](https://img.shields.io/jenkins/s/https/jenkins.qa.ubuntu.com/precise-desktop-amd64_default.svg)](https://img.shields.io/jenkins/s/https/jenkins.qa.ubuntu.com) -# Z80 Processor in Java +# Z80 Processor in Java 11 Z80Processor is a an implementation of the Mostek / Zilog Z80 processor in Java diff --git a/build.gradle b/build.gradle index 843b4b1..e6fad81 100644 --- a/build.gradle +++ b/build.gradle @@ -153,5 +153,5 @@ dependencies { } task wrapper(type: Wrapper) { - gradleVersion = '4.2.1' + gradleVersion = '4.10.3' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index deedc7f..0000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 0d32ce7..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Mon Oct 09 16:17:18 BST 2017 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-bin.zip diff --git a/src/main/java/com/codingrodent/microprocessor/Z80/Z80Core.java b/src/main/java/com/codingrodent/microprocessor/Z80/Z80Core.java index 69ca6f6..7015ca3 100644 --- a/src/main/java/com/codingrodent/microprocessor/Z80/Z80Core.java +++ b/src/main/java/com/codingrodent/microprocessor/Z80/Z80Core.java @@ -61,9 +61,9 @@ public Z80Core(IMemory ram, IBaseDevice io) { resetAddress = 0x0000; } - /* + /* * Public interfaces to processor control functions - */ + */ /** * Indicate when a block move instruction is in progress, LDIR, CPDR etc. May be sampled during repetitive cycles of @@ -1294,18 +1294,18 @@ private void decodeOneByteInstruction(int opcode) throws ProcessorException { /* * ***************************************************************************** - * - * Extended Instruction area - * - * ***************************************************************************** - */ + * + * Extended Instruction area + * + * ***************************************************************************** + */ /* * ***************************************************************************** - * - * CB Bit twiddling and shifting instructions - * - * ***************************************************************************** - */ + * + * CB Bit twiddling and shifting instructions + * + * ***************************************************************************** + */ private void extendedCB() { instruction = ram.readByte(reg_PC); incPC(); @@ -2356,13 +2356,13 @@ private void extendedCB() { } } - /* + /* * ***************************************************************************** - * - * Extended Instruction area - * - * ***************************************************************************** - */ + * + * Extended Instruction area + * + * ***************************************************************************** + */ private void extendedED() throws ProcessorException { instruction = ram.readByte(reg_PC); @@ -2844,13 +2844,13 @@ private void extendedED() throws ProcessorException { } } - /* + /* + * ***************************************************************************** + * + * IX and IY index register processing + * * ***************************************************************************** - * - * IX and IY index register processing - * - * ***************************************************************************** - */ + */ /* IX register processing */ private void extendedDD() throws ProcessorException { @@ -2866,7 +2866,7 @@ private void extendedFD() throws ProcessorException { reg_IY = reg_index; } - /* generic index register processing */ + /* generic index register processing */ private void extendedDDFD() throws ProcessorException { instruction = ram.readByte(reg_PC); @@ -3787,11 +3787,11 @@ private void extendedDDFD() throws ProcessorException { /* * ***************************************************************************** - * - * CB Bit twiddling and shifting instructions for Index - * - * ***************************************************************************** - */ + * + * CB Bit twiddling and shifting instructions for Index + * + * ***************************************************************************** + */ private void extendedIndexCB() { instruction = ram.readByte(reg_PC + 1); // fudge for DD CB dd ii tStates = tStates + OPCODE_INDEXED_CB_STATES[instruction]; @@ -4841,8 +4841,8 @@ private void extendedIndexCB() { } /* - * return an 8 bit register based on its code 000 -> 111 - */ + * return an 8 bit register based on its code 000 -> 111 + */ private int get8BitRegisterForIO(int reg) { switch (reg) { case 0: { @@ -4873,8 +4873,8 @@ private int get8BitRegisterForIO(int reg) { } /* - * return a 16 bit register based on its code 00 -> 11 - */ + * return a 16 bit register based on its code 00 -> 11 + */ private int get16BitRegister(int reg) { switch (reg) { case 0: { @@ -4893,8 +4893,8 @@ private int get16BitRegister(int reg) { } /* - * set a 16 bit register based on its code 00 -> 11 - */ + * set a 16 bit register based on its code 00 -> 11 + */ private void set16BitRegister(int value, int reg) { switch (reg) { case 0: { @@ -4917,8 +4917,8 @@ private void set16BitRegister(int value, int reg) { } /* - * increment (and wrap) the program counter - */ + * increment (and wrap) the program counter + */ private void incPC() { reg_PC++; reg_PC = reg_PC & MAX_ADDRESS; @@ -4940,8 +4940,8 @@ private void dec2PC() { } /* - * increment / decrement (and wrap) the stack pointer - */ + * increment / decrement (and wrap) the stack pointer + */ private void inc2SP() { reg_SP = reg_SP + 2; reg_SP = reg_SP & MAX_ADDRESS; @@ -4952,9 +4952,9 @@ private void dec2SP() { reg_SP = reg_SP & MAX_ADDRESS; } - /* - * ALU Operations - */ + /* + * ALU Operations + */ /* half carry flag control */ private void setHalfCarryFlagAdd(int left, int right, int carry) { @@ -4964,11 +4964,6 @@ private void setHalfCarryFlagAdd(int left, int right, int carry) { } /* half carry flag control */ - /* - * private void setHalfCarryFlagAdd16(int left, int right, int carry) { left = left & 0x0FFF; right = right & - * 0x0FFF; setH( (right + left + carry) > 0x0FFF); } - */ - /* half carry flag control */ private void setHalfCarryFlagAdd(int left, int right) { left = left & 0x000F; right = right & 0x000F; @@ -4990,11 +4985,11 @@ private void setHalfCarryFlagSub(int left, int right, int carry) { } /* half carry flag control */ - /* + /* * private void setHalfCarryFlagSub16(int left, int right, int carry) { left = left & 0x0FFF; right = right & - * 0x0FFF; setH ( left < (right+carry) ); } - */ - /* 2's compliment overflow flag control */ + * 0x0FFF; setH ( left < (right+carry) ); } + */ + /* 2's compliment overflow flag control */ private void setOverflowFlagAdd(int left, int right, int carry) { if (left > 127) left = left - 256; @@ -5006,12 +5001,7 @@ private void setOverflowFlagAdd(int left, int right, int carry) { /* 2's compliment overflow flag control */ private void setOverflowFlagAdd(int left, int right) { - if (left > 127) - left = left - 256; - if (right > 127) - right = right - 256; - left = left + right; - setPV((left < -128) || (left > 127)); + setOverflowFlagAdd(left, right, 0); } /* 2's compliment overflow flag control */ @@ -5036,12 +5026,7 @@ private void setOverflowFlagSub(int left, int right, int carry) { /* 2's compliment overflow flag control */ private void setOverflowFlagSub(int left, int right) { - if (left > 127) - left = left - 256; - if (right > 127) - right = right - 256; - left = left - right; - setPV((left < -128) || (left > 127)); + setOverflowFlagSub(left, right, 0); } /* 2's compliment overflow flag control */ @@ -5094,7 +5079,6 @@ private void ALU8BitAdc(int value) { /* 8 bit SUB */ private void ALU8BitSub(int value) { int local_reg_A = reg_A; - setHalfCarryFlagSub(local_reg_A, value); setOverflowFlagSub(local_reg_A, value); local_reg_A = local_reg_A - value; @@ -5134,10 +5118,7 @@ private void ALU8BitAnd(int value) { reg_A = reg_A & value; setS((reg_A & 0x0080) != 0); setZ(reg_A == 0); - // setH(); setPV(PARITY_TABLE[reg_A]); - // resetN(); - // resetC(); setUnusedFlags(reg_A); } @@ -5147,10 +5128,7 @@ private void ALU8BitOr(int value) { reg_A = reg_A | value; setS((reg_A & 0x0080) != 0); setZ(reg_A == 0); - // resetH(); setPV(PARITY_TABLE[reg_A]); - // resetN(); - // resetC(); setUnusedFlags(reg_A); } @@ -5160,23 +5138,19 @@ private void ALU8BitXor(int value) { reg_A = reg_A ^ value; setS((reg_A & 0x0080) != 0); setZ(reg_A == 0); - // resetH(); setPV(PARITY_TABLE[reg_A]); - // resetN(); - // resetC(); setUnusedFlags(reg_A); } /* 8 bit CP */ private void ALU8BitCp(int b) { - int a = reg_A; - int wans = a - b; - int ans = wans & 0xff; + final int a = reg_A; + final int wans = a - b; + final int ans = wans & 0xff; reg_F = 0x02; setS((ans & flag_S) != 0); set3((b & flag_3) != 0); set5((b & flag_5) != 0); - // if ( true ) setN(); setZ(ans == 0); setC((wans & 0x100) != 0); setH((((a & 0x0f) - (b & 0x0f)) & flag_H) != 0); @@ -5196,7 +5170,7 @@ private int ALU8BitInc(int value) { setS((value & 0x0080) != 0); value = value & 0x00ff; setZ(value == 0); - // resetN(); + resetN(); setUnusedFlags(value); return (value); } @@ -5317,7 +5291,7 @@ private void ALU16BitSBC(int regCode) { int a = getHL(); int b = get16BitRegister((byte) regCode); int c = getC() ? 1 : 0; - int lans = (a - b) - c; + int lans = a - b - c; int ans = lans & 0xffff; setS((ans & (flag_S << 8)) != 0); set3((ans & (0x08 << 8)) != 0); @@ -5335,8 +5309,8 @@ private void ALU16BitSBC(int regCode) { } /* - * varous register swap operations - */ + * varous register swap operations + */ private void EXAFAF() { int temp; @@ -5376,8 +5350,8 @@ private void EXX() { } /* - * test & set flag states - */ + * test & set flag states + */ private boolean getS() { return ((reg_F & flag_S) != 0); } @@ -5580,9 +5554,9 @@ private void setHL_ALT(int hl) { reg_L_ALT = hl & 0x00FF; } - /* - * shifts and rotates - */ + /* + * shifts and rotates + */ private void RLCA() { boolean carry = (reg_A & 0x0080) != 0; @@ -5642,7 +5616,7 @@ private void RRA() { } private void CPL() { - reg_A = (reg_A ^ 0x00FF) & 0x00FF; + reg_A = reg_A ^ 0x00FF; setH(); setN(); setUnusedFlags(reg_A); @@ -5689,15 +5663,14 @@ private void CCF() { } /* - * DAA is weird, can't find Zilog algorithm so using +0110 if Nibble>9 algorithm. - */ + * DAA is weird, can't find Zilog algorithm so using +0110 if Nibble>9 algorithm. + */ private void DAA() { - { int ans = reg_A; int incr = 0; boolean carry = getC(); if ((getH()) || ((ans & 0x0f) > 0x09)) { - incr |= 0x06; + incr = 0x06; } if (carry || (ans > 0x9f) || ((ans > 0x8f) && ((ans & 0x0f) > 0x09))) { incr |= 0x60; @@ -5716,7 +5689,6 @@ private void DAA() { else resetC(); // setC( carry ); setPV(PARITY_TABLE[ans]); // setPV( PARITY_TABLE[ ans ] ); - } } private int shiftGenericRLC(int temp) { @@ -5742,7 +5714,6 @@ private int shiftGenericRLC(int temp) { setPV(PARITY_TABLE[temp]); setUnusedFlags(temp); return temp; - } /** @@ -5762,7 +5733,6 @@ private int shiftGenericRL(int temp) { temp = temp | 0x01; // standard flag updates setS((temp & 0x0080) != 0); - resetH(); if ((temp & 0x0FF00) == 0) resetC(); else @@ -5773,6 +5743,7 @@ private int shiftGenericRL(int temp) { else resetZ(); setPV(PARITY_TABLE[temp]); + resetH(); resetN(); // put value back setUnusedFlags(temp); @@ -5878,9 +5849,6 @@ private int shiftGenericSLL(int temp) { temp = (temp << 1) | 0x01; // the fault // standard flag updates setS((temp & 0x0080) != 0); - // if ((temp & 0x00FF) == 0) - // setZ(); - // else resetZ(); resetH(); if ((temp & 0x0FF00) != 0) @@ -5934,7 +5902,6 @@ private int shiftGenericSRL(int temp) { setC((temp & 0x0001) != 0); temp = temp >> 1; // standard flag updates - // setS((temp & 0x0080) != 0); resetS(); setZ(temp == 0); resetH(); @@ -6003,8 +5970,8 @@ private void RLD() { } /* - * calls, jumps and returns + associated stack operations - */ + * calls, jumps and returns + associated stack operations + */ private void relativeJump() { reg_R++; int offset = ram.readByte(reg_PC); @@ -6048,7 +6015,6 @@ private void ret(boolean cc) { } else { tStates = tStates + 5; } - } private void ret() { @@ -6127,8 +6093,8 @@ private void rst(int code) { } /* - * Interrupt handling - */ + * Interrupt handling + */ private void DI() { IFF1 = false; EIDIFlag = true; @@ -6139,9 +6105,9 @@ private void EI() { EIDIFlag = true; } - /* - * IO port handling - */ + /* + * IO port handling + */ /* IN A,(NN) */ private void inAN() { @@ -6216,9 +6182,9 @@ private void outC(int reg) { io.IOWrite(getBC(), get8BitRegisterForIO(reg)); } - /* - * bit manipulation - */ + /* + * bit manipulation + */ private void testBit(int value, int bit) { // @@ -6271,53 +6237,54 @@ private void testBitInMemory(int bit) { testBitGeneric(bit, ram.readByte(getHL())); } - private void testBitGeneric(int bit, int temp) { + private void testBitGeneric(int bit, int value) { + int v = value; resetS(); switch (bit) { case 0: { - temp = temp & setBit0; + v = v & setBit0; break; } case 1: { - temp = temp & setBit1; + v = v & setBit1; break; } case 2: { - temp = temp & setBit2; + v = v & setBit2; break; } case 3: { - temp = temp & setBit3; + v = v & setBit3; break; } case 4: { - temp = temp & setBit4; + v = v & setBit4; break; } case 5: { - temp = temp & setBit5; + v = v & setBit5; break; } case 6: { - temp = temp & setBit6; + v = v & setBit6; break; } default: { - temp = temp & setBit7; - setS(temp != 0); + v = v & setBit7; + setS(v != 0); break; } } - setZ(0 == temp); - setPV(0 == temp); + setZ(0 == v); + setPV(0 == v); resetN(); setH(); } /* - * Increment / decrement repeat type instructions - */ - /* loads */ + * Increment / decrement repeat type instructions + */ + /* loads */ private void LDI() { reg_R++; int flags = reg_F; @@ -6331,11 +6298,11 @@ private void LDI() { resetN(); setPV(getBC() != 0); int temp = value + reg_A; - if ((temp & 0x00002) == 0) + if ((temp & 0x02) == 0) reset5(); else set5(); - if ((temp & 0x00008) == 0) + if ((temp & 0x08) == 0) reset3(); else set3(); @@ -6362,11 +6329,11 @@ private void LDD() { resetN(); setPV(getBC() != 0); int temp = reg_A + value; - if ((temp & 0x00002) == 0) + if ((temp & 0x02) == 0) reset5(); else set5(); - if ((temp & 0x00008) == 0) + if ((temp & 0x08) == 0) reset3(); else set3(); @@ -6382,20 +6349,19 @@ private void LDDR() { } /* - * block compares - */ + * block compares + */ private void CPI() { reg_R++; int value = ram.readByte(getHL()); - int result = reg_A - value; + int result = (reg_A - value) & lsb; setHL(ALU16BitInc(getHL())); setBC(ALU16BitDec(getBC())); // - if ((result & 0x0080) == 0) + if ((result & 0x80) == 0) resetS(); else setS(); - result = result & 0x00FF; if (result == 0) setZ(); else @@ -6426,15 +6392,14 @@ private void CPIR() { private void CPD() { reg_R++; int value = ram.readByte(getHL()); - int result = reg_A - value; + int result = (reg_A - value) & lsb; setHL(ALU16BitDec(getHL())); setBC(ALU16BitDec(getBC())); // - if ((result & 0x0080) == 0) + if ((result & 0x80) == 0) resetS(); else setS(); - result = result & lsb; if (result == 0) setZ(); else @@ -6445,11 +6410,11 @@ private void CPD() { // if (getH()) result--; - if ((result & 0x00002) == 0) + if ((result & 0x02) == 0) reset5(); else set5(); - if ((result & 0x00008) == 0) + if ((result & 0x08) == 0) reset3(); else set3(); @@ -6526,8 +6491,8 @@ private void OTDR() { } /* - * extended 16 bit loads for ED instructions - */ + * extended 16 bit loads for ED instructions + */ private void LDRegnnnnInd16Bit(int regCode) { int address = ram.readWord(reg_PC); int data = ram.readWord(address); @@ -6541,17 +6506,17 @@ private void LDnnnnRegInd16Bit(int regCode) { inc2PC(); } - /* - * odds & ends - */ + /* + * odds & ends + */ private void IM(int mode) { // interruptMode = mode; } /* - * special I reg loads - */ + * special I reg loads + */ private void LDAI() { reg_A = reg_I; setS((reg_A & flag_S) != 0); @@ -6566,9 +6531,9 @@ private void LDIA() { reg_I = reg_A; } - /* - * special R reg loads - */ + /* + * special R reg loads + */ private void LDAR() { reg_A = reg_R & 0x7F; @@ -6610,8 +6575,8 @@ private int getIndexAddress() { } /* - * Support for 8 bit index register manipulation (IX as IXH IXL) - */ + * Support for 8 bit index register manipulation (IX as IXH IXL) + */ private int getIndexAddressUndocumented(int reg) { switch (reg) { case 4: { @@ -6628,8 +6593,8 @@ private int getIndexAddressUndocumented(int reg) { } /* - * Support for 8 bit index register manipulation (IX as IXH IXL) - */ + * Support for 8 bit index register manipulation (IX as IXH IXL) + */ private void setIndexAddressUndocumented(int value, int reg) { switch (reg) { case 4: { @@ -6650,8 +6615,8 @@ private void setIndexAddressUndocumented(int value, int reg) { } /* - * return an 8 bit register based on its code 000 -> 111 - */ + * return an 8 bit register based on its code 000 -> 111 + */ private int get8BitRegisterIndexed(int reg) { switch (reg) { case 4: { diff --git a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTest.java b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTest.java index 7946f4a..ef56c8b 100644 --- a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTest.java +++ b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTest.java @@ -26,7 +26,7 @@ public class Z80CoreTest { @Before public void setUp() throws Exception { - z80Memory = new Z80Memory(); + z80Memory = new Z80Memory("NAS_Test.nas"); z80 = new Z80Core(z80Memory, new Z80IO()); z80.reset(); } @@ -35,38 +35,6 @@ public void setUp() throws Exception { public void tearDown() throws Exception { } - /** - * Test core by running test application this covers most instructions. Other tests are to 'mop up' uncovered - * regions - */ - @Test - public final void testCore() { - // Initial setup - assertEquals(z80.getProgramCounter(), 0x0000); - z80.setResetAddress(0x1234); - z80.reset(); - assertEquals(z80.getProgramCounter(), 0x1234); - z80.setProgramCounter(0x1000); - assertEquals(z80.getProgramCounter(), 0x1000); - // - // T states ? - assertEquals(0, z80.getTStates()); - // - // Ok, run the program - while (!z80.getHalt()) { - try { - z80.executeOneInstruction(); - // System.out.println(utilities.getWord(z80.getRegisterValue(RegisterNames.PC))); - } catch (ProcessorException e) { - System.out.println("Hardware crash, oops! " + e.getMessage()); - e.printStackTrace(); - } - } - assertTrue(z80.getTStates() > 0); - z80.resetTStates(); - assertEquals(0, z80.getTStates()); - } - /** * Check LDIR / LDDIR function */ diff --git a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestCB.java b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestCB.java index c80c690..f21c0cd 100644 --- a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestCB.java +++ b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestCB.java @@ -27,7 +27,7 @@ public class Z80CoreTestCB { @Before public void setUp() throws Exception { - z80Memory = new Z80Memory(); + z80Memory = new Z80Memory("NAS_Test.nas"); z80 = new Z80Core(z80Memory, new Z80IO()); z80.reset(); } diff --git a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestDDFD.java b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestDDFD.java index 9fff2bc..490a76b 100644 --- a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestDDFD.java +++ b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestDDFD.java @@ -26,7 +26,7 @@ public class Z80CoreTestDDFD { @Before public void setUp() throws Exception { - z80Memory = new Z80Memory(); + z80Memory = new Z80Memory("NAS_Test.nas"); z80 = new Z80Core(z80Memory, new Z80IO()); z80.reset(); } diff --git a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestED.java b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestED.java index e364aed..6f4c651 100644 --- a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestED.java +++ b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestED.java @@ -26,7 +26,7 @@ public class Z80CoreTestED { @Before public void setUp() throws Exception { - z80Memory = new Z80Memory(); + z80Memory = new Z80Memory("NAS_Test.nas"); z80 = new Z80Core(z80Memory, new Z80IO()); z80.reset(); } diff --git a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestInterrupts.java b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestInterrupts.java index 949f815..3316316 100644 --- a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestInterrupts.java +++ b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestInterrupts.java @@ -27,7 +27,7 @@ public class Z80CoreTestInterrupts { @Before public void setUp() throws Exception { - z80Memory = new Z80Memory(); + z80Memory = new Z80Memory("NAS_Test.nas"); z80 = new Z80Core(z80Memory, new Z80IO()); z80.reset(); } diff --git a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestUnimplemented.java b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestUnimplemented.java index 674aa1c..3be0a76 100644 --- a/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestUnimplemented.java +++ b/src/test/java/com/codingrodent/microprocessor/Z80/Z80CoreTestUnimplemented.java @@ -26,7 +26,7 @@ public class Z80CoreTestUnimplemented { @Before public void setUp() throws Exception { - z80Memory = new Z80Memory(); + z80Memory = new Z80Memory("NAS_Test.nas"); z80 = new Z80Core(z80Memory, new Z80IO()); z80.reset(); } diff --git a/src/test/java/com/codingrodent/microprocessor/Z80/Z80NasTest.java b/src/test/java/com/codingrodent/microprocessor/Z80/Z80NasTest.java new file mode 100644 index 0000000..15b0808 --- /dev/null +++ b/src/test/java/com/codingrodent/microprocessor/Z80/Z80NasTest.java @@ -0,0 +1,90 @@ +/* + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.codingrodent.microprocessor.Z80; + +import com.codingrodent.microprocessor.ProcessorException; +import com.codingrodent.microprocessor.support.*; +import org.junit.*; + +import static org.junit.Assert.*; + +public class Z80NasTest { + private Z80Core z80; + private Z80Memory z80Memory; + private int a =0; + + @Before + public void setUp() throws Exception { + z80Memory = new Z80Memory("NAS_Test.nas"); + z80 = new Z80Core(z80Memory, new Z80IO()); + z80.reset(); + } + + @After + public void tearDown() throws Exception { + } + + /** + * Test core by running test application this covers most instructions. Other tests are to 'mop up' uncovered + * regions + */ + @Test + public final void testCore() { + // Initial setup + assertEquals(z80.getProgramCounter(), 0x0000); + z80.setResetAddress(0x1234); + z80.reset(); + assertEquals(z80.getProgramCounter(), 0x1234); + z80.setProgramCounter(0x1000); + assertEquals(z80.getProgramCounter(), 0x1000); + // + // T states ? + assertEquals(0, z80.getTStates()); + // + // Ok, run the program + int c = 1000; + while (!z80.getHalt()) { + try { + // System.out.println(getRegs()); + a++; + z80.executeOneInstruction(); + } catch (ProcessorException e) { + System.out.println("Hardware crash, oops! " + e.getMessage()); + e.printStackTrace(); + } + c--; + // if (c<0) break; + } + assertTrue(z80.getTStates() > 0); + z80.resetTStates(); + assertEquals(0, z80.getTStates()); + assertEquals(0, z80.getTStates()); + } + + private String getRegs() { + return a+" >> Execute @" // + + Utilities.getWord(z80.getRegisterValue(CPUConstants.RegisterNames.PC)) // + + " : " + "00" + " SP:" + Utilities.getWord(z80.getRegisterValue(CPUConstants.RegisterNames.SP)) // + + " AF:" + Utilities.getByte(z80.getRegisterValue(CPUConstants.RegisterNames.A)) // + + Utilities.getByte(z80.getRegisterValue(CPUConstants.RegisterNames.F)) // + + " BC:" + Utilities.getWord(z80.getRegisterValue(CPUConstants.RegisterNames.BC)) // + + " DE:" + Utilities.getWord(z80.getRegisterValue(CPUConstants.RegisterNames.DE)) // + + " HL:" + Utilities.getWord(z80.getRegisterValue(CPUConstants.RegisterNames.HL)) // + + " IX:" + Utilities.getWord(z80.getRegisterValue(CPUConstants.RegisterNames.IX)) // + + " IY:" + Utilities.getWord(z80.getRegisterValue(CPUConstants.RegisterNames.IY)); // + + } + +} diff --git a/src/test/java/com/codingrodent/microprocessor/performance/TimedExecution.java b/src/test/java/com/codingrodent/microprocessor/performance/TimedExecution.java index 4bda9bc..25e15a2 100644 --- a/src/test/java/com/codingrodent/microprocessor/performance/TimedExecution.java +++ b/src/test/java/com/codingrodent/microprocessor/performance/TimedExecution.java @@ -37,7 +37,7 @@ public static void main(String[] args) { * Set up a computer with simple memory and I/O */ private void init() { - z80 = new Z80Core(new Z80Memory(), new Z80IOEcho()); + z80 = new Z80Core(new Z80Memory("NAS_Test.nas"), new Z80IOEcho()); z80.reset(); } diff --git a/src/test/java/com/codingrodent/microprocessor/support/Utilities.java b/src/test/java/com/codingrodent/microprocessor/support/Utilities.java index ceb2e87..b41833d 100644 --- a/src/test/java/com/codingrodent/microprocessor/support/Utilities.java +++ b/src/test/java/com/codingrodent/microprocessor/support/Utilities.java @@ -14,7 +14,7 @@ */ package com.codingrodent.microprocessor.support; -class Utilities { +public class Utilities { private final static String hexChar = "0123456789ABCDEF"; /* @@ -33,7 +33,7 @@ private static char getHexCharacter(final int value) { /* turn a byte into two hex digits */ - private static String getByte(final int value) { + public static String getByte(final int value) { char[] byteText = new char[2]; try { diff --git a/src/test/java/com/codingrodent/microprocessor/support/Z80Memory.java b/src/test/java/com/codingrodent/microprocessor/support/Z80Memory.java index a7aab58..654af60 100644 --- a/src/test/java/com/codingrodent/microprocessor/support/Z80Memory.java +++ b/src/test/java/com/codingrodent/microprocessor/support/Z80Memory.java @@ -22,7 +22,7 @@ public class Z80Memory implements IMemory { private final int[] memory = new int[65536]; - public Z80Memory() { + public Z80Memory(final String filename) { // Set all to HALT - stops runaway code for (int a = 0; a < memory.length; a++) { memory[a] = 0x76; @@ -32,8 +32,39 @@ public Z80Memory() { memory[0x31] = 0x00; // memory[0x32] = 0xC9; // ret // + // A very simple I/O routine to simulate CP/M BDOS string output calls + int addr = 0x05; + memory[addr++] = 0xC3; // jp + memory[addr++] = 0x45; // + memory[addr] = 0x00; // + + addr = 0x45; // get it out of teh way of RST addresses + memory[addr++] = 0x79; // ld a,c + memory[addr++] = 0xFE; // cp a, 09 + memory[addr++] = 0x09; // + memory[addr++] = 0xCA; // jp z + memory[addr++] = 0x4F; // + memory[addr++] = 0x00; // + // output single char BDOS 2 + memory[addr++] = 0x7B; // ld a,e + memory[addr++] = 0xD3; // out (00), a + memory[addr++] = 0x00; // + memory[addr++] = 0xC9; // ret + // Outtput string BDOS 6 + // addr 000F + memory[addr++] = 0x1A; // ld a,(de) + memory[addr++] = 0xFE; // cp a, '$' + memory[addr++] = 0x24; // + memory[addr++] = 0xC8; // ret z + memory[addr++] = 0xD3; // out (00), a + memory[addr++] = 0x00; // + memory[addr++] = 0x13; // inc de + memory[addr++] = 0xC3; // jp 0 + memory[addr++] = 0x4F; // + memory[addr] = 0x00; // + // try { - readHexDumpFile("NAS_Test.nas"); + readHexDumpFile(filename); } catch (Exception e) { e.printStackTrace(); } @@ -80,6 +111,7 @@ private void readHexDumpFile(String fileName) throws IOException { @Override // Read a byte from memory public int readByte(int address) { + // System.out.println("read " + Utilities.getByte(memory[address]) + " @ " + Utilities.getWord(address)); return memory[address]; } @@ -91,6 +123,8 @@ public int readWord(int address) { @Override public void writeByte(int address, int data) { + + // System.out.println("write " + Utilities.getByte(data) + " @ " + Utilities.getWord(address)); memory[address] = data; }