get rid of CpuCoreGenerator as it hasn't been used in a long time, the 6502 is commented out and isn't even the class used anymore, and the HuC6280 is very out of date, we don't do it this way anymore

This commit is contained in:
adelikat 2020-02-08 11:58:00 -06:00
parent 9d4ef3a3af
commit f5c5061681
9 changed files with 0 additions and 3077 deletions

View File

@ -1,20 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CpuCoreGenerator", "CpuCoreGenerator\CpuCoreGenerator.csproj", "{ED25C59A-0A09-49ED-8CC1-9363576A83A7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{ED25C59A-0A09-49ED-8CC1-9363576A83A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED25C59A-0A09-49ED-8CC1-9363576A83A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED25C59A-0A09-49ED-8CC1-9363576A83A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED25C59A-0A09-49ED-8CC1-9363576A83A7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,93 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{ED25C59A-0A09-49ED-8CC1-9363576A83A7}</ProjectGuid>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<OutputType>Exe</OutputType>
<NoStandardLibraries>false</NoStandardLibraries>
<AssemblyName>CpuCoreGenerator</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<RootNamespace>CpuCoreGenerator</RootNamespace>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<TargetFrameworkProfile />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="HuC6280\CDL.cs" />
<Compile Include="HuC6280\CoreGenerator.cs" />
<Compile Include="HuC6280\Instructions.cs" />
<Compile Include="MOS 6502\CoreGenerator.cs" />
<Compile Include="MOS 6502\Instructions.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
<ProjectExtensions>
<VisualStudio AllowExistingFolder="true" />
</ProjectExtensions>
</Project>

View File

@ -1,177 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace HuC6280
{
public partial class CoreGenerator
{
public void GenerateCDL(string file)
{
using (TextWriter w = new StreamWriter(file))
{
w.WriteLine("using System;");
w.WriteLine();
w.WriteLine("// Do not modify this file directly! This is GENERATED code.");
w.WriteLine("// Please open the CpuCoreGenerator solution and make your modifications there.");
w.WriteLine();
w.WriteLine("namespace BizHawk.Emulation.Cores.Components.H6280");
w.WriteLine("{");
w.WriteLine("\tpublic partial class HuC6280");
w.WriteLine("\t{");
w.WriteLine("\t\tvoid CDLOpcode()");
w.WriteLine("\t\t{");
w.WriteLine("\t\t\tbyte tmp8;");
w.WriteLine("\t\t\tbyte opcode = ReadMemory(PC);");
w.WriteLine("\t\t\tswitch (opcode)");
w.WriteLine("\t\t\t{");
for (int i = 0; i < 256; i++)
CDLOpcode(w, i);
w.WriteLine("\t\t\t}");
w.WriteLine("\t\t}");
w.WriteLine("\t}");
w.WriteLine("}");
}
}
void CDLOpcode(TextWriter w, int opcode)
{
// todo: T Flag
var op = Opcodes[opcode];
if (op == null)
{
// nop
w.WriteLine("\t\t\t\tcase 0x{0:X2}: // {1}", opcode, "??");
w.WriteLine("\t\t\t\t\tMarkCode(PC, 1);");
w.WriteLine("\t\t\t\t\tbreak;");
return;
}
w.WriteLine("\t\t\t\tcase 0x{0:X2}: // {1}", opcode, op);
w.WriteLine("\t\t\t\t\tMarkCode(PC, {0});", op.Size);
switch (op.AddressMode)
{
case AddrMode.Implicit:
switch (op.Instruction)
{
case "PHA": // push
case "PHP":
case "PHX":
case "PHY":
w.WriteLine("\t\t\t\t\tMarkPush(1);");
break;
case "PLA": // pop
case "PLP":
case "PLX":
case "PLY":
w.WriteLine("\t\t\t\t\tMarkPop(1);");
break;
case "RTI":
w.WriteLine("\t\t\t\t\tMarkPop(3);");
break;
case "RTS":
w.WriteLine("\t\t\t\t\tMarkPop(2);");
break;
}
break;
case AddrMode.Accumulator:
break;
case AddrMode.Immediate:
break;
case AddrMode.ZeroPage:
w.WriteLine("\t\t\t\t\tMarkZP(ReadMemory((ushort)(PC + 1)));");
break;
case AddrMode.ZeroPageX:
w.WriteLine("\t\t\t\t\tMarkZP(ReadMemory((ushort)(PC + 1)) + X);");
break;
case AddrMode.ZeroPageY:
w.WriteLine("\t\t\t\t\tMarkZP(ReadMemory((ushort)(PC + 1)) + Y);");
break;
case AddrMode.ZeroPageR:
w.WriteLine("\t\t\t\t\tMarkZP(ReadMemory((ushort)(PC + 1)));");
break;
case AddrMode.Absolute:
w.WriteLine("\t\t\t\t\tMarkAddr(ReadWord((ushort)(PC + 1)));");
break;
case AddrMode.AbsoluteX:
w.WriteLine("\t\t\t\t\tMarkAddr(ReadWord((ushort)(PC + 1)) + X);");
break;
case AddrMode.AbsoluteY:
w.WriteLine("\t\t\t\t\tMarkAddr(ReadWord((ushort)(PC + 1)) + Y);");
break;
case AddrMode.Indirect:
w.WriteLine("\t\t\t\t\ttmp8 = ReadMemory((ushort)(PC + 1));");
w.WriteLine("\t\t\t\t\tMarkZPPtr(tmp8);");
w.WriteLine("\t\t\t\t\tMarkIndirect(GetIndirect(tmp8));");
break;
case AddrMode.IndirectX:
w.WriteLine("\t\t\t\t\ttmp8 = (byte)(ReadMemory((ushort)(PC + 1)) + X);");
w.WriteLine("\t\t\t\t\tMarkZPPtr(tmp8);");
w.WriteLine("\t\t\t\t\tMarkIndirect(GetIndirect(tmp8));");
break;
case AddrMode.IndirectY:
w.WriteLine("\t\t\t\t\ttmp8 = ReadMemory((ushort)(PC + 1));");
w.WriteLine("\t\t\t\t\tMarkZPPtr(tmp8);");
w.WriteLine("\t\t\t\t\tMarkIndirect(GetIndirect(tmp8) + Y);");
break;
case AddrMode.Relative:
break;
case AddrMode.BlockMove:
w.WriteLine("\t\t\t\t\tif (!InBlockTransfer)");
w.WriteLine("\t\t\t\t\t{");
w.WriteLine("\t\t\t\t\t\tMarkBTFrom(ReadWord((ushort)(PC + 1)));");
w.WriteLine("\t\t\t\t\t\tMarkBTTo(ReadWord((ushort)(PC + 3)));");
w.WriteLine("\t\t\t\t\t}");
w.WriteLine("\t\t\t\t\telse");
w.WriteLine("\t\t\t\t\t{");
switch (op.Instruction)
{
case "TII":
case "TDD":
case "TIN":
w.WriteLine("\t\t\t\t\t\tMarkBTFrom(btFrom);");
w.WriteLine("\t\t\t\t\t\tMarkBTTo(btTo);");
break;
case "TIA":
w.WriteLine("\t\t\t\t\t\tMarkBTFrom(btFrom);");
w.WriteLine("\t\t\t\t\t\tMarkBTTo(btTo+btAlternator);");
break;
case "TAI":
w.WriteLine("\t\t\t\t\t\tMarkBTFrom(btFrom+btAlternator);");
w.WriteLine("\t\t\t\t\t\tMarkBTTo(btTo);");
break;
}
w.WriteLine("\t\t\t\t\t\t}");
break;
case AddrMode.ImmZeroPage:
w.WriteLine("\t\t\t\t\tMarkZP(ReadMemory((ushort)(PC + 2)));");
break;
case AddrMode.ImmZeroPageX:
w.WriteLine("\t\t\t\t\tMarkZP(ReadMemory((ushort)(PC + 2)) + X);");
break;
case AddrMode.ImmAbsolute:
w.WriteLine("\t\t\t\t\tMarkAddr(ReadWord((ushort)(PC + 2)));");
break;
case AddrMode.ImmAbsoluteX:
w.WriteLine("\t\t\t\t\tMarkAddr(ReadWord((ushort)(PC + 2)) + X);");
break;
case AddrMode.AbsoluteIndirect:
w.WriteLine("\t\t\t\t\tMarkFptr(ReadWord((ushort)(PC + 1)));");
break;
case AddrMode.AbsoluteIndirectX:
w.WriteLine("\t\t\t\t\tMarkFptr(ReadWord((ushort)(PC + 1)) + X);");
break;
}
w.WriteLine("\t\t\t\t\tbreak;");
}
}
}

View File

@ -1,839 +0,0 @@
using System;
using System.IO;
namespace HuC6280
{
public enum AddrMode
{
Implicit,
Accumulator,
Immediate,
ZeroPage,
ZeroPageX,
ZeroPageY,
ZeroPageR,
Absolute,
AbsoluteX,
AbsoluteY,
AbsoluteIndirect,
AbsoluteIndirectX,
Indirect,
IndirectX,
IndirectY,
Relative,
BlockMove,
ImmZeroPage,
ImmZeroPageX,
ImmAbsolute,
ImmAbsoluteX
}
public class OpcodeInfo
{
public string Instruction;
public AddrMode AddressMode;
public int Cycles;
public int Size
{
get
{
switch (AddressMode)
{
case AddrMode.Implicit: return 1;
case AddrMode.Accumulator: return 1;
case AddrMode.Immediate: return 2;
case AddrMode.ZeroPage: return 2;
case AddrMode.ZeroPageX: return 2;
case AddrMode.ZeroPageY: return 2;
case AddrMode.ZeroPageR: return 3;
case AddrMode.Absolute: return 3;
case AddrMode.AbsoluteX: return 3;
case AddrMode.AbsoluteY: return 3;
case AddrMode.Indirect: return 2;
case AddrMode.IndirectX: return 2;
case AddrMode.IndirectY: return 2;
case AddrMode.Relative: return 2;
case AddrMode.BlockMove: return 7;
case AddrMode.ImmZeroPage: return 3;
case AddrMode.ImmZeroPageX:return 3;
case AddrMode.ImmAbsolute: return 4;
case AddrMode.ImmAbsoluteX:return 4;
case AddrMode.AbsoluteIndirect: return 3;
case AddrMode.AbsoluteIndirectX: return 3;
default:
return -1;
}
}
}
public override string ToString()
{
switch (AddressMode)
{
case AddrMode.Implicit: return Instruction;
case AddrMode.Accumulator: return Instruction + " A";
case AddrMode.Immediate: return Instruction + " #nn";
case AddrMode.ZeroPage: return Instruction + " zp";
case AddrMode.ZeroPageX: return Instruction + " zp,X";
case AddrMode.ZeroPageY: return Instruction + " zp,Y";
case AddrMode.Absolute: return Instruction + " addr";
case AddrMode.AbsoluteX: return Instruction + " addr,X";
case AddrMode.AbsoluteY: return Instruction + " addr,Y";
case AddrMode.Indirect: return Instruction + " (addr)";
case AddrMode.IndirectX: return Instruction + " (addr,X)";
case AddrMode.IndirectY: return Instruction + " (addr),Y";
case AddrMode.Relative: return Instruction + " +/-rel";
case AddrMode.BlockMove: return Instruction + " src, dest, len";
default: return Instruction;
}
}
}
public partial class CoreGenerator
{
public OpcodeInfo[] Opcodes = new OpcodeInfo[256];
public void InitOpcodeTable()
{
// Add with Carry
Set(0x69, "ADC", AddrMode.Immediate, 2);
Set(0x65, "ADC", AddrMode.ZeroPage, 4);
Set(0x75, "ADC", AddrMode.ZeroPageX, 4);
Set(0x6D, "ADC", AddrMode.Absolute, 5);
Set(0x7D, "ADC", AddrMode.AbsoluteX, 5);
Set(0x79, "ADC", AddrMode.AbsoluteY, 5);
Set(0x72, "ADC", AddrMode.Indirect, 7);
Set(0x61, "ADC", AddrMode.IndirectX, 7);
Set(0x71, "ADC", AddrMode.IndirectY, 7);
// AND
Set(0x29, "AND", AddrMode.Immediate, 2);
Set(0x25, "AND", AddrMode.ZeroPage, 4);
Set(0x35, "AND", AddrMode.ZeroPageX, 4);
Set(0x2D, "AND", AddrMode.Absolute, 5);
Set(0x3D, "AND", AddrMode.AbsoluteX, 5);
Set(0x39, "AND", AddrMode.AbsoluteY, 5);
Set(0x32, "AND", AddrMode.Indirect, 7);
Set(0x21, "AND", AddrMode.IndirectX, 7);
Set(0x31, "AND", AddrMode.IndirectY, 7);
// Arithmatic Shift Left
Set(0x06, "ASL", AddrMode.ZeroPage, 6);
Set(0x16, "ASL", AddrMode.ZeroPageX, 6);
Set(0x0E, "ASL", AddrMode.Absolute, 7);
Set(0x1E, "ASL", AddrMode.AbsoluteX, 7);
Set(0x0A, "ASL", AddrMode.Accumulator, 2);
// Branch on Bit Reset
Set(0x0F, "BBR0", AddrMode.ZeroPageR, 6);
Set(0x1F, "BBR1", AddrMode.ZeroPageR, 6);
Set(0x2F, "BBR2", AddrMode.ZeroPageR, 6);
Set(0x3F, "BBR3", AddrMode.ZeroPageR, 6);
Set(0x4F, "BBR4", AddrMode.ZeroPageR, 6);
Set(0x5F, "BBR5", AddrMode.ZeroPageR, 6);
Set(0x6F, "BBR6", AddrMode.ZeroPageR, 6);
Set(0x7F, "BBR7", AddrMode.ZeroPageR, 6);
// Branch on Bit Set
Set(0x8F, "BBS0", AddrMode.ZeroPageR, 6);
Set(0x9F, "BBS1", AddrMode.ZeroPageR, 6);
Set(0xAF, "BBS2", AddrMode.ZeroPageR, 6);
Set(0xBF, "BBS3", AddrMode.ZeroPageR, 6);
Set(0xCF, "BBS4", AddrMode.ZeroPageR, 6);
Set(0xDF, "BBS5", AddrMode.ZeroPageR, 6);
Set(0xEF, "BBS6", AddrMode.ZeroPageR, 6);
Set(0xFF, "BBS7", AddrMode.ZeroPageR, 6);
// BIT
Set(0x89, "BIT", AddrMode.Immediate, 2);
Set(0x24, "BIT", AddrMode.ZeroPage, 4);
Set(0x34, "BIT", AddrMode.ZeroPageX, 4);
Set(0x2C, "BIT", AddrMode.Absolute, 5);
Set(0x3C, "BIT", AddrMode.AbsoluteX, 5);
// Branch instructions
Set(0x10, "BPL", AddrMode.Relative, 2); // Branch on Plus
Set(0x30, "BMI", AddrMode.Relative, 2); // Branch on Minus
Set(0x50, "BVC", AddrMode.Relative, 2); // Branch on Overflow Clear
Set(0x70, "BVS", AddrMode.Relative, 2); // Branch on Overflow Set
Set(0x90, "BCC", AddrMode.Relative, 2); // Branch on Carry Clear
Set(0xB0, "BCS", AddrMode.Relative, 2); // Branch on Carry Set
Set(0xD0, "BNE", AddrMode.Relative, 2); // Branch on Not Equal
Set(0xF0, "BEQ", AddrMode.Relative, 2); // Branch on Equal
Set(0x80, "BRA", AddrMode.Relative, 4); // Branch Always
Set(0x44, "BSR", AddrMode.Relative, 8); // Branch to Subroutine
// CPU Break
Set(0x00, "BRK", AddrMode.Implicit, 8);
// Compare accumulator
Set(0xC9, "CMP", AddrMode.Immediate, 2);
Set(0xC5, "CMP", AddrMode.ZeroPage, 4);
Set(0xD5, "CMP", AddrMode.ZeroPageX, 4);
Set(0xD2, "CMP", AddrMode.Indirect, 7);
Set(0xC1, "CMP", AddrMode.IndirectX, 7);
Set(0xD1, "CMP", AddrMode.IndirectY, 7);
Set(0xCD, "CMP", AddrMode.Absolute, 5);
Set(0xDD, "CMP", AddrMode.AbsoluteX, 5);
Set(0xD9, "CMP", AddrMode.AbsoluteY, 5);
// Compare X register
Set(0xE0, "CPX", AddrMode.Immediate, 2);
Set(0xE4, "CPX", AddrMode.ZeroPage, 4);
Set(0xEC, "CPX", AddrMode.Absolute, 5);
// Compare Y register
Set(0xC0, "CPY", AddrMode.Immediate, 2);
Set(0xC4, "CPY", AddrMode.ZeroPage, 4);
Set(0xCC, "CPY", AddrMode.Absolute, 5);
// DEC
Set(0xC6, "DEC", AddrMode.ZeroPage, 6);
Set(0xD6, "DEC", AddrMode.ZeroPageX, 6);
Set(0xCE, "DEC", AddrMode.Absolute, 7);
Set(0xDE, "DEC", AddrMode.AbsoluteX, 7);
Set(0x3A, "DEC", AddrMode.Accumulator, 2);
// Exclusive OR
Set(0x49, "EOR", AddrMode.Immediate, 2);
Set(0x45, "EOR", AddrMode.ZeroPage, 4);
Set(0x55, "EOR", AddrMode.ZeroPageX, 4);
Set(0x52, "EOR", AddrMode.Indirect, 7);
Set(0x41, "EOR", AddrMode.IndirectX, 7);
Set(0x51, "EOR", AddrMode.IndirectY, 7);
Set(0x4D, "EOR", AddrMode.Absolute, 5);
Set(0x5D, "EOR", AddrMode.AbsoluteX, 5);
Set(0x59, "EOR", AddrMode.AbsoluteY, 5);
// Flag Instructions
Set(0x18, "CLC", AddrMode.Implicit, 2); // Clear Carry
Set(0x38, "SEC", AddrMode.Implicit, 2); // Set Carry
Set(0x58, "CLI", AddrMode.Implicit, 2); // Clear Interrupt
Set(0x78, "SEI", AddrMode.Implicit, 2); // Set Interrupt
Set(0xB8, "CLV", AddrMode.Implicit, 2); // Clear Overflow
Set(0xD8, "CLD", AddrMode.Implicit, 2); // Clear Decimal
Set(0xF8, "SED", AddrMode.Implicit, 2); // Set Decimal
Set(0xF4, "SET", AddrMode.Implicit, 2); // Set T flag
// Additional clear instructions
Set(0x62, "CLA", AddrMode.Implicit, 2);
Set(0x82, "CLX", AddrMode.Implicit, 2);
Set(0xC2, "CLY", AddrMode.Implicit, 2);
// INC
Set(0xE6, "INC", AddrMode.ZeroPage, 6);
Set(0xF6, "INC", AddrMode.ZeroPageX, 6);
Set(0xEE, "INC", AddrMode.Absolute, 7);
Set(0xFE, "INC", AddrMode.AbsoluteX, 7);
Set(0x1A, "INC", AddrMode.Accumulator, 2);
// Jump
Set(0x4C, "JMP", AddrMode.Absolute, 4);
Set(0x6C, "JMP", AddrMode.AbsoluteIndirect, 7);
Set(0x7C, "JMP", AddrMode.AbsoluteIndirectX, 7);
// Jump to Subroutine
Set(0x20, "JSR", AddrMode.Absolute, 7);
// Load Accumulator
Set(0xA9, "LDA", AddrMode.Immediate, 2);
Set(0xA5, "LDA", AddrMode.ZeroPage, 4);
Set(0xB5, "LDA", AddrMode.ZeroPageX, 4);
Set(0xB2, "LDA", AddrMode.Indirect, 7);
Set(0xA1, "LDA", AddrMode.IndirectX, 7);
Set(0xB1, "LDA", AddrMode.IndirectY, 7);
Set(0xAD, "LDA", AddrMode.Absolute, 5);
Set(0xBD, "LDA", AddrMode.AbsoluteX, 5);
Set(0xB9, "LDA", AddrMode.AbsoluteY, 5);
// Load X register
Set(0xA2, "LDX", AddrMode.Immediate, 2);
Set(0xA6, "LDX", AddrMode.ZeroPage, 4);
Set(0xB6, "LDX", AddrMode.ZeroPageY, 4);
Set(0xAE, "LDX", AddrMode.Absolute, 5);
Set(0xBE, "LDX", AddrMode.AbsoluteY, 5);
// Load Y register
Set(0xA0, "LDY", AddrMode.Immediate, 2);
Set(0xA4, "LDY", AddrMode.ZeroPage, 4);
Set(0xB4, "LDY", AddrMode.ZeroPageX, 4);
Set(0xAC, "LDY", AddrMode.Absolute, 5);
Set(0xBC, "LDY", AddrMode.AbsoluteX, 5);
// Logical Shift Right
Set(0x46, "LSR", AddrMode.ZeroPage, 6);
Set(0x56, "LSR", AddrMode.ZeroPageX, 6);
Set(0x4E, "LSR", AddrMode.Absolute, 7);
Set(0x5E, "LSR", AddrMode.AbsoluteX, 7);
Set(0x4A, "LSR", AddrMode.Accumulator, 2);
// No Operation
Set(0xEA, "NOP", AddrMode.Implicit, 2);
// Bitwise OR with Accumulator
Set(0x09, "ORA", AddrMode.Immediate, 2);
Set(0x05, "ORA", AddrMode.ZeroPage, 4);
Set(0x15, "ORA", AddrMode.ZeroPageX, 4);
Set(0x12, "ORA", AddrMode.Indirect, 7);
Set(0x01, "ORA", AddrMode.IndirectX, 7);
Set(0x11, "ORA", AddrMode.IndirectY, 7);
Set(0x0D, "ORA", AddrMode.Absolute, 5);
Set(0x1D, "ORA", AddrMode.AbsoluteX, 5);
Set(0x19, "ORA", AddrMode.AbsoluteY, 5);
// Register instructions
Set(0xCA, "DEX", AddrMode.Implicit, 2); // DEC X
Set(0x88, "DEY", AddrMode.Implicit, 2); // DEC Y
Set(0xE8, "INX", AddrMode.Implicit, 2); // INC X
Set(0xC8, "INY", AddrMode.Implicit, 2); // INC Y
Set(0x22, "SAX", AddrMode.Implicit, 3); // Swap A and X
Set(0x42, "SAY", AddrMode.Implicit, 3); // Swap A and Y
Set(0x02, "SXY", AddrMode.Implicit, 3); // Swap X and Y
Set(0xAA, "TAX", AddrMode.Implicit, 2); // Transfer A to X
Set(0x8A, "TXA", AddrMode.Implicit, 2); // Transfer X to A
Set(0xA8, "TAY", AddrMode.Implicit, 2); // Transfer A to Y
Set(0x98, "TYA", AddrMode.Implicit, 2); // Transfer Y to A
// Rotate Left
Set(0x26, "ROL", AddrMode.ZeroPage, 6);
Set(0x36, "ROL", AddrMode.ZeroPageX, 6);
Set(0x2E, "ROL", AddrMode.Absolute, 7);
Set(0x3E, "ROL", AddrMode.AbsoluteX, 7);
Set(0x2A, "ROL", AddrMode.Accumulator, 2);
// Rotate Right
Set(0x66, "ROR", AddrMode.ZeroPage, 6);
Set(0x76, "ROR", AddrMode.ZeroPageX, 6);
Set(0x6E, "ROR", AddrMode.Absolute, 7);
Set(0x7E, "ROR", AddrMode.AbsoluteX, 7);
Set(0x6A, "ROR", AddrMode.Accumulator, 2);
// Return from Interrupt
Set(0x40, "RTI", AddrMode.Implicit, 7);
// Return from Subroutine
Set(0x60, "RTS", AddrMode.Implicit, 7);
// Subtract with Carry
Set(0xE9, "SBC", AddrMode.Immediate, 2);
Set(0xE5, "SBC", AddrMode.ZeroPage, 4);
Set(0xF5, "SBC", AddrMode.ZeroPageX, 4);
Set(0xF2, "SBC", AddrMode.Indirect, 7);
Set(0xE1, "SBC", AddrMode.IndirectX, 7);
Set(0xF1, "SBC", AddrMode.IndirectY, 7);
Set(0xED, "SBC", AddrMode.Absolute, 5);
Set(0xFD, "SBC", AddrMode.AbsoluteX, 5);
Set(0xF9, "SBC", AddrMode.AbsoluteY, 5);
// Store Accumulator
Set(0x85, "STA", AddrMode.ZeroPage, 4);
Set(0x95, "STA", AddrMode.ZeroPageX, 4);
Set(0x92, "STA", AddrMode.Indirect, 7);
Set(0x81, "STA", AddrMode.IndirectX, 7);
Set(0x91, "STA", AddrMode.IndirectY, 7);
Set(0x8D, "STA", AddrMode.Absolute, 5);
Set(0x9D, "STA", AddrMode.AbsoluteX, 5);
Set(0x99, "STA", AddrMode.AbsoluteY, 5);
// Stack instructions
Set(0x9A, "TXS", AddrMode.Implicit, 2); // Transfer X to Stack
Set(0xBA, "TSX", AddrMode.Implicit, 2); // Transfer Stack to X
Set(0x48, "PHA", AddrMode.Implicit, 3); // Push A
Set(0x68, "PLA", AddrMode.Implicit, 4); // Pull A
Set(0x08, "PHP", AddrMode.Implicit, 3); // Push P
Set(0x28, "PLP", AddrMode.Implicit, 4); // Pull P
Set(0xDA, "PHX", AddrMode.Implicit, 3); // Push X
Set(0xFA, "PLX", AddrMode.Implicit, 4); // Pull X
Set(0x5A, "PHY", AddrMode.Implicit, 3); // Push Y
Set(0x7A, "PLY", AddrMode.Implicit, 4); // Pull Y
// Store X register
Set(0x86, "STX", AddrMode.ZeroPage, 4);
Set(0x96, "STX", AddrMode.ZeroPageY, 4);
Set(0x8E, "STX", AddrMode.Absolute, 5);
// Store Y register
Set(0x84, "STY", AddrMode.ZeroPage, 4);
Set(0x94, "STY", AddrMode.ZeroPageX, 4);
Set(0x8C, "STY", AddrMode.Absolute, 5);
// Memory Paging Register instructions
Set(0x53, "TAM", AddrMode.Immediate, 5);
Set(0x43, "TMA", AddrMode.Immediate, 4);
// VDC I/O instructions
Set(0x03, "ST0", AddrMode.Immediate, 4);
Set(0x13, "ST1", AddrMode.Immediate, 4);
Set(0x23, "ST2", AddrMode.Immediate, 4);
// Store Memory To Zero
Set(0x64, "STZ", AddrMode.ZeroPage, 4);
Set(0x74, "STZ", AddrMode.ZeroPageX, 4);
Set(0x9C, "STZ", AddrMode.Absolute, 5);
Set(0x9E, "STZ", AddrMode.AbsoluteX, 5);
// Reset Memory Bit i
Set(0x07, "RMB0", AddrMode.ZeroPage, 7);
Set(0x17, "RMB1", AddrMode.ZeroPage, 7);
Set(0x27, "RMB2", AddrMode.ZeroPage, 7);
Set(0x37, "RMB3", AddrMode.ZeroPage, 7);
Set(0x47, "RMB4", AddrMode.ZeroPage, 7);
Set(0x57, "RMB5", AddrMode.ZeroPage, 7);
Set(0x67, "RMB6", AddrMode.ZeroPage, 7);
Set(0x77, "RMB7", AddrMode.ZeroPage, 7);
// Set Memory Bit i
Set(0x87, "SMB0", AddrMode.ZeroPage, 7);
Set(0x97, "SMB1", AddrMode.ZeroPage, 7);
Set(0xA7, "SMB2", AddrMode.ZeroPage, 7);
Set(0xB7, "SMB3", AddrMode.ZeroPage, 7);
Set(0xC7, "SMB4", AddrMode.ZeroPage, 7);
Set(0xD7, "SMB5", AddrMode.ZeroPage, 7);
Set(0xE7, "SMB6", AddrMode.ZeroPage, 7);
Set(0xF7, "SMB7", AddrMode.ZeroPage, 7);
// Test and Reset Memory Bit Against Accumulator
Set(0x14, "TRB", AddrMode.ZeroPage, 6);
Set(0x1C, "TRB", AddrMode.Absolute, 7);
// Test and Set Memory Bit Against Accumulator
Set(0x04, "TSB", AddrMode.ZeroPage, 6);
Set(0x0C, "TSB", AddrMode.Absolute, 7);
// Test and Reset Memory Bits
Set(0x83, "TST", AddrMode.ImmZeroPage, 7);
Set(0xA3, "TST", AddrMode.ImmZeroPageX, 7);
Set(0x93, "TST", AddrMode.ImmAbsolute, 8);
Set(0xB3, "TST", AddrMode.ImmAbsoluteX, 8);
// Cpu Speed instructions
Set(0xD4, "CSH", AddrMode.Implicit, 3);
Set(0x54, "CSL", AddrMode.Implicit, 3);
// Block Memory Transfer instructions
Set(0xF3, "TAI", AddrMode.BlockMove, 17); // Transfer Alternate Increment
Set(0xE3, "TIA", AddrMode.BlockMove, 17); // Transfer Increment Alternate
Set(0x73, "TII", AddrMode.BlockMove, 17); // Transfer Increment Increment
Set(0xD3, "TIN", AddrMode.BlockMove, 17); // Transfer Increment None
Set(0xC3, "TDD", AddrMode.BlockMove, 17); // Transfer Decrement Decrement
}
private void Set(byte value, string instr, AddrMode addressMode, int cycles)
{
var op = new OpcodeInfo();
op.Instruction = instr;
op.AddressMode = addressMode;
op.Cycles = cycles;
if (Opcodes[value] != null)
throw new Exception("opcode " + value + " already assigned");
Opcodes[value] = op;
}
public void GenerateExecutor(string file)
{
var w = new StreamWriter(file, false);
w.WriteLine("using System;");
w.WriteLine();
w.WriteLine("// Do not modify this file directly! This is GENERATED code.");
w.WriteLine("// Please open the CpuCoreGenerator solution and make your modifications there.");
w.WriteLine();
w.WriteLine("namespace BizHawk.Emulation.Cores.Components.H6280");
w.WriteLine("{");
w.WriteLine(" public partial class HuC6280");
w.WriteLine(" {");
w.WriteLine(" public bool Debug;");
w.WriteLine(" public Action<string> Logger;");
w.WriteLine();
w.WriteLine(" public void Execute(int cycles)");
w.WriteLine(" {");
w.WriteLine(" sbyte rel8;");
w.WriteLine(" byte value8, temp8, source8;");
w.WriteLine(" ushort value16, temp16;");
w.WriteLine(" int temp, lo, hi;");
w.WriteLine();
w.WriteLine(" PendingCycles += cycles;");
w.WriteLine(" while (PendingCycles > 0)");
w.WriteLine(" {");
w.WriteLine(" int lastCycles = PendingCycles;");
w.WriteLine();
w.WriteLine(" if (IRQ1Assert && FlagI == false && LagIFlag == false && (IRQControlByte & IRQ1Selector) == 0 && InBlockTransfer == false)");
w.WriteLine(" {");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)PC);");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10)));");
w.WriteLine(" FlagD = false;");
w.WriteLine(" FlagI = true;");
w.WriteLine(" PC = ReadWord(IRQ1Vector);");
w.WriteLine(" PendingCycles -= 8;");
w.WriteLine(" }");
w.WriteLine();
w.WriteLine(" if (TimerAssert && FlagI == false && LagIFlag == false && (IRQControlByte & TimerSelector) == 0 && InBlockTransfer == false)");
w.WriteLine(" {");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)PC);");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10)));");
w.WriteLine(" FlagD = false;");
w.WriteLine(" FlagI = true;");
w.WriteLine(" PC = ReadWord(TimerVector);");
w.WriteLine(" PendingCycles -= 8;");
w.WriteLine(" }");
w.WriteLine();
w.WriteLine(" if (IRQ2Assert && FlagI == false && LagIFlag == false && (IRQControlByte & IRQ2Selector) == 0 && InBlockTransfer == false)");
w.WriteLine(" {");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)PC);");
w.WriteLine(" WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10)));");
w.WriteLine(" FlagD = false;");
w.WriteLine(" FlagI = true;");
w.WriteLine(" PC = ReadWord(IRQ2Vector);");
w.WriteLine(" PendingCycles -= 8;");
w.WriteLine(" }");
w.WriteLine();
w.WriteLine(" IRQControlByte = IRQNextControlByte;");
w.WriteLine(" LagIFlag = FlagI;");
w.WriteLine();
w.WriteLine(" if (Debug) Logger(State());");
w.WriteLine(" MemoryCallbacks.CallExecutes(PC);");
w.WriteLine(" if (CDLLoggingActive) CDLOpcode();");
w.WriteLine();
w.WriteLine(" byte opcode = ReadMemory(PC++);");
w.WriteLine(" switch (opcode)");
w.WriteLine(" {");
for (int i = 0; i < 256; i++)
{
if (Opcodes[i] != null)
EmulateOpcode(w, i);
}
w.WriteLine(" default:");
w.WriteLine(" Console.WriteLine(\"Unhandled opcode: {0:X2}\", opcode);");
w.WriteLine(" break;");
w.WriteLine(" }");
w.WriteLine();
w.WriteLine(" P &= 0xDF; // Clear T flag");
w.WriteLine(" AfterClearTFlag: // SET command jumps here");
w.WriteLine(" int delta = lastCycles - PendingCycles;");
w.WriteLine(" if (LowSpeed)");
w.WriteLine(" {");
w.WriteLine(" delta *= 4;");
w.WriteLine(" PendingCycles = lastCycles - delta;");
w.WriteLine(" }");
w.WriteLine(" TotalExecutedCycles += delta;");
w.WriteLine();
w.WriteLine(" if (TimerEnabled)");
w.WriteLine(" {");
w.WriteLine(" TimerTickCounter += delta;");
w.WriteLine(" while (TimerTickCounter >= 1024)");
w.WriteLine(" {");
w.WriteLine(" TimerValue--;");
w.WriteLine(" TimerTickCounter -= 1024;");
w.WriteLine(" if (TimerValue == 0xFF)");
w.WriteLine(" {");
w.WriteLine(" TimerValue = TimerReloadValue;");
w.WriteLine(" TimerAssert = true;");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine(" ThinkAction(delta);");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine("}");
w.Close();
}
const string Spaces = " ";
private void EmulateOpcode(TextWriter w, int opcode)
{
var op = Opcodes[opcode];
w.WriteLine(" case 0x{0:X2}: // {1}", opcode, op);
switch (op.Instruction)
{
case "ADC": ADC(op, w); break;
case "AND": AND(op, w); break;
case "ASL": ASL(op, w); break;
case "BBR0": BB(op, w, 0, false); break;
case "BBR1": BB(op, w, 1, false); break;
case "BBR2": BB(op, w, 2, false); break;
case "BBR3": BB(op, w, 3, false); break;
case "BBR4": BB(op, w, 4, false); break;
case "BBR5": BB(op, w, 5, false); break;
case "BBR6": BB(op, w, 6, false); break;
case "BBR7": BB(op, w, 7, false); break;
case "BBS0": BB(op, w, 0, true); break;
case "BBS1": BB(op, w, 1, true); break;
case "BBS2": BB(op, w, 2, true); break;
case "BBS3": BB(op, w, 3, true); break;
case "BBS4": BB(op, w, 4, true); break;
case "BBS5": BB(op, w, 5, true); break;
case "BBS6": BB(op, w, 6, true); break;
case "BBS7": BB(op, w, 7, true); break;
case "BCC": Branch(op, w, "C", false); break;
case "BCS": Branch(op, w, "C", true); break;
case "BEQ": Branch(op, w, "Z", true); break;
case "BIT": BIT(op, w); break;
case "BMI": Branch(op, w, "N", true); break;
case "BNE": Branch(op, w, "Z", false); break;
case "BPL": Branch(op, w, "N", false); break;
case "BRA": BRA(op, w); break;
case "BRK": BRK(op, w); break;
case "BSR": BSR(op, w); break;
case "BVC": Branch(op, w, "V", false); break;
case "BVS": Branch(op, w, "V", true); break;
case "CLA": CLreg(op, w, "A"); break;
case "CLC": CLC(op, w); break;
case "CLD": CLD(op, w); break;
case "CLI": CLI(op, w); break;
case "CLV": CLV(op, w); break;
case "CLX": CLreg(op, w, "X"); break;
case "CLY": CLreg(op, w, "Y"); break;
case "CMP": CMP_reg(op, w, "A"); break;
case "CPX": CMP_reg(op, w, "X"); break;
case "CPY": CMP_reg(op, w, "Y"); break;
case "CSH": CSH(op, w); break;
case "CSL": CSL(op, w); break;
case "DEC": DEC(op, w); break;
case "DEX": DEX(op, w); break;
case "DEY": DEY(op, w); break;
case "EOR": EOR(op, w); break;
case "INC": INC(op, w); break;
case "INX": INX(op, w); break;
case "INY": INY(op, w); break;
case "JMP": JMP(op, w); break;
case "JSR": JSR(op, w); break;
case "LDA": LDA(op, w); break;
case "LDX": LDX(op, w); break;
case "LDY": LDY(op, w); break;
case "LSR": LSR(op, w); break;
case "NOP": NOP(op, w); break;
case "ORA": ORA(op, w); break;
case "PHA": PushReg(op, w, "A"); break;
case "PHP": PushReg(op, w, "P"); break;
case "PHX": PushReg(op, w, "X"); break;
case "PHY": PushReg(op, w, "Y"); break;
case "PLA": PullReg(op, w, "A"); break;
case "PLP": PLP(op, w); break;
case "PLX": PullReg(op, w, "X"); break;
case "PLY": PullReg(op, w, "Y"); break;
case "ROL": ROL(op, w); break;
case "ROR": ROR(op, w); break;
case "RTI": RTI(op, w); break;
case "RTS": RTS(op, w); break;
case "SAX": SAX(op, w); break;
case "SAY": SAY(op, w); break;
case "SBC": SBC(op, w); break;
case "SEC": SEC(op, w); break;
case "SED": SED(op, w); break;
case "SEI": SEI(op, w); break;
case "SET": SET(op, w); break;
case "SXY": SXY(op, w); break;
case "ST0": ST0(op, w); break;
case "ST1": ST1(op, w); break;
case "ST2": ST2(op, w); break;
case "STA": STA(op, w); break;
case "STX": STX(op, w); break;
case "STY": STY(op, w); break;
case "STZ": STZ(op, w); break;
case "TAI": TAI(op, w); break;
case "TAM": TAM(op, w); break;
case "TAX": TAX(op, w); break;
case "TAY": TAY(op, w); break;
case "TDD": TDD(op, w); break;
case "TIA": TIA(op, w); break;
case "TII": TII(op, w); break;
case "TIN": TIN(op, w); break;
case "TMA": TMA(op, w); break;
case "TRB": TRB(op, w); break;
case "TSB": TSB(op, w); break;
case "TST": TST(op, w); break;
case "TSX": TSX(op, w); break;
case "TXA": TXA(op, w); break;
case "TYA": TYA(op, w); break;
case "TXS": TXS(op, w); break;
case "RMB0": RMB(op, w, 0); break;
case "RMB1": RMB(op, w, 1); break;
case "RMB2": RMB(op, w, 2); break;
case "RMB3": RMB(op, w, 3); break;
case "RMB4": RMB(op, w, 4); break;
case "RMB5": RMB(op, w, 5); break;
case "RMB6": RMB(op, w, 6); break;
case "RMB7": RMB(op, w, 7); break;
case "SMB0": SMB(op, w, 0); break;
case "SMB1": SMB(op, w, 1); break;
case "SMB2": SMB(op, w, 2); break;
case "SMB3": SMB(op, w, 3); break;
case "SMB4": SMB(op, w, 4); break;
case "SMB5": SMB(op, w, 5); break;
case "SMB6": SMB(op, w, 6); break;
case "SMB7": SMB(op, w, 7); break;
default:
w.WriteLine("throw new Exception(\"unsupported opcode {0:X2}\");",opcode);
break;
}
if (op.Instruction != "SET" && op.Instruction != "RTI" && op.Instruction != "PLP")
w.WriteLine(Spaces + "break;");
}
private void GetValue8(OpcodeInfo op, TextWriter w, string dest)
{
switch (op.AddressMode)
{
case AddrMode.Immediate:
w.WriteLine(Spaces + dest + " = ReadMemory(PC++);"); break;
case AddrMode.ImmZeroPage:
case AddrMode.ZeroPage:
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadMemory(PC++)+0x2000));"); break;
case AddrMode.ImmZeroPageX:
case AddrMode.ZeroPageX:
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000));"); break;
case AddrMode.ZeroPageY:
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(((ReadMemory(PC++)+Y)&0xFF)+0x2000));"); break;
case AddrMode.ImmAbsolute:
case AddrMode.Absolute:
w.WriteLine(Spaces + dest + " = ReadMemory(ReadWord(PC)); PC += 2;"); break;
case AddrMode.ImmAbsoluteX:
case AddrMode.AbsoluteX:
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+X));");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.AbsoluteY:
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+Y));");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.Indirect:
w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000)));"); break;
case AddrMode.IndirectX:
w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000)));"); break;
case AddrMode.IndirectY:
w.WriteLine(Spaces + "temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000));");
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+Y));");
break;
default:
throw new Exception("p"+op.Instruction);
}
}
private void GetAddress(OpcodeInfo op, TextWriter w, string dest)
{
switch (op.AddressMode)
{
case AddrMode.ZeroPage:
w.WriteLine(Spaces + dest + " = (ushort)(ReadMemory(PC++)+0x2000);"); break;
case AddrMode.ZeroPageX:
w.WriteLine(Spaces + dest + " = (ushort)(((ReadMemory(PC++)+X)&0xFF)+0x2000);"); break;
case AddrMode.ZeroPageY:
w.WriteLine(Spaces + dest + " = (ushort)(((ReadMemory(PC++)+Y)&0xFF)+0x2000);"); break;
case AddrMode.Absolute:
w.WriteLine(Spaces + dest + " = ReadWord(PC); PC += 2;"); break;
case AddrMode.AbsoluteX:
w.WriteLine(Spaces + dest + " = (ushort)(ReadWord(PC)+X);");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.AbsoluteY:
w.WriteLine(Spaces + dest + " = (ushort)(ReadWord(PC)+Y);");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.Indirect:
w.WriteLine(Spaces + dest + " = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000));"); break;
case AddrMode.IndirectX:
w.WriteLine(Spaces + dest + " = ReadWordPageWrap((ushort)((byte)(ReadMemory(PC++)+X)+0x2000));"); break;
case AddrMode.IndirectY:
w.WriteLine(Spaces + "temp16 = ReadWordPageWrap((ushort)(ReadMemory(PC++)+0x2000));");
w.WriteLine(Spaces + dest + " = (ushort)(temp16+Y);");
break;
case AddrMode.Relative:
w.WriteLine(Spaces + "rel8 = (sbyte)ReadMemory(PC++);");
w.WriteLine(Spaces + dest + " = (ushort)(PC+rel8);");
break;
}
}
public void GenerateDisassembler(string file)
{
var w = new StreamWriter(file, false);
w.WriteLine("using System;");
w.WriteLine("namespace BizHawk.Emulation.Cores.Components.H6280");
w.WriteLine();
w.WriteLine("// Do not modify this file directly! This is GENERATED code.");
w.WriteLine("// Please open the CpuCoreGenerator solution and make your modifications there.");
w.WriteLine();
w.WriteLine("{");
w.WriteLine(" public partial class HuC6280");
w.WriteLine(" {");
w.WriteLine(" public string Disassemble(ushort pc, out int bytesToAdvance)");
w.WriteLine(" {");
w.WriteLine(" byte op = ReadMemory(pc);");
w.WriteLine(" switch (op)");
w.WriteLine(" {");
for (int i = 0; i < 256; i++)
{
if (Opcodes[i] != null)
DisassembleOpcode(w, i);
}
w.WriteLine(" }");
w.WriteLine(" bytesToAdvance = 1;");
w.WriteLine(" return \"???\";");
w.WriteLine(" }");
w.WriteLine();
w.WriteLine(" // avoid slowing down the other disassembler");
w.WriteLine(" public static string DisassembleExt(ushort pc, out int bytesToAdvance, Func<ushort, byte> ReadMemory, Func<ushort, ushort> ReadWord)");
w.WriteLine(" {");
w.WriteLine(" byte op = ReadMemory(pc);");
w.WriteLine(" switch (op)");
w.WriteLine(" {");
for (int i = 0; i < 256; i++)
{
if (Opcodes[i] != null)
DisassembleOpcode(w, i);
}
w.WriteLine(" }");
w.WriteLine(" bytesToAdvance = 1;");
w.WriteLine(" return \"???\";");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine("}");
w.Close();
}
private void DisassembleOpcode(TextWriter w, int i)
{
var op = Opcodes[i];
w.Write(" case 0x{0:X2}: ", i);
string mstr;
switch (op.AddressMode)
{
case AddrMode.Implicit: mstr = "\"" + op.Instruction + "\""; break;
case AddrMode.Accumulator: mstr = "\"" + op.Instruction + " A\""; break;
case AddrMode.Immediate: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}\", ReadMemory(++pc))"; break;
case AddrMode.ZeroPage: mstr = "string.Format(\"" + op.Instruction + " ${0:X2}\", ReadMemory(++pc))"; break;
case AddrMode.ZeroPageX: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},X\", ReadMemory(++pc))"; break;
case AddrMode.ZeroPageY: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},Y\", ReadMemory(++pc))"; break;
case AddrMode.ZeroPageR: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},{1}\", ReadMemory(++pc), (sbyte)ReadMemory(++pc))"; break;
case AddrMode.Absolute: mstr = "string.Format(\"" + op.Instruction + " ${0:X4}\", ReadWord(++pc))"; break;
case AddrMode.AbsoluteX: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},X\", ReadWord(++pc))"; break;
case AddrMode.AbsoluteY: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},Y\", ReadWord(++pc))"; break;
case AddrMode.Indirect: mstr = "string.Format(\"" + op.Instruction + " (${0:X2})\", ReadMemory(++pc))"; break;
case AddrMode.IndirectX: mstr = "string.Format(\"" + op.Instruction + " (${0:X2},X)\", ReadMemory(++pc))"; break;
case AddrMode.IndirectY: mstr = "string.Format(\"" + op.Instruction + " (${0:X2}),Y\", ReadMemory(++pc))"; break;
case AddrMode.Relative: mstr = "string.Format(\"" + op.Instruction + " {0}\", (sbyte)ReadMemory(++pc))"; break;
case AddrMode.BlockMove: mstr = "string.Format(\"" + op.Instruction + " {0:X4},{1:X4},{2:X4}\", ReadWord((ushort)(pc+1)),ReadWord((ushort)(pc+3)),ReadWord((ushort)(pc+5)))"; break;
case AddrMode.ImmZeroPage: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}, ${1:X2}\", ReadMemory(++pc), ReadMemory(++pc))"; break;
case AddrMode.ImmZeroPageX: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}, ${1:X2},X\", ReadMemory(++pc), ReadMemory(++pc))"; break;
case AddrMode.ImmAbsolute: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}, ${1:X4}\", ReadMemory(++pc), ReadWord(++pc))"; break;
case AddrMode.ImmAbsoluteX: mstr = "string.Format(\"" + op.Instruction + " #${0:X2}, ${1:X4},X\", ReadMemory(++pc), ReadWord(++pc))"; break;
case AddrMode.AbsoluteIndirect: mstr = "string.Format(\"" + op.Instruction + " (${0:X4})\", ReadWord(++pc))"; break;
case AddrMode.AbsoluteIndirectX: mstr = "string.Format(\"" + op.Instruction + " (${0:X4},X)\", ReadWord(++pc))"; break;
default: mstr = @"""?"""; break;
}
w.Write("bytesToAdvance = {0}; ", op.Size);
w.WriteLine("return " + mstr + ";");
}
}
}

