diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index 5e145b54592e..7b02a245bf66 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -1034,6 +1034,9 @@ SparcAsmParser::parseSparcAsmOperand(std::unique_ptr &Op, case Sparc::TBR: Op = SparcOperand::CreateToken("%tbr", S); break; + case Sparc::PC: + Op = SparcOperand::CreateToken("%pc", S); + break; case Sparc::ICC: if (name == "xcc") Op = SparcOperand::CreateToken("%xcc", S); @@ -1341,6 +1344,11 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, unsigned &RegNo, RegKind = SparcOperand::rk_Special; return true; } + if (name.equals("pc")) { + RegNo = Sparc::PC; + RegKind = SparcOperand::rk_Special; + return true; + } } return false; } diff --git a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp index 1caa33341300..5c4419c108c0 100644 --- a/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ b/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -113,7 +113,7 @@ static const unsigned ASRRegDecoderTable[] = { static const unsigned PRRegDecoderTable[] = { SP::TPC, SP::TNPC, SP::TSTATE, SP::TT, SP::TICK, SP::TBA, SP::PSTATE, SP::TL, SP::PIL, SP::CWP, SP::CANSAVE, SP::CANRESTORE, SP::CLEANWIN, - SP::OTHERWIN, SP::WSTATE + SP::OTHERWIN, SP::WSTATE, SP::PC }; static const uint16_t IntPairDecoderTable[] = { diff --git a/llvm/lib/Target/Sparc/SparcInstrAliases.td b/llvm/lib/Target/Sparc/SparcInstrAliases.td index 2c28e06718b7..1b3ec199fc16 100644 --- a/llvm/lib/Target/Sparc/SparcInstrAliases.td +++ b/llvm/lib/Target/Sparc/SparcInstrAliases.td @@ -444,6 +444,7 @@ def : InstAlias<"mov $asr, $rd", (RDASR IntRegs:$rd, ASRRegs:$asr), 0>; def : InstAlias<"mov %psr, $rd", (RDPSR IntRegs:$rd), 0>; def : InstAlias<"mov %wim, $rd", (RDWIM IntRegs:$rd), 0>; def : InstAlias<"mov %tbr, $rd", (RDTBR IntRegs:$rd), 0>; +def : InstAlias<"mov %pc, $rd", (RDPC IntRegs:$rd), 0>; // mov reg_or_imm, specialreg -> wr %g0, reg_or_imm, specialreg def : InstAlias<"mov $rs2, $asr", (WRASRrr ASRRegs:$asr, G0, IntRegs:$rs2), 0>; diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index 5e41ff51204a..b161e2a9d087 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -1056,6 +1056,14 @@ let Predicates = [HasNoV9] in { "rd %tbr, $rd", []>; } +// PC don't exist on the SparcV8, only the V9. +let Predicates = [HasV9] in { + let rs2 = 0, rs1 = 5 in + def RDPC : F3_1<2, 0b101000, + (outs IntRegs:$rd), (ins), + "rd %pc, $rd", []>; +} + // Section B.29 - Write State Register Instructions def WRASRrr : F3_1<2, 0b110000, (outs ASRRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.td b/llvm/lib/Target/Sparc/SparcRegisterInfo.td index 8225bc21e8fe..9453efb6fbb4 100644 --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.td +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.td @@ -106,6 +106,8 @@ def ASR31 : SparcCtrlReg<31, "ASR31">; def PSR : SparcCtrlReg<0, "PSR">; def WIM : SparcCtrlReg<0, "WIM">; def TBR : SparcCtrlReg<0, "TBR">; +// PC on the other hand is only available for SparcV9. +def PC : SparcCtrlReg<5, "PC">; def TPC : SparcCtrlReg<0, "TPC">; def TNPC : SparcCtrlReg<1, "TNPC">; diff --git a/llvm/test/MC/Sparc/sparcv9-instructions.s b/llvm/test/MC/Sparc/sparcv9-instructions.s index 83f846b86ed1..6a88375b8213 100644 --- a/llvm/test/MC/Sparc/sparcv9-instructions.s +++ b/llvm/test/MC/Sparc/sparcv9-instructions.s @@ -294,5 +294,10 @@ ! V9: rdpr %wstate, %i5 ! encoding: [0xbb,0x53,0x80,0x00] rdpr %wstate,%i5 + ! V8: error: instruction requires a CPU feature not currently enabled + ! V8-NEXT: rd %pc, %o7 + ! V9: rd %pc, %o7 ! encoding: [0x9f,0x41,0x40,0x00] + rd %pc, %o7 + ! V9: st %o1, [%o0] ! encoding: [0xd2,0x22,0x00,0x00] stw %o1, [%o0]