[llvm] e297d92 - [X86] Add assembler support for {disp8} and {disp32} to control the size of displacement used for memory operands.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 1 14:13:10 PDT 2020


Author: Craig Topper
Date: 2020-08-01T13:26:35-07:00
New Revision: e297d928dcde31ac92eff72532095f4f657f2ebd

URL: https://github.com/llvm/llvm-project/commit/e297d928dcde31ac92eff72532095f4f657f2ebd
DIFF: https://github.com/llvm/llvm-project/commit/e297d928dcde31ac92eff72532095f4f657f2ebd.diff

LOG: [X86] Add assembler support for {disp8} and {disp32} to control the size of displacement used for memory operands.

These prefixes should override the default behavior and force a larger immediate size. I don't believe gas issues any warning if you use {disp8} when a 32-bit displacement is already required. And this patch doesn't either.

This completes the {disp8} and {disp32} support from PR46650.

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D84793

Added: 
    

Modified: 
    llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
    llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
    llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
    llvm/test/MC/X86/x86-64.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 6b4f2e33f67d..49c01d7b9ef0 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -3572,6 +3572,12 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
   if (ForcedVEXEncoding == VEXEncoding_VEX3)
     Prefixes |= X86::IP_USE_VEX3;
 
+  // Set encoded flags for {disp8} and {disp32}.
+  if (ForcedDispEncoding == DispEncoding_Disp8)
+    Prefixes |= X86::IP_USE_DISP8;
+  else if (ForcedDispEncoding == DispEncoding_Disp32)
+    Prefixes |= X86::IP_USE_DISP32;
+
   if (Prefixes)
     Inst.setFlags(Prefixes);
 
@@ -3806,6 +3812,12 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
   if (ForcedVEXEncoding == VEXEncoding_VEX3)
     Prefixes |= X86::IP_USE_VEX3;
 
+  // Set encoded flags for {disp8} and {disp32}.
+  if (ForcedDispEncoding == DispEncoding_Disp8)
+    Prefixes |= X86::IP_USE_DISP8;
+  else if (ForcedDispEncoding == DispEncoding_Disp32)
+    Prefixes |= X86::IP_USE_DISP32;
+
   if (Prefixes)
     Inst.setFlags(Prefixes);
 

diff  --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
index 79f07d3c7792..b6e8d4813d4c 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h
@@ -62,6 +62,8 @@ namespace X86 {
     IP_HAS_LOCK = 16,
     IP_HAS_NOTRACK = 32,
     IP_USE_VEX3 = 64,
+    IP_USE_DISP8 = 128,
+    IP_USE_DISP32 = 256,
   };
 
   enum OperandType : unsigned {

diff  --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index abdc0f156b9f..0de94cda2d73 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -505,12 +505,18 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
     return;
   }
 
-  // Determine whether a SIB byte is needed.
-  // If no BaseReg, issue a RIP relative instruction only if the MCE can
-  // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table
-  // 2-7) and absolute references.
+  // Check for presence of {disp8} or {disp32} pseudo prefixes.
+  bool UseDisp8 = MI.getFlags() & X86::IP_USE_DISP8;
+  bool UseDisp32 = MI.getFlags() & X86::IP_USE_DISP32;
+
+  // We only allow no displacement if no pseudo prefix is present.
+  bool AllowNoDisp = !UseDisp8 && !UseDisp32;
+  // Disp8 is allowed unless the {disp32} prefix is present.
+  bool AllowDisp8 = !UseDisp32;
 
