summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/X86/X86.td2
-rw-r--r--lib/Target/X86/X86CodeEmitter.cpp3
-rw-r--r--lib/Target/X86/X86InstrFormats.td2
-rw-r--r--lib/Target/X86/X86InstrInfo.h6
-rw-r--r--lib/Target/X86/X86InstrInfo.td81
5 files changed, 88 insertions, 6 deletions
diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td
index db1418fedb..39ba093be7 100644
--- a/lib/Target/X86/X86.td
+++ b/lib/Target/X86/X86.td
@@ -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];
}
diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp
index 894726cf35..522891c7cd 100644
--- a/lib/Target/X86/X86CodeEmitter.cpp
+++ b/lib/Target/X86/X86CodeEmitter.cpp
@@ -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);
diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td
index 86a327d64f..6a3c18c449 100644
--- a/lib/Target/X86/X86InstrFormats.td
+++ b/lib/Target/X86/X86InstrFormats.td
@@ -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>
diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h
index 7a1ab51fc3..839a0f248b 100644
--- a/lib/Target/X86/X86InstrInfo.h
+++ b/lib/Target/X86/X86InstrInfo.h
@@ -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
};
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 98c5885250..87a001af89 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -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