Beispiel #1
0
 protected OpCodeHandler(EncFlags2 encFlags2, EncFlags3 encFlags3, bool isSpecialInstr, TryConvertToDisp8N?tryConvertToDisp8N, Op[] operands)
 {
     EncFlags3          = encFlags3;
     OpCode             = GetOpCode(encFlags2);
     Is2ByteOpCode      = (encFlags2 & EncFlags2.OpCodeIs2Bytes) != 0;
     GroupIndex         = (encFlags2 & EncFlags2.HasGroupIndex) == 0 ? -1 : (int)(((uint)encFlags2 >> (int)EncFlags2.GroupIndexShift) & 7);
     RmGroupIndex       = (encFlags3 & EncFlags3.HasRmGroupIndex) == 0 ? -1 : (int)(((uint)encFlags2 >> (int)EncFlags2.GroupIndexShift) & 7);
     IsSpecialInstr     = isSpecialInstr;
     OpSize             = (CodeSize)(((uint)encFlags3 >> (int)EncFlags3.OperandSizeShift) & (uint)EncFlags3.OperandSizeMask);
     AddrSize           = (CodeSize)(((uint)encFlags3 >> (int)EncFlags3.AddressSizeShift) & (uint)EncFlags3.AddressSizeMask);
     TryConvertToDisp8N = tryConvertToDisp8N;
     Operands           = operands;
 }
