Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/attic/GarboDev/FastArmCore.cs
2 views
//#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;
        }
    }
}