[PATCH]: llvm 3.4.1 sparc64 selfhosting patches
Roman Divacky
rdivacky at freebsd.org
Tue Feb 11 11:26:43 PST 2014
CCing llvm-commits@, so please respond to this copy.
On Tue, Feb 11, 2014 at 08:04:42PM +0100, Roman Divacky wrote:
> Hi,
>
> The two merge patches attached. I managed to selfhost with them. All tests
> pass.
>
> They are rather big though, llvm one:
>
> 91 files changed, 6627 insertions(+), 859 deletions(-)
>
> clang one:
>
> 10 files changed, 152 insertions(+), 6 deletions(-)
>
> The sparc specific stuff should be non-trivial (and tested by the selfhost),
> but I would appreciate review for the non-sparc changes (quite tiny) and
> ok for the sparc changes from Venkatraman as maintainer of that backend.
>
> The size of the llvm patch is mostly caused by adding the parser and MCization
> of the backend. While not strictly necessary for selfhosting, it made the
> merging easier (possible at all).
>
> These are the llvm changes I merged:
>
> LLVM_PATCH="r196755 r198028 r198029 r198030 r198145 r198149 r198157 r198565
> r199186 r199187 r198280 r198281 r198286 r198480 r198484 r198533 r198567 r198580
> r198591 r198592 r198658 r198681 r198738 r198739 r198740 r198893 r198909 r198910
> r199014 r199024 r199028 r199031 r199033 r199061 r199775 r199781 r199786 r199940
> r199974 r199975 r199977 r200103 rr200104 r200112 r200130 r200131 r200141
> r200282 r200368 r200373 r200376 r200509 r200617 r200960 r200961 r200962 r200963
> r200965"
>
> and these are clang ones:
>
> CLANG_PATCH="r198311 r198312 r198911 r198912 r198918 r198923 r199012 r199034
> r199037 r199188 r199399 r200452"
>
> There were some conflicts and due trunk/branch divergence I had to change a
> small bit in the sparc backend (getSymbolWithGlobalValueBase expanded and
> marking the asmwriter a MCized one as 3.4 still defaults to non-MC writer).
>
> Let me know what you think!
>
> Roman
> Index: include/llvm/MC/MCAsmInfo.h
> ===================================================================
> --- include/llvm/MC/MCAsmInfo.h (revision 201091)
> +++ include/llvm/MC/MCAsmInfo.h (working copy)
> @@ -371,7 +371,7 @@
> unsigned Encoding,
> MCStreamer &Streamer) const;
>
> - const MCExpr *
> + virtual const MCExpr *
> getExprForFDESymbol(const MCSymbol *Sym,
> unsigned Encoding,
> MCStreamer &Streamer) const;
> Index: include/llvm/Object/ELFObjectFile.h
> ===================================================================
> --- include/llvm/Object/ELFObjectFile.h (revision 201091)
> +++ include/llvm/Object/ELFObjectFile.h (working copy)
> @@ -922,6 +922,9 @@
> return "ELF32-mips";
> case ELF::EM_PPC:
> return "ELF32-ppc";
> + case ELF::EM_SPARC:
> + case ELF::EM_SPARC32PLUS:
> + return "ELF32-sparc";
> default:
> return "ELF32-unknown";
> }
> @@ -937,6 +940,8 @@
> return "ELF64-ppc64";
> case ELF::EM_S390:
> return "ELF64-s390";
> + case ELF::EM_SPARCV9:
> + return "ELF64-sparc";
> default:
> return "ELF64-unknown";
> }
> @@ -967,6 +972,13 @@
> : Triple::ppc64;
> case ELF::EM_S390:
> return Triple::systemz;
> +
> + case ELF::EM_SPARC:
> + case ELF::EM_SPARC32PLUS:
> + return Triple::sparc;
> + case ELF::EM_SPARCV9:
> + return Triple::sparcv9;
> +
> default:
> return Triple::UnknownArch;
> }
> Index: include/llvm/Support/ELF.h
> ===================================================================
> --- include/llvm/Support/ELF.h (revision 201091)
> +++ include/llvm/Support/ELF.h (working copy)
> @@ -1087,6 +1087,94 @@
> R_390_IRELATIVE = 61
> };
>
> +// ELF Relocation type for Sparc.
> +enum {
> + R_SPARC_NONE = 0,
> + R_SPARC_8 = 1,
> + R_SPARC_16 = 2,
> + R_SPARC_32 = 3,
> + R_SPARC_DISP8 = 4,
> + R_SPARC_DISP16 = 5,
> + R_SPARC_DISP32 = 6,
> + R_SPARC_WDISP30 = 7,
> + R_SPARC_WDISP22 = 8,
> + R_SPARC_HI22 = 9,
> + R_SPARC_22 = 10,
> + R_SPARC_13 = 11,
> + R_SPARC_LO10 = 12,
> + R_SPARC_GOT10 = 13,
> + R_SPARC_GOT13 = 14,
> + R_SPARC_GOT22 = 15,
> + R_SPARC_PC10 = 16,
> + R_SPARC_PC22 = 17,
> + R_SPARC_WPLT30 = 18,
> + R_SPARC_COPY = 19,
> + R_SPARC_GLOB_DAT = 20,
> + R_SPARC_JMP_SLOT = 21,
> + R_SPARC_RELATIVE = 22,
> + R_SPARC_UA32 = 23,
> + R_SPARC_PLT32 = 24,
> + R_SPARC_HIPLT22 = 25,
> + R_SPARC_LOPLT10 = 26,
> + R_SPARC_PCPLT32 = 27,
> + R_SPARC_PCPLT22 = 28,
> + R_SPARC_PCPLT10 = 29,
> + R_SPARC_10 = 30,
> + R_SPARC_11 = 31,
> + R_SPARC_64 = 32,
> + R_SPARC_OLO10 = 33,
> + R_SPARC_HH22 = 34,
> + R_SPARC_HM10 = 35,
> + R_SPARC_LM22 = 36,
> + R_SPARC_PC_HH22 = 37,
> + R_SPARC_PC_HM10 = 38,
> + R_SPARC_PC_LM22 = 39,
> + R_SPARC_WDISP16 = 40,
> + R_SPARC_WDISP19 = 41,
> + R_SPARC_7 = 43,
> + R_SPARC_5 = 44,
> + R_SPARC_6 = 45,
> + R_SPARC_DISP64 = 46,
> + R_SPARC_PLT64 = 47,
> + R_SPARC_HIX22 = 48,
> + R_SPARC_LOX10 = 49,
> + R_SPARC_H44 = 50,
> + R_SPARC_M44 = 51,
> + R_SPARC_L44 = 52,
> + R_SPARC_REGISTER = 53,
> + R_SPARC_UA64 = 54,
> + R_SPARC_UA16 = 55,
> + R_SPARC_TLS_GD_HI22 = 56,
> + R_SPARC_TLS_GD_LO10 = 57,
> + R_SPARC_TLS_GD_ADD = 58,
> + R_SPARC_TLS_GD_CALL = 59,
> + R_SPARC_TLS_LDM_HI22 = 60,
> + R_SPARC_TLS_LDM_LO10 = 61,
> + R_SPARC_TLS_LDM_ADD = 62,
> + R_SPARC_TLS_LDM_CALL = 63,
> + R_SPARC_TLS_LDO_HIX22 = 64,
> + R_SPARC_TLS_LDO_LOX10 = 65,
> + R_SPARC_TLS_LDO_ADD = 66,
> + R_SPARC_TLS_IE_HI22 = 67,
> + R_SPARC_TLS_IE_LO10 = 68,
> + R_SPARC_TLS_IE_LD = 69,
> + R_SPARC_TLS_IE_LDX = 70,
> + R_SPARC_TLS_IE_ADD = 71,
> + R_SPARC_TLS_LE_HIX22 = 72,
> + R_SPARC_TLS_LE_LOX10 = 73,
> + R_SPARC_TLS_DTPMOD32 = 74,
> + R_SPARC_TLS_DTPMOD64 = 75,
> + R_SPARC_TLS_DTPOFF32 = 76,
> + R_SPARC_TLS_DTPOFF64 = 77,
> + R_SPARC_TLS_TPOFF32 = 78,
> + R_SPARC_TLS_TPOFF64 = 79,
> + R_SPARC_GOTDATA_HIX22 = 80,
> + R_SPARC_GOTDATA_LOX22 = 81,
> + R_SPARC_GOTDATA_OP_HIX22 = 82,
> + R_SPARC_GOTDATA_OP_LOX22 = 83,
> + R_SPARC_GOTDATA_OP = 84
> +};
> +
> // Section header.
> struct Elf32_Shdr {
> Elf32_Word sh_name; // Section name (index into string table)
> Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp
> ===================================================================
> --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp (revision 201091)
> +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp (working copy)
> @@ -23,6 +23,7 @@
> #include "llvm/CodeGen/MachineConstantPool.h"
> #include "llvm/CodeGen/MachineFrameInfo.h"
> #include "llvm/CodeGen/MachineFunction.h"
> +#include "llvm/CodeGen/MachineInstrBundle.h"
> #include "llvm/CodeGen/MachineJumpTableInfo.h"
> #include "llvm/CodeGen/MachineLoopInfo.h"
> #include "llvm/CodeGen/MachineModuleInfo.h"
> @@ -2221,14 +2222,13 @@
> if (!MI.isBranch() || MI.isIndirectBranch())
> return false;
>
> - // If we are the operands of one of the branches, this is not
> - // a fall through.
> - for (MachineInstr::mop_iterator OI = MI.operands_begin(),
> - OE = MI.operands_end(); OI != OE; ++OI) {
> - const MachineOperand& OP = *OI;
> - if (OP.isJTI())
> + // If we are the operands of one of the branches, this is not a fall
> + // through. Note that targets with delay slots will usually bundle
> + // terminators with the delay slot instruction.
> + for (ConstMIBundleOperands OP(&MI); OP.isValid(); ++OP) {
> + if (OP->isJTI())
> return false;
> - if (OP.isMBB() && OP.getMBB() == MBB)
> + if (OP->isMBB() && OP->getMBB() == MBB)
> return false;
> }
> }
> Index: lib/CodeGen/SelectionDAG/InstrEmitter.cpp
> ===================================================================
> --- lib/CodeGen/SelectionDAG/InstrEmitter.cpp (revision 201091)
> +++ lib/CodeGen/SelectionDAG/InstrEmitter.cpp (working copy)
> @@ -220,10 +220,19 @@
> unsigned VRBase = 0;
> const TargetRegisterClass *RC =
> TRI->getAllocatableClass(TII->getRegClass(II, i, TRI, *MF));
> - // If the register class is unknown for the given definition, then try to
> - // infer one from the value type.
> - if (!RC && i < NumResults)
> - RC = TLI->getRegClassFor(Node->getSimpleValueType(i));
> + // Always let the value type influence the used register class. The
> + // constraints on the instruction may be too lax to represent the value
> + // type correctly. For example, a 64-bit float (X86::FR64) can't live in
> + // the 32-bit float super-class (X86::FR32).
> + if (i < NumResults && TLI->isTypeLegal(Node->getSimpleValueType(i))) {
> + const TargetRegisterClass *VTRC =
> + TLI->getRegClassFor(Node->getSimpleValueType(i));
> + if (RC)
> + VTRC = TRI->getCommonSubClass(RC, VTRC);
> + if (VTRC)
> + RC = VTRC;
> + }
> +
> if (II.OpInfo[i].isOptionalDef()) {
> // Optional def must be a physical register.
> unsigned NumResults = CountResults(Node);
> Index: lib/MC/MCObjectFileInfo.cpp
> ===================================================================
> --- lib/MC/MCObjectFileInfo.cpp (revision 201091)
> +++ lib/MC/MCObjectFileInfo.cpp (working copy)
> @@ -310,6 +310,33 @@
> FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8;
> TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
> dwarf::DW_EH_PE_udata8;
> + } else if (T.getArch() == Triple::sparc) {
> + if (RelocM == Reloc::PIC_) {
> + LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
> + PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
> + dwarf::DW_EH_PE_sdata4;
> + FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
> + TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
> + dwarf::DW_EH_PE_sdata4;
> + } else {
> + LSDAEncoding = dwarf::DW_EH_PE_absptr;
> + PersonalityEncoding = dwarf::DW_EH_PE_absptr;
> + FDEEncoding = dwarf::DW_EH_PE_udata4;
> + TTypeEncoding = dwarf::DW_EH_PE_absptr;
> + }
> + } else if (T.getArch() == Triple::sparcv9) {
> + LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
> + if (RelocM == Reloc::PIC_) {
> + PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
> + dwarf::DW_EH_PE_sdata4;
> + FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
> + TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
> + dwarf::DW_EH_PE_sdata4;
> + } else {
> + PersonalityEncoding = dwarf::DW_EH_PE_absptr;
> + FDEEncoding = dwarf::DW_EH_PE_udata4;
> + TTypeEncoding = dwarf::DW_EH_PE_absptr;
> + }
> } else if (T.getArch() == Triple::systemz) {
> // All currently-defined code models guarantee that 4-byte PC-relative
> // values will be in range.
> Index: lib/Object/ELF.cpp
> ===================================================================
> --- lib/Object/ELF.cpp (revision 201091)
> +++ lib/Object/ELF.cpp (working copy)
> @@ -702,6 +702,98 @@
> break;
> }
> break;
> + case ELF::EM_SPARC:
> + case ELF::EM_SPARC32PLUS:
> + case ELF::EM_SPARCV9:
> + switch (Type) {
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_NONE);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_8);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_16);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_32);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP8);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP16);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP32);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP30);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HI22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_13);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LO10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT13);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WPLT30);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_COPY);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GLOB_DAT);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_JMP_SLOT);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_RELATIVE);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA32);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PLT32);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HIPLT22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LOPLT10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT32);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_11);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_64);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_OLO10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HH22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HM10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LM22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_HH22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_HM10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_LM22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP16);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP19);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_7);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_5);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_6);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP64);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PLT64);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HIX22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LOX10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_H44);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_M44);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_L44);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_REGISTER);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA64);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA16);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_HI22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_LO10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_ADD);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_CALL);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_HI22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_LO10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_ADD);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_CALL);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_HIX22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_LOX10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_ADD);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_HI22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LO10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LD);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LDX);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_ADD);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LE_HIX22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LE_LOX10);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPMOD32);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPMOD64);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPOFF32);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPOFF64);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_TPOFF32);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_TPOFF64);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_HIX22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_LOX22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP_HIX22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP_LOX22);
> + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP);
> + default:
> + break;
> + }
> + break;
> default:
> break;
> }
> Index: lib/Target/ARM/ARMISelLowering.cpp
> ===================================================================
> --- lib/Target/ARM/ARMISelLowering.cpp (revision 201091)
> +++ lib/Target/ARM/ARMISelLowering.cpp (working copy)
> @@ -156,7 +156,7 @@
> }
>
> void ARMTargetLowering::addQRTypeForNEON(MVT VT) {
> - addRegisterClass(VT, &ARM::QPRRegClass);
> + addRegisterClass(VT, &ARM::DPairRegClass);
> addTypeForNEON(VT, MVT::v2f64, MVT::v4i32);
> }
>
> Index: lib/Target/Sparc/AsmParser/CMakeLists.txt
> ===================================================================
> --- lib/Target/Sparc/AsmParser/CMakeLists.txt (revision 0)
> +++ lib/Target/Sparc/AsmParser/CMakeLists.txt (working copy)
> @@ -0,0 +1,3 @@
> +add_llvm_library(LLVMSparcAsmParser
> + SparcAsmParser.cpp
> + )
> Index: lib/Target/Sparc/AsmParser/LLVMBuild.txt
> ===================================================================
> --- lib/Target/Sparc/AsmParser/LLVMBuild.txt (revision 0)
> +++ lib/Target/Sparc/AsmParser/LLVMBuild.txt (working copy)
> @@ -0,0 +1,23 @@
> +;===- ./lib/Target/Sparc/AsmParser/LLVMBuild.txt ---------------*- Conf -*--===;
> +;
> +; The LLVM Compiler Infrastructure
> +;
> +; This file is distributed under the University of Illinois Open Source
> +; License. See LICENSE.TXT for details.
> +;
> +;===------------------------------------------------------------------------===;
> +;
> +; This is an LLVMBuild description file for the components in this subdirectory.
> +;
> +; For more information on the LLVMBuild system, please see:
> +;
> +; http://llvm.org/docs/LLVMBuild.html
> +;
> +;===------------------------------------------------------------------------===;
> +
> +[component_0]
> +type = Library
> +name = SparcAsmParser
> +parent = Sparc
> +required_libraries = MC MCParser Support SparcDesc SparcInfo
> +add_to_library_groups = Sparc
> Index: lib/Target/Sparc/AsmParser/Makefile
> ===================================================================
> --- lib/Target/Sparc/AsmParser/Makefile (revision 0)
> +++ lib/Target/Sparc/AsmParser/Makefile (working copy)
> @@ -0,0 +1,15 @@
> +##===- lib/Target/Sparc/AsmParser/Makefile ------------------*- Makefile-*-===##
> +#
> +# The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +##===----------------------------------------------------------------------===##
> +LEVEL = ../../../..
> +LIBRARYNAME = LLVMSparcAsmParser
> +
> +# Hack: we need to include 'main' Sparc target directory to grab private headers
> +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
> +
> +include $(LEVEL)/Makefile.common
> Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
> ===================================================================
> --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp (revision 0)
> +++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp (working copy)
> @@ -0,0 +1,828 @@
> +//===-- SparcAsmParser.cpp - Parse Sparc assembly to MCInst instructions --===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "MCTargetDesc/SparcMCTargetDesc.h"
> +#include "MCTargetDesc/SparcMCExpr.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCInst.h"
> +#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
> +#include "llvm/MC/MCStreamer.h"
> +#include "llvm/MC/MCSubtargetInfo.h"
> +#include "llvm/MC/MCTargetAsmParser.h"
> +#include "llvm/Support/TargetRegistry.h"
> +
> +using namespace llvm;
> +
> +// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target
> +// namespace. But SPARC backend uses "SP" as its namespace.
> +namespace llvm {
> + namespace Sparc {
> + using namespace SP;
> + }
> +}
> +
> +namespace {
> +class SparcOperand;
> +class SparcAsmParser : public MCTargetAsmParser {
> +
> + MCSubtargetInfo &STI;
> + MCAsmParser &Parser;
> +
> + /// @name Auto-generated Match Functions
> + /// {
> +
> +#define GET_ASSEMBLER_HEADER
> +#include "SparcGenAsmMatcher.inc"
> +
> + /// }
> +
> + // public interface of the MCTargetAsmParser.
> + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
> + SmallVectorImpl<MCParsedAsmOperand*> &Operands,
> + MCStreamer &Out, unsigned &ErrorInfo,
> + bool MatchingInlineAsm);
> + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
> + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
> + SMLoc NameLoc,
> + SmallVectorImpl<MCParsedAsmOperand*> &Operands);
> + bool ParseDirective(AsmToken DirectiveID);
> +
> + virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
> + unsigned Kind);
> +
> + // Custom parse functions for Sparc specific operands.
> + OperandMatchResultTy
> + parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
> +
> + OperandMatchResultTy
> + parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
> + StringRef Name);
> +
> + OperandMatchResultTy
> + parseSparcAsmOperand(SparcOperand *&Operand);
> +
> + // returns true if Tok is matched to a register and returns register in RegNo.
> + bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
> + unsigned &RegKind);
> +
> + bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
> +
> +public:
> + SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
> + const MCInstrInfo &MII)
> + : MCTargetAsmParser(), STI(sti), Parser(parser) {
> + // Initialize the set of available features.
> + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
> + }
> +
> +};
> +
> + static unsigned IntRegs[32] = {
> + Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3,
> + Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7,
> + Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3,
> + Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7,
> + Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3,
> + Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7,
> + Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3,
> + Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 };
> +
> + static unsigned FloatRegs[32] = {
> + Sparc::F0, Sparc::F1, Sparc::F2, Sparc::F3,
> + Sparc::F4, Sparc::F5, Sparc::F6, Sparc::F7,
> + Sparc::F8, Sparc::F9, Sparc::F10, Sparc::F11,
> + Sparc::F12, Sparc::F13, Sparc::F14, Sparc::F15,
> + Sparc::F16, Sparc::F17, Sparc::F18, Sparc::F19,
> + Sparc::F20, Sparc::F21, Sparc::F22, Sparc::F23,
> + Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27,
> + Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 };
> +
> + static unsigned DoubleRegs[32] = {
> + Sparc::D0, Sparc::D1, Sparc::D2, Sparc::D3,
> + Sparc::D4, Sparc::D5, Sparc::D6, Sparc::D7,
> + Sparc::D8, Sparc::D7, Sparc::D8, Sparc::D9,
> + Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15,
> + Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19,
> + Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23,
> + Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27,
> + Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 };
> +
> + static unsigned QuadFPRegs[32] = {
> + Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3,
> + Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7,
> + Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11,
> + Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 };
> +
> +
> +/// SparcOperand - Instances of this class represent a parsed Sparc machine
> +/// instruction.
> +class SparcOperand : public MCParsedAsmOperand {
> +public:
> + enum RegisterKind {
> + rk_None,
> + rk_IntReg,
> + rk_FloatReg,
> + rk_DoubleReg,
> + rk_QuadReg,
> + rk_CCReg,
> + rk_Y
> + };
> +private:
> + enum KindTy {
> + k_Token,
> + k_Register,
> + k_Immediate,
> + k_MemoryReg,
> + k_MemoryImm
> + } Kind;
> +
> + SMLoc StartLoc, EndLoc;
> +
> + SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
> +
> + struct Token {
> + const char *Data;
> + unsigned Length;
> + };
> +
> + struct RegOp {
> + unsigned RegNum;
> + RegisterKind Kind;
> + };
> +
> + struct ImmOp {
> + const MCExpr *Val;
> + };
> +
> + struct MemOp {
> + unsigned Base;
> + unsigned OffsetReg;
> + const MCExpr *Off;
> + };
> +
> + union {
> + struct Token Tok;
> + struct RegOp Reg;
> + struct ImmOp Imm;
> + struct MemOp Mem;
> + };
> +public:
> + bool isToken() const { return Kind == k_Token; }
> + bool isReg() const { return Kind == k_Register; }
> + bool isImm() const { return Kind == k_Immediate; }
> + bool isMem() const { return isMEMrr() || isMEMri(); }
> + bool isMEMrr() const { return Kind == k_MemoryReg; }
> + bool isMEMri() const { return Kind == k_MemoryImm; }
> +
> + bool isFloatReg() const {
> + return (Kind == k_Register && Reg.Kind == rk_FloatReg);
> + }
> +
> + bool isFloatOrDoubleReg() const {
> + return (Kind == k_Register && (Reg.Kind == rk_FloatReg
> + || Reg.Kind == rk_DoubleReg));
> + }
> +
> +
> + StringRef getToken() const {
> + assert(Kind == k_Token && "Invalid access!");
> + return StringRef(Tok.Data, Tok.Length);
> + }
> +
> + unsigned getReg() const {
> + assert((Kind == k_Register) && "Invalid access!");
> + return Reg.RegNum;
> + }
> +
> + const MCExpr *getImm() const {
> + assert((Kind == k_Immediate) && "Invalid access!");
> + return Imm.Val;
> + }
> +
> + unsigned getMemBase() const {
> + assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!");
> + return Mem.Base;
> + }
> +
> + unsigned getMemOffsetReg() const {
> + assert((Kind == k_MemoryReg) && "Invalid access!");
> + return Mem.OffsetReg;
> + }
> +
> + const MCExpr *getMemOff() const {
> + assert((Kind == k_MemoryImm) && "Invalid access!");
> + return Mem.Off;
> + }
> +
> + /// getStartLoc - Get the location of the first token of this operand.
> + SMLoc getStartLoc() const {
> + return StartLoc;
> + }
> + /// getEndLoc - Get the location of the last token of this operand.
> + SMLoc getEndLoc() const {
> + return EndLoc;
> + }
> +
> + virtual void print(raw_ostream &OS) const {
> + switch (Kind) {
> + case k_Token: OS << "Token: " << getToken() << "\n"; break;
> + case k_Register: OS << "Reg: #" << getReg() << "\n"; break;
> + case k_Immediate: OS << "Imm: " << getImm() << "\n"; break;
> + case k_MemoryReg: OS << "Mem: " << getMemBase() << "+"
> + << getMemOffsetReg() << "\n"; break;
> + case k_MemoryImm: assert(getMemOff() != 0);
> + OS << "Mem: " << getMemBase()
> + << "+" << *getMemOff()
> + << "\n"; break;
> + }
> + }
> +
> + void addRegOperands(MCInst &Inst, unsigned N) const {
> + assert(N == 1 && "Invalid number of operands!");
> + Inst.addOperand(MCOperand::CreateReg(getReg()));
> + }
> +
> + void addImmOperands(MCInst &Inst, unsigned N) const {
> + assert(N == 1 && "Invalid number of operands!");
> + const MCExpr *Expr = getImm();
> + addExpr(Inst, Expr);
> + }
> +
> + void addExpr(MCInst &Inst, const MCExpr *Expr) const{
> + // Add as immediate when possible. Null MCExpr = 0.
> + if (Expr == 0)
> + Inst.addOperand(MCOperand::CreateImm(0));
> + else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
> + Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
> + else
> + Inst.addOperand(MCOperand::CreateExpr(Expr));
> + }
> +
> + void addMEMrrOperands(MCInst &Inst, unsigned N) const {
> + assert(N == 2 && "Invalid number of operands!");
> +
> + Inst.addOperand(MCOperand::CreateReg(getMemBase()));
> +
> + assert(getMemOffsetReg() != 0 && "Invalid offset");
> + Inst.addOperand(MCOperand::CreateReg(getMemOffsetReg()));
> + }
> +
> + void addMEMriOperands(MCInst &Inst, unsigned N) const {
> + assert(N == 2 && "Invalid number of operands!");
> +
> + Inst.addOperand(MCOperand::CreateReg(getMemBase()));
> +
> + const MCExpr *Expr = getMemOff();
> + addExpr(Inst, Expr);
> + }
> +
> + static SparcOperand *CreateToken(StringRef Str, SMLoc S) {
> + SparcOperand *Op = new SparcOperand(k_Token);
> + Op->Tok.Data = Str.data();
> + Op->Tok.Length = Str.size();
> + Op->StartLoc = S;
> + Op->EndLoc = S;
> + return Op;
> + }
> +
> + static SparcOperand *CreateReg(unsigned RegNum,
> + unsigned Kind,
> + SMLoc S, SMLoc E) {
> + SparcOperand *Op = new SparcOperand(k_Register);
> + Op->Reg.RegNum = RegNum;
> + Op->Reg.Kind = (SparcOperand::RegisterKind)Kind;
> + Op->StartLoc = S;
> + Op->EndLoc = E;
> + return Op;
> + }
> +
> + static SparcOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
> + SparcOperand *Op = new SparcOperand(k_Immediate);
> + Op->Imm.Val = Val;
> + Op->StartLoc = S;
> + Op->EndLoc = E;
> + return Op;
> + }
> +
> + static SparcOperand *MorphToDoubleReg(SparcOperand *Op) {
> + unsigned Reg = Op->getReg();
> + assert(Op->Reg.Kind == rk_FloatReg);
> + unsigned regIdx = Reg - Sparc::F0;
> + if (regIdx % 2 || regIdx > 31)
> + return 0;
> + Op->Reg.RegNum = DoubleRegs[regIdx / 2];
> + Op->Reg.Kind = rk_DoubleReg;
> + return Op;
> + }
> +
> + static SparcOperand *MorphToQuadReg(SparcOperand *Op) {
> + unsigned Reg = Op->getReg();
> + unsigned regIdx = 0;
> + switch (Op->Reg.Kind) {
> + default: assert(0 && "Unexpected register kind!");
> + case rk_FloatReg:
> + regIdx = Reg - Sparc::F0;
> + if (regIdx % 4 || regIdx > 31)
> + return 0;
> + Reg = QuadFPRegs[regIdx / 4];
> + break;
> + case rk_DoubleReg:
> + regIdx = Reg - Sparc::D0;
> + if (regIdx % 2 || regIdx > 31)
> + return 0;
> + Reg = QuadFPRegs[regIdx / 2];
> + break;
> + }
> + Op->Reg.RegNum = Reg;
> + Op->Reg.Kind = rk_QuadReg;
> + return Op;
> + }
> +
> + static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) {
> + unsigned offsetReg = Op->getReg();
> + Op->Kind = k_MemoryReg;
> + Op->Mem.Base = Base;
> + Op->Mem.OffsetReg = offsetReg;
> + Op->Mem.Off = 0;
> + return Op;
> + }
> +
> + static SparcOperand *CreateMEMri(unsigned Base,
> + const MCExpr *Off,
> + SMLoc S, SMLoc E) {
> + SparcOperand *Op = new SparcOperand(k_MemoryImm);
> + Op->Mem.Base = Base;
> + Op->Mem.OffsetReg = 0;
> + Op->Mem.Off = Off;
> + Op->StartLoc = S;
> + Op->EndLoc = E;
> + return Op;
> + }
> +
> + static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) {
> + const MCExpr *Imm = Op->getImm();
> + Op->Kind = k_MemoryImm;
> + Op->Mem.Base = Base;
> + Op->Mem.OffsetReg = 0;
> + Op->Mem.Off = Imm;
> + return Op;
> + }
> +};
> +
> +} // end namespace
> +
> +bool SparcAsmParser::
> +MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
> + SmallVectorImpl<MCParsedAsmOperand*> &Operands,
> + MCStreamer &Out, unsigned &ErrorInfo,
> + bool MatchingInlineAsm) {
> + MCInst Inst;
> + SmallVector<MCInst, 8> Instructions;
> + unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
> + MatchingInlineAsm);
> + switch (MatchResult) {
> + default:
> + break;
> +
> + case Match_Success: {
> + Inst.setLoc(IDLoc);
> + Out.EmitInstruction(Inst);
> + return false;
> + }
> +
> + case Match_MissingFeature:
> + return Error(IDLoc,
> + "instruction requires a CPU feature not currently enabled");
> +
> + case Match_InvalidOperand: {
> + SMLoc ErrorLoc = IDLoc;
> + if (ErrorInfo != ~0U) {
> + if (ErrorInfo >= Operands.size())
> + return Error(IDLoc, "too few operands for instruction");
> +
> + ErrorLoc = ((SparcOperand*) Operands[ErrorInfo])->getStartLoc();
> + if (ErrorLoc == SMLoc())
> + ErrorLoc = IDLoc;
> + }
> +
> + return Error(ErrorLoc, "invalid operand for instruction");
> + }
> + case Match_MnemonicFail:
> + return Error(IDLoc, "invalid instruction");
> + }
> + return true;
> +}
> +
> +bool SparcAsmParser::
> +ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc)
> +{
> + const AsmToken &Tok = Parser.getTok();
> + StartLoc = Tok.getLoc();
> + EndLoc = Tok.getEndLoc();
> + RegNo = 0;
> + if (getLexer().getKind() != AsmToken::Percent)
> + return false;
> + Parser.Lex();
> + unsigned regKind = SparcOperand::rk_None;
> + if (matchRegisterName(Tok, RegNo, regKind)) {
> + Parser.Lex();
> + return false;
> + }
> +
> + return Error(StartLoc, "invalid register name");
> +}
> +
> +bool SparcAsmParser::
> +ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
> + SMLoc NameLoc,
> + SmallVectorImpl<MCParsedAsmOperand*> &Operands)
> +{
> + // Check if we have valid mnemonic.
> + if (!mnemonicIsValid(Name, 0)) {
> + Parser.eatToEndOfStatement();
> + return Error(NameLoc, "Unknown instruction");
> + }
> + // First operand in MCInst is instruction mnemonic.
> + Operands.push_back(SparcOperand::CreateToken(Name, NameLoc));
> +
> + if (getLexer().isNot(AsmToken::EndOfStatement)) {
> + // Read the first operand.
> + if (parseOperand(Operands, Name) != MatchOperand_Success) {
> + SMLoc Loc = getLexer().getLoc();
> + Parser.eatToEndOfStatement();
> + return Error(Loc, "unexpected token");
> + }
> +
> + while (getLexer().is(AsmToken::Comma)) {
> + Parser.Lex(); // Eat the comma.
> + // Parse and remember the operand.
> + if (parseOperand(Operands, Name) != MatchOperand_Success) {
> + SMLoc Loc = getLexer().getLoc();
> + Parser.eatToEndOfStatement();
> + return Error(Loc, "unexpected token");
> + }
> + }
> + }
> + if (getLexer().isNot(AsmToken::EndOfStatement)) {
> + SMLoc Loc = getLexer().getLoc();
> + Parser.eatToEndOfStatement();
> + return Error(Loc, "unexpected token");
> + }
> + Parser.Lex(); // Consume the EndOfStatement.
> + return false;
> +}
> +
> +bool SparcAsmParser::
> +ParseDirective(AsmToken DirectiveID)
> +{
> + // Ignore all directives for now.
> + Parser.eatToEndOfStatement();
> + return false;
> +}
> +
> +SparcAsmParser::OperandMatchResultTy SparcAsmParser::
> +parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
> +{
> +
> + SMLoc S, E;
> + unsigned BaseReg = 0;
> +
> + if (ParseRegister(BaseReg, S, E)) {
> + return MatchOperand_NoMatch;
> + }
> +
> + switch (getLexer().getKind()) {
> + default: return MatchOperand_NoMatch;
> +
> + case AsmToken::Comma:
> + case AsmToken::RBrac:
> + case AsmToken::EndOfStatement:
> + Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
> + return MatchOperand_Success;
> +
> + case AsmToken:: Plus:
> + Parser.Lex(); // Eat the '+'
> + break;
> + case AsmToken::Minus:
> + break;
> + }
> +
> + SparcOperand *Offset = 0;
> + OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset);
> + if (ResTy != MatchOperand_Success || !Offset)
> + return MatchOperand_NoMatch;
> +
> + Offset = (Offset->isImm()
> + ? SparcOperand::MorphToMEMri(BaseReg, Offset)
> + : SparcOperand::MorphToMEMrr(BaseReg, Offset));
> +
> + Operands.push_back(Offset);
> + return MatchOperand_Success;
> +}
> +
> +SparcAsmParser::OperandMatchResultTy SparcAsmParser::
> +parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
> + StringRef Mnemonic)
> +{
> +
> + OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
> +
> + // If there wasn't a custom match, try the generic matcher below. Otherwise,
> + // there was a match, but an error occurred, in which case, just return that
> + // the operand parsing failed.
> + if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
> + return ResTy;
> +
> + if (getLexer().is(AsmToken::LBrac)) {
> + // Memory operand
> + Operands.push_back(SparcOperand::CreateToken("[",
> + Parser.getTok().getLoc()));
> + Parser.Lex(); // Eat the [
> +
> + if (Mnemonic == "cas" || Mnemonic == "casx") {
> + SMLoc S = Parser.getTok().getLoc();
> + if (getLexer().getKind() != AsmToken::Percent)
> + return MatchOperand_NoMatch;
> + Parser.Lex(); // eat %
> +
> + unsigned RegNo, RegKind;
> + if (!matchRegisterName(Parser.getTok(), RegNo, RegKind))
> + return MatchOperand_NoMatch;
> +
> + Parser.Lex(); // Eat the identifier token.
> + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
> + Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E));
> + ResTy = MatchOperand_Success;
> + } else {
> + ResTy = parseMEMOperand(Operands);
> + }
> +
> + if (ResTy != MatchOperand_Success)
> + return ResTy;
> +
> + if (!getLexer().is(AsmToken::RBrac))
> + return MatchOperand_ParseFail;
> +
> + Operands.push_back(SparcOperand::CreateToken("]",
> + Parser.getTok().getLoc()));
> + Parser.Lex(); // Eat the ]
> + return MatchOperand_Success;
> + }
> +
> + SparcOperand *Op = 0;
> + ResTy = parseSparcAsmOperand(Op);
> + if (ResTy != MatchOperand_Success || !Op)
> + return MatchOperand_ParseFail;
> +
> + // Push the parsed operand into the list of operands
> + Operands.push_back(Op);
> +
> + return MatchOperand_Success;
> +}
> +
> +SparcAsmParser::OperandMatchResultTy
> +SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op)
> +{
> +
> + SMLoc S = Parser.getTok().getLoc();
> + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
> + const MCExpr *EVal;
> +
> + Op = 0;
> + switch (getLexer().getKind()) {
> + default: break;
> +
> + case AsmToken::Percent:
> + Parser.Lex(); // Eat the '%'.
> + unsigned RegNo;
> + unsigned RegKind;
> + if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) {
> + StringRef name = Parser.getTok().getString();
> + Parser.Lex(); // Eat the identifier token.
> + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
> + switch (RegNo) {
> + default:
> + Op = SparcOperand::CreateReg(RegNo, RegKind, S, E);
> + break;
> + case Sparc::Y:
> + Op = SparcOperand::CreateToken("%y", S);
> + break;
> +
> + case Sparc::ICC:
> + if (name == "xcc")
> + Op = SparcOperand::CreateToken("%xcc", S);
> + else
> + Op = SparcOperand::CreateToken("%icc", S);
> + break;
> +
> + case Sparc::FCC:
> + assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet");
> + Op = SparcOperand::CreateToken("%fcc0", S);
> + break;
> + }
> + break;
> + }
> + if (matchSparcAsmModifiers(EVal, E)) {
> + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
> + Op = SparcOperand::CreateImm(EVal, S, E);
> + }
> + break;
> +
> + case AsmToken::Minus:
> + case AsmToken::Integer:
> + if (!getParser().parseExpression(EVal, E))
> + Op = SparcOperand::CreateImm(EVal, S, E);
> + break;
> +
> + case AsmToken::Identifier: {
> + StringRef Identifier;
> + if (!getParser().parseIdentifier(Identifier)) {
> + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
> + MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
> +
> + const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
> + getContext());
> + Op = SparcOperand::CreateImm(Res, S, E);
> + }
> + break;
> + }
> + }
> + return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
> +}
> +
> +bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
> + unsigned &RegNo,
> + unsigned &RegKind)
> +{
> + int64_t intVal = 0;
> + RegNo = 0;
> + RegKind = SparcOperand::rk_None;
> + if (Tok.is(AsmToken::Identifier)) {
> + StringRef name = Tok.getString();
> +
> + // %fp
> + if (name.equals("fp")) {
> + RegNo = Sparc::I6;
> + RegKind = SparcOperand::rk_IntReg;
> + return true;
> + }
> + // %sp
> + if (name.equals("sp")) {
> + RegNo = Sparc::O6;
> + RegKind = SparcOperand::rk_IntReg;
> + return true;
> + }
> +
> + if (name.equals("y")) {
> + RegNo = Sparc::Y;
> + RegKind = SparcOperand::rk_Y;
> + return true;
> + }
> +
> + if (name.equals("icc")) {
> + RegNo = Sparc::ICC;
> + RegKind = SparcOperand::rk_CCReg;
> + return true;
> + }
> +
> + if (name.equals("xcc")) {
> + // FIXME:: check 64bit.
> + RegNo = Sparc::ICC;
> + RegKind = SparcOperand::rk_CCReg;
> + return true;
> + }
> +
> + // %fcc0 - %fcc3
> + if (name.substr(0, 3).equals_lower("fcc")
> + && !name.substr(3).getAsInteger(10, intVal)
> + && intVal < 4) {
> + // FIXME: check 64bit and handle %fcc1 - %fcc3
> + RegNo = Sparc::FCC;
> + RegKind = SparcOperand::rk_CCReg;
> + return true;
> + }
> +
> + // %g0 - %g7
> + if (name.substr(0, 1).equals_lower("g")
> + && !name.substr(1).getAsInteger(10, intVal)
> + && intVal < 8) {
> + RegNo = IntRegs[intVal];
> + RegKind = SparcOperand::rk_IntReg;
> + return true;
> + }
> + // %o0 - %o7
> + if (name.substr(0, 1).equals_lower("o")
> + && !name.substr(1).getAsInteger(10, intVal)
> + && intVal < 8) {
> + RegNo = IntRegs[8 + intVal];
> + RegKind = SparcOperand::rk_IntReg;
> + return true;
> + }
> + if (name.substr(0, 1).equals_lower("l")
> + && !name.substr(1).getAsInteger(10, intVal)
> + && intVal < 8) {
> + RegNo = IntRegs[16 + intVal];
> + RegKind = SparcOperand::rk_IntReg;
> + return true;
> + }
> + if (name.substr(0, 1).equals_lower("i")
> + && !name.substr(1).getAsInteger(10, intVal)
> + && intVal < 8) {
> + RegNo = IntRegs[24 + intVal];
> + RegKind = SparcOperand::rk_IntReg;
> + return true;
> + }
> + // %f0 - %f31
> + if (name.substr(0, 1).equals_lower("f")
> + && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) {
> + RegNo = FloatRegs[intVal];
> + RegKind = SparcOperand::rk_FloatReg;
> + return true;
> + }
> + // %f32 - %f62
> + if (name.substr(0, 1).equals_lower("f")
> + && !name.substr(1, 2).getAsInteger(10, intVal)
> + && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) {
> + // FIXME: Check V9
> + RegNo = DoubleRegs[intVal/2];
> + RegKind = SparcOperand::rk_DoubleReg;
> + return true;
> + }
> +
> + // %r0 - %r31
> + if (name.substr(0, 1).equals_lower("r")
> + && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) {
> + RegNo = IntRegs[intVal];
> + RegKind = SparcOperand::rk_IntReg;
> + return true;
> + }
> + }
> + return false;
> +}
> +
> +
> +bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
> + SMLoc &EndLoc)
> +{
> + AsmToken Tok = Parser.getTok();
> + if (!Tok.is(AsmToken::Identifier))
> + return false;
> +
> + StringRef name = Tok.getString();
> +
> + SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
> +
> + if (VK == SparcMCExpr::VK_Sparc_None)
> + return false;
> +
> + Parser.Lex(); // Eat the identifier.
> + if (Parser.getTok().getKind() != AsmToken::LParen)
> + return false;
> +
> + Parser.Lex(); // Eat the LParen token.
> + const MCExpr *subExpr;
> + if (Parser.parseParenExpression(subExpr, EndLoc))
> + return false;
> + EVal = SparcMCExpr::Create(VK, subExpr, getContext());
> + return true;
> +}
> +
> +
> +extern "C" void LLVMInitializeSparcAsmParser() {
> + RegisterMCAsmParser<SparcAsmParser> A(TheSparcTarget);
> + RegisterMCAsmParser<SparcAsmParser> B(TheSparcV9Target);
> +}
> +
> +#define GET_REGISTER_MATCHER
> +#define GET_MATCHER_IMPLEMENTATION
> +#include "SparcGenAsmMatcher.inc"
> +
> +
> +
> +unsigned SparcAsmParser::
> +validateTargetOperandClass(MCParsedAsmOperand *GOp,
> + unsigned Kind)
> +{
> + SparcOperand *Op = (SparcOperand*)GOp;
> + if (Op->isFloatOrDoubleReg()) {
> + switch (Kind) {
> + default: break;
> + case MCK_DFPRegs:
> + if (!Op->isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
> + return MCTargetAsmParser::Match_Success;
> + break;
> + case MCK_QFPRegs:
> + if (SparcOperand::MorphToQuadReg(Op))
> + return MCTargetAsmParser::Match_Success;
> + break;
> + }
> + }
> + return Match_InvalidOperand;
> +}
> Index: lib/Target/Sparc/CMakeLists.txt
> ===================================================================
> --- lib/Target/Sparc/CMakeLists.txt (revision 201091)
> +++ lib/Target/Sparc/CMakeLists.txt (working copy)
> @@ -3,7 +3,10 @@
> tablegen(LLVM SparcGenRegisterInfo.inc -gen-register-info)
> tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info)
> tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter)
> +tablegen(LLVM SparcGenDisassemblerTables.inc -gen-disassembler)
> +tablegen(LLVM SparcGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
> tablegen(LLVM SparcGenAsmWriter.inc -gen-asm-writer)
> +tablegen(LLVM SparcGenAsmMatcher.inc -gen-asm-matcher)
> tablegen(LLVM SparcGenDAGISel.inc -gen-dag-isel)
> tablegen(LLVM SparcGenSubtargetInfo.inc -gen-subtarget)
> tablegen(LLVM SparcGenCallingConv.inc -gen-callingconv)
> @@ -23,6 +26,8 @@
> SparcSelectionDAGInfo.cpp
> SparcJITInfo.cpp
> SparcCodeEmitter.cpp
> + SparcMCInstLower.cpp
> + SparcTargetObjectFile.cpp
> )
>
> add_dependencies(LLVMSparcCodeGen SparcCommonTableGen intrinsics_gen)
> @@ -29,3 +34,6 @@
>
> add_subdirectory(TargetInfo)
> add_subdirectory(MCTargetDesc)
> +add_subdirectory(InstPrinter)
> +add_subdirectory(AsmParser)
> +add_subdirectory(Disassembler)
> Index: lib/Target/Sparc/DelaySlotFiller.cpp
> ===================================================================
> --- lib/Target/Sparc/DelaySlotFiller.cpp (revision 201091)
> +++ lib/Target/Sparc/DelaySlotFiller.cpp (working copy)
> @@ -19,6 +19,7 @@
> #include "llvm/ADT/Statistic.h"
> #include "llvm/CodeGen/MachineFunctionPass.h"
> #include "llvm/CodeGen/MachineInstrBuilder.h"
> +#include "llvm/CodeGen/MachineRegisterInfo.h"
> #include "llvm/Support/CommandLine.h"
> #include "llvm/Target/TargetInstrInfo.h"
> #include "llvm/Target/TargetMachine.h"
> @@ -55,6 +56,11 @@
> bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
> bool runOnMachineFunction(MachineFunction &F) {
> bool Changed = false;
> +
> + // This pass invalidates liveness information when it reorders
> + // instructions to fill delay slot.
> + F.getRegInfo().invalidateLiveness();
> +
> for (MachineFunction::iterator FI = F.begin(), FE = F.end();
> FI != FE; ++FI)
> Changed |= runOnMachineBasicBlock(*FI);
> @@ -61,9 +67,6 @@
> return Changed;
> }
>
> - bool isDelayFiller(MachineBasicBlock &MBB,
> - MachineBasicBlock::iterator candidate);
> -
> void insertCallDefsUses(MachineBasicBlock::iterator MI,
> SmallSet<unsigned, 32>& RegDefs,
> SmallSet<unsigned, 32>& RegUses);
> @@ -152,6 +155,10 @@
> assert (J != MBB.end() && "MI needs a delay instruction.");
> BuildMI(MBB, ++J, MI->getDebugLoc(),
> TII->get(SP::UNIMP)).addImm(structSize);
> + // Bundle the delay filler and unimp with the instruction.
> + MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), J);
> + } else {
> + MIBundleBuilder(MBB, MachineBasicBlock::iterator(MI), I);
> }
> }
> return Changed;
> @@ -209,7 +216,7 @@
> || I->isInlineAsm()
> || I->isLabel()
> || I->hasDelaySlot()
> - || isDelayFiller(MBB, I))
> + || I->isBundledWithSucc())
> break;
>
> if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) {
> @@ -278,19 +285,19 @@
> switch(MI->getOpcode()) {
> default: llvm_unreachable("Unknown opcode.");
> case SP::CALL: break;
> - case SP::JMPLrr:
> - case SP::JMPLri:
> + case SP::CALLrr:
> + case SP::CALLri:
> assert(MI->getNumOperands() >= 2);
> const MachineOperand &Reg = MI->getOperand(0);
> - assert(Reg.isReg() && "JMPL first operand is not a register.");
> - assert(Reg.isUse() && "JMPL first operand is not a use.");
> + assert(Reg.isReg() && "CALL first operand is not a register.");
> + assert(Reg.isUse() && "CALL first operand is not a use.");
> RegUses.insert(Reg.getReg());
>
> const MachineOperand &RegOrImm = MI->getOperand(1);
> if (RegOrImm.isImm())
> break;
> - assert(RegOrImm.isReg() && "JMPLrr second operand is not a register.");
> - assert(RegOrImm.isUse() && "JMPLrr second operand is not a use.");
> + assert(RegOrImm.isReg() && "CALLrr second operand is not a register.");
> + assert(RegOrImm.isUse() && "CALLrr second operand is not a use.");
> RegUses.insert(RegOrImm.getReg());
> break;
> }
> @@ -332,18 +339,6 @@
> return false;
> }
>
> -// return true if the candidate is a delay filler.
> -bool Filler::isDelayFiller(MachineBasicBlock &MBB,
> - MachineBasicBlock::iterator candidate)
> -{
> - if (candidate == MBB.begin())
> - return false;
> - if (candidate->getOpcode() == SP::UNIMP)
> - return true;
> - --candidate;
> - return candidate->hasDelaySlot();
> -}
> -
> bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
> {
> if (!I->isCall())
> @@ -353,8 +348,8 @@
> switch (I->getOpcode()) {
> default: llvm_unreachable("Unknown call opcode.");
> case SP::CALL: structSizeOpNum = 1; break;
> - case SP::JMPLrr:
> - case SP::JMPLri: structSizeOpNum = 2; break;
> + case SP::CALLrr:
> + case SP::CALLri: structSizeOpNum = 2; break;
> case SP::TLS_CALL: return false;
> }
>
> @@ -484,10 +479,10 @@
> && MBBI->getOperand(1).getReg() == SP::G0
> && MBBI->getOperand(2).getReg() == SP::G0);
>
> - MachineBasicBlock::iterator PrevInst = MBBI; --PrevInst;
> + MachineBasicBlock::iterator PrevInst = llvm::prior(MBBI);
>
> - // It cannot combine with a delay filler.
> - if (isDelayFiller(MBB, PrevInst))
> + // It cannot be combined with a bundled instruction.
> + if (PrevInst->isBundledWithSucc())
> return false;
>
> const TargetInstrInfo *TII = TM.getInstrInfo();
> Index: lib/Target/Sparc/Disassembler/CMakeLists.txt
> ===================================================================
> --- lib/Target/Sparc/Disassembler/CMakeLists.txt (revision 0)
> +++ lib/Target/Sparc/Disassembler/CMakeLists.txt (working copy)
> @@ -0,0 +1,12 @@
> +add_llvm_library(LLVMSparcDisassembler
> + SparcDisassembler.cpp
> + )
> +
> +# workaround for hanging compilation on MSVC9 and 10
> +if( MSVC_VERSION EQUAL 1400 OR MSVC_VERSION EQUAL 1500
> + OR MSVC_VERSION EQUAL 1600 )
> +set_property(
> + SOURCE SparcDisassembler.cpp
> + PROPERTY COMPILE_FLAGS "/Od"
> + )
> +endif()
> Index: lib/Target/Sparc/Disassembler/LLVMBuild.txt
> ===================================================================
> --- lib/Target/Sparc/Disassembler/LLVMBuild.txt (revision 0)
> +++ lib/Target/Sparc/Disassembler/LLVMBuild.txt (working copy)
> @@ -0,0 +1,23 @@
> +;===- ./lib/Target/Sparc/Disassembler/LLVMBuild.txt ------------*- Conf -*--===;
> +;
> +; The LLVM Compiler Infrastructure
> +;
> +; This file is distributed under the University of Illinois Open Source
> +; License. See LICENSE.TXT for details.
> +;
> +;===------------------------------------------------------------------------===;
> +;
> +; This is an LLVMBuild description file for the components in this subdirectory.
> +;
> +; For more information on the LLVMBuild system, please see:
> +;
> +; http://llvm.org/docs/LLVMBuild.html
> +;
> +;===------------------------------------------------------------------------===;
> +
> +[component_0]
> +type = Library
> +name = SparcDisassembler
> +parent = Sparc
> +required_libraries = MC Support SparcInfo
> +add_to_library_groups = Sparc
> Index: lib/Target/Sparc/Disassembler/Makefile
> ===================================================================
> --- lib/Target/Sparc/Disassembler/Makefile (revision 0)
> +++ lib/Target/Sparc/Disassembler/Makefile (working copy)
> @@ -0,0 +1,16 @@
> +##===- lib/Target/Sparc/Disassembler/Makefile --------------*- Makefile -*-===##
> +#
> +# The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +##===----------------------------------------------------------------------===##
> +
> +LEVEL = ../../../..
> +LIBRARYNAME = LLVMSparcDisassembler
> +
> +# Hack: we need to include 'main' Sparc target directory to grab private headers
> +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
> +
> +include $(LEVEL)/Makefile.common
> Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
> ===================================================================
> --- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp (revision 0)
> +++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp (working copy)
> @@ -0,0 +1,228 @@
> +//===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file is part of the Sparc Disassembler.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "sparc-disassembler"
> +
> +#include "Sparc.h"
> +#include "SparcRegisterInfo.h"
> +#include "SparcSubtarget.h"
> +#include "llvm/MC/MCDisassembler.h"
> +#include "llvm/MC/MCFixedLenDisassembler.h"
> +#include "llvm/Support/MemoryObject.h"
> +#include "llvm/Support/TargetRegistry.h"
> +
> +using namespace llvm;
> +
> +typedef MCDisassembler::DecodeStatus DecodeStatus;
> +
> +namespace {
> +
> +/// SparcDisassembler - a disassembler class for Sparc.
> +class SparcDisassembler : public MCDisassembler {
> +public:
> + /// Constructor - Initializes the disassembler.
> + ///
> + SparcDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info) :
> + MCDisassembler(STI), RegInfo(Info)
> + {}
> + virtual ~SparcDisassembler() {}
> +
> + const MCRegisterInfo *getRegInfo() const { return RegInfo.get(); }
> +
> + /// getInstruction - See MCDisassembler.
> + virtual DecodeStatus getInstruction(MCInst &instr,
> + uint64_t &size,
> + const MemoryObject ®ion,
> + uint64_t address,
> + raw_ostream &vStream,
> + raw_ostream &cStream) const;
> +private:
> + OwningPtr<const MCRegisterInfo> RegInfo;
> +};
> +
> +}
> +
> +namespace llvm {
> + extern Target TheSparcTarget, TheSparcV9Target;
> +}
> +
> +static MCDisassembler *createSparcDisassembler(
> + const Target &T,
> + const MCSubtargetInfo &STI) {
> + return new SparcDisassembler(STI, T.createMCRegInfo(""));
> +}
> +
> +
> +extern "C" void LLVMInitializeSparcDisassembler() {
> + // Register the disassembler.
> + TargetRegistry::RegisterMCDisassembler(TheSparcTarget,
> + createSparcDisassembler);
> + TargetRegistry::RegisterMCDisassembler(TheSparcV9Target,
> + createSparcDisassembler);
> +}
> +
> +
> +
> +static const unsigned IntRegDecoderTable[] = {
> + SP::G0, SP::G1, SP::G2, SP::G3,
> + SP::G4, SP::G5, SP::G6, SP::G7,
> + SP::O0, SP::O1, SP::O2, SP::O3,
> + SP::O4, SP::O5, SP::O6, SP::O7,
> + SP::L0, SP::L1, SP::L2, SP::L3,
> + SP::L4, SP::L5, SP::L6, SP::L7,
> + SP::I0, SP::I1, SP::I2, SP::I3,
> + SP::I4, SP::I5, SP::I6, SP::I7 };
> +
> +static const unsigned FPRegDecoderTable[] = {
> + SP::F0, SP::F1, SP::F2, SP::F3,
> + SP::F4, SP::F5, SP::F6, SP::F7,
> + SP::F8, SP::F9, SP::F10, SP::F11,
> + SP::F12, SP::F13, SP::F14, SP::F15,
> + SP::F16, SP::F17, SP::F18, SP::F19,
> + SP::F20, SP::F21, SP::F22, SP::F23,
> + SP::F24, SP::F25, SP::F26, SP::F27,
> + SP::F28, SP::F29, SP::F30, SP::F31 };
> +
> +static const unsigned DFPRegDecoderTable[] = {
> + SP::D0, SP::D16, SP::D1, SP::D17,
> + SP::D2, SP::D18, SP::D3, SP::D19,
> + SP::D4, SP::D20, SP::D5, SP::D21,
> + SP::D6, SP::D22, SP::D7, SP::D23,
> + SP::D8, SP::D24, SP::D9, SP::D25,
> + SP::D10, SP::D26, SP::D11, SP::D27,
> + SP::D12, SP::D28, SP::D13, SP::D29,
> + SP::D14, SP::D30, SP::D15, SP::D31 };
> +
> +static const unsigned QFPRegDecoderTable[] = {
> + SP::Q0, SP::Q8, ~0U, ~0U,
> + SP::Q1, SP::Q9, ~0U, ~0U,
> + SP::Q2, SP::Q10, ~0U, ~0U,
> + SP::Q3, SP::Q11, ~0U, ~0U,
> + SP::Q4, SP::Q12, ~0U, ~0U,
> + SP::Q5, SP::Q13, ~0U, ~0U,
> + SP::Q6, SP::Q14, ~0U, ~0U,
> + SP::Q7, SP::Q15, ~0U, ~0U } ;
> +
> +static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst,
> + unsigned RegNo,
> + uint64_t Address,
> + const void *Decoder) {
> + if (RegNo > 31)
> + return MCDisassembler::Fail;
> + unsigned Reg = IntRegDecoderTable[RegNo];
> + Inst.addOperand(MCOperand::CreateReg(Reg));
> + return MCDisassembler::Success;
> +}
> +
> +static DecodeStatus DecodeI64RegsRegisterClass(MCInst &Inst,
> + unsigned RegNo,
> + uint64_t Address,
> + const void *Decoder) {
> + if (RegNo > 31)
> + return MCDisassembler::Fail;
> + unsigned Reg = IntRegDecoderTable[RegNo];
> + Inst.addOperand(MCOperand::CreateReg(Reg));
> + return MCDisassembler::Success;
> +}
> +
> +
> +static DecodeStatus DecodeFPRegsRegisterClass(MCInst &Inst,
> + unsigned RegNo,
> + uint64_t Address,
> + const void *Decoder) {
> + if (RegNo > 31)
> + return MCDisassembler::Fail;
> + unsigned Reg = FPRegDecoderTable[RegNo];
> + Inst.addOperand(MCOperand::CreateReg(Reg));
> + return MCDisassembler::Success;
> +}
> +
> +
> +static DecodeStatus DecodeDFPRegsRegisterClass(MCInst &Inst,
> + unsigned RegNo,
> + uint64_t Address,
> + const void *Decoder) {
> + if (RegNo > 31)
> + return MCDisassembler::Fail;
> + unsigned Reg = DFPRegDecoderTable[RegNo];
> + Inst.addOperand(MCOperand::CreateReg(Reg));
> + return MCDisassembler::Success;
> +}
> +
> +
> +static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst,
> + unsigned RegNo,
> + uint64_t Address,
> + const void *Decoder) {
> + if (RegNo > 31)
> + return MCDisassembler::Fail;
> +
> + unsigned Reg = QFPRegDecoderTable[RegNo];
> + if (Reg == ~0U)
> + return MCDisassembler::Fail;
> + Inst.addOperand(MCOperand::CreateReg(Reg));
> + return MCDisassembler::Success;
> +}
> +
> +
> +#include "SparcGenDisassemblerTables.inc"
> +
> +/// readInstruction - read four bytes from the MemoryObject
> +/// and return 32 bit word.
> +static DecodeStatus readInstruction32(const MemoryObject ®ion,
> + uint64_t address,
> + uint64_t &size,
> + uint32_t &insn) {
> + uint8_t Bytes[4];
> +
> + // We want to read exactly 4 Bytes of data.
> + if (region.readBytes(address, 4, Bytes) == -1) {
> + size = 0;
> + return MCDisassembler::Fail;
> + }
> +
> + // Encoded as a big-endian 32-bit word in the stream.
> + insn = (Bytes[3] << 0) |
> + (Bytes[2] << 8) |
> + (Bytes[1] << 16) |
> + (Bytes[0] << 24);
> +
> + return MCDisassembler::Success;
> +}
> +
> +
> +DecodeStatus
> +SparcDisassembler::getInstruction(MCInst &instr,
> + uint64_t &Size,
> + const MemoryObject &Region,
> + uint64_t Address,
> + raw_ostream &vStream,
> + raw_ostream &cStream) const {
> + uint32_t Insn;
> +
> + DecodeStatus Result = readInstruction32(Region, Address, Size, Insn);
> + if (Result == MCDisassembler::Fail)
> + return MCDisassembler::Fail;
> +
> +
> + // Calling the auto-generated decoder function.
> + Result = decodeInstruction(DecoderTableSparc32, instr, Insn, Address,
> + this, STI);
> +
> + if (Result != MCDisassembler::Fail) {
> + Size = 4;
> + return Result;
> + }
> +
> + return MCDisassembler::Fail;
> +}
> Index: lib/Target/Sparc/InstPrinter/CMakeLists.txt
> ===================================================================
> --- lib/Target/Sparc/InstPrinter/CMakeLists.txt (revision 0)
> +++ lib/Target/Sparc/InstPrinter/CMakeLists.txt (working copy)
> @@ -0,0 +1,3 @@
> +add_llvm_library(LLVMSparcAsmPrinter
> + SparcInstPrinter.cpp
> + )
> Index: lib/Target/Sparc/InstPrinter/LLVMBuild.txt
> ===================================================================
> --- lib/Target/Sparc/InstPrinter/LLVMBuild.txt (revision 0)
> +++ lib/Target/Sparc/InstPrinter/LLVMBuild.txt (working copy)
> @@ -0,0 +1,23 @@
> +;===- ./lib/Target/Sparc/InstPrinter/LLVMBuild.txt -------------*- Conf -*--===;
> +;
> +; The LLVM Compiler Infrastructure
> +;
> +; This file is distributed under the University of Illinois Open Source
> +; License. See LICENSE.TXT for details.
> +;
> +;===------------------------------------------------------------------------===;
> +;
> +; This is an LLVMBuild description file for the components in this subdirectory.
> +;
> +; For more information on the LLVMBuild system, please see:
> +;
> +; http://llvm.org/docs/LLVMBuild.html
> +;
> +;===------------------------------------------------------------------------===;
> +
> +[component_0]
> +type = Library
> +name = SparcAsmPrinter
> +parent = Sparc
> +required_libraries = MC Support
> +add_to_library_groups = Sparc
> Index: lib/Target/Sparc/InstPrinter/Makefile
> ===================================================================
> --- lib/Target/Sparc/InstPrinter/Makefile (revision 0)
> +++ lib/Target/Sparc/InstPrinter/Makefile (working copy)
> @@ -0,0 +1,16 @@
> +##===- lib/Target/Sparc/InstPrinter/Makefile ---------------*- Makefile -*-===##
> +#
> +# The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +##===----------------------------------------------------------------------===##
> +
> +LEVEL = ../../../..
> +LIBRARYNAME = LLVMSparcAsmPrinter
> +
> +# Hack: we need to include 'main' target directory to grab private headers
> +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
> +
> +include $(LEVEL)/Makefile.common
> Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
> ===================================================================
> --- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp (revision 0)
> +++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp (working copy)
> @@ -0,0 +1,130 @@
> +//===-- SparcInstPrinter.cpp - Convert Sparc MCInst to assembly syntax -----==//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This class prints an Sparc MCInst to a .s file.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "asm-printer"
> +#include "SparcInstPrinter.h"
> +
> +#include "Sparc.h"
> +#include "MCTargetDesc/SparcBaseInfo.h"
> +#include "llvm/MC/MCExpr.h"
> +#include "llvm/MC/MCInst.h"
> +#include "llvm/MC/MCSymbol.h"
> +#include "llvm/Support/raw_ostream.h"
> +using namespace llvm;
> +
> +#define GET_INSTRUCTION_NAME
> +#define PRINT_ALIAS_INSTR
> +#include "SparcGenAsmWriter.inc"
> +
> +void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
> +{
> + OS << '%' << StringRef(getRegisterName(RegNo)).lower();
> +}
> +
> +void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
> + StringRef Annot)
> +{
> + if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O))
> + printInstruction(MI, O);
> + printAnnotation(O, Annot);
> +}
> +
> +bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O)
> +{
> + switch (MI->getOpcode()) {
> + default: return false;
> + case SP::JMPLrr:
> + case SP::JMPLri: {
> + if (MI->getNumOperands() != 3)
> + return false;
> + if (!MI->getOperand(0).isReg())
> + return false;
> + switch (MI->getOperand(0).getReg()) {
> + default: return false;
> + case SP::G0: // jmp $addr
> + O << "\tjmp "; printMemOperand(MI, 1, O);
> + return true;
> + case SP::O7: // call $addr
> + O << "\tcall "; printMemOperand(MI, 1, O);
> + return true;
> + }
> + }
> + }
> +}
> +
> +void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,
> + raw_ostream &O)
> +{
> + const MCOperand &MO = MI->getOperand (opNum);
> +
> + if (MO.isReg()) {
> + printRegName(O, MO.getReg());
> + return ;
> + }
> +
> + if (MO.isImm()) {
> + O << (int)MO.getImm();
> + return;
> + }
> +
> + assert(MO.isExpr() && "Unknown operand kind in printOperand");
> + MO.getExpr()->print(O);
> +}
> +
> +void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum,
> + raw_ostream &O, const char *Modifier)
> +{
> + printOperand(MI, opNum, O);
> +
> + // If this is an ADD operand, emit it like normal operands.
> + if (Modifier && !strcmp(Modifier, "arith")) {
> + O << ", ";
> + printOperand(MI, opNum+1, O);
> + return;
> + }
> + const MCOperand &MO = MI->getOperand(opNum+1);
> +
> + if (MO.isReg() && MO.getReg() == SP::G0)
> + return; // don't print "+%g0"
> + if (MO.isImm() && MO.getImm() == 0)
> + return; // don't print "+0"
> +
> + O << "+";
> +
> + printOperand(MI, opNum+1, O);
> +}
> +
> +void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,
> + raw_ostream &O)
> +{
> + int CC = (int)MI->getOperand(opNum).getImm();
> + switch (MI->getOpcode()) {
> + default: break;
> + case SP::FBCOND:
> + case SP::MOVFCCrr:
> + case SP::MOVFCCri:
> + case SP::FMOVS_FCC:
> + case SP::FMOVD_FCC:
> + case SP::FMOVQ_FCC: // Make sure CC is a fp conditional flag.
> + CC = (CC < 16) ? (CC + 16) : CC;
> + break;
> + }
> + O << SPARCCondCodeToString((SPCC::CondCodes)CC);
> +}
> +
> +bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum,
> + raw_ostream &O)
> +{
> + assert(0 && "FIXME: Implement SparcInstPrinter::printGetPCX.");
> + return true;
> +}
> Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
> ===================================================================
> --- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h (revision 0)
> +++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h (working copy)
> @@ -0,0 +1,48 @@
> +//===-- SparcInstPrinter.h - Convert Sparc MCInst to assembly syntax ------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This class prints an Sparc MCInst to a .s file.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef SparcINSTPRINTER_H
> +#define SparcINSTPRINTER_H
> +
> +#include "llvm/MC/MCInstPrinter.h"
> +
> +namespace llvm {
> +
> +class MCOperand;
> +
> +class SparcInstPrinter : public MCInstPrinter {
> +public:
> + SparcInstPrinter(const MCAsmInfo &MAI,
> + const MCInstrInfo &MII,
> + const MCRegisterInfo &MRI)
> + : MCInstPrinter(MAI, MII, MRI) {}
> +
> + virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
> + virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
> + bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS);
> +
> + // Autogenerated by tblgen.
> + void printInstruction(const MCInst *MI, raw_ostream &O);
> + bool printAliasInstr(const MCInst *MI, raw_ostream &O);
> + static const char *getRegisterName(unsigned RegNo);
> +
> + void printOperand(const MCInst *MI, int opNum, raw_ostream &OS);
> + void printMemOperand(const MCInst *MI, int opNum, raw_ostream &OS,
> + const char *Modifier = 0);
> + void printCCOperand(const MCInst *MI, int opNum, raw_ostream &OS);
> + bool printGetPCX(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
> +
> +};
> +} // end namespace llvm
> +
> +#endif
> Index: lib/Target/Sparc/LLVMBuild.txt
> ===================================================================
> --- lib/Target/Sparc/LLVMBuild.txt (revision 201091)
> +++ lib/Target/Sparc/LLVMBuild.txt (working copy)
> @@ -16,13 +16,15 @@
> ;===------------------------------------------------------------------------===;
>
> [common]
> -subdirectories = MCTargetDesc TargetInfo
> +subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo
>
> [component_0]
> type = TargetGroup
> name = Sparc
> parent = Target
> +has_asmparser = 1
> has_asmprinter = 1
> +has_disassembler = 1
> has_jit = 1
>
> [component_1]
> @@ -29,6 +31,6 @@
> type = Library
> name = SparcCodeGen
> parent = Sparc
> -required_libraries = AsmPrinter CodeGen Core MC SelectionDAG SparcDesc
> - SparcInfo Support Target
> +required_libraries = AsmPrinter CodeGen Core MC SelectionDAG SparcAsmPrinter
> + SparcDesc SparcInfo Support Target
> add_to_library_groups = Sparc
> Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt (revision 201091)
> +++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt (working copy)
> @@ -1,6 +1,11 @@
> add_llvm_library(LLVMSparcDesc
> + SparcAsmBackend.cpp
> + SparcELFObjectWriter.cpp
> + SparcMCAsmInfo.cpp
> + SparcMCCodeEmitter.cpp
> SparcMCTargetDesc.cpp
> - SparcMCAsmInfo.cpp
> + SparcMCExpr.cpp
> + SparcTargetStreamer.cpp
> )
>
> add_dependencies(LLVMSparcDesc SparcCommonTableGen)
> Index: lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt (revision 201091)
> +++ lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt (working copy)
> @@ -19,5 +19,5 @@
> type = Library
> name = SparcDesc
> parent = Sparc
> -required_libraries = MC SparcInfo Support
> +required_libraries = MC SparcAsmPrinter SparcInfo Support
> add_to_library_groups = Sparc
> Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp (revision 0)
> +++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp (working copy)
> @@ -0,0 +1,251 @@
> +//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/MC/MCAsmBackend.h"
> +#include "MCTargetDesc/SparcMCTargetDesc.h"
> +#include "MCTargetDesc/SparcFixupKinds.h"
> +#include "llvm/MC/MCELFObjectWriter.h"
> +#include "llvm/MC/MCFixupKindInfo.h"
> +#include "llvm/MC/MCObjectWriter.h"
> +#include "llvm/Support/TargetRegistry.h"
> +
> +using namespace llvm;
> +
> +static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
> + switch (Kind) {
> + default:
> + llvm_unreachable("Unknown fixup kind!");
> + case FK_Data_1:
> + case FK_Data_2:
> + case FK_Data_4:
> + case FK_Data_8:
> + return Value;
> +
> + case Sparc::fixup_sparc_wplt30:
> + case Sparc::fixup_sparc_call30:
> + return (Value >> 2) & 0x3fffffff;
> +
> + case Sparc::fixup_sparc_br22:
> + return (Value >> 2) & 0x3fffff;
> +
> + case Sparc::fixup_sparc_br19:
> + return (Value >> 2) & 0x7ffff;
> +
> + case Sparc::fixup_sparc_pc22:
> + case Sparc::fixup_sparc_got22:
> + case Sparc::fixup_sparc_tls_gd_hi22:
> + case Sparc::fixup_sparc_tls_ldm_hi22:
> + case Sparc::fixup_sparc_tls_ie_hi22:
> + case Sparc::fixup_sparc_hi22:
> + return (Value >> 10) & 0x3fffff;
> +
> + case Sparc::fixup_sparc_pc10:
> + case Sparc::fixup_sparc_got10:
> + case Sparc::fixup_sparc_tls_gd_lo10:
> + case Sparc::fixup_sparc_tls_ldm_lo10:
> + case Sparc::fixup_sparc_tls_ie_lo10:
> + case Sparc::fixup_sparc_lo10:
> + return Value & 0x3ff;
> +
> + case Sparc::fixup_sparc_tls_ldo_hix22:
> + case Sparc::fixup_sparc_tls_le_hix22:
> + return (~Value >> 10) & 0x3fffff;
> +
> + case Sparc::fixup_sparc_tls_ldo_lox10:
> + case Sparc::fixup_sparc_tls_le_lox10:
> + return (~(~Value & 0x3ff)) & 0x1fff;
> +
> + case Sparc::fixup_sparc_h44:
> + return (Value >> 22) & 0x3fffff;
> +
> + case Sparc::fixup_sparc_m44:
> + return (Value >> 12) & 0x3ff;
> +
> + case Sparc::fixup_sparc_l44:
> + return Value & 0xfff;
> +
> + case Sparc::fixup_sparc_hh:
> + return (Value >> 42) & 0x3fffff;
> +
> + case Sparc::fixup_sparc_hm:
> + return (Value >> 32) & 0x3ff;
> +
> + case Sparc::fixup_sparc_tls_gd_add:
> + case Sparc::fixup_sparc_tls_gd_call:
> + case Sparc::fixup_sparc_tls_ldm_add:
> + case Sparc::fixup_sparc_tls_ldm_call:
> + case Sparc::fixup_sparc_tls_ldo_add:
> + case Sparc::fixup_sparc_tls_ie_ld:
> + case Sparc::fixup_sparc_tls_ie_ldx:
> + case Sparc::fixup_sparc_tls_ie_add:
> + return 0;
> + }
> +}
> +
> +namespace {
> + class SparcAsmBackend : public MCAsmBackend {
> + const Target &TheTarget;
> + public:
> + SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
> +
> + unsigned getNumFixupKinds() const {
> + return Sparc::NumTargetFixupKinds;
> + }
> +
> + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
> + const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = {
> + // name offset bits flags
> + { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
> + { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel },
> + { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel },
> + { "fixup_sparc_hi22", 10, 22, 0 },
> + { "fixup_sparc_lo10", 22, 10, 0 },
> + { "fixup_sparc_h44", 10, 22, 0 },
> + { "fixup_sparc_m44", 22, 10, 0 },
> + { "fixup_sparc_l44", 20, 12, 0 },
> + { "fixup_sparc_hh", 10, 22, 0 },
> + { "fixup_sparc_hm", 22, 10, 0 },
> + { "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel },
> + { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel },
> + { "fixup_sparc_got22", 10, 22, 0 },
> + { "fixup_sparc_got10", 22, 10, 0 },
> + { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
> + { "fixup_sparc_tls_gd_hi22", 10, 22, 0 },
> + { "fixup_sparc_tls_gd_lo10", 22, 10, 0 },
> + { "fixup_sparc_tls_gd_add", 0, 0, 0 },
> + { "fixup_sparc_tls_gd_call", 0, 0, 0 },
> + { "fixup_sparc_tls_ldm_hi22", 10, 22, 0 },
> + { "fixup_sparc_tls_ldm_lo10", 22, 10, 0 },
> + { "fixup_sparc_tls_ldm_add", 0, 0, 0 },
> + { "fixup_sparc_tls_ldm_call", 0, 0, 0 },
> + { "fixup_sparc_tls_ldo_hix22", 10, 22, 0 },
> + { "fixup_sparc_tls_ldo_lox10", 22, 10, 0 },
> + { "fixup_sparc_tls_ldo_add", 0, 0, 0 },
> + { "fixup_sparc_tls_ie_hi22", 10, 22, 0 },
> + { "fixup_sparc_tls_ie_lo10", 22, 10, 0 },
> + { "fixup_sparc_tls_ie_ld", 0, 0, 0 },
> + { "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
> + { "fixup_sparc_tls_ie_add", 0, 0, 0 },
> + { "fixup_sparc_tls_le_hix22", 0, 0, 0 },
> + { "fixup_sparc_tls_le_lox10", 0, 0, 0 }
> + };
> +
> + if (Kind < FirstTargetFixupKind)
> + return MCAsmBackend::getFixupKindInfo(Kind);
> +
> + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
> + "Invalid kind!");
> + return Infos[Kind - FirstTargetFixupKind];
> + }
> +
> + void processFixupValue(const MCAssembler &Asm,
> + const MCAsmLayout &Layout,
> + const MCFixup &Fixup,
> + const MCFragment *DF,
> + MCValue & Target,
> + uint64_t &Value,
> + bool &IsResolved) {
> + switch ((Sparc::Fixups)Fixup.getKind()) {
> + default: break;
> + case Sparc::fixup_sparc_wplt30:
> + case Sparc::fixup_sparc_tls_gd_hi22:
> + case Sparc::fixup_sparc_tls_gd_lo10:
> + case Sparc::fixup_sparc_tls_gd_add:
> + case Sparc::fixup_sparc_tls_gd_call:
> + case Sparc::fixup_sparc_tls_ldm_hi22:
> + case Sparc::fixup_sparc_tls_ldm_lo10:
> + case Sparc::fixup_sparc_tls_ldm_add:
> + case Sparc::fixup_sparc_tls_ldm_call:
> + case Sparc::fixup_sparc_tls_ldo_hix22:
> + case Sparc::fixup_sparc_tls_ldo_lox10:
> + case Sparc::fixup_sparc_tls_ldo_add:
> + case Sparc::fixup_sparc_tls_ie_hi22:
> + case Sparc::fixup_sparc_tls_ie_lo10:
> + case Sparc::fixup_sparc_tls_ie_ld:
> + case Sparc::fixup_sparc_tls_ie_ldx:
> + case Sparc::fixup_sparc_tls_ie_add:
> + case Sparc::fixup_sparc_tls_le_hix22:
> + case Sparc::fixup_sparc_tls_le_lox10: IsResolved = false; break;
> + }
> + }
> +
> + bool mayNeedRelaxation(const MCInst &Inst) const {
> + // FIXME.
> + return false;
> + }
> +
> + /// fixupNeedsRelaxation - Target specific predicate for whether a given
> + /// fixup requires the associated instruction to be relaxed.
> + bool fixupNeedsRelaxation(const MCFixup &Fixup,
> + uint64_t Value,
> + const MCRelaxableFragment *DF,
> + const MCAsmLayout &Layout) const {
> + // FIXME.
> + assert(0 && "fixupNeedsRelaxation() unimplemented");
> + return false;
> + }
> + void relaxInstruction(const MCInst &Inst, MCInst &Res) const {
> + // FIXME.
> + assert(0 && "relaxInstruction() unimplemented");
> + }
> +
> + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const {
> + // FIXME: Zero fill for now.
> + for (uint64_t i = 0; i != Count; ++i)
> + OW->Write8(0);
> + return true;
> + }
> +
> + bool is64Bit() const {
> + StringRef name = TheTarget.getName();
> + return name == "sparcv9";
> + }
> + };
> +
> + class ELFSparcAsmBackend : public SparcAsmBackend {
> + Triple::OSType OSType;
> + public:
> + ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
> + SparcAsmBackend(T), OSType(OSType) { }
> +
> + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
> + uint64_t Value) const {
> +
> + Value = adjustFixupValue(Fixup.getKind(), Value);
> + if (!Value) return; // Doesn't change encoding.
> +
> + unsigned Offset = Fixup.getOffset();
> +
> + // For each byte of the fragment that the fixup touches, mask in the bits
> + // from the fixup value. The Value has been "split up" into the
> + // appropriate bitfields above.
> + for (unsigned i = 0; i != 4; ++i)
> + Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff);
> +
> + }
> +
> + MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
> + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
> + return createSparcELFObjectWriter(OS, is64Bit(), OSABI);
> + }
> +
> + virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
> + return false;
> + }
> + };
> +
> +} // end anonymous namespace
> +
> +
> +MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
> + const MCRegisterInfo &MRI,
> + StringRef TT,
> + StringRef CPU) {
> + return new ELFSparcAsmBackend(T, Triple(TT).getOS());
> +}
> Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp (revision 0)
> +++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp (working copy)
> @@ -0,0 +1,139 @@
> +//===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "MCTargetDesc/SparcFixupKinds.h"
> +#include "MCTargetDesc/SparcMCExpr.h"
> +#include "MCTargetDesc/SparcMCTargetDesc.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/MC/MCELFObjectWriter.h"
> +#include "llvm/MC/MCExpr.h"
> +#include "llvm/MC/MCValue.h"
> +#include "llvm/Support/ErrorHandling.h"
> +
> +using namespace llvm;
> +
> +namespace {
> + class SparcELFObjectWriter : public MCELFObjectTargetWriter {
> + public:
> + SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI)
> + : MCELFObjectTargetWriter(Is64Bit, OSABI,
> + Is64Bit ? ELF::EM_SPARCV9 : ELF::EM_SPARC,
> + /*HasRelocationAddend*/ true) {}
> +
> + virtual ~SparcELFObjectWriter() {}
> + protected:
> + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
> + bool IsPCRel, bool IsRelocWithSymbol,
> + int64_t Addend) const;
> +
> + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
> + const MCValue &Target,
> + const MCFragment &F,
> + const MCFixup &Fixup,
> + bool IsPCRel) const;
> + };
> +}
> +
> +
> +unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target,
> + const MCFixup &Fixup,
> + bool IsPCRel,
> + bool IsRelocWithSymbol,
> + int64_t Addend) const {
> +
> + if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Fixup.getValue())) {
> + if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32)
> + return ELF::R_SPARC_DISP32;
> + }
> +
> + if (IsPCRel) {
> + switch((unsigned)Fixup.getKind()) {
> + default:
> + llvm_unreachable("Unimplemented fixup -> relocation");
> + case FK_Data_1: return ELF::R_SPARC_DISP8;
> + case FK_Data_2: return ELF::R_SPARC_DISP16;
> + case FK_Data_4: return ELF::R_SPARC_DISP32;
> + case FK_Data_8: return ELF::R_SPARC_DISP64;
> + case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30;
> + case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22;
> + case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19;
> + case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22;
> + case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10;
> + case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30;
> + }
> + }
> +
> + switch((unsigned)Fixup.getKind()) {
> + default:
> + llvm_unreachable("Unimplemented fixup -> relocation");
> + case FK_Data_1: return ELF::R_SPARC_8;
> + case FK_Data_2: return ((Fixup.getOffset() % 2)
> + ? ELF::R_SPARC_UA16
> + : ELF::R_SPARC_16);
> + case FK_Data_4: return ((Fixup.getOffset() % 4)
> + ? ELF::R_SPARC_UA32
> + : ELF::R_SPARC_32);
> + case FK_Data_8: return ((Fixup.getOffset() % 8)
> + ? ELF::R_SPARC_UA64
> + : ELF::R_SPARC_64);
> + case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22;
> + case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10;
> + case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44;
> + case Sparc::fixup_sparc_m44: return ELF::R_SPARC_M44;
> + case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44;
> + case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22;
> + case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10;
> + case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22;
> + case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10;
> + case Sparc::fixup_sparc_tls_gd_hi22: return ELF::R_SPARC_TLS_GD_HI22;
> + case Sparc::fixup_sparc_tls_gd_lo10: return ELF::R_SPARC_TLS_GD_LO10;
> + case Sparc::fixup_sparc_tls_gd_add: return ELF::R_SPARC_TLS_GD_ADD;
> + case Sparc::fixup_sparc_tls_gd_call: return ELF::R_SPARC_TLS_GD_CALL;
> + case Sparc::fixup_sparc_tls_ldm_hi22: return ELF::R_SPARC_TLS_LDM_HI22;
> + case Sparc::fixup_sparc_tls_ldm_lo10: return ELF::R_SPARC_TLS_LDM_LO10;
> + case Sparc::fixup_sparc_tls_ldm_add: return ELF::R_SPARC_TLS_LDM_ADD;
> + case Sparc::fixup_sparc_tls_ldm_call: return ELF::R_SPARC_TLS_LDM_CALL;
> + case Sparc::fixup_sparc_tls_ldo_hix22: return ELF::R_SPARC_TLS_LDO_HIX22;
> + case Sparc::fixup_sparc_tls_ldo_lox10: return ELF::R_SPARC_TLS_LDO_LOX10;
> + case Sparc::fixup_sparc_tls_ldo_add: return ELF::R_SPARC_TLS_LDO_ADD;
> + case Sparc::fixup_sparc_tls_ie_hi22: return ELF::R_SPARC_TLS_IE_HI22;
> + case Sparc::fixup_sparc_tls_ie_lo10: return ELF::R_SPARC_TLS_IE_LO10;
> + case Sparc::fixup_sparc_tls_ie_ld: return ELF::R_SPARC_TLS_IE_LD;
> + case Sparc::fixup_sparc_tls_ie_ldx: return ELF::R_SPARC_TLS_IE_LDX;
> + case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD;
> + case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22;
> + case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10;
> + }
> +
> + return ELF::R_SPARC_NONE;
> +}
> +
> +const MCSymbol *SparcELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
> + const MCValue &Target,
> + const MCFragment &F,
> + const MCFixup &Fixup,
> + bool IsPCRel) const {
> +
> + if (!Target.getSymA())
> + return NULL;
> + switch((unsigned)Fixup.getKind()) {
> + default: break;
> + case Sparc::fixup_sparc_got22:
> + case Sparc::fixup_sparc_got10:
> + return &Target.getSymA()->getSymbol().AliasedSymbol();
> + }
> + return NULL;
> +}
> +
> +MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS,
> + bool Is64Bit,
> + uint8_t OSABI) {
> + MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI);
> + return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
> +}
> Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h (revision 0)
> +++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h (working copy)
> @@ -0,0 +1,93 @@
> +//===-- SparcFixupKinds.h - Sparc Specific Fixup Entries --------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_SPARC_FIXUPKINDS_H
> +#define LLVM_SPARC_FIXUPKINDS_H
> +
> +#include "llvm/MC/MCFixup.h"
> +
> +namespace llvm {
> + namespace Sparc {
> + enum Fixups {
> + // fixup_sparc_call30 - 30-bit PC relative relocation for call
> + fixup_sparc_call30 = FirstTargetFixupKind,
> +
> + /// fixup_sparc_br22 - 22-bit PC relative relocation for
> + /// branches
> + fixup_sparc_br22,
> +
> + /// fixup_sparc_br19 - 19-bit PC relative relocation for
> + /// branches on icc/xcc
> + fixup_sparc_br19,
> +
> + /// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo)
> + /// for sethi
> + fixup_sparc_hi22,
> +
> + /// fixup_sparc_lo10 - 10-bit fixup corresponding to %lo(foo)
> + fixup_sparc_lo10,
> +
> + /// fixup_sparc_h44 - 22-bit fixup corresponding to %h44(foo)
> + fixup_sparc_h44,
> +
> + /// fixup_sparc_m44 - 10-bit fixup corresponding to %m44(foo)
> + fixup_sparc_m44,
> +
> + /// fixup_sparc_l44 - 12-bit fixup corresponding to %l44(foo)
> + fixup_sparc_l44,
> +
> + /// fixup_sparc_hh - 22-bit fixup corresponding to %hh(foo)
> + fixup_sparc_hh,
> +
> + /// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo)
> + fixup_sparc_hm,
> +
> + /// fixup_sparc_pc22 - 22-bit fixup corresponding to %pc22(foo)
> + fixup_sparc_pc22,
> +
> + /// fixup_sparc_pc10 - 10-bit fixup corresponding to %pc10(foo)
> + fixup_sparc_pc10,
> +
> + /// fixup_sparc_got22 - 22-bit fixup corresponding to %got22(foo)
> + fixup_sparc_got22,
> +
> + /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo)
> + fixup_sparc_got10,
> +
> + /// fixup_sparc_wplt30
> + fixup_sparc_wplt30,
> +
> + /// fixups for Thread Local Storage
> + fixup_sparc_tls_gd_hi22,
> + fixup_sparc_tls_gd_lo10,
> + fixup_sparc_tls_gd_add,
> + fixup_sparc_tls_gd_call,
> + fixup_sparc_tls_ldm_hi22,
> + fixup_sparc_tls_ldm_lo10,
> + fixup_sparc_tls_ldm_add,
> + fixup_sparc_tls_ldm_call,
> + fixup_sparc_tls_ldo_hix22,
> + fixup_sparc_tls_ldo_lox10,
> + fixup_sparc_tls_ldo_add,
> + fixup_sparc_tls_ie_hi22,
> + fixup_sparc_tls_ie_lo10,
> + fixup_sparc_tls_ie_ld,
> + fixup_sparc_tls_ie_ldx,
> + fixup_sparc_tls_ie_add,
> + fixup_sparc_tls_le_hix22,
> + fixup_sparc_tls_le_lox10,
> +
> + // Marker
> + LastTargetFixupKind,
> + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
> + };
> + }
> +}
> +
> +#endif
> Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp (revision 201091)
> +++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp (working copy)
> @@ -12,7 +12,9 @@
> //===----------------------------------------------------------------------===//
>
> #include "SparcMCAsmInfo.h"
> +#include "SparcMCExpr.h"
> #include "llvm/ADT/Triple.h"
> +#include "llvm/MC/MCStreamer.h"
>
> using namespace llvm;
>
> @@ -44,4 +46,27 @@
> PrivateGlobalPrefix = ".L";
> }
>
> +const MCExpr*
> +SparcELFMCAsmInfo::getExprForPersonalitySymbol(const MCSymbol *Sym,
> + unsigned Encoding,
> + MCStreamer &Streamer) const {
> + if (Encoding & dwarf::DW_EH_PE_pcrel) {
> + MCContext &Ctx = Streamer.getContext();
> + return SparcMCExpr::Create(SparcMCExpr::VK_Sparc_R_DISP32,
> + MCSymbolRefExpr::Create(Sym, Ctx), Ctx);
> + }
>
> + return MCAsmInfo::getExprForPersonalitySymbol(Sym, Encoding, Streamer);
> +}
> +
> +const MCExpr*
> +SparcELFMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
> + unsigned Encoding,
> + MCStreamer &Streamer) const {
> + if (Encoding & dwarf::DW_EH_PE_pcrel) {
> + MCContext &Ctx = Streamer.getContext();
> + return SparcMCExpr::Create(SparcMCExpr::VK_Sparc_R_DISP32,
> + MCSymbolRefExpr::Create(Sym, Ctx), Ctx);
> + }
> + return MCAsmInfo::getExprForFDESymbol(Sym, Encoding, Streamer);
> +}
> Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h (revision 201091)
> +++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h (working copy)
> @@ -17,14 +17,21 @@
> #include "llvm/MC/MCAsmInfoELF.h"
>
> namespace llvm {
> - class StringRef;
> +class StringRef;
>
> - class SparcELFMCAsmInfo : public MCAsmInfoELF {
> - virtual void anchor();
> - public:
> - explicit SparcELFMCAsmInfo(StringRef TT);
> - };
> +class SparcELFMCAsmInfo : public MCAsmInfoELF {
> + virtual void anchor();
> +public:
> + explicit SparcELFMCAsmInfo(StringRef TT);
> + virtual const MCExpr* getExprForPersonalitySymbol(const MCSymbol *Sym,
> + unsigned Encoding,
> + MCStreamer &Streamer) const;
> + virtual const MCExpr* getExprForFDESymbol(const MCSymbol *Sym,
> + unsigned Encoding,
> + MCStreamer &Streamer) const;
>
> +};
> +
> } // namespace llvm
>
> #endif
> Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp (revision 0)
> +++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp (working copy)
> @@ -0,0 +1,176 @@
> +//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements the SparcMCCodeEmitter class.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "mccodeemitter"
> +#include "SparcMCExpr.h"
> +#include "SparcMCTargetDesc.h"
> +#include "MCTargetDesc/SparcFixupKinds.h"
> +#include "llvm/MC/MCCodeEmitter.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCExpr.h"
> +#include "llvm/MC/MCInst.h"
> +#include "llvm/MC/MCRegisterInfo.h"
> +#include "llvm/ADT/Statistic.h"
> +#include "llvm/MC/MCSymbol.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +
> +STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
> +
> +namespace {
> +class SparcMCCodeEmitter : public MCCodeEmitter {
> + SparcMCCodeEmitter(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
> + void operator=(const SparcMCCodeEmitter &) LLVM_DELETED_FUNCTION;
> + MCContext &Ctx;
> +
> +public:
> + SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
> +
> + ~SparcMCCodeEmitter() {}
> +
> + void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
> + SmallVectorImpl<MCFixup> &Fixups) const;
> +
> + // getBinaryCodeForInstr - TableGen'erated function for getting the
> + // binary encoding for an instruction.
> + uint64_t getBinaryCodeForInstr(const MCInst &MI,
> + SmallVectorImpl<MCFixup> &Fixups) const;
> +
> + /// getMachineOpValue - Return binary encoding of operand. If the machine
> + /// operand requires relocation, record the relocation and return zero.
> + unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
> + SmallVectorImpl<MCFixup> &Fixups) const;
> +
> + unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
> + SmallVectorImpl<MCFixup> &Fixups) const;
> + unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
> + SmallVectorImpl<MCFixup> &Fixups) const;
> +
> +};
> +} // end anonymous namespace
> +
> +MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
> + const MCRegisterInfo &MRI,
> + const MCSubtargetInfo &STI,
> + MCContext &Ctx) {
> + return new SparcMCCodeEmitter(Ctx);
> +}
> +
> +void SparcMCCodeEmitter::
> +EncodeInstruction(const MCInst &MI, raw_ostream &OS,
> + SmallVectorImpl<MCFixup> &Fixups) const {
> + unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
> +
> + // Output the constant in big endian byte order.
> + for (unsigned i = 0; i != 4; ++i) {
> + OS << (char)(Bits >> 24);
> + Bits <<= 8;
> + }
> + unsigned tlsOpNo = 0;
> + switch (MI.getOpcode()) {
> + default: break;
> + case SP::TLS_CALL: tlsOpNo = 1; break;
> + case SP::TLS_ADDrr:
> + case SP::TLS_ADDXrr:
> + case SP::TLS_LDrr:
> + case SP::TLS_LDXrr: tlsOpNo = 3; break;
> + }
> + if (tlsOpNo != 0) {
> + const MCOperand &MO = MI.getOperand(tlsOpNo);
> + uint64_t op = getMachineOpValue(MI, MO, Fixups);
> + assert(op == 0 && "Unexpected operand value!");
> + (void)op; // suppress warning.
> + }
> +
> + ++MCNumEmitted; // Keep track of the # of mi's emitted.
> +}
> +
> +
> +unsigned SparcMCCodeEmitter::
> +getMachineOpValue(const MCInst &MI, const MCOperand &MO,
> + SmallVectorImpl<MCFixup> &Fixups) const {
> +
> + if (MO.isReg())
> + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
> +
> + if (MO.isImm())
> + return MO.getImm();
> +
> + assert(MO.isExpr());
> + const MCExpr *Expr = MO.getExpr();
> + if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
> + MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
> + Fixups.push_back(MCFixup::Create(0, Expr, Kind));
> + return 0;
> + }
> +
> + int64_t Res;
> + if (Expr->EvaluateAsAbsolute(Res))
> + return Res;
> +
> + assert(0 && "Unhandled expression!");
> + return 0;
> +}
> +
> +unsigned SparcMCCodeEmitter::
> +getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
> + SmallVectorImpl<MCFixup> &Fixups) const {
> + const MCOperand &MO = MI.getOperand(OpNo);
> + if (MO.isReg() || MO.isImm())
> + return getMachineOpValue(MI, MO, Fixups);
> +
> + if (MI.getOpcode() == SP::TLS_CALL) {
> + // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
> + // EncodeInstruction.
> +#ifndef NDEBUG
> + // Verify that the callee is actually __tls_get_addr.
> + const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
> + assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
> + "Unexpected expression in TLS_CALL");
> + const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
> + assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
> + "Unexpected function for TLS_CALL");
> +#endif
> + return 0;
> + }
> +
> + MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
> +
> + if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
> + if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
> + fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
> + }
> +
> + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind));
> +
> + return 0;
> +}
> +
> +unsigned SparcMCCodeEmitter::
> +getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
> + SmallVectorImpl<MCFixup> &Fixups) const {
> + const MCOperand &MO = MI.getOperand(OpNo);
> + if (MO.isReg() || MO.isImm())
> + return getMachineOpValue(MI, MO, Fixups);
> +
> + Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
> + if (MI.getOpcode() == SP::BPXCC)
> + fixup = Sparc::fixup_sparc_br19;
> +
> + Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
> + (MCFixupKind)fixup));
> + return 0;
> +}
> +
> +#include "SparcGenMCCodeEmitter.inc"
> Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp (revision 0)
> +++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp (working copy)
> @@ -0,0 +1,254 @@
> +//===-- SparcMCExpr.cpp - Sparc specific MC expression classes --------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains the implementation of the assembly expression modifiers
> +// accepted by the Sparc architecture (e.g. "%hi", "%lo", ...).
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#define DEBUG_TYPE "sparcmcexpr"
> +#include "SparcMCExpr.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCAssembler.h"
> +#include "llvm/MC/MCELF.h"
> +#include "llvm/MC/MCSymbol.h"
> +#include "llvm/Object/ELF.h"
> +
> +
> +using namespace llvm;
> +
> +const SparcMCExpr*
> +SparcMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
> + MCContext &Ctx) {
> + return new (Ctx) SparcMCExpr(Kind, Expr);
> +}
> +
> +
> +
> +void SparcMCExpr::PrintImpl(raw_ostream &OS) const
> +{
> +
> + bool closeParen = printVariantKind(OS, Kind);
> +
> + const MCExpr *Expr = getSubExpr();
> + Expr->print(OS);
> +
> + if (closeParen)
> + OS << ')';
> +}
> +
> +bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind)
> +{
> + bool closeParen = true;
> + switch (Kind) {
> + case VK_Sparc_None: closeParen = false; break;
> + case VK_Sparc_LO: OS << "%lo("; break;
> + case VK_Sparc_HI: OS << "%hi("; break;
> + case VK_Sparc_H44: OS << "%h44("; break;
> + case VK_Sparc_M44: OS << "%m44("; break;
> + case VK_Sparc_L44: OS << "%l44("; break;
> + case VK_Sparc_HH: OS << "%hh("; break;
> + case VK_Sparc_HM: OS << "%hm("; break;
> + // FIXME: use %pc22/%pc10, if system assembler supports them.
> + case VK_Sparc_PC22: OS << "%hi("; break;
> + case VK_Sparc_PC10: OS << "%lo("; break;
> + // FIXME: use %got22/%got10, if system assembler supports them.
> + case VK_Sparc_GOT22: OS << "%hi("; break;
> + case VK_Sparc_GOT10: OS << "%lo("; break;
> + case VK_Sparc_WPLT30: closeParen = false; break;
> + case VK_Sparc_R_DISP32: OS << "%r_disp32("; break;
> + case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break;
> + case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; break;
> + case VK_Sparc_TLS_GD_ADD: OS << "%tgd_add("; break;
> + case VK_Sparc_TLS_GD_CALL: OS << "%tgd_call("; break;
> + case VK_Sparc_TLS_LDM_HI22: OS << "%tldm_hi22("; break;
> + case VK_Sparc_TLS_LDM_LO10: OS << "%tldm_lo10("; break;
> + case VK_Sparc_TLS_LDM_ADD: OS << "%tldm_add("; break;
> + case VK_Sparc_TLS_LDM_CALL: OS << "%tldm_call("; break;
> + case VK_Sparc_TLS_LDO_HIX22: OS << "%tldo_hix22("; break;
> + case VK_Sparc_TLS_LDO_LOX10: OS << "%tldo_lox10("; break;
> + case VK_Sparc_TLS_LDO_ADD: OS << "%tldo_add("; break;
> + case VK_Sparc_TLS_IE_HI22: OS << "%tie_hi22("; break;
> + case VK_Sparc_TLS_IE_LO10: OS << "%tie_lo10("; break;
> + case VK_Sparc_TLS_IE_LD: OS << "%tie_ld("; break;
> + case VK_Sparc_TLS_IE_LDX: OS << "%tie_ldx("; break;
> + case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; break;
> + case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; break;
> + case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; break;
> + }
> + return closeParen;
> +}
> +
> +SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name)
> +{
> + return StringSwitch<SparcMCExpr::VariantKind>(name)
> + .Case("lo", VK_Sparc_LO)
> + .Case("hi", VK_Sparc_HI)
> + .Case("h44", VK_Sparc_H44)
> + .Case("m44", VK_Sparc_M44)
> + .Case("l44", VK_Sparc_L44)
> + .Case("hh", VK_Sparc_HH)
> + .Case("hm", VK_Sparc_HM)
> + .Case("pc22", VK_Sparc_PC22)
> + .Case("pc10", VK_Sparc_PC10)
> + .Case("got22", VK_Sparc_GOT22)
> + .Case("got10", VK_Sparc_GOT10)
> + .Case("r_disp32", VK_Sparc_R_DISP32)
> + .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22)
> + .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10)
> + .Case("tgd_add", VK_Sparc_TLS_GD_ADD)
> + .Case("tgd_call", VK_Sparc_TLS_GD_CALL)
> + .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22)
> + .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10)
> + .Case("tldm_add", VK_Sparc_TLS_LDM_ADD)
> + .Case("tldm_call", VK_Sparc_TLS_LDM_CALL)
> + .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22)
> + .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10)
> + .Case("tldo_add", VK_Sparc_TLS_LDO_ADD)
> + .Case("tie_hi22", VK_Sparc_TLS_IE_HI22)
> + .Case("tie_lo10", VK_Sparc_TLS_IE_LO10)
> + .Case("tie_ld", VK_Sparc_TLS_IE_LD)
> + .Case("tie_ldx", VK_Sparc_TLS_IE_LDX)
> + .Case("tie_add", VK_Sparc_TLS_IE_ADD)
> + .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22)
> + .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10)
> + .Default(VK_Sparc_None);
> +}
> +
> +Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) {
> + switch (Kind) {
> + default: assert(0 && "Unhandled SparcMCExpr::VariantKind");
> + case VK_Sparc_LO: return Sparc::fixup_sparc_lo10;
> + case VK_Sparc_HI: return Sparc::fixup_sparc_hi22;
> + case VK_Sparc_H44: return Sparc::fixup_sparc_h44;
> + case VK_Sparc_M44: return Sparc::fixup_sparc_m44;
> + case VK_Sparc_L44: return Sparc::fixup_sparc_l44;
> + case VK_Sparc_HH: return Sparc::fixup_sparc_hh;
> + case VK_Sparc_HM: return Sparc::fixup_sparc_hm;
> + case VK_Sparc_PC22: return Sparc::fixup_sparc_pc22;
> + case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10;
> + case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22;
> + case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10;
> + case VK_Sparc_WPLT30: return Sparc::fixup_sparc_wplt30;
> + case VK_Sparc_TLS_GD_HI22: return Sparc::fixup_sparc_tls_gd_hi22;
> + case VK_Sparc_TLS_GD_LO10: return Sparc::fixup_sparc_tls_gd_lo10;
> + case VK_Sparc_TLS_GD_ADD: return Sparc::fixup_sparc_tls_gd_add;
> + case VK_Sparc_TLS_GD_CALL: return Sparc::fixup_sparc_tls_gd_call;
> + case VK_Sparc_TLS_LDM_HI22: return Sparc::fixup_sparc_tls_ldm_hi22;
> + case VK_Sparc_TLS_LDM_LO10: return Sparc::fixup_sparc_tls_ldm_lo10;
> + case VK_Sparc_TLS_LDM_ADD: return Sparc::fixup_sparc_tls_ldm_add;
> + case VK_Sparc_TLS_LDM_CALL: return Sparc::fixup_sparc_tls_ldm_call;
> + case VK_Sparc_TLS_LDO_HIX22: return Sparc::fixup_sparc_tls_ldo_hix22;
> + case VK_Sparc_TLS_LDO_LOX10: return Sparc::fixup_sparc_tls_ldo_lox10;
> + case VK_Sparc_TLS_LDO_ADD: return Sparc::fixup_sparc_tls_ldo_add;
> + case VK_Sparc_TLS_IE_HI22: return Sparc::fixup_sparc_tls_ie_hi22;
> + case VK_Sparc_TLS_IE_LO10: return Sparc::fixup_sparc_tls_ie_lo10;
> + case VK_Sparc_TLS_IE_LD: return Sparc::fixup_sparc_tls_ie_ld;
> + case VK_Sparc_TLS_IE_LDX: return Sparc::fixup_sparc_tls_ie_ldx;
> + case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add;
> + case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22;
> + case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10;
> + }
> +}
> +
> +bool
> +SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
> + const MCAsmLayout *Layout) const {
> + if (!Layout)
> + return false;
> + return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
> +}
> +
> +static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
> + switch (Expr->getKind()) {
> + case MCExpr::Target:
> + llvm_unreachable("Can't handle nested target expr!");
> + break;
> +
> + case MCExpr::Constant:
> + break;
> +
> + case MCExpr::Binary: {
> + const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
> + fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
> + fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
> + break;
> + }
> +
> + case MCExpr::SymbolRef: {
> + const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
> + MCSymbolData &SD = Asm.getOrCreateSymbolData(SymRef.getSymbol());
> + MCELF::SetType(SD, ELF::STT_TLS);
> + break;
> + }
> +
> + case MCExpr::Unary:
> + fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
> + break;
> + }
> +
> +}
> +
> +void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
> + switch(getKind()) {
> + default: return;
> + case VK_Sparc_TLS_GD_HI22:
> + case VK_Sparc_TLS_GD_LO10:
> + case VK_Sparc_TLS_GD_ADD:
> + case VK_Sparc_TLS_GD_CALL:
> + case VK_Sparc_TLS_LDM_HI22:
> + case VK_Sparc_TLS_LDM_LO10:
> + case VK_Sparc_TLS_LDM_ADD:
> + case VK_Sparc_TLS_LDM_CALL:
> + case VK_Sparc_TLS_LDO_HIX22:
> + case VK_Sparc_TLS_LDO_LOX10:
> + case VK_Sparc_TLS_LDO_ADD:
> + case VK_Sparc_TLS_IE_HI22:
> + case VK_Sparc_TLS_IE_LO10:
> + case VK_Sparc_TLS_IE_LD:
> + case VK_Sparc_TLS_IE_LDX:
> + case VK_Sparc_TLS_IE_ADD:
> + case VK_Sparc_TLS_LE_HIX22:
> + case VK_Sparc_TLS_LE_LOX10: break;
> + }
> + fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
> +}
> +
> +// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
> +// that method should be made public?
> +// FIXME: really do above: now that at least three other backends are using it.
> +static void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) {
> + switch (Value->getKind()) {
> + case MCExpr::Target:
> + llvm_unreachable("Can't handle nested target expr!");
> + break;
> +
> + case MCExpr::Constant:
> + break;
> +
> + case MCExpr::Binary: {
> + const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
> + AddValueSymbolsImpl(BE->getLHS(), Asm);
> + AddValueSymbolsImpl(BE->getRHS(), Asm);
> + break;
> + }
> +
> + case MCExpr::SymbolRef:
> + Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
> + break;
> +
> + case MCExpr::Unary:
> + AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
> + break;
> + }
> +}
> +
> +void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const {
> + AddValueSymbolsImpl(getSubExpr(), Asm);
> +}
> Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h (revision 0)
> +++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h (working copy)
> @@ -0,0 +1,111 @@
> +//====- SparcMCExpr.h - Sparc specific MC expression classes --*- C++ -*-=====//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file describes Sparc-specific MCExprs, used for modifiers like
> +// "%hi" or "%lo" etc.,
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_SPARCMCEXPR_H
> +#define LLVM_SPARCMCEXPR_H
> +
> +#include "SparcFixupKinds.h"
> +#include "llvm/MC/MCExpr.h"
> +
> +namespace llvm {
> +
> +class StringRef;
> +class SparcMCExpr : public MCTargetExpr {
> +public:
> + enum VariantKind {
> + VK_Sparc_None,
> + VK_Sparc_LO,
> + VK_Sparc_HI,
> + VK_Sparc_H44,
> + VK_Sparc_M44,
> + VK_Sparc_L44,
> + VK_Sparc_HH,
> + VK_Sparc_HM,
> + VK_Sparc_PC22,
> + VK_Sparc_PC10,
> + VK_Sparc_GOT22,
> + VK_Sparc_GOT10,
> + VK_Sparc_WPLT30,
> + VK_Sparc_R_DISP32,
> + VK_Sparc_TLS_GD_HI22,
> + VK_Sparc_TLS_GD_LO10,
> + VK_Sparc_TLS_GD_ADD,
> + VK_Sparc_TLS_GD_CALL,
> + VK_Sparc_TLS_LDM_HI22,
> + VK_Sparc_TLS_LDM_LO10,
> + VK_Sparc_TLS_LDM_ADD,
> + VK_Sparc_TLS_LDM_CALL,
> + VK_Sparc_TLS_LDO_HIX22,
> + VK_Sparc_TLS_LDO_LOX10,
> + VK_Sparc_TLS_LDO_ADD,
> + VK_Sparc_TLS_IE_HI22,
> + VK_Sparc_TLS_IE_LO10,
> + VK_Sparc_TLS_IE_LD,
> + VK_Sparc_TLS_IE_LDX,
> + VK_Sparc_TLS_IE_ADD,
> + VK_Sparc_TLS_LE_HIX22,
> + VK_Sparc_TLS_LE_LOX10
> + };
> +
> +private:
> + const VariantKind Kind;
> + const MCExpr *Expr;
> +
> + explicit SparcMCExpr(VariantKind _Kind, const MCExpr *_Expr)
> + : Kind(_Kind), Expr(_Expr) {}
> +
> +public:
> + /// @name Construction
> + /// @{
> +
> + static const SparcMCExpr *Create(VariantKind Kind, const MCExpr *Expr,
> + MCContext &Ctx);
> + /// @}
> + /// @name Accessors
> + /// @{
> +
> + /// getOpcode - Get the kind of this expression.
> + VariantKind getKind() const { return Kind; }
> +
> + /// getSubExpr - Get the child of this expression.
> + const MCExpr *getSubExpr() const { return Expr; }
> +
> + /// getFixupKind - Get the fixup kind of this expression.
> + Sparc::Fixups getFixupKind() const { return getFixupKind(Kind); }
> +
> + /// @}
> + void PrintImpl(raw_ostream &OS) const;
> + bool EvaluateAsRelocatableImpl(MCValue &Res,
> + const MCAsmLayout *Layout) const;
> + void AddValueSymbols(MCAssembler *) const;
> + const MCSection *FindAssociatedSection() const {
> + return getSubExpr()->FindAssociatedSection();
> + }
> +
> + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const;
> +
> + static bool classof(const MCExpr *E) {
> + return E->getKind() == MCExpr::Target;
> + }
> +
> + static bool classof(const SparcMCExpr *) { return true; }
> +
> + static VariantKind parseVariantKind(StringRef name);
> + static bool printVariantKind(raw_ostream &OS, VariantKind Kind);
> + static Sparc::Fixups getFixupKind(VariantKind Kind);
> +};
> +
> +} // end namespace llvm.
> +
> +#endif
> Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp (revision 201091)
> +++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp (working copy)
> @@ -13,6 +13,8 @@
>
> #include "SparcMCTargetDesc.h"
> #include "SparcMCAsmInfo.h"
> +#include "SparcTargetStreamer.h"
> +#include "InstPrinter/SparcInstPrinter.h"
> #include "llvm/MC/MCCodeGenInfo.h"
> #include "llvm/MC/MCInstrInfo.h"
> #include "llvm/MC/MCRegisterInfo.h"
> @@ -31,6 +33,25 @@
>
> using namespace llvm;
>
> +
> +static MCAsmInfo *createSparcMCAsmInfo(const MCRegisterInfo &MRI,
> + StringRef TT) {
> + MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT);
> + unsigned Reg = MRI.getDwarfRegNum(SP::O6, true);
> + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, Reg, 0);
> + MAI->addInitialFrameState(Inst);
> + return MAI;
> +}
> +
> +static MCAsmInfo *createSparcV9MCAsmInfo(const MCRegisterInfo &MRI,
> + StringRef TT) {
> + MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT);
> + unsigned Reg = MRI.getDwarfRegNum(SP::O6, true);
> + MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, Reg, 2047);
> + MAI->addInitialFrameState(Inst);
> + return MAI;
> +}
> +
> static MCInstrInfo *createSparcMCInstrInfo() {
> MCInstrInfo *X = new MCInstrInfo();
> InitSparcMCInstrInfo(X);
> @@ -39,7 +60,7 @@
>
> static MCRegisterInfo *createSparcMCRegisterInfo(StringRef TT) {
> MCRegisterInfo *X = new MCRegisterInfo();
> - InitSparcMCRegisterInfo(X, SP::I7);
> + InitSparcMCRegisterInfo(X, SP::O7);
> return X;
> }
>
> @@ -66,9 +87,13 @@
> CodeGenOpt::Level OL) {
> MCCodeGenInfo *X = new MCCodeGenInfo();
>
> - // The default 32-bit code model is abs32/pic32.
> - if (CM == CodeModel::Default)
> - CM = RM == Reloc::PIC_ ? CodeModel::Medium : CodeModel::Small;
> + // The default 32-bit code model is abs32/pic32 and the default 32-bit
> + // code model for JIT is abs32.
> + switch (CM) {
> + default: break;
> + case CodeModel::Default:
> + case CodeModel::JITDefault: CM = CodeModel::Small; break;
> + }
>
> X->InitMCCodeGenInfo(RM, CM, OL);
> return X;
> @@ -79,17 +104,55 @@
> CodeGenOpt::Level OL) {
> MCCodeGenInfo *X = new MCCodeGenInfo();
>
> - // The default 64-bit code model is abs44/pic32.
> - if (CM == CodeModel::Default)
> - CM = CodeModel::Medium;
> + // The default 64-bit code model is abs44/pic32 and the default 64-bit
> + // code model for JIT is abs64.
> + switch (CM) {
> + default: break;
> + case CodeModel::Default:
> + CM = RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium;
> + break;
> + case CodeModel::JITDefault:
> + CM = CodeModel::Large;
> + break;
> + }
>
> X->InitMCCodeGenInfo(RM, CM, OL);
> return X;
> }
> +
> +static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
> + MCContext &Context, MCAsmBackend &MAB,
> + raw_ostream &OS, MCCodeEmitter *Emitter,
> + bool RelaxAll, bool NoExecStack) {
> + SparcTargetELFStreamer *S = new SparcTargetELFStreamer();
> + return createELFStreamer(Context, S, MAB, OS, Emitter, RelaxAll, NoExecStack);
> +}
> +
> +static MCStreamer *
> +createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
> + bool isVerboseAsm, bool useLoc, bool useCFI,
> + bool useDwarfDirectory, MCInstPrinter *InstPrint,
> + MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) {
> + SparcTargetAsmStreamer *S = new SparcTargetAsmStreamer(OS);
> +
> + return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI,
> + useDwarfDirectory, InstPrint, CE, TAB,
> + ShowInst);
> +}
> +
> +static MCInstPrinter *createSparcMCInstPrinter(const Target &T,
> + unsigned SyntaxVariant,
> + const MCAsmInfo &MAI,
> + const MCInstrInfo &MII,
> + const MCRegisterInfo &MRI,
> + const MCSubtargetInfo &STI) {
> + return new SparcInstPrinter(MAI, MII, MRI);
> +}
> +
> extern "C" void LLVMInitializeSparcTargetMC() {
> // Register the MC asm info.
> - RegisterMCAsmInfo<SparcELFMCAsmInfo> X(TheSparcTarget);
> - RegisterMCAsmInfo<SparcELFMCAsmInfo> Y(TheSparcV9Target);
> + RegisterMCAsmInfoFn X(TheSparcTarget, createSparcMCAsmInfo);
> + RegisterMCAsmInfoFn Y(TheSparcV9Target, createSparcV9MCAsmInfo);
>
> // Register the MC codegen info.
> TargetRegistry::RegisterMCCodeGenInfo(TheSparcTarget,
> @@ -99,11 +162,46 @@
>
> // Register the MC instruction info.
> TargetRegistry::RegisterMCInstrInfo(TheSparcTarget, createSparcMCInstrInfo);
> + TargetRegistry::RegisterMCInstrInfo(TheSparcV9Target, createSparcMCInstrInfo);
>
> // Register the MC register info.
> TargetRegistry::RegisterMCRegInfo(TheSparcTarget, createSparcMCRegisterInfo);
> + TargetRegistry::RegisterMCRegInfo(TheSparcV9Target,
> + createSparcMCRegisterInfo);
>
> // Register the MC subtarget info.
> TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget,
> createSparcMCSubtargetInfo);
> + TargetRegistry::RegisterMCSubtargetInfo(TheSparcV9Target,
> + createSparcMCSubtargetInfo);
> +
> + // Register the MC Code Emitter.
> + TargetRegistry::RegisterMCCodeEmitter(TheSparcTarget,
> + createSparcMCCodeEmitter);
> + TargetRegistry::RegisterMCCodeEmitter(TheSparcV9Target,
> + createSparcMCCodeEmitter);
> +
> + //Register the asm backend.
> + TargetRegistry::RegisterMCAsmBackend(TheSparcTarget,
> + createSparcAsmBackend);
> + TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target,
> + createSparcAsmBackend);
> +
> + // Register the object streamer.
> + TargetRegistry::RegisterMCObjectStreamer(TheSparcTarget,
> + createMCStreamer);
> + TargetRegistry::RegisterMCObjectStreamer(TheSparcV9Target,
> + createMCStreamer);
> +
> + // Register the asm streamer.
> + TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
> + createMCAsmStreamer);
> + TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
> + createMCAsmStreamer);
> +
> + // Register the MCInstPrinter
> + TargetRegistry::RegisterMCInstPrinter(TheSparcTarget,
> + createSparcMCInstPrinter);
> + TargetRegistry::RegisterMCInstPrinter(TheSparcV9Target,
> + createSparcMCInstPrinter);
> }
> Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h (revision 201091)
> +++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h (working copy)
> @@ -14,12 +14,34 @@
> #ifndef SPARCMCTARGETDESC_H
> #define SPARCMCTARGETDESC_H
>
> +#include "llvm/Support/DataTypes.h"
> +
> namespace llvm {
> +class MCAsmBackend;
> +class MCCodeEmitter;
> +class MCContext;
> +class MCInstrInfo;
> +class MCObjectWriter;
> +class MCRegisterInfo;
> +class MCSubtargetInfo;
> class Target;
> +class StringRef;
> +class raw_ostream;
>
> extern Target TheSparcTarget;
> extern Target TheSparcV9Target;
>
> +MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII,
> + const MCRegisterInfo &MRI,
> + const MCSubtargetInfo &STI,
> + MCContext &Ctx);
> +MCAsmBackend *createSparcAsmBackend(const Target &T,
> + const MCRegisterInfo &MRI,
> + StringRef TT,
> + StringRef CPU);
> +MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS,
> + bool Is64Bit,
> + uint8_t OSABI);
> } // End llvm namespace
>
> // Defines symbolic names for Sparc registers. This defines a mapping from
> Index: lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
> ===================================================================
> --- lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp (revision 0)
> +++ lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp (working copy)
> @@ -0,0 +1,40 @@
> +//===-- SparcTargetStreamer.cpp - Sparc Target Streamer Methods -----------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file provides Sparc specific target streamer methods.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "SparcTargetStreamer.h"
> +#include "InstPrinter/SparcInstPrinter.h"
> +#include "llvm/Support/FormattedStream.h"
> +
> +using namespace llvm;
> +
> +// pin vtable to this file
> +void SparcTargetStreamer::anchor() {}
> +
> +SparcTargetAsmStreamer::SparcTargetAsmStreamer(formatted_raw_ostream &OS)
> + : OS(OS) {}
> +
> +void SparcTargetAsmStreamer::emitSparcRegisterIgnore(unsigned reg) {
> + OS << "\t.register "
> + << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower()
> + << ", #ignore\n";
> +}
> +
> +void SparcTargetAsmStreamer::emitSparcRegisterScratch(unsigned reg) {
> + OS << "\t.register "
> + << "%" << StringRef(SparcInstPrinter::getRegisterName(reg)).lower()
> + << ", #scratch\n";
> +}
> +
> +MCELFStreamer &SparcTargetELFStreamer::getStreamer() {
> + return static_cast<MCELFStreamer &>(*Streamer);
> +}
> Index: lib/Target/Sparc/Makefile
> ===================================================================
> --- lib/Target/Sparc/Makefile (revision 201091)
> +++ lib/Target/Sparc/Makefile (working copy)
> @@ -13,11 +13,12 @@
>
> # Make sure that tblgen is run, first thing.
> BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \
> - SparcGenAsmWriter.inc SparcGenDAGISel.inc \
> + SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \
> + SparcGenDAGISel.inc SparcGenDisassemblerTables.inc \
> SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
> - SparcGenCodeEmitter.inc
> + SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc
>
> -DIRS = TargetInfo MCTargetDesc
> +DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc
>
> include $(LEVEL)/Makefile.common
>
> Index: lib/Target/Sparc/Sparc.h
> ===================================================================
> --- lib/Target/Sparc/Sparc.h (revision 201091)
> +++ lib/Target/Sparc/Sparc.h (working copy)
> @@ -23,6 +23,9 @@
> class FunctionPass;
> class SparcTargetMachine;
> class formatted_raw_ostream;
> + class AsmPrinter;
> + class MCInst;
> + class MachineInstr;
>
> FunctionPass *createSparcISelDag(SparcTargetMachine &TM);
> FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM);
> @@ -29,6 +32,9 @@
> FunctionPass *createSparcJITCodeEmitterPass(SparcTargetMachine &TM,
> JITCodeEmitter &JCE);
>
> + void LowerSparcMachineInstrToMCInst(const MachineInstr *MI,
> + MCInst &OutMI,
> + AsmPrinter &AP);
> } // end namespace llvm;
>
> namespace llvm {
> Index: lib/Target/Sparc/Sparc.td
> ===================================================================
> --- lib/Target/Sparc/Sparc.td (revision 201091)
> +++ lib/Target/Sparc/Sparc.td (working copy)
> @@ -34,6 +34,9 @@
> : SubtargetFeature<"hard-quad-float", "HasHardQuad", "true",
> "Enable quad-word floating point instructions">;
>
> +def UsePopc : SubtargetFeature<"popc", "UsePopc", "true",
> + "Use the popc (population count) instruction">;
> +
> //===----------------------------------------------------------------------===//
> // Register File, Calling Conv, Instruction Descriptions
> //===----------------------------------------------------------------------===//
> @@ -44,6 +47,10 @@
>
> def SparcInstrInfo : InstrInfo;
>
> +def SparcAsmParser : AsmParser {
> + bit ShouldEmitMatchRegisterName = 0;
> +}
> +
> //===----------------------------------------------------------------------===//
> // SPARC processors supported.
> //===----------------------------------------------------------------------===//
> @@ -52,6 +59,7 @@
> : Processor<Name, NoItineraries, Features>;
>
> def : Proc<"generic", []>;
> +def : Proc<"v7", []>;
> def : Proc<"v8", []>;
> def : Proc<"supersparc", []>;
> def : Proc<"sparclite", []>;
> @@ -63,8 +71,15 @@
> def : Proc<"v9", [FeatureV9]>;
> def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated]>;
> def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>;
> -def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
> +def : Proc<"niagara", [FeatureV9, FeatureV8Deprecated]>;
> +def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated, UsePopc]>;
> +def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated, UsePopc]>;
> +def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated, UsePopc]>;
>
> +def SparcAsmWriter : AsmWriter {
> + string AsmWriterClassName = "InstPrinter";
> + bit isMCAsmWriter = 1;
> +}
>
> //===----------------------------------------------------------------------===//
> // Declare the target which we are implementing
> @@ -73,4 +88,7 @@
> def Sparc : Target {
> // Pull in Instruction Info:
> let InstructionSet = SparcInstrInfo;
> + let AssemblyParsers = [SparcAsmParser];
> +
> + let AssemblyWriters = [SparcAsmWriter];
> }
> Index: lib/Target/Sparc/SparcAsmPrinter.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcAsmPrinter.cpp (revision 201091)
> +++ lib/Target/Sparc/SparcAsmPrinter.cpp (working copy)
> @@ -16,12 +16,18 @@
> #include "Sparc.h"
> #include "SparcInstrInfo.h"
> #include "SparcTargetMachine.h"
> -#include "MCTargetDesc/SparcBaseInfo.h"
> +#include "SparcTargetStreamer.h"
> +#include "InstPrinter/SparcInstPrinter.h"
> +#include "MCTargetDesc/SparcMCExpr.h"
> #include "llvm/ADT/SmallString.h"
> #include "llvm/CodeGen/AsmPrinter.h"
> #include "llvm/CodeGen/MachineInstr.h"
> +#include "llvm/CodeGen/MachineModuleInfoImpls.h"
> #include "llvm/CodeGen/MachineRegisterInfo.h"
> +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
> #include "llvm/MC/MCAsmInfo.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCInst.h"
> #include "llvm/MC/MCStreamer.h"
> #include "llvm/MC/MCSymbol.h"
> #include "llvm/Support/TargetRegistry.h"
> @@ -31,6 +37,9 @@
>
> namespace {
> class SparcAsmPrinter : public AsmPrinter {
> + SparcTargetStreamer &getTargetStreamer() {
> + return static_cast<SparcTargetStreamer&>(OutStreamer.getTargetStreamer());
> + }
> public:
> explicit SparcAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
> : AsmPrinter(TM, Streamer) {}
> @@ -45,14 +54,12 @@
> void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
>
> virtual void EmitFunctionBodyStart();
> - virtual void EmitInstruction(const MachineInstr *MI) {
> - SmallString<128> Str;
> - raw_svector_ostream OS(Str);
> - printInstruction(MI, OS);
> - OutStreamer.EmitRawText(OS.str());
> + virtual void EmitInstruction(const MachineInstr *MI);
> + virtual void EmitEndOfAsmFile(Module &M);
> +
> + static const char *getRegisterName(unsigned RegNo) {
> + return SparcInstPrinter::getRegisterName(RegNo);
> }
> - void printInstruction(const MachineInstr *MI, raw_ostream &OS);// autogen'd.
> - static const char *getRegisterName(unsigned RegNo);
>
> bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
> unsigned AsmVariant, const char *ExtraCode,
> @@ -61,25 +68,203 @@
> unsigned AsmVariant, const char *ExtraCode,
> raw_ostream &O);
>
> - bool printGetPCX(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS);
> + void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI);
>
> - virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB)
> - const;
> - void EmitGlobalRegisterDecl(unsigned reg) {
> - SmallString<128> Str;
> - raw_svector_ostream OS(Str);
> - OS << "\t.register "
> - << "%" << StringRef(getRegisterName(reg)).lower()
> - << ", "
> - << ((reg == SP::G6 || reg == SP::G7)? "#ignore" : "#scratch");
> - OutStreamer.EmitRawText(OS.str());
> - }
> -
> };
> } // end of anonymous namespace
>
> -#include "SparcGenAsmWriter.inc"
> +static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
> + MCSymbol *Sym, MCContext &OutContext) {
> + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym,
> + OutContext);
> + const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext);
> + return MCOperand::CreateExpr(expr);
>
> +}
> +static MCOperand createPCXCallOP(MCSymbol *Label,
> + MCContext &OutContext) {
> + return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
> +}
> +
> +static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
> + MCSymbol *GOTLabel, MCSymbol *StartLabel,
> + MCSymbol *CurLabel,
> + MCContext &OutContext)
> +{
> + const MCSymbolRefExpr *GOT = MCSymbolRefExpr::Create(GOTLabel, OutContext);
> + const MCSymbolRefExpr *Start = MCSymbolRefExpr::Create(StartLabel,
> + OutContext);
> + const MCSymbolRefExpr *Cur = MCSymbolRefExpr::Create(CurLabel,
> + OutContext);
> +
> + const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Cur, Start, OutContext);
> + const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(GOT, Sub, OutContext);
> + const SparcMCExpr *expr = SparcMCExpr::Create(Kind,
> + Add, OutContext);
> + return MCOperand::CreateExpr(expr);
> +}
> +
> +static void EmitCall(MCStreamer &OutStreamer,
> + MCOperand &Callee)
> +{
> + MCInst CallInst;
> + CallInst.setOpcode(SP::CALL);
> + CallInst.addOperand(Callee);
> + OutStreamer.EmitInstruction(CallInst);
> +}
> +
> +static void EmitSETHI(MCStreamer &OutStreamer,
> + MCOperand &Imm, MCOperand &RD)
> +{
> + MCInst SETHIInst;
> + SETHIInst.setOpcode(SP::SETHIi);
> + SETHIInst.addOperand(RD);
> + SETHIInst.addOperand(Imm);
> + OutStreamer.EmitInstruction(SETHIInst);
> +}
> +
> +static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
> + MCOperand &RS1, MCOperand &Src2, MCOperand &RD)
> +{
> + MCInst Inst;
> + Inst.setOpcode(Opcode);
> + Inst.addOperand(RD);
> + Inst.addOperand(RS1);
> + Inst.addOperand(Src2);
> + OutStreamer.EmitInstruction(Inst);
> +}
> +
> +static void EmitOR(MCStreamer &OutStreamer,
> + MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
> + EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD);
> +}
> +
> +static void EmitADD(MCStreamer &OutStreamer,
> + MCOperand &RS1, MCOperand &RS2, MCOperand &RD) {
> + EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD);
> +}
> +
> +static void EmitSHL(MCStreamer &OutStreamer,
> + MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
> + EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD);
> +}
> +
> +
> +static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
> + SparcMCExpr::VariantKind HiKind,
> + SparcMCExpr::VariantKind LoKind,
> + MCOperand &RD,
> + MCContext &OutContext) {
> +
> + MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
> + MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
> + EmitSETHI(OutStreamer, hi, RD);
> + EmitOR(OutStreamer, RD, lo, RD);
> +}
> +
> +void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI)
> +{
> + MCSymbol *GOTLabel =
> + OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
> +
> + const MachineOperand &MO = MI->getOperand(0);
> + assert(MO.getReg() != SP::O7 &&
> + "%o7 is assigned as destination for getpcx!");
> +
> + MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg());
> +
> +
> + if (TM.getRelocationModel() != Reloc::PIC_) {
> + // Just load the address of GOT to MCRegOP.
> + switch(TM.getCodeModel()) {
> + default:
> + llvm_unreachable("Unsupported absolute code model");
> + case CodeModel::Small:
> + EmitHiLo(OutStreamer, GOTLabel,
> + SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
> + MCRegOP, OutContext);
> + break;
> + case CodeModel::Medium: {
> + EmitHiLo(OutStreamer, GOTLabel,
> + SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
> + MCRegOP, OutContext);
> + MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12,
> + OutContext));
> + EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
> + MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
> + GOTLabel, OutContext);
> + EmitOR(OutStreamer, MCRegOP, lo, MCRegOP);
> + break;
> + }
> + case CodeModel::Large: {
> + EmitHiLo(OutStreamer, GOTLabel,
> + SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
> + MCRegOP, OutContext);
> + MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32,
> + OutContext));
> + EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
> + // Use register %o7 to load the lower 32 bits.
> + MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
> + EmitHiLo(OutStreamer, GOTLabel,
> + SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
> + RegO7, OutContext);
> + EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP);
> + }
> + }
> + return;
> + }
> +
> + MCSymbol *StartLabel = OutContext.CreateTempSymbol();
> + MCSymbol *EndLabel = OutContext.CreateTempSymbol();
> + MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
> +
> + MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
> +
> + // <StartLabel>:
> + // call <EndLabel>
> + // <SethiLabel>:
> + // sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
> + // <EndLabel>:
> + // or <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
> + // add <MO>, %o7, <MO>
> +
> + OutStreamer.EmitLabel(StartLabel);
> + MCOperand Callee = createPCXCallOP(EndLabel, OutContext);
> + EmitCall(OutStreamer, Callee);
> + OutStreamer.EmitLabel(SethiLabel);
> + MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22,
> + GOTLabel, StartLabel, SethiLabel,
> + OutContext);
> + EmitSETHI(OutStreamer, hiImm, MCRegOP);
> + OutStreamer.EmitLabel(EndLabel);
> + MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10,
> + GOTLabel, StartLabel, EndLabel,
> + OutContext);
> + EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP);
> + EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP);
> +}
> +
> +void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
> +{
> +
> + switch (MI->getOpcode()) {
> + default: break;
> + case TargetOpcode::DBG_VALUE:
> + // FIXME: Debug Value.
> + return;
> + case SP::GETPCX:
> + LowerGETPCXAndEmitMCInsts(MI);
> + return;
> + }
> + MachineBasicBlock::const_instr_iterator I = MI;
> + MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
> + do {
> + MCInst TmpInst;
> + LowerSparcMachineInstrToMCInst(I, TmpInst, *this);
> + OutStreamer.EmitInstruction(TmpInst);
> + } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
> +}
> +
> void SparcAsmPrinter::EmitFunctionBodyStart() {
> if (!TM.getSubtarget<SparcSubtarget>().is64Bit())
> return;
> @@ -90,7 +275,11 @@
> unsigned reg = globalRegs[i];
> if (MRI.use_empty(reg))
> continue;
> - EmitGlobalRegisterDecl(reg);
> +
> + if (reg == SP::G6 || reg == SP::G7)
> + getTargetStreamer().emitSparcRegisterIgnore(reg);
> + else
> + getTargetStreamer().emitSparcRegisterScratch(reg);
> }
> }
>
> @@ -97,83 +286,60 @@
> void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
> raw_ostream &O) {
> const MachineOperand &MO = MI->getOperand (opNum);
> - unsigned TF = MO.getTargetFlags();
> + SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags();
> +
> #ifndef NDEBUG
> // Verify the target flags.
> if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
> if (MI->getOpcode() == SP::CALL)
> - assert(TF == SPII::MO_NO_FLAG &&
> + assert(TF == SparcMCExpr::VK_Sparc_None &&
> "Cannot handle target flags on call address");
> - else if (MI->getOpcode() == SP::SETHIi)
> - assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH
> - || TF == SPII::MO_TLS_GD_HI22
> - || TF == SPII::MO_TLS_LDM_HI22
> - || TF == SPII::MO_TLS_LDO_HIX22
> - || TF == SPII::MO_TLS_IE_HI22
> - || TF == SPII::MO_TLS_LE_HIX22) &&
> + else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
> + assert((TF == SparcMCExpr::VK_Sparc_HI
> + || TF == SparcMCExpr::VK_Sparc_H44
> + || TF == SparcMCExpr::VK_Sparc_HH
> + || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22
> + || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22
> + || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22
> + || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22
> + || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) &&
> "Invalid target flags for address operand on sethi");
> else if (MI->getOpcode() == SP::TLS_CALL)
> - assert((TF == SPII::MO_NO_FLAG
> - || TF == SPII::MO_TLS_GD_CALL
> - || TF == SPII::MO_TLS_LDM_CALL) &&
> + assert((TF == SparcMCExpr::VK_Sparc_None
> + || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL
> + || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) &&
> "Cannot handle target flags on tls call address");
> else if (MI->getOpcode() == SP::TLS_ADDrr)
> - assert((TF == SPII::MO_TLS_GD_ADD || TF == SPII::MO_TLS_LDM_ADD
> - || TF == SPII::MO_TLS_LDO_ADD || TF == SPII::MO_TLS_IE_ADD) &&
> + assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD
> + || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD
> + || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD
> + || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) &&
> "Cannot handle target flags on add for TLS");
> else if (MI->getOpcode() == SP::TLS_LDrr)
> - assert(TF == SPII::MO_TLS_IE_LD &&
> + assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD &&
> "Cannot handle target flags on ld for TLS");
> else if (MI->getOpcode() == SP::TLS_LDXrr)
> - assert(TF == SPII::MO_TLS_IE_LDX &&
> + assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX &&
> "Cannot handle target flags on ldx for TLS");
> - else if (MI->getOpcode() == SP::XORri)
> - assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) &&
> + else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
> + assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10
> + || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) &&
> "Cannot handle target flags on xor for TLS");
> else
> - assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44
> - || TF == SPII::MO_HM
> - || TF == SPII::MO_TLS_GD_LO10
> - || TF == SPII::MO_TLS_LDM_LO10
> - || TF == SPII::MO_TLS_IE_LO10 ) &&
> + assert((TF == SparcMCExpr::VK_Sparc_LO
> + || TF == SparcMCExpr::VK_Sparc_M44
> + || TF == SparcMCExpr::VK_Sparc_L44
> + || TF == SparcMCExpr::VK_Sparc_HM
> + || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10
> + || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10
> + || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) &&
> "Invalid target flags for small address operand");
> }
> #endif
>
> - bool CloseParen = true;
> - switch (TF) {
> - default:
> - llvm_unreachable("Unknown target flags on operand");
> - case SPII::MO_NO_FLAG:
> - CloseParen = false;
> - break;
> - case SPII::MO_LO: O << "%lo("; break;
> - case SPII::MO_HI: O << "%hi("; break;
> - case SPII::MO_H44: O << "%h44("; break;
> - case SPII::MO_M44: O << "%m44("; break;
> - case SPII::MO_L44: O << "%l44("; break;
> - case SPII::MO_HH: O << "%hh("; break;
> - case SPII::MO_HM: O << "%hm("; break;
> - case SPII::MO_TLS_GD_HI22: O << "%tgd_hi22("; break;
> - case SPII::MO_TLS_GD_LO10: O << "%tgd_lo10("; break;
> - case SPII::MO_TLS_GD_ADD: O << "%tgd_add("; break;
> - case SPII::MO_TLS_GD_CALL: O << "%tgd_call("; break;
> - case SPII::MO_TLS_LDM_HI22: O << "%tldm_hi22("; break;
> - case SPII::MO_TLS_LDM_LO10: O << "%tldm_lo10("; break;
> - case SPII::MO_TLS_LDM_ADD: O << "%tldm_add("; break;
> - case SPII::MO_TLS_LDM_CALL: O << "%tldm_call("; break;
> - case SPII::MO_TLS_LDO_HIX22: O << "%tldo_hix22("; break;
> - case SPII::MO_TLS_LDO_LOX10: O << "%tldo_lox10("; break;
> - case SPII::MO_TLS_LDO_ADD: O << "%tldo_add("; break;
> - case SPII::MO_TLS_IE_HI22: O << "%tie_hi22("; break;
> - case SPII::MO_TLS_IE_LO10: O << "%tie_lo10("; break;
> - case SPII::MO_TLS_IE_LD: O << "%tie_ld("; break;
> - case SPII::MO_TLS_IE_LDX: O << "%tie_ldx("; break;
> - case SPII::MO_TLS_IE_ADD: O << "%tie_add("; break;
> - case SPII::MO_TLS_LE_HIX22: O << "%tle_hix22("; break;
> - case SPII::MO_TLS_LE_LOX10: O << "%tle_lox10("; break;
> - }
>
> + bool CloseParen = SparcMCExpr::printVariantKind(O, TF);
> +
> switch (MO.getType()) {
> case MachineOperand::MO_Register:
> O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
> @@ -226,46 +392,6 @@
> printOperand(MI, opNum+1, O);
> }
>
> -bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum,
> - raw_ostream &O) {
> - std::string operand = "";
> - const MachineOperand &MO = MI->getOperand(opNum);
> - switch (MO.getType()) {
> - default: llvm_unreachable("Operand is not a register");
> - case MachineOperand::MO_Register:
> - assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
> - "Operand is not a physical register ");
> - assert(MO.getReg() != SP::O7 &&
> - "%o7 is assigned as destination for getpcx!");
> - operand = "%" + StringRef(getRegisterName(MO.getReg())).lower();
> - break;
> - }
> -
> - unsigned mfNum = MI->getParent()->getParent()->getFunctionNumber();
> - unsigned bbNum = MI->getParent()->getNumber();
> -
> - O << '\n' << ".LLGETPCH" << mfNum << '_' << bbNum << ":\n";
> - O << "\tcall\t.LLGETPC" << mfNum << '_' << bbNum << '\n' ;
> -
> - O << "\t sethi\t"
> - << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum
> - << ")), " << operand << '\n' ;
> -
> - O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ;
> - O << "\tor\t" << operand
> - << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum
> - << ")), " << operand << '\n';
> - O << "\tadd\t" << operand << ", %o7, " << operand << '\n';
> -
> - return true;
> -}
> -
> -void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum,
> - raw_ostream &O) {
> - int CC = (int)MI->getOperand(opNum).getImm();
> - O << SPARCCondCodeToString((SPCC::CondCodes)CC);
> -}
> -
> /// PrintAsmOperand - Print out an operand for an inline asm expression.
> ///
> bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
> @@ -303,35 +429,21 @@
> return false;
> }
>
> -/// isBlockOnlyReachableByFallthough - Return true if the basic block has
> -/// exactly one predecessor and the control transfer mechanism between
> -/// the predecessor and this block is a fall-through.
> -///
> -/// This overrides AsmPrinter's implementation to handle delay slots.
> -bool SparcAsmPrinter::
> -isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
> - // If this is a landing pad, it isn't a fall through. If it has no preds,
> - // then nothing falls through to it.
> - if (MBB->isLandingPad() || MBB->pred_empty())
> - return false;
> +void SparcAsmPrinter::EmitEndOfAsmFile(Module &M) {
> + const TargetLoweringObjectFileELF &TLOFELF =
> + static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
> + MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
>
> - // If there isn't exactly one predecessor, it can't be a fall through.
> - MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI;
> - ++PI2;
> - if (PI2 != MBB->pred_end())
> - return false;
> -
> - // The predecessor has to be immediately before this block.
> - const MachineBasicBlock *Pred = *PI;
> -
> - if (!Pred->isLayoutSuccessor(MBB))
> - return false;
> -
> - // Check if the last terminator is an unconditional branch.
> - MachineBasicBlock::const_iterator I = Pred->end();
> - while (I != Pred->begin() && !(--I)->isTerminator())
> - ; // Noop
> - return I == Pred->end() || !I->isBarrier();
> + // Generate stubs for global variables.
> + MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
> + if (!Stubs.empty()) {
> + OutStreamer.SwitchSection(TLOFELF.getDataSection());
> + unsigned PtrSize = TM.getDataLayout()->getPointerSize(0);
> + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
> + OutStreamer.EmitLabel(Stubs[i].first);
> + OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), PtrSize);
> + }
> + }
> }
>
> // Force static initialization.
> Index: lib/Target/Sparc/SparcCallingConv.td
> ===================================================================
> --- lib/Target/Sparc/SparcCallingConv.td (revision 201091)
> +++ lib/Target/Sparc/SparcCallingConv.td (working copy)
> @@ -103,7 +103,7 @@
> // Function return values are passed exactly like function arguments, except a
> // struct up to 32 bytes in size can be returned in registers.
>
> -// Function arguments AND return values.
> +// Function arguments AND most return values.
> def CC_Sparc64 : CallingConv<[
> // The frontend uses the inreg flag to indicate i32 and float arguments from
> // structs. These arguments are not promoted to 64 bits, but they can still
> @@ -118,6 +118,15 @@
> CCCustom<"CC_Sparc64_Full">
> ]>;
>
> +def RetCC_Sparc64 : CallingConv<[
> + // A single f32 return value always goes in %f0. The ABI doesn't specify what
> + // happens to multiple f32 return values outside a struct.
> + CCIfType<[f32], CCCustom<"CC_Sparc64_Half">>,
> +
> + // Otherwise, return values are passed exactly like arguments.
> + CCDelegateTo<CC_Sparc64>
> +]>;
> +
> // Callee-saved registers are handled by the register window mechanism.
> def CSR : CalleeSavedRegs<(add)> {
> let OtherPreserved = (add (sequence "I%u", 0, 7),
> Index: lib/Target/Sparc/SparcCodeEmitter.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcCodeEmitter.cpp (revision 201091)
> +++ lib/Target/Sparc/SparcCodeEmitter.cpp (working copy)
> @@ -14,7 +14,7 @@
>
> #define DEBUG_TYPE "jit"
> #include "Sparc.h"
> -#include "MCTargetDesc/SparcBaseInfo.h"
> +#include "MCTargetDesc/SparcMCExpr.h"
> #include "SparcRelocations.h"
> #include "SparcTargetMachine.h"
> #include "llvm/ADT/Statistic.h"
> @@ -72,6 +72,11 @@
> unsigned getMachineOpValue(const MachineInstr &MI,
> const MachineOperand &MO) const;
>
> + unsigned getCallTargetOpValue(const MachineInstr &MI,
> + unsigned) const;
> + unsigned getBranchTargetOpValue(const MachineInstr &MI,
> + unsigned) const;
> +
> void emitWord(unsigned Word);
>
> unsigned getRelocation(const MachineInstr &MI,
> @@ -181,6 +186,18 @@
> llvm_unreachable("Unable to encode MachineOperand!");
> return 0;
> }
> +unsigned SparcCodeEmitter::getCallTargetOpValue(const MachineInstr &MI,
> + unsigned opIdx) const {
> + const MachineOperand MO = MI.getOperand(opIdx);
> + return getMachineOpValue(MI, MO);
> +}
> +
> +unsigned SparcCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
> + unsigned opIdx) const {
> + const MachineOperand MO = MI.getOperand(opIdx);
> + return getMachineOpValue(MI, MO);
> +}
> +
> unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI,
> const MachineOperand &MO) const {
>
> @@ -187,14 +204,14 @@
> unsigned TF = MO.getTargetFlags();
> switch (TF) {
> default:
> - case SPII::MO_NO_FLAG: break;
> - case SPII::MO_LO: return SP::reloc_sparc_lo;
> - case SPII::MO_HI: return SP::reloc_sparc_hi;
> - case SPII::MO_H44:
> - case SPII::MO_M44:
> - case SPII::MO_L44:
> - case SPII::MO_HH:
> - case SPII::MO_HM: assert(0 && "FIXME: Implement Medium/Large code model.");
> + case SparcMCExpr::VK_Sparc_None: break;
> + case SparcMCExpr::VK_Sparc_LO: return SP::reloc_sparc_lo;
> + case SparcMCExpr::VK_Sparc_HI: return SP::reloc_sparc_hi;
> + case SparcMCExpr::VK_Sparc_H44: return SP::reloc_sparc_h44;
> + case SparcMCExpr::VK_Sparc_M44: return SP::reloc_sparc_m44;
> + case SparcMCExpr::VK_Sparc_L44: return SP::reloc_sparc_l44;
> + case SparcMCExpr::VK_Sparc_HH: return SP::reloc_sparc_hh;
> + case SparcMCExpr::VK_Sparc_HM: return SP::reloc_sparc_hm;
> }
>
> unsigned Opc = MI.getOpcode();
> Index: lib/Target/Sparc/SparcISelLowering.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcISelLowering.cpp (revision 201091)
> +++ lib/Target/Sparc/SparcISelLowering.cpp (working copy)
> @@ -13,10 +13,12 @@
> //===----------------------------------------------------------------------===//
>
> #include "SparcISelLowering.h"
> +#include "MCTargetDesc/SparcMCExpr.h"
> #include "SparcMachineFunctionInfo.h"
> #include "SparcRegisterInfo.h"
> #include "SparcTargetMachine.h"
> #include "MCTargetDesc/SparcBaseInfo.h"
> +#include "SparcTargetObjectFile.h"
> #include "llvm/CodeGen/CallingConvLower.h"
> #include "llvm/CodeGen/MachineFrameInfo.h"
> #include "llvm/CodeGen/MachineFunction.h"
> @@ -80,11 +82,14 @@
> static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT,
> MVT &LocVT, CCValAssign::LocInfo &LocInfo,
> ISD::ArgFlagsTy &ArgFlags, CCState &State) {
> - assert((LocVT == MVT::f32 || LocVT.getSizeInBits() == 64) &&
> + assert((LocVT == MVT::f32 || LocVT == MVT::f128
> + || LocVT.getSizeInBits() == 64) &&
> "Can't handle non-64 bits locations");
>
> // Stack space is allocated for all arguments starting from [%fp+BIAS+128].
> - unsigned Offset = State.AllocateStack(8, 8);
> + unsigned size = (LocVT == MVT::f128) ? 16 : 8;
> + unsigned alignment = (LocVT == MVT::f128) ? 16 : 8;
> + unsigned Offset = State.AllocateStack(size, alignment);
> unsigned Reg = 0;
>
> if (LocVT == MVT::i64 && Offset < 6*8)
> @@ -96,6 +101,9 @@
> else if (LocVT == MVT::f32 && Offset < 16*8)
> // Promote floats to %f1, %f3, ...
> Reg = SP::F1 + Offset/4;
> + else if (LocVT == MVT::f128 && Offset < 16*8)
> + // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7).
> + Reg = SP::Q0 + Offset/16;
>
> // Promote to register when possible, otherwise use the stack slot.
> if (Reg) {
> @@ -248,7 +256,7 @@
> DAG.getTarget(), RVLocs, *DAG.getContext());
>
> // Analyze return values.
> - CCInfo.AnalyzeReturn(Outs, CC_Sparc64);
> + CCInfo.AnalyzeReturn(Outs, RetCC_Sparc64);
>
> SDValue Flag;
> SmallVector<SDValue, 4> RetOps(1, Chain);
> @@ -888,10 +896,12 @@
> // If the callee is a GlobalAddress node (quite common, every direct call is)
> // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
> // Likewise ExternalSymbol -> TargetExternalSymbol.
> + unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
> + ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
> if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
> - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
> + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF);
> else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
> - Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
> + Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF);
>
> // Returns a chain & a flag for retval copy to use
> SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
> @@ -998,9 +1008,10 @@
> ArrayRef<ISD::OutputArg> Outs) {
> for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
> const CCValAssign &VA = ArgLocs[i];
> + MVT ValTy = VA.getLocVT();
> // FIXME: What about f32 arguments? C promotes them to f64 when calling
> // varargs functions.
> - if (!VA.isRegLoc() || VA.getLocVT() != MVT::f64)
> + if (!VA.isRegLoc() || (ValTy != MVT::f64 && ValTy != MVT::f128))
> continue;
> // The fixed arguments to a varargs function still go in FP registers.
> if (Outs[VA.getValNo()].IsFixed)
> @@ -1010,15 +1021,25 @@
> CCValAssign NewVA;
>
> // Determine the offset into the argument array.
> - unsigned Offset = 8 * (VA.getLocReg() - SP::D0);
> + unsigned firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0;
> + unsigned argSize = (ValTy == MVT::f64) ? 8 : 16;
> + unsigned Offset = argSize * (VA.getLocReg() - firstReg);
> assert(Offset < 16*8 && "Offset out of range, bad register enum?");
>
> if (Offset < 6*8) {
> // This argument should go in %i0-%i5.
> unsigned IReg = SP::I0 + Offset/8;
> - // Full register, just bitconvert into i64.
> - NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
> - IReg, MVT::i64, CCValAssign::BCvt);
> + if (ValTy == MVT::f64)
> + // Full register, just bitconvert into i64.
> + NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(),
> + IReg, MVT::i64, CCValAssign::BCvt);
> + else {
> + assert(ValTy == MVT::f128 && "Unexpected type!");
> + // Full register, just bitconvert into i128 -- We will lower this into
> + // two i64s in LowerCall_64.
> + NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(),
> + IReg, MVT::i128, CCValAssign::BCvt);
> + }
> } else {
> // This needs to go to memory, we're out of integer registers.
> NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(),
> @@ -1094,11 +1115,46 @@
> Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
> break;
> case CCValAssign::BCvt:
> - Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
> + // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But
> + // SPARC does not support i128 natively. Lower it into two i64, see below.
> + if (!VA.needsCustom() || VA.getValVT() != MVT::f128
> + || VA.getLocVT() != MVT::i128)
> + Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
> break;
> }
>
> if (VA.isRegLoc()) {
> + if (VA.needsCustom() && VA.getValVT() == MVT::f128
> + && VA.getLocVT() == MVT::i128) {
> + // Store and reload into the interger register reg and reg+1.
> + unsigned Offset = 8 * (VA.getLocReg() - SP::I0);
> + unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128;
> + SDValue StackPtr = DAG.getRegister(SP::O6, getPointerTy());
> + SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset);
> + HiPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
> + HiPtrOff);
> + SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8);
> + LoPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
> + LoPtrOff);
> +
> + // Store to %sp+BIAS+128+Offset
> + SDValue Store = DAG.getStore(Chain, DL, Arg, HiPtrOff,
> + MachinePointerInfo(),
> + false, false, 0);
> + // Load into Reg and Reg+1
> + SDValue Hi64 = DAG.getLoad(MVT::i64, DL, Store, HiPtrOff,
> + MachinePointerInfo(),
> + false, false, false, 0);
> + SDValue Lo64 = DAG.getLoad(MVT::i64, DL, Store, LoPtrOff,
> + MachinePointerInfo(),
> + false, false, false, 0);
> + RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()),
> + Hi64));
> + RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1),
> + Lo64));
> + continue;
> + }
> +
> // The custom bit on an i32 return value indicates that it should be
> // passed in the high bits of the register.
> if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {
> @@ -1156,10 +1212,13 @@
> // Likewise ExternalSymbol -> TargetExternalSymbol.
> SDValue Callee = CLI.Callee;
> bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS);
> + unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
> + ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
> if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
> - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy());
> + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0,
> + TF);
> else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
> - Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy());
> + Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), TF);
>
> // Build the operands for the call instruction itself.
> SmallVector<SDValue, 8> Ops;
> @@ -1200,8 +1259,14 @@
> SmallVector<CCValAssign, 16> RVLocs;
> CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(),
> DAG.getTarget(), RVLocs, *DAG.getContext());
> - RVInfo.AnalyzeCallResult(CLI.Ins, CC_Sparc64);
>
> + // Set inreg flag manually for codegen generated library calls that
> + // return float.
> + if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && CLI.CS == 0)
> + CLI.Ins[0].Flags.setInReg();
> +
> + RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64);
> +
> // Copy all of the result registers out of their specified physreg.
> for (unsigned i = 0; i != RVLocs.size(); ++i) {
> CCValAssign &VA = RVLocs[i];
> @@ -1303,7 +1368,7 @@
> }
>
> SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
> - : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
> + : TargetLowering(TM, new SparcELFTargetObjectFile()) {
> Subtarget = &TM.getSubtarget<SparcSubtarget>();
>
> // Set up the register classes.
> @@ -1403,7 +1468,8 @@
> setOperationAction(ISD::BR_CC, MVT::i64, Custom);
> setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
>
> - setOperationAction(ISD::CTPOP, MVT::i64, Legal);
> + setOperationAction(ISD::CTPOP, MVT::i64,
> + Subtarget->usePopc() ? Legal : Expand);
> setOperationAction(ISD::CTTZ , MVT::i64, Expand);
> setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
> setOperationAction(ISD::CTLZ , MVT::i64, Expand);
> @@ -1414,10 +1480,30 @@
> setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom);
> }
>
> - // FIXME: There are instructions available for ATOMIC_FENCE
> - // on SparcV8 and later.
> - setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
> + // ATOMICs.
> + // FIXME: We insert fences for each atomics and generate sub-optimal code
> + // for PSO/TSO. Also, implement other atomicrmw operations.
>
> + setInsertFencesForAtomic(true);
> +
> + setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Legal);
> + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32,
> + (Subtarget->isV9() ? Legal: Expand));
> +
> +
> + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Legal);
> +
> + // Custom Lower Atomic LOAD/STORE
> + setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom);
> + setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom);
> +
> + if (Subtarget->is64Bit()) {
> + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal);
> + setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Expand);
> + setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
> + setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom);
> + }
> +
> if (!Subtarget->isV9()) {
> // SparcV8 does not have FNEGD and FABSD.
> setOperationAction(ISD::FNEG, MVT::f64, Custom);
> @@ -1439,7 +1525,6 @@
> setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
> setOperationAction(ISD::FREM , MVT::f32, Expand);
> setOperationAction(ISD::FMA , MVT::f32, Expand);
> - setOperationAction(ISD::CTPOP, MVT::i32, Expand);
> setOperationAction(ISD::CTTZ , MVT::i32, Expand);
> setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
> setOperationAction(ISD::CTLZ , MVT::i32, Expand);
> @@ -1467,6 +1552,9 @@
> setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
> setOperationAction(ISD::MULHU, MVT::i64, Expand);
> setOperationAction(ISD::MULHS, MVT::i64, Expand);
> +
> + setOperationAction(ISD::UMULO, MVT::i64, Custom);
> + setOperationAction(ISD::SMULO, MVT::i64, Custom);
> }
>
> // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
> @@ -1486,8 +1574,8 @@
>
> setStackPointerRegisterToSaveRestore(SP::O6);
>
> - if (Subtarget->isV9())
> - setOperationAction(ISD::CTPOP, MVT::i32, Legal);
> + setOperationAction(ISD::CTPOP, MVT::i32,
> + Subtarget->usePopc() ? Legal : Expand);
>
> if (Subtarget->isV9() && Subtarget->hasHardQuad()) {
> setOperationAction(ISD::LOAD, MVT::f128, Legal);
> @@ -1714,7 +1802,8 @@
> // Handle PIC mode first.
> if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
> // This is the pic32 code model, the GOT is known to be smaller than 4GB.
> - SDValue HiLo = makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
> + SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
> + SparcMCExpr::VK_Sparc_GOT10, DAG);
> SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT);
> SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo);
> // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
> @@ -1729,23 +1818,26 @@
> switch(getTargetMachine().getCodeModel()) {
> default:
> llvm_unreachable("Unsupported absolute code model");
> - case CodeModel::JITDefault:
> case CodeModel::Small:
> // abs32.
> - return makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
> + return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
> + SparcMCExpr::VK_Sparc_LO, DAG);
> case CodeModel::Medium: {
> // abs44.
> - SDValue H44 = makeHiLoPair(Op, SPII::MO_H44, SPII::MO_M44, DAG);
> + SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44,
> + SparcMCExpr::VK_Sparc_M44, DAG);
> H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, MVT::i32));
> - SDValue L44 = withTargetFlags(Op, SPII::MO_L44, DAG);
> + SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG);
> L44 = DAG.getNode(SPISD::Lo, DL, VT, L44);
> return DAG.getNode(ISD::ADD, DL, VT, H44, L44);
> }
> case CodeModel::Large: {
> // abs64.
> - SDValue Hi = makeHiLoPair(Op, SPII::MO_HH, SPII::MO_HM, DAG);
> + SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH,
> + SparcMCExpr::VK_Sparc_HM, DAG);
> Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, MVT::i32));
> - SDValue Lo = makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
> + SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
> + SparcMCExpr::VK_Sparc_LO, DAG);
> return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
> }
> }
> @@ -1777,14 +1869,18 @@
> TLSModel::Model model = getTargetMachine().getTLSModel(GV);
>
> if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) {
> - unsigned HiTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_HI22
> - : SPII::MO_TLS_LDM_HI22);
> - unsigned LoTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_LO10
> - : SPII::MO_TLS_LDM_LO10);
> - unsigned addTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_ADD
> - : SPII::MO_TLS_LDM_ADD);
> - unsigned callTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_CALL
> - : SPII::MO_TLS_LDM_CALL);
> + unsigned HiTF = ((model == TLSModel::GeneralDynamic)
> + ? SparcMCExpr::VK_Sparc_TLS_GD_HI22
> + : SparcMCExpr::VK_Sparc_TLS_LDM_HI22);
> + unsigned LoTF = ((model == TLSModel::GeneralDynamic)
> + ? SparcMCExpr::VK_Sparc_TLS_GD_LO10
> + : SparcMCExpr::VK_Sparc_TLS_LDM_LO10);
> + unsigned addTF = ((model == TLSModel::GeneralDynamic)
> + ? SparcMCExpr::VK_Sparc_TLS_GD_ADD
> + : SparcMCExpr::VK_Sparc_TLS_LDM_ADD);
> + unsigned callTF = ((model == TLSModel::GeneralDynamic)
> + ? SparcMCExpr::VK_Sparc_TLS_GD_CALL
> + : SparcMCExpr::VK_Sparc_TLS_LDM_CALL);
>
> SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG);
> SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
> @@ -1822,17 +1918,17 @@
> return Ret;
>
> SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
> - withTargetFlags(Op, SPII::MO_TLS_LDO_HIX22, DAG));
> + withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG));
> SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
> - withTargetFlags(Op, SPII::MO_TLS_LDO_LOX10, DAG));
> + withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG));
> HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
> return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo,
> - withTargetFlags(Op, SPII::MO_TLS_LDO_ADD, DAG));
> + withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG));
> }
>
> if (model == TLSModel::InitialExec) {
> - unsigned ldTF = ((PtrVT == MVT::i64)? SPII::MO_TLS_IE_LDX
> - : SPII::MO_TLS_IE_LD);
> + unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX
> + : SparcMCExpr::VK_Sparc_TLS_IE_LD);
>
> SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
>
> @@ -1842,7 +1938,8 @@
> MFI->setHasCalls(true);
>
> SDValue TGA = makeHiLoPair(Op,
> - SPII::MO_TLS_IE_HI22, SPII::MO_TLS_IE_LO10, DAG);
> + SparcMCExpr::VK_Sparc_TLS_IE_HI22,
> + SparcMCExpr::VK_Sparc_TLS_IE_LO10, DAG);
> SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Base, TGA);
> SDValue Offset = DAG.getNode(SPISD::TLS_LD,
> DL, PtrVT, Ptr,
> @@ -1849,14 +1946,15 @@
> withTargetFlags(Op, ldTF, DAG));
> return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT,
> DAG.getRegister(SP::G7, PtrVT), Offset,
> - withTargetFlags(Op, SPII::MO_TLS_IE_ADD, DAG));
> + withTargetFlags(Op,
> + SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG));
> }
>
> assert(model == TLSModel::LocalExec);
> SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
> - withTargetFlags(Op, SPII::MO_TLS_LE_HIX22, DAG));
> + withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG));
> SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
> - withTargetFlags(Op, SPII::MO_TLS_LE_LOX10, DAG));
> + withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG));
> SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
>
> return DAG.getNode(ISD::ADD, DL, PtrVT,
> @@ -2334,7 +2432,8 @@
> return Chain;
> }
>
> -static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
> +static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
> + const SparcSubtarget *Subtarget) {
> MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
> MFI->setFrameAddressIsTaken(true);
>
> @@ -2341,32 +2440,49 @@
> EVT VT = Op.getValueType();
> SDLoc dl(Op);
> unsigned FrameReg = SP::I6;
> + unsigned stackBias = Subtarget->getStackPointerBias();
>
> - uint64_t depth = Op.getConstantOperandVal(0);
> + SDValue FrameAddr;
>
> - SDValue FrameAddr;
> - if (depth == 0)
> + if (depth == 0) {
> FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
> - else {
> - // flush first to make sure the windowed registers' values are in stack
> - SDValue Chain = getFLUSHW(Op, DAG);
> - FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
> + if (Subtarget->is64Bit())
> + FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
> + DAG.getIntPtrConstant(stackBias));
> + return FrameAddr;
> + }
>
> - for (uint64_t i = 0; i != depth; ++i) {
> - SDValue Ptr = DAG.getNode(ISD::ADD,
> - dl, MVT::i32,
> - FrameAddr, DAG.getIntPtrConstant(56));
> - FrameAddr = DAG.getLoad(MVT::i32, dl,
> - Chain,
> - Ptr,
> - MachinePointerInfo(), false, false, false, 0);
> - }
> + // flush first to make sure the windowed registers' values are in stack
> + SDValue Chain = getFLUSHW(Op, DAG);
> + FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
> +
> + unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
> +
> + while (depth--) {
> + SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
> + DAG.getIntPtrConstant(Offset));
> + FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo(),
> + false, false, false, 0);
> }
> + if (Subtarget->is64Bit())
> + FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
> + DAG.getIntPtrConstant(stackBias));
> return FrameAddr;
> }
>
> +
> +static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
> + const SparcSubtarget *Subtarget) {
> +
> + uint64_t depth = Op.getConstantOperandVal(0);
> +
> + return getFRAMEADDR(depth, Op, DAG, Subtarget);
> +
> +}
> +
> static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
> - const SparcTargetLowering &TLI) {
> + const SparcTargetLowering &TLI,
> + const SparcSubtarget *Subtarget) {
> MachineFunction &MF = DAG.getMachineFunction();
> MachineFrameInfo *MFI = MF.getFrameInfo();
> MFI->setReturnAddressIsTaken(true);
> @@ -2380,25 +2496,20 @@
> unsigned RetReg = MF.addLiveIn(SP::I7,
> TLI.getRegClassFor(TLI.getPointerTy()));
> RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT);
> - } else {
> - // Need frame address to find return address of the caller.
> - MFI->setFrameAddressIsTaken(true);
> + return RetAddr;
> + }
>
> - // flush first to make sure the windowed registers' values are in stack
> - SDValue Chain = getFLUSHW(Op, DAG);
> - RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT);
> + // Need frame address to find return address of the caller.
> + SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget);
>
> - for (uint64_t i = 0; i != depth; ++i) {
> - SDValue Ptr = DAG.getNode(ISD::ADD,
> - dl, MVT::i32,
> - RetAddr,
> - DAG.getIntPtrConstant((i == depth-1)?60:56));
> - RetAddr = DAG.getLoad(MVT::i32, dl,
> - Chain,
> - Ptr,
> - MachinePointerInfo(), false, false, false, 0);
> - }
> - }
> + unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60;
> + SDValue Ptr = DAG.getNode(ISD::ADD,
> + dl, VT,
> + FrameAddr,
> + DAG.getIntPtrConstant(Offset));
> + RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr,
> + MachinePointerInfo(), false, false, false, 0);
> +
> return RetAddr;
> }
>
> @@ -2615,6 +2726,63 @@
> return DAG.getMergeValues(Ops, 2, dl);
> }
>
> +// Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode()
> +// in LegalizeDAG.cpp except the order of arguments to the library function.
> +static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG,
> + const SparcTargetLowering &TLI)
> +{
> + unsigned opcode = Op.getOpcode();
> + assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode.");
> +
> + bool isSigned = (opcode == ISD::SMULO);
> + EVT VT = MVT::i64;
> + EVT WideVT = MVT::i128;
> + SDLoc dl(Op);
> + SDValue LHS = Op.getOperand(0);
> +
> + if (LHS.getValueType() != VT)
> + return Op;
> +
> + SDValue ShiftAmt = DAG.getConstant(63, VT);
> +
> + SDValue RHS = Op.getOperand(1);
> + SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt);
> + SDValue HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt);
> + SDValue Args[] = { HiLHS, LHS, HiRHS, RHS };
> +
> + SDValue MulResult = TLI.makeLibCall(DAG,
> + RTLIB::MUL_I128, WideVT,
> + Args, 4, isSigned, dl).first;
> + SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
> + MulResult, DAG.getIntPtrConstant(0));
> + SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
> + MulResult, DAG.getIntPtrConstant(1));
> + if (isSigned) {
> + SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt);
> + TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE);
> + } else {
> + TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, VT),
> + ISD::SETNE);
> + }
> + // MulResult is a node with an illegal type. Because such things are not
> + // generally permitted during this phase of legalization, delete the
> + // node. The above EXTRACT_ELEMENT nodes should have been folded.
> + DAG.DeleteNode(MulResult.getNode());
> +
> + SDValue Ops[2] = { BottomHalf, TopHalf } ;
> + return DAG.getMergeValues(Ops, 2, dl);
> +}
> +
> +static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {
> + // Monotonic load/stores are legal.
> + if (cast<AtomicSDNode>(Op)->getOrdering() <= Monotonic)
> + return Op;
> +
> + // Otherwise, expand with a fence.
> + return SDValue();
> +}
> +
> +
> SDValue SparcTargetLowering::
> LowerOperation(SDValue Op, SelectionDAG &DAG) const {
>
> @@ -2625,8 +2793,10 @@
> switch (Op.getOpcode()) {
> default: llvm_unreachable("Should not custom lower this!");
>
> - case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this);
> - case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
> + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this,
> + Subtarget);
> + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG,
> + Subtarget);
> case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
> case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
> case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
> @@ -2668,6 +2838,10 @@
> case ISD::ADDE:
> case ISD::SUBC:
> case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
> + case ISD::UMULO:
> + case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this);
> + case ISD::ATOMIC_LOAD:
> + case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG);
> }
> }
>
> @@ -2674,11 +2848,6 @@
> MachineBasicBlock *
> SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
> MachineBasicBlock *BB) const {
> - const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
> - unsigned BROpcode;
> - unsigned CC;
> - DebugLoc dl = MI->getDebugLoc();
> - // Figure out the conditional branch opcode to use for this select_cc.
> switch (MI->getOpcode()) {
> default: llvm_unreachable("Unknown SELECT_CC!");
> case SP::SELECT_CC_Int_ICC:
> @@ -2685,17 +2854,64 @@
> case SP::SELECT_CC_FP_ICC:
> case SP::SELECT_CC_DFP_ICC:
> case SP::SELECT_CC_QFP_ICC:
> - BROpcode = SP::BCOND;
> - break;
> + return expandSelectCC(MI, BB, SP::BCOND);
> case SP::SELECT_CC_Int_FCC:
> case SP::SELECT_CC_FP_FCC:
> case SP::SELECT_CC_DFP_FCC:
> case SP::SELECT_CC_QFP_FCC:
> - BROpcode = SP::FBCOND;
> - break;
> + return expandSelectCC(MI, BB, SP::FBCOND);
> +
> + case SP::ATOMIC_LOAD_ADD_32:
> + return expandAtomicRMW(MI, BB, SP::ADDrr);
> + case SP::ATOMIC_LOAD_ADD_64:
> + return expandAtomicRMW(MI, BB, SP::ADDXrr);
> + case SP::ATOMIC_LOAD_SUB_32:
> + return expandAtomicRMW(MI, BB, SP::SUBrr);
> + case SP::ATOMIC_LOAD_SUB_64:
> + return expandAtomicRMW(MI, BB, SP::SUBXrr);
> + case SP::ATOMIC_LOAD_AND_32:
> + return expandAtomicRMW(MI, BB, SP::ANDrr);
> + case SP::ATOMIC_LOAD_AND_64:
> + return expandAtomicRMW(MI, BB, SP::ANDXrr);
> + case SP::ATOMIC_LOAD_OR_32:
> + return expandAtomicRMW(MI, BB, SP::ORrr);
> + case SP::ATOMIC_LOAD_OR_64:
> + return expandAtomicRMW(MI, BB, SP::ORXrr);
> + case SP::ATOMIC_LOAD_XOR_32:
> + return expandAtomicRMW(MI, BB, SP::XORrr);
> + case SP::ATOMIC_LOAD_XOR_64:
> + return expandAtomicRMW(MI, BB, SP::XORXrr);
> + case SP::ATOMIC_LOAD_NAND_32:
> + return expandAtomicRMW(MI, BB, SP::ANDrr);
> + case SP::ATOMIC_LOAD_NAND_64:
> + return expandAtomicRMW(MI, BB, SP::ANDXrr);
> +
> + case SP::ATOMIC_LOAD_MAX_32:
> + return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G);
> + case SP::ATOMIC_LOAD_MAX_64:
> + return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_G);
> + case SP::ATOMIC_LOAD_MIN_32:
> + return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LE);
> + case SP::ATOMIC_LOAD_MIN_64:
> + return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LE);
> + case SP::ATOMIC_LOAD_UMAX_32:
> + return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_GU);
> + case SP::ATOMIC_LOAD_UMAX_64:
> + return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_GU);
> + case SP::ATOMIC_LOAD_UMIN_32:
> + return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LEU);
> + case SP::ATOMIC_LOAD_UMIN_64:
> + return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LEU);
> }
> +}
>
> - CC = (SPCC::CondCodes)MI->getOperand(3).getImm();
> +MachineBasicBlock*
> +SparcTargetLowering::expandSelectCC(MachineInstr *MI,
> + MachineBasicBlock *BB,
> + unsigned BROpcode) const {
> + const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
> + DebugLoc dl = MI->getDebugLoc();
> + unsigned CC = (SPCC::CondCodes)MI->getOperand(3).getImm();
>
> // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
> // control-flow pattern. The incoming instruction knows the destination vreg
> @@ -2749,6 +2965,100 @@
> return BB;
> }
>
> +MachineBasicBlock*
> +SparcTargetLowering::expandAtomicRMW(MachineInstr *MI,
> + MachineBasicBlock *MBB,
> + unsigned Opcode,
> + unsigned CondCode) const {
> + const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
> + MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
> + DebugLoc DL = MI->getDebugLoc();
> +
> + // MI is an atomic read-modify-write instruction of the form:
> + //
> + // rd = atomicrmw<op> addr, rs2
> + //
> + // All three operands are registers.
> + unsigned DestReg = MI->getOperand(0).getReg();
> + unsigned AddrReg = MI->getOperand(1).getReg();
> + unsigned Rs2Reg = MI->getOperand(2).getReg();
> +
> + // SelectionDAG has already inserted memory barriers before and after MI, so
> + // we simply have to implement the operatiuon in terms of compare-and-swap.
> + //
> + // %val0 = load %addr
> + // loop:
> + // %val = phi %val0, %dest
> + // %upd = op %val, %rs2
> + // %dest = cas %addr, %val, %upd
> + // cmp %val, %dest
> + // bne loop
> + // done:
> + //
> + bool is64Bit = SP::I64RegsRegClass.hasSubClassEq(MRI.getRegClass(DestReg));
> + const TargetRegisterClass *ValueRC =
> + is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
> + unsigned Val0Reg = MRI.createVirtualRegister(ValueRC);
> +
> + BuildMI(*MBB, MI, DL, TII.get(is64Bit ? SP::LDXri : SP::LDri), Val0Reg)
> + .addReg(AddrReg).addImm(0);
> +
> + // Split the basic block MBB before MI and insert the loop block in the hole.
> + MachineFunction::iterator MFI = MBB;
> + const BasicBlock *LLVM_BB = MBB->getBasicBlock();
> + MachineFunction *MF = MBB->getParent();
> + MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
> + MachineBasicBlock *DoneMBB = MF->CreateMachineBasicBlock(LLVM_BB);
> + ++MFI;
> + MF->insert(MFI, LoopMBB);
> + MF->insert(MFI, DoneMBB);
> +
> + // Move MI and following instructions to DoneMBB.
> + DoneMBB->splice(DoneMBB->begin(), MBB, MI, MBB->end());
> + DoneMBB->transferSuccessorsAndUpdatePHIs(MBB);
> +
> + // Connect the CFG again.
> + MBB->addSuccessor(LoopMBB);
> + LoopMBB->addSuccessor(LoopMBB);
> + LoopMBB->addSuccessor(DoneMBB);
> +
> + // Build the loop block.
> + unsigned ValReg = MRI.createVirtualRegister(ValueRC);
> + unsigned UpdReg = MRI.createVirtualRegister(ValueRC);
> +
> + BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg)
> + .addReg(Val0Reg).addMBB(MBB)
> + .addReg(DestReg).addMBB(LoopMBB);
> +
> + if (CondCode) {
> + // This is one of the min/max operations. We need a CMPrr followed by a
> + // MOVXCC/MOVICC.
> + BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(Rs2Reg);
> + BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg)
> + .addReg(ValReg).addReg(Rs2Reg).addImm(CondCode);
> + } else {
> + BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg)
> + .addReg(ValReg).addReg(Rs2Reg);
> + }
> +
> + if (MI->getOpcode() == SP::ATOMIC_LOAD_NAND_32 ||
> + MI->getOpcode() == SP::ATOMIC_LOAD_NAND_64) {
> + unsigned TmpReg = UpdReg;
> + UpdReg = MRI.createVirtualRegister(ValueRC);
> + BuildMI(LoopMBB, DL, TII.get(SP::XORri), UpdReg).addReg(TmpReg).addImm(-1);
> + }
> +
> + BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg)
> + .addReg(AddrReg).addReg(ValReg).addReg(UpdReg)
> + .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
> + BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(DestReg);
> + BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::BPXCC : SP::BCOND))
> + .addMBB(LoopMBB).addImm(SPCC::ICC_NE);
> +
> + MI->eraseFromParent();
> + return DoneMBB;
> +}
> +
> //===----------------------------------------------------------------------===//
> // Sparc Inline Assembly Support
> //===----------------------------------------------------------------------===//
> @@ -2761,6 +3071,8 @@
> switch (Constraint[0]) {
> default: break;
> case 'r': return C_RegisterClass;
> + case 'I': // SIMM13
> + return C_Other;
> }
> }
>
> @@ -2767,6 +3079,64 @@
> return TargetLowering::getConstraintType(Constraint);
> }
>
> +TargetLowering::ConstraintWeight SparcTargetLowering::
> +getSingleConstraintMatchWeight(AsmOperandInfo &info,
> + const char *constraint) const {
> + ConstraintWeight weight = CW_Invalid;
> + Value *CallOperandVal = info.CallOperandVal;
> + // If we don't have a value, we can't do a match,
> + // but allow it at the lowest weight.
> + if (CallOperandVal == NULL)
> + return CW_Default;
> +
> + // Look at the constraint type.
> + switch (*constraint) {
> + default:
> + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
> + break;
> + case 'I': // SIMM13
> + if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
> + if (isInt<13>(C->getSExtValue()))
> + weight = CW_Constant;
> + }
> + break;
> + }
> + return weight;
> +}
> +
> +/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
> +/// vector. If it is invalid, don't add anything to Ops.
> +void SparcTargetLowering::
> +LowerAsmOperandForConstraint(SDValue Op,
> + std::string &Constraint,
> + std::vector<SDValue> &Ops,
> + SelectionDAG &DAG) const {
> + SDValue Result(0, 0);
> +
> + // Only support length 1 constraints for now.
> + if (Constraint.length() > 1)
> + return;
> +
> + char ConstraintLetter = Constraint[0];
> + switch (ConstraintLetter) {
> + default: break;
> + case 'I':
> + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
> + if (isInt<13>(C->getSExtValue())) {
> + Result = DAG.getTargetConstant(C->getSExtValue(), Op.getValueType());
> + break;
> + }
> + return;
> + }
> + }
> +
> + if (Result.getNode()) {
> + Ops.push_back(Result);
> + return;
> + }
> + TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
> +}
> +
> std::pair<unsigned, const TargetRegisterClass*>
> SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
> MVT VT) const {
> @@ -2775,6 +3145,26 @@
> case 'r':
> return std::make_pair(0U, &SP::IntRegsRegClass);
> }
> + } else if (!Constraint.empty() && Constraint.size() <= 5
> + && Constraint[0] == '{' && *(Constraint.end()-1) == '}') {
> + // constraint = '{r<d>}'
> + // Remove the braces from around the name.
> + StringRef name(Constraint.data()+1, Constraint.size()-2);
> + // Handle register aliases:
> + // r0-r7 -> g0-g7
> + // r8-r15 -> o0-o7
> + // r16-r23 -> l0-l7
> + // r24-r31 -> i0-i7
> + uint64_t intVal = 0;
> + if (name.substr(0, 1).equals("r")
> + && !name.substr(1).getAsInteger(10, intVal) && intVal <= 31) {
> + const char regTypes[] = { 'g', 'o', 'l', 'i' };
> + char regType = regTypes[intVal/8];
> + char regIdx = '0' + (intVal % 8);
> + char tmp[] = { '{', regType, regIdx, '}', 0 };
> + std::string newConstraint = std::string(tmp);
> + return TargetLowering::getRegForInlineAsmConstraint(newConstraint, VT);
> + }
> }
>
> return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
> Index: lib/Target/Sparc/SparcISelLowering.h
> ===================================================================
> --- lib/Target/Sparc/SparcISelLowering.h (revision 201091)
> +++ lib/Target/Sparc/SparcISelLowering.h (working copy)
> @@ -73,6 +73,13 @@
> virtual const char *getTargetNodeName(unsigned Opcode) const;
>
> ConstraintType getConstraintType(const std::string &Constraint) const;
> + ConstraintWeight
> + getSingleConstraintMatchWeight(AsmOperandInfo &info,
> + const char *constraint) const;
> + void LowerAsmOperandForConstraint(SDValue Op,
> + std::string &Constraint,
> + std::vector<SDValue> &Ops,
> + SelectionDAG &DAG) const;
> std::pair<unsigned, const TargetRegisterClass*>
> getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const;
>
> @@ -158,6 +165,13 @@
> virtual void ReplaceNodeResults(SDNode *N,
> SmallVectorImpl<SDValue>& Results,
> SelectionDAG &DAG) const;
> +
> + MachineBasicBlock *expandSelectCC(MachineInstr *MI, MachineBasicBlock *BB,
> + unsigned BROpcode) const;
> + MachineBasicBlock *expandAtomicRMW(MachineInstr *MI,
> + MachineBasicBlock *BB,
> + unsigned Opcode,
> + unsigned CondCode = 0) const;
> };
> } // end namespace llvm
>
> Index: lib/Target/Sparc/SparcInstr64Bit.td
> ===================================================================
> --- lib/Target/Sparc/SparcInstr64Bit.td (revision 201091)
> +++ lib/Target/Sparc/SparcInstr64Bit.td (working copy)
> @@ -141,42 +141,44 @@
> let Predicates = [Is64Bit] in {
>
> // Register-register instructions.
> +let isCodeGenOnly = 1 in {
> +defm ANDX : F3_12<"and", 0b000001, and, I64Regs, i64, i64imm>;
> +defm ORX : F3_12<"or", 0b000010, or, I64Regs, i64, i64imm>;
> +defm XORX : F3_12<"xor", 0b000011, xor, I64Regs, i64, i64imm>;
>
> -def : Pat<(and i64:$a, i64:$b), (ANDrr $a, $b)>;
> -def : Pat<(or i64:$a, i64:$b), (ORrr $a, $b)>;
> -def : Pat<(xor i64:$a, i64:$b), (XORrr $a, $b)>;
> +def ANDXNrr : F3_1<2, 0b000101,
> + (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c),
> + "andn $b, $c, $dst",
> + [(set i64:$dst, (and i64:$b, (not i64:$c)))]>;
> +def ORXNrr : F3_1<2, 0b000110,
> + (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c),
> + "orn $b, $c, $dst",
> + [(set i64:$dst, (or i64:$b, (not i64:$c)))]>;
> +def XNORXrr : F3_1<2, 0b000111,
> + (outs I64Regs:$dst), (ins I64Regs:$b, I64Regs:$c),
> + "xnor $b, $c, $dst",
> + [(set i64:$dst, (not (xor i64:$b, i64:$c)))]>;
>
> -def : Pat<(and i64:$a, (not i64:$b)), (ANDNrr $a, $b)>;
> -def : Pat<(or i64:$a, (not i64:$b)), (ORNrr $a, $b)>;
> -def : Pat<(xor i64:$a, (not i64:$b)), (XNORrr $a, $b)>;
> +defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>;
> +defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>;
>
> -def : Pat<(add i64:$a, i64:$b), (ADDrr $a, $b)>;
> -def : Pat<(sub i64:$a, i64:$b), (SUBrr $a, $b)>;
> +def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd),
> + (ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym),
> + "add $rs1, $rs2, $rd, $sym",
> + [(set i64:$rd,
> + (tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>;
>
> -def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
> -
> -def : Pat<(tlsadd i64:$a, i64:$b, tglobaltlsaddr:$sym),
> - (TLS_ADDrr $a, $b, $sym)>;
> -
> -// Register-immediate instructions.
> -
> -def : Pat<(and i64:$a, (i64 simm13:$b)), (ANDri $a, (as_i32imm $b))>;
> -def : Pat<(or i64:$a, (i64 simm13:$b)), (ORri $a, (as_i32imm $b))>;
> -def : Pat<(xor i64:$a, (i64 simm13:$b)), (XORri $a, (as_i32imm $b))>;
> -
> -def : Pat<(add i64:$a, (i64 simm13:$b)), (ADDri $a, (as_i32imm $b))>;
> -def : Pat<(sub i64:$a, (i64 simm13:$b)), (SUBri $a, (as_i32imm $b))>;
> -
> -def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>;
> -
> -def : Pat<(ctpop i64:$src), (POPCrr $src)>;
> -
> // "LEA" form of add
> def LEAX_ADDri : F3_2<2, 0b000000,
> (outs I64Regs:$dst), (ins MEMri:$addr),
> "add ${addr:arith}, $dst",
> [(set iPTR:$dst, ADDRri:$addr)]>;
> +}
>
> +def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
> +def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>;
> +def : Pat<(ctpop i64:$src), (POPCrr $src)>;
> +
> } // Predicates = [Is64Bit]
>
>
> @@ -191,9 +193,9 @@
> "mulx $rs1, $rs2, $rd",
> [(set i64:$rd, (mul i64:$rs1, i64:$rs2))]>;
> def MULXri : F3_2<2, 0b001001,
> - (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$i),
> - "mulx $rs1, $i, $rd",
> - [(set i64:$rd, (mul i64:$rs1, (i64 simm13:$i)))]>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13),
> + "mulx $rs1, $simm13, $rd",
> + [(set i64:$rd, (mul i64:$rs1, (i64 simm13:$simm13)))]>;
>
> // Division can trap.
> let hasSideEffects = 1 in {
> @@ -202,9 +204,9 @@
> "sdivx $rs1, $rs2, $rd",
> [(set i64:$rd, (sdiv i64:$rs1, i64:$rs2))]>;
> def SDIVXri : F3_2<2, 0b101101,
> - (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$i),
> - "sdivx $rs1, $i, $rd",
> - [(set i64:$rd, (sdiv i64:$rs1, (i64 simm13:$i)))]>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13),
> + "sdivx $rs1, $simm13, $rd",
> + [(set i64:$rd, (sdiv i64:$rs1, (i64 simm13:$simm13)))]>;
>
> def UDIVXrr : F3_1<2, 0b001101,
> (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2),
> @@ -211,9 +213,9 @@
> "udivx $rs1, $rs2, $rd",
> [(set i64:$rd, (udiv i64:$rs1, i64:$rs2))]>;
> def UDIVXri : F3_2<2, 0b001101,
> - (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$i),
> - "udivx $rs1, $i, $rd",
> - [(set i64:$rd, (udiv i64:$rs1, (i64 simm13:$i)))]>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13),
> + "udivx $rs1, $simm13, $rd",
> + [(set i64:$rd, (udiv i64:$rs1, (i64 simm13:$simm13)))]>;
> } // hasSideEffects = 1
>
> } // Predicates = [Is64Bit]
> @@ -233,15 +235,9 @@
> let Predicates = [Is64Bit] in {
>
> // 64-bit loads.
> -def LDXrr : F3_1<3, 0b001011,
> - (outs I64Regs:$dst), (ins MEMrr:$addr),
> - "ldx [$addr], $dst",
> - [(set i64:$dst, (load ADDRrr:$addr))]>;
> -def LDXri : F3_2<3, 0b001011,
> - (outs I64Regs:$dst), (ins MEMri:$addr),
> - "ldx [$addr], $dst",
> - [(set i64:$dst, (load ADDRri:$addr))]>;
> -let mayLoad = 1 in
> +defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>;
> +
> +let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in
> def TLS_LDXrr : F3_1<3, 0b001011,
> (outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
> "ldx [$addr], $dst, $sym",
> @@ -274,24 +270,10 @@
> def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>;
>
> // Sign-extending load of i32 into i64 is a new SPARC v9 instruction.
> -def LDSWrr : F3_1<3, 0b001011,
> - (outs I64Regs:$dst), (ins MEMrr:$addr),
> - "ldsw [$addr], $dst",
> - [(set i64:$dst, (sextloadi32 ADDRrr:$addr))]>;
> -def LDSWri : F3_2<3, 0b001011,
> - (outs I64Regs:$dst), (ins MEMri:$addr),
> - "ldsw [$addr], $dst",
> - [(set i64:$dst, (sextloadi32 ADDRri:$addr))]>;
> +defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>;
>
> // 64-bit stores.
> -def STXrr : F3_1<3, 0b001110,
> - (outs), (ins MEMrr:$addr, I64Regs:$src),
> - "stx $src, [$addr]",
> - [(store i64:$src, ADDRrr:$addr)]>;
> -def STXri : F3_2<3, 0b001110,
> - (outs), (ins MEMri:$addr, I64Regs:$src),
> - "stx $src, [$addr]",
> - [(store i64:$src, ADDRri:$addr)]>;
> +defm STX : Store<"stx", 0b001110, store, I64Regs, i64>;
>
> // Truncating stores from i64 are identical to the i32 stores.
> def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>;
> @@ -311,6 +293,15 @@
> //===----------------------------------------------------------------------===//
> // 64-bit Conditionals.
> //===----------------------------------------------------------------------===//
> +
> +// Conditional branch class on %xcc:
> +class XBranchSP<dag ins, string asmstr, list<dag> pattern>
> + : F2_3<0b001, 0b10, (outs), ins, asmstr, pattern> {
> + let isBranch = 1;
> + let isTerminator = 1;
> + let hasDelaySlot = 1;
> +}
> +
> //
> // Flag-setting instructions like subcc and addcc set both icc and xcc flags.
> // The icc flags correspond to the 32-bit result, and the xcc are for the
> @@ -322,32 +313,42 @@
> let Predicates = [Is64Bit] in {
>
> let Uses = [ICC] in
> -def BPXCC : BranchSP<(ins brtarget:$imm22, CCOp:$cond),
> - "b$cond %xcc, $imm22",
> - [(SPbrxcc bb:$imm22, imm:$cond)]>;
> +def BPXCC : XBranchSP<(ins brtarget:$imm19, CCOp:$cond),
> + "b$cond %xcc, $imm19",
> + [(SPbrxcc bb:$imm19, imm:$cond)]>;
>
> // Conditional moves on %xcc.
> let Uses = [ICC], Constraints = "$f = $rd" in {
> -def MOVXCCrr : Pseudo<(outs IntRegs:$rd),
> +let cc = 0b110 in {
> +def MOVXCCrr : F4_1<0b101100, (outs IntRegs:$rd),
> (ins IntRegs:$rs2, IntRegs:$f, CCOp:$cond),
> "mov$cond %xcc, $rs2, $rd",
> [(set i32:$rd,
> (SPselectxcc i32:$rs2, i32:$f, imm:$cond))]>;
> -def MOVXCCri : Pseudo<(outs IntRegs:$rd),
> - (ins i32imm:$i, IntRegs:$f, CCOp:$cond),
> - "mov$cond %xcc, $i, $rd",
> +def MOVXCCri : F4_2<0b101100, (outs IntRegs:$rd),
> + (ins i32imm:$simm11, IntRegs:$f, CCOp:$cond),
> + "mov$cond %xcc, $simm11, $rd",
> [(set i32:$rd,
> - (SPselectxcc simm11:$i, i32:$f, imm:$cond))]>;
> -def FMOVS_XCC : Pseudo<(outs FPRegs:$rd),
> + (SPselectxcc simm11:$simm11, i32:$f, imm:$cond))]>;
> +} // cc
> +
> +let opf_cc = 0b110 in {
> +def FMOVS_XCC : F4_3<0b110101, 0b000001, (outs FPRegs:$rd),
> (ins FPRegs:$rs2, FPRegs:$f, CCOp:$cond),
> "fmovs$cond %xcc, $rs2, $rd",
> [(set f32:$rd,
> (SPselectxcc f32:$rs2, f32:$f, imm:$cond))]>;
> -def FMOVD_XCC : Pseudo<(outs DFPRegs:$rd),
> +def FMOVD_XCC : F4_3<0b110101, 0b000010, (outs DFPRegs:$rd),
> (ins DFPRegs:$rs2, DFPRegs:$f, CCOp:$cond),
> "fmovd$cond %xcc, $rs2, $rd",
> [(set f64:$rd,
> (SPselectxcc f64:$rs2, f64:$f, imm:$cond))]>;
> +def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd),
> + (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond),
> + "fmovq$cond %xcc, $rs2, $rd",
> + [(set f128:$rd,
> + (SPselectxcc f128:$rs2, f128:$f, imm:$cond))]>;
> +} // opf_cc
> } // Uses, Constraints
>
> //===----------------------------------------------------------------------===//
> @@ -357,31 +358,31 @@
> let Predicates = [Is64Bit] in {
>
> def FXTOS : F3_3u<2, 0b110100, 0b010000100,
> - (outs FPRegs:$dst), (ins DFPRegs:$src),
> - "fxtos $src, $dst",
> - [(set FPRegs:$dst, (SPxtof DFPRegs:$src))]>;
> + (outs FPRegs:$rd), (ins DFPRegs:$rs2),
> + "fxtos $rs2, $rd",
> + [(set FPRegs:$rd, (SPxtof DFPRegs:$rs2))]>;
> def FXTOD : F3_3u<2, 0b110100, 0b010001000,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src),
> - "fxtod $src, $dst",
> - [(set DFPRegs:$dst, (SPxtof DFPRegs:$src))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
> + "fxtod $rs2, $rd",
> + [(set DFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>;
> def FXTOQ : F3_3u<2, 0b110100, 0b010001100,
> - (outs QFPRegs:$dst), (ins DFPRegs:$src),
> - "fxtoq $src, $dst",
> - [(set QFPRegs:$dst, (SPxtof DFPRegs:$src))]>,
> + (outs QFPRegs:$rd), (ins DFPRegs:$rs2),
> + "fxtoq $rs2, $rd",
> + [(set QFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>,
> Requires<[HasHardQuad]>;
>
> def FSTOX : F3_3u<2, 0b110100, 0b010000001,
> - (outs DFPRegs:$dst), (ins FPRegs:$src),
> - "fstox $src, $dst",
> - [(set DFPRegs:$dst, (SPftox FPRegs:$src))]>;
> + (outs DFPRegs:$rd), (ins FPRegs:$rs2),
> + "fstox $rs2, $rd",
> + [(set DFPRegs:$rd, (SPftox FPRegs:$rs2))]>;
> def FDTOX : F3_3u<2, 0b110100, 0b010000010,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src),
> - "fdtox $src, $dst",
> - [(set DFPRegs:$dst, (SPftox DFPRegs:$src))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
> + "fdtox $rs2, $rd",
> + [(set DFPRegs:$rd, (SPftox DFPRegs:$rs2))]>;
> def FQTOX : F3_3u<2, 0b110100, 0b010000011,
> - (outs DFPRegs:$dst), (ins QFPRegs:$src),
> - "fqtox $src, $dst",
> - [(set DFPRegs:$dst, (SPftox QFPRegs:$src))]>,
> + (outs DFPRegs:$rd), (ins QFPRegs:$rs2),
> + "fqtox $rs2, $rd",
> + [(set DFPRegs:$rd, (SPftox QFPRegs:$rs2))]>,
> Requires<[HasHardQuad]>;
>
> } // Predicates = [Is64Bit]
> @@ -402,3 +403,89 @@
> (MOVFCCri (as_i32imm $t), $f, imm:$cond)>;
>
> } // Predicates = [Is64Bit]
> +
> +
> +// 64 bit SETHI
> +let Predicates = [Is64Bit], isCodeGenOnly = 1 in {
> +def SETHIXi : F2_1<0b100,
> + (outs IntRegs:$rd), (ins i64imm:$imm22),
> + "sethi $imm22, $rd",
> + [(set i64:$rd, SETHIimm:$imm22)]>;
> +}
> +
> +// ATOMICS.
> +let Predicates = [Is64Bit], Constraints = "$swap = $rd" in {
> + def CASXrr: F3_1_asi<3, 0b111110, 0b10000000,
> + (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2,
> + I64Regs:$swap),
> + "casx [$rs1], $rs2, $rd",
> + [(set i64:$rd,
> + (atomic_cmp_swap i64:$rs1, i64:$rs2, i64:$swap))]>;
> +
> +} // Predicates = [Is64Bit], Constraints = ...
> +
> +let Predicates = [Is64Bit] in {
> +
> +def : Pat<(atomic_fence imm, imm), (MEMBARi 0xf)>;
> +
> +// atomic_load_64 addr -> load addr
> +def : Pat<(i64 (atomic_load ADDRrr:$src)), (LDXrr ADDRrr:$src)>;
> +def : Pat<(i64 (atomic_load ADDRri:$src)), (LDXri ADDRri:$src)>;
> +
> +// atomic_store_64 val, addr -> store val, addr
> +def : Pat<(atomic_store ADDRrr:$dst, i64:$val), (STXrr ADDRrr:$dst, $val)>;
> +def : Pat<(atomic_store ADDRri:$dst, i64:$val), (STXri ADDRri:$dst, $val)>;
> +
> +} // Predicates = [Is64Bit]
> +
> +let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1,
> + Defs = [ICC] in
> +multiclass AtomicRMW<SDPatternOperator op32, SDPatternOperator op64> {
> +
> + def _32 : Pseudo<(outs IntRegs:$rd),
> + (ins ptr_rc:$addr, IntRegs:$rs2), "",
> + [(set i32:$rd, (op32 iPTR:$addr, i32:$rs2))]>;
> +
> + let Predicates = [Is64Bit] in
> + def _64 : Pseudo<(outs I64Regs:$rd),
> + (ins ptr_rc:$addr, I64Regs:$rs2), "",
> + [(set i64:$rd, (op64 iPTR:$addr, i64:$rs2))]>;
> +}
> +
> +defm ATOMIC_LOAD_ADD : AtomicRMW<atomic_load_add_32, atomic_load_add_64>;
> +defm ATOMIC_LOAD_SUB : AtomicRMW<atomic_load_sub_32, atomic_load_sub_64>;
> +defm ATOMIC_LOAD_AND : AtomicRMW<atomic_load_and_32, atomic_load_and_64>;
> +defm ATOMIC_LOAD_OR : AtomicRMW<atomic_load_or_32, atomic_load_or_64>;
> +defm ATOMIC_LOAD_XOR : AtomicRMW<atomic_load_xor_32, atomic_load_xor_64>;
> +defm ATOMIC_LOAD_NAND : AtomicRMW<atomic_load_nand_32, atomic_load_nand_64>;
> +defm ATOMIC_LOAD_MIN : AtomicRMW<atomic_load_min_32, atomic_load_min_64>;
> +defm ATOMIC_LOAD_MAX : AtomicRMW<atomic_load_max_32, atomic_load_max_64>;
> +defm ATOMIC_LOAD_UMIN : AtomicRMW<atomic_load_umin_32, atomic_load_umin_64>;
> +defm ATOMIC_LOAD_UMAX : AtomicRMW<atomic_load_umax_32, atomic_load_umax_64>;
> +
> +// Global addresses, constant pool entries
> +let Predicates = [Is64Bit] in {
> +
> +def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>;
> +def : Pat<(SPlo tglobaladdr:$in), (ORXri (i64 G0), tglobaladdr:$in)>;
> +def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>;
> +def : Pat<(SPlo tconstpool:$in), (ORXri (i64 G0), tconstpool:$in)>;
> +
> +// GlobalTLS addresses
> +def : Pat<(SPhi tglobaltlsaddr:$in), (SETHIi tglobaltlsaddr:$in)>;
> +def : Pat<(SPlo tglobaltlsaddr:$in), (ORXri (i64 G0), tglobaltlsaddr:$in)>;
> +def : Pat<(add (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)),
> + (ADDXri (SETHIXi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>;
> +def : Pat<(xor (SPhi tglobaltlsaddr:$in1), (SPlo tglobaltlsaddr:$in2)),
> + (XORXri (SETHIXi tglobaltlsaddr:$in1), (tglobaltlsaddr:$in2))>;
> +
> +// Blockaddress
> +def : Pat<(SPhi tblockaddress:$in), (SETHIi tblockaddress:$in)>;
> +def : Pat<(SPlo tblockaddress:$in), (ORXri (i64 G0), tblockaddress:$in)>;
> +
> +// Add reg, lo. This is used when taking the addr of a global/constpool entry.
> +def : Pat<(add iPTR:$r, (SPlo tglobaladdr:$in)), (ADDXri $r, tglobaladdr:$in)>;
> +def : Pat<(add iPTR:$r, (SPlo tconstpool:$in)), (ADDXri $r, tconstpool:$in)>;
> +def : Pat<(add iPTR:$r, (SPlo tblockaddress:$in)),
> + (ADDXri $r, tblockaddress:$in)>;
> +}
> Index: lib/Target/Sparc/SparcInstrAliases.td
> ===================================================================
> --- lib/Target/Sparc/SparcInstrAliases.td (revision 0)
> +++ lib/Target/Sparc/SparcInstrAliases.td (working copy)
> @@ -0,0 +1,142 @@
> +//===-- SparcInstrAliases.td - Instruction Aliases for Sparc Target -------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains instruction aliases for Sparc.
> +//===----------------------------------------------------------------------===//
> +
> +// Instruction aliases for conditional moves.
> +
> +// mov<cond> <ccreg> rs2, rd
> +multiclass cond_mov_alias<string cond, int condVal, string ccreg,
> + Instruction movrr, Instruction movri,
> + Instruction fmovs, Instruction fmovd> {
> +
> + // mov<cond> (%icc|%xcc|%fcc0), rs2, rd
> + def : InstAlias<!strconcat(!strconcat(!strconcat("mov", cond), ccreg),
> + ", $rs2, $rd"),
> + (movrr IntRegs:$rd, IntRegs:$rs2, condVal)>;
> +
> + // mov<cond> (%icc|%xcc|%fcc0), simm11, rd
> + def : InstAlias<!strconcat(!strconcat(!strconcat("mov", cond), ccreg),
> + ", $simm11, $rd"),
> + (movri IntRegs:$rd, i32imm:$simm11, condVal)>;
> +
> + // fmovs<cond> (%icc|%xcc|%fcc0), $rs2, $rd
> + def : InstAlias<!strconcat(!strconcat(!strconcat("fmovs", cond), ccreg),
> + ", $rs2, $rd"),
> + (fmovs FPRegs:$rd, FPRegs:$rs2, condVal)>;
> +
> + // fmovd<cond> (%icc|%xcc|%fcc0), $rs2, $rd
> + def : InstAlias<!strconcat(!strconcat(!strconcat("fmovd", cond), ccreg),
> + ", $rs2, $rd"),
> + (fmovd DFPRegs:$rd, DFPRegs:$rs2, condVal)>;
> +}
> +
> +
> +// Instruction aliases for integer conditional branches and moves.
> +multiclass int_cond_alias<string cond, int condVal> {
> +
> + // b<cond> $imm
> + def : InstAlias<!strconcat(!strconcat("b", cond), " $imm"),
> + (BCOND brtarget:$imm, condVal)>;
> +
> + // b<cond> %xcc, $imm
> + def : InstAlias<!strconcat(!strconcat("b", cond), " %xcc, $imm"),
> + (BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
> +
> + defm : cond_mov_alias<cond, condVal, " %icc",
> + MOVICCrr, MOVICCri,
> + FMOVS_ICC, FMOVD_ICC>, Requires<[HasV9]>;
> +
> + defm : cond_mov_alias<cond, condVal, " %xcc",
> + MOVXCCrr, MOVXCCri,
> + FMOVS_XCC, FMOVD_XCC>, Requires<[Is64Bit]>;
> +
> + // fmovq<cond> (%icc|%xcc), $rs2, $rd
> + def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %icc, $rs2, $rd"),
> + (FMOVQ_ICC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
> + Requires<[HasV9, HasHardQuad]>;
> + def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %xcc, $rs2, $rd"),
> + (FMOVQ_XCC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
> + Requires<[Is64Bit, HasHardQuad]>;
> +
> +}
> +
> +
> +// Instruction aliases for floating point conditional branches and moves.
> +multiclass fp_cond_alias<string cond, int condVal> {
> +
> + // fb<cond> $imm
> + def : InstAlias<!strconcat(!strconcat("fb", cond), " $imm"),
> + (FBCOND brtarget:$imm, condVal), 0>;
> +
> + defm : cond_mov_alias<cond, condVal, " %fcc0",
> + MOVFCCrr, MOVFCCri,
> + FMOVS_FCC, FMOVD_FCC>, Requires<[HasV9]>;
> +
> + // fmovq<cond> %fcc0, $rs2, $rd
> + def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %fcc0, $rs2, $rd"),
> + (FMOVQ_ICC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
> + Requires<[HasV9, HasHardQuad]>;
> +}
> +
> +defm : int_cond_alias<"a", 0b1000>;
> +defm : int_cond_alias<"n", 0b0000>;
> +defm : int_cond_alias<"ne", 0b1001>;
> +defm : int_cond_alias<"e", 0b0001>;
> +defm : int_cond_alias<"g", 0b1010>;
> +defm : int_cond_alias<"le", 0b0010>;
> +defm : int_cond_alias<"ge", 0b1011>;
> +defm : int_cond_alias<"l", 0b0011>;
> +defm : int_cond_alias<"gu", 0b1100>;
> +defm : int_cond_alias<"leu", 0b0100>;
> +defm : int_cond_alias<"cc", 0b1101>;
> +defm : int_cond_alias<"cs", 0b0101>;
> +defm : int_cond_alias<"pos", 0b1110>;
> +defm : int_cond_alias<"neg", 0b0110>;
> +defm : int_cond_alias<"vc", 0b1111>;
> +defm : int_cond_alias<"vs", 0b0111>;
> +
> +defm : fp_cond_alias<"u", 0b0111>;
> +defm : fp_cond_alias<"g", 0b0110>;
> +defm : fp_cond_alias<"ug", 0b0101>;
> +defm : fp_cond_alias<"l", 0b0100>;
> +defm : fp_cond_alias<"ul", 0b0011>;
> +defm : fp_cond_alias<"lg", 0b0010>;
> +defm : fp_cond_alias<"ne", 0b0001>;
> +defm : fp_cond_alias<"e", 0b1001>;
> +defm : fp_cond_alias<"ue", 0b1010>;
> +defm : fp_cond_alias<"ge", 0b1011>;
> +defm : fp_cond_alias<"uge", 0b1100>;
> +defm : fp_cond_alias<"le", 0b1101>;
> +defm : fp_cond_alias<"ule", 0b1110>;
> +defm : fp_cond_alias<"o", 0b1111>;
> +
> +
> +// Instruction aliases for JMPL.
> +
> +// jmp addr -> jmpl addr, %g0
> +def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr)>;
> +def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr)>;
> +
> +// call addr -> jmpl addr, %o7
> +def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>;
> +def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>;
> +
> +// retl -> RETL 8
> +def : InstAlias<"retl", (RETL 8)>;
> +
> +// ret -> RET 8
> +def : InstAlias<"ret", (RET 8)>;
> +
> +// mov reg, rd -> or %g0, reg, rd
> +def : InstAlias<"mov $rs2, $rd", (ORrr IntRegs:$rd, G0, IntRegs:$rs2)>;
> +
> +// mov simm13, rd -> or %g0, simm13, rd
> +def : InstAlias<"mov $simm13, $rd", (ORri IntRegs:$rd, G0, i32imm:$simm13)>;
> Index: lib/Target/Sparc/SparcInstrFormats.td
> ===================================================================
> --- lib/Target/Sparc/SparcInstrFormats.td (revision 201091)
> +++ lib/Target/Sparc/SparcInstrFormats.td (working copy)
> @@ -12,6 +12,7 @@
> field bits<32> Inst;
>
> let Namespace = "SP";
> + let Size = 4;
>
> bits<2> op;
> let Inst{31-30} = op; // Top two bits are the 'op' field
> @@ -20,6 +21,9 @@
> dag InOperandList = ins;
> let AsmString = asmstr;
> let Pattern = pattern;
> +
> + let DecoderNamespace = "Sparc";
> + field bits<32> SoftFail = 0;
> }
>
> //===----------------------------------------------------------------------===//
> @@ -58,6 +62,27 @@
> let Inst{28-25} = cond;
> }
>
> +class F2_3<bits<3> op2Val, bits<2> ccVal, dag outs, dag ins, string asmstr,
> + list<dag> pattern>
> + : InstSP<outs, ins, asmstr, pattern> {
> + bit annul;
> + bits<4> cond;
> + bit pred;
> + bits<19> imm19;
> +
> + let op = 0; // op = 0
> +
> + bit annul = 0; // currently unused
> + let pred = 1; // default is predict taken
> +
> + let Inst{29} = annul;
> + let Inst{28-25} = cond;
> + let Inst{24-22} = op2Val;
> + let Inst{21-20} = ccVal;
> + let Inst{19} = pred;
> + let Inst{18-0} = imm19;
> +}
> +
> //===----------------------------------------------------------------------===//
> // Format #3 instruction classes in the Sparc
> //===----------------------------------------------------------------------===//
> @@ -75,9 +100,8 @@
>
> // Specific F3 classes: SparcV8 manual, page 44
> //
> -class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
> +class F3_1_asi<bits<2> opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins,
> string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
> - bits<8> asi = 0; // asi not currently used
> bits<5> rs2;
>
> let op = opVal;
> @@ -88,6 +112,10 @@
> let Inst{4-0} = rs2;
> }
>
> +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>;
> +
> class F3_2<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
> string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
> bits<13> simm13;
> @@ -168,12 +196,12 @@
> // Define rr and ri shift instructions with patterns.
> multiclass F3_S<string OpcStr, bits<6> Op3Val, bit XVal, SDNode OpNode,
> ValueType VT, RegisterClass RC> {
> - def rr : F3_Sr<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs, IntRegs:$rs2),
> - !strconcat(OpcStr, " $rs, $rs2, $rd"),
> - [(set VT:$rd, (OpNode VT:$rs, i32:$rs2))]>;
> - def ri : F3_Si<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs, i32imm:$shcnt),
> - !strconcat(OpcStr, " $rs, $shcnt, $rd"),
> - [(set VT:$rd, (OpNode VT:$rs, (i32 imm:$shcnt)))]>;
> + def rr : F3_Sr<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs1, IntRegs:$rs2),
> + !strconcat(OpcStr, " $rs1, $rs2, $rd"),
> + [(set VT:$rd, (OpNode VT:$rs1, i32:$rs2))]>;
> + def ri : F3_Si<2, Op3Val, XVal, (outs RC:$rd), (ins RC:$rs1, i32imm:$shcnt),
> + !strconcat(OpcStr, " $rs1, $shcnt, $rd"),
> + [(set VT:$rd, (OpNode VT:$rs1, (i32 imm:$shcnt)))]>;
> }
>
> class F4<bits<6> op3, dag outs, dag ins, string asmstr, list<dag> pattern>
> Index: lib/Target/Sparc/SparcInstrInfo.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcInstrInfo.cpp (revision 201091)
> +++ lib/Target/Sparc/SparcInstrInfo.cpp (working copy)
> @@ -431,9 +431,10 @@
> MachineBasicBlock::iterator MBBI = FirstMBB.begin();
> MachineRegisterInfo &RegInfo = MF->getRegInfo();
>
> - GlobalBaseReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
> + const TargetRegisterClass *PtrRC =
> + Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
> + GlobalBaseReg = RegInfo.createVirtualRegister(PtrRC);
>
> -
> DebugLoc dl;
>
> BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg);
> Index: lib/Target/Sparc/SparcInstrInfo.td
> ===================================================================
> --- lib/Target/Sparc/SparcInstrInfo.td (revision 201091)
> +++ lib/Target/Sparc/SparcInstrInfo.td (working copy)
> @@ -76,21 +76,38 @@
> def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [frameindex], []>;
>
> // Address operands
> +def SparcMEMrrAsmOperand : AsmOperandClass {
> + let Name = "MEMrr";
> + let ParserMethod = "parseMEMOperand";
> +}
> +
> +def SparcMEMriAsmOperand : AsmOperandClass {
> + let Name = "MEMri";
> + let ParserMethod = "parseMEMOperand";
> +}
> +
> def MEMrr : Operand<iPTR> {
> let PrintMethod = "printMemOperand";
> let MIOperandInfo = (ops ptr_rc, ptr_rc);
> + let ParserMatchClass = SparcMEMrrAsmOperand;
> }
> def MEMri : Operand<iPTR> {
> let PrintMethod = "printMemOperand";
> let MIOperandInfo = (ops ptr_rc, i32imm);
> + let ParserMatchClass = SparcMEMriAsmOperand;
> }
>
> def TLSSym : Operand<iPTR>;
>
> // Branch targets have OtherVT type.
> -def brtarget : Operand<OtherVT>;
> -def calltarget : Operand<i32>;
> +def brtarget : Operand<OtherVT> {
> + let EncoderMethod = "getBranchTargetOpValue";
> +}
>
> +def calltarget : Operand<i32> {
> + let EncoderMethod = "getCallTargetOpValue";
> +}
> +
> // Operand for printing out a condition code.
> let PrintMethod = "printCCOperand" in
> def CCOp : Operand<i32>;
> @@ -163,7 +180,7 @@
> [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
> SDNPVariadic]>;
>
> -def getPCX : Operand<i32> {
> +def getPCX : Operand<iPTR> {
> let PrintMethod = "printGetPCX";
> }
>
> @@ -210,15 +227,16 @@
> //===----------------------------------------------------------------------===//
>
> /// F3_12 multiclass - Define a normal F3_1/F3_2 pattern in one shot.
> -multiclass F3_12<string OpcStr, bits<6> Op3Val, SDNode OpNode> {
> +multiclass F3_12<string OpcStr, bits<6> Op3Val, SDNode OpNode,
> + RegisterClass RC, ValueType Ty, Operand immOp> {
> def rr : F3_1<2, Op3Val,
> - (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
> - !strconcat(OpcStr, " $b, $c, $dst"),
> - [(set i32:$dst, (OpNode i32:$b, i32:$c))]>;
> + (outs RC:$rd), (ins RC:$rs1, RC:$rs2),
> + !strconcat(OpcStr, " $rs1, $rs2, $rd"),
> + [(set Ty:$rd, (OpNode Ty:$rs1, Ty:$rs2))]>;
> def ri : F3_2<2, Op3Val,
> - (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
> - !strconcat(OpcStr, " $b, $c, $dst"),
> - [(set i32:$dst, (OpNode i32:$b, (i32 simm13:$c)))]>;
> + (outs RC:$rd), (ins RC:$rs1, immOp:$simm13),
> + !strconcat(OpcStr, " $rs1, $simm13, $rd"),
> + [(set Ty:$rd, (OpNode Ty:$rs1, (Ty simm13:$simm13)))]>;
> }
>
> /// F3_12np multiclass - Define a normal F3_1/F3_2 pattern in one shot, with no
> @@ -225,13 +243,39 @@
> /// pattern.
> multiclass F3_12np<string OpcStr, bits<6> Op3Val> {
> def rr : F3_1<2, Op3Val,
> - (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
> - !strconcat(OpcStr, " $b, $c, $dst"), []>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
> + !strconcat(OpcStr, " $rs1, $rs2, $rd"), []>;
> def ri : F3_2<2, Op3Val,
> - (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
> - !strconcat(OpcStr, " $b, $c, $dst"), []>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
> + !strconcat(OpcStr, " $rs1, $simm13, $rd"), []>;
> }
>
> +// Load multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot.
> +multiclass Load<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
> + RegisterClass RC, ValueType Ty> {
> + def rr : F3_1<3, Op3Val,
> + (outs RC:$dst), (ins MEMrr:$addr),
> + !strconcat(OpcStr, " [$addr], $dst"),
> + [(set Ty:$dst, (OpNode ADDRrr:$addr))]>;
> + def ri : F3_2<3, Op3Val,
> + (outs RC:$dst), (ins MEMri:$addr),
> + !strconcat(OpcStr, " [$addr], $dst"),
> + [(set Ty:$dst, (OpNode ADDRri:$addr))]>;
> +}
> +
> +// 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> {
> + def rr : F3_1<3, Op3Val,
> + (outs), (ins MEMrr:$addr, RC:$rd),
> + !strconcat(OpcStr, " $rd, [$addr]"),
> + [(OpNode Ty:$rd, ADDRrr:$addr)]>;
> + def ri : F3_2<3, Op3Val,
> + (outs), (ins MEMri:$addr, RC:$rd),
> + !strconcat(OpcStr, " $rd, [$addr]"),
> + [(OpNode Ty:$rd, ADDRri:$addr)]>;
> +}
> +
> //===----------------------------------------------------------------------===//
> // Instructions
> //===----------------------------------------------------------------------===//
> @@ -238,7 +282,10 @@
>
> // Pseudo instructions.
> class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
> - : InstSP<outs, ins, asmstr, pattern>;
> + : InstSP<outs, ins, asmstr, pattern> {
> + let isCodeGenOnly = 1;
> + let isPseudo = 1;
> +}
>
> // GETPCX for PIC
> let Defs = [O7] in {
> @@ -315,10 +362,18 @@
> [(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>;
> }
>
> +// JMPL Instruction.
> +let isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
> + def JMPLrr: F3_1<2, 0b111000, (outs IntRegs:$dst), (ins MEMrr:$addr),
> + "jmpl $addr, $dst", []>;
> + def JMPLri: F3_2<2, 0b111000, (outs IntRegs:$dst), (ins MEMri:$addr),
> + "jmpl $addr, $dst", []>;
> +}
>
> // Section A.3 - Synthetic Instructions, p. 85
> // special cases of JMPL:
> -let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
> +let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1,
> + isCodeGenOnly = 1 in {
> let rd = 0, rs1 = 15 in
> def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val),
> "jmp %o7+$val", [(retflag simm13:$val)]>;
> @@ -329,128 +384,28 @@
> }
>
> // Section B.1 - Load Integer Instructions, p. 90
> -def LDSBrr : F3_1<3, 0b001001,
> - (outs IntRegs:$dst), (ins MEMrr:$addr),
> - "ldsb [$addr], $dst",
> - [(set i32:$dst, (sextloadi8 ADDRrr:$addr))]>;
> -def LDSBri : F3_2<3, 0b001001,
> - (outs IntRegs:$dst), (ins MEMri:$addr),
> - "ldsb [$addr], $dst",
> - [(set i32:$dst, (sextloadi8 ADDRri:$addr))]>;
> -def LDSHrr : F3_1<3, 0b001010,
> - (outs IntRegs:$dst), (ins MEMrr:$addr),
> - "ldsh [$addr], $dst",
> - [(set i32:$dst, (sextloadi16 ADDRrr:$addr))]>;
> -def LDSHri : F3_2<3, 0b001010,
> - (outs IntRegs:$dst), (ins MEMri:$addr),
> - "ldsh [$addr], $dst",
> - [(set i32:$dst, (sextloadi16 ADDRri:$addr))]>;
> -def LDUBrr : F3_1<3, 0b000001,
> - (outs IntRegs:$dst), (ins MEMrr:$addr),
> - "ldub [$addr], $dst",
> - [(set i32:$dst, (zextloadi8 ADDRrr:$addr))]>;
> -def LDUBri : F3_2<3, 0b000001,
> - (outs IntRegs:$dst), (ins MEMri:$addr),
> - "ldub [$addr], $dst",
> - [(set i32:$dst, (zextloadi8 ADDRri:$addr))]>;
> -def LDUHrr : F3_1<3, 0b000010,
> - (outs IntRegs:$dst), (ins MEMrr:$addr),
> - "lduh [$addr], $dst",
> - [(set i32:$dst, (zextloadi16 ADDRrr:$addr))]>;
> -def LDUHri : F3_2<3, 0b000010,
> - (outs IntRegs:$dst), (ins MEMri:$addr),
> - "lduh [$addr], $dst",
> - [(set i32:$dst, (zextloadi16 ADDRri:$addr))]>;
> -def LDrr : F3_1<3, 0b000000,
> - (outs IntRegs:$dst), (ins MEMrr:$addr),
> - "ld [$addr], $dst",
> - [(set i32:$dst, (load ADDRrr:$addr))]>;
> -def LDri : F3_2<3, 0b000000,
> - (outs IntRegs:$dst), (ins MEMri:$addr),
> - "ld [$addr], $dst",
> - [(set i32:$dst, (load ADDRri:$addr))]>;
> +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>;
>
> // Section B.2 - Load Floating-point Instructions, p. 92
> -def LDFrr : F3_1<3, 0b100000,
> - (outs FPRegs:$dst), (ins MEMrr:$addr),
> - "ld [$addr], $dst",
> - [(set f32:$dst, (load ADDRrr:$addr))]>;
> -def LDFri : F3_2<3, 0b100000,
> - (outs FPRegs:$dst), (ins MEMri:$addr),
> - "ld [$addr], $dst",
> - [(set f32:$dst, (load ADDRri:$addr))]>;
> -def LDDFrr : F3_1<3, 0b100011,
> - (outs DFPRegs:$dst), (ins MEMrr:$addr),
> - "ldd [$addr], $dst",
> - [(set f64:$dst, (load ADDRrr:$addr))]>;
> -def LDDFri : F3_2<3, 0b100011,
> - (outs DFPRegs:$dst), (ins MEMri:$addr),
> - "ldd [$addr], $dst",
> - [(set f64:$dst, (load ADDRri:$addr))]>;
> -def LDQFrr : F3_1<3, 0b100010,
> - (outs QFPRegs:$dst), (ins MEMrr:$addr),
> - "ldq [$addr], $dst",
> - [(set f128:$dst, (load ADDRrr:$addr))]>,
> - Requires<[HasV9, HasHardQuad]>;
> -def LDQFri : F3_2<3, 0b100010,
> - (outs QFPRegs:$dst), (ins MEMri:$addr),
> - "ldq [$addr], $dst",
> - [(set f128:$dst, (load ADDRri:$addr))]>,
> - Requires<[HasV9, HasHardQuad]>;
> +defm LDF : Load<"ld", 0b100000, load, FPRegs, f32>;
> +defm LDDF : Load<"ldd", 0b100011, load, DFPRegs, f64>;
> +defm LDQF : Load<"ldq", 0b100010, load, QFPRegs, f128>,
> + Requires<[HasV9, HasHardQuad]>;
>
> // Section B.4 - Store Integer Instructions, p. 95
> -def STBrr : F3_1<3, 0b000101,
> - (outs), (ins MEMrr:$addr, IntRegs:$rd),
> - "stb $rd, [$addr]",
> - [(truncstorei8 i32:$rd, ADDRrr:$addr)]>;
> -def STBri : F3_2<3, 0b000101,
> - (outs), (ins MEMri:$addr, IntRegs:$rd),
> - "stb $rd, [$addr]",
> - [(truncstorei8 i32:$rd, ADDRri:$addr)]>;
> -def STHrr : F3_1<3, 0b000110,
> - (outs), (ins MEMrr:$addr, IntRegs:$rd),
> - "sth $rd, [$addr]",
> - [(truncstorei16 i32:$rd, ADDRrr:$addr)]>;
> -def STHri : F3_2<3, 0b000110,
> - (outs), (ins MEMri:$addr, IntRegs:$rd),
> - "sth $rd, [$addr]",
> - [(truncstorei16 i32:$rd, ADDRri:$addr)]>;
> -def STrr : F3_1<3, 0b000100,
> - (outs), (ins MEMrr:$addr, IntRegs:$rd),
> - "st $rd, [$addr]",
> - [(store i32:$rd, ADDRrr:$addr)]>;
> -def STri : F3_2<3, 0b000100,
> - (outs), (ins MEMri:$addr, IntRegs:$rd),
> - "st $rd, [$addr]",
> - [(store i32:$rd, ADDRri:$addr)]>;
> +defm STB : Store<"stb", 0b000101, truncstorei8, IntRegs, i32>;
> +defm STH : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>;
> +defm ST : Store<"st", 0b000100, store, IntRegs, i32>;
>
> // Section B.5 - Store Floating-point Instructions, p. 97
> -def STFrr : F3_1<3, 0b100100,
> - (outs), (ins MEMrr:$addr, FPRegs:$rd),
> - "st $rd, [$addr]",
> - [(store f32:$rd, ADDRrr:$addr)]>;
> -def STFri : F3_2<3, 0b100100,
> - (outs), (ins MEMri:$addr, FPRegs:$rd),
> - "st $rd, [$addr]",
> - [(store f32:$rd, ADDRri:$addr)]>;
> -def STDFrr : F3_1<3, 0b100111,
> - (outs), (ins MEMrr:$addr, DFPRegs:$rd),
> - "std $rd, [$addr]",
> - [(store f64:$rd, ADDRrr:$addr)]>;
> -def STDFri : F3_2<3, 0b100111,
> - (outs), (ins MEMri:$addr, DFPRegs:$rd),
> - "std $rd, [$addr]",
> - [(store f64:$rd, ADDRri:$addr)]>;
> -def STQFrr : F3_1<3, 0b100110,
> - (outs), (ins MEMrr:$addr, QFPRegs:$rd),
> - "stq $rd, [$addr]",
> - [(store f128:$rd, ADDRrr:$addr)]>,
> - Requires<[HasV9, HasHardQuad]>;
> -def STQFri : F3_2<3, 0b100110,
> - (outs), (ins MEMri:$addr, QFPRegs:$rd),
> - "stq $rd, [$addr]",
> - [(store f128:$rd, ADDRri:$addr)]>,
> - Requires<[HasV9, HasHardQuad]>;
> +defm STF : Store<"st", 0b100100, store, FPRegs, f32>;
> +defm STDF : Store<"std", 0b100111, store, DFPRegs, f64>;
> +defm STQF : Store<"stq", 0b100110, store, QFPRegs, f128>,
> + Requires<[HasV9, HasHardQuad]>;
>
> // Section B.9 - SETHI Instruction, p. 104
> def SETHIi: F2_1<0b100,
> @@ -464,45 +419,45 @@
> def NOP : F2_1<0b100, (outs), (ins), "nop", []>;
>
> // Section B.11 - Logical Instructions, p. 106
> -defm AND : F3_12<"and", 0b000001, and>;
> +defm AND : F3_12<"and", 0b000001, and, IntRegs, i32, i32imm>;
>
> def ANDNrr : F3_1<2, 0b000101,
> - (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
> - "andn $b, $c, $dst",
> - [(set i32:$dst, (and i32:$b, (not i32:$c)))]>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
> + "andn $rs1, $rs2, $rd",
> + [(set i32:$rd, (and i32:$rs1, (not i32:$rs2)))]>;
> def ANDNri : F3_2<2, 0b000101,
> - (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
> - "andn $b, $c, $dst", []>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
> + "andn $rs1, $simm13, $rd", []>;
>
> -defm OR : F3_12<"or", 0b000010, or>;
> +defm OR : F3_12<"or", 0b000010, or, IntRegs, i32, i32imm>;
>
> def ORNrr : F3_1<2, 0b000110,
> - (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
> - "orn $b, $c, $dst",
> - [(set i32:$dst, (or i32:$b, (not i32:$c)))]>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
> + "orn $rs1, $rs2, $rd",
> + [(set i32:$rd, (or i32:$rs1, (not i32:$rs2)))]>;
> def ORNri : F3_2<2, 0b000110,
> - (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
> - "orn $b, $c, $dst", []>;
> -defm XOR : F3_12<"xor", 0b000011, xor>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
> + "orn $rs1, $simm13, $rd", []>;
> +defm XOR : F3_12<"xor", 0b000011, xor, IntRegs, i32, i32imm>;
>
> def XNORrr : F3_1<2, 0b000111,
> - (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
> - "xnor $b, $c, $dst",
> - [(set i32:$dst, (not (xor i32:$b, i32:$c)))]>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
> + "xnor $rs1, $rs2, $rd",
> + [(set i32:$rd, (not (xor i32:$rs1, i32:$rs2)))]>;
> def XNORri : F3_2<2, 0b000111,
> - (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
> - "xnor $b, $c, $dst", []>;
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
> + "xnor $rs1, $simm13, $rd", []>;
>
> // Section B.12 - Shift Instructions, p. 107
> -defm SLL : F3_12<"sll", 0b100101, shl>;
> -defm SRL : F3_12<"srl", 0b100110, srl>;
> -defm SRA : F3_12<"sra", 0b100111, sra>;
> +defm SLL : F3_12<"sll", 0b100101, shl, IntRegs, i32, i32imm>;
> +defm SRL : F3_12<"srl", 0b100110, srl, IntRegs, i32, i32imm>;
> +defm SRA : F3_12<"sra", 0b100111, sra, IntRegs, i32, i32imm>;
>
> // Section B.13 - Add Instructions, p. 108
> -defm ADD : F3_12<"add", 0b000000, add>;
> +defm ADD : F3_12<"add", 0b000000, add, IntRegs, i32, i32imm>;
>
> // "LEA" forms of add (patterns to make tblgen happy)
> -let Predicates = [Is32Bit] in
> +let Predicates = [Is32Bit], isCodeGenOnly = 1 in
> def LEA_ADDri : F3_2<2, 0b000000,
> (outs IntRegs:$dst), (ins MEMri:$addr),
> "add ${addr:arith}, $dst",
> @@ -509,40 +464,34 @@
> [(set iPTR:$dst, ADDRri:$addr)]>;
>
> let Defs = [ICC] in
> - defm ADDCC : F3_12<"addcc", 0b010000, addc>;
> + defm ADDCC : F3_12<"addcc", 0b010000, addc, IntRegs, i32, i32imm>;
>
> let Uses = [ICC], Defs = [ICC] in
> - defm ADDX : F3_12<"addxcc", 0b011000, adde>;
> + defm ADDE : F3_12<"addxcc", 0b011000, adde, IntRegs, i32, i32imm>;
>
> // Section B.15 - Subtract Instructions, p. 110
> -defm SUB : F3_12 <"sub" , 0b000100, sub>;
> +defm SUB : F3_12 <"sub" , 0b000100, sub, IntRegs, i32, i32imm>;
> let Uses = [ICC], Defs = [ICC] in
> - defm SUBX : F3_12 <"subxcc" , 0b011100, sube>;
> + defm SUBE : F3_12 <"subxcc" , 0b011100, sube, IntRegs, i32, i32imm>;
>
> let Defs = [ICC] in
> - defm SUBCC : F3_12 <"subcc", 0b010100, subc>;
> + defm SUBCC : F3_12 <"subcc", 0b010100, subc, IntRegs, i32, i32imm>;
>
> let Defs = [ICC], rd = 0 in {
> def CMPrr : F3_1<2, 0b010100,
> - (outs), (ins IntRegs:$b, IntRegs:$c),
> - "cmp $b, $c",
> - [(SPcmpicc i32:$b, i32:$c)]>;
> + (outs), (ins IntRegs:$rs1, IntRegs:$rs2),
> + "cmp $rs1, $rs2",
> + [(SPcmpicc i32:$rs1, i32:$rs2)]>;
> def CMPri : F3_2<2, 0b010100,
> - (outs), (ins IntRegs:$b, i32imm:$c),
> - "cmp $b, $c",
> - [(SPcmpicc i32:$b, (i32 simm13:$c))]>;
> + (outs), (ins IntRegs:$rs1, i32imm:$simm13),
> + "cmp $rs1, $simm13",
> + [(SPcmpicc i32:$rs1, (i32 simm13:$simm13))]>;
> }
>
> -let Uses = [ICC], Defs = [ICC] in
> - def SUBXCCrr: F3_1<2, 0b011100,
> - (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
> - "subxcc $b, $c, $dst", []>;
> -
> -
> // Section B.18 - Multiply Instructions, p. 113
> let Defs = [Y] in {
> defm UMUL : F3_12np<"umul", 0b001010>;
> - defm SMUL : F3_12 <"smul", 0b001011, mul>;
> + defm SMUL : F3_12 <"smul", 0b001011, mul, IntRegs, i32, i32imm>;
> }
>
> // Section B.19 - Divide Instructions, p. 115
> @@ -578,9 +527,8 @@
> }
>
> // Indirect branch instructions.
> -let isTerminator = 1, isBarrier = 1,
> - hasDelaySlot = 1, isBranch =1,
> - isIndirectBranch = 1, rd = 0 in {
> +let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1,
> + isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in {
> def BINDrr : F3_1<2, 0b111000,
> (outs), (ins MEMrr:$ptr),
> "jmp $ptr",
> @@ -623,15 +571,17 @@
> let Inst{29-0} = disp;
> }
>
> - // indirect calls
> - def JMPLrr : F3_1<2, 0b111000,
> - (outs), (ins MEMrr:$ptr, variable_ops),
> - "call $ptr",
> - [(call ADDRrr:$ptr)]> { let rd = 15; }
> - def JMPLri : F3_2<2, 0b111000,
> - (outs), (ins MEMri:$ptr, variable_ops),
> - "call $ptr",
> - [(call ADDRri:$ptr)]> { let rd = 15; }
> + // indirect calls: special cases of JMPL.
> + let isCodeGenOnly = 1, rd = 15 in {
> + def CALLrr : F3_1<2, 0b111000,
> + (outs), (ins MEMrr:$ptr, variable_ops),
> + "call $ptr",
> + [(call ADDRrr:$ptr)]>;
> + def CALLri : F3_2<2, 0b111000,
> + (outs), (ins MEMri:$ptr, variable_ops),
> + "call $ptr",
> + [(call ADDRri:$ptr)]>;
> + }
> }
>
> // Section B.28 - Read State Register Instructions
> @@ -651,91 +601,91 @@
> }
> // Convert Integer to Floating-point Instructions, p. 141
> def FITOS : F3_3u<2, 0b110100, 0b011000100,
> - (outs FPRegs:$dst), (ins FPRegs:$src),
> - "fitos $src, $dst",
> - [(set FPRegs:$dst, (SPitof FPRegs:$src))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs2),
> + "fitos $rs2, $rd",
> + [(set FPRegs:$rd, (SPitof FPRegs:$rs2))]>;
> def FITOD : F3_3u<2, 0b110100, 0b011001000,
> - (outs DFPRegs:$dst), (ins FPRegs:$src),
> - "fitod $src, $dst",
> - [(set DFPRegs:$dst, (SPitof FPRegs:$src))]>;
> + (outs DFPRegs:$rd), (ins FPRegs:$rs2),
> + "fitod $rs2, $rd",
> + [(set DFPRegs:$rd, (SPitof FPRegs:$rs2))]>;
> def FITOQ : F3_3u<2, 0b110100, 0b011001100,
> - (outs QFPRegs:$dst), (ins FPRegs:$src),
> - "fitoq $src, $dst",
> - [(set QFPRegs:$dst, (SPitof FPRegs:$src))]>,
> + (outs QFPRegs:$rd), (ins FPRegs:$rs2),
> + "fitoq $rs2, $rd",
> + [(set QFPRegs:$rd, (SPitof FPRegs:$rs2))]>,
> Requires<[HasHardQuad]>;
>
> // Convert Floating-point to Integer Instructions, p. 142
> def FSTOI : F3_3u<2, 0b110100, 0b011010001,
> - (outs FPRegs:$dst), (ins FPRegs:$src),
> - "fstoi $src, $dst",
> - [(set FPRegs:$dst, (SPftoi FPRegs:$src))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs2),
> + "fstoi $rs2, $rd",
> + [(set FPRegs:$rd, (SPftoi FPRegs:$rs2))]>;
> def FDTOI : F3_3u<2, 0b110100, 0b011010010,
> - (outs FPRegs:$dst), (ins DFPRegs:$src),
> - "fdtoi $src, $dst",
> - [(set FPRegs:$dst, (SPftoi DFPRegs:$src))]>;
> + (outs FPRegs:$rd), (ins DFPRegs:$rs2),
> + "fdtoi $rs2, $rd",
> + [(set FPRegs:$rd, (SPftoi DFPRegs:$rs2))]>;
> def FQTOI : F3_3u<2, 0b110100, 0b011010011,
> - (outs FPRegs:$dst), (ins QFPRegs:$src),
> - "fqtoi $src, $dst",
> - [(set FPRegs:$dst, (SPftoi QFPRegs:$src))]>,
> + (outs FPRegs:$rd), (ins QFPRegs:$rs2),
> + "fqtoi $rs2, $rd",
> + [(set FPRegs:$rd, (SPftoi QFPRegs:$rs2))]>,
> Requires<[HasHardQuad]>;
>
> // Convert between Floating-point Formats Instructions, p. 143
> def FSTOD : F3_3u<2, 0b110100, 0b011001001,
> - (outs DFPRegs:$dst), (ins FPRegs:$src),
> - "fstod $src, $dst",
> - [(set f64:$dst, (fextend f32:$src))]>;
> + (outs DFPRegs:$rd), (ins FPRegs:$rs2),
> + "fstod $rs2, $rd",
> + [(set f64:$rd, (fextend f32:$rs2))]>;
> def FSTOQ : F3_3u<2, 0b110100, 0b011001101,
> - (outs QFPRegs:$dst), (ins FPRegs:$src),
> - "fstoq $src, $dst",
> - [(set f128:$dst, (fextend f32:$src))]>,
> + (outs QFPRegs:$rd), (ins FPRegs:$rs2),
> + "fstoq $rs2, $rd",
> + [(set f128:$rd, (fextend f32:$rs2))]>,
> Requires<[HasHardQuad]>;
> def FDTOS : F3_3u<2, 0b110100, 0b011000110,
> - (outs FPRegs:$dst), (ins DFPRegs:$src),
> - "fdtos $src, $dst",
> - [(set f32:$dst, (fround f64:$src))]>;
> -def FDTOQ : F3_3u<2, 0b110100, 0b01101110,
> - (outs QFPRegs:$dst), (ins DFPRegs:$src),
> - "fdtoq $src, $dst",
> - [(set f128:$dst, (fextend f64:$src))]>,
> + (outs FPRegs:$rd), (ins DFPRegs:$rs2),
> + "fdtos $rs2, $rd",
> + [(set f32:$rd, (fround f64:$rs2))]>;
> +def FDTOQ : F3_3u<2, 0b110100, 0b011001110,
> + (outs QFPRegs:$rd), (ins DFPRegs:$rs2),
> + "fdtoq $rs2, $rd",
> + [(set f128:$rd, (fextend f64:$rs2))]>,
> Requires<[HasHardQuad]>;
> def FQTOS : F3_3u<2, 0b110100, 0b011000111,
> - (outs FPRegs:$dst), (ins QFPRegs:$src),
> - "fqtos $src, $dst",
> - [(set f32:$dst, (fround f128:$src))]>,
> + (outs FPRegs:$rd), (ins QFPRegs:$rs2),
> + "fqtos $rs2, $rd",
> + [(set f32:$rd, (fround f128:$rs2))]>,
> Requires<[HasHardQuad]>;
> def FQTOD : F3_3u<2, 0b110100, 0b011001011,
> - (outs DFPRegs:$dst), (ins QFPRegs:$src),
> - "fqtod $src, $dst",
> - [(set f64:$dst, (fround f128:$src))]>,
> + (outs DFPRegs:$rd), (ins QFPRegs:$rs2),
> + "fqtod $rs2, $rd",
> + [(set f64:$rd, (fround f128:$rs2))]>,
> Requires<[HasHardQuad]>;
>
> // Floating-point Move Instructions, p. 144
> def FMOVS : F3_3u<2, 0b110100, 0b000000001,
> - (outs FPRegs:$dst), (ins FPRegs:$src),
> - "fmovs $src, $dst", []>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs2),
> + "fmovs $rs2, $rd", []>;
> def FNEGS : F3_3u<2, 0b110100, 0b000000101,
> - (outs FPRegs:$dst), (ins FPRegs:$src),
> - "fnegs $src, $dst",
> - [(set f32:$dst, (fneg f32:$src))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs2),
> + "fnegs $rs2, $rd",
> + [(set f32:$rd, (fneg f32:$rs2))]>;
> def FABSS : F3_3u<2, 0b110100, 0b000001001,
> - (outs FPRegs:$dst), (ins FPRegs:$src),
> - "fabss $src, $dst",
> - [(set f32:$dst, (fabs f32:$src))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs2),
> + "fabss $rs2, $rd",
> + [(set f32:$rd, (fabs f32:$rs2))]>;
>
>
> // Floating-point Square Root Instructions, p.145
> def FSQRTS : F3_3u<2, 0b110100, 0b000101001,
> - (outs FPRegs:$dst), (ins FPRegs:$src),
> - "fsqrts $src, $dst",
> - [(set f32:$dst, (fsqrt f32:$src))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs2),
> + "fsqrts $rs2, $rd",
> + [(set f32:$rd, (fsqrt f32:$rs2))]>;
> def FSQRTD : F3_3u<2, 0b110100, 0b000101010,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src),
> - "fsqrtd $src, $dst",
> - [(set f64:$dst, (fsqrt f64:$src))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
> + "fsqrtd $rs2, $rd",
> + [(set f64:$rd, (fsqrt f64:$rs2))]>;
> def FSQRTQ : F3_3u<2, 0b110100, 0b000101011,
> - (outs QFPRegs:$dst), (ins QFPRegs:$src),
> - "fsqrtq $src, $dst",
> - [(set f128:$dst, (fsqrt f128:$src))]>,
> + (outs QFPRegs:$rd), (ins QFPRegs:$rs2),
> + "fsqrtq $rs2, $rd",
> + [(set f128:$rd, (fsqrt f128:$rs2))]>,
> Requires<[HasHardQuad]>;
>
>
> @@ -742,73 +692,73 @@
>
> // Floating-point Add and Subtract Instructions, p. 146
> def FADDS : F3_3<2, 0b110100, 0b001000001,
> - (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
> - "fadds $src1, $src2, $dst",
> - [(set f32:$dst, (fadd f32:$src1, f32:$src2))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
> + "fadds $rs1, $rs2, $rd",
> + [(set f32:$rd, (fadd f32:$rs1, f32:$rs2))]>;
> def FADDD : F3_3<2, 0b110100, 0b001000010,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
> - "faddd $src1, $src2, $dst",
> - [(set f64:$dst, (fadd f64:$src1, f64:$src2))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
> + "faddd $rs1, $rs2, $rd",
> + [(set f64:$rd, (fadd f64:$rs1, f64:$rs2))]>;
> def FADDQ : F3_3<2, 0b110100, 0b001000011,
> - (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
> - "faddq $src1, $src2, $dst",
> - [(set f128:$dst, (fadd f128:$src1, f128:$src2))]>,
> + (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2),
> + "faddq $rs1, $rs2, $rd",
> + [(set f128:$rd, (fadd f128:$rs1, f128:$rs2))]>,
> Requires<[HasHardQuad]>;
>
> def FSUBS : F3_3<2, 0b110100, 0b001000101,
> - (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
> - "fsubs $src1, $src2, $dst",
> - [(set f32:$dst, (fsub f32:$src1, f32:$src2))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
> + "fsubs $rs1, $rs2, $rd",
> + [(set f32:$rd, (fsub f32:$rs1, f32:$rs2))]>;
> def FSUBD : F3_3<2, 0b110100, 0b001000110,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
> - "fsubd $src1, $src2, $dst",
> - [(set f64:$dst, (fsub f64:$src1, f64:$src2))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
> + "fsubd $rs1, $rs2, $rd",
> + [(set f64:$rd, (fsub f64:$rs1, f64:$rs2))]>;
> def FSUBQ : F3_3<2, 0b110100, 0b001000111,
> - (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
> - "fsubq $src1, $src2, $dst",
> - [(set f128:$dst, (fsub f128:$src1, f128:$src2))]>,
> + (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2),
> + "fsubq $rs1, $rs2, $rd",
> + [(set f128:$rd, (fsub f128:$rs1, f128:$rs2))]>,
> Requires<[HasHardQuad]>;
>
>
> // Floating-point Multiply and Divide Instructions, p. 147
> def FMULS : F3_3<2, 0b110100, 0b001001001,
> - (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
> - "fmuls $src1, $src2, $dst",
> - [(set f32:$dst, (fmul f32:$src1, f32:$src2))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
> + "fmuls $rs1, $rs2, $rd",
> + [(set f32:$rd, (fmul f32:$rs1, f32:$rs2))]>;
> def FMULD : F3_3<2, 0b110100, 0b001001010,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
> - "fmuld $src1, $src2, $dst",
> - [(set f64:$dst, (fmul f64:$src1, f64:$src2))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
> + "fmuld $rs1, $rs2, $rd",
> + [(set f64:$rd, (fmul f64:$rs1, f64:$rs2))]>;
> def FMULQ : F3_3<2, 0b110100, 0b001001011,
> - (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
> - "fmulq $src1, $src2, $dst",
> - [(set f128:$dst, (fmul f128:$src1, f128:$src2))]>,
> + (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2),
> + "fmulq $rs1, $rs2, $rd",
> + [(set f128:$rd, (fmul f128:$rs1, f128:$rs2))]>,
> Requires<[HasHardQuad]>;
>
> def FSMULD : F3_3<2, 0b110100, 0b001101001,
> - (outs DFPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
> - "fsmuld $src1, $src2, $dst",
> - [(set f64:$dst, (fmul (fextend f32:$src1),
> - (fextend f32:$src2)))]>;
> + (outs DFPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
> + "fsmuld $rs1, $rs2, $rd",
> + [(set f64:$rd, (fmul (fextend f32:$rs1),
> + (fextend f32:$rs2)))]>;
> def FDMULQ : F3_3<2, 0b110100, 0b001101110,
> - (outs QFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
> - "fdmulq $src1, $src2, $dst",
> - [(set f128:$dst, (fmul (fextend f64:$src1),
> - (fextend f64:$src2)))]>,
> + (outs QFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
> + "fdmulq $rs1, $rs2, $rd",
> + [(set f128:$rd, (fmul (fextend f64:$rs1),
> + (fextend f64:$rs2)))]>,
> Requires<[HasHardQuad]>;
>
> def FDIVS : F3_3<2, 0b110100, 0b001001101,
> - (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
> - "fdivs $src1, $src2, $dst",
> - [(set f32:$dst, (fdiv f32:$src1, f32:$src2))]>;
> + (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
> + "fdivs $rs1, $rs2, $rd",
> + [(set f32:$rd, (fdiv f32:$rs1, f32:$rs2))]>;
> def FDIVD : F3_3<2, 0b110100, 0b001001110,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
> - "fdivd $src1, $src2, $dst",
> - [(set f64:$dst, (fdiv f64:$src1, f64:$src2))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
> + "fdivd $rs1, $rs2, $rd",
> + [(set f64:$rd, (fdiv f64:$rs1, f64:$rs2))]>;
> def FDIVQ : F3_3<2, 0b110100, 0b001001111,
> - (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
> - "fdivq $src1, $src2, $dst",
> - [(set f128:$dst, (fdiv f128:$src1, f128:$src2))]>,
> + (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2),
> + "fdivq $rs1, $rs2, $rd",
> + [(set f128:$rd, (fdiv f128:$rs1, f128:$rs2))]>,
> Requires<[HasHardQuad]>;
>
> // Floating-point Compare Instructions, p. 148
> @@ -820,17 +770,17 @@
>
> let Defs = [FCC] in {
> def FCMPS : F3_3c<2, 0b110101, 0b001010001,
> - (outs), (ins FPRegs:$src1, FPRegs:$src2),
> - "fcmps $src1, $src2",
> - [(SPcmpfcc f32:$src1, f32:$src2)]>;
> + (outs), (ins FPRegs:$rs1, FPRegs:$rs2),
> + "fcmps $rs1, $rs2",
> + [(SPcmpfcc f32:$rs1, f32:$rs2)]>;
> def FCMPD : F3_3c<2, 0b110101, 0b001010010,
> - (outs), (ins DFPRegs:$src1, DFPRegs:$src2),
> - "fcmpd $src1, $src2",
> - [(SPcmpfcc f64:$src1, f64:$src2)]>;
> + (outs), (ins DFPRegs:$rs1, DFPRegs:$rs2),
> + "fcmpd $rs1, $rs2",
> + [(SPcmpfcc f64:$rs1, f64:$rs2)]>;
> def FCMPQ : F3_3c<2, 0b110101, 0b001010011,
> - (outs), (ins QFPRegs:$src1, QFPRegs:$src2),
> - "fcmpq $src1, $src2",
> - [(SPcmpfcc f128:$src1, f128:$src2)]>,
> + (outs), (ins QFPRegs:$rs1, QFPRegs:$rs2),
> + "fcmpq $rs1, $rs2",
> + [(SPcmpfcc f128:$rs1, f128:$rs2)]>,
> Requires<[HasHardQuad]>;
> }
>
> @@ -837,7 +787,7 @@
> //===----------------------------------------------------------------------===//
> // Instructions for Thread Local Storage(TLS).
> //===----------------------------------------------------------------------===//
> -
> +let isCodeGenOnly = 1, isAsmParserOnly = 1 in {
> def TLS_ADDrr : F3_1<2, 0b000000,
> (outs IntRegs:$rd),
> (ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym),
> @@ -861,6 +811,7 @@
> let op = 1;
> let Inst{29-0} = disp;
> }
> +}
>
> //===----------------------------------------------------------------------===//
> // V9 Instructions
> @@ -912,8 +863,9 @@
> def FMOVQ_ICC
> : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd),
> (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond),
> - "fmovd$cond %icc, $rs2, $rd",
> - [(set f128:$rd, (SPselecticc f128:$rs2, f128:$f, imm:$cond))]>;
> + "fmovq$cond %icc, $rs2, $rd",
> + [(set f128:$rd, (SPselecticc f128:$rs2, f128:$f, imm:$cond))]>,
> + Requires<[HasHardQuad]>;
> }
>
> let Uses = [FCC], opf_cc = 0b000 in {
> @@ -930,8 +882,9 @@
> def FMOVQ_FCC
> : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd),
> (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond),
> - "fmovd$cond %fcc0, $rs2, $rd",
> - [(set f128:$rd, (SPselectfcc f128:$rs2, f128:$f, imm:$cond))]>;
> + "fmovq$cond %fcc0, $rs2, $rd",
> + [(set f128:$rd, (SPselectfcc f128:$rs2, f128:$f, imm:$cond))]>,
> + Requires<[HasHardQuad]>;
> }
>
> }
> @@ -939,41 +892,68 @@
> // Floating-Point Move Instructions, p. 164 of the V9 manual.
> let Predicates = [HasV9] in {
> def FMOVD : F3_3u<2, 0b110100, 0b000000010,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src),
> - "fmovd $src, $dst", []>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
> + "fmovd $rs2, $rd", []>;
> def FMOVQ : F3_3u<2, 0b110100, 0b000000011,
> - (outs QFPRegs:$dst), (ins QFPRegs:$src),
> - "fmovq $src, $dst", []>,
> + (outs QFPRegs:$rd), (ins QFPRegs:$rs2),
> + "fmovq $rs2, $rd", []>,
> Requires<[HasHardQuad]>;
> def FNEGD : F3_3u<2, 0b110100, 0b000000110,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src),
> - "fnegd $src, $dst",
> - [(set f64:$dst, (fneg f64:$src))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
> + "fnegd $rs2, $rd",
> + [(set f64:$rd, (fneg f64:$rs2))]>;
> def FNEGQ : F3_3u<2, 0b110100, 0b000000111,
> - (outs QFPRegs:$dst), (ins QFPRegs:$src),
> - "fnegq $src, $dst",
> - [(set f128:$dst, (fneg f128:$src))]>,
> + (outs QFPRegs:$rd), (ins QFPRegs:$rs2),
> + "fnegq $rs2, $rd",
> + [(set f128:$rd, (fneg f128:$rs2))]>,
> Requires<[HasHardQuad]>;
> def FABSD : F3_3u<2, 0b110100, 0b000001010,
> - (outs DFPRegs:$dst), (ins DFPRegs:$src),
> - "fabsd $src, $dst",
> - [(set f64:$dst, (fabs f64:$src))]>;
> + (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
> + "fabsd $rs2, $rd",
> + [(set f64:$rd, (fabs f64:$rs2))]>;
> def FABSQ : F3_3u<2, 0b110100, 0b000001011,
> - (outs QFPRegs:$dst), (ins QFPRegs:$src),
> - "fabsq $src, $dst",
> - [(set f128:$dst, (fabs f128:$src))]>,
> + (outs QFPRegs:$rd), (ins QFPRegs:$rs2),
> + "fabsq $rs2, $rd",
> + [(set f128:$rd, (fabs f128:$rs2))]>,
> Requires<[HasHardQuad]>;
> }
>
> // POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear
> -// the top 32-bits before using it. To do this clearing, we use a SLLri X,0.
> +// the top 32-bits before using it. To do this clearing, we use a SRLri X,0.
> let rs1 = 0 in
> def POPCrr : F3_1<2, 0b101110,
> (outs IntRegs:$dst), (ins IntRegs:$src),
> "popc $src, $dst", []>, Requires<[HasV9]>;
> def : Pat<(ctpop i32:$src),
> - (POPCrr (SLLri $src, 0))>;
> + (POPCrr (SRLri $src, 0))>;
>
> +// Atomic swap.
> +let hasSideEffects =1, rd = 0, rs1 = 0b01111, rs2 = 0 in
> + def STBAR : F3_1<2, 0b101000, (outs), (ins), "stbar", []>;
> +
> +let Predicates = [HasV9], hasSideEffects = 1, rd = 0, rs1 = 0b01111 in
> + def MEMBARi : F3_2<2, 0b101000, (outs), (ins i32imm:$simm13),
> + "membar $simm13", []>;
> +
> +let Constraints = "$val = $dst" in {
> + def SWAPrr : F3_1<3, 0b001111,
> + (outs IntRegs:$dst), (ins MEMrr:$addr, IntRegs:$val),
> + "swap [$addr], $dst",
> + [(set i32:$dst, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>;
> + def SWAPri : F3_2<3, 0b001111,
> + (outs IntRegs:$dst), (ins MEMri:$addr, IntRegs:$val),
> + "swap [$addr], $dst",
> + [(set i32:$dst, (atomic_swap_32 ADDRri:$addr, i32:$val))]>;
> +}
> +
> +let Predicates = [HasV9], Constraints = "$swap = $rd" in
> + def CASrr: F3_1_asi<3, 0b111100, 0b10000000,
> + (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2,
> + IntRegs:$swap),
> + "cas [$rs1], $rs2, $rd",
> + [(set i32:$rd,
> + (atomic_cmp_swap iPTR:$rs1, i32:$rs2, i32:$swap))]>;
> +
> //===----------------------------------------------------------------------===//
> // Non-Instruction Patterns
> //===----------------------------------------------------------------------===//
> @@ -987,6 +967,8 @@
>
>
> // Global addresses, constant pool entries
> +let Predicates = [Is32Bit] in {
> +
> def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>;
> def : Pat<(SPlo tglobaladdr:$in), (ORri (i32 G0), tglobaladdr:$in)>;
> def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>;
> @@ -1009,6 +991,7 @@
> def : Pat<(add iPTR:$r, (SPlo tconstpool:$in)), (ADDri $r, tconstpool:$in)>;
> def : Pat<(add iPTR:$r, (SPlo tblockaddress:$in)),
> (ADDri $r, tblockaddress:$in)>;
> +}
>
> // Calls:
> def : Pat<(call tglobaladdr:$dst),
> @@ -1032,4 +1015,18 @@
> def : Pat<(store (i32 0), ADDRrr:$dst), (STrr ADDRrr:$dst, (i32 G0))>;
> def : Pat<(store (i32 0), ADDRri:$dst), (STri ADDRri:$dst, (i32 G0))>;
>
> +// store bar for all atomic_fence in V8.
> +let Predicates = [HasNoV9] in
> + def : Pat<(atomic_fence imm, imm), (STBAR)>;
> +
> +// atomic_load_32 addr -> load addr
> +def : Pat<(i32 (atomic_load ADDRrr:$src)), (LDrr ADDRrr:$src)>;
> +def : Pat<(i32 (atomic_load ADDRri:$src)), (LDri ADDRri:$src)>;
> +
> +// atomic_store_32 val, addr -> store val, addr
> +def : Pat<(atomic_store ADDRrr:$dst, i32:$val), (STrr ADDRrr:$dst, $val)>;
> +def : Pat<(atomic_store ADDRri:$dst, i32:$val), (STri ADDRri:$dst, $val)>;
> +
> +
> include "SparcInstr64Bit.td"
> +include "SparcInstrAliases.td"
> Index: lib/Target/Sparc/SparcJITInfo.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcJITInfo.cpp (revision 201091)
> +++ lib/Target/Sparc/SparcJITInfo.cpp (working copy)
> @@ -12,8 +12,9 @@
> //===----------------------------------------------------------------------===//
> #define DEBUG_TYPE "jit"
> #include "SparcJITInfo.h"
> +#include "Sparc.h"
> #include "SparcRelocations.h"
> -
> +#include "llvm/ADT/SmallVector.h"
> #include "llvm/CodeGen/JITCodeEmitter.h"
> #include "llvm/Support/Memory.h"
>
> @@ -27,6 +28,13 @@
>
> extern "C" {
> #if defined (__sparc__)
> +
> +#if defined(__arch64__)
> +#define FRAME_PTR(X) #X "+2047"
> +#else
> +#define FRAME_PTR(X) #X
> +#endif
> +
> asm(
> ".text\n"
> "\t.align 4\n"
> @@ -33,20 +41,54 @@
> "\t.global SparcCompilationCallback\n"
> "\t.type SparcCompilationCallback, #function\n"
> "SparcCompilationCallback:\n"
> - // Save current register window.
> - "\tsave %sp, -192, %sp\n"
> - // stubaddr+4 is in %g1.
> + // Save current register window and create stack.
> + // 128 (save area) + 6*8 (for arguments) + 16*8 (for float regfile) = 304
> + "\tsave %sp, -304, %sp\n"
> + // save float regfile to the stack.
> + "\tstd %f0, [" FRAME_PTR(%fp) "-0]\n"
> + "\tstd %f2, [" FRAME_PTR(%fp) "-8]\n"
> + "\tstd %f4, [" FRAME_PTR(%fp) "-16]\n"
> + "\tstd %f6, [" FRAME_PTR(%fp) "-24]\n"
> + "\tstd %f8, [" FRAME_PTR(%fp) "-32]\n"
> + "\tstd %f10, [" FRAME_PTR(%fp) "-40]\n"
> + "\tstd %f12, [" FRAME_PTR(%fp) "-48]\n"
> + "\tstd %f14, [" FRAME_PTR(%fp) "-56]\n"
> + "\tstd %f16, [" FRAME_PTR(%fp) "-64]\n"
> + "\tstd %f18, [" FRAME_PTR(%fp) "-72]\n"
> + "\tstd %f20, [" FRAME_PTR(%fp) "-80]\n"
> + "\tstd %f22, [" FRAME_PTR(%fp) "-88]\n"
> + "\tstd %f24, [" FRAME_PTR(%fp) "-96]\n"
> + "\tstd %f26, [" FRAME_PTR(%fp) "-104]\n"
> + "\tstd %f28, [" FRAME_PTR(%fp) "-112]\n"
> + "\tstd %f30, [" FRAME_PTR(%fp) "-120]\n"
> + // stubaddr is in %g1.
> "\tcall SparcCompilationCallbackC\n"
> - "\t sub %g1, 4, %o0\n"
> + "\t mov %g1, %o0\n"
> + // restore float regfile from the stack.
> + "\tldd [" FRAME_PTR(%fp) "-0], %f0\n"
> + "\tldd [" FRAME_PTR(%fp) "-8], %f2\n"
> + "\tldd [" FRAME_PTR(%fp) "-16], %f4\n"
> + "\tldd [" FRAME_PTR(%fp) "-24], %f6\n"
> + "\tldd [" FRAME_PTR(%fp) "-32], %f8\n"
> + "\tldd [" FRAME_PTR(%fp) "-40], %f10\n"
> + "\tldd [" FRAME_PTR(%fp) "-48], %f12\n"
> + "\tldd [" FRAME_PTR(%fp) "-56], %f14\n"
> + "\tldd [" FRAME_PTR(%fp) "-64], %f16\n"
> + "\tldd [" FRAME_PTR(%fp) "-72], %f18\n"
> + "\tldd [" FRAME_PTR(%fp) "-80], %f20\n"
> + "\tldd [" FRAME_PTR(%fp) "-88], %f22\n"
> + "\tldd [" FRAME_PTR(%fp) "-96], %f24\n"
> + "\tldd [" FRAME_PTR(%fp) "-104], %f26\n"
> + "\tldd [" FRAME_PTR(%fp) "-112], %f28\n"
> + "\tldd [" FRAME_PTR(%fp) "-120], %f30\n"
> // restore original register window and
> // copy %o0 to %g1
> - "\t restore %o0, 0, %g1\n"
> + "\trestore %o0, 0, %g1\n"
> // call the new stub
> "\tjmp %g1\n"
> "\t nop\n"
> "\t.size SparcCompilationCallback, .-SparcCompilationCallback"
> );
> -
> #else
> void SparcCompilationCallback() {
> llvm_unreachable(
> @@ -55,33 +97,120 @@
> #endif
> }
>
> -#define HI(Val) (((unsigned)(Val)) >> 10)
> -#define LO(Val) (((unsigned)(Val)) & 0x3FF)
>
> #define SETHI_INST(imm, rd) (0x01000000 | ((rd) << 25) | ((imm) & 0x3FFFFF))
> #define JMP_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x38 << 19) \
> | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF))
> #define NOP_INST SETHI_INST(0, 0)
> +#define OR_INST_I(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x02 << 19) \
> + | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF))
> +#define OR_INST_R(rs1, rs2, rd) (0x80000000 | ((rd) << 25) | (0x02 << 19) \
> + | ((rs1) << 14) | (0 << 13) | ((rs2) & 0x1F))
> +#define RDPC_INST(rd) (0x80000000 | ((rd) << 25) | (0x28 << 19) \
> + | (5 << 14))
> +#define LDX_INST(rs1, imm, rd) (0xC0000000 | ((rd) << 25) | (0x0B << 19) \
> + | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF))
> +#define SLLX_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x25 << 19) \
> + | ((rs1) << 14) | (3 << 12) | ((imm) & 0x3F))
> +#define SUB_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x04 << 19) \
> + | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF))
> +#define XOR_INST(rs1, imm, rd) (0x80000000 | ((rd) << 25) | (0x03 << 19) \
> + | ((rs1) << 14) | (1 << 13) | ((imm) & 0x1FFF))
> +#define BA_INST(tgt) (0x10800000 | ((tgt) & 0x3FFFFF))
>
> +// Emit instructions to jump to Addr and store the starting address of
> +// the instructions emitted in the scratch register.
> +static void emitInstrForIndirectJump(intptr_t Addr,
> + unsigned scratch,
> + SmallVectorImpl<uint32_t> &Insts) {
> +
> + if (isInt<13>(Addr)) {
> + // Emit: jmpl %g0+Addr, <scratch>
> + // nop
> + Insts.push_back(JMP_INST(0, LO10(Addr), scratch));
> + Insts.push_back(NOP_INST);
> + return;
> + }
> +
> + if (isUInt<32>(Addr)) {
> + // Emit: sethi %hi(Addr), scratch
> + // jmpl scratch+%lo(Addr), scratch
> + // sub scratch, 4, scratch
> + Insts.push_back(SETHI_INST(HI22(Addr), scratch));
> + Insts.push_back(JMP_INST(scratch, LO10(Addr), scratch));
> + Insts.push_back(SUB_INST(scratch, 4, scratch));
> + return;
> + }
> +
> + if (Addr < 0 && isInt<33>(Addr)) {
> + // Emit: sethi %hix(Addr), scratch)
> + // xor scratch, %lox(Addr), scratch
> + // jmpl scratch+0, scratch
> + // sub scratch, 8, scratch
> + Insts.push_back(SETHI_INST(HIX22(Addr), scratch));
> + Insts.push_back(XOR_INST(scratch, LOX10(Addr), scratch));
> + Insts.push_back(JMP_INST(scratch, 0, scratch));
> + Insts.push_back(SUB_INST(scratch, 8, scratch));
> + return;
> + }
> +
> + // Emit: rd %pc, scratch
> + // ldx [scratch+16], scratch
> + // jmpl scratch+0, scratch
> + // sub scratch, 8, scratch
> + // <Addr: 8 byte>
> + Insts.push_back(RDPC_INST(scratch));
> + Insts.push_back(LDX_INST(scratch, 16, scratch));
> + Insts.push_back(JMP_INST(scratch, 0, scratch));
> + Insts.push_back(SUB_INST(scratch, 8, scratch));
> + Insts.push_back((uint32_t)(((int64_t)Addr) >> 32) & 0xffffffff);
> + Insts.push_back((uint32_t)(Addr & 0xffffffff));
> +
> + // Instruction sequence without rdpc instruction
> + // 7 instruction and 2 scratch register
> + // Emit: sethi %hh(Addr), scratch
> + // or scratch, %hm(Addr), scratch
> + // sllx scratch, 32, scratch
> + // sethi %hi(Addr), scratch2
> + // or scratch, scratch2, scratch
> + // jmpl scratch+%lo(Addr), scratch
> + // sub scratch, 20, scratch
> + // Insts.push_back(SETHI_INST(HH22(Addr), scratch));
> + // Insts.push_back(OR_INST_I(scratch, HM10(Addr), scratch));
> + // Insts.push_back(SLLX_INST(scratch, 32, scratch));
> + // Insts.push_back(SETHI_INST(HI22(Addr), scratch2));
> + // Insts.push_back(OR_INST_R(scratch, scratch2, scratch));
> + // Insts.push_back(JMP_INST(scratch, LO10(Addr), scratch));
> + // Insts.push_back(SUB_INST(scratch, 20, scratch));
> +}
> +
> extern "C" void *SparcCompilationCallbackC(intptr_t StubAddr) {
> // Get the address of the compiled code for this function.
> intptr_t NewVal = (intptr_t) JITCompilerFunction((void*) StubAddr);
>
> // Rewrite the function stub so that we don't end up here every time we
> - // execute the call. We're replacing the first three instructions of the
> - // stub with code that jumps to the compiled function:
> - // sethi %hi(NewVal), %g1
> - // jmp %g1+%lo(NewVal)
> - // nop
> + // execute the call. We're replacing the stub instructions with code
> + // that jumps to the compiled function:
>
> - *(intptr_t *)(StubAddr) = SETHI_INST(HI(NewVal), 1);
> - *(intptr_t *)(StubAddr + 4) = JMP_INST(1, LO(NewVal), 0);
> - *(intptr_t *)(StubAddr + 8) = NOP_INST;
> + SmallVector<uint32_t, 8> Insts;
> + intptr_t diff = (NewVal - StubAddr) >> 2;
> + if (isInt<22>(diff)) {
> + // Use branch instruction to jump
> + Insts.push_back(BA_INST(diff));
> + Insts.push_back(NOP_INST);
> + } else {
> + // Otherwise, use indirect jump to the compiled function
> + emitInstrForIndirectJump(NewVal, 1, Insts);
> + }
>
> - sys::Memory::InvalidateInstructionCache((void*) StubAddr, 12);
> + for (unsigned i = 0, e = Insts.size(); i != e; ++i)
> + *(uint32_t *)(StubAddr + i*4) = Insts[i];
> +
> + sys::Memory::InvalidateInstructionCache((void*) StubAddr, Insts.size() * 4);
> return (void*)StubAddr;
> }
>
> +
> void SparcJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
> assert(0 && "FIXME: Implement SparcJITInfo::replaceMachineCodeForFunction");
> }
> @@ -88,10 +217,10 @@
>
>
> TargetJITInfo::StubLayout SparcJITInfo::getStubLayout() {
> - // The stub contains 3 4-byte instructions, aligned at 4 bytes. See
> - // emitFunctionStub for details.
> -
> - StubLayout Result = { 3*4, 4 };
> + // The stub contains maximum of 4 4-byte instructions and 8 bytes for address,
> + // aligned at 32 bytes.
> + // See emitFunctionStub and emitInstrForIndirectJump for details.
> + StubLayout Result = { 4*4 + 8, 32 };
> return Result;
> }
>
> @@ -98,32 +227,41 @@
> void *SparcJITInfo::emitFunctionStub(const Function *F, void *Fn,
> JITCodeEmitter &JCE)
> {
> - JCE.emitAlignment(4);
> + JCE.emitAlignment(32);
> void *Addr = (void*) (JCE.getCurrentPCValue());
> - if (!sys::Memory::setRangeWritable(Addr, 12))
> - llvm_unreachable("ERROR: Unable to mark stub writable.");
>
> + intptr_t CurrentAddr = (intptr_t)Addr;
> intptr_t EmittedAddr;
> - if (Fn != (void*)(intptr_t)SparcCompilationCallback)
> + SmallVector<uint32_t, 8> Insts;
> + if (Fn != (void*)(intptr_t)SparcCompilationCallback) {
> EmittedAddr = (intptr_t)Fn;
> - else
> + intptr_t diff = (EmittedAddr - CurrentAddr) >> 2;
> + if (isInt<22>(diff)) {
> + Insts.push_back(BA_INST(diff));
> + Insts.push_back(NOP_INST);
> + }
> + } else {
> EmittedAddr = (intptr_t)SparcCompilationCallback;
> + }
>
> - // sethi %hi(EmittedAddr), %g1
> - // jmp %g1+%lo(EmittedAddr), %g1
> - // nop
> + if (Insts.size() == 0)
> + emitInstrForIndirectJump(EmittedAddr, 1, Insts);
>
> - JCE.emitWordBE(SETHI_INST(HI(EmittedAddr), 1));
> - JCE.emitWordBE(JMP_INST(1, LO(EmittedAddr), 1));
> - JCE.emitWordBE(NOP_INST);
>
> - sys::Memory::InvalidateInstructionCache(Addr, 12);
> - if (!sys::Memory::setRangeExecutable(Addr, 12))
> + if (!sys::Memory::setRangeWritable(Addr, 4 * Insts.size()))
> + llvm_unreachable("ERROR: Unable to mark stub writable.");
> +
> + for (unsigned i = 0, e = Insts.size(); i != e; ++i)
> + JCE.emitWordBE(Insts[i]);
> +
> + sys::Memory::InvalidateInstructionCache(Addr, 4 * Insts.size());
> + if (!sys::Memory::setRangeExecutable(Addr, 4 * Insts.size()))
> llvm_unreachable("ERROR: Unable to mark stub executable.");
>
> return Addr;
> }
>
> +
> TargetJITInfo::LazyResolverFn
> SparcJITInfo::getLazyResolverFunction(JITCompilerFn F) {
> JITCompilerFunction = F;
> @@ -159,6 +297,27 @@
> case SP::reloc_sparc_pc19:
> ResultPtr = ((ResultPtr - (intptr_t)RelocPos) >> 2) & 0x7ffff;
> break;
> +
> + case SP::reloc_sparc_h44:
> + ResultPtr = (ResultPtr >> 22) & 0x3fffff;
> + break;
> +
> + case SP::reloc_sparc_m44:
> + ResultPtr = (ResultPtr >> 12) & 0x3ff;
> + break;
> +
> + case SP::reloc_sparc_l44:
> + ResultPtr = (ResultPtr & 0xfff);
> + break;
> +
> + case SP::reloc_sparc_hh:
> + ResultPtr = (((int64_t)ResultPtr) >> 42) & 0x3fffff;
> + break;
> +
> + case SP::reloc_sparc_hm:
> + ResultPtr = (((int64_t)ResultPtr) >> 32) & 0x3ff;
> + break;
> +
> }
> *((unsigned*) RelocPos) |= (unsigned) ResultPtr;
> }
> Index: lib/Target/Sparc/SparcMCInstLower.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcMCInstLower.cpp (revision 0)
> +++ lib/Target/Sparc/SparcMCInstLower.cpp (working copy)
> @@ -0,0 +1,109 @@
> +//===-- SparcMCInstLower.cpp - Convert Sparc MachineInstr to MCInst -------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file contains code to lower Sparc MachineInstrs to their corresponding
> +// MCInst records.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "Sparc.h"
> +#include "MCTargetDesc/SparcMCExpr.h"
> +#include "llvm/CodeGen/AsmPrinter.h"
> +#include "llvm/CodeGen/MachineFunction.h"
> +#include "llvm/CodeGen/MachineInstr.h"
> +#include "llvm/CodeGen/MachineOperand.h"
> +#include "llvm/MC/MCContext.h"
> +#include "llvm/MC/MCAsmInfo.h"
> +#include "llvm/MC/MCExpr.h"
> +#include "llvm/MC/MCInst.h"
> +#include "llvm/Target/Mangler.h"
> +#include "llvm/ADT/SmallString.h"
> +
> +using namespace llvm;
> +
> +
> +static MCOperand LowerSymbolOperand(const MachineInstr *MI,
> + const MachineOperand &MO,
> + AsmPrinter &AP) {
> +
> + SparcMCExpr::VariantKind Kind =
> + (SparcMCExpr::VariantKind)MO.getTargetFlags();
> + const MCSymbol *Symbol = 0;
> +
> + switch(MO.getType()) {
> + default: llvm_unreachable("Unknown type in LowerSymbolOperand");
> + case MachineOperand::MO_MachineBasicBlock:
> + Symbol = MO.getMBB()->getSymbol();
> + break;
> +
> + case MachineOperand::MO_GlobalAddress:
> + Symbol = AP.getSymbol(MO.getGlobal());
> + break;
> +
> + case MachineOperand::MO_BlockAddress:
> + Symbol = AP.GetBlockAddressSymbol(MO.getBlockAddress());
> + break;
> +
> + case MachineOperand::MO_ExternalSymbol:
> + Symbol = AP.GetExternalSymbolSymbol(MO.getSymbolName());
> + break;
> +
> + case MachineOperand::MO_ConstantPoolIndex:
> + Symbol = AP.GetCPISymbol(MO.getIndex());
> + break;
> + }
> +
> + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol,
> + AP.OutContext);
> + const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym,
> + AP.OutContext);
> + return MCOperand::CreateExpr(expr);
> +}
> +
> +static MCOperand LowerOperand(const MachineInstr *MI,
> + const MachineOperand &MO,
> + AsmPrinter &AP) {
> + switch(MO.getType()) {
> + default: llvm_unreachable("unknown operand type"); break;
> + case MachineOperand::MO_Register:
> + if (MO.isImplicit())
> + break;
> + return MCOperand::CreateReg(MO.getReg());
> +
> + case MachineOperand::MO_Immediate:
> + return MCOperand::CreateImm(MO.getImm());
> +
> + case MachineOperand::MO_MachineBasicBlock:
> + case MachineOperand::MO_GlobalAddress:
> + case MachineOperand::MO_BlockAddress:
> + case MachineOperand::MO_ExternalSymbol:
> + case MachineOperand::MO_ConstantPoolIndex:
> + return LowerSymbolOperand(MI, MO, AP);
> +
> + case MachineOperand::MO_RegisterMask: break;
> +
> + }
> + return MCOperand();
> +}
> +
> +void llvm::LowerSparcMachineInstrToMCInst(const MachineInstr *MI,
> + MCInst &OutMI,
> + AsmPrinter &AP)
> +{
> +
> + OutMI.setOpcode(MI->getOpcode());
> +
> + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
> + const MachineOperand &MO = MI->getOperand(i);
> + MCOperand MCOp = LowerOperand(MI, MO, AP);
> +
> + if (MCOp.isValid())
> + OutMI.addOperand(MCOp);
> + }
> +}
> Index: lib/Target/Sparc/SparcRegisterInfo.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcRegisterInfo.cpp (revision 201091)
> +++ lib/Target/Sparc/SparcRegisterInfo.cpp (working copy)
> @@ -35,7 +35,7 @@
> cl::desc("Reserve application registers (%g2-%g4)"));
>
> SparcRegisterInfo::SparcRegisterInfo(SparcSubtarget &st)
> - : SparcGenRegisterInfo(SP::I7), Subtarget(st) {
> + : SparcGenRegisterInfo(SP::O7), Subtarget(st) {
> }
>
> const uint16_t* SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
> Index: lib/Target/Sparc/SparcRelocations.h
> ===================================================================
> --- lib/Target/Sparc/SparcRelocations.h (revision 201091)
> +++ lib/Target/Sparc/SparcRelocations.h (working copy)
> @@ -33,7 +33,22 @@
> reloc_sparc_pc22 = 4,
>
> // reloc_sparc_pc22 - pc rel. 19 bits for branch with icc/xcc
> - reloc_sparc_pc19 = 5
> + reloc_sparc_pc19 = 5,
> +
> + // reloc_sparc_h44 - 43-22 bits
> + reloc_sparc_h44 = 6,
> +
> + // reloc_sparc_m44 - 21-12 bits
> + reloc_sparc_m44 = 7,
> +
> + // reloc_sparc_l44 - lower 12 bits
> + reloc_sparc_l44 = 8,
> +
> + // reloc_sparc_hh - 63-42 bits
> + reloc_sparc_hh = 9,
> +
> + // reloc_sparc_hm - 41-32 bits
> + reloc_sparc_hm = 10
> };
> }
> }
> Index: lib/Target/Sparc/SparcSubtarget.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcSubtarget.cpp (revision 201091)
> +++ lib/Target/Sparc/SparcSubtarget.cpp (working copy)
> @@ -31,20 +31,20 @@
> V8DeprecatedInsts(false),
> IsVIS(false),
> Is64Bit(is64Bit),
> - HasHardQuad(false) {
> + HasHardQuad(false),
> + UsePopc(false) {
>
> // Determine default and user specified characteristics
> std::string CPUName = CPU;
> - if (CPUName.empty()) {
> - if (is64Bit)
> - CPUName = "v9";
> - else
> - CPUName = "v8";
> - }
> - IsV9 = CPUName == "v9";
> + if (CPUName.empty())
> + CPUName = (is64Bit) ? "v9" : "v8";
>
> // Parse features string.
> ParseSubtargetFeatures(CPUName, FS);
> +
> + // Popc is a v9-only instruction.
> + if (!IsV9)
> + UsePopc = false;
> }
>
>
> Index: lib/Target/Sparc/SparcSubtarget.h
> ===================================================================
> --- lib/Target/Sparc/SparcSubtarget.h (revision 201091)
> +++ lib/Target/Sparc/SparcSubtarget.h (working copy)
> @@ -30,6 +30,7 @@
> bool IsVIS;
> bool Is64Bit;
> bool HasHardQuad;
> + bool UsePopc;
>
> public:
> SparcSubtarget(const std::string &TT, const std::string &CPU,
> @@ -39,6 +40,7 @@
> bool isVIS() const { return IsVIS; }
> bool useDeprecatedV8Instructions() const { return V8DeprecatedInsts; }
> bool hasHardQuad() const { return HasHardQuad; }
> + bool usePopc() const { return UsePopc; }
>
> /// ParseSubtargetFeatures - Parses features string setting specified
> /// subtarget options. Definition of function is auto generated by tblgen.
> Index: lib/Target/Sparc/SparcTargetObjectFile.cpp
> ===================================================================
> --- lib/Target/Sparc/SparcTargetObjectFile.cpp (revision 0)
> +++ lib/Target/Sparc/SparcTargetObjectFile.cpp (working copy)
> @@ -0,0 +1,48 @@
> +//===------- SparcTargetObjectFile.cpp - Sparc Object Info Impl -----------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "SparcTargetObjectFile.h"
> +#include "MCTargetDesc/SparcMCExpr.h"
> +#include "llvm/CodeGen/MachineModuleInfoImpls.h"
> +#include "llvm/Support/Dwarf.h"
> +#include "llvm/Target/Mangler.h"
> +
> +using namespace llvm;
> +
> +
> +const MCExpr *SparcELFTargetObjectFile::
> +getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang,
> + MachineModuleInfo *MMI, unsigned Encoding,
> + MCStreamer &Streamer) const {
> +
> + if (Encoding & dwarf::DW_EH_PE_pcrel) {
> + MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo<MachineModuleInfoELF>();
> +
> + //MCSymbol *SSym = getSymbolWithGlobalValueBase(*Mang, GV, ".DW.stub");
> + SmallString<60> NameStr;
> + Mang->getNameWithPrefix(NameStr, GV, true);
> + NameStr.append(".DW.stub");
> + MCSymbol *SSym = getContext().GetOrCreateSymbol(NameStr.str());
> +
> + // Add information about the stub reference to ELFMMI so that the stub
> + // gets emitted by the asmprinter.
> + MachineModuleInfoImpl::StubValueTy &StubSym = ELFMMI.getGVStubEntry(SSym);
> + if (StubSym.getPointer() == 0) {
> + MCSymbol *Sym = getSymbol(*Mang, GV);
> + StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
> + }
> +
> + MCContext &Ctx = getContext();
> + return SparcMCExpr::Create(SparcMCExpr::VK_Sparc_R_DISP32,
> + MCSymbolRefExpr::Create(SSym, Ctx), Ctx);
> + }
> +
> + return TargetLoweringObjectFileELF::
> + getTTypeGlobalReference(GV, Mang, MMI, Encoding, Streamer);
> +}
> Index: lib/Target/Sparc/SparcTargetObjectFile.h
> ===================================================================
> --- lib/Target/Sparc/SparcTargetObjectFile.h (revision 0)
> +++ lib/Target/Sparc/SparcTargetObjectFile.h (working copy)
> @@ -0,0 +1,34 @@
> +//===-- SparcTargetObjectFile.h - Sparc Object Info -------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_TARGET_SPARC_TARGETOBJECTFILE_H
> +#define LLVM_TARGET_SPARC_TARGETOBJECTFILE_H
> +
> +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
> +
> +namespace llvm {
> +
> +class MCContext;
> +class TargetMachine;
> +
> +class SparcELFTargetObjectFile : public TargetLoweringObjectFileELF {
> +public:
> + SparcELFTargetObjectFile() :
> + TargetLoweringObjectFileELF()
> + {}
> +
> + const MCExpr *
> + getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang,
> + MachineModuleInfo *MMI, unsigned Encoding,
> + MCStreamer &Streamer) const;
> +};
> +
> +} // end namespace llvm
> +
> +#endif
> Index: lib/Target/Sparc/SparcTargetStreamer.h
> ===================================================================
> --- lib/Target/Sparc/SparcTargetStreamer.h (revision 0)
> +++ lib/Target/Sparc/SparcTargetStreamer.h (working copy)
> @@ -0,0 +1,47 @@
> +//===-- SparcTargetStreamer.h - Sparc Target Streamer ----------*- C++ -*--===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef SPARCTARGETSTREAMER_H
> +#define SPARCTARGETSTREAMER_H
> +
> +#include "llvm/MC/MCELFStreamer.h"
> +#include "llvm/MC/MCStreamer.h"
> +
> +namespace llvm {
> +class SparcTargetStreamer : public MCTargetStreamer {
> + virtual void anchor();
> +
> +public:
> + /// Emit ".register <reg>, #ignore".
> + virtual void emitSparcRegisterIgnore(unsigned reg) = 0;
> + /// Emit ".register <reg>, #scratch".
> + virtual void emitSparcRegisterScratch(unsigned reg) = 0;
> +};
> +
> +// This part is for ascii assembly output
> +class SparcTargetAsmStreamer : public SparcTargetStreamer {
> + formatted_raw_ostream &OS;
> +
> +public:
> + SparcTargetAsmStreamer(formatted_raw_ostream &OS);
> + virtual void emitSparcRegisterIgnore(unsigned reg);
> + virtual void emitSparcRegisterScratch(unsigned reg);
> +
> +};
> +
> +// This part is for ELF object output
> +class SparcTargetELFStreamer : public SparcTargetStreamer {
> +public:
> + MCELFStreamer &getStreamer();
> + virtual void emitSparcRegisterIgnore(unsigned reg) {}
> + virtual void emitSparcRegisterScratch(unsigned reg) {}
> +};
> +} // end namespace llvm
> +
> +#endif
> Index: test/CodeGen/SPARC/2009-08-28-PIC.ll
> ===================================================================
> --- test/CodeGen/SPARC/2009-08-28-PIC.ll (revision 201091)
> +++ test/CodeGen/SPARC/2009-08-28-PIC.ll (working copy)
> @@ -1,9 +1,45 @@
> -; RUN: llc -march=sparc --relocation-model=pic < %s | grep _GLOBAL_OFFSET_TABLE_
> +; RUN: llc -march=sparc --relocation-model=pic < %s | FileCheck %s --check-prefix=V8
> +; RUN: llc -march=sparcv9 --relocation-model=pic < %s | FileCheck %s --check-prefix=V9
> +; RUN: llc -march=sparc --relocation-model=pic < %s -O0 | FileCheck %s --check-prefix=V8UNOPT
> +; RUN: llc -march=sparcv9 --relocation-model=pic < %s -O0 | FileCheck %s --check-prefix=V9UNOPT
>
> +
> +; V8-LABEL: func
> +; V8: _GLOBAL_OFFSET_TABLE_
> +
> +; V9-LABEL: func
> +; V9: _GLOBAL_OFFSET_TABLE_
> +
> @foo = global i32 0 ; <i32*> [#uses=1]
>
> -define i32 @func() nounwind readonly {
> +define i32 @func(i32 %a) nounwind readonly {
> entry:
> %0 = load i32* @foo, align 4 ; <i32> [#uses=1]
> ret i32 %0
> }
> +
> +; V8UNOPT-LABEL: test_spill
> +; V8UNOPT: sethi %hi(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R:%[goli][0-7]]]
> +; V8UNOPT: or [[R]], %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R]]
> +; V8UNOPT: add [[R]], %o7, [[R]]
> +; V8UNOPT: st [[R]], [%fp+{{.+}}]
> +
> +; V9UNOPT-LABEL: test_spill
> +; V9UNOPT: sethi %hi(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R:%[goli][0-7]]]
> +; V9UNOPT: or [[R]], %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R]]
> +; V9UNOPT: add [[R]], %o7, [[R]]
> +; V9UNOPT: stx [[R]], [%fp+{{.+}}]
> +
> +define i32 @test_spill(i32 %a, i32 %b) {
> +entry:
> + %cmp = icmp eq i32 %b, 0
> + br i1 %cmp, label %if.then, label %if.end
> +
> +if.then:
> + %ret = load i32* @foo, align 4
> + ret i32 %ret
> +
> +if.end:
> + %add = add nsw i32 %b, %a
> + ret i32 %add
> +}
> Index: test/CodeGen/SPARC/2011-01-11-Call.ll
> ===================================================================
> --- test/CodeGen/SPARC/2011-01-11-Call.ll (revision 201091)
> +++ test/CodeGen/SPARC/2011-01-11-Call.ll (working copy)
> @@ -8,7 +8,7 @@
> ; V8-NEXT: nop
> ; V8: call bar
> ; V8-NEXT: nop
> -; V8: jmp %i7+8
> +; V8: ret
> ; V8-NEXT: restore
>
> ; V9-LABEL: test
> @@ -17,7 +17,7 @@
> ; V9-NEXT: nop
> ; V9: call bar
> ; V9-NEXT: nop
> -; V9: jmp %i7+8
> +; V9: ret
> ; V9-NEXT: restore
>
> define void @test() nounwind {
> @@ -36,7 +36,7 @@
> ; V8: save %sp
> ; V8: call foo
> ; V8-NEXT: nop
> -; V8: jmp %i7+8
> +; V8: ret
> ; V8-NEXT: restore %g0, %o0, %o0
>
> ; V9-LABEL: test_tail_call_with_return
> @@ -43,7 +43,7 @@
> ; V9: save %sp
> ; V9: call foo
> ; V9-NEXT: nop
> -; V9: jmp %i7+8
> +; V9: ret
> ; V9-NEXT: restore %g0, %o0, %o0
>
> define i32 @test_tail_call_with_return() nounwind {
> Index: test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
> ===================================================================
> --- test/CodeGen/SPARC/2011-01-11-FrameAddr.ll (revision 201091)
> +++ test/CodeGen/SPARC/2011-01-11-FrameAddr.ll (working copy)
> @@ -2,6 +2,7 @@
> ;RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9
> ;RUN: llc -march=sparc -regalloc=basic < %s | FileCheck %s -check-prefix=V8
> ;RUN: llc -march=sparc -regalloc=basic -mattr=v9 < %s | FileCheck %s -check-prefix=V9
> +;RUN: llc -march=sparcv9 < %s | FileCheck %s -check-prefix=SPARC64
>
>
> define i8* @frameaddr() nounwind readnone {
> @@ -8,13 +9,20 @@
> entry:
> ;V8-LABEL: frameaddr:
> ;V8: save %sp, -96, %sp
> -;V8: jmp %i7+8
> +;V8: ret
> ;V8: restore %g0, %fp, %o0
>
> ;V9-LABEL: frameaddr:
> ;V9: save %sp, -96, %sp
> -;V9: jmp %i7+8
> +;V9: ret
> ;V9: restore %g0, %fp, %o0
> +
> +;SPARC64-LABEL: frameaddr
> +;SPARC64: save %sp, -128, %sp
> +;SPARC64: add %fp, 2047, %i0
> +;SPARC64: ret
> +;SPARC64: restore %g0, %g0, %g0
> +
> %0 = tail call i8* @llvm.frameaddress(i32 0)
> ret i8* %0
> }
> @@ -32,6 +40,14 @@
> ;V9: ld [%fp+56], {{.+}}
> ;V9: ld [{{.+}}+56], {{.+}}
> ;V9: ld [{{.+}}+56], {{.+}}
> +
> +;SPARC64-LABEL: frameaddr2
> +;SPARC64: flushw
> +;SPARC64: ldx [%fp+2159], %[[R0:[goli][0-7]]]
> +;SPARC64: ldx [%[[R0]]+2159], %[[R1:[goli][0-7]]]
> +;SPARC64: ldx [%[[R1]]+2159], %[[R2:[goli][0-7]]]
> +;SPARC64: add %[[R2]], 2047, {{.+}}
> +
> %0 = tail call i8* @llvm.frameaddress(i32 3)
> ret i8* %0
> }
> @@ -48,6 +64,9 @@
> ;V9-LABEL: retaddr:
> ;V9: or %g0, %o7, {{.+}}
>
> +;SPARC64-LABEL: retaddr
> +;SPARC64: or %g0, %o7, {{.+}}
> +
> %0 = tail call i8* @llvm.returnaddress(i32 0)
> ret i8* %0
> }
> @@ -66,18 +85,12 @@
> ;V9: ld [{{.+}}+56], {{.+}}
> ;V9: ld [{{.+}}+60], {{.+}}
>
> -;V8LEAF-LABEL: retaddr2:
> -;V8LEAF: ta 3
> -;V8LEAF: ld [%fp+56], %[[R:[goli][0-7]]]
> -;V8LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]]
> -;V8LEAF: ld [%[[R1]]+60], {{.+}}
> +;SPARC64-LABEL: retaddr2
> +;SPARC64: flushw
> +;SPARC64: ldx [%fp+2159], %[[R0:[goli][0-7]]]
> +;SPARC64: ldx [%[[R0]]+2159], %[[R1:[goli][0-7]]]
> +;SPARC64: ldx [%[[R1]]+2167], {{.+}}
>
> -;V9LEAF-LABEL: retaddr2:
> -;V9LEAF: flushw
> -;V9LEAF: ld [%fp+56], %[[R:[goli][0-7]]]
> -;V9LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]]
> -;V9LEAF: ld [%[[R1]]+60], {{.+}}
> -
> %0 = tail call i8* @llvm.returnaddress(i32 3)
> ret i8* %0
> }
> Index: test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
> ===================================================================
> --- test/CodeGen/SPARC/2011-01-19-DelaySlot.ll (revision 201091)
> +++ test/CodeGen/SPARC/2011-01-19-DelaySlot.ll (working copy)
> @@ -1,5 +1,5 @@
> -;RUN: llc -march=sparc < %s | FileCheck %s
> -;RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=UNOPT
> +;RUN: llc -march=sparc < %s -verify-machineinstrs | FileCheck %s
> +;RUN: llc -march=sparc -O0 < %s -verify-machineinstrs | FileCheck %s -check-prefix=UNOPT
>
>
> define i32 @test(i32 %a) nounwind {
> @@ -7,7 +7,7 @@
> ; CHECK: test
> ; CHECK: call bar
> ; CHECK-NOT: nop
> -; CHECK: jmp
> +; CHECK: ret
> ; CHECK-NEXT: restore
> %0 = tail call i32 @bar(i32 %a) nounwind
> ret i32 %0
> @@ -18,7 +18,7 @@
> ; CHECK: test_jmpl
> ; CHECK: call
> ; CHECK-NOT: nop
> -; CHECK: jmp
> +; CHECK: ret
> ; CHECK-NEXT: restore
> %0 = tail call i32 %f(i32 %a, i32 %b) nounwind
> ret i32 %0
> @@ -47,7 +47,7 @@
>
> bb5: ; preds = %bb, %entry
> %a_addr.1.lcssa = phi i32 [ %a, %entry ], [ %a_addr.0, %bb ]
> -;CHECK: jmp
> +;CHECK: retl
> ;CHECK-NOT: restore
> ret i32 %a_addr.1.lcssa
> }
> @@ -110,7 +110,7 @@
> define i32 @restore_add(i32 %a, i32 %b) {
> entry:
> ;CHECK-LABEL: restore_add:
> -;CHECK: jmp %i7+8
> +;CHECK: ret
> ;CHECK: restore %o0, %i1, %o0
> %0 = tail call i32 @bar(i32 %a) nounwind
> %1 = add nsw i32 %0, %b
> @@ -120,7 +120,7 @@
> define i32 @restore_add_imm(i32 %a) {
> entry:
> ;CHECK-LABEL: restore_add_imm:
> -;CHECK: jmp %i7+8
> +;CHECK: ret
> ;CHECK: restore %o0, 20, %o0
> %0 = tail call i32 @bar(i32 %a) nounwind
> %1 = add nsw i32 %0, 20
> @@ -130,7 +130,7 @@
> define i32 @restore_or(i32 %a) {
> entry:
> ;CHECK-LABEL: restore_or:
> -;CHECK: jmp %i7+8
> +;CHECK: ret
> ;CHECK: restore %g0, %o0, %o0
> %0 = tail call i32 @bar(i32 %a) nounwind
> ret i32 %0
> @@ -140,7 +140,7 @@
> entry:
> ;CHECK-LABEL: restore_or_imm:
> ;CHECK: or %o0, 20, %i0
> -;CHECK: jmp %i7+8
> +;CHECK: ret
> ;CHECK: restore %g0, %g0, %g0
> %0 = tail call i32 @bar(i32 %a) nounwind
> %1 = or i32 %0, 20
> Index: test/CodeGen/SPARC/64abi.ll
> ===================================================================
> --- test/CodeGen/SPARC/64abi.ll (revision 201091)
> +++ test/CodeGen/SPARC/64abi.ll (working copy)
> @@ -180,7 +180,7 @@
> }
>
> ; CHECK: inreg_ff
> -; CHECK: fsubs %f0, %f1, %f1
> +; CHECK: fsubs %f0, %f1, %f0
> define float @inreg_ff(float inreg %a0, ; %f0
> float inreg %a1) { ; %f1
> %rv = fsub float %a0, %a1
> @@ -262,10 +262,10 @@
> ret void
> }
>
> -; This is not a C struct, each member uses 8 bytes.
> +; This is not a C struct, the i32 member uses 8 bytes, but the float only 4.
> ; CHECK: ret_i32_float_pair
> ; CHECK: ld [%i2], %i0
> -; CHECK: ld [%i3], %f3
> +; CHECK: ld [%i3], %f2
> define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1,
> i32* %p, float* %q) {
> %r1 = load i32* %p
> @@ -279,7 +279,7 @@
> ; CHECK: call_ret_i32_float_pair
> ; CHECK: call ret_i32_float_pair
> ; CHECK: st %o0, [%i0]
> -; CHECK: st %f3, [%i1]
> +; CHECK: st %f2, [%i1]
> define void @call_ret_i32_float_pair(i32* %i0, float* %i1) {
> %rv = call { i32, float } @ret_i32_float_pair(i32 undef, i32 undef,
> i32* undef, float* undef)
> @@ -411,3 +411,54 @@
> }
>
> declare i32 @use_buf(i32, i8*)
> +
> +; CHECK-LABEL: test_fp128_args
> +; CHECK-DAG: std %f0, [%fp+{{.+}}]
> +; CHECK-DAG: std %f2, [%fp+{{.+}}]
> +; CHECK-DAG: std %f6, [%fp+{{.+}}]
> +; CHECK-DAG: std %f4, [%fp+{{.+}}]
> +; CHECK: add %fp, [[Offset:[0-9]+]], %o0
> +; CHECK: call _Qp_add
> +; CHECK: ldd [%fp+[[Offset]]], %f0
> +define fp128 @test_fp128_args(fp128 %a, fp128 %b) {
> +entry:
> + %0 = fadd fp128 %a, %b
> + ret fp128 %0
> +}
> +
> +declare i64 @receive_fp128(i64 %a, ...)
> +
> +; CHECK-LABEL: test_fp128_variable_args
> +; CHECK-DAG: std %f4, [%sp+[[Offset0:[0-9]+]]]
> +; CHECK-DAG: std %f6, [%sp+[[Offset1:[0-9]+]]]
> +; CHECK-DAG: ldx [%sp+[[Offset0]]], %o2
> +; CHECK-DAG: ldx [%sp+[[Offset1]]], %o3
> +; CHECK: call receive_fp128
> +define i64 @test_fp128_variable_args(i64 %a, fp128 %b) {
> +entry:
> + %0 = call i64 (i64, ...)* @receive_fp128(i64 %a, fp128 %b)
> + ret i64 %0
> +}
> +
> +; CHECK-LABEL: test_call_libfunc
> +; CHECK: st %f1, [%fp+[[Offset0:[0-9]+]]]
> +; CHECK: fmovs %f3, %f1
> +; CHECK: call cosf
> +; CHECK: st %f0, [%fp+[[Offset1:[0-9]+]]]
> +; CHECK: ld [%fp+[[Offset0]]], %f1
> +; CHECK: call sinf
> +; CHECK: ld [%fp+[[Offset1]]], %f1
> +; CHECK: fmuls %f1, %f0, %f0
> +
> +define inreg float @test_call_libfunc(float %arg0, float %arg1) {
> +entry:
> + %0 = tail call inreg float @cosf(float %arg1)
> + %1 = tail call inreg float @sinf(float %arg0)
> + %2 = fmul float %0, %1
> + ret float %2
> +}
> +
> +declare inreg float @cosf(float %arg) readnone nounwind
> +declare inreg float @sinf(float %arg) readnone nounwind
> +
> +
> Index: test/CodeGen/SPARC/64bit.ll
> ===================================================================
> --- test/CodeGen/SPARC/64bit.ll (revision 201091)
> +++ test/CodeGen/SPARC/64bit.ll (working copy)
> @@ -1,11 +1,11 @@
> -; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s
> -; RUN: llc < %s -march=sparcv9 | FileCheck %s -check-prefix=OPT
> +; RUN: llc < %s -march=sparcv9 -mattr=+popc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s
> +; RUN: llc < %s -march=sparcv9 -mattr=+popc | FileCheck %s -check-prefix=OPT
>
> ; CHECK-LABEL: ret2:
> ; CHECK: or %g0, %i1, %i0
>
> ; OPT-LABEL: ret2:
> -; OPT: jmp %o7+8
> +; OPT: retl
> ; OPT: or %g0, %o1, %o0
> define i64 @ret2(i64 %a, i64 %b) {
> ret i64 %b
> @@ -15,7 +15,7 @@
> ; CHECK: sllx %i0, 7, %i0
>
> ; OPT-LABEL: shl_imm:
> -; OPT: jmp %o7+8
> +; OPT: retl
> ; OPT: sllx %o0, 7, %o0
> define i64 @shl_imm(i64 %a) {
> %x = shl i64 %a, 7
> @@ -26,7 +26,7 @@
> ; CHECK: srax %i0, %i1, %i0
>
> ; OPT-LABEL: sra_reg:
> -; OPT: jmp %o7+8
> +; OPT: retl
> ; OPT: srax %o0, %o1, %o0
> define i64 @sra_reg(i64 %a, i64 %b) {
> %x = ashr i64 %a, %b
> @@ -42,7 +42,7 @@
> ; CHECK: or %g0, 0, %i0
>
> ; OPT: ret_imm0
> -; OPT: jmp %o7+8
> +; OPT: retl
> ; OPT: or %g0, 0, %o0
> define i64 @ret_imm0() {
> ret i64 0
> @@ -52,7 +52,7 @@
> ; CHECK: or %g0, -4096, %i0
>
> ; OPT: ret_simm13
> -; OPT: jmp %o7+8
> +; OPT: retl
> ; OPT: or %g0, -4096, %o0
> define i64 @ret_simm13() {
> ret i64 -4096
> @@ -64,7 +64,7 @@
> ; CHECK: restore
>
> ; OPT: ret_sethi
> -; OPT: jmp %o7+8
> +; OPT: retl
> ; OPT: sethi 4, %o0
> define i64 @ret_sethi() {
> ret i64 4096
> @@ -76,7 +76,7 @@
>
> ; OPT: ret_sethi_or
> ; OPT: sethi 4, [[R:%[go][0-7]]]
> -; OPT: jmp %o7+8
> +; OPT: retl
> ; OPT: or [[R]], 1, %o0
>
> define i64 @ret_sethi_or() {
> @@ -89,7 +89,7 @@
>
> ; OPT: ret_nimm33
> ; OPT: sethi 4, [[R:%[go][0-7]]]
> -; OPT: jmp %o7+8
> +; OPT: retl
> ; OPT: xor [[R]], -4, %o0
>
> define i64 @ret_nimm33() {
> Index: test/CodeGen/SPARC/64cond.ll
> ===================================================================
> --- test/CodeGen/SPARC/64cond.ll (revision 201091)
> +++ test/CodeGen/SPARC/64cond.ll (working copy)
> @@ -80,7 +80,7 @@
> ; CHECK: selectf32_xcc
> ; CHECK: cmp %i0, %i1
> ; CHECK: fmovsg %xcc, %f5, %f7
> -; CHECK: fmovs %f7, %f1
> +; CHECK: fmovs %f7, %f0
> define float @selectf32_xcc(i64 %x, i64 %y, float %a, float %b) {
> entry:
> %tobool = icmp sgt i64 %x, %y
> @@ -111,6 +111,11 @@
> }
>
> ; CHECK-LABEL: setcc_resultty
> +; CHECK-DAG: srax %i0, 63, %o0
> +; CHECK-DAG: or %g0, %i0, %o1
> +; CHECK-DAG: or %g0, 0, %o2
> +; CHECK-DAG: or %g0, 32, %o3
> +; CHECK-DAG: call __multi3
> ; CHECK: cmp
> ; CHECK: movne %xcc, 1, [[R:%[gilo][0-7]]]
> ; CHECK: or [[R]], %i1, %i0
> Index: test/CodeGen/SPARC/64spill.ll
> ===================================================================
> --- test/CodeGen/SPARC/64spill.ll (revision 0)
> +++ test/CodeGen/SPARC/64spill.ll (working copy)
> @@ -0,0 +1,116 @@
> +; RUN: llc < %s -march=sparcv9 | FileCheck %s
> +
> +target datalayout = "E-i64:64-n32:64-S128"
> +target triple = "sparc64-sun-sparc"
> +
> +; CHECK-LABEL: test_and_spill
> +; CHECK: and %i0, %i1, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_and_spill(i64 %a, i64 %b) {
> +entry:
> + %r0 = and i64 %a, %b
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +; CHECK-LABEL: test_or_spill
> +; CHECK: or %i0, %i1, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_or_spill(i64 %a, i64 %b) {
> +entry:
> + %r0 = or i64 %a, %b
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +; CHECK-LABEL: test_xor_spill
> +; CHECK: xor %i0, %i1, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_xor_spill(i64 %a, i64 %b) {
> +entry:
> + %r0 = xor i64 %a, %b
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +
> +; CHECK-LABEL: test_add_spill
> +; CHECK: add %i0, %i1, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_add_spill(i64 %a, i64 %b) {
> +entry:
> + %r0 = add i64 %a, %b
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +; CHECK-LABEL: test_sub_spill
> +; CHECK: sub %i0, %i1, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_sub_spill(i64 %a, i64 %b) {
> +entry:
> + %r0 = sub i64 %a, %b
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +; CHECK-LABEL: test_andi_spill
> +; CHECK: and %i0, 1729, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_andi_spill(i64 %a) {
> +entry:
> + %r0 = and i64 %a, 1729
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +; CHECK-LABEL: test_ori_spill
> +; CHECK: or %i0, 1729, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_ori_spill(i64 %a) {
> +entry:
> + %r0 = or i64 %a, 1729
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +; CHECK-LABEL: test_xori_spill
> +; CHECK: xor %i0, 1729, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_xori_spill(i64 %a) {
> +entry:
> + %r0 = xor i64 %a, 1729
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +; CHECK-LABEL: test_addi_spill
> +; CHECK: add %i0, 1729, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_addi_spill(i64 %a) {
> +entry:
> + %r0 = add i64 %a, 1729
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> +; CHECK-LABEL: test_subi_spill
> +; CHECK: add %i0, -1729, [[R:%[gilo][0-7]]]
> +; CHECK: stx [[R]], [%fp+{{.+}}]
> +; CHECK: ldx [%fp+{{.+}}, %i0
> +define i64 @test_subi_spill(i64 %a) {
> +entry:
> + %r0 = sub i64 %a, 1729
> + %0 = tail call i64 asm sideeffect "#$0 $1", "=r,r,~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6}"(i64 %r0)
> + ret i64 %r0
> +}
> +
> Index: test/CodeGen/SPARC/atomics.ll
> ===================================================================
> --- test/CodeGen/SPARC/atomics.ll (revision 0)
> +++ test/CodeGen/SPARC/atomics.ll (working copy)
> @@ -0,0 +1,144 @@
> +; RUN: llc < %s -march=sparcv9 -verify-machineinstrs | FileCheck %s
> +
> +; CHECK-LABEL: test_atomic_i32
> +; CHECK: ld [%o0]
> +; CHECK: membar
> +; CHECK: ld [%o1]
> +; CHECK: membar
> +; CHECK: membar
> +; CHECK: st {{.+}}, [%o2]
> +define i32 @test_atomic_i32(i32* %ptr1, i32* %ptr2, i32* %ptr3) {
> +entry:
> + %0 = load atomic i32* %ptr1 acquire, align 8
> + %1 = load atomic i32* %ptr2 acquire, align 8
> + %2 = add i32 %0, %1
> + store atomic i32 %2, i32* %ptr3 release, align 8
> + ret i32 %2
> +}
> +
> +; CHECK-LABEL: test_atomic_i64
> +; CHECK: ldx [%o0]
> +; CHECK: membar
> +; CHECK: ldx [%o1]
> +; CHECK: membar
> +; CHECK: membar
> +; CHECK: stx {{.+}}, [%o2]
> +define i64 @test_atomic_i64(i64* %ptr1, i64* %ptr2, i64* %ptr3) {
> +entry:
> + %0 = load atomic i64* %ptr1 acquire, align 8
> + %1 = load atomic i64* %ptr2 acquire, align 8
> + %2 = add i64 %0, %1
> + store atomic i64 %2, i64* %ptr3 release, align 8
> + ret i64 %2
> +}
> +
> +; CHECK-LABEL: test_cmpxchg_i32
> +; CHECK: or %g0, 123, [[R:%[gilo][0-7]]]
> +; CHECK: cas [%o1], %o0, [[R]]
> +
> +define i32 @test_cmpxchg_i32(i32 %a, i32* %ptr) {
> +entry:
> + %b = cmpxchg i32* %ptr, i32 %a, i32 123 monotonic
> + ret i32 %b
> +}
> +
> +; CHECK-LABEL: test_cmpxchg_i64
> +; CHECK: or %g0, 123, [[R:%[gilo][0-7]]]
> +; CHECK: casx [%o1], %o0, [[R]]
> +
> +define i64 @test_cmpxchg_i64(i64 %a, i64* %ptr) {
> +entry:
> + %b = cmpxchg i64* %ptr, i64 %a, i64 123 monotonic
> + ret i64 %b
> +}
> +
> +; CHECK-LABEL: test_swap_i32
> +; CHECK: or %g0, 42, [[R:%[gilo][0-7]]]
> +; CHECK: swap [%o1], [[R]]
> +
> +define i32 @test_swap_i32(i32 %a, i32* %ptr) {
> +entry:
> + %b = atomicrmw xchg i32* %ptr, i32 42 monotonic
> + ret i32 %b
> +}
> +
> +; CHECK-LABEL: test_load_add_32
> +; CHECK: membar
> +; CHECK: add [[V:%[gilo][0-7]]], %o1, [[U:%[gilo][0-7]]]
> +; CHECK: cas [%o0], [[V]], [[U]]
> +; CHECK: membar
> +define zeroext i32 @test_load_add_32(i32* %p, i32 zeroext %v) {
> +entry:
> + %0 = atomicrmw add i32* %p, i32 %v seq_cst
> + ret i32 %0
> +}
> +
> +; CHECK-LABEL: test_load_sub_64
> +; CHECK: membar
> +; CHECK: sub
> +; CHECK: casx [%o0]
> +; CHECK: membar
> +define zeroext i64 @test_load_sub_64(i64* %p, i64 zeroext %v) {
> +entry:
> + %0 = atomicrmw sub i64* %p, i64 %v seq_cst
> + ret i64 %0
> +}
> +
> +; CHECK-LABEL: test_load_xor_32
> +; CHECK: membar
> +; CHECK: xor
> +; CHECK: cas [%o0]
> +; CHECK: membar
> +define zeroext i32 @test_load_xor_32(i32* %p, i32 zeroext %v) {
> +entry:
> + %0 = atomicrmw xor i32* %p, i32 %v seq_cst
> + ret i32 %0
> +}
> +
> +; CHECK-LABEL: test_load_and_32
> +; CHECK: membar
> +; CHECK: and
> +; CHECK-NOT: xor
> +; CHECK: cas [%o0]
> +; CHECK: membar
> +define zeroext i32 @test_load_and_32(i32* %p, i32 zeroext %v) {
> +entry:
> + %0 = atomicrmw and i32* %p, i32 %v seq_cst
> + ret i32 %0
> +}
> +
> +; CHECK-LABEL: test_load_nand_32
> +; CHECK: membar
> +; CHECK: and
> +; CHECK: xor
> +; CHECK: cas [%o0]
> +; CHECK: membar
> +define zeroext i32 @test_load_nand_32(i32* %p, i32 zeroext %v) {
> +entry:
> + %0 = atomicrmw nand i32* %p, i32 %v seq_cst
> + ret i32 %0
> +}
> +
> +; CHECK-LABEL: test_load_max_64
> +; CHECK: membar
> +; CHECK: cmp
> +; CHECK: movg %xcc
> +; CHECK: casx [%o0]
> +; CHECK: membar
> +define zeroext i64 @test_load_max_64(i64* %p, i64 zeroext %v) {
> +entry:
> + %0 = atomicrmw max i64* %p, i64 %v seq_cst
> + ret i64 %0
> +}
> +
> +; CHECK-LABEL: test_load_umin_32
> +; CHECK: membar
> +; CHECK: cmp
> +; CHECK: movleu %icc
> +; CHECK: cas [%o0]
> +; CHECK: membar
> +define zeroext i32 @test_load_umin_32(i32* %p, i32 zeroext %v) {
> +entry:
> + %0 = atomicrmw umin i32* %p, i32 %v seq_cst
> + ret i32 %0
> +}
> Index: test/CodeGen/SPARC/constpool.ll
> ===================================================================
> --- test/CodeGen/SPARC/constpool.ll (revision 201091)
> +++ test/CodeGen/SPARC/constpool.ll (working copy)
> @@ -12,7 +12,7 @@
>
> ; abs32: floatCP
> ; abs32: sethi %hi(.LCPI0_0), %[[R:[gilo][0-7]]]
> -; abs32: jmp %o7+8
> +; abs32: retl
> ; abs32: ld [%[[R]]+%lo(.LCPI0_0)], %f
>
>
> @@ -20,8 +20,8 @@
> ; abs44: sethi %h44(.LCPI0_0), %[[R1:[gilo][0-7]]]
> ; abs44: add %[[R1]], %m44(.LCPI0_0), %[[R2:[gilo][0-7]]]
> ; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]]
> -; abs44: jmp %o7+8
> -; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f1
> +; abs44: retl
> +; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f0
>
>
> ; abs64: floatCP
> @@ -30,8 +30,8 @@
> ; abs64: sethi %hh(.LCPI0_0), %[[R3:[gilo][0-7]]]
> ; abs64: add %[[R3]], %hm(.LCPI0_0), %[[R4:[gilo][0-7]]]
> ; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]]
> -; abs64: jmp %o7+8
> -; abs64: ld [%[[R5]]+%[[R2]]], %f1
> +; abs64: retl
> +; abs64: ld [%[[R5]]+%[[R2]]], %f0
>
>
> ; v8pic32: floatCP
> @@ -40,7 +40,7 @@
> ; v8pic32: add %[[R1]], %lo(.LCPI0_0), %[[Goffs:[gilo][0-7]]]
> ; v8pic32: ld [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]]
> ; v8pic32: ld [%[[Gaddr]]], %f0
> -; v8pic32: jmp %i7+8
> +; v8pic32: ret
> ; v8pic32: restore
>
>
> @@ -50,8 +50,8 @@
> ; v9pic32: sethi %hi(.LCPI0_0), %[[R1:[gilo][0-7]]]
> ; v9pic32: add %[[R1]], %lo(.LCPI0_0), %[[Goffs:[gilo][0-7]]]
> ; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]]
> -; v9pic32: ld [%[[Gaddr]]], %f1
> -; v9pic32: jmp %i7+8
> +; v9pic32: ld [%[[Gaddr]]], %f0
> +; v9pic32: ret
> ; v9pic32: restore
>
>
> Index: test/CodeGen/SPARC/ctpop.ll
> ===================================================================
> --- test/CodeGen/SPARC/ctpop.ll (revision 201091)
> +++ test/CodeGen/SPARC/ctpop.ll (working copy)
> @@ -1,8 +1,29 @@
> -; RUN: llc < %s -march=sparc -mattr=-v9 | not grep popc
> -; RUN: llc < %s -march=sparc -mattr=+v9 | grep popc
> +; RUN: llc < %s -march=sparc -mattr=-v9 | FileCheck %s -check-prefix=V8
> +; RUN: llc < %s -march=sparc -mattr=+v9,+popc | FileCheck %s -check-prefix=V9
> +; RUN: llc < %s -march=sparc -mcpu=v9 | FileCheck %s -check-prefix=V8
> +; RUN: llc < %s -march=sparc -mcpu=ultrasparc | FileCheck %s -check-prefix=V8
> +; RUN: llc < %s -march=sparc -mcpu=ultrasparc3 | FileCheck %s -check-prefix=V8
> +; RUN: llc < %s -march=sparc -mcpu=niagara | FileCheck %s -check-prefix=V8
> +; RUN: llc < %s -march=sparc -mcpu=niagara2 | FileCheck %s -check-prefix=V9
> +; RUN: llc < %s -march=sparc -mcpu=niagara3 | FileCheck %s -check-prefix=V9
> +; RUN: llc < %s -march=sparc -mcpu=niagara4 | FileCheck %s -check-prefix=V9
> +; RUN: llc < %s -march=sparcv9 -mattr=+popc | FileCheck %s -check-prefix=SPARC64
>
> declare i32 @llvm.ctpop.i32(i32)
>
> +; V8-LABEL: test
> +; V8-NOT : popc
> +
> +; V9-LABEL: test
> +; V9: srl %o0, 0, %o0
> +; V9-NEXT: retl
> +; V9-NEXT: popc %o0, %o0
> +
> +; SPARC64-LABEL: test
> +; SPARC64: srl %o0, 0, %o0
> +; SPARC64: retl
> +; SPARC64: popc %o0, %o0
> +
> define i32 @test(i32 %X) {
> %Y = call i32 @llvm.ctpop.i32( i32 %X ) ; <i32> [#uses=1]
> ret i32 %Y
> Index: test/CodeGen/SPARC/exception.ll
> ===================================================================
> --- test/CodeGen/SPARC/exception.ll (revision 201091)
> +++ test/CodeGen/SPARC/exception.ll (working copy)
> @@ -1,4 +1,9 @@
> -; RUN: llc < %s -march=sparc | FileCheck %s
> +; RUN: llc < %s -march=sparc -relocation-model=static | FileCheck -check-prefix=V8ABS %s
> +; RUN: llc < %s -march=sparc -relocation-model=pic | FileCheck -check-prefix=V8PIC %s
> +; RUN: llc < %s -march=sparc -relocation-model=pic -disable-cfi | FileCheck -check-prefix=V8PIC_NOCFI %s
> +; RUN: llc < %s -march=sparcv9 -relocation-model=static | FileCheck -check-prefix=V9ABS %s
> +; RUN: llc < %s -march=sparcv9 -relocation-model=pic | FileCheck -check-prefix=V9PIC %s
> +; RUN: llc < %s -march=sparcv9 -relocation-model=pic -disable-cfi | FileCheck -check-prefix=V9PIC_NOCFI %s
>
>
> %struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo }
> @@ -9,23 +14,97 @@
> @.cst = linker_private unnamed_addr constant [12 x i8] c"catched int\00", align 64
> @.cst1 = linker_private unnamed_addr constant [14 x i8] c"catched float\00", align 64
>
> -; CHECK-LABEL: main:
> -; CHECK: .cfi_startproc
> -; CHECK: .cfi_def_cfa_register 30
> -; CHECK: .cfi_window_save
> -; CHECK: .cfi_register 15, 31
> +; V8ABS-LABEL: main:
> +; V8ABS: .cfi_startproc
> +; V8ABS: .cfi_personality 0, __gxx_personality_v0
> +; V8ABS: .cfi_lsda 0,
> +; V8ABS: .cfi_def_cfa_register {{30|%fp}}
> +; V8ABS: .cfi_window_save
> +; V8ABS: .cfi_register 15, 31
>
> -; CHECK: call __cxa_throw
> -; CHECK: call __cxa_throw
> +; V8ABS: call __cxa_throw
> +; V8ABS: call __cxa_throw
>
> -; CHECK: call __cxa_begin_catch
> -; CHECK: call __cxa_end_catch
> +; V8ABS: call __cxa_begin_catch
> +; V8ABS: call __cxa_end_catch
>
> -; CHECK: call __cxa_begin_catch
> -; CHECK: call __cxa_end_catch
> +; V8ABS: call __cxa_begin_catch
> +; V8ABS: call __cxa_end_catch
>
> -; CHECK: .cfi_endproc
> +; V8ABS: .cfi_endproc
>
> +; V8PIC-LABEL: main:
> +; V8PIC: .cfi_startproc
> +; V8PIC: .cfi_personality 155, DW.ref.__gxx_personality_v0
> +; V8PIC: .cfi_lsda 27,
> +; V8PIC: .cfi_def_cfa_register {{30|%fp}}
> +; V8PIC: .cfi_window_save
> +; V8PIC: .cfi_register 15, 31
> +; V8PIC: .section .gcc_except_table
> +; V8PIC-NOT: .section
> +; V8PIC: .word %r_disp32(.L_ZTIi.DW.stub)
> +; V8PIC: .data
> +; V8PIC: .L_ZTIi.DW.stub:
> +; V8PIC-NEXT: .word _ZTIi
> +
> +; V8PIC_NOCFI-LABEL: main:
> +; V8PIC_NOCFI: .section .gcc_except_table
> +; V8PIC_NOCFI-NOT: .section
> +; V8PIC_NOCFI: .word %r_disp32(.L_ZTIi.DW.stub)
> +; V8PIC_NOCFI: .data
> +; V8PIC_NOCFI: .L_ZTIi.DW.stub:
> +; V8PIC_NOCFI-NEXT: .word _ZTIi
> +; V8PIC_NOCFI: .section .eh_frame
> +; V8PIC_NOCFI-NOT: .section
> +; V8PIC_NOCFI: .byte 15 ! CIE Return Address Column
> +; V8PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0)
> +; V8PIC_NOCFI: .byte 12 ! DW_CFA_def_cfa
> +; V8PIC_NOCFI: .byte 14 ! Reg 14
> +; V8PIC_NOCFI-NEXT: .byte 0 ! Offset 0
> +; V8PIC_NOCFI: .word %r_disp32(.Ltmp{{.+}}) ! FDE initial location
> +
> +
> +; V9ABS-LABEL: main:
> +; V9ABS: .cfi_startproc
> +; V9ABS: .cfi_personality 0, __gxx_personality_v0
> +; V9ABS: .cfi_lsda 27,
> +; V9ABS: .cfi_def_cfa_register {{30|%fp}}
> +; V9ABS: .cfi_window_save
> +; V9ABS: .cfi_register 15, 31
> +; V9ABS: .section .gcc_except_table
> +; V9ABS-NOT: .section
> +; V9ABS: .xword _ZTIi
> +
> +; V9PIC-LABEL: main:
> +; V9PIC: .cfi_startproc
> +; V9PIC: .cfi_personality 155, DW.ref.__gxx_personality_v0
> +; V9PIC: .cfi_lsda 27,
> +; V9PIC: .cfi_def_cfa_register {{30|%fp}}
> +; V9PIC: .cfi_window_save
> +; V9PIC: .cfi_register 15, 31
> +; V9PIC: .section .gcc_except_table
> +; V9PIC-NOT: .section
> +; V9PIC: .word %r_disp32(.L_ZTIi.DW.stub)
> +; V9PIC: .data
> +; V9PIC: .L_ZTIi.DW.stub:
> +; V9PIC-NEXT: .xword _ZTIi
> +
> +; V9PIC_NOCFI-LABEL: main:
> +; V9PIC_NOCFI: .section .gcc_except_table
> +; V9PIC_NOCFI-NOT: .section
> +; V9PIC_NOCFI: .word %r_disp32(.L_ZTIi.DW.stub)
> +; V9PIC_NOCFI: .data
> +; V9PIC_NOCFI: .L_ZTIi.DW.stub:
> +; V9PIC_NOCFI-NEXT: .xword _ZTIi
> +; V9PIC_NOCFI: .section .eh_frame
> +; V9PIC_NOCFI-NOT: .section
> +; V9PIC_NOCFI: .byte 15 ! CIE Return Address Column
> +; V9PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0)
> +; V9PIC_NOCFI: .byte 12 ! DW_CFA_def_cfa
> +; V9PIC_NOCFI-NEXT: .byte 14 ! Reg 14
> +; V9PIC_NOCFI: .ascii "\377\017" ! Offset 2047
> +; V9PIC_NOCFI: .word %r_disp32(.Ltmp{{.+}}) ! FDE initial location
> +
> define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 {
> entry:
> %0 = icmp eq i32 %argc, 2
> Index: test/CodeGen/SPARC/fp128.ll
> ===================================================================
> --- test/CodeGen/SPARC/fp128.ll (revision 201091)
> +++ test/CodeGen/SPARC/fp128.ll (working copy)
> @@ -45,7 +45,7 @@
> ; HARD: std %f{{.+}}, [%[[S1:.+]]]
> ; HARD-DAG: ldd [%[[S0]]], %f{{.+}}
> ; HARD-DAG: ldd [%[[S1]]], %f{{.+}}
> -; HARD: jmp
> +; HARD: jmp %o7+12
>
> ; SOFT-LABEL: f128_spill
> ; SOFT: std %f{{.+}}, [%[[S0:.+]]]
> @@ -52,7 +52,7 @@
> ; SOFT: std %f{{.+}}, [%[[S1:.+]]]
> ; SOFT-DAG: ldd [%[[S0]]], %f{{.+}}
> ; SOFT-DAG: ldd [%[[S1]]], %f{{.+}}
> -; SOFT: jmp
> +; SOFT: jmp %o7+12
>
> define void @f128_spill(fp128* noalias sret %scalar.result, fp128* byval %a) {
> entry:
> @@ -132,13 +132,13 @@
> ; HARD: ldub
> ; HARD: faddq
> ; HARD: stb
> -; HARD: jmp
> +; HARD: ret
>
> ; SOFT-LABEL: fp128_unaligned
> ; SOFT: ldub
> ; SOFT: call _Q_add
> ; SOFT: stb
> -; SOFT: jmp
> +; SOFT: ret
>
> define void @fp128_unaligned(fp128* %a, fp128* %b, fp128* %c) {
> entry:
> Index: test/CodeGen/SPARC/globals.ll
> ===================================================================
> --- test/CodeGen/SPARC/globals.ll (revision 201091)
> +++ test/CodeGen/SPARC/globals.ll (working copy)
> @@ -14,7 +14,7 @@
>
> ; abs32: loadG
> ; abs32: sethi %hi(G), %[[R:[gilo][0-7]]]
> -; abs32: jmp %o7+8
> +; abs32: retl
> ; abs32: ldub [%[[R]]+%lo(G)], %o0
>
>
> @@ -22,7 +22,7 @@
> ; abs44: sethi %h44(G), %[[R1:[gilo][0-7]]]
> ; abs44: add %[[R1]], %m44(G), %[[R2:[gilo][0-7]]]
> ; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]]
> -; abs44: jmp %o7+8
> +; abs44: retl
> ; abs44: ldub [%[[R3]]+%l44(G)], %o0
>
>
> @@ -32,7 +32,7 @@
> ; abs64: sethi %hh(G), %[[R3:[gilo][0-7]]]
> ; abs64: add %[[R3]], %hm(G), %[[R4:[gilo][0-7]]]
> ; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]]
> -; abs64: jmp %o7+8
> +; abs64: retl
> ; abs64: ldub [%[[R5]]+%[[R2]]], %o0
>
>
> @@ -42,7 +42,7 @@
> ; v8pic32: add %[[R1]], %lo(G), %[[Goffs:[gilo][0-7]]]
> ; v8pic32: ld [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]]
> ; v8pic32: ldub [%[[Gaddr]]], %i0
> -; v8pic32: jmp %i7+8
> +; v8pic32: ret
> ; v8pic32: restore
>
>
> @@ -52,6 +52,6 @@
> ; v9pic32: add %[[R1]], %lo(G), %[[Goffs:[gilo][0-7]]]
> ; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]]
> ; v9pic32: ldub [%[[Gaddr]]], %i0
> -; v9pic32: jmp %i7+8
> +; v9pic32: ret
> ; v9pic32: restore
>
> Index: test/CodeGen/SPARC/inlineasm.ll
> ===================================================================
> --- test/CodeGen/SPARC/inlineasm.ll (revision 0)
> +++ test/CodeGen/SPARC/inlineasm.ll (working copy)
> @@ -0,0 +1,45 @@
> +; RUN: llc -march=sparc <%s | FileCheck %s
> +
> +; CHECK-LABEL: test_constraint_r
> +; CHECK: add %o1, %o0, %o0
> +define i32 @test_constraint_r(i32 %a, i32 %b) {
> +entry:
> + %0 = tail call i32 asm sideeffect "add $2, $1, $0", "=r,r,r"(i32 %a, i32 %b)
> + ret i32 %0
> +}
> +
> +; CHECK-LABEL: test_constraint_I
> +; CHECK: add %o0, 1023, %o0
> +define i32 @test_constraint_I(i32 %a) {
> +entry:
> + %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 1023)
> + ret i32 %0
> +}
> +
> +; CHECK-LABEL: test_constraint_I_neg
> +; CHECK: add %o0, -4096, %o0
> +define i32 @test_constraint_I_neg(i32 %a) {
> +entry:
> + %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 -4096)
> + ret i32 %0
> +}
> +
> +; CHECK-LABEL: test_constraint_I_largeimm
> +; CHECK: sethi 9, [[R0:%[gilo][0-7]]]
> +; CHECK: or [[R0]], 784, [[R1:%[gilo][0-7]]]
> +; CHECK: add %o0, [[R1]], %o0
> +define i32 @test_constraint_I_largeimm(i32 %a) {
> +entry:
> + %0 = tail call i32 asm sideeffect "add $1, $2, $0", "=r,r,rI"(i32 %a, i32 10000)
> + ret i32 %0
> +}
> +
> +; CHECK-LABEL: test_constraint_reg
> +; CHECK: ldda [%o1] 43, %g2
> +; CHECK: ldda [%o1] 43, %g3
> +define void @test_constraint_reg(i32 %s, i32* %ptr) {
> +entry:
> + %0 = tail call i64 asm sideeffect "ldda [$1] $2, $0", "={r2},r,n"(i32* %ptr, i32 43)
> + %1 = tail call i64 asm sideeffect "ldda [$1] $2, $0", "={g3},r,n"(i32* %ptr, i32 43)
> + ret void
> +}
> Index: test/CodeGen/SPARC/leafproc.ll
> ===================================================================
> --- test/CodeGen/SPARC/leafproc.ll (revision 201091)
> +++ test/CodeGen/SPARC/leafproc.ll (working copy)
> @@ -1,7 +1,7 @@
> ; RUN: llc -march=sparc -disable-sparc-leaf-proc=0 < %s | FileCheck %s
>
> ; CHECK-LABEL: func_nobody:
> -; CHECK: jmp %o7+8
> +; CHECK: retl
> ; CHECK-NEXT: nop
> define void @func_nobody() {
> entry:
> @@ -10,7 +10,7 @@
>
>
> ; CHECK-LABEL: return_int_const:
> -; CHECK: jmp %o7+8
> +; CHECK: retl
> ; CHECK-NEXT: or %g0, 1729, %o0
> define i32 @return_int_const() {
> entry:
> @@ -19,7 +19,7 @@
>
> ; CHECK-LABEL: return_double_const:
> ; CHECK: sethi
> -; CHECK: jmp %o7+8
> +; CHECK: retl
> ; CHECK-NEXT: ldd {{.*}}, %f0
>
> define double @return_double_const() {
> @@ -29,7 +29,7 @@
>
> ; CHECK-LABEL: leaf_proc_with_args:
> ; CHECK: add {{%o[0-1]}}, {{%o[0-1]}}, [[R:%[go][0-7]]]
> -; CHECK: jmp %o7+8
> +; CHECK: retl
> ; CHECK-NEXT: add [[R]], %o2, %o0
>
> define i32 @leaf_proc_with_args(i32 %a, i32 %b, i32 %c) {
> @@ -42,7 +42,7 @@
> ; CHECK-LABEL: leaf_proc_with_args_in_stack:
> ; CHECK-DAG: ld [%sp+92], {{%[go][0-7]}}
> ; CHECK-DAG: ld [%sp+96], {{%[go][0-7]}}
> -; CHECK: jmp %o7+8
> +; CHECK: retl
> ; CHECK-NEXT: add {{.*}}, %o0
> define i32 @leaf_proc_with_args_in_stack(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {
> entry:
> @@ -63,7 +63,7 @@
> ; CHECK: or %g0, 2, [[R2:%[go][0-7]]]
> ; CHECK: st [[R2]], [%sp+100]
> ; CHECK: ld {{.+}}, %o0
> -; CHECK: jmp %o7+8
> +; CHECK: retl
> ; CHECK-NEXT: add %sp, 104, %sp
>
> define i32 @leaf_proc_with_local_array(i32 %a, i32 %b, i32 %c) {
> Index: test/CodeGen/SPARC/missinglabel.ll
> ===================================================================
> --- test/CodeGen/SPARC/missinglabel.ll (revision 0)
> +++ test/CodeGen/SPARC/missinglabel.ll (working copy)
> @@ -0,0 +1,23 @@
> +; RUN: llc < %s -verify-machineinstrs | FileCheck %s
> +target datalayout = "E-m:e-i64:64-n32:64-S128"
> +target triple = "sparc64-unknown-linux-gnu"
> +
> +define void @f() align 2 {
> +entry:
> +; CHECK: %xcc, .LBB0_1
> + %cmp = icmp eq i64 undef, 0
> + br i1 %cmp, label %targetblock, label %cond.false
> +
> +cond.false:
> + unreachable
> +
> +; CHECK: .LBB0_1: ! %targetblock
> +targetblock:
> + br i1 undef, label %cond.false.i83, label %exit.i85
> +
> +cond.false.i83:
> + unreachable
> +
> +exit.i85:
> + unreachable
> +}
> Index: test/CodeGen/SPARC/obj-relocs.ll
> ===================================================================
> --- test/CodeGen/SPARC/obj-relocs.ll (revision 0)
> +++ test/CodeGen/SPARC/obj-relocs.ll (working copy)
> @@ -0,0 +1,33 @@
> +; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=static | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-ABS
> +; RUN: llc < %s -march=sparcv9 -filetype=obj --relocation-model=pic | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-PIC
> +
> +;CHECK-ABS: Relocations [
> +;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_H44 AGlobalVar 0x0
> +;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_M44 AGlobalVar 0x0
> +;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_L44 AGlobalVar 0x0
> +;CHECK-ABS: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 bar 0x0
> +;CHECK-ABS:]
> +
> +; CHECK-PIC: Relocations [
> +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
> +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
> +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
> +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
> +; CHECK-PIC: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0
> +; CHECK-PIC: ]
> +
> +
> + at AGlobalVar = global i64 0, align 8
> +
> +; CHECK-ASM: sethi %h44(AGlobalVar), [[R:%[goli][0-7]]]
> +; CHECK-ASM: add [[R]], %m44(AGlobalVar), [[R]]
> +define i64 @foo(i64 %a) {
> +entry:
> + %0 = load i64* @AGlobalVar, align 4
> + %1 = add i64 %a, %0
> + %2 = call i64 @bar(i64 %1)
> + ret i64 %2
> +}
> +
> +
> +declare i64 @bar(i64)
> Index: test/CodeGen/SPARC/rem.ll
> ===================================================================
> --- test/CodeGen/SPARC/rem.ll (revision 201091)
> +++ test/CodeGen/SPARC/rem.ll (working copy)
> @@ -3,7 +3,7 @@
> ; CHECK-LABEL: test1:
> ; CHECK: sdivx %o0, %o1, %o2
> ; CHECK-NEXT: mulx %o2, %o1, %o1
> -; CHECK-NEXT: jmp %o7+8
> +; CHECK-NEXT: retl
> ; CHECK-NEXT: sub %o0, %o1, %o0
>
> define i64 @test1(i64 %X, i64 %Y) {
> @@ -14,7 +14,7 @@
> ; CHECK-LABEL: test2:
> ; CHECK: udivx %o0, %o1, %o2
> ; CHECK-NEXT: mulx %o2, %o1, %o1
> -; CHECK-NEXT: jmp %o7+8
> +; CHECK-NEXT: retl
> ; CHECK-NEXT: sub %o0, %o1, %o0
>
> define i64 @test2(i64 %X, i64 %Y) {
> Index: test/CodeGen/SPARC/spillsize.ll
> ===================================================================
> --- test/CodeGen/SPARC/spillsize.ll (revision 0)
> +++ test/CodeGen/SPARC/spillsize.ll (working copy)
> @@ -0,0 +1,25 @@
> +; RUN: llc < %s -verify-machineinstrs | FileCheck %s
> +target datalayout = "E-m:e-i64:64-n32:64-S128"
> +target triple = "sparcv9"
> +
> +; CHECK-LABEL: spill4
> +; This function spills two values: %p and the materialized large constant.
> +; Both must use 8-byte spill and fill instructions.
> +; CHECK: stx %{{..}}, [%fp+
> +; CHECK: stx %{{..}}, [%fp+
> +; CHECK: ldx [%fp+
> +; CHECK: ldx [%fp+
> +define void @spill4(i64* nocapture %p) {
> +entry:
> + %val0 = load i64* %p
> + %cmp0 = icmp ult i64 %val0, 385672958347594845
> + %cm80 = zext i1 %cmp0 to i64
> + store i64 %cm80, i64* %p, align 8
> + tail call void asm sideeffect "", "~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{g2},~{g3},~{g4},~{g5},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o7}"()
> + %arrayidx1 = getelementptr inbounds i64* %p, i64 1
> + %val = load i64* %arrayidx1
> + %cmp = icmp ult i64 %val, 385672958347594845
> + %cm8 = select i1 %cmp, i64 10, i64 20
> + store i64 %cm8, i64* %arrayidx1, align 8
> + ret void
> +}
> Index: test/CodeGen/SPARC/tls.ll
> ===================================================================
> --- test/CodeGen/SPARC/tls.ll (revision 201091)
> +++ test/CodeGen/SPARC/tls.ll (working copy)
> @@ -3,6 +3,10 @@
> ; RUN: llc <%s -march=sparc -relocation-model=pic | FileCheck %s --check-prefix=pic
> ; RUN: llc <%s -march=sparcv9 -relocation-model=pic | FileCheck %s --check-prefix=pic
>
> +; RUN: llc <%s -march=sparc -relocation-model=static -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=v8abs-obj
> +; RUN: llc <%s -march=sparcv9 -relocation-model=static -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=v9abs-obj
> +; RUN: llc <%s -march=sparc -relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=pic-obj
> +; RUN: llc <%s -march=sparcv9 -relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=pic-obj
>
> @local_symbol = internal thread_local global i32 0
> @extern_symbol = external thread_local global i32
> @@ -38,8 +42,7 @@
>
>
> ; v8abs-LABEL: test_tls_extern
> -; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
> -; v8abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
> +; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]]
> ; v8abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
> ; v8abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
> ; v8abs: ld [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ld(extern_symbol)
> @@ -47,8 +50,7 @@
> ; v8abs: ld [%[[R4]]]
>
> ; v9abs-LABEL: test_tls_extern
> -; v9abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
> -; v9abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
> +; v9abs: or {{%[goli][0-7]}}, %l44(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]]
> ; v9abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
> ; v9abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
> ; v9abs: ldx [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ldx(extern_symbol)
> @@ -71,3 +73,47 @@
> store i32 %1, i32* @extern_symbol, align 4
> ret i32 %1
> }
> +
> +
> +; v8abs-obj: Relocations [
> +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_HIX22 local_symbol 0x0
> +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_LOX10 local_symbol 0x0
> +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_HI22 _GLOBAL_OFFSET_TABLE_ 0x0
> +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_LO10 _GLOBAL_OFFSET_TABLE_ 0x0
> +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_HI22 extern_symbol 0x0
> +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LO10 extern_symbol 0x0
> +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LD extern_symbol 0x0
> +; v8abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_ADD extern_symbol 0x0
> +; v8abs-obj: ]
> +
> +; v9abs-obj: Relocations [
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_HIX22 local_symbol 0x0
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LE_LOX10 local_symbol 0x0
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_H44 _GLOBAL_OFFSET_TABLE_ 0x0
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_M44 _GLOBAL_OFFSET_TABLE_ 0x0
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_L44 _GLOBAL_OFFSET_TABLE_ 0x0
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_HI22 extern_symbol 0x0
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LO10 extern_symbol 0x0
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_LDX extern_symbol 0x0
> +; v9abs-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_IE_ADD extern_symbol 0x0
> +; v9abs-obj: ]
> +
> +; pic-obj: Relocations [
> +; pic-obj: Section (2) .rela.text {
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_HIX22 local_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_LOX10 local_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_HI22 local_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_LO10 local_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_ADD local_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDM_CALL local_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_LDO_ADD local_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_HI22 extern_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_LO10 extern_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_ADD extern_symbol 0x0
> +; pic-obj: 0x{{[0-9,A-F]+}} R_SPARC_TLS_GD_CALL extern_symbol 0x0
> +; pic-obj: ]
> +
> Index: test/MC/Disassembler/Sparc/lit.local.cfg
> ===================================================================
> --- test/MC/Disassembler/Sparc/lit.local.cfg (revision 0)
> +++ test/MC/Disassembler/Sparc/lit.local.cfg (working copy)
> @@ -0,0 +1,4 @@
> +targets = set(config.root.targets_to_build.split())
> +if not 'Sparc' in targets:
> + config.unsupported = True
> +
> Index: test/MC/Disassembler/Sparc/sparc-fp.txt
> ===================================================================
> --- test/MC/Disassembler/Sparc/sparc-fp.txt (revision 0)
> +++ test/MC/Disassembler/Sparc/sparc-fp.txt (working copy)
> @@ -0,0 +1,148 @@
> +# RUN: llvm-mc --disassemble %s -triple=sparc64-linux-gnu | FileCheck %s
> +
> +
> +# CHECK: fitos %f0, %f4
> +0x89 0xa0 0x18 0x80
> +
> +# CHECK: fitod %f0, %f4
> +0x89 0xa0 0x19 0x00
> +
> +# CHECK: fitoq %f0, %f4
> +0x89 0xa0 0x19 0x80
> +
> +# CHECK: fstoi %f0, %f4
> +0x89 0xa0 0x1a 0x20
> +
> +# CHECK: fdtoi %f0, %f4
> +0x89 0xa0 0x1a 0x40
> +
> +# CHECK: fqtoi %f0, %f4
> +0x89 0xa0 0x1a 0x60
> +
> +# CHECK: fstod %f0, %f4
> +0x89 0xa0 0x19 0x20
> +# CHECK: fstoq %f0, %f4
> +0x89 0xa0 0x19 0xa0
> +
> +# CHECK: fdtos %f0, %f4
> +0x89 0xa0 0x18 0xc0
> +
> +# CHECK: fdtoq %f0, %f4
> +0x89 0xa0 0x19 0xc0
> +
> +# CHECK: fqtos %f0, %f4
> +0x89 0xa0 0x18 0xe0
> +
> +# CHECK: fqtod %f0, %f4
> +0x89 0xa0 0x19 0x60
> +
> +# CHECK: fmovs %f0, %f4
> +0x89 0xa0 0x00 0x20
> +
> +# CHECK: fmovd %f0, %f4
> +0x89 0xa0 0x00 0x40
> +
> +# CHECK: fmovq %f0, %f4
> +0x89 0xa0 0x00 0x60
> +
> +# CHECK: fnegs %f0, %f4
> +0x89 0xa0 0x00 0xa0
> +
> +# CHECK: fnegd %f0, %f4
> +0x89 0xa0 0x00 0xc0
> +
> +# CHECK: fnegq %f0, %f4
> +0x89 0xa0 0x00 0xe0
> +
> +# CHECK: fabss %f0, %f4
> +0x89 0xa0 0x01 0x20
> +
> +# CHECK: fabsd %f0, %f4
> +0x89 0xa0 0x01 0x40
> +
> +# CHECK: fabsq %f0, %f4
> +0x89 0xa0 0x01 0x60
> +
> +# CHECK: fsqrts %f0, %f4
> +0x89 0xa0 0x05 0x20
> +
> +# CHECK: fsqrtd %f0, %f4
> +0x89 0xa0 0x05 0x40
> +
> +# CHECK: fsqrtq %f0, %f4
> +0x89 0xa0 0x05 0x60
> +
> +# CHECK: fadds %f0, %f4, %f8
> +0x91 0xa0 0x08 0x24
> +
> +# CHECK: faddd %f0, %f4, %f8
> +0x91 0xa0 0x08 0x44
> +
> +# CHECK: faddq %f0, %f4, %f8
> +0x91 0xa0 0x08 0x64
> +
> +# CHECK: faddd %f32, %f34, %f62
> +0xbf 0xa0 0x48 0x43
> +
> +# CHECK: faddq %f32, %f36, %f60
> +0xbb 0xa0 0x48 0x65
> +
> +# CHECK: fsubs %f0, %f4, %f8
> +0x91 0xa0 0x08 0xa4
> +
> +# CHECK: fsubd %f0, %f4, %f8
> +0x91 0xa0 0x08 0xc4
> +
> +# CHECK: fsubq %f0, %f4, %f8
> +0x91 0xa0 0x08 0xe4
> +
> +# CHECK: fmuls %f0, %f4, %f8
> +0x91 0xa0 0x09 0x24
> +
> +# CHECK: fmuld %f0, %f4, %f8
> +0x91 0xa0 0x09 0x44
> +
> +# CHECK: fmulq %f0, %f4, %f8
> +0x91 0xa0 0x09 0x64
> +
> +# CHECK: fsmuld %f0, %f4, %f8
> +0x91 0xa0 0x0d 0x24
> +
> +# CHECK: fdmulq %f0, %f4, %f8
> +0x91 0xa0 0x0d 0xc4
> +
> +# CHECK: fdivs %f0, %f4, %f8
> +0x91 0xa0 0x09 0xa4
> +
> +# CHECK: fdivd %f0, %f4, %f8
> +0x91 0xa0 0x09 0xc4
> +
> +# CHECK: fdivq %f0, %f4, %f8
> +0x91 0xa0 0x09 0xe4
> +
> +# CHECK: fcmps %f0, %f4
> +0x81 0xa8 0x0a 0x24
> +
> +# CHECK: fcmpd %f0, %f4
> +0x81 0xa8 0x0a 0x44
> +
> +# CHECK: fcmpq %f0, %f4
> +0x81 0xa8 0x0a 0x64
> +
> +# CHECK: fxtos %f0, %f4
> +0x89 0xa0 0x10 0x80
> +
> +# CHECK: fxtod %f0, %f4
> +0x89 0xa0 0x11 0x00
> +
> +# CHECK: fxtoq %f0, %f4
> +0x89 0xa0 0x11 0x80
> +
> +# CHECK: fstox %f0, %f4
> +0x89 0xa0 0x10 0x20
> +
> +# CHECK: fdtox %f0, %f4
> +0x89 0xa0 0x10 0x40
> +
> +# CHECK: fqtox %f0, %f4
> +0x89 0xa0 0x10 0x60
> Index: test/MC/Disassembler/Sparc/sparc.txt
> ===================================================================
> --- test/MC/Disassembler/Sparc/sparc.txt (revision 0)
> +++ test/MC/Disassembler/Sparc/sparc.txt (working copy)
> @@ -0,0 +1,169 @@
> +# RUN: llvm-mc --disassemble %s -triple=sparc-unknown-linux | FileCheck %s
> +
> +# CHECK: add %g0, %g0, %g0
> +0x80 0x00 0x00 0x00
> +
> +# CHECK: add %g1, %g2, %g3
> +0x86 0x00 0x40 0x02
> +
> +# CHECK: add %o0, %o1, %l0
> +0xa0 0x02 0x00 0x09
> +
> +# CHECK: add %o0, 10, %l0
> +0xa0 0x02 0x20 0x0a
> +
> +# CHECK: addcc %g1, %g2, %g3
> +0x86 0x80 0x40 0x02
> +
> +# CHECK: addxcc %g1, %g2, %g3
> +0x86 0xc0 0x40 0x02
> +
> +# CHECK: udiv %g1, %g2, %g3
> +0x86 0x70 0x40 0x02
> +
> +# CHECK: sdiv %g1, %g2, %g3
> +0x86 0x78 0x40 0x02
> +
> +# CHECK: and %g1, %g2, %g3
> +0x86 0x08 0x40 0x02
> +
> +# CHECK: andn %g1, %g2, %g3
> +0x86 0x28 0x40 0x02
> +
> +# CHECK: or %g1, %g2, %g3
> +0x86 0x10 0x40 0x02
> +
> +# CHECK: orn %g1, %g2, %g3
> +0x86 0x30 0x40 0x02
> +
> +# CHECK: xor %g1, %g2, %g3
> +0x86 0x18 0x40 0x02
> +
> +# CHECK: xnor %g1, %g2, %g3
> +0x86 0x38 0x40 0x02
> +
> +# CHECK: umul %g1, %g2, %g3
> +0x86 0x50 0x40 0x02
> +
> +# CHECK: smul %g1, %g2, %g3
> +0x86 0x58 0x40 0x02
> +
> +# CHECK: nop
> +0x01 0x00 0x00 0x00
> +
> +# CHECK: sethi 10, %l0
> +0x21 0x00 0x00 0x0a
> +
> +# CHECK: sll %g1, %g2, %g3
> +0x87 0x28 0x40 0x02
> +
> +# CHECK: sll %g1, 31, %g3
> +0x87 0x28 0x60 0x1f
> +
> +# CHECK: srl %g1, %g2, %g3
> +0x87 0x30 0x40 0x02
> +
> +# CHECK: srl %g1, 31, %g3
> +0x87 0x30 0x60 0x1f
> +
> +# CHECK: sra %g1, %g2, %g3
> +0x87 0x38 0x40 0x02
> +
> +# CHECK: sra %g1, 31, %g3
> +0x87 0x38 0x60 0x1f
> +
> +# CHECK: sub %g1, %g2, %g3
> +0x86 0x20 0x40 0x02
> +
> +# CHECK: subcc %g1, %g2, %g3
> +0x86 0xa0 0x40 0x02
> +
> +# CHECK: subxcc %g1, %g2, %g3
> +0x86 0xe0 0x40 0x02
> +
> +# CHECK: ba 4194303
> +0x10 0xbf 0xff 0xff
> +
> +# CHECK: bne 4194303
> +0x12 0xbf 0xff 0xff
> +
> +# CHECK: be 4194303
> +0x02 0xbf 0xff 0xff
> +
> +# CHECK: bg 4194303
> +0x14 0xbf 0xff 0xff
> +
> +# CHECK: ble 4194303
> +0x04 0xbf 0xff 0xff
> +
> +# CHECK: bge 4194303
> +0x16 0xbf 0xff 0xff
> +
> +# CHECK: bl 4194303
> +0x06 0xbf 0xff 0xff
> +
> +# CHECK: bgu 4194303
> +0x18 0xbf 0xff 0xff
> +
> +# CHECK: bleu 4194303
> +0x08 0xbf 0xff 0xff
> +
> +# CHECK: bcc 4194303
> +0x1a 0xbf 0xff 0xff
> +
> +# CHECK: bcs 4194303
> +0x0a 0xbf 0xff 0xff
> +
> +# CHECK: bpos 4194303
> +0x1c 0xbf 0xff 0xff
> +
> +# CHECK: bneg 4194303
> +0x0c 0xbf 0xff 0xff
> +
> +# CHECK: bvc 4194303
> +0x1e 0xbf 0xff 0xff
> +
> +# CHECK: bvs 4194303
> +0x0e 0xbf 0xff 0xff
> +
> +# CHECK: fbu 4194303
> +0x0f 0xbf 0xff 0xff
> +
> +# CHECK: fbg 4194303
> +0x0d 0xbf 0xff 0xff
> +
> +# CHECK: fbug 4194303
> +0x0b 0xbf 0xff 0xff
> +
> +# CHECK: fbl 4194303
> +0x09 0xbf 0xff 0xff
> +
> +# CHECK: fbul 4194303
> +0x07 0xbf 0xff 0xff
> +
> +# CHECK: fblg 4194303
> +0x05 0xbf 0xff 0xff
> +
> +# CHECK: fbne 4194303
> +0x03 0xbf 0xff 0xff
> +
> +# CHECK: fbe 4194303
> +0x13 0xbf 0xff 0xff
> +
> +# CHECK: fbue 4194303
> +0x15 0xbf 0xff 0xff
> +
> +# CHECK: fbge 4194303
> +0x17 0xbf 0xff 0xff
> +
> +# CHECK: fbuge 4194303
> +0x19 0xbf 0xff 0xff
> +
> +# CHECK: fble 4194303
> +0x1b 0xbf 0xff 0xff
> +
> +# CHECK: fbule 4194303
> +0x1d 0xbf 0xff 0xff
> +
> +# CHECK: fbo 4194303
> +0x1f 0xbf 0xff 0xff
> Index: test/MC/Sparc/sparc-alu-instructions.s
> ===================================================================
> --- test/MC/Sparc/sparc-alu-instructions.s (revision 0)
> +++ test/MC/Sparc/sparc-alu-instructions.s (working copy)
> @@ -0,0 +1,77 @@
> +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
> +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
> +
> + ! CHECK: add %g0, %g0, %g0 ! encoding: [0x80,0x00,0x00,0x00]
> + add %g0, %g0, %g0
> + ! CHECK: add %g1, %g2, %g3 ! encoding: [0x86,0x00,0x40,0x02]
> + add %g1, %g2, %g3
> + ! CHECK: add %o0, %o1, %l0 ! encoding: [0xa0,0x02,0x00,0x09]
> + add %r8, %r9, %l0
> + ! CHECK: add %o0, 10, %l0 ! encoding: [0xa0,0x02,0x20,0x0a]
> + add %o0, 10, %l0
> +
> + ! CHECK: addcc %g1, %g2, %g3 ! encoding: [0x86,0x80,0x40,0x02]
> + addcc %g1, %g2, %g3
> +
> + ! CHECK: addxcc %g1, %g2, %g3 ! encoding: [0x86,0xc0,0x40,0x02]
> + addxcc %g1, %g2, %g3
> +
> + ! CHECK: udiv %g1, %g2, %g3 ! encoding: [0x86,0x70,0x40,0x02]
> + udiv %g1, %g2, %g3
> +
> + ! CHECK: sdiv %g1, %g2, %g3 ! encoding: [0x86,0x78,0x40,0x02]
> + sdiv %g1, %g2, %g3
> +
> + ! CHECK: and %g1, %g2, %g3 ! encoding: [0x86,0x08,0x40,0x02]
> + and %g1, %g2, %g3
> + ! CHECK: andn %g1, %g2, %g3 ! encoding: [0x86,0x28,0x40,0x02]
> + andn %g1, %g2, %g3
> + ! CHECK: or %g1, %g2, %g3 ! encoding: [0x86,0x10,0x40,0x02]
> + or %g1, %g2, %g3
> + ! CHECK: orn %g1, %g2, %g3 ! encoding: [0x86,0x30,0x40,0x02]
> + orn %g1, %g2, %g3
> + ! CHECK: xor %g1, %g2, %g3 ! encoding: [0x86,0x18,0x40,0x02]
> + xor %g1, %g2, %g3
> + ! CHECK: xnor %g1, %g2, %g3 ! encoding: [0x86,0x38,0x40,0x02]
> + xnor %g1, %g2, %g3
> +
> + ! CHECK: umul %g1, %g2, %g3 ! encoding: [0x86,0x50,0x40,0x02]
> + umul %g1, %g2, %g3
> +
> + ! CHECK: smul %g1, %g2, %g3 ! encoding: [0x86,0x58,0x40,0x02]
> + smul %g1, %g2, %g3
> +
> + ! CHECK: nop ! encoding: [0x01,0x00,0x00,0x00]
> + nop
> +
> + ! CHECK: sethi 10, %l0 ! encoding: [0x21,0x00,0x00,0x0a]
> + sethi 10, %l0
> +
> + ! CHECK: sll %g1, %g2, %g3 ! encoding: [0x87,0x28,0x40,0x02]
> + sll %g1, %g2, %g3
> + ! CHECK: sll %g1, 31, %g3 ! encoding: [0x87,0x28,0x60,0x1f]
> + sll %g1, 31, %g3
> +
> + ! CHECK: srl %g1, %g2, %g3 ! encoding: [0x87,0x30,0x40,0x02]
> + srl %g1, %g2, %g3
> + ! CHECK: srl %g1, 31, %g3 ! encoding: [0x87,0x30,0x60,0x1f]
> + srl %g1, 31, %g3
> +
> + ! CHECK: sra %g1, %g2, %g3 ! encoding: [0x87,0x38,0x40,0x02]
> + sra %g1, %g2, %g3
> + ! CHECK: sra %g1, 31, %g3 ! encoding: [0x87,0x38,0x60,0x1f]
> + sra %g1, 31, %g3
> +
> + ! CHECK: sub %g1, %g2, %g3 ! encoding: [0x86,0x20,0x40,0x02]
> + sub %g1, %g2, %g3
> + ! CHECK: subcc %g1, %g2, %g3 ! encoding: [0x86,0xa0,0x40,0x02]
> + subcc %g1, %g2, %g3
> +
> + ! CHECK: subxcc %g1, %g2, %g3 ! encoding: [0x86,0xe0,0x40,0x02]
> + subxcc %g1, %g2, %g3
> +
> + ! CHECK: or %g0, %g1, %g3 ! encoding: [0x86,0x10,0x00,0x01]
> + mov %g1, %g3
> +
> + ! CHECK: or %g0, 255, %g3 ! encoding: [0x86,0x10,0x20,0xff]
> + mov 0xff, %g3
> Index: test/MC/Sparc/sparc-atomic-instructions.s
> ===================================================================
> --- test/MC/Sparc/sparc-atomic-instructions.s (revision 0)
> +++ test/MC/Sparc/sparc-atomic-instructions.s (working copy)
> @@ -0,0 +1,19 @@
> +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
> +
> + ! CHECK: membar 15 ! encoding: [0x81,0x43,0xe0,0x0f]
> + membar 15
> +
> + ! CHECK: stbar ! encoding: [0x81,0x43,0xc0,0x00]
> + stbar
> +
> + ! CHECK: swap [%i0+%l6], %o2 ! encoding: [0xd4,0x7e,0x00,0x16]
> + swap [%i0+%l6], %o2
> +
> + ! 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
> Index: test/MC/Sparc/sparc-ctrl-instructions.s
> ===================================================================
> --- test/MC/Sparc/sparc-ctrl-instructions.s (revision 0)
> +++ test/MC/Sparc/sparc-ctrl-instructions.s (working copy)
> @@ -0,0 +1,160 @@
> +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
> +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
> +
> + ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A]
> + ! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30
> + call foo
> +
> + ! CHECK: call %g1+%i2 ! encoding: [0x9f,0xc0,0x40,0x1a]
> + call %g1 + %i2
> +
> + ! CHECK: call %o1+8 ! encoding: [0x9f,0xc2,0x60,0x08]
> + call %o1 + 8
> +
> + ! CHECK: call %g1 ! encoding: [0x9f,0xc0,0x60,0x00]
> + call %g1
> +
> + ! CHECK: call %g1+%lo(sym) ! encoding: [0x9f,0xc0,0b011000AA,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
> + call %g1+%lo(sym)
> +
> + ! CHECK: jmp %g1+%i2 ! encoding: [0x81,0xc0,0x40,0x1a]
> + jmp %g1 + %i2
> +
> + ! CHECK: jmp %o1+8 ! encoding: [0x81,0xc2,0x60,0x08]
> + jmp %o1 + 8
> +
> + ! CHECK: jmp %g1 ! encoding: [0x81,0xc0,0x60,0x00]
> + jmp %g1
> +
> + ! CHECK: jmp %g1+%lo(sym) ! encoding: [0x81,0xc0,0b011000AA,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
> + jmp %g1+%lo(sym)
> +
> + ! CHECK: jmpl %g1+%i2, %g2 ! encoding: [0x85,0xc0,0x40,0x1a]
> + jmpl %g1 + %i2, %g2
> +
> + ! CHECK: jmpl %o1+8, %g2 ! encoding: [0x85,0xc2,0x60,0x08]
> + jmpl %o1 + 8, %g2
> +
> + ! CHECK: jmpl %g1, %g2 ! encoding: [0x85,0xc0,0x60,0x00]
> + jmpl %g1, %g2
> +
> + ! CHECK: jmpl %g1+%lo(sym), %g2 ! encoding: [0x85,0xc0,0b011000AA,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
> + jmpl %g1+%lo(sym), %g2
> +
> + ! CHECK: ba .BB0 ! encoding: [0x10,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + ba .BB0
> +
> + ! CHECK: bne .BB0 ! encoding: [0x12,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bne .BB0
> +
> + ! CHECK: be .BB0 ! encoding: [0x02,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + be .BB0
> +
> + ! CHECK: bg .BB0 ! encoding: [0x14,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bg .BB0
> +
> + ! CHECK: ble .BB0 ! encoding: [0x04,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + ble .BB0
> +
> + ! CHECK: bge .BB0 ! encoding: [0x16,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bge .BB0
> +
> + ! CHECK: bl .BB0 ! encoding: [0x06,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bl .BB0
> +
> + ! CHECK: bgu .BB0 ! encoding: [0x18,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bgu .BB0
> +
> + ! CHECK: bleu .BB0 ! encoding: [0x08,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bleu .BB0
> +
> + ! CHECK: bcc .BB0 ! encoding: [0x1a,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bcc .BB0
> +
> + ! CHECK: bcs .BB0 ! encoding: [0x0a,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bcs .BB0
> +
> + ! CHECK: bpos .BB0 ! encoding: [0x1c,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bpos .BB0
> +
> + ! CHECK: bneg .BB0 ! encoding: [0x0c,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bneg .BB0
> +
> + ! CHECK: bvc .BB0 ! encoding: [0x1e,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bvc .BB0
> +
> + ! CHECK: bvs .BB0 ! encoding: [0x0e,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + bvs .BB0
> +
> + ! CHECK: fbu .BB0 ! encoding: [0x0f,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbu .BB0
> +
> + ! CHECK: fbg .BB0 ! encoding: [0x0d,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbg .BB0
> + ! CHECK: fbug .BB0 ! encoding: [0x0b,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbug .BB0
> +
> + ! CHECK: fbl .BB0 ! encoding: [0x09,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbl .BB0
> +
> + ! CHECK: fbul .BB0 ! encoding: [0x07,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbul .BB0
> +
> + ! CHECK: fblg .BB0 ! encoding: [0x05,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fblg .BB0
> +
> + ! CHECK: fbne .BB0 ! encoding: [0x03,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbne .BB0
> +
> + ! CHECK: fbe .BB0 ! encoding: [0x13,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbe .BB0
> +
> + ! CHECK: fbue .BB0 ! encoding: [0x15,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbue .BB0
> +
> + ! CHECK: fbge .BB0 ! encoding: [0x17,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbge .BB0
> +
> + ! CHECK: fbuge .BB0 ! encoding: [0x19,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbuge .BB0
> +
> + ! CHECK: fble .BB0 ! encoding: [0x1b,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fble .BB0
> +
> + ! CHECK: fbule .BB0 ! encoding: [0x1d,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbule .BB0
> +
> + ! CHECK: fbo .BB0 ! encoding: [0x1f,0b10AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br22
> + fbo .BB0
> Index: test/MC/Sparc/sparc-fp-instructions.s
> ===================================================================
> --- test/MC/Sparc/sparc-fp-instructions.s (revision 0)
> +++ test/MC/Sparc/sparc-fp-instructions.s (working copy)
> @@ -0,0 +1,119 @@
> +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
> +
> + ! CHECK: fitos %f0, %f4 ! encoding: [0x89,0xa0,0x18,0x80]
> + ! CHECK: fitod %f0, %f4 ! encoding: [0x89,0xa0,0x19,0x00]
> + ! CHECK: fitoq %f0, %f4 ! encoding: [0x89,0xa0,0x19,0x80]
> + fitos %f0, %f4
> + fitod %f0, %f4
> + fitoq %f0, %f4
> +
> + ! CHECK: fstoi %f0, %f4 ! encoding: [0x89,0xa0,0x1a,0x20]
> + ! CHECK: fdtoi %f0, %f4 ! encoding: [0x89,0xa0,0x1a,0x40]
> + ! CHECK: fqtoi %f0, %f4 ! encoding: [0x89,0xa0,0x1a,0x60]
> + fstoi %f0, %f4
> + fdtoi %f0, %f4
> + fqtoi %f0, %f4
> +
> + ! CHECK: fstod %f0, %f4 ! encoding: [0x89,0xa0,0x19,0x20]
> + ! CHECK: fstoq %f0, %f4 ! encoding: [0x89,0xa0,0x19,0xa0]
> + fstod %f0, %f4
> + fstoq %f0, %f4
> +
> + ! CHECK: fdtos %f0, %f4 ! encoding: [0x89,0xa0,0x18,0xc0]
> + ! CHECK: fdtoq %f0, %f4 ! encoding: [0x89,0xa0,0x19,0xc0]
> + fdtos %f0, %f4
> + fdtoq %f0, %f4
> +
> + ! CHECK: fqtos %f0, %f4 ! encoding: [0x89,0xa0,0x18,0xe0]
> + ! CHECK: fqtod %f0, %f4 ! encoding: [0x89,0xa0,0x19,0x60]
> + fqtos %f0, %f4
> + fqtod %f0, %f4
> +
> + ! CHECK: fmovs %f0, %f4 ! encoding: [0x89,0xa0,0x00,0x20]
> + ! CHECK: fmovd %f0, %f4 ! encoding: [0x89,0xa0,0x00,0x40]
> + ! CHECK: fmovq %f0, %f4 ! encoding: [0x89,0xa0,0x00,0x60]
> + fmovs %f0, %f4
> + fmovd %f0, %f4
> + fmovq %f0, %f4
> +
> + ! CHECK: fnegs %f0, %f4 ! encoding: [0x89,0xa0,0x00,0xa0]
> + ! CHECK: fnegd %f0, %f4 ! encoding: [0x89,0xa0,0x00,0xc0]
> + ! CHECK: fnegq %f0, %f4 ! encoding: [0x89,0xa0,0x00,0xe0]
> + fnegs %f0, %f4
> + fnegd %f0, %f4
> + fnegq %f0, %f4
> +
> + ! CHECK: fabss %f0, %f4 ! encoding: [0x89,0xa0,0x01,0x20]
> + ! CHECK: fabsd %f0, %f4 ! encoding: [0x89,0xa0,0x01,0x40]
> + ! CHECK: fabsq %f0, %f4 ! encoding: [0x89,0xa0,0x01,0x60]
> + fabss %f0, %f4
> + fabsd %f0, %f4
> + fabsq %f0, %f4
> +
> + ! CHECK: fsqrts %f0, %f4 ! encoding: [0x89,0xa0,0x05,0x20]
> + ! CHECK: fsqrtd %f0, %f4 ! encoding: [0x89,0xa0,0x05,0x40]
> + ! CHECK: fsqrtq %f0, %f4 ! encoding: [0x89,0xa0,0x05,0x60]
> + fsqrts %f0, %f4
> + fsqrtd %f0, %f4
> + fsqrtq %f0, %f4
> +
> + ! CHECK: fadds %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0x24]
> + ! CHECK: faddd %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0x44]
> + ! CHECK: faddq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0x64]
> + fadds %f0, %f4, %f8
> + faddd %f0, %f4, %f8
> + faddq %f0, %f4, %f8
> +
> + ! make sure we can handle V9 double registers and their aliased quad registers.
> + ! CHECK: faddd %f32, %f34, %f62 ! encoding: [0xbf,0xa0,0x48,0x43]
> + ! CHECK: faddq %f32, %f36, %f60 ! encoding: [0xbb,0xa0,0x48,0x65]
> + faddd %f32, %f34, %f62
> + faddq %f32, %f36, %f60
> +
> + ! CHECK: fsubs %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xa4]
> + ! CHECK: fsubd %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xc4]
> + ! CHECK: fsubq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x08,0xe4]
> + fsubs %f0, %f4, %f8
> + fsubd %f0, %f4, %f8
> + fsubq %f0, %f4, %f8
> +
> + ! CHECK: fmuls %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0x24]
> + ! CHECK: fmuld %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0x44]
> + ! CHECK: fmulq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0x64]
> + fmuls %f0, %f4, %f8
> + fmuld %f0, %f4, %f8
> + fmulq %f0, %f4, %f8
> +
> + ! CHECK: fsmuld %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x0d,0x24]
> + ! CHECK: fdmulq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x0d,0xc4]
> + fsmuld %f0, %f4, %f8
> + fdmulq %f0, %f4, %f8
> +
> + ! CHECK: fdivs %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0xa4]
> + ! CHECK: fdivd %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0xc4]
> + ! CHECK: fdivq %f0, %f4, %f8 ! encoding: [0x91,0xa0,0x09,0xe4]
> + fdivs %f0, %f4, %f8
> + fdivd %f0, %f4, %f8
> + fdivq %f0, %f4, %f8
> +
> + ! CHECK: fcmps %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x24]
> + ! CHECK: fcmpd %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x44]
> + ! CHECK: fcmpq %f0, %f4 ! encoding: [0x81,0xa8,0x0a,0x64]
> + fcmps %f0, %f4
> + fcmpd %f0, %f4
> + fcmpq %f0, %f4
> +
> + ! CHECK: fxtos %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x80]
> + ! CHECK: fxtod %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x00]
> + ! CHECK: fxtoq %f0, %f4 ! encoding: [0x89,0xa0,0x11,0x80]
> + fxtos %f0, %f4
> + fxtod %f0, %f4
> + fxtoq %f0, %f4
> +
> + ! CHECK: fstox %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x20]
> + ! CHECK: fdtox %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x40]
> + ! CHECK: fqtox %f0, %f4 ! encoding: [0x89,0xa0,0x10,0x60]
> + fstox %f0, %f4
> + fdtox %f0, %f4
> + fqtox %f0, %f4
> +
> Index: test/MC/Sparc/sparc-mem-instructions.s
> ===================================================================
> --- test/MC/Sparc/sparc-mem-instructions.s (revision 0)
> +++ test/MC/Sparc/sparc-mem-instructions.s (working copy)
> @@ -0,0 +1,58 @@
> +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
> +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
> +
> + ! CHECK: ldsb [%i0+%l6], %o2 ! encoding: [0xd4,0x4e,0x00,0x16]
> + ldsb [%i0 + %l6], %o2
> + ! CHECK: ldsb [%i0+32], %o2 ! encoding: [0xd4,0x4e,0x20,0x20]
> + ldsb [%i0 + 32], %o2
> + ! CHECK: ldsb [%g1], %o4 ! encoding: [0xd8,0x48,0x60,0x00]
> + ldsb [%g1], %o4
> +
> + ! CHECK: ldsh [%i0+%l6], %o2 ! encoding: [0xd4,0x56,0x00,0x16]
> + ldsh [%i0 + %l6], %o2
> + ! CHECK: ldsh [%i0+32], %o2 ! encoding: [0xd4,0x56,0x20,0x20]
> + ldsh [%i0 + 32], %o2
> + ! CHECK: ldsh [%g1], %o4 ! encoding: [0xd8,0x50,0x60,0x00]
> + ldsh [%g1], %o4
> +
> + ! CHECK: ldub [%i0+%l6], %o2 ! encoding: [0xd4,0x0e,0x00,0x16]
> + ldub [%i0 + %l6], %o2
> + ! CHECK: ldub [%i0+32], %o2 ! encoding: [0xd4,0x0e,0x20,0x20]
> + ldub [%i0 + 32], %o2
> + ! CHECK: ldub [%g1], %o2 ! encoding: [0xd4,0x08,0x60,0x00]
> + ldub [%g1], %o2
> +
> + ! CHECK: lduh [%i0+%l6], %o2 ! encoding: [0xd4,0x16,0x00,0x16]
> + lduh [%i0 + %l6], %o2
> + ! CHECK: lduh [%i0+32], %o2 ! encoding: [0xd4,0x16,0x20,0x20]
> + lduh [%i0 + 32], %o2
> + ! CHECK: lduh [%g1], %o2 ! encoding: [0xd4,0x10,0x60,0x00]
> + lduh [%g1], %o2
> +
> + ! CHECK: ld [%i0+%l6], %o2 ! encoding: [0xd4,0x06,0x00,0x16]
> + ld [%i0 + %l6], %o2
> + ! CHECK: ld [%i0+32], %o2 ! encoding: [0xd4,0x06,0x20,0x20]
> + ld [%i0 + 32], %o2
> + ! CHECK: ld [%g1], %o2 ! encoding: [0xd4,0x00,0x60,0x00]
> + ld [%g1], %o2
> +
> + ! CHECK: stb %o2, [%i0+%l6] ! encoding: [0xd4,0x2e,0x00,0x16]
> + stb %o2, [%i0 + %l6]
> + ! CHECK: stb %o2, [%i0+32] ! encoding: [0xd4,0x2e,0x20,0x20]
> + stb %o2, [%i0 + 32]
> + ! CHECK: stb %o2, [%g1] ! encoding: [0xd4,0x28,0x60,0x00]
> + stb %o2, [%g1]
> +
> + ! CHECK: sth %o2, [%i0+%l6] ! encoding: [0xd4,0x36,0x00,0x16]
> + sth %o2, [%i0 + %l6]
> + ! CHECK: sth %o2, [%i0+32] ! encoding: [0xd4,0x36,0x20,0x20]
> + sth %o2, [%i0 + 32]
> + ! CHECK: sth %o2, [%g1] ! encoding: [0xd4,0x30,0x60,0x00]
> + sth %o2, [%g1]
> +
> + ! CHECK: st %o2, [%i0+%l6] ! encoding: [0xd4,0x26,0x00,0x16]
> + st %o2, [%i0 + %l6]
> + ! CHECK: st %o2, [%i0+32] ! encoding: [0xd4,0x26,0x20,0x20]
> + st %o2, [%i0 + 32]
> + ! CHECK: st %o2, [%g1] ! encoding: [0xd4,0x20,0x60,0x00]
> + st %o2, [%g1]
> Index: test/MC/Sparc/sparc-relocations.s
> ===================================================================
> --- test/MC/Sparc/sparc-relocations.s (revision 0)
> +++ test/MC/Sparc/sparc-relocations.s (working copy)
> @@ -0,0 +1,46 @@
> +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
> +! RUN: llvm-mc %s -arch=sparcv9 -filetype=obj | llvm-readobj -r | FileCheck %s --check-prefix=CHECK-OBJ
> +
> + ! CHECK-OBJ: Format: ELF64-sparc
> + ! CHECK-OBJ: Relocations [
> + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 foo
> + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_LO10 sym
> + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HI22 sym
> + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_H44 sym
> + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_M44 sym
> + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_L44 sym
> + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HH22 sym
> + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HM10 sym
> + ! CHECK-ELF: ]
> +
> + ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A]
> + ! CHECK: ! fixup A - offset: 0, value: foo, kind: fixup_sparc_call30
> + call foo
> +
> + ! CHECK: or %g1, %lo(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A]
> + ! CHECK-NEXT ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
> + or %g1, %lo(sym), %g3
> +
> + ! CHECK: sethi %hi(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: %hi(sym), kind: fixup_sparc_hi22
> + sethi %hi(sym), %l0
> +
> + ! CHECK: sethi %h44(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: %h44(sym), kind: fixup_sparc_h44
> + sethi %h44(sym), %l0
> +
> + ! CHECK: or %g1, %m44(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A]
> + ! CHECK-NEXT ! fixup A - offset: 0, value: %m44(sym), kind: fixup_sparc_m44
> + or %g1, %m44(sym), %g3
> +
> + ! CHECK: or %g1, %l44(sym), %g3 ! encoding: [0x86,0x10,0b0110AAAA,A]
> + ! CHECK-NEXT ! fixup A - offset: 0, value: %l44(sym), kind: fixup_sparc_l44
> + or %g1, %l44(sym), %g3
> +
> + ! CHECK: sethi %hh(sym), %l0 ! encoding: [0x21,0b00AAAAAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: %hh(sym), kind: fixup_sparc_hh
> + sethi %hh(sym), %l0
> +
> + ! CHECK: or %g1, %hm(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A]
> + ! CHECK-NEXT ! fixup A - offset: 0, value: %hm(sym), kind: fixup_sparc_hm
> + or %g1, %hm(sym), %g3
> Index: test/MC/Sparc/sparc64-alu-instructions.s
> ===================================================================
> --- test/MC/Sparc/sparc64-alu-instructions.s (revision 0)
> +++ test/MC/Sparc/sparc64-alu-instructions.s (working copy)
> @@ -0,0 +1,38 @@
> +! RUN: llvm-mc %s -triple=sparc64-unknown-linux-gnu -show-encoding | FileCheck %s
> +
> + ! CHECK: sllx %g1, %i2, %i0 ! encoding: [0xb1,0x28,0x50,0x1a]
> + sllx %g1, %i2, %i0
> +
> + ! CHECK: sllx %g1, 63, %i0 ! encoding: [0xb1,0x28,0x70,0x3f]
> + sllx %g1, 63, %i0
> +
> + ! CHECK: srlx %g1, %i2, %i0 ! encoding: [0xb1,0x30,0x50,0x1a]
> + srlx %g1, %i2, %i0
> +
> + ! CHECK: srlx %g1, 63, %i0 ! encoding: [0xb1,0x30,0x70,0x3f]
> + srlx %g1, 63, %i0
> +
> + ! CHECK: srax %g1, %i2, %i0 ! encoding: [0xb1,0x38,0x50,0x1a]
> + srax %g1, %i2, %i0
> +
> + ! CHECK: srax %g1, 63, %i0 ! encoding: [0xb1,0x38,0x70,0x3f]
> + srax %g1, 63, %i0
> +
> + ! CHECK: mulx %g1, %i2, %i0 ! encoding: [0xb0,0x48,0x40,0x1a]
> + mulx %g1, %i2, %i0
> +
> + ! CHECK: mulx %g1, 63, %i0 ! encoding: [0xb0,0x48,0x60,0x3f]
> + mulx %g1, 63, %i0
> +
> + ! CHECK: sdivx %g1, %i2, %i0 ! encoding: [0xb1,0x68,0x40,0x1a]
> + sdivx %g1, %i2, %i0
> +
> + ! CHECK: sdivx %g1, 63, %i0 ! encoding: [0xb1,0x68,0x60,0x3f]
> + sdivx %g1, 63, %i0
> +
> + ! CHECK: udivx %g1, %i2, %i0 ! encoding: [0xb0,0x68,0x40,0x1a]
> + udivx %g1, %i2, %i0
> +
> + ! CHECK: udivx %g1, 63, %i0 ! encoding: [0xb0,0x68,0x60,0x3f]
> + udivx %g1, 63, %i0
> +
> Index: test/MC/Sparc/sparc64-ctrl-instructions.s
> ===================================================================
> --- test/MC/Sparc/sparc64-ctrl-instructions.s (revision 0)
> +++ test/MC/Sparc/sparc64-ctrl-instructions.s (working copy)
> @@ -0,0 +1,235 @@
> +! RUN: llvm-mc %s -triple=sparc64-unknown-linux-gnu -show-encoding | FileCheck %s
> +
> +
> + ! CHECK: bne %xcc, .BB0 ! encoding: [0x12,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bne %xcc, .BB0
> +
> + ! CHECK: be %xcc, .BB0 ! encoding: [0x02,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + be %xcc, .BB0
> +
> + ! CHECK: bg %xcc, .BB0 ! encoding: [0x14,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bg %xcc, .BB0
> +
> + ! CHECK: ble %xcc, .BB0 ! encoding: [0x04,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + ble %xcc, .BB0
> +
> + ! CHECK: bge %xcc, .BB0 ! encoding: [0x16,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bge %xcc, .BB0
> +
> + ! CHECK: bl %xcc, .BB0 ! encoding: [0x06,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bl %xcc, .BB0
> +
> + ! CHECK: bgu %xcc, .BB0 ! encoding: [0x18,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bgu %xcc, .BB0
> +
> + ! CHECK: bleu %xcc, .BB0 ! encoding: [0x08,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bleu %xcc, .BB0
> +
> + ! CHECK: bcc %xcc, .BB0 ! encoding: [0x1a,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bcc %xcc, .BB0
> +
> + ! CHECK: bcs %xcc, .BB0 ! encoding: [0x0a,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bcs %xcc, .BB0
> +
> + ! CHECK: bpos %xcc, .BB0 ! encoding: [0x1c,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bpos %xcc, .BB0
> +
> + ! CHECK: bneg %xcc, .BB0 ! encoding: [0x0c,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bneg %xcc, .BB0
> +
> + ! CHECK: bvc %xcc, .BB0 ! encoding: [0x1e,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bvc %xcc, .BB0
> +
> + ! CHECK: bvs %xcc, .BB0 ! encoding: [0x0e,0b01101AAA,A,A]
> + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19
> + bvs %xcc, .BB0
> +
> +
> + ! CHECK: movne %icc, %g1, %g2 ! encoding: [0x85,0x66,0x40,0x01]
> + ! CHECK: move %icc, %g1, %g2 ! encoding: [0x85,0x64,0x40,0x01]
> + ! CHECK: movg %icc, %g1, %g2 ! encoding: [0x85,0x66,0x80,0x01]
> + ! CHECK: movle %icc, %g1, %g2 ! encoding: [0x85,0x64,0x80,0x01]
> + ! CHECK: movge %icc, %g1, %g2 ! encoding: [0x85,0x66,0xc0,0x01]
> + ! CHECK: movl %icc, %g1, %g2 ! encoding: [0x85,0x64,0xc0,0x01]
> + ! CHECK: movgu %icc, %g1, %g2 ! encoding: [0x85,0x67,0x00,0x01]
> + ! CHECK: movleu %icc, %g1, %g2 ! encoding: [0x85,0x65,0x00,0x01]
> + ! CHECK: movcc %icc, %g1, %g2 ! encoding: [0x85,0x67,0x40,0x01]
> + ! CHECK: movcs %icc, %g1, %g2 ! encoding: [0x85,0x65,0x40,0x01]
> + ! CHECK: movpos %icc, %g1, %g2 ! encoding: [0x85,0x67,0x80,0x01]
> + ! CHECK: movneg %icc, %g1, %g2 ! encoding: [0x85,0x65,0x80,0x01]
> + ! CHECK: movvc %icc, %g1, %g2 ! encoding: [0x85,0x67,0xc0,0x01]
> + ! CHECK: movvs %icc, %g1, %g2 ! encoding: [0x85,0x65,0xc0,0x01]
> + movne %icc, %g1, %g2
> + move %icc, %g1, %g2
> + movg %icc, %g1, %g2
> + movle %icc, %g1, %g2
> + movge %icc, %g1, %g2
> + movl %icc, %g1, %g2
> + movgu %icc, %g1, %g2
> + movleu %icc, %g1, %g2
> + movcc %icc, %g1, %g2
> + movcs %icc, %g1, %g2
> + movpos %icc, %g1, %g2
> + movneg %icc, %g1, %g2
> + movvc %icc, %g1, %g2
> + movvs %icc, %g1, %g2
> +
> + ! CHECK: movne %xcc, %g1, %g2 ! encoding: [0x85,0x66,0x50,0x01]
> + ! CHECK: move %xcc, %g1, %g2 ! encoding: [0x85,0x64,0x50,0x01]
> + ! CHECK: movg %xcc, %g1, %g2 ! encoding: [0x85,0x66,0x90,0x01]
> + ! CHECK: movle %xcc, %g1, %g2 ! encoding: [0x85,0x64,0x90,0x01]
> + ! CHECK: movge %xcc, %g1, %g2 ! encoding: [0x85,0x66,0xd0,0x01]
> + ! CHECK: movl %xcc, %g1, %g2 ! encoding: [0x85,0x64,0xd0,0x01]
> + ! CHECK: movgu %xcc, %g1, %g2 ! encoding: [0x85,0x67,0x10,0x01]
> + ! CHECK: movleu %xcc, %g1, %g2 ! encoding: [0x85,0x65,0x10,0x01]
> + ! CHECK: movcc %xcc, %g1, %g2 ! encoding: [0x85,0x67,0x50,0x01]
> + ! CHECK: movcs %xcc, %g1, %g2 ! encoding: [0x85,0x65,0x50,0x01]
> + ! CHECK: movpos %xcc, %g1, %g2 ! encoding: [0x85,0x67,0x90,0x01]
> + ! CHECK: movneg %xcc, %g1, %g2 ! encoding: [0x85,0x65,0x90,0x01]
> + ! CHECK: movvc %xcc, %g1, %g2 ! encoding: [0x85,0x67,0xd0,0x01]
> + ! CHECK: movvs %xcc, %g1, %g2 ! encoding: [0x85,0x65,0xd0,0x01]
> + movne %xcc, %g1, %g2
> + move %xcc, %g1, %g2
> + movg %xcc, %g1, %g2
> + movle %xcc, %g1, %g2
> + movge %xcc, %g1, %g2
> + movl %xcc, %g1, %g2
> + movgu %xcc, %g1, %g2
> + movleu %xcc, %g1, %g2
> + movcc %xcc, %g1, %g2
> + movcs %xcc, %g1, %g2
> + movpos %xcc, %g1, %g2
> + movneg %xcc, %g1, %g2
> + movvc %xcc, %g1, %g2
> + movvs %xcc, %g1, %g2
> +
> + ! CHECK: movu %fcc0, %g1, %g2 ! encoding: [0x85,0x61,0xc0,0x01]
> + ! CHECK: movg %fcc0, %g1, %g2 ! encoding: [0x85,0x61,0x80,0x01]
> + ! CHECK: movug %fcc0, %g1, %g2 ! encoding: [0x85,0x61,0x40,0x01]
> + ! CHECK: movl %fcc0, %g1, %g2 ! encoding: [0x85,0x61,0x00,0x01]
> + ! CHECK: movul %fcc0, %g1, %g2 ! encoding: [0x85,0x60,0xc0,0x01]
> + ! CHECK: movlg %fcc0, %g1, %g2 ! encoding: [0x85,0x60,0x80,0x01]
> + ! CHECK: movne %fcc0, %g1, %g2 ! encoding: [0x85,0x60,0x40,0x01]
> + ! CHECK: move %fcc0, %g1, %g2 ! encoding: [0x85,0x62,0x40,0x01]
> + ! CHECK: movue %fcc0, %g1, %g2 ! encoding: [0x85,0x62,0x80,0x01]
> + ! CHECK: movge %fcc0, %g1, %g2 ! encoding: [0x85,0x62,0xc0,0x01]
> + ! CHECK: movuge %fcc0, %g1, %g2 ! encoding: [0x85,0x63,0x00,0x01]
> + ! CHECK: movle %fcc0, %g1, %g2 ! encoding: [0x85,0x63,0x40,0x01]
> + ! CHECK: movule %fcc0, %g1, %g2 ! encoding: [0x85,0x63,0x80,0x01]
> + ! CHECK: movo %fcc0, %g1, %g2 ! encoding: [0x85,0x63,0xc0,0x01]
> + movu %fcc0, %g1, %g2
> + movg %fcc0, %g1, %g2
> + movug %fcc0, %g1, %g2
> + movl %fcc0, %g1, %g2
> + movul %fcc0, %g1, %g2
> + movlg %fcc0, %g1, %g2
> + movne %fcc0, %g1, %g2
> + move %fcc0, %g1, %g2
> + movue %fcc0, %g1, %g2
> + movge %fcc0, %g1, %g2
> + movuge %fcc0, %g1, %g2
> + movle %fcc0, %g1, %g2
> + movule %fcc0, %g1, %g2
> + movo %fcc0, %g1, %g2
> +
> +
> + ! CHECK fmovsne %icc, %f1, %f2 ! encoding: [0x85,0xaa,0x60,0x21]
> + ! CHECK fmovse %icc, %f1, %f2 ! encoding: [0x85,0xa8,0x60,0x21]
> + ! CHECK fmovsg %icc, %f1, %f2 ! encoding: [0x85,0xaa,0xa0,0x21]
> + ! CHECK fmovsle %icc, %f1, %f2 ! encoding: [0x85,0xa8,0xa0,0x21]
> + ! CHECK fmovsge %icc, %f1, %f2 ! encoding: [0x85,0xaa,0xe0,0x21]
> + ! CHECK fmovsl %icc, %f1, %f2 ! encoding: [0x85,0xa8,0xe0,0x21]
> + ! CHECK fmovsgu %icc, %f1, %f2 ! encoding: [0x85,0xab,0x20,0x21]
> + ! CHECK fmovsleu %icc, %f1, %f2 ! encoding: [0x85,0xa9,0x20,0x21]
> + ! CHECK fmovscc %icc, %f1, %f2 ! encoding: [0x85,0xab,0x60,0x21]
> + ! CHECK fmovscs %icc, %f1, %f2 ! encoding: [0x85,0xa9,0x60,0x21]
> + ! CHECK fmovspos %icc, %f1, %f2 ! encoding: [0x85,0xab,0xa0,0x21]
> + ! CHECK fmovsneg %icc, %f1, %f2 ! encoding: [0x85,0xa9,0xa0,0x21]
> + ! CHECK fmovsvc %icc, %f1, %f2 ! encoding: [0x85,0xab,0xe0,0x21]
> + ! CHECK fmovsvs %icc, %f1, %f2 ! encoding: [0x85,0xa9,0xe0,0x21]
> + fmovsne %icc, %f1, %f2
> + fmovse %icc, %f1, %f2
> + fmovsg %icc, %f1, %f2
> + fmovsle %icc, %f1, %f2
> + fmovsge %icc, %f1, %f2
> + fmovsl %icc, %f1, %f2
> + fmovsgu %icc, %f1, %f2
> + fmovsleu %icc, %f1, %f2
> + fmovscc %icc, %f1, %f2
> + fmovscs %icc, %f1, %f2
> + fmovspos %icc, %f1, %f2
> + fmovsneg %icc, %f1, %f2
> + fmovsvc %icc, %f1, %f2
> + fmovsvs %icc, %f1, %f2
> +
> + ! CHECK fmovsne %xcc, %f1, %f2 ! encoding: [0x85,0xaa,0x70,0x21]
> + ! CHECK fmovse %xcc, %f1, %f2 ! encoding: [0x85,0xa8,0x70,0x21]
> + ! CHECK fmovsg %xcc, %f1, %f2 ! encoding: [0x85,0xaa,0xb0,0x21]
> + ! CHECK fmovsle %xcc, %f1, %f2 ! encoding: [0x85,0xa8,0xb0,0x21]
> + ! CHECK fmovsge %xcc, %f1, %f2 ! encoding: [0x85,0xaa,0xf0,0x21]
> + ! CHECK fmovsl %xcc, %f1, %f2 ! encoding: [0x85,0xa8,0xf0,0x21]
> + ! CHECK fmovsgu %xcc, %f1, %f2 ! encoding: [0x85,0xab,0x30,0x21]
> + ! CHECK fmovsleu %xcc, %f1, %f2 ! encoding: [0x85,0xa9,0x30,0x21]
> + ! CHECK fmovscc %xcc, %f1, %f2 ! encoding: [0x85,0xab,0x70,0x21]
> + ! CHECK fmovscs %xcc, %f1, %f2 ! encoding: [0x85,0xa9,0x70,0x21]
> + ! CHECK fmovspos %xcc, %f1, %f2 ! encoding: [0x85,0xab,0xb0,0x21]
> + ! CHECK fmovsneg %xcc, %f1, %f2 ! encoding: [0x85,0xa9,0xb0,0x21]
> + ! CHECK fmovsvc %xcc, %f1, %f2 ! encoding: [0x85,0xab,0xf0,0x21]
> + ! CHECK fmovsvs %xcc, %f1, %f2 ! encoding: [0x85,0xa9,0xf0,0x21]
> + fmovsne %xcc, %f1, %f2
> + fmovse %xcc, %f1, %f2
> + fmovsg %xcc, %f1, %f2
> + fmovsle %xcc, %f1, %f2
> + fmovsge %xcc, %f1, %f2
> + fmovsl %xcc, %f1, %f2
> + fmovsgu %xcc, %f1, %f2
> + fmovsleu %xcc, %f1, %f2
> + fmovscc %xcc, %f1, %f2
> + fmovscs %xcc, %f1, %f2
> + fmovspos %xcc, %f1, %f2
> + fmovsneg %xcc, %f1, %f2
> + fmovsvc %xcc, %f1, %f2
> + fmovsvs %xcc, %f1, %f2
> +
> + ! CHECK fmovsu %fcc0, %f1, %f2 ! encoding: [0x85,0xa9,0xc0,0x21]
> + ! CHECK fmovsg %fcc0, %f1, %f2 ! encoding: [0x85,0xa9,0x80,0x21]
> + ! CHECK fmovsug %fcc0, %f1, %f2 ! encoding: [0x85,0xa9,0x40,0x21]
> + ! CHECK fmovsl %fcc0, %f1, %f2 ! encoding: [0x85,0xa9,0x00,0x21]
> + ! CHECK fmovsul %fcc0, %f1, %f2 ! encoding: [0x85,0xa8,0xc0,0x21]
> + ! CHECK fmovslg %fcc0, %f1, %f2 ! encoding: [0x85,0xa8,0x80,0x21]
> + ! CHECK fmovsne %fcc0, %f1, %f2 ! encoding: [0x85,0xa8,0x40,0x21]
> + ! CHECK fmovse %fcc0, %f1, %f2 ! encoding: [0x85,0xaa,0x40,0x21]
> + ! CHECK fmovsue %fcc0, %f1, %f2 ! encoding: [0x85,0xaa,0x80,0x21]
> + ! CHECK fmovsge %fcc0, %f1, %f2 ! encoding: [0x85,0xaa,0xc0,0x21]
> + ! CHECK fmovsuge %fcc0, %f1, %f2 ! encoding: [0x85,0xab,0x00,0x21]
> + ! CHECK fmovsle %fcc0, %f1, %f2 ! encoding: [0x85,0xab,0x40,0x21]
> + ! CHECK fmovsule %fcc0, %f1, %f2 ! encoding: [0x85,0xab,0x80,0x21]
> + ! CHECK fmovso %fcc0, %f1, %f2 ! encoding: [0x85,0xab,0xc0,0x21]
> + fmovsu %fcc0, %f1, %f2
> + fmovsg %fcc0, %f1, %f2
> + fmovsug %fcc0, %f1, %f2
> + fmovsl %fcc0, %f1, %f2
> + fmovsul %fcc0, %f1, %f2
> + fmovslg %fcc0, %f1, %f2
> + fmovsne %fcc0, %f1, %f2
> + fmovse %fcc0, %f1, %f2
> + fmovsue %fcc0, %f1, %f2
> + fmovsge %fcc0, %f1, %f2
> + fmovsuge %fcc0, %f1, %f2
> + fmovsle %fcc0, %f1, %f2
> + fmovsule %fcc0, %f1, %f2
> + fmovso %fcc0, %f1, %f2
> +
> Index: .
> ===================================================================
> --- . (revision 201091)
> +++ . (working copy)
>
> Property changes on: .
> ___________________________________________________________________
> Modified: svn:mergeinfo
> Merged /llvm/trunk:r198028-198030,198145,198149,198157,198280-198281,198286,198480,198484,198533,198565,198567,198580,198591-198592,198658,198681,198738-198740,198893,198909-198910,199014,199024,199028,199031,199033,199061,199186-199187,199775,199781,199786,199940,199974-199975,199977,200103-200104,200112,200130-200131,200141,200282,200368,200373,200376,200509,200617,200960-200963,200965
> Index: lib/Basic/Targets.cpp
> ===================================================================
> --- lib/Basic/Targets.cpp (revision 201091)
> +++ lib/Basic/Targets.cpp (working copy)
> @@ -4529,6 +4529,13 @@
> UIntMaxType = UnsignedLong;
> }
> Int64Type = IntMaxType;
> +
> + // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
> + // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
> + LongDoubleWidth = 128;
> + LongDoubleAlign = 128;
> + LongDoubleFormat = &llvm::APFloat::IEEEquad;
> + MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
> }
>
> virtual void getTargetDefines(const LangOptions &Opts,
> Index: lib/CodeGen/TargetInfo.cpp
> ===================================================================
> --- lib/CodeGen/TargetInfo.cpp (revision 201091)
> +++ lib/CodeGen/TargetInfo.cpp (working copy)
> @@ -5349,6 +5349,11 @@
> if (!isAggregateTypeForABI(Ty))
> return ABIArgInfo::getDirect();
>
> + // If a C++ object has either a non-trivial copy constructor or a non-trivial
> + // destructor, it is passed with an explicit indirect pointer / sret pointer.
> + if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
> + return ABIArgInfo::getIndirect(0, RAA == CGCXXABI::RAA_DirectInMemory);
> +
> // This is a small aggregate type that should be passed in registers.
> // Build a coercion type from the LLVM struct type.
> llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
> Index: lib/Driver/ToolChains.cpp
> ===================================================================
> --- lib/Driver/ToolChains.cpp (revision 201091)
> +++ lib/Driver/ToolChains.cpp (working copy)
> @@ -1164,6 +1164,13 @@
> "powerpc64le-suse-linux",
> "ppc64le-redhat-linux" };
>
> + static const char *const SPARCv8LibDirs[] = { "/lib32", "/lib" };
> + static const char *const SPARCv8Triples[] = { "sparc-linux-gnu",
> + "sparcv8-linux-gnu" };
> + static const char *const SPARCv9LibDirs[] = { "/lib64", "/lib" };
> + static const char *const SPARCv9Triples[] = { "sparc64-linux-gnu",
> + "sparcv9-linux-gnu" };
> +
> static const char *const SystemZLibDirs[] = { "/lib64", "/lib" };
> static const char *const SystemZTriples[] = {
> "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu",
> @@ -1283,6 +1290,26 @@
> TripleAliases.append(PPC64LETriples,
> PPC64LETriples + llvm::array_lengthof(PPC64LETriples));
> break;
> + case llvm::Triple::sparc:
> + LibDirs.append(SPARCv8LibDirs,
> + SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs));
> + TripleAliases.append(SPARCv8Triples,
> + SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples));
> + BiarchLibDirs.append(SPARCv9LibDirs,
> + SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs));
> + BiarchTripleAliases.append(
> + SPARCv9Triples, SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples));
> + break;
> + case llvm::Triple::sparcv9:
> + LibDirs.append(SPARCv9LibDirs,
> + SPARCv9LibDirs + llvm::array_lengthof(SPARCv9LibDirs));
> + TripleAliases.append(SPARCv9Triples,
> + SPARCv9Triples + llvm::array_lengthof(SPARCv9Triples));
> + BiarchLibDirs.append(SPARCv8LibDirs,
> + SPARCv8LibDirs + llvm::array_lengthof(SPARCv8LibDirs));
> + BiarchTripleAliases.append(
> + SPARCv8Triples, SPARCv8Triples + llvm::array_lengthof(SPARCv8Triples));
> + break;
> case llvm::Triple::systemz:
> LibDirs.append(SystemZLibDirs,
> SystemZLibDirs + llvm::array_lengthof(SystemZLibDirs));
> @@ -1379,6 +1406,7 @@
> Suffix = "/n32";
> else if (TargetArch == llvm::Triple::x86_64 ||
> TargetArch == llvm::Triple::ppc64 ||
> + TargetArch == llvm::Triple::sparcv9 ||
> TargetArch == llvm::Triple::systemz ||
> TargetArch == llvm::Triple::mips64 ||
> TargetArch == llvm::Triple::mips64el)
> Index: lib/Driver/Tools.cpp
> ===================================================================
> --- lib/Driver/Tools.cpp (revision 201091)
> +++ lib/Driver/Tools.cpp (working copy)
> @@ -5784,6 +5784,19 @@
> default:
> CmdArgs.push_back("-matpcs");
> }
> + } else if (getToolChain().getArch() == llvm::Triple::sparc ||
> + getToolChain().getArch() == llvm::Triple::sparcv9) {
> + Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
> + options::OPT_fpic, options::OPT_fno_pic,
> + options::OPT_fPIE, options::OPT_fno_PIE,
> + options::OPT_fpie, options::OPT_fno_pie);
> + if (LastPICArg &&
> + (LastPICArg->getOption().matches(options::OPT_fPIC) ||
> + LastPICArg->getOption().matches(options::OPT_fpic) ||
> + LastPICArg->getOption().matches(options::OPT_fPIE) ||
> + LastPICArg->getOption().matches(options::OPT_fpie))) {
> + CmdArgs.push_back("-KPIC");
> + }
> }
>
> Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
> @@ -6193,6 +6206,7 @@
> const ArgList &Args,
> const char *LinkingOutput) const {
> ArgStringList CmdArgs;
> + bool NeedsKPIC = false;
>
> // Add --32/--64 to make sure we get the format we want.
> // This is incomplete
> @@ -6212,6 +6226,14 @@
> CmdArgs.push_back("-a64");
> CmdArgs.push_back("-mppc64le");
> CmdArgs.push_back("-many");
> + } else if (getToolChain().getArch() == llvm::Triple::sparc) {
> + CmdArgs.push_back("-32");
> + CmdArgs.push_back("-Av8plusa");
> + NeedsKPIC = true;
> + } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
> + CmdArgs.push_back("-64");
> + CmdArgs.push_back("-Av9a");
> + NeedsKPIC = true;
> } else if (getToolChain().getArch() == llvm::Triple::arm) {
> StringRef MArch = getToolChain().getArchName();
> if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
> @@ -6271,6 +6293,15 @@
> CmdArgs.push_back(Args.MakeArgString("-mmsa"));
> }
>
> + NeedsKPIC = true;
> + } else if (getToolChain().getArch() == llvm::Triple::systemz) {
> + // Always pass an -march option, since our default of z10 is later
> + // than the GNU assembler's default.
> + StringRef CPUName = getSystemZTargetCPU(Args);
> + CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
> + }
> +
> + if (NeedsKPIC) {
> Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
> options::OPT_fpic, options::OPT_fno_pic,
> options::OPT_fPIE, options::OPT_fno_PIE,
> @@ -6282,11 +6313,6 @@
> LastPICArg->getOption().matches(options::OPT_fpie))) {
> CmdArgs.push_back("-KPIC");
> }
> - } else if (getToolChain().getArch() == llvm::Triple::systemz) {
> - // Always pass an -march option, since our default of z10 is later
> - // than the GNU assembler's default.
> - StringRef CPUName = getSystemZTargetCPU(Args);
> - CmdArgs.push_back(Args.MakeArgString("-march=" + CPUName));
> }
>
> Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
> @@ -6356,7 +6382,8 @@
> const toolchains::Linux &ToolChain) {
> if (ToolChain.getTriple().getEnvironment() == llvm::Triple::Android)
> return "/system/bin/linker";
> - else if (ToolChain.getArch() == llvm::Triple::x86)
> + else if (ToolChain.getArch() == llvm::Triple::x86 ||
> + ToolChain.getArch() == llvm::Triple::sparc)
> return "/lib/ld-linux.so.2";
> else if (ToolChain.getArch() == llvm::Triple::aarch64)
> return "/lib/ld-linux-aarch64.so.1";
> @@ -6381,6 +6408,8 @@
> ToolChain.getArch() == llvm::Triple::ppc64le ||
> ToolChain.getArch() == llvm::Triple::systemz)
> return "/lib64/ld64.so.1";
> + else if (ToolChain.getArch() == llvm::Triple::sparcv9)
> + return "/lib64/ld-linux.so.2";
> else
> return "/lib64/ld-linux-x86-64.so.2";
> }
> @@ -6443,6 +6472,10 @@
> CmdArgs.push_back("elf32ppclinux");
> else if (ToolChain.getArch() == llvm::Triple::ppc64)
> CmdArgs.push_back("elf64ppc");
> + else if (ToolChain.getArch() == llvm::Triple::sparc)
> + CmdArgs.push_back("elf32_sparc");
> + else if (ToolChain.getArch() == llvm::Triple::sparcv9)
> + CmdArgs.push_back("elf64_sparc");
> else if (ToolChain.getArch() == llvm::Triple::mips)
> CmdArgs.push_back("elf32btsmip");
> else if (ToolChain.getArch() == llvm::Triple::mipsel)
> Index: test/CodeGen/sparcv9-abi.c
> ===================================================================
> --- test/CodeGen/sparcv9-abi.c (revision 201091)
> +++ test/CodeGen/sparcv9-abi.c (working copy)
> @@ -18,6 +18,9 @@
> // CHECK-LABEL: define signext i8 @f_int_4(i8 signext %x)
> char f_int_4(char x) { return x; }
>
> +// CHECK-LABEL: define fp128 @f_ld(fp128 %x)
> +long double f_ld(long double x) { return x; }
> +
> // Small structs are passed in registers.
> struct small {
> int *a, *b;
> Index: test/CodeGen/sret.c
> ===================================================================
> --- test/CodeGen/sret.c (revision 201091)
> +++ test/CodeGen/sret.c (working copy)
> @@ -4,6 +4,8 @@
> long a;
> long b;
> long c;
> + long d;
> + long e;
> };
>
> struct abc foo1(void);
> Index: test/CodeGen/sret2.c
> ===================================================================
> --- test/CodeGen/sret2.c (revision 201091)
> +++ test/CodeGen/sret2.c (working copy)
> @@ -4,6 +4,8 @@
> long a;
> long b;
> long c;
> + long d;
> + long e;
> };
>
> struct abc foo2(){}
> Index: test/CodeGenCXX/sparcv9-abi.cpp
> ===================================================================
> --- test/CodeGenCXX/sparcv9-abi.cpp (revision 0)
> +++ test/CodeGenCXX/sparcv9-abi.cpp (working copy)
> @@ -0,0 +1,26 @@
> +// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
> +
> +struct pod {
> + int a, b;
> +};
> +
> +void f0();
> +void f1(struct pod);
> +
> +struct notpod {
> + int a, b;
> + ~notpod() { f0(); }
> +};
> +
> +void f2(struct notpod);
> +
> +// CHECK-LABEL: caller
> +// CHECK: call void @_Z2f13pod(i64
> +// CHECK: call void @_Z2f26notpod(%struct.notpod*
> +void caller()
> +{
> + pod p1;
> + notpod p2;
> + f1(p1);
> + f2(p2);
> +}
> Index: test/Driver/linux-as.c
> ===================================================================
> --- test/Driver/linux-as.c (revision 201091)
> +++ test/Driver/linux-as.c (working copy)
> @@ -60,6 +60,32 @@
> // RUN: | FileCheck -check-prefix=CHECK-PPC-NO-MCPU %s
> // CHECK-PPC-NO-MCPU-NOT: as{{.*}} "-mcpu=invalid-cpu"
> //
> +// RUN: %clang -target sparc64-linux -mcpu=invalid-cpu -### \
> +// RUN: -no-integrated-as -c %s 2>&1 \
> +// RUN: | FileCheck -check-prefix=CHECK-SPARCV9 %s
> +// CHECK-SPARCV9: as
> +// CHECK-SPARCV9: -64
> +// CHECK-SPARCV9: -Av9a
> +// CHECK-SPARCV9-NOT: -KPIC
> +// CHECK-SPARCV9: -o
> +//
> +// RUN: %clang -target sparc64-linux -mcpu=invalid-cpu -### \
> +// RUN: -no-integrated-as -fpic -c %s 2>&1 \
> +// RUN: | FileCheck -check-prefix=CHECK-SPARCV9PIC %s
> +// CHECK-SPARCV9PIC: as
> +// CHECK-SPARCV9PIC: -64
> +// CHECK-SPARCV9PIC: -Av9a
> +// CHECK-SPARCV9PIC: -KPIC
> +// CHECK-SPARCV9PIC: -o
> +//
> +// RUN: %clang -target sparc-linux -mcpu=invalid-cpu -### \
> +// RUN: -no-integrated-as -c %s 2>&1 \
> +// RUN: | FileCheck -check-prefix=CHECK-SPARCV8 %s
> +// CHECK-SPARCV8: as
> +// CHECK-SPARCV8: -32
> +// CHECK-SPARCV8: -Av8plusa
> +// CHECK-SPARCV8: -o
> +//
> // RUN: %clang -target s390x-linux -### -no-integrated-as -c %s 2>&1 \
> // RUN: | FileCheck -check-prefix=CHECK-Z-DEFAULT-ARCH %s
> // CHECK-Z-DEFAULT-ARCH: as{{.*}} "-march=z10"
> Index: test/Driver/linux-ld.c
> ===================================================================
> --- test/Driver/linux-ld.c (revision 201091)
> +++ test/Driver/linux-ld.c (working copy)
> @@ -384,6 +384,20 @@
> // CHECK-MIPS64EL-N32: "-dynamic-linker" "{{.*}}/lib32/ld.so.1"
> // CHECK-MIPS64EL-N32-NOT: "--hash-style={{gnu|both}}"
> //
> +// RUN: %clang %s -### -o %t.o 2>&1 \
> +// RUN: --target=sparc-linux-gnu \
> +// RUN: | FileCheck --check-prefix=CHECK-SPARCV8 %s
> +// CHECK-SPARCV8: "{{.*}}ld{{(.exe)?}}"
> +// CHECK-SPARCV8: "-m" "elf32_sparc"
> +// CHECK-SPARCV8: "-dynamic-linker" "/lib/ld-linux.so.2"
> +//
> +// RUN: %clang %s -### -o %t.o 2>&1 \
> +// RUN: --target=sparcv9-linux-gnu \
> +// RUN: | FileCheck --check-prefix=CHECK-SPARCV9 %s
> +// CHECK-SPARCV9: "{{.*}}ld{{(.exe)?}}"
> +// CHECK-SPARCV9: "-m" "elf64_sparc"
> +// CHECK-SPARCV9: "-dynamic-linker" "/lib64/ld-linux.so.2"
> +//
> // Thoroughly exercise the Debian multiarch environment.
> // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
> // RUN: --target=i686-linux-gnu \
> Index: .
> ===================================================================
> --- . (revision 201091)
> +++ . (working copy)
>
> Property changes on: .
> ___________________________________________________________________
> Modified: svn:mergeinfo
> Merged /cfe/trunk:r198311-198312,198911-198912,198918,198923,199012,199034,199037,199188,199399,200452
More information about the llvm-commits
mailing list