Beispiel #1
0
        private AddressOperand RelativeBranch(uint wInstr)
        {
            int off = (short)wInstr;

            off <<= 2;
            return(AddressOperand.Ptr32((uint)(off + rdr.Address.ToUInt32())));
        }
Beispiel #2
0
        private VaxInstruction DecodeOperands(Opcode opcode, string format)
        {
            var            ops = new List <MachineOperand>();
            MachineOperand op;
            PrimitiveType  width;
            int            i = 0;

            while (i != format.Length)
            {
                switch (format[i++])
                {
                case ',':
                    continue;

                case 'a':
                    if (!TryDecodeOperand(Width(format[i++]), out op))
                    {
                        return(null);
                    }
                    break;

                case 'r':
                case 'w':
                case 'm':
                case 'v':
                    if (!TryDecodeOperand(Width(format[i++]), out op))
                    {
                        return(null);
                    }
                    break;

                case 'b':
                    width = Width(format[i++]);
                    long  jOffset = rdr.ReadLeSigned(width);
                    ulong uAddr   = (uint)((long)rdr.Address.Offset + jOffset);
                    op = AddressOperand.Ptr32((uint)uAddr);
                    break;

                default:
                    throw new NotImplementedException(
                              string.Format(
                                  "Access type {0} not implemented.", format[i - 1]));
                }
                if (op == null)
                {
                    return(new VaxInstruction
                    {
                        Opcode = Opcode.Invalid,
                        Operands = new MachineOperand[0],
                    });
                }
                ops.Add(op);
            }
            return(new VaxInstruction
            {
                Opcode = opcode,
                Operands = ops.ToArray()
            });
        }
        private MachineOperand NegativePcRelativeAddress()
        {
            var nAddr =
                ((0xFFFF0000 | state.imm16) << 2) +
                (int)(rdr.Address.ToUInt32() & ~3);

            return(AddressOperand.Ptr32((uint)nAddr));
        }
Beispiel #4
0
 private static Mutator b(PrimitiveType width)
 {
     return(d =>
     {
         long jOffset = d.rdr.ReadLeSigned(width);
         uint uAddr = (uint)((long)d.rdr.Address.Offset + jOffset);
         d.ops.Add(AddressOperand.Ptr32(uAddr));
         return true;
     });
 }
Beispiel #5
0
        internal static bool Jijkm(uint uInstr, YmpDisassembler dasm)
        {
            if (!dasm.rdr.TryReadBeUInt16(out ushort n))
            {
                return(false);
            }
            var uAddr = ((uInstr & 0x1FF) << 16) | n;

            dasm.ops.Add(AddressOperand.Ptr32(uAddr));
            return(true);
        }
Beispiel #6
0
 // absolute address used by jump and call.
 private static bool Q(uint wInstr, Avr8Disassembler dasm)
 {
     if (!dasm.rdr.TryReadLeUInt16(out ushort w2))
     {
         return(false);
     }
     dasm.ops.Add(AddressOperand.Ptr32(
                      (uint)(((wInstr >> 4) & 0x1F) << 18) |
                      (uint)((wInstr & 1) << 17) |
                      (uint)(w2 << 1)));
     return(true);
 }
Beispiel #7
0
 private static Mutator b(PrimitiveType width)
 {
     return((u, d) =>
     {
         if (!d.rdr.TryReadLeSigned(width, out long jOffset))
         {
             return false;
         }
         uint uAddr = (uint)((long)d.rdr.Address.Offset + jOffset);
         d.ops.Add(AddressOperand.Ptr32(uAddr));
         return true;
     });
 }
Beispiel #8
0
 private MachineOperand DisplacementOperand(PrimitiveType width, RegisterStorage reg, Constant c, byte bSpecifier)
 {
     if (reg.Number == 15)
     {
         return(AddressOperand.Ptr32(
                    (uint)((int)rdr.Address.ToLinear() + c.ToInt32())));
     }
     return(new MemoryOperand(width)
     {
         Base = reg,
         Offset = c,
         Deferred = (bSpecifier >> 4) > 0xC
     });
 }
