From 6ea208d8bfa13653a94aec2439e96407cff0109d Mon Sep 17 00:00:00 2001 From: bird_egop Date: Fri, 18 Apr 2025 13:08:18 +0300 Subject: [PATCH] Fix FCLEX/FNCLEX instruction types and rename handler for consistency --- .../FloatingPoint/Control/FclexHandler.cs | 2 +- .../FloatingPoint/Control/FclexWaitHandler.cs | 71 +++++++++++++++++++ .../X86/Handlers/InstructionHandlerFactory.cs | 3 +- 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexWaitHandler.cs diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexHandler.cs index bf04f46..89802d3 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexHandler.cs @@ -53,7 +53,7 @@ public class FclexHandler : InstructionHandler byte secondByte = Decoder.ReadByte(); // Set the instruction type - instruction.Type = InstructionType.Fclex; + instruction.Type = InstructionType.Fnclex; // FCLEX has no operands instruction.StructuredOperands = []; diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexWaitHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexWaitHandler.cs new file mode 100644 index 0000000..ce8b076 --- /dev/null +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Control/FclexWaitHandler.cs @@ -0,0 +1,71 @@ +namespace X86Disassembler.X86.Handlers.FloatingPoint.Control; + +/// +/// Handler for FCLEX instruction with WAIT prefix (0x9B 0xDB 0xE2) +/// +public class FclexWaitHandler : InstructionHandler +{ + /// + /// Initializes a new instance of the FclexWaitHandler class + /// + /// The instruction decoder that owns this handler + public FclexWaitHandler(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 with WAIT prefix starts with 0x9B + if (opcode != 0x9B) return false; + + // Check if we can read the next two bytes + if (!Decoder.CanReadByte()) + return false; + + // Check if the next bytes are 0xDB 0xE2 (for FCLEX with WAIT) + var (nextByte, thirdByte) = Decoder.PeakTwoBytes(); + + // The sequence must be 9B DB E2 for FCLEX with WAIT + return nextByte == 0xDB && thirdByte == 0xE2; + } + + /// + /// Decodes a FCLEX instruction with WAIT prefix + /// + /// 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) + { + // Skip the WAIT prefix (0x9B) - we already read it in CanHandle + if (!Decoder.CanReadByte()) + return false; + + // Read the second byte (0xDB) + byte secondByte = Decoder.ReadByte(); + if (secondByte != 0xDB) + return false; + + // Read the third byte (0xE2) + if (!Decoder.CanReadByte()) + return false; + + byte thirdByte = Decoder.ReadByte(); + if (thirdByte != 0xE2) + return false; + + // Set the instruction type + instruction.Type = InstructionType.Fclex; + + // FCLEX has no operands + instruction.StructuredOperands = []; + + return true; + } +} diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs index 57ad0b6..37c6aed 100644 --- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs +++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs @@ -435,7 +435,8 @@ public class InstructionHandlerFactory _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.FclexHandler(_decoder)); // FNCLEX (DB E2) + _handlers.Add(new FloatingPoint.Control.FclexWaitHandler(_decoder)); // FCLEX (9B DB E2) _handlers.Add(new FloatingPoint.Control.FinitHandler(_decoder)); // FINIT (DB E3) // DB opcode handlers (comparison instructions)