/* * getIDWithAttrMask - Determines the ID of an instruction, consuming * the ModR/M byte as appropriate for extended and escape opcodes, * and using a supplied attribute mask. * * @param instructionID - A pointer whose target is filled in with the ID of the * instruction. * @param insn - The instruction whose ID is to be determined. * @param attrMask - The attribute mask to search. * @return - 0 if the ModR/M could be read when needed or was not * needed; nonzero otherwise. */ static int getIDWithAttrMask(uint16_t* instructionID, struct InternalInstruction* insn, uint8_t attrMask) { BOOL hasModRMExtension; uint8_t instructionClass; instructionClass = contextForAttrs(attrMask); hasModRMExtension = modRMRequired(insn->opcodeType, instructionClass, insn->opcode); if (hasModRMExtension) { if (readModRM(insn)) return -1; *instructionID = decode(insn->opcodeType, instructionClass, insn->opcode, insn->modRM); } else { *instructionID = decode(insn->opcodeType, instructionClass, insn->opcode, 0); } return 0; }
/* * readOperands - Consults the specifier for an instruction and consumes all * operands for that instruction, interpreting them as it goes. * * @param insn - The instruction whose operands are to be read and interpreted. * @return - 0 if all operands could be read; nonzero otherwise. */ static int readOperands(struct InternalInstruction* insn) { int index; int hasVVVV, needVVVV; int sawRegImm = 0; dbgprintf(insn, "readOperands()"); /* If non-zero vvvv specified, need to make sure one of the operands uses it. */ hasVVVV = !readVVVV(insn); needVVVV = hasVVVV && (insn->vvvv != 0); for (index = 0; index < X86_MAX_OPERANDS; ++index) { switch (insn->spec->operands[index].encoding) { case ENCODING_NONE: break; case ENCODING_REG: case ENCODING_RM: if (readModRM(insn)) return -1; if (fixupReg(insn, &insn->spec->operands[index])) return -1; break; case ENCODING_CB: case ENCODING_CW: case ENCODING_CD: case ENCODING_CP: case ENCODING_CO: case ENCODING_CT: dbgprintf(insn, "We currently don't hande code-offset encodings"); return -1; case ENCODING_IB: if (sawRegImm) { /* Saw a register immediate so don't read again and instead split the previous immediate. FIXME: This is a hack. */ insn->immediates[insn->numImmediatesConsumed] = insn->immediates[insn->numImmediatesConsumed - 1] & 0xf; ++insn->numImmediatesConsumed; break; } if (readImmediate(insn, 1)) return -1; if (insn->spec->operands[index].type == TYPE_IMM3 && insn->immediates[insn->numImmediatesConsumed - 1] > 7) return -1; if (insn->spec->operands[index].type == TYPE_XMM128 || insn->spec->operands[index].type == TYPE_XMM256) sawRegImm = 1; break; case ENCODING_IW: if (readImmediate(insn, 2)) return -1; break; case ENCODING_ID: if (readImmediate(insn, 4)) return -1; break; case ENCODING_IO: if (readImmediate(insn, 8)) return -1; break; case ENCODING_Iv: if (readImmediate(insn, insn->immediateSize)) return -1; break; case ENCODING_Ia: if (readImmediate(insn, insn->addressSize)) return -1; break; case ENCODING_RB: if (readOpcodeRegister(insn, 1)) return -1; break; case ENCODING_RW: if (readOpcodeRegister(insn, 2)) return -1; break; case ENCODING_RD: if (readOpcodeRegister(insn, 4)) return -1; break; case ENCODING_RO: if (readOpcodeRegister(insn, 8)) return -1; break; case ENCODING_Rv: if (readOpcodeRegister(insn, 0)) return -1; break; case ENCODING_I: if (readOpcodeModifier(insn)) return -1; break; case ENCODING_VVVV: needVVVV = 0; /* Mark that we have found a VVVV operand. */ if (!hasVVVV) return -1; if (fixupReg(insn, &insn->spec->operands[index])) return -1; break; case ENCODING_DUP: break; default: dbgprintf(insn, "Encountered an operand with an unknown encoding."); return -1; } } /* If we didn't find ENCODING_VVVV operand, but non-zero vvvv present, fail */ if (needVVVV) return -1; return 0; }
/* * readOperands - Consults the specifier for an instruction and consumes all * operands for that instruction, interpreting them as it goes. * * @param insn - The instruction whose operands are to be read and interpreted. * @return - 0 if all operands could be read; nonzero otherwise. */ static int readOperands(struct InternalInstruction* insn) { int index; dbgprintf(insn, "readOperands()"); for (index = 0; index < X86_MAX_OPERANDS; ++index) { switch (insn->spec->operands[index].encoding) { case ENCODING_NONE: break; case ENCODING_REG: case ENCODING_RM: if (readModRM(insn)) return -1; if (fixupReg(insn, &insn->spec->operands[index])) return -1; break; case ENCODING_CB: case ENCODING_CW: case ENCODING_CD: case ENCODING_CP: case ENCODING_CO: case ENCODING_CT: dbgprintf(insn, "We currently don't hande code-offset encodings"); return -1; case ENCODING_IB: if (readImmediate(insn, 1)) return -1; break; case ENCODING_IW: if (readImmediate(insn, 2)) return -1; break; case ENCODING_ID: if (readImmediate(insn, 4)) return -1; break; case ENCODING_IO: if (readImmediate(insn, 8)) return -1; break; case ENCODING_Iv: readImmediate(insn, insn->immediateSize); break; case ENCODING_Ia: readImmediate(insn, insn->addressSize); break; case ENCODING_RB: readOpcodeRegister(insn, 1); break; case ENCODING_RW: readOpcodeRegister(insn, 2); break; case ENCODING_RD: readOpcodeRegister(insn, 4); break; case ENCODING_RO: readOpcodeRegister(insn, 8); break; case ENCODING_Rv: readOpcodeRegister(insn, 0); break; case ENCODING_I: readOpcodeModifier(insn); break; case ENCODING_DUP: break; default: dbgprintf(insn, "Encountered an operand with an unknown encoding."); return -1; } } return 0; }