<div dir="ltr">Please remember to attach patches instead of sending them inline in separate mails.<div><br></div><div>-- Sean Silva</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jan 20, 2014 at 10:23 AM, David Woodhouse <span dir="ltr"><<a href="mailto:dwmw2@infradead.org" target="_blank">dwmw2@infradead.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
---<br>
lib/Target/X86/AsmParser/X86AsmParser.cpp | 70 +++++++++++++---------<br>
lib/Target/X86/Disassembler/X86Disassembler.cpp | 25 ++++++++<br>
.../X86/Disassembler/X86DisassemblerDecoder.c | 1 +<br>
.../Disassembler/X86DisassemblerDecoderCommon.h | 7 ++-<br>
lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp | 19 ++++++<br>
lib/Target/X86/InstPrinter/X86ATTInstPrinter.h | 13 ++++<br>
lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp | 14 +++++<br>
lib/Target/X86/InstPrinter/X86IntelInstPrinter.h | 18 ++++++<br>
lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 5 ++<br>
lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 13 ++++<br>
lib/Target/X86/X86InstrFormats.td | 1 +<br>
lib/Target/X86/X86InstrInfo.td | 61 +++++++++++++++++--<br>
test/MC/X86/index-operations.s | 46 ++++++++++++++<br>
test/MC/X86/x86-16.s | 6 +-<br>
test/MC/X86/x86-32.s | 6 +-<br>
test/MC/X86/x86-64.s | 8 +--<br>
utils/TableGen/X86RecognizableInstr.cpp | 12 ++++<br>
17 files changed, 280 insertions(+), 45 deletions(-)<br>
create mode 100644 test/MC/X86/index-operations.s<br>
<br>
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp<br>
index 5d60486..f354c95 100644<br>
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp<br>
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp<br>
@@ -551,6 +551,7 @@ private:<br>
return 0;<br>
}<br>
<br>
+ X86Operand *DefaultMemSIOperand(SMLoc Loc);<br>
X86Operand *ParseOperand();<br>
X86Operand *ParseATTOperand();<br>
X86Operand *ParseIntelOperand();<br>
@@ -922,6 +923,25 @@ struct X86Operand : public MCParsedAsmOperand {<br>
!getMemIndexReg() && getMemScale() == 1;<br>
}<br>
<br>
+ bool isSrcIdx() const {<br>
+ return !getMemIndexReg() && getMemScale() == 1 &&<br>
+ (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||<br>
+ getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&<br>
+ cast<MCConstantExpr>(getMemDisp())->getValue() == 0;<br>
+ }<br>
+ bool isSrcIdx8() const {<br>
+ return isMem8() && isSrcIdx();<br>
+ }<br>
+ bool isSrcIdx16() const {<br>
+ return isMem16() && isSrcIdx();<br>
+ }<br>
+ bool isSrcIdx32() const {<br>
+ return isMem32() && isSrcIdx();<br>
+ }<br>
+ bool isSrcIdx64() const {<br>
+ return isMem64() && isSrcIdx();<br>
+ }<br>
+<br>
bool isMemOffs8() const {<br>
return Kind == Memory && !getMemBaseReg() &&<br>
!getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 8);<br>
@@ -1014,6 +1034,12 @@ struct X86Operand : public MCParsedAsmOperand {<br>
Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));<br>
}<br>
<br>
+ void addSrcIdxOperands(MCInst &Inst, unsigned N) const {<br>
+ assert((N == 2) && "Invalid number of operands!");<br>
+ Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));<br>
+ Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));<br>
+ }<br>
+<br>
void addMemOffsOperands(MCInst &Inst, unsigned N) const {<br>
assert((N == 2) && "Invalid number of operands!");<br>
// Add as immediates when possible.<br>
@@ -1230,6 +1256,14 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo,<br>
return false;<br>
}<br>
<br>
+X86Operand *X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {<br>
+ unsigned basereg =<br>
+ is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI);<br>
+ const MCExpr *Disp = MCConstantExpr::Create(0, getContext());<br>
+ return X86Operand::CreateMem(/*SegReg=*/0, Disp, /*BaseReg=*/basereg,<br>
+ /*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0);<br>
+}<br>
+<br>
X86Operand *X86AsmParser::ParseOperand() {<br>
if (isParsingIntelSyntax())<br>
return ParseIntelOperand();<br>
@@ -2278,36 +2312,14 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,<br>
delete &Op2;<br>
}<br>
}<br>
- // Transform "lods[bwl] %ds:(%esi),{%al,%ax,%eax,%rax}" into "lods[bwl]"<br>
- if (Name.startswith("lods") && Operands.size() == 3 &&<br>
+ // Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate<br>
+ // values of $SIREG according to the mode. It would be nice if this<br>
+ // could be achieved with InstAlias in the tables.<br>
+ if (Name.startswith("lods") && Operands.size() == 1 &&<br>
(Name == "lods" || Name == "lodsb" || Name == "lodsw" ||<br>
- Name == "lodsl" || (is64BitMode() && Name == "lodsq"))) {<br>
- X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);<br>
- X86Operand *Op2 = static_cast<X86Operand*>(Operands[2]);<br>
- if (isSrcOp(*Op1) && Op2->isReg()) {<br>
- const char *ins;<br>
- unsigned reg = Op2->getReg();<br>
- bool isLods = Name == "lods";<br>
- if (reg == X86::AL && (isLods || Name == "lodsb"))<br>
- ins = "lodsb";<br>
- else if (reg == X86::AX && (isLods || Name == "lodsw"))<br>
- ins = "lodsw";<br>
- else if (reg == X86::EAX && (isLods || Name == "lodsl"))<br>
- ins = "lodsl";<br>
- else if (reg == X86::RAX && (isLods || Name == "lodsq"))<br>
- ins = "lodsq";<br>
- else<br>
- ins = NULL;<br>
- if (ins != NULL) {<br>
- Operands.pop_back();<br>
- Operands.pop_back();<br>
- delete Op1;<br>
- delete Op2;<br>
- if (Name != ins)<br>
- static_cast<X86Operand*>(Operands[0])->setTokenValue(ins);<br>
- }<br>
- }<br>
- }<br>
+ Name == "lodsl" || Name == "lodsd" || Name == "lodsq"))<br>
+ Operands.push_back(DefaultMemSIOperand(NameLoc));<br>
+<br>
// Transform "stos[bwl] {%al,%ax,%eax,%rax},%es:(%edi)" into "stos[bwl]"<br>
if (Name.startswith("stos") && Operands.size() == 3 &&<br>
(Name == "stos" || Name == "stosb" || Name == "stosw" ||<br>
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp<br>
index acfe88d..dae1345 100644<br>
--- a/lib/Target/X86/Disassembler/X86Disassembler.cpp<br>
+++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp<br>
@@ -233,6 +233,29 @@ static const uint8_t segmentRegnums[SEG_OVERRIDE_max] = {<br>
X86::GS<br>
};<br>
<br>
+/// translateSrcIndex - Appends a source index operand to an MCInst.<br>
+///<br>
+/// @param mcInst - The MCInst to append to.<br>
+/// @param operand - The operand, as stored in the descriptor table.<br>
+/// @param insn - The internal instruction.<br>
+static bool translateSrcIndex(MCInst &mcInst, InternalInstruction &insn) {<br>
+ unsigned baseRegNo;<br>
+<br>
+ if (insn.mode == MODE_64BIT)<br>
+ baseRegNo = insn.prefixPresent[0x67] ? X86::ESI : X86::RSI;<br>
+ else if (insn.mode == MODE_32BIT)<br>
+ baseRegNo = insn.prefixPresent[0x67] ? X86::SI : X86::ESI;<br>
+ else if (insn.mode == MODE_16BIT)<br>
+ baseRegNo = insn.prefixPresent[0x67] ? X86::ESI : X86::SI;<br>
+ MCOperand baseReg = MCOperand::CreateReg(baseRegNo);<br>
+ mcInst.addOperand(baseReg);<br>
+<br>
+ MCOperand segmentReg;<br>
+ segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]);<br>
+ mcInst.addOperand(segmentReg);<br>
+ return false;<br>
+}<br>
+<br>
/// translateImmediate - Appends an immediate operand to an MCInst.<br>
///<br>
/// @param mcInst - The MCInst to append to.<br>
@@ -694,6 +717,8 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,<br>
insn,<br>
Dis);<br>
return false;<br>
+ case ENCODING_SI:<br>
+ return translateSrcIndex(mcInst, insn);<br>
case ENCODING_RB:<br>
case ENCODING_RW:<br>
case ENCODING_RD:<br>
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c<br>
index 48c1697..8e591b8 100644<br>
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c<br>
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c<br>
@@ -1682,6 +1682,7 @@ static int readOperands(struct InternalInstruction* insn) {<br>
for (index = 0; index < X86_MAX_OPERANDS; ++index) {<br>
switch (x86OperandSets[insn->spec->operands][index].encoding) {<br>
case ENCODING_NONE:<br>
+ case ENCODING_SI:<br>
break;<br>
case ENCODING_REG:<br>
case ENCODING_RM:<br>
diff --git a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h<br>
index 1acaef1..c7fcb0c 100644<br>
--- a/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h<br>
+++ b/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h<br>
@@ -409,7 +409,8 @@ struct ContextDecision {<br>
ENUM_ENTRY(ENCODING_Rv, "Register code of operand size added to the " \<br>
"opcode byte") \<br>
ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \<br>
- "in type")<br>
+ "in type") \<br>
+ ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix")<br>
<br>
#define ENUM_ENTRY(n, d) n,<br>
typedef enum {<br>
@@ -460,6 +461,10 @@ struct ContextDecision {<br>
ENUM_ENTRY(TYPE_M16_16, "2+2-byte (BOUND)") \<br>
ENUM_ENTRY(TYPE_M32_32, "4+4-byte (BOUND)") \<br>
ENUM_ENTRY(TYPE_M16_64, "2+8-byte (LIDT, LGDT)") \<br>
+ ENUM_ENTRY(TYPE_SRCIDX8, "1-byte memory at source index") \<br>
+ ENUM_ENTRY(TYPE_SRCIDX16, "2-byte memory at source index") \<br>
+ ENUM_ENTRY(TYPE_SRCIDX32, "4-byte memory at source index") \<br>
+ ENUM_ENTRY(TYPE_SRCIDX64, "8-byte memory at source index") \<br>
ENUM_ENTRY(TYPE_MOFFS8, "1-byte memory offset (relative to segment " \<br>
"base)") \<br>
ENUM_ENTRY(TYPE_MOFFS16, "2-byte") \<br>
diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp<br>
index 11a9ada..4cd4457 100644<br>
--- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp<br>
+++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp<br>
@@ -226,6 +226,25 @@ void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op,<br>
O << markup(">");<br>
}<br>
<br>
+void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,<br>
+ raw_ostream &O) {<br>
+ const MCOperand &SegReg = MI->getOperand(Op+1);<br>
+<br>
+ O << markup("<mem:");<br>
+<br>
+ // If this has a segment register, print it.<br>
+ if (SegReg.getReg()) {<br>
+ printOperand(MI, Op+1, O);<br>
+ O << ':';<br>
+ }<br>
+<br>
+ O << "(";<br>
+ printOperand(MI, Op, O);<br>
+ O << ")";<br>
+<br>
+ O << markup(">");<br>
+}<br>
+<br>
void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,<br>
raw_ostream &O) {<br>
const MCOperand &DispSpec = MI->getOperand(Op);<br>
diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h<br>
index 4dc4fe6..8c7c838 100644<br>
--- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h<br>
+++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h<br>
@@ -42,6 +42,7 @@ public:<br>
void printSSECC(const MCInst *MI, unsigned Op, raw_ostream &OS);<br>
void printAVXCC(const MCInst *MI, unsigned Op, raw_ostream &OS);<br>
void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &OS);<br>
+ void printSrcIdx(const MCInst *MI, unsigned OpNo, raw_ostream &OS);<br>
void printMemOffset(const MCInst *MI, unsigned OpNo, raw_ostream &OS);<br>
void printRoundingControl(const MCInst *MI, unsigned Op, raw_ostream &OS);<br>
<br>
@@ -89,6 +90,18 @@ public:<br>
printMemReference(MI, OpNo, O);<br>
}<br>
<br>
+ void printSrcIdx8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
+ printSrcIdx(MI, OpNo, O);<br>
+ }<br>
+ void printSrcIdx16(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
+ printSrcIdx(MI, OpNo, O);<br>
+ }<br>
+ void printSrcIdx32(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
+ printSrcIdx(MI, OpNo, O);<br>
+ }<br>
+ void printSrcIdx64(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
+ printSrcIdx(MI, OpNo, O);<br>
+ }<br>
void printMemOffs8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
printMemOffset(MI, OpNo, O);<br>
}<br>
diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp<br>
index 59634f9..8ea070b 100644<br>
--- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp<br>
+++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp<br>
@@ -212,6 +212,20 @@ void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op,<br>
O << ']';<br>
}<br>
<br>
+void X86IntelInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,<br>
+ raw_ostream &O) {<br>
+ const MCOperand &SegReg = MI->getOperand(Op+1);<br>
+<br>
+ // If this has a segment register, print it.<br>
+ if (SegReg.getReg()) {<br>
+ printOperand(MI, Op+1, O);<br>
+ O << ':';<br>
+ }<br>
+ O << '[';<br>
+ printOperand(MI, Op, O);<br>
+ O << ']';<br>
+}<br>
+<br>
void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,<br>
raw_ostream &O) {<br>
const MCOperand &DispSpec = MI->getOperand(Op);<br>
diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h<br>
index 90d4e39..067df81 100644<br>
--- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h<br>
+++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h<br>
@@ -40,6 +40,7 @@ public:<br>
void printAVXCC(const MCInst *MI, unsigned Op, raw_ostream &O);<br>
void printPCRelImm(const MCInst *MI, unsigned OpNo, raw_ostream &O);<br>
void printMemOffset(const MCInst *MI, unsigned OpNo, raw_ostream &O);<br>
+ void printSrcIdx(const MCInst *MI, unsigned OpNo, raw_ostream &O);<br>
void printRoundingControl(const MCInst *MI, unsigned Op, raw_ostream &OS);<br>
<br>
void printopaquemem(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
@@ -100,6 +101,23 @@ public:<br>
printMemReference(MI, OpNo, O);<br>
}<br>
<br>
+<br>
+ void printSrcIdx8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
+ O << "byte ptr ";<br>
+ printSrcIdx(MI, OpNo, O);<br>
+ }<br>
+ void printSrcIdx16(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
+ O << "word ptr ";<br>
+ printSrcIdx(MI, OpNo, O);<br>
+ }<br>
+ void printSrcIdx32(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
+ O << "dword ptr ";<br>
+ printSrcIdx(MI, OpNo, O);<br>
+ }<br>
+ void printSrcIdx64(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
+ O << "qword ptr ";<br>
+ printSrcIdx(MI, OpNo, O);<br>
+ }<br>
void printMemOffs8(const MCInst *MI, unsigned OpNo, raw_ostream &O) {<br>
O << "byte ptr ";<br>
printMemOffset(MI, OpNo, O);<br>
diff --git a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h<br>
index b25a35e..1ca0bd6 100644<br>
--- a/lib/Target/X86/MCTargetDesc/X86BaseInfo.h<br>
+++ b/lib/Target/X86/MCTargetDesc/X86BaseInfo.h<br>
@@ -259,6 +259,10 @@ namespace X86II {<br>
/// memory offset as an immediate with a possible segment override.<br>
RawFrmMemOffs = 7,<br>
<br>
+ /// RawFrmSrc - This form is for instructions that use the source index<br>
+ /// register SI/ESI/RSI with a possible segment override.<br>
+ RawFrmSrc = 8,<br>
+<br>
/// MRM[0-7][rm] - These forms are used to represent instructions that use<br>
/// a Mod/RM byte, and use the middle field to hold extended opcode<br>
/// information. In the intel manual these are represented as /0, /1, ...<br>
@@ -612,6 +616,7 @@ namespace X86II {<br>
case X86II::RawFrmImm8:<br>
case X86II::RawFrmImm16:<br>
case X86II::RawFrmMemOffs:<br>
+ case X86II::RawFrmSrc:<br>
return -1;<br>
case X86II::MRMDestMem:<br>
return 0;<br>
diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp<br>
index 813691b..ac72fce 100644<br>
--- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp<br>
+++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp<br>
@@ -1317,6 +1317,19 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,<br>
llvm_unreachable("Unknown FormMask value in X86MCCodeEmitter!");<br>
case X86II::Pseudo:<br>
llvm_unreachable("Pseudo instruction shouldn't be emitted");<br>
+ case X86II::RawFrmSrc: {<br>
+ unsigned siReg = MI.getOperand(0).getReg();<br>
+ // Emit segment override opcode prefix as needed (not for %ds).<br>
+ if (MI.getOperand(1).getReg() != X86::DS)<br>
+ EmitSegmentOverridePrefix(CurByte, 1, MI, OS);<br>
+ // Emit OpSize prefix as needed.<br>
+ if ((!is32BitMode() && siReg == X86::ESI) ||<br>
+ (is32BitMode() && siReg == X86::SI))<br>
+ EmitByte(0x67, CurByte, OS);<br>
+ CurOp += 2; // Consume operands.<br>
+ EmitByte(BaseOpcode, CurByte, OS);<br>
+ break;<br>
+ }<br>
case X86II::RawFrm:<br>
EmitByte(BaseOpcode, CurByte, OS);<br>
break;<br>
diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td<br>
index eed3619..a239d1f 100644<br>
--- a/lib/Target/X86/X86InstrFormats.td<br>
+++ b/lib/Target/X86/X86InstrFormats.td<br>
@@ -22,6 +22,7 @@ def Pseudo : Format<0>; def RawFrm : Format<1>;<br>
def AddRegFrm : Format<2>; def MRMDestReg : Format<3>;<br>
def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>;<br>
def MRMSrcMem : Format<6>; def RawFrmMemOffs : Format<7>;<br>
+def RawFrmSrc : Format<8>;<br>
def MRM0r : Format<16>; def MRM1r : Format<17>; def MRM2r : Format<18>;<br>
def MRM3r : Format<19>; def MRM4r : Format<20>; def MRM5r : Format<21>;<br>
def MRM6r : Format<22>; def MRM7r : Format<23>;<br>
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td<br>
index 486435d..d3e1027 100644<br>
--- a/lib/Target/X86/X86InstrInfo.td<br>
+++ b/lib/Target/X86/X86InstrInfo.td<br>
@@ -445,6 +445,26 @@ def brtarget8 : Operand<OtherVT>;<br>
<br>
}<br>
<br>
+def X86SrcIdx8Operand : AsmOperandClass {<br>
+ let Name = "SrcIdx8";<br>
+ let RenderMethod = "addSrcIdxOperands";<br>
+ let SuperClasses = [X86Mem8AsmOperand];<br>
+}<br>
+def X86SrcIdx16Operand : AsmOperandClass {<br>
+ let Name = "SrcIdx16";<br>
+ let RenderMethod = "addSrcIdxOperands";<br>
+ let SuperClasses = [X86Mem16AsmOperand];<br>
+}<br>
+def X86SrcIdx32Operand : AsmOperandClass {<br>
+ let Name = "SrcIdx32";<br>
+ let RenderMethod = "addSrcIdxOperands";<br>
+ let SuperClasses = [X86Mem32AsmOperand];<br>
+}<br>
+def X86SrcIdx64Operand : AsmOperandClass {<br>
+ let Name = "SrcIdx64";<br>
+ let RenderMethod = "addSrcIdxOperands";<br>
+ let SuperClasses = [X86Mem64AsmOperand];<br>
+}<br>
def X86MemOffs8AsmOperand : AsmOperandClass {<br>
let Name = "MemOffs8";<br>
let RenderMethod = "addMemOffsOperands";<br>
@@ -465,8 +485,23 @@ def X86MemOffs64AsmOperand : AsmOperandClass {<br>
let RenderMethod = "addMemOffsOperands";<br>
let SuperClasses = [X86Mem64AsmOperand];<br>
}<br>
-<br>
let OperandType = "OPERAND_MEMORY" in {<br>
+def srcidx8 : Operand<iPTR> {<br>
+ let ParserMatchClass = X86SrcIdx8Operand;<br>
+ let MIOperandInfo = (ops ptr_rc, i8imm);<br>
+ let PrintMethod = "printSrcIdx8"; }<br>
+def srcidx16 : Operand<iPTR> {<br>
+ let ParserMatchClass = X86SrcIdx16Operand;<br>
+ let MIOperandInfo = (ops ptr_rc, i8imm);<br>
+ let PrintMethod = "printSrcIdx16"; }<br>
+def srcidx32 : Operand<iPTR> {<br>
+ let ParserMatchClass = X86SrcIdx32Operand;<br>
+ let MIOperandInfo = (ops ptr_rc, i8imm);<br>
+ let PrintMethod = "printSrcIdx32"; }<br>
+def srcidx64 : Operand<iPTR> {<br>
+ let ParserMatchClass = X86SrcIdx64Operand;<br>
+ let MIOperandInfo = (ops ptr_rc, i8imm);<br>
+ let PrintMethod = "printSrcIdx64"; }<br>
def offset8 : Operand<iPTR> {<br>
let ParserMatchClass = X86MemOffs8AsmOperand;<br>
let MIOperandInfo = (ops i64imm, i8imm);<br>
@@ -1676,10 +1711,14 @@ def REPNE_PREFIX : I<0xF2, RawFrm, (outs), (ins), "repne", []>;<br>
<br>
// String manipulation instructions<br>
let SchedRW = [WriteMicrocoded] in {<br>
-def LODSB : I<0xAC, RawFrm, (outs), (ins), "lodsb", [], IIC_LODS>;<br>
-def LODSW : I<0xAD, RawFrm, (outs), (ins), "lodsw", [], IIC_LODS>, OpSize;<br>
-def LODSL : I<0xAD, RawFrm, (outs), (ins), "lods{l|d}", [], IIC_LODS>, OpSize16;<br>
-def LODSQ : RI<0xAD, RawFrm, (outs), (ins), "lodsq", [], IIC_LODS>;<br>
+def LODSB : I<0xAC, RawFrmSrc, (outs), (ins srcidx8:$src),<br>
+ "lodsb\t{$src, %al|al, $src}", [], IIC_LODS>;<br>
+def LODSW : I<0xAD, RawFrmSrc, (outs), (ins srcidx16:$src),<br>
+ "lodsw\t{$src, %ax|ax, $src}", [], IIC_LODS>, OpSize;<br>
+def LODSL : I<0xAD, RawFrmSrc, (outs), (ins srcidx32:$src),<br>
+ "lods{l|d}\t{$src, %eax|eax, $src}", [], IIC_LODS>, OpSize16;<br>
+def LODSQ : RI<0xAD, RawFrmSrc, (outs), (ins srcidx64:$src),<br>
+ "lodsq\t{$src, %rax|rax, $src}", [], IIC_LODS>;<br>
}<br>
<br>
let SchedRW = [WriteSystem] in {<br>
@@ -2329,6 +2368,18 @@ def : InstAlias<"clrw $reg", (XOR16rr GR16:$reg, GR16:$reg), 0>;<br>
def : InstAlias<"clrl $reg", (XOR32rr GR32:$reg, GR32:$reg), 0>;<br>
def : InstAlias<"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg), 0>;<br>
<br>
+// lods aliases. Accept the destination being omitted because it's implicit<br>
+// in the mnemonic, or the mnemonic suffix being omitted because it's implicit<br>
+// in the destination.<br>
+def : InstAlias<"lodsb $src", (LODSB srcidx8:$src), 0>;<br>
+def : InstAlias<"lodsw $src", (LODSW srcidx16:$src), 0>;<br>
+def : InstAlias<"lods{l|d} $src", (LODSL srcidx32:$src), 0>;<br>
+def : InstAlias<"lodsq $src", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>;<br>
+def : InstAlias<"lods {$src, %al|al, $src}", (LODSB srcidx8:$src), 0>;<br>
+def : InstAlias<"lods {$src, %ax|ax, $src}", (LODSW srcidx16:$src), 0>;<br>
+def : InstAlias<"lods {$src, %eax|eax, $src}", (LODSL srcidx32:$src), 0>;<br>
+def : InstAlias<"lods {$src, %rax|rax, $src}", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>;<br>
+<br>
// div and idiv aliases for explicit A register.<br>
def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8r GR8 :$src)>;<br>
def : InstAlias<"div{w}\t{$src, %ax|ax, $src}", (DIV16r GR16:$src)>;<br>
diff --git a/test/MC/X86/index-operations.s b/test/MC/X86/index-operations.s<br>
new file mode 100644<br>
index 0000000..a5dd88b<br>
--- /dev/null<br>
+++ b/test/MC/X86/index-operations.s<br>
@@ -0,0 +1,46 @@<br>
+// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=64 %s<br>
+// RUN: FileCheck --check-prefix=ERR64 < %t.err %s<br>
+// RUN: not llvm-mc -triple i386-unknown-unknown --show-encoding %s 2> %t.err | FileCheck --check-prefix=32 %s<br>
+// RUN: FileCheck --check-prefix=ERR32 < %t.err %s<br>
+// RUN: not llvm-mc -triple i386-unknown-unknown-code16 --show-encoding %s 2> %t.err | FileCheck --check-prefix=16 %s<br>
+// RUN: FileCheck --check-prefix=ERR16 < %t.err %s<br>
+<br>
+lodsb<br>
+// 64: lodsb (%rsi), %al # encoding: [0xac]<br>
+// 32: lodsb (%esi), %al # encoding: [0xac]<br>
+// 16: lodsb (%si), %al # encoding: [0xac]<br>
+<br>
+lodsb (%rsi), %al<br>
+// 64: lodsb (%rsi), %al # encoding: [0xac]<br>
+// ERR32: 64-bit<br>
+// ERR16: 64-bit<br>
+<br>
+lodsb (%esi), %al<br>
+// 64: lodsb (%esi), %al # encoding: [0x67,0xac]<br>
+// 32: lodsb (%esi), %al # encoding: [0xac]<br>
+// 16: lodsb (%esi), %al # encoding: [0x67,0xac]<br>
+<br>
+lodsb (%si), %al<br>
+// ERR64: invalid 16-bit base register<br>
+// 32: lodsb (%si), %al # encoding: [0x67,0xac]<br>
+// 16: lodsb (%si), %al # encoding: [0xac]<br>
+<br>
+lodsl %gs:(%esi)<br>
+// 64: lodsl %gs:(%esi), %eax # encoding: [0x65,0x67,0xad]<br>
+// 32: lodsl %gs:(%esi), %eax # encoding: [0x65,0xad]<br>
+// 16: lodsl %gs:(%esi), %eax # encoding: [0x66,0x65,0x67,0xad]<br>
+<br>
+lodsl (%edi), %eax<br>
+// ERR64: invalid operand<br>
+// ERR32: invalid operand<br>
+// ERR16: invalid operand<br>
+<br>
+lodsl 44(%edi), %eax<br>
+// ERR64: invalid operand<br>
+// ERR32: invalid operand<br>
+// ERR16: invalid operand<br>
+<br>
+lods (%esi), %ax<br>
+// 64: lodsw (%esi), %ax # encoding: [0x66,0x67,0xad]<br>
+// 32: lodsw (%esi), %ax # encoding: [0x66,0xad]<br>
+// 16: lodsw (%esi), %ax # encoding: [0x67,0xad]<br>
diff --git a/test/MC/X86/x86-16.s b/test/MC/X86/x86-16.s<br>
index 41d068e..4b54a02 100644<br>
--- a/test/MC/X86/x86-16.s<br>
+++ b/test/MC/X86/x86-16.s<br>
@@ -845,7 +845,7 @@ pshufw $90, %mm4, %mm0<br>
movsl %ds:(%si), %es:(%di)<br>
movsl (%si), %es:(%di)<br>
<br>
-// CHECK: lodsb # encoding: [0xac]<br>
+// CHECK: lodsb (%si), %al # encoding: [0xac]<br>
// CHECK: lodsb<br>
// CHECK: lodsb<br>
// CHECK: lodsb<br>
@@ -856,7 +856,7 @@ pshufw $90, %mm4, %mm0<br>
lods %ds:(%si), %al<br>
lods (%si), %al<br>
<br>
-// CHECK: lodsw # encoding: [0xad]<br>
+// CHECK: lodsw (%si), %ax # encoding: [0xad]<br>
// CHECK: lodsw<br>
// CHECK: lodsw<br>
// CHECK: lodsw<br>
@@ -867,7 +867,7 @@ pshufw $90, %mm4, %mm0<br>
lods %ds:(%si), %ax<br>
lods (%si), %ax<br>
<br>
-// CHECK: lodsl # encoding: [0x66,0xad]<br>
+// CHECK: lodsl (%si), %eax # encoding: [0x66,0xad]<br>
// CHECK: lodsl<br>
// CHECK: lodsl<br>
// CHECK: lodsl<br>
diff --git a/test/MC/X86/x86-32.s b/test/MC/X86/x86-32.s<br>
index 140c05a..29be52e 100644<br>
--- a/test/MC/X86/x86-32.s<br>
+++ b/test/MC/X86/x86-32.s<br>
@@ -921,7 +921,7 @@ pshufw $90, %mm4, %mm0<br>
movsl %ds:(%esi), %es:(%edi)<br>
movsl (%esi), %es:(%edi)<br>
<br>
-// CHECK: lodsb # encoding: [0xac]<br>
+// CHECK: lodsb (%esi), %al # encoding: [0xac]<br>
// CHECK: lodsb<br>
// CHECK: lodsb<br>
// CHECK: lodsb<br>
@@ -932,7 +932,7 @@ pshufw $90, %mm4, %mm0<br>
lods %ds:(%esi), %al<br>
lods (%esi), %al<br>
<br>
-// CHECK: lodsw # encoding: [0x66,0xad]<br>
+// CHECK: lodsw (%esi), %ax # encoding: [0x66,0xad]<br>
// CHECK: lodsw<br>
// CHECK: lodsw<br>
// CHECK: lodsw<br>
@@ -943,7 +943,7 @@ pshufw $90, %mm4, %mm0<br>
lods %ds:(%esi), %ax<br>
lods (%esi), %ax<br>
<br>
-// CHECK: lodsl # encoding: [0xad]<br>
+// CHECK: lodsl (%esi), %eax # encoding: [0xad]<br>
// CHECK: lodsl<br>
// CHECK: lodsl<br>
// CHECK: lodsl<br>
diff --git a/test/MC/X86/x86-64.s b/test/MC/X86/x86-64.s<br>
index 28035c0..ef798d7 100644<br>
--- a/test/MC/X86/x86-64.s<br>
+++ b/test/MC/X86/x86-64.s<br>
@@ -1116,7 +1116,7 @@ xsetbv // CHECK: xsetbv # encoding: [0x0f,0x01,0xd1]<br>
movsq %ds:(%rsi), %es:(%rdi)<br>
movsq (%rsi), %es:(%rdi)<br>
<br>
-// CHECK: lodsb # encoding: [0xac]<br>
+// CHECK: lodsb (%rsi), %al # encoding: [0xac]<br>
// CHECK: lodsb<br>
// CHECK: lodsb<br>
// CHECK: lodsb<br>
@@ -1127,7 +1127,7 @@ xsetbv // CHECK: xsetbv # encoding: [0x0f,0x01,0xd1]<br>
lods %ds:(%rsi), %al<br>
lods (%rsi), %al<br>
<br>
-// CHECK: lodsw # encoding: [0x66,0xad]<br>
+// CHECK: lodsw (%rsi), %ax # encoding: [0x66,0xad]<br>
// CHECK: lodsw<br>
// CHECK: lodsw<br>
// CHECK: lodsw<br>
@@ -1138,7 +1138,7 @@ xsetbv // CHECK: xsetbv # encoding: [0x0f,0x01,0xd1]<br>
lods %ds:(%rsi), %ax<br>
lods (%rsi), %ax<br>
<br>
-// CHECK: lodsl # encoding: [0xad]<br>
+// CHECK: lodsl (%rsi), %eax # encoding: [0xad]<br>
// CHECK: lodsl<br>
// CHECK: lodsl<br>
// CHECK: lodsl<br>
@@ -1149,7 +1149,7 @@ xsetbv // CHECK: xsetbv # encoding: [0x0f,0x01,0xd1]<br>
lods %ds:(%rsi), %eax<br>
lods (%rsi), %eax<br>
<br>
-// CHECK: lodsq # encoding: [0x48,0xad]<br>
+// CHECK: lodsq (%rsi), %rax # encoding: [0x48,0xad]<br>
// CHECK: lodsq<br>
// CHECK: lodsq<br>
// CHECK: lodsq<br>
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp<br>
index c09abef..1530c42 100644<br>
--- a/utils/TableGen/X86RecognizableInstr.cpp<br>
+++ b/utils/TableGen/X86RecognizableInstr.cpp<br>
@@ -60,6 +60,7 @@ namespace X86Local {<br>
MRMSrcReg = 5,<br>
MRMSrcMem = 6,<br>
RawFrmMemOffs = 7,<br>
+ RawFrmSrc = 8,<br>
MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19,<br>
MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23,<br>
MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,<br>
@@ -630,6 +631,9 @@ void RecognizableInstr::emitInstructionSpecifier() {<br>
<br>
switch (Form) {<br>
default: llvm_unreachable("Unhandled form");<br>
+ case X86Local::RawFrmSrc:<br>
+ HANDLE_OPERAND(relocation);<br>
+ return;<br>
case X86Local::RawFrm:<br>
// Operand 1 (optional) is an address or immediate.<br>
// Operand 2 (optional) is an immediate.<br>
@@ -1262,6 +1266,10 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,<br>
TYPE("SEGMENT_REG", TYPE_SEGMENTREG)<br>
TYPE("DEBUG_REG", TYPE_DEBUGREG)<br>
TYPE("CONTROL_REG", TYPE_CONTROLREG)<br>
+ TYPE("srcidx8", TYPE_SRCIDX8)<br>
+ TYPE("srcidx16", TYPE_SRCIDX16)<br>
+ TYPE("srcidx32", TYPE_SRCIDX32)<br>
+ TYPE("srcidx64", TYPE_SRCIDX64)<br>
TYPE("offset8", TYPE_MOFFS8)<br>
TYPE("offset16", TYPE_MOFFS16)<br>
TYPE("offset32", TYPE_MOFFS32)<br>
@@ -1474,6 +1482,10 @@ OperandEncoding RecognizableInstr::relocationEncodingFromString<br>
ENCODING("offset16", ENCODING_Ia)<br>
ENCODING("offset32", ENCODING_Ia)<br>
ENCODING("offset64", ENCODING_Ia)<br>
+ ENCODING("srcidx8", ENCODING_SI)<br>
+ ENCODING("srcidx16", ENCODING_SI)<br>
+ ENCODING("srcidx32", ENCODING_SI)<br>
+ ENCODING("srcidx64", ENCODING_SI)<br>
errs() << "Unhandled relocation encoding " << s << "\n";<br>
llvm_unreachable("Unhandled relocation encoding");<br>
}<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.4.2<br>
<br>
<br>
--<br>
dwmw2<br>
</font></span><br>_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br></blockquote></div><br></div>