Пример #1
0
        private ParsedOperand ParsePtrOperand(PrimitiveType width)
        {
            Expect(Token.PTR);
            ParsedOperand op = ParseOperand();

            op.Operand.Width = width;
            return(op);
        }
Пример #2
0
        public ParsedOperand [] ParseOperandList(int min, int max)
        {
            OperandParser        opp = asm.CreateOperandParser(lexer);
            List <ParsedOperand> ops = new List <ParsedOperand>();

            asm.SegmentOverride = RegisterStorage.None;
            asm.AddressWidth    = asm.SegmentAddressWidth;
            if (lexer.PeekToken() != Token.EOL)
            {
                ops.Add(opp.ParseOperand());
                if (opp.SegmentOverride != RegisterStorage.None)
                {
                    asm.SegmentOverride = opp.SegmentOverride;
                }
                if (opp.AddressWidth != null)
                {
                    asm.AddressWidth = opp.AddressWidth;
                }

                while (lexer.PeekToken() == Token.COMMA)
                {
                    lexer.DiscardToken();
                    opp.DataWidth = ops[0].Operand.Width;
                    ops.Add(opp.ParseOperand());
                    if (opp.SegmentOverride != RegisterStorage.None)
                    {
                        if (asm.SegmentOverride != RegisterStorage.None)
                        {
                            Error("Can't have two segment overrides in one instruction");
                        }
                        asm.SegmentOverride = opp.SegmentOverride;
                    }
                    if (opp.AddressWidth != null)
                    {
                        asm.AddressWidth = opp.AddressWidth;
                    }
                }
            }

            if (min <= ops.Count && ops.Count <= max)
            {
                ParsedOperand [] o = new ParsedOperand[ops.Count];
                ops.CopyTo(o);
                return(o);
            }
            else
            {
                if (min == max)
                {
                    Error(string.Format("Instruction expects {0} operand(s).", min));
                }
                else
                {
                    Error(string.Format("Instruction expects between {0} and {1} operand(s).", min, max));
                }
                return(null);
            }
        }
Пример #3
0
 internal void ProcessBitScan(byte opCode, ParsedOperand dst, ParsedOperand src)
 {
     PrimitiveType dataWidth = EnsureValidOperandSize(src);
     RegisterOperand regDst = dst.Operand as RegisterOperand;
     if (regDst == null)
         Error("First operand of bit scan instruction must be a register");
     EmitOpcode(0x0F, dataWidth);
     emitter.EmitByte(opCode);
     EmitModRM(RegisterEncoding(regDst.Register), src);
 }
Пример #4
0
 internal void EmitModRM(int reg, ParsedOperand op)
 {
     RegisterOperand regOp = op.Operand as RegisterOperand;
     if (regOp != null)
     {
         modRm.EmitModRM(reg, regOp);
         return;
     }
     FpuOperand fpuOp = op.Operand as FpuOperand;
     if (fpuOp != null)
     {
         modRm.EmitModRM(reg, fpuOp);
     }
     else
     {
         EmitModRM(reg, (MemoryOperand) op.Operand, op.Symbol);
     }
 }
Пример #5
0
 private PrimitiveType EnsureValidOperandSizes(ParsedOperand[] ops, int count)
 {
     if (count == 0)
         return null;
     PrimitiveType w = ops[0].Operand.Width;
     if (count == 1 && ops[0].Operand.Width == null)
         Error("Width of the first operand is unknown");
     if (count == 2)
     {
         if (w == null)
         {
             w = ops[1].Operand.Width;
             if (w == null)
                 Error("Width of the first operand is unknown");
             else
                 ops[0].Operand.Width = w;
         }
         else
         {
             if (ops[1].Operand.Width == null)
                 ops[1].Operand.Width = w;
             else if (ops[0].Operand.Width != ops[0].Operand.Width)
                 Error("Operand widths don't match");
         }
     }
     return w;
 }
