diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddFloat32Handler.cs index f06c842..5da574e 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddFloat32Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddFloat32Handler.cs @@ -31,11 +31,13 @@ public class FaddFloat32Handler : InstructionHandler return false; } - // Check if the ModR/M byte has reg field = 0 + // Check if the ModR/M byte has reg field = 0 and mod != 3 (memory operand) byte modRm = Decoder.PeakByte(); byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); - return reg == 0; + // Only handle memory operands (mod != 3) with reg = 0 + return reg == 0 && mod != 3; } /// @@ -51,40 +53,20 @@ public class FaddFloat32Handler : InstructionHandler return false; } - // Read the ModR/M byte using the specialized FPU method + // Read the ModR/M byte using the specialized FPU method for 32-bit operands var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu(); - - // Verify reg field is 0 (FADD) - if (reg != 0) - { - return false; - } + + // We've already verified reg field is 0 (FADD) in CanHandle + // and we only handle memory operands (mod != 3) // 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 - ]; - } + // Set the structured operands - the operand already has the correct size from ReadModRMFpu + instruction.StructuredOperands = + [ + rawOperand + ]; return true; } diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddFloat64Handler.cs index 9830693..d25ee24 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddFloat64Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddFloat64Handler.cs @@ -31,11 +31,13 @@ public class FaddFloat64Handler : InstructionHandler return false; } - // Check if the ModR/M byte has reg field = 0 + // Check if the ModR/M byte has reg field = 0 and mod != 3 (memory operand) byte modRm = Decoder.PeakByte(); byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); - return reg == 0; + // Only handle memory operands (mod != 3) with reg = 0 + return reg == 0 && mod != 3; } /// @@ -54,37 +56,17 @@ public class FaddFloat64Handler : InstructionHandler // Read the ModR/M byte using the specialized FPU method for 64-bit operands var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu64(); - // Verify reg field is 0 (FADD) - if (reg != 0) - { - return false; - } + // We've already verified reg field is 0 (FADD) in CanHandle + // and we only handle memory operands (mod != 3) // 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 - ]; - } + // Set the structured operands - the operand already has the correct size from ReadModRMFpu64 + instruction.StructuredOperands = + [ + rawOperand + ]; return true; } diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddStStiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddStStiHandler.cs new file mode 100644 index 0000000..2de17a4 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddStStiHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FADD ST, ST(i) instruction (D8 C0-C7) +/// +public class FaddStStiHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FaddStStHandler class + /// + /// The instruction decoder that owns this handler + public FaddStStiHandler(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 ST, ST(i) is D8 C0-C7 + if (opcode != 0xD8) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); + + // Only handle C0-C7 + return secondOpcode is >= 0xC0 and <= 0xC7; + } + + /// + /// Decodes a FADD ST, ST(i) 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 and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xC0); + + // Set the instruction type + instruction.Type = InstructionType.Fadd; + + // Create the FPU register operands + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + var stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + st0Operand, + stiOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddStiStHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddStiStHandler.cs new file mode 100644 index 0000000..c706435 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddStiStHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FADD ST(i), ST instruction (DC C0-C7) +/// +public class FaddStiStHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FaddStiStHandler class + /// + /// The instruction decoder that owns this handler + public FaddStiStHandler(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 ST(i), ST is DC C0-C7 + if (opcode != 0xDC) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); + + // Only handle C0-C7 + return secondOpcode is >= 0xC0 and <= 0xC7; + } + + /// + /// Decodes a FADD ST(i), ST 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 and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xC0); + + // Set the instruction type + instruction.Type = InstructionType.Fadd; + + // Create the FPU register operands + var stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + stiOperand, + st0Operand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddpHandler.cs deleted file mode 100644 index 5c046e5..0000000 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddpHandler.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; - -using X86Disassembler.X86.Operands; - -/// -/// Handler for FADDP ST(i), ST(0) instruction (DE C0-C7) -/// -public class FaddpHandler : InstructionHandler -{ - /// - /// Initializes a new instance of the FaddpHandler class - /// - /// The instruction decoder that owns this handler - public FaddpHandler(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) - { - // FADDP ST(i), ST(0) is DE C0-C7 - if (opcode != 0xDE) return false; - - if (!Decoder.CanReadByte()) - { - return false; - } - - // Check if the ModR/M byte has reg field = 0 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 = 0 - return reg == 0 && mod == 3; - } - - /// - /// Decodes a FADDP ST(i), ST(0) 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.Faddp; - - // 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 operands - var destOperand = OperandFactory.CreateFPURegisterOperand(stIndex); - var srcOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); - - // Set the structured operands - instruction.StructuredOperands = - [ - destOperand, - srcOperand - ]; - - return true; - } -} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivFloat64Handler.cs index 28ca789..0c1747d 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivFloat64Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivFloat64Handler.cs @@ -31,11 +31,13 @@ public class FdivFloat64Handler : InstructionHandler return false; } - // Check if the ModR/M byte has reg field = 6 + // Check if the ModR/M byte has reg field = 6 and mod != 3 (memory operand) byte modRm = Decoder.PeakByte(); byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); - return reg == 6; + // Only handle memory operands (mod != 3) with reg = 6 + return reg == 6 && mod != 3; } /// @@ -51,34 +53,20 @@ public class FdivFloat64Handler : InstructionHandler return false; } - // Read the ModR/M byte using the specialized FPU method + // Read the ModR/M byte using the specialized FPU method for 64-bit operands var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu64(); + // We've already verified reg field is 6 (FDIV) in CanHandle + // and we only handle memory operands (mod != 3) + // 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 DC F0-DC F7, 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 - ]; - } + // Set the structured operands - the operand already has the correct size from ReadModRMFpu64 + instruction.StructuredOperands = + [ + rawOperand + ]; return true; } diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivStStiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivStStiHandler.cs new file mode 100644 index 0000000..df46f06 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivStStiHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FDIV ST, ST(i) instruction (D8 F0-F7) +/// +public class FdivStStiHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FdivStStHandler class + /// + /// The instruction decoder that owns this handler + public FdivStStiHandler(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 ST, ST(i) is D8 F0-F7 + if (opcode != 0xD8) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); + + // Only handle F0-F7 + return secondOpcode is >= 0xF0 and <= 0xF7; + } + + /// + /// Decodes a FDIV ST, ST(i) 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 and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xF0); + + // Set the instruction type + instruction.Type = InstructionType.Fdiv; + + // Create the FPU register operands + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + var stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + st0Operand, + stiOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivStiStHandler.cs similarity index 85% rename from X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs rename to X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivStiStHandler.cs index 295c875..6d822a4 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivStiStHandler.cs @@ -3,15 +3,15 @@ namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; using X86Disassembler.X86.Operands; /// -/// Handler for FDIV ST(i), ST(0) instruction (DC F0-F7) +/// Handler for FDIV ST(i), ST instruction (DC F0-F7) /// -public class FdivRegisterHandler : InstructionHandler +public class FdivStiStHandler : InstructionHandler { /// - /// Initializes a new instance of the FdivRegisterHandler class + /// Initializes a new instance of the FdivStiStHandler class /// /// The instruction decoder that owns this handler - public FdivRegisterHandler(InstructionDecoder decoder) + public FdivStiStHandler(InstructionDecoder decoder) : base(decoder) { } @@ -23,7 +23,7 @@ public class FdivRegisterHandler : InstructionHandler /// True if this handler can decode the opcode public override bool CanHandle(byte opcode) { - // FDIV ST(i), ST(0) is DC F0-F7 + // FDIV ST(i), ST is DC F0-F7 if (opcode != 0xDC) return false; if (!Decoder.CanReadByte()) @@ -39,7 +39,7 @@ public class FdivRegisterHandler : InstructionHandler } /// - /// Decodes a FDIV ST(i), ST(0) instruction + /// Decodes a FDIV ST(i), ST instruction /// /// The opcode of the instruction /// The instruction object to populate diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpHandler.cs deleted file mode 100644 index dfea862..0000000 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpHandler.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; - -using X86Disassembler.X86.Operands; - -/// -/// Handler for FDIVP ST(i), ST(0) instruction (DE F0-F7) -/// -public class FdivpHandler : InstructionHandler -{ - /// - /// Initializes a new instance of the FdivpHandler class - /// - /// The instruction decoder that owns this handler - public FdivpHandler(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) - { - // FDIVP ST(i), ST(0) is DE F0-F7 - if (opcode != 0xDE) return false; - - if (!Decoder.CanReadByte()) - { - return false; - } - - // Check if the ModR/M byte has reg field = 6 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 = 6 - return reg == 6 && mod == 3; - } - - /// - /// Decodes a FDIVP ST(i), ST(0) 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.Fdivp; - - // 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 operands - var destOperand = OperandFactory.CreateFPURegisterOperand(stIndex); - var srcOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); - - // Set the structured operands - instruction.StructuredOperands = - [ - destOperand, - srcOperand - ]; - - return true; - } -} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrFloat64Handler.cs index 78e7156..762a956 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrFloat64Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrFloat64Handler.cs @@ -31,11 +31,13 @@ public class FdivrFloat64Handler : InstructionHandler return false; } - // Check if the ModR/M byte has reg field = 7 + // Check if the ModR/M byte has reg field = 7 and mod != 3 (memory operand) byte modRm = Decoder.PeakByte(); byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); - return reg == 7; + // Only handle memory operands (mod != 3) with reg = 7 + return reg == 7 && mod != 3; } /// @@ -51,34 +53,20 @@ public class FdivrFloat64Handler : InstructionHandler return false; } - // Read the ModR/M byte using the specialized FPU method + // Read the ModR/M byte using the specialized FPU method for 64-bit operands var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu64(); + // We've already verified reg field is 7 (FDIVR) in CanHandle + // and we only handle memory operands (mod != 3) + // 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 DC F8-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 - ]; - } + // Set the structured operands - the operand already has the correct size from ReadModRMFpu64 + instruction.StructuredOperands = + [ + rawOperand + ]; return true; } diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrStStiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrStStiHandler.cs new file mode 100644 index 0000000..6868b11 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrStStiHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FDIVR ST, ST(i) instruction (D8 F8-FF) +/// +public class FdivrStStiHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FdivrStStHandler class + /// + /// The instruction decoder that owns this handler + public FdivrStStiHandler(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 ST, ST(i) is D8 F8-FF + if (opcode != 0xD8) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); + + // Only handle F8-FF + return secondOpcode is >= 0xF8 and <= 0xFF; + } + + /// + /// Decodes a FDIVR ST, ST(i) 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 and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xF8); + + // Set the instruction type + instruction.Type = InstructionType.Fdivr; + + // Create the FPU register operands + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + var stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + st0Operand, + stiOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrStiStHandler.cs similarity index 85% rename from X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrRegisterHandler.cs rename to X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrStiStHandler.cs index 510cd13..845d1d0 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrStiStHandler.cs @@ -3,15 +3,15 @@ namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; using X86Disassembler.X86.Operands; /// -/// Handler for FDIVR ST(i), ST(0) instruction (DC F8-FF) +/// Handler for FDIVR ST(i), ST instruction (DC F8-FF) /// -public class FdivrRegisterHandler : InstructionHandler +public class FdivrStiStHandler : InstructionHandler { /// - /// Initializes a new instance of the FdivrRegisterHandler class + /// Initializes a new instance of the FdivrStiStHandler class /// /// The instruction decoder that owns this handler - public FdivrRegisterHandler(InstructionDecoder decoder) + public FdivrStiStHandler(InstructionDecoder decoder) : base(decoder) { } @@ -23,7 +23,7 @@ public class FdivrRegisterHandler : InstructionHandler /// True if this handler can decode the opcode public override bool CanHandle(byte opcode) { - // FDIVR ST(i), ST(0) is DC F8-FF + // FDIVR ST(i), ST is DC F8-FF if (opcode != 0xDC) return false; if (!Decoder.CanReadByte()) @@ -39,7 +39,7 @@ public class FdivrRegisterHandler : InstructionHandler } /// - /// Decodes a FDIVR ST(i), ST(0) instruction + /// Decodes a FDIVR ST(i), ST instruction /// /// The opcode of the instruction /// The instruction object to populate diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpHandler.cs deleted file mode 100644 index 6a31ffd..0000000 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpHandler.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; - -using X86Disassembler.X86.Operands; - -/// -/// Handler for FDIVRP ST(i), ST(0) instruction (DE F8-FF) -/// -public class FdivrpHandler : InstructionHandler -{ - /// - /// Initializes a new instance of the FdivrpHandler class - /// - /// The instruction decoder that owns this handler - public FdivrpHandler(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) - { - // FDIVRP ST(i), ST(0) is DE F8-FF - if (opcode != 0xDE) return false; - - if (!Decoder.CanReadByte()) - { - return false; - } - - // Check if the ModR/M byte has reg field = 7 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 = 7 - return reg == 7 && mod == 3; - } - - /// - /// Decodes a FDIVRP ST(i), ST(0) 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.Fdivrp; - - // 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 operands - var destOperand = OperandFactory.CreateFPURegisterOperand(stIndex); - var srcOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); - - // Set the structured operands - instruction.StructuredOperands = - [ - destOperand, - srcOperand - ]; - - return true; - } -} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulFloat32Handler.cs index fe6ef8b..3c6cd26 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulFloat32Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulFloat32Handler.cs @@ -31,11 +31,13 @@ public class FmulFloat32Handler : InstructionHandler return false; } - // Check if the ModR/M byte has reg field = 1 + // Check if the ModR/M byte has reg field = 1 and mod != 3 (memory operand) byte modRm = Decoder.PeakByte(); byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); - return reg == 1; + // Only handle memory operands (mod != 3) with reg = 1 + return reg == 1 && mod != 3; } /// @@ -51,36 +53,20 @@ public class FmulFloat32Handler : InstructionHandler return false; } - // Read the ModR/M byte using the specialized FPU method + // Read the ModR/M byte using the specialized FPU method for 32-bit operands var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu(); + // We've already verified reg field is 1 (FMUL) in CanHandle + // and we only handle memory operands (mod != 3) + // 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 - ]; - } + // Set the structured operands - the operand already has the correct size from ReadModRMFpu + instruction.StructuredOperands = + [ + rawOperand + ]; return true; } diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulFloat64Handler.cs index 6a9d56d..90b527d 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulFloat64Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulFloat64Handler.cs @@ -31,11 +31,13 @@ public class FmulFloat64Handler : InstructionHandler return false; } - // Check if the ModR/M byte has reg field = 1 + // Check if the ModR/M byte has reg field = 1 and mod != 3 (memory operand) byte modRm = Decoder.PeakByte(); byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); - return reg == 1; + // Only handle memory operands (mod != 3) with reg = 1 + return reg == 1 && mod != 3; } /// @@ -54,31 +56,17 @@ public class FmulFloat64Handler : InstructionHandler // Read the ModR/M byte using the specialized FPU method for 64-bit operands var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu64(); + // We've already verified reg field is 1 (FMUL) in CanHandle + // and we only handle memory operands (mod != 3) + // 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 - ]; - } + // Set the structured operands - the operand already has the correct size from ReadModRMFpu64 + instruction.StructuredOperands = + [ + rawOperand + ]; return true; } diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulStStiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulStStiHandler.cs new file mode 100644 index 0000000..998a69c --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulStStiHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FMUL ST, ST(i) instruction (D8 C8-CF) +/// +public class FmulStStiHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FmulStStHandler class + /// + /// The instruction decoder that owns this handler + public FmulStStiHandler(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 ST, ST(i) is D8 C8-CF + if (opcode != 0xD8) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); + + // Only handle C8-CF + return secondOpcode is >= 0xC8 and <= 0xCF; + } + + /// + /// Decodes a FMUL ST, ST(i) 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 and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xC8); + + // Set the instruction type + instruction.Type = InstructionType.Fmul; + + // Create the FPU register operands + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + var stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + st0Operand, + stiOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulStiStHandler.cs similarity index 85% rename from X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs rename to X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulStiStHandler.cs index fae6aa4..dd49a7f 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulStiStHandler.cs @@ -3,15 +3,15 @@ namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; using X86Disassembler.X86.Operands; /// -/// Handler for FMUL ST(i), ST(0) instruction (DC C8-CF) +/// Handler for FMUL ST(i), ST instruction (DC C8-CF) /// -public class FmulRegisterHandler : InstructionHandler +public class FmulStiStHandler : InstructionHandler { /// - /// Initializes a new instance of the FmulRegisterHandler class + /// Initializes a new instance of the FmulStiStHandler class /// /// The instruction decoder that owns this handler - public FmulRegisterHandler(InstructionDecoder decoder) + public FmulStiStHandler(InstructionDecoder decoder) : base(decoder) { } @@ -23,7 +23,7 @@ public class FmulRegisterHandler : InstructionHandler /// True if this handler can decode the opcode public override bool CanHandle(byte opcode) { - // FMUL ST(i), ST(0) is DC C8-CF + // FMUL ST(i), ST is DC C8-CF if (opcode != 0xDC) return false; if (!Decoder.CanReadByte()) @@ -39,7 +39,7 @@ public class FmulRegisterHandler : InstructionHandler } /// - /// Decodes a FMUL ST(i), ST(0) instruction + /// Decodes a FMUL ST(i), ST instruction /// /// The opcode of the instruction /// The instruction object to populate diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpHandler.cs deleted file mode 100644 index e3a0825..0000000 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpHandler.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; - -using X86Disassembler.X86.Operands; - -/// -/// Handler for FMULP ST(i), ST(0) instruction (DE C8-CF) -/// -public class FmulpHandler : InstructionHandler -{ - /// - /// Initializes a new instance of the FmulpHandler class - /// - /// The instruction decoder that owns this handler - public FmulpHandler(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) - { - // FMULP ST(i), ST(0) is DE C8-CF - if (opcode != 0xDE) 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 FMULP ST(i), ST(0) 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.Fmulp; - - // 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 operands - var destOperand = OperandFactory.CreateFPURegisterOperand(stIndex); - var srcOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); - - // Set the structured operands - instruction.StructuredOperands = - [ - destOperand, - srcOperand - ]; - - return true; - } -} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubFloat64Handler.cs index 5c2a301..5d58530 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubFloat64Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubFloat64Handler.cs @@ -31,11 +31,13 @@ public class FsubFloat64Handler : InstructionHandler return false; } - // Check if the ModR/M byte has reg field = 4 + // Check if the ModR/M byte has reg field = 4 and mod != 3 (memory operand) byte modRm = Decoder.PeakByte(); byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); - return reg == 4; + // Only handle memory operands (mod != 3) with reg = 4 + return reg == 4 && mod != 3; } /// @@ -51,34 +53,20 @@ public class FsubFloat64Handler : InstructionHandler return false; } - // Read the ModR/M byte using the specialized FPU method + // Read the ModR/M byte using the specialized FPU method for 64-bit operands var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu64(); + // We've already verified reg field is 4 (FSUB) in CanHandle + // and we only handle memory operands (mod != 3) + // 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 DC E0-DC E7, 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 - ]; - } + // Set the structured operands - the operand already has the correct size from ReadModRMFpu64 + instruction.StructuredOperands = + [ + rawOperand + ]; return true; } diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubStStiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubStStiHandler.cs new file mode 100644 index 0000000..f3d8308 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubStStiHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSUB ST, ST(i) instruction (D8 E0-E7) +/// +public class FsubStStiHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FsubStStHandler class + /// + /// The instruction decoder that owns this handler + public FsubStStiHandler(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 ST, ST(i) is D8 E0-E7 + if (opcode != 0xD8) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); + + // Only handle E0-E7 + return secondOpcode is >= 0xE0 and <= 0xE7; + } + + /// + /// Decodes a FSUB ST, ST(i) 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 and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xE0); + + // Set the instruction type + instruction.Type = InstructionType.Fsub; + + // Create the FPU register operands + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + var stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + st0Operand, + stiOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubStiStHandler.cs similarity index 85% rename from X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubRegisterHandler.cs rename to X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubStiStHandler.cs index 0d42f92..fc7065e 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubStiStHandler.cs @@ -3,15 +3,15 @@ namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; using X86Disassembler.X86.Operands; /// -/// Handler for FSUB ST(i), ST(0) instruction (DC E0-E7) +/// Handler for FSUB ST(i), ST instruction (DC E0-E7) /// -public class FsubRegisterHandler : InstructionHandler +public class FsubStiStHandler : InstructionHandler { /// - /// Initializes a new instance of the FsubRegisterHandler class + /// Initializes a new instance of the FsubStiStHandler class /// /// The instruction decoder that owns this handler - public FsubRegisterHandler(InstructionDecoder decoder) + public FsubStiStHandler(InstructionDecoder decoder) : base(decoder) { } @@ -23,7 +23,7 @@ public class FsubRegisterHandler : InstructionHandler /// True if this handler can decode the opcode public override bool CanHandle(byte opcode) { - // FSUB ST(i), ST(0) is DC E0-E7 + // FSUB ST(i), ST is DC E0-E7 if (opcode != 0xDC) return false; if (!Decoder.CanReadByte()) @@ -39,7 +39,7 @@ public class FsubRegisterHandler : InstructionHandler } /// - /// Decodes a FSUB ST(i), ST(0) instruction + /// Decodes a FSUB ST(i), ST instruction /// /// The opcode of the instruction /// The instruction object to populate diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpHandler.cs deleted file mode 100644 index f3b661c..0000000 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpHandler.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; - -using X86Disassembler.X86.Operands; - -/// -/// Handler for FSUBP ST(i), ST(0) instruction (DE E0-E7) -/// -public class FsubpHandler : InstructionHandler -{ - /// - /// Initializes a new instance of the FsubpHandler class - /// - /// The instruction decoder that owns this handler - public FsubpHandler(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) - { - // FSUBP ST(i), ST(0) is DE E0-E7 - if (opcode != 0xDE) return false; - - if (!Decoder.CanReadByte()) - { - return false; - } - - // Check if the ModR/M byte has reg field = 4 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 = 4 - return reg == 4 && mod == 3; - } - - /// - /// Decodes a FSUBP ST(i), ST(0) 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.Fsubp; - - // 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 operands - var destOperand = OperandFactory.CreateFPURegisterOperand(stIndex); - var srcOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); - - // Set the structured operands - instruction.StructuredOperands = - [ - destOperand, - srcOperand - ]; - - return true; - } -} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrFloat64Handler.cs index 46c84db..7bdab97 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrFloat64Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrFloat64Handler.cs @@ -31,11 +31,13 @@ public class FsubrFloat64Handler : InstructionHandler return false; } - // Check if the ModR/M byte has reg field = 5 + // Check if the ModR/M byte has reg field = 5 and mod != 3 (memory operand) byte modRm = Decoder.PeakByte(); byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); - return reg == 5; + // Only handle memory operands (mod != 3) with reg = 5 + return reg == 5 && mod != 3; } /// @@ -51,34 +53,20 @@ public class FsubrFloat64Handler : InstructionHandler return false; } - // Read the ModR/M byte using the specialized FPU method + // Read the ModR/M byte using the specialized FPU method for 64-bit operands var (mod, reg, fpuRm, rawOperand) = ModRMDecoder.ReadModRMFpu64(); + // We've already verified reg field is 5 (FSUBR) in CanHandle + // and we only handle memory operands (mod != 3) + // 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 DC E8-DC EF, 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 - ]; - } + // Set the structured operands - the operand already has the correct size from ReadModRMFpu64 + instruction.StructuredOperands = + [ + rawOperand + ]; return true; } diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrStStiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrStStiHandler.cs new file mode 100644 index 0000000..6060bc1 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrStStiHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSUBR ST, ST(i) instruction (D8 E8-EF) +/// +public class FsubrStStiHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FsubrStStHandler class + /// + /// The instruction decoder that owns this handler + public FsubrStStiHandler(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 ST, ST(i) is D8 E8-EF + if (opcode != 0xD8) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); + + // Only handle E8-EF + return secondOpcode is >= 0xE8 and <= 0xEF; + } + + /// + /// Decodes a FSUBR ST, ST(i) 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 and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xE8); + + // Set the instruction type + instruction.Type = InstructionType.Fsubr; + + // Create the FPU register operands + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + var stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + st0Operand, + stiOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrStiStHandler.cs similarity index 85% rename from X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrRegisterHandler.cs rename to X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrStiStHandler.cs index 94c3580..cfbd744 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrStiStHandler.cs @@ -3,15 +3,15 @@ namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; using X86Disassembler.X86.Operands; /// -/// Handler for FSUBR ST(i), ST(0) instruction (DC E8-EF) +/// Handler for FSUBR ST(i), ST instruction (DC E8-EF) /// -public class FsubrRegisterHandler : InstructionHandler +public class FsubrStiStHandler : InstructionHandler { /// - /// Initializes a new instance of the FsubrRegisterHandler class + /// Initializes a new instance of the FsubrStiStHandler class /// /// The instruction decoder that owns this handler - public FsubrRegisterHandler(InstructionDecoder decoder) + public FsubrStiStHandler(InstructionDecoder decoder) : base(decoder) { } @@ -23,7 +23,7 @@ public class FsubrRegisterHandler : InstructionHandler /// True if this handler can decode the opcode public override bool CanHandle(byte opcode) { - // FSUBR ST(i), ST(0) is DC E8-EF + // FSUBR ST(i), ST is DC E8-EF if (opcode != 0xDC) return false; if (!Decoder.CanReadByte()) @@ -39,7 +39,7 @@ public class FsubrRegisterHandler : InstructionHandler } /// - /// Decodes a FSUBR ST(i), ST(0) instruction + /// Decodes a FSUBR ST(i), ST instruction /// /// The opcode of the instruction /// The instruction object to populate diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpHandler.cs deleted file mode 100644 index 6f3c4cb..0000000 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpHandler.cs +++ /dev/null @@ -1,89 +0,0 @@ -namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; - -using X86Disassembler.X86.Operands; - -/// -/// Handler for FSUBRP ST(i), ST(0) instruction (DE E8-EF) -/// -public class FsubrpHandler : InstructionHandler -{ - /// - /// Initializes a new instance of the FsubrpHandler class - /// - /// The instruction decoder that owns this handler - public FsubrpHandler(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) - { - // FSUBRP ST(i), ST(0) is DE E8-EF - if (opcode != 0xDE) return false; - - if (!Decoder.CanReadByte()) - { - return false; - } - - // Check if the ModR/M byte has reg field = 5 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 = 5 - return reg == 5 && mod == 3; - } - - /// - /// Decodes a FSUBRP ST(i), ST(0) 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.Fsubrp; - - // 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 operands - var destOperand = OperandFactory.CreateFPURegisterOperand(stIndex); - var srcOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); - - // Set the structured operands - instruction.StructuredOperands = - [ - destOperand, - srcOperand - ]; - - return true; - } -} diff --git a/X86DisassemblerTests/InstructionTests/InstructionHandlerFactoryTests.cs b/X86DisassemblerTests/InstructionTests/InstructionHandlerFactoryTests.cs index 1e11c0c..572e252 100644 --- a/X86DisassemblerTests/InstructionTests/InstructionHandlerFactoryTests.cs +++ b/X86DisassemblerTests/InstructionTests/InstructionHandlerFactoryTests.cs @@ -38,7 +38,10 @@ public class InstructionHandlerFactoryTests foreach (var handlerType in handlerTypes) { - Assert.Contains(handlers, x => x.GetType() == handlerType); + if (handlers.All(x => x.GetType() != handlerType)) + { + Assert.Fail($"{handlerType.Name} not found"); + } } var uniqueRegisteredHandlers = new HashSet();