summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp31
-rw-r--r--llvm/test/MC/X86/pr22028.s23
2 files changed, 52 insertions, 2 deletions
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 170f55cb1cd..eae22b8cc52 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -2784,6 +2784,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
assert(Op.isToken() && "Leading operand should always be a mnemonic!");
StringRef Mnemonic = Op.getToken();
SMRange EmptyRange = None;
+ StringRef Base = Op.getToken();
// First, handle aliases that expand to multiple instructions.
MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm);
@@ -2810,11 +2811,37 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
}
}
+ SmallVector<unsigned, 8> Match;
+ uint64_t ErrorInfoMissingFeature = 0;
+
+ // If unsized push has immediate operand we should default the default pointer
+ // size for the size.
+ if (Mnemonic == "push" && Operands.size() == 2) {
+ auto *X86Op = static_cast<X86Operand *>(Operands[1].get());
+ if (X86Op->isImm()) {
+ // If it's not a constant fall through and let remainder take care of it.
+ const auto *CE = dyn_cast<MCConstantExpr>(X86Op->getImm());
+ unsigned Size = getPointerWidth();
+ if (CE &&
+ (isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) {
+ SmallString<16> Tmp;
+ Tmp += Base;
+ Tmp += (is64BitMode())
+ ? "q"
+ : (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " ";
+ Op.setTokenValue(Tmp);
+ // Do match in ATT mode to allow explicit suffix usage.
+ Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo,
+ MatchingInlineAsm,
+ false /*isParsingIntelSyntax()*/));
+ Op.setTokenValue(Base);
+ }
+ }
+ }
+
// If an unsized memory operand is present, try to match with each memory
// operand size. In Intel assembly, the size is not part of the instruction
// mnemonic.
- SmallVector<unsigned, 8> Match;
- uint64_t ErrorInfoMissingFeature = 0;
if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) {
static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};
for (unsigned Size : MopSizes) {
diff --git a/llvm/test/MC/X86/pr22028.s b/llvm/test/MC/X86/pr22028.s
new file mode 100644
index 00000000000..6ce7da07488
--- /dev/null
+++ b/llvm/test/MC/X86/pr22028.s
@@ -0,0 +1,23 @@
+// RUN: llvm-mc -triple i386-unknown-unknown-code16 -show-encoding %s | FileCheck --check-prefix=CHECK16 %s
+// RUN: llvm-mc -triple i386-unknown-unknown -show-encoding %s | FileCheck --check-prefix=CHECK %s
+// RUN: llvm-mc -triple i686-unknown-unknown -show-encoding %s | FileCheck --check-prefix=CHECK %s
+
+.intel_syntax
+
+push 0
+push -1
+push 30
+push 257
+push 65536
+
+//CHECK16: pushw $0 # encoding: [0x6a,0x00]
+//CHECK16: pushw $-1 # encoding: [0x6a,0xff]
+//CHECK16: pushw $30 # encoding: [0x6a,0x1e]
+//CHECK16: pushw $257 # encoding: [0x68,0x01,0x01]
+//CHECK16: pushl $65536 # encoding: [0x66,0x68,0x00,0x00,0x01,0x00]
+
+//CHECK: pushl $0 # encoding: [0x6a,0x00]
+//CHECK: pushl $-1 # encoding: [0x6a,0xff]
+//CHECK: pushl $30 # encoding: [0x6a,0x1e]
+//CHECK: pushl $257 # encoding: [0x68,0x01,0x01,0x00,0x00]
+//CHECK: pushl $65536 # encoding: [0x68,0x00,0x00,0x01,0x00]
OpenPOWER on IntegriCloud