Ejemplo n.º 1
0
 public RegisterStorage?GetControlRegister(int v)
 {
     return(mode.GetControlRegister(v));
 }
Ejemplo n.º 2
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
            });
        }