delete extra/external 68k core
This commit is contained in:
parent
58738c1af3
commit
f3dc6068ce
|
@ -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" />
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 =======
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue