BizHawk/BizHawk.Emulation/CPUs/MC68000/MC68K.cs

239 lines
4.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
// BIG NOTICE!!!!!!
// This is the 68000 core from Sega360.
// IT IS GPL! It is a starter core so I can work on Genesis hardware emulation first.
// This core MUST BE, and WILL BE replaced with new code at a later date.
namespace MC68000
{
public sealed partial class MC68K
{
public int m_PC;
private int m_SR;
private ushort m_IR;
public int[] m_D = new int[8];
public int[] m_A = new int[8];
private int m_Usp;
private int m_Ssp;
private IMemoryController m_Controller;
public long m_Cycles;
private int m_InterruptFlag;
public MC68K(IMemoryController controller)
{
this.m_Controller = controller;
this.BuildOpTable();
}
public void Interrupt(int vector)
{
this.m_InterruptFlag = vector;
}
private void HandleInterrupt()
{
int vector = 24 + this.m_InterruptFlag;
this.m_InterruptFlag = 0;
Trap(vector);
}
public void Reset()
{
this.m_SR = 0x2000;
this.SP = ReadL(0x0);
this.m_PC = ReadL(0x4);
this.m_Cycles = 0;
}
private class OpHistory
{
public int PC;
public Operation Operation;
public OpHistory(int pc, Operation op)
{
this.PC = pc;
this.Operation = op;
}
}
List<OpHistory> m_OpList = new List<OpHistory>(200);
public void Execute(long cycles)
{
this.m_Cycles = 0;
do
{
// if (m_PC == 0x02DD8)
//m_PC = 0x02DD8;
if (this.m_Cycles >= cycles)
{
return;
}
if (this.m_InterruptFlag > 0)
{
HandleInterrupt();
}
//if (this.m_PC == 0x4752)
//{ }
// Fetch
this.m_IR = (ushort)FetchW();
// Decode
Operation op = this.m_OpTable[this.m_IR];
//if (op == null)
//{
// ShowOpList();
//}
//if (m_OpList.Count == m_OpList.Capacity)
//{
// m_OpList.RemoveAt(0);
//}
//m_OpList.Add(new OpHistory(this.m_PC - 2, op));
// Execute
op();
} while (true);
}
public void Step()
{
if (this.m_InterruptFlag > 0)
{
HandleInterrupt();
}
this.m_IR = (ushort)FetchW();
Operation op = this.m_OpTable[this.m_IR];
op();
}
private void ShowOpList()
{
for (int i = 0; i < m_OpList.Count; i++)
{
Console.WriteLine(Convert.ToString(m_OpList[i].PC, 16) + "\t" + m_OpList[i].Operation.Method.Name);
}
}
public bool C // Carry
{
get { return (this.m_SR & 1) > 0; }
set
{
if (value) { this.m_SR |= 1; }
else { this.m_SR &= -2; }
}
}
public bool V // Overflow
{
get { return (this.m_SR & 2) > 0; }
set
{
if (value) { this.m_SR |= 2; }
else { this.m_SR &= -3; }
}
}
public bool Z // Zero
{
get { return (this.m_SR & 4) > 0; }
set
{
if (value) { this.m_SR |= 4; }
else { this.m_SR &= -5; }
}
}
public bool N // Negative
{
get { return (this.m_SR & 8) > 0; }
set
{
if (value) { this.m_SR |= 8; }
else { this.m_SR &= -9; }
}
}
public bool X // Extend
{
get { return (this.m_SR & 16) > 0; }
set
{
if (value) { this.m_SR |= 16; }
else { this.m_SR &= -17; }
}
}
public bool S // Supervisor Mode
{
get { return (this.m_SR & 8192) > 0; }
set
{
if (value) { this.m_SR |= 8192; }
else { this.m_SR &= -8193; }
}
}
private int SP
{
get { return this.m_A[7]; }
set { this.m_A[7] = value; }
}
private bool TestCondition(int cCode)
{
switch (cCode)
{
case 0x0: // T
return true;
case 0x1: // F
return false;
case 0x2: // HI
return !C && !Z;
case 0x3: // LS
return C || Z;
case 0x4: // CC(HI)
return !C;
case 0x5: // CS(LO)
return C;
case 0x6: // NE
return !Z;
case 0x7: // EQ
return Z;
case 0x8: // VC
return !V;
case 0x9: // VS
return V;
case 0xA: // PL
return !N;
case 0xB: // MI
return N;
case 0xC: // GE
return N && V || !N && !V;
case 0xD: // LT
return N && !V || !N && V;
case 0xE: // GT
return N && V && !Z || !N && !V && !Z;
case 0xF: // LE
return Z || N && !V || !N && V;
default:
throw new ArgumentException("Bad condition code");
}
}
}
}