Beispiel #9
0
 private MachineOperand CreateAccess(
     RegisterStorage baseReg,
     int offset)
 {
     if (baseReg == null || baseReg.Number == 0)
     {
         return(AddressOperand.Ptr32((uint)offset));
     }
     return(new MemoryOperand(PrimitiveType.Word32)
     {
         Base = baseReg,
         Offset = offset
     });
 }
Beispiel #10
0
        private static Mutator <OpenRISCDisassembler> Page(int bitLen)
        {
            var offsetField = new Bitfield(0, bitLen);

            return((u, d) =>
            {
                long pageOffset = offsetField.ReadSigned(u) << 13;
                long lAddr = (long)(d.addr.ToLinear() & ~8192ul) + pageOffset;
                ulong uAddr = (ulong)lAddr;
                var aOp = d.arch.WordWidth.BitSize == 64
                    ? AddressOperand.Ptr64(uAddr)
                    : AddressOperand.Ptr32((uint)uAddr);
                d.ops.Add(aOp);
                return true;
            });
        }
Beispiel #11
0
        internal static bool Jnm(uint uInstr, YmpDisassembler dasm)
        {
            if (!dasm.rdr.TryReadBeUInt16(out ushort m))
            {
                return(false);
            }
            if (!dasm.rdr.TryReadBeUInt16(out ushort n))
            {
                return(false);
            }
            uint nm = n;

            nm = nm << 16 | m;
            dasm.ops.Add(AddressOperand.Ptr32(nm));
            return(true);
        }
Beispiel #12
0
        private MachineOperand AbsoluteDestination(int addrBytes)
        {
            uint uAddr = 0;
            int  sh    = 0;

            while (--addrBytes >= 0)
            {
                if (!rdr.TryReadByte(out byte b))
                {
                    return(null);
                }
                uAddr |= (uint)b << sh;
                sh    += 8;
            }
            return(AddressOperand.Ptr32(uAddr));
        }
Beispiel #13
0
 private MachineOperand CreateAccess(
     RegisterStorage baseReg,
     RegisterStorage idxReg,
     int offset)
 {
     if ((baseReg == null || baseReg.Number == 0) && 
         (idxReg == null || idxReg.Number == 0))
     {
         return AddressOperand.Ptr32((uint)offset);
     }
     return new MemoryOperand(PrimitiveType.Word32)
     {
         Base = baseReg,
         Index = idxReg,
         Offset = offset
     };
 }
            public override XtensaInstruction Decode(XtensaDisassembler dasm)
            {
                int shoff = dasm.state.imm12;

                if (shoff > 0x7FF)
                {
                    shoff |= ~0x7FF;
                }
                var dst = AddressOperand.Ptr32((uint)
                                               ((int)dasm.state.addr.ToUInt32() + 4 + shoff));

                return(new XtensaInstruction
                {
                    Opcode = opcode,
                    Operands = new MachineOperand[]
                    {
                        dasm.GetAluRegister(dasm.state.s),
                        dst,
                    }
                });
            }
