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)
        {
            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.º 3
0
        protected override AssemblerState CreateAssemblerState(binary_library.IBinaryFile file)
        {
            AssemblerState ret = base.CreateAssemblerState(file);

            ret.cur_bitness = binary_library.Bitness.Bits32;
            return(ret);
        }
Ejemplo n.º 4
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.º 5
0
 bool retf(List <OutputBlock> ret, AsmParser.ParseOutput op, List <AsmParser.ParseOutput> prefixes,
           List <AsmParser.ParseOutput> parameters, AssemblerState state)
 {
     ret.Add(new CodeBlock {
         Code = new byte[] { 0xcb }
     });
     return(true);
 }
Ejemplo n.º 6
0
        bool mov_r3264_creg(List <OutputBlock> ret, AsmParser.ParseOutput op, List <AsmParser.ParseOutput> prefixes,
                            List <AsmParser.ParseOutput> parameters, AssemblerState state)
        {
            Reg r  = regs[parameters[1].Name];
            Reg rm = regs[parameters[0].Name];

            AppendRex(ret, GenerateRex(false, r, rm));
            ret.Add(new CodeBlock {
                Code = new byte[] { 0x0f, 0x20 }
            });
            AppendModRM(ret, r, rm, state);
            return(true);
        }
Ejemplo n.º 7
0
        private void AssembleLabel(AsmParser.ParseOutput line_entry, AssemblerState state)
        {
            Label l = new Label {
                Name = line_entry.Name, ObjectType = binary_library.SymbolObjectType.Unknown, Type = binary_library.SymbolType.Local
            };

            if (state.sym_types.ContainsKey(line_entry.Name))
            {
                l.Type = state.sym_types[line_entry.Name];
            }
            if (state.sym_obj_types.ContainsKey(line_entry.Name))
            {
                l.ObjectType = state.sym_obj_types[line_entry.Name];
            }
            state.OutputBlocks.Add(l);
        }
Ejemplo n.º 8
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.º 9
0
        private void AssembleOperation(AsmParser.ParseOutput line_entry, AssemblerState state)
        {
            // Interpret the operation
            List <AsmParser.ParseOutput> prefixes = new List <AsmParser.ParseOutput>();

            AsmParser.ParseOutput        op         = null;
            List <AsmParser.ParseOutput> parameters = new List <AsmParser.ParseOutput>();

            foreach (AsmParser.ParseOutput p in line_entry.Children)
            {
                switch (p.Type)
                {
                case AsmParser.ParseOutput.OutputType.Operation:
                    if (op != null)
                    {
                        throw new Exception("More than one operation per line");
                    }
                    op = p;
                    break;

                case AsmParser.ParseOutput.OutputType.Prefix:
                    prefixes.Add(p);
                    break;

                case AsmParser.ParseOutput.OutputType.Parameter:
                    if (p.Children.Count > 1)
                    {
                        throw new Exception("Only one parameter child allowed");
                    }
                    parameters.Add(p.Children[0]);
                    break;

                default:
                    throw new Exception("Unsupported operation argument type: " + p.ToString());
                }
            }

            // Now get the appropriate operations
            OpcodeImplementation.OpcodeDelegate del = FindOperation(op, prefixes, parameters, state);
            if ((del == null) || (!del(state.OutputBlocks, op, prefixes, parameters, state)))
            {
                throw new Exception("Unable to assemble: " + line_entry.ToString());
            }
        }
Ejemplo n.º 10
0
        public void Assemble(AsmParser.ParseOutput input, binary_library.IBinaryFile output)
        {
            AssemblerState state = CreateAssemblerState(output);

            if (input.Type != AsmParser.ParseOutput.OutputType.Block)
            {
                throw new Exception("Expected Block");
            }

            foreach (AsmParser.ParseOutput line in input.Children)
            {
                if (line.Type != AsmParser.ParseOutput.OutputType.Line)
                {
                    throw new Exception("Expected Line");
                }

                foreach (AsmParser.ParseOutput line_entry in line.Children)
                {
                    switch (line_entry.Type)
                    {
                    case AsmParser.ParseOutput.OutputType.DirectiveCommand:
                        AssembleDirective(line_entry, state);
                        break;

                    case AsmParser.ParseOutput.OutputType.OpCommand:
                        AssembleOperation(line_entry, state);
                        break;

                    case AsmParser.ParseOutput.OutputType.Label:
                        AssembleLabel(line_entry, state);
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                }
            }
        }
Ejemplo n.º 11
0
 public abstract OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine);
Ejemplo n.º 12
0
        private void AssembleDirective(AsmParser.ParseOutput line_entry, AssemblerState state)
        {
            AsmParser.ParseOutput dir = line_entry.Children[0];

            // Interpret directives
            if ((dir.Name == "weak") || (dir.Name == "global"))
            {
                // these are of the form <weak | global> <label> [:function | :data]
                string t_name = line_entry.Children[1].Children[0].Name;
                binary_library.SymbolType       st  = binary_library.SymbolType.Undefined;
                binary_library.SymbolObjectType sot = binary_library.SymbolObjectType.Unknown;

                if (dir.Name == "weak")
                {
                    st = binary_library.SymbolType.Weak;
                }
                else if (dir.Name == "global")
                {
                    st = binary_library.SymbolType.Global;
                }

                if (line_entry.Children.Count >= 3)
                {
                    string ot_name = line_entry.Children[2].Children[0].Name;
                    if (ot_name == "function")
                    {
                        sot = binary_library.SymbolObjectType.Function;
                    }
                    else if (ot_name == "data")
                    {
                        sot = binary_library.SymbolObjectType.Object;
                    }
                }

                if (st != binary_library.SymbolType.Undefined)
                {
                    state.sym_types[t_name] = st;
                }
                if (sot != binary_library.SymbolObjectType.Unknown)
                {
                    state.sym_obj_types[t_name] = sot;
                }
            }
            else if (dir.Name == "extern")
            {
                string t_name = line_entry.Children[1].Name;
                if (!state.extern_labels.Contains(t_name))
                {
                    state.extern_labels.Add(t_name);
                }
            }
            else if (dir.Name == "bits16")
            {
                state.cur_bitness = binary_library.Bitness.Bits16;
            }
            else if (dir.Name == "bits32")
            {
                state.cur_bitness = binary_library.Bitness.Bits32;
            }
            else if (dir.Name == "bits64")
            {
                state.cur_bitness = binary_library.Bitness.Bits64;
            }
            else
            {
                throw new NotImplementedException();
            }
        }
Ejemplo n.º 13
0
        private OpcodeImplementation.OpcodeDelegate FindOperation(AsmParser.ParseOutput op, List <AsmParser.ParseOutput> prefixes, List <AsmParser.ParseOutput> parameters, AssemblerState state)
        {
            if (!opcodes.ContainsKey(op.Name))
            {
                return(null);
            }
            List <OpcodeImplementation> ops = opcodes[op.Name];

            if (ops == null)
            {
                return(null);
            }
            foreach (OpcodeImplementation oi in ops)
            {
                // Match prefixes
                bool allowed = true;
                foreach (AsmParser.ParseOutput prefix in prefixes)
                {
                    if (!oi.AllowedPrefixes.Contains(prefix.Name.ToLower()))
                    {
                        allowed = false;
                        break;
                    }
                }
                if (!allowed)
                {
                    continue;
                }

                // Match parameters
                if (parameters.Count != oi.ParamConstraints.Count)
                {
                    continue;
                }

                for (int i = 0; i < parameters.Count; i++)
                {
                    Location l = ParseLocation(parameters[i]);
                    if (!MatchConstraint(oi.ParamConstraints[i], l))
                    {
                        allowed = false;
                        break;
                    }
                }
                if (!allowed)
                {
                    continue;
                }

                return(oi.emitter);
            }
            return(null);
        }
Ejemplo n.º 14
0
 public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine)
 {
     assemblerState.RaiseError($"'{Symbol}' is not implemented.");
     return(new OperatorOutput());
 }
Ejemplo n.º 15
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.º 16
0
 bool mov_creg_r3264(List <OutputBlock> ret, AsmParser.ParseOutput op, List <AsmParser.ParseOutput> prefixes,
                     List <AsmParser.ParseOutput> parameters, AssemblerState state)
 {
     return(true);
 }
Ejemplo n.º 17
0
        void AppendModRM(List <OutputBlock> ret, byte r, byte rm, byte mod, long disp, AssemblerState state)
        {
            bool need_sib      = false;
            bool need_disp32   = false;
            bool need_disp8    = false;
            bool absolute_disp = false;
            bool is_ptr        = true;

            // Decide on addressing mode
            switch (state.cur_bitness)
            {
            case binary_library.Bitness.Bits32:
            case binary_library.Bitness.Bits64:
                // OK
                break;

            case binary_library.Bitness.Bits16:
                // Not done yet
                throw new NotImplementedException();

            default:
                throw new NotSupportedException();
            }

            if (mod == 3)
            {
                is_ptr = false;
            }
            if ((rm == regs["rsp"].id) && (mod != 3))
            {
                need_sib = true;
            }
            if ((rm == regs["rbp"].id) && (mod == 0))
            {
                absolute_disp = true;
                need_disp32   = true;
            }

            if (disp != 0)
            {
                if ((disp > Int32.MaxValue) || (disp < Int32.MinValue))
                {
                    throw new NotSupportedException();
                }
                else if ((disp > SByte.MaxValue) || (disp < SByte.MinValue))
                {
                    need_disp32 = true;
                }
                else
                {
                    need_disp8 = true;
                }
            }

            if (absolute_disp)
            {
                mod = 0;
            }
            else if (need_disp32)
            {
                mod = 2;
            }
            else if (need_disp8)
            {
                mod = 1;
            }
            else if (is_ptr)
            {
                mod = 0;
            }
            else
            {
                mod = 3;
            }

            // Encode the ModRM byte
            byte modrm = (byte)((byte)(rm & 0x7) | (byte)((r & 0x7) << 3) | (byte)((mod & 0x3) << 6));

            ret.Add(new CodeBlock {
                Code = new byte[] { modrm }
            });

            // Encode the SIB
            if (need_sib)
            {
                throw new NotImplementedException();
            }

            // Encode the displacement
            if (need_disp32 | need_disp8)
            {
                byte[] val = BitConverter.GetBytes(disp);

                if (need_disp32)
                {
                    ret.Add(new CodeBlock {
                        Code = new byte[] { val[0], val[1], val[2], val[3] }
                    });
                }
                else
                {
                    ret.Add(new CodeBlock {
                        Code = new byte[] { val[0] }
                    });
                }
            }
        }
Ejemplo n.º 18
0
 void AppendModRM(List <OutputBlock> ret, Reg r, Reg rm, AssemblerState state)
 {
     AppendModRM(ret, (byte)r.id, (byte)rm.id, 3, 0, state);
 }
Ejemplo n.º 19
0
 public override OperatorOutput GenerateBinary(AssemblerState assemblerState, AsmLine asmLine)
 {
     return(new OperatorOutput());
 }