diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FaddFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FaddFloat32Handler.cs
new file mode 100644
index 0000000..cb8e4bf
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FaddFloat32Handler.cs
@@ -0,0 +1,91 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FADD float32 instruction (D8 /0)
+///
+public class FaddFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FaddFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FaddFloat32Handler(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)
+ {
+ // FADD is D8 /0
+ if (opcode != 0xD8) 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);
+
+ return reg == 0;
+ }
+
+ ///
+ /// Decodes a FADD float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Verify reg field is 0 (FADD)
+ if (reg != 0)
+ {
+ return false;
+ }
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fadd;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands, we need to handle the stack registers
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ st0Operand,
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FaddFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FaddFloat64Handler.cs
new file mode 100644
index 0000000..1b76431
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FaddFloat64Handler.cs
@@ -0,0 +1,91 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FADD float64 instruction (DC /0)
+///
+public class FaddFloat64Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FaddFloat64Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FaddFloat64Handler(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)
+ {
+ // FADD is DC /0
+ if (opcode != 0xDC) 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);
+
+ return reg == 0;
+ }
+
+ ///
+ /// Decodes a FADD float64 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Verify reg field is 0 (FADD)
+ if (reg != 0)
+ {
+ return false;
+ }
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fadd;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM64
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For DC C0-DC FF, the operands are reversed: ST(i), ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ stiOperand,
+ st0Operand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FcomFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FcomFloat32Handler.cs
new file mode 100644
index 0000000..f3da079
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FcomFloat32Handler.cs
@@ -0,0 +1,85 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FCOM float32 instruction (D8 /2)
+///
+public class FcomFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FcomFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FcomFloat32Handler(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)
+ {
+ // FCOM is D8 /2
+ if (opcode != 0xD8) 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);
+
+ return reg == 2;
+ }
+
+ ///
+ /// Decodes a FCOM float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fcom;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands, we need to handle the stack registers
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ st0Operand,
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FcompFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FcompFloat32Handler.cs
new file mode 100644
index 0000000..8108dbf
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FcompFloat32Handler.cs
@@ -0,0 +1,85 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FCOMP float32 instruction (D8 /3)
+///
+public class FcompFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FcompFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FcompFloat32Handler(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)
+ {
+ // FCOMP is D8 /3
+ if (opcode != 0xD8) 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);
+
+ return reg == 3;
+ }
+
+ ///
+ /// Decodes a FCOMP float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fcomp;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands, we need to handle the stack registers
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ st0Operand,
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FdivFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FdivFloat32Handler.cs
new file mode 100644
index 0000000..f8580a0
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FdivFloat32Handler.cs
@@ -0,0 +1,85 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FDIV float32 instruction (D8 /6)
+///
+public class FdivFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FdivFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FdivFloat32Handler(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)
+ {
+ // FDIV is D8 /6
+ if (opcode != 0xD8) 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);
+
+ return reg == 6;
+ }
+
+ ///
+ /// Decodes a FDIV float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fdiv;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands, we need to handle the stack registers
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ st0Operand,
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FdivrFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FdivrFloat32Handler.cs
new file mode 100644
index 0000000..7c77ca1
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FdivrFloat32Handler.cs
@@ -0,0 +1,85 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FDIVR float32 instruction (D8 /7)
+///
+public class FdivrFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FdivrFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FdivrFloat32Handler(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)
+ {
+ // FDIVR is D8 /7
+ if (opcode != 0xD8) 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);
+
+ return reg == 7;
+ }
+
+ ///
+ /// Decodes a FDIVR float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fdivr;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands, we need to handle the stack registers
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ st0Operand,
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FldFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FldFloat32Handler.cs
new file mode 100644
index 0000000..5cf7279
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FldFloat32Handler.cs
@@ -0,0 +1,89 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FLD float32 instruction (D9 /0)
+///
+public class FldFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FldFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FldFloat32Handler(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)
+ {
+ // FLD is D9 /0
+ if (opcode != 0xD9) 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);
+
+ return reg == 0;
+ }
+
+ ///
+ /// Decodes an FLD float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Verify reg field is 0 (FLD)
+ if (reg != 0)
+ {
+ return false;
+ }
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fld;
+
+ // Handle based on addressing mode
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands with mod=3, this is FLD ST(i)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FmulFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FmulFloat32Handler.cs
new file mode 100644
index 0000000..f41225d
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FmulFloat32Handler.cs
@@ -0,0 +1,87 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FMUL float32 instruction (D8 /1)
+///
+public class FmulFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FmulFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FmulFloat32Handler(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)
+ {
+ // FMUL is D8 /1
+ if (opcode != 0xD8) 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);
+
+ return reg == 1;
+ }
+
+ ///
+ /// Decodes a FMUL float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fmul;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands, we need to handle the stack registers
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ st0Operand,
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FmulFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FmulFloat64Handler.cs
new file mode 100644
index 0000000..47dd396
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FmulFloat64Handler.cs
@@ -0,0 +1,85 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FMUL float64 instruction (DC /1)
+///
+public class FmulFloat64Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FmulFloat64Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FmulFloat64Handler(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)
+ {
+ // FMUL is DC /1
+ if (opcode != 0xDC) 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);
+
+ return reg == 1;
+ }
+
+ ///
+ /// Decodes a FMUL float64 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fmul;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM64
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For DC C0-DC FF, the operands are reversed: ST(i), ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ stiOperand,
+ st0Operand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FstFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FstFloat32Handler.cs
new file mode 100644
index 0000000..a8a29f6
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FstFloat32Handler.cs
@@ -0,0 +1,83 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FST float32 instruction (D9 /2)
+///
+public class FstFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FstFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FstFloat32Handler(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)
+ {
+ // FST is D9 /2
+ if (opcode != 0xD9) 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);
+
+ return reg == 2;
+ }
+
+ ///
+ /// Decodes an FST float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fst;
+
+ // Handle based on addressing mode
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands with mod=3, this is FST ST(i)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FstpFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FstpFloat32Handler.cs
new file mode 100644
index 0000000..36604f9
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FstpFloat32Handler.cs
@@ -0,0 +1,83 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FSTP float32 instruction (D9 /3)
+///
+public class FstpFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FstpFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FstpFloat32Handler(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)
+ {
+ // FSTP is D9 /3
+ if (opcode != 0xD9) 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);
+
+ return reg == 3;
+ }
+
+ ///
+ /// Decodes an FSTP float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fstp;
+
+ // Handle based on addressing mode
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands with mod=3, this is FSTP ST(i)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FsubFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FsubFloat32Handler.cs
new file mode 100644
index 0000000..1ba621e
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FsubFloat32Handler.cs
@@ -0,0 +1,85 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FSUB float32 instruction (D8 /4)
+///
+public class FsubFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FsubFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FsubFloat32Handler(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)
+ {
+ // FSUB is D8 /4
+ if (opcode != 0xD8) 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);
+
+ return reg == 4;
+ }
+
+ ///
+ /// Decodes a FSUB float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fsub;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands, we need to handle the stack registers
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ st0Operand,
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/FsubrFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/FsubrFloat32Handler.cs
new file mode 100644
index 0000000..3b348b8
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/FloatingPoint/FsubrFloat32Handler.cs
@@ -0,0 +1,85 @@
+namespace X86Disassembler.X86.Handlers.FloatingPoint;
+
+using Operands;
+
+///
+/// Handler for FSUBR float32 instruction (D8 /5)
+///
+public class FsubrFloat32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the FsubrFloat32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public FsubrFloat32Handler(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)
+ {
+ // FSUBR is D8 /5
+ if (opcode != 0xD8) 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);
+
+ return reg == 5;
+ }
+
+ ///
+ /// Decodes a FSUBR float32 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 using the specialized FPU method
+ var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu();
+
+ // Set the instruction type
+ instruction.Type = InstructionType.Fsubr;
+
+ // For memory operands, set the operand
+ if (mod != 3) // Memory operand
+ {
+ // Set the structured operands - the operand already has the correct size from ReadModRM
+ instruction.StructuredOperands =
+ [
+ rawOperand
+ ];
+ }
+ else // Register operand (ST(i))
+ {
+ // For register operands, we need to handle the stack registers
+ var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); // ST(0)
+ var stiOperand = OperandFactory.CreateFPURegisterOperand(fpuRm); // ST(i)
+
+ // Set the structured operands
+ instruction.StructuredOperands =
+ [
+ st0Operand,
+ stiOperand
+ ];
+ }
+
+ return true;
+ }
+}
diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
index 8a727a1..e5aa28a 100644
--- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
+++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
@@ -373,16 +373,38 @@ public class InstructionHandlerFactory
///
private void RegisterFloatingPointHandlers()
{
- // Add Floating Point handlers
- _handlers.Add(new FnstswHandler(_decoder)); // FSTSW (opcode DF /7)
- _handlers.Add(new Float32OperationHandler(_decoder)); // Floating Point operations on 32-bit values
- _handlers.Add(new LoadStoreControlHandler(_decoder)); // Load and store control words (opcode D9 /0)
- _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)); // Floating Point operations on 64-bit values
+ // Add specialized Floating Point handlers
+
+ // D8 opcode handlers (float32 operations)
+ _handlers.Add(new FaddFloat32Handler(_decoder)); // FADD float32 (D8 /0)
+ _handlers.Add(new FmulFloat32Handler(_decoder)); // FMUL float32 (D8 /1)
+ _handlers.Add(new FcomFloat32Handler(_decoder)); // FCOM float32 (D8 /2)
+ _handlers.Add(new FcompFloat32Handler(_decoder)); // FCOMP float32 (D8 /3)
+ _handlers.Add(new FsubFloat32Handler(_decoder)); // FSUB float32 (D8 /4)
+ _handlers.Add(new FsubrFloat32Handler(_decoder)); // FSUBR float32 (D8 /5)
+ _handlers.Add(new FdivFloat32Handler(_decoder)); // FDIV float32 (D8 /6)
+ _handlers.Add(new FdivrFloat32Handler(_decoder)); // FDIVR float32 (D8 /7)
+
+ // D9 opcode handlers (load/store float32 and control operations)
+ _handlers.Add(new FldFloat32Handler(_decoder)); // FLD float32 (D9 /0)
+ _handlers.Add(new FstFloat32Handler(_decoder)); // FST float32 (D9 /2)
+ _handlers.Add(new FstpFloat32Handler(_decoder)); // FSTP float32 (D9 /3)
+
+ // DC opcode handlers (float64 operations)
+ _handlers.Add(new FaddFloat64Handler(_decoder)); // FADD float64 (DC /0)
+ _handlers.Add(new FmulFloat64Handler(_decoder)); // FMUL float64 (DC /1)
+
+ // Other floating point handlers
+ _handlers.Add(new 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
- _handlers.Add(new Int16OperationHandler(_decoder)); // Integer operations on 16-bit values
- _handlers.Add(new LoadStoreInt16Handler(_decoder)); // Load and store 16-bit values
+ _handlers.Add(new Int16OperationHandler(_decoder)); // Integer operations on 16-bit values
+ _handlers.Add(new LoadStoreInt16Handler(_decoder)); // Load and store 16-bit values
}
///
diff --git a/X86Disassembler/X86/ModRMDecoder.cs b/X86Disassembler/X86/ModRMDecoder.cs
index 66ca3bb..6c85c65 100644
--- a/X86Disassembler/X86/ModRMDecoder.cs
+++ b/X86Disassembler/X86/ModRMDecoder.cs
@@ -205,6 +205,20 @@ public class ModRMDecoder
///
/// A tuple containing the mod, reg, rm fields and the decoded operand
public (byte mod, RegisterIndex reg, RegisterIndex rm, Operand operand) ReadModRM64() => ReadModRMInternal(true);
+
+ ///
+ /// Reads and decodes a ModR/M byte for FPU instructions
+ ///
+ /// A tuple containing the mod, reg, rm fields (with rm as FpuRegisterIndex) and the decoded operand
+ public (byte mod, RegisterIndex reg, FpuRegisterIndex fpuRm, Operand operand) ReadModRMFpu()
+ {
+ var (mod, reg, rm, operand) = ReadModRMInternal(false);
+
+ // Convert the RegisterIndex rm to FpuRegisterIndex
+ FpuRegisterIndex fpuRm = (FpuRegisterIndex)(int)rm;
+
+ return (mod, reg, fpuRm, operand);
+ }
///
/// Reads and decodes a ModR/M byte for 8-bit operands