Exemplo n.º 1
0
        //64bit multiply instructions (SMULL/UMULL/SMLAL/UMLAL)
        internal uint ExecuteDataOpMultiplyLong(DataOpMultiplyLongRaw opHandler, uint opcode, bool setflags)
        {
            //See comment in ExecuteDataOpMultiply
            uint Rm   = (opcode) & 0xf;
            uint Rs   = (opcode >> 8) & 0xf;
            uint RdHi = (opcode >> 16) & 0xf;
            uint RdLo = (opcode >> 12) & 0xf;

            uint   rs_value     = get_reg(Rs);
            uint   rm_value     = get_reg(Rm);
            UInt64 rdhilo_value = (((UInt64)get_reg(RdHi)) << 32) | (UInt64)get_reg(RdLo);
            //The number of cycles taken for multiplication varies depending
            //on the magnitude of rs_value.
            uint M = calculateMultM(rs_value);


            LongMultiplyOpResult result = opHandler(rdhilo_value, rs_value, rm_value);

            mGPR[RdHi] = (UInt32)((result.output_value >> 32) & 0xffffffff);
            mGPR[RdLo] = (UInt32)((result.output_value) & 0xffffffff);
            //If we set the flags after a long multiply, the N flag is based on bit 63, not bit 31.
            if (setflags)
            {
                CPSR.set_NZCV((result.output_value & 0x8000000000000000) != 0, result.output_value == 0, CPSR.cf, CPSR.vf);
            }

            return(result.cycles + M);
        }
Exemplo n.º 2
0
        }        //calculateMultM

        //32bit multiply instructions (MUL/MLA)
        internal uint ExecuteDataOpMultiply(DataOpMultiplyRaw opHandler, uint opcode, bool setflags)
        {
            //The original code used the masks rd_mask, rn_mask, rm_mask and rs_mask here
            //But the operands are in a strange order so the masks were used in a confusing way.
            //Therefore, we have one of the rare cases where it's better to use magic numbers...
            uint Rm = (opcode) & 0xf;
            uint Rs = (opcode >> 8) & 0xf;
            uint Rd = (opcode >> 16) & 0xf;
            uint Rn = (opcode >> 12) & 0xf;

            uint rs_value = get_reg(Rs);
            uint rm_value = get_reg(Rm);
            uint rn_value = get_reg(Rn);
            //The number of cycles taken for multiplication varies depending
            //on the magnitude of rs_value.
            uint M = calculateMultM(rs_value);

            MultiplyOpResult result = opHandler(rn_value, rs_value, rm_value);

            mGPR[Rd] = result.output_value;

            if (setflags)
            {
                CPSR.set_NZCV((result.output_value & 0x80000000) != 0, result.output_value == 0, CPSR.cf, CPSR.vf);
            }

            return(M + result.cycles);
        }
Exemplo n.º 3
0
 internal void DataOpHandleSetFlagsAWC_CMP(uint opcode, uint Rd, AWCResult awcResult)
 {
     //The CPSR is set the same way for all AWC-based instructions (the only difference
     //is the input to AWC).
     CPSR.set_NZCV((awcResult.result & 0x80000000) != 0, awcResult.result == 0, awcResult.carry_out, awcResult.overflow);
 }
Exemplo n.º 4
0
 internal void DataOpHandleSetFlagsLogical_CMP(uint opcode, uint Rd, uint result, bool shift_carry)
 {
     //The CPSR is always set the same way for logical operations
     //cf. MOV (ARMv7 A8.8.102)
     CPSR.set_NZCV((result & 0x80000000) != 0, result == 0, shift_carry, CPSR.vf);
 }