public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine) { if (string.IsNullOrWhiteSpace(asmLine.Label)) { assemblerState.RaiseError("IS must have a label."); } else { // TODO only integer constants and register substitutions are supported // register if (TryParseRegister(asmLine.Expr, out byte registerRef)) { assemblerState.DefineVariable(asmLine.Label, new RegisterCompilerVariable(registerRef)); } // constant else if (int.TryParse(asmLine.Expr, out int constant)) { assemblerState.DefineVariable(asmLine.Label, new ByteConstantAssemblerVariable((byte)constant)); } else { assemblerState.RaiseError($"IS expression, '{asmLine.Expr}' must be a constant integer or register reference."); } } return(new OperatorOutput()); }
public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine) { if (instructions == null) { instructions = ReflectionUtilities.FindExtendingClasses <mmix.Instructions.AbstractInstruction>().ToArray(); } var instruction = instructions.SingleOrDefault(i => i.Symbol == asmLine.Op); if (instruction == null) { throw new Exception("Unknown OP code."); } var hex = new byte[] { instruction.OpCode, assemblerState.ParseExprToken(asmLine.X).FetchByte(), assemblerState.ParseExprToken(asmLine.Y).FetchByte(), assemblerState.ParseExprToken(asmLine.Z).FetchByte(), }; return(new OperatorOutput() { Output = hex }); }
public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine) { List <byte> bytes = new List <byte>(); string[] args = new[] { asmLine.X, asmLine.Y, asmLine.Z }; foreach (var arg in args) { if (TryParseConstant(arg, out byte b)) { bytes.Add(b); } else if (arg.StartsWith('"') && arg.EndsWith('"')) { bytes.AddRange(Encoding.ASCII.GetBytes(arg.Trim('"'))); } else if (string.IsNullOrEmpty(arg)) { // do nothing } else { throw new Exception($"Unable to generate byte string. Unknown argument format: '{arg}'."); } } if (!string.IsNullOrEmpty(asmLine.Label)) { assemblerState.DefineVariable(asmLine.Label, new OctaConstantAssemblerVariable(assemblerState.ProgramCounter)); } return(new OperatorOutput() { Output = bytes.ToArray() }); }
public void ExprWithQuotesAndEscapedCharsCommentTest() { var asmLine = AsmLine.Parse("String BYTE \", wor\\\"ld\",#a,0 hello world"); Assert.AreEqual("String", asmLine.Label); Assert.AreEqual("BYTE", asmLine.Op); Assert.AreEqual(", wor\\\"ld,#a,0", asmLine.Expr); Assert.AreEqual("hello world", asmLine.Comment); }
public void LocLineTest() { var asmLine = AsmLine.Parse("LOC #100"); Assert.AreEqual("", asmLine.Label); Assert.AreEqual("LOC", asmLine.Op); Assert.AreEqual("#100", asmLine.Expr); Assert.AreEqual("", asmLine.Comment); }
public void MainLineTest() { var asmLine = AsmLine.Parse("Main LDOU $255,argv,0"); Assert.AreEqual("Main", asmLine.Label); Assert.AreEqual("LDOU", asmLine.Op); Assert.AreEqual("$255,argv,0", asmLine.Expr); Assert.AreEqual("", asmLine.Comment); }
public void ExprWithQuotesAndCommentTest() { var asmLine = AsmLine.Parse("String BYTE \", world\",#a,0 hello world"); Assert.AreEqual("String", asmLine.Label); Assert.AreEqual("BYTE", asmLine.Op); Assert.AreEqual("\", world\",#a,0", asmLine.Expr); Assert.AreEqual("\", world\"", asmLine.X); Assert.AreEqual("#a", asmLine.Y); Assert.AreEqual("0", asmLine.Z); Assert.AreEqual("hello world", asmLine.Comment); }
public void MainLineWithCommentsTest() { var asmLine = AsmLine.Parse("Main LDOU $255,argv,0 this is the main entry"); Assert.AreEqual("Main", asmLine.Label); Assert.AreEqual("LDOU", asmLine.Op); Assert.AreEqual("$255,argv,0", asmLine.Expr); Assert.AreEqual("$255", asmLine.X); Assert.AreEqual("argv", asmLine.Y); Assert.AreEqual("0", asmLine.Z); Assert.AreEqual("this is the main entry", asmLine.Comment); }
public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine) { // register alias ulong location; if (TryParseConstant(asmLine.Expr, out location)) { assemblerState.ProgramCounter = location; } else { assemblerState.RaiseError("LOC expression must be a constant value."); } return(new OperatorOutput()); }
public override ulong DetermineByteLength(AsmLine asmLine) { List <byte> bytes = new List <byte>(); string[] args = new[] { asmLine.X, asmLine.Y, asmLine.Z }; foreach (var arg in asmLine.Args) { // TODO multibyte constants if (TryParseConstant(arg, out byte b)) { bytes.Add(b); } else if (arg.StartsWith('"') && arg.EndsWith('"')) { bytes.AddRange(Encoding.ASCII.GetBytes(arg.Trim('"'))); } } return((ulong)bytes.Count); }
public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine) { assemblerState.RaiseError($"'{Symbol}' is not implemented."); return(new OperatorOutput()); }
public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine) { if (asmLine.ArgCount != 2) { throw new Exception("GETA must have exactly two arguments."); } // TODO don't forget GETAB[ackwards] bool backward = false; var destinationToken = assemblerState.ParseExprToken(asmLine.X); if (destinationToken.TokenType != ExprToken.ExprTokenType.REGISTER) { throw new Exception($"GETA X argument must be a register. {destinationToken.TokenType} received."); } ushort relativePointer; var pointerToken = assemblerState.ParseExprToken(asmLine.Y); if (pointerToken.TokenType == ExprToken.ExprTokenType.VARIABLE) { var octaVar = pointerToken.AssemblerVariable as OctaConstantAssemblerVariable; if (octaVar == null) { throw new Exception($"GETA reference must be an OCTA."); } // calculate relative pointer // TODO a different instruction is emitted if pointer points backwards. Care must be taken with unsigned weirdness. // divide by 4 for tetra alignment. relativePointer = (ushort)((octaVar.Constant - assemblerState.ProgramCounter).ToULong() / 4); } else if (pointerToken.TokenType == ExprToken.ExprTokenType.CONSTANT) { relativePointer = pointerToken.Value; } else { throw new Exception("GETA RA must be an OCTA reference or a constant."); } // GETA code. byte opCode = 0xF4; if (backward) { // GETAB code. opCode = 0xF5; } var hex = new byte[] { opCode, destinationToken.Value } .Concat(relativePointer.ToBytes()) .ToArray(); return(new OperatorOutput() { Output = hex }); }
public override ulong DetermineByteLength(AsmLine asmLine) => 0;
public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine) { return(new OperatorOutput()); }
/// <summary> /// Gets the length in bytes this operation will take in memory. /// </summary> public virtual ulong DetermineByteLength(AsmLine asmLine) => 4;
public abstract OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine);