StoicGoose.Unity/Assets/Plugins/StoicGooseUnity/StoicGoose.Core/CPU/V30MZ.Implementations.cs

528 lines
16 KiB
C#

namespace StoicGoose.Core.CPU
{
public sealed partial class V30MZ
{
private byte Add8(bool withCarry, byte a, byte b)
{
int result = a + b + (withCarry && IsFlagSet(Flags.Carry) ? 1 : 0);
// CF, PF, AF, ZF, SF, OF = according to result
SetClearFlagConditional(Flags.Carry, (result & 0x100) != 0);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((a ^ b ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ a) & (result ^ b) & 0x80) != 0);
return (byte)result;
}
private ushort Add16(bool withCarry, ushort a, ushort b)
{
int result = a + b + (withCarry && IsFlagSet(Flags.Carry) ? 1 : 0);
// CF, PF, AF, ZF, SF, OF = according to result
SetClearFlagConditional(Flags.Carry, (result & 0x10000) != 0);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((a ^ b ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ a) & (result ^ b) & 0x8000) != 0);
return (ushort)result;
}
private byte Or8(byte a, byte b)
{
int result = a | b;
// CF, OF = cleared; PF, ZF, SF = according to result; AF = undefined
ClearFlags(Flags.Carry);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
ClearFlags(Flags.Overflow);
return (byte)result;
}
private ushort Or16(ushort a, ushort b)
{
int result = a | b;
// CF, OF = cleared; PF, ZF, SF = according to result; AF = undefined
ClearFlags(Flags.Carry);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
ClearFlags(Flags.Overflow);
return (ushort)result;
}
private byte Sub8(bool withBorrow, byte a, byte b)
{
int result = a - (b + (withBorrow && IsFlagSet(Flags.Carry) ? 1 : 0));
// CF, PF, AF, ZF, SF, OF = according to result
SetClearFlagConditional(Flags.Carry, (result & 0x100) != 0);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((a ^ b ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ a) & (a ^ b) & 0x80) != 0);
return (byte)result;
}
private ushort Sub16(bool withBorrow, ushort a, ushort b)
{
int result = a - (b + (withBorrow && IsFlagSet(Flags.Carry) ? 1 : 0));
// CF, PF, AF, ZF, SF, OF = according to result
SetClearFlagConditional(Flags.Carry, (result & 0x10000) != 0);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((a ^ b ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ a) & (a ^ b) & 0x8000) != 0);
return (ushort)result;
}
private byte And8(byte a, byte b)
{
int result = a & b;
// CF, OF = cleared; PF, ZF, SF = according to result; AF = undefined
ClearFlags(Flags.Carry);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
ClearFlags(Flags.Overflow);
return (byte)result;
}
private ushort And16(ushort a, ushort b)
{
int result = a & b;
// CF, OF = cleared; PF, ZF, SF = according to result; AF = undefined
ClearFlags(Flags.Carry);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
ClearFlags(Flags.Overflow);
return (ushort)result;
}
private void Daa(bool isSubtract)
{
byte oldAl = ax.Low;
if (((oldAl & 0x0F) > 0x09) || IsFlagSet(Flags.Auxiliary))
{
ax.Low += (byte)(isSubtract ? -0x06 : 0x06);
SetFlags(Flags.Auxiliary);
}
else
ClearFlags(Flags.Auxiliary);
if ((oldAl > 0x99) || IsFlagSet(Flags.Carry))
{
ax.Low += (byte)(isSubtract ? -0x60 : 0x60);
SetFlags(Flags.Carry);
}
else
ClearFlags(Flags.Carry);
SetClearFlagConditional(Flags.Parity, CalculateParity(ax.Low & 0xFF));
SetClearFlagConditional(Flags.Zero, (ax.Low & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (ax.Low & 0x80) != 0);
}
private byte Xor8(byte a, byte b)
{
int result = a ^ b;
// CF, OF = cleared; PF, ZF, SF = according to result; AF = undefined
ClearFlags(Flags.Carry);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
ClearFlags(Flags.Overflow);
return (byte)result;
}
private ushort Xor16(ushort a, ushort b)
{
int result = a ^ b;
// CF, OF = cleared; PF, ZF, SF = according to result; AF = undefined
ClearFlags(Flags.Carry);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
ClearFlags(Flags.Overflow);
return (ushort)result;
}
private void Aaa(bool isSubtract)
{
if (((ax.Low & 0x0F) > 0x09) || IsFlagSet(Flags.Auxiliary))
{
ax.Low = (byte)(ax.Low + (isSubtract ? -0x06 : 0x06));
ax.High = (byte)(ax.High + (isSubtract ? -0x01 : 0x01));
SetFlags(Flags.Auxiliary);
SetFlags(Flags.Carry);
}
else
{
ClearFlags(Flags.Auxiliary);
ClearFlags(Flags.Carry);
}
ax.Low &= 0x0F;
}
private byte Inc8(byte a)
{
int result = a + 1;
// PF, AF, ZF, SF, OF = according to result, CF = undefined
//Carry
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((a ^ 1 ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ a) & (result ^ 1) & 0x80) != 0);
return (byte)result;
}
private ushort Inc16(ushort a)
{
int result = a + 1;
// PF, AF, ZF, SF, OF = according to result, CF = undefined
//Carry
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((a ^ 1 ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ a) & (result ^ 1) & 0x8000) != 0);
return (ushort)result;
}
private byte Dec8(byte a)
{
int result = a - 1;
// PF, AF, ZF, SF, OF = according to result, CF = undefined
//Carry
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((a ^ 1 ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ a) & (a ^ 1) & 0x80) != 0);
return (byte)result;
}
private ushort Dec16(ushort a)
{
int result = a - 1;
// PF, AF, ZF, SF, OF = according to result, CF = undefined
//Carry
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((a ^ 1 ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ a) & (a ^ 1) & 0x8000) != 0);
return (ushort)result;
}
private byte Rol8(bool withCarry, byte a, byte b)
{
int result;
if (withCarry)
{
result = a;
for (var n = 0; n < b; n++)
{
var carry = result & 0x80;
result = (result << 1) | (IsFlagSet(Flags.Carry) ? 0x01 : 0);
SetClearFlagConditional(Flags.Carry, carry != 0);
}
SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x80) != 0);
result &= 0xFF;
}
else
{
result = (a << b) | (a >> (8 - b));
SetClearFlagConditional(Flags.Carry, ((a << b) & (1 << 8)) != 0);
SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x80) != 0);
result &= 0xFF;
}
return (byte)result;
}
private ushort Rol16(bool withCarry, ushort a, ushort b)
{
int result;
if (withCarry)
{
result = a;
for (var n = 0; n < b; n++)
{
var carry = result & 0x80;
result = (result << 1) | (IsFlagSet(Flags.Carry) ? 0x0001 : 0);
SetClearFlagConditional(Flags.Carry, carry != 0);
}
SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x8000) != 0);
result &= 0xFFFF;
}
else
{
result = (a << b) | (a >> (16 - b));
SetClearFlagConditional(Flags.Carry, ((a << b) & (1 << 16)) != 0);
SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x8000) != 0);
result &= 0xFFFF;
}
return (ushort)result;
}
private byte Ror8(bool withCarry, byte a, byte b)
{
int result;
if (withCarry)
{
result = a;
for (var n = 0; n < b; n++)
{
var carry = result & 0x01;
result = (IsFlagSet(Flags.Carry) ? 0x80 : 0) | (result >> 1);
SetClearFlagConditional(Flags.Carry, carry != 0);
}
SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x80) != 0);
result &= 0xFF;
}
else
{
result = (a >> b) | (a << (8 - b));
SetClearFlagConditional(Flags.Carry, ((a >> (b - 1)) & 0x01) != 0);
SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x80) != 0);
result &= 0xFF;
}
return (byte)result;
}
private ushort Ror16(bool withCarry, ushort a, ushort b)
{
int result;
if (withCarry)
{
result = a;
for (var n = 0; n < b; n++)
{
var carry = result & 0x01;
result = (IsFlagSet(Flags.Carry) ? 0x8000 : 0) | (result >> 1);
SetClearFlagConditional(Flags.Carry, carry != 0);
}
SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x8000) != 0);
result &= 0xFFFF;
}
else
{
result = (a >> b) | (a << (16 - b));
SetClearFlagConditional(Flags.Carry, ((a >> (b - 1)) & 0x01) != 0);
SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x8000) != 0);
result &= 0xFFFF;
}
return (ushort)result;
}
private byte Shl8(byte a, byte b)
{
int result = (a << b) & 0xFF;
if (b != 0)
{
SetClearFlagConditional(Flags.Carry, ((a << b) & (1 << 8)) != 0);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
if (b == 1) SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x80) != 0);
}
return (byte)result;
}
private ushort Shl16(ushort a, ushort b)
{
int result = (a << b) & 0xFFFF;
if (b != 0)
{
SetClearFlagConditional(Flags.Carry, ((a << b) & (1 << 16)) != 0);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
if (b == 1) SetClearFlagConditional(Flags.Overflow, ((a ^ result) & 0x8000) != 0);
}
return (ushort)result;
}
private byte Shr8(bool signed, byte a, byte b)
{
if (signed && (b & 16) != 0)
{
SetClearFlagConditional(Flags.Carry, (a & 0x80) != 0);
return (byte)(0 - (IsFlagSet(Flags.Carry) ? 1 : 0));
}
int result = (a >> b) & 0xFF;
SetClearFlagConditional(Flags.Carry, ((a >> (b - 1)) & (1 << 0)) != 0);
if (signed && (a & 0x80) != 0) result |= 0xFF << (8 - b);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
SetClearFlagConditional(Flags.Overflow, !signed && ((a ^ result) & 0x80) != 0);
return (byte)result;
}
private ushort Shr16(bool signed, ushort a, ushort b)
{
if (signed && (b & 16) != 0)
{
SetClearFlagConditional(Flags.Carry, (a & 0x8000) != 0);
return (ushort)(0 - (IsFlagSet(Flags.Carry) ? 1 : 0));
}
int result = (a >> b) & 0xFFFF;
SetClearFlagConditional(Flags.Carry, ((a >> (b - 1)) & (1 << 0)) != 0);
if (signed && (a & 0x8000) != 0) result |= 0xFFFF << (16 - b);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
//Aux
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
SetClearFlagConditional(Flags.Overflow, !signed && ((a ^ result) & 0x8000) != 0);
return (ushort)result;
}
private byte Neg8(byte b)
{
int result = -b & 0xFF;
// CF = is operand non-zero?; PF, AF, ZF, SF, OF = according to result
SetClearFlagConditional(Flags.Carry, b != 0);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((0 ^ b ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x80) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ 0) & (0 ^ b) & 0x80) != 0);
return (byte)result;
}
private ushort Neg16(ushort b)
{
int result = -b & 0xFFFF;
// CF = is operand non-zero?; PF, AF, ZF, SF, OF = according to result
SetClearFlagConditional(Flags.Carry, b != 0);
SetClearFlagConditional(Flags.Parity, CalculateParity(result & 0xFF));
SetClearFlagConditional(Flags.Auxiliary, ((0 ^ b ^ result) & 0x10) != 0);
SetClearFlagConditional(Flags.Zero, (result & 0xFFFF) == 0);
SetClearFlagConditional(Flags.Sign, (result & 0x8000) != 0);
SetClearFlagConditional(Flags.Overflow, ((result ^ 0) & (0 ^ b) & 0x8000) != 0);
return (ushort)result;
}
private ushort Mul8(bool signed, byte a, byte b)
{
uint result = (uint)(signed ? ((sbyte)a * (sbyte)b) : (a * b));
// CF, OF = is upper half of result non-zero?; PF, AF, ZF, SF = undefined
SetClearFlagConditional(Flags.Overflow, (result >> 8) != 0);
SetClearFlagConditional(Flags.Carry, (result >> 8) != 0);
return (ushort)result;
}
private uint Mul16(bool signed, ushort a, ushort b)
{
uint result = (uint)(signed ? ((short)a * (short)b) : (a * b));
// CF, OF = is upper half of result non-zero?; PF, AF, ZF, SF = undefined
SetClearFlagConditional(Flags.Overflow, (result >> 16) != 0);
SetClearFlagConditional(Flags.Carry, (result >> 16) != 0);
return (uint)result;
}
private ushort Div8(bool signed, ushort a, byte b)
{
if (b == 0)
{
Interrupt(0);
return a;
}
int quotient = signed ? ((short)a / (sbyte)b) : (a / b);
int remainder = signed ? ((short)a % (sbyte)b) : (a % b);
// CF, PF, AF, ZF, SF, OF = undefined
return (ushort)(((remainder & 0xFF) << 8) | (quotient & 0xFF));
}
private uint Div16(bool signed, uint a, ushort b)
{
if (b == 0)
{
Interrupt(0);
return a;
}
int quotient = signed ? ((int)a / (short)b) : (int)(a / b);
int remainder = signed ? ((int)a % (short)b) : (int)(a % b);
// CF, PF, AF, ZF, SF, OF = undefined
return (uint)(((remainder & 0xFFFF) << 16) | (quotient & 0xFFFF));
}
}
}