diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp index f2c391b03bd4e..f756f06da8bcd 100644 --- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp +++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaELFObjectWriter.cpp @@ -8,6 +8,7 @@ // //===----------------------------------------------------------------------===// +#include "MCTargetDesc/XtensaMCExpr.h" #include "MCTargetDesc/XtensaMCTargetDesc.h" #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/ELF.h" @@ -45,10 +46,12 @@ XtensaObjectWriter::~XtensaObjectWriter() {} unsigned XtensaObjectWriter::getRelocType(const MCFixup &Fixup, const MCValue &Target, bool IsPCRel) const { + uint8_t Specifier = Target.getSpecifier(); switch ((unsigned)Fixup.getKind()) { case FK_Data_4: - return ELF::R_XTENSA_32; + return (Specifier == Xtensa::S_TPOFF ? ELF::R_XTENSA_TLS_TPOFF + : ELF::R_XTENSA_32); default: return ELF::R_XTENSA_SLOT0_OP; } diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp index 9a55635674d72..821cba0fc25c2 100644 --- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp +++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp @@ -186,11 +186,17 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits, return FeatureBits[Xtensa::FeatureMiscSR]; case Xtensa::PRID: return RAType == Xtensa::REGISTER_READ && FeatureBits[Xtensa::FeaturePRID]; + case Xtensa::THREADPTR: + return FeatureBits[FeatureTHREADPTR]; case Xtensa::VECBASE: return FeatureBits[Xtensa::FeatureRelocatableVector]; case Xtensa::FCR: case Xtensa::FSR: return FeatureBits[FeatureSingleFloat]; + case Xtensa::F64R_LO: + case Xtensa::F64R_HI: + case Xtensa::F64S: + return FeatureBits[FeatureDFPAccel]; case Xtensa::WINDOWBASE: case Xtensa::WINDOWSTART: return FeatureBits[Xtensa::FeatureWindowed]; @@ -203,12 +209,23 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits, // Get Xtensa User Register by encoding value. MCRegister Xtensa::getUserRegister(unsigned Code, const MCRegisterInfo &MRI) { + MCRegister UserReg = Xtensa::NoRegister; + if (MRI.getEncodingValue(Xtensa::FCR) == Code) { - return Xtensa::FCR; + UserReg = Xtensa::FCR; } else if (MRI.getEncodingValue(Xtensa::FSR) == Code) { - return Xtensa::FSR; + UserReg = Xtensa::FSR; + } else if (MRI.getEncodingValue(Xtensa::F64R_LO) == Code) { + UserReg = Xtensa::F64R_LO; + } else if (MRI.getEncodingValue(Xtensa::F64R_HI) == Code) { + UserReg = Xtensa::F64R_HI; + } else if (MRI.getEncodingValue(Xtensa::F64S) == Code) { + UserReg = Xtensa::F64S; + } else if (MRI.getEncodingValue(Xtensa::THREADPTR) == Code) { + UserReg = Xtensa::THREADPTR; } - return Xtensa::NoRegister; + + return UserReg; } static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI, diff --git a/llvm/lib/Target/Xtensa/XtensaFeatures.td b/llvm/lib/Target/Xtensa/XtensaFeatures.td index d48f494388a23..97d5472f3e96c 100644 --- a/llvm/lib/Target/Xtensa/XtensaFeatures.td +++ b/llvm/lib/Target/Xtensa/XtensaFeatures.td @@ -98,6 +98,11 @@ def FeatureDataCache : SubtargetFeature<"dcache", "HasDataCache", "true", def HasDataCache : Predicate<"Subtarget->hasDataCache()">, AssemblerPredicate<(all_of FeatureDataCache)>; +def FeatureTHREADPTR : SubtargetFeature<"threadptr", "HasTHREADPTR", "true", + "Enable Xtensa THREADPTR option">; +def HasTHREADPTR : Predicate<"Subtarget->hasTHREADPTR()">, + AssemblerPredicate<(all_of FeatureTHREADPTR)>; + // Xtensa Interrupts Options. def FeatureHighPriInterrupts : SubtargetFeature<"highpriinterrupts", "HasHighPriInterrupts", "true", @@ -137,3 +142,8 @@ def FeatureCoprocessor : SubtargetFeature<"coprocessor", "HasCoprocessor", "true "Enable Xtensa Coprocessor option">; def HasCoprocessor : Predicate<"Subtarget->hasCoprocessor()">, AssemblerPredicate<(all_of FeatureCoprocessor)>; + +def FeatureDFPAccel : SubtargetFeature<"dfpaccel", "HasDFPAccel", "true", + "Enable Xtensa Double Precision FP acceleration">; +def HasDFPAccel : Predicate<"Subtarget->hasDFPAccel()">, + AssemblerPredicate<(all_of FeatureDFPAccel)>; diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp index d51c573282da7..c0c8390ab2e4f 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -101,6 +101,7 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM, setOperationAction(ISD::ConstantPool, PtrVT, Custom); setOperationAction(ISD::GlobalAddress, PtrVT, Custom); + setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom); setOperationAction(ISD::BlockAddress, PtrVT, Custom); setOperationAction(ISD::JumpTable, PtrVT, Custom); @@ -919,6 +920,58 @@ SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op, return Res; } +SDValue XtensaTargetLowering::LowerGlobalTLSAddress(SDValue Op, + SelectionDAG &DAG) const { + const GlobalAddressSDNode *G = cast(Op); + SDLoc DL(Op); + auto PtrVT = Op.getValueType(); + const GlobalValue *GV = G->getGlobal(); + + if (DAG.getTarget().useEmulatedTLS()) + return LowerToTLSEmulatedModel(G, DAG); + + TLSModel::Model model = getTargetMachine().getTLSModel(GV); + + if (!Subtarget.hasTHREADPTR()) { + DAG.getContext()->diagnose(DiagnosticInfoUnsupported( + DAG.getMachineFunction().getFunction(), "only emulated TLS supported", + DL.getDebugLoc())); + } + + if (model == TLSModel::LocalExec || model == TLSModel::InitialExec) { + bool Priv = GV->isPrivateLinkage(GV->getLinkage()); + MachineFunction &MF = DAG.getMachineFunction(); + XtensaMachineFunctionInfo *XtensaFI = + MF.getInfo(); + unsigned LabelId = XtensaFI->createCPLabelId(); + + // Create a constant pool entry for the callee address + XtensaConstantPoolValue *CPV = XtensaConstantPoolSymbol::Create( + *DAG.getContext(), GV->getName().str().c_str(), LabelId, Priv, + XtensaCP::TPOFF); + + // Get the address of the callee into a register + SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, Align(4)); + SDValue CPWrap = getAddrPCRel(CPAddr, DAG); + SDValue Addr = DAG.getLoad( + PtrVT, DL, DAG.getEntryNode(), CPWrap, + MachinePointerInfo::getConstantPool(DAG.getMachineFunction())); + + SDValue TPRegister = DAG.getRegister(Xtensa::THREADPTR, MVT::i32); + SDValue ThreadPointer = + DAG.getNode(XtensaISD::RUR, DL, MVT::i32, TPRegister); + + return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadPointer, Addr); + } else { + DAG.getContext()->diagnose(DiagnosticInfoUnsupported( + DAG.getMachineFunction().getFunction(), + "only local-exec and initial-exec TLS mode supported", + DL.getDebugLoc())); + } + + return SDValue(); +} + SDValue XtensaTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const { BlockAddressSDNode *Node = cast(Op); @@ -1353,6 +1406,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op, return LowerRETURNADDR(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::GlobalTLSAddress: + return LowerGlobalTLSAddress(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::JumpTable: @@ -1406,6 +1461,8 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const { return "XtensaISD::RET"; case XtensaISD::RETW: return "XtensaISD::RETW"; + case XtensaISD::RUR: + return "XtensaISD::RUR"; case XtensaISD::SELECT_CC: return "XtensaISD::SELECT_CC"; case XtensaISD::SRCL: diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h index b6f2ebe21c940..91c79b1aa240e 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h @@ -45,6 +45,8 @@ enum { RET, RETW, + RUR, + // Select with condition operator - This selects between a true value and // a false value (ops #2 and #3) based on the boolean result of comparing // the lhs and rhs (ops #0 and #1) of a conditional expression with the @@ -156,6 +158,8 @@ class XtensaTargetLowering : public TargetLowering { SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td index 1335c6faff6b7..02156cefec142 100644 --- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td +++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td @@ -576,7 +576,7 @@ def WUR : RRR_Inst<0x00, 0x03, 0x0F, (outs UR:$ur), (ins AR:$t), } def RUR : RRR_Inst<0x00, 0x03, 0x0E, (outs AR:$r), (ins UR:$ur), - "rur\t$r, $ur", []> { + "rur\t$r, $ur", [(set AR:$r, (Xtensa_rur UR:$ur))]> { bits<8> ur; let s = ur{7-4}; diff --git a/llvm/lib/Target/Xtensa/XtensaOperators.td b/llvm/lib/Target/Xtensa/XtensaOperators.td index fea13c2298d97..1d70e94d6d5eb 100644 --- a/llvm/lib/Target/Xtensa/XtensaOperators.td +++ b/llvm/lib/Target/Xtensa/XtensaOperators.td @@ -38,6 +38,8 @@ def SDT_XtensaEXTUI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCi def SDT_XtensaMOVSP : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def SDT_XtensaRUR : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; + //===----------------------------------------------------------------------===// // Node definitions //===----------------------------------------------------------------------===// @@ -76,6 +78,9 @@ def Xtensa_extui: SDNode<"XtensaISD::EXTUI", SDT_XtensaEXTUI>; def Xtensa_movsp: SDNode<"XtensaISD::MOVSP", SDT_XtensaMOVSP, [SDNPHasChain, SDNPSideEffect, SDNPInGlue]>; +def Xtensa_rur: SDNode<"XtensaISD::RUR", SDT_XtensaRUR, + [SDNPInGlue]>; + def Xtensa_cmpoeq : SDNode<"XtensaISD::CMPOEQ", SDT_XtensaCmp, [SDNPOutGlue]>; def Xtensa_cmpolt : SDNode<"XtensaISD::CMPOLT", SDT_XtensaCmp, [SDNPOutGlue]>; def Xtensa_cmpole : SDNode<"XtensaISD::CMPOLE", SDT_XtensaCmp, [SDNPOutGlue]>; diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp index 74633050861c2..ed76431bf5495 100644 --- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp +++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp @@ -53,7 +53,10 @@ BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const { // Reserve frame pointer. Reserved.set(getFrameRegister(MF)); } - + if (Subtarget.hasTHREADPTR()) { + // Reserve frame pointer. + Reserved.set(Xtensa::THREADPTR); + } // Reserve stack pointer. Reserved.set(Xtensa::SP); return Reserved; diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td index 644faee51f513..596c4105c1118 100644 --- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td +++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.td @@ -234,10 +234,19 @@ class URReg num, string n, list alt = []> : XtensaReg { let AltNames = alt; } +// Thread Pointer register +def THREADPTR : URReg<231, "threadptr", ["THREADPTR"]>; + def FCR : URReg<232, "fcr", ["FCR"]>; def FSR : URReg<233, "fsr", ["FSR"]>; -def UR : RegisterClass<"Xtensa", [i32], 32, (add FCR, FSR)>; +// DFPAccel registers +def F64R_LO : URReg<234, "f64r_lo", ["F64R_LO"]>; +def F64R_HI : URReg<235, "f64r_hi", ["F64R_HI"]>; +def F64S : URReg<236, "f64s", ["F64S"]>; + +def UR : RegisterClass<"Xtensa", [i32], 32, (add + THREADPTR, FCR, FSR, F64R_LO, F64R_HI, F64S)>; //===----------------------------------------------------------------------===// // Floating-Point registers diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h index bc32541750ece..fd677a451f3fd 100644 --- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h +++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h @@ -91,7 +91,7 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo { bool hasHighPriInterruptsLevel7() const { return HasHighPriInterruptsLevel7; } bool hasInterrupt() const { return HasInterrupt; } bool hasException() const { return HasException; } - + bool hasTHREADPTR() const { return HasTHREADPTR; } bool isWindowedABI() const { return hasWindowed(); } // Automatically generated by tblgen. diff --git a/llvm/test/CodeGen/Xtensa/threadptr.ll b/llvm/test/CodeGen/Xtensa/threadptr.ll new file mode 100644 index 0000000000000..f294c8c5bd3ca --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/threadptr.ll @@ -0,0 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=xtensa -mattr=+threadptr -disable-block-placement -verify-machineinstrs < %s \ +; RUN: | FileCheck %s + +@i = external thread_local global i32 + +define i32 @f() { +; CHECK-LABEL: f: +; CHECK: .cfi_startproc +; CHECK-NEXT: # %bb.0: # %entry +; CHECK-NEXT: l32r a8, .LCPI0_0 +; CHECK-NEXT: rur a9, threadptr +; CHECK-NEXT: add a8, a9, a8 +; CHECK-NEXT: l32i a2, a8, 0 +; CHECK-NEXT: ret +entry: + %tmp1 = load i32, ptr @i + ret i32 %tmp1 +} diff --git a/llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt b/llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt new file mode 100644 index 0000000000000..e2f06c601fd5f --- /dev/null +++ b/llvm/test/MC/Disassembler/Xtensa/dfpaccel.txt @@ -0,0 +1,19 @@ +# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5 +# RUN: llvm-mc -triple=xtensa -mattr=+dfpaccel -disassemble %s | FileCheck -check-prefixes=CHECK-DFPACCEL %s +# RUN: not llvm-mc -triple=xtensa -disassemble %s 2>&1 | FileCheck --implicit-check-not=warning: -check-prefixes=CHECK-CORE %s + +## Verify that binary code is correctly disassembled with +## DFPACCEL option enabled. Also verify that dissasembling without +## DFPACCEL option generates warnings. + +[0xa0,0x3e,0xe3] +# CHECK-DFPACCEL: rur a3, f64r_lo +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0xb0,0x3e,0xe3] +# CHECK-DFPACCEL: rur a3, f64r_hi +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding + +[0xc0,0x3e,0xe3] +# CHECK-DFPACCEL: rur a3, f64s +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding diff --git a/llvm/test/MC/Disassembler/Xtensa/threadptr.txt b/llvm/test/MC/Disassembler/Xtensa/threadptr.txt new file mode 100644 index 0000000000000..1e8d75fa4003b --- /dev/null +++ b/llvm/test/MC/Disassembler/Xtensa/threadptr.txt @@ -0,0 +1,11 @@ +# NOTE: Assertions have been autogenerated by utils/update_mc_test_checks.py UTC_ARGS: --version 5 +# RUN: llvm-mc -triple=xtensa -mattr=+threadptr -disassemble %s | FileCheck -check-prefixes=CHECK-THREADPTR %s +# RUN: not llvm-mc -triple=xtensa -disassemble %s 2>&1 | FileCheck --implicit-check-not=warning: -check-prefixes=CHECK-CORE %s + +## Verify that binary code is correctly disassembled with +## THREADPTR option enabled. Also verify that dissasembling without +## THREADPTR option generates warnings. + +[0x70,0x3e,0xe3] +# CHECK-THREADPTR: rur a3, threadptr +# CHECK-CORE: :[[@LINE-2]]:2: warning: invalid instruction encoding diff --git a/llvm/test/MC/Xtensa/dfpaccel.s b/llvm/test/MC/Xtensa/dfpaccel.s new file mode 100644 index 0000000000000..13e8c2865f403 --- /dev/null +++ b/llvm/test/MC/Xtensa/dfpaccel.s @@ -0,0 +1,53 @@ +# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+dfpaccel \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s + +.align 4 +LBL0: + +# CHECK-INST: rur a3, f64r_lo +# CHECK: encoding: [0xa0,0x3e,0xe3] +rur a3, f64r_lo + +# CHECK-INST: rur a3, f64r_lo +# CHECK: encoding: [0xa0,0x3e,0xe3] +rur a3, 234 + +# CHECK-INST: rur a3, f64r_lo +# CHECK: encoding: [0xa0,0x3e,0xe3] +rur.f64r_lo a3 + +# CHECK-INST: wur a3, f64r_lo +# CHECK: encoding: [0x30,0xea,0xf3] +wur a3, f64r_lo + +# CHECK-INST: rur a3, f64r_hi +# CHECK: encoding: [0xb0,0x3e,0xe3] +rur a3, f64r_hi + +# CHECK-INST: rur a3, f64r_hi +# CHECK: encoding: [0xb0,0x3e,0xe3] +rur a3, 235 + +# CHECK-INST: rur a3, f64r_hi +# CHECK: encoding: [0xb0,0x3e,0xe3] +rur.f64r_hi a3 + +# CHECK-INST: wur a3, f64r_hi +# CHECK: encoding: [0x30,0xeb,0xf3] +wur a3, f64r_hi + +# CHECK-INST: rur a3, f64s +# CHECK: encoding: [0xc0,0x3e,0xe3] +rur a3, f64s + +# CHECK-INST: rur a3, f64s +# CHECK: encoding: [0xc0,0x3e,0xe3] +rur a3, 236 + +# CHECK-INST: rur a3, f64s +# CHECK: encoding: [0xc0,0x3e,0xe3] +rur.f64s a3 + +# CHECK-INST: wur a3, f64s +# CHECK: encoding: [0x30,0xec,0xf3] +wur a3, f64s diff --git a/llvm/test/MC/Xtensa/threadptr.s b/llvm/test/MC/Xtensa/threadptr.s new file mode 100644 index 0000000000000..c29d1ea91ed80 --- /dev/null +++ b/llvm/test/MC/Xtensa/threadptr.s @@ -0,0 +1,21 @@ +# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+threadptr \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s + +.align 4 +LBL0: + +# CHECK-INST: rur a3, threadptr +# CHECK: encoding: [0x70,0x3e,0xe3] +rur a3, threadptr + +# CHECK-INST: rur a3, threadptr +# CHECK: encoding: [0x70,0x3e,0xe3] +rur a3, 231 + +# CHECK-INST: rur a3, threadptr +# CHECK: encoding: [0x70,0x3e,0xe3] +rur.threadptr a3 + +# CHECK-INST: wur a3, threadptr +# CHECK: encoding: [0x30,0xe7,0xf3] +wur a3, threadptr