public int ElementCount => elementSize == size ? 1 : size / elementSize; // ElementSize can be 0 so we don't divide by it if es == s /// <summary> /// Constructor /// </summary> /// <param name="memorySize">Memory size value</param> /// <param name="size">Size of location</param> /// <param name="elementSize">Size of the packed element, or <paramref name="size"/> if it's not packed data</param> /// <param name="elementType">Element type if it's packed data or <paramref name="memorySize"/> if it's not packed data</param> /// <param name="isSigned"><see langword="true"/> if signed data</param> /// <param name="isBroadcast"><see langword="true"/> if broadcast</param> public MemorySizeInfo(MemorySize memorySize, int size, int elementSize, MemorySize elementType, bool isSigned, bool isBroadcast) { if (size < 0) { ThrowHelper.ThrowArgumentOutOfRangeException_size(); } if (elementSize < 0) { ThrowHelper.ThrowArgumentOutOfRangeException_elementSize(); } if (elementSize > size) { ThrowHelper.ThrowArgumentOutOfRangeException_elementSize(); } Static.Assert(IcedConstants.NumberOfMemorySizes <= byte.MaxValue + 1 ? 0 : -1); this.memorySize = (byte)memorySize; Debug.Assert(size <= ushort.MaxValue); this.size = (ushort)size; Debug.Assert(elementSize <= ushort.MaxValue); this.elementSize = (ushort)elementSize; Static.Assert(IcedConstants.NumberOfMemorySizes <= byte.MaxValue + 1 ? 0 : -1); this.elementType = (byte)elementType; this.isSigned = isSigned; this.isBroadcast = isBroadcast; }
internal InstructionInfo(bool dummy) { usedRegisters = new SimpleList <UsedRegister>(new UsedRegister[InstrInfoConstants.DefaultUsedRegisterCollCapacity]); usedMemoryLocations = new SimpleList <UsedMemory>(new UsedMemory[InstrInfoConstants.DefaultUsedMemoryCollCapacity]); unsafe { opAccesses[0] = 0; opAccesses[1] = 0; opAccesses[2] = 0; opAccesses[3] = 0; opAccesses[4] = 0; Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); } }
internal InstructionInfo(bool dummy) { usedRegisters = new SimpleList <UsedRegister>(new UsedRegister[InstrInfoConstants.DefaultUsedRegisterCollCapacity]); usedMemoryLocations = new SimpleList <UsedMemory>(new UsedMemory[InstrInfoConstants.DefaultUsedMemoryCollCapacity]); unsafe { opAccesses[0] = 0; opAccesses[1] = 0; opAccesses[2] = 0; opAccesses[3] = 0; opAccesses[4] = 0; Static.Assert(IcedConstants.MaxOpCount == 5 ? 0 : -1); } cpuidFeatureInternal = 0; flowControl = 0; encoding = 0; rflagsInfo = 0; flags = 0; }
/// <summary> /// Gets the virtual address of a memory operand /// </summary> /// <param name="operand">Operand number, must be a memory operand</param> /// <param name="elementIndex">Only used if it's a vsib memory operand. This is the element index of the vector index register.</param> /// <param name="registerValueProvider">Returns values of registers and segment base addresses</param> /// <param name="result">Result if this method returns <see langword="true"/></param> /// <returns></returns> public readonly bool TryGetVirtualAddress(int operand, int elementIndex, IVATryGetRegisterValueProvider registerValueProvider, out ulong result) { if (registerValueProvider is null) { throw new ArgumentNullException(nameof(registerValueProvider)); } ulong seg, @base; switch (GetOpKind(operand)) { case OpKind.Register: case OpKind.NearBranch16: case OpKind.NearBranch32: case OpKind.NearBranch64: case OpKind.FarBranch16: case OpKind.FarBranch32: case OpKind.Immediate8: case OpKind.Immediate8_2nd: case OpKind.Immediate16: case OpKind.Immediate32: case OpKind.Immediate64: case OpKind.Immediate8to16: case OpKind.Immediate8to32: case OpKind.Immediate8to64: case OpKind.Immediate32to64: result = 0; return(true); case OpKind.MemorySegSI: if (registerValueProvider.TryGetRegisterValue(MemorySegment, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.SI, 0, 0, out @base)) { result = seg + (ushort)@base; return(true); } break; case OpKind.MemorySegESI: if (registerValueProvider.TryGetRegisterValue(MemorySegment, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.ESI, 0, 0, out @base)) { result = seg + (uint)@base; return(true); } break; case OpKind.MemorySegRSI: if (registerValueProvider.TryGetRegisterValue(MemorySegment, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.RSI, 0, 0, out @base)) { result = seg + @base; return(true); } break; case OpKind.MemorySegDI: if (registerValueProvider.TryGetRegisterValue(MemorySegment, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.DI, 0, 0, out @base)) { result = seg + (ushort)@base; return(true); } break; case OpKind.MemorySegEDI: if (registerValueProvider.TryGetRegisterValue(MemorySegment, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.EDI, 0, 0, out @base)) { result = seg + (uint)@base; return(true); } break; case OpKind.MemorySegRDI: if (registerValueProvider.TryGetRegisterValue(MemorySegment, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.RDI, 0, 0, out @base)) { result = seg + @base; return(true); } break; case OpKind.MemoryESDI: if (registerValueProvider.TryGetRegisterValue(Register.ES, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.DI, 0, 0, out @base)) { result = seg + (ushort)@base; return(true); } break; case OpKind.MemoryESEDI: if (registerValueProvider.TryGetRegisterValue(Register.ES, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.EDI, 0, 0, out @base)) { result = seg + (uint)@base; return(true); } break; case OpKind.MemoryESRDI: if (registerValueProvider.TryGetRegisterValue(Register.ES, 0, 0, out seg) && registerValueProvider.TryGetRegisterValue(Register.RDI, 0, 0, out @base)) { result = seg + @base; return(true); } break; case OpKind.Memory: var baseReg = MemoryBase; var indexReg = MemoryIndex; int addrSize = InstructionUtils.GetAddressSizeInBytes(baseReg, indexReg, MemoryDisplSize, CodeSize); ulong offset = MemoryDisplacement64; ulong offsetMask; if (addrSize == 8) { offsetMask = ulong.MaxValue; } else if (addrSize == 4) { offsetMask = uint.MaxValue; } else { Debug.Assert(addrSize == 2); offsetMask = ushort.MaxValue; } if (baseReg != Register.None && baseReg != Register.RIP && baseReg != Register.EIP) { if (!registerValueProvider.TryGetRegisterValue(baseReg, 0, 0, out @base)) { break; } offset += @base; } var code = Code; if (indexReg != Register.None && !code.IgnoresIndex() && !code.IsTileStrideIndex()) { if (TryGetVsib64(out bool vsib64)) { bool b; if (vsib64) { b = registerValueProvider.TryGetRegisterValue(indexReg, elementIndex, 8, out @base); } else { b = registerValueProvider.TryGetRegisterValue(indexReg, elementIndex, 4, out @base); @base = (ulong)(int)@base; } if (!b) { break; } offset += @base << InternalMemoryIndexScale; } else { if (!registerValueProvider.TryGetRegisterValue(indexReg, 0, 0, out @base)) { break; } offset += @base << InternalMemoryIndexScale; } } #if MVEX Static.Assert(Code.MVEX_Vloadunpackhd_zmm_k1_mt + 1 == Code.MVEX_Vloadunpackhq_zmm_k1_mt ? 0 : -1); Static.Assert(Code.MVEX_Vloadunpackhd_zmm_k1_mt + 2 == Code.MVEX_Vpackstorehd_mt_k1_zmm ? 0 : -1); Static.Assert(Code.MVEX_Vloadunpackhd_zmm_k1_mt + 3 == Code.MVEX_Vpackstorehq_mt_k1_zmm ? 0 : -1); Static.Assert(Code.MVEX_Vloadunpackhd_zmm_k1_mt + 4 == Code.MVEX_Vloadunpackhps_zmm_k1_mt ? 0 : -1); Static.Assert(Code.MVEX_Vloadunpackhd_zmm_k1_mt + 5 == Code.MVEX_Vloadunpackhpd_zmm_k1_mt ? 0 : -1); Static.Assert(Code.MVEX_Vloadunpackhd_zmm_k1_mt + 6 == Code.MVEX_Vpackstorehps_mt_k1_zmm ? 0 : -1); Static.Assert(Code.MVEX_Vloadunpackhd_zmm_k1_mt + 7 == Code.MVEX_Vpackstorehpd_mt_k1_zmm ? 0 : -1); if (code >= Code.MVEX_Vloadunpackhd_zmm_k1_mt && code <= Code.MVEX_Vpackstorehpd_mt_k1_zmm) { offset -= 0x40; } #endif offset &= offsetMask; if (!code.IgnoresSegment()) { if (!registerValueProvider.TryGetRegisterValue(MemorySegment, 0, 0, out seg)) { break; } offset += seg; } result = offset; return(true); default: throw new InvalidOperationException(); } result = 0; return(false); }