Beispiel #15
0
        private Msp430Instruction Decode(ushort uInstr, Opcode opcode, string fmt)
        {
            PrimitiveType dataWidth = null;
            int           i         = 0;

            if (i < fmt.Length)
            {
                switch (fmt[i++])
                {
                case 'w': // use width bit
                    dataWidth = (uInstr & 0x40) != 0 ? PrimitiveType.Byte : PrimitiveType.Word16;
                    break;

                case 'a':   // a/w bit 4.
                    dataWidth = (uInstr & 0x04) != 0 ? PrimitiveType.Word16 : Msp430Architecture.Word20;
                    break;

                case 'x':
                    dataWidth = (uExtension != 0) && (uExtension & 0x40) == 0 ? Msp430Architecture.Word20 : PrimitiveType.Word16;
                    break;

                case 'p':
                    dataWidth = Msp430Architecture.Word20;
                    break;

                case 'W': // b/w/a combined from the op and the extension
                    var w = ((this.uExtension & 0x40) >> 5) | (uInstr & 0x040) >> 6;
                    switch (w)
                    {
                    case 0: return(Invalid());

                    case 1: dataWidth = Msp430Architecture.Word20; break;

                    case 2: dataWidth = PrimitiveType.Word16;      break;

                    case 3: dataWidth = PrimitiveType.Byte;        break;
                    }
                    break;

                default:
                    --i;
                    break;
                }
            }
            MachineOperand op1 = null;
            MachineOperand op2 = null;
            int            aS;
            int            iReg;

            if (i < fmt.Length)
            {
                switch (fmt[i++])
                {
                case 'J':
                    int offset = (short)(uInstr << 6) >> 5;
                    op1 = AddressOperand.Create(rdr.Address + offset);
                    break;

                case 'r':
                    op1 = SourceOperand(0, uInstr & 0x0F, dataWidth);
                    break;

                case 'S':
                    aS   = (uInstr >> 4) & 0x03;
                    iReg = (uInstr >> 8) & 0x0F;
                    op1  = SourceOperand(aS, iReg, dataWidth);
                    if (op1 == null)
                    {
                        return(null);
                    }
                    break;

                case 's':
                    aS   = (uInstr >> 4) & 0x03;
                    iReg = uInstr & 0x0F;
                    op1  = SourceOperand(aS, iReg, dataWidth);
                    if (op1 == null)
                    {
                        return(null);
                    }
                    break;

                case 'n':
                    int n = 1 + ((uInstr >> 4) & 0x0F);
                    op1 = ImmediateOperand.Byte((byte)n);
                    break;

                case 'N':
                    n   = 1 + ((uInstr >> 10) & 3);
                    op1 = ImmediateOperand.Byte((byte)n);
                    break;

                case '@':
                    iReg = (uInstr >> 8) & 0x0F;
                    var reg = Registers.GpRegisters[iReg];
                    op1 = new MemoryOperand(Msp430Architecture.Word20)
                    {
                        Base = reg,
                    };
                    break;

                case '+':
                    iReg = (uInstr >> 8) & 0x0F;
                    reg  = Registers.GpRegisters[iReg];
                    op1  = PostInc(reg, Msp430Architecture.Word20);
                    break;

                case '&':
                    if (!rdr.TryReadLeUInt16(out var lo16))
                    {
                        return(Invalid());
                    }
                    var hi4 = (uint)(uInstr >> 8) & 0x0F;
                    //$TODO: 20-bit address?
                    op1 = AddressOperand.Ptr32((hi4 << 16) | lo16);
                    break;

                case 'x':
                    if (!rdr.TryReadLeInt16(out var idxOffset))
                    {
                        return(Invalid());
                    }
                    iReg = (uInstr >> 8) & 0x0F;
                    reg  = Registers.GpRegisters[iReg];
                    op1  = new MemoryOperand(Msp430Architecture.Word20)
                    {
                        Base   = reg,
                        Offset = idxOffset
                    };
                    break;

                default:
                    --i;
                    break;
                }
            }
            if (i < fmt.Length)
            {
                switch (fmt[i])
                {
                case 'D':
                    var aD = (uInstr >> 7) & 0x01;
                    iReg = uInstr & 0x0F;
                    if (iReg == 3)
                    {
                        return(Invalid());
                    }
                    var reg = Registers.GpRegisters[iReg];
                    if (aD == 0)
                    {
                        if (iReg == 3)
                        {
                            return(Invalid());
                        }
                        op2 = new RegisterOperand(reg);
                    }
                    else
                    {
                        op2 = Indexed(reg, dataWidth);
                        if (op2 == null)
                        {
                            return(null);
                        }
                    }
                    break;

                case 'r':
                    op2 = SourceOperand(0, uInstr & 0x0F, dataWidth);
                    break;
                }
            }
            int rep   = (uExtension & 0x0F);
            var instr = new Msp430Instruction
            {
                opcode    = opcode,
                dataWidth = dataWidth,
                op1       = op1,
                op2       = op2,
                repeatImm = (uExtension & 0x80) != 0 ? 0 : rep + 1,
                repeatReg = (uExtension & 0x80) != 0 ? Registers.GpRegisters[rep] : null,
            };

            instr = SpecialCase(instr);
            return(instr);
        }
