diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddRegisterHandler.cs new file mode 100644 index 0000000..dcdea09 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddRegisterHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FADD ST(i), ST(0) instruction (DC C0-C7) +/// +public class FaddRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FaddRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FaddRegisterHandler(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(0) is DC C0-C7 + if (opcode != 0xDC) 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 FADD 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.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 + }; + + // 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 new file mode 100644 index 0000000..5c046e5 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FaddpHandler.cs @@ -0,0 +1,89 @@ +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/FdivRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs new file mode 100644 index 0000000..01cb4d8 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivRegisterHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FDIV ST(i), ST(0) instruction (DC F0-F7) +/// +public class FdivRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FdivRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FdivRegisterHandler(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(i), ST(0) is DC F0-F7 + if (opcode != 0xDC) 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 FDIV 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.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); + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + stiOperand, + st0Operand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpHandler.cs new file mode 100644 index 0000000..dfea862 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivpHandler.cs @@ -0,0 +1,89 @@ +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/FdivrRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrRegisterHandler.cs new file mode 100644 index 0000000..12459c1 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrRegisterHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FDIVR ST(i), ST(0) instruction (DC F8-FF) +/// +public class FdivrRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FdivrRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FdivrRegisterHandler(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(i), ST(0) is DC F8-FF + if (opcode != 0xDC) 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 FDIVR 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.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); + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + stiOperand, + st0Operand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpHandler.cs new file mode 100644 index 0000000..6a31ffd --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FdivrpHandler.cs @@ -0,0 +1,89 @@ +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/FiaddInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FiaddInt16Handler.cs new file mode 100644 index 0000000..0b8006a --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FiaddInt16Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIADD int16 instruction (DE /0) +/// +public class FiaddInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FiaddInt16Handler class + /// + /// The instruction decoder that owns this handler + public FiaddInt16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FIADD int16 is DE /0 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 0 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 0 + return reg == 0 && mod != 3; + } + + /// + /// Decodes a FIADD int16 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, specifying that we're dealing with 16-bit operands + var (mod, reg, rm, memoryOperand) = ModRMDecoder.ReadModRM16(); + + // Set the instruction type + instruction.Type = InstructionType.Fiadd; + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivInt16Handler.cs new file mode 100644 index 0000000..d61fce3 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivInt16Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIDIV int16 instruction (DE /6) +/// +public class FidivInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FidivInt16Handler class + /// + /// The instruction decoder that owns this handler + public FidivInt16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FIDIV int16 is DE /6 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 6 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 6 + return reg == 6 && mod != 3; + } + + /// + /// Decodes a FIDIV int16 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, specifying that we're dealing with 16-bit operands + var (mod, reg, rm, memoryOperand) = ModRMDecoder.ReadModRM16(); + + // Set the instruction type + instruction.Type = InstructionType.Fidiv; + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivrInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivrInt16Handler.cs new file mode 100644 index 0000000..7011c34 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FidivrInt16Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIDIVR int16 instruction (DE /7) +/// +public class FidivrInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FidivrInt16Handler class + /// + /// The instruction decoder that owns this handler + public FidivrInt16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FIDIVR int16 is DE /7 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 7 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 7 + return reg == 7 && mod != 3; + } + + /// + /// Decodes a FIDIVR int16 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, specifying that we're dealing with 16-bit operands + var (mod, reg, rm, memoryOperand) = ModRMDecoder.ReadModRM16(); + + // Set the instruction type + instruction.Type = InstructionType.Fidivr; + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FimulInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FimulInt16Handler.cs new file mode 100644 index 0000000..b1ebd47 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FimulInt16Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIMUL int16 instruction (DE /1) +/// +public class FimulInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FimulInt16Handler class + /// + /// The instruction decoder that owns this handler + public FimulInt16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FIMUL int16 is DE /1 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 1 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 1 + return reg == 1 && mod != 3; + } + + /// + /// Decodes a FIMUL int16 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, specifying that we're dealing with 16-bit operands + var (mod, reg, rm, memoryOperand) = ModRMDecoder.ReadModRM16(); + + // Set the instruction type + instruction.Type = InstructionType.Fimul; + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubInt16Handler.cs new file mode 100644 index 0000000..04d6f87 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubInt16Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FISUB int16 instruction (DE /4) +/// +public class FisubInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FisubInt16Handler class + /// + /// The instruction decoder that owns this handler + public FisubInt16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FISUB int16 is DE /4 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 4 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 4 + return reg == 4 && mod != 3; + } + + /// + /// Decodes a FISUB int16 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, specifying that we're dealing with 16-bit operands + var (mod, reg, rm, memoryOperand) = ModRMDecoder.ReadModRM16(); + + // Set the instruction type + instruction.Type = InstructionType.Fisub; + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubrInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubrInt16Handler.cs new file mode 100644 index 0000000..aceb53e --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FisubrInt16Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FISUBR int16 instruction (DE /5) +/// +public class FisubrInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FisubrInt16Handler class + /// + /// The instruction decoder that owns this handler + public FisubrInt16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FISUBR int16 is DE /5 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 5 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 5 + return reg == 5 && mod != 3; + } + + /// + /// Decodes a FISUBR int16 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, specifying that we're dealing with 16-bit operands + var (mod, reg, rm, memoryOperand) = ModRMDecoder.ReadModRM16(); + + // Set the instruction type + instruction.Type = InstructionType.Fisubr; + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs new file mode 100644 index 0000000..ccc8f12 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulRegisterHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FMUL ST(i), ST(0) instruction (DC C8-CF) +/// +public class FmulRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FmulRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FmulRegisterHandler(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(i), ST(0) is DC C8-CF + if (opcode != 0xDC) 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 FMUL 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.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); + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + stiOperand, + st0Operand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpHandler.cs new file mode 100644 index 0000000..e3a0825 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FmulpHandler.cs @@ -0,0 +1,89 @@ +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/FsubRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubRegisterHandler.cs new file mode 100644 index 0000000..2b6385c --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubRegisterHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSUB ST(i), ST(0) instruction (DC E0-E7) +/// +public class FsubRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FsubRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FsubRegisterHandler(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(i), ST(0) is DC E0-E7 + if (opcode != 0xDC) 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 FSUB 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.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); + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + stiOperand, + st0Operand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpHandler.cs new file mode 100644 index 0000000..f3b661c --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubpHandler.cs @@ -0,0 +1,89 @@ +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/FsubrRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrRegisterHandler.cs new file mode 100644 index 0000000..36fd43e --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrRegisterHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Arithmetic; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSUBR ST(i), ST(0) instruction (DC E8-EF) +/// +public class FsubrRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FsubrRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FsubrRegisterHandler(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(i), ST(0) is DC E8-EF + if (opcode != 0xDC) 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 FSUBR 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.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); + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + stiOperand, + st0Operand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpHandler.cs new file mode 100644 index 0000000..6f3c4cb --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Arithmetic/FsubrpHandler.cs @@ -0,0 +1,89 @@ +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/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomRegisterHandler.cs new file mode 100644 index 0000000..03ba4bf --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomRegisterHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCOM ST(i), ST(0) instruction (DC D0-D7) +/// +public class FcomRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcomRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FcomRegisterHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FCOM ST(i), ST(0) is DC D0-D7 + if (opcode != 0xDC) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 2 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 = 2 + return reg == 2 && mod == 3; + } + + /// + /// Decodes a FCOM 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.Fcom; + + // 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); + 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 new file mode 100644 index 0000000..9b17a6c --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomiHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCOMI instruction (DB F0-F7) +/// +public class FcomiHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcomiHandler class + /// + /// The instruction decoder that owns this handler + public FcomiHandler(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) + { + // FCOMI is DB F0-F7 + if (opcode != 0xDB) 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 FCOMI 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.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); + + // Set the structured operands + instruction.StructuredOperands = + [ + destOperand, + srcOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomipHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomipHandler.cs new file mode 100644 index 0000000..c6cbe3a --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomipHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCOMIP ST(0), ST(i) instruction (DF F0-F7) +/// +public class FcomipHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcomipHandler class + /// + /// The instruction decoder that owns this handler + public FcomipHandler(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) + { + // FCOMIP ST(0), ST(i) is DF F0-F7 + if (opcode != 0xDF) 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 FCOMIP ST(0), 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 + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // 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); + + // Set the structured operands + instruction.StructuredOperands = + [ + destOperand, + srcOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompRegisterHandler.cs new file mode 100644 index 0000000..e3a56ab --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompRegisterHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCOMP ST(i), ST(0) instruction (DC D8-DF) +/// +public class FcompRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcompRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FcompRegisterHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FCOMP ST(i), ST(0) is DC D8-DF + if (opcode != 0xDC) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 3 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 = 3 + return reg == 3 && mod == 3; + } + + /// + /// Decodes a FCOMP 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.Fcomp; + + // 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); + var st0Operand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + stiOperand, + st0Operand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompStHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompStHandler.cs new file mode 100644 index 0000000..6fb400f --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcompStHandler.cs @@ -0,0 +1,69 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCOMP ST(0) instruction (DE D3) +/// +public class FcompStHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcompStHandler class + /// + /// The instruction decoder that owns this handler + public FcompStHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FCOMP ST(0) is DE D3 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte is exactly D3 (reg = 2, rm = 3, mod = 3) + byte modRm = Decoder.PeakByte(); + return modRm == 0xD3; + } + + /// + /// Decodes a FCOMP 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.Fcomp; + + // Create the FPU register operand + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomppHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomppHandler.cs new file mode 100644 index 0000000..c554133 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FcomppHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCOMPP instruction (DE D9) +/// +public class FcomppHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcomppHandler class + /// + /// The instruction decoder that owns this handler + public FcomppHandler(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) + { + // FCOMPP is DE D9 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte is exactly D9 (reg = 3, rm = 1, mod = 3) + byte modRm = Decoder.PeakByte(); + return modRm == 0xD9; + } + + /// + /// Decodes a FCOMPP 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.Fcompp; + + // FCOMPP has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicomInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicomInt16Handler.cs new file mode 100644 index 0000000..80ab210 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicomInt16Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FICOM int16 instruction (DE /2) +/// +public class FicomInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FicomInt16Handler class + /// + /// The instruction decoder that owns this handler + public FicomInt16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FICOM int16 is DE /2 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 2 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 2 + return reg == 2 && mod != 3; + } + + /// + /// Decodes a FICOM int16 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, specifying that we're dealing with 16-bit operands + var (mod, reg, rm, memoryOperand) = ModRMDecoder.ReadModRM16(); + + // Set the instruction type + instruction.Type = InstructionType.Ficom; + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicompInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicompInt16Handler.cs new file mode 100644 index 0000000..ae1701c --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FicompInt16Handler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FICOMP int16 instruction (DE /3) +/// +public class FicompInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FicompInt16Handler class + /// + /// The instruction decoder that owns this handler + public FicompInt16Handler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FICOMP int16 is DE /3 + if (opcode != 0xDE) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 3 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 3 + return reg == 3 && mod != 3; + } + + /// + /// Decodes a FICOMP int16 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, specifying that we're dealing with 16-bit operands + var (mod, reg, rm, memoryOperand) = ModRMDecoder.ReadModRM16(); + + // Set the instruction type + instruction.Type = InstructionType.Ficomp; + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomHandler.cs new file mode 100644 index 0000000..e5ed053 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomHandler.cs @@ -0,0 +1,87 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FUCOM ST(i) instruction (DD E0-E7) +/// +public class FucomHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FucomHandler class + /// + /// The instruction decoder that owns this handler + public FucomHandler(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) + { + // FUCOM ST(i) is DD E0-E7 + if (opcode != 0xDD) 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 FUCOM 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 + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fucom; + + // Map rm field to FPU register index + FpuRegisterIndex stIndex = rm switch + { + RegisterIndex.A => FpuRegisterIndex.ST0, + RegisterIndex.C => FpuRegisterIndex.ST1, + RegisterIndex.D => FpuRegisterIndex.ST2, + RegisterIndex.B => FpuRegisterIndex.ST3, + RegisterIndex.Sp => FpuRegisterIndex.ST4, + RegisterIndex.Bp => FpuRegisterIndex.ST5, + RegisterIndex.Si => FpuRegisterIndex.ST6, + RegisterIndex.Di => FpuRegisterIndex.ST7, + _ => FpuRegisterIndex.ST0 // Default case, should not happen + }; + + // Create the FPU register operand + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomiHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomiHandler.cs new file mode 100644 index 0000000..bdd29fe --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomiHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FUCOMI instruction (DB E8-EF) +/// +public class FucomiHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FucomiHandler class + /// + /// The instruction decoder that owns this handler + public FucomiHandler(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) + { + // FUCOMI is DB E8-EF + if (opcode != 0xDB) 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 FUCOMI 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.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); + + // Set the structured operands + instruction.StructuredOperands = + [ + destOperand, + srcOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomipHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomipHandler.cs new file mode 100644 index 0000000..04a5c61 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucomipHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FUCOMIP ST(0), ST(i) instruction (DF E8-EF) +/// +public class FucomipHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FucomipHandler class + /// + /// The instruction decoder that owns this handler + public FucomipHandler(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) + { + // FUCOMIP ST(0), ST(i) is DF E8-EF + if (opcode != 0xDF) 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 FUCOMIP ST(0), 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 + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // 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); + + // Set the structured operands + instruction.StructuredOperands = + [ + destOperand, + srcOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucompHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucompHandler.cs new file mode 100644 index 0000000..193ee74 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Comparison/FucompHandler.cs @@ -0,0 +1,87 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Comparison; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FUCOMP ST(i) instruction (DD E8-EF) +/// +public class FucompHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FucompHandler class + /// + /// The instruction decoder that owns this handler + public FucompHandler(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) + { + // FUCOMP ST(i) is DD E8-EF + if (opcode != 0xDD) 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 FUCOMP 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 + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fucomp; + + // Map rm field to FPU register index + FpuRegisterIndex stIndex = rm switch + { + RegisterIndex.A => FpuRegisterIndex.ST0, + RegisterIndex.C => FpuRegisterIndex.ST1, + RegisterIndex.D => FpuRegisterIndex.ST2, + RegisterIndex.B => FpuRegisterIndex.ST3, + RegisterIndex.Sp => FpuRegisterIndex.ST4, + RegisterIndex.Bp => FpuRegisterIndex.ST5, + RegisterIndex.Si => FpuRegisterIndex.ST6, + RegisterIndex.Di => FpuRegisterIndex.ST7, + _ => FpuRegisterIndex.ST0 // Default case, should not happen + }; + + // Create the FPU register operand + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnbHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnbHandler.cs new file mode 100644 index 0000000..85004fa --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnbHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Conditional; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCMOVNB instruction (DB C0-C7) +/// +public class FcmovnbHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcmovnbHandler class + /// + /// The instruction decoder that owns this handler + public FcmovnbHandler(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) + { + // FCMOVNB is DB C0-C7 + if (opcode != 0xDB) 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 FCMOVNB 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.Fcmovnb; + + // 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); + + // Set the structured operands + instruction.StructuredOperands = + [ + destOperand, + srcOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnbeHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnbeHandler.cs new file mode 100644 index 0000000..18dbf34 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnbeHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Conditional; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCMOVNBE instruction (DB D0-D7) +/// +public class FcmovnbeHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcmovnbeHandler class + /// + /// The instruction decoder that owns this handler + public FcmovnbeHandler(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) + { + // FCMOVNBE is DB D0-D7 + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 2 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 = 2 + return reg == 2 && mod == 3; + } + + /// + /// Decodes a FCMOVNBE 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.Fcmovnbe; + + // 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); + + // Set the structured operands + instruction.StructuredOperands = + [ + destOperand, + srcOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovneHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovneHandler.cs new file mode 100644 index 0000000..11b29d8 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovneHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Conditional; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCMOVNE instruction (DB C8-CF) +/// +public class FcmovneHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcmovneHandler class + /// + /// The instruction decoder that owns this handler + public FcmovneHandler(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) + { + // FCMOVNE is DB C8-CF + if (opcode != 0xDB) 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 FCMOVNE 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.Fcmovne; + + // 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); + + // Set the structured operands + instruction.StructuredOperands = + [ + destOperand, + srcOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnuHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnuHandler.cs new file mode 100644 index 0000000..ac228e5 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Conditional/FcmovnuHandler.cs @@ -0,0 +1,89 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Conditional; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCMOVNU instruction (DB D8-DF) +/// +public class FcmovnuHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FcmovnuHandler class + /// + /// The instruction decoder that owns this handler + public FcmovnuHandler(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) + { + // FCMOVNU is DB D8-DF + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 3 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 = 3 + return reg == 3 && mod == 3; + } + + /// + /// Decodes a FCMOVNU 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.Fcmovnu; + + // 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); + + // Set the structured operands + instruction.StructuredOperands = + [ + destOperand, + srcOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexHandler.cs new file mode 100644 index 0000000..bf04f46 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FCLEX instruction (DB E2) +/// +public class FclexHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FclexHandler class + /// + /// The instruction decoder that owns this handler + public FclexHandler(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) + { + // FCLEX is DB E2 + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is E2 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xE2; + } + + /// + /// Decodes a FCLEX instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Fclex; + + // FCLEX has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FfreeHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FfreeHandler.cs new file mode 100644 index 0000000..d0c6e63 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FfreeHandler.cs @@ -0,0 +1,87 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FFREE ST(i) instruction (DD C0-C7) +/// +public class FfreeHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FfreeHandler class + /// + /// The instruction decoder that owns this handler + public FfreeHandler(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) + { + // FFREE ST(i) is DD C0-C7 + if (opcode != 0xDD) 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 FFREE 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 + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Ffree; + + // Map rm field to FPU register index + FpuRegisterIndex stIndex = rm switch + { + RegisterIndex.A => FpuRegisterIndex.ST0, + RegisterIndex.C => FpuRegisterIndex.ST1, + RegisterIndex.D => FpuRegisterIndex.ST2, + RegisterIndex.B => FpuRegisterIndex.ST3, + RegisterIndex.Sp => FpuRegisterIndex.ST4, + RegisterIndex.Bp => FpuRegisterIndex.ST5, + RegisterIndex.Si => FpuRegisterIndex.ST6, + RegisterIndex.Di => FpuRegisterIndex.ST7, + _ => FpuRegisterIndex.ST0 // Default case, should not happen + }; + + // Create the FPU register operand + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FfreepHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FfreepHandler.cs new file mode 100644 index 0000000..b7c6288 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FfreepHandler.cs @@ -0,0 +1,87 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FFREEP ST(i) instruction (DF C0-C7) +/// +public class FfreepHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FfreepHandler class + /// + /// The instruction decoder that owns this handler + public FfreepHandler(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) + { + // FFREEP ST(i) is DF C0-C7 + if (opcode != 0xDF) 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 FFREEP 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 + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Ffreep; + + // Map rm field to FPU register index + FpuRegisterIndex stIndex = rm switch + { + RegisterIndex.A => FpuRegisterIndex.ST0, + RegisterIndex.C => FpuRegisterIndex.ST1, + RegisterIndex.D => FpuRegisterIndex.ST2, + RegisterIndex.B => FpuRegisterIndex.ST3, + RegisterIndex.Sp => FpuRegisterIndex.ST4, + RegisterIndex.Bp => FpuRegisterIndex.ST5, + RegisterIndex.Si => FpuRegisterIndex.ST6, + RegisterIndex.Di => FpuRegisterIndex.ST7, + _ => FpuRegisterIndex.ST0 // Default case, should not happen + }; + + // Create the FPU register operand + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FinitHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FinitHandler.cs new file mode 100644 index 0000000..8200819 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FinitHandler.cs @@ -0,0 +1,63 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FINIT instruction (DB E3) +/// +public class FinitHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FinitHandler class + /// + /// The instruction decoder that owns this handler + public FinitHandler(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) + { + // FINIT is DB E3 + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the next byte is E3 + byte nextByte = Decoder.PeakByte(); + return nextByte == 0xE3; + } + + /// + /// Decodes a FINIT instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the second byte of the opcode + byte secondByte = Decoder.ReadByte(); + + // Set the instruction type + instruction.Type = InstructionType.Finit; + + // FINIT has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnsaveHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnsaveHandler.cs new file mode 100644 index 0000000..e2efae5 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnsaveHandler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FNSAVE instruction (DD /6) +/// +public class FnsaveHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FnsaveHandler class + /// + /// The instruction decoder that owns this handler + public FnsaveHandler(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) + { + // FNSAVE is DD /6 + if (opcode != 0xDD) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 6 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 6 && mod != 3; + } + + /// + /// Decodes a FNSAVE instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fnsave; + + // Set the structured operands + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstswMemoryHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstswMemoryHandler.cs new file mode 100644 index 0000000..35990e5 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FnstswMemoryHandler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FNSTSW memory instruction (DD /7) +/// +public class FnstswMemoryHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FnstswMemoryHandler class + /// + /// The instruction decoder that owns this handler + public FnstswMemoryHandler(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) + { + // FNSTSW is DD /7 + if (opcode != 0xDD) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 7 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 7 && mod != 3; + } + + /// + /// Decodes a FNSTSW memory instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fnstsw; + + // Create a 16-bit memory operand for status word + Operand memoryOperand; + + if (rawOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand16(directMemory.Address); + } + else if (rawOperand is BaseRegisterMemoryOperand baseRegMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand16(baseRegMemory.BaseRegister); + } + else if (rawOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand16(dispMemory.BaseRegister, dispMemory.Displacement); + } + else if (rawOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand16(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement); + } + else + { + memoryOperand = rawOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FrstorHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FrstorHandler.cs new file mode 100644 index 0000000..1d40fc1 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FrstorHandler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FRSTOR instruction (DD /4) +/// +public class FrstorHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FrstorHandler class + /// + /// The instruction decoder that owns this handler + public FrstorHandler(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) + { + // FRSTOR is DD /4 + if (opcode != 0xDD) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 4 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 4 && mod != 3; + } + + /// + /// Decodes a FRSTOR instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Frstor; + + // Set the structured operands + instruction.StructuredOperands = + [ + rawOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Int32OperationHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Int32OperationHandler.cs deleted file mode 100644 index 6539683..0000000 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Int32OperationHandler.cs +++ /dev/null @@ -1,145 +0,0 @@ -using X86Disassembler.X86.Operands; - -namespace X86Disassembler.X86.Handlers.FloatingPoint; - -/// -/// Handler for floating-point operations on int32 (DA opcode) -/// -public class Int32OperationHandler : InstructionHandler -{ - // Memory operand instruction types for DA opcode - operations on int32 - private static readonly InstructionType[] MemoryInstructionTypes = - [ - InstructionType.Fiadd, // fiadd dword ptr [r/m] - InstructionType.Fimul, // fimul dword ptr [r/m] - InstructionType.Ficom, // ficom dword ptr [r/m] - InstructionType.Ficomp, // ficomp dword ptr [r/m] - InstructionType.Fisub, // fisub dword ptr [r/m] - InstructionType.Fisubr, // fisubr dword ptr [r/m] - InstructionType.Fidiv, // fidiv dword ptr [r/m] - InstructionType.Fidivr // fidivr dword ptr [r/m] - ]; - - // Register-register operations mapping (mod=3) - private static readonly Dictionary<(RegisterIndex Reg, RegisterIndex Rm), (InstructionType Type, FpuRegisterIndex DestIndex, FpuRegisterIndex SrcIndex)> RegisterOperations = new() - { - // FCMOVB st(0), st(i) - { (RegisterIndex.A, RegisterIndex.A), (InstructionType.Fcmovb, FpuRegisterIndex.ST0, FpuRegisterIndex.ST0) }, - { (RegisterIndex.A, RegisterIndex.C), (InstructionType.Fcmovb, FpuRegisterIndex.ST0, FpuRegisterIndex.ST1) }, - { (RegisterIndex.A, RegisterIndex.D), (InstructionType.Fcmovb, FpuRegisterIndex.ST0, FpuRegisterIndex.ST2) }, - { (RegisterIndex.A, RegisterIndex.B), (InstructionType.Fcmovb, FpuRegisterIndex.ST0, FpuRegisterIndex.ST3) }, - { (RegisterIndex.A, RegisterIndex.Sp), (InstructionType.Fcmovb, FpuRegisterIndex.ST0, FpuRegisterIndex.ST4) }, - { (RegisterIndex.A, RegisterIndex.Bp), (InstructionType.Fcmovb, FpuRegisterIndex.ST0, FpuRegisterIndex.ST5) }, - { (RegisterIndex.A, RegisterIndex.Si), (InstructionType.Fcmovb, FpuRegisterIndex.ST0, FpuRegisterIndex.ST6) }, - { (RegisterIndex.A, RegisterIndex.Di), (InstructionType.Fcmovb, FpuRegisterIndex.ST0, FpuRegisterIndex.ST7) }, - - // FCMOVE st(0), st(i) - { (RegisterIndex.B, RegisterIndex.A), (InstructionType.Fcmove, FpuRegisterIndex.ST0, FpuRegisterIndex.ST0) }, - { (RegisterIndex.B, RegisterIndex.C), (InstructionType.Fcmove, FpuRegisterIndex.ST0, FpuRegisterIndex.ST1) }, - { (RegisterIndex.B, RegisterIndex.D), (InstructionType.Fcmove, FpuRegisterIndex.ST0, FpuRegisterIndex.ST2) }, - { (RegisterIndex.B, RegisterIndex.B), (InstructionType.Fcmove, FpuRegisterIndex.ST0, FpuRegisterIndex.ST3) }, - { (RegisterIndex.B, RegisterIndex.Sp), (InstructionType.Fcmove, FpuRegisterIndex.ST0, FpuRegisterIndex.ST4) }, - { (RegisterIndex.B, RegisterIndex.Bp), (InstructionType.Fcmove, FpuRegisterIndex.ST0, FpuRegisterIndex.ST5) }, - { (RegisterIndex.B, RegisterIndex.Si), (InstructionType.Fcmove, FpuRegisterIndex.ST0, FpuRegisterIndex.ST6) }, - { (RegisterIndex.B, RegisterIndex.Di), (InstructionType.Fcmove, FpuRegisterIndex.ST0, FpuRegisterIndex.ST7) }, - - // FCMOVBE st(0), st(i) - { (RegisterIndex.C, RegisterIndex.A), (InstructionType.Fcmovbe, FpuRegisterIndex.ST0, FpuRegisterIndex.ST0) }, - { (RegisterIndex.C, RegisterIndex.C), (InstructionType.Fcmovbe, FpuRegisterIndex.ST0, FpuRegisterIndex.ST1) }, - { (RegisterIndex.C, RegisterIndex.D), (InstructionType.Fcmovbe, FpuRegisterIndex.ST0, FpuRegisterIndex.ST2) }, - { (RegisterIndex.C, RegisterIndex.B), (InstructionType.Fcmovbe, FpuRegisterIndex.ST0, FpuRegisterIndex.ST3) }, - { (RegisterIndex.C, RegisterIndex.Sp), (InstructionType.Fcmovbe, FpuRegisterIndex.ST0, FpuRegisterIndex.ST4) }, - { (RegisterIndex.C, RegisterIndex.Bp), (InstructionType.Fcmovbe, FpuRegisterIndex.ST0, FpuRegisterIndex.ST5) }, - { (RegisterIndex.C, RegisterIndex.Si), (InstructionType.Fcmovbe, FpuRegisterIndex.ST0, FpuRegisterIndex.ST6) }, - { (RegisterIndex.C, RegisterIndex.Di), (InstructionType.Fcmovbe, FpuRegisterIndex.ST0, FpuRegisterIndex.ST7) }, - - // FCMOVU st(0), st(i) - { (RegisterIndex.D, RegisterIndex.A), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST0) }, - { (RegisterIndex.D, RegisterIndex.C), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST1) }, - { (RegisterIndex.D, RegisterIndex.D), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST2) }, - { (RegisterIndex.D, RegisterIndex.B), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST3) }, - { (RegisterIndex.D, RegisterIndex.Sp), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST4) }, - { (RegisterIndex.D, RegisterIndex.Bp), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST5) }, - { (RegisterIndex.D, RegisterIndex.Si), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST6) }, - { (RegisterIndex.D, RegisterIndex.Di), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST7) }, - - // Special case - { (RegisterIndex.Di, RegisterIndex.B), (InstructionType.Fcmovu, FpuRegisterIndex.ST0, FpuRegisterIndex.ST0) } - }; - - /// - /// Initializes a new instance of the Int32OperationHandler class - /// - /// The instruction decoder that owns this handler - public Int32OperationHandler(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) - { - return opcode == 0xDA; - } - - /// - /// Decodes a floating-point instruction for int32 operations - /// - /// 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, memoryOperand) = ModRMDecoder.ReadModRM(); - - // Handle based on addressing mode - if (mod != 3) // Memory operand - { - // Set the instruction type based on the reg field - instruction.Type = MemoryInstructionTypes[(int)reg]; - - // Set the structured operands - instruction.StructuredOperands = - [ - memoryOperand - ]; - } - else // Register operand (ST(i)) - { - // Look up the instruction type in the register operations dictionary - if (RegisterOperations.TryGetValue((reg, rm), out var operation)) - { - instruction.Type = operation.Type; - - // Create the FPU register operands - var destOperand = OperandFactory.CreateFPURegisterOperand(operation.DestIndex); - var srcOperand = OperandFactory.CreateFPURegisterOperand(operation.SrcIndex); - - // Set the structured operands - instruction.StructuredOperands = - [ - destOperand, - srcOperand - ]; - } - else - { - // Unknown instruction - instruction.Type = InstructionType.Unknown; - instruction.StructuredOperands = []; - } - } - - return true; - } -} \ No newline at end of file diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FbldHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FbldHandler.cs new file mode 100644 index 0000000..a25ad22 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FbldHandler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FBLD packed BCD instruction (DF /4) +/// +public class FbldHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FbldHandler class + /// + /// The instruction decoder that owns this handler + public FbldHandler(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) + { + // FBLD is DF /4 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 4 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 4 + return reg == 4 && mod != 3; + } + + /// + /// Decodes a FBLD packed BCD 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fbld; + + // Create an 80-bit memory operand for packed BCD + Operand memoryOperand; + + if (rawMemoryOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 80); + } + else if (rawMemoryOperand is BaseRegisterMemoryOperand baseMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseMemory.BaseRegister, 80); + } + else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 80); + } + else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 80); + } + else + { + memoryOperand = rawMemoryOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FbstpHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FbstpHandler.cs new file mode 100644 index 0000000..774d787 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FbstpHandler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FBSTP packed BCD instruction (DF /6) +/// +public class FbstpHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FbstpHandler class + /// + /// The instruction decoder that owns this handler + public FbstpHandler(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) + { + // FBSTP is DF /6 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 6 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 6 + return reg == 6 && mod != 3; + } + + /// + /// Decodes a FBSTP packed BCD 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fbstp; + + // Create an 80-bit memory operand for packed BCD + Operand memoryOperand; + + if (rawMemoryOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 80); + } + else if (rawMemoryOperand is BaseRegisterMemoryOperand baseMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseMemory.BaseRegister, 80); + } + else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 80); + } + else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 80); + } + else + { + memoryOperand = rawMemoryOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt16Handler.cs new file mode 100644 index 0000000..fb166c3 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt16Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FILD int16 instruction (DF /0) +/// +public class FildInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FildInt16Handler class + /// + /// The instruction decoder that owns this handler + public FildInt16Handler(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) + { + // FILD int16 is DF /0 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 0 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 0 + return reg == 0 && mod != 3; + } + + /// + /// Decodes a FILD int16 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fild; + + // Create a 16-bit memory operand + Operand memoryOperand; + + if (rawMemoryOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 16); + } + else if (rawMemoryOperand is BaseRegisterMemoryOperand baseMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseMemory.BaseRegister, 16); + } + else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 16); + } + else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 16); + } + else + { + memoryOperand = rawMemoryOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt32Handler.cs new file mode 100644 index 0000000..b263c45 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt32Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FILD int32 instruction (DB /0) +/// +public class FildInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FildInt32Handler class + /// + /// The instruction decoder that owns this handler + public FildInt32Handler(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) + { + // FILD is DB /0 + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 0 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 0 && mod != 3; + } + + /// + /// Decodes a FILD int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fild; + + // Create a 32-bit memory operand for integer operations + Operand memoryOperand; + + if (rawOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 32); + } + else if (rawOperand is BaseRegisterMemoryOperand baseRegMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseRegMemory.BaseRegister, 32); + } + else if (rawOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 32); + } + else if (rawOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 32); + } + else + { + memoryOperand = rawOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt64Handler.cs new file mode 100644 index 0000000..1d14d08 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FildInt64Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FILD int64 instruction (DF /5) +/// +public class FildInt64Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FildInt64Handler class + /// + /// The instruction decoder that owns this handler + public FildInt64Handler(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) + { + // FILD int64 is DF /5 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 5 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 5 + return reg == 5 && mod != 3; + } + + /// + /// Decodes a FILD int64 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fild; + + // Create a 64-bit memory operand + Operand memoryOperand; + + if (rawMemoryOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 64); + } + else if (rawMemoryOperand is BaseRegisterMemoryOperand baseMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseMemory.BaseRegister, 64); + } + else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 64); + } + else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 64); + } + else + { + memoryOperand = rawMemoryOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistInt16Handler.cs new file mode 100644 index 0000000..84dae5d --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistInt16Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIST int16 instruction (DF /2) +/// +public class FistInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FistInt16Handler class + /// + /// The instruction decoder that owns this handler + public FistInt16Handler(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) + { + // FIST int16 is DF /2 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 2 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 2 + return reg == 2 && mod != 3; + } + + /// + /// Decodes a FIST int16 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fist; + + // Create a 16-bit memory operand + Operand memoryOperand; + + if (rawMemoryOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 16); + } + else if (rawMemoryOperand is BaseRegisterMemoryOperand baseMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseMemory.BaseRegister, 16); + } + else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 16); + } + else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 16); + } + else + { + memoryOperand = rawMemoryOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistInt32Handler.cs new file mode 100644 index 0000000..0a7bfab --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistInt32Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FIST int32 instruction (DB /2) +/// +public class FistInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FistInt32Handler class + /// + /// The instruction decoder that owns this handler + public FistInt32Handler(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) + { + // FIST is DB /2 + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 2 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 2 && mod != 3; + } + + /// + /// Decodes a FIST int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fist; + + // Create a 32-bit memory operand for integer operations + Operand memoryOperand; + + if (rawOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 32); + } + else if (rawOperand is BaseRegisterMemoryOperand baseRegMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseRegMemory.BaseRegister, 32); + } + else if (rawOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 32); + } + else if (rawOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 32); + } + else + { + memoryOperand = rawOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt16Handler.cs new file mode 100644 index 0000000..8e3a659 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt16Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FISTP int16 instruction (DF /3) +/// +public class FistpInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FistpInt16Handler class + /// + /// The instruction decoder that owns this handler + public FistpInt16Handler(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) + { + // FISTP int16 is DF /3 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 3 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 3 + return reg == 3 && mod != 3; + } + + /// + /// Decodes a FISTP int16 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fistp; + + // Create a 16-bit memory operand + Operand memoryOperand; + + if (rawMemoryOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 16); + } + else if (rawMemoryOperand is BaseRegisterMemoryOperand baseMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseMemory.BaseRegister, 16); + } + else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 16); + } + else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 16); + } + else + { + memoryOperand = rawMemoryOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt32Handler.cs new file mode 100644 index 0000000..030d7a2 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt32Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FISTP int32 instruction (DB /3) +/// +public class FistpInt32Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FistpInt32Handler class + /// + /// The instruction decoder that owns this handler + public FistpInt32Handler(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) + { + // FISTP is DB /3 + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 3 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 3 && mod != 3; + } + + /// + /// Decodes a FISTP int32 instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fistp; + + // Create a 32-bit memory operand for integer operations + Operand memoryOperand; + + if (rawOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 32); + } + else if (rawOperand is BaseRegisterMemoryOperand baseRegMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseRegMemory.BaseRegister, 32); + } + else if (rawOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 32); + } + else if (rawOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 32); + } + else + { + memoryOperand = rawOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt64Handler.cs new file mode 100644 index 0000000..8643228 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FistpInt64Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FISTP int64 instruction (DF /7) +/// +public class FistpInt64Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FistpInt64Handler class + /// + /// The instruction decoder that owns this handler + public FistpInt64Handler(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) + { + // FISTP int64 is DF /7 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 7 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 7 + return reg == 7 && mod != 3; + } + + /// + /// Decodes a FISTP int64 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fistp; + + // Create a 64-bit memory operand + Operand memoryOperand; + + if (rawMemoryOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 64); + } + else if (rawMemoryOperand is BaseRegisterMemoryOperand baseMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseMemory.BaseRegister, 64); + } + else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 64); + } + else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 64); + } + else + { + memoryOperand = rawMemoryOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FisttpInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FisttpInt16Handler.cs new file mode 100644 index 0000000..2226601 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FisttpInt16Handler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FISTTP int16 instruction (DF /1) +/// +public class FisttpInt16Handler : InstructionHandler +{ + /// + /// Initializes a new instance of the FisttpInt16Handler class + /// + /// The instruction decoder that owns this handler + public FisttpInt16Handler(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) + { + // FISTTP int16 is DF /1 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 1 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) with reg = 1 + return reg == 1 && mod != 3; + } + + /// + /// Decodes a FISTTP int16 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fisttp; + + // Create a 16-bit memory operand + Operand memoryOperand; + + if (rawMemoryOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 16); + } + else if (rawMemoryOperand is BaseRegisterMemoryOperand baseMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseMemory.BaseRegister, 16); + } + else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 16); + } + else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 16); + } + else + { + memoryOperand = rawMemoryOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FldExtendedHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FldExtendedHandler.cs new file mode 100644 index 0000000..ad0b422 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FldExtendedHandler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FLD extended-precision instruction (DB /5) +/// +public class FldExtendedHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FldExtendedHandler class + /// + /// The instruction decoder that owns this handler + public FldExtendedHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FLD extended-precision is DB /5 + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 5 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 5 && mod != 3; + } + + /// + /// Decodes a FLD extended-precision instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fld; + + // Create an 80-bit memory operand for extended precision operations + Operand memoryOperand; + + if (rawOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 80); + } + else if (rawOperand is BaseRegisterMemoryOperand baseRegMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseRegMemory.BaseRegister, 80); + } + else if (rawOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 80); + } + else if (rawOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 80); + } + else + { + memoryOperand = rawOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstRegisterHandler.cs new file mode 100644 index 0000000..ec5708e --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstRegisterHandler.cs @@ -0,0 +1,87 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FST ST(i) instruction (DD D0-D7) +/// +public class FstRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FstRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FstRegisterHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FST ST(i) is DD D0-D7 + if (opcode != 0xDD) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 2 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 = 2 + return reg == 2 && mod == 3; + } + + /// + /// Decodes a FST 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 + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fst; + + // Map rm field to FPU register index + FpuRegisterIndex stIndex = rm switch + { + RegisterIndex.A => FpuRegisterIndex.ST0, + RegisterIndex.C => FpuRegisterIndex.ST1, + RegisterIndex.D => FpuRegisterIndex.ST2, + RegisterIndex.B => FpuRegisterIndex.ST3, + RegisterIndex.Sp => FpuRegisterIndex.ST4, + RegisterIndex.Bp => FpuRegisterIndex.ST5, + RegisterIndex.Si => FpuRegisterIndex.ST6, + RegisterIndex.Di => FpuRegisterIndex.ST7, + _ => FpuRegisterIndex.ST0 // Default case, should not happen + }; + + // Create the FPU register operand + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpDfHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpDfHandler.cs new file mode 100644 index 0000000..b933da3 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpDfHandler.cs @@ -0,0 +1,70 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSTP instruction with DF opcode (DF D0-D8) +/// +public class FstpDfHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FstpDfHandler class + /// + /// The instruction decoder that owns this handler + public FstpDfHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FSTP with DF opcode is DF D0 or DF D8 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte is D0 (reg = 2, rm = 0, mod = 3) or D8 (reg = 3, rm = 0, mod = 3) + byte modRm = Decoder.PeakByte(); + return modRm == 0xD0 || modRm == 0xD8; + } + + /// + /// Decodes a FSTP instruction with DF opcode + /// + /// 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.Fstp; + + // Create the FPU register operand + // For both D0 and D8, the operand is ST1 + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST1); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpExtendedHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpExtendedHandler.cs new file mode 100644 index 0000000..3e895c2 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpExtendedHandler.cs @@ -0,0 +1,94 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSTP extended-precision instruction (DB /7) +/// +public class FstpExtendedHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FstpExtendedHandler class + /// + /// The instruction decoder that owns this handler + public FstpExtendedHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FSTP extended-precision is DB /7 + if (opcode != 0xDB) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 7 + byte modRm = Decoder.PeakByte(); + byte reg = (byte)((modRm >> 3) & 0x7); + byte mod = (byte)((modRm >> 6) & 0x3); + + // Only handle memory operands (mod != 3) + return reg == 7 && mod != 3; + } + + /// + /// Decodes a FSTP extended-precision instruction + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, rawOperand) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fstp; + + // Create an 80-bit memory operand for extended precision operations + Operand memoryOperand; + + if (rawOperand is DirectMemoryOperand directMemory) + { + memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 80); + } + else if (rawOperand is BaseRegisterMemoryOperand baseRegMemory) + { + memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseRegMemory.BaseRegister, 80); + } + else if (rawOperand is DisplacementMemoryOperand dispMemory) + { + memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 80); + } + else if (rawOperand is ScaledIndexMemoryOperand scaledMemory) + { + memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 80); + } + else + { + memoryOperand = rawOperand; + } + + // Set the structured operands + instruction.StructuredOperands = + [ + memoryOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpRegisterHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpRegisterHandler.cs new file mode 100644 index 0000000..3f8e958 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FstpRegisterHandler.cs @@ -0,0 +1,87 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FSTP ST(i) instruction (DD D8-DF) +/// +public class FstpRegisterHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FstpRegisterHandler class + /// + /// The instruction decoder that owns this handler + public FstpRegisterHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FSTP ST(i) is DD D8-DF + if (opcode != 0xDD) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte has reg field = 3 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 = 3 + return reg == 3 && mod == 3; + } + + /// + /// Decodes a FSTP 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 + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fstp; + + // Map rm field to FPU register index + FpuRegisterIndex stIndex = rm switch + { + RegisterIndex.A => FpuRegisterIndex.ST0, + RegisterIndex.C => FpuRegisterIndex.ST1, + RegisterIndex.D => FpuRegisterIndex.ST2, + RegisterIndex.B => FpuRegisterIndex.ST3, + RegisterIndex.Sp => FpuRegisterIndex.ST4, + RegisterIndex.Bp => FpuRegisterIndex.ST5, + RegisterIndex.Si => FpuRegisterIndex.ST6, + RegisterIndex.Di => FpuRegisterIndex.ST7, + _ => FpuRegisterIndex.ST0 // Default case, should not happen + }; + + // Create the FPU register operand + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(stIndex); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FxchDfHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FxchDfHandler.cs new file mode 100644 index 0000000..f7ec688 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStore/FxchDfHandler.cs @@ -0,0 +1,69 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.LoadStore; + +using X86Disassembler.X86.Operands; + +/// +/// Handler for FXCH instruction with DF opcode (DF C8) +/// +public class FxchDfHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FxchDfHandler class + /// + /// The instruction decoder that owns this handler + public FxchDfHandler(InstructionDecoder decoder) + : base(decoder) + { + } + + /// + /// Checks if this handler can decode the given opcode + /// + /// The opcode to check + /// True if this handler can decode the opcode + public override bool CanHandle(byte opcode) + { + // FXCH with DF opcode is DF C8 + if (opcode != 0xDF) return false; + + if (!Decoder.CanReadByte()) + { + return false; + } + + // Check if the ModR/M byte is exactly C8 (reg = 1, rm = 0, mod = 3) + byte modRm = Decoder.PeakByte(); + return modRm == 0xC8; + } + + /// + /// Decodes a FXCH instruction with DF opcode + /// + /// The opcode of the instruction + /// The instruction object to populate + /// True if the instruction was successfully decoded + public override bool Decode(byte opcode, Instruction instruction) + { + if (!Decoder.CanReadByte()) + { + return false; + } + + // Read the ModR/M byte + var (mod, reg, rm, _) = ModRMDecoder.ReadModRM(); + + // Set the instruction type + instruction.Type = InstructionType.Fxch; + + // Create the FPU register operand + var fpuRegisterOperand = OperandFactory.CreateFPURegisterOperand(FpuRegisterIndex.ST0); + + // Set the structured operands + instruction.StructuredOperands = + [ + fpuRegisterOperand + ]; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreControlHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreControlHandler.cs deleted file mode 100644 index 8669f91..0000000 --- a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreControlHandler.cs +++ /dev/null @@ -1,212 +0,0 @@ -using X86Disassembler.X86.Operands; - -namespace X86Disassembler.X86.Handlers.FloatingPoint; - -/// -/// Handler for floating-point load, store, and control operations (D9 opcode) -/// -public class LoadStoreControlHandler : InstructionHandler -{ - // Memory operand instruction types for D9 opcode - load, store, and control operations - private static readonly InstructionType[] MemoryInstructionTypes = - [ - InstructionType.Fld, // 0 - fld dword ptr [r/m] - InstructionType.Unknown, // 1 - (reserved) - InstructionType.Fst, // 2 - fst dword ptr [r/m] - InstructionType.Fstp, // 3 - fstp dword ptr [r/m] - InstructionType.Fldenv, // 4 - fldenv [r/m] - InstructionType.Fldcw, // 5 - fldcw [r/m] - InstructionType.Fnstenv, // 6 - fnstenv [r/m] - InstructionType.Fnstcw // 7 - fnstcw [r/m] - ]; - - // Register-register operations mapping (mod=3) - private static readonly Dictionary<(RegisterIndex Reg, RegisterIndex Rm), (InstructionType Type, FpuRegisterIndex? OperandIndex)> RegisterOperations = new() - { - // FLD ST(i) - { (RegisterIndex.A, RegisterIndex.A), (InstructionType.Fld, FpuRegisterIndex.ST0) }, - { (RegisterIndex.A, RegisterIndex.C), (InstructionType.Fld, FpuRegisterIndex.ST1) }, - { (RegisterIndex.A, RegisterIndex.D), (InstructionType.Fld, FpuRegisterIndex.ST2) }, - { (RegisterIndex.A, RegisterIndex.B), (InstructionType.Fld, FpuRegisterIndex.ST3) }, - { (RegisterIndex.A, RegisterIndex.Sp), (InstructionType.Fld, FpuRegisterIndex.ST4) }, - { (RegisterIndex.A, RegisterIndex.Bp), (InstructionType.Fld, FpuRegisterIndex.ST5) }, - { (RegisterIndex.A, RegisterIndex.Si), (InstructionType.Fld, FpuRegisterIndex.ST6) }, - { (RegisterIndex.A, RegisterIndex.Di), (InstructionType.Fld, FpuRegisterIndex.ST7) }, - - // FXCH ST(i) - { (RegisterIndex.B, RegisterIndex.A), (InstructionType.Fxch, FpuRegisterIndex.ST0) }, - { (RegisterIndex.B, RegisterIndex.C), (InstructionType.Fxch, FpuRegisterIndex.ST1) }, - { (RegisterIndex.B, RegisterIndex.D), (InstructionType.Fxch, FpuRegisterIndex.ST2) }, - { (RegisterIndex.B, RegisterIndex.B), (InstructionType.Fxch, FpuRegisterIndex.ST3) }, - { (RegisterIndex.B, RegisterIndex.Sp), (InstructionType.Fxch, FpuRegisterIndex.ST4) }, - { (RegisterIndex.B, RegisterIndex.Bp), (InstructionType.Fxch, FpuRegisterIndex.ST5) }, - { (RegisterIndex.B, RegisterIndex.Si), (InstructionType.Fxch, FpuRegisterIndex.ST6) }, - { (RegisterIndex.B, RegisterIndex.Di), (InstructionType.Fxch, FpuRegisterIndex.ST7) }, - - // D9E0-D9EF special instructions (reg=6) - { (RegisterIndex.Si, RegisterIndex.A), (InstructionType.Fchs, null) }, - { (RegisterIndex.Si, RegisterIndex.B), (InstructionType.Fabs, null) }, - { (RegisterIndex.Si, RegisterIndex.Si), (InstructionType.Ftst, null) }, - { (RegisterIndex.Si, RegisterIndex.Di), (InstructionType.Fxam, null) }, - - // D9F0-D9FF special instructions (reg=7) - { (RegisterIndex.Di, RegisterIndex.A), (InstructionType.F2xm1, null) }, - { (RegisterIndex.Di, RegisterIndex.B), (InstructionType.Fyl2x, null) }, - { (RegisterIndex.Di, RegisterIndex.C), (InstructionType.Fptan, null) }, - { (RegisterIndex.Di, RegisterIndex.D), (InstructionType.Fpatan, null) }, - { (RegisterIndex.Di, RegisterIndex.Si), (InstructionType.Fxtract, null) }, - { (RegisterIndex.Di, RegisterIndex.Di), (InstructionType.Fprem1, null) }, - { (RegisterIndex.Di, RegisterIndex.Sp), (InstructionType.Fdecstp, null) }, - { (RegisterIndex.Di, RegisterIndex.Bp), (InstructionType.Fincstp, null) }, - - // D9D0-D9DF special instructions (reg=5) - { (RegisterIndex.Sp, RegisterIndex.A), (InstructionType.Fprem, null) }, - { (RegisterIndex.Sp, RegisterIndex.B), (InstructionType.Fyl2xp1, null) }, - { (RegisterIndex.Sp, RegisterIndex.C), (InstructionType.Fsqrt, null) }, - { (RegisterIndex.Sp, RegisterIndex.D), (InstructionType.Fsincos, null) }, - { (RegisterIndex.Sp, RegisterIndex.Si), (InstructionType.Frndint, null) }, - { (RegisterIndex.Sp, RegisterIndex.Di), (InstructionType.Fscale, null) }, - { (RegisterIndex.Sp, RegisterIndex.Sp), (InstructionType.Fsin, null) }, - { (RegisterIndex.Sp, RegisterIndex.Bp), (InstructionType.Fcos, null) }, - - // D9C8-D9CF special instructions (reg=4) - { (RegisterIndex.Bp, RegisterIndex.A), (InstructionType.Fnop, null) }, - { (RegisterIndex.Bp, RegisterIndex.C), (InstructionType.Fwait, null) } - }; - - /// - /// Initializes a new instance of the LoadStoreControlHandler class - /// - /// The instruction decoder that owns this handler - public LoadStoreControlHandler(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) - { - return opcode == 0xD9; - } - - /// - /// Decodes a floating-point instruction for load, store, and control operations - /// - /// 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, rawMemoryOperand) = ModRMDecoder.ReadModRM(); - - // Handle based on addressing mode - if (mod != 3) // Memory operand - { - // Set the instruction type based on the reg field - instruction.Type = MemoryInstructionTypes[(int)reg]; - - // Create a new memory operand with the appropriate size based on the operation - Operand memoryOperand; - - if (reg == RegisterIndex.A || reg == RegisterIndex.C || reg == RegisterIndex.D) // fld, fst, fstp - { - // Create a 32-bit memory operand for floating point operations - if (rawMemoryOperand is DirectMemoryOperand directMemory) - { - memoryOperand = OperandFactory.CreateDirectMemoryOperand(directMemory.Address, 32); - } - else if (rawMemoryOperand is BaseRegisterMemoryOperand baseRegMemory) - { - memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand(baseRegMemory.BaseRegister, 32); - } - else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) - { - memoryOperand = OperandFactory.CreateDisplacementMemoryOperand(dispMemory.BaseRegister, dispMemory.Displacement, 32); - } - else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) - { - memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement, 32); - } - else - { - memoryOperand = rawMemoryOperand; - } - } - else if (reg == RegisterIndex.Di || reg == RegisterIndex.Bp) // fldcw, fnstcw - { - // Create a 16-bit memory operand for control word operations - if (rawMemoryOperand is DirectMemoryOperand directMemory) - { - memoryOperand = OperandFactory.CreateDirectMemoryOperand16(directMemory.Address); - } - else if (rawMemoryOperand is BaseRegisterMemoryOperand baseRegMemory) - { - memoryOperand = OperandFactory.CreateBaseRegisterMemoryOperand16(baseRegMemory.BaseRegister); - } - else if (rawMemoryOperand is DisplacementMemoryOperand dispMemory) - { - memoryOperand = OperandFactory.CreateDisplacementMemoryOperand16(dispMemory.BaseRegister, dispMemory.Displacement); - } - else if (rawMemoryOperand is ScaledIndexMemoryOperand scaledMemory) - { - memoryOperand = OperandFactory.CreateScaledIndexMemoryOperand16(scaledMemory.IndexRegister, scaledMemory.Scale, scaledMemory.BaseRegister, scaledMemory.Displacement); - } - else - { - memoryOperand = rawMemoryOperand; - } - } - else - { - memoryOperand = rawMemoryOperand; - } - - // Set the structured operands - instruction.StructuredOperands = - [ - memoryOperand - ]; - } - else // Register operand (ST(i)) - { - // Look up the instruction type in the register operations dictionary - if (RegisterOperations.TryGetValue((reg, rm), out var operation)) - { - instruction.Type = operation.Type; - - // Set the structured operands - if (operation.OperandIndex.HasValue) - { - var operand = OperandFactory.CreateFPURegisterOperand(operation.OperandIndex.Value); - instruction.StructuredOperands = - [ - operand - ]; - } - else - { - // No operands for instructions like fchs, fabs, etc. - instruction.StructuredOperands = []; - } - } - else - { - // Unknown instruction - instruction.Type = InstructionType.Unknown; - instruction.StructuredOperands = []; - } - } - - return true; - } -} diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 1fbe786..3147715 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -437,12 +437,85 @@ public class InstructionHandlerFactory // Other floating point handlers _handlers.Add(new FloatingPoint.Control.FnstswHandler(_decoder)); // FNSTSW AX (DF E0) - // Keep the existing handlers for operations not yet migrated to specialized handlers - _handlers.Add(new LoadStoreInt32Handler(_decoder)); // Load and store 32-bit values - _handlers.Add(new Float64OperationHandler(_decoder)); // Remaining float64 operations - _handlers.Add(new LoadStoreFloat64Handler(_decoder)); // Load and store 64-bit values - _handlers.Add(new Int16OperationHandler(_decoder)); // Integer operations on 16-bit values - _handlers.Add(new LoadStoreInt16Handler(_decoder)); // Load and store 16-bit values + // DB opcode handlers (int32 operations and extended precision) + _handlers.Add(new FloatingPoint.LoadStore.FildInt32Handler(_decoder)); // FILD int32 (DB /0) + _handlers.Add(new FloatingPoint.LoadStore.FistInt32Handler(_decoder)); // FIST int32 (DB /2) + _handlers.Add(new FloatingPoint.LoadStore.FistpInt32Handler(_decoder)); // FISTP int32 (DB /3) + _handlers.Add(new FloatingPoint.LoadStore.FldExtendedHandler(_decoder)); // FLD extended-precision (DB /5) + _handlers.Add(new FloatingPoint.LoadStore.FstpExtendedHandler(_decoder)); // FSTP extended-precision (DB /7) + + // DB opcode handlers (conditional move instructions) + _handlers.Add(new FloatingPoint.Conditional.FcmovnbHandler(_decoder)); // FCMOVNB (DB C0-C7) + _handlers.Add(new FloatingPoint.Conditional.FcmovneHandler(_decoder)); // FCMOVNE (DB C8-CF) + _handlers.Add(new FloatingPoint.Conditional.FcmovnbeHandler(_decoder)); // FCMOVNBE (DB D0-D7) + _handlers.Add(new FloatingPoint.Conditional.FcmovnuHandler(_decoder)); // FCMOVNU (DB D8-DF) + + // DB opcode handlers (control instructions) + _handlers.Add(new FloatingPoint.Control.FclexHandler(_decoder)); // FCLEX (DB E2) + _handlers.Add(new FloatingPoint.Control.FinitHandler(_decoder)); // FINIT (DB E3) + + // DB opcode handlers (comparison instructions) + _handlers.Add(new FloatingPoint.Comparison.FucomiHandler(_decoder)); // FUCOMI (DB E8-EF) + _handlers.Add(new FloatingPoint.Comparison.FcomiHandler(_decoder)); // FCOMI (DB F0-F7) + + // DC opcode handlers (register-register operations) + _handlers.Add(new FloatingPoint.Arithmetic.FaddRegisterHandler(_decoder)); // FADD ST(i), ST(0) (DC C0-C7) + _handlers.Add(new FloatingPoint.Arithmetic.FmulRegisterHandler(_decoder)); // FMUL ST(i), ST(0) (DC C8-CF) + _handlers.Add(new FloatingPoint.Comparison.FcomRegisterHandler(_decoder)); // FCOM ST(i), ST(0) (DC D0-D7) + _handlers.Add(new FloatingPoint.Comparison.FcompRegisterHandler(_decoder)); // FCOMP ST(i), ST(0) (DC D8-DF) + _handlers.Add(new FloatingPoint.Arithmetic.FsubRegisterHandler(_decoder)); // FSUB ST(i), ST(0) (DC E0-E7) + _handlers.Add(new FloatingPoint.Arithmetic.FsubrRegisterHandler(_decoder)); // FSUBR ST(i), ST(0) (DC E8-EF) + _handlers.Add(new FloatingPoint.Arithmetic.FdivRegisterHandler(_decoder)); // FDIV ST(i), ST(0) (DC F0-F7) + _handlers.Add(new FloatingPoint.Arithmetic.FdivrRegisterHandler(_decoder)); // FDIVR ST(i), ST(0) (DC F8-FF) + + // DD opcode handlers (register operations) + _handlers.Add(new FloatingPoint.Control.FfreeHandler(_decoder)); // FFREE ST(i) (DD C0-C7) + _handlers.Add(new FloatingPoint.LoadStore.FstRegisterHandler(_decoder)); // FST ST(i) (DD D0-D7) + _handlers.Add(new FloatingPoint.LoadStore.FstpRegisterHandler(_decoder)); // FSTP ST(i) (DD D8-DF) + _handlers.Add(new FloatingPoint.Comparison.FucomHandler(_decoder)); // FUCOM ST(i) (DD E0-E7) + _handlers.Add(new FloatingPoint.Comparison.FucompHandler(_decoder)); // FUCOMP ST(i) (DD E8-EF) + + // DD opcode handlers (memory operations) + _handlers.Add(new FloatingPoint.Control.FrstorHandler(_decoder)); // FRSTOR (DD /4) + _handlers.Add(new FloatingPoint.Control.FnsaveHandler(_decoder)); // FNSAVE (DD /6) + _handlers.Add(new FloatingPoint.Control.FnstswMemoryHandler(_decoder)); // FNSTSW memory (DD /7) + + // DE opcode handlers (memory operations) + _handlers.Add(new FloatingPoint.Arithmetic.FiaddInt16Handler(_decoder)); // FIADD int16 (DE /0) + _handlers.Add(new FloatingPoint.Arithmetic.FimulInt16Handler(_decoder)); // FIMUL int16 (DE /1) + _handlers.Add(new FloatingPoint.Comparison.FicomInt16Handler(_decoder)); // FICOM int16 (DE /2) + _handlers.Add(new FloatingPoint.Comparison.FicompInt16Handler(_decoder)); // FICOMP int16 (DE /3) + _handlers.Add(new FloatingPoint.Arithmetic.FisubInt16Handler(_decoder)); // FISUB int16 (DE /4) + _handlers.Add(new FloatingPoint.Arithmetic.FisubrInt16Handler(_decoder)); // FISUBR int16 (DE /5) + _handlers.Add(new FloatingPoint.Arithmetic.FidivInt16Handler(_decoder)); // FIDIV int16 (DE /6) + _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.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) + + // DF opcode handlers (memory operations) + _handlers.Add(new FloatingPoint.LoadStore.FildInt16Handler(_decoder)); // FILD int16 (DF /0) + _handlers.Add(new FloatingPoint.LoadStore.FisttpInt16Handler(_decoder)); // FISTTP int16 (DF /1) + _handlers.Add(new FloatingPoint.LoadStore.FistInt16Handler(_decoder)); // FIST int16 (DF /2) + _handlers.Add(new FloatingPoint.LoadStore.FistpInt16Handler(_decoder)); // FISTP int16 (DF /3) + _handlers.Add(new FloatingPoint.LoadStore.FbldHandler(_decoder)); // FBLD packed BCD (DF /4) + _handlers.Add(new FloatingPoint.LoadStore.FildInt64Handler(_decoder)); // FILD int64 (DF /5) + _handlers.Add(new FloatingPoint.LoadStore.FbstpHandler(_decoder)); // FBSTP packed BCD (DF /6) + _handlers.Add(new FloatingPoint.LoadStore.FistpInt64Handler(_decoder)); // FISTP int64 (DF /7) + + // DF opcode handlers (register operations) + _handlers.Add(new FloatingPoint.Control.FfreepHandler(_decoder)); // FFREEP ST(i) (DF C0-C7) + _handlers.Add(new FloatingPoint.LoadStore.FxchDfHandler(_decoder)); // FXCH (DF C8) + _handlers.Add(new FloatingPoint.LoadStore.FstpDfHandler(_decoder)); // FSTP ST(1) (DF D0, DF D8) + _handlers.Add(new FloatingPoint.Comparison.FucomipHandler(_decoder)); // FUCOMIP ST(0), ST(i) (DF E8-EF) + _handlers.Add(new FloatingPoint.Comparison.FcomipHandler(_decoder)); // FCOMIP ST(0), ST(i) (DF F0-F7) } /// diff --git a/X86DisassemblerTests/TestData/string_tests.csv b/X86DisassemblerTests/TestData/string_tests.csv index 57cf024..eb27ec9 100644 --- a/X86DisassemblerTests/TestData/string_tests.csv +++ b/X86DisassemblerTests/TestData/string_tests.csv @@ -5,12 +5,12 @@ RawBytes;Instructions # MOVS - Move string A4;[{ "Type": "MovsB", "Operands": ["byte ptr es:[edi]", "byte ptr ds:[esi]"] }] A5;[{ "Type": "MovsD", "Operands": ["dword ptr es:[edi]", "dword ptr ds:[esi]"] }] -66A5;[{ "Type": "MovsW", "Operands": ["word ptr es:[edi]", "byte ptr es:[esi]"] }] +66A5;[{ "Type": "MovsW", "Operands": ["word ptr es:[edi]", "word ptr ds:[esi]"] }] # CMPS - Compare string -A6;[{ "Type": "CmpsB", "Operands": ["byte ptr es:[esi]", "byte ptr es:[edi]"] }] -A7;[{ "Type": "CmpsD", "Operands": ["dword ptr es:[esi]", "dword ptr es:[edi]"] }] -66A7;[{ "Type": "CmpsW", "Operands": ["word ptr es:[esi]", "word ptr es:[edi]"] }] +A6;[{ "Type": "CmpsB", "Operands": ["byte ptr ds:[esi]", "byte ptr es:[edi]"] }] +A7;[{ "Type": "CmpsD", "Operands": ["dword ptr ds:[esi]", "dword ptr es:[edi]"] }] +66A7;[{ "Type": "CmpsW", "Operands": ["word ptr ds:[esi]", "word ptr es:[edi]"] }] # SCAS - Scan string AE;[{ "Type": "ScasB", "Operands": ["al", "byte ptr es:[edi]"] }] @@ -20,7 +20,7 @@ AF;[{ "Type": "ScasD", "Operands": ["eax", "dword ptr es:[edi]"] }] # LODS - Load string AC;[{ "Type": "LodsB", "Operands": ["al", "byte ptr ds:[esi]"] }] AD;[{ "Type": "LodsD", "Operands": ["eax", "dword ptr ds:[esi]"] }] -66AD;[{ "Type": "LodsW", "Operands": ["ax", "byte ptr ds:[esi]"] }] +66AD;[{ "Type": "LodsW", "Operands": ["ax", "word ptr ds:[esi]"] }] # STOS - Store string AA;[{ "Type": "StosB", "Operands": ["byte ptr es:[edi]", "al"] }] @@ -36,17 +36,17 @@ F3AB;[{ "Type": "RepStosD", "Operands": ["dword ptr es:[edi]", "eax"] }] F366AB;[{ "Type": "RepStosW", "Operands": ["word ptr es:[edi]", "ax"] }] # REPE/REPZ prefix with string instructions -F3A6;[{ "Type": "RepeCmpsB", "Operands": ["byte ptr es:[esi]", "byte ptr es:[edi]"] }] -F3A7;[{ "Type": "RepeCmpsD", "Operands": ["dword ptr es:[esi]", "byte ptr es:[edi]"] }] -F366A7;[{ "Type": "RepeCmpsW", "Operands": ["word ptr es:[esi]", "word ptr es:[edi]"] }] +F3A6;[{ "Type": "RepeCmpsB", "Operands": ["byte ptr ds:[esi]", "byte ptr es:[edi]"] }] +F3A7;[{ "Type": "RepeCmpsD", "Operands": ["dword ptr ds:[esi]", "dword ptr es:[edi]"] }] +F366A7;[{ "Type": "RepeCmpsW", "Operands": ["word ptr ds:[esi]", "word ptr es:[edi]"] }] F3AE;[{ "Type": "RepScasB", "Operands": ["al", "byte ptr es:[edi]"] }] F3AF;[{ "Type": "RepScasD", "Operands": ["eax", "dword ptr es:[edi]"] }] F366AF;[{ "Type": "RepScasW", "Operands": ["ax", "word ptr es:[edi]"] }] # REPNE/REPNZ prefix with string instructions -F2A6;[{ "Type": "RepneCmpsB", "Operands": ["byte ptr es:[esi]", "byte ptr es:[edi]"] }] -F2A7;[{ "Type": "RepneCmpsD", "Operands": ["dword ptr es:[esi]", "dword ptr es:[edi]"] }] -F266A7;[{ "Type": "RepneCmpsW", "Operands": ["word ptr es:[esi]", "word ptr es:[edi]"] }] +F2A6;[{ "Type": "RepneCmpsB", "Operands": ["byte ptr ds:[esi]", "byte ptr es:[edi]"] }] +F2A7;[{ "Type": "RepneCmpsD", "Operands": ["dword ptr ds:[esi]", "dword ptr es:[edi]"] }] +F266A7;[{ "Type": "RepneCmpsW", "Operands": ["word ptr ds:[esi]", "word ptr es:[edi]"] }] F2AE;[{ "Type": "RepneScasB", "Operands": ["al", "byte ptr es:[edi]"] }] -F2AF;[{ "Type": "RepneScasD", "Operands": ["eax", "byte ptr es:[edi]"] }] -F266AF;[{ "Type": "RepneScasW", "Operands": ["eax", "byte ptr es:[edi]"] }] +F2AF;[{ "Type": "RepneScasD", "Operands": ["eax", "dword ptr es:[edi]"] }] +F266AF;[{ "Type": "RepneScasW", "Operands": ["ax", "word ptr es:[edi]"] }]