Cores/Nds/ARMInterpreter_Thumb.cs
using System.Numerics;
namespace Emulotl.Nds;
public static partial class ARMInterpreter
{
private static void FillThumb( int start, int count, InstrFunc fn )
{
for ( int i = 0; i < count; i++ )
THUMBInstrTable[start + i] = fn;
}
private static void BuildThumbTable()
{
FillThumb( 0x000, 0x20, T_LSL_IMM );
FillThumb( 0x020, 0x20, T_LSR_IMM );
FillThumb( 0x040, 0x20, T_ASR_IMM );
FillThumb( 0x060, 0x08, T_ADD_REG_ ); FillThumb( 0x068, 0x08, T_SUB_REG_ );
FillThumb( 0x070, 0x08, T_ADD_IMM_ ); FillThumb( 0x078, 0x08, T_SUB_IMM_ );
FillThumb( 0x080, 0x20, T_MOV_IMM );
FillThumb( 0x0A0, 0x20, T_CMP_IMM );
FillThumb( 0x0C0, 0x20, T_ADD_IMM );
FillThumb( 0x0E0, 0x20, T_SUB_IMM );
THUMBInstrTable[0x100] = T_AND_REG;
THUMBInstrTable[0x101] = T_EOR_REG;
THUMBInstrTable[0x102] = T_LSL_REG;
THUMBInstrTable[0x103] = T_LSR_REG;
THUMBInstrTable[0x104] = T_ASR_REG;
THUMBInstrTable[0x105] = T_ADC_REG;
THUMBInstrTable[0x106] = T_SBC_REG;
THUMBInstrTable[0x107] = T_ROR_REG;
THUMBInstrTable[0x108] = T_TST_REG;
THUMBInstrTable[0x109] = T_NEG_REG;
THUMBInstrTable[0x10A] = T_CMP_REG;
THUMBInstrTable[0x10B] = T_CMN_REG;
THUMBInstrTable[0x10C] = T_ORR_REG;
THUMBInstrTable[0x10D] = T_MUL_REG;
THUMBInstrTable[0x10E] = T_BIC_REG;
THUMBInstrTable[0x10F] = T_MVN_REG;
FillThumb( 0x110, 4, T_ADD_HIREG );
FillThumb( 0x114, 4, T_CMP_HIREG );
FillThumb( 0x118, 4, T_MOV_HIREG );
THUMBInstrTable[0x11C] = T_BX;
THUMBInstrTable[0x11D] = T_BX;
THUMBInstrTable[0x11E] = T_BLX_REG;
THUMBInstrTable[0x11F] = T_BLX_REG;
FillThumb( 0x120, 0x20, T_LDR_PCREL );
FillThumb( 0x140, 8, T_STR_REG ); FillThumb( 0x148, 8, T_STRH_REG );
FillThumb( 0x150, 8, T_STRB_REG ); FillThumb( 0x158, 8, T_LDRSB_REG );
FillThumb( 0x160, 8, T_LDR_REG ); FillThumb( 0x168, 8, T_LDRH_REG );
FillThumb( 0x170, 8, T_LDRB_REG ); FillThumb( 0x178, 8, T_LDRSH_REG );
FillThumb( 0x180, 0x20, T_STR_IMM );
FillThumb( 0x1A0, 0x20, T_LDR_IMM );
FillThumb( 0x1C0, 0x20, T_STRB_IMM );
FillThumb( 0x1E0, 0x20, T_LDRB_IMM );
FillThumb( 0x200, 0x20, T_STRH_IMM );
FillThumb( 0x220, 0x20, T_LDRH_IMM );
FillThumb( 0x240, 0x20, T_STR_SPREL );
FillThumb( 0x260, 0x20, T_LDR_SPREL );
FillThumb( 0x280, 0x20, T_ADD_PCREL );
FillThumb( 0x2A0, 0x20, T_ADD_SPREL );
FillThumb( 0x2C0, 4, T_ADD_SP );
FillThumb( 0x2D0, 8, T_PUSH );
FillThumb( 0x2F0, 8, T_POP );
FillThumb( 0x300, 0x20, T_STMIA );
FillThumb( 0x320, 0x20, T_LDMIA );
FillThumb( 0x340, 0x30, T_BCOND );
FillThumb( 0x370, 8, T_BCOND );
FillThumb( 0x37C, 4, T_SVC );
FillThumb( 0x380, 0x20, T_B );
FillThumb( 0x3A0, 0x20, T_BL_LONG_2 );
FillThumb( 0x3C0, 0x20, T_BL_LONG_1 );
FillThumb( 0x3E0, 0x20, T_BL_LONG_2 );
}
public static void T_LSL_IMM( ARM cpu )
{
uint op = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint s = (cpu.CurInstr >> 6) & 0x1F;
Shift( cpu, ref op, s, 0, false, true );
cpu.R[cpu.CurInstr & 0x7] = op;
cpu.SetNZ( (op & 0x80000000) != 0, op == 0 );
cpu.AddCycles_C();
}
public static void T_LSR_IMM( ARM cpu )
{
uint op = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint s = (cpu.CurInstr >> 6) & 0x1F;
Shift( cpu, ref op, s, 1, false, true );
cpu.R[cpu.CurInstr & 0x7] = op;
cpu.SetNZ( (op & 0x80000000) != 0, op == 0 );
cpu.AddCycles_C();
}
public static void T_ASR_IMM( ARM cpu )
{
uint op = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint s = (cpu.CurInstr >> 6) & 0x1F;
Shift( cpu, ref op, s, 2, false, true );
cpu.R[cpu.CurInstr & 0x7] = op;
cpu.SetNZ( (op & 0x80000000) != 0, op == 0 );
cpu.AddCycles_C();
}
public static void T_ADD_REG_( ARM cpu )
{
uint a = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 6) & 0x7];
uint res = a + b;
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarryAdd( a, b ), OverflowAdd( a, b ) );
cpu.AddCycles_C();
}
public static void T_SUB_REG_( ARM cpu )
{
uint a = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 6) & 0x7];
uint res = a - b;
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarrySub( a, b ), OverflowSub( a, b ) );
cpu.AddCycles_C();
}
public static void T_ADD_IMM_( ARM cpu )
{
uint a = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint b = (cpu.CurInstr >> 6) & 0x7;
uint res = a + b;
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarryAdd( a, b ), OverflowAdd( a, b ) );
cpu.AddCycles_C();
}
public static void T_SUB_IMM_( ARM cpu )
{
uint a = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint b = (cpu.CurInstr >> 6) & 0x7;
uint res = a - b;
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarrySub( a, b ), OverflowSub( a, b ) );
cpu.AddCycles_C();
}
public static void T_MOV_IMM( ARM cpu )
{
uint b = cpu.CurInstr & 0xFF;
cpu.R[(cpu.CurInstr >> 8) & 0x7] = b;
cpu.SetNZ( false, b == 0 );
cpu.AddCycles_C();
}
public static void T_CMP_IMM( ARM cpu )
{
uint a = cpu.R[(cpu.CurInstr >> 8) & 0x7];
uint b = cpu.CurInstr & 0xFF;
uint res = a - b;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarrySub( a, b ), OverflowSub( a, b ) );
cpu.AddCycles_C();
}
public static void T_ADD_IMM( ARM cpu )
{
uint a = cpu.R[(cpu.CurInstr >> 8) & 0x7];
uint b = cpu.CurInstr & 0xFF;
uint res = a + b;
cpu.R[(cpu.CurInstr >> 8) & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarryAdd( a, b ), OverflowAdd( a, b ) );
cpu.AddCycles_C();
}
public static void T_SUB_IMM( ARM cpu )
{
uint a = cpu.R[(cpu.CurInstr >> 8) & 0x7];
uint b = cpu.CurInstr & 0xFF;
uint res = a - b;
cpu.R[(cpu.CurInstr >> 8) & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarrySub( a, b ), OverflowSub( a, b ) );
cpu.AddCycles_C();
}
public static void T_AND_REG( ARM cpu )
{
uint res = cpu.R[cpu.CurInstr & 0x7] & cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZ( (res & 0x80000000) != 0, res == 0 );
cpu.AddCycles_C();
}
public static void T_EOR_REG( ARM cpu )
{
uint res = cpu.R[cpu.CurInstr & 0x7] ^ cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZ( (res & 0x80000000) != 0, res == 0 );
cpu.AddCycles_C();
}
public static void T_LSL_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7] & 0xFF;
Shift( cpu, ref a, b, 0, true, true );
cpu.R[cpu.CurInstr & 0x7] = a;
cpu.SetNZ( (a & 0x80000000) != 0, a == 0 );
cpu.AddCycles_CI( 1 );
}
public static void T_LSR_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7] & 0xFF;
Shift( cpu, ref a, b, 1, true, true );
cpu.R[cpu.CurInstr & 0x7] = a;
cpu.SetNZ( (a & 0x80000000) != 0, a == 0 );
cpu.AddCycles_CI( 1 );
}
public static void T_ASR_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7] & 0xFF;
Shift( cpu, ref a, b, 2, true, true );
cpu.R[cpu.CurInstr & 0x7] = a;
cpu.SetNZ( (a & 0x80000000) != 0, a == 0 );
cpu.AddCycles_CI( 1 );
}
public static void T_ADC_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint resTmp = a + b;
uint carry = (cpu.CPSR & 0x20000000) != 0 ? 1u : 0u;
uint res = resTmp + carry;
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarryAdd( a, b ) | CarryAdd( resTmp, carry ), OverflowAdc( a, b, carry ) );
cpu.AddCycles_C();
}
public static void T_SBC_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint resTmp = a - b;
uint carry = (cpu.CPSR & 0x20000000) != 0 ? 0u : 1u;
uint res = resTmp - carry;
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarrySub( a, b ) && CarrySub( resTmp, carry ), OverflowSbc( a, b, carry ) );
cpu.AddCycles_C();
}
public static void T_ROR_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7] & 0xFF;
Shift( cpu, ref a, b, 3, true, true );
cpu.R[cpu.CurInstr & 0x7] = a;
cpu.SetNZ( (a & 0x80000000) != 0, a == 0 );
cpu.AddCycles_CI( 1 );
}
public static void T_TST_REG( ARM cpu )
{
uint res = cpu.R[cpu.CurInstr & 0x7] & cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.SetNZ( (res & 0x80000000) != 0, res == 0 );
cpu.AddCycles_C();
}
public static void T_NEG_REG( ARM cpu )
{
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint res = 0u - b;
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarrySub( 0, b ), OverflowSub( 0, b ) );
cpu.AddCycles_C();
}
public static void T_CMP_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint res = a - b;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarrySub( a, b ), OverflowSub( a, b ) );
cpu.AddCycles_C();
}
public static void T_CMN_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint res = a + b;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarryAdd( a, b ), OverflowAdd( a, b ) );
cpu.AddCycles_C();
}
public static void T_ORR_REG( ARM cpu )
{
uint res = cpu.R[cpu.CurInstr & 0x7] | cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZ( (res & 0x80000000) != 0, res == 0 );
cpu.AddCycles_C();
}
public static void T_MUL_REG( ARM cpu )
{
uint a = cpu.R[cpu.CurInstr & 0x7];
uint b = cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint res = a * b;
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZ( (res & 0x80000000) != 0, res == 0 );
int cycles = 0;
if ( cpu.Num == 0 )
{
cycles += 3;
}
else
{
cpu.SetC( false );
if ( (a & 0xFF000000) != 0 ) cycles += 4;
else if ( (a & 0x00FF0000) != 0 ) cycles += 3;
else if ( (a & 0x0000FF00) != 0 ) cycles += 2;
else cycles += 1;
}
cpu.AddCycles_CI( cycles );
}
public static void T_BIC_REG( ARM cpu )
{
uint res = cpu.R[cpu.CurInstr & 0x7] & ~cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZ( (res & 0x80000000) != 0, res == 0 );
cpu.AddCycles_C();
}
public static void T_MVN_REG( ARM cpu )
{
uint res = ~cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.R[cpu.CurInstr & 0x7] = res;
cpu.SetNZ( (res & 0x80000000) != 0, res == 0 );
cpu.AddCycles_C();
}
public static void T_ADD_HIREG( ARM cpu )
{
uint rd = (cpu.CurInstr & 0x7) | ((cpu.CurInstr >> 4) & 0x8);
uint rs = (cpu.CurInstr >> 3) & 0xF;
uint a = cpu.R[rd];
uint b = cpu.R[rs];
cpu.AddCycles_C();
if ( rd == 15 ) cpu.JumpTo( (a + b) | 1 );
else cpu.R[rd] = a + b;
}
public static void T_CMP_HIREG( ARM cpu )
{
uint rd = (cpu.CurInstr & 0x7) | ((cpu.CurInstr >> 4) & 0x8);
uint rs = (cpu.CurInstr >> 3) & 0xF;
uint a = cpu.R[rd];
uint b = cpu.R[rs];
uint res = a - b;
cpu.SetNZCV( (res & 0x80000000) != 0, res == 0, CarrySub( a, b ), OverflowSub( a, b ) );
cpu.AddCycles_C();
}
public static void T_MOV_HIREG( ARM cpu )
{
uint rd = (cpu.CurInstr & 0x7) | ((cpu.CurInstr >> 4) & 0x8);
uint rs = (cpu.CurInstr >> 3) & 0xF;
cpu.AddCycles_C();
if ( rd == 15 ) cpu.JumpTo( cpu.R[rs] | 1 );
else cpu.R[rd] = cpu.R[rs];
}
public static void T_ADD_PCREL( ARM cpu )
{
uint val = cpu.R[15] & ~2u;
val += (cpu.CurInstr & 0xFF) << 2;
cpu.R[(cpu.CurInstr >> 8) & 0x7] = val;
cpu.AddCycles_C();
}
public static void T_ADD_SPREL( ARM cpu )
{
uint val = cpu.R[13];
val += (cpu.CurInstr & 0xFF) << 2;
cpu.R[(cpu.CurInstr >> 8) & 0x7] = val;
cpu.AddCycles_C();
}
public static void T_ADD_SP( ARM cpu )
{
uint val = cpu.R[13];
if ( (cpu.CurInstr & (1 << 7)) != 0 )
val -= (cpu.CurInstr & 0x7F) << 2;
else
val += (cpu.CurInstr & 0x7F) << 2;
cpu.R[13] = val;
cpu.AddCycles_C();
}
public static void T_LDR_PCREL( ARM cpu )
{
uint addr = (cpu.R[15] & ~0x2u) + ((cpu.CurInstr & 0xFF) << 2);
uint val = 0;
cpu.DataRead32( addr, ref val );
cpu.R[(cpu.CurInstr >> 8) & 0x7] = val;
cpu.AddCycles_CDI();
}
public static void T_STR_REG( ARM cpu )
{
uint addr = cpu.R[(cpu.CurInstr >> 3) & 0x7] + cpu.R[(cpu.CurInstr >> 6) & 0x7];
cpu.DataWrite32( addr, cpu.R[cpu.CurInstr & 0x7] );
cpu.AddCycles_CD();
}
public static void T_STRB_REG( ARM cpu )
{
uint addr = cpu.R[(cpu.CurInstr >> 3) & 0x7] + cpu.R[(cpu.CurInstr >> 6) & 0x7];
cpu.DataWrite8( addr, (byte)cpu.R[cpu.CurInstr & 0x7] );
cpu.AddCycles_CD();
}
public static void T_LDR_REG( ARM cpu )
{
uint addr = cpu.R[(cpu.CurInstr >> 3) & 0x7] + cpu.R[(cpu.CurInstr >> 6) & 0x7];
uint val = 0;
cpu.DataRead32( addr, ref val );
cpu.R[cpu.CurInstr & 0x7] = ARM.ROR( val, 8 * (addr & 0x3) );
cpu.AddCycles_CDI();
}
public static void T_LDRB_REG( ARM cpu )
{
uint addr = cpu.R[(cpu.CurInstr >> 3) & 0x7] + cpu.R[(cpu.CurInstr >> 6) & 0x7];
uint val = 0;
cpu.DataRead8( addr, ref val );
cpu.R[cpu.CurInstr & 0x7] = val;
cpu.AddCycles_CDI();
}
public static void T_STRH_REG( ARM cpu )
{
uint addr = cpu.R[(cpu.CurInstr >> 3) & 0x7] + cpu.R[(cpu.CurInstr >> 6) & 0x7];
cpu.DataWrite16( addr, (ushort)cpu.R[cpu.CurInstr & 0x7] );
cpu.AddCycles_CD();
}
public static void T_LDRSB_REG( ARM cpu )
{
uint addr = cpu.R[(cpu.CurInstr >> 3) & 0x7] + cpu.R[(cpu.CurInstr >> 6) & 0x7];
uint val = 0;
cpu.DataRead8( addr, ref val );
cpu.R[cpu.CurInstr & 0x7] = (uint)(sbyte)val;
cpu.AddCycles_CDI();
}
public static void T_LDRH_REG( ARM cpu )
{
uint addr = cpu.R[(cpu.CurInstr >> 3) & 0x7] + cpu.R[(cpu.CurInstr >> 6) & 0x7];
uint val = 0;
cpu.DataRead16( addr, ref val );
cpu.R[cpu.CurInstr & 0x7] = val;
cpu.AddCycles_CDI();
}
public static void T_LDRSH_REG( ARM cpu )
{
uint addr = cpu.R[(cpu.CurInstr >> 3) & 0x7] + cpu.R[(cpu.CurInstr >> 6) & 0x7];
uint val = 0;
cpu.DataRead16( addr, ref val );
cpu.R[cpu.CurInstr & 0x7] = (uint)(short)val;
cpu.AddCycles_CDI();
}
public static void T_STR_IMM( ARM cpu )
{
uint offset = (cpu.CurInstr >> 4) & 0x7C;
offset += cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.DataWrite32( offset, cpu.R[cpu.CurInstr & 0x7] );
cpu.AddCycles_CD();
}
public static void T_LDR_IMM( ARM cpu )
{
uint offset = (cpu.CurInstr >> 4) & 0x7C;
offset += cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint val = 0;
cpu.DataRead32( offset, ref val );
cpu.R[cpu.CurInstr & 0x7] = ARM.ROR( val, 8 * (offset & 0x3) );
cpu.AddCycles_CDI();
}
public static void T_STRB_IMM( ARM cpu )
{
uint offset = (cpu.CurInstr >> 6) & 0x1F;
offset += cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.DataWrite8( offset, (byte)cpu.R[cpu.CurInstr & 0x7] );
cpu.AddCycles_CD();
}
public static void T_LDRB_IMM( ARM cpu )
{
uint offset = (cpu.CurInstr >> 6) & 0x1F;
offset += cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint val = 0;
cpu.DataRead8( offset, ref val );
cpu.R[cpu.CurInstr & 0x7] = val;
cpu.AddCycles_CDI();
}
public static void T_STRH_IMM( ARM cpu )
{
uint offset = (cpu.CurInstr >> 5) & 0x3E;
offset += cpu.R[(cpu.CurInstr >> 3) & 0x7];
cpu.DataWrite16( offset, (ushort)cpu.R[cpu.CurInstr & 0x7] );
cpu.AddCycles_CD();
}
public static void T_LDRH_IMM( ARM cpu )
{
uint offset = (cpu.CurInstr >> 5) & 0x3E;
offset += cpu.R[(cpu.CurInstr >> 3) & 0x7];
uint val = 0;
cpu.DataRead16( offset, ref val );
cpu.R[cpu.CurInstr & 0x7] = val;
cpu.AddCycles_CDI();
}
public static void T_STR_SPREL( ARM cpu )
{
uint offset = (cpu.CurInstr << 2) & 0x3FC;
offset += cpu.R[13];
cpu.DataWrite32( offset, cpu.R[(cpu.CurInstr >> 8) & 0x7] );
cpu.AddCycles_CD();
}
public static void T_LDR_SPREL( ARM cpu )
{
uint offset = (cpu.CurInstr << 2) & 0x3FC;
offset += cpu.R[13];
uint val = 0;
cpu.DataRead32( offset, ref val );
cpu.R[(cpu.CurInstr >> 8) & 0x7] = val;
cpu.AddCycles_CDI();
}
public static void T_PUSH( ARM cpu )
{
int nregs = BitOperations.PopCount( cpu.CurInstr & 0x1FF );
bool first = true;
uint @base = cpu.R[13];
@base -= (uint)(nregs << 2);
cpu.R[13] = @base;
for ( int i = 0; i < 8; i++ )
{
if ( (cpu.CurInstr & (1 << i)) != 0 )
{
if ( first ) cpu.DataWrite32( @base, cpu.R[i] );
else cpu.DataWrite32S( @base, cpu.R[i] );
first = false;
@base += 4;
}
}
if ( (cpu.CurInstr & (1 << 8)) != 0 )
{
if ( first ) cpu.DataWrite32( @base, cpu.R[14] );
else cpu.DataWrite32S( @base, cpu.R[14] );
}
cpu.AddCycles_CD();
}
public static void T_POP( ARM cpu )
{
uint @base = cpu.R[13];
bool first = true;
for ( int i = 0; i < 8; i++ )
{
if ( (cpu.CurInstr & (1 << i)) != 0 )
{
uint v = 0;
if ( first ) cpu.DataRead32( @base, ref v );
else cpu.DataRead32S( @base, ref v );
cpu.R[i] = v;
first = false;
@base += 4;
}
}
if ( (cpu.CurInstr & (1 << 8)) != 0 )
{
uint pc = 0;
if ( first ) cpu.DataRead32( @base, ref pc );
else cpu.DataRead32S( @base, ref pc );
if ( cpu.Num == 1 ) pc |= 0x1;
cpu.JumpTo( pc );
@base += 4;
}
cpu.R[13] = @base;
cpu.AddCycles_CDI();
}
public static void T_STMIA( ARM cpu )
{
uint @base = cpu.R[(cpu.CurInstr >> 8) & 0x7];
bool first = true;
for ( int i = 0; i < 8; i++ )
{
if ( (cpu.CurInstr & (1 << i)) != 0 )
{
if ( first ) cpu.DataWrite32( @base, cpu.R[i] );
else cpu.DataWrite32S( @base, cpu.R[i] );
first = false;
@base += 4;
}
}
cpu.R[(cpu.CurInstr >> 8) & 0x7] = @base;
cpu.AddCycles_CD();
}
public static void T_LDMIA( ARM cpu )
{
uint @base = cpu.R[(cpu.CurInstr >> 8) & 0x7];
bool first = true;
for ( int i = 0; i < 8; i++ )
{
if ( (cpu.CurInstr & (1 << i)) != 0 )
{
uint v = 0;
if ( first ) cpu.DataRead32( @base, ref v );
else cpu.DataRead32S( @base, ref v );
cpu.R[i] = v;
first = false;
@base += 4;
}
}
if ( (cpu.CurInstr & (1 << (int)((cpu.CurInstr >> 8) & 0x7))) == 0 )
cpu.R[(cpu.CurInstr >> 8) & 0x7] = @base;
cpu.AddCycles_CDI();
}
}