Пример #6
0
        internal void ProcessPushPop(bool fPop, ParsedOperand op)
        {
            int imm;
            ImmediateOperand immOp = op.Operand as ImmediateOperand;
            if (immOp != null)
            {
                if (fPop)
                    throw new ApplicationException("Can't pop an immediate value");
                imm = immOp.Value.ToInt32();
                if (IsSignedByte(imm))
                {
                    EmitOpcode(0x6A, PrimitiveType.Byte);
                    emitter.EmitByte(imm);
                }
                else
                {
                    EmitOpcode(0x68, SegmentDataWidth);
                    emitter.EmitLe(SegmentDataWidth, imm);
                }
                return;
            }

            PrimitiveType dataWidth = EnsureValidOperandSize(op);
            RegisterOperand regOp = op.Operand as RegisterOperand;
            if (regOp != null)
            {
                var rrr = regOp.Register;
                if (IsBaseRegister(rrr))
                {
                    EmitOpcode(0x50 | (fPop ? 8 : 0) | RegisterEncoding(regOp.Register), dataWidth);
                }
                else
                {
                    int mask = (fPop ? 1 : 0);
                    if (regOp.Register == Registers.es) emitter.EmitByte(0x06 | mask);
                    else
                        if (regOp.Register == Registers.cs) emitter.EmitByte(0x0E | mask);
                        else
                            if (regOp.Register == Registers.ss) emitter.EmitByte(0x16 | mask);
                            else
                                if (regOp.Register == Registers.ds) emitter.EmitByte(0x1E | mask);
                                else
                                    if (regOp.Register == Registers.fs) { emitter.EmitByte(0x0F); emitter.EmitByte(0xA0 | mask); }
                                    else
                                        if (regOp.Register == Registers.gs) { emitter.EmitByte(0x0F); emitter.EmitByte(0xA8 | mask); }
                }
                return;
            }

            EmitOpcode(fPop ? 0x8F : 0xFF, dataWidth);
            EmitModRM(fPop ? 0 : 6, op);
        }
Пример #7
0
        internal void ProcessShiftRotation(byte bits, ParsedOperand dst, ParsedOperand count)
        {
            PrimitiveType dataWidth = EnsureValidOperandSize(dst);

            ImmediateOperand immOp = count.Operand as ImmediateOperand;
            if (immOp != null)
            {
                int imm = immOp.Value.ToInt32();
                if (imm == 1)
                {
                    EmitOpcode(0xD0 | IsWordWidth(dataWidth), dataWidth);
                    EmitModRM(bits, dst);
                }
                else
                {
                    EmitOpcode(0xC0 | IsWordWidth(dataWidth), dataWidth);
                    EmitModRM(bits, dst, (byte) immOp.Value.ToInt32());
                }
                return;
            }

            RegisterOperand regOp = count.Operand as RegisterOperand;
            if (regOp != null && regOp.Register == Registers.cl)
            {
                EmitOpcode(0xD2 | IsWordWidth(dataWidth), dataWidth);
                EmitModRM(bits, dst);
                return;
            }

            throw new ApplicationException("Shift/rotate instructions must be followed by a constant or CL");
        }
Пример #8
0
        internal void ProcessIncDec(bool fDec, ParsedOperand op)
        {
            PrimitiveType dataWidth = EnsureValidOperandSize(op);
            RegisterOperand regOp = op.Operand as RegisterOperand;
            if (regOp != null)
            {
                if (IsWordWidth(dataWidth) != 0)
                {
                    EmitOpcode((fDec ? 0x48 : 0x40) | RegisterEncoding(regOp.Register), dataWidth);
                }
                else
                {
                    EmitOpcode(0xFE | IsWordWidth(dataWidth), dataWidth);
                    EmitModRM(fDec ? 1 : 0, op);
                }
                return;
            }

            MemoryOperand memOp = op.Operand as MemoryOperand;
            if (memOp != null)
            {
                EmitOpcode(0xFE | IsWordWidth(dataWidth), dataWidth);
                EmitModRM(fDec ? 1 : 0, op);
            }
            else
            {
                throw new ApplicationException("constant operator illegal");
            }
        }
Пример #9
0
 internal void ProcessMovx(int opcode, ParsedOperand[] ops)
 {
     PrimitiveType dataWidth = EnsureValidOperandSize(ops[1]);
     RegisterOperand regDst = ops[0].Operand as RegisterOperand;
     if (regDst == null)
         Error("First operand must be a register");
     EmitOpcode(0x0F, regDst.Width);
     emitter.EmitByte(opcode | IsWordWidth(dataWidth));
     EmitModRM(RegisterEncoding(regDst.Register), ops[1]);
 }
Пример #10
0
 public void Cmp(ParsedOperand src, int dst)
 {
     ProcessBinop(0x7, src, Imm(dst));
 }
Пример #11
0
 public void Sub(ParsedOperand op, int constant)
 {
     Sub(op, Imm(op.Operand.Width, constant));
 }
Пример #12
0
 public void Shrd(ParsedOperand op1, ParsedOperand op2, byte count)
 {
     ProcessDoubleShift(8, op1, op2, new ParsedOperand(ImmediateOperand.Byte(count)));
 }
