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; }
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(); }