コード例 #1
0
ファイル: CompileResult.cs プロジェクト: chdft/AbaSim
        public CompileResult(TOutput output, CompileLog log)
        {
            if (log == null)
            {
                throw new ArgumentNullException("log");
            }

            Output = output;
            Log    = log;
        }
コード例 #2
0
ファイル: CompilePipeline.cs プロジェクト: chdft/AbaSim
 public TOutput GetCompilerResult(TInput initialInput, CompileLog log, bool continueOnCriticalError)
 {
     try
     {
         return(Step.Compile(initialInput, log));
     }
     catch (CompilerException e)
     {
         log.Error(string.Empty, e.GetType().ToString(), e.Message);
         return(default(TOutput));
     }
 }
コード例 #3
0
 public string Resolve(Lexing.Instruction original, CompileLog log)
 {
     if (Value == null)
     {
         if (Index >= original.Arguments.Count)
         {
             log.Error(original.SourceLine.ToString(), string.Format("Pseudo Instruction {0} is missing arguments.", original.Operation), string.Format("Operation {0} expects an argument at index {1}, however only {2} are provided.", original.Operation, Index, original.Arguments.Count));
             return(string.Empty);
         }
         return(original.Arguments[Index]);
     }
     else
     {
         return(Value);
     }
 }
コード例 #4
0
ファイル: CompilePipeline.cs プロジェクト: chdft/AbaSim
            public TOutput GetCompilerResult(TInitialInput initialInput, CompileLog log, bool continueOnCriticalError)
            {
                TInput previousOutput = Previous.GetCompilerResult(initialInput, log, continueOnCriticalError);

                if (log.ErrorOccured && !continueOnCriticalError)
                {
                    //skip this step, because a critical error occurred in a previous step
                    return(default(TOutput));
                }

                try
                {
                    return(Step.Compile(previousOutput, log));
                }
                catch (CompilerException e)
                {
                    log.Error(string.Empty, e.GetType().ToString(), e.Message);
                    return(default(TOutput));
                }
            }
コード例 #5
0
ファイル: AssemblerCompiler.cs プロジェクト: chdft/AbaSim
        private Dictionary <string, int> IndexInstructions(List <Lexing.Instruction> instructions, CompileLog log)
        {
            int instructionCounter = -1;
            var labels             = new Dictionary <string, int>();

            foreach (var instruction in instructions)
            {
                if (!string.IsNullOrWhiteSpace(instruction.Label))
                {
                    if (labels.ContainsKey(instruction.Label))
                    {
                        log.Error(instruction.SourceLine.ToString(),
                                  "Ambiguous Label",
                                  string.Format("Labels must be unique, however the label {0} was declared in line {1} and {2}.", instruction.Label, instruction.SourceLine, labels[instruction.Label]));
                    }
                    labels.Add(instruction.Label.Trim(), instructionCounter + 1);
                    if (string.IsNullOrWhiteSpace(instruction.Operation))
                    {
                        if (Dialect != Parsing.Dialects.ChDFT)
                        {
                            log.Error(instruction.SourceLine.ToString(),
                                      "Labels may only decorate Operations",
                                      "Labels may only be used on lines where an operation is declared. Consider using j 1 or nop if you need to declare a label separately.");
                        }
                        else
                        {
                            log.Information(instruction.SourceLine.ToString(),
                                            "Label without Operation",
                                            "A label was declared on a line without an operation.");
                        }
                    }
                }
                if (!string.IsNullOrWhiteSpace(instruction.Operation))
                {
                    instructionCounter++;
                }
            }
            return(labels);
        }