Пример #13
0
 public void Bsr(ParsedOperand dst, ParsedOperand src)
 {
     ProcessBitScan(0xBD, dst, src);
 }
Пример #14
0
 public void Shld(ParsedOperand op1, ParsedOperand op2, ParsedOperand op3)
 {
     ProcessDoubleShift(0, op1, op2, op3);
 }
Пример #15
0
        internal void ProcessDoubleShift(byte bits, ParsedOperand op0, ParsedOperand op1, ParsedOperand count)
        {
            PrimitiveType dataWidth = EnsureValidOperandSize(op0);

            RegisterOperand regSrc = op1.Operand as RegisterOperand;
            if (regSrc == null)
                Error("Second operand of SHLD/SHRD must be a register");

            ImmediateOperand immShift = count.Operand as ImmediateOperand;
            RegisterOperand regShift = count.Operand as RegisterOperand;
            if (regShift != null && regShift.Register == Registers.cl)
            {
                bits |= 0x01;
            }
            else if (immShift == null)
            {
                Error("SHLD/SHRD instruction must be followed by a constant or CL");
            }

            EmitOpcode(0x0F, dataWidth);
            emitter.EmitByte(0xA4 | bits);
            EmitModRM(RegisterEncoding(regSrc.Register), op0);
            if (immShift != null)
                emitter.EmitByte((byte) immShift.Value.ToUInt32());
        }
Пример #16
0
 internal void ProcessCallJmp(bool far, int indirect, ParsedOperand op)
 {
     if (far) indirect |= 1;
     EmitOpcode(0xFF, SegmentDataWidth);
     EmitModRM(indirect, op);
 }
Пример #17
0
        internal void ProcessFpuCommon(int opcodeFreg, int opcodeMem, int fpuOperation, bool isPop, bool fixedOrder, params ParsedOperand[] ops)
        {
            if (ops.Length == 0)
            {
                ops = new ParsedOperand[] { new ParsedOperand(new FpuOperand(0)), new ParsedOperand(new FpuOperand(1)) };
            }
            else if (ops.Length == 1 && ops[0].Operand is FpuOperand)
            {
                ops = new ParsedOperand[] { new ParsedOperand(new FpuOperand(0)), ops[0] };
            }

            FpuOperand fop1 = ops[0].Operand as FpuOperand;
            FpuOperand fop2 = ops.Length > 1 ? ops[1].Operand as FpuOperand : null;
            MemoryOperand mop = ops[0].Operand as MemoryOperand;
            if (mop == null && ops.Length > 1)
                mop = ops[1].Operand as MemoryOperand;
            if (mop != null)
            {
                EmitOpcode(opcodeMem | (mop.Width == PrimitiveType.Word64 ? 4 : 0), null);
                EmitModRM(fpuOperation, mop, null);
                return;
            }
            if (isPop)
            {
                if (fop1 == null)
                    Error("First operand must be of type ST(n)");
                EmitOpcode(opcodeFreg, null);
                if (fixedOrder)
                    fpuOperation ^= 1;
                if (fop1.StNumber == 0)
                    EmitModRM(fpuOperation, new ParsedOperand(fop2, null));
                else
                    EmitModRM(fpuOperation, new ParsedOperand(fop1, null));
                return;
            }
            if (fop1 != null)
            {
                fop2 = (FpuOperand) ops[1].Operand;
                if (fop1.StNumber != 0)
                {
                    if (fop2.StNumber != 0)
                        Error("at least one of the floating point stack arguments must be ST(0)");
                    if (fixedOrder)
                        fpuOperation ^= 1;
                    fop2 = fop1;
                }
                EmitOpcode(opcodeFreg, null);
                EmitModRM(fpuOperation, new ParsedOperand(fop2, null));
                return;
            }
            throw new NotImplementedException("NYI");
        }
Пример #18
0
 public void Les(ParsedOperand dst, ParsedOperand src)
 {
     ProcessLxs(-1, 0xC4, dst, src);
 }
Пример #19
0
 internal void ProcessFst(bool pop, ParsedOperand operand)
 {
     FpuOperand fop = operand.Operand as FpuOperand;
     MemoryOperand mop = operand.Operand as MemoryOperand;
     int regBits = pop ? 3 : 2;
     if (mop != null)
     {
         switch (mop.Width.Size)
         {
         case 4: EmitOpcode(0xD9, null); break;
         case 8: EmitOpcode(0xDD, null); break;
         default: Error("Unexpected operator width"); break;
         }
         EmitModRM(regBits, operand);
     }
     else if (fop != null)
     {
         EmitOpcode(0xDD, null);
         EmitModRM(regBits, new ParsedOperand(fop, null));
     }
     else
         Error("Unexpected operator type");
 }
