delete extra/external 68k core

This commit is contained in:
beirich 2011-09-27 02:46:23 +00:00
parent 58738c1af3
commit f3dc6068ce
17 changed files with 15 additions and 4407 deletions

View File

@ -191,19 +191,6 @@
<Compile Include="CPUs\HuC6280\Disassembler.cs" />
<Compile Include="CPUs\HuC6280\Execute.cs" />
<Compile Include="CPUs\HuC6280\HuC6280.cs" />
<Compile Include="CPUs\MC68000\Helpers.cs" />
<Compile Include="CPUs\MC68000\IMemoryController.cs" />
<Compile Include="CPUs\MC68000\MC68K.cs" />
<Compile Include="CPUs\MC68000\MemoryAccess.cs" />
<Compile Include="CPUs\MC68000\Operations\BitManipulation.cs" />
<Compile Include="CPUs\MC68000\Operations\DataMovement.cs" />
<Compile Include="CPUs\MC68000\Operations\IntegerArithmetic.cs" />
<Compile Include="CPUs\MC68000\Operations\Logical.cs" />
<Compile Include="CPUs\MC68000\Operations\Multiprocessor.cs" />
<Compile Include="CPUs\MC68000\Operations\ProgramControl.cs" />
<Compile Include="CPUs\MC68000\Operations\ShiftRotate.cs" />
<Compile Include="CPUs\MC68000\Operations\SystemControl.cs" />
<Compile Include="CPUs\MC68000\OpTable.cs" />
<Compile Include="CPUs\MOS 6502\Disassembler.cs" />
<Compile Include="CPUs\MOS 6502\Execute.cs" />
<Compile Include="CPUs\MOS 6502\MOS6502.cs" />

View File

@ -1,130 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public enum ShiftDirection
{
Right = 0,
Left = 1
}
public class Helpers
{
public static int[,] MOVECyclesBW;
public static int[,] MOVECyclesL;
static Helpers()
{
MOVECyclesBW = new int[12,9] {
{ 4, 4, 8, 8, 8, 12, 14, 12, 16 },
{ 4, 4, 8, 8, 8, 12, 14, 12, 16 },
{ 8, 8, 12, 12, 12, 16, 18, 16, 20 },
{ 8, 8, 12, 12, 12, 16, 18, 16, 20 },
{ 10, 10, 14, 14, 14, 18, 20, 18, 22 },
{ 12, 12, 16, 16, 16, 20, 22, 20, 24 },
{ 14, 14, 18, 18, 18, 22, 24, 22, 26 },
{ 12, 12, 16, 16, 16, 20, 22, 20, 24 },
{ 16, 16, 20, 20, 20, 24, 26, 24, 28 },
{ 12, 12, 16, 16, 16, 20, 22, 20, 24 },
{ 14, 14, 18, 18, 18, 22, 24, 22, 26 },
{ 8, 8, 12, 12, 12, 16, 18, 16, 20 }
};
MOVECyclesL = new int[12,9] {
{ 4, 4, 12, 12, 12, 16, 18, 16, 20 },
{ 4, 4, 12, 12, 12, 16, 18, 16, 20 },
{ 12, 12, 20, 20, 20, 24, 26, 24, 28 },
{ 12, 12, 20, 20, 20, 24, 26, 24, 28 },
{ 14, 14, 22, 22, 22, 26, 28, 26, 30 },
{ 16, 16, 24, 24, 24, 28, 30, 28, 32 },
{ 18, 18, 26, 26, 26, 30, 32, 30, 34 },
{ 16, 16, 24, 24, 24, 28, 30, 28, 32 },
{ 20, 20, 28, 28, 28, 32, 34, 32, 36 },
{ 16, 16, 24, 24, 24, 28, 30, 28, 32 },
{ 18, 18, 26, 26, 26, 30, 32, 30, 34 },
{ 12, 12, 20, 20, 20, 24, 26, 24, 28 }
};
}
#region Inject
public static void Inject(ref int register, byte value)
{
register = (register & -0x100) | value;
}
public static void Inject(ref int register, sbyte value)
{
register = (register & -0x100) | (byte)value;
}
public static void Inject(ref int register, ushort value)
{
register = (register & -0x10000) | value;
}
public static void Inject(ref int register, short value)
{
register = (register & -0x10000) | (ushort)value;
}
#endregion Inject
public static void Swap(ref int a, ref int b)
{
int c = a;
a = b;
b = c;
}
public static int EACalcTimeBW(int mode, int register)
{
switch (mode)
{
case 0: return 0;
case 1: return 0;
case 2: return 4;
case 3: return 4;
case 4: return 6;
case 5: return 8;
case 6: return 10;
case 7:
switch (register)
{
case 0: return 8;
case 1: return 12;
case 2: return 8;
case 3: return 10;
case 4: return 4;
}
break;
}
throw new ArgumentException();
}
public static int EACalcTimeL(int mode, int register)
{
switch (mode)
{
case 0: return 0;
case 1: return 0;
case 2: return 8;
case 3: return 8;
case 4: return 10;
case 5: return 12;
case 6: return 14;
case 7:
switch (register)
{
case 0: return 12;
case 1: return 16;
case 2: return 12;
case 3: return 14;
case 4: return 8;
}
break;
}
throw new ArgumentException();
}
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public interface IMemoryController
{
sbyte ReadB(int address);
short ReadW(int address);
int ReadL(int address);
void WriteB(int address, sbyte value);
void WriteW(int address, short value);
void WriteL(int address, int value);
}
}

View File

@ -1,238 +0,0 @@
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");
}
}
}
}

View File

