diff options
Diffstat (limited to 'llvm/lib/Target/Sparc')
-rw-r--r-- | llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstr64Bit.td | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrFormats.td | 9 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcInstrInfo.td | 51 |
5 files changed, 69 insertions, 15 deletions
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index de106679430..84cb440e742 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -631,6 +631,15 @@ SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 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<SparcOperand> Op; + ResTy = parseSparcAsmOperand(Op, false); + if (ResTy != MatchOperand_Success || !Op) + return MatchOperand_ParseFail; + Operands.push_back(std::move(Op)); + } return MatchOperand_Success; } diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp index b3a60381a83..3e56b9e9b88 100644 --- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -279,6 +279,8 @@ static DecodeStatus DecodeMem(MCInst &MI, unsigned insn, uint64_t Address, 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 @@ static DecodeStatus DecodeMem(MCInst &MI, unsigned insn, uint64_t Address, 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 @@ static DecodeStatus DecodeSWAP(MCInst &MI, unsigned insn, uint64_t Address, 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 @@ static DecodeStatus DecodeSWAP(MCInst &MI, unsigned insn, uint64_t Address, if (status != MCDisassembler::Success) return status; } + + if (hasAsi) + MI.addOperand(MCOperand::createImm(asi)); + return MCDisassembler::Success; } diff --git a/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/llvm/lib/Target/Sparc/SparcInstr64Bit.td index 0eb6f08c8f3..419e8ccb102 100644 --- a/llvm/lib/Target/Sparc/SparcInstr64Bit.td +++ b/llvm/lib/Target/Sparc/SparcInstr64Bit.td @@ -486,8 +486,8 @@ def SETHIXi : F2_1<0b100, } // 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", diff --git a/llvm/lib/Target/Sparc/SparcInstrFormats.td b/llvm/lib/Target/Sparc/SparcInstrFormats.td index 3b5e2389932..4c97687b14d 100644 --- a/llvm/lib/Target/Sparc/SparcInstrFormats.td +++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td @@ -113,8 +113,9 @@ class F3<dag outs, dag ins, string asmstr, list<dag> pattern> // Specific F3 classes: SparcV8 manual, page 44 // -class F3_1_asi<bits<2> opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins, +class F3_1_asi<bits<2> opVal, bits<6> op3val, dag outs, dag ins, string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> { + bits<8> asi; bits<5> rs2; let op = opVal; @@ -126,8 +127,10 @@ class F3_1_asi<bits<2> opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins, } class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins, string asmstr, - list<dag> pattern> : F3_1_asi<opVal, op3val, 0, outs, ins, - asmstr, pattern>; + list<dag> pattern> : F3_1_asi<opVal, op3val, outs, ins, + asmstr, pattern> { + let asi = 0; +} class F3_2<bits<2> opVal, bits<6> op3val, dag outs, dag ins, string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> { diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index ea17174e11a..732ec360100 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -283,6 +283,17 @@ multiclass Load<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode, [(set Ty:$dst, (OpNode ADDRri:$addr))]>; } +// LoadA multiclass - As above, but also define alternate address space variant +multiclass LoadA<string OpcStr, bits<6> Op3Val, bits<6> LoadAOp3Val, + SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> : + Load<OpcStr, Op3Val, OpNode, RC, Ty> { + // 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<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> { @@ -296,6 +307,16 @@ multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode, [(OpNode Ty:$rd, ADDRri:$addr)]>; } +multiclass StoreA<string OpcStr, bits<6> Op3Val, bits<6> StoreAOp3Val, + SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> : + Store<OpcStr, Op3Val, OpNode, RC, Ty> { + // 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 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, // 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 @@ let DecoderMethod = "DecodeLoadQFP" in // 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 @@ let Constraints = "$val = $dst", DecoderMethod = "DecodeSWAP" in { (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", |