Пример #20
0
 public void Sub(ParsedOperand minuend, ParsedOperand subtrahend)
 {
     ProcessBinop(0x05, minuend, subtrahend);
 }
Пример #21
0
 internal void ProcessInt(ParsedOperand vector)
 {
     ImmediateOperand op = (ImmediateOperand) vector.Operand;
     EmitOpcode(0xCD, null);
     emitter.EmitByte(op.Value.ToInt32());
 }
Пример #22
0
 public void Test(ParsedOperand op1, ParsedOperand op2)
 {
     ProcessTest( op1, op2 );
 }
Пример #23
0
        public void Mul(ParsedOperand op)
        {
            PrimitiveType dataWidth = EnsureValidOperandSize(op);
            // Single operand doesn't accept immediate values.
            if (op.Operand is ImmediateOperand)
                Error("Immediate operand not allowed for single-argument multiplication");

            EmitOpcode(0xF6 | IsWordWidth(dataWidth), dataWidth);
            EmitModRM(4, op);
        }
Пример #24
0
 internal void Xchg(ParsedOperand[] ops)
 {
     PrimitiveType dataWidth = EnsureValidOperandSizes(ops, 2);
     RegisterOperand regOp = ops[0].Operand as RegisterOperand;
     ParsedOperand otherOp = ops[1];
     if (regOp == null)
     {
         regOp = ops[1].Operand as RegisterOperand;
         if (regOp == null)
         {
             Error("One operand must be a register.");
         }
         otherOp = ops[0];
     }
     EmitOpcode(0x86 | IsWordWidth(regOp), dataWidth);
     EmitModRM(RegisterEncoding(regOp.Register), otherOp);
 }
Пример #25
0
 internal void ProcessSetCc(byte bits, ParsedOperand op)
 {
     PrimitiveType dataWidth = EnsureValidOperandSize(op);
     if (dataWidth != PrimitiveType.Byte)
         Error("Instruction takes only a byte operand");
     EmitOpcode(0x0F, dataWidth);
     emitter.EmitByte(0x90 | (bits & 0xF));
     EmitModRM(0, op);
 }
Пример #26
0
 public void Xor(ParsedOperand dst, ParsedOperand src)
 {
     ProcessBinop(0x06, dst, src);
 }
Пример #27
0
 internal void ProcessUnary(int operation, ParsedOperand op)
 {
     PrimitiveType dataWidth = EnsureValidOperandSize(op);
     EmitOpcode(0xF6 | IsWordWidth(dataWidth), dataWidth);
     EmitModRM(operation, op);
 }
Пример #28
0
 internal void ProcessBitOp(ParsedOperand[] ops)
 {
     PrimitiveType dataWidth = EnsureValidOperandSize(ops[0]);
     ImmediateOperand imm2 = ops[1].Operand as ImmediateOperand;
     if (imm2 != null)
     {
         EmitOpcode(0x0F, dataWidth);
         emitter.EmitByte(0xBA);
         EmitModRM(0x04, ops[0]);
         emitter.EmitByte(imm2.Value.ToInt32());
     }
     else
     {
         EmitOpcode(0x0F, dataWidth);
         emitter.EmitByte(0xA3);
         EmitModRM(RegisterEncoding(((RegisterOperand) ops[1].Operand).Register), ops[0]);
     }
 }
Пример #29
0
 internal void EmitModRM(int reg, ParsedOperand op, byte b)
 {
     RegisterOperand regOp = op.Operand as RegisterOperand;
     if (regOp != null)
     {
         modRm.EmitModRM(reg, regOp);
         emitter.EmitByte(b);
     }
     else
     {
         EmitModRM(reg, (MemoryOperand) op.Operand, b, op.Symbol);
     }
 }
Пример #30
0
 internal PrimitiveType EnsureValidOperandSize(ParsedOperand op)
 {
     PrimitiveType w = op.Operand.Width;
     if (w == null)
         Error("Width of the operand is unknown");
     return w;
 }
Пример #31
0
 public void Test(ParsedOperand op1, int imm)
 {
     ProcessTest(op1, Imm(imm));
 }
Пример #32
0
 public void Shr(ParsedOperand dst, byte c)
 {
     ProcessShiftRotation(0x05, dst, new ParsedOperand(new ImmediateOperand(Constant.Byte(c))));
 }