BizHawk/attic/GarboDev/FastArmCore.cs

9916 lines
370 KiB
C#

//#define ARM_DEBUG
namespace GarboDev
{
using System;
public partial class FastArmCore
{
private const uint COND_EQ = 0; // Z set
private const uint COND_NE = 1; // Z clear
private const uint COND_CS = 2; // C set
private const uint COND_CC = 3; // C clear
private const uint COND_MI = 4; // N set
private const uint COND_PL = 5; // N clear
private const uint COND_VS = 6; // V set
private const uint COND_VC = 7; // V clear
private const uint COND_HI = 8; // C set and Z clear
private const uint COND_LS = 9; // C clear or Z set
private const uint COND_GE = 10; // N equals V
private const uint COND_LT = 11; // N not equal to V
private const uint COND_GT = 12; // Z clear AND (N equals V)
private const uint COND_LE = 13; // Z set OR (N not equal to V)
private const uint COND_AL = 14; // Always
private const uint COND_NV = 15; // Never execute
private const uint OP_AND = 0x0;
private const uint OP_EOR = 0x1;
private const uint OP_SUB = 0x2;
private const uint OP_RSB = 0x3;
private const uint OP_ADD = 0x4;
private const uint OP_ADC = 0x5;
private const uint OP_SBC = 0x6;
private const uint OP_RSC = 0x7;
private const uint OP_TST = 0x8;
private const uint OP_TEQ = 0x9;
private const uint OP_CMP = 0xA;
private const uint OP_CMN = 0xB;
private const uint OP_ORR = 0xC;
private const uint OP_MOV = 0xD;
private const uint OP_BIC = 0xE;
private const uint OP_MVN = 0xF;
private delegate void ExecuteInstructionDelegate();
private ExecuteInstructionDelegate[] NormalOps = null;
private Arm7Processor parent;
private Memory memory;
private uint[] registers;
private uint instructionQueue;
private uint curInstruction;
// CPU flags
private uint zero, carry, negative, overflow;
private uint shifterCarry;
private bool thumbMode;
public FastArmCore(Arm7Processor parent, Memory memory)
{
this.parent = parent;
this.memory = memory;
this.registers = this.parent.Registers;
this.NormalOps = new ExecuteInstructionDelegate[8]
{
this.UndefinedInstruction,
this.UndefinedInstruction,
this.UndefinedInstruction,
this.UndefinedInstruction,
this.LoadStoreMultiple,
this.UndefinedInstruction,
this.CoprocessorLoadStore,
this.UndefinedInstruction
};
this.InitializeDispatchFunc();
}
public void BeginExecution()
{
this.FlushQueue();
}
public void Step()
{
this.UnpackFlags();
this.curInstruction = this.instructionQueue;
this.instructionQueue = this.memory.ReadU32(registers[15]);
registers[15] += 4;
uint cond = 0;
switch (this.curInstruction >> 28)
{
case COND_AL: cond = 1; break;
case COND_EQ: cond = zero; break;
case COND_NE: cond = 1 - zero; break;
case COND_CS: cond = carry; break;
case COND_CC: cond = 1 - carry; break;
case COND_MI: cond = negative; break;
case COND_PL: cond = 1 - negative; break;
case COND_VS: cond = overflow; break;
case COND_VC: cond = 1 - overflow; break;
case COND_HI: cond = carry & (1 - zero); break;
case COND_LS: cond = (1 - carry) | zero; break;
case COND_GE: cond = (1 - negative) ^ overflow; break;
case COND_LT: cond = negative ^ overflow; break;
case COND_GT: cond = (1 - zero) & (negative ^ (1 - overflow)); break;
case COND_LE: cond = (negative ^ overflow) | zero; break;
}
if (cond == 1)
{
// Execute the instruction
this.ExecuteInstruction((ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF)));
}
this.parent.Cycles -= this.memory.WaitCycles;
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.parent.ReloadQueue();
}
this.PackFlags();
}
public void Execute()
{
this.UnpackFlags();
this.thumbMode = false;
while (this.parent.Cycles > 0)
{
this.curInstruction = this.instructionQueue;
this.instructionQueue = this.memory.ReadU32Aligned(registers[15]);
registers[15] += 4;
if ((this.curInstruction >> 28) == COND_AL)
{
this.fastDispatch[(ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF))]();
// this.ExecuteInstruction((ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF)));
}
else
{
uint cond = 0;
switch (this.curInstruction >> 28)
{
case COND_EQ: cond = zero; break;
case COND_NE: cond = 1 - zero; break;
case COND_CS: cond = carry; break;
case COND_CC: cond = 1 - carry; break;
case COND_MI: cond = negative; break;
case COND_PL: cond = 1 - negative; break;
case COND_VS: cond = overflow; break;
case COND_VC: cond = 1 - overflow; break;
case COND_HI: cond = carry & (1 - zero); break;
case COND_LS: cond = (1 - carry) | zero; break;
case COND_GE: cond = (1 - negative) ^ overflow; break;
case COND_LT: cond = negative ^ overflow; break;
case COND_GT: cond = (1 - zero) & (negative ^ (1 - overflow)); break;
case COND_LE: cond = (negative ^ overflow) | zero; break;
}
if (cond == 1)
{
// Execute the instruction
this.fastDispatch[(ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF))]();
// this.ExecuteInstruction((ushort)(((this.curInstruction >> 16) & 0xFF0) | ((this.curInstruction >> 4) & 0xF)));
}
}
this.parent.Cycles -= this.memory.WaitCycles;
if (this.thumbMode)
{
this.parent.ReloadQueue();
break;
}
#if ARM_DEBUG
// Check the current PC
if (this.parent.Breakpoints.ContainsKey(registers[15] - 4U))
{
this.parent.BreakpointHit = true;
break;
}
#endif
}
this.PackFlags();
}
private void DataProcessingWriteToR15()
{
// Prevent writing if no SPSR exists (this will be true for USER or SYSTEM mode)
if (this.parent.SPSRExists) this.parent.WriteCpsr(this.parent.SPSR);
this.UnpackFlags();
// Check for branch back to Thumb Mode
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
return;
}
// Otherwise, flush the instruction queue
this.FlushQueue();
}
private uint BarrelShifterLslImmed()
{
// rm lsl immed
uint rm = registers[this.curInstruction & 0xF];
int amount = (int)((this.curInstruction >> 7) & 0x1F);
if (amount == 0)
{
this.shifterCarry = this.carry;
return rm;
}
else
{
this.shifterCarry = (rm >> (32 - amount)) & 1;
return rm << amount;
}
}
private uint BarrelShifterLslReg()
{
// rm lsl rs
uint rm = registers[this.curInstruction & 0xF];
uint rs = (this.curInstruction >> 8) & 0xF;
int amount;
if (rs == 15)
{
amount = (int)((registers[rs] + 0x4) & 0xFF);
}
else
{
amount = (int)(registers[rs] & 0xFF);
}
if ((this.curInstruction & 0xF) == 15)
{
rm += 4;
}
if (amount == 0)
{
this.shifterCarry = this.carry;
return rm;
}
if (amount < 32)
{
this.shifterCarry = (rm >> (32 - amount)) & 1;
return rm << amount;
}
else if (amount == 32)
{
this.shifterCarry = rm & 1;
return 0;
}
else
{
this.shifterCarry = 0;
return 0;
}
}
private uint BarrelShifterLsrImmed()
{
// rm lsr immed
uint rm = registers[this.curInstruction & 0xF];
int amount = (int)((this.curInstruction >> 7) & 0x1F);
if (amount == 0)
{
this.shifterCarry = (rm >> 31) & 1;
return 0;
}
else
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return rm >> amount;
}
}
private uint BarrelShifterLsrReg()
{
// rm lsr rs
uint rm = registers[this.curInstruction & 0xF];
uint rs = (this.curInstruction >> 8) & 0xF;
int amount;
if (rs == 15)
{
amount = (int)((registers[rs] + 0x4) & 0xFF);
}
else
{
amount = (int)(registers[rs] & 0xFF);
}
if ((this.curInstruction & 0xF) == 15)
{
rm += 4;
}
if (amount == 0)
{
this.shifterCarry = this.carry;
return rm;
}
if (amount < 32)
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return rm >> amount;
}
else if (amount == 32)
{
this.shifterCarry = (rm >> 31) & 1;
return 0;
}
else
{
this.shifterCarry = 0;
return 0;
}
}
private uint BarrelShifterAsrImmed()
{
// rm asr immed
uint rm = registers[this.curInstruction & 0xF];
int amount = (int)((this.curInstruction >> 7) & 0x1F);
if (amount == 0)
{
if ((rm & (1 << 31)) == 0)
{
this.shifterCarry = 0;
return 0;
}
else
{
this.shifterCarry = 1;
return 0xFFFFFFFF;
}
}
else
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return (uint)(((int)rm) >> amount);
}
}
private uint BarrelShifterAsrReg()
{
// rm asr rs
uint rm = registers[this.curInstruction & 0xF];
uint rs = (this.curInstruction >> 8) & 0xF;
int amount;
if (rs == 15)
{
amount = (int)((registers[rs] + 0x4) & 0xFF);
}
else
{
amount = (int)(registers[rs] & 0xFF);
}
if ((this.curInstruction & 0xF) == 15)
{
rm += 4;
}
if (amount == 0)
{
this.shifterCarry = this.carry;
return rm;
}
if (amount >= 32)
{
if ((rm & (1 << 31)) == 0)
{
this.shifterCarry = 0;
return 0;
}
else
{
this.shifterCarry = 1;
return 0xFFFFFFFF;
}
}
else
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return (uint)(((int)rm) >> amount);
}
}
private uint BarrelShifterRorImmed()
{
// rm ror immed
uint rm = registers[this.curInstruction & 0xF];
int amount = (int)((this.curInstruction >> 7) & 0x1F);
if (amount == 0)
{
// Actually an RRX
this.shifterCarry = rm & 1;
return (this.carry << 31) | (rm >> 1);
}
else
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return (rm >> amount) | (rm << (32 - amount));
}
}
private uint BarrelShifterRorReg()
{
// rm ror rs
uint rm = registers[this.curInstruction & 0xF];
uint rs = (this.curInstruction >> 8) & 0xF;
int amount;
if (rs == 15)
{
amount = (int)((registers[rs] + 0x4) & 0xFF);
}
else
{
amount = (int)(registers[rs] & 0xFF);
}
if ((this.curInstruction & 0xF) == 15)
{
rm += 4;
}
if (amount == 0)
{
this.shifterCarry = this.carry;
return rm;
}
if ((amount & 0x1F) == 0)
{
this.shifterCarry = (rm >> 31) & 1;
return rm;
}
else
{
amount &= 0x1F;
this.shifterCarry = (rm >> amount) & 1;
return (rm >> amount) | (rm << (32 - amount));
}
}
private uint BarrelShifterImmed()
{
uint immed = this.curInstruction & 0xFF;
int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2);
if (rotateAmount == 0)
{
this.shifterCarry = this.carry;
return immed;
}
else
{
immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount));
this.shifterCarry = (immed >> 31) & 1;
return immed;
}
}
private int MultiplyCycleCalculation(uint rs)
{
// Multiply cycle calculations
if ((registers[rs] & 0xFFFFFF00) == 0 || (registers[rs] & 0xFFFFFF00) == 0xFFFFFF00)
{
return 1;
}
else if ((registers[rs] & 0xFFFF0000) == 0 || (registers[rs] & 0xFFFF0000) == 0xFFFF0000)
{
return 2;
}
else if ((registers[rs] & 0xFF000000) == 0 || (registers[rs] & 0xFF000000) == 0xFF000000)
{
return 3;
}
return 4;
}
private void UndefinedInstruction()
{
// Do the undefined instruction dance here
throw new Exception("Undefined exception");
}
private void ExecuteInstruction(ushort op)
{
// Not emulating rn += 4 when register shift, in data operand when rn == pc
uint rn, rd, rs, rm, address, offset, shifterOperand, alu;
int cycles;
switch (op)
{
////////////////////////////////////////////////////////////////////////////////////////////
//
// AND implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x000:
case 0x008:
// AND rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterLslImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x001:
// AND rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterLslReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x002:
case 0x00A:
// AND rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterLsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x003:
// AND rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterLsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x004:
case 0x00C:
// AND rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterAsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x005:
// AND rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterAsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x006:
case 0x00E:
// AND rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterRorImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x007:
// AND rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterRorReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x010:
case 0x018:
// ANDS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterLslImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x011:
// ANDS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterLslReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x012:
case 0x01A:
// ANDS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterLsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x013:
// ANDS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterLsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x014:
case 0x01C:
// ANDS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterAsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x015:
// ANDS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterAsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x016:
case 0x01E:
// ANDS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterRorImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x017:
// ANDS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & BarrelShifterRorReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// Undefined instruction implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x00D: case 0x02D: case 0x04D: case 0x06D:
case 0x08D: case 0x0AD: case 0x0CD: case 0x0ED:
case 0x10D: case 0x12D: case 0x14D: case 0x16D:
case 0x18D: case 0x1AD: case 0x1CD: case 0x1ED:
case 0x00F: case 0x02F: case 0x04F: case 0x06F:
case 0x08F: case 0x0AF: case 0x0CF: case 0x0EF:
case 0x10F: case 0x12F: case 0x14F: case 0x16F:
case 0x18F: case 0x1AF: case 0x1CF: case 0x1EF:
UndefinedInstruction();
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// MUL implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x009:
// MUL rd, rm, rs
rd = (this.curInstruction >> 16) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs);
registers[rd] = registers[rs] * registers[rm];
this.parent.Cycles -= cycles;
break;
case 0x019:
// MULS rd, rm, rs
rd = (this.curInstruction >> 16) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs);
registers[rd] = registers[rs] * registers[rm];
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.parent.Cycles -= cycles;
break;
case 0x029:
// MLA rd, rm, rs, rn
rd = (this.curInstruction >> 16) & 0xF;
rn = registers[(this.curInstruction >> 12) & 0xF];
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs);
registers[rd] = registers[rs] * registers[rm] + rn;
this.parent.Cycles -= cycles + 1;
break;
case 0x039:
// MLAS rd, rm, rs
rd = (this.curInstruction >> 16) & 0xF;
rn = registers[(this.curInstruction >> 12) & 0xF];
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs);
registers[rd] = registers[rs] * registers[rm] + rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.parent.Cycles -= cycles + 1;
break;
case 0x089:
// UMULL rdlo, rdhi, rm, rs
{
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs) + 1;
ulong result = ((ulong)registers[rm]) * registers[rs];
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
this.parent.Cycles -= cycles;
}
break;
case 0x099:
// UMULLS rdlo, rdhi, rm, rs
{
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs) + 1;
ulong result = ((ulong)registers[rm]) * registers[rs];
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
negative = registers[rdhi] >> 31;
zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U;
this.parent.Cycles -= cycles;
}
break;
case 0x0A9:
// UMLAL rdlo, rdhi, rm, rs
{
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs) + 2;
ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo];
ulong result = ((ulong)registers[rm]) * registers[rs];
result += accum;
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
this.parent.Cycles -= cycles;
}
break;
case 0x0B9:
// UMLALS rdlo, rdhi, rm, rs
{
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs) + 2;
ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo];
ulong result = ((ulong)registers[rm]) * registers[rs];
result += accum;
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
negative = registers[rdhi] >> 31;
zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U;
this.parent.Cycles -= cycles;
}
break;
case 0x0C9:
// SMULL rdlo, rdhi, rm, rs
{
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs) + 1;
long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs]));
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
this.parent.Cycles -= cycles;
}
break;
case 0x0D9:
// SMULLS rdlo, rdhi, rm, rs
{
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs) + 1;
long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs]));
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
negative = registers[rdhi] >> 31;
zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U;
this.parent.Cycles -= cycles;
}
break;
case 0x0E9:
// SMLAL rdlo, rdhi, rm, rs
{
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs) + 2;
long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo];
long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs]));
result += accum;
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
this.parent.Cycles -= cycles;
}
break;
case 0x0F9:
// SMLALS rdlo, rdhi, rm, rs
{
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
rs = (this.curInstruction >> 8) & 0xF;
rm = this.curInstruction & 0xF;
cycles = this.MultiplyCycleCalculation(rs) + 2;
long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo];
long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs]));
result += accum;
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
negative = registers[rdhi] >> 31;
zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U;
this.parent.Cycles -= cycles;
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// STRH implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x00B:
// STRH rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
registers[rn] = address + offset;
break;
case 0x02B:
// Writeback bit set, instruction is unpredictable
// STRH rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
registers[rn] = address + offset;
break;
case 0x04B:
// STRH rd, [rn], -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
registers[rn] = address + offset;
break;
case 0x06B:
// Writeback bit set, instruction is unpredictable
// STRH rd, [rn], -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
registers[rn] = address + offset;
break;
case 0x08B:
// STRH rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
registers[rn] = address + offset;
break;
case 0x0AB:
// Writeback bit set, instruction is unpredictable
// STRH rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
registers[rn] = address + offset;
break;
case 0x0CB:
// STRH rd, [rn], immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
registers[rn] = address + offset;
break;
case 0x0EB:
// Writeback bit set, instruction is unpredictable
// STRH rd, [rn], immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
registers[rn] = address + offset;
break;
case 0x10B:
// STRH rd, [rn, -rm]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF));
break;
case 0x12B:
// STRH rd, [rn, -rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rn] += offset;
this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF));
break;
case 0x14B:
// STRH rd, [rn, -immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF));
break;
case 0x16B:
// STRH rd, [rn], -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rn] += offset;
this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF));
break;
case 0x18B:
// STRH rd, [rn, rm]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF));
break;
case 0x1AB:
// STRH rd, [rn, rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
registers[rn] += offset;
this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF));
break;
case 0x1CB:
// STRH rd, [rn, immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
this.memory.WriteU16(registers[rn] + offset, (ushort)(registers[rd] & 0xFFFF));
break;
case 0x1EB:
// STRH rd, [rn, immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rn] += offset;
this.memory.WriteU16(registers[rn], (ushort)(registers[rd] & 0xFFFF));
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// LDRH implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x01B:
// LDRH rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x03B:
// Writeback bit set, instruction is unpredictable
// LDRH rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x05B:
// LDRH rd, [rn], -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x07B:
// Writeback bit set, instruction is unpredictable
// LDRH rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x09B:
// LDRH rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0BB:
// Writeback bit set, instruction is unpredictable
// LDRH rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0DB:
// LDRH rd, [rn], immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0FB:
// Writeback bit set, instruction is unpredictable
// LDRH rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x11B:
// LDRH rd, [rn, -rm]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = this.memory.ReadU16(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x13B:
// LDRH rd, [rn, -rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU16(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x15B:
// LDRH rd, [rn, -immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = this.memory.ReadU16(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x17B:
// LDRH rd, [rn, -rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU16(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x19B:
// LDRH rd, [rn, rm]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = this.memory.ReadU16(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1BB:
// LDRH rd, [rn, rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
registers[rn] += offset;
registers[rd] = this.memory.ReadU16(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1DB:
// LDRH rd, [rn, immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = this.memory.ReadU16(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1FB:
// LDRH rd, [rn, rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rn] += offset;
registers[rd] = this.memory.ReadU16(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// LDRSB implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x01D:
// LDRSB rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x03D:
// Writeback bit set, instruction is unpredictable
// LDRSB rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x05D:
// LDRSB rd, [rn], -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x07D:
// Writeback bit set, instruction is unpredictable
// LDRSB rd, [rn], -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x09D:
// LDRSB rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = (uint)(sbyte)this.memory.ReadU8(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0BD:
// Writeback bit set, instruction is unpredictable
// LDRSB rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = (uint)(sbyte)this.memory.ReadU8(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0DD:
// LDRSB rd, [rn], immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = (uint)(sbyte)this.memory.ReadU8(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0FD:
// Writeback bit set, instruction is unpredictable
// LDRSB rd, [rn], immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = (uint)(sbyte)this.memory.ReadU8(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x11D:
// LDRSB rd, [rn, -rm]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x13D:
// LDRSB rd, [rn, -rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x15D:
// LDRSB rd, [rn, -immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x17D:
// LDRSB rd, [rn, -immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x19D:
// LDRSB rd, [rn, rm]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1BD:
// LDRSB rd, [rn, rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1DD:
// LDRSB rd, [rn, immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1FD:
// LDRSB rd, [rn, immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rn] += offset;
registers[rd] = (uint)(sbyte)this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// LDRSH implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x01F:
// LDRSH rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = (uint)(short)this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x03F:
// Writeback bit set, instruction is unpredictable
// LDRSH rd, [rn], -rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = (uint)(short)this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x05F:
// LDRSH rd, [rn], -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = (uint)(short)this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x07F:
// Writeback bit set, instruction is unpredictable
// LDRSH rd, [rn], -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = (uint)(short)this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x09F:
// LDRSH rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = (uint)(short)this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0BF:
// Writeback bit set, instruction is unpredictable
// LDRSH rd, [rn], rm
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = (uint)(short)this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0DF:
// LDRSH rd, [rn], immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = (uint)(short)this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x0FF:
// Writeback bit set, instruction is unpredictable
// LDRSH rd, [rn], immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
address = registers[rn];
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = (uint)(short)this.memory.ReadU16(address);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] = address + offset;
break;
case 0x11F:
// LDRSH rd, [rn, -rm]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x13F:
// LDRSH rd, [rn, -rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x15F:
// LDRSH rd, [rn, -immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x17F:
// LDRSH rd, [rn, -immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x19F:
// LDRSH rd, [rn, rm]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1BF:
// LDRSH rd, [rn, rm]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.registers[this.curInstruction & 0xF];
registers[rn] += offset;
registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1DF:
// LDRSH rd, [rn, immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x1FF:
// LDRSH rd, [rn, immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
registers[rn] += offset;
registers[rd] = (uint)(short)this.memory.ReadU16(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// EOR implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x020:
case 0x028:
// EOR rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterLslImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x021:
// EOR rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterLslReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x022:
case 0x02A:
// EOR rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterLsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x023:
// EOR rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterLsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x024:
case 0x02C:
// EOR rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterAsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x025:
// EOR rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterAsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x026:
case 0x02E:
// EOR rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterRorImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x027:
// EOR rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterRorReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x030:
case 0x038:
// EORS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterLslImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x031:
// EORS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterLslReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x032:
case 0x03A:
// EORS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterLsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x033:
// EORS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterLsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x034:
case 0x03C:
// EORS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterAsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x035:
// EORS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterAsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x036:
case 0x03E:
// EORS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterRorImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x037:
// EORS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn ^ BarrelShifterRorReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// SUB implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x040:
case 0x048:
// SUB rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterLslImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x041:
// SUB rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterLslReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x042:
case 0x04A:
// SUB rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterLsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x043:
// SUB rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterLsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x044:
case 0x04C:
// SUB rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterAsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x045:
// SUB rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterAsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x046:
case 0x04E:
// SUB rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterRorImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x047:
// SUB rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterRorReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x050:
case 0x058:
// SUBS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslImmed();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x051:
// SUBS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslReg();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x052:
case 0x05A:
// SUBS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrImmed();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x053:
// SUBS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrReg();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x054:
case 0x05C:
// SUBS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrImmed();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x055:
// SUBS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrReg();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x056:
case 0x05E:
// SUBS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorImmed();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x057:
// SUBS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorReg();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// RSB implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x060:
case 0x068:
// RSB rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLslImmed() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x061:
// RSB rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLslReg() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x062:
case 0x06A:
// RSB rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLsrImmed() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x063:
// RSB rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLsrReg() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x064:
case 0x06C:
// RSB rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterAsrImmed() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x065:
// RSB rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterAsrReg() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x066:
case 0x06E:
// RSB rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterRorImmed() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x067:
// RSB rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterRorReg() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x070:
case 0x078:
// RSBS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslImmed();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x071:
// RSBS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslReg();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x072:
case 0x07A:
// RSBS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrImmed();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x073:
// RSBS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrReg();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x074:
case 0x07C:
// RSBS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrImmed();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x075:
// RSBS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrReg();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x076:
case 0x07E:
// RSBS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorImmed();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x077:
// RSBS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorReg();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// ADD implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x080:
case 0x088:
// ADD rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterLslImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x081:
// ADD rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterLslReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x082:
case 0x08A:
// ADD rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterLsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x083:
// ADD rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterLsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x084:
case 0x08C:
// ADD rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterAsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x085:
// ADD rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterAsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x086:
case 0x08E:
// ADD rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterRorImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x087:
// ADD rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterRorReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x090:
case 0x098:
// ADDS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslImmed();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x091:
// ADDS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslReg();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x092:
case 0x09A:
// ADDS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrImmed();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x093:
// ADDS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrReg();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x094:
case 0x09C:
// ADDS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrImmed();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x095:
// ADDS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrReg();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x096:
case 0x09E:
// ADDS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorImmed();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x097:
// ADDS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorReg();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// ADC implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x0A0:
case 0x0A8:
// ADC rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterLslImmed() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0A1:
// ADC rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterLslReg() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0A2:
case 0x0AA:
// ADC rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterLsrImmed() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0A3:
// ADC rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterLsrReg() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0A4:
case 0x0AC:
// ADC rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterAsrImmed() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0A5:
// ADC rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterAsrReg() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0A6:
case 0x0AE:
// ADC rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterRorImmed() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0A7:
// ADC rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn + BarrelShifterRorReg() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0B0:
case 0x0B8:
// ADCS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslImmed();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0B1:
// ADCS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslReg();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0B2:
case 0x0BA:
// ADCS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrImmed();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0B3:
// ADCS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrReg();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0B4:
case 0x0BC:
// ADCS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrImmed();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0B5:
// ADCS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrReg();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0B6:
case 0x0BE:
// ADCS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorImmed();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0B7:
// ADCS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorReg();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// SBC implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x0C0:
case 0x0C8:
// SBC rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterLslImmed() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0C1:
// SBC rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterLslReg() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0C2:
case 0x0CA:
// SBC rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterLsrImmed() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0C3:
// SBC rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterLsrReg() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0C4:
case 0x0CC:
// SBC rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterAsrImmed() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0C5:
// SBC rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterAsrReg() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0C6:
case 0x0CE:
// SBC rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterRorImmed() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0C7:
// SBC rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn - BarrelShifterRorReg() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0D0:
case 0x0D8:
// SBCS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslImmed();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0D1:
// SBCS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslReg();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0D2:
case 0x0DA:
// SBCS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrImmed();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0D3:
// SBCS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrReg();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0D4:
case 0x0DC:
// SBCS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrImmed();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0D5:
// SBCS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrReg();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0D6:
case 0x0DE:
// SBCS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorImmed();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0D7:
// SBCS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorReg();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// RSC implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x0E0:
case 0x0E8:
// RSC rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLslImmed() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0E1:
// RSC rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLslReg() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0E2:
case 0x0EA:
// RSC rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLsrImmed() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0E3:
// RSC rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLsrReg() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0E4:
case 0x0EC:
// RSC rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterAsrImmed() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0E5:
// RSC rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterAsrReg() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0E6:
case 0x0EE:
// RSC rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterRorImmed() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0E7:
// RSC rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterRorReg() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x0F0:
case 0x0F8:
// RSCS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslImmed();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0F1:
// RSCS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLslReg();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0F2:
case 0x0FA:
// RSCS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrImmed();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0F3:
// RSCS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterLsrReg();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0F4:
case 0x0FC:
// RSCS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrImmed();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0F5:
// RSCS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterAsrReg();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0F6:
case 0x0FE:
// RSCS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorImmed();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x0F7:
// RSCS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
shifterOperand = BarrelShifterRorReg();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// Misc. instructions (MSR, MRS, SWP, BX)
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x109:
// SWP rd, rm, [rn]
{
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
rm = this.curInstruction & 0xF;
uint tmp = this.memory.ReadU32(registers[rn]);
this.memory.WriteU32(registers[rn], registers[rm]);
registers[rd] = tmp;
if (rd == 15)
{
this.FlushQueue();
}
}
break;
case 0x149:
// SWPB rd, rm, [rn]
{
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
rm = this.curInstruction & 0xF;
byte tmp = this.memory.ReadU8(registers[rn]);
this.memory.WriteU8(registers[rn], (byte)(registers[rm] & 0xFF));
registers[rd] = tmp;
if (rd == 15)
{
this.FlushQueue();
}
}
break;
case 0x100:
// MRS rd, cpsr
rd = (this.curInstruction >> 12) & 0xF;
this.PackFlags();
registers[rd] = this.parent.CPSR;
break;
case 0x140:
// MRS rd, spsr
rd = (this.curInstruction >> 12) & 0xF;
if (this.parent.SPSRExists) registers[rd] = this.parent.SPSR;
break;
case 0x120:
// MSR cpsr, rm
{
rm = registers[this.curInstruction & 0xF];
bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR;
this.PackFlags();
uint tmpCPSR = this.parent.CPSR;
if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode)
{
tmpCPSR &= 0xFFFFFF00;
tmpCPSR |= rm & 0x000000FF;
}
if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode)
{
tmpCPSR &= 0xFFFF00FF;
tmpCPSR |= rm & 0x0000FF00;
}
if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode)
{
tmpCPSR &= 0xFF00FFFF;
tmpCPSR |= rm & 0x00FF0000;
}
if ((this.curInstruction & (1 << 19)) == 1 << 19)
{
tmpCPSR &= 0x00FFFFFF;
tmpCPSR |= rm & 0xFF000000;
}
this.parent.WriteCpsr(tmpCPSR);
this.UnpackFlags();
// Check for branch back to Thumb Mode
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
return;
}
}
break;
case 0x160:
// MSR spsr, rm
if (this.parent.SPSRExists)
{
rm = registers[this.curInstruction & 0xF];
if ((this.curInstruction & (1 << 16)) == 1 << 16)
{
this.parent.SPSR &= 0xFFFFFF00;
this.parent.SPSR |= rm & 0x000000FF;
}
if ((this.curInstruction & (1 << 17)) == 1 << 17)
{
this.parent.SPSR &= 0xFFFF00FF;
this.parent.SPSR |= rm & 0x0000FF00;
}
if ((this.curInstruction & (1 << 18)) == 1 << 18)
{
this.parent.SPSR &= 0xFF00FFFF;
this.parent.SPSR |= rm & 0x00FF0000;
}
if ((this.curInstruction & (1 << 19)) == 1 << 19)
{
this.parent.SPSR &= 0x00FFFFFF;
this.parent.SPSR |= rm & 0xFF000000;
}
}
break;
case 0x320:
// MSR cpsr, immed
{
uint immed = this.curInstruction & 0xFF;
int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2);
immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount));
bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR;
this.PackFlags();
uint tmpCPSR = this.parent.CPSR;
if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode)
{
tmpCPSR &= 0xFFFFFF00;
tmpCPSR |= immed & 0x000000FF;
}
if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode)
{
tmpCPSR &= 0xFFFF00FF;
tmpCPSR |= immed & 0x0000FF00;
}
if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode)
{
tmpCPSR &= 0xFF00FFFF;
tmpCPSR |= immed & 0x00FF0000;
}
if ((this.curInstruction & (1 << 19)) == 1 << 19)
{
tmpCPSR &= 0x00FFFFFF;
tmpCPSR |= immed & 0xFF000000;
}
this.parent.WriteCpsr(tmpCPSR);
this.UnpackFlags();
// Check for branch back to Thumb Mode
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
return;
}
}
break;
case 0x360:
// MSR spsr, immed
if (this.parent.SPSRExists)
{
uint immed = this.curInstruction & 0xFF;
int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2);
immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount));
if ((this.curInstruction & (1 << 16)) == 1 << 16)
{
this.parent.SPSR &= 0xFFFFFF00;
this.parent.SPSR |= immed & 0x000000FF;
}
if ((this.curInstruction & (1 << 17)) == 1 << 17)
{
this.parent.SPSR &= 0xFFFF00FF;
this.parent.SPSR |= immed & 0x0000FF00;
}
if ((this.curInstruction & (1 << 18)) == 1 << 18)
{
this.parent.SPSR &= 0xFF00FFFF;
this.parent.SPSR |= immed & 0x00FF0000;
}
if ((this.curInstruction & (1 << 19)) == 1 << 19)
{
this.parent.SPSR &= 0x00FFFFFF;
this.parent.SPSR |= immed & 0xFF000000;
}
}
break;
case 0x121:
// BX rm
rm = this.curInstruction & 0xf;
this.PackFlags();
this.parent.CPSR &= ~Arm7Processor.T_MASK;
this.parent.CPSR |= (registers[rm] & 1) << Arm7Processor.T_BIT;
registers[15] = registers[rm] & (~1U);
this.UnpackFlags();
// Check for branch back to Thumb Mode
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
return;
}
this.FlushQueue();
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// TST implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x110:
case 0x118:
// TSTS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn & BarrelShifterLslImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x111:
// TSTS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn & BarrelShifterLslReg();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x112:
case 0x11A:
// TSTS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn & BarrelShifterLsrImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x113:
// TSTS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn & BarrelShifterLsrReg();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x114:
case 0x11C:
// TSTS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn & BarrelShifterAsrImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x115:
// TSTS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn & BarrelShifterAsrReg();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x116:
case 0x11E:
// TSTS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn & BarrelShifterRorImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x117:
// TSTS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
alu = rn & BarrelShifterRorReg();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// TEQ implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x130:
case 0x138:
// TEQS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn ^ BarrelShifterLslImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x131:
// TEQS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn ^ BarrelShifterLslReg();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x132:
case 0x13A:
// TEQS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn ^ BarrelShifterLsrImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x133:
// TEQS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn ^ BarrelShifterLsrReg();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x134:
case 0x13C:
// TEQS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn ^ BarrelShifterAsrImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x135:
// TEQS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn ^ BarrelShifterAsrReg();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x136:
case 0x13E:
// TEQS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn ^ BarrelShifterRorImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x137:
// TEQS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
alu = rn ^ BarrelShifterRorReg();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// CMP implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x150:
case 0x158:
// CMP rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterLslImmed();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case 0x151:
// CMP rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterLslReg();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case 0x152:
case 0x15A:
// CMP rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterLsrImmed();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case 0x153:
// CMP rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterLsrReg();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case 0x154:
case 0x15C:
// CMP rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterAsrImmed();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case 0x155:
// CMP rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterAsrReg();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case 0x156:
case 0x15E:
// CMP rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterRorImmed();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case 0x157:
// CMP rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterRorReg();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// CMN implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x170:
case 0x178:
// CMN rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterLslImmed();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case 0x171:
// CMN rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterLslReg();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case 0x172:
case 0x17A:
// CMN rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterLsrImmed();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case 0x173:
// CMN rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterLsrReg();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case 0x174:
case 0x17C:
// CMN rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterAsrImmed();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case 0x175:
// CMN rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterAsrReg();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case 0x176:
case 0x17E:
// CMN rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterRorImmed();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case 0x177:
// CMN rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterRorReg();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// ORR implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x180:
case 0x188:
// ORR rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterLslImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x181:
// ORR rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterLslReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x182:
case 0x18A:
// ORR rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterLsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x183:
// ORR rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterLsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x184:
case 0x18C:
// ORR rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterAsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x185:
// ORR rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterAsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x186:
case 0x18E:
// ORR rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterRorImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x187:
// ORR rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterRorReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x190:
case 0x198:
// ORRS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterLslImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x191:
// ORRS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterLslReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x192:
case 0x19A:
// ORRS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterLsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x193:
// ORRS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterLsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x194:
case 0x19C:
// ORRS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterAsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x195:
// ORRS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterAsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x196:
case 0x19E:
// ORRS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterRorImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x197:
// ORRS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn | BarrelShifterRorReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// MOV implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x1A0:
case 0x1A8:
// MOV rd, rm lsl immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLslImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1A1:
// MOV rd, rm lsl rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLslReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1A2:
case 0x1AA:
// MOV rd, rm lsr immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1A3:
// MOV rd, rm lsr rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1A4:
case 0x1AC:
// MOV rd, rm asr immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterAsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1A5:
// MOV rd, rm asr rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterAsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1A6:
case 0x1AE:
// MOV rd, rm ror immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterRorImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1A7:
// MOV rd, rm ror rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterRorReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1B0:
case 0x1B8:
// MOVS rd, rm lsl immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLslImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1B1:
// MOVS rd, rm lsl rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLslReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1B2:
case 0x1BA:
// MOVS rd, rm lsr immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1B3:
// MOVS rd, rn, rm lsr rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterLsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1B4:
case 0x1BC:
// MOVS rd, rn, rm asr immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterAsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1B5:
// MOVS rd, rn, rm asr rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterAsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1B6:
case 0x1BE:
// MOVS rd, rn, rm ror immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterRorImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1B7:
// MOVS rd, rn, rm ror rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterRorReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// BIC implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x1C0:
case 0x1C8:
// BIC rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterLslImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1C1:
// BIC rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterLslReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1C2:
case 0x1CA:
// BIC rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterLsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1C3:
// BIC rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterLsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1C4:
case 0x1CC:
// BIC rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterAsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1C5:
// BIC rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterAsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1C6:
case 0x1CE:
// BIC rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterRorImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1C7:
// BIC rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterRorReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1D0:
case 0x1D8:
// BICS rd, rn, rm lsl immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterLslImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1D1:
// BICS rd, rn, rm lsl rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterLslReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1D2:
case 0x1DA:
// BICS rd, rn, rm lsr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterLsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1D3:
// BICS rd, rn, rm lsr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterLsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1D4:
case 0x1DC:
// BICS rd, rn, rm asr immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterAsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1D5:
// BICS rd, rn, rm asr rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterAsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1D6:
case 0x1DE:
// BICS rd, rn, rm ror immed
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterRorImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1D7:
// BICS rd, rn, rm ror rs
rn = registers[(this.curInstruction >> 16) & 0xF];
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = rn & ~BarrelShifterRorReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// MVN implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x1E0:
case 0x1E8:
// MVN rd, rm lsl immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterLslImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1E1:
// MVN rd, rm lsl rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterLslReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1E2:
case 0x1EA:
// MVN rd, rm lsr immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterLsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1E3:
// MVN rd, rm lsr rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterLsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1E4:
case 0x1EC:
// MVN rd, rm asr immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterAsrImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1E5:
// MVN rd, rm asr rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterAsrReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1E6:
case 0x1EE:
// MVN rd, rm ror immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterRorImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1E7:
// MVN rd, rm ror rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterRorReg();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x1F0:
case 0x1F8:
// MVNS rd, rm lsl immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterLslImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1F1:
// MVNS rd, rm lsl rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterLslReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1F2:
case 0x1FA:
// MVNS rd, rm lsr immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterLsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1F3:
// MVNS rd, rn, rm lsr rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterLsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1F4:
case 0x1FC:
// MVNS rd, rn, rm asr immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterAsrImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1F5:
// MVNS rd, rn, rm asr rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterAsrReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1F6:
case 0x1FE:
// MVNS rd, rn, rm ror immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterRorImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x1F7:
// MVNS rd, rn, rm ror rs
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterRorReg();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// Data processing immediate operand implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x200: case 0x201: case 0x202: case 0x203: case 0x204: case 0x205: case 0x206: case 0x207:
case 0x208: case 0x209: case 0x20A: case 0x20B: case 0x20C: case 0x20D: case 0x20E: case 0x20F:
// AND rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn & BarrelShifterImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x210: case 0x211: case 0x212: case 0x213: case 0x214: case 0x215: case 0x216: case 0x217:
case 0x218: case 0x219: case 0x21A: case 0x21B: case 0x21C: case 0x21D: case 0x21E: case 0x21F:
// ANDS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn & BarrelShifterImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x220: case 0x221: case 0x222: case 0x223: case 0x224: case 0x225: case 0x226: case 0x227:
case 0x228: case 0x229: case 0x22A: case 0x22B: case 0x22C: case 0x22D: case 0x22E: case 0x22F:
// EOR rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn ^ BarrelShifterImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x230: case 0x231: case 0x232: case 0x233: case 0x234: case 0x235: case 0x236: case 0x237:
case 0x238: case 0x239: case 0x23A: case 0x23B: case 0x23C: case 0x23D: case 0x23E: case 0x23F:
// EORS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn ^ BarrelShifterImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x240: case 0x241: case 0x242: case 0x243: case 0x244: case 0x245: case 0x246: case 0x247:
case 0x248: case 0x249: case 0x24A: case 0x24B: case 0x24C: case 0x24D: case 0x24E: case 0x24F:
// SUB rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn - BarrelShifterImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x250: case 0x251: case 0x252: case 0x253: case 0x254: case 0x255: case 0x256: case 0x257:
case 0x258: case 0x259: case 0x25A: case 0x25B: case 0x25C: case 0x25D: case 0x25E: case 0x25F:
// SUBS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterImmed();
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x260: case 0x261: case 0x262: case 0x263: case 0x264: case 0x265: case 0x266: case 0x267:
case 0x268: case 0x269: case 0x26A: case 0x26B: case 0x26C: case 0x26D: case 0x26E: case 0x26F:
// RSB rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = BarrelShifterImmed() - rn;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x270: case 0x271: case 0x272: case 0x273: case 0x274: case 0x275: case 0x276: case 0x277:
case 0x278: case 0x279: case 0x27A: case 0x27B: case 0x27C: case 0x27D: case 0x27E: case 0x27F:
// RSBS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterImmed();
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x280: case 0x281: case 0x282: case 0x283: case 0x284: case 0x285: case 0x286: case 0x287:
case 0x288: case 0x289: case 0x28A: case 0x28B: case 0x28C: case 0x28D: case 0x28E: case 0x28F:
// ADD rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn + BarrelShifterImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x290: case 0x291: case 0x292: case 0x293: case 0x294: case 0x295: case 0x296: case 0x297:
case 0x298: case 0x299: case 0x29A: case 0x29B: case 0x29C: case 0x29D: case 0x29E: case 0x29F:
// ADDS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterImmed();
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x2A0: case 0x2A1: case 0x2A2: case 0x2A3: case 0x2A4: case 0x2A5: case 0x2A6: case 0x2A7:
case 0x2A8: case 0x2A9: case 0x2AA: case 0x2AB: case 0x2AC: case 0x2AD: case 0x2AE: case 0x2AF:
// ADC rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn + BarrelShifterImmed() + carry;
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x2B0: case 0x2B1: case 0x2B2: case 0x2B3: case 0x2B4: case 0x2B5: case 0x2B6: case 0x2B7:
case 0x2B8: case 0x2B9: case 0x2BA: case 0x2BB: case 0x2BC: case 0x2BD: case 0x2BE: case 0x2BF:
// ADCS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterImmed();
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x2C0: case 0x2C1: case 0x2C2: case 0x2C3: case 0x2C4: case 0x2C5: case 0x2C6: case 0x2C7:
case 0x2C8: case 0x2C9: case 0x2CA: case 0x2CB: case 0x2CC: case 0x2CD: case 0x2CE: case 0x2CF:
// SBC rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn - BarrelShifterImmed() - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x2D0: case 0x2D1: case 0x2D2: case 0x2D3: case 0x2D4: case 0x2D5: case 0x2D6: case 0x2D7:
case 0x2D8: case 0x2D9: case 0x2DA: case 0x2DB: case 0x2DC: case 0x2DD: case 0x2DE: case 0x2DF:
// SBCS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterImmed();
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x2E0: case 0x2E1: case 0x2E2: case 0x2E3: case 0x2E4: case 0x2E5: case 0x2E6: case 0x2E7:
case 0x2E8: case 0x2E9: case 0x2EA: case 0x2EB: case 0x2EC: case 0x2ED: case 0x2EE: case 0x2EF:
// RSC rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = BarrelShifterImmed() - rn - (1U - carry);
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x2F0: case 0x2F1: case 0x2F2: case 0x2F3: case 0x2F4: case 0x2F5: case 0x2F6: case 0x2F7:
case 0x2F8: case 0x2F9: case 0x2FA: case 0x2FB: case 0x2FC: case 0x2FD: case 0x2FE: case 0x2FF:
// RSCS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterImmed();
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x310: case 0x311: case 0x312: case 0x313: case 0x314: case 0x315: case 0x316: case 0x317:
case 0x318: case 0x319: case 0x31A: case 0x31B: case 0x31C: case 0x31D: case 0x31E: case 0x31F:
// TSTS rn, immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn & BarrelShifterImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x330: case 0x331: case 0x332: case 0x333: case 0x334: case 0x335: case 0x336: case 0x337:
case 0x338: case 0x339: case 0x33A: case 0x33B: case 0x33C: case 0x33D: case 0x33E: case 0x33F:
// TEQS rn, immed
rn = registers[(this.curInstruction >> 16) & 0xF];
alu = rn ^ BarrelShifterImmed();
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case 0x350: case 0x351: case 0x352: case 0x353: case 0x354: case 0x355: case 0x356: case 0x357:
case 0x358: case 0x359: case 0x35A: case 0x35B: case 0x35C: case 0x35D: case 0x35E: case 0x35F:
// CMP rn, immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterImmed();
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case 0x370: case 0x371: case 0x372: case 0x373: case 0x374: case 0x375: case 0x376: case 0x377:
case 0x378: case 0x379: case 0x37A: case 0x37B: case 0x37C: case 0x37D: case 0x37E: case 0x37F:
// CMN rn, immed
rn = registers[(this.curInstruction >> 16) & 0xF];
shifterOperand = BarrelShifterImmed();
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case 0x380: case 0x381: case 0x382: case 0x383: case 0x384: case 0x385: case 0x386: case 0x387:
case 0x388: case 0x389: case 0x38A: case 0x38B: case 0x38C: case 0x38D: case 0x38E: case 0x38F:
// ORR rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn | BarrelShifterImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x390: case 0x391: case 0x392: case 0x393: case 0x394: case 0x395: case 0x396: case 0x397:
case 0x398: case 0x399: case 0x39A: case 0x39B: case 0x39C: case 0x39D: case 0x39E: case 0x39F:
// ORRS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn | BarrelShifterImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x3A0: case 0x3A1: case 0x3A2: case 0x3A3: case 0x3A4: case 0x3A5: case 0x3A6: case 0x3A7:
case 0x3A8: case 0x3A9: case 0x3AA: case 0x3AB: case 0x3AC: case 0x3AD: case 0x3AE: case 0x3AF:
// MOV rd, immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x3B0: case 0x3B1: case 0x3B2: case 0x3B3: case 0x3B4: case 0x3B5: case 0x3B6: case 0x3B7:
case 0x3B8: case 0x3B9: case 0x3BA: case 0x3BB: case 0x3BC: case 0x3BD: case 0x3BE: case 0x3BF:
// MOVS rd, immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = BarrelShifterImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x3C0: case 0x3C1: case 0x3C2: case 0x3C3: case 0x3C4: case 0x3C5: case 0x3C6: case 0x3C7:
case 0x3C8: case 0x3C9: case 0x3CA: case 0x3CB: case 0x3CC: case 0x3CD: case 0x3CE: case 0x3CF:
// BIC rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn & ~BarrelShifterImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x3D0: case 0x3D1: case 0x3D2: case 0x3D3: case 0x3D4: case 0x3D5: case 0x3D6: case 0x3D7:
case 0x3D8: case 0x3D9: case 0x3DA: case 0x3DB: case 0x3DC: case 0x3DD: case 0x3DE: case 0x3DF:
// BICS rd, rn, immed
rd = (this.curInstruction >> 12) & 0xF;
rn = registers[(this.curInstruction >> 16) & 0xF];
registers[rd] = rn & ~BarrelShifterImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
case 0x3E0: case 0x3E1: case 0x3E2: case 0x3E3: case 0x3E4: case 0x3E5: case 0x3E6: case 0x3E7:
case 0x3E8: case 0x3E9: case 0x3EA: case 0x3EB: case 0x3EC: case 0x3ED: case 0x3EE: case 0x3EF:
// MVN rd, immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterImmed();
if (rd == 15)
{
this.FlushQueue();
}
break;
case 0x3F0: case 0x3F1: case 0x3F2: case 0x3F3: case 0x3F4: case 0x3F5: case 0x3F6: case 0x3F7:
case 0x3F8: case 0x3F9: case 0x3FA: case 0x3FB: case 0x3FC: case 0x3FD: case 0x3FE: case 0x3FF:
// MVNS rd, immed
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = ~BarrelShifterImmed();
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
if (rd == 15)
{
this.DataProcessingWriteToR15();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// STR immediate implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x400: case 0x401: case 0x402: case 0x403: case 0x404: case 0x405: case 0x406: case 0x407:
case 0x408: case 0x409: case 0x40A: case 0x40B: case 0x40C: case 0x40D: case 0x40E: case 0x40F:
// STR rd, rn, -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x420: case 0x421: case 0x422: case 0x423: case 0x424: case 0x425: case 0x426: case 0x427:
case 0x428: case 0x429: case 0x42A: case 0x42B: case 0x42C: case 0x42D: case 0x42E: case 0x42F:
// STRT rd, rn, -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x440: case 0x441: case 0x442: case 0x443: case 0x444: case 0x445: case 0x446: case 0x447:
case 0x448: case 0x449: case 0x44A: case 0x44B: case 0x44C: case 0x44D: case 0x44E: case 0x44F:
// STRB rd, rn, -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x460: case 0x461: case 0x462: case 0x463: case 0x464: case 0x465: case 0x466: case 0x467:
case 0x468: case 0x469: case 0x46A: case 0x46B: case 0x46C: case 0x46D: case 0x46E: case 0x46F:
// STRBT rd, rn, -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x480: case 0x481: case 0x482: case 0x483: case 0x484: case 0x485: case 0x486: case 0x487:
case 0x488: case 0x489: case 0x48A: case 0x48B: case 0x48C: case 0x48D: case 0x48E: case 0x48F:
// STR rd, rn, immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.curInstruction & 0xFFF;
break;
case 0x4A0: case 0x4A1: case 0x4A2: case 0x4A3: case 0x4A4: case 0x4A5: case 0x4A6: case 0x4A7:
case 0x4A8: case 0x4A9: case 0x4AA: case 0x4AB: case 0x4AC: case 0x4AD: case 0x4AE: case 0x4AF:
// STRT rd, rn, immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.curInstruction & 0xFFF;
break;
case 0x4C0: case 0x4C1: case 0x4C2: case 0x4C3: case 0x4C4: case 0x4C5: case 0x4C6: case 0x4C7:
case 0x4C8: case 0x4C9: case 0x4CA: case 0x4CB: case 0x4CC: case 0x4CD: case 0x4CE: case 0x4CF:
// STRB rd, rn, immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.curInstruction & 0xFFF;
break;
case 0x4E0: case 0x4E1: case 0x4E2: case 0x4E3: case 0x4E4: case 0x4E5: case 0x4E6: case 0x4E7:
case 0x4E8: case 0x4E9: case 0x4EA: case 0x4EB: case 0x4EC: case 0x4ED: case 0x4EE: case 0x4EF:
// STRBT rd, rn, immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.curInstruction & 0xFFF;
break;
case 0x500: case 0x501: case 0x502: case 0x503: case 0x504: case 0x505: case 0x506: case 0x507:
case 0x508: case 0x509: case 0x50A: case 0x50B: case 0x50C: case 0x50D: case 0x50E: case 0x50F:
// STR rd, [rn, -immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + offset, alu);
break;
case 0x520: case 0x521: case 0x522: case 0x523: case 0x524: case 0x525: case 0x526: case 0x527:
case 0x528: case 0x529: case 0x52A: case 0x52B: case 0x52C: case 0x52D: case 0x52E: case 0x52F:
// STR rd, [rn, -immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU32(registers[rn], alu);
break;
case 0x540: case 0x541: case 0x542: case 0x543: case 0x544: case 0x545: case 0x546: case 0x547:
case 0x548: case 0x549: case 0x54A: case 0x54B: case 0x54C: case 0x54D: case 0x54E: case 0x54F:
// STRB rd, [rn, -immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF));
break;
case 0x560: case 0x561: case 0x562: case 0x563: case 0x564: case 0x565: case 0x566: case 0x567:
case 0x568: case 0x569: case 0x56A: case 0x56B: case 0x56C: case 0x56D: case 0x56E: case 0x56F:
// STRB rd, [rn, -immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
case 0x580: case 0x581: case 0x582: case 0x583: case 0x584: case 0x585: case 0x586: case 0x587:
case 0x588: case 0x589: case 0x58A: case 0x58B: case 0x58C: case 0x58D: case 0x58E: case 0x58F:
// STR rd, [rn, immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + (this.curInstruction & 0xFFF), alu);
break;
case 0x5A0: case 0x5A1: case 0x5A2: case 0x5A3: case 0x5A4: case 0x5A5: case 0x5A6: case 0x5A7:
case 0x5A8: case 0x5A9: case 0x5AA: case 0x5AB: case 0x5AC: case 0x5AD: case 0x5AE: case 0x5AF:
// STRT rd, [rn, immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.curInstruction & 0xFFF;
this.memory.WriteU32(registers[rn], alu);
break;
case 0x5C0: case 0x5C1: case 0x5C2: case 0x5C3: case 0x5C4: case 0x5C5: case 0x5C6: case 0x5C7:
case 0x5C8: case 0x5C9: case 0x5CA: case 0x5CB: case 0x5CC: case 0x5CD: case 0x5CE: case 0x5CF:
// STRB rd, [rn, immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + (this.curInstruction & 0xFFF), (byte)(alu & 0xFF));
break;
case 0x5E0: case 0x5E1: case 0x5E2: case 0x5E3: case 0x5E4: case 0x5E5: case 0x5E6: case 0x5E7:
case 0x5E8: case 0x5E9: case 0x5EA: case 0x5EB: case 0x5EC: case 0x5ED: case 0x5EE: case 0x5EF:
// STRB rd, [rn, immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.curInstruction & 0xFFF;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// LDR immediate implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x410: case 0x411: case 0x412: case 0x413: case 0x414: case 0x415: case 0x416: case 0x417:
case 0x418: case 0x419: case 0x41A: case 0x41B: case 0x41C: case 0x41D: case 0x41E: case 0x41F:
// LDR rd, rn, -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x430: case 0x431: case 0x432: case 0x433: case 0x434: case 0x435: case 0x436: case 0x437:
case 0x438: case 0x439: case 0x43A: case 0x43B: case 0x43C: case 0x43D: case 0x43E: case 0x43F:
// LDRT rd, rn, -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x450: case 0x451: case 0x452: case 0x453: case 0x454: case 0x455: case 0x456: case 0x457:
case 0x458: case 0x459: case 0x45A: case 0x45B: case 0x45C: case 0x45D: case 0x45E: case 0x45F:
// LDRB rd, rn, -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x470: case 0x471: case 0x472: case 0x473: case 0x474: case 0x475: case 0x476: case 0x477:
case 0x478: case 0x479: case 0x47A: case 0x47B: case 0x47C: case 0x47D: case 0x47E: case 0x47F:
// LDRBT rd, rn, -immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x490: case 0x491: case 0x492: case 0x493: case 0x494: case 0x495: case 0x496: case 0x497:
case 0x498: case 0x499: case 0x49A: case 0x49B: case 0x49C: case 0x49D: case 0x49E: case 0x49F:
// LDR rd, rn, immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += this.curInstruction & 0xFFF;
break;
case 0x4B0: case 0x4B1: case 0x4B2: case 0x4B3: case 0x4B4: case 0x4B5: case 0x4B6: case 0x4B7:
case 0x4B8: case 0x4B9: case 0x4BA: case 0x4BB: case 0x4BC: case 0x4BD: case 0x4BE: case 0x4BF:
// LDRT rd, rn, immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += this.curInstruction & 0xFFF;
break;
case 0x4D0: case 0x4D1: case 0x4D2: case 0x4D3: case 0x4D4: case 0x4D5: case 0x4D6: case 0x4D7:
case 0x4D8: case 0x4D9: case 0x4DA: case 0x4DB: case 0x4DC: case 0x4DD: case 0x4DE: case 0x4DF:
// LDRB rd, rn, immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += this.curInstruction & 0xFFF;
break;
case 0x4F0: case 0x4F1: case 0x4F2: case 0x4F3: case 0x4F4: case 0x4F5: case 0x4F6: case 0x4F7:
case 0x4F8: case 0x4F9: case 0x4FA: case 0x4FB: case 0x4FC: case 0x4FD: case 0x4FE: case 0x4FF:
// LDRBT rd, rn, immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += this.curInstruction & 0xFFF;
break;
case 0x510: case 0x511: case 0x512: case 0x513: case 0x514: case 0x515: case 0x516: case 0x517:
case 0x518: case 0x519: case 0x51A: case 0x51B: case 0x51C: case 0x51D: case 0x51E: case 0x51F:
// LDR rd, [rn, -immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x530: case 0x531: case 0x532: case 0x533: case 0x534: case 0x535: case 0x536: case 0x537:
case 0x538: case 0x539: case 0x53A: case 0x53B: case 0x53C: case 0x53D: case 0x53E: case 0x53F:
// LDR rd, [rn, -immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x550: case 0x551: case 0x552: case 0x553: case 0x554: case 0x555: case 0x556: case 0x557:
case 0x558: case 0x559: case 0x55A: case 0x55B: case 0x55C: case 0x55D: case 0x55E: case 0x55F:
// LDRB rd, [rn, -immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x570: case 0x571: case 0x572: case 0x573: case 0x574: case 0x575: case 0x576: case 0x577:
case 0x578: case 0x579: case 0x57A: case 0x57B: case 0x57C: case 0x57D: case 0x57E: case 0x57F:
// LDRB rd, [rn, -immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.curInstruction & 0xFFF;
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x590: case 0x591: case 0x592: case 0x593: case 0x594: case 0x595: case 0x596: case 0x597:
case 0x598: case 0x599: case 0x59A: case 0x59B: case 0x59C: case 0x59D: case 0x59E: case 0x59F:
// LDR rd, [rn, immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU32(registers[rn] + (this.curInstruction & 0xFFF));
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x5B0: case 0x5B1: case 0x5B2: case 0x5B3: case 0x5B4: case 0x5B5: case 0x5B6: case 0x5B7:
case 0x5B8: case 0x5B9: case 0x5BA: case 0x5BB: case 0x5BC: case 0x5BD: case 0x5BE: case 0x5BF:
// LDR rd, [rn, immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.curInstruction & 0xFFF;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x5D0: case 0x5D1: case 0x5D2: case 0x5D3: case 0x5D4: case 0x5D5: case 0x5D6: case 0x5D7:
case 0x5D8: case 0x5D9: case 0x5DA: case 0x5DB: case 0x5DC: case 0x5DD: case 0x5DE: case 0x5DF:
// LDRB rd, [rn, immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU8(registers[rn] + (this.curInstruction & 0xFFF));
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x5F0: case 0x5F1: case 0x5F2: case 0x5F3: case 0x5F4: case 0x5F5: case 0x5F6: case 0x5F7:
case 0x5F8: case 0x5F9: case 0x5FA: case 0x5FB: case 0x5FC: case 0x5FD: case 0x5FE: case 0x5FF:
// LDRB rd, [rn, immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.curInstruction & 0xFFF;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// STR register shift implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x600:
case 0x608:
// STR rd, rn, -rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x602:
case 0x60A:
// STR rd, rn, -rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x604:
case 0x60C:
// STR rd, rn, -rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x606:
case 0x60E:
// STR rd, rn, -rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x620:
case 0x628:
// STRT rd, rn, -rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x622:
case 0x62A:
// STRT rd, rn, -rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x624:
case 0x62C:
// STRT rd, rn, -rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x626:
case 0x62E:
// STRT rd, rn, -rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += offset;
break;
case 0x640:
case 0x648:
// STRB rd, rn, -rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x642:
case 0x64A:
// STRB rd, rn, -rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x644:
case 0x64C:
// STRB rd, rn, -rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x646:
case 0x64E:
// STRB rd, rn, -rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x660:
case 0x668:
// STRBT rd, rn, -rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x662:
case 0x66A:
// STRBT rd, rn, -rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x664:
case 0x66C:
// STRBT rd, rn, -rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x666:
case 0x66E:
// STRBT rd, rn, -rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += offset;
break;
case 0x680:
case 0x688:
// STR rd, rn, rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.BarrelShifterLslImmed();
break;
case 0x682:
case 0x68A:
// STR rd, rn, rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.BarrelShifterLsrImmed();
break;
case 0x684:
case 0x68C:
// STR rd, rn, rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.BarrelShifterAsrImmed();
break;
case 0x686:
case 0x68E:
// STR rd, rn, rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.BarrelShifterRorImmed();
break;
case 0x6A0:
case 0x6A2:
// STRT rd, rn, rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.BarrelShifterLslImmed();
break;
case 0x6A4:
case 0x6A6:
// STRT rd, rn, rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.BarrelShifterLsrImmed();
break;
case 0x6A8:
case 0x6AA:
// STRT rd, rn, rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.BarrelShifterAsrImmed();
break;
case 0x6AC:
case 0x6AE:
// STRT rd, rn, rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn], alu);
registers[rn] += this.BarrelShifterRorImmed();
break;
case 0x6C0:
case 0x6C8:
// STRB rd, rn, rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.BarrelShifterLslImmed();
break;
case 0x6C2:
case 0x6CA:
// STRB rd, rn, rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.BarrelShifterLsrImmed();
break;
case 0x6C4:
case 0x6CC:
// STRB rd, rn, rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.BarrelShifterAsrImmed();
break;
case 0x6C6:
case 0x6CE:
// STRB rd, rn, rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.BarrelShifterRorImmed();
break;
case 0x6E0:
case 0x6E8:
// STRBT rd, rn, rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.BarrelShifterLslImmed();
break;
case 0x6E2:
case 0x6EA:
// STRBT rd, rn, rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.BarrelShifterLsrImmed();
break;
case 0x6E4:
case 0x6EC:
// STRBT rd, rn, rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.BarrelShifterAsrImmed();
break;
case 0x6E6:
case 0x6EE:
// STRBT rd, rn, rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
registers[rn] += this.BarrelShifterRorImmed();
break;
case 0x700:
case 0x708:
// STR rd, [rn, -rm lsl immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + offset, alu);
break;
case 0x702:
case 0x70A:
// STR rd, [rn, -rm lsr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + offset, alu);
break;
case 0x704:
case 0x70C:
// STR rd, [rn, -rm asr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + offset, alu);
break;
case 0x706:
case 0x70E:
// STR rd, [rn, -rm ror immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + offset, alu);
break;
case 0x720:
case 0x728:
// STR rd, [rn, -rm lsl immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU32(registers[rn], alu);
break;
case 0x722:
case 0x72A:
// STR rd, [rn, -rm lsr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU32(registers[rn], alu);
break;
case 0x724:
case 0x72C:
// STR rd, [rn, -rm asr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU32(registers[rn], alu);
break;
case 0x726:
case 0x72E:
// STR rd, [rn, -rm ror immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU32(registers[rn], alu);
break;
case 0x740:
case 0x748:
// STRB rd, [rn, -rm lsl immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF));
break;
case 0x742:
case 0x74A:
// STRB rd, [rn, -rm lsr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF));
break;
case 0x744:
case 0x74C:
// STRB rd, [rn, -rm asr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF));
break;
case 0x746:
case 0x74E:
// STRB rd, [rn, -rm ror immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + offset, (byte)(alu & 0xFF));
break;
case 0x760:
case 0x768:
// STRB rd, [rn, -rm lsl immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
case 0x762:
case 0x76A:
// STRB rd, [rn, -rm lsr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
case 0x764:
case 0x76C:
// STRB rd, [rn, -rm asr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
case 0x766:
case 0x76E:
// STRB rd, [rn, -rm ror immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += offset;
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
case 0x780:
case 0x788:
// STR rd, [rn, rm lsl immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + this.BarrelShifterLslImmed(), alu);
break;
case 0x782:
case 0x78A:
// STR rd, [rn, rm lsr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + this.BarrelShifterLsrImmed(), alu);
break;
case 0x784:
case 0x78C:
// STR rd, [rn, rm asr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + this.BarrelShifterAsrImmed(), alu);
break;
case 0x786:
case 0x78E:
// STR rd, [rn, rm ror immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU32(registers[rn] + this.BarrelShifterRorImmed(), alu);
break;
case 0x7A0:
case 0x7A8:
// STR rd, [rn, rm lsl immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.BarrelShifterLslImmed();
this.memory.WriteU32(registers[rn], alu);
break;
case 0x7A2:
case 0x7AA:
// STR rd, [rn, rm lsr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.BarrelShifterLsrImmed();
this.memory.WriteU32(registers[rn], alu);
break;
case 0x7A4:
case 0x7AC:
// STR rd, [rn, rm asr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.BarrelShifterAsrImmed();
this.memory.WriteU32(registers[rn], alu);
break;
case 0x7A6:
case 0x7AE:
// STR rd, [rn, rm ror immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.BarrelShifterRorImmed();
this.memory.WriteU32(registers[rn], alu);
break;
case 0x7C0:
case 0x7C8:
// STRB rd, [rn, rm lsl immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + this.BarrelShifterLslImmed(), (byte)(alu & 0xFF));
break;
case 0x7C2:
case 0x7CA:
// STRB rd, [rn, rm lsr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + this.BarrelShifterLsrImmed(), (byte)(alu & 0xFF));
break;
case 0x7C4:
case 0x7CC:
// STRB rd, [rn, rm asr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + this.BarrelShifterAsrImmed(), (byte)(alu & 0xFF));
break;
case 0x7C6:
case 0x7CE:
// STRB rd, [rn, rm ror immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
this.memory.WriteU8(registers[rn] + this.BarrelShifterRorImmed(), (byte)(alu & 0xFF));
break;
case 0x7E0:
case 0x7E8:
// STRB rd, [rn, rm lsl immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.BarrelShifterLslImmed();
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
case 0x7E2:
case 0x7EA:
// STRB rd, [rn, rm lsr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.BarrelShifterLsrImmed();
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
case 0x7E4:
case 0x7EC:
// STRB rd, [rn, rm asr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.BarrelShifterAsrImmed();
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
case 0x7E6:
case 0x7EE:
// STRB rd, [rn, rm ror immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
alu = registers[rd];
if (rd == 15) alu += 4;
registers[rn] += this.BarrelShifterRorImmed();
this.memory.WriteU8(registers[rn], (byte)(alu & 0xFF));
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// LDR register shift implementations
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0x610:
case 0x618:
// LDR rd, rn, -rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x612:
case 0x61A:
// LDR rd, rn, -rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x614:
case 0x61C:
// LDR rd, rn, -rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x616:
case 0x61E:
// LDR rd, rn, -rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x630:
case 0x638:
// LDRT rd, rn, -rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x632:
case 0x63A:
// LDRT rd, rn, -rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x634:
case 0x63C:
// LDRT rd, rn, -rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x636:
case 0x63E:
// LDRT rd, rn, -rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x650:
case 0x658:
// LDRB rd, rn, -rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x652:
case 0x65A:
// LDRB rd, rn, -rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x654:
case 0x65C:
// LDRB rd, rn, -rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x656:
case 0x65E:
// LDRB rd, rn, -rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x670:
case 0x678:
// LDRBT rd, rn, -rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x672:
case 0x67A:
// LDRBT rd, rn, -rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x674:
case 0x67C:
// LDRBT rd, rn, -rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x676:
case 0x67E:
// LDRBT rd, rn, -rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x690:
case 0x698:
// LDR rd, rn, rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x692:
case 0x69A:
// LDR rd, rn, rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x694:
case 0x69C:
// LDR rd, rn, rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x696:
case 0x69E:
// LDR rd, rn, rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6B0:
case 0x6B8:
// LDRT rd, rn, rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6B2:
case 0x6BA:
// LDRT rd, rn, rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6B4:
case 0x6BC:
// LDRT rd, rn, rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6B6:
case 0x6BE:
// LDRT rd, rn, rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6D0:
case 0x6D8:
// LDRB rd, rn, rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6D2:
case 0x6DA:
// LDRB rd, rn, rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6D4:
case 0x6DC:
// LDRB rd, rn, rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6D6:
case 0x6DE:
// LDRB rd, rn, rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6F0:
case 0x6F8:
// LDRBT rd, rn, rm lsl immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6F2:
case 0x6FA:
// LDRBT rd, rn, rm lsr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6F4:
case 0x6FC:
// LDRBT rd, rn, rm asr immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x6F6:
case 0x6FE:
// LDRBT rd, rn, rm ror immed
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (rn != rd)
registers[rn] += offset;
break;
case 0x710:
case 0x718:
// LDR rd, [rn, -rm lsl immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x712:
case 0x71A:
// LDR rd, [rn, -rm lsr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x714:
case 0x71C:
// LDR rd, [rn, -rm asr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x716:
case 0x71E:
// LDR rd, [rn, -rm ror immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU32(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x730:
case 0x738:
// LDR rd, [rn, -rm lsl immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x732:
case 0x73A:
// LDR rd, [rn, -rm lsr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x734:
case 0x73C:
// LDR rd, [rn, -rm asr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x736:
case 0x73E:
// LDR rd, [rn, -rm ror immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x750:
case 0x758:
// LDRB rd, [rn, -rm lsl immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x752:
case 0x75A:
// LDRB rd, [rn, -rm lsr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x754:
case 0x75C:
// LDRB rd, [rn, -rm asr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x756:
case 0x75E:
// LDRB rd, [rn, -rm ror immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
registers[rd] = this.memory.ReadU8(registers[rn] + offset);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x770:
case 0x778:
// LDRB rd, [rn, -rm lsl immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLslImmed();
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x772:
case 0x77A:
// LDRB rd, [rn, -rm lsr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterLsrImmed();
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x774:
case 0x77C:
// LDRB rd, [rn, -rm asr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterAsrImmed();
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x776:
case 0x77E:
// LDRB rd, [rn, -rm ror immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
offset = this.BarrelShifterRorImmed();
offset = (uint)-offset;
registers[rn] += offset;
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x790:
case 0x798:
// LDR rd, [rn, rm lsl immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterLslImmed());
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x792:
case 0x79A:
// LDR rd, [rn, rm lsr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterLsrImmed());
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x794:
case 0x79C:
// LDR rd, [rn, rm asr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterAsrImmed());
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x796:
case 0x79E:
// LDR rd, [rn, rm ror immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU32(registers[rn] + this.BarrelShifterRorImmed());
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7B0:
case 0x7B8:
// LDR rd, [rn, rm lsl immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.BarrelShifterLslImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7B2:
case 0x7BA:
// LDR rd, [rn, rm lsr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.BarrelShifterLsrImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7B4:
case 0x7BC:
// LDR rd, [rn, rm asr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.BarrelShifterAsrImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7B6:
case 0x7BE:
// LDR rd, [rn, rm ror immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.BarrelShifterRorImmed();
registers[rd] = this.memory.ReadU32(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7D0:
case 0x7D8:
// LDRB rd, [rn, rm lsl immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterLslImmed());
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7D2:
case 0x7DA:
// LDRB rd, [rn, rm lsr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterLsrImmed());
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7D4:
case 0x7DC:
// LDRB rd, [rn, rm asr immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterAsrImmed());
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7D6:
case 0x7DE:
// LDRB rd, [rn, rm ror immed]
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rd] = this.memory.ReadU8(registers[rn] + this.BarrelShifterRorImmed());
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7F0:
case 0x7F8:
// LDRB rd, [rn, rm lsl immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.BarrelShifterLslImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7F2:
case 0x7FA:
// LDRB rd, [rn, rm lsr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.BarrelShifterLsrImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7F4:
case 0x7FC:
// LDRB rd, [rn, rm asr immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.BarrelShifterAsrImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
case 0x7F6:
case 0x7FE:
// LDRB rd, [rn, rm ror immed]!
rn = (this.curInstruction >> 16) & 0xF;
rd = (this.curInstruction >> 12) & 0xF;
registers[rn] += this.BarrelShifterRorImmed();
registers[rd] = this.memory.ReadU8(registers[rn]);
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// LDM implementations (TODO)
//
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
//
// STM implementations (TODO)
//
////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////
//
// B implementation
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0xA00: case 0xA01: case 0xA02: case 0xA03: case 0xA04: case 0xA05: case 0xA06: case 0xA07:
case 0xA08: case 0xA09: case 0xA0A: case 0xA0B: case 0xA0C: case 0xA0D: case 0xA0E: case 0xA0F:
case 0xA10: case 0xA11: case 0xA12: case 0xA13: case 0xA14: case 0xA15: case 0xA16: case 0xA17:
case 0xA18: case 0xA19: case 0xA1A: case 0xA1B: case 0xA1C: case 0xA1D: case 0xA1E: case 0xA1F:
case 0xA20: case 0xA21: case 0xA22: case 0xA23: case 0xA24: case 0xA25: case 0xA26: case 0xA27:
case 0xA28: case 0xA29: case 0xA2A: case 0xA2B: case 0xA2C: case 0xA2D: case 0xA2E: case 0xA2F:
case 0xA30: case 0xA31: case 0xA32: case 0xA33: case 0xA34: case 0xA35: case 0xA36: case 0xA37:
case 0xA38: case 0xA39: case 0xA3A: case 0xA3B: case 0xA3C: case 0xA3D: case 0xA3E: case 0xA3F:
case 0xA40: case 0xA41: case 0xA42: case 0xA43: case 0xA44: case 0xA45: case 0xA46: case 0xA47:
case 0xA48: case 0xA49: case 0xA4A: case 0xA4B: case 0xA4C: case 0xA4D: case 0xA4E: case 0xA4F:
case 0xA50: case 0xA51: case 0xA52: case 0xA53: case 0xA54: case 0xA55: case 0xA56: case 0xA57:
case 0xA58: case 0xA59: case 0xA5A: case 0xA5B: case 0xA5C: case 0xA5D: case 0xA5E: case 0xA5F:
case 0xA60: case 0xA61: case 0xA62: case 0xA63: case 0xA64: case 0xA65: case 0xA66: case 0xA67:
case 0xA68: case 0xA69: case 0xA6A: case 0xA6B: case 0xA6C: case 0xA6D: case 0xA6E: case 0xA6F:
case 0xA70: case 0xA71: case 0xA72: case 0xA73: case 0xA74: case 0xA75: case 0xA76: case 0xA77:
case 0xA78: case 0xA79: case 0xA7A: case 0xA7B: case 0xA7C: case 0xA7D: case 0xA7E: case 0xA7F:
case 0xA80: case 0xA81: case 0xA82: case 0xA83: case 0xA84: case 0xA85: case 0xA86: case 0xA87:
case 0xA88: case 0xA89: case 0xA8A: case 0xA8B: case 0xA8C: case 0xA8D: case 0xA8E: case 0xA8F:
case 0xA90: case 0xA91: case 0xA92: case 0xA93: case 0xA94: case 0xA95: case 0xA96: case 0xA97:
case 0xA98: case 0xA99: case 0xA9A: case 0xA9B: case 0xA9C: case 0xA9D: case 0xA9E: case 0xA9F:
case 0xAA0: case 0xAA1: case 0xAA2: case 0xAA3: case 0xAA4: case 0xAA5: case 0xAA6: case 0xAA7:
case 0xAA8: case 0xAA9: case 0xAAA: case 0xAAB: case 0xAAC: case 0xAAD: case 0xAAE: case 0xAAF:
case 0xAB0: case 0xAB1: case 0xAB2: case 0xAB3: case 0xAB4: case 0xAB5: case 0xAB6: case 0xAB7:
case 0xAB8: case 0xAB9: case 0xABA: case 0xABB: case 0xABC: case 0xABD: case 0xABE: case 0xABF:
case 0xAC0: case 0xAC1: case 0xAC2: case 0xAC3: case 0xAC4: case 0xAC5: case 0xAC6: case 0xAC7:
case 0xAC8: case 0xAC9: case 0xACA: case 0xACB: case 0xACC: case 0xACD: case 0xACE: case 0xACF:
case 0xAD0: case 0xAD1: case 0xAD2: case 0xAD3: case 0xAD4: case 0xAD5: case 0xAD6: case 0xAD7:
case 0xAD8: case 0xAD9: case 0xADA: case 0xADB: case 0xADC: case 0xADD: case 0xADE: case 0xADF:
case 0xAE0: case 0xAE1: case 0xAE2: case 0xAE3: case 0xAE4: case 0xAE5: case 0xAE6: case 0xAE7:
case 0xAE8: case 0xAE9: case 0xAEA: case 0xAEB: case 0xAEC: case 0xAED: case 0xAEE: case 0xAEF:
case 0xAF0: case 0xAF1: case 0xAF2: case 0xAF3: case 0xAF4: case 0xAF5: case 0xAF6: case 0xAF7:
case 0xAF8: case 0xAF9: case 0xAFA: case 0xAFB: case 0xAFC: case 0xAFD: case 0xAFE: case 0xAFF:
{
uint branchOffset = this.curInstruction & 0x00FFFFFF;
if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000;
this.registers[15] += branchOffset << 2;
this.FlushQueue();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// BL implementation
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0xB00: case 0xB01: case 0xB02: case 0xB03: case 0xB04: case 0xB05: case 0xB06: case 0xB07:
case 0xB08: case 0xB09: case 0xB0A: case 0xB0B: case 0xB0C: case 0xB0D: case 0xB0E: case 0xB0F:
case 0xB10: case 0xB11: case 0xB12: case 0xB13: case 0xB14: case 0xB15: case 0xB16: case 0xB17:
case 0xB18: case 0xB19: case 0xB1A: case 0xB1B: case 0xB1C: case 0xB1D: case 0xB1E: case 0xB1F:
case 0xB20: case 0xB21: case 0xB22: case 0xB23: case 0xB24: case 0xB25: case 0xB26: case 0xB27:
case 0xB28: case 0xB29: case 0xB2A: case 0xB2B: case 0xB2C: case 0xB2D: case 0xB2E: case 0xB2F:
case 0xB30: case 0xB31: case 0xB32: case 0xB33: case 0xB34: case 0xB35: case 0xB36: case 0xB37:
case 0xB38: case 0xB39: case 0xB3A: case 0xB3B: case 0xB3C: case 0xB3D: case 0xB3E: case 0xB3F:
case 0xB40: case 0xB41: case 0xB42: case 0xB43: case 0xB44: case 0xB45: case 0xB46: case 0xB47:
case 0xB48: case 0xB49: case 0xB4A: case 0xB4B: case 0xB4C: case 0xB4D: case 0xB4E: case 0xB4F:
case 0xB50: case 0xB51: case 0xB52: case 0xB53: case 0xB54: case 0xB55: case 0xB56: case 0xB57:
case 0xB58: case 0xB59: case 0xB5A: case 0xB5B: case 0xB5C: case 0xB5D: case 0xB5E: case 0xB5F:
case 0xB60: case 0xB61: case 0xB62: case 0xB63: case 0xB64: case 0xB65: case 0xB66: case 0xB67:
case 0xB68: case 0xB69: case 0xB6A: case 0xB6B: case 0xB6C: case 0xB6D: case 0xB6E: case 0xB6F:
case 0xB70: case 0xB71: case 0xB72: case 0xB73: case 0xB74: case 0xB75: case 0xB76: case 0xB77:
case 0xB78: case 0xB79: case 0xB7A: case 0xB7B: case 0xB7C: case 0xB7D: case 0xB7E: case 0xB7F:
case 0xB80: case 0xB81: case 0xB82: case 0xB83: case 0xB84: case 0xB85: case 0xB86: case 0xB87:
case 0xB88: case 0xB89: case 0xB8A: case 0xB8B: case 0xB8C: case 0xB8D: case 0xB8E: case 0xB8F:
case 0xB90: case 0xB91: case 0xB92: case 0xB93: case 0xB94: case 0xB95: case 0xB96: case 0xB97:
case 0xB98: case 0xB99: case 0xB9A: case 0xB9B: case 0xB9C: case 0xB9D: case 0xB9E: case 0xB9F:
case 0xBA0: case 0xBA1: case 0xBA2: case 0xBA3: case 0xBA4: case 0xBA5: case 0xBA6: case 0xBA7:
case 0xBA8: case 0xBA9: case 0xBAA: case 0xBAB: case 0xBAC: case 0xBAD: case 0xBAE: case 0xBAF:
case 0xBB0: case 0xBB1: case 0xBB2: case 0xBB3: case 0xBB4: case 0xBB5: case 0xBB6: case 0xBB7:
case 0xBB8: case 0xBB9: case 0xBBA: case 0xBBB: case 0xBBC: case 0xBBD: case 0xBBE: case 0xBBF:
case 0xBC0: case 0xBC1: case 0xBC2: case 0xBC3: case 0xBC4: case 0xBC5: case 0xBC6: case 0xBC7:
case 0xBC8: case 0xBC9: case 0xBCA: case 0xBCB: case 0xBCC: case 0xBCD: case 0xBCE: case 0xBCF:
case 0xBD0: case 0xBD1: case 0xBD2: case 0xBD3: case 0xBD4: case 0xBD5: case 0xBD6: case 0xBD7:
case 0xBD8: case 0xBD9: case 0xBDA: case 0xBDB: case 0xBDC: case 0xBDD: case 0xBDE: case 0xBDF:
case 0xBE0: case 0xBE1: case 0xBE2: case 0xBE3: case 0xBE4: case 0xBE5: case 0xBE6: case 0xBE7:
case 0xBE8: case 0xBE9: case 0xBEA: case 0xBEB: case 0xBEC: case 0xBED: case 0xBEE: case 0xBEF:
case 0xBF0: case 0xBF1: case 0xBF2: case 0xBF3: case 0xBF4: case 0xBF5: case 0xBF6: case 0xBF7:
case 0xBF8: case 0xBF9: case 0xBFA: case 0xBFB: case 0xBFC: case 0xBFD: case 0xBFE: case 0xBFF:
{
uint branchOffset = this.curInstruction & 0x00FFFFFF;
if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000;
this.registers[14] = this.registers[15] - 4U;
this.registers[15] += branchOffset << 2;
this.FlushQueue();
}
break;
////////////////////////////////////////////////////////////////////////////////////////////
//
// SWI implementation
//
////////////////////////////////////////////////////////////////////////////////////////////
case 0xF00: case 0xF01: case 0xF02: case 0xF03: case 0xF04: case 0xF05: case 0xF06: case 0xF07:
case 0xF08: case 0xF09: case 0xF0A: case 0xF0B: case 0xF0C: case 0xF0D: case 0xF0E: case 0xF0F:
case 0xF10: case 0xF11: case 0xF12: case 0xF13: case 0xF14: case 0xF15: case 0xF16: case 0xF17:
case 0xF18: case 0xF19: case 0xF1A: case 0xF1B: case 0xF1C: case 0xF1D: case 0xF1E: case 0xF1F:
case 0xF20: case 0xF21: case 0xF22: case 0xF23: case 0xF24: case 0xF25: case 0xF26: case 0xF27:
case 0xF28: case 0xF29: case 0xF2A: case 0xF2B: case 0xF2C: case 0xF2D: case 0xF2E: case 0xF2F:
case 0xF30: case 0xF31: case 0xF32: case 0xF33: case 0xF34: case 0xF35: case 0xF36: case 0xF37:
case 0xF38: case 0xF39: case 0xF3A: case 0xF3B: case 0xF3C: case 0xF3D: case 0xF3E: case 0xF3F:
case 0xF40: case 0xF41: case 0xF42: case 0xF43: case 0xF44: case 0xF45: case 0xF46: case 0xF47:
case 0xF48: case 0xF49: case 0xF4A: case 0xF4B: case 0xF4C: case 0xF4D: case 0xF4E: case 0xF4F:
case 0xF50: case 0xF51: case 0xF52: case 0xF53: case 0xF54: case 0xF55: case 0xF56: case 0xF57:
case 0xF58: case 0xF59: case 0xF5A: case 0xF5B: case 0xF5C: case 0xF5D: case 0xF5E: case 0xF5F:
case 0xF60: case 0xF61: case 0xF62: case 0xF63: case 0xF64: case 0xF65: case 0xF66: case 0xF67:
case 0xF68: case 0xF69: case 0xF6A: case 0xF6B: case 0xF6C: case 0xF6D: case 0xF6E: case 0xF6F:
case 0xF70: case 0xF71: case 0xF72: case 0xF73: case 0xF74: case 0xF75: case 0xF76: case 0xF77:
case 0xF78: case 0xF79: case 0xF7A: case 0xF7B: case 0xF7C: case 0xF7D: case 0xF7E: case 0xF7F:
case 0xF80: case 0xF81: case 0xF82: case 0xF83: case 0xF84: case 0xF85: case 0xF86: case 0xF87:
case 0xF88: case 0xF89: case 0xF8A: case 0xF8B: case 0xF8C: case 0xF8D: case 0xF8E: case 0xF8F:
case 0xF90: case 0xF91: case 0xF92: case 0xF93: case 0xF94: case 0xF95: case 0xF96: case 0xF97:
case 0xF98: case 0xF99: case 0xF9A: case 0xF9B: case 0xF9C: case 0xF9D: case 0xF9E: case 0xF9F:
case 0xFA0: case 0xFA1: case 0xFA2: case 0xFA3: case 0xFA4: case 0xFA5: case 0xFA6: case 0xFA7:
case 0xFA8: case 0xFA9: case 0xFAA: case 0xFAB: case 0xFAC: case 0xFAD: case 0xFAE: case 0xFAF:
case 0xFB0: case 0xFB1: case 0xFB2: case 0xFB3: case 0xFB4: case 0xFB5: case 0xFB6: case 0xFB7:
case 0xFB8: case 0xFB9: case 0xFBA: case 0xFBB: case 0xFBC: case 0xFBD: case 0xFBE: case 0xFBF:
case 0xFC0: case 0xFC1: case 0xFC2: case 0xFC3: case 0xFC4: case 0xFC5: case 0xFC6: case 0xFC7:
case 0xFC8: case 0xFC9: case 0xFCA: case 0xFCB: case 0xFCC: case 0xFCD: case 0xFCE: case 0xFCF:
case 0xFD0: case 0xFD1: case 0xFD2: case 0xFD3: case 0xFD4: case 0xFD5: case 0xFD6: case 0xFD7:
case 0xFD8: case 0xFD9: case 0xFDA: case 0xFDB: case 0xFDC: case 0xFDD: case 0xFDE: case 0xFDF:
case 0xFE0: case 0xFE1: case 0xFE2: case 0xFE3: case 0xFE4: case 0xFE5: case 0xFE6: case 0xFE7:
case 0xFE8: case 0xFE9: case 0xFEA: case 0xFEB: case 0xFEC: case 0xFED: case 0xFEE: case 0xFEF:
case 0xFF0: case 0xFF1: case 0xFF2: case 0xFF3: case 0xFF4: case 0xFF5: case 0xFF6: case 0xFF7:
case 0xFF8: case 0xFF9: case 0xFFA: case 0xFFB: case 0xFFC: case 0xFFD: case 0xFFE: case 0xFFF:
this.registers[15] -= 4U;
this.parent.EnterException(Arm7Processor.SVC, 0x8, false, false);
break;
default:
this.NormalOps[(curInstruction >> 25) & 0x7]();
break;
}
}
#region Barrel Shifter
private const uint SHIFT_LSL = 0;
private const uint SHIFT_LSR = 1;
private const uint SHIFT_ASR = 2;
private const uint SHIFT_ROR = 3;
private uint BarrelShifter(uint shifterOperand)
{
uint type = (shifterOperand >> 5) & 0x3;
bool registerShift = (shifterOperand & (1 << 4)) == (1 << 4);
uint rm = registers[shifterOperand & 0xF];
int amount;
if (registerShift)
{
uint rs = (shifterOperand >> 8) & 0xF;
if (rs == 15)
{
amount = (int)((registers[rs] + 0x4) & 0xFF);
}
else
{
amount = (int)(registers[rs] & 0xFF);
}
if ((shifterOperand & 0xF) == 15)
{
rm += 4;
}
}
else
{
amount = (int)((shifterOperand >> 7) & 0x1F);
}
if (registerShift)
{
if (amount == 0)
{
this.shifterCarry = this.carry;
return rm;
}
switch (type)
{
case SHIFT_LSL:
if (amount < 32)
{
this.shifterCarry = (rm >> (32 - amount)) & 1;
return rm << amount;
}
else if (amount == 32)
{
this.shifterCarry = rm & 1;
return 0;
}
else
{
this.shifterCarry = 0;
return 0;
}
case SHIFT_LSR:
if (amount < 32)
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return rm >> amount;
}
else if (amount == 32)
{
this.shifterCarry = (rm >> 31) & 1;
return 0;
}
else
{
this.shifterCarry = 0;
return 0;
}
case SHIFT_ASR:
if (amount >= 32)
{
if ((rm & (1 << 31)) == 0)
{
this.shifterCarry = 0;
return 0;
}
else
{
this.shifterCarry = 1;
return 0xFFFFFFFF;
}
}
else
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return (uint)(((int)rm) >> amount);
}
case SHIFT_ROR:
if ((amount & 0x1F) == 0)
{
this.shifterCarry = (rm >> 31) & 1;
return rm;
}
else
{
amount &= 0x1F;
this.shifterCarry = (rm >> amount) & 1;
return (rm >> amount) | (rm << (32 - amount));
}
}
}
else
{
switch (type)
{
case SHIFT_LSL:
if (amount == 0)
{
this.shifterCarry = this.carry;
return rm;
}
else
{
this.shifterCarry = (rm >> (32 - amount)) & 1;
return rm << amount;
}
case SHIFT_LSR:
if (amount == 0)
{
this.shifterCarry = (rm >> 31) & 1;
return 0;
}
else
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return rm >> amount;
}
case SHIFT_ASR:
if (amount == 0)
{
if ((rm & (1 << 31)) == 0)
{
this.shifterCarry = 0;
return 0;
}
else
{
this.shifterCarry = 1;
return 0xFFFFFFFF;
}
}
else
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return (uint)(((int)rm) >> amount);
}
case SHIFT_ROR:
if (amount == 0)
{
// Actually an RRX
this.shifterCarry = rm & 1;
return (this.carry << 31) | (rm >> 1);
}
else
{
this.shifterCarry = (rm >> (amount - 1)) & 1;
return (rm >> amount) | (rm << (32 - amount));
}
}
}
// Should never happen...
throw new Exception("Barrel Shifter has messed up.");
}
#endregion
#region Flag helpers
public void OverflowCarryAdd(uint a, uint b, uint r)
{
overflow = ((a & b & ~r) | (~a & ~b & r)) >> 31;
carry = ((a & b) | (a & ~r) | (b & ~r)) >> 31;
}
public void OverflowCarrySub(uint a, uint b, uint r)
{
overflow = ((a & ~b & ~r) | (~a & b & r)) >> 31;
carry = ((a & ~b) | (a & ~r) | (~b & ~r)) >> 31;
}
#endregion
#region Opcodes
private void DoDataProcessing(uint shifterOperand)
{
uint rn = (this.curInstruction >> 16) & 0xF;
uint rd = (this.curInstruction >> 12) & 0xF;
uint alu;
bool registerShift = (this.curInstruction & (1 << 4)) == (1 << 4);
if (rn == 15 && ((this.curInstruction >> 25) & 0x7) == 0 && registerShift)
{
rn = registers[rn] + 4;
}
else
{
rn = registers[rn];
}
uint opcode = (this.curInstruction >> 21) & 0xF;
if (((this.curInstruction >> 20) & 1) == 1)
{
// Set flag bit set
switch (opcode)
{
case OP_ADC:
registers[rd] = rn + shifterOperand + carry;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
break;
case OP_ADD:
registers[rd] = rn + shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, registers[rd]);
break;
case OP_AND:
registers[rd] = rn & shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case OP_BIC:
registers[rd] = rn & ~shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case OP_CMN:
alu = rn + shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarryAdd(rn, shifterOperand, alu);
break;
case OP_CMP:
alu = rn - shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, alu);
break;
case OP_EOR:
registers[rd] = rn ^ shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case OP_MOV:
registers[rd] = shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case OP_MVN:
registers[rd] = ~shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case OP_ORR:
registers[rd] = rn | shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case OP_RSB:
registers[rd] = shifterOperand - rn;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
break;
case OP_RSC:
registers[rd] = shifterOperand - rn - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(shifterOperand, rn, registers[rd]);
break;
case OP_SBC:
registers[rd] = rn - shifterOperand - (1U - carry);
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
break;
case OP_SUB:
registers[rd] = rn - shifterOperand;
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
this.OverflowCarrySub(rn, shifterOperand, registers[rd]);
break;
case OP_TEQ:
alu = rn ^ shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
case OP_TST:
alu = rn & shifterOperand;
negative = alu >> 31;
zero = alu == 0 ? 1U : 0U;
carry = this.shifterCarry;
break;
}
if (rd == 15)
{
// Prevent writing if no SPSR exists (this will be true for USER or SYSTEM mode)
if (this.parent.SPSRExists) this.parent.WriteCpsr(this.parent.SPSR);
this.UnpackFlags();
// Check for branch back to Thumb Mode
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
return;
}
// Otherwise, flush the instruction queue
this.FlushQueue();
}
}
else
{
// Set flag bit not set
switch (opcode)
{
case OP_ADC: registers[rd] = rn + shifterOperand + carry; break;
case OP_ADD: registers[rd] = rn + shifterOperand; break;
case OP_AND: registers[rd] = rn & shifterOperand; break;
case OP_BIC: registers[rd] = rn & ~shifterOperand; break;
case OP_EOR: registers[rd] = rn ^ shifterOperand; break;
case OP_MOV: registers[rd] = shifterOperand; break;
case OP_MVN: registers[rd] = ~shifterOperand; break;
case OP_ORR: registers[rd] = rn | shifterOperand; break;
case OP_RSB: registers[rd] = shifterOperand - rn; break;
case OP_RSC: registers[rd] = shifterOperand - rn - (1U - carry); break;
case OP_SBC: registers[rd] = rn - shifterOperand - (1U - carry); break;
case OP_SUB: registers[rd] = rn - shifterOperand; break;
case OP_CMN:
// MSR SPSR, shifterOperand
if ((this.curInstruction & (1 << 16)) == 1 << 16 && this.parent.SPSRExists)
{
this.parent.SPSR &= 0xFFFFFF00;
this.parent.SPSR |= shifterOperand & 0x000000FF;
}
if ((this.curInstruction & (1 << 17)) == 1 << 17 && this.parent.SPSRExists)
{
this.parent.SPSR &= 0xFFFF00FF;
this.parent.SPSR |= shifterOperand & 0x0000FF00;
}
if ((this.curInstruction & (1 << 18)) == 1 << 18 && this.parent.SPSRExists)
{
this.parent.SPSR &= 0xFF00FFFF;
this.parent.SPSR |= shifterOperand & 0x00FF0000;
}
if ((this.curInstruction & (1 << 19)) == 1 << 19 && this.parent.SPSRExists)
{
this.parent.SPSR &= 0x00FFFFFF;
this.parent.SPSR |= shifterOperand & 0xFF000000;
}
// Queue will be flushed since rd == 15, so adjust the PC
registers[15] -= 4;
break;
case OP_CMP:
// MRS rd, SPSR
if (this.parent.SPSRExists) registers[rd] = this.parent.SPSR;
break;
case OP_TEQ:
if (((this.curInstruction >> 4) & 0xf) == 1)
{
// BX
uint rm = this.curInstruction & 0xf;
this.PackFlags();
this.parent.CPSR &= ~Arm7Processor.T_MASK;
this.parent.CPSR |= (registers[rm] & 1) << Arm7Processor.T_BIT;
registers[15] = registers[rm] & (~1U);
this.UnpackFlags();
// Check for branch back to Thumb Mode
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
return;
}
// Queue will be flushed later because rd == 15
}
else if (((this.curInstruction >> 4) & 0xf) == 0)
{
// MSR CPSR, shifterOperand
bool userMode = (this.parent.CPSR & 0x1F) == Arm7Processor.USR;
this.PackFlags();
uint tmpCPSR = this.parent.CPSR;
if ((this.curInstruction & (1 << 16)) == 1 << 16 && !userMode)
{
tmpCPSR &= 0xFFFFFF00;
tmpCPSR |= shifterOperand & 0x000000FF;
}
if ((this.curInstruction & (1 << 17)) == 1 << 17 && !userMode)
{
tmpCPSR &= 0xFFFF00FF;
tmpCPSR |= shifterOperand & 0x0000FF00;
}
if ((this.curInstruction & (1 << 18)) == 1 << 18 && !userMode)
{
tmpCPSR &= 0xFF00FFFF;
tmpCPSR |= shifterOperand & 0x00FF0000;
}
if ((this.curInstruction & (1 << 19)) == 1 << 19)
{
tmpCPSR &= 0x00FFFFFF;
tmpCPSR |= shifterOperand & 0xFF000000;
}
this.parent.WriteCpsr(tmpCPSR);
this.UnpackFlags();
// Check for branch back to Thumb Mode
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
return;
}
// Queue will be flushed since rd == 15, so adjust the PC
registers[15] -= 4;
}
break;
case OP_TST:
// MRS rd, CPSR
this.PackFlags();
registers[rd] = this.parent.CPSR;
break;
}
if (rd == 15)
{
// Flush the queue
this.FlushQueue();
}
}
}
private void DataProcessing()
{
// Special instruction
switch ((this.curInstruction >> 4) & 0xF)
{
case 0x9:
// Multiply or swap instructions
this.MultiplyOrSwap();
return;
case 0xB:
// Load/Store Unsigned halfword
this.LoadStoreHalfword();
return;
case 0xD:
// Load/Store Signed byte
this.LoadStoreHalfword();
return;
case 0xF:
// Load/Store Signed halfword
this.LoadStoreHalfword();
return;
}
this.DoDataProcessing(this.BarrelShifter(this.curInstruction));
}
private void DataProcessingImmed()
{
uint immed = this.curInstruction & 0xFF;
int rotateAmount = (int)(((this.curInstruction >> 8) & 0xF) * 2);
immed = (immed >> rotateAmount) | (immed << (32 - rotateAmount));
if (rotateAmount == 0)
{
this.shifterCarry = this.carry;
}
else
{
this.shifterCarry = (immed >> 31) & 1;
}
this.DoDataProcessing(immed);
}
private void LoadStore(uint offset)
{
uint rn = (this.curInstruction >> 16) & 0xF;
uint rd = (this.curInstruction >> 12) & 0xF;
uint address = registers[rn];
bool preIndexed = (this.curInstruction & (1 << 24)) == 1 << 24;
bool byteTransfer = (this.curInstruction & (1 << 22)) == 1 << 22;
bool writeback = (this.curInstruction & (1 << 21)) == 1 << 21;
// Add or subtract offset
if ((this.curInstruction & (1 << 23)) != 1 << 23) offset = (uint)-offset;
if (preIndexed)
{
address += offset;
if (writeback)
{
registers[rn] = address;
}
}
if ((this.curInstruction & (1 << 20)) == 1 << 20)
{
// Load
if (byteTransfer)
{
registers[rd] = this.memory.ReadU8(address);
}
else
{
registers[rd] = this.memory.ReadU32(address);
}
// ARM9 fix here
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (!preIndexed)
{
if (rn != rd)
registers[rn] = address + offset;
}
}
else
{
// Store
uint amount = registers[rd];
if (rd == 15) amount += 4;
if (byteTransfer)
{
this.memory.WriteU8(address, (byte)(amount & 0xFF));
}
else
{
this.memory.WriteU32(address, amount);
}
if (!preIndexed)
{
registers[rn] = address + offset;
}
}
}
private void LoadStoreImmediate()
{
this.LoadStore(this.curInstruction & 0xFFF);
}
private void LoadStoreRegister()
{
// The barrel shifter expects a 0 in bit 4 for immediate shifts, this is implicit in
// the meaning of the instruction, so it is fine
this.LoadStore(this.BarrelShifter(this.curInstruction));
}
private void LoadStoreMultiple()
{
uint rn = (this.curInstruction >> 16) & 0xF;
this.PackFlags();
uint curCpsr = this.parent.CPSR;
bool preIncrement = (this.curInstruction & (1 << 24)) != 0;
bool up = (this.curInstruction & (1 << 23)) != 0;
bool writeback = (this.curInstruction & (1 << 21)) != 0;
uint address;
uint bitsSet = 0;
for (int i = 0; i < 16; i++) if (((this.curInstruction >> i) & 1) != 0) bitsSet++;
if (preIncrement)
{
if (up)
{
// Increment before
address = this.registers[rn] + 4;
if (writeback) this.registers[rn] += bitsSet * 4;
}
else
{
// Decrement before
address = this.registers[rn] - (bitsSet * 4);
if (writeback) this.registers[rn] -= bitsSet * 4;
}
}
else
{
if (up)
{
// Increment after
address = this.registers[rn];
if (writeback) this.registers[rn] += bitsSet * 4;
}
else
{
// Decrement after
address = this.registers[rn] - (bitsSet * 4) + 4;
if (writeback) this.registers[rn] -= bitsSet * 4;
}
}
if ((this.curInstruction & (1 << 20)) != 0)
{
if ((this.curInstruction & (1 << 22)) != 0 && ((this.curInstruction >> 15) & 1) == 0)
{
// Switch to user mode temporarily
this.parent.WriteCpsr((curCpsr & ~0x1FU) | Arm7Processor.USR);
}
// Load multiple
for (int i = 0; i < 15; i++)
{
if (((this.curInstruction >> i) & 1) != 1) continue;
this.registers[i] = this.memory.ReadU32Aligned(address & (~0x3U));
address += 4;
}
if (((this.curInstruction >> 15) & 1) == 1)
{
// Arm9 fix here
this.registers[15] = this.memory.ReadU32Aligned(address & (~0x3U));
if ((this.curInstruction & (1 << 22)) != 0)
{
// Load the CPSR from the SPSR
if (this.parent.SPSRExists)
{
this.parent.WriteCpsr(this.parent.SPSR);
this.UnpackFlags();
// Check for branch back to Thumb Mode
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
this.registers[15] &= ~0x1U;
return;
}
}
}
this.registers[15] &= ~0x3U;
this.FlushQueue();
}
else
{
if ((this.curInstruction & (1 << 22)) != 0)
{
// Switch back to the correct mode
this.parent.WriteCpsr(curCpsr);
this.UnpackFlags();
if ((this.parent.CPSR & Arm7Processor.T_MASK) == Arm7Processor.T_MASK)
{
this.thumbMode = true;
return;
}
}
}
}
else
{
if ((this.curInstruction & (1 << 22)) != 0)
{
// Switch to user mode temporarily
this.parent.WriteCpsr((curCpsr & ~0x1FU) | Arm7Processor.USR);
}
/* if (((this.curInstruction >> (int)rn) & 1) != 0 && writeback &&
(this.curInstruction & ~(0xFFFFFFFF << (int)rn)) == 0)
{
// If the lowest register is also the writeback, we use the original value
// Does anybody do this????
throw new Exception("Unhandled STM state");
}
else*/
{
// Store multiple
for (int i = 0; i < 15; i++)
{
if (((this.curInstruction >> i) & 1) == 0) continue;
this.memory.WriteU32(address, this.registers[i]);
address += 4;
}
if (((this.curInstruction >> 15) & 1) != 0)
{
this.memory.WriteU32(address, this.registers[15] + 4U);
}
}
if ((this.curInstruction & (1 << 22)) != 0)
{
// Switch back to the correct mode
this.parent.WriteCpsr(curCpsr);
this.UnpackFlags();
}
}
}
private void Branch()
{
if ((this.curInstruction & (1 << 24)) != 0)
{
this.registers[14] = (this.registers[15] - 4U) & ~3U;
}
uint branchOffset = this.curInstruction & 0x00FFFFFF;
if (branchOffset >> 23 == 1) branchOffset |= 0xFF000000;
this.registers[15] += branchOffset << 2;
this.FlushQueue();
}
private void CoprocessorLoadStore()
{
throw new Exception("Unhandled opcode - coproc load/store");
}
private void SoftwareInterrupt()
{
// Adjust PC for prefetch
this.registers[15] -= 4U;
this.parent.EnterException(Arm7Processor.SVC, 0x8, false, false);
}
private void MultiplyOrSwap()
{
if ((this.curInstruction & (1 << 24)) == 1 << 24)
{
// Swap instruction
uint rn = (this.curInstruction >> 16) & 0xF;
uint rd = (this.curInstruction >> 12) & 0xF;
uint rm = this.curInstruction & 0xF;
if ((this.curInstruction & (1 << 22)) != 0)
{
// SWPB
byte tmp = this.memory.ReadU8(registers[rn]);
this.memory.WriteU8(registers[rn], (byte)(registers[rm] & 0xFF));
registers[rd] = tmp;
}
else
{
// SWP
uint tmp = this.memory.ReadU32(registers[rn]);
this.memory.WriteU32(registers[rn], registers[rm]);
registers[rd] = tmp;
}
}
else
{
// Multiply instruction
switch ((this.curInstruction >> 21) & 0x7)
{
case 0:
case 1:
{
// Multiply/Multiply + Accumulate
uint rd = (this.curInstruction >> 16) & 0xF;
uint rn = registers[(this.curInstruction >> 12) & 0xF];
uint rs = (this.curInstruction >> 8) & 0xF;
uint rm = this.curInstruction & 0xF;
int cycles = 4;
// Multiply cycle calculations
if ((registers[rs] & 0xFFFFFF00) == 0 || (registers[rs] & 0xFFFFFF00) == 0xFFFFFF00)
{
cycles = 1;
}
else if ((registers[rs] & 0xFFFF0000) == 0 || (registers[rs] & 0xFFFF0000) == 0xFFFF0000)
{
cycles = 2;
}
else if ((registers[rs] & 0xFF000000) == 0 || (registers[rs] & 0xFF000000) == 0xFF000000)
{
cycles = 3;
}
registers[rd] = registers[rs] * registers[rm];
this.parent.Cycles -= cycles;
if ((this.curInstruction & (1 << 21)) == 1 << 21)
{
registers[rd] += rn;
this.parent.Cycles -= 1;
}
if ((this.curInstruction & (1 << 20)) == 1 << 20)
{
negative = registers[rd] >> 31;
zero = registers[rd] == 0 ? 1U : 0U;
}
break;
}
case 2:
case 3:
throw new Exception("Invalid multiply");
case 4:
case 5:
case 6:
case 7:
{
// Multiply/Signed Multiply Long
uint rdhi = (this.curInstruction >> 16) & 0xF;
uint rdlo = (this.curInstruction >> 12) & 0xF;
uint rs = (this.curInstruction >> 8) & 0xF;
uint rm = this.curInstruction & 0xF;
int cycles = 5;
// Multiply cycle calculations
if ((registers[rs] & 0xFFFFFF00) == 0 || (registers[rs] & 0xFFFFFF00) == 0xFFFFFF00)
{
cycles = 2;
}
else if ((registers[rs] & 0xFFFF0000) == 0 || (registers[rs] & 0xFFFF0000) == 0xFFFF0000)
{
cycles = 3;
}
else if ((registers[rs] & 0xFF000000) == 0 || (registers[rs] & 0xFF000000) == 0xFF000000)
{
cycles = 4;
}
this.parent.Cycles -= cycles;
switch ((this.curInstruction >> 21) & 0x3)
{
case 0:
{
// UMULL
ulong result = ((ulong)registers[rm]) * registers[rs];
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
break;
}
case 1:
{
// UMLAL
ulong accum = (((ulong)registers[rdhi]) << 32) | registers[rdlo];
ulong result = ((ulong)registers[rm]) * registers[rs];
result += accum;
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
break;
}
case 2:
{
// SMULL
long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs]));
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
break;
}
case 3:
{
// SMLAL
long accum = (((long)((int)registers[rdhi])) << 32) | registers[rdlo];
long result = ((long)((int)registers[rm])) * ((long)((int)registers[rs]));
result += accum;
registers[rdhi] = (uint)(result >> 32);
registers[rdlo] = (uint)(result & 0xFFFFFFFF);
break;
}
}
if ((this.curInstruction & (1 << 20)) == 1 << 20)
{
negative = registers[rdhi] >> 31;
zero = (registers[rdhi] == 0 && registers[rdlo] == 0) ? 1U : 0U;
}
break;
}
}
}
}
private void LoadStoreHalfword()
{
uint rn = (this.curInstruction >> 16) & 0xF;
uint rd = (this.curInstruction >> 12) & 0xF;
uint address = registers[rn];
bool preIndexed = (this.curInstruction & (1 << 24)) != 0;
bool byteTransfer = (this.curInstruction & (1 << 5)) == 0;
bool signedTransfer = (this.curInstruction & (1 << 6)) != 0;
bool writeback = (this.curInstruction & (1 << 21)) != 0;
uint offset;
if ((this.curInstruction & (1 << 22)) != 0)
{
// Immediate offset
offset = ((this.curInstruction & 0xF00) >> 4) | (this.curInstruction & 0xF);
}
else
{
// Register offset
offset = this.registers[this.curInstruction & 0xF];
}
// Add or subtract offset
if ((this.curInstruction & (1 << 23)) == 0) offset = (uint)-offset;
if (preIndexed)
{
address += offset;
if (writeback)
{
registers[rn] = address;
}
}
if ((this.curInstruction & (1 << 20)) != 0)
{
// Load
if (byteTransfer)
{
if (signedTransfer)
{
registers[rd] = this.memory.ReadU8(address);
if ((registers[rd] & 0x80) != 0)
{
registers[rd] |= 0xFFFFFF00;
}
}
else
{
registers[rd] = this.memory.ReadU8(address);
}
}
else
{
if (signedTransfer)
{
registers[rd] = this.memory.ReadU16(address);
if ((registers[rd] & 0x8000) != 0)
{
registers[rd] |= 0xFFFF0000;
}
}
else
{
registers[rd] = this.memory.ReadU16(address);
}
}
if (rd == 15)
{
registers[rd] &= ~3U;
this.FlushQueue();
}
if (!preIndexed)
{
if (rn != rd)
registers[rn] = address + offset;
}
}
else
{
// Store
if (byteTransfer)
{
this.memory.WriteU8(address, (byte)(registers[rd] & 0xFF));
}
else
{
this.memory.WriteU16(address, (ushort)(registers[rd] & 0xFFFF));
}
if (!preIndexed)
{
registers[rn] = address + offset;
}
}
}
#endregion Opcodes
private void PackFlags()
{
this.parent.CPSR &= 0x0FFFFFFF;
this.parent.CPSR |= this.negative << Arm7Processor.N_BIT;
this.parent.CPSR |= this.zero << Arm7Processor.Z_BIT;
this.parent.CPSR |= this.carry << Arm7Processor.C_BIT;
this.parent.CPSR |= this.overflow << Arm7Processor.V_BIT;
}
private void UnpackFlags()
{
this.negative = (this.parent.CPSR >> Arm7Processor.N_BIT) & 1;
this.zero = (this.parent.CPSR >> Arm7Processor.Z_BIT) & 1;
this.carry = (this.parent.CPSR >> Arm7Processor.C_BIT) & 1;
this.overflow = (this.parent.CPSR >> Arm7Processor.V_BIT) & 1;
}
private void FlushQueue()
{
this.instructionQueue = this.memory.ReadU32(registers[15]);
registers[15] += 4;
}
}
}