예제 #1
0
        /// <summary>
        /// Set the value from an integer.  Used for serialization.
        /// </summary>
        public static StatusFlags FromInt(int value)
        {
            if ((value & ~0x01ff01ff) != 0)
            {
                throw new InvalidOperationException("Bad StatusFlags value " +
                                                    value.ToString("x8"));
            }
            StatusFlags newFlags = new StatusFlags();

            newFlags.mState.AsInt = value;
            return(newFlags);
        }
예제 #2
0
        private void UpdateControls()
        {
            CpuItem item = (CpuItem)cpuSelectionComboBox.SelectedItem;

            if (item == null)
            {
                // initializing
                return;
            }

            // Push current choice to settings.
            AppSettings.Global.SetEnum(AppSettings.INSTCH_MODE, typeof(CpuDef.CpuType),
                                       (int)item.Type);
            AppSettings.Global.SetBool(AppSettings.INSTCH_SHOW_UNDOC, mShowUndocumented);

            // Populate the items source.
            InstructionItems.Clear();
            CpuDef cpuDef = CpuDef.GetBestMatch(item.Type, true, false);

            for (int opc = 0; opc < 256; opc++)
            {
                OpDef op = cpuDef[opc];
                if (!mShowUndocumented && op.IsUndocumented)
                {
                    continue;
                }

                int    opLen       = op.GetLength(StatusFlags.AllIndeterminate);
                string sampleValue = "$12";
                if (op.AddrMode == OpDef.AddressMode.BlockMove)
                {
                    sampleValue = "#$12,#$34";
                }
                else if (opLen == 3)
                {
                    sampleValue = "$1234";
                }
                else if (opLen == 4)
                {
                    sampleValue = "$123456";
                }
                string instrSample = mFormatter.FormatMnemonic(op.Mnemonic,
                                                               OpDef.WidthDisambiguation.None) + " " +
                                     mFormatter.FormatOperand(op, sampleValue, OpDef.WidthDisambiguation.None);


                StringBuilder     flags         = new StringBuilder(8);
                const string      FLAGS         = "NVMXDIZC";
                Asm65.StatusFlags affectedFlags = op.FlagsAffected;
                for (int fl = 0; fl < 8; fl++)
                {
                    if (affectedFlags.GetBit((StatusFlags.FlagBits)(7 - fl)) >= 0)
                    {
                        flags.Append(FLAGS[fl]);
                    }
                    else
                    {
                        flags.Append("-");
                    }
                }

                string         cycles = op.Cycles.ToString();
                OpDef.CycleMod mods   = cpuDef.GetOpCycleMod(opc);
                if (mods != 0)
                {
                    cycles += '+';
                }

                InstructionItems.Add(new InstructionItem(mFormatter.FormatHexValue(opc, 2),
                                                         instrSample, flags.ToString(), cycles,
                                                         mOpDesc.GetShortDescription(op.Mnemonic),
                                                         mOpDesc.GetAddressModeDescription(op.AddrMode),
                                                         op.IsUndocumented));
            }
        }
예제 #3
0
 /// <summary>
 /// Applies flags, overwriting existing values.  This will set one or more flags
 /// to 0, 1, or indeterminate.  Unspecified (0/0) values have no effect.
 ///
 /// This is useful when merging "overrides" in.
 /// </summary>
 public void Apply(StatusFlags overrides)
 {
     mState.Apply(overrides.mState);
 }
예제 #4
0
 /// <summary>
 /// Merge a set of status flags into this one.
 /// </summary>
 public void Merge(StatusFlags other)
 {
     mState.Merge(other.mState);
 }
예제 #5
0
        /// <summary>
        /// Returns the number of cycles required to execute the instruction.  If the value
        /// is negative, the negated value represents the minimum number of cycles for an
        /// instruction with variable timing.
        ///
        /// The value returned will factor in any CPU-specific aspects.
        /// </summary>
        /// <param name="opNum">Instruction opcode value.</param>
        /// <returns>Cycle count.</returns>
        public int GetCycles(int opNum, StatusFlags flags, OpDef.BranchTaken branchTaken,
                             bool branchCrossesPage)
        {
            // The irrelevant modifiers have already been stripped out.
            OpDef.CycleMod mods   = mCycleMods[opNum];
            int            cycles = mCycleCounts[opNum];

            // Walk through the various cycle mods.  If we can evaluate them definitively,
            // do so now and remove them from the set.

            // The M/X flags are defined to be in one state or the other, even when the flag
            // value is indeterminate, because we have to be able to size immediate operands
            // appropriately.  So there's no ambiguity here even when there's ambiguity.  We
            // make a similar statement about the E flag.
            if ((mods & OpDef.CycleMod.OneIfM0) != 0)
            {
                if (!flags.ShortM)
                {
                    cycles++;
                }
                mods &= ~OpDef.CycleMod.OneIfM0;
            }
            if ((mods & OpDef.CycleMod.TwoIfM0) != 0)
            {
                if (!flags.ShortM)
                {
                    cycles += 2;
                }
                mods &= ~OpDef.CycleMod.TwoIfM0;
            }
            if ((mods & OpDef.CycleMod.OneIfX0) != 0)
            {
                if (!flags.ShortX)
                {
                    cycles++;
                }
                mods &= ~OpDef.CycleMod.OneIfX0;
            }
            if ((mods & OpDef.CycleMod.OneIfE0) != 0)
            {
                if (flags.E == 0)
                {
                    cycles++;
                }
                mods &= ~OpDef.CycleMod.OneIfE0;
            }

            // Some of these can be known, some can't.
            if ((mods & OpDef.CycleMod.OneIfD1) != 0)
            {
                if (flags.D == 1)
                {
                    cycles++;
                }
                if (flags.D == 0 || flags.D == 1)
                {
                    mods &= ~OpDef.CycleMod.OneIfD1;
                }
            }
            if ((mods & OpDef.CycleMod.OneIfBranchTaken) != 0)
            {
                if (branchTaken == OpDef.BranchTaken.Always)
                {
                    cycles++;
                }
                if (branchTaken != OpDef.BranchTaken.Indeterminate)
                {
                    mods &= ~OpDef.CycleMod.OneIfBranchTaken;
                }
            }
            if ((mods & OpDef.CycleMod.OneIfBranchPage) != 0)
            {
                if (branchCrossesPage && flags.E != 0)
                {
                    cycles++;   // +1 unless we're in native mode on 65816
                }
                mods &= ~OpDef.CycleMod.OneIfBranchPage;
            }

            // We can't evaluate OneIfDpNonzero, OneIfIndexPage, or MinusOneIfNoPage.
            // OneIf65C02 was handled earlier.
            // TODO(maybe): in some cases we can know that the index doesn't cross a
            //   page boundary by checking the address, e.g. "LDA $2000,X" can't cross.

            if (mods != 0)
            {
                // Some unresolved mods remain.
                cycles = -cycles;
            }
            return(cycles);
        }