summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-26 07:31:57 +0000
committerdim <dim@FreeBSD.org>2014-03-26 07:31:57 +0000
commitfb422e6d310915f9e2641190198698d922f7ef58 (patch)
tree8126abc77e6620e23932d186c7b2b75457af47a5
parent5a582ae617991f602ee6f8a954a36fd749aa466c (diff)
downloadFreeBSD-src-fb422e6d310915f9e2641190198698d922f7ef58.zip
FreeBSD-src-fb422e6d310915f9e2641190198698d922f7ef58.tar.gz
MFC r262613:
Merge the projects/clang-sparc64 branch back to head. This brings in several updates from the llvm and clang trunks to make the sparc64 backend fully functional. Apart from one patch to sys/sparc64/include/pcpu.h which is still under discussion, this makes it possible to let clang fully build world and kernel for sparc64. Any assistance with testing this on actual sparc64 hardware is greatly appreciated, as there will unavoidably be bugs left. Many thanks go to Roman Divacky for his upstream work on getting the sparc64 backend into shape. MFC r262985: Repair a few minor mismerges from r262261 in the clang-sparc64 project branch. This is also to minimize differences with upstream.
-rw-r--r--contrib/compiler-rt/lib/absvti2.c5
-rw-r--r--contrib/compiler-rt/lib/addvti3.c4
-rw-r--r--contrib/compiler-rt/lib/ashlti3.c4
-rw-r--r--contrib/compiler-rt/lib/ashrti3.c4
-rw-r--r--contrib/compiler-rt/lib/clzti2.c4
-rw-r--r--contrib/compiler-rt/lib/cmpti2.c4
-rw-r--r--contrib/compiler-rt/lib/ctzti2.c4
-rw-r--r--contrib/compiler-rt/lib/divti3.c4
-rw-r--r--contrib/compiler-rt/lib/ffsti2.c4
-rw-r--r--contrib/compiler-rt/lib/fixdfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixsfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixunsdfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixunssfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixunsxfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixxfti.c4
-rw-r--r--contrib/compiler-rt/lib/floattidf.c4
-rw-r--r--contrib/compiler-rt/lib/floattisf.c4
-rw-r--r--contrib/compiler-rt/lib/floattixf.c6
-rw-r--r--contrib/compiler-rt/lib/floatuntidf.c6
-rw-r--r--contrib/compiler-rt/lib/floatuntisf.c4
-rw-r--r--contrib/compiler-rt/lib/floatuntixf.c2
-rw-r--r--contrib/compiler-rt/lib/int_types.h7
-rw-r--r--contrib/compiler-rt/lib/lshrti3.c4
-rw-r--r--contrib/compiler-rt/lib/modti3.c4
-rw-r--r--contrib/compiler-rt/lib/muloti4.c4
-rw-r--r--contrib/compiler-rt/lib/multi3.c4
-rw-r--r--contrib/compiler-rt/lib/mulvti3.c4
-rw-r--r--contrib/compiler-rt/lib/negti2.c4
-rw-r--r--contrib/compiler-rt/lib/negvti2.c4
-rw-r--r--contrib/compiler-rt/lib/parityti2.c4
-rw-r--r--contrib/compiler-rt/lib/popcountti2.c4
-rw-r--r--contrib/compiler-rt/lib/subvti3.c4
-rw-r--r--contrib/compiler-rt/lib/ucmpti2.c4
-rw-r--r--contrib/compiler-rt/lib/udivmodti4.c4
-rw-r--r--contrib/compiler-rt/lib/udivti3.c4
-rw-r--r--contrib/compiler-rt/lib/umodti3.c4
-rw-r--r--contrib/gcc/longlong.h12
-rw-r--r--contrib/llvm/include/llvm/MC/MCAsmInfo.h2
-rw-r--r--contrib/llvm/include/llvm/Object/ELFObjectFile.h12
-rw-r--r--contrib/llvm/include/llvm/Support/ELF.h88
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp14
-rw-r--r--contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp17
-rw-r--r--contrib/llvm/lib/MC/MCObjectFileInfo.cpp27
-rw-r--r--contrib/llvm/lib/Object/ELF.cpp92
-rw-r--r--contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp2
-rw-r--r--contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp828
-rw-r--r--contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp49
-rw-r--r--contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp228
-rw-r--r--contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp129
-rw-r--r--contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h48
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp251
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h82
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp139
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h93
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp25
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h19
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp176
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp254
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h111
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp116
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h22
-rw-r--r--contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp40
-rw-r--r--contrib/llvm/lib/Target/Sparc/Sparc.h6
-rw-r--r--contrib/llvm/lib/Target/Sparc/Sparc.td20
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp408
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcCallingConv.td11
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcCodeEmitter.cpp35
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp616
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcISelLowering.h14
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td277
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td142
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td44
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp5
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td630
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcJITInfo.cpp229
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp109
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp2
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcRelocations.h17
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp16
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcSubtarget.h2
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.cpp48
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.h34
-rw-r--r--contrib/llvm/lib/Target/Sparc/SparcTargetStreamer.h47
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/Targets.cpp23
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp46
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp28
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/Tools.cpp53
-rw-r--r--lib/clang/Makefile6
-rw-r--r--lib/clang/clang.build.mk2
-rw-r--r--lib/clang/include/SparcGenAsmMatcher.inc2
-rw-r--r--lib/clang/include/SparcGenAsmWriter.inc2
-rw-r--r--lib/clang/include/SparcGenCallingConv.inc2
-rw-r--r--lib/clang/include/SparcGenCodeEmitter.inc2
-rw-r--r--lib/clang/include/SparcGenDAGISel.inc2
-rw-r--r--lib/clang/include/SparcGenDisassemblerTables.inc2
-rw-r--r--lib/clang/include/SparcGenInstrInfo.inc2
-rw-r--r--lib/clang/include/SparcGenMCCodeEmitter.inc2
-rw-r--r--lib/clang/include/SparcGenRegisterInfo.inc2
-rw-r--r--lib/clang/include/SparcGenSubtargetInfo.inc2
-rw-r--r--lib/clang/include/llvm/Config/AsmParsers.def1
-rw-r--r--lib/clang/include/llvm/Config/AsmPrinters.def1
-rw-r--r--lib/clang/include/llvm/Config/Disassemblers.def1
-rw-r--r--lib/clang/include/llvm/Config/Targets.def1
-rw-r--r--lib/clang/libllvmsparcasmparser/Makefile16
-rw-r--r--lib/clang/libllvmsparccodegen/Makefile34
-rw-r--r--lib/clang/libllvmsparcdesc/Makefile22
-rw-r--r--lib/clang/libllvmsparcdisassembler/Makefile16
-rw-r--r--lib/clang/libllvmsparcinfo/Makefile15
-rw-r--r--lib/clang/libllvmsparcinstprinter/Makefile16
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap_setup.c2
-rw-r--r--lib/msun/Makefile1
-rw-r--r--share/mk/bsd.sys.mk4
-rw-r--r--sys/boot/sparc64/boot1/Makefile4
-rw-r--r--sys/conf/kern.mk4
-rw-r--r--sys/dev/esp/esp_sbus.c2
-rw-r--r--sys/dev/fb/creator.c6
-rw-r--r--sys/dev/fb/machfb.c10
-rw-r--r--sys/dev/mk48txx/mk48txx.c2
-rw-r--r--sys/sparc64/conf/GENERIC2
-rw-r--r--sys/sparc64/isa/isa.c2
-rw-r--r--sys/sparc64/pci/firereg.h4
-rw-r--r--usr.bin/clang/clang/Makefile6
-rw-r--r--usr.bin/clang/llc/Makefile6
-rw-r--r--usr.bin/clang/llvm-mc/Makefile6
-rw-r--r--usr.bin/clang/llvm-objdump/Makefile6
-rw-r--r--usr.bin/clang/llvm-rtdyld/Makefile6
-rw-r--r--usr.bin/clang/opt/Makefile6
-rw-r--r--usr.sbin/eeprom/ofw_options.c2
128 files changed, 5146 insertions, 974 deletions
diff --git a/contrib/compiler-rt/lib/absvti2.c b/contrib/compiler-rt/lib/absvti2.c
index c1c7277..437bc3d 100644
--- a/contrib/compiler-rt/lib/absvti2.c
+++ b/contrib/compiler-rt/lib/absvti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: absolute value */
@@ -30,4 +30,5 @@ __absvti2(ti_int a)
return (a ^ s) - s;
}
-#endif
+#endif /* CRT_HAS_128BIT */
+
diff --git a/contrib/compiler-rt/lib/addvti3.c b/contrib/compiler-rt/lib/addvti3.c
index 2efcf3b..f2a5c56 100644
--- a/contrib/compiler-rt/lib/addvti3.c
+++ b/contrib/compiler-rt/lib/addvti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: a + b */
@@ -37,4 +37,4 @@ __addvti3(ti_int a, ti_int b)
return s;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/ashlti3.c b/contrib/compiler-rt/lib/ashlti3.c
index 4bd8219..08d2181d4 100644
--- a/contrib/compiler-rt/lib/ashlti3.c
+++ b/contrib/compiler-rt/lib/ashlti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: a << b */
@@ -42,4 +42,4 @@ __ashlti3(ti_int a, si_int b)
return result.all;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/ashrti3.c b/contrib/compiler-rt/lib/ashrti3.c
index ed43641..6161bd5 100644
--- a/contrib/compiler-rt/lib/ashrti3.c
+++ b/contrib/compiler-rt/lib/ashrti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: arithmetic a >> b */
@@ -43,4 +43,4 @@ __ashrti3(ti_int a, si_int b)
return result.all;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/clzti2.c b/contrib/compiler-rt/lib/clzti2.c
index 355c20e..d478db8 100644
--- a/contrib/compiler-rt/lib/clzti2.c
+++ b/contrib/compiler-rt/lib/clzti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: the number of leading 0-bits */
@@ -30,4 +30,4 @@ __clzti2(ti_int a)
((si_int)f & ((si_int)(sizeof(di_int) * CHAR_BIT)));
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/cmpti2.c b/contrib/compiler-rt/lib/cmpti2.c
index d0aec45..d287fab 100644
--- a/contrib/compiler-rt/lib/cmpti2.c
+++ b/contrib/compiler-rt/lib/cmpti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: if (a < b) returns 0
* if (a == b) returns 1
@@ -39,4 +39,4 @@ __cmpti2(ti_int a, ti_int b)
return 1;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/ctzti2.c b/contrib/compiler-rt/lib/ctzti2.c
index 66dc01b..43a8797 100644
--- a/contrib/compiler-rt/lib/ctzti2.c
+++ b/contrib/compiler-rt/lib/ctzti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: the number of trailing 0-bits */
@@ -30,4 +30,4 @@ __ctzti2(ti_int a)
((si_int)f & ((si_int)(sizeof(di_int) * CHAR_BIT)));
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/divti3.c b/contrib/compiler-rt/lib/divti3.c
index 0242c13..ad365ab 100644
--- a/contrib/compiler-rt/lib/divti3.c
+++ b/contrib/compiler-rt/lib/divti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem);
@@ -32,4 +32,4 @@ __divti3(ti_int a, ti_int b)
return (__udivmodti4(a, b, (tu_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/ffsti2.c b/contrib/compiler-rt/lib/ffsti2.c
index 27e15d5..e64266d 100644
--- a/contrib/compiler-rt/lib/ffsti2.c
+++ b/contrib/compiler-rt/lib/ffsti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: the index of the least significant 1-bit in a, or
* the value zero if a is zero. The least significant bit is index one.
@@ -34,4 +34,4 @@ __ffsti2(ti_int a)
return __builtin_ctzll(x.s.low) + 1;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/fixdfti.c b/contrib/compiler-rt/lib/fixdfti.c
index b110a94..3b9ddb2 100644
--- a/contrib/compiler-rt/lib/fixdfti.c
+++ b/contrib/compiler-rt/lib/fixdfti.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a signed long long, rounding toward zero. */
@@ -42,4 +42,4 @@ __fixdfti(double a)
return (r ^ s) - s;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/fixsfti.c b/contrib/compiler-rt/lib/fixsfti.c
index c730ae0..31c2702 100644
--- a/contrib/compiler-rt/lib/fixsfti.c
+++ b/contrib/compiler-rt/lib/fixsfti.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a signed long long, rounding toward zero. */
@@ -42,4 +42,4 @@ __fixsfti(float a)
return (r ^ s) - s;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/fixunsdfti.c b/contrib/compiler-rt/lib/fixunsdfti.c
index fb0336f..76c8592 100644
--- a/contrib/compiler-rt/lib/fixunsdfti.c
+++ b/contrib/compiler-rt/lib/fixunsdfti.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a unsigned long long, rounding toward zero.
* Negative values all become zero.
@@ -44,4 +44,4 @@ __fixunsdfti(double a)
return r;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/fixunssfti.c b/contrib/compiler-rt/lib/fixunssfti.c
index 8f4c626..2bb18af 100644
--- a/contrib/compiler-rt/lib/fixunssfti.c
+++ b/contrib/compiler-rt/lib/fixunssfti.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a unsigned long long, rounding toward zero.
* Negative values all become zero.
@@ -44,4 +44,4 @@ __fixunssfti(float a)
return r;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/fixunsxfti.c b/contrib/compiler-rt/lib/fixunsxfti.c
index 260bfc0..db3c070 100644
--- a/contrib/compiler-rt/lib/fixunsxfti.c
+++ b/contrib/compiler-rt/lib/fixunsxfti.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a unsigned long long, rounding toward zero.
* Negative values all become zero.
@@ -46,4 +46,4 @@ __fixunsxfti(long double a)
return r;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/fixxfti.c b/contrib/compiler-rt/lib/fixxfti.c
index 973dc31..ca3082e 100644
--- a/contrib/compiler-rt/lib/fixxfti.c
+++ b/contrib/compiler-rt/lib/fixxfti.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a signed long long, rounding toward zero. */
@@ -44,4 +44,4 @@ __fixxfti(long double a)
return (r ^ s) - s;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/floattidf.c b/contrib/compiler-rt/lib/floattidf.c
index 77749f8..042c203 100644
--- a/contrib/compiler-rt/lib/floattidf.c
+++ b/contrib/compiler-rt/lib/floattidf.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a double, rounding toward even.*/
@@ -82,4 +82,4 @@ __floattidf(ti_int a)
return fb.f;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/floattisf.c b/contrib/compiler-rt/lib/floattisf.c
index 4776125..cb4e29a 100644
--- a/contrib/compiler-rt/lib/floattisf.c
+++ b/contrib/compiler-rt/lib/floattisf.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a float, rounding toward even. */
@@ -81,4 +81,4 @@ __floattisf(ti_int a)
return fb.f;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/floattixf.c b/contrib/compiler-rt/lib/floattixf.c
index 3813dc6..866051e 100644
--- a/contrib/compiler-rt/lib/floattixf.c
+++ b/contrib/compiler-rt/lib/floattixf.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a long double, rounding toward even. */
@@ -47,7 +47,7 @@ __floattixf(ti_int a)
* P = bit LDBL_MANT_DIG-1 bits to the right of 1
* Q = bit LDBL_MANT_DIG bits to the right of 1
* R = "or" of all bits to the right of Q
- */
+ */
switch (sd)
{
case LDBL_MANT_DIG + 1:
@@ -83,4 +83,4 @@ __floattixf(ti_int a)
return fb.f;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/floatuntidf.c b/contrib/compiler-rt/lib/floatuntidf.c
index 4c1d328..e7d6416 100644
--- a/contrib/compiler-rt/lib/floatuntidf.c
+++ b/contrib/compiler-rt/lib/floatuntidf.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a double, rounding toward even. */
@@ -43,7 +43,7 @@ __floatuntidf(tu_int a)
* P = bit DBL_MANT_DIG-1 bits to the right of 1
* Q = bit DBL_MANT_DIG bits to the right of 1
* R = "or" of all bits to the right of Q
- */
+ */
switch (sd)
{
case DBL_MANT_DIG + 1:
@@ -79,4 +79,4 @@ __floatuntidf(tu_int a)
return fb.f;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/floatuntisf.c b/contrib/compiler-rt/lib/floatuntisf.c
index c8da260..e65db57 100644
--- a/contrib/compiler-rt/lib/floatuntisf.c
+++ b/contrib/compiler-rt/lib/floatuntisf.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a float, rounding toward even. */
@@ -78,4 +78,4 @@ __floatuntisf(tu_int a)
return fb.f;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/floatuntixf.c b/contrib/compiler-rt/lib/floatuntixf.c
index dbce80f..d607cc3 100644
--- a/contrib/compiler-rt/lib/floatuntixf.c
+++ b/contrib/compiler-rt/lib/floatuntixf.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: convert a to a long double, rounding toward even. */
diff --git a/contrib/compiler-rt/lib/int_types.h b/contrib/compiler-rt/lib/int_types.h
index fcce390..5107f71 100644
--- a/contrib/compiler-rt/lib/int_types.h
+++ b/contrib/compiler-rt/lib/int_types.h
@@ -56,8 +56,11 @@ typedef union
}s;
} udwords;
-#if __x86_64
+#if __LP64__
+#define CRT_HAS_128BIT
+#endif
+#ifdef CRT_HAS_128BIT
typedef int ti_int __attribute__ ((mode (TI)));
typedef unsigned tu_int __attribute__ ((mode (TI)));
@@ -105,7 +108,7 @@ static inline tu_int make_tu(du_int h, du_int l) {
return r.all;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
typedef union
{
diff --git a/contrib/compiler-rt/lib/lshrti3.c b/contrib/compiler-rt/lib/lshrti3.c
index be76814..6fc4e1f 100644
--- a/contrib/compiler-rt/lib/lshrti3.c
+++ b/contrib/compiler-rt/lib/lshrti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: logical a >> b */
@@ -42,4 +42,4 @@ __lshrti3(ti_int a, si_int b)
return result.all;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/modti3.c b/contrib/compiler-rt/lib/modti3.c
index 752202d..ded24a0 100644
--- a/contrib/compiler-rt/lib/modti3.c
+++ b/contrib/compiler-rt/lib/modti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem);
@@ -33,4 +33,4 @@ __modti3(ti_int a, ti_int b)
return (r ^ s) - s; /* negate if s == -1 */
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/muloti4.c b/contrib/compiler-rt/lib/muloti4.c
index f58dd07..0aa6f3b 100644
--- a/contrib/compiler-rt/lib/muloti4.c
+++ b/contrib/compiler-rt/lib/muloti4.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: a * b */
@@ -59,4 +59,4 @@ __muloti4(ti_int a, ti_int b, int* overflow)
return result;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/multi3.c b/contrib/compiler-rt/lib/multi3.c
index 0b8730f..85a6cf4 100644
--- a/contrib/compiler-rt/lib/multi3.c
+++ b/contrib/compiler-rt/lib/multi3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: a * b */
@@ -55,4 +55,4 @@ __multi3(ti_int a, ti_int b)
return r.all;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/mulvti3.c b/contrib/compiler-rt/lib/mulvti3.c
index 31f7d2f..11d239a 100644
--- a/contrib/compiler-rt/lib/mulvti3.c
+++ b/contrib/compiler-rt/lib/mulvti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: a * b */
@@ -57,4 +57,4 @@ __mulvti3(ti_int a, ti_int b)
return a * b;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/negti2.c b/contrib/compiler-rt/lib/negti2.c
index f7e4ad3..28ef941 100644
--- a/contrib/compiler-rt/lib/negti2.c
+++ b/contrib/compiler-rt/lib/negti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: -a */
@@ -27,4 +27,4 @@ __negti2(ti_int a)
return -a;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/negvti2.c b/contrib/compiler-rt/lib/negvti2.c
index 05df615..d15167f 100644
--- a/contrib/compiler-rt/lib/negvti2.c
+++ b/contrib/compiler-rt/lib/negvti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: -a */
@@ -29,4 +29,4 @@ __negvti2(ti_int a)
return -a;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/parityti2.c b/contrib/compiler-rt/lib/parityti2.c
index a1f47b1..fa28380 100644
--- a/contrib/compiler-rt/lib/parityti2.c
+++ b/contrib/compiler-rt/lib/parityti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: 1 if number of bits is odd else returns 0 */
@@ -28,4 +28,4 @@ __parityti2(ti_int a)
return __paritydi2(x.s.high ^ x.s.low);
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/popcountti2.c b/contrib/compiler-rt/lib/popcountti2.c
index 9566673..d7223d9 100644
--- a/contrib/compiler-rt/lib/popcountti2.c
+++ b/contrib/compiler-rt/lib/popcountti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: count of 1 bits */
@@ -41,4 +41,4 @@ __popcountti2(ti_int a)
return (x + (x >> 8)) & 0xFF; /* (8 significant bits) */
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/subvti3.c b/contrib/compiler-rt/lib/subvti3.c
index b32df5e..20a0814 100644
--- a/contrib/compiler-rt/lib/subvti3.c
+++ b/contrib/compiler-rt/lib/subvti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: a - b */
@@ -37,4 +37,4 @@ __subvti3(ti_int a, ti_int b)
return s;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/ucmpti2.c b/contrib/compiler-rt/lib/ucmpti2.c
index 5466d21..95d1ff8 100644
--- a/contrib/compiler-rt/lib/ucmpti2.c
+++ b/contrib/compiler-rt/lib/ucmpti2.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Returns: if (a < b) returns 0
* if (a == b) returns 1
@@ -39,4 +39,4 @@ __ucmpti2(tu_int a, tu_int b)
return 1;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/udivmodti4.c b/contrib/compiler-rt/lib/udivmodti4.c
index f619c74..d8cea2a 100644
--- a/contrib/compiler-rt/lib/udivmodti4.c
+++ b/contrib/compiler-rt/lib/udivmodti4.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
/* Effects: if rem != 0, *rem = a % b
* Returns: a / b
@@ -253,4 +253,4 @@ __udivmodti4(tu_int a, tu_int b, tu_int* rem)
return q.all;
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/udivti3.c b/contrib/compiler-rt/lib/udivti3.c
index d9e1bb4..4a942b8 100644
--- a/contrib/compiler-rt/lib/udivti3.c
+++ b/contrib/compiler-rt/lib/udivti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem);
@@ -26,4 +26,4 @@ __udivti3(tu_int a, tu_int b)
return __udivmodti4(a, b, 0);
}
-#endif /* __x86_64 */
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/compiler-rt/lib/umodti3.c b/contrib/compiler-rt/lib/umodti3.c
index 8ebe7f0..2ab4dd2 100644
--- a/contrib/compiler-rt/lib/umodti3.c
+++ b/contrib/compiler-rt/lib/umodti3.c
@@ -14,7 +14,7 @@
#include "int_lib.h"
-#if __x86_64
+#ifdef CRT_HAS_128BIT
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem);
@@ -28,4 +28,4 @@ __umodti3(tu_int a, tu_int b)
return r;
}
-#endif
+#endif /* CRT_HAS_128BIT */
diff --git a/contrib/gcc/longlong.h b/contrib/gcc/longlong.h
index f91eb52..304ee8d 100644
--- a/contrib/gcc/longlong.h
+++ b/contrib/gcc/longlong.h
@@ -1086,8 +1086,8 @@ UDItype __umulsidi3 (USItype, USItype);
"bcs,a,pn %%xcc, 1f\n\t" \
"add %0, 1, %0\n" \
"1:" \
- : "=r" ((UDItype)(sh)), \
- "=&r" ((UDItype)(sl)) \
+ : "=r" (sh), \
+ "=&r" (sl) \
: "%rJ" ((UDItype)(ah)), \
"rI" ((UDItype)(bh)), \
"%rJ" ((UDItype)(al)), \
@@ -1100,8 +1100,8 @@ UDItype __umulsidi3 (USItype, USItype);
"bcs,a,pn %%xcc, 1f\n\t" \
"sub %0, 1, %0\n\t" \
"1:" \
- : "=r" ((UDItype)(sh)), \
- "=&r" ((UDItype)(sl)) \
+ : "=r" (sh), \
+ "=&r" (sl) \
: "rJ" ((UDItype)(ah)), \
"rI" ((UDItype)(bh)), \
"rJ" ((UDItype)(al)), \
@@ -1133,8 +1133,8 @@ UDItype __umulsidi3 (USItype, USItype);
"sllx %3,32,%3\n\t" \
"add %1,%3,%1\n\t" \
"add %5,%2,%0" \
- : "=r" ((UDItype)(wh)), \
- "=&r" ((UDItype)(wl)), \
+ : "=r" (wh), \
+ "=&r" (wl), \
"=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
: "r" ((UDItype)(u)), \
"r" ((UDItype)(v)) \
diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h
index 7a99394..aba8bcb 100644
--- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/contrib/llvm/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;
diff --git a/contrib/llvm/include/llvm/Object/ELFObjectFile.h b/contrib/llvm/include/llvm/Object/ELFObjectFile.h
index 962a3e2..075ca5a 100644
--- a/contrib/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/contrib/llvm/include/llvm/Object/ELFObjectFile.h
@@ -922,6 +922,9 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const {
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() const {
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;
}
diff --git a/contrib/llvm/include/llvm/Support/ELF.h b/contrib/llvm/include/llvm/Support/ELF.h
index 2868f35..70ad606 100644
--- a/contrib/llvm/include/llvm/Support/ELF.h
+++ b/contrib/llvm/include/llvm/Support/ELF.h
@@ -1087,6 +1087,94 @@ 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,
+ R_SPARC_TLS_GD_HI22 = 56,
+ R_SPARC_TLS_GD_LO10 = 57,
+ R_SPARC_TLS_GD_ADD = 58,
+ R_SPARC_TLS_GD_CALL = 59,
+ R_SPARC_TLS_LDM_HI22 = 60,
+ R_SPARC_TLS_LDM_LO10 = 61,
+ R_SPARC_TLS_LDM_ADD = 62,
+ R_SPARC_TLS_LDM_CALL = 63,
+ R_SPARC_TLS_LDO_HIX22 = 64,
+ R_SPARC_TLS_LDO_LOX10 = 65,
+ R_SPARC_TLS_LDO_ADD = 66,
+ R_SPARC_TLS_IE_HI22 = 67,
+ R_SPARC_TLS_IE_LO10 = 68,
+ R_SPARC_TLS_IE_LD = 69,
+ R_SPARC_TLS_IE_LDX = 70,
+ R_SPARC_TLS_IE_ADD = 71,
+ R_SPARC_TLS_LE_HIX22 = 72,
+ R_SPARC_TLS_LE_LOX10 = 73,
+ R_SPARC_TLS_DTPMOD32 = 74,
+ R_SPARC_TLS_DTPMOD64 = 75,
+ R_SPARC_TLS_DTPOFF32 = 76,
+ R_SPARC_TLS_DTPOFF64 = 77,
+ R_SPARC_TLS_TPOFF32 = 78,
+ R_SPARC_TLS_TPOFF64 = 79,
+ R_SPARC_GOTDATA_HIX22 = 80,
+ R_SPARC_GOTDATA_LOX22 = 81,
+ R_SPARC_GOTDATA_OP_HIX22 = 82,
+ R_SPARC_GOTDATA_OP_LOX22 = 83,
+ R_SPARC_GOTDATA_OP = 84
+};
+
// Section header.
struct Elf32_Shdr {
Elf32_Word sh_name; // Section name (index into string table)
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 308b0e0..d5c6713 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/contrib/llvm/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 MachineBasicBlock *MBB) const {
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;
}
}
diff --git a/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
index 3a8fb85..856ef34 100644
--- a/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
+++ b/contrib/llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
@@ -220,10 +220,19 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node,
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);
diff --git a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
index 8ef4a0a..799e061 100644
--- a/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/contrib/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -310,6 +310,33 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
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.
diff --git a/contrib/llvm/lib/Object/ELF.cpp b/contrib/llvm/lib/Object/ELF.cpp
index 7c80d41..6ef8d32 100644
--- a/contrib/llvm/lib/Object/ELF.cpp
+++ b/contrib/llvm/lib/Object/ELF.cpp
@@ -702,6 +702,98 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) {
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;
}
diff --git a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp b/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 76a0a83..f3be818 100644
--- a/contrib/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/contrib/llvm/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);
}
diff --git a/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
new file mode 100644
index 0000000..e7addd7
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -0,0 +1,828 @@
+//===-- SparcAsmParser.cpp - Parse Sparc assembly to MCInst instructions --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SparcMCTargetDesc.h"
+#include "MCTargetDesc/SparcMCExpr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+// The generated AsmMatcher SparcGenAsmMatcher uses "Sparc" as the target
+// namespace. But SPARC backend uses "SP" as its namespace.
+namespace llvm {
+ namespace Sparc {
+ using namespace SP;
+ }
+}
+
+namespace {
+class SparcOperand;
+class SparcAsmParser : public MCTargetAsmParser {
+
+ MCSubtargetInfo &STI;
+ MCAsmParser &Parser;
+
+ /// @name Auto-generated Match Functions
+ /// {
+
+#define GET_ASSEMBLER_HEADER
+#include "SparcGenAsmMatcher.inc"
+
+ /// }
+
+ // public interface of the MCTargetAsmParser.
+ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+ MCStreamer &Out, unsigned &ErrorInfo,
+ bool MatchingInlineAsm);
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
+ bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+ SMLoc NameLoc,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+ bool ParseDirective(AsmToken DirectiveID);
+
+ virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
+ unsigned Kind);
+
+ // Custom parse functions for Sparc specific operands.
+ OperandMatchResultTy
+ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+
+ OperandMatchResultTy
+ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+ StringRef Name);
+
+ OperandMatchResultTy
+ parseSparcAsmOperand(SparcOperand *&Operand);
+
+ // returns true if Tok is matched to a register and returns register in RegNo.
+ bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
+ unsigned &RegKind);
+
+ bool matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc);
+
+public:
+ SparcAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
+ const MCInstrInfo &MII)
+ : MCTargetAsmParser(), STI(sti), Parser(parser) {
+ // Initialize the set of available features.
+ setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+ }
+
+};
+
+ static unsigned IntRegs[32] = {
+ Sparc::G0, Sparc::G1, Sparc::G2, Sparc::G3,
+ Sparc::G4, Sparc::G5, Sparc::G6, Sparc::G7,
+ Sparc::O0, Sparc::O1, Sparc::O2, Sparc::O3,
+ Sparc::O4, Sparc::O5, Sparc::O6, Sparc::O7,
+ Sparc::L0, Sparc::L1, Sparc::L2, Sparc::L3,
+ Sparc::L4, Sparc::L5, Sparc::L6, Sparc::L7,
+ Sparc::I0, Sparc::I1, Sparc::I2, Sparc::I3,
+ Sparc::I4, Sparc::I5, Sparc::I6, Sparc::I7 };
+
+ static unsigned FloatRegs[32] = {
+ Sparc::F0, Sparc::F1, Sparc::F2, Sparc::F3,
+ Sparc::F4, Sparc::F5, Sparc::F6, Sparc::F7,
+ Sparc::F8, Sparc::F9, Sparc::F10, Sparc::F11,
+ Sparc::F12, Sparc::F13, Sparc::F14, Sparc::F15,
+ Sparc::F16, Sparc::F17, Sparc::F18, Sparc::F19,
+ Sparc::F20, Sparc::F21, Sparc::F22, Sparc::F23,
+ Sparc::F24, Sparc::F25, Sparc::F26, Sparc::F27,
+ Sparc::F28, Sparc::F29, Sparc::F30, Sparc::F31 };
+
+ static unsigned DoubleRegs[32] = {
+ Sparc::D0, Sparc::D1, Sparc::D2, Sparc::D3,
+ Sparc::D4, Sparc::D5, Sparc::D6, Sparc::D7,
+ Sparc::D8, Sparc::D7, Sparc::D8, Sparc::D9,
+ Sparc::D12, Sparc::D13, Sparc::D14, Sparc::D15,
+ Sparc::D16, Sparc::D17, Sparc::D18, Sparc::D19,
+ Sparc::D20, Sparc::D21, Sparc::D22, Sparc::D23,
+ Sparc::D24, Sparc::D25, Sparc::D26, Sparc::D27,
+ Sparc::D28, Sparc::D29, Sparc::D30, Sparc::D31 };
+
+ static unsigned QuadFPRegs[32] = {
+ Sparc::Q0, Sparc::Q1, Sparc::Q2, Sparc::Q3,
+ Sparc::Q4, Sparc::Q5, Sparc::Q6, Sparc::Q7,
+ Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11,
+ Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 };
+
+
+/// SparcOperand - Instances of this class represent a parsed Sparc machine
+/// instruction.
+class SparcOperand : public MCParsedAsmOperand {
+public:
+ enum RegisterKind {
+ rk_None,
+ rk_IntReg,
+ rk_FloatReg,
+ rk_DoubleReg,
+ rk_QuadReg,
+ rk_CCReg,
+ rk_Y
+ };
+private:
+ enum KindTy {
+ k_Token,
+ k_Register,
+ k_Immediate,
+ k_MemoryReg,
+ k_MemoryImm
+ } Kind;
+
+ SMLoc StartLoc, EndLoc;
+
+ SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+
+ struct Token {
+ const char *Data;
+ unsigned Length;
+ };
+
+ struct RegOp {
+ unsigned RegNum;
+ RegisterKind Kind;
+ };
+
+ struct ImmOp {
+ const MCExpr *Val;
+ };
+
+ struct MemOp {
+ unsigned Base;
+ unsigned OffsetReg;
+ const MCExpr *Off;
+ };
+
+ union {
+ struct Token Tok;
+ struct RegOp Reg;
+ struct ImmOp Imm;
+ struct MemOp Mem;
+ };
+public:
+ bool isToken() const { return Kind == k_Token; }
+ bool isReg() const { return Kind == k_Register; }
+ bool isImm() const { return Kind == k_Immediate; }
+ bool isMem() const { return isMEMrr() || isMEMri(); }
+ bool isMEMrr() const { return Kind == k_MemoryReg; }
+ bool isMEMri() const { return Kind == k_MemoryImm; }
+
+ bool isFloatReg() const {
+ return (Kind == k_Register && Reg.Kind == rk_FloatReg);
+ }
+
+ bool isFloatOrDoubleReg() const {
+ return (Kind == k_Register && (Reg.Kind == rk_FloatReg
+ || Reg.Kind == rk_DoubleReg));
+ }
+
+
+ StringRef getToken() const {
+ assert(Kind == k_Token && "Invalid access!");
+ return StringRef(Tok.Data, Tok.Length);
+ }
+
+ unsigned getReg() const {
+ assert((Kind == k_Register) && "Invalid access!");
+ return Reg.RegNum;
+ }
+
+ const MCExpr *getImm() const {
+ assert((Kind == k_Immediate) && "Invalid access!");
+ return Imm.Val;
+ }
+
+ unsigned getMemBase() const {
+ assert((Kind == k_MemoryReg || Kind == k_MemoryImm) && "Invalid access!");
+ return Mem.Base;
+ }
+
+ unsigned getMemOffsetReg() const {
+ assert((Kind == k_MemoryReg) && "Invalid access!");
+ return Mem.OffsetReg;
+ }
+
+ const MCExpr *getMemOff() const {
+ assert((Kind == k_MemoryImm) && "Invalid access!");
+ return Mem.Off;
+ }
+
+ /// getStartLoc - Get the location of the first token of this operand.
+ SMLoc getStartLoc() const {
+ return StartLoc;
+ }
+ /// getEndLoc - Get the location of the last token of this operand.
+ SMLoc getEndLoc() const {
+ return EndLoc;
+ }
+
+ virtual void print(raw_ostream &OS) const {
+ switch (Kind) {
+ case k_Token: OS << "Token: " << getToken() << "\n"; break;
+ case k_Register: OS << "Reg: #" << getReg() << "\n"; break;
+ case k_Immediate: OS << "Imm: " << getImm() << "\n"; break;
+ case k_MemoryReg: OS << "Mem: " << getMemBase() << "+"
+ << getMemOffsetReg() << "\n"; break;
+ case k_MemoryImm: assert(getMemOff() != 0);
+ OS << "Mem: " << getMemBase()
+ << "+" << *getMemOff()
+ << "\n"; break;
+ }
+ }
+
+ void addRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getReg()));
+ }
+
+ void addImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCExpr *Expr = getImm();
+ addExpr(Inst, Expr);
+ }
+
+ void addExpr(MCInst &Inst, const MCExpr *Expr) const{
+ // Add as immediate when possible. Null MCExpr = 0.
+ if (Expr == 0)
+ Inst.addOperand(MCOperand::CreateImm(0));
+ else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
+ Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
+ else
+ Inst.addOperand(MCOperand::CreateExpr(Expr));
+ }
+
+ void addMEMrrOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+
+ Inst.addOperand(MCOperand::CreateReg(getMemBase()));
+
+ assert(getMemOffsetReg() != 0 && "Invalid offset");
+ Inst.addOperand(MCOperand::CreateReg(getMemOffsetReg()));
+ }
+
+ void addMEMriOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 2 && "Invalid number of operands!");
+
+ Inst.addOperand(MCOperand::CreateReg(getMemBase()));
+
+ const MCExpr *Expr = getMemOff();
+ addExpr(Inst, Expr);
+ }
+
+ static SparcOperand *CreateToken(StringRef Str, SMLoc S) {
+ SparcOperand *Op = new SparcOperand(k_Token);
+ Op->Tok.Data = Str.data();
+ Op->Tok.Length = Str.size();
+ Op->StartLoc = S;
+ Op->EndLoc = S;
+ return Op;
+ }
+
+ static SparcOperand *CreateReg(unsigned RegNum,
+ unsigned Kind,
+ SMLoc S, SMLoc E) {
+ SparcOperand *Op = new SparcOperand(k_Register);
+ Op->Reg.RegNum = RegNum;
+ Op->Reg.Kind = (SparcOperand::RegisterKind)Kind;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static SparcOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
+ SparcOperand *Op = new SparcOperand(k_Immediate);
+ Op->Imm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static SparcOperand *MorphToDoubleReg(SparcOperand *Op) {
+ unsigned Reg = Op->getReg();
+ assert(Op->Reg.Kind == rk_FloatReg);
+ unsigned regIdx = Reg - Sparc::F0;
+ if (regIdx % 2 || regIdx > 31)
+ return 0;
+ Op->Reg.RegNum = DoubleRegs[regIdx / 2];
+ Op->Reg.Kind = rk_DoubleReg;
+ return Op;
+ }
+
+ static SparcOperand *MorphToQuadReg(SparcOperand *Op) {
+ unsigned Reg = Op->getReg();
+ unsigned regIdx = 0;
+ switch (Op->Reg.Kind) {
+ default: assert(0 && "Unexpected register kind!");
+ case rk_FloatReg:
+ regIdx = Reg - Sparc::F0;
+ if (regIdx % 4 || regIdx > 31)
+ return 0;
+ Reg = QuadFPRegs[regIdx / 4];
+ break;
+ case rk_DoubleReg:
+ regIdx = Reg - Sparc::D0;
+ if (regIdx % 2 || regIdx > 31)
+ return 0;
+ Reg = QuadFPRegs[regIdx / 2];
+ break;
+ }
+ Op->Reg.RegNum = Reg;
+ Op->Reg.Kind = rk_QuadReg;
+ return Op;
+ }
+
+ static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) {
+ unsigned offsetReg = Op->getReg();
+ Op->Kind = k_MemoryReg;
+ Op->Mem.Base = Base;
+ Op->Mem.OffsetReg = offsetReg;
+ Op->Mem.Off = 0;
+ return Op;
+ }
+
+ static SparcOperand *CreateMEMri(unsigned Base,
+ const MCExpr *Off,
+ SMLoc S, SMLoc E) {
+ SparcOperand *Op = new SparcOperand(k_MemoryImm);
+ Op->Mem.Base = Base;
+ Op->Mem.OffsetReg = 0;
+ Op->Mem.Off = Off;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) {
+ const MCExpr *Imm = Op->getImm();
+ Op->Kind = k_MemoryImm;
+ Op->Mem.Base = Base;
+ Op->Mem.OffsetReg = 0;
+ Op->Mem.Off = Imm;
+ return Op;
+ }
+};
+
+} // end namespace
+
+bool SparcAsmParser::
+MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+ MCStreamer &Out, unsigned &ErrorInfo,
+ bool MatchingInlineAsm) {
+ MCInst Inst;
+ SmallVector<MCInst, 8> Instructions;
+ unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
+ MatchingInlineAsm);
+ switch (MatchResult) {
+ default:
+ break;
+
+ case Match_Success: {
+ Inst.setLoc(IDLoc);
+ Out.EmitInstruction(Inst);
+ return false;
+ }
+
+ case Match_MissingFeature:
+ return Error(IDLoc,
+ "instruction requires a CPU feature not currently enabled");
+
+ case Match_InvalidOperand: {
+ SMLoc ErrorLoc = IDLoc;
+ if (ErrorInfo != ~0U) {
+ if (ErrorInfo >= Operands.size())
+ return Error(IDLoc, "too few operands for instruction");
+
+ ErrorLoc = ((SparcOperand*) Operands[ErrorInfo])->getStartLoc();
+ if (ErrorLoc == SMLoc())
+ ErrorLoc = IDLoc;
+ }
+
+ return Error(ErrorLoc, "invalid operand for instruction");
+ }
+ case Match_MnemonicFail:
+ return Error(IDLoc, "invalid instruction");
+ }
+ return true;
+}
+
+bool SparcAsmParser::
+ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc)
+{
+ const AsmToken &Tok = Parser.getTok();
+ StartLoc = Tok.getLoc();
+ EndLoc = Tok.getEndLoc();
+ RegNo = 0;
+ if (getLexer().getKind() != AsmToken::Percent)
+ return false;
+ Parser.Lex();
+ unsigned regKind = SparcOperand::rk_None;
+ if (matchRegisterName(Tok, RegNo, regKind)) {
+ Parser.Lex();
+ return false;
+ }
+
+ return Error(StartLoc, "invalid register name");
+}
+
+bool SparcAsmParser::
+ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+ SMLoc NameLoc,
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands)
+{
+ // Check if we have valid mnemonic.
+ if (!mnemonicIsValid(Name, 0)) {
+ Parser.eatToEndOfStatement();
+ return Error(NameLoc, "Unknown instruction");
+ }
+ // First operand in MCInst is instruction mnemonic.
+ Operands.push_back(SparcOperand::CreateToken(Name, NameLoc));
+
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ // Read the first operand.
+ if (parseOperand(Operands, Name) != MatchOperand_Success) {
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, "unexpected token");
+ }
+
+ while (getLexer().is(AsmToken::Comma)) {
+ Parser.Lex(); // Eat the comma.
+ // Parse and remember the operand.
+ if (parseOperand(Operands, Name) != MatchOperand_Success) {
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, "unexpected token");
+ }
+ }
+ }
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, "unexpected token");
+ }
+ Parser.Lex(); // Consume the EndOfStatement.
+ return false;
+}
+
+bool SparcAsmParser::
+ParseDirective(AsmToken DirectiveID)
+{
+ // Ignore all directives for now.
+ Parser.eatToEndOfStatement();
+ return false;
+}
+
+SparcAsmParser::OperandMatchResultTy SparcAsmParser::
+parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
+{
+
+ SMLoc S, E;
+ unsigned BaseReg = 0;
+
+ if (ParseRegister(BaseReg, S, E)) {
+ return MatchOperand_NoMatch;
+ }
+
+ switch (getLexer().getKind()) {
+ default: return MatchOperand_NoMatch;
+
+ case AsmToken::Comma:
+ case AsmToken::RBrac:
+ case AsmToken::EndOfStatement:
+ Operands.push_back(SparcOperand::CreateMEMri(BaseReg, 0, S, E));
+ return MatchOperand_Success;
+
+ case AsmToken:: Plus:
+ Parser.Lex(); // Eat the '+'
+ break;
+ case AsmToken::Minus:
+ break;
+ }
+
+ SparcOperand *Offset = 0;
+ OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset);
+ if (ResTy != MatchOperand_Success || !Offset)
+ return MatchOperand_NoMatch;
+
+ Offset = (Offset->isImm()
+ ? SparcOperand::MorphToMEMri(BaseReg, Offset)
+ : SparcOperand::MorphToMEMrr(BaseReg, Offset));
+
+ Operands.push_back(Offset);
+ return MatchOperand_Success;
+}
+
+SparcAsmParser::OperandMatchResultTy SparcAsmParser::
+parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+ StringRef Mnemonic)
+{
+
+ OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
+
+ // If there wasn't a custom match, try the generic matcher below. Otherwise,
+ // there was a match, but an error occurred, in which case, just return that
+ // the operand parsing failed.
+ if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
+ return ResTy;
+
+ if (getLexer().is(AsmToken::LBrac)) {
+ // Memory operand
+ Operands.push_back(SparcOperand::CreateToken("[",
+ Parser.getTok().getLoc()));
+ Parser.Lex(); // Eat the [
+
+ if (Mnemonic == "cas" || Mnemonic == "casx") {
+ SMLoc S = Parser.getTok().getLoc();
+ if (getLexer().getKind() != AsmToken::Percent)
+ return MatchOperand_NoMatch;
+ Parser.Lex(); // eat %
+
+ unsigned RegNo, RegKind;
+ if (!matchRegisterName(Parser.getTok(), RegNo, RegKind))
+ return MatchOperand_NoMatch;
+
+ Parser.Lex(); // Eat the identifier token.
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
+ Operands.push_back(SparcOperand::CreateReg(RegNo, RegKind, S, E));
+ ResTy = MatchOperand_Success;
+ } else {
+ ResTy = parseMEMOperand(Operands);
+ }
+
+ if (ResTy != MatchOperand_Success)
+ return ResTy;
+
+ if (!getLexer().is(AsmToken::RBrac))
+ return MatchOperand_ParseFail;
+
+ Operands.push_back(SparcOperand::CreateToken("]",
+ Parser.getTok().getLoc()));
+ Parser.Lex(); // Eat the ]
+ return MatchOperand_Success;
+ }
+
+ SparcOperand *Op = 0;
+ ResTy = parseSparcAsmOperand(Op);
+ if (ResTy != MatchOperand_Success || !Op)
+ return MatchOperand_ParseFail;
+
+ // Push the parsed operand into the list of operands
+ Operands.push_back(Op);
+
+ return MatchOperand_Success;
+}
+
+SparcAsmParser::OperandMatchResultTy
+SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op)
+{
+
+ SMLoc S = Parser.getTok().getLoc();
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ const MCExpr *EVal;
+
+ Op = 0;
+ switch (getLexer().getKind()) {
+ default: break;
+
+ case AsmToken::Percent:
+ Parser.Lex(); // Eat the '%'.
+ unsigned RegNo;
+ unsigned RegKind;
+ if (matchRegisterName(Parser.getTok(), RegNo, RegKind)) {
+ StringRef name = Parser.getTok().getString();
+ Parser.Lex(); // Eat the identifier token.
+ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ switch (RegNo) {
+ default:
+ Op = SparcOperand::CreateReg(RegNo, RegKind, S, E);
+ break;
+ case Sparc::Y:
+ Op = SparcOperand::CreateToken("%y", S);
+ break;
+
+ case Sparc::ICC:
+ if (name == "xcc")
+ Op = SparcOperand::CreateToken("%xcc", S);
+ else
+ Op = SparcOperand::CreateToken("%icc", S);
+ break;
+
+ case Sparc::FCC:
+ assert(name == "fcc0" && "Cannot handle %fcc other than %fcc0 yet");
+ Op = SparcOperand::CreateToken("%fcc0", S);
+ break;
+ }
+ break;
+ }
+ if (matchSparcAsmModifiers(EVal, E)) {
+ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ Op = SparcOperand::CreateImm(EVal, S, E);
+ }
+ break;
+
+ case AsmToken::Minus:
+ case AsmToken::Integer:
+ if (!getParser().parseExpression(EVal, E))
+ Op = SparcOperand::CreateImm(EVal, S, E);
+ break;
+
+ case AsmToken::Identifier: {
+ StringRef Identifier;
+ if (!getParser().parseIdentifier(Identifier)) {
+ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ MCSymbol *Sym = getContext().GetOrCreateSymbol(Identifier);
+
+ const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
+ getContext());
+ Op = SparcOperand::CreateImm(Res, S, E);
+ }
+ break;
+ }
+ }
+ return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
+}
+
+bool SparcAsmParser::matchRegisterName(const AsmToken &Tok,
+ unsigned &RegNo,
+ unsigned &RegKind)
+{
+ int64_t intVal = 0;
+ RegNo = 0;
+ RegKind = SparcOperand::rk_None;
+ if (Tok.is(AsmToken::Identifier)) {
+ StringRef name = Tok.getString();
+
+ // %fp
+ if (name.equals("fp")) {
+ RegNo = Sparc::I6;
+ RegKind = SparcOperand::rk_IntReg;
+ return true;
+ }
+ // %sp
+ if (name.equals("sp")) {
+ RegNo = Sparc::O6;
+ RegKind = SparcOperand::rk_IntReg;
+ return true;
+ }
+
+ if (name.equals("y")) {
+ RegNo = Sparc::Y;
+ RegKind = SparcOperand::rk_Y;
+ return true;
+ }
+
+ if (name.equals("icc")) {
+ RegNo = Sparc::ICC;
+ RegKind = SparcOperand::rk_CCReg;
+ return true;
+ }
+
+ if (name.equals("xcc")) {
+ // FIXME:: check 64bit.
+ RegNo = Sparc::ICC;
+ RegKind = SparcOperand::rk_CCReg;
+ return true;
+ }
+
+ // %fcc0 - %fcc3
+ if (name.substr(0, 3).equals_lower("fcc")
+ && !name.substr(3).getAsInteger(10, intVal)
+ && intVal < 4) {
+ // FIXME: check 64bit and handle %fcc1 - %fcc3
+ RegNo = Sparc::FCC;
+ RegKind = SparcOperand::rk_CCReg;
+ return true;
+ }
+
+ // %g0 - %g7
+ if (name.substr(0, 1).equals_lower("g")
+ && !name.substr(1).getAsInteger(10, intVal)
+ && intVal < 8) {
+ RegNo = IntRegs[intVal];
+ RegKind = SparcOperand::rk_IntReg;
+ return true;
+ }
+ // %o0 - %o7
+ if (name.substr(0, 1).equals_lower("o")
+ && !name.substr(1).getAsInteger(10, intVal)
+ && intVal < 8) {
+ RegNo = IntRegs[8 + intVal];
+ RegKind = SparcOperand::rk_IntReg;
+ return true;
+ }
+ if (name.substr(0, 1).equals_lower("l")
+ && !name.substr(1).getAsInteger(10, intVal)
+ && intVal < 8) {
+ RegNo = IntRegs[16 + intVal];
+ RegKind = SparcOperand::rk_IntReg;
+ return true;
+ }
+ if (name.substr(0, 1).equals_lower("i")
+ && !name.substr(1).getAsInteger(10, intVal)
+ && intVal < 8) {
+ RegNo = IntRegs[24 + intVal];
+ RegKind = SparcOperand::rk_IntReg;
+ return true;
+ }
+ // %f0 - %f31
+ if (name.substr(0, 1).equals_lower("f")
+ && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 32) {
+ RegNo = FloatRegs[intVal];
+ RegKind = SparcOperand::rk_FloatReg;
+ return true;
+ }
+ // %f32 - %f62
+ if (name.substr(0, 1).equals_lower("f")
+ && !name.substr(1, 2).getAsInteger(10, intVal)
+ && intVal >= 32 && intVal <= 62 && (intVal % 2 == 0)) {
+ // FIXME: Check V9
+ RegNo = DoubleRegs[intVal/2];
+ RegKind = SparcOperand::rk_DoubleReg;
+ return true;
+ }
+
+ // %r0 - %r31
+ if (name.substr(0, 1).equals_lower("r")
+ && !name.substr(1, 2).getAsInteger(10, intVal) && intVal < 31) {
+ RegNo = IntRegs[intVal];
+ RegKind = SparcOperand::rk_IntReg;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
+ SMLoc &EndLoc)
+{
+ AsmToken Tok = Parser.getTok();
+ if (!Tok.is(AsmToken::Identifier))
+ return false;
+
+ StringRef name = Tok.getString();
+
+ SparcMCExpr::VariantKind VK = SparcMCExpr::parseVariantKind(name);
+
+ if (VK == SparcMCExpr::VK_Sparc_None)
+ return false;
+
+ Parser.Lex(); // Eat the identifier.
+ if (Parser.getTok().getKind() != AsmToken::LParen)
+ return false;
+
+ Parser.Lex(); // Eat the LParen token.
+ const MCExpr *subExpr;
+ if (Parser.parseParenExpression(subExpr, EndLoc))
+ return false;
+ EVal = SparcMCExpr::Create(VK, subExpr, getContext());
+ return true;
+}
+
+
+extern "C" void LLVMInitializeSparcAsmParser() {
+ RegisterMCAsmParser<SparcAsmParser> A(TheSparcTarget);
+ RegisterMCAsmParser<SparcAsmParser> B(TheSparcV9Target);
+}
+
+#define GET_REGISTER_MATCHER
+#define GET_MATCHER_IMPLEMENTATION
+#include "SparcGenAsmMatcher.inc"
+
+
+
+unsigned SparcAsmParser::
+validateTargetOperandClass(MCParsedAsmOperand *GOp,
+ unsigned Kind)
+{
+ SparcOperand *Op = (SparcOperand*)GOp;
+ if (Op->isFloatOrDoubleReg()) {
+ switch (Kind) {
+ default: break;
+ case MCK_DFPRegs:
+ if (!Op->isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
+ return MCTargetAsmParser::Match_Success;
+ break;
+ case MCK_QFPRegs:
+ if (SparcOperand::MorphToQuadReg(Op))
+ return MCTargetAsmParser::Match_Success;
+ break;
+ }
+ }
+ return Match_InvalidOperand;
+}
diff --git a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
index 9a0466a..f23ddc2 100644
--- a/contrib/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
+++ b/contrib/llvm/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,15 +56,17 @@ 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);
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(MachineBasicBlock &MBB) {
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)) {
@@ -278,19 +285,19 @@ void Filler::insertCallDefsUses(MachineBasicBlock::iterator MI,
switch(MI->getOpcode()) {
default: llvm_unreachable("Unknown opcode.");
case SP::CALL: break;
- case SP::JMPLrr:
- case SP::JMPLri:
+ case SP::CALLrr:
+ case SP::CALLri:
assert(MI->getNumOperands() >= 2);
const MachineOperand &Reg = MI->getOperand(0);
- assert(Reg.isReg() && "JMPL first operand is not a register.");
- assert(Reg.isUse() && "JMPL first operand is not a use.");
+ assert(Reg.isReg() && "CALL first operand is not a register.");
+ assert(Reg.isUse() && "CALL first operand is not a use.");
RegUses.insert(Reg.getReg());
const MachineOperand &RegOrImm = MI->getOperand(1);
if (RegOrImm.isImm())
break;
- assert(RegOrImm.isReg() && "JMPLrr second operand is not a register.");
- assert(RegOrImm.isUse() && "JMPLrr second operand is not a use.");
+ assert(RegOrImm.isReg() && "CALLrr second operand is not a register.");
+ assert(RegOrImm.isUse() && "CALLrr second operand is not a use.");
RegUses.insert(RegOrImm.getReg());
break;
}
@@ -332,18 +339,6 @@ bool Filler::IsRegInSet(SmallSet<unsigned, 32>& RegSet, unsigned Reg)
return false;
}
-// return true if the candidate is a delay filler.
-bool Filler::isDelayFiller(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator candidate)
-{
- if (candidate == MBB.begin())
- return false;
- if (candidate->getOpcode() == SP::UNIMP)
- return true;
- --candidate;
- return candidate->hasDelaySlot();
-}
-
bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
{
if (!I->isCall())
@@ -353,8 +348,8 @@ bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
switch (I->getOpcode()) {
default: llvm_unreachable("Unknown call opcode.");
case SP::CALL: structSizeOpNum = 1; break;
- case SP::JMPLrr:
- case SP::JMPLri: structSizeOpNum = 2; break;
+ case SP::CALLrr:
+ case SP::CALLri: structSizeOpNum = 2; break;
case SP::TLS_CALL: return false;
}
@@ -484,10 +479,10 @@ bool Filler::tryCombineRestoreWithPrevInst(MachineBasicBlock &MBB,
&& 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();
diff --git a/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp b/contrib/llvm/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp
new file mode 100644
index 0000000..6233805
--- /dev/null
+++ b/contrib/llvm/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 &region,
+ uint64_t address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const;
+private:
+ OwningPtr<const MCRegisterInfo> RegInfo;
+};
+
+}
+
+namespace llvm {
+ extern Target TheSparcTarget, TheSparcV9Target;
+}
+
+static MCDisassembler *createSparcDisassembler(
+ const Target &T,
+ const MCSubtargetInfo &STI) {
+ return new SparcDisassembler(STI, T.createMCRegInfo(""));
+}
+
+
+extern "C" void LLVMInitializeSparcDisassembler() {
+ // Register the disassembler.
+ TargetRegistry::RegisterMCDisassembler(TheSparcTarget,
+ createSparcDisassembler);
+ TargetRegistry::RegisterMCDisassembler(TheSparcV9Target,
+ createSparcDisassembler);
+}
+
+
+
+static const unsigned IntRegDecoderTable[] = {
+ SP::G0, SP::G1, SP::G2, SP::G3,
+ SP::G4, SP::G5, SP::G6, SP::G7,
+ SP::O0, SP::O1, SP::O2, SP::O3,
+ SP::O4, SP::O5, SP::O6, SP::O7,
+ SP::L0, SP::L1, SP::L2, SP::L3,
+ SP::L4, SP::L5, SP::L6, SP::L7,
+ SP::I0, SP::I1, SP::I2, SP::I3,
+ SP::I4, SP::I5, SP::I6, SP::I7 };
+
+static const unsigned FPRegDecoderTable[] = {
+ SP::F0, SP::F1, SP::F2, SP::F3,
+ SP::F4, SP::F5, SP::F6, SP::F7,
+ SP::F8, SP::F9, SP::F10, SP::F11,
+ SP::F12, SP::F13, SP::F14, SP::F15,
+ SP::F16, SP::F17, SP::F18, SP::F19,
+ SP::F20, SP::F21, SP::F22, SP::F23,
+ SP::F24, SP::F25, SP::F26, SP::F27,
+ SP::F28, SP::F29, SP::F30, SP::F31 };
+
+static const unsigned DFPRegDecoderTable[] = {
+ SP::D0, SP::D16, SP::D1, SP::D17,
+ SP::D2, SP::D18, SP::D3, SP::D19,
+ SP::D4, SP::D20, SP::D5, SP::D21,
+ SP::D6, SP::D22, SP::D7, SP::D23,
+ SP::D8, SP::D24, SP::D9, SP::D25,
+ SP::D10, SP::D26, SP::D11, SP::D27,
+ SP::D12, SP::D28, SP::D13, SP::D29,
+ SP::D14, SP::D30, SP::D15, SP::D31 };
+
+static const unsigned QFPRegDecoderTable[] = {
+ SP::Q0, SP::Q8, ~0U, ~0U,
+ SP::Q1, SP::Q9, ~0U, ~0U,
+ SP::Q2, SP::Q10, ~0U, ~0U,
+ SP::Q3, SP::Q11, ~0U, ~0U,
+ SP::Q4, SP::Q12, ~0U, ~0U,
+ SP::Q5, SP::Q13, ~0U, ~0U,
+ SP::Q6, SP::Q14, ~0U, ~0U,
+ SP::Q7, SP::Q15, ~0U, ~0U } ;
+
+static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+ unsigned Reg = IntRegDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeI64RegsRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+ unsigned Reg = IntRegDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
+
+static DecodeStatus DecodeFPRegsRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+ unsigned Reg = FPRegDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
+
+static DecodeStatus DecodeDFPRegsRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+ unsigned Reg = DFPRegDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
+
+static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+
+ unsigned Reg = QFPRegDecoderTable[RegNo];
+ if (Reg == ~0U)
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
+
+#include "SparcGenDisassemblerTables.inc"
+
+/// readInstruction - read four bytes from the MemoryObject
+/// and return 32 bit word.
+static DecodeStatus readInstruction32(const MemoryObject &region,
+ uint64_t address,
+ uint64_t &size,
+ uint32_t &insn) {
+ uint8_t Bytes[4];
+
+ // We want to read exactly 4 Bytes of data.
+ if (region.readBytes(address, 4, Bytes) == -1) {
+ size = 0;
+ return MCDisassembler::Fail;
+ }
+
+ // Encoded as a big-endian 32-bit word in the stream.
+ insn = (Bytes[3] << 0) |
+ (Bytes[2] << 8) |
+ (Bytes[1] << 16) |
+ (Bytes[0] << 24);
+
+ return MCDisassembler::Success;
+}
+
+
+DecodeStatus
+SparcDisassembler::getInstruction(MCInst &instr,
+ uint64_t &Size,
+ const MemoryObject &Region,
+ uint64_t Address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const {
+ uint32_t Insn;
+
+ DecodeStatus Result = readInstruction32(Region, Address, Size, Insn);
+ if (Result == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+
+
+ // Calling the auto-generated decoder function.
+ Result = decodeInstruction(DecoderTableSparc32, instr, Insn, Address,
+ this, STI);
+
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ return Result;
+ }
+
+ return MCDisassembler::Fail;
+}
diff --git a/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp b/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
new file mode 100644
index 0000000..6d7457a
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.cpp
@@ -0,0 +1,129 @@
+//===-- 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 "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#define GET_INSTRUCTION_NAME
+#define PRINT_ALIAS_INSTR
+#include "SparcGenAsmWriter.inc"
+
+void SparcInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const
+{
+ OS << '%' << StringRef(getRegisterName(RegNo)).lower();
+}
+
+void SparcInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
+ StringRef Annot)
+{
+ if (!printAliasInstr(MI, O) && !printSparcAliasInstr(MI, O))
+ printInstruction(MI, O);
+ printAnnotation(O, Annot);
+}
+
+bool SparcInstPrinter::printSparcAliasInstr(const MCInst *MI, raw_ostream &O)
+{
+ switch (MI->getOpcode()) {
+ default: return false;
+ case SP::JMPLrr:
+ case SP::JMPLri: {
+ if (MI->getNumOperands() != 3)
+ return false;
+ if (!MI->getOperand(0).isReg())
+ return false;
+ switch (MI->getOperand(0).getReg()) {
+ default: return false;
+ case SP::G0: // jmp $addr
+ O << "\tjmp "; printMemOperand(MI, 1, O);
+ return true;
+ case SP::O7: // call $addr
+ O << "\tcall "; printMemOperand(MI, 1, O);
+ return true;
+ }
+ }
+ }
+}
+
+void SparcInstPrinter::printOperand(const MCInst *MI, int opNum,
+ raw_ostream &O)
+{
+ const MCOperand &MO = MI->getOperand (opNum);
+
+ if (MO.isReg()) {
+ printRegName(O, MO.getReg());
+ return ;
+ }
+
+ if (MO.isImm()) {
+ O << (int)MO.getImm();
+ return;
+ }
+
+ assert(MO.isExpr() && "Unknown operand kind in printOperand");
+ MO.getExpr()->print(O);
+}
+
+void SparcInstPrinter::printMemOperand(const MCInst *MI, int opNum,
+ raw_ostream &O, const char *Modifier)
+{
+ printOperand(MI, opNum, O);
+
+ // If this is an ADD operand, emit it like normal operands.
+ if (Modifier && !strcmp(Modifier, "arith")) {
+ O << ", ";
+ printOperand(MI, opNum+1, O);
+ return;
+ }
+ const MCOperand &MO = MI->getOperand(opNum+1);
+
+ if (MO.isReg() && MO.getReg() == SP::G0)
+ return; // don't print "+%g0"
+ if (MO.isImm() && MO.getImm() == 0)
+ return; // don't print "+0"
+
+ O << "+";
+
+ printOperand(MI, opNum+1, O);
+}
+
+void SparcInstPrinter::printCCOperand(const MCInst *MI, int opNum,
+ raw_ostream &O)
+{
+ int CC = (int)MI->getOperand(opNum).getImm();
+ switch (MI->getOpcode()) {
+ default: break;
+ case SP::FBCOND:
+ case SP::MOVFCCrr:
+ case SP::MOVFCCri:
+ case SP::FMOVS_FCC:
+ case SP::FMOVD_FCC:
+ case SP::FMOVQ_FCC: // Make sure CC is a fp conditional flag.
+ CC = (CC < 16) ? (CC + 16) : CC;
+ break;
+ }
+ O << SPARCCondCodeToString((SPCC::CondCodes)CC);
+}
+
+bool SparcInstPrinter::printGetPCX(const MCInst *MI, unsigned opNum,
+ raw_ostream &O)
+{
+ assert(0 && "FIXME: Implement SparcInstPrinter::printGetPCX.");
+ return true;
+}
diff --git a/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h b/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
new file mode 100644
index 0000000..63ed41a
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/InstPrinter/SparcInstPrinter.h
@@ -0,0 +1,48 @@
+//===-- SparcInstPrinter.h - Convert Sparc MCInst to assembly syntax ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class prints an Sparc MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SparcINSTPRINTER_H
+#define SparcINSTPRINTER_H
+
+#include "llvm/MC/MCInstPrinter.h"
+
+namespace llvm {
+
+class MCOperand;
+
+class SparcInstPrinter : public MCInstPrinter {
+public:
+ SparcInstPrinter(const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI)
+ : MCInstPrinter(MAI, MII, MRI) {}
+
+ virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
+ virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
+ bool printSparcAliasInstr(const MCInst *MI, raw_ostream &OS);
+
+ // Autogenerated by tblgen.
+ void printInstruction(const MCInst *MI, raw_ostream &O);
+ bool printAliasInstr(const MCInst *MI, raw_ostream &O);
+ static const char *getRegisterName(unsigned RegNo);
+
+ void printOperand(const MCInst *MI, int opNum, raw_ostream &OS);
+ void printMemOperand(const MCInst *MI, int opNum, raw_ostream &OS,
+ const char *Modifier = 0);
+ void printCCOperand(const MCInst *MI, int opNum, raw_ostream &OS);
+ bool printGetPCX(const MCInst *MI, unsigned OpNo, raw_ostream &OS);
+
+};
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
new file mode 100644
index 0000000..6d2dd83
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -0,0 +1,251 @@
+//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmBackend.h"
+#include "MCTargetDesc/SparcMCTargetDesc.h"
+#include "MCTargetDesc/SparcFixupKinds.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown fixup kind!");
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ case FK_Data_8:
+ return Value;
+
+ case Sparc::fixup_sparc_wplt30:
+ case Sparc::fixup_sparc_call30:
+ return (Value >> 2) & 0x3fffffff;
+
+ case Sparc::fixup_sparc_br22:
+ return (Value >> 2) & 0x3fffff;
+
+ case Sparc::fixup_sparc_br19:
+ return (Value >> 2) & 0x7ffff;
+
+ case Sparc::fixup_sparc_pc22:
+ case Sparc::fixup_sparc_got22:
+ case Sparc::fixup_sparc_tls_gd_hi22:
+ case Sparc::fixup_sparc_tls_ldm_hi22:
+ case Sparc::fixup_sparc_tls_ie_hi22:
+ case Sparc::fixup_sparc_hi22:
+ return (Value >> 10) & 0x3fffff;
+
+ case Sparc::fixup_sparc_pc10:
+ case Sparc::fixup_sparc_got10:
+ case Sparc::fixup_sparc_tls_gd_lo10:
+ case Sparc::fixup_sparc_tls_ldm_lo10:
+ case Sparc::fixup_sparc_tls_ie_lo10:
+ case Sparc::fixup_sparc_lo10:
+ return Value & 0x3ff;
+
+ case Sparc::fixup_sparc_tls_ldo_hix22:
+ case Sparc::fixup_sparc_tls_le_hix22:
+ return (~Value >> 10) & 0x3fffff;
+
+ case Sparc::fixup_sparc_tls_ldo_lox10:
+ case Sparc::fixup_sparc_tls_le_lox10:
+ return (~(~Value & 0x3ff)) & 0x1fff;
+
+ case Sparc::fixup_sparc_h44:
+ return (Value >> 22) & 0x3fffff;
+
+ case Sparc::fixup_sparc_m44:
+ return (Value >> 12) & 0x3ff;
+
+ case Sparc::fixup_sparc_l44:
+ return Value & 0xfff;
+
+ case Sparc::fixup_sparc_hh:
+ return (Value >> 42) & 0x3fffff;
+
+ case Sparc::fixup_sparc_hm:
+ return (Value >> 32) & 0x3ff;
+
+ case Sparc::fixup_sparc_tls_gd_add:
+ case Sparc::fixup_sparc_tls_gd_call:
+ case Sparc::fixup_sparc_tls_ldm_add:
+ case Sparc::fixup_sparc_tls_ldm_call:
+ case Sparc::fixup_sparc_tls_ldo_add:
+ case Sparc::fixup_sparc_tls_ie_ld:
+ case Sparc::fixup_sparc_tls_ie_ldx:
+ case Sparc::fixup_sparc_tls_ie_add:
+ return 0;
+ }
+}
+
+namespace {
+ class SparcAsmBackend : public MCAsmBackend {
+ const Target &TheTarget;
+ public:
+ SparcAsmBackend(const Target &T) : MCAsmBackend(), TheTarget(T) {}
+
+ unsigned getNumFixupKinds() const {
+ return Sparc::NumTargetFixupKinds;
+ }
+
+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
+ const static MCFixupKindInfo Infos[Sparc::NumTargetFixupKinds] = {
+ // name offset bits flags
+ { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_sparc_hi22", 10, 22, 0 },
+ { "fixup_sparc_lo10", 22, 10, 0 },
+ { "fixup_sparc_h44", 10, 22, 0 },
+ { "fixup_sparc_m44", 22, 10, 0 },
+ { "fixup_sparc_l44", 20, 12, 0 },
+ { "fixup_sparc_hh", 10, 22, 0 },
+ { "fixup_sparc_hm", 22, 10, 0 },
+ { "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_sparc_got22", 10, 22, 0 },
+ { "fixup_sparc_got10", 22, 10, 0 },
+ { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_sparc_tls_gd_hi22", 10, 22, 0 },
+ { "fixup_sparc_tls_gd_lo10", 22, 10, 0 },
+ { "fixup_sparc_tls_gd_add", 0, 0, 0 },
+ { "fixup_sparc_tls_gd_call", 0, 0, 0 },
+ { "fixup_sparc_tls_ldm_hi22", 10, 22, 0 },
+ { "fixup_sparc_tls_ldm_lo10", 22, 10, 0 },
+ { "fixup_sparc_tls_ldm_add", 0, 0, 0 },
+ { "fixup_sparc_tls_ldm_call", 0, 0, 0 },
+ { "fixup_sparc_tls_ldo_hix22", 10, 22, 0 },
+ { "fixup_sparc_tls_ldo_lox10", 22, 10, 0 },
+ { "fixup_sparc_tls_ldo_add", 0, 0, 0 },
+ { "fixup_sparc_tls_ie_hi22", 10, 22, 0 },
+ { "fixup_sparc_tls_ie_lo10", 22, 10, 0 },
+ { "fixup_sparc_tls_ie_ld", 0, 0, 0 },
+ { "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
+ { "fixup_sparc_tls_ie_add", 0, 0, 0 },
+ { "fixup_sparc_tls_le_hix22", 0, 0, 0 },
+ { "fixup_sparc_tls_le_lox10", 0, 0, 0 }
+ };
+
+ if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
+
+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+ "Invalid kind!");
+ return Infos[Kind - FirstTargetFixupKind];
+ }
+
+ void processFixupValue(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFixup &Fixup,
+ const MCFragment *DF,
+ MCValue & Target,
+ uint64_t &Value,
+ bool &IsResolved) {
+ switch ((Sparc::Fixups)Fixup.getKind()) {
+ default: break;
+ case Sparc::fixup_sparc_wplt30:
+ case Sparc::fixup_sparc_tls_gd_hi22:
+ case Sparc::fixup_sparc_tls_gd_lo10:
+ case Sparc::fixup_sparc_tls_gd_add:
+ case Sparc::fixup_sparc_tls_gd_call:
+ case Sparc::fixup_sparc_tls_ldm_hi22:
+ case Sparc::fixup_sparc_tls_ldm_lo10:
+ case Sparc::fixup_sparc_tls_ldm_add:
+ case Sparc::fixup_sparc_tls_ldm_call:
+ case Sparc::fixup_sparc_tls_ldo_hix22:
+ case Sparc::fixup_sparc_tls_ldo_lox10:
+ case Sparc::fixup_sparc_tls_ldo_add:
+ case Sparc::fixup_sparc_tls_ie_hi22:
+ case Sparc::fixup_sparc_tls_ie_lo10:
+ case Sparc::fixup_sparc_tls_ie_ld:
+ case Sparc::fixup_sparc_tls_ie_ldx:
+ case Sparc::fixup_sparc_tls_ie_add:
+ case Sparc::fixup_sparc_tls_le_hix22:
+ case Sparc::fixup_sparc_tls_le_lox10: IsResolved = false; break;
+ }
+ }
+
+ bool mayNeedRelaxation(const MCInst &Inst) const {
+ // FIXME.
+ return false;
+ }
+
+ /// fixupNeedsRelaxation - Target specific predicate for whether a given
+ /// fixup requires the associated instruction to be relaxed.
+ bool fixupNeedsRelaxation(const MCFixup &Fixup,
+ uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const {
+ // FIXME.
+ assert(0 && "fixupNeedsRelaxation() unimplemented");
+ return false;
+ }
+ void relaxInstruction(const MCInst &Inst, MCInst &Res) const {
+ // FIXME.
+ assert(0 && "relaxInstruction() unimplemented");
+ }
+
+ bool writeNopData(uint64_t Count, MCObjectWriter *OW) const {
+ // FIXME: Zero fill for now.
+ for (uint64_t i = 0; i != Count; ++i)
+ OW->Write8(0);
+ return true;
+ }
+
+ bool is64Bit() const {
+ StringRef name = TheTarget.getName();
+ return name == "sparcv9";
+ }
+ };
+
+ class ELFSparcAsmBackend : public SparcAsmBackend {
+ Triple::OSType OSType;
+ public:
+ ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
+ SparcAsmBackend(T), OSType(OSType) { }
+
+ void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
+ uint64_t Value) const {
+
+ Value = adjustFixupValue(Fixup.getKind(), Value);
+ if (!Value) return; // Doesn't change encoding.
+
+ unsigned Offset = Fixup.getOffset();
+
+ // For each byte of the fragment that the fixup touches, mask in the bits
+ // from the fixup value. The Value has been "split up" into the
+ // appropriate bitfields above.
+ for (unsigned i = 0; i != 4; ++i)
+ Data[Offset + i] |= uint8_t((Value >> ((4 - i - 1)*8)) & 0xff);
+
+ }
+
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
+ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
+ return createSparcELFObjectWriter(OS, is64Bit(), OSABI);
+ }
+
+ virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+ return false;
+ }
+ };
+
+} // end anonymous namespace
+
+
+MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
+ const MCRegisterInfo &MRI,
+ StringRef TT,
+ StringRef CPU) {
+ return new ELFSparcAsmBackend(T, Triple(TT).getOS());
+}
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h
deleted file mode 100644
index f3caeaa..0000000
--- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcBaseInfo.h
+++ /dev/null
@@ -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
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
new file mode 100644
index 0000000..3a9929b
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp
@@ -0,0 +1,139 @@
+//===-- SparcELFObjectWriter.cpp - Sparc ELF Writer -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SparcFixupKinds.h"
+#include "MCTargetDesc/SparcMCExpr.h"
+#include "MCTargetDesc/SparcMCTargetDesc.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+namespace {
+ class SparcELFObjectWriter : public MCELFObjectTargetWriter {
+ public:
+ SparcELFObjectWriter(bool Is64Bit, uint8_t OSABI)
+ : MCELFObjectTargetWriter(Is64Bit, OSABI,
+ Is64Bit ? ELF::EM_SPARCV9 : ELF::EM_SPARC,
+ /*HasRelocationAddend*/ true) {}
+
+ virtual ~SparcELFObjectWriter() {}
+ protected:
+ virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
+ bool IsPCRel, bool IsRelocWithSymbol,
+ int64_t Addend) const;
+
+ virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
+ const MCValue &Target,
+ const MCFragment &F,
+ const MCFixup &Fixup,
+ bool IsPCRel) const;
+ };
+}
+
+
+unsigned SparcELFObjectWriter::GetRelocType(const MCValue &Target,
+ const MCFixup &Fixup,
+ bool IsPCRel,
+ bool IsRelocWithSymbol,
+ int64_t Addend) const {
+
+ if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Fixup.getValue())) {
+ if (SExpr->getKind() == SparcMCExpr::VK_Sparc_R_DISP32)
+ return ELF::R_SPARC_DISP32;
+ }
+
+ if (IsPCRel) {
+ switch((unsigned)Fixup.getKind()) {
+ default:
+ llvm_unreachable("Unimplemented fixup -> relocation");
+ case FK_Data_1: return ELF::R_SPARC_DISP8;
+ case FK_Data_2: return ELF::R_SPARC_DISP16;
+ case FK_Data_4: return ELF::R_SPARC_DISP32;
+ case FK_Data_8: return ELF::R_SPARC_DISP64;
+ case Sparc::fixup_sparc_call30: return ELF::R_SPARC_WDISP30;
+ case Sparc::fixup_sparc_br22: return ELF::R_SPARC_WDISP22;
+ case Sparc::fixup_sparc_br19: return ELF::R_SPARC_WDISP19;
+ case Sparc::fixup_sparc_pc22: return ELF::R_SPARC_PC22;
+ case Sparc::fixup_sparc_pc10: return ELF::R_SPARC_PC10;
+ case Sparc::fixup_sparc_wplt30: return ELF::R_SPARC_WPLT30;
+ }
+ }
+
+ switch((unsigned)Fixup.getKind()) {
+ default:
+ llvm_unreachable("Unimplemented fixup -> relocation");
+ case FK_Data_1: return ELF::R_SPARC_8;
+ case FK_Data_2: return ((Fixup.getOffset() % 2)
+ ? ELF::R_SPARC_UA16
+ : ELF::R_SPARC_16);
+ case FK_Data_4: return ((Fixup.getOffset() % 4)
+ ? ELF::R_SPARC_UA32
+ : ELF::R_SPARC_32);
+ case FK_Data_8: return ((Fixup.getOffset() % 8)
+ ? ELF::R_SPARC_UA64
+ : ELF::R_SPARC_64);
+ case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22;
+ case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10;
+ case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44;
+ case Sparc::fixup_sparc_m44: return ELF::R_SPARC_M44;
+ case Sparc::fixup_sparc_l44: return ELF::R_SPARC_L44;
+ case Sparc::fixup_sparc_hh: return ELF::R_SPARC_HH22;
+ case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10;
+ case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22;
+ case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10;
+ case Sparc::fixup_sparc_tls_gd_hi22: return ELF::R_SPARC_TLS_GD_HI22;
+ case Sparc::fixup_sparc_tls_gd_lo10: return ELF::R_SPARC_TLS_GD_LO10;
+ case Sparc::fixup_sparc_tls_gd_add: return ELF::R_SPARC_TLS_GD_ADD;
+ case Sparc::fixup_sparc_tls_gd_call: return ELF::R_SPARC_TLS_GD_CALL;
+ case Sparc::fixup_sparc_tls_ldm_hi22: return ELF::R_SPARC_TLS_LDM_HI22;
+ case Sparc::fixup_sparc_tls_ldm_lo10: return ELF::R_SPARC_TLS_LDM_LO10;
+ case Sparc::fixup_sparc_tls_ldm_add: return ELF::R_SPARC_TLS_LDM_ADD;
+ case Sparc::fixup_sparc_tls_ldm_call: return ELF::R_SPARC_TLS_LDM_CALL;
+ case Sparc::fixup_sparc_tls_ldo_hix22: return ELF::R_SPARC_TLS_LDO_HIX22;
+ case Sparc::fixup_sparc_tls_ldo_lox10: return ELF::R_SPARC_TLS_LDO_LOX10;
+ case Sparc::fixup_sparc_tls_ldo_add: return ELF::R_SPARC_TLS_LDO_ADD;
+ case Sparc::fixup_sparc_tls_ie_hi22: return ELF::R_SPARC_TLS_IE_HI22;
+ case Sparc::fixup_sparc_tls_ie_lo10: return ELF::R_SPARC_TLS_IE_LO10;
+ case Sparc::fixup_sparc_tls_ie_ld: return ELF::R_SPARC_TLS_IE_LD;
+ case Sparc::fixup_sparc_tls_ie_ldx: return ELF::R_SPARC_TLS_IE_LDX;
+ case Sparc::fixup_sparc_tls_ie_add: return ELF::R_SPARC_TLS_IE_ADD;
+ case Sparc::fixup_sparc_tls_le_hix22: return ELF::R_SPARC_TLS_LE_HIX22;
+ case Sparc::fixup_sparc_tls_le_lox10: return ELF::R_SPARC_TLS_LE_LOX10;
+ }
+
+ return ELF::R_SPARC_NONE;
+}
+
+const MCSymbol *SparcELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
+ const MCValue &Target,
+ const MCFragment &F,
+ const MCFixup &Fixup,
+ bool IsPCRel) const {
+
+ if (!Target.getSymA())
+ return NULL;
+ switch((unsigned)Fixup.getKind()) {
+ default: break;
+ case Sparc::fixup_sparc_got22:
+ case Sparc::fixup_sparc_got10:
+ return &Target.getSymA()->getSymbol().AliasedSymbol();
+ }
+ return NULL;
+}
+
+MCObjectWriter *llvm::createSparcELFObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ uint8_t OSABI) {
+ MCELFObjectTargetWriter *MOTW = new SparcELFObjectWriter(Is64Bit, OSABI);
+ return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
+}
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
new file mode 100644
index 0000000..005a024
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h
@@ -0,0 +1,93 @@
+//===-- SparcFixupKinds.h - Sparc Specific Fixup Entries --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SPARC_FIXUPKINDS_H
+#define LLVM_SPARC_FIXUPKINDS_H
+
+#include "llvm/MC/MCFixup.h"
+
+namespace llvm {
+ namespace Sparc {
+ enum Fixups {
+ // fixup_sparc_call30 - 30-bit PC relative relocation for call
+ fixup_sparc_call30 = FirstTargetFixupKind,
+
+ /// fixup_sparc_br22 - 22-bit PC relative relocation for
+ /// branches
+ fixup_sparc_br22,
+
+ /// fixup_sparc_br19 - 19-bit PC relative relocation for
+ /// branches on icc/xcc
+ fixup_sparc_br19,
+
+ /// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo)
+ /// for sethi
+ fixup_sparc_hi22,
+
+ /// fixup_sparc_lo10 - 10-bit fixup corresponding to %lo(foo)
+ fixup_sparc_lo10,
+
+ /// fixup_sparc_h44 - 22-bit fixup corresponding to %h44(foo)
+ fixup_sparc_h44,
+
+ /// fixup_sparc_m44 - 10-bit fixup corresponding to %m44(foo)
+ fixup_sparc_m44,
+
+ /// fixup_sparc_l44 - 12-bit fixup corresponding to %l44(foo)
+ fixup_sparc_l44,
+
+ /// fixup_sparc_hh - 22-bit fixup corresponding to %hh(foo)
+ fixup_sparc_hh,
+
+ /// fixup_sparc_hm - 10-bit fixup corresponding to %hm(foo)
+ fixup_sparc_hm,
+
+ /// fixup_sparc_pc22 - 22-bit fixup corresponding to %pc22(foo)
+ fixup_sparc_pc22,
+
+ /// fixup_sparc_pc10 - 10-bit fixup corresponding to %pc10(foo)
+ fixup_sparc_pc10,
+
+ /// fixup_sparc_got22 - 22-bit fixup corresponding to %got22(foo)
+ fixup_sparc_got22,
+
+ /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo)
+ fixup_sparc_got10,
+
+ /// fixup_sparc_wplt30
+ fixup_sparc_wplt30,
+
+ /// fixups for Thread Local Storage
+ fixup_sparc_tls_gd_hi22,
+ fixup_sparc_tls_gd_lo10,
+ fixup_sparc_tls_gd_add,
+ fixup_sparc_tls_gd_call,
+ fixup_sparc_tls_ldm_hi22,
+ fixup_sparc_tls_ldm_lo10,
+ fixup_sparc_tls_ldm_add,
+ fixup_sparc_tls_ldm_call,
+ fixup_sparc_tls_ldo_hix22,
+ fixup_sparc_tls_ldo_lox10,
+ fixup_sparc_tls_ldo_add,
+ fixup_sparc_tls_ie_hi22,
+ fixup_sparc_tls_ie_lo10,
+ fixup_sparc_tls_ie_ld,
+ fixup_sparc_tls_ie_ldx,
+ fixup_sparc_tls_ie_add,
+ fixup_sparc_tls_le_hix22,
+ fixup_sparc_tls_le_lox10,
+
+ // Marker
+ LastTargetFixupKind,
+ NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
+ };
+ }
+}
+
+#endif
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
index baac36b..8d0dfec 100644
--- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp
+++ b/contrib/llvm/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,27 @@ 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);
+}
+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);
+}
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
index 1e58e37..d53d09d 100644
--- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
+++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h
@@ -17,13 +17,20 @@
#include "llvm/MC/MCAsmInfoELF.h"
namespace llvm {
- class StringRef;
+class StringRef;
- class SparcELFMCAsmInfo : public MCAsmInfoELF {
- virtual void anchor();
- public:
- explicit SparcELFMCAsmInfo(StringRef TT);
- };
+class SparcELFMCAsmInfo : public MCAsmInfoELF {
+ virtual void anchor();
+public:
+ explicit SparcELFMCAsmInfo(StringRef TT);
+ virtual const MCExpr* getExprForPersonalitySymbol(const MCSymbol *Sym,
+ unsigned Encoding,
+ MCStreamer &Streamer) const;
+ virtual const MCExpr* getExprForFDESymbol(const MCSymbol *Sym,
+ unsigned Encoding,
+ MCStreamer &Streamer) const;
+
+};
} // namespace llvm
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
new file mode 100644
index 0000000..ed756d9
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
@@ -0,0 +1,176 @@
+//===-- SparcMCCodeEmitter.cpp - Convert Sparc code to machine code -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SparcMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mccodeemitter"
+#include "SparcMCExpr.h"
+#include "SparcMCTargetDesc.h"
+#include "MCTargetDesc/SparcFixupKinds.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSymbol.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;
+ }
+ unsigned tlsOpNo = 0;
+ switch (MI.getOpcode()) {
+ default: break;
+ case SP::TLS_CALL: tlsOpNo = 1; break;
+ case SP::TLS_ADDrr:
+ case SP::TLS_ADDXrr:
+ case SP::TLS_LDrr:
+ case SP::TLS_LDXrr: tlsOpNo = 3; break;
+ }
+ if (tlsOpNo != 0) {
+ const MCOperand &MO = MI.getOperand(tlsOpNo);
+ uint64_t op = getMachineOpValue(MI, MO, Fixups);
+ assert(op == 0 && "Unexpected operand value!");
+ (void)op; // suppress warning.
+ }
+
+ ++MCNumEmitted; // Keep track of the # of mi's emitted.
+}
+
+
+unsigned SparcMCCodeEmitter::
+getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+
+ if (MO.isReg())
+ return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
+
+ if (MO.isImm())
+ return MO.getImm();
+
+ assert(MO.isExpr());
+ const MCExpr *Expr = MO.getExpr();
+ if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
+ MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
+ Fixups.push_back(MCFixup::Create(0, Expr, Kind));
+ return 0;
+ }
+
+ int64_t Res;
+ if (Expr->EvaluateAsAbsolute(Res))
+ return Res;
+
+ assert(0 && "Unhandled expression!");
+ return 0;
+}
+
+unsigned SparcMCCodeEmitter::
+getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isReg() || MO.isImm())
+ return getMachineOpValue(MI, MO, Fixups);
+
+ if (MI.getOpcode() == SP::TLS_CALL) {
+ // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
+ // EncodeInstruction.
+#ifndef NDEBUG
+ // Verify that the callee is actually __tls_get_addr.
+ const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
+ assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
+ "Unexpected expression in TLS_CALL");
+ const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
+ assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
+ "Unexpected function for TLS_CALL");
+#endif
+ return 0;
+ }
+
+ MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
+
+ if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
+ if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
+ fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
+ }
+
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(), fixupKind));
+
+ return 0;
+}
+
+unsigned SparcMCCodeEmitter::
+getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+ if (MO.isReg() || MO.isImm())
+ return getMachineOpValue(MI, MO, Fixups);
+
+ Sparc::Fixups fixup = Sparc::fixup_sparc_br22;
+ if (MI.getOpcode() == SP::BPXCC)
+ fixup = Sparc::fixup_sparc_br19;
+
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
+ (MCFixupKind)fixup));
+ return 0;
+}
+
+#include "SparcGenMCCodeEmitter.inc"
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
new file mode 100644
index 0000000..0337c09
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp
@@ -0,0 +1,254 @@
+//===-- SparcMCExpr.cpp - Sparc specific MC expression classes --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the implementation of the assembly expression modifiers
+// accepted by the Sparc architecture (e.g. "%hi", "%lo", ...).
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "sparcmcexpr"
+#include "SparcMCExpr.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCELF.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Object/ELF.h"
+
+
+using namespace llvm;
+
+const SparcMCExpr*
+SparcMCExpr::Create(VariantKind Kind, const MCExpr *Expr,
+ MCContext &Ctx) {
+ return new (Ctx) SparcMCExpr(Kind, Expr);
+}
+
+
+
+void SparcMCExpr::PrintImpl(raw_ostream &OS) const
+{
+
+ bool closeParen = printVariantKind(OS, Kind);
+
+ const MCExpr *Expr = getSubExpr();
+ Expr->print(OS);
+
+ if (closeParen)
+ OS << ')';
+}
+
+bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind)
+{
+ bool closeParen = true;
+ switch (Kind) {
+ case VK_Sparc_None: closeParen = false; break;
+ case VK_Sparc_LO: OS << "%lo("; break;
+ case VK_Sparc_HI: OS << "%hi("; break;
+ case VK_Sparc_H44: OS << "%h44("; break;
+ case VK_Sparc_M44: OS << "%m44("; break;
+ case VK_Sparc_L44: OS << "%l44("; break;
+ case VK_Sparc_HH: OS << "%hh("; break;
+ case VK_Sparc_HM: OS << "%hm("; break;
+ // FIXME: use %pc22/%pc10, if system assembler supports them.
+ case VK_Sparc_PC22: OS << "%hi("; break;
+ case VK_Sparc_PC10: OS << "%lo("; break;
+ // FIXME: use %got22/%got10, if system assembler supports them.
+ case VK_Sparc_GOT22: OS << "%hi("; break;
+ case VK_Sparc_GOT10: OS << "%lo("; break;
+ case VK_Sparc_WPLT30: closeParen = false; break;
+ case VK_Sparc_R_DISP32: OS << "%r_disp32("; break;
+ case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break;
+ case VK_Sparc_TLS_GD_LO10: OS << "%tgd_lo10("; break;
+ case VK_Sparc_TLS_GD_ADD: OS << "%tgd_add("; break;
+ case VK_Sparc_TLS_GD_CALL: OS << "%tgd_call("; break;
+ case VK_Sparc_TLS_LDM_HI22: OS << "%tldm_hi22("; break;
+ case VK_Sparc_TLS_LDM_LO10: OS << "%tldm_lo10("; break;
+ case VK_Sparc_TLS_LDM_ADD: OS << "%tldm_add("; break;
+ case VK_Sparc_TLS_LDM_CALL: OS << "%tldm_call("; break;
+ case VK_Sparc_TLS_LDO_HIX22: OS << "%tldo_hix22("; break;
+ case VK_Sparc_TLS_LDO_LOX10: OS << "%tldo_lox10("; break;
+ case VK_Sparc_TLS_LDO_ADD: OS << "%tldo_add("; break;
+ case VK_Sparc_TLS_IE_HI22: OS << "%tie_hi22("; break;
+ case VK_Sparc_TLS_IE_LO10: OS << "%tie_lo10("; break;
+ case VK_Sparc_TLS_IE_LD: OS << "%tie_ld("; break;
+ case VK_Sparc_TLS_IE_LDX: OS << "%tie_ldx("; break;
+ case VK_Sparc_TLS_IE_ADD: OS << "%tie_add("; break;
+ case VK_Sparc_TLS_LE_HIX22: OS << "%tle_hix22("; break;
+ case VK_Sparc_TLS_LE_LOX10: OS << "%tle_lox10("; break;
+ }
+ return closeParen;
+}
+
+SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name)
+{
+ return StringSwitch<SparcMCExpr::VariantKind>(name)
+ .Case("lo", VK_Sparc_LO)
+ .Case("hi", VK_Sparc_HI)
+ .Case("h44", VK_Sparc_H44)
+ .Case("m44", VK_Sparc_M44)
+ .Case("l44", VK_Sparc_L44)
+ .Case("hh", VK_Sparc_HH)
+ .Case("hm", VK_Sparc_HM)
+ .Case("pc22", VK_Sparc_PC22)
+ .Case("pc10", VK_Sparc_PC10)
+ .Case("got22", VK_Sparc_GOT22)
+ .Case("got10", VK_Sparc_GOT10)
+ .Case("r_disp32", VK_Sparc_R_DISP32)
+ .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22)
+ .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10)
+ .Case("tgd_add", VK_Sparc_TLS_GD_ADD)
+ .Case("tgd_call", VK_Sparc_TLS_GD_CALL)
+ .Case("tldm_hi22", VK_Sparc_TLS_LDM_HI22)
+ .Case("tldm_lo10", VK_Sparc_TLS_LDM_LO10)
+ .Case("tldm_add", VK_Sparc_TLS_LDM_ADD)
+ .Case("tldm_call", VK_Sparc_TLS_LDM_CALL)
+ .Case("tldo_hix22", VK_Sparc_TLS_LDO_HIX22)
+ .Case("tldo_lox10", VK_Sparc_TLS_LDO_LOX10)
+ .Case("tldo_add", VK_Sparc_TLS_LDO_ADD)
+ .Case("tie_hi22", VK_Sparc_TLS_IE_HI22)
+ .Case("tie_lo10", VK_Sparc_TLS_IE_LO10)
+ .Case("tie_ld", VK_Sparc_TLS_IE_LD)
+ .Case("tie_ldx", VK_Sparc_TLS_IE_LDX)
+ .Case("tie_add", VK_Sparc_TLS_IE_ADD)
+ .Case("tle_hix22", VK_Sparc_TLS_LE_HIX22)
+ .Case("tle_lox10", VK_Sparc_TLS_LE_LOX10)
+ .Default(VK_Sparc_None);
+}
+
+Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) {
+ switch (Kind) {
+ default: assert(0 && "Unhandled SparcMCExpr::VariantKind");
+ case VK_Sparc_LO: return Sparc::fixup_sparc_lo10;
+ case VK_Sparc_HI: return Sparc::fixup_sparc_hi22;
+ case VK_Sparc_H44: return Sparc::fixup_sparc_h44;
+ case VK_Sparc_M44: return Sparc::fixup_sparc_m44;
+ case VK_Sparc_L44: return Sparc::fixup_sparc_l44;
+ case VK_Sparc_HH: return Sparc::fixup_sparc_hh;
+ case VK_Sparc_HM: return Sparc::fixup_sparc_hm;
+ case VK_Sparc_PC22: return Sparc::fixup_sparc_pc22;
+ case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10;
+ case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22;
+ case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10;
+ case VK_Sparc_WPLT30: return Sparc::fixup_sparc_wplt30;
+ case VK_Sparc_TLS_GD_HI22: return Sparc::fixup_sparc_tls_gd_hi22;
+ case VK_Sparc_TLS_GD_LO10: return Sparc::fixup_sparc_tls_gd_lo10;
+ case VK_Sparc_TLS_GD_ADD: return Sparc::fixup_sparc_tls_gd_add;
+ case VK_Sparc_TLS_GD_CALL: return Sparc::fixup_sparc_tls_gd_call;
+ case VK_Sparc_TLS_LDM_HI22: return Sparc::fixup_sparc_tls_ldm_hi22;
+ case VK_Sparc_TLS_LDM_LO10: return Sparc::fixup_sparc_tls_ldm_lo10;
+ case VK_Sparc_TLS_LDM_ADD: return Sparc::fixup_sparc_tls_ldm_add;
+ case VK_Sparc_TLS_LDM_CALL: return Sparc::fixup_sparc_tls_ldm_call;
+ case VK_Sparc_TLS_LDO_HIX22: return Sparc::fixup_sparc_tls_ldo_hix22;
+ case VK_Sparc_TLS_LDO_LOX10: return Sparc::fixup_sparc_tls_ldo_lox10;
+ case VK_Sparc_TLS_LDO_ADD: return Sparc::fixup_sparc_tls_ldo_add;
+ case VK_Sparc_TLS_IE_HI22: return Sparc::fixup_sparc_tls_ie_hi22;
+ case VK_Sparc_TLS_IE_LO10: return Sparc::fixup_sparc_tls_ie_lo10;
+ case VK_Sparc_TLS_IE_LD: return Sparc::fixup_sparc_tls_ie_ld;
+ case VK_Sparc_TLS_IE_LDX: return Sparc::fixup_sparc_tls_ie_ldx;
+ case VK_Sparc_TLS_IE_ADD: return Sparc::fixup_sparc_tls_ie_add;
+ case VK_Sparc_TLS_LE_HIX22: return Sparc::fixup_sparc_tls_le_hix22;
+ case VK_Sparc_TLS_LE_LOX10: return Sparc::fixup_sparc_tls_le_lox10;
+ }
+}
+
+bool
+SparcMCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
+ const MCAsmLayout *Layout) const {
+ if (!Layout)
+ return false;
+ return getSubExpr()->EvaluateAsRelocatable(Res, *Layout);
+}
+
+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
+ switch (Expr->getKind()) {
+ case MCExpr::Target:
+ llvm_unreachable("Can't handle nested target expr!");
+ break;
+
+ case MCExpr::Constant:
+ break;
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
+ fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
+ fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
+ break;
+ }
+
+ case MCExpr::SymbolRef: {
+ const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
+ MCSymbolData &SD = Asm.getOrCreateSymbolData(SymRef.getSymbol());
+ MCELF::SetType(SD, ELF::STT_TLS);
+ break;
+ }
+
+ case MCExpr::Unary:
+ fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
+ break;
+ }
+
+}
+
+void SparcMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
+ switch(getKind()) {
+ default: return;
+ case VK_Sparc_TLS_GD_HI22:
+ case VK_Sparc_TLS_GD_LO10:
+ case VK_Sparc_TLS_GD_ADD:
+ case VK_Sparc_TLS_GD_CALL:
+ case VK_Sparc_TLS_LDM_HI22:
+ case VK_Sparc_TLS_LDM_LO10:
+ case VK_Sparc_TLS_LDM_ADD:
+ case VK_Sparc_TLS_LDM_CALL:
+ case VK_Sparc_TLS_LDO_HIX22:
+ case VK_Sparc_TLS_LDO_LOX10:
+ case VK_Sparc_TLS_LDO_ADD:
+ case VK_Sparc_TLS_IE_HI22:
+ case VK_Sparc_TLS_IE_LO10:
+ case VK_Sparc_TLS_IE_LD:
+ case VK_Sparc_TLS_IE_LDX:
+ case VK_Sparc_TLS_IE_ADD:
+ case VK_Sparc_TLS_LE_HIX22:
+ case VK_Sparc_TLS_LE_LOX10: break;
+ }
+ fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
+}
+
+// FIXME: This basically copies MCObjectStreamer::AddValueSymbols. Perhaps
+// that method should be made public?
+// FIXME: really do above: now that at least three other backends are using it.
+static void AddValueSymbolsImpl(const MCExpr *Value, MCAssembler *Asm) {
+ switch (Value->getKind()) {
+ case MCExpr::Target:
+ llvm_unreachable("Can't handle nested target expr!");
+ break;
+
+ case MCExpr::Constant:
+ break;
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value);
+ AddValueSymbolsImpl(BE->getLHS(), Asm);
+ AddValueSymbolsImpl(BE->getRHS(), Asm);
+ break;
+ }
+
+ case MCExpr::SymbolRef:
+ Asm->getOrCreateSymbolData(cast<MCSymbolRefExpr>(Value)->getSymbol());
+ break;
+
+ case MCExpr::Unary:
+ AddValueSymbolsImpl(cast<MCUnaryExpr>(Value)->getSubExpr(), Asm);
+ break;
+ }
+}
+
+void SparcMCExpr::AddValueSymbols(MCAssembler *Asm) const {
+ AddValueSymbolsImpl(getSubExpr(), Asm);
+}
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
new file mode 100644
index 0000000..be6526e
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h
@@ -0,0 +1,111 @@
+//====- SparcMCExpr.h - Sparc specific MC expression classes --*- C++ -*-=====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes Sparc-specific MCExprs, used for modifiers like
+// "%hi" or "%lo" etc.,
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SPARCMCEXPR_H
+#define LLVM_SPARCMCEXPR_H
+
+#include "SparcFixupKinds.h"
+#include "llvm/MC/MCExpr.h"
+
+namespace llvm {
+
+class StringRef;
+class SparcMCExpr : public MCTargetExpr {
+public:
+ enum VariantKind {
+ VK_Sparc_None,
+ VK_Sparc_LO,
+ VK_Sparc_HI,
+ VK_Sparc_H44,
+ VK_Sparc_M44,
+ VK_Sparc_L44,
+ VK_Sparc_HH,
+ VK_Sparc_HM,
+ VK_Sparc_PC22,
+ VK_Sparc_PC10,
+ VK_Sparc_GOT22,
+ VK_Sparc_GOT10,
+ VK_Sparc_WPLT30,
+ VK_Sparc_R_DISP32,
+ VK_Sparc_TLS_GD_HI22,
+ VK_Sparc_TLS_GD_LO10,
+ VK_Sparc_TLS_GD_ADD,
+ VK_Sparc_TLS_GD_CALL,
+ VK_Sparc_TLS_LDM_HI22,
+ VK_Sparc_TLS_LDM_LO10,
+ VK_Sparc_TLS_LDM_ADD,
+ VK_Sparc_TLS_LDM_CALL,
+ VK_Sparc_TLS_LDO_HIX22,
+ VK_Sparc_TLS_LDO_LOX10,
+ VK_Sparc_TLS_LDO_ADD,
+ VK_Sparc_TLS_IE_HI22,
+ VK_Sparc_TLS_IE_LO10,
+ VK_Sparc_TLS_IE_LD,
+ VK_Sparc_TLS_IE_LDX,
+ VK_Sparc_TLS_IE_ADD,
+ VK_Sparc_TLS_LE_HIX22,
+ VK_Sparc_TLS_LE_LOX10
+ };
+
+private:
+ const VariantKind Kind;
+ const MCExpr *Expr;
+
+ explicit SparcMCExpr(VariantKind _Kind, const MCExpr *_Expr)
+ : Kind(_Kind), Expr(_Expr) {}
+
+public:
+ /// @name Construction
+ /// @{
+
+ static const SparcMCExpr *Create(VariantKind Kind, const MCExpr *Expr,
+ MCContext &Ctx);
+ /// @}
+ /// @name Accessors
+ /// @{
+
+ /// getOpcode - Get the kind of this expression.
+ VariantKind getKind() const { return Kind; }
+
+ /// getSubExpr - Get the child of this expression.
+ const MCExpr *getSubExpr() const { return Expr; }
+
+ /// getFixupKind - Get the fixup kind of this expression.
+ Sparc::Fixups getFixupKind() const { return getFixupKind(Kind); }
+
+ /// @}
+ void PrintImpl(raw_ostream &OS) const;
+ bool EvaluateAsRelocatableImpl(MCValue &Res,
+ const MCAsmLayout *Layout) const;
+ void AddValueSymbols(MCAssembler *) const;
+ const MCSection *FindAssociatedSection() const {
+ return getSubExpr()->FindAssociatedSection();
+ }
+
+ void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const;
+
+ static bool classof(const MCExpr *E) {
+ return E->getKind() == MCExpr::Target;
+ }
+
+ static bool classof(const SparcMCExpr *) { return true; }
+
+ static VariantKind parseVariantKind(StringRef name);
+ static bool printVariantKind(raw_ostream &OS, VariantKind Kind);
+ static Sparc::Fixups getFixupKind(VariantKind Kind);
+};
+
+} // end namespace llvm.
+
+#endif
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
index 1c64e1b..2832a71 100644
--- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.cpp
+++ b/contrib/llvm/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"
@@ -31,6 +33,25 @@
using namespace llvm;
+
+static MCAsmInfo *createSparcMCAsmInfo(const MCRegisterInfo &MRI,
+ StringRef TT) {
+ MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT);
+ unsigned Reg = MRI.getDwarfRegNum(SP::O6, true);
+ MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, Reg, 0);
+ MAI->addInitialFrameState(Inst);
+ return MAI;
+}
+
+static MCAsmInfo *createSparcV9MCAsmInfo(const MCRegisterInfo &MRI,
+ StringRef TT) {
+ MCAsmInfo *MAI = new SparcELFMCAsmInfo(TT);
+ unsigned Reg = MRI.getDwarfRegNum(SP::O6, true);
+ MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, Reg, 2047);
+ MAI->addInitialFrameState(Inst);
+ return MAI;
+}
+
static MCInstrInfo *createSparcMCInstrInfo() {
MCInstrInfo *X = new MCInstrInfo();
InitSparcMCInstrInfo(X);
@@ -39,7 +60,7 @@ static MCInstrInfo *createSparcMCInstrInfo() {
static MCRegisterInfo *createSparcMCRegisterInfo(StringRef TT) {
MCRegisterInfo *X = new MCRegisterInfo();
- InitSparcMCRegisterInfo(X, SP::I7);
+ InitSparcMCRegisterInfo(X, SP::O7);
return X;
}
@@ -66,9 +87,13 @@ static MCCodeGenInfo *createSparcMCCodeGenInfo(StringRef TT, Reloc::Model RM,
CodeGenOpt::Level OL) {
MCCodeGenInfo *X = new MCCodeGenInfo();
- // The default 32-bit code model is abs32/pic32.
- if (CM == CodeModel::Default)
- CM = RM == Reloc::PIC_ ? CodeModel::Medium : CodeModel::Small;
+ // The default 32-bit code model is abs32/pic32 and the default 32-bit
+ // code model for JIT is abs32.
+ switch (CM) {
+ default: break;
+ case CodeModel::Default:
+ case CodeModel::JITDefault: CM = CodeModel::Small; break;
+ }
X->InitMCCodeGenInfo(RM, CM, OL);
return X;
@@ -79,17 +104,55 @@ static MCCodeGenInfo *createSparcV9MCCodeGenInfo(StringRef TT, Reloc::Model RM,
CodeGenOpt::Level OL) {
MCCodeGenInfo *X = new MCCodeGenInfo();
- // The default 64-bit code model is abs44/pic32.
- if (CM == CodeModel::Default)
- CM = CodeModel::Medium;
+ // The default 64-bit code model is abs44/pic32 and the default 64-bit
+ // code model for JIT is abs64.
+ switch (CM) {
+ default: break;
+ case CodeModel::Default:
+ CM = RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium;
+ break;
+ case CodeModel::JITDefault:
+ CM = CodeModel::Large;
+ break;
+ }
X->InitMCCodeGenInfo(RM, CM, OL);
return X;
}
+
+static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
+ MCContext &Context, MCAsmBackend &MAB,
+ raw_ostream &OS, MCCodeEmitter *Emitter,
+ bool RelaxAll, bool NoExecStack) {
+ SparcTargetELFStreamer *S = new SparcTargetELFStreamer();
+ return createELFStreamer(Context, S, MAB, OS, Emitter, RelaxAll, NoExecStack);
+}
+
+static MCStreamer *
+createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
+ bool isVerboseAsm, bool useLoc, bool useCFI,
+ bool useDwarfDirectory, MCInstPrinter *InstPrint,
+ MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) {
+ SparcTargetAsmStreamer *S = new SparcTargetAsmStreamer(OS);
+
+ return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI,
+ useDwarfDirectory, InstPrint, CE, TAB,
+ ShowInst);
+}
+
+static MCInstPrinter *createSparcMCInstPrinter(const Target &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI,
+ const MCSubtargetInfo &STI) {
+ return new SparcInstPrinter(MAI, MII, MRI);
+}
+
extern "C" void LLVMInitializeSparcTargetMC() {
// Register the MC asm info.
- RegisterMCAsmInfo<SparcELFMCAsmInfo> X(TheSparcTarget);
- RegisterMCAsmInfo<SparcELFMCAsmInfo> Y(TheSparcV9Target);
+ RegisterMCAsmInfoFn X(TheSparcTarget, createSparcMCAsmInfo);
+ RegisterMCAsmInfoFn Y(TheSparcV9Target, createSparcV9MCAsmInfo);
// Register the MC codegen info.
TargetRegistry::RegisterMCCodeGenInfo(TheSparcTarget,
@@ -99,11 +162,46 @@ 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);
+
+ // Register the MC Code Emitter.
+ TargetRegistry::RegisterMCCodeEmitter(TheSparcTarget,
+ createSparcMCCodeEmitter);
+ TargetRegistry::RegisterMCCodeEmitter(TheSparcV9Target,
+ createSparcMCCodeEmitter);
+
+ //Register the asm backend.
+ TargetRegistry::RegisterMCAsmBackend(TheSparcTarget,
+ createSparcAsmBackend);
+ TargetRegistry::RegisterMCAsmBackend(TheSparcV9Target,
+ createSparcAsmBackend);
+
+ // Register the object streamer.
+ TargetRegistry::RegisterMCObjectStreamer(TheSparcTarget,
+ createMCStreamer);
+ TargetRegistry::RegisterMCObjectStreamer(TheSparcV9Target,
+ createMCStreamer);
+
+ // Register the asm streamer.
+ TargetRegistry::RegisterAsmStreamer(TheSparcTarget,
+ createMCAsmStreamer);
+ TargetRegistry::RegisterAsmStreamer(TheSparcV9Target,
+ createMCAsmStreamer);
+
+ // Register the MCInstPrinter
+ TargetRegistry::RegisterMCInstPrinter(TheSparcTarget,
+ createSparcMCInstPrinter);
+ TargetRegistry::RegisterMCInstPrinter(TheSparcV9Target,
+ createSparcMCInstPrinter);
}
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
index cba775a..c8029a8 100644
--- a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
+++ b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h
@@ -14,12 +14,34 @@
#ifndef SPARCMCTARGETDESC_H
#define SPARCMCTARGETDESC_H
+#include "llvm/Support/DataTypes.h"
+
namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCObjectWriter;
+class MCRegisterInfo;
+class MCSubtargetInfo;
class Target;
+class StringRef;
+class raw_ostream;
extern Target TheSparcTarget;
extern Target TheSparcV9Target;
+MCCodeEmitter *createSparcMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCRegisterInfo &MRI,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx);
+MCAsmBackend *createSparcAsmBackend(const Target &T,
+ const MCRegisterInfo &MRI,
+ StringRef TT,
+ StringRef CPU);
+MCObjectWriter *createSparcELFObjectWriter(raw_ostream &OS,
+ bool Is64Bit,
+ uint8_t OSABI);
} // End llvm namespace
// Defines symbolic names for Sparc registers. This defines a mapping from
diff --git a/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp b/contrib/llvm/lib/Target/Sparc/MCTargetDesc/SparcTargetStreamer.cpp
new file mode 100644
index 0000000..01043ae
--- /dev/null
+++ b/contrib/llvm/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);
+}
diff --git a/contrib/llvm/lib/Target/Sparc/Sparc.h b/contrib/llvm/lib/Target/Sparc/Sparc.h
index f44b604..8d46c60 100644
--- a/contrib/llvm/lib/Target/Sparc/Sparc.h
+++ b/contrib/llvm/lib/Target/Sparc/Sparc.h
@@ -23,12 +23,18 @@ namespace llvm {
class FunctionPass;
class SparcTargetMachine;
class formatted_raw_ostream;
+ class AsmPrinter;
+ class MCInst;
+ class MachineInstr;
FunctionPass *createSparcISelDag(SparcTargetMachine &TM);
FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM);
FunctionPass *createSparcJITCodeEmitterPass(SparcTargetMachine &TM,
JITCodeEmitter &JCE);
+ void LowerSparcMachineInstrToMCInst(const MachineInstr *MI,
+ MCInst &OutMI,
+ AsmPrinter &AP);
} // end namespace llvm;
namespace llvm {
diff --git a/contrib/llvm/lib/Target/Sparc/Sparc.td b/contrib/llvm/lib/Target/Sparc/Sparc.td
index 0df48f6..05ff996 100644
--- a/contrib/llvm/lib/Target/Sparc/Sparc.td
+++ b/contrib/llvm/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
//===----------------------------------------------------------------------===//
@@ -44,6 +47,10 @@ include "SparcInstrInfo.td"
def SparcInstrInfo : InstrInfo;
+def SparcAsmParser : AsmParser {
+ bit ShouldEmitMatchRegisterName = 0;
+}
+
//===----------------------------------------------------------------------===//
// SPARC processors supported.
//===----------------------------------------------------------------------===//
@@ -52,6 +59,7 @@ class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;
def : Proc<"generic", []>;
+def : Proc<"v7", []>;
def : Proc<"v8", []>;
def : Proc<"supersparc", []>;
def : Proc<"sparclite", []>;
@@ -63,8 +71,15 @@ def : Proc<"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, UsePopc]>;
+def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated, UsePopc]>;
+def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated, UsePopc]>;
+def SparcAsmWriter : AsmWriter {
+ string AsmWriterClassName = "InstPrinter";
+ bit isMCAsmWriter = 1;
+}
//===----------------------------------------------------------------------===//
// Declare the target which we are implementing
@@ -73,4 +88,7 @@ def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
def Sparc : Target {
// Pull in Instruction Info:
let InstructionSet = SparcInstrInfo;
+ let AssemblyParsers = [SparcAsmParser];
+
+ let AssemblyWriters = [SparcAsmWriter];
}
diff --git a/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp b/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
index d06c894..b2c536d 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/contrib/llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -16,12 +16,18 @@
#include "Sparc.h"
#include "SparcInstrInfo.h"
#include "SparcTargetMachine.h"
-#include "MCTargetDesc/SparcBaseInfo.h"
+#include "SparcTargetStreamer.h"
+#include "InstPrinter/SparcInstPrinter.h"
+#include "MCTargetDesc/SparcMCExpr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/TargetRegistry.h"
@@ -31,6 +37,9 @@ 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 +54,12 @@ 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);
+ virtual void EmitEndOfAsmFile(Module &M);
+
+ static const char *getRegisterName(unsigned RegNo) {
+ return SparcInstPrinter::getRegisterName(RegNo);
}
- void printInstruction(const MachineInstr *MI, raw_ostream &OS);// autogen'd.
- static const char *getRegisterName(unsigned RegNo);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode,
@@ -61,24 +68,202 @@ 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());
- }
+ void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI);
};
} // end of anonymous namespace
-#include "SparcGenAsmWriter.inc"
+static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
+ MCSymbol *Sym, MCContext &OutContext) {
+ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym,
+ OutContext);
+ const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext);
+ return MCOperand::CreateExpr(expr);
+
+}
+static MCOperand createPCXCallOP(MCSymbol *Label,
+ MCContext &OutContext) {
+ return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
+}
+
+static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
+ MCSymbol *GOTLabel, MCSymbol *StartLabel,
+ MCSymbol *CurLabel,
+ MCContext &OutContext)
+{
+ const MCSymbolRefExpr *GOT = MCSymbolRefExpr::Create(GOTLabel, OutContext);
+ const MCSymbolRefExpr *Start = MCSymbolRefExpr::Create(StartLabel,
+ OutContext);
+ const MCSymbolRefExpr *Cur = MCSymbolRefExpr::Create(CurLabel,
+ OutContext);
+
+ const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Cur, Start, OutContext);
+ const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(GOT, Sub, OutContext);
+ const SparcMCExpr *expr = SparcMCExpr::Create(Kind,
+ Add, OutContext);
+ return MCOperand::CreateExpr(expr);
+}
+
+static void EmitCall(MCStreamer &OutStreamer,
+ MCOperand &Callee)
+{
+ MCInst CallInst;
+ CallInst.setOpcode(SP::CALL);
+ CallInst.addOperand(Callee);
+ OutStreamer.EmitInstruction(CallInst);
+}
+
+static void EmitSETHI(MCStreamer &OutStreamer,
+ MCOperand &Imm, MCOperand &RD)
+{
+ MCInst SETHIInst;
+ SETHIInst.setOpcode(SP::SETHIi);
+ SETHIInst.addOperand(RD);
+ SETHIInst.addOperand(Imm);
+ OutStreamer.EmitInstruction(SETHIInst);
+}
+
+static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
+ MCOperand &RS1, MCOperand &Src2, MCOperand &RD)
+{
+ MCInst Inst;
+ Inst.setOpcode(Opcode);
+ Inst.addOperand(RD);
+ Inst.addOperand(RS1);
+ Inst.addOperand(Src2);
+ OutStreamer.EmitInstruction(Inst);
+}
+
+static void EmitOR(MCStreamer &OutStreamer,
+ MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
+ EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD);
+}
+
+static void EmitADD(MCStreamer &OutStreamer,
+ MCOperand &RS1, MCOperand &RS2, MCOperand &RD) {
+ EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD);
+}
+
+static void EmitSHL(MCStreamer &OutStreamer,
+ MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
+ EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD);
+}
+
+
+static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
+ SparcMCExpr::VariantKind HiKind,
+ SparcMCExpr::VariantKind LoKind,
+ MCOperand &RD,
+ MCContext &OutContext) {
+
+ MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
+ MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
+ EmitSETHI(OutStreamer, hi, RD);
+ EmitOR(OutStreamer, RD, lo, RD);
+}
+
+void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI)
+{
+ MCSymbol *GOTLabel =
+ OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
+
+ const MachineOperand &MO = MI->getOperand(0);
+ assert(MO.getReg() != SP::O7 &&
+ "%o7 is assigned as destination for getpcx!");
+
+ MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg());
+
+
+ if (TM.getRelocationModel() != Reloc::PIC_) {
+ // Just load the address of GOT to MCRegOP.
+ switch(TM.getCodeModel()) {
+ default:
+ llvm_unreachable("Unsupported absolute code model");
+ case CodeModel::Small:
+ EmitHiLo(OutStreamer, GOTLabel,
+ SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
+ MCRegOP, OutContext);
+ break;
+ case CodeModel::Medium: {
+ EmitHiLo(OutStreamer, GOTLabel,
+ SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
+ MCRegOP, OutContext);
+ MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12,
+ OutContext));
+ EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
+ MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
+ GOTLabel, OutContext);
+ EmitOR(OutStreamer, MCRegOP, lo, MCRegOP);
+ break;
+ }
+ case CodeModel::Large: {
+ EmitHiLo(OutStreamer, GOTLabel,
+ SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
+ MCRegOP, OutContext);
+ MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32,
+ OutContext));
+ EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
+ // Use register %o7 to load the lower 32 bits.
+ MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
+ EmitHiLo(OutStreamer, GOTLabel,
+ SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
+ RegO7, OutContext);
+ EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP);
+ }
+ }
+ return;
+ }
+
+ MCSymbol *StartLabel = OutContext.CreateTempSymbol();
+ MCSymbol *EndLabel = OutContext.CreateTempSymbol();
+ MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
+
+ MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
+
+ // <StartLabel>:
+ // call <EndLabel>
+ // <SethiLabel>:
+ // sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
+ // <EndLabel>:
+ // or <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
+ // add <MO>, %o7, <MO>
+
+ OutStreamer.EmitLabel(StartLabel);
+ MCOperand Callee = createPCXCallOP(EndLabel, OutContext);
+ EmitCall(OutStreamer, Callee);
+ OutStreamer.EmitLabel(SethiLabel);
+ MCOperand hiImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC22,
+ GOTLabel, StartLabel, SethiLabel,
+ OutContext);
+ EmitSETHI(OutStreamer, hiImm, MCRegOP);
+ OutStreamer.EmitLabel(EndLabel);
+ MCOperand loImm = createPCXRelExprOp(SparcMCExpr::VK_Sparc_PC10,
+ GOTLabel, StartLabel, EndLabel,
+ OutContext);
+ EmitOR(OutStreamer, MCRegOP, loImm, MCRegOP);
+ EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP);
+}
+
+void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
+{
+
+ switch (MI->getOpcode()) {
+ default: break;
+ case TargetOpcode::DBG_VALUE:
+ // FIXME: Debug Value.
+ return;
+ case SP::GETPCX:
+ LowerGETPCXAndEmitMCInsts(MI);
+ return;
+ }
+ MachineBasicBlock::const_instr_iterator I = MI;
+ MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
+ do {
+ MCInst TmpInst;
+ LowerSparcMachineInstrToMCInst(I, TmpInst, *this);
+ OutStreamer.EmitInstruction(TmpInst);
+ } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
+}
void SparcAsmPrinter::EmitFunctionBodyStart() {
if (!TM.getSubtarget<SparcSubtarget>().is64Bit())
@@ -90,89 +275,70 @@ 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);
}
}
void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
raw_ostream &O) {
const MachineOperand &MO = MI->getOperand (opNum);
- unsigned TF = MO.getTargetFlags();
+ SparcMCExpr::VariantKind TF = (SparcMCExpr::VariantKind) MO.getTargetFlags();
+
#ifndef NDEBUG
// Verify the target flags.
if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
if (MI->getOpcode() == SP::CALL)
- assert(TF == SPII::MO_NO_FLAG &&
+ assert(TF == SparcMCExpr::VK_Sparc_None &&
"Cannot handle target flags on call address");
- else if (MI->getOpcode() == SP::SETHIi)
- assert((TF == SPII::MO_HI || TF == SPII::MO_H44 || TF == SPII::MO_HH
- || TF == SPII::MO_TLS_GD_HI22
- || TF == SPII::MO_TLS_LDM_HI22
- || TF == SPII::MO_TLS_LDO_HIX22
- || TF == SPII::MO_TLS_IE_HI22
- || TF == SPII::MO_TLS_LE_HIX22) &&
+ else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
+ assert((TF == SparcMCExpr::VK_Sparc_HI
+ || TF == SparcMCExpr::VK_Sparc_H44
+ || TF == SparcMCExpr::VK_Sparc_HH
+ || TF == SparcMCExpr::VK_Sparc_TLS_GD_HI22
+ || TF == SparcMCExpr::VK_Sparc_TLS_LDM_HI22
+ || TF == SparcMCExpr::VK_Sparc_TLS_LDO_HIX22
+ || TF == SparcMCExpr::VK_Sparc_TLS_IE_HI22
+ || TF == SparcMCExpr::VK_Sparc_TLS_LE_HIX22) &&
"Invalid target flags for address operand on sethi");
else if (MI->getOpcode() == SP::TLS_CALL)
- assert((TF == SPII::MO_NO_FLAG
- || TF == SPII::MO_TLS_GD_CALL
- || TF == SPII::MO_TLS_LDM_CALL) &&
+ assert((TF == SparcMCExpr::VK_Sparc_None
+ || TF == SparcMCExpr::VK_Sparc_TLS_GD_CALL
+ || TF == SparcMCExpr::VK_Sparc_TLS_LDM_CALL) &&
"Cannot handle target flags on tls call address");
else if (MI->getOpcode() == SP::TLS_ADDrr)
- assert((TF == SPII::MO_TLS_GD_ADD || TF == SPII::MO_TLS_LDM_ADD
- || TF == SPII::MO_TLS_LDO_ADD || TF == SPII::MO_TLS_IE_ADD) &&
+ assert((TF == SparcMCExpr::VK_Sparc_TLS_GD_ADD
+ || TF == SparcMCExpr::VK_Sparc_TLS_LDM_ADD
+ || TF == SparcMCExpr::VK_Sparc_TLS_LDO_ADD
+ || TF == SparcMCExpr::VK_Sparc_TLS_IE_ADD) &&
"Cannot handle target flags on add for TLS");
else if (MI->getOpcode() == SP::TLS_LDrr)
- assert(TF == SPII::MO_TLS_IE_LD &&
+ assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD &&
"Cannot handle target flags on ld for TLS");
else if (MI->getOpcode() == SP::TLS_LDXrr)
- assert(TF == SPII::MO_TLS_IE_LDX &&
+ assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX &&
"Cannot handle target flags on ldx for TLS");
- else if (MI->getOpcode() == SP::XORri)
- assert((TF == SPII::MO_TLS_LDO_LOX10 || TF == SPII::MO_TLS_LE_LOX10) &&
+ else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
+ assert((TF == SparcMCExpr::VK_Sparc_TLS_LDO_LOX10
+ || TF == SparcMCExpr::VK_Sparc_TLS_LE_LOX10) &&
"Cannot handle target flags on xor for TLS");
else
- assert((TF == SPII::MO_LO || TF == SPII::MO_M44 || TF == SPII::MO_L44
- || TF == SPII::MO_HM
- || TF == SPII::MO_TLS_GD_LO10
- || TF == SPII::MO_TLS_LDM_LO10
- || TF == SPII::MO_TLS_IE_LO10 ) &&
+ assert((TF == SparcMCExpr::VK_Sparc_LO
+ || TF == SparcMCExpr::VK_Sparc_M44
+ || TF == SparcMCExpr::VK_Sparc_L44
+ || TF == SparcMCExpr::VK_Sparc_HM
+ || TF == SparcMCExpr::VK_Sparc_TLS_GD_LO10
+ || TF == SparcMCExpr::VK_Sparc_TLS_LDM_LO10
+ || TF == SparcMCExpr::VK_Sparc_TLS_IE_LO10 ) &&
"Invalid target flags for small address operand");
}
#endif
- bool CloseParen = true;
- switch (TF) {
- default:
- llvm_unreachable("Unknown target flags on operand");
- case SPII::MO_NO_FLAG:
- CloseParen = false;
- break;
- case SPII::MO_LO: O << "%lo("; break;
- case SPII::MO_HI: O << "%hi("; break;
- case SPII::MO_H44: O << "%h44("; break;
- case SPII::MO_M44: O << "%m44("; break;
- case SPII::MO_L44: O << "%l44("; break;
- case SPII::MO_HH: O << "%hh("; break;
- case SPII::MO_HM: O << "%hm("; break;
- case SPII::MO_TLS_GD_HI22: O << "%tgd_hi22("; break;
- case SPII::MO_TLS_GD_LO10: O << "%tgd_lo10("; break;
- case SPII::MO_TLS_GD_ADD: O << "%tgd_add("; break;
- case SPII::MO_TLS_GD_CALL: O << "%tgd_call("; break;
- case SPII::MO_TLS_LDM_HI22: O << "%tldm_hi22("; break;
- case SPII::MO_TLS_LDM_LO10: O << "%tldm_lo10("; break;
- case SPII::MO_TLS_LDM_ADD: O << "%tldm_add("; break;
- case SPII::MO_TLS_LDM_CALL: O << "%tldm_call("; break;
- case SPII::MO_TLS_LDO_HIX22: O << "%tldo_hix22("; break;
- case SPII::MO_TLS_LDO_LOX10: O << "%tldo_lox10("; break;
- case SPII::MO_TLS_LDO_ADD: O << "%tldo_add("; break;
- case SPII::MO_TLS_IE_HI22: O << "%tie_hi22("; break;
- case SPII::MO_TLS_IE_LO10: O << "%tie_lo10("; break;
- case SPII::MO_TLS_IE_LD: O << "%tie_ld("; break;
- case SPII::MO_TLS_IE_LDX: O << "%tie_ldx("; break;
- case SPII::MO_TLS_IE_ADD: O << "%tie_add("; break;
- case SPII::MO_TLS_LE_HIX22: O << "%tle_hix22("; break;
- case SPII::MO_TLS_LE_LOX10: O << "%tle_lox10("; break;
- }
+
+ bool CloseParen = SparcMCExpr::printVariantKind(O, TF);
switch (MO.getType()) {
case MachineOperand::MO_Register:
@@ -226,46 +392,6 @@ void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
printOperand(MI, opNum+1, O);
}
-bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum,
- raw_ostream &O) {
- std::string operand = "";
- const MachineOperand &MO = MI->getOperand(opNum);
- switch (MO.getType()) {
- default: llvm_unreachable("Operand is not a register");
- case MachineOperand::MO_Register:
- assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
- "Operand is not a physical register ");
- assert(MO.getReg() != SP::O7 &&
- "%o7 is assigned as destination for getpcx!");
- operand = "%" + StringRef(getRegisterName(MO.getReg())).lower();
- break;
- }
-
- unsigned mfNum = MI->getParent()->getParent()->getFunctionNumber();
- unsigned bbNum = MI->getParent()->getNumber();
-
- O << '\n' << ".LLGETPCH" << mfNum << '_' << bbNum << ":\n";
- O << "\tcall\t.LLGETPC" << mfNum << '_' << bbNum << '\n' ;
-
- O << "\t sethi\t"
- << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum
- << ")), " << operand << '\n' ;
-
- O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ;
- O << "\tor\t" << operand
- << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum
- << ")), " << operand << '\n';
- O << "\tadd\t" << operand << ", %o7, " << operand << '\n';
-
- return true;
-}
-
-void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum,
- raw_ostream &O) {
- int CC = (int)MI->getOperand(opNum).getImm();
- O << SPARCCondCodeToString((SPCC::CondCodes)CC);
-}
-
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -303,35 +429,21 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
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();
+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.
diff --git a/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td b/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td
index acd4ec2..dfaaabf 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcCallingConv.td
+++ b/contrib/llvm/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),
diff --git a/contrib/llvm/lib/Target/Sparc/SparcCodeEmitter.cpp b/contrib/llvm/lib/Target/Sparc/SparcCodeEmitter.cpp
index 9bfe31fe..b7b2182 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcCodeEmitter.cpp
+++ b/contrib/llvm/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"
@@ -72,6 +72,11 @@ private:
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,20 +186,32 @@ unsigned SparcCodeEmitter::getMachineOpValue(const MachineInstr &MI,
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 {
unsigned TF = MO.getTargetFlags();
switch (TF) {
default:
- case SPII::MO_NO_FLAG: break;
- case SPII::MO_LO: return SP::reloc_sparc_lo;
- case SPII::MO_HI: return SP::reloc_sparc_hi;
- case SPII::MO_H44:
- case SPII::MO_M44:
- case SPII::MO_L44:
- case SPII::MO_HH:
- case SPII::MO_HM: assert(0 && "FIXME: Implement Medium/Large code model.");
+ case SparcMCExpr::VK_Sparc_None: break;
+ case SparcMCExpr::VK_Sparc_LO: return SP::reloc_sparc_lo;
+ case SparcMCExpr::VK_Sparc_HI: return SP::reloc_sparc_hi;
+ case SparcMCExpr::VK_Sparc_H44: return SP::reloc_sparc_h44;
+ case SparcMCExpr::VK_Sparc_M44: return SP::reloc_sparc_m44;
+ case SparcMCExpr::VK_Sparc_L44: return SP::reloc_sparc_l44;
+ case SparcMCExpr::VK_Sparc_HH: return SP::reloc_sparc_hh;
+ case SparcMCExpr::VK_Sparc_HM: return SP::reloc_sparc_hm;
}
unsigned Opc = MI.getOpcode();
diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 64625f7..abe2de6 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -13,10 +13,11 @@
//===----------------------------------------------------------------------===//
#include "SparcISelLowering.h"
+#include "MCTargetDesc/SparcMCExpr.h"
#include "SparcMachineFunctionInfo.h"
#include "SparcRegisterInfo.h"
#include "SparcTargetMachine.h"
-#include "MCTargetDesc/SparcBaseInfo.h"
+#include "SparcTargetObjectFile.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -80,11 +81,14 @@ static bool CC_Sparc_Assign_f64(unsigned &ValNo, MVT &ValVT,
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 +100,9 @@ static bool CC_Sparc64_Full(unsigned &ValNo, MVT &ValVT,
else if (LocVT == MVT::f32 && Offset < 16*8)
// Promote floats to %f1, %f3, ...
Reg = SP::F1 + Offset/4;
+ else if (LocVT == MVT::f128 && Offset < 16*8)
+ // Promote long doubles to %q0-%q28. (Which LLVM calls Q0-Q7).
+ Reg = SP::Q0 + Offset/16;
// Promote to register when possible, otherwise use the stack slot.
if (Reg) {
@@ -248,7 +255,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);
@@ -888,10 +895,12 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
// If the callee is a GlobalAddress node (quite common, every direct call is)
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
// Likewise ExternalSymbol -> TargetExternalSymbol.
+ unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
+ ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
+ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32, 0, TF);
else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
- Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
+ Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32, TF);
// Returns a chain & a flag for retval copy to use
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
@@ -998,9 +1007,10 @@ static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs,
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 +1020,25 @@ static void fixupVariableFloatArgs(SmallVectorImpl<CCValAssign> &ArgLocs,
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 +1114,46 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
break;
case CCValAssign::BCvt:
- Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
+ // fixupVariableFloatArgs() may create bitcasts from f128 to i128. But
+ // SPARC does not support i128 natively. Lower it into two i64, see below.
+ if (!VA.needsCustom() || VA.getValVT() != MVT::f128
+ || VA.getLocVT() != MVT::i128)
+ Arg = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Arg);
break;
}
if (VA.isRegLoc()) {
+ if (VA.needsCustom() && VA.getValVT() == MVT::f128
+ && VA.getLocVT() == MVT::i128) {
+ // Store and reload into the interger register reg and reg+1.
+ unsigned Offset = 8 * (VA.getLocReg() - SP::I0);
+ unsigned StackOffset = Offset + Subtarget->getStackPointerBias() + 128;
+ SDValue StackPtr = DAG.getRegister(SP::O6, getPointerTy());
+ SDValue HiPtrOff = DAG.getIntPtrConstant(StackOffset);
+ HiPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
+ HiPtrOff);
+ SDValue LoPtrOff = DAG.getIntPtrConstant(StackOffset + 8);
+ LoPtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr,
+ LoPtrOff);
+
+ // Store to %sp+BIAS+128+Offset
+ SDValue Store = DAG.getStore(Chain, DL, Arg, HiPtrOff,
+ MachinePointerInfo(),
+ false, false, 0);
+ // Load into Reg and Reg+1
+ SDValue Hi64 = DAG.getLoad(MVT::i64, DL, Store, HiPtrOff,
+ MachinePointerInfo(),
+ false, false, false, 0);
+ SDValue Lo64 = DAG.getLoad(MVT::i64, DL, Store, LoPtrOff,
+ MachinePointerInfo(),
+ false, false, false, 0);
+ RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()),
+ Hi64));
+ RegsToPass.push_back(std::make_pair(toCallerWindow(VA.getLocReg()+1),
+ Lo64));
+ continue;
+ }
+
// The custom bit on an i32 return value indicates that it should be
// passed in the high bits of the register.
if (VA.getValVT() == MVT::i32 && VA.needsCustom()) {
@@ -1156,10 +1211,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
// Likewise ExternalSymbol -> TargetExternalSymbol.
SDValue Callee = CLI.Callee;
bool hasReturnsTwice = hasReturnsTwiceAttr(DAG, Callee, CLI.CS);
+ unsigned TF = ((getTargetMachine().getRelocationModel() == Reloc::PIC_)
+ ? SparcMCExpr::VK_Sparc_WPLT30 : 0);
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy());
+ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0,
+ TF);
else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
- Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy());
+ Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy(), TF);
// Build the operands for the call instruction itself.
SmallVector<SDValue, 8> Ops;
@@ -1200,7 +1258,13 @@ SparcTargetLowering::LowerCall_64(TargetLowering::CallLoweringInfo &CLI,
SmallVector<CCValAssign, 16> RVLocs;
CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(),
DAG.getTarget(), RVLocs, *DAG.getContext());
- RVInfo.AnalyzeCallResult(CLI.Ins, CC_Sparc64);
+
+ // Set inreg flag manually for codegen generated library calls that
+ // return float.
+ if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && CLI.CS == 0)
+ CLI.Ins[0].Flags.setInReg();
+
+ RVInfo.AnalyzeCallResult(CLI.Ins, RetCC_Sparc64);
// Copy all of the result registers out of their specified physreg.
for (unsigned i = 0; i != RVLocs.size(); ++i) {
@@ -1303,7 +1367,7 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
}
SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
- : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
+ : TargetLowering(TM, new SparcELFTargetObjectFile()) {
Subtarget = &TM.getSubtarget<SparcSubtarget>();
// Set up the register classes.
@@ -1403,7 +1467,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
- setOperationAction(ISD::CTPOP, MVT::i64, Legal);
+ setOperationAction(ISD::CTPOP, MVT::i64,
+ Subtarget->usePopc() ? Legal : Expand);
setOperationAction(ISD::CTTZ , MVT::i64, Expand);
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
setOperationAction(ISD::CTLZ , MVT::i64, Expand);
@@ -1414,9 +1479,29 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
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, Legal);
+ setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom);
+ setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Custom);
+ }
if (!Subtarget->isV9()) {
// SparcV8 does not have FNEGD and FABSD.
@@ -1439,7 +1524,6 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
setOperationAction(ISD::FREM , MVT::f32, Expand);
setOperationAction(ISD::FMA , MVT::f32, Expand);
- setOperationAction(ISD::CTPOP, MVT::i32, Expand);
setOperationAction(ISD::CTTZ , MVT::i32, Expand);
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
setOperationAction(ISD::CTLZ , MVT::i32, Expand);
@@ -1467,6 +1551,13 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
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);
+
+ 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.
@@ -1474,6 +1565,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
// 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);
@@ -1486,8 +1579,8 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
setStackPointerRegisterToSaveRestore(SP::O6);
- if (Subtarget->isV9())
- setOperationAction(ISD::CTPOP, MVT::i32, Legal);
+ setOperationAction(ISD::CTPOP, MVT::i32,
+ Subtarget->usePopc() ? Legal : Expand);
if (Subtarget->isV9() && Subtarget->hasHardQuad()) {
setOperationAction(ISD::LOAD, MVT::f128, Legal);
@@ -1714,7 +1807,8 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const {
// Handle PIC mode first.
if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
// This is the pic32 code model, the GOT is known to be smaller than 4GB.
- SDValue HiLo = makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
+ SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22,
+ SparcMCExpr::VK_Sparc_GOT10, DAG);
SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT);
SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo);
// GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this
@@ -1729,23 +1823,26 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const {
switch(getTargetMachine().getCodeModel()) {
default:
llvm_unreachable("Unsupported absolute code model");
- case CodeModel::JITDefault:
case CodeModel::Small:
// abs32.
- return makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
+ return makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
+ SparcMCExpr::VK_Sparc_LO, DAG);
case CodeModel::Medium: {
// abs44.
- SDValue H44 = makeHiLoPair(Op, SPII::MO_H44, SPII::MO_M44, DAG);
+ SDValue H44 = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_H44,
+ SparcMCExpr::VK_Sparc_M44, DAG);
H44 = DAG.getNode(ISD::SHL, DL, VT, H44, DAG.getConstant(12, MVT::i32));
- SDValue L44 = withTargetFlags(Op, SPII::MO_L44, DAG);
+ SDValue L44 = withTargetFlags(Op, SparcMCExpr::VK_Sparc_L44, DAG);
L44 = DAG.getNode(SPISD::Lo, DL, VT, L44);
return DAG.getNode(ISD::ADD, DL, VT, H44, L44);
}
case CodeModel::Large: {
// abs64.
- SDValue Hi = makeHiLoPair(Op, SPII::MO_HH, SPII::MO_HM, DAG);
+ SDValue Hi = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HH,
+ SparcMCExpr::VK_Sparc_HM, DAG);
Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, DAG.getConstant(32, MVT::i32));
- SDValue Lo = makeHiLoPair(Op, SPII::MO_HI, SPII::MO_LO, DAG);
+ SDValue Lo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_HI,
+ SparcMCExpr::VK_Sparc_LO, DAG);
return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
}
}
@@ -1777,14 +1874,18 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op,
TLSModel::Model model = getTargetMachine().getTLSModel(GV);
if (model == TLSModel::GeneralDynamic || model == TLSModel::LocalDynamic) {
- unsigned HiTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_HI22
- : SPII::MO_TLS_LDM_HI22);
- unsigned LoTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_LO10
- : SPII::MO_TLS_LDM_LO10);
- unsigned addTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_ADD
- : SPII::MO_TLS_LDM_ADD);
- unsigned callTF = ((model == TLSModel::GeneralDynamic)? SPII::MO_TLS_GD_CALL
- : SPII::MO_TLS_LDM_CALL);
+ unsigned HiTF = ((model == TLSModel::GeneralDynamic)
+ ? SparcMCExpr::VK_Sparc_TLS_GD_HI22
+ : SparcMCExpr::VK_Sparc_TLS_LDM_HI22);
+ unsigned LoTF = ((model == TLSModel::GeneralDynamic)
+ ? SparcMCExpr::VK_Sparc_TLS_GD_LO10
+ : SparcMCExpr::VK_Sparc_TLS_LDM_LO10);
+ unsigned addTF = ((model == TLSModel::GeneralDynamic)
+ ? SparcMCExpr::VK_Sparc_TLS_GD_ADD
+ : SparcMCExpr::VK_Sparc_TLS_LDM_ADD);
+ unsigned callTF = ((model == TLSModel::GeneralDynamic)
+ ? SparcMCExpr::VK_Sparc_TLS_GD_CALL
+ : SparcMCExpr::VK_Sparc_TLS_LDM_CALL);
SDValue HiLo = makeHiLoPair(Op, HiTF, LoTF, DAG);
SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
@@ -1822,17 +1923,17 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op,
return Ret;
SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
- withTargetFlags(Op, SPII::MO_TLS_LDO_HIX22, DAG));
+ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_HIX22, DAG));
SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
- withTargetFlags(Op, SPII::MO_TLS_LDO_LOX10, DAG));
+ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_LOX10, DAG));
HiLo = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT, Ret, HiLo,
- withTargetFlags(Op, SPII::MO_TLS_LDO_ADD, DAG));
+ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LDO_ADD, DAG));
}
if (model == TLSModel::InitialExec) {
- unsigned ldTF = ((PtrVT == MVT::i64)? SPII::MO_TLS_IE_LDX
- : SPII::MO_TLS_IE_LD);
+ unsigned ldTF = ((PtrVT == MVT::i64)? SparcMCExpr::VK_Sparc_TLS_IE_LDX
+ : SparcMCExpr::VK_Sparc_TLS_IE_LD);
SDValue Base = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, PtrVT);
@@ -1842,21 +1943,23 @@ SDValue SparcTargetLowering::LowerGlobalTLSAddress(SDValue Op,
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,
withTargetFlags(Op, ldTF, DAG));
return DAG.getNode(SPISD::TLS_ADD, DL, PtrVT,
DAG.getRegister(SP::G7, PtrVT), Offset,
- withTargetFlags(Op, SPII::MO_TLS_IE_ADD, DAG));
+ withTargetFlags(Op,
+ SparcMCExpr::VK_Sparc_TLS_IE_ADD, DAG));
}
assert(model == TLSModel::LocalExec);
SDValue Hi = DAG.getNode(SPISD::Hi, DL, PtrVT,
- withTargetFlags(Op, SPII::MO_TLS_LE_HIX22, DAG));
+ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_HIX22, DAG));
SDValue Lo = DAG.getNode(SPISD::Lo, DL, PtrVT,
- withTargetFlags(Op, SPII::MO_TLS_LE_LOX10, DAG));
+ withTargetFlags(Op, SparcMCExpr::VK_Sparc_TLS_LE_LOX10, DAG));
SDValue Offset = DAG.getNode(ISD::XOR, DL, PtrVT, Hi, Lo);
return DAG.getNode(ISD::ADD, DL, PtrVT,
@@ -2334,39 +2437,57 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) {
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);
EVT VT = Op.getValueType();
SDLoc dl(Op);
unsigned FrameReg = SP::I6;
-
- uint64_t depth = Op.getConstantOperandVal(0);
+ unsigned stackBias = Subtarget->getStackPointerBias();
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);
-
- 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);
- }
+ if (Subtarget->is64Bit())
+ FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
+ DAG.getIntPtrConstant(stackBias));
+ return FrameAddr;
}
+
+ // flush first to make sure the windowed registers' values are in stack
+ SDValue Chain = getFLUSHW(Op, DAG);
+ FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
+
+ unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
+
+ while (depth--) {
+ SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
+ DAG.getIntPtrConstant(Offset));
+ FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo(),
+ false, false, false, 0);
+ }
+ if (Subtarget->is64Bit())
+ FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
+ DAG.getIntPtrConstant(stackBias));
return FrameAddr;
}
+
+static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
+ const SparcSubtarget *Subtarget) {
+
+ uint64_t depth = Op.getConstantOperandVal(0);
+
+ return getFRAMEADDR(depth, Op, DAG, Subtarget);
+
+}
+
static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
- const SparcTargetLowering &TLI) {
+ const SparcTargetLowering &TLI,
+ const SparcSubtarget *Subtarget) {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MFI->setReturnAddressIsTaken(true);
@@ -2380,25 +2501,20 @@ static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
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);
-
- // 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);
-
- 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);
- }
+ return RetAddr;
}
+
+ // Need frame address to find return address of the caller.
+ SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget);
+
+ 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;
}
@@ -2527,24 +2643,16 @@ static SDValue LowerF128Store(SDValue Op, SelectionDAG &DAG) {
&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);
@@ -2555,7 +2663,7 @@ static SDValue LowerFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
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);
@@ -2615,18 +2723,76 @@ static SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) {
return DAG.getMergeValues(Ops, 2, dl);
}
+// Custom lower UMULO/SMULO for SPARC. This code is similar to ExpandNode()
+// in LegalizeDAG.cpp except the order of arguments to the library function.
+static SDValue LowerUMULO_SMULO(SDValue Op, SelectionDAG &DAG,
+ const SparcTargetLowering &TLI)
+{
+ unsigned opcode = Op.getOpcode();
+ assert((opcode == ISD::UMULO || opcode == ISD::SMULO) && "Invalid Opcode.");
+
+ bool isSigned = (opcode == ISD::SMULO);
+ EVT VT = MVT::i64;
+ EVT WideVT = MVT::i128;
+ SDLoc dl(Op);
+ SDValue LHS = Op.getOperand(0);
+
+ if (LHS.getValueType() != VT)
+ return Op;
+
+ SDValue ShiftAmt = DAG.getConstant(63, VT);
+
+ SDValue RHS = Op.getOperand(1);
+ SDValue HiLHS = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt);
+ SDValue HiRHS = DAG.getNode(ISD::SRA, dl, MVT::i64, RHS, ShiftAmt);
+ SDValue Args[] = { HiLHS, LHS, HiRHS, RHS };
+
+ SDValue MulResult = TLI.makeLibCall(DAG,
+ RTLIB::MUL_I128, WideVT,
+ Args, 4, isSigned, dl).first;
+ SDValue BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
+ MulResult, DAG.getIntPtrConstant(0));
+ SDValue TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT,
+ MulResult, DAG.getIntPtrConstant(1));
+ if (isSigned) {
+ SDValue Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, ShiftAmt);
+ TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, Tmp1, ISD::SETNE);
+ } else {
+ TopHalf = DAG.getSetCC(dl, MVT::i32, TopHalf, DAG.getConstant(0, VT),
+ ISD::SETNE);
+ }
+ // MulResult is a node with an illegal type. Because such things are not
+ // generally permitted during this phase of legalization, delete the
+ // node. The above EXTRACT_ELEMENT nodes should have been folded.
+ DAG.DeleteNode(MulResult.getNode());
+
+ SDValue Ops[2] = { BottomHalf, TopHalf } ;
+ return DAG.getMergeValues(Ops, 2, dl);
+}
+
+static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {
+ // Monotonic load/stores are legal.
+ if (cast<AtomicSDNode>(Op)->getOrdering() <= Monotonic)
+ return Op;
+
+ // Otherwise, expand with a fence.
+ return SDValue();
+}
+
+
SDValue SparcTargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
bool hasHardQuad = Subtarget->hasHardQuad();
- bool is64Bit = Subtarget->is64Bit();
bool isV9 = Subtarget->isV9();
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);
@@ -2660,42 +2826,91 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
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:
case ISD::ADDE:
case ISD::SUBC:
case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
+ case ISD::UMULO:
+ case ISD::SMULO: return LowerUMULO_SMULO(Op, DAG, *this);
+ case ISD::ATOMIC_LOAD:
+ case ISD::ATOMIC_STORE: return LowerATOMIC_LOAD_STORE(Op, DAG);
}
}
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:
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_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:
+ return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_G);
+ case SP::ATOMIC_LOAD_MIN_32:
+ return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LE);
+ case SP::ATOMIC_LOAD_MIN_64:
+ return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LE);
+ case SP::ATOMIC_LOAD_UMAX_32:
+ return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_GU);
+ case SP::ATOMIC_LOAD_UMAX_64:
+ return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_GU);
+ case SP::ATOMIC_LOAD_UMIN_32:
+ return expandAtomicRMW(MI, BB, SP::MOVICCrr, SPCC::ICC_LEU);
+ case SP::ATOMIC_LOAD_UMIN_64:
+ return expandAtomicRMW(MI, BB, SP::MOVXCCrr, SPCC::ICC_LEU);
}
+}
- CC = (SPCC::CondCodes)MI->getOperand(3).getImm();
+MachineBasicBlock*
+SparcTargetLowering::expandSelectCC(MachineInstr *MI,
+ MachineBasicBlock *BB,
+ unsigned BROpcode) const {
+ const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
+ DebugLoc dl = MI->getDebugLoc();
+ unsigned CC = (SPCC::CondCodes)MI->getOperand(3).getImm();
// To "insert" a SELECT_CC instruction, we actually have to insert the diamond
// control-flow pattern. The incoming instruction knows the destination vreg
@@ -2749,6 +2964,101 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
return BB;
}
+MachineBasicBlock*
+SparcTargetLowering::expandAtomicRMW(MachineInstr *MI,
+ MachineBasicBlock *MBB,
+ unsigned Opcode,
+ unsigned CondCode) const {
+ const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
+ MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
+ DebugLoc DL = MI->getDebugLoc();
+
+ // MI is an atomic read-modify-write instruction of the form:
+ //
+ // rd = atomicrmw<op> addr, rs2
+ //
+ // All three operands are registers.
+ unsigned DestReg = MI->getOperand(0).getReg();
+ unsigned AddrReg = MI->getOperand(1).getReg();
+ unsigned Rs2Reg = MI->getOperand(2).getReg();
+
+ // SelectionDAG has already inserted memory barriers before and after MI, so
+ // we simply have to implement the operatiuon in terms of compare-and-swap.
+ //
+ // %val0 = load %addr
+ // loop:
+ // %val = phi %val0, %dest
+ // %upd = op %val, %rs2
+ // %dest = cas %addr, %val, %upd
+ // cmp %val, %dest
+ // bne loop
+ // done:
+ //
+ bool is64Bit = SP::I64RegsRegClass.hasSubClassEq(MRI.getRegClass(DestReg));
+ const TargetRegisterClass *ValueRC =
+ is64Bit ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
+ unsigned Val0Reg = MRI.createVirtualRegister(ValueRC);
+
+ BuildMI(*MBB, MI, DL, TII.get(is64Bit ? SP::LDXri : SP::LDri), Val0Reg)
+ .addReg(AddrReg).addImm(0);
+
+ // Split the basic block MBB before MI and insert the loop block in the hole.
+ MachineFunction::iterator MFI = MBB;
+ const BasicBlock *LLVM_BB = MBB->getBasicBlock();
+ MachineFunction *MF = MBB->getParent();
+ MachineBasicBlock *LoopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *DoneMBB = MF->CreateMachineBasicBlock(LLVM_BB);
+ ++MFI;
+ MF->insert(MFI, LoopMBB);
+ MF->insert(MFI, DoneMBB);
+
+ // Move MI and following instructions to DoneMBB.
+ DoneMBB->splice(DoneMBB->begin(), MBB, MI, MBB->end());
+ DoneMBB->transferSuccessorsAndUpdatePHIs(MBB);
+
+ // Connect the CFG again.
+ MBB->addSuccessor(LoopMBB);
+ LoopMBB->addSuccessor(LoopMBB);
+ LoopMBB->addSuccessor(DoneMBB);
+
+ // Build the loop block.
+ unsigned ValReg = MRI.createVirtualRegister(ValueRC);
+ // 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)
+ .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 if (Opcode) {
+ BuildMI(LoopMBB, DL, TII.get(Opcode), UpdReg)
+ .addReg(ValReg).addReg(Rs2Reg);
+ }
+
+ if (MI->getOpcode() == SP::ATOMIC_LOAD_NAND_32 ||
+ MI->getOpcode() == SP::ATOMIC_LOAD_NAND_64) {
+ unsigned TmpReg = UpdReg;
+ UpdReg = MRI.createVirtualRegister(ValueRC);
+ BuildMI(LoopMBB, DL, TII.get(SP::XORri), UpdReg).addReg(TmpReg).addImm(-1);
+ }
+
+ BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::CASXrr : SP::CASrr), DestReg)
+ .addReg(AddrReg).addReg(ValReg).addReg(UpdReg)
+ .setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
+ BuildMI(LoopMBB, DL, TII.get(SP::CMPrr)).addReg(ValReg).addReg(DestReg);
+ BuildMI(LoopMBB, DL, TII.get(is64Bit ? SP::BPXCC : SP::BCOND))
+ .addMBB(LoopMBB).addImm(SPCC::ICC_NE);
+
+ MI->eraseFromParent();
+ return DoneMBB;
+}
+
//===----------------------------------------------------------------------===//
// Sparc Inline Assembly Support
//===----------------------------------------------------------------------===//
@@ -2761,12 +3071,72 @@ SparcTargetLowering::getConstraintType(const std::string &Constraint) const {
switch (Constraint[0]) {
default: break;
case 'r': return C_RegisterClass;
+ case 'I': // SIMM13
+ return C_Other;
}
}
return TargetLowering::getConstraintType(Constraint);
}
+TargetLowering::ConstraintWeight SparcTargetLowering::
+getSingleConstraintMatchWeight(AsmOperandInfo &info,
+ const char *constraint) const {
+ ConstraintWeight weight = CW_Invalid;
+ Value *CallOperandVal = info.CallOperandVal;
+ // If we don't have a value, we can't do a match,
+ // but allow it at the lowest weight.
+ if (CallOperandVal == NULL)
+ return CW_Default;
+
+ // Look at the constraint type.
+ switch (*constraint) {
+ default:
+ weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
+ break;
+ case 'I': // SIMM13
+ if (ConstantInt *C = dyn_cast<ConstantInt>(info.CallOperandVal)) {
+ if (isInt<13>(C->getSExtValue()))
+ weight = CW_Constant;
+ }
+ break;
+ }
+ return weight;
+}
+
+/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
+/// vector. If it is invalid, don't add anything to Ops.
+void SparcTargetLowering::
+LowerAsmOperandForConstraint(SDValue Op,
+ std::string &Constraint,
+ std::vector<SDValue> &Ops,
+ SelectionDAG &DAG) const {
+ SDValue Result(0, 0);
+
+ // Only support length 1 constraints for now.
+ if (Constraint.length() > 1)
+ return;
+
+ char ConstraintLetter = Constraint[0];
+ switch (ConstraintLetter) {
+ default: break;
+ case 'I':
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
+ if (isInt<13>(C->getSExtValue())) {
+ Result = DAG.getTargetConstant(C->getSExtValue(), Op.getValueType());
+ break;
+ }
+ return;
+ }
+ }
+
+ if (Result.getNode()) {
+ Ops.push_back(Result);
+ return;
+ }
+ TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
+}
+
std::pair<unsigned, const TargetRegisterClass*>
SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
MVT VT) const {
@@ -2775,6 +3145,26 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
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);
diff --git a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h b/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h
index 2659fc8..f7b45d0 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcISelLowering.h
+++ b/contrib/llvm/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;
@@ -158,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
diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td b/contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td
index 8656de5..a5b48f9 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td
+++ b/contrib/llvm/lib/Target/Sparc/SparcInstr64Bit.td
@@ -141,41 +141,43 @@ def : Pat<(i64 imm:$val),
let Predicates = [Is64Bit] in {
// Register-register instructions.
-
-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 : 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)>;
-
-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)>;
-
-// 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)>;
+let isCodeGenOnly = 1 in {
+defm ANDX : F3_12<"and", 0b000001, and, I64Regs, i64, i64imm>;
+defm ORX : F3_12<"or", 0b000010, or, I64Regs, i64, i64imm>;
+defm XORX : F3_12<"xor", 0b000011, xor, I64Regs, i64, i64imm>;
+
+def 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)))]>;
+
+defm ADDX : F3_12<"add", 0b000000, add, I64Regs, i64, i64imm>;
+defm SUBX : F3_12<"sub", 0b000100, sub, I64Regs, i64, i64imm>;
+
+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))]>;
// "LEA" form of add
def LEAX_ADDri : F3_2<2, 0b000000,
(outs I64Regs:$dst), (ins MEMri:$addr),
"add ${addr:arith}, $dst",
[(set iPTR:$dst, ADDRri:$addr)]>;
+}
+
+def : Pat<(SPcmpicc i64:$a, i64:$b), (CMPrr $a, $b)>;
+def : Pat<(SPcmpicc i64:$a, (i64 simm13:$b)), (CMPri $a, (as_i32imm $b))>;
+def : Pat<(ctpop i64:$src), (POPCrr $src)>;
} // Predicates = [Is64Bit]
@@ -191,9 +193,9 @@ 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 {
@@ -202,18 +204,18 @@ 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),
"udivx $rs1, $rs2, $rd",
[(set i64:$rd, (udiv i64:$rs1, i64:$rs2))]>;
def UDIVXri : F3_2<2, 0b001101,
- (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$i),
- "udivx $rs1, $i, $rd",
- [(set i64:$rd, (udiv i64:$rs1, (i64 simm13:$i)))]>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i64imm:$simm13),
+ "udivx $rs1, $simm13, $rd",
+ [(set i64:$rd, (udiv i64:$rs1, (i64 simm13:$simm13)))]>;
} // hasSideEffects = 1
} // Predicates = [Is64Bit]
@@ -233,15 +235,9 @@ 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))]>;
-let mayLoad = 1 in
+defm LDX : Load<"ldx", 0b001011, load, I64Regs, i64>;
+
+let mayLoad = 1, isCodeGenOnly = 1, isAsmParserOnly = 1 in
def TLS_LDXrr : F3_1<3, 0b001011,
(outs IntRegs:$dst), (ins MEMrr:$addr, TLSSym:$sym),
"ldx [$addr], $dst, $sym",
@@ -274,24 +270,10 @@ def : Pat<(i64 (extloadi32 ADDRrr:$addr)), (LDrr ADDRrr:$addr)>;
def : Pat<(i64 (extloadi32 ADDRri:$addr)), (LDri ADDRri:$addr)>;
// Sign-extending load of i32 into i64 is a new SPARC v9 instruction.
-def LDSWrr : F3_1<3, 0b001011,
- (outs I64Regs:$dst), (ins MEMrr:$addr),
- "ldsw [$addr], $dst",
- [(set i64:$dst, (sextloadi32 ADDRrr:$addr))]>;
-def LDSWri : F3_2<3, 0b001011,
- (outs I64Regs:$dst), (ins MEMri:$addr),
- "ldsw [$addr], $dst",
- [(set i64:$dst, (sextloadi32 ADDRri:$addr))]>;
+defm LDSW : Load<"ldsw", 0b001000, sextloadi32, I64Regs, i64>;
// 64-bit stores.
-def STXrr : F3_1<3, 0b001110,
- (outs), (ins MEMrr:$addr, I64Regs:$src),
- "stx $src, [$addr]",
- [(store i64:$src, ADDRrr:$addr)]>;
-def STXri : F3_2<3, 0b001110,
- (outs), (ins MEMri:$addr, I64Regs:$src),
- "stx $src, [$addr]",
- [(store i64:$src, ADDRri:$addr)]>;
+defm STX : Store<"stx", 0b001110, store, I64Regs, i64>;
// Truncating stores from i64 are identical to the i32 stores.
def : Pat<(truncstorei8 i64:$src, ADDRrr:$addr), (STBrr ADDRrr:$addr, $src)>;
@@ -311,6 +293,15 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADDRri:$dst, (i64 G0))>;
//===----------------------------------------------------------------------===//
// 64-bit Conditionals.
//===----------------------------------------------------------------------===//
+
+// Conditional branch class on %xcc:
+class XBranchSP<dag ins, string asmstr, list<dag> pattern>
+ : F2_3<0b001, 0b10, (outs), ins, asmstr, pattern> {
+ let isBranch = 1;
+ let isTerminator = 1;
+ let hasDelaySlot = 1;
+}
+
//
// Flag-setting instructions like subcc and addcc set both icc and xcc flags.
// The icc flags correspond to the 32-bit result, and the xcc are for the
@@ -322,32 +313,42 @@ def : Pat<(store (i64 0), ADDRri:$dst), (STXri ADDRri:$dst, (i64 G0))>;
let Predicates = [Is64Bit] in {
let Uses = [ICC] in
-def BPXCC : BranchSP<(ins brtarget:$imm22, CCOp:$cond),
- "b$cond %xcc, $imm22",
- [(SPbrxcc bb:$imm22, imm:$cond)]>;
+def BPXCC : XBranchSP<(ins brtarget:$imm19, CCOp:$cond),
+ "b$cond %xcc, $imm19",
+ [(SPbrxcc bb:$imm19, imm:$cond)]>;
// Conditional moves on %xcc.
let Uses = [ICC], Constraints = "$f = $rd" in {
-def MOVXCCrr : Pseudo<(outs IntRegs:$rd),
+let cc = 0b110 in {
+def MOVXCCrr : F4_1<0b101100, (outs IntRegs:$rd),
(ins IntRegs:$rs2, IntRegs:$f, CCOp:$cond),
"mov$cond %xcc, $rs2, $rd",
[(set i32:$rd,
(SPselectxcc i32:$rs2, i32:$f, imm:$cond))]>;
-def MOVXCCri : Pseudo<(outs IntRegs:$rd),
- (ins i32imm:$i, IntRegs:$f, CCOp:$cond),
- "mov$cond %xcc, $i, $rd",
+def MOVXCCri : F4_2<0b101100, (outs IntRegs:$rd),
+ (ins i32imm:$simm11, IntRegs:$f, CCOp:$cond),
+ "mov$cond %xcc, $simm11, $rd",
[(set i32:$rd,
- (SPselectxcc simm11:$i, i32:$f, imm:$cond))]>;
-def FMOVS_XCC : Pseudo<(outs FPRegs:$rd),
+ (SPselectxcc simm11:$simm11, i32:$f, imm:$cond))]>;
+} // cc
+
+let opf_cc = 0b110 in {
+def FMOVS_XCC : F4_3<0b110101, 0b000001, (outs FPRegs:$rd),
(ins FPRegs:$rs2, FPRegs:$f, CCOp:$cond),
"fmovs$cond %xcc, $rs2, $rd",
[(set f32:$rd,
(SPselectxcc f32:$rs2, f32:$f, imm:$cond))]>;
-def FMOVD_XCC : Pseudo<(outs DFPRegs:$rd),
+def FMOVD_XCC : F4_3<0b110101, 0b000010, (outs DFPRegs:$rd),
(ins DFPRegs:$rs2, DFPRegs:$f, CCOp:$cond),
"fmovd$cond %xcc, $rs2, $rd",
[(set f64:$rd,
(SPselectxcc f64:$rs2, f64:$f, imm:$cond))]>;
+def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd),
+ (ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond),
+ "fmovq$cond %xcc, $rs2, $rd",
+ [(set f128:$rd,
+ (SPselectxcc f128:$rs2, f128:$f, imm:$cond))]>;
+} // opf_cc
} // Uses, Constraints
//===----------------------------------------------------------------------===//
@@ -357,31 +358,31 @@ def FMOVD_XCC : Pseudo<(outs DFPRegs:$rd),
let Predicates = [Is64Bit] in {
def FXTOS : F3_3u<2, 0b110100, 0b010000100,
- (outs FPRegs:$dst), (ins DFPRegs:$src),
- "fxtos $src, $dst",
- [(set FPRegs:$dst, (SPxtof DFPRegs:$src))]>;
+ (outs FPRegs:$rd), (ins DFPRegs:$rs2),
+ "fxtos $rs2, $rd",
+ [(set FPRegs:$rd, (SPxtof DFPRegs:$rs2))]>;
def FXTOD : F3_3u<2, 0b110100, 0b010001000,
- (outs DFPRegs:$dst), (ins DFPRegs:$src),
- "fxtod $src, $dst",
- [(set DFPRegs:$dst, (SPxtof DFPRegs:$src))]>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
+ "fxtod $rs2, $rd",
+ [(set DFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>;
def FXTOQ : F3_3u<2, 0b110100, 0b010001100,
- (outs QFPRegs:$dst), (ins DFPRegs:$src),
- "fxtoq $src, $dst",
- [(set QFPRegs:$dst, (SPxtof DFPRegs:$src))]>,
+ (outs QFPRegs:$rd), (ins DFPRegs:$rs2),
+ "fxtoq $rs2, $rd",
+ [(set QFPRegs:$rd, (SPxtof DFPRegs:$rs2))]>,
Requires<[HasHardQuad]>;
def FSTOX : F3_3u<2, 0b110100, 0b010000001,
- (outs DFPRegs:$dst), (ins FPRegs:$src),
- "fstox $src, $dst",
- [(set DFPRegs:$dst, (SPftox FPRegs:$src))]>;
+ (outs DFPRegs:$rd), (ins FPRegs:$rs2),
+ "fstox $rs2, $rd",
+ [(set DFPRegs:$rd, (SPftox FPRegs:$rs2))]>;
def FDTOX : F3_3u<2, 0b110100, 0b010000010,
- (outs DFPRegs:$dst), (ins DFPRegs:$src),
- "fdtox $src, $dst",
- [(set DFPRegs:$dst, (SPftox DFPRegs:$src))]>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
+ "fdtox $rs2, $rd",
+ [(set DFPRegs:$rd, (SPftox DFPRegs:$rs2))]>;
def FQTOX : F3_3u<2, 0b110100, 0b010000011,
- (outs DFPRegs:$dst), (ins QFPRegs:$src),
- "fqtox $src, $dst",
- [(set DFPRegs:$dst, (SPftox QFPRegs:$src))]>,
+ (outs DFPRegs:$rd), (ins QFPRegs:$rs2),
+ "fqtox $rs2, $rd",
+ [(set DFPRegs:$rd, (SPftox QFPRegs:$rs2))]>,
Requires<[HasHardQuad]>;
} // Predicates = [Is64Bit]
@@ -402,3 +403,97 @@ def : Pat<(SPselectfcc (i64 simm11:$t), i64:$f, imm:$cond),
(MOVFCCri (as_i32imm $t), $f, imm:$cond)>;
} // Predicates = [Is64Bit]
+
+
+// 64 bit SETHI
+let Predicates = [Is64Bit], isCodeGenOnly = 1 in {
+def SETHIXi : F2_1<0b100,
+ (outs IntRegs:$rd), (ins i64imm:$imm22),
+ "sethi $imm22, $rd",
+ [(set i64:$rd, SETHIimm:$imm22)]>;
+}
+
+// ATOMICS.
+let Predicates = [Is64Bit], Constraints = "$swap = $rd" in {
+ def CASXrr: F3_1_asi<3, 0b111110, 0b10000000,
+ (outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2,
+ I64Regs:$swap),
+ "casx [$rs1], $rs2, $rd",
+ [(set i64:$rd,
+ (atomic_cmp_swap i64:$rs1, i64:$rs2, i64:$swap))]>;
+
+} // Predicates = [Is64Bit], Constraints = ...
+
+let Predicates = [Is64Bit] in {
+
+def : Pat<(atomic_fence imm, imm), (MEMBARi 0xf)>;
+
+// atomic_load_64 addr -> load addr
+def : Pat<(i64 (atomic_load ADDRrr:$src)), (LDXrr ADDRrr:$src)>;
+def : Pat<(i64 (atomic_load ADDRri:$src)), (LDXri ADDRri:$src)>;
+
+// atomic_store_64 val, addr -> store val, addr
+def : Pat<(atomic_store ADDRrr:$dst, i64:$val), (STXrr ADDRrr:$dst, $val)>;
+def : Pat<(atomic_store ADDRri:$dst, i64:$val), (STXri ADDRri:$dst, $val)>;
+
+} // Predicates = [Is64Bit]
+
+let usesCustomInserter = 1, hasCtrlDep = 1, mayLoad = 1, mayStore = 1,
+ Defs = [ICC] in
+multiclass AtomicRMW<SDPatternOperator op32, SDPatternOperator op64> {
+
+ def _32 : Pseudo<(outs IntRegs:$rd),
+ (ins ptr_rc:$addr, IntRegs:$rs2), "",
+ [(set i32:$rd, (op32 iPTR:$addr, i32:$rs2))]>;
+
+ let Predicates = [Is64Bit] in
+ def _64 : Pseudo<(outs I64Regs:$rd),
+ (ins ptr_rc:$addr, I64Regs:$rs2), "",
+ [(set i64:$rd, (op64 iPTR:$addr, i64:$rs2))]>;
+}
+
+defm ATOMIC_LOAD_ADD : AtomicRMW<atomic_load_add_32, atomic_load_add_64>;
+defm ATOMIC_LOAD_SUB : AtomicRMW<atomic_load_sub_32, atomic_load_sub_64>;
+defm ATOMIC_LOAD_AND : AtomicRMW<atomic_load_and_32, atomic_load_and_64>;
+defm ATOMIC_LOAD_OR : AtomicRMW<atomic_load_or_32, atomic_load_or_64>;
+defm ATOMIC_LOAD_XOR : AtomicRMW<atomic_load_xor_32, atomic_load_xor_64>;
+defm ATOMIC_LOAD_NAND : AtomicRMW<atomic_load_nand_32, atomic_load_nand_64>;
+defm ATOMIC_LOAD_MIN : AtomicRMW<atomic_load_min_32, atomic_load_min_64>;
+defm ATOMIC_LOAD_MAX : AtomicRMW<atomic_load_max_32, atomic_load_max_64>;
+defm ATOMIC_LOAD_UMIN : AtomicRMW<atomic_load_umin_32, atomic_load_umin_64>;
+defm ATOMIC_LOAD_UMAX : AtomicRMW<atomic_load_umax_32, atomic_load_umax_64>;
+
+// 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 {
+
+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)>;
+}
diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td b/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td
new file mode 100644
index 0000000..7242c59
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/SparcInstrAliases.td
@@ -0,0 +1,142 @@
+//===-- SparcInstrAliases.td - Instruction Aliases for Sparc Target -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains instruction aliases for Sparc.
+//===----------------------------------------------------------------------===//
+
+// Instruction aliases for conditional moves.
+
+// mov<cond> <ccreg> rs2, rd
+multiclass cond_mov_alias<string cond, int condVal, string ccreg,
+ Instruction movrr, Instruction movri,
+ Instruction fmovs, Instruction fmovd> {
+
+ // mov<cond> (%icc|%xcc|%fcc0), rs2, rd
+ def : InstAlias<!strconcat(!strconcat(!strconcat("mov", cond), ccreg),
+ ", $rs2, $rd"),
+ (movrr IntRegs:$rd, IntRegs:$rs2, condVal)>;
+
+ // mov<cond> (%icc|%xcc|%fcc0), simm11, rd
+ def : InstAlias<!strconcat(!strconcat(!strconcat("mov", cond), ccreg),
+ ", $simm11, $rd"),
+ (movri IntRegs:$rd, i32imm:$simm11, condVal)>;
+
+ // fmovs<cond> (%icc|%xcc|%fcc0), $rs2, $rd
+ def : InstAlias<!strconcat(!strconcat(!strconcat("fmovs", cond), ccreg),
+ ", $rs2, $rd"),
+ (fmovs FPRegs:$rd, FPRegs:$rs2, condVal)>;
+
+ // fmovd<cond> (%icc|%xcc|%fcc0), $rs2, $rd
+ def : InstAlias<!strconcat(!strconcat(!strconcat("fmovd", cond), ccreg),
+ ", $rs2, $rd"),
+ (fmovd DFPRegs:$rd, DFPRegs:$rs2, condVal)>;
+}
+
+
+// Instruction aliases for integer conditional branches and moves.
+multiclass int_cond_alias<string cond, int condVal> {
+
+ // b<cond> $imm
+ def : InstAlias<!strconcat(!strconcat("b", cond), " $imm"),
+ (BCOND brtarget:$imm, condVal)>;
+
+ // b<cond> %xcc, $imm
+ def : InstAlias<!strconcat(!strconcat("b", cond), " %xcc, $imm"),
+ (BPXCC brtarget:$imm, condVal)>, Requires<[Is64Bit]>;
+
+ defm : cond_mov_alias<cond, condVal, " %icc",
+ MOVICCrr, MOVICCri,
+ FMOVS_ICC, FMOVD_ICC>, Requires<[HasV9]>;
+
+ defm : cond_mov_alias<cond, condVal, " %xcc",
+ MOVXCCrr, MOVXCCri,
+ FMOVS_XCC, FMOVD_XCC>, Requires<[Is64Bit]>;
+
+ // fmovq<cond> (%icc|%xcc), $rs2, $rd
+ def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %icc, $rs2, $rd"),
+ (FMOVQ_ICC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
+ Requires<[HasV9, HasHardQuad]>;
+ def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %xcc, $rs2, $rd"),
+ (FMOVQ_XCC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
+ Requires<[Is64Bit, HasHardQuad]>;
+
+}
+
+
+// Instruction aliases for floating point conditional branches and moves.
+multiclass fp_cond_alias<string cond, int condVal> {
+
+ // fb<cond> $imm
+ def : InstAlias<!strconcat(!strconcat("fb", cond), " $imm"),
+ (FBCOND brtarget:$imm, condVal), 0>;
+
+ defm : cond_mov_alias<cond, condVal, " %fcc0",
+ MOVFCCrr, MOVFCCri,
+ FMOVS_FCC, FMOVD_FCC>, Requires<[HasV9]>;
+
+ // fmovq<cond> %fcc0, $rs2, $rd
+ def : InstAlias<!strconcat(!strconcat("fmovq", cond), " %fcc0, $rs2, $rd"),
+ (FMOVQ_ICC QFPRegs:$rd, QFPRegs:$rs2, condVal)>,
+ Requires<[HasV9, HasHardQuad]>;
+}
+
+defm : int_cond_alias<"a", 0b1000>;
+defm : int_cond_alias<"n", 0b0000>;
+defm : int_cond_alias<"ne", 0b1001>;
+defm : int_cond_alias<"e", 0b0001>;
+defm : int_cond_alias<"g", 0b1010>;
+defm : int_cond_alias<"le", 0b0010>;
+defm : int_cond_alias<"ge", 0b1011>;
+defm : int_cond_alias<"l", 0b0011>;
+defm : int_cond_alias<"gu", 0b1100>;
+defm : int_cond_alias<"leu", 0b0100>;
+defm : int_cond_alias<"cc", 0b1101>;
+defm : int_cond_alias<"cs", 0b0101>;
+defm : int_cond_alias<"pos", 0b1110>;
+defm : int_cond_alias<"neg", 0b0110>;
+defm : int_cond_alias<"vc", 0b1111>;
+defm : int_cond_alias<"vs", 0b0111>;
+
+defm : fp_cond_alias<"u", 0b0111>;
+defm : fp_cond_alias<"g", 0b0110>;
+defm : fp_cond_alias<"ug", 0b0101>;
+defm : fp_cond_alias<"l", 0b0100>;
+defm : fp_cond_alias<"ul", 0b0011>;
+defm : fp_cond_alias<"lg", 0b0010>;
+defm : fp_cond_alias<"ne", 0b0001>;
+defm : fp_cond_alias<"e", 0b1001>;
+defm : fp_cond_alias<"ue", 0b1010>;
+defm : fp_cond_alias<"ge", 0b1011>;
+defm : fp_cond_alias<"uge", 0b1100>;
+defm : fp_cond_alias<"le", 0b1101>;
+defm : fp_cond_alias<"ule", 0b1110>;
+defm : fp_cond_alias<"o", 0b1111>;
+
+
+// Instruction aliases for JMPL.
+
+// jmp addr -> jmpl addr, %g0
+def : InstAlias<"jmp $addr", (JMPLrr G0, MEMrr:$addr)>;
+def : InstAlias<"jmp $addr", (JMPLri G0, MEMri:$addr)>;
+
+// call addr -> jmpl addr, %o7
+def : InstAlias<"call $addr", (JMPLrr O7, MEMrr:$addr)>;
+def : InstAlias<"call $addr", (JMPLri O7, MEMri:$addr)>;
+
+// retl -> RETL 8
+def : InstAlias<"retl", (RETL 8)>;
+
+// ret -> RET 8
+def : InstAlias<"ret", (RET 8)>;
+
+// mov reg, rd -> or %g0, reg, rd
+def : InstAlias<"mov $rs2, $rd", (ORrr IntRegs:$rd, G0, IntRegs:$rs2)>;
+
+// mov simm13, rd -> or %g0, simm13, rd
+def : InstAlias<"mov $simm13, $rd", (ORri IntRegs:$rd, G0, i32imm:$simm13)>;
diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td b/contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td
index afa2874..b38a663 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td
+++ b/contrib/llvm/lib/Target/Sparc/SparcInstrFormats.td
@@ -12,6 +12,7 @@ class InstSP<dag outs, dag ins, string asmstr, list<dag> pattern>
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, list<dag> pattern>
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, string asmstr,
let Inst{28-25} = cond;
}
+class F2_3<bits<3> op2Val, bits<2> ccVal, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ : InstSP<outs, ins, asmstr, pattern> {
+ bit annul;
+ bits<4> cond;
+ bit pred;
+ bits<19> imm19;
+
+ let op = 0; // op = 0
+
+ bit annul = 0; // currently unused
+ let pred = 1; // default is predict taken
+
+ let Inst{29} = annul;
+ let Inst{28-25} = cond;
+ let Inst{24-22} = op2Val;
+ let Inst{21-20} = ccVal;
+ let Inst{19} = pred;
+ let Inst{18-0} = imm19;
+}
+
//===----------------------------------------------------------------------===//
// Format #3 instruction classes in the Sparc
//===----------------------------------------------------------------------===//
@@ -75,9 +100,8 @@ class F3<dag outs, dag ins, string asmstr, list<dag> pattern>
// Specific F3 classes: SparcV8 manual, page 44
//
-class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
+class F3_1_asi<bits<2> opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins,
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
- bits<8> asi = 0; // asi not currently used
bits<5> rs2;
let op = opVal;
@@ -88,6 +112,10 @@ class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
let Inst{4-0} = rs2;
}
+class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins, string asmstr,
+ list<dag> pattern> : F3_1_asi<opVal, op3val, 0, outs, ins,
+ asmstr, pattern>;
+
class F3_2<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
bits<13> simm13;
@@ -168,12 +196,12 @@ class F3_Si<bits<2> opVal, bits<6> op3val, bit xVal, dag outs, dag ins,
// 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>
diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
index c10b5b3..6ecf81d 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -431,8 +431,9 @@ unsigned SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const
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;
diff --git a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td
index ef7a114..ae10ca0 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td
+++ b/contrib/llvm/lib/Target/Sparc/SparcInstrInfo.td
@@ -76,20 +76,37 @@ def ADDRrr : ComplexPattern<iPTR, 2, "SelectADDRrr", [], []>;
def ADDRri : ComplexPattern<iPTR, 2, "SelectADDRri", [frameindex], []>;
// Address operands
+def SparcMEMrrAsmOperand : AsmOperandClass {
+ let Name = "MEMrr";
+ let ParserMethod = "parseMEMOperand";
+}
+
+def SparcMEMriAsmOperand : AsmOperandClass {
+ let Name = "MEMri";
+ let ParserMethod = "parseMEMOperand";
+}
+
def MEMrr : Operand<iPTR> {
let PrintMethod = "printMemOperand";
let MIOperandInfo = (ops ptr_rc, ptr_rc);
+ let ParserMatchClass = SparcMEMrrAsmOperand;
}
def MEMri : Operand<iPTR> {
let PrintMethod = "printMemOperand";
let MIOperandInfo = (ops ptr_rc, i32imm);
+ let ParserMatchClass = SparcMEMriAsmOperand;
}
def TLSSym : Operand<iPTR>;
// Branch targets have OtherVT type.
-def brtarget : Operand<OtherVT>;
-def calltarget : Operand<i32>;
+def brtarget : Operand<OtherVT> {
+ let EncoderMethod = "getBranchTargetOpValue";
+}
+
+def calltarget : Operand<i32> {
+ let EncoderMethod = "getCallTargetOpValue";
+}
// Operand for printing out a condition code.
let PrintMethod = "printCCOperand" in
@@ -163,7 +180,7 @@ def tlscall : SDNode<"SPISD::TLS_CALL", SDT_SPCall,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
SDNPVariadic]>;
-def getPCX : Operand<i32> {
+def getPCX : Operand<iPTR> {
let PrintMethod = "printGetPCX";
}
@@ -210,26 +227,53 @@ 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),
- !strconcat(OpcStr, " $b, $c, $dst"),
- [(set i32:$dst, (OpNode i32:$b, i32:$c))]>;
+ (outs RC:$rd), (ins RC:$rs1, RC:$rs2),
+ !strconcat(OpcStr, " $rs1, $rs2, $rd"),
+ [(set Ty:$rd, (OpNode Ty:$rs1, Ty:$rs2))]>;
def ri : F3_2<2, Op3Val,
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
- !strconcat(OpcStr, " $b, $c, $dst"),
- [(set i32:$dst, (OpNode i32:$b, (i32 simm13:$c)))]>;
+ (outs RC:$rd), (ins RC:$rs1, immOp:$simm13),
+ !strconcat(OpcStr, " $rs1, $simm13, $rd"),
+ [(set Ty:$rd, (OpNode Ty:$rs1, (Ty simm13:$simm13)))]>;
}
/// F3_12np multiclass - Define a normal F3_1/F3_2 pattern in one shot, with no
/// pattern.
multiclass F3_12np<string OpcStr, bits<6> Op3Val> {
def rr : F3_1<2, Op3Val,
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
- !strconcat(OpcStr, " $b, $c, $dst"), []>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
+ !strconcat(OpcStr, " $rs1, $rs2, $rd"), []>;
def ri : F3_2<2, Op3Val,
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
- !strconcat(OpcStr, " $b, $c, $dst"), []>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
+ !strconcat(OpcStr, " $rs1, $simm13, $rd"), []>;
+}
+
+// Load multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot.
+multiclass Load<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
+ RegisterClass RC, ValueType Ty> {
+ def rr : F3_1<3, Op3Val,
+ (outs RC:$dst), (ins MEMrr:$addr),
+ !strconcat(OpcStr, " [$addr], $dst"),
+ [(set Ty:$dst, (OpNode ADDRrr:$addr))]>;
+ def ri : F3_2<3, Op3Val,
+ (outs RC:$dst), (ins MEMri:$addr),
+ !strconcat(OpcStr, " [$addr], $dst"),
+ [(set Ty:$dst, (OpNode ADDRri:$addr))]>;
+}
+
+// Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot.
+multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
+ RegisterClass RC, ValueType Ty> {
+ def rr : F3_1<3, Op3Val,
+ (outs), (ins MEMrr:$addr, RC:$rd),
+ !strconcat(OpcStr, " $rd, [$addr]"),
+ [(OpNode Ty:$rd, ADDRrr:$addr)]>;
+ def ri : F3_2<3, Op3Val,
+ (outs), (ins MEMri:$addr, RC:$rd),
+ !strconcat(OpcStr, " $rd, [$addr]"),
+ [(OpNode Ty:$rd, ADDRri:$addr)]>;
}
//===----------------------------------------------------------------------===//
@@ -238,7 +282,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 {
@@ -265,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", []>;
@@ -315,10 +365,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)]>;
@@ -329,128 +387,28 @@ let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
}
// Section B.1 - Load Integer Instructions, p. 90
-def LDSBrr : F3_1<3, 0b001001,
- (outs IntRegs:$dst), (ins MEMrr:$addr),
- "ldsb [$addr], $dst",
- [(set i32:$dst, (sextloadi8 ADDRrr:$addr))]>;
-def LDSBri : F3_2<3, 0b001001,
- (outs IntRegs:$dst), (ins MEMri:$addr),
- "ldsb [$addr], $dst",
- [(set i32:$dst, (sextloadi8 ADDRri:$addr))]>;
-def LDSHrr : F3_1<3, 0b001010,
- (outs IntRegs:$dst), (ins MEMrr:$addr),
- "ldsh [$addr], $dst",
- [(set i32:$dst, (sextloadi16 ADDRrr:$addr))]>;
-def LDSHri : F3_2<3, 0b001010,
- (outs IntRegs:$dst), (ins MEMri:$addr),
- "ldsh [$addr], $dst",
- [(set i32:$dst, (sextloadi16 ADDRri:$addr))]>;
-def LDUBrr : F3_1<3, 0b000001,
- (outs IntRegs:$dst), (ins MEMrr:$addr),
- "ldub [$addr], $dst",
- [(set i32:$dst, (zextloadi8 ADDRrr:$addr))]>;
-def LDUBri : F3_2<3, 0b000001,
- (outs IntRegs:$dst), (ins MEMri:$addr),
- "ldub [$addr], $dst",
- [(set i32:$dst, (zextloadi8 ADDRri:$addr))]>;
-def LDUHrr : F3_1<3, 0b000010,
- (outs IntRegs:$dst), (ins MEMrr:$addr),
- "lduh [$addr], $dst",
- [(set i32:$dst, (zextloadi16 ADDRrr:$addr))]>;
-def LDUHri : F3_2<3, 0b000010,
- (outs IntRegs:$dst), (ins MEMri:$addr),
- "lduh [$addr], $dst",
- [(set i32:$dst, (zextloadi16 ADDRri:$addr))]>;
-def LDrr : F3_1<3, 0b000000,
- (outs IntRegs:$dst), (ins MEMrr:$addr),
- "ld [$addr], $dst",
- [(set i32:$dst, (load ADDRrr:$addr))]>;
-def LDri : F3_2<3, 0b000000,
- (outs IntRegs:$dst), (ins MEMri:$addr),
- "ld [$addr], $dst",
- [(set i32:$dst, (load ADDRri:$addr))]>;
+defm LDSB : Load<"ldsb", 0b001001, sextloadi8, IntRegs, i32>;
+defm LDSH : Load<"ldsh", 0b001010, sextloadi16, IntRegs, i32>;
+defm LDUB : Load<"ldub", 0b000001, zextloadi8, IntRegs, i32>;
+defm LDUH : Load<"lduh", 0b000010, zextloadi16, IntRegs, i32>;
+defm LD : Load<"ld", 0b000000, load, IntRegs, i32>;
// Section B.2 - Load Floating-point Instructions, p. 92
-def LDFrr : F3_1<3, 0b100000,
- (outs FPRegs:$dst), (ins MEMrr:$addr),
- "ld [$addr], $dst",
- [(set f32:$dst, (load ADDRrr:$addr))]>;
-def LDFri : F3_2<3, 0b100000,
- (outs FPRegs:$dst), (ins MEMri:$addr),
- "ld [$addr], $dst",
- [(set f32:$dst, (load ADDRri:$addr))]>;
-def LDDFrr : F3_1<3, 0b100011,
- (outs DFPRegs:$dst), (ins MEMrr:$addr),
- "ldd [$addr], $dst",
- [(set f64:$dst, (load ADDRrr:$addr))]>;
-def LDDFri : F3_2<3, 0b100011,
- (outs DFPRegs:$dst), (ins MEMri:$addr),
- "ldd [$addr], $dst",
- [(set f64:$dst, (load ADDRri:$addr))]>;
-def LDQFrr : F3_1<3, 0b100010,
- (outs QFPRegs:$dst), (ins MEMrr:$addr),
- "ldq [$addr], $dst",
- [(set f128:$dst, (load ADDRrr:$addr))]>,
- Requires<[HasV9, HasHardQuad]>;
-def LDQFri : F3_2<3, 0b100010,
- (outs QFPRegs:$dst), (ins MEMri:$addr),
- "ldq [$addr], $dst",
- [(set f128:$dst, (load ADDRri:$addr))]>,
- Requires<[HasV9, HasHardQuad]>;
+defm LDF : Load<"ld", 0b100000, load, FPRegs, f32>;
+defm LDDF : Load<"ldd", 0b100011, load, DFPRegs, f64>;
+defm LDQF : Load<"ldq", 0b100010, load, QFPRegs, f128>,
+ Requires<[HasV9, HasHardQuad]>;
// Section B.4 - Store Integer Instructions, p. 95
-def STBrr : F3_1<3, 0b000101,
- (outs), (ins MEMrr:$addr, IntRegs:$rd),
- "stb $rd, [$addr]",
- [(truncstorei8 i32:$rd, ADDRrr:$addr)]>;
-def STBri : F3_2<3, 0b000101,
- (outs), (ins MEMri:$addr, IntRegs:$rd),
- "stb $rd, [$addr]",
- [(truncstorei8 i32:$rd, ADDRri:$addr)]>;
-def STHrr : F3_1<3, 0b000110,
- (outs), (ins MEMrr:$addr, IntRegs:$rd),
- "sth $rd, [$addr]",
- [(truncstorei16 i32:$rd, ADDRrr:$addr)]>;
-def STHri : F3_2<3, 0b000110,
- (outs), (ins MEMri:$addr, IntRegs:$rd),
- "sth $rd, [$addr]",
- [(truncstorei16 i32:$rd, ADDRri:$addr)]>;
-def STrr : F3_1<3, 0b000100,
- (outs), (ins MEMrr:$addr, IntRegs:$rd),
- "st $rd, [$addr]",
- [(store i32:$rd, ADDRrr:$addr)]>;
-def STri : F3_2<3, 0b000100,
- (outs), (ins MEMri:$addr, IntRegs:$rd),
- "st $rd, [$addr]",
- [(store i32:$rd, ADDRri:$addr)]>;
+defm STB : Store<"stb", 0b000101, truncstorei8, IntRegs, i32>;
+defm STH : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>;
+defm ST : Store<"st", 0b000100, store, IntRegs, i32>;
// Section B.5 - Store Floating-point Instructions, p. 97
-def STFrr : F3_1<3, 0b100100,
- (outs), (ins MEMrr:$addr, FPRegs:$rd),
- "st $rd, [$addr]",
- [(store f32:$rd, ADDRrr:$addr)]>;
-def STFri : F3_2<3, 0b100100,
- (outs), (ins MEMri:$addr, FPRegs:$rd),
- "st $rd, [$addr]",
- [(store f32:$rd, ADDRri:$addr)]>;
-def STDFrr : F3_1<3, 0b100111,
- (outs), (ins MEMrr:$addr, DFPRegs:$rd),
- "std $rd, [$addr]",
- [(store f64:$rd, ADDRrr:$addr)]>;
-def STDFri : F3_2<3, 0b100111,
- (outs), (ins MEMri:$addr, DFPRegs:$rd),
- "std $rd, [$addr]",
- [(store f64:$rd, ADDRri:$addr)]>;
-def STQFrr : F3_1<3, 0b100110,
- (outs), (ins MEMrr:$addr, QFPRegs:$rd),
- "stq $rd, [$addr]",
- [(store f128:$rd, ADDRrr:$addr)]>,
- Requires<[HasV9, HasHardQuad]>;
-def STQFri : F3_2<3, 0b100110,
- (outs), (ins MEMri:$addr, QFPRegs:$rd),
- "stq $rd, [$addr]",
- [(store f128:$rd, ADDRri:$addr)]>,
- Requires<[HasV9, HasHardQuad]>;
+defm STF : Store<"st", 0b100100, store, FPRegs, f32>;
+defm STDF : Store<"std", 0b100111, store, DFPRegs, f64>;
+defm STQF : Store<"stq", 0b100110, store, QFPRegs, f128>,
+ Requires<[HasV9, HasHardQuad]>;
// Section B.9 - SETHI Instruction, p. 104
def SETHIi: F2_1<0b100,
@@ -464,85 +422,79 @@ 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),
- "andn $b, $c, $dst",
- [(set i32:$dst, (and i32:$b, (not i32:$c)))]>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
+ "andn $rs1, $rs2, $rd",
+ [(set i32:$rd, (and i32:$rs1, (not i32:$rs2)))]>;
def ANDNri : F3_2<2, 0b000101,
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
- "andn $b, $c, $dst", []>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
+ "andn $rs1, $simm13, $rd", []>;
-defm OR : F3_12<"or", 0b000010, or>;
+defm OR : F3_12<"or", 0b000010, or, IntRegs, i32, i32imm>;
def ORNrr : F3_1<2, 0b000110,
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
- "orn $b, $c, $dst",
- [(set i32:$dst, (or i32:$b, (not i32:$c)))]>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
+ "orn $rs1, $rs2, $rd",
+ [(set i32:$rd, (or i32:$rs1, (not i32:$rs2)))]>;
def ORNri : F3_2<2, 0b000110,
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
- "orn $b, $c, $dst", []>;
-defm XOR : F3_12<"xor", 0b000011, xor>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
+ "orn $rs1, $simm13, $rd", []>;
+defm XOR : F3_12<"xor", 0b000011, xor, IntRegs, i32, i32imm>;
def XNORrr : F3_1<2, 0b000111,
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
- "xnor $b, $c, $dst",
- [(set i32:$dst, (not (xor i32:$b, i32:$c)))]>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
+ "xnor $rs1, $rs2, $rd",
+ [(set i32:$rd, (not (xor i32:$rs1, i32:$rs2)))]>;
def XNORri : F3_2<2, 0b000111,
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
- "xnor $b, $c, $dst", []>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
+ "xnor $rs1, $simm13, $rd", []>;
// Section B.12 - Shift Instructions, p. 107
-defm SLL : F3_12<"sll", 0b100101, shl>;
-defm SRL : F3_12<"srl", 0b100110, srl>;
-defm SRA : F3_12<"sra", 0b100111, sra>;
+defm SLL : F3_12<"sll", 0b100101, shl, IntRegs, i32, i32imm>;
+defm SRL : F3_12<"srl", 0b100110, srl, IntRegs, i32, i32imm>;
+defm SRA : F3_12<"sra", 0b100111, sra, IntRegs, i32, i32imm>;
// Section B.13 - Add Instructions, p. 108
-defm ADD : F3_12<"add", 0b000000, add>;
+defm ADD : F3_12<"add", 0b000000, add, IntRegs, i32, i32imm>;
// "LEA" forms of add (patterns to make tblgen happy)
-let Predicates = [Is32Bit] in
+let Predicates = [Is32Bit], isCodeGenOnly = 1 in
def LEA_ADDri : F3_2<2, 0b000000,
(outs IntRegs:$dst), (ins MEMri:$addr),
"add ${addr:arith}, $dst",
[(set iPTR:$dst, ADDRri:$addr)]>;
let Defs = [ICC] in
- defm ADDCC : F3_12<"addcc", 0b010000, addc>;
+ defm ADDCC : F3_12<"addcc", 0b010000, addc, IntRegs, i32, i32imm>;
let Uses = [ICC], Defs = [ICC] in
- defm ADDX : F3_12<"addxcc", 0b011000, adde>;
+ defm ADDE : F3_12<"addxcc", 0b011000, adde, IntRegs, i32, i32imm>;
// Section B.15 - Subtract Instructions, p. 110
-defm SUB : F3_12 <"sub" , 0b000100, sub>;
+defm SUB : F3_12 <"sub" , 0b000100, sub, IntRegs, i32, i32imm>;
let Uses = [ICC], Defs = [ICC] in
- defm SUBX : F3_12 <"subxcc" , 0b011100, sube>;
+ defm SUBE : F3_12 <"subxcc" , 0b011100, sube, IntRegs, i32, i32imm>;
let Defs = [ICC] in
- defm SUBCC : F3_12 <"subcc", 0b010100, subc>;
+ defm SUBCC : F3_12 <"subcc", 0b010100, subc, IntRegs, i32, i32imm>;
let Defs = [ICC], rd = 0 in {
def CMPrr : F3_1<2, 0b010100,
- (outs), (ins IntRegs:$b, IntRegs:$c),
- "cmp $b, $c",
- [(SPcmpicc i32:$b, i32:$c)]>;
+ (outs), (ins IntRegs:$rs1, IntRegs:$rs2),
+ "cmp $rs1, $rs2",
+ [(SPcmpicc i32:$rs1, i32:$rs2)]>;
def CMPri : F3_2<2, 0b010100,
- (outs), (ins IntRegs:$b, i32imm:$c),
- "cmp $b, $c",
- [(SPcmpicc i32:$b, (i32 simm13:$c))]>;
+ (outs), (ins IntRegs:$rs1, i32imm:$simm13),
+ "cmp $rs1, $simm13",
+ [(SPcmpicc i32:$rs1, (i32 simm13:$simm13))]>;
}
-let Uses = [ICC], Defs = [ICC] in
- def SUBXCCrr: F3_1<2, 0b011100,
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
- "subxcc $b, $c, $dst", []>;
-
-
// Section B.18 - Multiply Instructions, p. 113
let Defs = [Y] in {
defm UMUL : F3_12np<"umul", 0b001010>;
- defm SMUL : F3_12 <"smul", 0b001011, mul>;
+ defm SMUL : F3_12 <"smul", 0b001011, mul, IntRegs, i32, i32imm>;
}
// Section B.19 - Divide Instructions, p. 115
@@ -578,9 +530,8 @@ class BranchSP<dag ins, string asmstr, list<dag> pattern>
}
// Indirect branch instructions.
-let isTerminator = 1, isBarrier = 1,
- hasDelaySlot = 1, isBranch =1,
- isIndirectBranch = 1, rd = 0 in {
+let isTerminator = 1, isBarrier = 1, hasDelaySlot = 1, isBranch =1,
+ isIndirectBranch = 1, rd = 0, isCodeGenOnly = 1 in {
def BINDrr : F3_1<2, 0b111000,
(outs), (ins MEMrr:$ptr),
"jmp $ptr",
@@ -623,15 +574,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
@@ -651,164 +604,164 @@ 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]>;
// Floating-point Add and Subtract Instructions, p. 146
def FADDS : F3_3<2, 0b110100, 0b001000001,
- (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
- "fadds $src1, $src2, $dst",
- [(set f32:$dst, (fadd f32:$src1, f32:$src2))]>;
+ (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
+ "fadds $rs1, $rs2, $rd",
+ [(set f32:$rd, (fadd f32:$rs1, f32:$rs2))]>;
def FADDD : F3_3<2, 0b110100, 0b001000010,
- (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
- "faddd $src1, $src2, $dst",
- [(set f64:$dst, (fadd f64:$src1, f64:$src2))]>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
+ "faddd $rs1, $rs2, $rd",
+ [(set f64:$rd, (fadd f64:$rs1, f64:$rs2))]>;
def FADDQ : F3_3<2, 0b110100, 0b001000011,
- (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
- "faddq $src1, $src2, $dst",
- [(set f128:$dst, (fadd f128:$src1, f128:$src2))]>,
+ (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2),
+ "faddq $rs1, $rs2, $rd",
+ [(set f128:$rd, (fadd f128:$rs1, f128:$rs2))]>,
Requires<[HasHardQuad]>;
def FSUBS : F3_3<2, 0b110100, 0b001000101,
- (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
- "fsubs $src1, $src2, $dst",
- [(set f32:$dst, (fsub f32:$src1, f32:$src2))]>;
+ (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
+ "fsubs $rs1, $rs2, $rd",
+ [(set f32:$rd, (fsub f32:$rs1, f32:$rs2))]>;
def FSUBD : F3_3<2, 0b110100, 0b001000110,
- (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
- "fsubd $src1, $src2, $dst",
- [(set f64:$dst, (fsub f64:$src1, f64:$src2))]>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
+ "fsubd $rs1, $rs2, $rd",
+ [(set f64:$rd, (fsub f64:$rs1, f64:$rs2))]>;
def FSUBQ : F3_3<2, 0b110100, 0b001000111,
- (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
- "fsubq $src1, $src2, $dst",
- [(set f128:$dst, (fsub f128:$src1, f128:$src2))]>,
+ (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2),
+ "fsubq $rs1, $rs2, $rd",
+ [(set f128:$rd, (fsub f128:$rs1, f128:$rs2))]>,
Requires<[HasHardQuad]>;
// Floating-point Multiply and Divide Instructions, p. 147
def FMULS : F3_3<2, 0b110100, 0b001001001,
- (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
- "fmuls $src1, $src2, $dst",
- [(set f32:$dst, (fmul f32:$src1, f32:$src2))]>;
+ (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
+ "fmuls $rs1, $rs2, $rd",
+ [(set f32:$rd, (fmul f32:$rs1, f32:$rs2))]>;
def FMULD : F3_3<2, 0b110100, 0b001001010,
- (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
- "fmuld $src1, $src2, $dst",
- [(set f64:$dst, (fmul f64:$src1, f64:$src2))]>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
+ "fmuld $rs1, $rs2, $rd",
+ [(set f64:$rd, (fmul f64:$rs1, f64:$rs2))]>;
def FMULQ : F3_3<2, 0b110100, 0b001001011,
- (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
- "fmulq $src1, $src2, $dst",
- [(set f128:$dst, (fmul f128:$src1, f128:$src2))]>,
+ (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2),
+ "fmulq $rs1, $rs2, $rd",
+ [(set f128:$rd, (fmul f128:$rs1, f128:$rs2))]>,
Requires<[HasHardQuad]>;
def FSMULD : F3_3<2, 0b110100, 0b001101001,
- (outs DFPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
- "fsmuld $src1, $src2, $dst",
- [(set f64:$dst, (fmul (fextend f32:$src1),
- (fextend f32:$src2)))]>;
+ (outs DFPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
+ "fsmuld $rs1, $rs2, $rd",
+ [(set f64:$rd, (fmul (fextend f32:$rs1),
+ (fextend f32:$rs2)))]>;
def FDMULQ : F3_3<2, 0b110100, 0b001101110,
- (outs QFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
- "fdmulq $src1, $src2, $dst",
- [(set f128:$dst, (fmul (fextend f64:$src1),
- (fextend f64:$src2)))]>,
+ (outs QFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
+ "fdmulq $rs1, $rs2, $rd",
+ [(set f128:$rd, (fmul (fextend f64:$rs1),
+ (fextend f64:$rs2)))]>,
Requires<[HasHardQuad]>;
def FDIVS : F3_3<2, 0b110100, 0b001001101,
- (outs FPRegs:$dst), (ins FPRegs:$src1, FPRegs:$src2),
- "fdivs $src1, $src2, $dst",
- [(set f32:$dst, (fdiv f32:$src1, f32:$src2))]>;
+ (outs FPRegs:$rd), (ins FPRegs:$rs1, FPRegs:$rs2),
+ "fdivs $rs1, $rs2, $rd",
+ [(set f32:$rd, (fdiv f32:$rs1, f32:$rs2))]>;
def FDIVD : F3_3<2, 0b110100, 0b001001110,
- (outs DFPRegs:$dst), (ins DFPRegs:$src1, DFPRegs:$src2),
- "fdivd $src1, $src2, $dst",
- [(set f64:$dst, (fdiv f64:$src1, f64:$src2))]>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs1, DFPRegs:$rs2),
+ "fdivd $rs1, $rs2, $rd",
+ [(set f64:$rd, (fdiv f64:$rs1, f64:$rs2))]>;
def FDIVQ : F3_3<2, 0b110100, 0b001001111,
- (outs QFPRegs:$dst), (ins QFPRegs:$src1, QFPRegs:$src2),
- "fdivq $src1, $src2, $dst",
- [(set f128:$dst, (fdiv f128:$src1, f128:$src2))]>,
+ (outs QFPRegs:$rd), (ins QFPRegs:$rs1, QFPRegs:$rs2),
+ "fdivq $rs1, $rs2, $rd",
+ [(set f128:$rd, (fdiv f128:$rs1, f128:$rs2))]>,
Requires<[HasHardQuad]>;
// Floating-point Compare Instructions, p. 148
@@ -820,24 +773,24 @@ 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]>;
}
//===----------------------------------------------------------------------===//
// Instructions for Thread Local Storage(TLS).
//===----------------------------------------------------------------------===//
-
+let isCodeGenOnly = 1, isAsmParserOnly = 1 in {
def TLS_ADDrr : F3_1<2, 0b000000,
(outs IntRegs:$rd),
(ins IntRegs:$rs1, IntRegs:$rs2, TLSSym:$sym),
@@ -861,6 +814,7 @@ let Uses = [O6], isCall = 1, hasDelaySlot = 1 in
let op = 1;
let Inst{29-0} = disp;
}
+}
//===----------------------------------------------------------------------===//
// V9 Instructions
@@ -912,8 +866,9 @@ let Predicates = [HasV9], Constraints = "$f = $rd" in {
def FMOVQ_ICC
: F4_3<0b110101, 0b000011, (outs QFPRegs:$rd),
(ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond),
- "fmovd$cond %icc, $rs2, $rd",
- [(set f128:$rd, (SPselecticc f128:$rs2, f128:$f, imm:$cond))]>;
+ "fmovq$cond %icc, $rs2, $rd",
+ [(set f128:$rd, (SPselecticc f128:$rs2, f128:$f, imm:$cond))]>,
+ Requires<[HasHardQuad]>;
}
let Uses = [FCC], opf_cc = 0b000 in {
@@ -930,8 +885,9 @@ let Predicates = [HasV9], Constraints = "$f = $rd" in {
def FMOVQ_FCC
: F4_3<0b110101, 0b000011, (outs QFPRegs:$rd),
(ins QFPRegs:$rs2, QFPRegs:$f, CCOp:$cond),
- "fmovd$cond %fcc0, $rs2, $rd",
- [(set f128:$rd, (SPselectfcc f128:$rs2, f128:$f, imm:$cond))]>;
+ "fmovq$cond %fcc0, $rs2, $rd",
+ [(set f128:$rd, (SPselectfcc f128:$rs2, f128:$f, imm:$cond))]>,
+ Requires<[HasHardQuad]>;
}
}
@@ -939,40 +895,67 @@ let Predicates = [HasV9], Constraints = "$f = $rd" in {
// Floating-Point Move Instructions, p. 164 of the V9 manual.
let Predicates = [HasV9] in {
def FMOVD : F3_3u<2, 0b110100, 0b000000010,
- (outs DFPRegs:$dst), (ins DFPRegs:$src),
- "fmovd $src, $dst", []>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
+ "fmovd $rs2, $rd", []>;
def FMOVQ : F3_3u<2, 0b110100, 0b000000011,
- (outs QFPRegs:$dst), (ins QFPRegs:$src),
- "fmovq $src, $dst", []>,
+ (outs QFPRegs:$rd), (ins QFPRegs:$rs2),
+ "fmovq $rs2, $rd", []>,
Requires<[HasHardQuad]>;
def FNEGD : F3_3u<2, 0b110100, 0b000000110,
- (outs DFPRegs:$dst), (ins DFPRegs:$src),
- "fnegd $src, $dst",
- [(set f64:$dst, (fneg f64:$src))]>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
+ "fnegd $rs2, $rd",
+ [(set f64:$rd, (fneg f64:$rs2))]>;
def FNEGQ : F3_3u<2, 0b110100, 0b000000111,
- (outs QFPRegs:$dst), (ins QFPRegs:$src),
- "fnegq $src, $dst",
- [(set f128:$dst, (fneg f128:$src))]>,
+ (outs QFPRegs:$rd), (ins QFPRegs:$rs2),
+ "fnegq $rs2, $rd",
+ [(set f128:$rd, (fneg f128:$rs2))]>,
Requires<[HasHardQuad]>;
def FABSD : F3_3u<2, 0b110100, 0b000001010,
- (outs DFPRegs:$dst), (ins DFPRegs:$src),
- "fabsd $src, $dst",
- [(set f64:$dst, (fabs f64:$src))]>;
+ (outs DFPRegs:$rd), (ins DFPRegs:$rs2),
+ "fabsd $rs2, $rd",
+ [(set f64:$rd, (fabs f64:$rs2))]>;
def FABSQ : F3_3u<2, 0b110100, 0b000001011,
- (outs QFPRegs:$dst), (ins QFPRegs:$src),
- "fabsq $src, $dst",
- [(set f128:$dst, (fabs f128:$src))]>,
+ (outs QFPRegs:$rd), (ins QFPRegs:$rs2),
+ "fabsq $rs2, $rd",
+ [(set f128:$rd, (fabs f128:$rs2))]>,
Requires<[HasHardQuad]>;
}
// POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear
-// the top 32-bits before using it. To do this clearing, we use a SLLri X,0.
+// the top 32-bits before using it. To do this clearing, we use a SRLri X,0.
let rs1 = 0 in
def POPCrr : F3_1<2, 0b101110,
(outs IntRegs:$dst), (ins IntRegs:$src),
"popc $src, $dst", []>, Requires<[HasV9]>;
def : Pat<(ctpop i32:$src),
- (POPCrr (SLLri $src, 0))>;
+ (POPCrr (SRLri $src, 0))>;
+
+// Atomic swap.
+let hasSideEffects =1, rd = 0, rs1 = 0b01111, rs2 = 0 in
+ def STBAR : F3_1<2, 0b101000, (outs), (ins), "stbar", []>;
+
+let Predicates = [HasV9], hasSideEffects = 1, rd = 0, rs1 = 0b01111 in
+ def MEMBARi : F3_2<2, 0b101000, (outs), (ins i32imm:$simm13),
+ "membar $simm13", []>;
+
+let Constraints = "$val = $dst" in {
+ def SWAPrr : F3_1<3, 0b001111,
+ (outs IntRegs:$dst), (ins MEMrr:$addr, IntRegs:$val),
+ "swap [$addr], $dst",
+ [(set i32:$dst, (atomic_swap_32 ADDRrr:$addr, i32:$val))]>;
+ def SWAPri : F3_2<3, 0b001111,
+ (outs IntRegs:$dst), (ins MEMri:$addr, IntRegs:$val),
+ "swap [$addr], $dst",
+ [(set i32:$dst, (atomic_swap_32 ADDRri:$addr, i32:$val))]>;
+}
+
+let Predicates = [HasV9], Constraints = "$swap = $rd" in
+ def CASrr: F3_1_asi<3, 0b111100, 0b10000000,
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2,
+ IntRegs:$swap),
+ "cas [$rs1], $rs2, $rd",
+ [(set i32:$rd,
+ (atomic_cmp_swap iPTR:$rs1, i32:$rs2, i32:$swap))]>;
//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
@@ -987,6 +970,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 +994,7 @@ def : Pat<(add iPTR:$r, (SPlo tglobaladdr:$in)), (ADDri $r, 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),
@@ -1032,4 +1018,18 @@ def : Pat<(i32 (zextloadi1 ADDRri:$src)), (LDUBri ADDRri:$src)>;
def : Pat<(store (i32 0), ADDRrr:$dst), (STrr ADDRrr:$dst, (i32 G0))>;
def : Pat<(store (i32 0), ADDRri:$dst), (STri ADDRri:$dst, (i32 G0))>;
+// store bar for all atomic_fence in V8.
+let Predicates = [HasNoV9] in
+ def : Pat<(atomic_fence imm, imm), (STBAR)>;
+
+// atomic_load_32 addr -> load addr
+def : Pat<(i32 (atomic_load ADDRrr:$src)), (LDrr ADDRrr:$src)>;
+def : Pat<(i32 (atomic_load ADDRri:$src)), (LDri ADDRri:$src)>;
+
+// atomic_store_32 val, addr -> store val, addr
+def : Pat<(atomic_store ADDRrr:$dst, i32:$val), (STrr ADDRrr:$dst, $val)>;
+def : Pat<(atomic_store ADDRri:$dst, i32:$val), (STri ADDRri:$dst, $val)>;
+
+
include "SparcInstr64Bit.td"
+include "SparcInstrAliases.td"
diff --git a/contrib/llvm/lib/Target/Sparc/SparcJITInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcJITInfo.cpp
index 6493c7d..959d12f 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcJITInfo.cpp
+++ b/contrib/llvm/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"
@@ -27,26 +28,67 @@ 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"
"\t.global SparcCompilationCallback\n"
"\t.type SparcCompilationCallback, #function\n"
"SparcCompilationCallback:\n"
- // Save current register window.
- "\tsave %sp, -192, %sp\n"
- // stubaddr+4 is in %g1.
+ // Save current register window and create stack.
+ // 128 (save area) + 6*8 (for arguments) + 16*8 (for float regfile) = 304
+ "\tsave %sp, -304, %sp\n"
+ // save float regfile to the stack.
+ "\tstd %f0, [" FRAME_PTR(%fp) "-0]\n"
+ "\tstd %f2, [" FRAME_PTR(%fp) "-8]\n"
+ "\tstd %f4, [" FRAME_PTR(%fp) "-16]\n"
+ "\tstd %f6, [" FRAME_PTR(%fp) "-24]\n"
+ "\tstd %f8, [" FRAME_PTR(%fp) "-32]\n"
+ "\tstd %f10, [" FRAME_PTR(%fp) "-40]\n"
+ "\tstd %f12, [" FRAME_PTR(%fp) "-48]\n"
+ "\tstd %f14, [" FRAME_PTR(%fp) "-56]\n"
+ "\tstd %f16, [" FRAME_PTR(%fp) "-64]\n"
+ "\tstd %f18, [" FRAME_PTR(%fp) "-72]\n"
+ "\tstd %f20, [" FRAME_PTR(%fp) "-80]\n"
+ "\tstd %f22, [" FRAME_PTR(%fp) "-88]\n"
+ "\tstd %f24, [" FRAME_PTR(%fp) "-96]\n"
+ "\tstd %f26, [" FRAME_PTR(%fp) "-104]\n"
+ "\tstd %f28, [" FRAME_PTR(%fp) "-112]\n"
+ "\tstd %f30, [" FRAME_PTR(%fp) "-120]\n"
+ // stubaddr is in %g1.
"\tcall SparcCompilationCallbackC\n"
- "\t sub %g1, 4, %o0\n"
+ "\t mov %g1, %o0\n"
+ // restore float regfile from the stack.
+ "\tldd [" FRAME_PTR(%fp) "-0], %f0\n"
+ "\tldd [" FRAME_PTR(%fp) "-8], %f2\n"
+ "\tldd [" FRAME_PTR(%fp) "-16], %f4\n"
+ "\tldd [" FRAME_PTR(%fp) "-24], %f6\n"
+ "\tldd [" FRAME_PTR(%fp) "-32], %f8\n"
+ "\tldd [" FRAME_PTR(%fp) "-40], %f10\n"
+ "\tldd [" FRAME_PTR(%fp) "-48], %f12\n"
+ "\tldd [" FRAME_PTR(%fp) "-56], %f14\n"
+ "\tldd [" FRAME_PTR(%fp) "-64], %f16\n"
+ "\tldd [" FRAME_PTR(%fp) "-72], %f18\n"
+ "\tldd [" FRAME_PTR(%fp) "-80], %f20\n"
+ "\tldd [" FRAME_PTR(%fp) "-88], %f22\n"
+ "\tldd [" FRAME_PTR(%fp) "-96], %f24\n"
+ "\tldd [" FRAME_PTR(%fp) "-104], %f26\n"
+ "\tldd [" FRAME_PTR(%fp) "-112], %f28\n"
+ "\tldd [" FRAME_PTR(%fp) "-120], %f30\n"
// restore original register window and
// copy %o0 to %g1
- "\t restore %o0, 0, %g1\n"
+ "\trestore %o0, 0, %g1\n"
// call the new stub
"\tjmp %g1\n"
"\t nop\n"
"\t.size SparcCompilationCallback, .-SparcCompilationCallback"
);
-
#else
void SparcCompilationCallback() {
llvm_unreachable(
@@ -55,75 +97,171 @@ 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:
+
+ 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);
+ }
- *(intptr_t *)(StubAddr) = SETHI_INST(HI(NewVal), 1);
- *(intptr_t *)(StubAddr + 4) = JMP_INST(1, LO(NewVal), 0);
- *(intptr_t *)(StubAddr + 8) = NOP_INST;
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i)
+ *(uint32_t *)(StubAddr + i*4) = Insts[i];
- sys::Memory::InvalidateInstructionCache((void*) StubAddr, 12);
+ sys::Memory::InvalidateInstructionCache((void*) StubAddr, Insts.size() * 4);
return (void*)StubAddr;
}
+
void SparcJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
assert(0 && "FIXME: Implement SparcJITInfo::replaceMachineCodeForFunction");
}
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;
}
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;
+ }
+
+ if (Insts.size() == 0)
+ emitInstrForIndirectJump(EmittedAddr, 1, Insts);
- // sethi %hi(EmittedAddr), %g1
- // jmp %g1+%lo(EmittedAddr), %g1
- // nop
- JCE.emitWordBE(SETHI_INST(HI(EmittedAddr), 1));
- JCE.emitWordBE(JMP_INST(1, LO(EmittedAddr), 1));
- JCE.emitWordBE(NOP_INST);
+ 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, 12);
- if (!sys::Memory::setRangeExecutable(Addr, 12))
+ sys::Memory::InvalidateInstructionCache(Addr, 4 * Insts.size());
+ if (!sys::Memory::setRangeExecutable(Addr, 4 * Insts.size()))
llvm_unreachable("ERROR: Unable to mark stub executable.");
return Addr;
}
+
TargetJITInfo::LazyResolverFn
SparcJITInfo::getLazyResolverFunction(JITCompilerFn F) {
JITCompilerFunction = F;
@@ -159,6 +297,27 @@ void SparcJITInfo::relocate(void *Function, MachineRelocation *MR,
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;
}
diff --git a/contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp b/contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp
new file mode 100644
index 0000000..fc3ba90
--- /dev/null
+++ b/contrib/llvm/lib/Target/Sparc/SparcMCInstLower.cpp
@@ -0,0 +1,109 @@
+//===-- SparcMCInstLower.cpp - Convert Sparc MachineInstr to MCInst -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to lower Sparc MachineInstrs to their corresponding
+// MCInst records.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sparc.h"
+#include "MCTargetDesc/SparcMCExpr.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace llvm;
+
+
+static MCOperand LowerSymbolOperand(const MachineInstr *MI,
+ const MachineOperand &MO,
+ AsmPrinter &AP) {
+
+ SparcMCExpr::VariantKind Kind =
+ (SparcMCExpr::VariantKind)MO.getTargetFlags();
+ const MCSymbol *Symbol = 0;
+
+ switch(MO.getType()) {
+ default: llvm_unreachable("Unknown type in LowerSymbolOperand");
+ case MachineOperand::MO_MachineBasicBlock:
+ Symbol = MO.getMBB()->getSymbol();
+ break;
+
+ case MachineOperand::MO_GlobalAddress:
+ Symbol = AP.getSymbol(MO.getGlobal());
+ break;
+
+ case MachineOperand::MO_BlockAddress:
+ Symbol = AP.GetBlockAddressSymbol(MO.getBlockAddress());
+ break;
+
+ case MachineOperand::MO_ExternalSymbol:
+ Symbol = AP.GetExternalSymbolSymbol(MO.getSymbolName());
+ break;
+
+ case MachineOperand::MO_ConstantPoolIndex:
+ Symbol = AP.GetCPISymbol(MO.getIndex());
+ break;
+ }
+
+ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol,
+ AP.OutContext);
+ const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym,
+ AP.OutContext);
+ return MCOperand::CreateExpr(expr);
+}
+
+static MCOperand LowerOperand(const MachineInstr *MI,
+ const MachineOperand &MO,
+ AsmPrinter &AP) {
+ switch(MO.getType()) {
+ default: llvm_unreachable("unknown operand type"); break;
+ case MachineOperand::MO_Register:
+ if (MO.isImplicit())
+ break;
+ return MCOperand::CreateReg(MO.getReg());
+
+ case MachineOperand::MO_Immediate:
+ return MCOperand::CreateImm(MO.getImm());
+
+ case MachineOperand::MO_MachineBasicBlock:
+ case MachineOperand::MO_GlobalAddress:
+ case MachineOperand::MO_BlockAddress:
+ case MachineOperand::MO_ExternalSymbol:
+ case MachineOperand::MO_ConstantPoolIndex:
+ return LowerSymbolOperand(MI, MO, AP);
+
+ case MachineOperand::MO_RegisterMask: break;
+
+ }
+ return MCOperand();
+}
+
+void llvm::LowerSparcMachineInstrToMCInst(const MachineInstr *MI,
+ MCInst &OutMI,
+ AsmPrinter &AP)
+{
+
+ OutMI.setOpcode(MI->getOpcode());
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+ MCOperand MCOp = LowerOperand(MI, MO, AP);
+
+ if (MCOp.isValid())
+ OutMI.addOperand(MCOp);
+ }
+}
diff --git a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp
index c98613a..f222382 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp
+++ b/contrib/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp
@@ -35,7 +35,7 @@ ReserveAppRegisters("sparc-reserve-app-registers", cl::Hidden, cl::init(false),
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)
diff --git a/contrib/llvm/lib/Target/Sparc/SparcRelocations.h b/contrib/llvm/lib/Target/Sparc/SparcRelocations.h
index 388cfe7..c1ff78d 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcRelocations.h
+++ b/contrib/llvm/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
};
}
}
diff --git a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp
index 7d09d0e..6fc9d56 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.cpp
@@ -31,20 +31,20 @@ SparcSubtarget::SparcSubtarget(const std::string &TT, const std::string &CPU,
V8DeprecatedInsts(false),
IsVIS(false),
Is64Bit(is64Bit),
- HasHardQuad(false) {
+ HasHardQuad(false),
+ UsePopc(false) {
// Determine default and user specified characteristics
std::string CPUName = CPU;
- if (CPUName.empty()) {
- if (is64Bit)
- CPUName = "v9";
- else
- CPUName = "v8";
- }
- IsV9 = CPUName == "v9";
+ if (CPUName.empty())
+ CPUName = (is64Bit) ? "v9" : "v8";
// Parse features string.
ParseSubtargetFeatures(CPUName, FS);
+
+ // Popc is a v9-only instruction.
+ if (!IsV9)
+ UsePopc = false;
}
diff --git a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h
index 0f81cc9..e4239e2 100644
--- a/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h
+++ b/contrib/llvm/lib/Target/Sparc/SparcSubtarget.h
@@ -30,6 +30,7 @@ class SparcSubtarget : public SparcGenSubtargetInfo {
bool IsVIS;
bool Is64Bit;
bool HasHardQuad;
+ bool UsePopc;
public:
SparcSubtarget(const std::string &TT, const std::string &CPU,
@@ -39,6 +40,7 @@ public:
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.
diff --git a/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.cpp b/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.cpp
new file mode 100644
index 0000000..18612bd
--- /dev/null
+++ b/contrib/llvm/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);
+}
diff --git a/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.h b/contrib/llvm/lib/Target/Sparc/SparcTargetObjectFile.h
new file mode 100644
index 0000000..7cf850d
--- /dev/null
+++ b/contrib/llvm/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
diff --git a/contrib/llvm/lib/Target/Sparc/SparcTargetStreamer.h b/contrib/llvm/lib/Target/Sparc/SparcTargetStreamer.h
new file mode 100644
index 0000000..73339ac
--- /dev/null
+++ b/contrib/llvm/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
diff --git a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
index bccd0d7..af9221b 100644
--- a/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -4529,6 +4529,13 @@ public:
UIntMaxType = UnsignedLong;
}
Int64Type = IntMaxType;
+
+ // The SPARCv8 System V ABI has long double 128-bits in size, but 64-bit
+ // aligned. The SPARCv9 SCD 2.4.1 says 16-byte aligned.
+ LongDoubleWidth = 128;
+ LongDoubleAlign = 128;
+ LongDoubleFormat = &llvm::APFloat::IEEEquad;
+ MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64;
}
virtual void getTargetDefines(const LangOptions &Opts,
@@ -4545,6 +4552,22 @@ public:
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.
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
index 76acf87..45eaec6 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/TargetInfo.cpp
@@ -5349,6 +5349,11 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
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));
@@ -5430,9 +5435,50 @@ class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo {
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
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
index 8a47e76..f5dc3dfb 100644
--- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp
@@ -1164,6 +1164,13 @@ void Generic_GCC::GCCInstallationDetector::print(raw_ostream &OS) const {
"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(raw_ostream &OS) const {
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 &Suffix, StringRef Path,
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)
diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
index 3529fc7..b37b31c 100644
--- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp
@@ -1373,7 +1373,8 @@ static std::string getCPUName(const ArgList &Args, const llvm::Triple &T) {
}
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 "";
@@ -5785,6 +5786,24 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
default:
CmdArgs.push_back("-matpcs");
}
+ } 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,
+ 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,
@@ -6194,6 +6213,7 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
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
@@ -6213,6 +6233,14 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-a64");
CmdArgs.push_back("-mppc64le");
CmdArgs.push_back("-many");
+ } else if (getToolChain().getArch() == llvm::Triple::sparc) {
+ CmdArgs.push_back("-32");
+ CmdArgs.push_back("-Av8plusa");
+ NeedsKPIC = true;
+ } else if (getToolChain().getArch() == llvm::Triple::sparcv9) {
+ CmdArgs.push_back("-64");
+ CmdArgs.push_back("-Av9a");
+ NeedsKPIC = true;
} else if (getToolChain().getArch() == llvm::Triple::arm) {
StringRef MArch = getToolChain().getArchName();
if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
@@ -6272,6 +6300,15 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
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,
@@ -6283,11 +6320,6 @@ void gnutools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
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,
@@ -6357,7 +6389,8 @@ static StringRef getLinuxDynamicLinker(const ArgList &Args,
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";
@@ -6382,6 +6415,8 @@ static StringRef getLinuxDynamicLinker(const ArgList &Args,
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";
}
@@ -6444,6 +6479,10 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
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)
diff --git a/lib/clang/Makefile b/lib/clang/Makefile
index ca5e1da..8b6f385 100644
--- a/lib/clang/Makefile
+++ b/lib/clang/Makefile
@@ -79,6 +79,12 @@ SUBDIR= libclanganalysis \
libllvmpowerpcdesc \
libllvmpowerpcinfo \
libllvmpowerpcinstprinter \
+ libllvmsparcasmparser \
+ libllvmsparccodegen \
+ libllvmsparcdesc \
+ libllvmsparcdisassembler \
+ libllvmsparcinfo \
+ libllvmsparcinstprinter \
libllvmx86asmparser \
libllvmx86codegen \
libllvmx86desc \
diff --git a/lib/clang/clang.build.mk b/lib/clang/clang.build.mk
index 61bc338..1742feb 100644
--- a/lib/clang/clang.build.mk
+++ b/lib/clang/clang.build.mk
@@ -52,7 +52,7 @@ Intrinsics.inc.h: ${LLVM_SRCS}/include/llvm/IR/Intrinsics.td \
-gen-intrinsic -o ${.TARGET} \
${LLVM_SRCS}/include/llvm/IR/Intrinsics.td
.for arch in \
- ARM/ARM Mips/Mips PowerPC/PPC X86/X86
+ ARM/ARM Mips/Mips PowerPC/PPC Sparc/Sparc X86/X86
. for hdr in \
AsmMatcher/-gen-asm-matcher \
AsmWriter1/-gen-asm-writer,-asmwriternum=1 \
diff --git a/lib/clang/include/SparcGenAsmMatcher.inc b/lib/clang/include/SparcGenAsmMatcher.inc
new file mode 100644
index 0000000..3522c59
--- /dev/null
+++ b/lib/clang/include/SparcGenAsmMatcher.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenAsmMatcher.inc.h"
diff --git a/lib/clang/include/SparcGenAsmWriter.inc b/lib/clang/include/SparcGenAsmWriter.inc
new file mode 100644
index 0000000..c5ae5dc
--- /dev/null
+++ b/lib/clang/include/SparcGenAsmWriter.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenAsmWriter.inc.h"
diff --git a/lib/clang/include/SparcGenCallingConv.inc b/lib/clang/include/SparcGenCallingConv.inc
new file mode 100644
index 0000000..dde4d8f
--- /dev/null
+++ b/lib/clang/include/SparcGenCallingConv.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenCallingConv.inc.h"
diff --git a/lib/clang/include/SparcGenCodeEmitter.inc b/lib/clang/include/SparcGenCodeEmitter.inc
new file mode 100644
index 0000000..0cd2fee
--- /dev/null
+++ b/lib/clang/include/SparcGenCodeEmitter.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenCodeEmitter.inc.h"
diff --git a/lib/clang/include/SparcGenDAGISel.inc b/lib/clang/include/SparcGenDAGISel.inc
new file mode 100644
index 0000000..d85ed6c
--- /dev/null
+++ b/lib/clang/include/SparcGenDAGISel.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenDAGISel.inc.h"
diff --git a/lib/clang/include/SparcGenDisassemblerTables.inc b/lib/clang/include/SparcGenDisassemblerTables.inc
new file mode 100644
index 0000000..0749ef2
--- /dev/null
+++ b/lib/clang/include/SparcGenDisassemblerTables.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenDisassemblerTables.inc.h"
diff --git a/lib/clang/include/SparcGenInstrInfo.inc b/lib/clang/include/SparcGenInstrInfo.inc
new file mode 100644
index 0000000..81c8e0b
--- /dev/null
+++ b/lib/clang/include/SparcGenInstrInfo.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenInstrInfo.inc.h"
diff --git a/lib/clang/include/SparcGenMCCodeEmitter.inc b/lib/clang/include/SparcGenMCCodeEmitter.inc
new file mode 100644
index 0000000..1e6d6ef
--- /dev/null
+++ b/lib/clang/include/SparcGenMCCodeEmitter.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenMCCodeEmitter.inc.h"
diff --git a/lib/clang/include/SparcGenRegisterInfo.inc b/lib/clang/include/SparcGenRegisterInfo.inc
new file mode 100644
index 0000000..0c3a91c
--- /dev/null
+++ b/lib/clang/include/SparcGenRegisterInfo.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenRegisterInfo.inc.h"
diff --git a/lib/clang/include/SparcGenSubtargetInfo.inc b/lib/clang/include/SparcGenSubtargetInfo.inc
new file mode 100644
index 0000000..ac63a72
--- /dev/null
+++ b/lib/clang/include/SparcGenSubtargetInfo.inc
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+#include "SparcGenSubtargetInfo.inc.h"
diff --git a/lib/clang/include/llvm/Config/AsmParsers.def b/lib/clang/include/llvm/Config/AsmParsers.def
index a2c0f78..e0165f0 100644
--- a/lib/clang/include/llvm/Config/AsmParsers.def
+++ b/lib/clang/include/llvm/Config/AsmParsers.def
@@ -3,6 +3,7 @@
LLVM_ASM_PARSER(ARM)
LLVM_ASM_PARSER(Mips)
LLVM_ASM_PARSER(PowerPC)
+LLVM_ASM_PARSER(Sparc)
LLVM_ASM_PARSER(X86)
#undef LLVM_ASM_PARSER
diff --git a/lib/clang/include/llvm/Config/AsmPrinters.def b/lib/clang/include/llvm/Config/AsmPrinters.def
index ca335df..97ca952 100644
--- a/lib/clang/include/llvm/Config/AsmPrinters.def
+++ b/lib/clang/include/llvm/Config/AsmPrinters.def
@@ -3,6 +3,7 @@
LLVM_ASM_PRINTER(ARM)
LLVM_ASM_PRINTER(Mips)
LLVM_ASM_PRINTER(PowerPC)
+LLVM_ASM_PRINTER(Sparc)
LLVM_ASM_PRINTER(X86)
#undef LLVM_ASM_PRINTER
diff --git a/lib/clang/include/llvm/Config/Disassemblers.def b/lib/clang/include/llvm/Config/Disassemblers.def
index 1b26531..25406a4 100644
--- a/lib/clang/include/llvm/Config/Disassemblers.def
+++ b/lib/clang/include/llvm/Config/Disassemblers.def
@@ -2,6 +2,7 @@
LLVM_DISASSEMBLER(ARM)
LLVM_DISASSEMBLER(Mips)
+LLVM_DISASSEMBLER(Sparc)
LLVM_DISASSEMBLER(X86)
#undef LLVM_DISASSEMBLER
diff --git a/lib/clang/include/llvm/Config/Targets.def b/lib/clang/include/llvm/Config/Targets.def
index 85c3ffe..e51e06a 100644
--- a/lib/clang/include/llvm/Config/Targets.def
+++ b/lib/clang/include/llvm/Config/Targets.def
@@ -3,6 +3,7 @@
LLVM_TARGET(ARM)
LLVM_TARGET(Mips)
LLVM_TARGET(PowerPC)
+LLVM_TARGET(Sparc)
LLVM_TARGET(X86)
#undef LLVM_TARGET
diff --git a/lib/clang/libllvmsparcasmparser/Makefile b/lib/clang/libllvmsparcasmparser/Makefile
new file mode 100644
index 0000000..f4e4f25
--- /dev/null
+++ b/lib/clang/libllvmsparcasmparser/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+LIB= llvmsparcasmparser
+
+SRCDIR= lib/Target/Sparc/AsmParser
+INCDIR= lib/Target/Sparc
+SRCS= SparcAsmParser.cpp
+
+TGHDRS= SparcGenAsmMatcher \
+ SparcGenInstrInfo \
+ SparcGenRegisterInfo \
+ SparcGenSubtargetInfo
+
+.include "../clang.lib.mk"
diff --git a/lib/clang/libllvmsparccodegen/Makefile b/lib/clang/libllvmsparccodegen/Makefile
new file mode 100644
index 0000000..36cf0a6
--- /dev/null
+++ b/lib/clang/libllvmsparccodegen/Makefile
@@ -0,0 +1,34 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+LIB= llvmsparccodegen
+
+SRCDIR= lib/Target/Sparc
+SRCS= DelaySlotFiller.cpp \
+ SparcAsmPrinter.cpp \
+ SparcCodeEmitter.cpp \
+ SparcFrameLowering.cpp \
+ SparcISelDAGToDAG.cpp \
+ SparcISelLowering.cpp \
+ SparcInstrInfo.cpp \
+ SparcJITInfo.cpp \
+ SparcMCInstLower.cpp \
+ SparcMachineFunctionInfo.cpp \
+ SparcRegisterInfo.cpp \
+ SparcSelectionDAGInfo.cpp \
+ SparcSubtarget.cpp \
+ SparcTargetMachine.cpp \
+ SparcTargetObjectFile.cpp
+
+TGHDRS= Intrinsics \
+ SparcGenAsmWriter \
+ SparcGenCallingConv \
+ SparcGenCodeEmitter \
+ SparcGenDAGISel \
+ SparcGenInstrInfo \
+ SparcGenMCCodeEmitter \
+ SparcGenRegisterInfo \
+ SparcGenSubtargetInfo
+
+.include "../clang.lib.mk"
diff --git a/lib/clang/libllvmsparcdesc/Makefile b/lib/clang/libllvmsparcdesc/Makefile
new file mode 100644
index 0000000..20605fb
--- /dev/null
+++ b/lib/clang/libllvmsparcdesc/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+LIB= llvmsparcdesc
+
+SRCDIR= lib/Target/Sparc/MCTargetDesc
+SRCS= SparcAsmBackend.cpp \
+ SparcELFObjectWriter.cpp \
+ SparcMCAsmInfo.cpp \
+ SparcMCCodeEmitter.cpp \
+ SparcMCExpr.cpp \
+ SparcMCTargetDesc.cpp \
+ SparcTargetStreamer.cpp
+CFLAGS+= -I${LLVM_SRCS}/${SRCDIR}/..
+
+TGHDRS= SparcGenInstrInfo \
+ SparcGenMCCodeEmitter \
+ SparcGenRegisterInfo \
+ SparcGenSubtargetInfo
+
+.include "../clang.lib.mk"
diff --git a/lib/clang/libllvmsparcdisassembler/Makefile b/lib/clang/libllvmsparcdisassembler/Makefile
new file mode 100644
index 0000000..a388ff2
--- /dev/null
+++ b/lib/clang/libllvmsparcdisassembler/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+LIB= llvmsparcdisassembler
+
+SRCDIR= lib/Target/Sparc/Disassembler
+INCDIR= lib/Target/Sparc
+SRCS= SparcDisassembler.cpp
+
+TGHDRS= SparcGenDisassemblerTables \
+ SparcGenInstrInfo \
+ SparcGenRegisterInfo \
+ SparcGenSubtargetInfo
+
+.include "../clang.lib.mk"
diff --git a/lib/clang/libllvmsparcinfo/Makefile b/lib/clang/libllvmsparcinfo/Makefile
new file mode 100644
index 0000000..6c8052e
--- /dev/null
+++ b/lib/clang/libllvmsparcinfo/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+LIB= llvmsparcinfo
+
+SRCDIR= lib/Target/Sparc/TargetInfo
+INCDIR= lib/Target/Sparc
+SRCS= SparcTargetInfo.cpp
+
+TGHDRS= SparcGenInstrInfo \
+ SparcGenRegisterInfo \
+ SparcGenSubtargetInfo
+
+.include "../clang.lib.mk"
diff --git a/lib/clang/libllvmsparcinstprinter/Makefile b/lib/clang/libllvmsparcinstprinter/Makefile
new file mode 100644
index 0000000..e15c55e
--- /dev/null
+++ b/lib/clang/libllvmsparcinstprinter/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+LIB= llvmsparcinstprinter
+
+SRCDIR= lib/Target/Sparc/InstPrinter
+INCDIR= lib/Target/Sparc
+SRCS= SparcInstPrinter.cpp
+
+TGHDRS= SparcGenAsmWriter \
+ SparcGenInstrInfo \
+ SparcGenRegisterInfo \
+ SparcGenSubtargetInfo
+
+.include "../clang.lib.mk"
diff --git a/lib/libc/sparc64/sys/__sparc_utrap_setup.c b/lib/libc/sparc64/sys/__sparc_utrap_setup.c
index f4a624b..2524f44 100644
--- a/lib/libc/sparc64/sys/__sparc_utrap_setup.c
+++ b/lib/libc/sparc64/sys/__sparc_utrap_setup.c
@@ -54,5 +54,5 @@ void
__sparc_utrap_setup(void)
{
- sysarch(SPARC_UTRAP_INSTALL, &uia);
+ sysarch(SPARC_UTRAP_INSTALL, (void *)&uia);
}
diff --git a/lib/msun/Makefile b/lib/msun/Makefile
index 629d523..4bca55b 100644
--- a/lib/msun/Makefile
+++ b/lib/msun/Makefile
@@ -43,6 +43,7 @@ LIB= m
SHLIBDIR?= /lib
SHLIB_MAJOR= 5
WARNS?= 1
+IGNORE_PRAGMA=
COMMON_SRCS= b_exp.c b_log.c b_tgamma.c \
e_acos.c e_acosf.c e_acosh.c e_acoshf.c e_asin.c e_asinf.c \
e_atan2.c e_atan2f.c e_atanh.c e_atanhf.c e_cosh.c e_coshf.c e_exp.c \
diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk
index dc15f4b..3428edc 100644
--- a/share/mk/bsd.sys.mk
+++ b/share/mk/bsd.sys.mk
@@ -120,6 +120,10 @@ CLANG_NO_IAS= -no-integrated-as
CLANG_OPT_SMALL= -mstack-alignment=8 -mllvm -inline-threshold=3\
-mllvm -enable-load-pre=false -mllvm -simplifycfg-dup-ret
CFLAGS+= -Qunused-arguments
+.if ${MACHINE_CPUARCH} == "sparc64"
+# Don't emit .cfi directives, since we must use GNU as on sparc64, for now.
+CFLAGS+= -fno-dwarf2-cfi-asm
+.endif # SPARC64
# The libc++ headers use c++11 extensions. These are normally silenced because
# they are treated as system headers, but we explicitly disable that warning
# suppression when building the base system to catch bugs in our headers.
diff --git a/sys/boot/sparc64/boot1/Makefile b/sys/boot/sparc64/boot1/Makefile
index 048c083..f8986ad 100644
--- a/sys/boot/sparc64/boot1/Makefile
+++ b/sys/boot/sparc64/boot1/Makefile
@@ -9,7 +9,9 @@ CLEANFILES=${FILES} boot1.aout
BOOTBLOCKBASE= 0x4000
-CFLAGS+=-mcmodel=medlow -Os -I${.CURDIR}/../../common
+CFLAGS.clang+=-mcmodel=small
+CFLAGS.gcc+=-mcmodel=medlow
+CFLAGS+=-Os -I${.CURDIR}/../../common
LDFLAGS=-Ttext ${BOOTBLOCKBASE} -Wl,-N
# Construct boot1. sunlabel expects it to contain zeroed-out space for the
diff --git a/sys/conf/kern.mk b/sys/conf/kern.mk
index e4a0b48..e49cf6d 100644
--- a/sys/conf/kern.mk
+++ b/sys/conf/kern.mk
@@ -90,7 +90,11 @@ INLINE_LIMIT?= 15000
# operations which it has a tendency to do.
#
.if ${MACHINE_CPUARCH} == "sparc64"
+.if ${COMPILER_TYPE} == "clang"
+CFLAGS+= -mcmodel=large -fno-dwarf2-cfi-asm
+.else
CFLAGS+= -mcmodel=medany -msoft-float
+.endif
INLINE_LIMIT?= 15000
.endif
diff --git a/sys/dev/esp/esp_sbus.c b/sys/dev/esp/esp_sbus.c
index 01ffb8d..4d658d6 100644
--- a/sys/dev/esp/esp_sbus.c
+++ b/sys/dev/esp/esp_sbus.c
@@ -165,7 +165,7 @@ static int espattach(struct esp_softc *esc,
const struct ncr53c9x_glue *gluep);
static int espdetach(struct esp_softc *esc);
-static const struct ncr53c9x_glue const esp_sbus_glue = {
+static const struct ncr53c9x_glue esp_sbus_glue = {
esp_read_reg,
esp_write_reg,
esp_dma_isintr,
diff --git a/sys/dev/fb/creator.c b/sys/dev/fb/creator.c
index 135fd3d..488d00d 100644
--- a/sys/dev/fb/creator.c
+++ b/sys/dev/fb/creator.c
@@ -97,7 +97,7 @@ struct creator_softc {
bus_space_write_4((sc)->sc_bt[(reg)], (sc)->sc_bh[(reg)], (off), (val))
#define C(r, g, b) ((b << 16) | (g << 8) | (r))
-static const uint32_t const creator_cmap[] = {
+static const uint32_t creator_cmap[] = {
C(0x00, 0x00, 0x00), /* black */
C(0x00, 0x00, 0xff), /* blue */
C(0x00, 0xff, 0x00), /* green */
@@ -121,7 +121,7 @@ static const struct {
vm_offset_t virt;
vm_paddr_t phys;
vm_size_t size;
-} const creator_fb_map[] = {
+} creator_fb_map[] = {
{ FFB_VIRT_SFB8R, FFB_PHYS_SFB8R, FFB_SIZE_SFB8R },
{ FFB_VIRT_SFB8G, FFB_PHYS_SFB8G, FFB_SIZE_SFB8G },
{ FFB_VIRT_SFB8B, FFB_PHYS_SFB8B, FFB_SIZE_SFB8B },
@@ -270,7 +270,7 @@ RENDERER(creator, 0, txtrndrsw, gfb_set);
RENDERER_MODULE(creator, gfb_set);
-static const u_char const creator_mouse_pointer[64][8] __aligned(8) = {
+static const u_char creator_mouse_pointer[64][8] __aligned(8) = {
{ 0x00, 0x00, }, /* ............ */
{ 0x80, 0x00, }, /* *........... */
{ 0xc0, 0x00, }, /* **.......... */
diff --git a/sys/dev/fb/machfb.c b/sys/dev/fb/machfb.c
index 1c3023d..368ff6a 100644
--- a/sys/dev/fb/machfb.c
+++ b/sys/dev/fb/machfb.c
@@ -131,7 +131,7 @@ static const struct {
uint16_t chip_id;
const char *name;
uint32_t ramdac_freq;
-} const machfb_info[] = {
+} machfb_info[] = {
{ ATI_MACH64_CT, "ATI Mach64 CT", 135000 },
{ ATI_RAGE_PRO_AGP, "ATI 3D Rage Pro (AGP)", 230000 },
{ ATI_RAGE_PRO_AGP1X, "ATI 3D Rage Pro (AGP 1x)", 230000 },
@@ -169,7 +169,7 @@ static const struct machfb_cmap {
uint8_t red;
uint8_t green;
uint8_t blue;
-} const machfb_default_cmap[16] = {
+} machfb_default_cmap[16] = {
{0x00, 0x00, 0x00}, /* black */
{0x00, 0x00, 0xff}, /* blue */
{0x00, 0xff, 0x00}, /* green */
@@ -190,7 +190,7 @@ static const struct machfb_cmap {
#define MACHFB_CMAP_OFF 16
-static const u_char const machfb_mouse_pointer_bits[64][8] = {
+static const u_char machfb_mouse_pointer_bits[64][8] = {
{ 0x00, 0x00, }, /* ............ */
{ 0x80, 0x00, }, /* *........... */
{ 0xc0, 0x00, }, /* **.......... */
@@ -219,7 +219,7 @@ static const u_char const machfb_mouse_pointer_bits[64][8] = {
* Lookup table to perform a bit-swap of the mouse pointer bits,
* map set bits to CUR_CLR0 and unset bits to transparent.
*/
-static const u_char const machfb_mouse_pointer_lut[] = {
+static const u_char machfb_mouse_pointer_lut[] = {
0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
};
@@ -1418,7 +1418,7 @@ static int
machfb_get_memsize(struct machfb_softc *sc)
{
int tmp, memsize;
- const int const mem_tab[] = {
+ const int mem_tab[] = {
512, 1024, 2048, 4096, 6144, 8192, 12288, 16384
};
diff --git a/sys/dev/mk48txx/mk48txx.c b/sys/dev/mk48txx/mk48txx.c
index de116d0..d1fcfb4 100644
--- a/sys/dev/mk48txx/mk48txx.c
+++ b/sys/dev/mk48txx/mk48txx.c
@@ -64,7 +64,7 @@ static const struct {
bus_size_t clkoff;
u_int flags;
#define MK48TXX_EXT_REGISTERS 1 /* Has extended register set. */
-} const mk48txx_models[] = {
+} mk48txx_models[] = {
{ "mk48t02", MK48T02_CLKSZ, MK48T02_CLKOFF, 0 },
{ "mk48t08", MK48T08_CLKSZ, MK48T08_CLKOFF, 0 },
{ "mk48t18", MK48T18_CLKSZ, MK48T18_CLKOFF, 0 },
diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC
index eaf82f0..c891911 100644
--- a/sys/sparc64/conf/GENERIC
+++ b/sys/sparc64/conf/GENERIC
@@ -21,7 +21,7 @@
cpu SUN4U
ident GENERIC
-makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+makeoptions DEBUG=-gdwarf-2 # Build kernel with gdb(1) debug symbols
# Platforms supported
# At this time all platforms are supported, as-is.
diff --git a/sys/sparc64/isa/isa.c b/sys/sparc64/isa/isa.c
index 6e22133..6783440 100644
--- a/sys/sparc64/isa/isa.c
+++ b/sys/sparc64/isa/isa.c
@@ -118,7 +118,7 @@ isa_init(device_t dev)
static const struct {
const char *const name;
uint32_t id;
-} const ofw_isa_pnp_map[] = {
+} ofw_isa_pnp_map[] = {
{ "SUNW,lomh", 0x0000ae4e }, /* SUN0000 */
{ "dma", 0x0002d041 }, /* PNP0200 */
{ "floppy", 0x0007d041 }, /* PNP0700 */
diff --git a/sys/sparc64/pci/firereg.h b/sys/sparc64/pci/firereg.h
index 650eb8c..247a3f7 100644
--- a/sys/sparc64/pci/firereg.h
+++ b/sys/sparc64/pci/firereg.h
@@ -922,7 +922,7 @@
#define FO_XBC_PRF_CNT_SHFT 0
/* Lookup tables */
-const uint16_t const fire_freq_nak_tmr_thrs[6][4] = {
+const uint16_t fire_freq_nak_tmr_thrs[6][4] = {
{ 0x00ed, 0x049, 0x043, 0x030 },
{ 0x01a0, 0x076, 0x06b, 0x048 },
{ 0x022f, 0x09a, 0x056, 0x056 },
@@ -931,7 +931,7 @@ const uint16_t const fire_freq_nak_tmr_thrs[6][4] = {
{ 0x102f, 0x41a, 0x216, 0x216 }
};
-const uint16_t const fire_rply_tmr_thrs[6][4] = {
+const uint16_t fire_rply_tmr_thrs[6][4] = {
{ 0x0379, 0x112, 0x0fc, 0x0b4 },
{ 0x0618, 0x1BA, 0x192, 0x10e },
{ 0x0831, 0x242, 0x143, 0x143 },
diff --git a/usr.bin/clang/clang/Makefile b/usr.bin/clang/clang/Makefile
index 0538ecd..ac6e685 100644
--- a/usr.bin/clang/clang/Makefile
+++ b/usr.bin/clang/clang/Makefile
@@ -89,6 +89,12 @@ LIBDEPS=clangfrontendtool \
llvmpowerpcdesc \
llvmpowerpcinfo \
llvmpowerpcinstprinter \
+ llvmsparcdisassembler \
+ llvmsparccodegen \
+ llvmsparcasmparser \
+ llvmsparcdesc \
+ llvmsparcinfo \
+ llvmsparcinstprinter \
llvmx86disassembler \
llvmx86asmparser \
llvmx86codegen \
diff --git a/usr.bin/clang/llc/Makefile b/usr.bin/clang/llc/Makefile
index 49af326..43eaf9b 100644
--- a/usr.bin/clang/llc/Makefile
+++ b/usr.bin/clang/llc/Makefile
@@ -27,6 +27,12 @@ LIBDEPS=llvmirreader \
llvmpowerpcdesc \
llvmpowerpcinfo \
llvmpowerpcinstprinter \
+ llvmsparcdisassembler \
+ llvmsparccodegen \
+ llvmsparcasmparser \
+ llvmsparcdesc \
+ llvmsparcinfo \
+ llvmsparcinstprinter \
llvmx86disassembler \
llvmx86asmparser \
llvmx86codegen \
diff --git a/usr.bin/clang/llvm-mc/Makefile b/usr.bin/clang/llvm-mc/Makefile
index 6199ca1..7a2c56a 100644
--- a/usr.bin/clang/llvm-mc/Makefile
+++ b/usr.bin/clang/llvm-mc/Makefile
@@ -27,6 +27,12 @@ LIBDEPS=llvmmcdisassembler \
llvmpowerpcdesc \
llvmpowerpcinfo \
llvmpowerpcinstprinter \
+ llvmsparcdisassembler \
+ llvmsparccodegen \
+ llvmsparcasmparser \
+ llvmsparcdesc \
+ llvmsparcinfo \
+ llvmsparcinstprinter \
llvmx86disassembler \
llvmx86asmparser \
llvmx86codegen \
diff --git a/usr.bin/clang/llvm-objdump/Makefile b/usr.bin/clang/llvm-objdump/Makefile
index 4d2aa12..f20d331 100644
--- a/usr.bin/clang/llvm-objdump/Makefile
+++ b/usr.bin/clang/llvm-objdump/Makefile
@@ -32,6 +32,12 @@ LIBDEPS=llvmmcdisassembler \
llvmpowerpcdesc \
llvmpowerpcinfo \
llvmpowerpcinstprinter \
+ llvmsparcdisassembler \
+ llvmsparccodegen \
+ llvmsparcasmparser \
+ llvmsparcdesc \
+ llvmsparcinfo \
+ llvmsparcinstprinter \
llvmx86disassembler \
llvmx86asmparser \
llvmx86codegen \
diff --git a/usr.bin/clang/llvm-rtdyld/Makefile b/usr.bin/clang/llvm-rtdyld/Makefile
index 721eb59..01b771b 100644
--- a/usr.bin/clang/llvm-rtdyld/Makefile
+++ b/usr.bin/clang/llvm-rtdyld/Makefile
@@ -31,6 +31,12 @@ LIBDEPS=llvmdebuginfo \
llvmpowerpcdesc \
llvmpowerpcinfo \
llvmpowerpcinstprinter \
+ llvmsparcdisassembler \
+ llvmsparccodegen \
+ llvmsparcasmparser \
+ llvmsparcdesc \
+ llvmsparcinfo \
+ llvmsparcinstprinter \
llvmx86disassembler \
llvmx86asmparser \
llvmx86codegen \
diff --git a/usr.bin/clang/opt/Makefile b/usr.bin/clang/opt/Makefile
index 083ec9b..eee7949 100644
--- a/usr.bin/clang/opt/Makefile
+++ b/usr.bin/clang/opt/Makefile
@@ -28,6 +28,12 @@ LIBDEPS=llvmarmdisassembler \
llvmpowerpcdesc \
llvmpowerpcinfo \
llvmpowerpcinstprinter \
+ llvmsparcdisassembler \
+ llvmsparccodegen \
+ llvmsparcasmparser \
+ llvmsparcdesc \
+ llvmsparcinfo \
+ llvmsparcinstprinter \
llvmx86disassembler \
llvmx86asmparser \
llvmx86codegen \
diff --git a/usr.sbin/eeprom/ofw_options.c b/usr.sbin/eeprom/ofw_options.c
index eb7437f..6e6aa85 100644
--- a/usr.sbin/eeprom/ofw_options.c
+++ b/usr.sbin/eeprom/ofw_options.c
@@ -63,7 +63,7 @@ static int ofwo_secmode(const struct ofwo_extabent *, int, const void *,
static int ofwo_secpwd(const struct ofwo_extabent *, int, const void *,
int, const char *);
-static const struct ofwo_extabent const ofwo_extab[] = {
+static const struct ofwo_extabent ofwo_extab[] = {
{ "oem-logo", ofwo_oemlogo },
{ "security-mode", ofwo_secmode },
{ "security-password", ofwo_secpwd },
OpenPOWER on IntegriCloud