示例#1
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;
}