/// <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); }
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)); } }
/// <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); }
/// <summary> /// Merge a set of status flags into this one. /// </summary> public void Merge(StatusFlags other) { mState.Merge(other.mState); }
/// <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); }