diff --git a/Iced/Intel/Instruction.Create.cs b/Iced/Intel/Instruction.Create.cs new file mode 100644 index 000000000..57905290a --- /dev/null +++ b/Iced/Intel/Instruction.Create.cs @@ -0,0 +1,1383 @@ +/* + Copyright (C) 2018 de4dot@gmail.com + + This file is part of Iced. + + Iced is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Iced is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Iced. If not, see . +*/ + +#if !NO_ENCODER +using System; +using System.Diagnostics; + +namespace Iced.Intel { + partial struct Instruction { + static OpKind GetImmediateOpKind(Code code, int operand) { + var handlers = EncoderInternal.OpCodeHandlers.Handlers; + if ((uint)code >= (uint)handlers.Length) + throw new ArgumentOutOfRangeException(nameof(code)); + var operands = handlers[(int)code].Operands; + if ((uint)operand >= (uint)operands.Length) + throw new ArgumentOutOfRangeException(nameof(operand), $"{code} doesn't have at least {operand + 1} operands"); + var opKind = operands[operand].GetImmediateOpKind(); + if (opKind == (OpKind)(-1)) + throw new ArgumentException($"{code}'s op{operand} isn't an immediate operand"); + return opKind; + } + + static OpKind GetNearBranchOpKind(Code code, int operand) { + var handlers = EncoderInternal.OpCodeHandlers.Handlers; + if ((uint)code >= (uint)handlers.Length) + throw new ArgumentOutOfRangeException(nameof(code)); + var operands = handlers[(int)code].Operands; + if ((uint)operand >= (uint)operands.Length) + throw new ArgumentOutOfRangeException(nameof(operand), $"{code} doesn't have at least {operand + 1} operands"); + var opKind = operands[operand].GetNearBranchOpKind(); + if (opKind == (OpKind)(-1)) + throw new ArgumentException($"{code}'s op{operand} isn't a near branch operand"); + return opKind; + } + + static OpKind GetFarBranchOpKind(Code code, int operand) { + var handlers = EncoderInternal.OpCodeHandlers.Handlers; + if ((uint)code >= (uint)handlers.Length) + throw new ArgumentOutOfRangeException(nameof(code)); + var operands = handlers[(int)code].Operands; + if ((uint)operand >= (uint)operands.Length) + throw new ArgumentOutOfRangeException(nameof(operand), $"{code} doesn't have at least {operand + 1} operands"); + var opKind = operands[operand].GetFarBranchOpKind(); + if (opKind == (OpKind)(-1)) + throw new ArgumentException($"{code}'s op{operand} isn't a far branch operand"); + return opKind; + } + + /// + /// Creates a new with no operands + /// + /// Code value + /// + public static Instruction Create(Code code) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(instruction.OpCount == 0); + return instruction; + } + + /// + /// Creates a new near/short branch + /// + /// Code value + /// Target address + /// + public static Instruction CreateBranch(Code code, ulong target) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.Op0Kind = GetNearBranchOpKind(code, 0); + instruction.NearBranch64 = target; + + Debug.Assert(instruction.OpCount == 1); + return instruction; + } + + /// + /// Creates a new far branch + /// + /// Code value + /// Selector/segment value + /// Offset + /// + public static Instruction CreateBranch(Code code, ushort selector, uint offset) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.Op0Kind = GetFarBranchOpKind(code, 0); + instruction.FarBranchSelector = selector; + instruction.FarBranch32 = offset; + + Debug.Assert(instruction.OpCount == 1); + return instruction; + } + + /// + /// Creates an instruction with a 64-bit memory offset as the second operand, eg. 'mov al,[123456789ABCDEF0]' + /// + /// Code value + /// Register (al, ax, eax, rax) + /// 64-bit address + /// Segment override or + /// + public static Instruction CreateMemory64(Code code, Register register, ulong address, Register prefixSegment = Register.None) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + instruction.InternalOp1Kind = OpKind.Memory64; + instruction.MemoryAddress64 = address; + instruction.InternalSetMemoryDisplSize(4); + instruction.PrefixSegment = prefixSegment; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction with a 64-bit memory offset as the first operand, eg. 'mov [123456789ABCDEF0],al' + /// + /// Code value + /// 64-bit address + /// Register (al, ax, eax, rax) + /// Segment override or + /// + public static Instruction CreateMemory64(Code code, ulong address, Register register, Register prefixSegment = Register.None) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = OpKind.Memory64; + instruction.MemoryAddress64 = address; + instruction.InternalSetMemoryDisplSize(4); + instruction.PrefixSegment = prefixSegment; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// + public static Instruction Create(Code code, Register register) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + Debug.Assert(instruction.OpCount == 1); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Immediate + /// + public static Instruction Create(Code code, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = GetImmediateOpKind(code, 0); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 1); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Immediate + /// + public static Instruction Create(Code code, uint immediate) => + Create(code, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Memory operand + /// + public static Instruction Create(Code code, in MemoryOperand memory) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(instruction.OpCount == 1); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// + public static Instruction Create(Code code, Register register1, Register register2) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + var opKind = GetImmediateOpKind(code, 1); + instruction.InternalOp1Kind = opKind; + if (opKind == OpKind.Immediate64) + instruction.Immediate64 = (ulong)immediate; + else + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register, uint immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + var opKind = GetImmediateOpKind(code, 1); + instruction.InternalOp1Kind = opKind; + if (opKind == OpKind.Immediate64) + instruction.Immediate64 = immediate; + else + instruction.Immediate32 = immediate; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction with a 64-bit immediate value + /// + /// Code value + /// Register + /// 64-bit immediate + /// + public static Instruction Create(Code code, Register register, long immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + instruction.InternalOp1Kind = OpKind.Immediate64; + instruction.Immediate64 = (ulong)immediate; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction with a 64-bit immediate value + /// + /// Code value + /// Register + /// 64-bit immediate + /// + public static Instruction Create(Code code, Register register, ulong immediate) => + Create(code, register, (long)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Register (eg. dx, al, ax, eax, rax) + /// si, esi, or rsi + /// Segment override or + /// + public static Instruction CreateString_Reg_SegRSI(Code code, Register register, Register rSI, Register prefixSegment = Register.None) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + if (rSI == Register.RSI) + instruction.InternalOp1Kind = OpKind.MemorySegRSI; + else if (rSI == Register.ESI) + instruction.InternalOp1Kind = OpKind.MemorySegESI; + else if (rSI == Register.SI) + instruction.InternalOp1Kind = OpKind.MemorySegSI; + else + throw new ArgumentOutOfRangeException(nameof(rSI)); + + instruction.PrefixSegment = prefixSegment; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register (eg. al, ax, eax, rax) + /// di, edi, or rdi + /// + public static Instruction CreateString_Reg_ESRDI(Code code, Register register, Register rDI) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + if (rDI == Register.RDI) + instruction.InternalOp1Kind = OpKind.MemoryESRDI; + else if (rDI == Register.EDI) + instruction.InternalOp1Kind = OpKind.MemoryESEDI; + else if (rDI == Register.DI) + instruction.InternalOp1Kind = OpKind.MemoryESDI; + else + throw new ArgumentOutOfRangeException(nameof(rDI)); + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Memory operand + /// + public static Instruction Create(Code code, Register register, in MemoryOperand memory) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + instruction.InternalOp1Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Immediate + /// Register + /// + public static Instruction Create(Code code, int immediate, Register register) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = GetImmediateOpKind(code, 0); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Immediate + /// Register + /// + public static Instruction Create(Code code, uint immediate, Register register) => + Create(code, (int)immediate, register); + + /// + /// Creates an instruction + /// + /// Code value + /// Immediate + /// Second immediate + /// + public static Instruction Create(Code code, int immediate, byte immediate2) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = GetImmediateOpKind(code, 0); + instruction.Immediate32 = (uint)immediate; + + instruction.InternalOp1Kind = OpKind.Immediate8_2nd; + instruction.Immediate8_2nd = immediate2; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Immediate + /// Second immediate + /// + public static Instruction Create(Code code, uint immediate, byte immediate2) => + Create(code, (int)immediate, immediate2); + + /// + /// Creates an instruction + /// + /// Code value + /// si, esi, or rsi + /// di, edi, or rdi + /// Segment override or + /// + public static Instruction CreateString_SegRSI_ESRDI(Code code, Register rSI, Register rDI, Register prefixSegment = Register.None) { + Instruction instruction = default; + instruction.InternalCode = code; + + if (rSI == Register.RSI) + instruction.InternalOp0Kind = OpKind.MemorySegRSI; + else if (rSI == Register.ESI) + instruction.InternalOp0Kind = OpKind.MemorySegESI; + else if (rSI == Register.SI) + instruction.InternalOp0Kind = OpKind.MemorySegSI; + else + throw new ArgumentOutOfRangeException(nameof(rSI)); + + if (rDI == Register.RDI) + instruction.InternalOp1Kind = OpKind.MemoryESRDI; + else if (rDI == Register.EDI) + instruction.InternalOp1Kind = OpKind.MemoryESEDI; + else if (rDI == Register.DI) + instruction.InternalOp1Kind = OpKind.MemoryESDI; + else + throw new ArgumentOutOfRangeException(nameof(rDI)); + + instruction.PrefixSegment = prefixSegment; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// di, edi, or rdi + /// Register (eg. dx, al, ax, eax, rax) + /// + public static Instruction CreateString_ESRDI_Reg(Code code, Register rDI, Register register) { + Instruction instruction = default; + instruction.InternalCode = code; + + if (rDI == Register.RDI) + instruction.InternalOp0Kind = OpKind.MemoryESRDI; + else if (rDI == Register.EDI) + instruction.InternalOp0Kind = OpKind.MemoryESEDI; + else if (rDI == Register.DI) + instruction.InternalOp0Kind = OpKind.MemoryESDI; + else + throw new ArgumentOutOfRangeException(nameof(rDI)); + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// di, edi, or rdi + /// si, esi, or rsi + /// Segment override or + /// + public static Instruction CreateString_ESRDI_SegRSI(Code code, Register rDI, Register rSI, Register prefixSegment = Register.None) { + Instruction instruction = default; + instruction.InternalCode = code; + + if (rDI == Register.RDI) + instruction.InternalOp0Kind = OpKind.MemoryESRDI; + else if (rDI == Register.EDI) + instruction.InternalOp0Kind = OpKind.MemoryESEDI; + else if (rDI == Register.DI) + instruction.InternalOp0Kind = OpKind.MemoryESDI; + else + throw new ArgumentOutOfRangeException(nameof(rDI)); + + if (rSI == Register.RSI) + instruction.InternalOp1Kind = OpKind.MemorySegRSI; + else if (rSI == Register.ESI) + instruction.InternalOp1Kind = OpKind.MemorySegESI; + else if (rSI == Register.SI) + instruction.InternalOp1Kind = OpKind.MemorySegSI; + else + throw new ArgumentOutOfRangeException(nameof(rSI)); + + instruction.PrefixSegment = prefixSegment; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Memory operand + /// Register + /// + public static Instruction Create(Code code, in MemoryOperand memory, Register register) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Memory operand + /// Immediate + /// + public static Instruction Create(Code code, in MemoryOperand memory, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + instruction.InternalOp1Kind = GetImmediateOpKind(code, 1); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 2); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Memory operand + /// Immediate + /// + public static Instruction Create(Code code, in MemoryOperand memory, uint immediate) => + Create(code, memory, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register3; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + instruction.InternalOp2Kind = GetImmediateOpKind(code, 2); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, uint immediate) => + Create(code, register1, register2, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Memory operand + /// + public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + instruction.InternalOp2Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Immediate + /// Second immediate + /// + public static Instruction Create(Code code, Register register, int immediate, byte immediate2) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + instruction.InternalOp1Kind = GetImmediateOpKind(code, 1); + instruction.Immediate32 = (uint)immediate; + + instruction.InternalOp2Kind = OpKind.Immediate8_2nd; + instruction.Immediate8_2nd = immediate2; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Immediate + /// Second immediate + /// + public static Instruction Create(Code code, Register register, uint immediate, byte immediate2) => + Create(code, register, (int)immediate, immediate2); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Memory operand + /// Register + /// + public static Instruction Create(Code code, Register register1, in MemoryOperand memory, Register register2) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + instruction.InternalOp1Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register2; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Memory operand + /// Immediate + /// + public static Instruction Create(Code code, Register register, in MemoryOperand memory, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register; + + instruction.InternalOp1Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + instruction.InternalOp2Kind = GetImmediateOpKind(code, 2); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Memory operand + /// Immediate + /// + public static Instruction Create(Code code, Register register, in MemoryOperand memory, uint immediate) => + Create(code, register, memory, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// di, edi, or rdi + /// Register + /// Register + /// Segment override or + /// + public static Instruction CreateMaskmov_SegRDI_Reg_Reg(Code code, Register rDI, Register register1, Register register2, Register prefixSegment = Register.None) { + Instruction instruction = default; + instruction.InternalCode = code; + + if (rDI == Register.RDI) + instruction.InternalOp0Kind = OpKind.MemorySegRDI; + else if (rDI == Register.EDI) + instruction.InternalOp0Kind = OpKind.MemorySegEDI; + else if (rDI == Register.DI) + instruction.InternalOp0Kind = OpKind.MemorySegDI; + else + throw new ArgumentOutOfRangeException(nameof(rDI)); + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register2; + + instruction.PrefixSegment = prefixSegment; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Memory operand + /// Register + /// Register + /// + public static Instruction Create(Code code, in MemoryOperand memory, Register register1, Register register2) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register2; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Memory operand + /// Register + /// Immediate + /// + public static Instruction Create(Code code, in MemoryOperand memory, Register register, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + instruction.InternalOp0Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register; + + instruction.InternalOp2Kind = GetImmediateOpKind(code, 2); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 3); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Memory operand + /// Register + /// Immediate + /// + public static Instruction Create(Code code, in MemoryOperand memory, Register register, uint immediate) => + Create(code, memory, register, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// Register + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3, Register register4) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register3; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp3Kind = OpKind.Register; + instruction.InternalOp3Register = register4; + + Debug.Assert(instruction.OpCount == 4); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register3; + + instruction.InternalOp3Kind = GetImmediateOpKind(code, 3); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 4); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3, uint immediate) => + Create(code, register1, register2, register3, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// Memory operand + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3, in MemoryOperand memory) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register3; + + instruction.InternalOp3Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(instruction.OpCount == 4); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Immediate + /// Second immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, int immediate, byte immediate2) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + instruction.InternalOp2Kind = GetImmediateOpKind(code, 2); + instruction.Immediate32 = (uint)immediate; + + instruction.InternalOp3Kind = OpKind.Immediate8_2nd; + instruction.Immediate8_2nd = immediate2; + + Debug.Assert(instruction.OpCount == 4); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Immediate + /// Second immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, uint immediate, byte immediate2) => + Create(code, register1, register2, (int)immediate, immediate2); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Memory operand + /// Register + /// + public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, Register register3) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + instruction.InternalOp2Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp3Kind = OpKind.Register; + instruction.InternalOp3Register = register3; + + Debug.Assert(instruction.OpCount == 4); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Memory operand + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + instruction.InternalOp2Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + instruction.InternalOp3Kind = GetImmediateOpKind(code, 3); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 4); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Memory operand + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, uint immediate) => + Create(code, register1, register2, memory, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3, Register register4, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register3; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp3Kind = OpKind.Register; + instruction.InternalOp3Register = register4; + + instruction.InternalOp4Kind = GetImmediateOpKind(code, 4); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 5); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3, Register register4, uint immediate) => + Create(code, register1, register2, register3, register4, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// Memory operand + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3, in MemoryOperand memory, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp2Kind = OpKind.Register; + instruction.InternalOp2Register = register3; + + instruction.InternalOp3Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + instruction.InternalOp4Kind = GetImmediateOpKind(code, 4); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 5); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Register + /// Memory operand + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, Register register3, in MemoryOperand memory, uint immediate) => + Create(code, register1, register2, register3, memory, (int)immediate); + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Memory operand + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, Register register3, int immediate) { + Instruction instruction = default; + instruction.InternalCode = code; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp0Kind = OpKind.Register; + instruction.InternalOp0Register = register1; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp1Kind = OpKind.Register; + instruction.InternalOp1Register = register2; + + instruction.InternalOp2Kind = OpKind.Memory; + instruction.InternalMemoryBase = memory.Base; + instruction.InternalMemoryIndex = memory.Index; + instruction.MemoryIndexScale = memory.Scale; + instruction.MemoryDisplSize = memory.DisplSize; + instruction.MemoryDisplacement = (uint)memory.Displacement; + instruction.IsBroadcast = memory.IsBroadcast; + instruction.PrefixSegment = memory.PrefixSegment; + + Debug.Assert(OpKind.Register == 0); + //instruction.InternalOp3Kind = OpKind.Register; + instruction.InternalOp3Register = register3; + + instruction.InternalOp4Kind = GetImmediateOpKind(code, 4); + instruction.Immediate32 = (uint)immediate; + + Debug.Assert(instruction.OpCount == 5); + return instruction; + } + + /// + /// Creates an instruction + /// + /// Code value + /// Register + /// Register + /// Memory operand + /// Register + /// Immediate + /// + public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, Register register3, uint immediate) => + Create(code, register1, register2, memory, register3, (int)immediate); + } +} +#endif diff --git a/Iced/Intel/Instruction.Info.cs b/Iced/Intel/Instruction.Info.cs new file mode 100644 index 000000000..f8678f008 --- /dev/null +++ b/Iced/Intel/Instruction.Info.cs @@ -0,0 +1,359 @@ +/* + Copyright (C) 2018 de4dot@gmail.com + + This file is part of Iced. + + Iced is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Iced is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with Iced. If not, see . +*/ + +#if !NO_INSTR_INFO +using System.Diagnostics; + +namespace Iced.Intel { + partial struct Instruction { + /// + /// Gets the number of bytes added to SP/ESP/RSP or 0 if it's not an instruction that pushes or pops data. This method + /// assumes the instruction doesn't change privilege (eg. iret/d/q). If it's the leave instruction, this method returns 0. + /// + /// + public int StackPointerIncrement { + get { + switch (Code) { + case Code.Pushw_ES: + case Code.Pushw_CS: + case Code.Pushw_SS: + case Code.Pushw_DS: + case Code.Push_r16: + case Code.Push_imm16: + case Code.Pushw_imm8: + case Code.Pushfw: + case Code.Push_rm16: + case Code.Pushw_FS: + case Code.Pushw_GS: + return -2; + + case Code.Pushd_ES: + case Code.Pushd_CS: + case Code.Pushd_SS: + case Code.Pushd_DS: + case Code.Push_r32: + case Code.Pushd_imm32: + case Code.Pushd_imm8: + case Code.Pushfd: + case Code.Push_rm32: + case Code.Pushd_FS: + case Code.Pushd_GS: + return -4; + + case Code.Push_r64: + case Code.Pushq_imm32: + case Code.Pushq_imm8: + case Code.Pushfq: + case Code.Push_rm64: + case Code.Pushq_FS: + case Code.Pushq_GS: + return -8; + + case Code.Pushaw: + return -2 * 8; + + case Code.Pushad: + return -4 * 8; + + case Code.Popw_ES: + case Code.Popw_SS: + case Code.Popw_DS: + case Code.Pop_r16: + case Code.Pop_rm16: + case Code.Popfw: + case Code.Popw_FS: + case Code.Popw_GS: + return 2; + + case Code.Popd_ES: + case Code.Popd_SS: + case Code.Popd_DS: + case Code.Pop_r32: + case Code.Pop_rm32: + case Code.Popfd: + case Code.Popd_FS: + case Code.Popd_GS: + return 4; + + case Code.Pop_r64: + case Code.Pop_rm64: + case Code.Popfq: + case Code.Popq_FS: + case Code.Popq_GS: + return 8; + + case Code.Popaw: + return 2 * 8; + + case Code.Popad: + return 4 * 8; + + case Code.Call_ptr1616: + case Code.Call_m1616: + return -(2 + 2); + + case Code.Call_ptr3216: + case Code.Call_m3216: + return -(4 + 4); + + case Code.Call_m6416: + return -(8 + 8); + + case Code.Call_rel16: + case Code.Call_rm16: + return -2; + + case Code.Call_rel32_32: + case Code.Call_rm32: + return -4; + + case Code.Call_rel32_64: + case Code.Call_rm64: + return -8; + + case Code.Retnw_imm16: + return 2 + Immediate16; + + case Code.Retnd_imm16: + return 4 + Immediate16; + + case Code.Retnq_imm16: + return 8 + Immediate16; + + case Code.Retnw: + return 2; + + case Code.Retnd: + return 4; + + case Code.Retnq: + return 8; + + case Code.Retfw_imm16: + return 2 + 2 + Immediate16; + + case Code.Retfd_imm16: + return 4 + 4 + Immediate16; + + case Code.Retfq_imm16: + return 8 + 8 + Immediate16; + + case Code.Retfw: + return 2 + 2; + + case Code.Retfd: + return 4 + 4; + + case Code.Retfq: + return 8 + 8; + + case Code.Iretw: + if (CodeSize == CodeSize.Code64) + return 2 * 5; + return 2 * 3; + + case Code.Iretd: + if (CodeSize == CodeSize.Code64) + return 4 * 5; + return 4 * 3; + + case Code.Iretq: + return 8 * 5; + + case Code.Enterw_imm16_imm8: + return -(2 + (Immediate8_2nd & 0x1F) * 2 + Immediate16); + + case Code.Enterd_imm16_imm8: + return -(4 + (Immediate8_2nd & 0x1F) * 4 + Immediate16); + + case Code.Enterq_imm16_imm8: + return -(8 + (Immediate8_2nd & 0x1F) * 8 + Immediate16); + + case Code.Leavew: + case Code.Leaved: + case Code.Leaveq: + return 0; + + default: + return 0; + } + } + } + + /// + /// (This method allocates and is slower than using an .) + /// + /// Gets instruction info such as which register is read and written etc. + /// + /// + public InstructionInfo GetInfo() { + var usedRegisters = InstructionInfoInternal.SimpleList.Empty; + var usedMemoryLocations = InstructionInfoInternal.SimpleList.Empty; + return InstructionInfoFactory.Create(ref this, ref usedRegisters, ref usedMemoryLocations, InstructionInfoOptions.None); + } + + /// + /// (This method allocates and is slower than using an .) + /// + /// Gets instruction info such as which register is read and written etc. + /// + /// Options + /// + public InstructionInfo GetInfo(InstructionInfoOptions options) { + var usedRegisters = InstructionInfoInternal.SimpleList.Empty; + var usedMemoryLocations = InstructionInfoInternal.SimpleList.Empty; + return InstructionInfoFactory.Create(ref this, ref usedRegisters, ref usedMemoryLocations, options); + } + + /// + /// (This method allocates and is slower than using an .) + /// + /// Gets a struct iterator that returns all read and written registers. There are some exceptions, this method doesn't return all used registers: + /// + /// 1) If is true, or + /// + /// 2) If it's a or instruction (call, sysenter, int n etc), it can read and write any register (including RFLAGS). + /// + /// + public InstructionInfo.UsedRegisterIterator GetUsedRegisters() { + var usedRegisters = InstructionInfoInternal.SimpleList.Empty; + var usedMemoryLocations = InstructionInfoInternal.SimpleList.Empty; + return InstructionInfoFactory.Create(ref this, ref usedRegisters, ref usedMemoryLocations, InstructionInfoOptions.NoMemoryUsage).GetUsedRegisters(); + } + + /// + /// (This method allocates and is slower than using an .) + /// + /// Gets a struct iterator that returns all read and written memory locations + /// + /// + public InstructionInfo.UsedMemoryIterator GetUsedMemory() { + var usedRegisters = InstructionInfoInternal.SimpleList.Empty; + var usedMemoryLocations = InstructionInfoInternal.SimpleList.Empty; + return InstructionInfoFactory.Create(ref this, ref usedRegisters, ref usedMemoryLocations, InstructionInfoOptions.NoRegisterUsage).GetUsedMemory(); + } + + /// + /// Instruction encoding, eg. legacy, VEX, EVEX, ... + /// + public EncodingKind Encoding => Code.Encoding(); + + /// + /// CPU or CPUID feature flag + /// + public CpuidFeature CpuidFeature { + get { + var code = Code; + var cpuidFeature = code.CpuidFeature(); + if (cpuidFeature == CpuidFeature.AVX && Op1Kind == OpKind.Register && (code == Code.VEX_Vbroadcastss_xmm_xmmm32 || code == Code.VEX_Vbroadcastss_ymm_xmmm32 || code == Code.VEX_Vbroadcastsd_ymm_xmmm64)) + return CpuidFeature.AVX2; + return cpuidFeature; + } + } + + /// + /// Flow control info + /// + public FlowControl FlowControl => Code.FlowControl(); + + /// + /// true if the instruction isn't available in real mode or virtual 8086 mode + /// + public bool ProtectedMode => Code.ProtectedMode(); + + /// + /// true if this is a privileged instruction + /// + public bool Privileged => Code.Privileged(); + + /// + /// true if this is an instruction that implicitly uses the stack pointer (SP/ESP/RSP), eg. call, push, pop, ret, etc. + /// See also + /// + public bool StackInstruction => Code.StackInstruction(); + + /// + /// true if it's an instruction that saves or restores too many registers (eg. fxrstor, xsave, etc). + /// + public bool SaveRestoreInstruction => Code.SaveRestoreInstruction(); + + InstructionInfoInternal.RflagsInfo GetRflagsInfo() { + var flags1 = InstructionInfoInternal.InfoHandlers.Data[(int)Code << 1]; + var codeInfo = (InstructionInfoInternal.CodeInfo)((flags1 >> (int)InstructionInfoInternal.InfoFlags1.CodeInfoShift) & (uint)InstructionInfoInternal.InfoFlags1.CodeInfoMask); + Debug.Assert(InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9 + 1 == InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD11); + Debug.Assert(InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9 + 2 == InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1F); + Debug.Assert(InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9 + 3 == InstructionInfoInternal.CodeInfo.Shift_Ib_MASK3F); + if ((uint)(codeInfo - InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9) <= 3) { + switch (codeInfo) { + case InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9: + if ((Immediate8 & 0x1F) % 9 == 0) + return InstructionInfoInternal.RflagsInfo.None; + break; + + case InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD11: + if ((Immediate8 & 0x1F) % 17 == 0) + return InstructionInfoInternal.RflagsInfo.None; + break; + + case InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1F: + if ((Immediate8 & 0x1F) == 0) + return InstructionInfoInternal.RflagsInfo.None; + break; + + case InstructionInfoInternal.CodeInfo.Shift_Ib_MASK3F: + if ((Immediate8 & 0x3F) == 0) + return InstructionInfoInternal.RflagsInfo.None; + break; + } + } + return (InstructionInfoInternal.RflagsInfo)((flags1 >> (int)InstructionInfoInternal.InfoFlags1.RflagsInfoShift) & (uint)InstructionInfoInternal.InfoFlags1.RflagsInfoMask); + } + + /// + /// All flags that are read by the CPU when executing the instruction + /// + public RflagsBits RflagsRead => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsRead[(int)GetRflagsInfo()]; + + /// + /// All flags that are written by the CPU, except those flags that are known to be undefined, always set or always cleared. See also + /// + public RflagsBits RflagsWritten => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsWritten[(int)GetRflagsInfo()]; + + /// + /// All flags that are always cleared by the CPU + /// + public RflagsBits RflagsCleared => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsCleared[(int)GetRflagsInfo()]; + + /// + /// All flags that are always set by the CPU + /// + public RflagsBits RflagsSet => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsSet[(int)GetRflagsInfo()]; + + /// + /// All flags that are undefined after executing the instruction + /// + public RflagsBits RflagsUndefined => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsUndefined[(int)GetRflagsInfo()]; + + /// + /// All flags that are modified by the CPU. This is + + + + /// + public RflagsBits RflagsModified => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsModified[(int)GetRflagsInfo()]; + } +} +#endif diff --git a/Iced/Intel/Instruction.cs b/Iced/Intel/Instruction.cs index 906ffa58f..0d577b907 100644 --- a/Iced/Intel/Instruction.cs +++ b/Iced/Intel/Instruction.cs @@ -26,7 +26,7 @@ namespace Iced.Intel { /// /// A 16/32/64-bit instruction /// - public struct Instruction { + public partial struct Instruction { internal const int TEST_OpKindBits = (int)OpKindFlags.OpKindBits; internal const int TEST_CodeBits = (int)CodeFlags.CodeBits; internal const int TEST_RegisterBits = 8; @@ -1290,1699 +1290,6 @@ namespace Iced.Intel { } } -#if !NO_INSTR_INFO - /// - /// Gets the number of bytes added to SP/ESP/RSP or 0 if it's not an instruction that pushes or pops data. This method - /// assumes the instruction doesn't change privilege (eg. iret/d/q). If it's the leave instruction, this method returns 0. - /// - /// - public int StackPointerIncrement { - get { - switch (Code) { - case Code.Pushw_ES: - case Code.Pushw_CS: - case Code.Pushw_SS: - case Code.Pushw_DS: - case Code.Push_r16: - case Code.Push_imm16: - case Code.Pushw_imm8: - case Code.Pushfw: - case Code.Push_rm16: - case Code.Pushw_FS: - case Code.Pushw_GS: - return -2; - - case Code.Pushd_ES: - case Code.Pushd_CS: - case Code.Pushd_SS: - case Code.Pushd_DS: - case Code.Push_r32: - case Code.Pushd_imm32: - case Code.Pushd_imm8: - case Code.Pushfd: - case Code.Push_rm32: - case Code.Pushd_FS: - case Code.Pushd_GS: - return -4; - - case Code.Push_r64: - case Code.Pushq_imm32: - case Code.Pushq_imm8: - case Code.Pushfq: - case Code.Push_rm64: - case Code.Pushq_FS: - case Code.Pushq_GS: - return -8; - - case Code.Pushaw: - return -2 * 8; - - case Code.Pushad: - return -4 * 8; - - case Code.Popw_ES: - case Code.Popw_SS: - case Code.Popw_DS: - case Code.Pop_r16: - case Code.Pop_rm16: - case Code.Popfw: - case Code.Popw_FS: - case Code.Popw_GS: - return 2; - - case Code.Popd_ES: - case Code.Popd_SS: - case Code.Popd_DS: - case Code.Pop_r32: - case Code.Pop_rm32: - case Code.Popfd: - case Code.Popd_FS: - case Code.Popd_GS: - return 4; - - case Code.Pop_r64: - case Code.Pop_rm64: - case Code.Popfq: - case Code.Popq_FS: - case Code.Popq_GS: - return 8; - - case Code.Popaw: - return 2 * 8; - - case Code.Popad: - return 4 * 8; - - case Code.Call_ptr1616: - case Code.Call_m1616: - return -(2 + 2); - - case Code.Call_ptr3216: - case Code.Call_m3216: - return -(4 + 4); - - case Code.Call_m6416: - return -(8 + 8); - - case Code.Call_rel16: - case Code.Call_rm16: - return -2; - - case Code.Call_rel32_32: - case Code.Call_rm32: - return -4; - - case Code.Call_rel32_64: - case Code.Call_rm64: - return -8; - - case Code.Retnw_imm16: - return 2 + Immediate16; - - case Code.Retnd_imm16: - return 4 + Immediate16; - - case Code.Retnq_imm16: - return 8 + Immediate16; - - case Code.Retnw: - return 2; - - case Code.Retnd: - return 4; - - case Code.Retnq: - return 8; - - case Code.Retfw_imm16: - return 2 + 2 + Immediate16; - - case Code.Retfd_imm16: - return 4 + 4 + Immediate16; - - case Code.Retfq_imm16: - return 8 + 8 + Immediate16; - - case Code.Retfw: - return 2 + 2; - - case Code.Retfd: - return 4 + 4; - - case Code.Retfq: - return 8 + 8; - - case Code.Iretw: - if (CodeSize == CodeSize.Code64) - return 2 * 5; - return 2 * 3; - - case Code.Iretd: - if (CodeSize == CodeSize.Code64) - return 4 * 5; - return 4 * 3; - - case Code.Iretq: - return 8 * 5; - - case Code.Enterw_imm16_imm8: - return -(2 + (Immediate8_2nd & 0x1F) * 2 + Immediate16); - - case Code.Enterd_imm16_imm8: - return -(4 + (Immediate8_2nd & 0x1F) * 4 + Immediate16); - - case Code.Enterq_imm16_imm8: - return -(8 + (Immediate8_2nd & 0x1F) * 8 + Immediate16); - - case Code.Leavew: - case Code.Leaved: - case Code.Leaveq: - return 0; - - default: - return 0; - } - } - } - - /// - /// (This method allocates and is slower than using an .) - /// - /// Gets instruction info such as which register is read and written etc. - /// - /// - public InstructionInfo GetInfo() { - var usedRegisters = InstructionInfoInternal.SimpleList.Empty; - var usedMemoryLocations = InstructionInfoInternal.SimpleList.Empty; - return InstructionInfoFactory.Create(ref this, ref usedRegisters, ref usedMemoryLocations, InstructionInfoOptions.None); - } - - /// - /// (This method allocates and is slower than using an .) - /// - /// Gets instruction info such as which register is read and written etc. - /// - /// Options - /// - public InstructionInfo GetInfo(InstructionInfoOptions options) { - var usedRegisters = InstructionInfoInternal.SimpleList.Empty; - var usedMemoryLocations = InstructionInfoInternal.SimpleList.Empty; - return InstructionInfoFactory.Create(ref this, ref usedRegisters, ref usedMemoryLocations, options); - } - - /// - /// (This method allocates and is slower than using an .) - /// - /// Gets a struct iterator that returns all read and written registers. There are some exceptions, this method doesn't return all used registers: - /// - /// 1) If is true, or - /// - /// 2) If it's a or instruction (call, sysenter, int n etc), it can read and write any register (including RFLAGS). - /// - /// - public InstructionInfo.UsedRegisterIterator GetUsedRegisters() { - var usedRegisters = InstructionInfoInternal.SimpleList.Empty; - var usedMemoryLocations = InstructionInfoInternal.SimpleList.Empty; - return InstructionInfoFactory.Create(ref this, ref usedRegisters, ref usedMemoryLocations, InstructionInfoOptions.NoMemoryUsage).GetUsedRegisters(); - } - - /// - /// (This method allocates and is slower than using an .) - /// - /// Gets a struct iterator that returns all read and written memory locations - /// - /// - public InstructionInfo.UsedMemoryIterator GetUsedMemory() { - var usedRegisters = InstructionInfoInternal.SimpleList.Empty; - var usedMemoryLocations = InstructionInfoInternal.SimpleList.Empty; - return InstructionInfoFactory.Create(ref this, ref usedRegisters, ref usedMemoryLocations, InstructionInfoOptions.NoRegisterUsage).GetUsedMemory(); - } - - /// - /// Instruction encoding, eg. legacy, VEX, EVEX, ... - /// - public EncodingKind Encoding => Code.Encoding(); - - /// - /// CPU or CPUID feature flag - /// - public CpuidFeature CpuidFeature { - get { - var code = Code; - var cpuidFeature = code.CpuidFeature(); - if (cpuidFeature == CpuidFeature.AVX && Op1Kind == OpKind.Register && (code == Code.VEX_Vbroadcastss_xmm_xmmm32 || code == Code.VEX_Vbroadcastss_ymm_xmmm32 || code == Code.VEX_Vbroadcastsd_ymm_xmmm64)) - return CpuidFeature.AVX2; - return cpuidFeature; - } - } - - /// - /// Flow control info - /// - public FlowControl FlowControl => Code.FlowControl(); - - /// - /// true if the instruction isn't available in real mode or virtual 8086 mode - /// - public bool ProtectedMode => Code.ProtectedMode(); - - /// - /// true if this is a privileged instruction - /// - public bool Privileged => Code.Privileged(); - - /// - /// true if this is an instruction that implicitly uses the stack pointer (SP/ESP/RSP), eg. call, push, pop, ret, etc. - /// See also - /// - public bool StackInstruction => Code.StackInstruction(); - - /// - /// true if it's an instruction that saves or restores too many registers (eg. fxrstor, xsave, etc). - /// - public bool SaveRestoreInstruction => Code.SaveRestoreInstruction(); - - InstructionInfoInternal.RflagsInfo GetRflagsInfo() { - var flags1 = InstructionInfoInternal.InfoHandlers.Data[(int)Code << 1]; - var codeInfo = (InstructionInfoInternal.CodeInfo)((flags1 >> (int)InstructionInfoInternal.InfoFlags1.CodeInfoShift) & (uint)InstructionInfoInternal.InfoFlags1.CodeInfoMask); - Debug.Assert(InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9 + 1 == InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD11); - Debug.Assert(InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9 + 2 == InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1F); - Debug.Assert(InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9 + 3 == InstructionInfoInternal.CodeInfo.Shift_Ib_MASK3F); - if ((uint)(codeInfo - InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9) <= 3) { - switch (codeInfo) { - case InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD9: - if ((Immediate8 & 0x1F) % 9 == 0) - return InstructionInfoInternal.RflagsInfo.None; - break; - - case InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1FMOD11: - if ((Immediate8 & 0x1F) % 17 == 0) - return InstructionInfoInternal.RflagsInfo.None; - break; - - case InstructionInfoInternal.CodeInfo.Shift_Ib_MASK1F: - if ((Immediate8 & 0x1F) == 0) - return InstructionInfoInternal.RflagsInfo.None; - break; - - case InstructionInfoInternal.CodeInfo.Shift_Ib_MASK3F: - if ((Immediate8 & 0x3F) == 0) - return InstructionInfoInternal.RflagsInfo.None; - break; - } - } - return (InstructionInfoInternal.RflagsInfo)((flags1 >> (int)InstructionInfoInternal.InfoFlags1.RflagsInfoShift) & (uint)InstructionInfoInternal.InfoFlags1.RflagsInfoMask); - } - - /// - /// All flags that are read by the CPU when executing the instruction - /// - public RflagsBits RflagsRead => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsRead[(int)GetRflagsInfo()]; - - /// - /// All flags that are written by the CPU, except those flags that are known to be undefined, always set or always cleared. See also - /// - public RflagsBits RflagsWritten => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsWritten[(int)GetRflagsInfo()]; - - /// - /// All flags that are always cleared by the CPU - /// - public RflagsBits RflagsCleared => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsCleared[(int)GetRflagsInfo()]; - - /// - /// All flags that are always set by the CPU - /// - public RflagsBits RflagsSet => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsSet[(int)GetRflagsInfo()]; - - /// - /// All flags that are undefined after executing the instruction - /// - public RflagsBits RflagsUndefined => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsUndefined[(int)GetRflagsInfo()]; - - /// - /// All flags that are modified by the CPU. This is + + + - /// - public RflagsBits RflagsModified => (RflagsBits)InstructionInfoInternal.RflagsInfoConstants.flagsModified[(int)GetRflagsInfo()]; -#endif - -#if !NO_ENCODER - static OpKind GetImmediateOpKind(Code code, int operand) { - var handlers = EncoderInternal.OpCodeHandlers.Handlers; - if ((uint)code >= (uint)handlers.Length) - throw new ArgumentOutOfRangeException(nameof(code)); - var operands = handlers[(int)code].Operands; - if ((uint)operand >= (uint)operands.Length) - throw new ArgumentOutOfRangeException(nameof(operand), $"{code} doesn't have at least {operand + 1} operands"); - var opKind = operands[operand].GetImmediateOpKind(); - if (opKind == (OpKind)(-1)) - throw new ArgumentException($"{code}'s op{operand} isn't an immediate operand"); - return opKind; - } - - static OpKind GetNearBranchOpKind(Code code, int operand) { - var handlers = EncoderInternal.OpCodeHandlers.Handlers; - if ((uint)code >= (uint)handlers.Length) - throw new ArgumentOutOfRangeException(nameof(code)); - var operands = handlers[(int)code].Operands; - if ((uint)operand >= (uint)operands.Length) - throw new ArgumentOutOfRangeException(nameof(operand), $"{code} doesn't have at least {operand + 1} operands"); - var opKind = operands[operand].GetNearBranchOpKind(); - if (opKind == (OpKind)(-1)) - throw new ArgumentException($"{code}'s op{operand} isn't a near branch operand"); - return opKind; - } - - static OpKind GetFarBranchOpKind(Code code, int operand) { - var handlers = EncoderInternal.OpCodeHandlers.Handlers; - if ((uint)code >= (uint)handlers.Length) - throw new ArgumentOutOfRangeException(nameof(code)); - var operands = handlers[(int)code].Operands; - if ((uint)operand >= (uint)operands.Length) - throw new ArgumentOutOfRangeException(nameof(operand), $"{code} doesn't have at least {operand + 1} operands"); - var opKind = operands[operand].GetFarBranchOpKind(); - if (opKind == (OpKind)(-1)) - throw new ArgumentException($"{code}'s op{operand} isn't a far branch operand"); - return opKind; - } - - /// - /// Creates a new with no operands - /// - /// Code value - /// - public static Instruction Create(Code code) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(instruction.OpCount == 0); - return instruction; - } - - /// - /// Creates a new near/short branch - /// - /// Code value - /// Target address - /// - public static Instruction CreateBranch(Code code, ulong target) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.Op0Kind = GetNearBranchOpKind(code, 0); - instruction.NearBranch64 = target; - - Debug.Assert(instruction.OpCount == 1); - return instruction; - } - - /// - /// Creates a new far branch - /// - /// Code value - /// Selector/segment value - /// Offset - /// - public static Instruction CreateBranch(Code code, ushort selector, uint offset) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.Op0Kind = GetFarBranchOpKind(code, 0); - instruction.FarBranchSelector = selector; - instruction.FarBranch32 = offset; - - Debug.Assert(instruction.OpCount == 1); - return instruction; - } - - /// - /// Creates an instruction with a 64-bit memory offset as the second operand, eg. 'mov al,[123456789ABCDEF0]' - /// - /// Code value - /// Register (al, ax, eax, rax) - /// 64-bit address - /// Segment override or - /// - public static Instruction CreateMemory64(Code code, Register register, ulong address, Register prefixSegment = Register.None) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - instruction.InternalOp1Kind = OpKind.Memory64; - instruction.MemoryAddress64 = address; - instruction.InternalSetMemoryDisplSize(4); - instruction.PrefixSegment = prefixSegment; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction with a 64-bit memory offset as the first operand, eg. 'mov [123456789ABCDEF0],al' - /// - /// Code value - /// 64-bit address - /// Register (al, ax, eax, rax) - /// Segment override or - /// - public static Instruction CreateMemory64(Code code, ulong address, Register register, Register prefixSegment = Register.None) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = OpKind.Memory64; - instruction.MemoryAddress64 = address; - instruction.InternalSetMemoryDisplSize(4); - instruction.PrefixSegment = prefixSegment; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// - public static Instruction Create(Code code, Register register) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - Debug.Assert(instruction.OpCount == 1); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Immediate - /// - public static Instruction Create(Code code, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = GetImmediateOpKind(code, 0); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 1); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Immediate - /// - public static Instruction Create(Code code, uint immediate) => - Create(code, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Memory operand - /// - public static Instruction Create(Code code, in MemoryOperand memory) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(instruction.OpCount == 1); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// - public static Instruction Create(Code code, Register register1, Register register2) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - var opKind = GetImmediateOpKind(code, 1); - instruction.InternalOp1Kind = opKind; - if (opKind == OpKind.Immediate64) - instruction.Immediate64 = (ulong)immediate; - else - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register, uint immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - var opKind = GetImmediateOpKind(code, 1); - instruction.InternalOp1Kind = opKind; - if (opKind == OpKind.Immediate64) - instruction.Immediate64 = immediate; - else - instruction.Immediate32 = immediate; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction with a 64-bit immediate value - /// - /// Code value - /// Register - /// 64-bit immediate - /// - public static Instruction Create(Code code, Register register, long immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - instruction.InternalOp1Kind = OpKind.Immediate64; - instruction.Immediate64 = (ulong)immediate; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction with a 64-bit immediate value - /// - /// Code value - /// Register - /// 64-bit immediate - /// - public static Instruction Create(Code code, Register register, ulong immediate) => - Create(code, register, (long)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Register (eg. dx, al, ax, eax, rax) - /// si, esi, or rsi - /// Segment override or - /// - public static Instruction CreateString_Reg_SegRSI(Code code, Register register, Register rSI, Register prefixSegment = Register.None) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - if (rSI == Register.RSI) - instruction.InternalOp1Kind = OpKind.MemorySegRSI; - else if (rSI == Register.ESI) - instruction.InternalOp1Kind = OpKind.MemorySegESI; - else if (rSI == Register.SI) - instruction.InternalOp1Kind = OpKind.MemorySegSI; - else - throw new ArgumentOutOfRangeException(nameof(rSI)); - - instruction.PrefixSegment = prefixSegment; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register (eg. al, ax, eax, rax) - /// di, edi, or rdi - /// - public static Instruction CreateString_Reg_ESRDI(Code code, Register register, Register rDI) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - if (rDI == Register.RDI) - instruction.InternalOp1Kind = OpKind.MemoryESRDI; - else if (rDI == Register.EDI) - instruction.InternalOp1Kind = OpKind.MemoryESEDI; - else if (rDI == Register.DI) - instruction.InternalOp1Kind = OpKind.MemoryESDI; - else - throw new ArgumentOutOfRangeException(nameof(rDI)); - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Memory operand - /// - public static Instruction Create(Code code, Register register, in MemoryOperand memory) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - instruction.InternalOp1Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Immediate - /// Register - /// - public static Instruction Create(Code code, int immediate, Register register) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = GetImmediateOpKind(code, 0); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Immediate - /// Register - /// - public static Instruction Create(Code code, uint immediate, Register register) => - Create(code, (int)immediate, register); - - /// - /// Creates an instruction - /// - /// Code value - /// Immediate - /// Second immediate - /// - public static Instruction Create(Code code, int immediate, byte immediate2) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = GetImmediateOpKind(code, 0); - instruction.Immediate32 = (uint)immediate; - - instruction.InternalOp1Kind = OpKind.Immediate8_2nd; - instruction.Immediate8_2nd = immediate2; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Immediate - /// Second immediate - /// - public static Instruction Create(Code code, uint immediate, byte immediate2) => - Create(code, (int)immediate, immediate2); - - /// - /// Creates an instruction - /// - /// Code value - /// si, esi, or rsi - /// di, edi, or rdi - /// Segment override or - /// - public static Instruction CreateString_SegRSI_ESRDI(Code code, Register rSI, Register rDI, Register prefixSegment = Register.None) { - Instruction instruction = default; - instruction.InternalCode = code; - - if (rSI == Register.RSI) - instruction.InternalOp0Kind = OpKind.MemorySegRSI; - else if (rSI == Register.ESI) - instruction.InternalOp0Kind = OpKind.MemorySegESI; - else if (rSI == Register.SI) - instruction.InternalOp0Kind = OpKind.MemorySegSI; - else - throw new ArgumentOutOfRangeException(nameof(rSI)); - - if (rDI == Register.RDI) - instruction.InternalOp1Kind = OpKind.MemoryESRDI; - else if (rDI == Register.EDI) - instruction.InternalOp1Kind = OpKind.MemoryESEDI; - else if (rDI == Register.DI) - instruction.InternalOp1Kind = OpKind.MemoryESDI; - else - throw new ArgumentOutOfRangeException(nameof(rDI)); - - instruction.PrefixSegment = prefixSegment; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// di, edi, or rdi - /// Register (eg. dx, al, ax, eax, rax) - /// - public static Instruction CreateString_ESRDI_Reg(Code code, Register rDI, Register register) { - Instruction instruction = default; - instruction.InternalCode = code; - - if (rDI == Register.RDI) - instruction.InternalOp0Kind = OpKind.MemoryESRDI; - else if (rDI == Register.EDI) - instruction.InternalOp0Kind = OpKind.MemoryESEDI; - else if (rDI == Register.DI) - instruction.InternalOp0Kind = OpKind.MemoryESDI; - else - throw new ArgumentOutOfRangeException(nameof(rDI)); - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// di, edi, or rdi - /// si, esi, or rsi - /// Segment override or - /// - public static Instruction CreateString_ESRDI_SegRSI(Code code, Register rDI, Register rSI, Register prefixSegment = Register.None) { - Instruction instruction = default; - instruction.InternalCode = code; - - if (rDI == Register.RDI) - instruction.InternalOp0Kind = OpKind.MemoryESRDI; - else if (rDI == Register.EDI) - instruction.InternalOp0Kind = OpKind.MemoryESEDI; - else if (rDI == Register.DI) - instruction.InternalOp0Kind = OpKind.MemoryESDI; - else - throw new ArgumentOutOfRangeException(nameof(rDI)); - - if (rSI == Register.RSI) - instruction.InternalOp1Kind = OpKind.MemorySegRSI; - else if (rSI == Register.ESI) - instruction.InternalOp1Kind = OpKind.MemorySegESI; - else if (rSI == Register.SI) - instruction.InternalOp1Kind = OpKind.MemorySegSI; - else - throw new ArgumentOutOfRangeException(nameof(rSI)); - - instruction.PrefixSegment = prefixSegment; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Memory operand - /// Register - /// - public static Instruction Create(Code code, in MemoryOperand memory, Register register) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Memory operand - /// Immediate - /// - public static Instruction Create(Code code, in MemoryOperand memory, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - instruction.InternalOp1Kind = GetImmediateOpKind(code, 1); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 2); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Memory operand - /// Immediate - /// - public static Instruction Create(Code code, in MemoryOperand memory, uint immediate) => - Create(code, memory, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register3; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - instruction.InternalOp2Kind = GetImmediateOpKind(code, 2); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, uint immediate) => - Create(code, register1, register2, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Memory operand - /// - public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - instruction.InternalOp2Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Immediate - /// Second immediate - /// - public static Instruction Create(Code code, Register register, int immediate, byte immediate2) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - instruction.InternalOp1Kind = GetImmediateOpKind(code, 1); - instruction.Immediate32 = (uint)immediate; - - instruction.InternalOp2Kind = OpKind.Immediate8_2nd; - instruction.Immediate8_2nd = immediate2; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Immediate - /// Second immediate - /// - public static Instruction Create(Code code, Register register, uint immediate, byte immediate2) => - Create(code, register, (int)immediate, immediate2); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Memory operand - /// Register - /// - public static Instruction Create(Code code, Register register1, in MemoryOperand memory, Register register2) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - instruction.InternalOp1Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register2; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Memory operand - /// Immediate - /// - public static Instruction Create(Code code, Register register, in MemoryOperand memory, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register; - - instruction.InternalOp1Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - instruction.InternalOp2Kind = GetImmediateOpKind(code, 2); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Memory operand - /// Immediate - /// - public static Instruction Create(Code code, Register register, in MemoryOperand memory, uint immediate) => - Create(code, register, memory, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// di, edi, or rdi - /// Register - /// Register - /// Segment override or - /// - public static Instruction CreateMaskmov_SegRDI_Reg_Reg(Code code, Register rDI, Register register1, Register register2, Register prefixSegment = Register.None) { - Instruction instruction = default; - instruction.InternalCode = code; - - if (rDI == Register.RDI) - instruction.InternalOp0Kind = OpKind.MemorySegRDI; - else if (rDI == Register.EDI) - instruction.InternalOp0Kind = OpKind.MemorySegEDI; - else if (rDI == Register.DI) - instruction.InternalOp0Kind = OpKind.MemorySegDI; - else - throw new ArgumentOutOfRangeException(nameof(rDI)); - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register2; - - instruction.PrefixSegment = prefixSegment; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Memory operand - /// Register - /// Register - /// - public static Instruction Create(Code code, in MemoryOperand memory, Register register1, Register register2) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register2; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Memory operand - /// Register - /// Immediate - /// - public static Instruction Create(Code code, in MemoryOperand memory, Register register, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - instruction.InternalOp0Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register; - - instruction.InternalOp2Kind = GetImmediateOpKind(code, 2); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 3); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Memory operand - /// Register - /// Immediate - /// - public static Instruction Create(Code code, in MemoryOperand memory, Register register, uint immediate) => - Create(code, memory, register, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// Register - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3, Register register4) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register3; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp3Kind = OpKind.Register; - instruction.InternalOp3Register = register4; - - Debug.Assert(instruction.OpCount == 4); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register3; - - instruction.InternalOp3Kind = GetImmediateOpKind(code, 3); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 4); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3, uint immediate) => - Create(code, register1, register2, register3, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// Memory operand - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3, in MemoryOperand memory) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register3; - - instruction.InternalOp3Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(instruction.OpCount == 4); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Immediate - /// Second immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, int immediate, byte immediate2) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - instruction.InternalOp2Kind = GetImmediateOpKind(code, 2); - instruction.Immediate32 = (uint)immediate; - - instruction.InternalOp3Kind = OpKind.Immediate8_2nd; - instruction.Immediate8_2nd = immediate2; - - Debug.Assert(instruction.OpCount == 4); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Immediate - /// Second immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, uint immediate, byte immediate2) => - Create(code, register1, register2, (int)immediate, immediate2); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Memory operand - /// Register - /// - public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, Register register3) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - instruction.InternalOp2Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp3Kind = OpKind.Register; - instruction.InternalOp3Register = register3; - - Debug.Assert(instruction.OpCount == 4); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Memory operand - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - instruction.InternalOp2Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - instruction.InternalOp3Kind = GetImmediateOpKind(code, 3); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 4); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Memory operand - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, uint immediate) => - Create(code, register1, register2, memory, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3, Register register4, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register3; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp3Kind = OpKind.Register; - instruction.InternalOp3Register = register4; - - instruction.InternalOp4Kind = GetImmediateOpKind(code, 4); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 5); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3, Register register4, uint immediate) => - Create(code, register1, register2, register3, register4, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// Memory operand - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3, in MemoryOperand memory, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp2Kind = OpKind.Register; - instruction.InternalOp2Register = register3; - - instruction.InternalOp3Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - instruction.InternalOp4Kind = GetImmediateOpKind(code, 4); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 5); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Register - /// Memory operand - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, Register register3, in MemoryOperand memory, uint immediate) => - Create(code, register1, register2, register3, memory, (int)immediate); - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Memory operand - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, Register register3, int immediate) { - Instruction instruction = default; - instruction.InternalCode = code; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp0Kind = OpKind.Register; - instruction.InternalOp0Register = register1; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp1Kind = OpKind.Register; - instruction.InternalOp1Register = register2; - - instruction.InternalOp2Kind = OpKind.Memory; - instruction.InternalMemoryBase = memory.Base; - instruction.InternalMemoryIndex = memory.Index; - instruction.MemoryIndexScale = memory.Scale; - instruction.MemoryDisplSize = memory.DisplSize; - instruction.MemoryDisplacement = (uint)memory.Displacement; - instruction.IsBroadcast = memory.IsBroadcast; - instruction.PrefixSegment = memory.PrefixSegment; - - Debug.Assert(OpKind.Register == 0); - //instruction.InternalOp3Kind = OpKind.Register; - instruction.InternalOp3Register = register3; - - instruction.InternalOp4Kind = GetImmediateOpKind(code, 4); - instruction.Immediate32 = (uint)immediate; - - Debug.Assert(instruction.OpCount == 5); - return instruction; - } - - /// - /// Creates an instruction - /// - /// Code value - /// Register - /// Register - /// Memory operand - /// Register - /// Immediate - /// - public static Instruction Create(Code code, Register register1, Register register2, in MemoryOperand memory, Register register3, uint immediate) => - Create(code, register1, register2, memory, register3, (int)immediate); -#endif - /// /// Formats the instruction using the default formatter with default formatter options ///