BizHawk/BizHawk.Emulation.Cores/Consoles/Fairchild/ChannelF/F8/F3850.Operations.cs

300 lines
6.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BizHawk.Common.NumberExtensions;
namespace BizHawk.Emulation.Cores.Consoles.ChannelF
{
/// <summary>
/// ALU Operations
/// </summary>
public sealed partial class F3850
{
public void Read_Func(byte dest, byte src_l, byte src_h)
{
Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8));
}
public void Write_Func(byte dest_l, byte dest_h, byte src)
{
WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), Regs[src]);
}
public void IN_Func(byte dest, byte src)
{
Regs[dest] = ReadHardware(Regs[src]);
}
public void LR_A_IO_Func(byte dest, byte src)
{
// helper method that simulates transferring DB to accumulator (as part of an IN operation)
// this sets flags accordingly
// dest should always == A and src should always == DB for this function
// overflow and carry unconditionally reset
FlagO = false;
FlagC = false;
Regs[dest] = Regs[src];
FlagZ = Regs[dest] == 0;
// Sign SET if MSB == 0 (positive signed number)
FlagS = Regs[dest].Bit(7) == false;
// ICB flag not affected
}
public void ClearFlags_Func()
{
FlagC = false;
FlagO = false;
FlagS = false;
FlagZ = false;
}
public void LR_Func(byte dest, byte src)
{
if (dest == DB)
{
// byte storage
Regs[dest] = (byte)(Regs[src] & 0xFF);
}
else if (dest == W)
{
// mask for status register
Regs[dest] = (byte)(Regs[src] & 0x1F);
}
else if (dest == ISAR)
{
// mask for ISAR register
Regs[dest] = (byte)(Regs[src] & 0x3F);
}
else
{
Regs[dest] = Regs[src];
}
}
/// <summary>
/// Right shift 'src' 'shift' positions (zero fill)
/// </summary>
/// <param name="src"></param>
/// <param name="shift"></param>
public void SR_Func(byte src, byte shift)
{
// overflow and carry unconditionally reset
FlagO = false;
FlagC = false;
Regs[src] = (byte)((Regs[src] >> shift) & 0xFF);
FlagZ = Regs[src] == 0;
// Sign SET if MSB == 0 (positive signed number)
FlagS = Regs[src].Bit(7) == false;
// ICB flag not affected
}
/// <summary>
/// Left shit 'src' 'shift' positions (zero fill)
/// </summary>
/// <param name="src"></param>
/// <param name="shift"></param>
public void SL_Func(byte src, byte shift)
{
// overflow and carry unconditionally reset
FlagO = false;
FlagC = false;
Regs[src] = (byte)((Regs[src] << shift) & 0xFF);
FlagZ = Regs[src] == 0;
// Sign SET if MSB == 0 (positive signed number)
FlagS = Regs[src].Bit(7) == false;
// ICB flag not affected
}
public void ADD_Func_(byte dest, byte src)
{
// addition of 2 signed bytes
ushort dest16 = Regs[dest];
dest16 += Regs[src];
FlagC = dest16.Bit(8);
FlagZ = (dest16 & 0xFF) == 0;
ushort ans = (ushort)(dest16 & 0xFF);
// Sign SET if MSB == 0 (positive signed number)
FlagS = ans.Bit(7) == false;
// overflow based on carry out of bit6 XOR carry out of bit7
var b6c = dest16 >> 7;
var b7c = dest16 >> 8;
FlagO = (b6c ^ b7c) != 0;
Regs[dest] = (byte)ans;
}
public void ADD_Func(byte dest, byte src)
{
// addition of 2 signed bytes
var sD = Regs[dest] & 0x80;
var sS = Regs[src] & 0x80;
var res = Regs[dest] + Regs[src];
var sR = res & 0x80;
FlagS = !((res & 0x80) > 0);
FlagZ = (res & 0xff) == 0;
FlagO = (sD == sS && sD != sR);
FlagC = (res & 0x100) > 0;
Regs[dest] = (byte) (res & 0xff);
}
public void SUB_Func(byte dest, byte src)
{
Regs[ALU0] = (byte)((Regs[src] ^ 0xff) + 1);
ADD_Func(dest, ALU0);
}
public void ADDD_Func(byte dest, byte src)
{
var d = Regs[dest];
var s = Regs[src];
var bcdRes = d + s;
var carryIntermediate = ((d & 0x0F) + (s & 0x0F)) > 0x0F;
var carryUpper = bcdRes >= 0x100;
// temporary storage and set flags
Regs[ALU0] = Regs[dest];
Regs[ALU1] = Regs[src];
ADD_Func(ALU0, ALU1);
if (!carryIntermediate)
{
bcdRes = (bcdRes & 0xF0) | ((bcdRes + 0x0A) & 0x0F);
}
if (!carryUpper)
{
bcdRes = (bcdRes + 0xA0);
}
Regs[dest] = (byte)(bcdRes & 0xFF);
}
public void CI_Func()
{
// compare immediate
// we need to achieve DB - A + 1
// flags set - results not stored
var comp = ((Regs[A] ^ 0xFF) + 1);
Regs[ALU0] = (byte)comp;
Regs[ALU1] = Regs[DB];
ADD_Func(ALU1, ALU0);
}
/*
public void ADDD_Func_(ushort dest, ushort src)
{
// from MAME f8.cpp (BSD-3)
// https://github.com/mamedev/mame/blob/97b67170277437131adf6ed4d60139c172529e4f/src/devices/cpu/f8/f8.cpp#L264
byte d = (byte)Regs[dest];
byte s = (byte)Regs[src];
byte tmp = (byte)(d + s);
byte c = 0; // high order carry
byte ic = 0; // low order carry
if (((d + s) & 0xFF0) > 0xF0)
{
c = 1;
}
if ((d & 0x0F) + (s & 0x0F) > 0x0F)
{
ic = 1;
}
//ALU_ClearFlags();
ALU_ADD8_FLAGSONLY_Func(dest, src);
Regs[ALU0] = tmp;
//ALU_SetFlags_SZ(ALU0);
if (c == 0 && ic == 0)
{
tmp = (byte)(((tmp + 0xa0) & 0xf0) + ((tmp + 0x0a) & 0x0f));
}
if (c == 0 && ic == 1)
{
tmp = (byte)(((tmp + 0xa0) & 0xf0) + (tmp & 0x0f));
}
if (c == 1 && ic == 0)
{
tmp = (byte)((tmp & 0xf0) + ((tmp + 0x0a) & 0x0f));
}
Regs[dest] = tmp;
}
*/
public void AND_Func(byte dest, byte src)
{
// overflow and carry unconditionally reset
FlagO = false;
FlagC = false;
Regs[dest] = (byte)(Regs[dest] & Regs[src]);
FlagZ = Regs[src] == 0;
// Sign SET if MSB == 0 (positive signed number)
FlagS = Regs[src].Bit(7) == false;
// ICB flag not affected
}
public void OR_Func(byte dest, byte src)
{
// overflow and carry unconditionally reset
FlagO = false;
FlagC = false;
Regs[dest] = (byte)(Regs[dest] | Regs[src]);
FlagZ = Regs[src] == 0;
// Sign SET if MSB == 0 (positive signed number)
FlagS = Regs[src].Bit(7) == false;
// ICB flag not affected
}
public void XOR_Func(byte dest, byte src)
{
// overflow and carry unconditionally reset
FlagO = false;
FlagC = false;
Regs[dest] = (byte)(Regs[dest] ^ Regs[src]);
FlagZ = Regs[src] == 0;
// Sign SET if MSB == 0 (positive signed number)
FlagS = Regs[src].Bit(7) == false;
// ICB flag not affected
}
}
}