mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
Cleanup patch set, and update README.TXT. Add three new patches.
This commit is contained in:
parent
59d1ed5b20
commit
2778984cca
120 changed files with 906 additions and 18965 deletions
|
|
@ -1,11 +1,11 @@
|
|||
This is a set of individual patches, which contain all the customizations to
|
||||
llvm/clang currently in the FreeBSD base system. These can be applied in
|
||||
alphabetical order to a pristine llvm/clang 3.4 release source tree, for example
|
||||
by doing:
|
||||
alphabetical order to a pristine llvm/clang 3.5.0 release source tree, for
|
||||
example by doing:
|
||||
|
||||
svn co https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_34/final llvm-3.4-final
|
||||
svn co https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_34/final llvm-3.4-final/tools/clang
|
||||
cd llvm-3.4-final
|
||||
svn co https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_350/final llvm-3.5.0-final
|
||||
svn co https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_350/final llvm-3.5.0-final/tools/clang
|
||||
cd llvm-3.5.0-final
|
||||
for p in /usr/src/contrib/llvm/patches/patch-*.diff; do
|
||||
patch -p0 -f -F0 -E -i $p -s || break
|
||||
done
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
This patch adjusts clang's default include paths to add FreeBSD-specific
|
||||
directories.
|
||||
This patch adjusts clang's default include path add a FreeBSD base system
|
||||
specific directory.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/208961
|
||||
|
||||
|
|
@ -15,25 +15,13 @@ Index: tools/clang/lib/Frontend/InitHeaderSearch.cpp
|
|||
#include "clang/Config/config.h" // C_INCLUDE_DIRS
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/HeaderSearchOptions.h"
|
||||
@@ -333,6 +334,9 @@ void InitHeaderSearch::AddDefaultCIncludePaths(con
|
||||
#endif
|
||||
@@ -336,6 +337,9 @@ void InitHeaderSearch::AddDefaultCIncludePaths(con
|
||||
break;
|
||||
}
|
||||
break;
|
||||
+ case llvm::Triple::FreeBSD:
|
||||
+ AddPath("/usr/include/clang/" CLANG_VERSION_STRING, System, false);
|
||||
+ break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -423,11 +427,6 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple
|
||||
else
|
||||
AddPath("/usr/include/c++/4.4", CXXSystem, false);
|
||||
break;
|
||||
- case llvm::Triple::FreeBSD:
|
||||
- // FreeBSD 8.0
|
||||
- // FreeBSD 7.3
|
||||
- AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
|
||||
- break;
|
||||
case llvm::Triple::OpenBSD: {
|
||||
std::string t = triple.getTriple();
|
||||
if (t.substr(0, 6) == "x86_64")
|
||||
}
|
||||
|
|
@ -3,12 +3,110 @@ which enables additional printf modifiers for the kernel.
|
|||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/208987
|
||||
|
||||
Index: tools/clang/include/clang/Driver/Options.td
|
||||
===================================================================
|
||||
--- tools/clang/include/clang/Driver/Options.td
|
||||
+++ tools/clang/include/clang/Driver/Options.td
|
||||
@@ -563,6 +563,8 @@ def fno_rewrite_includes : Flag<["-"], "fno-rewrit
|
||||
|
||||
def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Assert that the compilation takes place in a freestanding environment">;
|
||||
+def fformat_extensions: Flag<["-"], "fformat-extensions">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
+ HelpText<"Enable FreeBSD kernel specific format string extensions">;
|
||||
def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Allow GNU-extension keywords regardless of language standard">;
|
||||
def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
Index: tools/clang/include/clang/Basic/LangOptions.def
|
||||
===================================================================
|
||||
--- tools/clang/include/clang/Basic/LangOptions.def
|
||||
+++ tools/clang/include/clang/Basic/LangOptions.def
|
||||
@@ -87,6 +87,7 @@ LANGOPT(RTTI , 1, 1, "run-time type i
|
||||
LANGOPT(RTTIData , 1, 1, "emit run-time type information data")
|
||||
LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout")
|
||||
LANGOPT(Freestanding, 1, 0, "freestanding implementation")
|
||||
+LANGOPT(FormatExtensions , 1, 0, "FreeBSD format extensions")
|
||||
LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
|
||||
LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
|
||||
|
||||
Index: tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
||||
===================================================================
|
||||
--- tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
||||
+++ tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
||||
@@ -158,6 +158,11 @@ class ConversionSpecifier {
|
||||
ObjCObjArg, // '@'
|
||||
ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
|
||||
|
||||
+ // FreeBSD specific specifiers
|
||||
+ FreeBSDbArg,
|
||||
+ FreeBSDDArg,
|
||||
+ FreeBSDrArg,
|
||||
+
|
||||
// GlibC specific specifiers.
|
||||
PrintErrno, // 'm'
|
||||
|
||||
Index: tools/clang/lib/Sema/SemaChecking.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Sema/SemaChecking.cpp
|
||||
+++ tools/clang/lib/Sema/SemaChecking.cpp
|
||||
@@ -3074,6 +3074,40 @@ CheckPrintfHandler::HandlePrintfSpecifier(const an
|
||||
CoveredArgs.set(argIndex);
|
||||
}
|
||||
|
||||
+ // FreeBSD extensions
|
||||
+ if (CS.getKind() == ConversionSpecifier::FreeBSDbArg ||
|
||||
+ CS.getKind() == ConversionSpecifier::FreeBSDDArg) {
|
||||
+ // claim the second argument
|
||||
+ CoveredArgs.set(argIndex + 1);
|
||||
+
|
||||
+ // Now type check the data expression that matches the
|
||||
+ // format specifier.
|
||||
+ const Expr *Ex = getDataArg(argIndex);
|
||||
+ const analyze_printf::ArgType &AT =
|
||||
+ (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ?
|
||||
+ ArgType(S.Context.IntTy) : ArgType::CStrTy;
|
||||
+ if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
|
||||
+ S.Diag(getLocationOfByte(CS.getStart()),
|
||||
+ diag::warn_format_conversion_argument_type_mismatch)
|
||||
+ << AT.getRepresentativeType(S.Context) << Ex->getType()
|
||||
+ << getSpecifierRange(startSpecifier, specifierLen)
|
||||
+ << Ex->getSourceRange();
|
||||
+
|
||||
+ // Now type check the data expression that matches the
|
||||
+ // format specifier.
|
||||
+ Ex = getDataArg(argIndex + 1);
|
||||
+ const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
|
||||
+ if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
|
||||
+ S.Diag(getLocationOfByte(CS.getStart()),
|
||||
+ diag::warn_format_conversion_argument_type_mismatch)
|
||||
+ << AT2.getRepresentativeType(S.Context) << Ex->getType()
|
||||
+ << getSpecifierRange(startSpecifier, specifierLen)
|
||||
+ << Ex->getSourceRange();
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+ // END OF FREEBSD EXTENSIONS
|
||||
+
|
||||
// Check for using an Objective-C specific conversion specifier
|
||||
// in a non-ObjC literal.
|
||||
if (!ObjCContext && CS.isObjCArg()) {
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -3517,6 +3517,7 @@ void Clang::ConstructJob(Compilation &C, const Job
|
||||
|
||||
// Forward -f (flag) options which we can pass directly.
|
||||
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
|
||||
+ Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions);
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fstandalone_debug);
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fno_standalone_debug);
|
||||
Index: tools/clang/lib/Frontend/CompilerInvocation.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Frontend/CompilerInvocation.cpp
|
||||
+++ tools/clang/lib/Frontend/CompilerInvocation.cpp
|
||||
@@ -1319,6 +1319,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgLi
|
||||
Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
|
||||
@@ -1443,6 +1443,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgLi
|
||||
Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
|
||||
Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
|
||||
Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
|
||||
+ Opts.FormatExtensions = Args.hasArg(OPT_fformat_extensions);
|
||||
|
|
@ -114,101 +212,3 @@ Index: tools/clang/lib/Analysis/PrintfFormatString.cpp
|
|||
return true;
|
||||
|
||||
default:
|
||||
Index: tools/clang/lib/Sema/SemaChecking.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Sema/SemaChecking.cpp
|
||||
+++ tools/clang/lib/Sema/SemaChecking.cpp
|
||||
@@ -2980,6 +2980,40 @@ CheckPrintfHandler::HandlePrintfSpecifier(const an
|
||||
CoveredArgs.set(argIndex);
|
||||
}
|
||||
|
||||
+ // FreeBSD extensions
|
||||
+ if (CS.getKind() == ConversionSpecifier::FreeBSDbArg ||
|
||||
+ CS.getKind() == ConversionSpecifier::FreeBSDDArg) {
|
||||
+ // claim the second argument
|
||||
+ CoveredArgs.set(argIndex + 1);
|
||||
+
|
||||
+ // Now type check the data expression that matches the
|
||||
+ // format specifier.
|
||||
+ const Expr *Ex = getDataArg(argIndex);
|
||||
+ const analyze_printf::ArgType &AT =
|
||||
+ (CS.getKind() == ConversionSpecifier::FreeBSDbArg) ?
|
||||
+ ArgType(S.Context.IntTy) : ArgType::CStrTy;
|
||||
+ if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
|
||||
+ S.Diag(getLocationOfByte(CS.getStart()),
|
||||
+ diag::warn_printf_conversion_argument_type_mismatch)
|
||||
+ << AT.getRepresentativeType(S.Context) << Ex->getType()
|
||||
+ << getSpecifierRange(startSpecifier, specifierLen)
|
||||
+ << Ex->getSourceRange();
|
||||
+
|
||||
+ // Now type check the data expression that matches the
|
||||
+ // format specifier.
|
||||
+ Ex = getDataArg(argIndex + 1);
|
||||
+ const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
|
||||
+ if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
|
||||
+ S.Diag(getLocationOfByte(CS.getStart()),
|
||||
+ diag::warn_printf_conversion_argument_type_mismatch)
|
||||
+ << AT2.getRepresentativeType(S.Context) << Ex->getType()
|
||||
+ << getSpecifierRange(startSpecifier, specifierLen)
|
||||
+ << Ex->getSourceRange();
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+ // END OF FREEBSD EXTENSIONS
|
||||
+
|
||||
// Check for using an Objective-C specific conversion specifier
|
||||
// in a non-ObjC literal.
|
||||
if (!ObjCContext && CS.isObjCArg()) {
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -2991,6 +2991,7 @@ void Clang::ConstructJob(Compilation &C, const Job
|
||||
|
||||
// Forward -f (flag) options which we can pass directly.
|
||||
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
|
||||
+ Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions);
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
|
||||
Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
|
||||
Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);
|
||||
Index: tools/clang/include/clang/Basic/LangOptions.def
|
||||
===================================================================
|
||||
--- tools/clang/include/clang/Basic/LangOptions.def
|
||||
+++ tools/clang/include/clang/Basic/LangOptions.def
|
||||
@@ -84,6 +84,7 @@ LANGOPT(TraditionalCPP , 1, 0, "traditional CPP
|
||||
LANGOPT(RTTI , 1, 1, "run-time type information")
|
||||
LANGOPT(MSBitfields , 1, 0, "Microsoft-compatible structure layout")
|
||||
LANGOPT(Freestanding, 1, 0, "freestanding implementation")
|
||||
+LANGOPT(FormatExtensions , 1, 0, "FreeBSD format extensions")
|
||||
LANGOPT(NoBuiltin , 1, 0, "disable builtin functions")
|
||||
LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")
|
||||
|
||||
Index: tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
||||
===================================================================
|
||||
--- tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
||||
+++ tools/clang/include/clang/Analysis/Analyses/FormatString.h
|
||||
@@ -158,6 +158,11 @@ class ConversionSpecifier {
|
||||
ObjCObjArg, // '@'
|
||||
ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
|
||||
|
||||
+ // FreeBSD specific specifiers
|
||||
+ FreeBSDbArg,
|
||||
+ FreeBSDDArg,
|
||||
+ FreeBSDrArg,
|
||||
+
|
||||
// GlibC specific specifiers.
|
||||
PrintErrno, // 'm'
|
||||
|
||||
Index: tools/clang/include/clang/Driver/Options.td
|
||||
===================================================================
|
||||
--- tools/clang/include/clang/Driver/Options.td
|
||||
+++ tools/clang/include/clang/Driver/Options.td
|
||||
@@ -530,6 +530,8 @@ def fno_rewrite_includes : Flag<["-"], "fno-rewrit
|
||||
|
||||
def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Assert that the compilation takes place in a freestanding environment">;
|
||||
+def fformat_extensions: Flag<["-"], "fformat-extensions">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
+ HelpText<"Enable FreeBSD kernel specific format string extensions">;
|
||||
def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Allow GNU-extension keywords regardless of language standard">;
|
||||
def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
|
|
@ -8,8 +8,8 @@ Index: tools/clang/lib/Basic/Version.cpp
|
|||
===================================================================
|
||||
--- tools/clang/lib/Basic/Version.cpp
|
||||
+++ tools/clang/lib/Basic/Version.cpp
|
||||
@@ -124,8 +124,10 @@ std::string getClangFullVersion() {
|
||||
OS << "clang version " CLANG_VERSION_STRING " "
|
||||
@@ -128,8 +128,10 @@ std::string getClangToolFullVersion(StringRef Tool
|
||||
OS << ToolName << " version " CLANG_VERSION_STRING " "
|
||||
<< getClangFullRepositoryVersion();
|
||||
|
||||
+#ifdef CLANG_VENDOR_SUFFIX
|
||||
|
|
@ -17,6 +17,6 @@ Index: tools/clang/lib/Basic/Version.cpp
|
|||
+#elif defined(CLANG_VENDOR)
|
||||
// If vendor supplied, include the base LLVM version as well.
|
||||
-#ifdef CLANG_VENDOR
|
||||
OS << " (based on LLVM " << PACKAGE_VERSION << ")";
|
||||
OS << " (based on " << BACKEND_PACKAGE_STRING << ")";
|
||||
#endif
|
||||
|
||||
|
|
@ -21,6 +21,6 @@ Index: lib/Support/Unix/Host.inc
|
|||
|
||||
@@ -61,3 +66,4 @@ std::string sys::getDefaultTargetTriple() {
|
||||
|
||||
return Triple;
|
||||
return Triple::normalize(Triple);
|
||||
}
|
||||
+#endif // __FreeBSD__
|
||||
|
|
@ -7,19 +7,17 @@ Index: tools/clang/tools/driver/driver.cpp
|
|||
===================================================================
|
||||
--- tools/clang/tools/driver/driver.cpp
|
||||
+++ tools/clang/tools/driver/driver.cpp
|
||||
@@ -215,6 +215,7 @@ static void ParseProgName(SmallVectorImpl<const ch
|
||||
} suffixes [] = {
|
||||
{ "clang", 0 },
|
||||
@@ -217,11 +217,13 @@ static void ParseProgName(SmallVectorImpl<const ch
|
||||
{ "clang", nullptr },
|
||||
{ "clang++", "--driver-mode=g++" },
|
||||
+ { "clang-CC", "--driver-mode=g++" },
|
||||
{ "clang-c++", "--driver-mode=g++" },
|
||||
{ "clang-cc", 0 },
|
||||
+ { "clang-CC", "--driver-mode=g++" },
|
||||
{ "clang-cc", nullptr },
|
||||
{ "clang-cpp", "--driver-mode=cpp" },
|
||||
@@ -221,6 +222,7 @@ static void ParseProgName(SmallVectorImpl<const ch
|
||||
{ "clang-g++", "--driver-mode=g++" },
|
||||
{ "clang-gcc", 0 },
|
||||
{ "clang-gcc", nullptr },
|
||||
{ "clang-cl", "--driver-mode=cl" },
|
||||
+ { "CC", "--driver-mode=g++" },
|
||||
{ "cc", 0 },
|
||||
{ "cc", nullptr },
|
||||
{ "cpp", "--driver-mode=cpp" },
|
||||
{ "cl" , "--driver-mode=cl" },
|
||||
20
contrib/llvm/patches/patch-06-clang-arm-target-cpu.diff
Normal file
20
contrib/llvm/patches/patch-06-clang-arm-target-cpu.diff
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
Pull in r217454 from upstream llvm trunk (by Ed Maste):
|
||||
|
||||
Use armv6k default for FreeBSD/ARM
|
||||
|
||||
Patch by Andrew Turner.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/269387
|
||||
|
||||
Index: lib/Support/Triple.cpp
|
||||
===================================================================
|
||||
--- lib/Support/Triple.cpp
|
||||
+++ lib/Support/Triple.cpp
|
||||
@@ -963,6 +963,7 @@ const char *Triple::getARMCPUForArch(StringRef MAr
|
||||
MArch = getArchName();
|
||||
|
||||
switch (getOS()) {
|
||||
+ case llvm::Triple::FreeBSD:
|
||||
case llvm::Triple::NetBSD:
|
||||
if (MArch == "armv6")
|
||||
return "arm1176jzf-s";
|
||||
547
contrib/llvm/patches/patch-07-llvm-r213960-ppc32-tls.diff
Normal file
547
contrib/llvm/patches/patch-07-llvm-r213960-ppc32-tls.diff
Normal file
|
|
@ -0,0 +1,547 @@
|
|||
Pull in r213960 from upstream llvm trunk (by Hal Finkel):
|
||||
|
||||
[PowerPC] Support TLS on PPC32/ELF
|
||||
|
||||
Patch by Justin Hibbits!
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/270147
|
||||
|
||||
Index: lib/Target/PowerPC/PPCISelLowering.h
|
||||
===================================================================
|
||||
--- lib/Target/PowerPC/PPCISelLowering.h
|
||||
+++ lib/Target/PowerPC/PPCISelLowering.h
|
||||
@@ -181,6 +181,10 @@ namespace llvm {
|
||||
/// on PPC32.
|
||||
PPC32_GOT,
|
||||
|
||||
+ /// GPRC = address of _GLOBAL_OFFSET_TABLE_. Used by general dynamic and
|
||||
+ /// local dynamic TLS on PPC32.
|
||||
+ PPC32_PICGOT,
|
||||
+
|
||||
/// G8RC = ADDIS_GOT_TPREL_HA %X2, Symbol - Used by the initial-exec
|
||||
/// TLS model, produces an ADDIS8 instruction that adds the GOT
|
||||
/// base to sym\@got\@tprel\@ha.
|
||||
Index: lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
|
||||
+++ lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
+#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetOpcodes.h"
|
||||
@@ -308,10 +309,16 @@ void PPCInstPrinter::printMemRegReg(const MCInst *
|
||||
|
||||
void PPCInstPrinter::printTLSCall(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
- printBranchOperand(MI, OpNo, O);
|
||||
+ // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must
|
||||
+ // come at the _end_ of the expression.
|
||||
+ const MCOperand &Op = MI->getOperand(OpNo);
|
||||
+ const MCSymbolRefExpr &refExp = cast<MCSymbolRefExpr>(*Op.getExpr());
|
||||
+ O << refExp.getSymbol().getName();
|
||||
O << '(';
|
||||
printOperand(MI, OpNo+1, O);
|
||||
O << ')';
|
||||
+ if (refExp.getKind() != MCSymbolRefExpr::VK_None)
|
||||
+ O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind());
|
||||
}
|
||||
|
||||
|
||||
Index: lib/Target/PowerPC/PPCInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/PowerPC/PPCInstrInfo.td
|
||||
+++ lib/Target/PowerPC/PPCInstrInfo.td
|
||||
@@ -588,6 +588,12 @@ def tlsreg32 : Operand<i32> {
|
||||
let EncoderMethod = "getTLSRegEncoding";
|
||||
let ParserMatchClass = PPCTLSRegOperand;
|
||||
}
|
||||
+def tlsgd32 : Operand<i32> {}
|
||||
+def tlscall32 : Operand<i32> {
|
||||
+ let PrintMethod = "printTLSCall";
|
||||
+ let MIOperandInfo = (ops calltarget:$func, tlsgd32:$sym);
|
||||
+ let EncoderMethod = "getTLSCallEncoding";
|
||||
+}
|
||||
|
||||
// PowerPC Predicate operand.
|
||||
def pred : Operand<OtherVT> {
|
||||
@@ -1071,6 +1077,8 @@ let isCall = 1, PPC970_Unit = 7, Defs = [LR] in {
|
||||
"bla $func", IIC_BrB, [(PPCcall (i32 imm:$func))]>;
|
||||
|
||||
let isCodeGenOnly = 1 in {
|
||||
+ def BL_TLS : IForm<18, 0, 1, (outs), (ins tlscall32:$func),
|
||||
+ "bl $func", IIC_BrB, []>;
|
||||
def BCCL : BForm<16, 0, 1, (outs), (ins pred:$cond, condbrtarget:$dst),
|
||||
"b${cond:cc}l${cond:pm} ${cond:reg}, $dst">;
|
||||
def BCCLA : BForm<16, 1, 1, (outs), (ins pred:$cond, abscondbrtarget:$dst),
|
||||
@@ -2396,13 +2404,45 @@ def : Pat<(add i32:$in, (PPChi tblockaddress:$g, 0
|
||||
def PPC32GOT: Pseudo<(outs gprc:$rD), (ins), "#PPC32GOT",
|
||||
[(set i32:$rD, (PPCppc32GOT))]>;
|
||||
|
||||
+// Get the _GLOBAL_OFFSET_TABLE_ in PIC mode.
|
||||
+// This uses two output registers, the first as the real output, the second as a
|
||||
+// temporary register, used internally in code generation.
|
||||
+def PPC32PICGOT: Pseudo<(outs gprc:$rD, gprc:$rT), (ins), "#PPC32PICGOT",
|
||||
+ []>, NoEncode<"$rT">;
|
||||
+
|
||||
def LDgotTprelL32: Pseudo<(outs gprc:$rD), (ins s16imm:$disp, gprc_nor0:$reg),
|
||||
- "#LDgotTprelL32",
|
||||
- [(set i32:$rD,
|
||||
- (PPCldGotTprelL tglobaltlsaddr:$disp, i32:$reg))]>;
|
||||
+ "#LDgotTprelL32",
|
||||
+ [(set i32:$rD,
|
||||
+ (PPCldGotTprelL tglobaltlsaddr:$disp, i32:$reg))]>;
|
||||
def : Pat<(PPCaddTls i32:$in, tglobaltlsaddr:$g),
|
||||
(ADD4TLS $in, tglobaltlsaddr:$g)>;
|
||||
|
||||
+def ADDItlsgdL32 : Pseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, s16imm:$disp),
|
||||
+ "#ADDItlsgdL32",
|
||||
+ [(set i32:$rD,
|
||||
+ (PPCaddiTlsgdL i32:$reg, tglobaltlsaddr:$disp))]>;
|
||||
+def GETtlsADDR32 : Pseudo<(outs gprc:$rD), (ins gprc:$reg, tlsgd32:$sym),
|
||||
+ "#GETtlsADDR32",
|
||||
+ [(set i32:$rD,
|
||||
+ (PPCgetTlsAddr i32:$reg, tglobaltlsaddr:$sym))]>;
|
||||
+def ADDItlsldL32 : Pseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, s16imm:$disp),
|
||||
+ "#ADDItlsldL32",
|
||||
+ [(set i32:$rD,
|
||||
+ (PPCaddiTlsldL i32:$reg, tglobaltlsaddr:$disp))]>;
|
||||
+def GETtlsldADDR32 : Pseudo<(outs gprc:$rD), (ins gprc:$reg, tlsgd32:$sym),
|
||||
+ "#GETtlsldADDR32",
|
||||
+ [(set i32:$rD,
|
||||
+ (PPCgetTlsldAddr i32:$reg, tglobaltlsaddr:$sym))]>;
|
||||
+def ADDIdtprelL32 : Pseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, s16imm:$disp),
|
||||
+ "#ADDIdtprelL32",
|
||||
+ [(set i32:$rD,
|
||||
+ (PPCaddiDtprelL i32:$reg, tglobaltlsaddr:$disp))]>;
|
||||
+def ADDISdtprelHA32 : Pseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, s16imm:$disp),
|
||||
+ "#ADDISdtprelHA32",
|
||||
+ [(set i32:$rD,
|
||||
+ (PPCaddisDtprelHA i32:$reg,
|
||||
+ tglobaltlsaddr:$disp))]>;
|
||||
+
|
||||
// Support for Position-independent code
|
||||
def LWZtoc: Pseudo<(outs gprc:$rD), (ins tocentry32:$disp, gprc:$reg),
|
||||
"#LWZtoc",
|
||||
Index: lib/Target/PowerPC/PPCISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/PowerPC/PPCISelLowering.cpp
|
||||
+++ lib/Target/PowerPC/PPCISelLowering.cpp
|
||||
@@ -1685,47 +1685,61 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(S
|
||||
|
||||
if (Model == TLSModel::GeneralDynamic) {
|
||||
SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0);
|
||||
- SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
|
||||
- SDValue GOTEntryHi = DAG.getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT,
|
||||
- GOTReg, TGA);
|
||||
+ SDValue GOTPtr;
|
||||
+ if (is64bit) {
|
||||
+ SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
|
||||
+ GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT,
|
||||
+ GOTReg, TGA);
|
||||
+ } else {
|
||||
+ GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT);
|
||||
+ }
|
||||
SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSGD_L, dl, PtrVT,
|
||||
- GOTEntryHi, TGA);
|
||||
+ GOTPtr, TGA);
|
||||
|
||||
// We need a chain node, and don't have one handy. The underlying
|
||||
// call has no side effects, so using the function entry node
|
||||
// suffices.
|
||||
SDValue Chain = DAG.getEntryNode();
|
||||
- Chain = DAG.getCopyToReg(Chain, dl, PPC::X3, GOTEntry);
|
||||
- SDValue ParmReg = DAG.getRegister(PPC::X3, MVT::i64);
|
||||
+ Chain = DAG.getCopyToReg(Chain, dl,
|
||||
+ is64bit ? PPC::X3 : PPC::R3, GOTEntry);
|
||||
+ SDValue ParmReg = DAG.getRegister(is64bit ? PPC::X3 : PPC::R3,
|
||||
+ is64bit ? MVT::i64 : MVT::i32);
|
||||
SDValue TLSAddr = DAG.getNode(PPCISD::GET_TLS_ADDR, dl,
|
||||
PtrVT, ParmReg, TGA);
|
||||
// The return value from GET_TLS_ADDR really is in X3 already, but
|
||||
// some hacks are needed here to tie everything together. The extra
|
||||
// copies dissolve during subsequent transforms.
|
||||
- Chain = DAG.getCopyToReg(Chain, dl, PPC::X3, TLSAddr);
|
||||
- return DAG.getCopyFromReg(Chain, dl, PPC::X3, PtrVT);
|
||||
+ Chain = DAG.getCopyToReg(Chain, dl, is64bit ? PPC::X3 : PPC::R3, TLSAddr);
|
||||
+ return DAG.getCopyFromReg(Chain, dl, is64bit ? PPC::X3 : PPC::R3, PtrVT);
|
||||
}
|
||||
|
||||
if (Model == TLSModel::LocalDynamic) {
|
||||
SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0);
|
||||
- SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
|
||||
- SDValue GOTEntryHi = DAG.getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT,
|
||||
- GOTReg, TGA);
|
||||
+ SDValue GOTPtr;
|
||||
+ if (is64bit) {
|
||||
+ SDValue GOTReg = DAG.getRegister(PPC::X2, MVT::i64);
|
||||
+ GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT,
|
||||
+ GOTReg, TGA);
|
||||
+ } else {
|
||||
+ GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT);
|
||||
+ }
|
||||
SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSLD_L, dl, PtrVT,
|
||||
- GOTEntryHi, TGA);
|
||||
+ GOTPtr, TGA);
|
||||
|
||||
// We need a chain node, and don't have one handy. The underlying
|
||||
// call has no side effects, so using the function entry node
|
||||
// suffices.
|
||||
SDValue Chain = DAG.getEntryNode();
|
||||
- Chain = DAG.getCopyToReg(Chain, dl, PPC::X3, GOTEntry);
|
||||
- SDValue ParmReg = DAG.getRegister(PPC::X3, MVT::i64);
|
||||
+ Chain = DAG.getCopyToReg(Chain, dl,
|
||||
+ is64bit ? PPC::X3 : PPC::R3, GOTEntry);
|
||||
+ SDValue ParmReg = DAG.getRegister(is64bit ? PPC::X3 : PPC::R3,
|
||||
+ is64bit ? MVT::i64 : MVT::i32);
|
||||
SDValue TLSAddr = DAG.getNode(PPCISD::GET_TLSLD_ADDR, dl,
|
||||
PtrVT, ParmReg, TGA);
|
||||
// The return value from GET_TLSLD_ADDR really is in X3 already, but
|
||||
// some hacks are needed here to tie everything together. The extra
|
||||
// copies dissolve during subsequent transforms.
|
||||
- Chain = DAG.getCopyToReg(Chain, dl, PPC::X3, TLSAddr);
|
||||
+ Chain = DAG.getCopyToReg(Chain, dl, is64bit ? PPC::X3 : PPC::R3, TLSAddr);
|
||||
SDValue DtvOffsetHi = DAG.getNode(PPCISD::ADDIS_DTPREL_HA, dl, PtrVT,
|
||||
Chain, ParmReg, TGA);
|
||||
return DAG.getNode(PPCISD::ADDI_DTPREL_L, dl, PtrVT, DtvOffsetHi, TGA);
|
||||
Index: lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
|
||||
+++ lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
|
||||
@@ -236,7 +236,10 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(con
|
||||
Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
|
||||
- Type = ELF::R_PPC64_GOT_TLSGD16;
|
||||
+ if (is64Bit())
|
||||
+ Type = ELF::R_PPC64_GOT_TLSGD16;
|
||||
+ else
|
||||
+ Type = ELF::R_PPC_GOT_TLSGD16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
|
||||
Type = ELF::R_PPC64_GOT_TLSGD16_LO;
|
||||
@@ -248,7 +251,10 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(con
|
||||
Type = ELF::R_PPC64_GOT_TLSGD16_HA;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
|
||||
- Type = ELF::R_PPC64_GOT_TLSLD16;
|
||||
+ if (is64Bit())
|
||||
+ Type = ELF::R_PPC64_GOT_TLSLD16;
|
||||
+ else
|
||||
+ Type = ELF::R_PPC_GOT_TLSLD16;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
|
||||
Type = ELF::R_PPC64_GOT_TLSLD16_LO;
|
||||
@@ -344,13 +350,22 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(con
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_PPC_TLSGD:
|
||||
- Type = ELF::R_PPC64_TLSGD;
|
||||
+ if (is64Bit())
|
||||
+ Type = ELF::R_PPC64_TLSGD;
|
||||
+ else
|
||||
+ Type = ELF::R_PPC_TLSGD;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TLSLD:
|
||||
- Type = ELF::R_PPC64_TLSLD;
|
||||
+ if (is64Bit())
|
||||
+ Type = ELF::R_PPC64_TLSLD;
|
||||
+ else
|
||||
+ Type = ELF::R_PPC_TLSLD;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PPC_TLS:
|
||||
- Type = ELF::R_PPC64_TLS;
|
||||
+ if (is64Bit())
|
||||
+ Type = ELF::R_PPC64_TLS;
|
||||
+ else
|
||||
+ Type = ELF::R_PPC_TLS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
Index: lib/Target/PowerPC/PPCAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/PowerPC/PPCAsmPrinter.cpp
|
||||
+++ lib/Target/PowerPC/PPCAsmPrinter.cpp
|
||||
@@ -573,6 +573,34 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
||||
return;
|
||||
}
|
||||
|
||||
+ case PPC::PPC32PICGOT: {
|
||||
+ MCSymbol *GOTSymbol = OutContext.GetOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
|
||||
+ MCSymbol *GOTRef = OutContext.CreateTempSymbol();
|
||||
+ MCSymbol *NextInstr = OutContext.CreateTempSymbol();
|
||||
+
|
||||
+ EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL)
|
||||
+ // FIXME: We would like an efficient form for this, so we don't have to do
|
||||
+ // a lot of extra uniquing.
|
||||
+ .addExpr(MCSymbolRefExpr::Create(NextInstr, OutContext)));
|
||||
+ const MCExpr *OffsExpr =
|
||||
+ MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(GOTSymbol, OutContext),
|
||||
+ MCSymbolRefExpr::Create(GOTRef, OutContext),
|
||||
+ OutContext);
|
||||
+ OutStreamer.EmitLabel(GOTRef);
|
||||
+ OutStreamer.EmitValue(OffsExpr, 4);
|
||||
+ OutStreamer.EmitLabel(NextInstr);
|
||||
+ EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MFLR)
|
||||
+ .addReg(MI->getOperand(0).getReg()));
|
||||
+ EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LWZ)
|
||||
+ .addReg(MI->getOperand(1).getReg())
|
||||
+ .addImm(0)
|
||||
+ .addReg(MI->getOperand(0).getReg()));
|
||||
+ EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADD4)
|
||||
+ .addReg(MI->getOperand(0).getReg())
|
||||
+ .addReg(MI->getOperand(1).getReg())
|
||||
+ .addReg(MI->getOperand(0).getReg()));
|
||||
+ return;
|
||||
+ }
|
||||
case PPC::PPC32GOT: {
|
||||
MCSymbol *GOTSymbol = OutContext.GetOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
|
||||
const MCExpr *SymGotTlsL =
|
||||
@@ -606,31 +634,43 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
||||
.addExpr(SymGotTlsGD));
|
||||
return;
|
||||
}
|
||||
- case PPC::ADDItlsgdL: {
|
||||
+ case PPC::ADDItlsgdL:
|
||||
// Transform: %Xd = ADDItlsgdL %Xs, <ga:@sym>
|
||||
// Into: %Xd = ADDI8 %Xs, sym@got@tlsgd@l
|
||||
- assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
|
||||
+ case PPC::ADDItlsgdL32: {
|
||||
+ // Transform: %Rd = ADDItlsgdL32 %Rs, <ga:@sym>
|
||||
+ // Into: %Rd = ADDI %Rs, sym@got@tlsgd
|
||||
const MachineOperand &MO = MI->getOperand(2);
|
||||
const GlobalValue *GValue = MO.getGlobal();
|
||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||
const MCExpr *SymGotTlsGD =
|
||||
- MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO,
|
||||
+ MCSymbolRefExpr::Create(MOSymbol, Subtarget.isPPC64() ?
|
||||
+ MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO :
|
||||
+ MCSymbolRefExpr::VK_PPC_GOT_TLSGD,
|
||||
OutContext);
|
||||
- EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDI8)
|
||||
- .addReg(MI->getOperand(0).getReg())
|
||||
- .addReg(MI->getOperand(1).getReg())
|
||||
- .addExpr(SymGotTlsGD));
|
||||
+ EmitToStreamer(OutStreamer,
|
||||
+ MCInstBuilder(Subtarget.isPPC64() ? PPC::ADDI8 : PPC::ADDI)
|
||||
+ .addReg(MI->getOperand(0).getReg())
|
||||
+ .addReg(MI->getOperand(1).getReg())
|
||||
+ .addExpr(SymGotTlsGD));
|
||||
return;
|
||||
}
|
||||
- case PPC::GETtlsADDR: {
|
||||
+ case PPC::GETtlsADDR:
|
||||
// Transform: %X3 = GETtlsADDR %X3, <ga:@sym>
|
||||
// Into: BL8_NOP_TLS __tls_get_addr(sym@tlsgd)
|
||||
- assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
|
||||
+ case PPC::GETtlsADDR32: {
|
||||
+ // Transform: %R3 = GETtlsADDR32 %R3, <ga:@sym>
|
||||
+ // Into: BL_TLS __tls_get_addr(sym@tlsgd)@PLT
|
||||
|
||||
StringRef Name = "__tls_get_addr";
|
||||
MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);
|
||||
+ MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
|
||||
+
|
||||
+ if (!Subtarget.isPPC64() && !Subtarget.isDarwin() &&
|
||||
+ TM.getRelocationModel() == Reloc::PIC_)
|
||||
+ Kind = MCSymbolRefExpr::VK_PLT;
|
||||
const MCSymbolRefExpr *TlsRef =
|
||||
- MCSymbolRefExpr::Create(TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext);
|
||||
+ MCSymbolRefExpr::Create(TlsGetAddr, Kind, OutContext);
|
||||
const MachineOperand &MO = MI->getOperand(2);
|
||||
const GlobalValue *GValue = MO.getGlobal();
|
||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||
@@ -637,9 +677,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
||||
const MCExpr *SymVar =
|
||||
MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSGD,
|
||||
OutContext);
|
||||
- EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL8_NOP_TLS)
|
||||
- .addExpr(TlsRef)
|
||||
- .addExpr(SymVar));
|
||||
+ EmitToStreamer(OutStreamer,
|
||||
+ MCInstBuilder(Subtarget.isPPC64() ?
|
||||
+ PPC::BL8_NOP_TLS : PPC::BL_TLS)
|
||||
+ .addExpr(TlsRef)
|
||||
+ .addExpr(SymVar));
|
||||
return;
|
||||
}
|
||||
case PPC::ADDIStlsldHA: {
|
||||
@@ -658,31 +700,44 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
||||
.addExpr(SymGotTlsLD));
|
||||
return;
|
||||
}
|
||||
- case PPC::ADDItlsldL: {
|
||||
+ case PPC::ADDItlsldL:
|
||||
// Transform: %Xd = ADDItlsldL %Xs, <ga:@sym>
|
||||
// Into: %Xd = ADDI8 %Xs, sym@got@tlsld@l
|
||||
- assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
|
||||
+ case PPC::ADDItlsldL32: {
|
||||
+ // Transform: %Rd = ADDItlsldL32 %Rs, <ga:@sym>
|
||||
+ // Into: %Rd = ADDI %Rs, sym@got@tlsld
|
||||
const MachineOperand &MO = MI->getOperand(2);
|
||||
const GlobalValue *GValue = MO.getGlobal();
|
||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||
const MCExpr *SymGotTlsLD =
|
||||
- MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO,
|
||||
+ MCSymbolRefExpr::Create(MOSymbol, Subtarget.isPPC64() ?
|
||||
+ MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO :
|
||||
+ MCSymbolRefExpr::VK_PPC_GOT_TLSLD,
|
||||
OutContext);
|
||||
- EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDI8)
|
||||
- .addReg(MI->getOperand(0).getReg())
|
||||
- .addReg(MI->getOperand(1).getReg())
|
||||
- .addExpr(SymGotTlsLD));
|
||||
+ EmitToStreamer(OutStreamer,
|
||||
+ MCInstBuilder(Subtarget.isPPC64() ? PPC::ADDI8 : PPC::ADDI)
|
||||
+ .addReg(MI->getOperand(0).getReg())
|
||||
+ .addReg(MI->getOperand(1).getReg())
|
||||
+ .addExpr(SymGotTlsLD));
|
||||
return;
|
||||
}
|
||||
- case PPC::GETtlsldADDR: {
|
||||
+ case PPC::GETtlsldADDR:
|
||||
// Transform: %X3 = GETtlsldADDR %X3, <ga:@sym>
|
||||
// Into: BL8_NOP_TLS __tls_get_addr(sym@tlsld)
|
||||
- assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
|
||||
+ case PPC::GETtlsldADDR32: {
|
||||
+ // Transform: %R3 = GETtlsldADDR32 %R3, <ga:@sym>
|
||||
+ // Into: BL_TLS __tls_get_addr(sym@tlsld)@PLT
|
||||
|
||||
StringRef Name = "__tls_get_addr";
|
||||
MCSymbol *TlsGetAddr = OutContext.GetOrCreateSymbol(Name);
|
||||
+ MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
|
||||
+
|
||||
+ if (!Subtarget.isPPC64() && !Subtarget.isDarwin() &&
|
||||
+ TM.getRelocationModel() == Reloc::PIC_)
|
||||
+ Kind = MCSymbolRefExpr::VK_PLT;
|
||||
+
|
||||
const MCSymbolRefExpr *TlsRef =
|
||||
- MCSymbolRefExpr::Create(TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext);
|
||||
+ MCSymbolRefExpr::Create(TlsGetAddr, Kind, OutContext);
|
||||
const MachineOperand &MO = MI->getOperand(2);
|
||||
const GlobalValue *GValue = MO.getGlobal();
|
||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||
@@ -689,15 +744,19 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
||||
const MCExpr *SymVar =
|
||||
MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_TLSLD,
|
||||
OutContext);
|
||||
- EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL8_NOP_TLS)
|
||||
- .addExpr(TlsRef)
|
||||
- .addExpr(SymVar));
|
||||
+ EmitToStreamer(OutStreamer,
|
||||
+ MCInstBuilder(Subtarget.isPPC64() ?
|
||||
+ PPC::BL8_NOP_TLS : PPC::BL_TLS)
|
||||
+ .addExpr(TlsRef)
|
||||
+ .addExpr(SymVar));
|
||||
return;
|
||||
}
|
||||
- case PPC::ADDISdtprelHA: {
|
||||
+ case PPC::ADDISdtprelHA:
|
||||
// Transform: %Xd = ADDISdtprelHA %X3, <ga:@sym>
|
||||
// Into: %Xd = ADDIS8 %X3, sym@dtprel@ha
|
||||
- assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
|
||||
+ case PPC::ADDISdtprelHA32: {
|
||||
+ // Transform: %Rd = ADDISdtprelHA32 %R3, <ga:@sym>
|
||||
+ // Into: %Rd = ADDIS %R3, sym@dtprel@ha
|
||||
const MachineOperand &MO = MI->getOperand(2);
|
||||
const GlobalValue *GValue = MO.getGlobal();
|
||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||
@@ -704,16 +763,19 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
||||
const MCExpr *SymDtprel =
|
||||
MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_HA,
|
||||
OutContext);
|
||||
- EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDIS8)
|
||||
- .addReg(MI->getOperand(0).getReg())
|
||||
- .addReg(PPC::X3)
|
||||
- .addExpr(SymDtprel));
|
||||
+ EmitToStreamer(OutStreamer,
|
||||
+ MCInstBuilder(Subtarget.isPPC64() ? PPC::ADDIS8 : PPC::ADDIS)
|
||||
+ .addReg(MI->getOperand(0).getReg())
|
||||
+ .addReg(Subtarget.isPPC64() ? PPC::X3 : PPC::R3)
|
||||
+ .addExpr(SymDtprel));
|
||||
return;
|
||||
}
|
||||
- case PPC::ADDIdtprelL: {
|
||||
+ case PPC::ADDIdtprelL:
|
||||
// Transform: %Xd = ADDIdtprelL %Xs, <ga:@sym>
|
||||
// Into: %Xd = ADDI8 %Xs, sym@dtprel@l
|
||||
- assert(Subtarget.isPPC64() && "Not supported for 32-bit PowerPC");
|
||||
+ case PPC::ADDIdtprelL32: {
|
||||
+ // Transform: %Rd = ADDIdtprelL32 %Rs, <ga:@sym>
|
||||
+ // Into: %Rd = ADDI %Rs, sym@dtprel@l
|
||||
const MachineOperand &MO = MI->getOperand(2);
|
||||
const GlobalValue *GValue = MO.getGlobal();
|
||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||
@@ -720,10 +782,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
||||
const MCExpr *SymDtprel =
|
||||
MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_LO,
|
||||
OutContext);
|
||||
- EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ADDI8)
|
||||
- .addReg(MI->getOperand(0).getReg())
|
||||
- .addReg(MI->getOperand(1).getReg())
|
||||
- .addExpr(SymDtprel));
|
||||
+ EmitToStreamer(OutStreamer,
|
||||
+ MCInstBuilder(Subtarget.isPPC64() ? PPC::ADDI8 : PPC::ADDI)
|
||||
+ .addReg(MI->getOperand(0).getReg())
|
||||
+ .addReg(MI->getOperand(1).getReg())
|
||||
+ .addExpr(SymDtprel));
|
||||
return;
|
||||
}
|
||||
case PPC::MFOCRF:
|
||||
Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp
|
||||
===================================================================
|
||||
--- lib/Target/PowerPC/PPCISelDAGToDAG.cpp
|
||||
+++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp
|
||||
@@ -1473,6 +1473,12 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) {
|
||||
return CurDAG->getMachineNode(PPC::ADDItocL, dl, MVT::i64,
|
||||
SDValue(Tmp, 0), GA);
|
||||
}
|
||||
+ case PPCISD::PPC32_PICGOT: {
|
||||
+ // Generate a PIC-safe GOT reference.
|
||||
+ assert(!PPCSubTarget->isPPC64() && PPCSubTarget->isSVR4ABI() &&
|
||||
+ "PPCISD::PPC32_PICGOT is only supported for 32-bit SVR4");
|
||||
+ return CurDAG->SelectNodeTo(N, PPC::PPC32PICGOT, PPCLowering->getPointerTy(), MVT::i32);
|
||||
+ }
|
||||
case PPCISD::VADD_SPLAT: {
|
||||
// This expands into one of three sequences, depending on whether
|
||||
// the first operand is odd or even, positive or negative.
|
||||
Index: test/CodeGen/PowerPC/tls-pic.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/PowerPC/tls-pic.ll
|
||||
+++ test/CodeGen/PowerPC/tls-pic.ll
|
||||
@@ -1,5 +1,7 @@
|
||||
; RUN: llc -march=ppc64 -mcpu=pwr7 -O0 -relocation-model=pic < %s | FileCheck -check-prefix=OPT0 %s
|
||||
; RUN: llc -march=ppc64 -mcpu=pwr7 -O1 -relocation-model=pic < %s | FileCheck -check-prefix=OPT1 %s
|
||||
+; RUN: llc -march=ppc32 -O0 -relocation-model=pic < %s | FileCheck -check-prefix=OPT0-32 %s
|
||||
+; RUN: llc -march=ppc32 -O1 -relocation-model=pic < %s | FileCheck -check-prefix=OPT1-32 %s
|
||||
|
||||
target triple = "powerpc64-unknown-linux-gnu"
|
||||
; Test correct assembly code generation for thread-local storage using
|
||||
@@ -22,6 +24,16 @@ entry:
|
||||
; OPT0-NEXT: nop
|
||||
; OPT0: addis [[REG2:[0-9]+]], 3, a@dtprel@ha
|
||||
; OPT0-NEXT: addi {{[0-9]+}}, [[REG2]], a@dtprel@l
|
||||
+; OPT0-32-LABEL: main
|
||||
+; OPT0-32: addi {{[0-9]+}}, {{[0-9]+}}, a@got@tlsld
|
||||
+; OPT0-32: bl __tls_get_addr(a@tlsld)@PLT
|
||||
+; OPT0-32: addis [[REG:[0-9]+]], 3, a@dtprel@ha
|
||||
+; OPT0-32-NEXT: addi {{[0-9]+}}, [[REG]], a@dtprel@l
|
||||
+; OPT1-32-LABEL: main
|
||||
+; OPT1-32: addi 3, {{[0-9]+}}, a@got@tlsld
|
||||
+; OPT1-32: bl __tls_get_addr(a@tlsld)@PLT
|
||||
+; OPT1-32: addis [[REG:[0-9]+]], 3, a@dtprel@ha
|
||||
+; OPT1-32-NEXT: addi {{[0-9]+}}, [[REG]], a@dtprel@l
|
||||
|
||||
; Test peephole optimization for thread-local storage using the
|
||||
; local dynamic model.
|
||||
@@ -52,4 +64,6 @@ entry:
|
||||
; OPT1-NEXT: addi 3, [[REG]], a2@got@tlsgd@l
|
||||
; OPT1: bl __tls_get_addr(a2@tlsgd)
|
||||
; OPT1-NEXT: nop
|
||||
-
|
||||
+; OPT1-32-LABEL: main2
|
||||
+; OPT1-32: addi 3, {{[0-9]+}}, a2@got@tlsgd
|
||||
+; OPT1-32: bl __tls_get_addr(a2@tlsgd)@PLT
|
||||
|
|
@ -17,7 +17,7 @@ Index: lib/Target/ARM/ARMInstrInfo.td
|
|||
===================================================================
|
||||
--- lib/Target/ARM/ARMInstrInfo.td
|
||||
+++ lib/Target/ARM/ARMInstrInfo.td
|
||||
@@ -3248,7 +3248,8 @@
|
||||
@@ -3419,7 +3419,8 @@ def : ARMPat<(ARMaddc GPR:$src, imm0_65535_neg:$im
|
||||
def : ARMPat<(ARMadde GPR:$src, so_imm_not:$imm, CPSR),
|
||||
(SBCri GPR:$src, so_imm_not:$imm)>;
|
||||
def : ARMPat<(ARMadde GPR:$src, imm0_65535_neg:$imm, CPSR),
|
||||
|
|
@ -32,7 +32,7 @@ Index: test/CodeGen/ARM/carry.ll
|
|||
--- test/CodeGen/ARM/carry.ll
|
||||
+++ test/CodeGen/ARM/carry.ll
|
||||
@@ -1,4 +1,4 @@
|
||||
-; RUN: llc < %s -march=arm | FileCheck %s
|
||||
-; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s
|
||||
+; RUN: llc < %s -mtriple=armv6t2-eabi | FileCheck %s
|
||||
|
||||
define i64 @f1(i64 %a, i64 %b) {
|
||||
|
|
@ -17,9 +17,9 @@ Introduced here: http://svnweb.freebsd.org/changeset/base/271597
|
|||
|
||||
Index: lib/Target/X86/X86ISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/X86/X86ISelLowering.cpp (revision 208032)
|
||||
+++ lib/Target/X86/X86ISelLowering.cpp (working copy)
|
||||
@@ -300,6 +300,8 @@ void X86TargetLowering::resetOperationActions() {
|
||||
--- lib/Target/X86/X86ISelLowering.cpp
|
||||
+++ lib/Target/X86/X86ISelLowering.cpp
|
||||
@@ -316,6 +316,8 @@ void X86TargetLowering::resetOperationActions() {
|
||||
setTruncStoreAction(MVT::i32, MVT::i8 , Expand);
|
||||
setTruncStoreAction(MVT::i16, MVT::i8, Expand);
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ Index: lib/Target/X86/X86ISelLowering.cpp
|
|||
// SETOEQ and SETUNE require checking two conditions.
|
||||
setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);
|
||||
setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);
|
||||
@@ -1011,8 +1013,6 @@ void X86TargetLowering::resetOperationActions() {
|
||||
@@ -1043,8 +1045,6 @@ void X86TargetLowering::resetOperationActions() {
|
||||
AddPromotedToType (ISD::SELECT, VT, MVT::v2i64);
|
||||
}
|
||||
|
||||
|
|
@ -39,8 +39,8 @@ Index: lib/Target/X86/X86ISelLowering.cpp
|
|||
setOperationAction(ISD::LOAD, MVT::v2i64, Legal);
|
||||
Index: test/CodeGen/X86/dont-trunc-store-double-to-float.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/X86/dont-trunc-store-double-to-float.ll (revision 0)
|
||||
+++ test/CodeGen/X86/dont-trunc-store-double-to-float.ll (working copy)
|
||||
--- test/CodeGen/X86/dont-trunc-store-double-to-float.ll
|
||||
+++ test/CodeGen/X86/dont-trunc-store-double-to-float.ll
|
||||
@@ -0,0 +1,20 @@
|
||||
+; RUN: llc -march=x86 < %s | FileCheck %s
|
||||
+
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
Pull in r221709 from upstream llvm trunk (by Frédéric Riss):
|
||||
Pull in r221709 from upstream llvm trunk (by Frédéric Riss):
|
||||
|
||||
Totally forget deallocated SDNodes in SDDbgInfo.
|
||||
|
||||
|
|
@ -24,9 +24,9 @@ Introduced here: http://svnweb.freebsd.org/changeset/base/274442
|
|||
|
||||
Index: include/llvm/CodeGen/SelectionDAG.h
|
||||
===================================================================
|
||||
--- include/llvm/CodeGen/SelectionDAG.h
|
||||
+++ include/llvm/CodeGen/SelectionDAG.h
|
||||
@@ -127,6 +127,10 @@ class SDDbgInfo {
|
||||
--- include/llvm/CodeGen/SelectionDAG.h (revision 10)
|
||||
+++ include/llvm/CodeGen/SelectionDAG.h (revision 11)
|
||||
@@ -126,6 +126,10 @@ class SDDbgInfo {
|
||||
DbgValMap[Node].push_back(V);
|
||||
}
|
||||
|
||||
|
|
@ -39,9 +39,9 @@ Index: include/llvm/CodeGen/SelectionDAG.h
|
|||
DbgValues.clear();
|
||||
Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp
|
||||
===================================================================
|
||||
--- lib/CodeGen/SelectionDAG/SelectionDAG.cpp
|
||||
+++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp
|
||||
@@ -625,6 +625,15 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *
|
||||
--- lib/CodeGen/SelectionDAG/SelectionDAG.cpp (revision 10)
|
||||
+++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp (revision 11)
|
||||
@@ -686,6 +686,15 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *
|
||||
DeallocateNode(N);
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp
|
|||
void SelectionDAG::DeallocateNode(SDNode *N) {
|
||||
if (N->OperandsNeedDelete)
|
||||
delete[] N->OperandList;
|
||||
@@ -635,10 +644,9 @@ void SelectionDAG::DeallocateNode(SDNode *N) {
|
||||
@@ -696,10 +705,9 @@ void SelectionDAG::DeallocateNode(SDNode *N) {
|
||||
|
||||
NodeAllocator.Deallocate(AllNodes.remove(N));
|
||||
|
||||
22
contrib/llvm/patches/patch-11-llvm-r222562-loop-rotate.diff
Normal file
22
contrib/llvm/patches/patch-11-llvm-r222562-loop-rotate.diff
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Pull in r222562 from upstream llvm trunk (by Roman Divacky):
|
||||
|
||||
Disable header duplication at -Oz in loop-rotate pass.
|
||||
|
||||
This helps to minimize the size of boot2.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/274968
|
||||
|
||||
Index: lib/Transforms/IPO/PassManagerBuilder.cpp
|
||||
===================================================================
|
||||
--- lib/Transforms/IPO/PassManagerBuilder.cpp (revision 11)
|
||||
+++ lib/Transforms/IPO/PassManagerBuilder.cpp (revision 12)
|
||||
@@ -195,7 +195,8 @@ void PassManagerBuilder::populateModulePassManager
|
||||
MPM.add(createTailCallEliminationPass()); // Eliminate tail calls
|
||||
MPM.add(createCFGSimplificationPass()); // Merge & remove BBs
|
||||
MPM.add(createReassociatePass()); // Reassociate expressions
|
||||
- MPM.add(createLoopRotatePass()); // Rotate Loop
|
||||
+ // Rotate Loop - disable header duplication at -Oz
|
||||
+ MPM.add(createLoopRotatePass(SizeLevel == 2 ? 0 : -1));
|
||||
MPM.add(createLICMPass()); // Hoist loop invariants
|
||||
MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3));
|
||||
MPM.add(createInstructionCombiningPass());
|
||||
31
contrib/llvm/patches/patch-12-add-llvm-gvn-option.diff
Normal file
31
contrib/llvm/patches/patch-12-add-llvm-gvn-option.diff
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
Add an llvm option to enable/disable running the global value numbering
|
||||
optimization pass. Disabling this pass helps to minimize the size of
|
||||
boot2.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/274968
|
||||
|
||||
Index: lib/Transforms/IPO/PassManagerBuilder.cpp
|
||||
===================================================================
|
||||
--- lib/Transforms/IPO/PassManagerBuilder.cpp (revision 12)
|
||||
+++ lib/Transforms/IPO/PassManagerBuilder.cpp (revision 13)
|
||||
@@ -57,6 +57,10 @@ static cl::opt<bool> RunLoadCombine("combine-loads
|
||||
cl::Hidden,
|
||||
cl::desc("Run the load combining pass"));
|
||||
|
||||
+static cl::opt<bool> RunGVN("enable-gvn", cl::init(true),
|
||||
+ cl::Hidden,
|
||||
+ cl::desc("Run the global value numbering pass"));
|
||||
+
|
||||
PassManagerBuilder::PassManagerBuilder() {
|
||||
OptLevel = 2;
|
||||
SizeLevel = 0;
|
||||
@@ -210,7 +214,8 @@ void PassManagerBuilder::populateModulePassManager
|
||||
|
||||
if (OptLevel > 1) {
|
||||
MPM.add(createMergedLoadStoreMotionPass()); // Merge load/stores in diamond
|
||||
- MPM.add(createGVNPass()); // Remove redundancies
|
||||
+ if (RunGVN)
|
||||
+ MPM.add(createGVNPass()); // Remove redundancies
|
||||
}
|
||||
MPM.add(createMemCpyOptPass()); // Remove memcpy / form memset
|
||||
MPM.add(createSCCPPass()); // Constant prop with SCCP
|
||||
150
contrib/llvm/patches/patch-13-llvm-r218241-dwarf2-warning.diff
Normal file
150
contrib/llvm/patches/patch-13-llvm-r218241-dwarf2-warning.diff
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
Pull in r218241 from upstream llvm trunk (by Oliver Stannard):
|
||||
|
||||
Downgrade DWARF2 section limit error to a warning
|
||||
|
||||
We currently emit an error when trying to assemble a file with more
|
||||
than one section using DWARF2 debug info. This should be a warning
|
||||
instead, as the resulting file will still be usable, but with a
|
||||
degraded debug illusion.
|
||||
|
||||
This helps to compile sys/amd64/amd64/xen-locore.S, which mixes multiple
|
||||
sections into one file, and thus would emit an error about DWARF2 not
|
||||
supporting that.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/274968
|
||||
|
||||
Index: lib/MC/MCDwarf.cpp
|
||||
===================================================================
|
||||
--- lib/MC/MCDwarf.cpp (revision 13)
|
||||
+++ lib/MC/MCDwarf.cpp (revision 14)
|
||||
@@ -519,7 +519,8 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
|
||||
MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
|
||||
MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
|
||||
EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4);
|
||||
- if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1) {
|
||||
+ if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1 &&
|
||||
+ MCOS->getContext().getDwarfVersion() >= 3) {
|
||||
EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4);
|
||||
} else {
|
||||
EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
|
||||
@@ -855,10 +856,11 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
|
||||
if (MCOS->getContext().getGenDwarfSectionSyms().empty())
|
||||
return;
|
||||
|
||||
- // We only need to use the .debug_ranges section if we have multiple
|
||||
- // code sections.
|
||||
+ // We only use the .debug_ranges section if we have multiple code sections,
|
||||
+ // and we are emitting a DWARF version which supports it.
|
||||
const bool UseRangesSection =
|
||||
- MCOS->getContext().getGenDwarfSectionSyms().size() > 1;
|
||||
+ MCOS->getContext().getGenDwarfSectionSyms().size() > 1 &&
|
||||
+ MCOS->getContext().getDwarfVersion() >= 3;
|
||||
CreateDwarfSectionSymbols |= UseRangesSection;
|
||||
|
||||
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
|
||||
Index: lib/MC/MCParser/ELFAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/MC/MCParser/ELFAsmParser.cpp (revision 13)
|
||||
+++ lib/MC/MCParser/ELFAsmParser.cpp (revision 14)
|
||||
@@ -555,7 +555,7 @@ EndStmt:
|
||||
std::make_pair(ELFSection, std::make_pair(nullptr, nullptr)));
|
||||
if (InsertResult.second) {
|
||||
if (getContext().getDwarfVersion() <= 2)
|
||||
- Error(loc, "DWARF2 only supports one section per compilation unit");
|
||||
+ Warning(loc, "DWARF2 only supports one section per compilation unit");
|
||||
|
||||
MCSymbol *SectionStartSymbol = getContext().CreateTempSymbol();
|
||||
getStreamer().EmitLabel(SectionStartSymbol);
|
||||
Index: test/MC/ARM/dwarf-asm-multiple-sections-dwarf-2.s
|
||||
===================================================================
|
||||
--- test/MC/ARM/dwarf-asm-multiple-sections-dwarf-2.s (revision 0)
|
||||
+++ test/MC/ARM/dwarf-asm-multiple-sections-dwarf-2.s (revision 14)
|
||||
@@ -0,0 +1,66 @@
|
||||
+// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -fdebug-compilation-dir=/tmp -dwarf-version 2 2>&1 | FileCheck -check-prefix MESSAGES %s
|
||||
+// RUN: llvm-dwarfdump %t | FileCheck -check-prefix DWARF %s
|
||||
+// RUN: llvm-objdump -r %t | FileCheck -check-prefix RELOC %s
|
||||
+
|
||||
+ .section .text, "ax"
|
||||
+a:
|
||||
+ mov r0, r0
|
||||
+
|
||||
+ .section foo, "ax"
|
||||
+b:
|
||||
+ mov r1, r1
|
||||
+
|
||||
+// MESSAGES: warning: DWARF2 only supports one section per compilation unit
|
||||
+
|
||||
+// DWARF: .debug_abbrev contents:
|
||||
+// DWARF: Abbrev table for offset: 0x00000000
|
||||
+// DWARF: [1] DW_TAG_compile_unit DW_CHILDREN_yes
|
||||
+// DWARF: DW_AT_stmt_list DW_FORM_data4
|
||||
+// DWARF: DW_AT_low_pc DW_FORM_addr
|
||||
+// DWARF: DW_AT_high_pc DW_FORM_addr
|
||||
+// DWARF: DW_AT_name DW_FORM_string
|
||||
+// DWARF: DW_AT_comp_dir DW_FORM_string
|
||||
+// DWARF: DW_AT_producer DW_FORM_string
|
||||
+// DWARF: DW_AT_language DW_FORM_data2
|
||||
+
|
||||
+// DWARF: .debug_info contents:
|
||||
+// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_compile_unit [1]
|
||||
+// CHECK-NOT-DWARF: DW_TAG_
|
||||
+// DWARF: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
+// DWARF: DW_AT_high_pc [DW_FORM_addr] (0x0000000000000004)
|
||||
+
|
||||
+// DWARF: 0x{{[0-9a-f]+}}: DW_TAG_label [2] *
|
||||
+// DWARF-NEXT: DW_AT_name [DW_FORM_string] ("a")
|
||||
+
|
||||
+
|
||||
+// DWARF: .debug_aranges contents:
|
||||
+// DWARF-NEXT: Address Range Header: length = 0x00000024, version = 0x0002, cu_offset = 0x00000000, addr_size = 0x04, seg_size = 0x00
|
||||
+// DWARF-NEXT: [0x00000000 - 0x00000004)
|
||||
+// DWARF-NEXT: [0x00000000 - 0x00000004)
|
||||
+
|
||||
+// DWARF: .debug_line contents:
|
||||
+// DWARF: 0x0000000000000000 7 0 1 0 0 is_stmt
|
||||
+// DWARF-NEXT: 0x0000000000000004 7 0 1 0 0 is_stmt end_sequence
|
||||
+// DWARF: 0x0000000000000000 11 0 1 0 0 is_stmt
|
||||
+// DWARF-NEXT: 0x0000000000000004 11 0 1 0 0 is_stmt end_sequence
|
||||
+
|
||||
+
|
||||
+// DWARF: .debug_ranges contents:
|
||||
+// DWARF-NOT: {{0-9a-f}}
|
||||
+// DWARF: .debug_pubnames contents:
|
||||
+
|
||||
+
|
||||
+// RELOC: RELOCATION RECORDS FOR [.rel.debug_info]:
|
||||
+// RELOC-NEXT: 00000006 R_ARM_ABS32 .debug_abbrev
|
||||
+// RELOC-NEXT: 0000000c R_ARM_ABS32 .debug_line
|
||||
+// RELOC-NEXT: R_ARM_ABS32 .text
|
||||
+// RELOC-NEXT: R_ARM_ABS32 .text
|
||||
+// RELOC-NEXT: R_ARM_ABS32 .text
|
||||
+// RELOC-NEXT: R_ARM_ABS32 foo
|
||||
+
|
||||
+// RELOC-NOT: RELOCATION RECORDS FOR [.rel.debug_ranges]:
|
||||
+
|
||||
+// RELOC: RELOCATION RECORDS FOR [.rel.debug_aranges]:
|
||||
+// RELOC-NEXT: 00000006 R_ARM_ABS32 .debug_info
|
||||
+// RELOC-NEXT: 00000010 R_ARM_ABS32 .text
|
||||
+// RELOC-NEXT: 00000018 R_ARM_ABS32 foo
|
||||
Index: test/MC/ARM/dwarf-asm-multiple-sections.s
|
||||
===================================================================
|
||||
--- test/MC/ARM/dwarf-asm-multiple-sections.s (revision 13)
|
||||
+++ test/MC/ARM/dwarf-asm-multiple-sections.s (revision 14)
|
||||
@@ -1,7 +1,7 @@
|
||||
// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -fdebug-compilation-dir=/tmp
|
||||
// RUN: llvm-dwarfdump %t | FileCheck -check-prefix DWARF %s
|
||||
// RUN: llvm-objdump -r %t | FileCheck -check-prefix RELOC %s
|
||||
-// RUN: not llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 2 2>&1 | FileCheck -check-prefix VERSION %s
|
||||
+// RUN: llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 2 2>&1 | FileCheck -check-prefix VERSION %s
|
||||
// RUN: not llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 1 2>&1 | FileCheck -check-prefix DWARF1 %s
|
||||
// RUN: not llvm-mc < %s -triple=armv7-linux-gnueabi -filetype=obj -o %t -g -dwarf-version 5 2>&1 | FileCheck -check-prefix DWARF5 %s
|
||||
.section .text, "ax"
|
||||
@@ -73,7 +73,7 @@ b:
|
||||
// RELOC-NEXT: 00000018 R_ARM_ABS32 foo
|
||||
|
||||
|
||||
-// VERSION: {{.*}} error: DWARF2 only supports one section per compilation unit
|
||||
+// VERSION: {{.*}} warning: DWARF2 only supports one section per compilation unit
|
||||
|
||||
// DWARF1: Dwarf version 1 is not supported.
|
||||
// DWARF5: Dwarf version 5 is not supported.
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
This patch makes "clang -print-multi-os-directory" print "." on amd64, which is
|
||||
required by certain ports.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/213492
|
||||
|
||||
Index: tools/clang/lib/Driver/Driver.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Driver.cpp
|
||||
+++ tools/clang/lib/Driver/Driver.cpp
|
||||
@@ -780,7 +780,7 @@ bool Driver::HandleImmediateArgs(const Compilation
|
||||
break;
|
||||
|
||||
case llvm::Triple::x86_64:
|
||||
- llvm::outs() << "x86_64" << "\n";
|
||||
+ llvm::outs() << "." << "\n";
|
||||
break;
|
||||
|
||||
case llvm::Triple::ppc64:
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
This patch ensures __clear_cache is not called on arm. In earlier versions of
|
||||
clang, this special builtin was emitted as a function call, leading to link
|
||||
errors.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/243830
|
||||
|
||||
Index: lib/Support/Unix/Memory.inc
|
||||
===================================================================
|
||||
--- lib/Support/Unix/Memory.inc
|
||||
+++ lib/Support/Unix/Memory.inc
|
||||
@@ -332,7 +332,7 @@ void Memory::InvalidateInstructionCache(const void
|
||||
for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
|
||||
asm volatile("icbi 0, %0" : : "r"(Line));
|
||||
asm volatile("isync");
|
||||
-# elif (defined(__arm__) || defined(__aarch64__)) && defined(__GNUC__)
|
||||
+# elif (defined(__arm__) || defined(__aarch64__)) && defined(__GNUC__) && !defined(__FreeBSD__)
|
||||
// FIXME: Can we safely always call this for __GNUC__ everywhere?
|
||||
const char *Start = static_cast<const char *>(Addr);
|
||||
const char *End = Start + Len;
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
This patch applies a workaround for an ARM EABI issue, where clang would
|
||||
sometimes incorrectly align the stack in a leaf function that uses TLS.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/252503
|
||||
|
||||
Index: test/CodeGen/Thumb2/large-stack.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/Thumb2/large-stack.ll
|
||||
+++ test/CodeGen/Thumb2/large-stack.ll
|
||||
@@ -13,7 +13,7 @@ define void @test1() {
|
||||
define void @test2() {
|
||||
; DARWIN-LABEL: test2:
|
||||
; DARWIN: sub.w sp, sp, #4160
|
||||
-; DARWIN: sub sp, #8
|
||||
+; DARWIN: sub sp, #12
|
||||
; LINUX-LABEL: test2:
|
||||
; LINUX: sub.w sp, sp, #4160
|
||||
; LINUX: sub sp, #8
|
||||
Index: test/CodeGen/ARM/2009-10-30.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/ARM/2009-10-30.ll
|
||||
+++ test/CodeGen/ARM/2009-10-30.ll
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
define void @f(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, ...) {
|
||||
entry:
|
||||
-;CHECK: sub sp, sp, #4
|
||||
-;CHECK: add r{{[0-9]+}}, sp, #8
|
||||
-;CHECK: str r{{[0-9]+}}, [sp], #4
|
||||
+;CHECK: sub sp, sp, #8
|
||||
+;CHECK: add r{{[0-9]+}}, sp, #12
|
||||
+;CHECK: str r{{[0-9]+}}, [sp, #4]
|
||||
+;CHECK: add sp, sp, #8
|
||||
;CHECK: bx lr
|
||||
%ap = alloca i8*, align 4
|
||||
%ap1 = bitcast i8** %ap to i8*
|
||||
Index: test/CodeGen/ARM/vargs_align.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/ARM/vargs_align.ll
|
||||
+++ test/CodeGen/ARM/vargs_align.ll
|
||||
@@ -15,8 +15,8 @@ entry:
|
||||
return: ; preds = %entry
|
||||
%retval2 = load i32* %retval ; <i32> [#uses=1]
|
||||
ret i32 %retval2
|
||||
-; EABI: add sp, sp, #12
|
||||
; EABI: add sp, sp, #16
|
||||
+; EABI: add sp, sp, #16
|
||||
+; OABI: add sp, sp, #16
|
||||
; OABI: add sp, sp, #12
|
||||
-; OABI: add sp, sp, #12
|
||||
}
|
||||
Index: test/CodeGen/ARM/prefetch-thumb.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/ARM/prefetch-thumb.ll
|
||||
+++ test/CodeGen/ARM/prefetch-thumb.ll
|
||||
@@ -10,8 +10,8 @@ entry:
|
||||
;ARM: pld [sp, #50]
|
||||
|
||||
;THUMB2: t6:
|
||||
-;THUMB2: pld [sp]
|
||||
-;THUMB2: pld [sp, #50]
|
||||
+;THUMB2: pld [sp, #4]
|
||||
+;THUMB2: pld [sp, #54]
|
||||
|
||||
%red = alloca [100 x i8], align 1
|
||||
%0 = getelementptr inbounds [100 x i8]* %red, i32 0, i32 0
|
||||
Index: lib/Target/ARM/ARMFrameLowering.h
|
||||
===================================================================
|
||||
--- lib/Target/ARM/ARMFrameLowering.h
|
||||
+++ lib/Target/ARM/ARMFrameLowering.h
|
||||
@@ -27,7 +27,7 @@ class ARMFrameLowering : public TargetFrameLowerin
|
||||
|
||||
public:
|
||||
explicit ARMFrameLowering(const ARMSubtarget &sti)
|
||||
- : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, 4),
|
||||
+ : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, 8),
|
||||
STI(sti) {
|
||||
}
|
||||
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
This patch eliminates the unnecessary search for various gcc installation
|
||||
directories during each startup of clang.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/259053
|
||||
|
||||
Index: tools/clang/lib/Driver/ToolChains.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/ToolChains.cpp
|
||||
+++ tools/clang/lib/Driver/ToolChains.cpp
|
||||
@@ -1014,7 +1014,7 @@ static StringRef getGCCToolchainDir(const ArgList
|
||||
return GCC_INSTALL_PREFIX;
|
||||
}
|
||||
|
||||
-/// \brief Construct a GCCInstallationDetector from the driver.
|
||||
+/// \brief Initialize a GCCInstallationDetector from the driver.
|
||||
///
|
||||
/// This performs all of the autodetection and sets up the various paths.
|
||||
/// Once constructed, a GCCInstallationDetector is essentially immutable.
|
||||
@@ -1023,9 +1023,9 @@ static StringRef getGCCToolchainDir(const ArgList
|
||||
/// should instead pull the target out of the driver. This is currently
|
||||
/// necessary because the driver doesn't store the final version of the target
|
||||
/// triple.
|
||||
-Generic_GCC::GCCInstallationDetector::GCCInstallationDetector(
|
||||
- const Driver &D, const llvm::Triple &TargetTriple, const ArgList &Args)
|
||||
- : IsValid(false), D(D) {
|
||||
+void
|
||||
+Generic_GCC::GCCInstallationDetector::init(
|
||||
+ const llvm::Triple &TargetTriple, const ArgList &Args) {
|
||||
llvm::Triple BiarchVariantTriple =
|
||||
TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant()
|
||||
: TargetTriple.get32BitArchVariant();
|
||||
@@ -1565,7 +1565,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLib
|
||||
|
||||
Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple,
|
||||
const ArgList &Args)
|
||||
- : ToolChain(D, Triple, Args), GCCInstallation(getDriver(), Triple, Args) {
|
||||
+ : ToolChain(D, Triple, Args), GCCInstallation(getDriver()) {
|
||||
getProgramPaths().push_back(getDriver().getInstalledDir());
|
||||
if (getDriver().getInstalledDir() != getDriver().Dir)
|
||||
getProgramPaths().push_back(getDriver().Dir);
|
||||
@@ -2361,6 +2361,7 @@ static StringRef getMultilibDir(const llvm::Triple
|
||||
|
||||
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
: Generic_ELF(D, Triple, Args) {
|
||||
+ GCCInstallation.init(Triple, Args);
|
||||
llvm::Triple::ArchType Arch = Triple.getArch();
|
||||
std::string SysRoot = computeSysRoot();
|
||||
|
||||
Index: tools/clang/lib/Driver/ToolChains.h
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/ToolChains.h
|
||||
+++ tools/clang/lib/Driver/ToolChains.h
|
||||
@@ -92,8 +92,8 @@ class LLVM_LIBRARY_VISIBILITY Generic_GCC : public
|
||||
std::set<std::string> CandidateGCCInstallPaths;
|
||||
|
||||
public:
|
||||
- GCCInstallationDetector(const Driver &D, const llvm::Triple &TargetTriple,
|
||||
- const llvm::opt::ArgList &Args);
|
||||
+ GCCInstallationDetector(const Driver &D) : IsValid(false), D(D) {}
|
||||
+ void init(const llvm::Triple &TargetTriple, const llvm::opt::ArgList &Args);
|
||||
|
||||
/// \brief Check whether we detected a valid GCC install.
|
||||
bool isValid() const { return IsValid; }
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
This patch adds the alias bit_FXSAVE for bit_FXSR to cpuid.h.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/259498
|
||||
|
||||
Index: tools/clang/lib/Headers/cpuid.h
|
||||
===================================================================
|
||||
--- tools/clang/lib/Headers/cpuid.h
|
||||
+++ tools/clang/lib/Headers/cpuid.h
|
||||
@@ -79,6 +79,7 @@
|
||||
#define bit_ACPI 0x00400000
|
||||
#define bit_MMX 0x00800000
|
||||
#define bit_FXSR 0x01000000
|
||||
+#define bit_FXSAVE bit_FXSR /* for gcc compat */
|
||||
#define bit_SSE 0x02000000
|
||||
#define bit_SSE2 0x04000000
|
||||
#define bit_SS 0x08000000
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
Pull in r200899 from upstream clang trunk (by Serge Pavlov):
|
||||
|
||||
Allow transformation of VariableArray to ConstantArray.
|
||||
|
||||
In the following code:
|
||||
|
||||
struct A { static const int sz; };
|
||||
template<class T> void f() { T arr[A::sz]; }
|
||||
|
||||
the array 'arr' is represented as a variable size array in the template.
|
||||
If 'A::sz' gets value below in the translation unit, the array in
|
||||
instantiation can turn into constant size array.
|
||||
|
||||
This change fixes PR18633.
|
||||
|
||||
Differential Revision: http://llvm-reviews.chandlerc.com/D2688
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/261680
|
||||
|
||||
Index: tools/clang/test/SemaCXX/c99-variable-length-array.cpp
|
||||
===================================================================
|
||||
--- tools/clang/test/SemaCXX/c99-variable-length-array.cpp
|
||||
+++ tools/clang/test/SemaCXX/c99-variable-length-array.cpp
|
||||
@@ -140,3 +140,24 @@ namespace PR11744 {
|
||||
}
|
||||
int test = f<int>(0); // expected-note {{instantiation of}}
|
||||
}
|
||||
+
|
||||
+namespace pr18633 {
|
||||
+ struct A1 {
|
||||
+ static const int sz;
|
||||
+ static const int sz2;
|
||||
+ };
|
||||
+ const int A1::sz2 = 11;
|
||||
+ template<typename T>
|
||||
+ void func () {
|
||||
+ int arr[A1::sz]; // expected-warning{{variable length arrays are a C99 feature}}
|
||||
+ }
|
||||
+ template<typename T>
|
||||
+ void func2 () {
|
||||
+ int arr[A1::sz2];
|
||||
+ }
|
||||
+ const int A1::sz = 12;
|
||||
+ void func2() {
|
||||
+ func<int>();
|
||||
+ func2<int>();
|
||||
+ }
|
||||
+}
|
||||
Index: tools/clang/lib/Sema/TreeTransform.h
|
||||
===================================================================
|
||||
--- tools/clang/lib/Sema/TreeTransform.h
|
||||
+++ tools/clang/lib/Sema/TreeTransform.h
|
||||
@@ -3966,7 +3966,9 @@ TreeTransform<Derived>::TransformVariableArrayType
|
||||
return QualType();
|
||||
}
|
||||
|
||||
- VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result);
|
||||
+ // We might have constant size array now, but fortunately it has the same
|
||||
+ // location layout.
|
||||
+ ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result);
|
||||
NewTL.setLBracketLoc(TL.getLBracketLoc());
|
||||
NewTL.setRBracketLoc(TL.getRBracketLoc());
|
||||
NewTL.setSizeExpr(Size);
|
||||
|
|
@ -1,540 +0,0 @@
|
|||
Pull in r195391 from upstream llvm trunk (by Eric Christopher):
|
||||
|
||||
In Dwarf 3 (and Dwarf 2) attributes whose value are offsets into a
|
||||
section use the form DW_FORM_data4 whilst in Dwarf 4 and later they
|
||||
use the form DW_FORM_sec_offset.
|
||||
|
||||
This patch updates the places where such attributes are generated to
|
||||
use the appropriate form depending on the Dwarf version. The DIE entries
|
||||
affected have the following tags:
|
||||
DW_AT_stmt_list, DW_AT_ranges, DW_AT_location, DW_AT_GNU_pubnames,
|
||||
DW_AT_GNU_pubtypes, DW_AT_GNU_addr_base, DW_AT_GNU_ranges_base
|
||||
|
||||
It also adds a hidden command line option "--dwarf-version=<uint>"
|
||||
to llc which allows the version of Dwarf to be generated to override
|
||||
what is specified in the metadata; this makes it possible to update
|
||||
existing tests to check the debugging information generated for both
|
||||
Dwarf 4 (the default) and Dwarf 3 using the same metadata.
|
||||
|
||||
Patch (slightly modified) by Keith Walker!
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/261991
|
||||
|
||||
Index: lib/CodeGen/AsmPrinter/DIE.cpp
|
||||
===================================================================
|
||||
--- lib/CodeGen/AsmPrinter/DIE.cpp
|
||||
+++ lib/CodeGen/AsmPrinter/DIE.cpp
|
||||
@@ -338,6 +338,7 @@ void DIEDelta::EmitValue(AsmPrinter *AP, dwarf::Fo
|
||||
///
|
||||
unsigned DIEDelta::SizeOf(AsmPrinter *AP, dwarf::Form Form) const {
|
||||
if (Form == dwarf::DW_FORM_data4) return 4;
|
||||
+ if (Form == dwarf::DW_FORM_sec_offset) return 4;
|
||||
if (Form == dwarf::DW_FORM_strp) return 4;
|
||||
return AP->getDataLayout().getPointerSize();
|
||||
}
|
||||
Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp
|
||||
===================================================================
|
||||
--- lib/CodeGen/AsmPrinter/DwarfDebug.cpp
|
||||
+++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp
|
||||
@@ -105,6 +105,11 @@ DwarfPubSections("generate-dwarf-pub-sections", cl
|
||||
clEnumVal(Disable, "Disabled"), clEnumValEnd),
|
||||
cl::init(Default));
|
||||
|
||||
+static cl::opt<unsigned>
|
||||
+DwarfVersionNumber("dwarf-version", cl::Hidden,
|
||||
+ cl::desc("Generate DWARF for dwarf version."),
|
||||
+ cl::init(0));
|
||||
+
|
||||
static const char *const DWARFGroupName = "DWARF Emission";
|
||||
static const char *const DbgTimerName = "DWARF Debug Writer";
|
||||
|
||||
@@ -215,7 +220,9 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
|
||||
else
|
||||
HasDwarfPubSections = DwarfPubSections == Enable;
|
||||
|
||||
- DwarfVersion = getDwarfVersionFromModule(MMI->getModule());
|
||||
+ DwarfVersion = DwarfVersionNumber
|
||||
+ ? DwarfVersionNumber
|
||||
+ : getDwarfVersionFromModule(MMI->getModule());
|
||||
|
||||
{
|
||||
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
|
||||
@@ -470,9 +477,9 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileU
|
||||
// .debug_range section has not been laid out yet. Emit offset in
|
||||
// .debug_range as a uint, size 4, for now. emitDIE will handle
|
||||
// DW_AT_ranges appropriately.
|
||||
- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
|
||||
- DebugRangeSymbols.size()
|
||||
- * Asm->getDataLayout().getPointerSize());
|
||||
+ TheCU->addSectionOffset(ScopeDIE, dwarf::DW_AT_ranges,
|
||||
+ DebugRangeSymbols.size() *
|
||||
+ Asm->getDataLayout().getPointerSize());
|
||||
for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
|
||||
RE = Ranges.end(); RI != RE; ++RI) {
|
||||
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
|
||||
@@ -525,9 +532,9 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileU
|
||||
// .debug_range section has not been laid out yet. Emit offset in
|
||||
// .debug_range as a uint, size 4, for now. emitDIE will handle
|
||||
// DW_AT_ranges appropriately.
|
||||
- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
|
||||
- DebugRangeSymbols.size()
|
||||
- * Asm->getDataLayout().getPointerSize());
|
||||
+ TheCU->addSectionOffset(ScopeDIE, dwarf::DW_AT_ranges,
|
||||
+ DebugRangeSymbols.size() *
|
||||
+ Asm->getDataLayout().getPointerSize());
|
||||
for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
|
||||
RE = Ranges.end(); RI != RE; ++RI) {
|
||||
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
|
||||
@@ -758,14 +765,15 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICo
|
||||
// The line table entries are not always emitted in assembly, so it
|
||||
// is not okay to use line_table_start here.
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
- NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
|
||||
- UseTheFirstCU ? Asm->GetTempSymbol("section_line")
|
||||
- : LineTableStartSym);
|
||||
+ NewCU->addSectionLabel(
|
||||
+ Die, dwarf::DW_AT_stmt_list,
|
||||
+ UseTheFirstCU ? Asm->GetTempSymbol("section_line")
|
||||
+ : LineTableStartSym);
|
||||
else if (UseTheFirstCU)
|
||||
- NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
|
||||
+ NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0);
|
||||
else
|
||||
- NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
|
||||
- LineTableStartSym, DwarfLineSectionSym);
|
||||
+ NewCU->addSectionDelta(Die, dwarf::DW_AT_stmt_list,
|
||||
+ LineTableStartSym, DwarfLineSectionSym);
|
||||
|
||||
// If we're using split dwarf the compilation dir is going to be in the
|
||||
// skeleton CU and so we don't need to duplicate it here.
|
||||
@@ -776,26 +784,24 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICo
|
||||
// emit it here if we don't have a skeleton CU for split dwarf.
|
||||
if (GenerateGnuPubSections) {
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames,
|
||||
- dwarf::DW_FORM_sec_offset,
|
||||
- Asm->GetTempSymbol("gnu_pubnames",
|
||||
- NewCU->getUniqueID()));
|
||||
+ NewCU->addSectionLabel(
|
||||
+ Die, dwarf::DW_AT_GNU_pubnames,
|
||||
+ Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()));
|
||||
else
|
||||
- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4,
|
||||
- Asm->GetTempSymbol("gnu_pubnames",
|
||||
- NewCU->getUniqueID()),
|
||||
- DwarfGnuPubNamesSectionSym);
|
||||
+ NewCU->addSectionDelta(
|
||||
+ Die, dwarf::DW_AT_GNU_pubnames,
|
||||
+ Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()),
|
||||
+ DwarfGnuPubNamesSectionSym);
|
||||
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes,
|
||||
- dwarf::DW_FORM_sec_offset,
|
||||
- Asm->GetTempSymbol("gnu_pubtypes",
|
||||
- NewCU->getUniqueID()));
|
||||
+ NewCU->addSectionLabel(
|
||||
+ Die, dwarf::DW_AT_GNU_pubtypes,
|
||||
+ Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()));
|
||||
else
|
||||
- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4,
|
||||
- Asm->GetTempSymbol("gnu_pubtypes",
|
||||
- NewCU->getUniqueID()),
|
||||
- DwarfGnuPubTypesSectionSym);
|
||||
+ NewCU->addSectionDelta(
|
||||
+ Die, dwarf::DW_AT_GNU_pubtypes,
|
||||
+ Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()),
|
||||
+ DwarfGnuPubTypesSectionSym);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2956,11 +2962,10 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const
|
||||
// Relocate to the beginning of the addr_base section, else 0 for the
|
||||
// beginning of the one for this compile unit.
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset,
|
||||
- DwarfAddrSectionSym);
|
||||
+ NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base,
|
||||
+ DwarfAddrSectionSym);
|
||||
else
|
||||
- NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base,
|
||||
- dwarf::DW_FORM_sec_offset, 0);
|
||||
+ NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0);
|
||||
|
||||
// 2.17.1 requires that we use DW_AT_low_pc for a single entry point
|
||||
// into an entity. We're using 0, or a NULL label for this.
|
||||
@@ -2970,10 +2975,10 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const
|
||||
// compile unit in debug_line section.
|
||||
// FIXME: Should handle multiple compile units.
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
- NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
|
||||
- DwarfLineSectionSym);
|
||||
+ NewCU->addSectionLabel(Die, dwarf::DW_AT_stmt_list,
|
||||
+ DwarfLineSectionSym);
|
||||
else
|
||||
- NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0);
|
||||
+ NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0);
|
||||
|
||||
if (!CompilationDir.empty())
|
||||
NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
|
||||
@@ -2981,27 +2986,31 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const
|
||||
// Flags to let the linker know we have emitted new style pubnames.
|
||||
if (GenerateGnuPubSections) {
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_sec_offset,
|
||||
- Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()));
|
||||
+ NewCU->addSectionLabel(
|
||||
+ Die, dwarf::DW_AT_GNU_pubnames,
|
||||
+ Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()));
|
||||
else
|
||||
- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4,
|
||||
- Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()),
|
||||
- DwarfGnuPubNamesSectionSym);
|
||||
+ NewCU->addSectionDelta(
|
||||
+ Die, dwarf::DW_AT_GNU_pubnames,
|
||||
+ Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()),
|
||||
+ DwarfGnuPubNamesSectionSym);
|
||||
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_sec_offset,
|
||||
- Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()));
|
||||
+ NewCU->addSectionLabel(
|
||||
+ Die, dwarf::DW_AT_GNU_pubtypes,
|
||||
+ Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()));
|
||||
else
|
||||
- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4,
|
||||
- Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()),
|
||||
- DwarfGnuPubTypesSectionSym);
|
||||
+ NewCU->addSectionDelta(
|
||||
+ Die, dwarf::DW_AT_GNU_pubtypes,
|
||||
+ Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()),
|
||||
+ DwarfGnuPubTypesSectionSym);
|
||||
}
|
||||
|
||||
// Flag if we've emitted any ranges and their location for the compile unit.
|
||||
if (DebugRangeSymbols.size()) {
|
||||
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_ranges_base,
|
||||
- dwarf::DW_FORM_sec_offset, DwarfDebugRangeSectionSym);
|
||||
+ NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_ranges_base,
|
||||
+ DwarfDebugRangeSectionSym);
|
||||
else
|
||||
NewCU->addUInt(Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4,
|
||||
0);
|
||||
Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
===================================================================
|
||||
--- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
+++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
@@ -227,6 +227,26 @@ void CompileUnit::addLabel(DIEBlock *Die, dwarf::F
|
||||
addLabel(Die, (dwarf::Attribute)0, Form, Label);
|
||||
}
|
||||
|
||||
+/// addSectionLabel - Add a Dwarf section label attribute data and value.
|
||||
+///
|
||||
+void CompileUnit::addSectionLabel(DIE *Die, dwarf::Attribute Attribute,
|
||||
+ const MCSymbol *Label) {
|
||||
+ if (DD->getDwarfVersion() >= 4)
|
||||
+ addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label);
|
||||
+ else
|
||||
+ addLabel(Die, Attribute, dwarf::DW_FORM_data4, Label);
|
||||
+}
|
||||
+
|
||||
+/// addSectionOffset - Add an offset into a section attribute data and value.
|
||||
+///
|
||||
+void CompileUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute,
|
||||
+ uint64_t Integer) {
|
||||
+ if (DD->getDwarfVersion() >= 4)
|
||||
+ addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer);
|
||||
+ else
|
||||
+ addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);
|
||||
+}
|
||||
+
|
||||
/// addLabelAddress - Add a dwarf label attribute data and value using
|
||||
/// DW_FORM_addr or DW_FORM_GNU_addr_index.
|
||||
///
|
||||
@@ -264,13 +284,15 @@ void CompileUnit::addOpAddress(DIEBlock *Die, cons
|
||||
}
|
||||
}
|
||||
|
||||
-/// addDelta - Add a label delta attribute data and value.
|
||||
+/// addSectionDelta - Add a section label delta attribute data and value.
|
||||
///
|
||||
-void CompileUnit::addDelta(DIE *Die, dwarf::Attribute Attribute,
|
||||
- dwarf::Form Form, const MCSymbol *Hi,
|
||||
- const MCSymbol *Lo) {
|
||||
+void CompileUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute,
|
||||
+ const MCSymbol *Hi, const MCSymbol *Lo) {
|
||||
DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo);
|
||||
- Die->addValue(Attribute, Form, Value);
|
||||
+ if (DD->getDwarfVersion() >= 4)
|
||||
+ Die->addValue(Attribute, dwarf::DW_FORM_sec_offset, Value);
|
||||
+ else
|
||||
+ Die->addValue(Attribute, dwarf::DW_FORM_data4, Value);
|
||||
}
|
||||
|
||||
/// addDIEEntry - Add a DIE attribute data and value.
|
||||
@@ -1768,10 +1790,8 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable
|
||||
|
||||
unsigned Offset = DV.getDotDebugLocOffset();
|
||||
if (Offset != ~0U) {
|
||||
- addLabel(VariableDie, dwarf::DW_AT_location,
|
||||
- DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
|
||||
- : dwarf::DW_FORM_data4,
|
||||
- Asm->GetTempSymbol("debug_loc", Offset));
|
||||
+ addSectionLabel(VariableDie, dwarf::DW_AT_location,
|
||||
+ Asm->GetTempSymbol("debug_loc", Offset));
|
||||
DV.setDIE(VariableDie);
|
||||
return VariableDie;
|
||||
}
|
||||
Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
|
||||
===================================================================
|
||||
--- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
|
||||
+++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
|
||||
@@ -209,6 +209,14 @@ class CompileUnit {
|
||||
|
||||
void addLabel(DIEBlock *Die, dwarf::Form Form, const MCSymbol *Label);
|
||||
|
||||
+ /// addSectionLabel - Add a Dwarf section label attribute data and value.
|
||||
+ ///
|
||||
+ void addSectionLabel(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Label);
|
||||
+
|
||||
+ /// addSectionOffset - Add an offset into a section attribute data and value.
|
||||
+ ///
|
||||
+ void addSectionOffset(DIE *Die, dwarf::Attribute Attribute, uint64_t Integer);
|
||||
+
|
||||
/// addLabelAddress - Add a dwarf label attribute data and value using
|
||||
/// either DW_FORM_addr or DW_FORM_GNU_addr_index.
|
||||
///
|
||||
@@ -219,10 +227,9 @@ class CompileUnit {
|
||||
///
|
||||
void addOpAddress(DIEBlock *Die, const MCSymbol *Label);
|
||||
|
||||
- /// addDelta - Add a label delta attribute data and value.
|
||||
- ///
|
||||
- void addDelta(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, const MCSymbol *Hi,
|
||||
- const MCSymbol *Lo);
|
||||
+ /// addSectionDelta - Add a label delta attribute data and value.
|
||||
+ void addSectionDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi,
|
||||
+ const MCSymbol *Lo);
|
||||
|
||||
/// addDIEEntry - Add a DIE attribute data and value.
|
||||
///
|
||||
Index: test/DebugInfo/X86/gnu-public-names.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/gnu-public-names.ll
|
||||
+++ test/DebugInfo/X86/gnu-public-names.ll
|
||||
@@ -1,5 +1,6 @@
|
||||
; RUN: llc -mtriple=x86_64-pc-linux-gnu -generate-gnu-dwarf-pub-sections < %s | FileCheck -check-prefix=ASM %s
|
||||
; RUN: llc -mtriple=x86_64-pc-linux-gnu -generate-gnu-dwarf-pub-sections -filetype=obj < %s | llvm-dwarfdump - | FileCheck %s
|
||||
+; RUN: llc -mtriple=x86_64-pc-linux-gnu -generate-gnu-dwarf-pub-sections -filetype=obj -dwarf-version=3 < %s | llvm-dwarfdump - | FileCheck %s -check-prefix=DWARF3
|
||||
; ModuleID = 'dwarf-public-names.cpp'
|
||||
;
|
||||
; Generated from:
|
||||
@@ -123,6 +124,85 @@
|
||||
; CHECK-DAG: [[D]] EXTERNAL TYPE "ns::D"
|
||||
; CHECK-DAG: [[INT]] STATIC TYPE "int"
|
||||
|
||||
+; DWARF3: .debug_info contents:
|
||||
+; DWARF3: DW_AT_GNU_pubnames [DW_FORM_data4] (0x00000000)
|
||||
+; DWARF3: DW_AT_GNU_pubtypes [DW_FORM_data4] (0x00000000)
|
||||
+
|
||||
+; DWARF3: [[C:[0-9a-f]+]]: DW_TAG_structure_type
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "C"
|
||||
+
|
||||
+; DWARF3: [[STATIC_MEM_DECL:[0-9a-f]+]]: DW_TAG_member
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "static_member_variable"
|
||||
+
|
||||
+; DWARF3: [[MEM_FUNC_DECL:[0-9a-f]+]]: DW_TAG_subprogram
|
||||
+; DWARF3-NEXT: DW_AT_MIPS_linkage_name
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "member_function"
|
||||
+
|
||||
+; DWARF3: [[STATIC_MEM_FUNC_DECL:[0-9a-f]+]]: DW_TAG_subprogram
|
||||
+; DWARF3-NEXT: DW_AT_MIPS_linkage_name
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "static_member_function"
|
||||
+
|
||||
+; DWARF3: [[INT:[0-9a-f]+]]: DW_TAG_base_type
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "int"
|
||||
+
|
||||
+; DWARF3: [[STATIC_MEM_VAR:[0-9a-f]+]]: DW_TAG_variable
|
||||
+; DWARF3-NEXT: DW_AT_specification {{.*}}[[STATIC_MEM_DECL]]
|
||||
+
|
||||
+; DWARF3: [[GLOB_VAR:[0-9a-f]+]]: DW_TAG_variable
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "global_variable"
|
||||
+
|
||||
+; DWARF3: [[NS:[0-9a-f]+]]: DW_TAG_namespace
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "ns"
|
||||
+
|
||||
+; DWARF3: [[GLOB_NS_VAR_DECL:[0-9a-f]+]]: DW_TAG_variable
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "global_namespace_variable"
|
||||
+
|
||||
+; DWARF3: [[D_VAR_DECL:[0-9a-f]+]]: DW_TAG_variable
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "d"
|
||||
+
|
||||
+; DWARF3: [[D:[0-9a-f]+]]: DW_TAG_structure_type
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "D"
|
||||
+
|
||||
+; DWARF3: [[GLOB_NS_FUNC:[0-9a-f]+]]: DW_TAG_subprogram
|
||||
+; DWARF3-NEXT: DW_AT_MIPS_linkage_name
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "global_namespace_function"
|
||||
+
|
||||
+; DWARF3: [[GLOB_NS_VAR:[0-9a-f]+]]: DW_TAG_variable
|
||||
+; DWARF3-NEXT: DW_AT_specification {{.*}}[[GLOB_NS_VAR_DECL]]
|
||||
+
|
||||
+; DWARF3: [[D_VAR:[0-9a-f]+]]: DW_TAG_variable
|
||||
+; DWARF3-NEXT: DW_AT_specification {{.*}}[[D_VAR_DECL]]
|
||||
+
|
||||
+; DWARF3: [[MEM_FUNC:[0-9a-f]+]]: DW_TAG_subprogram
|
||||
+; DWARF3-NEXT: DW_AT_specification {{.*}}[[MEM_FUNC_DECL]]
|
||||
+
|
||||
+; DWARF3: [[STATIC_MEM_FUNC:[0-9a-f]+]]: DW_TAG_subprogram
|
||||
+; DWARF3-NEXT: DW_AT_specification {{.*}}[[STATIC_MEM_FUNC_DECL]]
|
||||
+
|
||||
+; DWARF3: [[GLOBAL_FUNC:[0-9a-f]+]]: DW_TAG_subprogram
|
||||
+; DWARF3-NEXT: DW_AT_MIPS_linkage_name
|
||||
+; DWARF3-NEXT: DW_AT_name {{.*}} "global_function"
|
||||
+
|
||||
+; DWARF3-LABEL: .debug_gnu_pubnames contents:
|
||||
+; DWARF3-NEXT: length = 0x000000e7 version = 0x0002 unit_offset = 0x00000000 unit_size = 0x0000018b
|
||||
+; DWARF3-NEXT: Offset Linkage Kind Name
|
||||
+; DWARF3-DAG: [[GLOBAL_FUNC]] EXTERNAL FUNCTION "global_function"
|
||||
+; DWARF3-DAG: [[NS]] EXTERNAL TYPE "ns"
|
||||
+; DWARF3-DAG: [[MEM_FUNC]] EXTERNAL FUNCTION "C::member_function"
|
||||
+; DWARF3-DAG: [[GLOB_VAR]] EXTERNAL VARIABLE "global_variable"
|
||||
+; DWARF3-DAG: [[GLOB_NS_VAR]] EXTERNAL VARIABLE "ns::global_namespace_variable"
|
||||
+; DWARF3-DAG: [[GLOB_NS_FUNC]] EXTERNAL FUNCTION "ns::global_namespace_function"
|
||||
+; DWARF3-DAG: [[D_VAR]] EXTERNAL VARIABLE "ns::d"
|
||||
+; DWARF3-DAG: [[STATIC_MEM_VAR]] EXTERNAL VARIABLE "C::static_member_variable"
|
||||
+; DWARF3-DAG: [[STATIC_MEM_FUNC]] EXTERNAL FUNCTION "C::static_member_function"
|
||||
+
|
||||
+
|
||||
+; DWARF3-LABEL: debug_gnu_pubtypes contents:
|
||||
+; DWARF3: Offset Linkage Kind Name
|
||||
+; DWARF3-DAG: [[C]] EXTERNAL TYPE "C"
|
||||
+; DWARF3-DAG: [[D]] EXTERNAL TYPE "ns::D"
|
||||
+; DWARF3-DAG: [[INT]] STATIC TYPE "int"
|
||||
+
|
||||
%struct.C = type { i8 }
|
||||
%"struct.ns::D" = type { i32 }
|
||||
|
||||
Index: test/DebugInfo/X86/stmt-list-multiple-compile-units.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/stmt-list-multiple-compile-units.ll
|
||||
+++ test/DebugInfo/X86/stmt-list-multiple-compile-units.ll
|
||||
@@ -1,5 +1,7 @@
|
||||
; RUN: llc -O0 %s -mtriple=x86_64-apple-darwin -filetype=obj -o %t
|
||||
; RUN: llvm-dwarfdump %t | FileCheck %s
|
||||
+; RUN: llc -O0 %s -mtriple=x86_64-apple-darwin -filetype=obj -o %t -dwarf-version=3
|
||||
+; RUN: llvm-dwarfdump %t | FileCheck %s -check-prefix=DWARF3
|
||||
; RUN: llc < %s -O0 -mtriple=x86_64-apple-macosx10.7 | FileCheck %s -check-prefix=ASM
|
||||
|
||||
; rdar://13067005
|
||||
@@ -6,11 +8,11 @@
|
||||
; CHECK: .debug_info contents:
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
-; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x00000000)
|
||||
+; CHECK: DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000)
|
||||
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
-; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x0000003c)
|
||||
+; CHECK: DW_AT_stmt_list [DW_FORM_sec_offset] (0x0000003c)
|
||||
|
||||
; CHECK: .debug_line contents:
|
||||
; CHECK-NEXT: Line table prologue:
|
||||
@@ -21,6 +23,24 @@
|
||||
; CHECK: file_names[ 1] 0 0x00000000 0x00000000 simple2.c
|
||||
; CHECK-NOT: file_names
|
||||
|
||||
+; DWARF3: .debug_info contents:
|
||||
+; DWARF3: DW_TAG_compile_unit
|
||||
+; DWARF3: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
+; DWARF3: DW_AT_stmt_list [DW_FORM_data4] (0x00000000)
|
||||
+
|
||||
+; DWARF3: DW_TAG_compile_unit
|
||||
+; DWARF3: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
+; DWARF3: DW_AT_stmt_list [DW_FORM_data4] (0x0000003c)
|
||||
+
|
||||
+; DWARF3: .debug_line contents:
|
||||
+; DWARF3-NEXT: Line table prologue:
|
||||
+; DWARF3-NEXT: total_length: 0x00000038
|
||||
+; DWARF3: file_names[ 1] 0 0x00000000 0x00000000 simple.c
|
||||
+; DWARF3: Line table prologue:
|
||||
+; DWARF3-NEXT: total_length: 0x00000039
|
||||
+; DWARF3: file_names[ 1] 0 0x00000000 0x00000000 simple2.c
|
||||
+; DWARF3-NOT: file_names
|
||||
+
|
||||
; PR15408
|
||||
; ASM: L__DWARF__debug_info_begin0:
|
||||
; ASM: .long 0 ## DW_AT_stmt_list
|
||||
Index: test/DebugInfo/X86/block-capture.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/block-capture.ll
|
||||
+++ test/DebugInfo/X86/block-capture.ll
|
||||
@@ -1,5 +1,7 @@
|
||||
; RUN: llc -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj
|
||||
; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
|
||||
+; RUN: llc -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj -dwarf-version=3
|
||||
+; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s -check-prefix=DWARF3
|
||||
|
||||
; Checks that we emit debug info for the block variable declare.
|
||||
; CHECK: DW_TAG_subprogram [3]
|
||||
@@ -7,6 +9,11 @@
|
||||
; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "block")
|
||||
; CHECK: DW_AT_location [DW_FORM_sec_offset] ({{.*}})
|
||||
|
||||
+; DWARF3: DW_TAG_subprogram [3]
|
||||
+; DWARF3: DW_TAG_variable [5]
|
||||
+; DWARF3: DW_AT_name [DW_FORM_strp] ( .debug_str[{{.*}}] = "block")
|
||||
+; DWARF3: DW_AT_location [DW_FORM_data4] ({{.*}})
|
||||
+
|
||||
%struct.__block_descriptor = type { i64, i64 }
|
||||
%struct.__block_literal_generic = type { i8*, i32, i32, i8*, %struct.__block_descriptor* }
|
||||
|
||||
Index: test/DebugInfo/X86/op_deref.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/op_deref.ll
|
||||
+++ test/DebugInfo/X86/op_deref.ll
|
||||
@@ -1,5 +1,7 @@
|
||||
; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj
|
||||
; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s -check-prefix=DW-CHECK
|
||||
+; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o %t -filetype=obj -dwarf-version=3
|
||||
+; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s -check-prefix=DWARF3
|
||||
|
||||
; DW-CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000067] = "vla")
|
||||
; FIXME: The location here needs to be fixed, but llvm-dwarfdump doesn't handle
|
||||
@@ -6,6 +8,11 @@
|
||||
; DW_AT_location lists yet.
|
||||
; DW-CHECK: DW_AT_location [DW_FORM_sec_offset] (0x00000000)
|
||||
|
||||
+; DWARF3: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000067] = "vla")
|
||||
+; FIXME: The location here needs to be fixed, but llvm-dwarfdump doesn't handle
|
||||
+; DW_AT_location lists yet.
|
||||
+; DWARF3: DW_AT_location [DW_FORM_data4] (0x00000000)
|
||||
+
|
||||
; Unfortunately llvm-dwarfdump can't unparse a list of DW_AT_locations
|
||||
; right now, so we check the asm output:
|
||||
; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o - -filetype=asm | FileCheck %s -check-prefix=ASM-CHECK
|
||||
Index: test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll
|
||||
+++ test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll
|
||||
@@ -1,7 +1,10 @@
|
||||
; RUN: llc -mtriple=i686-w64-mingw32 -o %t -filetype=obj %s
|
||||
; RUN: llvm-dwarfdump -debug-dump=all %t | FileCheck %s
|
||||
+; RUN: llc -mtriple=i686-w64-mingw32 -o %t -filetype=obj -dwarf-version=3 %s
|
||||
+; RUN: llvm-dwarfdump -debug-dump=all %t | FileCheck %s -check-prefix=DWARF3
|
||||
|
||||
; CHECK: DW_AT_stmt_list [DW_FORM_sec_offset]
|
||||
+; DWARF3: DW_AT_stmt_list [DW_FORM_data4]
|
||||
;
|
||||
; generated from:
|
||||
; clang -g -S -emit-llvm test.c -o test.ll
|
||||
@@ -36,6 +39,6 @@ attributes #0 = { nounwind "less-precise-fpmad"="f
|
||||
!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
|
||||
!7 = metadata !{metadata !8}
|
||||
!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
|
||||
-!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 3}
|
||||
+!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
|
||||
!10 = metadata !{i32 3, i32 0, metadata !4, null}
|
||||
!11 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
Pull in r198385 from upstream llvm trunk (by David Blaikie):
|
||||
|
||||
Reverting r193835 due to weirdness with Go...
|
||||
|
||||
Apologies for the noise - we're seeing some Go failures with cgo
|
||||
interacting with Clang's debug info due to this change.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/261991
|
||||
|
||||
Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
===================================================================
|
||||
--- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
+++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
@@ -1845,9 +1845,6 @@ void CompileUnit::constructMemberDIE(DIE &Buffer,
|
||||
|
||||
addSourceLine(MemberDie, DT);
|
||||
|
||||
- DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock();
|
||||
- addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
|
||||
-
|
||||
if (DT.getTag() == dwarf::DW_TAG_inheritance && DT.isVirtual()) {
|
||||
|
||||
// For C++, virtual base classes are not at fixed offset. Use following
|
||||
@@ -1892,7 +1889,11 @@ void CompileUnit::constructMemberDIE(DIE &Buffer,
|
||||
} else
|
||||
// This is not a bitfield.
|
||||
OffsetInBytes = DT.getOffsetInBits() >> 3;
|
||||
- addUInt(MemberDie, dwarf::DW_AT_data_member_location, None, OffsetInBytes);
|
||||
+
|
||||
+ DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock();
|
||||
+ addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
|
||||
+ addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
|
||||
+ addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
|
||||
}
|
||||
|
||||
if (DT.isProtected())
|
||||
Index: test/DebugInfo/X86/data_member_location.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/data_member_location.ll
|
||||
+++ test/DebugInfo/X86/data_member_location.ll
|
||||
@@ -11,11 +11,11 @@
|
||||
|
||||
; CHECK: DW_AT_name {{.*}} "c"
|
||||
; CHECK-NOT: DW_TAG
|
||||
-; CHECK: DW_AT_data_member_location {{.*}} (0x00)
|
||||
+; CHECK: DW_AT_data_member_location {{.*}} (<0x02> 23 00 )
|
||||
|
||||
; CHECK: DW_AT_name {{.*}} "i"
|
||||
; CHECK-NOT: DW_TAG
|
||||
-; CHECK: DW_AT_data_member_location {{.*}} (0x04)
|
||||
+; CHECK: DW_AT_data_member_location {{.*}} (<0x02> 23 04 )
|
||||
|
||||
%struct.foo = type { i8, i32 }
|
||||
|
||||
Index: test/DebugInfo/X86/concrete_out_of_line.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/concrete_out_of_line.ll
|
||||
+++ test/DebugInfo/X86/concrete_out_of_line.ll
|
||||
@@ -7,7 +7,7 @@
|
||||
; first check that we have a TAG_subprogram at a given offset and it has
|
||||
; AT_inline.
|
||||
|
||||
-; CHECK: 0x0000011c: DW_TAG_subprogram [17]
|
||||
+; CHECK: 0x0000011e: DW_TAG_subprogram [17]
|
||||
; CHECK-NEXT: DW_AT_specification
|
||||
; CHECK-NEXT: DW_AT_inline
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
; and then that a TAG_subprogram refers to it with AT_abstract_origin.
|
||||
|
||||
-; CHECK: 0x0000015d: DW_TAG_subprogram [19]
|
||||
-; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x011c => {0x0000011c})
|
||||
+; CHECK: 0x0000015f: DW_TAG_subprogram [19]
|
||||
+; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x011e => {0x0000011e})
|
||||
|
||||
define i32 @_ZN17nsAutoRefCnt7ReleaseEv() {
|
||||
entry:
|
||||
Index: test/DebugInfo/X86/generate-odr-hash.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/generate-odr-hash.ll
|
||||
+++ test/DebugInfo/X86/generate-odr-hash.ll
|
||||
@@ -1,5 +1,8 @@
|
||||
; REQUIRES: object-emission
|
||||
|
||||
+; Fail while investigating problem with non-block representations of member offsets.
|
||||
+; XFAIL: *
|
||||
+
|
||||
; RUN: llc %s -o %t -filetype=obj -O0 -generate-odr-hash -mtriple=x86_64-unknown-linux-gnu
|
||||
; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
|
||||
;
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
Pull in r198389 from upstream llvm trunk (by David Blaikie):
|
||||
|
||||
Revert "Reverting r193835 due to weirdness with Go..."
|
||||
|
||||
The cgo problem was that it wants dwarf2 which doesn't support direct
|
||||
constant encoding of the location. So let's add support for dwarf2
|
||||
encoding (using a location expression) of data member locations.
|
||||
|
||||
This reverts commit r198385.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/261991
|
||||
|
||||
Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
===================================================================
|
||||
--- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
+++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
|
||||
@@ -1890,10 +1890,14 @@ void CompileUnit::constructMemberDIE(DIE &Buffer,
|
||||
// This is not a bitfield.
|
||||
OffsetInBytes = DT.getOffsetInBits() >> 3;
|
||||
|
||||
- DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock();
|
||||
- addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
|
||||
- addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
|
||||
- addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
|
||||
+ if (DD->getDwarfVersion() <= 2) {
|
||||
+ DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock();
|
||||
+ addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
|
||||
+ addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
|
||||
+ addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
|
||||
+ } else
|
||||
+ addUInt(MemberDie, dwarf::DW_AT_data_member_location, None,
|
||||
+ OffsetInBytes);
|
||||
}
|
||||
|
||||
if (DT.isProtected())
|
||||
Index: test/DebugInfo/X86/data_member_location.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/data_member_location.ll
|
||||
+++ test/DebugInfo/X86/data_member_location.ll
|
||||
@@ -1,4 +1,5 @@
|
||||
; RUN: llc -mtriple=x86_64-linux -O0 -o - -filetype=obj < %s | llvm-dwarfdump -debug-dump=info -| FileCheck %s
|
||||
+; RUN: llc -mtriple=x86_64-linux -dwarf-version=2 -O0 -o - -filetype=obj < %s | llvm-dwarfdump -debug-dump=info -| FileCheck -check-prefix=DWARF2 %s
|
||||
|
||||
; Generated from Clang with the following source:
|
||||
;
|
||||
@@ -11,12 +12,20 @@
|
||||
|
||||
; CHECK: DW_AT_name {{.*}} "c"
|
||||
; CHECK-NOT: DW_TAG
|
||||
-; CHECK: DW_AT_data_member_location {{.*}} (<0x02> 23 00 )
|
||||
+; CHECK: DW_AT_data_member_location {{.*}} (0x00)
|
||||
|
||||
; CHECK: DW_AT_name {{.*}} "i"
|
||||
; CHECK-NOT: DW_TAG
|
||||
-; CHECK: DW_AT_data_member_location {{.*}} (<0x02> 23 04 )
|
||||
+; CHECK: DW_AT_data_member_location {{.*}} (0x04)
|
||||
|
||||
+; DWARF2: DW_AT_name {{.*}} "c"
|
||||
+; DWARF2-NOT: DW_TAG
|
||||
+; DWARF2: DW_AT_data_member_location {{.*}} (<0x02> 23 00 )
|
||||
+
|
||||
+; DWARF2: DW_AT_name {{.*}} "i"
|
||||
+; DWARF2-NOT: DW_TAG
|
||||
+; DWARF2: DW_AT_data_member_location {{.*}} (<0x02> 23 04 )
|
||||
+
|
||||
%struct.foo = type { i8, i32 }
|
||||
|
||||
@f = global %struct.foo zeroinitializer, align 4
|
||||
Index: test/DebugInfo/X86/concrete_out_of_line.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/concrete_out_of_line.ll
|
||||
+++ test/DebugInfo/X86/concrete_out_of_line.ll
|
||||
@@ -7,7 +7,7 @@
|
||||
; first check that we have a TAG_subprogram at a given offset and it has
|
||||
; AT_inline.
|
||||
|
||||
-; CHECK: 0x0000011e: DW_TAG_subprogram [17]
|
||||
+; CHECK: 0x0000011c: DW_TAG_subprogram [17]
|
||||
; CHECK-NEXT: DW_AT_specification
|
||||
; CHECK-NEXT: DW_AT_inline
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
; and then that a TAG_subprogram refers to it with AT_abstract_origin.
|
||||
|
||||
-; CHECK: 0x0000015f: DW_TAG_subprogram [19]
|
||||
-; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x011e => {0x0000011e})
|
||||
+; CHECK: 0x0000015d: DW_TAG_subprogram [19]
|
||||
+; CHECK-NEXT: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x011c => {0x0000011c})
|
||||
|
||||
define i32 @_ZN17nsAutoRefCnt7ReleaseEv() {
|
||||
entry:
|
||||
Index: test/DebugInfo/X86/generate-odr-hash.ll
|
||||
===================================================================
|
||||
--- test/DebugInfo/X86/generate-odr-hash.ll
|
||||
+++ test/DebugInfo/X86/generate-odr-hash.ll
|
||||
@@ -1,8 +1,5 @@
|
||||
; REQUIRES: object-emission
|
||||
|
||||
-; Fail while investigating problem with non-block representations of member offsets.
|
||||
-; XFAIL: *
|
||||
-
|
||||
; RUN: llc %s -o %t -filetype=obj -O0 -generate-odr-hash -mtriple=x86_64-unknown-linux-gnu
|
||||
; RUN: llvm-dwarfdump -debug-dump=info %t | FileCheck %s
|
||||
;
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
Pull in r198028 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add MCInstPrinter implementation for SPARC.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/InstPrinter/LLVMBuild.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/LLVMBuild.txt
|
||||
+++ lib/Target/Sparc/InstPrinter/LLVMBuild.txt
|
||||
@@ -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/SparcInstPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
@@ -0,0 +1,95 @@
|
||||
+//===-- 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
|
||||
+// Uncomment the following line once we are ready to use MCAsmWriter.
|
||||
+//#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)
|
||||
+{
|
||||
+ printInstruction(MI, O);
|
||||
+ printAnnotation(O, Annot);
|
||||
+}
|
||||
+
|
||||
+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();
|
||||
+ 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/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/InstPrinter/CMakeLists.txt
|
||||
@@ -0,0 +1,3 @@
|
||||
+add_llvm_library(LLVMSparcAsmPrinter
|
||||
+ SparcInstPrinter.cpp
|
||||
+ )
|
||||
Index: lib/Target/Sparc/InstPrinter/Makefile
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/Makefile
|
||||
+++ lib/Target/Sparc/InstPrinter/Makefile
|
||||
@@ -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.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
|
||||
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
|
||||
@@ -0,0 +1,46 @@
|
||||
+//===-- 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);
|
||||
+
|
||||
+ // Autogenerated by tblgen.
|
||||
+ void printInstruction(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
|
||||
+++ lib/Target/Sparc/LLVMBuild.txt
|
||||
@@ -16,7 +16,7 @@
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[common]
|
||||
-subdirectories = MCTargetDesc TargetInfo
|
||||
+subdirectories = InstPrinter MCTargetDesc TargetInfo
|
||||
|
||||
[component_0]
|
||||
type = TargetGroup
|
||||
@@ -29,6 +29,6 @@ has_jit = 1
|
||||
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/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/CMakeLists.txt
|
||||
@@ -29,3 +29,4 @@ add_dependencies(LLVMSparcCodeGen SparcCommonTable
|
||||
|
||||
add_subdirectory(TargetInfo)
|
||||
add_subdirectory(MCTargetDesc)
|
||||
+add_subdirectory(InstPrinter)
|
||||
Index: lib/Target/Sparc/Makefile
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Makefile
|
||||
+++ lib/Target/Sparc/Makefile
|
||||
@@ -17,7 +17,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenI
|
||||
SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
|
||||
SparcGenCodeEmitter.inc
|
||||
|
||||
-DIRS = TargetInfo MCTargetDesc
|
||||
+DIRS = InstPrinter TargetInfo MCTargetDesc
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
Pull in r198029 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add target specific MCExpr class to handle sparc specific modifiers like %hi, %lo, etc.,
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
@@ -0,0 +1,84 @@
|
||||
+//===-- 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/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 = 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;
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ const MCExpr *Expr = getSubExpr();
|
||||
+ Expr->print(OS);
|
||||
+ if (closeParen)
|
||||
+ OS << ')';
|
||||
+}
|
||||
+
|
||||
+bool
|
||||
+SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
|
||||
+ const MCAsmLayout *Layout) const {
|
||||
+ assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl");
|
||||
+ return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
|
||||
+ assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups");
|
||||
+}
|
||||
+
|
||||
+void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const {
|
||||
+ assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols");
|
||||
+}
|
||||
Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
@@ -1,6 +1,7 @@
|
||||
add_llvm_library(LLVMSparcDesc
|
||||
SparcMCTargetDesc.cpp
|
||||
SparcMCAsmInfo.cpp
|
||||
+ SparcMCExpr.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMSparcDesc SparcCommonTableGen)
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
@@ -0,0 +1,98 @@
|
||||
+//====- 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 "llvm/MC/MCExpr.h"
|
||||
+
|
||||
+namespace llvm {
|
||||
+
|
||||
+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_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; }
|
||||
+
|
||||
+ /// @}
|
||||
+ 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; }
|
||||
+
|
||||
+
|
||||
+};
|
||||
+
|
||||
+} // end namespace llvm.
|
||||
+
|
||||
+#endif
|
||||
|
|
@ -1,678 +0,0 @@
|
|||
Pull in r198030 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Lower and MachineInstr to MC and print assembly using MCInstPrinter.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
|
||||
@@ -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/MCTargetDesc/LLVMBuild.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt
|
||||
+++ lib/Target/Sparc/MCTargetDesc/LLVMBuild.txt
|
||||
@@ -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/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
@@ -2,6 +2,7 @@ add_llvm_library(LLVMSparcDesc
|
||||
SparcMCTargetDesc.cpp
|
||||
SparcMCAsmInfo.cpp
|
||||
SparcMCExpr.cpp
|
||||
+ SparcTargetStreamer.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMSparcDesc SparcCommonTableGen)
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
@@ -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"
|
||||
@@ -86,6 +88,28 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S
|
||||
X->InitMCCodeGenInfo(RM, CM, OL);
|
||||
return X;
|
||||
}
|
||||
+
|
||||
+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);
|
||||
@@ -106,4 +130,15 @@ extern "C" void LLVMInitializeSparcTargetMC() {
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(TheSparcTarget,
|
||||
createSparcMCSubtargetInfo);
|
||||
+
|
||||
+ TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
|
||||
+ createMCAsmStreamer);
|
||||
+ TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
|
||||
+ createMCAsmStreamer);
|
||||
+
|
||||
+ // Register the MCInstPrinter
|
||||
+ TargetRegistry::RegisterMCInstPrinter(TheSparcTarget,
|
||||
+ createSparcMCInstPrinter);
|
||||
+ TargetRegistry::RegisterMCInstPrinter(TheSparcV9Target,
|
||||
+ createSparcMCInstPrinter);
|
||||
}
|
||||
Index: lib/Target/Sparc/SparcTargetStreamer.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcTargetStreamer.h
|
||||
+++ lib/Target/Sparc/SparcTargetStreamer.h
|
||||
@@ -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: lib/Target/Sparc/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/CMakeLists.txt
|
||||
@@ -23,6 +23,7 @@ add_llvm_target(SparcCodeGen
|
||||
SparcSelectionDAGInfo.cpp
|
||||
SparcJITInfo.cpp
|
||||
SparcCodeEmitter.cpp
|
||||
+ SparcMCInstLower.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMSparcCodeGen SparcCommonTableGen intrinsics_gen)
|
||||
Index: lib/Target/Sparc/Sparc.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Sparc.td
|
||||
+++ lib/Target/Sparc/Sparc.td
|
||||
@@ -65,6 +65,10 @@ def : Proc<"ultrasparc", [FeatureV9, FeatureV
|
||||
def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>;
|
||||
def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
|
||||
|
||||
+def SparcAsmWriter : AsmWriter {
|
||||
+ string AsmWriterClassName = "InstPrinter";
|
||||
+ bit isMCAsmWriter = 1;
|
||||
+}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declare the target which we are implementing
|
||||
@@ -73,4 +77,6 @@ def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV
|
||||
def Sparc : Target {
|
||||
// Pull in Instruction Info:
|
||||
let InstructionSet = SparcInstrInfo;
|
||||
+
|
||||
+ let AssemblyWriters = [SparcAsmWriter];
|
||||
}
|
||||
Index: lib/Target/Sparc/SparcMCInstLower.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcMCInstLower.cpp
|
||||
+++ lib/Target/Sparc/SparcMCInstLower.cpp
|
||||
@@ -0,0 +1,141 @@
|
||||
+//===-- 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/SparcBaseInfo.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;
|
||||
+ const MCSymbol *Symbol = 0;
|
||||
+
|
||||
+ unsigned TF = MO.getTargetFlags();
|
||||
+
|
||||
+ switch(TF) {
|
||||
+ default: llvm_unreachable("Unknown target flags on operand");
|
||||
+ case SPII::MO_NO_FLAG: Kind = SparcMCExpr::VK_Sparc_None; break;
|
||||
+ case SPII::MO_LO: Kind = SparcMCExpr::VK_Sparc_LO; break;
|
||||
+ case SPII::MO_HI: Kind = SparcMCExpr::VK_Sparc_HI; break;
|
||||
+ case SPII::MO_H44: Kind = SparcMCExpr::VK_Sparc_H44; break;
|
||||
+ case SPII::MO_M44: Kind = SparcMCExpr::VK_Sparc_M44; break;
|
||||
+ case SPII::MO_L44: Kind = SparcMCExpr::VK_Sparc_L44; break;
|
||||
+ case SPII::MO_HH: Kind = SparcMCExpr::VK_Sparc_HH; break;
|
||||
+ case SPII::MO_HM: Kind = SparcMCExpr::VK_Sparc_HM; break;
|
||||
+ case SPII::MO_TLS_GD_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_GD_HI22; break;
|
||||
+ case SPII::MO_TLS_GD_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_GD_LO10; break;
|
||||
+ case SPII::MO_TLS_GD_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_GD_ADD; break;
|
||||
+ case SPII::MO_TLS_GD_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_GD_CALL; break;
|
||||
+ case SPII::MO_TLS_LDM_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_HI22; break;
|
||||
+ case SPII::MO_TLS_LDM_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_LO10; break;
|
||||
+ case SPII::MO_TLS_LDM_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_ADD; break;
|
||||
+ case SPII::MO_TLS_LDM_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_CALL; break;
|
||||
+ case SPII::MO_TLS_LDO_HIX22:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_HIX22; break;
|
||||
+ case SPII::MO_TLS_LDO_LOX10:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_LOX10; break;
|
||||
+ case SPII::MO_TLS_LDO_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDO_ADD; break;
|
||||
+ case SPII::MO_TLS_IE_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_IE_HI22; break;
|
||||
+ case SPII::MO_TLS_IE_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LO10; break;
|
||||
+ case SPII::MO_TLS_IE_LD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LD; break;
|
||||
+ case SPII::MO_TLS_IE_LDX: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LDX; break;
|
||||
+ case SPII::MO_TLS_IE_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_ADD; break;
|
||||
+ case SPII::MO_TLS_LE_HIX22: Kind = SparcMCExpr::VK_Sparc_TLS_LE_HIX22; break;
|
||||
+ case SPII::MO_TLS_LE_LOX10: Kind = SparcMCExpr::VK_Sparc_TLS_LE_LOX10; break;
|
||||
+ }
|
||||
+
|
||||
+ 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/Sparc.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Sparc.h
|
||||
+++ lib/Target/Sparc/Sparc.h
|
||||
@@ -23,6 +23,9 @@ namespace llvm {
|
||||
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 @@ namespace llvm {
|
||||
FunctionPass *createSparcJITCodeEmitterPass(SparcTargetMachine &TM,
|
||||
JITCodeEmitter &JCE);
|
||||
|
||||
+ void LowerSparcMachineInstrToMCInst(const MachineInstr *MI,
|
||||
+ MCInst &OutMI,
|
||||
+ AsmPrinter &AP);
|
||||
} // end namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
Index: lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -16,12 +16,17 @@
|
||||
#include "Sparc.h"
|
||||
#include "SparcInstrInfo.h"
|
||||
#include "SparcTargetMachine.h"
|
||||
+#include "SparcTargetStreamer.h"
|
||||
+#include "InstPrinter/SparcInstPrinter.h"
|
||||
#include "MCTargetDesc/SparcBaseInfo.h"
|
||||
+#include "MCTargetDesc/SparcMCExpr.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.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 +36,9 @@ using namespace llvm;
|
||||
|
||||
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 +53,11 @@ namespace {
|
||||
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);
|
||||
+
|
||||
+ 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 +66,139 @@ namespace {
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O);
|
||||
|
||||
- bool printGetPCX(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS);
|
||||
-
|
||||
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 createPCXCallOP(MCSymbol *Label,
|
||||
+ MCContext &OutContext)
|
||||
+{
|
||||
+ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label,
|
||||
+ OutContext);
|
||||
+ const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None,
|
||||
+ MCSym, OutContext);
|
||||
+ return MCOperand::CreateExpr(expr);
|
||||
+}
|
||||
|
||||
+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 EmitOR(MCStreamer &OutStreamer, MCOperand &RS1,
|
||||
+ MCOperand &Imm, MCOperand &RD)
|
||||
+{
|
||||
+ MCInst ORInst;
|
||||
+ ORInst.setOpcode(SP::ORri);
|
||||
+ ORInst.addOperand(RD);
|
||||
+ ORInst.addOperand(RS1);
|
||||
+ ORInst.addOperand(Imm);
|
||||
+ OutStreamer.EmitInstruction(ORInst);
|
||||
+}
|
||||
+
|
||||
+void EmitADD(MCStreamer &OutStreamer,
|
||||
+ MCOperand &RS1, MCOperand &RS2, MCOperand &RD)
|
||||
+{
|
||||
+ MCInst ADDInst;
|
||||
+ ADDInst.setOpcode(SP::ADDrr);
|
||||
+ ADDInst.addOperand(RD);
|
||||
+ ADDInst.addOperand(RS1);
|
||||
+ ADDInst.addOperand(RS2);
|
||||
+ OutStreamer.EmitInstruction(ADDInst);
|
||||
+}
|
||||
+
|
||||
+static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
|
||||
+ MCStreamer &OutStreamer,
|
||||
+ MCContext &OutContext)
|
||||
+{
|
||||
+ const MachineOperand &MO = MI->getOperand(0);
|
||||
+ MCSymbol *StartLabel = OutContext.CreateTempSymbol();
|
||||
+ MCSymbol *EndLabel = OutContext.CreateTempSymbol();
|
||||
+ MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
|
||||
+ MCSymbol *GOTLabel =
|
||||
+ OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
|
||||
+
|
||||
+ assert(MO.getReg() != SP::O7 &&
|
||||
+ "%o7 is assigned as destination for getpcx!");
|
||||
+
|
||||
+ MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg());
|
||||
+ 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_HI,
|
||||
+ GOTLabel, StartLabel, SethiLabel,
|
||||
+ OutContext);
|
||||
+ EmitSETHI(OutStreamer, hiImm, MCRegOP);
|
||||
+ OutStreamer.EmitLabel(EndLabel);
|
||||
+ MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO,
|
||||
+ GOTLabel, StartLabel, EndLabel,
|
||||
+ OutContext);
|
||||
+ EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP);
|
||||
+ EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP);
|
||||
+}
|
||||
+
|
||||
+void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
|
||||
+{
|
||||
+ MCInst TmpInst;
|
||||
+
|
||||
+ switch (MI->getOpcode()) {
|
||||
+ default: break;
|
||||
+ case TargetOpcode::DBG_VALUE:
|
||||
+ // FIXME: Debug Value.
|
||||
+ return;
|
||||
+ case SP::GETPCX:
|
||||
+ LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext);
|
||||
+ return;
|
||||
+ }
|
||||
+ LowerSparcMachineInstrToMCInst(MI, TmpInst, *this);
|
||||
+ OutStreamer.EmitInstruction(TmpInst);
|
||||
+}
|
||||
+
|
||||
void SparcAsmPrinter::EmitFunctionBodyStart() {
|
||||
if (!TM.getSubtarget<SparcSubtarget>().is64Bit())
|
||||
return;
|
||||
@@ -90,7 +209,11 @@ void SparcAsmPrinter::EmitFunctionBodyStart() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,46 +349,6 @@ void SparcAsmPrinter::printMemOperand(const Machin
|
||||
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,
|
||||
Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
@@ -23,8 +23,7 @@
|
||||
using namespace llvm;
|
||||
|
||||
#define GET_INSTRUCTION_NAME
|
||||
-// Uncomment the following line once we are ready to use MCAsmWriter.
|
||||
-//#include "SparcGenAsmWriter.inc"
|
||||
+#include "SparcGenAsmWriter.inc"
|
||||
|
||||
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
|
||||
{
|
||||
Index: test/CodeGen/SPARC/exception.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/exception.ll
|
||||
+++ test/CodeGen/SPARC/exception.ll
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
; CHECK-LABEL: main:
|
||||
; CHECK: .cfi_startproc
|
||||
-; CHECK: .cfi_def_cfa_register 30
|
||||
+; CHECK: .cfi_def_cfa_register {{30|%fp}}
|
||||
; CHECK: .cfi_window_save
|
||||
; CHECK: .cfi_register 15, 31
|
||||
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
Pull in r198145 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9]: Implement lowering of long double (fp128) arguments in Sparc64 ABI.
|
||||
Also, pass fp128 arguments to varargs through integer registers if necessary.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/CodeGen/SPARC/64abi.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/64abi.ll
|
||||
+++ test/CodeGen/SPARC/64abi.ll
|
||||
@@ -411,3 +411,33 @@ entry:
|
||||
}
|
||||
|
||||
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
|
||||
+}
|
||||
+
|
||||
+
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -80,11 +80,14 @@ static bool CC_Sparc_Assign_f64(unsigned &ValNo, M
|
||||
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 +99,9 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &
|
||||
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) {
|
||||
@@ -998,9 +1004,10 @@ static void fixupVariableFloatArgs(SmallVectorImpl
|
||||
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 +1017,25 @@ static void fixupVariableFloatArgs(SmallVectorImpl
|
||||
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 +1111,46 @@ SparcTargetLowering::LowerCall_64(TargetLowering::
|
||||
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()) {
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
Pull in r198149 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9] For codegen generated library calls that return float, set inreg flag manually in LowerCall().
|
||||
This makes the sparc backend to generate Sparc64 ABI compliant code.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1252,6 +1252,12 @@ SparcTargetLowering::LowerCall_64(TargetLowering::
|
||||
SmallVector<CCValAssign, 16> RVLocs;
|
||||
CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(),
|
||||
DAG.getTarget(), RVLocs, *DAG.getContext());
|
||||
+
|
||||
+ // 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, CC_Sparc64);
|
||||
|
||||
// Copy all of the result registers out of their specified physreg.
|
||||
Index: test/CodeGen/SPARC/64abi.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/64abi.ll
|
||||
+++ test/CodeGen/SPARC/64abi.ll
|
||||
@@ -440,4 +440,25 @@ entry:
|
||||
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
|
||||
+
|
||||
+
|
||||
|
|
@ -1,368 +0,0 @@
|
|||
Pull in r198157 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9] Use separate instruction patterns for 64 bit arithmetic instructions instead of reusing 32 bit instruction patterns.
|
||||
This is done to avoid spilling the result of the 64-bit instructions to a 4-byte slot.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -227,7 +227,7 @@ void SparcAsmPrinter::printOperand(const MachineIn
|
||||
if (MI->getOpcode() == SP::CALL)
|
||||
assert(TF == SPII::MO_NO_FLAG &&
|
||||
"Cannot handle target flags on call address");
|
||||
- else if (MI->getOpcode() == SP::SETHIi)
|
||||
+ else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
|
||||
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
|
||||
@@ -250,7 +250,7 @@ void SparcAsmPrinter::printOperand(const MachineIn
|
||||
else if (MI->getOpcode() == SP::TLS_LDXrr)
|
||||
assert(TF == SPII::MO_TLS_IE_LDX &&
|
||||
"Cannot handle target flags on ldx for TLS");
|
||||
- else if (MI->getOpcode() == SP::XORri)
|
||||
+ else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
|
||||
assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) &&
|
||||
"Cannot handle target flags on xor for TLS");
|
||||
else
|
||||
Index: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -141,32 +141,36 @@ def : Pat<(i64 imm:$val),
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
// Register-register instructions.
|
||||
+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 : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
|
||||
|
||||
-def : Pat<(tlsadd i64:$a, i64:$b, tglobaltlsaddr:$sym),
|
||||
- (TLS_ADDrr $a, $b, $sym)>;
|
||||
+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))]>;
|
||||
|
||||
// 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)>;
|
||||
@@ -402,3 +406,38 @@ def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, im
|
||||
(MOVFCCri (as_i32imm $t), $f, imm:$cond)>;
|
||||
|
||||
} // Predicates = [Is64Bit]
|
||||
+
|
||||
+
|
||||
+// 64 bit SETHI
|
||||
+let Predicates = [Is64Bit] in {
|
||||
+def SETHIXi : F2_1<0b100,
|
||||
+ (outs IntRegs:$rd), (ins i64imm:$imm22),
|
||||
+ "sethi $imm22, $rd",
|
||||
+ [(set i64:$rd, SETHIimm:$imm22)]>;
|
||||
+}
|
||||
+// 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/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -210,15 +210,16 @@ def FCC_O : FCC_VAL<29>; // Ordered
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// 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),
|
||||
+ (outs RC:$dst), (ins RC:$b, RC:$c),
|
||||
!strconcat(OpcStr, " $b, $c, $dst"),
|
||||
- [(set i32:$dst, (OpNode i32:$b, i32:$c))]>;
|
||||
+ [(set Ty:$dst, (OpNode Ty:$b, Ty:$c))]>;
|
||||
def ri : F3_2<2, Op3Val,
|
||||
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
|
||||
+ (outs RC:$dst), (ins RC:$b, immOp:$c),
|
||||
!strconcat(OpcStr, " $b, $c, $dst"),
|
||||
- [(set i32:$dst, (OpNode i32:$b, (i32 simm13:$c)))]>;
|
||||
+ [(set Ty:$dst, (OpNode Ty:$b, (Ty simm13:$c)))]>;
|
||||
}
|
||||
|
||||
/// F3_12np multiclass - Define a normal F3_1/F3_2 pattern in one shot, with no
|
||||
@@ -464,7 +465,7 @@ let rd = 0, imm22 = 0 in
|
||||
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),
|
||||
@@ -474,7 +475,7 @@ def ANDNri : F3_2<2, 0b000101,
|
||||
(outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
|
||||
"andn $b, $c, $dst", []>;
|
||||
|
||||
-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),
|
||||
@@ -483,7 +484,7 @@ def ORNrr : F3_1<2, 0b000110,
|
||||
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>;
|
||||
+defm XOR : F3_12<"xor", 0b000011, xor, IntRegs, i32, i32imm>;
|
||||
|
||||
def XNORrr : F3_1<2, 0b000111,
|
||||
(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
||||
@@ -494,12 +495,12 @@ def XNORri : F3_2<2, 0b000111,
|
||||
"xnor $b, $c, $dst", []>;
|
||||
|
||||
// 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
|
||||
@@ -509,18 +510,18 @@ let Predicates = [Is32Bit] in
|
||||
[(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,
|
||||
@@ -542,7 +543,7 @@ let Uses = [ICC], Defs = [ICC] in
|
||||
// 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
|
||||
@@ -987,6 +988,8 @@ def : Pat<(i32 imm:$val),
|
||||
|
||||
|
||||
// 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 +1012,7 @@ def : Pat<(add iPTR:$r, (SPlo tglobaladdr:$in)), (
|
||||
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),
|
||||
Index: test/CodeGen/SPARC/64spill.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/64spill.ll
|
||||
+++ test/CodeGen/SPARC/64spill.ll
|
||||
@@ -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
|
||||
+}
|
||||
+
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
Pull in r198280 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9]: Use SRL instead of SLL to clear top 32-bits in ctpop:i32. SLL does not clear top 32 bit, only SRL does.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -967,13 +967,13 @@ let Predicates = [HasV9] in {
|
||||
}
|
||||
|
||||
// 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))>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Non-Instruction Patterns
|
||||
Index: test/CodeGen/SPARC/ctpop.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/ctpop.ll
|
||||
+++ test/CodeGen/SPARC/ctpop.ll
|
||||
@@ -1,8 +1,22 @@
|
||||
-; 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 | FileCheck %s -check-prefix=V9
|
||||
+; RUN: llc < %s -march=sparcv9 | 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: jmp %o7+8
|
||||
+; V9-NEXT: popc %o0, %o0
|
||||
+
|
||||
+; SPARC64-LABEL: test
|
||||
+; SPARC64: srl %o0, 0, %o0
|
||||
+; SPARC64: jmp %o7+8
|
||||
+; SPARC64: popc %o0, %o0
|
||||
+
|
||||
define i32 @test(i32 %X) {
|
||||
%Y = call i32 @llvm.ctpop.i32( i32 %X ) ; <i32> [#uses=1]
|
||||
ret i32 %Y
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
Pull in r198281 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9]: Custom lower UMULO/SMULO so that the arguments are send to __multi3() in correct order.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1525,6 +1525,9 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
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.
|
||||
@@ -2673,6 +2676,53 @@ static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op
|
||||
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);
|
||||
+}
|
||||
+
|
||||
SDValue SparcTargetLowering::
|
||||
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
@@ -2726,6 +2776,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Index: test/CodeGen/SPARC/64cond.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/64cond.ll
|
||||
+++ test/CodeGen/SPARC/64cond.ll
|
||||
@@ -111,6 +111,11 @@ entry:
|
||||
}
|
||||
|
||||
; 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
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
Pull in r198286 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Handle atomic loads/stores in sparc backend.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -975,6 +975,33 @@ let rs1 = 0 in
|
||||
def : Pat<(ctpop i32:$src),
|
||||
(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 = $rd" in {
|
||||
+ def SWAPrr : F3_1<3, 0b001111,
|
||||
+ (outs IntRegs:$rd), (ins IntRegs:$val, MEMrr:$addr),
|
||||
+ "swap [$addr], $rd",
|
||||
+ [(set i32:$rd, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>;
|
||||
+ def SWAPri : F3_2<3, 0b001111,
|
||||
+ (outs IntRegs:$rd), (ins IntRegs:$val, MEMri:$addr),
|
||||
+ "swap [$addr], $rd",
|
||||
+ [(set i32:$rd, (atomic_swap_32 ADDRri:$addr, i32:$val))]>;
|
||||
+}
|
||||
+
|
||||
+let Predicates = [HasV9], Constraints = "$swap = $rd" in
|
||||
+ def CASrr: F3_1<3, 0b111100,
|
||||
+ (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
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -1036,4 +1063,17 @@ def : Pat<(i32 (zextloadi1 ADDRri:$src)), (LDUBri
|
||||
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"
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1472,10 +1472,30 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
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);
|
||||
@@ -2723,6 +2743,16 @@ static SDValue LowerUMULO_SMULO(SDValue Op, Select
|
||||
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 {
|
||||
|
||||
@@ -2778,6 +2808,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -415,6 +415,32 @@ def SETHIXi : F2_1<0b100,
|
||||
"sethi $imm22, $rd",
|
||||
[(set i64:$rd, SETHIimm:$imm22)]>;
|
||||
}
|
||||
+
|
||||
+// ATOMICS.
|
||||
+let Predicates = [Is64Bit], Constraints = "$swap = $rd" in {
|
||||
+ def CASXrr: F3_1<3, 0b111110,
|
||||
+ (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]
|
||||
+
|
||||
// Global addresses, constant pool entries
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
Index: test/CodeGen/SPARC/atomics.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/atomics.ll
|
||||
+++ test/CodeGen/SPARC/atomics.ll
|
||||
@@ -0,0 +1,63 @@
|
||||
+; RUN: llc < %s -march=sparcv9 | 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
|
||||
+}
|
||||
|
|
@ -1,213 +0,0 @@
|
|||
Pull in r198480 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9]: Implement RETURNADDR and FRAMEADDR lowering in SPARC64.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -2415,7 +2415,8 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG
|
||||
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);
|
||||
|
||||
@@ -2422,32 +2423,49 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG
|
||||
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);
|
||||
@@ -2461,25 +2479,20 @@ static SDValue LowerRETURNADDR(SDValue Op, Selecti
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -2763,8 +2776,10 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons
|
||||
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);
|
||||
Index: test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
|
||||
+++ test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
|
||||
@@ -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 {
|
||||
@@ -15,6 +16,13 @@ entry:
|
||||
;V9: save %sp, -96, %sp
|
||||
;V9: jmp %i7+8
|
||||
;V9: restore %g0, %fp, %o0
|
||||
+
|
||||
+;SPARC64-LABEL: frameaddr
|
||||
+;SPARC64: save %sp, -128, %sp
|
||||
+;SPARC64: add %fp, 2047, %i0
|
||||
+;SPARC64: jmp %i7+8
|
||||
+;SPARC64: restore %g0, %g0, %g0
|
||||
+
|
||||
%0 = tail call i8* @llvm.frameaddress(i32 0)
|
||||
ret i8* %0
|
||||
}
|
||||
@@ -32,6 +40,14 @@ entry:
|
||||
;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 @@ entry:
|
||||
;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 @@ entry:
|
||||
;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
|
||||
}
|
||||
|
|
@ -1,844 +0,0 @@
|
|||
Pull in r198484 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add the initial implementation of an asm parser for sparc/sparcv9.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
@@ -123,13 +123,18 @@ extern "C" void LLVMInitializeSparcTargetMC() {
|
||||
|
||||
// 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);
|
||||
|
||||
TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
|
||||
createMCAsmStreamer);
|
||||
Index: lib/Target/Sparc/LLVMBuild.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/LLVMBuild.txt
|
||||
+++ lib/Target/Sparc/LLVMBuild.txt
|
||||
@@ -16,7 +16,7 @@
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[common]
|
||||
-subdirectories = InstPrinter MCTargetDesc TargetInfo
|
||||
+subdirectories = AsmParser InstPrinter MCTargetDesc TargetInfo
|
||||
|
||||
[component_0]
|
||||
type = TargetGroup
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -76,13 +76,25 @@ def ADDRrr : ComplexPattern<iPTR, 2, "SelectADDRrr
|
||||
def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [frameindex], []>;
|
||||
|
||||
// Address operands
|
||||
+def SparcMEMrrAsmOperand : AsmOperandClass {
|
||||
+ let Name = "MEMrr";
|
||||
+ let ParserMethod = "parseMEMrrOperand";
|
||||
+}
|
||||
+
|
||||
+def SparcMEMriAsmOperand : AsmOperandClass {
|
||||
+ let Name = "MEMri";
|
||||
+ let ParserMethod = "parseMEMriOperand";
|
||||
+}
|
||||
+
|
||||
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>;
|
||||
@@ -239,7 +251,10 @@ multiclass F3_12np<string OpcStr, bits<6> Op3Val>
|
||||
|
||||
// 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 {
|
||||
@@ -503,7 +518,7 @@ defm SRA : F3_12<"sra", 0b100111, sra, IntRegs, i3
|
||||
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",
|
||||
Index: lib/Target/Sparc/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/CMakeLists.txt
|
||||
@@ -4,6 +4,7 @@ tablegen(LLVM SparcGenRegisterInfo.inc -gen-regist
|
||||
tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM SparcGenCodeEmitter.inc -gen-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)
|
||||
@@ -31,3 +32,4 @@ add_dependencies(LLVMSparcCodeGen SparcCommonTable
|
||||
add_subdirectory(TargetInfo)
|
||||
add_subdirectory(MCTargetDesc)
|
||||
add_subdirectory(InstPrinter)
|
||||
+add_subdirectory(AsmParser)
|
||||
Index: lib/Target/Sparc/Makefile
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Makefile
|
||||
+++ lib/Target/Sparc/Makefile
|
||||
@@ -13,11 +13,12 @@ TARGET = Sparc
|
||||
|
||||
# Make sure that tblgen is run, first thing.
|
||||
BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \
|
||||
- SparcGenAsmWriter.inc SparcGenDAGISel.inc \
|
||||
+ SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \
|
||||
+ SparcGenDAGISel.inc \
|
||||
SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
|
||||
SparcGenCodeEmitter.inc
|
||||
|
||||
-DIRS = InstPrinter TargetInfo MCTargetDesc
|
||||
+DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
Index: lib/Target/Sparc/Sparc.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Sparc.td
|
||||
+++ lib/Target/Sparc/Sparc.td
|
||||
@@ -44,6 +44,10 @@ include "SparcInstrInfo.td"
|
||||
|
||||
def SparcInstrInfo : InstrInfo;
|
||||
|
||||
+def SparcAsmParser : AsmParser {
|
||||
+ bit ShouldEmitMatchRegisterName = 0;
|
||||
+}
|
||||
+
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SPARC processors supported.
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -77,6 +81,7 @@ def SparcAsmWriter : AsmWriter {
|
||||
def Sparc : Target {
|
||||
// Pull in Instruction Info:
|
||||
let InstructionSet = SparcInstrInfo;
|
||||
+ let AssemblyParsers = [SparcAsmParser];
|
||||
|
||||
let AssemblyWriters = [SparcAsmWriter];
|
||||
}
|
||||
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -0,0 +1,614 @@
|
||||
+//===-- 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 "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 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);
|
||||
+
|
||||
+
|
||||
+ // Custom parse functions for Sparc specific operands.
|
||||
+ OperandMatchResultTy
|
||||
+ parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
+ OperandMatchResultTy
|
||||
+ parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
+
|
||||
+ OperandMatchResultTy
|
||||
+ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
+ int ImmOffsetOrReg);
|
||||
+
|
||||
+ OperandMatchResultTy
|
||||
+ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
+ StringRef Name);
|
||||
+
|
||||
+ // returns true if Tok is matched to a register and returns register in RegNo.
|
||||
+ bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP,
|
||||
+ bool isQFP);
|
||||
+
|
||||
+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::Q7, Sparc::Q8, Sparc::Q9,
|
||||
+ 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; }
|
||||
+
|
||||
+ 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,
|
||||
+ SparcOperand::RegisterKind Kind,
|
||||
+ SMLoc S, SMLoc E) {
|
||||
+ SparcOperand *Op = new SparcOperand(k_Register);
|
||||
+ Op->Reg.RegNum = RegNum;
|
||||
+ Op->Reg.Kind = 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;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+};
|
||||
+
|
||||
+} // 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();
|
||||
+ if (matchRegisterName(Tok, RegNo, false, false)) {
|
||||
+ 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,
|
||||
+ int ImmOffsetOrReg)
|
||||
+{
|
||||
+ // FIXME: Implement memory operand parsing here.
|
||||
+ return MatchOperand_NoMatch;
|
||||
+}
|
||||
+
|
||||
+SparcAsmParser::OperandMatchResultTy SparcAsmParser::
|
||||
+parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
|
||||
+{
|
||||
+ return parseMEMOperand(Operands, 2);
|
||||
+}
|
||||
+
|
||||
+SparcAsmParser::OperandMatchResultTy SparcAsmParser::
|
||||
+parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
|
||||
+{
|
||||
+ return parseMEMOperand(Operands, 1);
|
||||
+}
|
||||
+
|
||||
+SparcAsmParser::OperandMatchResultTy SparcAsmParser::
|
||||
+parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
+ StringRef Mnemonic)
|
||||
+{
|
||||
+ OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
|
||||
+ if (ResTy == MatchOperand_Success)
|
||||
+ return ResTy;
|
||||
+ // 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_ParseFail)
|
||||
+ return ResTy;
|
||||
+
|
||||
+ SMLoc S = Parser.getTok().getLoc();
|
||||
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||
+ const MCExpr *EVal;
|
||||
+ SparcOperand *Op;
|
||||
+ switch (getLexer().getKind()) {
|
||||
+ case AsmToken::Percent:
|
||||
+ Parser.Lex(); // Eat the '%'.
|
||||
+ unsigned RegNo;
|
||||
+ if (matchRegisterName(Parser.getTok(), RegNo, false, false)) {
|
||||
+ Parser.Lex(); // Eat the identifier token.
|
||||
+ Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E);
|
||||
+ break;
|
||||
+ }
|
||||
+ // FIXME: Handle modifiers like %hi, %lo etc.,
|
||||
+ return MatchOperand_ParseFail;
|
||||
+
|
||||
+ case AsmToken::Minus:
|
||||
+ case AsmToken::Integer:
|
||||
+ if (getParser().parseExpression(EVal))
|
||||
+ return MatchOperand_ParseFail;
|
||||
+
|
||||
+ Op = SparcOperand::CreateImm(EVal, S, E);
|
||||
+ break;
|
||||
+
|
||||
+ case AsmToken::Identifier: {
|
||||
+ StringRef Identifier;
|
||||
+ if (getParser().parseIdentifier(Identifier))
|
||||
+ return MatchOperand_ParseFail;
|
||||
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
|
||||
+
|
||||
+ // Otherwise create a symbol reference.
|
||||
+ const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
|
||||
+ getContext());
|
||||
+
|
||||
+ Op = SparcOperand::CreateImm(Res, S, E);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ case AsmToken::LBrac: // handle [
|
||||
+ return parseMEMOperand(Operands, 0);
|
||||
+
|
||||
+ default:
|
||||
+ return MatchOperand_ParseFail;
|
||||
+ }
|
||||
+ // Push the parsed operand into the list of operands
|
||||
+ Operands.push_back(Op);
|
||||
+ return MatchOperand_Success;
|
||||
+}
|
||||
+
|
||||
+bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
|
||||
+ unsigned &RegNo,
|
||||
+ bool isDFP,
|
||||
+ bool isQFP)
|
||||
+{
|
||||
+ int64_t intVal = 0;
|
||||
+ RegNo = 0;
|
||||
+ if (Tok.is(AsmToken::Identifier)) {
|
||||
+ StringRef name = Tok.getString();
|
||||
+
|
||||
+ // %fp
|
||||
+ if (name.equals("fp")) {
|
||||
+ RegNo = Sparc::I6;
|
||||
+ return true;
|
||||
+ }
|
||||
+ // %sp
|
||||
+ if (name.equals("sp")) {
|
||||
+ RegNo = Sparc::O6;
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (name.equals("y")) {
|
||||
+ RegNo = Sparc::Y;
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (name.equals("icc")) {
|
||||
+ RegNo = Sparc::ICC;
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (name.equals("xcc")) {
|
||||
+ // FIXME:: check 64bit.
|
||||
+ RegNo = Sparc::ICC;
|
||||
+ 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;
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // %g0 - %g7
|
||||
+ if (name.substr(0, 1).equals_lower("g")
|
||||
+ && !name.substr(1).getAsInteger(10, intVal)
|
||||
+ && intVal < 8) {
|
||||
+ RegNo = IntRegs[intVal];
|
||||
+ return true;
|
||||
+ }
|
||||
+ // %o0 - %o7
|
||||
+ if (name.substr(0, 1).equals_lower("o")
|
||||
+ && !name.substr(1).getAsInteger(10, intVal)
|
||||
+ && intVal < 8) {
|
||||
+ RegNo = IntRegs[8 + intVal];
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (name.substr(0, 1).equals_lower("l")
|
||||
+ && !name.substr(1).getAsInteger(10, intVal)
|
||||
+ && intVal < 8) {
|
||||
+ RegNo = IntRegs[16 + intVal];
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (name.substr(0, 1).equals_lower("i")
|
||||
+ && !name.substr(1).getAsInteger(10, intVal)
|
||||
+ && intVal < 8) {
|
||||
+ RegNo = IntRegs[24 + intVal];
|
||||
+ return true;
|
||||
+ }
|
||||
+ // %f0 - %f31
|
||||
+ if (name.substr(0, 1).equals_lower("f")
|
||||
+ && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) {
|
||||
+ if (isDFP && (intVal%2 == 0)) {
|
||||
+ RegNo = DoubleRegs[intVal/2];
|
||||
+ } else if (isQFP && (intVal%4 == 0)) {
|
||||
+ RegNo = QuadFPRegs[intVal/4];
|
||||
+ } else {
|
||||
+ RegNo = FloatRegs[intVal];
|
||||
+ }
|
||||
+ 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)) {
|
||||
+ if (isDFP) {
|
||||
+ RegNo = DoubleRegs[16 + intVal/2];
|
||||
+ } else if (isQFP && (intVal % 4 == 0)) {
|
||||
+ RegNo = QuadFPRegs[8 + intVal/4];
|
||||
+ } else {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // %r0 - %r31
|
||||
+ if (name.substr(0, 1).equals_lower("r")
|
||||
+ && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) {
|
||||
+ RegNo = IntRegs[intVal];
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+extern "C" void LLVMInitializeSparcAsmParser() {
|
||||
+ RegisterMCAsmParser<SparcAsmParser> A(TheSparcTarget);
|
||||
+ RegisterMCAsmParser<SparcAsmParser> B(TheSparcV9Target);
|
||||
+}
|
||||
+
|
||||
+#define GET_REGISTER_MATCHER
|
||||
+#define GET_MATCHER_IMPLEMENTATION
|
||||
+#include "SparcGenAsmMatcher.inc"
|
||||
Index: lib/Target/Sparc/AsmParser/LLVMBuild.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/LLVMBuild.txt
|
||||
+++ lib/Target/Sparc/AsmParser/LLVMBuild.txt
|
||||
@@ -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/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/AsmParser/CMakeLists.txt
|
||||
@@ -0,0 +1,3 @@
|
||||
+add_llvm_library(LLVMSparcAsmParser
|
||||
+ SparcAsmParser.cpp
|
||||
+ )
|
||||
Index: lib/Target/Sparc/AsmParser/Makefile
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/Makefile
|
||||
+++ lib/Target/Sparc/AsmParser/Makefile
|
||||
@@ -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/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -176,11 +176,11 @@ def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMP
|
||||
def : Pat<(ctpop i64:$src), (POPCrr $src)>;
|
||||
|
||||
// "LEA" form of add
|
||||
+let isCodeGenOnly = 1 in
|
||||
def LEAX_ADDri : F3_2<2, 0b000000,
|
||||
(outs I64Regs:$dst), (ins MEMri:$addr),
|
||||
"add ${addr:arith}, $dst",
|
||||
[(set iPTR:$dst, ADDRri:$addr)]>;
|
||||
-
|
||||
} // Predicates = [Is64Bit]
|
||||
|
||||
|
||||
|
|
@ -1,516 +0,0 @@
|
|||
Pull in r198533 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add initial implementation of MC Code emitter for sparc.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -100,9 +100,14 @@ def MEMri : Operand<iPTR> {
|
||||
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>;
|
||||
Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
@@ -1,6 +1,8 @@
|
||||
add_llvm_library(LLVMSparcDesc
|
||||
+ SparcAsmBackend.cpp
|
||||
+ SparcMCAsmInfo.cpp
|
||||
+ SparcMCCodeEmitter.cpp
|
||||
SparcMCTargetDesc.cpp
|
||||
- SparcMCAsmInfo.cpp
|
||||
SparcMCExpr.cpp
|
||||
SparcTargetStreamer.cpp
|
||||
)
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
@@ -0,0 +1,131 @@
|
||||
+//===-- 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 "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/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;
|
||||
+ }
|
||||
+
|
||||
+ ++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();
|
||||
+ 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);
|
||||
+
|
||||
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
|
||||
+ (MCFixupKind)Sparc::fixup_sparc_call30));
|
||||
+ 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/SparcMCTargetDesc.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
@@ -136,6 +136,18 @@ extern "C" void LLVMInitializeSparcTargetMC() {
|
||||
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);
|
||||
+
|
||||
TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
|
||||
createMCAsmStreamer);
|
||||
TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
@@ -0,0 +1,101 @@
|
||||
+//===-- 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/MCFixupKindInfo.h"
|
||||
+#include "llvm/MC/MCObjectWriter.h"
|
||||
+#include "llvm/Support/TargetRegistry.h"
|
||||
+
|
||||
+using namespace llvm;
|
||||
+
|
||||
+namespace {
|
||||
+ class SparcAsmBackend : public MCAsmBackend {
|
||||
+
|
||||
+ public:
|
||||
+ SparcAsmBackend(const Target &T) : MCAsmBackend() {}
|
||||
+
|
||||
+ 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", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
|
||||
+ { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
|
||||
+ { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }
|
||||
+ };
|
||||
+
|
||||
+ if (Kind < FirstTargetFixupKind)
|
||||
+ return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
+
|
||||
+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
|
||||
+ "Invalid kind!");
|
||||
+ return Infos[Kind - FirstTargetFixupKind];
|
||||
+ }
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ class ELFSparcAsmBackend : public SparcAsmBackend {
|
||||
+ public:
|
||||
+ ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
|
||||
+ SparcAsmBackend(T) { }
|
||||
+
|
||||
+ void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
|
||||
+ uint64_t Value) const {
|
||||
+ assert(0 && "applyFixup not implemented yet");
|
||||
+ }
|
||||
+
|
||||
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
|
||||
+ assert(0 && "Object Writer not implemented yet");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ 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/SparcFixupKinds.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
@@ -0,0 +1,36 @@
|
||||
+//===-- 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_br22 - 22-bit PC relative relocation for
|
||||
+ /// branches on icc/xcc
|
||||
+ fixup_sparc_br19,
|
||||
+
|
||||
+ // Marker
|
||||
+ LastTargetFixupKind,
|
||||
+ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
+ };
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
|
||||
@@ -15,11 +15,27 @@
|
||||
#define SPARCMCTARGETDESC_H
|
||||
|
||||
namespace llvm {
|
||||
+class MCAsmBackend;
|
||||
+class MCCodeEmitter;
|
||||
+class MCContext;
|
||||
+class MCInstrInfo;
|
||||
+class MCRegisterInfo;
|
||||
+class MCSubtargetInfo;
|
||||
class Target;
|
||||
+class StringRef;
|
||||
|
||||
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);
|
||||
+
|
||||
} // End llvm namespace
|
||||
|
||||
// Defines symbolic names for Sparc registers. This defines a mapping from
|
||||
Index: lib/Target/Sparc/Makefile
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Makefile
|
||||
+++ lib/Target/Sparc/Makefile
|
||||
@@ -16,7 +16,7 @@ BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenI
|
||||
SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \
|
||||
SparcGenDAGISel.inc \
|
||||
SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
|
||||
- SparcGenCodeEmitter.inc
|
||||
+ SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc
|
||||
|
||||
DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc
|
||||
|
||||
Index: lib/Target/Sparc/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/CMakeLists.txt
|
||||
@@ -3,6 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td)
|
||||
tablegen(LLVM SparcGenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM SparcGenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM SparcGenCodeEmitter.inc -gen-emitter)
|
||||
+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)
|
||||
Index: lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
+++ lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
@@ -72,6 +72,11 @@ class SparcCodeEmitter : public MachineFunctionPas
|
||||
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 @@ unsigned SparcCodeEmitter::getMachineOpValue(const
|
||||
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 {
|
||||
|
||||
Index: test/MC/Sparc/sparc-alu-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-alu-instructions.s
|
||||
+++ test/MC/Sparc/sparc-alu-instructions.s
|
||||
@@ -0,0 +1,72 @@
|
||||
+! 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
|
||||
+
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
Pull in r198565 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
ELF relocation types for sparc.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: include/llvm/Support/ELF.h
|
||||
===================================================================
|
||||
--- include/llvm/Support/ELF.h
|
||||
+++ include/llvm/Support/ELF.h
|
||||
@@ -1087,6 +1087,65 @@ enum {
|
||||
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
|
||||
+};
|
||||
+
|
||||
// Section header.
|
||||
struct Elf32_Shdr {
|
||||
Elf32_Word sh_name; // Section name (index into string table)
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
Pull in r198567 from upstream llvm trunk (by Benjamin Kramer):
|
||||
|
||||
SPARC: Make helper function static.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -130,8 +130,8 @@ static void EmitOR(MCStreamer &OutStreamer, MCOper
|
||||
OutStreamer.EmitInstruction(ORInst);
|
||||
}
|
||||
|
||||
-void EmitADD(MCStreamer &OutStreamer,
|
||||
- MCOperand &RS1, MCOperand &RS2, MCOperand &RD)
|
||||
+static void EmitADD(MCStreamer &OutStreamer,
|
||||
+ MCOperand &RS1, MCOperand &RS2, MCOperand &RD)
|
||||
{
|
||||
MCInst ADDInst;
|
||||
ADDInst.setOpcode(SP::ADDrr);
|
||||
|
|
@ -1,460 +0,0 @@
|
|||
Pull in r198580 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add ELF Object Writer for Sparc.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
@@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "mccodeemitter"
|
||||
+#include "SparcMCExpr.h"
|
||||
#include "SparcMCTargetDesc.h"
|
||||
#include "MCTargetDesc/SparcFixupKinds.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
@@ -92,6 +93,41 @@ getMachineOpValue(const MCInst &MI, const MCOperan
|
||||
|
||||
assert(MO.isExpr());
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
+ if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
|
||||
+ switch(SExpr->getKind()) {
|
||||
+ default: assert(0 && "Unhandled sparc expression!"); break;
|
||||
+ case SparcMCExpr::VK_Sparc_LO:
|
||||
+ Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
+ (MCFixupKind)Sparc::fixup_sparc_lo10));
|
||||
+ break;
|
||||
+ case SparcMCExpr::VK_Sparc_HI:
|
||||
+ Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
+ (MCFixupKind)Sparc::fixup_sparc_hi22));
|
||||
+ break;
|
||||
+ case SparcMCExpr::VK_Sparc_H44:
|
||||
+ Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
+ (MCFixupKind)Sparc::fixup_sparc_h44));
|
||||
+ break;
|
||||
+ case SparcMCExpr::VK_Sparc_M44:
|
||||
+ Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
+ (MCFixupKind)Sparc::fixup_sparc_m44));
|
||||
+ break;
|
||||
+ case SparcMCExpr::VK_Sparc_L44:
|
||||
+ Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
+ (MCFixupKind)Sparc::fixup_sparc_l44));
|
||||
+ break;
|
||||
+ case SparcMCExpr::VK_Sparc_HH:
|
||||
+ Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
+ (MCFixupKind)Sparc::fixup_sparc_hh));
|
||||
+ break;
|
||||
+ case SparcMCExpr::VK_Sparc_HM:
|
||||
+ Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
+ (MCFixupKind)Sparc::fixup_sparc_hm));
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
int64_t Res;
|
||||
if (Expr->EvaluateAsAbsolute(Res))
|
||||
return Res;
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
@@ -89,6 +89,14 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S
|
||||
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,
|
||||
@@ -148,6 +156,13 @@ extern "C" void LLVMInitializeSparcTargetMC() {
|
||||
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,
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
@@ -10,6 +10,7 @@
|
||||
#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"
|
||||
@@ -16,11 +17,43 @@
|
||||
|
||||
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_call30:
|
||||
+ return Value & 0x3fffffff;
|
||||
+ case Sparc::fixup_sparc_br22:
|
||||
+ return Value & 0x3fffff;
|
||||
+ case Sparc::fixup_sparc_br19:
|
||||
+ return Value & 0x1ffff;
|
||||
+ case Sparc::fixup_sparc_hi22:
|
||||
+ return (Value >> 10) & 0x3fffff;
|
||||
+ case Sparc::fixup_sparc_lo10:
|
||||
+ return Value & 0x3ff;
|
||||
+ 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;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
namespace {
|
||||
class SparcAsmBackend : public MCAsmBackend {
|
||||
-
|
||||
+ const Target &TheTarget;
|
||||
public:
|
||||
- SparcAsmBackend(const Target &T) : MCAsmBackend() {}
|
||||
+ SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
|
||||
|
||||
unsigned getNumFixupKinds() const {
|
||||
return Sparc::NumTargetFixupKinds;
|
||||
@@ -31,7 +64,14 @@ namespace {
|
||||
// name offset bits flags
|
||||
{ "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
|
||||
- { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }
|
||||
+ { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel },
|
||||
+ { "fixup_sparc_hi22", 0, 22, 0 },
|
||||
+ { "fixup_sparc_lo10", 0, 10, 0 },
|
||||
+ { "fixup_sparc_h44", 0, 22, 0 },
|
||||
+ { "fixup_sparc_m44", 0, 10, 0 },
|
||||
+ { "fixup_sparc_l44", 0, 12, 0 },
|
||||
+ { "fixup_sparc_hh", 0, 21, 0 },
|
||||
+ { "fixup_sparc_hm", 0, 10, 0 },
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
@@ -68,21 +108,38 @@ namespace {
|
||||
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) { }
|
||||
+ SparcAsmBackend(T), OSType(OSType) { }
|
||||
|
||||
void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
|
||||
uint64_t Value) const {
|
||||
- assert(0 && "applyFixup not implemented yet");
|
||||
+
|
||||
+ 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 {
|
||||
- assert(0 && "Object Writer not implemented yet");
|
||||
- return 0;
|
||||
+ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
|
||||
+ return createSparcELFObjectWriter(OS, is64Bit(), OSABI);
|
||||
}
|
||||
|
||||
virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
@@ -22,10 +22,32 @@ namespace llvm {
|
||||
/// branches
|
||||
fixup_sparc_br22,
|
||||
|
||||
- /// fixup_sparc_br22 - 22-bit PC relative relocation for
|
||||
+ /// 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,
|
||||
+
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
@@ -0,0 +1,86 @@
|
||||
+//===-- 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/SparcMCTargetDesc.h"
|
||||
+#include "MCTargetDesc/SparcFixupKinds.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;
|
||||
+
|
||||
+ };
|
||||
+}
|
||||
+
|
||||
+
|
||||
+unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
+ const MCFixup &Fixup,
|
||||
+ bool IsPCRel,
|
||||
+ bool IsRelocWithSymbol,
|
||||
+ int64_t Addend) const {
|
||||
+ 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;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
+ return ELF::R_SPARC_NONE;
|
||||
+}
|
||||
+
|
||||
+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/SparcMCTargetDesc.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
|
||||
@@ -14,15 +14,19 @@
|
||||
#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;
|
||||
@@ -35,7 +39,9 @@ MCAsmBackend *createSparcAsmBackend(const Target &
|
||||
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/SparcMCExpr.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
@@ -70,15 +70,67 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const
|
||||
bool
|
||||
SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout) const {
|
||||
- assert(0 && "FIXME: Implement SparcMCExpr::EvaluateAsRelocatableImpl");
|
||||
return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
|
||||
}
|
||||
|
||||
+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
|
||||
+ assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!");
|
||||
+}
|
||||
|
||||
void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
|
||||
- assert(0 && "FIXME: Implement SparcMCExpr::fixELFSymbolsInTLSFixups");
|
||||
+ 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 {
|
||||
- assert(0 && "FIXME: Implement SparcMCExpr::AddValueSymbols");
|
||||
+ AddValueSymbolsImpl(getSubExpr(), Asm);
|
||||
}
|
||||
Index: lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/MCTargetDesc/CMakeLists.txt
|
||||
@@ -1,5 +1,6 @@
|
||||
add_llvm_library(LLVMSparcDesc
|
||||
SparcAsmBackend.cpp
|
||||
+ SparcELFObjectWriter.cpp
|
||||
SparcMCAsmInfo.cpp
|
||||
SparcMCCodeEmitter.cpp
|
||||
SparcMCTargetDesc.cpp
|
||||
|
|
@ -1,762 +0,0 @@
|
|||
Pull in r198591 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add initial implementation of disassembler for sparc
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrFormats.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrFormats.td
|
||||
+++ lib/Target/Sparc/SparcInstrFormats.td
|
||||
@@ -12,6 +12,7 @@ class InstSP<dag outs, dag ins, string asmstr, lis
|
||||
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 @@ class InstSP<dag outs, dag ins, string asmstr, lis
|
||||
dag InOperandList = ins;
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
+
|
||||
+ let DecoderNamespace = "Sparc";
|
||||
+ field bits<32> SoftFail = 0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -58,6 +62,27 @@ class F2_2<bits<3> op2Val, dag outs, dag ins, stri
|
||||
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
|
||||
//===----------------------------------------------------------------------===//
|
||||
Index: lib/Target/Sparc/LLVMBuild.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/LLVMBuild.txt
|
||||
+++ lib/Target/Sparc/LLVMBuild.txt
|
||||
@@ -16,13 +16,15 @@
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[common]
|
||||
-subdirectories = AsmParser InstPrinter 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]
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -230,13 +230,13 @@ def FCC_O : FCC_VAL<29>; // Ordered
|
||||
multiclass F3_12<string OpcStr, bits<6> Op3Val, SDNode OpNode,
|
||||
RegisterClass RC, ValueType Ty, Operand immOp> {
|
||||
def rr : F3_1<2, Op3Val,
|
||||
- (outs RC:$dst), (ins RC:$b, RC:$c),
|
||||
- !strconcat(OpcStr, " $b, $c, $dst"),
|
||||
- [(set Ty:$dst, (OpNode Ty:$b, Ty:$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 RC:$dst), (ins RC:$b, immOp:$c),
|
||||
- !strconcat(OpcStr, " $b, $c, $dst"),
|
||||
- [(set Ty:$dst, (OpNode Ty:$b, (Ty 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
|
||||
@@ -243,11 +243,11 @@ multiclass F3_12<string OpcStr, bits<6> Op3Val, SD
|
||||
/// 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"), []>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -488,31 +488,31 @@ let rd = 0, imm22 = 0 in
|
||||
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, 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", []>;
|
||||
+ (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, IntRegs, i32, i32imm>;
|
||||
@@ -545,21 +545,15 @@ let Defs = [ICC] in
|
||||
|
||||
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>;
|
||||
@@ -858,7 +852,7 @@ let Defs = [FCC] in {
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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),
|
||||
@@ -882,6 +876,7 @@ let Uses = [O6], isCall = 1, hasDelaySlot = 1 in
|
||||
let op = 1;
|
||||
let Inst{29-0} = disp;
|
||||
}
|
||||
+}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// V9 Instructions
|
||||
Index: lib/Target/Sparc/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/CMakeLists.txt
|
||||
@@ -3,6 +3,7 @@ set(LLVM_TARGET_DEFINITIONS Sparc.td)
|
||||
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)
|
||||
@@ -34,3 +35,4 @@ add_subdirectory(TargetInfo)
|
||||
add_subdirectory(MCTargetDesc)
|
||||
add_subdirectory(InstPrinter)
|
||||
add_subdirectory(AsmParser)
|
||||
+add_subdirectory(Disassembler)
|
||||
Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
+++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
@@ -0,0 +1,228 @@
|
||||
+//===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- C++ -*-===//
|
||||
+//
|
||||
+// The LLVM Compiler Infrastructure
|
||||
+//
|
||||
+// This file is distributed under the University of Illinois Open Source
|
||||
+// License. See LICENSE.TXT for details.
|
||||
+//
|
||||
+//===----------------------------------------------------------------------===//
|
||||
+//
|
||||
+// This file is part of the Sparc Disassembler.
|
||||
+//
|
||||
+//===----------------------------------------------------------------------===//
|
||||
+
|
||||
+#define DEBUG_TYPE "sparc-disassembler"
|
||||
+
|
||||
+#include "Sparc.h"
|
||||
+#include "SparcRegisterInfo.h"
|
||||
+#include "SparcSubtarget.h"
|
||||
+#include "llvm/MC/MCDisassembler.h"
|
||||
+#include "llvm/MC/MCFixedLenDisassembler.h"
|
||||
+#include "llvm/Support/MemoryObject.h"
|
||||
+#include "llvm/Support/TargetRegistry.h"
|
||||
+
|
||||
+using namespace llvm;
|
||||
+
|
||||
+typedef MCDisassembler::DecodeStatus DecodeStatus;
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+/// SparcDisassembler - a disassembler class for Sparc.
|
||||
+class SparcDisassembler : public MCDisassembler {
|
||||
+public:
|
||||
+ /// Constructor - Initializes the disassembler.
|
||||
+ ///
|
||||
+ SparcDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info) :
|
||||
+ MCDisassembler(STI), RegInfo(Info)
|
||||
+ {}
|
||||
+ virtual ~SparcDisassembler() {}
|
||||
+
|
||||
+ const MCRegisterInfo *getRegInfo() const { return RegInfo.get(); }
|
||||
+
|
||||
+ /// getInstruction - See MCDisassembler.
|
||||
+ virtual DecodeStatus getInstruction(MCInst &instr,
|
||||
+ uint64_t &size,
|
||||
+ const MemoryObject ®ion,
|
||||
+ uint64_t address,
|
||||
+ raw_ostream &vStream,
|
||||
+ raw_ostream &cStream) const;
|
||||
+private:
|
||||
+ OwningPtr<const MCRegisterInfo> RegInfo;
|
||||
+};
|
||||
+
|
||||
+}
|
||||
+
|
||||
+namespace llvm {
|
||||
+ extern Target TheSparcTarget, TheSparcV9Target;
|
||||
+}
|
||||
+
|
||||
+static MCDisassembler *createSparcDisassembler(
|
||||
+ const Target &T,
|
||||
+ const MCSubtargetInfo &STI) {
|
||||
+ return new SparcDisassembler(STI, T.createMCRegInfo(""));
|
||||
+}
|
||||
+
|
||||
+
|
||||
+extern "C" void LLVMInitializeSparcDisassembler() {
|
||||
+ // Register the disassembler.
|
||||
+ TargetRegistry::RegisterMCDisassembler(TheSparcTarget,
|
||||
+ createSparcDisassembler);
|
||||
+ TargetRegistry::RegisterMCDisassembler(TheSparcV9Target,
|
||||
+ createSparcDisassembler);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+static const unsigned IntRegDecoderTable[] = {
|
||||
+ SP::G0, SP::G1, SP::G2, SP::G3,
|
||||
+ SP::G4, SP::G5, SP::G6, SP::G7,
|
||||
+ SP::O0, SP::O1, SP::O2, SP::O3,
|
||||
+ SP::O4, SP::O5, SP::O6, SP::O7,
|
||||
+ SP::L0, SP::L1, SP::L2, SP::L3,
|
||||
+ SP::L4, SP::L5, SP::L6, SP::L7,
|
||||
+ SP::I0, SP::I1, SP::I2, SP::I3,
|
||||
+ SP::I4, SP::I5, SP::I6, SP::I7 };
|
||||
+
|
||||
+static const unsigned FPRegDecoderTable[] = {
|
||||
+ SP::F0, SP::F1, SP::F2, SP::F3,
|
||||
+ SP::F4, SP::F5, SP::F6, SP::F7,
|
||||
+ SP::F8, SP::F9, SP::F10, SP::F11,
|
||||
+ SP::F12, SP::F13, SP::F14, SP::F15,
|
||||
+ SP::F16, SP::F17, SP::F18, SP::F19,
|
||||
+ SP::F20, SP::F21, SP::F22, SP::F23,
|
||||
+ SP::F24, SP::F25, SP::F26, SP::F27,
|
||||
+ SP::F28, SP::F29, SP::F30, SP::F31 };
|
||||
+
|
||||
+static const unsigned DFPRegDecoderTable[] = {
|
||||
+ SP::D0, SP::D16, SP::D1, SP::D17,
|
||||
+ SP::D2, SP::D18, SP::D3, SP::D19,
|
||||
+ SP::D4, SP::D20, SP::D5, SP::D21,
|
||||
+ SP::D6, SP::D22, SP::D7, SP::D23,
|
||||
+ SP::D8, SP::D24, SP::D9, SP::D25,
|
||||
+ SP::D10, SP::D26, SP::D11, SP::D27,
|
||||
+ SP::D12, SP::D28, SP::D13, SP::D29,
|
||||
+ SP::D14, SP::D30, SP::D15, SP::D31 };
|
||||
+
|
||||
+static const unsigned QFPRegDecoderTable[] = {
|
||||
+ SP::Q0, SP::Q8, -1, -1,
|
||||
+ SP::Q1, SP::Q9, -1, -1,
|
||||
+ SP::Q2, SP::Q10, -1, -1,
|
||||
+ SP::Q3, SP::Q11, -1, -1,
|
||||
+ SP::Q4, SP::Q12, -1, -1,
|
||||
+ SP::Q5, SP::Q13, -1, -1,
|
||||
+ SP::Q6, SP::Q14, -1, -1,
|
||||
+ SP::Q7, SP::Q15, -1, -1 } ;
|
||||
+
|
||||
+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 == (unsigned)-1)
|
||||
+ return MCDisassembler::Fail;
|
||||
+ Inst.addOperand(MCOperand::CreateReg(Reg));
|
||||
+ return MCDisassembler::Success;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+#include "SparcGenDisassemblerTables.inc"
|
||||
+
|
||||
+/// readInstruction - read four bytes from the MemoryObject
|
||||
+/// and return 32 bit word.
|
||||
+static DecodeStatus readInstruction32(const MemoryObject ®ion,
|
||||
+ uint64_t address,
|
||||
+ uint64_t &size,
|
||||
+ uint32_t &insn) {
|
||||
+ uint8_t Bytes[4];
|
||||
+
|
||||
+ // We want to read exactly 4 Bytes of data.
|
||||
+ if (region.readBytes(address, 4, Bytes) == -1) {
|
||||
+ size = 0;
|
||||
+ return MCDisassembler::Fail;
|
||||
+ }
|
||||
+
|
||||
+ // Encoded as a big-endian 32-bit word in the stream.
|
||||
+ insn = (Bytes[3] << 0) |
|
||||
+ (Bytes[2] << 8) |
|
||||
+ (Bytes[1] << 16) |
|
||||
+ (Bytes[0] << 24);
|
||||
+
|
||||
+ return MCDisassembler::Success;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+DecodeStatus
|
||||
+SparcDisassembler::getInstruction(MCInst &instr,
|
||||
+ uint64_t &Size,
|
||||
+ const MemoryObject &Region,
|
||||
+ uint64_t Address,
|
||||
+ raw_ostream &vStream,
|
||||
+ raw_ostream &cStream) const {
|
||||
+ uint32_t Insn;
|
||||
+
|
||||
+ DecodeStatus Result = readInstruction32(Region, Address, Size, Insn);
|
||||
+ if (Result == MCDisassembler::Fail)
|
||||
+ return MCDisassembler::Fail;
|
||||
+
|
||||
+
|
||||
+ // Calling the auto-generated decoder function.
|
||||
+ Result = decodeInstruction(DecoderTableSparc32, instr, Insn, Address,
|
||||
+ this, STI);
|
||||
+
|
||||
+ if (Result != MCDisassembler::Fail) {
|
||||
+ Size = 4;
|
||||
+ return Result;
|
||||
+ }
|
||||
+
|
||||
+ return MCDisassembler::Fail;
|
||||
+}
|
||||
Index: lib/Target/Sparc/Disassembler/LLVMBuild.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Disassembler/LLVMBuild.txt
|
||||
+++ lib/Target/Sparc/Disassembler/LLVMBuild.txt
|
||||
@@ -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/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Disassembler/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/Disassembler/CMakeLists.txt
|
||||
@@ -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/Makefile
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Disassembler/Makefile
|
||||
+++ lib/Target/Sparc/Disassembler/Makefile
|
||||
@@ -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/Makefile
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Makefile
|
||||
+++ lib/Target/Sparc/Makefile
|
||||
@@ -14,11 +14,11 @@ TARGET = Sparc
|
||||
# Make sure that tblgen is run, first thing.
|
||||
BUILT_SOURCES = SparcGenRegisterInfo.inc SparcGenInstrInfo.inc \
|
||||
SparcGenAsmWriter.inc SparcGenAsmMatcher.inc \
|
||||
- SparcGenDAGISel.inc \
|
||||
+ SparcGenDAGISel.inc SparcGenDisassemblerTables.inc \
|
||||
SparcGenSubtargetInfo.inc SparcGenCallingConv.inc \
|
||||
SparcGenCodeEmitter.inc SparcGenMCCodeEmitter.inc
|
||||
|
||||
-DIRS = InstPrinter AsmParser TargetInfo MCTargetDesc
|
||||
+DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -141,6 +141,7 @@ def : Pat<(i64 imm:$val),
|
||||
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>;
|
||||
@@ -161,8 +162,6 @@ def XNORXrr : F3_1<2, 0b000111,
|
||||
defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>;
|
||||
defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>;
|
||||
|
||||
-def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
|
||||
-
|
||||
def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$rd),
|
||||
(ins I64Regs:$rs1, I64Regs:$rs2, TLSSym:$sym),
|
||||
"add $rs1, $rs2, $rd, $sym",
|
||||
@@ -169,18 +168,17 @@ def TLS_ADDXrr : F3_1<2, 0b000000, (outs I64Regs:$
|
||||
[(set i64:$rd,
|
||||
(tlsadd i64:$rs1, i64:$rs2, tglobaltlsaddr:$sym))]>;
|
||||
|
||||
-// Register-immediate instructions.
|
||||
-
|
||||
-def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>;
|
||||
-
|
||||
-def : Pat<(ctpop i64:$src), (POPCrr $src)>;
|
||||
-
|
||||
// "LEA" form of add
|
||||
-let isCodeGenOnly = 1 in
|
||||
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]
|
||||
|
||||
|
||||
@@ -245,7 +243,7 @@ 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
|
||||
+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",
|
||||
@@ -278,11 +276,11 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr
|
||||
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,
|
||||
+def LDSWrr : F3_1<3, 0b001000,
|
||||
(outs I64Regs:$dst), (ins MEMrr:$addr),
|
||||
"ldsw [$addr], $dst",
|
||||
[(set i64:$dst, (sextloadi32 ADDRrr:$addr))]>;
|
||||
-def LDSWri : F3_2<3, 0b001011,
|
||||
+def LDSWri : F3_2<3, 0b001000,
|
||||
(outs I64Regs:$dst), (ins MEMri:$addr),
|
||||
"ldsw [$addr], $dst",
|
||||
[(set i64:$dst, (sextloadi32 ADDRri:$addr))]>;
|
||||
@@ -289,13 +287,13 @@ def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri
|
||||
|
||||
// 64-bit stores.
|
||||
def STXrr : F3_1<3, 0b001110,
|
||||
- (outs), (ins MEMrr:$addr, I64Regs:$src),
|
||||
- "stx $src, [$addr]",
|
||||
- [(store i64:$src, ADDRrr:$addr)]>;
|
||||
+ (outs), (ins MEMrr:$addr, I64Regs:$rd),
|
||||
+ "stx $rd, [$addr]",
|
||||
+ [(store i64:$rd, ADDRrr:$addr)]>;
|
||||
def STXri : F3_2<3, 0b001110,
|
||||
- (outs), (ins MEMri:$addr, I64Regs:$src),
|
||||
- "stx $src, [$addr]",
|
||||
- [(store i64:$src, ADDRri:$addr)]>;
|
||||
+ (outs), (ins MEMri:$addr, I64Regs:$rd),
|
||||
+ "stx $rd, [$addr]",
|
||||
+ [(store i64:$rd, ADDRri:$addr)]>;
|
||||
|
||||
// Truncating stores from i64 are identical to the i32 stores.
|
||||
def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>;
|
||||
@@ -315,6 +313,15 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADD
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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
|
||||
@@ -326,7 +333,7 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADD
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
let Uses = [ICC] in
|
||||
-def BPXCC : BranchSP<(ins brtarget:$imm22, CCOp:$cond),
|
||||
+def BPXCC : XBranchSP<(ins brtarget:$imm22, CCOp:$cond),
|
||||
"b$cond %xcc, $imm22",
|
||||
[(SPbrxcc bb:$imm22, imm:$cond)]>;
|
||||
|
||||
@@ -409,7 +416,7 @@ def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, im
|
||||
|
||||
|
||||
// 64 bit SETHI
|
||||
-let Predicates = [Is64Bit] in {
|
||||
+let Predicates = [Is64Bit], isCodeGenOnly = 1 in {
|
||||
def SETHIXi : F2_1<0b100,
|
||||
(outs IntRegs:$rd), (ins i64imm:$imm22),
|
||||
"sethi $imm22, $rd",
|
||||
Index: test/MC/Disassembler/Sparc/lit.local.cfg
|
||||
===================================================================
|
||||
--- test/MC/Disassembler/Sparc/lit.local.cfg
|
||||
+++ test/MC/Disassembler/Sparc/lit.local.cfg
|
||||
@@ -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.txt
|
||||
===================================================================
|
||||
--- test/MC/Disassembler/Sparc/sparc.txt
|
||||
+++ test/MC/Disassembler/Sparc/sparc.txt
|
||||
@@ -0,0 +1,82 @@
|
||||
+# 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
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
Pull in r198592 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Explicitly cast -1 to unsigned to fix buildbot errors.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
+++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
@@ -104,14 +104,14 @@ static const unsigned DFPRegDecoderTable[] = {
|
||||
SP::D14, SP::D30, SP::D15, SP::D31 };
|
||||
|
||||
static const unsigned QFPRegDecoderTable[] = {
|
||||
- SP::Q0, SP::Q8, -1, -1,
|
||||
- SP::Q1, SP::Q9, -1, -1,
|
||||
- SP::Q2, SP::Q10, -1, -1,
|
||||
- SP::Q3, SP::Q11, -1, -1,
|
||||
- SP::Q4, SP::Q12, -1, -1,
|
||||
- SP::Q5, SP::Q13, -1, -1,
|
||||
- SP::Q6, SP::Q14, -1, -1,
|
||||
- SP::Q7, SP::Q15, -1, -1 } ;
|
||||
+ SP::Q0, SP::Q8, (unsigned)-1, (unsigned)-1,
|
||||
+ SP::Q1, SP::Q9, (unsigned)-1, (unsigned)-1,
|
||||
+ SP::Q2, SP::Q10, (unsigned)-1, (unsigned)-1,
|
||||
+ SP::Q3, SP::Q11, (unsigned)-1, (unsigned)-1,
|
||||
+ SP::Q4, SP::Q12, (unsigned)-1, (unsigned)-1,
|
||||
+ SP::Q5, SP::Q13, (unsigned)-1, (unsigned)-1,
|
||||
+ SP::Q6, SP::Q14, (unsigned)-1, (unsigned)-1,
|
||||
+ SP::Q7, SP::Q15, (unsigned)-1, (unsigned)-1 } ;
|
||||
|
||||
static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst,
|
||||
unsigned RegNo,
|
||||
|
|
@ -1,359 +0,0 @@
|
|||
Pull in r198658 from upstream llvm trunk:
|
||||
|
||||
[Sparc] Add support for parsing memory operands in sparc AsmParser.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
+++ test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
@@ -0,0 +1,23 @@
|
||||
+! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
|
||||
+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
|
||||
+
|
||||
+ ! CHECK: call foo
|
||||
+ call foo
|
||||
+
|
||||
+ ! CHECK: call %g1+%i2
|
||||
+ call %g1 + %i2
|
||||
+
|
||||
+ ! CHECK: call %o1+8
|
||||
+ call %o1 + 8
|
||||
+
|
||||
+ ! CHECK: call %g1
|
||||
+ call %g1
|
||||
+
|
||||
+ ! CHECK: jmp %g1+%i2
|
||||
+ jmp %g1 + %i2
|
||||
+
|
||||
+ ! CHECK: jmp %o1+8
|
||||
+ jmp %o1 + 8
|
||||
+
|
||||
+ ! CHECK: jmp %g1
|
||||
+ jmp %g1
|
||||
Index: test/MC/Sparc/sparc-mem-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-mem-instructions.s
|
||||
+++ test/MC/Sparc/sparc-mem-instructions.s
|
||||
@@ -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: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -28,6 +28,7 @@ namespace llvm {
|
||||
}
|
||||
|
||||
namespace {
|
||||
+class SparcOperand;
|
||||
class SparcAsmParser : public MCTargetAsmParser {
|
||||
|
||||
MCSubtargetInfo &STI;
|
||||
@@ -55,18 +56,15 @@ class SparcAsmParser : public MCTargetAsmParser {
|
||||
|
||||
// Custom parse functions for Sparc specific operands.
|
||||
OperandMatchResultTy
|
||||
- parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
- OperandMatchResultTy
|
||||
- parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
+ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
|
||||
OperandMatchResultTy
|
||||
- parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
- int ImmOffsetOrReg);
|
||||
-
|
||||
- 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, bool isDFP,
|
||||
bool isQFP);
|
||||
@@ -298,7 +296,35 @@ class SparcOperand : public MCParsedAsmOperand {
|
||||
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
|
||||
@@ -412,23 +438,42 @@ ParseDirective(AsmToken DirectiveID)
|
||||
}
|
||||
|
||||
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
|
||||
-parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
- int ImmOffsetOrReg)
|
||||
+parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
|
||||
{
|
||||
- // FIXME: Implement memory operand parsing here.
|
||||
- return MatchOperand_NoMatch;
|
||||
-}
|
||||
|
||||
-SparcAsmParser::OperandMatchResultTy SparcAsmParser::
|
||||
-parseMEMrrOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
|
||||
-{
|
||||
- return parseMEMOperand(Operands, 2);
|
||||
-}
|
||||
+ SMLoc S, E;
|
||||
+ unsigned BaseReg = 0;
|
||||
|
||||
-SparcAsmParser::OperandMatchResultTy SparcAsmParser::
|
||||
-parseMEMriOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
|
||||
-{
|
||||
- return parseMEMOperand(Operands, 1);
|
||||
+ if (ParseRegister(BaseReg, S, E)) {
|
||||
+ return MatchOperand_NoMatch;
|
||||
+ }
|
||||
+
|
||||
+ switch (getLexer().getKind()) {
|
||||
+ default: return MatchOperand_NoMatch;
|
||||
+
|
||||
+ 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::
|
||||
@@ -435,20 +480,57 @@ SparcAsmParser::OperandMatchResultTy SparcAsmParse
|
||||
parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
StringRef Mnemonic)
|
||||
{
|
||||
+
|
||||
OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
|
||||
- if (ResTy == MatchOperand_Success)
|
||||
- return ResTy;
|
||||
+
|
||||
// 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_ParseFail)
|
||||
+ 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 [
|
||||
+
|
||||
+ 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;
|
||||
- SparcOperand *Op;
|
||||
+
|
||||
+ Op = 0;
|
||||
switch (getLexer().getKind()) {
|
||||
+ default: break;
|
||||
+
|
||||
case AsmToken::Percent:
|
||||
Parser.Lex(); // Eat the '%'.
|
||||
unsigned RegNo;
|
||||
@@ -458,40 +540,30 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*>
|
||||
break;
|
||||
}
|
||||
// FIXME: Handle modifiers like %hi, %lo etc.,
|
||||
- return MatchOperand_ParseFail;
|
||||
+ break;
|
||||
|
||||
case AsmToken::Minus:
|
||||
case AsmToken::Integer:
|
||||
- if (getParser().parseExpression(EVal))
|
||||
- return MatchOperand_ParseFail;
|
||||
-
|
||||
- Op = SparcOperand::CreateImm(EVal, S, E);
|
||||
+ if (!getParser().parseExpression(EVal))
|
||||
+ Op = SparcOperand::CreateImm(EVal, S, E);
|
||||
break;
|
||||
|
||||
case AsmToken::Identifier: {
|
||||
StringRef Identifier;
|
||||
- if (getParser().parseIdentifier(Identifier))
|
||||
- return MatchOperand_ParseFail;
|
||||
- SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||
- MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
|
||||
+ if (!getParser().parseIdentifier(Identifier)) {
|
||||
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().
|
||||
+ getLoc().getPointer() - 1);
|
||||
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
|
||||
|
||||
- // Otherwise create a symbol reference.
|
||||
- const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
|
||||
- getContext());
|
||||
+ const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
|
||||
+ getContext());
|
||||
|
||||
- Op = SparcOperand::CreateImm(Res, S, E);
|
||||
+ Op = SparcOperand::CreateImm(Res, S, E);
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
-
|
||||
- case AsmToken::LBrac: // handle [
|
||||
- return parseMEMOperand(Operands, 0);
|
||||
-
|
||||
- default:
|
||||
- return MatchOperand_ParseFail;
|
||||
}
|
||||
- // Push the parsed operand into the list of operands
|
||||
- Operands.push_back(Op);
|
||||
- return MatchOperand_Success;
|
||||
+ return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
|
||||
}
|
||||
|
||||
bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -78,12 +78,12 @@ def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri
|
||||
// Address operands
|
||||
def SparcMEMrrAsmOperand : AsmOperandClass {
|
||||
let Name = "MEMrr";
|
||||
- let ParserMethod = "parseMEMrrOperand";
|
||||
+ let ParserMethod = "parseMEMOperand";
|
||||
}
|
||||
|
||||
def SparcMEMriAsmOperand : AsmOperandClass {
|
||||
let Name = "MEMri";
|
||||
- let ParserMethod = "parseMEMriOperand";
|
||||
+ let ParserMethod = "parseMEMOperand";
|
||||
}
|
||||
|
||||
def MEMrr : Operand<iPTR> {
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
Pull in r198681 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add support for parsing sparc asm modifiers such as %hi, %lo etc.,
|
||||
Also, correct the offsets for FixupsKindInfo.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
@@ -27,11 +27,11 @@ static unsigned adjustFixupValue(unsigned Kind, ui
|
||||
case FK_Data_8:
|
||||
return Value;
|
||||
case Sparc::fixup_sparc_call30:
|
||||
- return Value & 0x3fffffff;
|
||||
+ return (Value >> 2) & 0x3fffffff;
|
||||
case Sparc::fixup_sparc_br22:
|
||||
- return Value & 0x3fffff;
|
||||
+ return (Value >> 2) & 0x3fffff;
|
||||
case Sparc::fixup_sparc_br19:
|
||||
- return Value & 0x1ffff;
|
||||
+ return (Value >> 2) & 0x1ffff;
|
||||
case Sparc::fixup_sparc_hi22:
|
||||
return (Value >> 10) & 0x3fffff;
|
||||
case Sparc::fixup_sparc_lo10:
|
||||
@@ -45,7 +45,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui
|
||||
case Sparc::fixup_sparc_hh:
|
||||
return (Value >> 42) & 0x3fffff;
|
||||
case Sparc::fixup_sparc_hm:
|
||||
- return (Value >>32) & 0x3ff;
|
||||
+ return (Value >> 32) & 0x3ff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,16 +62,16 @@ namespace {
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
|
||||
const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = {
|
||||
// name offset bits flags
|
||||
- { "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
|
||||
- { "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
|
||||
- { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel },
|
||||
- { "fixup_sparc_hi22", 0, 22, 0 },
|
||||
- { "fixup_sparc_lo10", 0, 10, 0 },
|
||||
- { "fixup_sparc_h44", 0, 22, 0 },
|
||||
- { "fixup_sparc_m44", 0, 10, 0 },
|
||||
- { "fixup_sparc_l44", 0, 12, 0 },
|
||||
- { "fixup_sparc_hh", 0, 21, 0 },
|
||||
- { "fixup_sparc_hm", 0, 10, 0 },
|
||||
+ { "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 },
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
@@ -67,6 +67,37 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
+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("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);
|
||||
+}
|
||||
+
|
||||
bool
|
||||
SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout) const {
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
+class StringRef;
|
||||
class SparcMCExpr : public MCTargetExpr {
|
||||
public:
|
||||
enum VariantKind {
|
||||
@@ -90,6 +91,7 @@ class SparcMCExpr : public MCTargetExpr {
|
||||
|
||||
static bool classof(const SparcMCExpr *) { return true; }
|
||||
|
||||
+ static VariantKind parseVariantKind(StringRef name);
|
||||
|
||||
};
|
||||
|
||||
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -8,6 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/SparcMCTargetDesc.h"
|
||||
+#include "MCTargetDesc/SparcMCExpr.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
@@ -68,6 +69,7 @@ class SparcAsmParser : public MCTargetAsmParser {
|
||||
// returns true if Tok is matched to a register and returns register in RegNo.
|
||||
bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP,
|
||||
bool isQFP);
|
||||
+ bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
|
||||
|
||||
public:
|
||||
SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
|
||||
@@ -536,15 +538,19 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand
|
||||
unsigned RegNo;
|
||||
if (matchRegisterName(Parser.getTok(), RegNo, false, false)) {
|
||||
Parser.Lex(); // Eat the identifier token.
|
||||
+ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||
Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E);
|
||||
break;
|
||||
}
|
||||
- // FIXME: Handle modifiers like %hi, %lo etc.,
|
||||
+ 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))
|
||||
+ if (!getParser().parseExpression(EVal, E))
|
||||
Op = SparcOperand::CreateImm(EVal, S, E);
|
||||
break;
|
||||
|
||||
@@ -551,13 +557,11 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand
|
||||
case AsmToken::Identifier: {
|
||||
StringRef Identifier;
|
||||
if (!getParser().parseIdentifier(Identifier)) {
|
||||
- SMLoc E = SMLoc::getFromPointer(Parser.getTok().
|
||||
- getLoc().getPointer() - 1);
|
||||
+ 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;
|
||||
@@ -675,7 +679,33 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
}
|
||||
|
||||
|
||||
+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);
|
||||
Index: test/MC/Sparc/sparc-relocations.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-relocations.s
|
||||
+++ test/MC/Sparc/sparc-relocations.s
|
||||
@@ -0,0 +1,33 @@
|
||||
+! 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: 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/sparc-ctrl-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
+++ test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
@@ -1,23 +1,33 @@
|
||||
! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
|
||||
! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
|
||||
|
||||
- ! CHECK: call foo
|
||||
+ ! 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
|
||||
+ ! CHECK: call %g1+%i2 ! encoding: [0x9f,0xc0,0x40,0x1a]
|
||||
call %g1 + %i2
|
||||
|
||||
- ! CHECK: call %o1+8
|
||||
+ ! CHECK: call %o1+8 ! encoding: [0x9f,0xc2,0x60,0x08]
|
||||
call %o1 + 8
|
||||
|
||||
- ! CHECK: call %g1
|
||||
+ ! CHECK: call %g1 ! encoding: [0x9f,0xc0,0x60,0x00]
|
||||
call %g1
|
||||
|
||||
- ! CHECK: jmp %g1+%i2
|
||||
+ ! 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
|
||||
+ ! CHECK: jmp %o1+8 ! encoding: [0x81,0xc2,0x60,0x08]
|
||||
jmp %o1 + 8
|
||||
|
||||
- ! CHECK: jmp %g1
|
||||
+ ! 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)
|
||||
+
|
||||
|
|
@ -1,734 +0,0 @@
|
|||
Pull in r198738 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add support for parsing branch instructions and conditional moves.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/MC/Disassembler/Sparc/sparc.txt
|
||||
===================================================================
|
||||
--- test/MC/Disassembler/Sparc/sparc.txt
|
||||
+++ test/MC/Disassembler/Sparc/sparc.txt
|
||||
@@ -80,3 +80,90 @@
|
||||
|
||||
# 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-ctrl-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
+++ test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
@@ -31,3 +31,117 @@
|
||||
! CHECK-NEXT: ! fixup A - offset: 0, value: %lo(sym), kind: fixup_sparc_lo10
|
||||
jmp %g1+%lo(sym)
|
||||
|
||||
+ ! 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/sparc64-ctrl-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc64-ctrl-instructions.s
|
||||
+++ test/MC/Sparc/sparc64-ctrl-instructions.s
|
||||
@@ -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: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -333,32 +333,42 @@ class XBranchSP<dag ins, string asmstr, list<dag>
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
let Uses = [ICC] in
|
||||
-def BPXCC : XBranchSP<(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
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -928,8 +928,9 @@ let Predicates = [HasV9], Constraints = "$f = $rd"
|
||||
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 {
|
||||
@@ -946,8 +947,9 @@ let Predicates = [HasV9], Constraints = "$f = $rd"
|
||||
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]>;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1092,3 +1094,4 @@ def : Pat<(atomic_store ADDRri:$dst, i32:$val), (S
|
||||
|
||||
|
||||
include "SparcInstr64Bit.td"
|
||||
+include "SparcInstrAliases.td"
|
||||
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -537,9 +537,29 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand
|
||||
Parser.Lex(); // Eat the '%'.
|
||||
unsigned RegNo;
|
||||
if (matchRegisterName(Parser.getTok(), RegNo, false, false)) {
|
||||
+ StringRef name = Parser.getTok().getString();
|
||||
Parser.Lex(); // Eat the identifier token.
|
||||
E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
|
||||
- Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, S, E);
|
||||
+ switch (RegNo) {
|
||||
+ default:
|
||||
+ Op = SparcOperand::CreateReg(RegNo, SparcOperand::rk_None, 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)) {
|
||||
Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
@@ -83,6 +83,17 @@ void SparcInstPrinter::printCCOperand(const MCInst
|
||||
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);
|
||||
}
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrAliases.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrAliases.td
|
||||
+++ lib/Target/Sparc/SparcInstrAliases.td
|
||||
@@ -0,0 +1,119 @@
|
||||
+//===-- 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>;
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
Pull in r198739 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Correct the mask for fixup_sparc_br19.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
@@ -31,7 +31,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui
|
||||
case Sparc::fixup_sparc_br22:
|
||||
return (Value >> 2) & 0x3fffff;
|
||||
case Sparc::fixup_sparc_br19:
|
||||
- return (Value >> 2) & 0x1ffff;
|
||||
+ return (Value >> 2) & 0x7ffff;
|
||||
case Sparc::fixup_sparc_hi22:
|
||||
return (Value >> 10) & 0x3fffff;
|
||||
case Sparc::fixup_sparc_lo10:
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
Pull in r198740 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9] Rename operands in some sparc64 instructions so that TableGen can encode them correctly.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/MC/Sparc/sparc64-alu-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc64-alu-instructions.s
|
||||
+++ test/MC/Sparc/sparc64-alu-instructions.s
|
||||
@@ -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: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -193,9 +193,9 @@ def MULXrr : F3_1<2, 0b001001,
|
||||
"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 {
|
||||
@@ -204,9 +204,9 @@ def SDIVXrr : F3_1<2, 0b101101,
|
||||
"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),
|
||||
@@ -213,9 +213,9 @@ def UDIVXrr : F3_1<2, 0b001101,
|
||||
"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]
|
||||
Index: lib/Target/Sparc/SparcInstrFormats.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrFormats.td
|
||||
+++ lib/Target/Sparc/SparcInstrFormats.td
|
||||
@@ -193,12 +193,12 @@ class F3_Si<bits<2> opVal, bits<6> op3val, bit xVa
|
||||
// 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>
|
||||
|
|
@ -1,236 +0,0 @@
|
|||
Pull in r198893 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Multiclass for loads/stores. No functionality change intended.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -235,14 +235,8 @@ def UDIVXri : F3_2<2, 0b001101,
|
||||
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))]>;
|
||||
+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),
|
||||
@@ -276,24 +270,10 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr
|
||||
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, 0b001000,
|
||||
- (outs I64Regs:$dst), (ins MEMrr:$addr),
|
||||
- "ldsw [$addr], $dst",
|
||||
- [(set i64:$dst, (sextloadi32 ADDRrr:$addr))]>;
|
||||
-def LDSWri : F3_2<3, 0b001000,
|
||||
- (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:$rd),
|
||||
- "stx $rd, [$addr]",
|
||||
- [(store i64:$rd, ADDRrr:$addr)]>;
|
||||
-def STXri : F3_2<3, 0b001110,
|
||||
- (outs), (ins MEMri:$addr, I64Regs:$rd),
|
||||
- "stx $rd, [$addr]",
|
||||
- [(store i64:$rd, 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)>;
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -250,6 +250,32 @@ multiclass F3_12np<string OpcStr, bits<6> Op3Val>
|
||||
!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
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -350,128 +376,28 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot =
|
||||
}
|
||||
|
||||
// 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,
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
Pull in r198909 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add support for parsing jmpl instruction and make indirect call and jmp instructions as aliases to jmpl.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -453,6 +453,7 @@ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand
|
||||
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));
|
||||
Index: lib/Target/Sparc/SparcInstrAliases.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrAliases.td
|
||||
+++ lib/Target/Sparc/SparcInstrAliases.td
|
||||
@@ -117,3 +117,14 @@ 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)>;
|
||||
Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
@@ -23,6 +23,7 @@
|
||||
using namespace llvm;
|
||||
|
||||
#define GET_INSTRUCTION_NAME
|
||||
+#define PRINT_ALIAS_INSTR
|
||||
#include "SparcGenAsmWriter.inc"
|
||||
|
||||
void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
|
||||
@@ -33,10 +34,34 @@ void SparcInstPrinter::printRegName(raw_ostream &O
|
||||
void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
||||
StringRef Annot)
|
||||
{
|
||||
- printInstruction(MI, O);
|
||||
+ 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)
|
||||
{
|
||||
Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
|
||||
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
|
||||
@@ -29,9 +29,11 @@ class SparcInstPrinter : public MCInstPrinter {
|
||||
|
||||
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);
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -362,10 +362,18 @@ let usesCustomInserter = 1, Uses = [FCC] in {
|
||||
[(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)]>;
|
||||
@@ -519,9 +527,8 @@ class BranchSP<dag ins, string asmstr, list<dag> p
|
||||
}
|
||||
|
||||
// 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",
|
||||
@@ -564,15 +571,17 @@ let Uses = [O6],
|
||||
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
|
||||
Index: lib/Target/Sparc/DelaySlotFiller.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/DelaySlotFiller.cpp
|
||||
+++ lib/Target/Sparc/DelaySlotFiller.cpp
|
||||
@@ -278,19 +278,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock:
|
||||
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;
|
||||
}
|
||||
@@ -353,8 +353,8 @@ bool Filler::needsUnimp(MachineBasicBlock::iterato
|
||||
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;
|
||||
}
|
||||
|
||||
Index: test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
+++ test/MC/Sparc/sparc-ctrl-instructions.s
|
||||
@@ -31,6 +31,19 @@
|
||||
! 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
|
||||
|
|
@ -1,463 +0,0 @@
|
|||
Pull in r198910 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Emit retl/ret instead of jmp instruction. It improves the readability of the assembly generated.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/CodeGen/SPARC/ctpop.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/ctpop.ll
|
||||
+++ test/CodeGen/SPARC/ctpop.ll
|
||||
@@ -9,12 +9,12 @@ declare i32 @llvm.ctpop.i32(i32)
|
||||
|
||||
; V9-LABEL: test
|
||||
; V9: srl %o0, 0, %o0
|
||||
-; V9-NEXT: jmp %o7+8
|
||||
+; V9-NEXT: retl
|
||||
; V9-NEXT: popc %o0, %o0
|
||||
|
||||
; SPARC64-LABEL: test
|
||||
; SPARC64: srl %o0, 0, %o0
|
||||
-; SPARC64: jmp %o7+8
|
||||
+; SPARC64: retl
|
||||
; SPARC64: popc %o0, %o0
|
||||
|
||||
define i32 @test(i32 %X) {
|
||||
Index: test/CodeGen/SPARC/2011-01-11-Call.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/2011-01-11-Call.ll
|
||||
+++ test/CodeGen/SPARC/2011-01-11-Call.ll
|
||||
@@ -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 @@ declare void @bar(...)
|
||||
; 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 @@ declare void @bar(...)
|
||||
; 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/leafproc.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/leafproc.ll
|
||||
+++ test/CodeGen/SPARC/leafproc.ll
|
||||
@@ -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 @@ entry:
|
||||
|
||||
|
||||
; 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 @@ entry:
|
||||
|
||||
; 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 @@ entry:
|
||||
|
||||
; 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 @@ entry:
|
||||
; 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 @@ entry:
|
||||
; 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/fp128.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/fp128.ll
|
||||
+++ test/CodeGen/SPARC/fp128.ll
|
||||
@@ -45,7 +45,7 @@ entry:
|
||||
; 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 @@ entry:
|
||||
; 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 @@ entry:
|
||||
; 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/2011-01-11-FrameAddr.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
|
||||
+++ test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
|
||||
@@ -9,18 +9,18 @@ define i8* @frameaddr() nounwind readnone {
|
||||
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: jmp %i7+8
|
||||
+;SPARC64: ret
|
||||
;SPARC64: restore %g0, %g0, %g0
|
||||
|
||||
%0 = tail call i8* @llvm.frameaddress(i32 0)
|
||||
Index: test/CodeGen/SPARC/constpool.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/constpool.ll
|
||||
+++ test/CodeGen/SPARC/constpool.ll
|
||||
@@ -12,7 +12,7 @@ entry:
|
||||
|
||||
; 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,7 +20,7 @@ entry:
|
||||
; 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: retl
|
||||
; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f1
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ entry:
|
||||
; 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: retl
|
||||
; abs64: ld [%[[R5]]+%[[R2]]], %f1
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ entry:
|
||||
; 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
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ entry:
|
||||
; 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: ret
|
||||
; v9pic32: restore
|
||||
|
||||
|
||||
Index: test/CodeGen/SPARC/globals.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/globals.ll
|
||||
+++ test/CodeGen/SPARC/globals.ll
|
||||
@@ -14,7 +14,7 @@ define zeroext i8 @loadG() {
|
||||
|
||||
; 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 @@ define zeroext i8 @loadG() {
|
||||
; 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 @@ define zeroext i8 @loadG() {
|
||||
; 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 @@ define zeroext i8 @loadG() {
|
||||
; 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 @@ define zeroext i8 @loadG() {
|
||||
; 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/rem.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/rem.ll
|
||||
+++ test/CodeGen/SPARC/rem.ll
|
||||
@@ -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 @@ define i64 @test1(i64 %X, i64 %Y) {
|
||||
; 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/2011-01-19-DelaySlot.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
|
||||
+++ test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
|
||||
@@ -7,7 +7,7 @@ entry:
|
||||
; 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 @@ entry:
|
||||
; 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 @@ bb:
|
||||
|
||||
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 @@ declare i32 @func(i32*)
|
||||
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 @@ entry:
|
||||
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 @@ entry:
|
||||
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 @@ define i32 @restore_or_imm(i32 %a) {
|
||||
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/64bit.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/64bit.ll
|
||||
+++ test/CodeGen/SPARC/64bit.ll
|
||||
@@ -5,7 +5,7 @@
|
||||
; 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 @@ define i64 @ret2(i64 %a, i64 %b) {
|
||||
; 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 @@ define i64 @shl_imm(i64 %a) {
|
||||
; 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 @@ define i64 @sra_reg(i64 %a, i64 %b) {
|
||||
; 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 @@ define i64 @ret_imm0() {
|
||||
; 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 @@ define i64 @ret_simm13() {
|
||||
; 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 @@ define i64 @ret_sethi() {
|
||||
|
||||
; 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 @@ define i64 @ret_sethi_or() {
|
||||
|
||||
; 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: lib/Target/Sparc/SparcInstrAliases.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrAliases.td
|
||||
+++ lib/Target/Sparc/SparcInstrAliases.td
|
||||
@@ -128,3 +128,9 @@ def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$ad
|
||||
// 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)>;
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
Pull in r199014 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Bundle instruction with delay slow and its filler. Now, we can use -verify-machineinstrs with SPARC backend.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/DelaySlotFiller.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/DelaySlotFiller.cpp
|
||||
+++ lib/Target/Sparc/DelaySlotFiller.cpp
|
||||
@@ -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 @@ namespace {
|
||||
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 @@ namespace {
|
||||
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 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBl
|
||||
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 @@ Filler::findDelayInstr(MachineBasicBlock &MBB,
|
||||
|| I->isInlineAsm()
|
||||
|| I->isLabel()
|
||||
|| I->hasDelaySlot()
|
||||
- || isDelayFiller(MBB, I))
|
||||
+ || I->isBundledWithSucc())
|
||||
break;
|
||||
|
||||
if (delayHasHazard(I, sawLoad, sawStore, RegDefs, RegUses)) {
|
||||
@@ -332,18 +339,6 @@ bool Filler::IsRegInSet(SmallSet<unsigned, 32>& Re
|
||||
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())
|
||||
@@ -484,10 +479,10 @@ bool Filler::tryCombineRestoreWithPrevInst(Machine
|
||||
&& 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/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -184,7 +184,6 @@ static void LowerGETPCXAndEmitMCInsts(const Machin
|
||||
|
||||
void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
|
||||
{
|
||||
- MCInst TmpInst;
|
||||
|
||||
switch (MI->getOpcode()) {
|
||||
default: break;
|
||||
@@ -195,8 +194,13 @@ void SparcAsmPrinter::EmitInstruction(const Machin
|
||||
LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext);
|
||||
return;
|
||||
}
|
||||
- LowerSparcMachineInstrToMCInst(MI, TmpInst, *this);
|
||||
- OutStreamer.EmitInstruction(TmpInst);
|
||||
+ 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() {
|
||||
Index: test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
|
||||
+++ test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
|
||||
@@ -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 {
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
Pull in r199024 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add missing processor types: v7 and niagara
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/Sparc.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Sparc.td
|
||||
+++ lib/Target/Sparc/Sparc.td
|
||||
@@ -56,6 +56,7 @@ class Proc<string Name, list<SubtargetFeature> Fea
|
||||
: Processor<Name, NoItineraries, Features>;
|
||||
|
||||
def : Proc<"generic", []>;
|
||||
+def : Proc<"v7", []>;
|
||||
def : Proc<"v8", []>;
|
||||
def : Proc<"supersparc", []>;
|
||||
def : Proc<"sparclite", []>;
|
||||
@@ -67,7 +68,10 @@ def : Proc<"tsc701", []>;
|
||||
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]>;
|
||||
+def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated]>;
|
||||
+def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated]>;
|
||||
|
||||
def SparcAsmWriter : AsmWriter {
|
||||
string AsmWriterClassName = "InstPrinter";
|
||||
Index: lib/Target/Sparc/SparcSubtarget.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcSubtarget.cpp
|
||||
+++ lib/Target/Sparc/SparcSubtarget.cpp
|
||||
@@ -35,13 +35,8 @@ SparcSubtarget::SparcSubtarget(const std::string &
|
||||
|
||||
// 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);
|
||||
Index: test/CodeGen/SPARC/ctpop.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/ctpop.ll
|
||||
+++ test/CodeGen/SPARC/ctpop.ll
|
||||
@@ -1,6 +1,13 @@
|
||||
; RUN: llc < %s -march=sparc -mattr=-v9 | FileCheck %s -check-prefix=V8
|
||||
; RUN: llc < %s -march=sparc -mattr=+v9 | FileCheck %s -check-prefix=V9
|
||||
-; RUN: llc < %s -march=sparcv9 | FileCheck %s -check-prefix=SPARC64
|
||||
+; RUN: llc < %s -march=sparc -mcpu=v9 | FileCheck %s -check-prefix=V9
|
||||
+; RUN: llc < %s -march=sparc -mcpu=ultrasparc | FileCheck %s -check-prefix=V9
|
||||
+; RUN: llc < %s -march=sparc -mcpu=ultrasparc3 | FileCheck %s -check-prefix=V9
|
||||
+; RUN: llc < %s -march=sparc -mcpu=niagara | FileCheck %s -check-prefix=V9
|
||||
+; 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 | FileCheck %s -check-prefix=SPARC64
|
||||
|
||||
declare i32 @llvm.ctpop.i32(i32)
|
||||
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
Pull in r199028 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
The SPARCv9 ABI returns a float in %f0.
|
||||
|
||||
This is different from the argument passing convention which puts the
|
||||
first float argument in %f1.
|
||||
|
||||
With this patch, all returned floats are treated as if the 'inreg' flag
|
||||
were set. This means multiple float return values get packed in %f0,
|
||||
%f1, %f2, ...
|
||||
|
||||
Note that when returning a struct in registers, clang will set the
|
||||
'inreg' flag on the return value, so that behavior is unchanged. This
|
||||
also happens when returning a float _Complex.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/CodeGen/SPARC/64abi.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/64abi.ll
|
||||
+++ test/CodeGen/SPARC/64abi.ll
|
||||
@@ -180,7 +180,7 @@ define void @call_inreg_fi(i32* %p, i32 %i1, float
|
||||
}
|
||||
|
||||
; 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 @@ define void @call_ret_i64_pair(i64* %i0) {
|
||||
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 @@ define { i32, float } @ret_i32_float_pair(i32 %a0,
|
||||
; 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)
|
||||
Index: test/CodeGen/SPARC/constpool.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/constpool.ll
|
||||
+++ test/CodeGen/SPARC/constpool.ll
|
||||
@@ -21,7 +21,7 @@ entry:
|
||||
; abs44: add %[[R1]], %m44(.LCPI0_0), %[[R2:[gilo][0-7]]]
|
||||
; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]]
|
||||
; abs44: retl
|
||||
-; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f1
|
||||
+; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f0
|
||||
|
||||
|
||||
; abs64: floatCP
|
||||
@@ -31,7 +31,7 @@ entry:
|
||||
; abs64: add %[[R3]], %hm(.LCPI0_0), %[[R4:[gilo][0-7]]]
|
||||
; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]]
|
||||
; abs64: retl
|
||||
-; abs64: ld [%[[R5]]+%[[R2]]], %f1
|
||||
+; abs64: ld [%[[R5]]+%[[R2]]], %f0
|
||||
|
||||
|
||||
; v8pic32: floatCP
|
||||
@@ -50,7 +50,7 @@ entry:
|
||||
; 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: ld [%[[Gaddr]]], %f0
|
||||
; v9pic32: ret
|
||||
; v9pic32: restore
|
||||
|
||||
Index: test/CodeGen/SPARC/64cond.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/64cond.ll
|
||||
+++ test/CodeGen/SPARC/64cond.ll
|
||||
@@ -80,7 +80,7 @@ entry:
|
||||
; 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
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -254,7 +254,7 @@ SparcTargetLowering::LowerReturn_64(SDValue Chain,
|
||||
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);
|
||||
@@ -1258,7 +1258,7 @@ SparcTargetLowering::LowerCall_64(TargetLowering::
|
||||
if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && CLI.CS == 0)
|
||||
CLI.Ins[0].Flags.setInReg();
|
||||
|
||||
- RVInfo.AnalyzeCallResult(CLI.Ins, CC_Sparc64);
|
||||
+ 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) {
|
||||
Index: lib/Target/Sparc/SparcCallingConv.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcCallingConv.td
|
||||
+++ lib/Target/Sparc/SparcCallingConv.td
|
||||
@@ -103,7 +103,7 @@ def RetCC_Sparc32 : CallingConv<[
|
||||
// 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 @@ def CC_Sparc64 : CallingConv<[
|
||||
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),
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
Pull in r199031 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Replace (unsigned)-1 with ~OU as suggested by Reid Kleckner.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
+++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
|
||||
@@ -104,14 +104,14 @@ static const unsigned DFPRegDecoderTable[] = {
|
||||
SP::D14, SP::D30, SP::D15, SP::D31 };
|
||||
|
||||
static const unsigned QFPRegDecoderTable[] = {
|
||||
- SP::Q0, SP::Q8, (unsigned)-1, (unsigned)-1,
|
||||
- SP::Q1, SP::Q9, (unsigned)-1, (unsigned)-1,
|
||||
- SP::Q2, SP::Q10, (unsigned)-1, (unsigned)-1,
|
||||
- SP::Q3, SP::Q11, (unsigned)-1, (unsigned)-1,
|
||||
- SP::Q4, SP::Q12, (unsigned)-1, (unsigned)-1,
|
||||
- SP::Q5, SP::Q13, (unsigned)-1, (unsigned)-1,
|
||||
- SP::Q6, SP::Q14, (unsigned)-1, (unsigned)-1,
|
||||
- SP::Q7, SP::Q15, (unsigned)-1, (unsigned)-1 } ;
|
||||
+ 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,
|
||||
@@ -168,7 +168,7 @@ static DecodeStatus DecodeQFPRegsRegisterClass(MCI
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
unsigned Reg = QFPRegDecoderTable[RegNo];
|
||||
- if (Reg == (unsigned)-1)
|
||||
+ if (Reg == ~0U)
|
||||
return MCDisassembler::Fail;
|
||||
Inst.addOperand(MCOperand::CreateReg(Reg));
|
||||
return MCDisassembler::Success;
|
||||
|
|
@ -1,944 +0,0 @@
|
|||
Pull in r199033 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add support for parsing floating point instructions.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -601,91 +601,91 @@ let Defs = [Y], rd = 0 in {
|
||||
}
|
||||
// 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]>;
|
||||
|
||||
|
||||
@@ -692,73 +692,73 @@ def FSQRTQ : F3_3u<2, 0b110100, 0b000101011,
|
||||
|
||||
// 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
|
||||
@@ -770,17 +770,17 @@ def FDIVQ : F3_3<2, 0b110100, 0b001001111,
|
||||
|
||||
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]>;
|
||||
}
|
||||
|
||||
@@ -892,29 +892,29 @@ let Predicates = [HasV9], Constraints = "$f = $rd"
|
||||
// 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]>;
|
||||
}
|
||||
|
||||
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -54,6 +54,8 @@ class SparcAsmParser : public MCTargetAsmParser {
|
||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||
bool ParseDirective(AsmToken DirectiveID);
|
||||
|
||||
+ virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
|
||||
+ unsigned Kind);
|
||||
|
||||
// Custom parse functions for Sparc specific operands.
|
||||
OperandMatchResultTy
|
||||
@@ -67,8 +69,9 @@ class SparcAsmParser : public MCTargetAsmParser {
|
||||
parseSparcAsmOperand(SparcOperand *&Operand);
|
||||
|
||||
// returns true if Tok is matched to a register and returns register in RegNo.
|
||||
- bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, bool isDFP,
|
||||
- bool isQFP);
|
||||
+ bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
|
||||
+ unsigned &RegKind);
|
||||
+
|
||||
bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
|
||||
|
||||
public:
|
||||
@@ -178,6 +181,16 @@ class SparcOperand : public MCParsedAsmOperand {
|
||||
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);
|
||||
@@ -280,11 +293,11 @@ class SparcOperand : public MCParsedAsmOperand {
|
||||
}
|
||||
|
||||
static SparcOperand *CreateReg(unsigned RegNum,
|
||||
- SparcOperand::RegisterKind Kind,
|
||||
+ unsigned Kind,
|
||||
SMLoc S, SMLoc E) {
|
||||
SparcOperand *Op = new SparcOperand(k_Register);
|
||||
Op->Reg.RegNum = RegNum;
|
||||
- Op->Reg.Kind = Kind;
|
||||
+ Op->Reg.Kind = (SparcOperand::RegisterKind)Kind;
|
||||
Op->StartLoc = S;
|
||||
Op->EndLoc = E;
|
||||
return Op;
|
||||
@@ -298,6 +311,40 @@ class SparcOperand : public MCParsedAsmOperand {
|
||||
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;
|
||||
@@ -383,7 +430,8 @@ ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SM
|
||||
if (getLexer().getKind() != AsmToken::Percent)
|
||||
return false;
|
||||
Parser.Lex();
|
||||
- if (matchRegisterName(Tok, RegNo, false, false)) {
|
||||
+ unsigned regKind = SparcOperand::rk_None;
|
||||
+ if (matchRegisterName(Tok, RegNo, regKind)) {
|
||||
Parser.Lex();
|
||||
return false;
|
||||
}
|
||||
@@ -537,13 +585,14 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand
|
||||
case AsmToken::Percent:
|
||||
Parser.Lex(); // Eat the '%'.
|
||||
unsigned RegNo;
|
||||
- if (matchRegisterName(Parser.getTok(), RegNo, false, false)) {
|
||||
+ 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, SparcOperand::rk_None, S, E);
|
||||
+ Op = SparcOperand::CreateReg(RegNo, RegKind, S, E);
|
||||
break;
|
||||
case Sparc::Y:
|
||||
Op = SparcOperand::CreateToken("%y", S);
|
||||
@@ -593,11 +642,11 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand
|
||||
|
||||
bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
|
||||
unsigned &RegNo,
|
||||
- bool isDFP,
|
||||
- bool isQFP)
|
||||
+ unsigned &RegKind)
|
||||
{
|
||||
int64_t intVal = 0;
|
||||
RegNo = 0;
|
||||
+ RegKind = SparcOperand::rk_None;
|
||||
if (Tok.is(AsmToken::Identifier)) {
|
||||
StringRef name = Tok.getString();
|
||||
|
||||
@@ -604,21 +653,25 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
// %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;
|
||||
}
|
||||
|
||||
@@ -625,6 +678,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
if (name.equals("xcc")) {
|
||||
// FIXME:: check 64bit.
|
||||
RegNo = Sparc::ICC;
|
||||
+ RegKind = SparcOperand::rk_CCReg;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -634,6 +688,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
&& intVal < 4) {
|
||||
// FIXME: check 64bit and handle %fcc1 - %fcc3
|
||||
RegNo = Sparc::FCC;
|
||||
+ RegKind = SparcOperand::rk_CCReg;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -642,6 +697,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
&& !name.substr(1).getAsInteger(10, intVal)
|
||||
&& intVal < 8) {
|
||||
RegNo = IntRegs[intVal];
|
||||
+ RegKind = SparcOperand::rk_IntReg;
|
||||
return true;
|
||||
}
|
||||
// %o0 - %o7
|
||||
@@ -649,6 +705,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
&& !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")
|
||||
@@ -655,6 +712,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
&& !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")
|
||||
@@ -661,18 +719,14 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
&& !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) {
|
||||
- if (isDFP && (intVal%2 == 0)) {
|
||||
- RegNo = DoubleRegs[intVal/2];
|
||||
- } else if (isQFP && (intVal%4 == 0)) {
|
||||
- RegNo = QuadFPRegs[intVal/4];
|
||||
- } else {
|
||||
- RegNo = FloatRegs[intVal];
|
||||
- }
|
||||
+ RegNo = FloatRegs[intVal];
|
||||
+ RegKind = SparcOperand::rk_FloatReg;
|
||||
return true;
|
||||
}
|
||||
// %f32 - %f62
|
||||
@@ -679,13 +733,9 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
if (name.substr(0, 1).equals_lower("f")
|
||||
&& !name.substr(1, 2).getAsInteger(10, intVal)
|
||||
&& intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) {
|
||||
- if (isDFP) {
|
||||
- RegNo = DoubleRegs[16 + intVal/2];
|
||||
- } else if (isQFP && (intVal % 4 == 0)) {
|
||||
- RegNo = QuadFPRegs[8 + intVal/4];
|
||||
- } else {
|
||||
- return false;
|
||||
- }
|
||||
+ // FIXME: Check V9
|
||||
+ RegNo = DoubleRegs[16 + intVal/2];
|
||||
+ RegKind = SparcOperand::rk_DoubleReg;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -693,6 +743,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -735,3 +786,26 @@ extern "C" void LLVMInitializeSparcAsmParser() {
|
||||
#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/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -358,31 +358,31 @@ def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFP
|
||||
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]
|
||||
Index: test/MC/Disassembler/Sparc/sparc-fp.txt
|
||||
===================================================================
|
||||
--- test/MC/Disassembler/Sparc/sparc-fp.txt
|
||||
+++ test/MC/Disassembler/Sparc/sparc-fp.txt
|
||||
@@ -0,0 +1,142 @@
|
||||
+# 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: 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/Sparc/sparc-fp-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-fp-instructions.s
|
||||
+++ test/MC/Sparc/sparc-fp-instructions.s
|
||||
@@ -0,0 +1,113 @@
|
||||
+! 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
|
||||
+
|
||||
+ ! 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
|
||||
+
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
Pull in r199061 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Handle bundled terminators in isBlockOnlyReachableByFallthrough.
|
||||
|
||||
Targets like SPARC and MIPS have delay slots and normally bundle the
|
||||
delay slot instruction with the corresponding terminator.
|
||||
|
||||
Teach isBlockOnlyReachableByFallthrough to find any MBB operands on
|
||||
bundled terminators so SPARC doesn't need to specialize this function.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/CodeGen/SPARC/missinglabel.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/missinglabel.ll
|
||||
+++ test/CodeGen/SPARC/missinglabel.ll
|
||||
@@ -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: lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -65,10 +65,6 @@ namespace {
|
||||
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O);
|
||||
-
|
||||
- virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB)
|
||||
- const;
|
||||
-
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
@@ -390,37 +386,6 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const
|
||||
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;
|
||||
-
|
||||
- // 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();
|
||||
-}
|
||||
-
|
||||
// Force static initialization.
|
||||
extern "C" void LLVMInitializeSparcAsmPrinter() {
|
||||
RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
|
||||
Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/CodeGen/AsmPrinter/AsmPrinter.cpp
|
||||
+++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp
|
||||
@@ -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 @@ isBlockOnlyReachableByFallthrough(const MachineBas
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
Pull in r199186 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Switch the NEON register class from QPR to DPair.
|
||||
|
||||
The already allocatable DPair superclass contains odd-even D register
|
||||
pair in addition to the even-odd pairs in the QPR register class. There
|
||||
is no reason to constrain the set of D register pairs that can be used
|
||||
for NEON values. Any NEON instructions that require a Q register will
|
||||
automatically constrain the register class to QPR.
|
||||
|
||||
The allocation order for DPair begins with the QPR registers, so
|
||||
register allocation is unlikely to change much.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/ARM/ARMISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/ARM/ARMISelLowering.cpp
|
||||
+++ lib/Target/ARM/ARMISelLowering.cpp
|
||||
@@ -156,7 +156,7 @@ void ARMTargetLowering::addDRTypeForNEON(MVT VT) {
|
||||
}
|
||||
|
||||
void ARMTargetLowering::addQRTypeForNEON(MVT VT) {
|
||||
- addRegisterClass(VT, &ARM::QPRRegClass);
|
||||
+ addRegisterClass(VT, &ARM::DPairRegClass);
|
||||
addTypeForNEON(VT, MVT::v2f64, MVT::v4i32);
|
||||
}
|
||||
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
Pull in r199187 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Always let value types influence register classes.
|
||||
|
||||
When creating a virtual register for a def, the value type should be
|
||||
used to pick the register class. If we only use the register class
|
||||
constraint on the instruction, we might pick a too large register class.
|
||||
|
||||
Some registers can store values of different sizes. For example, the x86
|
||||
xmm registers can hold f32, f64, and 128-bit vectors. The three
|
||||
different value sizes are represented by register classes with identical
|
||||
register sets: FR32, FR64, and VR128. These register classes have
|
||||
different spill slot sizes, so it is important to use the right one.
|
||||
|
||||
The register class constraint on an instruction doesn't necessarily care
|
||||
about the size of the value its defining. The value type determines
|
||||
that.
|
||||
|
||||
This fixes a problem where InstrEmitter was picking 32-bit register
|
||||
classes for 64-bit values on SPARC.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/CodeGen/SPARC/spillsize.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/spillsize.ll
|
||||
+++ test/CodeGen/SPARC/spillsize.ll
|
||||
@@ -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: lib/CodeGen/SelectionDAG/InstrEmitter.cpp
|
||||
===================================================================
|
||||
--- lib/CodeGen/SelectionDAG/InstrEmitter.cpp
|
||||
+++ lib/CodeGen/SelectionDAG/InstrEmitter.cpp
|
||||
@@ -220,10 +220,19 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *
|
||||
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);
|
||||
|
|
@ -1,200 +0,0 @@
|
|||
Pull in r199775 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Do not add PC to _GLOBAL_OFFSET_TABLE_ address to access GOT in absolute code.
|
||||
Fixes PR#18521
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -65,18 +65,24 @@ namespace {
|
||||
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O);
|
||||
+
|
||||
+ void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI);
|
||||
+
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
-static MCOperand createPCXCallOP(MCSymbol *Label,
|
||||
- MCContext &OutContext)
|
||||
-{
|
||||
- const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label,
|
||||
+static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
|
||||
+ MCSymbol *Sym, MCContext &OutContext) {
|
||||
+ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym,
|
||||
OutContext);
|
||||
- const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None,
|
||||
- MCSym, 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,
|
||||
@@ -115,43 +121,101 @@ static void EmitSETHI(MCStreamer &OutStreamer,
|
||||
OutStreamer.EmitInstruction(SETHIInst);
|
||||
}
|
||||
|
||||
-static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1,
|
||||
- MCOperand &Imm, MCOperand &RD)
|
||||
+static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
|
||||
+ MCOperand &RS1, MCOperand &Src2, MCOperand &RD)
|
||||
{
|
||||
- MCInst ORInst;
|
||||
- ORInst.setOpcode(SP::ORri);
|
||||
- ORInst.addOperand(RD);
|
||||
- ORInst.addOperand(RS1);
|
||||
- ORInst.addOperand(Imm);
|
||||
- OutStreamer.EmitInstruction(ORInst);
|
||||
+ 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)
|
||||
-{
|
||||
- MCInst ADDInst;
|
||||
- ADDInst.setOpcode(SP::ADDrr);
|
||||
- ADDInst.addOperand(RD);
|
||||
- ADDInst.addOperand(RS1);
|
||||
- ADDInst.addOperand(RS2);
|
||||
- OutStreamer.EmitInstruction(ADDInst);
|
||||
+ MCOperand &RS1, MCOperand &RS2, MCOperand &RD) {
|
||||
+ EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD);
|
||||
}
|
||||
|
||||
-static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
|
||||
- MCStreamer &OutStreamer,
|
||||
- MCContext &OutContext)
|
||||
+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)
|
||||
{
|
||||
- const MachineOperand &MO = MI->getOperand(0);
|
||||
- MCSymbol *StartLabel = OutContext.CreateTempSymbol();
|
||||
- MCSymbol *EndLabel = OutContext.CreateTempSymbol();
|
||||
- MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
|
||||
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>:
|
||||
@@ -187,7 +251,7 @@ void SparcAsmPrinter::EmitInstruction(const Machin
|
||||
// FIXME: Debug Value.
|
||||
return;
|
||||
case SP::GETPCX:
|
||||
- LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext);
|
||||
+ LowerGETPCXAndEmitMCInsts(MI);
|
||||
return;
|
||||
}
|
||||
MachineBasicBlock::const_instr_iterator I = MI;
|
||||
Index: test/CodeGen/SPARC/tls.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/tls.ll
|
||||
+++ test/CodeGen/SPARC/tls.ll
|
||||
@@ -38,8 +38,7 @@ entry:
|
||||
|
||||
|
||||
; 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 +46,7 @@ entry:
|
||||
; 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)
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
Pull in r199781 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add support for inline assembly constraint 'I'.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/CodeGen/SPARC/inlineasm.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/inlineasm.ll
|
||||
+++ test/CodeGen/SPARC/inlineasm.ll
|
||||
@@ -0,0 +1,35 @@
|
||||
+; 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
|
||||
+}
|
||||
Index: lib/Target/Sparc/SparcISelLowering.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.h
|
||||
+++ lib/Target/Sparc/SparcISelLowering.h
|
||||
@@ -73,6 +73,13 @@ namespace llvm {
|
||||
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;
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -2918,6 +2918,8 @@ SparcTargetLowering::getConstraintType(const std::
|
||||
switch (Constraint[0]) {
|
||||
default: break;
|
||||
case 'r': return C_RegisterClass;
|
||||
+ case 'I': // SIMM13
|
||||
+ return C_Other;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2924,6 +2926,64 @@ SparcTargetLowering::getConstraintType(const std::
|
||||
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 {
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
Pull in r199786 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add support for inline assembly constraints which specify registers by their aliases.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -2992,6 +2992,26 @@ SparcTargetLowering::getRegForInlineAsmConstraint(
|
||||
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: test/CodeGen/SPARC/inlineasm.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/inlineasm.ll
|
||||
+++ test/CodeGen/SPARC/inlineasm.ll
|
||||
@@ -33,3 +33,13 @@ 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
|
||||
+}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
Pull in r199940 from upstream llvm trunk (by Eric Christopher):
|
||||
|
||||
Fix out of bounds access to the double regs array. Given the
|
||||
code this looks correct, but could use review. The previous
|
||||
was definitely not correct.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -734,7 +734,7 @@ bool SparcAsmParser::matchRegisterName(const AsmTo
|
||||
&& !name.substr(1, 2).getAsInteger(10, intVal)
|
||||
&& intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) {
|
||||
// FIXME: Check V9
|
||||
- RegNo = DoubleRegs[16 + intVal/2];
|
||||
+ RegNo = DoubleRegs[intVal/2];
|
||||
RegKind = SparcOperand::rk_DoubleReg;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
Pull in r199974 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Correct quad register list in the asm parser.
|
||||
Add test cases to check parsing of v9 double registers and their aliased quad registers.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/MC/Disassembler/Sparc/sparc-fp.txt
|
||||
===================================================================
|
||||
--- test/MC/Disassembler/Sparc/sparc-fp.txt
|
||||
+++ test/MC/Disassembler/Sparc/sparc-fp.txt
|
||||
@@ -81,6 +81,12 @@
|
||||
# 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
|
||||
|
||||
Index: test/MC/Sparc/sparc-fp-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-fp-instructions.s
|
||||
+++ test/MC/Sparc/sparc-fp-instructions.s
|
||||
@@ -64,6 +64,12 @@
|
||||
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]
|
||||
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -117,7 +117,7 @@ class SparcAsmParser : public MCTargetAsmParser {
|
||||
static unsigned QuadFPRegs[32] = {
|
||||
Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3,
|
||||
Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7,
|
||||
- Sparc::Q8, Sparc::Q7, Sparc::Q8, Sparc::Q9,
|
||||
+ Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11,
|
||||
Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 };
|
||||
|
||||
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
Pull in r199975 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Implement atomicrmw operations in 32 and 64 bits for SPARCv9.
|
||||
|
||||
These all use the compare-and-swap CASA/CASXA instructions.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/CodeGen/SPARC/atomics.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/atomics.ll
|
||||
+++ test/CodeGen/SPARC/atomics.ll
|
||||
@@ -1,4 +1,4 @@
|
||||
-; RUN: llc < %s -march=sparcv9 | FileCheck %s
|
||||
+; RUN: llc < %s -march=sparcv9 -verify-machineinstrs | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: test_atomic_i32
|
||||
; CHECK: ld [%o0]
|
||||
@@ -61,3 +61,84 @@ entry:
|
||||
%b = atomicrmw xchg i32* %ptr, i32 42 monotonic
|
||||
ret i32 %b
|
||||
}
|
||||
+
|
||||
+; CHECK-LABEL: test_load_add_32
|
||||
+; CHECK: membar
|
||||
+; CHECK: add
|
||||
+; CHECK: cas [%o0]
|
||||
+; 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: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -438,6 +438,31 @@ def : Pat<(atomic_store ADDRri:$dst, i64:$val), (S
|
||||
|
||||
} // 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 {
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -2831,11 +2831,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons
|
||||
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:
|
||||
@@ -2842,17 +2837,64 @@ SparcTargetLowering::EmitInstrWithCustomInserter(M
|
||||
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
|
||||
@@ -2906,6 +2948,100 @@ SparcTargetLowering::EmitInstrWithCustomInserter(M
|
||||
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, %upd, %val
|
||||
+ // 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(UpdReg).addReg(ValReg)
|
||||
+ .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
|
||||
//===----------------------------------------------------------------------===//
|
||||
Index: lib/Target/Sparc/SparcISelLowering.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.h
|
||||
+++ lib/Target/Sparc/SparcISelLowering.h
|
||||
@@ -165,6 +165,13 @@ namespace llvm {
|
||||
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
|
||||
|
||||
|
|
@ -1,377 +0,0 @@
|
|||
Pull in r199977 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9] Add support for JIT in Sparc64.
|
||||
With this change, all supported tests in test/ExecutionEngine pass in sparcv9.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcJITInfo.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcJITInfo.cpp
|
||||
+++ lib/Target/Sparc/SparcJITInfo.cpp
|
||||
@@ -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"
|
||||
|
||||
@@ -35,18 +36,17 @@ extern "C" {
|
||||
"SparcCompilationCallback:\n"
|
||||
// Save current register window.
|
||||
"\tsave %sp, -192, %sp\n"
|
||||
- // stubaddr+4 is in %g1.
|
||||
+ // stubaddr is in %g1.
|
||||
"\tcall SparcCompilationCallbackC\n"
|
||||
- "\t sub %g1, 4, %o0\n"
|
||||
+ "\t mov %g1, %o0\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 +55,120 @@ extern "C" {
|
||||
#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 +175,10 @@ void SparcJITInfo::replaceMachineCodeForFunction(v
|
||||
|
||||
|
||||
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 +185,41 @@ TargetJITInfo::StubLayout SparcJITInfo::getStubLay
|
||||
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 +255,27 @@ void SparcJITInfo::relocate(void *Function, Machin
|
||||
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/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
@@ -68,9 +68,13 @@ static MCCodeGenInfo *createSparcMCCodeGenInfo(Str
|
||||
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;
|
||||
@@ -81,9 +85,17 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(S
|
||||
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;
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1810,7 +1810,6 @@ SDValue SparcTargetLowering::makeAddress(SDValue O
|
||||
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);
|
||||
Index: lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
+++ lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
@@ -207,11 +207,11 @@ unsigned SparcCodeEmitter::getRelocation(const Mac
|
||||
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 SPII::MO_H44: return SP::reloc_sparc_h44;
|
||||
+ case SPII::MO_M44: return SP::reloc_sparc_m44;
|
||||
+ case SPII::MO_L44: return SP::reloc_sparc_l44;
|
||||
+ case SPII::MO_HH: return SP::reloc_sparc_hh;
|
||||
+ case SPII::MO_HM: return SP::reloc_sparc_hm;
|
||||
}
|
||||
|
||||
unsigned Opc = MI.getOpcode();
|
||||
Index: lib/Target/Sparc/SparcRelocations.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcRelocations.h
|
||||
+++ lib/Target/Sparc/SparcRelocations.h
|
||||
@@ -33,7 +33,22 @@ namespace llvm {
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
Pull in r200103 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
Missing ELF relocations for Sparc.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: include/llvm/Support/ELF.h
|
||||
===================================================================
|
||||
--- include/llvm/Support/ELF.h
|
||||
+++ include/llvm/Support/ELF.h
|
||||
@@ -1143,7 +1143,37 @@ enum {
|
||||
R_SPARC_L44 = 52,
|
||||
R_SPARC_REGISTER = 53,
|
||||
R_SPARC_UA64 = 54,
|
||||
- R_SPARC_UA16 = 55
|
||||
+ R_SPARC_UA16 = 55,
|
||||
+ 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.
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
Pull in r200104 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
removing duplicate enum value
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: include/llvm/Support/ELF.h
|
||||
===================================================================
|
||||
--- include/llvm/Support/ELF.h
|
||||
+++ include/llvm/Support/ELF.h
|
||||
@@ -1144,7 +1144,6 @@ enum {
|
||||
R_SPARC_REGISTER = 53,
|
||||
R_SPARC_UA64 = 54,
|
||||
R_SPARC_UA16 = 55,
|
||||
- R_SPARC_UA16 = 55,
|
||||
R_SPARC_TLS_GD_HI22 = 56,
|
||||
R_SPARC_TLS_GD_LO10 = 57,
|
||||
R_SPARC_TLS_GD_ADD = 58,
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
Pull in r200112 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add support for sparc relocation types in ELF object file.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/MC/Sparc/sparc-relocations.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-relocations.s
|
||||
+++ test/MC/Sparc/sparc-relocations.s
|
||||
@@ -1,5 +1,18 @@
|
||||
! 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
|
||||
Index: include/llvm/Object/ELFObjectFile.h
|
||||
===================================================================
|
||||
--- include/llvm/Object/ELFObjectFile.h
|
||||
+++ include/llvm/Object/ELFObjectFile.h
|
||||
@@ -922,6 +922,9 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName()
|
||||
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 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName()
|
||||
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 @@ unsigned ELFObjectFile<ELFT>::getArch() const {
|
||||
: 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: lib/Object/ELF.cpp
|
||||
===================================================================
|
||||
--- lib/Object/ELF.cpp
|
||||
+++ lib/Object/ELF.cpp
|
||||
@@ -702,6 +702,98 @@ StringRef getELFRelocationTypeName(uint32_t Machin
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
Pull in r200130 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Fix swapped CASA operands.
|
||||
|
||||
Found by SingleSource/UnitTests/AtomicOps.c
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -2972,7 +2972,7 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr
|
||||
// loop:
|
||||
// %val = phi %val0, %dest
|
||||
// %upd = op %val, %rs2
|
||||
- // %dest = cas %addr, %upd, %val
|
||||
+ // %dest = cas %addr, %val, %upd
|
||||
// cmp %val, %dest
|
||||
// bne loop
|
||||
// done:
|
||||
@@ -3031,7 +3031,7 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr
|
||||
}
|
||||
|
||||
BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg)
|
||||
- .addReg(AddrReg).addReg(UpdReg).addReg(ValReg)
|
||||
+ .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))
|
||||
Index: test/CodeGen/SPARC/atomics.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/atomics.ll
|
||||
+++ test/CodeGen/SPARC/atomics.ll
|
||||
@@ -64,8 +64,8 @@ entry:
|
||||
|
||||
; CHECK-LABEL: test_load_add_32
|
||||
; CHECK: membar
|
||||
-; CHECK: add
|
||||
-; CHECK: cas [%o0]
|
||||
+; 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:
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
Pull in r200131 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Only generate the popc instruction for SPARC CPUs that implement it.
|
||||
|
||||
The popc instruction is defined in the SPARCv9 instruction set
|
||||
architecture, but it was emulated on CPUs older than Niagara 2.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1461,7 +1461,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
|
||||
|
||||
- setOperationAction(ISD::CTPOP, MVT::i64, Legal);
|
||||
+ if (Subtarget->usePopc())
|
||||
+ setOperationAction(ISD::CTPOP, MVT::i64, Legal);
|
||||
setOperationAction(ISD::CTTZ , MVT::i64, Expand);
|
||||
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
|
||||
setOperationAction(ISD::CTLZ , MVT::i64, Expand);
|
||||
@@ -1567,7 +1568,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
|
||||
setStackPointerRegisterToSaveRestore(SP::O6);
|
||||
|
||||
- if (Subtarget->isV9())
|
||||
+ if (Subtarget->isV9() && Subtarget->usePopc())
|
||||
setOperationAction(ISD::CTPOP, MVT::i32, Legal);
|
||||
|
||||
if (Subtarget->isV9() && Subtarget->hasHardQuad()) {
|
||||
Index: lib/Target/Sparc/Sparc.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/Sparc.td
|
||||
+++ lib/Target/Sparc/Sparc.td
|
||||
@@ -34,6 +34,9 @@ def FeatureHardQuad
|
||||
: 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
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -69,9 +72,9 @@ def : Proc<"v9", [FeatureV9]>;
|
||||
def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated]>;
|
||||
def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated]>;
|
||||
def : Proc<"niagara", [FeatureV9, FeatureV8Deprecated]>;
|
||||
-def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated]>;
|
||||
-def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated]>;
|
||||
-def : Proc<"niagara4", [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";
|
||||
Index: lib/Target/Sparc/SparcSubtarget.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcSubtarget.h
|
||||
+++ lib/Target/Sparc/SparcSubtarget.h
|
||||
@@ -30,6 +30,7 @@ class SparcSubtarget : public SparcGenSubtargetInf
|
||||
bool IsVIS;
|
||||
bool Is64Bit;
|
||||
bool HasHardQuad;
|
||||
+ bool UsePopc;
|
||||
|
||||
public:
|
||||
SparcSubtarget(const std::string &TT, const std::string &CPU,
|
||||
@@ -39,6 +40,7 @@ class SparcSubtarget : public SparcGenSubtargetInf
|
||||
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/SparcSubtarget.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcSubtarget.cpp
|
||||
+++ lib/Target/Sparc/SparcSubtarget.cpp
|
||||
@@ -31,7 +31,8 @@ SparcSubtarget::SparcSubtarget(const std::string &
|
||||
V8DeprecatedInsts(false),
|
||||
IsVIS(false),
|
||||
Is64Bit(is64Bit),
|
||||
- HasHardQuad(false) {
|
||||
+ HasHardQuad(false),
|
||||
+ UsePopc(false) {
|
||||
|
||||
// Determine default and user specified characteristics
|
||||
std::string CPUName = CPU;
|
||||
Index: test/CodeGen/SPARC/ctpop.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/ctpop.ll
|
||||
+++ test/CodeGen/SPARC/ctpop.ll
|
||||
@@ -1,13 +1,13 @@
|
||||
; RUN: llc < %s -march=sparc -mattr=-v9 | FileCheck %s -check-prefix=V8
|
||||
-; RUN: llc < %s -march=sparc -mattr=+v9 | FileCheck %s -check-prefix=V9
|
||||
-; RUN: llc < %s -march=sparc -mcpu=v9 | FileCheck %s -check-prefix=V9
|
||||
-; RUN: llc < %s -march=sparc -mcpu=ultrasparc | FileCheck %s -check-prefix=V9
|
||||
-; RUN: llc < %s -march=sparc -mcpu=ultrasparc3 | FileCheck %s -check-prefix=V9
|
||||
-; RUN: llc < %s -march=sparc -mcpu=niagara | FileCheck %s -check-prefix=V9
|
||||
+; 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 | FileCheck %s -check-prefix=SPARC64
|
||||
+; RUN: llc < %s -march=sparcv9 -mattr=+popc | FileCheck %s -check-prefix=SPARC64
|
||||
|
||||
declare i32 @llvm.ctpop.i32(i32)
|
||||
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
Pull in r200141 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Clean up the Legal/Expand logic for SPARC popc.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcSubtarget.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcSubtarget.cpp
|
||||
+++ lib/Target/Sparc/SparcSubtarget.cpp
|
||||
@@ -41,6 +41,10 @@ SparcSubtarget::SparcSubtarget(const std::string &
|
||||
|
||||
// Parse features string.
|
||||
ParseSubtargetFeatures(CPUName, FS);
|
||||
+
|
||||
+ // Popc is a v9-only instruction.
|
||||
+ if (!IsV9)
|
||||
+ UsePopc = false;
|
||||
}
|
||||
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1461,8 +1461,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
|
||||
|
||||
- if (Subtarget->usePopc())
|
||||
- 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);
|
||||
@@ -1518,7 +1518,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
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);
|
||||
@@ -1568,8 +1567,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
|
||||
setStackPointerRegisterToSaveRestore(SP::O6);
|
||||
|
||||
- if (Subtarget->isV9() && Subtarget->usePopc())
|
||||
- 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);
|
||||
Index: test/CodeGen/SPARC/64bit.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/64bit.ll
|
||||
+++ test/CodeGen/SPARC/64bit.ll
|
||||
@@ -1,5 +1,5 @@
|
||||
-; 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
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
Pull in r200282 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Fix the DWARF EH encodings for Sparc PIC code.
|
||||
|
||||
Also emit the stubs that were generated for references to typeinfo
|
||||
symbols.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -23,7 +23,9 @@
|
||||
#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"
|
||||
@@ -54,6 +56,7 @@ namespace {
|
||||
|
||||
virtual void EmitFunctionBodyStart();
|
||||
virtual void EmitInstruction(const MachineInstr *MI);
|
||||
+ virtual void EmitEndOfAsmFile(Module &M);
|
||||
|
||||
static const char *getRegisterName(unsigned RegNo) {
|
||||
return SparcInstPrinter::getRegisterName(RegNo);
|
||||
@@ -450,6 +453,23 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const
|
||||
return false;
|
||||
}
|
||||
|
||||
+void SparcAsmPrinter::EmitEndOfAsmFile(Module &M) {
|
||||
+ const TargetLoweringObjectFileELF &TLOFELF =
|
||||
+ static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
|
||||
+ MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
|
||||
+
|
||||
+ // 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.
|
||||
extern "C" void LLVMInitializeSparcAsmPrinter() {
|
||||
RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
|
||||
Index: lib/MC/MCObjectFileInfo.cpp
|
||||
===================================================================
|
||||
--- lib/MC/MCObjectFileInfo.cpp
|
||||
+++ lib/MC/MCObjectFileInfo.cpp
|
||||
@@ -310,6 +310,33 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Tri
|
||||
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: test/CodeGen/SPARC/exception.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/exception.ll
|
||||
+++ test/CodeGen/SPARC/exception.ll
|
||||
@@ -1,4 +1,7 @@
|
||||
-; 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=sparcv9 -relocation-model=static | FileCheck -check-prefix=V9ABS %s
|
||||
+; RUN: llc < %s -march=sparcv9 -relocation-model=pic | FileCheck -check-prefix=V9PIC %s
|
||||
|
||||
|
||||
%struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo }
|
||||
@@ -9,23 +12,64 @@
|
||||
@.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|%fp}}
|
||||
-; 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 .L_ZTIi.DW.stub-
|
||||
+; V8PIC: .data
|
||||
+; V8PIC: .L_ZTIi.DW.stub:
|
||||
+; V8PIC-NEXT: .word _ZTIi
|
||||
+
|
||||
+; 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 .L_ZTIi.DW.stub-
|
||||
+; V9PIC: .data
|
||||
+; V9PIC: .L_ZTIi.DW.stub:
|
||||
+; V9PIC-NEXT: .xword _ZTIi
|
||||
+
|
||||
define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 {
|
||||
entry:
|
||||
%0 = icmp eq i32 %argc, 2
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
Pull r200368 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[SparcV9] Use correct register class (I64RegClass) to hold the address of _GLOBAL_OFFSET_TABLE_ in sparcv9.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.cpp
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.cpp
|
||||
@@ -431,9 +431,10 @@ unsigned SparcInstrInfo::getGlobalBaseReg(MachineF
|
||||
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
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -180,7 +180,7 @@ def tlscall : SDNode<"SPISD::TLS_CALL", SDT_
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
|
||||
SDNPVariadic]>;
|
||||
|
||||
-def getPCX : Operand<i32> {
|
||||
+def getPCX : Operand<iPTR> {
|
||||
let PrintMethod = "printGetPCX";
|
||||
}
|
||||
|
||||
Index: test/CodeGen/SPARC/2009-08-28-PIC.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/2009-08-28-PIC.ll
|
||||
+++ test/CodeGen/SPARC/2009-08-28-PIC.ll
|
||||
@@ -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
|
||||
+}
|
||||
|
|
@ -1,296 +0,0 @@
|
|||
Pull in r200373 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Use %r_disp32 for pc_rel entries in gcc_except_table and eh_frame.
|
||||
|
||||
Otherwise, assembler (gas) fails to assemble them with error message "operation
|
||||
combines symbols in different segments". This is because MC computes
|
||||
pc_rel entries with subtract expression between labels from different sections.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcTargetObjectFile.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcTargetObjectFile.h
|
||||
+++ lib/Target/Sparc/SparcTargetObjectFile.h
|
||||
@@ -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/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "SparcMachineFunctionInfo.h"
|
||||
#include "SparcRegisterInfo.h"
|
||||
#include "SparcTargetMachine.h"
|
||||
+#include "SparcTargetObjectFile.h"
|
||||
#include "MCTargetDesc/SparcBaseInfo.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
@@ -1361,7 +1362,7 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondC
|
||||
}
|
||||
|
||||
SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
- : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
|
||||
+ : TargetLowering(TM, new SparcELFTargetObjectFile()) {
|
||||
Subtarget = &TM.getSubtarget<SparcSubtarget>();
|
||||
|
||||
// Set up the register classes.
|
||||
Index: lib/Target/Sparc/SparcTargetObjectFile.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcTargetObjectFile.cpp
|
||||
+++ lib/Target/Sparc/SparcTargetObjectFile.cpp
|
||||
@@ -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/MCTargetDesc/SparcMCAsmInfo.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
|
||||
@@ -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,15 @@ SparcELFMCAsmInfo::SparcELFMCAsmInfo(StringRef TT)
|
||||
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);
|
||||
+}
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
@@ -41,6 +41,7 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const
|
||||
case VK_Sparc_L44: OS << "%l44("; break;
|
||||
case VK_Sparc_HH: OS << "%hh("; break;
|
||||
case VK_Sparc_HM: OS << "%hm("; 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;
|
||||
@@ -77,6 +78,7 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant
|
||||
.Case("l44", VK_Sparc_L44)
|
||||
.Case("hh", VK_Sparc_HH)
|
||||
.Case("hm", VK_Sparc_HM)
|
||||
+ .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)
|
||||
@@ -101,6 +103,8 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant
|
||||
bool
|
||||
SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout) const {
|
||||
+ if (!Layout)
|
||||
+ return false;
|
||||
return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
|
||||
}
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
|
||||
@@ -17,13 +17,16 @@
|
||||
#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;
|
||||
+};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
@@ -31,6 +31,7 @@ class SparcMCExpr : public MCTargetExpr {
|
||||
VK_Sparc_L44,
|
||||
VK_Sparc_HH,
|
||||
VK_Sparc_HM,
|
||||
+ VK_Sparc_R_DISP32,
|
||||
VK_Sparc_TLS_GD_HI22,
|
||||
VK_Sparc_TLS_GD_LO10,
|
||||
VK_Sparc_TLS_GD_ADD,
|
||||
Index: lib/Target/Sparc/CMakeLists.txt
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/CMakeLists.txt
|
||||
+++ lib/Target/Sparc/CMakeLists.txt
|
||||
@@ -27,6 +27,7 @@ add_llvm_target(SparcCodeGen
|
||||
SparcJITInfo.cpp
|
||||
SparcCodeEmitter.cpp
|
||||
SparcMCInstLower.cpp
|
||||
+ SparcTargetObjectFile.cpp
|
||||
)
|
||||
|
||||
add_dependencies(LLVMSparcCodeGen SparcCommonTableGen intrinsics_gen)
|
||||
Index: test/CodeGen/SPARC/exception.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/exception.ll
|
||||
+++ test/CodeGen/SPARC/exception.ll
|
||||
@@ -1,7 +1,9 @@
|
||||
; 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 }
|
||||
@@ -40,11 +42,23 @@
|
||||
; V8PIC: .cfi_register 15, 31
|
||||
; V8PIC: .section .gcc_except_table
|
||||
; V8PIC-NOT: .section
|
||||
-; V8PIC: .word .L_ZTIi.DW.stub-
|
||||
+; 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: .word %r_disp32(DW.ref.__gxx_personality_v0)
|
||||
+
|
||||
+
|
||||
; V9ABS-LABEL: main:
|
||||
; V9ABS: .cfi_startproc
|
||||
; V9ABS: .cfi_personality 0, __gxx_personality_v0
|
||||
@@ -65,11 +79,22 @@
|
||||
; V9PIC: .cfi_register 15, 31
|
||||
; V9PIC: .section .gcc_except_table
|
||||
; V9PIC-NOT: .section
|
||||
-; V9PIC: .word .L_ZTIi.DW.stub-
|
||||
+; 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: .word %r_disp32(DW.ref.__gxx_personality_v0)
|
||||
+
|
||||
define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 {
|
||||
entry:
|
||||
%0 = icmp eq i32 %argc, 2
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
Pull in r200376 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Use %r_disp32 for pc_rel entries in FDE as well.
|
||||
|
||||
This makes MCAsmInfo::getExprForFDESymbol() a virtual function and overrides it in SparcMCAsmInfo.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
|
||||
@@ -26,6 +26,10 @@ class SparcELFMCAsmInfo : public MCAsmInfoELF {
|
||||
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
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
|
||||
@@ -58,3 +58,15 @@ SparcELFMCAsmInfo::getExprForPersonalitySymbol(con
|
||||
|
||||
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: test/CodeGen/SPARC/exception.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/exception.ll
|
||||
+++ test/CodeGen/SPARC/exception.ll
|
||||
@@ -57,6 +57,7 @@
|
||||
; V8PIC_NOCFI: .section .eh_frame
|
||||
; V8PIC_NOCFI-NOT: .section
|
||||
; V8PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0)
|
||||
+; V8PIC_NOCFI: .word %r_disp32(.Ltmp{{.+}}) ! FDE initial location
|
||||
|
||||
|
||||
; V9ABS-LABEL: main:
|
||||
@@ -94,6 +95,7 @@
|
||||
; V9PIC_NOCFI: .section .eh_frame
|
||||
; V9PIC_NOCFI-NOT: .section
|
||||
; V9PIC_NOCFI: .word %r_disp32(DW.ref.__gxx_personality_v0)
|
||||
+; V9PIC_NOCFI: .word %r_disp32(.Ltmp{{.+}}) ! FDE initial location
|
||||
|
||||
define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 {
|
||||
entry:
|
||||
Index: include/llvm/MC/MCAsmInfo.h
|
||||
===================================================================
|
||||
--- include/llvm/MC/MCAsmInfo.h
|
||||
+++ include/llvm/MC/MCAsmInfo.h
|
||||
@@ -371,7 +371,7 @@ namespace llvm {
|
||||
unsigned Encoding,
|
||||
MCStreamer &Streamer) const;
|
||||
|
||||
- const MCExpr *
|
||||
+ virtual const MCExpr *
|
||||
getExprForFDESymbol(const MCSymbol *Sym,
|
||||
unsigned Encoding,
|
||||
MCStreamer &Streamer) const;
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
Pull in r200509 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Save and restore float registers that may be used for parameter passing.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcJITInfo.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcJITInfo.cpp
|
||||
+++ lib/Target/Sparc/SparcJITInfo.cpp
|
||||
@@ -28,6 +28,13 @@ extern "C" void SparcCompilationCallback();
|
||||
|
||||
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"
|
||||
@@ -34,11 +41,46 @@ extern "C" {
|
||||
"\t.global SparcCompilationCallback\n"
|
||||
"\t.type SparcCompilationCallback, #function\n"
|
||||
"SparcCompilationCallback:\n"
|
||||
- // Save current register window.
|
||||
- "\tsave %sp, -192, %sp\n"
|
||||
+ // 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 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
|
||||
"\trestore %o0, 0, %g1\n"
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
Pull in r200617 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Set %o7 as the return address register instead of %i7 in MCRegisterInfo. Also, add CFI instructions to initialize the frame correctly.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
|
||||
@@ -33,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);
|
||||
@@ -41,7 +60,7 @@ static MCInstrInfo *createSparcMCInstrInfo() {
|
||||
|
||||
static MCRegisterInfo *createSparcMCRegisterInfo(StringRef TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
- InitSparcMCRegisterInfo(X, SP::I7);
|
||||
+ InitSparcMCRegisterInfo(X, SP::O7);
|
||||
return X;
|
||||
}
|
||||
|
||||
@@ -132,8 +151,8 @@ static MCInstPrinter *createSparcMCInstPrinter(con
|
||||
|
||||
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,
|
||||
Index: lib/Target/Sparc/SparcRegisterInfo.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcRegisterInfo.cpp
|
||||
+++ lib/Target/Sparc/SparcRegisterInfo.cpp
|
||||
@@ -35,7 +35,7 @@ ReserveAppRegisters("sparc-reserve-app-registers",
|
||||
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: test/CodeGen/SPARC/exception.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/exception.ll
|
||||
+++ test/CodeGen/SPARC/exception.ll
|
||||
@@ -56,7 +56,11 @@
|
||||
; 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
|
||||
|
||||
|
||||
@@ -94,7 +98,11 @@
|
||||
; 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 {
|
||||
|
|
@ -1,512 +0,0 @@
|
|||
Pull in r200960 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Use SparcMCExpr::VariantKind itself as MachineOperand's target flags.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -13,11 +13,11 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SparcISelLowering.h"
|
||||
+#include "MCTargetDesc/SparcMCExpr.h"
|
||||
#include "SparcMachineFunctionInfo.h"
|
||||
#include "SparcRegisterInfo.h"
|
||||
#include "SparcTargetMachine.h"
|
||||
#include "SparcTargetObjectFile.h"
|
||||
-#include "MCTargetDesc/SparcBaseInfo.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
@@ -1796,7 +1796,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue O
|
||||
// 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_HI,
|
||||
+ SparcMCExpr::VK_Sparc_LO, 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
|
||||
@@ -1813,20 +1814,24 @@ SDValue SparcTargetLowering::makeAddress(SDValue O
|
||||
llvm_unreachable("Unsupported absolute code model");
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1858,14 +1863,18 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress
|
||||
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);
|
||||
@@ -1903,17 +1912,17 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress
|
||||
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);
|
||||
|
||||
@@ -1923,7 +1932,8 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress
|
||||
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,
|
||||
@@ -1930,14 +1940,15 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress
|
||||
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,
|
||||
Index: lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
+++ lib/Target/Sparc/SparcCodeEmitter.cpp
|
||||
@@ -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"
|
||||
@@ -204,14 +204,14 @@ unsigned SparcCodeEmitter::getRelocation(const Mac
|
||||
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: return SP::reloc_sparc_h44;
|
||||
- case SPII::MO_M44: return SP::reloc_sparc_m44;
|
||||
- case SPII::MO_L44: return SP::reloc_sparc_l44;
|
||||
- case SPII::MO_HH: return SP::reloc_sparc_hh;
|
||||
- case SPII::MO_HM: return SP::reloc_sparc_hm;
|
||||
+ 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/SparcMCInstLower.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcMCInstLower.cpp
|
||||
+++ lib/Target/Sparc/SparcMCInstLower.cpp
|
||||
@@ -13,7 +13,6 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Sparc.h"
|
||||
-#include "MCTargetDesc/SparcBaseInfo.h"
|
||||
#include "MCTargetDesc/SparcMCExpr.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
@@ -33,41 +32,10 @@ static MCOperand LowerSymbolOperand(const MachineI
|
||||
const MachineOperand &MO,
|
||||
AsmPrinter &AP) {
|
||||
|
||||
- SparcMCExpr::VariantKind Kind;
|
||||
+ SparcMCExpr::VariantKind Kind =
|
||||
+ (SparcMCExpr::VariantKind)MO.getTargetFlags();
|
||||
const MCSymbol *Symbol = 0;
|
||||
|
||||
- unsigned TF = MO.getTargetFlags();
|
||||
-
|
||||
- switch(TF) {
|
||||
- default: llvm_unreachable("Unknown target flags on operand");
|
||||
- case SPII::MO_NO_FLAG: Kind = SparcMCExpr::VK_Sparc_None; break;
|
||||
- case SPII::MO_LO: Kind = SparcMCExpr::VK_Sparc_LO; break;
|
||||
- case SPII::MO_HI: Kind = SparcMCExpr::VK_Sparc_HI; break;
|
||||
- case SPII::MO_H44: Kind = SparcMCExpr::VK_Sparc_H44; break;
|
||||
- case SPII::MO_M44: Kind = SparcMCExpr::VK_Sparc_M44; break;
|
||||
- case SPII::MO_L44: Kind = SparcMCExpr::VK_Sparc_L44; break;
|
||||
- case SPII::MO_HH: Kind = SparcMCExpr::VK_Sparc_HH; break;
|
||||
- case SPII::MO_HM: Kind = SparcMCExpr::VK_Sparc_HM; break;
|
||||
- case SPII::MO_TLS_GD_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_GD_HI22; break;
|
||||
- case SPII::MO_TLS_GD_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_GD_LO10; break;
|
||||
- case SPII::MO_TLS_GD_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_GD_ADD; break;
|
||||
- case SPII::MO_TLS_GD_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_GD_CALL; break;
|
||||
- case SPII::MO_TLS_LDM_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_HI22; break;
|
||||
- case SPII::MO_TLS_LDM_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_LO10; break;
|
||||
- case SPII::MO_TLS_LDM_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_ADD; break;
|
||||
- case SPII::MO_TLS_LDM_CALL: Kind = SparcMCExpr::VK_Sparc_TLS_LDM_CALL; break;
|
||||
- case SPII::MO_TLS_LDO_HIX22:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_HIX22; break;
|
||||
- case SPII::MO_TLS_LDO_LOX10:Kind = SparcMCExpr::VK_Sparc_TLS_LDO_LOX10; break;
|
||||
- case SPII::MO_TLS_LDO_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_LDO_ADD; break;
|
||||
- case SPII::MO_TLS_IE_HI22: Kind = SparcMCExpr::VK_Sparc_TLS_IE_HI22; break;
|
||||
- case SPII::MO_TLS_IE_LO10: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LO10; break;
|
||||
- case SPII::MO_TLS_IE_LD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LD; break;
|
||||
- case SPII::MO_TLS_IE_LDX: Kind = SparcMCExpr::VK_Sparc_TLS_IE_LDX; break;
|
||||
- case SPII::MO_TLS_IE_ADD: Kind = SparcMCExpr::VK_Sparc_TLS_IE_ADD; break;
|
||||
- case SPII::MO_TLS_LE_HIX22: Kind = SparcMCExpr::VK_Sparc_TLS_LE_HIX22; break;
|
||||
- case SPII::MO_TLS_LE_LOX10: Kind = SparcMCExpr::VK_Sparc_TLS_LE_LOX10; break;
|
||||
- }
|
||||
-
|
||||
switch(MO.getType()) {
|
||||
default: llvm_unreachable("Unknown type in LowerSymbolOperand");
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
Index: lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "SparcTargetMachine.h"
|
||||
#include "SparcTargetStreamer.h"
|
||||
#include "InstPrinter/SparcInstPrinter.h"
|
||||
-#include "MCTargetDesc/SparcBaseInfo.h"
|
||||
#include "MCTargetDesc/SparcMCExpr.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
@@ -287,83 +286,60 @@ void SparcAsmPrinter::EmitFunctionBodyStart() {
|
||||
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 || MI->getOpcode() == SP::SETHIXi)
|
||||
- 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) &&
|
||||
+ 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 || MI->getOpcode() == SP::XORXri)
|
||||
- assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) &&
|
||||
+ 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();
|
||||
Index: lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
+++ lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
|
||||
@@ -15,7 +15,6 @@
|
||||
#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"
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h
|
||||
@@ -1,82 +0,0 @@
|
||||
-//===-- SparcBaseInfo.h - Top level definitions 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 contains small standalone helper functions and enum definitions
|
||||
-// for the Sparc target useful for the compiler back-end and the MC libraries.
|
||||
-// As such, it deliberately does not include references to LLVM core code gen
|
||||
-// types, passes, etc..
|
||||
-//
|
||||
-//===----------------------------------------------------------------------===//
|
||||
-
|
||||
-#ifndef SPARCBASEINFO_H
|
||||
-#define SPARCBASEINFO_H
|
||||
-
|
||||
-namespace llvm {
|
||||
-
|
||||
-/// SPII - This namespace holds target specific flags for instruction info.
|
||||
-namespace SPII {
|
||||
-
|
||||
-/// Target Operand Flags. Sparc specific TargetFlags for MachineOperands and
|
||||
-/// SDNodes.
|
||||
-enum TOF {
|
||||
- MO_NO_FLAG,
|
||||
-
|
||||
- // Extract the low 10 bits of an address.
|
||||
- // Assembler: %lo(addr)
|
||||
- MO_LO,
|
||||
-
|
||||
- // Extract bits 31-10 of an address. Only for sethi.
|
||||
- // Assembler: %hi(addr) or %lm(addr)
|
||||
- MO_HI,
|
||||
-
|
||||
- // Extract bits 43-22 of an adress. Only for sethi.
|
||||
- // Assembler: %h44(addr)
|
||||
- MO_H44,
|
||||
-
|
||||
- // Extract bits 21-12 of an address.
|
||||
- // Assembler: %m44(addr)
|
||||
- MO_M44,
|
||||
-
|
||||
- // Extract bits 11-0 of an address.
|
||||
- // Assembler: %l44(addr)
|
||||
- MO_L44,
|
||||
-
|
||||
- // Extract bits 63-42 of an address. Only for sethi.
|
||||
- // Assembler: %hh(addr)
|
||||
- MO_HH,
|
||||
-
|
||||
- // Extract bits 41-32 of an address.
|
||||
- // Assembler: %hm(addr)
|
||||
- MO_HM,
|
||||
-
|
||||
- // TargetFlags for Thread Local Storage.
|
||||
- MO_TLS_GD_HI22,
|
||||
- MO_TLS_GD_LO10,
|
||||
- MO_TLS_GD_ADD,
|
||||
- MO_TLS_GD_CALL,
|
||||
- MO_TLS_LDM_HI22,
|
||||
- MO_TLS_LDM_LO10,
|
||||
- MO_TLS_LDM_ADD,
|
||||
- MO_TLS_LDM_CALL,
|
||||
- MO_TLS_LDO_HIX22,
|
||||
- MO_TLS_LDO_LOX10,
|
||||
- MO_TLS_LDO_ADD,
|
||||
- MO_TLS_IE_HI22,
|
||||
- MO_TLS_IE_LO10,
|
||||
- MO_TLS_IE_LD,
|
||||
- MO_TLS_IE_LDX,
|
||||
- MO_TLS_IE_ADD,
|
||||
- MO_TLS_LE_HIX22,
|
||||
- MO_TLS_LE_LOX10
|
||||
-};
|
||||
-
|
||||
-} // end namespace SPII
|
||||
-} // end namespace llvm
|
||||
-
|
||||
-#endif
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
@@ -29,8 +29,21 @@ SparcMCExpr::Create(VariantKind Kind, const MCExpr
|
||||
}
|
||||
|
||||
|
||||
+
|
||||
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;
|
||||
@@ -61,11 +74,7 @@ void SparcMCExpr::PrintImpl(raw_ostream &OS) const
|
||||
case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; break;
|
||||
case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; break;
|
||||
}
|
||||
-
|
||||
- const MCExpr *Expr = getSubExpr();
|
||||
- Expr->print(OS);
|
||||
- if (closeParen)
|
||||
- OS << ')';
|
||||
+ return closeParen;
|
||||
}
|
||||
|
||||
SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name)
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
@@ -93,7 +93,7 @@ class SparcMCExpr : public MCTargetExpr {
|
||||
static bool classof(const SparcMCExpr *) { return true; }
|
||||
|
||||
static VariantKind parseVariantKind(StringRef name);
|
||||
-
|
||||
+ static bool printVariantKind(raw_ostream &OS, VariantKind Kind);
|
||||
};
|
||||
|
||||
} // end namespace llvm.
|
||||
|
|
@ -1,443 +0,0 @@
|
|||
Pull in r200961 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Emit correct relocations for PIC code when integrated assembler is used.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/CodeGen/SPARC/obj-relocs.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/obj-relocs.ll
|
||||
+++ test/CodeGen/SPARC/obj-relocs.ll
|
||||
@@ -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: ]
|
||||
+
|
||||
+
|
||||
+@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: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -895,10 +895,12 @@ SparcTargetLowering::LowerCall_32(TargetLowering::
|
||||
// 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);
|
||||
@@ -1209,10 +1211,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::
|
||||
// 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;
|
||||
@@ -1796,8 +1801,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue O
|
||||
// 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, SparcMCExpr::VK_Sparc_HI,
|
||||
- SparcMCExpr::VK_Sparc_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
|
||||
Index: lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
||||
@@ -232,12 +232,12 @@ void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(co
|
||||
MCOperand Callee = createPCXCallOP(EndLabel, OutContext);
|
||||
EmitCall(OutStreamer, Callee);
|
||||
OutStreamer.EmitLabel(SethiLabel);
|
||||
- MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_HI,
|
||||
+ MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22,
|
||||
GOTLabel, StartLabel, SethiLabel,
|
||||
OutContext);
|
||||
EmitSETHI(OutStreamer, hiImm, MCRegOP);
|
||||
OutStreamer.EmitLabel(EndLabel);
|
||||
- MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_LO,
|
||||
+ MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10,
|
||||
GOTLabel, StartLabel, EndLabel,
|
||||
OutContext);
|
||||
EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP);
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
@@ -26,6 +26,7 @@ static unsigned adjustFixupValue(unsigned Kind, ui
|
||||
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:
|
||||
@@ -32,8 +33,12 @@ static unsigned adjustFixupValue(unsigned Kind, ui
|
||||
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_hi22:
|
||||
return (Value >> 10) & 0x3fffff;
|
||||
+ case Sparc::fixup_sparc_pc10:
|
||||
+ case Sparc::fixup_sparc_got10:
|
||||
case Sparc::fixup_sparc_lo10:
|
||||
return Value & 0x3ff;
|
||||
case Sparc::fixup_sparc_h44:
|
||||
@@ -72,6 +77,11 @@ namespace {
|
||||
{ "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 }
|
||||
};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
@@ -82,6 +92,20 @@ namespace {
|
||||
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: IsResolved = false; break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const {
|
||||
// FIXME.
|
||||
return false;
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
@@ -48,6 +48,21 @@ namespace llvm {
|
||||
/// 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,
|
||||
+
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
@@ -7,8 +7,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
+#include "MCTargetDesc/SparcFixupKinds.h"
|
||||
+#include "MCTargetDesc/SparcMCExpr.h"
|
||||
#include "MCTargetDesc/SparcMCTargetDesc.h"
|
||||
-#include "MCTargetDesc/SparcFixupKinds.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
@@ -31,6 +32,11 @@ namespace {
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,6 +46,12 @@ unsigned SparcELFObjectWriter::GetRelocType(const
|
||||
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:
|
||||
@@ -51,6 +63,9 @@ unsigned SparcELFObjectWriter::GetRelocType(const
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,10 +89,30 @@ unsigned SparcELFObjectWriter::GetRelocType(const
|
||||
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;
|
||||
}
|
||||
+
|
||||
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) {
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
@@ -17,6 +17,7 @@
|
||||
#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"
|
||||
|
||||
|
||||
@@ -54,6 +55,13 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS
|
||||
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;
|
||||
@@ -87,6 +95,10 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant
|
||||
.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)
|
||||
@@ -109,9 +121,26 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariant
|
||||
.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;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
bool
|
||||
SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
|
||||
- const MCAsmLayout *Layout) const {
|
||||
+ const MCAsmLayout *Layout) const {
|
||||
if (!Layout)
|
||||
return false;
|
||||
return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef LLVM_SPARCMCEXPR_H
|
||||
#define LLVM_SPARCMCEXPR_H
|
||||
|
||||
+#include "SparcFixupKinds.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
|
||||
namespace llvm {
|
||||
@@ -31,6 +32,11 @@ class SparcMCExpr : public MCTargetExpr {
|
||||
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,
|
||||
@@ -75,6 +81,9 @@ class SparcMCExpr : public MCTargetExpr {
|
||||
/// 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,
|
||||
@@ -94,6 +103,7 @@ class SparcMCExpr : public MCTargetExpr {
|
||||
|
||||
static VariantKind parseVariantKind(StringRef name);
|
||||
static bool printVariantKind(raw_ostream &OS, VariantKind Kind);
|
||||
+ static Sparc::Fixups getFixupKind(VariantKind Kind);
|
||||
};
|
||||
|
||||
} // end namespace llvm.
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
@@ -94,37 +94,8 @@ getMachineOpValue(const MCInst &MI, const MCOperan
|
||||
assert(MO.isExpr());
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
|
||||
- switch(SExpr->getKind()) {
|
||||
- default: assert(0 && "Unhandled sparc expression!"); break;
|
||||
- case SparcMCExpr::VK_Sparc_LO:
|
||||
- Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
- (MCFixupKind)Sparc::fixup_sparc_lo10));
|
||||
- break;
|
||||
- case SparcMCExpr::VK_Sparc_HI:
|
||||
- Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
- (MCFixupKind)Sparc::fixup_sparc_hi22));
|
||||
- break;
|
||||
- case SparcMCExpr::VK_Sparc_H44:
|
||||
- Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
- (MCFixupKind)Sparc::fixup_sparc_h44));
|
||||
- break;
|
||||
- case SparcMCExpr::VK_Sparc_M44:
|
||||
- Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
- (MCFixupKind)Sparc::fixup_sparc_m44));
|
||||
- break;
|
||||
- case SparcMCExpr::VK_Sparc_L44:
|
||||
- Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
- (MCFixupKind)Sparc::fixup_sparc_l44));
|
||||
- break;
|
||||
- case SparcMCExpr::VK_Sparc_HH:
|
||||
- Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
- (MCFixupKind)Sparc::fixup_sparc_hh));
|
||||
- break;
|
||||
- case SparcMCExpr::VK_Sparc_HM:
|
||||
- Fixups.push_back(MCFixup::Create(0, Expr,
|
||||
- (MCFixupKind)Sparc::fixup_sparc_hm));
|
||||
- break;
|
||||
- }
|
||||
+ MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
|
||||
+ Fixups.push_back(MCFixup::Create(0, Expr, Kind));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -143,8 +114,15 @@ getCallTargetOpValue(const MCInst &MI, unsigned Op
|
||||
if (MO.isReg() || MO.isImm())
|
||||
return getMachineOpValue(MI, MO, Fixups);
|
||||
|
||||
- Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
|
||||
- (MCFixupKind)Sparc::fixup_sparc_call30));
|
||||
+ 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;
|
||||
}
|
||||
|
||||
|
|
@ -1,378 +0,0 @@
|
|||
Pull in r200962 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Emit relocations for Thread Local Storage (TLS) when integrated assembler is used.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
|
||||
@@ -26,31 +26,65 @@ static unsigned adjustFixupValue(unsigned Kind, ui
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +115,25 @@ namespace {
|
||||
{ "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_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)
|
||||
@@ -101,11 +153,28 @@ namespace {
|
||||
bool &IsResolved) {
|
||||
switch ((Sparc::Fixups)Fixup.getKind()) {
|
||||
default: break;
|
||||
- case Sparc::fixup_sparc_wplt30: IsResolved = false; 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;
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
|
||||
@@ -63,6 +63,26 @@ namespace llvm {
|
||||
/// 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
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
|
||||
@@ -91,6 +91,24 @@ unsigned SparcELFObjectWriter::GetRelocType(const
|
||||
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;
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
|
||||
@@ -135,6 +135,25 @@ Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExp
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +166,33 @@ SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Re
|
||||
}
|
||||
|
||||
static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
|
||||
- assert(0 && "Implement fixELFSymbolsInTLSFixupsImpl!");
|
||||
+ 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 {
|
||||
Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
+++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
+#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
@@ -76,6 +77,21 @@ EncodeInstruction(const MCInst &MI, raw_ostream &O
|
||||
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.
|
||||
}
|
||||
@@ -114,6 +130,21 @@ getCallTargetOpValue(const MCInst &MI, unsigned Op
|
||||
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())) {
|
||||
Index: test/CodeGen/SPARC/tls.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/tls.ll
|
||||
+++ test/CodeGen/SPARC/tls.ll
|
||||
@@ -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
|
||||
@@ -69,3 +73,47 @@ entry:
|
||||
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: ]
|
||||
+
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
Pull in r200963 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Emit correct encoding for atomic instructions. Also, add support for parsing CAS instructions to test the CAS encoding.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: test/MC/Sparc/sparc-atomic-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-atomic-instructions.s
|
||||
+++ test/MC/Sparc/sparc-atomic-instructions.s
|
||||
@@ -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: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -935,19 +935,19 @@ let Predicates = [HasV9], hasSideEffects = 1, rd =
|
||||
def MEMBARi : F3_2<2, 0b101000, (outs), (ins i32imm:$simm13),
|
||||
"membar $simm13", []>;
|
||||
|
||||
-let Constraints = "$val = $rd" in {
|
||||
+let Constraints = "$val = $dst" in {
|
||||
def SWAPrr : F3_1<3, 0b001111,
|
||||
- (outs IntRegs:$rd), (ins IntRegs:$val, MEMrr:$addr),
|
||||
- "swap [$addr], $rd",
|
||||
- [(set i32:$rd, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>;
|
||||
+ (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:$rd), (ins IntRegs:$val, MEMri:$addr),
|
||||
- "swap [$addr], $rd",
|
||||
- [(set i32:$rd, (atomic_swap_32 ADDRri:$addr, i32:$val))]>;
|
||||
+ (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<3, 0b111100,
|
||||
+ def CASrr: F3_1_asi<3, 0b111100, 0b10000000,
|
||||
(outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2,
|
||||
IntRegs:$swap),
|
||||
"cas [$rs1], $rs2, $rd",
|
||||
Index: lib/Target/Sparc/SparcInstrFormats.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrFormats.td
|
||||
+++ lib/Target/Sparc/SparcInstrFormats.td
|
||||
@@ -100,9 +100,8 @@ class F3<dag outs, dag ins, string asmstr, list<da
|
||||
|
||||
// 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;
|
||||
@@ -113,6 +112,10 @@ class F3<dag outs, dag ins, string asmstr, list<da
|
||||
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;
|
||||
Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
+++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
|
||||
@@ -546,7 +546,24 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*>
|
||||
Parser.getTok().getLoc()));
|
||||
Parser.Lex(); // Eat the [
|
||||
|
||||
- ResTy = parseMEMOperand(Operands);
|
||||
+ 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;
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -415,7 +415,7 @@ def SETHIXi : F2_1<0b100,
|
||||
|
||||
// ATOMICS.
|
||||
let Predicates = [Is64Bit], Constraints = "$swap = $rd" in {
|
||||
- def CASXrr: F3_1<3, 0b111110,
|
||||
+ def CASXrr: F3_1_asi<3, 0b111110, 0b10000000,
|
||||
(outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2,
|
||||
I64Regs:$swap),
|
||||
"casx [$rs1], $rs2, $rd",
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
Pull in r200965 from upstream llvm trunk (by Venkatraman Govindaraju):
|
||||
|
||||
[Sparc] Add support for parsing synthetic instruction 'mov'.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrAliases.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrAliases.td
|
||||
+++ lib/Target/Sparc/SparcInstrAliases.td
|
||||
@@ -134,3 +134,9 @@ 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: test/MC/Sparc/sparc-alu-instructions.s
|
||||
===================================================================
|
||||
--- test/MC/Sparc/sparc-alu-instructions.s
|
||||
+++ test/MC/Sparc/sparc-alu-instructions.s
|
||||
@@ -70,3 +70,8 @@
|
||||
! 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
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
Pull in r198311 from upstream clang trunk (by Roman Divacky):
|
||||
|
||||
In the FreeBSD assembler driver, inform the sparc assembler that we're producing
|
||||
PIC code.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -5785,6 +5785,19 @@ void freebsd::Assemble::ConstructJob(Compilation &
|
||||
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,
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
Pull in r198312 from upstream clang trunk (by Roman Divacky):
|
||||
|
||||
Remove a tab that snuck in.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -5786,7 +5786,7 @@ void freebsd::Assemble::ConstructJob(Compilation &
|
||||
CmdArgs.push_back("-matpcs");
|
||||
}
|
||||
} else if (getToolChain().getArch() == llvm::Triple::sparc ||
|
||||
- getToolChain().getArch() == llvm::Triple::sparcv9) {
|
||||
+ 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,
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
Pull in r198911 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Pass -32/-64 to the assembler when building for sparc/sparc64.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/test/Driver/linux-as.c
|
||||
===================================================================
|
||||
--- tools/clang/test/Driver/linux-as.c
|
||||
+++ tools/clang/test/Driver/linux-as.c
|
||||
@@ -60,6 +60,20 @@
|
||||
// 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: -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: -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: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -6226,6 +6226,10 @@ void gnutools::Assemble::ConstructJob(Compilation
|
||||
CmdArgs.push_back("-a64");
|
||||
CmdArgs.push_back("-mppc64le");
|
||||
CmdArgs.push_back("-many");
|
||||
+ } else if (getToolChain().getArch() == llvm::Triple::sparc) {
|
||||
+ CmdArgs.push_back("-32");
|
||||
+ } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
|
||||
+ CmdArgs.push_back("-64");
|
||||
} else if (getToolChain().getArch() == llvm::Triple::arm) {
|
||||
StringRef MArch = getToolChain().getArchName();
|
||||
if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
Pull in r198912 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Give the linker the right ELF type for SPARC targets.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -6461,6 +6461,10 @@ void gnutools::Link::ConstructJob(Compilation &C,
|
||||
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: tools/clang/test/Driver/linux-ld.c
|
||||
===================================================================
|
||||
--- tools/clang/test/Driver/linux-ld.c
|
||||
+++ tools/clang/test/Driver/linux-ld.c
|
||||
@@ -384,6 +384,18 @@
|
||||
// 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"
|
||||
+//
|
||||
+// 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"
|
||||
+//
|
||||
// Thoroughly exercise the Debian multiarch environment.
|
||||
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
|
||||
// RUN: --target=i686-linux-gnu \
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
Pull in r198918 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Locate GCC installations on SPARC systems.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/Driver/ToolChains.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/ToolChains.cpp
|
||||
+++ tools/clang/lib/Driver/ToolChains.cpp
|
||||
@@ -1164,6 +1164,13 @@ void Generic_GCC::GCCInstallationDetector::print(r
|
||||
"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 @@ void Generic_GCC::GCCInstallationDetector::print(r
|
||||
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 @@ static bool findTargetBiarchSuffix(std::string &Su
|
||||
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)
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
Pull in r198923 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Use the right dynamic linker for SPARC Linux executables.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -6374,7 +6374,8 @@ static StringRef getLinuxDynamicLinker(const ArgLi
|
||||
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";
|
||||
@@ -6399,6 +6400,8 @@ static StringRef getLinuxDynamicLinker(const ArgLi
|
||||
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";
|
||||
}
|
||||
Index: tools/clang/test/Driver/linux-ld.c
|
||||
===================================================================
|
||||
--- tools/clang/test/Driver/linux-ld.c
|
||||
+++ tools/clang/test/Driver/linux-ld.c
|
||||
@@ -389,6 +389,7 @@
|
||||
// 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 \
|
||||
@@ -395,6 +396,7 @@
|
||||
// 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 \
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
Pull in r199012 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Select the UltraSPARC instruction set when invoking the assembler.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -6228,8 +6228,10 @@ void gnutools::Assemble::ConstructJob(Compilation
|
||||
CmdArgs.push_back("-many");
|
||||
} else if (getToolChain().getArch() == llvm::Triple::sparc) {
|
||||
CmdArgs.push_back("-32");
|
||||
+ CmdArgs.push_back("-Av8plusa");
|
||||
} else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
|
||||
CmdArgs.push_back("-64");
|
||||
+ CmdArgs.push_back("-Av9a");
|
||||
} else if (getToolChain().getArch() == llvm::Triple::arm) {
|
||||
StringRef MArch = getToolChain().getArchName();
|
||||
if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
|
||||
Index: tools/clang/test/Driver/linux-as.c
|
||||
===================================================================
|
||||
--- tools/clang/test/Driver/linux-as.c
|
||||
+++ tools/clang/test/Driver/linux-as.c
|
||||
@@ -65,6 +65,7 @@
|
||||
// RUN: | FileCheck -check-prefix=CHECK-SPARCV9 %s
|
||||
// CHECK-SPARCV9: as
|
||||
// CHECK-SPARCV9: -64
|
||||
+// CHECK-SPARCV9: -Av9a
|
||||
// CHECK-SPARCV9: -o
|
||||
//
|
||||
// RUN: %clang -target sparc-linux -mcpu=invalid-cpu -### \
|
||||
@@ -72,6 +73,7 @@
|
||||
// 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 \
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
Pull in r199034 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
MIPS and SPARC assemblers both take the -KPIC flag.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -6207,6 +6207,7 @@ void gnutools::Assemble::ConstructJob(Compilation
|
||||
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
|
||||
@@ -6229,9 +6230,11 @@ void gnutools::Assemble::ConstructJob(Compilation
|
||||
} 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")
|
||||
@@ -6291,6 +6294,15 @@ void gnutools::Assemble::ConstructJob(Compilation
|
||||
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,
|
||||
@@ -6302,11 +6314,6 @@ void gnutools::Assemble::ConstructJob(Compilation
|
||||
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,
|
||||
Index: tools/clang/test/Driver/linux-as.c
|
||||
===================================================================
|
||||
--- tools/clang/test/Driver/linux-as.c
|
||||
+++ tools/clang/test/Driver/linux-as.c
|
||||
@@ -66,8 +66,18 @@
|
||||
// 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
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
Pull in r199037 from upstream clang trunk (by Jakob Stokund Olesen):
|
||||
|
||||
SPARC passes non-trivial C++ objects indirectly like everybody else.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/CodeGen/TargetInfo.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/CodeGen/TargetInfo.cpp
|
||||
+++ tools/clang/lib/CodeGen/TargetInfo.cpp
|
||||
@@ -5349,6 +5349,11 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned
|
||||
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: tools/clang/test/CodeGenCXX/sparcv9-abi.cpp
|
||||
===================================================================
|
||||
--- tools/clang/test/CodeGenCXX/sparcv9-abi.cpp
|
||||
+++ tools/clang/test/CodeGenCXX/sparcv9-abi.cpp
|
||||
@@ -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);
|
||||
+}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
Pull in r199188 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Puny 24-byte structs are returned by value on SPARC.
|
||||
|
||||
Pad these structs up so they are sret-returned even on that
|
||||
architecture.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/test/CodeGen/sret.c
|
||||
===================================================================
|
||||
--- tools/clang/test/CodeGen/sret.c
|
||||
+++ tools/clang/test/CodeGen/sret.c
|
||||
@@ -4,6 +4,8 @@ struct abc {
|
||||
long a;
|
||||
long b;
|
||||
long c;
|
||||
+ long d;
|
||||
+ long e;
|
||||
};
|
||||
|
||||
struct abc foo1(void);
|
||||
Index: tools/clang/test/CodeGen/sret2.c
|
||||
===================================================================
|
||||
--- tools/clang/test/CodeGen/sret2.c
|
||||
+++ tools/clang/test/CodeGen/sret2.c
|
||||
@@ -4,6 +4,8 @@ struct abc {
|
||||
long a;
|
||||
long b;
|
||||
long c;
|
||||
+ long d;
|
||||
+ long e;
|
||||
};
|
||||
|
||||
struct abc foo2(){}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
Pull in r199399 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
SPARCv9 implements long double as an IEEE quad.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/test/CodeGen/sparcv9-abi.c
|
||||
===================================================================
|
||||
--- tools/clang/test/CodeGen/sparcv9-abi.c
|
||||
+++ tools/clang/test/CodeGen/sparcv9-abi.c
|
||||
@@ -18,6 +18,9 @@ long long f_int_3(long long x) { return x; }
|
||||
// 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: tools/clang/lib/Basic/Targets.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Basic/Targets.cpp
|
||||
+++ tools/clang/lib/Basic/Targets.cpp
|
||||
@@ -4529,6 +4529,12 @@ class SparcV9TargetInfo : public SparcTargetInfo {
|
||||
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;
|
||||
}
|
||||
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
Pull in r200452 from upstream clang trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
SPARCv9 supports atomic operations up to 64 bits.
|
||||
|
||||
Patch by Roman Divacky!
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262262
|
||||
|
||||
Index: tools/clang/lib/Basic/Targets.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Basic/Targets.cpp
|
||||
+++ tools/clang/lib/Basic/Targets.cpp
|
||||
@@ -4535,6 +4535,7 @@ class SparcV9TargetInfo : public SparcTargetInfo {
|
||||
LongDoubleWidth = 128;
|
||||
LongDoubleAlign = 128;
|
||||
LongDoubleFormat = &llvm::APFloat::IEEEquad;
|
||||
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
|
||||
}
|
||||
|
||||
virtual void getTargetDefines(const LangOptions &Opts,
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
Pull in r200453 from upstream llvm trunk (by Jakob Stoklund Olesen):
|
||||
|
||||
Implement SPARCv9 atomic_swap_64 with a pseudo.
|
||||
|
||||
The SWAP instruction only exists in a 32-bit variant, but the 64-bit
|
||||
atomic swap can be implemented in terms of CASX, like the other atomic
|
||||
rmw primitives.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262264
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstr64Bit.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstr64Bit.td
|
||||
+++ lib/Target/Sparc/SparcInstr64Bit.td
|
||||
@@ -463,6 +463,14 @@ defm ATOMIC_LOAD_MAX : AtomicRMW<atomic_load_max_
|
||||
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>;
|
||||
|
||||
+// There is no 64-bit variant of SWAP, so use a pseudo.
|
||||
+let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1,
|
||||
+ Defs = [ICC], Predicates = [Is64Bit] in
|
||||
+def ATOMIC_SWAP_64 : Pseudo<(outs I64Regs:$rd),
|
||||
+ (ins ptr_rc:$addr, I64Regs:$rs2), "",
|
||||
+ [(set i64:$rd,
|
||||
+ (atomic_swap_64 iPTR:$addr, i64:$rs2))]>;
|
||||
+
|
||||
// Global addresses, constant pool entries
|
||||
let Predicates = [Is64Bit] in {
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1498,7 +1498,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
|
||||
if (Subtarget->is64Bit()) {
|
||||
setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Legal);
|
||||
- setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Expand);
|
||||
+ setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Legal);
|
||||
setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
|
||||
setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom);
|
||||
}
|
||||
@@ -2885,6 +2885,9 @@ SparcTargetLowering::EmitInstrWithCustomInserter(M
|
||||
case SP::ATOMIC_LOAD_NAND_64:
|
||||
return expandAtomicRMW(MI, BB, SP::ANDXrr);
|
||||
|
||||
+ case SP::ATOMIC_SWAP_64:
|
||||
+ return expandAtomicRMW(MI, BB, 0);
|
||||
+
|
||||
case SP::ATOMIC_LOAD_MAX_32:
|
||||
return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_G);
|
||||
case SP::ATOMIC_LOAD_MAX_64:
|
||||
@@ -3023,7 +3026,8 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr
|
||||
|
||||
// Build the loop block.
|
||||
unsigned ValReg = MRI.createVirtualRegister(ValueRC);
|
||||
- unsigned UpdReg = MRI.createVirtualRegister(ValueRC);
|
||||
+ // Opcode == 0 means try to write Rs2Reg directly (ATOMIC_SWAP).
|
||||
+ unsigned UpdReg = (Opcode ? MRI.createVirtualRegister(ValueRC) : Rs2Reg);
|
||||
|
||||
BuildMI(LoopMBB, DL, TII.get(SP::PHI), ValReg)
|
||||
.addReg(Val0Reg).addMBB(MBB)
|
||||
@@ -3035,7 +3039,7 @@ SparcTargetLowering::expandAtomicRMW(MachineInstr
|
||||
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 {
|
||||
+ } else if (Opcode) {
|
||||
BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg)
|
||||
.addReg(ValReg).addReg(Rs2Reg);
|
||||
}
|
||||
Index: test/CodeGen/SPARC/atomics.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/atomics.ll
|
||||
+++ test/CodeGen/SPARC/atomics.ll
|
||||
@@ -62,6 +62,15 @@ entry:
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
+; CHECK-LABEL: test_swap_i64
|
||||
+; CHECK: casx [%o1],
|
||||
+
|
||||
+define i64 @test_swap_i64(i64 %a, i64* %ptr) {
|
||||
+entry:
|
||||
+ %b = atomicrmw xchg i64* %ptr, i64 42 monotonic
|
||||
+ ret i64 %b
|
||||
+}
|
||||
+
|
||||
; CHECK-LABEL: test_load_add_32
|
||||
; CHECK: membar
|
||||
; CHECK: add [[V:%[gilo][0-7]]], %o1, [[U:%[gilo][0-7]]]
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
Pull in r201718 from upstream llvm trunk (by Roman Divacky):
|
||||
|
||||
Expand 64bit {SHL,SHR,SRA}_PARTS on sparcv9.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262265
|
||||
|
||||
Index: test/CodeGen/SPARC/parts.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/parts.ll
|
||||
+++ test/CodeGen/SPARC/parts.ll
|
||||
@@ -0,0 +1,14 @@
|
||||
+; RUN: llc < %s -march=sparcv9 | FileCheck %s
|
||||
+
|
||||
+; CHECK-LABEL: test
|
||||
+; CHECK: srl %i1, 0, %o2
|
||||
+; CHECK-NEXT: or %g0, %i2, %o0
|
||||
+; CHECK-NEXT: call __ashlti3
|
||||
+; CHECK-NEXT: or %g0, %i3, %o1
|
||||
+; CHECK-NEXT: or %g0, %o0, %i0
|
||||
+
|
||||
+define i128 @test(i128 %a, i128 %b) {
|
||||
+entry:
|
||||
+ %tmp = shl i128 %b, %a
|
||||
+ ret i128 %tmp
|
||||
+}
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1554,6 +1554,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
|
||||
setOperationAction(ISD::UMULO, MVT::i64, Custom);
|
||||
setOperationAction(ISD::SMULO, MVT::i64, Custom);
|
||||
+
|
||||
+ setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
|
||||
+ setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
|
||||
+ setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand);
|
||||
}
|
||||
|
||||
// VASTART needs to be custom lowered to use the VarArgsFrameIndex.
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
Pull in r197521 from upstream clang trunk (by Roman Divacky):
|
||||
|
||||
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262303
|
||||
|
||||
Index: tools/clang/lib/Driver/ToolChains.h
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/ToolChains.h
|
||||
+++ tools/clang/lib/Driver/ToolChains.h
|
||||
@@ -512,8 +512,13 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Gen
|
||||
virtual void
|
||||
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const;
|
||||
+ virtual bool IsIntegratedAssemblerDefault() const {
|
||||
+ if (getTriple().getArch() == llvm::Triple::ppc ||
|
||||
+ getTriple().getArch() == llvm::Triple::ppc64)
|
||||
+ return true;
|
||||
+ return Generic_ELF::IsIntegratedAssemblerDefault();
|
||||
+ }
|
||||
|
||||
-
|
||||
virtual bool UseSjLjExceptions() const;
|
||||
protected:
|
||||
virtual Tool *buildAssembler() const;
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
Pull in r201994 from upstream llvm trunk (by Benjamin Kramer):
|
||||
|
||||
SPARC: Implement TRAP lowering. Matches what GCC emits.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262415
|
||||
|
||||
Index: lib/Target/Sparc/SparcInstrInfo.td
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcInstrInfo.td
|
||||
+++ lib/Target/Sparc/SparcInstrInfo.td
|
||||
@@ -312,6 +312,9 @@ let hasSideEffects = 1, mayStore = 1 in {
|
||||
[(flushw)]>;
|
||||
}
|
||||
|
||||
+let isBarrier = 1, isTerminator = 1, rd = 0b1000, rs1 = 0, simm13 = 5 in
|
||||
+ def TA5 : F3_2<0b10, 0b111010, (outs), (ins), "ta 5", [(trap)]>;
|
||||
+
|
||||
let rd = 0 in
|
||||
def UNIMP : F2_1<0b000, (outs), (ins i32imm:$val),
|
||||
"unimp $val", []>;
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -1565,6 +1565,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMac
|
||||
// VAARG needs to be lowered to not do unaligned accesses for doubles.
|
||||
setOperationAction(ISD::VAARG , MVT::Other, Custom);
|
||||
|
||||
+ setOperationAction(ISD::TRAP , MVT::Other, Legal);
|
||||
+
|
||||
// Use the default implementation.
|
||||
setOperationAction(ISD::VACOPY , MVT::Other, Expand);
|
||||
setOperationAction(ISD::VAEND , MVT::Other, Expand);
|
||||
Index: test/CodeGen/SPARC/trap.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/trap.ll
|
||||
+++ test/CodeGen/SPARC/trap.ll
|
||||
@@ -0,0 +1,11 @@
|
||||
+; RUN: llc -mtriple=sparc-linux-gnu < %s -show-mc-encoding | FileCheck %s
|
||||
+
|
||||
+define void @test1() {
|
||||
+ tail call void @llvm.trap()
|
||||
+ unreachable
|
||||
+
|
||||
+; CHECK-LABEL: test1:
|
||||
+; CHECK: ta 5 ! encoding: [0x91,0xd0,0x20,0x05]
|
||||
+}
|
||||
+
|
||||
+declare void @llvm.trap()
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
Pull in r202059 from upstream clang trunk (by Roman Divacky):
|
||||
|
||||
Implement getDwarfEHStackPointer() and initDwarfEHRegSizeTable() for sparcv9.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262460
|
||||
|
||||
Index: tools/clang/lib/CodeGen/TargetInfo.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/CodeGen/TargetInfo.cpp
|
||||
+++ tools/clang/lib/CodeGen/TargetInfo.cpp
|
||||
@@ -5435,10 +5435,51 @@ class SparcV9TargetCodeGenInfo : public TargetCode
|
||||
public:
|
||||
SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)
|
||||
: TargetCodeGenInfo(new SparcV9ABIInfo(CGT)) {}
|
||||
+
|
||||
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
|
||||
+ return 14;
|
||||
+ }
|
||||
+
|
||||
+ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
||||
+ llvm::Value *Address) const;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
+bool
|
||||
+SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
||||
+ llvm::Value *Address) const {
|
||||
+ // This is calculated from the LLVM and GCC tables and verified
|
||||
+ // against gcc output. AFAIK all ABIs use the same encoding.
|
||||
|
||||
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
|
||||
+
|
||||
+ llvm::IntegerType *i8 = CGF.Int8Ty;
|
||||
+ llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);
|
||||
+ llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
|
||||
+
|
||||
+ // 0-31: the 8-byte general-purpose registers
|
||||
+ AssignToArrayRange(Builder, Address, Eight8, 0, 31);
|
||||
+
|
||||
+ // 32-63: f0-31, the 4-byte floating-point registers
|
||||
+ AssignToArrayRange(Builder, Address, Four8, 32, 63);
|
||||
+
|
||||
+ // Y = 64
|
||||
+ // PSR = 65
|
||||
+ // WIM = 66
|
||||
+ // TBR = 67
|
||||
+ // PC = 68
|
||||
+ // NPC = 69
|
||||
+ // FSR = 70
|
||||
+ // CSR = 71
|
||||
+ AssignToArrayRange(Builder, Address, Eight8, 64, 71);
|
||||
+
|
||||
+ // 72-87: d0-15, the 8-byte floating-point registers
|
||||
+ AssignToArrayRange(Builder, Address, Eight8, 72, 87);
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Xcore ABI Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
Pull in r202177 from upstream clang trunk (by Roman Divacky):
|
||||
|
||||
Give sparcv9 the ability to set the target cpu. Change it from accepting
|
||||
-march which doesnt exist on sparc gcc to -mcpu. While here adjust a
|
||||
few tests to not write an unused temporary file.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262535
|
||||
|
||||
Index: tools/clang/lib/Basic/Targets.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Basic/Targets.cpp
|
||||
+++ tools/clang/lib/Basic/Targets.cpp
|
||||
@@ -4552,6 +4552,22 @@ class SparcV9TargetInfo : public SparcTargetInfo {
|
||||
Builder.defineMacro("__sparcv9__");
|
||||
}
|
||||
}
|
||||
+
|
||||
+ virtual bool setCPU(const std::string &Name) {
|
||||
+ bool CPUKnown = llvm::StringSwitch<bool>(Name)
|
||||
+ .Case("v9", true)
|
||||
+ .Case("ultrasparc", true)
|
||||
+ .Case("ultrasparc3", true)
|
||||
+ .Case("niagara", true)
|
||||
+ .Case("niagara2", true)
|
||||
+ .Case("niagara3", true)
|
||||
+ .Case("niagara4", true)
|
||||
+ .Default(false);
|
||||
+
|
||||
+ // No need to store the CPU yet. There aren't any CPU-specific
|
||||
+ // macros to define.
|
||||
+ return CPUKnown;
|
||||
+ }
|
||||
};
|
||||
|
||||
} // end anonymous namespace.
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -1373,7 +1373,8 @@ static std::string getCPUName(const ArgList &Args,
|
||||
}
|
||||
|
||||
case llvm::Triple::sparc:
|
||||
- if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
|
||||
+ case llvm::Triple::sparcv9:
|
||||
+ if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
|
||||
return A->getValue();
|
||||
return "";
|
||||
|
||||
Index: tools/clang/test/Driver/freebsd.c
|
||||
===================================================================
|
||||
--- tools/clang/test/Driver/freebsd.c
|
||||
+++ tools/clang/test/Driver/freebsd.c
|
||||
@@ -59,13 +59,13 @@
|
||||
// CHECK-MIPSEL: "{{[^" ]*}}ld{{[^" ]*}}"
|
||||
// CHECK-MIPSEL: "-dynamic-linker" "{{.*}}/libexec/ld-elf.so.1"
|
||||
// CHECK-MIPSEL-NOT: "--hash-style={{gnu|both}}"
|
||||
-// RUN: %clang %s -### -o %t.o 2>&1 \
|
||||
+// RUN: %clang %s -### 2>&1 \
|
||||
// RUN: -target mips64-unknown-freebsd10.0 \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-MIPS64 %s
|
||||
// CHECK-MIPS64: "{{[^" ]*}}ld{{[^" ]*}}"
|
||||
// CHECK-MIPS64: "-dynamic-linker" "{{.*}}/libexec/ld-elf.so.1"
|
||||
// CHECK-MIPS64-NOT: "--hash-style={{gnu|both}}"
|
||||
-// RUN: %clang %s -### -o %t.o 2>&1 \
|
||||
+// RUN: %clang %s -### 2>&1 \
|
||||
// RUN: -target mips64el-unknown-freebsd10.0 \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-MIPS64EL %s
|
||||
// CHECK-MIPS64EL: "{{[^" ]*}}ld{{[^" ]*}}"
|
||||
@@ -97,12 +97,12 @@
|
||||
// CHECK-NORMAL: crt1.o
|
||||
// CHECK-NORMAL: crtbegin.o
|
||||
|
||||
-// RUN: %clang %s -### -o %t.o -target arm-unknown-freebsd10.0 2>&1 \
|
||||
+// RUN: %clang %s -### -target arm-unknown-freebsd10.0 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-ARM %s
|
||||
// CHECK-ARM: clang{{.*}}" "-cc1"{{.*}}" "-fsjlj-exceptions"
|
||||
// CHECK-ARM: as{{.*}}" "-mfpu=softvfp"{{.*}}"-matpcs"
|
||||
|
||||
-// RUN: %clang %s -### -o %t.o -target arm-gnueabi-freebsd10.0 2>&1 \
|
||||
+// RUN: %clang %s -### -target arm-gnueabi-freebsd10.0 2>&1 \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-ARM-EABI %s
|
||||
// CHECK-ARM-EABI-NOT: clang{{.*}}" "-cc1"{{.*}}" "-fsjlj-exceptions"
|
||||
// CHECK-ARM-EABI: as{{.*}}" "-mfpu=softvfp" "-meabi=5"
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
Pull in r202179 from upstream clang trunk (by Roman Divacky):
|
||||
|
||||
Pass the sparc architecture variant to the assembler.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262536
|
||||
|
||||
Index: tools/clang/lib/Driver/Tools.cpp
|
||||
===================================================================
|
||||
--- tools/clang/lib/Driver/Tools.cpp
|
||||
+++ tools/clang/lib/Driver/Tools.cpp
|
||||
@@ -5788,6 +5788,11 @@ void freebsd::Assemble::ConstructJob(Compilation &
|
||||
}
|
||||
} else if (getToolChain().getArch() == llvm::Triple::sparc ||
|
||||
getToolChain().getArch() == llvm::Triple::sparcv9) {
|
||||
+ if (getToolChain().getArch() == llvm::Triple::sparc)
|
||||
+ CmdArgs.push_back("-Av8plusa");
|
||||
+ else
|
||||
+ CmdArgs.push_back("-Av9a");
|
||||
+
|
||||
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,
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
Pull in r202422 from upstream llvm trunk (by Roman Divacky):
|
||||
|
||||
Lower FNEG just like FABS to fneg[ds] and fmov[ds], thus avoiding
|
||||
expensive libcall. Also, Qp_neg is not implemented on at least
|
||||
FreeBSD. This is also what gcc is doing.
|
||||
|
||||
Introduced here: http://svnweb.freebsd.org/changeset/base/262582
|
||||
|
||||
Index: lib/Target/Sparc/SparcISelLowering.cpp
|
||||
===================================================================
|
||||
--- lib/Target/Sparc/SparcISelLowering.cpp
|
||||
+++ lib/Target/Sparc/SparcISelLowering.cpp
|
||||
@@ -2643,24 +2643,16 @@ static SDValue LowerF128Store(SDValue Op, Selectio
|
||||
&OutChains[0], 2);
|
||||
}
|
||||
|
||||
-static SDValue LowerFNEG(SDValue Op, SelectionDAG &DAG,
|
||||
- const SparcTargetLowering &TLI,
|
||||
- bool is64Bit) {
|
||||
- if (Op.getValueType() == MVT::f64)
|
||||
- return LowerF64Op(Op, DAG, ISD::FNEG);
|
||||
- if (Op.getValueType() == MVT::f128)
|
||||
- return TLI.LowerF128Op(Op, DAG, ((is64Bit) ? "_Qp_neg" : "_Q_neg"), 1);
|
||||
- return Op;
|
||||
-}
|
||||
+static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
|
||||
+ assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS) && "invalid");
|
||||
|
||||
-static SDValue LowerFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
|
||||
if (Op.getValueType() == MVT::f64)
|
||||
- return LowerF64Op(Op, DAG, ISD::FABS);
|
||||
+ return LowerF64Op(Op, DAG, Op.getOpcode());
|
||||
if (Op.getValueType() != MVT::f128)
|
||||
return Op;
|
||||
|
||||
- // Lower fabs on f128 to fabs on f64
|
||||
- // fabs f128 => fabs f64:sub_even64, fmov f64:sub_odd64
|
||||
+ // Lower fabs/fneg on f128 to fabs/fneg on f64
|
||||
+ // fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64
|
||||
|
||||
SDLoc dl(Op);
|
||||
SDValue SrcReg128 = Op.getOperand(0);
|
||||
@@ -2671,7 +2663,7 @@ static SDValue LowerF128Store(SDValue Op, Selectio
|
||||
if (isV9)
|
||||
Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64);
|
||||
else
|
||||
- Hi64 = LowerF64Op(Hi64, DAG, ISD::FABS);
|
||||
+ Hi64 = LowerF64Op(Hi64, DAG, Op.getOpcode());
|
||||
|
||||
SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
|
||||
dl, MVT::f128), 0);
|
||||
@@ -2792,7 +2784,6 @@ SDValue SparcTargetLowering::
|
||||
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
bool hasHardQuad = Subtarget->hasHardQuad();
|
||||
- bool is64Bit = Subtarget->is64Bit();
|
||||
bool isV9 = Subtarget->isV9();
|
||||
|
||||
switch (Op.getOpcode()) {
|
||||
@@ -2835,8 +2826,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons
|
||||
getLibcallName(RTLIB::DIV_F128), 2);
|
||||
case ISD::FSQRT: return LowerF128Op(Op, DAG,
|
||||
getLibcallName(RTLIB::SQRT_F128),1);
|
||||
- case ISD::FNEG: return LowerFNEG(Op, DAG, *this, is64Bit);
|
||||
- case ISD::FABS: return LowerFABS(Op, DAG, isV9);
|
||||
+ case ISD::FABS:
|
||||
+ case ISD::FNEG: return LowerFNEGorFABS(Op, DAG, isV9);
|
||||
case ISD::FP_EXTEND: return LowerF128_FPEXTEND(Op, DAG, *this);
|
||||
case ISD::FP_ROUND: return LowerF128_FPROUND(Op, DAG, *this);
|
||||
case ISD::ADDC:
|
||||
Index: test/CodeGen/SPARC/fp128.ll
|
||||
===================================================================
|
||||
--- test/CodeGen/SPARC/fp128.ll
|
||||
+++ test/CodeGen/SPARC/fp128.ll
|
||||
@@ -232,3 +232,14 @@ entry:
|
||||
store i32 %3, i32* %4, align 8
|
||||
ret void
|
||||
}
|
||||
+
|
||||
+; SOFT-LABEL: f128_neg
|
||||
+; SOFT: fnegs
|
||||
+
|
||||
+define void @f128_neg(fp128* noalias sret %scalar.result, fp128* byval %a) {
|
||||
+entry:
|
||||
+ %0 = load fp128* %a, align 8
|
||||
+ %1 = fsub fp128 0xL00000000000000008000000000000000, %0
|
||||
+ store fp128 %1, fp128* %scalar.result, align 8
|
||||
+ ret void
|
||||
+}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue