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

870 lines
25 KiB
C#

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