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
            });
        }
Beispiel #2
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
            });
        }