Example #1
0
        internal uint data1(uint opcode)
        {
            uint Rd  = (opcode >> 8) & 0x07;
            uint imm = opcode & 0x00ff;
            uint result;

            switch (opcode & 0x1800)
            {
            case 0x0000:
                //MOV (1)
                result = imm;
                CPSR.set_NZ(result);
                mGPR[Rd] = result;
                break;

            case 0x0800:
            {        //CMP (1)
                uint op1 = get_reg(Rd);
                result = (op1 - imm);
                CPSR.set_flags_sub(op1, imm, result, true);
            } break;

            case 0x1000:
            {        //ADD (2)
                uint op1 = get_reg(Rd);
                result = (op1 + imm);
                CPSR.set_flags_add(op1, imm, result, false);
                mGPR[Rd] = result;
            } break;

            case 0x1800:
            {        //SUB (2)
                uint op1 = get_reg(Rd);
                result = (op1 - imm);
                CPSR.set_flags_sub(op1, imm, result, true);
                mGPR[Rd] = result;
            } break;
            } //switch
            return(1);
        }     //data1
Example #2
0
        /*----------------------------------------------------------------------------*/



        //----------------------------------------------------------------------------
        internal uint normal_data_op(uint op_code, uint operation)
        {
            //extract the S bit value from the opcode
            bool SBit = ((op_code & s_mask) != 0);

            //extract destination register from opcode
            uint Rd = ((op_code & rd_mask) >> 12);

            //extract operand register and get first operand
            uint Rn = ((op_code & rn_mask) >> 16);
            uint a  = get_reg(Rn);

            bool shift_carry = false;

            uint b;

            if ((op_code & imm_mask) == 0)
            {
                b = b_reg(op_code & op2_mask, ref shift_carry);
            }
            else
            {
                b = b_immediate(op_code & op2_mask, ref shift_carry);
            }

            uint rd = 0;

            switch (operation)                                               /* R15s @@?! */
            {
            case 0x0: rd = a & b; break;                                     //AND

            case 0x1: rd = a ^ b; break;                                     //EOR

            case 0x2: rd = a - b; break;                                     //SUB

            case 0x3: rd = b - a; break;                                     //RSB

            case 0x4: rd = a + b; break;                                     //ADD

            case 0x5: rd = a + b;                                            //ADC
                if (CPSR.cf)
                {
                    ++rd;
                }
                break;

            case 0x6: rd = a - b - 1;                                                   //SBC
                if (CPSR.cf)
                {
                    ++rd;
                }
                break;

            case 0x7: rd = b - a - 1;                                                   //RSC
                if (CPSR.cf)
                {
                    ++rd;
                }
                break;

            case 0x8: rd = a & b; break;                                        //TST

            case 0x9: rd = a ^ b; break;                                        //TEQ

            case 0xa: rd = a - b; break;                                        //CMP

            case 0xb: rd = a + b; break;                                        //CMN

            case 0xc: rd = a | b; break;                                        //ORR

            case 0xd: rd = b; break;                                            //MOV

            case 0xe: rd = a & ~b; break;                                       //BIC

            case 0xf: rd = ~b; break;                                           //MVN
            }//switch

            if ((operation & 0xc) != 0x8)                                                       //Return result unless a compare
            {
                //write result into destination register
                mGPR[Rd] = rd;

                //if S bit is set and if the destination register is r15(pc) then this instruction has
                //special meaning. We are returning from a non-user mode to user-mode.
                //ie  movs pc,r14
                if (SBit && (Rd == GeneralPurposeRegisters.PCRegisterIndex))
                {
                    CPSR.RestoreCPUMode();
                    return(1);
                } //if
            }     //if

            //if S bit is not set, we do not need to set any cpu flags, so we are done here
            if (!SBit)
            {
                return(1);
            }

            switch (operation)
            {                                                           //LOGICALs
            case 0x0:                                                   //AND
            case 0x1:                                                   //EOR
            case 0x8:                                                   //TST
            case 0x9:                                                   //TEQ
            case 0xc:                                                   //ORR
            case 0xd:                                                   //MOV
            case 0xe:                                                   //BIC
            case 0xf:                                                   //MVN
                CPSR.set_NZ(rd);
                CPSR.cf = shift_carry;
                break;

            case 0x2:                                                   //SUB
            case 0xa:                                                   //CMP
                CPSR.set_flags_sub(a, b, rd, true);
                break;

            case 0x6:                                                   //SBC
                CPSR.set_flags_sub(a, b, rd, CPSR.cf);
                break;

            case 0x3:                                                   //RSB
                CPSR.set_flags_sub(b, a, rd, true);
                break;

            case 0x7:                                                   //RSC
                CPSR.set_flags_sub(b, a, rd, CPSR.cf);
                break;

            case 0x4:                                                   //ADD
            case 0xb:                                                   //CMN
                CPSR.set_flags_add(a, b, rd, false);
                break;

            case 0x5:                                                   //ADC
                CPSR.set_flags_add(a, b, rd, CPSR.cf);
                break;

            default: break;
            } //switch
            return(1);
        }     //normal_data_op
Example #3
0
        }//data0(Thumb)

        internal uint data_transfer(uint opcode)
        {
            if ((opcode & 0x1000) == 0)
            {         //NOT load/store
                if ((opcode & 0x0800) == 0)
                {     //NOT load literal pool
                    if ((opcode & 0x0400) == 0)
                    { //Data processing
                        uint Rd = (opcode & 0x07);
                        uint Rm = ((opcode >> 3) & 7);

                        uint op1 = get_reg(Rd);
                        uint op2 = get_reg(Rm);
                        uint result;

                        //data processing opcode
                        switch (opcode & 0x03c0)
                        {
                        case 0x0000:
                            //AND
                            result = op1 & op2;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                            break;

                        case 0x0040:
                            //EOR
                            result = op1 ^ op2;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                            break;

                        case 0x0080:
                        {
                            //LSL(2)
                            bool cf = CPSR.cf;
                            result  = lsl(op1, op2 & 0x00ff, ref cf);
                            CPSR.cf = cf;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                        } break;

                        case 0x00c0:
                            //LSR(2)
                        {
                            bool cf = CPSR.cf;
                            result  = lsr(op1, op2 & 0x00ff, ref cf);
                            CPSR.cf = cf;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                        } break;

                        case 0x0100:
                            //ASR (2)
                        {
                            bool cf = CPSR.cf;
                            result  = asr(op1, op2 & 0x00ff, ref cf);
                            CPSR.cf = cf;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                        } break;

                        case 0x0140:
                            //ADC
                            result = op1 + op2;
                            if (CPSR.cf)
                            {
                                result++;    //Add CF
                            }
                            CPSR.set_flags_add(op1, op2, result, CPSR.cf);
                            mGPR[Rd] = result;
                            break;

                        case 0x0180:
                            //SBC
                            result = op1 - op2 - 1;
                            if (CPSR.cf)
                            {
                                result++;    //Add CF
                            }
                            CPSR.set_flags_sub(op1, op2, result, CPSR.cf);
                            mGPR[Rd] = result;
                            break;

                        case 0x01c0:
                        {        //ROR
                            bool cf = CPSR.cf;
                            result  = ror(op1, op2 & 0x00ff, ref cf);
                            CPSR.cf = cf;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                        } break;

                        case 0x0200:
                            //TST
                            CPSR.set_NZ(op1 & op2);
                            break;

                        case 0x0240:
                            //NEG
                            result = (uint)(0 - (int)op2);
                            CPSR.set_flags_sub(0, op2, result, true);
                            mGPR[Rd] = result;
                            break;

                        case 0x0280:
                            //CMP(2)
                            CPSR.set_flags_sub(op1, op2, op1 - op2, true);
                            break;

                        case 0x02c0:
                            //CMN
                            CPSR.set_flags_add(op1, op2, op1 + op2, false);
                            break;

                        case 0x0300:
                            //ORR
                            result = op1 | op2;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                            break;

                        case 0x0340:
                            //MUL
                            result = op1 * op2;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                            break;

                        case 0x0380:
                            //BIC
                            result = op1 & ~op2;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                            break;

                        case 0x03c0:
                            //MVN
                            result = ~op2;
                            CPSR.set_NZ(result);
                            mGPR[Rd] = result;
                            break;
                        }//switch
                    }
                    else
                    {//special data processing -- NO FLAG UPDATE
                        //ADD(4),CMP(3),MOV(2),BX,BLX
                        uint Rd = ((opcode & 0x0080) >> 4) | (opcode & 0x07);
                        uint Rm = ((opcode >> 3) & 15);

                        switch (opcode & 0x0300)
                        {
                        case 0x0000:
                            //ADD (4) high registers
                            mGPR[Rd] = get_reg(Rd) + get_reg(Rm);
                            break;

                        case 0x0100:
                        {        //CMP (3) high registers
                            uint op1 = get_reg(Rd);
                            uint op2 = get_reg(Rm);
                            CPSR.set_flags_sub(op1, op2, op1 - op2, true);
                        } break;

                        case 0x0200:
                        {        //MOV (2) high registers
                            uint op2 = get_reg(Rm);
                            if (Rd == GeneralPurposeRegisters.PCRegisterIndex)
                            {
                                op2 = op2 & 0xfffffffe;        //Tweak mov to PC
                            }
                            mGPR[Rd] = op2;
                        } break;

                        case 0x0300:
                        {        //BX/BLX Rm
                            bool link = ((opcode & 0x0080) != 0);
                            old_bx((opcode >> 3) & 0x0f, link);
                        } break;
                        }//switch
                    }
                }
                else
                {//load from literal pool -- LDR PC
                    uint Rd      = ((opcode >> 8) & 0x07);
                    uint address = (((opcode & 0x00ff) << 2)) + (get_reg(GeneralPurposeRegisters.PCRegisterIndex) & 0xfffffffc);
                    mGPR[Rd] = GetMemory(address, ARMPluginInterfaces.MemorySize.Word);
                }//else
            }
            else
            {
                data_transfer_load_store(opcode);
            }
            return(1);
        }//data_transfer(Thumb)
Example #4
0
        }//thumb_branch1

        internal uint data0(uint opcode)
        {
            if ((opcode & 0x1800) != 0x1800)
            {                                        //Either LSL,LSR or ASR
                uint Rm    = ((opcode >> 3) & 0x07); //Source register
                uint Rd    = (opcode & 0x07);        //Destination register
                uint shift = ((opcode >> 6) & 0x1f); //Shift value

                uint result = 0;
                bool cf     = (this.CPSR.cf);

                switch (opcode & 0X1800)
                {
                case 0x0000:
                    //LSL(1)
                    result = lsl(get_reg(Rm), shift, ref cf);
                    break;

                case 0x0800:
                    //LSR(1)
                    //A shift value of 0 means shift by 32
                    if (shift == 0)
                    {
                        shift = 32;
                    }
                    result = lsr(get_reg(Rm), shift, ref cf);
                    break;

                case 0x1000:
                    //ASR(1)
                    //A shift value of 0 means shift by 32
                    if (shift == 0)
                    {
                        shift = 32;
                    }
                    result = asr(get_reg(Rm), shift, ref cf);
                    break;

                default:
                    //Can't get here, but just in case
                    return(1);
                }//switch
                this.CPSR.cf = cf;
                this.CPSR.set_NZ(result);
                mGPR[Rd] = result;
            }//if
            else
            {//Either ADD or SUB
                uint Rd = (opcode & 0x07);              //Destination register
                uint Rn = ((opcode >> 3) & 0x07);
                uint Rm = ((opcode >> 6) & 0x07);

                uint op2;
                if ((opcode & 0x0400) == 0)
                {//ADD(3) or SUB(3)
                    op2 = get_reg(Rm);
                }
                else
                {//ADD(1) or SUB(1)
                    op2 = Rm;
                }

                uint result;
                uint op1 = get_reg(Rn);
                if ((opcode & 0x0200) == 0)
                {
                    result = op1 + op2;
                    CPSR.set_flags_add(op1, op2, result, false);
                }
                else
                {
                    result = op1 - op2;
                    CPSR.set_flags_sub(op1, op2, result, true);
                } //else
                mGPR[Rd] = result;
            }     //else

            return(1);
        }//data0(Thumb)