/// <summary> /// Method that compares this addressing mode with another. /// </summary> /// <param name="am"> /// Another addressing mode to be compared with. /// </param> /// Bool value that tells whether two addressing modes are equal or not. /// <returns></returns> public bool Equals(AddressingMode am) { return(this.name.Equals(am.name)); }
/// <summary> /// Assembles the given code. /// </summary> /// <param name="outputPath"> /// Path to output file. /// </param> /// <returns> /// Binary code of assembled program. /// </returns> public byte[] Assemble(string outputPath = "out.o") { try { if (!code.EndsWith("\n")) { code += "\r\n"; } var provider = CSharpCodeProvider.CreateProvider("c#"); var options = new CompilerParameters(); var assemblyContainingNotDynamicClass = Path.GetFileName(Assembly.GetExecutingAssembly().Location); options.ReferencedAssemblies.Add(assemblyContainingNotDynamicClass); string parserCode = File.ReadAllText("Grammar/cs/" + ((SystemComponent)cpu).Name + "Parser.cs"); string constantsCode = File.ReadAllText("Grammar/cs/" + ((SystemComponent)cpu).Name + "Constants.cs"); string tokenizerCode = File.ReadAllText("Grammar/cs/" + ((SystemComponent)cpu).Name + "Tokenizer.cs"); string analyzerCode = File.ReadAllText("Grammar/cs/" + ((SystemComponent)cpu).Name + "Analyzer.cs"); var results = provider.CompileAssemblyFromSource(options, new[] { parserCode, constantsCode, tokenizerCode, analyzerCode }); if (results.Errors.Count > 0) { foreach (var error in results.Errors) { File.AppendAllText("error.txt", error + "\n"); } return(null); } else { Parser parser = null; var t = results.CompiledAssembly.GetType("MultiArc_Compiler." + cpu.Name + "Parser", true); object instance = Activator.CreateInstance(t, new[] { new StringReader(code) }); parser = (Parser)instance; try { Node n = parser.Parse(); instructions.Clear(); labels.Clear(); symbolTable.Clear(); getInstructionsFromTree(n); getOriginFromTree(n); binaryCode = new byte[instructions.Count * cpu.Constants.MAX_BYTES]; // THIS MUST BE TESTED. count = 0; separators.Clear(); separators = new LinkedList <int>(); // First passing: for (int i = 0; i < instructions.Count; i++) { Instruction inst = cpu.Constants.GetInstruction(instructions.ElementAt(i).GetName()); if (labels.ContainsKey(instructions.ElementAt(i))) { Symbol symbol = new Symbol(labels[instructions.ElementAt(i)], 0, count, true); if (symbolTable.Contains(symbol)) { throw new Exception("Label already defined"); } else { symbolTable.AddLast(symbol); } } for (int j = inst.Mask.Length - 1; j >= 0; j--) { binaryCode[count + j] = inst.Mask[j]; } LinkedList <AddressingMode> addrModes = new LinkedList <AddressingMode>(); LinkedList <int> argumentsIndexes = new LinkedList <int>(); for (int j = 0; j < instructions.ElementAt(i).GetChildCount(); j++) { AddressingMode am = null; am = cpu.Constants.GetAddressingMode(instructions.ElementAt(i).GetChildAt(j).Name); if (!object.ReferenceEquals(am, null)) { addrModes.AddLast(am); argumentsIndexes.AddLast(j); } } for (int j = 0; j < inst.Arguments.Count; j++) { int argcodeValue = inst.Arguments.ElementAt(j).CodeValues[addrModes.ElementAt(j).Name]; int argcodeStart = inst.Arguments.ElementAt(j).CodeStarts[addrModes.ElementAt(j).Name]; int argcodeEnd = inst.Arguments.ElementAt(j).CodeEnds[addrModes.ElementAt(j).Name]; int argcodeSize = 1; for (int k = argcodeStart; k >= argcodeEnd; k--) { if (k % 8 == 0 && k != argcodeEnd) { argcodeSize++; } } int argcodeCount = argcodeStart - argcodeEnd; int byteCount = argcodeSize - 1; for (int k = argcodeStart; k >= argcodeEnd; k--) { int semiValue = (argcodeValue & (1 << argcodeCount)) << argcodeEnd % 8; binaryCode[count + inst.Size - 1 - argcodeEnd / 8 - byteCount] |= (byte)((semiValue & (1 << (argcodeEnd % 8 + argcodeCount))) >> byteCount * 8); // This might be a problem. if ((argcodeEnd + argcodeCount) % 8 == 0) { byteCount--; } argcodeCount--; } AddressingMode am = addrModes.ElementAt(j); int argumentIndex = argumentsIndexes.ElementAt(j); int operandValue = 0; bool shouldBeWritten = false; if (am.OperandInValues) { shouldBeWritten = true; string expr = ""; if (instructions.ElementAt(i).GetChildAt(argumentIndex).GetChildAt(0) is Production) { expr = ((Production)instructions.ElementAt(i).GetChildAt(argumentIndex).GetChildAt(0)).Name; } else { for (int l = 0; l < instructions.ElementAt(i).GetChildAt(argumentIndex).GetChildCount(); l++) { expr += ((Token)instructions.ElementAt(i).GetChildAt(argumentIndex).GetChildAt(l)).Image; } } if (am.Values.ContainsKey(expr.ToLower())) { operandValue = am.Values[expr.ToLower()]; } } else if (am.OperandReadFromExpression) { Node node = (instructions.ElementAt(i).GetChildAt(argumentIndex)); int childCount = node.GetChildCount(); Node child = node; int sign = 1; while (!(child.GetChildAt(0) is Token)) { child = child.GetChildAt(0); } for (int l = 0; l < node.GetChildCount() && !child.Name.Equals("DEC_NUMBER") && !child.Name.Equals("HEX_NUMBER") && !child.Name.Equals("OCT_NUMBER") && !child.Name.Equals("BIN_NUMBER") && !child.Name.Equals("IDENTIFIER"); l++) { child = node.GetChildAt(l); if (l != 0 && node.GetChildAt(l - 1).Name.Equals("SIGN")) { if (((Token)node.GetChildAt(l - 1)).Image.Equals("+")) { sign = 1; } else { sign = -1; } } } if (child.Name.Equals("DEC_NUMBER")) { operandValue = Convert.ToInt32(((Token)child).Image.ToLower()) * sign; shouldBeWritten = true; } else if (child.Name.Equals("HEX_NUMBER")) { operandValue = Convert.ToInt32(((Token)child).Image.ToLower().Substring(0, ((Token)child).Image.Length - 1), 16) * sign; shouldBeWritten = true; } else if (child.Name.Equals("OCT_NUMBER")) { operandValue = Convert.ToInt32(((Token)child).Image.ToLower().Substring(0, ((Token)child).Image.Length - 1), 8) * sign; shouldBeWritten = true; } else if (child.Name.Equals("BIN_NUMBER")) { operandValue = Convert.ToInt32(((Token)child).Image.ToLower().Substring(0, ((Token)child).Image.Length - 1), 2) * sign; shouldBeWritten = true; } else if (child.Name.Equals("IDENTIFIER")) { string label = ((Token)child).Image; operandValue = 0; foreach (Symbol s in symbolTable) { if (s.Label.ToLower().Equals(label)) { operandValue = s.Offset; break; } } } if (am.OperandType.ToLower().Equals("relative")) { operandValue = operandValue - inst.Size - count; } } else if (am.OperandValueDefinedByUser) { Node node = (instructions.ElementAt(i).GetChildAt(argumentIndex)); int childCount = node.GetChildCount(); Node child = node; bool labelNotYet = false; int sign = 1; while (!(child.GetChildAt(0) is Token)) { child = child.GetChildAt(0); } for (int l = 0; l < node.GetChildCount() && !child.Name.Equals("DEC_NUMBER") && !child.Name.Equals("HEX_NUMBER") && !child.Name.Equals("OCT_NUMBER") && !child.Name.Equals("BIN_NUMBER") && !child.Name.Equals("IDENTIFIER"); l++) { child = node.GetChildAt(l); if (l != 0 && node.GetChildAt(l - 1).Name.Equals("SIGN")) { if (((Token)node.GetChildAt(l - 1)).Image.Equals("+")) { sign = 1; } else { sign = -1; } } } if (child.Name.Equals("DEC_NUMBER")) { operandValue = Convert.ToInt32(((Token)child).Image.ToLower()) * sign; } else if (child.Name.Equals("HEX_NUMBER")) { operandValue = Convert.ToInt32(((Token)child).Image.ToLower().Substring(0, ((Token)child).Image.Length - 1), 16) * sign; } else if (child.Name.Equals("OCT_NUMBER")) { operandValue = Convert.ToInt32(((Token)child).Image.ToLower().Substring(0, ((Token)child).Image.Length - 1), 8) * sign; } else if (child.Name.Equals("BIN_NUMBER")) { operandValue = Convert.ToInt32(((Token)child).Image.ToLower().Substring(0, ((Token)child).Image.Length - 1), 2) * sign; } else if (child.Name.Equals("IDENTIFIER")) { string label = ((Token)child).Image; operandValue = 0; bool found = false; foreach (Symbol s in symbolTable) { if (s.Label.ToLower().Equals(label)) { operandValue = s.Offset; found = true; break; } } if (found == false) { labelNotYet = true; } } int relativeOperandValue = operandValue - inst.Size - count; string image = getExpression(instructions.ElementAt(i), ""); if (labelNotYet == false) { operandValue = am.GetOperandValue(image, count + inst.Size, relativeOperandValue, operandValue); shouldBeWritten = true; } } if (shouldBeWritten == true) { int operandStart = inst.Arguments.ElementAt(j).OperandStarts[am.Name]; int operandEnd = inst.Arguments.ElementAt(j).OperandEnds[am.Name]; int operandSize = 1; for (int k = operandStart; k >= operandEnd; k--) { if (k % 8 == 0 && k != operandEnd) { operandSize++; } } int operandCount = operandStart - operandEnd; byteCount = operandSize - 1; for (int k = operandStart; k >= operandEnd; k--) { int semiValue = (operandValue & (1 << operandCount)) << operandEnd % 8; binaryCode[count + inst.Size - 1 - operandEnd / 8 - byteCount] |= (byte)((semiValue & (1 << (operandEnd % 8 + operandCount))) >> byteCount * 8); // This might be a problem. if ((operandEnd + operandCount) % 8 == 0) { byteCount--; } operandCount--; } } } separators.AddLast(count); count += inst.Size; } separators.AddLast(count); count = 0; // Second passing: for (int i = 0; i < instructions.Count; i++) { Instruction inst = cpu.Constants.GetInstruction(instructions.ElementAt(i).GetName()); LinkedList <AddressingMode> addrModes = new LinkedList <AddressingMode>(); LinkedList <int> argumentsIndexes = new LinkedList <int>(); for (int j = 0; j < instructions.ElementAt(i).GetChildCount(); j++) { AddressingMode am = null; am = cpu.Constants.GetAddressingMode(instructions.ElementAt(i).GetChildAt(j).Name); if (!object.ReferenceEquals(am, null)) { addrModes.AddLast(am); argumentsIndexes.AddLast(j); } } for (int j = 0; j < inst.Arguments.Count; j++) { AddressingMode am = addrModes.ElementAt(j); int argumentIndex = argumentsIndexes.ElementAt(j); int operandValue = 0; bool shouldBeOverwriten = false; if (am.OperandReadFromExpression) { Node node = (instructions.ElementAt(i).GetChildAt(argumentIndex)); int childCount = node.GetChildCount(); Node child = node; while (!(child.GetChildAt(0) is Token)) { child = child.GetChildAt(0); } for (int l = 0; l < node.GetChildCount() && !child.Name.Equals("DEC_NUMBER") && !child.Name.Equals("HEX_NUMBER") && !child.Name.Equals("OCT_NUMBER") && !child.Name.Equals("BIN_NUMBER") && !child.Name.Equals("IDENTIFIER"); l++) { child = node.GetChildAt(l); } if (child.Name.Equals("IDENTIFIER")) { string label = ((Token)child).Image; operandValue = 0; shouldBeOverwriten = true; bool found = false; foreach (Symbol s in symbolTable) { if (s.Label.ToLower().Equals(label)) { operandValue = s.Offset; found = true; break; } } if (found == false) { operandValue = Program.Mem.FirstFreeInRAM(am.Result.Size / 8); if (operandValue == -1) { throw new Exception("Memory full"); } Symbol newSymbol = new Symbol(label, 0, operandValue, true); symbolTable.AddLast(newSymbol); Program.Mem.Allocate(operandValue, am.Result.Size / 8); } } if (am.OperandType.ToLower().Equals("relative")) { operandValue = operandValue - inst.Size - count; } } else if (am.OperandValueDefinedByUser) { Node node = (instructions.ElementAt(i).GetChildAt(argumentIndex)); int childCount = node.GetChildCount(); Node child = node; while (!(child.GetChildAt(0) is Token)) { child = child.GetChildAt(0); } for (int l = 0; l < node.GetChildCount() && !child.Name.Equals("DEC_NUMBER") && !child.Name.Equals("HEX_NUMBER") && !child.Name.Equals("OCT_NUMBER") && !child.Name.Equals("BIN_NUMBER") && !child.Name.Equals("IDENTIFIER"); l++) { child = node.GetChildAt(l); } if (child.Name.Equals("IDENTIFIER")) { string label = ((Token)child).Image; bool found = false; shouldBeOverwriten = true; foreach (Symbol s in symbolTable) { if (s.Label.ToLower().Equals(label)) { operandValue = s.Offset; found = true; break; } } if (found == false) { operandValue = Program.Mem.FirstFree(Program.Mem.AuSize); Program.Mem.Allocate(operandValue, Program.Mem.AuSize); // This must be improved. } } int relativeOperandValue = operandValue - inst.Size - count; string image = getExpression(instructions.ElementAt(i), ""); operandValue = am.GetOperandValue(image, count + inst.Size, relativeOperandValue, operandValue); } if (shouldBeOverwriten == true) { int operandStart = inst.Arguments.ElementAt(j).OperandStarts[am.Name]; int operandEnd = inst.Arguments.ElementAt(j).OperandEnds[am.Name]; int operandSize = 1; for (int k = operandStart; k >= operandEnd; k--) { if (k % 8 == 0 && k != operandEnd) { operandSize++; } } int operandCount = operandStart - operandEnd; int byteCount = operandSize - 1; for (int k = operandStart; k >= operandEnd; k--) { int semiValue = (operandValue & (1 << operandCount)) << operandEnd % 8; binaryCode[count + inst.Size - 1 - operandEnd / 8 - byteCount] |= (byte)((semiValue & (1 << (operandEnd % 8 + operandCount))) >> byteCount * 8); // This might be a problem. if ((operandEnd + operandCount) % 8 == 0) { byteCount--; } operandCount--; } } } count += inst.Size; } output.Text += DateTime.Now.ToString() + " Compile successfull.\n"; output.ScrollToCaret(); byte[] ret = new byte[count]; for (int i = 0; i < count; i++) { ret[i] = binaryCode[i]; } for (int i = 0; i < count; i += Program.Mem.AuSize) { byte[] toWrite = new byte[Program.Mem.AuSize]; for (int j = 0; j < Program.Mem.AuSize && i + j < count; j++) { toWrite[j] = ret[j + i]; } Program.Mem[(uint)(i + origin)] = toWrite; } return(ret); } catch (ParserLogException ex) { string o = "Error(s) in code existed. Compile unsuccessfull.\r\nList of errors:\r\n"; for (int j = 0; j < ex.Count; j++) { ParseException pe = ex[j]; o += (j + 1) + ": Syntax error " + '\'' + pe.ErrorMessage + '\'' + " in line " + pe.Line + " and column " + pe.Column + "\n"; } output.Text += DateTime.Now.ToString() + " " + o; output.ScrollToCaret(); return(null); } } } catch (Exception ex) { File.AppendAllText("error.txt", ex.ToString()); return(null); } }