[x86] Fix MOV8ao8 et al for 16-bit mode, fix up disassembler to understand
authorDavid Woodhouse <dwmw2@infradead.org>
Wed, 8 Jan 2014 12:58:24 +0000 (12:58 +0000)
committerDavid Woodhouse <dwmw2@infradead.org>
Wed, 8 Jan 2014 12:58:24 +0000 (12:58 +0000)
It seems there is no separate instruction class for having AdSize *and*
OpSize bits set, which is required in order to disambiguate between all
these instructions. So add that to the disassembler.

Hm, perhaps we do need an AdSize16 bit after all?

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198759 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h
lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
lib/Target/X86/X86InstrInfo.td
test/MC/X86/x86-16.s
utils/TableGen/X86DisassemblerTables.cpp
utils/TableGen/X86RecognizableInstr.cpp

index 1acaef1b9472f80eb0bcd88ef510f3566b4833c7..954a3d7ac55ba72017cf8bde2667c8606a5d3e07 100644 (file)
@@ -92,6 +92,8 @@ enum attributeBits {
                                         "operands change width")               \
   ENUM_ENTRY(IC_ADSIZE,             3,  "requires an ADSIZE prefix, so "       \
                                         "operands change width")               \
                                         "operands change width")               \
   ENUM_ENTRY(IC_ADSIZE,             3,  "requires an ADSIZE prefix, so "       \
                                         "operands change width")               \
