//===- X86RecognizableInstr.cpp - Disassembler instruction spec --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is part of the X86 Disassembler Emitter.
// It contains the implementation of a single recognizable instruction.
// Documentation for the disassembler emitter in general can be found in
// X86DisasemblerEmitter.h.
//
//===----------------------------------------------------------------------===//
#include "X86DisassemblerShared.h"
#include "X86RecognizableInstr.h"
#include "X86ModRMFilters.h"
#include "llvm/Support/ErrorHandling.h"
#include <string>
using namespace llvm;
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
enum {
Pseudo = 0,
RawFrm = 1,
AddRegFrm = 2,
MRMDestReg = 3,
MRMDestMem = 4,
MRMSrcReg = 5,
MRMSrcMem = 6,
MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19,
MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23,
MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,
MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31,
MRMInitReg = 32
};
enum {
TB = 1,
REP = 2,
D8 = 3, D9 = 4, DA = 5, DB = 6,
DC = 7, DD = 8, DE = 9, DF = 10,
XD = 11, XS = 12,
T8 = 13, P_TA = 14,
P_0F_AE = 16, P_0F_01 = 17
};
}
#define ONE_BYTE_EXTENSION_TABLES \
EXTENSION_TABLE(80) \
EXTENSION_TABLE(81) \
EXTENSION_TABLE(82) \
EXTENSION_TABLE(83) \
EXTENSION_TABLE(8f) \
EXTENSION_TABLE(c0) \
EXTENSION_TABLE(c1) \
EXTENSION_TABLE(c6) \
EXTENSION_TABLE(c7) \
EXTENSION_TABLE(d0) \
EXTENSION_TABLE(d1) \
EXTENSION_TABLE(d2) \
EXTENSION_TABLE(d3) \
EXTENSION_TABLE(f6) \
EXTENSION_TABLE(f7) \
EXTENSION_TABLE(fe) \
EXTENSION_TABLE(ff)
#define TWO_BYTE_EXTENSION_TABLES \
EXTENSION_TABLE(00) \
EXTENSION_TABLE(01) \
EXTENSION_TABLE(18) \
EXTENSION_TABLE(71) \
EXTENSION_TABLE(72) \
EXTENSION_TABLE(73) \
EXTENSION_TABLE(ae) \
EXTENSION_TABLE(b9) \
EXTENSION_TABLE(ba) \
EXTENSION_TABLE(c7)
#define TWO_BYTE_FULL_EXTENSION_TABLES \
EXTENSION_TABLE(01)
using namespace X86Disassembler;
/// needsModRMForDecode - Indicates whether a particular instruction requires a
/// ModR/M byte for the instruction to be properly decoded. For example, a
/// MRMDestReg instruction needs the Mod field in the ModR/M byte to be set to
/// 0b11.
///
/// @param form - The form of the instruction.
/// @return - true if the form implies that a ModR/M byte is required, false
/// otherwise.
static bool needsModRMForDecode(uint8_t form) {
if (form == X86Local::MRMDestReg ||
form == X86Local::MRMDestMem ||
form == X86Local::MRMSrcReg ||
form == X86Local::MRMSrcMem ||
(form >= X86Local::MRM0r && form <= X86Local::MRM7r) ||
(form >= X86Local::MRM0m && form <= X86Local::MRM7m))
return true;
else
return false;
}
/// isRegFormat - Indicates whether a particular form requires the Mod field of
/// the ModR/M byte to be 0b11.
///
/// @param form - The form of the instruction.
/// @return - true if the form implies that Mod must be 0b11, false
/// otherwise.
static bool isRegFormat(uint8_t form) {
if (form == X86Local::MRMDestReg ||
form == X86Local::MRMSrcReg ||
(form >= X86Local::MRM0r && form <= X86Local::MRM7r))
return true;
else
return false;
}
/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.
/// Useful for switch statements and the like.
///
/// @param init - A reference to the BitsInit to be decoded.
/// @return - The field, with the first bit in the BitsInit as the lowest
/// order bit.
static uint8_t byteFromBitsInit(BitsInit &init) {
int width = init.getNumBits();
assert(width <= 8 && "Field is too large for uint8_t!");
int index;
uint8_t mask = 0x01;
uint8_t ret = 0;
for (index = 0; index < width; index++) {
if (static_cast<BitInit*>(init.getBit(index))->getValue())
ret |= mask;
mask <<= 1;
}
return ret;
}
/// byteFromRec - Extract a value at most 8 bits in with from a Record given the
/// name of the field.
///
/// @param rec - The record from which to extract the value.
/// @param name - The name of the field in the record.
/// @return - The field, as translated by byteFromBitsInit().
static uint8_t byteFromRec(const Record* rec, const std::string &name) {
BitsInit* bits = rec->getValueAsBitsInit(name);
return byteFromBitsInit(*bits);
}
RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
const CodeGenInstruction &insn,