Esempio n. 1
0
/*
 * decode - Reads the appropriate instruction table to obtain the unique ID of
 *   an instruction.
 *
 * @param type        - See modRMRequired().
 * @param insnContext - See modRMRequired().
 * @param opcode      - See modRMRequired().
 * @param modRM       - The ModR/M byte if required, or any value if not.
 * @return            - The UID of the instruction, or 0 on failure.
 */
static InstrUID decode(OpcodeType type,
                       InstructionContext insnContext,
                       uint8_t opcode,
                       uint8_t modRM) {
  const struct ModRMDecision* dec = 0;
  
  switch (type) {
  case ONEBYTE:
    dec = &ONEBYTE_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
    break;
  case TWOBYTE:
    dec = &TWOBYTE_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
    break;
  case THREEBYTE_38:
    dec = &THREEBYTE38_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
    break;
  case THREEBYTE_3A:
    dec = &THREEBYTE3A_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
    break;
  case THREEBYTE_A6:
    dec = &THREEBYTEA6_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
    break;
  case THREEBYTE_A7:
    dec = &THREEBYTEA7_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
    break;
  }
  
  switch (dec->modrm_type) {
  default:
    debug("Corrupt table!  Unknown modrm_type");
    return 0;
  case MODRM_ONEENTRY:
    return modRMTable[dec->instructionIDs];
  case MODRM_SPLITRM:
    if (modFromModRM(modRM) == 0x3)
      return modRMTable[dec->instructionIDs+1];
    return modRMTable[dec->instructionIDs];
  case MODRM_SPLITREG:
    if (modFromModRM(modRM) == 0x3)
      return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)+8];
    return modRMTable[dec->instructionIDs+((modRM & 0x38) >> 3)];
  case MODRM_FULL:
    return modRMTable[dec->instructionIDs+modRM];
  }
}
/*
 * decode - Reads the appropriate instruction table to obtain the unique ID of
 *   an instruction.
 *
 * @param type        - See modRMRequired().
 * @param insnContext - See modRMRequired().
 * @param opcode      - See modRMRequired().
 * @param modRM       - The ModR/M byte if required, or any value if not.
 */
static InstrUID decode(OpcodeType type,
                       InstructionContext insnContext,
                       uint8_t opcode,
                       uint8_t modRM) {
    struct ModRMDecision* dec;

    switch (type) {
    default:
        unreachable("Unknown opcode type");
    case ONEBYTE:
        dec = &ONEBYTE_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
        break;
    case TWOBYTE:
        dec = &TWOBYTE_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
        break;
    case THREEBYTE_38:
        dec = &THREEBYTE38_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
        break;
    case THREEBYTE_3A:
        dec = &THREEBYTE3A_SYM.opcodeDecisions[insnContext].modRMDecisions[opcode];
        break;
    }

    switch (dec->modrm_type) {
    default:
        unreachable("Corrupt table!  Unknown modrm_type");
    case MODRM_ONEENTRY:
        return dec->instructionIDs[0];
    case MODRM_SPLITRM:
        if (modFromModRM(modRM) == 0x3)
            return dec->instructionIDs[1];
        else
            return dec->instructionIDs[0];
    case MODRM_FULL:
        return dec->instructionIDs[modRM];
    }

    return 0;
}
Esempio n. 3
0
/*
 * readSIB - Consumes the SIB byte to determine addressing information for an
 *   instruction.
 *
 * @param insn  - The instruction whose SIB byte is to be read.
 * @return      - 0 if the SIB byte was successfully read; nonzero otherwise.
 */
static int readSIB(struct InternalInstruction* insn) {
  SIBIndex sibIndexBase = 0;
  SIBBase sibBaseBase = 0;
  uint8_t index, base;
  
  dbgprintf(insn, "readSIB()");
  
  if (insn->consumedSIB)
    return 0;
  
  insn->consumedSIB = TRUE;
  
  switch (insn->addressSize) {
  case 2:
    dbgprintf(insn, "SIB-based addressing doesn't work in 16-bit mode");
    return -1;
    break;
  case 4:
    sibIndexBase = SIB_INDEX_EAX;
    sibBaseBase = SIB_BASE_EAX;
    break;
  case 8:
    sibIndexBase = SIB_INDEX_RAX;
    sibBaseBase = SIB_BASE_RAX;
    break;
  }

  if (consumeByte(insn, &insn->sib))
    return -1;
  
  index = indexFromSIB(insn->sib) | (xFromREX(insn->rexPrefix) << 3);
  
  switch (index) {
  case 0x4:
    insn->sibIndex = SIB_INDEX_NONE;
    break;
  default:
    insn->sibIndex = (SIBIndex)(sibIndexBase + index);
    if (insn->sibIndex == SIB_INDEX_sib ||
        insn->sibIndex == SIB_INDEX_sib64)
      insn->sibIndex = SIB_INDEX_NONE;
    break;
  }
  
  switch (scaleFromSIB(insn->sib)) {
  case 0:
    insn->sibScale = 1;
    break;
  case 1:
    insn->sibScale = 2;
    break;
  case 2:
    insn->sibScale = 4;
    break;
  case 3:
    insn->sibScale = 8;
    break;
  }
  
  base = baseFromSIB(insn->sib) | (bFromREX(insn->rexPrefix) << 3);
  
  switch (base) {
  case 0x5:
    switch (modFromModRM(insn->modRM)) {
    case 0x0:
      insn->eaDisplacement = EA_DISP_32;
      insn->sibBase = SIB_BASE_NONE;
      break;
    case 0x1:
      insn->eaDisplacement = EA_DISP_8;
      insn->sibBase = (insn->addressSize == 4 ? 
                       SIB_BASE_EBP : SIB_BASE_RBP);
      break;
    case 0x2:
      insn->eaDisplacement = EA_DISP_32;
      insn->sibBase = (insn->addressSize == 4 ? 
                       SIB_BASE_EBP : SIB_BASE_RBP);
      break;
    case 0x3:
      debug("Cannot have Mod = 0b11 and a SIB byte");
      return -1;
    }
    break;
  default:
    insn->sibBase = (SIBBase)(sibBaseBase + base);
    break;
  }
  
  return 0;
}
Esempio n. 4
0
/*
 * readModRM - Consumes all addressing information (ModR/M byte, SIB byte, and
 *   displacement) for an instruction and interprets it.
 *
 * @param insn  - The instruction whose addressing information is to be read.
 * @return      - 0 if the information was successfully read; nonzero otherwise.
 */
