summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2014-01-08 12:58:28 +0000
committerDavid Woodhouse <dwmw2@infradead.org>2014-01-08 12:58:28 +0000
commitab5b9489e9e91ef21d9cebf5cf9453d2e9fce1d7 (patch)
tree4838e95316a428fefedc48c15bd8ac10f32a25c1
parentaab59870a4f57f3d3246c858cb775766e38f0795 (diff)
downloadllvm-ab5b9489e9e91ef21d9cebf5cf9453d2e9fce1d7.tar.gz
llvm-ab5b9489e9e91ef21d9cebf5cf9453d2e9fce1d7.tar.bz2
llvm-ab5b9489e9e91ef21d9cebf5cf9453d2e9fce1d7.tar.xz
[x86] Make AsmParser validate registers for memory operands a bit better
We can't do a perfect job here. We *have* to allow (%dx) even in 64-bit mode, for example, because it might be used for an unofficial form of the in/out instructions. We actually want to do a better job of validation *later*. Perhaps *instead* of doing it where we are at the moment. But for now, doing what validation we *can* do in the place that the code already has its validation, is an improvement. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198760 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp41
-rw-r--r--test/MC/X86/x86_errors.s17
2 files changed, 54 insertions, 4 deletions
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 86ba185819..3ed20d99f5 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -1853,10 +1853,11 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
// If we reached here, then we just ate the ( of the memory operand. Process
// the rest of the memory operand.
unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
- SMLoc IndexLoc;
+ SMLoc IndexLoc, BaseLoc;
if (getLexer().is(AsmToken::Percent)) {
SMLoc StartLoc, EndLoc;
+ BaseLoc = Parser.getTok().getLoc();
if (ParseRegister(BaseReg, StartLoc, EndLoc)) return 0;
if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
Error(StartLoc, "eiz and riz can only be used as index registers",
@@ -1899,6 +1900,11 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
}
// Validate the scale amount.
+ if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
+ ScaleVal != 1) {
+ Error(Loc, "scale factor in 16-bit address must be 1");
+ return 0;
+ }
if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
return 0;
@@ -1929,6 +1935,21 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
SMLoc MemEnd = Parser.getTok().getEndLoc();
Parser.Lex(); // Eat the ')'.
+ // Check for use of invalid 16-bit registers. Only BX/BP/SI/DI are allowed,
+ // and then only in non-64-bit modes. Except for DX, which is a special case
+ // because an unofficial form of in/out instructions uses it.
+ if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
+ (is64BitMode() || (BaseReg != X86::BX && BaseReg != X86::BP &&
+ BaseReg != X86::SI && BaseReg != X86::DI)) &&
+ BaseReg != X86::DX) {
+ Error(BaseLoc, "invalid 16-bit base register");
+ return 0;
+ }
+ if (BaseReg == 0 &&
+ X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg)) {
+ Error(IndexLoc, "16-bit memory operand may not include only index register");
+ return 0;
+ }
// If we have both a base register and an index register make sure they are
// both 64-bit or 32-bit registers.
// To support VSIB, IndexReg can be 128-bit or 256-bit registers.
@@ -1937,16 +1958,30 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
(X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg)) &&
IndexReg != X86::RIZ) {
- Error(IndexLoc, "index register is 32-bit, but base register is 64-bit");
+ Error(BaseLoc, "base register is 64-bit, but index register is not");
return 0;
}
if (X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) &&
(X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) &&
IndexReg != X86::EIZ){
- Error(IndexLoc, "index register is 64-bit, but base register is 32-bit");
+ Error(BaseLoc, "base register is 32-bit, but index register is not");
return 0;
}
+ if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg)) {
+ if (X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
+ X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) {
+ Error(BaseLoc, "base register is 16-bit, but index register is not");
+ return 0;
+ }
+ if (((BaseReg == X86::BX || BaseReg == X86::BP) &&
+ IndexReg != X86::SI && IndexReg != X86::DI) ||
+ ((BaseReg == X86::SI || BaseReg == X86::DI) &&
+ IndexReg != X86::BX && IndexReg != X86::BP)) {
+ Error(BaseLoc, "invalid 16-bit base/index register combination");
+ return 0;
+ }
+ }
}
return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
diff --git a/test/MC/X86/x86_errors.s b/test/MC/X86/x86_errors.s
index a974233d2f..51f2e8e146 100644
--- a/test/MC/X86/x86_errors.s
+++ b/test/MC/X86/x86_errors.s
@@ -26,8 +26,23 @@ sysexitq
lea (%rsp, %rbp, $4), %rax
// rdar://10423777
-// 64: error: index register is 32-bit, but base register is 64-bit
+// 64: error: base register is 64-bit, but index register is not
movq (%rsi,%ecx),%xmm0
+// 64: error: invalid 16-bit base register
+movl %eax,(%bp,%si)
+
+// 32: error: scale factor in 16-bit address must be 1
+movl %eax,(%bp,%si,2)
+
+// 32: error: invalid 16-bit base register
+movl %eax,(%cx)
+
+// 32: error: invalid 16-bit base/index register combination
+movl %eax,(%bp,%bx)
+
+// 32: error: 16-bit memory operand may not include only index register
+movl %eax,(,%bx)
+
// 32: error: invalid operand for instruction
outb al, 4