BizHawk/BizHawk.Emulation.Cores/CPUs/HuC6280/CDL.cs

156 lines
3.8 KiB
C#
Raw Normal View History

2014-02-09 23:13:11 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Cores.Components.H6280
{
public partial class HuC6280
{
public struct MemMapping
{
public string Name;
public int Offs;
}
public MemMapping[] Mappings; // = new MemMapping[256];
public Dictionary<string, byte[]> CodeDataLog = new Dictionary<string, byte[]>();
/// <summary>
/// create a new empty CodeDataLog to match the Mappings
/// </summary>
public void InitCDL()
{
Dictionary<string, int> sizes = new Dictionary<string, int>();
foreach (var m in Mappings)
{
if (!sizes.ContainsKey(m.Name) || m.Offs >= sizes[m.Name])
sizes[m.Name] = m.Offs;
}
CodeDataLog.Clear();
foreach (var kvp in sizes)
{
// becase we were looking at offsets, and each bank is 8192 big, we need to add that size
CodeDataLog[kvp.Key] = new byte[kvp.Value + 8192];
}
}
[Flags]
enum CDLUsage : byte
{
// was fetched as an opcode
Code = 0x01,
// was read or written as data
Data = 0x02,
// was read and used as a pointer to data via indirect addressing
DataPtr = 0x04,
// was read or written as stack
Stack = 0x08,
// was read or written as data via indirect addressing
IndirectData = 0x10,
// was read and used as function pointer
// NB: there is no "IndirectCode"; all code is marked simply as code regardless of how it is reached
FcnPtr = 0x20,
// was used as a source (either initial or during the loop) of a block xfer
BlockFrom = 0x40,
// was used as a destination (either initial or during the loop) of a block xfer
BlockTo = 0x80
}
void Mark(ushort addr, CDLUsage flag)
{
var m = Mappings[MPR[addr >> 13]];
CodeDataLog[m.Name][addr & 0x1fff | m.Offs] |= (byte)flag;
}
// mark addr as having been fetched for execute
void MarkCode(int addr_)
{
ushort addr = (ushort)addr_;
Mark(addr, CDLUsage.Code);
}
// mark addr as having been seen as data
void MarkAddr(int addr_)
{
ushort addr = (ushort)addr_;
Mark(addr, CDLUsage.Data);
}
// convert address to zero-page, then mark as data
void MarkZP(int addr_)
{
ushort addr = (ushort)(addr_ & 0xff | 0x2000);
Mark(addr, CDLUsage.Data);
}
// convert address to zero-page, then return the pointer stored there
ushort GetIndirect(int addr_)
{
ushort addr = (ushort)(addr_ & 0xff | 0x2000);
return ReadWordPageWrap(addr);
}
// convert address to zero-page, then mark as pointer (two bytes)
void MarkZPPtr(int addr_)
{
ushort addr = (ushort)(addr_ & 0xff | 0x2000);
ushort addr2 = (ushort)(addr & 0xff00 | (addr + 1) & 0x00ff);
Mark(addr, CDLUsage.DataPtr);
Mark(addr2, CDLUsage.DataPtr);
}
// mark address as destination data of an indirect pointer
void MarkIndirect(int addr_)
{
ushort addr = (ushort)addr_;
Mark(addr, CDLUsage.IndirectData);
}
// mark stack space
void MarkPush(int n)
{
for (int i = 0; i < n; i++)
{
ushort addr = (ushort)(S - i);
Mark(addr, CDLUsage.Stack);
}
}
void MarkPop(int n)
{
for (int i = 0; i < n; i++)
{
ushort addr = (ushort)(S + i + 1);
Mark(addr, CDLUsage.Stack);
}
}
// mark addr as function pointer (2 bytes)
void MarkFptr(int addr_)
{
ushort addr = (ushort)addr_;
ushort addr2 = (ushort)(addr & 0xff00 | (addr + 1) & 0x00ff);
Mark(addr, CDLUsage.FcnPtr);
Mark(addr2, CDLUsage.FcnPtr);
}
// block transfer "from"
void MarkBTFrom(int addr_)
{
ushort addr = (ushort)addr_;
Mark(addr, CDLUsage.BlockFrom);
}
// block transfer "to"
void MarkBTTo(int addr_)
{
ushort addr = (ushort)addr_;
Mark(addr, CDLUsage.BlockTo);
}
}
}