diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddpStiStHandler.cs similarity index 51% rename from X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddRegisterHandler.cs rename to X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddpStiStHandler.cs index dcdea09..dd9a4ab 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddpStiStHandler.cs @@ -3,15 +3,15 @@ namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; using X86Disassembler.X86.Operands; /// -/// Handler for FADD ST(i), ST(0) instruction (DC C0-C7) +/// Handler for FADDP ST(i), ST instruction (DE C0-C7) /// -public class FaddRegisterHandler : InstructionHandler +public class FaddpStiStHandler : InstructionHandler { /// - /// Initializes a new instance of the FaddRegisterHandler class + /// Initializes a new instance of the FaddpStiStHandler class /// /// The instruction decoder that owns this handler - public FaddRegisterHandler(InstructionDecoder decoder) + public FaddpStiStHandler(InstructionDecoder decoder) : base(decoder) { } @@ -23,25 +23,23 @@ public class FaddRegisterHandler : InstructionHandler /// True if this handler can decode the opcode public override bool CanHandle(byte opcode) { - // FADD ST(i), ST(0) is DC C0-C7 - if (opcode != 0xDC) return false; + // FADDP ST(i), ST 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 0 - return reg == 0 && mod == 3; + // Only handle C0-C7 + return secondOpcode is >= 0xC0 and <= 0xC7; } /// - /// Decodes a FADD ST(i), ST(0) instruction + /// Decodes a FADDP ST(i), ST instruction /// /// The opcode of the instruction /// The instruction object to populate @@ -53,25 +51,11 @@ public class FaddRegisterHandler : InstructionHandler return false; } - // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + // Read the ModR/M byte and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xC0); // Set the instruction type - instruction.Type = InstructionType.Fadd; - - // 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 - }; + instruction.Type = InstructionType.Faddp; // Create the FPU register operands var stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs index 01cb4d8..295c875 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs @@ -31,13 +31,11 @@ public class FdivRegisterHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 6 - return reg == 6 && mod == 3; + // Only handle F0-F7 + return secondOpcode is >= 0xF0 and <= 0xF7; } /// @@ -53,25 +51,11 @@ public class FdivRegisterHandler : InstructionHandler return false; } - // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + // Read the ModR/M byte and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xF0); // Set the instruction type instruction.Type = InstructionType.Fdiv; - - // 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 stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpStiStHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpStiStHandler.cs new file mode 100644 index 0000000..e3e2ce5 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpStiStHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FDIVP ST(i), ST instruction (DE F0-F7) +/// +public class FdivpStiStHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FdivpStiStHandler class + /// + /// The instruction decoder that owns this handler + public FdivpStiStHandler(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 is DE F0-F7 + if (opcode != 0xDE) 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 FDIVP 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() - 0xF0); + + // Set the instruction type + instruction.Type = InstructionType.Fdivp; + + // 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/FdivrRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrRegisterHandler.cs index 12459c1..510cd13 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrRegisterHandler.cs @@ -31,13 +31,11 @@ public class FdivrRegisterHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 7 - return reg == 7 && mod == 3; + // Only handle F8-FF + return secondOpcode is >= 0xF8 and <= 0xFF; } /// @@ -53,25 +51,11 @@ public class FdivrRegisterHandler : InstructionHandler return false; } - // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + // Read the ModR/M byte and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xF8); // Set the instruction type instruction.Type = InstructionType.Fdivr; - - // 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 stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpStiStHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpStiStHandler.cs new file mode 100644 index 0000000..a2b3f9d --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpStiStHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FDIVRP ST(i), ST instruction (DE F8-FF) +/// +public class FdivrpStiStHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FdivrpStiStHandler class + /// + /// The instruction decoder that owns this handler + public FdivrpStiStHandler(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 is DE F8-FF + if (opcode != 0xDE) 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 FDIVRP 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() - 0xF8); + + // Set the instruction type + instruction.Type = InstructionType.Fdivrp; + + // 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/FmulRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs index ccc8f12..fae6aa4 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs @@ -31,13 +31,11 @@ public class FmulRegisterHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 1 - return reg == 1 && mod == 3; + // Only handle C8-CF + return secondOpcode is >= 0xC8 and <= 0xCF; } /// @@ -53,25 +51,11 @@ public class FmulRegisterHandler : InstructionHandler return false; } - // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + // Read the ModR/M byte and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xC8); // Set the instruction type instruction.Type = InstructionType.Fmul; - - // 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 stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpStiStHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpStiStHandler.cs new file mode 100644 index 0000000..12222ce --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpStiStHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FMULP ST(i), ST instruction (DE C8-CF) +/// +public class FmulpStiStHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FmulpStiStHandler class + /// + /// The instruction decoder that owns this handler + public FmulpStiStHandler(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 is DE C8-CF + if (opcode != 0xDE) 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 FMULP 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() - 0xC8); + + // Set the instruction type + instruction.Type = InstructionType.Fmulp; + + // 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/FsubRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubRegisterHandler.cs index 2b6385c..0d42f92 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubRegisterHandler.cs @@ -31,13 +31,11 @@ public class FsubRegisterHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 4 - return reg == 4 && mod == 3; + // Only handle E0-E7 + return secondOpcode is >= 0xE0 and <= 0xE7; } /// @@ -53,25 +51,11 @@ public class FsubRegisterHandler : InstructionHandler return false; } - // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + // Read the ModR/M byte and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xE0); // Set the instruction type instruction.Type = InstructionType.Fsub; - - // 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 stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpStiStHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpStiStHandler.cs new file mode 100644 index 0000000..57b1891 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpStiStHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSUBP ST(i), ST instruction (DE E0-E7) +/// +public class FsubpStiStHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FsubpStiStHandler class + /// + /// The instruction decoder that owns this handler + public FsubpStiStHandler(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 is DE E0-E7 + if (opcode != 0xDE) 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 FSUBP 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() - 0xE0); + + // Set the instruction type + instruction.Type = InstructionType.Fsubp; + + // 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/FsubrRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrRegisterHandler.cs index 36fd43e..94c3580 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrRegisterHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrRegisterHandler.cs @@ -31,13 +31,11 @@ public class FsubrRegisterHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 5 - return reg == 5 && mod == 3; + // Only handle E8-EF + return secondOpcode is >= 0xE8 and <= 0xEF; } /// @@ -53,25 +51,11 @@ public class FsubrRegisterHandler : InstructionHandler return false; } - // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + // Read the ModR/M byte and calculate ST(i) index + var stIndex = (FpuRegisterIndex)(Decoder.ReadByte() - 0xE8); // Set the instruction type instruction.Type = InstructionType.Fsubr; - - // 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 stiOperand = OperandFactory.CreateFPURegisterOperand(stIndex); diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpStiStHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpStiStHandler.cs new file mode 100644 index 0000000..00e54b8 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpStiStHandler.cs @@ -0,0 +1,73 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSUBRP ST(i), ST instruction (DE E8-EF) +/// +public class FsubrpStiStHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FsubrpStiStHandler class + /// + /// The instruction decoder that owns this handler + public FsubrpStiStHandler(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 is DE E8-EF + if (opcode != 0xDE) 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 FSUBRP 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() - 0xE8); + + // Set the instruction type + instruction.Type = InstructionType.Fsubrp; + + // 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/Comparison/FcomiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomiHandler.cs index 9b17a6c..af4f71b 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomiHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomiHandler.cs @@ -31,13 +31,11 @@ public class FcomiHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 7 - return reg == 7 && mod == 3; + // Only handle F0-F7 + return secondOpcode is >= 0xF0 and <= 0xF7; } /// @@ -54,33 +52,17 @@ public class FcomiHandler : InstructionHandler } // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + var (mod, reg, rm, _) = ModRMDecoder.ReadModRMFpu(); // Set the instruction type instruction.Type = InstructionType.Fcomi; - - // 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(FpuRegisterIndex.ST0); - var srcOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + var srcOperand = OperandFactory.CreateFPURegisterOperand(rm); // Set the structured operands instruction.StructuredOperands = [ - destOperand, srcOperand ]; diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomipHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomipHandler.cs index c6cbe3a..816fdaa 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomipHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomipHandler.cs @@ -31,13 +31,11 @@ public class FcomipHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 6 - return reg == 6 && mod == 3; + // Only handle F0-F7 + return secondOpcode is >= 0xF0 and <= 0xF7; } /// @@ -54,33 +52,17 @@ public class FcomipHandler : InstructionHandler } // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + var (mod, reg, rm, _) = ModRMDecoder.ReadModRMFpu(); // Set the instruction type instruction.Type = InstructionType.Fcomip; - - // 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(FpuRegisterIndex.ST0); - var srcOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + var srcOperand = OperandFactory.CreateFPURegisterOperand(rm); // Set the structured operands instruction.StructuredOperands = [ - destOperand, srcOperand ]; diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompFloat32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompFloat32Handler.cs index 0f07eec..9df0268 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompFloat32Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompFloat32Handler.cs @@ -36,7 +36,7 @@ public class FcompFloat32Handler : InstructionHandler byte reg = (byte)((modRm >> 3) & 0x7); // special handling of modRM for D8 D8+i FCOMP ST(i) - return reg == 3 && modRm is < 0xD8 or > 0xDE; + return reg == 3 && modRm is < 0xD8 or > 0xDF; } /// diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompStHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompStHandler.cs index 6946fb6..6f2ac5e 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompStHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompStHandler.cs @@ -34,7 +34,7 @@ public class FcompStHandler : InstructionHandler var opcodeSecond = Decoder.PeakByte(); // this is a special case of a handler, only handling FCOMP with ST(i) - if (opcodeSecond < 0xD8 || opcodeSecond > 0xDF) + if (opcodeSecond is < 0xD8 or > 0xDF) return false; return true; diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomiHandler.cs index bdd29fe..450d781 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomiHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomiHandler.cs @@ -31,13 +31,11 @@ public class FucomiHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 6 - return reg == 6 && mod == 3; + // Only handle F0-F7 + return secondOpcode is >= 0xE8 and <= 0xEF; } /// @@ -54,28 +52,14 @@ public class FucomiHandler : InstructionHandler } // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + var (mod, reg, rm, _) = ModRMDecoder.ReadModRMFpu(); // Set the instruction type instruction.Type = InstructionType.Fucomi; - - // 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(FpuRegisterIndex.ST0); - var srcOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + var srcOperand = OperandFactory.CreateFPURegisterOperand(rm); // Set the structured operands instruction.StructuredOperands = diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomipHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomipHandler.cs index 04a5c61..23397f1 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomipHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomipHandler.cs @@ -31,13 +31,11 @@ public class FucomipHandler : InstructionHandler 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); + // Check second opcode byte + byte secondOpcode = Decoder.PeakByte(); - // Only handle register operands (mod = 3) with reg = 5 - return reg == 5 && mod == 3; + // Only handle F0-F7 + return secondOpcode is >= 0xE8 and <= 0xEF; } /// @@ -54,33 +52,17 @@ public class FucomipHandler : InstructionHandler } // Read the ModR/M byte - var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + var (mod, reg, rm, _) = ModRMDecoder.ReadModRMFpu(); // Set the instruction type instruction.Type = InstructionType.Fucomip; - // 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(FpuRegisterIndex.ST0); - var srcOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + var srcOperand = OperandFactory.CreateFPURegisterOperand(rm); // Set the structured operands instruction.StructuredOperands = [ - destOperand, srcOperand ]; diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 18a8d3d..8a0a3d4 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -439,14 +439,14 @@ public class InstructionHandlerFactory _handlers.Add(new FloatingPoint.Comparison.FcomiHandler(_decoder)); // FCOMI (DB F0-F7) // D8 opcode handlers (register operations) - _handlers.Add(new FloatingPoint.Arithmetic.FaddRegisterHandler(_decoder)); // FADD ST(0), ST(i) (D8 C0-C7) - _handlers.Add(new FloatingPoint.Arithmetic.FmulRegisterHandler(_decoder)); // FMUL ST(0), ST(i) (D8 C8-CF) + _handlers.Add(new FloatingPoint.Arithmetic.FaddStStiHandler(_decoder)); // FADD ST, ST(i) (D8 C0-C7) + _handlers.Add(new FloatingPoint.Arithmetic.FmulStStiHandler(_decoder)); // FMUL ST, ST(i) (D8 C8-CF) _handlers.Add(new FloatingPoint.Comparison.FcomStHandler(_decoder)); // FCOM ST(i) (D8 D0-D7) _handlers.Add(new FloatingPoint.Comparison.FcompStHandler(_decoder)); // FCOMP ST(i) (D8 D8-DF) - _handlers.Add(new FloatingPoint.Arithmetic.FsubRegisterHandler(_decoder)); // FSUB ST(0), ST(i) (D8 E0-E7) - _handlers.Add(new FloatingPoint.Arithmetic.FsubrRegisterHandler(_decoder)); // FSUBR ST(0), ST(i) (D8 E8-EF) - _handlers.Add(new FloatingPoint.Arithmetic.FdivRegisterHandler(_decoder)); // FDIV ST(0), ST(i) (D8 F0-F7) - _handlers.Add(new FloatingPoint.Arithmetic.FdivrRegisterHandler(_decoder)); // FDIVR ST(0), ST(i) (D8 F8-FF) + _handlers.Add(new FloatingPoint.Arithmetic.FsubStStiHandler(_decoder)); // FSUB ST, ST(i) (D8 E0-E7) + _handlers.Add(new FloatingPoint.Arithmetic.FsubrStStiHandler(_decoder)); // FSUBR ST, ST(i) (D8 E8-EF) + _handlers.Add(new FloatingPoint.Arithmetic.FdivStStiHandler(_decoder)); // FDIV ST, ST(i) (D8 F0-F7) + _handlers.Add(new FloatingPoint.Arithmetic.FdivrStStiHandler(_decoder)); // FDIVR ST, ST(i) (D8 F8-FF) // DC opcode handlers (memory operations - float64) _handlers.Add(new FloatingPoint.Arithmetic.FaddFloat64Handler(_decoder)); // FADD float64 (DC /0) @@ -459,7 +459,13 @@ public class InstructionHandlerFactory _handlers.Add(new FloatingPoint.Arithmetic.FdivrFloat64Handler(_decoder)); // FDIVR float64 (DC /7) // DC opcode handlers (register operations) + _handlers.Add(new FloatingPoint.Arithmetic.FaddStiStHandler(_decoder)); // FADD ST(i), ST (DC C0-C7) + _handlers.Add(new FloatingPoint.Arithmetic.FmulStiStHandler(_decoder)); // FMUL ST(i), ST (DC C8-CF) _handlers.Add(new FloatingPoint.Comparison.FcomRegisterHandler(_decoder)); // FCOM ST(i), ST(0) (DC D0-D7) + _handlers.Add(new FloatingPoint.Arithmetic.FsubStiStHandler(_decoder)); // FSUB ST(i), ST (DC E0-E7) + _handlers.Add(new FloatingPoint.Arithmetic.FsubrStiStHandler(_decoder)); // FSUBR ST(i), ST (DC E8-EF) + _handlers.Add(new FloatingPoint.Arithmetic.FdivStiStHandler(_decoder)); // FDIV ST(i), ST (DC F0-F7) + _handlers.Add(new FloatingPoint.Arithmetic.FdivrStiStHandler(_decoder)); // FDIVR ST(i), ST (DC F8-FF) _handlers.Add(new FloatingPoint.Comparison.FcompRegisterHandler(_decoder)); // FCOMP ST(i), ST(0) (DC D8-DF) // DD opcode handlers (register operations) @@ -485,14 +491,13 @@ public class InstructionHandlerFactory _handlers.Add(new FloatingPoint.Arithmetic.FidivrInt16Handler(_decoder)); // FIDIVR int16 (DE /7) // DE opcode handlers (register operations) - _handlers.Add(new FloatingPoint.Arithmetic.FaddpHandler(_decoder)); // FADDP ST(i), ST(0) (DE C0-C7) - _handlers.Add(new FloatingPoint.Arithmetic.FmulpHandler(_decoder)); // FMULP ST(i), ST(0) (DE C8-CF) - _handlers.Add(new FloatingPoint.Comparison.FcompStHandler(_decoder)); // FCOMP ST(0) (DE D3) + _handlers.Add(new FloatingPoint.Arithmetic.FaddpStiStHandler(_decoder)); // FADDP ST(i), ST (DE C0-C7) + _handlers.Add(new FloatingPoint.Arithmetic.FmulpStiStHandler(_decoder)); // FMULP ST(i), ST (DE C8-CF) _handlers.Add(new FloatingPoint.Comparison.FcomppHandler(_decoder)); // FCOMPP (DE D9) - _handlers.Add(new FloatingPoint.Arithmetic.FsubpHandler(_decoder)); // FSUBP ST(i), ST(0) (DE E0-E7) - _handlers.Add(new FloatingPoint.Arithmetic.FsubrpHandler(_decoder)); // FSUBRP ST(i), ST(0) (DE E8-EF) - _handlers.Add(new FloatingPoint.Arithmetic.FdivpHandler(_decoder)); // FDIVP ST(i), ST(0) (DE F0-F7) - _handlers.Add(new FloatingPoint.Arithmetic.FdivrpHandler(_decoder)); // FDIVRP ST(i), ST(0) (DE F8-FF) + _handlers.Add(new FloatingPoint.Arithmetic.FsubpStiStHandler(_decoder)); // FSUBP ST(i), ST (DE E0-E7) + _handlers.Add(new FloatingPoint.Arithmetic.FsubrpStiStHandler(_decoder)); // FSUBRP ST(i), ST (DE E8-EF) + _handlers.Add(new FloatingPoint.Arithmetic.FdivpStiStHandler(_decoder)); // FDIVP ST(i), ST (DE F0-F7) + _handlers.Add(new FloatingPoint.Arithmetic.FdivrpStiStHandler(_decoder)); // FDIVRP ST(i), ST (DE F8-FF) // DF opcode handlers (memory operations) _handlers.Add(new FloatingPoint.LoadStore.FildInt16Handler(_decoder)); // FILD int16 (DF /0) diff --git a/X86DisassemblerTests/TestData/fcom_tests.csv b/X86DisassemblerTests/TestData/fcom_tests.csv index 4dcfe5c..70e4265 100644 --- a/X86DisassemblerTests/TestData/fcom_tests.csv +++ b/X86DisassemblerTests/TestData/fcom_tests.csv @@ -39,8 +39,8 @@ D8DF;[{ "Type": "Fcomp", "Operands": ["ST(7)"] }] # Memory operands D81C2510000000;[{ "Type": "Fcomp", "Operands": ["dword ptr [0x10]"] }] DC1C2510000000;[{ "Type": "Fcomp", "Operands": ["qword ptr [0x10]"] }] -D81C25;[{ "Type": "Fcomp", "Operands": ["dword ptr [eax]"] }] -DC1C25;[{ "Type": "Fcomp", "Operands": ["qword ptr [eax]"] }] +D818;[{ "Type": "Fcomp", "Operands": ["dword ptr [eax]"] }] +DC18;[{ "Type": "Fcomp", "Operands": ["qword ptr [eax]"] }] # FCOMPP - Compare floating point values and pop twice DED9;[{ "Type": "Fcompp", "Operands": [] }]