From 30c2c0f050ad083e70a7e75b521c112465c212a2 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 7 Jan 2021 21:59:00 -0500 Subject: [PATCH] Attempts to complete operand recognition. --- Processors/Decoders/x86/x86.cpp | 55 ++++++++++++++++++++++++++------- Processors/Decoders/x86/x86.hpp | 16 ++++++++-- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/Processors/Decoders/x86/x86.cpp b/Processors/Decoders/x86/x86.cpp index 2837cec08..236289bf9 100644 --- a/Processors/Decoders/x86/x86.cpp +++ b/Processors/Decoders/x86/x86.cpp @@ -285,9 +285,9 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) { case 0xe7: AddrReg(OUT, AX, 2, 1); break; case 0xe8: RegData(CALLD, None, 2); break; - case 0xe9: RegData(JMP, None, 2); break; - case 0xea: Far(JMP); break; - case 0xeb: Jump(JMP); break; + case 0xe9: RegData(JMPN, None, 2); break; + case 0xea: Far(JMPF); break; + case 0xeb: Jump(JMPN); break; case 0xec: Complete(IN, DX, AL, 1); break; case 0xed: Complete(IN, DX, AX, 1); break; @@ -306,14 +306,8 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) { case 0xfc: Complete(CLD, None, None, 1); break; case 0xfd: Complete(STD, None, None, 1); break; - /* - Unimplemented (but should be): - - 0xfe, 0xff - - [and consider which others are unused but seem to be - known to consume a second byte?] - */ + case 0xfe: MemRegReg(Invalid, MemRegINC_DEC, 1); break; + case 0xff: MemRegReg(Invalid, MemRegINC_to_PUSH, 1); break; // Other prefix bytes. case 0xf0: lock_ = true; break; @@ -444,6 +438,45 @@ Instruction Decoder::decode(const uint8_t *source, size_t length) { } break; + case ModRegRMFormat::MemRegINC_DEC: + source_ = destination_ = memreg; + + switch(reg) { + default: + reset_parsing(); + return Instruction(consumed_); + + case 0: operation_ = Operation::INC; break; + case 1: operation_ = Operation::DEC; break; + } + break; + + case ModRegRMFormat::MemRegINC_to_PUSH: + source_ = destination_ = memreg; + + switch(reg) { + default: + reset_parsing(); + return Instruction(consumed_); + + case 0: operation_ = Operation::INC; break; + case 1: operation_ = Operation::DEC; break; + case 2: operation_ = Operation::CALLN; break; + case 3: + operation_ = Operation::CALLF; + operand_size_ = 4; + source_ = Source::Immediate; + break; + case 4: operation_ = Operation::JMPN; break; + case 5: + operation_ = Operation::JMPF; + operand_size_ = 4; + source_ = Source::Immediate; + break; + case 6: operation_ = Operation::PUSH; break; + } + break; + case ModRegRMFormat::MemRegPOP: source_ = destination_ = memreg; diff --git a/Processors/Decoders/x86/x86.hpp b/Processors/Decoders/x86/x86.hpp index bb6a7b312..7f43b8ca9 100644 --- a/Processors/Decoders/x86/x86.hpp +++ b/Processors/Decoders/x86/x86.hpp @@ -41,7 +41,7 @@ enum class Operation: uint8_t { CALLF, /// Displacement call; followed by a 16-bit operand providing a call offset. CALLD, - /* TODO: other CALLs */ + CALLN, /// Convert byte into word; source will be AL, destination will be AH. CBW, /// Clear carry flag; no source or destination provided. @@ -68,7 +68,9 @@ enum class Operation: uint8_t { INC, INT, INT3, INTO, IRET, JO, JNO, JB, JNB, JE, JNE, JBE, JNBE, JS, JNS, JP, JNP, JL, JNL, JLE, JNLE, - JMP, JCXZ, + JMPN, + JMPF, + JCXZ, LAHF, LDS, LEA, LODS, LOOPE, LOOPNE, MOV, MOVS, MUL, NEG, NOP, NOT, OR, OUT, POP, POPF, PUSH, PUSHF, RCL, RCR, REP, ROL, ROR, SAHF, @@ -210,6 +212,16 @@ struct Decoder { // register based on the reg field. SegReg, + // Parse for mode and register/memory fields, populating the + // source_ and destination_ fields with the result. Uses the + // 'register' field to pick INC or DEC. + MemRegINC_DEC, + + // Parse for mode and register/memory fields, populating the + // source_ and destination_ fields with the result. Uses the + // 'register' field to pick from INC/DEC/CALL/JMP/PUSH, altering + // the source to ::Immediate and setting an operand size if necessary. + MemRegINC_to_PUSH, } modregrm_format_ = ModRegRMFormat::MemReg_Reg; // Ephemeral decoding state.