mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
[x86] Allow address-size overrides for STOS[BWLQ] (PR9385)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199804 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
db9fa461d7
commit
ccbfd5b18a
@ -552,6 +552,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
X86Operand *DefaultMemSIOperand(SMLoc Loc);
|
X86Operand *DefaultMemSIOperand(SMLoc Loc);
|
||||||
|
X86Operand *DefaultMemDIOperand(SMLoc Loc);
|
||||||
X86Operand *ParseOperand();
|
X86Operand *ParseOperand();
|
||||||
X86Operand *ParseATTOperand();
|
X86Operand *ParseATTOperand();
|
||||||
X86Operand *ParseIntelOperand();
|
X86Operand *ParseIntelOperand();
|
||||||
@ -942,6 +943,26 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
return isMem64() && isSrcIdx();
|
return isMem64() && isSrcIdx();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isDstIdx() const {
|
||||||
|
return !getMemIndexReg() && getMemScale() == 1 &&
|
||||||
|
(getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
|
||||||
|
(getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
|
||||||
|
getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
|
||||||
|
cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
|
||||||
|
}
|
||||||
|
bool isDstIdx8() const {
|
||||||
|
return isMem8() && isDstIdx();
|
||||||
|
}
|
||||||
|
bool isDstIdx16() const {
|
||||||
|
return isMem16() && isDstIdx();
|
||||||
|
}
|
||||||
|
bool isDstIdx32() const {
|
||||||
|
return isMem32() && isDstIdx();
|
||||||
|
}
|
||||||
|
bool isDstIdx64() const {
|
||||||
|
return isMem64() && isDstIdx();
|
||||||
|
}
|
||||||
|
|
||||||
bool isMemOffs8() const {
|
bool isMemOffs8() const {
|
||||||
return Kind == Memory && !getMemBaseReg() &&
|
return Kind == Memory && !getMemBaseReg() &&
|
||||||
!getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 8);
|
!getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 8);
|
||||||
@ -1039,6 +1060,10 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
|
Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
|
||||||
Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
|
Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
|
||||||
}
|
}
|
||||||
|
void addDstIdxOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert((N == 1) && "Invalid number of operands!");
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
|
||||||
|
}
|
||||||
|
|
||||||
void addMemOffsOperands(MCInst &Inst, unsigned N) const {
|
void addMemOffsOperands(MCInst &Inst, unsigned N) const {
|
||||||
assert((N == 2) && "Invalid number of operands!");
|
assert((N == 2) && "Invalid number of operands!");
|
||||||
@ -1264,6 +1289,14 @@ X86Operand *X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
|
|||||||
/*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0);
|
/*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X86Operand *X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
|
||||||
|
unsigned basereg =
|
||||||
|
is64BitMode() ? X86::RDI : (is32BitMode() ? X86::EDI : X86::DI);
|
||||||
|
const MCExpr *Disp = MCConstantExpr::Create(0, getContext());
|
||||||
|
return X86Operand::CreateMem(/*SegReg=*/0, Disp, /*BaseReg=*/basereg,
|
||||||
|
/*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0);
|
||||||
|
}
|
||||||
|
|
||||||
X86Operand *X86AsmParser::ParseOperand() {
|
X86Operand *X86AsmParser::ParseOperand() {
|
||||||
if (isParsingIntelSyntax())
|
if (isParsingIntelSyntax())
|
||||||
return ParseIntelOperand();
|
return ParseIntelOperand();
|
||||||
@ -2320,36 +2353,13 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
|
|||||||
Name == "lodsl" || Name == "lodsd" || Name == "lodsq"))
|
Name == "lodsl" || Name == "lodsd" || Name == "lodsq"))
|
||||||
Operands.push_back(DefaultMemSIOperand(NameLoc));
|
Operands.push_back(DefaultMemSIOperand(NameLoc));
|
||||||
|
|
||||||
// Transform "stos[bwl] {%al,%ax,%eax,%rax},%es:(%edi)" into "stos[bwl]"
|
// Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate
|
||||||
if (Name.startswith("stos") && Operands.size() == 3 &&
|
// values of $DIREG according to the mode. It would be nice if this
|
||||||
|
// could be achieved with InstAlias in the tables.
|
||||||
|
if (Name.startswith("stos") && Operands.size() == 1 &&
|
||||||
(Name == "stos" || Name == "stosb" || Name == "stosw" ||
|
(Name == "stos" || Name == "stosb" || Name == "stosw" ||
|
||||||
Name == "stosl" || (is64BitMode() && Name == "stosq"))) {
|
Name == "stosl" || Name == "stosd" || Name == "stosq"))
|
||||||
X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);
|
Operands.push_back(DefaultMemDIOperand(NameLoc));
|
||||||
X86Operand *Op2 = static_cast<X86Operand*>(Operands[2]);
|
|
||||||
if (isDstOp(*Op2) && Op1->isReg()) {
|
|
||||||
const char *ins;
|
|
||||||
unsigned reg = Op1->getReg();
|
|
||||||
bool isStos = Name == "stos";
|
|
||||||
if (reg == X86::AL && (isStos || Name == "stosb"))
|
|
||||||
ins = "stosb";
|
|
||||||
else if (reg == X86::AX && (isStos || Name == "stosw"))
|
|
||||||
ins = "stosw";
|
|
||||||
else if (reg == X86::EAX && (isStos || Name == "stosl"))
|
|
||||||
ins = "stosl";
|
|
||||||
else if (reg == X86::RAX && (isStos || Name == "stosq"))
|
|
||||||
ins = "stosq";
|
|
||||||
else
|
|
||||||
ins = NULL;
|
|
||||||
if (ins != NULL) {
|
|
||||||
Operands.pop_back();
|
|
||||||
Operands.pop_back();
|
|
||||||
delete Op1;
|
|
||||||
delete Op2;
|
|
||||||
if (Name != ins)
|
|
||||||
static_cast<X86Operand*>(Operands[0])->setTokenValue(ins);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to
|
// FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to
|
||||||
// "shift <op>".
|
// "shift <op>".
|
||||||
|
@ -256,6 +256,26 @@ static bool translateSrcIndex(MCInst &mcInst, InternalInstruction &insn) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// translateDstIndex - Appends a destination index operand to an MCInst.
|
||||||
|
///
|
||||||
|
/// @param mcInst - The MCInst to append to.
|
||||||
|
/// @param operand - The operand, as stored in the descriptor table.
|
||||||
|
/// @param insn - The internal instruction.
|
||||||
|
|
||||||
|
static bool translateDstIndex(MCInst &mcInst, InternalInstruction &insn) {
|
||||||
|
unsigned baseRegNo;
|
||||||
|
|
||||||
|
if (insn.mode == MODE_64BIT)
|
||||||
|
baseRegNo = insn.prefixPresent[0x67] ? X86::EDI : X86::RDI;
|
||||||
|
else if (insn.mode == MODE_32BIT)
|
||||||
|
baseRegNo = insn.prefixPresent[0x67] ? X86::DI : X86::EDI;
|
||||||
|
else if (insn.mode == MODE_16BIT)
|
||||||
|
baseRegNo = insn.prefixPresent[0x67] ? X86::EDI : X86::DI;
|
||||||
|
MCOperand baseReg = MCOperand::CreateReg(baseRegNo);
|
||||||
|
mcInst.addOperand(baseReg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// translateImmediate - Appends an immediate operand to an MCInst.
|
/// translateImmediate - Appends an immediate operand to an MCInst.
|
||||||
///
|
///
|
||||||
/// @param mcInst - The MCInst to append to.
|
/// @param mcInst - The MCInst to append to.
|
||||||
@ -719,6 +739,8 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
|
|||||||
return false;
|
return false;
|
||||||
case ENCODING_SI:
|
case ENCODING_SI:
|
||||||
return translateSrcIndex(mcInst, insn);
|
return translateSrcIndex(mcInst, insn);
|
||||||
|
case ENCODING_DI:
|
||||||
|
return translateDstIndex(mcInst, insn);
|
||||||
case ENCODING_RB:
|
case ENCODING_RB:
|
||||||
case ENCODING_RW:
|
case ENCODING_RW:
|
||||||
case ENCODING_RD:
|
case ENCODING_RD:
|
||||||
|
@ -1683,6 +1683,7 @@ static int readOperands(struct InternalInstruction* insn) {
|
|||||||
switch (x86OperandSets[insn->spec->operands][index].encoding) {
|
switch (x86OperandSets[insn->spec->operands][index].encoding) {
|
||||||
case ENCODING_NONE:
|
case ENCODING_NONE:
|
||||||
case ENCODING_SI:
|
case ENCODING_SI:
|
||||||
|
case ENCODING_DI:
|
||||||
break;
|
break;
|
||||||
case ENCODING_REG:
|
case ENCODING_REG:
|
||||||
case ENCODING_RM:
|
case ENCODING_RM:
|
||||||
|
@ -410,7 +410,8 @@ struct ContextDecision {
|
|||||||
"opcode byte") \
|
"opcode byte") \
|
||||||
ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \
|
ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \
|
||||||
"in type") \
|
"in type") \
|
||||||
ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix")
|
ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix") \
|
||||||
|
ENUM_ENTRY(ENCODING_DI, "Destination index; encoded in prefixes")
|
||||||
|
|
||||||
#define ENUM_ENTRY(n, d) n,
|
#define ENUM_ENTRY(n, d) n,
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -465,6 +466,10 @@ struct ContextDecision {
|
|||||||
ENUM_ENTRY(TYPE_SRCIDX16, "2-byte memory at source index") \
|
ENUM_ENTRY(TYPE_SRCIDX16, "2-byte memory at source index") \
|
||||||
ENUM_ENTRY(TYPE_SRCIDX32, "4-byte memory at source index") \
|
ENUM_ENTRY(TYPE_SRCIDX32, "4-byte memory at source index") \
|
||||||
ENUM_ENTRY(TYPE_SRCIDX64, "8-byte memory at source index") \
|
ENUM_ENTRY(TYPE_SRCIDX64, "8-byte memory at source index") \
|
||||||
|
ENUM_ENTRY(TYPE_DSTIDX8, "1-byte memory at destination index") \
|
||||||
|
ENUM_ENTRY(TYPE_DSTIDX16, "2-byte memory at destination index") \
|
||||||
|
ENUM_ENTRY(TYPE_DSTIDX32, "4-byte memory at destination index") \
|
||||||
|
ENUM_ENTRY(TYPE_DSTIDX64, "8-byte memory at destination index") \
|
||||||
ENUM_ENTRY(TYPE_MOFFS8, "1-byte memory offset (relative to segment " \
|
ENUM_ENTRY(TYPE_MOFFS8, "1-byte memory offset (relative to segment " \
|
||||||
"base)") \
|
"base)") \
|
||||||
ENUM_ENTRY(TYPE_MOFFS16, "2-byte") \
|
ENUM_ENTRY(TYPE_MOFFS16, "2-byte") \
|
||||||
|
@ -245,6 +245,17 @@ void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
|
|||||||
O << markup(">");
|
O << markup(">");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
|
||||||
|
raw_ostream &O) {
|
||||||
|
O << markup("<mem:");
|
||||||
|
|
||||||
|
O << "%es:(";
|
||||||
|
printOperand(MI, Op, O);
|
||||||
|
O << ")";
|
||||||
|
|
||||||
|
O << markup(">");
|
||||||
|
}
|
||||||
|
|
||||||
void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
|
void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
|
||||||
raw_ostream &O) {
|
raw_ostream &O) {
|
||||||
const MCOperand &DispSpec = MI->getOperand(Op);
|
const MCOperand &DispSpec = MI->getOperand(Op);
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
void printAVXCC(const MCInst *MI, unsigned Op, raw_ostream &OS);
|
void printAVXCC(const MCInst *MI, unsigned Op, raw_ostream &OS);
|
||||||
void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
|
void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
|
||||||
void printSrcIdx(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
|
void printSrcIdx(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
|
||||||
|
void printDstIdx(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
|
||||||
void printMemOffset(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
|
void printMemOffset(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
|
||||||
void printRoundingControl(const MCInst *MI, unsigned Op, raw_ostream &OS);
|
void printRoundingControl(const MCInst *MI, unsigned Op, raw_ostream &OS);
|
||||||
|
|
||||||
@ -102,6 +103,18 @@ public:
|
|||||||
void printSrcIdx64(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
void printSrcIdx64(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
printSrcIdx(MI, OpNo, O);
|
printSrcIdx(MI, OpNo, O);
|
||||||
}
|
}
|
||||||
|
void printDstIdx8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
|
printDstIdx(MI, OpNo, O);
|
||||||
|
}
|
||||||
|
void printDstIdx16(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
|
printDstIdx(MI, OpNo, O);
|
||||||
|
}
|
||||||
|
void printDstIdx32(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
|
printDstIdx(MI, OpNo, O);
|
||||||
|
}
|
||||||
|
void printDstIdx64(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
|
printDstIdx(MI, OpNo, O);
|
||||||
|
}
|
||||||
void printMemOffs8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
void printMemOffs8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
printMemOffset(MI, OpNo, O);
|
printMemOffset(MI, OpNo, O);
|
||||||
}
|
}
|
||||||
|
@ -226,6 +226,14 @@ void X86IntelInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
|
|||||||
O << ']';
|
O << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void X86IntelInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
|
||||||
|
raw_ostream &O) {
|
||||||
|
// DI accesses are always ES-based.
|
||||||
|
O << "es:[";
|
||||||
|
printOperand(MI, Op, O);
|
||||||
|
O << ']';
|
||||||
|
}
|
||||||
|
|
||||||
void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
|
void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
|
||||||
raw_ostream &O) {
|
raw_ostream &O) {
|
||||||
const MCOperand &DispSpec = MI->getOperand(Op);
|
const MCOperand &DispSpec = MI->getOperand(Op);
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||||
void printMemOffset(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
void printMemOffset(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||||
void printSrcIdx(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
void printSrcIdx(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||||
|
void printDstIdx(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||||
void printRoundingControl(const MCInst *MI, unsigned Op, raw_ostream &OS);
|
void printRoundingControl(const MCInst *MI, unsigned Op, raw_ostream &OS);
|
||||||
|
|
||||||
void printopaquemem(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
void printopaquemem(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
@ -118,6 +119,22 @@ public:
|
|||||||
O << "qword ptr ";
|
O << "qword ptr ";
|
||||||
printSrcIdx(MI, OpNo, O);
|
printSrcIdx(MI, OpNo, O);
|
||||||
}
|
}
|
||||||
|
void printDstIdx8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
|
O << "byte ptr ";
|
||||||
|
printDstIdx(MI, OpNo, O);
|
||||||
|
}
|
||||||
|
void printDstIdx16(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
|
O << "word ptr ";
|
||||||
|
printDstIdx(MI, OpNo, O);
|
||||||
|
}
|
||||||
|
void printDstIdx32(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
|
O << "dword ptr ";
|
||||||
|
printDstIdx(MI, OpNo, O);
|
||||||
|
}
|
||||||
|
void printDstIdx64(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
|
O << "qword ptr ";
|
||||||
|
printDstIdx(MI, OpNo, O);
|
||||||
|
}
|
||||||
void printMemOffs8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
void printMemOffs8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {
|
||||||
O << "byte ptr ";
|
O << "byte ptr ";
|
||||||
printMemOffset(MI, OpNo, O);
|
printMemOffset(MI, OpNo, O);
|
||||||
|
@ -263,6 +263,10 @@ namespace X86II {
|
|||||||
/// register SI/ESI/RSI with a possible segment override.
|
/// register SI/ESI/RSI with a possible segment override.
|
||||||
RawFrmSrc = 8,
|
RawFrmSrc = 8,
|
||||||
|
|
||||||
|
/// RawFrmDst - This form is for instructions that use the destination index
|
||||||
|
/// register DI/EDI/ESI.
|
||||||
|
RawFrmDst = 9,
|
||||||
|
|
||||||
/// MRM[0-7][rm] - These forms are used to represent instructions that use
|
/// MRM[0-7][rm] - These forms are used to represent instructions that use
|
||||||
/// a Mod/RM byte, and use the middle field to hold extended opcode
|
/// a Mod/RM byte, and use the middle field to hold extended opcode
|
||||||
/// information. In the intel manual these are represented as /0, /1, ...
|
/// information. In the intel manual these are represented as /0, /1, ...
|
||||||
@ -617,6 +621,7 @@ namespace X86II {
|
|||||||
case X86II::RawFrmImm16:
|
case X86II::RawFrmImm16:
|
||||||
case X86II::RawFrmMemOffs:
|
case X86II::RawFrmMemOffs:
|
||||||
case X86II::RawFrmSrc:
|
case X86II::RawFrmSrc:
|
||||||
|
case X86II::RawFrmDst:
|
||||||
return -1;
|
return -1;
|
||||||
case X86II::MRMDestMem:
|
case X86II::MRMDestMem:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1330,6 +1330,16 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
|||||||
EmitByte(BaseOpcode, CurByte, OS);
|
EmitByte(BaseOpcode, CurByte, OS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case X86II::RawFrmDst: {
|
||||||
|
unsigned siReg = MI.getOperand(0).getReg();
|
||||||
|
// Emit OpSize prefix as needed.
|
||||||
|
if ((!is32BitMode() && siReg == X86::EDI) ||
|
||||||
|
(is32BitMode() && siReg == X86::DI))
|
||||||
|
EmitByte(0x67, CurByte, OS);
|
||||||
|
++CurOp; // Consume operand.
|
||||||
|
EmitByte(BaseOpcode, CurByte, OS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case X86II::RawFrm:
|
case X86II::RawFrm:
|
||||||
EmitByte(BaseOpcode, CurByte, OS);
|
EmitByte(BaseOpcode, CurByte, OS);
|
||||||
break;
|
break;
|
||||||
|
@ -22,7 +22,7 @@ def Pseudo : Format<0>; def RawFrm : Format<1>;
|
|||||||
def AddRegFrm : Format<2>; def MRMDestReg : Format<3>;
|
def AddRegFrm : Format<2>; def MRMDestReg : Format<3>;
|
||||||
def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>;
|
def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>;
|
||||||
def MRMSrcMem : Format<6>; def RawFrmMemOffs : Format<7>;
|
def MRMSrcMem : Format<6>; def RawFrmMemOffs : Format<7>;
|
||||||
def RawFrmSrc : Format<8>;
|
def RawFrmSrc : Format<8>; def RawFrmDst : Format<9>;
|
||||||
def MRM0r : Format<16>; def MRM1r : Format<17>; def MRM2r : Format<18>;
|
def MRM0r : Format<16>; def MRM1r : Format<17>; def MRM2r : Format<18>;
|
||||||
def MRM3r : Format<19>; def MRM4r : Format<20>; def MRM5r : Format<21>;
|
def MRM3r : Format<19>; def MRM4r : Format<20>; def MRM5r : Format<21>;
|
||||||
def MRM6r : Format<22>; def MRM7r : Format<23>;
|
def MRM6r : Format<22>; def MRM7r : Format<23>;
|
||||||
|
@ -465,6 +465,26 @@ def X86SrcIdx64Operand : AsmOperandClass {
|
|||||||
let RenderMethod = "addSrcIdxOperands";
|
let RenderMethod = "addSrcIdxOperands";
|
||||||
let SuperClasses = [X86Mem64AsmOperand];
|
let SuperClasses = [X86Mem64AsmOperand];
|
||||||
}
|
}
|
||||||
|
def X86DstIdx8Operand : AsmOperandClass {
|
||||||
|
let Name = "DstIdx8";
|
||||||
|
let RenderMethod = "addDstIdxOperands";
|
||||||
|
let SuperClasses = [X86Mem8AsmOperand];
|
||||||
|
}
|
||||||
|
def X86DstIdx16Operand : AsmOperandClass {
|
||||||
|
let Name = "DstIdx16";
|
||||||
|
let RenderMethod = "addDstIdxOperands";
|
||||||
|
let SuperClasses = [X86Mem16AsmOperand];
|
||||||
|
}
|
||||||
|
def X86DstIdx32Operand : AsmOperandClass {
|
||||||
|
let Name = "DstIdx32";
|
||||||
|
let RenderMethod = "addDstIdxOperands";
|
||||||
|
let SuperClasses = [X86Mem32AsmOperand];
|
||||||
|
}
|
||||||
|
def X86DstIdx64Operand : AsmOperandClass {
|
||||||
|
let Name = "DstIdx64";
|
||||||
|
let RenderMethod = "addDstIdxOperands";
|
||||||
|
let SuperClasses = [X86Mem64AsmOperand];
|
||||||
|
}
|
||||||
def X86MemOffs8AsmOperand : AsmOperandClass {
|
def X86MemOffs8AsmOperand : AsmOperandClass {
|
||||||
let Name = "MemOffs8";
|
let Name = "MemOffs8";
|
||||||
let RenderMethod = "addMemOffsOperands";
|
let RenderMethod = "addMemOffsOperands";
|
||||||
@ -502,6 +522,22 @@ def srcidx64 : Operand<iPTR> {
|
|||||||
let ParserMatchClass = X86SrcIdx64Operand;
|
let ParserMatchClass = X86SrcIdx64Operand;
|
||||||
let MIOperandInfo = (ops ptr_rc, i8imm);
|
let MIOperandInfo = (ops ptr_rc, i8imm);
|
||||||
let PrintMethod = "printSrcIdx64"; }
|
let PrintMethod = "printSrcIdx64"; }
|
||||||
|
def dstidx8 : Operand<iPTR> {
|
||||||
|
let ParserMatchClass = X86DstIdx8Operand;
|
||||||
|
let MIOperandInfo = (ops ptr_rc);
|
||||||
|
let PrintMethod = "printDstIdx8"; }
|
||||||
|
def dstidx16 : Operand<iPTR> {
|
||||||
|
let ParserMatchClass = X86DstIdx16Operand;
|
||||||
|
let MIOperandInfo = (ops ptr_rc);
|
||||||
|
let PrintMethod = "printDstIdx16"; }
|
||||||
|
def dstidx32 : Operand<iPTR> {
|
||||||
|
let ParserMatchClass = X86DstIdx32Operand;
|
||||||
|
let MIOperandInfo = (ops ptr_rc);
|
||||||
|
let PrintMethod = "printDstIdx32"; }
|
||||||
|
def dstidx64 : Operand<iPTR> {
|
||||||
|
let ParserMatchClass = X86DstIdx64Operand;
|
||||||
|
let MIOperandInfo = (ops ptr_rc);
|
||||||
|
let PrintMethod = "printDstIdx64"; }
|
||||||
def offset8 : Operand<iPTR> {
|
def offset8 : Operand<iPTR> {
|
||||||
let ParserMatchClass = X86MemOffs8AsmOperand;
|
let ParserMatchClass = X86MemOffs8AsmOperand;
|
||||||
let MIOperandInfo = (ops i64imm, i8imm);
|
let MIOperandInfo = (ops i64imm, i8imm);
|
||||||
@ -1109,13 +1145,17 @@ def MOVSQ : RI<0xA5, RawFrm, (outs), (ins), "movsq", [], IIC_MOVS>;
|
|||||||
|
|
||||||
// These uses the DF flag in the EFLAGS register to inc or dec EDI and ESI
|
// These uses the DF flag in the EFLAGS register to inc or dec EDI and ESI
|
||||||
let Defs = [EDI], Uses = [AL,EDI,EFLAGS] in
|
let Defs = [EDI], Uses = [AL,EDI,EFLAGS] in
|
||||||
def STOSB : I<0xAA, RawFrm, (outs), (ins), "stosb", [], IIC_STOS>;
|
def STOSB : I<0xAA, RawFrmDst, (outs dstidx8:$dst), (ins),
|
||||||
|
"stosb\t{%al, $dst|$dst, al}", [], IIC_STOS>;
|
||||||
let Defs = [EDI], Uses = [AX,EDI,EFLAGS] in
|
let Defs = [EDI], Uses = [AX,EDI,EFLAGS] in
|
||||||
def STOSW : I<0xAB, RawFrm, (outs), (ins), "stosw", [], IIC_STOS>, OpSize;
|
def STOSW : I<0xAB, RawFrmDst, (outs dstidx16:$dst), (ins),
|
||||||
|
"stosw\t{%ax, $dst|$dst, ax}", [], IIC_STOS>, OpSize;
|
||||||
let Defs = [EDI], Uses = [EAX,EDI,EFLAGS] in
|
let Defs = [EDI], Uses = [EAX,EDI,EFLAGS] in
|
||||||
def STOSL : I<0xAB, RawFrm, (outs), (ins), "stos{l|d}", [], IIC_STOS>, OpSize16;
|
def STOSL : I<0xAB, RawFrmDst, (outs dstidx32:$dst), (ins),
|
||||||
|
"stos{l|d}\t{%eax, $dst|$dst, eax}", [], IIC_STOS>, OpSize16;
|
||||||
let Defs = [RCX,RDI], Uses = [RAX,RCX,RDI,EFLAGS] in
|
let Defs = [RCX,RDI], Uses = [RAX,RCX,RDI,EFLAGS] in
|
||||||
def STOSQ : RI<0xAB, RawFrm, (outs), (ins), "stosq", [], IIC_STOS>;
|
def STOSQ : RI<0xAB, RawFrmDst, (outs dstidx64:$dst), (ins),
|
||||||
|
"stosq\t{%rax, $dst|$dst, rax}", [], IIC_STOS>;
|
||||||
|
|
||||||
def SCAS8 : I<0xAE, RawFrm, (outs), (ins), "scasb", [], IIC_SCAS>;
|
def SCAS8 : I<0xAE, RawFrm, (outs), (ins), "scasb", [], IIC_SCAS>;
|
||||||
def SCAS16 : I<0xAF, RawFrm, (outs), (ins), "scasw", [], IIC_SCAS>, OpSize;
|
def SCAS16 : I<0xAF, RawFrm, (outs), (ins), "scasw", [], IIC_SCAS>, OpSize;
|
||||||
@ -2380,6 +2420,18 @@ def : InstAlias<"lods {$src, %ax|ax, $src}", (LODSW srcidx16:$src), 0>;
|
|||||||
def : InstAlias<"lods {$src, %eax|eax, $src}", (LODSL srcidx32:$src), 0>;
|
def : InstAlias<"lods {$src, %eax|eax, $src}", (LODSL srcidx32:$src), 0>;
|
||||||
def : InstAlias<"lods {$src, %rax|rax, $src}", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>;
|
def : InstAlias<"lods {$src, %rax|rax, $src}", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>;
|
||||||
|
|
||||||
|
// stos aliases. Accept the source being omitted because it's implicit in
|
||||||
|
// the mnemonic, or the mnemonic suffix being omitted because it's implicit
|
||||||
|
// in the source.
|
||||||
|
def : InstAlias<"stosb $dst", (STOSB dstidx8:$dst), 0>;
|
||||||
|
def : InstAlias<"stosw $dst", (STOSW dstidx16:$dst), 0>;
|
||||||
|
def : InstAlias<"stos{l|d} $dst", (STOSL dstidx32:$dst), 0>;
|
||||||
|
def : InstAlias<"stosq $dst", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>;
|
||||||
|
def : InstAlias<"stos {%al, $dst|$dst, al}", (STOSB dstidx8:$dst), 0>;
|
||||||
|
def : InstAlias<"stos {%ax, $dst|$dst, ax}", (STOSW dstidx16:$dst), 0>;
|
||||||
|
def : InstAlias<"stos {%eax, $dst|$dst, eax}", (STOSL dstidx32:$dst), 0>;
|
||||||
|
def : InstAlias<"stos {%rax, $dst|$dst, rax}", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>;
|
||||||
|
|
||||||
// div and idiv aliases for explicit A register.
|
// div and idiv aliases for explicit A register.
|
||||||
def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8r GR8 :$src)>;
|
def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8r GR8 :$src)>;
|
||||||
def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16r GR16:$src)>;
|
def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16r GR16:$src)>;
|
||||||
|
@ -44,3 +44,33 @@ lods (%esi), %ax
|
|||||||
// 64: lodsw (%esi), %ax # encoding: [0x66,0x67,0xad]
|
// 64: lodsw (%esi), %ax # encoding: [0x66,0x67,0xad]
|
||||||
// 32: lodsw (%esi), %ax # encoding: [0x66,0xad]
|
// 32: lodsw (%esi), %ax # encoding: [0x66,0xad]
|
||||||
// 16: lodsw (%esi), %ax # encoding: [0x67,0xad]
|
// 16: lodsw (%esi), %ax # encoding: [0x67,0xad]
|
||||||
|
|
||||||
|
stosw
|
||||||
|
// 64: stosw %ax, %es:(%rdi) # encoding: [0x66,0xab]
|
||||||
|
// 32: stosw %ax, %es:(%edi) # encoding: [0x66,0xab]
|
||||||
|
// 16: stosw %ax, %es:(%di) # encoding: [0xab]
|
||||||
|
|
||||||
|
stos %eax, (%edi)
|
||||||
|
// 64: stosl %eax, %es:(%edi) # encoding: [0x67,0xab]
|
||||||
|
// 32: stosl %eax, %es:(%edi) # encoding: [0xab]
|
||||||
|
// 16: stosl %eax, %es:(%edi) # encoding: [0x66,0x67,0xab]
|
||||||
|
|
||||||
|
stosb %al, %fs:(%edi)
|
||||||
|
// ERR64: invalid operand for instruction
|
||||||
|
// ERR32: invalid operand for instruction
|
||||||
|
// ERR16: invalid operand for instruction
|
||||||
|
|
||||||
|
stosb %al, %es:(%edi)
|
||||||
|
// 64: stosb %al, %es:(%edi) # encoding: [0x67,0xaa]
|
||||||
|
// 32: stosb %al, %es:(%edi) # encoding: [0xaa]
|
||||||
|
// 16: stosb %al, %es:(%edi) # encoding: [0x67,0xaa]
|
||||||
|
|
||||||
|
stosq
|
||||||
|
// 64: stosq %rax, %es:(%rdi) # encoding: [0x48,0xab]
|
||||||
|
// ERR32: 64-bit
|
||||||
|
// ERR16: 64-bit
|
||||||
|
|
||||||
|
stos %rax, (%edi)
|
||||||
|
// 64: stosq %rax, %es:(%edi) # encoding: [0x48,0x67,0xab]
|
||||||
|
// ERR32: only available in 64-bit mode
|
||||||
|
// ERR16: only available in 64-bit mode
|
||||||
|
@ -878,21 +878,21 @@ pshufw $90, %mm4, %mm0
|
|||||||
lods %ds:(%si), %eax
|
lods %ds:(%si), %eax
|
||||||
lods (%si), %eax
|
lods (%si), %eax
|
||||||
|
|
||||||
// CHECK: stosb # encoding: [0xaa]
|
// CHECK: stosb %al, %es:(%di) # encoding: [0xaa]
|
||||||
// CHECK: stosb
|
// CHECK: stosb
|
||||||
// CHECK: stosb
|
// CHECK: stosb
|
||||||
stosb
|
stosb
|
||||||
stosb %al, %es:(%di)
|
stosb %al, %es:(%di)
|
||||||
stos %al, %es:(%di)
|
stos %al, %es:(%di)
|
||||||
|
|
||||||
// CHECK: stosw # encoding: [0xab]
|
// CHECK: stosw %ax, %es:(%di) # encoding: [0xab]
|
||||||
// CHECK: stosw
|
// CHECK: stosw
|
||||||
// CHECK: stosw
|
// CHECK: stosw
|
||||||
stosw
|
stosw
|
||||||
stosw %ax, %es:(%di)
|
stosw %ax, %es:(%di)
|
||||||
stos %ax, %es:(%di)
|
stos %ax, %es:(%di)
|
||||||
|
|
||||||
// CHECK: stosl # encoding: [0x66,0xab]
|
// CHECK: stosl %eax, %es:(%di) # encoding: [0x66,0xab]
|
||||||
// CHECK: stosl
|
// CHECK: stosl
|
||||||
// CHECK: stosl
|
// CHECK: stosl
|
||||||
stosl
|
stosl
|
||||||
|
@ -954,21 +954,21 @@ pshufw $90, %mm4, %mm0
|
|||||||
lods %ds:(%esi), %eax
|
lods %ds:(%esi), %eax
|
||||||
lods (%esi), %eax
|
lods (%esi), %eax
|
||||||
|
|
||||||
// CHECK: stosb # encoding: [0xaa]
|
// CHECK: stosb %al, %es:(%edi) # encoding: [0xaa]
|
||||||
// CHECK: stosb
|
// CHECK: stosb
|
||||||
// CHECK: stosb
|
// CHECK: stosb
|
||||||
stosb
|
stosb
|
||||||
stosb %al, %es:(%edi)
|
stosb %al, %es:(%edi)
|
||||||
stos %al, %es:(%edi)
|
stos %al, %es:(%edi)
|
||||||
|
|
||||||
// CHECK: stosw # encoding: [0x66,0xab]
|
// CHECK: stosw %ax, %es:(%edi) # encoding: [0x66,0xab]
|
||||||
// CHECK: stosw
|
// CHECK: stosw
|
||||||
// CHECK: stosw
|
// CHECK: stosw
|
||||||
stosw
|
stosw
|
||||||
stosw %ax, %es:(%edi)
|
stosw %ax, %es:(%edi)
|
||||||
stos %ax, %es:(%edi)
|
stos %ax, %es:(%edi)
|
||||||
|
|
||||||
// CHECK: stosl # encoding: [0xab]
|
// CHECK: stosl %eax, %es:(%edi) # encoding: [0xab]
|
||||||
// CHECK: stosl
|
// CHECK: stosl
|
||||||
// CHECK: stosl
|
// CHECK: stosl
|
||||||
stosl
|
stosl
|
||||||
|
@ -1160,28 +1160,28 @@ xsetbv // CHECK: xsetbv # encoding: [0x0f,0x01,0xd1]
|
|||||||
lods %ds:(%rsi), %rax
|
lods %ds:(%rsi), %rax
|
||||||
lods (%rsi), %rax
|
lods (%rsi), %rax
|
||||||
|
|
||||||
// CHECK: stosb # encoding: [0xaa]
|
// CHECK: stosb %al, %es:(%rdi) # encoding: [0xaa]
|
||||||
// CHECK: stosb
|
// CHECK: stosb
|
||||||
// CHECK: stosb
|
// CHECK: stosb
|
||||||
stosb
|
stosb
|
||||||
stosb %al, %es:(%rdi)
|
stosb %al, %es:(%rdi)
|
||||||
stos %al, %es:(%rdi)
|
stos %al, %es:(%rdi)
|
||||||
|
|
||||||
// CHECK: stosw # encoding: [0x66,0xab]
|
// CHECK: stosw %ax, %es:(%rdi) # encoding: [0x66,0xab]
|
||||||
// CHECK: stosw
|
// CHECK: stosw
|
||||||
// CHECK: stosw
|
// CHECK: stosw
|
||||||
stosw
|
stosw
|
||||||
stosw %ax, %es:(%rdi)
|
stosw %ax, %es:(%rdi)
|
||||||
stos %ax, %es:(%rdi)
|
stos %ax, %es:(%rdi)
|
||||||
|
|
||||||
// CHECK: stosl # encoding: [0xab]
|
// CHECK: stosl %eax, %es:(%rdi) # encoding: [0xab]
|
||||||
// CHECK: stosl
|
// CHECK: stosl
|
||||||
// CHECK: stosl
|
// CHECK: stosl
|
||||||
stosl
|
stosl
|
||||||
stosl %eax, %es:(%rdi)
|
stosl %eax, %es:(%rdi)
|
||||||
stos %eax, %es:(%rdi)
|
stos %eax, %es:(%rdi)
|
||||||
|
|
||||||
// CHECK: stosq # encoding: [0x48,0xab]
|
// CHECK: stosq %rax, %es:(%rdi) # encoding: [0x48,0xab]
|
||||||
// CHECK: stosq
|
// CHECK: stosq
|
||||||
// CHECK: stosq
|
// CHECK: stosq
|
||||||
stosq
|
stosq
|
||||||
|
@ -61,6 +61,7 @@ namespace X86Local {
|
|||||||
MRMSrcMem = 6,
|
MRMSrcMem = 6,
|
||||||
RawFrmMemOffs = 7,
|
RawFrmMemOffs = 7,
|
||||||
RawFrmSrc = 8,
|
RawFrmSrc = 8,
|
||||||
|
RawFrmDst = 9,
|
||||||
MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19,
|
MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19,
|
||||||
MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23,
|
MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23,
|
||||||
MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,
|
MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,
|
||||||
@ -634,6 +635,9 @@ void RecognizableInstr::emitInstructionSpecifier() {
|
|||||||
case X86Local::RawFrmSrc:
|
case X86Local::RawFrmSrc:
|
||||||
HANDLE_OPERAND(relocation);
|
HANDLE_OPERAND(relocation);
|
||||||
return;
|
return;
|
||||||
|
case X86Local::RawFrmDst:
|
||||||
|
HANDLE_OPERAND(relocation);
|
||||||
|
return;
|
||||||
case X86Local::RawFrm:
|
case X86Local::RawFrm:
|
||||||
// Operand 1 (optional) is an address or immediate.
|
// Operand 1 (optional) is an address or immediate.
|
||||||
// Operand 2 (optional) is an immediate.
|
// Operand 2 (optional) is an immediate.
|
||||||
@ -1270,6 +1274,10 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
|
|||||||
TYPE("srcidx16", TYPE_SRCIDX16)
|
TYPE("srcidx16", TYPE_SRCIDX16)
|
||||||
TYPE("srcidx32", TYPE_SRCIDX32)
|
TYPE("srcidx32", TYPE_SRCIDX32)
|
||||||
TYPE("srcidx64", TYPE_SRCIDX64)
|
TYPE("srcidx64", TYPE_SRCIDX64)
|
||||||
|
TYPE("dstidx8", TYPE_DSTIDX8)
|
||||||
|
TYPE("dstidx16", TYPE_DSTIDX16)
|
||||||
|
TYPE("dstidx32", TYPE_DSTIDX32)
|
||||||
|
TYPE("dstidx64", TYPE_DSTIDX64)
|
||||||
TYPE("offset8", TYPE_MOFFS8)
|
TYPE("offset8", TYPE_MOFFS8)
|
||||||
TYPE("offset16", TYPE_MOFFS16)
|
TYPE("offset16", TYPE_MOFFS16)
|
||||||
TYPE("offset32", TYPE_MOFFS32)
|
TYPE("offset32", TYPE_MOFFS32)
|
||||||
@ -1486,6 +1494,10 @@ OperandEncoding RecognizableInstr::relocationEncodingFromString
|
|||||||
ENCODING("srcidx16", ENCODING_SI)
|
ENCODING("srcidx16", ENCODING_SI)
|
||||||
ENCODING("srcidx32", ENCODING_SI)
|
ENCODING("srcidx32", ENCODING_SI)
|
||||||
ENCODING("srcidx64", ENCODING_SI)
|
ENCODING("srcidx64", ENCODING_SI)
|
||||||
|
ENCODING("dstidx8", ENCODING_DI)
|
||||||
|
ENCODING("dstidx16", ENCODING_DI)
|
||||||
|
ENCODING("dstidx32", ENCODING_DI)
|
||||||
|
ENCODING("dstidx64", ENCODING_DI)
|
||||||
errs() << "Unhandled relocation encoding " << s << "\n";
|
errs() << "Unhandled relocation encoding " << s << "\n";
|
||||||
llvm_unreachable("Unhandled relocation encoding");
|
llvm_unreachable("Unhandled relocation encoding");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user