From 35a66c03c24664d229bbd20fc3ed67539806a022 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 7 Mar 2022 10:32:34 -0500 Subject: [PATCH] Add the SETs. --- InstructionSets/x86/Decoder.cpp | 59 +++++++++++++------ InstructionSets/x86/Decoder.hpp | 6 +- .../x86/Documentation/80386 opcode map.html | 18 +++--- InstructionSets/x86/Instruction.hpp | 3 + 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/InstructionSets/x86/Decoder.cpp b/InstructionSets/x86/Decoder.cpp index b22edc312..b0ca271cf 100644 --- a/InstructionSets/x86/Decoder.cpp +++ b/InstructionSets/x86/Decoder.cpp @@ -267,18 +267,18 @@ std::pair::InstructionT> Decoder::decode(con case 0x82: MemRegReg(Invalid, MemRegADD_to_CMP_SignExtend, DataSize::Byte); break; case 0x83: MemRegReg(Invalid, MemRegADD_to_CMP_SignExtend, data_size_); break; - case 0x84: MemRegReg(TEST, MemReg_Reg, DataSize::Byte); break; - case 0x85: MemRegReg(TEST, MemReg_Reg, data_size_); break; - case 0x86: MemRegReg(XCHG, Reg_MemReg, DataSize::Byte); break; - case 0x87: MemRegReg(XCHG, Reg_MemReg, data_size_); break; - case 0x88: MemRegReg(MOV, MemReg_Reg, DataSize::Byte); break; - case 0x89: MemRegReg(MOV, MemReg_Reg, data_size_); break; - case 0x8a: MemRegReg(MOV, Reg_MemReg, DataSize::Byte); break; - case 0x8b: MemRegReg(MOV, Reg_MemReg, data_size_); break; - case 0x8c: MemRegReg(MOV, MemReg_Seg, DataSize::Word); break; - case 0x8d: MemRegReg(LEA, Reg_MemReg, data_size_); break; - case 0x8e: MemRegReg(MOV, Seg_MemReg, DataSize::Word); break; - case 0x8f: MemRegReg(POP, MemRegPOP, data_size_); break; + case 0x84: MemRegReg(TEST, MemReg_Reg, DataSize::Byte); break; + case 0x85: MemRegReg(TEST, MemReg_Reg, data_size_); break; + case 0x86: MemRegReg(XCHG, Reg_MemReg, DataSize::Byte); break; + case 0x87: MemRegReg(XCHG, Reg_MemReg, data_size_); break; + case 0x88: MemRegReg(MOV, MemReg_Reg, DataSize::Byte); break; + case 0x89: MemRegReg(MOV, MemReg_Reg, data_size_); break; + case 0x8a: MemRegReg(MOV, Reg_MemReg, DataSize::Byte); break; + case 0x8b: MemRegReg(MOV, Reg_MemReg, data_size_); break; + case 0x8c: MemRegReg(MOV, MemReg_Seg, DataSize::Word); break; + case 0x8d: MemRegReg(LEA, Reg_MemReg, data_size_); break; + case 0x8e: MemRegReg(MOV, Seg_MemReg, DataSize::Word); break; + case 0x8f: MemRegReg(POP, MemRegSingleOperand, data_size_); break; case 0x90: Complete(NOP, None, None, DataSize::None); break; // Or XCHG AX, AX? case 0x91: Complete(XCHG, eAX, eCX, data_size_); break; @@ -474,8 +474,28 @@ std::pair::InstructionT> Decoder::decode(con case 0x7e: RequiresMin(i80386); Displacement(JLE, data_size_); break; case 0x7f: RequiresMin(i80386); Displacement(JNLE, data_size_); break; - // TODO: [0x90, 0x97]: byte set on condition Eb: SETO, SETNO, SETB, SETNB, SETZ, SETNZ, SETBE, SETNBE - // TODO: [0x98, 0x9f]: SETS, SETNS, SETP, SETNP, SETL, SETNL, SETLE, SETNLE +#define Set(x) \ + RequiresMin(i80386); \ + MemRegReg(SET##x, MemRegSingleOperand, DataSize::Byte); + + case 0x90: Set(O); break; + case 0x91: Set(NO); break; + case 0x92: Set(B); break; + case 0x93: Set(NB); break; + case 0x94: Set(Z); break; + case 0x95: Set(NZ); break; + case 0x96: Set(BE); break; + case 0x97: Set(NBE); break; + case 0x98: Set(S); break; + case 0x99: Set(NS); break; + case 0x9a: Set(P); break; + case 0x9b: Set(NP); break; + case 0x9c: Set(L); break; + case 0x9d: Set(NL); break; + case 0x9e: Set(LE); break; + case 0x9f: Set(NLE); break; + +#undef Set case 0xa0: RequiresMin(i80386); Complete(PUSH, FS, None, data_size_); break; case 0xa1: RequiresMin(i80386); Complete(POP, FS, None, data_size_); break; @@ -568,8 +588,13 @@ std::pair::InstructionT> Decoder::decode(con case 3: memreg = reg_table[rm]; - // LES and LDS accept a memory argument only, not a register. - if(operation_ == Operation::LES || operation_ == Operation::LDS) { + // LES, LDS, etc accept a memory argument only, not a register. + if( + operation_ == Operation::LES || + operation_ == Operation::LDS || + operation_ == Operation::LGS || + operation_ == Operation::LSS || + operation_ == Operation::LFS) { undefined(); } break; @@ -678,7 +703,7 @@ std::pair::InstructionT> Decoder::decode(con } break; - case ModRegRMFormat::MemRegPOP: + case ModRegRMFormat::MemRegSingleOperand: source_ = destination_ = memreg; if(reg != 0) { diff --git a/InstructionSets/x86/Decoder.hpp b/InstructionSets/x86/Decoder.hpp index 041937fb6..6f0c4a6aa 100644 --- a/InstructionSets/x86/Decoder.hpp +++ b/InstructionSets/x86/Decoder.hpp @@ -70,13 +70,11 @@ template class Decoder { Reg_MemReg, // Parse for mode and register/memory fields, populating both - // source_ and destination_ fields with the result. Use the 'register' - // field to check for the POP operation. - MemRegPOP, + // source_ and destination_ fields with the single register/memory result. + MemRegSingleOperand, // Parse for mode and register/memory fields, populating both // the destination_ field with the result and setting source_ to Immediate. - // Use the 'register' field to check for the MOV operation. MemRegMOV, // Parse for mode and register/memory fields, populating the diff --git a/InstructionSets/x86/Documentation/80386 opcode map.html b/InstructionSets/x86/Documentation/80386 opcode map.html index e1dcbe5bc..9b9b05252 100644 --- a/InstructionSets/x86/Documentation/80386 opcode map.html +++ b/InstructionSets/x86/Documentation/80386 opcode map.html @@ -700,15 +700,7 @@ 9x - Byte set on condition (Eb) - SETS - SETNS - SETP - SETNP - SETL - SETNL - SETLE - SETNLE + Byte set on condition (Eb) @@ -720,6 +712,14 @@ SETNZ SETBE SETNBE + SETS + SETNS + SETP + SETNP + SETL + SETNL + SETLE + SETNLE Ax diff --git a/InstructionSets/x86/Instruction.hpp b/InstructionSets/x86/Instruction.hpp index 618545ab7..ba55df6fe 100644 --- a/InstructionSets/x86/Instruction.hpp +++ b/InstructionSets/x86/Instruction.hpp @@ -325,6 +325,9 @@ enum class Operation: uint8_t { IRETD, JECXZ, LODSD, + + SETO, SETNO, SETB, SETNB, SETZ, SETNZ, SETBE, SETNBE, + SETS, SETNS, SETP, SETNP, SETL, SETNL, SETLE, SETNLE, }; enum class DataSize: uint8_t {