Index: llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -631,6 +631,15 @@ Operands.push_back(SparcOperand::CreateToken("]", Parser.getTok().getLoc())); Parser.Lex(); // Eat the ] + + // Parse an optional address-space identifier after the address. + if (getLexer().is(AsmToken::Integer)) { + std::unique_ptr Op; + ResTy = parseSparcAsmOperand(Op, false); + if (ResTy != MatchOperand_Success || !Op) + return MatchOperand_ParseFail; + Operands.push_back(std::move(Op)); + } return MatchOperand_Success; } Index: llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -279,6 +279,8 @@ unsigned rd = fieldFromInstruction(insn, 25, 5); unsigned rs1 = fieldFromInstruction(insn, 14, 5); bool isImm = fieldFromInstruction(insn, 13, 1); + bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field) + unsigned asi = fieldFromInstruction(insn, 5, 8); unsigned rs2 = 0; unsigned simm13 = 0; if (isImm) @@ -307,6 +309,9 @@ return status; } + if (hasAsi) + MI.addOperand(MCOperand::createImm(asi)); + if (!isLoad) { status = DecodeRD(MI, rd, Address, Decoder); if (status != MCDisassembler::Success) @@ -457,6 +462,8 @@ unsigned rd = fieldFromInstruction(insn, 25, 5); unsigned rs1 = fieldFromInstruction(insn, 14, 5); unsigned isImm = fieldFromInstruction(insn, 13, 1); + bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field) + unsigned asi = fieldFromInstruction(insn, 5, 8); unsigned rs2 = 0; unsigned simm13 = 0; if (isImm) @@ -482,5 +489,9 @@ if (status != MCDisassembler::Success) return status; } + + if (hasAsi) + MI.addOperand(MCOperand::createImm(asi)); + return MCDisassembler::Success; } Index: llvm/trunk/lib/Target/Sparc/SparcInstr64Bit.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcInstr64Bit.td +++ llvm/trunk/lib/Target/Sparc/SparcInstr64Bit.td @@ -486,8 +486,8 @@ } // ATOMICS. -let Predicates = [Is64Bit], Constraints = "$swap = $rd" in { - def CASXrr: F3_1_asi<3, 0b111110, 0b10000000, +let Predicates = [Is64Bit], Constraints = "$swap = $rd", asi = 0b10000000 in { + def CASXrr: F3_1_asi<3, 0b111110, (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2, I64Regs:$swap), "casx [$rs1], $rs2, $rd", Index: llvm/trunk/lib/Target/Sparc/SparcInstrFormats.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcInstrFormats.td +++ llvm/trunk/lib/Target/Sparc/SparcInstrFormats.td @@ -113,8 +113,9 @@ // Specific F3 classes: SparcV8 manual, page 44 // -class F3_1_asi opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins, +class F3_1_asi opVal, bits<6> op3val, dag outs, dag ins, string asmstr, list pattern> : F3 { + bits<8> asi; bits<5> rs2; let op = opVal; @@ -126,8 +127,10 @@ } class F3_1 opVal, bits<6> op3val, dag outs, dag ins, string asmstr, - list pattern> : F3_1_asi; + list pattern> : F3_1_asi { + let asi = 0; +} class F3_2 opVal, bits<6> op3val, dag outs, dag ins, string asmstr, list pattern> : F3 { Index: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td +++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td @@ -283,6 +283,17 @@ [(set Ty:$dst, (OpNode ADDRri:$addr))]>; } +// LoadA multiclass - As above, but also define alternate address space variant +multiclass LoadA Op3Val, bits<6> LoadAOp3Val, + SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> : + Load { + // TODO: The LD*Arr instructions are currently asm only; hooking up + // CodeGen's address spaces to use these is a future task. + def Arr : F3_1_asi<3, LoadAOp3Val, (outs RC:$dst), (ins MEMrr:$addr, i8imm:$asi), + !strconcat(OpcStr, "a [$addr] $asi, $dst"), + []>; +} + // Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot. multiclass Store Op3Val, SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> { @@ -296,6 +307,16 @@ [(OpNode Ty:$rd, ADDRri:$addr)]>; } +multiclass StoreA Op3Val, bits<6> StoreAOp3Val, + SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> : + Store { + // TODO: The ST*Arr instructions are currently asm only; hooking up + // CodeGen's address spaces to use these is a future task. + def Arr : F3_1_asi<3, StoreAOp3Val, (outs), (ins MEMrr:$addr, RC:$rd, i8imm:$asi), + !strconcat(OpcStr, "a $rd, [$addr] $asi"), + []>; +} + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -417,11 +438,11 @@ // Section B.1 - Load Integer Instructions, p. 90 let DecoderMethod = "DecodeLoadInt" in { - defm LDSB : Load<"ldsb", 0b001001, sextloadi8, IntRegs, i32>; - defm LDSH : Load<"ldsh", 0b001010, sextloadi16, IntRegs, i32>; - defm LDUB : Load<"ldub", 0b000001, zextloadi8, IntRegs, i32>; - defm LDUH : Load<"lduh", 0b000010, zextloadi16, IntRegs, i32>; - defm LD : Load<"ld", 0b000000, load, IntRegs, i32>; + defm LDSB : LoadA<"ldsb", 0b001001, 0b011001, sextloadi8, IntRegs, i32>; + defm LDSH : LoadA<"ldsh", 0b001010, 0b011010, sextloadi16, IntRegs, i32>; + defm LDUB : LoadA<"ldub", 0b000001, 0b010001, zextloadi8, IntRegs, i32>; + defm LDUH : LoadA<"lduh", 0b000010, 0b010010, zextloadi16, IntRegs, i32>; + defm LD : LoadA<"ld", 0b000000, 0b010000, load, IntRegs, i32>; } // Section B.2 - Load Floating-point Instructions, p. 92 @@ -435,9 +456,9 @@ // Section B.4 - Store Integer Instructions, p. 95 let DecoderMethod = "DecodeStoreInt" in { - defm STB : Store<"stb", 0b000101, truncstorei8, IntRegs, i32>; - defm STH : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>; - defm ST : Store<"st", 0b000100, store, IntRegs, i32>; + defm STB : StoreA<"stb", 0b000101, 0b010101, truncstorei8, IntRegs, i32>; + defm STH : StoreA<"sth", 0b000110, 0b010110, truncstorei16, IntRegs, i32>; + defm ST : StoreA<"st", 0b000100, 0b010100, store, IntRegs, i32>; } // Section B.5 - Store Floating-point Instructions, p. 97 @@ -1116,10 +1137,20 @@ (outs IntRegs:$dst), (ins MEMri:$addr, IntRegs:$val), "swap [$addr], $dst", [(set i32:$dst, (atomic_swap_32 ADDRri:$addr, i32:$val))]>; + def SWAPArr : F3_1_asi<3, 0b011111, + (outs IntRegs:$dst), (ins MEMrr:$addr, i8imm:$asi, IntRegs:$val), + "swapa [$addr] $asi, $dst", + [/*FIXME: pattern?*/]>; } -let Predicates = [HasV9], Constraints = "$swap = $rd" in - def CASrr: F3_1_asi<3, 0b111100, 0b10000000, +// TODO: Should add a CASArr variant. In fact, 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. (Also of note: some modern +// SparcV8 implementations provide CASA as an extension, but require +// the use of SparcV8's default ASI, 0xA ("User Data") instead.) +let Predicates = [HasV9], Constraints = "$swap = $rd", asi = 0b10000000 in + def CASrr: F3_1_asi<3, 0b111100, (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2, IntRegs:$swap), "cas [$rs1], $rs2, $rd", Index: llvm/trunk/test/MC/Disassembler/Sparc/sparc-mem.txt =================================================================== --- llvm/trunk/test/MC/Disassembler/Sparc/sparc-mem.txt +++ llvm/trunk/test/MC/Disassembler/Sparc/sparc-mem.txt @@ -215,3 +215,9 @@ # CHECK: swap [%g1], %o2 0xd4 0x78 0x40 0x00 + +# CHECK: swapa [%i0+%l6] 131, %o2 +0xd4 0xfe 0x10 0x76 + +# CHECK: swapa [%g1] 131, %o2 +0xd4 0xf8 0x50 0x60 Index: llvm/trunk/test/MC/Sparc/sparc-atomic-instructions.s =================================================================== --- llvm/trunk/test/MC/Sparc/sparc-atomic-instructions.s +++ llvm/trunk/test/MC/Sparc/sparc-atomic-instructions.s @@ -1,7 +1,5 @@ ! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s - - ! CHECK: membar 15 ! encoding: [0x81,0x43,0xe0,0x0f] - membar 15 +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s ! CHECK: stbar ! encoding: [0x81,0x43,0xc0,0x00] stbar @@ -12,8 +10,5 @@ ! CHECK: swap [%i0+32], %o2 ! encoding: [0xd4,0x7e,0x20,0x20] swap [%i0+32], %o2 - ! 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 + ! CHECK: swapa [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xfe,0x10,0x76] + swapa [%i0+%l6] 131, %o2 Index: llvm/trunk/test/MC/Sparc/sparc-mem-instructions.s =================================================================== --- llvm/trunk/test/MC/Sparc/sparc-mem-instructions.s +++ llvm/trunk/test/MC/Sparc/sparc-mem-instructions.s @@ -7,6 +7,8 @@ ldsb [%i0 + 32], %o2 ! CHECK: ldsb [%g1], %o4 ! encoding: [0xd8,0x48,0x40,0x00] ldsb [%g1], %o4 + ! CHECK: ldsba [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xce,0x10,0x76] + ldsba [%i0 + %l6] 131, %o2 ! CHECK: ldsh [%i0+%l6], %o2 ! encoding: [0xd4,0x56,0x00,0x16] ldsh [%i0 + %l6], %o2 @@ -14,6 +16,8 @@ ldsh [%i0 + 32], %o2 ! CHECK: ldsh [%g1], %o4 ! encoding: [0xd8,0x50,0x40,0x00] ldsh [%g1], %o4 + ! CHECK: ldsha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xd6,0x10,0x76] + ldsha [%i0 + %l6] 131, %o2 ! CHECK: ldub [%i0+%l6], %o2 ! encoding: [0xd4,0x0e,0x00,0x16] ldub [%i0 + %l6], %o2 @@ -21,6 +25,8 @@ ldub [%i0 + 32], %o2 ! CHECK: ldub [%g1], %o2 ! encoding: [0xd4,0x08,0x40,0x00] ldub [%g1], %o2 + ! CHECK: lduba [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x8e,0x10,0x76] + lduba [%i0 + %l6] 131, %o2 ! CHECK: lduh [%i0+%l6], %o2 ! encoding: [0xd4,0x16,0x00,0x16] lduh [%i0 + %l6], %o2 @@ -28,6 +34,8 @@ lduh [%i0 + 32], %o2 ! CHECK: lduh [%g1], %o2 ! encoding: [0xd4,0x10,0x40,0x00] lduh [%g1], %o2 + ! CHECK: lduha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x96,0x10,0x76] + lduha [%i0 + %l6] 131, %o2 ! CHECK: ld [%i0+%l6], %o2 ! encoding: [0xd4,0x06,0x00,0x16] ld [%i0 + %l6], %o2 @@ -35,6 +43,8 @@ ld [%i0 + 32], %o2 ! CHECK: ld [%g1], %o2 ! encoding: [0xd4,0x00,0x40,0x00] ld [%g1], %o2 + ! CHECK: lda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x86,0x10,0x76] + lda [%i0 + %l6] 131, %o2 ! CHECK: stb %o2, [%i0+%l6] ! encoding: [0xd4,0x2e,0x00,0x16] stb %o2, [%i0 + %l6] @@ -42,6 +52,8 @@ stb %o2, [%i0 + 32] ! CHECK: stb %o2, [%g1] ! encoding: [0xd4,0x28,0x40,0x00] stb %o2, [%g1] + ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76] + stba %o2, [%i0 + %l6] 131 ! CHECK: sth %o2, [%i0+%l6] ! encoding: [0xd4,0x36,0x00,0x16] sth %o2, [%i0 + %l6] @@ -49,6 +61,8 @@ sth %o2, [%i0 + 32] ! CHECK: sth %o2, [%g1] ! encoding: [0xd4,0x30,0x40,0x00] sth %o2, [%g1] + ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76] + stha %o2, [%i0 + %l6] 131 ! CHECK: st %o2, [%i0+%l6] ! encoding: [0xd4,0x26,0x00,0x16] st %o2, [%i0 + %l6] @@ -56,3 +70,5 @@ st %o2, [%i0 + 32] ! CHECK: st %o2, [%g1] ! encoding: [0xd4,0x20,0x40,0x00] st %o2, [%g1] + ! CHECK: sta %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xa6,0x10,0x76] + sta %o2, [%i0 + %l6] 131 Index: llvm/trunk/test/MC/Sparc/sparcv9-atomic-instructions.s =================================================================== --- llvm/trunk/test/MC/Sparc/sparcv9-atomic-instructions.s +++ llvm/trunk/test/MC/Sparc/sparcv9-atomic-instructions.s @@ -0,0 +1,10 @@ +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s + + ! CHECK: membar 15 ! encoding: [0x81,0x43,0xe0,0x0f] + membar 15 + + ! 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