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