Beispiel #16
0
        public IEnumerator <MachineInstruction> GetEnumerator()
        {
            Address addr = rdr.Address;

            while (rdr.TryReadByte(out byte opcode))
            {
                MachineInstruction instr;
                switch ((opcode >> 4) & 0xF)
                {
                case 0: // nop
                    instr = new TestMachineInstruction(InstrClass.Padding | InstrClass.Linear, Mnemonic.nop);
                    break;

                case 1: // ALU
                    instr = new TestMachineInstruction(InstrClass.Linear, Mnemonic.alu);
                    break;

                case 2: // a jump
                    if (!rdr.TryReadBeUInt16(out ushort uAddr))
                    {
                        instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid);
                    }
                    else if ((opcode & 0xF) != 0)
                    {
                        instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Conditional, Mnemonic.bra);
                    }
                    else
                    {
                        instr = new TestMachineInstruction(InstrClass.Transfer, Mnemonic.jmp);
                    }
                    instr.Operands = new MachineOperand[] { AddressOperand.Ptr32(uAddr) };
                    break;

                case 3: // a call.
                    if (!rdr.TryReadBeUInt16(out uAddr))
                    {
                        instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid);
                    }
                    else
                    {
                        instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Call, Mnemonic.call);
                    }
                    instr.Operands = new MachineOperand[] { AddressOperand.Ptr32(uAddr) };
                    break;

                case 4: // a jump with delay slot
                    if (!rdr.TryReadBeUInt16(out uAddr))
                    {
                        instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid);
                    }
                    else if ((opcode & 0xF) != 0)
                    {
                        instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Conditional | InstrClass.Delay, Mnemonic.braD);
                    }
                    else
                    {
                        instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Delay, Mnemonic.jmpD);
                    }
                    instr.Operands = new MachineOperand[] { AddressOperand.Ptr32(uAddr) };
                    break;

                case 5: // a call with delay slot.
                    if (!rdr.TryReadBeUInt16(out uAddr))
                    {
                        instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid);
                    }
                    else
                    {
                        instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Call | InstrClass.Delay, Mnemonic.callD);
                    }
                    instr.Operands = new MachineOperand[] { AddressOperand.Ptr32(uAddr) };
                    break;

                case 6: // return
                    instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Return, Mnemonic.ret);
                    break;

                case 7: // return with delay slot.
                    instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Return | InstrClass.Delay, Mnemonic.ret);
                    break;

                default:
                    instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid);
                    break;
                }
                var addrNew = rdr.Address;
                instr.Address = addr;
                instr.Length  = (int)(addrNew - addr);
                yield return(instr);

                addr = addrNew;
            }
        }
