Add lock prefix support to x86. Also add the instructions necessary for the atomic...
authorAndrew Lenharth <andrewl@lenharth.org>
Sat, 1 Mar 2008 13:37:02 +0000 (13:37 +0000)
committerAndrew Lenharth <andrewl@lenharth.org>
Sat, 1 Mar 2008 13:37:02 +0000 (13:37 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47795 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86.td
lib/Target/X86/X86CodeEmitter.cpp
lib/Target/X86/X86InstrFormats.td
lib/Target/X86/X86InstrInfo.h
lib/Target/X86/X86InstrInfo.td

index db1418fedb72bbc7130cc147779b3a46878352f1..39ba093be743be4e1b4605bd20124f70ec00d25d 100644 (file)
@@ -115,6 +115,7 @@ def X86InstrInfo : InstrInfo {
                        "hasREX_WPrefix",
                        "ImmTypeBits",
                        "FPFormBits",
+                       "hasLockPrefix",
                        "Opcode"];
   let TSFlagsShifts = [0,
                        6,
@@ -123,6 +124,7 @@ def X86InstrInfo : InstrInfo {
                        12,
                        13,
                        16,
+                       19,
                        24];
 }
 
index 894726cf35f755d9f585abed942b52318dd44d62..522891c7cd15876936e1e7ff46960d323e1cf2c6 100644 (file)
@@ -540,6 +540,9 @@ void Emitter::emitInstruction(const MachineInstr &MI,
                               const TargetInstrDesc *Desc) {
   unsigned Opcode = Desc->Opcode;
 
+  // Emit the lock opcode prefix as needed.
+  if (Desc->TSFlags & X86II::LOCK) MCE.emitByte(0xF0);
+
   // Emit the repeat opcode prefix as needed.
   if ((Desc->TSFlags & X86II::Op0Mask) == X86II::REP) MCE.emitByte(0xF3);
 
index 86a327d64fc713b115883a0f319966573736a327..6a3c18c449585ff44bd4f057711cafce28fea218 100644 (file)
@@ -62,6 +62,7 @@ def SpecialFP  : FPFormat<7>;
 class OpSize { bit hasOpSizePrefix = 1; }
 class AdSize { bit hasAdSizePrefix = 1; }
 class REX_W  { bit hasREX_WPrefix = 1; }
+class LOCK   { bit hasLockPrefix = 1; }
 class TB     { bits<4> Prefix = 1; }
 class REP    { bits<4> Prefix = 2; }
 class D8     { bits<4> Prefix = 3; }
@@ -102,6 +103,7 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
   bit hasREX_WPrefix  = 0;  // Does this inst requires the REX.W prefix?
   FPFormat FPForm;          // What flavor of FP instruction is this?
   bits<3> FPFormBits = 0;
+  bit hasLockPrefix = 0;  // Does this inst have a 0xF0 prefix?
 }
 
 class I<bits<8> o, Format f, dag outs, dag ins, string asm, list<dag> pattern>
index 7a1ab51fc38625826eb27f07330010efe1a74ca7..839a0f248b6bffaecc1bfe311fa143c238e4f2a0 100644 (file)
@@ -216,7 +216,11 @@ namespace X86II {
     // SpecialFP - Special instruction forms.  Dispatch by opcode explicitly.
     SpecialFP  = 7 << FPTypeShift,
 
-    // Bits 19 -> 23 are unused
+    // Lock prefix
+    LOCKShift = 19,
+    LOCK = 1 << LOCKShift,
+
+    // Bits 20 -> 23 are unused
     OpcodeShift   = 24,
     OpcodeMask    = 0xFF << OpcodeShift
   };
index 98c588525086a6805a7745f4f7defd4d71bb2347..87a001af89c1a0fd460f82fda08f30b857f7bea4 100644 (file)
@@ -2538,11 +2538,82 @@ def EH_RETURN   : I<0xC3, RawFrm, (outs), (ins GR32:$addr),
 //===----------------------------------------------------------------------===//
 // Atomic support
 //
-let Defs = [EAX] in
-def LCMPXCHGL : I<0, Pseudo, (outs GR32:$dst), 
-                  (ins GR32:$ptr, GR32:$cmp, GR32:$swap),
-                  "movl $cmp, %eax ; lock cmpxchgl $swap,($ptr) ; movl %eax, $dst",
-                  [(set GR32:$dst, (atomic_lcs_32 GR32:$ptr, GR32:$cmp, GR32:$swap))]>;
+
+//FIXME: Please check the format
+
+let Defs = [EAX], Uses = [EAX] in {
+def CMPXCHG32 : I<0xB1, Pseudo, (outs), (ins GR32:$ptr, GR32:$swap),
+               "cmpxchgl $swap,($ptr)", []>, TB;
+def LCMPXCHG32 : I<0xB1, Pseudo, (outs), (ins GR32:$ptr, GR32:$swap),
+               "lock cmpxchgl $swap,($ptr)", []>, TB, LOCK;
+}
+let Defs = [AX], Uses = [AX] in {
+def CMPXCHG16 : I<0xB1, Pseudo, (outs), (ins GR32:$ptr, GR16:$swap),
+               "cmpxchgw $swap,($ptr)", []>, TB, OpSize;
+def LCMPXCHG16 : I<0xB1, Pseudo, (outs), (ins GR32:$ptr, GR16:$swap),
+               "cmpxchgw $swap,($ptr)", []>, TB, OpSize, LOCK;
+}
+let Defs = [AL], Uses = [AL] in {
+def CMPXCHG8 : I<0xB0, Pseudo, (outs), (ins GR32:$ptr, GR8:$swap),
+               "cmpxchgb $swap,($ptr)", []>, TB;
+def LCMPXCHG8 : I<0xB0, Pseudo, (outs), (ins GR32:$ptr, GR8:$swap),
+               "cmpxchgb $swap,($ptr)", []>, TB, LOCK;
+}
+
+let Constraints = "$val = $dst" in {
+def LXADD32 : I<0xC1, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
+               "lock xadd $val, $ptr", 
+               [(set GR32:$dst, (atomic_las_32 addr:$ptr, GR32:$val))]>,
+                TB, LOCK;
+def LXADD16 : I<0xC1, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val),
+               "lock xadd $val, $ptr", 
+               [(set GR16:$dst, (atomic_las_16 addr:$ptr, GR16:$val))]>,
+                TB, OpSize, LOCK;
+def LXADD8  : I<0xC0, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val),
+               "lock xadd $val, $ptr", 
+               [(set GR8:$dst, (atomic_las_8 addr:$ptr, GR8:$val))]>,
+                TB, LOCK;
+def XADD32 : I<0xC1, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
+               "lock xadd $val, $ptr", []>, TB;
+def XADD16 : I<0xC1, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val),
+               "lock xadd $val, $ptr", []>, TB, OpSize;
+def XADD8  : I<0xC0, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val),
+               "lock xadd $val, $ptr", []>, TB;
+
+def LXCHG32 : I<0x87, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
+               "lock xchg $val, $ptr", 
+               [(set GR32:$dst, (atomic_swap_32 addr:$ptr, GR32:$val))]>, LOCK;
+def LXCHG16 : I<0x87, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val),
+               "lock xchg $val, $ptr", 
+               [(set GR16:$dst, (atomic_swap_16 addr:$ptr, GR16:$val))]>, 
+                OpSize, LOCK;
+def LXCHG8  : I<0x86, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val),
+               "lock xchg $val, $ptr", 
+               [(set GR8:$dst, (atomic_swap_8 addr:$ptr, GR8:$val))]>, LOCK;
+def XCHG32 : I<0x87, Pseudo, (outs GR32:$dst), (ins i32mem:$ptr, GR32:$val),
+               "lock xchg $val, $ptr", []>;
+def XCHG16 : I<0x87, Pseudo, (outs GR16:$dst), (ins i16mem:$ptr, GR16:$val),
+               "lock xchg $val, $ptr", []>, OpSize;
+def XCHG8  : I<0x86, Pseudo, (outs GR8:$dst), (ins i8mem:$ptr, GR8:$val),
+               "lock xchg $val, $ptr", []>;
+}
+
+//FIXME: these are a hack until the patterns using the LCMPXCHG written
+let Defs = [EAX], Uses = [EAX] in
+def PLCMPXCHG32 : I<0, Pseudo, (outs GR32:$dst), 
+                  (ins i32mem:$ptr, GR32:$cmp, GR32:$swap),
+                  "movl $cmp, %eax \n lock \n cmpxchgl $swap,$ptr \n movl %eax, $dst",
+                  [(set GR32:$dst, (atomic_lcs_32 addr:$ptr, GR32:$cmp, GR32:$swap))]>;
+let Defs = [AX] in
+def PLCMPXCHG16 : I<0, Pseudo, (outs GR16:$dst), 
+                  (ins i16mem:$ptr, GR16:$cmp, GR16:$swap),
+                  "movw $cmp, %ax \n lock \n cmpxchgw $swap,$ptr \n movw %ax, $dst",
+                  [(set GR16:$dst, (atomic_lcs_16 addr:$ptr, GR16:$cmp, GR16:$swap))]>;
+let Defs = [AL] in
+def PLCMPXCHG8 : I<0, Pseudo, (outs GR8:$dst), 
+                  (ins i8mem:$ptr, GR8:$cmp, GR8:$swap),
+                  "movb $cmp, %al \n lock cmpxchgb $swap,$ptr \n movb %al, $dst",
+                  [(set GR8:$dst, (atomic_lcs_8 addr:$ptr, GR8:$cmp, GR8:$swap))]>;
 
 //===----------------------------------------------------------------------===//
 // Non-Instruction Patterns