[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 &region,
> +                                      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 &region,
> +                                      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