コード例 #6
0
ファイル: AssemblerCompiler.cs プロジェクト: chdft/AbaSim
        public byte[] Compile(IEnumerable <Lexing.Instruction> instructions, CompileLog log)
        {
            List <Lexing.Instruction> instructionsList = instructions.ToList();

            List <Word> nativeInstructions = new List <Word>();

            var labels = IndexInstructions(instructionsList, log);

            int instructionCounter = 0;

            foreach (var instruction in instructionsList)
            {
                if (!string.IsNullOrWhiteSpace(instruction.Operation))
                {
                    InstructionMapping mapping;

                    if (Mappings.TryGetValue(instruction.Operation.Trim(), out mapping))
                    {
                        Word nativeInstruction = Word.Empty;

                        nativeInstruction |= ((Word)mapping.OpCode) << 10;

                        switch (mapping.Type)
                        {
                        case AbaSim.Core.Compiler.Parsing.InstructionType.Register:
                        case AbaSim.Core.Compiler.Parsing.InstructionType.VRegister:
                            if (instruction.Arguments.Count == 3)
                            {
                                //rd
                                int rd = ParseRawRegister(instruction.Arguments[0]);
                                nativeInstruction |= ((((Word)rd) & ((Word)Bit.MaskFirstS(3))) << 7);

                                //rl
                                int rl = ParseRawRegister(instruction.Arguments[1]);
                                nativeInstruction |= ((((Word)rl) & ((Word)Bit.MaskFirstS(3))) << 4);

                                //rr
                                int rr = ParseRawRegister(instruction.Arguments[1]);
                                nativeInstruction |= ((((Word)rr) & ((Word)Bit.MaskFirstS(3))) << 1);

                                if (mapping.Type == Parsing.InstructionType.VRegister)
                                {
                                    nativeInstruction |= ((Word)Bit.S0);
                                }
                            }
                            else
                            {
                                log.Error(instruction.SourceLine.ToString(),
                                          "Illegal parameter list (wrong parameter count).",
                                          string.Format("Register instructions without fixed parameters expect exactly 3 parameters (register rd, register rl, register rr), however {0} were provided ({2}).", instruction.Arguments.Count, string.Join(",", instruction.Arguments)));

                                //throw new IllegalArgumentListException(instruction.Operation, instruction.Arguments, mapping.Type);
                            }
                            break;

                        case AbaSim.Core.Compiler.Parsing.InstructionType.Store:
                        {
                            byte constantSize = 7;
                            int  constant     = 0;
                            int  rd           = 0;
                            if (mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Fixed && mapping.DestinationRestriction == Parsing.RegisterReferenceRestriction.Fixed)
                            {
                                constant = mapping.FixedConstantValue;
                                rd       = mapping.FixedDestinationValue;
                                if (instruction.Arguments.Count != 0)
                                {
                                    log.Warning(instruction.SourceLine.ToString(),
                                                "Ignoring parameters on fixed store instruction.",
                                                "Fixed store instructions use the constant part of the binary instruction to multiplex between multiple logical instructions. They do not accept any parameters.");
                                }
                            }
                            else if (mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Fixed && mapping.DestinationRestriction != Parsing.RegisterReferenceRestriction.Fixed)
                            {
                                constant = mapping.FixedConstantValue;
                                rd       = ParseRawRegister(instruction.Arguments[0]);
                                if (instruction.Arguments.Count != 1)
                                {
                                    log.Warning(instruction.SourceLine.ToString(),
                                                "Ignoring parameters on constant-fixed store instruction.",
                                                "Constant-fixed store instructions use the constant part of the binary instruction to multiplex between multiple logical instructions. They accept exactly 1 parameter (rd).");
                                }
                            }
                            else if (mapping.ConstantRestriction != Parsing.ConstantValueRestriction.Fixed && mapping.DestinationRestriction == Parsing.RegisterReferenceRestriction.Fixed)
                            {
                                constant = ParseRawConstant(instruction.Arguments[1], instructionCounter, labels);
                                rd       = mapping.FixedDestinationValue;
                                if (instruction.Arguments.Count != 1)
                                {
                                    log.Warning(instruction.SourceLine.ToString(),
                                                "Ignoring parameters on destination-fixed store instruction.",
                                                "Destination-fixed store instructions use the rd (destination register) part of the binary instruction to multiplex between multiple logical instructions. They accept exactly 1 parameter (c).");
                                }
                            }
                            else if (instruction.Arguments.Count == 2)
                            {
                                constant = ParseRawConstant(instruction.Arguments[1], instructionCounter, labels);
                                rd       = ParseRawRegister(instruction.Arguments[0]);
                            }
                            else
                            {
                                log.Error(instruction.SourceLine.ToString(),
                                          "Illegal parameter list (wrong parameter count).",
                                          string.Format("Store instructions without fixed parameters expect exactly 2 parameters (register rd, constant c), however {0} were provided ({2}).", instruction.Arguments.Count, string.Join(",", instruction.Arguments)));
                                //throw new IllegalArgumentListException(instruction.Operation, instruction.Arguments, mapping.Type);
                            }

                            int constantMin = Bit.LowerBound(constantSize, mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Unsigned);
                            int constantMax = Bit.UpperBound(constantSize, mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Unsigned);
                            if (constant < constantMin || constant > constantMax)
                            {
                                log.Error(instruction.SourceLine.ToString(),
                                          string.Format("Constant/Label (c={0}) is out of bounds ([{1};{2}]).", constant, constantMin, constantMax),
                                          "Consider using a mov statement and adding the remainder in a register using addi/addiu.");
                            }

                            nativeInstruction |= (((Word)constant) & ((Word)Bit.MaskFirstS(7)));
                            nativeInstruction |= ((((Word)rd) & ((Word)Bit.MaskFirstS(3))) << 7);
                        }
                        break;

                        case AbaSim.Core.Compiler.Parsing.InstructionType.Immediate:
                        {
                            byte constantSize = 4;
                            int  constant     = 0;
                            int  rd           = 0;
                            int  rl           = 0;
                            if (mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Fixed && mapping.DestinationRestriction == Parsing.RegisterReferenceRestriction.Fixed)
                            {
                                constant = mapping.FixedConstantValue;
                                rd       = mapping.FixedDestinationValue;
                                rl       = 0;
                                if (instruction.Arguments.Count != 0)
                                {
                                    log.Warning(instruction.SourceLine.ToString(),
                                                "Illegal parameter list (wrong parameter count).",
                                                "Fixed immediate instructions use the constant part of the binary instruction to multiplex between multiple logical instructions. They do not accept any parameters.");
                                }
                            }
                            else if (mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Fixed && mapping.DestinationRestriction != Parsing.RegisterReferenceRestriction.Fixed)
                            {
                                if (instruction.Arguments.Count == 1)
                                {
                                    constant = mapping.FixedConstantValue;
                                    rd       = ParseRawRegister(instruction.Arguments[0]);
                                    rl       = 0;
                                }
                                else
                                {
                                    log.Warning(instruction.SourceLine.ToString(),
                                                "Illegal parameter list (wrong parameter count).",
                                                "Constant-fixed immediate instructions use the constant part of the binary instruction to multiplex between multiple logical instructions. They accept exactly 1 parameter (rd).");
                                }
                            }
                            else if (mapping.ConstantRestriction != Parsing.ConstantValueRestriction.Fixed && mapping.DestinationRestriction == Parsing.RegisterReferenceRestriction.Fixed)
                            {
                                if (instruction.Arguments.Count == 1)
                                {
                                    constant = ParseRawConstant(instruction.Arguments[0], instructionCounter, labels);
                                    rd       = mapping.FixedDestinationValue;
                                    rl       = 0;
                                }
                                else
                                {
                                    log.Error(instruction.SourceLine.ToString(),
                                              "Ignoring parameters on destination-fixed immediate instruction.",
                                              "Destination-fixed immediate instructions use the rd (destination register) part of the binary instruction to multiplex between multiple logical instructions. They accept exactly 1 parameter (c).");
                                }
                            }
                            else
                            {
                                if (instruction.Arguments.Count == 3)
                                {
                                    constant = ParseRawConstant(instruction.Arguments[2], instructionCounter, labels);
                                    rd       = ParseRawRegister(instruction.Arguments[0]);
                                    rl       = ParseRawRegister(instruction.Arguments[1]);
                                }
                                else
                                {
                                    log.Error(instruction.SourceLine.ToString(),
                                              "Illegal parameter list (wrong parameter count).",
                                              string.Format("Immediate instructions without fixed parameters expect exactly 3 parameters (register rd, register rl, constant c), however {0} were provided ({2}).", instruction.Arguments.Count, string.Join(",", instruction.Arguments)));

                                    //throw new IllegalArgumentListException(instruction.Operation, instruction.Arguments, mapping.Type);
                                }
                            }

                            //bounds validation
                            //int constantMin = (mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Unsigned ? 0 : -1 * (int)constantMask / 2);
                            //int constantMax = (mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Unsigned ? (int)constantMask : (int)constantMask / 2);
                            int constantMin = Bit.LowerBound(constantSize, mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Unsigned);
                            int constantMax = Bit.UpperBound(constantSize, mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Unsigned);
                            if (constant < constantMin || constant > constantMax)
                            {
                                log.Error(instruction.SourceLine.ToString(),
                                          string.Format("Constant/Label (c={0}) is out of bounds ([{1};{2}]).", constant, constantMin, constantMax),
                                          "Consider using a mov statement and adding the remainder in a register using addi/addiu.");
                            }

                            nativeInstruction |= (((Word)constant) & Bit.MaskFirstS(constantSize));
                            nativeInstruction |= ((((Word)rd) & ((Word)Bit.MaskFirstS(3))) << 7);
                            nativeInstruction |= ((((Word)rl) & ((Word)Bit.MaskFirstS(3))) << 4);
                        }
                        break;

                        case AbaSim.Core.Compiler.Parsing.InstructionType.Jump:
                        {
                            byte constantSize = 10;
                            int  constant     = 0;
                            if (mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Fixed)
                            {
                                if (instruction.Arguments.Count == 0)
                                {
                                    constant = mapping.FixedConstantValue;
                                }
                                else
                                {
                                    log.Warning(instruction.SourceLine.ToString(),
                                                "Ignoring parameters on constant-fixed jump instruction.",
                                                "Constant-fixed jump instructions use the constant part of the binary instruction to multiplex between multiple logical instructions. They accept exactly 1 parameter (c).");
                                }
                            }
                            else
                            {
                                if (instruction.Arguments.Count == 1)
                                {
                                    constant = ParseRawConstant(instruction.Arguments[0], instructionCounter, labels);
                                }
                                else
                                {
                                    log.Error(instruction.SourceLine.ToString(),
                                              "Illegal parameter list (wrong parameter count).",
                                              string.Format("Jump instructions without fixed parameters expect exactly 1 parameter (constant c), however {0} were provided ({2}).", instruction.Arguments.Count, string.Join(",", instruction.Arguments)));


                                    //throw new IllegalArgumentListException(instruction.Operation, instruction.Arguments, mapping.Type);
                                }
                            }

                            nativeInstruction |= (((Word)constant) & Bit.MaskFirstS(constantSize));
                            int constantMin = Bit.LowerBound(constantSize, mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Unsigned);
                            int constantMax = Bit.UpperBound(constantSize, mapping.ConstantRestriction == Parsing.ConstantValueRestriction.Unsigned);
                            if (constant < constantMin || constant > constantMax)
                            {
                                log.Error(instruction.SourceLine.ToString(),
                                          string.Format("Constant/Label (c={0}) is out of bounds ([{1};{2}]).", constant, constantMin, constantMax),
                                          "Consider using jmp with a pre-calculated (i.e. using mov and add) target instead of a constant jump (j) for long jumps.");
                            }
                        }
                        break;

                        default:
                            //should not happen
                            throw new CompilerException("Unknown Instruction Type");
                        }

                        nativeInstructions.Add(nativeInstruction);
                    }
                    else
                    {
                        //unmapped instruction
                        throw new UnmappedOperationException(instruction.Operation);
                    }

                    instructionCounter++;
                }
            }

            byte[] binary = new byte[nativeInstructions.Count * (Word.Size / 8)];
            for (int i = 0; i < nativeInstructions.Count; i++)
            {
                nativeInstructions[i].RawValue.CopyTo(binary, i * (Word.Size / 8));
            }
            return(binary);
        }
