public void RecurseAssignBaseAddress(SymbolContainer container, int address) //Recursively assign a sequence base address to all symbols { foreach (KeyValuePair <String, Object> kv in container.Symbols) { Object o = kv.Value; if (o is SequenceLabel) { (o as SequenceLabel).BaseAddress = address; } if (o is SymbolContainer) { RecurseAssignBaseAddress(o as SymbolContainer, address); } } }
public static String GetLocalLabels(SymbolContainer container, int labelAddress, String parentSymbol = "") { String labels = ""; foreach (KeyValuePair <String, Object> kv in container.Symbols) { if (kv.Value is SymbolContainer) { labels += GetLocalLabels(kv.Value as SymbolContainer, labelAddress, (parentSymbol.Length > 0) ? parentSymbol + "." + kv.Key : kv.Key); } else if (kv.Value is SequenceLabel && (kv.Value as SequenceLabel).LocalAddress == labelAddress) { labels += $" ::{((parentSymbol.Length > 0) ? parentSymbol + "." : "") + kv.Key}:: |"; } } return(labels); }
public void RecurseOffset(SymbolContainer container, int startAddr, int offset) { foreach (KeyValuePair <String, Object> kv in container.Symbols) { Object o = kv.Value; if (o is SequenceLabel) { SequenceLabel ol = o as SequenceLabel; if (ol.LocalAddress > startAddr) { ol.LocalAddress += offset; } } if (o is SymbolContainer) { RecurseOffset(o as SymbolContainer, startAddr, offset); } } }
public void ExpandMicroprogram(Microprogram microprogram) //Expands all macro references and resolves constants/macro variables { Microprogram = microprogram; Sequence sequence; do { sequence = microprogram.Symbols.Where(kv => ((kv.Value is Sequence) && (kv.Value as Sequence).Unexpanded && !(kv.Value as Sequence).IsMacro && (kv.Value as Sequence).Steps.Count > 0)).Select(kv => (Sequence)kv.Value).FirstOrDefault(); //Get first unexpanded sequence if (sequence == null) { break; } int macroAddr; for (macroAddr = 0; macroAddr < sequence.Steps.Count; macroAddr++) { if (sequence.Steps[macroAddr].Type == SequenceStepType.MacroReference) { break; //Find the first macro reference within the sequence } } SequenceMacroReference mRef = sequence.Steps[macroAddr] as SequenceMacroReference; if (microprogram[mRef.Symbol] == null || !(microprogram[mRef.Symbol] is Sequence)) { throw new MicroassemblerExpansionException($"Macro {mRef.Symbol} referenced on line {mRef.Line} does not exist"); } Sequence macro = (Sequence)Microprogram[mRef.Symbol]; if (macro.Parameters.Count > mRef.Arguments.Count) { throw new MicroassemblerExpansionException($"Macro reference on line {mRef.Line} provides {mRef.Arguments.Count} arguments, while the referenced macro has {macro.Parameters.Count} parameters"); } List <SequenceStep> copiedSteps = macro.Steps.Select(s => (SequenceStep)s.Clone()).ToList(); //Find a unique expansion symbol String expansionSymbol; int symNum = 0; do { expansionSymbol = ((String.IsNullOrEmpty(mRef.ParentReference)) ? "_" : mRef.ParentReference + "._") + mRef.Symbol + "_" + symNum.ToString(); symNum++; }while (sequence[expansionSymbol] != null); //Recursively Offset all address symbols after the macro RecurseOffset(sequence, macroAddr, macro.Steps.Count - 1); //The macro call step is removed, so that is not counted as part of the offset //Create a container for symbols within the expanded macro and copy symbols from the original macro SymbolContainer expansionContainer = new SymbolContainer(); macro.Symbols.ForEach(kv => expansionContainer.Symbols.Add(kv.Key, (kv.Value is ICloneable) ? (kv.Value as ICloneable).Clone() : kv.Value)); sequence[expansionSymbol] = expansionContainer; expansionContainer.Symbols.ForEach(kv => OffsetObject(kv.Value, macroAddr)); //Replace parameter references in copied steps with arguments, also add the expanded symbol name to any internal macro symbol references foreach (SequenceStep step in copiedSteps) { if (step is SequenceMacroReference) { SequenceMacroReference stepRef = step as SequenceMacroReference; if (stepRef.Symbol.Equals(mRef.Symbol)) { throw new MicroassemblerExpansionException($"Caught recursive macro self-reference on line {stepRef.Line}"); //Sanity check } stepRef.Arguments = stepRef.Arguments.Select(a => SubArgumentsAndSymbols(a, macro, mRef, expansionSymbol)).ToList(); stepRef.ParentReference = expansionSymbol; } else if (step is SequenceAssertion) { SequenceAssertion stepAssertion = step as SequenceAssertion; stepAssertion.AssertedSignals = stepAssertion.AssertedSignals.Select(kv => new KeyValuePair <ControlWordLabel, Object>(kv.Key, SubArgumentsAndSymbols(kv.Value, macro, mRef, expansionSymbol))).ToDictionary(kv => kv.Key, kv => kv.Value); } } //Remove macro reference and insert steps sequence.Steps.RemoveAt(macroAddr); sequence.Steps.InsertRange(macroAddr, copiedSteps); }while (sequence != null); }