Index: llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -1175,7 +1175,8 @@ Parser.getTok().getLoc())); Parser.Lex(); // Eat the [ - if (Mnemonic == "cas" || Mnemonic == "casx" || Mnemonic == "casa") { + if (Mnemonic == "cas" || Mnemonic == "casl" || Mnemonic == "casa" || + Mnemonic == "casx" || Mnemonic == "casxl" || Mnemonic == "casxa") { SMLoc S = Parser.getTok().getLoc(); if (getLexer().getKind() != AsmToken::Percent) return MatchOperand_NoMatch; Index: llvm/lib/Target/Sparc/SparcInstr64Bit.td =================================================================== --- llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ llvm/lib/Target/Sparc/SparcInstr64Bit.td @@ -475,14 +475,34 @@ } // ATOMICS. -let Predicates = [Is64Bit], Constraints = "$swap = $rd", asi = 0b10000000 in { - def CASXrr: F3_1_asi<3, 0b111110, +let Predicates = [Is64Bit, HasV9], Constraints = "$swap = $rd" in { + let asi = 0b10000000 in + def CASXrr: F3_1_asi<3, 0b111110, (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2, I64Regs:$swap), "casx [$rs1], $rs2, $rd", [(set i64:$rd, (atomic_cmp_swap_64 i64:$rs1, i64:$rs2, i64:$swap))]>; + let asi = 0b10001000 in + def CASXLrr: F3_1_asi<3, 0b111110, + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2, + I64Regs:$swap), + "casxl [$rs1], $rs2, $rd", + []>; + + def CASXArr: F3_1_asi<3, 0b111110, + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2, + I64Regs:$swap, ASITag:$asi), + "casxa [$rs1] $asi, $rs2, $rd", + []>; + + let Uses = [ASR3] in + def CASXAri: F3_1_cas_asi<3, 0b111110, + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2, + I64Regs:$swap), + "casxa [$rs1] %asi, $rs2, $rd", + []>; } // Predicates = [Is64Bit], Constraints = ... let Predicates = [Is64Bit] in { Index: llvm/lib/Target/Sparc/SparcInstrFormats.td =================================================================== --- llvm/lib/Target/Sparc/SparcInstrFormats.td +++ llvm/lib/Target/Sparc/SparcInstrFormats.td @@ -135,6 +135,14 @@ let Inst{4-0} = rs2; } +// CAS instructions does not use an immediate even when i=1 +class F3_1_cas_asi opVal, bits<6> op3val, dag outs, dag ins, + string asmstr, list pattern, InstrItinClass itin = NoItinerary> + : F3_1_asi { + let asi = 0; + let Inst{13} = 1; // i field = 1 +} + class F3_1 opVal, bits<6> op3val, dag outs, dag ins, string asmstr, list pattern, InstrItinClass itin = IIC_iu_instr> : F3_1_asi { Index: llvm/lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- llvm/lib/Target/Sparc/SparcInstrInfo.td +++ llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -51,10 +51,14 @@ // point instructions. def HasHardQuad : Predicate<"Subtarget->hasHardQuad()">; -// HasLeonCASA - This is true when the target processor supports the CASA -// instruction +// HasLeonCASA - This is true when the target processor supports the Leon CASA +// instruction. def HasLeonCASA : Predicate<"Subtarget->hasLeonCasa()">; +// HasCASA - This is true when the target processor supports CASA instruction. +def HasCASA : Predicate<"Subtarget->hasLeonCasa() || Subtarget->isV9()">, + AssemblerPredicate<(any_of LeonCASA, FeatureV9)>; + // HasPWRPSR - This is true when the target processor supports partial // writes to the PSR register that only affects the ET field. def HasPWRPSR : Predicate<"Subtarget->hasPWRPSR()">, @@ -1700,16 +1704,26 @@ "sir $simm13", []>; // The CAS instruction, unlike other instructions, only comes in a -// form which requires an ASI be provided. The ASI value hardcoded -// here is ASI_PRIMARY, the default unprivileged ASI for SparcV9. -let Predicates = [HasV9], Constraints = "$swap = $rd", asi = 0b10000000 in - def CASrr: F3_1_asi<3, 0b111100, +// form which requires an ASI be provided. +let Predicates = [HasV9], Constraints = "$swap = $rd" in { + // The ASI value hardcoded here is ASI_PRIMARY, the default + // unprivileged ASI for SparcV9. + let asi = 0b10000000 in + def CASrr: F3_1_asi<3, 0b111100, (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, IntRegs:$swap), "cas [$rs1], $rs2, $rd", [(set i32:$rd, (atomic_cmp_swap_32 iPTR:$rs1, i32:$rs2, i32:$swap))]>; + // SparcV9 also specifies a CASL alias, which uses ASI_PRIMARY_LITTLE. + let asi = 0b10001000 in + def CASLrr: F3_1_asi<3, 0b111100, + (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, + IntRegs:$swap), + "casl [$rs1], $rs2, $rd", + []>; +} // CASA is supported as an instruction on some LEON3 and all LEON4 processors. // This version can be automatically lowered from C code, selecting ASI 10 @@ -1721,15 +1735,23 @@ [(set i32:$rd, (atomic_cmp_swap_32 iPTR:$rs1, i32:$rs2, i32:$swap))]>; -// CASA supported on some LEON3 and all LEON4 processors. Same pattern as -// CASrr, above, but with a different ASI. This version is supported for -// inline assembly lowering only. -let Predicates = [HasLeonCASA], Constraints = "$swap = $rd" in +// CASA supported on all V9, some LEON3 and all LEON4 processors. +// Same pattern as CASrr above, but with a different ASI. +// This version is supported for inline assembly lowering only. +let Predicates = [HasCASA], Constraints = "$swap = $rd" in def CASArr: F3_1_asi<3, 0b111100, (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, IntRegs:$swap, ASITag:$asi), "casa [$rs1] $asi, $rs2, $rd", []>; +// On the other hand, CASA that takes its ASI from a register +// is only supported on V9 processors. +let Predicates = [HasV9], Uses = [ASR3], Constraints = "$swap = $rd" in + def CASAri: F3_1_cas_asi<3, 0b111100, + (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, + IntRegs:$swap), + "casa [$rs1] %asi, $rs2, $rd", []>; + // TODO: Add DAG sequence to lower these instructions. Currently, only provided // as inline assembler-supported instructions. let Predicates = [HasUMAC_SMAC], Defs = [Y, ASR18], Uses = [Y, ASR18] in { Index: llvm/test/MC/Disassembler/Sparc/sparc-atomics.txt =================================================================== --- /dev/null +++ llvm/test/MC/Disassembler/Sparc/sparc-atomics.txt @@ -0,0 +1,25 @@ +# RUN: llvm-mc --disassemble %s -triple=sparcv9-unknown-linux | FileCheck %s + +# CHECK: cas [%i0], %l6, %o2 +0xd5,0xe6,0x10,0x16 + +# CHECK: casl [%i0], %l6, %o2 +0xd5,0xe6,0x11,0x16 + +# CHECK: casa [%i0] 255, %l6, %o2 +0xd5,0xe6,0x1f,0xf6 + +# CHECK: casa [%i0] %asi, %l6, %o2 +0xd5,0xe6,0x20,0x16 + +# CHECK: casx [%i0], %l6, %o2 +0xd5,0xf6,0x10,0x16 + +# CHECK: casxl [%i0], %l6, %o2 +0xd5,0xf6,0x11,0x16 + +# CHECK: casxa [%i0] 255, %l6, %o2 +0xd5,0xf6,0x1f,0xf6 + +# CHECK: casxa [%i0] %asi, %l6, %o2 +0xd5,0xf6,0x20,0x16 Index: llvm/test/MC/Sparc/leon-instructions.s =================================================================== --- llvm/test/MC/Sparc/leon-instructions.s +++ llvm/test/MC/Sparc/leon-instructions.s @@ -1,20 +1,11 @@ -! RUN: llvm-mc %s -arch=sparc -mcpu=leon3 -show-encoding | FileCheck %s -check-prefix=CHECK_NO_CASA -! RUN: llvm-mc %s -arch=sparc -mcpu=ut699 -show-encoding | FileCheck %s -check-prefix=CHECK_NO_CASA +! RUN: llvm-mc %s -arch=sparc -mcpu=leon3 -show-encoding | FileCheck %s +! RUN: llvm-mc %s -arch=sparc -mcpu=ut699 -show-encoding | FileCheck %s ! RUN: llvm-mc %s -arch=sparc -mcpu=gr712rc -show-encoding | FileCheck %s ! RUN: llvm-mc %s -arch=sparc -mcpu=leon4 -show-encoding | FileCheck %s ! RUN: llvm-mc %s -arch=sparc -mcpu=gr740 -show-encoding | FileCheck %s - - ! CHECK: casa [%i0] 10, %l6, %o2 ! encoding: [0xd5,0xe6,0x01,0x56] - casa [%i0] 10, %l6, %o2 - - ! CHECK: casa [%i0] 5, %l6, %o2 ! encoding: [0xd5,0xe6,0x00,0xb6] - casa [%i0] 5, %l6, %o2 - ! CHECK: umac %i0, %l6, %o2 ! encoding: [0x95,0xf6,0x00,0x16] - ! CHECK_NO_CASA: umac %i0, %l6, %o2 ! encoding: [0x95,0xf6,0x00,0x16] umac %i0, %l6, %o2 ! CHECK: smac %i0, %l6, %o2 ! encoding: [0x95,0xfe,0x00,0x16] - ! CHECK_NO_CASA: smac %i0, %l6, %o2 ! encoding: [0x95,0xfe,0x00,0x16] smac %i0, %l6, %o2 Index: llvm/test/MC/Sparc/sparc-cas-instructions.s =================================================================== --- /dev/null +++ llvm/test/MC/Sparc/sparc-cas-instructions.s @@ -0,0 +1,53 @@ +! RUN: not llvm-mc %s -arch=sparc -show-encoding 2>&1 | FileCheck %s --check-prefix=V8 +! RUN: not llvm-mc %s -arch=sparc -mattr=+hasleoncasa -show-encoding 2>&1 | FileCheck %s --check-prefix=LEON +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s --check-prefix=V9 + +! V8: error: instruction requires a CPU feature not currently enabled +! V9: cas [%i0], %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16] +! LEON: error: instruction requires a CPU feature not currently enabled +cas [%i0], %l6, %o2 + +! V8: error: instruction requires a CPU feature not currently enabled +! V9: casl [%i0], %l6, %o2 ! encoding: [0xd5,0xe6,0x11,0x16] +! LEON: error: instruction requires a CPU feature not currently enabled +casl [%i0], %l6, %o2 + +! V8: error: instruction requires a CPU feature not currently enabled +! V9: casx [%i0], %l6, %o2 ! encoding: [0xd5,0xf6,0x10,0x16] +! LEON: error: instruction requires a CPU feature not currently enabled +casx [%i0], %l6, %o2 + +! V8: error: instruction requires a CPU feature not currently enabled +! V9: casxl [%i0], %l6, %o2 ! encoding: [0xd5,0xf6,0x11,0x16] +! LEON: error: instruction requires a CPU feature not currently enabled +casxl [%i0], %l6, %o2 + +! V8: error: malformed ASI tag, must be a constant integer expression +! V9: casxa [%i0] %asi, %l6, %o2 ! encoding: [0xd5,0xf6,0x20,0x16] +! LEON: error: malformed ASI tag, must be a constant integer expression +casxa [%i0] %asi, %l6, %o2 + +! V8: error: instruction requires a CPU feature not currently enabled +! V9: casxa [%i0] 128, %l6, %o2 ! encoding: [0xd5,0xf6,0x10,0x16] +! LEON: error: instruction requires a CPU feature not currently enabled +casxa [%i0] 0x80, %l6, %o2 + +! V8: error: instruction requires a CPU feature not currently enabled +! V9: casxa [%i0] 128, %l6, %o2 ! encoding: [0xd5,0xf6,0x10,0x16] +! LEON: error: instruction requires a CPU feature not currently enabled +casxa [%i0] (0x40+0x40), %l6, %o2 + +! V8: error: malformed ASI tag, must be a constant integer expression +! V9: casa [%i0] %asi, %l6, %o2 ! encoding: [0xd5,0xe6,0x20,0x16] +! LEON: error: malformed ASI tag, must be a constant integer expression +casa [%i0] %asi, %l6, %o2 + +! V8: error: instruction requires a CPU feature not currently enabled +! V9: casa [%i0] 128, %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16] +! LEON: casa [%i0] 128, %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16] +casa [%i0] 0x80, %l6, %o2 + +! V8: error: instruction requires a CPU feature not currently enabled +! V9: casa [%i0] 128, %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16] +! LEON: casa [%i0] 128, %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16] +casa [%i0] (0x40+0x40), %l6, %o2 Index: llvm/test/MC/Sparc/sparcv9-atomic-instructions.s =================================================================== --- llvm/test/MC/Sparc/sparcv9-atomic-instructions.s +++ llvm/test/MC/Sparc/sparcv9-atomic-instructions.s @@ -17,9 +17,3 @@ ! CHECK: ldstuba [%i0+2] %asi, %g1 ! encoding: [0xc2,0xee,0x20,0x02] ldstuba [%i0+2] %asi, %g1 - - ! CHECK: cas [%i0], %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16] - cas [%i0], %l6, %o2 - - ! CHECK: casx [%i0], %l6, %o2 ! encoding: [0xd5,0xf6,0x10,0x16] - casx [%i0], %l6, %o2