コード例 #7
0
ファイル: CompilePipeline.cs プロジェクト: chdft/AbaSim
 public TInput Compile(TInput input, CompileLog log)
 {
     Inspector(input, log);
     return(input);
 }
コード例 #8
0
ファイル: CompilePipeline.cs プロジェクト: chdft/AbaSim
 public TOutput Compile(TInput input, CompileLog log)
 {
     return(Converter(input));
 }
コード例 #9
0
        public IEnumerable <Lexing.Instruction> Compile(IEnumerable <Lexing.Instruction> input, CompileLog log)
        {
            foreach (var instruction in input)
            {
                InstructionSubstitution substitution = Substitutions.FirstOrDefault(s => instruction.Operation == s.PseudoOperation);
                if (substitution != null)
                {
                    var label = instruction.Label;
                    foreach (var replacementInstruction in substitution.Replacement)
                    {
                        List <string> arguments = new List <string>();
                        foreach (var parameterSource in replacementInstruction.ParameterSources)
                        {
                            arguments.Add(parameterSource.Resolve(instruction, log));
                        }
                        yield return(new Lexing.Instruction()
                        {
                            Operation = replacementInstruction.Operation,
                            Arguments = arguments,
                            Comment = "replaced pseudo instruction " + instruction.Operation,
                            SourceLine = instruction.SourceLine,
                            Label = label
                        });

                        //avoid setting the label on the next instruction as well
                        label = null;
                    }
                }
                else
                {
                    yield return(instruction);
                }
            }
        }