Beispiel #2
0
        internal OpCodeInfo(Code code, EncFlags1 encFlags1, EncFlags2 encFlags2, EncFlags3 encFlags3, OpCodeInfoFlags1 opcFlags1, OpCodeInfoFlags2 opcFlags2, StringBuilder sb)
        {
            Debug.Assert((uint)code < (uint)IcedConstants.CodeEnumCount);
            Debug.Assert((uint)code <= ushort.MaxValue);
            this.code      = (ushort)code;
            this.encFlags2 = encFlags2;
            this.encFlags3 = encFlags3;
            this.opcFlags1 = opcFlags1;
            this.opcFlags2 = opcFlags2;

            if ((encFlags1 & EncFlags1.IgnoresRoundingControl) != 0)
            {
                flags |= Flags.IgnoresRoundingControl;
            }
            if ((encFlags1 & EncFlags1.AmdLockRegBit) != 0)
            {
                flags |= Flags.AmdLockRegBit;
            }
            flags |= (opcFlags1 & (OpCodeInfoFlags1.Cpl0Only | OpCodeInfoFlags1.Cpl3Only)) switch {
                OpCodeInfoFlags1.Cpl0Only => Flags.CPL0,
                OpCodeInfoFlags1.Cpl3Only => Flags.CPL3,
                _ => Flags.CPL0 | Flags.CPL1 | Flags.CPL2 | Flags.CPL3,
            };

            encoding        = (byte)(((uint)encFlags3 >> (int)EncFlags3.EncodingShift) & (uint)EncFlags3.EncodingMask);
            mandatoryPrefix = (MandatoryPrefixByte)(((uint)encFlags2 >> (int)EncFlags2.MandatoryPrefixShift) & (uint)EncFlags2.MandatoryPrefixMask) switch {
                MandatoryPrefixByte.None => (byte)((encFlags2 & EncFlags2.HasMandatoryPrefix) != 0 ? MandatoryPrefix.PNP : MandatoryPrefix.None),
                MandatoryPrefixByte.P66 => (byte)MandatoryPrefix.P66,
                MandatoryPrefixByte.PF3 => (byte)MandatoryPrefix.PF3,
                MandatoryPrefixByte.PF2 => (byte)MandatoryPrefix.PF2,
                _ => throw new InvalidOperationException(),
            };
            operandSize = (CodeSize)(((uint)encFlags3 >> (int)EncFlags3.OperandSizeShift) & (uint)EncFlags3.OperandSizeMask) switch {
                CodeSize.Unknown => 0,
                CodeSize.Code16 => 16,
                CodeSize.Code32 => 32,
                CodeSize.Code64 => 64,
                _ => throw new InvalidOperationException(),
            };
            addressSize = (CodeSize)(((uint)encFlags3 >> (int)EncFlags3.AddressSizeShift) & (uint)EncFlags3.AddressSizeMask) switch {
                CodeSize.Unknown => 0,
                CodeSize.Code16 => 16,
                CodeSize.Code32 => 32,
                CodeSize.Code64 => 64,
                _ => throw new InvalidOperationException(),
            };
            groupIndex   = (sbyte)((encFlags2 & EncFlags2.HasGroupIndex) == 0 ? -1 : (int)(((uint)encFlags2 >> (int)EncFlags2.GroupIndexShift) & 7));
            rmGroupIndex = (sbyte)((encFlags2 & EncFlags2.HasRmGroupIndex) == 0 ? -1 : (int)(((uint)encFlags2 >> (int)EncFlags2.GroupIndexShift) & 7));
            tupleType    = (byte)(((uint)encFlags3 >> (int)EncFlags3.TupleTypeShift) & (uint)EncFlags3.TupleTypeMask);

            LKind lkind;

#if !NO_VEX || !NO_EVEX || !NO_XOP
            switch ((LBit)(((uint)encFlags2 >> (int)EncFlags2.LBitShift) & (int)EncFlags2.LBitMask))
            {
            case LBit.LZ:
                lkind = LKind.LZ;
                l     = 0;
                break;

            case LBit.L0:
                lkind = LKind.L0;
                l     = 0;
                break;

            case LBit.L1:
                lkind = LKind.L0;
                l     = 1;
                break;

            case LBit.L128:
                lkind = LKind.L128;
                l     = 0;
                break;

            case LBit.L256:
                lkind = LKind.L128;
                l     = 1;
                break;

            case LBit.L512:
                lkind = LKind.L128;
                l     = 2;
                break;

            case LBit.LIG:
                lkind  = LKind.None;
                l      = 0;
                flags |= Flags.LIG;
                break;

            default:
                throw new InvalidOperationException();
            }
#else
            lkind = LKind.LZ;
#endif

#if !NO_VEX || !NO_EVEX || !NO_XOP
            switch ((WBit)(((uint)encFlags2 >> (int)EncFlags2.WBitShift) & (uint)EncFlags2.WBitMask))
            {
            case WBit.W0:
                break;

            case WBit.W1:
                flags |= Flags.W;
                break;

            case WBit.WIG:
                flags |= Flags.WIG;
                break;

            case WBit.WIG32:
                flags |= Flags.WIG32;
                break;

            default:
                throw new InvalidOperationException();
            }
#endif

            string?toOpCodeStringValue      = null;
            string?toInstructionStringValue = null;
#if HAS_SPAN
            ReadOnlySpan <byte> opKinds;
#else
            byte[] opKinds;
#endif
            switch ((EncodingKind)encoding)
            {
            case EncodingKind.Legacy:
                opKinds = OpCodeOperandKinds.LegacyOpKinds;
                op0Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.Legacy_Op0Shift) & (uint)EncFlags1.Legacy_OpMask)];
                op1Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.Legacy_Op1Shift) & (uint)EncFlags1.Legacy_OpMask)];
                op2Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.Legacy_Op2Shift) & (uint)EncFlags1.Legacy_OpMask)];
                op3Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.Legacy_Op3Shift) & (uint)EncFlags1.Legacy_OpMask)];

                table = (LegacyOpCodeTable)(((uint)encFlags2 >> (int)EncFlags2.TableShift) & (uint)EncFlags2.TableMask) switch {
                    LegacyOpCodeTable.Normal => (byte)OpCodeTableKind.Normal,
                    LegacyOpCodeTable.Table0F => (byte)OpCodeTableKind.T0F,
                    LegacyOpCodeTable.Table0F38 => (byte)OpCodeTableKind.T0F38,
                    LegacyOpCodeTable.Table0F3A => (byte)OpCodeTableKind.T0F3A,
                    _ => throw new InvalidOperationException(),
                };
                break;

            case EncodingKind.VEX:
