Ejemplo n.º 1
0
        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());
        }
Ejemplo n.º 2
0
        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
            });
        }
Ejemplo n.º 3
0
        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()
            });
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        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());
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
 public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine)
 {
     assemblerState.RaiseError($"'{Symbol}' is not implemented.");
     return(new OperatorOutput());
 }
Ejemplo n.º 12
0
        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
            });
        }
Ejemplo n.º 13
0
 public override ulong DetermineByteLength(AsmLine asmLine) => 0;
Ejemplo n.º 14
0
 public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine)
 {
     return(new OperatorOutput());
 }
Ejemplo n.º 15
0
 /// <summary>
 /// Gets the length in bytes this operation will take in memory.
 /// </summary>
 public virtual ulong DetermineByteLength(AsmLine asmLine) => 4;
Ejemplo n.º 16
0
 public abstract OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine);