More sharing of concepts between all Intel style processors

This commit is contained in:
Adrian Conlon
2026-01-03 23:17:30 +00:00
parent 810d05a50e
commit e1bf58afbc
3 changed files with 344 additions and 304 deletions

View File

@@ -85,8 +85,9 @@ namespace Intel8080
this.OnReadingMemory();
this.Tick(2);
base.MemoryRead();
this.Tick();
this.OnReadMemory();
this.Tick(2);
this.Tick();
return this.Bus.Data;
}
@@ -103,6 +104,14 @@ namespace Intel8080
return this.Bus.Data;
}
protected override void HandleINT()
{
base.HandleINT();
var data = this.ReadDataUnderInterrupt();
this.Tick();
this.Execute(data);
}
protected override void Call(Register16 destination)
{
this.Tick();
@@ -115,14 +124,6 @@ namespace Intel8080
this.Tick(5);
}
protected override void HandleINT()
{
base.HandleINT();
var data = this.ReadDataUnderInterrupt();
this.Tick();
this.Execute(data);
}
private int Zero() => ZeroTest(this.F);
private int Carry() => CarryTest(this.F);
@@ -145,14 +146,24 @@ namespace Intel8080
private static byte SetBit(byte f, StatusBits flag) => SetBit(f, (byte)flag);
private void SetBit(StatusBits flag) => this.F = SetBit(this.F, flag);
private static byte SetBit(byte f, StatusBits flag, int condition) => SetBit(f, (byte)flag, condition);
private void SetBit(StatusBits flag, int condition) => this.F = SetBit(this.F, flag, condition);
private static byte SetBit(byte f, StatusBits flag, bool condition) => SetBit(f, (byte)flag, condition);
private void SetBit(StatusBits flag, bool condition) => this.F = SetBit(this.F, flag, condition);
private static byte ClearBit(byte f, StatusBits flag) => ClearBit(f, (byte)flag);
private void ClearBit(StatusBits flag) => this.F = ClearBit(this.F, flag);
private static byte ClearBit(byte f, StatusBits flag, int condition) => ClearBit(f, (byte)flag, condition);
private void ClearBit(StatusBits flag, int condition) => this.F = ClearBit(this.F, flag, condition);
private static byte AdjustSign(byte input, byte value) => SetBit(input, StatusBits.SF, SignTest(value));
private static byte AdjustZero(byte input, byte value) => ClearBit(input, StatusBits.ZF, value);
@@ -171,14 +182,38 @@ namespace Intel8080
return AdjustParity(input, value);
}
private void AdjustSZP(byte value) => this.F = AdjustSZP(this.F, value);
private static byte AdjustAuxiliaryCarryAdd(byte input, byte before, byte value, int calculation) => SetBit(input, StatusBits.AC, CalculateHalfCarryAdd(before, value, calculation));
private void AdjustAuxiliaryCarryAdd(byte before, byte value, int calculation) => this.F = AdjustAuxiliaryCarryAdd(this.F, before, value, calculation);
private static byte AdjustAuxiliaryCarrySub(byte input, byte before, byte value, int calculation) => ClearBit(input, StatusBits.AC, CalculateHalfCarrySub(before, value, calculation));
private void AdjustAuxiliaryCarrySub(byte before, byte value, int calculation) => this.F = AdjustAuxiliaryCarrySub(this.F, before, value, calculation);
protected override void DisableInterrupts() => this.interruptEnable = false;
protected override void EnableInterrupts() => this.interruptEnable = true;
private Register16 RP(int rp) => rp switch
{
0 => this.BC,
1 => this.DE,
2 => this.HL,
3 => this.SP,
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
};
private Register16 RP2(int rp) => rp switch
{
0 => this.BC,
1 => this.DE,
2 => this.HL,
3 => this.AF,
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
};
private ref byte R(int r, AccessLevel access = AccessLevel.ReadOnly)
{
switch (r)
@@ -226,24 +261,6 @@ namespace Intel8080
}
}
private Register16 RP(int rp) => rp switch
{
0 => this.BC,
1 => this.DE,
2 => this.HL,
3 => this.SP,
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
};
private Register16 RP2(int rp) => rp switch
{
0 => this.BC,
1 => this.DE,
2 => this.HL,
3 => this.AF,
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
};
private void Execute(int x, int y, int z, int p, int q)
{
var memoryY = y == 6;
@@ -403,37 +420,40 @@ namespace Intel8080
this.R(y, this.R(z));
}
break;
case 2: // Operate on accumulator and register/memory location
switch (y)
{
case 0: // ADD A,r
this.Add(this.R(z));
break;
case 1: // ADC A,r
this.ADC(this.R(z));
break;
case 2: // SUB r
this.SUB(this.R(z));
break;
case 3: // SBC A,r
this.SBB(this.R(z));
break;
case 4: // AND r
this.AndR(this.R(z));
break;
case 5: // XOR r
this.XorR(this.R(z));
break;
case 6: // OR r
this.OrR(this.R(z));
break;
case 7: // CP r
this.Compare(this.R(z));
break;
default:
throw new NotSupportedException("Invalid operation mode");
case 2:
{ // Operate on accumulator and register/memory location
var value = this.R(z);
switch (y)
{
case 0: // ADD A,r
this.A = this.Add(this.A, value);
break;
case 1: // ADC A,r
this.A = this.ADC(this.A, value);
break;
case 2: // SUB r
this.A = this.SUB(this.A, value);
break;
case 3: // SBC A,r
this.A = this.SBC(this.A, value);
break;
case 4: // AND r
this.AndR(value);
break;
case 5: // XOR r
this.XorR(value);
break;
case 6: // OR r
this.OrR(value);
break;
case 7: // CP r
this.Compare(value);
break;
default:
throw new NotSupportedException("Invalid operation mode");
}
break;
}
break;
case 3:
switch (z)
{
@@ -528,38 +548,40 @@ 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.Bus.Data);
break;
case 1: // ADC A,n
this.ADC(this.Bus.Data);
break;
case 2: // SUB n
this.SUB(this.Bus.Data);
break;
case 3: // SBC A,n
this.SBB(this.Bus.Data);
break;
case 4: // AND n
this.AndR(this.Bus.Data);
break;
case 5: // XOR n
this.XorR(this.Bus.Data);
break;
case 6: // OR n
this.OrR(this.Bus.Data);
break;
case 7: // CP n
this.Compare(this.Bus.Data);
break;
default:
throw new NotSupportedException("Invalid operation mode");
case 6:
{ // Operate on accumulator and immediate operand: alu[y] n
var operand = this.FetchByte();
switch (y)
{
case 0: // ADD A,n
this.A = this.Add(this.A, operand);
break;
case 1: // ADC A,n
this.A = this.ADC(this.A, operand);
break;
case 2: // SUB n
this.A = this.SUB(this.A, operand);
break;
case 3: // SBC A,n
this.A = this.SBC(this.A, operand);
break;
case 4: // AND n
this.AndR(operand);
break;
case 5: // XOR n
this.XorR(operand);
break;
case 6: // OR n
this.OrR(operand);
break;
case 7: // CP n
this.Compare(operand);
break;
default:
throw new NotSupportedException("Invalid operation mode");
}
break;
}
break;
case 7: // Restart: RST y * 8
this.Restart((byte)(y << 3));
break;
@@ -575,16 +597,18 @@ namespace Intel8080
private byte Increment(byte operand)
{
this.F = AdjustSZP(this.F, ++operand);
this.F = ClearBit(this.F, StatusBits.AC, LowNibble(operand));
return operand;
var result = operand; ++operand;
AdjustSZP(result);
ClearBit(StatusBits.AC, LowNibble(result));
return result;
}
private byte Decrement(byte operand)
{
this.F = AdjustSZP(this.F, --operand);
this.F = SetBit(this.F, StatusBits.AC, LowNibble(operand) != (byte)Mask.Four);
return operand;
var result = operand; --operand;
AdjustSZP(result);
SetBit(StatusBits.AC, LowNibble(result) != (byte)Mask.Four);
return result;
}
protected sealed override bool ConvertCondition(int flag) => flag switch
@@ -614,58 +638,58 @@ namespace Intel8080
{
var result = this.HL.Word + value.Word;
this.HL.Word = (ushort)result;
this.F = SetBit(this.F, StatusBits.CF, result & (int)Bits.Bit16);
SetBit(StatusBits.CF, result & (int)Bits.Bit16);
}
private void Add(byte value, int carry = 0)
private byte Add(byte operand, byte value, int carry = 0)
{
this.MEMPTR.Word = (ushort)(this.A + value + carry);
this.Intermediate.Word = (ushort)(operand + value + carry);
var result = this.Intermediate.Low;
this.F = AdjustAuxiliaryCarryAdd(this.F, this.A, value, this.MEMPTR.Low);
AdjustAuxiliaryCarryAdd(operand, value, result);
this.A = this.MEMPTR.Low;
this.F = SetBit(this.F, StatusBits.CF, CarryTest(this.MEMPTR.High));
this.F = AdjustSZP(this.F, this.A);
}
private void ADC(byte value) => this.Add(value, this.Carry());
private byte Subtract(byte operand, byte value, int carry = 0)
{
this.MEMPTR.Word = (ushort)(operand - value - carry);
this.F = AdjustAuxiliaryCarrySub(this.F, operand, value, this.MEMPTR.Word);
var result = this.MEMPTR.Low;
this.F = SetBit(this.F, StatusBits.CF, CarryTest(this.MEMPTR.High));
this.F = AdjustSZP(this.F, result);
SetBit(StatusBits.CF, CarryTest(this.Intermediate.High));
AdjustSZP(result);
return result;
}
private void SUB(byte value, int carry = 0) => this.A = this.Subtract(this.A, value, carry);
private byte ADC(byte operand, byte value) => this.Add(operand, value, this.Carry());
private void SBB(byte value) => this.SUB(value, this.Carry());
private byte Subtract(byte operand, byte value, int carry = 0)
{
this.Intermediate.Word = (ushort)(operand - value - carry);
var result = this.Intermediate.Low;
AdjustAuxiliaryCarrySub(operand, value, this.Intermediate.Word);
SetBit(StatusBits.CF, CarryTest(this.Intermediate.High));
AdjustSZP(result);
return result;
}
private byte SUB(byte operand, byte value, int carry = 0) => this.Subtract(operand, value, carry);
private byte SBC(byte operand, byte value) => this.SUB(operand, value, this.Carry());
private void AndR(byte value)
{
this.F = SetBit(this.F, StatusBits.AC, (this.A | value) & (int)Bits.Bit3);
this.F = ClearBit(this.F, StatusBits.CF);
this.F = AdjustSZP(this.F, this.A &= value);
SetBit(StatusBits.AC, (this.A | value) & (int)Bits.Bit3);
ClearBit(StatusBits.CF);
AdjustSZP(this.A &= value);
}
private void XorR(byte value)
{
this.F = ClearBit(this.F, StatusBits.AC | StatusBits.CF);
this.F = AdjustSZP(this.F, this.A ^= value);
ClearBit(StatusBits.AC | StatusBits.CF);
AdjustSZP(this.A ^= value);
}
private void OrR(byte value)
{
this.F = ClearBit(this.F, StatusBits.AC | StatusBits.CF);
this.F = AdjustSZP(this.F, this.A |= value);
ClearBit(StatusBits.AC | StatusBits.CF);
AdjustSZP(this.A |= value);
}
private void Compare(byte value) => this.Subtract(this.A, value);
@@ -673,28 +697,28 @@ namespace Intel8080
private byte RLC(byte operand)
{
var carry = operand & (byte)Bits.Bit7;
this.F = SetBit(this.F, StatusBits.CF, carry);
SetBit(StatusBits.CF, carry);
return (byte)((operand << 1) | (carry >> 7));
}
private byte RRC(byte operand)
{
var carry = operand & (byte)Bits.Bit0;
this.F = SetBit(this.F, StatusBits.CF, carry);
SetBit(StatusBits.CF, carry);
return (byte)((operand >> 1) | (carry << 7));
}
private byte RL(byte operand)
{
var carry = this.Carry();
this.F = SetBit(this.F, StatusBits.CF, operand & (byte)Bits.Bit7);
SetBit(StatusBits.CF, operand & (byte)Bits.Bit7);
return (byte)((operand << 1) | carry);
}
private byte RR(byte operand)
{
var carry = this.Carry();
this.F = SetBit(this.F, StatusBits.CF, operand & (byte)Bits.Bit0);
SetBit(StatusBits.CF, operand & (byte)Bits.Bit0);
return (byte)((operand >> 1) | (carry << 7));
}
@@ -714,15 +738,15 @@ namespace Intel8080
carry = true;
}
this.Add(addition);
this.F = SetBit(this.F, StatusBits.CF, carry);
this.A = this.Add(this.A, addition);
SetBit(StatusBits.CF, carry);
}
private void CMA() => this.A = (byte)~this.A;
private void STC() => this.F = SetBit(this.F, StatusBits.CF);
private void STC() => SetBit(StatusBits.CF);
private void CMC() => this.F = ClearBit(this.F, StatusBits.CF, this.Carry());
private void CMC() => ClearBit(StatusBits.CF, this.Carry());
private void XHTL(Register16 exchange)
{

View File

@@ -324,9 +324,9 @@ namespace LR35902
private static byte AdjustHalfCarrySub(byte input, byte before, byte value, int calculation) => SetBit(input, StatusBits.HC, CalculateHalfCarrySub(before, value, calculation));
private static byte Res(int n, byte operand) => ClearBit(operand, Bit(n));
private static byte RES(int n, byte operand) => ClearBit(operand, Bit(n));
private static byte Set(int n, byte operand) => SetBit(operand, Bit(n));
private static byte SET(int n, byte operand) => SetBit(operand, Bit(n));
protected override void DisableInterrupts() => this.IME = false;
@@ -336,23 +336,28 @@ namespace LR35902
private void Start() => this.Stopped = false;
protected override void MemoryWrite()
private void MemoryUpdate(int ticks)
{
this.LowerMWR();
this.LowerWR();
base.MemoryWrite();
this.TickMachine();
this.RaiseWR();
this.LowerWR();
base.MemoryWrite();
this.TickMachine(ticks);
this.RaiseWR();
this.RaiseMWR();
}
protected override void MemoryWrite()
{
this.MemoryUpdate(1);
}
protected override byte MemoryRead()
{
this.LowerMWR();
this.LowerRD();
_ = base.MemoryRead();
this.TickMachine();
this.RaiseRD();
this.LowerRD();
_ = base.MemoryRead();
this.TickMachine();
this.RaiseRD();
this.RaiseMWR();
return this.Bus.Data;
}
@@ -396,52 +401,53 @@ namespace LR35902
this.TickMachine();
}
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,
@@ -462,11 +468,12 @@ namespace LR35902
private void ExecuteCB(int x, int y, int z)
{
var operand = this.R(z);
var update = x != 1; // BIT does not update
switch (x)
{
case 0: // rot[y] r[z]
{
var operand = this.R(z);
operand = y switch
{
0 => this.RLC(operand),
@@ -479,30 +486,36 @@ namespace LR35902
7 => this.SRL(operand),
_ => throw new InvalidOperationException("Unreachable code block reached"),
};
this.R(z, operand);
this.AdjustZero(operand);
}
break;
case 1: // BIT y, r[z]
this.Bit(y, this.R(z));
this.Bit(y, operand);
break;
case 2: // RES y, r[z]
this.R(z, Res(y, this.R(z)));
operand = RES(y, operand);
break;
case 3: // SET y, r[z]
this.R(z, Set(y, this.R(z)));
operand = SET(y, operand);
break;
default:
throw new InvalidOperationException("Unreachable code block reached");
}
if (update)
{
this.R(z, operand);
}
}
private void ExecuteOther(int x, int y, int z, int p, int q)
{
var memoryY = y == 6;
var memoryZ = z == 6;
switch (x)
{
case 0:
@@ -544,7 +557,8 @@ namespace LR35902
break;
case 1: // ADD HL,rp
this.Add(this.HL, this.RP(p));
this.Add(this.RP(p));
this.TickMachine();
break;
default:
@@ -616,14 +630,18 @@ namespace LR35902
break;
case 3: // 16-bit INC/DEC
_ = q switch
switch (q)
{
// INC rp
0 => this.RP(p).Increment(),
// DEC rp
1 => this.RP(p).Decrement(),
_ => throw new InvalidOperationException("Invalid operation mode"),
};
case 0: // INC rp
this.RP(p).Increment();
break;
case 1: // DEC rp
this.RP(p).Decrement();
break;
default:
throw new InvalidOperationException("Invalid operation mode");
}
this.TickMachine();
break;
@@ -678,48 +696,51 @@ namespace LR35902
break;
case 1: // 8-bit loading
if (z == 6 && y == 6)
if (!(memoryZ && memoryY))
{
this.R(y, this.R(z));
}
else
{
this.LowerHALT(); // Exception (replaces LD (HL), (HL))
this.TickMachine(2);
}
else
{
this.R(y, this.R(z));
}
break;
case 2: // Operate on accumulator and register/memory location
switch (y)
{
case 0: // ADD A,r
this.A = this.Add(this.A, this.R(z));
break;
case 1: // ADC A,r
this.A = this.ADC(this.A, this.R(z));
break;
case 2: // SUB r
this.A = this.Subtract(this.A, this.R(z));
break;
case 3: // SBC A,r
this.A = this.SBC(this.A, this.R(z));
break;
case 4: // AND r
this.AndR(this.R(z));
break;
case 5: // XOR r
this.XorR(this.R(z));
break;
case 6: // OR r
this.OrR(this.R(z));
break;
case 7: // CP r
this.Compare(this.R(z));
break;
default:
throw new InvalidOperationException("Invalid operation mode");
case 2:
{ // Operate on accumulator and register/memory location
var value = this.R(z);
switch (y)
{
case 0: // ADD A,r
this.A = this.Add(this.A, value);
break;
case 1: // ADC A,r
this.A = this.ADC(this.A, value);
break;
case 2: // SUB r
this.A = this.Subtract(this.A, value);
break;
case 3: // SBC A,r
this.A = this.SBC(this.A, value);
break;
case 4: // AND r
this.AndR(value);
break;
case 5: // XOR r
this.XorR(value);
break;
case 6: // OR r
this.OrR(value);
break;
case 7: // CP r
this.Compare(value);
break;
default:
throw new InvalidOperationException("Invalid operation mode");
}
break;
}
break;
case 3:
switch (z)
{
@@ -886,38 +907,40 @@ 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.Bus.Data);
break;
case 1: // ADC A,n
this.A = this.ADC(this.A, this.Bus.Data);
break;
case 2: // SUB n
this.A = this.Subtract(this.A, this.Bus.Data);
break;
case 3: // SBC A,n
this.A = this.SBC(this.A, this.Bus.Data);
break;
case 4: // AND n
this.AndR(this.Bus.Data);
break;
case 5: // XOR n
this.XorR(this.Bus.Data);
break;
case 6: // OR n
this.OrR(this.Bus.Data);
break;
case 7: // CP n
this.Compare(this.Bus.Data);
break;
default:
throw new InvalidOperationException("Invalid operation mode");
case 6:
{ // Operate on accumulator and immediate operand: alu[y] n
var operand = this.FetchByte();
switch (y)
{
case 0: // ADD A,n
this.A = this.Add(this.A, operand);
break;
case 1: // ADC A,n
this.A = this.ADC(this.A, operand);
break;
case 2: // SUB n
this.A = this.Subtract(this.A, operand);
break;
case 3: // SBC A,n
this.A = this.SBC(this.A, operand);
break;
case 4: // AND n
this.AndR(operand);
break;
case 5: // XOR n
this.XorR(operand);
break;
case 6: // OR n
this.OrR(operand);
break;
case 7: // CP n
this.Compare(operand);
break;
default:
throw new InvalidOperationException("Invalid operation mode");
}
break;
}
break;
case 7: // Restart: RST y * 8
this.Restart((byte)(y << 3));
@@ -936,17 +959,19 @@ namespace LR35902
private byte Increment(byte operand)
{
this.ClearBit(StatusBits.NF);
this.AdjustZero(++operand);
this.ClearBit(StatusBits.HC, LowNibble(operand));
return operand;
var result = operand; ++result;
this.AdjustZero(result);
this.ClearBit(StatusBits.HC, LowNibble(result));
return result;
}
private byte Decrement(byte operand)
{
this.SetBit(StatusBits.NF);
this.ClearBit(StatusBits.HC, LowNibble(operand));
this.AdjustZero(--operand);
return operand;
var result = operand; --result;
this.AdjustZero(result);
return result;
}
protected sealed override bool ConvertCondition(int flag) => flag switch
@@ -958,49 +983,42 @@ namespace LR35902
_ => throw new ArgumentOutOfRangeException(nameof(flag)),
};
private void Add(Register16 operand, Register16 value)
private void Add(Register16 value)
{
this.TickMachine();
this.MEMPTR.Assign(operand);
var result = this.MEMPTR.Word + value.Word;
operand.Word = (ushort)result;
this.Intermediate.Assign(this.HL);
var result = this.HL.Word + value.Word;
this.HL.Word = (ushort)result;
this.ClearBit(StatusBits.NF);
this.SetBit(StatusBits.CF, result & (int)Bits.Bit16);
this.AdjustHalfCarryAdd(this.MEMPTR.High, value.High, operand.High);
this.AdjustHalfCarryAdd(this.Intermediate.High, value.High, this.HL.High);
}
private byte Add(byte operand, byte value, int carry = 0)
{
this.MEMPTR.Word = (ushort)(operand + value + carry);
this.Intermediate.Word = (ushort)(operand + value + carry);
var result = this.Intermediate.Low;
this.AdjustHalfCarryAdd(operand, value, this.MEMPTR.Low);
operand = this.MEMPTR.Low;
this.AdjustHalfCarryAdd(operand, value, result);
this.ClearBit(StatusBits.NF);
this.SetBit(StatusBits.CF, this.MEMPTR.Word & (ushort)Bits.Bit8);
this.AdjustZero(operand);
this.SetBit(StatusBits.CF, this.Intermediate.High & (byte)Bits.Bit0);
this.AdjustZero(result);
return operand;
return result;
}
private byte ADC(byte operand, byte value) => this.Add(operand, value, this.Carry() >> 4);
private byte Subtract(byte operand, byte value, int carry = 0)
{
this.MEMPTR.Word = (ushort)(operand - value - carry);
this.Intermediate.Word = (ushort)(operand - value - carry);
var result = this.Intermediate.Low;
this.AdjustHalfCarrySub(operand, value, this.MEMPTR.Low);
var result = operand = this.MEMPTR.Low;
this.AdjustHalfCarrySub(operand, value, result);
this.SetBit(StatusBits.NF);
this.SetBit(StatusBits.CF, this.MEMPTR.High & (byte)Bits.Bit0);
this.AdjustZero(operand);
this.SetBit(StatusBits.CF, this.Intermediate.High & (byte)Bits.Bit0);
this.AdjustZero(result);
return result;
}

View File

@@ -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)
{
@@ -1480,7 +1480,8 @@ namespace Z80
this.WritePort(this.FetchByte());
break;
case 3: // IN A,(n)
this.A = this.ReadPort(this.FetchByte());
this.ReadPort(this.FetchByte());
this.A = this.Bus.Data;
break;
case 4: // EX (SP),HL
this.XHTL(this.HL2());
@@ -2138,7 +2139,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);
@@ -2293,6 +2294,12 @@ namespace Z80
#region Input/output port control
private void WritePort(Register16 port, byte data)
{
this.Bus.Data = data;
this.WritePort(port);
}
private void WritePort(byte port)
{
this.Bus.Address.Assign(port, this.Bus.Data = this.A);
@@ -2300,12 +2307,6 @@ namespace Z80
++this.MEMPTR.Low;
}
private void WritePort(Register16 port, byte data)
{
this.Bus.Data = data;
this.WritePort(port);
}
private void WritePort(Register16 port)
{
this.Bus.Address.Assign(port);
@@ -2315,8 +2316,7 @@ namespace Z80
private void WritePort()
{
this.MEMPTR.Assign(this.Bus.Address);
this.Tick();
this.Tick();
this.Tick(2);
this.LowerIORQ();
this.LowerWR();
this.Tick();
@@ -2326,21 +2326,20 @@ namespace Z80
this.Tick();
}
private byte ReadPort(byte port)
{
this.Bus.Address.Assign(port, this.Bus.Data = this.A);
_ = this.ReadPort();
this.MEMPTR.Increment();
return this.Bus.Data;
}
private byte ReadPort(Register16 port)
private void ReadPort(Register16 port)
{
this.Bus.Address.Assign(port);
return this.ReadPort();
this.ReadPort();
}
private byte ReadPort()
private void ReadPort(byte port)
{
this.Bus.Address.Assign(port, this.Bus.Data = this.A);
this.ReadPort();
this.MEMPTR.Increment();
}
private void ReadPort()
{
this.MEMPTR.Assign(this.Bus.Address);
this.Tick(2);
@@ -2351,7 +2350,6 @@ namespace Z80
this.RaiseRD();
this.RaiseIORQ();
this.Tick();
return this.Bus.Data;
}
#endregion