From ea7da50e5a7f291295c10d91fc3fdba76d339579 Mon Sep 17 00:00:00 2001 From: Andrew Lenharth Date: Sat, 1 Mar 2008 13:37:02 +0000 Subject: [PATCH] Add lock prefix support to x86. Also add the instructions necessary for the atomic ops. They are still marked pseudo, since I cannot figure out what format to use, but they are the correct opcode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47795 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86.td | 2 + lib/Target/X86/X86CodeEmitter.cpp | 3 ++ lib/Target/X86/X86InstrFormats.td | 2 + lib/Target/X86/X86InstrInfo.h | 6 ++- lib/Target/X86/X86InstrInfo.td | 81 +++++++++++++++++++++++++++++-- 5 files changed, 88 insertions(+), 6 deletions(-) diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index db1418fedb7..39ba093be74 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 894726cf35f..522891c7cd1 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 86a327d64fc..6a3c18c4495 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 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 o, Format f, dag outs, dag ins, string asm, list pattern> diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 7a1ab51fc38..839a0f248b6 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 98c58852508..87a001af89c 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 -- 2.34.1