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

208 lines
4.5 KiB
C#

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);
}
}
}