diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FabsHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FabsHandler.cs new file mode 100644 index 0000000..ba49fd4 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FabsHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FABS instruction (D9 E1) +/// +public class FabsHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FabsHandler class + /// + /// The instruction decoder that owns this handler + public FabsHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FABS is D9 E1 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is E1 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xE1; + } + + /// + /// Decodes a FABS instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Fabs; + + // FABS has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FchsHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FchsHandler.cs new file mode 100644 index 0000000..c38ce36 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FchsHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCHS instruction (D9 E0) +/// +public class FchsHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FchsHandler class + /// + /// The instruction decoder that owns this handler + public FchsHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FCHS is D9 E0 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is E0 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xE0; + } + + /// + /// Decodes a FCHS instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Fchs; + + // FCHS has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FiaddInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FiaddInt32Handler.cs new file mode 100644 index 0000000..bef0536 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FiaddInt32Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIADD int32 instruction (DA /0) +/// +public class FiaddInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FiaddInt32Handler class + /// + /// The instruction decoder that owns this handler + public FiaddInt32Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FIADD is DA /0 + if (opcode != 0xDA) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 0 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 0 && mod != 3; + } + + /// + /// Decodes a FIADD int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fiadd; + + // Set the structured operands - the operand already has the correct size from ReadModRM + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivInt32Handler.cs new file mode 100644 index 0000000..f1bf779 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivInt32Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIDIV int32 instruction (DA /6) +/// +public class FidivInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FidivInt32Handler class + /// + /// The instruction decoder that owns this handler + public FidivInt32Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FIDIV is DA /6 + if (opcode != 0xDA) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 6 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 6 && mod != 3; + } + + /// + /// Decodes a FIDIV int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fidiv; + + // Set the structured operands - the operand already has the correct size from ReadModRM + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivrInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivrInt32Handler.cs new file mode 100644 index 0000000..d669886 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivrInt32Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIDIVR int32 instruction (DA /7) +/// +public class FidivrInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FidivrInt32Handler class + /// + /// The instruction decoder that owns this handler + public FidivrInt32Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FIDIVR is DA /7 + if (opcode != 0xDA) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 7 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 7 && mod != 3; + } + + /// + /// Decodes a FIDIVR int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fidivr; + + // Set the structured operands - the operand already has the correct size from ReadModRM + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FimulInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FimulInt32Handler.cs new file mode 100644 index 0000000..4d230eb --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FimulInt32Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIMUL int32 instruction (DA /1) +/// +public class FimulInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FimulInt32Handler class + /// + /// The instruction decoder that owns this handler + public FimulInt32Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FIMUL is DA /1 + if (opcode != 0xDA) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 1 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 1 && mod != 3; + } + + /// + /// Decodes a FIMUL int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fimul; + + // Set the structured operands - the operand already has the correct size from ReadModRM + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubInt32Handler.cs new file mode 100644 index 0000000..7775897 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubInt32Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FISUB int32 instruction (DA /4) +/// +public class FisubInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FisubInt32Handler class + /// + /// The instruction decoder that owns this handler + public FisubInt32Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FISUB is DA /4 + if (opcode != 0xDA) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 4 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 4 && mod != 3; + } + + /// + /// Decodes a FISUB int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fisub; + + // Set the structured operands - the operand already has the correct size from ReadModRM + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubrInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubrInt32Handler.cs new file mode 100644 index 0000000..d6906b3 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubrInt32Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FISUBR int32 instruction (DA /5) +/// +public class FisubrInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FisubrInt32Handler class + /// + /// The instruction decoder that owns this handler + public FisubrInt32Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FISUBR is DA /5 + if (opcode != 0xDA) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 5 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 5 && mod != 3; + } + + /// + /// Decodes a FISUBR int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fisubr; + + // Set the structured operands - the operand already has the correct size from ReadModRM + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicomInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicomInt32Handler.cs new file mode 100644 index 0000000..a3a106f --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicomInt32Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FICOM int32 instruction (DA /2) +/// +public class FicomInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FicomInt32Handler class + /// + /// The instruction decoder that owns this handler + public FicomInt32Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FICOM is DA /2 + if (opcode != 0xDA) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 2 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 2 && mod != 3; + } + + /// + /// Decodes a FICOM int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Ficom; + + // Set the structured operands - the operand already has the correct size from ReadModRM + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicompInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicompInt32Handler.cs new file mode 100644 index 0000000..c426ba6 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicompInt32Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FICOMP int32 instruction (DA /3) +/// +public class FicompInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FicompInt32Handler class + /// + /// The instruction decoder that owns this handler + public FicompInt32Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FICOMP is DA /3 + if (opcode != 0xDA) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 3 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 3 && mod != 3; + } + + /// + /// Decodes a FICOMP int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Ficomp; + + // Set the structured operands - the operand already has the correct size from ReadModRM + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FtstHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FtstHandler.cs new file mode 100644 index 0000000..8a0fc1d --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FtstHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FTST instruction (D9 E4) +/// +public class FtstHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FtstHandler class + /// + /// The instruction decoder that owns this handler + public FtstHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FTST is D9 E4 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is E4 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xE4; + } + + /// + /// Decodes a FTST instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Ftst; + + // FTST has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FldcwHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FldcwHandler.cs new file mode 100644 index 0000000..bc26c27 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FldcwHandler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FLDCW instruction (D9 /5) +/// +public class FldcwHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FldcwHandler class + /// + /// The instruction decoder that owns this handler + public FldcwHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FLDCW is D9 /5 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 5 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 5 && mod != 3; + } + + /// + /// Decodes a FLDCW instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fldcw; + + // Create a 16-bit memory operand for control word operations + Operand memoryOperand; + + if (rawOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand16(directMemory.Address); + } + else if (rawOperand is BaseRegisterMemoryOperand baseRegMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand16(baseRegMemory.BaseRegister); + } + else if (rawOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand16(dispMemory.BaseRegister, dispMemory.Displacement); + } + else if (rawOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand16(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement); + } + else + { + memoryOperand = rawOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FldenvHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FldenvHandler.cs new file mode 100644 index 0000000..0eb329f --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FldenvHandler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FLDENV instruction (D9 /4) +/// +public class FldenvHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FldenvHandler class + /// + /// The instruction decoder that owns this handler + public FldenvHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FLDENV is D9 /4 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 4 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 4 && mod != 3; + } + + /// + /// Decodes a FLDENV instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fldenv; + + // Set the structured operands + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstcwHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstcwHandler.cs new file mode 100644 index 0000000..e520bdb --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstcwHandler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FNSTCW instruction (D9 /7) +/// +public class FnstcwHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FnstcwHandler class + /// + /// The instruction decoder that owns this handler + public FnstcwHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FNSTCW is D9 /7 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 7 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 7 && mod != 3; + } + + /// + /// Decodes a FNSTCW instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fnstcw; + + // Create a 16-bit memory operand for control word operations + Operand memoryOperand; + + if (rawOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand16(directMemory.Address); + } + else if (rawOperand is BaseRegisterMemoryOperand baseRegMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand16(baseRegMemory.BaseRegister); + } + else if (rawOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand16(dispMemory.BaseRegister, dispMemory.Displacement); + } + else if (rawOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand16(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement); + } + else + { + memoryOperand = rawOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstenvHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstenvHandler.cs new file mode 100644 index 0000000..567c71b --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstenvHandler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FNSTENV instruction (D9 /6) +/// +public class FnstenvHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FnstenvHandler class + /// + /// The instruction decoder that owns this handler + public FnstenvHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FNSTENV is D9 /6 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 6 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 6 && mod != 3; + } + + /// + /// Decodes a FNSTENV instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fnstenv; + + // Set the structured operands + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FxamHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FxamHandler.cs new file mode 100644 index 0000000..5009d8a --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FxamHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FXAM instruction (D9 E5) +/// +public class FxamHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FxamHandler class + /// + /// The instruction decoder that owns this handler + public FxamHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FXAM is D9 E5 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is E5 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xE5; + } + + /// + /// Decodes a FXAM instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Fxam; + + // FXAM has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FxchHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FxchHandler.cs new file mode 100644 index 0000000..816ee12 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FxchHandler.cs @@ -0,0 +1,87 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FXCH instruction (D9 /1 with mod=3) +/// +public class FxchHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FxchHandler class + /// + /// The instruction decoder that owns this handler + public FxchHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FXCH is D9 /1 with mod=3 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 1 and mod = 3 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle register operands (mod = 3) with reg = 1 + return reg == 1 && mod == 3; + } + + /// + /// Decodes a FXCH instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fxch; + + // Map rm field to FPU register index + FpuRegisterIndex stIndex = rm switch + { + RegisterIndex.A => FpuRegisterIndex.ST0, + RegisterIndex.C => FpuRegisterIndex.ST1, + RegisterIndex.D => FpuRegisterIndex.ST2, + RegisterIndex.B => FpuRegisterIndex.ST3, + RegisterIndex.Sp => FpuRegisterIndex.ST4, + RegisterIndex.Bp => FpuRegisterIndex.ST5, + RegisterIndex.Si => FpuRegisterIndex.ST6, + RegisterIndex.Di => FpuRegisterIndex.ST7, + _ => FpuRegisterIndex.ST0 // Default case, should not happen + }; + + // Create the FPU register operand + var operand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + operand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/F2xm1Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/F2xm1Handler.cs new file mode 100644 index 0000000..c523974 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/F2xm1Handler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Transcendental; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for F2XM1 instruction (D9 F0) +/// +public class F2xm1Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the F2xm1Handler class + /// + /// The instruction decoder that owns this handler + public F2xm1Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // F2XM1 is D9 F0 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is F0 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xF0; + } + + /// + /// Decodes a F2XM1 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.F2xm1; + + // F2XM1 has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/FpatanHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/FpatanHandler.cs new file mode 100644 index 0000000..3274c6e --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/FpatanHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Transcendental; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FPATAN instruction (D9 F3) +/// +public class FpatanHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FpatanHandler class + /// + /// The instruction decoder that owns this handler + public FpatanHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FPATAN is D9 F3 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is F3 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xF3; + } + + /// + /// Decodes a FPATAN instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Fpatan; + + // FPATAN has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/FptanHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/FptanHandler.cs new file mode 100644 index 0000000..7cc6989 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/FptanHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Transcendental; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FPTAN instruction (D9 F2) +/// +public class FptanHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FptanHandler class + /// + /// The instruction decoder that owns this handler + public FptanHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FPTAN is D9 F2 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is F2 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xF2; + } + + /// + /// Decodes a FPTAN instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Fptan; + + // FPTAN has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/Fyl2xHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/Fyl2xHandler.cs new file mode 100644 index 0000000..4d47720 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Transcendental/Fyl2xHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Transcendental; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FYL2X instruction (D9 F1) +/// +public class Fyl2xHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the Fyl2xHandler class + /// + /// The instruction decoder that owns this handler + public Fyl2xHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FYL2X is D9 F1 + if (opcode != 0xD9) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is F1 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xF1; + } + + /// + /// Decodes a FYL2X instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Fyl2x; + + // FYL2X has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 16437ac..1fbe786 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -389,6 +389,20 @@ public class InstructionHandlerFactory _handlers.Add(new FloatingPoint.LoadStore.FldFloat32Handler(_decoder)); // FLD float32 (D9 /0) _handlers.Add(new FloatingPoint.LoadStore.FstFloat32Handler(_decoder)); // FST float32 (D9 /2) _handlers.Add(new FloatingPoint.LoadStore.FstpFloat32Handler(_decoder)); // FSTP float32 (D9 /3) + _handlers.Add(new FloatingPoint.Control.FldenvHandler(_decoder)); // FLDENV (D9 /4) + _handlers.Add(new FloatingPoint.Control.FldcwHandler(_decoder)); // FLDCW (D9 /5) + _handlers.Add(new FloatingPoint.Control.FnstenvHandler(_decoder)); // FNSTENV (D9 /6) + _handlers.Add(new FloatingPoint.Control.FnstcwHandler(_decoder)); // FNSTCW (D9 /7) + + // DA opcode handlers (int32 operations) + _handlers.Add(new FloatingPoint.Arithmetic.FiaddInt32Handler(_decoder)); // FIADD int32 (DA /0) + _handlers.Add(new FloatingPoint.Arithmetic.FimulInt32Handler(_decoder)); // FIMUL int32 (DA /1) + _handlers.Add(new FloatingPoint.Comparison.FicomInt32Handler(_decoder)); // FICOM int32 (DA /2) + _handlers.Add(new FloatingPoint.Comparison.FicompInt32Handler(_decoder)); // FICOMP int32 (DA /3) + _handlers.Add(new FloatingPoint.Arithmetic.FisubInt32Handler(_decoder)); // FISUB int32 (DA /4) + _handlers.Add(new FloatingPoint.Arithmetic.FisubrInt32Handler(_decoder)); // FISUBR int32 (DA /5) + _handlers.Add(new FloatingPoint.Arithmetic.FidivInt32Handler(_decoder)); // FIDIV int32 (DA /6) + _handlers.Add(new FloatingPoint.Arithmetic.FidivrInt32Handler(_decoder)); // FIDIVR int32 (DA /7) // DC opcode handlers (float64 operations) _handlers.Add(new FloatingPoint.Arithmetic.FaddFloat64Handler(_decoder)); // FADD float64 (DC /0) @@ -405,12 +419,25 @@ public class InstructionHandlerFactory _handlers.Add(new FloatingPoint.LoadStore.FstFloat64Handler(_decoder)); // FST float64 (DD /2) _handlers.Add(new FloatingPoint.LoadStore.FstpFloat64Handler(_decoder)); // FSTP float64 (DD /3) + // Register-register operations + _handlers.Add(new FloatingPoint.Control.FxchHandler(_decoder)); // FXCH (D9 C8-CF) + + // Special floating point instructions + _handlers.Add(new FloatingPoint.Arithmetic.FchsHandler(_decoder)); // FCHS (D9 E0) + _handlers.Add(new FloatingPoint.Arithmetic.FabsHandler(_decoder)); // FABS (D9 E1) + _handlers.Add(new FloatingPoint.Comparison.FtstHandler(_decoder)); // FTST (D9 E4) + _handlers.Add(new FloatingPoint.Control.FxamHandler(_decoder)); // FXAM (D9 E5) + + // Transcendental functions + _handlers.Add(new FloatingPoint.Transcendental.F2xm1Handler(_decoder)); // F2XM1 (D9 F0) + _handlers.Add(new FloatingPoint.Transcendental.Fyl2xHandler(_decoder)); // FYL2X (D9 F1) + _handlers.Add(new FloatingPoint.Transcendental.FptanHandler(_decoder)); // FPTAN (D9 F2) + _handlers.Add(new FloatingPoint.Transcendental.FpatanHandler(_decoder)); // FPATAN (D9 F3) + // Other floating point handlers - _handlers.Add(new FloatingPoint.Control.FnstswHandler(_decoder)); // FNSTSW AX (DF E0) + _handlers.Add(new FloatingPoint.Control.FnstswHandler(_decoder)); // FNSTSW AX (DF E0) // Keep the existing handlers for operations not yet migrated to specialized handlers - _handlers.Add(new LoadStoreControlHandler(_decoder)); // Load and store control words (D9 /4-/7) - _handlers.Add(new Int32OperationHandler(_decoder)); // Integer operations on 32-bit values _handlers.Add(new LoadStoreInt32Handler(_decoder)); // Load and store 32-bit values _handlers.Add(new Float64OperationHandler(_decoder)); // Remaining float64 operations _handlers.Add(new LoadStoreFloat64Handler(_decoder)); // Load and store 64-bit values