Example #1
0
        /// <summary>
        ///     Branch (1).
        /// </summary>
        private void Thumb_B()
        {
            sbyte Immediate = (sbyte)(Opcode & 0xff);

            ARMCondition Condition = (ARMCondition)((Opcode >> 8) & 0xf);

            if (IsConditionMet(Condition))
            {
                Registers[15] = (uint)(Registers[15] + (Immediate << 1));
            }
        }
Example #2
0
    public List<string> Disassemble(uint* ptr, int count)
    {
        List<string> instructions = new();

        while (count --> 0)
        {
            uint cond = (*ptr & MASK_COND) >> RSHIFT_COND;

            if (cond >= 0b1111)
                instructions.Add($"NOP  ; undefined behaviour in COND: 0x{*ptr:x8}");
            else
            {
                string rn = get_register(ptr, ARMRegisterType.Rn);
                string rd = get_register(ptr, ARMRegisterType.Rd);
                string rs = get_register(ptr, ARMRegisterType.Rs);
                string rm = get_register(ptr, ARMRegisterType.Rm);
                string suffix = (ARMCondition)cond switch
                {
                    ARMCondition.AL or
                    ARMCondition.RV => "",
                    ARMCondition c => c.ToString(),
                };

                if ((matches(*ptr, MASK_DATA_PROCESSING, MATCH_DATA_PROCESSING) ||
                    matches(*ptr, MASK_MULTIPLY, MATCH_MULTIPLY) ||
                    matches(*ptr, MASK_MULTIPLY_LONG, MATCH_MULTIPLY_LONG)) &&
                    (*ptr & MASK_BIT_SL) != 0)
                    suffix += 'S';

                if (matches(*ptr, MASK_BRANCH, MATCH_BRANCH))
                {
                    string instr = get_bit(ptr, ARMInstructionBit.Link) ? "BL" : "B";
                    int offs = (int)((*ptr & MASK_BR_OFFSET) << 8);

                    instructions.Add($"{instr}{suffix} 0x{offs >> 6:x8}");
                }
                else if (matches(*ptr, MASK_DATA_PROCESSING, MATCH_DATA_PROCESSING))
                {
                    ARMDataProcessingOpCode opcode = (ARMDataProcessingOpCode)((*ptr & MASK_OPCODE) >> RSHIFT_OPCODE);
                    string instr = $"{opcode}{suffix} {opcode switch
                    {
                        ARMDataProcessingOpCode.MOV or
                        ARMDataProcessingOpCode.MVN => rd,
                        ARMDataProcessingOpCode.CMP or
                        ARMDataProcessingOpCode.CMN or
                        ARMDataProcessingOpCode.TEQ or
                        ARMDataProcessingOpCode.TST => rn,
                        _ => $"{rd}, {rn}",
                    }}, ";
Example #3
0
        /// <summary>
        ///     Checks whenever the Condition of a Opcode matches the current Status Register, to see if the condition is true.
        /// </summary>
        /// <param name="Condition">The Condition of the Opcode</param>
        /// <returns>If the condition is true or not</returns>
        private bool IsConditionMet(ARMCondition Condition)
        {
            switch (Condition)
            {
            case ARMCondition.Equal: return(Registers.IsFlagSet(ARMFlag.Zero));

            case ARMCondition.NotEqual: return(Registers.IsFlagClear(ARMFlag.Zero));

            case ARMCondition.CarrySet: return(Registers.IsFlagSet(ARMFlag.Carry));

            case ARMCondition.CarryClear: return(Registers.IsFlagClear(ARMFlag.Carry));

            case ARMCondition.Minus: return(Registers.IsFlagSet(ARMFlag.Negative));

            case ARMCondition.Plus: return(Registers.IsFlagClear(ARMFlag.Negative));

            case ARMCondition.Overflow: return(Registers.IsFlagSet(ARMFlag.Overflow));

            case ARMCondition.NoOverflow: return(Registers.IsFlagClear(ARMFlag.Overflow));

            case ARMCondition.UnsignedHigher: return(ConditionHI());

            case ARMCondition.UnsignedLowerOrSame: return(ConditionLS());

            case ARMCondition.SignedGreaterThanOrEqual: return(ConditionGE());

            case ARMCondition.SignedLessThan: return(ConditionLT());

            case ARMCondition.SignedGreaterThan: return(Registers.IsFlagClear(ARMFlag.Zero) && ConditionGE());

            case ARMCondition.SignedLessThanOrEqual: return(Registers.IsFlagSet(ARMFlag.Zero) || ConditionLT());

            case ARMCondition.Always: return(true);
            }

            return(false);
        }
Example #4
0
        /// <summary>
        ///     Executes a single instruction.
        /// </summary>
        public void Execute()
        {
            uint TruePC = Registers[15] - 4;

            if (Registers.IsFlagSet(ARMFlag.Thumb))
            {
                Opcode              = NextOpcode;
                NextOpcode          = ReadUInt16(Registers[15]);
                Registers[15]      += 2;
                Registers.PCChanged = false;

                switch ((Opcode >> 13) & 7)
                {
                case 0:
                    switch ((Opcode >> 11) & 3)
                    {
                    case 0: Thumb_LSL(); break;

                    case 1: Thumb_LSR(); break;

                    case 2: Thumb_ASR(); break;

                    case 3:
                        if (IsOpcodeBitSet(9))
                        {
                            if (IsOpcodeBitSet(10))
                            {
                                Thumb_SUB();
                            }
                            else
                            {
                                Thumb_SUB_3();
                            }
                        }
                        else
                        {
                            if (IsOpcodeBitSet(10))
                            {
                                Thumb_ADD();
                            }
                            else
                            {
                                Thumb_ADD_3();
                            }
                        }
                        break;
                    }
                    break;

                case 1:
                    switch ((Opcode >> 11) & 3)
                    {
                    case 0: Thumb_MOV(); break;

                    case 1: Thumb_CMP(); break;

                    case 2: Thumb_ADD_2(); break;

                    case 3: Thumb_SUB_2(); break;
                    }
                    break;

                case 2:
                    if (IsOpcodeBitSet(12))
                    {
                        switch ((Opcode >> 9) & 7)
                        {
                        case 0: Thumb_STR_2(); break;

                        case 1: Thumb_STRH_2(); break;

                        case 2: Thumb_STRB_2(); break;

                        case 3: Thumb_LDRSB(); break;

                        case 4: Thumb_LDR_2(); break;

                        case 5: Thumb_LDRH_2(); break;

                        case 6: Thumb_LDRB_2(); break;

                        case 7: Thumb_LDRSH(); break;
                        }
                    }
                    else
                    {
                        if (IsOpcodeBitSet(11))
                        {
                            Thumb_LDR_3();
                        }
                        else
                        {
                            if (IsOpcodeBitSet(10))
                            {
                                switch ((Opcode >> 8) & 3)
                                {
                                case 0: Thumb_ADD_4(); break;

                                case 1: Thumb_CMP_3(); break;

                                case 2: Thumb_CPY(); break;

                                case 3:
                                    if (IsOpcodeBitSet(7))
                                    {
                                        Thumb_BLX_2();
                                    }
                                    else
                                    {
                                        Thumb_BX();
                                    }
                                    break;
                                }
                            }
                            else     //Data Processing
                            {
                                switch ((Opcode >> 6) & 0xf)
                                {
                                case 0: Thumb_AND(); break;

                                case 1: Thumb_EOR(); break;

                                case 2: Thumb_LSL_2(); break;

                                case 3: Thumb_LSR_2(); break;

                                case 4: Thumb_ASR_2(); break;

                                case 5: Thumb_ADC(); break;

                                case 6: Thumb_SBC(); break;

                                case 7: Thumb_ROR(); break;

                                case 8: Thumb_TST(); break;

                                case 9: Thumb_NEG(); break;

                                case 0xa: Thumb_CMP_2(); break;

                                case 0xb: Thumb_CMN(); break;

                                case 0xc: Thumb_ORR(); break;

                                case 0xd: Thumb_MUL(); break;

                                case 0xe: Thumb_BIC(); break;

                                case 0xf: Thumb_MVN(); break;
                                }
                            }
                        }
                    }
                    break;

                case 3:
                    if (IsOpcodeBitSet(11))
                    {
                        if (IsOpcodeBitSet(12))
                        {
                            Thumb_LDRB();
                        }
                        else
                        {
                            Thumb_LDR();
                        }
                    }
                    else
                    {
                        if (IsOpcodeBitSet(12))
                        {
                            Thumb_STRB();
                        }
                        else
                        {
                            Thumb_STR();
                        }
                    }
                    break;

                case 4:
                    if (IsOpcodeBitSet(12))
                    {
                        if (IsOpcodeBitSet(11))
                        {
                            Thumb_LDR_4();
                        }
                        else
                        {
                            Thumb_STR_3();
                        }
                    }
                    else
                    {
                        if (IsOpcodeBitSet(11))
                        {
                            Thumb_LDRH();
                        }
                        else
                        {
                            Thumb_STRH();
                        }
                    }
                    break;

                case 5:
                    if (IsOpcodeBitSet(12))
                    {
                        switch ((Opcode >> 9) & 3)
                        {
                        case 0:
                            if (IsOpcodeBitSet(7))
                            {
                                Thumb_SUB_4();
                            }
                            else
                            {
                                Thumb_ADD_7();
                            }
                            break;

                        case 1:
                            if (IsOpcodeBitSet(11))
                            {
                                switch ((Opcode >> 6) & 3)
                                {
                                case 0: Thumb_REV(); break;

                                case 1: Thumb_REV16(); break;

                                case 3: Thumb_REVSH(); break;
                                }
                            }
                            else
                            {
                                switch ((Opcode >> 6) & 3)
                                {
                                case 0: Thumb_SXTH(); break;

                                case 1: Thumb_SXTB(); break;

                                case 2: Thumb_UXTH(); break;

                                case 3: Thumb_UXTB(); break;
                                }
                            }
                            break;

                        case 2:
                            if (IsOpcodeBitSet(11))
                            {
                                Thumb_POP();
                            }
                            else
                            {
                                Thumb_PUSH();
                            }
                            break;

                        case 3:
                            if (IsOpcodeBitSet(11))
                            {
                                Thumb_BKPT();
                            }
                            else
                            {
                                if (IsOpcodeBitSet(5))
                                {
                                    Thumb_CPS();
                                }
                                else
                                {
                                    Thumb_SETEND();
                                }
                            }
                            break;
                        }
                    }
                    else
                    {
                        if (IsOpcodeBitSet(11))
                        {
                            Thumb_ADD_6();
                        }
                        else
                        {
                            Thumb_ADD_5();
                        }
                    }
                    break;

                case 6:
                    if (IsOpcodeBitSet(12))
                    {
                        if (((Opcode >> 8) & 0xf) == 0xf)
                        {
                            Thumb_SWI();
                        }
                        else
                        {
                            Thumb_B();
                        }
                    }
                    else
                    {
                        if (IsOpcodeBitSet(11))
                        {
                            Thumb_LDMIA();
                        }
                        else
                        {
                            Thumb_STMIA();
                        }
                    }
                    break;

                case 7:
                    if (((Opcode >> 11) & 3) == 0)
                    {
                        Thumb_B_2();
                    }
                    else
                    {
                        Thumb_BLX();
                    }
                    break;
                }
            }
            else
            {
                Opcode              = NextOpcode;
                NextOpcode          = ReadUInt32(Registers[15]);
                Registers[15]      += 4;
                Registers.PCChanged = false;

                ARMCondition Condition = (ARMCondition)(Opcode >> 28);
                if (IsConditionMet(Condition))
                {
                    switch ((Opcode >> 25) & 7)
                    {
                    case 0:
                    case 1:
                        if (IsOpcodeBitSet(4) && IsOpcodeBitSet(7) && !IsOpcodeBitSet(25))
                        {
                            if (((Opcode >> 5) & 3) > 0 || IsOpcodeBitSet(24))
                            {
                                ARM_DecodeLoadAndStoreExtension();
                            }
                            else
                            {
                                ARM_DecodeMultiplyExtension();
                            }
                        }
                        else
                        {
                            if (((Opcode >> 23) & 3) == 2 && !IsOpcodeBitSet(20))
                            {
                                ARM_DecodeDSPExtension();
                            }
                            else     //Data Processing
                            {
                                switch ((Opcode >> 21) & 0xf)
                                {
                                case 0: ARM_AND(); break;

                                case 1: ARM_EOR(); break;

                                case 2: ARM_SUB(); break;

                                case 3: ARM_RSB(); break;

                                case 4: ARM_ADD(); break;

                                case 5: ARM_ADC(); break;

                                case 6: ARM_SBC(); break;

                                case 7: ARM_RSC(); break;

                                case 8: ARM_TST(); break;

                                case 9: ARM_TEQ(); break;

                                case 0xa: ARM_CMP(); break;

                                case 0xb: ARM_CMN(); break;

                                case 0xc: ARM_ORR(); break;

                                case 0xd: ARM_MOV(); break;

                                case 0xe: ARM_BIC(); break;

                                case 0xf: ARM_MVN(); break;
                                }
                            }
                        }
                        break;

                    case 2:
                    case 3:
                        if (IsOpcodeBitSet(4) && IsOpcodeBitSet(25))
                        {
                            ARM_DecodeMediaExtension();
                        }
                        else     //Load/Store
                        {
                            if (IsOpcodeBitSet(20))
                            {
                                if (IsOpcodeBitSet(22))
                                {
                                    ARM_LDRB();
                                }
                                else
                                {
                                    ARM_LDR();
                                }
                            }
                            else
                            {
                                if (IsOpcodeBitSet(22))
                                {
                                    ARM_STRB();
                                }
                                else
                                {
                                    ARM_STR();
                                }
                            }
                        }
                        break;

                    case 4:
                        //Load/Store Multiple
                        if (IsOpcodeBitSet(20))
                        {
                            ARM_LDM();
                        }
                        else
                        {
                            ARM_STM();
                        }
                        break;

                    case 5: ARM_B(); break;

                    case 6:
                    case 7:
                        //Coprocessor
                        if (IsOpcodeBitSet(25))
                        {
                            if (IsOpcodeBitSet(24))
                            {
                                ARM_SWI();
                            }
                            else
                            {
                                if (IsOpcodeBitSet(4))
                                {
                                    if (IsOpcodeBitSet(20))
                                    {
                                        ARM_MRC();
                                    }
                                    else
                                    {
                                        ARM_MCR();
                                    }
                                }
                                else
                                {
                                    ARM_CDP();
                                }
                            }
                        }
                        else
                        {
                            if (IsOpcodeBitSet(20))
                            {
                                ARM_MRRC();
                            }
                            else
                            {
                                ARM_MCRR();
                            }
                        }
                        break;
                    }
                }
                else if (Condition == ARMCondition.Unconditional)
                {
                    switch ((Opcode >> 26) & 3)
                    {
                    case 0:
                        if (IsOpcodeBitSet(16))
                        {
                            ARM_SETEND();
                        }
                        else
                        {
                            ARM_CPS();
                        }
                        break;

                    case 1: ARM_PLD(); break;

                    case 2:
                        if (IsOpcodeBitSet(25))
                        {
                            ARM_BLX();
                        }
                        else
                        {
                            if (IsOpcodeBitSet(22))
                            {
                                ARM_SRS();
                            }
                            else
                            {
                                ARM_RFE();
                            }
                        }
                        break;

                    case 3:
                        if (IsOpcodeBitSet(25))
                        {
                            if (IsOpcodeBitSet(20))
                            {
                                ARM_MRC();
                            }
                            else
                            {
                                ARM_MCR();
                            }
                        }
                        else
                        {
                            if (IsOpcodeBitSet(20))
                            {
                                ARM_MRRC();
                            }
                            else
                            {
                                ARM_MCRR();
                            }
                        }
                        break;
                    }
                }
            }

            if (Registers.PCChanged)
            {
                ReloadPipeline();
            }

            if (Debug)
            {
                string RVals = null;
                for (int i = 0; i < 15; i++)
                {
                    RVals += "R" + i + " = " + Registers[i].ToString("X8") + " ";
                }
                System.Diagnostics.Debug.WriteLine(Opcode.ToString("X8") + " - " + TruePC.ToString("X8") + ": " + RVals + " CPSR: " + Registers.CPSR.ToString("X8"));
            }
        }