[PATCH]: llvm 3.4.1 sparc64 selfhosting patches

Tom Stellard tom at stellard.net
Tue Feb 11 14:58:19 PST 2014


On Tue, Feb 11, 2014 at 08:26:43PM +0100, Roman Divacky wrote:
> 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).
> 

Under the current stable patch rules this change is too big.  It also
looks like it might change the ABI with the addition of all the new
classes (though I'm not an ABI export so I could be wrong).

How big would the patchset be if you did not include the MCization
changes?

-Tom

P.S. It looks like there is a spurious change to the ARM backend in your
patch.
> 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