Beispiel #17
0
        public AvrInstruction Decode(ushort wInstr, Opcode opcode, InstrClass iclass, string fmt)
        {
            var    ops = new List <MachineOperand>();
            int    offset;
            ushort w2;

            for (int i = 0; i < fmt.Length; ++i)
            {
                MachineOperand op;
                switch (fmt[i++])
                {
                case ',':
                    continue;

                case '+':
                    op = IncDec(true, fmt[i++]);
                    break;

                case '-':
                    op = IncDec(false, fmt[i++]);
                    break;

                case 'A': // I/O location
                    op = ImmediateOperand.Byte((byte)(((wInstr >> 5) & 0x30) | (wInstr & 0xF)));
                    break;

                case 'B': // 8-bit immediate at bits 8..11 and 0..3
                    op = ImmediateOperand.Byte((byte)(((wInstr >> 4) & 0xF0) | (wInstr & 0x0F)));
                    break;

                case 'g': // 4-bit field in sgis
                    op = ImmediateOperand.Byte((byte)((wInstr >> 3) & 0x0F));
                    break;

                case 'h': // 3-bit field in sgis, indicating bit nr.
                    op = ImmediateOperand.Byte((byte)(wInstr & 7));
                    break;

                case 'I': // 4-bit immediate at bit 0
                    op = ImmediateOperand.Byte((byte)(wInstr & 0x0F));
                    break;

                case 'i': // 4-bit immediate at bit 4
                    op = ImmediateOperand.Byte((byte)((wInstr >> 4) & 0x0F));
                    break;

                case 'J': // Relative jump
                    offset = (short)((wInstr & 0xFFF) << 4);
                    offset = offset >> 3;
                    op     = AddressOperand.Create(this.addr + 2 + offset);
                    break;

                case 'D': // Destination register
                    op = Register((wInstr >> 4) & 0x1F);
                    break;

                case 'd': // Destination register (r16-r31)
                    op = Register(0x10 | (wInstr >> 4) & 0x0F);
                    break;

                case 'R': // source register (5 bits)
                    op = Register((wInstr >> 5) & 0x10 | (wInstr) & 0x0F);
                    break;

                case 'r':
                    if (i < fmt.Length && fmt[i] == '4')
                    {
                        ++i;
                        // source register (r16-r31)
                        op = Register(0x10 | wInstr & 0x0F);
                    }
                    else
                    {
                        // source register (5 bits)
                        op = Register((wInstr >> 4) & 0x10 | (wInstr >> 4) & 0x0F);
                    }
                    break;

                case 'K':
                    op = ImmediateOperand.Byte((byte)(((wInstr >> 4) & 0xF0) | (wInstr & 0xF)));
                    break;

                case 'P': // register pair source
                    op = Register((wInstr << 1) & ~1);
                    break;

                case 'p': // register pair destination
                    op = Register((wInstr >> 3) & ~1);
                    break;

                case 'Q':   // absolute address used by jump and call.
                    if (!rdr.TryReadLeUInt16(out w2))
                    {
                        return(null);
                    }
                    op = AddressOperand.Ptr32(
                        (uint)(((wInstr >> 4) & 0x1F) << 18) |
                        (uint)((wInstr & 1) << 17) |
                        (uint)(w2 << 1));
                    break;

                case 'q':   // register pair used by adiw
                    op = Register(24 + ((wInstr >> 3) & 6));
                    break;

                case 's':   // immediate used by adiw/sbiw
                    op = ImmediateOperand.Byte((byte)(((wInstr >> 2) & 0x30) | (wInstr & 0xF)));
                    break;

                case 'w': // Trailing 16-bit absolute address
                    if (!rdr.TryReadLeUInt16(out w2))
                    {
                        return(null);
                    }
                    op = AddressOperand.Ptr16(w2);
                    break;

                case 'o':   // Branch offset
                    offset = (short)wInstr;
                    offset = (short)(offset << 6);
                    offset = (short)(offset >> 8);
                    offset = (short)(offset & ~1);
                    op     = AddressOperand.Create(this.addr + offset + 2);
                    break;

                case 'X':
                    op = MemD(arch.x, 0);
                    break;

                case 'Y':
                    op = MemD(arch.y, 0);
                    break;

                case 'y':
                    op = MemD(arch.y, Displacement(wInstr));
                    break;

                case 'Z':
                    op = MemD(arch.z, 0);
                    break;

                case 'z':
                    op = MemD(arch.z, Displacement(wInstr));
                    break;

                default:
                    throw new NotImplementedException(string.Format("Unimplemented AVR8 format symbol '{0}'.'", fmt[i - 1]));
                }
                ops.Add(op);
            }
            return(new AvrInstruction
            {
                opcode = opcode,
                iclass = iclass,
                operands = ops.ToArray(),
            });
        }