View File

@ -1,815 +0,0 @@
using System.IO;
namespace HuC6280
{
public partial class CoreGenerator
{
private string SetNZ(string val)
{
return "P = (byte)((P & 0x7D) | TableNZ[" + val + "]);";
}
private void ADC(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "source8 = FlagT ? ReadMemory((ushort)(0x2000 + X)) : A;");
w.WriteLine();
w.WriteLine(Spaces + "if ((P & 0x08) != 0) {");
w.WriteLine(Spaces + " lo = (source8 & 0x0F) + (value8 & 0x0F) + (FlagC ? 1 : 0);");
w.WriteLine(Spaces + " hi = (source8 & 0xF0) + (value8 & 0xF0);");
w.WriteLine(Spaces + " if (lo > 0x09) {");
w.WriteLine(Spaces + " hi += 0x10;");
w.WriteLine(Spaces + " lo += 0x06;");
w.WriteLine(Spaces + " }");
w.WriteLine(Spaces + " if (hi > 0x90) hi += 0x60;");
w.WriteLine(Spaces + " FlagV = (~(source8^value8) & (source8^hi) & 0x80) != 0;");
w.WriteLine(Spaces + " FlagC = (hi & 0xFF00) != 0;");
w.WriteLine(Spaces + " source8 = (byte) ((lo & 0x0F) | (hi & 0xF0));");
w.WriteLine(Spaces + " PendingCycles--;");
w.WriteLine(Spaces + "} else {");
w.WriteLine(Spaces + " temp = value8 + source8 + (FlagC ? 1 : 0);");
w.WriteLine(Spaces + " FlagV = (~(source8 ^ value8) & (source8 ^ temp) & 0x80) != 0;");
w.WriteLine(Spaces + " FlagC = temp > 0xFF;");
w.WriteLine(Spaces + " source8 = (byte)temp;");
w.WriteLine(Spaces + "}");
w.WriteLine(Spaces + "if (FlagT == false)");
w.WriteLine(Spaces + " A = source8;");
w.WriteLine(Spaces + "else { ");
w.WriteLine(Spaces + " WriteMemory((ushort)(0x2000 + X), source8);");
w.WriteLine(Spaces + " PendingCycles -= 3;");
w.WriteLine(Spaces + "}");
w.WriteLine(Spaces + SetNZ("source8"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void AND(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "if (FlagT == false) { ");
w.WriteLine(Spaces + " A &= value8;");
w.WriteLine(Spaces + " " + SetNZ("A"));
w.WriteLine(Spaces + " PendingCycles -= {0};", op.Cycles);
w.WriteLine(Spaces + "} else {");
w.WriteLine(Spaces + " temp8 = ReadMemory((ushort)(0x2000 + X));");
w.WriteLine(Spaces + " temp8 &= value8;");
w.WriteLine(Spaces + " " + SetNZ("temp8"));
w.WriteLine(Spaces + " WriteMemory((ushort)(0x2000 + X), temp8);");
w.WriteLine(Spaces + " PendingCycles -= {0};", op.Cycles + 3);
w.WriteLine(Spaces + "}");
}
private void ASL(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode == AddrMode.Accumulator)
{
w.WriteLine(Spaces + "FlagC = (A & 0x80) != 0;");
w.WriteLine(Spaces + "A = (byte) (A << 1);");
w.WriteLine(Spaces + SetNZ("A"));
}
else
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = ReadMemory(value16);");
w.WriteLine(Spaces + "FlagC = (value8 & 0x80) != 0;");
w.WriteLine(Spaces + "value8 = (byte)(value8 << 1);");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + SetNZ("value8"));
}
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void BB(OpcodeInfo op, TextWriter w, int bit, bool set)
{
string filter = "";
switch (bit)
{
case 0: filter = "0x01"; break;
case 1: filter = "0x02"; break;
case 2: filter = "0x04"; break;
case 3: filter = "0x08"; break;
case 4: filter = "0x10"; break;
case 5: filter = "0x20"; break;
case 6: filter = "0x40"; break;
case 7: filter = "0x80"; break;
}
string cond = set ? "!=" : "==";
w.WriteLine(Spaces + "value8 = ReadMemory((ushort)(ReadMemory(PC++)+0x2000));");
w.WriteLine(Spaces + "rel8 = (sbyte) ReadMemory(PC++);");
w.WriteLine(Spaces + "if ((value8 & "+filter+") "+cond+" 0) {");
w.WriteLine(Spaces + " PendingCycles -= 2;");
w.WriteLine(Spaces + " PC = (ushort)(PC+rel8);");
w.WriteLine(Spaces + "}");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void Branch(OpcodeInfo op, TextWriter w, string flag, bool cond)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "if (Flag" + flag + " == " + cond.ToString().ToLower() + ") {");
w.WriteLine(Spaces + " PendingCycles -= 2;");
w.WriteLine(Spaces + " PC = value16;");
w.WriteLine(Spaces + "}");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void BRA(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "PC");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void BRK(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "Console.WriteLine(\"EXEC BRK\");");
w.WriteLine(Spaces + "PC++;");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)(PC >> 8));");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)PC);");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)(P & (~0x10)));");
w.WriteLine(Spaces + "FlagT = false;");
w.WriteLine(Spaces + "FlagB = true;");
w.WriteLine(Spaces + "FlagD = false;");
w.WriteLine(Spaces + "FlagI = true;");
w.WriteLine(Spaces + "PC = ReadWord(IRQ2Vector);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void BSR(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "temp16 = (ushort)(PC-1);");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)(temp16 >> 8));");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)temp16);");
w.WriteLine(Spaces + "PC = value16;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void BIT(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "FlagN = (value8 & 0x80) != 0;");
w.WriteLine(Spaces + "FlagV = (value8 & 0x40) != 0;");
w.WriteLine(Spaces + "FlagZ = (A & value8) == 0;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void CLC(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagC = false;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void CLD(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagD = false;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void CLI(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagI = false;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void CLV(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagV = false;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void CLreg(OpcodeInfo op, TextWriter w, string reg)
{
w.WriteLine(Spaces + "{0} = 0;",reg);
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void CMP_reg(OpcodeInfo op, TextWriter w, string reg)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "value16 = (ushort) (" + reg + " - value8);");
w.WriteLine(Spaces + "FlagC = (" + reg + " >= value8);");
w.WriteLine(Spaces + SetNZ("(byte)value16"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void CSH(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "LowSpeed = false;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void CSL(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "LowSpeed = true;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void DEC(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode != AddrMode.Accumulator)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = (byte)(ReadMemory(value16) - 1);");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + SetNZ("value8"));
} else {
w.WriteLine(Spaces + SetNZ("--A"));
}
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void DEX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + SetNZ("--X"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void DEY(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + SetNZ("--Y"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void EOR(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "if (FlagT == false) { ");
w.WriteLine(Spaces + " A ^= value8;");
w.WriteLine(Spaces + " "+SetNZ("A"));
w.WriteLine(Spaces + " PendingCycles -= {0};", op.Cycles);
w.WriteLine(Spaces + "} else {");
w.WriteLine(Spaces + " temp8 = ReadMemory((ushort)(0x2000 + X));");
w.WriteLine(Spaces + " temp8 ^= value8;");
w.WriteLine(Spaces + " " + SetNZ("temp8"));
w.WriteLine(Spaces + " WriteMemory((ushort)(0x2000 + X), temp8);");
w.WriteLine(Spaces + " PendingCycles -= {0};", op.Cycles+3);
w.WriteLine(Spaces + "}");
}
private void INC(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode != AddrMode.Accumulator)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = (byte)(ReadMemory(value16) + 1);");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + SetNZ("value8"));
} else {
w.WriteLine(Spaces + SetNZ("++A"));
}
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void INX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + SetNZ("++X"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void INY(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + SetNZ("++Y"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void JMP(OpcodeInfo op, TextWriter w)
{
switch (op.AddressMode)
{
case AddrMode.Absolute: w.WriteLine(Spaces + "PC = ReadWord(PC);"); break;
case AddrMode.AbsoluteIndirect: w.WriteLine(Spaces + "PC = ReadWord(ReadWord(PC));"); break;
case AddrMode.AbsoluteIndirectX: w.WriteLine(Spaces + "PC = ReadWord((ushort)(ReadWord(PC)+X));"); break;
}
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void JSR(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "temp16 = (ushort)(PC+1);");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)(temp16 >> 8));");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), (byte)temp16);");
w.WriteLine(Spaces + "PC = ReadWord(PC);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void LDA(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "A");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void LDX(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "X");
w.WriteLine(Spaces + SetNZ("X"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void LDY(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "Y");
w.WriteLine(Spaces + SetNZ("Y"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void LSR(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode == AddrMode.Accumulator)
{
w.WriteLine(Spaces + "FlagC = (A & 1) != 0;");
w.WriteLine(Spaces + "A = (byte) (A >> 1);");
w.WriteLine(Spaces + SetNZ("A"));
}
else
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = ReadMemory(value16);");
w.WriteLine(Spaces + "FlagC = (value8 & 1) != 0;");
w.WriteLine(Spaces + "value8 = (byte)(value8 >> 1);");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + SetNZ("value8"));
}
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void NOP(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void ORA(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "if (FlagT == false)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " A |= value8;");
w.WriteLine(Spaces + " "+SetNZ("A"));
w.WriteLine(Spaces + " PendingCycles -= {0};", op.Cycles);
w.WriteLine(Spaces + "} else {");
w.WriteLine(Spaces + " source8 = ReadMemory((ushort)(0x2000 + X));");
w.WriteLine(Spaces + " source8 |= value8;");
w.WriteLine(Spaces + " " + SetNZ("source8"));
w.WriteLine(Spaces + " WriteMemory((ushort)(0x2000 + X), source8);");
w.WriteLine(Spaces + " PendingCycles -= {0};", op.Cycles+3);
w.WriteLine(Spaces + "}");
}
private void PushReg(OpcodeInfo op, TextWriter w, string reg)
{
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x2100), {0});", reg);
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void PullReg(OpcodeInfo op, TextWriter w, string reg)
{
w.WriteLine(Spaces + "{0} = ReadMemory((ushort)(++S + 0x2100));", reg);
w.WriteLine(Spaces + SetNZ(reg));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void PLP(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "P = ReadMemory((ushort)(++S + 0x2100));");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
w.WriteLine(Spaces + "goto AfterClearTFlag;");
}
private void ROL(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode == AddrMode.Accumulator)
{
w.WriteLine(Spaces + "temp8 = A;");
w.WriteLine(Spaces + "A = (byte)((A << 1) | (P & 1));");
w.WriteLine(Spaces + "FlagC = (temp8 & 0x80) != 0;");
w.WriteLine(Spaces + SetNZ("A"));
}
else
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = temp8 = ReadMemory(value16);");
w.WriteLine(Spaces + "value8 = (byte)((value8 << 1) | (P & 1));");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + "FlagC = (temp8 & 0x80) != 0;");
w.WriteLine(Spaces + SetNZ("value8"));
}
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void ROR(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode == AddrMode.Accumulator)
{
w.WriteLine(Spaces + "temp8 = A;");
w.WriteLine(Spaces + "A = (byte)((A >> 1) | ((P & 1)<<7));");
w.WriteLine(Spaces + "FlagC = (temp8 & 1) != 0;");
w.WriteLine(Spaces + SetNZ("A"));
}
else
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = temp8 = ReadMemory(value16);");
w.WriteLine(Spaces + "value8 = (byte)((value8 >> 1) | ((P & 1)<<7));");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + "FlagC = (temp8 & 1) != 0;");
w.WriteLine(Spaces + SetNZ("value8"));
}
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void RTI(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "P = ReadMemory((ushort)(++S + 0x2100));");
w.WriteLine(Spaces + "PC = ReadMemory((ushort)(++S + 0x2100));");
w.WriteLine(Spaces + "PC |= (ushort)(ReadMemory((ushort)(++S + 0x2100)) << 8);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
w.WriteLine(Spaces + "goto AfterClearTFlag;");
}
private void RTS(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "PC = ReadMemory((ushort)(++S + 0x2100));");
w.WriteLine(Spaces + "PC |= (ushort)(ReadMemory((ushort)(++S + 0x2100)) << 8);");
w.WriteLine(Spaces + "PC++;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SAX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "temp8 = A;");
w.WriteLine(Spaces + "A = X;");
w.WriteLine(Spaces + "X = temp8;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SAY(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "temp8 = A;");
w.WriteLine(Spaces + "A = Y;");
w.WriteLine(Spaces + "Y = temp8;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SXY(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "temp8 = X;");
w.WriteLine(Spaces + "X = Y;");
w.WriteLine(Spaces + "Y = temp8;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SBC(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "temp = A - value8 - (FlagC ? 0 : 1);");
w.WriteLine(Spaces + "if ((P & 0x08) != 0) {");
w.WriteLine(Spaces + " lo = (A & 0x0F) - (value8 & 0x0F) - (FlagC ? 0 : 1);");
w.WriteLine(Spaces + " hi = (A & 0xF0) - (value8 & 0xF0);");
w.WriteLine(Spaces + " if ((lo & 0xF0) != 0) lo -= 0x06;");
w.WriteLine(Spaces + " if ((lo & 0x80) != 0) hi -= 0x10;");
w.WriteLine(Spaces + " if ((hi & 0x0F00) != 0) hi -= 0x60;");
w.WriteLine(Spaces + " FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0;");
w.WriteLine(Spaces + " FlagC = (hi & 0xFF00) == 0;");
w.WriteLine(Spaces + " A = (byte) ((lo & 0x0F) | (hi & 0xF0));");
w.WriteLine(Spaces + " PendingCycles--;");
w.WriteLine(Spaces + "} else {");
w.WriteLine(Spaces + " FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0;");
w.WriteLine(Spaces + " FlagC = temp >= 0;");
w.WriteLine(Spaces + " A = (byte)temp;");
w.WriteLine(Spaces + "}");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SEC(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagC = true;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SED(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagD = true;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SEI(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagI = true;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SET(OpcodeInfo op, TextWriter w)
{
w.WriteLine(" int a; // TODO remove these extra checks"); // TODO remove these extra checks
w.WriteLine(" string b = Disassemble(PC, out a);");
w.WriteLine(" if (b.StartsWith(\"ADC\") == false && b.StartsWith(\"EOR\") == false && b.StartsWith(\"AND\") == false && b.StartsWith(\"ORA\") == false)");
w.WriteLine(" Console.WriteLine(\"SETTING T FLAG, NEXT INSTRUCTION IS UNHANDLED: {0}\", b);");
w.WriteLine(Spaces + "FlagT = true;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
w.WriteLine(Spaces + "goto AfterClearTFlag;");
}
private void ST0(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "WriteVDC(0,value8);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void ST1(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "WriteVDC(2,value8);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void ST2(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "WriteVDC(3,value8);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void STA(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "WriteMemory(value16, A);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void STX(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "WriteMemory(value16, X);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void STY(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "WriteMemory(value16, Y);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void STZ(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "WriteMemory(value16, 0);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TAM(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "for (byte reg=0; reg<8; reg++)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " if ((value8 & (1 << reg)) != 0)");
w.WriteLine(Spaces + " MPR[reg] = A;");
w.WriteLine(Spaces + "}");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TAX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "X = A;");
w.WriteLine(Spaces + SetNZ("X"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TAY(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "Y = A;");
w.WriteLine(Spaces + SetNZ("Y"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TMA(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + " if ((value8 & 0x01) != 0) A = MPR[0];");
w.WriteLine(Spaces + "else if ((value8 & 0x02) != 0) A = MPR[1];");
w.WriteLine(Spaces + "else if ((value8 & 0x04) != 0) A = MPR[2];");
w.WriteLine(Spaces + "else if ((value8 & 0x08) != 0) A = MPR[3];");
w.WriteLine(Spaces + "else if ((value8 & 0x10) != 0) A = MPR[4];");
w.WriteLine(Spaces + "else if ((value8 & 0x20) != 0) A = MPR[5];");
w.WriteLine(Spaces + "else if ((value8 & 0x40) != 0) A = MPR[6];");
w.WriteLine(Spaces + "else if ((value8 & 0x80) != 0) A = MPR[7];");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TRB(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = ReadMemory(value16);");
w.WriteLine(Spaces + "WriteMemory(value16, (byte)(value8 & ~A));");
w.WriteLine(Spaces + "FlagN = (value8 & 0x80) != 0;");
w.WriteLine(Spaces + "FlagV = (value8 & 0x40) != 0;");
w.WriteLine(Spaces + "FlagZ = (A & value8) == 0;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TSB(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = ReadMemory(value16);");
w.WriteLine(Spaces + "WriteMemory(value16, (byte)(value8 | A));");
w.WriteLine(Spaces + "FlagN = (value8 & 0x80) != 0;");
w.WriteLine(Spaces + "FlagV = (value8 & 0x40) != 0;");
w.WriteLine(Spaces + "FlagZ = (A | value8) == 0;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TST(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "value8 = ReadMemory(PC++);");
GetValue8(op, w, "temp8");
w.WriteLine(Spaces + "FlagN = (temp8 & 0x80) != 0;");
w.WriteLine(Spaces + "FlagV = (temp8 & 0x40) != 0;");
w.WriteLine(Spaces + "FlagZ = (temp8 & value8) == 0;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TSX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "X = S;");
w.WriteLine(Spaces + SetNZ("X"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TXA(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "A = X;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TXS(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "S = X;");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TYA(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "A = Y;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void RMB(OpcodeInfo op, TextWriter w, int bit)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = ReadMemory(value16);");
w.WriteLine(Spaces + "value8 &= 0x{0:X2};", (byte)(~(1 << bit)));
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void SMB(OpcodeInfo op, TextWriter w, int bit)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = ReadMemory(value16);");
w.WriteLine(Spaces + "value8 |= 0x{0:X2};",(1<<bit));
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + "PendingCycles -= {0};", op.Cycles);
}
private void TAI(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "if (InBlockTransfer == false)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " InBlockTransfer = true;");
w.WriteLine(Spaces + " btFrom = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btTo = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btLen = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btAlternator = 0;");
w.WriteLine(Spaces + " PendingCycles -= 14;");
w.WriteLine(Spaces + " PC -= 7;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "if (btLen-- != 0)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " WriteMemory(btTo++, ReadMemory((ushort)(btFrom + btAlternator)));");
w.WriteLine(Spaces + " btAlternator ^= 1;");
w.WriteLine(Spaces + " PendingCycles -= 6;");
w.WriteLine(Spaces + " PC--;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "InBlockTransfer = false;");
w.WriteLine(Spaces + "PendingCycles -= 3;");
w.WriteLine(Spaces + "PC += 6;");
}
private void TIA(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "if (InBlockTransfer == false)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " InBlockTransfer = true;");
w.WriteLine(Spaces + " btFrom = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btTo = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btLen = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btAlternator = 0;");
w.WriteLine(Spaces + " PendingCycles -= 14;");
w.WriteLine(Spaces + " PC -= 7;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "if (btLen-- != 0)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " WriteMemory((ushort)(btTo+btAlternator), ReadMemory(btFrom++));");
w.WriteLine(Spaces + " btAlternator ^= 1;");
w.WriteLine(Spaces + " PendingCycles -= 6;");
w.WriteLine(Spaces + " PC--;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "InBlockTransfer = false;");
w.WriteLine(Spaces + "PendingCycles -= 3;");
w.WriteLine(Spaces + "PC += 6;");
}
private void TII(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "if (InBlockTransfer == false)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " InBlockTransfer = true;");
w.WriteLine(Spaces + " btFrom = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btTo = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btLen = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " PendingCycles -= 14;");
w.WriteLine(Spaces + " PC -= 7;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "if (btLen-- != 0)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " WriteMemory(btTo++, ReadMemory(btFrom++));");
w.WriteLine(Spaces + " PendingCycles -= 6;");
w.WriteLine(Spaces + " PC--;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "InBlockTransfer = false;");
w.WriteLine(Spaces + "PendingCycles -= 3;");
w.WriteLine(Spaces + "PC += 6;");
}
private void TIN(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "if (InBlockTransfer == false)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " InBlockTransfer = true;");
w.WriteLine(Spaces + " btFrom = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btTo = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btLen = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " PendingCycles -= 14;");
w.WriteLine(Spaces + " PC -= 7;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "if (btLen-- != 0)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " WriteMemory(btTo, ReadMemory(btFrom++));");
w.WriteLine(Spaces + " PendingCycles -= 6;");
w.WriteLine(Spaces + " PC--;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "InBlockTransfer = false;");
w.WriteLine(Spaces + "PendingCycles -= 3;");
w.WriteLine(Spaces + "PC += 6;");
}
private void TDD(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "if (InBlockTransfer == false)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " InBlockTransfer = true;");
w.WriteLine(Spaces + " btFrom = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btTo = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " btLen = ReadWord(PC); PC += 2;");
w.WriteLine(Spaces + " PendingCycles -= 14;");
w.WriteLine(Spaces + " PC -= 7;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "if (btLen-- != 0)");
w.WriteLine(Spaces + "{");
w.WriteLine(Spaces + " WriteMemory(btTo--, ReadMemory(btFrom--));");
w.WriteLine(Spaces + " PendingCycles -= 6;");
w.WriteLine(Spaces + " PC--;");
w.WriteLine(Spaces + " break;");
w.WriteLine(Spaces + "}");
w.WriteLine();
w.WriteLine(Spaces + "InBlockTransfer = false;");
w.WriteLine(Spaces + "PendingCycles -= 3;");
w.WriteLine(Spaces + "PC += 6;");
}
}
}

View File

@ -1,663 +0,0 @@
using System;
using System.IO;
namespace M6502
{
public enum AddrMode
{
Implicit,
Accumulator,
Immediate,
ZeroPage,
ZeroPageX,
ZeroPageY,
Absolute,
AbsoluteX,
AbsoluteX_P, //* page-crossing penalty
AbsoluteY,
AbsoluteY_P, //* page-crossing penalty
Indirect,
IndirectX,
IndirectY,
IndirectY_P, //* page-crossing penalty
Relative
}
public class OpcodeInfo
{
public string Instruction;
public AddrMode AddressMode;
public int Cycles;
public int Size
{
get
{
switch (AddressMode)
{
case AddrMode.Implicit: return 1;
case AddrMode.Accumulator: return 1;
case AddrMode.Immediate: return 2;
case AddrMode.ZeroPage: return 2;
case AddrMode.ZeroPageX: return 2;
case AddrMode.ZeroPageY: return 2;
case AddrMode.Absolute: return 3;
case AddrMode.AbsoluteX: return 3;
case AddrMode.AbsoluteX_P: return 3;
case AddrMode.AbsoluteY: return 3;
case AddrMode.AbsoluteY_P: return 3;
case AddrMode.Indirect: return 3;
case AddrMode.IndirectX: return 2;
case AddrMode.IndirectY: return 2;
case AddrMode.IndirectY_P: return 2;
case AddrMode.Relative: return 2;
default:
return -1;
}
}
}
public override string ToString()
{
switch (AddressMode)
{
case AddrMode.Implicit: return Instruction;
case AddrMode.Accumulator: return Instruction+" A";
case AddrMode.Immediate: return Instruction+" #nn";
case AddrMode.ZeroPage: return Instruction+" zp";
case AddrMode.ZeroPageX: return Instruction + " zp,X";
case AddrMode.ZeroPageY: return Instruction + " zp,Y";
case AddrMode.Absolute: return Instruction + " addr";
case AddrMode.AbsoluteX: return Instruction + " addr,X";
case AddrMode.AbsoluteX_P: return Instruction + " addr,X*";
case AddrMode.AbsoluteY: return Instruction + " addr,Y";
case AddrMode.AbsoluteY_P: return Instruction + " addr,Y*";
case AddrMode.Indirect: return Instruction + " (addr)";
case AddrMode.IndirectX: return Instruction + " (addr,X)";
case AddrMode.IndirectY: return Instruction + " (addr),Y";
case AddrMode.IndirectY_P: return Instruction + " (addr),Y*";
case AddrMode.Relative: return Instruction + " +/-rel";
default: return Instruction;
}
}
}
public partial class CoreGenerator
{
public OpcodeInfo[] Opcodes = new OpcodeInfo[256];
// NOTE: page is 256 bytes.
public void InitOpcodeTable()
{
// Add with Carry
Set(0x69, "ADC", AddrMode.Immediate, 2);
Set(0x65, "ADC", AddrMode.ZeroPage , 3);
Set(0x75, "ADC", AddrMode.ZeroPageX, 4);
Set(0x6D, "ADC", AddrMode.Absolute , 4);
Set(0x7D, "ADC", AddrMode.AbsoluteX_P, 4);
Set(0x79, "ADC", AddrMode.AbsoluteY_P, 4);
Set(0x61, "ADC", AddrMode.IndirectX, 6);
Set(0x71, "ADC", AddrMode.IndirectY_P, 5);
// AND
Set(0x29, "AND", AddrMode.Immediate, 2);
Set(0x25, "AND", AddrMode.ZeroPage , 3);
Set(0x35, "AND", AddrMode.ZeroPageX, 4);
Set(0x2D, "AND", AddrMode.Absolute , 4);
Set(0x3D, "AND", AddrMode.AbsoluteX_P, 4);
Set(0x39, "AND", AddrMode.AbsoluteY_P, 4);
Set(0x21, "AND", AddrMode.IndirectX, 6);
Set(0x31, "AND", AddrMode.IndirectY_P, 5);
// Arithmatic Shift Left
Set(0x0A, "ASL", AddrMode.Accumulator, 2);
Set(0x06, "ASL", AddrMode.ZeroPage , 5);
Set(0x16, "ASL", AddrMode.ZeroPageX, 6);
Set(0x0E, "ASL", AddrMode.Absolute , 6);
Set(0x1E, "ASL", AddrMode.AbsoluteX, 7);
// BIT
Set(0x24, "BIT", AddrMode.ZeroPage, 3);
Set(0x2C, "BIT", AddrMode.Absolute, 4);
// Branch instructions
Set(0x10, "BPL", AddrMode.Relative, 2); // Branch on Plus
Set(0x30, "BMI", AddrMode.Relative, 2); // Branch on Minus
Set(0x50, "BVC", AddrMode.Relative, 2); // Branch on Overflow Clear
Set(0x70, "BVS", AddrMode.Relative, 2); // Branch on Overflow Set
Set(0x90, "BCC", AddrMode.Relative, 2); // Branch on Carry Clear
Set(0xB0, "BCS", AddrMode.Relative, 2); // Branch on Carry Set
Set(0xD0, "BNE", AddrMode.Relative, 2); // Branch on Not Equal
Set(0xF0, "BEQ", AddrMode.Relative, 2); // Branch on Equal
// CPU Break
Set(0x00, "BRK", AddrMode.Implicit, 7);
// Compare accumulator
Set(0xC9, "CMP", AddrMode.Immediate, 2);
Set(0xC5, "CMP", AddrMode.ZeroPage , 3);
Set(0xD5, "CMP", AddrMode.ZeroPageX, 4);
Set(0xCD, "CMP", AddrMode.Absolute , 4);
Set(0xDD, "CMP", AddrMode.AbsoluteX_P, 4);
Set(0xD9, "CMP", AddrMode.AbsoluteY_P, 4);
Set(0xC1, "CMP", AddrMode.IndirectX, 6);
Set(0xD1, "CMP", AddrMode.IndirectY_P, 5);
// Compare X register
Set(0xE0, "CPX", AddrMode.Immediate, 2);
Set(0xE4, "CPX", AddrMode.ZeroPage , 3);
Set(0xEC, "CPX", AddrMode.Absolute , 4);
// Compare Y register
Set(0xC0, "CPY", AddrMode.Immediate, 2);
Set(0xC4, "CPY", AddrMode.ZeroPage , 3);
Set(0xCC, "CPY", AddrMode.Absolute , 4);
// DEC
Set(0xC6, "DEC", AddrMode.ZeroPage , 5);
Set(0xD6, "DEC", AddrMode.ZeroPageX, 6);
Set(0xCE, "DEC", AddrMode.Absolute , 6);
Set(0xDE, "DEC", AddrMode.AbsoluteX, 7);
// Exclusive OR
Set(0x49, "EOR", AddrMode.Immediate, 2);
Set(0x45, "EOR", AddrMode.ZeroPage , 3);
Set(0x55, "EOR", AddrMode.ZeroPageX, 4);
Set(0x4D, "EOR", AddrMode.Absolute , 4);
Set(0x5D, "EOR", AddrMode.AbsoluteX_P, 4);
Set(0x59, "EOR", AddrMode.AbsoluteY_P, 4);
Set(0x41, "EOR", AddrMode.IndirectX, 6);
Set(0x51, "EOR", AddrMode.IndirectY_P, 5);
// Flag Instructions
Set(0x18, "CLC", AddrMode.Implicit, 2); // Clear Carry
Set(0x38, "SEC", AddrMode.Implicit, 2); // Set Carry
Set(0x58, "CLI", AddrMode.Implicit, 2); // Clear Interrupt
Set(0x78, "SEI", AddrMode.Implicit, 2); // Set Interrupt
Set(0xB8, "CLV", AddrMode.Implicit, 2); // Clear Overflow
Set(0xD8, "CLD", AddrMode.Implicit, 2); // Clear Decimal
Set(0xF8, "SED", AddrMode.Implicit, 2); // Set Decimal
// INC
Set(0xE6, "INC", AddrMode.ZeroPage , 5);
Set(0xF6, "INC", AddrMode.ZeroPageX, 6);
Set(0xEE, "INC", AddrMode.Absolute , 6);
Set(0xFE, "INC", AddrMode.AbsoluteX, 7);
// Jump
Set(0x4C, "JMP", AddrMode.Absolute, 3);
Set(0x6C, "JMP", AddrMode.Indirect, 5);
// Jump to Subroutine
Set(0x20, "JSR", AddrMode.Absolute, 6);
// Load Accumulator
Set(0xA9, "LDA", AddrMode.Immediate, 2);
Set(0xA5, "LDA", AddrMode.ZeroPage , 3);
Set(0xB5, "LDA", AddrMode.ZeroPageX, 4);
Set(0xAD, "LDA", AddrMode.Absolute , 4);
Set(0xBD, "LDA", AddrMode.AbsoluteX_P, 4);
Set(0xB9, "LDA", AddrMode.AbsoluteY_P, 4);
Set(0xA1, "LDA", AddrMode.IndirectX, 6);
Set(0xB1, "LDA", AddrMode.IndirectY_P, 5);
// Load X register
Set(0xA2, "LDX", AddrMode.Immediate, 2);
Set(0xA6, "LDX", AddrMode.ZeroPage , 3);
Set(0xB6, "LDX", AddrMode.ZeroPageY, 4);
Set(0xAE, "LDX", AddrMode.Absolute , 4);
Set(0xBE, "LDX", AddrMode.AbsoluteY_P, 4);
// Load Y register
Set(0xA0, "LDY", AddrMode.Immediate, 2);
Set(0xA4, "LDY", AddrMode.ZeroPage , 3);
Set(0xB4, "LDY", AddrMode.ZeroPageX, 4);
Set(0xAC, "LDY", AddrMode.Absolute , 4);
Set(0xBC, "LDY", AddrMode.AbsoluteX_P, 4);
// Logical Shift Right
Set(0x4A, "LSR", AddrMode.Accumulator, 2);
Set(0x46, "LSR", AddrMode.ZeroPage , 5);
Set(0x56, "LSR", AddrMode.ZeroPageX, 6);
Set(0x4E, "LSR", AddrMode.Absolute , 6);
Set(0x5E, "LSR", AddrMode.AbsoluteX, 7);
// No Operation
Set(0xEA, "NOP", AddrMode.Implicit, 2);
// Illegal NOPs
Set(0x1A, "NOP", AddrMode.Implicit, 2);
Set(0x3A, "NOP", AddrMode.Implicit, 2);
Set(0x5A, "NOP", AddrMode.Implicit, 2);
Set(0x7A, "NOP", AddrMode.Implicit, 2);
Set(0xDA, "NOP", AddrMode.Implicit, 2);
Set(0xFA, "NOP", AddrMode.Implicit, 2);
Set(0x80, "NOP", AddrMode.Immediate, 2);
Set(0x82, "NOP", AddrMode.Immediate, 2);
Set(0x89, "NOP", AddrMode.Immediate, 2);
Set(0xC2, "NOP", AddrMode.Immediate, 2);
Set(0xE2, "NOP", AddrMode.Immediate, 2);
Set(0x04, "NOP", AddrMode.ZeroPage, 3);
Set(0x44, "NOP", AddrMode.ZeroPage, 3);
Set(0x64, "NOP", AddrMode.ZeroPage, 3);
Set(0x14, "NOP", AddrMode.ZeroPageX, 4);
Set(0x34, "NOP", AddrMode.ZeroPageX, 4);
Set(0x54, "NOP", AddrMode.ZeroPageX, 4);
Set(0x74, "NOP", AddrMode.ZeroPageX, 4);
Set(0xD4, "NOP", AddrMode.ZeroPageX, 4);
Set(0xF4, "NOP", AddrMode.ZeroPageX, 4);
//do the following issue a read or write? if so, we need to emulate with another instruction
Set(0x0C, "NOP", AddrMode.Indirect, 4);
Set(0x1C, "NOP", AddrMode.IndirectX, 4);
Set(0x3C, "NOP", AddrMode.IndirectX, 4);
Set(0x5C, "NOP", AddrMode.IndirectX, 4);
Set(0x7C, "NOP", AddrMode.IndirectX, 4);
Set(0xDC, "NOP", AddrMode.IndirectX, 4);
Set(0xFC, "NOP", AddrMode.IndirectX, 4);
//undocumented opcodes
//RLA:
//Set(0x23, "RLA", AddrMode.IndirectX, 8);
// Bitwise OR with Accumulator
Set(0x09, "ORA", AddrMode.Immediate, 2);
Set(0x05, "ORA", AddrMode.ZeroPage , 3);
Set(0x15, "ORA", AddrMode.ZeroPageX, 4);
Set(0x0D, "ORA", AddrMode.Absolute , 4);
Set(0x1D, "ORA", AddrMode.AbsoluteX_P, 4);
Set(0x19, "ORA", AddrMode.AbsoluteY_P, 4);
Set(0x01, "ORA", AddrMode.IndirectX, 6);
Set(0x11, "ORA", AddrMode.IndirectY_P, 5);
// Register instructions
Set(0xAA, "TAX", AddrMode.Implicit, 2); // Transfer A to X
Set(0x8A, "TXA", AddrMode.Implicit, 2); // Transfer X to A
Set(0xCA, "DEX", AddrMode.Implicit, 2); // DEC X
Set(0xE8, "INX", AddrMode.Implicit, 2); // INC X
Set(0xA8, "TAY", AddrMode.Implicit, 2); // Transfer A to Y
Set(0x98, "TYA", AddrMode.Implicit, 2); // Transfer Y to A
Set(0x88, "DEY", AddrMode.Implicit, 2); // DEC Y
Set(0xC8, "INY", AddrMode.Implicit, 2); // INC Y
// Rotate Left
Set(0x2A, "ROL", AddrMode.Accumulator, 2);
Set(0x26, "ROL", AddrMode.ZeroPage , 5);
Set(0x36, "ROL", AddrMode.ZeroPageX, 6);
Set(0x2E, "ROL", AddrMode.Absolute , 6);
Set(0x3E, "ROL", AddrMode.AbsoluteX, 7);
// Rotate Right
Set(0x6A, "ROR", AddrMode.Accumulator, 2);
Set(0x66, "ROR", AddrMode.ZeroPage , 5);
Set(0x76, "ROR", AddrMode.ZeroPageX, 6);
Set(0x6E, "ROR", AddrMode.Absolute , 6);
Set(0x7E, "ROR", AddrMode.AbsoluteX, 7);
// Return from Interrupt
Set(0x40, "RTI", AddrMode.Implicit, 6);
// Return from Subroutine
Set(0x60, "RTS", AddrMode.Implicit, 6);
// Subtract with Carry
Set(0xE9, "SBC", AddrMode.Immediate, 2);
Set(0xE5, "SBC", AddrMode.ZeroPage , 3);
Set(0xF5, "SBC", AddrMode.ZeroPageX, 4);
Set(0xED, "SBC", AddrMode.Absolute , 4);
Set(0xFD, "SBC", AddrMode.AbsoluteX_P, 4);
Set(0xF9, "SBC", AddrMode.AbsoluteY_P, 4);
Set(0xE1, "SBC", AddrMode.IndirectX, 6);
Set(0xF1, "SBC", AddrMode.IndirectY_P, 5);
// Store Accumulator
Set(0x85, "STA", AddrMode.ZeroPage , 3);
Set(0x95, "STA", AddrMode.ZeroPageX, 4);
Set(0x8D, "STA", AddrMode.Absolute , 4);
Set(0x9D, "STA", AddrMode.AbsoluteX, 5);
Set(0x99, "STA", AddrMode.AbsoluteY, 5);
Set(0x81, "STA", AddrMode.IndirectX, 6);
Set(0x91, "STA", AddrMode.IndirectY, 6);
// Stack instructions
Set(0x9A, "TXS", AddrMode.Implicit, 2); // Transfer X to Stack
Set(0xBA, "TSX", AddrMode.Implicit, 2); // Transfer Stack to X
Set(0x48, "PHA", AddrMode.Implicit, 3); // Push A
Set(0x68, "PLA", AddrMode.Implicit, 4); // Pull A
Set(0x08, "PHP", AddrMode.Implicit, 3); // Push P
Set(0x28, "PLP", AddrMode.Implicit, 4); // Pull P
// Store X register
Set(0x86, "STX", AddrMode.ZeroPage , 3);
Set(0x96, "STX", AddrMode.ZeroPageY, 4);
Set(0x8E, "STX", AddrMode.Absolute , 4);
// Store Y register
Set(0x84, "STY", AddrMode.ZeroPage , 3);
Set(0x94, "STY", AddrMode.ZeroPageX, 4);
Set(0x8C, "STY", AddrMode.Absolute , 4);
}
private void Set(byte value, string instr, AddrMode addressMode, int cycles)
{
var op = new OpcodeInfo();
op.Instruction = instr;
op.AddressMode = addressMode;
op.Cycles = cycles;
if (Opcodes[value] != null)
throw new Exception("opcode "+value+" already assigned");
Opcodes[value] = op;
}
public void GenerateExecutor(string file)
{
var w = new StreamWriter(file, false);
w.WriteLine("using System;");
w.WriteLine();
w.WriteLine("// Do not modify this file directly! This is GENERATED code.");
w.WriteLine("// Please open the CpuCoreGenerator solution and make your modifications there.");
w.WriteLine();
w.WriteLine("namespace BizHawk.Emulation.Common.Components.M6502");
w.WriteLine("{");
w.WriteLine(" public partial class MOS6502");
w.WriteLine(" {");
w.WriteLine(" public void Execute(int cycles)");
w.WriteLine(" {");
w.WriteLine(" sbyte rel8;");
w.WriteLine(" byte value8, temp8;");
w.WriteLine(" ushort value16, temp16;");
w.WriteLine(" int temp;");
w.WriteLine();
w.WriteLine(" PendingCycles += cycles;");
w.WriteLine(" while (PendingCycles > 0)");
w.WriteLine(" {");
w.WriteLine(" if (NMI)");
w.WriteLine(" {");
w.WriteLine(" TriggerException(ExceptionType.NMI);");
w.WriteLine(" NMI = false;");
w.WriteLine(" }");
w.WriteLine(" if (IRQ && !FlagI)");
w.WriteLine(" {");
w.WriteLine(" if (SEI_Pending)");
w.WriteLine(" FlagI = true;");
w.WriteLine(" TriggerException(ExceptionType.IRQ);");
w.WriteLine(" }");
w.WriteLine(" if (CLI_Pending)");
w.WriteLine(" {");
w.WriteLine(" FlagI = false;");
w.WriteLine(" CLI_Pending = false;");
w.WriteLine(" }");
w.WriteLine(" if (SEI_Pending)");
w.WriteLine(" {");
w.WriteLine(" FlagI = true;");
w.WriteLine(" SEI_Pending = false;");
w.WriteLine(" }");
w.WriteLine(" if(debug) Console.WriteLine(State());");
w.WriteLine("");
w.WriteLine(" ushort this_pc = PC;");
w.WriteLine(" byte opcode = ReadMemory(PC++);");
w.WriteLine(" switch (opcode)");
w.WriteLine(" {");
for (int i = 0; i < 256; i++)
{
if (Opcodes[i] != null)
{
EmulateOpcode(w, i);
}
}
w.WriteLine(" default:");
w.WriteLine(" if(throw_unhandled)");
w.WriteLine(" throw new Exception(String.Format(\"Unhandled opcode: {0:X2}\", opcode));");
w.WriteLine(" break;");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine("}");
w.Close();
}
const string Spaces = " ";
private void EmulateOpcode(TextWriter w, int opcode)
{
var op = Opcodes[opcode];
w.WriteLine(" case 0x{0:X2}: // {1}", opcode, op);
switch (op.Instruction)
{
case "ADC": ADC(op, w); break;
case "AND": AND(op, w); break;
case "ASL": ASL(op, w); break;
case "BCC": Branch(op, w, "C", false); break;
case "BCS": Branch(op, w, "C", true); break;
case "BEQ": Branch(op, w, "Z", true); break;
case "BIT": BIT(op, w); break;
case "BMI": Branch(op, w, "N", true); break;
case "BNE": Branch(op, w, "Z", false); break;
case "BPL": Branch(op, w, "N", false); break;
case "BRK": w.WriteLine(Spaces + "TriggerException(ExceptionType.BRK);"); break;
case "BVC": Branch(op, w, "V", false); break;
case "BVS": Branch(op, w, "V", true); break;
case "CLC": CLC(op, w); break;
case "CLD": CLD(op, w); break;
case "CLI": CLI(op, w); break;
case "CLV": CLV(op, w); break;
case "CMP": CMP_reg(op, w, "A"); break;
case "CPX": CMP_reg(op, w, "X"); break;
case "CPY": CMP_reg(op, w, "Y"); break;
case "DEC": DEC(op, w); break;
case "DEX": DEX(op, w); break;
case "DEY": DEY(op, w); break;
case "EOR": EOR(op, w); break;
case "INC": INC(op, w); break;
case "INX": INX(op, w); break;
case "INY": INY(op, w); break;
case "JMP": JMP(op, w); break;
case "JSR": JSR(op, w); break;
case "LDA": LDA(op, w); break;
case "LDX": LDX(op, w); break;
case "LDY": LDY(op, w); break;
case "LSR": LSR(op, w); break;
case "NOP": NOP(op, w); break;
case "ORA": ORA(op, w); break;
case "PHA": PHA(op, w); break;
case "PHP": PHP(op, w); break;
case "PLA": PLA(op, w); break;
case "PLP": PLP(op, w); break;
case "ROL": ROL(op, w); break;
case "ROR": ROR(op, w); break;
case "RTI": RTI(op, w); break;
case "RTS": RTS(op, w); break;
case "SBC": SBC(op, w); break;
case "SEC": SEC(op, w); break;
case "SED": SED(op, w); break;
case "SEI": SEI(op, w); break;
case "STA": STA(op, w); break;
case "STX": STX(op, w); break;
case "STY": STY(op, w); break;
case "TAX": TAX(op, w); break;
case "TAY": TAY(op, w); break;
case "TSX": TSX(op, w); break;
case "TXA": TXA(op, w); break;
case "TYA": TYA(op, w); break;
case "TXS": TXS(op, w); break;
}
w.WriteLine(Spaces+"break;");
}
private void GetValue8(OpcodeInfo op, TextWriter w, string dest)
{
switch (op.AddressMode)
{
case AddrMode.Immediate:
w.WriteLine(Spaces + dest + " = ReadMemory(PC++);"); break;
case AddrMode.ZeroPage:
w.WriteLine(Spaces + dest + " = ReadMemory(ReadMemory(PC++));"); break;
case AddrMode.ZeroPageX:
w.WriteLine(Spaces + dest + " = ReadMemory((byte)(ReadMemory(PC++)+X));"); break;
case AddrMode.ZeroPageY:
w.WriteLine(Spaces + dest + " = ReadMemory((byte)(ReadMemory(PC++)+Y));"); break;
case AddrMode.Absolute:
w.WriteLine(Spaces + dest + " = ReadMemory(ReadWord(PC)); PC += 2;"); break;
case AddrMode.AbsoluteX_P:
w.WriteLine(Spaces + "temp16 = ReadWord(PC);");
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+X));");
w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) ");
w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.AbsoluteX:
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+X));");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.AbsoluteY_P:
w.WriteLine(Spaces + "temp16 = ReadWord(PC);");
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+Y));");
w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) ");
w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.AbsoluteY:
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(ReadWord(PC)+Y));");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.IndirectX:
w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+X)));"); break;
case AddrMode.IndirectY:
w.WriteLine(Spaces + dest + " = ReadMemory(ReadWordPageWrap((byte)(ReadMemory(PC++)+Y)));"); break;
case AddrMode.IndirectY_P:
w.WriteLine(Spaces + "temp16 = ReadWordPageWrap(ReadMemory(PC++));");
w.WriteLine(Spaces + dest + " = ReadMemory((ushort)(temp16+Y));");
w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) ");
w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }");
break;
}
}
private void GetAddress(OpcodeInfo op, TextWriter w, string dest)
{
// TODO it APPEARS that the +1 opcode penalty applies to all AbsoluteX, AbsoluteY, and IndirectY
// but this is not completely clear. the doc has some exceptions, but are they real?
switch (op.AddressMode)
{
case AddrMode.ZeroPage:
w.WriteLine(Spaces + dest + " = ReadMemory(PC++);"); break;
case AddrMode.ZeroPageX:
w.WriteLine(Spaces + dest + " = (byte)(ReadMemory(PC++)+X);"); break;
case AddrMode.ZeroPageY:
w.WriteLine(Spaces + dest + " = (byte)(ReadMemory(PC++)+Y);"); break;
case AddrMode.Absolute:
w.WriteLine(Spaces + dest + " = ReadWord(PC); PC += 2;"); break;
case AddrMode.AbsoluteX:
w.WriteLine(Spaces + dest + " = (ushort)(ReadWord(PC)+X);");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.AbsoluteX_P:
w.WriteLine(Spaces + "temp16 = ReadWord(PC);");
w.WriteLine(Spaces + dest + " = (ushort)(temp16+X);");
w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16 + X) & 0xFF00)) ");
w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.AbsoluteY:
w.WriteLine(Spaces + dest + " = (ushort)(ReadWord(PC)+Y);");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.AbsoluteY_P:
w.WriteLine(Spaces + "temp16 = ReadWord(PC);");
w.WriteLine(Spaces + dest + " = (ushort)(temp16+Y);");
w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16 + Y) & 0xFF00)) ");
w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }");
w.WriteLine(Spaces + "PC += 2;");
break;
case AddrMode.IndirectX:
w.WriteLine(Spaces + "temp8 = (byte)(ReadMemory(PC++) + X);");
w.WriteLine(Spaces + dest + " = ReadWordPageWrap(temp8);");
break;
case AddrMode.IndirectY:
w.WriteLine(Spaces + "temp16 = ReadWordPageWrap(ReadMemory(PC++));");
w.WriteLine(Spaces + dest + " = (ushort)(temp16+Y);");
break;
case AddrMode.IndirectY_P:
w.WriteLine(Spaces + "temp16 = ReadWordPageWrap(ReadMemory(PC++));");
w.WriteLine(Spaces + dest + " = (ushort)(temp16+Y);");
w.WriteLine(Spaces + "if ((temp16 & 0xFF00) != ((temp16+Y) & 0xFF00)) ");
w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }");
break;
case AddrMode.Relative:
w.WriteLine(Spaces + "rel8 = (sbyte)ReadMemory(PC++);");
w.WriteLine(Spaces + dest +" = (ushort)(PC+rel8);");
break;
}
}
public void GenerateDisassembler(string file)
{
var w = new StreamWriter(file, false);
w.WriteLine("using System;");
w.WriteLine();
w.WriteLine("// Do not modify this file directly! This is GENERATED code.");
w.WriteLine("// Please open the CpuCoreGenerator solution and make your modifications there.");
w.WriteLine();
w.WriteLine("namespace BizHawk.Emulation.Common.Components.M6502");
w.WriteLine("{");
w.WriteLine(" public partial class MOS6502");
w.WriteLine(" {");
w.WriteLine(" public string Disassemble(ushort pc, out int bytesToAdvance)");
w.WriteLine(" {");
w.WriteLine(" byte op = ReadMemory(pc);");
w.WriteLine(" switch (op)");
w.WriteLine(" {");
for (int i = 0; i < 256; i++)
{
if (Opcodes[i] != null)
DisassembleOpcode(w,i);
}
w.WriteLine(" }");
w.WriteLine(" bytesToAdvance = 1;");
w.WriteLine(" return \"???\";");
w.WriteLine(" }");
w.WriteLine(" }");
w.WriteLine("}");
w.Close();
}
private void DisassembleOpcode(TextWriter w, int i)
{
var op = Opcodes[i];
w.Write(" case 0x{0:X2}: ", i);
string mstr;
switch (op.AddressMode)
{
case AddrMode.Implicit: mstr = "\""+op.Instruction+"\""; break;
case AddrMode.Accumulator: mstr = "\"" + op.Instruction + " A\""; break;
case AddrMode.Immediate: mstr = "string.Format(\""+op.Instruction+" #${0:X2}\", ReadMemory(++pc))"; break;
case AddrMode.ZeroPage: mstr = "string.Format(\"" + op.Instruction + " ${0:X2}\", ReadMemory(++pc))"; break;
case AddrMode.ZeroPageX: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},X\", ReadMemory(++pc))"; break;
case AddrMode.ZeroPageY: mstr = "string.Format(\"" + op.Instruction + " ${0:X2},Y\", ReadMemory(++pc))"; break;
case AddrMode.Absolute: mstr = "string.Format(\"" + op.Instruction + " ${0:X4}\", ReadWord(++pc))"; break;
case AddrMode.AbsoluteX: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},X\", ReadWord(++pc))"; break;
case AddrMode.AbsoluteX_P: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},X *\", ReadWord(++pc))"; break;
case AddrMode.AbsoluteY: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},Y\", ReadWord(++pc))"; break;
case AddrMode.AbsoluteY_P: mstr = "string.Format(\"" + op.Instruction + " ${0:X4},Y *\", ReadWord(++pc))"; break;
case AddrMode.Indirect: mstr = "string.Format(\"" + op.Instruction + " (${0:X4})\", ReadWord(++pc))"; break;
case AddrMode.IndirectX: mstr = "string.Format(\"" + op.Instruction + " (${0:X2},X)\", ReadMemory(++pc))"; break;
case AddrMode.IndirectY: mstr = "string.Format(\"" + op.Instruction + " (${0:X2}),Y\", ReadMemory(++pc))"; break;
case AddrMode.IndirectY_P: mstr = "string.Format(\"" + op.Instruction + " (${0:X2}),Y *\", ReadMemory(++pc))"; break;
case AddrMode.Relative: mstr = "string.Format(\"" + op.Instruction + " ${0:X4}\", pc+2+(sbyte)ReadMemory(++pc))"; break;
default: mstr = @"""?"""; break;
}
// BRK is 2-byte, but it is rarely used. So I don't care about it.
w.Write("bytesToAdvance = {0}; ", op.Size);
w.WriteLine("return " + mstr + ";");
}
}
}

View File

@ -1,417 +0,0 @@
using System.IO;
namespace M6502
{
public partial class CoreGenerator
{
private string SetNZ(string val)
{
return "P = (byte)((P & 0x7D) | TableNZ[" + val + "]);"; // NES version
//return "P = (byte)((P & 0x5D) | TableNZ[" + val + "]);"; // PCE version
}
private void ADC(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "temp = value8 + A + (FlagC ? 1 : 0);");
w.WriteLine(Spaces + "FlagV = (~(A ^ value8) & (A ^ temp) & 0x80) != 0;");
w.WriteLine(Spaces + "FlagC = temp > 0xFF;");
w.WriteLine(Spaces + "A = (byte)temp;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void AND(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "A &= value8;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void ASL(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode == AddrMode.Accumulator)
{
w.WriteLine(Spaces + "FlagC = (A & 0x80) != 0;");
w.WriteLine(Spaces + "A = (byte) (A << 1);");
w.WriteLine(Spaces + SetNZ("A"));
} else {
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = ReadMemory(value16);");
w.WriteLine(Spaces + "FlagC = (value8 & 0x80) != 0;");
w.WriteLine(Spaces + "value8 = (byte)(value8 << 1);");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + SetNZ("value8"));
}
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void Branch(OpcodeInfo op, TextWriter w, string flag, bool cond)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "if (Flag"+flag+" == "+cond.ToString().ToLower()+") {");
w.WriteLine(Spaces + " PendingCycles--; TotalExecutedCycles++;");
w.WriteLine(Spaces + " if ((PC & 0xFF00) != (value16 & 0xFF00)) ");
w.WriteLine(Spaces + " { PendingCycles--; TotalExecutedCycles++; }");
w.WriteLine(Spaces + " PC = value16;");
w.WriteLine(Spaces + "}");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void BIT(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "FlagN = (value8 & 0x80) != 0;");
w.WriteLine(Spaces + "FlagV = (value8 & 0x40) != 0;");
w.WriteLine(Spaces + "FlagZ = (A & value8) == 0;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void CLC(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagC = false;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void CLD(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagD = false;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void CLI(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "//FlagI = false;");
w.WriteLine(Spaces + "CLI_Pending = true;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void CLV(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagV = false;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void CMP_reg(OpcodeInfo op, TextWriter w, string reg)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "value16 = (ushort) (" + reg + " - value8);");
w.WriteLine(Spaces + "FlagC = (" + reg + " >= value8);");
w.WriteLine(Spaces + SetNZ("(byte)value16"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void DEC(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = (byte)(ReadMemory(value16) - 1);");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + SetNZ("value8"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void DEX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + SetNZ("--X"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void DEY(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + SetNZ("--Y"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void EOR(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "A ^= value8;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void INC(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = (byte)(ReadMemory(value16) + 1);");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + SetNZ("value8"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void INX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + SetNZ("++X"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void INY(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + SetNZ("++Y"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void JMP(OpcodeInfo op, TextWriter w)
{
switch (op.AddressMode)
{
case AddrMode.Absolute: w.WriteLine(Spaces+"PC = ReadWord(PC);"); break;
case AddrMode.Indirect: w.WriteLine(Spaces+"PC = ReadWordPageWrap(ReadWord(PC));"); break;
}
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void JSR(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "temp16 = (ushort)(PC+1);");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x100), (byte)(temp16 >> 8));");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x100), (byte)temp16);");
w.WriteLine(Spaces + "PC = ReadWord(PC);");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void LDA(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "A");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void LDX(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "X");
w.WriteLine(Spaces + SetNZ("X"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void LDY(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "Y");
w.WriteLine(Spaces + SetNZ("Y"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void LSR(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode == AddrMode.Accumulator)
{
w.WriteLine(Spaces + "FlagC = (A & 1) != 0;");
w.WriteLine(Spaces + "A = (byte) (A >> 1);");
w.WriteLine(Spaces + SetNZ("A"));
} else {
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = ReadMemory(value16);");
w.WriteLine(Spaces + "FlagC = (value8 & 1) != 0;");
w.WriteLine(Spaces + "value8 = (byte)(value8 >> 1);");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + SetNZ("value8"));
}
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void NOP(OpcodeInfo op, TextWriter w)
{
// This code is quite insufficient, but at least, we have to increment program counter appropriately.
// For immediate addressing mode, it will be correct, and it will fix desyncs of "Puzznic (J)" and "Puzznic (U)".
// For other addressing modes, I don't know whether they access memory, so further investigation will be needed.
if (op.Size > 1)
w.WriteLine(Spaces+"PC += {0};", op.Size-1);
w.WriteLine(Spaces+"PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void ORA(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "A |= value8;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void PHA(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x100), A);");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void PHP(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagB = true; //why would it do this?? how weird");
w.WriteLine(Spaces + "WriteMemory((ushort)(S-- + 0x100), P);");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void PLA(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "A = ReadMemory((ushort)(++S + 0x100));");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void PLP(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "//handle I flag differently. sort of a sloppy way to do the job, but it does finish it off.");
w.WriteLine(Spaces + "value8 = ReadMemory((ushort)(++S + 0x100));");
w.WriteLine(Spaces + "if ((value8 & 0x04) != 0 && !FlagI)");
w.WriteLine(Spaces + "\tSEI_Pending = true;");
w.WriteLine(Spaces + "if ((value8 & 0x04) == 0 && FlagI)");
w.WriteLine(Spaces + "\tCLI_Pending = true;");
w.WriteLine(Spaces + "value8 &= unchecked((byte)~0x04);");
w.WriteLine(Spaces + "P &= 0x04;");
w.WriteLine(Spaces + "P |= value8;");
w.WriteLine("FlagT = true;//this seems wrong");//this seems wrong
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void ROL(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode == AddrMode.Accumulator)
{
w.WriteLine(Spaces + "temp8 = A;");
w.WriteLine(Spaces + "A = (byte)((A << 1) | (P & 1));");
w.WriteLine(Spaces + "FlagC = (temp8 & 0x80) != 0;");
w.WriteLine(Spaces + SetNZ("A"));
}
else
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = temp8 = ReadMemory(value16);");
w.WriteLine(Spaces + "value8 = (byte)((value8 << 1) | (P & 1));");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + "FlagC = (temp8 & 0x80) != 0;");
w.WriteLine(Spaces + SetNZ("value8"));
}
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void ROR(OpcodeInfo op, TextWriter w)
{
if (op.AddressMode == AddrMode.Accumulator)
{
w.WriteLine(Spaces + "temp8 = A;");
w.WriteLine(Spaces + "A = (byte)((A >> 1) | ((P & 1)<<7));");
w.WriteLine(Spaces + "FlagC = (temp8 & 1) != 0;");
w.WriteLine(Spaces + SetNZ("A"));
}
else
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "value8 = temp8 = ReadMemory(value16);");
w.WriteLine(Spaces + "value8 = (byte)((value8 >> 1) | ((P & 1)<<7));");
w.WriteLine(Spaces + "WriteMemory(value16, value8);");
w.WriteLine(Spaces + "FlagC = (temp8 & 1) != 0;");
w.WriteLine(Spaces + SetNZ("value8"));
}
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void RTI(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "P = ReadMemory((ushort)(++S + 0x100));");
w.WriteLine("FlagT = true;// this seems wrong");//this seems wrong
w.WriteLine(Spaces + "PC = ReadMemory((ushort)(++S + 0x100));");
w.WriteLine(Spaces + "PC |= (ushort)(ReadMemory((ushort)(++S + 0x100)) << 8);");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void RTS(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "PC = ReadMemory((ushort)(++S + 0x100));");
w.WriteLine(Spaces + "PC |= (ushort)(ReadMemory((ushort)(++S + 0x100)) << 8);");
w.WriteLine(Spaces + "PC++;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void SBC(OpcodeInfo op, TextWriter w)
{
GetValue8(op, w, "value8");
w.WriteLine(Spaces + "temp = A - value8 - (FlagC?0:1);");
w.WriteLine(Spaces + "FlagV = ((A ^ value8) & (A ^ temp) & 0x80) != 0;");
w.WriteLine(Spaces + "FlagC = temp >= 0;");
w.WriteLine(Spaces + "A = (byte)temp;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void SEC(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagC = true;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void SED(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "FlagD = true;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void SEI(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "//FlagI = true;");
w.WriteLine(Spaces + "SEI_Pending = true;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void STA(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "WriteMemory(value16, A);");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void STX(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "WriteMemory(value16, X);");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void STY(OpcodeInfo op, TextWriter w)
{
GetAddress(op, w, "value16");
w.WriteLine(Spaces + "WriteMemory(value16, Y);");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void TAX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "X = A;");
w.WriteLine(Spaces + SetNZ("X"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void TAY(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "Y = A;");
w.WriteLine(Spaces + SetNZ("Y"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void TSX(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "X = S;");
w.WriteLine(Spaces + SetNZ("X"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void TXA(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "A = X;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void TXS(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "S = X;");
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
private void TYA(OpcodeInfo op, TextWriter w)
{
w.WriteLine(Spaces + "A = Y;");
w.WriteLine(Spaces + SetNZ("A"));
w.WriteLine(Spaces + "PendingCycles -= {0}; TotalExecutedCycles += {0};", op.Cycles);
}
}
}

View File

@ -1,17 +0,0 @@
class Program
{
static void Main()
{
//We don't currently use this anymore
//var x = new M6502.CoreGenerator();
//x.InitOpcodeTable();
//x.GenerateDisassembler("../../../BizHawk.Emulation.Common/CPUs/MOS 6502X/Disassembler.cs");
//x.GenerateExecutor("../../../BizHawk.Emulation.Common/CPUs/MOS 6502X/Execute.cs");
var y = new HuC6280.CoreGenerator();
y.InitOpcodeTable();
y.GenerateDisassembler("../../../BizHawk.Emulation.Cores/CPUs/HuC6280/Disassembler.cs");
y.GenerateExecutor("../../../BizHawk.Emulation.Cores/CPUs/HuC6280/Execute.cs");
y.GenerateCDL("../../../BizHawk.Emulation.Cores/CPUs/HuC6280/CDLOpcodes.cs");
}
}

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("M6502CoreGenerator")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("M6502CoreGenerator")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ab5eef8f-50f4-4c39-af46-8c5ba9404c6b")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]