@ -1,819 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
#region Read
private sbyte ReadB(int address)
{
return this.m_Controller.ReadB(address &= 0x00FFFFFF);
}
private short ReadW(int address)
{
return this.m_Controller.ReadW(address &= 0x00FFFFFF);
}
private int ReadL(int address)
{
return this.m_Controller.ReadL(address &= 0x00FFFFFF);
}
#endregion Read
#region Write
private void WriteB(int address, sbyte value)
{
this.m_Controller.WriteB(address &= 0x00FFFFFF, value);
}
private void WriteW(int address, short value)
{
this.m_Controller.WriteW(address &= 0x00FFFFFF, value);
}
private void WriteL(int address, int value)
{
this.m_Controller.WriteL(address &= 0x00FFFFFF, value);
}
#endregion Write
#region Fetch
private sbyte FetchB()
{
return ReadB(this.m_PC++);
}
private short FetchW()
{
short data = ReadW(this.m_PC);
this.m_PC += 2;
return data;
}
private int FetchL()
{
int data = ReadL(this.m_PC);
this.m_PC += 4;
return data;
}
#endregion Fetch
#region Peek
private sbyte PeekB()
{
return ReadB(this.m_PC);
}
private short PeekW()
{
return ReadW(this.m_PC);
}
private int PeekL()
{
return ReadL(this.m_PC);
}
#endregion Peek
private int FetchIndex()
{
short extension = FetchW();
int da = (extension >> 15) & 0x1;
int reg = (extension >> 12) & 0x7;
int wl = (extension >> 11) & 0x1;
int scale = (extension >> 9) & 0x3;
sbyte displacement = (sbyte)extension;
int indexReg = (scale == 0) ? 1 : ((scale == 1) ? 2 : ((scale == 2) ? 4 : 8));
if (da == 0)
{
indexReg *= (wl == 0) ? (short)this.m_D[reg] : this.m_D[reg];
}
else
{
indexReg *= (wl == 0) ? (short)this.m_A[reg] : this.m_A[reg];
}
return displacement + indexReg;
}
private int PeekIndex()
{
short extension = PeekW();
int da = extension >> 15 & 0x1;
int reg = extension >> 12 & 0x7;
int wl = extension >> 11 & 0x1;
int scale = extension >> 9 & 0x3;
sbyte displacement = (sbyte)extension;
int indexReg = (scale == 0) ? 1 : ((scale == 1) ? 2 : ((scale == 2) ? 4 : 8));
if (da == 0)
{
indexReg *= (wl == 0) ? (short)this.m_D[reg] : this.m_D[reg];
}
else
{
indexReg *= (wl == 0) ? (short)this.m_A[reg] : this.m_A[reg];
}
return displacement + indexReg;
}
#region FetchOperand
private sbyte FetchOperandB(int mode, int register)
{
switch (mode)
{
case 0x0: // Dn
{
return (sbyte)this.m_D[register];
}
case 0x1: // An
{
return (sbyte)this.m_A[register];
}
case 0x2: // (An)
{
return ReadB(this.m_A[register]);
}
case 0x3: // (An)+
{
sbyte operand = ReadB(this.m_A[register]);
this.m_A[register] += (register == 7) ? 2 : 1;
return operand;
}
case 0x4: // -(An)
{
this.m_A[register] -= (register == 7) ? 2 : 1;
return ReadB(this.m_A[register]);
}
case 0x5: //(d16,An)
{
return ReadB(this.m_A[register] + FetchW());
}
case 0x6: // (d8,An,Xn)
{
return this.ReadB(this.m_A[register] + FetchIndex());
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
return ReadB(FetchW());
}
case 0x1: // (xxx).L
{
return ReadB(FetchL());
}
case 0x2: // (d16,PC)
{
return ReadB(this.m_PC + FetchW());
}
case 0x3: // (d8,PC,Xn)
{
sbyte operand = ReadB(this.m_PC + PeekIndex());
this.m_PC += 2;
return operand;
}
case 0x4: // #<data>
{
return (sbyte)FetchW();
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
}
private short FetchOperandW(int mode, int register)
{
switch (mode)
{
case 0x0: // Dn
{
return (short)this.m_D[register];
}
case 0x1: // An
{
return (short)this.m_A[register];
}
case 0x2: // (An)
{
return ReadW(this.m_A[register]);
}
case 0x3: // (An)+
{
short operand = ReadW(this.m_A[register]);
this.m_A[register] += 2;
return operand;
}
case 0x4: // -(An)
{
this.m_A[register] -= 2;
return ReadW(this.m_A[register]);
}
case 0x5: //(d16,An)
{
return ReadW(this.m_A[register] + FetchW());
}
case 0x6: // (d8,An,Xn)
{
return ReadW(this.m_A[register] + FetchIndex());
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
return ReadW(FetchW());
}
case 0x1: // (xxx).L
{
return ReadW(FetchL());
}
case 0x4: // #<data>
{
return FetchW();
}
case 0x2: // (d16,PC)
{
return ReadW(this.m_PC + FetchW());
}
case 0x3: // (d8,PC,Xn)
{
short operand = ReadW(this.m_PC + PeekIndex());
this.m_PC += 2;
return operand;
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
}
private int FetchOperandL(int mode, int register)
{
switch (mode)
{
case 0x0: // Dn
{
return this.m_D[register];
}
case 0x1: // An
{
return this.m_A[register];
}
case 0x2: // (An)
{
return ReadL(this.m_A[register]);
}
case 0x3: // (An)+
{
int operand = ReadL(this.m_A[register]);
this.m_A[register] += 4;
return operand;
}
case 0x4: // -(An)
{
this.m_A[register] -= 4;
return ReadL(this.m_A[register]);
}
case 0x5: //(d16,An)
{
return ReadL(this.m_A[register] + FetchW());
}
case 0x6: // (d8,An,Xn)
{
return ReadL(this.m_A[register] + FetchIndex());
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
return ReadL(FetchW());
}
case 0x1: // (xxx).L
{
return ReadL(FetchL());
}
case 0x4: // #<data>
{
return FetchL();
}
case 0x2: // (d16,PC)
{
return ReadL(this.m_PC + FetchW());
}
case 0x3: // (d8,PC,Xn)
{
int operand = ReadL(this.m_PC + PeekIndex());
this.m_PC += 2;
return operand;
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
}
#endregion FetchOperand
#region FetchAddress
private int FetchAddress(int mode, int register)
{
switch (mode)
{
case 0x0: // Dn
{
throw new ArgumentException("Invalid mode!");
}
case 0x1: // An
{
throw new ArgumentException("Invalid mode!");
}
case 0x2: // (An)
{
return this.m_A[register];
}
case 0x3: // (An)+
{
return this.m_A[register];
}
case 0x4: // -(An)
{
return this.m_A[register];
}
case 0x5: //(d16,An)
{
return (this.m_A[register]);
}
case 0x6: // (d8,An,Xn)
{
return (this.m_A[register] + FetchIndex());
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
return FetchW();
}
case 0x1: // (xxx).L
{
return FetchL();
}
case 0x4: // #<data>
{
throw new ArgumentException("Invalid mode!");
}
case 0x2: // (d16,PC)
{
return (this.m_PC + FetchW());
}
case 0x3: // (d8,PC,Xn)
{
int address = (this.m_PC + PeekIndex());
this.m_PC += 2;
return address;
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new NotImplementedException("Addressing mode doesn't exist!");
}
}
#endregion FetchAddress
#region SetOperand
private void SetOperandB(int mode, int register, sbyte value)
{
switch (mode)
{
case 0x0: // Dn
{
Helpers.Inject(ref this.m_D[register], value);
return;
}
case 0x1: // An
{
this.m_A[register] = value;
return;
}
case 0x2: // (An)
{
WriteB(this.m_A[register], value);
return;
}
case 0x3: // (An)+
{
WriteB(this.m_A[register]++, value);
return;
}
case 0x4: // -(An)
{
WriteB(--this.m_A[register], value);
return;
}
case 0x5: //(d16,An)
{
WriteB(this.m_A[register] + FetchW(), value);
return;
}
case 0x6: // (d8,An,Xn)
{
WriteB(this.m_A[register] + FetchIndex(), value);
return;
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
WriteB(FetchW(), value);
return;
}
case 0x1: // (xxx).L
{
WriteB(FetchL(), value);
return;
}
case 0x4: // #<data>
{
throw new ArgumentException("Invalid mode!");
}
case 0x2: // (d16,PC)
{
WriteB(this.m_PC + FetchW(), value);
return;
}
case 0x3: // (d8,PC,Xn)
{
WriteB(this.m_PC + PeekIndex(), value);
return;
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new NotImplementedException("Addressing mode doesn't exist!");
}
}
private void SetOperandW(int mode, int register, short value)
{
switch (mode)
{
case 0x0: // Dn
{
Helpers.Inject(ref this.m_D[register], value);
break;
}
case 0x1: // An
{
this.m_A[register] = value;
return;
}
case 0x2: // (An)
{
WriteW(m_A[register], value);
return;
}
case 0x3: // (An)+
{
WriteW(m_A[register], value);
m_A[register] += 2;
return;
}
case 0x4: // -(An)
{
m_A[register] -= 2;
WriteW(m_A[register], value);
return;
}
case 0x5: //(d16,An)
{
WriteW(this.m_A[register] + FetchW(), value);
return;
}
case 0x6: // (d8,An,Xn)
{
WriteW(this.m_A[register] + FetchIndex(), value);
return;
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
WriteW(FetchW(), value);
return;
}
case 0x1: // (xxx).L
{
WriteW(FetchL(), value);
return;
}
case 0x4: // #<data>
{
throw new ArgumentException("Invalid mode!");
}
case 0x2: // (d16,PC)
{
WriteW(this.m_PC + FetchW(), value);
return;
}
case 0x3: // (d8,PC,Xn)
{
WriteW(this.m_PC + PeekIndex(), value);
return;
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new NotImplementedException("Addressing mode doesn't exist!");
}
}
private void SetOperandL(int mode, int register, int value)
{
switch (mode)
{
case 0x0: // Dn
{
this.m_D[register] = value;
return;
}
case 0x1:
{
// When setting address registers, need to fill whole byte
this.m_A[register] = value;
return;
}
case 0x2: // (An)
{
WriteL(this.m_A[register], value);
return;
}
case 0x3: // (An)+
{
WriteL(this.m_A[register], value);
this.m_A[register] += 4;
return;
}
case 0x4: // -(An)
{
this.m_A[register] -= 4;
WriteL(this.m_A[register], value);
return;
}
case 0x5: //(d16,An)
{
WriteL(this.m_A[register] + FetchW(), value);
return;
}
case 0x6: // (d8,An,Xn)
{
WriteL(this.m_A[register] + FetchIndex(), value);
return;
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
WriteL(FetchW(), value);
return;
}
case 0x1: // (xxx).L
{
WriteL(FetchL(), value);
return;
}
case 0x4: // #<data>
{
throw new ArgumentException("Invalid mode!");
}
case 0x2: // (d16,PC)
{
WriteL(this.m_PC + FetchW(), value);
return;
}
case 0x3: // (d8,PC,Xn)
{
WriteL(this.m_A[register] + PeekIndex(), value);
return;
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new NotImplementedException("Addressing mode doesn't exist!");
}
}
#endregion SetOperand
#region PeekOperand
private sbyte PeekOperandB(int mode, int register)
{
switch (mode)
{
case 0x0: // Dn
{
return (sbyte)this.m_D[register];
}
case 0x1: // An
{
return (sbyte)this.m_A[register];
}
case 0x2: // (An)
{
return ReadB(this.m_A[register]);
}
case 0x3: // (An)+
{
return ReadB(this.m_A[register]);
}
case 0x4: // -(An)
{
return ReadB(this.m_A[register]);
}
case 0x5: //(d16,An)
{
return ReadB(this.m_A[register] + PeekW());
}
case 0x6: // (d8,An,Xn)
{
return this.ReadB(this.m_A[register] + PeekIndex());
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
return ReadB(PeekW());
}
case 0x1: // (xxx).L
{
return ReadB(PeekL());
}
case 0x4: // #<data>
{
return (sbyte)PeekW();
}
case 0x2: // (d16,PC)
{
return ReadB(this.m_PC + PeekW());
}
case 0x3: // (d8,PC,Xn)
{
return this.ReadB(this.m_PC + FetchIndex());
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
}
private short PeekOperandW(int mode, int register)
{
switch (mode)
{
case 0x0: // Dn
{
return (short)this.m_D[register];
}
case 0x1: // An
{
return (short)this.m_A[register];
}
case 0x2: // (An)
{
return ReadW(this.m_A[register]);
}
case 0x3: // (An)+
{
return ReadW(this.m_A[register]);
}
case 0x4: // -(An)
{
return ReadW(this.m_A[register]);
}
case 0x5: //(d16,An)
{
return ReadW(this.m_A[register] + PeekW());
}
case 0x6: // (d8,An,Xn)
{
return ReadW(this.m_A[register] + PeekIndex());
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
return ReadW(PeekW());
}
case 0x1: // (xxx).L
{
return ReadW(PeekL());
}
case 0x4: // #<data>
{
return PeekW();
}
case 0x2: // (d16,PC)
{
return ReadW(this.m_PC + PeekW());
}
case 0x3: // (d8,PC,Xn)
{
return ReadW(this.m_PC + PeekIndex());
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
}
private int PeekOperandL(int mode, int register)
{
switch (mode)
{
case 0x0: // Dn
{
return this.m_D[register];
}
case 0x1: // An
{
return this.m_A[register];
}
case 0x2: // (An)
{
return ReadL(this.m_A[register]);
}
case 0x3: // (An)+
{
return ReadL(this.m_A[register]);
}
case 0x4: // -(An)
{
return ReadL(this.m_A[register]);
}
case 0x5: //(d16,An)
{
return ReadL(this.m_A[register] + PeekW());
}
case 0x6: // (d8,An,Xn)
{
return this.ReadL(this.m_A[register] + FetchIndex());
}
case 0x7:
switch (register)
{
case 0x0: // (xxx).W
{
return ReadL(PeekW());
}
case 0x1: // (xxx).L
{
return ReadL(PeekL());
}
case 0x4: // #<data>
{
return PeekL();
}
case 0x2: // (d16,PC)
{
return ReadL(this.m_PC + PeekW());
}
case 0x3: // (d8,PC,Xn)
{
return this.ReadB(this.m_PC + FetchIndex());
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
default:
throw new ArgumentException("Addressing mode doesn't exist!");
}
}
#endregion PeekOperand
}
}

View File

@ -1,153 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace MC68000
{
internal delegate void Operation();
public partial class MC68K
{
private Operation[] m_OpTable = new Operation[0x10000];
private void BuildOpTable()
{
// First, define regular expressions for each operation
Dictionary<Operation, Regex> opIndex = new Dictionary<Operation, Regex>();
// Data Movement
opIndex.Add(new Operation(EXG), new Regex("1100" + "[0-1]{3}" + "1" + "(01000|01001|10001)" + "[0-1]{3}"));
opIndex.Add(new Operation(LEA), new Regex("0100" + "[0-1]{3}" + "111" + "(((010|101|110)[0-1]{3})|(111(000|001|010|011)))"));
opIndex.Add(new Operation(LINK), new Regex("0100111001010" + "[0-1]{3}"));
opIndex.Add(new Operation(MOVE), new Regex("00" + "(01|11|10)" + "(([0-1]{3}(000|010|011|100|101|110))|((000|001)111))" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(MOVEA), new Regex("00" + "(11|10)" + "[0-1]{3}" + "001" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(MOVEM_Mem2Reg), new Regex("01001" + "1" + "001" + "[0-1]" + "((010|011|101|110)[0-1]{3}|(111(000|001|010|011)))"));
opIndex.Add(new Operation(MOVEM_Reg2Mem), new Regex("01001" + "0" + "001" + "[0-1]" + "((010|100|101|110)[0-1]{3}|(111(000|001)))"));
opIndex.Add(new Operation(MOVEP), new Regex("0000" + "[0-1]{3}" + "(100|101|110|111)" + "001" + "[0-1]{3}"));
opIndex.Add(new Operation(MOVEQ), new Regex("0111" + "[0-1]{3}" + "0" + "[0-1]{8}"));
opIndex.Add(new Operation(PEA), new Regex("0100100001" + "(((010|101|110)[0-1]{3})|(111(000|001|010|011)))"));
opIndex.Add(new Operation(UNLK), new Regex("0100111001011" + "[0-1]{3}"));
// Integer Arithmetic
opIndex.Add(new Operation(ADD_Dest), new Regex("1101" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(ADD_Source), new Regex("1101" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(ADDA), new Regex("1101" + "[0-1]{3}" + "(011|111)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(ADDI), new Regex("00000110" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(ADDQ), new Regex("0101" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(ADDX), new Regex("1101" + "[0-1]{3}" + "1" + "(00|01|10)" + "00" + "[0-1]" + "[0-1]{3}"));
opIndex.Add(new Operation(CLR), new Regex("01000010" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(CMP), new Regex("1011" + "[0-1]{3}" + "(000|001|010)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(CMPA), new Regex("1011" + "[0-1]{3}" + "(011|111)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(CMPI), new Regex("00001100" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|010|011)))"));
opIndex.Add(new Operation(CMPM), new Regex("1011" + "[0-1]{3}" + "1" + "(00|01|10)" + "001" + "[0-1]{3}"));
opIndex.Add(new Operation(DIVS), new Regex("1000" + "[0-1]{3}" + "111" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(DIVU), new Regex("1000" + "[0-1]{3}" + "011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(EXT), new Regex("0100100" + "(010|011|111)" + "000" + "[0-1]{3}"));
opIndex.Add(new Operation(MULS), new Regex("1100" + "[0-1]{3}" + "111" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(MULU), new Regex("1100" + "[0-1]{3}" + "011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(NEG), new Regex("01000100" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(NEGX), new Regex("01000000" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(SUB_Dest), new Regex("1001" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(SUB_Source), new Regex("1001" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(SUBA), new Regex("1001" + "[0-1]{3}" + "(011|111)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(SUBI), new Regex("00000100" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(SUBQ), new Regex("0101" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((000|001|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(SUBX), new Regex("1001" + "[0-1]{3}" + "1" + "(00|01|10)" + "00" + "[0-1]" + "[0-1]{3}"));
// Logical
opIndex.Add(new Operation(AND_Dest), new Regex("1100" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(AND_Source), new Regex("1100" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(ANDI), new Regex("00000010" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(EOR), new Regex("1011" + "[0-1]{3}" + "(100|101|110)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(EORI), new Regex("00001010" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(OR_Dest), new Regex("1000" + "[0-1]{3}" + "1" + "(00|01|10)" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(OR_Source), new Regex("1000" + "[0-1]{3}" + "0" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(ORI), new Regex("00000000" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(NOT), new Regex("01000110" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
// Shift and Rotate
opIndex.Add(new Operation(ASL), new Regex("1110" + "[0-1]{3}" + "1" + "(00|01|10)" + "[0-1]" + "00" + "[0-1]{3}"));
opIndex.Add(new Operation(ASR), new Regex("1110" + "[0-1]{3}" + "0" + "(00|01|10)" + "[0-1]" + "00" + "[0-1]{3}"));
opIndex.Add(new Operation(ASL_ASR_Memory), new Regex("1110000" + "[0-1]" + "11" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(LSL), new Regex("1110" + "[0-1]{3}" + "1" + "(00|01|10)" + "[0-1]" + "01" + "[0-1]{3}"));
opIndex.Add(new Operation(LSR), new Regex("1110" + "[0-1]{3}" + "0" + "(00|01|10)" + "[0-1]" + "01" + "[0-1]{3}"));
opIndex.Add(new Operation(LSL_LSR_Memory), new Regex("1110001" + "[0-1]" + "11" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(ROL), new Regex("1110" + "[0-1]{3}" + "1" + "(00|01|10)" + "[0-1]" + "11" + "[0-1]{3}"));
opIndex.Add(new Operation(ROR), new Regex("1110" + "[0-1]{3}" + "0" + "(00|01|10)" + "[0-1]" + "11" + "[0-1]{3}"));
opIndex.Add(new Operation(ROL_ROR_Memory), new Regex("1110011" + "[0-1]" + "11" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(ROXL), new Regex("1110" + "[0-1]{3}" + "1" + "(00|01|10)" + "[0-1]" + "10" + "[0-1]{3}"));
opIndex.Add(new Operation(ROXR), new Regex("1110" + "[0-1]{3}" + "0" + "(00|01|10)" + "[0-1]" + "10" + "[0-1]{3}"));
opIndex.Add(new Operation(ROXL_ROXR_Memory), new Regex("1110010" + "[0-1]" + "11" + "(((010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(SWAP), new Regex("0100100001000" + "[0-1]{3}"));
// Bit Manipulation
opIndex.Add(new Operation(BTST_Dynamic), new Regex("0000" + "[0-1]{3}" + "100" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(BTST_Static), new Regex("0000100000" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|010|011)))"));
opIndex.Add(new Operation(BSET_Dynamic), new Regex("0000" + "[0-1]{3}" + "111" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(BSET_Static), new Regex("0000100011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(BCLR_Dynamic), new Regex("0000" + "[0-1]{3}" + "110" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(BCLR_Static), new Regex("0000100010" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(BCHG_Dynamic), new Regex("0000" + "[0-1]{3}" + "101" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(BCHG_Static), new Regex("0000100001" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
// Program Control
opIndex.Add(new Operation(Bcc), new Regex("0110" + "(001|010|011|100|101|110|111)[0-1]" + "[0-1]{8}"));
opIndex.Add(new Operation(DBcc), new Regex("0101" + "[0-1]{4}" + "11001" + "[0-1]{3}"));
opIndex.Add(new Operation(Scc), new Regex("0101" + "[0-1]{4}" + "11" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(BRA), new Regex("01100000" + "[0-1]{8}"));
opIndex.Add(new Operation(BSR), new Regex("01100001" + "[0-1]{8}"));
opIndex.Add(new Operation(JMP), new Regex("0100111011" + "(((010|101|110)[0-1]{3})|(111(000|001|010|011)))"));
opIndex.Add(new Operation(JSR), new Regex("0100111010" + "(((010|101|110)[0-1]{3})|(111(000|001|010|011)))"));
opIndex.Add(new Operation(NOP), new Regex("0100111001110001"));
opIndex.Add(new Operation(RTS), new Regex("0100111001110101"));
opIndex.Add(new Operation(TST), new Regex("01001010" + "(00|01|10)" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
// System Control
opIndex.Add(new Operation(ANDI_to_CCR), new Regex("0000001000111100"));
opIndex.Add(new Operation(ANDI_to_SR), new Regex("0000001001111100"));
opIndex.Add(new Operation(CHK), new Regex("0100" + "[0-1]{3}" + "(11|10)" + "0" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(EORI_to_CCR), new Regex("0000101000111100"));
opIndex.Add(new Operation(EORI_to_SR), new Regex("0000101001111100"));
opIndex.Add(new Operation(ILLEGAL), new Regex("0100101011111100"));
opIndex.Add(new Operation(MOVE_from_SR), new Regex("0100000011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001)))"));
opIndex.Add(new Operation(MOVE_to_CCR), new Regex("0100010011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(MOVE_to_SR), new Regex("0100011011" + "(((000|010|011|100|101|110)[0-1]{3})|(111(000|001|100|010|011)))"));
opIndex.Add(new Operation(MOVE_USP), new Regex("010011100110" + "[0-1]" + "[0-1]{3}"));
opIndex.Add(new Operation(ORI_to_CCR), new Regex("0000000000111100"));
opIndex.Add(new Operation(ORI_to_SR), new Regex("0000000001111100"));
opIndex.Add(new Operation(RESET), new Regex("0100111001110000"));
opIndex.Add(new Operation(RTE), new Regex("0100111001110011"));
opIndex.Add(new Operation(RTR), new Regex("0100111001110111"));
opIndex.Add(new Operation(STOP), new Regex("0100111001110010"));
opIndex.Add(new Operation(TRAP), new Regex("010011100100" + "[0-1]{4}"));
opIndex.Add(new Operation(TRAPV), new Regex("0100111001110110"));
// Now, run through every possible 16-bit binary number,
// find the matching expression, and add that code to the table
for (int i = 0; i < 0x10000; i++)
{
string binaryString = Convert.ToString(i, 2);
binaryString = binaryString.PadLeft(16, '0');
Dictionary<Operation, Regex>.Enumerator enumerator = opIndex.GetEnumerator();
while (enumerator.MoveNext())
{
if (enumerator.Current.Value.IsMatch(binaryString))
{
if (this.m_OpTable[i] != null)
{
throw new Exception("Two operations with clashing codes!");
}
this.m_OpTable[i] = enumerator.Current.Key;
}
}
}
}
}
}

View File

@ -1,207 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
private void Btst(int mode, int register, int mask)
{
switch (mode)
{
case 0: // Destination is data register
{
int operand = FetchOperandL(mode, register);
this.Z = ((operand & mask) == 0);
return;
}
default:
{
byte operand = (byte)FetchOperandB(mode, register);
this.Z = ((operand & mask) == 0);
return;
}
}
}
private void BTST_Dynamic()
{
int bitNumberRegister = (this.m_IR >> 9) & 0x7;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Need to convert bit number into a mask
int bitNumber = this.m_D[bitNumberRegister];
bitNumber %= (mode == 0) ? 32 : 8;
int mask = 1 << bitNumber;
Btst(mode, register, mask);
this.m_Cycles += (mode == 0) ? 6 : 4 + Helpers.EACalcTimeBW(mode, register);
}
private void BTST_Static()
{
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Need to convert bit number into a mask
int bitNumber = (byte)(FetchW() & 0x00FF);
bitNumber %= (mode == 0) ? 32 : 8;
int mask = 1 << bitNumber;
Btst(mode, register, mask);
this.m_Cycles += (mode == 0) ? 10 : 8 + Helpers.EACalcTimeBW(mode, register);
}
private void Bset(int mode, int register, int mask)
{
switch (mode)
{
case 0: // Destination is data register
{
int operand = PeekOperandL(mode, register);
this.Z = ((operand & mask) == 0);
SetOperandL(mode, register, (operand | mask));
return;
}
default:
{
byte operand = (byte)PeekOperandB(mode, register);
this.Z = ((operand & mask) == 0);
SetOperandB(mode, register, (sbyte)(operand | mask));
return;
}
}
}
private void BSET_Dynamic()
{
int bitNumberRegister = (this.m_IR >> 9) & 0x7;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Need to convert bit number into a mask
int bitNumber = this.m_D[bitNumberRegister];
bitNumber %= (mode == 0) ? 32 : 8;
int mask = 1 << bitNumber;
Bset(mode, register, mask);
this.m_Cycles += (mode == 0) ? 8 : 8 + Helpers.EACalcTimeBW(mode, register);
}
private void BSET_Static()
{
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Need to convert bit number into a mask
int bitNumber = (byte)(FetchW() & 0x00FF);
bitNumber %= (mode == 0) ? 32 : 8;
int mask = 1 << bitNumber;
Bset(mode, register, mask);
this.m_Cycles += (mode == 0) ? 12 : 12 + Helpers.EACalcTimeBW(mode, register);
}
private void Bclr(int mode, int register, int mask)
{
switch (mode)
{
case 0: // Destination is data register
{
int operand = PeekOperandL(mode, register);
this.Z = ((operand & mask) > 0);
SetOperandL(mode, register, (operand & ~mask));
return;
}
default:
{
byte operand = (byte)PeekOperandB(mode, register);
this.Z = ((operand & mask) > 0);
SetOperandB(mode, register, (sbyte)(operand & ~mask));
return;
}
}
}
private void BCLR_Dynamic()
{
int bitNumberRegister = (this.m_IR >> 9) & 0x7;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Need to convert bit number into a mask
int bitNumber = this.m_D[bitNumberRegister];
bitNumber %= (mode == 0) ? 32 : 8;
int mask = 1 << bitNumber;
Bclr(mode, register, mask);
this.m_Cycles += (mode == 0) ? 10 : 8 + Helpers.EACalcTimeBW(mode, register);
}
private void BCLR_Static()
{
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Need to convert bit number into a mask
int bitNumber = (byte)(FetchW() & 0x00FF);
bitNumber %= (mode == 0) ? 32 : 8;
int mask = 1 << bitNumber;
Bclr(mode, register, mask);
this.m_Cycles += (mode == 0) ? 14 : 12 + Helpers.EACalcTimeBW(mode, register);
}
private void Bchg(int mode, int register, int mask)
{
switch (mode)
{
case 0: // Destination is data register
{
int operand = PeekOperandL(mode, register);
this.Z = ((operand & mask) > 0);
SetOperandL(mode, register, (operand ^ mask));
return;
}
default:
{
byte operand = (byte)PeekOperandB(mode, register);
this.Z = ((operand & mask) > 0);
SetOperandB(mode, register, (sbyte)(operand ^ mask));
return;
}
}
}
private void BCHG_Dynamic()
{
int bitNumberRegister = (this.m_IR >> 9) & 0x7;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Need to convert bit number into a mask
int bitNumber = this.m_D[bitNumberRegister];
bitNumber %= (mode == 0) ? 32 : 8;
int mask = 1 << bitNumber;
Bchg(mode, register, mask);
this.m_Cycles += (mode == 0) ? 8 : 8 + Helpers.EACalcTimeBW(mode, register);
}
private void BCHG_Static()
{
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Need to convert bit number into a mask
int bitNumber = (byte)(FetchW() & 0x00FF);
bitNumber %= (mode == 0) ? 32 : 8;
int mask = 1 << bitNumber;
Bchg(mode, register, mask);
this.m_Cycles += (mode == 0) ? 12 : 12 + Helpers.EACalcTimeBW(mode, register);
}
}
}

View File

@ -1,396 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
private void EXG() // Exchange registers
{
this.m_Cycles += 6;
switch ((this.m_IR >> 3) & 0x31)
{
case 8:
Helpers.Swap(ref this.m_D[(this.m_IR >> 9) & 0x7], ref this.m_D[this.m_IR & 0x7]);
return;
case 9:
Helpers.Swap(ref this.m_A[(this.m_IR >> 9) & 0x7], ref this.m_A[this.m_IR & 0x7]);
return;
case 17:
Helpers.Swap(ref this.m_D[(this.m_IR >> 9) & 0x7], ref this.m_A[this.m_IR & 0x7]);
return;
}
}
private void LEA() // Load effective address
{
this.m_A[(this.m_IR >> 9) & 0x7] =
FetchAddress((this.m_IR >> 3) & 0x7, this.m_IR & 0x7);
switch ((this.m_IR >> 3) & 0x7)
{
case 0x2: this.m_Cycles += 4; break;
case 0x5: this.m_Cycles += 8; break;
case 0x6: this.m_Cycles += 12; break;
case 0x7:
switch (this.m_IR & 0x7)
{
case 0x0: this.m_Cycles += 8; break;
case 0x1: this.m_Cycles += 12; break;
case 0x2: this.m_Cycles += 8; break;
case 0x3: this.m_Cycles += 12; break;
}
break;
}
}
private void LINK()
{
this.SP -= 4;
WriteL(this.SP, this.m_A[this.m_IR & 0x7]);
this.m_A[this.m_IR & 0x7] = this.SP;
this.SP += FetchW();
this.m_Cycles += 16;
}
private void MOVE() // Move data from source to destination
{
int src_mode = (this.m_IR >> 3) & 0x7;
int src_reg = this.m_IR & 0x7;
int dest_mode = (this.m_IR >> 6) & 0x7;
int dest_reg = (this.m_IR >> 9) & 0x7;
int operand = 0;
switch ((this.m_IR >> 12) & 0x3)
{
case 1: // B
operand = FetchOperandB(src_mode, src_reg);
SetOperandB(dest_mode, dest_reg, (sbyte)operand);
this.m_Cycles += Helpers.MOVECyclesBW[src_mode + ((src_mode == 7) ? src_reg : 0),
dest_mode + ((dest_mode == 7) ? dest_reg : 0)];
break;
case 3: // W
operand = FetchOperandW(src_mode, src_reg);
SetOperandW(dest_mode, dest_reg, (short)operand);
this.m_Cycles += Helpers.MOVECyclesBW[src_mode + ((src_mode == 7) ? src_reg : 0),
dest_mode + ((dest_mode == 7) ? dest_reg : 0)];
break;
case 2: // L
operand = FetchOperandL(src_mode, src_reg);
SetOperandL(dest_mode, dest_reg, operand);
this.m_Cycles += Helpers.MOVECyclesL[src_mode + ((src_mode == 7) ? src_reg : 0),
dest_mode + ((dest_mode == 7) ? dest_reg : 0)];
break;
}
this.V = this.C = false;
this.N = (operand < 0);
this.Z = (operand == 0);
}
private void MOVEA() // Move Address
{
// W
if ((this.m_IR >> 12 & 0x3) == 3)
{
this.m_A[this.m_IR >> 9 & 0x7] =
FetchOperandW(this.m_IR >> 3 & 0x7, this.m_IR & 0x7);
// TODO Need to check these clock cycles
this.m_Cycles += Helpers.MOVECyclesBW[(this.m_IR >> 3 & 0x7) + (((this.m_IR >> 3 & 0x7) == 7) ? (this.m_IR & 0x7) : 0), 1];
}
// L
else
{
this.m_A[this.m_IR >> 9 & 0x7] =
FetchOperandL(this.m_IR >> 3 & 0x7, this.m_IR & 0x7);
// TODO Need to check these clock cycles
this.m_Cycles += Helpers.MOVECyclesL[(this.m_IR >> 3 & 0x7) + (((this.m_IR >> 3 & 0x7) == 7) ? (this.m_IR & 0x7) : 0), 1];
}
}
private void MOVEM_Mem2Reg()
{
int size = (this.m_IR >> 6) & 0x1;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
ushort regMap = (ushort)FetchW();
int count = 0;
int address = FetchAddress(src_mode, src_register);
switch (size)
{
case 0: // W
{
for (int i = 0; i < 8; i++)
{
if ((regMap & 0x1) > 0)
{
this.m_D[i] = ReadW(address);
address += 2;
count++;
}
regMap = (ushort)(regMap >> 1);
}
for (int i = 0; i < 8; i++)
{
if ((regMap & 0x1) > 0)
{
this.m_A[i] = ReadW(address);
address += 2;
count++;
}
regMap = (ushort)(regMap >> 1);
}
if (src_mode == 3) // Postincrement mode
{
this.m_A[src_register] = address;
}
this.m_Cycles += count * 4;
break;
}
case 1: // L
{
for (int i = 0; i < 8; i++)
{
if ((regMap & 0x1) > 0)
{
this.m_D[i] = (int)ReadL(address);
address += 4;
count++;
}
regMap = (ushort)(regMap >> 1);
}
for (int i = 0; i < 8; i++)
{
if ((regMap & 0x1) > 0)
{
this.m_A[i] = (int)ReadL(address);
address += 4;
count++;
}
regMap = (ushort)(regMap >> 1);
}
if (src_mode == 3) // Postincrement mode
{
this.m_A[src_register] = address;
}
this.m_Cycles += count * 8;
break;
}
}
switch (src_mode)
{
case 0x2: this.m_Cycles += 12; break;
case 0x3: this.m_Cycles += 12; break;
case 0x5: this.m_Cycles += 16; break;
case 0x6: this.m_Cycles += 18; break;
case 0x7:
switch (src_register)
{
case 0x0: this.m_Cycles += 16; break;
case 0x1: this.m_Cycles += 20; break;
case 0x2: this.m_Cycles += 16; break;
case 0x3: this.m_Cycles += 18; break;
}
break;
}
}
private void MOVEM_Reg2Mem()
{
int size = (this.m_IR >> 6) & 0x1;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
ushort regMap = (ushort)FetchW();
int count = 0;
int address = FetchAddress(src_mode, src_register);
switch (size)
{
case 0: // W
{
if (src_mode == 4) // Pre-decrement mode
{
for (int i = 7; i >= 0; i--)
{
if ((regMap & 0x1) > 0)
{
address -= 2;
WriteW(address, (sbyte)this.m_A[i]);
count++;
}
regMap = (ushort)(regMap >> 1);
}
for (int i = 7; i >= 0; i--)
{
if ((regMap & 0x1) > 0)
{
address -= 2;
WriteW(address, (sbyte)this.m_D[i]);
count++;
}
regMap = (ushort)(regMap >> 1);
}
this.m_A[src_register] = address;
}
else
{
for (int i = 0; i < 8; i++)
{
if ((regMap & 0x1) > 0)
{
WriteW(address, (sbyte)this.m_D[i]);
address += 2;
count++;
}
regMap = (ushort)(regMap >> 1);
}
for (int i = 0; i < 8; i++)
{
if ((regMap & 0x1) > 0)
{
WriteW(address, (sbyte)this.m_A[i]);
address += 2;
count++;
}
regMap = (ushort)(regMap >> 1);
}
}
this.m_Cycles += 4 * count;
break;
}
case 1: // L
{
if (src_mode == 4) // Pre-decrement mode
{
for (int i = 7; i >= 0; i--)
{
if ((regMap & 0x1) > 0)
{
address -= 4;
WriteL(address, this.m_A[i]);
count++;
}
regMap = (ushort)(regMap >> 1);
}
for (int i = 7; i >= 0; i--)
{
if ((regMap & 0x1) > 0)
{
address -= 4;
WriteL(address, this.m_D[i]);
count++;
}
regMap = (ushort)(regMap >> 1);
}
this.m_A[src_register] = address;
}
else
{
for (int i = 0; i < 8; i++)
{
if ((regMap & 0x1) > 0)
{
WriteL(address, this.m_D[i]);
address += 4;
count++;
}
regMap = (ushort)(regMap >> 1);
}
for (int i = 0; i < 8; i++)
{
if ((regMap & 0x1) > 0)
{
WriteL(address, this.m_A[i]);
address += 4;
count++;
}
regMap = (ushort)(regMap >> 1);
}
}
this.m_Cycles += 8 * count;
break;
}
}
switch (src_mode)
{
case 0x2: this.m_Cycles += 8; break;
case 0x4: this.m_Cycles += 8; break;
case 0x5: this.m_Cycles += 12; break;
case 0x6: this.m_Cycles += 14; break;
case 0x7:
switch (src_register)
{
case 0x0: this.m_Cycles += 12; break;
case 0x1: this.m_Cycles += 16; break;
}
break;
}
}
private void MOVEP()
{
int dataregister = (this.m_IR >> 9) & 0x7;
int opmode = (this.m_IR >> 6) & 0x7;
int addressregister = this.m_IR & 0x7;
short displacement = FetchW();
throw new NotImplementedException();
}
private void MOVEQ() // Move quick
{
// Data byte is sign-extended to 32 bits
int data = (sbyte)this.m_IR;
this.N = (data < 0);
this.Z = (data == 0);
this.V = this.C = false;
this.m_D[(this.m_IR >> 9) & 0x7] = data;
this.m_Cycles += 4;
}
private void PEA() // Push effective address
{
this.SP -= 4;
WriteL(this.SP, FetchAddress((this.m_IR >> 3) & 0x7, this.m_IR & 0x7));
switch ((this.m_IR >> 3) & 0x7)
{
case 0x2: this.m_Cycles += 12; break;
case 0x5: this.m_Cycles += 16; break;
case 0x6: this.m_Cycles += 20; break;
case 0x7:
switch (this.m_IR & 0x7)
{
case 0x0: this.m_Cycles += 16; break;
case 0x1: this.m_Cycles += 20; break;
case 0x2: this.m_Cycles += 16; break;
case 0x3: this.m_Cycles += 20; break;
}
break;
}
}
private void UNLK()
{
this.SP = this.m_A[this.m_IR & 0x7];
this.m_A[this.m_IR & 0x7] = ReadL(this.SP);
this.SP += 4;
this.m_Cycles += 12;
}
}
}

View File

@ -1,869 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
#region Add Helper Functions
private sbyte Add(sbyte a, sbyte b, bool updateConditions, bool useX)
{
int result = useX ? (int)a + (int)b + (this.X ? 1 : 0) : (int)a + (int)b;
if (updateConditions)
{
this.C = this.X = (result & 0x100) > 0;
this.V = result > sbyte.MaxValue || result < sbyte.MinValue;
this.N = result < 0;
if (!useX) { this.Z = result == 0; }
}
return (sbyte)result;
}
private short Add(short a, short b, bool updateConditions, bool useX)
{
int result = useX ? (int)a + (int)b + (this.X ? 1 : 0) : (int)a + (int)b;
if (updateConditions)
{
this.C = this.X = (result & 0x10000) > 0;
this.V = result > short.MaxValue || result < short.MinValue;
this.N = result < 0;
if (!useX) { this.Z = result == 0; }
}
return (short)result;
}
private int Add(int a, int b, bool updateConditions, bool useX)
{
long result = useX ? (long)a + (long)b + (this.X ? 1 : 0) : (long)a + (long)b;
if (updateConditions)
{
this.C = this.X = (result & 0x100000000) > 0;
this.V = result > int.MaxValue || result < int.MinValue;
this.N = result < 0;
if (!useX) { this.Z = result == 0; }
}
return (int)result;
}
#endregion Add Helper Functions
#region Sub Helper Functions
private sbyte Sub(sbyte a, sbyte b, bool updateConditions, bool setX, bool useX)
{
int result = useX ? (int)b - (int)a - (this.X ? 1 : 0) : (int)b - (int)a;
if (updateConditions)
{
this.C = (result & 0x100) > 0;
this.V = result > sbyte.MaxValue || result < sbyte.MinValue;
this.N = result < 0;
if (!useX) { this.Z = result == 0; }
if (setX) { this.X = this.C; }
}
return (sbyte)result;
}
private short Sub(short a, short b, bool updateConditions, bool setX, bool useX)
{
int result = useX ? (int)b - (int)a - (this.X ? 1 : 0) : (int)b - (int)a;
if (updateConditions)
{
this.C = (result & 0x10000) > 0;
this.V = result > short.MaxValue || result < short.MinValue;
this.N = result < 0;
if (!useX) { this.Z = result == 0; }
if (setX) { this.X = this.C; }
}
return (short)result;
}
private int Sub(int a, int b, bool updateConditions, bool setX, bool useX)
{
long result = useX ? (long)b - (long)a - (this.X ? 1 : 0) : (long)b - (long)a;
if (updateConditions)
{
this.C = (result & 0x100000000) > 0;
this.V = result > int.MaxValue || result < int.MinValue;
this.N = result < 0;
if (!useX) { this.Z = result == 0; }
if (setX) { this.X = this.C; }
}
return (int)result;
}
#endregion Sub Helper Functions
private void ADD_Dest()
{
int src_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0:
{
sbyte result = Add((sbyte)this.m_D[src_register], PeekOperandB(mode, register), true, false);
SetOperandB(mode, register, result);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 1:
{
short result = Add((short)this.m_D[src_register], PeekOperandW(mode, register), true, false);
SetOperandW(mode, register, result);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 2:
{
int result = Add(this.m_D[src_register], PeekOperandL(mode, register), true, false);
SetOperandL(mode, register, result);
this.m_Cycles += 12 + Helpers.EACalcTimeL(mode, register);
return;
}
}
}
private void ADD_Source()
{
int dest_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
switch (size)
{
case 0:
{
sbyte result = Add((sbyte)this.m_D[dest_register], FetchOperandB(src_mode, src_register), true, false);
Helpers.Inject(ref this.m_D[dest_register], result);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
case 1:
{
short result = Add((short)this.m_D[dest_register], FetchOperandW(src_mode, src_register), true, false);
Helpers.Inject(ref this.m_D[dest_register], result);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
case 2:
{
int result = Add(this.m_D[dest_register], FetchOperandL(src_mode, src_register), true, false);
this.m_D[dest_register] = result;
this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register);
return;
}
}
}
private void ADDA()
{
int register = (this.m_IR >> 9) & 0x7;
int opmode = (this.m_IR >> 6) & 0x7;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
switch (opmode)
{
case 3: // W
this.m_A[register] += FetchOperandW(src_mode, src_register);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
case 7: // L
this.m_A[register] += FetchOperandL(src_mode, src_register);
this.m_Cycles += 6 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
}
private void ADDI()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = Add((sbyte)FetchW(), PeekOperandB(mode, register), true, false);
SetOperandB(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 1: // W
{
short result = Add(FetchW(), PeekOperandW(mode, register), true, false);
SetOperandW(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 2: // L
{
int result = Add(FetchL(), PeekOperandL(mode, register), true, false);
SetOperandL(mode, register, result);
this.m_Cycles += (mode == 0) ? 16 : 20 + Helpers.EACalcTimeL(mode, register);
return;
}
}
}
private void ADDQ() // Add Quick
{
int data = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// With data, 0 means 8
data = (data == 0) ? 8 : data;
switch (size)
{
case 0: // B
{
if (mode == 1)
{
throw new ArgumentException("Byte operation not allowed on address registers");
}
sbyte result = Add(PeekOperandB(mode, register), (sbyte)data, (mode != 1), false);
SetOperandB(mode, register, result);
switch (mode) {
case 0: this.m_Cycles += 4; break;
case 1: this.m_Cycles += 4; break;
default: this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); break;
}
return;
}
case 1: // W
{
if (mode == 1)
{
int result = Add(PeekOperandL(mode, register), data, false, false);
SetOperandL(mode, register, result);
}
else
{
short result = Add(PeekOperandW(mode, register), (short)data, true, false);
SetOperandW(mode, register, result);
}
switch (mode)
{
case 0: this.m_Cycles += 4; break;
case 1: this.m_Cycles += 4; break;
default: this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); break;
}
return;
}
case 2: // L
{
int result = Add(PeekOperandL(mode, register), data, (mode != 1), false);
SetOperandL(mode, register, result);
switch (mode)
{
case 0: this.m_Cycles += 8; break;
case 1: this.m_Cycles += 8; break;
default: this.m_Cycles += 12 + Helpers.EACalcTimeL(mode, register); break;
}
return;
}
}
}
private void ADDX()
{
int regRx = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int rm = (this.m_IR >> 3) & 0x1;
int regRy = this.m_IR & 0x7;
switch (size)
{
case 0:
{
if (rm == 0)
{
this.m_D[regRy] = Add((sbyte)this.m_D[regRx], (sbyte)this.m_D[regRy], true, true);
this.m_Cycles += 4;
}
else
{
WriteB(this.m_A[regRy], Add(ReadB(this.m_A[regRx]), ReadB(this.m_A[regRy]), true, true));
this.m_Cycles += 18;
}
return;
}
case 1:
{
if (rm == 0)
{
this.m_D[regRy] = Add((short)this.m_D[regRx], (short)this.m_D[regRy], true, true);
this.m_Cycles += 4;
}
else
{
WriteW(this.m_A[regRy], Add(ReadW(this.m_A[regRx]), ReadW(this.m_A[regRy]), true, true));
this.m_Cycles += 18;
}
return;
}
case 2:
{
if (rm == 0)
{
this.m_D[regRy] = Add(this.m_D[regRx], this.m_D[regRy], true, true);
this.m_Cycles += 8;
}
else
{
WriteL(this.m_A[regRy], Add(ReadB(this.m_A[regRx]), ReadB(this.m_A[regRy]), true, true));
this.m_Cycles += 30;
}
return;
}
}
}
private void CLR() // Clear an operand
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
this.C = this.N = this.V = false;
this.Z = true;
switch (size)
{
case 0: // B
SetOperandB(mode, register, 0);
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
return;
case 1: // W
SetOperandW(mode, register, 0);
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
return;
case 2: // L
SetOperandL(mode, register, 0);
this.m_Cycles += (mode == 0) ? 6 : 12 + Helpers.EACalcTimeL(mode, register);
return;
}
}
private void CMP() // Compare
{
int dest_register = (this.m_IR >> 9) & 0x7;
int opmode = (this.m_IR >> 6) & 0x7;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
switch (opmode)
{
case 0: // B
Sub(FetchOperandB(src_mode, src_register), (sbyte)this.m_D[dest_register], true, false, false);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
case 1: // W
Sub(FetchOperandW(src_mode, src_register), (short)this.m_D[dest_register], true, false, false);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
case 2: // L
Sub(FetchOperandL(src_mode, src_register), this.m_D[dest_register], true, false, false);
this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register);
return;
}
}
private void CMPA()
{
int dest_register = (this.m_IR >> 9) & 0x7;
int opmode = (this.m_IR >> 6) & 0x7;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
switch (opmode)
{
case 3: // W
Sub((int)FetchOperandW(src_mode, src_register), this.m_A[dest_register], true, false, false);
this.m_Cycles += 6 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
case 7: // L
Sub(FetchOperandL(src_mode, src_register), this.m_A[dest_register], true, false, false);
this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register);
return;
}
}
private void CMPI()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
Sub((sbyte)FetchW(), FetchOperandB(mode, register), true, false, false);
this.m_Cycles += (mode == 0) ? 8 : 8 + Helpers.EACalcTimeBW(mode, register);
return;
case 1: // W
Sub((short)FetchW(), FetchOperandW(mode, register), true, false, false);
this.m_Cycles += (mode == 0) ? 8 : 8 + Helpers.EACalcTimeBW(mode, register);
return;
case 2: // L
Sub(FetchL(), FetchOperandL(mode, register), true, false, false);
this.m_Cycles += (mode == 0) ? 14 : 12 + Helpers.EACalcTimeL(mode, register);
return;
}
}
private void CMPM()
{
int registerAx = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int registerAy = this.m_IR & 0x7;
switch (size)
{
case 0: // B
Sub((sbyte)this.m_A[registerAy], (sbyte)this.m_A[registerAy], true, false, false);
this.m_Cycles += 12;
return;
case 1: // W
Sub((short)this.m_A[registerAy], (short)this.m_A[registerAy], true, false, false);
this.m_Cycles += 12;
return;
case 2: // L
Sub(this.m_A[registerAy], this.m_A[registerAy], true, false, false);
this.m_Cycles += 20;
return;
}
}
private void DIVS() // Unsigned multiply
{
int dest_register = (this.m_IR >> 9) & 0x7;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
// On 68000, only allowable size is Word
int source = (short)FetchOperandW(src_mode, src_register);
int dest = this.m_D[dest_register];
this.C = false;
if (source == 0)
{
throw new ArgumentException("Divide by zero...");
}
int quotient = dest / source;
int remainder = dest % source;
// Detect overflow
if (quotient < short.MinValue || quotient > short.MaxValue)
{
this.V = true;
throw new ArgumentException("Division overflow");
}
this.m_D[dest_register] = (remainder << 16) | quotient;
this.m_Cycles += 158 + Helpers.EACalcTimeBW(src_mode, src_register);
this.N = quotient < 0;
this.Z = quotient == 0;
this.V = false;
}
private void DIVU() // Unsigned multiply
{
int dest_register = (this.m_IR >> 9) & 0x7;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
// On 68000, only allowable size is Word
uint source = (uint)FetchOperandW(src_mode, src_register);
uint dest = (uint)this.m_D[dest_register];
this.C = false;
if (source == 0)
{
throw new ArgumentException("Divide by zero...");
}
uint quotient = dest / source;
uint remainder = dest % source;
// Detect overflow
if (quotient < ushort.MinValue || quotient > ushort.MaxValue ||
remainder < ushort.MinValue || remainder > ushort.MaxValue)
{
this.V = true;
throw new ArgumentException("Division overflow");
}
this.m_D[dest_register] = (int)((remainder << 16) | quotient);
this.m_Cycles += 140 + Helpers.EACalcTimeBW(src_mode, src_register);
this.N = quotient < 0;
this.Z = quotient == 0;
this.V = false;
}
private void EXT() // Sign extend
{
this.m_Cycles += 4;
switch ((this.m_IR >> 6) & 0x7)
{
case 2: // Byte to word
Helpers.Inject(ref this.m_D[this.m_IR & 0x7], (short)((sbyte)this.m_D[this.m_IR & 0x7]));
break;
case 3: // Word to long
this.m_D[this.m_IR & 0x7] = (short)this.m_D[this.m_IR & 0x7];
break;
}
}
private void MULS() // Unsigned multiply
{
int dest_register = (this.m_IR >> 9) & 0x7;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
// On 68000, only allowable size is Word
short operand = FetchOperandW(src_mode, src_register);
short currentValue = (short)this.m_D[dest_register];
int newValue = operand * currentValue;
this.m_D[dest_register] = newValue;
this.m_Cycles += 70 + Helpers.EACalcTimeBW(src_mode, src_register);
this.N = newValue < 0;
this.Z = newValue == 0;
this.V = false; // Can't get an overflow
this.C = false;
}
private void MULU() // Unsigned multiply
{
int dest_register = (this.m_IR >> 9) & 0x7;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
// On 68000, only allowable size is Word
ushort operand = (ushort)FetchOperandW(src_mode, src_register);
ushort currentValue = (ushort)this.m_D[dest_register];
uint newValue = (uint)(operand * currentValue);
this.m_D[dest_register] = (int)newValue;
this.m_Cycles += 70 + Helpers.EACalcTimeBW(src_mode, src_register);
this.N = (int)newValue < 0;
this.Z = (newValue == 0);
this.V = false; // Can't get an overflow
this.C = false;
}
private void NEG()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0:
SetOperandB(mode, register, Sub(PeekOperandB(mode, register), (sbyte)0, true, true, false));
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
return;
case 1:
SetOperandW(mode, register, Sub(PeekOperandW(mode, register), (short)0, true, true, false));
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
return;
case 2:
SetOperandL(mode, register, Sub(PeekOperandL(mode, register), (int)0, true, true, false));
this.m_Cycles += (mode == 0) ? 6 : 12 + Helpers.EACalcTimeL(mode, register);
return;
}
}
private void NEGX()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0:
SetOperandB(mode, register, Sub(PeekOperandB(mode, register), (sbyte)0, true, true, false));
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
return;
case 1:
SetOperandW(mode, register, Sub(PeekOperandW(mode, register), (short)0, true, true, false));
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
return;
case 2:
SetOperandL(mode, register, Sub(PeekOperandL(mode, register), (int)0, true, true, false));
this.m_Cycles += (mode == 0) ? 6 : 12 + Helpers.EACalcTimeL(mode, register);
return;
}
}
private void SUB_Dest()
{
int src_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0:
{
sbyte result = Sub((sbyte)this.m_D[src_register], PeekOperandB(mode, register), true, true, false);
SetOperandB(mode, register, result);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, src_register);
return;
}
case 1:
{
short result = Sub((short)this.m_D[src_register], PeekOperandW(mode, register), true, true, false);
SetOperandW(mode, register, result);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, src_register);
return;
}
case 2:
{
int result = Sub(this.m_D[src_register], PeekOperandL(mode, register), true, true, false);
SetOperandL(mode, register, result);
this.m_Cycles += 12 + Helpers.EACalcTimeL(mode, src_register);
return;
}
}
}
private void SUB_Source()
{
int dest_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
switch (size)
{
case 0:
{
sbyte result = Sub(FetchOperandB(src_mode, src_register), (sbyte)this.m_D[dest_register], true, true, false);
Helpers.Inject(ref this.m_D[dest_register], result);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
case 1:
{
short result = Sub(FetchOperandW(src_mode, src_register), (short)this.m_D[dest_register], true, true, false);
Helpers.Inject(ref this.m_D[dest_register], result);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
case 2:
{
int result = Sub(FetchOperandL(src_mode, src_register), this.m_D[dest_register], true, true, false);
this.m_D[dest_register] = (int)result;
this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register);
return;
}
}
}
private void SUBA()
{
int dest_register = (this.m_IR >> 9) & 0x7;
int opmode = (this.m_IR >> 6) & 0x7;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
switch (opmode)
{
case 3: // W
{
int operand = FetchOperandW(src_mode, src_register); // Sign-extended
this.m_A[dest_register] -= operand;
this.m_Cycles += 8 + Helpers.EACalcTimeBW(src_mode, src_register);
break;
}
case 7: // L
{
int operand = FetchOperandL(src_mode, src_register);
this.m_A[dest_register] -= operand;
this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register);
break;
}
}
}
private void SUBI()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = Sub((sbyte)FetchW(), PeekOperandB(mode, register), true, true, false);
SetOperandB(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 1: // W
{
short result = Sub(FetchW(), PeekOperandW(mode, register), true, true, false);
SetOperandW(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 2: // L
{
int result = Sub(FetchL(), PeekOperandL(mode, register), true, true, false);
SetOperandL(mode, register, result);
this.m_Cycles += (mode == 0) ? 16 : 20 + Helpers.EACalcTimeL(mode, register);
return;
}
}
}
private void SUBQ() // Add Quick
{
int data = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// With data, 0 means 8
data = (data == 0) ? 8 : data;
switch (size)
{
case 0: // B
{
if (mode == 1)
{
throw new ArgumentException("Byte operation not allowed on address registers");
}
sbyte result = Sub((sbyte)data, PeekOperandB(mode, register), (mode != 1), true, false);
SetOperandB(mode, register, result);
switch (mode)
{
case 0: this.m_Cycles += 4; break;
case 1: this.m_Cycles += 8; break;
default: this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); break;
}
return;
}
case 1: // W
{
if (mode == 1)
{
int result = Sub(data, PeekOperandL(mode, register), false, true, false);
SetOperandL(mode, register, result);
}
else
{
short result = Sub((short)data, PeekOperandW(mode, register), true, true, false);
SetOperandW(mode, register, result);
}
switch (mode)
{
case 0: this.m_Cycles += 4; break;
case 1: this.m_Cycles += 8; break;
default: this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register); break;
}
return;
}
case 2: // L
{
int result = Sub(data, PeekOperandL(mode, register), (mode != 1), true, false);
SetOperandL(mode, register, result);
switch (mode)
{
case 0: this.m_Cycles += 8; break;
case 1: this.m_Cycles += 8; break;
default: this.m_Cycles += 12 + Helpers.EACalcTimeL(mode, register); break;
}
return;
}
}
}
private void SUBX()
{
int regRx = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int rm = (this.m_IR >> 3) & 0x1;
int regRy = this.m_IR & 0x7;
switch (size)
{
case 0:
{
if (rm == 0)
{
this.m_D[regRy] = Sub((sbyte)this.m_D[regRx], (sbyte)this.m_D[regRy], true, true, true);
this.m_Cycles += 4;
}
else
{
WriteB(this.m_A[regRy], Sub(ReadB(this.m_A[regRx]), ReadB(this.m_A[regRy]), true, true, true));
this.m_Cycles += 18;
}
return;
}
case 1:
{
if (rm == 0)
{
this.m_D[regRy] = Sub((short)this.m_D[regRx], (short)this.m_D[regRy], true, true, true);
this.m_Cycles += 4;
}
else
{
WriteW(this.m_A[regRy], Sub(ReadW(this.m_A[regRx]), ReadW(this.m_A[regRy]), true, true, true));
this.m_Cycles += 18;
}
return;
}
case 2:
{
if (rm == 0)
{
this.m_D[regRy] = Sub(this.m_D[regRx], this.m_D[regRy], true, true, true);
this.m_Cycles += 8;
}
else
{
WriteL(this.m_A[regRy], Sub(ReadB(this.m_A[regRx]), ReadB(this.m_A[regRy]), true, true, true));
this.m_Cycles += 30;
}
return;
}
}
}
}
}

View File

@ -1,405 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
#region AND Helpers
private sbyte And(sbyte a, sbyte b)
{
sbyte result = (sbyte)(a & b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
private short And(short a, short b)
{
short result = (short)(a & b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
private int And(int a, int b)
{
int result = (int)(a & b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
#endregion AND Helpers
private void AND_Dest()
{
int src_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int dest_mode = (this.m_IR >> 3) & 0x7;
int dest_register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = And((sbyte)this.m_D[src_register], PeekOperandB(dest_mode, dest_register));
SetOperandB(dest_mode, dest_register, result);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(dest_mode, dest_register);
return;
}
case 1: // W
{
short result = And((short)this.m_D[src_register], PeekOperandW(dest_mode, dest_register));
SetOperandW(dest_mode, dest_register, result);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(dest_mode, dest_register);
return;
}
case 2: // L
{
int result = And(this.m_D[src_register], PeekOperandL(dest_mode, dest_register));
SetOperandL(dest_mode, dest_register, result);
this.m_Cycles += 6 + Helpers.EACalcTimeL(dest_mode, dest_register);
return;
}
}
}
private void AND_Source()
{
int dest_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = And((sbyte)this.m_D[dest_register], FetchOperandB(src_mode, src_register));
Helpers.Inject(ref this.m_D[dest_register], result);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
case 1: // W
{
short result = And((short)this.m_D[dest_register], FetchOperandW(src_mode, src_register));
Helpers.Inject(ref this.m_D[dest_register], result);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
case 2: // L
{
int result = And(this.m_D[dest_register], FetchOperandL(src_mode, src_register));
this.m_D[dest_register] = result;
this.m_Cycles += 12 + Helpers.EACalcTimeL(src_mode, src_register);
return;
}
}
}
private void ANDI()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = And((sbyte)FetchW(), PeekOperandB(mode, register));
SetOperandB(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 1: // W
{
short result = And(FetchW(), PeekOperandW(mode, register));
SetOperandW(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 2: // L
{
int result = And(FetchL(), PeekOperandL(mode, register));
SetOperandL(mode, register, result);
this.m_Cycles += (mode == 0) ? 14 : 20 + Helpers.EACalcTimeL(mode, register);
return;
}
}
}
#region EOR Helpers
private sbyte Eor(sbyte a, sbyte b)
{
sbyte result = (sbyte)(a ^ b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
private short Eor(short a, short b)
{
short result = (short)(a ^ b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
private int Eor(int a, int b)
{
int result = (int)(a ^ b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
#endregion EOR Helpers
private void EOR()
{
int src_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int dest_mode = (this.m_IR >> 3) & 0x7;
int dest_register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = Eor((sbyte)this.m_D[src_register], PeekOperandB(dest_mode, dest_register));
SetOperandB(dest_mode, dest_register, result);
this.m_Cycles += (dest_mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(dest_mode, dest_register);
return;
}
case 1: // W
{
short result = Eor((short)this.m_D[src_register], PeekOperandW(dest_mode, dest_register));
SetOperandW(dest_mode, dest_register, result);
this.m_Cycles += (dest_mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(dest_mode, dest_register);
return;
}
case 2: // L
{
int result = Eor(this.m_D[src_register], PeekOperandL(dest_mode, dest_register));
SetOperandL(dest_mode, dest_register, result);
this.m_Cycles += (dest_mode == 0) ? 8 : 12 + Helpers.EACalcTimeL(dest_mode, dest_register);
return;
}
}
}
private void EORI()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = Eor((sbyte)FetchW(), PeekOperandB(mode, register));
SetOperandB(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 1: // W
{
short result = Eor(FetchW(), PeekOperandW(mode, register));
SetOperandW(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 2: // L
{
int result = Eor(FetchL(), PeekOperandL(mode, register));
SetOperandL(mode, register, result);
this.m_Cycles += (mode == 0) ? 16 : 20 + Helpers.EACalcTimeL(mode, register);
return;
}
}
}
#region OR Helpers
private sbyte Or(sbyte a, sbyte b)
{
sbyte result = (sbyte)(a | b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
private short Or(short a, short b)
{
short result = (short)(a | b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
private int Or(int a, int b)
{
int result = (int)(a | b);
this.V = this.C = false;
this.N = result < 0;
this.Z = result == 0;
return result;
}
#endregion OR Helpers
private void OR_Dest()
{
int src_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int dest_mode = (this.m_IR >> 3) & 0x7;
int dest_register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = Or((sbyte)this.m_D[src_register], PeekOperandB(dest_mode, dest_register));
SetOperandB(dest_mode, dest_register, result);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(dest_mode, dest_register);
return;
}
case 1: // W
{
short result = Or((short)this.m_D[src_register], PeekOperandW(dest_mode, dest_register));
SetOperandW(dest_mode, dest_register, result);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(dest_mode, dest_register);
return;
}
case 2: // L
{
int result = Or(this.m_D[src_register], PeekOperandL(dest_mode, dest_register));
SetOperandL(dest_mode, dest_register, result);
this.m_Cycles += 12 + Helpers.EACalcTimeL(dest_mode, dest_register);
return;
}
}
}
private void OR_Source()
{
int dest_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int src_mode = (this.m_IR >> 3) & 0x7;
int src_register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = Or((sbyte)this.m_D[dest_register], FetchOperandB(src_mode, src_register));
Helpers.Inject(ref this.m_D[dest_register], result);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
case 1: // W
{
short result = Or((short)this.m_D[dest_register], FetchOperandW(src_mode, src_register));
Helpers.Inject(ref this.m_D[dest_register], result);
this.m_Cycles += 4 + Helpers.EACalcTimeBW(src_mode, src_register);
return;
}
case 2: // L
{
int result = Or(this.m_D[dest_register], FetchOperandL(src_mode, src_register));
this.m_D[dest_register] = result;
this.m_Cycles += 6 + Helpers.EACalcTimeL(src_mode, src_register);
return;
}
}
}
private void ORI()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
switch (size)
{
case 0: // B
{
sbyte result = Or((sbyte)FetchW(), PeekOperandB(mode, register));
SetOperandB(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 1: // W
{
short result = Or(FetchW(), PeekOperandW(mode, register));
SetOperandW(mode, register, result);
this.m_Cycles += (mode == 0) ? 8 : 12 + Helpers.EACalcTimeBW(mode, register);
return;
}
case 2: // L
{
int result = Or(FetchL(), PeekOperandL(mode, register));
SetOperandL(mode, register, result);
this.m_Cycles += (mode == 0) ? 16 : 20 + Helpers.EACalcTimeL(mode, register);
return;
}
}
}
private void NOT()
{
int size = (this.m_IR >> 6) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
long result = 0;
this.V = this.C = false;
switch (size)
{
case 0:
result = ~PeekOperandB(mode, register);
SetOperandB(mode, register, (sbyte)result);
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
break;
case 1:
result = ~PeekOperandW(mode, register);
SetOperandW(mode, register, (short)result);
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
break;
case 2:
result = ~PeekOperandL(mode, register);
SetOperandL(mode, register, (int)result);
this.m_Cycles += (mode == 0) ? 6 : 12 + Helpers.EACalcTimeL(mode, register);
break;
}
this.N = result < 0;
this.Z = result == 0;
}
}
}

View File

@ -1,29 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
private void TAS() // Test and set
{
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
sbyte operand = PeekOperandB(mode, register);
this.N = (operand < 0);
this.Z = (operand == 0);
this.V = false;
this.C = false;
this.m_Cycles += (mode == 0) ? 4 : 14 + Helpers.EACalcTimeBW(mode, register);
// Set the 7th bit
byte uOperand = (byte)operand;
uOperand |= 0x80;
SetOperandB(mode, register, (sbyte)uOperand);
}
}
}

View File

@ -1,208 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
private void Bcc() // Branch conditionally
{
if ((sbyte)this.m_IR == 0)
{
if (TestCondition((this.m_IR >> 8) & 0xF))
{
this.m_PC += FetchW();
this.m_Cycles += 10;
}
else
{
this.m_PC += 2;
this.m_Cycles += 12;
}
}
else
{
if (TestCondition((this.m_IR >> 8) & 0xF))
{
this.m_PC += (sbyte)this.m_IR;
this.m_Cycles += 10;
}
else
{
this.m_Cycles += 8;
}
}
}
private void DBcc() // Test condition, decrement, branch
{
if (TestCondition((this.m_IR >> 8) & 0xF))
{
// Need to move PC on...
this.m_PC += 2;
this.m_Cycles += 12;
}
else
{
short counter = (short)this.m_D[this.m_IR & 0x7];
Helpers.Inject(ref this.m_D[this.m_IR & 0x7], --counter);
if (counter == -1)
{
this.m_PC += 2;
this.m_Cycles += 14;
}
else
{
this.m_PC += FetchW();
this.m_Cycles += 10;
}
}
}
private void Scc() // Set according to condition
{
int cCode = (this.m_IR >> 8) & 0xF;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
if (TestCondition(cCode))
{
// Set all the bits
SetOperandB(mode, register, -1);
this.m_Cycles += (mode == 0) ? 6 : 8 + Helpers.EACalcTimeBW(mode, register);
}
else
{
// Clear all the bits
SetOperandB(mode, register, 0);
this.m_Cycles += (mode == 0) ? 4 : 8 + Helpers.EACalcTimeBW(mode, register);
}
}
private void BRA() // Branch Always
{
this.m_Cycles += 10;
if ((sbyte)this.m_IR == 0)
{
this.m_PC += PeekW();
}
else
{
this.m_PC += (sbyte)this.m_IR;
}
}
private void BSR() // Branch to subroutine
{
this.SP -= 4;
// 16-bit displacement
if ((sbyte)this.m_IR == 0)
{
WriteL(this.SP, this.m_PC + 2);
this.m_PC += PeekW();
}
// 8-bit displacement
else
{
WriteL(this.SP, this.m_PC);
this.m_PC += (sbyte)this.m_IR;
}
this.m_Cycles += 18;
}
private void JMP() // Jump
{
this.m_PC = FetchAddress((this.m_IR >> 3) & 0x7, this.m_IR & 0x7);
switch ((this.m_IR >> 3) & 0x7)
{
case 0x2: this.m_Cycles += 8; break;
case 0x5: this.m_Cycles += 10; break;
case 0x6: this.m_Cycles += 14; break;
case 0x7:
switch (this.m_IR & 0x7)
{
case 0x0: this.m_Cycles += 10; break;
case 0x1: this.m_Cycles += 12; break;
case 0x2: this.m_Cycles += 10; break;
case 0x3: this.m_Cycles += 14; break;
}
break;
}
}
private void JSR() // Jump to subroutine
{
int address = FetchAddress((this.m_IR >> 3) & 0x7, this.m_IR & 0x7) & 0x00FFFFFF;
this.SP -= 4;
WriteL(this.SP, this.m_PC);
this.m_PC = address;
switch ((this.m_IR >> 3) & 0x7)
{
case 0x2: this.m_Cycles += 16; break;
case 0x5: this.m_Cycles += 18; break;
case 0x6: this.m_Cycles += 22; break;
case 0x7:
switch (this.m_IR & 0x7)
{
case 0x0: this.m_Cycles += 18; break;
case 0x1: this.m_Cycles += 20; break;
case 0x2: this.m_Cycles += 18; break;
case 0x3: this.m_Cycles += 22; break;
}
break;
}
}
private void NOP() // No operation
{
// Doesn't do anything, it's there to help flush the integer pipeline
this.m_Cycles += 4;
}
private void RTS() // Return from Subroutine
{
this.m_PC = ReadL(this.SP);
this.SP += 4;
this.m_Cycles += 16;
}
private void TST() // Test an operand
{
// Use an integer operand, it gets sign-extended and we can check it afterwards
int operand = 0;
switch ((this.m_IR >> 6) & 0x3)
{
case 0: // B
{
operand = FetchOperandB((this.m_IR >> 3) & 0x7, this.m_IR & 0x7);
this.m_Cycles += 4 + Helpers.EACalcTimeBW((this.m_IR >> 3) & 0x7, this.m_IR & 0x7);
break;
}
case 1: // W
{
operand = FetchOperandW((this.m_IR >> 3) & 0x7, this.m_IR & 0x7);
this.m_Cycles += 4 + Helpers.EACalcTimeBW((this.m_IR >> 3) & 0x7, this.m_IR & 0x7);
break;
}
case 2: // L
{
operand = FetchOperandL((this.m_IR >> 3) & 0x7, this.m_IR & 0x7);
this.m_Cycles += 4 + Helpers.EACalcTimeL((this.m_IR >> 3) & 0x7, this.m_IR & 0x7);
break;
}
}
this.V = this.C = false;
this.N = (operand < 0);
this.Z = (operand == 0);
}
}
}

View File

@ -1,622 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
#region Arithmetic Shift
private void ASL()
{
int count_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int ir = (this.m_IR >> 5) & 0x1;
int register = this.m_IR & 0x7;
int shift_count = (ir == 0) ?
((count_register == 0) ? 8 : count_register) :
(this.m_D[count_register] % 64);
this.C = this.V = false;
switch (size)
{
case 0:
{
sbyte value = (sbyte)this.m_D[register];
bool msbit = value < 0;
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = value < 0;
value <<= 1;
this.V |= ((value < 0) != msbit);
}
Helpers.Inject(ref this.m_D[register], value);
this.N = value < 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 1:
{
short value = (short)this.m_D[register];
bool msbit = value < 0;
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = value < 0;
value <<= 1;
this.V |= ((value < 0) != msbit);
}
Helpers.Inject(ref this.m_D[register], value);
this.N = value < 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 2:
{
int value = this.m_D[register];
bool msbit = value < 0;
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = value < 0;
value <<= 1;
this.V |= ((value < 0) != msbit);
}
this.m_D[register] = value;
this.N = value < 0;
this.Z = value == 0;
this.m_Cycles += 8 + 2 * shift_count;
return;
}
}
}
private void ASR()
{
int count_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int ir = (this.m_IR >> 5) & 0x1;
int register = this.m_IR & 0x7;
int shift_count = (ir == 0) ?
((count_register == 0) ? 8 : count_register) :
(this.m_D[count_register] % 64);
this.C = this.V = false;
switch (size)
{
case 0:
{
sbyte value = (sbyte)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 1) > 0;
value >>= 1;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = value < 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 1:
{
short value = (short)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 1) > 0;
value >>= 1;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = value < 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 2:
{
int value = this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 1) > 0;
value >>= 1;
}
this.m_D[register] = value;
this.N = value < 0;
this.Z = value == 0;
this.m_Cycles += 8 + 2 * shift_count;
return;
}
}
}
private void ASL_ASR_Memory()
{
int direction = (this.m_IR >> 8) & 0x1; // 0 = Right, 1 = Left
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
short value = PeekOperandW(mode, register);
if (direction == 0)
{
this.C = this.X = (value & 1) > 0;
this.V = false; // For right shift, MSB can't change
value >>= 1;
}
else
{
bool msbit = (value < 0);
this.C = this.X = value < 0;
value <<= 1;
this.V |= ((value < 0) != msbit);
}
this.N = value < 0;
this.Z = value == 0;
SetOperandW(mode, register, value);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register);
}
#endregion Arithmetic Shift
#region Logical Shift
private void LSL()
{
int count_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int ir = (this.m_IR >> 5) & 0x1;
int register = this.m_IR & 0x7;
int shift_count = (ir == 0) ?
((count_register == 0) ? 8 : count_register) :
(this.m_D[count_register] % 64);
this.C = this.V = false;
switch (size)
{
case 0:
{
byte value = (byte)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 0x80) > 0;
value <<= 1;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x80) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 1:
{
ushort value = (ushort)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 0x8000) > 0;
value <<= 1;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 2:
{
uint value = (uint)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 0x80000000) > 0;
value <<= 1;
}
this.m_D[register] = (int)value;
this.N = (value & 0x80000000) > 0;
this.Z = value == 0;
this.m_Cycles += 8 + 2 * shift_count;
return;
}
}
}
private void LSR()
{
int count_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int ir = (this.m_IR >> 5) & 0x1;
int register = this.m_IR & 0x7;
int shift_count = (ir == 0) ?
((count_register == 0) ? 8 : count_register) :
(this.m_D[count_register] % 64);
this.C = this.V = false;
switch (size)
{
case 0:
{
byte value = (byte)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 1) > 0;
value >>= 1;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x80) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 1:
{
ushort value = (ushort)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 1) > 0;
value >>= 1;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 2:
{
uint value = (uint)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = this.X = (value & 1) > 0;
value >>= 1;
}
this.m_D[register] = (int)value;
this.N = (value & 0x80000000) > 0;
this.Z = value == 0;
this.m_Cycles += 8 + 2 * shift_count;
return;
}
}
}
private void LSL_LSR_Memory()
{
int direction = (this.m_IR >> 8) & 0x1; // 0 = Right, 1 = Left
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
ushort value = (ushort)PeekOperandW(mode, register);
if (direction == 0)
{
this.C = this.X = (value & 1) > 0;
value >>= 1;
}
else
{
this.C = this.X = (value & 0x8000) > 0;
value <<= 1;
}
this.V = false;
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
SetOperandW(mode, register, (short)value);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register);
}
#endregion Logical Shift
#region Rotate (without extend)
private void ROL()
{
int count_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int ir = (this.m_IR >> 5) & 0x1;
int register = this.m_IR & 0x7;
int shift_count = (ir == 0) ?
((count_register == 0) ? 8 : count_register) :
(this.m_D[count_register] % 64);
this.C = this.V = false;
switch (size)
{
case 0:
{
byte value = (byte)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 0x80) > 0;
value = (byte)((value >> 7) | (value << 1));
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x80) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 1:
{
ushort value = (ushort)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 0x8000) > 0;
value = (ushort)((value >> 15) | (value << 1));
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 2:
{
uint value = (uint)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 0x80000000) > 0;
value = (uint)((value >> 31) | (value << 1));
}
this.m_D[register] = (int)value;
this.N = (value & 0x80000000) > 0;
this.Z = value == 0;
this.m_Cycles += 8 + 2 * shift_count;
return;
}
}
}
private void ROR()
{
int count_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int ir = (this.m_IR >> 5) & 0x1;
int register = this.m_IR & 0x7;
int shift_count = (ir == 0) ?
((count_register == 0) ? 8 : count_register) :
(this.m_D[count_register] % 64);
this.C = this.V = false;
switch (size)
{
case 0:
{
byte value = (byte)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 1) > 0;
value = (byte)((value << 7) | (value >> 1));
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x80) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 1:
{
ushort value = (ushort)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 1) > 0;
value = (ushort)((value << 15) | (value >> 1));
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 2:
{
uint value = (uint)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 1) > 0;
value = (uint)((value << 31) | (value >> 1));
}
this.m_D[register] = (int)value;
this.N = (value & 0x80000000) > 0;
this.Z = value == 0;
this.m_Cycles += 8 + 2 * shift_count;
return;
}
}
}
private void ROL_ROR_Memory()
{
int direction = (this.m_IR >> 8) & 0x1; // 0 = Right, 1 = Left
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
ushort value = (ushort)PeekOperandW(mode, register);
if (direction == 0)
{
this.C = (value & 1) > 0;
value = (ushort)((value >> 1) | (value << 15));
}
else
{
this.C = (value & 0x8000) > 0;
value = (ushort)((value >> 15) | (value << 1));
}
this.V = false;
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
SetOperandW(mode, register, (short)value);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register);
}
#endregion Rotate (without extend)
#region Rotate (with extend)
private void ROXL()
{
int count_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int ir = (this.m_IR >> 5) & 0x1;
int register = this.m_IR & 0x7;
int shift_count = (ir == 0) ?
((count_register == 0) ? 8 : count_register) :
(this.m_D[count_register] % 64);
this.V = false;
this.C = this.X;
switch (size)
{
case 0:
{
byte value = (byte)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 0x80) > 0;
value = (byte)((value << 1) | ((this.X) ? 1: 0));
this.X = this.C;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x80) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 1:
{
ushort value = (ushort)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 0x8000) > 0;
value = (ushort)((value << 1) | ((this.X) ? 1 : 0));
this.X = this.C;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 2:
{
uint value = (uint)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 0x80000000) > 0;
value = (uint)((value << 1) | ((this.X) ? (uint)1 : (uint)0));
this.X = this.C;
}
this.m_D[register] = (int)value;
this.N = (value & 0x80000000) > 0;
this.Z = value == 0;
this.m_Cycles += 8 + 2 * shift_count;
return;
}
}
}
private void ROXR()
{
int count_register = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 6) & 0x3;
int ir = (this.m_IR >> 5) & 0x1;
int register = this.m_IR & 0x7;
int shift_count = (ir == 0) ?
((count_register == 0) ? 8 : count_register) :
(this.m_D[count_register] % 64);
this.V = false;
this.C = this.X;
switch (size)
{
case 0:
{
byte value = (byte)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 1) > 0;
value = (byte)(((this.X) ? 0x80 : 0) | (value >> 1));
this.X = this.C;
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x80) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 1:
{
ushort value = (ushort)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 1) > 0;
value = (ushort)(((this.X) ? 0x8000 : 0) | (value >> 1));
}
Helpers.Inject(ref this.m_D[register], value);
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
this.m_Cycles += 6 + 2 * shift_count;
return;
}
case 2:
{
uint value = (uint)this.m_D[register];
for (int i = 0; i < shift_count; i++)
{
this.C = (value & 1) > 0;
value = (uint)(((this.X) ? 0x80000000 : 0) | (value >> 1));
}
this.m_D[register] = (int)value;
this.N = (value & 0x80000000) > 0;
this.Z = value == 0;
this.m_Cycles += 8 + 2 * shift_count;
return;
}
}
}
private void ROXL_ROXR_Memory()
{
int direction = (this.m_IR >> 8) & 0x1; // 0 = Right, 1 = Left
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
ushort value = (ushort)PeekOperandW(mode, register);
if (direction == 0)
{
this.C = (value & 1) > 0;
value = (ushort)(((this.X) ? 0x8000 : 0) | (value >> 1));
this.X = this.C;
}
else
{
this.C = (value & 0x8000) > 0;
value = (ushort)((value << 1) | ((this.X) ? 1 : 0));
this.X = this.C;
}
this.V = false;
this.N = (value & 0x8000) > 0;
this.Z = value == 0;
SetOperandW(mode, register, (short)value);
this.m_Cycles += 8 + Helpers.EACalcTimeBW(mode, register);
}
#endregion Rotate (with extend)
private void SWAP() // Swap halves of a register
{
int register = this.m_IR & 0x7;
this.m_D[register] = (int)(((uint)this.m_D[register] << 16) |
((uint)this.m_D[register] >> 16));
this.N = (this.m_D[register] < 0);
this.Z = (this.m_D[register] == 0);
this.V = this.C = false;
this.m_Cycles += 4;
}
}
}

View File

@ -1,271 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MC68000
{
public partial class MC68K
{
private void ANDI_to_CCR()
{
Helpers.Inject(ref this.m_SR, (byte)(this.m_SR & FetchW()));
this.m_Cycles += 20;
}
private void ANDI_to_SR()
{
if (this.S)
{
this.m_SR &= FetchW();
// Might not be in supervisor mode any more...
if (!this.S)
{
this.m_Ssp = this.SP;
this.SP = this.m_Usp;
}
this.m_Cycles += 20;
}
else
{
// TODO - cycle counter
Trap(8);
}
}
private void CHK()
{
int registerToCheck = (this.m_IR >> 9) & 0x7;
int size = (this.m_IR >> 7) & 0x3;
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
// Only word size is legal on the 68000
if ((short)this.m_D[registerToCheck] < 0)
{
this.N = true;
Trap(6);
}
else if ((short)this.m_D[registerToCheck] > FetchOperandW(mode, size))
{
this.N = false;
Trap(6);
}
else
{
this.m_Cycles += 10 + Helpers.EACalcTimeBW(mode, register);
}
}
private void EORI_to_CCR()
{
Helpers.Inject(ref this.m_SR, (byte)(this.m_SR ^ FetchW()));
this.m_Cycles += 20;
}
private void EORI_to_SR()
{
if (this.S)
{
this.m_SR ^= FetchW();
// Might not be in supervisor mode any more...
if (!this.S)
{
this.m_Ssp = this.SP;
this.SP = this.m_Usp;
}
this.m_Cycles += 20;
}
else
{
// TODO - cycle counter
Trap(8);
}
}
private void ILLEGAL()
{
Trap(4);
}
private void MOVE_from_SR()
{
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
SetOperandW(mode, register, (short)this.m_SR);
this.m_Cycles += (mode == 0) ? 6 : 8 + Helpers.EACalcTimeBW(mode, register);
}
private void MOVE_to_CCR()
{
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
this.m_SR &= 0xFF00;
this.m_SR |= (ushort)(FetchOperandW(mode, register) & 0x00FF);
this.m_Cycles += (mode == 0) ? 12 : 12 + Helpers.EACalcTimeBW(mode, register);
}
private void MOVE_to_SR() // Move to the Status Register
{
int mode = (this.m_IR >> 3) & 0x7;
int register = this.m_IR & 0x7;
if (this.S)
{
this.m_SR = (ushort)FetchOperandW(mode, register);
this.m_Cycles += (mode == 0) ? 12 : 12 + Helpers.EACalcTimeBW(mode, register);
// Might not be in supervisor mode now...
if (!this.S)
{
this.m_Ssp = this.SP;
this.SP = this.m_Usp;
}
}
else
{
Trap(8);
}
}
private void MOVE_USP() // Move User Stack Pointer
{
if (this.S)
{
if (((this.m_IR >> 3) & 0x1) == 0)
{
this.m_Usp = this.m_A[this.m_IR & 0x7];
}
else
{
this.m_A[this.m_IR & 0x7] = this.m_Usp;
}
this.m_Cycles += 4;
}
else
{
// TODO Cycles
Trap(8);
}
}
private void ORI_to_CCR()
{
Helpers.Inject(ref this.m_SR, (byte)(this.m_SR | (ushort)FetchW()));
this.m_Cycles += 20;
}
private void ORI_to_SR()
{
if (this.S)
{
this.m_SR |= (ushort)FetchW();
// Might not be in supervisor mode any more...
if (!this.S)
{
this.m_Ssp = this.SP;
this.SP = this.m_Usp;
}
this.m_Cycles += 20;
}
else
{
// TODO - TRAP, cycle counter
throw new NotImplementedException();
}
}
private void RESET()
{
this.m_Cycles += 132;
throw new NotImplementedException();
}
private void RTE()
{
if (this.S)
{
this.m_SR = (ushort)ReadW(this.SP);
this.SP += 2;
this.m_PC = ReadL(this.SP);
this.SP += 4;
// Might not be in supervisor mode any more...
if (!this.S)
{
this.m_Ssp = this.SP;
this.SP = this.m_Usp;
}
this.m_Cycles += 20;
}
else
{
// Privilege exception
Trap(8);
}
}
private void RTR()
{
// Seems a bit like RTE, but only affects condition codes
this.m_SR = (ushort)((0x00FF & ReadW(this.m_Ssp)) | (0xFF00 & this.m_SR));
this.SP += 2;
this.m_PC = ReadL(this.SP);
this.SP += 4;
this.m_Cycles += 20;
}
private void STOP()
{
this.m_Cycles += 4;
throw new NotImplementedException();
}
private void Trap(int trapVector)
{
// Make sure we're in supervisor mode
if (!this.S)
{
this.m_Usp = this.SP;
this.SP = this.m_Ssp;
}
// Add stack frame
this.SP -= 4;
WriteL(this.SP, this.m_PC);
this.SP -= 2;
WriteW(this.SP, (short)this.m_SR);
// Enter supervisor mode
this.S = true;
// Get vector address from ROM header
this.m_PC = ReadL(trapVector * 4);
}
private void TRAP()
{
int trapVector = (this.m_IR & 0x000F);
Trap(trapVector + 32);
}
private void TRAPV()
{
this.m_Cycles += 4;
if (this.V)
{
Trap(7);
}
}
}
}

View File

@ -11,7 +11,7 @@
- Ys IV
- Graphics corruption:
- Buster Bros, check seagull during opening
- Camp California, check seagull during opening
- In part of Dungeon Explorer II intro
- Popful Mail... some corruption on Turbo Engine too.... and pcejin?
@ -25,7 +25,6 @@ Arcade Card games:
- Record of Lodoss War wont start game from title screen
- Valis: Screen is black during entire intro section
- Valis III: playable,gfx issue on title screen... possible due to not updating VDC regs on LSB? really should just fix that once at for all...
======= TurboGrafx compatibility issues =======

View File

@ -4,18 +4,16 @@ using System.IO;
using BizHawk.Emulation.CPUs.M68K;
using BizHawk.Emulation.CPUs.Z80;
using BizHawk.Emulation.Sound;
using MC68000;
namespace BizHawk.Emulation.Consoles.Sega
{
public sealed partial class Genesis : IEmulator, IMemoryController
public sealed partial class Genesis : IEmulator
{
// ROM
public byte[] RomData;
// Machine stuff
public MC68K MainCPU; // TODO un-static
public M68000 _MainCPU;
public M68000 MainCPU;
public Z80A SoundCPU;
public GenVDP VDP;
public SN76489 PSG;
@ -55,12 +53,10 @@ namespace BizHawk.Emulation.Consoles.Sega
// 320 are active display, the remaining 160 are horizontal blanking.
// A total of 3420 mclks per line, but 2560 mclks are active display and 860 mclks are blanking.
public Genesis(bool sega360)
public Genesis()
{
CoreOutputComm = new CoreOutputComm();
if (sega360) MainCPU = new MC68K(this);
_MainCPU = new M68000();
MainCPU = new M68000();
SoundCPU = new Z80A();
YM2612 = new YM2612();
PSG = new SN76489();
@ -68,12 +64,12 @@ namespace BizHawk.Emulation.Consoles.Sega
VDP.DmaReadFrom68000 = ReadW;
SoundMixer = new SoundMixer(YM2612, PSG);
_MainCPU.ReadByte = ReadB;
_MainCPU.ReadWord = ReadW;
_MainCPU.ReadLong = ReadL;
_MainCPU.WriteByte = WriteB;
_MainCPU.WriteWord = WriteW;
_MainCPU.WriteLong = WriteL;
MainCPU.ReadByte = ReadB;
MainCPU.ReadWord = ReadW;
MainCPU.ReadLong = ReadL;
MainCPU.WriteByte = WriteB;
MainCPU.WriteWord = WriteW;
MainCPU.WriteLong = WriteL;
SoundCPU.ReadMemory = ReadMemoryZ80;
SoundCPU.WriteMemory = WriteMemoryZ80;
@ -95,16 +91,6 @@ namespace BizHawk.Emulation.Consoles.Sega
_MainCPU.Reset();
}*/
public void StepMine()
{
_MainCPU.Step();
}
public void StepHis()
{
MainCPU.Step();
}
public void FrameAdvance(bool render)
{
Frame++;
@ -116,7 +102,7 @@ namespace BizHawk.Emulation.Consoles.Sega
if (VDP.ScanLine < 224)
VDP.RenderLine();
_MainCPU.ExecuteCycles(488);
MainCPU.ExecuteCycles(488);
if (Z80Runnable)
{
//Console.WriteLine("running z80");
@ -127,8 +113,8 @@ namespace BizHawk.Emulation.Consoles.Sega
if (VDP.ScanLine == 224)
{
// End-frame stuff
if (VDP.VInterruptEnabled)
MainCPU.Interrupt(6);
/*if (VDP.VInterruptEnabled)
MainCPU.Interrupt(6);*/
if (Z80Runnable)
SoundCPU.Interrupt = true;

View File

@ -1043,7 +1043,7 @@ namespace BizHawk.MultiClient
nextEmulator = new PCEngine(game, rom.RomData);
break;
case "GEN":
nextEmulator = new Genesis(true); //TODO
nextEmulator = new Genesis(); //TODO
break;
case "TI83":
nextEmulator = new TI83(game, rom.RomData);