Beispiel #18
0
        private X86Instruction DecodeOperands(Opcode opcode, byte op, string strFormat, InstrClass iclass)
        {
            if (strFormat == null)
            {
                return(null);
            }
            MachineOperand        pOperand;
            PrimitiveType         width  = null;
            PrimitiveType         iWidth = dataWidth;
            byte                  modRm;
            List <MachineOperand> ops = new List <MachineOperand>();
            int i = 0;

            while (i != strFormat.Length)
            {
                if (strFormat[i] == ',')
                {
                    ++i;
                }

                pOperand = null;
                MemoryOperand memOp;
                char          chFmt = strFormat[i++];
                switch (chFmt)
                {
                case '1':
                    pOperand = new ImmediateOperand(Constant.Byte(1));
                    break;

                case '3':
                    pOperand = new ImmediateOperand(Constant.Byte(3));
                    break;

                case 'A':               // Absolute memory address.
                    ++i;
                    if (!rdr.TryReadLeUInt16(out ushort off))
                    {
                        return(null);
                    }
                    if (!rdr.TryReadLeUInt16(out ushort seg))
                    {
                        return(null);
                    }
                    var addr = mode.CreateSegmentedAddress(seg, off);
                    if (addr == null)
                    {
                        return(null);
                    }
                    pOperand = new X86AddressOperand(addr);
                    break;

                case 'C':       // control register encoded in the reg field.
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    var creg = mode.GetControlRegister((modRm >> 3) & 7);
                    if (creg == null)
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(creg);
                    break;

                case 'D':       // debug register encoded in the reg field.
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    var dreg = mode.GetDebugRegister((modRm >> 3) & 7);
                    if (dreg == null)
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(dreg);
                    break;

                case 'E':               // memory or register operand specified by mod & r/m fields.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, GpRegFromBits);
                    if (pOperand == null)
                    {
                        return(null);
                    }
                    break;

                case 'Q':               // memory or register MMX operand specified by mod & r/m fields.
                    width    = SseOperandWidth(strFormat, ref i);
                    pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, MmxRegFromBits);
                    if (pOperand == null)
                    {
                        return(null);
                    }
                    break;

                case 'G':               // register operand specified by the reg field of the modRM byte.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, GpRegFromBits));
                    break;

                case 'H':       // If VEX encoding, use vvvv register.
                    if (currentDecodingContext.IsVex)
                    {
                        width    = SseOperandWidth(strFormat, ref i);
                        pOperand = new RegisterOperand(XmmRegFromBits(currentDecodingContext.VexRegister, width));
                    }
                    else
                    {
                        i = strFormat.IndexOf(',', i);
                    }
                    break;

                case 'N':       // MMX register operand specified by the r/m field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, MmxRegFromBits));
                    break;

                case 'P':               // MMX register operand specified by the reg field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, MmxRegFromBits));
                    break;

                case 'I':               // Immediate operand.
                    if (strFormat[i] == 'x')
                    {
                        iWidth = width; // Use width of the previous operand.
                    }
                    else
                    {
                        width = OperandWidth(strFormat, ref i); //  Don't use the width of the previous operand.
                    }
                    ++i;
                    pOperand = CreateImmediateOperand(width, dataWidth);
                    if (pOperand == null)
                    {
                        return(null);
                    }
                    break;

                case 'L': // The upper 4 bits of the 8-bit immediate selects a 128-bit XMM register or a 256-bit YMM register, determined
                          // by operand type.
                    if (!rdr.TryReadByte(out var lReg))
                    {
                        return(null);
                    }
                    if (strFormat[i] == 'x')
                    {
                        iWidth = width; // Use width of the previous operand.
                    }
                    else
                    {
                        width = OperandWidth(strFormat, ref i); //  Don't use the width of the previous operand.
                    }
                    ++i;
                    pOperand = new RegisterOperand(XmmRegFromBits((lReg >> 4) & 0xF, width));
                    break;

                case 'J':               // Relative ("near") jump.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    Constant cOffset;
                    if (!rdr.TryRead(width, out cOffset))
                    {
                        return(null);
                    }
                    long  jOffset = cOffset.ToInt64();
                    ulong uAddr   = (ulong)((long)rdr.Address.Offset + jOffset);
                    if (defaultAddressWidth.BitSize == 64)      //$REVIEW: not too keen on the switch statement here.
                    {
                        pOperand = AddressOperand.Ptr64(uAddr);
                    }
                    else if (defaultAddressWidth.BitSize == 32)
                    {
                        pOperand = AddressOperand.Ptr32((uint)uAddr);
                    }
                    else
                    {
                        pOperand = new ImmediateOperand(Constant.Create(defaultDataWidth, uAddr));
                    }
                    break;

                case 'M':               // modRM may only refer to memory.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    if ((modRm & 0xC0) == 0xC0)
                    {
                        return(null);
                    }
                    pOperand = DecodeModRM(dataWidth, this.currentDecodingContext.SegmentOverride, GpRegFromBits) as MemoryOperand;
                    if (pOperand == null)
                    {
                        return(null);
                    }
                    break;

                case 'O':               // Offset of the operand is encoded directly after the opcode.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    if (!rdr.TryReadLe(addressWidth, out var offset))
                    {
                        return(null);
                    }
                    pOperand          = memOp = new MemoryOperand(width, offset);
                    memOp.SegOverride = this.currentDecodingContext.SegmentOverride;
                    break;

                case 'R':       // register operand specified by the mod field of the modRM byte.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, GpRegFromBits));
                    break;

                case 'S':       // Segment register encoded by reg field of modRM byte.
                    ++i;        // Skip over the 'w'.
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(SegFromBits(modRm >> 3));
                    break;

                case 'U':               // XMM operand specified by the modRm field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, XmmRegFromBits));
                    break;

                case 'V':               // XMM operand specified by the reg field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, XmmRegFromBits));
                    break;

                case 'W':               // memory or XMM operand specified by mod & r/m fields.
                    width    = SseOperandWidth(strFormat, ref i);
                    pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, XmmRegFromBits);
                    break;

                case 'a':               // Implicit use of accumulator.
                    pOperand = new RegisterOperand(RegFromBitsRexW(0, OperandWidth(strFormat, ref i)));
                    ++i;
                    break;

                case 'b':
                    iWidth   = PrimitiveType.Byte;
                    pOperand = null;
                    break;

                case 'c':               // Implicit use of CL.
                    pOperand = new RegisterOperand(Registers.cl);
                    break;

                case 'd':               // Implicit use of DX or EDX.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    pOperand = new RegisterOperand(RegFromBitsRexW(2, width));
                    break;

                case 'r':               // Register encoded as last 3 bits of instruction.
                    iWidth = width = OperandWidth(strFormat, ref i);
                    ++i;
                    pOperand = new RegisterOperand(RegFromBitsRexB(op, width));
                    break;

                case 's':               // Segment encoded as next byte of the format string.
                    pOperand = new RegisterOperand(SegFromBits(strFormat[i++] - '0'));
                    break;

                case 'F':               // Floating-point ST(x)
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new FpuOperand(modRm & 0x07);
                    break;

                case 'f':               // ST(0)
                    pOperand = new FpuOperand(0);
                    break;

                default:
                    throw new ArgumentOutOfRangeException(string.Format("Unknown format specifier '{0}' at position {1} of format string '{2}'.", chFmt, i, strFormat));
                }
                if (pOperand != null)
                {
                    ops.Add(pOperand);
                }
            }
            return(new X86Instruction(opcode, iclass, iWidth, addressWidth, ops.ToArray())
            {
                repPrefix = this.currentDecodingContext.F2Prefix ? 2 :
                            this.currentDecodingContext.F3Prefix ? 3 : 0
            });
        }
        private MachineOperand JumpOffset(byte offset)
        {
            int dst = (int)state.addr.ToUInt32() + (sbyte)offset + 4;

            return(AddressOperand.Ptr32((uint)dst));
        }
 private AddressOperand LongJumpOffset()
 {
     return(AddressOperand.Ptr32((uint)((int)state.addr.ToLinear() + (state.offset + 4))));
 }
 private MachineOperand CallOffset(int offset)
 {
     return(AddressOperand.Ptr32((uint)((state.addr.ToUInt32() & ~3) + (offset << 2) + 4)));
 }
