public IInstructionDefinition TryFind([NotNull] InstructionFormat format) { IInstructionDefinition instruction_definition; registry.TryGetValue(format, out instruction_definition); return(instruction_definition); }
public InstructionMetadata(InstructionMnemonic instructionMnemonic, int opcode, int function, InstructionFormat format) { Instruction = instructionMnemonic; Format = format; OpCode = opcode; Function = function; }
public IInstructionDefinition Find([NotNull] InstructionFormat format) { IInstructionDefinition instruction_definition; registry.TryGetValue(format, out instruction_definition); if (instruction_definition != null) { return(instruction_definition); } else { throw new InvalidOperationException("An instruction defintion of the given format has not been registered."); } }
public static MsilInstruction GetInstruction(string Format) { foreach (MsilInstruction istn in Instructions) { string text = istn.Format; if (istn.Format.IndexOf(' ') != -1) { text = InstructionFormat.Match(istn.Format).Value; } if (string.Compare(text, Format.Replace('_', '.'), true) == 0) { return(istn); } } return(null); }
/// <summary> /// Check if an instruction_definition of the given format has been registered. /// </summary> public bool IsRegistered([NotNull] InstructionFormat format) => registry.ContainsKey(format);
private void SetInstruction(Instruction inst, InstructionFormat format, string line) { string[] split = line.Substring(format.Key.Length).Replace('(', ',').Replace(")", "").Replace('\t', ' ').Split(','); int formatIndex = 0; inst.Format = format; for (int i = 0; i < split.Length; ++i) { if (formatIndex >= format.Inputs.Length) { return; } string str = split[i].Trim(); if (format.Inputs[formatIndex][0] == 'r') { if (str == "$ra") { str = "$31"; } inst.Register.Add(Int32.Parse(str.Substring(1))); } else if (format.Inputs[formatIndex][0] == 'i') { if (Char.IsDigit(str[0]) || str[0] == '-') { bool neg = false; if (str[0] == '-') { neg = true; str = str.Substring(1); } if (str.IndexOf("0x") == 0) { string num = str.Substring(2); inst.Immediate = 0; for (int j = 0; j < num.Length; ++j) { inst.Immediate *= 16; if (Char.IsDigit(num[j]) || num[j] == '-') { inst.Immediate += num[j] - '0'; } else { inst.Immediate += num[j] - 'a' + 10; } } } else { inst.Immediate = Int32.Parse(str); } if (neg) { inst.Immediate = -inst.Immediate; } inst.ImmediateLabel = null; } else { inst.ImmediateLabel = str; } } ++formatIndex; } }
/// <summary> /// Construct directly from instruction format and mappings. /// </summary> public NativeInstructionDefinition([NotNull] InstructionFormat format, [NotNull] InstructionFieldMappingBuilder.InstructionFieldMapping mapping) { Format = format; field_mapping = mapping; }
// Constructors /////////////////////////////////////////////////////// /// <summary> /// Construct from mnemonic, operand formats, and mappings. /// </summary> public NativeInstructionDefinition([NotNull] string mnemonic, [NotNull] OperandFormat operand_format, [NotNull] InstructionFieldMappingBuilder.InstructionFieldMapping mapping) { Format = new InstructionFormat(mnemonic, operand_format); field_mapping = mapping; }
// Constructors /////////////////////////////////////////////////////// /// <summary> /// Construct from an instruction format and assembler delegate. /// </summary> /// <param name="format"> The format of this pseudo-instruction. </param> /// <param name="assembler_delegate"> /// A function that will assemble machine code based on a list of operands. /// Must not return null. /// </param> public CustomInstructionDefinition([NotNull] InstructionFormat format, [NotNull] Func <OperandList, MachineCode> assembler_delegate) { Format = format; this.assembler_delegate = assembler_delegate; }
} // End constructor. /// <summary> /// Parses the given string into an operation. /// </summary> /// <param name="tokens">An array containing a mnemonic as well as any operands the instruction may have. The mnemonic may be have a prefix: * means SIC; + means Format 4.</param> /// <param name="result">If the parse was successful, an instruction with operations uninitialized. Otherwise, null.</param> /// <returns>A Boolean value indicating whether the parse succeeded.</returns> public static bool TryParse(string[] tokens, out Instruction result) { if (tokens.Length == 0 || tokens[0].Length == 0) { result = null; return(false); } string mnemonic = tokens[0]; bool removePrefix = false; bool sic = false; InstructionFormat fmt = InstructionFormat.NotSet; switch (mnemonic[0]) { case '*': // This is a SIC instruction. // Means all flags are low. (Right?) sic = true; removePrefix = true; break; case '+': fmt = InstructionFormat.Format4; removePrefix = true; break; } if (removePrefix) { mnemonic = mnemonic.Substring(1); } if (mnemonic.Length < 1) { result = null; return(false); } Mnemonic m; if (char.IsDigit(mnemonic[0]) || !Enum.TryParse(mnemonic, true, out m)) // true to ignore case. { result = null; return(false); } var ret = new Instruction(m); //if (m == Mnemonic.CLEAR) // Debugger.Break(); if (sic) { ret.Flags = 0; } if (ret.Format == InstructionFormat.NotSet || (ret.Format == InstructionFormat.Format3Or4 && fmt == InstructionFormat.Format4)) { ret.Format = fmt; } else { if (fmt != InstructionFormat.NotSet) { // Instruction already knows its format but we planned to set it to something! Console.Error.WriteLine($"Instruction {m} must be format {(int)ret.Format} (prefix indicated format {(int)fmt})!"); result = null; return(false); } } // If format 4 has not been indicated by this point, assume 3/4 instructions are 3. if (ret.Format == InstructionFormat.Format3Or4) { ret.Format = InstructionFormat.Format3; } Debug.Assert(ret.Format != InstructionFormat.NotSet, "Instruction's format should be set by this point."); bool isIndexed = false; if (tokens.Length >= 2) { var args = tokens[1]; int commaIdx = args.IndexOf(','); if (commaIdx >= 0) { var afterComma = args.Substring(commaIdx + 1); if (ret.Format == InstructionFormat.Format2) { if (ret.Operands.Count == 2) { var splitOnComma = new string[tokens.Length + 1]; splitOnComma[0] = tokens[0]; splitOnComma[1] = args.Substring(0, commaIdx); splitOnComma[2] = args.Substring(commaIdx + 1); Array.Copy(tokens, 2, splitOnComma, 3, tokens.Length - 2); tokens = splitOnComma; } isIndexed = false; } else { if (afterComma != "x" && afterComma != "X") { Console.Error.WriteLine($"Unexpected ',' in {string.Join(" ", tokens)}"); result = null; return(false); } isIndexed = true; } } } // Copy in all the operands by parsing as many tokens as we need. // Extra tokens are usually just comments. In this method, we simply ignore them, or leave operands as null if there aren't enough. int tokenIdx; int operandCount = ret.Operands.Count; for (tokenIdx = 1; tokenIdx < tokens.Length && tokenIdx <= operandCount; ++tokenIdx) { var operand = ret.Operands[tokenIdx - 1]; var token = tokens[tokenIdx]; // Parse the operand as the type we expect. switch (operand.Type) { //case OperandType.Device: case OperandType.Address: // Acceptable formats: // Number. // Number with either @ or # prefix. // Symbol (most any string?) // Literal (=C followed by any string surrounded by ', or =X followed by any even-length hex string surrounded by '). switch (token[0]) { case '@': operand.AddressingMode = AddressingMode.Indirect; token = token.Substring(1); break; case '#': operand.AddressingMode = AddressingMode.Immediate; token = token.Substring(1); break; } // Interpret the remainder of the token as an address, if possible, or else a symbol. int addr; if (int.TryParse(token, out addr)) { if (ret.Operation == Mnemonic.SHIFTL || ret.Operation == Mnemonic.SHIFTR) { if (addr == 0) { Console.Error.WriteLine("Shift by zero is not allowed."); result = null; return(false); } // The book says to subtract one. // Osprey's sicasm does it too. operand.Value = addr - 1; } else { operand.Value = addr; } } else { // todo: check that token is valid for a symbol name and return false if it isn't. operand.SymbolName = token; } if (isIndexed) { operand.AddressingMode |= AddressingMode.Indexed; } break; case OperandType.Register: Register reg; if (Enum.TryParse(token, true, out reg)) { operand.Value = (int)reg; // Casting Register to int. } else { Console.Error.WriteLine($"Could not parse {token} as a register."); result = null; return(false); } break; } Debug.WriteLine($"Parsed {token} as {operand.Type.ToString()}."); } // for each operand. ret.Comment = string.Join(" ", tokens, tokenIdx, tokens.Length - tokenIdx); result = ret; return(true); }
public Instruction(Mnemonic mnemonic) { Operation = mnemonic; switch (mnemonic) { case Mnemonic.LDA: case Mnemonic.LDX: case Mnemonic.LDS: case Mnemonic.LDT: case Mnemonic.LDB: case Mnemonic.LDL: case Mnemonic.LDCH: case Mnemonic.STCH: case Mnemonic.STA: case Mnemonic.STX: case Mnemonic.STS: case Mnemonic.STT: case Mnemonic.STB: case Mnemonic.STL: case Mnemonic.ADD: case Mnemonic.SUB: case Mnemonic.MUL: case Mnemonic.DIV: case Mnemonic.AND: case Mnemonic.OR: case Mnemonic.COMP: case Mnemonic.J: case Mnemonic.JSUB: case Mnemonic.JLT: case Mnemonic.JGT: case Mnemonic.JEQ: case Mnemonic.TIX: case Mnemonic.TD: case Mnemonic.WD: case Mnemonic.RD: Operands = new List <Operand>() { new Operand(OperandType.Address) }.AsReadOnly(); Format = InstructionFormat.Format3Or4; break; case Mnemonic.CLEAR: case Mnemonic.TIXR: Operands = new List <Operand>() { new Operand(OperandType.Register) }.AsReadOnly(); Format = InstructionFormat.Format2; break; case Mnemonic.RMO: case Mnemonic.ADDR: case Mnemonic.SUBR: case Mnemonic.COMPR: case Mnemonic.DIVR: case Mnemonic.MULR: Operands = new List <Operand>() { new Operand(OperandType.Register), new Operand(OperandType.Register) }.AsReadOnly(); Format = InstructionFormat.Format2; break; case Mnemonic.SHIFTL: case Mnemonic.SHIFTR: // The second operand isn't really an address, but we mark it that way so that it isn't ToStringged as a register. // For example, we don't want to print "SHIFTR A,PC" instead of "SHIFTR A,8". Operands = new List <Operand>() { new Operand(OperandType.Register), new Operand(OperandType.Address) }.AsReadOnly(); Format = InstructionFormat.Format2; break; case Mnemonic.RSUB: Operands = new List <Operand>(); Format = InstructionFormat.Format3Or4; break; case Mnemonic.NOP: Operands = new List <Operand>(); Format = InstructionFormat.Format1; break; default: throw new NotSupportedException("That operation is not yet supported."); } } // End constructor.