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