BizHawk/BizHawk.Emulation/CPUs/MC68000/Operations/DataMovement.cs

397 lines
9.5 KiB
C#
Raw Normal View History

2011-01-11 02:55:51 +00:00
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;
}
}
}