Skip to content
X86RecognizableInstr.cpp 50.4 KiB
Newer Older
    opcodeToSet = Opcode;
    break;
  case X86Local::A7:
    opcodeType = THREEBYTE_A7;
    if (needsModRMForDecode(Form))
      filter = new ModFilter(isRegFormat(Form));
    else
      filter = new DumbFilter();
    opcodeToSet = Opcode;
    break;
  case X86Local::XOP8:
    opcodeType = XOP8_MAP;
    if (needsModRMForDecode(Form))
      filter = new ModFilter(isRegFormat(Form));
    else
      filter = new DumbFilter();
    opcodeToSet = Opcode;
    break;
  case X86Local::XOP9:
    opcodeType = XOP9_MAP;
    switch (Opcode) {
    default:
      if (needsModRMForDecode(Form))
        filter = new ModFilter(isRegFormat(Form));
      else
        filter = new DumbFilter();
      break;
#define EXTENSION_TABLE(n) case 0x##n:
    XOP9_MAP_EXTENSION_TABLES
#undef EXTENSION_TABLE
      switch (Form) {
      default:
        llvm_unreachable("Unhandled XOP9 extended opcode");
      case X86Local::MRM0r:
      case X86Local::MRM1r:
      case X86Local::MRM2r:
      case X86Local::MRM3r:
      case X86Local::MRM4r:
      case X86Local::MRM5r:
      case X86Local::MRM6r:
      case X86Local::MRM7r:
        filter = new ExtendedFilter(true, Form - X86Local::MRM0r);
        break;
      case X86Local::MRM0m:
      case X86Local::MRM1m:
      case X86Local::MRM2m:
      case X86Local::MRM3m:
      case X86Local::MRM4m:
      case X86Local::MRM5m:
      case X86Local::MRM6m:
      case X86Local::MRM7m:
        filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
        break;
      MRM_MAPPING
      } // switch (Form)
      break;
    } // switch (Opcode)
    opcodeToSet = Opcode;
    break;
  case X86Local::XOPA:
    opcodeType = XOPA_MAP;
    if (needsModRMForDecode(Form))
      filter = new ModFilter(isRegFormat(Form));
    else
      filter = new DumbFilter();
    opcodeToSet = Opcode;
    break;
  case X86Local::D8:
  case X86Local::D9:
  case X86Local::DA:
  case X86Local::DB:
  case X86Local::DC:
  case X86Local::DD:
  case X86Local::DE:
  case X86Local::DF:
    assert(Opcode >= 0xc0 && "Unexpected opcode for an escape opcode");
    opcodeType = ONEBYTE;
    if (Form == X86Local::AddRegFrm) {
      Spec->modifierType = MODIFIER_MODRM;
      Spec->modifierBase = Opcode;
      filter = new AddRegEscapeFilter(Opcode);
    } else {
      filter = new EscapeFilter(true, Opcode);
    }
    opcodeToSet = 0xd8 + (Prefix - X86Local::D8);
    break;
    opcodeType = ONEBYTE;
    switch (Opcode) {
#define EXTENSION_TABLE(n) case 0x##n:
    ONE_BYTE_EXTENSION_TABLES
#undef EXTENSION_TABLE
      switch (Form) {
      default:
        llvm_unreachable("Fell through the cracks of a single-byte "
                         "extended opcode");
      case X86Local::MRM0r:
      case X86Local::MRM1r:
      case X86Local::MRM2r:
      case X86Local::MRM3r:
      case X86Local::MRM4r:
      case X86Local::MRM5r:
      case X86Local::MRM6r:
      case X86Local::MRM7r:
        filter = new ExtendedFilter(true, Form - X86Local::MRM0r);
        break;
      case X86Local::MRM0m:
      case X86Local::MRM1m:
      case X86Local::MRM2m:
      case X86Local::MRM3m:
      case X86Local::MRM4m:
      case X86Local::MRM5m:
      case X86Local::MRM6m:
      case X86Local::MRM7m:
        filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
        break;
      } // switch (Form)
      break;
    case 0xd8:
    case 0xd9:
    case 0xda:
    case 0xdb:
    case 0xdc:
    case 0xdd:
    case 0xde:
    case 0xdf:
      filter = new EscapeFilter(false, Form - X86Local::MRM0m);
      break;
    default:
      if (needsModRMForDecode(Form))
        filter = new ModFilter(isRegFormat(Form));
      else
        filter = new DumbFilter();
      break;
    } // switch (Opcode)
    opcodeToSet = Opcode;
  } // switch (Prefix)

  assert(opcodeType != (OpcodeType)-1 &&
         "Opcode type not set");
  assert(filter && "Filter not set");

  if (Form == X86Local::AddRegFrm) {
    if(Spec->modifierType != MODIFIER_MODRM) {
      assert(opcodeToSet < 0xf9 &&
             "Not enough room for all ADDREG_FRM operands");
      uint8_t currentOpcode;

      for (currentOpcode = opcodeToSet;
           currentOpcode < opcodeToSet + 8;
           ++currentOpcode)
        tables.setTableFields(opcodeType,
                              insnContext(),
                              currentOpcode,
                              *filter,
      Spec->modifierType = MODIFIER_OPCODE;
      Spec->modifierBase = opcodeToSet;
    } else {
      // modifierBase was set where MODIFIER_MODRM was set
      tables.setTableFields(opcodeType,
                            insnContext(),
                            opcodeToSet,
                            *filter,
    }
  } else {
    tables.setTableFields(opcodeType,
                          insnContext(),
                          opcodeToSet,
                          *filter,
    Spec->modifierType = MODIFIER_NONE;
    Spec->modifierBase = opcodeToSet;
  }
}

#define TYPE(str, type) if (s == str) return type;
OperandType RecognizableInstr::typeFromString(const std::string &s,
                                              bool isSSE,
                                              bool hasREX_WPrefix,
                                              bool hasOpSizePrefix) {
  if (isSSE) {
    // For SSE instructions, we ignore the OpSize prefix and force operand
    // sizes.
    TYPE("GR16",              TYPE_R16)
    TYPE("GR32",              TYPE_R32)
    TYPE("GR64",              TYPE_R64)
  }
  if(hasREX_WPrefix) {
    // For instructions with a REX_W prefix, a declared 32-bit register encoding
    // is special.
    TYPE("GR32",              TYPE_R32)
  }
  if(!hasOpSizePrefix) {
    // For instructions without an OpSize prefix, a declared 16-bit register or
    // immediate encoding is special.
    TYPE("GR16",              TYPE_R16)
    TYPE("i16imm",            TYPE_IMM16)
  }
  TYPE("i16mem",              TYPE_Mv)
  TYPE("i16imm",              TYPE_IMMv)
  TYPE("i16i8imm",            TYPE_IMMv)
  TYPE("GR16",                TYPE_Rv)
  TYPE("i32mem",              TYPE_Mv)
  TYPE("i32imm",              TYPE_IMMv)
  TYPE("i32i8imm",            TYPE_IMM32)
  TYPE("i64mem",              TYPE_Mv)
  TYPE("i64i32imm",           TYPE_IMM64)
  TYPE("i64i8imm",            TYPE_IMM64)
  TYPE("GR64",                TYPE_R64)
  TYPE("i8mem",               TYPE_M8)
  TYPE("i8imm",               TYPE_IMM8)
  TYPE("GR8",                 TYPE_R8)
  TYPE("VR128",               TYPE_XMM128)
  TYPE("VR128X",              TYPE_XMM128)
  TYPE("f512mem",             TYPE_M512)
  TYPE("FR64X",               TYPE_XMM64)
  TYPE("FR32X",               TYPE_XMM32)
  TYPE("RST",                 TYPE_ST)
  TYPE("i128mem",             TYPE_M128)
  TYPE("i256mem",             TYPE_M256)
  TYPE("i512mem",             TYPE_M512)
  TYPE("i16imm_pcrel",        TYPE_REL16)
  TYPE("brtarget8",           TYPE_REL8)
  TYPE("f80mem",              TYPE_M80FP)
  TYPE("lea32mem",            TYPE_LEA)
  TYPE("lea64_32mem",         TYPE_LEA)
  TYPE("lea64mem",            TYPE_LEA)
  TYPE("VR64",                TYPE_MM64)
  TYPE("i64imm",              TYPE_IMMv)
  TYPE("opaque32mem",         TYPE_M1616)
  TYPE("opaque48mem",         TYPE_M1632)
  TYPE("opaque80mem",         TYPE_M1664)
  TYPE("opaque512mem",        TYPE_M512)
  TYPE("SEGMENT_REG",         TYPE_SEGMENTREG)
  TYPE("DEBUG_REG",           TYPE_DEBUGREG)
  TYPE("CONTROL_REG",         TYPE_CONTROLREG)
  TYPE("offset8",             TYPE_MOFFS8)
  TYPE("offset16",            TYPE_MOFFS16)
  TYPE("offset32",            TYPE_MOFFS32)
  TYPE("offset64",            TYPE_MOFFS64)
  TYPE("VR256",               TYPE_XMM256)
  TYPE("VR256X",              TYPE_XMM256)
  TYPE("VR512",               TYPE_XMM512)
  TYPE("VK1",                 TYPE_VK1)
  TYPE("VK1WM",               TYPE_VK1)
  TYPE("VK8",                 TYPE_VK8)
  TYPE("VK8WM",               TYPE_VK8)
  TYPE("VK16",                TYPE_VK16)
  TYPE("VK16WM",              TYPE_VK16)
  TYPE("GR16_NOAX",           TYPE_Rv)
  TYPE("GR32_NOAX",           TYPE_Rv)
  TYPE("GR64_NOAX",           TYPE_R64)
  TYPE("vx32mem",             TYPE_M32)
  TYPE("vy32mem",             TYPE_M32)
  TYPE("vz32mem",             TYPE_M32)
  TYPE("vx64mem",             TYPE_M64)
  TYPE("vy64mem",             TYPE_M64)
  TYPE("vy64xmem",            TYPE_M64)
  TYPE("vz64mem",             TYPE_M64)
  errs() << "Unhandled type string " << s << "\n";
  llvm_unreachable("Unhandled type string");
}
#undef TYPE

#define ENCODING(str, encoding) if (s == str) return encoding;
OperandEncoding RecognizableInstr::immediateEncodingFromString
  (const std::string &s,
   bool hasOpSizePrefix) {
  if(!hasOpSizePrefix) {
    // For instructions without an OpSize prefix, a declared 16-bit register or
    // immediate encoding is special.
    ENCODING("i16imm",        ENCODING_IW)
  }
  ENCODING("i32i8imm",        ENCODING_IB)
  ENCODING("i16imm",          ENCODING_Iv)
  ENCODING("i16i8imm",        ENCODING_IB)
  ENCODING("i32imm",          ENCODING_Iv)
  ENCODING("i64i32imm",       ENCODING_ID)
  ENCODING("i64i8imm",        ENCODING_IB)
  ENCODING("i8imm",           ENCODING_IB)
  // This is not a typo.  Instructions like BLENDVPD put
  // register IDs in 8-bit immediates nowadays.
  ENCODING("FR32",            ENCODING_IB)
  ENCODING("FR64",            ENCODING_IB)
  ENCODING("VR128",           ENCODING_IB)
  ENCODING("VR256",           ENCODING_IB)
  ENCODING("FR32X",           ENCODING_IB)
  ENCODING("FR64X",           ENCODING_IB)
  ENCODING("VR128X",          ENCODING_IB)
  ENCODING("VR256X",          ENCODING_IB)
  ENCODING("VR512",           ENCODING_IB)
  errs() << "Unhandled immediate encoding " << s << "\n";
  llvm_unreachable("Unhandled immediate encoding");
}

OperandEncoding RecognizableInstr::rmRegisterEncodingFromString
  (const std::string &s,
   bool hasOpSizePrefix) {
  ENCODING("GR16",            ENCODING_RM)
  ENCODING("GR32",            ENCODING_RM)
  ENCODING("GR32orGR64",      ENCODING_RM)
  ENCODING("GR64",            ENCODING_RM)
  ENCODING("GR8",             ENCODING_RM)
  ENCODING("VR128",           ENCODING_RM)
  ENCODING("VR128X",          ENCODING_RM)
  ENCODING("FR64",            ENCODING_RM)
  ENCODING("FR32",            ENCODING_RM)
  ENCODING("FR64X",           ENCODING_RM)
  ENCODING("FR32X",           ENCODING_RM)
  ENCODING("VR256",           ENCODING_RM)
  ENCODING("VR256X",          ENCODING_RM)
  ENCODING("VR512",           ENCODING_RM)
  ENCODING("VK8",             ENCODING_RM)
  ENCODING("VK16",            ENCODING_RM)
  errs() << "Unhandled R/M register encoding " << s << "\n";
  llvm_unreachable("Unhandled R/M register encoding");
}

OperandEncoding RecognizableInstr::roRegisterEncodingFromString
  (const std::string &s,
   bool hasOpSizePrefix) {
  ENCODING("GR16",            ENCODING_REG)
  ENCODING("GR32",            ENCODING_REG)
  ENCODING("GR32orGR64",      ENCODING_REG)
  ENCODING("GR64",            ENCODING_REG)
  ENCODING("GR8",             ENCODING_REG)
  ENCODING("VR128",           ENCODING_REG)
  ENCODING("FR64",            ENCODING_REG)
  ENCODING("FR32",            ENCODING_REG)
  ENCODING("VR64",            ENCODING_REG)
  ENCODING("SEGMENT_REG",     ENCODING_REG)
  ENCODING("DEBUG_REG",       ENCODING_REG)
  ENCODING("CONTROL_REG",     ENCODING_REG)
  ENCODING("VR256",           ENCODING_REG)
  ENCODING("VR256X",          ENCODING_REG)
  ENCODING("VR128X",          ENCODING_REG)
  ENCODING("FR64X",           ENCODING_REG)
  ENCODING("FR32X",           ENCODING_REG)
  ENCODING("VR512",           ENCODING_REG)
  ENCODING("VK1",             ENCODING_REG)
  ENCODING("VK8",             ENCODING_REG)
  ENCODING("VK16",            ENCODING_REG)
  ENCODING("VK1WM",           ENCODING_REG)
  ENCODING("VK8WM",           ENCODING_REG)
  ENCODING("VK16WM",          ENCODING_REG)
  errs() << "Unhandled reg/opcode register encoding " << s << "\n";
  llvm_unreachable("Unhandled reg/opcode register encoding");
}

OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString
  (const std::string &s,
   bool hasOpSizePrefix) {
  ENCODING("GR32",            ENCODING_VVVV)
  ENCODING("GR64",            ENCODING_VVVV)
  ENCODING("FR32",            ENCODING_VVVV)
  ENCODING("FR64",            ENCODING_VVVV)
  ENCODING("VR128",           ENCODING_VVVV)
  ENCODING("VR256",           ENCODING_VVVV)
  ENCODING("FR32X",           ENCODING_VVVV)
  ENCODING("FR64X",           ENCODING_VVVV)
  ENCODING("VR128X",          ENCODING_VVVV)
  ENCODING("VR256X",          ENCODING_VVVV)
  ENCODING("VR512",           ENCODING_VVVV)
  ENCODING("VK1",             ENCODING_VVVV)
  ENCODING("VK8",             ENCODING_VVVV)
  ENCODING("VK16",            ENCODING_VVVV)
  errs() << "Unhandled VEX.vvvv register encoding " << s << "\n";
  llvm_unreachable("Unhandled VEX.vvvv register encoding");
}

OperandEncoding RecognizableInstr::writemaskRegisterEncodingFromString
  (const std::string &s,
   bool hasOpSizePrefix) {
  ENCODING("VK1WM",           ENCODING_WRITEMASK)
  ENCODING("VK8WM",           ENCODING_WRITEMASK)
  ENCODING("VK16WM",          ENCODING_WRITEMASK)
  errs() << "Unhandled mask register encoding " << s << "\n";
  llvm_unreachable("Unhandled mask register encoding");
}

OperandEncoding RecognizableInstr::memoryEncodingFromString
  (const std::string &s,
   bool hasOpSizePrefix) {
  ENCODING("i16mem",          ENCODING_RM)
  ENCODING("i32mem",          ENCODING_RM)
  ENCODING("i64mem",          ENCODING_RM)
  ENCODING("i8mem",           ENCODING_RM)
  ENCODING("ssmem",           ENCODING_RM)
  ENCODING("sdmem",           ENCODING_RM)
  ENCODING("f512mem",         ENCODING_RM)
  ENCODING("f64mem",          ENCODING_RM)
  ENCODING("f32mem",          ENCODING_RM)
  ENCODING("i128mem",         ENCODING_RM)
  ENCODING("i256mem",         ENCODING_RM)
  ENCODING("i512mem",         ENCODING_RM)
  ENCODING("f80mem",          ENCODING_RM)
  ENCODING("lea32mem",        ENCODING_RM)
  ENCODING("lea64_32mem",     ENCODING_RM)
  ENCODING("lea64mem",        ENCODING_RM)
  ENCODING("opaque32mem",     ENCODING_RM)
  ENCODING("opaque48mem",     ENCODING_RM)
  ENCODING("opaque80mem",     ENCODING_RM)
  ENCODING("opaque512mem",    ENCODING_RM)
  ENCODING("vx32mem",         ENCODING_RM)
  ENCODING("vy32mem",         ENCODING_RM)
  ENCODING("vz32mem",         ENCODING_RM)
  ENCODING("vx64mem",         ENCODING_RM)
  ENCODING("vy64mem",         ENCODING_RM)
  ENCODING("vy64xmem",        ENCODING_RM)
  ENCODING("vz64mem",         ENCODING_RM)
  errs() << "Unhandled memory encoding " << s << "\n";
  llvm_unreachable("Unhandled memory encoding");
}

OperandEncoding RecognizableInstr::relocationEncodingFromString
  (const std::string &s,
   bool hasOpSizePrefix) {
  if(!hasOpSizePrefix) {
    // For instructions without an OpSize prefix, a declared 16-bit register or
    // immediate encoding is special.
    ENCODING("i16imm",        ENCODING_IW)
  }
  ENCODING("i16imm",          ENCODING_Iv)
  ENCODING("i16i8imm",        ENCODING_IB)
  ENCODING("i32imm",          ENCODING_Iv)
  ENCODING("i32i8imm",        ENCODING_IB)
  ENCODING("i64i32imm",       ENCODING_ID)
  ENCODING("i64i8imm",        ENCODING_IB)
  ENCODING("i8imm",           ENCODING_IB)
  ENCODING("i64i32imm_pcrel", ENCODING_ID)
  ENCODING("i16imm_pcrel",    ENCODING_IW)
  ENCODING("i32imm_pcrel",    ENCODING_ID)
  ENCODING("brtarget",        ENCODING_Iv)
  ENCODING("brtarget8",       ENCODING_IB)
  ENCODING("i64imm",          ENCODING_IO)
  ENCODING("offset8",         ENCODING_Ia)
  ENCODING("offset16",        ENCODING_Ia)
  ENCODING("offset32",        ENCODING_Ia)
  ENCODING("offset64",        ENCODING_Ia)
  errs() << "Unhandled relocation encoding " << s << "\n";
  llvm_unreachable("Unhandled relocation encoding");
}

OperandEncoding RecognizableInstr::opcodeModifierEncodingFromString
  (const std::string &s,
   bool hasOpSizePrefix) {
  ENCODING("RST",             ENCODING_I)
  ENCODING("GR32",            ENCODING_Rv)
  ENCODING("GR64",            ENCODING_RO)
  ENCODING("GR16",            ENCODING_Rv)
  ENCODING("GR8",             ENCODING_RB)
  ENCODING("GR16_NOAX",       ENCODING_Rv)
  ENCODING("GR32_NOAX",       ENCODING_Rv)
  ENCODING("GR64_NOAX",       ENCODING_RO)
  errs() << "Unhandled opcode modifier encoding " << s << "\n";
  llvm_unreachable("Unhandled opcode modifier encoding");
}
#undef ENCODING