-  if ( // The SIB byte must be used if there is an index register.
+  // Determine whether a SIB byte is needed.
+  if (// The SIB byte must be used if there is an index register or the
+      // encoding requires a SIB byte.
       !ForceSIB && IndexReg.getReg() == 0 &&
       // The SIB byte must be used if the base is ESP/RSP/R12, all of which
       // encode to an R/M value of 4, which indicates that a SIB byte is
@@ -526,12 +532,12 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
       return;
     }
 
-    // If the base is not EBP/ESP and there is no displacement, use simple
-    // indirect register encoding, this handles addresses like [EAX].  The
-    // encoding for [EBP] with no displacement means [disp32] so we handle it
-    // by emitting a displacement of 0 below.
+    // If the base is not EBP/ESP/R12/R13 and there is no displacement, use
+    // simple indirect register encoding, this handles addresses like [EAX].
+    // The encoding for [EBP] or[R13] with no displacement means [disp32] so we
+    // handle it by emitting a displacement of 0 later.
     if (BaseRegNo != N86::EBP) {
-      if (Disp.isImm() && Disp.getImm() == 0) {
+      if (Disp.isImm() && Disp.getImm() == 0 && AllowNoDisp) {
         emitByte(modRMByte(0, RegOpcodeField, BaseRegNo), OS);
         return;
       }
@@ -550,7 +556,10 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
     }
 
     // Otherwise, if the displacement fits in a byte, encode as [REG+disp8].
-    if (Disp.isImm()) {
+    // Including a compressed disp8 for EVEX instructions that support it.
+    // This also handles the 0 displacement for [EBP] or [R13]. We can't use
+    // disp8 if the {disp32} pseudo prefix is present.
+    if (Disp.isImm() && AllowDisp8) {
       int ImmOffset = 0;
       if (isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) {
         emitByte(modRMByte(1, RegOpcodeField, BaseRegNo), OS);
@@ -560,7 +569,9 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
       }
     }
 
-    // Otherwise, emit the most general non-SIB encoding: [REG+disp32]
+    // Otherwise, emit the most general non-SIB encoding: [REG+disp32].
+    // Displacement may be 0 for [EBP] or [R13] case if {disp32} pseudo prefix
+    // prevented using disp8 above.
     emitByte(modRMByte(2, RegOpcodeField, BaseRegNo), OS);
     unsigned Opcode = MI.getOpcode();
     unsigned FixupKind = Opcode == X86::MOV32rm ? X86::reloc_signed_4byte_relax
@@ -580,21 +591,26 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
   if (BaseReg == 0) {
     // If there is no base register, we emit the special case SIB byte with
     // MOD=0, BASE=5, to JUST get the index, scale, and displacement.
+    BaseRegNo = 5;
     emitByte(modRMByte(0, RegOpcodeField, 4), OS);
     ForceDisp32 = true;
-  } else if (Disp.isImm() && Disp.getImm() == 0 &&
-             // Base reg can't be anything that ends up with '5' as the base
-             // reg, it is the magic [*] nomenclature that indicates no base.
+  } else if (Disp.isImm() && Disp.getImm() == 0 && AllowNoDisp &&
+             // Base reg can't be EBP/RBP/R13 as that would end up with '5' as
+             // the base field, but that is the magic [*] nomenclature that
+             // indicates no base when mod=0. For these cases we'll emit a 0
+             // displacement instead.
              BaseRegNo != N86::EBP) {
     // Emit no displacement ModR/M byte
     emitByte(modRMByte(0, RegOpcodeField, 4), OS);
-  } else if (Disp.isImm() &&
+  } else if (Disp.isImm() && AllowDisp8 &&
              isDispOrCDisp8(TSFlags, Disp.getImm(), ImmOffset)) {
-    // Emit the disp8 encoding.
+    // Displacement fits in a byte or matches an EVEX compressed disp8, use
+    // disp8 encoding. This also handles EBP/R13 base with 0 displacement unless
+    // {disp32} pseudo prefix was used.
     emitByte(modRMByte(1, RegOpcodeField, 4), OS);
-    ForceDisp8 = true; // Make sure to force 8 bit disp if Base=EBP
+    ForceDisp8 = true;
   } else {
-    // Emit the normal disp32 encoding.
+    // Otherwise, emit the normal disp32 encoding.
     emitByte(modRMByte(2, RegOpcodeField, 4), OS);
     ForceDisp32 = true;
   }
@@ -605,11 +621,6 @@ void X86MCCodeEmitter::emitMemModRMByte(const MCInst &MI, unsigned Op,
 
   unsigned IndexRegNo = IndexReg.getReg() ? getX86RegNum(IndexReg) : 4;
 
-  // Handle the SIB byte for the case where there is no base, see Intel
-  // Manual 2A, table 2-7. The displacement has already been output.
-  if (BaseReg == 0)
-    BaseRegNo = 5;
-
   emitSIBByte(SS, IndexRegNo, BaseRegNo, OS);
 
   // Do we need to output a displacement?

diff  --git a/llvm/test/MC/X86/x86-64.s b/llvm/test/MC/X86/x86-64.s
index 38d5c6173f3b..c61cae69c3ff 100644
--- a/llvm/test/MC/X86/x86-64.s
+++ b/llvm/test/MC/X86/x86-64.s
@@ -1904,3 +1904,91 @@ ud1 %rdx, %rdi
 // CHECK: ud1q (%rbx), %rcx
 // CHECK:  encoding: [0x48,0x0f,0xb9,0x0b]
 ud2b (%rbx), %rcx
+
+// Requires no displacement by default
+// CHECK: movl $1, (%rax)
+// CHECK: encoding: [0xc7,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%rax)
+// CHECK: encoding: [0xc7,0x40,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%rax)
+// CHECK: encoding: [0xc7,0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
+movl $1, (%rax)
+{disp8} movl $1, (%rax)
+{disp32} movl $1, (%rax)
+
+// Requires disp8 by default
+// CHECK: movl $1, (%rbp)
+// CHECK: encoding: [0xc7,0x45,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%rbp)
+// CHECK: encoding: [0xc7,0x45,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%rbp)
+// CHECK: encoding: [0xc7,0x85,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
+movl $1, (%rbp)
+{disp8} movl $1, (%rbp)
+{disp32} movl $1, (%rbp)
+
+// Requires disp8 by default
+// CHECK: movl $1, (%r13)
+// CHECK: encoding: [0x41,0xc7,0x45,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%r13)
+// CHECK: encoding: [0x41,0xc7,0x45,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%r13)
+// CHECK: encoding: [0x41,0xc7,0x85,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
+movl $1, (%r13)
+{disp8} movl $1, (%r13)
+{disp32} movl $1, (%r13)
+
+// Requires disp8 by default
+// CHECK: movl $1, 8(%rax)
+// CHECK: encoding: [0xc7,0x40,0x08,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, 8(%rax)
+// CHECK: encoding: [0xc7,0x40,0x08,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, 8(%rax)
+// CHECK: encoding: [0xc7,0x80,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
+movl $1, 8(%rax)
+{disp8} movl $1, 8(%rax)
+{disp32} movl $1, 8(%rax)
+
+// Requires no displacement by default
+// CHECK: movl $1, (%rax,%rbx,4)
+// CHECK: encoding: [0xc7,0x04,0x98,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%rax,%rbx,4)
+// CHECK: encoding: [0xc7,0x44,0x98,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%rax,%rbx,4)
+// CHECK: encoding: [0xc7,0x84,0x98,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
+movl $1, (%rax,%rbx,4)
+{disp8} movl $1, (%rax,%rbx,4)
+{disp32} movl $1, (%rax,%rbx,4)
+
+// Requires disp8 by default.
+// CHECK: movl $1, 8(%rax,%rbx,4)
+// CHECK: encoding: [0xc7,0x44,0x98,0x08,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, 8(%rax,%rbx,4)
+// CHECK: encoding: [0xc7,0x44,0x98,0x08,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, 8(%rax,%rbx,4)
+// CHECK: encoding: [0xc7,0x84,0x98,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
+movl $1, 8(%rax,%rbx,4)
+{disp8} movl $1, 8(%rax,%rbx,4)
+{disp32} movl $1, 8(%rax,%rbx,4)
+
+// Requires disp8 by default.
+// CHECK: movl $1, (%rbp,%rbx,4)
+// CHECK: encoding: [0xc7,0x44,0x9d,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%rbp,%rbx,4)
+// CHECK: encoding: [0xc7,0x44,0x9d,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%rbp,%rbx,4)
+// CHECK: encoding: [0xc7,0x84,0x9d,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
+movl $1, (%rbp,%rbx,4)
+{disp8} movl $1, (%rbp,%rbx,4)
+{disp32} movl $1, (%rbp,%rbx,4)
+
+// Requires disp8 by default.
+// CHECK: movl $1, (%r13,%rbx,4)
+// CHECK: encoding: [0x41,0xc7,0x44,0x9d,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%r13,%rbx,4)
+// CHECK: encoding: [0x41,0xc7,0x44,0x9d,0x00,0x01,0x00,0x00,0x00]
+// CHECK: movl $1, (%r13,%rbx,4)
+// CHECK: encoding: [0x41,0xc7,0x84,0x9d,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00]
+movl $1, (%r13,%rbx,4)
+{disp8} movl $1, (%r13,%rbx,4)
+{disp32} movl $1, (%r13,%rbx,4)


        


More information about the llvm-commits mailing list