Beispiel #22
0
        private IntelInstruction DecodeOperands(Opcode opcode, byte op, string strFormat)
        {
            MachineOperand        pOperand;
            PrimitiveType         width  = null;
            PrimitiveType         iWidth = dataWidth;
            byte                  modRm;
            List <MachineOperand> ops = new List <MachineOperand>();
            int i = 0;

            while (i != strFormat.Length)
            {
                if (strFormat[i] == ',')
                {
                    ++i;
                }

                pOperand = null;
                ImmediateOperand  immOp;
                MemoryOperand     memOp;
                X86AddressOperand addrOp;
                int offset;

                char chFmt = strFormat[i++];
                switch (chFmt)
                {
                case '1':
                    pOperand = immOp = new ImmediateOperand(Constant.Byte(1));
                    break;

                case '3':
                    pOperand = immOp = new ImmediateOperand(Constant.Byte(3));
                    break;

                case 'A':               // Absolute memory address.
                    ++i;
                    ushort off = rdr.ReadLeUInt16();
                    ushort seg = rdr.ReadLeUInt16();
                    pOperand = addrOp = new X86AddressOperand(Address.SegPtr(seg, off));
                    break;

                case 'E':               // memory or register operand specified by mod & r/m fields.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = DecodeModRM(width, segmentOverride, GpRegFromBits);
                    break;

                case 'Q':               // memory or register MMX operand specified by mod & r/m fields.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = DecodeModRM(width, segmentOverride, MmxRegFromBits);
                    break;

                case 'G':               // register operand specified by the reg field of the modRM byte.
                    width = OperandWidth(strFormat[i++]);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, GpRegFromBits));
                    break;

                case 'P':               // MMX register operand specified by the reg field of the modRM byte.
                    width = OperandWidth(strFormat[i++]);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, MmxRegFromBits));
                    break;

                case 'I':               // Immediate operand.
                    if (strFormat[i] == 'x')
                    {
                        iWidth = width; // Use width of the previous operand.
                    }
                    else
                    {
                        width = OperandWidth(strFormat[i]); //  Don't use the width of the previous operand.
                    }
                    ++i;
                    pOperand = CreateImmediateOperand(width, dataWidth);
                    break;

                case 'J':               // Relative ("near") jump.
                    width  = OperandWidth(strFormat[i++]);
                    offset = rdr.ReadLeSigned(width);
                    ulong uAddr = (ulong)((long)rdr.Address.Offset + (long)offset);
                    if (defaultAddressWidth.BitSize == 64)      //$REVIEW: not too keen on the switch statement here.
                    {
                        pOperand = AddressOperand.Ptr64(uAddr);
                    }
                    else if (defaultAddressWidth.BitSize == 32)
                    {
                        pOperand = AddressOperand.Ptr32((uint)uAddr);
                    }
                    else
                    {
                        pOperand = new ImmediateOperand(Constant.Create(defaultDataWidth, uAddr));
                    }
                    break;

                case 'M':               // modRM may only refer to memory.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = DecodeModRM(dataWidth, segmentOverride, GpRegFromBits);
                    break;

                case 'O':               // Offset of the operand is encoded directly after the opcode.
                    width             = OperandWidth(strFormat[i++]);
                    pOperand          = memOp = new MemoryOperand(width, rdr.ReadLe(addressWidth));
                    memOp.SegOverride = segmentOverride;
                    break;

                case 'S':       // Segment register encoded by reg field of modRM byte.
                    ++i;        // Skip over the 'w'.
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(SegFromBits(modRm >> 3));
                    break;

                case 'V':               // XMM operand specified by the reg field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, XmmRegFromBits));
                    break;

                case 'W':               // memory or XMM operand specified by mod & r/m fields.
                    width    = SseOperandWidth(strFormat, ref i);
                    pOperand = DecodeModRM(width, segmentOverride, XmmRegFromBits);
                    break;

                case 'a':               // Implicit use of accumulator.
                    pOperand = new RegisterOperand(RegFromBitsRexW(0, OperandWidth(strFormat[i++])));
                    break;

                case 'b':
                    iWidth   = PrimitiveType.Byte;
                    pOperand = null;
                    break;

                case 'c':               // Implicit use of CL.
                    pOperand = new RegisterOperand(Registers.cl);
                    break;

                case 'd':               // Implicit use of DX or EDX.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = new RegisterOperand(RegFromBitsRexW(2, width));
                    break;

                case 'r':               // Register encoded as last 3 bits of instruction.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = new RegisterOperand(RegFromBitsRexW(op, width));
                    break;

                case 's':               // Segment encoded as next byte of the format string.
                    pOperand = new RegisterOperand(SegFromBits(strFormat[i++] - '0'));
                    break;

                case 'F':               // Floating-point ST(x)
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new FpuOperand(modRm & 0x07);
                    break;

                case 'f':               // ST(0)
                    pOperand = new FpuOperand(0);
                    break;

                default:
                    throw new ArgumentOutOfRangeException(string.Format("Unknown format specifier '{0}' at position {1} of format string '{2}'.", chFmt, i, strFormat));
                }
                if (pOperand != null)
                {
                    ops.Add(pOperand);
                }
            }
            return(new IntelInstruction(opcode, iWidth, addressWidth, ops.ToArray()));
        }
Beispiel #23
0
        private AddressOperand LargeBranch(uint wInstr)
        {
            var off = (wInstr & 0x03FFFFFF) << 2;

            return(AddressOperand.Ptr32((rdr.Address.ToUInt32() & 0xF0000000u) | off));
        }