mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2026-01-22 16:16:17 +00:00
Fix up some oddities in the EightBit library
This commit is contained in:
@@ -18,19 +18,17 @@ namespace EightBit
|
||||
this.Bus.Poke(++address, value.Low);
|
||||
}
|
||||
|
||||
protected override Register16 FetchWord()
|
||||
protected override void FetchInto(Register16 into)
|
||||
{
|
||||
this.Intermediate.High = this.FetchByte();
|
||||
this.Intermediate.Low = this.FetchByte();
|
||||
return this.Intermediate;
|
||||
into.High = this.FetchByte();
|
||||
into.Low = this.FetchByte();
|
||||
}
|
||||
|
||||
protected override Register16 GetWord()
|
||||
protected override void GetInto(Register16 into)
|
||||
{
|
||||
this.Intermediate.High = this.MemoryRead();
|
||||
into.High = this.MemoryRead();
|
||||
_ = this.Bus.Address.Increment();
|
||||
this.Intermediate.Low = this.MemoryRead();
|
||||
return this.Intermediate;
|
||||
into.Low = this.MemoryRead();
|
||||
}
|
||||
|
||||
protected override Register16 GetWordPaged()
|
||||
@@ -41,11 +39,10 @@ namespace EightBit
|
||||
return this.Intermediate;
|
||||
}
|
||||
|
||||
protected override Register16 PopWord()
|
||||
protected override void PopInto(Register16 into)
|
||||
{
|
||||
this.Intermediate.High = this.Pop();
|
||||
this.Intermediate.Low = this.Pop();
|
||||
return this.Intermediate;
|
||||
into.High = this.Pop();
|
||||
into.Low = this.Pop();
|
||||
}
|
||||
|
||||
protected override void PushWord(Register16 value)
|
||||
|
||||
@@ -99,8 +99,8 @@ namespace EightBit
|
||||
|
||||
protected override byte FetchInstruction()
|
||||
{
|
||||
var read = this.FetchByte();
|
||||
return this.HALT.Lowered() ? (byte)0 : read;
|
||||
_ = this.FetchByte();
|
||||
return this.HALT.Lowered() ? (byte)0 : this.Bus.Data;
|
||||
}
|
||||
|
||||
protected static int BuildHalfCarryIndex(byte before, byte value, int calculation) => ((before & 0x88) >> 1) | ((value & 0x88) >> 2) | ((calculation & 0x88) >> 3);
|
||||
@@ -176,57 +176,44 @@ namespace EightBit
|
||||
this.Call();
|
||||
}
|
||||
|
||||
protected bool CallConditional(bool condition)
|
||||
protected void CallConditional(bool condition)
|
||||
{
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
if (condition)
|
||||
{
|
||||
this.Call();
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected virtual bool JumpConditional(bool condition)
|
||||
protected virtual void JumpConditional(bool condition)
|
||||
{
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
if (condition)
|
||||
{
|
||||
this.Jump();
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected virtual bool JumpRelativeConditional(bool condition)
|
||||
protected virtual void JumpRelativeConditional(bool condition)
|
||||
{
|
||||
var offset = this.FetchByte();
|
||||
if (condition)
|
||||
{
|
||||
this.JumpRelative(offset);
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected virtual bool ReturnConditional(bool condition)
|
||||
protected virtual void ReturnConditional(bool condition)
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
this.Return();
|
||||
}
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected void FetchWordMEMPTR()
|
||||
{
|
||||
_ = this.FetchWord();
|
||||
this.MEMPTR.Assign(this.Intermediate);
|
||||
}
|
||||
|
||||
protected virtual void JumpIndirect()
|
||||
{
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
this.Jump();
|
||||
}
|
||||
|
||||
@@ -237,7 +224,7 @@ namespace EightBit
|
||||
|
||||
protected void CallIndirect()
|
||||
{
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
this.Call();
|
||||
}
|
||||
|
||||
@@ -262,12 +249,12 @@ namespace EightBit
|
||||
|
||||
protected abstract bool ConvertCondition(int flag);
|
||||
|
||||
protected virtual bool JumpConditionalFlag(int flag) => this.JumpConditional(this.ConvertCondition(flag));
|
||||
protected virtual void JumpConditionalFlag(int flag) => this.JumpConditional(this.ConvertCondition(flag));
|
||||
|
||||
protected virtual bool JumpRelativeConditionalFlag(int flag) => this.JumpRelativeConditional(this.ConvertCondition(flag));
|
||||
protected virtual void JumpRelativeConditionalFlag(int flag) => this.JumpRelativeConditional(this.ConvertCondition(flag));
|
||||
|
||||
protected virtual bool ReturnConditionalFlag(int flag) => this.ReturnConditional(this.ConvertCondition(flag));
|
||||
protected virtual void ReturnConditionalFlag(int flag) => this.ReturnConditional(this.ConvertCondition(flag));
|
||||
|
||||
protected virtual bool CallConditionalFlag(int flag) => this.CallConditional(this.ConvertCondition(flag));
|
||||
protected virtual void CallConditionalFlag(int flag) => this.CallConditional(this.ConvertCondition(flag));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,19 +19,17 @@ namespace EightBit
|
||||
this.Bus.Poke(++address, value.High);
|
||||
}
|
||||
|
||||
protected override Register16 FetchWord()
|
||||
protected override void FetchInto(Register16 into)
|
||||
{
|
||||
this.Intermediate.Low = this.FetchByte();
|
||||
this.Intermediate.High = this.FetchByte();
|
||||
return this.Intermediate;
|
||||
into.Low = this.FetchByte();
|
||||
into.High = this.FetchByte();
|
||||
}
|
||||
|
||||
protected override Register16 GetWord()
|
||||
protected override void GetInto(Register16 into)
|
||||
{
|
||||
this.Intermediate.Low = this.MemoryRead();
|
||||
into.Low = this.MemoryRead();
|
||||
_ = this.Bus.Address.Increment();
|
||||
this.Intermediate.High = this.MemoryRead();
|
||||
return this.Intermediate;
|
||||
into.High = this.MemoryRead();
|
||||
}
|
||||
|
||||
protected override Register16 GetWordPaged()
|
||||
@@ -42,11 +40,10 @@ namespace EightBit
|
||||
return this.Intermediate;
|
||||
}
|
||||
|
||||
protected override Register16 PopWord()
|
||||
protected override void PopInto(Register16 into)
|
||||
{
|
||||
this.Intermediate.Low = this.Pop();
|
||||
this.Intermediate.High = this.Pop();
|
||||
return this.Intermediate;
|
||||
into.Low = this.Pop();
|
||||
into.High = this.Pop();
|
||||
}
|
||||
|
||||
protected override void PushWord(Register16 value)
|
||||
|
||||
@@ -224,10 +224,7 @@ namespace EightBit
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
protected virtual byte MemoryRead()
|
||||
{
|
||||
return this.BusRead();
|
||||
}
|
||||
protected virtual byte MemoryRead() => this.BusRead();
|
||||
|
||||
protected virtual byte BusRead() => this.Bus.Read(); // N.B. Should be the only real call into the "Bus.Read" code.
|
||||
|
||||
@@ -247,18 +244,18 @@ namespace EightBit
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
protected abstract Register16 GetWord();
|
||||
protected abstract void GetInto(Register16 into);
|
||||
|
||||
protected virtual Register16 GetWord()
|
||||
{
|
||||
this.GetInto(this.Intermediate);
|
||||
return this.Intermediate;
|
||||
}
|
||||
|
||||
protected abstract void SetWord(Register16 value);
|
||||
|
||||
protected abstract Register16 GetWordPaged();
|
||||
|
||||
protected Register16 GetWordPaged(Register16 address)
|
||||
{
|
||||
this.Bus.Address.Assign(address);
|
||||
return this.GetWordPaged();
|
||||
}
|
||||
|
||||
protected Register16 GetWordPaged(byte page, byte offset)
|
||||
{
|
||||
this.Bus.Address.Assign(offset, page);
|
||||
@@ -279,27 +276,23 @@ namespace EightBit
|
||||
this.SetWordPaged(value);
|
||||
}
|
||||
|
||||
protected abstract Register16 FetchWord();
|
||||
protected abstract void FetchInto(Register16 into);
|
||||
|
||||
protected void FetchWordAddress()
|
||||
protected Register16 FetchWord()
|
||||
{
|
||||
_ = this.FetchWord();
|
||||
this.Bus.Address.Assign(this.Intermediate);
|
||||
this.FetchInto(this.Intermediate);
|
||||
return this.Intermediate;
|
||||
}
|
||||
|
||||
protected void FetchWordAddress() => this.Bus.Address.Assign(this.FetchWord());
|
||||
|
||||
protected abstract void Push(byte value);
|
||||
|
||||
protected abstract byte Pop();
|
||||
|
||||
protected abstract void PushWord(Register16 value);
|
||||
|
||||
protected abstract Register16 PopWord();
|
||||
|
||||
protected Register16 GetWord(ushort address)
|
||||
{
|
||||
this.Bus.Address.Word = address;
|
||||
return this.GetWord();
|
||||
}
|
||||
protected abstract void PopInto(Register16 into);
|
||||
|
||||
protected Register16 GetWord(Register16 address)
|
||||
{
|
||||
@@ -307,12 +300,6 @@ namespace EightBit
|
||||
return this.GetWord();
|
||||
}
|
||||
|
||||
protected void SetWord(ushort address, Register16 value)
|
||||
{
|
||||
this.Bus.Address.Word = address;
|
||||
this.SetWord(value);
|
||||
}
|
||||
|
||||
protected void SetWord(Register16 address, Register16 value)
|
||||
{
|
||||
this.Bus.Address.Assign(address);
|
||||
@@ -323,12 +310,6 @@ namespace EightBit
|
||||
|
||||
protected void Jump(Register16 destination) => this.PC.Assign(destination);
|
||||
|
||||
protected void Call(ushort destination)
|
||||
{
|
||||
this.Intermediate.Word = destination;
|
||||
this.Call(this.Intermediate);
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "Not using VB.NET")]
|
||||
protected virtual void Call(Register16 destination)
|
||||
{
|
||||
@@ -337,6 +318,6 @@ namespace EightBit
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "Not using VB.NET")]
|
||||
protected virtual void Return() => this.Jump(this.PopWord());
|
||||
protected virtual void Return() => this.PopInto(this.PC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,12 @@ namespace Intel8080.Test
|
||||
|
||||
public string RomDirectory { get; } = "roms";
|
||||
|
||||
public string Program { get; } = "8080EX1.COM";
|
||||
//public string Program { get; } = "8080EX1.COM";
|
||||
public string Program { get; } = "8080EXER.COM";
|
||||
//public string Program { get; } = "8080EXM.COM";
|
||||
//public string Program { get; } = "8080PRE.COM";
|
||||
//public string Program { get; } = "CPUTEST.COM";
|
||||
//public string Program { get; } = "TEST.COM";
|
||||
//public string Program { get; } = "TST8080.COM";
|
||||
}
|
||||
}
|
||||
Binary file not shown.
1283
Intel8080/Intel8080.Test/roms/8080EXER.MAC
Normal file
1283
Intel8080/Intel8080.Test/roms/8080EXER.MAC
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Intel8080/Intel8080.Test/roms/8080EXER.PNG
Normal file
BIN
Intel8080/Intel8080.Test/roms/8080EXER.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
2239
Intel8080/Intel8080.Test/roms/8080EXER.PRN
Normal file
2239
Intel8080/Intel8080.Test/roms/8080EXER.PRN
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Intel8080/Intel8080.Test/roms/8080EXM.COM
Normal file
BIN
Intel8080/Intel8080.Test/roms/8080EXM.COM
Normal file
Binary file not shown.
1296
Intel8080/Intel8080.Test/roms/8080EXM.MAC
Normal file
1296
Intel8080/Intel8080.Test/roms/8080EXM.MAC
Normal file
File diff suppressed because it is too large
Load Diff
2254
Intel8080/Intel8080.Test/roms/8080EXM.PRN
Normal file
2254
Intel8080/Intel8080.Test/roms/8080EXM.PRN
Normal file
File diff suppressed because it is too large
Load Diff
535
Intel8080/Intel8080.Test/roms/8080PRE.PRN
Normal file
535
Intel8080/Intel8080.Test/roms/8080PRE.PRN
Normal file
@@ -0,0 +1,535 @@
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1
|
||||
|
||||
|
||||
title 'Preliminary Z80 tests'
|
||||
|
||||
; prelim.z80 - Preliminary Z80 tests
|
||||
; Copyright (C) 1994 Frank D. Cringle
|
||||
;
|
||||
; This program is free software; you can redistribute it and/or
|
||||
; modify it under the terms of the GNU General Public License
|
||||
; as published by the Free Software Foundation; either version 2
|
||||
; of the License, or (at your option) any later version.
|
||||
;
|
||||
; This program is distributed in the hope that it will be useful,
|
||||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
; GNU General Public License for more details.
|
||||
;
|
||||
; You should have received a copy of the GNU General Public License
|
||||
; along with this program; if not, write to the Free Software
|
||||
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
; These tests have two goals. To start with, we assume the worst and
|
||||
; successively test the instructions needed to continue testing.
|
||||
; Then we try to test all instructions which cannot be handled by
|
||||
; zexlax - the crc-based instruction exerciser.
|
||||
|
||||
; Initially errors are 'reported' by jumping to 0. This should reboot
|
||||
; cp/m, so if the program terminates without any output one of the
|
||||
; early tests failed. Later errors are reported by outputting an
|
||||
; address via the bdos conout routine. The address can be located in
|
||||
; a listing of this program.
|
||||
|
||||
; If the program runs to completion it displays a suitable message.
|
||||
|
||||
;******************************************************************************
|
||||
;
|
||||
; Modified by Ian Bartholomew to run a preliminary test on an 8080 CPU
|
||||
;
|
||||
; Assemble using M80
|
||||
;
|
||||
;******************************************************************************
|
||||
|
||||
.8080
|
||||
0000' aseg
|
||||
org 100h
|
||||
|
||||
0100 3E 01 start: mvi a,1 ; test simple compares and z/nz jumps
|
||||
0102 FE 02 cpi 2
|
||||
0104 CA 0000 jz 0
|
||||
0107 FE 01 cpi 1
|
||||
0109 C2 0000 jnz 0
|
||||
010C C3 0111 jmp lab0
|
||||
010F 76 hlt ; emergency exit
|
||||
0110 FF db 0ffh
|
||||
|
||||
0111 CD 0117 lab0: call lab2 ; does a simple call work?
|
||||
0114 C3 0000 lab1: jmp 0 ; fail
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1-1
|
||||
|
||||
|
||||
|
||||
0117 E1 lab2: pop h ; check return address
|
||||
0118 7C mov a,h
|
||||
0119 FE 01 cpi high lab1
|
||||
011B CA 0121 jz lab3
|
||||
011E C3 0000 jmp 0
|
||||
0121 7D lab3: mov a,l
|
||||
0122 FE 14 cpi low lab1
|
||||
0124 CA 012A jz lab4
|
||||
0127 C3 0000 jmp 0
|
||||
|
||||
; test presence and uniqueness of all machine registers
|
||||
; (except ir)
|
||||
012A 31 0399 lab4: lxi sp,regs1
|
||||
012D F1 pop psw
|
||||
012E C1 pop b
|
||||
012F D1 pop d
|
||||
0130 E1 pop h
|
||||
0131 31 03A9 lxi sp,regs2+8
|
||||
0134 E5 push h
|
||||
0135 D5 push d
|
||||
0136 C5 push b
|
||||
0137 F5 push psw
|
||||
|
||||
0000 v defl 0
|
||||
rept 8
|
||||
lda regs2+v/2
|
||||
v defl v+2
|
||||
cpi v
|
||||
jnz 0
|
||||
endm
|
||||
0138 3A 03A1 + lda regs2+v/2
|
||||
013B FE 02 + cpi v
|
||||
013D C2 0000 + jnz 0
|
||||
0140 3A 03A2 + lda regs2+v/2
|
||||
0143 FE 04 + cpi v
|
||||
0145 C2 0000 + jnz 0
|
||||
0148 3A 03A3 + lda regs2+v/2
|
||||
014B FE 06 + cpi v
|
||||
014D C2 0000 + jnz 0
|
||||
0150 3A 03A4 + lda regs2+v/2
|
||||
0153 FE 08 + cpi v
|
||||
0155 C2 0000 + jnz 0
|
||||
0158 3A 03A5 + lda regs2+v/2
|
||||
015B FE 0A + cpi v
|
||||
015D C2 0000 + jnz 0
|
||||
0160 3A 03A6 + lda regs2+v/2
|
||||
0163 FE 0C + cpi v
|
||||
0165 C2 0000 + jnz 0
|
||||
0168 3A 03A7 + lda regs2+v/2
|
||||
016B FE 0E + cpi v
|
||||
016D C2 0000 + jnz 0
|
||||
0170 3A 03A8 + lda regs2+v/2
|
||||
0173 FE 10 + cpi v
|
||||
0175 C2 0000 + jnz 0
|
||||
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1-2
|
||||
|
||||
|
||||
; test access to memory via (hl)
|
||||
0178 21 03A9 lxi h,hlval
|
||||
017B 7E mov a,m
|
||||
017C FE A5 cpi 0a5h
|
||||
017E C2 0000 jnz 0
|
||||
0181 21 03AA lxi h,hlval+1
|
||||
0184 7E mov a,m
|
||||
0185 FE 3C cpi 03ch
|
||||
0187 C2 0000 jnz 0
|
||||
|
||||
; test unconditional return
|
||||
018A 31 0500 lxi sp,stack
|
||||
018D 21 0195 lxi h,reta
|
||||
0190 E5 push h
|
||||
0191 C9 ret
|
||||
0192 C3 0000 jmp 0
|
||||
|
||||
; test instructions needed for hex output
|
||||
0195 3E FF reta: mvi a,0ffh
|
||||
0197 E6 0F ani 0fh
|
||||
0199 FE 0F cpi 0fh
|
||||
019B C2 0000 jnz 0
|
||||
019E 3E 5A mvi a,05ah
|
||||
01A0 E6 0F ani 0fh
|
||||
01A2 FE 0A cpi 0ah
|
||||
01A4 C2 0000 jnz 0
|
||||
01A7 0F rrc
|
||||
01A8 FE 05 cpi 05h
|
||||
01AA C2 0000 jnz 0
|
||||
01AD 0F rrc
|
||||
01AE FE 82 cpi 82h
|
||||
01B0 C2 0000 jnz 0
|
||||
01B3 0F rrc
|
||||
01B4 FE 41 cpi 41h
|
||||
01B6 C2 0000 jnz 0
|
||||
01B9 0F rrc
|
||||
01BA FE A0 cpi 0a0h
|
||||
01BC C2 0000 jnz 0
|
||||
01BF 21 1234 lxi h,01234h
|
||||
01C2 E5 push h
|
||||
01C3 C1 pop b
|
||||
01C4 78 mov a,b
|
||||
01C5 FE 12 cpi 12h
|
||||
01C7 C2 0000 jnz 0
|
||||
01CA 79 mov a,c
|
||||
01CB FE 34 cpi 34h
|
||||
01CD C2 0000 jnz 0
|
||||
|
||||
; from now on we can report errors by displaying an address
|
||||
|
||||
; test conditional call, ret, jp, jr
|
||||
tcond macro flag,pcond,ncond,rel
|
||||
lxi h,&flag
|
||||
push h
|
||||
pop psw
|
||||
c&pcond lab1&pcond
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1-3
|
||||
|
||||
|
||||
jmp error
|
||||
lab1&pcond: pop h
|
||||
lxi h,0d7h xor &flag
|
||||
push h
|
||||
pop psw
|
||||
c&ncond lab2&pcond
|
||||
jmp error
|
||||
lab2&pcond: pop h
|
||||
lxi h,lab3&pcond
|
||||
push h
|
||||
lxi h,&flag
|
||||
push h
|
||||
pop psw
|
||||
r&pcond
|
||||
call error
|
||||
lab3&pcond: lxi h,lab4&pcond
|
||||
push h
|
||||
lxi h,0d7h xor &flag
|
||||
push h
|
||||
pop psw
|
||||
r&ncond
|
||||
call error
|
||||
lab4&pcond: lxi h,&flag
|
||||
push h
|
||||
pop psw
|
||||
j&pcond lab5&pcond
|
||||
call error
|
||||
lab5&pcond: lxi h,0d7h xor &flag
|
||||
push h
|
||||
pop psw
|
||||
j&ncond lab6&pcond
|
||||
call error
|
||||
lab6&pcond:
|
||||
endm
|
||||
|
||||
tcond 1,c,nc,1
|
||||
01D0 21 0001 + lxi h,&1
|
||||
01D3 E5 + push h
|
||||
01D4 F1 + pop psw
|
||||
01D5 DC 01DB + c&c lab1&c
|
||||
01D8 C3 0352 + jmp error
|
||||
01DB E1 + lab1&c: pop h
|
||||
01DC 21 00D6 + lxi h,0d7h xor &1
|
||||
01DF E5 + push h
|
||||
01E0 F1 + pop psw
|
||||
01E1 D4 01E7 + c&nc lab2&c
|
||||
01E4 C3 0352 + jmp error
|
||||
01E7 E1 + lab2&c: pop h
|
||||
01E8 21 01F5 + lxi h,lab3&c
|
||||
01EB E5 + push h
|
||||
01EC 21 0001 + lxi h,&1
|
||||
01EF E5 + push h
|
||||
01F0 F1 + pop psw
|
||||
01F1 D8 + r&c
|
||||
01F2 CD 0352 + call error
|
||||
01F5 21 0202 + lab3&c: lxi h,lab4&c
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1-4
|
||||
|
||||
|
||||
01F8 E5 + push h
|
||||
01F9 21 00D6 + lxi h,0d7h xor &1
|
||||
01FC E5 + push h
|
||||
01FD F1 + pop psw
|
||||
01FE D0 + r&nc
|
||||
01FF CD 0352 + call error
|
||||
0202 21 0001 + lab4&c: lxi h,&1
|
||||
0205 E5 + push h
|
||||
0206 F1 + pop psw
|
||||
0207 DA 020D + j&c lab5&c
|
||||
020A CD 0352 + call error
|
||||
020D 21 00D6 + lab5&c: lxi h,0d7h xor &1
|
||||
0210 E5 + push h
|
||||
0211 F1 + pop psw
|
||||
0212 D2 0218 + j&nc lab6&c
|
||||
0215 CD 0352 + call error
|
||||
0218 + lab6&c:
|
||||
tcond 4,pe,po,0
|
||||
0218 21 0004 + lxi h,&4
|
||||
021B E5 + push h
|
||||
021C F1 + pop psw
|
||||
021D EC 0223 + c&pe lab1&pe
|
||||
0220 C3 0352 + jmp error
|
||||
0223 E1 + lab1&pe: pop h
|
||||
0224 21 00D3 + lxi h,0d7h xor &4
|
||||
0227 E5 + push h
|
||||
0228 F1 + pop psw
|
||||
0229 E4 022F + c&po lab2&pe
|
||||
022C C3 0352 + jmp error
|
||||
022F E1 + lab2&pe: pop h
|
||||
0230 21 023D + lxi h,lab3&pe
|
||||
0233 E5 + push h
|
||||
0234 21 0004 + lxi h,&4
|
||||
0237 E5 + push h
|
||||
0238 F1 + pop psw
|
||||
0239 E8 + r&pe
|
||||
023A CD 0352 + call error
|
||||
023D 21 024A + lab3&pe: lxi h,lab4&pe
|
||||
0240 E5 + push h
|
||||
0241 21 00D3 + lxi h,0d7h xor &4
|
||||
0244 E5 + push h
|
||||
0245 F1 + pop psw
|
||||
0246 E0 + r&po
|
||||
0247 CD 0352 + call error
|
||||
024A 21 0004 + lab4&pe: lxi h,&4
|
||||
024D E5 + push h
|
||||
024E F1 + pop psw
|
||||
024F EA 0255 + j&pe lab5&pe
|
||||
0252 CD 0352 + call error
|
||||
0255 21 00D3 + lab5&pe: lxi h,0d7h xor &4
|
||||
0258 E5 + push h
|
||||
0259 F1 + pop psw
|
||||
025A E2 0260 + j&po lab6&pe
|
||||
025D CD 0352 + call error
|
||||
0260 + lab6&pe:
|
||||
tcond 040h,z,nz,1
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1-5
|
||||
|
||||
|
||||
0260 21 0040 + lxi h,&040h
|
||||
0263 E5 + push h
|
||||
0264 F1 + pop psw
|
||||
0265 CC 026B + c&z lab1&z
|
||||
0268 C3 0352 + jmp error
|
||||
026B E1 + lab1&z: pop h
|
||||
026C 21 0097 + lxi h,0d7h xor &040h
|
||||
026F E5 + push h
|
||||
0270 F1 + pop psw
|
||||
0271 C4 0277 + c&nz lab2&z
|
||||
0274 C3 0352 + jmp error
|
||||
0277 E1 + lab2&z: pop h
|
||||
0278 21 0285 + lxi h,lab3&z
|
||||
027B E5 + push h
|
||||
027C 21 0040 + lxi h,&040h
|
||||
027F E5 + push h
|
||||
0280 F1 + pop psw
|
||||
0281 C8 + r&z
|
||||
0282 CD 0352 + call error
|
||||
0285 21 0292 + lab3&z: lxi h,lab4&z
|
||||
0288 E5 + push h
|
||||
0289 21 0097 + lxi h,0d7h xor &040h
|
||||
028C E5 + push h
|
||||
028D F1 + pop psw
|
||||
028E C0 + r&nz
|
||||
028F CD 0352 + call error
|
||||
0292 21 0040 + lab4&z: lxi h,&040h
|
||||
0295 E5 + push h
|
||||
0296 F1 + pop psw
|
||||
0297 CA 029D + j&z lab5&z
|
||||
029A CD 0352 + call error
|
||||
029D 21 0097 + lab5&z: lxi h,0d7h xor &040h
|
||||
02A0 E5 + push h
|
||||
02A1 F1 + pop psw
|
||||
02A2 C2 02A8 + j&nz lab6&z
|
||||
02A5 CD 0352 + call error
|
||||
02A8 + lab6&z:
|
||||
tcond 080h,m,p,0
|
||||
02A8 21 0080 + lxi h,&080h
|
||||
02AB E5 + push h
|
||||
02AC F1 + pop psw
|
||||
02AD FC 02B3 + c&m lab1&m
|
||||
02B0 C3 0352 + jmp error
|
||||
02B3 E1 + lab1&m: pop h
|
||||
02B4 21 0057 + lxi h,0d7h xor &080h
|
||||
02B7 E5 + push h
|
||||
02B8 F1 + pop psw
|
||||
02B9 F4 02BF + c&p lab2&m
|
||||
02BC C3 0352 + jmp error
|
||||
02BF E1 + lab2&m: pop h
|
||||
02C0 21 02CD + lxi h,lab3&m
|
||||
02C3 E5 + push h
|
||||
02C4 21 0080 + lxi h,&080h
|
||||
02C7 E5 + push h
|
||||
02C8 F1 + pop psw
|
||||
02C9 F8 + r&m
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1-6
|
||||
|
||||
|
||||
02CA CD 0352 + call error
|
||||
02CD 21 02DA + lab3&m: lxi h,lab4&m
|
||||
02D0 E5 + push h
|
||||
02D1 21 0057 + lxi h,0d7h xor &080h
|
||||
02D4 E5 + push h
|
||||
02D5 F1 + pop psw
|
||||
02D6 F0 + r&p
|
||||
02D7 CD 0352 + call error
|
||||
02DA 21 0080 + lab4&m: lxi h,&080h
|
||||
02DD E5 + push h
|
||||
02DE F1 + pop psw
|
||||
02DF FA 02E5 + j&m lab5&m
|
||||
02E2 CD 0352 + call error
|
||||
02E5 21 0057 + lab5&m: lxi h,0d7h xor &080h
|
||||
02E8 E5 + push h
|
||||
02E9 F1 + pop psw
|
||||
02EA F2 02F0 + j&p lab6&m
|
||||
02ED CD 0352 + call error
|
||||
02F0 + lab6&m:
|
||||
|
||||
; test indirect jumps
|
||||
02F0 21 02F7 lxi h,lab7
|
||||
02F3 E9 pchl
|
||||
02F4 CD 0352 call error
|
||||
|
||||
; djnz (and (partially) inc a, inc hl)
|
||||
02F7 3E A5 lab7: mvi a,0a5h
|
||||
02F9 06 04 mvi b,4
|
||||
02FB 0F lab8: rrc
|
||||
02FC 05 dcr b
|
||||
02FD C2 02FB jnz lab8
|
||||
0300 FE 5A cpi 05ah
|
||||
0302 C4 0352 cnz error
|
||||
0305 06 10 mvi b,16
|
||||
0307 3C lab9: inr a
|
||||
0308 05 dcr b
|
||||
0309 C2 0307 jnz lab9
|
||||
030C FE 6A cpi 06ah
|
||||
030E C4 0352 cnz error
|
||||
0311 06 00 mvi b,0
|
||||
0313 21 0000 lxi h,0
|
||||
0316 23 lab10: inx h
|
||||
0317 05 dcr b
|
||||
0318 C2 0316 jnz lab10
|
||||
031B 7C mov a,h
|
||||
031C FE 01 cpi 1
|
||||
031E C4 0352 cnz error
|
||||
0321 7D mov a,l
|
||||
0322 FE 00 cpi 0
|
||||
0324 C4 0352 cnz error
|
||||
|
||||
0327 11 0332 allok: lxi d,okmsg
|
||||
032A 0E 09 mvi c,9
|
||||
032C CD 0005 call 5
|
||||
032F C3 0000 jmp 0
|
||||
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1-7
|
||||
|
||||
|
||||
0332 38 30 38 30 okmsg: db '8080 Preliminary tests complete$'
|
||||
0336 20 50 72 65
|
||||
033A 6C 69 6D 69
|
||||
033E 6E 61 72 79
|
||||
0342 20 74 65 73
|
||||
0346 74 73 20 63
|
||||
034A 6F 6D 70 6C
|
||||
034E 65 74 65 24
|
||||
|
||||
; display address at top of stack and exit
|
||||
0352 C1 error: pop b
|
||||
0353 26 04 mvi h,high hextab
|
||||
0355 78 mov a,b
|
||||
0356 0F rrc
|
||||
0357 0F rrc
|
||||
0358 0F rrc
|
||||
0359 0F rrc
|
||||
035A E6 0F ani 15
|
||||
035C 6F mov l,a
|
||||
035D 7E mov a,m
|
||||
035E CD 038A call conout
|
||||
0361 78 mov a,b
|
||||
0362 E6 0F ani 15
|
||||
0364 6F mov l,a
|
||||
0365 7E mov a,m
|
||||
0366 CD 038A call conout
|
||||
0369 79 mov a,c
|
||||
036A 0F rrc
|
||||
036B 0F rrc
|
||||
036C 0F rrc
|
||||
036D 0F rrc
|
||||
036E E6 0F ani 15
|
||||
0370 6F mov l,a
|
||||
0371 7E mov a,m
|
||||
0372 CD 038A call conout
|
||||
0375 79 mov a,c
|
||||
0376 E6 0F ani 15
|
||||
0378 6F mov l,a
|
||||
0379 7E mov a,m
|
||||
037A CD 038A call conout
|
||||
037D 3E 0D mvi a,13
|
||||
037F CD 038A call conout
|
||||
0382 3E 0A mvi a,10
|
||||
0384 CD 038A call conout
|
||||
0387 C3 0000 jmp 0
|
||||
|
||||
038A F5 conout: push psw
|
||||
038B C5 push b
|
||||
038C D5 push d
|
||||
038D E5 push h
|
||||
038E 0E 02 mvi c,2
|
||||
0390 5F mov e,a
|
||||
0391 CD 0005 call 5
|
||||
0394 E1 pop h
|
||||
0395 D1 pop d
|
||||
0396 C1 pop b
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE 1-8
|
||||
|
||||
|
||||
0397 F1 pop psw
|
||||
0398 C9 ret
|
||||
|
||||
0000 v defl 0
|
||||
0399 regs1: rept 8
|
||||
v defl v+2
|
||||
db v
|
||||
endm
|
||||
0399 02 + db v
|
||||
039A 04 + db v
|
||||
039B 06 + db v
|
||||
039C 08 + db v
|
||||
039D 0A + db v
|
||||
039E 0C + db v
|
||||
039F 0E + db v
|
||||
03A0 10 + db v
|
||||
|
||||
03A1 regs2: ds 8,0
|
||||
|
||||
03A9 A5 3C hlval: db 0a5h,03ch
|
||||
|
||||
; skip to next page boundary
|
||||
org (($+255)/256)*256
|
||||
0400 30 31 32 33 hextab: db '0123456789abcdef'
|
||||
0404 34 35 36 37
|
||||
0408 38 39 61 62
|
||||
040C 63 64 65 66
|
||||
0410 ds 240
|
||||
|
||||
0500 stack equ $
|
||||
|
||||
end start
|
||||
'Preliminary Z80 tests' MACRO-80 3.44 09-Dec-81 PAGE S
|
||||
|
||||
|
||||
Macros:
|
||||
TCOND
|
||||
|
||||
Symbols:
|
||||
0327 ALLOK 038A CONOUT 0352 ERROR
|
||||
0400 HEXTAB 03A9 HLVAL 0111 LAB0
|
||||
0114 LAB1 0316 LAB10 01DB LAB1C
|
||||
02B3 LAB1M 0223 LAB1PE 026B LAB1Z
|
||||
0117 LAB2 01E7 LAB2C 02BF LAB2M
|
||||
022F LAB2PE 0277 LAB2Z 0121 LAB3
|
||||
01F5 LAB3C 02CD LAB3M 023D LAB3PE
|
||||
0285 LAB3Z 012A LAB4 0202 LAB4C
|
||||
02DA LAB4M 024A LAB4PE 0292 LAB4Z
|
||||
020D LAB5C 02E5 LAB5M 0255 LAB5PE
|
||||
029D LAB5Z 0218 LAB6C 02F0 LAB6M
|
||||
0260 LAB6PE 02A8 LAB6Z 02F7 LAB7
|
||||
02FB LAB8 0307 LAB9 0332 OKMSG
|
||||
0399 REGS1 03A1 REGS2 0195 RETA
|
||||
0500 STACK 0100 START 0010 V
|
||||
|
||||
|
||||
|
||||
No Fatal error(s)
|
||||
|
||||
|
||||
31
Intel8080/Intel8080.Test/roms/README.TXT
Normal file
31
Intel8080/Intel8080.Test/roms/README.TXT
Normal file
@@ -0,0 +1,31 @@
|
||||
This folder contains 8080 CPU test programs that run under CP/M
|
||||
|
||||
TST8080
|
||||
8080/8085 CPU Diagnostic, version 1.0, by Microcosm Associates
|
||||
(Kelly Smith test)
|
||||
|
||||
8080PRE
|
||||
Preliminary test for 8080/8085 CPU Exerciser by Ian Bartholomew
|
||||
and Frank Cringles.
|
||||
|
||||
8080EXER
|
||||
8080/8085 CPU Exerciser by Ian Bartholomew and Frank Cringles.
|
||||
This is a very thorough test that generates a CRC code for each
|
||||
group of tests. The program will say "Error" for every test, but
|
||||
it's not actually an error. Instead, compare the reported CRC
|
||||
with results from tests against real silicon. See 8080EXER.PNG in
|
||||
this directory and http://www.idb.me.uk/sunhillow/8080.html. The
|
||||
full test takes several hours. The "aluop <b,c,d,e,h,l,m,a>" section
|
||||
takes especially long.
|
||||
|
||||
8080EXM
|
||||
8080/80805 Exerciser "M"odified with the correct result CRCs in
|
||||
the program so it can display "pass" or "fail" correctly.
|
||||
|
||||
CPUTEST
|
||||
SuperSoft Associates CPU test from the Diagnostic II
|
||||
suite. When it displays "ABCDEF..." those are actually
|
||||
indications of test that have passed. Additional testing
|
||||
occurs during the "Begin Timing Test" and "End Timing Test"
|
||||
period. On a 2MHz 8080, the timing test period lasts about
|
||||
two minutes.
|
||||
819
Intel8080/Intel8080.Test/roms/TST8080.ASM
Normal file
819
Intel8080/Intel8080.Test/roms/TST8080.ASM
Normal file
@@ -0,0 +1,819 @@
|
||||
;***********************************************************************
|
||||
; MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC VERSION 1.0 (C) 1980
|
||||
;***********************************************************************
|
||||
;
|
||||
;DONATED TO THE "SIG/M" CP/M USER'S GROUP BY:
|
||||
;KELLY SMITH, MICROCOSM ASSOCIATES
|
||||
;3055 WACO AVENUE
|
||||
;SIMI VALLEY, CALIFORNIA, 93065
|
||||
;(805) 527-9321 (MODEM, CP/M-NET (TM))
|
||||
;(805) 527-0518 (VERBAL)
|
||||
;
|
||||
; Updated by Mike Douglas October, 2012
|
||||
;
|
||||
; Added the following tests that were missing:
|
||||
; mov c,m
|
||||
; mov m,c
|
||||
; ana b
|
||||
;
|
||||
; Fixed the CPUER exit routine which did not display the
|
||||
; low byte of the failure address properly.
|
||||
;
|
||||
; Added display of the Microcosm welcome message
|
||||
;
|
||||
ORG 00100H
|
||||
|
||||
;
|
||||
JMP CPU ;JUMP TO 8080 CPU DIAGNOSTIC
|
||||
;
|
||||
WELCOM DB 'MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC',13,10
|
||||
DB ' VERSION 1.0 (C) 1980',13,10,'$'
|
||||
;
|
||||
BDOS EQU 00005H ;BDOS ENTRY TO CP/M
|
||||
WBOOT EQU 00000H ;RE-ENTRY TO CP/M WARM BOOT
|
||||
;
|
||||
;
|
||||
;
|
||||
;MESSAGE OUTPUT ROUTINE
|
||||
;
|
||||
MSG: PUSH D ;EXILE D REG.
|
||||
XCHG ;SWAP H&L REGS. TO D&E REGS.
|
||||
MVI C,9 ;LET BDOS KNOW WE WANT TO SEND A MESSAGE
|
||||
CALL BDOS
|
||||
POP D ;BACK FROM EXILE
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
;CHARACTER OUTPUT ROUTINE
|
||||
;
|
||||
PCHAR: MVI C,2
|
||||
CALL BDOS
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
BYTEO: PUSH PSW
|
||||
CALL BYTO1
|
||||
MOV E,A
|
||||
CALL PCHAR
|
||||
POP PSW
|
||||
CALL BYTO2
|
||||
MOV E,A
|
||||
JMP PCHAR
|
||||
BYTO1: RRC
|
||||
RRC
|
||||
RRC
|
||||
RRC
|
||||
BYTO2: ANI 0FH
|
||||
CPI 0AH
|
||||
JM BYTO3
|
||||
ADI 7
|
||||
BYTO3: ADI 30H
|
||||
RET
|
||||
;
|
||||
;
|
||||
;
|
||||
;************************************************************
|
||||
; MESSAGE TABLE FOR OPERATIONAL CPU TEST
|
||||
;************************************************************
|
||||
;
|
||||
OKCPU: DB 0DH,0AH,' CPU IS OPERATIONAL$'
|
||||
;
|
||||
NGCPU: DB 0DH,0AH,' CPU HAS FAILED! ERROR EXIT=$'
|
||||
;
|
||||
;
|
||||
;
|
||||
;************************************************************
|
||||
; 8080/8085 CPU TEST/DIAGNOSTIC
|
||||
;************************************************************
|
||||
;
|
||||
;NOTE: (1) PROGRAM ASSUMES "CALL",AND "LXI SP" INSTRUCTIONS WORK!
|
||||
;
|
||||
; (2) INSTRUCTIONS NOT TESTED ARE "HLT","DI","EI","RIM","SIM",
|
||||
; AND "RST 0" THRU "RST 7"
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST JUMP INSTRUCTIONS AND FLAGS
|
||||
;
|
||||
CPU: LXI SP,STACK ;SET THE STACK POINTER
|
||||
LXI H,WELCOM
|
||||
CALL MSG
|
||||
ANI 0 ;INITIALIZE A REG. AND CLEAR ALL FLAGS
|
||||
JZ J010 ;TEST "JZ"
|
||||
CALL CPUER
|
||||
J010: JNC J020 ;TEST "JNC"
|
||||
CALL CPUER
|
||||
J020: JPE J030 ;TEST "JPE"
|
||||
CALL CPUER
|
||||
J030: JP J040 ;TEST "JP"
|
||||
CALL CPUER
|
||||
J040: JNZ J050 ;TEST "JNZ"
|
||||
JC J050 ;TEST "JC"
|
||||
JPO J050 ;TEST "JPO"
|
||||
JM J050 ;TEST "JM"
|
||||
JMP J060 ;TEST "JMP" (IT'S A LITTLE LATE,BUT WHAT THE HELL!
|
||||
J050: CALL CPUER
|
||||
J060: ADI 6 ;A=6,C=0,P=1,S=0,Z=0
|
||||
JNZ J070 ;TEST "JNZ"
|
||||
CALL CPUER
|
||||
J070: JC J080 ;TEST "JC"
|
||||
JPO J080 ;TEST "JPO"
|
||||
JP J090 ;TEST "JP"
|
||||
J080: CALL CPUER
|
||||
J090: ADI 070H ;A=76H,C=0,P=0,S=0,Z=0
|
||||
JPO J100 ;TEST "JPO"
|
||||
CALL CPUER
|
||||
J100: JM J110 ;TEST "JM"
|
||||
JZ J110 ;TEST "JZ"
|
||||
JNC J120 ;TEST "JNC"
|
||||
J110: CALL CPUER
|
||||
J120: ADI 081H ;A=F7H,C=0,P=0,S=1,Z=0
|
||||
JM J130 ;TEST "JM"
|
||||
CALL CPUER
|
||||
J130: JZ J140 ;TEST "JZ"
|
||||
JC J140 ;TEST "JC"
|
||||
JPO J150 ;TEST "JPO"
|
||||
J140: CALL CPUER
|
||||
J150: ADI 0FEH ;A=F5H,C=1,P=1,S=1,Z=0
|
||||
JC J160 ;TEST "JC"
|
||||
CALL CPUER
|
||||
J160: JZ J170 ;TEST "JZ"
|
||||
JPO J170 ;TEST "JPO"
|
||||
JM AIMM ;TEST "JM"
|
||||
J170: CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST ACCUMULATOR IMMEDIATE INSTRUCTIONS
|
||||
;
|
||||
AIMM: CPI 0 ;A=F5H,C=0,Z=0
|
||||
JC CPIE ;TEST "CPI" FOR RE-SET CARRY
|
||||
JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
CPI 0F5H ;A=F5H,C=0,Z=1
|
||||
JC CPIE ;TEST "CPI" FOR RE-SET CARRY ("ADI")
|
||||
JNZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
CPI 0FFH ;A=F5H,C=1,Z=0
|
||||
JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
JC ACII ;TEST "CPI" FOR SET CARRY
|
||||
CPIE: CALL CPUER
|
||||
ACII: ACI 00AH ;A=F5H+0AH+CARRY(1)=0,C=1
|
||||
ACI 00AH ;A=0+0AH+CARRY(0)=0BH,C=0
|
||||
CPI 00BH
|
||||
JZ SUII ;TEST "ACI"
|
||||
CALL CPUER
|
||||
SUII: SUI 00CH ;A=FFH,C=0
|
||||
SUI 00FH ;A=F0H,C=1
|
||||
CPI 0F0H
|
||||
JZ SBII ;TEST "SUI"
|
||||
CALL CPUER
|
||||
SBII: SBI 0F1H ;A=F0H-0F1H-CARRY(0)=FFH,C=1
|
||||
SBI 00EH ;A=FFH-OEH-CARRY(1)=F0H,C=0
|
||||
CPI 0F0H
|
||||
JZ ANII ;TEST "SBI"
|
||||
CALL CPUER
|
||||
ANII: ANI 055H ;A=F0H<AND>55H=50H,C=0,P=1,S=0,Z=0
|
||||
CPI 050H
|
||||
JZ ORII ;TEST "ANI"
|
||||
CALL CPUER
|
||||
ORII: ORI 03AH ;A=50H<OR>3AH=7AH,C=0,P=0,S=0,Z=0
|
||||
CPI 07AH
|
||||
JZ XRII ;TEST "ORI"
|
||||
CALL CPUER
|
||||
XRII: XRI 00FH ;A=7AH<XOR>0FH=75H,C=0,P=0,S=0,Z=0
|
||||
CPI 075H
|
||||
JZ C010 ;TEST "XRI"
|
||||
CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST CALLS AND RETURNS
|
||||
;
|
||||
C010: ANI 000H ;A=0,C=0,P=1,S=0,Z=1
|
||||
CC CPUER ;TEST "CC"
|
||||
CPO CPUER ;TEST "CPO"
|
||||
CM CPUER ;TEST "CM"
|
||||
CNZ CPUER ;TEST "CNZ"
|
||||
CPI 000H
|
||||
JZ C020 ;A=0,C=0,P=0,S=0,Z=1
|
||||
CALL CPUER
|
||||
C020: SUI 077H ;A=89H,C=1,P=0,S=1,Z=0
|
||||
CNC CPUER ;TEST "CNC"
|
||||
CPE CPUER ;TEST "CPE"
|
||||
CP CPUER ;TEST "CP"
|
||||
CZ CPUER ;TEST "CZ"
|
||||
CPI 089H
|
||||
JZ C030 ;TEST FOR "CALLS" TAKING BRANCH
|
||||
CALL CPUER
|
||||
C030: ANI 0FFH ;SET FLAGS BACK!
|
||||
CPO CPOI ;TEST "CPO"
|
||||
CPI 0D9H
|
||||
JZ MOVI ;TEST "CALL" SEQUENCE SUCCESS
|
||||
CALL CPUER
|
||||
CPOI: RPE ;TEST "RPE"
|
||||
ADI 010H ;A=99H,C=0,P=0,S=1,Z=0
|
||||
CPE CPEI ;TEST "CPE"
|
||||
ADI 002H ;A=D9H,C=0,P=0,S=1,Z=0
|
||||
RPO ;TEST "RPO"
|
||||
CALL CPUER
|
||||
CPEI: RPO ;TEST "RPO"
|
||||
ADI 020H ;A=B9H,C=0,P=0,S=1,Z=0
|
||||
CM CMI ;TEST "CM"
|
||||
ADI 004H ;A=D7H,C=0,P=1,S=1,Z=0
|
||||
RPE ;TEST "RPE"
|
||||
CALL CPUER
|
||||
CMI: RP ;TEST "RP"
|
||||
ADI 080H ;A=39H,C=1,P=1,S=0,Z=0
|
||||
CP TCPI ;TEST "CP"
|
||||
ADI 080H ;A=D3H,C=0,P=0,S=1,Z=0
|
||||
RM ;TEST "RM"
|
||||
CALL CPUER
|
||||
TCPI: RM ;TEST "RM"
|
||||
ADI 040H ;A=79H,C=0,P=0,S=0,Z=0
|
||||
CNC CNCI ;TEST "CNC"
|
||||
ADI 040H ;A=53H,C=0,P=1,S=0,Z=0
|
||||
RP ;TEST "RP"
|
||||
CALL CPUER
|
||||
CNCI: RC ;TEST "RC"
|
||||
ADI 08FH ;A=08H,C=1,P=0,S=0,Z=0
|
||||
CC CCI ;TEST "CC"
|
||||
SUI 002H ;A=13H,C=0,P=0,S=0,Z=0
|
||||
RNC ;TEST "RNC"
|
||||
CALL CPUER
|
||||
CCI: RNC ;TEST "RNC"
|
||||
ADI 0F7H ;A=FFH,C=0,P=1,S=1,Z=0
|
||||
CNZ CNZI ;TEST "CNZ"
|
||||
ADI 0FEH ;A=15H,C=1,P=0,S=0,Z=0
|
||||
RC ;TEST "RC"
|
||||
CALL CPUER
|
||||
CNZI: RZ ;TEST "RZ"
|
||||
ADI 001H ;A=00H,C=1,P=1,S=0,Z=1
|
||||
CZ CZI ;TEST "CZ"
|
||||
ADI 0D0H ;A=17H,C=1,P=1,S=0,Z=0
|
||||
RNZ ;TEST "RNZ"
|
||||
CALL CPUER
|
||||
CZI: RNZ ;TEST "RNZ"
|
||||
ADI 047H ;A=47H,C=0,P=1,S=0,Z=0
|
||||
CPI 047H ;A=47H,C=0,P=1,S=0,Z=1
|
||||
RZ ;TEST "RZ"
|
||||
CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST "MOV","INR",AND "DCR" INSTRUCTIONS
|
||||
;
|
||||
MOVI: MVI A,077H
|
||||
INR A
|
||||
MOV B,A
|
||||
INR B
|
||||
MOV C,B
|
||||
DCR C
|
||||
MOV D,C
|
||||
MOV E,D
|
||||
MOV H,E
|
||||
MOV L,H
|
||||
MOV A,L ;TEST "MOV" A,L,H,E,D,C,B,A
|
||||
DCR A
|
||||
MOV C,A
|
||||
MOV E,C
|
||||
MOV L,E
|
||||
MOV B,L
|
||||
MOV D,B
|
||||
MOV H,D
|
||||
MOV A,H ;TEST "MOV" A,H,D,B,L,E,C,A
|
||||
MOV D,A
|
||||
INR D
|
||||
MOV L,D
|
||||
MOV C,L
|
||||
INR C
|
||||
MOV H,C
|
||||
MOV B,H
|
||||
DCR B
|
||||
MOV E,B
|
||||
MOV A,E ;TEST "MOV" A,E,B,H,C,L,D,A
|
||||
MOV E,A
|
||||
INR E
|
||||
MOV B,E
|
||||
MOV H,B
|
||||
INR H
|
||||
MOV C,H
|
||||
MOV L,C
|
||||
MOV D,L
|
||||
DCR D
|
||||
MOV A,D ;TEST "MOV" A,D,L,C,H,B,E,A
|
||||
MOV H,A
|
||||
DCR H
|
||||
MOV D,H
|
||||
MOV B,D
|
||||
MOV L,B
|
||||
INR L
|
||||
MOV E,L
|
||||
DCR E
|
||||
MOV C,E
|
||||
MOV A,C ;TEST "MOV" A,C,E,L,B,D,H,A
|
||||
MOV L,A
|
||||
DCR L
|
||||
MOV H,L
|
||||
MOV E,H
|
||||
MOV D,E
|
||||
MOV C,D
|
||||
MOV B,C
|
||||
MOV A,B
|
||||
CPI 077H
|
||||
CNZ CPUER ;TEST "MOV" A,B,C,D,E,H,L,A
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST ARITHMETIC AND LOGIC INSTRUCTIONS
|
||||
;
|
||||
XRA A
|
||||
MVI B,001H
|
||||
MVI C,003H
|
||||
MVI D,007H
|
||||
MVI E,00FH
|
||||
MVI H,01FH
|
||||
MVI L,03FH
|
||||
ADD B
|
||||
ADD C
|
||||
ADD D
|
||||
ADD E
|
||||
ADD H
|
||||
ADD L
|
||||
ADD A
|
||||
CPI 0F0H
|
||||
CNZ CPUER ;TEST "ADD" B,C,D,E,H,L,A
|
||||
SUB B
|
||||
SUB C
|
||||
SUB D
|
||||
SUB E
|
||||
SUB H
|
||||
SUB L
|
||||
CPI 078H
|
||||
CNZ CPUER ;TEST "SUB" B,C,D,E,H,L
|
||||
SUB A
|
||||
CNZ CPUER ;TEST "SUB" A
|
||||
MVI A,080H
|
||||
ADD A
|
||||
MVI B,001H
|
||||
MVI C,002H
|
||||
MVI D,003H
|
||||
MVI E,004H
|
||||
MVI H,005H
|
||||
MVI L,006H
|
||||
ADC B
|
||||
MVI B,080H
|
||||
ADD B
|
||||
ADD B
|
||||
ADC C
|
||||
ADD B
|
||||
ADD B
|
||||
ADC D
|
||||
ADD B
|
||||
ADD B
|
||||
ADC E
|
||||
ADD B
|
||||
ADD B
|
||||
ADC H
|
||||
ADD B
|
||||
ADD B
|
||||
ADC L
|
||||
ADD B
|
||||
ADD B
|
||||
ADC A
|
||||
CPI 037H
|
||||
CNZ CPUER ;TEST "ADC" B,C,D,E,H,L,A
|
||||
MVI A,080H
|
||||
ADD A
|
||||
MVI B,001H
|
||||
SBB B
|
||||
MVI B,0FFH
|
||||
ADD B
|
||||
SBB C
|
||||
ADD B
|
||||
SBB D
|
||||
ADD B
|
||||
SBB E
|
||||
ADD B
|
||||
SBB H
|
||||
ADD B
|
||||
SBB L
|
||||
CPI 0E0H
|
||||
CNZ CPUER ;TEST "SBB" B,C,D,E,H,L
|
||||
MVI A,080H
|
||||
ADD A
|
||||
SBB A
|
||||
CPI 0FFH
|
||||
CNZ CPUER ;TEST "SBB" A
|
||||
MVI A,0FFH
|
||||
MVI B,0FEH
|
||||
MVI C,0FCH
|
||||
MVI D,0EFH
|
||||
MVI E,07FH
|
||||
MVI H,0F4H
|
||||
MVI L,0BFH
|
||||
ANA B ;changed from ANA A (mwd)
|
||||
ANA C
|
||||
ANA D
|
||||
ANA E
|
||||
ANA H
|
||||
ANA L
|
||||
ANA A
|
||||
CPI 024H
|
||||
CNZ CPUER ;TEST "ANA" B,C,D,E,H,L,A
|
||||
XRA A
|
||||
MVI B,001H
|
||||
MVI C,002H
|
||||
MVI D,004H
|
||||
MVI E,008H
|
||||
MVI H,010H
|
||||
MVI L,020H
|
||||
ORA B
|
||||
ORA C
|
||||
ORA D
|
||||
ORA E
|
||||
ORA H
|
||||
ORA L
|
||||
ORA A
|
||||
CPI 03FH
|
||||
CNZ CPUER ;TEST "ORA" B,C,D,E,H,L,A
|
||||
MVI A,000H
|
||||
MVI H,08FH
|
||||
MVI L,04FH
|
||||
XRA B
|
||||
XRA C
|
||||
XRA D
|
||||
XRA E
|
||||
XRA H
|
||||
XRA L
|
||||
CPI 0CFH
|
||||
CNZ CPUER ;TEST "XRA" B,C,D,E,H,L
|
||||
XRA A
|
||||
CNZ CPUER ;TEST "XRA" A
|
||||
MVI B,044H
|
||||
MVI C,045H
|
||||
MVI D,046H
|
||||
MVI E,047H
|
||||
MVI H,(TEMP0 / 0FFH) ;HIGH BYTE OF TEST MEMORY LOCATION
|
||||
MVI L,(TEMP0 AND 0FFH) ;LOW BYTE OF TEST MEMORY LOCATION
|
||||
MOV M,B
|
||||
MVI B,000H
|
||||
MOV B,M
|
||||
MVI A,044H
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "MOV" M,B AND B,M
|
||||
MOV M,C ;added (mwd)
|
||||
MVI C,000H ;added (mwd)
|
||||
MOV C,M ;added (mwd)
|
||||
MVI A,045H ;added (mwd)
|
||||
CMP C ;added (mwd)
|
||||
CNZ CPUER ;TEST "MOV" M,C AND C,M added (mwd)
|
||||
MOV M,D
|
||||
MVI D,000H
|
||||
MOV D,M
|
||||
MVI A,046H
|
||||
CMP D
|
||||
CNZ CPUER ;TEST "MOV" M,D AND D,M
|
||||
MOV M,E
|
||||
MVI E,000H
|
||||
MOV E,M
|
||||
MVI A,047H
|
||||
CMP E
|
||||
CNZ CPUER ;TEST "MOV" M,E AND E,M
|
||||
MOV M,H
|
||||
MVI H,(TEMP0 / 0FFH)
|
||||
MVI L,(TEMP0 AND 0FFH)
|
||||
MOV H,M
|
||||
MVI A,(TEMP0 / 0FFH)
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "MOV" M,H AND H,M
|
||||
MOV M,L
|
||||
MVI H,(TEMP0 / 0FFH)
|
||||
MVI L,(TEMP0 AND 0FFH)
|
||||
MOV L,M
|
||||
MVI A,(TEMP0 AND 0FFH)
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "MOV" M,L AND L,M
|
||||
MVI H,(TEMP0 / 0FFH)
|
||||
MVI L,(TEMP0 AND 0FFH)
|
||||
MVI A,032H
|
||||
MOV M,A
|
||||
CMP M
|
||||
CNZ CPUER ;TEST "MOV" M,A
|
||||
ADD M
|
||||
CPI 064H
|
||||
CNZ CPUER ;TEST "ADD" M
|
||||
XRA A
|
||||
MOV A,M
|
||||
CPI 032H
|
||||
CNZ CPUER ;TEST "MOV" A,M
|
||||
MVI H,(TEMP0 / 0FFH)
|
||||
MVI L,(TEMP0 AND 0FFH)
|
||||
MOV A,M
|
||||
SUB M
|
||||
CNZ CPUER ;TEST "SUB" M
|
||||
MVI A,080H
|
||||
ADD A
|
||||
ADC M
|
||||
CPI 033H
|
||||
CNZ CPUER ;TEST "ADC" M
|
||||
MVI A,080H
|
||||
ADD A
|
||||
SBB M
|
||||
CPI 0CDH
|
||||
CNZ CPUER ;TEST "SBB" M
|
||||
ANA M
|
||||
CNZ CPUER ;TEST "ANA" M
|
||||
MVI A,025H
|
||||
ORA M
|
||||
CPI 037H
|
||||
CNZ CPUER ;TEST "ORA" M
|
||||
XRA M
|
||||
CPI 005H
|
||||
CNZ CPUER ;TEST "XRA" M
|
||||
MVI M,055H
|
||||
INR M
|
||||
DCR M
|
||||
ADD M
|
||||
CPI 05AH
|
||||
CNZ CPUER ;TEST "INR","DCR",AND "MVI" M
|
||||
LXI B,12FFH
|
||||
LXI D,12FFH
|
||||
LXI H,12FFH
|
||||
INX B
|
||||
INX D
|
||||
INX H
|
||||
MVI A,013H
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" B
|
||||
CMP D
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" D
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" H
|
||||
MVI A,000H
|
||||
CMP C
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" B
|
||||
CMP E
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" D
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "LXI" AND "INX" H
|
||||
DCX B
|
||||
DCX D
|
||||
DCX H
|
||||
MVI A,012H
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "DCX" B
|
||||
CMP D
|
||||
CNZ CPUER ;TEST "DCX" D
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "DCX" H
|
||||
MVI A,0FFH
|
||||
CMP C
|
||||
CNZ CPUER ;TEST "DCX" B
|
||||
CMP E
|
||||
CNZ CPUER ;TEST "DCX" D
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "DCX" H
|
||||
STA TEMP0
|
||||
XRA A
|
||||
LDA TEMP0
|
||||
CPI 0FFH
|
||||
CNZ CPUER ;TEST "LDA" AND "STA"
|
||||
LHLD TEMPP
|
||||
SHLD TEMP0
|
||||
LDA TEMPP
|
||||
MOV B,A
|
||||
LDA TEMP0
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "LHLD" AND "SHLD"
|
||||
LDA TEMPP+1
|
||||
MOV B,A
|
||||
LDA TEMP0+1
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "LHLD" AND "SHLD"
|
||||
MVI A,0AAH
|
||||
STA TEMP0
|
||||
MOV B,H
|
||||
MOV C,L
|
||||
XRA A
|
||||
LDAX B
|
||||
CPI 0AAH
|
||||
CNZ CPUER ;TEST "LDAX" B
|
||||
INR A
|
||||
STAX B
|
||||
LDA TEMP0
|
||||
CPI 0ABH
|
||||
CNZ CPUER ;TEST "STAX" B
|
||||
MVI A,077H
|
||||
STA TEMP0
|
||||
LHLD TEMPP
|
||||
LXI D,00000H
|
||||
XCHG
|
||||
XRA A
|
||||
LDAX D
|
||||
CPI 077H
|
||||
CNZ CPUER ;TEST "LDAX" D AND "XCHG"
|
||||
XRA A
|
||||
ADD H
|
||||
ADD L
|
||||
CNZ CPUER ;TEST "XCHG"
|
||||
MVI A,0CCH
|
||||
STAX D
|
||||
LDA TEMP0
|
||||
CPI 0CCH
|
||||
STAX D
|
||||
LDA TEMP0
|
||||
CPI 0CCH
|
||||
CNZ CPUER ;TEST "STAX" D
|
||||
LXI H,07777H
|
||||
DAD H
|
||||
MVI A,0EEH
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "DAD" H
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "DAD" H
|
||||
LXI H,05555H
|
||||
LXI B,0FFFFH
|
||||
DAD B
|
||||
MVI A,055H
|
||||
CNC CPUER ;TEST "DAD" B
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "DAD" B
|
||||
MVI A,054H
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "DAD" B
|
||||
LXI H,0AAAAH
|
||||
LXI D,03333H
|
||||
DAD D
|
||||
MVI A,0DDH
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "DAD" D
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "DAD" B
|
||||
STC
|
||||
CNC CPUER ;TEST "STC"
|
||||
CMC
|
||||
CC CPUER ;TEST "CMC
|
||||
MVI A,0AAH
|
||||
CMA
|
||||
CPI 055H
|
||||
CNZ CPUER ;TEST "CMA"
|
||||
ORA A ;RE-SET AUXILIARY CARRY
|
||||
DAA
|
||||
CPI 055H
|
||||
CNZ CPUER ;TEST "DAA"
|
||||
MVI A,088H
|
||||
ADD A
|
||||
DAA
|
||||
CPI 076H
|
||||
CNZ CPUER ;TEST "DAA"
|
||||
XRA A
|
||||
MVI A,0AAH
|
||||
DAA
|
||||
CNC CPUER ;TEST "DAA"
|
||||
CPI 010H
|
||||
CNZ CPUER ;TEST "DAA"
|
||||
XRA A
|
||||
MVI A,09AH
|
||||
DAA
|
||||
CNC CPUER ;TEST "DAA"
|
||||
CNZ CPUER ;TEST "DAA"
|
||||
STC
|
||||
MVI A,042H
|
||||
RLC
|
||||
CC CPUER ;TEST "RLC" FOR RE-SET CARRY
|
||||
RLC
|
||||
CNC CPUER ;TEST "RLC" FOR SET CARRY
|
||||
CPI 009H
|
||||
CNZ CPUER ;TEST "RLC" FOR ROTATION
|
||||
RRC
|
||||
CNC CPUER ;TEST "RRC" FOR SET CARRY
|
||||
RRC
|
||||
CPI 042H
|
||||
CNZ CPUER ;TEST "RRC" FOR ROTATION
|
||||
RAL
|
||||
RAL
|
||||
CNC CPUER ;TEST "RAL" FOR SET CARRY
|
||||
CPI 008H
|
||||
CNZ CPUER ;TEST "RAL" FOR ROTATION
|
||||
RAR
|
||||
RAR
|
||||
CC CPUER ;TEST "RAR" FOR RE-SET CARRY
|
||||
CPI 002H
|
||||
CNZ CPUER ;TEST "RAR" FOR ROTATION
|
||||
LXI B,01234H
|
||||
LXI D,0AAAAH
|
||||
LXI H,05555H
|
||||
XRA A
|
||||
PUSH B
|
||||
PUSH D
|
||||
PUSH H
|
||||
PUSH PSW
|
||||
LXI B,00000H
|
||||
LXI D,00000H
|
||||
LXI H,00000H
|
||||
MVI A,0C0H
|
||||
ADI 0F0H
|
||||
POP PSW
|
||||
POP H
|
||||
POP D
|
||||
POP B
|
||||
CC CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
CNZ CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
CPO CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
CM CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
MVI A,012H
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "PUSH B" AND "POP B"
|
||||
MVI A,034H
|
||||
CMP C
|
||||
CNZ CPUER ;TEST "PUSH B" AND "POP B"
|
||||
MVI A,0AAH
|
||||
CMP D
|
||||
CNZ CPUER ;TEST "PUSH D" AND "POP D"
|
||||
CMP E
|
||||
CNZ CPUER ;TEST "PUSH D" AND "POP D"
|
||||
MVI A,055H
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "PUSH H" AND "POP H"
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "PUSH H" AND "POP H"
|
||||
LXI H,00000H
|
||||
DAD SP
|
||||
SHLD SAVSTK ;SAVE THE "OLD" STACK-POINTER!
|
||||
LXI SP,TEMP4
|
||||
DCX SP
|
||||
DCX SP
|
||||
INX SP
|
||||
DCX SP
|
||||
MVI A,055H
|
||||
STA TEMP2
|
||||
CMA
|
||||
STA TEMP3
|
||||
POP B
|
||||
CMP B
|
||||
CNZ CPUER ;TEST "LXI","DAD","INX",AND "DCX" SP
|
||||
CMA
|
||||
CMP C
|
||||
CNZ CPUER ;TEST "LXI","DAD","INX", AND "DCX" SP
|
||||
LXI H,TEMP4
|
||||
SPHL
|
||||
LXI H,07733H
|
||||
DCX SP
|
||||
DCX SP
|
||||
XTHL
|
||||
LDA TEMP3
|
||||
CPI 077H
|
||||
CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
LDA TEMP2
|
||||
CPI 033H
|
||||
CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
MVI A,055H
|
||||
CMP L
|
||||
CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
CMA
|
||||
CMP H
|
||||
CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
LHLD SAVSTK ;RESTORE THE "OLD" STACK-POINTER
|
||||
SPHL
|
||||
LXI H,CPUOK
|
||||
PCHL ;TEST "PCHL"
|
||||
;
|
||||
;
|
||||
;
|
||||
CPUER: LXI H,NGCPU ;OUTPUT "CPU HAS FAILED ERROR EXIT=" TO CONSOLE
|
||||
CALL MSG
|
||||
POP H ;HL = ADDRESS FOLLOWING CALL CPUER
|
||||
PUSH H
|
||||
MOV A,H
|
||||
CALL BYTEO ;SHOW ERROR EXIT ADDRESS HIGH BYTE
|
||||
POP H
|
||||
MOV A,L
|
||||
CALL BYTEO ;SHOW ERROR EXIT ADDRESS LOW BYTE
|
||||
JMP WBOOT ;EXIT TO CP/M WARM BOOT
|
||||
;
|
||||
;
|
||||
;
|
||||
CPUOK: LXI H,OKCPU ;OUTPUT "CPU IS OPERATIONAL" TO CONSOLE
|
||||
CALL MSG
|
||||
JMP WBOOT ;EXIT TO CP/M WARM BOOT
|
||||
;
|
||||
;
|
||||
;
|
||||
TEMPP: DW TEMP0 ;POINTER USED TO TEST "LHLD","SHLD",
|
||||
; AND "LDAX" INSTRUCTIONS
|
||||
;
|
||||
TEMP0: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
TEMP1: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
TEMP2 DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
TEMP3: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
TEMP4: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
SAVSTK: DS 2 ;TEMPORARY STACK-POINTER STORAGE LOCATION
|
||||
;
|
||||
;
|
||||
;
|
||||
STACK EQU TEMPP+256 ;DE-BUG STACK POINTER STORAGE AREA
|
||||
;
|
||||
;
|
||||
;
|
||||
END
|
||||
BIN
Intel8080/Intel8080.Test/roms/TST8080.COM
Normal file
BIN
Intel8080/Intel8080.Test/roms/TST8080.COM
Normal file
Binary file not shown.
821
Intel8080/Intel8080.Test/roms/TST8080.PRN
Normal file
821
Intel8080/Intel8080.Test/roms/TST8080.PRN
Normal file
@@ -0,0 +1,821 @@
|
||||
|
||||
|
||||
;***********************************************************************
|
||||
; MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC VERSION 1.0 (C) 1980
|
||||
;***********************************************************************
|
||||
;
|
||||
;DONATED TO THE "SIG/M" CP/M USER'S GROUP BY:
|
||||
;KELLY SMITH, MICROCOSM ASSOCIATES
|
||||
;3055 WACO AVENUE
|
||||
;SIMI VALLEY, CALIFORNIA, 93065
|
||||
;(805) 527-9321 (MODEM, CP/M-NET (TM))
|
||||
;(805) 527-0518 (VERBAL)
|
||||
;
|
||||
; Updated by Mike Douglas October, 2012
|
||||
;
|
||||
; Added the following tests that were missing:
|
||||
; mov c,m
|
||||
; mov m,c
|
||||
; ana b
|
||||
;
|
||||
; Fixed the CPUER exit routine which did not display the
|
||||
; low byte of the failure address properly.
|
||||
;
|
||||
; Added display of the Microcosm welcome message
|
||||
;
|
||||
0100 ORG 00100H
|
||||
|
||||
;
|
||||
0100 C3B201 JMP CPU ;JUMP TO 8080 CPU DIAGNOSTIC
|
||||
;
|
||||
0103 4D4943524FWELCOM DB 'MICROCOSM ASSOCIATES 8080/8085 CPU DIAGNOSTIC',13,10
|
||||
0132 2056455253 DB ' VERSION 1.0 (C) 1980',13,10,'$'
|
||||
;
|
||||
0005 = BDOS EQU 00005H ;BDOS ENTRY TO CP/M
|
||||
0000 = WBOOT EQU 00000H ;RE-ENTRY TO CP/M WARM BOOT
|
||||
;
|
||||
;
|
||||
;
|
||||
;MESSAGE OUTPUT ROUTINE
|
||||
;
|
||||
014B D5 MSG: PUSH D ;EXILE D REG.
|
||||
014C EB XCHG ;SWAP H&L REGS. TO D&E REGS.
|
||||
014D 0E09 MVI C,9 ;LET BDOS KNOW WE WANT TO SEND A MESSAGE
|
||||
014F CD0500 CALL BDOS
|
||||
0152 D1 POP D ;BACK FROM EXILE
|
||||
0153 C9 RET
|
||||
;
|
||||
;
|
||||
;
|
||||
;CHARACTER OUTPUT ROUTINE
|
||||
;
|
||||
0154 0E02 PCHAR: MVI C,2
|
||||
0156 CD0500 CALL BDOS
|
||||
0159 C9 RET
|
||||
;
|
||||
;
|
||||
;
|
||||
015A F5 BYTEO: PUSH PSW
|
||||
015B CD6A01 CALL BYTO1
|
||||
015E 5F MOV E,A
|
||||
015F CD5401 CALL PCHAR
|
||||
0162 F1 POP PSW
|
||||
0163 CD6E01 CALL BYTO2
|
||||
0166 5F MOV E,A
|
||||
0167 C35401 JMP PCHAR
|
||||
016A 0F BYTO1: RRC
|
||||
016B 0F RRC
|
||||
016C 0F RRC
|
||||
016D 0F RRC
|
||||
016E E60F BYTO2: ANI 0FH
|
||||
0170 FE0A CPI 0AH
|
||||
0172 FA7701 JM BYTO3
|
||||
0175 C607 ADI 7
|
||||
0177 C630 BYTO3: ADI 30H
|
||||
0179 C9 RET
|
||||
;
|
||||
;
|
||||
;
|
||||
;************************************************************
|
||||
; MESSAGE TABLE FOR OPERATIONAL CPU TEST
|
||||
;************************************************************
|
||||
;
|
||||
017A 0D0A204350OKCPU: DB 0DH,0AH,' CPU IS OPERATIONAL$'
|
||||
;
|
||||
0190 0D0A204350NGCPU: DB 0DH,0AH,' CPU HAS FAILED! ERROR EXIT=$'
|
||||
;
|
||||
;
|
||||
;
|
||||
;************************************************************
|
||||
; 8080/8085 CPU TEST/DIAGNOSTIC
|
||||
;************************************************************
|
||||
;
|
||||
;NOTE: (1) PROGRAM ASSUMES "CALL",AND "LXI SP" INSTRUCTIONS WORK!
|
||||
;
|
||||
; (2) INSTRUCTIONS NOT TESTED ARE "HLT","DI","EI","RIM","SIM",
|
||||
; AND "RST 0" THRU "RST 7"
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST JUMP INSTRUCTIONS AND FLAGS
|
||||
;
|
||||
01B2 31BD07 CPU: LXI SP,STACK ;SET THE STACK POINTER
|
||||
01B5 210301 LXI H,WELCOM
|
||||
01B8 CD4B01 CALL MSG
|
||||
01BB E600 ANI 0 ;INITIALIZE A REG. AND CLEAR ALL FLAGS
|
||||
01BD CAC301 JZ J010 ;TEST "JZ"
|
||||
01C0 CDA006 CALL CPUER
|
||||
01C3 D2C901 J010: JNC J020 ;TEST "JNC"
|
||||
01C6 CDA006 CALL CPUER
|
||||
01C9 EACF01 J020: JPE J030 ;TEST "JPE"
|
||||
01CC CDA006 CALL CPUER
|
||||
01CF F2D501 J030: JP J040 ;TEST "JP"
|
||||
01D2 CDA006 CALL CPUER
|
||||
01D5 C2E401 J040: JNZ J050 ;TEST "JNZ"
|
||||
01D8 DAE401 JC J050 ;TEST "JC"
|
||||
01DB E2E401 JPO J050 ;TEST "JPO"
|
||||
01DE FAE401 JM J050 ;TEST "JM"
|
||||
01E1 C3E701 JMP J060 ;TEST "JMP" (IT'S A LITTLE LATE,BUT WHAT THE HELL!
|
||||
01E4 CDA006 J050: CALL CPUER
|
||||
01E7 C606 J060: ADI 6 ;A=6,C=0,P=1,S=0,Z=0
|
||||
01E9 C2EF01 JNZ J070 ;TEST "JNZ"
|
||||
01EC CDA006 CALL CPUER
|
||||
01EF DAF801 J070: JC J080 ;TEST "JC"
|
||||
01F2 E2F801 JPO J080 ;TEST "JPO"
|
||||
01F5 F2FB01 JP J090 ;TEST "JP"
|
||||
01F8 CDA006 J080: CALL CPUER
|
||||
01FB C670 J090: ADI 070H ;A=76H,C=0,P=0,S=0,Z=0
|
||||
01FD E20302 JPO J100 ;TEST "JPO"
|
||||
0200 CDA006 CALL CPUER
|
||||
0203 FA0C02 J100: JM J110 ;TEST "JM"
|
||||
0206 CA0C02 JZ J110 ;TEST "JZ"
|
||||
0209 D20F02 JNC J120 ;TEST "JNC"
|
||||
020C CDA006 J110: CALL CPUER
|
||||
020F C681 J120: ADI 081H ;A=F7H,C=0,P=0,S=1,Z=0
|
||||
0211 FA1702 JM J130 ;TEST "JM"
|
||||
0214 CDA006 CALL CPUER
|
||||
0217 CA2002 J130: JZ J140 ;TEST "JZ"
|
||||
021A DA2002 JC J140 ;TEST "JC"
|
||||
021D E22302 JPO J150 ;TEST "JPO"
|
||||
0220 CDA006 J140: CALL CPUER
|
||||
0223 C6FE J150: ADI 0FEH ;A=F5H,C=1,P=1,S=1,Z=0
|
||||
0225 DA2B02 JC J160 ;TEST "JC"
|
||||
0228 CDA006 CALL CPUER
|
||||
022B CA3402 J160: JZ J170 ;TEST "JZ"
|
||||
022E E23402 JPO J170 ;TEST "JPO"
|
||||
0231 FA3702 JM AIMM ;TEST "JM"
|
||||
0234 CDA006 J170: CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST ACCUMULATOR IMMEDIATE INSTRUCTIONS
|
||||
;
|
||||
0237 FE00 AIMM: CPI 0 ;A=F5H,C=0,Z=0
|
||||
0239 DA4F02 JC CPIE ;TEST "CPI" FOR RE-SET CARRY
|
||||
023C CA4F02 JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
023F FEF5 CPI 0F5H ;A=F5H,C=0,Z=1
|
||||
0241 DA4F02 JC CPIE ;TEST "CPI" FOR RE-SET CARRY ("ADI")
|
||||
0244 C24F02 JNZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
0247 FEFF CPI 0FFH ;A=F5H,C=1,Z=0
|
||||
0249 CA4F02 JZ CPIE ;TEST "CPI" FOR RE-SET ZERO
|
||||
024C DA5202 JC ACII ;TEST "CPI" FOR SET CARRY
|
||||
024F CDA006 CPIE: CALL CPUER
|
||||
0252 CE0A ACII: ACI 00AH ;A=F5H+0AH+CARRY(1)=0,C=1
|
||||
0254 CE0A ACI 00AH ;A=0+0AH+CARRY(0)=0BH,C=0
|
||||
0256 FE0B CPI 00BH
|
||||
0258 CA5E02 JZ SUII ;TEST "ACI"
|
||||
025B CDA006 CALL CPUER
|
||||
025E D60C SUII: SUI 00CH ;A=FFH,C=0
|
||||
0260 D60F SUI 00FH ;A=F0H,C=1
|
||||
0262 FEF0 CPI 0F0H
|
||||
0264 CA6A02 JZ SBII ;TEST "SUI"
|
||||
0267 CDA006 CALL CPUER
|
||||
026A DEF1 SBII: SBI 0F1H ;A=F0H-0F1H-CARRY(0)=FFH,C=1
|
||||
026C DE0E SBI 00EH ;A=FFH-OEH-CARRY(1)=F0H,C=0
|
||||
026E FEF0 CPI 0F0H
|
||||
0270 CA7602 JZ ANII ;TEST "SBI"
|
||||
0273 CDA006 CALL CPUER
|
||||
0276 E655 ANII: ANI 055H ;A=F0H<AND>55H=50H,C=0,P=1,S=0,Z=0
|
||||
0278 FE50 CPI 050H
|
||||
027A CA8002 JZ ORII ;TEST "ANI"
|
||||
027D CDA006 CALL CPUER
|
||||
0280 F63A ORII: ORI 03AH ;A=50H<OR>3AH=7AH,C=0,P=0,S=0,Z=0
|
||||
0282 FE7A CPI 07AH
|
||||
0284 CA8A02 JZ XRII ;TEST "ORI"
|
||||
0287 CDA006 CALL CPUER
|
||||
028A EE0F XRII: XRI 00FH ;A=7AH<XOR>0FH=75H,C=0,P=0,S=0,Z=0
|
||||
028C FE75 CPI 075H
|
||||
028E CA9402 JZ C010 ;TEST "XRI"
|
||||
0291 CDA006 CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST CALLS AND RETURNS
|
||||
;
|
||||
0294 E600 C010: ANI 000H ;A=0,C=0,P=1,S=0,Z=1
|
||||
0296 DCA006 CC CPUER ;TEST "CC"
|
||||
0299 E4A006 CPO CPUER ;TEST "CPO"
|
||||
029C FCA006 CM CPUER ;TEST "CM"
|
||||
029F C4A006 CNZ CPUER ;TEST "CNZ"
|
||||
02A2 FE00 CPI 000H
|
||||
02A4 CAAA02 JZ C020 ;A=0,C=0,P=0,S=0,Z=1
|
||||
02A7 CDA006 CALL CPUER
|
||||
02AA D677 C020: SUI 077H ;A=89H,C=1,P=0,S=1,Z=0
|
||||
02AC D4A006 CNC CPUER ;TEST "CNC"
|
||||
02AF ECA006 CPE CPUER ;TEST "CPE"
|
||||
02B2 F4A006 CP CPUER ;TEST "CP"
|
||||
02B5 CCA006 CZ CPUER ;TEST "CZ"
|
||||
02B8 FE89 CPI 089H
|
||||
02BA CAC002 JZ C030 ;TEST FOR "CALLS" TAKING BRANCH
|
||||
02BD CDA006 CALL CPUER
|
||||
02C0 E6FF C030: ANI 0FFH ;SET FLAGS BACK!
|
||||
02C2 E4CD02 CPO CPOI ;TEST "CPO"
|
||||
02C5 FED9 CPI 0D9H
|
||||
02C7 CA2A03 JZ MOVI ;TEST "CALL" SEQUENCE SUCCESS
|
||||
02CA CDA006 CALL CPUER
|
||||
02CD E8 CPOI: RPE ;TEST "RPE"
|
||||
02CE C610 ADI 010H ;A=99H,C=0,P=0,S=1,Z=0
|
||||
02D0 ECD902 CPE CPEI ;TEST "CPE"
|
||||
02D3 C602 ADI 002H ;A=D9H,C=0,P=0,S=1,Z=0
|
||||
02D5 E0 RPO ;TEST "RPO"
|
||||
02D6 CDA006 CALL CPUER
|
||||
02D9 E0 CPEI: RPO ;TEST "RPO"
|
||||
02DA C620 ADI 020H ;A=B9H,C=0,P=0,S=1,Z=0
|
||||
02DC FCE502 CM CMI ;TEST "CM"
|
||||
02DF C604 ADI 004H ;A=D7H,C=0,P=1,S=1,Z=0
|
||||
02E1 E8 RPE ;TEST "RPE"
|
||||
02E2 CDA006 CALL CPUER
|
||||
02E5 F0 CMI: RP ;TEST "RP"
|
||||
02E6 C680 ADI 080H ;A=39H,C=1,P=1,S=0,Z=0
|
||||
02E8 F4F102 CP TCPI ;TEST "CP"
|
||||
02EB C680 ADI 080H ;A=D3H,C=0,P=0,S=1,Z=0
|
||||
02ED F8 RM ;TEST "RM"
|
||||
02EE CDA006 CALL CPUER
|
||||
02F1 F8 TCPI: RM ;TEST "RM"
|
||||
02F2 C640 ADI 040H ;A=79H,C=0,P=0,S=0,Z=0
|
||||
02F4 D4FD02 CNC CNCI ;TEST "CNC"
|
||||
02F7 C640 ADI 040H ;A=53H,C=0,P=1,S=0,Z=0
|
||||
02F9 F0 RP ;TEST "RP"
|
||||
02FA CDA006 CALL CPUER
|
||||
02FD D8 CNCI: RC ;TEST "RC"
|
||||
02FE C68F ADI 08FH ;A=08H,C=1,P=0,S=0,Z=0
|
||||
0300 DC0903 CC CCI ;TEST "CC"
|
||||
0303 D602 SUI 002H ;A=13H,C=0,P=0,S=0,Z=0
|
||||
0305 D0 RNC ;TEST "RNC"
|
||||
0306 CDA006 CALL CPUER
|
||||
0309 D0 CCI: RNC ;TEST "RNC"
|
||||
030A C6F7 ADI 0F7H ;A=FFH,C=0,P=1,S=1,Z=0
|
||||
030C C41503 CNZ CNZI ;TEST "CNZ"
|
||||
030F C6FE ADI 0FEH ;A=15H,C=1,P=0,S=0,Z=0
|
||||
0311 D8 RC ;TEST "RC"
|
||||
0312 CDA006 CALL CPUER
|
||||
0315 C8 CNZI: RZ ;TEST "RZ"
|
||||
0316 C601 ADI 001H ;A=00H,C=1,P=1,S=0,Z=1
|
||||
0318 CC2103 CZ CZI ;TEST "CZ"
|
||||
031B C6D0 ADI 0D0H ;A=17H,C=1,P=1,S=0,Z=0
|
||||
031D C0 RNZ ;TEST "RNZ"
|
||||
031E CDA006 CALL CPUER
|
||||
0321 C0 CZI: RNZ ;TEST "RNZ"
|
||||
0322 C647 ADI 047H ;A=47H,C=0,P=1,S=0,Z=0
|
||||
0324 FE47 CPI 047H ;A=47H,C=0,P=1,S=0,Z=1
|
||||
0326 C8 RZ ;TEST "RZ"
|
||||
0327 CDA006 CALL CPUER
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST "MOV","INR",AND "DCR" INSTRUCTIONS
|
||||
;
|
||||
032A 3E77 MOVI: MVI A,077H
|
||||
032C 3C INR A
|
||||
032D 47 MOV B,A
|
||||
032E 04 INR B
|
||||
032F 48 MOV C,B
|
||||
0330 0D DCR C
|
||||
0331 51 MOV D,C
|
||||
0332 5A MOV E,D
|
||||
0333 63 MOV H,E
|
||||
0334 6C MOV L,H
|
||||
0335 7D MOV A,L ;TEST "MOV" A,L,H,E,D,C,B,A
|
||||
0336 3D DCR A
|
||||
0337 4F MOV C,A
|
||||
0338 59 MOV E,C
|
||||
0339 6B MOV L,E
|
||||
033A 45 MOV B,L
|
||||
033B 50 MOV D,B
|
||||
033C 62 MOV H,D
|
||||
033D 7C MOV A,H ;TEST "MOV" A,H,D,B,L,E,C,A
|
||||
033E 57 MOV D,A
|
||||
033F 14 INR D
|
||||
0340 6A MOV L,D
|
||||
0341 4D MOV C,L
|
||||
0342 0C INR C
|
||||
0343 61 MOV H,C
|
||||
0344 44 MOV B,H
|
||||
0345 05 DCR B
|
||||
0346 58 MOV E,B
|
||||
0347 7B MOV A,E ;TEST "MOV" A,E,B,H,C,L,D,A
|
||||
0348 5F MOV E,A
|
||||
0349 1C INR E
|
||||
034A 43 MOV B,E
|
||||
034B 60 MOV H,B
|
||||
034C 24 INR H
|
||||
034D 4C MOV C,H
|
||||
034E 69 MOV L,C
|
||||
034F 55 MOV D,L
|
||||
0350 15 DCR D
|
||||
0351 7A MOV A,D ;TEST "MOV" A,D,L,C,H,B,E,A
|
||||
0352 67 MOV H,A
|
||||
0353 25 DCR H
|
||||
0354 54 MOV D,H
|
||||
0355 42 MOV B,D
|
||||
0356 68 MOV L,B
|
||||
0357 2C INR L
|
||||
0358 5D MOV E,L
|
||||
0359 1D DCR E
|
||||
035A 4B MOV C,E
|
||||
035B 79 MOV A,C ;TEST "MOV" A,C,E,L,B,D,H,A
|
||||
035C 6F MOV L,A
|
||||
035D 2D DCR L
|
||||
035E 65 MOV H,L
|
||||
035F 5C MOV E,H
|
||||
0360 53 MOV D,E
|
||||
0361 4A MOV C,D
|
||||
0362 41 MOV B,C
|
||||
0363 78 MOV A,B
|
||||
0364 FE77 CPI 077H
|
||||
0366 C4A006 CNZ CPUER ;TEST "MOV" A,B,C,D,E,H,L,A
|
||||
;
|
||||
;
|
||||
;
|
||||
;TEST ARITHMETIC AND LOGIC INSTRUCTIONS
|
||||
;
|
||||
0369 AF XRA A
|
||||
036A 0601 MVI B,001H
|
||||
036C 0E03 MVI C,003H
|
||||
036E 1607 MVI D,007H
|
||||
0370 1E0F MVI E,00FH
|
||||
0372 261F MVI H,01FH
|
||||
0374 2E3F MVI L,03FH
|
||||
0376 80 ADD B
|
||||
0377 81 ADD C
|
||||
0378 82 ADD D
|
||||
0379 83 ADD E
|
||||
037A 84 ADD H
|
||||
037B 85 ADD L
|
||||
037C 87 ADD A
|
||||
037D FEF0 CPI 0F0H
|
||||
037F C4A006 CNZ CPUER ;TEST "ADD" B,C,D,E,H,L,A
|
||||
0382 90 SUB B
|
||||
0383 91 SUB C
|
||||
0384 92 SUB D
|
||||
0385 93 SUB E
|
||||
0386 94 SUB H
|
||||
0387 95 SUB L
|
||||
0388 FE78 CPI 078H
|
||||
038A C4A006 CNZ CPUER ;TEST "SUB" B,C,D,E,H,L
|
||||
038D 97 SUB A
|
||||
038E C4A006 CNZ CPUER ;TEST "SUB" A
|
||||
0391 3E80 MVI A,080H
|
||||
0393 87 ADD A
|
||||
0394 0601 MVI B,001H
|
||||
0396 0E02 MVI C,002H
|
||||
0398 1603 MVI D,003H
|
||||
039A 1E04 MVI E,004H
|
||||
039C 2605 MVI H,005H
|
||||
039E 2E06 MVI L,006H
|
||||
03A0 88 ADC B
|
||||
03A1 0680 MVI B,080H
|
||||
03A3 80 ADD B
|
||||
03A4 80 ADD B
|
||||
03A5 89 ADC C
|
||||
03A6 80 ADD B
|
||||
03A7 80 ADD B
|
||||
03A8 8A ADC D
|
||||
03A9 80 ADD B
|
||||
03AA 80 ADD B
|
||||
03AB 8B ADC E
|
||||
03AC 80 ADD B
|
||||
03AD 80 ADD B
|
||||
03AE 8C ADC H
|
||||
03AF 80 ADD B
|
||||
03B0 80 ADD B
|
||||
03B1 8D ADC L
|
||||
03B2 80 ADD B
|
||||
03B3 80 ADD B
|
||||
03B4 8F ADC A
|
||||
03B5 FE37 CPI 037H
|
||||
03B7 C4A006 CNZ CPUER ;TEST "ADC" B,C,D,E,H,L,A
|
||||
03BA 3E80 MVI A,080H
|
||||
03BC 87 ADD A
|
||||
03BD 0601 MVI B,001H
|
||||
03BF 98 SBB B
|
||||
03C0 06FF MVI B,0FFH
|
||||
03C2 80 ADD B
|
||||
03C3 99 SBB C
|
||||
03C4 80 ADD B
|
||||
03C5 9A SBB D
|
||||
03C6 80 ADD B
|
||||
03C7 9B SBB E
|
||||
03C8 80 ADD B
|
||||
03C9 9C SBB H
|
||||
03CA 80 ADD B
|
||||
03CB 9D SBB L
|
||||
03CC FEE0 CPI 0E0H
|
||||
03CE C4A006 CNZ CPUER ;TEST "SBB" B,C,D,E,H,L
|
||||
03D1 3E80 MVI A,080H
|
||||
03D3 87 ADD A
|
||||
03D4 9F SBB A
|
||||
03D5 FEFF CPI 0FFH
|
||||
03D7 C4A006 CNZ CPUER ;TEST "SBB" A
|
||||
03DA 3EFF MVI A,0FFH
|
||||
03DC 06FE MVI B,0FEH
|
||||
03DE 0EFC MVI C,0FCH
|
||||
03E0 16EF MVI D,0EFH
|
||||
03E2 1E7F MVI E,07FH
|
||||
03E4 26F4 MVI H,0F4H
|
||||
03E6 2EBF MVI L,0BFH
|
||||
03E8 A0 ANA B ;changed from ANA A (mwd)
|
||||
03E9 A1 ANA C
|
||||
03EA A2 ANA D
|
||||
03EB A3 ANA E
|
||||
03EC A4 ANA H
|
||||
03ED A5 ANA L
|
||||
03EE A7 ANA A
|
||||
03EF FE24 CPI 024H
|
||||
03F1 C4A006 CNZ CPUER ;TEST "ANA" B,C,D,E,H,L,A
|
||||
03F4 AF XRA A
|
||||
03F5 0601 MVI B,001H
|
||||
03F7 0E02 MVI C,002H
|
||||
03F9 1604 MVI D,004H
|
||||
03FB 1E08 MVI E,008H
|
||||
03FD 2610 MVI H,010H
|
||||
03FF 2E20 MVI L,020H
|
||||
0401 B0 ORA B
|
||||
0402 B1 ORA C
|
||||
0403 B2 ORA D
|
||||
0404 B3 ORA E
|
||||
0405 B4 ORA H
|
||||
0406 B5 ORA L
|
||||
0407 B7 ORA A
|
||||
0408 FE3F CPI 03FH
|
||||
040A C4A006 CNZ CPUER ;TEST "ORA" B,C,D,E,H,L,A
|
||||
040D 3E00 MVI A,000H
|
||||
040F 268F MVI H,08FH
|
||||
0411 2E4F MVI L,04FH
|
||||
0413 A8 XRA B
|
||||
0414 A9 XRA C
|
||||
0415 AA XRA D
|
||||
0416 AB XRA E
|
||||
0417 AC XRA H
|
||||
0418 AD XRA L
|
||||
0419 FECF CPI 0CFH
|
||||
041B C4A006 CNZ CPUER ;TEST "XRA" B,C,D,E,H,L
|
||||
041E AF XRA A
|
||||
041F C4A006 CNZ CPUER ;TEST "XRA" A
|
||||
0422 0644 MVI B,044H
|
||||
0424 0E45 MVI C,045H
|
||||
0426 1646 MVI D,046H
|
||||
0428 1E47 MVI E,047H
|
||||
042A 2606 MVI H,(TEMP0 / 0FFH) ;HIGH BYTE OF TEST MEMORY LOCATION
|
||||
042C 2EBF MVI L,(TEMP0 AND 0FFH) ;LOW BYTE OF TEST MEMORY LOCATION
|
||||
042E 70 MOV M,B
|
||||
042F 0600 MVI B,000H
|
||||
0431 46 MOV B,M
|
||||
0432 3E44 MVI A,044H
|
||||
0434 B8 CMP B
|
||||
0435 C4A006 CNZ CPUER ;TEST "MOV" M,B AND B,M
|
||||
0438 71 MOV M,C ;added (mwd)
|
||||
0439 0E00 MVI C,000H ;added (mwd)
|
||||
043B 4E MOV C,M ;added (mwd)
|
||||
043C 3E45 MVI A,045H ;added (mwd)
|
||||
043E B9 CMP C ;added (mwd)
|
||||
043F C4A006 CNZ CPUER ;TEST "MOV" M,C AND C,M added (mwd)
|
||||
0442 72 MOV M,D
|
||||
0443 1600 MVI D,000H
|
||||
0445 56 MOV D,M
|
||||
0446 3E46 MVI A,046H
|
||||
0448 BA CMP D
|
||||
0449 C4A006 CNZ CPUER ;TEST "MOV" M,D AND D,M
|
||||
044C 73 MOV M,E
|
||||
044D 1E00 MVI E,000H
|
||||
044F 5E MOV E,M
|
||||
0450 3E47 MVI A,047H
|
||||
0452 BB CMP E
|
||||
0453 C4A006 CNZ CPUER ;TEST "MOV" M,E AND E,M
|
||||
0456 74 MOV M,H
|
||||
0457 2606 MVI H,(TEMP0 / 0FFH)
|
||||
0459 2EBF MVI L,(TEMP0 AND 0FFH)
|
||||
045B 66 MOV H,M
|
||||
045C 3E06 MVI A,(TEMP0 / 0FFH)
|
||||
045E BC CMP H
|
||||
045F C4A006 CNZ CPUER ;TEST "MOV" M,H AND H,M
|
||||
0462 75 MOV M,L
|
||||
0463 2606 MVI H,(TEMP0 / 0FFH)
|
||||
0465 2EBF MVI L,(TEMP0 AND 0FFH)
|
||||
0467 6E MOV L,M
|
||||
0468 3EBF MVI A,(TEMP0 AND 0FFH)
|
||||
046A BD CMP L
|
||||
046B C4A006 CNZ CPUER ;TEST "MOV" M,L AND L,M
|
||||
046E 2606 MVI H,(TEMP0 / 0FFH)
|
||||
0470 2EBF MVI L,(TEMP0 AND 0FFH)
|
||||
0472 3E32 MVI A,032H
|
||||
0474 77 MOV M,A
|
||||
0475 BE CMP M
|
||||
0476 C4A006 CNZ CPUER ;TEST "MOV" M,A
|
||||
0479 86 ADD M
|
||||
047A FE64 CPI 064H
|
||||
047C C4A006 CNZ CPUER ;TEST "ADD" M
|
||||
047F AF XRA A
|
||||
0480 7E MOV A,M
|
||||
0481 FE32 CPI 032H
|
||||
0483 C4A006 CNZ CPUER ;TEST "MOV" A,M
|
||||
0486 2606 MVI H,(TEMP0 / 0FFH)
|
||||
0488 2EBF MVI L,(TEMP0 AND 0FFH)
|
||||
048A 7E MOV A,M
|
||||
048B 96 SUB M
|
||||
048C C4A006 CNZ CPUER ;TEST "SUB" M
|
||||
048F 3E80 MVI A,080H
|
||||
0491 87 ADD A
|
||||
0492 8E ADC M
|
||||
0493 FE33 CPI 033H
|
||||
0495 C4A006 CNZ CPUER ;TEST "ADC" M
|
||||
0498 3E80 MVI A,080H
|
||||
049A 87 ADD A
|
||||
049B 9E SBB M
|
||||
049C FECD CPI 0CDH
|
||||
049E C4A006 CNZ CPUER ;TEST "SBB" M
|
||||
04A1 A6 ANA M
|
||||
04A2 C4A006 CNZ CPUER ;TEST "ANA" M
|
||||
04A5 3E25 MVI A,025H
|
||||
04A7 B6 ORA M
|
||||
04A8 FE37 CPI 037H
|
||||
04AA C4A006 CNZ CPUER ;TEST "ORA" M
|
||||
04AD AE XRA M
|
||||
04AE FE05 CPI 005H
|
||||
04B0 C4A006 CNZ CPUER ;TEST "XRA" M
|
||||
04B3 3655 MVI M,055H
|
||||
04B5 34 INR M
|
||||
04B6 35 DCR M
|
||||
04B7 86 ADD M
|
||||
04B8 FE5A CPI 05AH
|
||||
04BA C4A006 CNZ CPUER ;TEST "INR","DCR",AND "MVI" M
|
||||
04BD 01FF12 LXI B,12FFH
|
||||
04C0 11FF12 LXI D,12FFH
|
||||
04C3 21FF12 LXI H,12FFH
|
||||
04C6 03 INX B
|
||||
04C7 13 INX D
|
||||
04C8 23 INX H
|
||||
04C9 3E13 MVI A,013H
|
||||
04CB B8 CMP B
|
||||
04CC C4A006 CNZ CPUER ;TEST "LXI" AND "INX" B
|
||||
04CF BA CMP D
|
||||
04D0 C4A006 CNZ CPUER ;TEST "LXI" AND "INX" D
|
||||
04D3 BC CMP H
|
||||
04D4 C4A006 CNZ CPUER ;TEST "LXI" AND "INX" H
|
||||
04D7 3E00 MVI A,000H
|
||||
04D9 B9 CMP C
|
||||
04DA C4A006 CNZ CPUER ;TEST "LXI" AND "INX" B
|
||||
04DD BB CMP E
|
||||
04DE C4A006 CNZ CPUER ;TEST "LXI" AND "INX" D
|
||||
04E1 BD CMP L
|
||||
04E2 C4A006 CNZ CPUER ;TEST "LXI" AND "INX" H
|
||||
04E5 0B DCX B
|
||||
04E6 1B DCX D
|
||||
04E7 2B DCX H
|
||||
04E8 3E12 MVI A,012H
|
||||
04EA B8 CMP B
|
||||
04EB C4A006 CNZ CPUER ;TEST "DCX" B
|
||||
04EE BA CMP D
|
||||
04EF C4A006 CNZ CPUER ;TEST "DCX" D
|
||||
04F2 BC CMP H
|
||||
04F3 C4A006 CNZ CPUER ;TEST "DCX" H
|
||||
04F6 3EFF MVI A,0FFH
|
||||
04F8 B9 CMP C
|
||||
04F9 C4A006 CNZ CPUER ;TEST "DCX" B
|
||||
04FC BB CMP E
|
||||
04FD C4A006 CNZ CPUER ;TEST "DCX" D
|
||||
0500 BD CMP L
|
||||
0501 C4A006 CNZ CPUER ;TEST "DCX" H
|
||||
0504 32BF06 STA TEMP0
|
||||
0507 AF XRA A
|
||||
0508 3ABF06 LDA TEMP0
|
||||
050B FEFF CPI 0FFH
|
||||
050D C4A006 CNZ CPUER ;TEST "LDA" AND "STA"
|
||||
0510 2ABD06 LHLD TEMPP
|
||||
0513 22BF06 SHLD TEMP0
|
||||
0516 3ABD06 LDA TEMPP
|
||||
0519 47 MOV B,A
|
||||
051A 3ABF06 LDA TEMP0
|
||||
051D B8 CMP B
|
||||
051E C4A006 CNZ CPUER ;TEST "LHLD" AND "SHLD"
|
||||
0521 3ABE06 LDA TEMPP+1
|
||||
0524 47 MOV B,A
|
||||
0525 3AC006 LDA TEMP0+1
|
||||
0528 B8 CMP B
|
||||
0529 C4A006 CNZ CPUER ;TEST "LHLD" AND "SHLD"
|
||||
052C 3EAA MVI A,0AAH
|
||||
052E 32BF06 STA TEMP0
|
||||
0531 44 MOV B,H
|
||||
0532 4D MOV C,L
|
||||
0533 AF XRA A
|
||||
0534 0A LDAX B
|
||||
0535 FEAA CPI 0AAH
|
||||
0537 C4A006 CNZ CPUER ;TEST "LDAX" B
|
||||
053A 3C INR A
|
||||
053B 02 STAX B
|
||||
053C 3ABF06 LDA TEMP0
|
||||
053F FEAB CPI 0ABH
|
||||
0541 C4A006 CNZ CPUER ;TEST "STAX" B
|
||||
0544 3E77 MVI A,077H
|
||||
0546 32BF06 STA TEMP0
|
||||
0549 2ABD06 LHLD TEMPP
|
||||
054C 110000 LXI D,00000H
|
||||
054F EB XCHG
|
||||
0550 AF XRA A
|
||||
0551 1A LDAX D
|
||||
0552 FE77 CPI 077H
|
||||
0554 C4A006 CNZ CPUER ;TEST "LDAX" D AND "XCHG"
|
||||
0557 AF XRA A
|
||||
0558 84 ADD H
|
||||
0559 85 ADD L
|
||||
055A C4A006 CNZ CPUER ;TEST "XCHG"
|
||||
055D 3ECC MVI A,0CCH
|
||||
055F 12 STAX D
|
||||
0560 3ABF06 LDA TEMP0
|
||||
0563 FECC CPI 0CCH
|
||||
0565 12 STAX D
|
||||
0566 3ABF06 LDA TEMP0
|
||||
0569 FECC CPI 0CCH
|
||||
056B C4A006 CNZ CPUER ;TEST "STAX" D
|
||||
056E 217777 LXI H,07777H
|
||||
0571 29 DAD H
|
||||
0572 3EEE MVI A,0EEH
|
||||
0574 BC CMP H
|
||||
0575 C4A006 CNZ CPUER ;TEST "DAD" H
|
||||
0578 BD CMP L
|
||||
0579 C4A006 CNZ CPUER ;TEST "DAD" H
|
||||
057C 215555 LXI H,05555H
|
||||
057F 01FFFF LXI B,0FFFFH
|
||||
0582 09 DAD B
|
||||
0583 3E55 MVI A,055H
|
||||
0585 D4A006 CNC CPUER ;TEST "DAD" B
|
||||
0588 BC CMP H
|
||||
0589 C4A006 CNZ CPUER ;TEST "DAD" B
|
||||
058C 3E54 MVI A,054H
|
||||
058E BD CMP L
|
||||
058F C4A006 CNZ CPUER ;TEST "DAD" B
|
||||
0592 21AAAA LXI H,0AAAAH
|
||||
0595 113333 LXI D,03333H
|
||||
0598 19 DAD D
|
||||
0599 3EDD MVI A,0DDH
|
||||
059B BC CMP H
|
||||
059C C4A006 CNZ CPUER ;TEST "DAD" D
|
||||
059F BD CMP L
|
||||
05A0 C4A006 CNZ CPUER ;TEST "DAD" B
|
||||
05A3 37 STC
|
||||
05A4 D4A006 CNC CPUER ;TEST "STC"
|
||||
05A7 3F CMC
|
||||
05A8 DCA006 CC CPUER ;TEST "CMC
|
||||
05AB 3EAA MVI A,0AAH
|
||||
05AD 2F CMA
|
||||
05AE FE55 CPI 055H
|
||||
05B0 C4A006 CNZ CPUER ;TEST "CMA"
|
||||
05B3 B7 ORA A ;RE-SET AUXILIARY CARRY
|
||||
05B4 27 DAA
|
||||
05B5 FE55 CPI 055H
|
||||
05B7 C4A006 CNZ CPUER ;TEST "DAA"
|
||||
05BA 3E88 MVI A,088H
|
||||
05BC 87 ADD A
|
||||
05BD 27 DAA
|
||||
05BE FE76 CPI 076H
|
||||
05C0 C4A006 CNZ CPUER ;TEST "DAA"
|
||||
05C3 AF XRA A
|
||||
05C4 3EAA MVI A,0AAH
|
||||
05C6 27 DAA
|
||||
05C7 D4A006 CNC CPUER ;TEST "DAA"
|
||||
05CA FE10 CPI 010H
|
||||
05CC C4A006 CNZ CPUER ;TEST "DAA"
|
||||
05CF AF XRA A
|
||||
05D0 3E9A MVI A,09AH
|
||||
05D2 27 DAA
|
||||
05D3 D4A006 CNC CPUER ;TEST "DAA"
|
||||
05D6 C4A006 CNZ CPUER ;TEST "DAA"
|
||||
05D9 37 STC
|
||||
05DA 3E42 MVI A,042H
|
||||
05DC 07 RLC
|
||||
05DD DCA006 CC CPUER ;TEST "RLC" FOR RE-SET CARRY
|
||||
05E0 07 RLC
|
||||
05E1 D4A006 CNC CPUER ;TEST "RLC" FOR SET CARRY
|
||||
05E4 FE09 CPI 009H
|
||||
05E6 C4A006 CNZ CPUER ;TEST "RLC" FOR ROTATION
|
||||
05E9 0F RRC
|
||||
05EA D4A006 CNC CPUER ;TEST "RRC" FOR SET CARRY
|
||||
05ED 0F RRC
|
||||
05EE FE42 CPI 042H
|
||||
05F0 C4A006 CNZ CPUER ;TEST "RRC" FOR ROTATION
|
||||
05F3 17 RAL
|
||||
05F4 17 RAL
|
||||
05F5 D4A006 CNC CPUER ;TEST "RAL" FOR SET CARRY
|
||||
05F8 FE08 CPI 008H
|
||||
05FA C4A006 CNZ CPUER ;TEST "RAL" FOR ROTATION
|
||||
05FD 1F RAR
|
||||
05FE 1F RAR
|
||||
05FF DCA006 CC CPUER ;TEST "RAR" FOR RE-SET CARRY
|
||||
0602 FE02 CPI 002H
|
||||
0604 C4A006 CNZ CPUER ;TEST "RAR" FOR ROTATION
|
||||
0607 013412 LXI B,01234H
|
||||
060A 11AAAA LXI D,0AAAAH
|
||||
060D 215555 LXI H,05555H
|
||||
0610 AF XRA A
|
||||
0611 C5 PUSH B
|
||||
0612 D5 PUSH D
|
||||
0613 E5 PUSH H
|
||||
0614 F5 PUSH PSW
|
||||
0615 010000 LXI B,00000H
|
||||
0618 110000 LXI D,00000H
|
||||
061B 210000 LXI H,00000H
|
||||
061E 3EC0 MVI A,0C0H
|
||||
0620 C6F0 ADI 0F0H
|
||||
0622 F1 POP PSW
|
||||
0623 E1 POP H
|
||||
0624 D1 POP D
|
||||
0625 C1 POP B
|
||||
0626 DCA006 CC CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
0629 C4A006 CNZ CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
062C E4A006 CPO CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
062F FCA006 CM CPUER ;TEST "PUSH PSW" AND "POP PSW"
|
||||
0632 3E12 MVI A,012H
|
||||
0634 B8 CMP B
|
||||
0635 C4A006 CNZ CPUER ;TEST "PUSH B" AND "POP B"
|
||||
0638 3E34 MVI A,034H
|
||||
063A B9 CMP C
|
||||
063B C4A006 CNZ CPUER ;TEST "PUSH B" AND "POP B"
|
||||
063E 3EAA MVI A,0AAH
|
||||
0640 BA CMP D
|
||||
0641 C4A006 CNZ CPUER ;TEST "PUSH D" AND "POP D"
|
||||
0644 BB CMP E
|
||||
0645 C4A006 CNZ CPUER ;TEST "PUSH D" AND "POP D"
|
||||
0648 3E55 MVI A,055H
|
||||
064A BC CMP H
|
||||
064B C4A006 CNZ CPUER ;TEST "PUSH H" AND "POP H"
|
||||
064E BD CMP L
|
||||
064F C4A006 CNZ CPUER ;TEST "PUSH H" AND "POP H"
|
||||
0652 210000 LXI H,00000H
|
||||
0655 39 DAD SP
|
||||
0656 22C406 SHLD SAVSTK ;SAVE THE "OLD" STACK-POINTER!
|
||||
0659 31C306 LXI SP,TEMP4
|
||||
065C 3B DCX SP
|
||||
065D 3B DCX SP
|
||||
065E 33 INX SP
|
||||
065F 3B DCX SP
|
||||
0660 3E55 MVI A,055H
|
||||
0662 32C106 STA TEMP2
|
||||
0665 2F CMA
|
||||
0666 32C206 STA TEMP3
|
||||
0669 C1 POP B
|
||||
066A B8 CMP B
|
||||
066B C4A006 CNZ CPUER ;TEST "LXI","DAD","INX",AND "DCX" SP
|
||||
066E 2F CMA
|
||||
066F B9 CMP C
|
||||
0670 C4A006 CNZ CPUER ;TEST "LXI","DAD","INX", AND "DCX" SP
|
||||
0673 21C306 LXI H,TEMP4
|
||||
0676 F9 SPHL
|
||||
0677 213377 LXI H,07733H
|
||||
067A 3B DCX SP
|
||||
067B 3B DCX SP
|
||||
067C E3 XTHL
|
||||
067D 3AC206 LDA TEMP3
|
||||
0680 FE77 CPI 077H
|
||||
0682 C4A006 CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
0685 3AC106 LDA TEMP2
|
||||
0688 FE33 CPI 033H
|
||||
068A C4A006 CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
068D 3E55 MVI A,055H
|
||||
068F BD CMP L
|
||||
0690 C4A006 CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
0693 2F CMA
|
||||
0694 BC CMP H
|
||||
0695 C4A006 CNZ CPUER ;TEST "SPHL" AND "XTHL"
|
||||
0698 2AC406 LHLD SAVSTK ;RESTORE THE "OLD" STACK-POINTER
|
||||
069B F9 SPHL
|
||||
069C 21B406 LXI H,CPUOK
|
||||
069F E9 PCHL ;TEST "PCHL"
|
||||
;
|
||||
;
|
||||
;
|
||||
06A0 219001 CPUER: LXI H,NGCPU ;OUTPUT "CPU HAS FAILED ERROR EXIT=" TO CONSOLE
|
||||
06A3 CD4B01 CALL MSG
|
||||
06A6 E1 POP H ;HL = ADDRESS FOLLOWING CALL CPUER
|
||||
06A7 E5 PUSH H
|
||||
06A8 7C MOV A,H
|
||||
06A9 CD5A01 CALL BYTEO ;SHOW ERROR EXIT ADDRESS HIGH BYTE
|
||||
06AC E1 POP H
|
||||
06AD 7D MOV A,L
|
||||
06AE CD5A01 CALL BYTEO ;SHOW ERROR EXIT ADDRESS LOW BYTE
|
||||
06B1 C30000 JMP WBOOT ;EXIT TO CP/M WARM BOOT
|
||||
;
|
||||
;
|
||||
;
|
||||
06B4 217A01 CPUOK: LXI H,OKCPU ;OUTPUT "CPU IS OPERATIONAL" TO CONSOLE
|
||||
06B7 CD4B01 CALL MSG
|
||||
06BA C30000 JMP WBOOT ;EXIT TO CP/M WARM BOOT
|
||||
;
|
||||
;
|
||||
;
|
||||
06BD BF06 TEMPP: DW TEMP0 ;POINTER USED TO TEST "LHLD","SHLD",
|
||||
; AND "LDAX" INSTRUCTIONS
|
||||
;
|
||||
06BF TEMP0: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
06C0 TEMP1: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
06C1 TEMP2 DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
06C2 TEMP3: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
06C3 TEMP4: DS 1 ;TEMPORARY STORAGE FOR CPU TEST MEMORY LOCATIONS
|
||||
06C4 SAVSTK: DS 2 ;TEMPORARY STACK-POINTER STORAGE LOCATION
|
||||
;
|
||||
;
|
||||
;
|
||||
07BD = STACK EQU TEMPP+256 ;DE-BUG STACK POINTER STORAGE AREA
|
||||
;
|
||||
;
|
||||
;
|
||||
06C6 END
|
||||
@@ -6,6 +6,8 @@
|
||||
namespace Intel8080
|
||||
{
|
||||
using EightBit;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
public class Intel8080(Bus bus, InputOutput ports) : IntelProcessor(bus)
|
||||
{
|
||||
@@ -63,17 +65,62 @@ namespace Intel8080
|
||||
}
|
||||
}
|
||||
|
||||
private void MemoryUpdate(int ticks)
|
||||
{
|
||||
Debug.Assert(ticks > 0, "Ticks must be greater than zero");
|
||||
this.OnWritingMemory();
|
||||
this.Tick(ticks + 1);
|
||||
base.MemoryWrite();
|
||||
this.Tick();
|
||||
this.OnWrittenMemory();
|
||||
}
|
||||
|
||||
protected override void MemoryWrite()
|
||||
{
|
||||
this.MemoryUpdate(1);
|
||||
}
|
||||
|
||||
protected override byte MemoryRead()
|
||||
{
|
||||
this.OnReadingMemory();
|
||||
this.Tick(2);
|
||||
base.MemoryRead();
|
||||
this.OnReadMemory();
|
||||
this.Tick(2);
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
protected override void HandleRESET()
|
||||
{
|
||||
base.HandleRESET();
|
||||
this.Tick(3);
|
||||
this.DisableInterrupts();
|
||||
this.SP.Word = this.AF.Word = (ushort)Mask.Sixteen;
|
||||
}
|
||||
|
||||
private byte ReadDataUnderInterrupt()
|
||||
{
|
||||
this.Tick(4);
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
protected override void Call(Register16 destination)
|
||||
{
|
||||
this.Tick();
|
||||
base.Call(destination);
|
||||
}
|
||||
|
||||
protected override void JumpRelative(sbyte offset)
|
||||
{
|
||||
base.JumpRelative(offset);
|
||||
this.Tick(5);
|
||||
}
|
||||
|
||||
protected override void HandleINT()
|
||||
{
|
||||
base.HandleINT();
|
||||
this.Execute(this.Bus.Data);
|
||||
this.Tick(3);
|
||||
var data = this.ReadDataUnderInterrupt();
|
||||
this.Tick();
|
||||
this.Execute(data);
|
||||
}
|
||||
|
||||
private int Zero() => ZeroTest(this.F);
|
||||
@@ -132,52 +179,53 @@ namespace Intel8080
|
||||
|
||||
protected override void EnableInterrupts() => this.interruptEnable = true;
|
||||
|
||||
private byte R(int r) => r switch
|
||||
{
|
||||
0 => this.B,
|
||||
1 => this.C,
|
||||
2 => this.D,
|
||||
3 => this.E,
|
||||
4 => this.H,
|
||||
5 => this.L,
|
||||
6 => this.MemoryRead(this.HL),
|
||||
7 => this.A,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(r)),
|
||||
};
|
||||
|
||||
private void R(int r, byte value)
|
||||
private ref byte R(int r, AccessLevel access = AccessLevel.ReadOnly)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case 0:
|
||||
this.B = value;
|
||||
break;
|
||||
return ref this.B;
|
||||
case 1:
|
||||
this.C = value;
|
||||
break;
|
||||
return ref this.C;
|
||||
case 2:
|
||||
this.D = value;
|
||||
break;
|
||||
return ref this.D;
|
||||
case 3:
|
||||
this.E = value;
|
||||
break;
|
||||
return ref this.E;
|
||||
case 4:
|
||||
this.H = value;
|
||||
break;
|
||||
return ref this.H;
|
||||
case 5:
|
||||
this.L = value;
|
||||
break;
|
||||
return ref this.L;
|
||||
case 6:
|
||||
this.MemoryWrite(this.HL, value);
|
||||
break;
|
||||
this.Bus.Address.Assign(this.HL);
|
||||
switch (access)
|
||||
{
|
||||
case AccessLevel.ReadOnly:
|
||||
this.MemoryRead();
|
||||
break;
|
||||
case AccessLevel.WriteOnly:
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid access level");
|
||||
}
|
||||
|
||||
// Will need a post-MemoryWrite
|
||||
return ref this.Bus.Data;
|
||||
case 7:
|
||||
this.A = value;
|
||||
break;
|
||||
return ref this.A;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(r));
|
||||
}
|
||||
}
|
||||
|
||||
private void R(int r, byte value, int ticks = 1)
|
||||
{
|
||||
this.R(r, AccessLevel.WriteOnly) = value;
|
||||
if (r == 6)
|
||||
{
|
||||
this.MemoryUpdate(ticks);
|
||||
}
|
||||
}
|
||||
|
||||
private Register16 RP(int rp) => rp switch
|
||||
{
|
||||
0 => this.BC,
|
||||
@@ -198,6 +246,8 @@ namespace Intel8080
|
||||
|
||||
private void Execute(int x, int y, int z, int p, int q)
|
||||
{
|
||||
var memoryY = y == 6;
|
||||
var memoryZ = z == 6;
|
||||
switch (x)
|
||||
{
|
||||
case 0:
|
||||
@@ -207,7 +257,6 @@ namespace Intel8080
|
||||
switch (y)
|
||||
{
|
||||
case 0: // NOP
|
||||
this.Tick(4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -219,11 +268,10 @@ namespace Intel8080
|
||||
{
|
||||
case 0: // LD rp,nn
|
||||
this.RP(p).Assign(this.FetchWord());
|
||||
this.Tick(10);
|
||||
break;
|
||||
case 1: // ADD HL,rp
|
||||
this.Add(this.RP(p));
|
||||
this.Tick(11);
|
||||
this.Tick(7);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
@@ -238,21 +286,17 @@ namespace Intel8080
|
||||
{
|
||||
case 0: // LD (BC),A
|
||||
this.WriteMemoryIndirect(this.BC, this.A);
|
||||
this.Tick(7);
|
||||
break;
|
||||
case 1: // LD (DE),A
|
||||
this.WriteMemoryIndirect(this.DE, this.A);
|
||||
this.Tick(7);
|
||||
break;
|
||||
case 2: // LD (nn),HL
|
||||
this.FetchWordAddress();
|
||||
this.SetWord(this.HL);
|
||||
this.Tick(16);
|
||||
break;
|
||||
case 3: // LD (nn),A
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
this.WriteMemoryIndirect(this.A);
|
||||
this.Tick(13);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
@@ -264,21 +308,17 @@ namespace Intel8080
|
||||
{
|
||||
case 0: // LD A,(BC)
|
||||
this.A = this.ReadMemoryIndirect(this.BC);
|
||||
this.Tick(7);
|
||||
break;
|
||||
case 1: // LD A,(DE)
|
||||
this.A = this.ReadMemoryIndirect(this.DE);
|
||||
this.Tick(7);
|
||||
break;
|
||||
case 2: // LD HL,(nn)
|
||||
this.FetchWordAddress();
|
||||
this.HL.Assign(this.GetWord());
|
||||
this.Tick(16);
|
||||
this.GetInto(this.HL);
|
||||
break;
|
||||
case 3: // LD A,(nn)
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
this.A = this.ReadMemoryIndirect();
|
||||
this.Tick(13);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
@@ -291,41 +331,31 @@ namespace Intel8080
|
||||
|
||||
break;
|
||||
case 3: // 16-bit INC/DEC
|
||||
switch (q)
|
||||
_ = q switch
|
||||
{
|
||||
case 0: // INC rp
|
||||
_ = this.RP(p).Increment();
|
||||
break;
|
||||
case 1: // DEC rp
|
||||
_ = this.RP(p).Decrement();
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
}
|
||||
|
||||
this.Tick(6);
|
||||
// INC rp
|
||||
0 => this.RP(p).Increment(),
|
||||
// DEC rp
|
||||
1 => this.RP(p).Decrement(),
|
||||
_ => throw new NotSupportedException("Invalid operation mode"),
|
||||
};
|
||||
this.Tick(2);
|
||||
break;
|
||||
case 4: // 8-bit INC
|
||||
this.R(y, this.Increment(this.R(y)));
|
||||
this.Tick(4);
|
||||
this.R(y, this.Increment(this.R(y)), 2);
|
||||
break;
|
||||
case 5: // 8-bit DEC
|
||||
this.R(y, this.Decrement(this.R(y)));
|
||||
this.Tick(4);
|
||||
if (y == 6)
|
||||
{
|
||||
this.Tick(7);
|
||||
}
|
||||
|
||||
this.R(y, this.Decrement(this.R(y)), 2);
|
||||
break;
|
||||
case 6: // 8-bit load immediate
|
||||
this.R(y, this.FetchByte());
|
||||
this.Tick(7);
|
||||
if (y == 6)
|
||||
{
|
||||
this.Tick(3);
|
||||
_ = this.FetchByte(); // LD r,n
|
||||
if (memoryY)
|
||||
{
|
||||
this.Tick(2);
|
||||
}
|
||||
this.R(y, this.Bus.Data);
|
||||
}
|
||||
|
||||
break;
|
||||
case 7: // Assorted operations on accumulator/flags
|
||||
switch (y)
|
||||
@@ -357,8 +387,6 @@ namespace Intel8080
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
}
|
||||
|
||||
this.Tick(4);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
@@ -366,20 +394,14 @@ namespace Intel8080
|
||||
|
||||
break;
|
||||
case 1: // 8-bit loading
|
||||
if (z == 6 && y == 6)
|
||||
if (memoryZ && memoryY)
|
||||
{
|
||||
this.LowerHALT(); // Exception (replaces LD (HL), (HL))
|
||||
}
|
||||
else
|
||||
{
|
||||
this.R(y, this.R(z));
|
||||
if (y == 6 || z == 6)
|
||||
{
|
||||
this.Tick(3); // M operations
|
||||
}
|
||||
}
|
||||
|
||||
this.Tick(4);
|
||||
break;
|
||||
case 2: // Operate on accumulator and register/memory location
|
||||
switch (y)
|
||||
@@ -411,46 +433,31 @@ namespace Intel8080
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
}
|
||||
|
||||
this.Tick(4);
|
||||
if (z == 6)
|
||||
{
|
||||
this.Tick(3);
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
switch (z)
|
||||
{
|
||||
case 0: // Conditional return
|
||||
if (this.ReturnConditionalFlag(y))
|
||||
{
|
||||
this.Tick(6);
|
||||
}
|
||||
|
||||
this.Tick(5);
|
||||
this.ReturnConditionalFlag(y);
|
||||
break;
|
||||
case 1: // POP & various ops
|
||||
switch (q)
|
||||
{
|
||||
case 0: // POP rp2[p]
|
||||
this.RP2(p).Assign(this.PopWord());
|
||||
this.Tick(10);
|
||||
this.PopInto(this.RP2(p));
|
||||
break;
|
||||
case 1:
|
||||
switch (p)
|
||||
{
|
||||
case 0: // RET
|
||||
this.Return();
|
||||
this.Tick(10);
|
||||
break;
|
||||
case 2: // JP HL
|
||||
this.Jump(this.HL);
|
||||
this.Tick(4);
|
||||
break;
|
||||
case 3: // LD SP,HL
|
||||
this.SP.Assign(this.HL);
|
||||
this.Tick(4);
|
||||
this.Tick(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -463,39 +470,32 @@ namespace Intel8080
|
||||
|
||||
break;
|
||||
case 2: // Conditional jump
|
||||
_ = this.JumpConditionalFlag(y);
|
||||
this.Tick(10);
|
||||
this.JumpConditionalFlag(y);
|
||||
break;
|
||||
case 3: // Assorted operations
|
||||
switch (y)
|
||||
{
|
||||
case 0: // JP nn
|
||||
this.JumpIndirect();
|
||||
this.Tick(10);
|
||||
break;
|
||||
case 2: // OUT (n),A
|
||||
this.WritePort(this.FetchByte());
|
||||
this.Tick(11);
|
||||
break;
|
||||
case 3: // IN A,(n)
|
||||
this.A = this.ReadPort(this.FetchByte());
|
||||
this.Tick(11);
|
||||
break;
|
||||
case 4: // EX (SP),HL
|
||||
this.XHTL(this.HL);
|
||||
this.Tick(19);
|
||||
break;
|
||||
case 5: // EX DE,HL
|
||||
(this.DE.Word, this.HL.Word) = (this.HL.Word, this.DE.Word);
|
||||
this.Tick(4);
|
||||
(this.HL.Low, this.DE.Low) = (this.DE.Low, this.HL.Low);
|
||||
(this.HL.High, this.DE.High) = (this.DE.High, this.HL.High);
|
||||
break;
|
||||
case 6: // DI
|
||||
this.DisableInterrupts();
|
||||
this.Tick(4);
|
||||
break;
|
||||
case 7: // EI
|
||||
this.EnableInterrupts();
|
||||
this.Tick(4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -503,26 +503,20 @@ namespace Intel8080
|
||||
|
||||
break;
|
||||
case 4: // Conditional call: CALL cc[y], nn
|
||||
if (this.CallConditionalFlag(y))
|
||||
{
|
||||
this.Tick(7);
|
||||
}
|
||||
|
||||
this.Tick(10);
|
||||
this.CallConditionalFlag(y);
|
||||
break;
|
||||
case 5: // PUSH & various ops
|
||||
switch (q)
|
||||
{
|
||||
case 0: // PUSH rp2[p]
|
||||
this.Tick();
|
||||
this.PushWord(this.RP2(p));
|
||||
this.Tick(11);
|
||||
break;
|
||||
case 1:
|
||||
switch (p)
|
||||
{
|
||||
case 0: // CALL nn
|
||||
this.CallIndirect();
|
||||
this.Tick(17);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -535,41 +529,39 @@ namespace Intel8080
|
||||
|
||||
break;
|
||||
case 6: // Operate on accumulator and immediate operand: alu[y] n
|
||||
_ = this.FetchByte();
|
||||
switch (y)
|
||||
{
|
||||
case 0: // ADD A,n
|
||||
this.Add(this.FetchByte());
|
||||
this.Add(this.Bus.Data);
|
||||
break;
|
||||
case 1: // ADC A,n
|
||||
this.ADC(this.FetchByte());
|
||||
this.ADC(this.Bus.Data);
|
||||
break;
|
||||
case 2: // SUB n
|
||||
this.SUB(this.FetchByte());
|
||||
this.SUB(this.Bus.Data);
|
||||
break;
|
||||
case 3: // SBC A,n
|
||||
this.SBB(this.FetchByte());
|
||||
this.SBB(this.Bus.Data);
|
||||
break;
|
||||
case 4: // AND n
|
||||
this.AndR(this.FetchByte());
|
||||
this.AndR(this.Bus.Data);
|
||||
break;
|
||||
case 5: // XOR n
|
||||
this.XorR(this.FetchByte());
|
||||
this.XorR(this.Bus.Data);
|
||||
break;
|
||||
case 6: // OR n
|
||||
this.OrR(this.FetchByte());
|
||||
this.OrR(this.Bus.Data);
|
||||
break;
|
||||
case 7: // CP n
|
||||
this.Compare(this.FetchByte());
|
||||
this.Compare(this.Bus.Data);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
}
|
||||
|
||||
this.Tick(7);
|
||||
break;
|
||||
case 7: // Restart: RST y * 8
|
||||
this.Restart((byte)(y << 3));
|
||||
this.Tick(11);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
@@ -608,6 +600,16 @@ namespace Intel8080
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(flag)),
|
||||
};
|
||||
|
||||
protected sealed override void ReturnConditionalFlag(int flag)
|
||||
{
|
||||
var condition = this.ConvertCondition(flag);
|
||||
this.Tick();
|
||||
if (condition)
|
||||
{
|
||||
this.Return();
|
||||
}
|
||||
}
|
||||
|
||||
private void Add(Register16 value)
|
||||
{
|
||||
var result = this.HL.Word + value.Word;
|
||||
@@ -725,13 +727,16 @@ namespace Intel8080
|
||||
private void XHTL(Register16 exchange)
|
||||
{
|
||||
this.MEMPTR.Low = this.MemoryRead(this.SP);
|
||||
_ = this.Bus.Address.Increment();
|
||||
this.Bus.Address.Increment();
|
||||
this.MEMPTR.High = this.MemoryRead();
|
||||
this.MemoryWrite(exchange.High);
|
||||
this.Bus.Data = exchange.High;
|
||||
exchange.High = this.MEMPTR.High;
|
||||
this.MemoryUpdate(2);
|
||||
_ = this.Bus.Address.Decrement();
|
||||
this.MemoryWrite(exchange.Low);
|
||||
this.Bus.Data = exchange.Low;
|
||||
exchange.Low = this.MEMPTR.Low;
|
||||
this.MemoryUpdate(1);
|
||||
this.Tick(2);
|
||||
}
|
||||
|
||||
private byte ReadMemoryIndirect(Register16 via)
|
||||
@@ -768,7 +773,12 @@ namespace Intel8080
|
||||
this.WritePort();
|
||||
}
|
||||
|
||||
private void WritePort() => this.ports.Write(this.Bus.Address, this.Bus.Data);
|
||||
private void WritePort()
|
||||
{
|
||||
this.Tick(3);
|
||||
this.ports.Write(this.Bus.Address, this.Bus.Data);
|
||||
this.Tick(1);
|
||||
}
|
||||
|
||||
private byte ReadPort(byte port)
|
||||
{
|
||||
@@ -776,6 +786,12 @@ namespace Intel8080
|
||||
return this.ReadPort();
|
||||
}
|
||||
|
||||
private byte ReadPort() => this.Bus.Data = this.ports.Read(this.Bus.Address);
|
||||
private byte ReadPort()
|
||||
{
|
||||
this.Tick(2);
|
||||
this.Bus.Data = this.ports.Read(this.Bus.Address);
|
||||
this.Tick(2);
|
||||
return this.Bus.Data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace LR35902.BlarggTest
|
||||
{
|
||||
using System;
|
||||
|
||||
internal class Board : Bus
|
||||
internal sealed class Board : Bus
|
||||
{
|
||||
private readonly Configuration configuration;
|
||||
private readonly Disassembler disassembler;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace LR35902.BlarggTest
|
||||
{
|
||||
internal class Computer(Configuration configuration)
|
||||
internal sealed class Computer(Configuration configuration)
|
||||
{
|
||||
private readonly Board board = new(configuration);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace LR35902.BlarggTest
|
||||
{
|
||||
internal class Configuration
|
||||
internal sealed class Configuration
|
||||
{
|
||||
public bool DebugMode { get; set; }
|
||||
|
||||
|
||||
@@ -6,17 +6,11 @@ namespace LR35902.FuseTest
|
||||
{
|
||||
using Fuse;
|
||||
|
||||
public class TestSuite<T>
|
||||
public class TestSuite<T>(string path)
|
||||
where T : IRegisterState, new()
|
||||
{
|
||||
private readonly Tests<T> tests;
|
||||
private readonly Results<T> results;
|
||||
|
||||
public TestSuite(string path)
|
||||
{
|
||||
this.tests = new Tests<T>(path + ".in");
|
||||
this.results = new Results<T>(path + ".expected");
|
||||
}
|
||||
private readonly Tests<T> tests = new(path + ".in");
|
||||
private readonly Results<T> results = new(path + ".expected");
|
||||
|
||||
public void Read()
|
||||
{
|
||||
|
||||
@@ -369,19 +369,19 @@ namespace LR35902
|
||||
this.TickMachine();
|
||||
}
|
||||
|
||||
protected override bool JumpConditional(bool condition)
|
||||
protected override void JumpConditional(bool condition)
|
||||
{
|
||||
if (base.JumpConditional(condition))
|
||||
base.JumpConditional(condition);
|
||||
if (condition)
|
||||
{
|
||||
this.TickMachine();
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
|
||||
protected override bool ReturnConditional(bool condition)
|
||||
protected override void ReturnConditional(bool condition)
|
||||
{
|
||||
this.TickMachine();
|
||||
return base.ReturnConditional(condition);
|
||||
base.ReturnConditional(condition);
|
||||
}
|
||||
|
||||
protected override void Return()
|
||||
@@ -528,7 +528,7 @@ namespace LR35902
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
_ = this.JumpRelativeConditionalFlag(y - 4);
|
||||
this.JumpRelativeConditionalFlag(y - 4);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unreachable code block reached");
|
||||
@@ -727,7 +727,7 @@ namespace LR35902
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_ = this.ReturnConditionalFlag(y);
|
||||
this.ReturnConditionalFlag(y);
|
||||
break;
|
||||
|
||||
case 4: // GB: LD (FF00 + n),A
|
||||
@@ -775,7 +775,7 @@ namespace LR35902
|
||||
switch (q)
|
||||
{
|
||||
case 0: // POP rp2[p]
|
||||
this.RP2(p).Assign(this.PopWord());
|
||||
this.PopInto(this.RP2(p));
|
||||
break;
|
||||
case 1:
|
||||
switch (p)
|
||||
@@ -811,20 +811,20 @@ namespace LR35902
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
_ = this.JumpConditionalFlag(y);
|
||||
this.JumpConditionalFlag(y);
|
||||
break;
|
||||
case 4: // GB: LD (FF00 + C),A
|
||||
this.MemoryWrite(this.C, IoRegisters.BasePage, this.A);
|
||||
break;
|
||||
case 5: // GB: LD (nn),A
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
this.MemoryWrite(this.MEMPTR, this.A);
|
||||
break;
|
||||
case 6: // GB: LD A,(FF00 + C)
|
||||
this.A = this.MemoryRead(this.C, IoRegisters.BasePage);
|
||||
break;
|
||||
case 7: // GB: LD A,(nn)
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
this.A = this.MemoryRead(this.MEMPTR);
|
||||
break;
|
||||
default:
|
||||
@@ -855,7 +855,7 @@ namespace LR35902
|
||||
break;
|
||||
|
||||
case 4: // Conditional call: CALL cc[y], nn
|
||||
_ = this.CallConditionalFlag(y);
|
||||
this.CallConditionalFlag(y);
|
||||
break;
|
||||
|
||||
case 5: // PUSH & various ops
|
||||
@@ -884,31 +884,32 @@ namespace LR35902
|
||||
break;
|
||||
|
||||
case 6: // Operate on accumulator and immediate operand: alu[y] n
|
||||
_ = this.FetchByte();
|
||||
switch (y)
|
||||
{
|
||||
case 0: // ADD A,n
|
||||
this.A = this.Add(this.A, this.FetchByte());
|
||||
this.A = this.Add(this.A, this.Bus.Data);
|
||||
break;
|
||||
case 1: // ADC A,n
|
||||
this.A = this.ADC(this.A, this.FetchByte());
|
||||
this.A = this.ADC(this.A, this.Bus.Data);
|
||||
break;
|
||||
case 2: // SUB n
|
||||
this.A = this.Subtract(this.A, this.FetchByte());
|
||||
this.A = this.Subtract(this.A, this.Bus.Data);
|
||||
break;
|
||||
case 3: // SBC A,n
|
||||
this.A = this.SBC(this.A, this.FetchByte());
|
||||
this.A = this.SBC(this.A, this.Bus.Data);
|
||||
break;
|
||||
case 4: // AND n
|
||||
this.AndR(this.FetchByte());
|
||||
this.AndR(this.Bus.Data);
|
||||
break;
|
||||
case 5: // XOR n
|
||||
this.XorR(this.FetchByte());
|
||||
this.XorR(this.Bus.Data);
|
||||
break;
|
||||
case 6: // OR n
|
||||
this.OrR(this.FetchByte());
|
||||
this.OrR(this.Bus.Data);
|
||||
break;
|
||||
case 7: // CP n
|
||||
this.Compare(this.FetchByte());
|
||||
this.Compare(this.Bus.Data);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Invalid operation mode");
|
||||
|
||||
162
M6502/Core.cs
162
M6502/Core.cs
@@ -308,11 +308,11 @@ namespace M6502
|
||||
|
||||
#region Cycle wastage
|
||||
|
||||
protected void SwallowRead() => this.MemoryRead(this.PC);
|
||||
protected void SwallowRead() => _ = this.MemoryRead(this.PC);
|
||||
|
||||
protected void SwallowPop() => this.MemoryRead(this.S, 1);
|
||||
protected void SwallowPop() => _ = this.MemoryRead(this.S, 1);
|
||||
|
||||
protected void SwallowFetch() => this.FetchByte();
|
||||
protected void SwallowFetch() => _ = this.FetchByte();
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -326,17 +326,17 @@ namespace M6502
|
||||
switch (this.OpCode)
|
||||
{
|
||||
case 0x00: this.SwallowFetch(); this.Interrupt(IRQ_vector, InterruptSource.software); break;// BRK (implied)
|
||||
case 0x01: this.IndexedIndirectXRead(); this.OrR(); break; // ORA (indexed indirect X)
|
||||
case 0x01: this.OrR(this.IndexedIndirectXRead()); break; // ORA (indexed indirect X)
|
||||
case 0x05: this.ZeroPageRead(); this.OrR(); break; // ORA (zero page)
|
||||
case 0x06: this.ZeroPageRead(); this.ModifyWrite(this.ASL()); break; // ASL (zero page)
|
||||
case 0x08: this.SwallowRead(); this.PHP(); break; // PHP (implied)
|
||||
case 0x09: this.FetchByte(); this.OrR(); break; // ORA (immediate)
|
||||
case 0x09: this.OrR(this.FetchByte()); break; // ORA (immediate)
|
||||
case 0x0a: this.SwallowRead(); this.A = this.ASL(this.A); break; // ASL A (implied)
|
||||
case 0x0d: this.AbsoluteRead(); this.OrR(); break; // ORA (absolute)
|
||||
case 0x0e: this.AbsoluteRead(); this.ModifyWrite(this.ASL()); break; // ASL (absolute)
|
||||
|
||||
case 0x10: this.BranchNot(this.Negative); break; // BPL (relative)
|
||||
case 0x11: this.IndirectIndexedYRead(); this.OrR(); break; // ORA (indirect indexed Y)
|
||||
case 0x11: this.OrR(this.IndirectIndexedYRead()); break; // ORA (indirect indexed Y)
|
||||
case 0x15: this.ZeroPageXRead(); this.OrR(); break; // ORA (zero page, X)
|
||||
case 0x16: this.ZeroPageXRead(); this.ModifyWrite(this.ASL()); break; // ASL (zero page, X)
|
||||
case 0x18: this.SwallowRead(); this.ResetFlag(StatusBits.CF); break; // CLC (implied)
|
||||
@@ -345,19 +345,19 @@ namespace M6502
|
||||
case 0x1e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ASL()); break; // ASL (absolute, X)
|
||||
|
||||
case 0x20: this.JSR(); break; // JSR (absolute)
|
||||
case 0x21: this.IndexedIndirectXRead(); this.AndR(); break; // AND (indexed indirect X)
|
||||
case 0x21: this.AndR(this.IndexedIndirectXRead()); break; // AND (indexed indirect X)
|
||||
case 0x24: this.ZeroPageRead(); this.BIT(); break; // BIT (zero page)
|
||||
case 0x25: this.ZeroPageRead(); this.AndR(); break; // AND (zero page)
|
||||
case 0x26: this.ZeroPageRead(); this.ModifyWrite(this.ROL()); break; // ROL (zero page)
|
||||
case 0x28: this.SwallowRead(); this.PLP(); break; // PLP (implied)
|
||||
case 0x29: this.FetchByte(); this.AndR(); break; // AND (immediate)
|
||||
case 0x29: this.AndR(this.FetchByte()); break; // AND (immediate)
|
||||
case 0x2a: this.SwallowRead(); this.A = this.ROL(this.A); break; // ROL A (implied)
|
||||
case 0x2c: this.AbsoluteRead(); this.BIT(); break; // BIT (absolute)
|
||||
case 0x2d: this.AbsoluteRead(); this.AndR(); break; // AND (absolute)
|
||||
case 0x2e: this.AbsoluteRead(); this.ModifyWrite(this.ROL()); break; // ROL (absolute)
|
||||
|
||||
case 0x30: this.Branch(this.Negative); break; // BMI (relative)
|
||||
case 0x31: this.IndirectIndexedYRead(); this.AndR(); break; // AND (indirect indexed Y)
|
||||
case 0x31: this.AndR(this.IndirectIndexedYRead()); break; // AND (indirect indexed Y)
|
||||
case 0x35: this.ZeroPageXRead(); this.AndR(); break; // AND (zero page, X)
|
||||
case 0x36: this.ZeroPageXRead(); this.ModifyWrite(this.ROL()); break; // ROL (zero page, X)
|
||||
case 0x38: this.SwallowRead(); this.SetFlag(StatusBits.CF); break; // SEC (implied)
|
||||
@@ -366,19 +366,19 @@ namespace M6502
|
||||
case 0x3e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ROL()); break; // ROL (absolute, X)
|
||||
|
||||
case 0x40: this.SwallowRead(); this.RTI(); break; // RTI (implied)
|
||||
case 0x41: this.IndexedIndirectXRead(); this.EorR(); break; // EOR (indexed indirect X)
|
||||
case 0x41: this.EorR(this.IndexedIndirectXRead()); break; // EOR (indexed indirect X)
|
||||
case 0x44: this.ZeroPageRead(); break; // *NOP (zero page)
|
||||
case 0x45: this.ZeroPageRead(); this.EorR(); break; // EOR (zero page)
|
||||
case 0x46: this.ZeroPageRead(); this.ModifyWrite(this.LSR()); break; // LSR (zero page)
|
||||
case 0x48: this.SwallowRead(); this.Push(this.A); break; // PHA (implied)
|
||||
case 0x49: this.FetchByte(); this.EorR(); break; // EOR (immediate)
|
||||
case 0x49: this.EorR(this.FetchByte()); break; // EOR (immediate)
|
||||
case 0x4a: this.SwallowRead(); this.A = this.LSR(this.A); break; // LSR A (implied)
|
||||
case 0x4c: this.AbsoluteAddress(); this.Jump(this.Bus.Address); break; // JMP (absolute)
|
||||
case 0x4d: this.AbsoluteRead(); this.EorR(); break; // EOR (absolute)
|
||||
case 0x4e: this.AbsoluteRead(); this.ModifyWrite(this.LSR()); break; // LSR (absolute)
|
||||
|
||||
case 0x50: this.BranchNot(this.Overflow); break; // BVC (relative)
|
||||
case 0x51: this.IndirectIndexedYRead(); this.EorR(); break; // EOR (indirect indexed Y)
|
||||
case 0x51: this.EorR(this.IndirectIndexedYRead()); break; // EOR (indirect indexed Y)
|
||||
case 0x54: this.ZeroPageXRead(); break; // *NOP (zero page, X)
|
||||
case 0x55: this.ZeroPageXRead(); this.EorR(); break; // EOR (zero page, X)
|
||||
case 0x56: this.ZeroPageXRead(); this.ModifyWrite(this.LSR()); break; // LSR (zero page, X)
|
||||
@@ -388,27 +388,27 @@ namespace M6502
|
||||
case 0x5e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.LSR()); break; // LSR (absolute, X)
|
||||
|
||||
case 0x60: this.SwallowRead(); this.Return(); break; // RTS (implied)
|
||||
case 0x61: this.IndexedIndirectXRead(); this.ADC(); break; // ADC (indexed indirect X)
|
||||
case 0x65: this.ZeroPageRead(); this.ADC(); break; // ADC (zero page)
|
||||
case 0x61: this.ADC(this.IndexedIndirectXRead()); break; // ADC (indexed indirect X)
|
||||
case 0x65: this.ADC(this.ZeroPageRead()); break; // ADC (zero page)
|
||||
case 0x66: this.ZeroPageRead(); this.ModifyWrite(this.ROR()); break; // ROR (zero page)
|
||||
case 0x68: this.SwallowRead(); this.SwallowPop(); this.A = this.Through(this.Pop()); break; // PLA (implied)
|
||||
case 0x69: this.FetchByte(); this.ADC(); break; // ADC (immediate)
|
||||
case 0x69: this.ADC(this.FetchByte()); break; // ADC (immediate)
|
||||
case 0x6a: this.SwallowRead(); this.A = this.ROR(this.A); break; // ROR A (implied)
|
||||
case 0x6c: this.IndirectAddress(); this.Jump(this.Bus.Address); break; // JMP (indirect)
|
||||
case 0x6d: this.AbsoluteRead(); this.ADC(); break; // ADC (absolute)
|
||||
case 0x6d: this.ADC(this.AbsoluteRead()); break; // ADC (absolute)
|
||||
case 0x6e: this.AbsoluteRead(); this.ModifyWrite(this.ROR()); break; // ROR (absolute)
|
||||
|
||||
case 0x70: this.Branch(this.Overflow); break; // BVS (relative)
|
||||
case 0x71: this.IndirectIndexedYRead(); this.ADC(); break; // ADC (indirect indexed Y)
|
||||
case 0x75: this.ZeroPageXRead(); this.ADC(); break; // ADC (zero page, X)
|
||||
case 0x71: this.ADC(this.IndirectIndexedYRead()); break; // ADC (indirect indexed Y)
|
||||
case 0x75: this.ADC(this.ZeroPageXRead()); break; // ADC (zero page, X)
|
||||
case 0x76: this.ZeroPageXRead(); this.ModifyWrite(this.ROR()); break; // ROR (zero page, X)
|
||||
case 0x78: this.SwallowRead(); this.SetFlag(StatusBits.IF); break; // SEI (implied)
|
||||
case 0x79: this.AbsoluteYRead(); this.ADC(); break; // ADC (absolute, Y)
|
||||
case 0x7d: this.AbsoluteXRead(); this.ADC(); break; // ADC (absolute, X)
|
||||
case 0x79: this.ADC(this.AbsoluteYRead()); break; // ADC (absolute, Y)
|
||||
case 0x7d: this.ADC(this.AbsoluteXRead()); break; // ADC (absolute, X)
|
||||
case 0x7e: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.ROR()); break; // ROR (absolute, X)
|
||||
|
||||
case 0x81: this.IndexedIndirectXAddress(); this.MemoryWrite(this.A); break; // STA (indexed indirect X)
|
||||
case 0x82: this.FetchByte(); break; // *NOP (immediate)
|
||||
case 0x82: _ = this.FetchByte(); break; // *NOP (immediate)
|
||||
case 0x84: this.ZeroPageAddress(); this.MemoryWrite(this.Y); break; // STY (zero page)
|
||||
case 0x85: this.ZeroPageAddress(); this.MemoryWrite(this.A); break; // STA (zero page)
|
||||
case 0x86: this.ZeroPageAddress(); this.MemoryWrite(this.X); break; // STX (zero page)
|
||||
@@ -428,21 +428,21 @@ namespace M6502
|
||||
case 0x9a: this.SwallowRead(); this.S = this.X; break; // TXS (implied)
|
||||
case 0x9d: this.AbsoluteXAddress(); this.Fixup(); this.MemoryWrite(this.A); break; // STA (absolute, X)
|
||||
|
||||
case 0xa0: this.FetchByte(); this.Y = this.Through(); break; // LDY (immediate)
|
||||
case 0xa1: this.IndexedIndirectXRead(); this.A = this.Through(); break; // LDA (indexed indirect X)
|
||||
case 0xa2: this.FetchByte(); this.X = this.Through(); break; // LDX (immediate)
|
||||
case 0xa0: this.Y = this.Through(this.FetchByte()); break; // LDY (immediate)
|
||||
case 0xa1: this.A = this.Through(this.IndexedIndirectXRead()); break; // LDA (indexed indirect X)
|
||||
case 0xa2: this.X = this.Through(this.FetchByte()); break; // LDX (immediate)
|
||||
case 0xa4: this.ZeroPageRead(); this.Y = this.Through(); break; // LDY (zero page)
|
||||
case 0xa5: this.ZeroPageRead(); this.A = this.Through(); break; // LDA (zero page)
|
||||
case 0xa6: this.ZeroPageRead(); this.X = this.Through(); break; // LDX (zero page)
|
||||
case 0xa8: this.SwallowRead(); this.Y = this.Through(this.A); break; // TAY (implied)
|
||||
case 0xa9: this.FetchByte(); this.A = this.Through(); break; // LDA (immediate)
|
||||
case 0xa9: this.A = this.Through(this.FetchByte()); break; // LDA (immediate)
|
||||
case 0xaa: this.SwallowRead(); this.X = this.Through(this.A); break; // TAX (implied)
|
||||
case 0xac: this.AbsoluteRead(); this.Y = this.Through(); break; // LDY (absolute)
|
||||
case 0xad: this.AbsoluteRead(); this.A = this.Through(); break; // LDA (absolute)
|
||||
case 0xae: this.AbsoluteRead(); this.X = this.Through(); break; // LDX (absolute)
|
||||
case 0xac: this.Y = this.Through(this.AbsoluteRead()); break; // LDY (absolute)
|
||||
case 0xad: this.A = this.Through(this.AbsoluteRead()); break; // LDA (absolute)
|
||||
case 0xae: this.X = this.Through(this.AbsoluteRead()); break; // LDX (absolute)
|
||||
|
||||
case 0xb0: this.Branch(this.Carry); break; // BCS (relative)
|
||||
case 0xb1: this.IndirectIndexedYRead(); this.A = this.Through(); break; // LDA (indirect indexed Y)
|
||||
case 0xb1: this.A = this.Through(this.IndirectIndexedYRead()); break; // LDA (indirect indexed Y)
|
||||
case 0xb4: this.ZeroPageXRead(); this.Y = this.Through(); break; // LDY (zero page, X)
|
||||
case 0xb5: this.ZeroPageXRead(); this.A = this.Through(); break; // LDA (zero page, X)
|
||||
case 0xb6: this.ZeroPageYRead(); this.X = this.Through(); break; // LDX (zero page, Y)
|
||||
@@ -453,39 +453,39 @@ namespace M6502
|
||||
case 0xbd: this.AbsoluteXRead(); this.A = this.Through(); break; // LDA (absolute, X)
|
||||
case 0xbe: this.AbsoluteYRead(); this.X = this.Through(); break; // LDX (absolute, Y)
|
||||
|
||||
case 0xc0: this.FetchByte(); this.CMP(this.Y); break; // CPY (immediate)
|
||||
case 0xc1: this.IndexedIndirectXRead(); this.CMP(this.A); break; // CMP (indexed indirect X)
|
||||
case 0xc2: this.FetchByte(); break; // *NOP (immediate)
|
||||
case 0xc4: this.ZeroPageRead(); this.CMP(this.Y); break; // CPY (zero page)
|
||||
case 0xc5: this.ZeroPageRead(); this.CMP(this.A); break; // CMP (zero page)
|
||||
case 0xc0: this.CMP(this.Y, this.FetchByte()); break; // CPY (immediate)
|
||||
case 0xc1: this.CMP(this.A, this.IndexedIndirectXRead()); break; // CMP (indexed indirect X)
|
||||
case 0xc2: _ = this.FetchByte(); break; // *NOP (immediate)
|
||||
case 0xc4: this.CMP(this.Y, this.ZeroPageRead()); break; // CPY (zero page)
|
||||
case 0xc5: this.CMP(this.A, this.ZeroPageRead()); break; // CMP (zero page)
|
||||
case 0xc6: this.ZeroPageRead(); this.ModifyWrite(this.DEC()); break; // DEC (zero page)
|
||||
case 0xc8: this.SwallowRead(); this.Y = this.INC(this.Y); break; // INY (implied)
|
||||
case 0xc9: this.FetchByte(); this.CMP(this.A); break; // CMP (immediate)
|
||||
case 0xc9: this.CMP(this.A, this.FetchByte()); break; // CMP (immediate)
|
||||
case 0xca: this.SwallowRead(); this.X = this.DEC(this.X); break; // DEX (implied)
|
||||
case 0xcc: this.AbsoluteRead(); this.CMP(this.Y); break; // CPY (absolute)
|
||||
case 0xcd: this.AbsoluteRead(); this.CMP(this.A); break; // CMP (absolute)
|
||||
case 0xcc: this.CMP(this.Y, this.AbsoluteRead()); break; // CPY (absolute)
|
||||
case 0xcd: this.CMP(this.A, this.AbsoluteRead()); break; // CMP (absolute)
|
||||
case 0xce: this.AbsoluteRead(); this.ModifyWrite(this.DEC()); break; // DEC (absolute)
|
||||
|
||||
case 0xd0: this.BranchNot(this.Zero); break; // BNE (relative)
|
||||
case 0xd1: this.IndirectIndexedYRead(); this.CMP(this.A); break; // CMP (indirect indexed Y)
|
||||
case 0xd1: this.CMP(this.A, this.IndirectIndexedYRead()); break; // CMP (indirect indexed Y)
|
||||
case 0xd4: this.ZeroPageXRead(); break; // *NOP (zero page, X)
|
||||
case 0xd5: this.ZeroPageXRead(); this.CMP(this.A); break; // CMP (zero page, X)
|
||||
case 0xd5: this.CMP(this.A, this.ZeroPageXRead()); break; // CMP (zero page, X)
|
||||
case 0xd6: this.ZeroPageXRead(); this.ModifyWrite(this.DEC()); break; // DEC (zero page, X)
|
||||
case 0xd8: this.SwallowRead(); this.ResetFlag(StatusBits.DF); break; // CLD (implied)
|
||||
case 0xd9: this.AbsoluteYRead(); this.CMP(this.A); break; // CMP (absolute, Y)
|
||||
case 0xdd: this.AbsoluteXRead(); this.CMP(this.A); break; // CMP (absolute, X)
|
||||
case 0xd9: this.CMP(this.A, this.AbsoluteYRead()); break; // CMP (absolute, Y)
|
||||
case 0xdd: this.CMP(this.A, this.AbsoluteXRead()); break; // CMP (absolute, X)
|
||||
case 0xde: this.AbsoluteXAddress(); this.FixupRead(); this.ModifyWrite(this.DEC()); break; // DEC (absolute, X)
|
||||
|
||||
case 0xe0: this.FetchByte(); this.CMP(this.X); break; // CPX (immediate)
|
||||
case 0xe0: this.CMP(this.X, this.FetchByte()); break; // CPX (immediate)
|
||||
case 0xe1: this.IndexedIndirectXRead(); this.SBC(); break; // SBC (indexed indirect X)
|
||||
case 0xe2: this.FetchByte(); break; // *NOP (immediate)
|
||||
case 0xe4: this.ZeroPageRead(); this.CMP(this.X); break; // CPX (zero page)
|
||||
case 0xe2: _ = this.FetchByte(); break; // *NOP (immediate)
|
||||
case 0xe4: this.CMP(this.X, this.ZeroPageRead()); break; // CPX (zero page)
|
||||
case 0xe5: this.ZeroPageRead(); this.SBC(); break; // SBC (zero page)
|
||||
case 0xe6: this.ZeroPageRead(); this.ModifyWrite(this.INC()); break; // INC (zero page)
|
||||
case 0xe8: this.SwallowRead(); this.X = this.INC(this.X); break; // INX (implied)
|
||||
case 0xe9: this.FetchByte(); this.SBC(); break; // SBC (immediate)
|
||||
case 0xe9: _ = this.FetchByte(); this.SBC(); break; // SBC (immediate)
|
||||
case 0xea: this.SwallowRead(); break; // NOP (implied)
|
||||
case 0xec: this.AbsoluteRead(); this.CMP(this.X); break; // CPX (absolute)
|
||||
case 0xec: this.CMP(this.X, this.AbsoluteRead()); break; // CPX (absolute)
|
||||
case 0xed: this.AbsoluteRead(); this.SBC(); break; // SBC (absolute)
|
||||
case 0xee: this.AbsoluteRead(); this.ModifyWrite(this.INC()); break; // INC (absolute)
|
||||
|
||||
@@ -543,7 +543,7 @@ namespace M6502
|
||||
|
||||
// Can't use "FetchByte", since that would add an extra tick.
|
||||
this.ImmediateAddress();
|
||||
_ = this.ReadFromBus();
|
||||
this.ReadFromBus();
|
||||
|
||||
System.Diagnostics.Debug.Assert(this.Cycles == 1, "BUS read has introduced stray cycles");
|
||||
this.RaiseSYNC();
|
||||
@@ -631,16 +631,16 @@ namespace M6502
|
||||
|
||||
protected abstract void Fixup();
|
||||
|
||||
protected void MaybeFixupRead()
|
||||
protected byte MaybeFixupRead()
|
||||
{
|
||||
this.MaybeFixup();
|
||||
_ = this.MemoryRead();
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
protected void FixupRead()
|
||||
protected byte FixupRead()
|
||||
{
|
||||
this.Fixup();
|
||||
_ = this.MemoryRead();
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -711,52 +711,52 @@ namespace M6502
|
||||
|
||||
#region Address and read
|
||||
|
||||
protected void AbsoluteRead()
|
||||
protected byte AbsoluteRead()
|
||||
{
|
||||
this.AbsoluteAddress();
|
||||
_ = this.MemoryRead();
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
protected void ZeroPageRead()
|
||||
protected byte ZeroPageRead()
|
||||
{
|
||||
this.ZeroPageAddress();
|
||||
_ = this.MemoryRead();
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
protected void ZeroPageXRead()
|
||||
protected byte ZeroPageXRead()
|
||||
{
|
||||
this.ZeroPageXAddress();
|
||||
_ = this.MemoryRead();
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
protected void ZeroPageYRead()
|
||||
protected byte ZeroPageYRead()
|
||||
{
|
||||
this.ZeroPageYAddress();
|
||||
_ = this.MemoryRead();
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
protected void IndexedIndirectXRead()
|
||||
protected byte IndexedIndirectXRead()
|
||||
{
|
||||
this.IndexedIndirectXAddress();
|
||||
_ = this.MemoryRead();
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
protected void AbsoluteXRead()
|
||||
protected byte AbsoluteXRead()
|
||||
{
|
||||
this.AbsoluteXAddress();
|
||||
this.MaybeFixupRead();
|
||||
return this.MaybeFixupRead();
|
||||
}
|
||||
|
||||
protected void AbsoluteYRead()
|
||||
protected byte AbsoluteYRead()
|
||||
{
|
||||
this.AbsoluteYAddress();
|
||||
this.MaybeFixupRead();
|
||||
return this.MaybeFixupRead();
|
||||
}
|
||||
|
||||
protected void IndirectIndexedYRead()
|
||||
protected byte IndirectIndexedYRead()
|
||||
{
|
||||
this.IndirectIndexedYAddress();
|
||||
this.MaybeFixupRead();
|
||||
return this.MaybeFixupRead();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -771,7 +771,7 @@ namespace M6502
|
||||
|
||||
protected void Branch(bool condition)
|
||||
{
|
||||
this.FetchByte();
|
||||
_ = this.FetchByte();
|
||||
if (condition)
|
||||
{
|
||||
var relative = (sbyte)this.Bus.Data;
|
||||
@@ -876,12 +876,11 @@ namespace M6502
|
||||
this.SetFlag(StatusBits.VF, NegativeTest((byte)(~(operand ^ data) & (operand ^ intermediate))));
|
||||
}
|
||||
|
||||
protected void ADC() => this.A = this.DecimalMasked != 0 ? this.DecimalADC() : this.BinaryADC();
|
||||
protected void ADC(byte data) => this.A = this.DecimalMasked != 0 ? this.DecimalADC(data) : this.BinaryADC(data);
|
||||
|
||||
private byte BinaryADC()
|
||||
private byte BinaryADC(byte data)
|
||||
{
|
||||
var operand = this.A;
|
||||
var data = this.Bus.Data;
|
||||
this.Intermediate.Word = (ushort)(operand + data + this.Carry);
|
||||
|
||||
this.AdjustOverflowAdd(operand);
|
||||
@@ -892,10 +891,9 @@ namespace M6502
|
||||
return this.Intermediate.Low;
|
||||
}
|
||||
|
||||
private byte DecimalADC()
|
||||
private byte DecimalADC(byte data)
|
||||
{
|
||||
var operand = this.A;
|
||||
var data = this.Bus.Data;
|
||||
|
||||
var low = (ushort)(LowerNibble(operand) + LowerNibble(data) + this.Carry);
|
||||
this.Intermediate.Word = (ushort)(HigherNibble(operand) + HigherNibble(data));
|
||||
@@ -929,11 +927,17 @@ namespace M6502
|
||||
|
||||
#region Bitwise operations
|
||||
|
||||
protected void OrR() => this.A = this.Through(this.A | this.Bus.Data);
|
||||
protected void OrR(byte data) => this.A = this.Through(this.A | data);
|
||||
|
||||
protected void AndR() => this.A = this.Through(this.A & this.Bus.Data);
|
||||
protected void OrR() => this.OrR(this.Bus.Data);
|
||||
|
||||
protected void EorR() => this.A = this.Through(this.A ^ this.Bus.Data);
|
||||
protected void AndR(byte data) => this.A = this.Through(this.A & data);
|
||||
|
||||
protected void AndR() => this.AndR(this.Bus.Data);
|
||||
|
||||
protected void EorR(byte data) => this.A = this.Through(this.A ^ data);
|
||||
|
||||
protected void EorR() => this.EorR(this.Bus.Data);
|
||||
|
||||
protected void BIT()
|
||||
{
|
||||
@@ -945,9 +949,8 @@ namespace M6502
|
||||
|
||||
#endregion
|
||||
|
||||
protected void CMP(byte first)
|
||||
protected void CMP(byte first, byte second)
|
||||
{
|
||||
var second = this.Bus.Data;
|
||||
this.Intermediate.Word = (ushort)(first - second);
|
||||
this.AdjustNZ(this.Intermediate.Low);
|
||||
this.ResetFlag(StatusBits.CF, this.Intermediate.High);
|
||||
@@ -981,7 +984,8 @@ namespace M6502
|
||||
private void PLP()
|
||||
{
|
||||
this.SwallowPop();
|
||||
this.P = ClearBit(SetBit(this.Pop(), StatusBits.RF), StatusBits.BF);
|
||||
this.Pop();
|
||||
this.P = ClearBit(SetBit(this.Bus.Data, StatusBits.RF), StatusBits.BF);
|
||||
}
|
||||
|
||||
private void RTI()
|
||||
|
||||
@@ -323,7 +323,7 @@ namespace M6502
|
||||
private void RRA()
|
||||
{
|
||||
this.ModifyWrite(this.ROR());
|
||||
this.ADC();
|
||||
this.ADC(this.Bus.Data);
|
||||
}
|
||||
|
||||
private void SLO()
|
||||
@@ -341,7 +341,7 @@ namespace M6502
|
||||
private void DCP()
|
||||
{
|
||||
this.ModifyWrite(this.DEC());
|
||||
this.CMP(this.A);
|
||||
this.CMP(this.A, this.Bus.Data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace M6502
|
||||
case 0x0c: this.AbsoluteRead(); this.TSB(); break; // TSB a
|
||||
case 0x0f: this.ZeroPageRead(); this.BBR(Bit(0)); break; // BBR0 r
|
||||
|
||||
case 0x12: this.ZeroPageIndirectRead(); this.OrR(); break; // ORA (zp),y
|
||||
case 0x12: this.OrR(this.ZeroPageIndirectRead()); break; // ORA (zp),y
|
||||
case 0x13: break; // null
|
||||
case 0x14: this.ZeroPageRead(); this.TRB(); break; // TRB zp
|
||||
case 0x17: this.ZeroPageRead(); this.RMB(Bit(1)); break; // RMB1 zp
|
||||
@@ -109,11 +109,11 @@ namespace M6502
|
||||
case 0x6b: break; // null
|
||||
case 0x6f: this.ZeroPageRead(); this.BBR(Bit(6)); break; // BBR6 r
|
||||
|
||||
case 0x72: this.ZeroPageIndirectRead(); this.ADC(); break; // ADC (zp)
|
||||
case 0x72: this.ADC(this.ZeroPageIndirectRead()); break; // ADC (zp)
|
||||
case 0x73: break; // null
|
||||
case 0x74: this.ZeroPageXAddress(); this.MemoryWrite(0); break; // STZ zp,x
|
||||
case 0x77: this.ZeroPageRead(); this.RMB(Bit(7)); break; // RMB7 zp
|
||||
case 0x7a: this.SwallowRead(); this.SwallowPop(); this.Y = this.Through(this.Pop()); break; // PLY s
|
||||
case 0x7a: this.SwallowRead(); this.SwallowPop(); this.Pop(); this.Y = this.Through(); break; // PLY s
|
||||
case 0x7b: break; // null
|
||||
case 0x7c: this.AbsoluteXAddress(); this.Bus.Address.Assign(this.Intermediate); this.GetAddressPaged(); this.Jump(this.Bus.Address); break; // JMP (a,x)
|
||||
case 0x7f: this.ZeroPageRead(); this.BBR(Bit(7)); break; // BBR7 r
|
||||
@@ -149,7 +149,7 @@ namespace M6502
|
||||
case 0xcb: this.SwallowRead(); this.Waiting = true; break; // WAI i
|
||||
case 0xcf: this.ZeroPageRead(); this.BBS(Bit(4)); break; // BBS4 r
|
||||
|
||||
case 0xd2: this.ZeroPageIndirectRead(); this.CMP(this.A); break; // CMP (zp)
|
||||
case 0xd2: this.CMP(this.A, this.ZeroPageIndirectRead()); break; // CMP (zp)
|
||||
case 0xd3: break; // null
|
||||
case 0xd7: this.ZeroPageRead(); this.SMB(Bit(5)); break; // SMB5 zp
|
||||
case 0xda: this.SwallowRead(); this.Push(this.X); break; // PHX s
|
||||
@@ -165,7 +165,7 @@ namespace M6502
|
||||
case 0xf2: this.ZeroPageIndirectRead(); this.SBC(); break; // SBC (zp)
|
||||
case 0xf3: break; // null
|
||||
case 0xf7: this.ZeroPageRead(); this.SMB(Bit(7)); break; // SMB7 zp
|
||||
case 0xfa: this.SwallowRead(); this.SwallowPop(); this.X = this.Through(this.Pop()); break; // PLX s
|
||||
case 0xfa: this.SwallowRead(); this.SwallowPop(); this.Pop(); this.X = this.Through(); break; // PLX s
|
||||
case 0xfb: break; // null
|
||||
case 0xfc: break; // null
|
||||
case 0xff: this.ZeroPageRead(); this.BBS(Bit(7)); break; // BBS7 r
|
||||
@@ -263,10 +263,10 @@ namespace M6502
|
||||
|
||||
#region Address and read
|
||||
|
||||
private void ZeroPageIndirectRead()
|
||||
private byte ZeroPageIndirectRead()
|
||||
{
|
||||
this.ZeroPageIndirectAddress();
|
||||
this.MemoryRead();
|
||||
return this.MemoryRead();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -290,7 +290,7 @@ namespace M6502
|
||||
|
||||
private void BranchBit(bool condition)
|
||||
{
|
||||
this.FetchByte();
|
||||
_ = this.FetchByte();
|
||||
if (condition)
|
||||
{
|
||||
var relative = (sbyte)this.Bus.Data;
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit
|
||||
namespace MC6809.Test
|
||||
{
|
||||
using EightBit;
|
||||
using System;
|
||||
|
||||
public sealed class Board : Bus
|
||||
{
|
||||
private readonly Configuration configuration;
|
||||
private readonly Ram ram = new Ram(0x8000); // 0000 - 7FFF, 32K RAM
|
||||
private readonly UnusedMemory unused2000 = new UnusedMemory(0x2000, 0xff); // 8000 - 9FFF, 8K unused
|
||||
private readonly Ram io = new Ram(0x2000); // A000 - BFFF, 8K serial interface, minimally decoded
|
||||
private readonly Rom rom = new Rom(0x4000); // C000 - FFFF, 16K ROM
|
||||
private readonly Ram ram = new(0x8000); // 0000 - 7FFF, 32K RAM
|
||||
private readonly UnusedMemory unused2000 = new(0x2000, 0xff); // 8000 - 9FFF, 8K unused
|
||||
private readonly Ram io = new(0x2000); // A000 - BFFF, 8K serial interface, minimally decoded
|
||||
private readonly Rom rom = new(0x4000); // C000 - FFFF, 16K ROM
|
||||
|
||||
private readonly Disassembler disassembler;
|
||||
private readonly Profiler profiler;
|
||||
@@ -27,9 +28,9 @@ namespace EightBit
|
||||
public Board(Configuration configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
this.CPU = new MC6809(this);
|
||||
this.disassembler = new Disassembler(this, this.CPU);
|
||||
this.profiler = new Profiler(this, this.CPU, this.disassembler);
|
||||
CPU = new MC6809(this);
|
||||
disassembler = new Disassembler(this, CPU);
|
||||
profiler = new Profiler(this, CPU, disassembler);
|
||||
}
|
||||
|
||||
public MC6809 CPU { get; }
|
||||
@@ -40,20 +41,20 @@ namespace EightBit
|
||||
{
|
||||
if (absolute < 0x8000)
|
||||
{
|
||||
return new MemoryMapping(this.ram, 0x0000, Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
return new MemoryMapping(ram, 0x0000, Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
}
|
||||
|
||||
if (absolute < 0xa000)
|
||||
{
|
||||
return new MemoryMapping(this.unused2000, 0x8000, Mask.Sixteen, AccessLevel.ReadOnly);
|
||||
return new MemoryMapping(unused2000, 0x8000, Mask.Sixteen, AccessLevel.ReadOnly);
|
||||
}
|
||||
|
||||
if (absolute < 0xc000)
|
||||
{
|
||||
return new MemoryMapping(this.io, 0xa000, Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
return new MemoryMapping(io, 0xa000, Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
}
|
||||
|
||||
return new MemoryMapping(this.rom, 0xc000, Mask.Sixteen, AccessLevel.ReadOnly);
|
||||
return new MemoryMapping(rom, 0xc000, Mask.Sixteen, AccessLevel.ReadOnly);
|
||||
}
|
||||
|
||||
public override void RaisePOWER()
|
||||
@@ -61,166 +62,167 @@ namespace EightBit
|
||||
base.RaisePOWER();
|
||||
|
||||
// Get the CPU ready for action
|
||||
this.CPU.RaisePOWER();
|
||||
this.CPU.LowerRESET();
|
||||
this.CPU.RaiseINT();
|
||||
this.CPU.RaiseNMI();
|
||||
this.CPU.RaiseFIRQ();
|
||||
this.CPU.RaiseHALT();
|
||||
CPU.RaisePOWER();
|
||||
CPU.LowerRESET();
|
||||
CPU.RaiseINT();
|
||||
CPU.RaiseNMI();
|
||||
CPU.RaiseFIRQ();
|
||||
CPU.RaiseHALT();
|
||||
|
||||
// Get the ACIA ready for action
|
||||
this.Address.Word = 0b1010000000000000;
|
||||
this.Data = (byte)(MC6850.ControlRegister.CR0 | MC6850.ControlRegister.CR1); // Master reset
|
||||
this.ACIA.CTS.Lower();
|
||||
this.ACIA.RW.Lower();
|
||||
this.UpdateAciaPins();
|
||||
this.ACIA.RaisePOWER();
|
||||
this.AccessAcia();
|
||||
Address.Word = 0b1010000000000000;
|
||||
Data = (byte)(MC6850.ControlRegister.CR0 | MC6850.ControlRegister.CR1); // Master reset
|
||||
ACIA.CTS.Lower();
|
||||
ACIA.RW.Lower();
|
||||
UpdateAciaPins();
|
||||
ACIA.RaisePOWER();
|
||||
AccessAcia();
|
||||
}
|
||||
|
||||
public override void LowerPOWER()
|
||||
{
|
||||
////this.profiler.Generate();
|
||||
|
||||
this.ACIA.LowerPOWER();
|
||||
this.CPU.LowerPOWER();
|
||||
ACIA.LowerPOWER();
|
||||
CPU.LowerPOWER();
|
||||
base.LowerPOWER();
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
System.Console.TreatControlCAsInput = true;
|
||||
Console.TreatControlCAsInput = true;
|
||||
|
||||
// Load our BASIC interpreter
|
||||
var directory = this.configuration.RomDirectory + "\\";
|
||||
this.LoadHexFile(directory + "ExBasROM.hex");
|
||||
var directory = configuration.RomDirectory + "\\";
|
||||
LoadHexFile(directory + "ExBasROM.hex");
|
||||
|
||||
// Catch a byte being transmitted
|
||||
this.ACIA.Transmitting += this.ACIA_Transmitting;
|
||||
ACIA.Transmitting += ACIA_Transmitting;
|
||||
|
||||
// Keyboard wiring, check for input once per frame
|
||||
this.CPU.ExecutedInstruction += this.CPU_ExecutedInstruction;
|
||||
CPU.ExecutedInstruction += CPU_ExecutedInstruction;
|
||||
|
||||
if (this.configuration.DebugMode)
|
||||
// Marshal data from ACIA -> memory
|
||||
this.ReadingByte += Board_ReadingByte;
|
||||
|
||||
// Marshal data from memory -> ACIA
|
||||
this.WrittenByte += Board_WrittenByte;
|
||||
|
||||
if (configuration.DebugMode)
|
||||
{
|
||||
// MC6809 disassembly wiring
|
||||
this.CPU.ExecutingInstruction += this.CPU_ExecutingInstruction;
|
||||
this.CPU.ExecutedInstruction += this.CPU_ExecutedInstruction_Debug;
|
||||
CPU.ExecutingInstruction += CPU_ExecutingInstruction;
|
||||
CPU.ExecutedInstruction += CPU_ExecutedInstruction_Debug;
|
||||
}
|
||||
|
||||
if (this.configuration.TerminatesEarly)
|
||||
if (configuration.TerminatesEarly)
|
||||
{
|
||||
// Early termination condition for CPU timing code
|
||||
this.CPU.ExecutedInstruction += this.CPU_ExecutedInstruction_Termination;
|
||||
CPU.ExecutedInstruction += CPU_ExecutedInstruction_Termination;
|
||||
}
|
||||
|
||||
////this.profiler.Enable();
|
||||
////this.profiler.EmitLine += this.Profiler_EmitLine;
|
||||
}
|
||||
|
||||
// Marshal data from ACIA -> memory
|
||||
protected override void OnReadingByte()
|
||||
private void Board_ReadingByte(object? sender, EventArgs e)
|
||||
{
|
||||
this.UpdateAciaPins();
|
||||
this.ACIA.RW.Raise();
|
||||
if (this.AccessAcia())
|
||||
UpdateAciaPins();
|
||||
ACIA.RW.Raise();
|
||||
if (AccessAcia())
|
||||
{
|
||||
this.Poke(this.ACIA.DATA);
|
||||
}
|
||||
|
||||
base.OnReadingByte();
|
||||
}
|
||||
|
||||
// Marshal data from memory -> ACIA
|
||||
protected override void OnWrittenByte()
|
||||
{
|
||||
base.OnWrittenByte();
|
||||
this.UpdateAciaPins();
|
||||
if (this.ACIA.Selected)
|
||||
{
|
||||
this.ACIA.RW.Lower();
|
||||
this.AccessAcia();
|
||||
Poke(ACIA.DATA);
|
||||
}
|
||||
}
|
||||
|
||||
private void Profiler_EmitLine(object sender, ProfileLineEventArgs e)
|
||||
private void Board_WrittenByte(object? sender, EventArgs e)
|
||||
{
|
||||
UpdateAciaPins();
|
||||
if (ACIA.Selected)
|
||||
{
|
||||
ACIA.RW.Lower();
|
||||
AccessAcia();
|
||||
}
|
||||
}
|
||||
|
||||
private void Profiler_EmitLine(object? sender, ProfileLineEventArgs e)
|
||||
{
|
||||
var cycles = e.Cycles;
|
||||
var disassembled = e.Source;
|
||||
System.Console.Error.WriteLine(disassembled);
|
||||
Console.Error.WriteLine(disassembled);
|
||||
}
|
||||
|
||||
private void CPU_ExecutedInstruction_Termination(object sender, EventArgs e)
|
||||
private void CPU_ExecutedInstruction_Termination(object? sender, EventArgs e)
|
||||
{
|
||||
this.totalCycleCount += (ulong)this.CPU.Cycles;
|
||||
if (this.totalCycleCount > Configuration.TerminationCycles)
|
||||
totalCycleCount += (ulong)CPU.Cycles;
|
||||
if (totalCycleCount > Configuration.TerminationCycles)
|
||||
{
|
||||
this.LowerPOWER();
|
||||
LowerPOWER();
|
||||
}
|
||||
}
|
||||
|
||||
private void CPU_ExecutedInstruction_Debug(object sender, EventArgs e)
|
||||
private void CPU_ExecutedInstruction_Debug(object? sender, EventArgs e)
|
||||
{
|
||||
if (!this.ignoreDisassembly)
|
||||
if (!ignoreDisassembly)
|
||||
{
|
||||
var disassembled = $"{this.disassembler.Trace(this.disassembleAt)}\t{this.ACIA.DumpStatus()}";
|
||||
System.Console.Error.WriteLine(disassembled);
|
||||
var disassembled = $"{disassembler.Trace(disassembleAt)}\t{ACIA.DumpStatus()}";
|
||||
Console.Error.WriteLine(disassembled);
|
||||
}
|
||||
}
|
||||
|
||||
private void CPU_ExecutingInstruction(object sender, EventArgs e)
|
||||
private void CPU_ExecutingInstruction(object? sender, EventArgs e)
|
||||
{
|
||||
this.disassembleAt = this.CPU.PC.Word;
|
||||
this.ignoreDisassembly = this.disassembler.Ignore || this.disassembler.Pause;
|
||||
disassembleAt = CPU.PC.Word;
|
||||
ignoreDisassembly = disassembler.Ignore || disassembler.Pause;
|
||||
}
|
||||
|
||||
private void CPU_ExecutedInstruction(object sender, EventArgs e)
|
||||
private void CPU_ExecutedInstruction(object? sender, EventArgs e)
|
||||
{
|
||||
this.frameCycleCount -= this.CPU.Cycles;
|
||||
if (this.frameCycleCount < 0)
|
||||
frameCycleCount -= CPU.Cycles;
|
||||
if (frameCycleCount < 0)
|
||||
{
|
||||
if (System.Console.KeyAvailable)
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
var key = System.Console.ReadKey(true);
|
||||
var key = Console.ReadKey(true);
|
||||
if (key.Key == ConsoleKey.F12)
|
||||
{
|
||||
this.LowerPOWER();
|
||||
LowerPOWER();
|
||||
}
|
||||
|
||||
this.ACIA.RDR = System.Convert.ToByte(key.KeyChar);
|
||||
this.ACIA.MarkReceiveStarting();
|
||||
ACIA.RDR = Convert.ToByte(key.KeyChar);
|
||||
ACIA.MarkReceiveStarting();
|
||||
}
|
||||
|
||||
this.frameCycleCount = (long)Configuration.FrameCycleInterval;
|
||||
frameCycleCount = (long)Configuration.FrameCycleInterval;
|
||||
}
|
||||
}
|
||||
|
||||
private void ACIA_Transmitting(object sender, EventArgs e)
|
||||
private void ACIA_Transmitting(object? sender, EventArgs e)
|
||||
{
|
||||
System.Console.Out.Write(Convert.ToChar(this.ACIA.TDR));
|
||||
this.ACIA.MarkTransmitComplete();
|
||||
Console.Out.Write(Convert.ToChar(ACIA.TDR));
|
||||
ACIA.MarkTransmitComplete();
|
||||
}
|
||||
|
||||
private void UpdateAciaPins()
|
||||
{
|
||||
this.ACIA.DATA = this.Data;
|
||||
this.ACIA.RS.Match(this.Address.Word & (ushort)Bits.Bit0);
|
||||
this.ACIA.CS0.Match(this.Address.Word & (ushort)Bits.Bit15);
|
||||
this.ACIA.CS1.Match(this.Address.Word & (ushort)Bits.Bit13);
|
||||
this.ACIA.CS2.Match(this.Address.Word & (ushort)Bits.Bit14);
|
||||
ACIA.DATA = Data;
|
||||
ACIA.RS.Match(Address.Word & (ushort)Bits.Bit0);
|
||||
ACIA.CS0.Match(Address.Word & (ushort)Bits.Bit15);
|
||||
ACIA.CS1.Match(Address.Word & (ushort)Bits.Bit13);
|
||||
ACIA.CS2.Match(Address.Word & (ushort)Bits.Bit14);
|
||||
}
|
||||
|
||||
private bool AccessAcia()
|
||||
{
|
||||
this.ACIA.E.Raise();
|
||||
ACIA.E.Raise();
|
||||
try
|
||||
{
|
||||
this.ACIA.Tick();
|
||||
return this.ACIA.Activated;
|
||||
ACIA.Tick();
|
||||
return ACIA.Activated;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.ACIA.E.Lower();
|
||||
ACIA.E.Lower();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809.Test;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal sealed class TestHarness(Configuration configuration)
|
||||
|
||||
@@ -580,17 +580,19 @@ namespace MC6809
|
||||
|
||||
private byte Pop(Register16 stack)
|
||||
{
|
||||
var read = this.MemoryRead(stack);
|
||||
_ = this.MemoryRead(stack);
|
||||
stack.Increment();
|
||||
return read;
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
private byte PopS() => this.Pop(this.S);
|
||||
|
||||
private Register16 PopWord(Register16 stack)
|
||||
{
|
||||
this.Intermediate.High = this.Pop(stack);
|
||||
this.Intermediate.Low = this.Pop(stack);
|
||||
this.Pop(stack);
|
||||
this.Intermediate.High = this.Bus.Data;
|
||||
this.Pop(stack);
|
||||
this.Intermediate.Low = this.Bus.Data;
|
||||
return this.Intermediate;
|
||||
}
|
||||
|
||||
@@ -600,7 +602,8 @@ namespace MC6809
|
||||
|
||||
private Register16 Address_relative_byte()
|
||||
{
|
||||
var offset = (sbyte)this.FetchByte();
|
||||
this.FetchByte();
|
||||
var offset = (sbyte)this.Bus.Data;
|
||||
this.Intermediate.Word = (ushort)(this.PC.Word + offset);
|
||||
return this.Intermediate;
|
||||
}
|
||||
@@ -614,7 +617,8 @@ namespace MC6809
|
||||
|
||||
private Register16 Address_direct()
|
||||
{
|
||||
this.Intermediate.Assign(this.FetchByte(), this.DP);
|
||||
this.FetchByte();
|
||||
this.Intermediate.Assign(this.Bus.Data, this.DP);
|
||||
return this.Intermediate;
|
||||
}
|
||||
|
||||
@@ -634,7 +638,8 @@ namespace MC6809
|
||||
|
||||
private Register16 Address_indexed()
|
||||
{
|
||||
var type = this.FetchByte();
|
||||
this.FetchByte();
|
||||
var type = this.Bus.Data;
|
||||
var r = this.RR((type & (byte)(Bits.Bit6 | Bits.Bit5)) >> 5);
|
||||
|
||||
if ((type & (byte)Bits.Bit7) != 0)
|
||||
@@ -672,7 +677,8 @@ namespace MC6809
|
||||
break;
|
||||
case 0b1000: // n,R (eight-bit)
|
||||
this.Tick();
|
||||
this.Intermediate.Word = (ushort)(r.Word + (sbyte)this.FetchByte());
|
||||
this.FetchByte();
|
||||
this.Intermediate.Word = (ushort)(r.Word + (sbyte)this.Bus.Data);
|
||||
break;
|
||||
case 0b1001: // n,R (sixteen-bit)
|
||||
this.Tick(4);
|
||||
@@ -715,13 +721,29 @@ namespace MC6809
|
||||
return this.Intermediate;
|
||||
}
|
||||
|
||||
private byte AM_immediate_byte() => this.FetchByte();
|
||||
private byte AM_immediate_byte()
|
||||
{
|
||||
this.FetchByte();
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
private byte AM_direct_byte() => this.MemoryRead(this.Address_direct());
|
||||
private byte AM_direct_byte()
|
||||
{
|
||||
this.MemoryRead(this.Address_direct());
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
private byte AM_indexed_byte() => this.MemoryRead(this.Address_indexed());
|
||||
private byte AM_indexed_byte()
|
||||
{
|
||||
this.MemoryRead(this.Address_indexed());
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
private byte AM_extended_byte() => this.MemoryRead(this.Address_extended());
|
||||
private byte AM_extended_byte()
|
||||
{
|
||||
this.MemoryRead(this.Address_extended());
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
private Register16 AM_immediate_word() => this.FetchWord();
|
||||
|
||||
@@ -859,25 +881,29 @@ namespace MC6809
|
||||
if ((data & (byte)Bits.Bit0) != 0)
|
||||
{
|
||||
this.Tick();
|
||||
this.CC = this.Pop(stack);
|
||||
this.Pop(stack);
|
||||
this.CC = this.Bus.Data;
|
||||
}
|
||||
|
||||
if ((data & (byte)Bits.Bit1) != 0)
|
||||
{
|
||||
this.Tick();
|
||||
this.A = this.Pop(stack);
|
||||
this.Pop(stack);
|
||||
this.A = this.Bus.Data;
|
||||
}
|
||||
|
||||
if ((data & (byte)Bits.Bit2) != 0)
|
||||
{
|
||||
this.Tick();
|
||||
this.B = this.Pop(stack);
|
||||
this.Pop(stack);
|
||||
this.B = this.Bus.Data;
|
||||
}
|
||||
|
||||
if ((data & (byte)Bits.Bit3) != 0)
|
||||
{
|
||||
this.Tick();
|
||||
this.DP = this.Pop(stack);
|
||||
this.Pop(stack);
|
||||
this.DP = this.Bus.Data;
|
||||
}
|
||||
|
||||
if ((data & (byte)Bits.Bit4) != 0)
|
||||
@@ -1050,7 +1076,8 @@ namespace MC6809
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Execute(this.FetchByte());
|
||||
this.FetchByte();
|
||||
this.Execute(this.Bus.Data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1079,8 +1106,8 @@ namespace MC6809
|
||||
{
|
||||
switch (this.OpCode)
|
||||
{
|
||||
case 0x10: this.prefix10 = true; this.Execute(this.FetchByte()); break;
|
||||
case 0x11: this.prefix11 = true; this.Execute(this.FetchByte()); break;
|
||||
case 0x10: this.prefix10 = true; this.FetchByte(); this.Execute(this.Bus.Data); break;
|
||||
case 0x11: this.prefix11 = true; this.FetchByte(); this.Execute(this.Bus.Data); break;
|
||||
|
||||
// ABX
|
||||
case 0x3a: this.Tick(3); this.X.Word += this.B; break; // ABX (inherent)
|
||||
|
||||
66
Z80/Z80.cs
66
Z80/Z80.cs
@@ -549,14 +549,14 @@ namespace Z80
|
||||
private byte ReadDataUnderInterrupt()
|
||||
{
|
||||
this.LowerM1();
|
||||
this.Tick(3);
|
||||
this.LowerIORQ();
|
||||
this.Tick();
|
||||
_ = this.Bus.Data;
|
||||
this.RaiseIORQ();
|
||||
Debug.Assert(this.Cycles == 4);
|
||||
this.RefreshMemory();
|
||||
Debug.Assert(this.Cycles == 5);
|
||||
this.Tick(3);
|
||||
this.LowerIORQ();
|
||||
this.Tick();
|
||||
_ = this.Bus.Data;
|
||||
this.RaiseIORQ();
|
||||
Debug.Assert(this.Cycles == 4);
|
||||
this.RefreshMemory();
|
||||
Debug.Assert(this.Cycles == 5);
|
||||
this.RaiseM1();
|
||||
return this.Bus.Data;
|
||||
}
|
||||
@@ -933,7 +933,7 @@ namespace Z80
|
||||
switch (z)
|
||||
{
|
||||
case 0: // Input from port with 16-bit address
|
||||
this.ReadPort(this.BC);
|
||||
_ = this.ReadPort(this.BC);
|
||||
this.MEMPTR.Increment();
|
||||
if (y != 6)
|
||||
{
|
||||
@@ -1149,7 +1149,7 @@ namespace Z80
|
||||
break;
|
||||
case 2: // DJNZ d
|
||||
this.Tick();
|
||||
_ = this.JumpRelativeConditional(--this.B != 0);
|
||||
this.JumpRelativeConditional(--this.B != 0);
|
||||
break;
|
||||
case 3: // JR d
|
||||
this.JumpRelative(this.FetchByte());
|
||||
@@ -1158,7 +1158,7 @@ namespace Z80
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
_ = this.JumpRelativeConditionalFlag(y - 4);
|
||||
this.JumpRelativeConditionalFlag(y - 4);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
@@ -1197,7 +1197,7 @@ namespace Z80
|
||||
this.SetWord(this.HL2());
|
||||
break;
|
||||
case 3: // LD (nn),A
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
WriteMemoryIndirect(this.A);
|
||||
break;
|
||||
default:
|
||||
@@ -1219,7 +1219,7 @@ namespace Z80
|
||||
this.HL2().Assign(this.GetWord());
|
||||
break;
|
||||
case 3: // LD A,(nn)
|
||||
this.FetchWordMEMPTR();
|
||||
this.FetchInto(this.MEMPTR);
|
||||
this.A = this.ReadMemoryIndirect();
|
||||
break;
|
||||
default:
|
||||
@@ -1270,14 +1270,12 @@ namespace Z80
|
||||
this.FetchDisplacement();
|
||||
}
|
||||
|
||||
_ = this.FetchByte(); // LD r,n
|
||||
if (memoryY)
|
||||
{
|
||||
var value = this.FetchByte(); // LD r,n
|
||||
if (memoryY)
|
||||
{
|
||||
this.Tick(2);
|
||||
}
|
||||
this.R(y, value);
|
||||
this.Tick(2);
|
||||
}
|
||||
this.R(y, this.Bus.Data);
|
||||
break;
|
||||
|
||||
case 7: // Assorted operations on accumulator/flags
|
||||
@@ -1422,13 +1420,13 @@ namespace Z80
|
||||
switch (z)
|
||||
{
|
||||
case 0: // Conditional return
|
||||
_ = this.ReturnConditionalFlag(y);
|
||||
this.ReturnConditionalFlag(y);
|
||||
break;
|
||||
case 1: // POP & various ops
|
||||
switch (q)
|
||||
{
|
||||
case 0: // POP rp2[p]
|
||||
this.RP2(p).Assign(this.PopWord());
|
||||
this.PopInto(this.RP2(p));
|
||||
break;
|
||||
case 1:
|
||||
switch (p)
|
||||
@@ -1457,7 +1455,7 @@ namespace Z80
|
||||
|
||||
break;
|
||||
case 2: // Conditional jump
|
||||
_ = this.JumpConditionalFlag(y);
|
||||
this.JumpConditionalFlag(y);
|
||||
break;
|
||||
case 3: // Assorted operations
|
||||
switch (y)
|
||||
@@ -1482,8 +1480,7 @@ namespace Z80
|
||||
this.WritePort(this.FetchByte());
|
||||
break;
|
||||
case 3: // IN A,(n)
|
||||
this.ReadPort(this.FetchByte());
|
||||
this.A = this.Bus.Data;
|
||||
this.A = this.ReadPort(this.FetchByte());
|
||||
break;
|
||||
case 4: // EX (SP),HL
|
||||
this.XHTL(this.HL2());
|
||||
@@ -1504,7 +1501,7 @@ namespace Z80
|
||||
|
||||
break;
|
||||
case 4: // Conditional call: CALL cc[y], nn
|
||||
_ = this.CallConditionalFlag(y);
|
||||
this.CallConditionalFlag(y);
|
||||
break;
|
||||
case 5: // PUSH & various ops
|
||||
switch (q)
|
||||
@@ -1682,7 +1679,7 @@ namespace Z80
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(flag)),
|
||||
};
|
||||
|
||||
protected sealed override bool ReturnConditionalFlag(int flag)
|
||||
protected sealed override void ReturnConditionalFlag(int flag)
|
||||
{
|
||||
var condition = this.ConvertCondition(flag);
|
||||
this.Tick();
|
||||
@@ -1690,7 +1687,6 @@ namespace Z80
|
||||
{
|
||||
this.Return();
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
|
||||
private Register16 SBC(Register16 operand, Register16 value)
|
||||
@@ -2041,7 +2037,7 @@ namespace Z80
|
||||
|
||||
private void BlockLoad()
|
||||
{
|
||||
this.MemoryRead(this.HL);
|
||||
_ = this.MemoryRead(this.HL);
|
||||
this.Bus.Address.Assign(this.DE);
|
||||
this.MemoryUpdate(1);
|
||||
this.Tick(2);
|
||||
@@ -2142,7 +2138,7 @@ namespace Z80
|
||||
private void BlockIn()
|
||||
{
|
||||
this.Tick();
|
||||
this.ReadPort(this.BC);
|
||||
_ = this.ReadPort(this.BC);
|
||||
this.Bus.Address.Assign(this.HL);
|
||||
this.MemoryUpdate(1);
|
||||
this.AdjustSZXY(--this.B);
|
||||
@@ -2357,20 +2353,21 @@ namespace Z80
|
||||
this.Tick();
|
||||
}
|
||||
|
||||
private void ReadPort(byte port)
|
||||
private byte ReadPort(byte port)
|
||||
{
|
||||
this.Bus.Address.Assign(port, this.Bus.Data = this.A);
|
||||
this.ReadPort();
|
||||
_ = this.ReadPort();
|
||||
this.MEMPTR.Increment();
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
private void ReadPort(Register16 port)
|
||||
private byte ReadPort(Register16 port)
|
||||
{
|
||||
this.Bus.Address.Assign(port);
|
||||
this.ReadPort();
|
||||
return this.ReadPort();
|
||||
}
|
||||
|
||||
private void ReadPort()
|
||||
private byte ReadPort()
|
||||
{
|
||||
this.MEMPTR.Assign(this.Bus.Address);
|
||||
this.Tick(2);
|
||||
@@ -2381,6 +2378,7 @@ namespace Z80
|
||||
this.RaiseRD();
|
||||
this.RaiseIORQ();
|
||||
this.Tick();
|
||||
return this.Bus.Data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user