#if !NO_VEX
                opKinds = OpCodeOperandKinds.VexOpKinds;
                op0Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.VEX_Op0Shift) & (uint)EncFlags1.VEX_OpMask)];
                op1Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.VEX_Op1Shift) & (uint)EncFlags1.VEX_OpMask)];
                op2Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.VEX_Op2Shift) & (uint)EncFlags1.VEX_OpMask)];
                op3Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.VEX_Op3Shift) & (uint)EncFlags1.VEX_OpMask)];
                op4Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.VEX_Op4Shift) & (uint)EncFlags1.VEX_OpMask)];

                table = (VexOpCodeTable)(((uint)encFlags2 >> (int)EncFlags2.TableShift) & (uint)EncFlags2.TableMask) switch {
                    VexOpCodeTable.Table0F => (byte)OpCodeTableKind.T0F,
                    VexOpCodeTable.Table0F38 => (byte)OpCodeTableKind.T0F38,
                    VexOpCodeTable.Table0F3A => (byte)OpCodeTableKind.T0F3A,
                    _ => throw new InvalidOperationException(),
                };
                break;
#else
                op4Kind                  = (byte)OpCodeOperandKind.None;
                toOpCodeStringValue      = string.Empty;
                toInstructionStringValue = string.Empty;
                break;
#endif

            case EncodingKind.EVEX:
#if !NO_EVEX
                opKinds = OpCodeOperandKinds.EvexOpKinds;
                op0Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.EVEX_Op0Shift) & (uint)EncFlags1.EVEX_OpMask)];
                op1Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.EVEX_Op1Shift) & (uint)EncFlags1.EVEX_OpMask)];
                op2Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.EVEX_Op2Shift) & (uint)EncFlags1.EVEX_OpMask)];
                op3Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.EVEX_Op3Shift) & (uint)EncFlags1.EVEX_OpMask)];

                table = (EvexOpCodeTable)(((uint)encFlags2 >> (int)EncFlags2.TableShift) & (uint)EncFlags2.TableMask) switch {
                    EvexOpCodeTable.Table0F => (byte)OpCodeTableKind.T0F,
                    EvexOpCodeTable.Table0F38 => (byte)OpCodeTableKind.T0F38,
                    EvexOpCodeTable.Table0F3A => (byte)OpCodeTableKind.T0F3A,
                    _ => throw new InvalidOperationException(),
                };
                break;
#else
                toOpCodeStringValue      = string.Empty;
                toInstructionStringValue = string.Empty;
                break;
#endif

            case EncodingKind.XOP:
#if !NO_XOP
                opKinds = OpCodeOperandKinds.XopOpKinds;
                op0Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.XOP_Op0Shift) & (uint)EncFlags1.XOP_OpMask)];
                op1Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.XOP_Op1Shift) & (uint)EncFlags1.XOP_OpMask)];
                op2Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.XOP_Op2Shift) & (uint)EncFlags1.XOP_OpMask)];
                op3Kind = opKinds[(int)(((uint)encFlags1 >> (int)EncFlags1.XOP_Op3Shift) & (uint)EncFlags1.XOP_OpMask)];

                table = (XopOpCodeTable)(((uint)encFlags2 >> (int)EncFlags2.TableShift) & (uint)EncFlags2.TableMask) switch {
                    XopOpCodeTable.XOP8 => (byte)OpCodeTableKind.XOP8,
                    XopOpCodeTable.XOP9 => (byte)OpCodeTableKind.XOP9,
                    XopOpCodeTable.XOPA => (byte)OpCodeTableKind.XOPA,
                    _ => throw new InvalidOperationException(),
                };
                break;
#else
                toOpCodeStringValue      = string.Empty;
                toInstructionStringValue = string.Empty;
                break;
#endif

            case EncodingKind.D3NOW:
#if !NO_D3NOW
                op0Kind = (byte)OpCodeOperandKind.mm_reg;
                op1Kind = (byte)OpCodeOperandKind.mm_or_mem;
                table   = (byte)OpCodeTableKind.T0F;
                break;
#else
                toOpCodeStringValue      = string.Empty;
                toInstructionStringValue = string.Empty;
                break;
#endif

            default:
                throw new InvalidOperationException();
            }

            this.toOpCodeStringValue = toOpCodeStringValue ?? new OpCodeFormatter(this, sb, lkind, (opcFlags1 & OpCodeInfoFlags1.ModRegRmString) != 0).Format();
            var fmtOption = (InstrStrFmtOption)(((uint)opcFlags2 >> (int)OpCodeInfoFlags2.InstrStrFmtOptionShift) & (uint)OpCodeInfoFlags2.InstrStrFmtOptionMask);
            this.toInstructionStringValue = toInstructionStringValue ?? new InstructionFormatter(this, fmtOption, sb).Format();
        }