static int readModRM(struct InternalInstruction* insn) {  
  uint8_t mod, rm, reg;
  
  dbgprintf(insn, "readModRM()");
  
  if (insn->consumedModRM)
    return 0;
  
  if (consumeByte(insn, &insn->modRM))
    return -1;
  insn->consumedModRM = TRUE;
  
  mod     = modFromModRM(insn->modRM);
  rm      = rmFromModRM(insn->modRM);
  reg     = regFromModRM(insn->modRM);
  
  /*
   * This goes by insn->registerSize to pick the correct register, which messes
   * up if we're using (say) XMM or 8-bit register operands.  That gets fixed in
   * fixupReg().
   */
  switch (insn->registerSize) {
  case 2:
    insn->regBase = MODRM_REG_AX;
    insn->eaRegBase = EA_REG_AX;
    break;
  case 4:
    insn->regBase = MODRM_REG_EAX;
    insn->eaRegBase = EA_REG_EAX;
    break;
  case 8:
    insn->regBase = MODRM_REG_RAX;
    insn->eaRegBase = EA_REG_RAX;
    break;
  }
  
  reg |= rFromREX(insn->rexPrefix) << 3;
  rm  |= bFromREX(insn->rexPrefix) << 3;
  
  insn->reg = (Reg)(insn->regBase + reg);
  
  switch (insn->addressSize) {
  case 2:
    insn->eaBaseBase = EA_BASE_BX_SI;
     
    switch (mod) {
    case 0x0:
      if (rm == 0x6) {
        insn->eaBase = EA_BASE_NONE;
        insn->eaDisplacement = EA_DISP_16;
        if (readDisplacement(insn))
          return -1;
      } else {
        insn->eaBase = (EABase)(insn->eaBaseBase + rm);
        insn->eaDisplacement = EA_DISP_NONE;
      }
      break;
    case 0x1:
      insn->eaBase = (EABase)(insn->eaBaseBase + rm);
      insn->eaDisplacement = EA_DISP_8;
      if (readDisplacement(insn))
        return -1;
      break;
    case 0x2:
      insn->eaBase = (EABase)(insn->eaBaseBase + rm);
      insn->eaDisplacement = EA_DISP_16;
      if (readDisplacement(insn))
        return -1;
      break;
    case 0x3:
      insn->eaBase = (EABase)(insn->eaRegBase + rm);
      if (readDisplacement(insn))
        return -1;
      break;
    }
    break;
  case 4:
  case 8:
    insn->eaBaseBase = (insn->addressSize == 4 ? EA_BASE_EAX : EA_BASE_RAX);
    
    switch (mod) {
    case 0x0:
      insn->eaDisplacement = EA_DISP_NONE; /* readSIB may override this */
      switch (rm) {
      case 0x4:
      case 0xc:   /* in case REXW.b is set */
        insn->eaBase = (insn->addressSize == 4 ? 
                        EA_BASE_sib : EA_BASE_sib64);
        readSIB(insn);
        if (readDisplacement(insn))
          return -1;
        break;
      case 0x5:
        insn->eaBase = EA_BASE_NONE;
        insn->eaDisplacement = EA_DISP_32;
        if (readDisplacement(insn))
          return -1;
        break;
      default:
        insn->eaBase = (EABase)(insn->eaBaseBase + rm);
        break;
      }
      break;
    case 0x1:
    case 0x2:
      insn->eaDisplacement = (mod == 0x1 ? EA_DISP_8 : EA_DISP_32);
      switch (rm) {
      case 0x4:
      case 0xc:   /* in case REXW.b is set */
        insn->eaBase = EA_BASE_sib;
        readSIB(insn);
        if (readDisplacement(insn))
          return -1;
        break;
      default:
        insn->eaBase = (EABase)(insn->eaBaseBase + rm);
        if (readDisplacement(insn))
          return -1;
        break;
      }
      break;
    case 0x3:
      insn->eaDisplacement = EA_DISP_NONE;
      insn->eaBase = (EABase)(insn->eaRegBase + rm);
      break;
    }
    break;
  } /* switch (insn->addressSize) */
  
  return 0;
}