+  ENUM_ENTRY(IC_OPSIZE_ADSIZE,      3,  "requires both OPSIZE and ADSIZE "     \
+                                        "prefixes")                            \
   ENUM_ENTRY(IC_XD,                 2,  "may say something about the opcode "  \
                                         "but not the operands")                \
   ENUM_ENTRY(IC_XS,                 2,  "may say something about the opcode "  \
   ENUM_ENTRY(IC_XD,                 2,  "may say something about the opcode "  \
                                         "but not the operands")                \
   ENUM_ENTRY(IC_XS,                 2,  "may say something about the opcode "  \
index ae4fc2b3b71bc08f3dcc90bd1bd8e801f86dc3a8..576b6e0eb649a885980b9cfffa805f5488ed45a7 100644 (file)
@@ -1165,11 +1165,16 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
 
   // Emit the address size opcode prefix as needed.
   bool need_address_override;
 
   // Emit the address size opcode prefix as needed.
   bool need_address_override;
-  // The AdSize prefix is only for 32-bit and 64-bit modes; in 16-bit mode we
-  // need the address override only for JECXZ instead. Since it's only one
-  // instruction, we special-case it rather than introducing an AdSize16 bit.
+  // The AdSize prefix is only for 32-bit and 64-bit modes. Hm, perhaps we
+  // should introduce an AdSize16 bit instead of having seven special cases?
   if ((!is16BitMode() && TSFlags & X86II::AdSize) ||
   if ((!is16BitMode() && TSFlags & X86II::AdSize) ||
-      (is16BitMode() && MI.getOpcode() == X86::JECXZ_32)) {
+      (is16BitMode() && (MI.getOpcode() == X86::JECXZ_32 ||
+                         MI.getOpcode() == X86::MOV8o8a ||
+                         MI.getOpcode() == X86::MOV16o16a ||
+                         MI.getOpcode() == X86::MOV32o32a ||
+                         MI.getOpcode() == X86::MOV8ao8 ||
+                         MI.getOpcode() == X86::MOV16ao16 ||
+                         MI.getOpcode() == X86::MOV32ao32))) {
     need_address_override = true;
   } else if (MemOperand == -1) {
     need_address_override = false;
     need_address_override = true;
   } else if (MemOperand == -1) {
     need_address_override = false;
index 130ead8db30684a16223aeea0fd30eb0df9534c1..b4955646666790a3c6128af948085fab2ca66844 100644 (file)
@@ -1140,29 +1140,49 @@ def MOV64mi32 : RIi32<0xC7, MRM0m, (outs), (ins i64mem:$dst, i64i32imm:$src),
 let hasSideEffects = 0 in {
 
 /// moffs8, moffs16 and moffs32 versions of moves.  The immediate is a
 let hasSideEffects = 0 in {
 
 /// moffs8, moffs16 and moffs32 versions of moves.  The immediate is a
-/// 32-bit offset from the PC.  These are only valid in x86-32 mode.
+/// 32-bit offset from the segment base. These are only valid in x86-32 mode.
 let SchedRW = [WriteALU] in {
 let mayLoad = 1 in {
 def MOV8o8a : Ii32 <0xA0, RawFrm, (outs), (ins offset8:$src),
                    "mov{b}\t{$src, %al|al, $src}", [], IIC_MOV_MEM>,
 let SchedRW = [WriteALU] in {
 let mayLoad = 1 in {
 def MOV8o8a : Ii32 <0xA0, RawFrm, (outs), (ins offset8:$src),
                    "mov{b}\t{$src, %al|al, $src}", [], IIC_MOV_MEM>,
-                   Requires<[Not64BitMode]>;
+                   Requires<[In32BitMode]>;
 def MOV16o16a : Ii32 <0xA1, RawFrm, (outs), (ins offset16:$src),
                       "mov{w}\t{$src, %ax|ax, $src}", [], IIC_MOV_MEM>, OpSize,
 def MOV16o16a : Ii32 <0xA1, RawFrm, (outs), (ins offset16:$src),
                       "mov{w}\t{$src, %ax|ax, $src}", [], IIC_MOV_MEM>, OpSize,
-                     Requires<[Not64BitMode]>;
+                     Requires<[In32BitMode]>;
 def MOV32o32a : Ii32 <0xA1, RawFrm, (outs), (ins offset32:$src),
                       "mov{l}\t{$src, %eax|eax, $src}", [], IIC_MOV_MEM>,
 def MOV32o32a : Ii32 <0xA1, RawFrm, (outs), (ins offset32:$src),
                       "mov{l}\t{$src, %eax|eax, $src}", [], IIC_MOV_MEM>,
-                      OpSize16, Requires<[Not64BitMode]>;
+                      OpSize16, Requires<[In32BitMode]>;
+
+def MOV8o8a_16 : Ii16 <0xA0, RawFrm, (outs), (ins offset8:$src),
+                   "mov{b}\t{$src, %al|al, $src}", [], IIC_MOV_MEM>,
+                   AdSize, Requires<[In16BitMode]>;
+def MOV16o16a_16 : Ii16 <0xA1, RawFrm, (outs), (ins offset16:$src),
+                      "mov{w}\t{$src, %ax|ax, $src}", [], IIC_MOV_MEM>, OpSize,
+                     AdSize, Requires<[In16BitMode]>;
+def MOV32o32a_16 : Ii16 <0xA1, RawFrm, (outs), (ins offset32:$src),
+                      "mov{l}\t{$src, %eax|eax, $src}", [], IIC_MOV_MEM>,
+                      AdSize, OpSize16, Requires<[In16BitMode]>;
 }
 let mayStore = 1 in {
 def MOV8ao8 : Ii32 <0xA2, RawFrm, (outs offset8:$dst), (ins),
                    "mov{b}\t{%al, $dst|$dst, al}", [], IIC_MOV_MEM>,
 }
 let mayStore = 1 in {
 def MOV8ao8 : Ii32 <0xA2, RawFrm, (outs offset8:$dst), (ins),
                    "mov{b}\t{%al, $dst|$dst, al}", [], IIC_MOV_MEM>,
-                  Requires<[Not64BitMode]>;
+                  Requires<[In32BitMode]>;
 def MOV16ao16 : Ii32 <0xA3, RawFrm, (outs offset16:$dst), (ins),
                       "mov{w}\t{%ax, $dst|$dst, ax}", [], IIC_MOV_MEM>, OpSize,
 def MOV16ao16 : Ii32 <0xA3, RawFrm, (outs offset16:$dst), (ins),
                       "mov{w}\t{%ax, $dst|$dst, ax}", [], IIC_MOV_MEM>, OpSize,
-                     Requires<[Not64BitMode]>;
+                     Requires<[In32BitMode]>;
 def MOV32ao32 : Ii32 <0xA3, RawFrm, (outs offset32:$dst), (ins),
                       "mov{l}\t{%eax, $dst|$dst, eax}", [], IIC_MOV_MEM>,
 def MOV32ao32 : Ii32 <0xA3, RawFrm, (outs offset32:$dst), (ins),
                       "mov{l}\t{%eax, $dst|$dst, eax}", [], IIC_MOV_MEM>,
-                     OpSize16, Requires<[Not64BitMode]>;
+                     OpSize16, Requires<[In32BitMode]>;
+
+def MOV8ao8_16 : Ii16 <0xA2, RawFrm, (outs offset8:$dst), (ins),
+                   "mov{b}\t{%al, $dst|$dst, al}", [], IIC_MOV_MEM>,
+                  AdSize, Requires<[In16BitMode]>;
+def MOV16ao16_16 : Ii16 <0xA3, RawFrm, (outs offset16:$dst), (ins),
+                      "mov{w}\t{%ax, $dst|$dst, ax}", [], IIC_MOV_MEM>, OpSize,
+                     AdSize, Requires<[In16BitMode]>;
+def MOV32ao32_16 : Ii16 <0xA3, RawFrm, (outs offset32:$dst), (ins),
+                      "mov{l}\t{%eax, $dst|$dst, eax}", [], IIC_MOV_MEM>,
+                     OpSize16, AdSize, Requires<[In16BitMode]>;
 }
 }
 
 }
 }
 
index 4f2108cbde1f9953353647f9861ec50060f0d97a..1910f46378f0e0794b1d484005c088118c3b87aa 100644 (file)
 // CHECK: shll %eax                    # encoding: [0x66,0xd1,0xe0]
         sal $1, %eax
 
 // CHECK: shll %eax                    # encoding: [0x66,0xd1,0xe0]
         sal $1, %eax
 
+// moffset forms of moves
+
+// CHECK: movb 0, %al  # encoding: [0xa0,0x00,0x00]
+movb   0, %al
+
+// CHECK: movw 0, %ax  # encoding: [0xa1,0x00,0x00]
+movw   0, %ax
+
+// CHECK: movl 0, %eax  # encoding: [0x66,0xa1,0x00,0x00]
+movl   0, %eax
+
 into
 // CHECK: into
 // CHECK:  encoding: [0xce]
 into
 // CHECK: into
 // CHECK:  encoding: [0xce]
index 6ef924a882f82bc00b165c4f27ac1269416798b0..4c7066432a8d431d93dfcd6b9cf12b44e73386cc 100644 (file)
@@ -94,8 +94,11 @@ static inline bool inheritsFrom(InstructionContext child,
            inheritsFrom(child, IC_64BIT_XD)     ||
            inheritsFrom(child, IC_64BIT_XS));
   case IC_OPSIZE:
            inheritsFrom(child, IC_64BIT_XD)     ||
            inheritsFrom(child, IC_64BIT_XS));
   case IC_OPSIZE:
-    return inheritsFrom(child, IC_64BIT_OPSIZE);
+    return (inheritsFrom(child, IC_64BIT_OPSIZE) ||
+            inheritsFrom(child, IC_OPSIZE_ADSIZE));
   case IC_ADSIZE:
   case IC_ADSIZE:
+    return inheritsFrom(child, IC_OPSIZE_ADSIZE);
+  case IC_OPSIZE_ADSIZE:
   case IC_64BIT_ADSIZE:
     return false;
   case IC_XD:
   case IC_64BIT_ADSIZE:
     return false;
   case IC_XD:
index 1df04224376c0f24d08d7ed5af132b8755e15c0e..ab97a5f5433c767768679d875eb9842c00b713b8 100644 (file)
@@ -456,6 +456,8 @@ InstructionContext RecognizableInstr::insnContext() const {
     else if (HasOpSizePrefix &&
              (Prefix == X86Local::XS || Prefix == X86Local::T8XS))
       insnContext = IC_XS_OPSIZE;
     else if (HasOpSizePrefix &&
              (Prefix == X86Local::XS || Prefix == X86Local::T8XS))
       insnContext = IC_XS_OPSIZE;
+    else if (HasOpSizePrefix && HasAdSizePrefix)
+      insnContext = IC_OPSIZE_ADSIZE;
     else if (HasOpSizePrefix)
       insnContext = IC_OPSIZE;
     else if (HasAdSizePrefix)
     else if (HasOpSizePrefix)
       insnContext = IC_OPSIZE;
     else if (HasAdSizePrefix)