#include "Assembly.h" #include "InMemoryBuffer.h" struct MachineCodeInstruction { bool needsRex; char opcode[3]; char opcodeLength; bool needsModRM; char modRM; bool sibNeeded; char sib; char disp[4]; char dispLength; char imm[8]; char immLength; bool operandSizeOverride; bool errIfRex; bool errIfNoRex; bool exR; bool exX; bool exB; bool vexL; bool exWE; int vexVVVV; char vexPP; bool needsVex; void write(Framework::StreamWriter& writer) const { if (operandSizeOverride) { char prefix = 0x66; writer.schreibe(&prefix, 1); } if (needsRex && !needsVex) { char rex = 0b01000000 | ((exWE & 0b1) << 3) | ((exR & 0b1) << 2) | ((exX & 0b1) << 1) | (exB & 0b1); writer.schreibe(&rex, 1); } int opCodeOffset = 0; if (needsVex) { char vexMapSelect = 0; if (opcode[0] == 0x0F) { opCodeOffset = 1; vexMapSelect = 1; if (opcode[1] == 0x38) { vexMapSelect = 2; opCodeOffset = 2; } else if (opcode[1] == 0x3A) { vexMapSelect = 3; opCodeOffset = 2; } } if (exX || exB || exWE || vexMapSelect != 1) { // 3-byte VEX char vex2[3]; vex2[0] = (char)0xC4; vex2[1] = (((~(char)exR) & 0b1) << 7) | (((~(char)exX) & 0b1) << 6) | (((~(char)exB) & 0b1) << 5) | (vexMapSelect & 0b11111); vex2[2] = ((exWE & 0b1) << 7) | (((~(char)vexVVVV) & 0b1111) << 3) | ((vexL & 0b1) << 2) | (vexPP & 0b11); writer.schreibe(vex2, 3); } else { // 2-byte VEX char vex2[2]; vex2[0] = (char)0xC5; vex2[1] = (((~(char)exR) & 0b1) << 7) | (((~(char)vexVVVV) & 0b1111) << 3) | ((vexL & 0b1) << 2) | (vexPP & 0b11); writer.schreibe(vex2, 2); } } writer.schreibe(opcode + opCodeOffset, opcodeLength - opCodeOffset); if (needsModRM) { writer.schreibe(&modRM, 1); } if (sibNeeded) { writer.schreibe(&sib, 1); } if (dispLength > 0) { writer.schreibe(disp, dispLength); } if (immLength > 0) { writer.schreibe(imm, immLength); } } int calculateSize() const { int size = 0; if (operandSizeOverride) { size += 1; } if (needsRex && !needsVex) { size += 1; } int opCodeOffset = 0; if (needsVex) { char vexMapSelect = 0; if (opcode[0] == 0x0F) { opCodeOffset = 1; vexMapSelect = 1; if (opcode[1] == 0x38) { vexMapSelect = 2; opCodeOffset = 2; } else if (opcode[1] == 0x3A) { vexMapSelect = 3; opCodeOffset = 2; } } if (exX || exB || exWE || vexMapSelect != 1) { size += 3; } else { size += 2; } } size += opcodeLength - opCodeOffset; if (needsModRM) { size += 1; } if (sibNeeded) { size += 1; } size += dispLength; size += immLength; return size; } }; enum OperandEncoding { UNDEFINED, MODRM_REG, MODRM_RM, VEX_VVVV, OPCODE_RD, // EVEX_VVVV, IMM8, IMM16, IMM32, IMM64, }; enum OperandRW { NONE = 0, READ = 1, WRITE = 2, READWRITE = 3, }; class MachineCodeTableEntry { private: int numArgs; std::function op1Validator; std::function op2Validator; std::function op3Validator; std::function op4Validator; bool vex; bool vexL; char vexPP; bool rexW; char rmReg; char opcode[3]; char opcodeLength; OperandEncoding op1Encoding; OperandEncoding op2Encoding; OperandEncoding op3Encoding; OperandEncoding op4Encoding; OperandRW op1RW; OperandRW op2RW; OperandRW op3RW; OperandRW op4RW; std::vector impliedReadGPRegs; std::vector impliedWriteGPRegs; std::vector impliedReadFPRegs; std::vector impliedWriteFPRegs; bool operandSizeOverride; public: MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg) : numArgs(0), rexW(rexW), rmReg(rmReg), opcodeLength(opcodeLength), operandSizeOverride(operandSizeOverride), vex(vex), vexL(vexL), vexPP(vexPP), op1Encoding(UNDEFINED), op2Encoding(UNDEFINED), op3Encoding(UNDEFINED), op4Encoding(UNDEFINED), op1RW(NONE), op2RW(NONE), op3RW(NONE), op4RW(NONE) { this->opcode[0] = (char)(opcode & 0xFF); this->opcode[1] = (char)((opcode >> 8) & 0xFF); this->opcode[2] = (char)((opcode >> 16) & 0xFF); } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::initializer_list impliedReadGPRegs, std::initializer_list impliedWriteGPRegs, std::initializer_list impliedReadFPRegs, std::initializer_list impliedWriteFPRegs) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg) { this->opcode[0] = (char)(opcode & 0xFF); this->opcode[1] = (char)((opcode >> 8) & 0xFF); this->opcode[2] = (char)((opcode >> 16) & 0xFF); this->impliedReadGPRegs = impliedReadGPRegs; this->impliedWriteGPRegs = impliedWriteGPRegs; this->impliedReadFPRegs = impliedReadFPRegs; this->impliedWriteFPRegs = impliedWriteFPRegs; } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::function op1Validator, OperandEncoding op1Encoding, OperandRW op1RW) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg) { numArgs = 1; this->op1Validator = op1Validator; this->op1Encoding = op1Encoding; this->op1RW = op1RW; } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::initializer_list impliedReadGPRegs, std::initializer_list impliedWriteGPRegs, std::initializer_list impliedReadFPRegs, std::initializer_list impliedWriteFPRegs, std::function op1Validator, OperandEncoding op1Encoding, OperandRW op1RW) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg, impliedReadGPRegs, impliedWriteGPRegs, impliedReadFPRegs, impliedWriteFPRegs) { numArgs = 1; this->op1Validator = op1Validator; this->op1Encoding = op1Encoding; this->op1RW = op1RW; } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::function op1Validator, OperandEncoding op1Encoding, OperandRW op1RW, std::function op2Validator, OperandEncoding op2Encoding, OperandRW op2RW) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg, op1Validator, op1Encoding, op1RW) { numArgs = 2; this->op2Validator = op2Validator; this->op2Encoding = op2Encoding; this->op2RW = op2RW; } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::initializer_list impliedReadGPRegs, std::initializer_list impliedWriteGPRegs, std::initializer_list impliedReadFPRegs, std::initializer_list impliedWriteFPRegs, std::function op1Validator, OperandEncoding op1Encoding, OperandRW op1RW, std::function op2Validator, OperandEncoding op2Encoding, OperandRW op2RW) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg, impliedReadGPRegs, impliedWriteGPRegs, impliedReadFPRegs, impliedWriteFPRegs, op1Validator, op1Encoding, op1RW) { numArgs = 2; this->op2Validator = op2Validator; this->op2Encoding = op2Encoding; this->op2RW = op2RW; } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::function op1Validator, OperandEncoding op1Encoding, OperandRW op1RW, std::function op2Validator, OperandEncoding op2Encoding, OperandRW op2RW, std::function op3Validator, OperandEncoding op3Encoding, OperandRW op3RW) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg, op1Validator, op1Encoding, op1RW, op2Validator, op2Encoding, op2RW) { numArgs = 3; this->op3Validator = op3Validator; this->op3Encoding = op3Encoding; this->op3RW = op3RW; } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::initializer_list impliedReadGPRegs, std::initializer_list impliedWriteGPRegs, std::initializer_list impliedReadFPRegs, std::initializer_list impliedWriteFPRegs, std::function op1Validator, OperandEncoding op1Encoding, OperandRW op1RW, std::function op2Validator, OperandEncoding op2Encoding, OperandRW op2RW, std::function op3Validator, OperandEncoding op3Encoding, OperandRW op3RW) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg, impliedReadGPRegs, impliedWriteGPRegs, impliedReadFPRegs, impliedWriteFPRegs, op1Validator, op1Encoding, op1RW, op2Validator, op2Encoding, op2RW) { numArgs = 3; this->op3Validator = op3Validator; this->op3Encoding = op3Encoding; this->op3RW = op3RW; } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::function op1Validator, OperandEncoding op1Encoding, OperandRW op1RW, std::function op2Validator, OperandEncoding op2Encoding, OperandRW op2RW, std::function op3Validator, OperandEncoding op3Encoding, OperandRW op3RW, std::function op4Validator, OperandEncoding op4Encoding, OperandRW op4RW) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg, op1Validator, op1Encoding, op1RW, op2Validator, op2Encoding, op2RW, op3Validator, op3Encoding, op3RW) { numArgs = 4; this->op4Validator = op4Validator; this->op4Encoding = op4Encoding; this->op4RW = op4RW; } MachineCodeTableEntry(bool rexW, int opcode, char opcodeLength, bool operandSizeOverride, bool vex, bool vexL, char vexPP, char rmReg, std::initializer_list impliedReadGPRegs, std::initializer_list impliedWriteGPRegs, std::initializer_list impliedReadFPRegs, std::initializer_list impliedWriteFPRegs, std::function op1Validator, OperandEncoding op1Encoding, OperandRW op1RW, std::function op2Validator, OperandEncoding op2Encoding, OperandRW op2RW, std::function op3Validator, OperandEncoding op3Encoding, OperandRW op3RW, std::function op4Validator, OperandEncoding op4Encoding, OperandRW op4RW) : MachineCodeTableEntry(rexW, opcode, opcodeLength, operandSizeOverride, vex, vexL, vexPP, rmReg, impliedReadGPRegs, impliedWriteGPRegs, impliedReadFPRegs, impliedWriteFPRegs, op1Validator, op1Encoding, op1RW, op2Validator, op2Encoding, op2RW, op3Validator, op3Encoding, op3RW) { numArgs = 4; this->op4Validator = op4Validator; this->op4Encoding = op4Encoding; this->op4RW = op4RW; } MachineCodeTableEntry(const MachineCodeTableEntry& other) = default; bool matches(int numArgs, const std::vector& args) const { if (numArgs != this->numArgs) { return false; } if (numArgs >= 1 && !op1Validator(*args[0])) { return false; } if (numArgs >= 2 && !op2Validator(*args[1])) { return false; } if (numArgs >= 3 && !op3Validator(*args[2])) { return false; } if (numArgs >= 4 && !op4Validator(*args[3])) { return false; } return true; } OperandRW getOperandRW(int index) const { switch (index) { case 0: return op1RW; case 1: return op2RW; case 2: return op3RW; case 3: return op4RW; default: return NONE; } } const std::vector& getImpliedReadGPRegs() const { return impliedReadGPRegs; } const std::vector& getImpliedWriteGPRegs() const { return impliedWriteGPRegs; } const std::vector& getImpliedReadFPRegs() const { return impliedReadFPRegs; } const std::vector& getImpliedWriteFPRegs() const { return impliedWriteFPRegs; } friend class OperationCodeTable; }; class OperationCodeTable : public Framework::ReferenceCounter { public: thread_local static Framework::RCArray machineCodeTranslationTable; private: Framework::Assembly::Operation op; std::vector entries; public: OperationCodeTable(Framework::Assembly::Operation op, std::initializer_list entries) : ReferenceCounter(), op(op), entries(entries) {} MachineCodeInstruction getInstruction( const std::vector& args, const Framework::Assembly::AssemblyBlock* codeBlock, const Framework::Assembly::Instruction* current) { MachineCodeInstruction result; memset(&result, 0, sizeof(MachineCodeInstruction)); const MachineCodeTableEntry& entry = getEntry(args, codeBlock, current); result.needsVex = entry.vex; result.vexL = entry.vexL; result.vexPP = entry.vexPP; result.needsRex = entry.rexW; result.exWE = entry.rexW; result.modRM = entry.rmReg << 3; if (entry.rmReg) { result.needsModRM = true; } memcpy(result.opcode, entry.opcode, 3); result.opcodeLength = entry.opcodeLength; result.operandSizeOverride = entry.operandSizeOverride; for (int i = 0; i < args.size(); i++) { OperandEncoding encoding = UNDEFINED; switch (i) { case 0: encoding = entry.op1Encoding; break; case 1: encoding = entry.op2Encoding; break; case 2: encoding = entry.op3Encoding; break; case 3: encoding = entry.op4Encoding; break; } switch (encoding) { case MODRM_REG: encodeModRM_REG(result, args[i], i + 1); break; case MODRM_RM: encodeModRM_RM(result, args[i], i + 1); break; case VEX_VVVV: encodeVex_VVVV(result, args[i], i + 1); break; case OPCODE_RD: encodeOpcode_RD(result, args[i], i + 1); break; case IMM8: encodeIMM8(result, args[i], i + 1); break; case IMM16: encodeIMM16(result, args[i], i + 1); break; case IMM32: encodeIMM32(result, args[i], i + 1); break; case IMM64: encodeIMM64(result, args[i], i + 1); break; } } if (result.errIfNoRex && !result.needsRex) { Framework::Text* err = new Framework::Text(); err->append() << "Instruction " << op << " has no REX prefix and can not address " "LOWER8 of registers RSP, RBP, RSI or RDI"; throw err->getText(); } if (result.errIfRex && result.needsRex) { Framework::Text* err = new Framework::Text(); err->append() << "Instruction " << op << " has a REX prefix and can not address " "HIGHER8 of registers RAX, RBX, RCX or RDX"; throw err->getText(); } return result; } virtual MachineCodeTableEntry& getEntry( const std::vector& args, const Framework::Assembly::AssemblyBlock* codeBlock, const Framework::Assembly::Instruction* current) { MachineCodeInstruction result; memset(&result, 0, sizeof(MachineCodeInstruction)); for (MachineCodeTableEntry& entry : entries) { if (entry.matches((int)args.size(), args)) { return entry; } } Framework::Text err; err.append() << "operation " << (int)op << " not found in translation table. args: \n"; for (auto arg : args) { err.append() << " " << typeid(*arg).name() << "\n"; } throw err.getText(); } Framework::Assembly::Operation getOperation() const { return op; } void encodeModRM_REG(MachineCodeInstruction& result, const Framework::Assembly::OperationArgument* arg, int index) const { result.needsModRM = true; const Framework::Assembly::GPRegisterArgument* gpRegArg = arg->asGPRegisterArgument(); const Framework::Assembly::FPRegisterArgument* fpRegArg = arg->asFPRegisterArgument(); if (gpRegArg) { encodeModRM_REG_GP(result, gpRegArg, index); } else if (fpRegArg) { encodeModRM_REG_FP(result, fpRegArg, index); } else { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument type for operand " << index << " for operation " << op << " encoded as MODRM_REG: found " << typeid(*arg).name() << " but expected GPRegisterArgument or FPRegisterArgument"; throw err->getText(); } } void encodeModRM_REG_GP(MachineCodeInstruction& result, const Framework::Assembly::GPRegisterArgument* arg, int index) const { Framework::Assembly::GPRegister reg = arg->getRegister(); if (reg >= Framework::Assembly::R8) { result.needsRex = true; result.exR = 1; } if (arg->getPart() == Framework::Assembly::GPRegisterPart::HIGHER8) { if (reg == Framework::Assembly::RAX) { result.modRM |= 0b100000; result.errIfRex = true; } else if (reg == Framework::Assembly::RBX) { result.modRM |= 0b111000; result.errIfRex = true; } else if (reg == Framework::Assembly::RCX) { result.modRM |= 0b101000; result.errIfRex = true; } else if (reg == Framework::Assembly::RDX) { result.modRM |= 0b110000; result.errIfRex = true; } else { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument for operand " << index << " for operation " << op << " HIGHER8 can only be used for registers RAX, " "RBX, RCX or RDX"; } } else { result.modRM |= (reg & 0b111) << 3; } if (arg->getPart() == Framework::Assembly::GPRegisterPart::LOWER8 && (reg == Framework::Assembly::RSP || reg == Framework::Assembly::RBP || reg == Framework::Assembly::RSI || reg == Framework::Assembly::RDI)) { result.errIfNoRex = true; } } void encodeModRM_REG_FP(MachineCodeInstruction& result, const Framework::Assembly::FPRegisterArgument* arg, int index) const { Framework::Assembly::FPRegister reg = arg->getRegister(); if (reg >= Framework::Assembly::MM8) { result.needsRex = true; result.exR = 1; } result.modRM |= (reg & 0b111) << 3; } void encodeModRM_RM(MachineCodeInstruction& result, const Framework::Assembly::OperationArgument* arg, int index) const { result.needsModRM = true; const Framework::Assembly::GPRegisterArgument* gpRegArg = arg->asGPRegisterArgument(); const Framework::Assembly::FPRegisterArgument* fpRegArg = arg->asFPRegisterArgument(); const Framework::Assembly::MemoryAccessArgument* memArg = arg->asMemoryAccessArgument(); if (gpRegArg) { encodeModRM_RM_GP(result, gpRegArg, index); } else if (fpRegArg) { encodeModRM_RM_FP(result, fpRegArg, index); } else if (memArg) { encodeModRM_RM_Mem(result, memArg, index); } else { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument type for operand " << index << " for operation " << op << " encoded as MODRM_RM: found " << typeid(*arg).name() << " but expected GPRegisterArgument, FPRegisterArgument " "or MemoryAccessArgument"; throw err->getText(); } } void encodeModRM_RM_GP(MachineCodeInstruction& result, const Framework::Assembly::GPRegisterArgument* arg, int index) const { Framework::Assembly::GPRegister reg = arg->getRegister(); if (reg >= Framework::Assembly::R8) { result.needsRex = true; result.exB = 1; } result.modRM |= 0b11 << 6; // direct register access if (arg->getPart() == Framework::Assembly::GPRegisterPart::HIGHER8) { if (reg == Framework::Assembly::RAX) { result.modRM |= 0b100; result.errIfRex = true; } else if (reg == Framework::Assembly::RBX) { result.modRM |= 0b111; result.errIfRex = true; } else if (reg == Framework::Assembly::RCX) { result.modRM |= 0b101; result.errIfRex = true; } else if (reg == Framework::Assembly::RDX) { result.modRM |= 0b110; result.errIfRex = true; } else { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument for operand " << index << " for operation " << op << " HIGHER8 can only be used for registers RAX, " "RBX, RCX or RDX"; } } else { result.modRM |= reg & 0b111; } if (arg->getPart() == Framework::Assembly::GPRegisterPart::LOWER8 && (reg == Framework::Assembly::RSP || reg == Framework::Assembly::RBP || reg == Framework::Assembly::RSI || reg == Framework::Assembly::RDI)) { result.errIfNoRex = true; } } void encodeModRM_RM_FP(MachineCodeInstruction& result, const Framework::Assembly::FPRegisterArgument* arg, int index) const { Framework::Assembly::FPRegister reg = arg->getRegister(); if (reg >= Framework::Assembly::MM8) { result.needsRex = true; result.exB = 1; } result.modRM |= 0b11 << 6; // direct register access result.modRM |= reg & 0b111; } void encodeModRM_RM_Mem(MachineCodeInstruction& result, const Framework::Assembly::MemoryAccessArgument* arg, int index) const { if (arg->isUsingAddressRegister() || arg->isUsingOffsetRegister()) { Framework::Assembly::GPRegister reg = arg->isUsingAddressRegister() ? arg->getAddressRegister() : arg->getOffsetRegister(); if (arg->isUsingAddressRegister() && arg->isUsingOffsetRegister()) { // SIB needed result.sibNeeded = true; result.modRM |= 0b100 << 3; // indicate SIB if (reg >= Framework::Assembly::R8) { result.needsRex = true; result.exB = 1; } result.sib |= reg & 0b111; Framework::Assembly::GPRegister offsetReg = arg->getOffsetRegister(); if (offsetReg == Framework::Assembly::RSP) { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument for operand " << index << " for operation " << op << " RSP can not be used as index register"; throw err->getText(); } if (offsetReg >= Framework::Assembly::R8) { result.needsRex = true; result.exX = 1; } result.sib |= (offsetReg & 0b111) << 3; // index register } else { if (reg >= Framework::Assembly::R8) { result.needsRex = true; result.exB = 1; } result.modRM |= reg & 0b111; } int offset = arg->getOffset(); if (offset > 0) { if (offset <= 127 && offset >= -128) { result.modRM |= 0b01 << 6; // 8 bit displacement result.disp[0] = (char)offset; result.dispLength = 1; } else { result.modRM |= 0b10 << 6; // 32 bit displacement memcpy(result.disp, &offset, 4); } } else { if ((result.modRM & 0b111) == 0b101) { // special case: EBP or R13 as // address register needs disp8=0 result.modRM |= 0b01 << 6; // 8 bit displacement result.disp[0] = 0; result.dispLength = 1; } } } else { result.modRM |= 0b100; result.sibNeeded = true; result.sib = 0b00100101; // no base, no index only // disp32 int offset = arg->getOffset(); memcpy(result.disp, &offset, 4); result.dispLength = 4; } } void encodeVex_VVVV(MachineCodeInstruction& result, const Framework::Assembly::OperationArgument* arg, int index) const { const Framework::Assembly::FPRegisterArgument* fpRegArg = arg->asFPRegisterArgument(); if (fpRegArg) { encodeVex_VVVV_FP(result, fpRegArg, index); } else { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument type for operand " << index << " for operation " << op << " encoded as VEX_VVVV: found " << typeid(*arg).name() << " but expected FPRegisterArgument"; throw err->getText(); } } void encodeVex_VVVV_FP(MachineCodeInstruction& result, const Framework::Assembly::FPRegisterArgument* arg, int index) const { Framework::Assembly::FPRegister reg = arg->getRegister(); result.vexVVVV = reg & 0b1111; result.needsVex = true; } void encodeOpcode_RD(MachineCodeInstruction& result, const Framework::Assembly::OperationArgument* arg, int index) const { const Framework::Assembly::GPRegisterArgument* gpRegArg = arg->asGPRegisterArgument(); if (gpRegArg) { encodeOpcode_RD_GP(result, gpRegArg, index); } else { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument type for operand " << index << " for operation " << op << " encoded as OPCODE_RD: found " << typeid(*arg).name() << " but expected GPRegisterArgument"; throw err->getText(); } } void encodeOpcode_RD_GP(MachineCodeInstruction& result, const Framework::Assembly::GPRegisterArgument* arg, int index) const { Framework::Assembly::GPRegister reg = arg->getRegister(); if (reg >= Framework::Assembly::R8) { result.needsRex = true; result.exB = 1; } result.opcode[result.opcodeLength - 1] |= reg & 0b111; } void encodeIMM8(MachineCodeInstruction& result, Framework::Assembly::OperationArgument* arg, int index) const { result.immLength = 1; const Framework::Assembly::ConstantArgument* constArg = arg->asConstantArgument(); if (constArg == 0) { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument type for operand " << index << " for operation " << op << " encoded as IMM8: found " << typeid(*arg).name() << " but expected ConstantArgument"; throw err->getText(); } int value = (int)constArg->getValue(); int len = (int)constArg->getSize(); if (len > 1) { Framework::Text* err = new Framework::Text(); err->append() << "Constant size too large for operand " << index << " for operation " << op << " encoded as IMM8: found size " << len << " but expected size BYTE"; throw err->getText(); } result.imm[0] = (char)(value); result.immLength = 1; } void encodeIMM16(MachineCodeInstruction& result, Framework::Assembly::OperationArgument* arg, int index) const { result.immLength = 1; const Framework::Assembly::ConstantArgument* constArg = arg->asConstantArgument(); if (constArg == 0) { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument type for operand " << index << " for operation " << op << " encoded as IMM8: found " << typeid(*arg).name() << " but expected ConstantArgument"; throw err->getText(); } int value = (int)constArg->getValue(); int len = (int)constArg->getSize(); if (len > 2) { Framework::Text* err = new Framework::Text(); err->append() << "Constant size too large for operand " << index << " for operation " << op << " encoded as IMM8: found size " << len << " but expected size range [BYTE, WORD]"; throw err->getText(); } short val = (short)(value); memcpy(result.imm, &val, 2); result.immLength = 2; } void encodeIMM32(MachineCodeInstruction& result, Framework::Assembly::OperationArgument* arg, int index) const { result.immLength = 1; const Framework::Assembly::ConstantArgument* constArg = arg->asConstantArgument(); if (constArg == 0) { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument type for operand " << index << " for operation " << op << " encoded as IMM8: found " << typeid(*arg).name() << " but expected ConstantArgument"; throw err->getText(); } int value = (int)constArg->getValue(); int len = (int)constArg->getSize(); if (len > 4) { Framework::Text* err = new Framework::Text(); err->append() << "Constant size too large for operand " << index << " for operation " << op << " encoded as IMM8: found size " << len << " but expected size range [BYTE, DWORD]"; throw err->getText(); } memcpy(result.imm, &value, 4); result.immLength = 4; } void encodeIMM64(MachineCodeInstruction& result, Framework::Assembly::OperationArgument* arg, int index) const { result.immLength = 1; const Framework::Assembly::ConstantArgument* constArg = arg->asConstantArgument(); if (constArg == 0) { Framework::Text* err = new Framework::Text(); err->append() << "Invalid argument type for operand " << index << " for operation " << op << " encoded as IMM8: found " << typeid(*arg).name() << " but expected ConstantArgument"; throw err->getText(); } __int64 value = constArg->getValue(); int len = (int)constArg->getSize(); if (len > 8) { Framework::Text* err = new Framework::Text(); err->append() << "Constant size too large for operand " << index << " for operation " << op << " encoded as IMM8: found size " << len << " but expected size range [BYTE, QWORD]"; throw err->getText(); } memcpy(result.imm, &value, 8); result.immLength = 8; } }; class JumpOperationCodeTable : public OperationCodeTable { private: char opCodeLength; bool inGetEntry; public: JumpOperationCodeTable(Framework::Assembly::Operation op, char opCodeLength, std::initializer_list entries) : OperationCodeTable(op, entries), opCodeLength(opCodeLength) {} virtual MachineCodeTableEntry& getEntry( const std::vector& args, const Framework::Assembly::AssemblyBlock* codeBlock, const Framework::Assembly::Instruction* current) override { if (inGetEntry) { // recursion can only happen during size calculation so we just // create a dummy const argument for each jump target std::vector newArgs; std::vector transformedArgs; for (Framework::Assembly::OperationArgument* arg : args) { if (arg->asJumpTargetArgument()) { Framework::Assembly::ConstantArgument* constArg = new Framework::Assembly::ConstantArgument(0); transformedArgs.push_back(constArg); newArgs.push_back(constArg); } else { transformedArgs.push_back(arg); } } MachineCodeTableEntry& result = OperationCodeTable::getEntry( transformedArgs, codeBlock, current); for (Framework::Assembly::OperationArgument* arg : newArgs) { delete arg; } return result; } inGetEntry = 1; std::vector newArgs; std::vector transformedArgs; for (Framework::Assembly::OperationArgument* arg : args) { if (arg->asJumpTargetArgument()) { Framework::Text label = arg->asJumpTargetArgument()->getLabel(); bool currentFound = false; bool labelFound = false; bool backwords = false; int jumpLength = 0; // search for the label for (const Framework::Assembly::Instruction* instr : codeBlock->getInstructions()) { if (instr == current) { currentFound = true; if (labelFound) { break; } else { backwords = true; } continue; } if (instr->definesLabel(label)) { labelFound = true; if (currentFound) { break; } continue; } if (labelFound || currentFound) { jumpLength += instr->compiledSize(codeBlock); } } if (backwords) { jumpLength = -jumpLength - 4 - opCodeLength; } Framework::Assembly::ConstantArgument* constArg = new Framework::Assembly::ConstantArgument(jumpLength); transformedArgs.push_back(constArg); newArgs.push_back(constArg); } else { transformedArgs.push_back(arg); } } MachineCodeTableEntry& result = OperationCodeTable::getEntry(transformedArgs, codeBlock, current); for (Framework::Assembly::OperationArgument* arg : newArgs) { delete arg; } return result; } }; thread_local Framework::RCArray OperationCodeTable::machineCodeTranslationTable; std::function isGPRegister(Framework::Assembly::MemoryBlockSize size) { return [size](const Framework::Assembly::OperationArgument& arg) { return arg.asGPRegisterArgument() != 0 && ((size == Framework::Assembly::MemoryBlockSize::BYTE && (arg.asGPRegisterArgument()->getPart() == Framework::Assembly::LOWER8 || arg.asGPRegisterArgument()->getPart() == Framework::Assembly::HIGHER8)) || (size == Framework::Assembly::MemoryBlockSize::WORD && arg.asGPRegisterArgument()->getPart() == Framework::Assembly::LOWER16) || (size == Framework::Assembly::MemoryBlockSize::DWORD && arg.asGPRegisterArgument()->getPart() == Framework::Assembly::LOWER32) || (size == Framework::Assembly::MemoryBlockSize::QWORD && arg.asGPRegisterArgument()->getPart() == Framework::Assembly::FULL64)); }; } std::function isSpecificGPRegister(Framework::Assembly::GPRegister reg, Framework::Assembly::GPRegisterPart part) { return [reg, part](const Framework::Assembly::OperationArgument& arg) { return arg.asGPRegisterArgument() != 0 && arg.asGPRegisterArgument()->getRegister() == reg && arg.asGPRegisterArgument()->getPart() == part; }; } std::function isGPRegisterOrMemoryAccess(Framework::Assembly::MemoryBlockSize size) { return [size](const Framework::Assembly::OperationArgument& arg) { return isGPRegister(size)(arg) || arg.asMemoryAccessArgument() && arg.asMemoryAccessArgument()->getBlockSize() == size; }; } std::function isIMM() { return [](const Framework::Assembly::OperationArgument& arg) { return arg.asConstantArgument(); }; } std::function isIMM( Framework::Assembly::MemoryBlockSize maxSize) { return [maxSize](const Framework::Assembly::OperationArgument& arg) { return arg.asConstantArgument() && arg.asConstantArgument()->getSize() <= maxSize; }; } std::function isFPRegister(Framework::Assembly::MemoryBlockSize size) { return [size](const Framework::Assembly::OperationArgument& arg) { return arg.asFPRegisterArgument() != 0 && ((size == Framework::Assembly::MemoryBlockSize::M128 && arg.asFPRegisterArgument()->getPart() == Framework::Assembly::X) || (size == Framework::Assembly::MemoryBlockSize::M256 && arg.asFPRegisterArgument()->getPart() == Framework::Assembly::Y) /* || (size == Framework::Assembly::MemoryBlockSize::M512 && arg.asFPRegisterArgument()->getPart() == Framework::Assembly::Z)*/); }; } std::function isFPRegisterOrMEmoryAccess(Framework::Assembly::MemoryBlockSize size) { return [size](const Framework::Assembly::OperationArgument& arg) { return isFPRegister(size) || (arg.asMemoryAccessArgument() && arg.asMemoryAccessArgument()->getBlockSize() == size); }; } std::function isFPRegisterOrMEmoryAccess(Framework::Assembly::MemoryBlockSize regSize, Framework::Assembly::MemoryBlockSize memSize) { return [regSize, memSize](const Framework::Assembly::OperationArgument& arg) { return isFPRegister(regSize) || (arg.asMemoryAccessArgument() && arg.asMemoryAccessArgument()->getBlockSize() == memSize); }; } void __intializeMachineCodeTranslationTable() { if (!OperationCodeTable::machineCodeTranslationTable.getEintragAnzahl()) { OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::ADD, {// ADD AL, IMM8 MachineCodeTableEntry(false, 0x04, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER8), UNDEFINED, READWRITE, isIMM(), IMM8, READ), // ADD AX, IMM16 MachineCodeTableEntry(false, 0x05, (char)1, true, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER16), UNDEFINED, READWRITE, isIMM(), IMM16, READ), // ADD EAX, IMM32 MachineCodeTableEntry( false, 0x05, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER32), UNDEFINED, READWRITE, [](const Framework::Assembly::OperationArgument& arg) { return arg.asConstantArgument() != 0; }, IMM32, READ), // ADD RAX, IMM32 MachineCodeTableEntry(true, 0x05, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::FULL64), UNDEFINED, READWRITE, isIMM(), IMM32, READ), // ADD r/m8, IMM8 MachineCodeTableEntry(false, 0x80, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isIMM(), IMM8, READ), // ADD r/m16, IMM8 MachineCodeTableEntry(false, 0x83, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // ADD r/m32, IMM8 MachineCodeTableEntry(false, 0x83, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // ADD r/m64, IMM8 MachineCodeTableEntry(true, 0x83, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // ADD r/m16, IMM16 MachineCodeTableEntry( false, 0x81, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, [](const Framework::Assembly::OperationArgument& arg) { return arg.asConstantArgument() && arg.asConstantArgument()->getSize() != Framework::Assembly::MemoryBlockSize:: BYTE; }, IMM16, READ), // ADD r/m32, IMM32 MachineCodeTableEntry( false, 0x81, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, [](const Framework::Assembly::OperationArgument& arg) { return arg.asConstantArgument() != 0 && arg.asConstantArgument()->getSize() != Framework::Assembly::MemoryBlockSize:: BYTE; }, IMM32, READ), // ADD r/m64, IMM32 MachineCodeTableEntry( true, 0x81, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, [](const Framework::Assembly::OperationArgument& arg) { return arg.asConstantArgument() != 0 && arg.asConstantArgument()->getSize() != Framework::Assembly::MemoryBlockSize:: BYTE; }, IMM32, READ), // ADD r/m8, r8 MachineCodeTableEntry(false, 0x00, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ), // ADD r/m16, r16 MachineCodeTableEntry(false, 0x01, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ), // ADD r/m32, r32 MachineCodeTableEntry(false, 0x01, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ), // ADD r/m64, r64 MachineCodeTableEntry(true, 0x01, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ), // ADD r8, r/m8 MachineCodeTableEntry(false, 0x02, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // ADD r16, r/m16 MachineCodeTableEntry(false, 0x03, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // ADD r32, r/m32 MachineCodeTableEntry(false, 0x03, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // ADD r64, r/m64 MachineCodeTableEntry(true, 0x03, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::ADDPD, {// ADDPD xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x580F, (char)2, true, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VADDPD xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x580F, (char)2, false, true, false, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VADDPD ymm1,ymm2, ymm3/m256 MachineCodeTableEntry(false, 0x580F, (char)2, false, true, true, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::ADDPS, {// ADDPS xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x580F, (char)2, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VADDPS xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x580F, (char)2, false, true, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VADDPS ymm1, ymm2, ymm3/m256 MachineCodeTableEntry(false, 0x580F, (char)2, false, true, true, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::ADDSD, {// ADDSD xmm1, xmm2/m64 MachineCodeTableEntry(false, 0x580FF2, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), // VADDPS VADDSD xmm1, xmm2, xmm3/m64 MachineCodeTableEntry(false, 0x580F, (char)2, false, true, false, 0b11, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::ADDSS, {// ADDPS xmm1, xmm2/m32 MachineCodeTableEntry(false, 0x580FF3, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // VADDPS VADDSD xmm1, xmm2, xmm3/m64 MachineCodeTableEntry(false, 0x580F, (char)2, false, true, false, 0b10, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::SUB, { // SUB AL, imm8 MachineCodeTableEntry(false, 0x2C, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER8), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // SUB AX, imm16 MachineCodeTableEntry(false, 0x2D, (char)1, true, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER16), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // SUB EAX, imm32 MachineCodeTableEntry(false, 0x2D, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER32), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // SUB RAX, imm32 MachineCodeTableEntry(true, 0x2D, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::FULL64), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // SUB r/m8, imm8 MachineCodeTableEntry(false, 0x80, (char)1, false, false, false, 0, 0b101, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // SUB r/m16, imm8 MachineCodeTableEntry(false, 0x83, (char)1, true, false, false, 0, 0b101, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // SUB r/m32, imm8 MachineCodeTableEntry(false, 0x83, (char)1, false, false, false, 0, 0b101, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // SUB r/m64, imm8 MachineCodeTableEntry(true, 0x83, (char)1, false, false, false, 0, 0b101, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // SUB r/m16, imm16 MachineCodeTableEntry(false, 0x81, (char)1, true, false, false, 0, 0b101, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // SUB r/m32, imm32 MachineCodeTableEntry(false, 0x81, (char)1, false, false, false, 0, 0b101, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // SUB r/m64, imm32 MachineCodeTableEntry(true, 0x81, (char)1, false, false, false, 0, 0b101, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // SUB r/m8, r8 MachineCodeTableEntry(false, 0x28, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ), // SUB r/m16, r16 MachineCodeTableEntry(false, 0x29, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ), // SUB r/m32, r32 MachineCodeTableEntry(false, 0x29, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ), // SUB r/m64, r64 MachineCodeTableEntry(true, 0x29, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ), // SUB r8, r/m8 MachineCodeTableEntry(false, 0x2A, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // SUB r16, r/m16 MachineCodeTableEntry(false, 0x2B, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // SUB r32, r/m32 MachineCodeTableEntry(false, 0x2B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // SUB SUB r64, r/m64 MachineCodeTableEntry(true, 0x2B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::SUBPD, { // SUBPD xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x5D0F, (char)2, true, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VSUBPD xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x5C0F, (char)2, false, true, false, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VSUBPD ymm1, ymm2, ymm3/m256 MachineCodeTableEntry(false, 0x5C0F, (char)2, false, true, true, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::SUBPS, { // SUBPS xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x5D0F, (char)2, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VSUBPS xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x5C0F, (char)2, false, true, false, 0b00, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VSUBPS ymm1, ymm2, ymm3/m256 MachineCodeTableEntry(false, 0x5C0F, (char)2, false, true, true, 0b00, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::SUBSD, { // SUBSD xmm1, xmm2/m64 MachineCodeTableEntry(false, 0x5C0FF2, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), // VSUBSD xmm1,xmm2, xmm3/m64 MachineCodeTableEntry(false, 0x5C0F, (char)2, false, true, false, 0b11, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::SUBSS, { // SUBSS xmm1, xmm2/m32 MachineCodeTableEntry(false, 0x5C0FF3, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // VSUBSD xmm1,xmm2, xmm3/m32 MachineCodeTableEntry(false, 0x5C0F, (char)2, false, true, false, 0b10, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MUL, { // MUL r/m8 MachineCodeTableEntry(false, 0xF6, (char)1, false, false, false, 0, 0b100, {Framework::Assembly::RAX}, {Framework::Assembly::RAX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // MUL r/m16 MachineCodeTableEntry(false, 0xF7, (char)1, true, false, false, 0, 0b100, {Framework::Assembly::RAX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // MUL r/m32 MachineCodeTableEntry(false, 0xF7, (char)1, false, false, false, 0, 0b100, {Framework::Assembly::RAX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // MUL r/m64 MachineCodeTableEntry(true, 0xF7, (char)1, false, false, false, 0, 0b100, {Framework::Assembly::RAX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::IMUL, { // IMUL r/m8 MachineCodeTableEntry(false, 0xF6, (char)1, false, false, false, 0, 0b101, {Framework::Assembly::RAX}, {Framework::Assembly::RAX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // IMUL r/m16 MachineCodeTableEntry(false, 0xF7, (char)1, true, false, false, 0, 0b101, {Framework::Assembly::RAX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // IMUL r/m32 MachineCodeTableEntry(false, 0xF7, (char)1, false, false, false, 0, 0b101, {Framework::Assembly::RAX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // IMUL r/m64 MachineCodeTableEntry(true, 0xF7, (char)1, false, false, false, 0, 0b101, {Framework::Assembly::RAX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), // IMUL r16, r/m16 MachineCodeTableEntry(false, 0xAF0F, (char)2, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // IMUL r32, r/m32 MachineCodeTableEntry(false, 0xAF0F, (char)2, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // IMUL r64, r/m64 MachineCodeTableEntry(true, 0xAF0F, (char)2, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), // IMUL r16, r/m16, imm8 MachineCodeTableEntry(false, 0x6B, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, WRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // IMUL r32, r/m32, imm8 MachineCodeTableEntry(false, 0x6B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // IMUL r64, r/m64, imm8 MachineCodeTableEntry(true, 0x6B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // IMUL r16, r/m16, imm16 MachineCodeTableEntry(false, 0x69, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, WRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // IMUL r32, r/m32, imm32 MachineCodeTableEntry(false, 0x69, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // IMUL r64, r/m64 MachineCodeTableEntry(true, 0x69, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MULPD, { // MULPD xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x590F, (char)2, true, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VMULPD xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x590F, (char)2, false, true, false, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VMULPD ymm1, ymm2, ymm3/m256 MachineCodeTableEntry(false, 0x590F, (char)2, false, true, true, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MULPS, { // MULPS xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x590F, (char)2, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VMULPS xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x590F, (char)2, false, true, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VMULPS ymm1, ymm2, ymm3/m256 MachineCodeTableEntry(false, 0x590F, (char)2, false, true, true, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MULSD, { // MULSD xmm1,xmm2/m64 MachineCodeTableEntry(false, 0x590FF2, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VMULSD xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x590F, (char)2, false, true, false, 0b11, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MULSS, { // MULSS xmm1,xmm2/m64 MachineCodeTableEntry(false, 0x590FF3, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VMULSS xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x590F, (char)2, false, true, false, 0b10, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::DIV, { // DIV r/m8 MachineCodeTableEntry(false, 0xF6, (char)1, false, false, false, 0, 0b110, {Framework::Assembly::RAX}, {Framework::Assembly::RAX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // DIV r/m16 MachineCodeTableEntry(false, 0xF7, (char)1, true, false, false, 0, 0b110, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // DIV r/m32 MachineCodeTableEntry(false, 0xF7, (char)1, false, false, false, 0, 0b110, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // DIV r/m64 MachineCodeTableEntry(true, 0xF7, (char)1, false, false, false, 0, 0b110, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::IDIV, { // IDIV r/m8 MachineCodeTableEntry(false, 0xF6, (char)1, false, false, false, 0, 0b111, {Framework::Assembly::RAX}, {Framework::Assembly::RAX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // IDIV r/m16 MachineCodeTableEntry(false, 0xF7, (char)1, true, false, false, 0, 0b111, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // IDIV r/m32 MachineCodeTableEntry(false, 0xF7, (char)1, false, false, false, 0, 0b111, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // IDIV r/m64 MachineCodeTableEntry(true, 0xF7, (char)1, false, false, false, 0, 0b111, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {Framework::Assembly::RAX, Framework::Assembly::RDX}, {}, {}, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::DIVPD, { // DIVPD xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x5E0F, (char)2, true, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VDIVPD xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x5E0F, (char)2, false, true, false, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VDIVPD ymm1, ymm2, ymm3/m256 MachineCodeTableEntry(false, 0x5E0F, (char)2, false, true, true, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::DIVPS, { // DIVPS xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x5E0F, (char)2, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VDIVPS xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x5E0F, (char)2, false, true, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VDIVPS ymm1, ymm2, ymm3/m256 MachineCodeTableEntry(false, 0x5E0F, (char)2, false, true, true, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::DIVSD, { // DIVSD xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x5E0FF2, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VDIVSD xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x5E0F, (char)2, false, true, false, 0b11, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::DIVSS, { // DIVSS xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x5E0FF3, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VDIVSS xmm1,xmm2, xmm3/m128 MachineCodeTableEntry(false, 0x5E0F, (char)2, false, true, false, 0b10, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::NEG, { // NEG r/m8 MachineCodeTableEntry(false, 0xF6, (char)1, false, false, false, 0, 0b011, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE), // NEG r/m16 MachineCodeTableEntry(false, 0xF7, (char)1, true, false, false, 0, 0b011, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE), // NEG r/m32 MachineCodeTableEntry(false, 0xF7, (char)1, false, false, false, 0, 0b011, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE), // NEG r/m64 MachineCodeTableEntry(true, 0xF7, (char)1, false, false, false, 0, 0b011, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::INC, { // INC r/m8 MachineCodeTableEntry(false, 0xFE, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE), // INC r/m16 MachineCodeTableEntry(false, 0xF7, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE), // INC r/m32 MachineCodeTableEntry(false, 0xF7, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE), // INC r/m64 MachineCodeTableEntry(true, 0xF7, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::AND, { // AND AL, imm8 MachineCodeTableEntry(false, 0x24, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER8), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // AND AX, imm16 MachineCodeTableEntry(false, 0x25, (char)1, true, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER16), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // AND EAX, imm32 MachineCodeTableEntry(false, 0x25, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER32), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // AND RAX, imm32 MachineCodeTableEntry(true, 0x25, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::FULL64), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // AND r/m8, imm8 MachineCodeTableEntry(false, 0x80, (char)1, false, false, false, 0, 0b100, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // AND r/m16, imm8 MachineCodeTableEntry(false, 0x83, (char)1, true, false, false, 0, 0b100, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // AND r/m32, imm8 MachineCodeTableEntry(false, 0x83, (char)1, false, false, false, 0, 0b100, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // AND r/m64, imm8 MachineCodeTableEntry(true, 0x83, (char)1, false, false, false, 0, 0b100, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // AND r/m16, imm16 MachineCodeTableEntry(false, 0x81, (char)1, true, false, false, 0, 0b100, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // AND r/m32, imm32 MachineCodeTableEntry(false, 0x81, (char)1, false, false, false, 0, 0b100, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // AND r/m64, imm32 MachineCodeTableEntry(true, 0x81, (char)1, false, false, false, 0, 0b100, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // AND r/m8, r8 MachineCodeTableEntry(false, 0x20, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ), // AND r/m16, r16 MachineCodeTableEntry(false, 0x21, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ), // AND r/m32, r32 MachineCodeTableEntry(false, 0x21, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ), // AND r/m64, r64 MachineCodeTableEntry(true, 0x21, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ), // AND r8, r/m8 MachineCodeTableEntry(false, 0x22, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // AND r16, r/m16 MachineCodeTableEntry(false, 0x23, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // AND r32, r/m32 MachineCodeTableEntry(false, 0x23, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // AND r64, r/m64 MachineCodeTableEntry(true, 0x23, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::OR, { // OR AL, imm8 MachineCodeTableEntry(false, 0x0C, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER8), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // OR AX, imm16 MachineCodeTableEntry(false, 0x0D, (char)1, true, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER16), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // OR EAX, imm32 MachineCodeTableEntry(false, 0x0D, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER32), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // OR RAX, imm32 MachineCodeTableEntry(true, 0x0D, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::FULL64), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // OR r/m8, imm8 MachineCodeTableEntry(false, 0x80, (char)1, false, false, false, 0, 0b001, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // OR r/m16, imm8 MachineCodeTableEntry(false, 0x83, (char)1, true, false, false, 0, 0b001, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // OR r/m32, imm8 MachineCodeTableEntry(false, 0x83, (char)1, false, false, false, 0, 0b001, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // OR r/m64, imm8 MachineCodeTableEntry(true, 0x83, (char)1, false, false, false, 0, 0b001, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // OR r/m16, imm16 MachineCodeTableEntry(false, 0x81, (char)1, true, false, false, 0, 0b001, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // OR r/m32, imm32 MachineCodeTableEntry(false, 0x81, (char)1, false, false, false, 0, 0b001, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // OR r/m64, imm32 MachineCodeTableEntry(true, 0x81, (char)1, false, false, false, 0, 0b001, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // OR r/m8, r8 MachineCodeTableEntry(false, 0x08, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ), // OR r/m16, r16 MachineCodeTableEntry(false, 0x09, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ), // OR r/m32, r32 MachineCodeTableEntry(false, 0x09, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ), // OR r/m64, r64 MachineCodeTableEntry(true, 0x09, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ), // OR r8, r/m8 MachineCodeTableEntry(false, 0x0A, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // OR r16, r/m16 MachineCodeTableEntry(false, 0x0B, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // OR r32, r/m32 MachineCodeTableEntry(false, 0x0B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // OR r64, r/m64 MachineCodeTableEntry(true, 0x0B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::XOR, { // XOR AL, imm8 MachineCodeTableEntry(false, 0x34, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER8), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // XOR AX, imm16 MachineCodeTableEntry(false, 0x35, (char)1, true, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER16), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // XOR EAX, imm32 MachineCodeTableEntry(false, 0x35, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER32), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // XOR RAX, imm32 MachineCodeTableEntry(true, 0x35, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::FULL64), UNDEFINED, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // XOR r/m8, imm8 MachineCodeTableEntry(false, 0x80, (char)1, false, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // XOR r/m16, imm8 MachineCodeTableEntry(false, 0x83, (char)1, true, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // XOR r/m32, imm8 MachineCodeTableEntry(false, 0x83, (char)1, false, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // XOR r/m64, imm8 MachineCodeTableEntry(true, 0x83, (char)1, false, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // XOR r/m16, imm16 MachineCodeTableEntry(false, 0x81, (char)1, true, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // XOR r/m32, imm32 MachineCodeTableEntry(false, 0x81, (char)1, false, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // XOR r/m64, imm32 MachineCodeTableEntry(true, 0x81, (char)1, false, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // XOR r/m8, r8 MachineCodeTableEntry(false, 0x30, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ), // XOR r/m16, r16 MachineCodeTableEntry(false, 0x31, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ), // XOR r/m32, r32 MachineCodeTableEntry(false, 0x31, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ), // XOR r/m64, r64 MachineCodeTableEntry(true, 0x31, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READWRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ), // XOR r8, r/m8 MachineCodeTableEntry(false, 0x32, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // XOR r16, r/m16 MachineCodeTableEntry(false, 0x33, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // XOR r32, r/m32 MachineCodeTableEntry(false, 0x33, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // XOR r64, r/m64 MachineCodeTableEntry(true, 0x33, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READWRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::NOT, { // NOT r/m8 MachineCodeTableEntry(false, 0xF6, (char)1, false, false, false, 0, 0b010, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READWRITE), // NOT r/m16 MachineCodeTableEntry(false, 0xF7, (char)1, true, false, false, 0, 0b010, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READWRITE), // NOT r/m32 MachineCodeTableEntry(false, 0xF7, (char)1, false, false, false, 0, 0b010, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE), // NOT r/m64 MachineCodeTableEntry(true, 0xF7, (char)1, false, false, false, 0, 0b010, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READWRITE), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::TEST, { // TEST AL, imm8 MachineCodeTableEntry(false, 0xA8, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER8), UNDEFINED, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // TEST AX, imm16 MachineCodeTableEntry(false, 0xA9, (char)1, true, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER16), UNDEFINED, READ, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // TEST EAX, imm32 MachineCodeTableEntry(false, 0xA9, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER32), UNDEFINED, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // TEST RAX, imm32 MachineCodeTableEntry(true, 0xA9, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::FULL64), UNDEFINED, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // TEST r/m8, imm8 MachineCodeTableEntry(false, 0xF6, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // TEST r/m16, imm16 MachineCodeTableEntry(false, 0xF7, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // TEST r/m32, imm32 MachineCodeTableEntry(false, 0xF7, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // TEST r/m64, imm32 MachineCodeTableEntry(true, 0xF7, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // TEST r/m8, r8 MachineCodeTableEntry(false, 0x84, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ), // TEST r/m16, r16 MachineCodeTableEntry(false, 0x85, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ), // TEST r/m32, r32 MachineCodeTableEntry(false, 0x85, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ), // TEST r/m64, r64 MachineCodeTableEntry(true, 0x85, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::CMP, { // CMP AL, imm8 MachineCodeTableEntry(false, 0x3C, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER8), UNDEFINED, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // CMP AX, imm16 MachineCodeTableEntry(false, 0x3D, (char)1, true, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER16), UNDEFINED, READ, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // CMP EAX, imm32 MachineCodeTableEntry(false, 0x3D, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::LOWER32), UNDEFINED, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // CMP RAX, imm32 MachineCodeTableEntry(true, 0x3D, (char)1, false, false, false, 0, 0, isSpecificGPRegister(Framework::Assembly::RAX, Framework::Assembly::FULL64), UNDEFINED, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // CMP r/m8, imm8 MachineCodeTableEntry(false, 0x80, (char)1, false, false, false, 0, 0b111, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // CMP r/m16, imm8 MachineCodeTableEntry(false, 0x83, (char)1, true, false, false, 0, 0b111, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // CMP r/m32, imm8 MachineCodeTableEntry(false, 0x83, (char)1, false, false, false, 0, 0b111, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // CMP r/m64, imm8 MachineCodeTableEntry(true, 0x83, (char)1, false, false, false, 0, 0b111, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // CMP r/m16, imm16 MachineCodeTableEntry(false, 0x81, (char)1, true, false, false, 0, 0b111, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // CMP r/m32, imm32 MachineCodeTableEntry(false, 0x81, (char)1, false, false, false, 0, 0b111, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // TEST r/m64, imm32 MachineCodeTableEntry(true, 0x81, (char)1, false, false, false, 0, 0b111, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // CMP r/m8, r8 MachineCodeTableEntry(false, 0x38, (char)1, false, false, false, 0, 0b111, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ), // CMP r/m16, r16 MachineCodeTableEntry(false, 0x39, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ), // CMP r/m32, r32 MachineCodeTableEntry(false, 0x39, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ), // CMP r/m64, r64 MachineCodeTableEntry(true, 0x39, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ), // CMP r8, r/m8 MachineCodeTableEntry(false, 0x3A, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // CMP r16, r/m16 MachineCodeTableEntry(false, 0x3B, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // CMP r32, r/m32 MachineCodeTableEntry(false, 0x3B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // CMP r64, r/m64 MachineCodeTableEntry(true, 0x3B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::CMPPD, { // CMPPD xmm1, xmm2/m128, imm8 MachineCodeTableEntry(false, 0xC20F, (char)2, true, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // VCMPPD xmm1, xmm2, xmm3/m128, imm8 MachineCodeTableEntry(false, 0xC20F, (char)2, false, true, false, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // VCMPPD ymm1, ymm2, ymm3/m256, imm8 MachineCodeTableEntry(false, 0xC20F, (char)2, false, true, true, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::CMPPS, { // CMPPS xmm1, xmm2/m128, imm8 MachineCodeTableEntry(false, 0xC20F, (char)2, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // VCMPPS xmm1, xmm2, xmm3/m128, imm8 MachineCodeTableEntry(false, 0xC20F, (char)2, false, true, false, 0b00, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // VCMPPS ymm1, ymm2, ymm3/m256, imm8 MachineCodeTableEntry(false, 0xC20F, (char)2, false, true, true, 0b00, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::CMPSD, { // CMPSD xmm1, xmm2/m128, imm8 MachineCodeTableEntry(false, 0xC20FF2, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // VCMPSD xmm1, xmm2, xmm3/m128, imm8 MachineCodeTableEntry(false, 0xC20F, (char)2, false, true, false, 0b11, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::CMPSS, { // CMPSS xmm1, xmm2/m128, imm8 MachineCodeTableEntry(false, 0xC20FF3, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READWRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // VCMPSS xmm1, xmm2, xmm3/m128, imm8 MachineCodeTableEntry(false, 0xC20F, (char)2, false, true, false, 0b10, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MOV, {// MOV r/m8, r8 MachineCodeTableEntry(false, 0x88, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, WRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, READ), // MOV r/m16, r16 MachineCodeTableEntry(false, 0x89, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, WRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, READ), // MOV r/m32, r32 MachineCodeTableEntry(false, 0x89, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, WRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, READ), // MOV r/m64, r64 MachineCodeTableEntry(true, 0x89, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, WRITE, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, READ), // MOV r8, r/m8 MachineCodeTableEntry(false, 0x8A, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_REG, WRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, READ), // MOV r/m16, r16 MachineCodeTableEntry(false, 0x8B, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, WRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // MOV r/m32, r32 MachineCodeTableEntry(false, 0x8B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, WRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // MOV r/m64, r64 MachineCodeTableEntry(true, 0x8B, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, WRITE, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), // Move imm8 to r8 MachineCodeTableEntry(false, 0xB0, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::BYTE), OPCODE_RD, WRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // MOV r16, imm16 MachineCodeTableEntry(false, 0xB8, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), OPCODE_RD, WRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // MOV r32, imm32 MachineCodeTableEntry(false, 0xB8, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), OPCODE_RD, WRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // MOV r64, imm64 MachineCodeTableEntry(true, 0xB8, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), OPCODE_RD, WRITE, isIMM(Framework::Assembly::MemoryBlockSize::QWORD), IMM64, READ), // MOV r/m8, imm8 MachineCodeTableEntry(false, 0xC6, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::BYTE), MODRM_RM, WRITE, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // MOV r/m16, imm16 MachineCodeTableEntry(false, 0xC7, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, WRITE, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // MOV r/m32, imm32 MachineCodeTableEntry(false, 0xC7, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, WRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // MOV r/m64, imm64 MachineCodeTableEntry(true, 0xC7, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, WRITE, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MOVAPD, { // MOVAPD xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x280F, (char)2, true, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // MOVAPD xmm2/m128, xmm1 MachineCodeTableEntry(false, 0x290F, (char)2, true, false, false, 0, 0, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READ), // MOVAPD xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x280F, (char)2, false, true, false, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VMOVAPD xmm2/m128, xmm1 MachineCodeTableEntry(false, 0x290F, (char)2, false, true, false, 0b01, 0, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READ), // MOVAPD ymm1, ymm2/m256 MachineCodeTableEntry(false, 0x280F, (char)2, false, true, true, 0b01, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ), // VMOVAPD ymm2/m256, ymm1 MachineCodeTableEntry(false, 0x290F, (char)2, false, true, true, 0b01, 0, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MOVAPS, { // MOVAPS xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x280F, (char)2, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // MOVAPS xmm2/m128, xmm1 MachineCodeTableEntry(false, 0x290F, (char)2, false, false, false, 0, 0, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READ), // VMOVAPS xmm1, xmm2/m128 MachineCodeTableEntry(false, 0x280F, (char)2, false, true, false, 0b00, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), // VMOVAPS xmm2/m128, xmm1 MachineCodeTableEntry(false, 0x290F, (char)2, false, true, false, 0b00, 0, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READ), // VMOVAPS ymm1, ymm2/m256 MachineCodeTableEntry(false, 0x280F, (char)2, false, true, true, 0b00, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, WRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, READ), // VMOVAPS ymm2/m256, ymm1 MachineCodeTableEntry(false, 0x290F, (char)2, false, true, true, 0b00, 0, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M256), MODRM_RM, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M256), MODRM_REG, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MOVSD, { // MOVSD xmm1, xmm2/m64 MachineCodeTableEntry(false, 0x100FF2, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), // MOVSD xmm2/m128, xmm1 MachineCodeTableEntry(false, 0x110FF2, (char)3, false, false, false, 0, 0, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READ), // VMOVSD VMOVSD xmm1, xmm2, xmm3 MachineCodeTableEntry(false, 0x100F, (char)2, false, true, false, 0b11, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::MOVSS, { // MOVSS xmm1, xmm2/m32 MachineCodeTableEntry(false, 0x100FF3, (char)3, false, false, false, 0, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::DWORD), MODRM_RM, READ), // MOVSS xmm2/m128, xmm1 MachineCodeTableEntry(false, 0x110FF3, (char)3, false, false, false, 0, 0, isFPRegisterOrMEmoryAccess( Framework::Assembly::MemoryBlockSize::M128, Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, READ), // VMOVSS VMOVSD xmm1, xmm2, xmm3 MachineCodeTableEntry(false, 0x100F, (char)2, false, true, false, 0b10, 0, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_REG, WRITE, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), VEX_VVVV, READ, isFPRegister( Framework::Assembly::MemoryBlockSize::M128), MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::LEA, { // LEA r16,m MachineCodeTableEntry( false, 0x8D, (char)1, true, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::WORD), MODRM_REG, WRITE, [](const Framework::Assembly::OperationArgument& p) { return p.asMemoryAccessArgument(); }, MODRM_RM, READ), // LEA r32,m MachineCodeTableEntry( false, 0x8D, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::DWORD), MODRM_REG, WRITE, [](const Framework::Assembly::OperationArgument& p) { return p.asMemoryAccessArgument(); }, MODRM_RM, READ), // LEA r64,m MachineCodeTableEntry( true, 0x8D, (char)1, false, false, false, 0, 0, isGPRegister( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_REG, WRITE, [](const Framework::Assembly::OperationArgument& p) { return p.asMemoryAccessArgument(); }, MODRM_RM, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JMP, 1, {// JMP rel32 MachineCodeTableEntry(false, 0xE9, (char)1, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JZ, 2, {// JZ rel32 MachineCodeTableEntry(false, 0x840F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JNZ, 2, {// JNZ rel32 MachineCodeTableEntry(false, 0x850F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JG, 2, {// JG rel32 MachineCodeTableEntry(false, 0x8F0F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JGE, 2, {// JGE rel32 MachineCodeTableEntry(false, 0x8D0F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JL, 2, {// JL rel32 MachineCodeTableEntry(false, 0x8C0F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JLE, 2, {// JLE rel32 MachineCodeTableEntry(false, 0x8E0F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JA, 2, {// JA rel32 MachineCodeTableEntry(false, 0x870F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JC, 2, {// JC rel32 MachineCodeTableEntry(false, 0x820F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JNC, 2, {// JNC rel32 MachineCodeTableEntry(false, 0x830F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JBE, 2, {// JBE rel32 MachineCodeTableEntry(false, 0x860F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JO, 2, {// JO rel32 MachineCodeTableEntry(false, 0x800F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JNO, 2, {// JNO rel32 MachineCodeTableEntry(false, 0x810F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JP, 2, {// JP rel32 MachineCodeTableEntry(false, 0x8A0F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JNP, 2, {// JNP rel32 MachineCodeTableEntry(false, 0x8B0F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JS, 2, {// JS rel32 MachineCodeTableEntry(false, 0x880F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new JumpOperationCodeTable(Framework::Assembly::JNS, 2, {// JNS rel32 MachineCodeTableEntry(false, 0x890F, (char)2, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::CALL, {// CALL rel32 MachineCodeTableEntry(false, 0xE8, (char)1, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), // CALL r/m64 MachineCodeTableEntry(false, 0xFF, (char)1, false, false, false, 0, 0b010, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::RET, {// RET MachineCodeTableEntry( false, 0xC3, (char)1, false, false, false, 0, 0)})); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::PUSH, { // PUSH r/m16 MachineCodeTableEntry(false, 0xFF, (char)1, true, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // PUSH r/m64 MachineCodeTableEntry(false, 0xFF, (char)1, false, false, false, 0, 0b110, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), // PUSH imm8 MachineCodeTableEntry(false, 0x6A, (char)1, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::BYTE), IMM8, READ), // PUSH imm16 MachineCodeTableEntry(false, 0x68, (char)1, true, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::WORD), IMM16, READ), // PUSH imm32 MachineCodeTableEntry(false, 0x68, (char)1, false, false, false, 0, 0, isIMM(Framework::Assembly::MemoryBlockSize::DWORD), IMM32, READ), })); OperationCodeTable::machineCodeTranslationTable.add( new OperationCodeTable(Framework::Assembly::POP, { // POP r/m16 MachineCodeTableEntry(false, 0x8F, (char)1, true, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::WORD), MODRM_RM, READ), // POP r/m64 MachineCodeTableEntry(false, 0x8F, (char)1, false, false, false, 0, 0, isGPRegisterOrMemoryAccess( Framework::Assembly::MemoryBlockSize::QWORD), MODRM_RM, READ), })); } } bool Framework::Assembly::OperationArgument::usesRegister(GPRegister reg) const { return false; } bool Framework::Assembly::OperationArgument::usesRegister(FPRegister reg) const { return false; } void Framework::Assembly::OperationArgument::replaceRegister( GPRegister oldReg, GPRegister newReg) {} void Framework::Assembly::OperationArgument::replaceRegister( FPRegister oldReg, FPRegister newReg) {} void Framework::Assembly::OperationArgument::addJumpLabelPrefix( Text labelPrefix) {} const Framework::Assembly::GPRegisterArgument* Framework::Assembly::OperationArgument::asGPRegisterArgument() const { return dynamic_cast(this); } const Framework::Assembly::MemoryAccessArgument* Framework::Assembly::OperationArgument::asMemoryAccessArgument() const { return dynamic_cast(this); } const Framework::Assembly::ConstantArgument* Framework::Assembly::OperationArgument::asConstantArgument() const { return dynamic_cast(this); } const Framework::Assembly::FPRegisterArgument* Framework::Assembly::OperationArgument::asFPRegisterArgument() const { return dynamic_cast(this); } const Framework::Assembly::JumpTargetArgument* Framework::Assembly::OperationArgument::asJumpTargetArgument() const { return dynamic_cast(this); } Framework::Assembly::GPRegisterArgument::GPRegisterArgument( GPRegister reg, GPRegisterPart part) : reg(reg), part(part) {} bool Framework::Assembly::GPRegisterArgument::usesRegister(GPRegister reg) const { return this->reg == reg; } void Framework::Assembly::GPRegisterArgument::replaceRegister( GPRegister oldReg, GPRegister newReg) { if (reg == oldReg) { reg = newReg; } } Framework::Assembly::GPRegister Framework::Assembly::GPRegisterArgument::getRegister() const { return reg; } Framework::Assembly::GPRegisterPart Framework::Assembly::GPRegisterArgument::getPart() const { return part; } Framework::Assembly::FPRegisterArgument::FPRegisterArgument( FPRegister reg, FPRegisterPart part) : reg(reg), part(part) {} bool Framework::Assembly::FPRegisterArgument::usesRegister(FPRegister reg) const { return this->reg == reg; } void Framework::Assembly::FPRegisterArgument::replaceRegister( FPRegister oldReg, FPRegister newReg) { if (reg == oldReg) { reg = newReg; } } Framework::Assembly::FPRegister Framework::Assembly::FPRegisterArgument::getRegister() const { return reg; } Framework::Assembly::FPRegisterPart Framework::Assembly::FPRegisterArgument::getPart() const { return part; } Framework::Assembly::MemoryAccessArgument::MemoryAccessArgument( MemoryBlockSize blockSize, GPRegister address, bool useAddressReg, int offset, bool useOffsetReg, GPRegister offsetReg) : blockSize(blockSize), useAddressReg(useAddressReg), address(address), offset(offset), offsetReg(offsetReg), useOffsetReg(useOffsetReg) {} bool Framework::Assembly::MemoryAccessArgument::usesRegister( GPRegister reg) const { return (useAddressReg && this->address == reg) || (useOffsetReg && offsetReg == reg); } void Framework::Assembly::MemoryAccessArgument::replaceRegister( GPRegister oldReg, GPRegister newReg) { if (useAddressReg && address == oldReg) { address = newReg; } if (useOffsetReg && offsetReg == oldReg) { offsetReg = newReg; } } bool Framework::Assembly::MemoryAccessArgument::isUsingAddressRegister() const { return useAddressReg; } Framework::Assembly::GPRegister Framework::Assembly::MemoryAccessArgument::getAddressRegister() const { return address; } int Framework::Assembly::MemoryAccessArgument::getOffset() const { return offset; } bool Framework::Assembly::MemoryAccessArgument::isUsingOffsetRegister() const { return useOffsetReg; } Framework::Assembly::GPRegister Framework::Assembly::MemoryAccessArgument::getOffsetRegister() const { return offsetReg; } Framework::Assembly::MemoryBlockSize Framework::Assembly::MemoryAccessArgument::getBlockSize() const { return blockSize; } Framework::Assembly::ConstantArgument::ConstantArgument( __int64 value, MemoryBlockSize size) : value(value), size(size) {} Framework::Assembly::ConstantArgument::ConstantArgument( int value, MemoryBlockSize size) : value((__int64)value), size(size) {} Framework::Assembly::ConstantArgument::ConstantArgument( short value, MemoryBlockSize size) : value((__int64)value), size(size) {} Framework::Assembly::ConstantArgument::ConstantArgument( char value, MemoryBlockSize size) : value((__int64)value), size(size) {} __int64 Framework::Assembly::ConstantArgument::getValue() const { return value; } Framework::Assembly::MemoryBlockSize Framework::Assembly::ConstantArgument::getSize() const { return size; } Framework::Assembly::JumpTargetArgument::JumpTargetArgument(Text name) : name(name) {} void Framework::Assembly::JumpTargetArgument::addJumpLabelPrefix( Text labelPrefix) { name = labelPrefix + name; } const Framework::Text& Framework::Assembly::JumpTargetArgument::getLabel() const { return name; } Framework::Assembly::Instruction::Instruction( Operation op, std::initializer_list args) : ReferenceCounter(), op(op), args(args) {} Framework::Assembly::Instruction::~Instruction() { for (auto arg : args) { delete arg; } } bool Framework::Assembly::Instruction::writesToRegister( GPRegister reg, const AssemblyBlock* block) const { __intializeMachineCodeTranslationTable(); for (OperationCodeTable* tableEntry : OperationCodeTable::machineCodeTranslationTable) { if (tableEntry->getOperation() == op) { MachineCodeTableEntry& entry = tableEntry->getEntry(args, block, this); for (GPRegister r : entry.getImpliedWriteGPRegs()) { if (r == reg) { return 1; } } int index = 0; for (const OperationArgument* arg : args) { OperandRW rw = entry.getOperandRW(index); if (rw == WRITE || rw == READWRITE) { if (arg->asGPRegisterArgument() && arg->asGPRegisterArgument()->getRegister() == reg) { return 1; } } index++; } } } return 0; } bool Framework::Assembly::Instruction::writesToRegister( FPRegister reg, const AssemblyBlock* block) const { __intializeMachineCodeTranslationTable(); for (OperationCodeTable* tableEntry : OperationCodeTable::machineCodeTranslationTable) { if (tableEntry->getOperation() == op) { MachineCodeTableEntry& entry = tableEntry->getEntry(args, block, this); for (FPRegister r : entry.getImpliedWriteFPRegs()) { if (r == reg) { return 1; } } int index = 0; for (const OperationArgument* arg : args) { OperandRW rw = entry.getOperandRW(index); if (rw == WRITE || rw == READWRITE) { if (arg->asFPRegisterArgument() && arg->asFPRegisterArgument()->getRegister() == reg) { return 1; } } index++; } } } return 0; } bool Framework::Assembly::Instruction::readsFromRegister( GPRegister reg, const AssemblyBlock* block) const { __intializeMachineCodeTranslationTable(); for (OperationCodeTable* tableEntry : OperationCodeTable::machineCodeTranslationTable) { if (tableEntry->getOperation() == op) { const MachineCodeTableEntry& entry = tableEntry->getEntry(args, block, this); for (GPRegister r : entry.getImpliedReadGPRegs()) { if (r == reg) { return 1; } } int index = 0; for (const OperationArgument* arg : args) { OperandRW rw = entry.getOperandRW(index); if (rw == READ || rw == READWRITE) { if (arg->asGPRegisterArgument() && arg->asGPRegisterArgument()->getRegister() == reg) { return 1; } } if (arg->asMemoryAccessArgument() && arg->asMemoryAccessArgument()->usesRegister(reg)) { return 1; } index++; } } } return 0; } bool Framework::Assembly::Instruction::readsFromRegister( FPRegister reg, const AssemblyBlock* block) const { __intializeMachineCodeTranslationTable(); for (OperationCodeTable* tableEntry : OperationCodeTable::machineCodeTranslationTable) { if (tableEntry->getOperation() == op) { MachineCodeTableEntry& entry = tableEntry->getEntry(args, block, this); for (FPRegister r : entry.getImpliedReadFPRegs()) { if (r == reg) { return 1; } } int index = 0; for (const OperationArgument* arg : args) { OperandRW rw = entry.getOperandRW(index); if (rw == READ || rw == READWRITE) { if (arg->asFPRegisterArgument() && arg->asFPRegisterArgument()->getRegister() == reg) { return 1; } } index++; } } } return 0; } bool Framework::Assembly::Instruction::isReplacementPossible( GPRegister oldReg, GPRegister newReg, const AssemblyBlock* block) const { __intializeMachineCodeTranslationTable(); for (OperationCodeTable* tableEntry : OperationCodeTable::machineCodeTranslationTable) { if (tableEntry->getOperation() == op) { MachineCodeTableEntry& entry = tableEntry->getEntry(args, block, this); for (GPRegister r : entry.getImpliedReadGPRegs()) { if (r == oldReg) { return 0; } } for (GPRegister r : entry.getImpliedWriteGPRegs()) { if (r == oldReg) { return 0; } } } } if (newReg == RBP || newReg == RSI || newReg == RDI) { if (oldReg == RBP || oldReg == RSI || oldReg == RDI) { return 1; } else { return 0; } } if (newReg >= R8) { return oldReg >= R8; } return oldReg < R8; } bool Framework::Assembly::Instruction::isReplacementPossible( FPRegister oldReg, FPRegister newReg, const AssemblyBlock* block) const { __intializeMachineCodeTranslationTable(); for (OperationCodeTable* tableEntry : OperationCodeTable::machineCodeTranslationTable) { if (tableEntry->getOperation() == op) { MachineCodeTableEntry& entry = tableEntry->getEntry(args, block, this); for (FPRegister r : entry.getImpliedReadFPRegs()) { if (r == oldReg) { return 0; } } for (FPRegister r : entry.getImpliedWriteFPRegs()) { if (r == oldReg) { return 0; } } } } return 1; } void Framework::Assembly::Instruction::replaceRegister( GPRegister oldReg, GPRegister newReg) { for (auto arg : args) { arg->replaceRegister(oldReg, newReg); } } void Framework::Assembly::Instruction::replaceRegister( FPRegister oldReg, FPRegister newReg) { for (auto arg : args) { arg->replaceRegister(oldReg, newReg); } } void Framework::Assembly::Instruction::addJumpLabelPrefix(Text labelPrefix) { for (auto arg : args) { arg->addJumpLabelPrefix(labelPrefix); } } void Framework::Assembly::Instruction::compile( StreamWriter* byteCodeWriter, const AssemblyBlock* block) const { __intializeMachineCodeTranslationTable(); for (OperationCodeTable* tableEntry : OperationCodeTable::machineCodeTranslationTable) { if (tableEntry->getOperation() == op) { MachineCodeInstruction instr = tableEntry->getInstruction(args, block, this); instr.write(*byteCodeWriter); return; } } Text err; err.append() << "Failed to compile instruction: operation code " << (int)op << " not found in translation table. args: \n"; for (auto arg : args) { err.append() << " " << typeid(*arg).name() << "\n"; } throw err.getText(); } int Framework::Assembly::Instruction::compiledSize( const AssemblyBlock* block) const { __intializeMachineCodeTranslationTable(); for (OperationCodeTable* tableEntry : OperationCodeTable::machineCodeTranslationTable) { if (tableEntry->getOperation() == op) { MachineCodeInstruction instr = tableEntry->getInstruction(args, block, this); return instr.calculateSize(); } } return 0; } Framework::Assembly::Operation Framework::Assembly::Instruction::getOperation() const { return op; } bool Framework::Assembly::Instruction::definesLabel(Text label) const { return op == NOP && args.size() == 1 && args.at(0)->asJumpTargetArgument() && args.at(0)->asJumpTargetArgument()->getLabel().istGleich(label); } Framework::Assembly::AssemblyBlock::AssemblyBlock() : inlineIndex(0), compiledCode(0) {} Framework::Assembly::AssemblyBlock::~AssemblyBlock() { if (compiledCode != 0) { // Free the compiled code memory VirtualFree(compiledCode, 0, MEM_RELEASE); } } void Framework::Assembly::AssemblyBlock::addInstruction(Instruction* instr) { instructions.add(instr); } void Framework::Assembly::AssemblyBlock::defineJumpTarget(Text name) { instructions.add(new Instruction(NOP, {new JumpTargetArgument(name)})); } void Framework::Assembly::AssemblyBlock::addJump( Operation jumpOp, Text targetName) { instructions.add( new Instruction(jumpOp, {new JumpTargetArgument(targetName)})); } void Framework::Assembly::AssemblyBlock::addLoadValue( char* valueAddress, GPRegister target) { instructions.add(new Instruction(MOV, {new GPRegisterArgument(target), new ConstantArgument(reinterpret_cast<__int64>(valueAddress))})); instructions.add(new Instruction(MOV, {new GPRegisterArgument(target, LOWER8), new MemoryAccessArgument(MemoryBlockSize::BYTE, target)})); } void Framework::Assembly::AssemblyBlock::addLoadValue( short* valueAddress, GPRegister target) { instructions.add(new Instruction(MOV, {new GPRegisterArgument(target), new ConstantArgument(reinterpret_cast<__int64>(valueAddress))})); instructions.add(new Instruction(MOV, {new GPRegisterArgument(target, LOWER16), new MemoryAccessArgument(MemoryBlockSize::WORD, target)})); } void Framework::Assembly::AssemblyBlock::addLoadValue( int* valueAddress, GPRegister target) { instructions.add(new Instruction(MOV, {new GPRegisterArgument(target), new ConstantArgument(reinterpret_cast<__int64>(valueAddress))})); instructions.add(new Instruction(MOV, {new GPRegisterArgument(target, LOWER32), new MemoryAccessArgument(MemoryBlockSize::DWORD, target)})); } void Framework::Assembly::AssemblyBlock::addLoadValue( __int64* valueAddress, GPRegister target) { instructions.add(new Instruction(MOV, {new GPRegisterArgument(target), new ConstantArgument(reinterpret_cast<__int64>(valueAddress))})); instructions.add(new Instruction(MOV, {new GPRegisterArgument(target), new MemoryAccessArgument(MemoryBlockSize::QWORD, target)})); } void Framework::Assembly::AssemblyBlock::addLoadValue( float* valueAddress, FPRegister target, GPRegister temp) { instructions.add(new Instruction(MOV, {new GPRegisterArgument(temp), new ConstantArgument(reinterpret_cast<__int64>(valueAddress))})); instructions.add(new Instruction(MOVSS, {new FPRegisterArgument(target), new MemoryAccessArgument(MemoryBlockSize::DWORD, temp)})); } void Framework::Assembly::AssemblyBlock::addLoadValue( double* valueAddress, FPRegister target, GPRegister temp) { instructions.add(new Instruction(MOV, {new GPRegisterArgument(temp), new ConstantArgument(reinterpret_cast<__int64>(valueAddress))})); instructions.add(new Instruction(MOVSD, {new FPRegisterArgument(target), new MemoryAccessArgument(MemoryBlockSize::QWORD, temp)})); } void Framework::Assembly::AssemblyBlock::addCall( void* functionAddress, GPRegister temp) { instructions.add(new Instruction(MOV, {new GPRegisterArgument(temp), new ConstantArgument(reinterpret_cast<__int64>(functionAddress))})); instructions.add(new Instruction( CALL, {new MemoryAccessArgument(MemoryBlockSize::QWORD, temp)})); } void Framework::Assembly::AssemblyBlock::addReturn() { instructions.add(new Instruction(RET, {})); } void Framework::Assembly::AssemblyBlock::addPush( GPRegister reg, GPRegisterPart part) { instructions.add( new Instruction(PUSH, {new GPRegisterArgument(reg, part)})); } void Framework::Assembly::AssemblyBlock::addPop( GPRegister reg, GPRegisterPart part) { instructions.add(new Instruction(POP, {new GPRegisterArgument(reg, part)})); } void Framework::Assembly::AssemblyBlock::addPush( FPRegister reg, FPRegisterPart part) { instructions.add(new Instruction(SUB, {new GPRegisterArgument(RSP), new ConstantArgument(part == X ? 16 : 32)})); instructions.add(new Instruction(MOVAPD, {new MemoryAccessArgument( part == X ? MemoryBlockSize::M128 : MemoryBlockSize::M256, RSP), new FPRegisterArgument(reg, part)})); } void Framework::Assembly::AssemblyBlock::addPop( FPRegister reg, FPRegisterPart part) { instructions.add(new Instruction(MOVAPD, {new FPRegisterArgument(reg, part), new MemoryAccessArgument( part == X ? MemoryBlockSize::M128 : MemoryBlockSize::M256, RSP)})); instructions.add(new Instruction(ADD, {new GPRegisterArgument(RSP), new ConstantArgument(part == X ? 16 : 32)})); } void Framework::Assembly::AssemblyBlock::addBlock(AssemblyBlock* block, std::initializer_list preservedGPRegisters, std::initializer_list preservedFPRegisters, GPRegister* blockResultGpReg, FPRegister* blockResultFpReg) { RCArray tempInstructions; for (GPRegister preservedReg : preservedGPRegisters) { if (block->writesToRegister(preservedReg)) { bool replaced = false; for (int i = 0; i < 16; i++) { if (i == 4) { continue; // Skip RSP (stack counter register) } bool found = false; for (GPRegister r : preservedGPRegisters) { if (r == (GPRegister)i) { found = true; break; } } if (found) { continue; } GPRegister newReg = (GPRegister)i; if (!block->writesToRegister(newReg) && !block->readsFromRegister(newReg) && block->isReplacementPossible(preservedReg, newReg)) { if (preservedReg == RAX) { *blockResultGpReg = newReg; } replaced = true; block->replaceRegister(preservedReg, newReg); break; } } if (!replaced) { addPush(preservedReg); tempInstructions.add( new Instruction( POP, {new GPRegisterArgument(preservedReg)}), 0); } } } for (FPRegister preservedReg : preservedFPRegisters) { if (block->writesToRegister(preservedReg)) { bool replaced = false; for (int i = 0; i < __FP_REGISTER_COUNT; i++) { bool found = false; for (FPRegister r : preservedFPRegisters) { if (r == (FPRegister)i) { found = true; break; } } if (found) { continue; } FPRegister newReg = (FPRegister)i; if (!block->writesToRegister(newReg) && !block->readsFromRegister(newReg) && block->isReplacementPossible(preservedReg, newReg)) { if (preservedReg == MM0) { *blockResultFpReg = newReg; } replaced = true; block->replaceRegister(preservedReg, newReg); break; } } if (!replaced) { addPush(preservedReg); tempInstructions.add(new Instruction(MOVAPD, {new FPRegisterArgument(preservedReg, Y), new MemoryAccessArgument(MemoryBlockSize::M256, RSP)})); tempInstructions.add(new Instruction(ADD, {new GPRegisterArgument(RSP), new ConstantArgument(32)})); } } } int index = 0; Text prefix = "inlined_"; prefix.append() << inlineIndex << "_"; block->addJumpLabelPrefix(prefix); bool returnFound = false; for (const auto& instr : block->instructions) { if (instr->getOperation() == RET) { if (index != block->instructions.getEintragAnzahl() - 1) { returnFound = true; instructions.add(new Instruction( JMP, {new JumpTargetArgument(Text("after_") + prefix)})); } } else { instructions.add(dynamic_cast(instr->getThis())); } index++; } if (returnFound) { defineJumpTarget(Text("after_") + prefix); } for (const auto& instr : tempInstructions) { instructions.add(dynamic_cast(instr->getThis())); } } bool Framework::Assembly::AssemblyBlock::writesToRegister(GPRegister reg) const { for (const auto& instr : instructions) { if (instr->writesToRegister(reg, this)) { return true; } } return false; } bool Framework::Assembly::AssemblyBlock::writesToRegister(FPRegister reg) const { for (const auto& instr : instructions) { if (instr->writesToRegister(reg, this)) { return true; } } return false; } bool Framework::Assembly::AssemblyBlock::readsFromRegister(GPRegister reg) const { for (const auto& instr : instructions) { if (instr->readsFromRegister(reg, this)) { return true; } } return false; } bool Framework::Assembly::AssemblyBlock::readsFromRegister(FPRegister reg) const { for (const auto& instr : instructions) { if (instr->readsFromRegister(reg, this)) { return true; } } return false; } bool Framework::Assembly::AssemblyBlock::isReplacementPossible( GPRegister oldReg, GPRegister newReg) const { for (const auto& instr : instructions) { if (!instr->isReplacementPossible(oldReg, newReg, this)) { return false; } } return true; } bool Framework::Assembly::AssemblyBlock::isReplacementPossible( FPRegister oldReg, FPRegister newReg) const { for (const auto& instr : instructions) { if (!instr->isReplacementPossible(oldReg, newReg, this)) { return false; } } return true; } void Framework::Assembly::AssemblyBlock::replaceRegister( GPRegister oldReg, GPRegister newReg) { for (const auto& instr : instructions) { instr->replaceRegister(oldReg, newReg); } } void Framework::Assembly::AssemblyBlock::replaceRegister( FPRegister oldReg, FPRegister newReg) { for (const auto& instr : instructions) { instr->replaceRegister(oldReg, newReg); } } void Framework::Assembly::AssemblyBlock::addJumpLabelPrefix(Text labelPrefix) { for (const auto& instr : instructions) { instr->addJumpLabelPrefix(labelPrefix); } } const Framework::RCArray& Framework::Assembly::AssemblyBlock::getInstructions() const { return instructions; } void* Framework::Assembly::AssemblyBlock::compile() { if (compiledCode != 0) { return compiledCode; } InMemoryBuffer buffer; int index = 0; // check non-volatile registers RCArray restoreInstructions; for (GPRegister nvReg : {RBX, RBP, RSI, RDI, R12, R13, R14, R15}) { if (writesToRegister(nvReg)) { Instruction pushInstr( PUSH, {new GPRegisterArgument(nvReg, FULL64)}); pushInstr.compile(&buffer, this); restoreInstructions.add( new Instruction(POP, {new GPRegisterArgument(nvReg, FULL64)}), 0); } } for (FPRegister nvReg : {MM6, MM7, MM8, MM9, MM10, MM11, MM12, MM13, MM14, MM15}) { if (writesToRegister(nvReg)) { Instruction subInst( SUB, {new GPRegisterArgument(RSP), new ConstantArgument(32)}); subInst.compile(&buffer, this); Instruction pushInstr(MOVAPD, {new MemoryAccessArgument(MemoryBlockSize::M256, RSP), new FPRegisterArgument(nvReg, Y)}); pushInstr.compile(&buffer, this); restoreInstructions.add(new Instruction(MOVAPD, {new FPRegisterArgument(nvReg, Y), new MemoryAccessArgument(MemoryBlockSize::M256, RSP)})); restoreInstructions.add(new Instruction( ADD, {new GPRegisterArgument(RSP), new ConstantArgument(32)})); } } // replace return instructions with jumps to the end if (restoreInstructions.getEintragAnzahl() > 0) { bool needed = false; for (int index = 0; index < instructions.getEintragAnzahl(); index++) { if (instructions.z(index)->getOperation() == RET) { if (index < instructions.getEintragAnzahl() - 1) { needed = true; instructions.set( new Instruction(JMP, {new JumpTargetArgument( Text("_restore_non_volatile_registers"))}), index); } else { // remove last RET instruction, will be added after non // volatile registers were restored from the stack instructions.remove(index); } } } if (needed) { defineJumpTarget(Text("_restore_non_volatile_registers")); } } // compile instructions for (const auto& instr : instructions) { instr->compile(&buffer, this); } // restore non-volatile registers for (const auto& instr : restoreInstructions) { instr->compile(&buffer, this); } // add final RET instruction if (instructions.z(instructions.getLastIndex())->getOperation() != RET) { Instruction retInstr(RET, {}); retInstr.compile(&buffer, this); } int totalSize = (int)buffer.getSize(); // Allocate executable memory compiledCode = VirtualAlloc(nullptr, totalSize, MEM_COMMIT, PAGE_READWRITE); if (compiledCode == nullptr) { throw std::runtime_error("Failed to allocate executable memory."); } // Write the compiled code into the allocated memory buffer.lese((char*)compiledCode, totalSize); DWORD dummy; VirtualProtect(compiledCode, totalSize, PAGE_EXECUTE_READ, &dummy); return compiledCode; }