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